[SCM] ffmpeg/master: Imported Upstream version 3.1.1

sramacher at users.alioth.debian.org sramacher at users.alioth.debian.org
Tue Jul 12 00:21:50 UTC 2016


The following commit has been merged in the master branch:
commit c1a7bf0ae231d5bdcd001fb679f43e4e3f655e9d
Author: Sebastian Ramacher <sramacher at debian.org>
Date:   Tue Jul 12 01:58:18 2016 +0200

    Imported Upstream version 3.1.1

diff --git a/Changelog b/Changelog
index 248f8b5..2a87916 100644
--- a/Changelog
+++ b/Changelog
@@ -1,67 +1,68 @@
 Entries are sorted chronologically from oldest to youngest within each release,
 releases are sorted from youngest to oldest.
 
-
-version 3.0.2:
-- avcodec/ttaenc: Reallocate packet if its too small
-- configure: build fix for P5600 with mips code restructuring
-- mips: add support for R6
-- pgssubdec: fix subpicture output colorspace and range
-- avcodec/ac3dec: Reset SPX when switching from EAC3 to AC3
-- avfilter/vf_drawtext: Check return code of load_glyph()
-- avformat/mux: Check that deinit is set before calling it
-- avcodec/takdec: add code that got somehow lost in process of REing
-- avcodec/apedec: fix decoding of stereo files with one channel full of silence
-- avcodec/avpacket: Fix off by 5 error
-- avcodec/h264: Fix for H.264 configuration parsing
-- avcodec/bmp_parser: Ensure remaining_size is not too small in startcode packet crossing corner case
-- avcodec/pngdec: Fix alpha detection with skip_frame
-- Changelog: Make formating consistent
-- avfilter/src_movie: fix how we check for overflows with seek_point
-- avcodec/j2kenc: Add attribution to OpenJPEG project:
-
-
-version 3.0.1:
-- avcodec/libutvideodec: copy frame so it has reference counters when refcounted_frames is set
-- avformat/rtpdec_jpeg: fix low contrast image on low quality setting
-- avformat/mpegtsenc: Fix used service
-- avformat/mpegtsenc: Keep track of the program for each service
-- avformat/file: Add crypto to default whitelist
-- avcodec/mjpegenc_common: Store approximate aspect if exact cannot be stored
-- lavc/hevc: Allow arbitrary garbage in bytestream as long as at least one NAL unit is found.
-- avcodec/resample: Remove disabled and faulty code
-- indeo2: Fix banding artefacts
-- indeo2data: K&R formatting cosmetics
-- avformat/hlsenc: Fix passing options, regression since bc9a5965c815cf7fd998d8ce14a18b8e861dd9ce
-- avutil/random_seed: Add the runtime in cycles of the main loop to the entropy pool
-- avutil/channel_layout: AV_CH_LAYOUT_6POINT1_BACK not reachable in parsing
-- avformat/concatdec: set safe mode to enabled instead of auto
-- avformat/utils: fix dts from pts code in compute_pkt_fields() during ascending delay
-- avformat/rtpenc: Fix integer overflow in NTP_TO_RTP_FORMAT
-- avcodec/dca: clear X96 channels if nothing was decoded
-- fate/aac: Increase fuzz from of fate-aac-pns-encode from 72 to 74 for Loongson
-- avformat/cache: Fix memleak of tree entries
-- lavf/mov: downgrade sidx errors to non-fatal warnings; fixes trac #5216
-- lavf/mov: fix sidx with edit lists
-- avcodec/mjpegdec: Fix decoding slightly odd progressive jpeg
-- swscale/utils: Fix chrSrcHSubSample for GBRAP16
-- swscale/input: Fix GBRAP16 input
-- avutil/pixdesc: Make get_color_type() aware of CIE XYZ formats
-- avcodec/h264: Execute error concealment before marking the frame as done.
-- swscale/x86/output: Fix yuv2planeX_16* with unaligned destination
-- swscale/x86/output: Move code into yuv2planeX_mainloop
-- MAINTAINERS: add myself as an OS/2 maintainer
-- libwebpenc_animencoder: print library messages in verbose log levels
-- libwebpenc_animencoder: zero initialize the WebPAnimEncoderOptions struct
-- configure: check for SEC_I_CONTEXT_EXPIRED before enabling SChannel
-- lavf/http: Add httpproxy to the default protocol whitelist.
-- doc/utils: fix typo for min() description
-- ffserver&ffm: Fixed issues preventing ffserver write_index and files_size from being set correctly which was breaking ffserver streaming.
-- postproc: fix unaligned access
-- vc2enc: fix use of uninitialized variables in the rate control system, correctly zero out coefficient array padding
-- aacenc: optimize encoding speed
-- avcodec/diracdec: check bitstream size related fields for overflows
-- avcodec/h264_slice: Check PPS more extensively when its not copied
+version <next>:
+
+
+version 3.1.1:
+- doc/APIchanges: document the lavu/lavf field moves
+- avformat/avformat: Move new field to the end of AVStream
+- avformat/utils: update deprecated AVStream->codec when the context is updated
+- avutil/frame: Move new field to the end of AVFrame
+- libavcodec/exr : fix decoding piz float file.
+- avformat/mov: Check sample size
+- lavfi: Move new field to the end of AVFilterContext
+- lavfi: Move new field to the end of AVFilterLink
+- ffplay: Fix usage of private lavfi API
+- lavc/mediacodecdec_h264: add missing NAL headers to SPS/PPS buffers
+- lavc/pnm_parser: disable parsing for text based PNMs
+
+
+version 3.1:
+- DXVA2-accelerated HEVC Main10 decoding
+- fieldhint filter
+- loop video filter and aloop audio filter
+- Bob Weaver deinterlacing filter
+- firequalizer filter
+- datascope filter
+- bench and abench filters
+- ciescope filter
+- protocol blacklisting API
+- MediaCodec H264 decoding
+- VC-2 HQ RTP payload format (draft v1) depacketizer and packetizer
+- VP9 RTP payload format (draft v2) packetizer
+- AudioToolbox audio decoders
+- AudioToolbox audio encoders
+- coreimage filter (GPU based image filtering on OSX)
+- libdcadec removed
+- bitstream filter for extracting DTS core
+- ADPCM IMA DAT4 decoder
+- musx demuxer
+- aix demuxer
+- remap filter
+- hash and framehash muxers
+- colorspace filter
+- hdcd filter
+- readvitc filter
+- VAAPI-accelerated format conversion and scaling
+- libnpp/CUDA-accelerated format conversion and scaling
+- Duck TrueMotion 2.0 Real Time decoder
+- Wideband Single-bit Data (WSD) demuxer
+- VAAPI-accelerated H.264/HEVC/MJPEG encoding
+- DTS Express (LBR) decoder
+- Generic OpenMAX IL encoder with support for Raspberry Pi
+- IFF ANIM demuxer & decoder
+- Direct Stream Transfer (DST) decoder
+- loudnorm filter
+- MTAF demuxer and decoder
+- MagicYUV decoder
+- OpenExr improvements (tile data and B44/B44A support)
+- BitJazz SheerVideo decoder
+- CUDA CUVID H264/HEVC decoder
+- 10-bit depth support in native utvideo decoder
+- libutvideo wrapper removed
+- YUY2 Lossless Codec decoder
+- VideoToolbox H.264 encoder
 
 
 version 3.0:
@@ -934,8 +935,8 @@ version 0.8:
 - showinfo filter added
 - SMPTE 302M AES3 audio decoder
 - Apple Core Audio Format muxer
-- 9bit and 10bit per sample support in the H.264 decoder
-- 9bit and 10bit FFV1 encoding / decoding
+- 9 bits and 10 bits per sample support in the H.264 decoder
+- 9 bits and 10 bits FFV1 encoding / decoding
 - split filter added
 - select filter added
 - sdl output device added
@@ -1228,7 +1229,7 @@ version 0.4.9-pre1:
 - rate distorted optimal lambda->qp support
 - AAC encoding with libfaac
 - Sunplus JPEG codec (SP5X) support
-- use Lagrange multipler instead of QP for ratecontrol
+- use Lagrange multiplier instead of QP for ratecontrol
 - Theora/VP3 decoding support
 - XA and ADX ADPCM codecs
 - export MPEG-2 active display area / pan scan
diff --git a/LICENSE.md b/LICENSE.md
index 0c53d0f..d08c747 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,4 +1,4 @@
-#FFmpeg:
+# License
 
 Most files in FFmpeg are under the GNU Lesser General Public License version 2.1
 or later (LGPL v2.1+). Read the file `COPYING.LGPLv2.1` for details. Some other
@@ -13,16 +13,18 @@ configure to activate them. In this case, FFmpeg's license changes to GPL v2+.
 Specifically, the GPL parts of FFmpeg are:
 
 - libpostproc
-- optional x86 optimizations in the files
-  - `libavcodec/x86/flac_dsp_gpl.asm`
-  - `libavcodec/x86/idct_mmx.c`
-  - `libavfilter/x86/vf_removegrain.asm`
-- libutvideo encoding/decoding wrappers in
-  `libavcodec/libutvideo*.cpp`
+- optional x86 optimization in the files
+    - `libavcodec/x86/flac_dsp_gpl.asm`
+    - `libavcodec/x86/idct_mmx.c`
+    - `libavfilter/x86/vf_removegrain.asm`
 - the X11 grabber in `libavdevice/x11grab.c`
-- the swresample test app in
-  `libswresample/swresample-test.c`
-- the `texi2pod.pl` tool
+- the following building and testing tools
+    - `compat/solaris/make_sunver.pl`
+    - `doc/t2h.pm`
+    - `doc/texi2pod.pl`
+    - `libswresample/swresample-test.c`
+    - `tests/checkasm/*`
+    - `tests/tiny_ssim.c`
 - the following filters in libavfilter:
     - `f_ebur128.c`
     - `vf_blackframe.c`
@@ -47,9 +49,9 @@ Specifically, the GPL parts of FFmpeg are:
     - `vf_pp.c`
     - `vf_pp7.c`
     - `vf_pullup.c`
+    - `vf_repeatfields.c`
     - `vf_sab.c`
     - `vf_smartblur.c`
-    - `vf_repeatfields.c`
     - `vf_spp.c`
     - `vf_stereo3d.c`
     - `vf_super2xsai.c`
@@ -73,20 +75,17 @@ There are a handful of files under other licensing terms, namely:
 * `tests/reference.pnm` is under the expat license.
 
 
-external libraries
-==================
+## External libraries
 
 FFmpeg can be combined with a number of external libraries, which sometimes
 affect the licensing of binaries resulting from the combination.
 
-compatible libraries
---------------------
+### Compatible libraries
 
 The following libraries are under GPL:
 - frei0r
 - libcdio
 - librubberband
-- libutvideo
 - libvidstab
 - libx264
 - libx265
@@ -101,14 +100,25 @@ license is incompatible with the LGPL v2.1 and the GPL v2, but not with
 version 3 of those licenses. So to combine these libraries with FFmpeg, the
 license version needs to be upgraded by passing `--enable-version3` to configure.
 
-incompatible libraries
-----------------------
-
-The Fraunhofer AAC library and FAAC are under licenses which
-are incompatible with the GPLv2 and v3. We do not know for certain if their
-licenses are compatible with the LGPL.
-If you wish to enable these libraries, pass `--enable-nonfree` to configure.
-But note that if you enable any of these libraries the resulting binary will
-be under a complex license mix that is more restrictive than the LGPL and that
-may result in additional obligations. It is possible that these
-restrictions cause the resulting binary to be unredistributeable.
+### Incompatible libraries
+
+There are certain libraries you can combine with FFmpeg whose licenses are not
+compatible with the GPL and/or the LGPL. If you wish to enable these
+libraries, even in circumstances that their license may be incompatible, pass
+`--enable-nonfree` to configure. But note that if you enable any of these
+libraries the resulting binary will be under a complex license mix that is
+more restrictive than the LGPL and that may result in additional obligations.
+It is possible that these restrictions cause the resulting binary to be
+unredistributable.
+
+The Fraunhofer FDK AAC and OpenSSL libraries are under licenses which are
+incompatible with the GPLv2 and v3. To the best of our knowledge, they are
+compatible with the LGPL.
+
+The FAAC library is incompatible with all versions of GPL and LGPL.
+
+The NVENC library, while its header file is licensed under the compatible MIT
+license, requires a proprietary binary blob at run time, and is deemed to be
+incompatible with the GPL. We are not certain if it is compatible with the
+LGPL, but we require `--enable-nonfree` even with LGPL configurations in case
+it is not.
diff --git a/MAINTAINERS b/MAINTAINERS
index 0705a69..fd87db5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -43,8 +43,7 @@ Miscellaneous Areas
 ===================
 
 documentation                           Stefano Sabatini, Mike Melanson, Timothy Gu, Lou Logan
-build system (configure, makefiles)     Diego Biurrun, Mans Rullgard
-project server                          Árpád Gereöffy, Michael Niedermayer, Reimar Doeffinger, Alexander Strasser, Lou Logan
+project server                          Árpád Gereöffy, Michael Niedermayer, Reimar Doeffinger, Alexander Strasser
 presets                                 Robert Swain
 metadata subsystem                      Aurelien Jacobs
 release management                      Michael Niedermayer
@@ -56,7 +55,7 @@ Communication
 website                                 Deby Barbara Lepage
 fate.ffmpeg.org                         Timothy Gu
 Trac bug tracker                        Alexander Strasser, Michael Niedermayer, Carl Eugen Hoyos, Lou Logan
-mailing lists                           Michael Niedermayer, Baptiste Coudurier, Lou Logan
+mailing lists                           Baptiste Coudurier, Lou Logan
 Google+                                 Paul B Mahol, Michael Niedermayer, Alexander Strasser
 Twitter                                 Lou Logan, Reynaldo H. Verdejo Pinochet
 Launchpad                               Timothy Gu
@@ -89,7 +88,6 @@ Other:
   rational.c, rational.h                Michael Niedermayer
   rc4                                   Reimar Doeffinger
   ripemd.c, ripemd.h                    James Almer
-  timecode                              Clément Bœsch
 
 
 libavcodec
@@ -117,8 +115,6 @@ Generic Parts:
     faandct.c, faandct.h                Michael Niedermayer
   Golomb coding:
     golomb.c, golomb.h                  Michael Niedermayer
-  LPC:
-    lpc.c, lpc.h                        Justin Ruggles
   motion estimation:
     motion*                             Michael Niedermayer
   rate control:
@@ -139,19 +135,13 @@ Codecs:
   8bps.c                                Roberto Togni
   8svx.c                                Jaikrishnan Menon
   aacenc*, aaccoder.c                   Rostislav Pehlivanov
-  aasc.c                                Kostya Shishkov
-  ac3*                                  Justin Ruggles
   alacenc.c                             Jaikrishnan Menon
   alsdec.c                              Thilo Borgmann
-  apedec.c                              Kostya Shishkov
   ass*                                  Aurelien Jacobs
   asv*                                  Michael Niedermayer
-  atrac3*                               Benjamin Larsson
   atrac3plus*                           Maxim Poliakovski
   bgmc.c, bgmc.h                        Thilo Borgmann
-  bink.c                                Kostya Shishkov
   binkaudio.c                           Peter Ross
-  bmp.c                                 Mans Rullgard, Kostya Shishkov
   cavs*                                 Stefan Gehrer
   cdxl.c                                Paul B Mahol
   celp_filters.*                        Vitor Sessak
@@ -159,27 +149,21 @@ Codecs:
   cinepakenc.c                          Rl / Aetey G.T. AB
   ccaption_dec.c                        Anshul Maheshwari
   cljr                                  Alex Beregszaszi
-  cllc.c                                Derek Buitenhuis
-  cook.c, cookdata.h                    Benjamin Larsson
   cpia.c                                Stephan Hilb
   crystalhd.c                           Philip Langdale
   cscd.c                                Reimar Doeffinger
-  dca.c                                 Kostya Shishkov, Benjamin Larsson
+  cuvid.c                               Timo Rothenpieler
   dirac*                                Rostislav Pehlivanov
   dnxhd*                                Baptiste Coudurier
   dpcm.c                                Mike Melanson
-  dss_sp.c                              Oleksij Rempel, Michael Niedermayer
+  dss_sp.c                              Oleksij Rempel
   dv.c                                  Roman Shaposhnik
   dvbsubdec.c                           Anshul Maheshwari
-  dxa.c                                 Kostya Shishkov
   eacmv*, eaidct*, eat*                 Peter Ross
   evrc*                                 Paul B Mahol
   exif.c, exif.h                        Thilo Borgmann
   ffv1*                                 Michael Niedermayer
   ffwavesynth.c                         Nicolas George
-  fic.c                                 Derek Buitenhuis
-  flac*                                 Justin Ruggles
-  flashsv*                              Benjamin Larsson
   flicvideo.c                           Mike Melanson
   g722.c                                Martin Storsjo
   g726.c                                Roman Shaposhnik
@@ -190,16 +174,10 @@ Codecs:
   hap*                                  Tom Butterworth
   huffyuv*                              Michael Niedermayer, Christophe Gisquet
   idcinvideo.c                          Mike Melanson
-  imc*                                  Benjamin Larsson
-  indeo2*                               Kostya Shishkov
-  indeo5*                               Kostya Shishkov
   interplayvideo.c                      Mike Melanson
-  ivi*                                  Kostya Shishkov
-  jacosub*                              Clément Bœsch
+  jni*, ffjni*                          Matthieu Bouron
   jpeg2000*                             Nicolas Bertrand
-  jpeg_ls.c                             Kostya Shishkov
   jvdec.c                               Peter Ross
-  kmvc.c                                Kostya Shishkov
   lcl*.c                                Roberto Togni, Reimar Doeffinger
   libcelt_dec.c                         Nicolas George
   libdirac*                             David Conrad
@@ -208,40 +186,31 @@ Codecs:
   libopenjpeg.c                         Jaikrishnan Menon
   libopenjpegenc.c                      Michael Bradshaw
   libschroedinger*                      David Conrad
-  libspeexdec.c                         Justin Ruggles
   libtheoraenc.c                        David Conrad
-  libutvideo*                           Carl Eugen Hoyos
   libvorbis.c                           David Conrad
   libvpx*                               James Zern
-  libx264.c                             Mans Rullgard, Jason Garrett-Glaser
-  libx265.c                             Derek Buitenhuis
   libxavs.c                             Stefan Gehrer
   libzvbi-teletextdec.c                 Marton Balint
-  loco.c                                Kostya Shishkov
   lzo.h, lzo.c                          Reimar Doeffinger
   mdec.c                                Michael Niedermayer
   mimic.c                               Ramiro Polla
   mjpeg*.c                              Michael Niedermayer
   mlp*                                  Ramiro Polla
   mmvideo.c                             Peter Ross
-  mpc*                                  Kostya Shishkov
   mpeg12.c, mpeg12data.h                Michael Niedermayer
   mpegvideo.c, mpegvideo.h              Michael Niedermayer
   mqc*                                  Nicolas Bertrand
   msmpeg4.c, msmpeg4data.h              Michael Niedermayer
   msrle.c                               Mike Melanson
   msvideo1.c                            Mike Melanson
-  nellymoserdec.c                       Benjamin Larsson
   nuv.c                                 Reimar Doeffinger
-  nvenc.c                               Timo Rothenpieler
+  nvenc*                                Timo Rothenpieler
   paf.*                                 Paul B Mahol
   pcx.c                                 Ivo van Poorten
   pgssubdec.c                           Reimar Doeffinger
   ptx.c                                 Ivo van Poorten
   qcelp*                                Reynaldo H. Verdejo Pinochet
-  qdm2.c, qdm2data.h                    Roberto Togni, Benjamin Larsson
-  qdrw.c                                Kostya Shishkov
-  qpeg.c                                Kostya Shishkov
+  qdm2.c, qdm2data.h                    Roberto Togni
   qsv*                                  Ivan Uskov
   qtrle.c                               Mike Melanson
   ra144.c, ra144.h, ra288.c, ra288.h    Roberto Togni
@@ -250,10 +219,8 @@ Codecs:
   rpza.c                                Roberto Togni
   rtjpeg.c, rtjpeg.h                    Reimar Doeffinger
   rv10.c                                Michael Niedermayer
-  rv3*                                  Kostya Shishkov
-  rv4*                                  Kostya Shishkov, Christophe Gisquet
+  rv4*                                  Christophe Gisquet
   s3tc*                                 Ivo van Poorten
-  smacker.c                             Kostya Shishkov
   smc.c                                 Mike Melanson
   smvjpegdec.c                          Ash Hughes
   snow*                                 Michael Niedermayer, Loren Merritt
@@ -262,54 +229,41 @@ Codecs:
   sunrast.c                             Ivo van Poorten
   svq3.c                                Michael Niedermayer
   tak*                                  Paul B Mahol
-  targa.c                               Kostya Shishkov
-  tiff.c                                Kostya Shishkov
   truemotion1*                          Mike Melanson
-  truemotion2*                          Kostya Shishkov
-  truespeech.c                          Kostya Shishkov
-  tscc.c                                Kostya Shishkov
   tta.c                                 Alex Beregszaszi, Jaikrishnan Menon
   ttaenc.c                              Paul B Mahol
   txd.c                                 Ivo van Poorten
-  ulti*                                 Kostya Shishkov
-  v410*.c                               Derek Buitenhuis
-  vb.c                                  Kostya Shishkov
-  vble.c                                Derek Buitenhuis
-  vc1*                                  Kostya Shishkov, Christophe Gisquet
+  vc1*                                  Christophe Gisquet
   vc2*                                  Rostislav Pehlivanov
   vcr1.c                                Michael Niedermayer
   vda_h264_dec.c                        Xidorn Quan
+  videotoolboxenc.c                     Rick Kern
   vima.c                                Paul B Mahol
-  vmnc.c                                Kostya Shishkov
   vorbisdec.c                           Denes Balatoni, David Conrad
   vorbisenc.c                           Oded Shimon
   vp3*                                  Mike Melanson
   vp5                                   Aurelien Jacobs
   vp6                                   Aurelien Jacobs
-  vp8                                   David Conrad, Jason Garrett-Glaser, Ronald Bultje
-  vp9                                   Ronald Bultje, Clément Bœsch
+  vp8                                   David Conrad, Ronald Bultje
+  vp9                                   Ronald Bultje
   vqavideo.c                            Mike Melanson
-  wavpack.c                             Kostya Shishkov
   wmaprodec.c                           Sascha Sommer
   wmavoice.c                            Ronald S. Bultje
   wmv2.c                                Michael Niedermayer
-  wnv1.c                                Kostya Shishkov
   xan.c                                 Mike Melanson
   xbm*                                  Paul B Mahol
   xface                                 Stefano Sabatini
-  xl.c                                  Kostya Shishkov
   xvmc.c                                Ivan Kalvachev
   xwd*                                  Paul B Mahol
-  zerocodec.c                           Derek Buitenhuis
-  zmbv*                                 Kostya Shishkov
 
 Hardware acceleration:
   crystalhd.c                           Philip Langdale
   dxva2*                                Hendrik Leppkes, Laurent Aimar
+  mediacodec*                           Matthieu Bouron
   vaapi*                                Gwenole Beauchesne
-  vda*                                  Sebastien Zwickert
+  vaapi_encode*                         Mark Thompson
   vdpau*                                Philip Langdale, Carl Eugen Hoyos
-  videotoolbox*                         Sebastien Zwickert
+  videotoolbox*                         Rick Kern
 
 
 libavdevice
@@ -353,7 +307,9 @@ Filters:
   af_biquads.c                          Paul B Mahol
   af_chorus.c                           Paul B Mahol
   af_compand.c                          Paul B Mahol
+  af_firequalizer.c                     Muhammad Faiz
   af_ladspa.c                           Paul B Mahol
+  af_loudnorm.c                         Kyle Swanson
   af_pan.c                              Nicolas George
   af_sidechaincompress.c                Paul B Mahol
   af_silenceremove.c                    Paul B Mahol
@@ -366,6 +322,7 @@ Filters:
   vf_colorbalance.c                     Paul B Mahol
   vf_colorkey.c                         Timo Rothenpieler
   vf_colorlevels.c                      Paul B Mahol
+  vf_coreimage.m                        Thilo Borgmann
   vf_deband.c                           Paul B Mahol
   vf_dejudder.c                         Nicholas Robbins
   vf_delogo.c                           Jean Delvare (CC <jdelvare at suse.com>)
@@ -380,6 +337,7 @@ Filters:
   vf_neighbor.c                         Paul B Mahol
   vf_psnr.c                             Paul B Mahol
   vf_random.c                           Paul B Mahol
+  vf_readvitc.c                         Tobias Rapp (CC t.rapp at noa-archive dot com)
   vf_scale.c                            Michael Niedermayer
   vf_separatefields.c                   Paul B Mahol
   vf_ssim.c                             Paul B Mahol
@@ -399,6 +357,7 @@ Generic parts:
     libavformat/avformat.h              Michael Niedermayer
   Utility Code:
     libavformat/utils.c                 Michael Niedermayer
+  Text Subtitles                        Clément Bœsch
 
 
 Muxers/Demuxers:
@@ -408,7 +367,6 @@ Muxers/Demuxers:
   afc.c                                 Paul B Mahol
   aiffdec.c                             Baptiste Coudurier, Matthieu Bouron
   aiffenc.c                             Baptiste Coudurier, Matthieu Bouron
-  ape.c                                 Kostya Shishkov
   apngdec.c                             Benoit Fouet
   ass*                                  Aurelien Jacobs
   astdec.c                              Paul B Mahol
@@ -422,14 +380,12 @@ Muxers/Demuxers:
   cdxl.c                                Paul B Mahol
   crc.c                                 Michael Niedermayer
   daud.c                                Reimar Doeffinger
-  dss.c                                 Oleksij Rempel, Michael Niedermayer
+  dss.c                                 Oleksij Rempel
   dtshddec.c                            Paul B Mahol
   dv.c                                  Roman Shaposhnik
-  dxa.c                                 Kostya Shishkov
   electronicarts.c                      Peter Ross
   epafdec.c                             Paul B Mahol
   ffm*                                  Baptiste Coudurier
-  flac*                                 Justin Ruggles
   flic.c                                Mike Melanson
   flvdec.c, flvenc.c                    Michael Niedermayer
   gxf.c                                 Reimar Doeffinger
@@ -443,7 +399,6 @@ Muxers/Demuxers:
   ipmovie.c                             Mike Melanson
   ircam*                                Paul B Mahol
   iss.c                                 Stefan Gehrer
-  jacosub*                              Clément Bœsch
   jvdec.c                               Peter Ross
   libmodplug.c                          Clément Bœsch
   libnut.c                              Oded Shimon
@@ -458,10 +413,9 @@ Muxers/Demuxers:
   mgsts.c                               Paul B Mahol
   microdvd*                             Aurelien Jacobs
   mm.c                                  Peter Ross
-  mov.c                                 Michael Niedermayer, Baptiste Coudurier
+  mov.c                                 Baptiste Coudurier
   movenc.c                              Baptiste Coudurier, Matthieu Bouron
   movenccenc.c                          Eran Kornblau
-  mpc.c                                 Kostya Shishkov
   mpeg.c                                Michael Niedermayer
   mpegenc.c                             Michael Niedermayer
   mpegts.c                              Marton Balint
@@ -487,8 +441,7 @@ Muxers/Demuxers:
   raw.c                                 Michael Niedermayer
   rdt.c                                 Ronald S. Bultje
   rl2.c                                 Sascha Sommer
-  rmdec.c, rmenc.c                      Ronald S. Bultje, Kostya Shishkov
-  rtmp*                                 Kostya Shishkov
+  rmdec.c, rmenc.c                      Ronald S. Bultje
   rtp.c, rtpenc.c                       Martin Storsjo
   rtpdec_ac3.*                          Gilles Chanteperdrix
   rtpdec_dv.*                           Thomas Volkert
@@ -496,15 +449,13 @@ Muxers/Demuxers:
   rtpdec_hevc.*, rtpenc_hevc.*          Thomas Volkert
   rtpdec_mpa_robust.*                   Gilles Chanteperdrix
   rtpdec_asf.*                          Ronald S. Bultje
+  rtpdec_vc2hq.*, rtpenc_vc2hq.*        Thomas Volkert
   rtpdec_vp9.c                          Thomas Volkert
   rtpenc_mpv.*, rtpenc_aac.*            Martin Storsjo
-  rtsp.c                                Luca Barbato
   sbgdec.c                              Nicolas George
   sdp.c                                 Martin Storsjo
   segafilm.c                            Mike Melanson
   segment.c                             Stefano Sabatini
-  siff.c                                Kostya Shishkov
-  smacker.c                             Kostya Shishkov
   smjpeg*                               Paul B Mahol
   spdif*                                Anssi Hannula
   srtdec.c                              Aurelien Jacobs
@@ -519,7 +470,6 @@ Muxers/Demuxers:
   webvtt*                               Matthew J Heaney
   westwood.c                            Mike Melanson
   wtv.c                                 Peter Ross
-  wv.c                                  Kostya Shishkov
   wvenc.c                               Paul B Mahol
 
 Protocols:
@@ -550,20 +500,16 @@ Resamplers:
 Operating systems / CPU architectures
 =====================================
 
-Alpha                                   Mans Rullgard, Falk Hueffner
-ARM                                     Mans Rullgard
-AVR32                                   Mans Rullgard
-MIPS                                    Mans Rullgard, Nedeljko Babic
+Alpha                                   Falk Hueffner
+MIPS                                    Nedeljko Babic
 Mac OS X / PowerPC                      Romain Dolbeau, Guillaume Poirier
 Amiga / PowerPC                         Colin Ward
-Linux / PowerPC                         Luca Barbato
 Windows MinGW                           Alex Beregszaszi, Ramiro Polla
 Windows Cygwin                          Victor Paesa
 Windows MSVC                            Matthew Oliver, Hendrik Leppkes
 Windows ICL                             Matthew Oliver
 ADI/Blackfin DSP                        Marc Hoffman
 Sparc                                   Roman Shaposhnik
-x86                                     Michael Niedermayer
 OS/2                                    KO Myung-Hun
 
 
@@ -584,7 +530,6 @@ GnuPG Fingerprints of maintainers and contributors
 
 Alexander Strasser            1C96 78B7 83CB 8AA7 9AF5 D1EB A7D8 A57B A876 E58F
 Anssi Hannula                 1A92 FF42 2DD9 8D2E 8AF7 65A9 4278 C520 513D F3CB
-Anton Khirnov                 6D0C 6625 56F8 65D1 E5F5 814B B50A 1241 C067 07AB
 Ash Hughes                    694D 43D2 D180 C7C7 6421 ABD3 A641 D0B7 623D 6029
 Attila Kinali                 11F0 F9A6 A1D2 11F6 C745 D10C 6520 BCDD F2DF E765
 Baptiste Coudurier            8D77 134D 20CC 9220 201F C5DB 0AC9 325C 5C1A BAAA
@@ -592,16 +537,13 @@ Ben Littler                   3EE3 3723 E560 3214 A8CD 4DEB 2CDB FCE7 768C 8D2C
 Benoit Fouet                  B22A 4F4F 43EF 636B BB66 FCDC 0023 AE1E 2985 49C8
 Clément Bœsch                 52D0 3A82 D445 F194 DB8B 2B16 87EE 2CB8 F4B8 FCF9
 Daniel Verkamp                78A6 07ED 782C 653E C628 B8B9 F0EB 8DD8 2F0E 21C7
-Diego Biurrun                 8227 1E31 B6D9 4994 7427 E220 9CAE D6CC 4757 FCC5
 FFmpeg release signing key    FCF9 86EA 15E6 E293 A564 4F10 B432 2F04 D676 58D8
 Ganesh Ajjanagadde            C96A 848E 97C3 CEA2 AB72 5CE4 45F9 6A2D 3C36 FB1B
 Gwenole Beauchesne            2E63 B3A6 3E44 37E2 017D 2704 53C7 6266 B153 99C4
 Jaikrishnan Menon             61A1 F09F 01C9 2D45 78E1 C862 25DC 8831 AF70 D368
 Jean Delvare                  7CA6 9F44 60F1 BDC4 1FD2 C858 A552 6B9B B3CD 4E6A
-Justin Ruggles                3136 ECC0 C10D 6C04 5F43 CA29 FCBE CD2A 3787 1EBF
 Loren Merritt                 ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE
 Lou Logan                     7D68 DC73 CBEF EABB 671A B6CF 621C 2E28 82F8 DC3A
-Luca Barbato                  6677 4209 213C 8843 5B67 29E7 E84C 78C2 84E9 0E34
 Michael Niedermayer           9FF2 128B 147E F673 0BAD F133 611E C787 040B 0FAB
 Nicolas George                24CE 01CE 9ACC 5CEB 74D8 8D9D B063 D997 36E5 4C93
 Panagiotis Issaris            6571 13A3 33D9 3726 F728 AA98 F643 B12E ECF3 E029
diff --git a/Makefile b/Makefile
index 87a9869..8aa72fd 100644
--- a/Makefile
+++ b/Makefile
@@ -30,16 +30,18 @@ $(foreach prog,$(AVBASENAMES),$(eval OBJS-$(prog) += cmdutils.o))
 $(foreach prog,$(AVBASENAMES),$(eval OBJS-$(prog)-$(CONFIG_OPENCL) += cmdutils_opencl.o))
 
 OBJS-ffmpeg                   += ffmpeg_opt.o ffmpeg_filter.o
-OBJS-ffmpeg-$(HAVE_VDPAU_X11) += ffmpeg_vdpau.o
-OBJS-ffmpeg-$(HAVE_DXVA2_LIB) += ffmpeg_dxva2.o
+OBJS-ffmpeg-$(CONFIG_VIDEOTOOLBOX) += ffmpeg_videotoolbox.o
+OBJS-ffmpeg-$(CONFIG_LIBMFX)  += ffmpeg_qsv.o
+OBJS-ffmpeg-$(CONFIG_VAAPI)   += ffmpeg_vaapi.o
 ifndef CONFIG_VIDEOTOOLBOX
 OBJS-ffmpeg-$(CONFIG_VDA)     += ffmpeg_videotoolbox.o
 endif
-OBJS-ffmpeg-$(CONFIG_VIDEOTOOLBOX) += ffmpeg_videotoolbox.o
-OBJS-ffmpeg-$(CONFIG_LIBMFX)  += ffmpeg_qsv.o
+OBJS-ffmpeg-$(CONFIG_CUVID)   += ffmpeg_cuvid.o
+OBJS-ffmpeg-$(HAVE_DXVA2_LIB) += ffmpeg_dxva2.o
+OBJS-ffmpeg-$(HAVE_VDPAU_X11) += ffmpeg_vdpau.o
 OBJS-ffserver                 += ffserver_config.o
 
-TESTTOOLS   = audiogen videogen rotozoom tiny_psnr tiny_ssim base64
+TESTTOOLS   = audiogen videogen rotozoom tiny_psnr tiny_ssim base64 audiomatch
 HOSTPROGS  := $(TESTTOOLS:%=tests/%) doc/print_options
 TOOLS       = qt-faststart trasher uncoded_frame
 TOOLS-$(CONFIG_ZLIB) += cws2fws
@@ -59,7 +61,8 @@ FFLIBS := avutil
 DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.ffpreset) $(SRC_PATH)/doc/ffprobe.xsd
 EXAMPLES_FILES := $(wildcard $(SRC_PATH)/doc/examples/*.c) $(SRC_PATH)/doc/examples/Makefile $(SRC_PATH)/doc/examples/README
 
-SKIPHEADERS = cmdutils_common_opts.h compat/w32pthreads.h
+SKIPHEADERS = cmdutils_common_opts.h                                    \
+              compat/w32pthreads.h
 
 include $(SRC_PATH)/common.mak
 
@@ -181,7 +184,7 @@ clean::
 
 distclean::
 	$(RM) $(DISTCLEANSUFFIXES)
-	$(RM) config.* .config libavutil/avconfig.h .version avversion.h version.h libavutil/ffversion.h libavcodec/codec_names.h
+	$(RM) config.* .config libavutil/avconfig.h .version mapfile avversion.h version.h libavutil/ffversion.h libavcodec/codec_names.h libavcodec/bsf_list.c libavformat/protocol_list.c
 ifeq ($(SRC_LINK),src)
 	$(RM) src
 endif
diff --git a/RELEASE b/RELEASE
index b502146..94ff29c 100644
--- a/RELEASE
+++ b/RELEASE
@@ -1 +1 @@
-3.0.2
+3.1.1
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 861dc04..afa25ae 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -1,10 +1,10 @@
 
-              ┌─────────────────────────────────────────┐
-              │ RELEASE NOTES for FFmpeg 3.0 "Einstein" │
-              └─────────────────────────────────────────┘
+              ┌────────────────────────────────────────┐
+              │ RELEASE NOTES for FFmpeg 3.1 "Laplace" │
+              └────────────────────────────────────────┘
 
-   The FFmpeg Project proudly presents FFmpeg 3.0 "Einstein", about 5
-   months after the release of FFmpeg 2.8.
+   The FFmpeg Project proudly presents FFmpeg 3.1 "Laplace", about 4
+   months after the release of FFmpeg 3.0.
 
    A complete Changelog is available at the root of the project, and the
    complete Git history on http://source.ffmpeg.org.
diff --git a/VERSION b/VERSION
index b502146..94ff29c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0.2
+3.1.1
diff --git a/common.mak b/common.mak
index 03b51c5..3f2096d 100644
--- a/common.mak
+++ b/common.mak
@@ -39,7 +39,7 @@ CCFLAGS     = $(CPPFLAGS) $(CFLAGS)
 OBJCFLAGS  += $(EOBJCFLAGS)
 OBJCCFLAGS  = $(CPPFLAGS) $(CFLAGS) $(OBJCFLAGS)
 ASFLAGS    := $(CPPFLAGS) $(ASFLAGS)
-CXXFLAGS   += $(CPPFLAGS) $(CFLAGS)
+CXXFLAGS   := $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS)
 YASMFLAGS  += $(IFLAGS:%=%/) -Pconfig.asm
 
 HOSTCCFLAGS = $(IFLAGS) $(HOSTCPPFLAGS) $(HOSTCFLAGS)
@@ -114,8 +114,8 @@ FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(EXTRALIBS)
 
 OBJS      := $(sort $(OBJS:%=$(SUBDIR)%))
 SLIBOBJS  := $(sort $(SLIBOBJS:%=$(SUBDIR)%))
-TESTOBJS  := $(TESTOBJS:%=$(SUBDIR)%) $(TESTPROGS:%=$(SUBDIR)%-test.o)
-TESTPROGS := $(TESTPROGS:%=$(SUBDIR)%-test$(EXESUF))
+TESTOBJS  := $(TESTOBJS:%=$(SUBDIR)tests/%) $(TESTPROGS:%=$(SUBDIR)tests/%.o)
+TESTPROGS := $(TESTPROGS:%=$(SUBDIR)tests/%$(EXESUF))
 HOSTOBJS  := $(HOSTPROGS:%=$(SUBDIR)%.o)
 HOSTPROGS := $(HOSTPROGS:%=$(SUBDIR)%$(HOSTEXESUF))
 TOOLS     += $(TOOLS-yes)
@@ -158,9 +158,7 @@ LIBSUFFIXES       = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a
 
 define RULES
 clean::
-	$(RM) $(OBJS) $(OBJS:.o=.d) $(OBJS:.o=$(DEFAULT_YASMD).d)
-	$(RM) $(HOSTPROGS)
-	$(RM) $(TOOLS)
+	$(RM) $(HOSTPROGS) $(TESTPROGS) $(TOOLS)
 endef
 
 $(eval $(RULES))
diff --git a/compat/dispatch_semaphore/semaphore.h b/compat/dispatch_semaphore/semaphore.h
new file mode 100644
index 0000000..008c637
--- /dev/null
+++ b/compat/dispatch_semaphore/semaphore.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef COMPAT_DISPATCH_SEMAPHORE_SEMAPHORE_H
+#define COMPAT_DISPATCH_SEMAPHORE_SEMAPHORE_H
+
+#include <dispatch/dispatch.h>
+#include <errno.h>
+
+#define sem_t dispatch_semaphore_t
+#define sem_post(psem)              dispatch_semaphore_signal(*psem)
+#define sem_wait(psem)              dispatch_semaphore_wait(*psem, DISPATCH_TIME_FOREVER)
+#define sem_timedwait(psem, val)    dispatch_semaphore_wait(*psem, dispatch_walltime(val, 0))
+#define sem_destroy(psem)           dispatch_release(*psem)
+
+static inline int compat_sem_init(dispatch_semaphore_t *psem,
+                                  int unused, int val)
+{
+    int ret = !!(*psem = dispatch_semaphore_create(val)) - 1;
+    if (ret < 0)
+        errno = ENOMEM;
+    return ret;
+}
+
+#define sem_init compat_sem_init
+
+#endif /* COMPAT_DISPATCH_SEMAPHORE_SEMAPHORE_H */
diff --git a/configure b/configure
index 9103e85..3760641 100755
--- a/configure
+++ b/configure
@@ -91,6 +91,7 @@ Standard options:
   --enable-rpath           use rpath to allow installing libraries in paths
                            not part of the dynamic linker search path
                            use rpath when linking programs [USE WITH CARE]
+  --install-name-dir=DIR   Darwin directory name for installed targets
 
 Licensing options:
   --enable-gpl             allow use of GPL code, the resulting libs
@@ -148,14 +149,6 @@ Component options:
   --disable-faan           disable floating point AAN (I)DCT code
   --disable-pixelutils     disable pixel utils in libavutil
 
-Hardware accelerators:
-  --disable-d3d11va        disable D3D11VA code [autodetect]
-  --disable-dxva2          disable DXVA2 code [autodetect]
-  --disable-vaapi          disable VAAPI code [autodetect]
-  --disable-vda            disable VDA code [autodetect]
-  --disable-vdpau          disable VDPAU code [autodetect]
-  --enable-videotoolbox    enable VideoToolbox code [autodetect]
-
 Individual component options:
   --disable-everything     disable all components listed below
   --disable-encoder=NAME   disable encoder NAME
@@ -194,10 +187,23 @@ Individual component options:
   --disable-filters        disable all filters
 
 External library support:
+
+  Using any of the following switches will allow FFmpeg to link to the
+  corresponding external library. All the components depending on that library
+  will become enabled, if all their other dependencies are met and they are not
+  explicitly disabled. E.g. --enable-libwavpack will enable linking to
+  libwavpack and allow the libwavpack encoder to be built, unless it is
+  specifically disabled with --disable-encoder=libwavpack.
+
+  Note that only the system libraries are auto-detected. All the other external
+  libraries must be explicitly enabled.
+
+  Also note that the following help text describes the purpose of the libraries
+  themselves, not all their features will necessarily be usable by FFmpeg.
+
   --enable-avisynth        enable reading of AviSynth script files [no]
   --disable-bzlib          disable bzlib [autodetect]
   --enable-chromaprint     enable audio fingerprinting with chromaprint [no]
-  --enable-fontconfig      enable fontconfig, useful for drawtext filter [no]
   --enable-frei0r          enable frei0r video filtering [no]
   --enable-gcrypt          enable gcrypt, needed for rtmp(t)e support
                            if openssl, librtmp or gmp is not used [no]
@@ -206,6 +212,7 @@ External library support:
   --enable-gnutls          enable gnutls, needed for https support
                            if openssl is not used [no]
   --disable-iconv          disable iconv [autodetect]
+  --enable-jni             enable JNI support [no]
   --enable-ladspa          enable LADSPA audio filtering [no]
   --enable-libass          enable libass subtitles rendering,
                            needed for subtitles and ass filter [no]
@@ -216,10 +223,12 @@ External library support:
   --enable-libcdio         enable audio CD grabbing with libcdio [no]
   --enable-libdc1394       enable IIDC-1394 grabbing using libdc1394
                            and libraw1394 [no]
-  --enable-libdcadec       enable DCA decoding via libdcadec [no]
+  --enable-libebur128      enable libebur128 for EBU R128 measurement,
+                           needed for loudnorm filter [no]
   --enable-libfaac         enable AAC encoding via libfaac [no]
   --enable-libfdk-aac      enable AAC de/encoding via libfdk-aac [no]
   --enable-libflite        enable flite (voice synthesis) support via libflite [no]
+  --enable-libfontconfig   enable libfontconfig, useful for drawtext filter [no]
   --enable-libfreetype     enable libfreetype, needed for drawtext filter [no]
   --enable-libfribidi      enable libfribidi, improves drawtext filter [no]
   --enable-libgme          enable Game Music Emu via libgme [no]
@@ -227,7 +236,6 @@ External library support:
   --enable-libiec61883     enable iec61883 via libiec61883 [no]
   --enable-libilbc         enable iLBC de/encoding via libilbc [no]
   --enable-libkvazaar      enable HEVC encoding via libkvazaar [no]
-  --enable-libmfx          enable HW acceleration through libmfx
   --enable-libmodplug      enable ModPlug via libmodplug [no]
   --enable-libmp3lame      enable MP3 encoding via libmp3lame [no]
   --enable-libnut          enable NUT (de)muxing via libnut,
@@ -251,7 +259,6 @@ External library support:
   --enable-libtesseract    enable Tesseract, needed for ocr filter [no]
   --enable-libtheora       enable Theora encoding via libtheora [no]
   --enable-libtwolame      enable MP2 encoding via libtwolame [no]
-  --enable-libutvideo      enable Ut Video encoding and decoding via libutvideo [no]
   --enable-libv4l2         enable libv4l2/v4l-utils [no]
   --enable-libvidstab      enable video stabilization using vid.stab [no]
   --enable-libvo-amrwbenc  enable AMR-WB encoding via libvo-amrwbenc [no]
@@ -274,9 +281,8 @@ External library support:
   --enable-libzvbi         enable teletext support via libzvbi [no]
   --disable-lzma           disable lzma [autodetect]
   --enable-decklink        enable Blackmagic DeckLink I/O support [no]
-  --enable-mmal            enable decoding via MMAL [no]
+  --enable-mediacodec      enable Android MediaCodec support [no]
   --enable-netcdf          enable NetCDF, needed for sofalizer filter [no]
-  --enable-nvenc           enable NVIDIA NVENC support [no]
   --enable-openal          enable OpenAL 1.1 capture support [no]
   --enable-opencl          enable OpenCL code
   --enable-opengl          enable OpenGL rendering [no]
@@ -291,6 +297,23 @@ External library support:
   --disable-xlib           disable xlib [autodetect]
   --disable-zlib           disable zlib [autodetect]
 
+  The following libraries provide various hardware acceleration features:
+  --disable-audiotoolbox   disable Apple AudioToolbox code [autodetect]
+  --enable-cuda            enable dynamically linked Nvidia CUDA code [no]
+  --enable-cuvid           enable Nvidia CUVID support [autodetect]
+  --disable-d3d11va        disable Microsoft Direct3D 11 video acceleration code [autodetect]
+  --disable-dxva2          disable Microsoft DirectX 9 video acceleration code [autodetect]
+  --enable-libmfx          enable Intel MediaSDK (AKA Quick Sync Video) code via libmfx [no]
+  --enable-libnpp          enable Nvidia Performance Primitives-based code [no]
+  --enable-mmal            enable Broadcom Multi-Media Abstraction Layer (Raspberry Pi) via MMAL [no]
+  --enable-nvenc           enable Nvidia video encoding code [no]
+  --enable-omx             enable OpenMAX IL code [no]
+  --enable-omx-rpi         enable OpenMAX IL code for Raspberry Pi [no]
+  --disable-vaapi          disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
+  --disable-vda            disable Apple Video Decode Acceleration code [autodetect]
+  --disable-vdpau          disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
+  --disable-videotoolbox   disable VideoToolbox code [autodetect]
+
 Toolchain options:
   --arch=ARCH              select architecture [$arch]
   --cpu=CPU                select the minimum required CPU (affects
@@ -309,6 +332,8 @@ Toolchain options:
   --nm=NM                  use nm tool NM [$nm_default]
   --ar=AR                  use archive tool AR [$ar_default]
   --as=AS                  use assembler AS [$as_default]
+  --ln_s=LN_S              use symbolic link tool LN_S [$ln_s_default]
+  --strip=STRIP            use strip tool STRIP [$strip_default]
   --windres=WINDRES        use windows resource compiler WINDRES [$windres_default]
   --yasmexe=EXE            use yasm-compatible assembler EXE [$yasmexe_default]
   --cc=CC                  use C compiler CC [$cc_default]
@@ -762,7 +787,7 @@ print_enabled(){
     suf=$1
     shift
     for v; do
-        enabled $v && printf "%s\n" ${v%$suf};
+        enabled $v && printf "%s\n" ${v%$suf}
     done
 }
 
@@ -1451,6 +1476,7 @@ EXTERNAL_LIBRARY_LIST="
     gmp
     gnutls
     iconv
+    jni
     ladspa
     libass
     libbluray
@@ -1459,7 +1485,7 @@ EXTERNAL_LIBRARY_LIST="
     libcdio
     libcelt
     libdc1394
-    libdcadec
+    libebur128
     libfaac
     libfdk_aac
     libflite
@@ -1471,7 +1497,6 @@ EXTERNAL_LIBRARY_LIST="
     libiec61883
     libilbc
     libkvazaar
-    libmfx
     libmodplug
     libmp3lame
     libnut
@@ -1494,7 +1519,6 @@ EXTERNAL_LIBRARY_LIST="
     libtesseract
     libtheora
     libtwolame
-    libutvideo
     libv4l2
     libvidstab
     libvo_amrwbenc
@@ -1514,9 +1538,8 @@ EXTERNAL_LIBRARY_LIST="
     libzmq
     libzvbi
     lzma
-    mmal
+    mediacodec
     netcdf
-    nvenc
     openal
     opencl
     opengl
@@ -1524,11 +1547,30 @@ EXTERNAL_LIBRARY_LIST="
     schannel
     sdl
     securetransport
+    videotoolbox
     x11grab
     xlib
     zlib
 "
 
+HWACCEL_LIBRARY_LIST="
+    audiotoolbox
+    cuda
+    cuvid
+    d3d11va
+    dxva2
+    libmfx
+    libnpp
+    mmal
+    nvenc
+    omx
+    vaapi
+    vda
+    vdpau
+    videotoolbox_hwaccel
+    xvmc
+"
+
 DOCUMENT_LIST="
     doc
     htmlpages
@@ -1541,6 +1583,7 @@ FEATURE_LIST="
     ftrapv
     gray
     hardcoded_tables
+    omx_rpi
     runtime_cpudetect
     safe_bitstream_reader
     shared
@@ -1549,16 +1592,6 @@ FEATURE_LIST="
     swscale_alpha
 "
 
-HWACCEL_LIST="
-    d3d11va
-    dxva2
-    vaapi
-    vda
-    vdpau
-    videotoolbox
-    xvmc
-"
-
 LIBRARY_LIST="
     avcodec
     avdevice
@@ -1604,8 +1637,8 @@ CONFIG_LIST="
     $DOCUMENT_LIST
     $EXAMPLE_LIST
     $EXTERNAL_LIBRARY_LIST
+    $HWACCEL_LIBRARY_LIST
     $FEATURE_LIST
-    $HWACCEL_LIST
     $LICENSE_LIST
     $LIBRARY_LIST
     $PROGRAM_LIST
@@ -1752,6 +1785,7 @@ BUILTIN_LIST="
     mm_empty
     rdtsc
     sarestart
+    sem_timedwait
     sync_val_compare_and_swap
 "
 HAVE_LIST_CMDLINE="
@@ -1773,6 +1807,7 @@ HEADERS_LIST="
     asm_types_h
     cdio_paranoia_h
     cdio_paranoia_paranoia_h
+    dispatch_dispatch_h
     dev_bktr_ioctl_bt848_h
     dev_bktr_ioctl_meteor_h
     dev_ic_bt8xx_h
@@ -1943,6 +1978,7 @@ TYPES_LIST="
     struct_group_source_req
     struct_ip_mreq_source
     struct_ipv6_mreq
+    struct_msghdr_msg_flags
     struct_pollfd
     struct_rusage_ru_maxrss
     struct_sctp_event_subscribe
@@ -1979,12 +2015,14 @@ HAVE_LIST="
     libdc1394_2
     makeinfo
     makeinfo_html
+    MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS
     perl
     pod2man
     sdl
     section_data_rel_ro
     texi2html
     threads
+    vaapi_drm
     vaapi_x11
     vdpau_x11
     winrt
@@ -2025,6 +2063,7 @@ CONFIG_EXTRA="
     iirfilter
     imdct15
     intrax8
+    iso_media
     ividsp
     jpegtables
     lgplv3
@@ -2053,14 +2092,18 @@ CONFIG_EXTRA="
     rv34dsp
     sinewin
     snappy
+    srtp
     startcode
     texturedsp
     texturedspenc
     tpeldsp
+    vaapi_encode
+    vc1dsp
     videodsp
     vp3dsp
     vp56dsp
     vp8dsp
+    vt_bt2020
     wma_freqs
     wmv2dsp
 "
@@ -2091,6 +2134,7 @@ PATHS_LIST="
     pkgconfigdir
     prefix
     shlibdir
+    install_name_dir
 "
 
 CMDLINE_SET="
@@ -2119,6 +2163,7 @@ CMDLINE_SET="
     host_os
     install
     ld
+    ln_s
     logfile
     malloc_prefix
     nm
@@ -2241,8 +2286,9 @@ dirac_parse_select="golomb"
 error_resilience_select="me_cmp"
 faandct_deps="faan fdctdsp"
 faanidct_deps="faan idctdsp"
+h264dsp_select="startcode"
 frame_thread_encoder_deps="encoders threads"
-intrax8_select="error_resilience"
+intrax8_select="blockdsp idctdsp"
 mdct_select="fft"
 me_cmp_select="fdctdsp idctdsp pixblockdsp"
 mpeg_er_select="error_resilience"
@@ -2250,8 +2296,7 @@ mpegaudio_select="mpegaudiodsp"
 mpegaudiodsp_select="dct"
 mpegvideo_select="blockdsp h264chroma hpeldsp idctdsp me_cmp mpeg_er videodsp"
 mpegvideoenc_select="me_cmp mpegvideo pixblockdsp qpeldsp"
-qsvdec_select="qsv"
-qsvenc_select="qsv"
+vc1dsp_select="h264chroma qpeldsp startcode"
 rdft_select="fft"
 
 # decoders / encoders
@@ -2305,7 +2350,7 @@ eac3_decoder_select="ac3_decoder"
 eac3_encoder_select="ac3_encoder"
 eamad_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpegvideo"
 eatgq_decoder_select="aandcttables"
-eatqi_decoder_select="aandcttables blockdsp bswapdsp idctdsp mpeg1video_decoder"
+eatqi_decoder_select="aandcttables blockdsp bswapdsp idctdsp"
 exr_decoder_select="zlib"
 ffv1_decoder_select="golomb rangecoder"
 ffv1_encoder_select="rangecoder"
@@ -2331,20 +2376,12 @@ h263_encoder_select="aandcttables h263dsp mpegvideoenc"
 h263i_decoder_select="h263_decoder"
 h263p_decoder_select="h263_decoder"
 h263p_encoder_select="h263_encoder"
-h264_decoder_select="cabac golomb h264chroma h264dsp h264pred h264qpel startcode videodsp"
+h264_decoder_select="cabac golomb h264chroma h264dsp h264pred h264qpel videodsp"
 h264_decoder_suggest="error_resilience"
-h264_qsv_decoder_deps="libmfx"
-h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec h264_qsv_hwaccel"
-h264_qsv_encoder_deps="libmfx"
-h264_qsv_encoder_select="qsvenc"
 hap_decoder_select="snappy texturedsp"
 hap_encoder_deps="libsnappy"
 hap_encoder_select="texturedspenc"
 hevc_decoder_select="bswapdsp cabac golomb videodsp"
-hevc_qsv_decoder_deps="libmfx"
-hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec hevc_qsv_hwaccel"
-hevc_qsv_encoder_deps="libmfx"
-hevc_qsv_encoder_select="qsvenc"
 huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp"
 huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llviddsp"
 iac_decoder_select="imc_decoder"
@@ -2359,12 +2396,15 @@ jv_decoder_select="blockdsp"
 lagarith_decoder_select="huffyuvdsp"
 ljpeg_encoder_select="aandcttables idctdsp jpegtables"
 loco_decoder_select="golomb"
+magicyuv_decoder_select="huffyuvdsp"
 mdec_decoder_select="blockdsp idctdsp mpegvideo"
 metasound_decoder_select="lsp mdct sinewin"
 mimic_decoder_select="blockdsp bswapdsp hpeldsp idctdsp"
 mjpeg_decoder_select="blockdsp hpeldsp exif idctdsp jpegtables"
 mjpeg_encoder_select="aandcttables jpegtables mpegvideoenc"
 mjpegb_decoder_select="mjpeg_decoder"
+mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG"
+mjpeg_vaapi_encoder_select="vaapi_encode jpegtables"
 mlp_decoder_select="mlp_parser"
 motionpixels_decoder_select="bswapdsp"
 mp1_decoder_select="mpegaudio"
@@ -2386,10 +2426,6 @@ mpeg1video_decoder_select="mpegvideo"
 mpeg1video_encoder_select="aandcttables mpegvideoenc h263dsp"
 mpeg2video_decoder_select="mpegvideo"
 mpeg2video_encoder_select="aandcttables mpegvideoenc h263dsp"
-mpeg2_qsv_decoder_deps="libmfx"
-mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel"
-mpeg2_qsv_encoder_deps="libmfx"
-mpeg2_qsv_encoder_select="qsvenc"
 mpeg4_decoder_select="h263_decoder mpeg4video_parser"
 mpeg4_encoder_select="h263_encoder"
 msa1_decoder_select="mss34dsp"
@@ -2398,7 +2434,7 @@ msmpeg4v2_decoder_select="h263_decoder"
 msmpeg4v2_encoder_select="h263_encoder"
 msmpeg4v3_decoder_select="h263_decoder"
 msmpeg4v3_encoder_select="h263_encoder"
-mss2_decoder_select="vc1_decoder"
+mss2_decoder_select="vc1_decoder mpegvideo"
 mts2_decoder_select="mss34dsp"
 mxpeg_decoder_select="mjpeg_decoder"
 nellymoser_decoder_select="mdct sinewin"
@@ -2436,7 +2472,7 @@ sonic_ls_encoder_select="golomb rangecoder"
 sp5x_decoder_select="mjpeg_decoder"
 svq1_decoder_select="hpeldsp"
 svq1_encoder_select="aandcttables hpeldsp me_cmp mpegvideoenc"
-svq3_decoder_select="h264_decoder hpeldsp tpeldsp"
+svq3_decoder_select="golomb h264dsp h264pred hpeldsp tpeldsp videodsp"
 svq3_decoder_suggest="zlib"
 tak_decoder_select="audiodsp"
 tdsc_decoder_select="zlib mjpeg_decoder"
@@ -2453,7 +2489,7 @@ txd_decoder_select="texturedsp"
 utvideo_decoder_select="bswapdsp"
 utvideo_encoder_select="bswapdsp huffman huffyuvencdsp"
 vble_decoder_select="huffyuvdsp"
-vc1_decoder_select="blockdsp h263_decoder h264qpel intrax8 qpeldsp startcode"
+vc1_decoder_select="blockdsp h263_decoder h264qpel intrax8 mpegvideo vc1dsp"
 vc1_qsv_decoder_deps="libmfx"
 vc1_qsv_decoder_select="qsvdec vc1_qsv_hwaccel"
 vc1image_decoder_select="vc1_decoder"
@@ -2477,7 +2513,7 @@ wmav2_encoder_select="mdct sinewin wma_freqs"
 wmavoice_decoder_select="lsp rdft dct mdct sinewin"
 wmv1_decoder_select="h263_decoder"
 wmv1_encoder_select="h263_encoder"
-wmv2_decoder_select="blockdsp h263_decoder idctdsp intrax8 videodsp wmv2dsp"
+wmv2_decoder_select="blockdsp error_resilience h263_decoder idctdsp intrax8 videodsp wmv2dsp"
 wmv2_encoder_select="h263_encoder wmv2dsp"
 wmv3_decoder_select="vc1_decoder"
 wmv3image_decoder_select="wmv3_decoder"
@@ -2489,16 +2525,23 @@ zlib_encoder_select="zlib"
 zmbv_decoder_select="zlib"
 zmbv_encoder_select="zlib"
 
+# platform codecs
+audiotoolbox_deps="AudioToolbox_AudioToolbox_h"
+audiotoolbox_extralibs="-framework CoreFoundation -framework AudioToolbox -framework CoreMedia"
+
 # hardware accelerators
 crystalhd_deps="libcrystalhd_libcrystalhd_if_h"
+cuvid_deps="cuda"
 d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder ID3D11VideoContext"
 dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode"
 vaapi_deps="va_va_h"
-vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads"
-vda_extralibs="-framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore"
+vda_framework_deps="VideoDecodeAcceleration_VDADecoder_h"
+vda_framework_extralibs="-framework VideoDecodeAcceleration"
+vda_deps="vda_framework pthreads"
+vda_extralibs="-framework CoreFoundation -framework QuartzCore"
 vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h"
-videotoolbox_deps="VideoToolbox_VideoToolbox_h pthreads"
-videotoolbox_extralibs="-framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework QuartzCore -framework CoreVideo"
+videotoolbox_hwaccel_deps="videotoolbox pthreads"
+videotoolbox_hwaccel_extralibs="-framework QuartzCore"
 xvmc_deps="X11_extensions_XvMClib_h"
 
 h263_vaapi_hwaccel_deps="vaapi"
@@ -2506,13 +2549,17 @@ h263_vaapi_hwaccel_select="h263_decoder"
 h263_videotoolbox_hwaccel_deps="videotoolbox"
 h263_videotoolbox_hwaccel_select="h263_decoder"
 h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
+h264_cuvid_hwaccel_deps="cuda cuvid CUVIDH264PICPARAMS"
 h264_d3d11va_hwaccel_deps="d3d11va"
 h264_d3d11va_hwaccel_select="h264_decoder"
 h264_dxva2_hwaccel_deps="dxva2"
 h264_dxva2_hwaccel_select="h264_decoder"
+h264_mediacodec_decoder_deps="mediacodec"
+h264_mediacodec_decoder_select="h264_mp4toannexb_bsf h264_parser"
 h264_mmal_decoder_deps="mmal"
 h264_mmal_decoder_select="mmal"
 h264_mmal_hwaccel_deps="mmal"
+h264_omx_encoder_deps="omx"
 h264_qsv_hwaccel_deps="libmfx"
 h264_vaapi_hwaccel_deps="vaapi"
 h264_vaapi_hwaccel_select="h264_decoder"
@@ -2528,6 +2575,7 @@ h264_vdpau_hwaccel_deps="vdpau"
 h264_vdpau_hwaccel_select="h264_decoder"
 h264_videotoolbox_hwaccel_deps="videotoolbox"
 h264_videotoolbox_hwaccel_select="h264_decoder"
+hevc_cuvid_hwaccel_deps="cuda cuvid CUVIDHEVCPICPARAMS"
 hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC"
 hevc_d3d11va_hwaccel_select="hevc_decoder"
 hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
@@ -2571,6 +2619,7 @@ mpeg4_crystalhd_decoder_select="crystalhd"
 mpeg4_mmal_decoder_deps="mmal"
 mpeg4_mmal_decoder_select="mmal"
 mpeg4_mmal_hwaccel_deps="mmal"
+mpeg4_omx_encoder_deps="omx"
 mpeg4_vaapi_hwaccel_deps="vaapi"
 mpeg4_vaapi_hwaccel_select="mpeg4_decoder"
 mpeg4_vdpau_decoder_deps="vdpau"
@@ -2581,6 +2630,7 @@ mpeg4_videotoolbox_hwaccel_deps="videotoolbox"
 mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder"
 msmpeg4_crystalhd_decoder_select="crystalhd"
 vc1_crystalhd_decoder_select="crystalhd"
+vc1_cuvid_hwaccel_deps="cuda cuvid CUVIDVC1PICPARAMS"
 vc1_d3d11va_hwaccel_deps="d3d11va"
 vc1_d3d11va_hwaccel_select="vc1_decoder"
 vc1_dxva2_hwaccel_deps="dxva2"
@@ -2596,6 +2646,8 @@ vc1_vdpau_decoder_deps="vdpau"
 vc1_vdpau_decoder_select="vc1_decoder"
 vc1_vdpau_hwaccel_deps="vdpau"
 vc1_vdpau_hwaccel_select="vc1_decoder"
+vp8_cuvid_hwaccel_deps="cuda cuvid CUVIDVP9PICPARAMS"
+vp9_cuvid_hwaccel_deps="cuda cuvid CUVIDVP9PICPARAMS"
 vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9"
 vp9_d3d11va_hwaccel_select="vp9_decoder"
 vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9"
@@ -2609,20 +2661,91 @@ wmv3_vaapi_hwaccel_select="vc1_vaapi_hwaccel"
 wmv3_vdpau_decoder_select="vc1_vdpau_decoder"
 wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel"
 
+# hardware-accelerated codecs
+omx_deps="dlopen pthreads"
+omx_extralibs='$ldl'
+qsvdec_select="qsv"
+qsvenc_select="qsv"
+vaapi_encode_deps="vaapi"
+
+hwupload_cuda_filter_deps="cuda"
+scale_npp_filter_deps="cuda libnpp"
+
+nvenc_encoder_deps="nvenc"
+h264_cuvid_decoder_deps="cuda cuvid CUVIDH264PICPARAMS"
+h264_cuvid_decoder_select="h264_mp4toannexb_bsf h264_cuvid_hwaccel"
+h264_nvenc_encoder_deps="nvenc"
+h264_qsv_decoder_deps="libmfx"
+h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec h264_qsv_hwaccel"
+h264_qsv_encoder_deps="libmfx"
+h264_qsv_encoder_select="qsvenc"
+h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264"
+h264_vaapi_encoder_select="vaapi_encode golomb"
+
+hevc_cuvid_decoder_deps="cuda cuvid CUVIDHEVCPICPARAMS"
+hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf hevc_cuvid_hwaccel"
+hevc_nvenc_encoder_deps="nvenc"
+hevc_qsv_decoder_deps="libmfx"
+hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec hevc_qsv_hwaccel"
+hevc_qsv_encoder_deps="libmfx"
+hevc_qsv_encoder_select="qsvenc"
+hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC"
+hevc_vaapi_encoder_select="vaapi_encode golomb"
+mpeg2_qsv_decoder_deps="libmfx"
+mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel"
+mpeg2_qsv_encoder_deps="libmfx"
+mpeg2_qsv_encoder_select="qsvenc"
+nvenc_h264_encoder_deps="nvenc"
+nvenc_hevc_encoder_deps="nvenc"
+
+vc1_cuvid_decoder_deps="cuda cuvid CUVIDVC1PICPARAMS"
+vc1_cuvid_decoder_select="vc1_cuvid_hwaccel"
+vp8_cuvid_decoder_deps="cuda cuvid CUVIDVP9PICPARAMS"
+vp8_cuvid_decoder_select="vp8_cuvid_hwaccel"
+vp9_cuvid_decoder_deps="cuda cuvid CUVIDVP9PICPARAMS"
+vp9_cuvid_decoder_select="vp9_cuvid_hwaccel"
+
 # parsers
-h264_parser_select="h264_decoder"
+h264_parser_select="golomb h264dsp"
 hevc_parser_select="golomb"
 mpegvideo_parser_select="mpegvideo"
 mpeg4video_parser_select="h263dsp mpegvideo qpeldsp"
-vc1_parser_select="mpegvideo startcode vc1_decoder"
+vc1_parser_select="vc1dsp"
 
 # bitstream_filters
 mjpeg2jpeg_bsf_select="jpegtables"
 
 # external libraries
+aac_at_decoder_deps="audiotoolbox"
+ac3_at_decoder_deps="audiotoolbox"
+ac3_at_decoder_select="ac3_parser"
+adpcm_ima_qt_at_decoder_deps="audiotoolbox"
+alac_at_decoder_deps="audiotoolbox"
+amr_nb_at_decoder_deps="audiotoolbox"
+eac3_at_decoder_deps="audiotoolbox"
+eac3_at_decoder_select="ac3_parser"
+gsm_ms_at_decoder_deps="audiotoolbox"
+ilbc_at_decoder_deps="audiotoolbox"
+mp1_at_decoder_deps="audiotoolbox"
+mp2_at_decoder_deps="audiotoolbox"
+mp3_at_decoder_deps="audiotoolbox"
+pcm_alaw_at_decoder_deps="audiotoolbox"
+pcm_mulaw_at_decoder_deps="audiotoolbox"
+qdmc_at_decoder_deps="audiotoolbox"
+qdm2_at_decoder_deps="audiotoolbox"
+aac_at_encoder_deps="audiotoolbox"
+aac_at_encoder_select="audio_frame_queue"
+alac_at_encoder_deps="audiotoolbox"
+alac_at_encoder_select="audio_frame_queue"
+ilbc_at_encoder_deps="audiotoolbox"
+ilbc_at_encoder_select="audio_frame_queue"
+pcm_alaw_at_encoder_deps="audiotoolbox"
+pcm_alaw_at_encoder_select="audio_frame_queue"
+pcm_mulaw_at_encoder_deps="audiotoolbox"
+pcm_mulaw_at_encoder_select="audio_frame_queue"
 chromaprint_muxer_deps="chromaprint"
+h264_videotoolbox_encoder_deps="videotoolbox_encoder pthreads"
 libcelt_decoder_deps="libcelt"
-libdcadec_decoder_deps="libdcadec"
 libfaac_encoder_deps="libfaac"
 libfaac_encoder_select="audio_frame_queue"
 libfdk_aac_decoder_deps="libfdk_aac"
@@ -2658,8 +2781,6 @@ libspeex_encoder_deps="libspeex"
 libspeex_encoder_select="audio_frame_queue"
 libtheora_encoder_deps="libtheora"
 libtwolame_encoder_deps="libtwolame"
-libutvideo_decoder_deps="libutvideo"
-libutvideo_encoder_deps="libutvideo"
 libvo_amrwbenc_encoder_deps="libvo_amrwbenc"
 libvorbis_decoder_deps="libvorbis"
 libvorbis_encoder_deps="libvorbis"
@@ -2673,15 +2794,17 @@ libwebp_encoder_deps="libwebp"
 libwebp_anim_encoder_deps="libwebp"
 libx262_encoder_deps="libx262"
 libx264_encoder_deps="libx264"
-libx264rgb_encoder_deps="libx264"
+libx264rgb_encoder_deps="libx264 x264_csp_bgr"
 libx264rgb_encoder_select="libx264_encoder"
 libx265_encoder_deps="libx265"
 libxavs_encoder_deps="libxavs"
 libxvid_encoder_deps="libxvid"
 libzvbi_teletext_decoder_deps="libzvbi"
-nvenc_encoder_deps="nvenc"
-nvenc_h264_encoder_deps="nvenc"
-nvenc_hevc_encoder_deps="nvenc"
+videotoolbox_deps="VideoToolbox_VideoToolbox_h"
+videotoolbox_extralibs="-framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework CoreVideo"
+videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrames"
+videotoolbox_encoder_suggest="vda_framework vt_bt2020"
+vt_bt2020_deps="kCVImageBufferColorPrimaries_ITU_R_2020"
 
 # demuxers / muxers
 ac3_demuxer_select="ac3_parser"
@@ -2689,11 +2812,11 @@ asf_demuxer_select="riffdec"
 asf_o_demuxer_select="riffdec"
 asf_muxer_select="riffenc"
 asf_stream_muxer_select="asf_muxer"
-avi_demuxer_select="riffdec exif"
+avi_demuxer_select="iso_media riffdec exif"
 avi_muxer_select="riffenc"
 avisynth_demuxer_deps="avisynth"
 avisynth_demuxer_select="riffdec"
-caf_demuxer_select="riffdec"
+caf_demuxer_select="iso_media riffdec"
 dash_muxer_select="mp4_muxer"
 dirac_demuxer_select="dirac_parser"
 dts_demuxer_select="dca_parser"
@@ -2713,15 +2836,16 @@ ismv_muxer_select="mov_muxer"
 libnut_demuxer_deps="libnut"
 libnut_muxer_deps="libnut"
 matroska_audio_muxer_select="matroska_muxer"
-matroska_demuxer_select="riffdec"
+matroska_demuxer_select="iso_media riffdec"
 matroska_demuxer_suggest="bzlib lzo zlib"
-matroska_muxer_select="riffenc"
+matroska_muxer_select="iso_media riffenc"
 mmf_muxer_select="riffenc"
-mov_demuxer_select="riffdec"
+mov_demuxer_select="iso_media riffdec"
 mov_demuxer_suggest="zlib"
-mov_muxer_select="riffenc rtpenc_chain"
+mov_muxer_select="iso_media riffenc rtpenc_chain"
 mp3_demuxer_select="mpegaudio_parser"
 mp4_muxer_select="mov_muxer"
+mpegts_demuxer_select="iso_media"
 mpegts_muxer_select="adts_muxer latm_muxer"
 mpegtsraw_demuxer_select="mpegts_demuxer"
 mxf_d10_muxer_select="mxf_muxer"
@@ -2733,7 +2857,7 @@ ogg_demuxer_select="dirac_parse"
 opus_muxer_select="ogg_muxer"
 psp_muxer_select="mov_muxer"
 rtp_demuxer_select="sdp_demuxer"
-rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol"
+rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp"
 rtsp_demuxer_select="http_protocol rtpdec"
 rtsp_muxer_select="rtp_muxer http_protocol rtp_protocol rtpenc_chain"
 sap_demuxer_select="sdp_demuxer"
@@ -2751,9 +2875,10 @@ w64_demuxer_select="wav_demuxer"
 w64_muxer_select="wav_muxer"
 wav_demuxer_select="riffdec"
 wav_muxer_select="riffenc"
-webm_muxer_select="riffenc"
-wtv_demuxer_select="riffdec"
-wtv_muxer_select="riffenc"
+webm_muxer_select="iso_media riffenc"
+webm_dash_manifest_demuxer_select="matroska_demuxer"
+wtv_demuxer_select="mpegts_demuxer riffdec"
+wtv_muxer_select="mpegts_muxer riffenc"
 xmv_demuxer_select="riffdec"
 xwma_demuxer_select="riffdec"
 
@@ -2778,7 +2903,8 @@ gdigrab_indev_deps="CreateDIBSection"
 gdigrab_indev_extralibs="-lgdi32"
 gdigrab_indev_select="bmp_decoder"
 iec61883_indev_deps="libiec61883"
-jack_indev_deps="jack_jack_h sem_timedwait"
+jack_indev_deps="jack_jack_h"
+jack_indev_deps_any="sem_timedwait dispatch_dispatch_h"
 lavfi_indev_deps="avfilter"
 libcdio_indev_deps="libcdio"
 libdc1394_indev_deps="libdc1394"
@@ -2836,9 +2962,9 @@ rtmpt_protocol_select="ffrtmphttp_protocol"
 rtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol"
 rtmpts_protocol_select="ffrtmphttp_protocol https_protocol"
 rtp_protocol_select="udp_protocol"
-sctp_protocol_deps="struct_sctp_event_subscribe"
+sctp_protocol_deps="struct_sctp_event_subscribe struct_msghdr_msg_flags"
 sctp_protocol_select="network"
-srtp_protocol_select="rtp_protocol"
+srtp_protocol_select="rtp_protocol srtp"
 tcp_protocol_select="network"
 tls_gnutls_protocol_deps="gnutls !tls_schannel_protocol !tls_securetransport_protocol"
 tls_gnutls_protocol_select="tcp_protocol"
@@ -2878,7 +3004,10 @@ eq_filter_deps="gpl"
 fftfilt_filter_deps="avcodec"
 fftfilt_filter_select="rdft"
 find_rect_filter_deps="avcodec avformat gpl"
+firequalizer_filter_deps="avcodec"
+firequalizer_filter_select="rdft"
 flite_filter_deps="libflite"
+framerate_filter_select="pixelutils"
 frei0r_filter_deps="frei0r dlopen"
 frei0r_src_filter_deps="frei0r dlopen"
 fspp_filter_deps="gpl"
@@ -2888,6 +3017,7 @@ hqdn3d_filter_deps="gpl"
 interlace_filter_deps="gpl"
 kerndeint_filter_deps="gpl"
 ladspa_filter_deps="ladspa dlopen"
+loudnorm_filter_deps="libebur128"
 mcdeint_filter_deps="avcodec gpl"
 movie_filter_deps="avcodec avformat"
 mpdecimate_filter_deps="gpl"
@@ -2940,6 +3070,7 @@ vidstabtransform_filter_deps="libvidstab"
 zmq_filter_deps="libzmq"
 zoompan_filter_deps="swscale"
 zscale_filter_deps="libzimg"
+scale_vaapi_filter_deps="vaapi VAProcPipelineParameterBuffer"
 
 # examples
 avcodec_example_deps="avcodec avutil"
@@ -3011,7 +3142,7 @@ host_cc_default="gcc"
 cp_f="cp -f"
 doxygen_default="doxygen"
 install="install"
-ln_s="ln -s -f"
+ln_s_default="ln -s -f"
 nm_default="nm -g"
 objformat="elf"
 pkg_config_default=pkg-config
@@ -3055,10 +3186,15 @@ enable valgrind_backtrace
 sws_max_filter_size_default=256
 set_default sws_max_filter_size
 
+# Enable platform codecs by default.
+enable audiotoolbox
+
 # Enable hwaccels by default.
-enable d3d11va dxva2 vaapi vda vdpau videotoolbox xvmc
+enable d3d11va dxva2 vaapi vda vdpau videotoolbox_hwaccel xvmc
 enable xlib
 
+enable vda_framework videotoolbox videotoolbox_encoder
+
 # build settings
 SHFLAGS='-shared -Wl,-soname,$$(@F)'
 LIBPREF="lib"
@@ -3137,14 +3273,22 @@ ENCODER_LIST=$(find_things  encoder  ENC      libavcodec/allcodecs.c)
 DECODER_LIST=$(find_things  decoder  DEC      libavcodec/allcodecs.c)
 HWACCEL_LIST=$(find_things  hwaccel  HWACCEL  libavcodec/allcodecs.c)
 PARSER_LIST=$(find_things   parser   PARSER   libavcodec/allcodecs.c)
-BSF_LIST=$(find_things      bsf      BSF      libavcodec/allcodecs.c)
 MUXER_LIST=$(find_things    muxer    _MUX     libavformat/allformats.c)
 DEMUXER_LIST=$(find_things  demuxer  DEMUX    libavformat/allformats.c)
 OUTDEV_LIST=$(find_things   outdev   OUTDEV   libavdevice/alldevices.c)
 INDEV_LIST=$(find_things    indev    _IN      libavdevice/alldevices.c)
-PROTOCOL_LIST=$(find_things protocol PROTOCOL libavformat/allformats.c)
 FILTER_LIST=$(find_things   filter   FILTER   libavfilter/allfilters.c)
 
+find_things_extern(){
+    thing=$1
+    pattern=$2
+    file=$source_path/$3
+    sed -n "s/^[^#]*extern.*$pattern *ff_\([^ ]*\)_$thing;/\1_$thing/p" "$file"
+}
+
+BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c)
+PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c)
+
 ALL_COMPONENTS="
     $BSF_LIST
     $DECODER_LIST
@@ -3315,43 +3459,42 @@ set >> $logfile
 test -n "$valgrind" && toolchain="valgrind-memcheck"
 
 case "$toolchain" in
-    clang-asan)
-        cc_default="clang"
+    *-asan)
+        cc_default="${toolchain%-asan}"
         add_cflags  -fsanitize=address
         add_ldflags -fsanitize=address
     ;;
-    clang-tsan)
-        cc_default="clang"
+    *-msan)
+        cc_default="${toolchain%-msan}"
+        add_cflags  -fsanitize=memory -fsanitize-memory-track-origins
+        add_ldflags -fsanitize=memory
+    ;;
+    *-tsan)
+        cc_default="${toolchain%-tsan}"
         add_cflags  -fsanitize=thread -pie
         add_ldflags -fsanitize=thread -pie
+        case "$toolchain" in
+            gcc-tsan)
+                add_cflags  -fPIC
+                add_ldflags -fPIC
+                ;;
+        esac
     ;;
-    clang-usan)
-        cc_default="clang"
-        add_cflags  -fsanitize=undefined
-        add_ldflags -fsanitize=undefined
-    ;;
-    gcc-asan)
-        cc_default="gcc"
-        add_cflags  -fsanitize=address
-        add_ldflags -fsanitize=address
-    ;;
-    gcc-tsan)
-        cc_default="gcc"
-        add_cflags  -fsanitize=thread -pie -fPIC
-        add_ldflags -fsanitize=thread -pie -fPIC
-    ;;
-    gcc-usan)
-        cc_default="gcc"
+    *-usan)
+        cc_default="${toolchain%-usan}"
         add_cflags  -fsanitize=undefined
         add_ldflags -fsanitize=undefined
     ;;
-    valgrind-massif)
-        target_exec_default=${valgrind:-"valgrind"}
-        target_exec_args="--tool=massif --alloc-fn=av_malloc --alloc-fn=av_mallocz --alloc-fn=av_calloc --alloc-fn=av_fast_padded_malloc --alloc-fn=av_fast_malloc --alloc-fn=av_realloc_f --alloc-fn=av_fast_realloc --alloc-fn=av_realloc"
-    ;;
-    valgrind-memcheck)
-        target_exec_default=${valgrind:-"valgrind"}
-        target_exec_args="--error-exitcode=1 --malloc-fill=0x2a --track-origins=yes --leak-check=full --gen-suppressions=all --suppressions=$source_path/tests/fate-valgrind.supp"
+    valgrind-*)
+        target_exec_default="valgrind"
+        case "$toolchain" in
+            valgrind-massif)
+                target_exec_args="--tool=massif --alloc-fn=av_malloc --alloc-fn=av_mallocz --alloc-fn=av_calloc --alloc-fn=av_fast_padded_malloc --alloc-fn=av_fast_malloc --alloc-fn=av_realloc_f --alloc-fn=av_fast_realloc --alloc-fn=av_realloc"
+                ;;
+            valgrind-memcheck)
+                target_exec_args="--error-exitcode=1 --malloc-fill=0x2a --track-origins=yes --leak-check=full --gen-suppressions=all --suppressions=$source_path/tests/fate-valgrind.supp"
+                ;;
+        esac
     ;;
     msvc)
         # Check whether the current MSVC version needs the C99 converter.
@@ -3393,6 +3536,10 @@ case "$toolchain" in
         add_cflags  -fprofile-arcs -ftest-coverage
         add_ldflags -fprofile-arcs -ftest-coverage
     ;;
+    llvm-cov)
+        add_cflags -fprofile-arcs -ftest-coverage
+        add_ldflags --coverage
+    ;;
     hardened)
         add_cppflags -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2
         add_cflags   -fno-strict-overflow -fstack-protector-all
@@ -3918,7 +4065,7 @@ test -n "$cc_type" && enable $cc_type ||
 : ${dep_cc_default:=$cc}
 : ${ld_default:=$cc}
 : ${host_ld_default:=$host_cc}
-set_default ar as objcc dep_cc ld host_ld windres
+set_default ar as objcc dep_cc ld ln_s host_ld windres
 
 probe_cc as "$as"
 asflags_filter=$_flags_filter
@@ -4093,26 +4240,26 @@ elif enabled arm; then
     }
 
     probe_arm_arch() {
-        if   check_arm_arch 4;        then echo armv4;
-        elif check_arm_arch 4T;       then echo armv4t;
-        elif check_arm_arch 5;        then echo armv5;
-        elif check_arm_arch 5E;       then echo armv5e;
-        elif check_arm_arch 5T;       then echo armv5t;
-        elif check_arm_arch 5TE;      then echo armv5te;
-        elif check_arm_arch 5TEJ;     then echo armv5te;
-        elif check_arm_arch 6;        then echo armv6;
-        elif check_arm_arch 6J;       then echo armv6j;
-        elif check_arm_arch 6K;       then echo armv6k;
-        elif check_arm_arch 6Z;       then echo armv6z;
-        elif check_arm_arch 6ZK;      then echo armv6zk;
-        elif check_arm_arch 6T2;      then echo armv6t2;
-        elif check_arm_arch 7;        then echo armv7;
-        elif check_arm_arch 7A  7_A;  then echo armv7-a;
-        elif check_arm_arch 7S;       then echo armv7-a;
-        elif check_arm_arch 7R  7_R;  then echo armv7-r;
-        elif check_arm_arch 7M  7_M;  then echo armv7-m;
-        elif check_arm_arch 7EM 7E_M; then echo armv7-m;
-        elif check_arm_arch 8A  8_A;  then echo armv8-a;
+        if   check_arm_arch 4;        then echo armv4
+        elif check_arm_arch 4T;       then echo armv4t
+        elif check_arm_arch 5;        then echo armv5
+        elif check_arm_arch 5E;       then echo armv5e
+        elif check_arm_arch 5T;       then echo armv5t
+        elif check_arm_arch 5TE;      then echo armv5te
+        elif check_arm_arch 5TEJ;     then echo armv5te
+        elif check_arm_arch 6;        then echo armv6
+        elif check_arm_arch 6J;       then echo armv6j
+        elif check_arm_arch 6K;       then echo armv6k
+        elif check_arm_arch 6Z;       then echo armv6z
+        elif check_arm_arch 6ZK;      then echo armv6zk
+        elif check_arm_arch 6T2;      then echo armv6t2
+        elif check_arm_arch 7;        then echo armv7
+        elif check_arm_arch 7A  7_A;  then echo armv7-a
+        elif check_arm_arch 7S;       then echo armv7-a
+        elif check_arm_arch 7R  7_R;  then echo armv7-r
+        elif check_arm_arch 7M  7_M;  then echo armv7-m
+        elif check_arm_arch 7EM 7E_M; then echo armv7-m
+        elif check_arm_arch 8A  8_A;  then echo armv8-a
         fi
     }
 
@@ -4382,6 +4529,7 @@ fi
 
 add_cppflags -D_ISOC99_SOURCE
 add_cxxflags -D__STDC_CONSTANT_MACROS
+add_cxxflags -std=c++98
 check_cflags -std=c99
 check_cc -D_FILE_OFFSET_BITS=64 <<EOF && add_cppflags -D_FILE_OFFSET_BITS=64
 #include <stdlib.h>
@@ -4506,7 +4654,8 @@ case $target_os in
         ;;
     darwin)
         enabled ppc && add_asflags -force_cpusubtype_ALL
-        SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(SHLIBDIR)/$(SLIBNAME_WITH_MAJOR),-current_version,$(LIBVERSION),-compatibility_version,$(LIBMAJOR)'
+        install_name_dir_default='$(SHLIBDIR)'
+        SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(INSTALL_NAME_DIR)/$(SLIBNAME_WITH_MAJOR),-current_version,$(LIBVERSION),-compatibility_version,$(LIBMAJOR)'
         enabled x86_32 && append SHFLAGS -Wl,-read_only_relocs,suppress
         strip="${strip} -x"
         add_ldflags -Wl,-dynamic,-search_paths_first
@@ -4517,9 +4666,11 @@ case $target_os in
         enabled x86_64 && objformat="macho64"
         enabled_any pic shared x86_64 ||
             { check_cflags -mdynamic-no-pic && add_asflags -mdynamic-no-pic; }
+        check_header dispatch/dispatch.h &&
+            add_cppflags '-I\$(SRC_PATH)/compat/dispatch_semaphore'
         ;;
     msys*)
-        die "Native MSYS builds are discouraged, please use the MINGW environment.";
+        die "Native MSYS builds are discouraged, please use the MINGW environment."
         ;;
     mingw32*|mingw64*)
         if test $target_os = "mingw32ce"; then
@@ -4566,9 +4717,9 @@ case $target_os in
         # however ld then forgets what the entry point should be (oops) so we
         # have to manually (re)set it.
         if enabled x86_32; then
-            add_ldexeflags -Wl,--pic-executable,-e,_mainCRTStartup
+            disabled debug && add_ldexeflags -Wl,--pic-executable,-e,_mainCRTStartup
         elif enabled x86_64; then
-            add_ldexeflags -Wl,--pic-executable,-e,mainCRTStartup
+            disabled debug && add_ldexeflags -Wl,--pic-executable,-e,mainCRTStartup
             check_ldflags -Wl,--high-entropy-va # binutils 2.25
             # Set image base >4GB for extra entropy with HEASLR
             add_ldexeflags -Wl,--image-base,0x140000000
@@ -4631,7 +4782,6 @@ case $target_os in
         ;;
     os/2*)
         strip="lxlite -CS"
-        ln_s="cp -f"
         objformat="aout"
         add_cppflags -D_GNU_SOURCE
         add_ldflags -Zomf -Zbin-files -Zargs-wild -Zmap
@@ -4639,16 +4789,18 @@ case $target_os in
         LIBSUF="_s.a"
         SLIBPREF=""
         SLIBSUF=".dll"
-        SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)'
-        SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(shell echo $(NAME) | cut -c1-6)$(LIBMAJOR)$(SLIBSUF)'
-        SLIB_CREATE_DEF_CMD='echo LIBRARY $(SLIBNAME_WITH_MAJOR) INITINSTANCE TERMINSTANCE > $(SUBDIR)$(NAME).def; \
-            echo CODE PRELOAD MOVEABLE DISCARDABLE >> $(SUBDIR)$(NAME).def; \
-            echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $(SUBDIR)$(NAME).def; \
-            echo EXPORTS >> $(SUBDIR)$(NAME).def; \
-            emxexp $(OBJS) >> $(SUBDIR)$(NAME).def'
-        SLIB_EXTRA_CMD='emximp -o $(SUBDIR)$(LIBPREF)$(NAME)_dll.a $(SUBDIR)$(NAME).def; \
-            emximp -o $(SUBDIR)$(LIBPREF)$(NAME)_dll.lib $(SUBDIR)$(NAME).def;'
-        SLIB_INSTALL_EXTRA_LIB='$(LIBPREF)$(NAME)_dll.a $(LIBPREF)$(NAME)_dll.lib'
+        SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)'
+        SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(shell echo $(FULLNAME) | cut -c1-6)$(LIBMAJOR)$(SLIBSUF)'
+        SLIB_CREATE_DEF_CMD='echo LIBRARY $(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=) INITINSTANCE TERMINSTANCE > $(SUBDIR)$(FULLNAME).def; \
+            echo CODE PRELOAD MOVEABLE DISCARDABLE >> $(SUBDIR)$(FULLNAME).def; \
+            echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $(SUBDIR)$(FULLNAME).def; \
+            echo EXPORTS >> $(SUBDIR)$(FULLNAME).def; \
+            emxexp $(OBJS) >> $(SUBDIR)$(FULLNAME).def'
+        SLIB_EXTRA_CMD='emximp -o $(SUBDIR)$(LIBPREF)$(FULLNAME)_dll.a $(SUBDIR)$(FULLNAME).def; \
+            emximp -o $(SUBDIR)$(LIBPREF)$(FULLNAME)_dll.lib $(SUBDIR)$(FULLNAME).def;'
+        SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
+        SLIB_INSTALL_LINKS=
+        SLIB_INSTALL_EXTRA_LIB='$(LIBPREF)$(FULLNAME)_dll.a $(LIBPREF)$(FULLNAME)_dll.lib'
         enable dos_paths
         enable_weak os2threads
         ;;
@@ -4853,7 +5005,7 @@ Specify --enable-static to build the static libraries or --enable-shared to
 build the shared libraries as well. To only build the shared libraries specify
 --disable-static in addition to --enable-shared.
 EOF
-    exit 1;
+    exit 1
 fi
 
 die_license_disabled() {
@@ -4868,7 +5020,6 @@ die_license_disabled gpl frei0r
 die_license_disabled gpl libcdio
 die_license_disabled gpl librubberband
 die_license_disabled gpl libsmbclient
-die_license_disabled gpl libutvideo
 die_license_disabled gpl libvidstab
 die_license_disabled gpl libx264
 die_license_disabled gpl libx265
@@ -4876,8 +5027,10 @@ die_license_disabled gpl libxavs
 die_license_disabled gpl libxvid
 die_license_disabled gpl x11grab
 
+die_license_disabled nonfree cuda
+die_license_disabled nonfree cuvid
 die_license_disabled nonfree libfaac
-die_license_disabled nonfree nvenc
+die_license_disabled nonfree libnpp
 enabled gpl && die_license_disabled_gpl nonfree libfdk_aac
 enabled gpl && die_license_disabled_gpl nonfree openssl
 
@@ -5215,6 +5368,8 @@ frei0r_filter_extralibs='$ldl'
 frei0r_src_filter_extralibs='$ldl'
 ladspa_filter_extralibs='$ldl'
 nvenc_encoder_extralibs='$ldl'
+coreimage_filter_extralibs="-framework QuartzCore -framework AppKit -framework OpenGL"
+coreimagesrc_filter_extralibs="-framework QuartzCore -framework AppKit -framework OpenGL"
 
 if ! disabled network; then
     check_func getaddrinfo $network_extralibs
@@ -5226,6 +5381,7 @@ if ! disabled network; then
     check_type netinet/in.h "struct ipv6_mreq" -D_DARWIN_C_SOURCE
     check_type poll.h "struct pollfd"
     check_type netinet/sctp.h "struct sctp_event_subscribe"
+    check_struct "sys/socket.h" "struct msghdr" msg_flags
     check_struct "sys/types.h sys/socket.h" "struct sockaddr" sa_len
     check_type netinet/in.h "struct sockaddr_in6"
     check_type "sys/types.h sys/socket.h" "struct sockaddr_storage"
@@ -5260,9 +5416,11 @@ check_builtin atomic_compare_exchange "" "int *ptr, *oldval; int newval; __atomi
 check_builtin machine_rw_barrier mbarrier.h "__machine_rw_barrier()"
 check_builtin MemoryBarrier windows.h "MemoryBarrier()"
 check_builtin sarestart signal.h "SA_RESTART"
+check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); sem_timedwait(s,0); sem_destroy(s)" -lpthread
 check_builtin sync_val_compare_and_swap "" "int *ptr; int oldval, newval; __sync_val_compare_and_swap(ptr, oldval, newval)"
 check_builtin gmtime_r time.h "time_t *time; struct tm *tm; gmtime_r(time, tm)"
 check_builtin localtime_r time.h "time_t *time; struct tm *tm; localtime_r(time, tm)"
+check_builtin x264_csp_bgr "stdint.h x264.h" "X264_CSP_BGR"
 
 case "$custom_allocator" in
     jemalloc)
@@ -5324,6 +5482,7 @@ check_func_headers glob.h glob
 enabled xlib &&
     check_func_headers "X11/Xlib.h X11/extensions/Xvlib.h" XvGetPortAttribute -lXv -lX11 -lXext
 
+check_header AudioToolbox/AudioToolbox.h
 check_header direct.h
 check_header dirent.h
 check_header dlfcn.h
@@ -5349,6 +5508,8 @@ check_header vdpau/vdpau.h
 check_header vdpau/vdpau_x11.h
 check_header VideoDecodeAcceleration/VDADecoder.h
 check_header VideoToolbox/VideoToolbox.h
+check_func_headers VideoToolbox/VTCompressionSession.h VTCompressionSessionPrepareToEncodeFrames -framework VideoToolbox
+enabled videotoolbox && check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferColorPrimaries_ITU_R_2020 -framework CoreVideo
 check_header windows.h
 check_header X11/extensions/XvMClib.h
 check_header asm/types.h
@@ -5368,9 +5529,18 @@ check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602
 
 check_type "va/va.h" "VAPictureParameterBufferHEVC"
 check_type "va/va.h" "VADecPictureParameterBufferVP9"
+check_type "va/va.h va/va_vpp.h" "VAProcPipelineParameterBuffer"
+check_type "va/va.h va/va_enc_h264.h" "VAEncPictureParameterBufferH264"
+check_type "va/va.h va/va_enc_hevc.h" "VAEncPictureParameterBufferHEVC"
+check_type "va/va.h va/va_enc_jpeg.h" "VAEncPictureParameterBufferJPEG"
 
 check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC"
 
+check_type "cuviddec.h" "CUVIDH264PICPARAMS"
+check_type "cuviddec.h" "CUVIDHEVCPICPARAMS"
+check_type "cuviddec.h" "CUVIDVC1PICPARAMS"
+check_type "cuviddec.h" "CUVIDVP9PICPARAMS"
+
 check_cpp_condition windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" && enable winrt || disable winrt
 
 if ! disabled w32threads && ! enabled pthreads; then
@@ -5410,6 +5580,9 @@ if enabled pthreads; then
   check_func pthread_cancel
 fi
 
+enabled pthreads &&
+    check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); sem_timedwait(s,0); sem_destroy(s)"
+
 disabled  zlib || check_lib   zlib.h      zlibVersion -lz   || disable  zlib
 disabled bzlib || check_lib2 bzlib.h BZ2_bzlibVersion -lbz2 || disable bzlib
 disabled  lzma || check_lib2  lzma.h lzma_version_number -llzma || disable lzma
@@ -5431,6 +5604,11 @@ for func in $COMPLEX_FUNCS; do
     eval check_complexfunc $func \${${func}_args:-1}
 done
 
+# Enable CUVID by default if CUDA is enabled
+if enabled cuda && ! disabled cuvid; then
+    enable cuvid
+fi
+
 # these are off by default, so fail if requested and not available
 enabled avfoundation_indev && { check_header_objcc AVFoundation/AVFoundation.h || disable avfoundation_indev; }
 enabled avfoundation_indev && { check_lib2 CoreGraphics/CoreGraphics.h CGGetActiveDisplayList -framework CoreGraphics ||
@@ -5438,11 +5616,21 @@ enabled avfoundation_indev && { check_lib2 CoreGraphics/CoreGraphics.h CGGetActi
 enabled avisynth          && { { check_lib2 "windows.h" LoadLibrary; } ||
                                { check_lib2 "dlfcn.h" dlopen -ldl; } ||
                                die "ERROR: LoadLibrary/dlopen not found for avisynth"; }
+enabled cuda              && { check_lib cuda.h cuInit -lcuda ||
+                               die "ERROR: CUDA not found"; }
+enabled cuvid             && { check_lib cuviddec.h cuvidCreateDecoder -lnvcuvid ||
+                               die "ERROR: CUVID not found"; } &&
+                             { enabled cuda ||
+                               die "ERROR: CUVID requires CUDA"; }
 enabled chromaprint       && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint
+enabled coreimage_filter  && { check_header_objcc QuartzCore/CoreImage.h || disable coreimage_filter; }
+enabled coreimagesrc_filter && { check_header_objcc QuartzCore/CoreImage.h || disable coreimagesrc_filter; }
 enabled decklink          && { check_header DeckLinkAPI.h || die "ERROR: DeckLinkAPI.h header not found"; }
 enabled frei0r            && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; }
 enabled gmp               && require2 gmp gmp.h mpz_export -lgmp
 enabled gnutls            && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init
+enabled jni               && { [ $target_os = "android" ] && check_header jni.h && enabled pthreads &&
+                               check_lib2 "dlfcn.h" dlopen -ldl; }
 enabled ladspa            && { check_header ladspa.h || die "ERROR: ladspa.h header not found"; }
 enabled libiec61883       && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883
 enabled libass            && require_pkg_config libass ass/ass.h ass_library_init
@@ -5452,7 +5640,7 @@ enabled libcelt           && require libcelt celt/celt.h celt_decode -lcelt0 &&
                              { check_lib celt/celt.h celt_decoder_create_custom -lcelt0 ||
                                die "ERROR: libcelt must be installed and version must be >= 0.11.0."; }
 enabled libcaca           && require_pkg_config caca caca.h caca_create_canvas
-enabled libdcadec         && require_pkg_config "dcadec >= 0.1.0" libdcadec/dca_context.h dcadec_context_create
+enabled libebur128        && require ebur128 ebur128.h ebur128_relative_threshold -lebur128
 enabled libfaac           && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac
 enabled libfdk_aac        && { use_pkg_config fdk-aac "fdk-aac/aacenc_lib.h" aacEncOpen ||
                                { require libfdk_aac fdk-aac/aacenc_lib.h aacEncOpen -lfdk-aac &&
@@ -5473,10 +5661,12 @@ enabled libmfx            && require_pkg_config libmfx "mfx/mfxvideo.h" MFXInit
 enabled libmodplug        && require_pkg_config libmodplug libmodplug/modplug.h ModPlug_Load
 enabled libmp3lame        && require "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame
 enabled libnut            && require libnut libnut.h nut_demuxer_init -lnut
+enabled libnpp            && require libnpp npp.h nppGetLibVersion -lnppi -lnppc
 enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb
 enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb
 enabled libopencv         && { check_header opencv2/core/core_c.h &&
-                               require_pkg_config opencv opencv2/core/core_c.h cvCreateImageHeader ||
+                               { use_pkg_config opencv opencv2/core/core_c.h cvCreateImageHeader ||
+                                 require opencv opencv2/core/core_c.h cvCreateImageHeader -lopencv_core -lopencv_imgproc; } ||
                                require_pkg_config opencv opencv/cxcore.h cvCreateImageHeader; }
 enabled libopenh264       && require_pkg_config openh264 wels/codec_api.h WelsGetCodecVersion
 enabled libopenjpeg       && { check_lib openjpeg-2.1/openjpeg.h opj_version -lopenjp2 -DOPJ_STATIC ||
@@ -5501,7 +5691,6 @@ enabled libtheora         && require libtheora theora/theoraenc.h th_info_init -
 enabled libtwolame        && require libtwolame twolame.h twolame_init -ltwolame &&
                              { check_lib twolame.h twolame_encode_buffer_float32_interleaved -ltwolame ||
                                die "ERROR: libtwolame must be installed and version must be >= 0.3.10"; }
-enabled libutvideo        && require_cpp utvideo "stdint.h stdlib.h utvideo/utvideo.h utvideo/Codec.h" 'CCodec*' -lutvideo -lstdc++
 enabled libv4l2           && require_pkg_config libv4l2 libv4l2.h v4l2_ioctl
 enabled libvidstab        && require_pkg_config "vidstab >= 0.98" vid.stab/libvidstab.h vsMotionDetectInit
 enabled libvo_amrwbenc    && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc
@@ -5554,6 +5743,7 @@ enabled libzmq            && require_pkg_config libzmq zmq.h zmq_ctx_new
 enabled libzvbi           && require libzvbi libzvbi.h vbi_decoder_new -lzvbi &&
                              { check_cpp_condition libzvbi.h "VBI_VERSION_MAJOR > 0 || VBI_VERSION_MINOR > 2 || VBI_VERSION_MINOR == 2 && VBI_VERSION_MICRO >= 28" ||
                                enabled gpl || die "ERROR: libzvbi requires version 0.2.28 or --enable-gpl."; }
+enabled mediacodec        && { enabled jni || die "ERROR: mediacodec requires --enable-jni"; }
 enabled mmal              && { check_lib interface/mmal/mmal.h mmal_port_connect -lmmal_core -lmmal_util -lmmal_vc_client -lbcm_host ||
                                 { ! enabled cross_compile && {
                                     add_cflags -isystem/opt/vc/include/ -isystem/opt/vc/include/interface/vmcs_host/linux -isystem/opt/vc/include/interface/vcos/pthreads -fgnu89-inline ;
@@ -5561,14 +5751,12 @@ enabled mmal              && { check_lib interface/mmal/mmal.h mmal_port_connect
                                     check_lib interface/mmal/mmal.h mmal_port_connect ; }
                                 check_lib interface/mmal/mmal.h mmal_port_connect ; } ||
                                die "ERROR: mmal not found"; }
-enabled mmal &&
-    (check_code cc interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS" ||
-     die "ERROR: mmal firmware headers too old")
+enabled mmal && check_func_headers interface/mmal/mmal.h "MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS"
 
 enabled netcdf            && require_pkg_config netcdf netcdf.h nc_inq_libvers
 enabled nvenc             && { check_header nvEncodeAPI.h || die "ERROR: nvEncodeAPI.h not found."; } &&
-                             { check_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 5" ||
-                               die "ERROR: NVENC API version 4 or older is not supported"; } &&
+                             { check_cpp_condition nvEncodeAPI.h "NVENCAPI_MAJOR_VERSION >= 6" ||
+                               die "ERROR: NVENC API version 5 or older is not supported"; } &&
                              { [ $target_os != cygwin ] || die "ERROR: NVENC is not supported on Cygwin currently."; }
 enabled openal            && { { for al_libs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do
                                check_lib 'AL/al.h' alGetError "${al_libs}" && break; done } ||
@@ -5587,6 +5775,12 @@ enabled opengl            && { check_lib GL/glx.h glXGetProcAddress "-lGL" ||
                                check_lib2 ES2/gl.h glGetError "-isysroot=${sysroot} -Wl,-framework,OpenGLES" ||
                                die "ERROR: opengl not found."
                              }
+enabled omx_rpi && enable omx
+enabled omx               && { check_header OMX_Core.h ||
+                                { ! enabled cross_compile && enabled omx_rpi && {
+                                    add_cflags -isystem/opt/vc/include/IL ; }
+                                check_header OMX_Core.h ; } ||
+                               die "ERROR: OpenMAX IL headers not found"; }
 enabled openssl           && { use_pkg_config openssl openssl/ssl.h SSL_library_init ||
                                check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto ||
                                check_lib openssl/ssl.h SSL_library_init -lssl32 -leay32 ||
@@ -5646,8 +5840,8 @@ disabled securetransport || { check_func SecIdentityCreate "-Wl,-framework,CoreF
     check_lib2 "Security/SecureTransport.h Security/Security.h" "SSLCreateContext SecItemImport" "-Wl,-framework,CoreFoundation -Wl,-framework,Security" &&
     enable securetransport; }
 
-disabled schannel || { check_func_headers "windows.h Security.h" InitializeSecurityContext -DSECURITY_WIN32 -lSecur32 &&
-                       check_cpp_condition winerror.h "defined(SEC_I_CONTEXT_EXPIRED)" && enable schannel && add_extralibs -lSecur32; }
+disabled schannel || { check_func_headers "windows.h security.h" InitializeSecurityContext -DSECURITY_WIN32 -lsecur32 &&
+                       check_cpp_condition winerror.h "defined(SEC_I_CONTEXT_EXPIRED)" && enable schannel && add_extralibs -lsecur32; }
 
 makeinfo --version > /dev/null 2>&1 && enable makeinfo  || disable makeinfo
 enabled makeinfo \
@@ -5696,7 +5890,7 @@ check_header soundcard.h
 enabled_any alsa_indev alsa_outdev &&
     check_lib2 alsa/asoundlib.h snd_pcm_htimestamp -lasound
 
-enabled jack_indev && check_lib2 jack/jack.h jack_client_open -ljack && check_func sem_timedwait &&
+enabled jack_indev && check_lib2 jack/jack.h jack_client_open -ljack &&
     check_func jack_port_get_latency_range -ljack
 
 enabled_any sndio_indev sndio_outdev && check_lib2 sndio.h sio_open -lsndio
@@ -5758,17 +5952,25 @@ enabled vaapi &&
     check_lib va/va.h vaInitialize -lva ||
     disable vaapi
 
-enabled vaapi && enabled xlib &&
+enabled vaapi &&
+    check_code cc "va/va.h" "vaCreateSurfaces(0, 0, 0, 0, 0, 0, 0, 0)" ||
+    disable vaapi
+
+if enabled vaapi ; then
+    enabled xlib &&
     check_lib2 "va/va.h va/va_x11.h" vaGetDisplay -lva -lva-x11 &&
     enable vaapi_x11
 
+    check_lib2 "va/va.h va/va_drm.h" vaGetDisplayDRM -lva -lva-drm &&
+    enable vaapi_drm
+fi
+
 enabled vdpau &&
     check_cpp_condition vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" ||
     disable vdpau
 
 enabled vdpau && enabled xlib &&
-    check_func_headers "vdpau/vdpau.h vdpau/vdpau_x11.h" vdp_device_create_x11 -lvdpau &&
-    prepend ffmpeg_libs $($ldflags_filter "-lvdpau") &&
+    check_lib2 "vdpau/vdpau.h vdpau/vdpau_x11.h" vdp_device_create_x11 -lvdpau &&
     enable vdpau_x11
 
 # Funny iconv installations are not unusual, so check it after all flags have been set
@@ -6210,6 +6412,7 @@ echo "threading support         ${thread_type-no}"
 echo "safe bitstream reader     ${safe_bitstream_reader-no}"
 echo "SDL support               ${sdl-no}"
 echo "opencl enabled            ${opencl-no}"
+echo "JNI support               ${jni-no}"
 echo "texi2html enabled         ${texi2html-no}"
 echo "perl enabled              ${perl-no}"
 echo "pod2man enabled           ${pod2man-no}"
@@ -6227,6 +6430,14 @@ echo "External libraries:"
 print_enabled '' $EXTERNAL_LIBRARY_LIST | print_in_columns
 echo
 
+echo "External libraries providing hardware acceleration:"
+print_enabled '' $HWACCEL_LIBRARY_LIST | print_in_columns
+echo
+
+echo "Libraries:"
+print_enabled '' $LIBRARY_LIST | print_in_columns
+echo
+
 for type in decoder encoder hwaccel parser demuxer muxer protocol filter bsf indev outdev; do
     echo "Enabled ${type}s:"
     eval list=\$$(toupper $type)_LIST
@@ -6269,6 +6480,7 @@ DATADIR=\$(DESTDIR)$datadir
 DOCDIR=\$(DESTDIR)$docdir
 MANDIR=\$(DESTDIR)$mandir
 PKGCONFIGDIR=\$(DESTDIR)$pkgconfigdir
+INSTALL_NAME_DIR=$install_name_dir
 SRC_PATH=$source_path
 SRC_LINK=$source_link
 ifndef MAIN_MAKEFILE
@@ -6472,6 +6684,23 @@ if test -n "$WARNINGS"; then
     enabled fatal_warnings && exit 1
 fi
 
+# generate the lists of enabled components
+print_enabled_components(){
+    file=$1
+    struct_name=$2
+    name=$3
+    shift 3
+    echo "static const $struct_name *$name[] = {" > $TMPH
+    for c in $*; do
+        enabled $c && printf "    &ff_%s,\n" $c >> $TMPH
+    done
+    echo "    NULL };" >> $TMPH
+    cp_if_changed $TMPH $file
+}
+
+print_enabled_components libavcodec/bsf_list.c AVBitStreamFilter bitstream_filters $BSF_LIST
+print_enabled_components libavformat/protocol_list.c URLProtocol url_protocols $PROTOCOL_LIST
+
 # build pkg-config files
 
 lib_version(){
diff --git a/doc/APIchanges b/doc/APIchanges
index 85d4db7..52cd48c 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,131 @@ libavutil:     2015-08-28
 
 API changes, most recent first:
 
+2016-06-30 - c1c7e0ab - lavf 57.41.100 - avformat.h
+  Moved codecpar field from AVStream to the end of the struct, so that
+  the following private fields are in the same location as in FFmpeg 3.0 (lavf 57.25.100).
+
+2016-06-30 - 042fb69d - lavu 55.28.100 - frame.h
+  Moved hw_frames_ctx field from AVFrame to the end of the struct, so that
+  the following private fields are in the same location as in FFmpeg 3.0 (lavu 55.17.103).
+
+2016-06-29 - 1a751455 - lavfi 6.47.100 - avfilter.h
+  Fix accidental ABI breakage in AVFilterContext.
+  ABI was broken in 8688d3a, lavfi 6.42.100 and released as ffmpeg 3.1.
+
+  Because of this, ffmpeg and ffplay built against lavfi>=6.42.100 will not be
+  compatible with lavfi>=6.47.100. Potentially also affects other users of
+  libavfilter if they are using one of the affected fields.
+
+-------- 8< --------- FFmpeg 3.1 was cut here -------- 8< ---------
+
+2016-06-26 - 481f320 / 1c9e861 - lavu 55.27.100 / 55.13.0 - hwcontext.h
+  Add av_hwdevice_ctx_create().
+
+2016-06-26 - b95534b / e47b8bb - lavc 57.48.101 / 57.19.1 - avcodec.h
+  Adjust values for JPEG 2000 profiles.
+
+2016-06-23 - 5d75e46 / db7968b - lavf 57.40.100 / 57.7.0 - avio.h
+  Add AVIODataMarkerType, write_data_type, ignore_boundary_point and
+  avio_write_marker.
+
+2016-06-23 - abb3cc4 / 0c4468d - lavu 55.26.100 / 55.12.0 - opt.h
+  Add av_stereo3d_type_name() and av_stereo3d_from_name().
+
+2016-06-22 - 3689efe / c46db38 - lavu 55.25.100 / 55.11.0 - hwcontext_dxva2.h
+  Add new installed header with DXVA2-specific hwcontext definitions.
+
+2016-04-27 - fb91871 - lavu 55.23.100 - log.h
+  Add a new function av_log_format_line2() which returns number of bytes
+  written to the target buffer.
+
+2016-04-21 - 7fc329e - lavc 57.37.100 - avcodec.h
+  Add a new audio/video encoding and decoding API with decoupled input
+  and output -- avcodec_send_packet(), avcodec_receive_frame(),
+  avcodec_send_frame() and avcodec_receive_packet().
+
+2016-04-17 - af9cac1 / 33d1898 - lavc 57.35.100 / 57.15.0 - avcodec.h
+  Add a new bitstream filtering API working with AVPackets.
+  Deprecate the old bitstream filtering API.
+
+2016-04-14 - 8688d3a / 07a844f - lavfi 6.42.100 / 6.3.0 - avfilter.h
+  Add AVFilterContext.hw_device_ctx.
+
+2016-04-14 - 28abb21 / 551c677 - lavu 55.22.100 / 55.9.0 - hwcontext_vaapi.h
+  Add new installed header with VAAPI-specific hwcontext definitions.
+
+2016-04-14 - afccfaf / b1f01e8 - lavu 55.21.100 / 55.7.0 - hwcontext.h
+  Add AVHWFramesConstraints and associated API.
+
+2016-04-11 - 6f69f7a / 9200514 - lavf 57.33.100 / 57.5.0 - avformat.h
+  Add AVStream.codecpar, deprecate AVStream.codec.
+
+2016-04-02 - e8a9b64 - lavu 55.20.100 - base64.h
+  Add AV_BASE64_DECODE_SIZE(x) macro.
+
+2016-xx-xx - lavc 57.33.100 / 57.14.0 - avcodec.h
+  f9b1cf1 / 998e1b8 - Add AVCodecParameters and its related API.
+  e6053b3 / a806834 - Add av_get_audio_frame_duration2().
+
+2016-03-11 - 6d8ab35 - lavf/lavc 57.28.101
+  Add requirement to bitstream filtering API that returned packets with
+  size == 0 and side_data_elems == 0 are to be skipped by the caller.
+
+2016-03-04 - 9362973 - lavf 57.28.100
+  Add protocol blacklisting API
+
+2016-02-28 - 4dd4d53 - lavc 57.27.101
+  Validate AVFrame returned by get_buffer2 to have required
+  planes not NULL and unused planes set to NULL as crashes
+  and buffer overflow are possible with certain streams if
+  that is not the case.
+
+2016-02-26 - 30e7685 - lavc 57.27.100 - avcodec.h
+  "flags2" decoding option now allows the flag "ass_ro_flush_noop" preventing
+  the reset of the ASS ReadOrder field on flush. This affects the content of
+  AVSubtitles.rects[N]->ass when "sub_text_format" is set to "ass" (see
+  previous entry).
+
+2016-02-26 - 2941282 - lavc 57.26.100 - avcodec.h
+  Add a "sub_text_format" subtitles decoding option allowing the values "ass"
+  (recommended) and "ass_with_timings" (not recommended, deprecated, default).
+  The default value for this option will change to "ass" at the next major
+  libavcodec version bump.
+
+  The current default is "ass_with_timings" for compatibility. This means that
+  all subtitles text decoders currently still output ASS with timings printed
+  as strings in the AVSubtitles.rects[N]->ass fields.
+
+  Setting "sub_text_format" to "ass" allows a better timing accuracy (ASS
+  timing is limited to a 1/100 time base, so this is relevant for any subtitles
+  format needing a bigger one), ease timing adjustments, and prevents the need
+  of removing the timing from the decoded string yourself. This form is also
+  known as "the Matroska form". The timing information (start time, duration)
+  can be found in the AVSubtitles fields.
+
+2016-02-24 - 7e49cdd / 7b3214d0 - lavc 57.25.100 / 57.13.0 - avcodec.h
+  Add AVCodecContext.hw_frames_ctx.
+
+2016-02-24 - 1042402 / b3dd30d - lavfi 6.36.100 / 6.2.0 - avfilter.h
+  avfilter.h - Add AVFilterLink.hw_frames_ctx.
+  buffersrc.h - Add AVBufferSrcParameters and functions for handling it.
+
+2016-02-23 - 14f7a3d - lavc 57.25.100
+  Add AV_PKT_DATA_MPEGTS_STREAM_ID for exporting the MPEGTS stream ID.
+
+2016-02-18 - 08acab8 - lavu 55.18.100 - audio_fifo.h
+  Add av_audio_fifo_peek_at().
+
+2016-xx-xx - lavu 55.18.100 / 55.6.0
+  26abd51 / 721a4ef buffer.h - Add av_buffer_pool_init2().
+  1a70878 / 89923e4 hwcontext.h - Add a new installed header hwcontext.h with a new API
+                        for handling hwaccel frames.
+  6992276 / ad884d1 hwcontext_cuda.h - Add a new installed header hwcontext_cuda.h with
+                             CUDA-specific hwcontext definitions.
+  d779d8d / a001ce3 hwcontext_vdpau.h - Add a new installed header hwcontext_vdpau.h with
+                              VDPAU-specific hwcontext definitions.
+  63c3e35 / 7bc780c pixfmt.h - Add AV_PIX_FMT_CUDA.
+
 -------- 8< --------- FFmpeg 3.0 was cut here -------- 8< ---------
 
 2016-02-10 - bc9a596 / 9f61abc - lavf 57.25.100 / 57.3.0 - avformat.h
@@ -1084,7 +1209,7 @@ lavd 54.4.100 / 54.0.0, lavfi 3.5.0
                 * base -- is now stored in AVBufferRef
                 * reference, type, buffer_hints -- are unnecessary in the new API
                 * hwaccel_picture_private, owner, thread_opaque -- should not
-                  have been acessed from outside of lavc
+                  have been accessed from outside of lavc
                 * qscale_table, qstride, qscale_type, mbskip_table, motion_val,
                   mb_type, dct_coeff, ref_index -- mpegvideo-specific tables,
                   which are not exported anymore.
diff --git a/doc/Doxyfile b/doc/Doxyfile
index 845d8dc..68c0679 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME           = FFmpeg
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 3.0.2
+PROJECT_NUMBER         = 3.1.1
 
 # With the PROJECT_LOGO tag one can specify a logo or icon that is included
 # in the documentation. The maximum height of the logo should not exceed 55
@@ -1429,7 +1429,7 @@ PERL_PATH              = /usr/bin/perl
 #---------------------------------------------------------------------------
 
 # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# generate an inheritance diagram (in HTML, RTF and LaTeX) for classes with base
 # or super classes. Setting the tag to NO turns the diagrams off. Note that
 # this option is superseded by the HAVE_DOT option below. This is only a
 # fallback. It is recommended to install and use dot, since it yields more
diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index 563049e..6c58d02 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -67,6 +67,10 @@ the header stored in extradata to the key packets:
 ffmpeg -i INPUT -map 0 -flags:v +global_header -c:v libx264 -bsf:v dump_extra out.ts
 @end example
 
+ at section dca_core
+
+Extract DCA core from DTS-HD streams.
+
 @section h264_mp4toannexb
 
 Convert an H.264 bitstream from length prefixed mode to start code
diff --git a/doc/build_system.txt b/doc/build_system.txt
index a9bd4eb..8c12e0e 100644
--- a/doc/build_system.txt
+++ b/doc/build_system.txt
@@ -39,9 +39,6 @@ examples
 libavformat/output-example
     Build the libavformat basic example.
 
-libavcodec/api-example
-    Build the libavcodec basic example.
-
 libswscale/swscale-test
     Build the swscale self-test (useful also as an example).
 
diff --git a/doc/codecs.texi b/doc/codecs.texi
index b481b4a..48fc3bf 100644
--- a/doc/codecs.texi
+++ b/doc/codecs.texi
@@ -257,7 +257,7 @@ Specify how strictly to follow the standards.
 Possible values:
 @table @samp
 @item very
-strictly conform to a older more strict version of the spec or reference software
+strictly conform to an older more strict version of the spec or reference software
 @item strict
 strictly conform to all the things in the spec no matter what consequences
 @item normal
@@ -456,6 +456,9 @@ Possible values:
 @item aspect @var{rational number} (@emph{encoding,video})
 Set sample aspect ratio.
 
+ at item sar @var{rational number} (@emph{encoding,video})
+Set sample aspect ratio. Alias to @var{aspect}.
+
 @item debug @var{flags} (@emph{decoding/encoding,audio,video,subtitles})
 Print specific debug info.
 
@@ -1047,7 +1050,38 @@ Possible values:
 @item rc_min_vbv_use @var{float} (@emph{encoding,video})
 @item ticks_per_frame @var{integer} (@emph{decoding/encoding,audio,video})
 @item color_primaries @var{integer} (@emph{decoding/encoding,video})
+
 @item color_trc @var{integer} (@emph{decoding/encoding,video})
+Possible values:
+ at table @samp
+ at item bt709
+BT.709
+ at item gamma22
+BT.470 M
+ at item gamma28
+BT.470 BG
+ at item linear
+SMPTE 170 M
+ at item log
+SMPTE 240 M
+ at item log_sqrt
+Linear
+ at item iec61966_2_4
+Log
+ at item bt1361
+Log square root
+ at item iec61966_2_1
+IEC 61966-2-4
+ at item bt2020_10bit
+BT.1361
+ at item bt2020_12bit
+IEC 61966-2-1
+ at item smpte2084
+BT.2020 - 10 bit
+ at item smpte428_1
+BT.2020 - 12 bit
+ at end table
+
 @item colorspace @var{integer} (@emph{decoding/encoding,video})
 
 @item color_range @var{integer} (@emph{decoding/encoding,video})
diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index 3947bf6..e34f8b3 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -441,9 +441,9 @@ ffmpeg -framerate 10 -pattern_type glob -i "*.png" out.mkv
 @end example
 @end itemize
 
- at section mov/mp4/3gp/Quicktme
+ at section mov/mp4/3gp/QuickTime
 
-Quicktime / MP4 demuxer.
+QuickTime / MP4 demuxer.
 
 This demuxer accepts the following options:
 @table @option
diff --git a/doc/developer.texi b/doc/developer.texi
index 6db93ce..4d3a7ae 100644
--- a/doc/developer.texi
+++ b/doc/developer.texi
@@ -403,6 +403,35 @@ finding a new maintainer and also don't forget to update the @file{MAINTAINERS}
 
 We think our rules are not too hard. If you have comments, contact us.
 
+ at section Code of conduct
+
+Be friendly and respectful towards others and third parties.
+Treat others the way you yourself want to be treated.
+
+Be considerate. Not everyone shares the same viewpoint and priorities as you do.
+Different opinions and interpretations help the project.
+Looking at issues from a different perspective assists development.
+
+Do not assume malice for things that can be attributed to incompetence. Even if
+it is malice, it's rarely good to start with that as initial assumption.
+
+Stay friendly even if someone acts contrarily. Everyone has a bad day
+once in a while.
+If you yourself have a bad day or are angry then try to take a break and reply
+once you are calm and without anger if you have to.
+
+Try to help other team members and cooperate if you can.
+
+The goal of software development is to create technical excellence, not for any
+individual to be better and "win" against the others. Large software projects
+are only possible and successful through teamwork.
+
+If someone struggles do not put them down. Give them a helping hand
+instead and point them in the right direction.
+
+Finally, keep in mind the immortal words of Bill and Ted,
+"Be excellent to each other."
+
 @anchor{Submitting patches}
 @section Submitting patches
 
diff --git a/doc/examples/decoding_encoding.c b/doc/examples/decoding_encoding.c
index 06a98a6..43a64c2 100644
--- a/doc/examples/decoding_encoding.c
+++ b/doc/examples/decoding_encoding.c
@@ -25,9 +25,9 @@
  * libavcodec API use example.
  *
  * @example decoding_encoding.c
- * Note that libavcodec only handles codecs (mpeg, mpeg4, etc...),
- * not file formats (avi, vob, mp4, mov, mkv, mxf, flv, mpegts, mpegps, etc...). See library 'libavformat' for the
- * format handling
+ * Note that libavcodec only handles codecs (MPEG, MPEG-4, etc...),
+ * not file formats (AVI, VOB, MP4, MOV, MKV, MXF, FLV, MPEG-TS, MPEG-PS, etc...).
+ * See library 'libavformat' for the format handling
  */
 
 #include <math.h>
@@ -253,7 +253,7 @@ static void audio_decode_example(const char *outfilename, const char *filename)
 
     printf("Decode audio file %s to %s\n", filename, outfilename);
 
-    /* find the mpeg audio decoder */
+    /* find the MPEG audio decoder */
     codec = avcodec_find_decoder(AV_CODEC_ID_MP2);
     if (!codec) {
         fprintf(stderr, "Codec not found\n");
@@ -356,7 +356,7 @@ static void video_encode_example(const char *filename, int codec_id)
 
     printf("Encode video file %s\n", filename);
 
-    /* find the mpeg1 video encoder */
+    /* find the video encoder */
     codec = avcodec_find_encoder(codec_id);
     if (!codec) {
         fprintf(stderr, "Codec not found\n");
@@ -475,7 +475,7 @@ static void video_encode_example(const char *filename, int codec_id)
         }
     }
 
-    /* add sequence end code to have a real mpeg file */
+    /* add sequence end code to have a real MPEG file */
     fwrite(endcode, 1, sizeof(endcode), f);
     fclose(f);
 
@@ -543,12 +543,12 @@ static void video_decode_example(const char *outfilename, const char *filename)
 
     av_init_packet(&avpkt);
 
-    /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
+    /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */
     memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
 
     printf("Decode video file %s to %s\n", filename, outfilename);
 
-    /* find the mpeg1 video decoder */
+    /* find the MPEG-1 video decoder */
     codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);
     if (!codec) {
         fprintf(stderr, "Codec not found\n");
@@ -613,9 +613,9 @@ static void video_decode_example(const char *outfilename, const char *filename)
                 exit(1);
     }
 
-    /* some codecs, such as MPEG, transmit the I and P frame with a
+    /* Some codecs, such as MPEG, transmit the I- and P-frame with a
        latency of one frame. You must do the following to have a
-       chance to get the last frame of the video */
+       chance to get the last frame of the video. */
     avpkt.data = NULL;
     avpkt.size = 0;
     decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 1);
diff --git a/doc/examples/filtering_audio.c b/doc/examples/filtering_audio.c
index 89c80cf..6bb24a4 100644
--- a/doc/examples/filtering_audio.c
+++ b/doc/examples/filtering_audio.c
@@ -65,7 +65,7 @@ static int open_input_file(const char *filename)
     /* select the audio stream */
     ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0);
     if (ret < 0) {
-        av_log(NULL, AV_LOG_ERROR, "Cannot find a audio stream in the input file\n");
+        av_log(NULL, AV_LOG_ERROR, "Cannot find an audio stream in the input file\n");
         return ret;
     }
     audio_stream_index = ret;
diff --git a/doc/examples/muxing.c b/doc/examples/muxing.c
index d4dac5c..f1f5bb8 100644
--- a/doc/examples/muxing.c
+++ b/doc/examples/muxing.c
@@ -52,6 +52,7 @@
 // a wrapper around a single output AVStream
 typedef struct OutputStream {
     AVStream *st;
+    AVCodecContext *enc;
 
     /* pts of the next frame that will be generated */
     int64_t next_pts;
@@ -104,13 +105,18 @@ static void add_stream(OutputStream *ost, AVFormatContext *oc,
         exit(1);
     }
 
-    ost->st = avformat_new_stream(oc, *codec);
+    ost->st = avformat_new_stream(oc, NULL);
     if (!ost->st) {
         fprintf(stderr, "Could not allocate stream\n");
         exit(1);
     }
     ost->st->id = oc->nb_streams-1;
-    c = ost->st->codec;
+    c = avcodec_alloc_context3(*codec);
+    if (!c) {
+        fprintf(stderr, "Could not alloc an encoding context\n");
+        exit(1);
+    }
+    ost->enc = c;
 
     switch ((*codec)->type) {
     case AVMEDIA_TYPE_AUDIO:
@@ -155,7 +161,7 @@ static void add_stream(OutputStream *ost, AVFormatContext *oc,
         c->gop_size      = 12; /* emit one intra frame every twelve frames at most */
         c->pix_fmt       = STREAM_PIX_FMT;
         if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
-            /* just for testing, we also add B frames */
+            /* just for testing, we also add B-frames */
             c->max_b_frames = 2;
         }
         if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
@@ -213,7 +219,7 @@ static void open_audio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, A
     int ret;
     AVDictionary *opt = NULL;
 
-    c = ost->st->codec;
+    c = ost->enc;
 
     /* open it */
     av_dict_copy(&opt, opt_arg, 0);
@@ -240,6 +246,13 @@ static void open_audio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, A
     ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout,
                                        c->sample_rate, nb_samples);
 
+    /* copy the stream parameters to the muxer */
+    ret = avcodec_parameters_from_context(ost->st->codecpar, c);
+    if (ret < 0) {
+        fprintf(stderr, "Could not copy the stream parameters\n");
+        exit(1);
+    }
+
     /* create resampler context */
         ost->swr_ctx = swr_alloc();
         if (!ost->swr_ctx) {
@@ -271,13 +284,13 @@ static AVFrame *get_audio_frame(OutputStream *ost)
     int16_t *q = (int16_t*)frame->data[0];
 
     /* check if we want to generate more frames */
-    if (av_compare_ts(ost->next_pts, ost->st->codec->time_base,
+    if (av_compare_ts(ost->next_pts, ost->enc->time_base,
                       STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
         return NULL;
 
     for (j = 0; j <frame->nb_samples; j++) {
         v = (int)(sin(ost->t) * 10000);
-        for (i = 0; i < ost->st->codec->channels; i++)
+        for (i = 0; i < ost->enc->channels; i++)
             *q++ = v;
         ost->t     += ost->tincr;
         ost->tincr += ost->tincr2;
@@ -303,7 +316,7 @@ static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
     int dst_nb_samples;
 
     av_init_packet(&pkt);
-    c = ost->st->codec;
+    c = ost->enc;
 
     frame = get_audio_frame(ost);
 
@@ -383,7 +396,7 @@ static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
 static void open_video(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
 {
     int ret;
-    AVCodecContext *c = ost->st->codec;
+    AVCodecContext *c = ost->enc;
     AVDictionary *opt = NULL;
 
     av_dict_copy(&opt, opt_arg, 0);
@@ -414,6 +427,13 @@ static void open_video(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, A
             exit(1);
         }
     }
+
+    /* copy the stream parameters to the muxer */
+    ret = avcodec_parameters_from_context(ost->st->codecpar, c);
+    if (ret < 0) {
+        fprintf(stderr, "Could not copy the stream parameters\n");
+        exit(1);
+    }
 }
 
 /* Prepare a dummy image. */
@@ -448,10 +468,10 @@ static void fill_yuv_image(AVFrame *pict, int frame_index,
 
 static AVFrame *get_video_frame(OutputStream *ost)
 {
-    AVCodecContext *c = ost->st->codec;
+    AVCodecContext *c = ost->enc;
 
     /* check if we want to generate more frames */
-    if (av_compare_ts(ost->next_pts, ost->st->codec->time_base,
+    if (av_compare_ts(ost->next_pts, c->time_base,
                       STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
         return NULL;
 
@@ -495,7 +515,7 @@ static int write_video_frame(AVFormatContext *oc, OutputStream *ost)
     int got_packet = 0;
     AVPacket pkt = { 0 };
 
-    c = ost->st->codec;
+    c = ost->enc;
 
     frame = get_video_frame(ost);
 
@@ -524,7 +544,7 @@ static int write_video_frame(AVFormatContext *oc, OutputStream *ost)
 
 static void close_stream(AVFormatContext *oc, OutputStream *ost)
 {
-    avcodec_close(ost->st->codec);
+    avcodec_free_context(&ost->enc);
     av_frame_free(&ost->frame);
     av_frame_free(&ost->tmp_frame);
     sws_freeContext(ost->sws_ctx);
@@ -545,6 +565,7 @@ int main(int argc, char **argv)
     int have_video = 0, have_audio = 0;
     int encode_video = 0, encode_audio = 0;
     AVDictionary *opt = NULL;
+    int i;
 
     /* Initialize libavcodec, and register all codecs and formats. */
     av_register_all();
@@ -561,8 +582,9 @@ int main(int argc, char **argv)
     }
 
     filename = argv[1];
-    if (argc > 3 && !strcmp(argv[2], "-flags")) {
-        av_dict_set(&opt, argv[2]+1, argv[3], 0);
+    for (i = 2; i+1 < argc; i+=2) {
+        if (!strcmp(argv[i], "-flags") || !strcmp(argv[i], "-fflags"))
+            av_dict_set(&opt, argv[i]+1, argv[i+1], 0);
     }
 
     /* allocate the output media context */
@@ -620,8 +642,8 @@ int main(int argc, char **argv)
     while (encode_video || encode_audio) {
         /* select the stream to encode */
         if (encode_video &&
-            (!encode_audio || av_compare_ts(video_st.next_pts, video_st.st->codec->time_base,
-                                            audio_st.next_pts, audio_st.st->codec->time_base) <= 0)) {
+            (!encode_audio || av_compare_ts(video_st.next_pts, video_st.enc->time_base,
+                                            audio_st.next_pts, audio_st.enc->time_base) <= 0)) {
             encode_video = !write_video_frame(oc, &video_st);
         } else {
             encode_audio = !write_audio_frame(oc, &audio_st);
diff --git a/doc/examples/qsvdec.c b/doc/examples/qsvdec.c
index fd934be..aaecd81 100644
--- a/doc/examples/qsvdec.c
+++ b/doc/examples/qsvdec.c
@@ -352,7 +352,7 @@ int main(int argc, char **argv)
     for (i = 0; i < input_ctx->nb_streams; i++) {
         AVStream *st = input_ctx->streams[i];
 
-        if (st->codec->codec_id == AV_CODEC_ID_H264 && !video_st)
+        if (st->codecpar->codec_id == AV_CODEC_ID_H264 && !video_st)
             video_st = st;
         else
             st->discard = AVDISCARD_ALL;
@@ -404,16 +404,16 @@ int main(int argc, char **argv)
         goto finish;
     }
     decoder_ctx->codec_id = AV_CODEC_ID_H264;
-    if (video_st->codec->extradata_size) {
-        decoder_ctx->extradata = av_mallocz(video_st->codec->extradata_size +
+    if (video_st->codecpar->extradata_size) {
+        decoder_ctx->extradata = av_mallocz(video_st->codecpar->extradata_size +
                                             AV_INPUT_BUFFER_PADDING_SIZE);
         if (!decoder_ctx->extradata) {
             ret = AVERROR(ENOMEM);
             goto finish;
         }
-        memcpy(decoder_ctx->extradata, video_st->codec->extradata,
-               video_st->codec->extradata_size);
-        decoder_ctx->extradata_size = video_st->codec->extradata_size;
+        memcpy(decoder_ctx->extradata, video_st->codecpar->extradata,
+               video_st->codecpar->extradata_size);
+        decoder_ctx->extradata_size = video_st->codecpar->extradata_size;
     }
     decoder_ctx->refcounted_frames = 1;
 
diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c
index 486e54c..9b3ee67 100644
--- a/doc/examples/transcode_aac.c
+++ b/doc/examples/transcode_aac.c
@@ -62,6 +62,7 @@ static int open_input_file(const char *filename,
                            AVFormatContext **input_format_context,
                            AVCodecContext **input_codec_context)
 {
+    AVCodecContext *avctx;
     AVCodec *input_codec;
     int error;
 
@@ -91,23 +92,39 @@ static int open_input_file(const char *filename,
     }
 
     /** Find a decoder for the audio stream. */
-    if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codec->codec_id))) {
+    if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codecpar->codec_id))) {
         fprintf(stderr, "Could not find input codec\n");
         avformat_close_input(input_format_context);
         return AVERROR_EXIT;
     }
 
+    /** allocate a new decoding context */
+    avctx = avcodec_alloc_context3(input_codec);
+    if (!avctx) {
+        fprintf(stderr, "Could not allocate a decoding context\n");
+        avformat_close_input(input_format_context);
+        return AVERROR(ENOMEM);
+    }
+
+    /** initialize the stream parameters with demuxer information */
+    error = avcodec_parameters_to_context(avctx, (*input_format_context)->streams[0]->codecpar);
+    if (error < 0) {
+        avformat_close_input(input_format_context);
+        avcodec_free_context(&avctx);
+        return error;
+    }
+
     /** Open the decoder for the audio stream to use it later. */
-    if ((error = avcodec_open2((*input_format_context)->streams[0]->codec,
-                               input_codec, NULL)) < 0) {
+    if ((error = avcodec_open2(avctx, input_codec, NULL)) < 0) {
         fprintf(stderr, "Could not open input codec (error '%s')\n",
                 get_error_text(error));
+        avcodec_free_context(&avctx);
         avformat_close_input(input_format_context);
         return error;
     }
 
     /** Save the decoder context for easier access later. */
-    *input_codec_context = (*input_format_context)->streams[0]->codec;
+    *input_codec_context = avctx;
 
     return 0;
 }
@@ -122,6 +139,7 @@ static int open_output_file(const char *filename,
                             AVFormatContext **output_format_context,
                             AVCodecContext **output_codec_context)
 {
+    AVCodecContext *avctx          = NULL;
     AVIOContext *output_io_context = NULL;
     AVStream *stream               = NULL;
     AVCodec *output_codec          = NULL;
@@ -161,27 +179,31 @@ static int open_output_file(const char *filename,
     }
 
     /** Create a new audio stream in the output file container. */
-    if (!(stream = avformat_new_stream(*output_format_context, output_codec))) {
+    if (!(stream = avformat_new_stream(*output_format_context, NULL))) {
         fprintf(stderr, "Could not create new stream\n");
         error = AVERROR(ENOMEM);
         goto cleanup;
     }
 
-    /** Save the encoder context for easier access later. */
-    *output_codec_context = stream->codec;
+    avctx = avcodec_alloc_context3(output_codec);
+    if (!avctx) {
+        fprintf(stderr, "Could not allocate an encoding context\n");
+        error = AVERROR(ENOMEM);
+        goto cleanup;
+    }
 
     /**
      * Set the basic encoder parameters.
      * The input file's sample rate is used to avoid a sample rate conversion.
      */
-    (*output_codec_context)->channels       = OUTPUT_CHANNELS;
-    (*output_codec_context)->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS);
-    (*output_codec_context)->sample_rate    = input_codec_context->sample_rate;
-    (*output_codec_context)->sample_fmt     = output_codec->sample_fmts[0];
-    (*output_codec_context)->bit_rate       = OUTPUT_BIT_RATE;
+    avctx->channels       = OUTPUT_CHANNELS;
+    avctx->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS);
+    avctx->sample_rate    = input_codec_context->sample_rate;
+    avctx->sample_fmt     = output_codec->sample_fmts[0];
+    avctx->bit_rate       = OUTPUT_BIT_RATE;
 
     /** Allow the use of the experimental AAC encoder */
-    (*output_codec_context)->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
+    avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
 
     /** Set the sample rate for the container. */
     stream->time_base.den = input_codec_context->sample_rate;
@@ -192,18 +214,28 @@ static int open_output_file(const char *filename,
      * Mark the encoder so that it behaves accordingly.
      */
     if ((*output_format_context)->oformat->flags & AVFMT_GLOBALHEADER)
-        (*output_codec_context)->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+        avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 
     /** Open the encoder for the audio stream to use it later. */
-    if ((error = avcodec_open2(*output_codec_context, output_codec, NULL)) < 0) {
+    if ((error = avcodec_open2(avctx, output_codec, NULL)) < 0) {
         fprintf(stderr, "Could not open output codec (error '%s')\n",
                 get_error_text(error));
         goto cleanup;
     }
 
+    error = avcodec_parameters_from_context(stream->codecpar, avctx);
+    if (error < 0) {
+        fprintf(stderr, "Could not initialize stream parameters\n");
+        goto cleanup;
+    }
+
+    /** Save the encoder context for easier access later. */
+    *output_codec_context = avctx;
+
     return 0;
 
 cleanup:
+    avcodec_free_context(&avctx);
     avio_closep(&(*output_format_context)->pb);
     avformat_free_context(*output_format_context);
     *output_format_context = NULL;
@@ -756,13 +788,13 @@ cleanup:
         av_audio_fifo_free(fifo);
     swr_free(&resample_context);
     if (output_codec_context)
-        avcodec_close(output_codec_context);
+        avcodec_free_context(&output_codec_context);
     if (output_format_context) {
         avio_closep(&output_format_context->pb);
         avformat_free_context(output_format_context);
     }
     if (input_codec_context)
-        avcodec_close(input_codec_context);
+        avcodec_free_context(&input_codec_context);
     if (input_format_context)
         avformat_close_input(&input_format_context);
 
diff --git a/doc/examples/transcoding.c b/doc/examples/transcoding.c
index d5d410b..8633362 100644
--- a/doc/examples/transcoding.c
+++ b/doc/examples/transcoding.c
@@ -128,7 +128,10 @@ static int open_output_file(const char *filename)
                 enc_ctx->width = dec_ctx->width;
                 enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;
                 /* take first format from list of supported formats */
-                enc_ctx->pix_fmt = encoder->pix_fmts[0];
+                if (encoder->pix_fmts)
+                    enc_ctx->pix_fmt = encoder->pix_fmts[0];
+                else
+                    enc_ctx->pix_fmt = dec_ctx->pix_fmt;
                 /* video time_base can be set to whatever is handy and supported by encoder */
                 enc_ctx->time_base = dec_ctx->time_base;
             } else {
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index e02807c..7368cdb 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -720,7 +720,7 @@ For DXVA2, this option should contain the number of the display adapter to use.
 If this option is not specified, the default adapter is used.
 
 @item qsv
-For QSV, this option corresponds to the valus of MFX_IMPL_* . Allowed values
+For QSV, this option corresponds to the values of MFX_IMPL_* . Allowed values
 are:
 @table @option
 @item auto
diff --git a/doc/filters.texi b/doc/filters.texi
index 68f54f1..3cf3d7c 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -2366,6 +2366,119 @@ Sets the difference coefficient (default: 2.5). 0.0 means mono sound
 Enable clipping. By default is enabled.
 @end table
 
+ at section firequalizer
+Apply FIR Equalization using arbitrary frequency response.
+
+The filter accepts the following option:
+
+ at table @option
+ at item gain
+Set gain curve equation (in dB). The expression can contain variables:
+ at table @option
+ at item f
+the evaluated frequency
+ at item sr
+sample rate
+ at item ch
+channel number, set to 0 when multichannels evaluation is disabled
+ at item chid
+channel id, see libavutil/channel_layout.h, set to the first channel id when
+multichannels evaluation is disabled
+ at item chs
+number of channels
+ at item chlayout
+channel_layout, see libavutil/channel_layout.h
+
+ at end table
+and functions:
+ at table @option
+ at item gain_interpolate(f)
+interpolate gain on frequency f based on gain_entry
+ at end table
+This option is also available as command. Default is @code{gain_interpolate(f)}.
+
+ at item gain_entry
+Set gain entry for gain_interpolate function. The expression can
+contain functions:
+ at table @option
+ at item entry(f, g)
+store gain entry at frequency f with value g
+ at end table
+This option is also available as command.
+
+ at item delay
+Set filter delay in seconds. Higher value means more accurate.
+Default is @code{0.01}.
+
+ at item accuracy
+Set filter accuracy in Hz. Lower value means more accurate.
+Default is @code{5}.
+
+ at item wfunc
+Set window function. Acceptable values are:
+ at table @option
+ at item rectangular
+rectangular window, useful when gain curve is already smooth
+ at item hann
+hann window (default)
+ at item hamming
+hamming window
+ at item blackman
+blackman window
+ at item nuttall3
+3-terms continuous 1st derivative nuttall window
+ at item mnuttall3
+minimum 3-terms discontinuous nuttall window
+ at item nuttall
+4-terms continuous 1st derivative nuttall window
+ at item bnuttall
+minimum 4-terms discontinuous nuttall (blackman-nuttall) window
+ at item bharris
+blackman-harris window
+ at end table
+
+ at item fixed
+If enabled, use fixed number of audio samples. This improves speed when
+filtering with large delay. Default is disabled.
+
+ at item multi
+Enable multichannels evaluation on gain. Default is disabled.
+
+ at item zero_phase
+Enable zero phase mode by substracting timestamp to compensate delay.
+Default is disabled.
+ at end table
+
+ at subsection Examples
+ at itemize
+ at item
+lowpass at 1000 Hz:
+ at example
+firequalizer=gain='if(lt(f,1000), 0, -INF)'
+ at end example
+ at item
+lowpass at 1000 Hz with gain_entry:
+ at example
+firequalizer=gain_entry='entry(1000,0); entry(1001, -INF)'
+ at end example
+ at item
+custom equalization:
+ at example
+firequalizer=gain_entry='entry(100,0); entry(400, -4); entry(1000, -6); entry(2000, 0)'
+ at end example
+ at item
+higher delay with zero phase to compensate delay:
+ at example
+firequalizer=delay=0.1:fixed=on:zero_phase=on
+ at end example
+ at item
+lowpass on left channel, highpass on right channel:
+ at example
+firequalizer=gain='if(eq(chid,1), gain_interpolate(f), if(eq(chid,2), gain_interpolate(1e6+f), 0))'
+:gain_entry='entry(1000, 0); entry(1001,-INF); entry(1e6+1000,0)':multi=on
+ at end example
+ at end itemize
+
 @section flanger
 Apply a flanging effect to the audio.
 
@@ -2602,6 +2715,68 @@ Modify the @var{N}-th control value.
 If the specified value is not valid, it is ignored and prior one is kept.
 @end table
 
+ at section loudnorm
+
+EBU R128 loudness normalization. Includes both dynamic and linear normalization modes.
+Support for both single pass (livestreams, files) and double pass (files) modes.
+This algorithm can target IL, LRA, and maximum true peak.
+
+To enable compilation of this filter you need to configure FFmpeg with
+ at code{--enable-libebur128}.
+
+The filter accepts the following options:
+
+ at table @option
+ at item I, i
+Set integrated loudness target.
+Range is -70.0 - -5.0. Default value is -24.0.
+
+ at item LRA, lra
+Set loudness range target.
+Range is 1.0 - 20.0. Default value is 7.0.
+
+ at item TP, tp
+Set maximum true peak.
+Range is -9.0 - +0.0. Default value is -2.0.
+
+ at item measured_I, measured_i
+Measured IL of input file.
+Range is -99.0 - +0.0.
+
+ at item measured_LRA, measured_lra
+Measured LRA of input file.
+Range is  0.0 - 99.0.
+
+ at item measured_TP, measured_tp
+Measured true peak of input file.
+Range is  -99.0 - +99.0.
+
+ at item measured_thresh
+Measured threshold of input file.
+Range is -99.0 - +0.0.
+
+ at item offset
+Set offset gain. Gain is applied before the true-peak limiter.
+Range is  -99.0 - +99.0. Default is +0.0.
+
+ at item linear
+Normalize linearly if possible.
+measured_I, measured_LRA, measured_TP, and measured_thresh must also
+to be specified in order to use this mode.
+Options are true or false. Default is true.
+
+ at item dual_mono
+Treat mono input files as "dual-mono". If a mono file is intended for playback
+on a stereo system, its EBU R128 measurement will be perceptually incorrect.
+If set to @code{true}, this option will compensate for this effect.
+Multi-channel input files are not affected by this option.
+Options are true or false. Default is false.
+
+ at item print_format
+Set print format for stats. Options are summary, json, or none.
+Default value is none.
+ at end table
+
 @section lowpass
 
 Apply a low-pass filter with 3dB point frequency.
@@ -3108,11 +3283,44 @@ HRTFs. Default is 1.
 
 @item type
 Set processing type. Can be @var{time} or @var{freq}. @var{time} is
-processing audio in time domain which is slow but gives high quality output.
- at var{freq} is processing audio in frequency domain which is fast but gives
-mediocre output. Default is @var{freq}.
+processing audio in time domain which is slow.
+ at var{freq} is processing audio in frequency domain which is fast.
+Default is @var{freq}.
+
+ at item speakers
+Set custom positions of virtual loudspeakers. Syntax for this option is:
+<CH> <AZIM> <ELEV>[|<CH> <AZIM> <ELEV>|...].
+Each virtual loudspeaker is described with short channel name following with
+azimuth and elevation in degreees.
+Each virtual loudspeaker description is separated by '|'.
+For example to override front left and front right channel positions use:
+'speakers=FL 45 15|FR 345 15'.
+Descriptions with unrecognised channel names are ignored.
 @end table
 
+ at subsection Examples
+
+ at itemize
+ at item
+Using ClubFritz6 sofa file:
+ at example
+sofalizer=sofa=/path/to/ClubFritz6.sofa:type=freq:radius=1
+ at end example
+
+ at item
+Using ClubFritz12 sofa file and bigger radius with small rotation:
+ at example
+sofalizer=sofa=/path/to/ClubFritz12.sofa:type=freq:radius=2:rotation=5
+ at end example
+
+ at item
+Similar as above but with custom speaker positions for front left, front right, rear left and rear right
+and also with custom gain:
+ at example
+"sofalizer=sofa=/path/to/ClubFritz6.sofa:type=freq:radius=2:speakers=FL 45|FR 315|RL 135|RR 225:gain=28"
+ at end example
+ at end itemize
+
 @section stereotools
 
 This filter has some handy utilities to manage stereo signals, for converting
@@ -3210,6 +3418,22 @@ Set S/C level. Default is 1. Allowed range is from 1 to 100.
 Set the stereo phase in degrees. Default is 0. Allowed range is from 0 to 360.
 @end table
 
+ at subsection Examples
+
+ at itemize
+ at item
+Apply karaoke like effect:
+ at example
+stereotools=mlev=0.015625
+ at end example
+
+ at item
+Convert M/S signal to L/R:
+ at example
+"stereotools=mode=ms>lr"
+ at end example
+ at end itemize
+
 @section stereowiden
 
 This filter enhance the stereo effect by suppressing signal common to both
@@ -3237,6 +3461,47 @@ channels. Default is 0.3.
 Set level of input signal of original channel. Default is 0.8.
 @end table
 
+ at section scale_npp
+
+Use the NVIDIA Performance Primitives (libnpp) to perform scaling and/or pixel
+format conversion on CUDA video frames. Setting the output width and height
+works in the same way as for the @var{scale} filter.
+
+The following additional options are accepted:
+ at table @option
+ at item format
+The pixel format of the output CUDA frames. If set to the string "same" (the
+default), the input format will be kept. Note that automatic format negotiation
+and conversion is not yet supported for hardware frames
+
+ at item interp_algo
+The interpolation algorithm used for resizing. One of the following:
+ at table @option
+ at item nn
+Nearest neighbour.
+
+ at item linear
+ at item cubic
+ at item cubic2p_bspline
+2-parameter cubic (B=1, C=0)
+
+ at item cubic2p_catmullrom
+2-parameter cubic (B=0, C=1/2)
+
+ at item cubic2p_b05c03
+2-parameter cubic (B=1/2, C=3/10)
+
+ at item super
+Supersampling
+
+ at item lanczos
+ at end table
+
+ at end table
+
+ at section select
+Select frames to pass in output.
+
 @section treble
 
 Boost or cut treble (upper) frequencies of the audio using a two-pole
@@ -4131,10 +4396,12 @@ Available values for component modes are:
 @item difference128
 @item divide
 @item dodge
+ at item freeze
 @item exclusion
 @item glow
 @item hardlight
 @item hardmix
+ at item heat
 @item lighten
 @item linearlight
 @item multiply
@@ -4344,6 +4611,59 @@ boxblur=luma_radius=min(h\,w)/10:luma_power=1:chroma_radius=min(cw\,ch)/10:chrom
 @end example
 @end itemize
 
+ at section bwdif
+
+Deinterlace the input video ("bwdif" stands for "Bob Weaver
+Deinterlacing Filter").
+
+Motion adaptive deinterlacing based on yadif with the use of w3fdif and cubic
+interpolation algorithms.
+It accepts the following parameters:
+
+ at table @option
+ at item mode
+The interlacing mode to adopt. It accepts one of the following values:
+
+ at table @option
+ at item 0, send_frame
+Output one frame for each frame.
+ at item 1, send_field
+Output one frame for each field.
+ at end table
+
+The default value is @code{send_field}.
+
+ at item parity
+The picture field parity assumed for the input interlaced video. It accepts one
+of the following values:
+
+ at table @option
+ at item 0, tff
+Assume the top field is first.
+ at item 1, bff
+Assume the bottom field is first.
+ at item -1, auto
+Enable automatic detection of field parity.
+ at end table
+
+The default value is @code{auto}.
+If the interlacing is unknown or the decoder does not export this information,
+top field first will be assumed.
+
+ at item deint
+Specify which frames to deinterlace. Accept one of the following
+values:
+
+ at table @option
+ at item 0, all
+Deinterlace all frames.
+ at item 1, interlaced
+Only deinterlace frames marked as interlaced.
+ at end table
+
+The default value is @code{all}.
+ at end table
+
 @section chromakey
 YUV colorspace color/chroma keying.
 
@@ -4389,6 +4709,61 @@ ffmpeg -f lavfi -i color=c=black:s=1280x720 -i video.mp4 -shortest -filter_compl
 @end example
 @end itemize
 
+ at section ciescope
+
+Display CIE color diagram with pixels overlaid onto it.
+
+The filter acccepts the following options:
+
+ at table @option
+ at item system
+Set color system.
+
+ at table @samp
+ at item ntsc, 470m
+ at item ebu, 470bg
+ at item smpte
+ at item 240m
+ at item apple
+ at item widergb
+ at item cie1931
+ at item rec709, hdtv
+ at item uhdtv, rec2020
+ at end table
+
+ at item cie
+Set CIE system.
+
+ at table @samp
+ at item xyy
+ at item ucs
+ at item luv
+ at end table
+
+ at item gamuts
+Set what gamuts to draw.
+
+See @code{system} option for avaiable values.
+
+ at item size, s
+Set ciescope size, by default set to 512.
+
+ at item intensity, i
+Set intensity used to map input pixel values to CIE diagram.
+
+ at item contrast
+Set contrast used to draw tongue colors that are out of active color system gamut.
+
+ at item corrgamma
+Correct gamma displayed on scope, by default enabled.
+
+ at item showwhite
+Show white point on CIE diagram, by default disabled.
+
+ at item gamma
+Set input gamma. Used only with XYZ input color space.
+ at end table
+
 @section codecview
 
 Visualize information exported by some codecs.
@@ -4415,16 +4790,48 @@ backward predicted MVs of B-frames
 @end table
 
 @item qp
-Display quantization parameters using the chroma planes
+Display quantization parameters using the chroma planes.
+
+ at item mv_type, mvt
+Set motion vectors type to visualize. Includes MVs from all frames unless specified by @var{frame_type} option.
+
+Available flags for @var{mv_type} are:
+
+ at table @samp
+ at item fp
+forward predicted MVs
+ at item bp
+backward predicted MVs
+ at end table
+
+ at item frame_type, ft
+Set frame type to visualize motion vectors of.
+
+Available flags for @var{frame_type} are:
+
+ at table @samp
+ at item if
+intra-coded frames (I-frames)
+ at item pf
+predicted frames (P-frames)
+ at item bf
+bi-directionally predicted frames (B-frames)
+ at end table
 @end table
 
 @subsection Examples
 
 @itemize
 @item
-Visualizes multi-directionals MVs from P and B-Frames using @command{ffplay}:
+Visualize forward predicted MVs of all frames using @command{ffplay}:
 @example
-ffplay -flags2 +export_mvs input.mpg -vf codecview=mv=pf+bf+bb
+ffplay -flags2 +export_mvs input.mp4 -vf codecview=mv_type=fp
+ at end example
+
+ at item
+Visualize multi-directionals MVs of P and B-Frames using @command{ffplay}:
+ at example
+ffplay -flags2 +export_mvs input.mp4 -vf codecview=mv=pf+bf+bb
 @end example
 @end itemize
 
@@ -4661,6 +5068,9 @@ SMPTE-240M
 
 @item fcc
 FCC
+
+ at item bt2020
+BT.2020
 @end table
 @end table
 
@@ -4669,6 +5079,217 @@ For example to convert from BT.601 to SMPTE-240M, use the command:
 colormatrix=bt601:smpte240m
 @end example
 
+ at section colorspace
+
+Convert colorspace, transfer characteristics or color primaries.
+
+The filter accepts the following options:
+
+ at table @option
+ at item all
+Specify all color properties at once.
+
+The accepted values are:
+ at table @samp
+ at item bt470m
+BT.470M
+
+ at item bt470bg
+BT.470BG
+
+ at item bt601-6-525
+BT.601-6 525
+
+ at item bt601-6-625
+BT.601-6 625
+
+ at item bt709
+BT.709
+
+ at item smpte170m
+SMPTE-170M
+
+ at item smpte240m
+SMPTE-240M
+
+ at item bt2020
+BT.2020
+
+ at end table
+
+ at item space
+Specify output colorspace.
+
+The accepted values are:
+ at table @samp
+ at item bt709
+BT.709
+
+ at item fcc
+FCC
+
+ at item bt470bg
+BT.470BG or BT.601-6 625
+
+ at item smpte170m
+SMPTE-170M or BT.601-6 525
+
+ at item smpte240m
+SMPTE-240M
+
+ at item bt2020ncl
+BT.2020 with non-constant luminance
+
+ at end table
+
+ at item trc
+Specify output transfer characteristics.
+
+The accepted values are:
+ at table @samp
+ at item bt709
+BT.709
+
+ at item gamma22
+Constant gamma of 2.2
+
+ at item gamma28
+Constant gamma of 2.8
+
+ at item smpte170m
+SMPTE-170M, BT.601-6 625 or BT.601-6 525
+
+ at item smpte240m
+SMPTE-240M
+
+ at item bt2020-10
+BT.2020 for 10-bits content
+
+ at item bt2020-12
+BT.2020 for 12-bits content
+
+ at end table
+
+ at item prm
+Specify output color primaries.
+
+The accepted values are:
+ at table @samp
+ at item bt709
+BT.709
+
+ at item bt470m
+BT.470M
+
+ at item bt470bg
+BT.470BG or BT.601-6 625
+
+ at item smpte170m
+SMPTE-170M or BT.601-6 525
+
+ at item smpte240m
+SMPTE-240M
+
+ at item bt2020
+BT.2020
+
+ at end table
+
+ at item rng
+Specify output color range.
+
+The accepted values are:
+ at table @samp
+ at item mpeg
+MPEG (restricted) range
+
+ at item jpeg
+JPEG (full) range
+
+ at end table
+
+ at item format
+Specify output color format.
+
+The accepted values are:
+ at table @samp
+ at item yuv420p
+YUV 4:2:0 planar 8-bits
+
+ at item yuv420p10
+YUV 4:2:0 planar 10-bits
+
+ at item yuv420p12
+YUV 4:2:0 planar 12-bits
+
+ at item yuv422p
+YUV 4:2:2 planar 8-bits
+
+ at item yuv422p10
+YUV 4:2:2 planar 10-bits
+
+ at item yuv422p12
+YUV 4:2:2 planar 12-bits
+
+ at item yuv444p
+YUV 4:4:4 planar 8-bits
+
+ at item yuv444p10
+YUV 4:4:4 planar 10-bits
+
+ at item yuv444p12
+YUV 4:4:4 planar 12-bits
+
+ at end table
+
+ at item fast
+Do a fast conversion, which skips gamma/primary correction. This will take
+significantly less CPU, but will be mathematically incorrect. To get output
+compatible with that produced by the colormatrix filter, use fast=1.
+
+ at item dither
+Specify dithering mode.
+
+The accepted values are:
+ at table @samp
+ at item none
+No dithering
+
+ at item fsb
+Floyd-Steinberg dithering
+ at end table
+
+ at item wpadapt
+Whitepoint adaptation mode.
+
+The accepted values are:
+ at table @samp
+ at item bradford
+Bradford whitepoint adaptation
+
+ at item vonkries
+von Kries whitepoint adaptation
+
+ at item identity
+identity whitepoint adaptation (i.e. no whitepoint adaptation)
+ at end table
+
+ at end table
+
+The filter converts the transfer characteristics, color space and color
+primaries to the specified user values. The output value, if not specified,
+is set to a default value based on the "all" property. If that property is
+also not specified, the filter will log an error. The output color range and
+format default to the same value as the input color range and format. The
+input transfer characteristics, color space, color primaries and color range
+should be set on the input data. If any of these are missing, the filter will
+log an error and no conversion will take place.
+
+For example to convert the input to SMPTE-240M, use the command:
+ at example
+colorspace=smpte240m
+ at end example
+
 @section convolution
 
 Apply convolution 3x3 or 5x5 filter.
@@ -4736,6 +5357,111 @@ convolution="-2 -1 0 -1 1 1 0 1 2:-2 -1 0 -1 1 1 0 1 2:-2 -1 0 -1 1 1 0 1 2:-2 -
 Copy the input source unchanged to the output. This is mainly useful for
 testing purposes.
 
+ at anchor{coreimage}
+ at section coreimage
+Video filtering on GPU using Apple's CoreImage API on OSX.
+
+Hardware acceleration is based on an OpenGL context. Usually, this means it is
+processed by video hardware. However, software-based OpenGL implementations
+exist which means there is no guarantee for hardware processing. It depends on
+the respective OSX.
+
+There are many filters and image generators provided by Apple that come with a
+large variety of options. The filter has to be referenced by its name along
+with its options.
+
+The coreimage filter accepts the following options:
+ at table @option
+ at item list_filters
+List all available filters and generators along with all their respective
+options as well as possible minimum and maximum values along with the default
+values.
+ at example
+list_filters=true
+ at end example
+
+ at item filter
+Specify all filters by their respective name and options.
+Use @var{list_filters} to determine all valid filter names and options.
+Numerical options are specified by a float value and are automatically clamped
+to their respective value range.  Vector and color options have to be specified
+by a list of space separated float values. Character escaping has to be done.
+A special option name @code{default} is available to use default options for a
+filter.
+
+It is required to specify either @code{default} or at least one of the filter options.
+All omitted options are used with their default values.
+The syntax of the filter string is as follows:
+ at example
+filter=<NAME>@@<OPTION>=<VALUE>[@@<OPTION>=<VALUE>][@@...][#<NAME>@@<OPTION>=<VALUE>[@@<OPTION>=<VALUE>][@@...]][#...]
+ at end example
+
+ at item output_rect
+Specify a rectangle where the output of the filter chain is copied into the
+input image. It is given by a list of space separated float values:
+ at example
+output_rect=x\ y\ width\ height
+ at end example
+If not given, the output rectangle equals the dimensions of the input image.
+The output rectangle is automatically cropped at the borders of the input
+image. Negative values are valid for each component.
+ at example
+output_rect=25\ 25\ 100\ 100
+ at end example
+ at end table
+
+Several filters can be chained for successive processing without GPU-HOST
+transfers allowing for fast processing of complex filter chains.
+Currently, only filters with zero (generators) or exactly one (filters) input
+image and one output image are supported. Also, transition filters are not yet
+usable as intended.
+
+Some filters generate output images with additional padding depending on the
+respective filter kernel. The padding is automatically removed to ensure the
+filter output has the same size as the input image.
+
+For image generators, the size of the output image is determined by the
+previous output image of the filter chain or the input image of the whole
+filterchain, respectively. The generators do not use the pixel information of
+this image to generate their output. However, the generated output is
+blended onto this image, resulting in partial or complete coverage of the
+output image.
+
+The @ref{coreimagesrc} video source can be used for generating input images
+which are directly fed into the filter chain. By using it, providing input
+images by another video source or an input video is not required.
+
+ at subsection Examples
+
+ at itemize
+
+ at item
+List all filters available:
+ at example
+coreimage=list_filters=true
+ at end example
+
+ at item
+Use the CIBoxBlur filter with default options to blur an image:
+ at example
+coreimage=filter=CIBoxBlur@@default
+ at end example
+
+ at item
+Use a filter chain with CISepiaTone at default values and CIVignetteEffect with
+its center at 100x100 and a radius of 50 pixels:
+ at example
+coreimage=filter=CIBoxBlur@@default#CIVignetteEffect@@inputCenter=100\ 100@@inputRadius=50
+ at end example
+
+ at item
+Use nullsrc and CIQRCodeGenerator to create a QR code for the FFmpeg homepage,
+given as complete and escaped command-line for Apple's standard bash shell:
+ at example
+ffmpeg -f lavfi -i nullsrc=s=100x100,coreimage=filter=CIQRCodeGenerator@@inputMessage=https\\\\\://FFmpeg.org/@@inputCorrectionLevel=H -frames:v 1 QRCode.png
+ at end example
+ at end itemize
+
 @section crop
 
 Crop the input video to given dimensions.
@@ -4941,7 +5667,7 @@ It accepts the following parameters:
 
 @item limit
 Set higher black value threshold, which can be optionally specified
-from nothing (0) to everything (255 for 8bit based formats). An intensity
+from nothing (0) to everything (255 for 8-bit based formats). An intensity
 value greater to the set value is considered non-black. It defaults to 24.
 You can also specify a value between 0.0 and 1.0 which will be scaled depending
 on the bitdepth of the pixel format.
@@ -5063,18 +5789,55 @@ The previous example can also be achieved with the associated built-in preset:
 curves=preset=vintage
 @end example
 
- at item
-Or simply:
- at example
-curves=vintage
- at end example
+ at item
+Or simply:
+ at example
+curves=vintage
+ at end example
+
+ at item
+Use a Photoshop preset and redefine the points of the green component:
+ at example
+curves=psfile='MyCurvesPresets/purple.acv':green='0.45/0.53'
+ at end example
+ at end itemize
+
+ at section datascope
+
+Video data analysis filter.
+
+This filter shows hexadecimal pixel values of part of video.
+
+The filter accepts the following options:
+
+ at table @option
+ at item size, s
+Set output video size.
+
+ at item x
+Set x offset from where to pick pixels.
+
+ at item y
+Set y offset from where to pick pixels.
+
+ at item mode
+Set scope mode, can be one of the following:
+ at table @samp
+ at item mono
+Draw hexadecimal pixel values with white color on black background.
+
+ at item color
+Draw hexadecimal pixel values with input video pixel color on black
+background.
 
- at item
-Use a Photoshop preset and redefine the points of the green component:
- at example
-curves=psfile='MyCurvesPresets/purple.acv':green='0.45/0.53'
- at end example
- at end itemize
+ at item color2
+Draw hexadecimal pixel values on color background picked from input video,
+the text color is picked in such way so its always visible.
+ at end table
+
+ at item axis
+Draw rows and columns numbers on left and top of video.
+ at end table
 
 @section dctdnoiz
 
@@ -6089,7 +6852,12 @@ The time at which the filter is running, expressed in the local time zone.
 It can accept an argument: a strftime() format string.
 
 @item metadata
-Frame metadata. It must take one argument specifying metadata key.
+Frame metadata. Takes one or two arguments.
+
+The first argument is mandatory and specifies the metadata key.
+
+The second argument is optional and specifies a default value, used when the
+metadata key is not found or empty.
 
 @item n, frame_num
 The frame number, starting from 0.
@@ -6147,6 +6915,12 @@ drawtext="fontsize=30:fontfile=FreeSerif.ttf:text='hello world':x=(w-text_w)/2:y
 @end example
 
 @item
+Show the text at a random position, switching to a new position every 30 seconds:
+ at example
+drawtext="fontsize=30:fontfile=FreeSerif.ttf:text='hello world':x=if(eq(mod(t\,30)\,0)\,rand(0\,(w-text_w))\,x):y=if(eq(mod(t\,30)\,0)\,rand(0\,(h-text_h))\,y)"
+ at end example
+
+ at item
 Show a text line sliding from right to left in the last row of the video
 frame. The file @file{LONG_LINE} is assumed to contain a single line
 with no newlines.
@@ -6637,6 +7411,50 @@ Specify whether to extract the top (if the value is @code{0} or
 @code{bottom}).
 @end table
 
+ at section fieldhint
+
+Create new frames by copying the top and bottom fields from surrounding frames
+supplied as numbers by the hint file.
+
+ at table @option
+ at item hint
+Set file containing hints: absolute/relative frame numbers.
+
+There must be one line for each frame in a clip. Each line must contain two
+numbers separated by the comma, optionally followed by @code{-} or @code{+}.
+Numbers supplied on each line of file can not be out of [N-1,N+1] where N
+is current frame number for @code{absolute} mode or out of [-1, 1] range
+for @code{relative} mode. First number tells from which frame to pick up top
+field and second number tells from which frame to pick up bottom field.
+
+If optionally followed by @code{+} output frame will be marked as interlaced,
+else if followed by @code{-} output frame will be marked as progressive, else
+it will be marked same as input frame.
+If line starts with @code{#} or @code{;} that line is skipped.
+
+ at item mode
+Can be item @code{absolute} or @code{relative}. Default is @code{absolute}.
+ at end table
+
+Example of first several lines of @code{hint} file for @code{relative} mode:
+ at example
+0,0 - # first frame
+1,0 - # second frame, use third's frame top field and second's frame bottom field
+1,0 - # third frame, use fourth's frame top field and third's frame bottom field
+1,0 -
+0,0 -
+0,0 -
+1,0 -
+1,0 -
+1,0 -
+0,0 -
+0,0 -
+1,0 -
+1,0 -
+1,0 -
+0,0 -
+ at end example
+
 @section fieldmatch
 
 Field matching filter for inverse telecine. It is meant to reconstruct the
@@ -7482,18 +8300,12 @@ the @ref{vignette} filter):
 @example
 geq=lum=255*gauss((X/W-0.5)*3)*gauss((Y/H-0.5)*3)/gauss(0)/gauss(0),format=gray
 @end example
-
- at item
-Diagonal split screen to compare filter effect:
- at example
-ffmpeg -i input -filter_complex "[0:v]geq=lum=if(gt(X\,Y*(W/H))\,255),format=gray[alpha];[0:v][alpha]alphamerge,curves=preset=color_negative[filtered];[0:v][filtered]overlay" output
- at end example
 @end itemize
 
 @section gradfun
 
 Fix the banding artifacts that are sometimes introduced into nearly flat
-regions by truncation to 8bit color depth.
+regions by truncation to 8-bit color depth.
 Interpolate the gradients that should go where the bands are, and
 dither them.
 
@@ -7613,6 +8425,11 @@ Then, the effect of this Hald CLUT can be visualized with:
 ffplay input.mkv -vf "movie=clut.png, [in] haldclut"
 @end example
 
+ at section hdcd
+
+Decodes high definition audio cd data. 16-Bit PCM stream containing hdcd flags
+is converted to 20-bit PCM stream.
+
 @section hflip
 
 Flip the input video horizontally.
@@ -7740,6 +8557,18 @@ A floating point number which specifies chroma temporal strength. It defaults to
 @var{luma_tmp}*@var{chroma_spatial}/@var{luma_spatial}.
 @end table
 
+ at anchor{hwupload_cuda}
+ at section hwupload_cuda
+
+Upload system memory frames to a CUDA device.
+
+It accepts the following optional parameters:
+
+ at table @option
+ at item device
+The number of the CUDA device to use
+ at end table
+
 @section hqx
 
 Apply a high-quality magnification filter designed for pixel art. This filter
@@ -7949,7 +8778,7 @@ The filter accepts the following options:
 Set interlacing threshold.
 @item prog_thres
 Set progressive threshold.
- at item repeat_thres
+ at item rep_thres
 Threshold for repeated field detection.
 @item half_life
 Number of frames after which a given frame's contribution to the
@@ -8147,6 +8976,25 @@ The formula that generates the correction is:
 where @var{r_0} is halve of the image diagonal and @var{r_src} and @var{r_tgt} are the
 distances from the focal point in the source and target images, respectively.
 
+ at section loop, aloop
+
+Loop video frames or audio samples.
+
+Those filters accepts the following options:
+
+ at table @option
+ at item loop
+Set the number of loops.
+
+ at item size
+Set maximal size in number of frames for @code{loop} filter or maximal number
+of samples in case of @code{aloop} filter.
+
+ at item start
+Set first frame of loop for @code{loop} filter or first sample of loop in case
+of @code{aloop} filter.
+ at end table
+
 @anchor{lut3d}
 @section lut3d
 
@@ -8623,9 +9471,9 @@ Use frame flags, single field.
 Use top field only.
 @item b
 Use bottom field only.
- at item ft
+ at item tf
 Use both fields, top first.
- at item fb
+ at item bf
 Use both fields, bottom first.
 @end table
 
@@ -9450,6 +10298,10 @@ The expressions can use the following variables:
 @item W
 @item H
 the width and height of video frame.
+ at item in
+Input frame count.
+ at item on
+Output frame count.
 @end table
 
 @item interpolation
@@ -9480,6 +10332,21 @@ by the given coordinates.
 
 Default value is @samp{source}.
 @end table
+
+ at item eval
+Set when the expressions for coordinates @option{x0,y0,...x3,y3} are evaluated.
+
+It accepts the following values:
+ at table @samp
+ at item init
+only evaluate expressions once during the filter initialization or
+when a command is processed
+
+ at item frame
+evaluate expressions for each incoming frame
+ at end table
+
+Default value is @samp{init}.
 @end table
 
 @section phase
@@ -9940,6 +10807,55 @@ less than @code{0}, the filter will try to use a good random seed on a
 best effort basis.
 @end table
 
+ at section readvitc
+
+Read vertical interval timecode (VITC) information from the top lines of a
+video frame.
+
+The filter adds frame metadata key @code{lavfi.readvitc.tc_str} with the
+timecode value, if a valid timecode has been detected. Further metadata key
+ at code{lavfi.readvitc.found} is set to 0/1 depending on whether
+timecode data has been found or not.
+
+This filter accepts the following options:
+
+ at table @option
+ at item scan_max
+Set the maximum number of lines to scan for VITC data. If the value is set to
+ at code{-1} the full video frame is scanned. Default is @code{45}.
+
+ at item thr_b
+Set the luma threshold for black. Accepts float numbers in the range [0.0,1.0],
+default value is @code{0.2}. The value must be equal or less than @code{thr_w}.
+
+ at item thr_w
+Set the luma threshold for white. Accepts float numbers in the range [0.0,1.0],
+default value is @code{0.6}. The value must be equal or greater than @code{thr_b}.
+ at end table
+
+ at subsection Examples
+
+ at itemize
+ at item
+Detect and draw VITC data onto the video frame; if no valid VITC is detected,
+draw @code{--:--:--:--} as a placeholder:
+ at example
+ffmpeg -i input.avi -filter:v 'readvitc,drawtext=fontfile=FreeMono.ttf:text=%@{metadata\\:lavfi.readvitc.tc_str\\:--\\\\\\:--\\\\\\:--\\\\\\:--@}:x=(w-tw)/2:y=400-ascent'
+ at end example
+ at end itemize
+
+ at section remap
+
+Remap pixels using 2nd: Xmap and 3rd: Ymap input video stream.
+
+Destination pixel at position (X, Y) will be picked from source (x, y) position
+where x = Xmap(X, Y) and y = Ymap(X, Y). If mapping values are out of range, zero
+value for pixel will be used for destination pixel.
+
+Xmap and Ymap input video streams must be of same dimensions. Output video stream
+will have Xmap/Ymap video stream dimensions.
+Xmap and Ymap input video streams are 16bit depth, single channel.
+
 @section removegrain
 
 The removegrain filter is a spatial denoiser for progressive video.
@@ -10604,6 +11520,7 @@ Scale a subtitle stream to match the main video in size before overlaying
 @end example
 @end itemize
 
+ at anchor{selectivecolor}
 @section selectivecolor
 
 Adjust cyan, magenta, yellow and black (CMYK) to certain ranges of colors (such
@@ -10764,7 +11681,6 @@ To change the display aspect ratio to 16:9, specify one of the following:
 @example
 setdar=dar=1.77777
 setdar=dar=16/9
-setdar=dar=1.77777
 @end example
 
 @item
@@ -11798,8 +12714,8 @@ Output:
 22222                           44444
 @end example
 
- at item drop_odd, 1
-Only output even frames, odd frames are dropped, generating a frame with
+ at item drop_even, 1
+Only output odd frames, even frames are dropped, generating a frame with
 unchanged height at half frame rate.
 
 @example
@@ -11813,14 +12729,14 @@ Frame 1         Frame 2         Frame 3         Frame 4
 11111           22222           33333           44444
 
 Output:
-                22222                           44444
-                22222                           44444
-                22222                           44444
-                22222                           44444
+11111                           33333
+11111                           33333
+11111                           33333
+11111                           33333
 @end example
 
- at item drop_even, 2
-Only output odd frames, even frames are dropped, generating a frame with
+ at item drop_odd, 2
+Only output even frames, odd frames are dropped, generating a frame with
 unchanged height at half frame rate.
 
 @example
@@ -11834,10 +12750,10 @@ Frame 1         Frame 2         Frame 3         Frame 4
 11111           22222           33333           44444
 
 Output:
-11111                           33333
-11111                           33333
-11111                           33333
-11111                           33333
+                22222                           44444
+                22222                           44444
+                22222                           44444
+                22222                           44444
 @end example
 
 @item pad, 3
@@ -11934,9 +12850,11 @@ Output:
  11111   11111   22222   22222   33333   33333   44444
 @end example
 
+
 @item mergex2, 7
 Move odd frames into the upper field, even into the lower field,
 generating a double height frame at same frame rate.
+
 @example
  ------> time
 Input:
@@ -12243,7 +13161,7 @@ same component color value on location in graph. This is the default mode.
 @item color
 Gray values are displayed on graph. Surrounding pixels values which are not
 present in video frame are drawn in gradient of 2 color components which are
-set by option @code{x} and @code{y}.
+set by option @code{x} and @code{y}. The 3rd color component is static.
 
 @item color2
 Actual color components values present in video frame are displayed on graph.
@@ -12257,6 +13175,10 @@ default values of @code{x} and @code{y}.
 Actual colors present in video frame are displayed on graph. If two different
 colors map to same position on graph then color with higher value of component
 not present in graph is picked.
+
+ at item color5
+Gray values are displayed on graph. Similar to @code{color} but with 3rd color
+component picked from radial gradient.
 @end table
 
 @item x
@@ -12266,7 +13188,7 @@ Set which color component will be represented on X-axis. Default is @code{1}.
 Set which color component will be represented on Y-axis. Default is @code{2}.
 
 @item intensity, i
-Set intensity, used by modes: gray, color and color3 for increasing brightness
+Set intensity, used by modes: gray, color, color3 and color5 for increasing brightness
 of color component which represents frequency of (X, Y) location in graph.
 
 @item envelope, e
@@ -12284,6 +13206,57 @@ can still spot out of range values without constantly looking at vectorscope.
 @item peak+instant
 Peak and instant envelope combined together.
 @end table
+
+ at item graticule, g
+Set what kind of graticule to draw.
+ at table @samp
+ at item none
+ at item green
+ at item color
+ at end table
+
+ at item opacity, o
+Set graticule opacity.
+
+ at item flags, f
+Set graticule flags.
+
+ at table @samp
+ at item white
+Draw graticule for white point.
+
+ at item black
+Draw graticule for black point.
+
+ at item name
+Draw color points short names.
+ at end table
+
+ at item bgopacity, b
+Set background opacity.
+
+ at item lthreshold, l
+Set low threshold for color component not represented on X or Y axis.
+Values lower than this value will be ignored. Default is 0.
+Note this value is multiplied with actual max possible value one pixel component
+can have. So for 8-bit input and low threshold value of 0.1 actual threshold
+is 0.1 * 255 = 25.
+
+ at item hthreshold, h
+Set high threshold for color component not represented on X or Y axis.
+Values higher than this value will be ignored. Default is 1.
+Note this value is multiplied with actual max possible value one pixel component
+can have. So for 8-bit input and high threshold value of 0.9 actual threshold
+is 0.9 * 255 = 230.
+
+ at item colorspace, c
+Set what kind of colorspace to use when drawing graticule.
+ at table @samp
+ at item auto
+ at item 601
+ at item 709
+ at end table
+Default is auto.
 @end table
 
 @anchor{vidstabdetect}
@@ -12737,10 +13710,14 @@ This display mode makes it easier to spot relative differences or similarities
 in overlapping areas of the color components that are supposed to be identical,
 such as neutral whites, grays, or blacks.
 
- at item parade
+ at item stack
 Display separate graph for the color components side by side in
 @code{row} mode or one below the other in @code{column} mode.
 
+ at item parade
+Display separate graph for the color components side by side in
+ at code{column} mode or one below the other in @code{row} mode.
+
 Using this display mode makes it easy to spot color casts in the highlights
 and shadows of an image, by comparing the contours of the top and the bottom
 graphs of each waveform. Since whites, grays, and blacks are characterized
@@ -12748,7 +13725,7 @@ by exactly equal amounts of red, green, and blue, neutral areas of the picture
 should display three waveforms of roughly equal width/height. If not, the
 correction is easy to perform by making level adjustments the three waveforms.
 @end table
-Default is @code{parade}.
+Default is @code{stack}.
 
 @item components, c
 Set which color components to display. Default is 1, which means only luminance
@@ -12786,12 +13763,47 @@ Similar as above, but shows difference between blue and red chroma.
 @item chroma
 Displays only chroma.
 
- at item achroma
-Similar as above, but shows difference between blue and red chroma.
-
 @item color
 Displays actual color value on waveform.
+
+ at item acolor
+Similar as above, but with luma showing frequency of chroma values.
+ at end table
+
+ at item graticule, g
+Set which graticule to display.
+
+ at table @samp
+ at item none
+Do not display graticule.
+
+ at item green
+Display green graticule showing legal broadcast ranges.
+ at end table
+
+ at item opacity, o
+Set graticule opacity.
+
+ at item flags, fl
+Set graticule flags.
+
+ at table @samp
+ at item numbers
+Draw numbers above lines. By default enabled.
+
+ at item dots
+Draw dots instead of lines.
+ at end table
+
+ at item scale, s
+Set scale used for displaying graticule.
+
+ at table @samp
+ at item digital
+ at item millivolts
+ at item ire
 @end table
+Default is digital.
 @end table
 
 @section xbr
@@ -13238,6 +14250,10 @@ The sample (pixel) aspect ratio of the input video.
 Specify the optional parameters to be used for the scale filter which
 is automatically inserted when an input change is detected in the
 input size or format.
+
+ at item hw_frames_ctx
+When using a hardware pixel format, this should be a reference to an
+AVHWFramesContext describing input frames.
 @end table
 
 For example:
@@ -13374,6 +14390,67 @@ cellauto=p='@@@@ @@ @@@@':s=100x400:full=0:rule=18
 
 @end itemize
 
+ at anchor{coreimagesrc}
+ at section coreimagesrc
+Video source generated on GPU using Apple's CoreImage API on OSX.
+
+This video source is a specialized version of the @ref{coreimage} video filter.
+Use a core image generator at the beginning of the applied filterchain to
+generate the content.
+
+The coreimagesrc video source accepts the following options:
+ at table @option
+ at item list_generators
+List all available generators along with all their respective options as well as
+possible minimum and maximum values along with the default values.
+ at example
+list_generators=true
+ at end example
+
+ at item size, s
+Specify the size of the sourced video. For the syntax of this option, check the
+ at ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}.
+The default value is @code{320x240}.
+
+ at item rate, r
+Specify the frame rate of the sourced video, as the number of frames
+generated per second. It has to be a string in the format
+ at var{frame_rate_num}/@var{frame_rate_den}, an integer number, a floating point
+number or a valid video frame rate abbreviation. The default value is
+"25".
+
+ at item sar
+Set the sample aspect ratio of the sourced video.
+
+ at item duration, d
+Set the duration of the sourced video. See
+ at ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils}
+for the accepted syntax.
+
+If not specified, or the expressed duration is negative, the video is
+supposed to be generated forever.
+ at end table
+
+Additionally, all options of the @ref{coreimage} video filter are accepted.
+A complete filterchain can be used for further processing of the
+generated input without CPU-HOST transfer. See @ref{coreimage} documentation
+and examples for details.
+
+ at subsection Examples
+
+ at itemize
+
+ at item
+Use CIQRCodeGenerator to create a QR code for the FFmpeg homepage,
+given as complete and escaped command-line for Apple's standard bash shell:
+ at example
+ffmpeg -f lavfi -i coreimagesrc=s=100x100:filter=CIQRCodeGenerator@@inputMessage=https\\\\\://FFmpeg.org/@@inputCorrectionLevel=H -frames:v 1 QRCode.png
+ at end example
+This example is equivalent to the QRCode example of @ref{coreimage} without the
+need for a nullsrc video source.
+ at end itemize
+
+
 @section mandelbrot
 
 Generate a Mandelbrot set fractal, and progressively zoom towards the
@@ -13673,7 +14750,8 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c
 @anchor{smptebars}
 @anchor{smptehdbars}
 @anchor{testsrc}
- at section allrgb, allyuv, color, haldclutsrc, nullsrc, rgbtestsrc, smptebars, smptehdbars, testsrc
+ at anchor{testsrc2}
+ at section allrgb, allyuv, color, haldclutsrc, nullsrc, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2
 
 The @code{allrgb} source returns frames of size 4096x4096 of all rgb colors.
 
@@ -13702,6 +14780,10 @@ The @code{testsrc} source generates a test video pattern, showing a
 color pattern, a scrolling gradient and a timestamp. This is mainly
 intended for testing purposes.
 
+The @code{testsrc2} source is similar to testsrc, but supports more
+pixel formats instead of just @code{rgb24}. This allows using it as an
+input for other tests without requiring a format conversion.
+
 The sources accept the following parameters:
 
 @table @option
@@ -14011,6 +15093,40 @@ ffplay -f lavfi 'amovie=input.mp3, asplit [a][out1];
 @end example
 @end itemize
 
+ at section bench, abench
+
+Benchmark part of a filtergraph.
+
+The filter accepts the following options:
+
+ at table @option
+ at item action
+Start or stop a timer.
+
+Available values are:
+ at table @samp
+ at item start
+Get the current time, set it as frame metadata (using the key
+ at code{lavfi.bench.start_time}), and forward the frame to the next filter.
+
+ at item stop
+Get the current time and fetch the @code{lavfi.bench.start_time} metadata from
+the input frame metadata to get the time difference. Time difference, average,
+maximum and minimum time (respectively @code{t}, @code{avg}, @code{max} and
+ at code{min}) are then printed. The timestamps are expressed in seconds.
+ at end table
+ at end table
+
+ at subsection Examples
+
+ at itemize
+ at item
+Benchmark @ref{selectivecolor} filter:
+ at example
+bench=start,selectivecolor=reds=-.2 .12 -.49,bench=stop
+ at end example
+ at end itemize
+
 @section concat
 
 Concatenate audio and video streams, joining them together one after the
@@ -14472,7 +15588,7 @@ select=between(t\,10\,20)
 @end example
 
 @item
-Select only I frames contained in the 10-20 time interval:
+Select only I-frames contained in the 10-20 time interval:
 @example
 select=between(t\,10\,20)*eq(pict_type\,I)
 @end example
@@ -15488,10 +16604,10 @@ Set video rate.
 Set border width, allowed range is [0, 5]. Default is 1.
 
 @item w
-Set channel width, allowed range is [80, 1080]. Default is 400.
+Set channel width, allowed range is [80, 8192]. Default is 400.
 
 @item h
-Set channel height, allowed range is [1, 100]. Default is 20.
+Set channel height, allowed range is [1, 900]. Default is 20.
 
 @item f
 Set fade, allowed range is [0.001, 1]. Default is 0.95.
@@ -15514,6 +16630,14 @@ If set, displays channel names. Default is enabled.
 
 @item v
 If set, displays volume values. Default is enabled.
+
+ at item o
+Set orientation, can be @code{horizontal} or @code{vertical},
+default is @code{horizontal}.
+
+ at item s
+Set step size, allowed range s [0, 5]. Default is 0, which means
+step is disabled.
 @end table
 
 @section showwaves
@@ -15620,14 +16744,6 @@ in a 1024x800 picture using @command{ffmpeg}:
 @example
 ffmpeg -i audio.flac -lavfi showwavespic=split_channels=1:s=1024x800 waveform.png
 @end example
-
- at item
-Colorize the waveform with colorchannelmixer. This example will make
-the waveform a green color approximately RGB(66,217,150). Additional
-channels will be shades of this color.
- at example
-ffmpeg -i audio.mp3 -filter_complex "showwavespic,colorchannelmixer=rr=66/255:gg=217/255:bb=150/255" waveform.png
- at end example
 @end itemize
 
 @section spectrumsynth
@@ -15857,6 +16973,11 @@ Default value is "1".
 
 Note that when the movie is looped the source timestamps are not
 changed, so it will generate non monotonically increasing timestamps.
+
+ at item discontinuity
+Specifies the time difference between frames above which the point is
+considered a timestamp discontinuity which is removed by adjusting the later
+timestamps.
 @end table
 
 It allows overlaying a second video on top of the main input of
@@ -15897,4 +17018,28 @@ movie=dvd.vob:s=v:0+#0x81 [video] [audio]
 @end example
 @end itemize
 
+ at subsection Commands
+
+Both movie and amovie support the following commands:
+ at table @option
+ at item seek
+Perform seek using "av_seek_frame".
+The syntax is: seek @var{stream_index}|@var{timestamp}|@var{flags}
+ at itemize
+ at item
+ at var{stream_index}: If stream_index is -1, a default
+stream is selected, and @var{timestamp} is automatically converted
+from AV_TIME_BASE units to the stream specific time_base.
+ at item
+ at var{timestamp}: Timestamp in AVStream.time_base units
+or, if no stream is specified, in AV_TIME_BASE units.
+ at item
+ at var{flags}: Flags which select direction and seeking mode.
+ at end itemize
+
+ at item get_duration
+Get movie duration in AV_TIME_BASE units.
+
+ at end table
+
 @c man end MULTIMEDIA SOURCES
diff --git a/doc/formats.texi b/doc/formats.texi
index 617cda5..f79ebe2 100644
--- a/doc/formats.texi
+++ b/doc/formats.texi
@@ -147,7 +147,7 @@ a packet for each stream, regardless of the maximum timestamp
 difference between the buffered packets.
 
 @item use_wallclock_as_timestamps @var{integer} (@emph{input})
-Use wallclock as timestamps.
+Use wallclock as timestamps if set to 1. Default is 0.
 
 @item avoid_negative_ts @var{integer} (@emph{output})
 
diff --git a/doc/general.texi b/doc/general.texi
index 59ea4f4..4db209f 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -520,6 +520,7 @@ library:
     @tab Multimedia format used in Westwood Studios games.
 @item Westwood Studios VQA      @tab   @tab X
     @tab Multimedia format used in Westwood Studios games.
+ at item Wideband Single-bit Data (WSD) @tab   @tab X
 @item WVE                       @tab   @tab X
 @item XMV                       @tab   @tab X
     @tab Microsoft video container used in Xbox games.
@@ -643,6 +644,7 @@ following image formats are supported:
 @item Bethesda VID video     @tab     @tab  X
     @tab Used in some games from Bethesda Softworks.
 @item Bink Video             @tab     @tab  X
+ at item BitJazz SheerVideo     @tab     @tab  X
 @item Bitmap Brothers JV video  @tab   @tab X
 @item y41p Brooktree uncompressed 4:1:1 12-bit     @tab  X  @tab  X
 @item Brute Force & Ignorance   @tab   @tab X
@@ -743,6 +745,7 @@ following image formats are supported:
 @item LucasArts SANM/Smush   @tab     @tab  X
     @tab Used in LucasArts games / SMUSH animations.
 @item lossless MJPEG         @tab  X  @tab  X
+ at item MagicYUV Lossless Video @tab     @tab  X
 @item Microsoft ATC Screen   @tab     @tab  X
     @tab Also known as Microsoft Screen 3.
 @item Microsoft Expression Encoder Screen  @tab     @tab  X
@@ -950,7 +953,7 @@ following image formats are supported:
 @item COOK                   @tab     @tab  X
     @tab All versions except 5.1 are supported.
 @item DCA (DTS Coherent Acoustics)  @tab  X  @tab  X
-    @tab supported extensions: XCh, XLL (partially)
+    @tab supported extensions: XCh, XXCH, X96, XBR, XLL, LBR (partially)
 @item DPCM id RoQ            @tab  X  @tab  X
     @tab Used in Quake III, Jedi Knight 2 and other computer games.
 @item DPCM Interplay         @tab     @tab  X
@@ -967,6 +970,7 @@ following image formats are supported:
 @item DSD (Direct Stream Digitial), least significant bit first, planar  @tab  @tab  X
 @item DSD (Direct Stream Digitial), most significant bit first, planar   @tab  @tab  X
 @item DSP Group TrueSpeech   @tab     @tab  X
+ at item DST (Direct Stream Transfer) @tab  @tab  X
 @item DV audio               @tab     @tab  X
 @item Enhanced AC-3          @tab  X  @tab  X
 @item EVRC (Enhanced Variable Rate Codec) @tab     @tab  X
diff --git a/doc/git-howto.texi b/doc/git-howto.texi
index e5e3c81..2b4fb80 100644
--- a/doc/git-howto.texi
+++ b/doc/git-howto.texi
@@ -408,7 +408,7 @@ with @option{--dry-run} first. And then inspecting the commits listed with
 @command{git log -p 1234567..987654}. The @command{git status} command
 may help in finding local changes that have been forgotten to be added.
 
-Next let the code pass through a full run of our testsuite.
+Next let the code pass through a full run of our test suite.
 
 @itemize
 @item @command{make distclean}
@@ -418,7 +418,7 @@ Next let the code pass through a full run of our testsuite.
 @end itemize
 
 Make sure all your changes have been checked before pushing them, the
-testsuite only checks against regressions and that only to some extend. It does
+test suite only checks against regressions and that only to some extend. It does
 obviously not check newly added features/code to be working unless you have
 added a test for that (which is recommended).
 
diff --git a/doc/muxers.texi b/doc/muxers.texi
index 2e6bb4c..c2ca0ba 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -174,30 +174,70 @@ ffmpeg -i INPUT -c:a pcm_u8 -c:v mpeg2video -f framecrc -
 
 See also the @ref{crc} muxer.
 
- at anchor{framemd5}
- at section framemd5
+ at anchor{framehash}
+ at section framehash
 
-Per-packet MD5 testing format.
+Per-packet hash testing format.
 
-This muxer computes and prints the MD5 hash for each audio
-and video packet. By default audio frames are converted to signed
-16-bit raw audio and video frames to raw video before computing the
-hash.
+This muxer computes and prints a cryptographic hash for each audio
+and video packet. This can be used for packet-by-packet equality
+checks without having to individually do a binary comparison on each.
+
+By default audio frames are converted to signed 16-bit raw audio and
+video frames to raw video before computing the hash, but the output
+of explicit conversions to other codecs can also be used. It uses the
+SHA-256 cryptographic hash function by default, but supports several
+other algorithms.
 
 The output of the muxer consists of a line for each audio and video
 packet of the form:
 @example
- at var{stream_index}, @var{packet_dts}, @var{packet_pts}, @var{packet_duration}, @var{packet_size}, @var{MD5}
+ at var{stream_index}, @var{packet_dts}, @var{packet_pts}, @var{packet_duration}, @var{packet_size}, @var{hash}
 @end example
 
- at var{MD5} is a hexadecimal number representing the computed MD5 hash
+ at var{hash} is a hexadecimal number representing the computed hash
 for the packet.
 
+ at table @option
+ at item hash @var{algorithm}
+Use the cryptographic hash function specified by the string @var{algorithm}.
+Supported values include @code{MD5}, @code{murmur3}, @code{RIPEMD128},
+ at code{RIPEMD160}, @code{RIPEMD256}, @code{RIPEMD320}, @code{SHA160},
+ at code{SHA224}, @code{SHA256} (default), @code{SHA512/224}, @code{SHA512/256},
+ at code{SHA384}, @code{SHA512}, @code{CRC32} and @code{adler32}.
+
+ at end table
+
 @subsection Examples
 
-For example to compute the MD5 of the audio and video frames in
- at file{INPUT}, converted to raw audio and video packets, and store it
-in the file @file{out.md5}:
+To compute the SHA-256 hash of the audio and video frames in @file{INPUT},
+converted to raw audio and video packets, and store it in the file
+ at file{out.sha256}:
+ at example
+ffmpeg -i INPUT -f framehash out.sha256
+ at end example
+
+To print the information to stdout, using the MD5 hash function, use
+the command:
+ at example
+ffmpeg -i INPUT -f framehash -hash md5 -
+ at end example
+
+See also the @ref{hash} muxer.
+
+ at anchor{framemd5}
+ at section framemd5
+
+Per-packet MD5 testing format.
+
+This is a variant of the @ref{framehash} muxer. Unlike that muxer,
+it defaults to using the MD5 hash function.
+
+ at subsection Examples
+
+To compute the MD5 hash of the audio and video frames in @file{INPUT},
+converted to raw audio and video packets, and store it in the file
+ at file{out.md5}:
 @example
 ffmpeg -i INPUT -f framemd5 out.md5
 @end example
@@ -207,7 +247,7 @@ To print the information to stdout, use the command:
 ffmpeg -i INPUT -f framemd5 -
 @end example
 
-See also the @ref{md5} muxer.
+See also the @ref{framehash} and @ref{md5} muxers.
 
 @anchor{gif}
 @section gif
@@ -243,6 +283,51 @@ ffmpeg -i INPUT -c:v gif -f image2 "out%d.gif"
 Note 2: the GIF format has a very small time base: the delay between two frames
 can not be smaller than one centi second.
 
+ at anchor{hash}
+ at section hash
+
+Hash testing format.
+
+This muxer computes and prints a cryptographic hash of all the input
+audio and video frames. This can be used for equality checks without
+having to do a complete binary comparison.
+
+By default audio frames are converted to signed 16-bit raw audio and
+video frames to raw video before computing the hash, but the output
+of explicit conversions to other codecs can also be used. Timestamps
+are ignored. It uses the SHA-256 cryptographic hash function by default,
+but supports several other algorithms.
+
+The output of the muxer consists of a single line of the form:
+ at var{algo}=@var{hash}, where @var{algo} is a short string representing
+the hash function used, and @var{hash} is a hexadecimal number
+representing the computed hash.
+
+ at table @option
+ at item hash @var{algorithm}
+Use the cryptographic hash function specified by the string @var{algorithm}.
+Supported values include @code{MD5}, @code{murmur3}, @code{RIPEMD128},
+ at code{RIPEMD160}, @code{RIPEMD256}, @code{RIPEMD320}, @code{SHA160},
+ at code{SHA224}, @code{SHA256} (default), @code{SHA512/224}, @code{SHA512/256},
+ at code{SHA384}, @code{SHA512}, @code{CRC32} and @code{adler32}.
+
+ at end table
+
+ at subsection Examples
+
+To compute the SHA-256 hash of the input converted to raw audio and
+video, and store it in the file @file{out.sha256}:
+ at example
+ffmpeg -i INPUT -f hash out.sha256
+ at end example
+
+To print an MD5 hash to stdout use the command:
+ at example
+ffmpeg -i INPUT -f hash -hash md5 -
+ at end example
+
+See also the @ref{framehash} muxer.
+
 @anchor{hls}
 @section hls
 
@@ -273,7 +358,8 @@ This muxer supports the following options:
 
 @table @option
 @item hls_time @var{seconds}
-Set the segment length in seconds. Default value is 2.
+Set the target segment length in seconds. Default value is 2.
+Segment will be cut on the next key frame after this time has passed.
 
 @item hls_list_size @var{size}
 Set the maximum number of playlist entries. If set to 0 the list file
@@ -318,6 +404,26 @@ ffmpeg in.nut -hls_segment_filename 'file%03d.ts' out.m3u8
 This example will produce the playlist, @file{out.m3u8}, and segment files:
 @file{file000.ts}, @file{file001.ts}, @file{file002.ts}, etc.
 
+ at item use_localtime
+Use strftime on @var{filename} to expand the segment filename with localtime.
+The segment number (%d) is not available in this mode.
+ at example
+ffmpeg in.nut -use_localtime 1 -hls_segment_filename 'file-%Y%m%d-%s.ts' out.m3u8
+ at end example
+This example will produce the playlist, @file{out.m3u8}, and segment files:
+ at file{file-20160215-1455569023.ts}, @file{file-20160215-1455569024.ts}, etc.
+
+ at item use_localtime_mkdir
+Used together with -use_localtime, it will create up to one subdirectory which
+is expanded in @var{filename}.
+ at example
+ffmpeg in.nut -use_localtime 1 -use_localtime_mkdir 1 -hls_segment_filename '%Y%m%d/file-%Y%m%d-%s.ts' out.m3u8
+ at end example
+This example will create a directory 201560215 (if it does not exist), and then
+produce the playlist, @file{out.m3u8}, and segment files:
+ at file{201560215/file-20160215-1455569023.ts}, @file{201560215/file-20160215-1455569024.ts}, etc.
+
+
 @item hls_key_info_file @var{key_info_file}
 Use the information in @var{key_info_file} for segment encryption. The first
 line of @var{key_info_file} specifies the key URI written to the playlist. The
@@ -388,6 +494,14 @@ Will produce the playlist, @file{out.m3u8}, and a single segment file,
 @item hls_flags delete_segments
 Segment files removed from the playlist are deleted after a period of time
 equal to the duration of the segment plus the duration of the playlist.
+
+ at item hls_playlist_type event
+Emit @code{#EXT-X-PLAYLIST-TYPE:EVENT} in the m3u8 header. Forces
+ at option{hls_list_size} to 0; the playlist can only be appended to.
+
+ at item hls_playlist_type vod
+Emit @code{#EXT-X-PLAYLIST-TYPE:VOD} in the m3u8 header. Forces
+ at option{hls_list_size} to 0; the playlist must not change.
 @end table
 
 @anchor{ico}
@@ -601,16 +715,12 @@ have no effect if it is not.
 
 MD5 testing format.
 
-This muxer computes and prints the MD5 hash of all the input audio
-and video frames. By default audio frames are converted to signed
-16-bit raw audio and video frames to raw video before computing the
-hash. Timestamps are ignored.
+This is a variant of the @ref{hash} muxer. Unlike that muxer, it
+defaults to using the MD5 hash function.
 
-The output of the muxer consists of a single line of the form:
-MD5=@var{MD5}, where @var{MD5} is a hexadecimal number representing
-the computed MD5 hash.
+ at subsection Examples
 
-For example to compute the MD5 hash of the input converted to raw
+To compute the MD5 hash of the input converted to raw
 audio and video, and store it in the file @file{out.md5}:
 @example
 ffmpeg -i INPUT -f md5 out.md5
@@ -621,7 +731,7 @@ You can print the MD5 to stdout with the command:
 ffmpeg -i INPUT -f md5 -
 @end example
 
-See also the @ref{framemd5} muxer.
+See also the @ref{hash} and @ref{framemd5} muxers.
 
 @section mov, mp4, ismv
 
@@ -798,41 +908,41 @@ and @code{service_name}. If they are not set the default for
 The muxer options are:
 
 @table @option
- at item -mpegts_original_network_id @var{number}
+ at item mpegts_original_network_id @var{number}
 Set the original_network_id (default 0x0001). This is unique identifier
 of a network in DVB. Its main use is in the unique identification of a
 service through the path Original_Network_ID, Transport_Stream_ID.
- at item -mpegts_transport_stream_id @var{number}
+ at item mpegts_transport_stream_id @var{number}
 Set the transport_stream_id (default 0x0001). This identifies a
 transponder in DVB.
- at item -mpegts_service_id @var{number}
+ at item mpegts_service_id @var{number}
 Set the service_id (default 0x0001) also known as program in DVB.
- at item -mpegts_service_type @var{number}
+ at item mpegts_service_type @var{number}
 Set the program service_type (default @var{digital_tv}), see below
 a list of pre defined values.
- at item -mpegts_pmt_start_pid @var{number}
+ at item mpegts_pmt_start_pid @var{number}
 Set the first PID for PMT (default 0x1000, max 0x1f00).
- at item -mpegts_start_pid @var{number}
+ at item mpegts_start_pid @var{number}
 Set the first PID for data packets (default 0x0100, max 0x0f00).
- at item -mpegts_m2ts_mode @var{number}
+ at item mpegts_m2ts_mode @var{number}
 Enable m2ts mode if set to 1. Default value is -1 which disables m2ts mode.
- at item -muxrate @var{number}
+ at item muxrate @var{number}
 Set a constant muxrate (default VBR).
- at item -pcr_period @var{numer}
+ at item pcr_period @var{numer}
 Override the default PCR retransmission time (default 20ms), ignored
 if variable muxrate is selected.
 @item pat_period @var{number}
 Maximal time in seconds between PAT/PMT tables.
 @item sdt_period @var{number}
 Maximal time in seconds between SDT tables.
- at item -pes_payload_size @var{number}
+ at item pes_payload_size @var{number}
 Set minimum PES packet payload in bytes.
- at item -mpegts_flags @var{flags}
+ at item mpegts_flags @var{flags}
 Set flags (see below).
- at item -mpegts_copyts @var{number}
+ at item mpegts_copyts @var{number}
 Preserve original timestamps, if value is set to 1. Default value is -1, which
 results in shifting timestamps so that they start from 0.
- at item -tables_version @var{number}
+ at item tables_version @var{number}
 Set PAT, PMT and SDT version (default 0, valid values are from 0 to 31, inclusively).
 This option allows updating stream structure so that standard consumer may
 detect the change. To do so, reopen output AVFormatContext (in case of API
@@ -848,7 +958,7 @@ ffmpeg -i source2.ts -codec copy -f mpegts -tables_version 1 udp://1.1.1.1:1111
 @end example
 @end table
 
-Option mpegts_service_type accepts the following values:
+Option @option{mpegts_service_type} accepts the following values:
 
 @table @option
 @item hex_value
@@ -869,7 +979,7 @@ Advanced Codec Digital SDTV service.
 Advanced Codec Digital HDTV service.
 @end table
 
-Option mpegts_flags may take a set of such flags:
+Option @option{mpegts_flags} may take a set of such flags:
 
 @table @option
 @item resend_headers
@@ -1017,6 +1127,12 @@ implementation for HLS segmentation.
 The segment muxer supports the following options:
 
 @table @option
+ at item increment_tc @var{1|0}
+if set to @code{1}, increment timecode between each segment
+If this is selected, the input need to have
+a timecode in the first video stream. Default value is
+ at code{0}.
+
 @item reference_stream @var{specifier}
 Set the reference stream, as specified by the string @var{specifier}.
 If @var{specifier} is set to @code{auto}, the reference is chosen
@@ -1204,6 +1320,11 @@ muxers/codecs. It is set to @code{0} by default.
 @item initial_offset @var{offset}
 Specify timestamp offset to apply to the output packet timestamps. The
 argument must be a time duration specification, and defaults to 0.
+
+ at item write_empty_segments @var{1|0}
+If enabled, write an empty segment if there are no packets during the period a
+segment would usually span. Otherwise, the segment will be filled with the next
+packet written. Defaults to @code{0}.
 @end table
 
 @subsection Examples
@@ -1333,6 +1454,12 @@ Select the streams that should be mapped to the slave output,
 specified by a stream specifier. If not specified, this defaults to
 all the input streams. You may use multiple stream specifiers
 separated by commas (@code{,}) e.g.: @code{a:0,v}
+
+ at item onfail
+Specify behaviour on output failure. This can be set to either @code{abort} (which is
+default) or @code{ignore}. @code{abort} will cause whole process to fail in case of failure
+on this slave output. @code{ignore} will ignore failure on this output, so other outputs
+will continue without being affected.
 @end table
 
 @subsection Examples
@@ -1347,6 +1474,14 @@ ffmpeg -i ... -c:v libx264 -c:a mp2 -f tee -map 0:v -map 0:a
 @end example
 
 @item
+As above, but continue streaming even if output to local file fails
+(for example local drive fills up):
+ at example
+ffmpeg -i ... -c:v libx264 -c:a mp2 -f tee -map 0:v -map 0:a
+  "[onfail=ignore]archive-20121107.mkv|[f=mpegts]udp://10.0.1.255:1234/"
+ at end example
+
+ at item
 Use @command{ffmpeg} to encode the input, and send the output
 to three different destinations. The @code{dump_extra} bitstream
 filter is used to add extradata information to all the output video
diff --git a/doc/nut.texi b/doc/nut.texi
index a02f86a..f9b18f5 100644
--- a/doc/nut.texi
+++ b/doc/nut.texi
@@ -34,7 +34,7 @@ NUT has some variants signaled by using the flags field in its main header.
 
 The BROADCAST variant provides a secondary time reference to facilitate
 detecting endpoint latency and network delays.
-It assumes all the endpoint clocks are syncronized.
+It assumes all the endpoint clocks are synchronized.
 To be used in real-time scenarios.
 
 @section PIPE
diff --git a/doc/optimization.txt b/doc/optimization.txt
index 1a0b98c..b4b0a06 100644
--- a/doc/optimization.txt
+++ b/doc/optimization.txt
@@ -7,7 +7,7 @@ If you plan to do non-x86 architecture specific optimizations (SIMD normally),
 then take a look in the x86/ directory, as most important functions are
 already optimized for MMX.
 
-If you want to do x86 optimizations then you can either try to finetune the
+If you want to do x86 optimizations then you can either try to fine-tune the
 stuff in the x86 directory or find some other functions in the C source to
 optimize, but there aren't many left.
 
@@ -163,7 +163,7 @@ general x86 registers (e.g. eax) as well as XMM registers. This last one is
 particularly important on Win64, where xmm6-15 are callee-save, and not
 restoring their contents leads to undefined results. In external asm (e.g.
 yasm), you do this by using:
-cglobal functon_name, num_args, num_regs, num_xmm_regs
+cglobal function_name, num_args, num_regs, num_xmm_regs
 In inline asm, you specify clobbered registers at the end of your asm:
 __asm__(".." ::: "%eax").
 If gcc is not set to support sse (-msse) it will not accept xmm registers
diff --git a/doc/platform.texi b/doc/platform.texi
index f7ee456..21b135f 100644
--- a/doc/platform.texi
+++ b/doc/platform.texi
@@ -63,7 +63,7 @@ bash ./configure
 @section Darwin (Mac OS X, iPhone)
 
 The toolchain provided with Xcode is sufficient to build the basic
-unacelerated code.
+unaccelerated code.
 
 Mac OS X on PowerPC or ARM (iPhone) requires a preprocessor from
 @url{https://github.com/FFmpeg/gas-preprocessor} or
@@ -144,7 +144,7 @@ pacman -S make pkgconf diffutils
 pacman -S mingw-w64-x86_64-yasm mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL
 @end example
 
-To target 32bit replace the @code{x86_64} with @code{i686} in the command above.
+To target 32 bits replace @code{x86_64} with @code{i686} in the command above.
 
 @section Microsoft Visual C++ or Intel C++ Compiler for Windows
 
diff --git a/doc/protocols.texi b/doc/protocols.texi
index 375d042..72b3914 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -36,6 +36,14 @@ particular protocol using the option
 The option "-protocols" of the ff* tools will display the list of
 supported protocols.
 
+All protocols accept the following options:
+
+ at table @option
+ at item rw_timeout
+Maximum time to wait for (network) read/write operations to complete,
+in microseconds.
+ at end table
+
 A description of the currently available protocols follows.
 
 @section async
@@ -216,6 +224,17 @@ it, unless special care is taken (tests, customized server configuration
 etc.). Different FTP servers behave in different way during seek
 operation. ff* tools may produce incomplete content due to server limitations.
 
+This protocol accepts the following options:
+
+ at table @option
+ at item follow
+If set to 1, the protocol will retry reading at the end of the file, allowing
+reading files that still are being written. In order for this to terminate,
+you either need to use the rw_timeout option, or use the interrupt callback
+(for API users).
+
+ at end table
+
 @section gopher
 
 Gopher protocol.
@@ -1266,6 +1285,14 @@ Set the UDP maximum socket buffer size in bytes. This is used to set either
 the receive or send buffer size, depending on what the socket is used for.
 Default is 64KB.  See also @var{fifo_size}.
 
+ at item bitrate=@var{bitrate}
+If set to nonzero, the output will have the specified constant bitrate if the
+input has enough packets to sustain it.
+
+ at item burst_bits=@var{bits}
+When using @var{bitrate} this specifies the maximum number of bits in
+packet bursts.
+
 @item localport=@var{port}
 Override the local UDP port to bind with.
 
diff --git a/doc/resampler.texi b/doc/resampler.texi
index cb7d536..d72677c 100644
--- a/doc/resampler.texi
+++ b/doc/resampler.texi
@@ -120,8 +120,8 @@ select the native SW Resampler; filter options precision and cheby are not
 applicable in this case.
 @item soxr
 select the SoX Resampler (where available); compensation, and filter options
-filter_size, phase_shift, filter_type & kaiser_beta, are not applicable in this
-case.
+filter_size, phase_shift, exact_rational, filter_type & kaiser_beta, are not
+applicable in this case.
 @end table
 
 @item filter_size
@@ -134,6 +134,11 @@ the interval [0,30].
 @item linear_interp
 Use linear interpolation if set to 1, default value is 0.
 
+ at item exact_rational
+For swr only, when enabled, try to use exact phase_count based on input and
+output sample rate. However, if it is larger than @code{1 << phase_shift},
+the phase_count will be @code{1 << phase_shift} as fallback. Default is disabled.
+
 @item cutoff
 Set cutoff frequency (swr: 6dB point; soxr: 0dB point) ratio; must be a float
 value between 0 and 1.  Default value is 0.97 with swr, and 0.91 with soxr
diff --git a/doc/snow.txt b/doc/snow.txt
index 9d5778d..bbf28bc 100644
--- a/doc/snow.txt
+++ b/doc/snow.txt
@@ -527,7 +527,7 @@ Wavelet Transform:
 ==================
 
 Snow supports 2 wavelet transforms, the symmetric biorthogonal 5/3 integer
-transform and a integer approximation of the symmetric biorthogonal 9/7
+transform and an integer approximation of the symmetric biorthogonal 9/7
 daubechies wavelet.
 
 2D IDWT (inverse discrete wavelet transform)
diff --git a/doc/swscale.txt b/doc/swscale.txt
index 2066009..dbb4e29 100644
--- a/doc/swscale.txt
+++ b/doc/swscale.txt
@@ -10,12 +10,12 @@ Current (simplified) Architecture:
                /                       \
        special converter     [Input to YUV converter]
               |                         |
-              |          (8bit YUV 4:4:4 / 4:2:2 / 4:2:0 / 4:0:0 )
+              |         (8-bit YUV 4:4:4 / 4:2:2 / 4:2:0 / 4:0:0 )
               |                         |
               |                         v
               |                  Horizontal scaler
               |                         |
-              |      (15bit YUV 4:4:4 / 4:2:2 / 4:2:0 / 4:1:1 / 4:0:0 )
+              |     (15-bit YUV 4:4:4 / 4:2:2 / 4:2:0 / 4:1:1 / 4:0:0 )
               |                         |
               |                         v
               |          Vertical scaler and output converter
diff --git a/ffmpeg.c b/ffmpeg.c
index a5ec3c3..9ffd833 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -197,15 +197,15 @@ static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h,
     }
 
     dst += r->y * dst_linesize + r->x * 4;
-    src = r->pict.data[0];
-    pal = (uint32_t *)r->pict.data[1];
+    src = r->data[0];
+    pal = (uint32_t *)r->data[1];
     for (y = 0; y < r->h; y++) {
         dst2 = (uint32_t *)dst;
         src2 = src;
         for (x = 0; x < r->w; x++)
             *(dst2++) = pal[*(src2++)];
         dst += dst_linesize;
-        src += r->pict.linesize[0];
+        src += r->linesize[0];
     }
 }
 
@@ -694,6 +694,17 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
         if (exit_on_error)
             exit_program(1);
     }
+    if (pkt->size == 0 && pkt->side_data_elems == 0)
+        return;
+    if (!ost->st->codecpar->extradata && avctx->extradata) {
+        ost->st->codecpar->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
+        if (!ost->st->codecpar->extradata) {
+            av_log(NULL, AV_LOG_ERROR, "Could not allocate extradata buffer to copy parser data.\n");
+            exit_program(1);
+        }
+        ost->st->codecpar->extradata_size = avctx->extradata_size;
+        memcpy(ost->st->codecpar->extradata, avctx->extradata, avctx->extradata_size);
+    }
 
     if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
         if (pkt->dts != AV_NOPTS_VALUE &&
@@ -710,6 +721,7 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
      if(
         (avctx->codec_type == AVMEDIA_TYPE_AUDIO || avctx->codec_type == AVMEDIA_TYPE_VIDEO) &&
         pkt->dts != AV_NOPTS_VALUE &&
+        !(avctx->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) &&
         ost->last_mux_dts != AV_NOPTS_VALUE) {
       int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
       if (pkt->dts < max) {
@@ -1910,7 +1922,7 @@ int guess_input_channel_layout(InputStream *ist)
             return 0;
         av_get_channel_layout_string(layout_name, sizeof(layout_name),
                                      dec->channels, dec->channel_layout);
-        av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for  Input Stream "
+        av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream "
                "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name);
     }
     return 1;
@@ -2123,8 +2135,12 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
     ist->hwaccel_retrieved_pix_fmt = decoded_frame->format;
 
     best_effort_timestamp= av_frame_get_best_effort_timestamp(decoded_frame);
-    if(best_effort_timestamp != AV_NOPTS_VALUE)
-        ist->next_pts = ist->pts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q);
+    if(best_effort_timestamp != AV_NOPTS_VALUE) {
+        int64_t ts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q);
+
+        if (ts != AV_NOPTS_VALUE)
+            ist->next_pts = ist->pts = ts;
+    }
 
     if (debug_ts) {
         av_log(NULL, AV_LOG_INFO, "decoder -> ist_index:%d type:video "
@@ -2543,6 +2559,8 @@ static int init_input_stream(int ist_index, char *error, int error_len)
                 av_log(NULL, AV_LOG_WARNING, "Warning using DVB subtitles for filtering and output at the same time is not fully supported, also see -compute_edt [0|1]\n");
         }
 
+        av_dict_set(&ist->decoder_opts, "sub_text_format", "ass", AV_DICT_DONT_OVERWRITE);
+
         if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0))
             av_dict_set(&ist->decoder_opts, "threads", "auto", 0);
         if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) {
@@ -2603,6 +2621,12 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
             !av_dict_get(ost->encoder_opts, "ab", NULL, 0))
             av_dict_set(&ost->encoder_opts, "b", "128000", 0);
 
+        if (ost->filter && ost->filter->filter->inputs[0]->hw_frames_ctx) {
+            ost->enc_ctx->hw_frames_ctx = av_buffer_ref(ost->filter->filter->inputs[0]->hw_frames_ctx);
+            if (!ost->enc_ctx->hw_frames_ctx)
+                return AVERROR(ENOMEM);
+        }
+
         if ((ret = avcodec_open2(ost->enc_ctx, codec, &ost->encoder_opts)) < 0) {
             if (ret == AVERROR_EXPERIMENTAL)
                 abort_codec_experimental(codec, 1);
@@ -2654,7 +2678,7 @@ static int init_output_stream(OutputStream *ost, char *error, int error_len)
         ost->st->time_base = av_add_q(ost->enc_ctx->time_base, (AVRational){0, 1});
         ost->st->codec->codec= ost->enc_ctx->codec;
     } else {
-        ret = av_opt_set_dict(ost->enc_ctx, &ost->encoder_opts);
+        ret = av_opt_set_dict(ost->st->codec, &ost->encoder_opts);
         if (ret < 0) {
            av_log(NULL, AV_LOG_FATAL,
                   "Error setting up codec context options.\n");
@@ -2893,7 +2917,8 @@ static int transcode_init(void)
              * overhead
              */
             if(!strcmp(oc->oformat->name, "avi")) {
-                if ( copy_tb<0 && av_q2d(ist->st->r_frame_rate) >= av_q2d(ist->st->avg_frame_rate)
+                if ( copy_tb<0 && ist->st->r_frame_rate.num
+                               && av_q2d(ist->st->r_frame_rate) >= av_q2d(ist->st->avg_frame_rate)
                                && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(ist->st->time_base)
                                && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(dec_ctx->time_base)
                                && av_q2d(ist->st->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500
@@ -2987,6 +3012,10 @@ static int transcode_init(void)
                 break;
             case AVMEDIA_TYPE_VIDEO:
                 enc_ctx->pix_fmt            = dec_ctx->pix_fmt;
+                enc_ctx->colorspace         = dec_ctx->colorspace;
+                enc_ctx->color_range        = dec_ctx->color_range;
+                enc_ctx->color_primaries    = dec_ctx->color_primaries;
+                enc_ctx->color_trc          = dec_ctx->color_trc;
                 enc_ctx->width              = dec_ctx->width;
                 enc_ctx->height             = dec_ctx->height;
                 enc_ctx->has_b_frames       = dec_ctx->has_b_frames;
@@ -3034,6 +3063,11 @@ static int transcode_init(void)
                 exit_program(1);
 #endif
 
+#if CONFIG_CUVID
+            if (cuvid_transcode_init(ost))
+                exit_program(1);
+#endif
+
             if (!ost->filter &&
                 (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO ||
                  enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO)) {
@@ -3194,13 +3228,6 @@ static int transcode_init(void)
         }
     }
 
-    /* open each encoder */
-    for (i = 0; i < nb_output_streams; i++) {
-        ret = init_output_stream(output_streams[i], error, sizeof(error));
-        if (ret < 0)
-            goto dump_format;
-    }
-
     /* init input streams */
     for (i = 0; i < nb_input_streams; i++)
         if ((ret = init_input_stream(i, error, sizeof(error))) < 0) {
@@ -3211,6 +3238,13 @@ static int transcode_init(void)
             goto dump_format;
         }
 
+    /* open each encoder */
+    for (i = 0; i < nb_output_streams; i++) {
+        ret = init_output_stream(output_streams[i], error, sizeof(error));
+        if (ret < 0)
+            goto dump_format;
+    }
+
     /* discard unused programs */
     for (i = 0; i < nb_input_files; i++) {
         InputFile *ifile = input_files[i];
@@ -4189,6 +4223,8 @@ static int transcode(void)
         }
     }
 
+    av_buffer_unref(&hw_device_ctx);
+
     /* finished ! */
     ret = 0;
 
diff --git a/ffmpeg.h b/ffmpeg.h
index 20322b0..f09d33b 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -65,6 +65,8 @@ enum HWAccelID {
     HWACCEL_VDA,
     HWACCEL_VIDEOTOOLBOX,
     HWACCEL_QSV,
+    HWACCEL_VAAPI,
+    HWACCEL_CUVID,
 };
 
 typedef struct HWAccel {
@@ -126,6 +128,8 @@ typedef struct OptionsContext {
     int        nb_hwaccels;
     SpecifierOpt *hwaccel_devices;
     int        nb_hwaccel_devices;
+    SpecifierOpt *hwaccel_output_formats;
+    int        nb_hwaccel_output_formats;
     SpecifierOpt *autorotate;
     int        nb_autorotate;
 
@@ -325,6 +329,7 @@ typedef struct InputStream {
     /* hwaccel options */
     enum HWAccelID hwaccel_id;
     char  *hwaccel_device;
+    enum AVPixelFormat hwaccel_output_format;
 
     /* hwaccel context */
     enum HWAccelID active_hwaccel_id;
@@ -334,6 +339,7 @@ typedef struct InputStream {
     int  (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame);
     enum AVPixelFormat hwaccel_pix_fmt;
     enum AVPixelFormat hwaccel_retrieved_pix_fmt;
+    AVBufferRef *hw_frames_ctx;
 
     /* stats */
     // combined size of all the packets read
@@ -538,13 +544,14 @@ extern int stdin_interaction;
 extern int frame_bits_per_raw_sample;
 extern AVIOContext *progress_avio;
 extern float max_error_rate;
-extern int vdpau_api_ver;
 extern char *videotoolbox_pixfmt;
 
 extern const AVIOInterruptCB int_cb;
 
 extern const OptionDef options[];
 extern const HWAccel hwaccels[];
+extern int hwaccel_lax_profile_check;
+extern AVBufferRef *hw_device_ctx;
 
 
 void term_init(void);
@@ -577,5 +584,9 @@ int vda_init(AVCodecContext *s);
 int videotoolbox_init(AVCodecContext *s);
 int qsv_init(AVCodecContext *s);
 int qsv_transcode_init(OutputStream *ost);
+int vaapi_decode_init(AVCodecContext *avctx);
+int vaapi_device_init(const char *device);
+int cuvid_init(AVCodecContext *s);
+int cuvid_transcode_init(OutputStream *ost);
 
 #endif /* FFMPEG_H */
diff --git a/ffmpeg_cuvid.c b/ffmpeg_cuvid.c
new file mode 100644
index 0000000..7fb47a2
--- /dev/null
+++ b/ffmpeg_cuvid.c
@@ -0,0 +1,237 @@
+/*
+ * 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/hwcontext.h"
+#include "libavutil/hwcontext_cuda.h"
+
+#include "ffmpeg.h"
+
+#include <cuda.h>
+#include <nvcuvid.h>
+
+typedef struct CUVIDContext {
+    AVBufferRef *hw_frames_ctx;
+} CUVIDContext;
+
+static void cuvid_uninit(AVCodecContext *avctx)
+{
+    InputStream  *ist = avctx->opaque;
+    CUVIDContext *ctx = ist->hwaccel_ctx;
+
+    if (ctx) {
+        av_buffer_unref(&ctx->hw_frames_ctx);
+        av_freep(&ctx);
+    }
+
+    av_buffer_unref(&ist->hw_frames_ctx);
+
+    ist->hwaccel_ctx = 0;
+    ist->hwaccel_uninit = 0;
+}
+
+int cuvid_init(AVCodecContext *avctx)
+{
+    InputStream  *ist = avctx->opaque;
+    CUVIDContext *ctx = ist->hwaccel_ctx;
+
+    av_log(NULL, AV_LOG_TRACE, "Initializing cuvid hwaccel\n");
+
+    if (!ctx) {
+        av_log(NULL, AV_LOG_ERROR, "CUVID transcoding is not initialized. "
+               "-hwaccel cuvid should only be used for one-to-one CUVID transcoding "
+               "with no (software) filters.\n");
+        return AVERROR(EINVAL);
+    }
+
+    return 0;
+}
+
+static void cuvid_ctx_free(AVHWDeviceContext *ctx)
+{
+    AVCUDADeviceContext *hwctx = ctx->hwctx;
+    cuCtxDestroy(hwctx->cuda_ctx);
+}
+
+int cuvid_transcode_init(OutputStream *ost)
+{
+    InputStream *ist;
+    const enum AVPixelFormat *pix_fmt;
+    AVCUDADeviceContext *device_hwctx;
+    AVHWDeviceContext *device_ctx;
+    AVHWFramesContext *hwframe_ctx;
+    CUVIDContext *ctx = NULL;
+    CUdevice device;
+    CUcontext cuda_ctx = NULL;
+    CUcontext dummy;
+    CUresult err;
+    int ret = 0;
+
+    av_log(NULL, AV_LOG_TRACE, "Initializing cuvid transcoding\n");
+
+    if (ost->source_index < 0)
+        return 0;
+
+    ist = input_streams[ost->source_index];
+
+    /* check if the encoder supports CUVID */
+    if (!ost->enc->pix_fmts)
+        goto cancel;
+    for (pix_fmt = ost->enc->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++)
+        if (*pix_fmt == AV_PIX_FMT_CUDA)
+            break;
+    if (*pix_fmt == AV_PIX_FMT_NONE)
+        goto cancel;
+
+    /* check if the decoder supports CUVID */
+    if (ist->hwaccel_id != HWACCEL_CUVID || !ist->dec || !ist->dec->pix_fmts)
+        goto cancel;
+    for (pix_fmt = ist->dec->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++)
+        if (*pix_fmt == AV_PIX_FMT_CUDA)
+            break;
+    if (*pix_fmt == AV_PIX_FMT_NONE)
+        goto cancel;
+
+    av_log(NULL, AV_LOG_VERBOSE, "Setting up CUVID transcoding\n");
+
+    if (ist->hwaccel_ctx) {
+        ctx = ist->hwaccel_ctx;
+    } else {
+        ctx = av_mallocz(sizeof(*ctx));
+        if (!ctx) {
+            ret = AVERROR(ENOMEM);
+            goto error;
+        }
+    }
+
+    if (!hw_device_ctx) {
+        hw_device_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA);
+        if (!hw_device_ctx) {
+            av_log(NULL, AV_LOG_ERROR, "av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA) failed\n");
+            ret = AVERROR(ENOMEM);
+            goto error;
+        }
+
+        err = cuInit(0);
+        if (err != CUDA_SUCCESS) {
+            av_log(NULL, AV_LOG_ERROR, "Could not initialize the CUDA driver API\n");
+            ret = AVERROR_UNKNOWN;
+            goto error;
+        }
+
+        err = cuDeviceGet(&device, 0); ///TODO: Make device index configurable
+        if (err != CUDA_SUCCESS) {
+            av_log(NULL, AV_LOG_ERROR, "Could not get the device number %d\n", 0);
+            ret = AVERROR_UNKNOWN;
+            goto error;
+        }
+
+        err = cuCtxCreate(&cuda_ctx, CU_CTX_SCHED_BLOCKING_SYNC, device);
+        if (err != CUDA_SUCCESS) {
+            av_log(NULL, AV_LOG_ERROR, "Error creating a CUDA context\n");
+            ret = AVERROR_UNKNOWN;
+            goto error;
+        }
+
+        device_ctx = (AVHWDeviceContext*)hw_device_ctx->data;
+        device_ctx->free = cuvid_ctx_free;
+
+        device_hwctx = device_ctx->hwctx;
+        device_hwctx->cuda_ctx = cuda_ctx;
+
+        err = cuCtxPopCurrent(&dummy);
+        if (err != CUDA_SUCCESS) {
+            av_log(NULL, AV_LOG_ERROR, "cuCtxPopCurrent failed\n");
+            ret = AVERROR_UNKNOWN;
+            goto error;
+        }
+
+        ret = av_hwdevice_ctx_init(hw_device_ctx);
+        if (ret < 0) {
+            av_log(NULL, AV_LOG_ERROR, "av_hwdevice_ctx_init failed\n");
+            goto error;
+        }
+    } else {
+        device_ctx = (AVHWDeviceContext*)hw_device_ctx->data;
+        device_hwctx = device_ctx->hwctx;
+        cuda_ctx = device_hwctx->cuda_ctx;
+    }
+
+    if (device_ctx->type != AV_HWDEVICE_TYPE_CUDA) {
+        av_log(NULL, AV_LOG_ERROR, "Hardware device context is already initialized for a diffrent hwaccel.\n");
+        ret = AVERROR(EINVAL);
+        goto error;
+    }
+
+    if (!ctx->hw_frames_ctx) {
+        ctx->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx);
+        if (!ctx->hw_frames_ctx) {
+            av_log(NULL, AV_LOG_ERROR, "av_hwframe_ctx_alloc failed\n");
+            ret = AVERROR(ENOMEM);
+            goto error;
+        }
+    }
+
+    /* This is a bit hacky, av_hwframe_ctx_init is called by the cuvid decoder
+     * once it has probed the neccesary format information. But as filters/nvenc
+     * need to know the format/sw_format, set them here so they are happy.
+     * This is fine as long as CUVID doesn't add another supported pix_fmt.
+     */
+    hwframe_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
+    hwframe_ctx->format = AV_PIX_FMT_CUDA;
+    hwframe_ctx->sw_format = AV_PIX_FMT_NV12;
+
+    ost->hwaccel_ctx = ctx;
+    ost->enc_ctx->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx);
+    ost->enc_ctx->pix_fmt = AV_PIX_FMT_CUDA;
+
+    if (!ost->enc_ctx->hw_frames_ctx) {
+        av_log(NULL, AV_LOG_ERROR, "av_buffer_ref failed\n");
+        ret = AVERROR(ENOMEM);
+        goto error;
+    }
+
+    if (!ist->hwaccel_ctx) {
+        ist->hwaccel_ctx = ctx;
+        ist->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx);
+        ist->dec_ctx->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx);
+        ist->dec_ctx->pix_fmt = AV_PIX_FMT_CUDA;
+        ist->resample_pix_fmt = AV_PIX_FMT_CUDA;
+
+        ist->hwaccel_uninit = cuvid_uninit;
+
+        if (!ist->hw_frames_ctx || !ist->dec_ctx->hw_frames_ctx) {
+            av_log(NULL, AV_LOG_ERROR, "av_buffer_ref failed\n");
+            ret = AVERROR(ENOMEM);
+            goto error;
+        }
+    }
+
+    return 0;
+
+error:
+    av_freep(&ctx);
+    return ret;
+
+cancel:
+    if (ist->hwaccel_id == HWACCEL_CUVID) {
+        av_log(NULL, AV_LOG_ERROR, "CUVID hwaccel requested, but impossible to achive.\n");
+        return AVERROR(EINVAL);
+    }
+
+    return 0;
+}
diff --git a/ffmpeg_dxva2.c b/ffmpeg_dxva2.c
index 905bf89..1a391f8 100644
--- a/ffmpeg_dxva2.c
+++ b/ffmpeg_dxva2.c
@@ -40,6 +40,9 @@
 #include "libavutil/imgutils.h"
 #include "libavutil/pixfmt.h"
 
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_dxva2.h"
+
 /* define all the GUIDs used directly here,
    to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */
 #include <initguid.h>
@@ -53,13 +56,11 @@ DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0
 DEFINE_GUID(DXVA2_ModeVC1_D,          0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
 DEFINE_GUID(DXVA2_ModeVC1_D2010,      0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
 DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main,  0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0);
+DEFINE_GUID(DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13);
 DEFINE_GUID(DXVA2_ModeVP9_VLD_Profile0, 0x463707f8, 0xa1d0,0x4585,0x87,0x6d,0x83,0xaa,0x6d,0x60,0xb8,0x9e);
 DEFINE_GUID(DXVA2_NoEncrypt,          0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
 DEFINE_GUID(GUID_NULL,                0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
 
-typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT);
-typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **);
-
 typedef struct dxva2_mode {
   const GUID     *guid;
   enum AVCodecID codec;
@@ -84,6 +85,7 @@ static const dxva2_mode dxva2_modes[] = {
 
     /* HEVC/H.265 */
     { &DXVA2_ModeHEVC_VLD_Main,  AV_CODEC_ID_HEVC },
+    { &DXVA2_ModeHEVC_VLD_Main10,AV_CODEC_ID_HEVC },
 
     /* VP8/9 */
     { &DXVA2_ModeVP9_VLD_Profile0, AV_CODEC_ID_VP9 },
@@ -91,62 +93,18 @@ static const dxva2_mode dxva2_modes[] = {
     { NULL,                      0 },
 };
 
-typedef struct surface_info {
-    int used;
-    uint64_t age;
-} surface_info;
-
 typedef struct DXVA2Context {
-    HMODULE d3dlib;
-    HMODULE dxva2lib;
-
-    HANDLE  deviceHandle;
-
-    IDirect3D9                  *d3d9;
-    IDirect3DDevice9            *d3d9device;
-    IDirect3DDeviceManager9     *d3d9devmgr;
-    IDirectXVideoDecoderService *decoder_service;
     IDirectXVideoDecoder        *decoder;
 
     GUID                        decoder_guid;
     DXVA2_ConfigPictureDecode   decoder_config;
-
-    LPDIRECT3DSURFACE9          *surfaces;
-    surface_info                *surface_infos;
-    uint32_t                    num_surfaces;
-    uint64_t                    surface_age;
+    IDirectXVideoDecoderService *decoder_service;
 
     AVFrame                     *tmp_frame;
-} DXVA2Context;
-
-typedef struct DXVA2SurfaceWrapper {
-    DXVA2Context         *ctx;
-    LPDIRECT3DSURFACE9   surface;
-    IDirectXVideoDecoder *decoder;
-} DXVA2SurfaceWrapper;
-
-static void dxva2_destroy_decoder(AVCodecContext *s)
-{
-    InputStream  *ist = s->opaque;
-    DXVA2Context *ctx = ist->hwaccel_ctx;
-    int i;
 
-    if (ctx->surfaces) {
-        for (i = 0; i < ctx->num_surfaces; i++) {
-            if (ctx->surfaces[i])
-                IDirect3DSurface9_Release(ctx->surfaces[i]);
-        }
-    }
-    av_freep(&ctx->surfaces);
-    av_freep(&ctx->surface_infos);
-    ctx->num_surfaces = 0;
-    ctx->surface_age  = 0;
-
-    if (ctx->decoder) {
-        IDirectXVideoDecoder_Release(ctx->decoder);
-        ctx->decoder = NULL;
-    }
-}
+    AVBufferRef                 *hw_device_ctx;
+    AVBufferRef                 *hw_frames_ctx;
+} DXVA2Context;
 
 static void dxva2_uninit(AVCodecContext *s)
 {
@@ -157,29 +115,11 @@ static void dxva2_uninit(AVCodecContext *s)
     ist->hwaccel_get_buffer    = NULL;
     ist->hwaccel_retrieve_data = NULL;
 
-    if (ctx->decoder)
-        dxva2_destroy_decoder(s);
-
     if (ctx->decoder_service)
         IDirectXVideoDecoderService_Release(ctx->decoder_service);
 
-    if (ctx->d3d9devmgr && ctx->deviceHandle != INVALID_HANDLE_VALUE)
-        IDirect3DDeviceManager9_CloseDeviceHandle(ctx->d3d9devmgr, ctx->deviceHandle);
-
-    if (ctx->d3d9devmgr)
-        IDirect3DDeviceManager9_Release(ctx->d3d9devmgr);
-
-    if (ctx->d3d9device)
-        IDirect3DDevice9_Release(ctx->d3d9device);
-
-    if (ctx->d3d9)
-        IDirect3D9_Release(ctx->d3d9);
-
-    if (ctx->d3dlib)
-        FreeLibrary(ctx->d3dlib);
-
-    if (ctx->dxva2lib)
-        FreeLibrary(ctx->dxva2lib);
+    av_buffer_unref(&ctx->hw_frames_ctx);
+    av_buffer_unref(&ctx->hw_device_ctx);
 
     av_frame_free(&ctx->tmp_frame);
 
@@ -187,119 +127,34 @@ static void dxva2_uninit(AVCodecContext *s)
     av_freep(&s->hwaccel_context);
 }
 
-static void dxva2_release_buffer(void *opaque, uint8_t *data)
-{
-    DXVA2SurfaceWrapper *w   = opaque;
-    DXVA2Context        *ctx = w->ctx;
-    int i;
-
-    for (i = 0; i < ctx->num_surfaces; i++) {
-        if (ctx->surfaces[i] == w->surface) {
-            ctx->surface_infos[i].used = 0;
-            break;
-        }
-    }
-    IDirect3DSurface9_Release(w->surface);
-    IDirectXVideoDecoder_Release(w->decoder);
-    av_free(w);
-}
-
 static int dxva2_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
 {
     InputStream  *ist = s->opaque;
     DXVA2Context *ctx = ist->hwaccel_ctx;
-    int i, old_unused = -1;
-    LPDIRECT3DSURFACE9 surface;
-    DXVA2SurfaceWrapper *w = NULL;
-
-    av_assert0(frame->format == AV_PIX_FMT_DXVA2_VLD);
-
-    for (i = 0; i < ctx->num_surfaces; i++) {
-        surface_info *info = &ctx->surface_infos[i];
-        if (!info->used && (old_unused == -1 || info->age < ctx->surface_infos[old_unused].age))
-            old_unused = i;
-    }
-    if (old_unused == -1) {
-        av_log(NULL, AV_LOG_ERROR, "No free DXVA2 surface!\n");
-        return AVERROR(ENOMEM);
-    }
-    i = old_unused;
 
-    surface = ctx->surfaces[i];
-
-    w = av_mallocz(sizeof(*w));
-    if (!w)
-        return AVERROR(ENOMEM);
-
-    frame->buf[0] = av_buffer_create((uint8_t*)surface, 0,
-                                     dxva2_release_buffer, w,
-                                     AV_BUFFER_FLAG_READONLY);
-    if (!frame->buf[0]) {
-        av_free(w);
-        return AVERROR(ENOMEM);
-    }
-
-    w->ctx     = ctx;
-    w->surface = surface;
-    IDirect3DSurface9_AddRef(w->surface);
-    w->decoder = ctx->decoder;
-    IDirectXVideoDecoder_AddRef(w->decoder);
-
-    ctx->surface_infos[i].used = 1;
-    ctx->surface_infos[i].age  = ctx->surface_age++;
-
-    frame->data[3] = (uint8_t *)surface;
-
-    return 0;
+    return av_hwframe_get_buffer(ctx->hw_frames_ctx, frame, 0);
 }
 
 static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame)
 {
-    LPDIRECT3DSURFACE9 surface =  (LPDIRECT3DSURFACE9)frame->data[3];
     InputStream        *ist = s->opaque;
     DXVA2Context       *ctx = ist->hwaccel_ctx;
-    D3DSURFACE_DESC    surfaceDesc;
-    D3DLOCKED_RECT     LockedRect;
-    HRESULT            hr;
     int                ret;
 
-    IDirect3DSurface9_GetDesc(surface, &surfaceDesc);
-
-    ctx->tmp_frame->width  = frame->width;
-    ctx->tmp_frame->height = frame->height;
-    ctx->tmp_frame->format = AV_PIX_FMT_NV12;
-
-    ret = av_frame_get_buffer(ctx->tmp_frame, 32);
+    ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0);
     if (ret < 0)
         return ret;
 
-    hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, D3DLOCK_READONLY);
-    if (FAILED(hr)) {
-        av_log(NULL, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n");
-        return AVERROR_UNKNOWN;
-    }
-
-    av_image_copy_plane(ctx->tmp_frame->data[0], ctx->tmp_frame->linesize[0],
-                        (uint8_t*)LockedRect.pBits,
-                        LockedRect.Pitch, frame->width, frame->height);
-
-    av_image_copy_plane(ctx->tmp_frame->data[1], ctx->tmp_frame->linesize[1],
-                        (uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height,
-                        LockedRect.Pitch, frame->width, frame->height / 2);
-
-    IDirect3DSurface9_UnlockRect(surface);
-
     ret = av_frame_copy_props(ctx->tmp_frame, frame);
-    if (ret < 0)
-        goto fail;
+    if (ret < 0) {
+        av_frame_unref(ctx->tmp_frame);
+        return ret;
+    }
 
     av_frame_unref(frame);
     av_frame_move_ref(frame, ctx->tmp_frame);
 
     return 0;
-fail:
-    av_frame_unref(ctx->tmp_frame);
-    return ret;
 }
 
 static int dxva2_alloc(AVCodecContext *s)
@@ -307,94 +162,40 @@ static int dxva2_alloc(AVCodecContext *s)
     InputStream  *ist = s->opaque;
     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
     DXVA2Context *ctx;
-    pDirect3DCreate9      *createD3D = NULL;
-    pCreateDeviceManager9 *createDeviceManager = NULL;
+    HANDLE device_handle;
     HRESULT hr;
-    D3DPRESENT_PARAMETERS d3dpp = {0};
-    D3DDISPLAYMODE        d3ddm;
-    unsigned resetToken = 0;
-    UINT adapter = D3DADAPTER_DEFAULT;
+
+    AVHWDeviceContext    *device_ctx;
+    AVDXVA2DeviceContext *device_hwctx;
+    int ret;
 
     ctx = av_mallocz(sizeof(*ctx));
     if (!ctx)
         return AVERROR(ENOMEM);
 
-    ctx->deviceHandle = INVALID_HANDLE_VALUE;
-
     ist->hwaccel_ctx           = ctx;
     ist->hwaccel_uninit        = dxva2_uninit;
     ist->hwaccel_get_buffer    = dxva2_get_buffer;
     ist->hwaccel_retrieve_data = dxva2_retrieve_data;
 
-    ctx->d3dlib = LoadLibrary("d3d9.dll");
-    if (!ctx->d3dlib) {
-        av_log(NULL, loglevel, "Failed to load D3D9 library\n");
-        goto fail;
-    }
-    ctx->dxva2lib = LoadLibrary("dxva2.dll");
-    if (!ctx->dxva2lib) {
-        av_log(NULL, loglevel, "Failed to load DXVA2 library\n");
-        goto fail;
-    }
-
-    createD3D = (pDirect3DCreate9 *)GetProcAddress(ctx->d3dlib, "Direct3DCreate9");
-    if (!createD3D) {
-        av_log(NULL, loglevel, "Failed to locate Direct3DCreate9\n");
-        goto fail;
-    }
-    createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(ctx->dxva2lib, "DXVA2CreateDirect3DDeviceManager9");
-    if (!createDeviceManager) {
-        av_log(NULL, loglevel, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
-        goto fail;
-    }
-
-    ctx->d3d9 = createD3D(D3D_SDK_VERSION);
-    if (!ctx->d3d9) {
-        av_log(NULL, loglevel, "Failed to create IDirect3D object\n");
-        goto fail;
-    }
-
-    if (ist->hwaccel_device) {
-        adapter = atoi(ist->hwaccel_device);
-        av_log(NULL, AV_LOG_INFO, "Using HWAccel device %d\n", adapter);
-    }
-
-    IDirect3D9_GetAdapterDisplayMode(ctx->d3d9, adapter, &d3ddm);
-    d3dpp.Windowed         = TRUE;
-    d3dpp.BackBufferWidth  = 640;
-    d3dpp.BackBufferHeight = 480;
-    d3dpp.BackBufferCount  = 0;
-    d3dpp.BackBufferFormat = d3ddm.Format;
-    d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
-    d3dpp.Flags            = D3DPRESENTFLAG_VIDEO;
-
-    hr = IDirect3D9_CreateDevice(ctx->d3d9, adapter, D3DDEVTYPE_HAL, GetDesktopWindow(),
-                                 D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
-                                 &d3dpp, &ctx->d3d9device);
-    if (FAILED(hr)) {
-        av_log(NULL, loglevel, "Failed to create Direct3D device\n");
-        goto fail;
-    }
-
-    hr = createDeviceManager(&resetToken, &ctx->d3d9devmgr);
-    if (FAILED(hr)) {
-        av_log(NULL, loglevel, "Failed to create Direct3D device manager\n");
-        goto fail;
-    }
-
-    hr = IDirect3DDeviceManager9_ResetDevice(ctx->d3d9devmgr, ctx->d3d9device, resetToken);
-    if (FAILED(hr)) {
-        av_log(NULL, loglevel, "Failed to bind Direct3D device to device manager\n");
+    ret = av_hwdevice_ctx_create(&ctx->hw_device_ctx, AV_HWDEVICE_TYPE_DXVA2,
+                                 ist->hwaccel_device, NULL, 0);
+    if (ret < 0)
         goto fail;
-    }
+    device_ctx   = (AVHWDeviceContext*)ctx->hw_device_ctx->data;
+    device_hwctx = device_ctx->hwctx;
 
-    hr = IDirect3DDeviceManager9_OpenDeviceHandle(ctx->d3d9devmgr, &ctx->deviceHandle);
+    hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr,
+                                                  &device_handle);
     if (FAILED(hr)) {
-        av_log(NULL, loglevel, "Failed to open device handle\n");
+        av_log(NULL, loglevel, "Failed to open a device handle\n");
         goto fail;
     }
 
-    hr = IDirect3DDeviceManager9_GetVideoService(ctx->d3d9devmgr, ctx->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service);
+    hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle,
+                                                 &IID_IDirectXVideoDecoderService,
+                                                 (void **)&ctx->decoder_service);
+    IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle);
     if (FAILED(hr)) {
         av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n");
         goto fail;
@@ -470,13 +271,17 @@ static int dxva2_create_decoder(AVCodecContext *s)
     GUID *guid_list = NULL;
     unsigned guid_count = 0, i, j;
     GUID device_guid = GUID_NULL;
+    const D3DFORMAT surface_format = (s->sw_pix_fmt == AV_PIX_FMT_YUV420P10) ? MKTAG('P','0','1','0') : MKTAG('N','V','1','2');
     D3DFORMAT target_format = 0;
     DXVA2_VideoDesc desc = { 0 };
     DXVA2_ConfigPictureDecode config;
     HRESULT hr;
-    int surface_alignment;
+    int surface_alignment, num_surfaces;
     int ret;
 
+    AVDXVA2FramesContext *frames_hwctx;
+    AVHWFramesContext *frames_ctx;
+
     hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->decoder_service, &guid_count, &guid_list);
     if (FAILED(hr)) {
         av_log(NULL, loglevel, "Failed to retrieve decoder device GUIDs\n");
@@ -503,7 +308,7 @@ static int dxva2_create_decoder(AVCodecContext *s)
         }
         for (j = 0; j < target_count; j++) {
             const D3DFORMAT format = target_list[j];
-            if (format == MKTAG('N','V','1','2')) {
+            if (format == surface_format) {
                 target_format = format;
                 break;
             }
@@ -542,43 +347,43 @@ static int dxva2_create_decoder(AVCodecContext *s)
         surface_alignment = 16;
 
     /* 4 base work surfaces */
-    ctx->num_surfaces = 4;
+    num_surfaces = 4;
 
     /* add surfaces based on number of possible refs */
     if (s->codec_id == AV_CODEC_ID_H264 || s->codec_id == AV_CODEC_ID_HEVC)
-        ctx->num_surfaces += 16;
+        num_surfaces += 16;
     else if (s->codec_id == AV_CODEC_ID_VP9)
-        ctx->num_surfaces += 8;
+        num_surfaces += 8;
     else
-        ctx->num_surfaces += 2;
+        num_surfaces += 2;
 
     /* add extra surfaces for frame threading */
     if (s->active_thread_type & FF_THREAD_FRAME)
-        ctx->num_surfaces += s->thread_count;
+        num_surfaces += s->thread_count;
 
-    ctx->surfaces      = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surfaces));
-    ctx->surface_infos = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surface_infos));
-
-    if (!ctx->surfaces || !ctx->surface_infos) {
-        av_log(NULL, loglevel, "Unable to allocate surface arrays\n");
+    ctx->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->hw_device_ctx);
+    if (!ctx->hw_frames_ctx)
         goto fail;
-    }
+    frames_ctx   = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
+    frames_hwctx = frames_ctx->hwctx;
 
-    hr = IDirectXVideoDecoderService_CreateSurface(ctx->decoder_service,
-                                                   FFALIGN(s->coded_width, surface_alignment),
-                                                   FFALIGN(s->coded_height, surface_alignment),
-                                                   ctx->num_surfaces - 1,
-                                                   target_format, D3DPOOL_DEFAULT, 0,
-                                                   DXVA2_VideoDecoderRenderTarget,
-                                                   ctx->surfaces, NULL);
-    if (FAILED(hr)) {
-        av_log(NULL, loglevel, "Failed to create %d video surfaces\n", ctx->num_surfaces);
+    frames_ctx->format            = AV_PIX_FMT_DXVA2_VLD;
+    frames_ctx->sw_format         = (target_format == MKTAG('P','0','1','0') ? AV_PIX_FMT_P010 : AV_PIX_FMT_NV12);
+    frames_ctx->width             = FFALIGN(s->coded_width, surface_alignment);
+    frames_ctx->height            = FFALIGN(s->coded_height, surface_alignment);
+    frames_ctx->initial_pool_size = num_surfaces;
+
+    frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
+
+    ret = av_hwframe_ctx_init(ctx->hw_frames_ctx);
+    if (ret < 0) {
+        av_log(NULL, loglevel, "Failed to initialize the HW frames context\n");
         goto fail;
     }
 
     hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->decoder_service, &device_guid,
-                                                        &desc, &config, ctx->surfaces,
-                                                        ctx->num_surfaces, &ctx->decoder);
+                                                        &desc, &config, frames_hwctx->surfaces,
+                                                        frames_hwctx->nb_surfaces, &frames_hwctx->decoder_to_release);
     if (FAILED(hr)) {
         av_log(NULL, loglevel, "Failed to create DXVA2 video decoder\n");
         goto fail;
@@ -588,16 +393,16 @@ static int dxva2_create_decoder(AVCodecContext *s)
     ctx->decoder_config = config;
 
     dxva_ctx->cfg           = &ctx->decoder_config;
-    dxva_ctx->decoder       = ctx->decoder;
-    dxva_ctx->surface       = ctx->surfaces;
-    dxva_ctx->surface_count = ctx->num_surfaces;
+    dxva_ctx->decoder       = frames_hwctx->decoder_to_release;
+    dxva_ctx->surface       = frames_hwctx->surfaces;
+    dxva_ctx->surface_count = frames_hwctx->nb_surfaces;
 
     if (IsEqualGUID(&ctx->decoder_guid, &DXVADDI_Intel_ModeH264_E))
         dxva_ctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
 
     return 0;
 fail:
-    dxva2_destroy_decoder(s);
+    av_buffer_unref(&ctx->hw_frames_ctx);
     return AVERROR(EINVAL);
 }
 
@@ -621,8 +426,13 @@ int dxva2_init(AVCodecContext *s)
         return AVERROR(EINVAL);
     }
 
-    if (ctx->decoder)
-        dxva2_destroy_decoder(s);
+    if (s->codec_id == AV_CODEC_ID_HEVC &&
+        s->profile != FF_PROFILE_HEVC_MAIN && s->profile != FF_PROFILE_HEVC_MAIN_10) {
+        av_log(NULL, loglevel, "Unsupported HEVC profile for DXVA2 HWAccel: %d\n", s->profile);
+        return AVERROR(EINVAL);
+    }
+
+    av_buffer_unref(&ctx->hw_frames_ctx);
 
     ret = dxva2_create_decoder(s);
     if (ret < 0) {
diff --git a/ffmpeg_filter.c b/ffmpeg_filter.c
index 6896a78..7745cb6 100644
--- a/ffmpeg_filter.c
+++ b/ffmpeg_filter.c
@@ -24,6 +24,7 @@
 
 #include "libavfilter/avfilter.h"
 #include "libavfilter/buffersink.h"
+#include "libavfilter/buffersrc.h"
 
 #include "libavresample/avresample.h"
 
@@ -38,7 +39,6 @@
 #include "libavutil/imgutils.h"
 #include "libavutil/samplefmt.h"
 
-
 static const enum AVPixelFormat *get_compliance_unofficial_pix_fmts(enum AVCodecID codec_id, const enum AVPixelFormat default_formats[])
 {
     static const enum AVPixelFormat mjpeg_formats[] =
@@ -428,7 +428,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter,
     if (ret < 0)
         return ret;
 
-    if (codec->width || codec->height) {
+    if (!hw_device_ctx && (codec->width || codec->height)) {
         char args[255];
         AVFilterContext *filter;
         AVDictionaryEntry *e = NULL;
@@ -656,7 +656,7 @@ int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOu
     DESCRIBE_FILTER_LINK(ofilter, out, 0);
 
     if (!ofilter->ost) {
-        av_log(NULL, AV_LOG_FATAL, "Filter %s has a unconnected output\n", ofilter->name);
+        av_log(NULL, AV_LOG_FATAL, "Filter %s has an unconnected output\n", ofilter->name);
         exit_program(1);
     }
 
@@ -719,10 +719,17 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
     char name[255];
     int ret, pad_idx = 0;
     int64_t tsoffset = 0;
+    AVBufferSrcParameters *par = av_buffersrc_parameters_alloc();
+
+    if (!par)
+        return AVERROR(ENOMEM);
+    memset(par, 0, sizeof(*par));
+    par->format = AV_PIX_FMT_NONE;
 
     if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
         av_log(NULL, AV_LOG_ERROR, "Cannot connect video filter to audio input\n");
-        return AVERROR(EINVAL);
+        ret = AVERROR(EINVAL);
+        goto fail;
     }
 
     if (!fr.num)
@@ -731,7 +738,7 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
     if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
         ret = sub2video_prepare(ist);
         if (ret < 0)
-            return ret;
+            goto fail;
     }
 
     sar = ist->st->sample_aspect_ratio.num ?
@@ -752,9 +759,15 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
     snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
              ist->file_index, ist->st->index);
 
+
     if ((ret = avfilter_graph_create_filter(&ifilter->filter, buffer_filt, name,
                                             args.str, NULL, fg->graph)) < 0)
-        return ret;
+        goto fail;
+    par->hw_frames_ctx = ist->hw_frames_ctx;
+    ret = av_buffersrc_parameters_set(ifilter->filter, par);
+    if (ret < 0)
+        goto fail;
+    av_freep(&par);
     last_filter = ifilter->filter;
 
     if (ist->autorotate) {
@@ -828,6 +841,10 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
     if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0)
         return ret;
     return 0;
+fail:
+    av_freep(&par);
+
+    return ret;
 }
 
 static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter,
@@ -1010,6 +1027,12 @@ int configure_filtergraph(FilterGraph *fg)
     if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0)
         return ret;
 
+    if (hw_device_ctx) {
+        for (i = 0; i < fg->graph->nb_filters; i++) {
+            fg->graph->filters[i]->hw_device_ctx = av_buffer_ref(hw_device_ctx);
+        }
+    }
+
     if (simple && (!inputs || inputs->next || !outputs || outputs->next)) {
         const char *num_inputs;
         const char *num_outputs;
diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index bc8355e..7785a30 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -40,7 +40,6 @@
 #include "libavutil/parseutils.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/pixfmt.h"
-#include "libavutil/time_internal.h"
 
 #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
 
@@ -82,8 +81,16 @@ const HWAccel hwaccels[] = {
 #if CONFIG_LIBMFX
     { "qsv",   qsv_init,   HWACCEL_QSV,   AV_PIX_FMT_QSV },
 #endif
+#if CONFIG_VAAPI
+    { "vaapi", vaapi_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI },
+#endif
+#if CONFIG_CUVID
+    { "cuvid", cuvid_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA },
+#endif
     { 0 },
 };
+int hwaccel_lax_profile_check = 0;
+AVBufferRef *hw_device_ctx;
 
 char *vstats_filename;
 char *sdp_filename;
@@ -442,6 +449,17 @@ static int opt_sdp_file(void *optctx, const char *opt, const char *arg)
     return 0;
 }
 
+#if CONFIG_VAAPI
+static int opt_vaapi_device(void *optctx, const char *opt, const char *arg)
+{
+    int err;
+    err = vaapi_device_init(arg);
+    if (err < 0)
+        exit_program(1);
+    return 0;
+}
+#endif
+
 /**
  * Parse a metadata specifier passed as 'arg' parameter.
  * @param arg  metadata string to parse
@@ -634,6 +652,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
         AVCodecContext *dec = st->codec;
         InputStream *ist = av_mallocz(sizeof(*ist));
         char *framerate = NULL, *hwaccel = NULL, *hwaccel_device = NULL;
+        char *hwaccel_output_format = NULL;
         char *codec_tag = NULL;
         char *next;
         char *discard_str = NULL;
@@ -753,6 +772,19 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
                 if (!ist->hwaccel_device)
                     exit_program(1);
             }
+
+            MATCH_PER_STREAM_OPT(hwaccel_output_formats, str,
+                                 hwaccel_output_format, ic, st);
+            if (hwaccel_output_format) {
+                ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format);
+                if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) {
+                    av_log(NULL, AV_LOG_FATAL, "Unrecognised hwaccel output "
+                           "format: %s", hwaccel_output_format);
+                }
+            } else {
+                ist->hwaccel_output_format = AV_PIX_FMT_NONE;
+            }
+
             ist->hwaccel_pix_fmt = AV_PIX_FMT_NONE;
 
             break;
@@ -2430,7 +2462,6 @@ loop_end:
         char type, *val;
         const char *stream_spec;
         int index = 0, j, ret = 0;
-        char now_time[256];
 
         val = strchr(o->metadata[i].u.str, '=');
         if (!val) {
@@ -2440,17 +2471,6 @@ loop_end:
         }
         *val++ = 0;
 
-        if (!strcmp(o->metadata[i].u.str, "creation_time") &&
-            !strcmp(val, "now")) {
-            time_t now = time(0);
-            struct tm *ptm, tmbuf;
-            ptm = localtime_r(&now, &tmbuf);
-            if (ptm) {
-                if (strftime(now_time, sizeof(now_time), "%Y-%m-%d %H:%M:%S", ptm))
-                    val = now_time;
-            }
-        }
-
         parse_meta_type(o->metadata[i].specifier, &type, &index, &stream_spec);
         if (type == 's') {
             for (j = 0; j < oc->nb_streams; j++) {
@@ -3361,9 +3381,12 @@ const OptionDef options[] = {
     { "hwaccel_device",   OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
                           OPT_SPEC | OPT_INPUT,                                  { .off = OFFSET(hwaccel_devices) },
         "select a device for HW acceleration", "devicename" },
-#if HAVE_VDPAU_X11
-    { "vdpau_api_ver", HAS_ARG | OPT_INT | OPT_EXPERT, { &vdpau_api_ver }, "" },
-#endif
+    { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
+                          OPT_SPEC | OPT_INPUT,                                  { .off = OFFSET(hwaccel_output_formats) },
+        "select output format used with HW accelerated decoding", "format" },
+    { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
+                          OPT_SPEC | OPT_INPUT,                                  { .off = OFFSET(hwaccel_output_formats) },
+        "select output format used with HW accelerated decoding", "format" },
 #if CONFIG_VDA || CONFIG_VIDEOTOOLBOX
     { "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" },
 #endif
@@ -3372,6 +3395,8 @@ const OptionDef options[] = {
     { "autorotate",       HAS_ARG | OPT_BOOL | OPT_SPEC |
                           OPT_EXPERT | OPT_INPUT,                                { .off = OFFSET(autorotate) },
         "automatically insert correct rotate filters" },
+    { "hwaccel_lax_profile_check", OPT_BOOL | OPT_EXPERT,                        { &hwaccel_lax_profile_check},
+        "attempt to decode anyway if HW accelerated decoder's supported profiles do not exactly match the stream" },
 
     /* audio options */
     { "aframes",        OPT_AUDIO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_audio_frames },
@@ -3455,5 +3480,10 @@ const OptionDef options[] = {
     { "dn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(data_disable) },
         "disable data" },
 
+#if CONFIG_VAAPI
+    { "vaapi_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vaapi_device },
+        "set VAAPI hardware device (DRM path or X11 display name)", "device" },
+#endif
+
     { NULL, },
 };
diff --git a/ffmpeg_vaapi.c b/ffmpeg_vaapi.c
new file mode 100644
index 0000000..8090597
--- /dev/null
+++ b/ffmpeg_vaapi.c
@@ -0,0 +1,538 @@
+/*
+ * 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 "config.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <va/va.h>
+#if HAVE_VAAPI_X11
+#   include <va/va_x11.h>
+#endif
+#if HAVE_VAAPI_DRM
+#   include <va/va_drm.h>
+#endif
+
+#include "libavutil/avassert.h"
+#include "libavutil/avconfig.h"
+#include "libavutil/buffer.h"
+#include "libavutil/frame.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_vaapi.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixfmt.h"
+
+#include "libavcodec/vaapi.h"
+
+#include "ffmpeg.h"
+
+
+static AVClass vaapi_class = {
+    .class_name = "vaapi",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+#define DEFAULT_SURFACES 20
+
+typedef struct VAAPIDecoderContext {
+    const AVClass *class;
+
+    AVBufferRef       *device_ref;
+    AVHWDeviceContext *device;
+    AVBufferRef       *frames_ref;
+    AVHWFramesContext *frames;
+
+    VAProfile    va_profile;
+    VAEntrypoint va_entrypoint;
+    VAConfigID   va_config;
+    VAContextID  va_context;
+
+    enum AVPixelFormat decode_format;
+    int decode_width;
+    int decode_height;
+    int decode_surfaces;
+
+    // The output need not have the same format, width and height as the
+    // decoded frames - the copy for non-direct-mapped access is actually
+    // a whole vpp instance which can do arbitrary scaling and format
+    // conversion.
+    enum AVPixelFormat output_format;
+
+    struct vaapi_context decoder_vaapi_context;
+} VAAPIDecoderContext;
+
+
+static int vaapi_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
+{
+    InputStream *ist = avctx->opaque;
+    VAAPIDecoderContext *ctx = ist->hwaccel_ctx;
+    int err;
+
+    err = av_hwframe_get_buffer(ctx->frames_ref, frame, 0);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to allocate decoder surface.\n");
+    } else {
+        av_log(ctx, AV_LOG_DEBUG, "Decoder given surface %#x.\n",
+               (unsigned int)(uintptr_t)frame->data[3]);
+    }
+    return err;
+}
+
+static int vaapi_retrieve_data(AVCodecContext *avctx, AVFrame *input)
+{
+    InputStream *ist = avctx->opaque;
+    VAAPIDecoderContext *ctx = ist->hwaccel_ctx;
+    AVFrame *output = 0;
+    int err;
+
+    av_assert0(input->format == AV_PIX_FMT_VAAPI);
+
+    if (ctx->output_format == AV_PIX_FMT_VAAPI) {
+        // Nothing to do.
+        return 0;
+    }
+
+    av_log(ctx, AV_LOG_DEBUG, "Retrieve data from surface %#x.\n",
+           (unsigned int)(uintptr_t)input->data[3]);
+
+    output = av_frame_alloc();
+    if (!output)
+        return AVERROR(ENOMEM);
+
+    output->format = ctx->output_format;
+
+    err = av_hwframe_transfer_data(output, input, 0);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to transfer data to "
+               "output frame: %d.\n", err);
+        goto fail;
+    }
+
+    err = av_frame_copy_props(output, input);
+    if (err < 0) {
+        av_frame_unref(output);
+        goto fail;
+    }
+
+    av_frame_unref(input);
+    av_frame_move_ref(input, output);
+    av_frame_free(&output);
+
+    return 0;
+
+fail:
+    if (output)
+        av_frame_free(&output);
+    return err;
+}
+
+
+static const struct {
+    enum AVCodecID codec_id;
+    int codec_profile;
+    VAProfile va_profile;
+} vaapi_profile_map[] = {
+#define MAP(c, p, v) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, VAProfile ## v }
+    MAP(MPEG2VIDEO,  MPEG2_SIMPLE,    MPEG2Simple ),
+    MAP(MPEG2VIDEO,  MPEG2_MAIN,      MPEG2Main   ),
+    MAP(H263,        UNKNOWN,         H263Baseline),
+    MAP(MPEG4,       MPEG4_SIMPLE,    MPEG4Simple ),
+    MAP(MPEG4,       MPEG4_ADVANCED_SIMPLE,
+                               MPEG4AdvancedSimple),
+    MAP(MPEG4,       MPEG4_MAIN,      MPEG4Main   ),
+    MAP(H264,        H264_CONSTRAINED_BASELINE,
+                           H264ConstrainedBaseline),
+    MAP(H264,        H264_BASELINE,   H264Baseline),
+    MAP(H264,        H264_MAIN,       H264Main    ),
+    MAP(H264,        H264_HIGH,       H264High    ),
+#if VA_CHECK_VERSION(0, 37, 0)
+    MAP(HEVC,        HEVC_MAIN,       HEVCMain    ),
+#endif
+    MAP(WMV3,        VC1_SIMPLE,      VC1Simple   ),
+    MAP(WMV3,        VC1_MAIN,        VC1Main     ),
+    MAP(WMV3,        VC1_COMPLEX,     VC1Advanced ),
+    MAP(WMV3,        VC1_ADVANCED,    VC1Advanced ),
+    MAP(VC1,         VC1_SIMPLE,      VC1Simple   ),
+    MAP(VC1,         VC1_MAIN,        VC1Main     ),
+    MAP(VC1,         VC1_COMPLEX,     VC1Advanced ),
+    MAP(VC1,         VC1_ADVANCED,    VC1Advanced ),
+#if VA_CHECK_VERSION(0, 35, 0)
+    MAP(VP8,         UNKNOWN,       VP8Version0_3 ),
+#endif
+#if VA_CHECK_VERSION(0, 37, 1)
+    MAP(VP9,         VP9_0,           VP9Profile0 ),
+#endif
+#undef MAP
+};
+
+static int vaapi_build_decoder_config(VAAPIDecoderContext *ctx,
+                                      AVCodecContext *avctx,
+                                      int fallback_allowed)
+{
+    AVVAAPIDeviceContext *hwctx = ctx->device->hwctx;
+    AVVAAPIHWConfig *hwconfig = NULL;
+    AVHWFramesConstraints *constraints = NULL;
+    VAStatus vas;
+    int err, i, j;
+    int loglevel = fallback_allowed ? AV_LOG_VERBOSE : AV_LOG_ERROR;
+    const AVCodecDescriptor *codec_desc;
+    const AVPixFmtDescriptor *pix_desc;
+    enum AVPixelFormat pix_fmt;
+    VAProfile profile, *profile_list = NULL;
+    int profile_count, exact_match, alt_profile;
+
+    codec_desc = avcodec_descriptor_get(avctx->codec_id);
+    if (!codec_desc) {
+        err = AVERROR(EINVAL);
+        goto fail;
+    }
+
+    profile_count = vaMaxNumProfiles(hwctx->display);
+    profile_list = av_malloc(profile_count * sizeof(VAProfile));
+    if (!profile_list) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    vas = vaQueryConfigProfiles(hwctx->display,
+                                profile_list, &profile_count);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, loglevel, "Failed to query profiles: %d (%s).\n",
+               vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    profile = VAProfileNone;
+    exact_match = 0;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) {
+        int profile_match = 0;
+        if (avctx->codec_id != vaapi_profile_map[i].codec_id)
+            continue;
+        if (avctx->profile == vaapi_profile_map[i].codec_profile)
+            profile_match = 1;
+        profile = vaapi_profile_map[i].va_profile;
+        for (j = 0; j < profile_count; j++) {
+            if (profile == profile_list[j]) {
+                exact_match = profile_match;
+                break;
+            }
+        }
+        if (j < profile_count) {
+            if (exact_match)
+                break;
+            alt_profile = vaapi_profile_map[i].codec_profile;
+        }
+    }
+    av_freep(&profile_list);
+
+    if (profile == VAProfileNone) {
+        av_log(ctx, loglevel, "No VAAPI support for codec %s.\n",
+               codec_desc->name);
+        err = AVERROR(ENOSYS);
+        goto fail;
+    }
+    if (!exact_match) {
+        if (fallback_allowed || !hwaccel_lax_profile_check) {
+            av_log(ctx, loglevel, "No VAAPI support for codec %s "
+                   "profile %d.\n", codec_desc->name, avctx->profile);
+            if (!fallback_allowed) {
+                av_log(ctx, AV_LOG_WARNING, "If you want attempt decoding "
+                       "anyway with a possibly-incompatible profile, add "
+                       "the option -hwaccel_lax_profile_check.\n");
+            }
+            err = AVERROR(EINVAL);
+            goto fail;
+        } else {
+            av_log(ctx, AV_LOG_WARNING, "No VAAPI support for codec %s "
+                   "profile %d: trying instead with profile %d.\n",
+                   codec_desc->name, avctx->profile, alt_profile);
+            av_log(ctx, AV_LOG_WARNING, "This may fail or give "
+                   "incorrect results, depending on your hardware.\n");
+        }
+    }
+
+    ctx->va_profile = profile;
+    ctx->va_entrypoint = VAEntrypointVLD;
+
+    vas = vaCreateConfig(hwctx->display, ctx->va_profile,
+                         ctx->va_entrypoint, 0, 0, &ctx->va_config);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create decode pipeline "
+               "configuration: %d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref);
+    if (!hwconfig) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    hwconfig->config_id = ctx->va_config;
+
+    constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref,
+                                                      hwconfig);
+    if (!constraints)
+        goto fail;
+
+    // Decide on the decoder target format.
+    // If the user specified something with -hwaccel_output_format then
+    // try to use that to minimise conversions later.
+    ctx->decode_format = AV_PIX_FMT_NONE;
+    if (ctx->output_format != AV_PIX_FMT_NONE &&
+        ctx->output_format != AV_PIX_FMT_VAAPI) {
+        for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
+            if (constraints->valid_sw_formats[i] == ctx->decode_format) {
+                ctx->decode_format = ctx->output_format;
+                av_log(ctx, AV_LOG_DEBUG, "Using decode format %s (output "
+                       "format).\n", av_get_pix_fmt_name(ctx->decode_format));
+                break;
+            }
+        }
+    }
+    // Otherwise, we would like to try to choose something which matches the
+    // decoder output, but there isn't enough information available here to
+    // do so.  Assume for now that we are always dealing with YUV 4:2:0, so
+    // pick a format which does that.
+    if (ctx->decode_format == AV_PIX_FMT_NONE) {
+        for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
+            pix_fmt  = constraints->valid_sw_formats[i];
+            pix_desc = av_pix_fmt_desc_get(pix_fmt);
+            if (pix_desc->nb_components == 3 &&
+                pix_desc->log2_chroma_w == 1 &&
+                pix_desc->log2_chroma_h == 1) {
+                ctx->decode_format = pix_fmt;
+                av_log(ctx, AV_LOG_DEBUG, "Using decode format %s (format "
+                       "matched).\n", av_get_pix_fmt_name(ctx->decode_format));
+                break;
+            }
+        }
+    }
+    // Otherwise pick the first in the list and hope for the best.
+    if (ctx->decode_format == AV_PIX_FMT_NONE) {
+        ctx->decode_format = constraints->valid_sw_formats[0];
+        av_log(ctx, AV_LOG_DEBUG, "Using decode format %s (first in list).\n",
+               av_get_pix_fmt_name(ctx->decode_format));
+        if (i > 1) {
+            // There was a choice, and we picked randomly.  Warn the user
+            // that they might want to choose intelligently instead.
+            av_log(ctx, AV_LOG_WARNING, "Using randomly chosen decode "
+                   "format %s.\n", av_get_pix_fmt_name(ctx->decode_format));
+        }
+    }
+
+    // Ensure the picture size is supported by the hardware.
+    ctx->decode_width  = avctx->coded_width;
+    ctx->decode_height = avctx->coded_height;
+    if (ctx->decode_width  < constraints->min_width  ||
+        ctx->decode_height < constraints->min_height ||
+        ctx->decode_width  > constraints->max_width  ||
+        ctx->decode_height >constraints->max_height) {
+        av_log(ctx, AV_LOG_ERROR, "VAAPI hardware does not support image "
+               "size %dx%d (constraints: width %d-%d height %d-%d).\n",
+               ctx->decode_width, ctx->decode_height,
+               constraints->min_width,  constraints->max_width,
+               constraints->min_height, constraints->max_height);
+        err = AVERROR(EINVAL);
+        goto fail;
+    }
+
+    av_hwframe_constraints_free(&constraints);
+    av_freep(&hwconfig);
+
+    // Decide how many reference frames we need.  This might be doable more
+    // nicely based on the codec and input stream?
+    ctx->decode_surfaces = DEFAULT_SURFACES;
+    // For frame-threaded decoding, one additional surfaces is needed for
+    // each thread.
+    if (avctx->active_thread_type & FF_THREAD_FRAME)
+        ctx->decode_surfaces += avctx->thread_count;
+
+    return 0;
+
+fail:
+    av_hwframe_constraints_free(&constraints);
+    av_freep(&hwconfig);
+    vaDestroyConfig(hwctx->display, ctx->va_config);
+    av_freep(&profile_list);
+    return err;
+}
+
+static void vaapi_decode_uninit(AVCodecContext *avctx)
+{
+    InputStream *ist = avctx->opaque;
+    VAAPIDecoderContext *ctx = ist->hwaccel_ctx;
+
+    if (ctx) {
+        AVVAAPIDeviceContext *hwctx = ctx->device->hwctx;
+
+        if (ctx->va_context != VA_INVALID_ID) {
+            vaDestroyContext(hwctx->display, ctx->va_context);
+            ctx->va_context = VA_INVALID_ID;
+        }
+        if (ctx->va_config != VA_INVALID_ID) {
+            vaDestroyConfig(hwctx->display, ctx->va_config);
+            ctx->va_config = VA_INVALID_ID;
+        }
+
+        av_buffer_unref(&ctx->frames_ref);
+        av_buffer_unref(&ctx->device_ref);
+        av_free(ctx);
+    }
+
+    av_buffer_unref(&ist->hw_frames_ctx);
+
+    ist->hwaccel_ctx           = 0;
+    ist->hwaccel_uninit        = 0;
+    ist->hwaccel_get_buffer    = 0;
+    ist->hwaccel_retrieve_data = 0;
+}
+
+int vaapi_decode_init(AVCodecContext *avctx)
+{
+    InputStream *ist = avctx->opaque;
+    AVVAAPIDeviceContext *hwctx;
+    AVVAAPIFramesContext *avfc;
+    VAAPIDecoderContext *ctx;
+    VAStatus vas;
+    int err;
+    int loglevel = (ist->hwaccel_id != HWACCEL_VAAPI ? AV_LOG_VERBOSE
+                                                     : AV_LOG_ERROR);
+
+    if (ist->hwaccel_ctx)
+        vaapi_decode_uninit(avctx);
+
+    // We have -hwaccel without -vaapi_device, so just initialise here with
+    // the device passed as -hwaccel_device (if -vaapi_device was passed, it
+    // will always have been called before now).
+    if (!hw_device_ctx) {
+        err = vaapi_device_init(ist->hwaccel_device);
+        if (err < 0)
+            return err;
+    }
+
+    ctx = av_mallocz(sizeof(*ctx));
+    if (!ctx)
+        return AVERROR(ENOMEM);
+    ctx->class = &vaapi_class;
+
+    ctx->device_ref = av_buffer_ref(hw_device_ctx);
+    ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
+
+    ctx->va_config  = VA_INVALID_ID;
+    ctx->va_context = VA_INVALID_ID;
+
+    hwctx = ctx->device->hwctx;
+
+    ctx->output_format = ist->hwaccel_output_format;
+
+    err = vaapi_build_decoder_config(ctx, avctx,
+                                     ist->hwaccel_id != HWACCEL_VAAPI);
+    if (err < 0) {
+        av_log(ctx, loglevel, "No supported configuration for this codec.");
+        goto fail;
+    }
+
+    avctx->pix_fmt = ctx->output_format;
+
+    ctx->frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
+    if (!ctx->frames_ref) {
+        av_log(ctx, loglevel, "Failed to create VAAPI frame context.\n");
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ctx->frames = (AVHWFramesContext*)ctx->frames_ref->data;
+
+    ctx->frames->format    = AV_PIX_FMT_VAAPI;
+    ctx->frames->sw_format = ctx->decode_format;
+    ctx->frames->width     = ctx->decode_width;
+    ctx->frames->height    = ctx->decode_height;
+    ctx->frames->initial_pool_size = ctx->decode_surfaces;
+
+    err = av_hwframe_ctx_init(ctx->frames_ref);
+    if (err < 0) {
+        av_log(ctx, loglevel, "Failed to initialise VAAPI frame "
+               "context: %d\n", err);
+        goto fail;
+    }
+
+    avfc = ctx->frames->hwctx;
+
+    vas = vaCreateContext(hwctx->display, ctx->va_config,
+                          ctx->decode_width, ctx->decode_height,
+                          VA_PROGRESSIVE,
+                          avfc->surface_ids, avfc->nb_surfaces,
+                          &ctx->va_context);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create decode pipeline "
+               "context: %d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EINVAL);
+        goto fail;
+    }
+
+    av_log(ctx, AV_LOG_DEBUG, "VAAPI decoder (re)init complete.\n");
+
+    // We would like to set this on the AVCodecContext for use by whoever gets
+    // the frames from the decoder, but unfortunately the AVCodecContext we
+    // have here need not be the "real" one (H.264 makes many copies for
+    // threading purposes).  To avoid the problem, we instead store it in the
+    // InputStream and propagate it from there.
+    ist->hw_frames_ctx = av_buffer_ref(ctx->frames_ref);
+    if (!ist->hw_frames_ctx) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ist->hwaccel_ctx           = ctx;
+    ist->hwaccel_uninit        = vaapi_decode_uninit;
+    ist->hwaccel_get_buffer    = vaapi_get_buffer;
+    ist->hwaccel_retrieve_data = vaapi_retrieve_data;
+
+    ctx->decoder_vaapi_context.display    = hwctx->display;
+    ctx->decoder_vaapi_context.config_id  = ctx->va_config;
+    ctx->decoder_vaapi_context.context_id = ctx->va_context;
+    avctx->hwaccel_context = &ctx->decoder_vaapi_context;
+
+    return 0;
+
+fail:
+    vaapi_decode_uninit(avctx);
+    return err;
+}
+
+static AVClass *vaapi_log = &vaapi_class;
+
+av_cold int vaapi_device_init(const char *device)
+{
+    int err;
+
+    err = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI,
+                                 device, NULL, 0);
+    if (err < 0) {
+        av_log(&vaapi_log, AV_LOG_ERROR, "Failed to create a VAAPI device\n");
+        return err;
+    }
+
+    return 0;
+}
diff --git a/ffmpeg_vdpau.c b/ffmpeg_vdpau.c
index 92a98ea..7d4fbf8 100644
--- a/ffmpeg_vdpau.c
+++ b/ffmpeg_vdpau.c
@@ -18,49 +18,21 @@
 
 #include <stdint.h>
 
-#include <vdpau/vdpau.h>
-#include <vdpau/vdpau_x11.h>
-
-#include <X11/Xlib.h>
-
 #include "ffmpeg.h"
 
 #include "libavcodec/vdpau.h"
 
-#include "libavutil/avassert.h"
 #include "libavutil/buffer.h"
 #include "libavutil/frame.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_vdpau.h"
 #include "libavutil/pixfmt.h"
 
 typedef struct VDPAUContext {
-    Display *dpy;
-
-    VdpDevice  device;
-    VdpDecoder decoder;
-    VdpGetProcAddress *get_proc_address;
-
-    VdpGetErrorString                               *get_error_string;
-    VdpGetInformationString                         *get_information_string;
-    VdpDeviceDestroy                                *device_destroy;
-#if 1 // for ffmpegs older vdpau API, not the oldest though
-    VdpDecoderCreate                                *decoder_create;
-    VdpDecoderDestroy                               *decoder_destroy;
-    VdpDecoderRender                                *decoder_render;
-#endif
-    VdpVideoSurfaceCreate                           *video_surface_create;
-    VdpVideoSurfaceDestroy                          *video_surface_destroy;
-    VdpVideoSurfaceGetBitsYCbCr                     *video_surface_get_bits;
-    VdpVideoSurfaceGetParameters                    *video_surface_get_parameters;
-    VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *video_surface_query;
-
+    AVBufferRef *hw_frames_ctx;
     AVFrame *tmp_frame;
-
-    enum AVPixelFormat pix_fmt;
-    VdpYCbCrFormat vdpau_format;
 } VDPAUContext;
 
-int vdpau_api_ver = 2;
-
 static void vdpau_uninit(AVCodecContext *s)
 {
     InputStream  *ist = s->opaque;
@@ -70,140 +42,54 @@ static void vdpau_uninit(AVCodecContext *s)
     ist->hwaccel_get_buffer    = NULL;
     ist->hwaccel_retrieve_data = NULL;
 
-    if (ctx->decoder_destroy)
-        ctx->decoder_destroy(ctx->decoder);
-
-    if (ctx->device_destroy)
-        ctx->device_destroy(ctx->device);
-
-    if (ctx->dpy)
-        XCloseDisplay(ctx->dpy);
-
+    av_buffer_unref(&ctx->hw_frames_ctx);
     av_frame_free(&ctx->tmp_frame);
 
     av_freep(&ist->hwaccel_ctx);
     av_freep(&s->hwaccel_context);
 }
 
-static void vdpau_release_buffer(void *opaque, uint8_t *data)
-{
-    VdpVideoSurface surface = *(VdpVideoSurface*)data;
-    VDPAUContext *ctx = opaque;
-
-    ctx->video_surface_destroy(surface);
-    av_freep(&data);
-}
-
 static int vdpau_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
 {
     InputStream         *ist = s->opaque;
     VDPAUContext        *ctx = ist->hwaccel_ctx;
-    VdpVideoSurface *surface;
-    VdpStatus err;
-    VdpChromaType chroma;
-    uint32_t width, height;
-
-    av_assert0(frame->format == AV_PIX_FMT_VDPAU);
-
-    if (av_vdpau_get_surface_parameters(s, &chroma, &width, &height))
-        return AVERROR(ENOSYS);
-
-    surface = av_malloc(sizeof(*surface));
-    if (!surface)
-        return AVERROR(ENOMEM);
-
-    frame->buf[0] = av_buffer_create((uint8_t*)surface, sizeof(*surface),
-                                     vdpau_release_buffer, ctx,
-                                     AV_BUFFER_FLAG_READONLY);
-    if (!frame->buf[0]) {
-        av_freep(&surface);
-        return AVERROR(ENOMEM);
-    }
 
-    // properly we should keep a pool of surfaces instead of creating
-    // them anew for each frame, but since we don't care about speed
-    // much in this code, we don't bother
-    err = ctx->video_surface_create(ctx->device, chroma, width, height,
-                                    surface);
-    if (err != VDP_STATUS_OK) {
-        av_log(NULL, AV_LOG_ERROR, "Error allocating a VDPAU video surface: %s\n",
-               ctx->get_error_string(err));
-        av_buffer_unref(&frame->buf[0]);
-        return AVERROR_UNKNOWN;
-    }
-
-    frame->data[3] = (uint8_t*)(uintptr_t)*surface;
-
-    return 0;
+    return av_hwframe_get_buffer(ctx->hw_frames_ctx, frame, 0);
 }
 
 static int vdpau_retrieve_data(AVCodecContext *s, AVFrame *frame)
 {
-    VdpVideoSurface surface = (VdpVideoSurface)(uintptr_t)frame->data[3];
     InputStream        *ist = s->opaque;
     VDPAUContext       *ctx = ist->hwaccel_ctx;
-    VdpStatus err;
-    int ret, chroma_type;
-
-    err = ctx->video_surface_get_parameters(surface, &chroma_type,
-                                            &ctx->tmp_frame->width,
-                                            &ctx->tmp_frame->height);
-    if (err != VDP_STATUS_OK) {
-        av_log(NULL, AV_LOG_ERROR, "Error getting surface parameters: %s\n",
-               ctx->get_error_string(err));
-        return AVERROR_UNKNOWN;
-    }
-    ctx->tmp_frame->format = ctx->pix_fmt;
+    int ret;
 
-    ret = av_frame_get_buffer(ctx->tmp_frame, 32);
+    ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0);
     if (ret < 0)
         return ret;
 
-    ctx->tmp_frame->width  = frame->width;
-    ctx->tmp_frame->height = frame->height;
-
-    err = ctx->video_surface_get_bits(surface, ctx->vdpau_format,
-                                      (void * const *)ctx->tmp_frame->data,
-                                      ctx->tmp_frame->linesize);
-    if (err != VDP_STATUS_OK) {
-        av_log(NULL, AV_LOG_ERROR, "Error retrieving frame data from VDPAU: %s\n",
-               ctx->get_error_string(err));
-        ret = AVERROR_UNKNOWN;
-        goto fail;
-    }
-
-    if (ctx->vdpau_format == VDP_YCBCR_FORMAT_YV12)
-        FFSWAP(uint8_t*, ctx->tmp_frame->data[1], ctx->tmp_frame->data[2]);
-
     ret = av_frame_copy_props(ctx->tmp_frame, frame);
-    if (ret < 0)
-        goto fail;
+    if (ret < 0) {
+        av_frame_unref(ctx->tmp_frame);
+        return ret;
+    }
 
     av_frame_unref(frame);
     av_frame_move_ref(frame, ctx->tmp_frame);
-    return 0;
 
-fail:
-    av_frame_unref(ctx->tmp_frame);
-    return ret;
+    return 0;
 }
 
-static const int vdpau_formats[][2] = {
-    { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV420P },
-    { VDP_YCBCR_FORMAT_NV12, AV_PIX_FMT_NV12 },
-    { VDP_YCBCR_FORMAT_YUYV, AV_PIX_FMT_YUYV422 },
-    { VDP_YCBCR_FORMAT_UYVY, AV_PIX_FMT_UYVY422 },
-};
-
 static int vdpau_alloc(AVCodecContext *s)
 {
     InputStream  *ist = s->opaque;
     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
-    AVVDPAUContext *vdpau_ctx;
     VDPAUContext *ctx;
-    const char *display, *vendor;
-    VdpStatus err;
-    int i;
+    int ret;
+
+    AVBufferRef          *device_ref = NULL;
+    AVHWDeviceContext    *device_ctx;
+    AVVDPAUDeviceContext *device_hwctx;
+    AVHWFramesContext    *frames_ctx;
 
     ctx = av_mallocz(sizeof(*ctx));
     if (!ctx)
@@ -218,145 +104,48 @@ static int vdpau_alloc(AVCodecContext *s)
     if (!ctx->tmp_frame)
         goto fail;
 
-    ctx->dpy = XOpenDisplay(ist->hwaccel_device);
-    if (!ctx->dpy) {
-        av_log(NULL, loglevel, "Cannot open the X11 display %s.\n",
-               XDisplayName(ist->hwaccel_device));
+    ret = av_hwdevice_ctx_create(&device_ref, AV_HWDEVICE_TYPE_VDPAU,
+                                 ist->hwaccel_device, NULL, 0);
+    if (ret < 0)
         goto fail;
-    }
-    display = XDisplayString(ctx->dpy);
+    device_ctx   = (AVHWDeviceContext*)device_ref->data;
+    device_hwctx = device_ctx->hwctx;
 
-    err = vdp_device_create_x11(ctx->dpy, XDefaultScreen(ctx->dpy), &ctx->device,
-                                &ctx->get_proc_address);
-    if (err != VDP_STATUS_OK) {
-        av_log(NULL, loglevel, "VDPAU device creation on X11 display %s failed.\n",
-               display);
+    ctx->hw_frames_ctx = av_hwframe_ctx_alloc(device_ref);
+    if (!ctx->hw_frames_ctx)
         goto fail;
-    }
+    av_buffer_unref(&device_ref);
 
-#define GET_CALLBACK(id, result)                                                \
-do {                                                                            \
-    void *tmp;                                                                  \
-    err = ctx->get_proc_address(ctx->device, id, &tmp);                         \
-    if (err != VDP_STATUS_OK) {                                                 \
-        av_log(NULL, loglevel, "Error getting the " #id " callback.\n");        \
-        goto fail;                                                              \
-    }                                                                           \
-    ctx->result = tmp;                                                          \
-} while (0)
-
-    GET_CALLBACK(VDP_FUNC_ID_GET_ERROR_STRING,               get_error_string);
-    GET_CALLBACK(VDP_FUNC_ID_GET_INFORMATION_STRING,         get_information_string);
-    GET_CALLBACK(VDP_FUNC_ID_DEVICE_DESTROY,                 device_destroy);
-    if (vdpau_api_ver == 1) {
-        GET_CALLBACK(VDP_FUNC_ID_DECODER_CREATE,                 decoder_create);
-        GET_CALLBACK(VDP_FUNC_ID_DECODER_DESTROY,                decoder_destroy);
-        GET_CALLBACK(VDP_FUNC_ID_DECODER_RENDER,                 decoder_render);
-    }
-    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_CREATE,           video_surface_create);
-    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY,          video_surface_destroy);
-    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, video_surface_get_bits);
-    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS,   video_surface_get_parameters);
-    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES,
-                 video_surface_query);
-
-    for (i = 0; i < FF_ARRAY_ELEMS(vdpau_formats); i++) {
-        VdpBool supported;
-        err = ctx->video_surface_query(ctx->device, VDP_CHROMA_TYPE_420,
-                                       vdpau_formats[i][0], &supported);
-        if (err != VDP_STATUS_OK) {
-            av_log(NULL, loglevel,
-                   "Error querying VDPAU surface capabilities: %s\n",
-                   ctx->get_error_string(err));
-            goto fail;
-        }
-        if (supported)
-            break;
-    }
-    if (i == FF_ARRAY_ELEMS(vdpau_formats)) {
-        av_log(NULL, loglevel,
-               "No supported VDPAU format for retrieving the data.\n");
-        return AVERROR(EINVAL);
-    }
-    ctx->vdpau_format = vdpau_formats[i][0];
-    ctx->pix_fmt      = vdpau_formats[i][1];
-
-    if (vdpau_api_ver == 1) {
-        vdpau_ctx = av_vdpau_alloc_context();
-        if (!vdpau_ctx)
-            goto fail;
-        vdpau_ctx->render = ctx->decoder_render;
-
-        s->hwaccel_context = vdpau_ctx;
-    } else
-    if (av_vdpau_bind_context(s, ctx->device, ctx->get_proc_address,
-                              AV_HWACCEL_FLAG_IGNORE_LEVEL))
+    frames_ctx            = (AVHWFramesContext*)ctx->hw_frames_ctx->data;
+    frames_ctx->format    = AV_PIX_FMT_VDPAU;
+    frames_ctx->sw_format = s->sw_pix_fmt;
+    frames_ctx->width     = s->coded_width;
+    frames_ctx->height    = s->coded_height;
+
+    ret = av_hwframe_ctx_init(ctx->hw_frames_ctx);
+    if (ret < 0)
         goto fail;
 
-    ctx->get_information_string(&vendor);
-    av_log(NULL, AV_LOG_VERBOSE, "Using VDPAU -- %s -- on X11 display %s, "
-           "to decode input stream #%d:%d.\n", vendor,
-           display, ist->file_index, ist->st->index);
+    if (av_vdpau_bind_context(s, device_hwctx->device, device_hwctx->get_proc_address, 0))
+        goto fail;
+
+    av_log(NULL, AV_LOG_VERBOSE, "Using VDPAU to decode input stream #%d:%d.\n",
+           ist->file_index, ist->st->index);
 
     return 0;
 
 fail:
     av_log(NULL, loglevel, "VDPAU init failed for stream #%d:%d.\n",
            ist->file_index, ist->st->index);
+    av_buffer_unref(&device_ref);
     vdpau_uninit(s);
     return AVERROR(EINVAL);
 }
 
-static int vdpau_old_init(AVCodecContext *s)
-{
-    InputStream *ist = s->opaque;
-    int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
-    AVVDPAUContext *vdpau_ctx;
-    VDPAUContext *ctx;
-    VdpStatus err;
-    int profile, ret;
-
-    if (!ist->hwaccel_ctx) {
-        ret = vdpau_alloc(s);
-        if (ret < 0)
-            return ret;
-    }
-    ctx       = ist->hwaccel_ctx;
-    vdpau_ctx = s->hwaccel_context;
-
-    ret = av_vdpau_get_profile(s, &profile);
-    if (ret < 0) {
-        av_log(NULL, loglevel, "No known VDPAU decoder profile for this stream.\n");
-        return AVERROR(EINVAL);
-    }
-
-    if (ctx->decoder)
-        ctx->decoder_destroy(ctx->decoder);
-
-    err = ctx->decoder_create(ctx->device, profile,
-                              s->coded_width, s->coded_height,
-                              16, &ctx->decoder);
-    if (err != VDP_STATUS_OK) {
-        av_log(NULL, loglevel, "Error creating the VDPAU decoder: %s\n",
-               ctx->get_error_string(err));
-        return AVERROR_UNKNOWN;
-    }
-
-    vdpau_ctx->decoder = ctx->decoder;
-
-    ist->hwaccel_get_buffer    = vdpau_get_buffer;
-    ist->hwaccel_retrieve_data = vdpau_retrieve_data;
-
-    return 0;
-}
-
 int vdpau_init(AVCodecContext *s)
 {
     InputStream *ist = s->opaque;
 
-    if (vdpau_api_ver == 1)
-        return vdpau_old_init(s);
-
     if (!ist->hwaccel_ctx) {
         int ret = vdpau_alloc(s);
         if (ret < 0)
diff --git a/ffplay.c b/ffplay.c
index 2cfdf26..b0702eb 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -117,6 +117,7 @@ typedef struct PacketQueue {
     MyAVPacketList *first_pkt, *last_pkt;
     int nb_packets;
     int size;
+    int64_t duration;
     int abort_request;
     int serial;
     SDL_mutex *mutex;
@@ -243,7 +244,6 @@ typedef struct VideoState {
     AVStream *audio_st;
     PacketQueue audioq;
     int audio_hw_buf_size;
-    uint8_t silence_buf[SDL_AUDIO_MIN_BUFFER_SIZE];
     uint8_t *audio_buf;
     uint8_t *audio_buf1;
     unsigned int audio_buf_size; /* in bytes */
@@ -418,6 +418,7 @@ static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
     q->last_pkt = pkt1;
     q->nb_packets++;
     q->size += pkt1->pkt.size + sizeof(*pkt1);
+    q->duration += pkt1->pkt.duration;
     /* XXX: should duplicate packet data in DV case */
     SDL_CondSignal(q->cond);
     return 0;
@@ -479,6 +480,7 @@ static void packet_queue_flush(PacketQueue *q)
     q->first_pkt = NULL;
     q->nb_packets = 0;
     q->size = 0;
+    q->duration = 0;
     SDL_UnlockMutex(q->mutex);
 }
 
@@ -529,6 +531,7 @@ static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *seria
                 q->last_pkt = NULL;
             q->nb_packets--;
             q->size -= pkt1->pkt.size + sizeof(*pkt1);
+            q->duration -= pkt1->pkt.duration;
             *pkt = pkt1->pkt;
             if (serial)
                 *serial = pkt1->serial;
@@ -642,6 +645,7 @@ static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
 
 static void decoder_destroy(Decoder *d) {
     av_packet_unref(&d->pkt);
+    avcodec_free_context(&d->avctx);
 }
 
 static void frame_queue_unref_item(Frame *vp)
@@ -769,14 +773,6 @@ static void frame_queue_next(FrameQueue *f)
     SDL_UnlockMutex(f->mutex);
 }
 
-/* jump back to the previous frame if available by resetting rindex_shown */
-static int frame_queue_prev(FrameQueue *f)
-{
-    int ret = f->rindex_shown;
-    f->rindex_shown = 0;
-    return ret;
-}
-
 /* return the number of undisplayed frames in the queue */
 static int frame_queue_nb_remaining(FrameQueue *f)
 {
@@ -947,7 +943,7 @@ static void video_image_display(VideoState *is)
     SDL_Rect rect;
     int i;
 
-    vp = frame_queue_peek(&is->pictq);
+    vp = frame_queue_peek_last(&is->pictq);
     if (vp->bmp) {
         if (is->subtitle_st) {
             if (frame_queue_nb_remaining(&is->subpq) > 0) {
@@ -1140,13 +1136,13 @@ static void video_audio_display(VideoState *s)
 static void stream_component_close(VideoState *is, int stream_index)
 {
     AVFormatContext *ic = is->ic;
-    AVCodecContext *avctx;
+    AVCodecParameters *codecpar;
 
     if (stream_index < 0 || stream_index >= ic->nb_streams)
         return;
-    avctx = ic->streams[stream_index]->codec;
+    codecpar = ic->streams[stream_index]->codecpar;
 
-    switch (avctx->codec_type) {
+    switch (codecpar->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
         decoder_abort(&is->auddec, &is->sampq);
         SDL_CloseAudio();
@@ -1176,8 +1172,7 @@ static void stream_component_close(VideoState *is, int stream_index)
     }
 
     ic->streams[stream_index]->discard = AVDISCARD_ALL;
-    avcodec_close(avctx);
-    switch (avctx->codec_type) {
+    switch (codecpar->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
         is->audio_st = NULL;
         is->audio_stream = -1;
@@ -1528,9 +1523,6 @@ static void video_refresh(void *opaque, double *remaining_time)
     }
 
     if (is->video_st) {
-        int redisplay = 0;
-        if (is->force_refresh)
-            redisplay = frame_queue_prev(&is->pictq);
 retry:
         if (frame_queue_nb_remaining(&is->pictq) == 0) {
             // nothing to do, no picture to display in the queue
@@ -1544,11 +1536,10 @@ retry:
 
             if (vp->serial != is->videoq.serial) {
                 frame_queue_next(&is->pictq);
-                redisplay = 0;
                 goto retry;
             }
 
-            if (lastvp->serial != vp->serial && !redisplay)
+            if (lastvp->serial != vp->serial)
                 is->frame_timer = av_gettime_relative() / 1000000.0;
 
             if (is->paused)
@@ -1556,15 +1547,12 @@ retry:
 
             /* compute nominal last_duration */
             last_duration = vp_duration(is, lastvp, vp);
-            if (redisplay)
-                delay = 0.0;
-            else
-                delay = compute_target_delay(last_duration, is);
+            delay = compute_target_delay(last_duration, is);
 
             time= av_gettime_relative()/1000000.0;
-            if (time < is->frame_timer + delay && !redisplay) {
+            if (time < is->frame_timer + delay) {
                 *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time);
-                return;
+                goto display;
             }
 
             is->frame_timer += delay;
@@ -1572,18 +1560,16 @@ retry:
                 is->frame_timer = time;
 
             SDL_LockMutex(is->pictq.mutex);
-            if (!redisplay && !isnan(vp->pts))
+            if (!isnan(vp->pts))
                 update_video_pts(is, vp->pts, vp->pos, vp->serial);
             SDL_UnlockMutex(is->pictq.mutex);
 
             if (frame_queue_nb_remaining(&is->pictq) > 1) {
                 Frame *nextvp = frame_queue_peek_next(&is->pictq);
                 duration = vp_duration(is, vp, nextvp);
-                if(!is->step && (redisplay || framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){
-                    if (!redisplay)
-                        is->frame_drops_late++;
+                if(!is->step && (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration){
+                    is->frame_drops_late++;
                     frame_queue_next(&is->pictq);
-                    redisplay = 0;
                     goto retry;
                 }
             }
@@ -1608,16 +1594,16 @@ retry:
                     }
             }
 
-display:
-            /* display picture */
-            if (!display_disable && is->show_mode == SHOW_MODE_VIDEO)
-                video_display(is);
-
             frame_queue_next(&is->pictq);
+            is->force_refresh = 1;
 
             if (is->step && !is->paused)
                 stream_toggle_pause(is);
         }
+display:
+        /* display picture */
+        if (!display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown)
+            video_display(is);
     }
     is->force_refresh = 0;
     if (show_status) {
@@ -1653,8 +1639,8 @@ display:
                    aqsize / 1024,
                    vqsize / 1024,
                    sqsize,
-                   is->video_st ? is->video_st->codec->pts_correction_num_faulty_dts : 0,
-                   is->video_st ? is->video_st->codec->pts_correction_num_faulty_pts : 0);
+                   is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0,
+                   is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0);
             fflush(stdout);
             last_time = cur_time;
         }
@@ -1716,7 +1702,7 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double
 {
     Frame *vp;
 
-#if defined(DEBUG_SYNC) && 0
+#if defined(DEBUG_SYNC)
     printf("frame_type=%c pts=%0.3f\n",
            av_get_picture_type_char(src_frame->pict_type), pts);
 #endif
@@ -1906,7 +1892,7 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
     char buffersrc_args[256];
     int ret;
     AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL;
-    AVCodecContext *codec = is->video_st->codec;
+    AVCodecParameters *codecpar = is->video_st->codecpar;
     AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL);
     AVDictionaryEntry *e = NULL;
 
@@ -1925,7 +1911,7 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
              "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
              frame->width, frame->height, frame->format,
              is->video_st->time_base.num, is->video_st->time_base.den,
-             codec->sample_aspect_ratio.num, FFMAX(codec->sample_aspect_ratio.den, 1));
+             codecpar->sample_aspect_ratio.num, FFMAX(codecpar->sample_aspect_ratio.den, 1));
     if (fr.num && fr.den)
         av_strlcatf(buffersrc_args, sizeof(buffersrc_args), ":frame_rate=%d/%d", fr.num, fr.den);
 
@@ -2541,8 +2527,8 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
            audio_size = audio_decode_frame(is);
            if (audio_size < 0) {
                 /* if error, just output silence */
-               is->audio_buf      = is->silence_buf;
-               is->audio_buf_size = sizeof(is->silence_buf) / is->audio_tgt.frame_size * is->audio_tgt.frame_size;
+               is->audio_buf = NULL;
+               is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size;
            } else {
                if (is->show_mode != SHOW_MODE_VIDEO)
                    update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
@@ -2553,11 +2539,11 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
         len1 = is->audio_buf_size - is->audio_buf_index;
         if (len1 > len)
             len1 = len;
-        if (!is->muted && is->audio_volume == SDL_MIX_MAXVOLUME)
+        if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME)
             memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
         else {
-            memset(stream, is->silence_buf[0], len1);
-            if (!is->muted)
+            memset(stream, 0, len1);
+            if (!is->muted && is->audio_buf)
                 SDL_MixAudio(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1, is->audio_volume);
         }
         len -= len1;
@@ -2652,7 +2638,7 @@ static int stream_component_open(VideoState *is, int stream_index)
     AVCodecContext *avctx;
     AVCodec *codec;
     const char *forced_codec_name = NULL;
-    AVDictionary *opts;
+    AVDictionary *opts = NULL;
     AVDictionaryEntry *t = NULL;
     int sample_rate, nb_channels;
     int64_t channel_layout;
@@ -2661,7 +2647,15 @@ static int stream_component_open(VideoState *is, int stream_index)
 
     if (stream_index < 0 || stream_index >= ic->nb_streams)
         return -1;
-    avctx = ic->streams[stream_index]->codec;
+
+    avctx = avcodec_alloc_context3(NULL);
+    if (!avctx)
+        return AVERROR(ENOMEM);
+
+    ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar);
+    if (ret < 0)
+        goto fail;
+    av_codec_set_pkt_timebase(avctx, ic->streams[stream_index]->time_base);
 
     codec = avcodec_find_decoder(avctx->codec_id);
 
@@ -2677,7 +2671,8 @@ static int stream_component_open(VideoState *is, int stream_index)
                                       "No codec could be found with name '%s'\n", forced_codec_name);
         else                   av_log(NULL, AV_LOG_WARNING,
                                       "No codec could be found with id %d\n", avctx->codec_id);
-        return -1;
+        ret = AVERROR(EINVAL);
+        goto fail;
     }
 
     avctx->codec_id = codec->id;
@@ -2730,7 +2725,7 @@ static int stream_component_open(VideoState *is, int stream_index)
                 goto fail;
             link = is->out_audio_filter->inputs[0];
             sample_rate    = link->sample_rate;
-            nb_channels    = link->channels;
+            nb_channels    = avfilter_link_get_channels(link);
             channel_layout = link->channel_layout;
         }
 #else
@@ -2750,7 +2745,7 @@ static int stream_component_open(VideoState *is, int stream_index)
         /* init averaging filter */
         is->audio_diff_avg_coef  = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
         is->audio_diff_avg_count = 0;
-        /* since we do not have a precise anough audio fifo fullness,
+        /* since we do not have a precise anough audio FIFO fullness,
            we correct audio sync only if larger than this threshold */
         is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec;
 
@@ -2763,7 +2758,7 @@ static int stream_component_open(VideoState *is, int stream_index)
             is->auddec.start_pts_tb = is->audio_st->time_base;
         }
         if ((ret = decoder_start(&is->auddec, audio_thread, is)) < 0)
-            goto fail;
+            goto out;
         SDL_PauseAudio(0);
         break;
     case AVMEDIA_TYPE_VIDEO:
@@ -2775,7 +2770,7 @@ static int stream_component_open(VideoState *is, int stream_index)
 
         decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread);
         if ((ret = decoder_start(&is->viddec, video_thread, is)) < 0)
-            goto fail;
+            goto out;
         is->queue_attachments_req = 1;
         break;
     case AVMEDIA_TYPE_SUBTITLE:
@@ -2784,13 +2779,16 @@ static int stream_component_open(VideoState *is, int stream_index)
 
         decoder_init(&is->subdec, avctx, &is->subtitleq, is->continue_read_thread);
         if ((ret = decoder_start(&is->subdec, subtitle_thread, is)) < 0)
-            goto fail;
+            goto out;
         break;
     default:
         break;
     }
+    goto out;
 
 fail:
+    avcodec_free_context(&avctx);
+out:
     av_dict_free(&opts);
 
     return ret;
@@ -2802,6 +2800,13 @@ static int decode_interrupt_cb(void *ctx)
     return is->abort_request;
 }
 
+static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) {
+    return stream_id < 0 ||
+           queue->abort_request ||
+           (st->disposition & AV_DISPOSITION_ATTACHED_PIC) ||
+           queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0);
+}
+
 static int is_realtime(AVFormatContext *s)
 {
     if(   !strcmp(s->iformat->name, "rtp")
@@ -2929,7 +2934,7 @@ static int read_thread(void *arg)
 
     for (i = 0; i < ic->nb_streams; i++) {
         AVStream *st = ic->streams[i];
-        enum AVMediaType type = st->codec->codec_type;
+        enum AVMediaType type = st->codecpar->codec_type;
         st->discard = AVDISCARD_ALL;
         if (wanted_stream_spec[type] && st_index[type] == -1)
             if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
@@ -2964,10 +2969,10 @@ static int read_thread(void *arg)
     is->show_mode = show_mode;
     if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
         AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]];
-        AVCodecContext *avctx = st->codec;
+        AVCodecParameters *codecpar = st->codecpar;
         AVRational sar = av_guess_sample_aspect_ratio(ic, st, NULL);
-        if (avctx->width)
-            set_default_window_size(avctx->width, avctx->height, sar);
+        if (codecpar->width)
+            set_default_window_size(codecpar->width, codecpar->height, sar);
     }
 
     /* open the streams */
@@ -3066,10 +3071,9 @@ static int read_thread(void *arg)
         /* if the queue are full, no need to read more */
         if (infinite_buffer<1 &&
               (is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
-            || (   (is->audioq   .nb_packets > MIN_FRAMES || is->audio_stream < 0 || is->audioq.abort_request)
-                && (is->videoq   .nb_packets > MIN_FRAMES || is->video_stream < 0 || is->videoq.abort_request
-                    || (is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC))
-                && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0 || is->subtitleq.abort_request)))) {
+            || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) &&
+                stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq) &&
+                stream_has_enough_packets(is->subtitle_st, is->subtitle_stream, &is->subtitleq)))) {
             /* wait 10 ms */
             SDL_LockMutex(wait_mutex);
             SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
@@ -3241,12 +3245,12 @@ static void stream_cycle_channel(VideoState *is, int codec_type)
         if (stream_index == start_index)
             return;
         st = is->ic->streams[p ? p->stream_index[stream_index] : stream_index];
-        if (st->codec->codec_type == codec_type) {
+        if (st->codecpar->codec_type == codec_type) {
             /* check that parameters are OK */
             switch (codec_type) {
             case AVMEDIA_TYPE_AUDIO:
-                if (st->codec->sample_rate != 0 &&
-                    st->codec->channels != 0)
+                if (st->codecpar->sample_rate != 0 &&
+                    st->codecpar->channels != 0)
                     goto the_end;
                 break;
             case AVMEDIA_TYPE_VIDEO:
@@ -3770,6 +3774,7 @@ int main(int argc, char **argv)
     int flags;
     VideoState *is;
     char dummy_videodriver[] = "SDL_VIDEODRIVER=dummy";
+    char alsa_bufsize[] = "SDL_AUDIO_ALSA_SET_BUFFER_SIZE=1";
 
     av_log_set_flags(AV_LOG_SKIP_REPEATED);
     parse_loglevel(argc, argv, options);
@@ -3807,6 +3812,12 @@ int main(int argc, char **argv)
     flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
     if (audio_disable)
         flags &= ~SDL_INIT_AUDIO;
+    else {
+        /* Try to work around an occasional ALSA buffer underflow issue when the
+         * period size is NPOT due to ALSA resampling by forcing the buffer size. */
+        if (!SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
+            SDL_putenv(alsa_bufsize);
+    }
     if (display_disable)
         SDL_putenv(dummy_videodriver); /* For the event queue, we always need a video driver. */
 #if !defined(_WIN32) && !defined(__APPLE__)
diff --git a/ffprobe.c b/ffprobe.c
index f7b51ad..b9c3760 100644
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -37,6 +37,7 @@
 #include "libavutil/hash.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/stereo3d.h"
 #include "libavutil/dict.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/libm.h"
@@ -49,6 +50,19 @@
 #include "libpostproc/postprocess.h"
 #include "cmdutils.h"
 
+typedef struct InputStream {
+    AVStream *st;
+
+    AVCodecContext *dec_ctx;
+} InputStream;
+
+typedef struct InputFile {
+    AVFormatContext *fmt_ctx;
+
+    InputStream *streams;
+    int       nb_streams;
+} InputFile;
+
 const char program_name[] = "ffprobe";
 const int program_birth_year = 2007;
 
@@ -1746,10 +1760,39 @@ static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id
     return ret;
 }
 
-static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pkt, int packet_idx)
+static void print_pkt_side_data(WriterContext *w,
+                                const AVPacketSideData *side_data,
+                                int nb_side_data,
+                                SectionID id_data_list,
+                                SectionID id_data)
+{
+    int i;
+
+    writer_print_section_header(w, SECTION_ID_STREAM_SIDE_DATA_LIST);
+    for (i = 0; i < nb_side_data; i++) {
+        const AVPacketSideData *sd = &side_data[i];
+        const char *name = av_packet_side_data_name(sd->type);
+
+        writer_print_section_header(w, SECTION_ID_STREAM_SIDE_DATA);
+        print_str("side_data_type", name ? name : "unknown");
+        print_int("side_data_size", sd->size);
+        if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
+            writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+            print_int("rotation", av_display_rotation_get((int32_t *)sd->data));
+        } else if (sd->type == AV_PKT_DATA_STEREO3D) {
+            const AVStereo3D *stereo = (AVStereo3D *)sd->data;
+            print_str("type", av_stereo3d_type_name(stereo->type));
+            print_int("inverted", !!(stereo->flags & AV_STEREO3D_FLAG_INVERT));
+        }
+        writer_print_section_footer(w);
+    }
+    writer_print_section_footer(w);
+}
+
+static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
 {
     char val_str[128];
-    AVStream *st = fmt_ctx->streams[pkt->stream_index];
+    AVStream *st = ifile->streams[pkt->stream_index].st;
     AVBPrint pbuf;
     const char *s;
 
@@ -1757,7 +1800,7 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk
 
     writer_print_section_header(w, SECTION_ID_PACKET);
 
-    s = av_get_media_type_string(st->codec->codec_type);
+    s = av_get_media_type_string(st->codecpar->codec_type);
     if (s) print_str    ("codec_type", s);
     else   print_str_opt("codec_type", "unknown");
     print_int("stream_index",     pkt->stream_index);
@@ -1775,7 +1818,6 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk
     print_fmt("flags", "%c",      pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_');
 
     if (pkt->side_data_elems) {
-        int i;
         int size;
         const uint8_t *side_metadata;
 
@@ -1786,20 +1828,10 @@ static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pk
                 show_tags(w, dict, SECTION_ID_PACKET_TAGS);
             av_dict_free(&dict);
         }
-        writer_print_section_header(w, SECTION_ID_PACKET_SIDE_DATA_LIST);
-        for (i = 0; i < pkt->side_data_elems; i++) {
-            AVPacketSideData *sd = &pkt->side_data[i];
-            const char *name = av_packet_side_data_name(sd->type);
-            writer_print_section_header(w, SECTION_ID_PACKET_SIDE_DATA);
-            print_str("side_data_type", name ? name : "unknown");
-            print_int("side_data_size", sd->size);
-            if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
-                writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
-                print_int("rotation", av_display_rotation_get((int32_t *)sd->data));
-            }
-            writer_print_section_footer(w);
-        }
-        writer_print_section_footer(w);
+
+        print_pkt_side_data(w, pkt->side_data, pkt->side_data_elems,
+                            SECTION_ID_PACKET_SIDE_DATA_LIST,
+                            SECTION_ID_PACKET_SIDE_DATA);
     }
 
     if (do_show_data)
@@ -1846,7 +1878,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
 
     writer_print_section_header(w, SECTION_ID_FRAME);
 
-    s = av_get_media_type_string(stream->codec->codec_type);
+    s = av_get_media_type_string(stream->codecpar->codec_type);
     if (s) print_str    ("media_type", s);
     else   print_str_opt("media_type", "unknown");
     print_int("stream_index",           stream->index);
@@ -1864,7 +1896,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
     if (av_frame_get_pkt_size(frame) != -1) print_val    ("pkt_size", av_frame_get_pkt_size(frame), unit_byte_str);
     else                       print_str_opt("pkt_size", "N/A");
 
-    switch (stream->codec->codec_type) {
+    switch (stream->codecpar->codec_type) {
         AVRational sar;
 
     case AVMEDIA_TYPE_VIDEO:
@@ -1934,15 +1966,17 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
 }
 
 static av_always_inline int process_frame(WriterContext *w,
-                                          AVFormatContext *fmt_ctx,
+                                          InputFile *ifile,
                                           AVFrame *frame, AVPacket *pkt)
 {
-    AVCodecContext *dec_ctx = fmt_ctx->streams[pkt->stream_index]->codec;
+    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
+    AVCodecContext *dec_ctx = ifile->streams[pkt->stream_index].dec_ctx;
+    AVCodecParameters *par = ifile->streams[pkt->stream_index].st->codecpar;
     AVSubtitle sub;
     int ret = 0, got_frame = 0;
 
-    if (dec_ctx->codec) {
-        switch (dec_ctx->codec_type) {
+    if (dec_ctx && dec_ctx->codec) {
+        switch (par->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
             ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, pkt);
             break;
@@ -1963,13 +1997,13 @@ static av_always_inline int process_frame(WriterContext *w,
     pkt->data += ret;
     pkt->size -= ret;
     if (got_frame) {
-        int is_sub = (dec_ctx->codec_type == AVMEDIA_TYPE_SUBTITLE);
+        int is_sub = (par->codec_type == AVMEDIA_TYPE_SUBTITLE);
         nb_streams_frames[pkt->stream_index]++;
         if (do_show_frames)
             if (is_sub)
-                show_subtitle(w, &sub, fmt_ctx->streams[pkt->stream_index], fmt_ctx);
+                show_subtitle(w, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
             else
-                show_frame(w, frame, fmt_ctx->streams[pkt->stream_index], fmt_ctx);
+                show_frame(w, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
         if (is_sub)
             avsubtitle_free(&sub);
     }
@@ -2000,9 +2034,10 @@ static void log_read_interval(const ReadInterval *interval, void *log_ctx, int l
     av_log(log_ctx, log_level, "\n");
 }
 
-static int read_interval_packets(WriterContext *w, AVFormatContext *fmt_ctx,
+static int read_interval_packets(WriterContext *w, InputFile *ifile,
                                  const ReadInterval *interval, int64_t *cur_ts)
 {
+    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
     AVPacket pkt, pkt1;
     AVFrame *frame = NULL;
     int ret = 0, i = 0, frame_count = 0;
@@ -2044,14 +2079,14 @@ static int read_interval_packets(WriterContext *w, AVFormatContext *fmt_ctx,
         goto end;
     }
     while (!av_read_frame(fmt_ctx, &pkt)) {
-        if (fmt_ctx->nb_streams > nb_streams) {
+        if (ifile->nb_streams > nb_streams) {
             REALLOCZ_ARRAY_STREAM(nb_streams_frames,  nb_streams, fmt_ctx->nb_streams);
             REALLOCZ_ARRAY_STREAM(nb_streams_packets, nb_streams, fmt_ctx->nb_streams);
             REALLOCZ_ARRAY_STREAM(selected_streams,   nb_streams, fmt_ctx->nb_streams);
-            nb_streams = fmt_ctx->nb_streams;
+            nb_streams = ifile->nb_streams;
         }
         if (selected_streams[pkt.stream_index]) {
-            AVRational tb = fmt_ctx->streams[pkt.stream_index]->time_base;
+            AVRational tb = ifile->streams[pkt.stream_index].st->time_base;
 
             if (pkt.pts != AV_NOPTS_VALUE)
                 *cur_ts = av_rescale_q(pkt.pts, tb, AV_TIME_BASE_Q);
@@ -2076,12 +2111,12 @@ static int read_interval_packets(WriterContext *w, AVFormatContext *fmt_ctx,
             frame_count++;
             if (do_read_packets) {
                 if (do_show_packets)
-                    show_packet(w, fmt_ctx, &pkt, i++);
+                    show_packet(w, ifile, &pkt, i++);
                 nb_streams_packets[pkt.stream_index]++;
             }
             if (do_read_frames) {
                 pkt1 = pkt;
-                while (pkt1.size && process_frame(w, fmt_ctx, frame, &pkt1) > 0);
+                while (pkt1.size && process_frame(w, ifile, frame, &pkt1) > 0);
             }
         }
         av_packet_unref(&pkt);
@@ -2093,7 +2128,7 @@ static int read_interval_packets(WriterContext *w, AVFormatContext *fmt_ctx,
     for (i = 0; i < fmt_ctx->nb_streams; i++) {
         pkt.stream_index = i;
         if (do_read_frames)
-            while (process_frame(w, fmt_ctx, frame, &pkt) > 0);
+            while (process_frame(w, ifile, frame, &pkt) > 0);
     }
 
 end:
@@ -2105,17 +2140,18 @@ end:
     return ret;
 }
 
-static int read_packets(WriterContext *w, AVFormatContext *fmt_ctx)
+static int read_packets(WriterContext *w, InputFile *ifile)
 {
+    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
     int i, ret = 0;
     int64_t cur_ts = fmt_ctx->start_time;
 
     if (read_intervals_nb == 0) {
         ReadInterval interval = (ReadInterval) { .has_start = 0, .has_end = 0 };
-        ret = read_interval_packets(w, fmt_ctx, &interval, &cur_ts);
+        ret = read_interval_packets(w, ifile, &interval, &cur_ts);
     } else {
         for (i = 0; i < read_intervals_nb; i++) {
-            ret = read_interval_packets(w, fmt_ctx, &read_intervals[i], &cur_ts);
+            ret = read_interval_packets(w, ifile, &read_intervals[i], &cur_ts);
             if (ret < 0)
                 break;
         }
@@ -2124,17 +2160,18 @@ static int read_packets(WriterContext *w, AVFormatContext *fmt_ctx)
     return ret;
 }
 
-static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, int in_program)
+static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int in_program)
 {
-    AVStream *stream = fmt_ctx->streams[stream_idx];
+    AVStream *stream = ist->st;
+    AVCodecParameters *par;
     AVCodecContext *dec_ctx;
-    const AVCodec *dec;
     char val_str[128];
     const char *s;
     AVRational sar, dar;
     AVBPrint pbuf;
     const AVCodecDescriptor *cd;
     int ret = 0;
+    const char *profile = NULL;
 
     av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
 
@@ -2142,140 +2179,138 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
 
     print_int("index", stream->index);
 
-    if ((dec_ctx = stream->codec)) {
-        const char *profile = NULL;
-        dec = dec_ctx->codec;
-        if (dec) {
-            print_str("codec_name", dec->name);
-            if (!do_bitexact) {
-                if (dec->long_name) print_str    ("codec_long_name", dec->long_name);
-                else                print_str_opt("codec_long_name", "unknown");
-            }
-        } else if ((cd = avcodec_descriptor_get(stream->codec->codec_id))) {
-            print_str_opt("codec_name", cd->name);
-            if (!do_bitexact) {
-                print_str_opt("codec_long_name",
-                              cd->long_name ? cd->long_name : "unknown");
-            }
-        } else {
-            print_str_opt("codec_name", "unknown");
-            if (!do_bitexact) {
-                print_str_opt("codec_long_name", "unknown");
-            }
+    par     = stream->codecpar;
+    dec_ctx = ist->dec_ctx;
+    if (cd = avcodec_descriptor_get(par->codec_id)) {
+        print_str("codec_name", cd->name);
+        if (!do_bitexact) {
+            print_str("codec_long_name",
+                      cd->long_name ? cd->long_name : "unknown");
         }
-
-        if (!do_bitexact && dec && (profile = av_get_profile_name(dec, dec_ctx->profile)))
-            print_str("profile", profile);
-        else {
-            if (dec_ctx->profile != FF_PROFILE_UNKNOWN) {
-                char profile_num[12];
-                snprintf(profile_num, sizeof(profile_num), "%d", dec_ctx->profile);
-                print_str("profile", profile_num);
-            } else
-                print_str_opt("profile", "unknown");
+    } else {
+        print_str_opt("codec_name", "unknown");
+        if (!do_bitexact) {
+            print_str_opt("codec_long_name", "unknown");
         }
+    }
+
+    if (!do_bitexact && (profile = avcodec_profile_name(par->codec_id, par->profile)))
+        print_str("profile", profile);
+    else {
+        if (par->profile != FF_PROFILE_UNKNOWN) {
+            char profile_num[12];
+            snprintf(profile_num, sizeof(profile_num), "%d", par->profile);
+            print_str("profile", profile_num);
+        } else
+            print_str_opt("profile", "unknown");
+    }
 
-        s = av_get_media_type_string(dec_ctx->codec_type);
-        if (s) print_str    ("codec_type", s);
-        else   print_str_opt("codec_type", "unknown");
+    s = av_get_media_type_string(par->codec_type);
+    if (s) print_str    ("codec_type", s);
+    else   print_str_opt("codec_type", "unknown");
+#if FF_API_LAVF_AVCTX
+    if (dec_ctx)
         print_q("codec_time_base", dec_ctx->time_base, '/');
+#endif
 
-        /* print AVI/FourCC tag */
-        av_get_codec_tag_string(val_str, sizeof(val_str), dec_ctx->codec_tag);
-        print_str("codec_tag_string",    val_str);
-        print_fmt("codec_tag", "0x%04x", dec_ctx->codec_tag);
+    /* print AVI/FourCC tag */
+    av_get_codec_tag_string(val_str, sizeof(val_str), par->codec_tag);
+    print_str("codec_tag_string",    val_str);
+    print_fmt("codec_tag", "0x%04x", par->codec_tag);
 
-        switch (dec_ctx->codec_type) {
-        case AVMEDIA_TYPE_VIDEO:
-            print_int("width",        dec_ctx->width);
-            print_int("height",       dec_ctx->height);
+    switch (par->codec_type) {
+    case AVMEDIA_TYPE_VIDEO:
+        print_int("width",        par->width);
+        print_int("height",       par->height);
+        if (dec_ctx) {
             print_int("coded_width",  dec_ctx->coded_width);
             print_int("coded_height", dec_ctx->coded_height);
-            print_int("has_b_frames", dec_ctx->has_b_frames);
-            sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL);
-            if (sar.den) {
-                print_q("sample_aspect_ratio", sar, ':');
-                av_reduce(&dar.num, &dar.den,
-                          dec_ctx->width  * sar.num,
-                          dec_ctx->height * sar.den,
-                          1024*1024);
-                print_q("display_aspect_ratio", dar, ':');
-            } else {
-                print_str_opt("sample_aspect_ratio", "N/A");
-                print_str_opt("display_aspect_ratio", "N/A");
-            }
-            s = av_get_pix_fmt_name(dec_ctx->pix_fmt);
-            if (s) print_str    ("pix_fmt", s);
-            else   print_str_opt("pix_fmt", "unknown");
-            print_int("level",   dec_ctx->level);
-            if (dec_ctx->color_range != AVCOL_RANGE_UNSPECIFIED)
-                print_str    ("color_range", av_color_range_name(dec_ctx->color_range));
-            else
-                print_str_opt("color_range", "N/A");
-            s = av_get_colorspace_name(dec_ctx->colorspace);
-            if (s) print_str    ("color_space", s);
-            else   print_str_opt("color_space", "unknown");
+        }
+        print_int("has_b_frames", par->video_delay);
+        sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL);
+        if (sar.den) {
+            print_q("sample_aspect_ratio", sar, ':');
+            av_reduce(&dar.num, &dar.den,
+                      par->width  * sar.num,
+                      par->height * sar.den,
+                      1024*1024);
+            print_q("display_aspect_ratio", dar, ':');
+        } else {
+            print_str_opt("sample_aspect_ratio", "N/A");
+            print_str_opt("display_aspect_ratio", "N/A");
+        }
+        s = av_get_pix_fmt_name(par->format);
+        if (s) print_str    ("pix_fmt", s);
+        else   print_str_opt("pix_fmt", "unknown");
+        print_int("level",   par->level);
+        if (par->color_range != AVCOL_RANGE_UNSPECIFIED)
+            print_str    ("color_range", av_color_range_name(par->color_range));
+        else
+            print_str_opt("color_range", "N/A");
 
-            if (dec_ctx->color_trc != AVCOL_TRC_UNSPECIFIED)
-                print_str("color_transfer", av_color_transfer_name(dec_ctx->color_trc));
-            else
-                print_str_opt("color_transfer", av_color_transfer_name(dec_ctx->color_trc));
+        s = av_get_colorspace_name(par->color_space);
+        if (s) print_str    ("color_space", s);
+        else   print_str_opt("color_space", "unknown");
 
-            if (dec_ctx->color_primaries != AVCOL_PRI_UNSPECIFIED)
-                print_str("color_primaries", av_color_primaries_name(dec_ctx->color_primaries));
-            else
-                print_str_opt("color_primaries", av_color_primaries_name(dec_ctx->color_primaries));
+        if (par->color_trc != AVCOL_TRC_UNSPECIFIED)
+            print_str("color_transfer", av_color_transfer_name(par->color_trc));
+        else
+            print_str_opt("color_transfer", av_color_transfer_name(par->color_trc));
 
-            if (dec_ctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED)
-                print_str("chroma_location", av_chroma_location_name(dec_ctx->chroma_sample_location));
-            else
-                print_str_opt("chroma_location", av_chroma_location_name(dec_ctx->chroma_sample_location));
+        if (par->color_primaries != AVCOL_PRI_UNSPECIFIED)
+            print_str("color_primaries", av_color_primaries_name(par->color_primaries));
+        else
+            print_str_opt("color_primaries", av_color_primaries_name(par->color_primaries));
+
+        if (par->chroma_location != AVCHROMA_LOC_UNSPECIFIED)
+            print_str("chroma_location", av_chroma_location_name(par->chroma_location));
+        else
+            print_str_opt("chroma_location", av_chroma_location_name(par->chroma_location));
 
 #if FF_API_PRIVATE_OPT
-            if (dec_ctx->timecode_frame_start >= 0) {
-                char tcbuf[AV_TIMECODE_STR_SIZE];
-                av_timecode_make_mpeg_tc_string(tcbuf, dec_ctx->timecode_frame_start);
-                print_str("timecode", tcbuf);
-            } else {
-                print_str_opt("timecode", "N/A");
-            }
+        if (dec_ctx && dec_ctx->timecode_frame_start >= 0) {
+            char tcbuf[AV_TIMECODE_STR_SIZE];
+            av_timecode_make_mpeg_tc_string(tcbuf, dec_ctx->timecode_frame_start);
+            print_str("timecode", tcbuf);
+        } else {
+            print_str_opt("timecode", "N/A");
+        }
 #endif
+        if (dec_ctx)
             print_int("refs", dec_ctx->refs);
-            break;
-
-        case AVMEDIA_TYPE_AUDIO:
-            s = av_get_sample_fmt_name(dec_ctx->sample_fmt);
-            if (s) print_str    ("sample_fmt", s);
-            else   print_str_opt("sample_fmt", "unknown");
-            print_val("sample_rate",     dec_ctx->sample_rate, unit_hertz_str);
-            print_int("channels",        dec_ctx->channels);
-
-            if (dec_ctx->channel_layout) {
-                av_bprint_clear(&pbuf);
-                av_bprint_channel_layout(&pbuf, dec_ctx->channels, dec_ctx->channel_layout);
-                print_str    ("channel_layout", pbuf.str);
-            } else {
-                print_str_opt("channel_layout", "unknown");
-            }
+        break;
 
-            print_int("bits_per_sample", av_get_bits_per_sample(dec_ctx->codec_id));
-            break;
+    case AVMEDIA_TYPE_AUDIO:
+        s = av_get_sample_fmt_name(par->format);
+        if (s) print_str    ("sample_fmt", s);
+        else   print_str_opt("sample_fmt", "unknown");
+        print_val("sample_rate",     par->sample_rate, unit_hertz_str);
+        print_int("channels",        par->channels);
 
-        case AVMEDIA_TYPE_SUBTITLE:
-            if (dec_ctx->width)
-                print_int("width",       dec_ctx->width);
-            else
-                print_str_opt("width",   "N/A");
-            if (dec_ctx->height)
-                print_int("height",      dec_ctx->height);
-            else
-                print_str_opt("height",  "N/A");
-            break;
+        if (par->channel_layout) {
+            av_bprint_clear(&pbuf);
+            av_bprint_channel_layout(&pbuf, par->channels, par->channel_layout);
+            print_str    ("channel_layout", pbuf.str);
+        } else {
+            print_str_opt("channel_layout", "unknown");
         }
-    } else {
-        print_str_opt("codec_type", "unknown");
+
+        print_int("bits_per_sample", av_get_bits_per_sample(par->codec_id));
+        break;
+
+    case AVMEDIA_TYPE_SUBTITLE:
+        if (par->width)
+            print_int("width",       par->width);
+        else
+            print_str_opt("width",   "N/A");
+        if (par->height)
+            print_int("height",      par->height);
+        else
+            print_str_opt("height",  "N/A");
+        break;
     }
-    if (dec_ctx->codec && dec_ctx->codec->priv_class && show_private_data) {
+
+    if (dec_ctx && dec_ctx->codec && dec_ctx->codec->priv_class && show_private_data) {
         const AVOption *opt = NULL;
         while (opt = av_opt_next(dec_ctx->priv_data,opt)) {
             uint8_t *str;
@@ -2296,12 +2331,14 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
     print_time("start_time",  stream->start_time, &stream->time_base);
     print_ts  ("duration_ts", stream->duration);
     print_time("duration",    stream->duration, &stream->time_base);
-    if (dec_ctx->bit_rate > 0) print_val    ("bit_rate", dec_ctx->bit_rate, unit_bit_per_second_str);
+    if (par->bit_rate > 0)     print_val    ("bit_rate", par->bit_rate, unit_bit_per_second_str);
     else                       print_str_opt("bit_rate", "N/A");
-    if (dec_ctx->rc_max_rate > 0) print_val ("max_bit_rate", dec_ctx->rc_max_rate, unit_bit_per_second_str);
-    else                       print_str_opt("max_bit_rate", "N/A");
-    if (dec_ctx->bits_per_raw_sample > 0) print_fmt("bits_per_raw_sample", "%d", dec_ctx->bits_per_raw_sample);
-    else                       print_str_opt("bits_per_raw_sample", "N/A");
+#if FF_API_LAVF_AVCTX
+    if (stream->codec->rc_max_rate > 0) print_val ("max_bit_rate", stream->codec->rc_max_rate, unit_bit_per_second_str);
+    else                                print_str_opt("max_bit_rate", "N/A");
+#endif
+    if (dec_ctx && dec_ctx->bits_per_raw_sample > 0) print_fmt("bits_per_raw_sample", "%d", dec_ctx->bits_per_raw_sample);
+    else                                             print_str_opt("bits_per_raw_sample", "N/A");
     if (stream->nb_frames) print_fmt    ("nb_frames", "%"PRId64, stream->nb_frames);
     else                   print_str_opt("nb_frames", "N/A");
     if (nb_streams_frames[stream_idx])  print_fmt    ("nb_read_frames", "%"PRIu64, nb_streams_frames[stream_idx]);
@@ -2309,10 +2346,10 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
     if (nb_streams_packets[stream_idx]) print_fmt    ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
     else                                print_str_opt("nb_read_packets", "N/A");
     if (do_show_data)
-        writer_print_data(w, "extradata", dec_ctx->extradata,
-                                          dec_ctx->extradata_size);
-    writer_print_data_hash(w, "extradata_hash", dec_ctx->extradata,
-                                                dec_ctx->extradata_size);
+        writer_print_data(w, "extradata", par->extradata,
+                                          par->extradata_size);
+    writer_print_data_hash(w, "extradata_hash", par->extradata,
+                                                par->extradata_size);
 
     /* Print disposition information */
 #define PRINT_DISPOSITION(flagname, name) do {                                \
@@ -2339,22 +2376,9 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
         ret = show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS);
 
     if (stream->nb_side_data) {
-        int i;
-        writer_print_section_header(w, SECTION_ID_STREAM_SIDE_DATA_LIST);
-        for (i = 0; i < stream->nb_side_data; i++) {
-            AVPacketSideData *sd = &stream->side_data[i];
-            const char *name = av_packet_side_data_name(sd->type);
-
-            writer_print_section_header(w, SECTION_ID_STREAM_SIDE_DATA);
-            print_str("side_data_type", name ? name : "unknown");
-            print_int("side_data_size", sd->size);
-            if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
-                writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
-                print_int("rotation", av_display_rotation_get((int32_t *)sd->data));
-            }
-            writer_print_section_footer(w);
-        }
-        writer_print_section_footer(w);
+        print_pkt_side_data(w, stream->side_data, stream->nb_side_data,
+                            SECTION_ID_STREAM_SIDE_DATA_LIST,
+                            SECTION_ID_STREAM_SIDE_DATA);
     }
 
     writer_print_section_footer(w);
@@ -2364,14 +2388,15 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
     return ret;
 }
 
-static int show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
+static int show_streams(WriterContext *w, InputFile *ifile)
 {
+    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
     int i, ret = 0;
 
     writer_print_section_header(w, SECTION_ID_STREAMS);
-    for (i = 0; i < fmt_ctx->nb_streams; i++)
+    for (i = 0; i < ifile->nb_streams; i++)
         if (selected_streams[i]) {
-            ret = show_stream(w, fmt_ctx, i, 0);
+            ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
             if (ret < 0)
                 break;
         }
@@ -2380,8 +2405,9 @@ static int show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
     return ret;
 }
 
-static int show_program(WriterContext *w, AVFormatContext *fmt_ctx, AVProgram *program)
+static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
 {
+    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
     int i, ret = 0;
 
     writer_print_section_header(w, SECTION_ID_PROGRAM);
@@ -2402,7 +2428,7 @@ static int show_program(WriterContext *w, AVFormatContext *fmt_ctx, AVProgram *p
     writer_print_section_header(w, SECTION_ID_PROGRAM_STREAMS);
     for (i = 0; i < program->nb_stream_indexes; i++) {
         if (selected_streams[program->stream_index[i]]) {
-            ret = show_stream(w, fmt_ctx, program->stream_index[i], 1);
+            ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], 1);
             if (ret < 0)
                 break;
         }
@@ -2414,8 +2440,9 @@ end:
     return ret;
 }
 
-static int show_programs(WriterContext *w, AVFormatContext *fmt_ctx)
+static int show_programs(WriterContext *w, InputFile *ifile)
 {
+    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
     int i, ret = 0;
 
     writer_print_section_header(w, SECTION_ID_PROGRAMS);
@@ -2423,7 +2450,7 @@ static int show_programs(WriterContext *w, AVFormatContext *fmt_ctx)
         AVProgram *program = fmt_ctx->programs[i];
         if (!program)
             continue;
-        ret = show_program(w, fmt_ctx, program);
+        ret = show_program(w, ifile, program);
         if (ret < 0)
             break;
     }
@@ -2431,8 +2458,9 @@ static int show_programs(WriterContext *w, AVFormatContext *fmt_ctx)
     return ret;
 }
 
-static int show_chapters(WriterContext *w, AVFormatContext *fmt_ctx)
+static int show_chapters(WriterContext *w, InputFile *ifile)
 {
+    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
     int i, ret = 0;
 
     writer_print_section_header(w, SECTION_ID_CHAPTERS);
@@ -2455,8 +2483,9 @@ static int show_chapters(WriterContext *w, AVFormatContext *fmt_ctx)
     return ret;
 }
 
-static int show_format(WriterContext *w, AVFormatContext *fmt_ctx)
+static int show_format(WriterContext *w, InputFile *ifile)
 {
+    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
     char val_str[128];
     int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
     int ret = 0;
@@ -2499,7 +2528,7 @@ static void show_error(WriterContext *w, int err)
     writer_print_section_footer(w);
 }
 
-static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
+static int open_input_file(InputFile *ifile, const char *filename)
 {
     int err, i, orig_nb_streams;
     AVFormatContext *fmt_ctx = NULL;
@@ -2516,7 +2545,7 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
         print_error(filename, err);
         return err;
     }
-    *fmt_ctx_ptr = fmt_ctx;
+    ifile->fmt_ctx = fmt_ctx;
     if (scan_all_pmts_set)
         av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
     if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
@@ -2541,26 +2570,58 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
 
     av_dump_format(fmt_ctx, 0, filename, 0);
 
+    ifile->streams = av_mallocz_array(fmt_ctx->nb_streams,
+                                      sizeof(*ifile->streams));
+    if (!ifile->streams)
+        exit(1);
+    ifile->nb_streams = fmt_ctx->nb_streams;
+
     /* bind a decoder to each input stream */
     for (i = 0; i < fmt_ctx->nb_streams; i++) {
+        InputStream *ist = &ifile->streams[i];
         AVStream *stream = fmt_ctx->streams[i];
         AVCodec *codec;
 
-        if (stream->codec->codec_id == AV_CODEC_ID_PROBE) {
+        ist->st = stream;
+
+        if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) {
             av_log(NULL, AV_LOG_WARNING,
                    "Failed to probe codec for input stream %d\n",
                     stream->index);
-        } else if (!(codec = avcodec_find_decoder(stream->codec->codec_id))) {
+            continue;
+        }
+
+        codec = avcodec_find_decoder(stream->codecpar->codec_id);
+        if (!codec) {
             av_log(NULL, AV_LOG_WARNING,
                     "Unsupported codec with id %d for input stream %d\n",
-                    stream->codec->codec_id, stream->index);
-        } else {
-            AVDictionary *opts = filter_codec_opts(codec_opts, stream->codec->codec_id,
+                    stream->codecpar->codec_id, stream->index);
+            continue;
+        }
+        {
+            AVDictionary *opts = filter_codec_opts(codec_opts, stream->codecpar->codec_id,
                                                    fmt_ctx, stream, codec);
-            if (avcodec_open2(stream->codec, codec, &opts) < 0) {
+
+            ist->dec_ctx = avcodec_alloc_context3(codec);
+            if (!ist->dec_ctx)
+                exit(1);
+
+            err = avcodec_parameters_to_context(ist->dec_ctx, stream->codecpar);
+            if (err < 0)
+                exit(1);
+
+            ist->dec_ctx->pkt_timebase = stream->time_base;
+#if FF_API_LAVF_AVCTX
+            ist->dec_ctx->time_base = stream->codec->time_base;
+            ist->dec_ctx->framerate = stream->codec->framerate;
+#endif
+
+            if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) {
                 av_log(NULL, AV_LOG_WARNING, "Could not open codec for input stream %d\n",
                        stream->index);
+                exit(1);
             }
+
             if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
                 av_log(NULL, AV_LOG_ERROR, "Option %s for input stream %d not found\n",
                        t->key, stream->index);
@@ -2569,47 +2630,49 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
         }
     }
 
-    *fmt_ctx_ptr = fmt_ctx;
+    ifile->fmt_ctx = fmt_ctx;
     return 0;
 }
 
-static void close_input_file(AVFormatContext **ctx_ptr)
+static void close_input_file(InputFile *ifile)
 {
     int i;
-    AVFormatContext *fmt_ctx = *ctx_ptr;
 
     /* close decoder for each stream */
-    for (i = 0; i < fmt_ctx->nb_streams; i++)
-        if (fmt_ctx->streams[i]->codec->codec_id != AV_CODEC_ID_NONE)
-            avcodec_close(fmt_ctx->streams[i]->codec);
+    for (i = 0; i < ifile->nb_streams; i++)
+        if (ifile->streams[i].st->codecpar->codec_id != AV_CODEC_ID_NONE)
+            avcodec_free_context(&ifile->streams[i].dec_ctx);
 
-    avformat_close_input(ctx_ptr);
+    av_freep(&ifile->streams);
+    ifile->nb_streams = 0;
+
+    avformat_close_input(&ifile->fmt_ctx);
 }
 
 static int probe_file(WriterContext *wctx, const char *filename)
 {
-    AVFormatContext *fmt_ctx = NULL;
+    InputFile ifile = { 0 };
     int ret, i;
     int section_id;
 
     do_read_frames = do_show_frames || do_count_frames;
     do_read_packets = do_show_packets || do_count_packets;
 
-    ret = open_input_file(&fmt_ctx, filename);
+    ret = open_input_file(&ifile, filename);
     if (ret < 0)
         goto end;
 
 #define CHECK_END if (ret < 0) goto end
 
-    nb_streams = fmt_ctx->nb_streams;
-    REALLOCZ_ARRAY_STREAM(nb_streams_frames,0,fmt_ctx->nb_streams);
-    REALLOCZ_ARRAY_STREAM(nb_streams_packets,0,fmt_ctx->nb_streams);
-    REALLOCZ_ARRAY_STREAM(selected_streams,0,fmt_ctx->nb_streams);
+    nb_streams = ifile.fmt_ctx->nb_streams;
+    REALLOCZ_ARRAY_STREAM(nb_streams_frames,0,ifile.fmt_ctx->nb_streams);
+    REALLOCZ_ARRAY_STREAM(nb_streams_packets,0,ifile.fmt_ctx->nb_streams);
+    REALLOCZ_ARRAY_STREAM(selected_streams,0,ifile.fmt_ctx->nb_streams);
 
-    for (i = 0; i < fmt_ctx->nb_streams; i++) {
+    for (i = 0; i < ifile.fmt_ctx->nb_streams; i++) {
         if (stream_specifier) {
-            ret = avformat_match_stream_specifier(fmt_ctx,
-                                                  fmt_ctx->streams[i],
+            ret = avformat_match_stream_specifier(ifile.fmt_ctx,
+                                                  ifile.fmt_ctx->streams[i],
                                                   stream_specifier);
             CHECK_END;
             else
@@ -2630,33 +2693,33 @@ static int probe_file(WriterContext *wctx, const char *filename)
             section_id = SECTION_ID_FRAMES;
         if (do_show_frames || do_show_packets)
             writer_print_section_header(wctx, section_id);
-        ret = read_packets(wctx, fmt_ctx);
+        ret = read_packets(wctx, &ifile);
         if (do_show_frames || do_show_packets)
             writer_print_section_footer(wctx);
         CHECK_END;
     }
 
     if (do_show_programs) {
-        ret = show_programs(wctx, fmt_ctx);
+        ret = show_programs(wctx, &ifile);
         CHECK_END;
     }
 
     if (do_show_streams) {
-        ret = show_streams(wctx, fmt_ctx);
+        ret = show_streams(wctx, &ifile);
         CHECK_END;
     }
     if (do_show_chapters) {
-        ret = show_chapters(wctx, fmt_ctx);
+        ret = show_chapters(wctx, &ifile);
         CHECK_END;
     }
     if (do_show_format) {
-        ret = show_format(wctx, fmt_ctx);
+        ret = show_format(wctx, &ifile);
         CHECK_END;
     }
 
 end:
-    if (fmt_ctx)
-        close_input_file(&fmt_ctx);
+    if (ifile.fmt_ctx)
+        close_input_file(&ifile);
     av_freep(&nb_streams_frames);
     av_freep(&nb_streams_packets);
     av_freep(&selected_streams);
diff --git a/ffserver.c b/ffserver.c
index 374af99..1a27583 100644
--- a/ffserver.c
+++ b/ffserver.c
@@ -2622,6 +2622,7 @@ static int http_start_receive_data(HTTPContext *c)
 {
     int fd;
     int ret;
+    int64_t ret64;
 
     if (c->stream->feed_opened) {
         http_log("Stream feed '%s' was not opened\n",
@@ -2657,13 +2658,13 @@ static int http_start_receive_data(HTTPContext *c)
             return ret;
         }
     } else {
-        ret = ffm_read_write_index(fd);
-        if (ret < 0) {
+        ret64 = ffm_read_write_index(fd);
+        if (ret64 < 0) {
             http_log("Error reading write index from feed file '%s': %s\n",
                      c->stream->feed_filename, strerror(errno));
-            return ret;
+            return ret64;
         }
-        c->stream->feed_write_index = ret;
+        c->stream->feed_write_index = ret64;
     }
 
     c->stream->feed_write_index = FFMAX(ffm_read_write_index(fd),
@@ -2995,6 +2996,8 @@ static int prepare_sdp_description(FFServerStream *stream, uint8_t **pbuffer,
     for(i = 0; i < stream->nb_streams; i++) {
         avc->streams[i] = &avs[i];
         avc->streams[i]->codec = stream->streams[i]->codec;
+        avcodec_parameters_from_context(stream->streams[i]->codecpar, stream->streams[i]->codec);
+        avc->streams[i]->codecpar = stream->streams[i]->codecpar;
     }
     *pbuffer = av_mallocz(2048);
     if (!*pbuffer)
@@ -3535,6 +3538,8 @@ static AVStream *add_av_stream1(FFServerStream *stream,
 
     fst->priv_data = av_mallocz(sizeof(FeedData));
     fst->internal = av_mallocz(sizeof(*fst->internal));
+    fst->internal->avctx = avcodec_alloc_context3(NULL);
+    fst->codecpar = avcodec_parameters_alloc();
     fst->index = stream->nb_streams;
     avpriv_set_pts_info(fst, 33, 1, 90000);
     fst->sample_aspect_ratio = codec->sample_aspect_ratio;
@@ -3858,6 +3863,8 @@ drop:
             if (avformat_write_header(s, NULL) < 0) {
                 http_log("Container doesn't support the required parameters\n");
                 avio_closep(&s->pb);
+                s->streams = NULL;
+                s->nb_streams = 0;
                 avformat_free_context(s);
                 goto bail;
             }
diff --git a/ffserver_config.c b/ffserver_config.c
index 9fc1f00..0ec93b5 100644
--- a/ffserver_config.c
+++ b/ffserver_config.c
@@ -1138,6 +1138,8 @@ static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd,
         av_dict_free(&config->audio_opts);
         avcodec_free_context(&config->dummy_vctx);
         avcodec_free_context(&config->dummy_actx);
+        config->no_video = 0;
+        config->no_audio = 0;
         *pstream = NULL;
     } else if (!av_strcasecmp(cmd, "File") ||
                !av_strcasecmp(cmd, "ReadOnlyFile")) {
diff --git a/libavcodec/8bps.c b/libavcodec/8bps.c
index 2e4464d..46344e0 100644
--- a/libavcodec/8bps.c
+++ b/libavcodec/8bps.c
@@ -28,7 +28,6 @@
  * Supports: PAL8 (RGB 8bpp, paletted)
  *         : BGR24 (RGB 24bpp) (can also output it as RGB32)
  *         : RGB32 (RGB 32bpp, 4th plane is alpha)
- *
  */
 
 #include <stdio.h>
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index f6a4fbb..fd0d1f0 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -5,10 +5,11 @@ NAME = avcodec
 HEADERS = avcodec.h                                                     \
           avdct.h                                                       \
           avfft.h                                                       \
-          dv_profile.h                                                  \
           d3d11va.h                                                     \
           dirac.h                                                       \
+          dv_profile.h                                                  \
           dxva2.h                                                       \
+          jni.h                                                         \
           qsv.h                                                         \
           vaapi.h                                                       \
           vda.h                                                         \
@@ -25,11 +26,14 @@ OBJS = allcodecs.o                                                      \
        avpicture.o                                                      \
        bitstream.o                                                      \
        bitstream_filter.o                                               \
+       bitstream_filters.o                                              \
+       bsf.o                                                            \
        codec_desc.o                                                     \
        d3d11va.o                                                        \
        dirac.o                                                          \
        dv_profile.o                                                     \
        imgconvert.o                                                     \
+       jni.o                                                            \
        mathtables.o                                                     \
        options.o                                                        \
        parser.o                                                         \
@@ -78,6 +82,7 @@ OBJS-$(CONFIG_IIRFILTER)               += iirfilter.o
 OBJS-$(CONFIG_IMDCT15)                 += imdct15.o
 OBJS-$(CONFIG_INTRAX8)                 += intrax8.o intrax8dsp.o
 OBJS-$(CONFIG_IVIDSP)                  += ivi_dsp.o
+OBJS-$(CONFIG_JNI)                     += ffjni.o jni.o
 OBJS-$(CONFIG_JPEGTABLES)              += jpegtables.o
 OBJS-$(CONFIG_LIBXVID)                 += libxvid_rc.o
 OBJS-$(CONFIG_LLAUDDSP)                += lossless_audiodsp.o
@@ -87,6 +92,7 @@ OBJS-$(CONFIG_LSP)                     += lsp.o
 OBJS-$(CONFIG_LZF)                     += lzf.o
 OBJS-$(CONFIG_MDCT)                    += mdct_fixed.o mdct_float.o mdct_fixed_32.o
 OBJS-$(CONFIG_ME_CMP)                  += me_cmp.o
+OBJS-$(CONFIG_MEDIACODEC)              += mediacodecdec.o mediacodec_wrapper.o mediacodec_sw_buffer.o
 OBJS-$(CONFIG_MPEG_ER)                 += mpeg_er.o
 OBJS-$(CONFIG_MPEGAUDIO)               += mpegaudio.o mpegaudiodata.o   \
                                           mpegaudiodecheader.o
@@ -118,6 +124,8 @@ OBJS-$(CONFIG_STARTCODE)               += startcode.o
 OBJS-$(CONFIG_TEXTUREDSP)              += texturedsp.o
 OBJS-$(CONFIG_TEXTUREDSPENC)           += texturedspenc.o
 OBJS-$(CONFIG_TPELDSP)                 += tpeldsp.o
+OBJS-$(CONFIG_VAAPI_ENCODE)            += vaapi_encode.o
+OBJS-$(CONFIG_VC1DSP)                  += vc1dsp.o
 OBJS-$(CONFIG_VIDEODSP)                += videodsp.o
 OBJS-$(CONFIG_VP3DSP)                  += vp3dsp.o
 OBJS-$(CONFIG_VP56DSP)                 += vp56dsp.o
@@ -131,17 +139,17 @@ OBJS-$(CONFIG_A64MULTI_ENCODER)        += a64multienc.o elbg.o
 OBJS-$(CONFIG_A64MULTI5_ENCODER)       += a64multienc.o elbg.o
 OBJS-$(CONFIG_AAC_DECODER)             += aacdec.o aactab.o aacsbr.o aacps_float.o \
                                           aacadtsdec.o mpeg4audio.o kbdwin.o \
-                                          sbrdsp.o aacpsdsp_float.o
+                                          sbrdsp.o aacpsdsp_float.o cbrt_data.o
 OBJS-$(CONFIG_AAC_FIXED_DECODER)       += aacdec_fixed.o aactab.o aacsbr_fixed.o aacps_fixed.o \
                                           aacadtsdec.o mpeg4audio.o kbdwin.o \
-                                          sbrdsp_fixed.o aacpsdsp_fixed.o
+                                          sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o
 OBJS-$(CONFIG_AAC_ENCODER)             += aacenc.o aaccoder.o aacenctab.o    \
                                           aacpsy.o aactab.o      \
                                           aacenc_is.o \
                                           aacenc_tns.o \
                                           aacenc_ltp.o \
                                           aacenc_pred.o \
-                                          psymodel.o mpeg4audio.o kbdwin.o
+                                          psymodel.o mpeg4audio.o kbdwin.o cbrt_data.o
 OBJS-$(CONFIG_AASC_DECODER)            += aasc.o msrledec.o
 OBJS-$(CONFIG_AC3_DECODER)             += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o
 OBJS-$(CONFIG_AC3_FIXED_DECODER)       += ac3dec_fixed.o ac3dec_data.o ac3.o kbdwin.o
@@ -171,9 +179,9 @@ OBJS-$(CONFIG_ANSI_DECODER)            += ansi.o cga_data.o
 OBJS-$(CONFIG_APE_DECODER)             += apedec.o
 OBJS-$(CONFIG_APNG_DECODER)            += png.o pngdec.o pngdsp.o
 OBJS-$(CONFIG_APNG_ENCODER)            += png.o pngenc.o
-OBJS-$(CONFIG_SSA_DECODER)             += assdec.o ass.o ass_split.o
+OBJS-$(CONFIG_SSA_DECODER)             += assdec.o ass.o
 OBJS-$(CONFIG_SSA_ENCODER)             += assenc.o ass.o
-OBJS-$(CONFIG_ASS_DECODER)             += assdec.o ass.o ass_split.o
+OBJS-$(CONFIG_ASS_DECODER)             += assdec.o ass.o
 OBJS-$(CONFIG_ASS_ENCODER)             += assenc.o ass.o
 OBJS-$(CONFIG_ASV1_DECODER)            += asvdec.o asv.o mpeg12data.o
 OBJS-$(CONFIG_ASV1_ENCODER)            += asvenc.o asv.o mpeg12data.o
@@ -216,14 +224,14 @@ OBJS-$(CONFIG_CINEPAK_ENCODER)         += cinepakenc.o elbg.o
 OBJS-$(CONFIG_CLJR_DECODER)            += cljrdec.o
 OBJS-$(CONFIG_CLJR_ENCODER)            += cljrenc.o
 OBJS-$(CONFIG_CLLC_DECODER)            += cllc.o canopus.o
-OBJS-$(CONFIG_COOK_DECODER)            += cook.o
 OBJS-$(CONFIG_COMFORTNOISE_DECODER)    += cngdec.o celp_filters.o
 OBJS-$(CONFIG_COMFORTNOISE_ENCODER)    += cngenc.o
+OBJS-$(CONFIG_COOK_DECODER)            += cook.o
 OBJS-$(CONFIG_CPIA_DECODER)            += cpia.o
 OBJS-$(CONFIG_CSCD_DECODER)            += cscd.o
 OBJS-$(CONFIG_CYUV_DECODER)            += cyuv.o
-OBJS-$(CONFIG_DCA_DECODER)             += dcadec.o dca.o dcadata.o        \
-                                          dca_core.o dca_exss.o dca_xll.o \
+OBJS-$(CONFIG_DCA_DECODER)             += dcadec.o dca.o dcadata.o dcahuff.o \
+                                          dca_core.o dca_exss.o dca_xll.o dca_lbr.o \
                                           dcadsp.o dcadct.o synth_filter.o
 OBJS-$(CONFIG_DCA_ENCODER)             += dcaenc.o dca.o dcadata.o
 OBJS-$(CONFIG_DDS_DECODER)             += dds.o
@@ -234,13 +242,14 @@ OBJS-$(CONFIG_DNXHD_DECODER)           += dnxhddec.o dnxhddata.o
 OBJS-$(CONFIG_DNXHD_ENCODER)           += dnxhdenc.o dnxhddata.o
 OBJS-$(CONFIG_DPX_DECODER)             += dpx.o
 OBJS-$(CONFIG_DPX_ENCODER)             += dpxenc.o
-OBJS-$(CONFIG_DSD_LSBF_DECODER)        += dsddec.o
-OBJS-$(CONFIG_DSD_MSBF_DECODER)        += dsddec.o
-OBJS-$(CONFIG_DSD_LSBF_PLANAR_DECODER) += dsddec.o
-OBJS-$(CONFIG_DSD_MSBF_PLANAR_DECODER) += dsddec.o
+OBJS-$(CONFIG_DSD_LSBF_DECODER)        += dsddec.o dsd.o
+OBJS-$(CONFIG_DSD_MSBF_DECODER)        += dsddec.o dsd.o
+OBJS-$(CONFIG_DSD_LSBF_PLANAR_DECODER) += dsddec.o dsd.o
+OBJS-$(CONFIG_DSD_MSBF_PLANAR_DECODER) += dsddec.o dsd.o
 OBJS-$(CONFIG_DSICINAUDIO_DECODER)     += dsicinaudio.o
 OBJS-$(CONFIG_DSICINVIDEO_DECODER)     += dsicinvideo.o
 OBJS-$(CONFIG_DSS_SP_DECODER)          += dss_sp.o
+OBJS-$(CONFIG_DST_DECODER)             += dstdec.o dsd.o
 OBJS-$(CONFIG_DVBSUB_DECODER)          += dvbsubdec.o
 OBJS-$(CONFIG_DVBSUB_ENCODER)          += dvbsub.o
 OBJS-$(CONFIG_DVDSUB_DECODER)          += dvdsubdec.o
@@ -258,7 +267,7 @@ OBJS-$(CONFIG_EAMAD_DECODER)           += eamad.o eaidct.o mpeg12.o \
                                           mpeg12data.o
 OBJS-$(CONFIG_EATGQ_DECODER)           += eatgq.o eaidct.o
 OBJS-$(CONFIG_EATGV_DECODER)           += eatgv.o
-OBJS-$(CONFIG_EATQI_DECODER)           += eatqi.o eaidct.o
+OBJS-$(CONFIG_EATQI_DECODER)           += eatqi.o eaidct.o mpeg12.o mpeg12data.o mpegvideodata.o rl.o
 OBJS-$(CONFIG_EIGHTBPS_DECODER)        += 8bps.o
 OBJS-$(CONFIG_EIGHTSVX_EXP_DECODER)    += 8svx.o
 OBJS-$(CONFIG_EIGHTSVX_FIB_DECODER)    += 8svx.o
@@ -296,22 +305,36 @@ OBJS-$(CONFIG_H263_DECODER)            += h263dec.o h263.o ituh263dec.o        \
                                           mpeg4video.o mpeg4videodec.o flvdec.o\
                                           intelh263dec.o h263data.o
 OBJS-$(CONFIG_H263_ENCODER)            += mpeg4videoenc.o mpeg4video.o  \
-                                          h263.o h263data.o ituh263enc.o flvenc.o
+                                          h263.o ituh263enc.o flvenc.o h263data.o
 OBJS-$(CONFIG_H264_DECODER)            += h264.o h264_cabac.o h264_cavlc.o \
                                           h264_direct.o h264_loopfilter.o  \
                                           h264_mb.o h264_picture.o h264_ps.o \
-                                          h264_refs.o h264_sei.o h264_slice.o
+                                          h264_refs.o h264_sei.o \
+                                          h264_slice.o h264data.o h264_parse.o \
+                                          h2645_parse.o
+OBJS-$(CONFIG_H264_CUVID_DECODER)      += cuvid.o
+OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec_h264.o
 OBJS-$(CONFIG_H264_MMAL_DECODER)       += mmaldec.o
+OBJS-$(CONFIG_H264_NVENC_ENCODER)      += nvenc_h264.o
+OBJS-$(CONFIG_NVENC_ENCODER)           += nvenc_h264.o
+OBJS-$(CONFIG_NVENC_H264_ENCODER)      += nvenc_h264.o
 OBJS-$(CONFIG_H264_VDA_DECODER)        += vda_h264_dec.o
+OBJS-$(CONFIG_H264_OMX_ENCODER)        += omx.o
 OBJS-$(CONFIG_H264_QSV_DECODER)        += qsvdec_h2645.o
 OBJS-$(CONFIG_H264_QSV_ENCODER)        += qsvenc_h264.o
+OBJS-$(CONFIG_H264_VAAPI_ENCODER)      += vaapi_encode_h264.o vaapi_encode_h26x.o
+OBJS-$(CONFIG_H264_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
 OBJS-$(CONFIG_HAP_DECODER)             += hapdec.o hap.o
 OBJS-$(CONFIG_HAP_ENCODER)             += hapenc.o hap.o
 OBJS-$(CONFIG_HEVC_DECODER)            += hevc.o hevc_mvs.o hevc_ps.o hevc_sei.o \
                                           hevc_cabac.o hevc_refs.o hevcpred.o    \
-                                          hevcdsp.o hevc_filter.o hevc_parse.o hevc_data.o
+                                          hevcdsp.o hevc_filter.o h2645_parse.o hevc_data.o
+OBJS-$(CONFIG_HEVC_CUVID_DECODER)      += cuvid.o
+OBJS-$(CONFIG_HEVC_NVENC_ENCODER)      += nvenc_hevc.o
+OBJS-$(CONFIG_NVENC_HEVC_ENCODER)      += nvenc_hevc.o
 OBJS-$(CONFIG_HEVC_QSV_DECODER)        += qsvdec_h2645.o
-OBJS-$(CONFIG_HEVC_QSV_ENCODER)        += qsvenc_hevc.o hevc_ps_enc.o hevc_parse.o
+OBJS-$(CONFIG_HEVC_QSV_ENCODER)        += qsvenc_hevc.o hevc_ps_enc.o h2645_parse.o
+OBJS-$(CONFIG_HEVC_VAAPI_ENCODER)      += vaapi_encode_h265.o vaapi_encode_h26x.o
 OBJS-$(CONFIG_HNM4_VIDEO_DECODER)      += hnm4video.o
 OBJS-$(CONFIG_HQ_HQA_DECODER)          += hq_hqa.o hq_hqadata.o hq_hqadsp.o \
                                           canopus.o
@@ -342,8 +365,10 @@ OBJS-$(CONFIG_KMVC_DECODER)            += kmvc.o
 OBJS-$(CONFIG_LAGARITH_DECODER)        += lagarith.o lagarithrac.o
 OBJS-$(CONFIG_LJPEG_ENCODER)           += ljpegenc.o mjpegenc_common.o
 OBJS-$(CONFIG_LOCO_DECODER)            += loco.o
+OBJS-$(CONFIG_M101_DECODER)            += m101.o
 OBJS-$(CONFIG_MACE3_DECODER)           += mace.o
 OBJS-$(CONFIG_MACE6_DECODER)           += mace.o
+OBJS-$(CONFIG_MAGICYUV_DECODER)        += magicyuv.o
 OBJS-$(CONFIG_MDEC_DECODER)            += mdec.o mpeg12.o mpeg12data.o
 OBJS-$(CONFIG_METASOUND_DECODER)       += metasound.o metasound_data.o \
                                           twinvq.o
@@ -352,6 +377,7 @@ OBJS-$(CONFIG_MIMIC_DECODER)           += mimic.o
 OBJS-$(CONFIG_MJPEG_DECODER)           += mjpegdec.o
 OBJS-$(CONFIG_MJPEG_ENCODER)           += mjpegenc.o mjpegenc_common.o
 OBJS-$(CONFIG_MJPEGB_DECODER)          += mjpegbdec.o
+OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER)     += vaapi_encode_mjpeg.o
 OBJS-$(CONFIG_MLP_DECODER)             += mlpdec.o mlpdsp.o
 OBJS-$(CONFIG_MMVIDEO_DECODER)         += mmvideo.o
 OBJS-$(CONFIG_MOTIONPIXELS_DECODER)    += motionpixels.o
@@ -376,22 +402,23 @@ OBJS-$(CONFIG_MPC8_DECODER)            += mpc8.o mpc.o
 OBJS-$(CONFIG_MPEGVIDEO_DECODER)       += mpeg12dec.o mpeg12.o mpeg12data.o
 OBJS-$(CONFIG_MPEG1VIDEO_DECODER)      += mpeg12dec.o mpeg12.o mpeg12data.o
 OBJS-$(CONFIG_MPEG1VIDEO_ENCODER)      += mpeg12enc.o mpeg12.o
-OBJS-$(CONFIG_MPEG2VIDEO_DECODER)      += mpeg12dec.o mpeg12.o mpeg12data.o
-OBJS-$(CONFIG_MPEG2VIDEO_ENCODER)      += mpeg12enc.o mpeg12.o
 OBJS-$(CONFIG_MPEG2_MMAL_DECODER)      += mmaldec.o
 OBJS-$(CONFIG_MPEG2_QSV_DECODER)       += qsvdec_mpeg2.o
 OBJS-$(CONFIG_MPEG2_QSV_ENCODER)       += qsvenc_mpeg2.o
+OBJS-$(CONFIG_MPEG2VIDEO_DECODER)      += mpeg12dec.o mpeg12.o mpeg12data.o
+OBJS-$(CONFIG_MPEG2VIDEO_ENCODER)      += mpeg12enc.o mpeg12.o
 OBJS-$(CONFIG_MPEG4_DECODER)           += xvididct.o
+OBJS-$(CONFIG_MPEG4_OMX_ENCODER)       += omx.o
 OBJS-$(CONFIG_MPL2_DECODER)            += mpl2dec.o ass.o
+OBJS-$(CONFIG_MSA1_DECODER)            += mss3.o
 OBJS-$(CONFIG_MSMPEG4V1_DECODER)       += msmpeg4dec.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_MSMPEG4V2_DECODER)       += msmpeg4dec.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_MSMPEG4V2_ENCODER)       += msmpeg4enc.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_MSMPEG4V3_DECODER)       += msmpeg4dec.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_MSMPEG4V3_ENCODER)       += msmpeg4enc.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_MSRLE_DECODER)           += msrle.o msrledec.o
-OBJS-$(CONFIG_MSA1_DECODER)            += mss3.o
 OBJS-$(CONFIG_MSS1_DECODER)            += mss1.o mss12.o
-OBJS-$(CONFIG_MSS2_DECODER)            += mss2.o mss12.o mss2dsp.o
+OBJS-$(CONFIG_MSS2_DECODER)            += mss2.o mss12.o mss2dsp.o wmv2data.o
 OBJS-$(CONFIG_MSVIDEO1_DECODER)        += msvideo1.o
 OBJS-$(CONFIG_MSVIDEO1_ENCODER)        += msvideo1enc.o elbg.o
 OBJS-$(CONFIG_MSZH_DECODER)            += lcldec.o
@@ -471,6 +498,7 @@ OBJS-$(CONFIG_SDX2_DPCM_DECODER)       += dpcm.o
 OBJS-$(CONFIG_SGI_DECODER)             += sgidec.o
 OBJS-$(CONFIG_SGI_ENCODER)             += sgienc.o rle.o
 OBJS-$(CONFIG_SGIRLE_DECODER)          += sgirledec.o
+OBJS-$(CONFIG_SHEERVIDEO_DECODER)      += sheervideo.o
 OBJS-$(CONFIG_SHORTEN_DECODER)         += shorten.o
 OBJS-$(CONFIG_SIPR_DECODER)            += sipr.o acelp_pitch_delay.o \
                                           celp_math.o acelp_vectors.o \
@@ -497,10 +525,10 @@ OBJS-$(CONFIG_SUBVIEWER1_DECODER)      += textdec.o ass.o
 OBJS-$(CONFIG_SUBVIEWER_DECODER)       += subviewerdec.o ass.o
 OBJS-$(CONFIG_SUNRAST_DECODER)         += sunrast.o
 OBJS-$(CONFIG_SUNRAST_ENCODER)         += sunrastenc.o
-OBJS-$(CONFIG_SVQ1_DECODER)            += svq1dec.o svq1.o svq13.o h263.o
-OBJS-$(CONFIG_SVQ1_ENCODER)            += svq1enc.o svq1.o    \
+OBJS-$(CONFIG_SVQ1_DECODER)            += svq1dec.o svq1.o svq13.o h263data.o
+OBJS-$(CONFIG_SVQ1_ENCODER)            += svq1enc.o svq1.o  h263data.o  \
                                           h263.o ituh263enc.o
-OBJS-$(CONFIG_SVQ3_DECODER)            += svq3.o svq13.o mpegutils.o
+OBJS-$(CONFIG_SVQ3_DECODER)            += svq3.o svq13.o mpegutils.o h264_parse.o h264data.o
 OBJS-$(CONFIG_TEXT_DECODER)            += textdec.o ass.o
 OBJS-$(CONFIG_TEXT_ENCODER)            += srtenc.o ass_split.o
 OBJS-$(CONFIG_TAK_DECODER)             += takdec.o tak.o takdsp.o
@@ -515,6 +543,7 @@ OBJS-$(CONFIG_TMV_DECODER)             += tmv.o cga_data.o
 OBJS-$(CONFIG_TRUEHD_DECODER)          += mlpdec.o mlpdsp.o
 OBJS-$(CONFIG_TRUEMOTION1_DECODER)     += truemotion1.o
 OBJS-$(CONFIG_TRUEMOTION2_DECODER)     += truemotion2.o
+OBJS-$(CONFIG_TRUEMOTION2RT_DECODER)   += truemotion2rt.o
 OBJS-$(CONFIG_TRUESPEECH_DECODER)      += truespeech.o
 OBJS-$(CONFIG_TSCC_DECODER)            += tscc.o msrledec.o
 OBJS-$(CONFIG_TSCC2_DECODER)           += tscc2.o
@@ -527,20 +556,20 @@ OBJS-$(CONFIG_UTVIDEO_DECODER)         += utvideodec.o utvideo.o
 OBJS-$(CONFIG_UTVIDEO_ENCODER)         += utvideoenc.o utvideo.o
 OBJS-$(CONFIG_V210_DECODER)            += v210dec.o
 OBJS-$(CONFIG_V210_ENCODER)            += v210enc.o
+OBJS-$(CONFIG_V210X_DECODER)           += v210x.o
 OBJS-$(CONFIG_V308_DECODER)            += v308dec.o
 OBJS-$(CONFIG_V308_ENCODER)            += v308enc.o
 OBJS-$(CONFIG_V408_DECODER)            += v408dec.o
 OBJS-$(CONFIG_V408_ENCODER)            += v408enc.o
 OBJS-$(CONFIG_V410_DECODER)            += v410dec.o
 OBJS-$(CONFIG_V410_ENCODER)            += v410enc.o
-OBJS-$(CONFIG_V210X_DECODER)           += v210x.o
 OBJS-$(CONFIG_VB_DECODER)              += vb.o
 OBJS-$(CONFIG_VBLE_DECODER)            += vble.o
 OBJS-$(CONFIG_VC1_DECODER)             += vc1dec.o vc1_block.o vc1_loopfilter.o \
                                           vc1_mc.o vc1_pred.o vc1.o vc1data.o \
-                                          vc1dsp.o \
                                           msmpeg4dec.o msmpeg4.o msmpeg4data.o \
-                                          wmv2dsp.o
+                                          wmv2dsp.o wmv2data.o
+OBJS-$(CONFIG_VC1_CUVID_DECODER)       += cuvid.o
 OBJS-$(CONFIG_VC1_MMAL_DECODER)        += mmaldec.o
 OBJS-$(CONFIG_VC1_QSV_DECODER)         += qsvdec_vc1.o
 OBJS-$(CONFIG_VC2_ENCODER)             += vc2enc.o vc2enc_dwt.o diractab.o
@@ -558,8 +587,10 @@ OBJS-$(CONFIG_VP6_DECODER)             += vp6.o vp56.o vp56data.o \
                                           vp6dsp.o vp56rac.o
 OBJS-$(CONFIG_VP7_DECODER)             += vp8.o vp56rac.o
 OBJS-$(CONFIG_VP8_DECODER)             += vp8.o vp56rac.o
+OBJS-$(CONFIG_VP8_CUVID_DECODER)       += cuvid.o
 OBJS-$(CONFIG_VP9_DECODER)             += vp9.o vp9dsp.o vp56rac.o vp9dsp_8bpp.o \
                                           vp9dsp_10bpp.o vp9dsp_12bpp.o
+OBJS-$(CONFIG_VP9_CUVID_DECODER)       += cuvid.o
 OBJS-$(CONFIG_VPLAYER_DECODER)         += textdec.o ass.o
 OBJS-$(CONFIG_VQA_DECODER)             += vqavideo.o
 OBJS-$(CONFIG_WAVPACK_DECODER)         += wavpack.o
@@ -578,13 +609,13 @@ OBJS-$(CONFIG_WMAVOICE_DECODER)        += wmavoice.o \
                                           acelp_vectors.o acelp_filters.o
 OBJS-$(CONFIG_WMV1_DECODER)            += msmpeg4dec.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_WMV1_ENCODER)            += msmpeg4enc.o
-OBJS-$(CONFIG_WMV2_DECODER)            += wmv2dec.o wmv2.o \
+OBJS-$(CONFIG_WMV2_DECODER)            += wmv2dec.o wmv2.o wmv2data.o \
                                           msmpeg4dec.o msmpeg4.o msmpeg4data.o
-OBJS-$(CONFIG_WMV2_ENCODER)            += wmv2enc.o wmv2.o \
+OBJS-$(CONFIG_WMV2_ENCODER)            += wmv2enc.o wmv2.o wmv2data.o \
                                           msmpeg4.o msmpeg4enc.o msmpeg4data.o
 OBJS-$(CONFIG_WNV1_DECODER)            += wnv1.o
-OBJS-$(CONFIG_WS_SND1_DECODER)         += ws-snd1.o
 OBJS-$(CONFIG_WRAPPED_AVFRAME_ENCODER) += wrapped_avframe.o
+OBJS-$(CONFIG_WS_SND1_DECODER)         += ws-snd1.o
 OBJS-$(CONFIG_XAN_DPCM_DECODER)        += dpcm.o
 OBJS-$(CONFIG_XAN_WC3_DECODER)         += xan.o
 OBJS-$(CONFIG_XAN_WC4_DECODER)         += xxan.o
@@ -602,6 +633,7 @@ OBJS-$(CONFIG_XWD_DECODER)             += xwddec.o
 OBJS-$(CONFIG_XWD_ENCODER)             += xwdenc.o
 OBJS-$(CONFIG_Y41P_DECODER)            += y41pdec.o
 OBJS-$(CONFIG_Y41P_ENCODER)            += y41penc.o
+OBJS-$(CONFIG_YLC_DECODER)             += ylc.o
 OBJS-$(CONFIG_YOP_DECODER)             += yop.o
 OBJS-$(CONFIG_YUV4_DECODER)            += yuv4dec.o
 OBJS-$(CONFIG_YUV4_ENCODER)            += yuv4enc.o
@@ -689,6 +721,7 @@ OBJS-$(CONFIG_ADPCM_G726_ENCODER)         += g726.o
 OBJS-$(CONFIG_ADPCM_G726LE_DECODER)       += g726.o
 OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_APC_DECODER)      += adpcm.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_IMA_DAT4_DECODER)     += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER)  += adpcm.o adpcm_data.o
@@ -704,6 +737,7 @@ OBJS-$(CONFIG_ADPCM_IMA_WAV_ENCODER)      += adpcmenc.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_IMA_WS_DECODER)       += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_MS_DECODER)           += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_MS_ENCODER)           += adpcmenc.o adpcm_data.o
+OBJS-$(CONFIG_ADPCM_MTAF_DECODER)         += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_PSX_DECODER)          += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_SBPRO_2_DECODER)      += adpcm.o adpcm_data.o
 OBJS-$(CONFIG_ADPCM_SBPRO_3_DECODER)      += adpcm.o adpcm_data.o
@@ -757,28 +791,24 @@ OBJS-$(CONFIG_VP9_DXVA2_HWACCEL)          += dxva2_vp9.o
 OBJS-$(CONFIG_VP9_VAAPI_HWACCEL)          += vaapi_vp9.o
 
 # libavformat dependencies
+OBJS-$(CONFIG_ISO_MEDIA)               += mpeg4audio.o mpegaudiodata.o
+
 OBJS-$(CONFIG_ADTS_MUXER)              += mpeg4audio.o
-OBJS-$(CONFIG_AVI_DEMUXER)             += mpeg4audio.o mpegaudiodata.o
-OBJS-$(CONFIG_CAF_DEMUXER)             += mpeg4audio.o mpegaudiodata.o  \
-                                          ac3tab.o
+OBJS-$(CONFIG_CAF_DEMUXER)             += ac3tab.o
+OBJS-$(CONFIG_DNXHD_DEMUXER)           += dnxhddata.o
 OBJS-$(CONFIG_FLAC_DEMUXER)            += flac.o flacdata.o vorbis_data.o
 OBJS-$(CONFIG_FLAC_MUXER)              += flac.o flacdata.o vorbis_data.o
 OBJS-$(CONFIG_FLV_DEMUXER)             += mpeg4audio.o
 OBJS-$(CONFIG_GXF_DEMUXER)             += mpeg12data.o
 OBJS-$(CONFIG_IFF_DEMUXER)             += iff.o
-OBJS-$(CONFIG_ISMV_MUXER)              += mpeg4audio.o mpegaudiodata.o
 OBJS-$(CONFIG_LATM_MUXER)              += mpeg4audio.o
 OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER)    += mpeg4audio.o vorbis_data.o    \
                                           flac.o flacdata.o
-OBJS-$(CONFIG_MATROSKA_DEMUXER)        += mpeg4audio.o mpegaudiodata.o
-OBJS-$(CONFIG_MATROSKA_MUXER)          += mpeg4audio.o mpegaudiodata.o  \
-                                          flac.o flacdata.o vorbis_data.o
+OBJS-$(CONFIG_MATROSKA_MUXER)          += flac.o flacdata.o vorbis_data.o
+OBJS-$(CONFIG_MOV_DEMUXER)             += ac3tab.o
 OBJS-$(CONFIG_MP2_MUXER)               += mpegaudiodata.o mpegaudiodecheader.o
 OBJS-$(CONFIG_MP3_MUXER)               += mpegaudiodata.o mpegaudiodecheader.o
-OBJS-$(CONFIG_MOV_DEMUXER)             += mpeg4audio.o mpegaudiodata.o ac3tab.o
-OBJS-$(CONFIG_MOV_MUXER)               += mpeg4audio.o mpegaudiodata.o
 OBJS-$(CONFIG_MPEGTS_MUXER)            += mpeg4audio.o
-OBJS-$(CONFIG_MPEGTS_DEMUXER)          += mpeg4audio.o mpegaudiodata.o
 OBJS-$(CONFIG_MXF_MUXER)               += dnxhddata.o
 OBJS-$(CONFIG_NUT_MUXER)               += mpegaudiodata.o
 OBJS-$(CONFIG_NUT_DEMUXER)             += mpegaudiodata.o mpeg4audio.o
@@ -794,14 +824,32 @@ OBJS-$(CONFIG_TAK_DEMUXER)             += tak.o
 OBJS-$(CONFIG_WEBM_MUXER)              += mpeg4audio.o mpegaudiodata.o  \
                                           flac.o flacdata.o \
                                           vorbis_data.o
-OBJS-$(CONFIG_WTV_DEMUXER)             += mpeg4audio.o mpegaudiodata.o
 
 # libavfilter dependencies
 OBJS-$(CONFIG_ELBG_FILTER)             += elbg.o
 
 # external codec libraries
+OBJS-$(CONFIG_AAC_AT_DECODER)             += audiotoolboxdec.o
+OBJS-$(CONFIG_AC3_AT_DECODER)             += audiotoolboxdec.o
+OBJS-$(CONFIG_ADPCM_IMA_QT_AT_DECODER)    += audiotoolboxdec.o
+OBJS-$(CONFIG_ALAC_AT_DECODER)            += audiotoolboxdec.o
+OBJS-$(CONFIG_AMR_NB_AT_DECODER)          += audiotoolboxdec.o
+OBJS-$(CONFIG_EAC3_AT_DECODER)            += audiotoolboxdec.o
+OBJS-$(CONFIG_GSM_MS_AT_DECODER)          += audiotoolboxdec.o
+OBJS-$(CONFIG_ILBC_AT_DECODER)            += audiotoolboxdec.o
+OBJS-$(CONFIG_MP1_AT_DECODER)             += audiotoolboxdec.o mpegaudiodecheader.o
+OBJS-$(CONFIG_MP2_AT_DECODER)             += audiotoolboxdec.o mpegaudiodecheader.o
+OBJS-$(CONFIG_MP3_AT_DECODER)             += audiotoolboxdec.o mpegaudiodecheader.o
+OBJS-$(CONFIG_PCM_MULAW_AT_DECODER)       += audiotoolboxdec.o
+OBJS-$(CONFIG_PCM_ALAW_AT_DECODER)        += audiotoolboxdec.o
+OBJS-$(CONFIG_QDMC_AT_DECODER)            += audiotoolboxdec.o
+OBJS-$(CONFIG_QDM2_AT_DECODER)            += audiotoolboxdec.o
+OBJS-$(CONFIG_AAC_AT_ENCODER)             += audiotoolboxenc.o
+OBJS-$(CONFIG_ALAC_AT_ENCODER)            += audiotoolboxenc.o
+OBJS-$(CONFIG_ILBC_AT_ENCODER)            += audiotoolboxenc.o
+OBJS-$(CONFIG_PCM_ALAW_AT_ENCODER)        += audiotoolboxenc.o
+OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER)       += audiotoolboxenc.o
 OBJS-$(CONFIG_LIBCELT_DECODER)            += libcelt_dec.o
-OBJS-$(CONFIG_LIBDCADEC_DECODER)          += libdcadec.o dca.o
 OBJS-$(CONFIG_LIBFAAC_ENCODER)            += libfaac.o
 OBJS-$(CONFIG_LIBFDK_AAC_DECODER)         += libfdk-aacdec.o
 OBJS-$(CONFIG_LIBFDK_AAC_ENCODER)         += libfdk-aacenc.o
@@ -832,8 +880,6 @@ OBJS-$(CONFIG_LIBSPEEX_DECODER)           += libspeexdec.o
 OBJS-$(CONFIG_LIBSPEEX_ENCODER)           += libspeexenc.o
 OBJS-$(CONFIG_LIBTHEORA_ENCODER)          += libtheoraenc.o
 OBJS-$(CONFIG_LIBTWOLAME_ENCODER)         += libtwolame.o
-OBJS-$(CONFIG_LIBUTVIDEO_DECODER)         += libutvideodec.o
-OBJS-$(CONFIG_LIBUTVIDEO_ENCODER)         += libutvideoenc.o
 OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER)     += libvo-amrwbenc.o
 OBJS-$(CONFIG_LIBVORBIS_DECODER)          += libvorbisdec.o
 OBJS-$(CONFIG_LIBVORBIS_ENCODER)          += libvorbisenc.o \
@@ -853,16 +899,16 @@ OBJS-$(CONFIG_LIBXVID_ENCODER)            += libxvid.o
 OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER)   += libzvbi-teletextdec.o
 
 # parsers
+OBJS-$(CONFIG_AAC_LATM_PARSER)         += latm_parser.o
 OBJS-$(CONFIG_AAC_PARSER)              += aac_parser.o aac_ac3_parser.o \
                                           aacadtsdec.o mpeg4audio.o
-OBJS-$(CONFIG_AAC_LATM_PARSER)         += latm_parser.o
 OBJS-$(CONFIG_AC3_PARSER)              += ac3_parser.o ac3tab.o \
                                           aac_ac3_parser.o
 OBJS-$(CONFIG_ADX_PARSER)              += adx_parser.o adx.o
 OBJS-$(CONFIG_BMP_PARSER)              += bmp_parser.o
 OBJS-$(CONFIG_CAVSVIDEO_PARSER)        += cavs_parser.o
 OBJS-$(CONFIG_COOK_PARSER)             += cook_parser.o
-OBJS-$(CONFIG_DCA_PARSER)              += dca_parser.o dca.o
+OBJS-$(CONFIG_DCA_PARSER)              += dca_parser.o dca_exss.o dca.o
 OBJS-$(CONFIG_DIRAC_PARSER)            += dirac_parser.o
 OBJS-$(CONFIG_DNXHD_PARSER)            += dnxhd_parser.o
 OBJS-$(CONFIG_DPX_PARSER)              += dpx_parser.o
@@ -876,8 +922,9 @@ OBJS-$(CONFIG_G729_PARSER)             += g729_parser.o
 OBJS-$(CONFIG_GSM_PARSER)              += gsm_parser.o
 OBJS-$(CONFIG_H261_PARSER)             += h261_parser.o
 OBJS-$(CONFIG_H263_PARSER)             += h263_parser.o
-OBJS-$(CONFIG_H264_PARSER)             += h264_parser.o
-OBJS-$(CONFIG_HEVC_PARSER)             += hevc_parser.o hevc_parse.o hevc_ps.o hevc_data.o
+OBJS-$(CONFIG_H264_PARSER)             += h264_parser.o h264_parse.o h2645_parse.o \
+                                          h264_ps.o h264_sei.o h264data.o
+OBJS-$(CONFIG_HEVC_PARSER)             += hevc_parser.o h2645_parse.o hevc_ps.o hevc_data.o
 OBJS-$(CONFIG_MJPEG_PARSER)            += mjpeg_parser.o
 OBJS-$(CONFIG_MLP_PARSER)              += mlp_parser.o mlp.o
 OBJS-$(CONFIG_MPEG4VIDEO_PARSER)       += mpeg4video_parser.o h263.o \
@@ -894,7 +941,8 @@ OBJS-$(CONFIG_PNM_PARSER)              += pnm_parser.o pnm.o
 OBJS-$(CONFIG_RV30_PARSER)             += rv34_parser.o
 OBJS-$(CONFIG_RV40_PARSER)             += rv34_parser.o
 OBJS-$(CONFIG_TAK_PARSER)              += tak_parser.o tak.o
-OBJS-$(CONFIG_VC1_PARSER)              += vc1_parser.o
+OBJS-$(CONFIG_VC1_PARSER)              += vc1_parser.o vc1.o vc1data.o  \
+                                          simple_idct.o wmv2data.o
 OBJS-$(CONFIG_VP3_PARSER)              += vp3_parser.o
 OBJS-$(CONFIG_VP8_PARSER)              += vp8_parser.o
 OBJS-$(CONFIG_VP9_PARSER)              += vp9_parser.o
@@ -904,6 +952,7 @@ OBJS-$(CONFIG_AAC_ADTSTOASC_BSF)          += aac_adtstoasc_bsf.o aacadtsdec.o \
                                              mpeg4audio.o
 OBJS-$(CONFIG_CHOMP_BSF)                  += chomp_bsf.o
 OBJS-$(CONFIG_DUMP_EXTRADATA_BSF)         += dump_extradata_bsf.o
+OBJS-$(CONFIG_DCA_CORE_BSF)               += dca_core_bsf.o
 OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF)       += h264_mp4toannexb_bsf.o
 OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF)       += hevc_mp4toannexb_bsf.o
 OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF)        += imx_dump_header_bsf.o
@@ -916,6 +965,7 @@ OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF)  += mp3_header_decompress_bsf.o \
 OBJS-$(CONFIG_NOISE_BSF)                  += noise_bsf.o
 OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF)       += remove_extradata_bsf.o
 OBJS-$(CONFIG_TEXT2MOVSUB_BSF)            += movsub_bsf.o
+OBJS-$(CONFIG_VP9_SUPERFRAME_BSF)         += vp9_superframe_bsf.o
 
 # thread libraries
 OBJS-$(HAVE_LIBC_MSVCRT)               += file_open.o
@@ -939,15 +989,17 @@ SKIPHEADERS                            += %_tablegen.h                  \
 
 SKIPHEADERS-$(CONFIG_D3D11VA)          += d3d11va.h dxva2_internal.h
 SKIPHEADERS-$(CONFIG_DXVA2)            += dxva2.h dxva2_internal.h
+SKIPHEADERS-$(CONFIG_JNI)              += ffjni.h
 SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER)  += libschroedinger.h
-SKIPHEADERS-$(CONFIG_LIBUTVIDEO)       += libutvideo.h
 SKIPHEADERS-$(CONFIG_LIBVPX)           += libvpx.h
 SKIPHEADERS-$(CONFIG_LIBWEBP_ENCODER)  += libwebpenc_common.h
+SKIPHEADERS-$(CONFIG_MEDIACODEC)       += mediacodecdec.h mediacodec_wrapper.h mediacodec_sw_buffer.h
+SKIPHEADERS-$(CONFIG_NVENC)            += nvenc.h
 SKIPHEADERS-$(CONFIG_QSV)              += qsv.h qsv_internal.h
 SKIPHEADERS-$(CONFIG_QSVDEC)           += qsvdec.h
 SKIPHEADERS-$(CONFIG_QSVENC)           += qsvenc.h
 SKIPHEADERS-$(CONFIG_XVMC)             += xvmc.h
-SKIPHEADERS-$(CONFIG_VAAPI)            += vaapi_internal.h
+SKIPHEADERS-$(CONFIG_VAAPI)            += vaapi_encode.h vaapi_internal.h
 SKIPHEADERS-$(CONFIG_VDA)              += vda.h vda_vt_internal.h
 SKIPHEADERS-$(CONFIG_VDPAU)            += vdpau.h vdpau_internal.h
 SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX)     += videotoolbox.h vda_vt_internal.h
@@ -956,14 +1008,15 @@ TESTPROGS = imgconvert                                                  \
             jpeg2000dwt                                                 \
             mathops                                                    \
             options                                                     \
-            avfft                                                       \
+            utils                                                       \
 
 TESTPROGS-$(CONFIG_CABAC)                 += cabac
+TESTPROGS-$(CONFIG_DCT)                   += avfft
 TESTPROGS-$(CONFIG_FFT)                   += fft fft-fixed fft-fixed32
+TESTPROGS-$(CONFIG_GOLOMB)                += golomb
 TESTPROGS-$(CONFIG_IDCTDSP)               += dct
 TESTPROGS-$(CONFIG_IIRFILTER)             += iirfilter
 TESTPROGS-$(HAVE_MMX)                     += motion
-TESTPROGS-$(CONFIG_GOLOMB)                += golomb
 TESTPROGS-$(CONFIG_RANGECODER)            += rangecoder
 TESTPROGS-$(CONFIG_SNOW_ENCODER)          += snowenc
 
@@ -986,7 +1039,7 @@ HOSTPROGS = aacps_tablegen                                              \
 
 CLEANFILES = *_tables.c *_tables.h *_tablegen$(HOSTEXESUF)
 
-$(SUBDIR)dct-test$(EXESUF): $(SUBDIR)dctref.o $(SUBDIR)aandcttab.o
+$(SUBDIR)tests/dct$(EXESUF): $(SUBDIR)dctref.o $(SUBDIR)aandcttab.o
 $(SUBDIR)dv_tablegen$(HOSTEXESUF): $(SUBDIR)dvdata_host.o
 
 TRIG_TABLES  = cos cos_fixed sin
@@ -1011,17 +1064,17 @@ $(GEN_HEADERS): $(SUBDIR)%_tables.h: $(SUBDIR)%_tablegen$(HOSTEXESUF)
 	$(M)./$< > $@
 
 ifdef CONFIG_HARDCODED_TABLES
-$(SUBDIR)aacdec.o: $(SUBDIR)cbrt_tables.h
-$(SUBDIR)aacdec_fixed.o: $(SUBDIR)cbrt_fixed_tables.h
+$(SUBDIR)cbrt_data.o: $(SUBDIR)cbrt_tables.h
+$(SUBDIR)cbrt_data_fixed.o: $(SUBDIR)cbrt_fixed_tables.h
 $(SUBDIR)aacps_float.o: $(SUBDIR)aacps_tables.h
 $(SUBDIR)aacps_fixed.o: $(SUBDIR)aacps_fixed_tables.h
 $(SUBDIR)aactab_fixed.o: $(SUBDIR)aac_fixed_tables.h
 $(SUBDIR)dvenc.o: $(SUBDIR)dv_tables.h
-$(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h
-$(SUBDIR)sinewin_fixed.o: $(SUBDIR)sinewin_fixed_tables.h
+$(SUBDIR)motionpixels.o: $(SUBDIR)motionpixels_tables.h
 $(SUBDIR)mpegaudiodec_fixed.o: $(SUBDIR)mpegaudio_tables.h
 $(SUBDIR)mpegaudiodec_float.o: $(SUBDIR)mpegaudio_tables.h
-$(SUBDIR)motionpixels.o: $(SUBDIR)motionpixels_tables.h
 $(SUBDIR)pcm.o: $(SUBDIR)pcm_tables.h
 $(SUBDIR)qdm2.o: $(SUBDIR)qdm2_tables.h
+$(SUBDIR)sinewin.o: $(SUBDIR)sinewin_tables.h
+$(SUBDIR)sinewin_fixed.o: $(SUBDIR)sinewin_fixed_tables.h
 endif
diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c
index 2f7d568..c9ba6bf 100644
--- a/libavcodec/aac_ac3_parser.c
+++ b/libavcodec/aac_ac3_parser.c
@@ -34,6 +34,7 @@ int ff_aac_ac3_parse(AVCodecParserContext *s1,
     ParseContext *pc = &s->pc;
     int len, i;
     int new_frame_start;
+    int got_frame = 0;
 
 get_next:
     i=END_NOT_FOUND;
@@ -51,6 +52,7 @@ get_next:
             if(len<=0){
                 i=END_NOT_FOUND;
             }else{
+                got_frame = 1;
                 s->state=0;
                 i-= s->header_size -1;
                 s->remaining_size = len;
@@ -76,31 +78,34 @@ get_next:
     if(s->codec_id)
         avctx->codec_id = s->codec_id;
 
-    /* Due to backwards compatible HE-AAC the sample rate, channel count,
-       and total number of samples found in an AAC ADTS header are not
-       reliable. Bit rate is still accurate because the total frame duration in
-       seconds is still correct (as is the number of bits in the frame). */
-    if (avctx->codec_id != AV_CODEC_ID_AAC) {
-        avctx->sample_rate = s->sample_rate;
+    if (got_frame) {
+        /* Due to backwards compatible HE-AAC the sample rate, channel count,
+           and total number of samples found in an AAC ADTS header are not
+           reliable. Bit rate is still accurate because the total frame
+           duration in seconds is still correct (as is the number of bits in
+           the frame). */
+        if (avctx->codec_id != AV_CODEC_ID_AAC) {
+            avctx->sample_rate = s->sample_rate;
 
-        /* (E-)AC-3: allow downmixing to stereo or mono */
-        if (s->channels > 1 &&
-            avctx->request_channel_layout == AV_CH_LAYOUT_MONO) {
-            avctx->channels       = 1;
-            avctx->channel_layout = AV_CH_LAYOUT_MONO;
-        } else if (s->channels > 2 &&
-                   avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
-            avctx->channels       = 2;
-            avctx->channel_layout = AV_CH_LAYOUT_STEREO;
-        } else {
-            avctx->channels = s->channels;
-            avctx->channel_layout = s->channel_layout;
+            /* (E-)AC-3: allow downmixing to stereo or mono */
+            if (s->channels > 1 &&
+                avctx->request_channel_layout == AV_CH_LAYOUT_MONO) {
+                avctx->channels       = 1;
+                avctx->channel_layout = AV_CH_LAYOUT_MONO;
+            } else if (s->channels > 2 &&
+                       avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+                avctx->channels       = 2;
+                avctx->channel_layout = AV_CH_LAYOUT_STEREO;
+            } else {
+                avctx->channels = s->channels;
+                avctx->channel_layout = s->channel_layout;
+            }
+            s1->duration = s->samples;
+            avctx->audio_service_type = s->service_type;
         }
-        s1->duration = s->samples;
-        avctx->audio_service_type = s->service_type;
-    }
 
-    avctx->bit_rate = s->bit_rate;
+        avctx->bit_rate = s->bit_rate;
+    }
 
     return i;
 }
diff --git a/libavcodec/aac_adtstoasc_bsf.c b/libavcodec/aac_adtstoasc_bsf.c
index 9c117c6..48889fc 100644
--- a/libavcodec/aac_adtstoasc_bsf.c
+++ b/libavcodec/aac_adtstoasc_bsf.c
@@ -21,6 +21,7 @@
 
 #include "avcodec.h"
 #include "aacadtsdec.h"
+#include "bsf.h"
 #include "put_bits.h"
 #include "get_bits.h"
 #include "mpeg4audio.h"
@@ -34,68 +35,75 @@ typedef struct AACBSFContext {
  * This filter creates an MPEG-4 AudioSpecificConfig from an MPEG-2/4
  * ADTS header and removes the ADTS header.
  */
-static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc,
-                                AVCodecContext *avctx, const char *args,
-                                uint8_t  **poutbuf, int *poutbuf_size,
-                                const uint8_t *buf, int      buf_size,
-                                int keyframe)
+static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out)
 {
+    AACBSFContext *ctx = bsfc->priv_data;
+
     GetBitContext gb;
     PutBitContext pb;
     AACADTSHeaderInfo hdr;
+    AVPacket *in;
+    int ret;
 
-    AACBSFContext *ctx = bsfc->priv_data;
+    ret = ff_bsf_get_packet(bsfc, &in);
+    if (ret < 0)
+        return ret;
 
-    init_get_bits(&gb, buf, AAC_ADTS_HEADER_SIZE*8);
+    if (in->size < AAC_ADTS_HEADER_SIZE)
+        goto packet_too_small;
 
-    *poutbuf = (uint8_t*) buf;
-    *poutbuf_size = buf_size;
+    init_get_bits(&gb, in->data, AAC_ADTS_HEADER_SIZE * 8);
 
-    if (avctx->extradata)
-        if (show_bits(&gb, 12) != 0xfff)
-            return 0;
+    if (bsfc->par_in->extradata && show_bits(&gb, 12) != 0xfff)
+        goto finish;
 
     if (avpriv_aac_parse_header(&gb, &hdr) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Error parsing ADTS frame header!\n");
-        return AVERROR_INVALIDDATA;
+        av_log(bsfc, AV_LOG_ERROR, "Error parsing ADTS frame header!\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
     }
 
     if (!hdr.crc_absent && hdr.num_aac_frames > 1) {
-        avpriv_report_missing_feature(avctx,
+        avpriv_report_missing_feature(bsfc,
                                       "Multiple RDBs per frame with CRC");
-        return AVERROR_PATCHWELCOME;
+        ret = AVERROR_PATCHWELCOME;
+        goto fail;
     }
 
-    buf      += AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent;
-    buf_size -= AAC_ADTS_HEADER_SIZE + 2*!hdr.crc_absent;
+    in->size -= AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
+    if (in->size <= 0)
+        goto packet_too_small;
+    in->data += AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
 
     if (!ctx->first_frame_done) {
         int            pce_size = 0;
         uint8_t        pce_data[MAX_PCE_SIZE];
+        uint8_t       *extradata;
+
         if (!hdr.chan_config) {
-            init_get_bits(&gb, buf, buf_size * 8);
+            init_get_bits(&gb, in->data, in->size * 8);
             if (get_bits(&gb, 3) != 5) {
-                avpriv_report_missing_feature(avctx,
+                avpriv_report_missing_feature(bsfc,
                                               "PCE-based channel configuration "
                                               "without PCE as first syntax "
                                               "element");
-                return AVERROR_PATCHWELCOME;
+                ret = AVERROR_PATCHWELCOME;
+                goto fail;
             }
             init_put_bits(&pb, pce_data, MAX_PCE_SIZE);
             pce_size = avpriv_copy_pce_data(&pb, &gb)/8;
             flush_put_bits(&pb);
-            buf_size -= get_bits_count(&gb)/8;
-            buf      += get_bits_count(&gb)/8;
+            in->size -= get_bits_count(&gb)/8;
+            in->data += get_bits_count(&gb)/8;
         }
-        av_free(avctx->extradata);
-        avctx->extradata_size = 2 + pce_size;
-        avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
-        if (!avctx->extradata) {
-            avctx->extradata_size = 0;
-            return AVERROR(ENOMEM);
+
+        extradata = av_mallocz(2 + pce_size + AV_INPUT_BUFFER_PADDING_SIZE);
+        if (!extradata) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
         }
 
-        init_put_bits(&pb, avctx->extradata, avctx->extradata_size);
+        init_put_bits(&pb, extradata, 2 + pce_size);
         put_bits(&pb, 5, hdr.object_type);
         put_bits(&pb, 4, hdr.sampling_index);
         put_bits(&pb, 4, hdr.chan_config);
@@ -104,20 +112,44 @@ static int aac_adtstoasc_filter(AVBitStreamFilterContext *bsfc,
         put_bits(&pb, 1, 0); //is not extension
         flush_put_bits(&pb);
         if (pce_size) {
-            memcpy(avctx->extradata + 2, pce_data, pce_size);
+            memcpy(extradata + 2, pce_data, pce_size);
         }
 
+        bsfc->par_out->extradata = extradata;
+        bsfc->par_out->extradata_size = 2 + pce_size;
         ctx->first_frame_done = 1;
     }
 
-    *poutbuf = (uint8_t*) buf;
-    *poutbuf_size = buf_size;
+finish:
+    av_packet_move_ref(out, in);
+    av_packet_free(&in);
 
     return 0;
+
+packet_too_small:
+    av_log(bsfc, AV_LOG_ERROR, "Input packet too small\n");
+    ret = AVERROR_INVALIDDATA;
+fail:
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_aac_adtstoasc_bsf = {
+static int aac_adtstoasc_init(AVBSFContext *ctx)
+{
+    av_freep(&ctx->par_out->extradata);
+    ctx->par_out->extradata_size = 0;
+
+    return 0;
+}
+
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_AAC, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_aac_adtstoasc_bsf = {
     .name           = "aac_adtstoasc",
     .priv_data_size = sizeof(AACBSFContext),
+    .init           = aac_adtstoasc_init,
     .filter         = aac_adtstoasc_filter,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/aac_defines.h b/libavcodec/aac_defines.h
index eff63b3..c12dc2f 100644
--- a/libavcodec/aac_defines.h
+++ b/libavcodec/aac_defines.h
@@ -89,9 +89,9 @@ typedef float               AAC_FLOAT;
 typedef unsigned            AAC_SIGNE;
 #define FIXR(x)             ((float)(x))
 #define FIXR10(x)           ((float)(x))
-#define Q23(x)              x
-#define Q30(x)              x
-#define Q31(x)              x
+#define Q23(x)              ((float)(x))
+#define Q30(x)              ((float)(x))
+#define Q31(x)              ((float)(x))
 #define RANGE15(x)          (32768.0 * (x))
 #define GET_GAIN(x, y)      powf((x), -(y))
 #define AAC_MUL16(x, y)     ((x) * (y))
diff --git a/libavcodec/aaccoder_twoloop.h b/libavcodec/aaccoder_twoloop.h
index 397a4db..42aea52 100644
--- a/libavcodec/aaccoder_twoloop.h
+++ b/libavcodec/aaccoder_twoloop.h
@@ -77,7 +77,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
     int toomanybits, toofewbits;
     char nzs[128];
     uint8_t nextband[128];
-    int maxsf[128];
+    int maxsf[128], minsf[128];
     float dists[128] = { 0 }, qenergies[128] = { 0 }, uplims[128], euplims[128], energies[128];
     float maxvals[128], spread_thr_r[128];
     float min_spread_thr_r, max_spread_thr_r;
@@ -294,11 +294,19 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
     abs_pow34_v(s->scoefs, sce->coeffs, 1024);
     ff_quantize_band_cost_cache_init(s);
 
+    for (i = 0; i < sizeof(minsf) / sizeof(minsf[0]); ++i)
+        minsf[i] = 0;
     for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
         start = w*128;
         for (g = 0;  g < sce->ics.num_swb; g++) {
             const float *scaled = s->scoefs + start;
+            int minsfidx;
             maxvals[w*16+g] = find_max_val(sce->ics.group_len[w], sce->ics.swb_sizes[g], scaled);
+            if (maxvals[w*16+g] > 0) {
+                minsfidx = coef2minsf(maxvals[w*16+g]);
+                for (w2 = 0; w2 < sce->ics.group_len[w]; w2++)
+                    minsf[(w+w2)*16+g] = minsfidx;
+            }
             start += sce->ics.swb_sizes[g];
         }
     }
@@ -425,7 +433,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
                 recomprd = 1;
                 for (i = 0; i < 128; i++) {
                     if (sce->sf_idx[i] > SCALE_ONE_POS) {
-                        int new_sf = FFMAX(SCALE_ONE_POS, sce->sf_idx[i] - qstep);
+                        int new_sf = FFMAX3(minsf[i], SCALE_ONE_POS, sce->sf_idx[i] - qstep);
                         if (new_sf != sce->sf_idx[i]) {
                             sce->sf_idx[i] = new_sf;
                             changed = 1;
@@ -595,7 +603,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
                     int cmb = find_min_book(maxvals[w*16+g], sce->sf_idx[w*16+g]);
                     int mindeltasf = FFMAX(0, prev - SCALE_MAX_DIFF);
                     int maxdeltasf = FFMIN(SCALE_MAX_POS - SCALE_DIV_512, prev + SCALE_MAX_DIFF);
-                    if ((!cmb || dists[w*16+g] > uplims[w*16+g]) && sce->sf_idx[w*16+g] > mindeltasf) {
+                    if ((!cmb || dists[w*16+g] > uplims[w*16+g]) && sce->sf_idx[w*16+g] > FFMAX(mindeltasf, minsf[w*16+g])) {
                         /* Try to make sure there is some energy in every nonzero band
                          * NOTE: This algorithm must be forcibly imbalanced, pushing harder
                          *  on holes or more distorted bands at first, otherwise there's
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 26bdea1..ee9b4eb 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -50,7 +50,7 @@
 #include "aac.h"
 #include "aactab.h"
 #include "aacdectab.h"
-#include "cbrt_tablegen.h"
+#include "cbrt_data.h"
 #include "sbr.h"
 #include "aacsbr.h"
 #include "mpeg4audio.h"
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 396a874..acb8178 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -75,7 +75,7 @@
 #include "aac.h"
 #include "aactab.h"
 #include "aacdectab.h"
-#include "cbrt_tablegen.h"
+#include "cbrt_data.h"
 #include "sbr.h"
 #include "aacsbr.h"
 #include "mpeg4audio.h"
@@ -155,9 +155,9 @@ static void vector_pow43(int *coefs, int len)
     for (i=0; i<len; i++) {
         coef = coefs[i];
         if (coef < 0)
-            coef = -(int)cbrt_tab[-coef];
+            coef = -(int)ff_cbrt_tab_fixed[-coef];
         else
-            coef = (int)cbrt_tab[coef];
+            coef = (int)ff_cbrt_tab_fixed[coef];
         coefs[i] = coef;
     }
 }
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 6bc94c8..883ed52 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1104,7 +1104,7 @@ static av_cold void aac_static_table_init(void)
     AAC_RENAME(ff_init_ff_sine_windows)( 9);
     AAC_RENAME(ff_init_ff_sine_windows)( 7);
 
-    AAC_RENAME(cbrt_tableinit)();
+    AAC_RENAME(ff_cbrt_tableinit)();
 }
 
 static AVOnce aac_table_init = AV_ONCE_INIT;
@@ -1795,7 +1795,7 @@ static int decode_spectrum_and_dequant(AACContext *ac, INTFLOAT coef[1024],
                                         v = -v;
                                     *icf++ = v;
 #else
-                                    *icf++ = cbrt_tab[n] | (bits & 1U<<31);
+                                    *icf++ = ff_cbrt_tab[n] | (bits & 1U<<31);
 #endif /* USE_FIXED */
                                     bits <<= 1;
                                 } else {
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 5a70da1..2653cef 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -78,11 +78,10 @@ static void put_audio_specific_config(AVCodecContext *avctx)
 
 void ff_quantize_band_cost_cache_init(struct AACEncContext *s)
 {
-    int sf, g;
-    for (sf = 0; sf < 256; sf++) {
-        for (g = 0; g < 128; g++) {
-            s->quantize_band_cost_cache[sf][g].bits = -1;
-        }
+    ++s->quantize_band_cost_cache_generation;
+    if (s->quantize_band_cost_cache_generation == 0) {
+        memset(s->quantize_band_cost_cache, 0, sizeof(s->quantize_band_cost_cache));
+        s->quantize_band_cost_cache_generation = 1;
     }
 }
 
@@ -555,10 +554,11 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
             if (!frame)
                 la = NULL;
             if (tag == TYPE_LFE) {
-                wi[ch].window_type[0] = ONLY_LONG_SEQUENCE;
+                wi[ch].window_type[0] = wi[ch].window_type[1] = ONLY_LONG_SEQUENCE;
                 wi[ch].window_shape   = 0;
                 wi[ch].num_windows    = 1;
                 wi[ch].grouping[0]    = 1;
+                wi[ch].clipping[0]    = 0;
 
                 /* Only the lowest 12 coefficients are used in a LFE channel.
                  * The expression below results in only the bottom 8 coefficients
@@ -583,9 +583,22 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
             ics->tns_max_bands      = wi[ch].window_type[0] == EIGHT_SHORT_SEQUENCE ?
                                         ff_tns_max_bands_128 [s->samplerate_index]:
                                         ff_tns_max_bands_1024[s->samplerate_index];
-            clip_avoidance_factor = 0.0f;
+
             for (w = 0; w < ics->num_windows; w++)
                 ics->group_len[w] = wi[ch].grouping[w];
+
+            /* Calculate input sample maximums and evaluate clipping risk */
+            clip_avoidance_factor = 0.0f;
+            for (w = 0; w < ics->num_windows; w++) {
+                const float *wbuf = overlap + w * 128;
+                const int wlen = 2048 / ics->num_windows;
+                float max = 0;
+                int j;
+                /* mdct input is 2 * output */
+                for (j = 0; j < wlen; j++)
+                    max = FFMAX(max, fabsf(wbuf[j]));
+                wi[ch].clipping[w] = max;
+            }
             for (w = 0; w < ics->num_windows; w++) {
                 if (wi[ch].clipping[w] > CLIP_AVOIDANCE_FACTOR) {
                     ics->window_clipping[w] = 1;
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index 2252e29..63e7893 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -84,10 +84,10 @@ extern AACCoefficientsEncoder ff_aac_coders[];
 typedef struct AACQuantizeBandCostCacheEntry {
     float rd;
     float energy;
-    int bits; ///< -1 means uninitialized entry
+    int bits;
     char cb;
     char rtz;
-    char padding[2]; ///< Keeps the entry size a multiple of 32 bits
+    uint16_t generation;
 } AACQuantizeBandCostCacheEntry;
 
 /**
@@ -126,6 +126,7 @@ typedef struct AACEncContext {
     DECLARE_ALIGNED(16, int,   qcoefs)[96];      ///< quantized coefficients
     DECLARE_ALIGNED(32, float, scoefs)[1024];    ///< scaled coefficients
 
+    uint16_t quantize_band_cost_cache_generation;
     AACQuantizeBandCostCacheEntry quantize_band_cost_cache[256][128]; ///< memoization area for quantize_band_cost
 
     struct {
diff --git a/libavcodec/aacenc_quantization_misc.h b/libavcodec/aacenc_quantization_misc.h
index eaa71c9..28676ca 100644
--- a/libavcodec/aacenc_quantization_misc.h
+++ b/libavcodec/aacenc_quantization_misc.h
@@ -36,11 +36,12 @@ static inline float quantize_band_cost_cached(struct AACEncContext *s, int w, in
     AACQuantizeBandCostCacheEntry *entry;
     av_assert1(scale_idx >= 0 && scale_idx < 256);
     entry = &s->quantize_band_cost_cache[scale_idx][w*16+g];
-    if (entry->bits < 0 || entry->cb != cb || entry->rtz != rtz) {
+    if (entry->generation != s->quantize_band_cost_cache_generation || entry->cb != cb || entry->rtz != rtz) {
         entry->rd = quantize_band_cost(s, in, scaled, size, scale_idx,
                                        cb, lambda, uplim, &entry->bits, &entry->energy, rtz);
         entry->cb = cb;
         entry->rtz = rtz;
+        entry->generation = s->quantize_band_cost_cache_generation;
     }
     if (bits)
         *bits = entry->bits;
diff --git a/libavcodec/aacenc_utils.h b/libavcodec/aacenc_utils.h
index 07f7337..bb1dcb4 100644
--- a/libavcodec/aacenc_utils.h
+++ b/libavcodec/aacenc_utils.h
@@ -28,7 +28,7 @@
 #ifndef AVCODEC_AACENC_UTILS_H
 #define AVCODEC_AACENC_UTILS_H
 
-#include "libavutil/internal.h"
+#include "libavutil/ffmath.h"
 #include "aac.h"
 #include "aacenctab.h"
 #include "aactab.h"
diff --git a/libavcodec/aacpsy.c b/libavcodec/aacpsy.c
index 8643fe7..a5fec73 100644
--- a/libavcodec/aacpsy.c
+++ b/libavcodec/aacpsy.c
@@ -25,8 +25,7 @@
  */
 
 #include "libavutil/attributes.h"
-#include "libavutil/internal.h"
-#include "libavutil/libm.h"
+#include "libavutil/ffmath.h"
 
 #include "avcodec.h"
 #include "aactab.h"
@@ -686,7 +685,7 @@ static void psy_3gpp_analyze_channel(FFPsyContext *ctx, int channel,
 
             band->thr_quiet = band->thr = FFMAX(band->thr, coeffs[g].ath);
             //5.4.2.5 "Pre-echo control"
-            if (!(wi->window_type[0] == LONG_STOP_SEQUENCE || (wi->window_type[1] == LONG_START_SEQUENCE && !w)))
+            if (!(wi->window_type[0] == LONG_STOP_SEQUENCE || (!w && wi->window_type[1] == LONG_START_SEQUENCE)))
                 band->thr = FFMAX(PSY_3GPP_RPEMIN*band->thr, FFMIN(band->thr,
                                   PSY_3GPP_RPELEV*pch->prev_band[w+g].thr_quiet));
 
@@ -886,13 +885,12 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio,
     int grouping     = 0;
     int uselongblock = 1;
     int attacks[AAC_NUM_BLOCKS_SHORT + 1] = { 0 };
-    float clippings[AAC_NUM_BLOCKS_SHORT];
     int i;
     FFPsyWindowInfo wi = { { 0 } };
 
     if (la) {
         float hpfsmpl[AAC_BLOCK_SIZE_LONG];
-        float const *pf = hpfsmpl;
+        const float *pf = hpfsmpl;
         float attack_intensity[(AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS];
         float energy_subshort[(AAC_NUM_BLOCKS_SHORT + 1) * PSY_LAME_NUM_SUBBLOCKS];
         float energy_short[AAC_NUM_BLOCKS_SHORT + 1] = { 0 };
@@ -911,7 +909,7 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio,
         }
 
         for (i = 0; i < AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS; i++) {
-            float const *const pfe = pf + AAC_BLOCK_SIZE_LONG / (AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS);
+            const float *const pfe = pf + AAC_BLOCK_SIZE_LONG / (AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS);
             float p = 1.0f;
             for (; pf < pfe; pf++)
                 p = FFMAX(p, fabsf(*pf));
@@ -944,9 +942,9 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio,
         /* GB: tuned (1) to avoid too many short blocks for test sample TRUMPET */
         /* RH: tuned (2) to let enough short blocks through for test sample FSOL and SNAPS */
         for (i = 1; i < AAC_NUM_BLOCKS_SHORT + 1; i++) {
-            float const u = energy_short[i - 1];
-            float const v = energy_short[i];
-            float const m = FFMAX(u, v);
+            const float u = energy_short[i - 1];
+            const float v = energy_short[i];
+            const float m = FFMAX(u, v);
             if (m < 40000) {                          /* (2) */
                 if (u < 1.7f * v && v < 1.7f * u) {   /* (1) */
                     if (i == 1 && attacks[0] < attacks[i])
@@ -976,24 +974,8 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio,
 
     lame_apply_block_type(pch, &wi, uselongblock);
 
-    /* Calculate input sample maximums and evaluate clipping risk */
-    if (audio) {
-        for (i = 0; i < AAC_NUM_BLOCKS_SHORT; i++) {
-            const float *wbuf = audio + i * AAC_BLOCK_SIZE_SHORT;
-            float max = 0;
-            int j;
-            for (j = 0; j < AAC_BLOCK_SIZE_SHORT; j++)
-                max = FFMAX(max, fabsf(wbuf[j]));
-            clippings[i] = max;
-        }
-    } else {
-        for (i = 0; i < 8; i++)
-            clippings[i] = 0;
-    }
-
     wi.window_type[1] = prev_type;
     if (wi.window_type[0] != EIGHT_SHORT_SEQUENCE) {
-        float clipping = 0.0f;
 
         wi.num_windows  = 1;
         wi.grouping[0]  = 1;
@@ -1002,9 +984,6 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio,
         else
             wi.window_shape = 1;
 
-        for (i = 0; i < 8; i++)
-            clipping = FFMAX(clipping, clippings[i]);
-        wi.clipping[0] = clipping;
     } else {
         int lastgrp = 0;
 
@@ -1015,14 +994,6 @@ static FFPsyWindowInfo psy_lame_window(FFPsyContext *ctx, const float *audio,
                 lastgrp = i;
             wi.grouping[lastgrp]++;
         }
-
-        for (i = 0; i < 8; i += wi.grouping[i]) {
-            int w;
-            float clipping = 0.0f;
-            for (w = 0; w < wi.grouping[i] && !clipping; w++)
-                clipping = FFMAX(clipping, clippings[i+w]);
-            wi.clipping[i] = clipping;
-        }
     }
 
     /* Determine grouping, based on the location of the first attack, and save for
diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c
index 733e619..5110542 100644
--- a/libavcodec/aacsbr_template.c
+++ b/libavcodec/aacsbr_template.c
@@ -1473,7 +1473,7 @@ void AAC_RENAME(ff_sbr_apply)(AACContext *ac, SpectralBandReplication *sbr, int
     int err;
 
     if (id_aac != sbr->id_aac) {
-        av_log(ac->avctx, AV_LOG_ERROR,
+        av_log(ac->avctx, id_aac == TYPE_LFE ? AV_LOG_VERBOSE : AV_LOG_WARNING,
             "element type mismatch %d != %d\n", id_aac, sbr->id_aac);
         sbr_turnoff(sbr);
     }
diff --git a/libavcodec/aactab.h b/libavcodec/aactab.h
index b48e7da..a0d44a2 100644
--- a/libavcodec/aactab.h
+++ b/libavcodec/aactab.h
@@ -92,8 +92,8 @@ static inline void ff_aac_tableinit(void)
  * Table of the LTP coefficients
  */
 static const INTFLOAT ltp_coef[8] = {
-    Q30(0.570829f), Q30(0.696616f), Q30(0.813004f), Q30(0.911304f),
-    Q30(0.984900f), Q30(1.067894f), Q30(1.194601f), Q30(1.369533f),
+    Q30(0.570829), Q30(0.696616), Q30(0.813004), Q30(0.911304),
+    Q30(0.984900), Q30(1.067894), Q30(1.194601), Q30(1.369533),
 };
 
 /* @name tns_tmp2_map
@@ -103,24 +103,24 @@ static const INTFLOAT ltp_coef[8] = {
  * @{
  */
 static const INTFLOAT tns_tmp2_map_1_3[4] = {
-    Q31(0.00000000f), Q31(-0.43388373f),  Q31(0.64278758f),  Q31(0.34202015f),
+    Q31(0.00000000), Q31(-0.43388373),  Q31(0.64278758),  Q31(0.34202015),
 };
 
 static const INTFLOAT tns_tmp2_map_0_3[8] = {
-    Q31(0.00000000f), Q31(-0.43388373f), Q31(-0.78183150f), Q31(-0.97492790f),
-    Q31(0.98480773f), Q31( 0.86602539f), Q31( 0.64278758f), Q31( 0.34202015f),
+    Q31(0.00000000), Q31(-0.43388373), Q31(-0.78183150), Q31(-0.97492790),
+    Q31(0.98480773), Q31( 0.86602539), Q31( 0.64278758), Q31( 0.34202015),
 };
 
 static const INTFLOAT tns_tmp2_map_1_4[8] = {
-    Q31(0.00000000f), Q31(-0.20791170f), Q31(-0.40673664f), Q31(-0.58778524f),
-    Q31(0.67369562f), Q31( 0.52643216f), Q31( 0.36124167f), Q31( 0.18374951f),
+    Q31(0.00000000), Q31(-0.20791170), Q31(-0.40673664), Q31(-0.58778524),
+    Q31(0.67369562), Q31( 0.52643216), Q31( 0.36124167), Q31( 0.18374951),
 };
 
 static const INTFLOAT tns_tmp2_map_0_4[16] = {
-    Q31( 0.00000000f), Q31(-0.20791170f), Q31(-0.40673664f), Q31(-0.58778524f),
-    Q31(-0.74314481f), Q31(-0.86602539f), Q31(-0.95105654f), Q31(-0.99452192f),
-    Q31( 0.99573416f), Q31( 0.96182561f), Q31( 0.89516330f), Q31( 0.79801720f),
-    Q31( 0.67369562f), Q31( 0.52643216f), Q31( 0.36124167f), Q31( 0.18374951f),
+    Q31( 0.00000000), Q31(-0.20791170), Q31(-0.40673664), Q31(-0.58778524),
+    Q31(-0.74314481), Q31(-0.86602539), Q31(-0.95105654), Q31(-0.99452192),
+    Q31( 0.99573416), Q31( 0.96182561), Q31( 0.89516330), Q31( 0.79801720),
+    Q31( 0.67369562), Q31( 0.52643216), Q31( 0.36124167), Q31( 0.18374951),
 };
 
 static const INTFLOAT * const tns_tmp2_map[4] = {
diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile
index fd89035..36d9d34 100644
--- a/libavcodec/aarch64/Makefile
+++ b/libavcodec/aarch64/Makefile
@@ -1,4 +1,4 @@
-OBJS-$(CONFIG_DCA_DECODER)              += aarch64/synth_filter_init.o
+# subsystems
 OBJS-$(CONFIG_FFT)                      += aarch64/fft_init_aarch64.o
 OBJS-$(CONFIG_FMTCONVERT)               += aarch64/fmtconvert_init.o
 OBJS-$(CONFIG_H264CHROMA)               += aarch64/h264chroma_init_aarch64.o
@@ -11,13 +11,20 @@ OBJS-$(CONFIG_MPEGAUDIODSP)             += aarch64/mpegaudiodsp_init.o
 OBJS-$(CONFIG_NEON_CLOBBER_TEST)        += aarch64/neontest.o
 OBJS-$(CONFIG_VIDEODSP)                 += aarch64/videodsp_init.o
 
+# decoders/encoders
+OBJS-$(CONFIG_DCA_DECODER)              += aarch64/synth_filter_init.o
 OBJS-$(CONFIG_RV40_DECODER)             += aarch64/rv40dsp_init_aarch64.o
 OBJS-$(CONFIG_VC1_DECODER)              += aarch64/vc1dsp_init_aarch64.o
 OBJS-$(CONFIG_VORBIS_DECODER)           += aarch64/vorbisdsp_init.o
 
+# ARMv8 optimizations
+
+# subsystems
 ARMV8-OBJS-$(CONFIG_VIDEODSP)           += aarch64/videodsp.o
 
-NEON-OBJS-$(CONFIG_DCA_DECODER)         += aarch64/synth_filter_neon.o
+# NEON optimizations
+
+# subsystems
 NEON-OBJS-$(CONFIG_FFT)                 += aarch64/fft_neon.o
 NEON-OBJS-$(CONFIG_FMTCONVERT)          += aarch64/fmtconvert_neon.o
 NEON-OBJS-$(CONFIG_H264CHROMA)          += aarch64/h264cmc_neon.o
@@ -28,7 +35,9 @@ NEON-OBJS-$(CONFIG_H264QPEL)            += aarch64/h264qpel_neon.o             \
                                            aarch64/hpeldsp_neon.o
 NEON-OBJS-$(CONFIG_HPELDSP)             += aarch64/hpeldsp_neon.o
 NEON-OBJS-$(CONFIG_IMDCT15)             += aarch64/imdct15_neon.o
-NEON-OBJS-$(CONFIG_MPEGAUDIODSP)        += aarch64/mpegaudiodsp_neon.o
 NEON-OBJS-$(CONFIG_MDCT)                += aarch64/mdct_neon.o
+NEON-OBJS-$(CONFIG_MPEGAUDIODSP)        += aarch64/mpegaudiodsp_neon.o
 
+# decoders/encoders
+NEON-OBJS-$(CONFIG_DCA_DECODER)         += aarch64/synth_filter_neon.o
 NEON-OBJS-$(CONFIG_VORBIS_DECODER)      += aarch64/vorbisdsp_neon.o
diff --git a/libavcodec/aarch64/fft_init_aarch64.c b/libavcodec/aarch64/fft_init_aarch64.c
index 8514d3b..db28520 100644
--- a/libavcodec/aarch64/fft_init_aarch64.c
+++ b/libavcodec/aarch64/fft_init_aarch64.c
@@ -20,7 +20,10 @@
 
 #include "config.h"
 
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
 #include "libavutil/aarch64/cpu.h"
+
 #include "libavcodec/fft.h"
 
 void ff_fft_permute_neon(FFTContext *s, FFTComplex *z);
diff --git a/libavcodec/aarch64/h264idct_neon.S b/libavcodec/aarch64/h264idct_neon.S
index 91f1e77..fa414f7 100644
--- a/libavcodec/aarch64/h264idct_neon.S
+++ b/libavcodec/aarch64/h264idct_neon.S
@@ -33,25 +33,25 @@ function ff_h264_idct_add_neon, export=1
         sshr            v17.4H, v3.4H,  #1
         st1             {v30.8H},    [x1], #16
         sub             v5.4H,  v0.4H,  v2.4H
-        add             v6.4H,  v1.4H,  v17.4H
-        sub             v7.4H,  v16.4H, v3.4H
-        add             v0.4H,  v4.4H,  v6.4H
-        add             v1.4H,  v5.4H,  v7.4H
-        sub             v3.4H,  v4.4H,  v6.4H
-        sub             v2.4H,  v5.4H,  v7.4H
+        sub             v6.4H,  v16.4H, v3.4H
+        add             v7.4H,  v1.4H,  v17.4H
+        add             v0.4H,  v4.4H,  v7.4H
+        add             v1.4H,  v5.4H,  v6.4H
+        sub             v2.4H,  v5.4H,  v6.4H
+        sub             v3.4H,  v4.4H,  v7.4H
 
         transpose_4x4H  v0, v1, v2, v3, v4, v5, v6, v7
 
-        add             v4.4H,  v0.4H,  v3.4H
+        add             v4.4H,  v0.4H,  v2.4H
         ld1             {v18.S}[0], [x0], x2
-        sshr            v16.4H,  v2.4H,  #1
+        sshr            v16.4H,  v3.4H,  #1
         sshr            v17.4H,  v1.4H,  #1
-        ld1             {v19.S}[1], [x0], x2
-        sub             v5.4H,  v0.4H,  v3.4H
         ld1             {v18.S}[1], [x0], x2
+        sub             v5.4H,  v0.4H,  v2.4H
+        ld1             {v19.S}[1], [x0], x2
         add             v6.4H,  v16.4H, v1.4H
         ins             v4.D[1],  v5.D[0]
-        sub             v7.4H,  v2.4H,  v17.4H
+        sub             v7.4H,  v17.4H, v3.4H
         ld1             {v19.S}[0], [x0], x2
         ins             v6.D[1],  v7.D[0]
         sub             x0,  x0,  x2, lsl #2
@@ -68,8 +68,8 @@ function ff_h264_idct_add_neon, export=1
         sqxtun          v1.8B, v1.8H
 
         st1             {v0.S}[0],  [x0], x2
-        st1             {v1.S}[1],  [x0], x2
         st1             {v0.S}[1],  [x0], x2
+        st1             {v1.S}[1],  [x0], x2
         st1             {v1.S}[0],  [x0], x2
 
         sub             x1,  x1,  #32
diff --git a/libavcodec/aarch64/mpegaudiodsp_neon.S b/libavcodec/aarch64/mpegaudiodsp_neon.S
index 733fc84..97d2e1f 100644
--- a/libavcodec/aarch64/mpegaudiodsp_neon.S
+++ b/libavcodec/aarch64/mpegaudiodsp_neon.S
@@ -142,7 +142,7 @@ function ff_mpadsp_apply_window_\type\()_neon, export=1
         sub             x10, x10, #4<<2
         b.gt            1b
 
-// comuting samples[16]
+// computing samples[16]
         add             x6,  x1,  #32<<2
         ld1             {v0.2s},  [x6],  x9
         ld1             {v1.2s},  [x0],  x9
diff --git a/libavcodec/aarch64/neon.S b/libavcodec/aarch64/neon.S
index a227cbd..0fddbec 100644
--- a/libavcodec/aarch64/neon.S
+++ b/libavcodec/aarch64/neon.S
@@ -107,12 +107,12 @@
 .macro  transpose_4x4H  r0, r1, r2, r3, r4, r5, r6, r7
         trn1            \r4\().4H,  \r0\().4H,  \r1\().4H
         trn2            \r5\().4H,  \r0\().4H,  \r1\().4H
-        trn1            \r7\().4H,  \r2\().4H,  \r3\().4H
-        trn2            \r6\().4H,  \r2\().4H,  \r3\().4H
-        trn1            \r0\().2S,  \r4\().2S,  \r7\().2S
-        trn2            \r3\().2S,  \r4\().2S,  \r7\().2S
-        trn1            \r1\().2S,  \r5\().2S,  \r6\().2S
-        trn2            \r2\().2S,  \r5\().2S,  \r6\().2S
+        trn1            \r6\().4H,  \r2\().4H,  \r3\().4H
+        trn2            \r7\().4H,  \r2\().4H,  \r3\().4H
+        trn1            \r0\().2S,  \r4\().2S,  \r6\().2S
+        trn2            \r2\().2S,  \r4\().2S,  \r6\().2S
+        trn1            \r1\().2S,  \r5\().2S,  \r7\().2S
+        trn2            \r3\().2S,  \r5\().2S,  \r7\().2S
 .endm
 
 .macro  transpose_8x8H  r0, r1, r2, r3, r4, r5, r6, r7, r8, r9
diff --git a/libavcodec/aarch64/neontest.c b/libavcodec/aarch64/neontest.c
index 6e41f37..b1f1a6d 100644
--- a/libavcodec/aarch64/neontest.c
+++ b/libavcodec/aarch64/neontest.c
@@ -23,7 +23,7 @@
 #include "libavutil/aarch64/neontest.h"
 
 wrap(avcodec_open2(AVCodecContext *avctx,
-                   AVCodec *codec,
+                   const AVCodec *codec,
                    AVDictionary **options))
 {
     testneonclobbers(avcodec_open2, avctx, codec, options);
diff --git a/libavcodec/aasc.c b/libavcodec/aasc.c
index 6abf3b7..fd63aba 100644
--- a/libavcodec/aasc.c
+++ b/libavcodec/aasc.c
@@ -1,6 +1,6 @@
 /*
  * Autodesk RLE Decoder
- * Copyright (c) 2005 The FFmpeg Project
+ * Copyright (C) 2005 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index f82f397..fac189b 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -1445,8 +1445,9 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
             /* skip frame if CRC is ok. otherwise use error concealment. */
             /* TODO: add support for substreams and dependent frames */
             if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT || s->substreamid) {
-                av_log(avctx, AV_LOG_WARNING, "unsupported frame type : "
-                       "skipping frame\n");
+                av_log(avctx, AV_LOG_DEBUG,
+                       "unsupported frame type %d: skipping frame\n",
+                       s->frame_type);
                 *got_frame_ptr = 0;
                 return buf_size;
             } else {
diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h
index b3498fe..c2b867e 100644
--- a/libavcodec/ac3dec.h
+++ b/libavcodec/ac3dec.h
@@ -96,6 +96,8 @@ typedef struct AC3DecodeContext {
     int lfe_mix_level_exists;               ///< indicates if lfemixlevcod is specified (lfemixlevcode)
     int lfe_mix_level;                      ///< LFE mix level index                    (lfemixlevcod)
     int eac3;                               ///< indicates if current frame is E-AC-3
+    int eac3_frame_dependent_found;         ///< bitstream has E-AC-3 dependent frame(s)
+    int eac3_subsbtreamid_found;            ///< bitstream has E-AC-3 additional substream(s)
     int dolby_surround_mode;                ///< dolby surround mode                    (dsurmod)
     int dolby_surround_ex_mode;             ///< dolby surround ex mode                 (dsurexmod)
     int dolby_headphone_mode;               ///< dolby headphone mode                   (dheadphonmod)
diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c
index fe87b5b..9902f90 100644
--- a/libavcodec/ac3dsp.c
+++ b/libavcodec/ac3dsp.c
@@ -19,7 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavutil/avassert.h"
 #include "avcodec.h"
 #include "ac3.h"
 #include "ac3dsp.h"
diff --git a/libavcodec/acelp_filters.h b/libavcodec/acelp_filters.h
index 7a3061b..fe86cb2 100644
--- a/libavcodec/acelp_filters.h
+++ b/libavcodec/acelp_filters.h
@@ -82,7 +82,6 @@ extern const int16_t ff_acelp_interp_filter[61];
  * filter_coeffs contains coefficients of the right half of the symmetric
  * interpolation filter. filter_coeffs[0] should the central (unpaired) coefficient.
  * See ff_acelp_interp_filter for an example.
- *
  */
 void ff_acelp_interpolate(int16_t* out, const int16_t* in,
                           const int16_t* filter_coeffs, int precision,
diff --git a/libavcodec/acelp_pitch_delay.c b/libavcodec/acelp_pitch_delay.c
index c2533b1..8ec1ba3 100644
--- a/libavcodec/acelp_pitch_delay.c
+++ b/libavcodec/acelp_pitch_delay.c
@@ -21,9 +21,8 @@
  */
 
 #include "libavutil/common.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/float_dsp.h"
-#include "libavutil/internal.h"
-#include "libavutil/libm.h"
 #include "libavutil/mathematics.h"
 #include "avcodec.h"
 #include "acelp_pitch_delay.h"
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index c4a0a18..46c63a2 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2003 The FFmpeg Project
+ * Copyright (c) 2001-2003 The FFmpeg project
  *
  * first version by Francois Revol (revol at free.fr)
  * fringe ADPCM codecs (e.g., DK3, DK4, Westwood)
@@ -107,9 +107,14 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
     case AV_CODEC_ID_ADPCM_EA_XAS:
         max_channels = 6;
         break;
+    case AV_CODEC_ID_ADPCM_MTAF:
+        min_channels = 2;
+        max_channels = 8;
+        break;
     case AV_CODEC_ID_ADPCM_PSX:
         max_channels = 8;
         break;
+    case AV_CODEC_ID_ADPCM_IMA_DAT4:
     case AV_CODEC_ID_ADPCM_THP:
     case AV_CODEC_ID_ADPCM_THP_LE:
         max_channels = 14;
@@ -144,6 +149,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
 
     switch(avctx->codec->id) {
         case AV_CODEC_ID_ADPCM_AICA:
+        case AV_CODEC_ID_ADPCM_IMA_DAT4:
         case AV_CODEC_ID_ADPCM_IMA_QT:
         case AV_CODEC_ID_ADPCM_IMA_WAV:
         case AV_CODEC_ID_ADPCM_4XM:
@@ -157,6 +163,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
         case AV_CODEC_ID_ADPCM_AFC:
         case AV_CODEC_ID_ADPCM_DTK:
         case AV_CODEC_ID_ADPCM_PSX:
+        case AV_CODEC_ID_ADPCM_MTAF:
             avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
             break;
         case AV_CODEC_ID_ADPCM_IMA_WS:
@@ -170,7 +177,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx)
     return 0;
 }
 
-static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble, int shift)
+static inline int16_t adpcm_ima_expand_nibble(ADPCMChannelStatus *c, int8_t nibble, int shift)
 {
     int step_index;
     int predictor;
@@ -193,7 +200,7 @@ static inline short adpcm_ima_expand_nibble(ADPCMChannelStatus *c, char nibble,
     c->predictor = av_clip_int16(predictor);
     c->step_index = step_index;
 
-    return (short)c->predictor;
+    return (int16_t)c->predictor;
 }
 
 static inline int16_t adpcm_ima_wav_expand_nibble(ADPCMChannelStatus *c, GetBitContext *gb, int bps)
@@ -245,7 +252,7 @@ static inline int adpcm_ima_qt_expand_nibble(ADPCMChannelStatus *c, int nibble,
     return c->predictor;
 }
 
-static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, int nibble)
+static inline int16_t adpcm_ms_expand_nibble(ADPCMChannelStatus *c, int nibble)
 {
     int predictor;
 
@@ -264,7 +271,7 @@ static inline short adpcm_ms_expand_nibble(ADPCMChannelStatus *c, int nibble)
     return c->sample1;
 }
 
-static inline short adpcm_ima_oki_expand_nibble(ADPCMChannelStatus *c, int nibble)
+static inline int16_t adpcm_ima_oki_expand_nibble(ADPCMChannelStatus *c, int nibble)
 {
     int step_index, predictor, sign, delta, diff, step;
 
@@ -285,7 +292,7 @@ static inline short adpcm_ima_oki_expand_nibble(ADPCMChannelStatus *c, int nibbl
     return c->predictor << 4;
 }
 
-static inline short adpcm_ct_expand_nibble(ADPCMChannelStatus *c, char nibble)
+static inline int16_t adpcm_ct_expand_nibble(ADPCMChannelStatus *c, int8_t nibble)
 {
     int sign, delta, diff;
     int new_step;
@@ -303,10 +310,10 @@ static inline short adpcm_ct_expand_nibble(ADPCMChannelStatus *c, char nibble)
     new_step = (ff_adpcm_AdaptationTable[nibble & 7] * c->step) >> 8;
     c->step = av_clip(new_step, 511, 32767);
 
-    return (short)c->predictor;
+    return (int16_t)c->predictor;
 }
 
-static inline short adpcm_sbpro_expand_nibble(ADPCMChannelStatus *c, char nibble, int size, int shift)
+static inline int16_t adpcm_sbpro_expand_nibble(ADPCMChannelStatus *c, int8_t nibble, int size, int shift)
 {
     int sign, delta, diff;
 
@@ -323,10 +330,10 @@ static inline short adpcm_sbpro_expand_nibble(ADPCMChannelStatus *c, char nibble
     else if (delta == 0 && c->step > 0)
         c->step--;
 
-    return (short) c->predictor;
+    return (int16_t) c->predictor;
 }
 
-static inline short adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, unsigned char nibble)
+static inline int16_t adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, uint8_t nibble)
 {
     if(!c->step) {
         c->predictor = 0;
@@ -340,6 +347,15 @@ static inline short adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, unsigned c
     return c->predictor;
 }
 
+static inline int16_t adpcm_mtaf_expand_nibble(ADPCMChannelStatus *c, uint8_t nibble)
+{
+    c->predictor += ff_adpcm_mtaf_stepsize[c->step][nibble];
+    c->predictor = av_clip_int16(c->predictor);
+    c->step += ff_adpcm_index_table[nibble];
+    c->step = av_clip_uintp2(c->step, 5);
+    return c->predictor;
+}
+
 static int xa_decode(AVCodecContext *avctx, int16_t *out0, int16_t *out1,
                      const uint8_t *in, ADPCMChannelStatus *left,
                      ADPCMChannelStatus *right, int channels, int sample_offset)
@@ -450,7 +466,7 @@ static void adpcm_swf_decode(AVCodecContext *avctx, const uint8_t *buf, int buf_
                 // similar to IMA adpcm
                 int delta = get_bits(&gb, nb_bits);
                 int step = ff_adpcm_step_table[c->status[i].step_index];
-                long vpdiff = 0; // vpdiff = (delta+0.5)*step/4
+                int vpdiff = 0; // vpdiff = (delta+0.5)*step/4
                 int k = k0;
 
                 do {
@@ -533,6 +549,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
     header_size = 0;
     switch (avctx->codec->id) {
         case AV_CODEC_ID_ADPCM_4XM:
+        case AV_CODEC_ID_ADPCM_IMA_DAT4:
         case AV_CODEC_ID_ADPCM_IMA_ISS:     header_size = 4 * ch;      break;
         case AV_CODEC_ID_ADPCM_IMA_AMV:     header_size = 8;           break;
         case AV_CODEC_ID_ADPCM_IMA_SMJPEG:  header_size = 4 * ch;      break;
@@ -614,6 +631,11 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb,
             buf_size = FFMIN(buf_size, avctx->block_align);
         nb_samples = (buf_size - 6 * ch) * 2 / ch;
         break;
+    case AV_CODEC_ID_ADPCM_MTAF:
+        if (avctx->block_align > 0)
+            buf_size = FFMIN(buf_size, avctx->block_align);
+        nb_samples = (buf_size - 16 * (ch / 2)) * 2 / ch;
+        break;
     case AV_CODEC_ID_ADPCM_SBPRO_2:
     case AV_CODEC_ID_ADPCM_SBPRO_3:
     case AV_CODEC_ID_ADPCM_SBPRO_4:
@@ -692,7 +714,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
     ADPCMDecodeContext *c = avctx->priv_data;
     ADPCMChannelStatus *cs;
     int n, m, channel, i;
-    short *samples;
+    int16_t *samples;
     int16_t **samples_p;
     int st; /* stereo */
     int count1, count2;
@@ -710,7 +732,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
     frame->nb_samples = nb_samples;
     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
-    samples = (short *)frame->data[0];
+    samples = (int16_t *)frame->data[0];
     samples_p = (int16_t **)frame->extended_data;
 
     /* use coded_samples when applicable */
@@ -780,15 +802,23 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
 
         if (avctx->bits_per_coded_sample != 4) {
             int samples_per_block = ff_adpcm_ima_block_samples[avctx->bits_per_coded_sample - 2];
+            int block_size = ff_adpcm_ima_block_sizes[avctx->bits_per_coded_sample - 2];
+            uint8_t temp[20] = { 0 };
             GetBitContext g;
 
-            ret = init_get_bits8(&g, gb.buffer, bytestream2_get_bytes_left(&gb));
-            if (ret < 0)
-                return ret;
             for (n = 0; n < (nb_samples - 1) / samples_per_block; n++) {
                 for (i = 0; i < avctx->channels; i++) {
+                    int j;
+
                     cs = &c->status[i];
                     samples = &samples_p[i][1 + n * samples_per_block];
+                    for (j = 0; j < block_size; j++) {
+                        temp[j] = buf[4 * avctx->channels + block_size * n * avctx->channels +
+                                        (j % 4) + (j / 4) * (avctx->channels * 4) + i * 4];
+                    }
+                    ret = init_get_bits8(&g, (const uint8_t *)&temp, block_size);
+                    if (ret < 0)
+                        return ret;
                     for (m = 0; m < samples_per_block; m++) {
                         samples[m] = adpcm_ima_wav_expand_nibble(cs, &g,
                                           avctx->bits_per_coded_sample);
@@ -876,6 +906,27 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         }
         break;
     }
+    case AV_CODEC_ID_ADPCM_MTAF:
+        for (channel = 0; channel < avctx->channels; channel+=2) {
+            bytestream2_skipu(&gb, 4);
+            c->status[channel    ].step      = bytestream2_get_le16u(&gb);
+            c->status[channel + 1].step      = bytestream2_get_le16u(&gb);
+            c->status[channel    ].predictor = sign_extend(bytestream2_get_le16u(&gb), 16);
+            bytestream2_skipu(&gb, 2);
+            c->status[channel + 1].predictor = sign_extend(bytestream2_get_le16u(&gb), 16);
+            bytestream2_skipu(&gb, 2);
+            for (n = 0; n < nb_samples; n+=2) {
+                int v = bytestream2_get_byteu(&gb);
+                samples_p[channel][n    ] = adpcm_mtaf_expand_nibble(&c->status[channel], v & 0x0F);
+                samples_p[channel][n + 1] = adpcm_mtaf_expand_nibble(&c->status[channel], v >> 4  );
+            }
+            for (n = 0; n < nb_samples; n+=2) {
+                int v = bytestream2_get_byteu(&gb);
+                samples_p[channel + 1][n    ] = adpcm_mtaf_expand_nibble(&c->status[channel + 1], v & 0x0F);
+                samples_p[channel + 1][n + 1] = adpcm_mtaf_expand_nibble(&c->status[channel + 1], v >> 4  );
+            }
+        }
+        break;
     case AV_CODEC_ID_ADPCM_IMA_DK4:
         for (channel = 0; channel < avctx->channels; channel++) {
             cs = &c->status[channel];
@@ -984,6 +1035,18 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
             *samples++ = adpcm_ima_expand_nibble(&c->status[st], v2, 3);
         }
         break;
+    case AV_CODEC_ID_ADPCM_IMA_DAT4:
+        for (channel = 0; channel < avctx->channels; channel++) {
+            cs = &c->status[channel];
+            samples = samples_p[channel];
+            bytestream2_skip(&gb, 4);
+            for (n = 0; n < nb_samples; n += 2) {
+                int v = bytestream2_get_byteu(&gb);
+                *samples++ = adpcm_ima_expand_nibble(cs, v >> 4  , 3);
+                *samples++ = adpcm_ima_expand_nibble(cs, v & 0x0F, 3);
+            }
+        }
+        break;
     case AV_CODEC_ID_ADPCM_IMA_APC:
         while (bytestream2_get_bytes_left(&gb) > 0) {
             int v = bytestream2_get_byteu(&gb);
@@ -1287,8 +1350,8 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
         break;
     case AV_CODEC_ID_ADPCM_IMA_AMV:
         c->status[0].predictor = sign_extend(bytestream2_get_le16u(&gb), 16);
-        c->status[0].step_index = bytestream2_get_le16u(&gb);
-        bytestream2_skipu(&gb, 4);
+        c->status[0].step_index = bytestream2_get_byteu(&gb);
+        bytestream2_skipu(&gb, 5);
         if (c->status[0].step_index > 88u) {
             av_log(avctx, AV_LOG_ERROR, "ERROR: step_index = %i\n",
                    c->status[0].step_index);
@@ -1670,6 +1733,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_R3,       sample_fmts_s16p, adpcm_ea_r3,
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_EA_XAS,      sample_fmts_s16p, adpcm_ea_xas,      "ADPCM Electronic Arts XAS");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_AMV,     sample_fmts_s16,  adpcm_ima_amv,     "ADPCM IMA AMV");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_APC,     sample_fmts_s16,  adpcm_ima_apc,     "ADPCM IMA CRYO APC");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DAT4,    sample_fmts_s16,  adpcm_ima_dat4,    "ADPCM IMA Eurocom DAT4");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK3,     sample_fmts_s16,  adpcm_ima_dk3,     "ADPCM IMA Duck DK3");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_DK4,     sample_fmts_s16,  adpcm_ima_dk4,     "ADPCM IMA Duck DK4");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_EA_EACS, sample_fmts_s16,  adpcm_ima_ea_eacs, "ADPCM IMA Electronic Arts EACS");
@@ -1682,6 +1746,7 @@ ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_SMJPEG,  sample_fmts_s16,  adpcm_ima_smjpeg,
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WAV,     sample_fmts_s16p, adpcm_ima_wav,     "ADPCM IMA WAV");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_IMA_WS,      sample_fmts_both, adpcm_ima_ws,      "ADPCM IMA Westwood");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_MS,          sample_fmts_s16,  adpcm_ms,          "ADPCM Microsoft");
+ADPCM_DECODER(AV_CODEC_ID_ADPCM_MTAF,        sample_fmts_s16p, adpcm_mtaf,        "ADPCM MTAF");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_PSX,         sample_fmts_s16p, adpcm_psx,         "ADPCM Playstation");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_2,     sample_fmts_s16,  adpcm_sbpro_2,     "ADPCM Sound Blaster Pro 2-bit");
 ADPCM_DECODER(AV_CODEC_ID_ADPCM_SBPRO_3,     sample_fmts_s16,  adpcm_sbpro_3,     "ADPCM Sound Blaster Pro 2.6-bit");
diff --git a/libavcodec/adpcm.h b/libavcodec/adpcm.h
index fcbb70b..580db7d 100644
--- a/libavcodec/adpcm.h
+++ b/libavcodec/adpcm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2003 The FFmpeg Project
+ * Copyright (c) 2001-2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/adpcm_data.c b/libavcodec/adpcm_data.c
index 9c38360..52271be 100644
--- a/libavcodec/adpcm_data.c
+++ b/libavcodec/adpcm_data.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2003 The FFmpeg Project
+ * Copyright (c) 2001-2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -110,3 +110,70 @@ const int16_t ff_adpcm_afc_coeffs[2][16] = {
     { 0, 2048, 0, 1024, 4096, 3584, 3072, 4608, 4200, 4800, 5120, 2048, 1024, 64512, 64512, 63488 },
     { 0, 0, 2048, 1024, 63488, 64000, 64512, 62976, 63288, 63236, 62464, 63488, 64512, 1024, 0, 0 }
 };
+
+const int16_t ff_adpcm_mtaf_stepsize[32][16] = {
+    {     1,     5,     9,    13,    16,    20,    24,    28,
+         -1,    -5,    -9,   -13,   -16,   -20,   -24,   -28, },
+    {     2,     6,    11,    15,    20,    24,    29,    33,
+         -2,    -6,   -11,   -15,   -20,   -24,   -29,   -33, },
+    {     2,     7,    13,    18,    23,    28,    34,    39,
+         -2,    -7,   -13,   -18,   -23,   -28,   -34,   -39, },
+    {     3,     9,    15,    21,    28,    34,    40,    46,
+         -3,    -9,   -15,   -21,   -28,   -34,   -40,   -46, },
+    {     3,    11,    18,    26,    33,    41,    48,    56,
+         -3,   -11,   -18,   -26,   -33,   -41,   -48,   -56, },
+    {     4,    13,    22,    31,    40,    49,    58,    67,
+         -4,   -13,   -22,   -31,   -40,   -49,   -58,   -67, },
+    {     5,    16,    26,    37,    48,    59,    69,    80,
+         -5,   -16,   -26,   -37,   -48,   -59,   -69,   -80, },
+    {     6,    19,    31,    44,    57,    70,    82,    95,
+         -6,   -19,   -31,   -44,   -57,   -70,   -82,   -95, },
+    {     7,    22,    38,    53,    68,    83,    99,   114,
+         -7,   -22,   -38,   -53,   -68,   -83,   -99,  -114, },
+    {     9,    27,    45,    63,    81,    99,   117,   135,
+         -9,   -27,   -45,   -63,   -81,   -99,  -117,  -135, },
+    {    10,    32,    53,    75,    96,   118,   139,   161,
+        -10,   -32,   -53,   -75,   -96,  -118,  -139,  -161, },
+    {    12,    38,    64,    90,   115,   141,   167,   193,
+        -12,   -38,   -64,   -90,  -115,  -141,  -167,  -193, },
+    {    15,    45,    76,   106,   137,   167,   198,   228,
+        -15,   -45,   -76,  -106,  -137,  -167,  -198,  -228, },
+    {    18,    54,    91,   127,   164,   200,   237,   273,
+        -18,   -54,   -91,  -127,  -164,  -200,  -237,  -273, },
+    {    21,    65,   108,   152,   195,   239,   282,   326,
+        -21,   -65,  -108,  -152,  -195,  -239,  -282,  -326, },
+    {    25,    77,   129,   181,   232,   284,   336,   388,
+        -25,   -77,  -129,  -181,  -232,  -284,  -336,  -388, },
+    {    30,    92,   153,   215,   276,   338,   399,   461,
+        -30,   -92,  -153,  -215,  -276,  -338,  -399,  -461, },
+    {    36,   109,   183,   256,   329,   402,   476,   549,
+        -36,  -109,  -183,  -256,  -329,  -402,  -476,  -549, },
+    {    43,   130,   218,   305,   392,   479,   567,   654,
+        -43,  -130,  -218,  -305,  -392,  -479,  -567,  -654, },
+    {    52,   156,   260,   364,   468,   572,   676,   780,
+        -52,  -156,  -260,  -364,  -468,  -572,  -676,  -780, },
+    {    62,   186,   310,   434,   558,   682,   806,   930,
+        -62,  -186,  -310,  -434,  -558,  -682,  -806,  -930, },
+    {    73,   221,   368,   516,   663,   811,   958,  1106,
+        -73,  -221,  -368,  -516,  -663,  -811,  -958, -1106, },
+    {    87,   263,   439,   615,   790,   966,  1142,  1318,
+        -87,  -263,  -439,  -615,  -790,  -966, -1142, -1318, },
+    {   104,   314,   523,   733,   942,  1152,  1361,  1571,
+       -104,  -314,  -523,  -733,  -942, -1152, -1361, -1571, },
+    {   124,   374,   623,   873,  1122,  1372,  1621,  1871,
+       -124,  -374,  -623,  -873, -1122, -1372, -1621, -1871, },
+    {   148,   445,   743,  1040,  1337,  1634,  1932,  2229,
+       -148,  -445,  -743, -1040, -1337, -1634, -1932, -2229, },
+    {   177,   531,   885,  1239,  1593,  1947,  2301,  2655,
+       -177,  -531,  -885, -1239, -1593, -1947, -2301, -2655, },
+    {   210,   632,  1053,  1475,  1896,  2318,  2739,  3161,
+       -210,  -632, -1053, -1475, -1896, -2318, -2739, -3161, },
+    {   251,   753,  1255,  1757,  2260,  2762,  3264,  3766,
+       -251,  -753, -1255, -1757, -2260, -2762, -3264, -3766, },
+    {   299,   897,  1495,  2093,  2692,  3290,  3888,  4486,
+       -299,  -897, -1495, -2093, -2692, -3290, -3888, -4486, },
+    {   356,  1068,  1781,  2493,  3206,  3918,  4631,  5343,
+       -356, -1068, -1781, -2493, -3206, -3918, -4631, -5343, },
+    {   424,  1273,  2121,  2970,  3819,  4668,  5516,  6365,
+       -424, -1273, -2121, -2970, -3819, -4668, -5516, -6365, },
+};
diff --git a/libavcodec/adpcm_data.h b/libavcodec/adpcm_data.h
index b179d65..5a68713 100644
--- a/libavcodec/adpcm_data.h
+++ b/libavcodec/adpcm_data.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2003 The FFmpeg Project
+ * Copyright (c) 2001-2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -41,5 +41,6 @@ extern const int8_t  ff_adpcm_AdaptCoeff2[];
 extern const int16_t ff_adpcm_yamaha_indexscale[];
 extern const int8_t  ff_adpcm_yamaha_difflookup[];
 extern const int16_t ff_adpcm_afc_coeffs[2][16];
+extern const int16_t ff_adpcm_mtaf_stepsize[32][16];
 
 #endif /* AVCODEC_ADPCM_DATA_H */
diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index 9ceea09..36974fd 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2003 The FFmpeg Project
+ * Copyright (c) 2001-2003 The FFmpeg project
  *
  * first version by Francois Revol (revol at free.fr)
  * fringe ADPCM codecs (e.g., DK3, DK4, Westwood)
diff --git a/libavcodec/aic.c b/libavcodec/aic.c
index 5decc78..ff8e392 100644
--- a/libavcodec/aic.c
+++ b/libavcodec/aic.c
@@ -28,6 +28,7 @@
 #include "get_bits.h"
 #include "golomb.h"
 #include "idctdsp.h"
+#include "thread.h"
 #include "unary.h"
 
 #define AIC_HDR_SIZE    24
@@ -375,6 +376,7 @@ static int aic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     uint32_t off;
     int x, y, ret;
     int slice_size;
+    ThreadFrame frame = { .f = data };
 
     ctx->frame            = data;
     ctx->frame->pict_type = AV_PICTURE_TYPE_I;
@@ -393,7 +395,7 @@ static int aic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         return ret;
     }
 
-    if ((ret = ff_get_buffer(avctx, ctx->frame, 0)) < 0)
+    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
         return ret;
 
     bytestream2_init(&gb, buf + AIC_HDR_SIZE,
@@ -488,5 +490,6 @@ AVCodec ff_aic_decoder = {
     .init           = aic_decode_init,
     .close          = aic_decode_close,
     .decode         = aic_decode_frame,
-    .capabilities   = AV_CODEC_CAP_DR1,
+    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .init_thread_copy = ONLY_IF_THREADS_ENABLED(aic_decode_init),
 };
diff --git a/libavcodec/alac.c b/libavcodec/alac.c
index fc8bc96..b9c3400 100644
--- a/libavcodec/alac.c
+++ b/libavcodec/alac.c
@@ -29,20 +29,20 @@
  * passed through the extradata[_size] fields. This atom is tacked onto
  * the end of an 'alac' stsd atom and has the following format:
  *
- * 32bit  atom size
- * 32bit  tag                  ("alac")
- * 32bit  tag version          (0)
- * 32bit  samples per frame    (used when not set explicitly in the frames)
- *  8bit  compatible version   (0)
- *  8bit  sample size
- *  8bit  history mult         (40)
- *  8bit  initial history      (10)
- *  8bit  rice param limit     (14)
- *  8bit  channels
- * 16bit  maxRun               (255)
- * 32bit  max coded frame size (0 means unknown)
- * 32bit  average bitrate      (0 means unknown)
- * 32bit  samplerate
+ * 32 bits  atom size
+ * 32 bits  tag                  ("alac")
+ * 32 bits  tag version          (0)
+ * 32 bits  samples per frame    (used when not set explicitly in the frames)
+ *  8 bits  compatible version   (0)
+ *  8 bits  sample size
+ *  8 bits  history mult         (40)
+ *  8 bits  initial history      (10)
+ *  8 bits  rice param limit     (14)
+ *  8 bits  channels
+ * 16 bits  maxRun               (255)
+ * 32 bits  max coded frame size (0 means unknown)
+ * 32 bits  average bitrate      (0 means unknown)
+ * 32 bits  samplerate
  */
 
 #include <inttypes.h>
@@ -391,6 +391,12 @@ static int decode_element(AVCodecContext *avctx, AVFrame *frame, int ch_index,
                 *outbuffer++ = alac->output_samples_buffer[ch][i];
         }}
         break;
+    case 20: {
+        for (ch = 0; ch < channels; ch++) {
+            for (i = 0; i < alac->nb_samples; i++)
+                alac->output_samples_buffer[ch][i] <<= 12;
+        }}
+        break;
     case 24: {
         for (ch = 0; ch < channels; ch++) {
             for (i = 0; i < alac->nb_samples; i++)
@@ -556,6 +562,7 @@ static av_cold int alac_decode_init(AVCodecContext * avctx)
     switch (alac->sample_size) {
     case 16: avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
              break;
+    case 20:
     case 24:
     case 32: avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
              break;
diff --git a/libavcodec/alacenc.c b/libavcodec/alacenc.c
index c80c887..9ac35f1 100644
--- a/libavcodec/alacenc.c
+++ b/libavcodec/alacenc.c
@@ -81,7 +81,7 @@ typedef struct AlacEncodeContext {
 
 
 static void init_sample_buffers(AlacEncodeContext *s, int channels,
-                                uint8_t const *samples[2])
+                                const uint8_t *samples[2])
 {
     int ch, i;
     int shift = av_get_bytes_per_sample(s->avctx->sample_fmt) * 8 -
@@ -364,7 +364,7 @@ static void write_element(AlacEncodeContext *s,
                           enum AlacRawDataBlockType element, int instance,
                           const uint8_t *samples0, const uint8_t *samples1)
 {
-    uint8_t const *samples[2] = { samples0, samples1 };
+    const uint8_t *samples[2] = { samples0, samples1 };
     int i, j, channels;
     int prediction_type = 0;
     PutBitContext *pb = &s->pbctx;
@@ -376,14 +376,14 @@ static void write_element(AlacEncodeContext *s,
         /* samples are channel-interleaved in verbatim mode */
         if (s->avctx->sample_fmt == AV_SAMPLE_FMT_S32P) {
             int shift = 32 - s->avctx->bits_per_raw_sample;
-            int32_t const *samples_s32[2] = { (const int32_t *)samples0,
+            const int32_t *samples_s32[2] = { (const int32_t *)samples0,
                                               (const int32_t *)samples1 };
             for (i = 0; i < s->frame_size; i++)
                 for (j = 0; j < channels; j++)
                     put_sbits(pb, s->avctx->bits_per_raw_sample,
                               samples_s32[j][i] >> shift);
         } else {
-            int16_t const *samples_s16[2] = { (const int16_t *)samples0,
+            const int16_t *samples_s16[2] = { (const int16_t *)samples0,
                                               (const int16_t *)samples1 };
             for (i = 0; i < s->frame_size; i++)
                 for (j = 0; j < channels; j++)
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 2097db0..54efaad 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -58,13 +58,6 @@
             av_register_codec_parser(&ff_##x##_parser);                 \
     }
 
-#define REGISTER_BSF(X, x)                                              \
-    {                                                                   \
-        extern AVBitStreamFilter ff_##x##_bsf;                          \
-        if (CONFIG_##X##_BSF)                                           \
-            av_register_bitstream_filter(&ff_##x##_bsf);                \
-    }
-
 void avcodec_register_all(void)
 {
     static int initialized;
@@ -76,6 +69,7 @@ void avcodec_register_all(void)
     /* hardware accelerators */
     REGISTER_HWACCEL(H263_VAAPI,        h263_vaapi);
     REGISTER_HWACCEL(H263_VIDEOTOOLBOX, h263_videotoolbox);
+    REGISTER_HWACCEL(H264_CUVID,        h264_cuvid);
     REGISTER_HWACCEL(H264_D3D11VA,      h264_d3d11va);
     REGISTER_HWACCEL(H264_DXVA2,        h264_dxva2);
     REGISTER_HWACCEL(H264_MMAL,         h264_mmal);
@@ -85,6 +79,7 @@ void avcodec_register_all(void)
     REGISTER_HWACCEL(H264_VDA_OLD,      h264_vda_old);
     REGISTER_HWACCEL(H264_VDPAU,        h264_vdpau);
     REGISTER_HWACCEL(H264_VIDEOTOOLBOX, h264_videotoolbox);
+    REGISTER_HWACCEL(HEVC_CUVID,        hevc_cuvid);
     REGISTER_HWACCEL(HEVC_D3D11VA,      hevc_d3d11va);
     REGISTER_HWACCEL(HEVC_DXVA2,        hevc_dxva2);
     REGISTER_HWACCEL(HEVC_QSV,          hevc_qsv);
@@ -105,12 +100,15 @@ void avcodec_register_all(void)
     REGISTER_HWACCEL(MPEG4_VAAPI,       mpeg4_vaapi);
     REGISTER_HWACCEL(MPEG4_VDPAU,       mpeg4_vdpau);
     REGISTER_HWACCEL(MPEG4_VIDEOTOOLBOX, mpeg4_videotoolbox);
+    REGISTER_HWACCEL(VC1_CUVID,         vc1_cuvid);
     REGISTER_HWACCEL(VC1_D3D11VA,       vc1_d3d11va);
     REGISTER_HWACCEL(VC1_DXVA2,         vc1_dxva2);
     REGISTER_HWACCEL(VC1_VAAPI,         vc1_vaapi);
     REGISTER_HWACCEL(VC1_VDPAU,         vc1_vdpau);
     REGISTER_HWACCEL(VC1_MMAL,          vc1_mmal);
     REGISTER_HWACCEL(VC1_QSV,           vc1_qsv);
+    REGISTER_HWACCEL(VP8_CUVID,         vp8_cuvid);
+    REGISTER_HWACCEL(VP9_CUVID,         vp9_cuvid);
     REGISTER_HWACCEL(VP9_D3D11VA,       vp9_d3d11va);
     REGISTER_HWACCEL(VP9_DXVA2,         vp9_dxva2);
     REGISTER_HWACCEL(VP9_VAAPI,         vp9_vaapi);
@@ -196,6 +194,7 @@ void avcodec_register_all(void)
     REGISTER_ENCDEC (H263P,             h263p);
     REGISTER_DECODER(H264,              h264);
     REGISTER_DECODER(H264_CRYSTALHD,    h264_crystalhd);
+    REGISTER_DECODER(H264_MEDIACODEC,   h264_mediacodec);
     REGISTER_DECODER(H264_MMAL,         h264_mmal);
     REGISTER_DECODER(H264_QSV,          h264_qsv);
     REGISTER_DECODER(H264_VDA,          h264_vda);
@@ -224,6 +223,8 @@ void avcodec_register_all(void)
     REGISTER_DECODER(LAGARITH,          lagarith);
     REGISTER_ENCODER(LJPEG,             ljpeg);
     REGISTER_DECODER(LOCO,              loco);
+    REGISTER_DECODER(M101,              m101);
+    REGISTER_DECODER(MAGICYUV,          magicyuv);
     REGISTER_DECODER(MDEC,              mdec);
     REGISTER_DECODER(MIMIC,             mimic);
     REGISTER_ENCDEC (MJPEG,             mjpeg);
@@ -298,6 +299,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(SDX2_DPCM,         sdx2_dpcm);
     REGISTER_ENCDEC (SGI,               sgi);
     REGISTER_DECODER(SGIRLE,            sgirle);
+    REGISTER_DECODER(SHEERVIDEO,        sheervideo);
     REGISTER_DECODER(SMACKER,           smacker);
     REGISTER_DECODER(SMC,               smc);
     REGISTER_DECODER(SMVJPEG,           smvjpeg);
@@ -316,6 +318,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(TMV,               tmv);
     REGISTER_DECODER(TRUEMOTION1,       truemotion1);
     REGISTER_DECODER(TRUEMOTION2,       truemotion2);
+    REGISTER_DECODER(TRUEMOTION2RT,     truemotion2rt);
     REGISTER_DECODER(TSCC,              tscc);
     REGISTER_DECODER(TSCC2,             tscc2);
     REGISTER_DECODER(TXD,               txd);
@@ -367,6 +370,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(XL,                xl);
     REGISTER_ENCDEC (XWD,               xwd);
     REGISTER_ENCDEC (Y41P,              y41p);
+    REGISTER_DECODER(YLC,               ylc);
     REGISTER_DECODER(YOP,               yop);
     REGISTER_ENCDEC (YUV4,              yuv4);
     REGISTER_DECODER(ZERO12V,           zero12v);
@@ -399,6 +403,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(DSD_MSBF_PLANAR,   dsd_msbf_planar);
     REGISTER_DECODER(DSICINAUDIO,       dsicinaudio);
     REGISTER_DECODER(DSS_SP,            dss_sp);
+    REGISTER_DECODER(DST,               dst);
     REGISTER_ENCDEC (EAC3,              eac3);
     REGISTER_DECODER(EVRC,              evrc);
     REGISTER_DECODER(FFWAVESYNTH,       ffwavesynth);
@@ -514,6 +519,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(ADPCM_G726LE,      adpcm_g726le);
     REGISTER_DECODER(ADPCM_IMA_AMV,     adpcm_ima_amv);
     REGISTER_DECODER(ADPCM_IMA_APC,     adpcm_ima_apc);
+    REGISTER_DECODER(ADPCM_IMA_DAT4,    adpcm_ima_dat4);
     REGISTER_DECODER(ADPCM_IMA_DK3,     adpcm_ima_dk3);
     REGISTER_DECODER(ADPCM_IMA_DK4,     adpcm_ima_dk4);
     REGISTER_DECODER(ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs);
@@ -526,6 +532,7 @@ void avcodec_register_all(void)
     REGISTER_ENCDEC (ADPCM_IMA_WAV,     adpcm_ima_wav);
     REGISTER_DECODER(ADPCM_IMA_WS,      adpcm_ima_ws);
     REGISTER_ENCDEC (ADPCM_MS,          adpcm_ms);
+    REGISTER_DECODER(ADPCM_MTAF,        adpcm_mtaf);
     REGISTER_DECODER(ADPCM_PSX,         adpcm_psx);
     REGISTER_DECODER(ADPCM_SBPRO_2,     adpcm_sbpro_2);
     REGISTER_DECODER(ADPCM_SBPRO_3,     adpcm_sbpro_3);
@@ -562,8 +569,22 @@ void avcodec_register_all(void)
     REGISTER_ENCDEC (XSUB,              xsub);
 
     /* external libraries */
+    REGISTER_ENCDEC (AAC_AT,            aac_at);
+    REGISTER_DECODER(AC3_AT,            ac3_at);
+    REGISTER_DECODER(ADPCM_IMA_QT_AT,   adpcm_ima_qt_at);
+    REGISTER_ENCDEC (ALAC_AT,           alac_at);
+    REGISTER_DECODER(AMR_NB_AT,         amr_nb_at);
+    REGISTER_DECODER(EAC3_AT,           eac3_at);
+    REGISTER_DECODER(GSM_MS_AT,         gsm_ms_at);
+    REGISTER_ENCDEC (ILBC_AT,           ilbc_at);
+    REGISTER_DECODER(MP1_AT,            mp1_at);
+    REGISTER_DECODER(MP2_AT,            mp2_at);
+    REGISTER_DECODER(MP3_AT,            mp3_at);
+    REGISTER_ENCDEC (PCM_ALAW_AT,       pcm_alaw_at);
+    REGISTER_ENCDEC (PCM_MULAW_AT,      pcm_mulaw_at);
+    REGISTER_DECODER(QDMC_AT,           qdmc_at);
+    REGISTER_DECODER(QDM2_AT,           qdm2_at);
     REGISTER_DECODER(LIBCELT,           libcelt);
-    REGISTER_DECODER(LIBDCADEC,         libdcadec)
     REGISTER_ENCODER(LIBFAAC,           libfaac);
     REGISTER_ENCDEC (LIBFDK_AAC,        libfdk_aac);
     REGISTER_ENCDEC (LIBGSM,            libgsm);
@@ -579,7 +600,6 @@ void avcodec_register_all(void)
     REGISTER_ENCDEC (LIBSPEEX,          libspeex);
     REGISTER_ENCODER(LIBTHEORA,         libtheora);
     REGISTER_ENCODER(LIBTWOLAME,        libtwolame);
-    REGISTER_ENCDEC (LIBUTVIDEO,        libutvideo);
     REGISTER_ENCODER(LIBVO_AMRWBENC,    libvo_amrwbenc);
     REGISTER_ENCDEC (LIBVORBIS,         libvorbis);
     REGISTER_ENCDEC (LIBVPX_VP8,        libvpx_vp8);
@@ -603,13 +623,27 @@ void avcodec_register_all(void)
     /* external libraries, that shouldn't be used by default if one of the
      * above is available */
     REGISTER_ENCODER(LIBOPENH264,       libopenh264);
+    REGISTER_DECODER(H264_CUVID,        h264_cuvid);
+    REGISTER_ENCODER(H264_NVENC,        h264_nvenc);
+    REGISTER_ENCODER(H264_OMX,          h264_omx);
     REGISTER_ENCODER(H264_QSV,          h264_qsv);
+    REGISTER_ENCODER(H264_VAAPI,        h264_vaapi);
+    REGISTER_ENCODER(H264_VIDEOTOOLBOX, h264_videotoolbox);
+#if FF_API_NVENC_OLD_NAME
     REGISTER_ENCODER(NVENC,             nvenc);
     REGISTER_ENCODER(NVENC_H264,        nvenc_h264);
     REGISTER_ENCODER(NVENC_HEVC,        nvenc_hevc);
+#endif
+    REGISTER_DECODER(HEVC_CUVID,        hevc_cuvid);
+    REGISTER_ENCODER(HEVC_NVENC,        hevc_nvenc);
     REGISTER_ENCODER(HEVC_QSV,          hevc_qsv);
+    REGISTER_ENCODER(HEVC_VAAPI,        hevc_vaapi);
     REGISTER_ENCODER(LIBKVAZAAR,        libkvazaar);
+    REGISTER_ENCODER(MJPEG_VAAPI,       mjpeg_vaapi);
     REGISTER_ENCODER(MPEG2_QSV,         mpeg2_qsv);
+    REGISTER_DECODER(VC1_CUVID,         vc1_cuvid);
+    REGISTER_DECODER(VP8_CUVID,         vp8_cuvid);
+    REGISTER_DECODER(VP9_CUVID,         vp9_cuvid);
 
     /* parsers */
     REGISTER_PARSER(AAC,                aac);
@@ -650,20 +684,4 @@ void avcodec_register_all(void)
     REGISTER_PARSER(VP3,                vp3);
     REGISTER_PARSER(VP8,                vp8);
     REGISTER_PARSER(VP9,                vp9);
-
-    /* bitstream filters */
-    REGISTER_BSF(AAC_ADTSTOASC,         aac_adtstoasc);
-    REGISTER_BSF(CHOMP,                 chomp);
-    REGISTER_BSF(DUMP_EXTRADATA,        dump_extradata);
-    REGISTER_BSF(H264_MP4TOANNEXB,      h264_mp4toannexb);
-    REGISTER_BSF(HEVC_MP4TOANNEXB,      hevc_mp4toannexb);
-    REGISTER_BSF(IMX_DUMP_HEADER,       imx_dump_header);
-    REGISTER_BSF(MJPEG2JPEG,            mjpeg2jpeg);
-    REGISTER_BSF(MJPEGA_DUMP_HEADER,    mjpega_dump_header);
-    REGISTER_BSF(MP3_HEADER_DECOMPRESS, mp3_header_decompress);
-    REGISTER_BSF(MPEG4_UNPACK_BFRAMES,  mpeg4_unpack_bframes);
-    REGISTER_BSF(MOV2TEXTSUB,           mov2textsub);
-    REGISTER_BSF(NOISE,                 noise);
-    REGISTER_BSF(REMOVE_EXTRADATA,      remove_extradata);
-    REGISTER_BSF(TEXT2MOVSUB,           text2movsub);
 }
diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c
index ebd364e..a7e58a2 100644
--- a/libavcodec/alsdec.c
+++ b/libavcodec/alsdec.c
@@ -729,7 +729,7 @@ static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd)
                     quant_cof[k] = decode_rice(gb, rice_param) + offset;
                     if (quant_cof[k] < -64 || quant_cof[k] > 63) {
                         av_log(avctx, AV_LOG_ERROR,
-                               "quant_cof %"PRIu32" is out of range.\n",
+                               "quant_cof %"PRId32" is out of range.\n",
                                quant_cof[k]);
                         return AVERROR_INVALIDDATA;
                     }
@@ -765,8 +765,13 @@ static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd)
             bd->ltp_gain[0]   = decode_rice(gb, 1) << 3;
             bd->ltp_gain[1]   = decode_rice(gb, 2) << 3;
 
-            r                 = get_unary(gb, 0, 3);
+            r                 = get_unary(gb, 0, 4);
             c                 = get_bits(gb, 2);
+            if (r >= 4) {
+                av_log(avctx, AV_LOG_ERROR, "r overflow\n");
+                return AVERROR_INVALIDDATA;
+            }
+
             bd->ltp_gain[2]   = ltp_gain_values[r][c];
 
             bd->ltp_gain[3]   = decode_rice(gb, 2) << 3;
@@ -867,9 +872,6 @@ static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd)
                 *current_res++ = decode_rice(gb, s[sb]);
      }
 
-    if (!sconf->mc_coding || ctx->js_switch)
-        align_get_bits(gb);
-
     return 0;
 }
 
@@ -989,6 +991,7 @@ static int read_block(ALSDecContext *ctx, ALSBlockData *bd)
 {
     int ret;
     GetBitContext *gb        = &ctx->gb;
+    ALSSpecificConfig *sconf = &ctx->sconf;
 
     *bd->shift_lsbs = 0;
     // read block type flag and read the samples accordingly
@@ -998,6 +1001,9 @@ static int read_block(ALSDecContext *ctx, ALSBlockData *bd)
         ret = read_const_block_data(ctx, bd);
     }
 
+    if (!sconf->mc_coding || ctx->js_switch)
+        align_get_bits(gb);
+
     return ret;
 }
 
@@ -1292,13 +1298,13 @@ static int revert_channel_correlation(ALSDecContext *ctx, ALSBlockData *bd,
             if (ch[dep].time_diff_sign) {
                 t      = -t;
                 if (begin < t) {
-                    av_log(ctx->avctx, AV_LOG_ERROR, "begin %td smaller than time diff index %d.\n", begin, t);
+                    av_log(ctx->avctx, AV_LOG_ERROR, "begin %"PTRDIFF_SPECIFIER" smaller than time diff index %d.\n", begin, t);
                     return AVERROR_INVALIDDATA;
                 }
                 begin -= t;
             } else {
                 if (end < t) {
-                    av_log(ctx->avctx, AV_LOG_ERROR, "end %td smaller than time diff index %d.\n", end, t);
+                    av_log(ctx->avctx, AV_LOG_ERROR, "end %"PTRDIFF_SPECIFIER" smaller than time diff index %d.\n", end, t);
                     return AVERROR_INVALIDDATA;
                 }
                 end   -= t;
diff --git a/libavcodec/amrnbdec.c b/libavcodec/amrnbdec.c
index 2299a25..ea299ac 100644
--- a/libavcodec/amrnbdec.c
+++ b/libavcodec/amrnbdec.c
@@ -547,13 +547,13 @@ static void decode_fixed_sparse(AMRFixed *fixed_sparse, const uint16_t *pulses,
  * @param p the context
  * @param subframe unpacked amr subframe
  * @param mode mode of the current frame
- * @param fixed_sparse sparse respresentation of the fixed vector
+ * @param fixed_sparse sparse representation of the fixed vector
  */
 static void pitch_sharpening(AMRContext *p, int subframe, enum Mode mode,
                              AMRFixed *fixed_sparse)
 {
     // The spec suggests the current pitch gain is always used, but in other
-    // modes the pitch and codebook gains are joinly quantized (sec 5.8.2)
+    // modes the pitch and codebook gains are jointly quantized (sec 5.8.2)
     // so the codebook gain cannot depend on the quantized pitch gain.
     if (mode == MODE_12k2)
         p->beta = FFMIN(p->pitch_gain[4], 1.0);
diff --git a/libavcodec/amrwbdata.h b/libavcodec/amrwbdata.h
index 8390582..e0152a6 100644
--- a/libavcodec/amrwbdata.h
+++ b/libavcodec/amrwbdata.h
@@ -38,7 +38,7 @@
 
 #define MIN_ISF_SPACING     (128.0 / 32768.0) ///< minimum isf gap
 #define PRED_FACTOR         (1.0 / 3.0)
-#define MIN_ENERGY         -14.0              ///< initial innnovation energy (dB)
+#define MIN_ENERGY         -14.0              ///< initial innovation energy (dB)
 #define ENERGY_MEAN         30.0              ///< mean innovation energy (dB) in all modes
 #define PREEMPH_FAC         0.68              ///< factor used to de-emphasize synthesis
 
diff --git a/libavcodec/amrwbdec.c b/libavcodec/amrwbdec.c
index a99dbd1..7d0c135 100644
--- a/libavcodec/amrwbdec.c
+++ b/libavcodec/amrwbdec.c
@@ -151,7 +151,6 @@ static int decode_mime_header(AMRWBContext *ctx, const uint8_t *buf)
  *
  * @param[in]  ind                 Array of 5 indexes
  * @param[out] isf_q               Buffer for isf_q[LP_ORDER]
- *
  */
 static void decode_isf_indices_36b(uint16_t *ind, float *isf_q)
 {
@@ -178,7 +177,6 @@ static void decode_isf_indices_36b(uint16_t *ind, float *isf_q)
  *
  * @param[in]  ind                 Array of 7 indexes
  * @param[out] isf_q               Buffer for isf_q[LP_ORDER]
- *
  */
 static void decode_isf_indices_46b(uint16_t *ind, float *isf_q)
 {
@@ -212,7 +210,6 @@ static void decode_isf_indices_46b(uint16_t *ind, float *isf_q)
  *
  * @param[in,out] isf_q            Current quantized ISF
  * @param[in,out] isf_past         Past quantized ISF
- *
  */
 static void isf_add_mean_and_past(float *isf_q, float *isf_past)
 {
diff --git a/libavcodec/ansi.c b/libavcodec/ansi.c
index 21d5ae1..4808ea7 100644
--- a/libavcodec/ansi.c
+++ b/libavcodec/ansi.c
@@ -206,7 +206,7 @@ static int execute_code(AVCodecContext * avctx, int c)
         s->y = s->nb_args > 0 ? av_clip((s->args[0] - 1)*s->font_height, 0, avctx->height - s->font_height) : 0;
         s->x = s->nb_args > 1 ? av_clip((s->args[1] - 1)*FONT_WIDTH,     0, avctx->width  - FONT_WIDTH) : 0;
         break;
-    case 'h': //set creen mode
+    case 'h': //set screen mode
     case 'l': //reset screen mode
         if (s->nb_args < 2)
             s->args[0] = DEFAULT_SCREEN_MODE;
diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c
index de9d71c..b99598b 100644
--- a/libavcodec/apedec.c
+++ b/libavcodec/apedec.c
@@ -339,10 +339,10 @@ static inline void range_dec_normalize(APEContext *ctx)
 }
 
 /**
- * Calculate culmulative frequency for next symbol. Does NO update!
+ * Calculate cumulative frequency for next symbol. Does NO update!
  * @param ctx decoder context
  * @param tot_f is the total frequency or (code_value)1<<shift
- * @return the culmulative frequency
+ * @return the cumulative frequency
  */
 static inline int range_decode_culfreq(APEContext *ctx, int tot_f)
 {
@@ -1284,8 +1284,16 @@ static void do_apply_filter(APEContext *ctx, int version, APEFilter *f,
             /* Update the adaption coefficients */
             absres = FFABS(res);
             if (absres)
-                *f->adaptcoeffs = ((res & INT32_MIN) ^ (-(1<<30))) >>
-                                  (25 + (absres <= f->avg*3) + (absres <= f->avg*4/3));
+                *f->adaptcoeffs = APESIGN(res) *
+                                  (8 << ((absres > f->avg * 3) + (absres > f->avg * 4 / 3)));
+                /* equivalent to the following code
+                    if (absres <= f->avg * 4 / 3)
+                        *f->adaptcoeffs = APESIGN(res) * 8;
+                    else if (absres <= f->avg * 3)
+                        *f->adaptcoeffs = APESIGN(res) * 16;
+                    else
+                        *f->adaptcoeffs = APESIGN(res) * 32;
+                */
             else
                 *f->adaptcoeffs = 0;
 
diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile
index 179c403..a4ceca7 100644
--- a/libavcodec/arm/Makefile
+++ b/libavcodec/arm/Makefile
@@ -7,7 +7,10 @@ OBJS-$(CONFIG_AUDIODSP)                += arm/audiodsp_init_arm.o
 OBJS-$(CONFIG_BLOCKDSP)                += arm/blockdsp_init_arm.o
 OBJS-$(CONFIG_FFT)                     += arm/fft_init_arm.o            \
                                           arm/fft_fixed_init_arm.o
+OBJS-$(CONFIG_FLACDSP)                 += arm/flacdsp_init_arm.o        \
+                                          arm/flacdsp_arm.o
 OBJS-$(CONFIG_FMTCONVERT)              += arm/fmtconvert_init_arm.o
+OBJS-$(CONFIG_G722DSP)                 += arm/g722dsp_init_arm.o
 OBJS-$(CONFIG_H264CHROMA)              += arm/h264chroma_init_arm.o
 OBJS-$(CONFIG_H264DSP)                 += arm/h264dsp_init_arm.o
 OBJS-$(CONFIG_H264PRED)                += arm/h264pred_init_arm.o
@@ -18,9 +21,6 @@ OBJS-$(CONFIG_IDCTDSP)                 += arm/idctdsp_init_arm.o        \
                                           arm/idctdsp_arm.o             \
                                           arm/jrevdct_arm.o             \
                                           arm/simple_idct_arm.o
-OBJS-$(CONFIG_FLACDSP)                 += arm/flacdsp_init_arm.o        \
-                                          arm/flacdsp_arm.o
-OBJS-$(CONFIG_G722DSP)                 += arm/g722dsp_init_arm.o
 OBJS-$(CONFIG_LLAUDDSP)                += arm/lossless_audiodsp_init_arm.o
 OBJS-$(CONFIG_ME_CMP)                  += arm/me_cmp_init_arm.o
 OBJS-$(CONFIG_MPEGAUDIODSP)            += arm/mpegaudiodsp_init_arm.o
@@ -28,7 +28,9 @@ OBJS-$(CONFIG_MPEGVIDEO)               += arm/mpegvideo_arm.o
 OBJS-$(CONFIG_MPEGVIDEOENC)            += arm/mpegvideoencdsp_init_arm.o
 OBJS-$(CONFIG_NEON_CLOBBER_TEST)       += arm/neontest.o
 OBJS-$(CONFIG_PIXBLOCKDSP)             += arm/pixblockdsp_init_arm.o
+OBJS-$(CONFIG_RDFT)                    += arm/rdft_init_arm.o
 OBJS-$(CONFIG_RV34DSP)                 += arm/rv34dsp_init_arm.o
+OBJS-$(CONFIG_VC1DSP)                  += arm/vc1dsp_init_arm.o
 OBJS-$(CONFIG_VIDEODSP)                += arm/videodsp_init_arm.o
 OBJS-$(CONFIG_VP3DSP)                  += arm/vp3dsp_init_arm.o
 OBJS-$(CONFIG_VP8DSP)                  += arm/vp8dsp_init_arm.o
@@ -40,7 +42,6 @@ OBJS-$(CONFIG_DCA_DECODER)             += arm/synth_filter_init_arm.o
 OBJS-$(CONFIG_HEVC_DECODER)            += arm/hevcdsp_init_arm.o
 OBJS-$(CONFIG_MLP_DECODER)             += arm/mlpdsp_init_arm.o
 OBJS-$(CONFIG_RV40_DECODER)            += arm/rv40dsp_init_arm.o
-OBJS-$(CONFIG_VC1_DECODER)             += arm/vc1dsp_init_arm.o
 OBJS-$(CONFIG_VORBIS_DECODER)          += arm/vorbisdsp_init_arm.o
 OBJS-$(CONFIG_VP6_DECODER)             += arm/vp6dsp_init_arm.o
 
@@ -70,13 +71,13 @@ ARMV6-OBJS-$(CONFIG_ME_CMP)            += arm/me_cmp_armv6.o
 ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP)      += arm/mpegaudiodsp_fixed_armv6.o
 ARMV6-OBJS-$(CONFIG_MPEGVIDEOENC)      += arm/mpegvideoencdsp_armv6.o
 ARMV6-OBJS-$(CONFIG_PIXBLOCKDSP)       += arm/pixblockdsp_armv6.o
+ARMV6-OBJS-$(CONFIG_STARTCODE)         += arm/startcode_armv6.o
 ARMV6-OBJS-$(CONFIG_VP8DSP)            += arm/vp8_armv6.o               \
                                           arm/vp8dsp_init_armv6.o       \
                                           arm/vp8dsp_armv6.o
 
 # decoders/encoders
 ARMV6-OBJS-$(CONFIG_MLP_DECODER)       += arm/mlpdsp_armv6.o
-ARMV6-OBJS-$(CONFIG_STARTCODE)         += arm/startcode_armv6.o
 
 
 # VFP optimizations
@@ -118,6 +119,8 @@ NEON-OBJS-$(CONFIG_MDCT)               += arm/mdct_neon.o               \
                                           arm/mdct_fixed_neon.o
 NEON-OBJS-$(CONFIG_MPEGVIDEO)          += arm/mpegvideo_neon.o
 NEON-OBJS-$(CONFIG_RDFT)               += arm/rdft_neon.o
+NEON-OBJS-$(CONFIG_VC1DSP)             += arm/vc1dsp_init_neon.o        \
+                                          arm/vc1dsp_neon.o
 NEON-OBJS-$(CONFIG_VP3DSP)             += arm/vp3dsp_neon.o
 NEON-OBJS-$(CONFIG_VP8DSP)             += arm/vp8dsp_init_neon.o        \
                                           arm/vp8dsp_neon.o
@@ -134,7 +137,5 @@ NEON-OBJS-$(CONFIG_HEVC_DECODER)       += arm/hevcdsp_init_neon.o       \
 NEON-OBJS-$(CONFIG_RV30_DECODER)       += arm/rv34dsp_neon.o
 NEON-OBJS-$(CONFIG_RV40_DECODER)       += arm/rv34dsp_neon.o            \
                                           arm/rv40dsp_neon.o
-NEON-OBJS-$(CONFIG_VC1_DECODER)        += arm/vc1dsp_init_neon.o        \
-                                          arm/vc1dsp_neon.o
 NEON-OBJS-$(CONFIG_VORBIS_DECODER)     += arm/vorbisdsp_neon.o
 NEON-OBJS-$(CONFIG_VP6_DECODER)        += arm/vp6dsp_neon.o
diff --git a/libavcodec/arm/dct-test.c b/libavcodec/arm/dct-test.c
deleted file mode 100644
index f9076b3..0000000
--- a/libavcodec/arm/dct-test.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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 "config.h"
-
-#include "idct.h"
-
-static const struct algo fdct_tab_arch[] = {
-    { 0 }
-};
-
-static const struct algo idct_tab_arch[] = {
-    { "SIMPLE-ARM",     ff_simple_idct_arm,     FF_IDCT_PERM_NONE },
-    { "INT-ARM",        ff_j_rev_dct_arm,       FF_IDCT_PERM_LIBMPEG2 },
-#if HAVE_ARMV5TE
-    { "SIMPLE-ARMV5TE", ff_simple_idct_armv5te, FF_IDCT_PERM_NONE,      AV_CPU_FLAG_ARMV5TE },
-#endif
-#if HAVE_ARMV6
-    { "SIMPLE-ARMV6",   ff_simple_idct_armv6,   FF_IDCT_PERM_LIBMPEG2,  AV_CPU_FLAG_ARMV6 },
-#endif
-#if HAVE_NEON
-    { "SIMPLE-NEON",    ff_simple_idct_neon,    FF_IDCT_PERM_PARTTRANS, AV_CPU_FLAG_NEON },
-#endif
-    { 0 }
-};
diff --git a/libavcodec/arm/fft_fixed_init_arm.c b/libavcodec/arm/fft_fixed_init_arm.c
index b60bb9f..11226d6 100644
--- a/libavcodec/arm/fft_fixed_init_arm.c
+++ b/libavcodec/arm/fft_fixed_init_arm.c
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
 #include "libavutil/arm/cpu.h"
 
 #define FFT_FLOAT 0
diff --git a/libavcodec/arm/fft_init_arm.c b/libavcodec/arm/fft_init_arm.c
index 055c2c1..331bd65 100644
--- a/libavcodec/arm/fft_init_arm.c
+++ b/libavcodec/arm/fft_init_arm.c
@@ -18,10 +18,11 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
 #include "libavutil/arm/cpu.h"
+
 #include "libavcodec/fft.h"
-#include "libavcodec/rdft.h"
-#include "libavcodec/synth_filter.h"
 
 void ff_fft_calc_vfp(FFTContext *s, FFTComplex *z);
 
@@ -34,8 +35,6 @@ void ff_imdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input
 void ff_imdct_half_neon(FFTContext *s, FFTSample *output, const FFTSample *input);
 void ff_mdct_calc_neon(FFTContext *s, FFTSample *output, const FFTSample *input);
 
-void ff_rdft_calc_neon(struct RDFTContext *s, FFTSample *z);
-
 av_cold void ff_fft_init_arm(FFTContext *s)
 {
     int cpu_flags = av_get_cpu_flags();
@@ -60,13 +59,3 @@ av_cold void ff_fft_init_arm(FFTContext *s)
 #endif
     }
 }
-
-#if CONFIG_RDFT
-av_cold void ff_rdft_init_arm(RDFTContext *s)
-{
-    int cpu_flags = av_get_cpu_flags();
-
-    if (have_neon(cpu_flags))
-        s->rdft_calc    = ff_rdft_calc_neon;
-}
-#endif
diff --git a/libavcodec/arm/mlpdsp_armv6.S b/libavcodec/arm/mlpdsp_armv6.S
index d98f807..b7ecf6c 100644
--- a/libavcodec/arm/mlpdsp_armv6.S
+++ b/libavcodec/arm/mlpdsp_armv6.S
@@ -240,7 +240,7 @@ DAT3    .req    v4
 DAT4    .req    v5
 DAT5    .req    v6
 DAT6    .req    sl // use these rather than the otherwise unused
-DAT7    .req    fp // ip and lr so that we can load them usinf LDRD
+DAT7    .req    fp // ip and lr so that we can load them using LDRD
 
  .macro output4words  tail, head, r0, r1, r2, r3, r4, r5, r6, r7, pointer_dead=0
   .if \head
diff --git a/libavcodec/arm/mpegvideo_armv5te.c b/libavcodec/arm/mpegvideo_armv5te.c
index 88c5f4f..e20bb4c 100644
--- a/libavcodec/arm/mpegvideo_armv5te.c
+++ b/libavcodec/arm/mpegvideo_armv5te.c
@@ -29,7 +29,7 @@ void ff_dct_unquantize_h263_armv5te(int16_t *block, int qmul, int qadd, int coun
 
 #ifdef ENABLE_ARM_TESTS
 /**
- * h263 dequantizer supplementary function, it is performance critical and needs to
+ * H.263 dequantizer supplementary function, it is performance critical and needs to
  * have optimized implementations for each architecture. Is also used as a reference
  * implementation in regression tests
  */
diff --git a/libavcodec/arm/neontest.c b/libavcodec/arm/neontest.c
index a3b5b8e..a81d14d 100644
--- a/libavcodec/arm/neontest.c
+++ b/libavcodec/arm/neontest.c
@@ -23,7 +23,7 @@
 #include "libavutil/arm/neontest.h"
 
 wrap(avcodec_open2(AVCodecContext *avctx,
-                   AVCodec *codec,
+                   const AVCodec *codec,
                    AVDictionary **options))
 {
     testneonclobbers(avcodec_open2, avctx, codec, options);
diff --git a/libavcodec/arm/rdft_init_arm.c b/libavcodec/arm/rdft_init_arm.c
new file mode 100644
index 0000000..1c5d8be
--- /dev/null
+++ b/libavcodec/arm/rdft_init_arm.c
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/arm/cpu.h"
+
+#include "libavcodec/rdft.h"
+
+void ff_rdft_calc_neon(struct RDFTContext *s, FFTSample *z);
+
+av_cold void ff_rdft_init_arm(RDFTContext *s)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (have_neon(cpu_flags))
+        s->rdft_calc    = ff_rdft_calc_neon;
+}
diff --git a/libavcodec/arm/simple_idct_arm.S b/libavcodec/arm/simple_idct_arm.S
index c630073..42d79ab 100644
--- a/libavcodec/arm/simple_idct_arm.S
+++ b/libavcodec/arm/simple_idct_arm.S
@@ -64,7 +64,7 @@ function ff_simple_idct_arm, export=1
 
 
 __row_loop:
-        @@ read the row and check if it is null, almost null, or not, according to strongarm specs, it is not necessary to optimize ldr accesses (i.e. split 32bits in 2 16bits words), at least it gives more usable registers :)
+        @@ read the row and check if it is null, almost null, or not, according to strongarm specs, it is not necessary to optimize ldr accesses (i.e. split 32 bits in two 16-bit words), at least it gives more usable registers :)
         ldr r1, [r14, #0]        @ R1=(int32)(R12)[0]=ROWr32[0] (relative row cast to a 32b pointer)
         ldr r2, [r14, #4]        @ R2=(int32)(R12)[1]=ROWr32[1]
         ldr r3, [r14, #8]        @ R3=ROWr32[2]
@@ -234,8 +234,8 @@ __end_a_evaluation:
         @@ row[7] = (a0 - b0) >> ROW_SHIFT;
         add r8, r6, r0           @ R8=a0+b0
         add r9, r2, r1           @ R9=a1+b1
-        @@ put 2 16 bits half-words in a 32bits word
-        @@ ROWr32[0]=ROWr16[0] | (ROWr16[1]<<16) (only Little Endian compliant then!!!)
+        @@ put two 16-bit half-words in a 32-bit word
+        @@ ROWr32[0]=ROWr16[0] | (ROWr16[1]<<16) (only little-endian compliant then!!!)
         ldr r10, =MASK_MSHW      @ R10=0xFFFF0000
         and r9, r10, r9, lsl #ROW_SHIFT2MSHW @ R9=0xFFFF0000 & ((a1+b1)<<5)
         mvn r11, r10             @ R11= NOT R10= 0x0000FFFF
diff --git a/libavcodec/arm/vp8dsp_neon.S b/libavcodec/arm/vp8dsp_neon.S
index 5319346..2e87fb0 100644
--- a/libavcodec/arm/vp8dsp_neon.S
+++ b/libavcodec/arm/vp8dsp_neon.S
@@ -322,7 +322,7 @@ endfunc
 
         vmov.i16        q12, #3
         vsubl.s8        q10, d8,  d6            @ QS0 - PS0
-        vsubl.s8        q11, d9,  d7            @   (widened to 16bit)
+        vsubl.s8        q11, d9,  d7            @   (widened to 16 bits)
         veor            q2,  q2,  q13           @ PS1 = P1 ^ 0x80
         veor            q5,  q5,  q13           @ QS1 = Q1 ^ 0x80
         vmul.i16        q10, q10, q12           @ w = 3 * (QS0 - PS0)
diff --git a/libavcodec/ass.c b/libavcodec/ass.c
index 56d452f..b4f081c 100644
--- a/libavcodec/ass.c
+++ b/libavcodec/ass.c
@@ -90,101 +90,42 @@ int ff_ass_subtitle_header_default(AVCodecContext *avctx)
                                ASS_DEFAULT_ALIGNMENT);
 }
 
-static void insert_ts(AVBPrint *buf, int ts)
+char *ff_ass_get_dialog(int readorder, int layer, const char *style,
+                        const char *speaker, const char *text)
 {
-    if (ts == -1) {
-        av_bprintf(buf, "9:59:59.99,");
-    } else {
-        int h, m, s;
-
-        h = ts/360000;  ts -= 360000*h;
-        m = ts/  6000;  ts -=   6000*m;
-        s = ts/   100;  ts -=    100*s;
-        av_bprintf(buf, "%d:%02d:%02d.%02d,", h, m, s, ts);
-    }
-}
-
-int ff_ass_bprint_dialog(AVBPrint *buf, const char *dialog,
-                         int ts_start, int duration, int raw)
-{
-    int dlen;
-
-    if (!raw || raw == 2) {
-        long int layer = 0;
-
-        if (raw == 2) {
-            /* skip ReadOrder */
-            dialog = strchr(dialog, ',');
-            if (!dialog)
-                return AVERROR_INVALIDDATA;
-            dialog++;
-
-            /* extract Layer or Marked */
-            layer = strtol(dialog, (char**)&dialog, 10);
-            if (*dialog != ',')
-                return AVERROR_INVALIDDATA;
-            dialog++;
-        }
-        av_bprintf(buf, "Dialogue: %ld,", layer);
-        insert_ts(buf, ts_start);
-        insert_ts(buf, duration == -1 ? -1 : ts_start + duration);
-        if (raw != 2)
-            av_bprintf(buf, "Default,,0,0,0,,");
-    }
-
-    dlen = strcspn(dialog, "\n");
-    dlen += dialog[dlen] == '\n';
-
-    av_bprintf(buf, "%.*s", dlen, dialog);
-    if (raw == 2)
-        av_bprintf(buf, "\r\n");
-
-    return dlen;
+    return av_asprintf("%d,%d,%s,%s,0,0,0,,%s",
+                       readorder, layer, style ? style : "Default",
+                       speaker ? speaker : "", text);
 }
 
 int ff_ass_add_rect(AVSubtitle *sub, const char *dialog,
-                    int ts_start, int duration, int raw)
+                    int readorder, int layer, const char *style,
+                    const char *speaker)
 {
-    AVBPrint buf;
-    int ret, dlen;
+    char *ass_str;
     AVSubtitleRect **rects;
 
-    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
-    if ((ret = ff_ass_bprint_dialog(&buf, dialog, ts_start, duration, raw)) < 0)
-        goto err;
-    dlen = ret;
-    if (!av_bprint_is_complete(&buf))
-        goto errnomem;
-
     rects = av_realloc_array(sub->rects, (sub->num_rects+1), sizeof(*sub->rects));
     if (!rects)
-        goto errnomem;
+        return AVERROR(ENOMEM);
     sub->rects = rects;
-    sub->end_display_time = FFMAX(sub->end_display_time, 10 * duration);
     rects[sub->num_rects]       = av_mallocz(sizeof(*rects[0]));
     if (!rects[sub->num_rects])
-        goto errnomem;
+        return AVERROR(ENOMEM);
     rects[sub->num_rects]->type = SUBTITLE_ASS;
-    ret = av_bprint_finalize(&buf, &rects[sub->num_rects]->ass);
-    if (ret < 0)
-        goto err;
+    ass_str = ff_ass_get_dialog(readorder, layer, style, speaker, dialog);
+    if (!ass_str)
+        return AVERROR(ENOMEM);
+    rects[sub->num_rects]->ass = ass_str;
     sub->num_rects++;
-    return dlen;
-
-errnomem:
-    ret = AVERROR(ENOMEM);
-err:
-    av_bprint_finalize(&buf, NULL);
-    return ret;
+    return 0;
 }
 
-int ff_ass_add_rect_bprint(AVSubtitle *sub, AVBPrint *buf,
-                           int ts_start, int duration)
+void ff_ass_decoder_flush(AVCodecContext *avctx)
 {
-    av_bprintf(buf, "\r\n");
-    if (!av_bprint_is_complete(buf))
-        return AVERROR(ENOMEM);
-    return ff_ass_add_rect(sub, buf->str, ts_start, duration, 0);
+    FFASSDecoderContext *s = avctx->priv_data;
+    if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
+        s->readorder = 0;
 }
 
 void ff_ass_bprint_text_event(AVBPrint *buf, const char *p, int size,
diff --git a/libavcodec/ass.h b/libavcodec/ass.h
index 621a7ba..314b43b 100644
--- a/libavcodec/ass.h
+++ b/libavcodec/ass.h
@@ -43,6 +43,10 @@
 #define ASS_DEFAULT_BORDERSTYLE 1
 /** @} */
 
+typedef struct FFASSDecoderContext {
+    int readorder;
+} FFASSDecoderContext;
+
 /**
  * Generate a suitable AVCodecContext.subtitle_header for SUBTITLE_ASS.
  *
@@ -74,55 +78,23 @@ int ff_ass_subtitle_header(AVCodecContext *avctx,
 int ff_ass_subtitle_header_default(AVCodecContext *avctx);
 
 /**
- * Add an ASS dialog line to an AVSubtitle as a new AVSubtitleRect.
- *
- * @param sub pointer to the AVSubtitle
- * @param dialog ASS dialog to add to sub
- * @param ts_start start timestamp for this dialog (in 1/100 second unit)
- * @param duration duration for this dialog (in 1/100 second unit), can be -1
- *                 to last until the end of the presentation
- * @param raw when set to 2, it indicates that dialog contains an ASS
- *                           dialog line as muxed in Matroska
- *            when set to 1, it indicates that dialog contains a whole SSA
- *                           dialog line which should be copied as is.
- *            when set to 0, it indicates that dialog contains only the Text
- *                           part of the ASS dialog line, the rest of the line
- *                           will be generated.
- * @return number of characters read from dialog. It can be less than the whole
- *         length of dialog, if dialog contains several lines of text.
- *         A negative value indicates an error.
+ * Craft an ASS dialog string.
  */
-int ff_ass_add_rect(AVSubtitle *sub, const char *dialog,
-                    int ts_start, int duration, int raw);
+char *ff_ass_get_dialog(int readorder, int layer, const char *style,
+                        const char *speaker, const char *text);
 
 /**
- * Same as ff_ass_add_rect, but taking an AVBPrint buffer instead of a
- * string, and assuming raw=0.
+ * Add an ASS dialog to a subtitle.
  */
-int ff_ass_add_rect_bprint(AVSubtitle *sub, AVBPrint *buf,
-                           int ts_start, int duration);
+int ff_ass_add_rect(AVSubtitle *sub, const char *dialog,
+                    int readorder, int layer, const char *style,
+                    const char *speaker);
 
 /**
- * Add an ASS dialog line to an AVBPrint buffer.
- *
- * @param buf pointer to an initialized AVBPrint buffer
- * @param dialog ASS dialog to add to sub
- * @param ts_start start timestamp for this dialog (in 1/100 second unit)
- * @param duration duration for this dialog (in 1/100 second unit), can be -1
- *                 to last until the end of the presentation
- * @param raw when set to 2, it indicates that dialog contains an ASS
- *                           dialog line as muxed in Matroska
- *            when set to 1, it indicates that dialog contains a whole SSA
- *                           dialog line which should be copied as is.
- *            when set to 0, it indicates that dialog contains only the Text
- *                           part of the ASS dialog line, the rest of the line
- *                           will be generated.
- * @return number of characters read from dialog. It can be less than the whole
- *         length of dialog, if dialog contains several lines of text.
- *         A negative value indicates an error.
+ * Helper to flush a text subtitles decoder making use of the
+ * FFASSDecoderContext.
  */
-int ff_ass_bprint_dialog(AVBPrint *buf, const char *dialog,
-                         int ts_start, int duration, int raw);
+void ff_ass_decoder_flush(AVCodecContext *avctx);
 
 /**
  * Escape a text subtitle using ASS syntax into an AVBPrint buffer.
diff --git a/libavcodec/ass_split.c b/libavcodec/ass_split.c
index f84a686..beaba7e 100644
--- a/libavcodec/ass_split.c
+++ b/libavcodec/ass_split.c
@@ -409,6 +409,55 @@ ASSDialog *ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf,
     return dialog;
 }
 
+void ff_ass_free_dialog(ASSDialog **dialogp)
+{
+    ASSDialog *dialog = *dialogp;
+    if (!dialog)
+        return;
+    av_freep(&dialog->style);
+    av_freep(&dialog->name);
+    av_freep(&dialog->effect);
+    av_freep(&dialog->text);
+    av_freep(dialogp);
+}
+
+ASSDialog *ff_ass_split_dialog2(ASSSplitContext *ctx, const char *buf)
+{
+    int i;
+    static const ASSFields fields[] = {
+        {"ReadOrder", ASS_INT, offsetof(ASSDialog, readorder)},
+        {"Layer",     ASS_INT, offsetof(ASSDialog, layer)    },
+        {"Style",     ASS_STR, offsetof(ASSDialog, style)    },
+        {"Name",      ASS_STR, offsetof(ASSDialog, name)     },
+        {"MarginL",   ASS_INT, offsetof(ASSDialog, margin_l) },
+        {"MarginR",   ASS_INT, offsetof(ASSDialog, margin_r) },
+        {"MarginV",   ASS_INT, offsetof(ASSDialog, margin_v) },
+        {"Effect",    ASS_STR, offsetof(ASSDialog, effect)   },
+        {"Text",      ASS_STR, offsetof(ASSDialog, text)     },
+    };
+
+    ASSDialog *dialog = av_mallocz(sizeof(*dialog));
+    if (!dialog)
+        return NULL;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(fields); i++) {
+        size_t len;
+        const int last = i == FF_ARRAY_ELEMS(fields) - 1;
+        const ASSFieldType type = fields[i].type;
+        uint8_t *ptr = (uint8_t *)dialog + fields[i].offset;
+        buf = skip_space(buf);
+        len = last ? strlen(buf) : strcspn(buf, ",");
+        if (len >= INT_MAX) {
+            ff_ass_free_dialog(&dialog);
+            return NULL;
+        }
+        convert_func[type](ptr, buf, len);
+        buf += len;
+        if (*buf) buf++;
+    }
+    return dialog;
+}
+
 void ff_ass_split_free(ASSSplitContext *ctx)
 {
     if (ctx) {
diff --git a/libavcodec/ass_split.h b/libavcodec/ass_split.h
index defb5cc..30ce772 100644
--- a/libavcodec/ass_split.h
+++ b/libavcodec/ass_split.h
@@ -69,6 +69,7 @@ typedef struct {
  * fields extracted from the [Events] section
  */
 typedef struct {
+    int   readorder;
     int   layer;    /**< higher numbered layers are drawn over lower numbered */
     int   start;    /**< start time of the dialog in centiseconds */
     int   end;      /**< end time of the dialog in centiseconds */
@@ -110,7 +111,7 @@ ASSSplitContext *ff_ass_split(const char *buf);
 
 /**
  * Split one or several ASS "Dialogue" lines from a string buffer and store
- * them in a already initialized context.
+ * them in an already initialized context.
  *
  * @param ctx Context previously initialized by ff_ass_split().
  * @param buf String containing the ASS "Dialogue" lines.
@@ -125,6 +126,20 @@ ASSDialog *ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf,
                                int cache, int *number);
 
 /**
+ * Free a dialogue obtained from ff_ass_split_dialog2().
+ */
+void ff_ass_free_dialog(ASSDialog **dialogp);
+
+/**
+ * Split one ASS Dialogue line from a string buffer.
+ *
+ * @param ctx Context previously initialized by ff_ass_split().
+ * @param buf String containing the ASS "Dialogue" line.
+ * @return Pointer to the split ASSDialog. Must be freed with ff_ass_free_dialog()
+ */
+ASSDialog *ff_ass_split_dialog2(ASSSplitContext *ctx, const char *buf);
+
+/**
  * Free all the memory allocated for an ASSSplitContext.
  *
  * @param ctx Context previously initialized by ff_ass_split().
diff --git a/libavcodec/assdec.c b/libavcodec/assdec.c
index 11dbde0..3178f29 100644
--- a/libavcodec/assdec.c
+++ b/libavcodec/assdec.c
@@ -23,7 +23,6 @@
 
 #include "avcodec.h"
 #include "ass.h"
-#include "ass_split.h"
 #include "libavutil/internal.h"
 #include "libavutil/mem.h"
 
@@ -35,79 +34,44 @@ static av_cold int ass_decode_init(AVCodecContext *avctx)
     memcpy(avctx->subtitle_header, avctx->extradata, avctx->extradata_size);
     avctx->subtitle_header[avctx->extradata_size] = 0;
     avctx->subtitle_header_size = avctx->extradata_size;
-    avctx->priv_data = ff_ass_split(avctx->extradata);
-    if(!avctx->priv_data)
-        return -1;
     return 0;
 }
 
-static int ass_decode_close(AVCodecContext *avctx)
-{
-    ff_ass_split_free(avctx->priv_data);
-    avctx->priv_data = NULL;
-    return 0;
-}
-
-#if CONFIG_SSA_DECODER
-static int ssa_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr,
+static int ass_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr,
                             AVPacket *avpkt)
 {
-    const char *ptr = avpkt->data;
-    int len, size = avpkt->size;
+    AVSubtitle *sub = data;
 
-    while (size > 0) {
-        int duration;
-        ASSDialog *dialog = ff_ass_split_dialog(avctx->priv_data, ptr, 0, NULL);
-        if (!dialog)
-            return AVERROR_INVALIDDATA;
-        duration = dialog->end - dialog->start;
-        len = ff_ass_add_rect(data, ptr, 0, duration, 1);
-        if (len < 0)
-            return len;
-        ptr  += len;
-        size -= len;
-    }
+    if (avpkt->size <= 0)
+        return avpkt->size;
 
-    *got_sub_ptr = avpkt->size > 0;
+    sub->rects = av_malloc(sizeof(*sub->rects));
+    if (!sub->rects)
+        return AVERROR(ENOMEM);
+    sub->rects[0] = av_mallocz(sizeof(*sub->rects[0]));
+    if (!sub->rects[0])
+        return AVERROR(ENOMEM);
+    sub->num_rects = 1;
+    sub->rects[0]->type = SUBTITLE_ASS;
+    sub->rects[0]->ass  = av_strdup(avpkt->data);
+    if (!sub->rects[0]->ass)
+        return AVERROR(ENOMEM);
+    *got_sub_ptr = 1;
     return avpkt->size;
 }
 
+#if CONFIG_SSA_DECODER
 AVCodec ff_ssa_decoder = {
     .name         = "ssa",
-    .long_name    = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"),
+    .long_name    = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"),
     .type         = AVMEDIA_TYPE_SUBTITLE,
-    .id           = AV_CODEC_ID_SSA,
+    .id           = AV_CODEC_ID_ASS,
     .init         = ass_decode_init,
-    .decode       = ssa_decode_frame,
-    .close        = ass_decode_close,
+    .decode       = ass_decode_frame,
 };
 #endif
 
 #if CONFIG_ASS_DECODER
-static int ass_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr,
-                            AVPacket *avpkt)
-{
-    int ret;
-    AVSubtitle *sub = data;
-    const char *ptr = avpkt->data;
-    static const AVRational ass_tb = {1, 100};
-    const int ts_start    = av_rescale_q(avpkt->pts,      avctx->time_base, ass_tb);
-    const int ts_duration = av_rescale_q(avpkt->duration, avctx->time_base, ass_tb);
-
-    if (avpkt->size <= 0)
-        return avpkt->size;
-
-    ret = ff_ass_add_rect(sub, ptr, ts_start, ts_duration, 2);
-    if (ret < 0) {
-        if (ret == AVERROR_INVALIDDATA)
-            av_log(avctx, AV_LOG_ERROR, "Invalid ASS packet\n");
-        return ret;
-    }
-
-    *got_sub_ptr = avpkt->size > 0;
-    return avpkt->size;
-}
-
 AVCodec ff_ass_decoder = {
     .name         = "ass",
     .long_name    = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"),
@@ -115,6 +79,5 @@ AVCodec ff_ass_decoder = {
     .id           = AV_CODEC_ID_ASS,
     .init         = ass_decode_init,
     .decode       = ass_decode_frame,
-    .close        = ass_decode_close,
 };
 #endif
diff --git a/libavcodec/assenc.c b/libavcodec/assenc.c
index 5dc3b09..dc4f0ff 100644
--- a/libavcodec/assenc.c
+++ b/libavcodec/assenc.c
@@ -22,7 +22,6 @@
 #include <string.h>
 
 #include "avcodec.h"
-#include "ass_split.h"
 #include "ass.h"
 #include "libavutil/avstring.h"
 #include "libavutil/internal.h"
@@ -53,22 +52,16 @@ static int ass_encode_frame(AVCodecContext *avctx,
     for (i=0; i<sub->num_rects; i++) {
         char ass_line[2048];
         const char *ass = sub->rects[i]->ass;
+        long int layer;
+        char *p;
 
         if (sub->rects[i]->type != SUBTITLE_ASS) {
             av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
             return -1;
         }
 
-        if (strncmp(ass, "Dialogue: ", 10)) {
-            av_log(avctx, AV_LOG_ERROR, "AVSubtitle rectangle ass \"%s\""
-                   " does not look like a SSA markup\n", ass);
-            return AVERROR_INVALIDDATA;
-        }
-
-        if (avctx->codec->id == AV_CODEC_ID_ASS) {
-            long int layer;
-            char *p;
-
+#if FF_API_ASS_TIMING
+        if (!strncmp(ass, "Dialogue: ", 10)) {
             if (i > 0) {
                 av_log(avctx, AV_LOG_ERROR, "ASS encoder supports only one "
                        "ASS rectangle field.\n");
@@ -94,6 +87,8 @@ static int ass_encode_frame(AVCodecContext *avctx,
             ass_line[strcspn(ass_line, "\r\n")] = 0;
             ass = ass_line;
         }
+#endif
+
         len = av_strlcpy(buf+total_len, ass, bufsize-total_len);
 
         if (len > bufsize-total_len-1) {
@@ -110,9 +105,9 @@ static int ass_encode_frame(AVCodecContext *avctx,
 #if CONFIG_SSA_ENCODER
 AVCodec ff_ssa_encoder = {
     .name         = "ssa",
-    .long_name    = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"),
+    .long_name    = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"),
     .type         = AVMEDIA_TYPE_SUBTITLE,
-    .id           = AV_CODEC_ID_SSA,
+    .id           = AV_CODEC_ID_ASS,
     .init         = ass_encode_init,
     .encode_sub   = ass_encode_frame,
     .priv_data_size = sizeof(ASSEncodeContext),
diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c
index 4bdb63f..256990b 100644
--- a/libavcodec/atrac3.c
+++ b/libavcodec/atrac3.c
@@ -762,7 +762,7 @@ static int atrac3_decode_frame(AVCodecContext *avctx, void *data,
 
     ret = decode_frame(avctx, databuf, (float **)frame->extended_data);
     if (ret) {
-        av_log(NULL, AV_LOG_ERROR, "Frame decoding error!\n");
+        av_log(avctx, AV_LOG_ERROR, "Frame decoding error!\n");
         return ret;
     }
 
@@ -843,7 +843,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx)
         q->scrambled_stream    = 1;
 
     } else {
-        av_log(NULL, AV_LOG_ERROR, "Unknown extradata size %d.\n",
+        av_log(avctx, AV_LOG_ERROR, "Unknown extradata size %d.\n",
                avctx->extradata_size);
         return AVERROR(EINVAL);
     }
diff --git a/libavcodec/audiotoolboxdec.c b/libavcodec/audiotoolboxdec.c
new file mode 100644
index 0000000..1097668
--- /dev/null
+++ b/libavcodec/audiotoolboxdec.c
@@ -0,0 +1,625 @@
+/*
+ * Audio Toolbox system codecs
+ *
+ * copyright (c) 2016 Rodger Combs
+ *
+ * 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 <AudioToolbox/AudioToolbox.h>
+
+#include "config.h"
+#include "avcodec.h"
+#include "ac3_parser.h"
+#include "bytestream.h"
+#include "internal.h"
+#include "mpegaudiodecheader.h"
+#include "libavutil/avassert.h"
+#include "libavutil/opt.h"
+#include "libavutil/log.h"
+
+#ifndef __MAC_10_11
+#define kAudioFormatEnhancedAC3 'ec-3'
+#endif
+
+typedef struct ATDecodeContext {
+    AVClass *av_class;
+
+    AudioConverterRef converter;
+    AudioStreamPacketDescription pkt_desc;
+    AVPacket in_pkt;
+    AVPacket new_in_pkt;
+    AVBSFContext *bsf;
+    char *decoded_data;
+    int channel_map[64];
+
+    uint8_t *extradata;
+    int extradata_size;
+
+    int64_t last_pts;
+    int eof;
+} ATDecodeContext;
+
+static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
+{
+    switch (codec) {
+    case AV_CODEC_ID_AAC:
+        return kAudioFormatMPEG4AAC;
+    case AV_CODEC_ID_AC3:
+        return kAudioFormatAC3;
+    case AV_CODEC_ID_ADPCM_IMA_QT:
+        return kAudioFormatAppleIMA4;
+    case AV_CODEC_ID_ALAC:
+        return kAudioFormatAppleLossless;
+    case AV_CODEC_ID_AMR_NB:
+        return kAudioFormatAMR;
+    case AV_CODEC_ID_EAC3:
+        return kAudioFormatEnhancedAC3;
+    case AV_CODEC_ID_GSM_MS:
+        return kAudioFormatMicrosoftGSM;
+    case AV_CODEC_ID_ILBC:
+        return kAudioFormatiLBC;
+    case AV_CODEC_ID_MP1:
+        return kAudioFormatMPEGLayer1;
+    case AV_CODEC_ID_MP2:
+        return kAudioFormatMPEGLayer2;
+    case AV_CODEC_ID_MP3:
+        return kAudioFormatMPEGLayer3;
+    case AV_CODEC_ID_PCM_ALAW:
+        return kAudioFormatALaw;
+    case AV_CODEC_ID_PCM_MULAW:
+        return kAudioFormatULaw;
+    case AV_CODEC_ID_QDMC:
+        return kAudioFormatQDesign;
+    case AV_CODEC_ID_QDM2:
+        return kAudioFormatQDesign2;
+    default:
+        av_assert0(!"Invalid codec ID!");
+        return 0;
+    }
+}
+
+static int ffat_get_channel_id(AudioChannelLabel label)
+{
+    if (label == 0)
+        return -1;
+    else if (label <= kAudioChannelLabel_LFEScreen)
+        return label - 1;
+    else if (label <= kAudioChannelLabel_RightSurround)
+        return label + 4;
+    else if (label <= kAudioChannelLabel_CenterSurround)
+        return label + 1;
+    else if (label <= kAudioChannelLabel_RightSurroundDirect)
+        return label + 23;
+    else if (label <= kAudioChannelLabel_TopBackRight)
+        return label - 1;
+    else if (label < kAudioChannelLabel_RearSurroundLeft)
+        return -1;
+    else if (label <= kAudioChannelLabel_RearSurroundRight)
+        return label - 29;
+    else if (label <= kAudioChannelLabel_RightWide)
+        return label - 4;
+    else if (label == kAudioChannelLabel_LFE2)
+        return ff_ctzll(AV_CH_LOW_FREQUENCY_2);
+    else if (label == kAudioChannelLabel_Mono)
+        return ff_ctzll(AV_CH_FRONT_CENTER);
+    else
+        return -1;
+}
+
+static int ffat_compare_channel_descriptions(const void* a, const void* b)
+{
+    const AudioChannelDescription* da = a;
+    const AudioChannelDescription* db = b;
+    return ffat_get_channel_id(da->mChannelLabel) - ffat_get_channel_id(db->mChannelLabel);
+}
+
+static AudioChannelLayout *ffat_convert_layout(AudioChannelLayout *layout, UInt32* size)
+{
+    AudioChannelLayoutTag tag = layout->mChannelLayoutTag;
+    AudioChannelLayout *new_layout;
+    if (tag == kAudioChannelLayoutTag_UseChannelDescriptions)
+        return layout;
+    else if (tag == kAudioChannelLayoutTag_UseChannelBitmap)
+        AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForBitmap,
+                                   sizeof(UInt32), &layout->mChannelBitmap, size);
+    else
+        AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutForTag,
+                                   sizeof(AudioChannelLayoutTag), &tag, size);
+    new_layout = av_malloc(*size);
+    if (!new_layout) {
+        av_free(layout);
+        return NULL;
+    }
+    if (tag == kAudioChannelLayoutTag_UseChannelBitmap)
+        AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForBitmap,
+                               sizeof(UInt32), &layout->mChannelBitmap, size, new_layout);
+    else
+        AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutForTag,
+                               sizeof(AudioChannelLayoutTag), &tag, size, new_layout);
+    new_layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
+    av_free(layout);
+    return new_layout;
+}
+
+static int ffat_update_ctx(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    AudioStreamBasicDescription format;
+    UInt32 size = sizeof(format);
+    if (!AudioConverterGetProperty(at->converter,
+                                   kAudioConverterCurrentInputStreamDescription,
+                                   &size, &format)) {
+        if (format.mSampleRate)
+            avctx->sample_rate = format.mSampleRate;
+        avctx->channels = format.mChannelsPerFrame;
+        avctx->channel_layout = av_get_default_channel_layout(avctx->channels);
+        avctx->frame_size = format.mFramesPerPacket;
+    }
+
+    if (!AudioConverterGetProperty(at->converter,
+                                   kAudioConverterCurrentOutputStreamDescription,
+                                   &size, &format)) {
+        format.mSampleRate = avctx->sample_rate;
+        format.mChannelsPerFrame = avctx->channels;
+        AudioConverterSetProperty(at->converter,
+                                  kAudioConverterCurrentOutputStreamDescription,
+                                  size, &format);
+    }
+
+    if (!AudioConverterGetPropertyInfo(at->converter, kAudioConverterOutputChannelLayout,
+                                       &size, NULL) && size) {
+        AudioChannelLayout *layout = av_malloc(size);
+        uint64_t layout_mask = 0;
+        int i;
+        if (!layout)
+            return AVERROR(ENOMEM);
+        AudioConverterGetProperty(at->converter, kAudioConverterOutputChannelLayout,
+                                  &size, layout);
+        if (!(layout = ffat_convert_layout(layout, &size)))
+            return AVERROR(ENOMEM);
+        for (i = 0; i < layout->mNumberChannelDescriptions; i++) {
+            int id = ffat_get_channel_id(layout->mChannelDescriptions[i].mChannelLabel);
+            if (id < 0)
+                goto done;
+            if (layout_mask & (1 << id))
+                goto done;
+            layout_mask |= 1 << id;
+            layout->mChannelDescriptions[i].mChannelFlags = i; // Abusing flags as index
+        }
+        avctx->channel_layout = layout_mask;
+        qsort(layout->mChannelDescriptions, layout->mNumberChannelDescriptions,
+              sizeof(AudioChannelDescription), &ffat_compare_channel_descriptions);
+        for (i = 0; i < layout->mNumberChannelDescriptions; i++)
+            at->channel_map[i] = layout->mChannelDescriptions[i].mChannelFlags;
+done:
+        av_free(layout);
+    }
+
+    if (!avctx->frame_size)
+        avctx->frame_size = 2048;
+
+    return 0;
+}
+
+static void put_descr(PutByteContext *pb, int tag, unsigned int size)
+{
+    int i = 3;
+    bytestream2_put_byte(pb, tag);
+    for (; i > 0; i--)
+        bytestream2_put_byte(pb, (size >> (7 * i)) | 0x80);
+    bytestream2_put_byte(pb, size & 0x7F);
+}
+
+static uint8_t* ffat_get_magic_cookie(AVCodecContext *avctx, UInt32 *cookie_size)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    if (avctx->codec_id == AV_CODEC_ID_AAC) {
+        char *extradata;
+        PutByteContext pb;
+        *cookie_size = 5 + 3 + 5+13 + 5+at->extradata_size;
+        if (!(extradata = av_malloc(*cookie_size)))
+            return NULL;
+
+        bytestream2_init_writer(&pb, extradata, *cookie_size);
+
+        // ES descriptor
+        put_descr(&pb, 0x03, 3 + 5+13 + 5+at->extradata_size);
+        bytestream2_put_be16(&pb, 0);
+        bytestream2_put_byte(&pb, 0x00); // flags (= no flags)
+
+        // DecoderConfig descriptor
+        put_descr(&pb, 0x04, 13 + 5+at->extradata_size);
+
+        // Object type indication
+        bytestream2_put_byte(&pb, 0x40);
+
+        bytestream2_put_byte(&pb, 0x15); // flags (= Audiostream)
+
+        bytestream2_put_be24(&pb, 0); // Buffersize DB
+
+        bytestream2_put_be32(&pb, 0); // maxbitrate
+        bytestream2_put_be32(&pb, 0); // avgbitrate
+
+        // DecoderSpecific info descriptor
+        put_descr(&pb, 0x05, at->extradata_size);
+        bytestream2_put_buffer(&pb, at->extradata, at->extradata_size);
+        return extradata;
+    } else {
+        *cookie_size = at->extradata_size;
+        return at->extradata;
+    }
+}
+
+static av_cold int ffat_usable_extradata(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    return at->extradata_size &&
+           (avctx->codec_id == AV_CODEC_ID_ALAC ||
+            avctx->codec_id == AV_CODEC_ID_QDM2 ||
+            avctx->codec_id == AV_CODEC_ID_QDMC ||
+            avctx->codec_id == AV_CODEC_ID_AAC);
+}
+
+static int ffat_set_extradata(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    if (ffat_usable_extradata(avctx)) {
+        OSStatus status;
+        UInt32 cookie_size;
+        uint8_t *cookie = ffat_get_magic_cookie(avctx, &cookie_size);
+        if (!cookie)
+            return AVERROR(ENOMEM);
+
+        status = AudioConverterSetProperty(at->converter,
+                                           kAudioConverterDecompressionMagicCookie,
+                                           cookie_size, cookie);
+        if (status != 0)
+            av_log(avctx, AV_LOG_WARNING, "AudioToolbox cookie error: %i\n", (int)status);
+
+        if (cookie != at->extradata)
+            av_free(cookie);
+    }
+    return 0;
+}
+
+static av_cold int ffat_create_decoder(AVCodecContext *avctx, AVPacket *pkt)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    OSStatus status;
+    int i;
+
+    enum AVSampleFormat sample_fmt = (avctx->bits_per_raw_sample == 32) ?
+                                     AV_SAMPLE_FMT_S32 : AV_SAMPLE_FMT_S16;
+
+    AudioStreamBasicDescription in_format = {
+        .mFormatID = ffat_get_format_id(avctx->codec_id, avctx->profile),
+        .mBytesPerPacket = (avctx->codec_id == AV_CODEC_ID_ILBC) ? avctx->block_align : 0,
+    };
+    AudioStreamBasicDescription out_format = {
+        .mFormatID = kAudioFormatLinearPCM,
+        .mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked,
+        .mFramesPerPacket = 1,
+        .mBitsPerChannel = av_get_bytes_per_sample(sample_fmt) * 8,
+    };
+
+    avctx->sample_fmt = sample_fmt;
+
+    if (ffat_usable_extradata(avctx)) {
+        UInt32 format_size = sizeof(in_format);
+        UInt32 cookie_size;
+        uint8_t *cookie = ffat_get_magic_cookie(avctx, &cookie_size);
+        if (!cookie)
+            return AVERROR(ENOMEM);
+        status = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
+                                        cookie_size, cookie, &format_size, &in_format);
+        if (cookie != at->extradata)
+            av_free(cookie);
+        if (status != 0) {
+            av_log(avctx, AV_LOG_ERROR, "AudioToolbox header-parse error: %i\n", (int)status);
+            return AVERROR_UNKNOWN;
+        }
+#if CONFIG_MP1_AT_DECODER || CONFIG_MP2_AT_DECODER || CONFIG_MP3_AT_DECODER
+    } else if (pkt && pkt->size >= 4 &&
+               (avctx->codec_id == AV_CODEC_ID_MP1 ||
+                avctx->codec_id == AV_CODEC_ID_MP2 ||
+                avctx->codec_id == AV_CODEC_ID_MP3)) {
+        enum AVCodecID codec_id;
+        int bit_rate;
+        if (ff_mpa_decode_header(AV_RB32(pkt->data), &avctx->sample_rate,
+                                 &in_format.mChannelsPerFrame, &avctx->frame_size,
+                                 &bit_rate, &codec_id) < 0)
+            return AVERROR_INVALIDDATA;
+        avctx->bit_rate = bit_rate;
+        in_format.mSampleRate = avctx->sample_rate;
+#endif
+#if CONFIG_AC3_AT_DECODER || CONFIG_EAC3_AT_DECODER
+    } else if (pkt && pkt->size >= 7 &&
+               (avctx->codec_id == AV_CODEC_ID_AC3 ||
+                avctx->codec_id == AV_CODEC_ID_EAC3)) {
+        AC3HeaderInfo hdr, *phdr = &hdr;
+        GetBitContext gbc;
+        init_get_bits(&gbc, pkt->data, pkt->size);
+        if (avpriv_ac3_parse_header(&gbc, &phdr) < 0)
+            return AVERROR_INVALIDDATA;
+        in_format.mSampleRate = hdr.sample_rate;
+        in_format.mChannelsPerFrame = hdr.channels;
+        avctx->frame_size = hdr.num_blocks * 256;
+        avctx->bit_rate = hdr.bit_rate;
+#endif
+    } else {
+        in_format.mSampleRate = avctx->sample_rate ? avctx->sample_rate : 44100;
+        in_format.mChannelsPerFrame = avctx->channels ? avctx->channels : 1;
+    }
+
+    avctx->sample_rate = out_format.mSampleRate = in_format.mSampleRate;
+    avctx->channels = out_format.mChannelsPerFrame = in_format.mChannelsPerFrame;
+
+    if (avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_QT)
+        in_format.mFramesPerPacket = 64;
+
+    status = AudioConverterNew(&in_format, &out_format, &at->converter);
+
+    if (status != 0) {
+        av_log(avctx, AV_LOG_ERROR, "AudioToolbox init error: %i\n", (int)status);
+        return AVERROR_UNKNOWN;
+    }
+
+    if ((status = ffat_set_extradata(avctx)) < 0)
+        return status;
+
+    for (i = 0; i < (sizeof(at->channel_map) / sizeof(at->channel_map[0])); i++)
+        at->channel_map[i] = i;
+
+    ffat_update_ctx(avctx);
+
+    if(!(at->decoded_data = av_malloc(av_get_bytes_per_sample(avctx->sample_fmt)
+                                      * avctx->frame_size * avctx->channels)))
+        return AVERROR(ENOMEM);
+
+    at->last_pts = AV_NOPTS_VALUE;
+
+    return 0;
+}
+
+static av_cold int ffat_init_decoder(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    at->extradata = avctx->extradata;
+    at->extradata_size = avctx->extradata_size;
+
+    if ((avctx->channels && avctx->sample_rate) || ffat_usable_extradata(avctx))
+        return ffat_create_decoder(avctx, NULL);
+    else
+        return 0;
+}
+
+static OSStatus ffat_decode_callback(AudioConverterRef converter, UInt32 *nb_packets,
+                                     AudioBufferList *data,
+                                     AudioStreamPacketDescription **packets,
+                                     void *inctx)
+{
+    AVCodecContext *avctx = inctx;
+    ATDecodeContext *at = avctx->priv_data;
+
+    if (at->eof) {
+        *nb_packets = 0;
+        if (packets) {
+            *packets = &at->pkt_desc;
+            at->pkt_desc.mDataByteSize = 0;
+        }
+        return 0;
+    }
+
+    av_packet_unref(&at->in_pkt);
+    av_packet_move_ref(&at->in_pkt, &at->new_in_pkt);
+
+    if (!at->in_pkt.data) {
+        *nb_packets = 0;
+        return 1;
+    }
+
+    data->mNumberBuffers              = 1;
+    data->mBuffers[0].mNumberChannels = 0;
+    data->mBuffers[0].mDataByteSize   = at->in_pkt.size;
+    data->mBuffers[0].mData           = at->in_pkt.data;
+    *nb_packets = 1;
+
+    if (packets) {
+        *packets = &at->pkt_desc;
+        at->pkt_desc.mDataByteSize = at->in_pkt.size;
+    }
+
+    return 0;
+}
+
+#define COPY_SAMPLES(type) \
+    type *in_ptr = (type*)at->decoded_data; \
+    type *end_ptr = in_ptr + frame->nb_samples * avctx->channels; \
+    type *out_ptr = (type*)frame->data[0]; \
+    for (; in_ptr < end_ptr; in_ptr += avctx->channels, out_ptr += avctx->channels) { \
+        int c; \
+        for (c = 0; c < avctx->channels; c++) \
+            out_ptr[c] = in_ptr[at->channel_map[c]]; \
+    }
+
+static void ffat_copy_samples(AVCodecContext *avctx, AVFrame *frame)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    if (avctx->sample_fmt == AV_SAMPLE_FMT_S32) {
+        COPY_SAMPLES(int32_t);
+    } else {
+        COPY_SAMPLES(int16_t);
+    }
+}
+
+static int ffat_decode(AVCodecContext *avctx, void *data,
+                       int *got_frame_ptr, AVPacket *avpkt)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    AVFrame *frame = data;
+    int pkt_size = avpkt->size;
+    AVPacket filtered_packet = {0};
+    OSStatus ret;
+    AudioBufferList out_buffers;
+
+    if (avctx->codec_id == AV_CODEC_ID_AAC && avpkt->size > 2 &&
+        (AV_RB16(avpkt->data) & 0xfff0) == 0xfff0) {
+        AVPacket filter_pkt = {0};
+        if (!at->bsf) {
+            const AVBitStreamFilter *bsf = av_bsf_get_by_name("aac_adtstoasc");
+            if(!bsf)
+                return AVERROR_BSF_NOT_FOUND;
+            if ((ret = av_bsf_alloc(bsf, &at->bsf)))
+                return ret;
+            if (((ret = avcodec_parameters_from_context(at->bsf->par_in, avctx)) < 0) ||
+                ((ret = av_bsf_init(at->bsf)) < 0)) {
+                av_bsf_free(&at->bsf);
+                return ret;
+            }
+        }
+
+        if ((ret = av_packet_ref(&filter_pkt, avpkt)) < 0)
+            return ret;
+
+        if ((ret = av_bsf_send_packet(at->bsf, &filter_pkt)) < 0) {
+            av_packet_unref(&filter_pkt);
+            return ret;
+        }
+
+        if ((ret = av_bsf_receive_packet(at->bsf, &filtered_packet)) < 0)
+            return ret;
+
+        at->extradata = at->bsf->par_out->extradata;
+        at->extradata_size = at->bsf->par_out->extradata_size;
+
+        avpkt = &filtered_packet;
+    }
+
+    if (!at->converter) {
+        if ((ret = ffat_create_decoder(avctx, avpkt)) < 0) {
+            av_packet_unref(&filtered_packet);
+            return ret;
+        }
+    }
+
+    out_buffers = (AudioBufferList){
+        .mNumberBuffers = 1,
+        .mBuffers = {
+            {
+                .mNumberChannels = avctx->channels,
+                .mDataByteSize = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->frame_size
+                                 * avctx->channels,
+            }
+        }
+    };
+
+    av_packet_unref(&at->new_in_pkt);
+
+    if (avpkt->size) {
+        if (filtered_packet.data) {
+            at->new_in_pkt = filtered_packet;
+        } else if ((ret = av_packet_ref(&at->new_in_pkt, avpkt)) < 0) {
+            return ret;
+        }
+    } else {
+        at->eof = 1;
+    }
+
+    frame->sample_rate = avctx->sample_rate;
+
+    frame->nb_samples = avctx->frame_size;
+
+    out_buffers.mBuffers[0].mData = at->decoded_data;
+
+    ret = AudioConverterFillComplexBuffer(at->converter, ffat_decode_callback, avctx,
+                                          &frame->nb_samples, &out_buffers, NULL);
+    if ((!ret || ret == 1) && frame->nb_samples) {
+        if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+            return ret;
+        ffat_copy_samples(avctx, frame);
+        *got_frame_ptr = 1;
+        if (at->last_pts != AV_NOPTS_VALUE) {
+            frame->pkt_pts = at->last_pts;
+            at->last_pts = avpkt->pts;
+        }
+    } else if (ret && ret != 1) {
+        av_log(avctx, AV_LOG_WARNING, "Decode error: %i\n", ret);
+    } else {
+        at->last_pts = avpkt->pts;
+    }
+
+    return pkt_size;
+}
+
+static av_cold void ffat_decode_flush(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    AudioConverterReset(at->converter);
+    av_packet_unref(&at->new_in_pkt);
+    av_packet_unref(&at->in_pkt);
+}
+
+static av_cold int ffat_close_decoder(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    AudioConverterDispose(at->converter);
+    av_bsf_free(&at->bsf);
+    av_packet_unref(&at->new_in_pkt);
+    av_packet_unref(&at->in_pkt);
+    av_free(at->decoded_data);
+    return 0;
+}
+
+#define FFAT_DEC_CLASS(NAME) \
+    static const AVClass ffat_##NAME##_dec_class = { \
+        .class_name = "at_" #NAME "_dec", \
+        .version    = LIBAVUTIL_VERSION_INT, \
+    };
+
+#define FFAT_DEC(NAME, ID) \
+    FFAT_DEC_CLASS(NAME) \
+    AVCodec ff_##NAME##_at_decoder = { \
+        .name           = #NAME "_at", \
+        .long_name      = NULL_IF_CONFIG_SMALL(#NAME " (AudioToolbox)"), \
+        .type           = AVMEDIA_TYPE_AUDIO, \
+        .id             = ID, \
+        .priv_data_size = sizeof(ATDecodeContext), \
+        .init           = ffat_init_decoder, \
+        .close          = ffat_close_decoder, \
+        .decode         = ffat_decode, \
+        .flush          = ffat_decode_flush, \
+        .priv_class     = &ffat_##NAME##_dec_class, \
+        .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, \
+        .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE, \
+    };
+
+FFAT_DEC(aac,          AV_CODEC_ID_AAC)
+FFAT_DEC(ac3,          AV_CODEC_ID_AC3)
+FFAT_DEC(adpcm_ima_qt, AV_CODEC_ID_ADPCM_IMA_QT)
+FFAT_DEC(alac,         AV_CODEC_ID_ALAC)
+FFAT_DEC(amr_nb,       AV_CODEC_ID_AMR_NB)
+FFAT_DEC(eac3,         AV_CODEC_ID_EAC3)
+FFAT_DEC(gsm_ms,       AV_CODEC_ID_GSM_MS)
+FFAT_DEC(ilbc,         AV_CODEC_ID_ILBC)
+FFAT_DEC(mp1,          AV_CODEC_ID_MP1)
+FFAT_DEC(mp2,          AV_CODEC_ID_MP2)
+FFAT_DEC(mp3,          AV_CODEC_ID_MP3)
+FFAT_DEC(pcm_alaw,     AV_CODEC_ID_PCM_ALAW)
+FFAT_DEC(pcm_mulaw,    AV_CODEC_ID_PCM_MULAW)
+FFAT_DEC(qdmc,         AV_CODEC_ID_QDMC)
+FFAT_DEC(qdm2,         AV_CODEC_ID_QDM2)
diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c
new file mode 100644
index 0000000..c47fbd1
--- /dev/null
+++ b/libavcodec/audiotoolboxenc.c
@@ -0,0 +1,645 @@
+/*
+ * Audio Toolbox system codecs
+ *
+ * copyright (c) 2016 Rodger Combs
+ *
+ * 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 <AudioToolbox/AudioToolbox.h>
+
+#define FF_BUFQUEUE_SIZE 256
+#include "libavfilter/bufferqueue.h"
+
+#include "config.h"
+#include "audio_frame_queue.h"
+#include "avcodec.h"
+#include "bytestream.h"
+#include "internal.h"
+#include "libavformat/isom.h"
+#include "libavutil/avassert.h"
+#include "libavutil/opt.h"
+#include "libavutil/log.h"
+
+typedef struct ATDecodeContext {
+    AVClass *av_class;
+    int mode;
+    int quality;
+
+    AudioConverterRef converter;
+    struct FFBufQueue frame_queue;
+    struct FFBufQueue used_frame_queue;
+
+    unsigned pkt_size;
+    AudioFrameQueue afq;
+    int eof;
+    int frame_size;
+} ATDecodeContext;
+
+static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
+{
+    switch (codec) {
+    case AV_CODEC_ID_AAC:
+        switch (profile) {
+        case FF_PROFILE_AAC_LOW:
+        default:
+            return kAudioFormatMPEG4AAC;
+        case FF_PROFILE_AAC_HE:
+            return kAudioFormatMPEG4AAC_HE;
+        case FF_PROFILE_AAC_HE_V2:
+            return kAudioFormatMPEG4AAC_HE_V2;
+        case FF_PROFILE_AAC_LD:
+            return kAudioFormatMPEG4AAC_LD;
+        case FF_PROFILE_AAC_ELD:
+            return kAudioFormatMPEG4AAC_ELD;
+        }
+    case AV_CODEC_ID_ADPCM_IMA_QT:
+        return kAudioFormatAppleIMA4;
+    case AV_CODEC_ID_ALAC:
+        return kAudioFormatAppleLossless;
+    case AV_CODEC_ID_ILBC:
+        return kAudioFormatiLBC;
+    case AV_CODEC_ID_PCM_ALAW:
+        return kAudioFormatALaw;
+    case AV_CODEC_ID_PCM_MULAW:
+        return kAudioFormatULaw;
+    default:
+        av_assert0(!"Invalid codec ID!");
+        return 0;
+    }
+}
+
+static void ffat_update_ctx(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    UInt32 size = sizeof(unsigned);
+    AudioConverterPrimeInfo prime_info;
+    AudioStreamBasicDescription out_format;
+
+    AudioConverterGetProperty(at->converter,
+                              kAudioConverterPropertyMaximumOutputPacketSize,
+                              &size, &at->pkt_size);
+
+    if (at->pkt_size <= 0)
+        at->pkt_size = 1024 * 50;
+
+    size = sizeof(prime_info);
+
+    if (!AudioConverterGetProperty(at->converter,
+                                   kAudioConverterPrimeInfo,
+                                   &size, &prime_info)) {
+        avctx->initial_padding = prime_info.leadingFrames;
+    }
+
+    size = sizeof(out_format);
+    if (!AudioConverterGetProperty(at->converter,
+                                   kAudioConverterCurrentOutputStreamDescription,
+                                   &size, &out_format)) {
+        if (out_format.mFramesPerPacket)
+            avctx->frame_size = out_format.mFramesPerPacket;
+        if (out_format.mBytesPerPacket && avctx->codec_id == AV_CODEC_ID_ILBC)
+            avctx->block_align = out_format.mBytesPerPacket;
+    }
+
+    at->frame_size = avctx->frame_size;
+    if (avctx->codec_id == AV_CODEC_ID_PCM_MULAW ||
+        avctx->codec_id == AV_CODEC_ID_PCM_ALAW) {
+        at->pkt_size *= 1024;
+        avctx->frame_size *= 1024;
+    }
+}
+
+static int read_descr(GetByteContext *gb, int *tag)
+{
+    int len = 0;
+    int count = 4;
+    *tag = bytestream2_get_byte(gb);
+    while (count--) {
+        int c = bytestream2_get_byte(gb);
+        len = (len << 7) | (c & 0x7f);
+        if (!(c & 0x80))
+            break;
+    }
+    return len;
+}
+
+static int get_ilbc_mode(AVCodecContext *avctx)
+{
+    if (avctx->block_align == 38)
+        return 20;
+    else if (avctx->block_align == 50)
+        return 30;
+    else if (avctx->bit_rate > 0)
+        return avctx->bit_rate <= 14000 ? 30 : 20;
+    else
+        return 30;
+}
+
+static av_cold int get_channel_label(int channel)
+{
+    uint64_t map = 1 << channel;
+    if (map <= AV_CH_LOW_FREQUENCY)
+        return channel + 1;
+    else if (map <= AV_CH_BACK_RIGHT)
+        return channel + 29;
+    else if (map <= AV_CH_BACK_CENTER)
+        return channel - 1;
+    else if (map <= AV_CH_SIDE_RIGHT)
+        return channel - 4;
+    else if (map <= AV_CH_TOP_BACK_RIGHT)
+        return channel + 1;
+    else if (map <= AV_CH_STEREO_RIGHT)
+        return -1;
+    else if (map <= AV_CH_WIDE_RIGHT)
+        return channel + 4;
+    else if (map <= AV_CH_SURROUND_DIRECT_RIGHT)
+        return channel - 23;
+    else if (map == AV_CH_LOW_FREQUENCY_2)
+        return kAudioChannelLabel_LFE2;
+    else
+        return -1;
+}
+
+static int remap_layout(AudioChannelLayout *layout, uint64_t in_layout, int count)
+{
+    int i;
+    int c = 0;
+    layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
+    layout->mNumberChannelDescriptions = count;
+    for (i = 0; i < count; i++) {
+        int label;
+        while (!(in_layout & (1 << c)) && c < 64)
+            c++;
+        if (c == 64)
+            return AVERROR(EINVAL); // This should never happen
+        label = get_channel_label(c);
+        layout->mChannelDescriptions[i].mChannelLabel = label;
+        if (label < 0)
+            return AVERROR(EINVAL);
+        c++;
+    }
+    return 0;
+}
+
+static int get_aac_tag(uint64_t in_layout)
+{
+    switch (in_layout) {
+    case AV_CH_LAYOUT_MONO:
+        return kAudioChannelLayoutTag_Mono;
+    case AV_CH_LAYOUT_STEREO:
+        return kAudioChannelLayoutTag_Stereo;
+    case AV_CH_LAYOUT_QUAD:
+        return kAudioChannelLayoutTag_AAC_Quadraphonic;
+    case AV_CH_LAYOUT_OCTAGONAL:
+        return kAudioChannelLayoutTag_AAC_Octagonal;
+    case AV_CH_LAYOUT_SURROUND:
+        return kAudioChannelLayoutTag_AAC_3_0;
+    case AV_CH_LAYOUT_4POINT0:
+        return kAudioChannelLayoutTag_AAC_4_0;
+    case AV_CH_LAYOUT_5POINT0:
+        return kAudioChannelLayoutTag_AAC_5_0;
+    case AV_CH_LAYOUT_5POINT1:
+        return kAudioChannelLayoutTag_AAC_5_1;
+    case AV_CH_LAYOUT_6POINT0:
+        return kAudioChannelLayoutTag_AAC_6_0;
+    case AV_CH_LAYOUT_6POINT1:
+        return kAudioChannelLayoutTag_AAC_6_1;
+    case AV_CH_LAYOUT_7POINT0:
+        return kAudioChannelLayoutTag_AAC_7_0;
+    case AV_CH_LAYOUT_7POINT1_WIDE_BACK:
+        return kAudioChannelLayoutTag_AAC_7_1;
+    case AV_CH_LAYOUT_7POINT1:
+        return kAudioChannelLayoutTag_MPEG_7_1_C;
+    default:
+        return 0;
+    }
+}
+
+static av_cold int ffat_init_encoder(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    OSStatus status;
+
+    AudioStreamBasicDescription in_format = {
+        .mSampleRate = avctx->sample_rate,
+        .mFormatID = kAudioFormatLinearPCM,
+        .mFormatFlags = ((avctx->sample_fmt == AV_SAMPLE_FMT_FLT ||
+                          avctx->sample_fmt == AV_SAMPLE_FMT_DBL) ? kAudioFormatFlagIsFloat
+                        : avctx->sample_fmt == AV_SAMPLE_FMT_U8 ? 0
+                        : kAudioFormatFlagIsSignedInteger)
+                        | kAudioFormatFlagIsPacked,
+        .mBytesPerPacket = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels,
+        .mFramesPerPacket = 1,
+        .mBytesPerFrame = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels,
+        .mChannelsPerFrame = avctx->channels,
+        .mBitsPerChannel = av_get_bytes_per_sample(avctx->sample_fmt) * 8,
+    };
+    AudioStreamBasicDescription out_format = {
+        .mSampleRate = avctx->sample_rate,
+        .mFormatID = ffat_get_format_id(avctx->codec_id, avctx->profile),
+        .mChannelsPerFrame = in_format.mChannelsPerFrame,
+    };
+    UInt32 layout_size = sizeof(AudioChannelLayout) +
+                         sizeof(AudioChannelDescription) * avctx->channels;
+    AudioChannelLayout *channel_layout = av_malloc(layout_size);
+
+    if (!channel_layout)
+        return AVERROR(ENOMEM);
+
+    if (avctx->codec_id == AV_CODEC_ID_ILBC) {
+        int mode = get_ilbc_mode(avctx);
+        out_format.mFramesPerPacket  = 8000 * mode / 1000;
+        out_format.mBytesPerPacket   = (mode == 20 ? 38 : 50);
+    }
+
+    status = AudioConverterNew(&in_format, &out_format, &at->converter);
+
+    if (status != 0) {
+        av_log(avctx, AV_LOG_ERROR, "AudioToolbox init error: %i\n", (int)status);
+        av_free(channel_layout);
+        return AVERROR_UNKNOWN;
+    }
+
+    if (!avctx->channel_layout)
+        avctx->channel_layout = av_get_default_channel_layout(avctx->channels);
+
+    if ((status = remap_layout(channel_layout, avctx->channel_layout, avctx->channels)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid channel layout\n");
+        av_free(channel_layout);
+        return status;
+    }
+
+    if (AudioConverterSetProperty(at->converter, kAudioConverterInputChannelLayout,
+                                  layout_size, channel_layout)) {
+        av_log(avctx, AV_LOG_ERROR, "Unsupported input channel layout\n");
+        av_free(channel_layout);
+        return AVERROR(EINVAL);
+    }
+    if (avctx->codec_id == AV_CODEC_ID_AAC) {
+        int tag = get_aac_tag(avctx->channel_layout);
+        if (tag) {
+            channel_layout->mChannelLayoutTag = tag;
+            channel_layout->mNumberChannelDescriptions = 0;
+        }
+    }
+    if (AudioConverterSetProperty(at->converter, kAudioConverterOutputChannelLayout,
+                                  layout_size, channel_layout)) {
+        av_log(avctx, AV_LOG_ERROR, "Unsupported output channel layout\n");
+        av_free(channel_layout);
+        return AVERROR(EINVAL);
+    }
+    av_free(channel_layout);
+
+    if (avctx->bits_per_raw_sample)
+        AudioConverterSetProperty(at->converter,
+                                  kAudioConverterPropertyBitDepthHint,
+                                  sizeof(avctx->bits_per_raw_sample),
+                                  &avctx->bits_per_raw_sample);
+
+#if !TARGET_OS_IPHONE
+    if (at->mode == -1)
+        at->mode = (avctx->flags & AV_CODEC_FLAG_QSCALE) ?
+                   kAudioCodecBitRateControlMode_Variable :
+                   kAudioCodecBitRateControlMode_Constant;
+
+    AudioConverterSetProperty(at->converter, kAudioCodecPropertyBitRateControlMode,
+                              sizeof(at->mode), &at->mode);
+
+    if (at->mode == kAudioCodecBitRateControlMode_Variable) {
+        int q = avctx->global_quality / FF_QP2LAMBDA;
+        if (q < 0 || q > 14) {
+            av_log(avctx, AV_LOG_WARNING,
+                   "VBR quality %d out of range, should be 0-14\n", q);
+            q = av_clip(q, 0, 14);
+        }
+        q = 127 - q * 9;
+        AudioConverterSetProperty(at->converter, kAudioCodecPropertySoundQualityForVBR,
+                                  sizeof(q), &q);
+    } else
+#endif
+    if (avctx->bit_rate > 0) {
+        UInt32 rate = avctx->bit_rate;
+        UInt32 size;
+        status = AudioConverterGetPropertyInfo(at->converter,
+                                               kAudioConverterApplicableEncodeBitRates,
+                                               &size, NULL);
+        if (!status && size) {
+            UInt32 new_rate = rate;
+            int count;
+            int i;
+            AudioValueRange *ranges = av_malloc(size);
+            if (!ranges)
+                return AVERROR(ENOMEM);
+            AudioConverterGetProperty(at->converter,
+                                      kAudioConverterApplicableEncodeBitRates,
+                                      &size, ranges);
+            count = size / sizeof(AudioValueRange);
+            for (i = 0; i < count; i++) {
+                AudioValueRange *range = &ranges[i];
+                if (rate >= range->mMinimum && rate <= range->mMaximum) {
+                    new_rate = rate;
+                    break;
+                } else if (rate > range->mMaximum) {
+                    new_rate = range->mMaximum;
+                } else {
+                    new_rate = range->mMinimum;
+                    break;
+                }
+            }
+            if (new_rate != rate) {
+                av_log(avctx, AV_LOG_WARNING,
+                       "Bitrate %u not allowed; changing to %u\n", rate, new_rate);
+                rate = new_rate;
+            }
+            av_free(ranges);
+        }
+        AudioConverterSetProperty(at->converter, kAudioConverterEncodeBitRate,
+                                  sizeof(rate), &rate);
+    }
+
+    at->quality = 96 - at->quality * 32;
+    AudioConverterSetProperty(at->converter, kAudioConverterCodecQuality,
+                              sizeof(at->quality), &at->quality);
+
+    if (!AudioConverterGetPropertyInfo(at->converter, kAudioConverterCompressionMagicCookie,
+                                       &avctx->extradata_size, NULL) &&
+        avctx->extradata_size) {
+        int extradata_size = avctx->extradata_size;
+        uint8_t *extradata;
+        if (!(avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE)))
+            return AVERROR(ENOMEM);
+        if (avctx->codec_id == AV_CODEC_ID_ALAC) {
+            avctx->extradata_size = 0x24;
+            AV_WB32(avctx->extradata,     0x24);
+            AV_WB32(avctx->extradata + 4, MKBETAG('a','l','a','c'));
+            extradata = avctx->extradata + 12;
+            avctx->extradata_size = 0x24;
+        } else {
+            extradata = avctx->extradata;
+        }
+        status = AudioConverterGetProperty(at->converter,
+                                           kAudioConverterCompressionMagicCookie,
+                                           &extradata_size, extradata);
+        if (status != 0) {
+            av_log(avctx, AV_LOG_ERROR, "AudioToolbox cookie error: %i\n", (int)status);
+            return AVERROR_UNKNOWN;
+        } else if (avctx->codec_id == AV_CODEC_ID_AAC) {
+            GetByteContext gb;
+            int tag, len;
+            bytestream2_init(&gb, extradata, extradata_size);
+            do {
+                len = read_descr(&gb, &tag);
+                if (tag == MP4DecConfigDescrTag) {
+                    bytestream2_skip(&gb, 13);
+                    len = read_descr(&gb, &tag);
+                    if (tag == MP4DecSpecificDescrTag) {
+                        len = FFMIN(gb.buffer_end - gb.buffer, len);
+                        memmove(extradata, gb.buffer, len);
+                        avctx->extradata_size = len;
+                        break;
+                    }
+                } else if (tag == MP4ESDescrTag) {
+                    int flags;
+                    bytestream2_skip(&gb, 2);
+                    flags = bytestream2_get_byte(&gb);
+                    if (flags & 0x80) //streamDependenceFlag
+                        bytestream2_skip(&gb, 2);
+                    if (flags & 0x40) //URL_Flag
+                        bytestream2_skip(&gb, bytestream2_get_byte(&gb));
+                    if (flags & 0x20) //OCRstreamFlag
+                        bytestream2_skip(&gb, 2);
+                }
+            } while (bytestream2_get_bytes_left(&gb));
+        } else if (avctx->codec_id != AV_CODEC_ID_ALAC) {
+            avctx->extradata_size = extradata_size;
+        }
+    }
+
+    ffat_update_ctx(avctx);
+
+#if !TARGET_OS_IPHONE && defined(__MAC_10_9)
+    if (at->mode == kAudioCodecBitRateControlMode_Variable && avctx->rc_max_rate) {
+        UInt32 max_size = avctx->rc_max_rate * avctx->frame_size / avctx->sample_rate;
+        if (max_size)
+            AudioConverterSetProperty(at->converter, kAudioCodecPropertyPacketSizeLimitForVBR,
+                                      sizeof(max_size), &max_size);
+    }
+#endif
+
+    ff_af_queue_init(avctx, &at->afq);
+
+    return 0;
+}
+
+static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_packets,
+                                     AudioBufferList *data,
+                                     AudioStreamPacketDescription **packets,
+                                     void *inctx)
+{
+    AVCodecContext *avctx = inctx;
+    ATDecodeContext *at = avctx->priv_data;
+    AVFrame *frame;
+
+    if (!at->frame_queue.available) {
+        if (at->eof) {
+            *nb_packets = 0;
+            return 0;
+        } else {
+            *nb_packets = 0;
+            return 1;
+        }
+    }
+
+    frame = ff_bufqueue_get(&at->frame_queue);
+
+    data->mNumberBuffers              = 1;
+    data->mBuffers[0].mNumberChannels = avctx->channels;
+    data->mBuffers[0].mDataByteSize   = frame->nb_samples *
+                                        av_get_bytes_per_sample(avctx->sample_fmt) *
+                                        avctx->channels;
+    data->mBuffers[0].mData           = frame->data[0];
+    if (*nb_packets > frame->nb_samples)
+        *nb_packets = frame->nb_samples;
+
+    ff_bufqueue_add(avctx, &at->used_frame_queue, frame);
+
+    return 0;
+}
+
+static int ffat_encode(AVCodecContext *avctx, AVPacket *avpkt,
+                       const AVFrame *frame, int *got_packet_ptr)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    OSStatus ret;
+
+    AudioBufferList out_buffers = {
+        .mNumberBuffers = 1,
+        .mBuffers = {
+            {
+                .mNumberChannels = avctx->channels,
+                .mDataByteSize = at->pkt_size,
+            }
+        }
+    };
+    AudioStreamPacketDescription out_pkt_desc = {0};
+
+    if (frame) {
+        AVFrame *in_frame;
+
+        if (ff_bufqueue_is_full(&at->frame_queue)) {
+            /*
+             * The frame queue is significantly larger than needed in practice,
+             * but no clear way to determine the minimum number of samples to
+             * get output from AudioConverterFillComplexBuffer().
+             */
+            av_log(avctx, AV_LOG_ERROR, "Bug: frame queue is too small.\n");
+            return AVERROR_BUG;
+        }
+
+        if ((ret = ff_af_queue_add(&at->afq, frame)) < 0)
+            return ret;
+
+        in_frame = av_frame_clone(frame);
+        if (!in_frame)
+            return AVERROR(ENOMEM);
+
+        ff_bufqueue_add(avctx, &at->frame_queue, in_frame);
+    } else {
+        at->eof = 1;
+    }
+
+    if ((ret = ff_alloc_packet2(avctx, avpkt, at->pkt_size, 0)) < 0)
+        return ret;
+
+
+    out_buffers.mBuffers[0].mData = avpkt->data;
+
+    *got_packet_ptr = avctx->frame_size / at->frame_size;
+
+    ret = AudioConverterFillComplexBuffer(at->converter, ffat_encode_callback, avctx,
+                                          got_packet_ptr, &out_buffers,
+                                          (avctx->frame_size > at->frame_size) ? NULL : &out_pkt_desc);
+
+    ff_bufqueue_discard_all(&at->used_frame_queue);
+
+    if ((!ret || ret == 1) && *got_packet_ptr) {
+        avpkt->size = out_buffers.mBuffers[0].mDataByteSize;
+        ff_af_queue_remove(&at->afq, out_pkt_desc.mVariableFramesInPacket ?
+                                     out_pkt_desc.mVariableFramesInPacket :
+                                     avctx->frame_size,
+                           &avpkt->pts,
+                           &avpkt->duration);
+    } else if (ret && ret != 1) {
+        av_log(avctx, AV_LOG_WARNING, "Encode error: %i\n", ret);
+    }
+
+    return 0;
+}
+
+static av_cold void ffat_encode_flush(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    AudioConverterReset(at->converter);
+    ff_bufqueue_discard_all(&at->frame_queue);
+    ff_bufqueue_discard_all(&at->used_frame_queue);
+}
+
+static av_cold int ffat_close_encoder(AVCodecContext *avctx)
+{
+    ATDecodeContext *at = avctx->priv_data;
+    AudioConverterDispose(at->converter);
+    ff_bufqueue_discard_all(&at->frame_queue);
+    ff_bufqueue_discard_all(&at->used_frame_queue);
+    ff_af_queue_close(&at->afq);
+    return 0;
+}
+
+static const AVProfile aac_profiles[] = {
+    { FF_PROFILE_AAC_LOW,   "LC"       },
+    { FF_PROFILE_AAC_HE,    "HE-AAC"   },
+    { FF_PROFILE_AAC_HE_V2, "HE-AACv2" },
+    { FF_PROFILE_AAC_LD,    "LD"       },
+    { FF_PROFILE_AAC_ELD,   "ELD"      },
+    { FF_PROFILE_UNKNOWN },
+};
+
+#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+#if !TARGET_OS_IPHONE
+    {"aac_at_mode", "ratecontrol mode", offsetof(ATDecodeContext, mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, kAudioCodecBitRateControlMode_Variable, AE, "mode"},
+        {"auto", "VBR if global quality is given; CBR otherwise", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, INT_MIN, INT_MAX, AE, "mode"},
+        {"cbr",  "constant bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Constant}, INT_MIN, INT_MAX, AE, "mode"},
+        {"abr",  "long-term average bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_LongTermAverage}, INT_MIN, INT_MAX, AE, "mode"},
+        {"cvbr", "constrained variable bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_VariableConstrained}, INT_MIN, INT_MAX, AE, "mode"},
+        {"vbr" , "variable bitrate", 0, AV_OPT_TYPE_CONST, {.i64 = kAudioCodecBitRateControlMode_Variable}, INT_MIN, INT_MAX, AE, "mode"},
+#endif
+    {"aac_at_quality", "quality vs speed control", offsetof(ATDecodeContext, quality), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 2, AE},
+    { NULL },
+};
+
+#define FFAT_ENC_CLASS(NAME) \
+    static const AVClass ffat_##NAME##_enc_class = { \
+        .class_name = "at_" #NAME "_enc", \
+        .item_name  = av_default_item_name, \
+        .option     = options, \
+        .version    = LIBAVUTIL_VERSION_INT, \
+    };
+
+#define FFAT_ENC(NAME, ID, PROFILES, ...) \
+    FFAT_ENC_CLASS(NAME) \
+    AVCodec ff_##NAME##_at_encoder = { \
+        .name           = #NAME "_at", \
+        .long_name      = NULL_IF_CONFIG_SMALL(#NAME " (AudioToolbox)"), \
+        .type           = AVMEDIA_TYPE_AUDIO, \
+        .id             = ID, \
+        .priv_data_size = sizeof(ATDecodeContext), \
+        .init           = ffat_init_encoder, \
+        .close          = ffat_close_encoder, \
+        .encode2        = ffat_encode, \
+        .flush          = ffat_encode_flush, \
+        .priv_class     = &ffat_##NAME##_enc_class, \
+        .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY __VA_ARGS__, \
+        .sample_fmts    = (const enum AVSampleFormat[]) { \
+            AV_SAMPLE_FMT_S16, \
+            AV_SAMPLE_FMT_U8,  AV_SAMPLE_FMT_NONE \
+        }, \
+        .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE, \
+        .profiles       = PROFILES, \
+    };
+
+static const uint64_t aac_at_channel_layouts[] = {
+    AV_CH_LAYOUT_MONO,
+    AV_CH_LAYOUT_STEREO,
+    AV_CH_LAYOUT_SURROUND,
+    AV_CH_LAYOUT_4POINT0,
+    AV_CH_LAYOUT_5POINT0,
+    AV_CH_LAYOUT_5POINT1,
+    AV_CH_LAYOUT_6POINT0,
+    AV_CH_LAYOUT_6POINT1,
+    AV_CH_LAYOUT_7POINT0,
+    AV_CH_LAYOUT_7POINT1_WIDE_BACK,
+    AV_CH_LAYOUT_QUAD,
+    AV_CH_LAYOUT_OCTAGONAL,
+    0,
+};
+
+FFAT_ENC(aac,          AV_CODEC_ID_AAC,          aac_profiles, , .channel_layouts = aac_at_channel_layouts)
+//FFAT_ENC(adpcm_ima_qt, AV_CODEC_ID_ADPCM_IMA_QT, NULL)
+FFAT_ENC(alac,         AV_CODEC_ID_ALAC,         NULL, | AV_CODEC_CAP_VARIABLE_FRAME_SIZE | AV_CODEC_CAP_LOSSLESS)
+FFAT_ENC(ilbc,         AV_CODEC_ID_ILBC,         NULL)
+FFAT_ENC(pcm_alaw,     AV_CODEC_ID_PCM_ALAW,     NULL)
+FFAT_ENC(pcm_mulaw,    AV_CODEC_ID_PCM_MULAW,    NULL)
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index d849765..39713ed 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -70,7 +70,95 @@
  * @{
  * @}
  * @}
+ */
+
+/**
+ * @ingroup libavc
+ * @defgroup lavc_encdec send/receive encoding and decoding API overview
+ * @{
  *
+ * The avcodec_send_packet()/avcodec_receive_frame()/avcodec_send_frame()/
+ * avcodec_receive_packet() functions provide an encode/decode API, which
+ * decouples input and output.
+ *
+ * The API is very similar for encoding/decoding and audio/video, and works as
+ * follows:
+ * - Set up and open the AVCodecContext as usual.
+ * - Send valid input:
+ *   - For decoding, call avcodec_send_packet() to give the decoder raw
+ *     compressed data in an AVPacket.
+ *   - For encoding, call avcodec_send_frame() to give the decoder an AVFrame
+ *     containing uncompressed audio or video.
+ *   In both cases, it is recommended that AVPackets and AVFrames are
+ *   refcounted, or libavcodec might have to copy the input data. (libavformat
+ *   always returns refcounted AVPackets, and av_frame_get_buffer() allocates
+ *   refcounted AVFrames.)
+ * - Receive output in a loop. Periodically call one of the avcodec_receive_*()
+ *   functions and process their output:
+ *   - For decoding, call avcodec_receive_frame(). On success, it will return
+ *     an AVFrame containing uncompressed audio or video data.
+ *   - For encoding, call avcodec_receive_packet(). On success, it will return
+ *     an AVPacket with a compressed frame.
+ *   Repeat this call until it returns AVERROR(EAGAIN) or an error. The
+ *   AVERROR(EAGAIN) return value means that new input data is required to
+ *   return new output. In this case, continue with sending input. For each
+ *   input frame/packet, the codec will typically return 1 output frame/packet,
+ *   but it can also be 0 or more than 1.
+ *
+ * At the beginning of decoding or encoding, the codec might accept multiple
+ * input frames/packets without returning a frame, until its internal buffers
+ * are filled. This situation is handled transparently if you follow the steps
+ * outlined above.
+ *
+ * End of stream situations. These require "flushing" (aka draining) the codec,
+ * as the codec might buffer multiple frames or packets internally for
+ * performance or out of necessity (consider B-frames).
+ * This is handled as follows:
+ * - Instead of valid input, send NULL to the avcodec_send_packet() (decoding)
+ *   or avcodec_send_frame() (encoding) functions. This will enter draining
+ *   mode.
+ * - Call avcodec_receive_frame() (decoding) or avcodec_receive_packet()
+ *   (encoding) in a loop until AVERROR_EOF is returned. The functions will
+ *   not return AVERROR(EAGAIN), unless you forgot to enter draining mode.
+ * - Before decoding can be resumed again, the codec has to be reset with
+ *   avcodec_flush_buffers().
+ *
+ * Using the API as outlined above is highly recommended. But it is also
+ * possible to call functions outside of this rigid schema. For example, you can
+ * call avcodec_send_packet() repeatedly without calling
+ * avcodec_receive_frame(). In this case, avcodec_send_packet() will succeed
+ * until the codec's internal buffer has been filled up (which is typically of
+ * size 1 per output frame, after initial input), and then reject input with
+ * AVERROR(EAGAIN). Once it starts rejecting input, you have no choice but to
+ * read at least some output.
+ *
+ * Not all codecs will follow a rigid and predictable dataflow; the only
+ * guarantee is that an AVERROR(EAGAIN) return value on a send/receive call on
+ * one end implies that a receive/send call on the other end will succeed. In
+ * general, no codec will permit unlimited buffering of input or output.
+ *
+ * This API replaces the following legacy functions:
+ * - avcodec_decode_video2() and avcodec_decode_audio4():
+ *   Use avcodec_send_packet() to feed input to the decoder, then use
+ *   avcodec_receive_frame() to receive decoded frames after each packet.
+ *   Unlike with the old video decoding API, multiple frames might result from
+ *   a packet. For audio, splitting the input packet into frames by partially
+ *   decoding packets becomes transparent to the API user. You never need to
+ *   feed an AVPacket to the API twice.
+ *   Additionally, sending a flush/draining packet is required only once.
+ * - avcodec_encode_video2()/avcodec_encode_audio2():
+ *   Use avcodec_send_frame() to feed input to the encoder, then use
+ *   avcodec_receive_packet() to receive encoded packets.
+ *   Providing user-allocated buffers for avcodec_receive_packet() is not
+ *   possible.
+ * - The new API does not handle subtitles yet.
+ *
+ * Mixing new and old function calls on the same AVCodecContext is not allowed,
+ * and will result in undefined behavior.
+ *
+ * Some codecs might require using the new API; using the old API will return
+ * an error when calling it.
+ * @}
  */
 
 /**
@@ -92,7 +180,7 @@
  * details.
  *
  * If you add a codec ID to this list, add it so that
- * 1. no value of a existing codec ID changes (that would break ABI),
+ * 1. no value of an existing codec ID changes (that would break ABI),
  * 2. it is as close as possible to similar codecs
  *
  * After adding new codec IDs, do not forget to add an entry to the codec
@@ -316,6 +404,11 @@ enum AVCodecID {
     AV_CODEC_ID_APNG,
     AV_CODEC_ID_DAALA,
     AV_CODEC_ID_CFHD,
+    AV_CODEC_ID_TRUEMOTION2RT,
+    AV_CODEC_ID_M101,
+    AV_CODEC_ID_MAGICYUV,
+    AV_CODEC_ID_SHEERVIDEO,
+    AV_CODEC_ID_YLC,
 
     /* various PCM "codecs" */
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
@@ -398,6 +491,8 @@ enum AVCodecID {
     AV_CODEC_ID_ADPCM_THP_LE,
     AV_CODEC_ID_ADPCM_PSX,
     AV_CODEC_ID_ADPCM_AICA,
+    AV_CODEC_ID_ADPCM_IMA_DAT4,
+    AV_CODEC_ID_ADPCM_MTAF,
 
     /* AMR */
     AV_CODEC_ID_AMR_NB = 0x12000,
@@ -500,6 +595,7 @@ enum AVCodecID {
     AV_CODEC_ID_INTERPLAY_ACM,
     AV_CODEC_ID_XMA1,
     AV_CODEC_ID_XMA2,
+    AV_CODEC_ID_DST,
 
     /* subtitle codecs */
     AV_CODEC_ID_FIRST_SUBTITLE = 0x17000,          ///< A dummy ID pointing at the start of subtitle codecs.
@@ -785,7 +881,7 @@ typedef struct RcOverride{
  * Use only bitexact stuff (except (I)DCT).
  */
 #define AV_CODEC_FLAG_BITEXACT        (1 << 23)
-/* Fx : Flag for h263+ extra options */
+/* Fx : Flag for H.263+ extra options */
 /**
  * H.263 advanced intra coding / MPEG-4 AC prediction
  */
@@ -836,6 +932,10 @@ typedef struct RcOverride{
  * Do not skip samples and export skip information as frame side data
  */
 #define AV_CODEC_FLAG2_SKIP_MANUAL    (1 << 29)
+/**
+ * Do not reset ASS ReadOrder field on flush (subtitles decoding)
+ */
+#define AV_CODEC_FLAG2_RO_FLUSH_NOOP  (1 << 30)
 
 /* Unsupported options :
  *              Syntax Arithmetic coding (SAC)
@@ -898,7 +998,7 @@ typedef struct RcOverride{
  * are connected to a parser to split what they return into proper frames.
  * This flag is reserved to the very rare category of codecs which have a
  * bitstream that cannot be split into frames without timeconsuming
- * operations like full decoding. Demuxers carring such bitstreams thus
+ * operations like full decoding. Demuxers carrying such bitstreams thus
  * may return multiple frames in a packet. This has many disadvantages like
  * prohibiting stream copy in many cases thus it should only be considered
  * as a last resort.
@@ -1078,7 +1178,7 @@ typedef struct RcOverride{
  * are connected to a parser to split what they return into proper frames.
  * This flag is reserved to the very rare category of codecs which have a
  * bitstream that cannot be split into frames without timeconsuming
- * operations like full decoding. Demuxers carring such bitstreams thus
+ * operations like full decoding. Demuxers carrying such bitstreams thus
  * may return multiple frames in a packet. This has many disadvantages like
  * prohibiting stream copy in many cases thus it should only be considered
  * as a last resort.
@@ -1158,7 +1258,7 @@ typedef struct RcOverride{
 #define MB_TYPE_L0L1       (MB_TYPE_L0   | MB_TYPE_L1)
 #define MB_TYPE_QUANT      0x00010000
 #define MB_TYPE_CBP        0x00020000
-//Note bits 24-31 are reserved for codec specific use (h264 ref0, mpeg1 0mv, ...)
+// Note bits 24-31 are reserved for codec specific use (H.264 ref0, MPEG-1 0mv, ...)
 #endif
 
 /**
@@ -1403,6 +1503,19 @@ enum AVPacketSideDataType {
      * side data includes updated metadata which appeared in the stream.
      */
     AV_PKT_DATA_METADATA_UPDATE,
+
+    /**
+     * MPEGTS stream ID, this is required to pass the stream ID
+     * information from the demuxer to the corresponding muxer.
+     */
+    AV_PKT_DATA_MPEGTS_STREAM_ID,
+
+    /**
+     * Mastering display metadata (based on SMPTE-2086:2014). This metadata
+     * should be associated with a video stream and containts data in the form
+     * of the AVMasteringDisplayMetadata struct.
+     */
+    AV_PKT_DATA_MASTERING_DISPLAY_METADATA
 };
 
 #define AV_PKT_DATA_QUALITY_FACTOR AV_PKT_DATA_QUALITY_STATS //DEPRECATED
@@ -1527,6 +1640,10 @@ enum AVFieldOrder {
  * version bump.
  * Please use AVOptions (av_opt* / av_set/get*()) to access these fields from user
  * applications.
+ * The name string for AVOptions options matches the associated command line
+ * parameter name and can be found in libavcodec/options_table.h
+ * The AVOption/command line parameter names differ in some cases from the C
+ * structure field names for historic reasons or brevity.
  * sizeof(AVCodecContext) must not be used outside libav*.
  */
 typedef struct AVCodecContext {
@@ -1635,9 +1752,9 @@ typedef struct AVCodecContext {
 
     /**
      * some codecs need / can use extradata like Huffman tables.
-     * mjpeg: Huffman tables
+     * MJPEG: Huffman tables
      * rv10: additional flags
-     * mpeg4: global headers (they can be in the bitstream or here)
+     * MPEG-4: global headers (they can be in the bitstream or here)
      * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger
      * than extradata_size to avoid problems if it is read with the bitstream reader.
      * The bytewise contents of extradata must not depend on the architecture or CPU endianness.
@@ -1653,7 +1770,15 @@ typedef struct AVCodecContext {
      * timebase should be 1/framerate and timestamp increments should be
      * identically 1.
      * This often, but not always is the inverse of the frame rate or field rate
-     * for video.
+     * for video. 1/time_base is not the average frame rate if the frame rate is not
+     * constant.
+     *
+     * Like containers, elementary streams also can store timestamps, 1/time_base
+     * is the unit in which these timestamps are specified.
+     * As example of such codec time base see ISO/IEC 14496-2:2001(E)
+     * vop_time_increment_resolution and fixed_vop_rate
+     * (fixed_vop_rate == 0 implies that it is different from the framerate)
+     *
      * - encoding: MUST be set by user.
      * - decoding: the use of this field for decoding is deprecated.
      *             Use framerate instead.
@@ -1699,7 +1824,7 @@ typedef struct AVCodecContext {
      * picture width / height.
      *
      * @note Those fields may not match the values of the last
-     * AVFrame outputted by avcodec_decode_video2 due frame
+     * AVFrame output by avcodec_decode_video2 due frame
      * reordering.
      *
      * - encoding: MUST be set by user.
@@ -1715,7 +1840,7 @@ typedef struct AVCodecContext {
      * the decoded frame is cropped before being output or lowres is enabled.
      *
      * @note Those field may not match the value of the last
-     * AVFrame outputted by avcodec_decode_video2 due frame
+     * AVFrame output by avcodec_receive_frame() due frame
      * reordering.
      *
      * - encoding: unused
@@ -1742,7 +1867,7 @@ typedef struct AVCodecContext {
      * May be overridden by the decoder if it knows better.
      *
      * @note This field may not match the value of the last
-     * AVFrame outputted by avcodec_decode_video2 due frame
+     * AVFrame output by avcodec_receive_frame() due frame
      * reordering.
      *
      * - encoding: Set by user.
@@ -1852,8 +1977,8 @@ typedef struct AVCodecContext {
 #endif
 
     /**
-     * qscale factor between P and I-frames
-     * If > 0 then the last p frame quantizer will be used (q= lastp_q*factor+offset).
+     * qscale factor between P- and I-frames
+     * If > 0 then the last P-frame quantizer will be used (q = lastp_q * factor + offset).
      * If < 0 then normal ratecontrol will be done (q= -normal_q*factor+offset).
      * - encoding: Set by user.
      * - decoding: unused
@@ -2065,7 +2190,7 @@ typedef struct AVCodecContext {
      */
     int slice_flags;
 #define SLICE_FLAG_CODED_ORDER    0x0001 ///< draw_horiz_band() is called in coded order instead of display
-#define SLICE_FLAG_ALLOW_FIELD    0x0002 ///< allow draw_horiz_band() with field slices (MPEG2 field pics)
+#define SLICE_FLAG_ALLOW_FIELD    0x0002 ///< allow draw_horiz_band() with field slices (MPEG-2 field pics)
 #define SLICE_FLAG_ALLOW_PLANE    0x0004 ///< allow draw_horiz_band() with 1 component at a time (SVQ1)
 
 #if FF_API_XVMC
@@ -2156,14 +2281,14 @@ typedef struct AVCodecContext {
 #endif
 
     /**
-     * minimum MB lagrange multipler
+     * minimum MB Lagrange multiplier
      * - encoding: Set by user.
      * - decoding: unused
      */
     int mb_lmin;
 
     /**
-     * maximum MB lagrange multipler
+     * maximum MB Lagrange multiplier
      * - encoding: Set by user.
      * - decoding: unused
      */
@@ -2178,7 +2303,6 @@ typedef struct AVCodecContext {
 #endif
 
     /**
-     *
      * - encoding: Set by user.
      * - decoding: unused
      */
@@ -2220,7 +2344,6 @@ typedef struct AVCodecContext {
 #endif
 
     /**
-     *
      * Note: Value depends upon the compare function used for fullpel ME.
      * - encoding: Set by user.
      * - decoding: unused
@@ -2385,7 +2508,7 @@ typedef struct AVCodecContext {
      *     to all data planes. data[] must hold as many pointers as it can.
      *     extended_data must be allocated with av_malloc() and will be freed in
      *     av_frame_unref().
-     *   * otherwise exended_data must point to data
+     *   * otherwise extended_data must point to data
      * - buf[] must contain one or more pointers to AVBufferRef structures. Each of
      *   the frame's data and extended_data pointers must be contained in these. That
      *   is, one AVBufferRef for each allocated chunk of memory, not necessarily one
@@ -2449,6 +2572,8 @@ typedef struct AVCodecContext {
      * Otherwise, the decoded frames must not be freed by the caller and are
      * only valid until the next decode call.
      *
+     * This is always automatically enabled if avcodec_receive_frame() is used.
+     *
      * - encoding: unused
      * - decoding: set by the caller before avcodec_open2().
      */
@@ -2727,7 +2852,7 @@ typedef struct AVCodecContext {
 #define FF_BUG_TRUNCATED       16384
 
     /**
-     * strictly follow the standard (MPEG4, ...).
+     * strictly follow the standard (MPEG-4, ...).
      * - encoding: Set by user.
      * - decoding: Set by user.
      * Setting this to STRICT or higher means the encoder and decoder will
@@ -2798,9 +2923,9 @@ typedef struct AVCodecContext {
      * - decoding: Set by user.
      */
     int debug_mv;
-#define FF_DEBUG_VIS_MV_P_FOR  0x00000001 //visualize forward predicted MVs of P frames
-#define FF_DEBUG_VIS_MV_B_FOR  0x00000002 //visualize forward predicted MVs of B frames
-#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 //visualize backward predicted MVs of B frames
+#define FF_DEBUG_VIS_MV_P_FOR  0x00000001 // visualize forward predicted MVs of P-frames
+#define FF_DEBUG_VIS_MV_B_FOR  0x00000002 // visualize forward predicted MVs of B-frames
+#define FF_DEBUG_VIS_MV_B_BACK 0x00000004 // visualize backward predicted MVs of B-frames
 #endif
 
     /**
@@ -2828,7 +2953,7 @@ typedef struct AVCodecContext {
 
 
     /**
-     * opaque 64bit number (generally a PTS) that will be reordered and
+     * opaque 64-bit number (generally a PTS) that will be reordered and
      * output in AVFrame.reordered_opaque
      * - encoding: unused
      * - decoding: Set by user.
@@ -3093,9 +3218,9 @@ typedef struct AVCodecContext {
 #define FF_PROFILE_MPEG4_SIMPLE_STUDIO             14
 #define FF_PROFILE_MPEG4_ADVANCED_SIMPLE           15
 
-#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0   0
-#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1   1
-#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION  2
+#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_0   1
+#define FF_PROFILE_JPEG2000_CSTREAM_RESTRICTION_1   2
+#define FF_PROFILE_JPEG2000_CSTREAM_NO_RESTRICTION  32768
 #define FF_PROFILE_JPEG2000_DCINEMA_2K              3
 #define FF_PROFILE_JPEG2000_DCINEMA_4K              4
 
@@ -3207,7 +3332,8 @@ typedef struct AVCodecContext {
      * - decoding: For codecs that store a framerate value in the compressed
      *             bitstream, the decoder may export it here. { 0, 1} when
      *             unknown.
-     * - encoding: unused
+     * - encoding: May be used to signal the framerate of CFR content to an
+     *             encoder.
      */
     AVRational framerate;
 
@@ -3355,6 +3481,30 @@ typedef struct AVCodecContext {
     AVPacketSideData *coded_side_data;
     int            nb_coded_side_data;
 
+    /**
+     * Encoding only.
+     *
+     * For hardware encoders configured to use a hwaccel pixel format, this
+     * field should be set by the caller to a reference to the AVHWFramesContext
+     * describing input frames. AVHWFramesContext.format must be equal to
+     * AVCodecContext.pix_fmt.
+     *
+     * This field should be set before avcodec_open2() is called and is
+     * afterwards owned and managed by libavcodec.
+     */
+    AVBufferRef *hw_frames_ctx;
+
+    /**
+     * Control the form of AVSubtitle.rects[N]->ass
+     * - decoding: set by user
+     * - encoding: unused
+     */
+    int sub_text_format;
+#define FF_SUB_TEXT_FMT_ASS              0
+#if FF_API_ASS_TIMING
+#define FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS 1
+#endif
+
 } AVCodecContext;
 
 AVRational av_codec_get_pkt_timebase         (const AVCodecContext *avctx);
@@ -3475,6 +3625,21 @@ typedef struct AVCodec {
     int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt);
     int (*close)(AVCodecContext *);
     /**
+     * Decode/encode API with decoupled packet/frame dataflow. The API is the
+     * same as the avcodec_ prefixed APIs (avcodec_send_frame() etc.), except
+     * that:
+     * - never called if the codec is closed or the wrong type,
+     * - AVPacket parameter change side data is applied right before calling
+     *   AVCodec->send_packet,
+     * - if AV_CODEC_CAP_DELAY is not set, drain packets or frames are never sent,
+     * - only one drain packet is ever passed down (until the next flush()),
+     * - a drain AVPacket is always NULL (no need to check for avpkt->size).
+     */
+    int (*send_frame)(AVCodecContext *avctx, const AVFrame *frame);
+    int (*send_packet)(AVCodecContext *avctx, const AVPacket *avpkt);
+    int (*receive_frame)(AVCodecContext *avctx, AVFrame *frame);
+    int (*receive_packet)(AVCodecContext *avctx, AVPacket *avpkt);
+    /**
      * Flush buffers.
      * Will be called when seeking
      */
@@ -3740,6 +3905,164 @@ typedef struct AVSubtitle {
 } AVSubtitle;
 
 /**
+ * This struct describes the properties of an encoded stream.
+ *
+ * sizeof(AVCodecParameters) is not a part of the public ABI, this struct must
+ * be allocated with avcodec_parameters_alloc() and freed with
+ * avcodec_parameters_free().
+ */
+typedef struct AVCodecParameters {
+    /**
+     * General type of the encoded data.
+     */
+    enum AVMediaType codec_type;
+    /**
+     * Specific type of the encoded data (the codec used).
+     */
+    enum AVCodecID   codec_id;
+    /**
+     * Additional information about the codec (corresponds to the AVI FOURCC).
+     */
+    uint32_t         codec_tag;
+
+    /**
+     * Extra binary data needed for initializing the decoder, codec-dependent.
+     *
+     * Must be allocated with av_malloc() and will be freed by
+     * avcodec_parameters_free(). The allocated size of extradata must be at
+     * least extradata_size + AV_INPUT_BUFFER_PADDING_SIZE, with the padding
+     * bytes zeroed.
+     */
+    uint8_t *extradata;
+    /**
+     * Size of the extradata content in bytes.
+     */
+    int      extradata_size;
+
+    /**
+     * - video: the pixel format, the value corresponds to enum AVPixelFormat.
+     * - audio: the sample format, the value corresponds to enum AVSampleFormat.
+     */
+    int format;
+
+    /**
+     * The average bitrate of the encoded data (in bits per second).
+     */
+    int64_t bit_rate;
+
+    /**
+     * The number of bits per sample in the codedwords.
+     *
+     * This is basically the bitrate per sample. It is mandatory for a bunch of
+     * formats to actually decode them. It's the number of bits for one sample in
+     * the actual coded bitstream.
+     *
+     * This could be for example 4 for ADPCM
+     * For PCM formats this matches bits_per_raw_sample
+     * Can be 0
+     */
+    int bits_per_coded_sample;
+
+    /**
+     * This is the number of valid bits in each output sample. If the
+     * sample format has more bits, the least significant bits are additional
+     * padding bits, which are always 0. Use right shifts to reduce the sample
+     * to its actual size. For example, audio formats with 24 bit samples will
+     * have bits_per_raw_sample set to 24, and format set to AV_SAMPLE_FMT_S32.
+     * To get the original sample use "(int32_t)sample >> 8"."
+     *
+     * For ADPCM this might be 12 or 16 or similar
+     * Can be 0
+     */
+    int bits_per_raw_sample;
+
+    /**
+     * Codec-specific bitstream restrictions that the stream conforms to.
+     */
+    int profile;
+    int level;
+
+    /**
+     * Video only. The dimensions of the video frame in pixels.
+     */
+    int width;
+    int height;
+
+    /**
+     * Video only. The aspect ratio (width / height) which a single pixel
+     * should have when displayed.
+     *
+     * When the aspect ratio is unknown / undefined, the numerator should be
+     * set to 0 (the denominator may have any value).
+     */
+    AVRational sample_aspect_ratio;
+
+    /**
+     * Video only. The order of the fields in interlaced video.
+     */
+    enum AVFieldOrder                  field_order;
+
+    /**
+     * Video only. Additional colorspace characteristics.
+     */
+    enum AVColorRange                  color_range;
+    enum AVColorPrimaries              color_primaries;
+    enum AVColorTransferCharacteristic color_trc;
+    enum AVColorSpace                  color_space;
+    enum AVChromaLocation              chroma_location;
+
+    /**
+     * Video only. Number of delayed frames.
+     */
+    int video_delay;
+
+    /**
+     * Audio only. The channel layout bitmask. May be 0 if the channel layout is
+     * unknown or unspecified, otherwise the number of bits set must be equal to
+     * the channels field.
+     */
+    uint64_t channel_layout;
+    /**
+     * Audio only. The number of audio channels.
+     */
+    int      channels;
+    /**
+     * Audio only. The number of audio samples per second.
+     */
+    int      sample_rate;
+    /**
+     * Audio only. The number of bytes per coded audio frame, required by some
+     * formats.
+     *
+     * Corresponds to nBlockAlign in WAVEFORMATEX.
+     */
+    int      block_align;
+    /**
+     * Audio only. Audio frame size, if known. Required by some formats to be static.
+     */
+    int      frame_size;
+
+    /**
+     * Audio only. The amount of padding (in samples) inserted by the encoder at
+     * the beginning of the audio. I.e. this number of leading decoded samples
+     * must be discarded by the caller to get the original audio without leading
+     * padding.
+     */
+    int initial_padding;
+    /**
+     * Audio only. The amount of padding (in samples) appended by the encoder to
+     * the end of the audio. I.e. this number of decoded samples must be
+     * discarded by the caller from the end of the stream to get the original
+     * audio without any trailing padding.
+     */
+    int trailing_padding;
+    /**
+     * Audio only. Number of samples to skip after a discontinuity.
+     */
+    int seek_preroll;
+} AVCodecParameters;
+
+/**
  * If c is NULL, returns the first registered codec,
  * if c is non-NULL, returns the next registered codec after c,
  * or NULL if c is the last one.
@@ -3795,7 +4118,6 @@ void avcodec_register_all(void);
  *              important mainly for encoders, e.g. libx264).
  *
  * @return An AVCodecContext filled with default values or NULL on failure.
- * @see avcodec_get_context_defaults
  */
 AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
 
@@ -3805,16 +4127,14 @@ AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
  */
 void avcodec_free_context(AVCodecContext **avctx);
 
+#if FF_API_GET_CONTEXT_DEFAULTS
 /**
- * Set the fields of the given AVCodecContext to default values corresponding
- * to the given codec (defaults may be codec-dependent).
- *
- * Do not call this function if a non-NULL codec has been passed
- * to avcodec_alloc_context3() that allocated this AVCodecContext.
- * If codec is non-NULL, it is illegal to call avcodec_open2() with a
- * different codec on this AVCodecContext.
+ * @deprecated This function should not be used, as closing and opening a codec
+ * context multiple time is not supported. A new codec context should be
+ * allocated for each new use.
  */
 int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec);
+#endif
 
 /**
  * Get the AVClass for AVCodecContext. It can be used in combination with
@@ -3824,6 +4144,7 @@ int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec);
  */
 const AVClass *avcodec_get_class(void);
 
+#if FF_API_COPY_CONTEXT
 /**
  * Get the AVClass for AVFrame. It can be used in combination with
  * AV_OPT_SEARCH_FAKE_OBJ for examining options.
@@ -3850,8 +4171,58 @@ const AVClass *avcodec_get_subtitle_rect_class(void);
  *             avcodec_alloc_context3(NULL), but otherwise uninitialized
  * @param src source codec context
  * @return AVERROR() on error (e.g. memory allocation error), 0 on success
+ *
+ * @deprecated The semantics of this function are ill-defined and it should not
+ * be used. If you need to transfer the stream parameters from one codec context
+ * to another, use an intermediate AVCodecParameters instance and the
+ * avcodec_parameters_from_context() / avcodec_parameters_to_context()
+ * functions.
  */
+attribute_deprecated
 int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src);
+#endif
+
+/**
+ * Allocate a new AVCodecParameters and set its fields to default values
+ * (unknown/invalid/0). The returned struct must be freed with
+ * avcodec_parameters_free().
+ */
+AVCodecParameters *avcodec_parameters_alloc(void);
+
+/**
+ * Free an AVCodecParameters instance and everything associated with it and
+ * write NULL to the supplied pointer.
+ */
+void avcodec_parameters_free(AVCodecParameters **par);
+
+/**
+ * Copy the contents of src to dst. Any allocated fields in dst are freed and
+ * replaced with newly allocated duplicates of the corresponding fields in src.
+ *
+ * @return >= 0 on success, a negative AVERROR code on failure.
+ */
+int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src);
+
+/**
+ * Fill the parameters struct based on the values from the supplied codec
+ * context. Any allocated fields in par are freed and replaced with duplicates
+ * of the corresponding fields in codec.
+ *
+ * @return >= 0 on success, a negative AVERROR code on failure
+ */
+int avcodec_parameters_from_context(AVCodecParameters *par,
+                                    const AVCodecContext *codec);
+
+/**
+ * Fill the codec context based on the values from the supplied codec
+ * parameters. Any allocated fields in codec that have a corresponding field in
+ * par are freed and replaced with duplicates of the corresponding field in par.
+ * Fields in codec that do not have a counterpart in par are not touched.
+ *
+ * @return >= 0 on success, a negative AVERROR code on failure.
+ */
+int avcodec_parameters_to_context(AVCodecContext *codec,
+                                  const AVCodecParameters *par);
 
 /**
  * Initialize the AVCodecContext to use the given AVCodec. Prior to using this
@@ -3864,7 +4235,7 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src);
  * @warning This function is not thread safe!
  *
  * @note Always call this function before using decoding routines (such as
- * @ref avcodec_decode_video2()).
+ * @ref avcodec_receive_frame()).
  *
  * @code
  * avcodec_register_all();
@@ -3882,9 +4253,8 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src);
  * @param avctx The context to initialize.
  * @param codec The codec to open this context for. If a non-NULL codec has been
  *              previously passed to avcodec_alloc_context3() or
- *              avcodec_get_context_defaults3() for this context, then this
- *              parameter MUST be either NULL or equal to the previously passed
- *              codec.
+ *              for this context, then this parameter MUST be either NULL or
+ *              equal to the previously passed codec.
  * @param options A dictionary filled with AVCodecContext and codec-private options.
  *                On return this object will be filled with options that were not found.
  *
@@ -3899,9 +4269,13 @@ int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **op
  * (but not the AVCodecContext itself).
  *
  * Calling this function on an AVCodecContext that hasn't been opened will free
- * the codec-specific data allocated in avcodec_alloc_context3() /
- * avcodec_get_context_defaults3() with a non-NULL codec. Subsequent calls will
- * do nothing.
+ * the codec-specific data allocated in avcodec_alloc_context3() with a non-NULL
+ * codec. Subsequent calls will do nothing.
+ *
+ * @note Do not use this function. Use avcodec_free_context() to destroy a
+ * codec context (either open or closed). Opening and closing a codec context
+ * multiple times is not supported anymore -- use multiple codec contexts
+ * instead.
  */
 int avcodec_close(AVCodecContext *avctx);
 
@@ -4169,7 +4543,6 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src);
  * @param src Source packet
  *
  * @return 0 on success AVERROR on failure.
- *
  */
 int av_packet_copy_props(AVPacket *dst, const AVPacket *src);
 
@@ -4324,7 +4697,10 @@ enum AVChromaLocation avcodec_chroma_pos_to_enum(int xpos, int ypos);
  * @return A negative error code is returned if an error occurred during
  *         decoding, otherwise the number of bytes consumed from the input
  *         AVPacket is returned.
+ *
+* @deprecated Use avcodec_send_packet() and avcodec_receive_frame().
  */
+attribute_deprecated
 int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame,
                           int *got_frame_ptr, const AVPacket *avpkt);
 
@@ -4370,7 +4746,10 @@ int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame,
  * @param[in,out] got_picture_ptr Zero if no frame could be decompressed, otherwise, it is nonzero.
  * @return On error a negative value is returned, otherwise the number of bytes
  * used or zero if no frame could be decompressed.
+ *
+ * @deprecated Use avcodec_send_packet() and avcodec_receive_frame().
  */
+attribute_deprecated
 int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
                          int *got_picture_ptr,
                          const AVPacket *avpkt);
@@ -4407,6 +4786,129 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
                             AVPacket *avpkt);
 
 /**
+ * Supply raw packet data as input to a decoder.
+ *
+ * Internally, this call will copy relevant AVCodecContext fields, which can
+ * influence decoding per-packet, and apply them when the packet is actually
+ * decoded. (For example AVCodecContext.skip_frame, which might direct the
+ * decoder to drop the frame contained by the packet sent with this function.)
+ *
+ * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE
+ *          larger than the actual read bytes because some optimized bitstream
+ *          readers read 32 or 64 bits at once and could read over the end.
+ *
+ * @warning Do not mix this API with the legacy API (like avcodec_decode_video2())
+ *          on the same AVCodecContext. It will return unexpected results now
+ *          or in future libavcodec versions.
+ *
+ * @note The AVCodecContext MUST have been opened with @ref avcodec_open2()
+ *       before packets may be fed to the decoder.
+ *
+ * @param avctx codec context
+ * @param[in] avpkt The input AVPacket. Usually, this will be a single video
+ *                  frame, or several complete audio frames.
+ *                  Ownership of the packet remains with the caller, and the
+ *                  decoder will not write to the packet. The decoder may create
+ *                  a reference to the packet data (or copy it if the packet is
+ *                  not reference-counted).
+ *                  Unlike with older APIs, the packet is always fully consumed,
+ *                  and if it contains multiple frames (e.g. some audio codecs),
+ *                  will require you to call avcodec_receive_frame() multiple
+ *                  times afterwards before you can send a new packet.
+ *                  It can be NULL (or an AVPacket with data set to NULL and
+ *                  size set to 0); in this case, it is considered a flush
+ *                  packet, which signals the end of the stream. Sending the
+ *                  first flush packet will return success. Subsequent ones are
+ *                  unnecessary and will return AVERROR_EOF. If the decoder
+ *                  still has frames buffered, it will return them after sending
+ *                  a flush packet.
+ *
+ * @return 0 on success, otherwise negative error code:
+ *      AVERROR(EAGAIN):   input is not accepted right now - the packet must be
+ *                         resent after trying to read output
+ *      AVERROR_EOF:       the decoder has been flushed, and no new packets can
+ *                         be sent to it (also returned if more than 1 flush
+ *                         packet is sent)
+ *      AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
+ *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
+ *      other errors: legitimate decoding errors
+ */
+int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
+
+/**
+ * Return decoded output data from a decoder.
+ *
+ * @param avctx codec context
+ * @param frame This will be set to a reference-counted video or audio
+ *              frame (depending on the decoder type) allocated by the
+ *              decoder. Note that the function will always call
+ *              av_frame_unref(frame) before doing anything else.
+ *
+ * @return
+ *      0:                 success, a frame was returned
+ *      AVERROR(EAGAIN):   output is not available right now - user must try
+ *                         to send new input
+ *      AVERROR_EOF:       the decoder has been fully flushed, and there will be
+ *                         no more output frames
+ *      AVERROR(EINVAL):   codec not opened, or it is an encoder
+ *      other negative values: legitimate decoding errors
+ */
+int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
+
+/**
+ * Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet()
+ * to retrieve buffered output packets.
+ *
+ * @param avctx     codec context
+ * @param[in] frame AVFrame containing the raw audio or video frame to be encoded.
+ *                  Ownership of the frame remains with the caller, and the
+ *                  encoder will not write to the frame. The encoder may create
+ *                  a reference to the frame data (or copy it if the frame is
+ *                  not reference-counted).
+ *                  It can be NULL, in which case it is considered a flush
+ *                  packet.  This signals the end of the stream. If the encoder
+ *                  still has packets buffered, it will return them after this
+ *                  call. Once flushing mode has been entered, additional flush
+ *                  packets are ignored, and sending frames will return
+ *                  AVERROR_EOF.
+ *
+ *                  For audio:
+ *                  If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame
+ *                  can have any number of samples.
+ *                  If it is not set, frame->nb_samples must be equal to
+ *                  avctx->frame_size for all frames except the last.
+ *                  The final frame may be smaller than avctx->frame_size.
+ * @return 0 on success, otherwise negative error code:
+ *      AVERROR(EAGAIN):   input is not accepted right now - the frame must be
+ *                         resent after trying to read output packets
+ *      AVERROR_EOF:       the encoder has been flushed, and no new frames can
+ *                         be sent to it
+ *      AVERROR(EINVAL):   codec not opened, refcounted_frames not set, it is a
+ *                         decoder, or requires flush
+ *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
+ *      other errors: legitimate decoding errors
+ */
+int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
+
+/**
+ * Read encoded data from the encoder.
+ *
+ * @param avctx codec context
+ * @param avpkt This will be set to a reference-counted packet allocated by the
+ *              encoder. Note that the function will always call
+ *              av_frame_unref(frame) before doing anything else.
+ * @return 0 on success, otherwise negative error code:
+ *      AVERROR(EAGAIN):   output is not available right now - user must try
+ *                         to send input
+ *      AVERROR_EOF:       the encoder has been fully flushed, and there will be
+ *                         no more output packets
+ *      AVERROR(EINVAL):   codec not opened, or it is an encoder
+ *      other errors: legitimate decoding errors
+ */
+int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
+
+
+/**
  * @defgroup lavc_parsing Frame parsing
  * @{
  */
@@ -4713,7 +5215,10 @@ AVCodec *avcodec_find_encoder_by_name(const char *name);
  *                            value of got_packet_ptr is undefined and should
  *                            not be used.
  * @return          0 on success, negative error code on failure
+ *
+ * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead
  */
+attribute_deprecated
 int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt,
                           const AVFrame *frame, int *got_packet_ptr);
 
@@ -4749,7 +5254,10 @@ int avcodec_encode_audio2(AVCodecContext *avctx, AVPacket *avpkt,
  *                            value of got_packet_ptr is undefined and should
  *                            not be used.
  * @return          0 on success, negative error code on failure
+ *
+ * @deprecated use avcodec_send_frame()/avcodec_receive_packet() instead
  */
+attribute_deprecated
 int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt,
                           const AVFrame *frame, int *got_packet_ptr);
 
@@ -5134,7 +5642,13 @@ int av_get_exact_bits_per_sample(enum AVCodecID codec_id);
  */
 int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes);
 
+/**
+ * This function is the same as av_get_audio_frame_duration(), except it works
+ * with AVCodecParameters instead of an AVCodecContext.
+ */
+int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes);
 
+#if FF_API_OLD_BSF
 typedef struct AVBitStreamFilterContext {
     void *priv_data;
     struct AVBitStreamFilter *filter;
@@ -5146,19 +5660,102 @@ typedef struct AVBitStreamFilterContext {
      */
     char *args;
 } AVBitStreamFilterContext;
+#endif
 
+typedef struct AVBSFInternal AVBSFInternal;
+
+/**
+ * The bitstream filter state.
+ *
+ * This struct must be allocated with av_bsf_alloc() and freed with
+ * av_bsf_free().
+ *
+ * The fields in the struct will only be changed (by the caller or by the
+ * filter) as described in their documentation, and are to be considered
+ * immutable otherwise.
+ */
+typedef struct AVBSFContext {
+    /**
+     * A class for logging and AVOptions
+     */
+    const AVClass *av_class;
+
+    /**
+     * The bitstream filter this context is an instance of.
+     */
+    const struct AVBitStreamFilter *filter;
+
+    /**
+     * Opaque libavcodec internal data. Must not be touched by the caller in any
+     * way.
+     */
+    AVBSFInternal *internal;
+
+    /**
+     * Opaque filter-specific private data. If filter->priv_class is non-NULL,
+     * this is an AVOptions-enabled struct.
+     */
+    void *priv_data;
+
+    /**
+     * Parameters of the input stream. Set by the caller before av_bsf_init().
+     */
+    AVCodecParameters *par_in;
+
+    /**
+     * Parameters of the output stream. Set by the filter in av_bsf_init().
+     */
+    AVCodecParameters *par_out;
+
+    /**
+     * The timebase used for the timestamps of the input packets. Set by the
+     * caller before av_bsf_init().
+     */
+    AVRational time_base_in;
+
+    /**
+     * The timebase used for the timestamps of the output packets. Set by the
+     * filter in av_bsf_init().
+     */
+    AVRational time_base_out;
+} AVBSFContext;
 
 typedef struct AVBitStreamFilter {
     const char *name;
+
+    /**
+     * A list of codec ids supported by the filter, terminated by
+     * AV_CODEC_ID_NONE.
+     * May be NULL, in that case the bitstream filter works with any codec id.
+     */
+    const enum AVCodecID *codec_ids;
+
+    /**
+     * A class for the private data, used to declare bitstream filter private
+     * AVOptions. This field is NULL for bitstream filters that do not declare
+     * any options.
+     *
+     * If this field is non-NULL, the first member of the filter private data
+     * must be a pointer to AVClass, which will be set by libavcodec generic
+     * code to this class.
+     */
+    const AVClass *priv_class;
+
+    /*****************************************************************
+     * No fields below this line are part of the public API. They
+     * may not be used outside of libavcodec and can be changed and
+     * removed at will.
+     * New public fields should be added right above.
+     *****************************************************************
+     */
+
     int priv_data_size;
-    int (*filter)(AVBitStreamFilterContext *bsfc,
-                  AVCodecContext *avctx, const char *args,
-                  uint8_t **poutbuf, int *poutbuf_size,
-                  const uint8_t *buf, int buf_size, int keyframe);
-    void (*close)(AVBitStreamFilterContext *bsfc);
-    struct AVBitStreamFilter *next;
+    int (*init)(AVBSFContext *ctx);
+    int (*filter)(AVBSFContext *ctx, AVPacket *pkt);
+    void (*close)(AVBSFContext *ctx);
 } AVBitStreamFilter;
 
+#if FF_API_OLD_BSF
 /**
  * Register a bitstream filter.
  *
@@ -5168,6 +5765,7 @@ typedef struct AVBitStreamFilter {
  *
  * @see avcodec_register_all()
  */
+attribute_deprecated
 void av_register_bitstream_filter(AVBitStreamFilter *bsf);
 
 /**
@@ -5180,6 +5778,7 @@ void av_register_bitstream_filter(AVBitStreamFilter *bsf);
  * @return a bitstream filter context if a matching filter was found
  * and successfully initialized, NULL otherwise
  */
+attribute_deprecated
 AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
 
 /**
@@ -5208,8 +5807,10 @@ AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
  * If the return value is 0, the output buffer is not allocated and
  * should be considered identical to the input buffer, or in case
  * *poutbuf was set it points to the input buffer (not necessarily to
- * its starting address).
+ * its starting address). A special case is if *poutbuf was set to NULL and
+ * *poutbuf_size was set to 0, which indicates the packet should be dropped.
  */
+attribute_deprecated
 int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
                                AVCodecContext *avctx, const char *args,
                                uint8_t **poutbuf, int *poutbuf_size,
@@ -5221,6 +5822,7 @@ int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
  * @param bsf the bitstream filter context created with
  * av_bitstream_filter_init(), can be NULL
  */
+attribute_deprecated
 void av_bitstream_filter_close(AVBitStreamFilterContext *bsf);
 
 /**
@@ -5231,7 +5833,103 @@ void av_bitstream_filter_close(AVBitStreamFilterContext *bsf);
  * This function can be used to iterate over all registered bitstream
  * filters.
  */
+attribute_deprecated
 AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f);
+#endif
+
+/**
+ * @return a bitstream filter with the specified name or NULL if no such
+ *         bitstream filter exists.
+ */
+const AVBitStreamFilter *av_bsf_get_by_name(const char *name);
+
+/**
+ * Iterate over all registered bitstream filters.
+ *
+ * @param opaque a pointer where libavcodec will store the iteration state. Must
+ *               point to NULL to start the iteration.
+ *
+ * @return the next registered bitstream filter or NULL when the iteration is
+ *         finished
+ */
+const AVBitStreamFilter *av_bsf_next(void **opaque);
+
+/**
+ * Allocate a context for a given bitstream filter. The caller must fill in the
+ * context parameters as described in the documentation and then call
+ * av_bsf_init() before sending any data to the filter.
+ *
+ * @param filter the filter for which to allocate an instance.
+ * @param ctx a pointer into which the pointer to the newly-allocated context
+ *            will be written. It must be freed with av_bsf_free() after the
+ *            filtering is done.
+ *
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **ctx);
+
+/**
+ * Prepare the filter for use, after all the parameters and options have been
+ * set.
+ */
+int av_bsf_init(AVBSFContext *ctx);
+
+/**
+ * Submit a packet for filtering.
+ *
+ * After sending each packet, the filter must be completely drained by calling
+ * av_bsf_receive_packet() repeatedly until it returns AVERROR(EAGAIN) or
+ * AVERROR_EOF.
+ *
+ * @param pkt the packet to filter. The bitstream filter will take ownership of
+ * the packet and reset the contents of pkt. pkt is not touched if an error occurs.
+ * This parameter may be NULL, which signals the end of the stream (i.e. no more
+ * packets will be sent). That will cause the filter to output any packets it
+ * may have buffered internally.
+ *
+ * @return 0 on success, a negative AVERROR on error.
+ */
+int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt);
+
+/**
+ * Retrieve a filtered packet.
+ *
+ * @param[out] pkt this struct will be filled with the contents of the filtered
+ *                 packet. It is owned by the caller and must be freed using
+ *                 av_packet_unref() when it is no longer needed.
+ *                 This parameter should be "clean" (i.e. freshly allocated
+ *                 with av_packet_alloc() or unreffed with av_packet_unref())
+ *                 when this function is called. If this function returns
+ *                 successfully, the contents of pkt will be completely
+ *                 overwritten by the returned data. On failure, pkt is not
+ *                 touched.
+ *
+ * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the
+ * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there
+ * will be no further output from the filter. Another negative AVERROR value if
+ * an error occurs.
+ *
+ * @note one input packet may result in several output packets, so after sending
+ * a packet with av_bsf_send_packet(), this function needs to be called
+ * repeatedly until it stops returning 0. It is also possible for a filter to
+ * output fewer packets than were sent to it, so this function may return
+ * AVERROR(EAGAIN) immediately after a successful av_bsf_send_packet() call.
+ */
+int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt);
+
+/**
+ * Free a bitstream filter context and everything associated with it; write NULL
+ * into the supplied pointer.
+ */
+void av_bsf_free(AVBSFContext **ctx);
+
+/**
+ * Get the AVClass for AVBSFContext. It can be used in combination with
+ * AV_OPT_SEARCH_FAKE_OBJ for examining options.
+ *
+ * @see av_opt_find().
+ */
+const AVClass *av_bsf_get_class(void);
 
 /* memory */
 
@@ -5268,7 +5966,7 @@ unsigned int av_xiphlacing(unsigned char *s, unsigned int v);
  * a pointer to an AVClass struct
  * @param[in] feature string containing the name of the missing feature
  * @param[in] want_sample indicates if samples are wanted which exhibit this feature.
- * If want_sample is non-zero, additional verbage will be added to the log
+ * If want_sample is non-zero, additional verbiage will be added to the log
  * message which tells the user how to report samples to the development
  * mailing list.
  * @deprecated Use avpriv_report_missing_feature() instead.
diff --git a/libavcodec/avfft.c b/libavcodec/avfft.c
index 675d2b9..2200f37 100644
--- a/libavcodec/avfft.c
+++ b/libavcodec/avfft.c
@@ -142,38 +142,4 @@ av_cold void av_dct_end(DCTContext *s)
     }
 }
 
-#ifdef TEST
-int main(int argc, char **argv)
-{
-    int i;
-#define LEN 1024
-    FFTSample *ref  = av_malloc_array(LEN, sizeof(*ref));
-    FFTSample *data = av_malloc_array(LEN, sizeof(*data));
-    RDFTContext *rdft_context  = av_rdft_init(10, DFT_R2C);
-    RDFTContext *irdft_context = av_rdft_init(10, IDFT_C2R);
-
-    if (!ref || !data || !rdft_context || !irdft_context)
-        return 2;
-    for (i=0; i<LEN; i++) {
-        ref[i] = data[i] = i*456 + 123 + i*i;
-    }
-    av_rdft_calc(rdft_context, data);
-    av_rdft_calc(irdft_context, data);
-
-    for (i=0; i<LEN; i++) {
-        if (fabs(ref[i] - data[i]/LEN*2) > 1) {
-            fprintf(stderr, "Failed at %d (%f %f)\n", i, ref[i], data[i]/LEN*2);
-            return 1;
-        }
-    }
-
-    av_rdft_end(rdft_context);
-    av_rdft_end(irdft_context);
-    av_free(data);
-    av_free(ref);
-
-    return 0;
-}
-#endif
-
 #endif /* CONFIG_DCT */
diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index b2079f6..9218689 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -110,24 +110,38 @@ int av_grow_packet(AVPacket *pkt, int grow_by)
 {
     int new_size;
     av_assert0((unsigned)pkt->size <= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!pkt->size)
-        return av_new_packet(pkt, grow_by);
     if ((unsigned)grow_by >
         INT_MAX - (pkt->size + AV_INPUT_BUFFER_PADDING_SIZE))
         return -1;
 
     new_size = pkt->size + grow_by + AV_INPUT_BUFFER_PADDING_SIZE;
     if (pkt->buf) {
-        int ret = av_buffer_realloc(&pkt->buf, new_size);
-        if (ret < 0)
-            return ret;
+        size_t data_offset;
+        uint8_t *old_data = pkt->data;
+        if (pkt->data == NULL) {
+            data_offset = 0;
+            pkt->data = pkt->buf->data;
+        } else {
+            data_offset = pkt->data - pkt->buf->data;
+            if (data_offset > INT_MAX - new_size)
+                return -1;
+        }
+
+        if (new_size + data_offset > pkt->buf->size) {
+            int ret = av_buffer_realloc(&pkt->buf, new_size + data_offset);
+            if (ret < 0) {
+                pkt->data = old_data;
+                return ret;
+            }
+            pkt->data = pkt->buf->data + data_offset;
+        }
     } else {
         pkt->buf = av_buffer_alloc(new_size);
         if (!pkt->buf)
             return AVERROR(ENOMEM);
-        memcpy(pkt->buf->data, pkt->data, FFMIN(pkt->size, pkt->size + grow_by));
+        memcpy(pkt->buf->data, pkt->data, pkt->size);
+        pkt->data = pkt->buf->data;
     }
-    pkt->data  = pkt->buf->data;
     pkt->size += grow_by;
     memset(pkt->data + pkt->size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
 
@@ -335,22 +349,24 @@ uint8_t *av_packet_get_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
 const char *av_packet_side_data_name(enum AVPacketSideDataType type)
 {
     switch(type) {
-    case AV_PKT_DATA_PALETTE:                   return "Palette";
-    case AV_PKT_DATA_NEW_EXTRADATA:             return "New Extradata";
-    case AV_PKT_DATA_PARAM_CHANGE:              return "Param Change";
-    case AV_PKT_DATA_H263_MB_INFO:              return "H263 MB Info";
-    case AV_PKT_DATA_REPLAYGAIN:                return "Replay Gain";
-    case AV_PKT_DATA_DISPLAYMATRIX:             return "Display Matrix";
-    case AV_PKT_DATA_STEREO3D:                  return "Stereo 3D";
-    case AV_PKT_DATA_AUDIO_SERVICE_TYPE:        return "Audio Service Type";
-    case AV_PKT_DATA_SKIP_SAMPLES:              return "Skip Samples";
-    case AV_PKT_DATA_JP_DUALMONO:               return "JP Dual Mono";
-    case AV_PKT_DATA_STRINGS_METADATA:          return "Strings Metadata";
-    case AV_PKT_DATA_SUBTITLE_POSITION:         return "Subtitle Position";
-    case AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL:  return "Matroska BlockAdditional";
-    case AV_PKT_DATA_WEBVTT_IDENTIFIER:         return "WebVTT ID";
-    case AV_PKT_DATA_WEBVTT_SETTINGS:           return "WebVTT Settings";
-    case AV_PKT_DATA_METADATA_UPDATE:           return "Metadata Update";
+    case AV_PKT_DATA_PALETTE:                    return "Palette";
+    case AV_PKT_DATA_NEW_EXTRADATA:              return "New Extradata";
+    case AV_PKT_DATA_PARAM_CHANGE:               return "Param Change";
+    case AV_PKT_DATA_H263_MB_INFO:               return "H263 MB Info";
+    case AV_PKT_DATA_REPLAYGAIN:                 return "Replay Gain";
+    case AV_PKT_DATA_DISPLAYMATRIX:              return "Display Matrix";
+    case AV_PKT_DATA_STEREO3D:                   return "Stereo 3D";
+    case AV_PKT_DATA_AUDIO_SERVICE_TYPE:         return "Audio Service Type";
+    case AV_PKT_DATA_SKIP_SAMPLES:               return "Skip Samples";
+    case AV_PKT_DATA_JP_DUALMONO:                return "JP Dual Mono";
+    case AV_PKT_DATA_STRINGS_METADATA:           return "Strings Metadata";
+    case AV_PKT_DATA_SUBTITLE_POSITION:          return "Subtitle Position";
+    case AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL:   return "Matroska BlockAdditional";
+    case AV_PKT_DATA_WEBVTT_IDENTIFIER:          return "WebVTT ID";
+    case AV_PKT_DATA_WEBVTT_SETTINGS:            return "WebVTT Settings";
+    case AV_PKT_DATA_METADATA_UPDATE:            return "Metadata Update";
+    case AV_PKT_DATA_MPEGTS_STREAM_ID:           return "MPEGTS Stream ID";
+    case AV_PKT_DATA_MASTERING_DISPLAY_METADATA: return "Mastering display metadata";
     }
     return NULL;
 }
@@ -566,16 +582,19 @@ int av_packet_ref(AVPacket *dst, const AVPacket *src)
         if (ret < 0)
             goto fail;
         memcpy(dst->buf->data, src->data, src->size);
+
+        dst->data = dst->buf->data;
     } else {
         dst->buf = av_buffer_ref(src->buf);
         if (!dst->buf) {
             ret = AVERROR(ENOMEM);
             goto fail;
         }
+        dst->data = src->data;
     }
 
     dst->size = src->size;
-    dst->data = dst->buf->data;
+
     return 0;
 fail:
     av_packet_free_side_data(dst);
@@ -599,6 +618,8 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src)
 {
     *dst = *src;
     av_init_packet(src);
+    src->data = NULL;
+    src->size = 0;
 }
 
 void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
diff --git a/libavcodec/bink.c b/libavcodec/bink.c
index 131eaa1..dffcdee 100644
--- a/libavcodec/bink.c
+++ b/libavcodec/bink.c
@@ -1240,7 +1240,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
 }
 
 /**
- * Caclulate quantization tables for version b
+ * Calculate quantization tables for version b
  */
 static av_cold void binkb_calc_quant(void)
 {
diff --git a/libavcodec/bitstream.c b/libavcodec/bitstream.c
index 1acb7a3..562ca1c 100644
--- a/libavcodec/bitstream.c
+++ b/libavcodec/bitstream.c
@@ -34,8 +34,8 @@
 #include "avcodec.h"
 #include "internal.h"
 #include "mathops.h"
-#include "get_bits.h"
 #include "put_bits.h"
+#include "vlc.h"
 
 const uint8_t ff_log2_run[41]={
  0, 0, 0, 0, 1, 1, 1, 1,
@@ -150,7 +150,7 @@ static int compare_vlcspec(const void *a, const void *b)
 /**
  * Build VLC decoding tables suitable for use with get_vlc().
  *
- * @param vlc            the context to be initted
+ * @param vlc            the context to be initialized
  *
  * @param table_nb_bits  max length of vlc codes to store directly in this table
  *                       (Longer codes are delegated to subtables.)
@@ -167,7 +167,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
     int table_size, table_index, index, code_prefix, symbol, subtable_bits;
     int i, j, k, n, nb, inc;
     uint32_t code;
-    volatile VLC_TYPE (* volatile table)[2]; // the double volatile is needed to prevent a internal compiler error in gcc 4.2
+    volatile VLC_TYPE (* volatile table)[2]; // the double volatile is needed to prevent an internal compiler error in gcc 4.2
 
     table_size = 1 << table_nb_bits;
     if (table_nb_bits > 30)
@@ -248,7 +248,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
 
 /* Build VLC decoding tables suitable for use with get_vlc().
 
-   'nb_bits' set the decoding table size (2^nb_bits) entries. The
+   'nb_bits' sets the decoding table size (2^nb_bits) entries. The
    bigger it is, the faster is the decoding. But it should not be too
    big to save memory and L1 cache. '9' is a good compromise.
 
@@ -317,7 +317,7 @@ int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes,
         }                                                                   \
         GET_DATA(buf[j].code, codes, i, codes_wrap, codes_size);            \
         if (buf[j].code >= (1LL<<buf[j].bits)) {                            \
-            av_log(NULL, AV_LOG_ERROR, "Invalid code in init_vlc\n");       \
+            av_log(NULL, AV_LOG_ERROR, "Invalid code %x for %d in init_vlc\n", buf[j].code, i);\
             if (!(flags & INIT_VLC_USE_NEW_STATIC))                         \
                 av_free(buf);                                               \
             return -1;                                                      \
diff --git a/libavcodec/bitstream_filter.c b/libavcodec/bitstream_filter.c
index fb690b6..02878e3 100644
--- a/libavcodec/bitstream_filter.c
+++ b/libavcodec/bitstream_filter.c
@@ -22,59 +22,76 @@
 
 #include "avcodec.h"
 #include "libavutil/atomic.h"
+#include "libavutil/internal.h"
 #include "libavutil/mem.h"
+#include "libavutil/opt.h"
 
-static AVBitStreamFilter *first_bitstream_filter = NULL;
+#if FF_API_OLD_BSF
+FF_DISABLE_DEPRECATION_WARNINGS
 
 AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f)
 {
-    if (f)
-        return f->next;
-    else
-        return first_bitstream_filter;
+    const AVBitStreamFilter *filter = NULL;
+    void *opaque = NULL;
+
+    while (filter != f)
+        filter = av_bsf_next(&opaque);
+
+    return av_bsf_next(&opaque);
 }
 
 void av_register_bitstream_filter(AVBitStreamFilter *bsf)
 {
-    do {
-        bsf->next = first_bitstream_filter;
-    } while(bsf->next != avpriv_atomic_ptr_cas((void * volatile *)&first_bitstream_filter, bsf->next, bsf));
 }
 
+typedef struct BSFCompatContext {
+    AVBSFContext *ctx;
+    int extradata_updated;
+} BSFCompatContext;
+
 AVBitStreamFilterContext *av_bitstream_filter_init(const char *name)
 {
-    AVBitStreamFilter *bsf = NULL;
-
-    while (bsf = av_bitstream_filter_next(bsf)) {
-        if (!strcmp(name, bsf->name)) {
-            AVBitStreamFilterContext *bsfc =
-                av_mallocz(sizeof(AVBitStreamFilterContext));
-            if (!bsfc)
-                return NULL;
-            bsfc->filter    = bsf;
-            bsfc->priv_data = NULL;
-            if (bsf->priv_data_size) {
-                bsfc->priv_data = av_mallocz(bsf->priv_data_size);
-                if (!bsfc->priv_data) {
-                    av_freep(&bsfc);
-                    return NULL;
-                }
-            }
-            return bsfc;
-        }
-    }
+    AVBitStreamFilterContext *ctx = NULL;
+    BSFCompatContext         *priv = NULL;
+    const AVBitStreamFilter *bsf;
+
+    bsf = av_bsf_get_by_name(name);
+    if (!bsf)
+        return NULL;
+
+    ctx = av_mallocz(sizeof(*ctx));
+    if (!ctx)
+        return NULL;
+
+    priv = av_mallocz(sizeof(*priv));
+    if (!priv)
+        goto fail;
+
+
+    ctx->filter    = bsf;
+    ctx->priv_data = priv;
+
+    return ctx;
+
+fail:
+    if (priv)
+        av_bsf_free(&priv->ctx);
+    av_freep(&priv);
+    av_freep(&ctx);
     return NULL;
 }
 
 void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc)
 {
+    BSFCompatContext *priv;
+
     if (!bsfc)
         return;
-    if (bsfc->filter->close)
-        bsfc->filter->close(bsfc);
+
+    priv = bsfc->priv_data;
+
+    av_bsf_free(&priv->ctx);
     av_freep(&bsfc->priv_data);
-    av_freep(&bsfc->args);
-    av_parser_close(bsfc->parser);
     av_free(bsfc);
 }
 
@@ -83,8 +100,85 @@ int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
                                uint8_t **poutbuf, int *poutbuf_size,
                                const uint8_t *buf, int buf_size, int keyframe)
 {
-    *poutbuf      = (uint8_t *)buf;
-    *poutbuf_size = buf_size;
-    return bsfc->filter->filter(bsfc, avctx, args ? args : bsfc->args,
-                                poutbuf, poutbuf_size, buf, buf_size, keyframe);
+    BSFCompatContext *priv = bsfc->priv_data;
+    AVPacket pkt = { 0 };
+    int ret;
+
+    if (!priv->ctx) {
+        ret = av_bsf_alloc(bsfc->filter, &priv->ctx);
+        if (ret < 0)
+            return ret;
+
+        ret = avcodec_parameters_from_context(priv->ctx->par_in, avctx);
+        if (ret < 0)
+            return ret;
+
+        priv->ctx->time_base_in = avctx->time_base;
+
+        if (bsfc->args && bsfc->filter->priv_class) {
+            const AVOption *opt = av_opt_next(priv->ctx->priv_data, NULL);
+            const char * shorthand[2] = {NULL};
+
+            if (opt)
+                shorthand[0] = opt->name;
+
+            ret = av_opt_set_from_string(priv->ctx->priv_data, bsfc->args, shorthand, "=", ":");
+        }
+
+        ret = av_bsf_init(priv->ctx);
+        if (ret < 0)
+            return ret;
+    }
+
+    pkt.data = buf;
+    pkt.size = buf_size;
+
+    ret = av_bsf_send_packet(priv->ctx, &pkt);
+    if (ret < 0)
+        return ret;
+
+    *poutbuf      = NULL;
+    *poutbuf_size = 0;
+
+    ret = av_bsf_receive_packet(priv->ctx, &pkt);
+    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+        return 0;
+    else if (ret < 0)
+        return ret;
+
+    *poutbuf = av_malloc(pkt.size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!*poutbuf) {
+        av_packet_unref(&pkt);
+        return AVERROR(ENOMEM);
+    }
+
+    *poutbuf_size = pkt.size;
+    memcpy(*poutbuf, pkt.data, pkt.size);
+
+    av_packet_unref(&pkt);
+
+    /* drain all the remaining packets we cannot return */
+    while (ret >= 0) {
+        ret = av_bsf_receive_packet(priv->ctx, &pkt);
+        av_packet_unref(&pkt);
+    }
+
+    if (!priv->extradata_updated) {
+        /* update extradata in avctx from the output codec parameters */
+        if (priv->ctx->par_out->extradata_size && (!args || !strstr(args, "private_spspps_buf"))) {
+            av_freep(&avctx->extradata);
+            avctx->extradata_size = 0;
+            avctx->extradata = av_mallocz(priv->ctx->par_out->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!avctx->extradata)
+                return AVERROR(ENOMEM);
+            memcpy(avctx->extradata, priv->ctx->par_out->extradata, priv->ctx->par_out->extradata_size);
+            avctx->extradata_size = priv->ctx->par_out->extradata_size;
+        }
+
+        priv->extradata_updated = 1;
+    }
+
+    return 1;
 }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
new file mode 100644
index 0000000..840bb43
--- /dev/null
+++ b/libavcodec/bitstream_filters.c
@@ -0,0 +1,87 @@
+/*
+ * 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 "config.h"
+
+#include "libavutil/common.h"
+#include "libavutil/log.h"
+
+#include "avcodec.h"
+#include "bsf.h"
+
+extern const AVBitStreamFilter ff_aac_adtstoasc_bsf;
+extern const AVBitStreamFilter ff_chomp_bsf;
+extern const AVBitStreamFilter ff_dump_extradata_bsf;
+extern const AVBitStreamFilter ff_dca_core_bsf;
+extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf;
+extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf;
+extern const AVBitStreamFilter ff_imx_dump_header_bsf;
+extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf;
+extern const AVBitStreamFilter ff_mjpega_dump_header_bsf;
+extern const AVBitStreamFilter ff_mp3_header_decompress_bsf;
+extern const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf;
+extern const AVBitStreamFilter ff_mov2textsub_bsf;
+extern const AVBitStreamFilter ff_noise_bsf;
+extern const AVBitStreamFilter ff_remove_extradata_bsf;
+extern const AVBitStreamFilter ff_text2movsub_bsf;
+extern const AVBitStreamFilter ff_vp9_superframe_bsf;
+
+#include "libavcodec/bsf_list.c"
+
+const AVBitStreamFilter *av_bsf_next(void **opaque)
+{
+    uintptr_t i = (uintptr_t)*opaque;
+    const AVBitStreamFilter *f = bitstream_filters[i];
+
+    if (f)
+        *opaque = (void*)(i + 1);
+
+    return f;
+}
+
+const AVBitStreamFilter *av_bsf_get_by_name(const char *name)
+{
+    int i;
+
+    for (i = 0; bitstream_filters[i]; i++) {
+        const AVBitStreamFilter *f = bitstream_filters[i];
+        if (!strcmp(f->name, name))
+            return f;
+    }
+
+    return NULL;
+}
+
+const AVClass *ff_bsf_child_class_next(const AVClass *prev)
+{
+    int i;
+
+    /* find the filter that corresponds to prev */
+    for (i = 0; prev && bitstream_filters[i]; i++) {
+        if (bitstream_filters[i]->priv_class == prev) {
+            i++;
+            break;
+        }
+    }
+
+    /* find next filter with priv options */
+    for (; bitstream_filters[i]; i++)
+        if (bitstream_filters[i]->priv_class)
+            return bitstream_filters[i]->priv_class;
+    return NULL;
+}
diff --git a/libavcodec/bmp_parser.c b/libavcodec/bmp_parser.c
index 7ab32a0..cd65f02 100644
--- a/libavcodec/bmp_parser.c
+++ b/libavcodec/bmp_parser.c
@@ -53,7 +53,8 @@ restart:
             if (bpc->pc.frame_start_found == 0) {
                 if ((state >> 48) == (('B' << 8) | 'M')) {
                     bpc->fsize = av_bswap32(state >> 16);
-                    bpc->pc.frame_start_found = 1;
+                    if (bpc->fsize > 17)
+                        bpc->pc.frame_start_found = 1;
                 }
             } else if (bpc->pc.frame_start_found == 2+4+4) {
 //                 unsigned hsize = av_bswap32(state>>32);
@@ -63,12 +64,16 @@ restart:
                     continue;
                 }
                 bpc->pc.frame_start_found++;
-                bpc->remaining_size = bpc->fsize + FFMAX(i - 17, 0);
+                bpc->remaining_size = bpc->fsize + i - 17;
 
                 if (bpc->pc.index + i > 17) {
                     next = i - 17;
-                } else
+                    state = 0;
+                    break;
+                } else {
+                    bpc->pc.state64 = 0;
                     goto restart;
+                }
             } else if (bpc->pc.frame_start_found)
                 bpc->pc.frame_start_found++;
         }
@@ -89,7 +94,10 @@ flush:
     if (ff_combine_frame(&bpc->pc, next, &buf, &buf_size) < 0)
         return buf_size;
 
-    bpc->pc.frame_start_found = 0;
+    if (next != END_NOT_FOUND && next < 0)
+        bpc->pc.frame_start_found = FFMAX(bpc->pc.frame_start_found - i - 1, 0);
+    else
+        bpc->pc.frame_start_found = 0;
 
     *poutbuf      = buf;
     *poutbuf_size = buf_size;
diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c
new file mode 100644
index 0000000..88b7f29
--- /dev/null
+++ b/libavcodec/bsf.c
@@ -0,0 +1,219 @@
+/*
+ * 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 <string.h>
+
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+
+#include "avcodec.h"
+#include "bsf.h"
+
+struct AVBSFInternal {
+    AVPacket *buffer_pkt;
+    int eof;
+};
+
+void av_bsf_free(AVBSFContext **pctx)
+{
+    AVBSFContext *ctx;
+
+    if (!pctx || !*pctx)
+        return;
+    ctx = *pctx;
+
+    if (ctx->filter->close)
+        ctx->filter->close(ctx);
+    if (ctx->filter->priv_class && ctx->priv_data)
+        av_opt_free(ctx->priv_data);
+
+    av_opt_free(ctx);
+
+    av_packet_free(&ctx->internal->buffer_pkt);
+    av_freep(&ctx->internal);
+    av_freep(&ctx->priv_data);
+
+    avcodec_parameters_free(&ctx->par_in);
+    avcodec_parameters_free(&ctx->par_out);
+
+    av_freep(pctx);
+}
+
+static void *bsf_child_next(void *obj, void *prev)
+{
+    AVBSFContext *ctx = obj;
+    if (!prev && ctx->filter->priv_class)
+        return ctx->priv_data;
+    return NULL;
+}
+
+static const AVClass bsf_class = {
+    .class_name       = "AVBSFContext",
+    .item_name        = av_default_item_name,
+    .version          = LIBAVUTIL_VERSION_INT,
+    .child_next       = bsf_child_next,
+    .child_class_next = ff_bsf_child_class_next,
+};
+
+const AVClass *av_bsf_get_class(void)
+{
+    return &bsf_class;
+}
+
+int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
+{
+    AVBSFContext *ctx;
+    int ret;
+
+    ctx = av_mallocz(sizeof(*ctx));
+    if (!ctx)
+        return AVERROR(ENOMEM);
+
+    ctx->av_class = &bsf_class;
+    ctx->filter   = filter;
+
+    ctx->par_in  = avcodec_parameters_alloc();
+    ctx->par_out = avcodec_parameters_alloc();
+    if (!ctx->par_in || !ctx->par_out) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ctx->internal = av_mallocz(sizeof(*ctx->internal));
+    if (!ctx->internal) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ctx->internal->buffer_pkt = av_packet_alloc();
+    if (!ctx->internal->buffer_pkt) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    av_opt_set_defaults(ctx);
+
+    /* allocate priv data and init private options */
+    if (filter->priv_data_size) {
+        ctx->priv_data = av_mallocz(filter->priv_data_size);
+        if (!ctx->priv_data) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        if (filter->priv_class) {
+            *(const AVClass **)ctx->priv_data = filter->priv_class;
+            av_opt_set_defaults(ctx->priv_data);
+        }
+    }
+
+    *pctx = ctx;
+    return 0;
+fail:
+    av_bsf_free(&ctx);
+    return ret;
+}
+
+int av_bsf_init(AVBSFContext *ctx)
+{
+    int ret, i;
+
+    /* check that the codec is supported */
+    if (ctx->filter->codec_ids) {
+        for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++)
+            if (ctx->par_in->codec_id == ctx->filter->codec_ids[i])
+                break;
+        if (ctx->filter->codec_ids[i] == AV_CODEC_ID_NONE) {
+            const AVCodecDescriptor *desc = avcodec_descriptor_get(ctx->par_in->codec_id);
+            av_log(ctx, AV_LOG_ERROR, "Codec '%s' (%d) is not supported by the "
+                   "bitstream filter '%s'. Supported codecs are: ",
+                   desc ? desc->name : "unknown", ctx->par_in->codec_id, ctx->filter->name);
+            for (i = 0; ctx->filter->codec_ids[i] != AV_CODEC_ID_NONE; i++) {
+                desc = avcodec_descriptor_get(ctx->filter->codec_ids[i]);
+                av_log(ctx, AV_LOG_ERROR, "%s (%d) ",
+                       desc ? desc->name : "unknown", ctx->filter->codec_ids[i]);
+            }
+            av_log(ctx, AV_LOG_ERROR, "\n");
+            return AVERROR(EINVAL);
+        }
+    }
+
+    /* initialize output parameters to be the same as input
+     * init below might overwrite that */
+    ret = avcodec_parameters_copy(ctx->par_out, ctx->par_in);
+    if (ret < 0)
+        return ret;
+
+    ctx->time_base_out = ctx->time_base_in;
+
+    if (ctx->filter->init) {
+        ret = ctx->filter->init(ctx);
+        if (ret < 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
+{
+    if (!pkt || !pkt->data) {
+        ctx->internal->eof = 1;
+        return 0;
+    }
+
+    if (ctx->internal->eof) {
+        av_log(ctx, AV_LOG_ERROR, "A non-NULL packet sent after an EOF.\n");
+        return AVERROR(EINVAL);
+    }
+
+    if (ctx->internal->buffer_pkt->data ||
+        ctx->internal->buffer_pkt->side_data_elems)
+        return AVERROR(EAGAIN);
+
+    av_packet_move_ref(ctx->internal->buffer_pkt, pkt);
+
+    return 0;
+}
+
+int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
+{
+    return ctx->filter->filter(ctx, pkt);
+}
+
+int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
+{
+    AVBSFInternal *in = ctx->internal;
+    AVPacket *tmp_pkt;
+
+    if (in->eof)
+        return AVERROR_EOF;
+
+    if (!ctx->internal->buffer_pkt->data &&
+        !ctx->internal->buffer_pkt->side_data_elems)
+        return AVERROR(EAGAIN);
+
+    tmp_pkt = av_packet_alloc();
+    if (!tmp_pkt)
+        return AVERROR(ENOMEM);
+
+    *pkt = ctx->internal->buffer_pkt;
+    ctx->internal->buffer_pkt = tmp_pkt;
+
+    return 0;
+}
diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h
new file mode 100644
index 0000000..3435df5
--- /dev/null
+++ b/libavcodec/bsf.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_BSF_H
+#define AVCODEC_BSF_H
+
+#include "avcodec.h"
+
+/**
+ * Called by the bitstream filters to get the next packet for filtering.
+ * The filter is responsible for either freeing the packet or passing it to the
+ * caller.
+ */
+int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt);
+
+const AVClass *ff_bsf_child_class_next(const AVClass *prev);
+
+#endif /* AVCODEC_BSF_H */
diff --git a/libavcodec/cabac.c b/libavcodec/cabac.c
index a9fafbd..c0abe83 100644
--- a/libavcodec/cabac.c
+++ b/libavcodec/cabac.c
@@ -28,7 +28,7 @@
 
 #include "libavutil/common.h"
 #include "libavutil/timer.h"
-#include "get_bits.h"
+
 #include "cabac.h"
 #include "cabac_functions.h"
 
@@ -159,7 +159,6 @@ const uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63] = {
 };
 
 /**
- *
  * @param buf_size size of buf in bits
  */
 void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){
@@ -201,150 +200,3 @@ int ff_init_cabac_decoder(CABACContext *c, const uint8_t *buf, int buf_size){
         return AVERROR_INVALIDDATA;
     return 0;
 }
-
-#ifdef TEST
-#define SIZE 10240
-
-#include "libavutil/lfg.h"
-#include "avcodec.h"
-
-static inline void put_cabac_bit(CABACContext *c, int b){
-    put_bits(&c->pb, 1, b);
-    for(;c->outstanding_count; c->outstanding_count--){
-        put_bits(&c->pb, 1, 1-b);
-    }
-}
-
-static inline void renorm_cabac_encoder(CABACContext *c){
-    while(c->range < 0x100){
-        //FIXME optimize
-        if(c->low<0x100){
-            put_cabac_bit(c, 0);
-        }else if(c->low<0x200){
-            c->outstanding_count++;
-            c->low -= 0x100;
-        }else{
-            put_cabac_bit(c, 1);
-            c->low -= 0x200;
-        }
-
-        c->range+= c->range;
-        c->low += c->low;
-    }
-}
-
-static void put_cabac(CABACContext *c, uint8_t * const state, int bit){
-    int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state];
-
-    if(bit == ((*state)&1)){
-        c->range -= RangeLPS;
-        *state    = ff_h264_mlps_state[128 + *state];
-    }else{
-        c->low += c->range - RangeLPS;
-        c->range = RangeLPS;
-        *state= ff_h264_mlps_state[127 - *state];
-    }
-
-    renorm_cabac_encoder(c);
-}
-
-/**
- * @param bit 0 -> write zero bit, !=0 write one bit
- */
-static void put_cabac_bypass(CABACContext *c, int bit){
-    c->low += c->low;
-
-    if(bit){
-        c->low += c->range;
-    }
-//FIXME optimize
-    if(c->low<0x200){
-        put_cabac_bit(c, 0);
-    }else if(c->low<0x400){
-        c->outstanding_count++;
-        c->low -= 0x200;
-    }else{
-        put_cabac_bit(c, 1);
-        c->low -= 0x400;
-    }
-}
-
-/**
- *
- * @return the number of bytes written
- */
-static int put_cabac_terminate(CABACContext *c, int bit){
-    c->range -= 2;
-
-    if(!bit){
-        renorm_cabac_encoder(c);
-    }else{
-        c->low += c->range;
-        c->range= 2;
-
-        renorm_cabac_encoder(c);
-
-        av_assert0(c->low <= 0x1FF);
-        put_cabac_bit(c, c->low>>9);
-        put_bits(&c->pb, 2, ((c->low>>7)&3)|1);
-
-        flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong
-    }
-
-    return (put_bits_count(&c->pb)+7)>>3;
-}
-
-int main(void){
-    CABACContext c;
-    uint8_t b[9*SIZE];
-    uint8_t r[9*SIZE];
-    int i, ret = 0;
-    uint8_t state[10]= {0};
-    AVLFG prng;
-
-    av_lfg_init(&prng, 1);
-    ff_init_cabac_encoder(&c, b, SIZE);
-
-    for(i=0; i<SIZE; i++){
-        if(2*i<SIZE) r[i] = av_lfg_get(&prng) % 7;
-        else         r[i] = (i>>8)&1;
-    }
-
-    for(i=0; i<SIZE; i++){
-        put_cabac_bypass(&c, r[i]&1);
-    }
-
-    for(i=0; i<SIZE; i++){
-        put_cabac(&c, state, r[i]&1);
-    }
-
-    i= put_cabac_terminate(&c, 1);
-    b[i++] = av_lfg_get(&prng);
-    b[i  ] = av_lfg_get(&prng);
-
-    ff_init_cabac_decoder(&c, b, SIZE);
-
-    memset(state, 0, sizeof(state));
-
-    for(i=0; i<SIZE; i++){
-        if( (r[i]&1) != get_cabac_bypass(&c) ) {
-            av_log(NULL, AV_LOG_ERROR, "CABAC bypass failure at %d\n", i);
-            ret = 1;
-        }
-    }
-
-    for(i=0; i<SIZE; i++){
-        if( (r[i]&1) != get_cabac_noinline(&c, state) ) {
-            av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i);
-            ret = 1;
-        }
-    }
-    if(!get_cabac_terminate(&c)) {
-        av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n");
-        ret = 1;
-    }
-
-    return ret;
-}
-
-#endif /* TEST */
diff --git a/libavcodec/cabac_functions.h b/libavcodec/cabac_functions.h
index cbb186b..fe72a82 100644
--- a/libavcodec/cabac_functions.h
+++ b/libavcodec/cabac_functions.h
@@ -172,7 +172,6 @@ static av_always_inline int get_cabac_bypass_sign(CABACContext *c, int val){
 #endif
 
 /**
- *
  * @return the number of bytes read or 0 if no end
  */
 #ifndef get_cabac_terminate
diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c
index 10a25d8..10e118e 100644
--- a/libavcodec/cavs.c
+++ b/libavcodec/cavs.c
@@ -105,7 +105,6 @@ static inline int get_bs(cavs_vector *mvP, cavs_vector *mvQ, int b)
  * | 6 | 7 |
  * 1   3   |
  * ---------
- *
  */
 void ff_cavs_filter(AVSContext *h, enum cavs_mb mb_type)
 {
diff --git a/libavcodec/cbrt_data.c b/libavcodec/cbrt_data.c
new file mode 100644
index 0000000..d2e36cd
--- /dev/null
+++ b/libavcodec/cbrt_data.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016 Reimar Döffinger <Reimar.Doeffinger at gmx.de>
+ *
+ * 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 "config.h"
+#include "cbrt_data.h"
+
+#include "libavutil/libm.h"
+
+#if CONFIG_HARDCODED_TABLES
+#include "libavcodec/cbrt_tables.h"
+#else
+#include "cbrt_tablegen.h"
+#endif
diff --git a/libavcodec/cbrt_data.h b/libavcodec/cbrt_data.h
new file mode 100644
index 0000000..232f74f
--- /dev/null
+++ b/libavcodec/cbrt_data.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 Reimar Döffinger <Reimar.Doeffinger at gmx.de>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_CBRT_DATA_H
+#define AVCODEC_CBRT_DATA_H
+
+#include <stdint.h>
+
+#if CONFIG_HARDCODED_TABLES
+#define ff_cbrt_tableinit_fixed()
+#define ff_cbrt_tableinit()
+extern const uint32_t ff_cbrt_tab[1 << 13];
+extern const uint32_t ff_cbrt_tab_fixed[1 << 13];
+#else
+void ff_cbrt_tableinit(void);
+void ff_cbrt_tableinit_fixed(void);
+extern uint32_t ff_cbrt_tab[1 << 13];
+extern uint32_t ff_cbrt_tab_fixed[1 << 13];
+#endif
+
+#endif
diff --git a/libavcodec/cbrt_data_fixed.c b/libavcodec/cbrt_data_fixed.c
new file mode 100644
index 0000000..d661b25
--- /dev/null
+++ b/libavcodec/cbrt_data_fixed.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 Reimar Döffinger <Reimar.Doeffinger at gmx.de>
+ *
+ * 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 "config.h"
+#include "cbrt_data.h"
+
+#if CONFIG_HARDCODED_TABLES
+#include "libavcodec/cbrt_fixed_tables.h"
+#else
+#define USE_FIXED 1
+#include "cbrt_tablegen.h"
+#endif
diff --git a/libavcodec/cbrt_tablegen.h b/libavcodec/cbrt_tablegen.h
index 21e4b9a..9af18d8 100644
--- a/libavcodec/cbrt_tablegen.h
+++ b/libavcodec/cbrt_tablegen.h
@@ -35,21 +35,12 @@
 #define CBRT(x) av_float2int((float)(x))
 #endif
 
-#if CONFIG_HARDCODED_TABLES
-#if USE_FIXED
-#define cbrt_tableinit_fixed()
-#include "libavcodec/cbrt_fixed_tables.h"
-#else
-#define cbrt_tableinit()
-#include "libavcodec/cbrt_tables.h"
-#endif
-#else
-static uint32_t cbrt_tab[1 << 13];
+uint32_t AAC_RENAME(ff_cbrt_tab)[1 << 13];
 
-static av_cold void AAC_RENAME(cbrt_tableinit)(void)
+av_cold void AAC_RENAME(ff_cbrt_tableinit)(void)
 {
     static double cbrt_tab_dbl[1 << 13];
-    if (!cbrt_tab[(1<<13) - 1]) {
+    if (!AAC_RENAME(ff_cbrt_tab)[(1<<13) - 1]) {
         int i, j, k;
         double cbrt_val;
 
@@ -75,9 +66,8 @@ static av_cold void AAC_RENAME(cbrt_tableinit)(void)
         }
 
         for (i = 0; i < 1<<13; i++)
-            cbrt_tab[i] = CBRT(cbrt_tab_dbl[i]);
+            AAC_RENAME(ff_cbrt_tab)[i] = CBRT(cbrt_tab_dbl[i]);
     }
 }
-#endif /* CONFIG_HARDCODED_TABLES */
 
 #endif /* AVCODEC_CBRT_TABLEGEN_H */
diff --git a/libavcodec/cbrt_tablegen_template.c b/libavcodec/cbrt_tablegen_template.c
index 7dcab91..21ed2a6 100644
--- a/libavcodec/cbrt_tablegen_template.c
+++ b/libavcodec/cbrt_tablegen_template.c
@@ -28,11 +28,15 @@
 
 int main(void)
 {
-    AAC_RENAME(cbrt_tableinit)();
+    AAC_RENAME(ff_cbrt_tableinit)();
 
     write_fileheader();
 
-    WRITE_ARRAY("static const", uint32_t, cbrt_tab);
+#if USE_FIXED
+    WRITE_ARRAY("const", uint32_t, ff_cbrt_tab_fixed);
+#else
+    WRITE_ARRAY("const", uint32_t, ff_cbrt_tab);
+#endif
 
     return 0;
 }
diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c
index 790f071..3b15149 100644
--- a/libavcodec/ccaption_dec.c
+++ b/libavcodec/ccaption_dec.c
@@ -30,7 +30,7 @@
 #define UNSET_FLAG(var, val) ( (var) &=  ~( 1 << (val)) )
 #define CHECK_FLAG(var, val) ( (var) &    ( 1 << (val)) )
 
-static const AVRational ass_tb = {1, 100};
+static const AVRational ms_tb = {1, 1000};
 
 /*
  * TODO list
@@ -63,6 +63,116 @@ enum cc_font {
     CCFONT_UNDERLINED_ITALICS,
 };
 
+enum cc_charset {
+    CCSET_BASIC_AMERICAN,
+    CCSET_SPECIAL_AMERICAN,
+    CCSET_EXTENDED_SPANISH_FRENCH_MISC,
+    CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH,
+};
+
+static const char *charset_overrides[4][128] =
+{
+    [CCSET_BASIC_AMERICAN] = {
+        [0x27] = "\u2019",
+        [0x2a] = "\u00e1",
+        [0x5c] = "\u00e9",
+        [0x5e] = "\u00ed",
+        [0x5f] = "\u00f3",
+        [0x60] = "\u00fa",
+        [0x7b] = "\u00e7",
+        [0x7c] = "\u00f7",
+        [0x7d] = "\u00d1",
+        [0x7e] = "\u00f1",
+        [0x7f] = "\u2588"
+    },
+    [CCSET_SPECIAL_AMERICAN] = {
+        [0x30] = "\u00ae",
+        [0x31] = "\u00b0",
+        [0x32] = "\u00bd",
+        [0x33] = "\u00bf",
+        [0x34] = "\u2122",
+        [0x35] = "\u00a2",
+        [0x36] = "\u00a3",
+        [0x37] = "\u266a",
+        [0x38] = "\u00e0",
+        [0x39] = "\u00A0",
+        [0x3a] = "\u00e8",
+        [0x3b] = "\u00e2",
+        [0x3c] = "\u00ea",
+        [0x3d] = "\u00ee",
+        [0x3e] = "\u00f4",
+        [0x3f] = "\u00fb",
+    },
+    [CCSET_EXTENDED_SPANISH_FRENCH_MISC] = {
+        [0x20] = "\u00c1",
+        [0x21] = "\u00c9",
+        [0x22] = "\u00d3",
+        [0x23] = "\u00da",
+        [0x24] = "\u00dc",
+        [0x25] = "\u00fc",
+        [0x26] = "\u00b4",
+        [0x27] = "\u00a1",
+        [0x28] = "*",
+        [0x29] = "\u2018",
+        [0x2a] = "-",
+        [0x2b] = "\u00a9",
+        [0x2c] = "\u2120",
+        [0x2d] = "\u00b7",
+        [0x2e] = "\u201c",
+        [0x2f] = "\u201d",
+        [0x30] = "\u00c0",
+        [0x31] = "\u00c2",
+        [0x32] = "\u00c7",
+        [0x33] = "\u00c8",
+        [0x34] = "\u00ca",
+        [0x35] = "\u00cb",
+        [0x36] = "\u00eb",
+        [0x37] = "\u00ce",
+        [0x38] = "\u00cf",
+        [0x39] = "\u00ef",
+        [0x3a] = "\u00d4",
+        [0x3b] = "\u00d9",
+        [0x3c] = "\u00f9",
+        [0x3d] = "\u00db",
+        [0x3e] = "\u00ab",
+        [0x3f] = "\u00bb",
+    },
+    [CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH] = {
+        [0x20] = "\u00c3",
+        [0x21] = "\u00e3",
+        [0x22] = "\u00cd",
+        [0x23] = "\u00cc",
+        [0x24] = "\u00ec",
+        [0x25] = "\u00d2",
+        [0x26] = "\u00f2",
+        [0x27] = "\u00d5",
+        [0x28] = "\u00f5",
+        [0x29] = "{",
+        [0x2a] = "}",
+        [0x2b] = "\\",
+        [0x2c] = "^",
+        [0x2d] = "_",
+        [0x2e] = "|",
+        [0x2f] = "~",
+        [0x30] = "\u00c4",
+        [0x31] = "\u00e4",
+        [0x32] = "\u00d6",
+        [0x33] = "\u00f6",
+        [0x34] = "\u00df",
+        [0x35] = "\u00a5",
+        [0x36] = "\u00a4",
+        [0x37] = "\u00a6",
+        [0x38] = "\u00c5",
+        [0x39] = "\u00e5",
+        [0x3a] = "\u00d8",
+        [0x3b] = "\u00f8",
+        [0x3c] = "\u250c",
+        [0x3d] = "\u2510",
+        [0x3e] = "\u2514",
+        [0x3f] = "\u2518",
+    },
+};
+
 static const unsigned char pac2_attribs[32][3] = // Color, font, ident
 {
     { CCCOL_WHITE,   CCFONT_REGULAR,            0 },  // 0x40 || 0x60
@@ -103,6 +213,7 @@ static const unsigned char pac2_attribs[32][3] = // Color, font, ident
 struct Screen {
     /* +1 is used to compensate null character of string */
     uint8_t characters[SCREEN_ROWS][SCREEN_COLUMNS+1];
+    uint8_t charsets[SCREEN_ROWS][SCREEN_COLUMNS+1];
     uint8_t colors[SCREEN_ROWS][SCREEN_COLUMNS+1];
     uint8_t fonts[SCREEN_ROWS][SCREEN_COLUMNS+1];
     /*
@@ -123,6 +234,7 @@ typedef struct CCaptionSubContext {
     uint8_t cursor_column;
     uint8_t cursor_color;
     uint8_t cursor_font;
+    uint8_t cursor_charset;
     AVBPrint buffer;
     int buffer_changed;
     int rollup;
@@ -136,6 +248,7 @@ typedef struct CCaptionSubContext {
     char prev_cmd[2];
     /* buffer to store pkt data */
     AVBufferRef *pktbuf;
+    int readorder;
 } CCaptionSubContext;
 
 
@@ -189,10 +302,13 @@ static void flush_decoder(AVCodecContext *avctx)
     ctx->cursor_column = 0;
     ctx->cursor_font = 0;
     ctx->cursor_color = 0;
+    ctx->cursor_charset = 0;
     ctx->active_screen = 0;
     ctx->last_real_time = 0;
     ctx->screen_touched = 0;
     ctx->buffer_changed = 0;
+    if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
+        ctx->readorder = 0;
     av_bprint_clear(&ctx->buffer);
 }
 
@@ -204,10 +320,13 @@ static int write_char(CCaptionSubContext *ctx, struct Screen *screen, char ch)
     uint8_t col = ctx->cursor_column;
     char *row = screen->characters[ctx->cursor_row];
     char *font = screen->fonts[ctx->cursor_row];
+    char *charset = screen->charsets[ctx->cursor_row];
 
     if (col < SCREEN_COLUMNS) {
         row[col] = ch;
         font[col] = ctx->cursor_font;
+        charset[col] = ctx->cursor_charset;
+        ctx->cursor_charset = CCSET_BASIC_AMERICAN;
         if (ch) ctx->cursor_column++;
         return 0;
     }
@@ -306,6 +425,7 @@ static void roll_up(CCaptionSubContext *ctx)
         memcpy(screen->characters[i_row], screen->characters[i_row+1], SCREEN_COLUMNS);
         memcpy(screen->colors[i_row], screen->colors[i_row+1], SCREEN_COLUMNS);
         memcpy(screen->fonts[i_row], screen->fonts[i_row+1], SCREEN_COLUMNS);
+        memcpy(screen->charsets[i_row], screen->charsets[i_row+1], SCREEN_COLUMNS);
         if (CHECK_FLAG(screen->row_used, i_row + 1))
             SET_FLAG(screen->row_used, i_row);
     }
@@ -325,10 +445,12 @@ static int capture_screen(CCaptionSubContext *ctx)
         if (CHECK_FLAG(screen->row_used, i)) {
             const char *row = screen->characters[i];
             const char *font = screen->fonts[i];
+            const char *charset = screen->charsets[i];
+            const char *override;
             int j = 0;
 
             /* skip leading space */
-            while (row[j] == ' ')
+            while (row[j] == ' ' && charset[j] == CCSET_BASIC_AMERICAN)
                 j++;
 
             for (; j < SCREEN_COLUMNS; j++) {
@@ -362,7 +484,12 @@ static int capture_screen(CCaptionSubContext *ctx)
                     }
                 }
                 prev_font = font[j];
-                av_bprintf(&ctx->buffer, "%s%s%c", e_tag, s_tag, row[j]);
+                override = charset_overrides[(int)charset[j]][(int)row[j]];
+                if (override) {
+                    av_bprintf(&ctx->buffer, "%s%s%s", e_tag, s_tag, override);
+                } else {
+                    av_bprintf(&ctx->buffer, "%s%s%c", e_tag, s_tag, row[j]);
+                }
             }
             av_bprintf(&ctx->buffer, "\\N");
         }
@@ -419,6 +546,7 @@ static void handle_pac(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo)
     ctx->cursor_row = row_map[index] - 1;
     ctx->cursor_color =  pac2_attribs[lo][0];
     ctx->cursor_font = pac2_attribs[lo][1];
+    ctx->cursor_charset = CCSET_BASIC_AMERICAN;
     ctx->cursor_column = 0;
     indent = pac2_attribs[lo][2];
     for (i = 0; i < indent; i++) {
@@ -474,7 +602,25 @@ static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts)
 
     SET_FLAG(screen->row_used, ctx->cursor_row);
 
-    write_char(ctx, screen, hi);
+    switch (hi) {
+      case 0x11:
+        ctx->cursor_charset = CCSET_SPECIAL_AMERICAN;
+        break;
+      case 0x12:
+        if (ctx->cursor_column > 0)
+            ctx->cursor_column -= 1;
+        ctx->cursor_charset = CCSET_EXTENDED_SPANISH_FRENCH_MISC;
+        break;
+      case 0x13:
+        if (ctx->cursor_column > 0)
+            ctx->cursor_column -= 1;
+        ctx->cursor_charset = CCSET_EXTENDED_PORTUGUESE_GERMAN_DANISH;
+        break;
+      default:
+        ctx->cursor_charset = CCSET_BASIC_AMERICAN;
+        write_char(ctx, screen, hi);
+        break;
+    }
 
     if (lo) {
         write_char(ctx, screen, lo);
@@ -484,9 +630,6 @@ static void handle_char(CCaptionSubContext *ctx, char hi, char lo, int64_t pts)
     if (ctx->mode != CCMODE_POPON)
         ctx->screen_touched = 1;
 
-    /* reset prev command since character can repeat */
-    ctx->prev_cmd[0] = 0;
-    ctx->prev_cmd[1] = 0;
     if (lo)
        ff_dlog(ctx, "(%c,%c)\n", hi, lo);
     else
@@ -497,8 +640,15 @@ static void process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint
 {
     if (hi == ctx->prev_cmd[0] && lo == ctx->prev_cmd[1]) {
         /* ignore redundant command */
-    } else if ( (hi == 0x10 && (lo >= 0x40 && lo <= 0x5f)) ||
-              ( (hi >= 0x11 && hi <= 0x17) && (lo >= 0x40 && lo <= 0x7f) ) ) {
+        return;
+    }
+
+    /* set prev command */
+    ctx->prev_cmd[0] = hi;
+    ctx->prev_cmd[1] = lo;
+
+    if ( (hi == 0x10 && (lo >= 0x40 && lo <= 0x5f)) ||
+       ( (hi >= 0x11 && hi <= 0x17) && (lo >= 0x40 && lo <= 0x7f) ) ) {
         handle_pac(ctx, hi, lo);
     } else if ( ( hi == 0x11 && lo >= 0x20 && lo <= 0x2f ) ||
                 ( hi == 0x17 && lo >= 0x2e && lo <= 0x2f) ) {
@@ -556,23 +706,24 @@ static void process_cc608(CCaptionSubContext *ctx, int64_t pts, uint8_t hi, uint
             ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
             break;
         }
+    } else if (hi >= 0x11 && hi <= 0x13) {
+        /* Special characters */
+        handle_char(ctx, hi, lo, pts);
     } else if (hi >= 0x20) {
         /* Standard characters (always in pairs) */
         handle_char(ctx, hi, lo, pts);
+        ctx->prev_cmd[0] = ctx->prev_cmd[1] = 0;
     } else {
         /* Ignoring all other non data code */
         ff_dlog(ctx, "Unknown command 0x%hhx 0x%hhx\n", hi, lo);
     }
-
-    /* set prev command */
-    ctx->prev_cmd[0] = hi;
-    ctx->prev_cmd[1] = lo;
 }
 
 static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt)
 {
     CCaptionSubContext *ctx = avctx->priv_data;
     AVSubtitle *sub = data;
+    const int64_t start_time = sub->pts;
     uint8_t *bptr = NULL;
     int len = avpkt->size;
     int ret = 0;
@@ -597,7 +748,7 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp
         if(cc_type == 1)
             continue;
         else
-            process_cc608(ctx, avpkt->pts, *(bptr + i + 1) & 0x7f, *(bptr + i + 2) & 0x7f);
+            process_cc608(ctx, start_time, *(bptr + i + 1) & 0x7f, *(bptr + i + 2) & 0x7f);
 
         if (!ctx->buffer_changed)
             continue;
@@ -605,38 +756,34 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp
 
         if (*ctx->buffer.str || ctx->real_time)
         {
-            int64_t sub_pts = ctx->real_time ? avpkt->pts : ctx->start_time;
-            int start_time = av_rescale_q(sub_pts, avctx->time_base, ass_tb);
-            int duration = -1;
-            if (!ctx->real_time) {
-                int end_time = av_rescale_q(ctx->end_time, avctx->time_base, ass_tb);
-                duration = end_time - start_time;
-            }
             ff_dlog(ctx, "cdp writing data (%s)\n",ctx->buffer.str);
-            ret = ff_ass_add_rect_bprint(sub, &ctx->buffer, start_time, duration);
+            ret = ff_ass_add_rect(sub, ctx->buffer.str, ctx->readorder++, 0, NULL, NULL);
             if (ret < 0)
                 return ret;
-            sub->pts = av_rescale_q(sub_pts, avctx->time_base, AV_TIME_BASE_Q);
+            sub->pts = ctx->start_time;
+            if (!ctx->real_time)
+                sub->end_display_time = av_rescale_q(ctx->end_time - ctx->start_time,
+                                                     AV_TIME_BASE_Q, ms_tb);
+            else
+                sub->end_display_time = -1;
             ctx->buffer_changed = 0;
-            ctx->last_real_time = avpkt->pts;
+            ctx->last_real_time = sub->pts;
             ctx->screen_touched = 0;
         }
     }
 
     if (ctx->real_time && ctx->screen_touched &&
-        avpkt->pts > ctx->last_real_time + av_rescale_q(20, ass_tb, avctx->time_base)) {
-        int start_time;
-        ctx->last_real_time = avpkt->pts;
+        sub->pts > ctx->last_real_time + av_rescale_q(200, ms_tb, AV_TIME_BASE_Q)) {
+        ctx->last_real_time = sub->pts;
         ctx->screen_touched = 0;
 
         capture_screen(ctx);
         ctx->buffer_changed = 0;
 
-        start_time = av_rescale_q(avpkt->pts, avctx->time_base, ass_tb);
-        ret = ff_ass_add_rect_bprint(sub, &ctx->buffer, start_time, -1);
+        ret = ff_ass_add_rect(sub, ctx->buffer.str, ctx->readorder++, 0, NULL, NULL);
         if (ret < 0)
             return ret;
-        sub->pts = av_rescale_q(avpkt->pts, avctx->time_base, AV_TIME_BASE_Q);
+        sub->end_display_time = -1;
     }
 
     *got_sub = sub->num_rects > 0;
diff --git a/libavcodec/cdxl.c b/libavcodec/cdxl.c
index 50d514b..c8d66b5 100644
--- a/libavcodec/cdxl.c
+++ b/libavcodec/cdxl.c
@@ -30,6 +30,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/imgutils.h"
 #include "avcodec.h"
+#include "bytestream.h"
 #include "get_bits.h"
 #include "internal.h"
 
@@ -107,6 +108,17 @@ static void bitline2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
     }
 }
 
+static void chunky2chunky(CDXLVideoContext *c, int linesize, uint8_t *out)
+{
+    GetByteContext gb;
+    int y;
+
+    bytestream2_init(&gb, c->video, c->video_size);
+    for (y = 0; y < c->avctx->height; y++) {
+        bytestream2_get_buffer(&gb, out + linesize * y, c->avctx->width * 3);
+    }
+}
+
 static void import_format(CDXLVideoContext *c, int linesize, uint8_t *out)
 {
     memset(out, 0, linesize * c->avctx->height);
@@ -118,6 +130,9 @@ static void import_format(CDXLVideoContext *c, int linesize, uint8_t *out)
     case BIT_LINE:
         bitline2chunky(c, linesize, out);
         break;
+    case CHUNKY:
+        chunky2chunky(c, linesize, out);
+        break;
     }
 }
 
@@ -130,6 +145,11 @@ static void cdxl_decode_rgb(CDXLVideoContext *c, AVFrame *frame)
     import_format(c, frame->linesize[0], frame->data[0]);
 }
 
+static void cdxl_decode_raw(CDXLVideoContext *c, AVFrame *frame)
+{
+    import_format(c, frame->linesize[0], frame->data[0]);
+}
+
 static void cdxl_decode_ham6(CDXLVideoContext *c, AVFrame *frame)
 {
     AVCodecContext *avctx = c->avctx;
@@ -242,7 +262,7 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data,
         return AVERROR_INVALIDDATA;
     if (c->bpp < 1)
         return AVERROR_INVALIDDATA;
-    if (c->format != BIT_PLANAR && c->format != BIT_LINE) {
+    if (c->format != BIT_PLANAR && c->format != BIT_LINE && c->format != CHUNKY) {
         avpriv_request_sample(avctx, "Pixel format 0x%0x", c->format);
         return AVERROR_PATCHWELCOME;
     }
@@ -250,7 +270,10 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data,
     if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
         return ret;
 
-    aligned_width = FFALIGN(c->avctx->width, 16);
+    if (c->format == CHUNKY)
+        aligned_width = avctx->width;
+    else
+        aligned_width = FFALIGN(c->avctx->width, 16);
     c->padded_bits  = aligned_width - c->avctx->width;
     if (c->video_size < aligned_width * avctx->height * c->bpp / 8)
         return AVERROR_INVALIDDATA;
@@ -260,9 +283,12 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data,
         if (c->palette_size != (1 << (c->bpp - 1)))
             return AVERROR_INVALIDDATA;
         avctx->pix_fmt = AV_PIX_FMT_BGR24;
+    } else if (!encoding && c->bpp == 24 && c->format == CHUNKY &&
+               !c->palette_size) {
+        avctx->pix_fmt = AV_PIX_FMT_RGB24;
     } else {
-        avpriv_request_sample(avctx, "Encoding %d and bpp %d",
-                              encoding, c->bpp);
+        avpriv_request_sample(avctx, "Encoding %d, bpp %d and format 0x%x",
+                              encoding, c->bpp, c->format);
         return AVERROR_PATCHWELCOME;
     }
 
@@ -279,8 +305,10 @@ static int cdxl_decode_frame(AVCodecContext *avctx, void *data,
             cdxl_decode_ham8(c, p);
         else
             cdxl_decode_ham6(c, p);
-    } else {
+    } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
         cdxl_decode_rgb(c, p);
+    } else {
+        cdxl_decode_raw(c, p);
     }
     *got_frame = 1;
 
diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c
index d6d831b..74facd4 100644
--- a/libavcodec/cfhd.c
+++ b/libavcodec/cfhd.c
@@ -43,8 +43,6 @@ static av_cold int cfhd_decode_init(AVCodecContext *avctx)
 
     avctx->bits_per_raw_sample = 10;
     s->avctx                   = avctx;
-    avctx->width               = 0;
-    avctx->height              = 0;
 
     return ff_cfhd_init_vlcs(s);
 }
@@ -139,11 +137,17 @@ static void vert_filter(int16_t *output, int out_stride, int16_t *low, int low_s
 static void free_buffers(AVCodecContext *avctx)
 {
     CFHDContext *s = avctx->priv_data;
-    int i;
+    int i, j;
 
-    for (i = 0; i < 3; i++) {
+    for (i = 0; i < 4; i++) {
         av_freep(&s->plane[i].idwt_buf);
         av_freep(&s->plane[i].idwt_tmp);
+
+        for (j = 0; j < 9; j++)
+            s->plane[i].subband[j] = NULL;
+
+        for (j = 0; j < 8; j++)
+            s->plane[i].l_h[j] = NULL;
     }
     s->a_height = 0;
     s->a_width  = 0;
@@ -152,14 +156,16 @@ static void free_buffers(AVCodecContext *avctx)
 static int alloc_buffers(AVCodecContext *avctx)
 {
     CFHDContext *s = avctx->priv_data;
-    int i, j, k, ret;
+    int i, j, k, ret, planes;
 
     if ((ret = ff_set_dimensions(avctx, s->coded_width, s->coded_height)) < 0)
         return ret;
+    avctx->pix_fmt = s->coded_format;
 
     avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift);
+    planes = av_pix_fmt_count_planes(avctx->pix_fmt);
 
-    for (i = 0; i < 3; i++) {
+    for (i = 0; i < planes; i++) {
         int width = i ? avctx->width >> s->chroma_x_shift : avctx->width;
         int height = i ? avctx->height >> s->chroma_y_shift : avctx->height;
         int stride = FFALIGN(width / 8, 8) * 8;
@@ -176,7 +182,7 @@ static int alloc_buffers(AVCodecContext *avctx)
         w2 = w4 * 2;
         h2 = h4 * 2;
 
-        s->plane[i].idwt_buf = av_malloc_array(height * stride, sizeof(*s->plane[i].idwt_buf));
+        s->plane[i].idwt_buf = av_mallocz_array(height * stride, sizeof(*s->plane[i].idwt_buf));
         s->plane[i].idwt_tmp = av_malloc_array(height * stride, sizeof(*s->plane[i].idwt_tmp));
         if (!s->plane[i].idwt_buf || !s->plane[i].idwt_tmp) {
             return AVERROR(ENOMEM);
@@ -213,6 +219,7 @@ static int alloc_buffers(AVCodecContext *avctx)
 
     s->a_height = s->coded_height;
     s->a_width  = s->coded_width;
+    s->a_format = s->coded_format;
 
     return 0;
 }
@@ -224,11 +231,12 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
     GetByteContext gb;
     ThreadFrame frame = { .f = data };
     AVFrame *pic = data;
-    int ret = 0, i, j, plane, got_buffer = 0;
+    int ret = 0, i, j, planes, plane, got_buffer = 0;
     int16_t *coeff_data;
 
-    avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
+    s->coded_format = AV_PIX_FMT_YUV422P10;
     init_frame_defaults(s);
+    planes = av_pix_fmt_count_planes(s->coded_format);
 
     bytestream2_init(&gb, avpkt->data, avpkt->size);
 
@@ -254,7 +262,7 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
         } else if (tag == 12) {
             av_log(avctx, AV_LOG_DEBUG, "Channel Count: %"PRIu16"\n", data);
             s->channel_cnt = data;
-            if (data != 3) {
+            if (data > 4) {
                 av_log(avctx, AV_LOG_ERROR, "Channel Count of %"PRIu16" is unsupported\n", data);
                 ret = AVERROR_PATCHWELCOME;
                 break;
@@ -269,7 +277,7 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
         } else if (tag == 62) {
             s->channel_num = data;
             av_log(avctx, AV_LOG_DEBUG, "Channel number %"PRIu16"\n", data);
-            if (s->channel_num > 2) {
+            if (s->channel_num >= planes) {
                 av_log(avctx, AV_LOG_ERROR, "Invalid channel number\n");
                 ret = AVERROR(EINVAL);
                 break;
@@ -329,17 +337,17 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
             av_log(avctx, AV_LOG_DEBUG, "Sample type? %"PRIu16"\n", data);
         else if (tag == 10) {
             if (data != 0) {
-                avpriv_report_missing_feature(avctx, "Transform type of %"PRIu16" is unsupported\n", data);
+                avpriv_report_missing_feature(avctx, "Transform type of %"PRIu16, data);
                 ret = AVERROR_PATCHWELCOME;
                 break;
             }
             av_log(avctx, AV_LOG_DEBUG, "Transform-type? %"PRIu16"\n", data);
         } else if (abstag >= 0x4000 && abstag <= 0x40ff) {
-            av_log(avctx, AV_LOG_DEBUG, "Small chunk length %"PRIu16" %s\n", data * 4, tag < 0 ? "optional" : "required");
+            av_log(avctx, AV_LOG_DEBUG, "Small chunk length %d %s\n", data * 4, tag < 0 ? "optional" : "required");
             bytestream2_skipu(&gb, data * 4);
         } else if (tag == 23) {
             av_log(avctx, AV_LOG_DEBUG, "Skip frame\n");
-            avpriv_report_missing_feature(avctx, "Skip frame not supported\n");
+            avpriv_report_missing_feature(avctx, "Skip frame");
             ret = AVERROR_PATCHWELCOME;
             break;
         } else if (tag == 2) {
@@ -405,32 +413,43 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
         } else if (tag == 84) {
             av_log(avctx, AV_LOG_DEBUG, "Sample format? %i\n", data);
             if (data == 1)
-                avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
+                s->coded_format = AV_PIX_FMT_YUV422P10;
             else if (data == 3)
-                avctx->pix_fmt = AV_PIX_FMT_GBRP12;
+                s->coded_format = AV_PIX_FMT_GBRP12;
+            else if (data == 4)
+                s->coded_format = AV_PIX_FMT_GBRAP12;
             else {
-                avpriv_report_missing_feature(avctx, "Sample format of %"PRIu16" is unsupported\n", data);
+                avpriv_report_missing_feature(avctx, "Sample format of %"PRIu16, data);
                 ret = AVERROR_PATCHWELCOME;
                 break;
             }
+            planes = av_pix_fmt_count_planes(s->coded_format);
         } else
             av_log(avctx, AV_LOG_DEBUG,  "Unknown tag %i data %x\n", tag, data);
 
         /* Some kind of end of header tag */
-        if (tag == 4 && data == 0x1a4a && s->coded_width && s->coded_height && avctx->pix_fmt != AV_PIX_FMT_NONE) {
-            if (s->a_width != s->coded_width || s->a_height != s->coded_height) {
+        if (tag == 4 && data == 0x1a4a && s->coded_width && s->coded_height &&
+            s->coded_format != AV_PIX_FMT_NONE) {
+            if (s->a_width != s->coded_width || s->a_height != s->coded_height ||
+                s->a_format != s->coded_format) {
                 free_buffers(avctx);
                 if ((ret = alloc_buffers(avctx)) < 0) {
                     free_buffers(avctx);
                     return ret;
                 }
             }
+            ret = ff_set_dimensions(avctx, s->coded_width, s->coded_height);
+            if (ret < 0)
+                return ret;
+            frame.f->width =
+            frame.f->height = 0;
 
             if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
                 return ret;
 
             s->coded_width = 0;
             s->coded_height = 0;
+            s->coded_format = AV_PIX_FMT_NONE;
             got_buffer = 1;
         }
         coeff_data = s->plane[s->channel_num].subband[s->subband_num_actual];
@@ -442,6 +461,12 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
             int lowpass_a_height = s->plane[s->channel_num].band[0][0].a_height;
             int lowpass_a_width  = s->plane[s->channel_num].band[0][0].a_width;
 
+            if (!got_buffer) {
+                av_log(avctx, AV_LOG_ERROR, "No end of header tag found\n");
+                ret = AVERROR(EINVAL);
+                goto end;
+            }
+
             if (lowpass_height > lowpass_a_height || lowpass_width > lowpass_a_width ||
                 lowpass_a_width * lowpass_a_height * sizeof(int16_t) > bytestream2_get_bytes_left(&gb)) {
                 av_log(avctx, AV_LOG_ERROR, "Too many lowpass coefficients\n");
@@ -449,7 +474,7 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
                 goto end;
             }
 
-            av_log(avctx, AV_LOG_DEBUG, "Start of lowpass coeffs component %"PRIu16" height:%d, width:%d\n", s->channel_num, lowpass_height, lowpass_width);
+            av_log(avctx, AV_LOG_DEBUG, "Start of lowpass coeffs component %d height:%d, width:%d\n", s->channel_num, lowpass_height, lowpass_width);
             for (i = 0; i < lowpass_height; i++) {
                 for (j = 0; j < lowpass_width; j++)
                     coeff_data[j] = bytestream2_get_be16u(&gb);
@@ -457,6 +482,9 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
                 coeff_data += lowpass_width;
             }
 
+            /* Align to mod-4 position to continue reading tags */
+            bytestream2_seek(&gb, bytestream2_tell(&gb) & 3, SEEK_CUR);
+
             /* Copy last line of coefficients if odd height */
             if (lowpass_height & 1) {
                 memcpy(&coeff_data[lowpass_height * lowpass_width],
@@ -464,7 +492,7 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
                        lowpass_width * sizeof(*coeff_data));
             }
 
-            av_log(avctx, AV_LOG_DEBUG, "Lowpass coefficients %"PRIu16"\n", lowpass_width * lowpass_height);
+            av_log(avctx, AV_LOG_DEBUG, "Lowpass coefficients %d\n", lowpass_width * lowpass_height);
         }
 
         if (tag == 55 && s->subband_num_actual != 255 && s->a_width && s->a_height) {
@@ -478,6 +506,12 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
             int level, run, coeff;
             int count = 0, bytes;
 
+            if (!got_buffer) {
+                av_log(avctx, AV_LOG_ERROR, "No end of header tag found\n");
+                ret = AVERROR(EINVAL);
+                goto end;
+            }
+
             if (highpass_height > highpass_a_height || highpass_width > highpass_a_width || a_expected < expected) {
                 av_log(avctx, AV_LOG_ERROR, "Too many highpass coefficents\n");
                 ret = AVERROR(EINVAL);
@@ -557,7 +591,8 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
         }
     }
 
-    if (!s->a_width || !s->a_height || s->coded_width || s->coded_height) {
+    if (!s->a_width || !s->a_height || s->a_format == AV_PIX_FMT_NONE ||
+        s->coded_width || s->coded_height || s->coded_format != AV_PIX_FMT_NONE) {
         av_log(avctx, AV_LOG_ERROR, "Invalid dimensions\n");
         ret = AVERROR(EINVAL);
         goto end;
@@ -569,12 +604,13 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
         goto end;
     }
 
-    for (plane = 0; plane < 3 && !ret; plane++) {
+    planes = av_pix_fmt_count_planes(avctx->pix_fmt);
+    for (plane = 0; plane < planes && !ret; plane++) {
         /* level 1 */
         int lowpass_height  = s->plane[plane].band[0][0].height;
         int lowpass_width   = s->plane[plane].band[0][0].width;
         int highpass_stride = s->plane[plane].band[0][1].stride;
-        int act_plane = plane == 1 ? 2 : plane == 2 ? 1 : 0;
+        int act_plane = plane == 1 ? 2 : plane == 2 ? 1 : plane;
         int16_t *low, *high, *output, *dst;
 
         if (lowpass_height > s->plane[plane].band[0][0].a_height || lowpass_width > s->plane[plane].band[0][0].a_width ||
@@ -617,7 +653,7 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
             high   += lowpass_width;
             output += lowpass_width * 2;
         }
-        if (avctx->pix_fmt == AV_PIX_FMT_GBRP12) {
+        if (s->bpc == 12) {
             output = s->plane[plane].subband[0];
             for (i = 0; i < lowpass_height * 2; i++) {
                 for (j = 0; j < lowpass_width * 2; j++)
@@ -756,6 +792,6 @@ AVCodec ff_cfhd_decoder = {
     .init           = cfhd_decode_init,
     .close          = cfhd_close_decoder,
     .decode         = cfhd_decode,
-    .capabilities   = AV_CODEC_CAP_DR1,
+    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/cfhd.h b/libavcodec/cfhd.h
index a263124..67a0e4c 100644
--- a/libavcodec/cfhd.h
+++ b/libavcodec/cfhd.h
@@ -84,9 +84,11 @@ typedef struct CFHDContext {
 
     int coded_width;
     int coded_height;
+    int coded_format;
 
     int a_width;
     int a_height;
+    int a_format;
 
     int bpc;
     int channel_cnt;
diff --git a/libavcodec/chomp_bsf.c b/libavcodec/chomp_bsf.c
index 2b93fa9..cc94380 100644
--- a/libavcodec/chomp_bsf.c
+++ b/libavcodec/chomp_bsf.c
@@ -20,19 +20,23 @@
  */
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "internal.h"
 
-static int chomp_filter(AVBitStreamFilterContext *bsfc,
-                        AVCodecContext *avctx, const char *args,
-                        uint8_t  **poutbuf, int *poutbuf_size,
-                        const uint8_t *buf, int      buf_size,
-                        int keyframe)
+static int chomp_filter(AVBSFContext *ctx, AVPacket *out)
 {
-    while (buf_size > 0 && !buf[buf_size-1])
-        buf_size--;
+    AVPacket *in;
+    int ret;
 
-    *poutbuf = (uint8_t*) buf;
-    *poutbuf_size = buf_size;
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    while (in->size > 0 && !in->data[in->size - 1])
+        in->size--;
+
+    av_packet_move_ref(out, in);
+    av_packet_free(&in);
 
     return 0;
 }
@@ -40,7 +44,7 @@ static int chomp_filter(AVBitStreamFilterContext *bsfc,
 /**
  * This filter removes a string of NULL bytes from the end of a packet.
  */
-AVBitStreamFilter ff_chomp_bsf = {
+const AVBitStreamFilter ff_chomp_bsf = {
     .name   = "chomp",
     .filter = chomp_filter,
 };
diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c
index f1a4656..a2190d7 100644
--- a/libavcodec/cinepak.c
+++ b/libavcodec/cinepak.c
@@ -1,6 +1,6 @@
 /*
  * Cinepak Video Decoder
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c
index 0251086..34f8814 100644
--- a/libavcodec/cngdec.c
+++ b/libavcodec/cngdec.c
@@ -22,7 +22,7 @@
 #include <math.h>
 
 #include "libavutil/common.h"
-#include "libavutil/internal.h"
+#include "libavutil/ffmath.h"
 #include "avcodec.h"
 #include "celp_filters.h"
 #include "internal.h"
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 672bf3f..9d94b72 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -887,7 +887,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .id        = AV_CODEC_ID_IFF_ILBM,
         .type      = AVMEDIA_TYPE_VIDEO,
         .name      = "iff_ilbm",
-        .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
+        .long_name = NULL_IF_CONFIG_SMALL("IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
     {
@@ -948,6 +948,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
     },
     {
+        .id        = AV_CODEC_ID_M101,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "m101",
+        .long_name = NULL_IF_CONFIG_SMALL("Matrox Uncompressed SD"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
+    },
+    {
         .id        = AV_CODEC_ID_MVC1,
         .type      = AVMEDIA_TYPE_VIDEO,
         .name      = "mvc1",
@@ -1528,6 +1535,34 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("Cineform HD"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_TRUEMOTION2RT,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "truemotion2rt",
+        .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
+    {
+        .id        = AV_CODEC_ID_MAGICYUV,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "magicyuv",
+        .long_name = NULL_IF_CONFIG_SMALL("MagicYUV Lossless Video"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
+    },
+    {
+        .id        = AV_CODEC_ID_SHEERVIDEO,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "sheervideo",
+        .long_name = NULL_IF_CONFIG_SMALL("BitJazz SheerVideo"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
+    },
+    {
+        .id        = AV_CODEC_ID_YLC,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "ylc",
+        .long_name = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"),
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
+    },
 
     /* various PCM "codecs" */
     {
@@ -2022,6 +2057,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("ADPCM Yamaha AICA"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_ADPCM_IMA_DAT4,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_ima_dat4",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM IMA Eurocom DAT4"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
 
     /* AMR */
     {
@@ -2662,6 +2704,20 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 2"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_DST,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "dst",
+        .long_name = NULL_IF_CONFIG_SMALL("DST (Direct Stream Transfer)"),
+        .props     = AV_CODEC_PROP_LOSSLESS,
+    },
+    {
+        .id        = AV_CODEC_ID_ADPCM_MTAF,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "adpcm_mtaf",
+        .long_name = NULL_IF_CONFIG_SMALL("ADPCM MTAF"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
 
     /* subtitle codecs */
     {
diff --git a/libavcodec/cook.c b/libavcodec/cook.c
index 1b38019..794a475 100644
--- a/libavcodec/cook.c
+++ b/libavcodec/cook.c
@@ -141,7 +141,7 @@ typedef struct cook {
     VLC                 envelope_quant_index[13];
     VLC                 sqvh[7];          // scalar quantization
 
-    /* generatable tables and related variables */
+    /* generate tables and related variables */
     int                 gain_size_factor;
     float               gain_table[23];
 
@@ -1187,7 +1187,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
         /* Initialize variable relations */
         q->subpacket[s].numvector_size = (1 << q->subpacket[s].log2_numvector_size);
 
-        /* Try to catch some obviously faulty streams, othervise it might be exploitable */
+        /* Try to catch some obviously faulty streams, otherwise it might be exploitable */
         if (q->subpacket[s].total_subbands > 53) {
             avpriv_request_sample(avctx, "total_subbands > 53");
             return AVERROR_PATCHWELCOME;
@@ -1260,7 +1260,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
         q->saturate_output = saturate_output_float;
     }
 
-    /* Try to catch some obviously faulty streams, othervise it might be exploitable */
+    /* Try to catch some obviously faulty streams, otherwise it might be exploitable */
     if (q->samples_per_channel != 256 && q->samples_per_channel != 512 &&
         q->samples_per_channel != 1024) {
         avpriv_request_sample(avctx, "samples_per_channel = %d",
diff --git a/libavcodec/cookdata.h b/libavcodec/cookdata.h
index 7b9cba3..dcdb912 100644
--- a/libavcodec/cookdata.h
+++ b/libavcodec/cookdata.h
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * Cook AKA RealAudio G2 compatible decoderdata
+ * Cook AKA RealAudio G2 compatible decoder data
  */
 
 #ifndef AVCODEC_COOKDATA_H
diff --git a/libavcodec/cos_tablegen.c b/libavcodec/cos_tablegen.c
index dbd0cc0..7206aad 100644
--- a/libavcodec/cos_tablegen.c
+++ b/libavcodec/cos_tablegen.c
@@ -26,7 +26,7 @@
 
 #include "libavutil/mathematics.h"
 
-#define BITS 16
+#define BITS 17
 #define FLOATFMT "%.18e"
 #define FIXEDFMT "%6d"
 
diff --git a/libavcodec/cpia.c b/libavcodec/cpia.c
index 6b784b2..07cdd50 100644
--- a/libavcodec/cpia.c
+++ b/libavcodec/cpia.c
@@ -134,7 +134,7 @@ static int cpia_decode_frame(AVCodecContext *avctx,
         v_end = v + frame->linesize[2] - 1;
 
         if ((i & 1) && header[17] == SUBSAMPLE_420) {
-            /* We are on a odd line and 420 subsample is used.
+            /* We are on an odd line and 420 subsample is used.
              * On this line only Y values are specified, one per pixel.
              */
             for (j = 0; j < linelength - 1; j++) {
diff --git a/libavcodec/cuvid.c b/libavcodec/cuvid.c
new file mode 100644
index 0000000..1da0e87
--- /dev/null
+++ b/libavcodec/cuvid.c
@@ -0,0 +1,698 @@
+/*
+ * Nvidia CUVID decoder
+ * Copyright (c) 2016 Timo Rothenpieler <timo at rothenpieler.org>
+ *
+ * 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/buffer.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_cuda.h"
+#include "libavutil/fifo.h"
+#include "libavutil/log.h"
+
+#include "avcodec.h"
+#include "internal.h"
+
+#include <nvcuvid.h>
+
+#define MAX_FRAME_COUNT 20
+
+typedef struct CuvidContext
+{
+    CUvideodecoder cudecoder;
+    CUvideoparser cuparser;
+
+    AVBufferRef *hwdevice;
+    AVBufferRef *hwframe;
+
+    AVBSFContext *bsf;
+
+    AVFifoBuffer *frame_queue;
+
+    int internal_error;
+
+    cudaVideoCodec codec_type;
+    cudaVideoChromaFormat chroma_format;
+} CuvidContext;
+
+static int check_cu(AVCodecContext *avctx, CUresult err, const char *func)
+{
+    const char *err_name;
+    const char *err_string;
+
+    av_log(avctx, AV_LOG_TRACE, "Calling %s\n", func);
+
+    if (err == CUDA_SUCCESS)
+        return 0;
+
+    cuGetErrorName(err, &err_name);
+    cuGetErrorString(err, &err_string);
+
+    av_log(avctx, AV_LOG_ERROR, "%s failed", func);
+    if (err_name && err_string)
+        av_log(avctx, AV_LOG_ERROR, " -> %s: %s", err_name, err_string);
+    av_log(avctx, AV_LOG_ERROR, "\n");
+
+    return AVERROR_EXTERNAL;
+}
+
+#define CHECK_CU(x) check_cu(avctx, (x), #x)
+
+static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* format)
+{
+    AVCodecContext *avctx = opaque;
+    CuvidContext *ctx = avctx->priv_data;
+    AVHWFramesContext *hwframe_ctx = (AVHWFramesContext*)ctx->hwframe->data;
+    CUVIDDECODECREATEINFO cuinfo;
+
+    av_log(avctx, AV_LOG_TRACE, "pfnSequenceCallback\n");
+
+    ctx->internal_error = 0;
+
+    avctx->width = format->display_area.right;
+    avctx->height = format->display_area.bottom;
+
+    ff_set_sar(avctx, av_div_q(
+        (AVRational){ format->display_aspect_ratio.x, format->display_aspect_ratio.y },
+        (AVRational){ avctx->width, avctx->height }));
+
+    if (!format->progressive_sequence)
+        avctx->flags |= AV_CODEC_FLAG_INTERLACED_DCT;
+    else
+        avctx->flags &= ~AV_CODEC_FLAG_INTERLACED_DCT;
+
+    if (format->video_signal_description.video_full_range_flag)
+        avctx->color_range = AVCOL_RANGE_JPEG;
+    else
+        avctx->color_range = AVCOL_RANGE_MPEG;
+
+    avctx->color_primaries = format->video_signal_description.color_primaries;
+    avctx->color_trc = format->video_signal_description.transfer_characteristics;
+    avctx->colorspace = format->video_signal_description.matrix_coefficients;
+
+    if (format->bitrate)
+        avctx->bit_rate = format->bitrate;
+
+    if (format->frame_rate.numerator && format->frame_rate.denominator) {
+        avctx->framerate.num = format->frame_rate.numerator;
+        avctx->framerate.den = format->frame_rate.denominator;
+    }
+
+    if (ctx->cudecoder
+            && avctx->coded_width == format->coded_width
+            && avctx->coded_height == format->coded_height
+            && ctx->chroma_format == format->chroma_format
+            && ctx->codec_type == format->codec)
+        return 1;
+
+    if (ctx->cudecoder) {
+        av_log(avctx, AV_LOG_ERROR, "re-initializing decoder is not supported\n");
+        ctx->internal_error = AVERROR(EINVAL);
+        return 0;
+    }
+
+    if (hwframe_ctx->pool) {
+        av_log(avctx, AV_LOG_ERROR, "AVHWFramesContext is already initialized\n");
+        ctx->internal_error = AVERROR(EINVAL);
+        return 0;
+    }
+
+    avctx->coded_width = format->coded_width;
+    avctx->coded_height = format->coded_height;
+
+    ctx->chroma_format = format->chroma_format;
+
+    memset(&cuinfo, 0, sizeof(cuinfo));
+
+    cuinfo.CodecType = ctx->codec_type = format->codec;
+    cuinfo.ChromaFormat = format->chroma_format;
+    cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12;
+
+    cuinfo.ulWidth = avctx->coded_width;
+    cuinfo.ulHeight = avctx->coded_height;
+    cuinfo.ulTargetWidth = cuinfo.ulWidth;
+    cuinfo.ulTargetHeight = cuinfo.ulHeight;
+
+    cuinfo.target_rect.left = 0;
+    cuinfo.target_rect.top = 0;
+    cuinfo.target_rect.right = cuinfo.ulWidth;
+    cuinfo.target_rect.bottom = cuinfo.ulHeight;
+
+    cuinfo.ulNumDecodeSurfaces = MAX_FRAME_COUNT;
+    cuinfo.ulNumOutputSurfaces = 1;
+    cuinfo.ulCreationFlags = cudaVideoCreate_PreferCUVID;
+
+    cuinfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave;
+
+    ctx->internal_error = CHECK_CU(cuvidCreateDecoder(&ctx->cudecoder, &cuinfo));
+    if (ctx->internal_error < 0)
+        return 0;
+
+    hwframe_ctx->format = AV_PIX_FMT_CUDA;
+    hwframe_ctx->sw_format = AV_PIX_FMT_NV12;
+    hwframe_ctx->width = FFALIGN(avctx->coded_width, 32);
+    hwframe_ctx->height = FFALIGN(avctx->coded_height, 32);
+
+    if ((ctx->internal_error = av_hwframe_ctx_init(ctx->hwframe)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_init failed\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+static int CUDAAPI cuvid_handle_picture_decode(void *opaque, CUVIDPICPARAMS* picparams)
+{
+    AVCodecContext *avctx = opaque;
+    CuvidContext *ctx = avctx->priv_data;
+
+    av_log(avctx, AV_LOG_TRACE, "pfnDecodePicture\n");
+
+    ctx->internal_error = CHECK_CU(cuvidDecodePicture(ctx->cudecoder, picparams));
+    if (ctx->internal_error < 0)
+        return 0;
+
+    return 1;
+}
+
+static int CUDAAPI cuvid_handle_picture_display(void *opaque, CUVIDPARSERDISPINFO* dispinfo)
+{
+    AVCodecContext *avctx = opaque;
+    CuvidContext *ctx = avctx->priv_data;
+
+    av_log(avctx, AV_LOG_TRACE, "pfnDisplayPicture\n");
+
+    ctx->internal_error = 0;
+
+    av_fifo_generic_write(ctx->frame_queue, dispinfo, sizeof(CUVIDPARSERDISPINFO), NULL);
+
+    return 1;
+}
+
+static int cuvid_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
+{
+    CuvidContext *ctx = avctx->priv_data;
+    AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)ctx->hwdevice->data;
+    AVCUDADeviceContext *device_hwctx = device_ctx->hwctx;
+    CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx;
+    AVFrame *frame = data;
+    CUVIDSOURCEDATAPACKET cupkt;
+    AVPacket filter_packet = { 0 };
+    AVPacket filtered_packet = { 0 };
+    CUdeviceptr mapped_frame = 0;
+    int ret = 0, eret = 0;
+
+    if (ctx->bsf && avpkt->size) {
+        if ((ret = av_packet_ref(&filter_packet, avpkt)) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "av_packet_ref failed\n");
+            return ret;
+        }
+
+        if ((ret = av_bsf_send_packet(ctx->bsf, &filter_packet)) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "av_bsf_send_packet failed\n");
+            av_packet_unref(&filter_packet);
+            return ret;
+        }
+
+        if ((ret = av_bsf_receive_packet(ctx->bsf, &filtered_packet)) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "av_bsf_receive_packet failed\n");
+            return ret;
+        }
+
+        avpkt = &filtered_packet;
+    }
+
+    ret = CHECK_CU(cuCtxPushCurrent(cuda_ctx));
+    if (ret < 0) {
+        av_packet_unref(&filtered_packet);
+        return ret;
+    }
+
+    memset(&cupkt, 0, sizeof(cupkt));
+
+    if (avpkt->size) {
+        cupkt.payload_size = avpkt->size;
+        cupkt.payload = avpkt->data;
+
+        if (avpkt->pts != AV_NOPTS_VALUE) {
+            cupkt.flags = CUVID_PKT_TIMESTAMP;
+            cupkt.timestamp = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1, 10000000});
+        }
+    } else {
+        cupkt.flags = CUVID_PKT_ENDOFSTREAM;
+    }
+
+    ret = CHECK_CU(cuvidParseVideoData(ctx->cuparser, &cupkt));
+
+    av_packet_unref(&filtered_packet);
+
+    if (ret < 0) {
+        if (ctx->internal_error)
+            ret = ctx->internal_error;
+        goto error;
+    }
+
+    if (av_fifo_size(ctx->frame_queue)) {
+        CUVIDPARSERDISPINFO dispinfo;
+        CUVIDPROCPARAMS params;
+        unsigned int pitch = 0;
+        int offset = 0;
+        int i;
+
+        av_fifo_generic_read(ctx->frame_queue, &dispinfo, sizeof(CUVIDPARSERDISPINFO), NULL);
+
+        memset(&params, 0, sizeof(params));
+        params.progressive_frame = dispinfo.progressive_frame;
+        params.second_field = 0;
+        params.top_field_first = dispinfo.top_field_first;
+
+        ret = CHECK_CU(cuvidMapVideoFrame(ctx->cudecoder, dispinfo.picture_index, &mapped_frame, &pitch, &params));
+        if (ret < 0)
+            goto error;
+
+        if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
+            ret = av_hwframe_get_buffer(ctx->hwframe, frame, 0);
+            if (ret < 0) {
+                av_log(avctx, AV_LOG_ERROR, "av_hwframe_get_buffer failed\n");
+                goto error;
+            }
+
+            ret = ff_decode_frame_props(avctx, frame);
+            if (ret < 0) {
+                av_log(avctx, AV_LOG_ERROR, "ff_decode_frame_props failed\n");
+                goto error;
+            }
+
+            for (i = 0; i < 2; i++) {
+                CUDA_MEMCPY2D cpy = {
+                    .srcMemoryType = CU_MEMORYTYPE_DEVICE,
+                    .dstMemoryType = CU_MEMORYTYPE_DEVICE,
+                    .srcDevice     = mapped_frame,
+                    .dstDevice     = (CUdeviceptr)frame->data[i],
+                    .srcPitch      = pitch,
+                    .dstPitch      = frame->linesize[i],
+                    .srcY          = offset,
+                    .WidthInBytes  = FFMIN(pitch, frame->linesize[i]),
+                    .Height        = avctx->coded_height >> (i ? 1 : 0),
+                };
+
+                ret = CHECK_CU(cuMemcpy2D(&cpy));
+                if (ret < 0)
+                    goto error;
+
+                offset += avctx->coded_height;
+            }
+        } else if (avctx->pix_fmt == AV_PIX_FMT_NV12) {
+            AVFrame *tmp_frame = av_frame_alloc();
+            if (!tmp_frame) {
+                av_log(avctx, AV_LOG_ERROR, "av_frame_alloc failed\n");
+                ret = AVERROR(ENOMEM);
+                goto error;
+            }
+
+            tmp_frame->format        = AV_PIX_FMT_CUDA;
+            tmp_frame->hw_frames_ctx = av_buffer_ref(ctx->hwframe);
+            tmp_frame->data[0]       = (uint8_t*)mapped_frame;
+            tmp_frame->linesize[0]   = pitch;
+            tmp_frame->data[1]       = (uint8_t*)(mapped_frame + avctx->coded_height * pitch);
+            tmp_frame->linesize[1]   = pitch;
+            tmp_frame->width         = avctx->width;
+            tmp_frame->height        = avctx->height;
+
+            ret = ff_get_buffer(avctx, frame, 0);
+            if (ret < 0) {
+                av_log(avctx, AV_LOG_ERROR, "ff_get_buffer failed\n");
+                av_frame_free(&tmp_frame);
+                goto error;
+            }
+
+            ret = av_hwframe_transfer_data(frame, tmp_frame, 0);
+            if (ret) {
+                av_log(avctx, AV_LOG_ERROR, "av_hwframe_transfer_data failed\n");
+                av_frame_free(&tmp_frame);
+                goto error;
+            }
+
+            av_frame_free(&tmp_frame);
+        } else {
+            ret = AVERROR_BUG;
+            goto error;
+        }
+
+        frame->width = avctx->width;
+        frame->height = avctx->height;
+        frame->pts = av_rescale_q(dispinfo.timestamp, (AVRational){1, 10000000}, avctx->time_base);
+
+        /* CUVIDs opaque reordering breaks the internal pkt logic.
+         * So set pkt_pts and clear all the other pkt_ fields.
+         */
+        frame->pkt_pts = frame->pts;
+        av_frame_set_pkt_pos(frame, -1);
+        av_frame_set_pkt_duration(frame, 0);
+        av_frame_set_pkt_size(frame, -1);
+
+        frame->interlaced_frame = !dispinfo.progressive_frame;
+
+        if (!dispinfo.progressive_frame)
+            frame->top_field_first = dispinfo.top_field_first;
+
+        *got_frame = 1;
+    } else {
+        *got_frame = 0;
+    }
+
+error:
+    if (mapped_frame)
+        eret = CHECK_CU(cuvidUnmapVideoFrame(ctx->cudecoder, mapped_frame));
+
+    eret = CHECK_CU(cuCtxPopCurrent(&dummy));
+
+    if (eret < 0)
+        return eret;
+    else
+        return ret;
+}
+
+static av_cold int cuvid_decode_end(AVCodecContext *avctx)
+{
+    CuvidContext *ctx = avctx->priv_data;
+
+    av_fifo_freep(&ctx->frame_queue);
+
+    if (ctx->bsf)
+        av_bsf_free(&ctx->bsf);
+
+    if (ctx->cuparser)
+        cuvidDestroyVideoParser(ctx->cuparser);
+
+    if (ctx->cudecoder)
+        cuvidDestroyDecoder(ctx->cudecoder);
+
+    av_buffer_unref(&ctx->hwframe);
+    av_buffer_unref(&ctx->hwdevice);
+
+    return 0;
+}
+
+static void cuvid_ctx_free(AVHWDeviceContext *ctx)
+{
+    AVCUDADeviceContext *hwctx = ctx->hwctx;
+    cuCtxDestroy(hwctx->cuda_ctx);
+}
+
+static int cuvid_test_dummy_decoder(AVCodecContext *avctx, CUVIDPARSERPARAMS *cuparseinfo)
+{
+    CUVIDDECODECREATEINFO cuinfo;
+    CUvideodecoder cudec = 0;
+    int ret = 0;
+
+    memset(&cuinfo, 0, sizeof(cuinfo));
+
+    cuinfo.CodecType = cuparseinfo->CodecType;
+    cuinfo.ChromaFormat = cudaVideoChromaFormat_420;
+    cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12;
+
+    cuinfo.ulWidth = 1280;
+    cuinfo.ulHeight = 720;
+    cuinfo.ulTargetWidth = cuinfo.ulWidth;
+    cuinfo.ulTargetHeight = cuinfo.ulHeight;
+
+    cuinfo.target_rect.left = 0;
+    cuinfo.target_rect.top = 0;
+    cuinfo.target_rect.right = cuinfo.ulWidth;
+    cuinfo.target_rect.bottom = cuinfo.ulHeight;
+
+    cuinfo.ulNumDecodeSurfaces = MAX_FRAME_COUNT;
+    cuinfo.ulNumOutputSurfaces = 1;
+    cuinfo.ulCreationFlags = cudaVideoCreate_PreferCUVID;
+
+    cuinfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave;
+
+    ret = CHECK_CU(cuvidCreateDecoder(&cudec, &cuinfo));
+    if (ret < 0)
+        return ret;
+
+    ret = CHECK_CU(cuvidDestroyDecoder(cudec));
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
+static av_cold int cuvid_decode_init(AVCodecContext *avctx)
+{
+    CuvidContext *ctx = avctx->priv_data;
+    AVCUDADeviceContext *device_hwctx;
+    AVHWDeviceContext *device_ctx;
+    AVHWFramesContext *hwframe_ctx;
+    CUVIDPARSERPARAMS cuparseinfo;
+    CUVIDEOFORMATEX cuparse_ext;
+    CUVIDSOURCEDATAPACKET seq_pkt;
+    CUdevice device;
+    CUcontext cuda_ctx = NULL;
+    CUcontext dummy;
+    const AVBitStreamFilter *bsf;
+    int ret = 0;
+
+    enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_CUDA,
+                                       AV_PIX_FMT_NV12,
+                                       AV_PIX_FMT_NONE };
+
+    ret = ff_get_format(avctx, pix_fmts);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR, "ff_get_format failed: %d\n", ret);
+        return ret;
+    }
+
+    ctx->frame_queue = av_fifo_alloc(MAX_FRAME_COUNT * sizeof(CUVIDPARSERDISPINFO));
+    if (!ctx->frame_queue) {
+        ret = AVERROR(ENOMEM);
+        goto error;
+    }
+
+    avctx->pix_fmt = ret;
+
+    if (avctx->hw_frames_ctx) {
+        ctx->hwframe = av_buffer_ref(avctx->hw_frames_ctx);
+        if (!ctx->hwframe) {
+            ret = AVERROR(ENOMEM);
+            goto error;
+        }
+
+        hwframe_ctx = (AVHWFramesContext*)ctx->hwframe->data;
+
+        ctx->hwdevice = av_buffer_ref(hwframe_ctx->device_ref);
+        if (!ctx->hwdevice) {
+            ret = AVERROR(ENOMEM);
+            goto error;
+        }
+
+        device_ctx = hwframe_ctx->device_ctx;
+        device_hwctx = device_ctx->hwctx;
+        cuda_ctx = device_hwctx->cuda_ctx;
+    } else {
+        ctx->hwdevice = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA);
+        if (!ctx->hwdevice) {
+            av_log(avctx, AV_LOG_ERROR, "Error allocating hwdevice\n");
+            ret = AVERROR(ENOMEM);
+            goto error;
+        }
+
+        ret = CHECK_CU(cuInit(0));
+        if (ret < 0)
+            goto error;
+
+        ret = CHECK_CU(cuDeviceGet(&device, 0));
+        if (ret < 0)
+            goto error;
+
+        ret = CHECK_CU(cuCtxCreate(&cuda_ctx, CU_CTX_SCHED_BLOCKING_SYNC, device));
+        if (ret < 0)
+            goto error;
+
+        device_ctx = (AVHWDeviceContext*)ctx->hwdevice->data;
+        device_ctx->free = cuvid_ctx_free;
+
+        device_hwctx = device_ctx->hwctx;
+        device_hwctx->cuda_ctx = cuda_ctx;
+
+        ret = CHECK_CU(cuCtxPopCurrent(&dummy));
+        if (ret < 0)
+            goto error;
+
+        ret = av_hwdevice_ctx_init(ctx->hwdevice);
+        if (ret < 0) {
+            av_log(avctx, AV_LOG_ERROR, "av_hwdevice_ctx_init failed\n");
+            goto error;
+        }
+
+        ctx->hwframe = av_hwframe_ctx_alloc(ctx->hwdevice);
+        if (!ctx->hwframe) {
+            av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_alloc failed\n");
+            ret = AVERROR(ENOMEM);
+            goto error;
+        }
+    }
+
+    memset(&cuparseinfo, 0, sizeof(cuparseinfo));
+    memset(&cuparse_ext, 0, sizeof(cuparse_ext));
+    memset(&seq_pkt, 0, sizeof(seq_pkt));
+
+    cuparseinfo.pExtVideoInfo = &cuparse_ext;
+
+    switch (avctx->codec->id) {
+#if CONFIG_H264_CUVID_DECODER
+    case AV_CODEC_ID_H264:
+        cuparseinfo.CodecType = cudaVideoCodec_H264;
+        break;
+#endif
+#if CONFIG_HEVC_CUVID_DECODER
+    case AV_CODEC_ID_HEVC:
+        cuparseinfo.CodecType = cudaVideoCodec_HEVC;
+        break;
+#endif
+#if CONFIG_VP8_CUVID_DECODER
+    case AV_CODEC_ID_VP8:
+        cuparseinfo.CodecType = cudaVideoCodec_VP8;
+        break;
+#endif
+#if CONFIG_VP9_CUVID_DECODER
+    case AV_CODEC_ID_VP9:
+        cuparseinfo.CodecType = cudaVideoCodec_VP9;
+        break;
+#endif
+#if CONFIG_VC1_CUVID_DECODER
+    case AV_CODEC_ID_VC1:
+        cuparseinfo.CodecType = cudaVideoCodec_VC1;
+        break;
+#endif
+    default:
+        av_log(avctx, AV_LOG_ERROR, "Invalid CUVID codec!\n");
+        return AVERROR_BUG;
+    }
+
+    if (avctx->codec->id == AV_CODEC_ID_H264 || avctx->codec->id == AV_CODEC_ID_HEVC) {
+        if (avctx->codec->id == AV_CODEC_ID_H264)
+            bsf = av_bsf_get_by_name("h264_mp4toannexb");
+        else
+            bsf = av_bsf_get_by_name("hevc_mp4toannexb");
+
+        if (!bsf) {
+            ret = AVERROR_BSF_NOT_FOUND;
+            goto error;
+        }
+        if (ret = av_bsf_alloc(bsf, &ctx->bsf)) {
+            goto error;
+        }
+        if (((ret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx)) < 0) || ((ret = av_bsf_init(ctx->bsf)) < 0)) {
+            av_bsf_free(&ctx->bsf);
+            goto error;
+        }
+
+        cuparse_ext.format.seqhdr_data_length = ctx->bsf->par_out->extradata_size;
+        memcpy(cuparse_ext.raw_seqhdr_data,
+               ctx->bsf->par_out->extradata,
+               FFMIN(sizeof(cuparse_ext.raw_seqhdr_data), ctx->bsf->par_out->extradata_size));
+    } else if (avctx->extradata_size > 0) {
+        cuparse_ext.format.seqhdr_data_length = avctx->extradata_size;
+        memcpy(cuparse_ext.raw_seqhdr_data,
+               avctx->extradata,
+               FFMIN(sizeof(cuparse_ext.raw_seqhdr_data), avctx->extradata_size));
+    }
+
+    cuparseinfo.ulMaxNumDecodeSurfaces = MAX_FRAME_COUNT;
+    cuparseinfo.ulMaxDisplayDelay = 4;
+    cuparseinfo.pUserData = avctx;
+    cuparseinfo.pfnSequenceCallback = cuvid_handle_video_sequence;
+    cuparseinfo.pfnDecodePicture = cuvid_handle_picture_decode;
+    cuparseinfo.pfnDisplayPicture = cuvid_handle_picture_display;
+
+    ret = CHECK_CU(cuCtxPushCurrent(cuda_ctx));
+    if (ret < 0)
+        goto error;
+
+    ret = cuvid_test_dummy_decoder(avctx, &cuparseinfo);
+    if (ret < 0)
+        goto error;
+
+    ret = CHECK_CU(cuvidCreateVideoParser(&ctx->cuparser, &cuparseinfo));
+    if (ret < 0)
+        goto error;
+
+    seq_pkt.payload = cuparse_ext.raw_seqhdr_data;
+    seq_pkt.payload_size = cuparse_ext.format.seqhdr_data_length;
+
+    if (seq_pkt.payload && seq_pkt.payload_size) {
+        ret = CHECK_CU(cuvidParseVideoData(ctx->cuparser, &seq_pkt));
+        if (ret < 0)
+            goto error;
+    }
+
+    ret = CHECK_CU(cuCtxPopCurrent(&dummy));
+    if (ret < 0)
+        goto error;
+
+    return 0;
+
+error:
+    cuvid_decode_end(avctx);
+    return ret;
+}
+
+#define DEFINE_CUVID_CODEC(x, X) \
+    AVHWAccel ff_##x##_cuvid_hwaccel = { \
+        .name           = #x "_cuvid", \
+        .type           = AVMEDIA_TYPE_VIDEO, \
+        .id             = AV_CODEC_ID_##X, \
+        .pix_fmt        = AV_PIX_FMT_CUDA, \
+    }; \
+    AVCodec ff_##x##_cuvid_decoder = { \
+        .name           = #x "_cuvid", \
+        .long_name      = NULL_IF_CONFIG_SMALL("Nvidia CUVID " #X " decoder"), \
+        .type           = AVMEDIA_TYPE_VIDEO, \
+        .id             = AV_CODEC_ID_##X, \
+        .priv_data_size = sizeof(CuvidContext), \
+        .init           = cuvid_decode_init, \
+        .close          = cuvid_decode_end, \
+        .decode         = cuvid_decode_frame, \
+        .capabilities   = AV_CODEC_CAP_DELAY, \
+        .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, \
+                                                        AV_PIX_FMT_NV12, \
+                                                        AV_PIX_FMT_NONE }, \
+    };
+
+#if CONFIG_HEVC_CUVID_DECODER
+DEFINE_CUVID_CODEC(hevc, HEVC)
+#endif
+
+#if CONFIG_H264_CUVID_DECODER
+DEFINE_CUVID_CODEC(h264, H264)
+#endif
+
+#if CONFIG_VP8_CUVID_DECODER
+DEFINE_CUVID_CODEC(vp8, VP8)
+#endif
+
+#if CONFIG_VP9_CUVID_DECODER
+DEFINE_CUVID_CODEC(vp9, VP9)
+#endif
+
+#if CONFIG_VC1_CUVID_DECODER
+DEFINE_CUVID_CODEC(vc1, VC1)
+#endif
diff --git a/libavcodec/cyuv.c b/libavcodec/cyuv.c
index c7ec008..8e6749b 100644
--- a/libavcodec/cyuv.c
+++ b/libavcodec/cyuv.c
@@ -4,7 +4,7 @@
  * based on "Creative YUV (CYUV) stream format for AVI":
  *   http://www.csse.monash.edu.au/~timf/videocodec/cyuv.txt
  *
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/dca.c b/libavcodec/dca.c
index 714509b..58f340e 100644
--- a/libavcodec/dca.c
+++ b/libavcodec/dca.c
@@ -36,6 +36,15 @@ const uint32_t avpriv_dca_sample_rates[16] = {
     12000, 24000, 48000, 96000, 192000
 };
 
+const uint32_t ff_dca_sampling_freqs[16] = {
+      8000,  16000, 32000, 64000, 128000, 22050,  44100,  88200,
+    176400, 352800, 12000, 24000,  48000, 96000, 192000, 384000,
+};
+
+const uint8_t ff_dca_freq_ranges[16] = {
+    0, 1, 2, 3, 4, 1, 2, 3, 4, 4, 0, 1, 2, 3, 4, 4
+};
+
 int avpriv_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst,
                              int max_size)
 {
@@ -49,6 +58,7 @@ int avpriv_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst,
     mrk = AV_RB32(src);
     switch (mrk) {
     case DCA_SYNCWORD_CORE_BE:
+    case DCA_SYNCWORD_SUBSTREAM:
         memcpy(dst, src, src_size);
         return src_size;
     case DCA_SYNCWORD_CORE_LE:
diff --git a/libavcodec/dca.h b/libavcodec/dca.h
index ccb02af..bd96bc9 100644
--- a/libavcodec/dca.h
+++ b/libavcodec/dca.h
@@ -28,6 +28,7 @@
 
 #include <stdint.h>
 
+#include "libavutil/common.h"
 #include "libavutil/internal.h"
 #include "libavutil/intreadwrite.h"
 
@@ -90,6 +91,33 @@ enum DCASpeakerMask {
 #define DCA_HAS_STEREO(mask) \
     ((mask & DCA_SPEAKER_LAYOUT_STEREO) == DCA_SPEAKER_LAYOUT_STEREO)
 
+enum DCASpeakerPair {
+    DCA_SPEAKER_PAIR_C      = 0x0001,
+    DCA_SPEAKER_PAIR_LR     = 0x0002,
+    DCA_SPEAKER_PAIR_LsRs   = 0x0004,
+    DCA_SPEAKER_PAIR_LFE1   = 0x0008,
+    DCA_SPEAKER_PAIR_Cs     = 0x0010,
+    DCA_SPEAKER_PAIR_LhRh   = 0x0020,
+    DCA_SPEAKER_PAIR_LsrRsr = 0x0040,
+    DCA_SPEAKER_PAIR_Ch     = 0x0080,
+    DCA_SPEAKER_PAIR_Oh     = 0x0100,
+    DCA_SPEAKER_PAIR_LcRc   = 0x0200,
+    DCA_SPEAKER_PAIR_LwRw   = 0x0400,
+    DCA_SPEAKER_PAIR_LssRss = 0x0800,
+    DCA_SPEAKER_PAIR_LFE2   = 0x1000,
+    DCA_SPEAKER_PAIR_LhsRhs = 0x2000,
+    DCA_SPEAKER_PAIR_Chr    = 0x4000,
+    DCA_SPEAKER_PAIR_LhrRhr = 0x8000
+};
+
+/**
+ * Return number of individual channels in DCASpeakerPair mask
+ */
+static inline int ff_dca_count_chs_for_mask(unsigned int mask)
+{
+    return av_popcount((mask & 0xffff) | ((mask & 0xae66) << 16));
+}
+
 enum DCARepresentationType {
     DCA_REPR_TYPE_LtRt = 2,
     DCA_REPR_TYPE_LhRh = 3
@@ -126,6 +154,9 @@ enum DCADownMixType {
 
 extern av_export const uint32_t avpriv_dca_sample_rates[16];
 
+extern const uint32_t ff_dca_sampling_freqs[16];
+extern const uint8_t ff_dca_freq_ranges[16];
+
 /**
  * Convert bitstream to one representation based on sync marker
  */
diff --git a/libavcodec/dca_core.c b/libavcodec/dca_core.c
index d9f1a4c..46825ed 100644
--- a/libavcodec/dca_core.c
+++ b/libavcodec/dca_core.c
@@ -100,62 +100,6 @@ static const uint8_t quant_index_group_size[DCA_CODE_BOOKS] = {
     1, 3, 3, 3, 3, 7, 7, 7, 7, 7
 };
 
-typedef struct DCAVLC {
-    int offset;         ///< Code values offset
-    int max_depth;      ///< Parameter for get_vlc2()
-    VLC vlc[7];         ///< Actual codes
-} DCAVLC;
-
-static DCAVLC   vlc_bit_allocation;
-static DCAVLC   vlc_transition_mode;
-static DCAVLC   vlc_scale_factor;
-static DCAVLC   vlc_quant_index[DCA_CODE_BOOKS];
-
-static av_cold void dca_init_vlcs(void)
-{
-    static VLC_TYPE dca_table[23622][2];
-    static int vlcs_initialized = 0;
-    int i, j, k;
-
-    if (vlcs_initialized)
-        return;
-
-#define DCA_INIT_VLC(vlc, a, b, c, d)                                      \
-    do {                                                                   \
-        vlc.table           = &dca_table[ff_dca_vlc_offs[k]];              \
-        vlc.table_allocated = ff_dca_vlc_offs[k + 1] - ff_dca_vlc_offs[k]; \
-        init_vlc(&vlc, a, b, c, 1, 1, d, 2, 2, INIT_VLC_USE_NEW_STATIC);   \
-    } while (0)
-
-    vlc_bit_allocation.offset    = 1;
-    vlc_bit_allocation.max_depth = 2;
-    for (i = 0, k = 0; i < 5; i++, k++)
-        DCA_INIT_VLC(vlc_bit_allocation.vlc[i], bitalloc_12_vlc_bits[i], 12,
-                     bitalloc_12_bits[i], bitalloc_12_codes[i]);
-
-    vlc_scale_factor.offset    = -64;
-    vlc_scale_factor.max_depth = 2;
-    for (i = 0; i < 5; i++, k++)
-        DCA_INIT_VLC(vlc_scale_factor.vlc[i], SCALES_VLC_BITS, 129,
-                     scales_bits[i], scales_codes[i]);
-
-    vlc_transition_mode.offset    = 0;
-    vlc_transition_mode.max_depth = 1;
-    for (i = 0; i < 4; i++, k++)
-        DCA_INIT_VLC(vlc_transition_mode.vlc[i], tmode_vlc_bits[i], 4,
-                     tmode_bits[i], tmode_codes[i]);
-
-    for (i = 0; i < DCA_CODE_BOOKS; i++) {
-        vlc_quant_index[i].offset    = bitalloc_offsets[i];
-        vlc_quant_index[i].max_depth = 1 + (i > 4);
-        for (j = 0; j < quant_index_group_size[i]; j++, k++)
-            DCA_INIT_VLC(vlc_quant_index[i].vlc[j], bitalloc_maxbits[i][j],
-                         bitalloc_sizes[i], bitalloc_bits[i][j], bitalloc_codes[i][j]);
-    }
-
-    vlcs_initialized = 1;
-}
-
 static int dca_get_vlc(GetBitContext *s, DCAVLC *v, int i)
 {
     return get_vlc2(s, v->vlc[i].table, v->vlc[i].bits, v->max_depth) + v->offset;
@@ -325,8 +269,7 @@ static int parse_coding_header(DCACoreDecoder *s, enum HeaderType header, int xc
 
         // Check CRC
         if (s->xxch_crc_present
-            && (s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-            && ff_dca_check_crc(&s->gb, header_pos, header_pos + header_size * 8)) {
+            && ff_dca_check_crc(s->avctx, &s->gb, header_pos, header_pos + header_size * 8)) {
             av_log(s->avctx, AV_LOG_ERROR, "Invalid XXCH channel set header checksum\n");
             return AVERROR_INVALIDDATA;
         }
@@ -498,7 +441,7 @@ static inline int parse_scale(DCACoreDecoder *s, int *scale_index, int sel)
 
     // If Huffman code was used, the difference of scales was encoded
     if (sel < 5)
-        *scale_index += dca_get_vlc(&s->gb, &vlc_scale_factor, sel);
+        *scale_index += dca_get_vlc(&s->gb, &ff_dca_vlc_scale_factor, sel);
     else
         *scale_index = get_bits(&s->gb, sel + 1);
 
@@ -517,7 +460,7 @@ static inline int parse_joint_scale(DCACoreDecoder *s, int sel)
 
     // Absolute value was encoded even when Huffman code was used
     if (sel < 5)
-        scale_index = dca_get_vlc(&s->gb, &vlc_scale_factor, sel);
+        scale_index = dca_get_vlc(&s->gb, &ff_dca_vlc_scale_factor, sel);
     else
         scale_index = get_bits(&s->gb, sel + 1);
 
@@ -569,7 +512,7 @@ static int parse_subframe_header(DCACoreDecoder *s, int sf,
             int abits;
 
             if (sel < 5)
-                abits = dca_get_vlc(&s->gb, &vlc_bit_allocation, sel);
+                abits = dca_get_vlc(&s->gb, &ff_dca_vlc_bit_allocation, sel);
             else
                 abits = get_bits(&s->gb, sel - 1);
 
@@ -592,7 +535,7 @@ static int parse_subframe_header(DCACoreDecoder *s, int sf,
             int sel = s->transition_mode_sel[ch];
             for (band = 0; band < s->subband_vq_start[ch]; band++)
                 if (s->bit_allocation[ch][band])
-                    s->transition_mode[sf][ch][band] = dca_get_vlc(&s->gb, &vlc_transition_mode, sel);
+                    s->transition_mode[sf][ch][band] = dca_get_vlc(&s->gb, &ff_dca_vlc_transition_mode, sel);
         }
     }
 
@@ -703,7 +646,7 @@ static inline int parse_huffman_codes(DCACoreDecoder *s, int32_t *audio, int abi
 
     // Extract Huffman codes from the bit stream
     for (i = 0; i < DCA_SUBBAND_SAMPLES; i++)
-        audio[i] = dca_get_vlc(&s->gb, &vlc_quant_index[abits - 1], sel);
+        audio[i] = dca_get_vlc(&s->gb, &ff_dca_vlc_quant_index[abits - 1], sel);
 
     return 1;
 }
@@ -1033,8 +976,7 @@ static int parse_xxch_frame(DCACoreDecoder *s)
     header_size = get_bits(&s->gb, 6) + 1;
 
     // Check XXCH frame header CRC
-    if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-        && ff_dca_check_crc(&s->gb, header_pos + 32, header_pos + header_size * 8)) {
+    if (ff_dca_check_crc(s->avctx, &s->gb, header_pos + 32, header_pos + header_size * 8)) {
         av_log(s->avctx, AV_LOG_ERROR, "Invalid XXCH frame header checksum\n");
         return AVERROR_INVALIDDATA;
     }
@@ -1249,8 +1191,7 @@ static int parse_xbr_frame(DCACoreDecoder *s)
     header_size = get_bits(&s->gb, 6) + 1;
 
     // Check XBR frame header CRC
-    if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-        && ff_dca_check_crc(&s->gb, header_pos + 32, header_pos + header_size * 8)) {
+    if (ff_dca_check_crc(s->avctx, &s->gb, header_pos + 32, header_pos + header_size * 8)) {
         av_log(s->avctx, AV_LOG_ERROR, "Invalid XBR frame header checksum\n");
         return AVERROR_INVALIDDATA;
     }
@@ -1494,7 +1435,7 @@ static int parse_x96_subframe_header(DCACoreDecoder *s, int xch_base)
         for (band = s->x96_subband_start; band < s->nsubbands[ch]; band++) {
             // If Huffman code was used, the difference of abits was encoded
             if (sel < 7)
-                abits += dca_get_vlc(&s->gb, &vlc_quant_index[5 + 2 * s->x96_high_res], sel);
+                abits += dca_get_vlc(&s->gb, &ff_dca_vlc_quant_index[5 + 2 * s->x96_high_res], sel);
             else
                 abits = get_bits(&s->gb, 3 + s->x96_high_res);
 
@@ -1565,8 +1506,7 @@ static int parse_x96_coding_header(DCACoreDecoder *s, int exss, int xch_base)
 
         // Check CRC
         if (s->x96_crc_present
-            && (s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-            && ff_dca_check_crc(&s->gb, header_pos, header_pos + header_size * 8)) {
+            && ff_dca_check_crc(s->avctx, &s->gb, header_pos, header_pos + header_size * 8)) {
             av_log(s->avctx, AV_LOG_ERROR, "Invalid X96 channel set header checksum\n");
             return AVERROR_INVALIDDATA;
         }
@@ -1721,8 +1661,7 @@ static int parse_x96_frame_exss(DCACoreDecoder *s)
     header_size = get_bits(&s->gb, 6) + 1;
 
     // Check X96 frame header CRC
-    if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-        && ff_dca_check_crc(&s->gb, header_pos + 32, header_pos + header_size * 8)) {
+    if (ff_dca_check_crc(s->avctx, &s->gb, header_pos + 32, header_pos + header_size * 8)) {
         av_log(s->avctx, AV_LOG_ERROR, "Invalid X96 frame header checksum\n");
         return AVERROR_INVALIDDATA;
     }
@@ -1841,8 +1780,7 @@ static int parse_aux_data(DCACoreDecoder *s)
     skip_bits(&s->gb, 16);
 
     // Check CRC
-    if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-        && ff_dca_check_crc(&s->gb, aux_pos, get_bits_count(&s->gb))) {
+    if (ff_dca_check_crc(s->avctx, &s->gb, aux_pos, get_bits_count(&s->gb))) {
         av_log(s->avctx, AV_LOG_ERROR, "Invalid auxiliary data checksum\n");
         return AVERROR_INVALIDDATA;
     }
@@ -1900,9 +1838,10 @@ static int parse_optional_info(DCACoreDecoder *s)
                 }
             }
 
-            if (s->avctx->err_recognition & AV_EF_EXPLODE) {
+            if (!s->xch_pos) {
                 av_log(s->avctx, AV_LOG_ERROR, "XCH sync word not found\n");
-                return AVERROR_INVALIDDATA;
+                if (s->avctx->err_recognition & AV_EF_EXPLODE)
+                    return AVERROR_INVALIDDATA;
             }
             break;
 
@@ -1922,9 +1861,10 @@ static int parse_optional_info(DCACoreDecoder *s)
                 }
             }
 
-            if (s->avctx->err_recognition & AV_EF_EXPLODE) {
+            if (!s->x96_pos) {
                 av_log(s->avctx, AV_LOG_ERROR, "X96 sync word not found\n");
-                return AVERROR_INVALIDDATA;
+                if (s->avctx->err_recognition & AV_EF_EXPLODE)
+                    return AVERROR_INVALIDDATA;
             }
             break;
 
@@ -1938,18 +1878,20 @@ static int parse_optional_info(DCACoreDecoder *s)
                 if (AV_RB32(s->gb.buffer + sync_pos * 4) == DCA_SYNCWORD_XXCH) {
                     s->gb.index = (sync_pos + 1) * 32;
                     size = get_bits(&s->gb, 6) + 1;
-                    if (size >= 11 &&
-                        !ff_dca_check_crc(&s->gb, (sync_pos + 1) * 32,
-                                          sync_pos * 32 + size * 8)) {
+                    dist = s->gb.size_in_bits / 8 - sync_pos * 4;
+                    if (size >= 11 && size <= dist &&
+                        !av_crc(dca->crctab, 0xffff, s->gb.buffer +
+                                (sync_pos + 1) * 4, size - 4)) {
                         s->xxch_pos = sync_pos * 32;
                         break;
                     }
                 }
             }
 
-            if (s->avctx->err_recognition & AV_EF_EXPLODE) {
+            if (!s->xxch_pos) {
                 av_log(s->avctx, AV_LOG_ERROR, "XXCH sync word not found\n");
-                return AVERROR_INVALIDDATA;
+                if (s->avctx->err_recognition & AV_EF_EXPLODE)
+                    return AVERROR_INVALIDDATA;
             }
             break;
         }
@@ -1979,10 +1921,8 @@ int ff_dca_core_parse(DCACoreDecoder *s, uint8_t *data, int size)
         return ret;
 
     // Workaround for DTS in WAV
-    if (s->frame_size > size && s->frame_size < size + 4) {
-        av_log(s->avctx, AV_LOG_DEBUG, "Working around excessive core frame size (%d > %d)\n", s->frame_size, size);
+    if (s->frame_size > size && s->frame_size < size + 4)
         s->frame_size = size;
-    }
 
     if (ff_dca_seek_bits(&s->gb, s->frame_size * 8)) {
         av_log(s->avctx, AV_LOG_ERROR, "Read past end of core frame\n");
@@ -2575,8 +2515,6 @@ av_cold void ff_dca_core_flush(DCACoreDecoder *s)
 
 av_cold int ff_dca_core_init(DCACoreDecoder *s)
 {
-    dca_init_vlcs();
-
     if (!(s->float_dsp = avpriv_float_dsp_alloc(0)))
         return -1;
     if (!(s->fixed_dsp = avpriv_alloc_fixed_dsp(0)))
diff --git a/libavcodec/dca_core.h b/libavcodec/dca_core.h
index 112b72b..e84bdab 100644
--- a/libavcodec/dca_core.h
+++ b/libavcodec/dca_core.h
@@ -33,6 +33,7 @@
 #include "dca_exss.h"
 #include "dcadsp.h"
 #include "dcadct.h"
+#include "dcahuff.h"
 #include "fft.h"
 #include "synth_filter.h"
 
@@ -44,7 +45,6 @@
 #define DCA_PCMBLOCK_SAMPLES    32
 #define DCA_ADPCM_COEFFS        4
 #define DCA_LFE_HISTORY         8
-#define DCA_CODE_BOOKS          10
 #define DCA_ABITS_MAX           26
 
 #define DCA_CORE_CHANNELS_MAX       6
diff --git a/libavcodec/dca_core_bsf.c b/libavcodec/dca_core_bsf.c
new file mode 100644
index 0000000..9edc0cf
--- /dev/null
+++ b/libavcodec/dca_core_bsf.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avcodec.h"
+#include "bsf.h"
+#include "bytestream.h"
+#include "dca_syncwords.h"
+#include "libavutil/mem.h"
+
+static int dca_core_filter(AVBSFContext *ctx, AVPacket *out)
+{
+    AVPacket *in;
+    GetByteContext gb;
+    uint32_t syncword;
+    int core_size = 0, ret;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    bytestream2_init(&gb, in->data, in->size);
+    syncword = bytestream2_get_be32(&gb);
+    bytestream2_skip(&gb, 1);
+
+    switch (syncword) {
+    case DCA_SYNCWORD_CORE_BE:
+        core_size = ((bytestream2_get_be24(&gb) >> 4) & 0x3fff) + 1;
+        break;
+    }
+
+    av_packet_move_ref(out, in);
+    av_packet_free(&in);
+
+    if (core_size > 0 && core_size <= out->size) {
+        out->size = core_size;
+    }
+
+    return 0;
+}
+
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_DTS, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_dca_core_bsf = {
+    .name      = "dca_core",
+    .filter    = dca_core_filter,
+    .codec_ids = codec_ids,
+};
diff --git a/libavcodec/dca_exss.c b/libavcodec/dca_exss.c
index 4579f23..e873088 100644
--- a/libavcodec/dca_exss.c
+++ b/libavcodec/dca_exss.c
@@ -19,12 +19,6 @@
  */
 
 #include "dcadec.h"
-#include "dcadata.h"
-
-static int count_chs_for_mask(int mask)
-{
-    return av_popcount(mask) + av_popcount(mask & 0xae66);
-}
 
 static void parse_xll_parameters(DCAExssParser *s, DCAExssAsset *asset)
 {
@@ -117,12 +111,10 @@ static int parse_descriptor(DCAExssParser *s, DCAExssAsset *asset)
             int nspeakers[8];
 
             // Embedded stereo flag
-            if (asset->nchannels_total > 2)
-                asset->embedded_stereo = get_bits1(&s->gb);
+            asset->embedded_stereo = asset->nchannels_total > 2 && get_bits1(&s->gb);
 
             // Embedded 6 channels flag
-            if (asset->nchannels_total > 6)
-                asset->embedded_6ch = get_bits1(&s->gb);
+            asset->embedded_6ch = asset->nchannels_total > 6 && get_bits1(&s->gb);
 
             // Speaker mask enabled flag
             if (asset->spkr_mask_enabled = get_bits1(&s->gb)) {
@@ -135,13 +127,14 @@ static int parse_descriptor(DCAExssParser *s, DCAExssAsset *asset)
 
             // Number of speaker remapping sets
             if ((spkr_remap_nsets = get_bits(&s->gb, 3)) && !spkr_mask_nbits) {
-                av_log(s->avctx, AV_LOG_ERROR, "Speaker mask disabled yet there are remapping sets\n");
+                if (s->avctx)
+                    av_log(s->avctx, AV_LOG_ERROR, "Speaker mask disabled yet there are remapping sets\n");
                 return AVERROR_INVALIDDATA;
             }
 
             // Standard loudspeaker layout mask
             for (i = 0; i < spkr_remap_nsets; i++)
-                nspeakers[i] = count_chs_for_mask(get_bits(&s->gb, spkr_mask_nbits));
+                nspeakers[i] = ff_dca_count_chs_for_mask(get_bits(&s->gb, spkr_mask_nbits));
 
             for (i = 0; i < spkr_remap_nsets; i++) {
                 // Number of channels to be decoded for speaker remapping
@@ -220,7 +213,8 @@ static int parse_descriptor(DCAExssParser *s, DCAExssAsset *asset)
 
         for (i = 0; i < s->nmixoutconfigs; i++) {
             if (!s->nmixoutchs[i]) {
-                av_log(s->avctx, AV_LOG_ERROR, "Invalid speaker layout mask for mixing configuration\n");
+                if (s->avctx)
+                    av_log(s->avctx, AV_LOG_ERROR, "Invalid speaker layout mask for mixing configuration\n");
                 return AVERROR_INVALIDDATA;
             }
             for (j = 0; j < nchannels_dmix; j++) {
@@ -317,7 +311,8 @@ static int parse_descriptor(DCAExssParser *s, DCAExssAsset *asset)
     // Reserved
     // Zero pad
     if (ff_dca_seek_bits(&s->gb, descr_pos + descr_size * 8)) {
-        av_log(s->avctx, AV_LOG_ERROR, "Read past end of EXSS asset descriptor\n");
+        if (s->avctx)
+            av_log(s->avctx, AV_LOG_ERROR, "Read past end of EXSS asset descriptor\n");
         return AVERROR_INVALIDDATA;
     }
 
@@ -380,7 +375,7 @@ static int set_exss_offsets(DCAExssAsset *asset)
     return 0;
 }
 
-int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size)
+int ff_dca_exss_parse(DCAExssParser *s, const uint8_t *data, int size)
 {
     int i, ret, offset, wide_hdr, header_size;
 
@@ -403,8 +398,7 @@ int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size)
     header_size = get_bits(&s->gb, 8 + 4 * wide_hdr) + 1;
 
     // Check CRC
-    if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-        && ff_dca_check_crc(&s->gb, 32 + 8, header_size * 8)) {
+    if (s->avctx && ff_dca_check_crc(s->avctx, &s->gb, 32 + 8, header_size * 8)) {
         av_log(s->avctx, AV_LOG_ERROR, "Invalid EXSS header checksum\n");
         return AVERROR_INVALIDDATA;
     }
@@ -414,7 +408,8 @@ int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size)
     // Number of bytes of extension substream
     s->exss_size = get_bits(&s->gb, s->exss_size_nbits) + 1;
     if (s->exss_size > size) {
-        av_log(s->avctx, AV_LOG_ERROR, "Packet too short for EXSS frame\n");
+        if (s->avctx)
+            av_log(s->avctx, AV_LOG_ERROR, "Packet too short for EXSS frame\n");
         return AVERROR_INVALIDDATA;
     }
 
@@ -436,14 +431,16 @@ int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size)
         // Number of defined audio presentations
         s->npresents = get_bits(&s->gb, 3) + 1;
         if (s->npresents > 1) {
-            avpriv_request_sample(s->avctx, "%d audio presentations", s->npresents);
+            if (s->avctx)
+                avpriv_request_sample(s->avctx, "%d audio presentations", s->npresents);
             return AVERROR_PATCHWELCOME;
         }
 
         // Number of audio assets in extension substream
         s->nassets = get_bits(&s->gb, 3) + 1;
         if (s->nassets > 1) {
-            avpriv_request_sample(s->avctx, "%d audio assets", s->nassets);
+            if (s->avctx)
+                avpriv_request_sample(s->avctx, "%d audio assets", s->nassets);
             return AVERROR_PATCHWELCOME;
         }
 
@@ -470,7 +467,7 @@ int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size)
 
             // Speaker layout mask for mixer output channels
             for (i = 0; i < s->nmixoutconfigs; i++)
-                s->nmixoutchs[i] = count_chs_for_mask(get_bits(&s->gb, spkr_mask_nbits));
+                s->nmixoutchs[i] = ff_dca_count_chs_for_mask(get_bits(&s->gb, spkr_mask_nbits));
         }
     } else {
         s->npresents = 1;
@@ -484,7 +481,8 @@ int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size)
         s->assets[i].asset_size = get_bits(&s->gb, s->exss_size_nbits) + 1;
         offset += s->assets[i].asset_size;
         if (offset > s->exss_size) {
-            av_log(s->avctx, AV_LOG_ERROR, "EXSS asset out of bounds\n");
+            if (s->avctx)
+                av_log(s->avctx, AV_LOG_ERROR, "EXSS asset out of bounds\n");
             return AVERROR_INVALIDDATA;
         }
     }
@@ -494,7 +492,8 @@ int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size)
         if ((ret = parse_descriptor(s, &s->assets[i])) < 0)
             return ret;
         if ((ret = set_exss_offsets(&s->assets[i])) < 0) {
-            av_log(s->avctx, AV_LOG_ERROR, "Invalid extension size in EXSS asset descriptor\n");
+            if (s->avctx)
+                av_log(s->avctx, AV_LOG_ERROR, "Invalid extension size in EXSS asset descriptor\n");
             return ret;
         }
     }
@@ -506,7 +505,8 @@ int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size)
     // Byte align
     // CRC16 of extension substream header
     if (ff_dca_seek_bits(&s->gb, header_size * 8)) {
-        av_log(s->avctx, AV_LOG_ERROR, "Read past end of EXSS header\n");
+        if (s->avctx)
+            av_log(s->avctx, AV_LOG_ERROR, "Read past end of EXSS header\n");
         return AVERROR_INVALIDDATA;
     }
 
diff --git a/libavcodec/dca_exss.h b/libavcodec/dca_exss.h
index 323063a..208fae1 100644
--- a/libavcodec/dca_exss.h
+++ b/libavcodec/dca_exss.h
@@ -87,6 +87,6 @@ typedef struct DCAExssParser {
     DCAExssAsset   assets[1];    ///< Audio asset descriptors
 } DCAExssParser;
 
-int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size);
+int ff_dca_exss_parse(DCAExssParser *s, const uint8_t *data, int size);
 
 #endif
diff --git a/libavcodec/dca_lbr.c b/libavcodec/dca_lbr.c
new file mode 100644
index 0000000..342603c
--- /dev/null
+++ b/libavcodec/dca_lbr.c
@@ -0,0 +1,1819 @@
+/*
+ * Copyright (C) 2016 foo86
+ *
+ * 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
+ */
+
+#define BITSTREAM_READER_LE
+
+#include "libavutil/channel_layout.h"
+
+#include "dcadec.h"
+#include "dcadata.h"
+#include "dcahuff.h"
+#include "dca_syncwords.h"
+#include "bytestream.h"
+
+#define AMP_MAX     56
+
+enum LBRHeader {
+    LBR_HEADER_SYNC_ONLY    = 1,
+    LBR_HEADER_DECODER_INIT = 2
+};
+
+enum LBRFlags {
+    LBR_FLAG_24_BIT             = 0x01,
+    LBR_FLAG_LFE_PRESENT        = 0x02,
+    LBR_FLAG_BAND_LIMIT_2_3     = 0x04,
+    LBR_FLAG_BAND_LIMIT_1_2     = 0x08,
+    LBR_FLAG_BAND_LIMIT_1_3     = 0x0c,
+    LBR_FLAG_BAND_LIMIT_1_4     = 0x10,
+    LBR_FLAG_BAND_LIMIT_1_8     = 0x18,
+    LBR_FLAG_BAND_LIMIT_NONE    = 0x14,
+    LBR_FLAG_BAND_LIMIT_MASK    = 0x1c,
+    LBR_FLAG_DMIX_STEREO        = 0x20,
+    LBR_FLAG_DMIX_MULTI_CH      = 0x40
+};
+
+enum LBRChunkTypes {
+    LBR_CHUNK_NULL              = 0x00,
+    LBR_CHUNK_PAD               = 0x01,
+    LBR_CHUNK_FRAME             = 0x04,
+    LBR_CHUNK_FRAME_NO_CSUM     = 0x06,
+    LBR_CHUNK_LFE               = 0x0a,
+    LBR_CHUNK_ECS               = 0x0b,
+    LBR_CHUNK_RESERVED_1        = 0x0c,
+    LBR_CHUNK_RESERVED_2        = 0x0d,
+    LBR_CHUNK_SCF               = 0x0e,
+    LBR_CHUNK_TONAL             = 0x10,
+    LBR_CHUNK_TONAL_GRP_1       = 0x11,
+    LBR_CHUNK_TONAL_GRP_2       = 0x12,
+    LBR_CHUNK_TONAL_GRP_3       = 0x13,
+    LBR_CHUNK_TONAL_GRP_4       = 0x14,
+    LBR_CHUNK_TONAL_GRP_5       = 0x15,
+    LBR_CHUNK_TONAL_SCF         = 0x16,
+    LBR_CHUNK_TONAL_SCF_GRP_1   = 0x17,
+    LBR_CHUNK_TONAL_SCF_GRP_2   = 0x18,
+    LBR_CHUNK_TONAL_SCF_GRP_3   = 0x19,
+    LBR_CHUNK_TONAL_SCF_GRP_4   = 0x1a,
+    LBR_CHUNK_TONAL_SCF_GRP_5   = 0x1b,
+    LBR_CHUNK_RES_GRID_LR       = 0x30,
+    LBR_CHUNK_RES_GRID_LR_LAST  = 0x3f,
+    LBR_CHUNK_RES_GRID_HR       = 0x40,
+    LBR_CHUNK_RES_GRID_HR_LAST  = 0x4f,
+    LBR_CHUNK_RES_TS_1          = 0x50,
+    LBR_CHUNK_RES_TS_1_LAST     = 0x5f,
+    LBR_CHUNK_RES_TS_2          = 0x60,
+    LBR_CHUNK_RES_TS_2_LAST     = 0x6f,
+    LBR_CHUNK_EXTENSION         = 0x7f
+};
+
+typedef struct LBRChunk {
+    int id, len;
+    const uint8_t *data;
+} LBRChunk;
+
+static const int8_t channel_reorder_nolfe[7][5] = {
+    { 0, -1, -1, -1, -1 },  // C
+    { 0,  1, -1, -1, -1 },  // LR
+    { 0,  1,  2, -1, -1 },  // LR C
+    { 0,  1, -1, -1, -1 },  // LsRs
+    { 1,  2,  0, -1, -1 },  // LsRs C
+    { 0,  1,  2,  3, -1 },  // LR LsRs
+    { 0,  1,  3,  4,  2 },  // LR LsRs C
+};
+
+static const int8_t channel_reorder_lfe[7][5] = {
+    { 0, -1, -1, -1, -1 },  // C
+    { 0,  1, -1, -1, -1 },  // LR
+    { 0,  1,  2, -1, -1 },  // LR C
+    { 1,  2, -1, -1, -1 },  // LsRs
+    { 2,  3,  0, -1, -1 },  // LsRs C
+    { 0,  1,  3,  4, -1 },  // LR LsRs
+    { 0,  1,  4,  5,  2 },  // LR LsRs C
+};
+
+static const uint8_t lfe_index[7] = {
+    1, 2, 3, 0, 1, 2, 3
+};
+
+static const uint8_t channel_counts[7] = {
+    1, 2, 3, 2, 3, 4, 5
+};
+
+static const uint16_t channel_layouts[7] = {
+    AV_CH_LAYOUT_MONO,
+    AV_CH_LAYOUT_STEREO,
+    AV_CH_LAYOUT_SURROUND,
+    AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT,
+    AV_CH_FRONT_CENTER | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT,
+    AV_CH_LAYOUT_2_2,
+    AV_CH_LAYOUT_5POINT0
+};
+
+static float    cos_tab[256];
+static float    lpc_tab[16];
+
+static av_cold void init_tables(void)
+{
+    static int initialized;
+    int i;
+
+    if (initialized)
+        return;
+
+    for (i = 0; i < 256; i++)
+        cos_tab[i] = cos(M_PI * i / 128);
+
+    for (i = 0; i < 16; i++)
+        lpc_tab[i] = sin((i - 8) * (M_PI / ((i < 8) ? 17 : 15)));
+
+    initialized = 1;
+}
+
+static int parse_lfe_24(DCALbrDecoder *s)
+{
+    int step_max = FF_ARRAY_ELEMS(ff_dca_lfe_step_size_24) - 1;
+    int i, ps, si, code, step_i;
+    float step, value, delta;
+
+    ps = get_bits(&s->gb, 24);
+    si = ps >> 23;
+
+    value = (((ps & 0x7fffff) ^ -si) + si) * (1.0f / 0x7fffff);
+
+    step_i = get_bits(&s->gb, 8);
+    if (step_i > step_max) {
+        av_log(s->avctx, AV_LOG_ERROR, "Invalid LFE step size index\n");
+        return -1;
+    }
+
+    step = ff_dca_lfe_step_size_24[step_i];
+
+    for (i = 0; i < 64; i++) {
+        code = get_bits(&s->gb, 6);
+
+        delta = step * 0.03125f;
+        if (code & 16)
+            delta += step;
+        if (code & 8)
+            delta += step * 0.5f;
+        if (code & 4)
+            delta += step * 0.25f;
+        if (code & 2)
+            delta += step * 0.125f;
+        if (code & 1)
+            delta += step * 0.0625f;
+
+        if (code & 32) {
+            value -= delta;
+            if (value < -3.0f)
+                value = -3.0f;
+        } else {
+            value += delta;
+            if (value > 3.0f)
+                value = 3.0f;
+        }
+
+        step_i += ff_dca_lfe_delta_index_24[code & 31];
+        step_i = av_clip(step_i, 0, step_max);
+
+        step = ff_dca_lfe_step_size_24[step_i];
+        s->lfe_data[i] = value * s->lfe_scale;
+    }
+
+    return 0;
+}
+
+static int parse_lfe_16(DCALbrDecoder *s)
+{
+    int step_max = FF_ARRAY_ELEMS(ff_dca_lfe_step_size_16) - 1;
+    int i, ps, si, code, step_i;
+    float step, value, delta;
+
+    ps = get_bits(&s->gb, 16);
+    si = ps >> 15;
+
+    value = (((ps & 0x7fff) ^ -si) + si) * (1.0f / 0x7fff);
+
+    step_i = get_bits(&s->gb, 8);
+    if (step_i > step_max) {
+        av_log(s->avctx, AV_LOG_ERROR, "Invalid LFE step size index\n");
+        return -1;
+    }
+
+    step = ff_dca_lfe_step_size_16[step_i];
+
+    for (i = 0; i < 64; i++) {
+        code = get_bits(&s->gb, 4);
+
+        delta = step * 0.125f;
+        if (code & 4)
+            delta += step;
+        if (code & 2)
+            delta += step * 0.5f;
+        if (code & 1)
+            delta += step * 0.25f;
+
+        if (code & 8) {
+            value -= delta;
+            if (value < -3.0f)
+                value = -3.0f;
+        } else {
+            value += delta;
+            if (value > 3.0f)
+                value = 3.0f;
+        }
+
+        step_i += ff_dca_lfe_delta_index_16[code & 7];
+        step_i = av_clip(step_i, 0, step_max);
+
+        step = ff_dca_lfe_step_size_16[step_i];
+        s->lfe_data[i] = value * s->lfe_scale;
+    }
+
+    return 0;
+}
+
+static int parse_lfe_chunk(DCALbrDecoder *s, LBRChunk *chunk)
+{
+    if (!(s->flags & LBR_FLAG_LFE_PRESENT))
+        return 0;
+
+    if (!chunk->len)
+        return 0;
+
+    if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0)
+        return -1;
+
+    // Determine bit depth from chunk size
+    if (chunk->len >= 52)
+        return parse_lfe_24(s);
+    if (chunk->len >= 35)
+        return parse_lfe_16(s);
+
+    av_log(s->avctx, AV_LOG_ERROR, "LFE chunk too short\n");
+    return -1;
+}
+
+static inline int parse_vlc(GetBitContext *s, VLC *vlc, int max_depth)
+{
+    int v = get_vlc2(s, vlc->table, vlc->bits, max_depth);
+    if (v > 0)
+        return v - 1;
+    // Rare value
+    return get_bits(s, get_bits(s, 3) + 1);
+}
+
+static int parse_tonal(DCALbrDecoder *s, int group)
+{
+    unsigned int amp[DCA_LBR_CHANNELS_TOTAL];
+    unsigned int phs[DCA_LBR_CHANNELS_TOTAL];
+    unsigned int diff, main_amp, shift;
+    int sf, sf_idx, ch, main_ch, freq;
+    int ch_nbits = av_ceil_log2(s->nchannels_total);
+
+    // Parse subframes for this group
+    for (sf = 0; sf < 1 << group; sf += diff ? 8 : 1) {
+        sf_idx = ((s->framenum << group) + sf) & 31;
+        s->tonal_bounds[group][sf_idx][0] = s->ntones;
+
+        // Parse tones for this subframe
+        for (freq = 1;; freq++) {
+            if (get_bits_left(&s->gb) < 1) {
+                av_log(s->avctx, AV_LOG_ERROR, "Tonal group chunk too short\n");
+                return -1;
+            }
+
+            diff = parse_vlc(&s->gb, &ff_dca_vlc_tnl_grp[group], 2);
+            if (diff >= FF_ARRAY_ELEMS(ff_dca_fst_amp)) {
+                av_log(s->avctx, AV_LOG_ERROR, "Invalid tonal frequency diff\n");
+                return -1;
+            }
+
+            diff = get_bitsz(&s->gb, diff >> 2) + ff_dca_fst_amp[diff];
+            if (diff <= 1)
+                break;  // End of subframe
+
+            freq += diff - 2;
+            if (freq >> (5 - group) > s->nsubbands * 4 - 5) {
+                av_log(s->avctx, AV_LOG_ERROR, "Invalid spectral line offset\n");
+                return -1;
+            }
+
+            // Main channel
+            main_ch = get_bitsz(&s->gb, ch_nbits);
+            main_amp = parse_vlc(&s->gb, &ff_dca_vlc_tnl_scf, 2)
+                + s->tonal_scf[ff_dca_freq_to_sb[freq >> (7 - group)]]
+                + s->limited_range - 2;
+            amp[main_ch] = main_amp < AMP_MAX ? main_amp : 0;
+            phs[main_ch] = get_bits(&s->gb, 3);
+
+            // Secondary channels
+            for (ch = 0; ch < s->nchannels_total; ch++) {
+                if (ch == main_ch)
+                    continue;
+                if (get_bits1(&s->gb)) {
+                    amp[ch] = amp[main_ch] - parse_vlc(&s->gb, &ff_dca_vlc_damp, 1);
+                    phs[ch] = phs[main_ch] - parse_vlc(&s->gb, &ff_dca_vlc_dph,  1);
+                } else {
+                    amp[ch] = 0;
+                    phs[ch] = 0;
+                }
+            }
+
+            if (amp[main_ch]) {
+                // Allocate new tone
+                DCALbrTone *t = &s->tones[s->ntones];
+                s->ntones = (s->ntones + 1) & (DCA_LBR_TONES - 1);
+
+                t->x_freq = freq >> (5 - group);
+                t->f_delt = (freq & ((1 << (5 - group)) - 1)) << group;
+                t->ph_rot = 256 - (t->x_freq & 1) * 128 - t->f_delt * 4;
+
+                shift = ff_dca_ph0_shift[(t->x_freq & 3) * 2 + (freq & 1)]
+                    - ((t->ph_rot << (5 - group)) - t->ph_rot);
+
+                for (ch = 0; ch < s->nchannels; ch++) {
+                    t->amp[ch] = amp[ch] < AMP_MAX ? amp[ch] : 0;
+                    t->phs[ch] = 128 - phs[ch] * 32 + shift;
+                }
+            }
+        }
+
+        s->tonal_bounds[group][sf_idx][1] = s->ntones;
+    }
+
+    return 0;
+}
+
+static int parse_tonal_chunk(DCALbrDecoder *s, LBRChunk *chunk)
+{
+    int sb, group;
+
+    if (!chunk->len)
+        return 0;
+
+    if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0)
+        return -1;
+
+    // Scale factors
+    if (chunk->id == LBR_CHUNK_SCF || chunk->id == LBR_CHUNK_TONAL_SCF) {
+        if (get_bits_left(&s->gb) < 36) {
+            av_log(s->avctx, AV_LOG_ERROR, "Tonal scale factor chunk too short\n");
+            return -1;
+        }
+        for (sb = 0; sb < 6; sb++)
+            s->tonal_scf[sb] = get_bits(&s->gb, 6);
+    }
+
+    // Tonal groups
+    if (chunk->id == LBR_CHUNK_TONAL || chunk->id == LBR_CHUNK_TONAL_SCF)
+        for (group = 0; group < 5; group++)
+            if (parse_tonal(s, group) < 0)
+                return -1;
+
+    return 0;
+}
+
+static int parse_tonal_group(DCALbrDecoder *s, LBRChunk *chunk)
+{
+    if (!chunk->len)
+        return 0;
+
+    if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0)
+        return -1;
+
+    return parse_tonal(s, chunk->id);
+}
+
+/**
+ * Check point to ensure that enough bits are left. Aborts decoding
+ * by skipping to the end of chunk otherwise.
+ */
+static int ensure_bits(GetBitContext *s, int n)
+{
+    int left = get_bits_left(s);
+    if (left < 0)
+        return -1;
+    if (left < n) {
+        skip_bits_long(s, left);
+        return 1;
+    }
+    return 0;
+}
+
+static int parse_scale_factors(DCALbrDecoder *s, uint8_t *scf)
+{
+    int i, sf, prev, next, dist;
+
+    // Truncated scale factors remain zero
+    if (ensure_bits(&s->gb, 20))
+        return 0;
+
+    // Initial scale factor
+    prev = parse_vlc(&s->gb, &ff_dca_vlc_fst_rsd_amp, 2);
+
+    for (sf = 0; sf < 7; sf += dist) {
+        scf[sf] = prev; // Store previous value
+
+        if (ensure_bits(&s->gb, 20))
+            return 0;
+
+        // Interpolation distance
+        dist = parse_vlc(&s->gb, &ff_dca_vlc_rsd_apprx, 1) + 1;
+        if (dist > 7 - sf) {
+            av_log(s->avctx, AV_LOG_ERROR, "Invalid scale factor distance\n");
+            return -1;
+        }
+
+        if (ensure_bits(&s->gb, 20))
+            return 0;
+
+        // Final interpolation point
+        next = parse_vlc(&s->gb, &ff_dca_vlc_rsd_amp, 2);
+
+        if (next & 1)
+            next = prev + ((next + 1) >> 1);
+        else
+            next = prev - ( next      >> 1);
+
+        // Interpolate
+        switch (dist) {
+        case 2:
+            if (next > prev)
+                scf[sf + 1] = prev + ((next - prev) >> 1);
+            else
+                scf[sf + 1] = prev - ((prev - next) >> 1);
+            break;
+
+        case 4:
+            if (next > prev) {
+                scf[sf + 1] = prev + ( (next - prev)      >> 2);
+                scf[sf + 2] = prev + ( (next - prev)      >> 1);
+                scf[sf + 3] = prev + (((next - prev) * 3) >> 2);
+            } else {
+                scf[sf + 1] = prev - ( (prev - next)      >> 2);
+                scf[sf + 2] = prev - ( (prev - next)      >> 1);
+                scf[sf + 3] = prev - (((prev - next) * 3) >> 2);
+            }
+            break;
+
+        default:
+            for (i = 1; i < dist; i++)
+                scf[sf + i] = prev + (next - prev) * i / dist;
+            break;
+        }
+
+        prev = next;
+    }
+
+    scf[sf] = next; // Store final value
+
+    return 0;
+}
+
+static int parse_st_code(GetBitContext *s, int min_v)
+{
+    unsigned int v = parse_vlc(s, &ff_dca_vlc_st_grid, 2) + min_v;
+
+    if (v & 1)
+        v = 16 + (v >> 1);
+    else
+        v = 16 - (v >> 1);
+
+    if (v >= FF_ARRAY_ELEMS(ff_dca_st_coeff))
+        v = 16;
+    return v;
+}
+
+static int parse_grid_1_chunk(DCALbrDecoder *s, LBRChunk *chunk, int ch1, int ch2)
+{
+    int ch, sb, sf, nsubbands;
+
+    if (!chunk->len)
+        return 0;
+
+    if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0)
+        return -1;
+
+    // Scale factors
+    nsubbands = ff_dca_scf_to_grid_1[s->nsubbands - 1] + 1;
+    for (sb = 2; sb < nsubbands; sb++) {
+        if (parse_scale_factors(s, s->grid_1_scf[ch1][sb]) < 0)
+            return -1;
+        if (ch1 != ch2 && ff_dca_grid_1_to_scf[sb] < s->min_mono_subband
+            && parse_scale_factors(s, s->grid_1_scf[ch2][sb]) < 0)
+            return -1;
+    }
+
+    if (get_bits_left(&s->gb) < 1)
+        return 0;   // Should not happen, but a sample exists that proves otherwise
+
+    // Average values for third grid
+    for (sb = 0; sb < s->nsubbands - 4; sb++) {
+        s->grid_3_avg[ch1][sb] = parse_vlc(&s->gb, &ff_dca_vlc_avg_g3, 2) - 16;
+        if (ch1 != ch2) {
+            if (sb + 4 < s->min_mono_subband)
+                s->grid_3_avg[ch2][sb] = parse_vlc(&s->gb, &ff_dca_vlc_avg_g3, 2) - 16;
+            else
+                s->grid_3_avg[ch2][sb] = s->grid_3_avg[ch1][sb];
+        }
+    }
+
+    if (get_bits_left(&s->gb) < 0) {
+        av_log(s->avctx, AV_LOG_ERROR, "First grid chunk too short\n");
+        return -1;
+    }
+
+    // Stereo image for partial mono mode
+    if (ch1 != ch2) {
+        int min_v[2];
+
+        if (ensure_bits(&s->gb, 8))
+            return 0;
+
+        min_v[0] = get_bits(&s->gb, 4);
+        min_v[1] = get_bits(&s->gb, 4);
+
+        nsubbands = (s->nsubbands - s->min_mono_subband + 3) / 4;
+        for (sb = 0; sb < nsubbands; sb++)
+            for (ch = ch1; ch <= ch2; ch++)
+                for (sf = 1; sf <= 4; sf++)
+                    s->part_stereo[ch][sb][sf] = parse_st_code(&s->gb, min_v[ch - ch1]);
+
+        if (get_bits_left(&s->gb) >= 0)
+            s->part_stereo_pres |= 1 << ch1;
+    }
+
+    // Low resolution spatial information is not decoded
+
+    return 0;
+}
+
+static int parse_grid_1_sec_ch(DCALbrDecoder *s, int ch2)
+{
+    int sb, nsubbands;
+
+    // Scale factors
+    nsubbands = ff_dca_scf_to_grid_1[s->nsubbands - 1] + 1;
+    for (sb = 2; sb < nsubbands; sb++) {
+        if (ff_dca_grid_1_to_scf[sb] >= s->min_mono_subband
+            && parse_scale_factors(s, s->grid_1_scf[ch2][sb]) < 0)
+            return -1;
+    }
+
+    // Average values for third grid
+    for (sb = 0; sb < s->nsubbands - 4; sb++) {
+        if (sb + 4 >= s->min_mono_subband) {
+            if (ensure_bits(&s->gb, 20))
+                return 0;
+            s->grid_3_avg[ch2][sb] = parse_vlc(&s->gb, &ff_dca_vlc_avg_g3, 2) - 16;
+        }
+    }
+
+    return 0;
+}
+
+static void parse_grid_3(DCALbrDecoder *s, int ch1, int ch2, int sb, int flag)
+{
+    int i, ch;
+
+    for (ch = ch1; ch <= ch2; ch++) {
+        if ((ch != ch1 && sb + 4 >= s->min_mono_subband) != flag)
+            continue;
+
+        if (s->grid_3_pres[ch] & (1U << sb))
+            continue;   // Already parsed
+
+        for (i = 0; i < 8; i++) {
+            if (ensure_bits(&s->gb, 20))
+                return;
+            s->grid_3_scf[ch][sb][i] = parse_vlc(&s->gb, &ff_dca_vlc_grid_3, 2) - 16;
+        }
+
+        // Flag scale factors for this subband parsed
+        s->grid_3_pres[ch] |= 1U << sb;
+    }
+}
+
+static float lbr_rand(DCALbrDecoder *s, int sb)
+{
+    s->lbr_rand = 1103515245U * s->lbr_rand + 12345U;
+    return s->lbr_rand * s->sb_scf[sb];
+}
+
+/**
+ * Parse time samples for one subband, filling truncated samples with randomness
+ */
+static void parse_ch(DCALbrDecoder *s, int ch, int sb, int quant_level, int flag)
+{
+    float *samples = s->time_samples[ch][sb];
+    int i, j, code, nblocks, coding_method;
+
+    if (ensure_bits(&s->gb, 20))
+        return; // Too few bits left
+
+    coding_method = get_bits1(&s->gb);
+
+    switch (quant_level) {
+    case 1:
+        nblocks = FFMIN(get_bits_left(&s->gb) / 8, DCA_LBR_TIME_SAMPLES / 8);
+        for (i = 0; i < nblocks; i++, samples += 8) {
+            code = get_bits(&s->gb, 8);
+            for (j = 0; j < 8; j++)
+                samples[j] = ff_dca_rsd_level_2a[(code >> j) & 1];
+        }
+        i = nblocks * 8;
+        break;
+
+    case 2:
+        if (coding_method) {
+            for (i = 0; i < DCA_LBR_TIME_SAMPLES && get_bits_left(&s->gb) >= 2; i++) {
+                if (get_bits1(&s->gb))
+                    samples[i] = ff_dca_rsd_level_2b[get_bits1(&s->gb)];
+                else
+                    samples[i] = 0;
+            }
+        } else {
+            nblocks = FFMIN(get_bits_left(&s->gb) / 8, (DCA_LBR_TIME_SAMPLES + 4) / 5);
+            for (i = 0; i < nblocks; i++, samples += 5) {
+                code = ff_dca_rsd_pack_5_in_8[get_bits(&s->gb, 8)];
+                for (j = 0; j < 5; j++)
+                    samples[j] = ff_dca_rsd_level_3[(code >> j * 2) & 3];
+            }
+            i = nblocks * 5;
+        }
+        break;
+
+    case 3:
+        nblocks = FFMIN(get_bits_left(&s->gb) / 7, (DCA_LBR_TIME_SAMPLES + 2) / 3);
+        for (i = 0; i < nblocks; i++, samples += 3) {
+            code = get_bits(&s->gb, 7);
+            for (j = 0; j < 3; j++)
+                samples[j] = ff_dca_rsd_level_5[ff_dca_rsd_pack_3_in_7[code][j]];
+        }
+        i = nblocks * 3;
+        break;
+
+    case 4:
+        for (i = 0; i < DCA_LBR_TIME_SAMPLES && get_bits_left(&s->gb) >= 6; i++)
+            samples[i] = ff_dca_rsd_level_8[get_vlc2(&s->gb, ff_dca_vlc_rsd.table, 6, 1)];
+        break;
+
+    case 5:
+        nblocks = FFMIN(get_bits_left(&s->gb) / 4, DCA_LBR_TIME_SAMPLES);
+        for (i = 0; i < nblocks; i++)
+            samples[i] = ff_dca_rsd_level_16[get_bits(&s->gb, 4)];
+        break;
+
+    default:
+        av_assert0(0);
+    }
+
+    if (flag && get_bits_left(&s->gb) < 20)
+        return; // Skip incomplete mono subband
+
+    for (; i < DCA_LBR_TIME_SAMPLES; i++)
+        s->time_samples[ch][sb][i] = lbr_rand(s, sb);
+
+    s->ch_pres[ch] |= 1U << sb;
+}
+
+static int parse_ts(DCALbrDecoder *s, int ch1, int ch2,
+                    int start_sb, int end_sb, int flag)
+{
+    int sb, sb_g3, sb_reorder, quant_level;
+
+    for (sb = start_sb; sb < end_sb; sb++) {
+        // Subband number before reordering
+        if (sb < 6) {
+            sb_reorder = sb;
+        } else if (flag && sb < s->max_mono_subband) {
+            sb_reorder = s->sb_indices[sb];
+        } else {
+            if (ensure_bits(&s->gb, 28))
+                break;
+            sb_reorder = get_bits(&s->gb, s->limited_range + 3);
+            if (sb_reorder < 6)
+                sb_reorder = 6;
+            s->sb_indices[sb] = sb_reorder;
+        }
+        if (sb_reorder >= s->nsubbands)
+            return -1;
+
+        // Third grid scale factors
+        if (sb == 12) {
+            for (sb_g3 = 0; sb_g3 < s->g3_avg_only_start_sb - 4; sb_g3++)
+                parse_grid_3(s, ch1, ch2, sb_g3, flag);
+        } else if (sb < 12 && sb_reorder >= 4) {
+            parse_grid_3(s, ch1, ch2, sb_reorder - 4, flag);
+        }
+
+        // Secondary channel flags
+        if (ch1 != ch2) {
+            if (ensure_bits(&s->gb, 20))
+                break;
+            if (!flag || sb_reorder >= s->max_mono_subband)
+                s->sec_ch_sbms[ch1 / 2][sb_reorder] = get_bits(&s->gb, 8);
+            if (flag && sb_reorder >= s->min_mono_subband)
+                s->sec_ch_lrms[ch1 / 2][sb_reorder] = get_bits(&s->gb, 8);
+        }
+
+        quant_level = s->quant_levels[ch1 / 2][sb];
+        if (!quant_level)
+            return -1;
+
+        // Time samples for one or both channels
+        if (sb < s->max_mono_subband && sb_reorder >= s->min_mono_subband) {
+            if (!flag)
+                parse_ch(s, ch1, sb_reorder, quant_level, 0);
+            else if (ch1 != ch2)
+                parse_ch(s, ch2, sb_reorder, quant_level, 1);
+        } else {
+            parse_ch(s, ch1, sb_reorder, quant_level, 0);
+            if (ch1 != ch2)
+                parse_ch(s, ch2, sb_reorder, quant_level, 0);
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * Convert from reflection coefficients to direct form coefficients
+ */
+static void convert_lpc(float *coeff, const int *codes)
+{
+    int i, j;
+
+    for (i = 0; i < 8; i++) {
+        float rc = lpc_tab[codes[i]];
+        for (j = 0; j < (i + 1) / 2; j++) {
+            float tmp1 = coeff[    j    ];
+            float tmp2 = coeff[i - j - 1];
+            coeff[    j    ] = tmp1 + rc * tmp2;
+            coeff[i - j - 1] = tmp2 + rc * tmp1;
+        }
+        coeff[i] = rc;
+    }
+}
+
+static int parse_lpc(DCALbrDecoder *s, int ch1, int ch2, int start_sb, int end_sb)
+{
+    int f = s->framenum & 1;
+    int i, sb, ch, codes[16];
+
+    // First two subbands have two sets of coefficients, third subband has one
+    for (sb = start_sb; sb < end_sb; sb++) {
+        int ncodes = 8 * (1 + (sb < 2));
+        for (ch = ch1; ch <= ch2; ch++) {
+            if (ensure_bits(&s->gb, 4 * ncodes))
+                return 0;
+            for (i = 0; i < ncodes; i++)
+                codes[i] = get_bits(&s->gb, 4);
+            for (i = 0; i < ncodes / 8; i++)
+                convert_lpc(s->lpc_coeff[f][ch][sb][i], &codes[i * 8]);
+        }
+    }
+
+    return 0;
+}
+
+static int parse_high_res_grid(DCALbrDecoder *s, LBRChunk *chunk, int ch1, int ch2)
+{
+    int quant_levels[DCA_LBR_SUBBANDS];
+    int sb, ch, ol, st, max_sb, profile;
+
+    if (!chunk->len)
+        return 0;
+
+    if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0)
+        return -1;
+
+    // Quantizer profile
+    profile = get_bits(&s->gb, 8);
+    // Overall level
+    ol = (profile >> 3) & 7;
+    // Steepness
+    st = profile >> 6;
+    // Max energy subband
+    max_sb = profile & 7;
+
+    // Calculate quantization levels
+    for (sb = 0; sb < s->nsubbands; sb++) {
+        int f = sb * s->limited_rate / s->nsubbands;
+        int a = 18000 / (12 * f / 1000 + 100 + 40 * st) + 20 * ol;
+        if (a <= 95)
+            quant_levels[sb] = 1;
+        else if (a <= 140)
+            quant_levels[sb] = 2;
+        else if (a <= 180)
+            quant_levels[sb] = 3;
+        else if (a <= 230)
+            quant_levels[sb] = 4;
+        else
+            quant_levels[sb] = 5;
+    }
+
+    // Reorder quantization levels for lower subbands
+    for (sb = 0; sb < 8; sb++)
+        s->quant_levels[ch1 / 2][sb] = quant_levels[ff_dca_sb_reorder[max_sb][sb]];
+    for (; sb < s->nsubbands; sb++)
+        s->quant_levels[ch1 / 2][sb] = quant_levels[sb];
+
+    // LPC for the first two subbands
+    if (parse_lpc(s, ch1, ch2, 0, 2) < 0)
+        return -1;
+
+    // Time-samples for the first two subbands of main channel
+    if (parse_ts(s, ch1, ch2, 0, 2, 0) < 0)
+        return -1;
+
+    // First two bands of the first grid
+    for (sb = 0; sb < 2; sb++)
+        for (ch = ch1; ch <= ch2; ch++)
+            if (parse_scale_factors(s, s->grid_1_scf[ch][sb]) < 0)
+                return -1;
+
+    return 0;
+}
+
+static int parse_grid_2(DCALbrDecoder *s, int ch1, int ch2,
+                        int start_sb, int end_sb, int flag)
+{
+    int i, j, sb, ch, nsubbands;
+
+    nsubbands = ff_dca_scf_to_grid_2[s->nsubbands - 1] + 1;
+    if (end_sb > nsubbands)
+        end_sb = nsubbands;
+
+    for (sb = start_sb; sb < end_sb; sb++) {
+        for (ch = ch1; ch <= ch2; ch++) {
+            uint8_t *g2_scf = s->grid_2_scf[ch][sb];
+
+            if ((ch != ch1 && ff_dca_grid_2_to_scf[sb] >= s->min_mono_subband) != flag) {
+                if (!flag)
+                    memcpy(g2_scf, s->grid_2_scf[ch1][sb], 64);
+                continue;
+            }
+
+            // Scale factors in groups of 8
+            for (i = 0; i < 8; i++, g2_scf += 8) {
+                if (get_bits_left(&s->gb) < 1) {
+                    memset(g2_scf, 0, 64 - i * 8);
+                    break;
+                }
+                // Bit indicating if whole group has zero values
+                if (get_bits1(&s->gb)) {
+                    for (j = 0; j < 8; j++) {
+                        if (ensure_bits(&s->gb, 20))
+                            break;
+                        g2_scf[j] = parse_vlc(&s->gb, &ff_dca_vlc_grid_2, 2);
+                    }
+                } else {
+                    memset(g2_scf, 0, 8);
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int parse_ts1_chunk(DCALbrDecoder *s, LBRChunk *chunk, int ch1, int ch2)
+{
+    if (!chunk->len)
+        return 0;
+    if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0)
+        return -1;
+    if (parse_lpc(s, ch1, ch2, 2, 3) < 0)
+        return -1;
+    if (parse_ts(s, ch1, ch2, 2, 4, 0) < 0)
+        return -1;
+    if (parse_grid_2(s, ch1, ch2, 0, 1, 0) < 0)
+        return -1;
+    if (parse_ts(s, ch1, ch2, 4, 6, 0) < 0)
+        return -1;
+    return 0;
+}
+
+static int parse_ts2_chunk(DCALbrDecoder *s, LBRChunk *chunk, int ch1, int ch2)
+{
+    if (!chunk->len)
+        return 0;
+    if (init_get_bits8(&s->gb, chunk->data, chunk->len) < 0)
+        return -1;
+    if (parse_grid_2(s, ch1, ch2, 1, 3, 0) < 0)
+        return -1;
+    if (parse_ts(s, ch1, ch2, 6, s->max_mono_subband, 0) < 0)
+        return -1;
+    if (ch1 != ch2) {
+        if (parse_grid_1_sec_ch(s, ch2) < 0)
+            return -1;
+        if (parse_grid_2(s, ch1, ch2, 0, 3, 1) < 0)
+            return -1;
+    }
+    if (parse_ts(s, ch1, ch2, s->min_mono_subband, s->nsubbands, 1) < 0)
+        return -1;
+    return 0;
+}
+
+static int init_sample_rate(DCALbrDecoder *s)
+{
+    double scale = (-1.0 / (1 << 17)) * sqrt(1 << (2 - s->limited_range));
+    int i, br_per_ch = s->bit_rate_scaled / s->nchannels_total;
+
+    ff_mdct_end(&s->imdct);
+
+    if (ff_mdct_init(&s->imdct, s->freq_range + 6, 1, scale) < 0)
+        return -1;
+
+    for (i = 0; i < 32 << s->freq_range; i++)
+        s->window[i] = ff_dca_long_window[i << (2 - s->freq_range)];
+
+    if (br_per_ch < 14000)
+        scale = 0.85;
+    else if (br_per_ch < 32000)
+        scale = (br_per_ch - 14000) * (1.0 / 120000) + 0.85;
+    else
+        scale = 1.0;
+
+    scale *= 1.0 / INT_MAX;
+
+    for (i = 0; i < s->nsubbands; i++) {
+        if (i < 2)
+            s->sb_scf[i] = 0;   // The first two subbands are always zero
+        else if (i < 5)
+            s->sb_scf[i] = (i - 1) * 0.25 * 0.785 * scale;
+        else
+            s->sb_scf[i] = 0.785 * scale;
+    }
+
+    s->lfe_scale = (16 << s->freq_range) * 0.0000078265894;
+
+    return 0;
+}
+
+static int alloc_sample_buffer(DCALbrDecoder *s)
+{
+    // Reserve space for history and padding
+    int nchsamples = DCA_LBR_TIME_SAMPLES + DCA_LBR_TIME_HISTORY * 2;
+    int nsamples = nchsamples * s->nchannels * s->nsubbands;
+    int ch, sb;
+    float *ptr;
+
+    // Reallocate time sample buffer
+    av_fast_mallocz(&s->ts_buffer, &s->ts_size, nsamples * sizeof(float));
+    if (!s->ts_buffer)
+        return -1;
+
+    ptr = s->ts_buffer + DCA_LBR_TIME_HISTORY;
+    for (ch = 0; ch < s->nchannels; ch++) {
+        for (sb = 0; sb < s->nsubbands; sb++) {
+            s->time_samples[ch][sb] = ptr;
+            ptr += nchsamples;
+        }
+    }
+
+    return 0;
+}
+
+static int parse_decoder_init(DCALbrDecoder *s, GetByteContext *gb)
+{
+    int old_rate = s->sample_rate;
+    int old_band_limit = s->band_limit;
+    int old_nchannels = s->nchannels;
+    int version, bit_rate_hi;
+    unsigned int sr_code;
+
+    // Sample rate of LBR audio
+    sr_code = bytestream2_get_byte(gb);
+    if (sr_code >= FF_ARRAY_ELEMS(ff_dca_sampling_freqs)) {
+        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR sample rate\n");
+        return AVERROR_INVALIDDATA;
+    }
+    s->sample_rate = ff_dca_sampling_freqs[sr_code];
+    if (s->sample_rate > 48000) {
+        avpriv_report_missing_feature(s->avctx, "%d Hz LBR sample rate", s->sample_rate);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    // LBR speaker mask
+    s->ch_mask = bytestream2_get_le16(gb);
+    if (!(s->ch_mask & 0x7)) {
+        avpriv_report_missing_feature(s->avctx, "LBR channel mask %#x", s->ch_mask);
+        return AVERROR_PATCHWELCOME;
+    }
+    if ((s->ch_mask & 0xfff0) && !(s->warned & 1)) {
+        avpriv_report_missing_feature(s->avctx, "LBR channel mask %#x", s->ch_mask);
+        s->warned |= 1;
+    }
+
+    // LBR bitstream version
+    version = bytestream2_get_le16(gb);
+    if ((version & 0xff00) != 0x0800) {
+        avpriv_report_missing_feature(s->avctx, "LBR stream version %#x", version);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    // Flags for LBR decoder initialization
+    s->flags = bytestream2_get_byte(gb);
+    if (s->flags & LBR_FLAG_DMIX_MULTI_CH) {
+        avpriv_report_missing_feature(s->avctx, "LBR multi-channel downmix");
+        return AVERROR_PATCHWELCOME;
+    }
+    if ((s->flags & LBR_FLAG_LFE_PRESENT) && s->sample_rate != 48000) {
+        if (!(s->warned & 2)) {
+            avpriv_report_missing_feature(s->avctx, "%d Hz LFE interpolation", s->sample_rate);
+            s->warned |= 2;
+        }
+        s->flags &= ~LBR_FLAG_LFE_PRESENT;
+    }
+
+    // Most significant bit rate nibbles
+    bit_rate_hi = bytestream2_get_byte(gb);
+
+    // Least significant original bit rate word
+    s->bit_rate_orig = bytestream2_get_le16(gb) | ((bit_rate_hi & 0x0F) << 16);
+
+    // Least significant scaled bit rate word
+    s->bit_rate_scaled = bytestream2_get_le16(gb) | ((bit_rate_hi & 0xF0) << 12);
+
+    // Setup number of fullband channels
+    s->nchannels_total = ff_dca_count_chs_for_mask(s->ch_mask & ~DCA_SPEAKER_PAIR_LFE1);
+    s->nchannels = FFMIN(s->nchannels_total, DCA_LBR_CHANNELS);
+
+    // Setup band limit
+    switch (s->flags & LBR_FLAG_BAND_LIMIT_MASK) {
+    case LBR_FLAG_BAND_LIMIT_NONE:
+        s->band_limit = 0;
+        break;
+    case LBR_FLAG_BAND_LIMIT_1_2:
+        s->band_limit = 1;
+        break;
+    case LBR_FLAG_BAND_LIMIT_1_4:
+        s->band_limit = 2;
+        break;
+    default:
+        avpriv_report_missing_feature(s->avctx, "LBR band limit %#x", s->flags & LBR_FLAG_BAND_LIMIT_MASK);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    // Setup frequency range
+    s->freq_range = ff_dca_freq_ranges[sr_code];
+
+    // Setup resolution profile
+    if (s->bit_rate_orig >= 44000 * (s->nchannels_total + 2))
+        s->res_profile = 2;
+    else if (s->bit_rate_orig >= 25000 * (s->nchannels_total + 2))
+        s->res_profile = 1;
+    else
+        s->res_profile = 0;
+
+    // Setup limited sample rate, number of subbands, etc
+    s->limited_rate = s->sample_rate >> s->band_limit;
+    s->limited_range = s->freq_range - s->band_limit;
+    if (s->limited_range < 0) {
+        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR band limit for frequency range\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    s->nsubbands = 8 << s->limited_range;
+
+    s->g3_avg_only_start_sb = s->nsubbands * ff_dca_avg_g3_freqs[s->res_profile] / (s->limited_rate / 2);
+    if (s->g3_avg_only_start_sb > s->nsubbands)
+        s->g3_avg_only_start_sb = s->nsubbands;
+
+    s->min_mono_subband = s->nsubbands *  2000 / (s->limited_rate / 2);
+    if (s->min_mono_subband > s->nsubbands)
+        s->min_mono_subband = s->nsubbands;
+
+    s->max_mono_subband = s->nsubbands * 14000 / (s->limited_rate / 2);
+    if (s->max_mono_subband > s->nsubbands)
+        s->max_mono_subband = s->nsubbands;
+
+    // Handle change of sample rate
+    if ((old_rate != s->sample_rate || old_band_limit != s->band_limit) && init_sample_rate(s) < 0)
+        return AVERROR(ENOMEM);
+
+    // Setup stereo downmix
+    if (s->flags & LBR_FLAG_DMIX_STEREO) {
+        DCAContext *dca = s->avctx->priv_data;
+
+        if (s->nchannels_total < 3 || s->nchannels_total > DCA_LBR_CHANNELS_TOTAL - 2) {
+            av_log(s->avctx, AV_LOG_ERROR, "Invalid number of channels for LBR stereo downmix\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        // This decoder doesn't support ECS chunk
+        if (dca->request_channel_layout != DCA_SPEAKER_LAYOUT_STEREO && !(s->warned & 4)) {
+            avpriv_report_missing_feature(s->avctx, "Embedded LBR stereo downmix");
+            s->warned |= 4;
+        }
+
+        // Account for extra downmixed channel pair
+        s->nchannels_total += 2;
+        s->nchannels = 2;
+        s->ch_mask = DCA_SPEAKER_PAIR_LR;
+        s->flags &= ~LBR_FLAG_LFE_PRESENT;
+    }
+
+    // Handle change of sample rate or number of channels
+    if (old_rate != s->sample_rate
+        || old_band_limit != s->band_limit
+        || old_nchannels != s->nchannels) {
+        if (alloc_sample_buffer(s) < 0)
+            return AVERROR(ENOMEM);
+        ff_dca_lbr_flush(s);
+    }
+
+    return 0;
+}
+
+int ff_dca_lbr_parse(DCALbrDecoder *s, uint8_t *data, DCAExssAsset *asset)
+{
+    struct {
+        LBRChunk    lfe;
+        LBRChunk    tonal;
+        LBRChunk    tonal_grp[5];
+        LBRChunk    grid1[DCA_LBR_CHANNELS / 2];
+        LBRChunk    hr_grid[DCA_LBR_CHANNELS / 2];
+        LBRChunk    ts1[DCA_LBR_CHANNELS / 2];
+        LBRChunk    ts2[DCA_LBR_CHANNELS / 2];
+    } chunk = { {0} };
+
+    GetByteContext gb;
+
+    int i, ch, sb, sf, ret, group, chunk_id, chunk_len;
+
+    bytestream2_init(&gb, data + asset->lbr_offset, asset->lbr_size);
+
+    // LBR sync word
+    if (bytestream2_get_be32(&gb) != DCA_SYNCWORD_LBR) {
+        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR sync word\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    // LBR header type
+    switch (bytestream2_get_byte(&gb)) {
+    case LBR_HEADER_SYNC_ONLY:
+        if (!s->sample_rate) {
+            av_log(s->avctx, AV_LOG_ERROR, "LBR decoder not initialized\n");
+            return AVERROR_INVALIDDATA;
+        }
+        break;
+    case LBR_HEADER_DECODER_INIT:
+        if ((ret = parse_decoder_init(s, &gb)) < 0) {
+            s->sample_rate = 0;
+            return ret;
+        }
+        break;
+    default:
+        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR header type\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    // LBR frame chunk header
+    chunk_id = bytestream2_get_byte(&gb);
+    chunk_len = (chunk_id & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb);
+
+    if (chunk_len > bytestream2_get_bytes_left(&gb)) {
+        chunk_len = bytestream2_get_bytes_left(&gb);
+        av_log(s->avctx, AV_LOG_WARNING, "LBR frame chunk was truncated\n");
+        if (s->avctx->err_recognition & AV_EF_EXPLODE)
+            return AVERROR_INVALIDDATA;
+    }
+
+    bytestream2_init(&gb, gb.buffer, chunk_len);
+
+    switch (chunk_id & 0x7f) {
+    case LBR_CHUNK_FRAME:
+        if (s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL)) {
+            int checksum = bytestream2_get_be16(&gb);
+            uint16_t res = chunk_id;
+            res += (chunk_len >> 8) & 0xff;
+            res += chunk_len & 0xff;
+            for (i = 0; i < chunk_len - 2; i++)
+                res += gb.buffer[i];
+            if (checksum != res) {
+                av_log(s->avctx, AV_LOG_WARNING, "Invalid LBR checksum\n");
+                if (s->avctx->err_recognition & AV_EF_EXPLODE)
+                    return AVERROR_INVALIDDATA;
+            }
+        } else {
+            bytestream2_skip(&gb, 2);
+        }
+        break;
+    case LBR_CHUNK_FRAME_NO_CSUM:
+        break;
+    default:
+        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR frame chunk ID\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    // Clear current frame
+    memset(s->quant_levels, 0, sizeof(s->quant_levels));
+    memset(s->sb_indices, 0xff, sizeof(s->sb_indices));
+    memset(s->sec_ch_sbms, 0, sizeof(s->sec_ch_sbms));
+    memset(s->sec_ch_lrms, 0, sizeof(s->sec_ch_lrms));
+    memset(s->ch_pres, 0, sizeof(s->ch_pres));
+    memset(s->grid_1_scf, 0, sizeof(s->grid_1_scf));
+    memset(s->grid_2_scf, 0, sizeof(s->grid_2_scf));
+    memset(s->grid_3_avg, 0, sizeof(s->grid_3_avg));
+    memset(s->grid_3_scf, 0, sizeof(s->grid_3_scf));
+    memset(s->grid_3_pres, 0, sizeof(s->grid_3_pres));
+    memset(s->tonal_scf, 0, sizeof(s->tonal_scf));
+    memset(s->lfe_data, 0, sizeof(s->lfe_data));
+    s->part_stereo_pres = 0;
+    s->framenum = (s->framenum + 1) & 31;
+
+    for (ch = 0; ch < s->nchannels; ch++) {
+        for (sb = 0; sb < s->nsubbands / 4; sb++) {
+            s->part_stereo[ch][sb][0] = s->part_stereo[ch][sb][4];
+            s->part_stereo[ch][sb][4] = 16;
+        }
+    }
+
+    memset(s->lpc_coeff[s->framenum & 1], 0, sizeof(s->lpc_coeff[0]));
+
+    for (group = 0; group < 5; group++) {
+        for (sf = 0; sf < 1 << group; sf++) {
+            int sf_idx = ((s->framenum << group) + sf) & 31;
+            s->tonal_bounds[group][sf_idx][0] =
+            s->tonal_bounds[group][sf_idx][1] = s->ntones;
+        }
+    }
+
+    // Parse chunk headers
+    while (bytestream2_get_bytes_left(&gb) > 0) {
+        chunk_id = bytestream2_get_byte(&gb);
+        chunk_len = (chunk_id & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb);
+        chunk_id &= 0x7f;
+
+        if (chunk_len > bytestream2_get_bytes_left(&gb)) {
+            chunk_len = bytestream2_get_bytes_left(&gb);
+            av_log(s->avctx, AV_LOG_WARNING, "LBR chunk %#x was truncated\n", chunk_id);
+            if (s->avctx->err_recognition & AV_EF_EXPLODE)
+                return AVERROR_INVALIDDATA;
+        }
+
+        switch (chunk_id) {
+        case LBR_CHUNK_LFE:
+            chunk.lfe.len  = chunk_len;
+            chunk.lfe.data = gb.buffer;
+            break;
+
+        case LBR_CHUNK_SCF:
+        case LBR_CHUNK_TONAL:
+        case LBR_CHUNK_TONAL_SCF:
+            chunk.tonal.id   = chunk_id;
+            chunk.tonal.len  = chunk_len;
+            chunk.tonal.data = gb.buffer;
+            break;
+
+        case LBR_CHUNK_TONAL_GRP_1:
+        case LBR_CHUNK_TONAL_GRP_2:
+        case LBR_CHUNK_TONAL_GRP_3:
+        case LBR_CHUNK_TONAL_GRP_4:
+        case LBR_CHUNK_TONAL_GRP_5:
+            i = LBR_CHUNK_TONAL_GRP_5 - chunk_id;
+            chunk.tonal_grp[i].id   = i;
+            chunk.tonal_grp[i].len  = chunk_len;
+            chunk.tonal_grp[i].data = gb.buffer;
+            break;
+
+        case LBR_CHUNK_TONAL_SCF_GRP_1:
+        case LBR_CHUNK_TONAL_SCF_GRP_2:
+        case LBR_CHUNK_TONAL_SCF_GRP_3:
+        case LBR_CHUNK_TONAL_SCF_GRP_4:
+        case LBR_CHUNK_TONAL_SCF_GRP_5:
+            i = LBR_CHUNK_TONAL_SCF_GRP_5 - chunk_id;
+            chunk.tonal_grp[i].id   = i;
+            chunk.tonal_grp[i].len  = chunk_len;
+            chunk.tonal_grp[i].data = gb.buffer;
+            break;
+
+        case LBR_CHUNK_RES_GRID_LR:
+        case LBR_CHUNK_RES_GRID_LR + 1:
+        case LBR_CHUNK_RES_GRID_LR + 2:
+            i = chunk_id - LBR_CHUNK_RES_GRID_LR;
+            chunk.grid1[i].len  = chunk_len;
+            chunk.grid1[i].data = gb.buffer;
+            break;
+
+        case LBR_CHUNK_RES_GRID_HR:
+        case LBR_CHUNK_RES_GRID_HR + 1:
+        case LBR_CHUNK_RES_GRID_HR + 2:
+            i = chunk_id - LBR_CHUNK_RES_GRID_HR;
+            chunk.hr_grid[i].len  = chunk_len;
+            chunk.hr_grid[i].data = gb.buffer;
+            break;
+
+        case LBR_CHUNK_RES_TS_1:
+        case LBR_CHUNK_RES_TS_1 + 1:
+        case LBR_CHUNK_RES_TS_1 + 2:
+            i = chunk_id - LBR_CHUNK_RES_TS_1;
+            chunk.ts1[i].len  = chunk_len;
+            chunk.ts1[i].data = gb.buffer;
+            break;
+
+        case LBR_CHUNK_RES_TS_2:
+        case LBR_CHUNK_RES_TS_2 + 1:
+        case LBR_CHUNK_RES_TS_2 + 2:
+            i = chunk_id - LBR_CHUNK_RES_TS_2;
+            chunk.ts2[i].len  = chunk_len;
+            chunk.ts2[i].data = gb.buffer;
+            break;
+        }
+
+        bytestream2_skip(&gb, chunk_len);
+    }
+
+    // Parse the chunks
+    ret = parse_lfe_chunk(s, &chunk.lfe);
+
+    ret |= parse_tonal_chunk(s, &chunk.tonal);
+
+    for (i = 0; i < 5; i++)
+        ret |= parse_tonal_group(s, &chunk.tonal_grp[i]);
+
+    for (i = 0; i < (s->nchannels + 1) / 2; i++) {
+        int ch1 = i * 2;
+        int ch2 = FFMIN(ch1 + 1, s->nchannels - 1);
+
+        if (parse_grid_1_chunk (s, &chunk.grid1  [i], ch1, ch2) < 0 ||
+            parse_high_res_grid(s, &chunk.hr_grid[i], ch1, ch2) < 0) {
+            ret = -1;
+            continue;
+        }
+
+        // TS chunks depend on both grids. TS_2 depends on TS_1.
+        if (!chunk.grid1[i].len || !chunk.hr_grid[i].len || !chunk.ts1[i].len)
+            continue;
+
+        if (parse_ts1_chunk(s, &chunk.ts1[i], ch1, ch2) < 0 ||
+            parse_ts2_chunk(s, &chunk.ts2[i], ch1, ch2) < 0) {
+            ret = -1;
+            continue;
+        }
+    }
+
+    if (ret < 0 && (s->avctx->err_recognition & AV_EF_EXPLODE))
+        return AVERROR_INVALIDDATA;
+
+    return 0;
+}
+
+/**
+ * Reconstruct high-frequency resolution grid from first and third grids
+ */
+static void decode_grid(DCALbrDecoder *s, int ch1, int ch2)
+{
+    int i, ch, sb;
+
+    for (ch = ch1; ch <= ch2; ch++) {
+        for (sb = 0; sb < s->nsubbands; sb++) {
+            int g1_sb = ff_dca_scf_to_grid_1[sb];
+
+            uint8_t *g1_scf_a = s->grid_1_scf[ch][g1_sb    ];
+            uint8_t *g1_scf_b = s->grid_1_scf[ch][g1_sb + 1];
+
+            int w1 = ff_dca_grid_1_weights[g1_sb    ][sb];
+            int w2 = ff_dca_grid_1_weights[g1_sb + 1][sb];
+
+            uint8_t *hr_scf = s->high_res_scf[ch][sb];
+
+            if (sb < 4) {
+                for (i = 0; i < 8; i++) {
+                    int scf = w1 * g1_scf_a[i] + w2 * g1_scf_b[i];
+                    hr_scf[i] = scf >> 7;
+                }
+            } else {
+                int8_t *g3_scf = s->grid_3_scf[ch][sb - 4];
+                int g3_avg = s->grid_3_avg[ch][sb - 4];
+
+                for (i = 0; i < 8; i++) {
+                    int scf = w1 * g1_scf_a[i] + w2 * g1_scf_b[i];
+                    hr_scf[i] = (scf >> 7) - g3_avg - g3_scf[i];
+                }
+            }
+        }
+    }
+}
+
+/**
+ * Fill unallocated subbands with randomness
+ */
+static void random_ts(DCALbrDecoder *s, int ch1, int ch2)
+{
+    int i, j, k, ch, sb;
+
+    for (ch = ch1; ch <= ch2; ch++) {
+        for (sb = 0; sb < s->nsubbands; sb++) {
+            float *samples = s->time_samples[ch][sb];
+
+            if (s->ch_pres[ch] & (1U << sb))
+                continue;   // Skip allocated subband
+
+            if (sb < 2) {
+                // The first two subbands are always zero
+                memset(samples, 0, DCA_LBR_TIME_SAMPLES * sizeof(float));
+            } else if (sb < 10) {
+                for (i = 0; i < DCA_LBR_TIME_SAMPLES; i++)
+                    samples[i] = lbr_rand(s, sb);
+            } else {
+                for (i = 0; i < DCA_LBR_TIME_SAMPLES / 8; i++, samples += 8) {
+                    float accum[8] = { 0 };
+
+                    // Modulate by subbands 2-5 in blocks of 8
+                    for (k = 2; k < 6; k++) {
+                        float *other = &s->time_samples[ch][k][i * 8];
+                        for (j = 0; j < 8; j++)
+                            accum[j] += fabs(other[j]);
+                    }
+
+                    for (j = 0; j < 8; j++)
+                        samples[j] = (accum[j] * 0.25f + 0.5f) * lbr_rand(s, sb);
+                }
+            }
+        }
+    }
+}
+
+static void predict(float *samples, const float *coeff, int nsamples)
+{
+    int i, j;
+
+    for (i = 0; i < nsamples; i++) {
+        float res = 0;
+        for (j = 0; j < 8; j++)
+            res += coeff[j] * samples[i - j - 1];
+        samples[i] -= res;
+    }
+}
+
+static void synth_lpc(DCALbrDecoder *s, int ch1, int ch2, int sb)
+{
+    int f = s->framenum & 1;
+    int ch;
+
+    for (ch = ch1; ch <= ch2; ch++) {
+        float *samples = s->time_samples[ch][sb];
+
+        if (!(s->ch_pres[ch] & (1U << sb)))
+            continue;
+
+        if (sb < 2) {
+            predict(samples,      s->lpc_coeff[f^1][ch][sb][1],  16);
+            predict(samples + 16, s->lpc_coeff[f  ][ch][sb][0],  64);
+            predict(samples + 80, s->lpc_coeff[f  ][ch][sb][1],  48);
+        } else {
+            predict(samples,      s->lpc_coeff[f^1][ch][sb][0],  16);
+            predict(samples + 16, s->lpc_coeff[f  ][ch][sb][0], 112);
+        }
+    }
+}
+
+static void filter_ts(DCALbrDecoder *s, int ch1, int ch2)
+{
+    int i, j, sb, ch;
+
+    for (sb = 0; sb < s->nsubbands; sb++) {
+        // Scale factors
+        for (ch = ch1; ch <= ch2; ch++) {
+            float *samples = s->time_samples[ch][sb];
+            uint8_t *hr_scf = s->high_res_scf[ch][sb];
+            if (sb < 4) {
+                for (i = 0; i < DCA_LBR_TIME_SAMPLES / 16; i++, samples += 16) {
+                    unsigned int scf = hr_scf[i];
+                    if (scf > AMP_MAX)
+                        scf = AMP_MAX;
+                    for (j = 0; j < 16; j++)
+                        samples[j] *= ff_dca_quant_amp[scf];
+                }
+            } else {
+                uint8_t *g2_scf = s->grid_2_scf[ch][ff_dca_scf_to_grid_2[sb]];
+                for (i = 0; i < DCA_LBR_TIME_SAMPLES / 2; i++, samples += 2) {
+                    unsigned int scf = hr_scf[i / 8] - g2_scf[i];
+                    if (scf > AMP_MAX)
+                        scf = AMP_MAX;
+                    samples[0] *= ff_dca_quant_amp[scf];
+                    samples[1] *= ff_dca_quant_amp[scf];
+                }
+            }
+        }
+
+        // Mid-side stereo
+        if (ch1 != ch2) {
+            float *samples_l = s->time_samples[ch1][sb];
+            float *samples_r = s->time_samples[ch2][sb];
+            int ch2_pres = s->ch_pres[ch2] & (1U << sb);
+
+            for (i = 0; i < DCA_LBR_TIME_SAMPLES / 16; i++) {
+                int sbms = (s->sec_ch_sbms[ch1 / 2][sb] >> i) & 1;
+                int lrms = (s->sec_ch_lrms[ch1 / 2][sb] >> i) & 1;
+
+                if (sb >= s->min_mono_subband) {
+                    if (lrms && ch2_pres) {
+                        if (sbms) {
+                            for (j = 0; j < 16; j++) {
+                                float tmp = samples_l[j];
+                                samples_l[j] =  samples_r[j];
+                                samples_r[j] = -tmp;
+                            }
+                        } else {
+                            for (j = 0; j < 16; j++) {
+                                float tmp = samples_l[j];
+                                samples_l[j] =  samples_r[j];
+                                samples_r[j] =  tmp;
+                            }
+                        }
+                    } else if (!ch2_pres) {
+                        if (sbms && (s->part_stereo_pres & (1 << ch1))) {
+                            for (j = 0; j < 16; j++)
+                                samples_r[j] = -samples_l[j];
+                        } else {
+                            for (j = 0; j < 16; j++)
+                                samples_r[j] =  samples_l[j];
+                        }
+                    }
+                } else if (sbms && ch2_pres) {
+                    for (j = 0; j < 16; j++) {
+                        float tmp = samples_l[j];
+                        samples_l[j] = (tmp + samples_r[j]) * 0.5f;
+                        samples_r[j] = (tmp - samples_r[j]) * 0.5f;
+                    }
+                }
+
+                samples_l += 16;
+                samples_r += 16;
+            }
+        }
+
+        // Inverse prediction
+        if (sb < 3)
+            synth_lpc(s, ch1, ch2, sb);
+    }
+}
+
+/**
+ * Modulate by interpolated partial stereo coefficients
+ */
+static void decode_part_stereo(DCALbrDecoder *s, int ch1, int ch2)
+{
+    int i, ch, sb, sf;
+
+    for (ch = ch1; ch <= ch2; ch++) {
+        for (sb = s->min_mono_subband; sb < s->nsubbands; sb++) {
+            uint8_t *pt_st = s->part_stereo[ch][(sb - s->min_mono_subband) / 4];
+            float *samples = s->time_samples[ch][sb];
+
+            if (s->ch_pres[ch2] & (1U << sb))
+                continue;
+
+            for (sf = 1; sf <= 4; sf++, samples += 32) {
+                float prev = ff_dca_st_coeff[pt_st[sf - 1]];
+                float next = ff_dca_st_coeff[pt_st[sf    ]];
+
+                for (i = 0; i < 32; i++)
+                    samples[i] *= (32 - i) * prev + i * next;
+            }
+        }
+    }
+}
+
+/**
+ * Synthesise tones in the given group for the given tonal subframe
+ */
+static void synth_tones(DCALbrDecoder *s, int ch, float *values,
+                        int group, int group_sf, int synth_idx)
+{
+    int i, start, count;
+
+    if (synth_idx < 0)
+        return;
+
+    start =  s->tonal_bounds[group][group_sf][0];
+    count = (s->tonal_bounds[group][group_sf][1] - start) & (DCA_LBR_TONES - 1);
+
+    for (i = 0; i < count; i++) {
+        DCALbrTone *t = &s->tones[(start + i) & (DCA_LBR_TONES - 1)];
+
+        if (t->amp[ch]) {
+            float amp = ff_dca_synth_env[synth_idx] * ff_dca_quant_amp[t->amp[ch]];
+            float c = amp * cos_tab[(t->phs[ch]     ) & 255];
+            float s = amp * cos_tab[(t->phs[ch] + 64) & 255];
+            const float *cf = ff_dca_corr_cf[t->f_delt];
+            int x_freq = t->x_freq;
+
+            switch (x_freq) {
+            case 0:
+                goto p0;
+            case 1:
+                values[3] += cf[0] * -s;
+                values[2] += cf[1] *  c;
+                values[1] += cf[2] *  s;
+                values[0] += cf[3] * -c;
+                goto p1;
+            case 2:
+                values[2] += cf[0] * -s;
+                values[1] += cf[1] *  c;
+                values[0] += cf[2] *  s;
+                goto p2;
+            case 3:
+                values[1] += cf[0] * -s;
+                values[0] += cf[1] *  c;
+                goto p3;
+            case 4:
+                values[0] += cf[0] * -s;
+                goto p4;
+            }
+
+            values[x_freq - 5] += cf[ 0] * -s;
+        p4: values[x_freq - 4] += cf[ 1] *  c;
+        p3: values[x_freq - 3] += cf[ 2] *  s;
+        p2: values[x_freq - 2] += cf[ 3] * -c;
+        p1: values[x_freq - 1] += cf[ 4] * -s;
+        p0: values[x_freq    ] += cf[ 5] *  c;
+            values[x_freq + 1] += cf[ 6] *  s;
+            values[x_freq + 2] += cf[ 7] * -c;
+            values[x_freq + 3] += cf[ 8] * -s;
+            values[x_freq + 4] += cf[ 9] *  c;
+            values[x_freq + 5] += cf[10] *  s;
+        }
+
+        t->phs[ch] += t->ph_rot;
+    }
+}
+
+/**
+ * Synthesise all tones in all groups for the given residual subframe
+ */
+static void base_func_synth(DCALbrDecoder *s, int ch, float *values, int sf)
+{
+    int group;
+
+    // Tonal vs residual shift is 22 subframes
+    for (group = 0; group < 5; group++) {
+        int group_sf = (s->framenum << group) + ((sf - 22) >> (5 - group));
+        int synth_idx = ((((sf - 22) & 31) << group) & 31) + (1 << group) - 1;
+
+        synth_tones(s, ch, values, group, (group_sf - 1) & 31, 30 - synth_idx);
+        synth_tones(s, ch, values, group, (group_sf    ) & 31,      synth_idx);
+    }
+}
+
+static void transform_channel(DCALbrDecoder *s, int ch, float *output)
+{
+    LOCAL_ALIGNED_32(float, values, [DCA_LBR_SUBBANDS    ], [4]);
+    LOCAL_ALIGNED_32(float, result, [DCA_LBR_SUBBANDS * 2], [4]);
+    int sf, sb, nsubbands = s->nsubbands, noutsubbands = 8 << s->freq_range;
+
+    // Clear inactive subbands
+    if (nsubbands < noutsubbands)
+        memset(values[nsubbands], 0, (noutsubbands - nsubbands) * sizeof(values[0]));
+
+    for (sf = 0; sf < DCA_LBR_TIME_SAMPLES / 4; sf++) {
+        // Hybrid filterbank
+        s->dcadsp->lbr_bank(values, s->time_samples[ch],
+                            ff_dca_bank_coeff, sf * 4, nsubbands);
+
+        base_func_synth(s, ch, values[0], sf);
+
+        s->imdct.imdct_calc(&s->imdct, result[0], values[0]);
+
+        // Long window and overlap-add
+        s->fdsp->vector_fmul_add(output, result[0], s->window,
+                                 s->history[ch], noutsubbands * 4);
+        s->fdsp->vector_fmul_reverse(s->history[ch], result[noutsubbands],
+                                     s->window, noutsubbands * 4);
+        output += noutsubbands * 4;
+    }
+
+    // Update history for LPC and forward MDCT
+    for (sb = 0; sb < nsubbands; sb++) {
+        float *samples = s->time_samples[ch][sb] - DCA_LBR_TIME_HISTORY;
+        memcpy(samples, samples + DCA_LBR_TIME_SAMPLES, DCA_LBR_TIME_HISTORY * sizeof(float));
+    }
+}
+
+int ff_dca_lbr_filter_frame(DCALbrDecoder *s, AVFrame *frame)
+{
+    AVCodecContext *avctx = s->avctx;
+    int i, ret, nchannels, ch_conf = (s->ch_mask & 0x7) - 1;
+    const int8_t *reorder;
+
+    avctx->channel_layout = channel_layouts[ch_conf];
+    avctx->channels = nchannels = channel_counts[ch_conf];
+    avctx->sample_rate = s->sample_rate;
+    avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
+    avctx->bits_per_raw_sample = 0;
+    avctx->profile = FF_PROFILE_DTS_EXPRESS;
+    avctx->bit_rate = s->bit_rate_scaled;
+
+    if (s->flags & LBR_FLAG_LFE_PRESENT) {
+        avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
+        avctx->channels++;
+        reorder = channel_reorder_lfe[ch_conf];
+    } else {
+        reorder = channel_reorder_nolfe[ch_conf];
+    }
+
+    frame->nb_samples = 1024 << s->freq_range;
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+        return ret;
+
+    // Filter fullband channels
+    for (i = 0; i < (s->nchannels + 1) / 2; i++) {
+        int ch1 = i * 2;
+        int ch2 = FFMIN(ch1 + 1, s->nchannels - 1);
+
+        decode_grid(s, ch1, ch2);
+
+        random_ts(s, ch1, ch2);
+
+        filter_ts(s, ch1, ch2);
+
+        if (ch1 != ch2 && (s->part_stereo_pres & (1 << ch1)))
+            decode_part_stereo(s, ch1, ch2);
+
+        if (ch1 < nchannels)
+            transform_channel(s, ch1, (float *)frame->extended_data[reorder[ch1]]);
+
+        if (ch1 != ch2 && ch2 < nchannels)
+            transform_channel(s, ch2, (float *)frame->extended_data[reorder[ch2]]);
+    }
+
+    // Interpolate LFE channel
+    if (s->flags & LBR_FLAG_LFE_PRESENT) {
+        s->dcadsp->lfe_iir((float *)frame->extended_data[lfe_index[ch_conf]],
+                           s->lfe_data, ff_dca_lfe_iir,
+                           s->lfe_history, 16 << s->freq_range);
+    }
+
+    if ((ret = ff_side_data_update_matrix_encoding(frame, AV_MATRIX_ENCODING_NONE)) < 0)
+        return ret;
+
+    return 0;
+}
+
+av_cold void ff_dca_lbr_flush(DCALbrDecoder *s)
+{
+    int ch, sb;
+
+    if (!s->sample_rate)
+        return;
+
+    // Clear history
+    memset(s->part_stereo, 16, sizeof(s->part_stereo));
+    memset(s->lpc_coeff, 0, sizeof(s->lpc_coeff));
+    memset(s->history, 0, sizeof(s->history));
+    memset(s->tonal_bounds, 0, sizeof(s->tonal_bounds));
+    memset(s->lfe_history, 0, sizeof(s->lfe_history));
+    s->framenum = 0;
+    s->ntones = 0;
+
+    for (ch = 0; ch < s->nchannels; ch++) {
+        for (sb = 0; sb < s->nsubbands; sb++) {
+            float *samples = s->time_samples[ch][sb] - DCA_LBR_TIME_HISTORY;
+            memset(samples, 0, DCA_LBR_TIME_HISTORY * sizeof(float));
+        }
+    }
+}
+
+av_cold int ff_dca_lbr_init(DCALbrDecoder *s)
+{
+    init_tables();
+
+    if (!(s->fdsp = avpriv_float_dsp_alloc(0)))
+        return -1;
+
+    s->lbr_rand = 1;
+    return 0;
+}
+
+av_cold void ff_dca_lbr_close(DCALbrDecoder *s)
+{
+    s->sample_rate = 0;
+
+    av_freep(&s->ts_buffer);
+    s->ts_size = 0;
+
+    av_freep(&s->fdsp);
+    ff_mdct_end(&s->imdct);
+}
diff --git a/libavcodec/dca_lbr.h b/libavcodec/dca_lbr.h
new file mode 100644
index 0000000..e6ca805
--- /dev/null
+++ b/libavcodec/dca_lbr.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2016 foo86
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_DCA_LBR_H
+#define AVCODEC_DCA_LBR_H
+
+#include "libavutil/common.h"
+#include "libavutil/float_dsp.h"
+#include "libavutil/mem.h"
+
+#include "avcodec.h"
+#include "internal.h"
+#include "get_bits.h"
+#include "dca.h"
+#include "dca_exss.h"
+#include "dcadsp.h"
+#include "fft.h"
+
+#define DCA_LBR_CHANNELS        6
+#define DCA_LBR_CHANNELS_TOTAL  32
+#define DCA_LBR_SUBBANDS        32
+#define DCA_LBR_TONES           512
+
+#define DCA_LBR_TIME_SAMPLES    128
+#define DCA_LBR_TIME_HISTORY    8
+
+typedef struct DCALbrTone {
+    uint8_t     x_freq;     ///< Spectral line offset
+    uint8_t     f_delt;     ///< Difference between original and center frequency
+    uint8_t     ph_rot;     ///< Phase rotation
+    uint8_t     pad;        ///< Padding field
+    uint8_t     amp[DCA_LBR_CHANNELS];  ///< Per-channel amplitude
+    uint8_t     phs[DCA_LBR_CHANNELS];  ///< Per-channel phase
+} DCALbrTone;
+
+typedef struct DCALbrDecoder {
+    AVCodecContext  *avctx;
+    GetBitContext   gb;
+
+    int     sample_rate;        ///< Sample rate of LBR audio
+    int     ch_mask;            ///< LBR speaker mask
+    int     flags;              ///< Flags for LBR decoder initialization
+    int     bit_rate_orig;      ///< Original bit rate
+    int     bit_rate_scaled;    ///< Scaled bit rate
+
+    int     nchannels;          ///< Number of fullband channels to decode
+    int     nchannels_total;    ///< Total number of fullband channels
+    int     freq_range;         ///< Frequency range of LBR audio
+    int     band_limit;         ///< Band limit factor
+    int     limited_rate;       ///< Band limited sample rate
+    int     limited_range;      ///< Band limited frequency range
+    int     res_profile;        ///< Resolution profile
+    int     nsubbands;          ///< Number of encoded subbands
+    int     g3_avg_only_start_sb;   ///< Subband index where grid 3 scale factors end
+    int     min_mono_subband;   ///< Subband index where mono encoding starts
+    int     max_mono_subband;   ///< Subband index where mono encoding ends
+
+    int     framenum;   ///< Lower 5 bits of current frame number
+    int     lbr_rand;   ///< Seed for subband randomization
+    int     warned;     ///< Flags for warning suppression
+
+    uint8_t     quant_levels[DCA_LBR_CHANNELS / 2][DCA_LBR_SUBBANDS];   ///< Quantization levels
+    uint8_t     sb_indices[DCA_LBR_SUBBANDS];   ///< Subband reordering indices
+
+    uint8_t     sec_ch_sbms[DCA_LBR_CHANNELS / 2][DCA_LBR_SUBBANDS];    ///< Right channel inversion or mid/side decoding flags
+    uint8_t     sec_ch_lrms[DCA_LBR_CHANNELS / 2][DCA_LBR_SUBBANDS];    ///< Flags indicating if left/right channel are swapped
+    uint32_t    ch_pres[DCA_LBR_CHANNELS];  ///< Subband allocation flags
+
+    uint8_t     grid_1_scf[DCA_LBR_CHANNELS][12][8];    ///< Grid 1 scale factors
+    uint8_t     grid_2_scf[DCA_LBR_CHANNELS][3][64];    ///< Grid 2 scale factors
+
+    int8_t      grid_3_avg[DCA_LBR_CHANNELS][DCA_LBR_SUBBANDS - 4];     ///< Grid 3 average values
+    int8_t      grid_3_scf[DCA_LBR_CHANNELS][DCA_LBR_SUBBANDS - 4][8];  ///< Grid 3 scale factors
+    uint32_t    grid_3_pres[DCA_LBR_CHANNELS];  ///< Grid 3 scale factors presence flags
+
+    uint8_t     high_res_scf[DCA_LBR_CHANNELS][DCA_LBR_SUBBANDS][8];    ///< High-frequency resolution scale factors
+
+    uint8_t     part_stereo[DCA_LBR_CHANNELS][DCA_LBR_SUBBANDS / 4][5]; ///< Partial stereo coefficients
+    uint8_t     part_stereo_pres;   ///< Partial stereo coefficients presence flags
+
+    float       lpc_coeff[2][DCA_LBR_CHANNELS][3][2][8];    ///< Predictor coefficients
+
+    float       sb_scf[DCA_LBR_SUBBANDS];   ///< Subband randomization scale factors
+
+    float       *time_samples[DCA_LBR_CHANNELS][DCA_LBR_SUBBANDS]; ///< Time samples
+
+    float           *ts_buffer; ///< Time sample buffer base
+    unsigned int    ts_size;    ///< Time sample buffer size
+
+    DECLARE_ALIGNED(32, float, history)[DCA_LBR_CHANNELS][DCA_LBR_SUBBANDS * 4];    ///< IMDCT history
+    DECLARE_ALIGNED(32, float, window)[DCA_LBR_SUBBANDS * 4];   ///< Long window for IMDCT
+
+    DECLARE_ALIGNED(32, float, lfe_data)[64];       ///< Decimated LFE samples
+    DECLARE_ALIGNED(32, float, lfe_history)[5][2];  ///< LFE IIR filter history
+    float lfe_scale;    ///< Scale factor of LFE samples before IIR filter
+
+    uint8_t     tonal_scf[6];           ///< Tonal scale factors
+    uint16_t    tonal_bounds[5][32][2]; ///< Per-group per-subframe start/end positions of tones
+    DCALbrTone  tones[DCA_LBR_TONES];   ///< Circular buffer of tones
+    int         ntones;                 ///< Circular buffer head position
+
+    FFTContext          imdct;
+    AVFloatDSPContext   *fdsp;
+    DCADSPContext       *dcadsp;
+} DCALbrDecoder;
+
+int ff_dca_lbr_parse(DCALbrDecoder *s, uint8_t *data, DCAExssAsset *asset);
+int ff_dca_lbr_filter_frame(DCALbrDecoder *s, AVFrame *frame);
+av_cold void ff_dca_lbr_flush(DCALbrDecoder *s);
+av_cold int ff_dca_lbr_init(DCALbrDecoder *s);
+av_cold void ff_dca_lbr_close(DCALbrDecoder *s);
+
+#endif
diff --git a/libavcodec/dca_parser.c b/libavcodec/dca_parser.c
index bde7dfe..e5bea33 100644
--- a/libavcodec/dca_parser.c
+++ b/libavcodec/dca_parser.c
@@ -23,6 +23,7 @@
  */
 
 #include "dca.h"
+#include "dca_exss.h"
 #include "dca_syncwords.h"
 #include "get_bits.h"
 #include "parser.h"
@@ -32,6 +33,9 @@ typedef struct DCAParseContext {
     uint32_t lastmarker;
     int size;
     int framesize;
+    unsigned int startpos;
+    DCAExssParser exss;
+    unsigned int sr_code;
 } DCAParseContext;
 
 #define IS_CORE_MARKER(state) \
@@ -47,6 +51,14 @@ typedef struct DCAParseContext {
 #define CORE_MARKER(state)      ((state >> 16) & 0xFFFFFFFF)
 #define EXSS_MARKER(state)      (state & 0xFFFFFFFF)
 
+#define STATE_LE(state)     (((state & 0xFF00FF00) >> 8) | ((state & 0x00FF00FF) << 8))
+#define STATE_14(state)     (((state & 0x3FFF0000) >> 8) | ((state & 0x00003FFF) >> 6))
+
+#define CORE_FRAMESIZE(state)   (((state >> 4) & 0x3FFF) + 1)
+#define EXSS_FRAMESIZE(state)   ((state & 0x2000000000) ? \
+                                 ((state >>  5) & 0xFFFFF) + 1 : \
+                                 ((state >> 13) & 0x0FFFF) + 1)
+
 /**
  * Find the end of the current frame in the bitstream.
  * @return the position of the first byte of the next frame, or -1
@@ -54,41 +66,105 @@ typedef struct DCAParseContext {
 static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf,
                               int buf_size)
 {
-    int start_found, i;
+    int start_found, size, i;
     uint64_t state;
     ParseContext *pc = &pc1->pc;
 
     start_found = pc->frame_start_found;
     state       = pc->state64;
+    size        = pc1->size;
 
     i = 0;
     if (!start_found) {
-        for (i = 0; i < buf_size; i++) {
+        for (; i < buf_size; i++) {
+            size++;
             state = (state << 8) | buf[i];
-            if (IS_MARKER(state)) {
-                if (!pc1->lastmarker ||
-                    pc1->lastmarker == CORE_MARKER(state) ||
-                    pc1->lastmarker == DCA_SYNCWORD_SUBSTREAM) {
-                    start_found = 1;
-                    if (IS_EXSS_MARKER(state))
-                        pc1->lastmarker = EXSS_MARKER(state);
-                    else
-                        pc1->lastmarker = CORE_MARKER(state);
-                    i++;
-                    break;
-                }
+
+            if (IS_MARKER(state) &&
+                (!pc1->lastmarker ||
+                  pc1->lastmarker == CORE_MARKER(state) ||
+                  pc1->lastmarker == DCA_SYNCWORD_SUBSTREAM)) {
+                if (!pc1->lastmarker)
+                    pc1->startpos = IS_EXSS_MARKER(state) ? size - 4 : size - 6;
+
+                if (IS_EXSS_MARKER(state))
+                    pc1->lastmarker = EXSS_MARKER(state);
+                else
+                    pc1->lastmarker = CORE_MARKER(state);
+
+                start_found = 1;
+                size        = 0;
+
+                i++;
+                break;
             }
         }
     }
+
     if (start_found) {
         for (; i < buf_size; i++) {
-            pc1->size++;
+            size++;
             state = (state << 8) | buf[i];
+
+            if (start_found == 1) {
+                switch (pc1->lastmarker) {
+                case DCA_SYNCWORD_CORE_BE:
+                    if (size == 2) {
+                        pc1->framesize = CORE_FRAMESIZE(state);
+                        start_found    = 2;
+                    }
+                    break;
+                case DCA_SYNCWORD_CORE_LE:
+                    if (size == 2) {
+                        pc1->framesize = CORE_FRAMESIZE(STATE_LE(state));
+                        start_found    = 4;
+                    }
+                    break;
+                case DCA_SYNCWORD_CORE_14B_BE:
+                    if (size == 4) {
+                        pc1->framesize = CORE_FRAMESIZE(STATE_14(state)) * 8 / 14 * 2;
+                        start_found    = 4;
+                    }
+                    break;
+                case DCA_SYNCWORD_CORE_14B_LE:
+                    if (size == 4) {
+                        pc1->framesize = CORE_FRAMESIZE(STATE_14(STATE_LE(state))) * 8 / 14 * 2;
+                        start_found    = 4;
+                    }
+                    break;
+                case DCA_SYNCWORD_SUBSTREAM:
+                    if (size == 6) {
+                        pc1->framesize = EXSS_FRAMESIZE(state);
+                        start_found    = 4;
+                    }
+                    break;
+                default:
+                    av_assert0(0);
+                }
+                continue;
+            }
+
+            if (start_found == 2 && IS_EXSS_MARKER(state) &&
+                pc1->framesize <= size + 2) {
+                pc1->framesize  = size + 2;
+                start_found     = 3;
+                continue;
+            }
+
+            if (start_found == 3) {
+                if (size == pc1->framesize + 4) {
+                    pc1->framesize += EXSS_FRAMESIZE(state);
+                    start_found     = 4;
+                }
+                continue;
+            }
+
+            if (pc1->framesize > size)
+                continue;
+
             if (IS_MARKER(state) &&
                 (pc1->lastmarker == CORE_MARKER(state) ||
                  pc1->lastmarker == DCA_SYNCWORD_SUBSTREAM)) {
-                if (pc1->framesize > pc1->size)
-                    continue;
                 pc->frame_start_found = 0;
                 pc->state64           = -1;
                 pc1->size             = 0;
@@ -96,8 +172,10 @@ static int dca_find_frame_end(DCAParseContext *pc1, const uint8_t *buf,
             }
         }
     }
+
     pc->frame_start_found = start_found;
     pc->state64           = state;
+    pc1->size             = size;
     return END_NOT_FOUND;
 }
 
@@ -106,19 +184,77 @@ static av_cold int dca_parse_init(AVCodecParserContext *s)
     DCAParseContext *pc1 = s->priv_data;
 
     pc1->lastmarker = 0;
+    pc1->sr_code = -1;
     return 0;
 }
 
-static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration,
-                            int *sample_rate, int *framesize)
+static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf,
+                            int buf_size, int *duration, int *sample_rate)
 {
     GetBitContext gb;
     uint8_t hdr[12 + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 };
-    int ret, sample_blocks, sr_code;
+    int ret, sample_blocks;
 
     if (buf_size < 12)
         return AVERROR_INVALIDDATA;
 
+    if (AV_RB32(buf) == DCA_SYNCWORD_SUBSTREAM) {
+        DCAExssAsset *asset = &pc1->exss.assets[0];
+
+        if ((ret = ff_dca_exss_parse(&pc1->exss, buf, buf_size)) < 0)
+            return ret;
+
+        if (asset->extension_mask & DCA_EXSS_LBR) {
+            if ((ret = init_get_bits8(&gb, buf + asset->lbr_offset, asset->lbr_size)) < 0)
+                return ret;
+
+            if (get_bits_long(&gb, 32) != DCA_SYNCWORD_LBR)
+                return AVERROR_INVALIDDATA;
+
+            switch (get_bits(&gb, 8)) {
+            case 2:
+                pc1->sr_code = get_bits(&gb, 8);
+            case 1:
+                break;
+            default:
+                return AVERROR_INVALIDDATA;
+            }
+
+            if (pc1->sr_code >= FF_ARRAY_ELEMS(ff_dca_sampling_freqs))
+                return AVERROR_INVALIDDATA;
+
+            *sample_rate = ff_dca_sampling_freqs[pc1->sr_code];
+            *duration = 1024 << ff_dca_freq_ranges[pc1->sr_code];
+            return 0;
+        }
+
+        if (asset->extension_mask & DCA_EXSS_XLL) {
+            int nsamples_log2;
+
+            if ((ret = init_get_bits8(&gb, buf + asset->xll_offset, asset->xll_size)) < 0)
+                return ret;
+
+            if (get_bits_long(&gb, 32) != DCA_SYNCWORD_XLL)
+                return AVERROR_INVALIDDATA;
+
+            if (get_bits(&gb, 4))
+                return AVERROR_INVALIDDATA;
+
+            skip_bits(&gb, 8);
+            skip_bits_long(&gb, get_bits(&gb, 5) + 1);
+            skip_bits(&gb, 4);
+            nsamples_log2 = get_bits(&gb, 4) + get_bits(&gb, 4);
+            if (nsamples_log2 > 24)
+                return AVERROR_INVALIDDATA;
+
+            *sample_rate = asset->max_sample_rate;
+            *duration = (1 + (*sample_rate > 96000)) << nsamples_log2;
+            return 0;
+        }
+
+        return AVERROR_INVALIDDATA;
+    }
+
     if ((ret = avpriv_dca_convert_bitstream(buf, 12, hdr, 12)) < 0)
         return ret;
 
@@ -130,13 +266,8 @@ static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration,
         return AVERROR_INVALIDDATA;
     *duration = 256 * (sample_blocks / 8);
 
-    *framesize = get_bits(&gb, 14) + 1;
-    if (*framesize < 95)
-        return AVERROR_INVALIDDATA;
-
-    skip_bits(&gb, 6);
-    sr_code      = get_bits(&gb, 4);
-    *sample_rate = avpriv_dca_sample_rates[sr_code];
+    skip_bits(&gb, 20);
+    *sample_rate = avpriv_dca_sample_rates[get_bits(&gb, 4)];
     if (*sample_rate == 0)
         return AVERROR_INVALIDDATA;
 
@@ -161,10 +292,17 @@ static int dca_parse(AVCodecParserContext *s, AVCodecContext *avctx,
             *poutbuf_size = 0;
             return buf_size;
         }
+
+        /* skip initial padding */
+        if (buf_size  > pc1->startpos) {
+            buf      += pc1->startpos;
+            buf_size -= pc1->startpos;
+        }
+        pc1->startpos = 0;
     }
 
     /* read the duration and sample rate from the frame header */
-    if (!dca_parse_params(buf, buf_size, &duration, &sample_rate, &pc1->framesize)) {
+    if (!dca_parse_params(pc1, buf, buf_size, &duration, &sample_rate)) {
         if (!avctx->sample_rate)
             avctx->sample_rate = sample_rate;
         s->duration = av_rescale(duration, avctx->sample_rate, sample_rate);
diff --git a/libavcodec/dca_xll.c b/libavcodec/dca_xll.c
index cd1af81..1d616c2 100644
--- a/libavcodec/dca_xll.c
+++ b/libavcodec/dca_xll.c
@@ -32,7 +32,7 @@ static int get_linear(GetBitContext *gb, int n)
 
 static int get_rice_un(GetBitContext *gb, int k)
 {
-    unsigned int v = get_unary(gb, 1, 128);
+    unsigned int v = get_unary(gb, 1, get_bits_left(gb));
     return (v << k) | get_bits_long(gb, k);
 }
 
@@ -123,8 +123,7 @@ static int chs_parse_header(DCAXllDecoder *s, DCAXllChSet *c, DCAExssAsset *asse
     header_size = get_bits(&s->gb, 10) + 1;
 
     // Check CRC
-    if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-        && ff_dca_check_crc(&s->gb, header_pos, header_pos + header_size * 8)) {
+    if (ff_dca_check_crc(s->avctx, &s->gb, header_pos, header_pos + header_size * 8)) {
         av_log(s->avctx, AV_LOG_ERROR, "Invalid XLL sub-header checksum\n");
         return AVERROR_INVALIDDATA;
     }
@@ -460,19 +459,14 @@ static int chs_parse_band_data(DCAXllDecoder *s, DCAXllChSet *c, int band, int s
             // Unpack Rice coding flag
             // 0 - linear code, 1 - Rice code
             c->rice_code_flag[i] = get_bits1(&s->gb);
-            if (!c->seg_common && c->rice_code_flag[i]) {
-                // Unpack Hybrid Rice coding flag
-                // 0 - Rice code, 1 - Hybrid Rice code
-                if (get_bits1(&s->gb))
-                    // Unpack binary code length for isolated samples
-                    c->bitalloc_hybrid_linear[i] = get_bits(&s->gb, c->nabits) + 1;
-                else
-                    // 0 indicates no Hybrid Rice coding
-                    c->bitalloc_hybrid_linear[i] = 0;
-            } else {
+            // Unpack Hybrid Rice coding flag
+            // 0 - Rice code, 1 - Hybrid Rice code
+            if (!c->seg_common && c->rice_code_flag[i] && get_bits1(&s->gb))
+                // Unpack binary code length for isolated samples
+                c->bitalloc_hybrid_linear[i] = get_bits(&s->gb, c->nabits) + 1;
+            else
                 // 0 indicates no Hybrid Rice coding
                 c->bitalloc_hybrid_linear[i] = 0;
-            }
         }
 
         // Unpack coding parameters
@@ -602,7 +596,7 @@ static int chs_parse_band_data(DCAXllDecoder *s, DCAXllChSet *c, int band, int s
     return 0;
 }
 
-static void av_cold chs_clear_band_data(DCAXllDecoder *s, DCAXllChSet *c, int band, int seg)
+static av_cold void chs_clear_band_data(DCAXllDecoder *s, DCAXllChSet *c, int band, int seg)
 {
     DCAXllBand *b = &c->bands[band];
     int i, offset, nsamples;
@@ -789,8 +783,7 @@ static int parse_common_header(DCAXllDecoder *s)
     header_size = get_bits(&s->gb, 8) + 1;
 
     // Check CRC
-    if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-        && ff_dca_check_crc(&s->gb, 32, header_size * 8)) {
+    if (ff_dca_check_crc(s->avctx, &s->gb, 32, header_size * 8)) {
         av_log(s->avctx, AV_LOG_ERROR, "Invalid XLL common header checksum\n");
         return AVERROR_INVALIDDATA;
     }
@@ -998,8 +991,7 @@ static int parse_navi_table(DCAXllDecoder *s)
     skip_bits(&s->gb, 16);
 
     // Check CRC
-    if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
-        && ff_dca_check_crc(&s->gb, navi_pos, get_bits_count(&s->gb))) {
+    if (ff_dca_check_crc(s->avctx, &s->gb, navi_pos, get_bits_count(&s->gb))) {
         av_log(s->avctx, AV_LOG_ERROR, "Invalid NAVI checksum\n");
         return AVERROR_INVALIDDATA;
     }
@@ -1078,7 +1070,7 @@ static int copy_to_pbr(DCAXllDecoder *s, uint8_t *data, int size, int delay)
     if (size > DCA_XLL_PBR_BUFFER_MAX)
         return AVERROR(ENOSPC);
 
-    if (!s->pbr_buffer && !(s->pbr_buffer = av_malloc(DCA_XLL_PBR_BUFFER_MAX + DCA_BUFFER_PADDING_SIZE)))
+    if (!s->pbr_buffer && !(s->pbr_buffer = av_malloc(DCA_XLL_PBR_BUFFER_MAX + AV_INPUT_BUFFER_PADDING_SIZE)))
         return AVERROR(ENOMEM);
 
     memcpy(s->pbr_buffer, data, size);
@@ -1242,7 +1234,7 @@ static void scale_down_mix(DCAXllDecoder *s, DCAXllChSet *o, int band)
 
 // Clear all band data and replace non-residual encoded channels with lossy
 // counterparts
-static void av_cold force_lossy_output(DCAXllDecoder *s, DCAXllChSet *c)
+static av_cold void force_lossy_output(DCAXllDecoder *s, DCAXllChSet *c)
 {
     DCAContext *dca = s->avctx->priv_data;
     int band, ch;
diff --git a/libavcodec/dcadata.c b/libavcodec/dcadata.c
index e991134..b2e0f6c 100644
--- a/libavcodec/dcadata.c
+++ b/libavcodec/dcadata.c
@@ -52,7 +52,7 @@ const uint8_t ff_dca_dmix_primary_nch[8] = {
 
 /* ADPCM data */
 
-/* 16bits signed fractional Q13 binary codes */
+/* 16 bits signed fractional Q13 binary codes */
 const int16_t ff_dca_adpcm_vb[4096][4] = {
     {   9928,  -2618,  -1093, -1263 },
     {  11077,  -2876,  -1747,  -308 },
@@ -4215,7 +4215,7 @@ const uint32_t ff_dca_quant_levels[32] = {
     2097152, 4194304, 8388608,     0,      0,      0,      0,       0
 };
 
-/* 20bits unsigned fractional binary codes */
+/* 20 bits unsigned fractional binary codes */
 const uint32_t ff_dca_lossy_quant[32] = {
          0, 6710886, 4194304, 3355443, 2474639, 2097152, 1761608, 1426063,
     796918,  461373,  251658,  146801,   79692,   46137,   27263,   16777,
@@ -4223,7 +4223,7 @@ const uint32_t ff_dca_lossy_quant[32] = {
         84,      42,      21,       0,       0,       0,       0,       0
 };
 
-/* 20bits unsigned fractional binary codes */
+/* 20 bits unsigned fractional binary codes */
 const uint32_t ff_dca_lossless_quant[32] = {
          0, 4194304, 2097152, 1384120, 1048576, 696254, 524288, 348127,
     262144,  131072,   65431,   33026,   16450,   8208,   4100,   2049,
@@ -8725,58 +8725,468 @@ const int32_t ff_dca_xll_band_coeff[20] = {
      3259333, -5074941,  6928550, -8204883
 };
 
-const int32_t ff_dca_sampling_freqs[16] = {
-      8000,  16000, 32000, 64000, 128000, 22050,  44100,  88200,
-    176400, 352800, 12000, 24000,  48000, 96000, 192000, 384000,
+const uint16_t ff_dca_avg_g3_freqs[3] = { 16000, 18000, 24000 };
+
+const uint16_t ff_dca_fst_amp[44] = {
+       0,    1,    2,    3,
+       4,    6,    8,   10,
+      12,   16,   20,   24,
+      28,   36,   44,   52,
+      60,   76,   92,  108,
+     124,  156,  188,  220,
+     252,  316,  380,  444,
+     508,  636,  764,  892,
+    1020, 1276, 1532, 1788,
+    2044, 2556, 3068, 3580,
+    4092, 5116, 6140, 7164
+};
+
+const uint8_t ff_dca_freq_to_sb[32] = {
+    0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+};
+
+const int8_t ff_dca_ph0_shift[8] = {
+    -32, +96, -96, +32, +96, -32, +32, -96
+};
+
+const uint8_t ff_dca_grid_1_to_scf[11] = {
+    0, 1, 2, 3, 4, 6, 7, 10, 14, 19, 26
+};
+
+const uint8_t ff_dca_grid_2_to_scf[3] = {
+    4, 10, 18
+};
+
+const uint8_t ff_dca_scf_to_grid_1[32] = {
+    0, 1, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+    7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10
+};
+
+const uint8_t ff_dca_scf_to_grid_2[32] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+};
+
+const uint8_t ff_dca_grid_1_weights[12][32] = {
+    {
+        128,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+    }, {
+          0, 128,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+    }, {
+          0,   0, 128,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+    }, {
+          0,   0,   0, 128,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+    }, {
+          0,   0,   0,   0, 128, 128,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+    }, {
+          0,   0,   0,   0,   0,   0, 128,  85,
+         43,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+    }, {
+          0,   0,   0,   0,   0,   0,   0,  43,
+         85, 128,  96,  64,  32,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+    }, {
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,  32,  64,  96, 128, 102,  77,
+         51,  26,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+    }, {
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,  26,  51,
+         77, 102, 128, 107,  85,  64,  43,  21,
+          0,   0,   0,   0,   0,   0,   0,   0,
+    }, {
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,  21,  43,  64,  85, 107,
+        128, 110,  91,  73,  55,  37,  18,   0,
+    }, {
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,   0,   0,   0,   0,   0,   0,   0,
+          0,  18,  37,  55,  73,  91, 110, 128,
+    }, {
+        0 /* empty */
+    }
+};
+
+const uint8_t ff_dca_sb_reorder[8][8] = {
+    { 0, 1, 2, 3, 4, 5, 6, 7 },
+    { 1, 0, 2, 3, 4, 5, 6, 7 },
+    { 3, 1, 0, 2, 4, 5, 6, 7 },
+    { 1, 2, 3, 0, 4, 5, 6, 7 },
+    { 1, 2, 5, 3, 0, 4, 6, 7 },
+    { 1, 2, 2, 5, 3, 0, 4, 6 },
+    { 1, 2, 2, 6, 5, 3, 0, 4 },
+    { 1, 2, 2, 6, 5, 4, 0, 3 }
+};
+
+const int8_t ff_dca_lfe_delta_index_16[8] = {
+    -4, -3, -2, -1, 2, 4, 6, 8
+};
+
+const int8_t ff_dca_lfe_delta_index_24[32] = {
+    -8, -8, -7, -7, -6, -6, -5, -5, -4, -4, -3, -3, -2, -2, -1, -1,
+     1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8
+};
+
+const uint16_t ff_dca_rsd_pack_5_in_8[256] = {
+    0x0000, 0x0100, 0x0200, 0x0040, 0x0140, 0x0240, 0x0080, 0x0180,
+    0x0280, 0x0010, 0x0110, 0x0210, 0x0050, 0x0150, 0x0250, 0x0090,
+    0x0190, 0x0290, 0x0020, 0x0120, 0x0220, 0x0060, 0x0160, 0x0260,
+    0x00a0, 0x01a0, 0x02a0, 0x0004, 0x0104, 0x0204, 0x0044, 0x0144,
+    0x0244, 0x0084, 0x0184, 0x0284, 0x0014, 0x0114, 0x0214, 0x0054,
+    0x0154, 0x0254, 0x0094, 0x0194, 0x0294, 0x0024, 0x0124, 0x0224,
+    0x0064, 0x0164, 0x0264, 0x00a4, 0x01a4, 0x02a4, 0x0008, 0x0108,
+    0x0208, 0x0048, 0x0148, 0x0248, 0x0088, 0x0188, 0x0288, 0x0018,
+    0x0118, 0x0218, 0x0058, 0x0158, 0x0258, 0x0098, 0x0198, 0x0298,
+    0x0028, 0x0128, 0x0228, 0x0068, 0x0168, 0x0268, 0x00a8, 0x01a8,
+    0x02a8, 0x0001, 0x0101, 0x0201, 0x0041, 0x0141, 0x0241, 0x0081,
+    0x0181, 0x0281, 0x0011, 0x0111, 0x0211, 0x0051, 0x0151, 0x0251,
+    0x0091, 0x0191, 0x0291, 0x0021, 0x0121, 0x0221, 0x0061, 0x0161,
+    0x0261, 0x00a1, 0x01a1, 0x02a1, 0x0005, 0x0105, 0x0205, 0x0045,
+    0x0145, 0x0245, 0x0085, 0x0185, 0x0285, 0x0015, 0x0115, 0x0215,
+    0x0055, 0x0155, 0x0255, 0x0095, 0x0195, 0x0295, 0x0025, 0x0125,
+    0x0225, 0x0065, 0x0165, 0x0265, 0x00a5, 0x01a5, 0x02a5, 0x0009,
+    0x0109, 0x0209, 0x0049, 0x0149, 0x0249, 0x0089, 0x0189, 0x0289,
+    0x0019, 0x0119, 0x0219, 0x0059, 0x0159, 0x0259, 0x0099, 0x0199,
+    0x0299, 0x0029, 0x0129, 0x0229, 0x0069, 0x0169, 0x0269, 0x00a9,
+    0x01a9, 0x02a9, 0x0002, 0x0102, 0x0202, 0x0042, 0x0142, 0x0242,
+    0x0082, 0x0182, 0x0282, 0x0012, 0x0112, 0x0212, 0x0052, 0x0152,
+    0x0252, 0x0092, 0x0192, 0x0292, 0x0022, 0x0122, 0x0222, 0x0062,
+    0x0162, 0x0262, 0x00a2, 0x01a2, 0x02a2, 0x0006, 0x0106, 0x0206,
+    0x0046, 0x0146, 0x0246, 0x0086, 0x0186, 0x0286, 0x0016, 0x0116,
+    0x0216, 0x0056, 0x0156, 0x0256, 0x0096, 0x0196, 0x0296, 0x0026,
+    0x0126, 0x0226, 0x0066, 0x0166, 0x0266, 0x00a6, 0x01a6, 0x02a6,
+    0x000a, 0x010a, 0x020a, 0x004a, 0x014a, 0x024a, 0x008a, 0x018a,
+    0x028a, 0x001a, 0x011a, 0x021a, 0x005a, 0x015a, 0x025a, 0x009a,
+    0x019a, 0x029a, 0x002a, 0x012a, 0x022a, 0x006a, 0x016a, 0x026a,
+    0x00aa, 0x01aa, 0x02aa, 0x0155, 0x0155, 0x0155, 0x0155, 0x0155,
+    0x0155, 0x0155, 0x0155, 0x0155, 0x0155, 0x0155, 0x0155, 0x0155
+};
+
+const uint8_t ff_dca_rsd_pack_3_in_7[128][3] = {
+    { 0, 0, 0 }, { 0, 0, 1 }, { 0, 0, 2 }, { 0, 0, 3 },
+    { 0, 0, 4 }, { 0, 1, 0 }, { 0, 1, 1 }, { 0, 1, 2 },
+    { 0, 1, 3 }, { 0, 1, 4 }, { 0, 2, 0 }, { 0, 2, 1 },
+    { 0, 2, 2 }, { 0, 2, 3 }, { 0, 2, 4 }, { 0, 3, 0 },
+    { 0, 3, 1 }, { 0, 3, 2 }, { 0, 3, 3 }, { 0, 3, 4 },
+    { 0, 4, 0 }, { 0, 4, 1 }, { 0, 4, 2 }, { 0, 4, 3 },
+    { 0, 4, 4 }, { 1, 0, 0 }, { 1, 0, 1 }, { 1, 0, 2 },
+    { 1, 0, 3 }, { 1, 0, 4 }, { 1, 1, 0 }, { 1, 1, 1 },
+    { 1, 1, 2 }, { 1, 1, 3 }, { 1, 1, 4 }, { 1, 2, 0 },
+    { 1, 2, 1 }, { 1, 2, 2 }, { 1, 2, 3 }, { 1, 2, 4 },
+    { 1, 3, 0 }, { 1, 3, 1 }, { 1, 3, 2 }, { 1, 3, 3 },
+    { 1, 3, 4 }, { 1, 4, 0 }, { 1, 4, 1 }, { 1, 4, 2 },
+    { 1, 4, 3 }, { 1, 4, 4 }, { 2, 0, 0 }, { 2, 0, 1 },
+    { 2, 0, 2 }, { 2, 0, 3 }, { 2, 0, 4 }, { 2, 1, 0 },
+    { 2, 1, 1 }, { 2, 1, 2 }, { 2, 1, 3 }, { 2, 1, 4 },
+    { 2, 2, 0 }, { 2, 2, 1 }, { 2, 2, 2 }, { 2, 2, 3 },
+    { 2, 2, 4 }, { 2, 3, 0 }, { 2, 3, 1 }, { 2, 3, 2 },
+    { 2, 3, 3 }, { 2, 3, 4 }, { 2, 4, 0 }, { 2, 4, 1 },
+    { 2, 4, 2 }, { 2, 4, 3 }, { 2, 4, 4 }, { 3, 0, 0 },
+    { 3, 0, 1 }, { 3, 0, 2 }, { 3, 0, 3 }, { 3, 0, 4 },
+    { 3, 1, 0 }, { 3, 1, 1 }, { 3, 1, 2 }, { 3, 1, 3 },
+    { 3, 1, 4 }, { 3, 2, 0 }, { 3, 2, 1 }, { 3, 2, 2 },
+    { 3, 2, 3 }, { 3, 2, 4 }, { 3, 3, 0 }, { 3, 3, 1 },
+    { 3, 3, 2 }, { 3, 3, 3 }, { 3, 3, 4 }, { 3, 4, 0 },
+    { 3, 4, 1 }, { 3, 4, 2 }, { 3, 4, 3 }, { 3, 4, 4 },
+    { 4, 0, 0 }, { 4, 0, 1 }, { 4, 0, 2 }, { 4, 0, 3 },
+    { 4, 0, 4 }, { 4, 1, 0 }, { 4, 1, 1 }, { 4, 1, 2 },
+    { 4, 1, 3 }, { 4, 1, 4 }, { 4, 2, 0 }, { 4, 2, 1 },
+    { 4, 2, 2 }, { 4, 2, 3 }, { 4, 2, 4 }, { 4, 3, 0 },
+    { 4, 3, 1 }, { 4, 3, 2 }, { 4, 3, 3 }, { 4, 3, 4 },
+    { 4, 4, 0 }, { 4, 4, 1 }, { 4, 4, 2 }, { 4, 4, 3 },
+    { 4, 4, 4 }, { 2, 2, 2 }, { 2, 2, 2 }, { 2, 2, 2 }
+};
+
+const float ff_dca_rsd_level_2a[2] = {
+    -0.47, 0.47
+};
+
+const float ff_dca_rsd_level_2b[2] = {
+    -0.645, 0.645
+};
+
+const float ff_dca_rsd_level_3[3] = {
+    -0.645, 0.0, 0.645
+};
+
+const float ff_dca_rsd_level_5[5] = {
+    -0.875, -0.375, 0.0, 0.375, 0.875
+};
+
+const float ff_dca_rsd_level_8[8] = {
+    -1.0, -0.625, -0.291666667, 0.0, 0.25, 0.5, 0.75, 1.0
+};
+
+const float ff_dca_rsd_level_16[16] = {
+    -1.3125, -1.1375, -0.9625, -0.7875,
+    -0.6125, -0.4375, -0.2625, -0.0875,
+     0.0875,  0.2625,  0.4375,  0.6125,
+     0.7875,  0.9625,  1.1375,  1.3125
+};
+
+const float ff_dca_synth_env[32] = {
+    0.00240763666390, 0.00960735979838, 0.02152983213390, 0.03806023374436,
+    0.05903936782582, 0.08426519384873, 0.11349477331863, 0.14644660940673,
+    0.18280335791818, 0.22221488349020, 0.26430163158700, 0.30865828381746,
+    0.35485766137277, 0.40245483899194, 0.45099142983522, 0.5,
+    0.54900857016478, 0.59754516100806, 0.64514233862723, 0.69134171618254,
+    0.73569836841300, 0.77778511650980, 0.81719664208182, 0.85355339059327,
+    0.88650522668137, 0.91573480615127, 0.94096063217418, 0.96193976625564,
+    0.97847016786610, 0.99039264020162, 0.99759236333610, 1.0
+};
+
+const float ff_dca_corr_cf[32][11] = {
+    {-0.01179, 0.04281, 0.46712, 0.46345,-3.94525, 3.94525,
+     -0.46345,-0.46712,-0.04281, 0.01179,-0.00299 },
+    {-0.00929, 0.04882, 0.45252, 0.37972,-3.85446, 4.03189,
+     -0.55069,-0.48040,-0.03599, 0.01445,-0.00229 },
+    {-0.00696, 0.05403, 0.43674, 0.29961,-3.75975, 4.11413,
+     -0.64135,-0.49221,-0.02834, 0.01726,-0.00156 },
+    {-0.00481, 0.05847, 0.41993, 0.22319,-3.66138, 4.19175,
+     -0.73529,-0.50241,-0.01983, 0.02021,-0.00080 },
+    {-0.00284, 0.06216, 0.40224, 0.15053,-3.55963, 4.26452,
+     -0.83239,-0.51085,-0.01047, 0.02328,-0.00003 },
+    {-0.00105, 0.06515, 0.38378, 0.08168,-3.45475, 4.33225,
+     -0.93249,-0.51738,-0.00024, 0.02646, 0.00074 },
+    { 0.00054, 0.06745, 0.36471, 0.01668,-3.34703, 4.39475,
+     -1.03543,-0.52184, 0.01085, 0.02973, 0.00152 },
+    { 0.00195, 0.06912, 0.34515,-0.04445,-3.23676, 4.45185,
+     -1.14105,-0.52410, 0.02280, 0.03306, 0.00228 },
+    { 0.00318, 0.07017, 0.32521,-0.10168,-3.12422, 4.50339,
+     -1.24914,-0.52400, 0.03561, 0.03643, 0.00302 },
+    { 0.00422, 0.07065, 0.30503,-0.15503,-3.00969, 4.54921,
+     -1.35952,-0.52141, 0.04925, 0.03981, 0.00373 },
+    { 0.00508, 0.07061, 0.28471,-0.20450,-2.89348, 4.58919,
+     -1.47197,-0.51618, 0.06370, 0.04319, 0.00440 },
+    { 0.00577, 0.07007, 0.26436,-0.25013,-2.77587, 4.62321,
+     -1.58627,-0.50818, 0.07895, 0.04652, 0.00501 },
+    { 0.00629, 0.06909, 0.24410,-0.29194,-2.65716, 4.65118,
+     -1.70219,-0.49727, 0.09494, 0.04979, 0.00556 },
+    { 0.00666, 0.06769, 0.22400,-0.33000,-2.53764, 4.67302,
+     -1.81949,-0.48335, 0.11166, 0.05295, 0.00604 },
+    { 0.00687, 0.06592, 0.20416,-0.36435,-2.41760, 4.68866,
+     -1.93791,-0.46627, 0.12904, 0.05597, 0.00642 },
+    { 0.00694, 0.06383, 0.18468,-0.39506,-2.29732, 4.69806,
+     -2.05720,-0.44593, 0.14705, 0.05881, 0.00671 },
+    { 0.00689, 0.06144, 0.16561,-0.42223,-2.17710, 4.70120,
+     -2.17710,-0.42223, 0.16561, 0.06144, 0.00689 },
+    { 0.00671, 0.05881, 0.14705,-0.44593,-2.05720, 4.69806,
+     -2.29732,-0.39506, 0.18468, 0.06383, 0.00694 },
+    { 0.00642, 0.05597, 0.12904,-0.46627,-1.93791, 4.68865,
+     -2.41759,-0.36435, 0.20416, 0.06592, 0.00687 },
+    { 0.00604, 0.05295, 0.11166,-0.48334,-1.81949, 4.67301,
+     -2.53763,-0.33000, 0.22400, 0.06769, 0.00666 },
+    { 0.00556, 0.04979, 0.09494,-0.49727,-1.70219, 4.65117,
+     -2.65715,-0.29194, 0.24409, 0.06909, 0.00629 },
+    { 0.00501, 0.04652, 0.07894,-0.50818,-1.58627, 4.62321,
+     -2.77587,-0.25013, 0.26436, 0.07007, 0.00577 },
+    { 0.00440, 0.04319, 0.06370,-0.51618,-1.47197, 4.58919,
+     -2.89348,-0.20450, 0.28471, 0.07061, 0.00508 },
+    { 0.00373, 0.03981, 0.04925,-0.52141,-1.35952, 4.54921,
+     -3.00970,-0.15503, 0.30503, 0.07065, 0.00422 },
+    { 0.00302, 0.03643, 0.03561,-0.52400,-1.24915, 4.50339,
+     -3.12422,-0.10168, 0.32521, 0.07017, 0.00318 },
+    { 0.00228, 0.03306, 0.02280,-0.52410,-1.14105, 4.45186,
+     -3.23677,-0.04445, 0.34515, 0.06912, 0.00195 },
+    { 0.00152, 0.02973, 0.01085,-0.52184,-1.03544, 4.39477,
+     -3.34704, 0.01668, 0.36471, 0.06745, 0.00054 },
+    { 0.00074, 0.02646,-0.00024,-0.51738,-0.93249, 4.33226,
+     -3.45476, 0.08168, 0.38378, 0.06515,-0.00105 },
+    {-0.00003, 0.02328,-0.01047,-0.51085,-0.83239, 4.26452,
+     -3.55963, 0.15053, 0.40224, 0.06216,-0.00284 },
+    {-0.00080, 0.02021,-0.01983,-0.50241,-0.73529, 4.19174,
+     -3.66138, 0.22319, 0.41993, 0.05847,-0.00481 },
+    {-0.00156, 0.01726,-0.02834,-0.49221,-0.64135, 4.11413,
+     -3.75974, 0.29961, 0.43674, 0.05403,-0.00696 },
+    {-0.00229, 0.01445,-0.03599,-0.48040,-0.55069, 4.03188,
+     -3.85445, 0.37972, 0.45251, 0.04882,-0.00929 },
+};
+
+const float ff_dca_quant_amp[57] = {
+    4.88281250E-04, 1.46484375E-03, 2.32267031E-03, 3.28475167E-03,
+    4.64534014E-03, 6.56950334E-03, 9.29068029E-03, 1.31390067E-02,
+    1.85813606E-02, 2.62780134E-02, 3.71627212E-02, 5.25560267E-02,
+    7.43254423E-02, 1.05112053E-01, 1.48650885E-01, 2.10224107E-01,
+    2.97301769E-01, 4.20448214E-01, 5.94603539E-01, 8.40896428E-01,
+    1.18920708E+00, 1.68179286E+00, 2.37841415E+00, 3.36358571E+00,
+    4.75682831E+00, 6.72717142E+00, 9.51365662E+00, 1.34543428E+01,
+    1.90273132E+01, 2.69086857E+01, 3.80546265E+01, 5.38173714E+01,
+    7.61092529E+01, 1.07634743E+02, 1.52218506E+02, 2.15269485E+02,
+    3.04437012E+02, 4.30538971E+02, 6.08874023E+02, 8.61077942E+02,
+    1.21774805E+03, 1.72215588E+03, 2.43549609E+03, 3.44431177E+03,
+    4.87099219E+03, 6.88862354E+03, 9.74198438E+03, 1.37772471E+04,
+    1.94839688E+04, 2.75544941E+04, 3.89679375E+04, 5.51089883E+04,
+    7.79358750E+04, 1.10217977E+05, 1.55871750E+05, 2.20435953E+05,
+    0.00000000E+00,
+};
+
+const float ff_dca_st_coeff[34] = {
+    2.69086857E+01, 2.69086857E+01, 1.34543419E+01, 6.72717142E+00,
+    3.36358571E+00, 1.68179286E+00, 8.40896428E-01, 5.94603479E-01,
+    4.20448214E-01, 2.97301799E-01, 2.10224107E-01, 1.48650900E-01,
+    1.05112098E-01, 7.43253976E-02, 5.25560006E-02, 3.71626988E-02,
+    3.12500000E-02, 2.62780003E-02, 1.85813997E-02, 1.31390002E-02,
+    9.29069985E-03, 6.56950008E-03, 4.64530010E-03, 3.28480010E-03,
+    2.32270011E-03, 1.64240005E-03, 1.16130000E-03, 5.80699998E-04,
+    2.90299999E-04, 1.45200000E-04, 7.25999998E-05, 3.62999999E-05,
+    1.82000003E-05, 0.00000000E+00,
+};
+
+const float ff_dca_long_window[128] = {
+    0.00000000E+00, 7.42882412E-06, 5.28020973E-05, 1.71007006E-04,
+    3.96653224E-04, 7.63946096E-04, 1.30655791E-03, 2.05750111E-03,
+    3.04900459E-03, 4.31239139E-03, 5.87796280E-03, 7.77488295E-03,
+    1.00310687E-02, 1.26730874E-02, 1.57260559E-02, 1.92135461E-02,
+    2.31574941E-02, 2.75781266E-02, 3.24938744E-02, 3.79213169E-02,
+    4.38751020E-02, 5.03679104E-02, 5.74104004E-02, 6.50111660E-02,
+    7.31767192E-02, 8.19114447E-02, 9.12176073E-02, 1.01095326E-01,
+    1.11542597E-01, 1.22555278E-01, 1.34127125E-01, 1.46249816E-01,
+    1.58912972E-01, 1.72104210E-01, 1.85809180E-01, 2.00011641E-01,
+    2.14693516E-01, 2.29834959E-01, 2.45414421E-01, 2.61408776E-01,
+    2.77793378E-01, 2.94542134E-01, 3.11627686E-01, 3.29021394E-01,
+    3.46693635E-01, 3.64613682E-01, 3.82750064E-01, 4.01070446E-01,
+    4.19541985E-01, 4.38131332E-01, 4.56804723E-01, 4.75528270E-01,
+    4.94267941E-01, 5.12989700E-01, 5.31659782E-01, 5.50244689E-01,
+    5.68711281E-01, 5.87027133E-01, 6.05160415E-01, 6.23080134E-01,
+    6.40756190E-01, 6.58159554E-01, 6.75262392E-01, 6.92038059E-01,
+    7.08461344E-01, 7.24508464E-01, 7.40157187E-01, 7.55386829E-01,
+    7.70178556E-01, 7.84515142E-01, 7.98381269E-01, 8.11763465E-01,
+    8.24650168E-01, 8.37031603E-01, 8.48900259E-01, 8.60250235E-01,
+    8.71077836E-01, 8.81381273E-01, 8.91160548E-01, 9.00417745E-01,
+    9.09156621E-01, 9.17382956E-01, 9.25104082E-01, 9.32328999E-01,
+    9.39068437E-01, 9.45334494E-01, 9.51140642E-01, 9.56501782E-01,
+    9.61433768E-01, 9.65953648E-01, 9.70079303E-01, 9.73829389E-01,
+    9.77223217E-01, 9.80280578E-01, 9.83021557E-01, 9.85466540E-01,
+    9.87635851E-01, 9.89549816E-01, 9.91228402E-01, 9.92691338E-01,
+    9.93957877E-01, 9.95046616E-01, 9.95975435E-01, 9.96761382E-01,
+    9.97420728E-01, 9.97968733E-01, 9.98419642E-01, 9.98786569E-01,
+    9.99081731E-01, 9.99315977E-01, 9.99499321E-01, 9.99640644E-01,
+    9.99747574E-01, 9.99826968E-01, 9.99884665E-01, 9.99925494E-01,
+    9.99953628E-01, 9.99972343E-01, 9.99984324E-01, 9.99991655E-01,
+    9.99995887E-01, 9.99998152E-01, 9.99999285E-01, 9.99999762E-01,
+    9.99999940E-01, 1.00000000E+00, 1.00000000E+00, 1.00000000E+00,
 };
 
-const int8_t ff_dca_lfe_index[16] = {
-    1, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 1, 3, 2, 3
+const float ff_dca_lfe_step_size_16[101] = {
+    2.1362956633198035E-004, 2.4414807580797754E-004, 2.7466658528397473E-004,
+    2.7466658528397473E-004, 3.0518509475997192E-004, 3.3570360423596911E-004,
+    3.9674062318796350E-004, 4.2725913266396069E-004, 4.5777764213995788E-004,
+    5.1881466109195227E-004, 5.7985168004394665E-004, 6.1037018951994385E-004,
+    6.7140720847193823E-004, 7.6296273689992981E-004, 8.2399975585192419E-004,
+    9.1555528427991577E-004, 1.0071108127079073E-003, 1.0986663411358989E-003,
+    1.2207403790398877E-003, 1.3428144169438765E-003, 1.4648884548478652E-003,
+    1.6174810022278512E-003, 1.7700735496078372E-003, 1.9531846064638203E-003,
+    2.1362956633198035E-003, 2.3499252296517838E-003, 2.5940733054597613E-003,
+    2.8687398907437361E-003, 3.1434064760277108E-003, 3.4485915707876827E-003,
+    3.7842951750236518E-003, 4.1810357982116153E-003, 4.6082949308755760E-003,
+    5.0660725730155339E-003, 5.5543687246314890E-003, 6.1037018951994385E-003,
+    6.7445905941953795E-003, 7.4159978026673177E-003, 8.1484420300912512E-003,
+    8.9419232764671782E-003, 9.8574785607470940E-003, 1.0834070863979004E-002,
+    1.1932737205114903E-002, 1.3122959074678793E-002, 1.4435254982146673E-002,
+    1.5869624927518540E-002, 1.7456587420270394E-002, 1.9196142460402233E-002,
+    2.1118808557390057E-002, 2.3224585711233862E-002, 2.5543992431409649E-002,
+    2.8107547227393413E-002, 3.0915250099185155E-002, 3.4028138065736867E-002,
+    3.7415692617572556E-002, 4.1169469283120215E-002, 4.5258949552903834E-002,
+    4.9806207464827418E-002, 5.4780724509414958E-002, 6.0274056215094456E-002,
+    6.6286202581865905E-002, 7.2908719138157288E-002, 8.0202642902920618E-002,
+    8.8229010895107887E-002, 9.7048860133671075E-002, 1.0675374614703818E-001,
+    1.1743522446363720E-001, 1.2918485061189611E-001, 1.4209418012024294E-001,
+    1.5628528702658162E-001, 1.7191076387829218E-001, 1.8912320322275461E-001,
+    2.0804467909787286E-001, 2.2882778405102694E-001, 2.5171666615802485E-001,
+    2.7689443647572254E-001, 3.0457472457045198E-001, 3.3503219702749720E-001,
+    3.6854152043214211E-001, 4.0537736136967073E-001, 4.4593646046327096E-001,
+    4.9052400280770286E-001, 5.3956724753563035E-001, 5.9352397228919340E-001,
+    6.5288247322000792E-001, 7.1816156498916595E-001, 7.9000213629566329E-001,
+    8.6898403881954400E-001, 9.5590075380718409E-001, 1.0514847254860074E+000,
+    1.1566209906308176E+000, 1.2722861415448470E+000, 1.3995178075502792E+000,
+    1.5394756920072024E+000, 1.6934110538041323E+000, 1.8627582628864405E+000,
+    2.0490432447279274E+000, 2.2539445173497725E+000, 2.4793237098300120E+000,
+    2.7272865993224893E+000, 3.0000000000000000E+000
 };
 
-const int8_t ff_dca_channel_reorder_lfe[16][9] = {
-    { 0, -1, -1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
-    { 2,  0,  1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1,  3, -1, -1, -1, -1, -1, -1 },
-    { 2,  0,  1,  4, -1, -1, -1, -1, -1 },
-    { 0,  1,  3,  4, -1, -1, -1, -1, -1 },
-    { 2,  0,  1,  4,  5, -1, -1, -1, -1 },
-    { 3,  4,  0,  1,  5,  6, -1, -1, -1 },
-    { 2,  0,  1,  4,  5,  6, -1, -1, -1 },
-    { 0,  6,  4,  5,  2,  3, -1, -1, -1 },
-    { 4,  2,  5,  0,  1,  6,  7, -1, -1 },
-    { 5,  6,  0,  1,  7,  3,  8,  4, -1 },
-    { 4,  2,  5,  0,  1,  6,  8,  7, -1 },
+const float ff_dca_lfe_step_size_24[144] = {
+    3.5762791128491298E-006, 3.9339070241340428E-006, 4.4107442391805934E-006,
+    4.7683721504655064E-006, 5.2452093655120570E-006, 5.8412558843202453E-006,
+    6.4373024031284336E-006, 7.0333489219366219E-006, 7.7486047445064479E-006,
+    8.4638605670762738E-006, 9.4175349971693751E-006, 1.0252000123500839E-005,
+    1.1324883857355578E-005, 1.2516976894971954E-005, 1.3709069932588331E-005,
+    1.5139581577727983E-005, 1.6570093222867636E-005, 1.8239023475530564E-005,
+    2.0146372335716766E-005, 2.2053721195902969E-005, 2.4318697967374082E-005,
+    2.6702884042606836E-005, 2.9444698029124504E-005, 3.2305721319403807E-005,
+    3.5643581824729662E-005, 3.9100651633817152E-005, 4.3034558657951193E-005,
+    4.7326093593370149E-005, 5.2094465743835655E-005, 5.7339675109347712E-005,
+    6.3061721689906320E-005, 6.9379814789273121E-005, 7.6293954407448102E-005,
+    8.3923349848192912E-005, 9.2268001111507552E-005, 1.0156632680491529E-004,
+    1.1169911762465449E-004, 1.2290479217824841E-004, 1.3518335046569711E-004,
+    1.4865400179076216E-004, 1.6355516476096688E-004, 1.7988683937631122E-004,
+    1.9788744424431852E-004, 2.1767618866875036E-004, 2.3949149125713007E-004,
+    2.6345256131321922E-004, 2.8979781744454115E-004, 3.1876567825861912E-004,
+    3.5059456236297636E-004, 3.8564209766889782E-004, 4.2426591208766842E-004,
+    4.6670442422681142E-004, 5.1331526199761173E-004, 5.6469447191887759E-004,
+    6.2108047259813216E-004, 6.8318851985794547E-004, 7.5149545091336386E-004,
+    8.2671652158695713E-004, 9.0932856909377204E-004, 1.0002852678639017E-003,
+    1.1003018737199156E-003, 1.2103320610919071E-003, 1.3314487137137310E-003,
+    1.4646055060154803E-003, 1.6109945310347714E-003, 1.7721655097205054E-003,
+    1.9493105351102991E-003, 2.1442177467605765E-003, 2.3586752842277626E-003,
+    2.5945904963720436E-003, 2.8539899413573674E-003, 3.1393770145627278E-003,
+    3.4533743206708813E-003, 3.7987236736683454E-003, 4.1785245154529228E-003,
+    4.5963531251374630E-003, 5.0560242004423382E-003, 5.5617100669992049E-003,
+    6.1178214690472445E-003, 6.7296036159519689E-003, 7.4025401356864135E-003,
+    8.1428299120461841E-003, 8.9571486660419298E-003, 9.8527681652031147E-003,
+    1.0838033060793050E-002, 1.1921884050593860E-002, 1.3114096297513997E-002,
+    1.4425517848195773E-002, 1.5868069633015350E-002, 1.7454864675386508E-002,
+    1.9200327301064409E-002, 2.1120431556753107E-002, 2.3232462791498040E-002,
+    2.5555613703204836E-002, 2.8111222757246822E-002, 3.0922297349250002E-002,
+    3.4014586688826884E-002, 3.7415985753057691E-002, 4.1157608170224208E-002,
+    4.5273428591898514E-002, 4.9800759530157987E-002, 5.4780847404104160E-002,
+    6.0258872539862694E-002, 6.6284783635709721E-002, 7.2913297762071824E-002,
+    8.0204615617348624E-002, 8.8225017574431602E-002, 9.7047578936526643E-002,
+    1.0675228914645780E-001, 1.1742748229831246E-001, 1.2917031397465634E-001,
+    1.4208735729305236E-001, 1.5629603341770570E-001, 1.7192568444319778E-001,
+    1.8911816944100493E-001, 2.0803001022696618E-001, 2.2883310661710579E-001,
+    2.5171640535788598E-001, 2.7688804589367461E-001, 3.0457679087839018E-001,
+    3.3503452957088109E-001, 3.6853794676517804E-001, 4.0539174144169587E-001,
+    4.4593089174400469E-001, 4.9052399283933557E-001, 5.3957635636047796E-001,
+    5.9353406352210802E-001, 6.5288742219059737E-001, 7.1817609288407480E-001,
+    7.8999373793527339E-001, 8.6899314749159184E-001, 9.5589243839889027E-001,
+    1.0514817299225008E+000, 1.1566298194682383E+000, 1.2722928848615747E+000,
+    1.3995221137430804E+000, 1.5394743131964581E+000, 1.6934218041207556E+000,
+    1.8627639845328312E+000, 2.0490403233814627E+000, 2.2539444272451910E+000,
+    2.4793389414952922E+000, 2.7272728356448215E+000, 2.9999998807906962E+000
 };
 
-const int8_t ff_dca_channel_reorder_nolfe[16][9] = {
-    { 0, -1, -1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
-    { 2,  0,  1, -1, -1, -1, -1, -1, -1 },
-    { 0,  1,  2, -1, -1, -1, -1, -1, -1 },
-    { 2,  0,  1,  3, -1, -1, -1, -1, -1 },
-    { 0,  1,  2,  3, -1, -1, -1, -1, -1 },
-    { 2,  0,  1,  3,  4, -1, -1, -1, -1 },
-    { 2,  3,  0,  1,  4,  5, -1, -1, -1 },
-    { 2,  0,  1,  3,  4,  5, -1, -1, -1 },
-    { 0,  5,  3,  4,  1,  2, -1, -1, -1 },
-    { 3,  2,  4,  0,  1,  5,  6, -1, -1 },
-    { 4,  5,  0,  1,  6,  2,  7,  3, -1 },
-    { 3,  2,  4,  0,  1,  5,  7,  6, -1 },
+const float ff_dca_bank_coeff[10] = {
+    0.022810893, 0.41799772, 0.90844810, 0.99973983,
+    0.068974845, 0.34675997, 0.29396889, 0.19642374,
+    0.308658270, 0.038060233
 };
 
-const uint16_t ff_dca_vlc_offs[63] = {
-        0,   512,   640,   768,  1282,  1794,  2436,  3080,  3770,  4454,  5364,
-     5372,  5380,  5388,  5392,  5396,  5412,  5420,  5428,  5460,  5492,  5508,
-     5572,  5604,  5668,  5796,  5860,  5892,  6412,  6668,  6796,  7308,  7564,
-     7820,  8076,  8620,  9132,  9388,  9910, 10166, 10680, 11196, 11726, 12240,
-    12752, 13298, 13810, 14326, 14840, 15500, 16022, 16540, 17158, 17678, 18264,
-    18796, 19352, 19926, 20468, 21472, 22398, 23014, 23622,
+const float ff_dca_lfe_iir[5][4] = {
+    { -0.98618466, 1.9861259, 1.0, -1.9840510 },
+    { -0.98883152, 1.9887193, 1.0, -1.9979848 },
+    { -0.99252087, 1.9923381, 1.0, -1.9990897 },
+    { -0.99591690, 1.9956781, 1.0, -1.9993745 },
+    { -0.99872285, 1.9984550, 1.0, -1.9994639 }
 };
diff --git a/libavcodec/dcadata.h b/libavcodec/dcadata.h
index d864251..17aa712 100644
--- a/libavcodec/dcadata.h
+++ b/libavcodec/dcadata.h
@@ -71,13 +71,51 @@ extern const uint16_t ff_dca_xll_refl_coeff[128];
 
 extern const int32_t ff_dca_xll_band_coeff[20];
 
-extern const int32_t ff_dca_sampling_freqs[16];
+extern const uint16_t ff_dca_avg_g3_freqs[3];
 
-extern const int8_t ff_dca_lfe_index[16];
+extern const uint16_t ff_dca_fst_amp[44];
 
-extern const int8_t ff_dca_channel_reorder_lfe[16][9];
-extern const int8_t ff_dca_channel_reorder_nolfe[16][9];
+extern const uint8_t ff_dca_freq_to_sb[32];
 
-extern const uint16_t ff_dca_vlc_offs[63];
+extern const int8_t ff_dca_ph0_shift[8];
+
+extern const uint8_t ff_dca_grid_1_to_scf[11];
+extern const uint8_t ff_dca_grid_2_to_scf[3];
+
+extern const uint8_t ff_dca_scf_to_grid_1[32];
+extern const uint8_t ff_dca_scf_to_grid_2[32];
+
+extern const uint8_t ff_dca_grid_1_weights[12][32];
+
+extern const uint8_t ff_dca_sb_reorder[8][8];
+
+extern const int8_t ff_dca_lfe_delta_index_16[8];
+extern const int8_t ff_dca_lfe_delta_index_24[32];
+
+extern const uint16_t ff_dca_rsd_pack_5_in_8[256];
+extern const uint8_t ff_dca_rsd_pack_3_in_7[128][3];
+
+extern const float ff_dca_rsd_level_2a[2];
+extern const float ff_dca_rsd_level_2b[2];
+extern const float ff_dca_rsd_level_3[3];
+extern const float ff_dca_rsd_level_5[5];
+extern const float ff_dca_rsd_level_8[8];
+extern const float ff_dca_rsd_level_16[16];
+
+extern const float ff_dca_synth_env[32];
+
+extern const float ff_dca_corr_cf[32][11];
+
+extern const float ff_dca_quant_amp[57];
+
+extern const float ff_dca_st_coeff[34];
+
+extern const float ff_dca_long_window[128];
+
+extern const float ff_dca_lfe_step_size_16[101];
+extern const float ff_dca_lfe_step_size_24[144];
+
+extern const float ff_dca_bank_coeff[10];
+extern const float ff_dca_lfe_iir[5][4];
 
 #endif /* AVCODEC_DCADATA_H */
diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c
index f3c3972..4146a85 100644
--- a/libavcodec/dcadec.c
+++ b/libavcodec/dcadec.c
@@ -22,7 +22,7 @@
 #include "libavutil/channel_layout.h"
 
 #include "dcadec.h"
-#include "dcamath.h"
+#include "dcahuff.h"
 #include "dca_syncwords.h"
 #include "profiles.h"
 
@@ -76,33 +76,6 @@ int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int dca_mask
     return nchannels;
 }
 
-static uint16_t crc16(const uint8_t *data, int size)
-{
-    static const uint16_t crctab[16] = {
-        0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
-        0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
-    };
-
-    uint16_t res = 0xffff;
-    int i;
-
-    for (i = 0; i < size; i++) {
-        res = (res << 4) ^ crctab[(data[i] >> 4) ^ (res >> 12)];
-        res = (res << 4) ^ crctab[(data[i] & 15) ^ (res >> 12)];
-    }
-
-    return res;
-}
-
-int ff_dca_check_crc(GetBitContext *s, int p1, int p2)
-{
-    if (((p1 | p2) & 7) || p1 < 0 || p2 > s->size_in_bits || p2 - p1 < 16)
-        return -1;
-    if (crc16(s->buffer + p1 / 8, (p2 - p1) / 8))
-        return -1;
-    return 0;
-}
-
 void ff_dca_downmix_to_stereo_fixed(DCADSPContext *dcadsp, int32_t **samples,
                                     int *coeff_l, int nsamples, int ch_mask)
 {
@@ -168,22 +141,6 @@ void ff_dca_downmix_to_stereo_float(AVFloatDSPContext *fdsp, float **samples,
     }
 }
 
-static int convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst, int max_size)
-{
-    switch (AV_RB32(src)) {
-    case DCA_SYNCWORD_CORE_BE:
-    case DCA_SYNCWORD_SUBSTREAM:
-        memcpy(dst, src, src_size);
-        return src_size;
-    case DCA_SYNCWORD_CORE_LE:
-    case DCA_SYNCWORD_CORE_14B_BE:
-    case DCA_SYNCWORD_CORE_14B_LE:
-        return avpriv_dca_convert_bitstream(src, src_size, dst, max_size);
-    default:
-        return AVERROR_INVALIDDATA;
-    }
-}
-
 static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
                                int *got_frame_ptr, AVPacket *avpkt)
 {
@@ -192,25 +149,31 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
     uint8_t *input = avpkt->data;
     int input_size = avpkt->size;
     int i, ret, prev_packet = s->packet;
+    uint32_t mrk;
 
     if (input_size < MIN_PACKET_SIZE || input_size > MAX_PACKET_SIZE) {
         av_log(avctx, AV_LOG_ERROR, "Invalid packet size\n");
         return AVERROR_INVALIDDATA;
     }
 
-    av_fast_malloc(&s->buffer, &s->buffer_size,
-                   FFALIGN(input_size, 4096) + DCA_BUFFER_PADDING_SIZE);
-    if (!s->buffer)
-        return AVERROR(ENOMEM);
+    // Convert input to BE format
+    mrk = AV_RB32(input);
+    if (mrk != DCA_SYNCWORD_CORE_BE && mrk != DCA_SYNCWORD_SUBSTREAM) {
+        av_fast_padded_malloc(&s->buffer, &s->buffer_size, input_size);
+        if (!s->buffer)
+            return AVERROR(ENOMEM);
 
-    for (i = 0, ret = AVERROR_INVALIDDATA; i < input_size - MIN_PACKET_SIZE + 1 && ret < 0; i++)
-        ret = convert_bitstream(input + i, input_size - i, s->buffer, s->buffer_size);
+        for (i = 0, ret = AVERROR_INVALIDDATA; i < input_size - MIN_PACKET_SIZE + 1 && ret < 0; i++)
+            ret = avpriv_dca_convert_bitstream(input + i, input_size - i, s->buffer, s->buffer_size);
 
-    if (ret < 0)
-        return ret;
+        if (ret < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n");
+            return ret;
+        }
 
-    input      = s->buffer;
-    input_size = ret;
+        input      = s->buffer;
+        input_size = ret;
+    }
 
     s->packet = 0;
 
@@ -218,10 +181,8 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
     if (AV_RB32(input) == DCA_SYNCWORD_CORE_BE) {
         int frame_size;
 
-        if ((ret = ff_dca_core_parse(&s->core, input, input_size)) < 0) {
-            s->core_residual_valid = 0;
+        if ((ret = ff_dca_core_parse(&s->core, input, input_size)) < 0)
             return ret;
-        }
 
         s->packet |= DCA_PACKET_CORE;
 
@@ -262,6 +223,16 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
             }
         }
 
+        // Parse LBR component in EXSS
+        if (asset && (asset->extension_mask & DCA_EXSS_LBR)) {
+            if ((ret = ff_dca_lbr_parse(&s->lbr, input, asset)) < 0) {
+                if (ret == AVERROR(ENOMEM) || (avctx->err_recognition & AV_EF_EXPLODE))
+                    return ret;
+            } else {
+                s->packet |= DCA_PACKET_LBR;
+            }
+        }
+
         // Parse core extensions in EXSS or backward compatible core sub-stream
         if ((s->packet & DCA_PACKET_CORE)
             && (ret = ff_dca_core_parse_exss(&s->core, input, asset)) < 0)
@@ -269,7 +240,10 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
     }
 
     // Filter the frame
-    if (s->packet & DCA_PACKET_XLL) {
+    if (s->packet & DCA_PACKET_LBR) {
+        if ((ret = ff_dca_lbr_filter_frame(&s->lbr, frame)) < 0)
+            return ret;
+    } else if (s->packet & DCA_PACKET_XLL) {
         if (s->packet & DCA_PACKET_CORE) {
             int x96_synth = -1;
 
@@ -277,19 +251,20 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
             if (s->xll.chset[0].freq == 96000 && s->core.sample_rate == 48000)
                 x96_synth = 1;
 
-            if ((ret = ff_dca_core_filter_fixed(&s->core, x96_synth)) < 0) {
-                s->core_residual_valid = 0;
+            if ((ret = ff_dca_core_filter_fixed(&s->core, x96_synth)) < 0)
                 return ret;
-            }
 
             // Force lossy downmixed output on the first core frame filtered.
             // This prevents audible clicks when seeking and is consistent with
             // what reference decoder does when there are multiple channel sets.
-            if (!s->core_residual_valid) {
-                if (s->xll.nreschsets > 0 && s->xll.nchsets > 1)
-                    s->packet |= DCA_PACKET_RECOVERY;
-                s->core_residual_valid = 1;
+            if (!(prev_packet & DCA_PACKET_RESIDUAL) && s->xll.nreschsets > 0
+                && s->xll.nchsets > 1) {
+                av_log(avctx, AV_LOG_VERBOSE, "Forcing XLL recovery mode\n");
+                s->packet |= DCA_PACKET_RECOVERY;
             }
+
+            // Set 'residual ok' flag for the next frame
+            s->packet |= DCA_PACKET_RESIDUAL;
         }
 
         if ((ret = ff_dca_xll_filter_frame(&s->xll, frame)) < 0) {
@@ -298,18 +273,18 @@ static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
                 return ret;
             if (ret != AVERROR_INVALIDDATA || (avctx->err_recognition & AV_EF_EXPLODE))
                 return ret;
-            if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) {
-                s->core_residual_valid = 0;
+            if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0)
                 return ret;
-            }
         }
     } else if (s->packet & DCA_PACKET_CORE) {
-        if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0) {
-            s->core_residual_valid = 0;
+        if ((ret = ff_dca_core_filter_frame(&s->core, frame)) < 0)
             return ret;
-        }
-        s->core_residual_valid = !!(s->core.filter_mode & DCA_FILTER_MODE_FIXED);
+        if (s->core.filter_mode & DCA_FILTER_MODE_FIXED)
+            s->packet |= DCA_PACKET_RESIDUAL;
     } else {
+        av_log(avctx, AV_LOG_ERROR, "No valid DCA sub-stream found\n");
+        if (s->core_only)
+            av_log(avctx, AV_LOG_WARNING, "Consider disabling 'core_only' option\n");
         return AVERROR_INVALIDDATA;
     }
 
@@ -324,8 +299,9 @@ static av_cold void dcadec_flush(AVCodecContext *avctx)
 
     ff_dca_core_flush(&s->core);
     ff_dca_xll_flush(&s->xll);
+    ff_dca_lbr_flush(&s->lbr);
 
-    s->core_residual_valid = 0;
+    s->packet &= DCA_PACKET_MASK;
 }
 
 static av_cold int dcadec_close(AVCodecContext *avctx)
@@ -334,6 +310,7 @@ static av_cold int dcadec_close(AVCodecContext *avctx)
 
     ff_dca_core_close(&s->core);
     ff_dca_xll_close(&s->xll);
+    ff_dca_lbr_close(&s->lbr);
 
     av_freep(&s->buffer);
     s->buffer_size = 0;
@@ -349,13 +326,22 @@ static av_cold int dcadec_init(AVCodecContext *avctx)
     s->core.avctx = avctx;
     s->exss.avctx = avctx;
     s->xll.avctx = avctx;
+    s->lbr.avctx = avctx;
+
+    ff_dca_init_vlcs();
 
     if (ff_dca_core_init(&s->core) < 0)
         return AVERROR(ENOMEM);
 
+    if (ff_dca_lbr_init(&s->lbr) < 0)
+        return AVERROR(ENOMEM);
+
     ff_dcadsp_init(&s->dcadsp);
     s->core.dcadsp = &s->dcadsp;
     s->xll.dcadsp = &s->dcadsp;
+    s->lbr.dcadsp = &s->dcadsp;
+
+    s->crctab = av_crc_get_table(AV_CRC_16_CCITT);
 
     switch (avctx->request_channel_layout & ~AV_CH_LAYOUT_NATIVE) {
     case 0:
@@ -376,9 +362,6 @@ static av_cold int dcadec_init(AVCodecContext *avctx)
         break;
     }
 
-    avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
-    avctx->bits_per_raw_sample = 24;
-
     return 0;
 }
 
diff --git a/libavcodec/dcadec.h b/libavcodec/dcadec.h
index 6726121..456f3c4 100644
--- a/libavcodec/dcadec.h
+++ b/libavcodec/dcadec.h
@@ -22,6 +22,7 @@
 #define AVCODEC_DCADEC_H
 
 #include "libavutil/common.h"
+#include "libavutil/crc.h"
 #include "libavutil/float_dsp.h"
 
 #include "avcodec.h"
@@ -31,13 +32,16 @@
 #include "dca_core.h"
 #include "dca_exss.h"
 #include "dca_xll.h"
-
-#define DCA_BUFFER_PADDING_SIZE     1024
+#include "dca_lbr.h"
 
 #define DCA_PACKET_CORE         0x01
 #define DCA_PACKET_EXSS         0x02
 #define DCA_PACKET_XLL          0x04
-#define DCA_PACKET_RECOVERY     0x08
+#define DCA_PACKET_LBR          0x08
+#define DCA_PACKET_MASK         0x0f
+
+#define DCA_PACKET_RECOVERY     0x10    ///< Sync error recovery flag
+#define DCA_PACKET_RESIDUAL     0x20    ///< Core valid for residual decoding
 
 typedef struct DCAContext {
     const AVClass   *class;       ///< class for AVOptions
@@ -46,29 +50,42 @@ typedef struct DCAContext {
     DCACoreDecoder core;  ///< Core decoder context
     DCAExssParser  exss;  ///< EXSS parser context
     DCAXllDecoder  xll;   ///< XLL decoder context
+    DCALbrDecoder  lbr;   ///< LBR decoder context
 
     DCADSPContext   dcadsp;
 
+    const AVCRC     *crctab;
+
     uint8_t         *buffer;    ///< Packet buffer
     unsigned int    buffer_size;
 
     int     packet; ///< Packet flags
 
-    int     core_residual_valid;    ///< Core valid for residual decoding
-
     int     request_channel_layout; ///< Converted from avctx.request_channel_layout
     int     core_only;              ///< Core only decoding flag
 } DCAContext;
 
 int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int dca_mask);
 
-int ff_dca_check_crc(GetBitContext *s, int p1, int p2);
-
 void ff_dca_downmix_to_stereo_fixed(DCADSPContext *dcadsp, int32_t **samples,
                                     int *coeff_l, int nsamples, int ch_mask);
 void ff_dca_downmix_to_stereo_float(AVFloatDSPContext *fdsp, float **samples,
                                     int *coeff_l, int nsamples, int ch_mask);
 
+static inline int ff_dca_check_crc(AVCodecContext *avctx, GetBitContext *s,
+                                   int p1, int p2)
+{
+    DCAContext *dca = avctx->priv_data;
+
+    if (!(avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL)))
+        return 0;
+    if (((p1 | p2) & 7) || p1 < 0 || p2 > s->size_in_bits || p2 - p1 < 16)
+        return -1;
+    if (av_crc(dca->crctab, 0xffff, s->buffer + p1 / 8, (p2 - p1) / 8))
+        return -1;
+    return 0;
+}
+
 static inline int ff_dca_seek_bits(GetBitContext *s, int p)
 {
     if (p < s->index || p > s->size_in_bits)
diff --git a/libavcodec/dcadsp.c b/libavcodec/dcadsp.c
index 09faee5..1cd2e4e 100644
--- a/libavcodec/dcadsp.c
+++ b/libavcodec/dcadsp.c
@@ -122,7 +122,7 @@ static void sub_qmf32_float_c(SynthFilterContext *synth,
                               const float *filter_coeff, ptrdiff_t npcmblocks,
                               float scale)
 {
-    LOCAL_ALIGNED(32, float, input, [32]);
+    LOCAL_ALIGNED_32(float, input, [32]);
     int i, j;
 
     for (j = 0; j < npcmblocks; j++) {
@@ -151,7 +151,7 @@ static void sub_qmf64_float_c(SynthFilterContext *synth,
                               const float *filter_coeff, ptrdiff_t npcmblocks,
                               float scale)
 {
-    LOCAL_ALIGNED(32, float, input, [64]);
+    LOCAL_ALIGNED_32(float, input, [64]);
     int i, j;
 
     if (!subband_samples_hi)
@@ -243,7 +243,7 @@ static void sub_qmf32_fixed_c(SynthFilterContext *synth,
                               int32_t *hist1, int *offset, int32_t *hist2,
                               const int32_t *filter_coeff, ptrdiff_t npcmblocks)
 {
-    LOCAL_ALIGNED(32, int32_t, input, [32]);
+    LOCAL_ALIGNED_32(int32_t, input, [32]);
     int i, j;
 
     for (j = 0; j < npcmblocks; j++) {
@@ -267,7 +267,7 @@ static void sub_qmf64_fixed_c(SynthFilterContext *synth,
                               int32_t *hist1, int *offset, int32_t *hist2,
                               const int32_t *filter_coeff, ptrdiff_t npcmblocks)
 {
-    LOCAL_ALIGNED(32, int32_t, input, [64]);
+    LOCAL_ALIGNED_32(int32_t, input, [64]);
     int i, j;
 
     if (!subband_samples_hi)
@@ -385,6 +385,77 @@ static void assemble_freq_bands_c(int32_t *dst, int32_t *src0, int32_t *src1,
     }
 }
 
+static void lbr_bank_c(float output[32][4], float **input,
+                       const float *coeff, ptrdiff_t ofs, ptrdiff_t len)
+{
+    float SW0 = coeff[0];
+    float SW1 = coeff[1];
+    float SW2 = coeff[2];
+    float SW3 = coeff[3];
+
+    float C1  = coeff[4];
+    float C2  = coeff[5];
+    float C3  = coeff[6];
+    float C4  = coeff[7];
+
+    float AL1 = coeff[8];
+    float AL2 = coeff[9];
+
+    int i;
+
+    // Short window and 8 point forward MDCT
+    for (i = 0; i < len; i++) {
+        float *src = input[i] + ofs;
+
+        float a = src[-4] * SW0 - src[-1] * SW3;
+        float b = src[-3] * SW1 - src[-2] * SW2;
+        float c = src[ 2] * SW1 + src[ 1] * SW2;
+        float d = src[ 3] * SW0 + src[ 0] * SW3;
+
+        output[i][0] = C1 * b - C2 * c + C4 * a - C3 * d;
+        output[i][1] = C1 * d - C2 * a - C4 * b - C3 * c;
+        output[i][2] = C3 * b + C2 * d - C4 * c + C1 * a;
+        output[i][3] = C3 * a - C2 * b + C4 * d - C1 * c;
+    }
+
+    // Aliasing cancellation for high frequencies
+    for (i = 12; i < len - 1; i++) {
+        float a = output[i  ][3] * AL1;
+        float b = output[i+1][0] * AL1;
+        output[i  ][3] += b - a;
+        output[i+1][0] -= b + a;
+        a = output[i  ][2] * AL2;
+        b = output[i+1][1] * AL2;
+        output[i  ][2] += b - a;
+        output[i+1][1] -= b + a;
+    }
+}
+
+static void lfe_iir_c(float *output, const float *input,
+                      const float iir[5][4], float hist[5][2],
+                      ptrdiff_t factor)
+{
+    float res, tmp;
+    int i, j, k;
+
+    for (i = 0; i < 64; i++) {
+        res = *input++;
+
+        for (j = 0; j < factor; j++) {
+            for (k = 0; k < 5; k++) {
+                tmp = hist[k][0] * iir[k][0] + hist[k][1] * iir[k][1] + res;
+                res = hist[k][0] * iir[k][2] + hist[k][1] * iir[k][3] + tmp;
+
+                hist[k][0] = hist[k][1];
+                hist[k][1] = tmp;
+            }
+
+            *output++ = res;
+            res = 0;
+        }
+    }
+}
+
 av_cold void ff_dcadsp_init(DCADSPContext *s)
 {
     s->decode_hf     = decode_hf_c;
@@ -411,6 +482,9 @@ av_cold void ff_dcadsp_init(DCADSPContext *s)
 
     s->assemble_freq_bands = assemble_freq_bands_c;
 
+    s->lbr_bank = lbr_bank_c;
+    s->lfe_iir = lfe_iir_c;
+
     if (ARCH_X86)
         ff_dcadsp_init_x86(s);
 }
diff --git a/libavcodec/dcadsp.h b/libavcodec/dcadsp.h
index c82b7b1..8f2f467 100644
--- a/libavcodec/dcadsp.h
+++ b/libavcodec/dcadsp.h
@@ -84,6 +84,13 @@ typedef struct DCADSPContext {
 
     void (*assemble_freq_bands)(int32_t *dst, int32_t *src0, int32_t *src1,
                                 const int32_t *coeff, ptrdiff_t len);
+
+    void (*lbr_bank)(float output[32][4], float **input,
+                     const float *coeff, ptrdiff_t ofs, ptrdiff_t len);
+
+    void (*lfe_iir)(float *output, const float *input,
+                    const float iir[5][4], float hist[5][2],
+                    ptrdiff_t factor);
 } DCADSPContext;
 
 av_cold void ff_dcadsp_init(DCADSPContext *s);
diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c
index 70e9230..6bb7d29 100644
--- a/libavcodec/dcaenc.c
+++ b/libavcodec/dcaenc.c
@@ -24,7 +24,7 @@
 #include "libavutil/avassert.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/common.h"
-#include "libavutil/internal.h"
+#include "libavutil/ffmath.h"
 #include "avcodec.h"
 #include "dca.h"
 #include "dcadata.h"
@@ -137,9 +137,9 @@ static int encode_init(AVCodecContext *avctx)
 
     if (c->lfe_channel) {
         c->fullband_channels--;
-        c->channel_order_tab = ff_dca_channel_reorder_lfe[c->channel_config];
+        c->channel_order_tab = channel_reorder_lfe[c->channel_config];
     } else {
-        c->channel_order_tab = ff_dca_channel_reorder_nolfe[c->channel_config];
+        c->channel_order_tab = channel_reorder_nolfe[c->channel_config];
     }
 
     for (i = 0; i < 9; i++) {
@@ -303,7 +303,7 @@ static void subband_transform(DCAEncContext *c, const int32_t *input)
 static void lfe_downsample(DCAEncContext *c, const int32_t *input)
 {
     /* FIXME: make 128x LFE downsampling possible */
-    const int lfech = ff_dca_lfe_index[c->channel_config];
+    const int lfech = lfe_index[c->channel_config];
     int i, j, lfes;
     int32_t hist[512];
     int32_t accum;
@@ -683,7 +683,7 @@ static int calc_one_scale(int32_t peak_cb, int abits, softfloat *quant)
             continue;
         our_quant.m = mul32(scalefactor_inv[our_nscale - try_remove].m, stepsize_inv[abits].m);
         our_quant.e = scalefactor_inv[our_nscale - try_remove].e + stepsize_inv[abits].e - 17;
-        if ((quant_levels[abits] - 1) / 2 < quantize_value(peak, our_quant))
+        if ((ff_dca_quant_levels[abits] - 1) / 2 < quantize_value(peak, our_quant))
             continue;
         our_nscale -= try_remove;
     }
@@ -693,7 +693,7 @@ static int calc_one_scale(int32_t peak_cb, int abits, softfloat *quant)
 
     quant->m = mul32(scalefactor_inv[our_nscale].m, stepsize_inv[abits].m);
     quant->e = scalefactor_inv[our_nscale].e + stepsize_inv[abits].e - 17;
-    av_assert0((quant_levels[abits] - 1) / 2 >= quantize_value(peak, *quant));
+    av_assert0((ff_dca_quant_levels[abits] - 1) / 2 >= quantize_value(peak, *quant));
 
     return our_nscale;
 }
@@ -858,9 +858,9 @@ static void put_subframe_samples(DCAEncContext *c, int ss, int band, int ch)
         for (i = 0; i < 8; i += 4) {
             sum = 0;
             for (j = 3; j >= 0; j--) {
-                sum *= quant_levels[c->abits[band][ch]];
+                sum *= ff_dca_quant_levels[c->abits[band][ch]];
                 sum += c->quantized[ss * 8 + i + j][band][ch];
-                sum += (quant_levels[c->abits[band][ch]] - 1) / 2;
+                sum += (ff_dca_quant_levels[c->abits[band][ch]] - 1) / 2;
             }
             put_bits(&c->pb, bit_consumption[c->abits[band][ch]] / 4, sum);
         }
diff --git a/libavcodec/dcaenc.h b/libavcodec/dcaenc.h
index 0443ca6..eccfb42 100644
--- a/libavcodec/dcaenc.h
+++ b/libavcodec/dcaenc.h
@@ -103,11 +103,46 @@ static const int bit_consumption[27] = {
     272, 288, 304, 320, 336, 352, 368,
 };
 
-/* Table B.5: Selection of quantization levels and codebooks */
-static const int quant_levels[27] = {
-    1, 3, 5, 7, 9, 13, 17, 25, 32, 64,
-    128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536,
-    131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608,
+static const int8_t lfe_index[16] = {
+    1, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 1, 3, 2, 3
+};
+
+static const int8_t channel_reorder_lfe[16][9] = {
+    { 0, -1, -1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
+    { 2,  0,  1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1,  3, -1, -1, -1, -1, -1, -1 },
+    { 2,  0,  1,  4, -1, -1, -1, -1, -1 },
+    { 0,  1,  3,  4, -1, -1, -1, -1, -1 },
+    { 2,  0,  1,  4,  5, -1, -1, -1, -1 },
+    { 3,  4,  0,  1,  5,  6, -1, -1, -1 },
+    { 2,  0,  1,  4,  5,  6, -1, -1, -1 },
+    { 0,  6,  4,  5,  2,  3, -1, -1, -1 },
+    { 4,  2,  5,  0,  1,  6,  7, -1, -1 },
+    { 5,  6,  0,  1,  7,  3,  8,  4, -1 },
+    { 4,  2,  5,  0,  1,  6,  8,  7, -1 },
+};
+
+static const int8_t channel_reorder_nolfe[16][9] = {
+    { 0, -1, -1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1, -1, -1, -1, -1, -1, -1, -1 },
+    { 2,  0,  1, -1, -1, -1, -1, -1, -1 },
+    { 0,  1,  2, -1, -1, -1, -1, -1, -1 },
+    { 2,  0,  1,  3, -1, -1, -1, -1, -1 },
+    { 0,  1,  2,  3, -1, -1, -1, -1, -1 },
+    { 2,  0,  1,  3,  4, -1, -1, -1, -1 },
+    { 2,  3,  0,  1,  4,  5, -1, -1, -1 },
+    { 2,  0,  1,  3,  4,  5, -1, -1, -1 },
+    { 0,  5,  3,  4,  1,  2, -1, -1, -1 },
+    { 3,  2,  4,  0,  1,  5,  6, -1, -1 },
+    { 4,  5,  0,  1,  6,  2,  7,  3, -1 },
+    { 3,  2,  4,  0,  1,  5,  7,  6, -1 },
 };
 
 #endif /* AVCODEC_DCAENC_H */
diff --git a/libavcodec/dcahuff.c b/libavcodec/dcahuff.c
new file mode 100644
index 0000000..bea3530
--- /dev/null
+++ b/libavcodec/dcahuff.c
@@ -0,0 +1,1337 @@
+/*
+ * DCA compatible decoder - huffman tables
+ * Copyright (C) 2004 Gildas Bazin
+ * Copyright (C) 2007 Konstantin Shishkov
+ *
+ * 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/common.h"
+
+#include "avcodec.h"
+#include "get_bits.h"
+#include "dcahuff.h"
+
+#define TMODE_COUNT 4
+static const uint8_t tmode_vlc_bits[TMODE_COUNT] = { 3, 3, 3, 2 };
+static const uint16_t tmode_codes[TMODE_COUNT][4] = {
+    { 0x0000, 0x0002, 0x0006, 0x0007 },
+    { 0x0002, 0x0006, 0x0007, 0x0000 },
+    { 0x0006, 0x0007, 0x0000, 0x0002 },
+    { 0x0000, 0x0001, 0x0002, 0x0003 }
+};
+
+static const uint8_t tmode_bits[TMODE_COUNT][4] = {
+    { 1, 2, 3, 3 },
+    { 2, 3, 3, 1 },
+    { 3, 3, 1, 2 },
+    { 2, 2, 2, 2 }
+};
+
+#define BITALLOC_12_COUNT    5
+#define BITALLOC_12_VLC_BITS 9
+static const uint8_t bitalloc_12_vlc_bits[BITALLOC_12_COUNT] = {
+    9, 7, 7, 9, 9
+};
+
+static const uint16_t bitalloc_12_codes[BITALLOC_12_COUNT][12] = {
+    { 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, 0x00FF, 0x00FE,
+      0x01FB, 0x01FA, 0x01F9, 0x01F8, },
+    { 0x0001, 0x0000, 0x0002, 0x000F, 0x000C, 0x001D, 0x0039, 0x0038,
+      0x0037, 0x0036, 0x0035, 0x0034, },
+    { 0x0000, 0x0007, 0x0005, 0x0004, 0x0002, 0x000D, 0x000C, 0x0006,
+      0x000F, 0x001D, 0x0039, 0x0038, },
+    { 0x0003, 0x0002, 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E,
+      0x007E, 0x00FE, 0x01FF, 0x01FE, },
+    { 0x0001, 0x0000, 0x0002, 0x0006, 0x000E, 0x003F, 0x003D, 0x007C,
+      0x0079, 0x0078, 0x00FB, 0x00FA, }
+};
+
+static const uint8_t bitalloc_12_bits[BITALLOC_12_COUNT][12] = {
+    { 1, 2, 3, 4, 5, 6, 8, 8, 9, 9,  9,  9 },
+    { 1, 2, 3, 5, 5, 6, 7, 7, 7, 7,  7,  7 },
+    { 2, 3, 3, 3, 3, 4, 4, 4, 5, 6,  7,  7 },
+    { 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10 },
+    { 1, 2, 3, 4, 5, 7, 7, 8, 8, 8,  9,  9 }
+};
+
+#define SCALES_COUNT    5
+#define SCALES_VLC_BITS 9
+static const uint16_t scales_codes[SCALES_COUNT][129] = {
+    { 0x3AB0, 0x3AB2, 0x3AB4, 0x3AB6, 0x3AB8, 0x3ABA, 0x3ABC, 0x3ABE,
+      0x3AC0, 0x3AC2, 0x3AC4, 0x3AC6, 0x3AC8, 0x3ACA, 0x3ACC, 0x3ACE,
+      0x3AD0, 0x3AD2, 0x3AD4, 0x3AD6, 0x3AD8, 0x3ADA, 0x3ADC, 0x3ADE,
+      0x3AE0, 0x3AE2, 0x3AE4, 0x3AE6, 0x3AE8, 0x3AEA, 0x3AEC, 0x3AEE,
+      0x3AF0, 0x3AF2, 0x3AF4, 0x3AF6, 0x3AF8, 0x3AFA, 0x3AFC, 0x3AFE,
+      0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E,
+      0x0558, 0x055E, 0x02AD, 0x0154, 0x0754, 0x03A8, 0x0056, 0x0028,
+      0x00E8, 0x004A, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005,
+      0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x004B,
+      0x00E9, 0x0029, 0x0057, 0x03A9, 0x0755, 0x0155, 0x02AE, 0x055F,
+      0x0559, 0x054F, 0x054D, 0x054B, 0x0549, 0x0547, 0x0545, 0x0543,
+      0x0541, 0x3AFF, 0x3AFD, 0x3AFB, 0x3AF9, 0x3AF7, 0x3AF5, 0x3AF3,
+      0x3AF1, 0x3AEF, 0x3AED, 0x3AEB, 0x3AE9, 0x3AE7, 0x3AE5, 0x3AE3,
+      0x3AE1, 0x3ADF, 0x3ADD, 0x3ADB, 0x3AD9, 0x3AD7, 0x3AD5, 0x3AD3,
+      0x3AD1, 0x3ACF, 0x3ACD, 0x3ACB, 0x3AC9, 0x3AC7, 0x3AC5, 0x3AC3,
+      0x3AC1, 0x3ABF, 0x3ABD, 0x3ABB, 0x3AB9, 0x3AB7, 0x3AB5, 0x3AB3,
+      0x3AB1, },
+    { 0x0F60, 0x0F62, 0x0F64, 0x0F66, 0x0F68, 0x0F6A, 0x0F6C, 0x0F6E,
+      0x0F70, 0x0F72, 0x0F74, 0x0F76, 0x0F78, 0x0F7A, 0x0F7C, 0x0F7E,
+      0x0F80, 0x0F82, 0x0F84, 0x0F86, 0x0F88, 0x0F8A, 0x0F8C, 0x0F8E,
+      0x0F90, 0x0F92, 0x0F94, 0x0F96, 0x0F98, 0x0F9A, 0x0F9C, 0x0F9E,
+      0x0FA0, 0x0FA2, 0x0FA4, 0x0FA6, 0x0FA8, 0x0FAA, 0x0FAC, 0x0FAE,
+      0x0FB0, 0x0FB2, 0x0FB4, 0x0FB6, 0x0FB8, 0x0FBA, 0x0FBC, 0x0FBE,
+      0x07A0, 0x07A2, 0x03D2, 0x01EA, 0x00FC, 0x007F, 0x001C, 0x000C,
+      0x0004, 0x0034, 0x0010, 0x001B, 0x0009, 0x000B, 0x000E, 0x0001,
+      0x0003, 0x0002, 0x000F, 0x000C, 0x000A, 0x0000, 0x0011, 0x0035,
+      0x0005, 0x000D, 0x001D, 0x003C, 0x00FD, 0x01EB, 0x03D3, 0x07A3,
+      0x07A1, 0x0FBF, 0x0FBD, 0x0FBB, 0x0FB9, 0x0FB7, 0x0FB5, 0x0FB3,
+      0x0FB1, 0x0FAF, 0x0FAD, 0x0FAB, 0x0FA9, 0x0FA7, 0x0FA5, 0x0FA3,
+      0x0FA1, 0x0F9F, 0x0F9D, 0x0F9B, 0x0F99, 0x0F97, 0x0F95, 0x0F93,
+      0x0F91, 0x0F8F, 0x0F8D, 0x0F8B, 0x0F89, 0x0F87, 0x0F85, 0x0F83,
+      0x0F81, 0x0F7F, 0x0F7D, 0x0F7B, 0x0F79, 0x0F77, 0x0F75, 0x0F73,
+      0x0F71, 0x0F6F, 0x0F6D, 0x0F6B, 0x0F69, 0x0F67, 0x0F65, 0x0F63,
+      0x0F61, },
+    { 0x51D0, 0x51D2, 0x51D4, 0x51D6, 0x51D8, 0x51DA, 0x51DC, 0x51DE,
+      0x51E0, 0x51E2, 0x51E4, 0x51E6, 0x51E8, 0x51EA, 0x51EC, 0x51EE,
+      0x51F0, 0x51F2, 0x51F4, 0x51F6, 0x51F8, 0x51FA, 0x51FC, 0x51FE,
+      0x70C0, 0x70C2, 0x70C4, 0x70C6, 0x70C8, 0x70CA, 0x70CC, 0x70CE,
+      0x70EC, 0x10EA, 0x3868, 0x3877, 0x0876, 0x1C35, 0x0434, 0x0A34,
+      0x0E1B, 0x021B, 0x051B, 0x070F, 0x010F, 0x0380, 0x0080, 0x0140,
+      0x01C1, 0x0041, 0x00A1, 0x00E2, 0x0022, 0x0052, 0x0072, 0x0012,
+      0x002A, 0x003A, 0x000A, 0x0016, 0x001E, 0x0006, 0x000C, 0x0000,
+      0x0004, 0x0001, 0x000D, 0x0007, 0x001F, 0x0017, 0x000B, 0x003B,
+      0x002B, 0x0013, 0x0073, 0x0053, 0x0023, 0x00E3, 0x00A2, 0x0042,
+      0x01C2, 0x0141, 0x0081, 0x0381, 0x028C, 0x010C, 0x051C, 0x021C,
+      0x0E1C, 0x0A35, 0x0435, 0x1C3A, 0x0877, 0x0874, 0x3869, 0x10EB,
+      0x70ED, 0x70CF, 0x70CD, 0x70CB, 0x70C9, 0x70C7, 0x70C5, 0x70C3,
+      0x70C1, 0x51FF, 0x51FD, 0x51FB, 0x51F9, 0x51F7, 0x51F5, 0x51F3,
+      0x51F1, 0x51EF, 0x51ED, 0x51EB, 0x51E9, 0x51E7, 0x51E5, 0x51E3,
+      0x51E1, 0x51DF, 0x51DD, 0x51DB, 0x51D9, 0x51D7, 0x51D5, 0x51D3,
+      0x51D1, },
+    { 0x6F64, 0x6F66, 0x6F68, 0x6F6A, 0x6F6C, 0x6F6E, 0x6F70, 0x6F72,
+      0x6F74, 0x6F76, 0x6F78, 0x6F7A, 0x6F7C, 0x6F7E, 0x6F80, 0x6F82,
+      0x6F84, 0x6F86, 0x6F88, 0x6F8A, 0x6F8C, 0x6F8E, 0x6F90, 0x6F92,
+      0x6F94, 0x6F96, 0x6F98, 0x6F9A, 0x6F9C, 0x6F9E, 0x6FA0, 0x6FA2,
+      0x6FA4, 0x6FA6, 0x6FA8, 0x6FAA, 0x6FAC, 0x6FAE, 0x6FB0, 0x6FB2,
+      0x6FB4, 0x6FB6, 0x17B4, 0x37DC, 0x0BDB, 0x1BEF, 0x05EE, 0x0DF8,
+      0x02F8, 0x06FD, 0x017D, 0x037F, 0x00BF, 0x0040, 0x00C0, 0x0021,
+      0x0061, 0x0011, 0x0031, 0x0009, 0x0019, 0x0006, 0x000E, 0x0004,
+      0x0000, 0x0005, 0x000F, 0x0007, 0x001A, 0x000A, 0x0036, 0x0016,
+      0x006E, 0x002E, 0x00C1, 0x0041, 0x01BC, 0x00BC, 0x037A, 0x017A,
+      0x02F9, 0x0DF9, 0x05EF, 0x05EC, 0x1BD8, 0x37DD, 0x17B5, 0x6FB7,
+      0x6FB5, 0x6FB3, 0x6FB1, 0x6FAF, 0x6FAD, 0x6FAB, 0x6FA9, 0x6FA7,
+      0x6FA5, 0x6FA3, 0x6FA1, 0x6F9F, 0x6F9D, 0x6F9B, 0x6F99, 0x6F97,
+      0x6F95, 0x6F93, 0x6F91, 0x6F8F, 0x6F8D, 0x6F8B, 0x6F89, 0x6F87,
+      0x6F85, 0x6F83, 0x6F81, 0x6F7F, 0x6F7D, 0x6F7B, 0x6F79, 0x6F77,
+      0x6F75, 0x6F73, 0x6F71, 0x6F6F, 0x6F6D, 0x6F6B, 0x6F69, 0x6F67,
+      0x6F65, },
+    { 0xDF54, 0xDF56, 0xDFC8, 0xDFCA, 0xDFCC, 0xDFCE, 0xDFD0, 0xDFD2,
+      0xDFD4, 0xDFD6, 0xDFD8, 0xDFDA, 0xDFDC, 0xDFDE, 0xDFE0, 0xDFE2,
+      0x0FE8, 0x2FEA, 0x6FA8, 0x6FF6, 0x07F5, 0x07F7, 0x37D2, 0x37F9,
+      0x03F8, 0x0BF8, 0x0BFB, 0x1BEB, 0x01FA, 0x05FA, 0x09FA, 0x0DFA,
+      0x0DFF, 0x00FF, 0x02FF, 0x06FB, 0x007C, 0x017C, 0x027C, 0x027F,
+      0x003C, 0x00BC, 0x013C, 0x01BC, 0x001C, 0x005C, 0x009C, 0x00DC,
+      0x000C, 0x002C, 0x004C, 0x006C, 0x0004, 0x0014, 0x0024, 0x0034,
+      0x0000, 0x0008, 0x0010, 0x0018, 0x001E, 0x0002, 0x0006, 0x000A,
+      0x000E, 0x000B, 0x0007, 0x0003, 0x001F, 0x0019, 0x0011, 0x0009,
+      0x0001, 0x0035, 0x0025, 0x0015, 0x0005, 0x006D, 0x004D, 0x002D,
+      0x000D, 0x00DD, 0x009D, 0x005D, 0x001D, 0x01BD, 0x013D, 0x00BD,
+      0x003D, 0x037C, 0x027D, 0x017D, 0x007D, 0x06FC, 0x04FC, 0x02FC,
+      0x00FC, 0x0DFB, 0x09FB, 0x05FB, 0x01FB, 0x1BF8, 0x1BE8, 0x0BF9,
+      0x03F9, 0x37FA, 0x37D3, 0x17F4, 0x07F6, 0x6FF7, 0x6FA9, 0x2FEB,
+      0x0FE9, 0xDFE3, 0xDFE1, 0xDFDF, 0xDFDD, 0xDFDB, 0xDFD9, 0xDFD7,
+      0xDFD5, 0xDFD3, 0xDFD1, 0xDFCF, 0xDFCD, 0xDFCB, 0xDFC9, 0xDF57,
+      0xDF55, }
+};
+
+static const uint8_t scales_bits[SCALES_COUNT][129] = {
+    { 14, 14, 14, 14, 14, 14, 14, 14,
+      14, 14, 14, 14, 14, 14, 14, 14,
+      14, 14, 14, 14, 14, 14, 14, 14,
+      14, 14, 14, 14, 14, 14, 14, 14,
+      14, 14, 14, 14, 14, 14, 14, 14,
+      13, 13, 13, 13, 13, 13, 13, 13,
+      13, 13, 12, 11, 11, 10,  9,  8,
+       8,  7,  6,  6,  5,  4,  4,  3,
+       2,  3,  3,  4,  5,  5,  6,  7,
+       8,  8,  9, 10, 11, 11, 12, 13,
+      13, 13, 13, 13, 13, 13, 13, 13,
+      13, 14, 14, 14, 14, 14, 14, 14,
+      14, 14, 14, 14, 14, 14, 14, 14,
+      14, 14, 14, 14, 14, 14, 14, 14,
+      14, 14, 14, 14, 14, 14, 14, 14,
+      14, 14, 14, 14, 14, 14, 14, 14,
+      14, },
+    { 15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      14, 14, 13, 12, 11, 10,  8,  7,
+       6,  6,  5,  5,  4,  4,  4,  3,
+       3,  3,  4,  4,  4,  4,  5,  6,
+       6,  7,  8,  9, 11, 12, 13, 14,
+      14, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, },
+    { 15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 14, 14, 14, 13, 13, 12, 12,
+      12, 11, 11, 11, 10, 10,  9,  9,
+       9,  8,  8,  8,  7,  7,  7,  6,
+       6,  6,  5,  5,  5,  4,  4,  3,
+       3,  3,  4,  4,  5,  5,  5,  6,
+       6,  6,  7,  7,  7,  8,  8,  8,
+       9,  9,  9, 10, 10, 10, 11, 11,
+      12, 12, 12, 13, 13, 13, 14, 14,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, },
+    { 15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 14, 14, 13, 13, 12, 12,
+      11, 11, 10, 10,  9,  8,  8,  7,
+       7,  6,  6,  5,  5,  4,  4,  3,
+       2,  3,  4,  4,  5,  5,  6,  6,
+       7,  7,  8,  8,  9,  9, 10, 10,
+      11, 12, 12, 12, 13, 14, 14, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, 15, 15, 15, 15, 15, 15, 15,
+      15, },
+    { 16, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,
+      15, 15, 15, 15, 14, 14, 14, 14,
+      13, 13, 13, 13, 12, 12, 12, 12,
+      12, 11, 11, 11, 10, 10, 10, 10,
+       9,  9,  9,  9,  8,  8,  8,  8,
+       7,  7,  7,  7,  6,  6,  6,  6,
+       5,  5,  5,  5,  5,  4,  4,  4,
+       4,  4,  4,  4,  5,  5,  5,  5,
+       5,  6,  6,  6,  6,  7,  7,  7,
+       7,  8,  8,  8,  8,  9,  9,  9,
+       9, 10, 10, 10, 10, 11, 11, 11,
+      11, 12, 12, 12, 12, 13, 13, 13,
+      13, 14, 14, 14, 14, 15, 15, 15,
+      15, 16, 16, 16, 16, 16, 16, 16,
+      16, 16, 16, 16, 16, 16, 16, 16,
+      16,
+    }
+};
+
+static const uint16_t bitalloc_3_codes[3] = {
+    0x0003, 0x0000, 0x0002,
+};
+
+static const uint8_t bitalloc_3_bits[3] = {
+    2,  1,  2,
+};
+
+static const uint16_t bitalloc_5_codes_a[5] = {
+    0x000F, 0x0006, 0x0000, 0x0002, 0x000E,
+};
+
+static const uint16_t bitalloc_5_codes_b[5] = {
+    0x0007, 0x0001, 0x0002, 0x0000, 0x0006,
+};
+
+static const uint16_t bitalloc_5_codes_c[5] = {
+    0x0007, 0x0005, 0x0000, 0x0004, 0x0006,
+};
+
+static const uint8_t bitalloc_5_bits_a[5] = {
+    4,  3,  1,  2,  4,
+};
+
+static const uint8_t bitalloc_5_bits_b[5] = {
+    3,  2,  2,  2,  3,
+};
+
+static const uint8_t bitalloc_5_bits_c[5] = {
+    3,  3,  1,  3,  3,
+};
+
+static const uint16_t bitalloc_7_codes_a[7] = {
+    0x001E, 0x000E, 0x0005, 0x0000, 0x0006, 0x0004, 0x001F,
+};
+
+static const uint16_t bitalloc_7_codes_b[7] = {
+    0x0014, 0x000B, 0x0000, 0x0003, 0x0001, 0x0004, 0x0015,
+};
+
+static const uint16_t bitalloc_7_codes_c[7] = {
+    0x0000, 0x0002, 0x0001, 0x0003, 0x0002, 0x0003, 0x0001,
+};
+
+static const uint8_t bitalloc_7_bits_a[7] = {
+    5,  4,  3,  1,  3,  3,  5,
+};
+
+static const uint8_t bitalloc_7_bits_b[7] = {
+    5,  4,  2,  2,  2,  3,  5,
+};
+
+static const uint8_t bitalloc_7_bits_c[7] = {
+    4,  4,  2,  2,  2,  4,  4,
+};
+
+static const uint16_t bitalloc_9_codes_a[9] = {
+    0x0030, 0x0019, 0x0009, 0x0005, 0x0000, 0x0007, 0x000D, 0x0008,
+    0x0031,
+};
+
+static const uint16_t bitalloc_9_codes_b[9] = {
+    0x0018, 0x001A, 0x0002, 0x0007, 0x0002, 0x0000, 0x0003, 0x001B,
+    0x0019,
+};
+
+static const uint16_t bitalloc_9_codes_c[9] = {
+    0x001C, 0x000F, 0x0002, 0x0007, 0x0002, 0x0000, 0x0006, 0x0006,
+    0x001D,
+};
+
+static const uint8_t bitalloc_9_bits_a[9] = {
+    6,  5,  4,  3,  1,  3,  4,  4,  6,
+};
+
+static const uint8_t bitalloc_9_bits_b[9] = {
+    5,  5,  3,  3,  2,  2,  3,  5,  5,
+};
+
+static const uint8_t bitalloc_9_bits_c[9] = {
+    6,  5,  3,  3,  2,  2,  3,  4,  6,
+};
+
+static const uint16_t bitalloc_13_codes_a[13] = {
+    0x0070, 0x002E, 0x0039, 0x001D, 0x000C, 0x000F, 0x0000, 0x0004,
+    0x000D, 0x000A, 0x0016, 0x002F, 0x0071,
+};
+
+static const uint16_t bitalloc_13_codes_b[13] = {
+    0x0038, 0x0010, 0x001D, 0x0007, 0x000F, 0x0005, 0x0000, 0x0006,
+    0x0002, 0x0009, 0x0006, 0x0011, 0x0039,
+};
+
+static const uint16_t bitalloc_13_codes_c[13] = {
+    0x0004, 0x001A, 0x0003, 0x000E, 0x0000, 0x0003, 0x0005, 0x0004,
+    0x0002, 0x000F, 0x000C, 0x001B, 0x0005,
+};
+
+static const uint8_t bitalloc_13_bits_a[13] = {
+     7,  6,  6,  5,  4,  4,  1,  3,  4,  4,  5,  6,  7,
+};
+
+static const uint8_t bitalloc_13_bits_b[13] = {
+     6,  5,  5,  4,  4,  3,  2,  3,  3,  4,  4,  5,  6,
+};
+
+static const uint8_t bitalloc_13_bits_c[13] = {
+     5,  5,  4,  4,  3,  3,  3,  3,  3,  4,  4,  5,  5,
+};
+
+static const uint16_t bitalloc_17_codes_a[17] = {
+    0x0154, 0x00AB, 0x002B, 0x000B, 0x0003, 0x000A, 0x0001, 0x0006,
+    0x0001, 0x0007, 0x0004, 0x000B, 0x0000, 0x0004, 0x0014, 0x0054,
+    0x0155,
+};
+
+static const uint16_t bitalloc_17_codes_b[17] = {
+    0x007C, 0x003F, 0x0019, 0x000D, 0x001C, 0x0008, 0x000F, 0x0005,
+    0x0000, 0x0006, 0x0002, 0x0009, 0x001D, 0x000E, 0x001E, 0x0018,
+    0x007D,
+};
+
+static const uint16_t bitalloc_17_codes_c[17] = {
+    0x002C, 0x0017, 0x0005, 0x001C, 0x0003, 0x000A, 0x000F, 0x0003,
+    0x0006, 0x0004, 0x0000, 0x000B, 0x0004, 0x001D, 0x000A, 0x0004,
+    0x002D,
+};
+
+static const uint16_t bitalloc_17_codes_d[17] = {
+    0x0100, 0x0102, 0x0082, 0x0042, 0x0022, 0x0012, 0x000A, 0x0006,
+    0x0000, 0x0007, 0x000B, 0x0013, 0x0023, 0x0043, 0x0083, 0x0103,
+    0x0101,
+};
+
+static const uint16_t bitalloc_17_codes_e[17] = {
+    0x00E8, 0x00F6, 0x0075, 0x0034, 0x003B, 0x001B, 0x001F, 0x0004,
+    0x0000, 0x0005, 0x000C, 0x001C, 0x003C, 0x0035, 0x007A, 0x00F7,
+    0x00E9,
+};
+
+static const uint16_t bitalloc_17_codes_f[17] = {
+    0x0004, 0x0003, 0x001E, 0x0001, 0x0001, 0x000E, 0x0001, 0x0004,
+    0x0006, 0x0005, 0x0002, 0x000F, 0x0006, 0x000E, 0x001F, 0x0000,
+    0x0005,
+};
+
+static const uint16_t bitalloc_17_codes_g[17] = {
+    0x0060, 0x007E, 0x0031, 0x0019, 0x000D, 0x0004, 0x0000, 0x0006,
+    0x0002, 0x0007, 0x0001, 0x0005, 0x000E, 0x001E, 0x003E, 0x007F,
+    0x0061,
+};
+
+static const uint8_t bitalloc_17_bits_a[17] = {
+    12, 11,  9,  7,  5,  4,  3,  3,  2,  3,  3,  4,  4,  6,  8, 10,
+    12,
+};
+
+static const uint8_t bitalloc_17_bits_b[17] = {
+    8,  7,  6,  5,  5,  4,  4,  3,  2,  3,  3,  4,  5,  5,  6,  6,
+    8,
+};
+
+static const uint8_t bitalloc_17_bits_c[17] = {
+    7,  6,  5,  5,  4,  4,  4,  3,  3,  3,  3,  4,  4,  5,  5,  5,
+    7,
+};
+
+static const uint8_t bitalloc_17_bits_d[17] = {
+    9,  9,  8,  7,  6,  5,  4,  3,  1,  3,  4,  5,  6,  7,  8,  9,
+    9,
+};
+
+static const uint8_t bitalloc_17_bits_e[17] = {
+    8,  8,  7,  6,  6,  5,  5,  3,  1,  3,  4,  5,  6,  6,  7,  8,
+    8,
+};
+
+static const uint8_t bitalloc_17_bits_f[17] = {
+    8,  7,  6,  5,  4,  4,  3,  3,  3,  3,  3,  4,  4,  5,  6,  6,
+    8,
+};
+
+static const uint8_t bitalloc_17_bits_g[17] = {
+    8,  8,  7,  6,  5,  4,  3,  3,  2,  3,  3,  4,  5,  6,  7,  8,
+    8,
+};
+
+static const uint16_t bitalloc_25_codes_a[25] = {
+    0x2854, 0x142B, 0x050B, 0x0143, 0x00A2, 0x0052, 0x002E, 0x0015,
+    0x0004, 0x000E, 0x0000, 0x0003, 0x0006, 0x0004, 0x0001, 0x000F,
+    0x0005, 0x0016, 0x002F, 0x0053, 0x00A3, 0x00A0, 0x0284, 0x0A14,
+    0x2855,
+};
+
+static const uint16_t bitalloc_25_codes_b[25] = {
+    0x001C, 0x000F, 0x0005, 0x0000, 0x0030, 0x0036, 0x000E, 0x0019,
+    0x0001, 0x0008, 0x000E, 0x0001, 0x0005, 0x0002, 0x000F, 0x0009,
+    0x0006, 0x001A, 0x000F, 0x0037, 0x0031, 0x0001, 0x0006, 0x0004,
+    0x001D,
+};
+
+static const uint16_t bitalloc_25_codes_c[25] = {
+    0x004C, 0x0027, 0x006D, 0x0028, 0x0037, 0x000E, 0x0015, 0x0000,
+    0x0005, 0x0008, 0x000B, 0x000E, 0x0001, 0x000F, 0x000C, 0x0009,
+    0x0006, 0x0001, 0x001A, 0x000F, 0x0008, 0x0029, 0x0012, 0x006C,
+    0x004D,
+};
+
+static const uint16_t bitalloc_25_codes_d[25] = {
+    0x0780, 0x0782, 0x03C2, 0x01E2, 0x00FE, 0x0079, 0x003D, 0x001C,
+    0x000C, 0x0004, 0x0000, 0x0006, 0x0002, 0x0007, 0x0001, 0x0005,
+    0x000D, 0x001D, 0x003E, 0x007E, 0x00FF, 0x01E3, 0x03C3, 0x0783,
+    0x0781,
+};
+
+static const uint16_t bitalloc_25_codes_e[25] = {
+    0x003C, 0x0092, 0x0018, 0x001F, 0x004E, 0x000D, 0x0025, 0x0004,
+    0x0010, 0x0000, 0x000A, 0x0002, 0x0003, 0x0003, 0x000B, 0x0001,
+    0x0011, 0x0005, 0x0026, 0x000E, 0x004F, 0x0048, 0x0019, 0x0093,
+    0x003D,
+};
+
+static const uint16_t bitalloc_25_codes_f[25] = {
+    0x0324, 0x0193, 0x00CE, 0x0065, 0x0024, 0x000C, 0x0013, 0x0004,
+    0x0007, 0x000A, 0x000D, 0x000F, 0x0001, 0x0000, 0x000E, 0x000B,
+    0x0008, 0x0005, 0x0018, 0x000D, 0x0025, 0x0066, 0x00CF, 0x00C8,
+    0x0325,
+};
+
+static const uint16_t bitalloc_25_codes_g[25] = {
+    0x03A8, 0x03AE, 0x01D5, 0x0094, 0x0014, 0x004B, 0x000B, 0x003B,
+    0x0013, 0x0003, 0x000F, 0x0005, 0x0001, 0x0006, 0x0000, 0x0008,
+    0x001C, 0x0004, 0x0024, 0x0074, 0x0015, 0x0095, 0x01D6, 0x03AF,
+    0x03A9,
+};
+
+static const uint8_t bitalloc_25_bits_a[25] = {
+    14, 13, 11,  9,  8,  7,  6,  5,  4,  4,  3,  3,  3,  3,  3,  4,
+     4,  5,  6,  7,  8,  8, 10, 12, 14,
+};
+
+static const uint8_t bitalloc_25_bits_b[25] = {
+    9,  8,  7,  6,  6,  6,  5,  5,  4,  4,  4,  3,  3,  3,  4,  4,
+    4,  5,  5,  6,  6,  6,  7,  7,  9,
+};
+
+static const uint8_t bitalloc_25_bits_c[25] = {
+    8,  7,  7,  6,  6,  5,  5,  4,  4,  4,  4,  4,  3,  4,  4,  4,
+    4,  4,  5,  5,  5,  6,  6,  7,  8,
+};
+
+static const uint8_t bitalloc_25_bits_d[25] = {
+    12, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  3,  2,  3,  3,  4,
+     5,  6,  7,  8,  9, 10, 11, 12, 12,
+};
+
+static const uint8_t bitalloc_25_bits_e[25] = {
+    8,  8,  7,  7,  7,  6,  6,  5,  5,  4,  4,  3,  2,  3,  4,  4,
+    5,  5,  6,  6,  7,  7,  7,  8,  8,
+};
+
+static const uint8_t bitalloc_25_bits_f[25] = {
+    10,  9,  8,  7,  6,  5,  5,  4,  4,  4,  4,  4,  3,  3,  4,  4,
+     4,  4,  5,  5,  6,  7,  8,  8, 10,
+};
+
+static const uint8_t bitalloc_25_bits_g[25] = {
+    10, 10,  9,  8,  7,  7,  6,  6,  5,  4,  4,  3,  2,  3,  3,  4,
+     5,  5,  6,  7,  7,  8,  9, 10, 10,
+};
+
+static const uint16_t bitalloc_33_codes_a[33] = {
+    0x1580, 0x1582, 0x0AC2, 0x0562, 0x02B2, 0x015E, 0x00AD, 0x0054,
+    0x001C, 0x003C, 0x000F, 0x001F, 0x0008, 0x000B, 0x000D, 0x0000,
+    0x0002, 0x0001, 0x000E, 0x000C, 0x0009, 0x0006, 0x0014, 0x003D,
+    0x001D, 0x0055, 0x00AE, 0x015F, 0x02B3, 0x0563, 0x0AC3, 0x1583,
+    0x1581,
+};
+
+static const uint16_t bitalloc_33_codes_b[33] = {
+    0x030C, 0x0187, 0x006D, 0x0028, 0x0037, 0x0066, 0x0015, 0x0031,
+    0x0000, 0x000B, 0x0012, 0x001A, 0x0001, 0x0007, 0x000A, 0x000E,
+    0x0001, 0x000F, 0x000B, 0x0008, 0x0004, 0x001B, 0x0013, 0x000C,
+    0x0001, 0x0032, 0x001A, 0x0067, 0x0060, 0x0029, 0x00C2, 0x006C,
+    0x030D,
+};
+
+static const uint16_t bitalloc_33_codes_c[33] = {
+    0x00CC, 0x0067, 0x0005, 0x0070, 0x0003, 0x001A, 0x0039, 0x003F,
+    0x000A, 0x0012, 0x0018, 0x001D, 0x0001, 0x0003, 0x0007, 0x000A,
+    0x000D, 0x000B, 0x0008, 0x0004, 0x0002, 0x001E, 0x0019, 0x0013,
+    0x000B, 0x0000, 0x003E, 0x001B, 0x0018, 0x0071, 0x0032, 0x0004,
+    0x00CD,
+};
+
+static const uint16_t bitalloc_33_codes_d[33] = {
+    0x3AF8, 0x3AFA, 0x1D7E, 0x0EBC, 0x075C, 0x03AC, 0x01D4, 0x0094,
+    0x0014, 0x004B, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005,
+    0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x0074,
+    0x0015, 0x0095, 0x01D5, 0x03AD, 0x075D, 0x0EBD, 0x1D7F, 0x3AFB,
+    0x3AF9,
+};
+
+static const uint16_t bitalloc_33_codes_e[33] = {
+    0x01C8, 0x01E6, 0x0064, 0x00E2, 0x00E5, 0x0030, 0x0033, 0x0073,
+    0x007A, 0x001A, 0x003A, 0x0002, 0x001A, 0x001F, 0x0007, 0x0001,
+    0x0002, 0x0002, 0x000C, 0x0000, 0x001B, 0x0003, 0x003B, 0x001B,
+    0x007B, 0x0078, 0x0070, 0x0031, 0x00F2, 0x00E3, 0x0065, 0x01E7,
+    0x01C9,
+};
+
+static const uint16_t bitalloc_33_codes_f[33] = {
+    0x0724, 0x0393, 0x01CE, 0x00E5, 0x002C, 0x0008, 0x0017, 0x003E,
+    0x0005, 0x0014, 0x001D, 0x0000, 0x0003, 0x0006, 0x0008, 0x000B,
+    0x000D, 0x000C, 0x0009, 0x0007, 0x0004, 0x0001, 0x001E, 0x0015,
+    0x000A, 0x003F, 0x0038, 0x0009, 0x002D, 0x00E6, 0x01CF, 0x01C8,
+    0x0725,
+};
+
+static const uint16_t bitalloc_33_codes_g[33] = {
+    0x0284, 0x0042, 0x0140, 0x0143, 0x003E, 0x00BE, 0x0011, 0x0051,
+    0x0009, 0x0029, 0x0005, 0x0015, 0x0000, 0x0008, 0x000E, 0x0002,
+    0x0006, 0x0003, 0x000F, 0x0009, 0x0001, 0x0016, 0x0006, 0x002E,
+    0x000E, 0x005E, 0x001E, 0x00BF, 0x003F, 0x0020, 0x0141, 0x0043,
+    0x0285,
+};
+
+static const uint8_t bitalloc_33_bits_a[33] = {
+    13, 13, 12, 11, 10,  9,  8,  7,  6,  6,  5,  5,  4,  4,  4,  3,
+     3,  3,  4,  4,  4,  4,  5,  6,  6,  7,  8,  9, 10, 11, 12, 13,
+    13,
+};
+
+static const uint8_t bitalloc_33_bits_b[33] = {
+    10,  9,  8,  7,  7,  7,  6,  6,  5,  5,  5,  5,  4,  4,  4,  4,
+     3,  4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  7,  7,  7,  8,  8,
+    10,
+};
+
+static const uint8_t bitalloc_33_bits_c[33] = {
+    9,  8,  7,  7,  6,  6,  6,  6,  5,  5,  5,  5,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  6,  6,  6,  7,  7,  7,
+    9,
+};
+
+static const uint8_t bitalloc_33_bits_d[33] = {
+    14, 14, 13, 12, 11, 10,  9,  8,  7,  7,  6,  6,  5,  4,  4,  3,
+     2,  3,  3,  4,  5,  5,  6,  7,  7,  8,  9, 10, 11, 12, 13, 14,
+    14,
+};
+
+static const uint8_t bitalloc_33_bits_e[33] = {
+    9,  9,  8,  8,  8,  7,  7,  7,  7,  6,  6,  5,  5,  5,  4,  3,
+    2,  3,  4,  4,  5,  5,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,
+    9,
+};
+
+static const uint8_t bitalloc_33_bits_f[33] = {
+    11, 10,  9,  8,  7,  6,  6,  6,  5,  5,  5,  4,  4,  4,  4,  4,
+     4,  4,  4,  4,  4,  4,  5,  5,  5,  6,  6,  6,  7,  8,  9,  9,
+    11,
+};
+
+static const uint8_t bitalloc_33_bits_g[33] = {
+    10,  9,  9,  9,  8,  8,  7,  7,  6,  6,  5,  5,  4,  4,  4,  3,
+     3,  3,  4,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8,  8,  9,  9,
+    10,
+};
+
+static const uint16_t bitalloc_65_codes_a[65] = {
+    0x9E5C, 0x9E5E, 0x4F2C, 0x2794, 0x13C4, 0x1E44, 0x09E3, 0x0F23,
+    0x04F3, 0x0792, 0x027E, 0x03CE, 0x013D, 0x01E5, 0x009C, 0x00CC,
+    0x0040, 0x0058, 0x0067, 0x001E, 0x0021, 0x002D, 0x003D, 0x0007,
+    0x0011, 0x0014, 0x0017, 0x001A, 0x001C, 0x001F, 0x0001, 0x0004,
+    0x0006, 0x0005, 0x0002, 0x0000, 0x001D, 0x001B, 0x0018, 0x0015,
+    0x0012, 0x000E, 0x0006, 0x0032, 0x0026, 0x001F, 0x0078, 0x0059,
+    0x0041, 0x00CD, 0x009D, 0x01E6, 0x013E, 0x03CF, 0x027F, 0x0793,
+    0x0790, 0x04F0, 0x09E4, 0x1E45, 0x13C5, 0x2795, 0x4F2D, 0x9E5F,
+    0x9E5D,
+};
+
+static const uint16_t bitalloc_65_codes_b[65] = {
+    0x0A8C, 0x0547, 0x01B5, 0x0008, 0x00DB, 0x0152, 0x0005, 0x000B,
+    0x008E, 0x00AE, 0x00E4, 0x0003, 0x0037, 0x0039, 0x0055, 0x006C,
+    0x0073, 0x0003, 0x0015, 0x001D, 0x0028, 0x0030, 0x0037, 0x003E,
+    0x0006, 0x000B, 0x000F, 0x0012, 0x0016, 0x0019, 0x001D, 0x0001,
+    0x0004, 0x0002, 0x001E, 0x001A, 0x0017, 0x0013, 0x0010, 0x000C,
+    0x0007, 0x003F, 0x0038, 0x0031, 0x0029, 0x0022, 0x001A, 0x0014,
+    0x0000, 0x006D, 0x0056, 0x0046, 0x0038, 0x0004, 0x00E5, 0x00AF,
+    0x008F, 0x006C, 0x000A, 0x0153, 0x0150, 0x0009, 0x02A2, 0x01B4,
+    0x0A8D,
+};
+
+static const uint16_t bitalloc_65_codes_c[65] = {
+    0x045C, 0x022F, 0x03F5, 0x01BC, 0x01FB, 0x0059, 0x00D0, 0x00DF,
+    0x000A, 0x002D, 0x002F, 0x0052, 0x0069, 0x0078, 0x007F, 0x000A,
+    0x0010, 0x001C, 0x0023, 0x002A, 0x0035, 0x003A, 0x003D, 0x0000,
+    0x0003, 0x0006, 0x0009, 0x000C, 0x000F, 0x0012, 0x0016, 0x0018,
+    0x001C, 0x0019, 0x0017, 0x0013, 0x0010, 0x000D, 0x000A, 0x0007,
+    0x0004, 0x0001, 0x003E, 0x003B, 0x0036, 0x002B, 0x0028, 0x001D,
+    0x0011, 0x000B, 0x0004, 0x0079, 0x006E, 0x0053, 0x0044, 0x002E,
+    0x000B, 0x00FC, 0x00D1, 0x008A, 0x0058, 0x01BD, 0x0116, 0x03F4,
+    0x045D,
+};
+
+static const uint16_t bitalloc_65_codes_d[65] = {
+    0x70B0, 0x70B2, 0x70B4, 0x2852, 0x385B, 0x142E, 0x1C2E, 0x0A15,
+    0x0E14, 0x0214, 0x0704, 0x0104, 0x010B, 0x0383, 0x0083, 0x0143,
+    0x01C3, 0x0043, 0x00A2, 0x00E2, 0x0022, 0x0052, 0x0072, 0x0012,
+    0x002A, 0x003A, 0x000A, 0x0016, 0x001E, 0x0006, 0x000C, 0x0000,
+    0x0004, 0x0001, 0x000D, 0x0007, 0x001F, 0x0017, 0x000B, 0x003B,
+    0x002B, 0x0013, 0x0073, 0x0053, 0x0023, 0x00E3, 0x00A3, 0x00A0,
+    0x0040, 0x01C0, 0x0084, 0x0384, 0x0284, 0x0105, 0x0705, 0x0215,
+    0x0E15, 0x0A16, 0x1C2F, 0x142F, 0x1428, 0x2853, 0x70B5, 0x70B3,
+    0x70B1,
+};
+
+static const uint16_t bitalloc_65_codes_e[65] = {
+    0x032C, 0x0332, 0x0378, 0x037E, 0x008C, 0x014A, 0x0188, 0x0197,
+    0x019E, 0x01BD, 0x0044, 0x0047, 0x00AA, 0x00C5, 0x00CD, 0x00DC,
+    0x001C, 0x002C, 0x0053, 0x0063, 0x0068, 0x0008, 0x000F, 0x0017,
+    0x002B, 0x0035, 0x0005, 0x0009, 0x0016, 0x001C, 0x0006, 0x000F,
+    0x0004, 0x0000, 0x0007, 0x001D, 0x0017, 0x000A, 0x0006, 0x0036,
+    0x0030, 0x0028, 0x0010, 0x0009, 0x0069, 0x0064, 0x0054, 0x002D,
+    0x001D, 0x00DD, 0x00CE, 0x00CA, 0x00AB, 0x00A4, 0x0045, 0x01BE,
+    0x019F, 0x0198, 0x0189, 0x014B, 0x008D, 0x037F, 0x0379, 0x0333,
+    0x032D,
+};
+
+static const uint16_t bitalloc_65_codes_f[65] = {
+    0x0FE0, 0x0FE2, 0x0FE8, 0x0FEA, 0x0FEC, 0x0FEE, 0x0FF0, 0x0FF2,
+    0x0FF4, 0x2FF2, 0x07F2, 0x07FB, 0x03F6, 0x0BFA, 0x0BFD, 0x01FF,
+    0x05FF, 0x02FC, 0x007C, 0x017C, 0x003C, 0x00BC, 0x001C, 0x005C,
+    0x000C, 0x002C, 0x0004, 0x0014, 0x0000, 0x0008, 0x000E, 0x0002,
+    0x0006, 0x0003, 0x000F, 0x0009, 0x0001, 0x0015, 0x0005, 0x002D,
+    0x000D, 0x005D, 0x001D, 0x00BD, 0x003D, 0x017D, 0x007D, 0x02FD,
+    0x00FC, 0x05FC, 0x01FA, 0x0BFB, 0x03F7, 0x17F8, 0x07F3, 0x2FF3,
+    0x0FF5, 0x0FF3, 0x0FF1, 0x0FEF, 0x0FED, 0x0FEB, 0x0FE9, 0x0FE3,
+    0x0FE1,
+};
+
+static const uint16_t bitalloc_65_codes_g[65] = {
+    0x010C, 0x038A, 0x0608, 0x0786, 0x0084, 0x0087, 0x0302, 0x0305,
+    0x0040, 0x00E0, 0x00E3, 0x0183, 0x001E, 0x005E, 0x009E, 0x00DE,
+    0x00F1, 0x0011, 0x0039, 0x0061, 0x0079, 0x0009, 0x001D, 0x0031,
+    0x003D, 0x0005, 0x000F, 0x0019, 0x001F, 0x0003, 0x0006, 0x000A,
+    0x000E, 0x000B, 0x0008, 0x0004, 0x0000, 0x001A, 0x0012, 0x000A,
+    0x0002, 0x0036, 0x0026, 0x0016, 0x0006, 0x006E, 0x004E, 0x002E,
+    0x000E, 0x00DF, 0x009F, 0x005F, 0x001F, 0x01E0, 0x0180, 0x00E1,
+    0x0041, 0x03C2, 0x0303, 0x01C4, 0x0085, 0x0787, 0x0609, 0x038B,
+    0x010D,
+};
+
+static const uint8_t bitalloc_65_bits_a[65] = {
+    16, 16, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10,  9,  9,  8,  8,
+     7,  7,  7,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,  5,  4,  4,
+     4,  4,  4,  4,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  7,  7,
+     7,  8,  8,  9,  9, 10, 10, 11, 11, 11, 12, 13, 13, 14, 15, 16,
+    16,
+};
+
+static const uint8_t bitalloc_65_bits_b[65] = {
+    12, 11, 10,  9,  9,  9,  8,  8,  8,  8,  8,  7,  7,  7,  7,  7,
+     7,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,  5,  4,
+     4,  4,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,
+     6,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  9,  9,  9, 10, 10,
+    12,
+};
+
+static const uint8_t bitalloc_65_bits_c[65] = {
+    11, 10, 10,  9,  9,  8,  8,  8,  7,  7,  7,  7,  7,  7,  7,  6,
+     6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,  5,  5,  5,
+     5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,
+     6,  6,  6,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  9,  9, 10,
+    11,
+};
+
+static const uint8_t bitalloc_65_bits_d[65] = {
+    15, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 10,  9,  9,
+     9,  8,  8,  8,  7,  7,  7,  6,  6,  6,  5,  5,  5,  4,  4,  3,
+     3,  3,  4,  4,  5,  5,  5,  6,  6,  6,  7,  7,  7,  8,  8,  8,
+     8,  9,  9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 15, 15,
+    15,
+};
+
+static const uint8_t bitalloc_65_bits_e[65] = {
+    10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,
+     7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  5,  5,  5,  5,  4,  4,
+     3,  3,  4,  5,  5,  5,  5,  6,  6,  6,  6,  6,  7,  7,  7,  7,
+     7,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9, 10, 10, 10,
+    10,
+};
+
+static const uint8_t bitalloc_65_bits_f[65] = {
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 11,
+    11, 10,  9,  9,  8,  8,  7,  7,  6,  6,  5,  5,  4,  4,  4,  3,
+     3,  3,  4,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8,  9,  9, 10,
+    10, 11, 11, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14,
+};
+
+static const uint8_t bitalloc_65_bits_g[65] = {
+    11, 11, 11, 11, 10, 10, 10, 10,  9,  9,  9,  9,  8,  8,  8,  8,
+     8,  7,  7,  7,  7,  6,  6,  6,  6,  5,  5,  5,  5,  4,  4,  4,
+     4,  4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,
+     7,  8,  8,  8,  8,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11,
+    11,
+};
+
+static const uint16_t bitalloc_129_codes_a[129] = {
+    0x0660, 0x0666, 0x06EC, 0x0722, 0x0760, 0x076E, 0x004C, 0x004E,
+    0x00F4, 0x010A, 0x0148, 0x0156, 0x01D4, 0x01F2, 0x0331, 0x0370,
+    0x0377, 0x0396, 0x03B1, 0x0024, 0x0064, 0x007B, 0x008A, 0x00A5,
+    0x00D4, 0x00EB, 0x00FA, 0x019A, 0x01B9, 0x01C9, 0x01D9, 0x0010,
+    0x0030, 0x0033, 0x0043, 0x0053, 0x006B, 0x007A, 0x00CA, 0x00D2,
+    0x00DE, 0x00E6, 0x00F6, 0x000E, 0x001F, 0x0023, 0x002B, 0x003B,
+    0x003F, 0x0067, 0x0070, 0x0077, 0x0005, 0x000D, 0x0012, 0x001B,
+    0x002C, 0x0035, 0x003A, 0x0004, 0x000B, 0x0017, 0x001F, 0x0009,
+    0x0008, 0x000A, 0x0000, 0x0018, 0x000C, 0x0005, 0x003C, 0x0036,
+    0x002D, 0x001C, 0x0013, 0x000E, 0x0006, 0x007A, 0x0071, 0x0068,
+    0x0064, 0x003C, 0x0034, 0x0028, 0x0020, 0x000F, 0x00F7, 0x00E7,
+    0x00DF, 0x00D3, 0x00CB, 0x007B, 0x0074, 0x0054, 0x0044, 0x003C,
+    0x0031, 0x0011, 0x01DA, 0x01CA, 0x01BA, 0x019B, 0x00FB, 0x00F8,
+    0x00D5, 0x00AA, 0x008B, 0x0084, 0x0065, 0x0025, 0x03B6, 0x0397,
+    0x0390, 0x0371, 0x0332, 0x01F3, 0x01D5, 0x0157, 0x0149, 0x010B,
+    0x00F5, 0x004F, 0x004D, 0x076F, 0x0761, 0x0723, 0x06ED, 0x0667,
+    0x0661,
+};
+
+static const uint16_t bitalloc_129_codes_b[129] = {
+    0x29DC, 0x14EF, 0x0455, 0x0E9C, 0x022B, 0x0489, 0x0740, 0x074F,
+    0x0172, 0x0245, 0x0247, 0x030A, 0x03A1, 0x001C, 0x008B, 0x00D6,
+    0x010C, 0x0148, 0x014F, 0x0186, 0x01D1, 0x0008, 0x000F, 0x0046,
+    0x005D, 0x0078, 0x0087, 0x0096, 0x00A5, 0x00BC, 0x00D8, 0x00DE,
+    0x00F6, 0x0005, 0x0014, 0x0024, 0x002F, 0x003A, 0x003D, 0x0049,
+    0x0050, 0x0058, 0x005F, 0x0066, 0x006D, 0x0075, 0x007C, 0x0004,
+    0x000B, 0x0013, 0x0018, 0x001B, 0x001F, 0x0022, 0x0026, 0x002A,
+    0x002D, 0x0031, 0x0034, 0x0038, 0x003B, 0x003F, 0x0003, 0x0006,
+    0x000A, 0x0007, 0x0004, 0x0000, 0x003C, 0x0039, 0x0035, 0x0032,
+    0x002E, 0x002B, 0x0027, 0x0023, 0x0020, 0x001C, 0x0019, 0x0016,
+    0x0010, 0x0005, 0x007D, 0x007A, 0x006E, 0x0067, 0x0060, 0x0059,
+    0x0051, 0x004A, 0x0042, 0x003B, 0x0034, 0x0025, 0x0015, 0x0006,
+    0x00F7, 0x00DF, 0x00D9, 0x00BD, 0x00A6, 0x0097, 0x0090, 0x0079,
+    0x006A, 0x0047, 0x0044, 0x0009, 0x01D2, 0x0187, 0x0184, 0x0149,
+    0x010D, 0x00D7, 0x00B8, 0x001D, 0x03A6, 0x030B, 0x029C, 0x0246,
+    0x0173, 0x0114, 0x0741, 0x053A, 0x0488, 0x0E9D, 0x0A76, 0x0454,
+    0x29DD,
+};
+
+static const uint16_t bitalloc_129_codes_c[129] = {
+    0x0E5C, 0x072F, 0x001D, 0x0724, 0x000F, 0x010D, 0x0324, 0x0393,
+    0x03E9, 0x0080, 0x0087, 0x00FA, 0x0164, 0x0193, 0x01DE, 0x01F5,
+    0x0010, 0x002A, 0x0041, 0x0064, 0x0073, 0x008E, 0x00A4, 0x00B3,
+    0x00D6, 0x00E5, 0x00F4, 0x00FB, 0x0002, 0x0009, 0x0013, 0x001E,
+    0x0026, 0x002C, 0x0033, 0x003F, 0x0041, 0x004C, 0x0053, 0x005E,
+    0x0065, 0x0070, 0x0073, 0x0078, 0x007B, 0x007E, 0x0002, 0x0005,
+    0x0007, 0x000B, 0x000D, 0x0011, 0x0014, 0x0017, 0x001A, 0x001D,
+    0x0021, 0x0024, 0x0027, 0x002A, 0x002D, 0x0030, 0x0033, 0x0036,
+    0x003A, 0x0037, 0x0034, 0x0031, 0x002E, 0x002B, 0x0028, 0x0025,
+    0x0022, 0x001E, 0x001B, 0x0018, 0x0015, 0x0012, 0x000E, 0x000C,
+    0x0008, 0x0006, 0x0003, 0x007F, 0x007C, 0x0079, 0x0076, 0x0071,
+    0x006A, 0x005F, 0x0058, 0x004D, 0x0046, 0x0040, 0x0038, 0x002D,
+    0x0027, 0x001F, 0x0014, 0x0012, 0x0003, 0x0000, 0x00F5, 0x00EE,
+    0x00D7, 0x00C8, 0x00A5, 0x008F, 0x007C, 0x0065, 0x0042, 0x002B,
+    0x0011, 0x0002, 0x01DF, 0x01C8, 0x0165, 0x00FB, 0x00E4, 0x0081,
+    0x0006, 0x03E8, 0x0325, 0x01CA, 0x010C, 0x0725, 0x0396, 0x001C,
+    0x0E5D,
+};
+
+static const uint16_t bitalloc_129_codes_d[129] = {
+    0xA598, 0xA59A, 0xA59C, 0xA59E, 0xC598, 0xE586, 0x3ACC, 0x52CA,
+    0x62CD, 0x0D48, 0x1D67, 0x2978, 0x3167, 0x3966, 0x06A5, 0x0EBC,
+    0x14BD, 0x1CB1, 0x0350, 0x0353, 0x075F, 0x0A5F, 0x0C5E, 0x0E5E,
+    0x01AE, 0x03AD, 0x052D, 0x062D, 0x072D, 0x00D5, 0x01D4, 0x0294,
+    0x0314, 0x0394, 0x0014, 0x0094, 0x0114, 0x0174, 0x01B4, 0x01F4,
+    0x000B, 0x004B, 0x008B, 0x00BB, 0x00DB, 0x00FB, 0x001B, 0x003B,
+    0x0053, 0x0063, 0x0073, 0x0003, 0x0013, 0x0023, 0x002F, 0x0037,
+    0x003F, 0x0007, 0x000F, 0x0015, 0x0019, 0x001D, 0x0001, 0x0005,
+    0x0009, 0x0006, 0x0002, 0x001E, 0x001A, 0x0016, 0x0010, 0x0008,
+    0x0000, 0x0038, 0x0030, 0x0028, 0x001C, 0x000C, 0x007C, 0x006C,
+    0x005C, 0x0044, 0x0024, 0x0004, 0x00E4, 0x00C4, 0x00A4, 0x0074,
+    0x0034, 0x01F5, 0x01B5, 0x0175, 0x0115, 0x0095, 0x0015, 0x0395,
+    0x0315, 0x0295, 0x01D5, 0x00D6, 0x072E, 0x062E, 0x052E, 0x03AE,
+    0x01AF, 0x0E5F, 0x0C5F, 0x0C58, 0x0A58, 0x0758, 0x0351, 0x1CB2,
+    0x18B2, 0x0EBD, 0x0EB2, 0x3967, 0x3960, 0x2979, 0x2964, 0x0D49,
+    0x72C2, 0x52CB, 0x3ACD, 0xE587, 0xC599, 0xA59F, 0xA59D, 0xA59B,
+    0xA599,
+};
+
+static const uint16_t bitalloc_129_codes_e[129] = {
+    0xA13C, 0xC720, 0xA13F, 0xA13E, 0xA13D, 0xE722, 0x5090, 0x6393,
+    0x7392, 0x2849, 0x31CE, 0x39CE, 0x1425, 0x18E5, 0x1CE5, 0x0844,
+    0x0A1C, 0x0C7C, 0x036C, 0x0423, 0x050F, 0x063F, 0x01B7, 0x0216,
+    0x0285, 0x031D, 0x039D, 0x0109, 0x0140, 0x0180, 0x01C8, 0x01CF,
+    0x007A, 0x008A, 0x00A2, 0x00C1, 0x00E5, 0x0014, 0x0037, 0x0043,
+    0x004E, 0x0056, 0x0061, 0x006C, 0x007C, 0x000B, 0x001C, 0x001F,
+    0x0023, 0x0025, 0x0029, 0x002C, 0x002E, 0x0032, 0x0034, 0x0037,
+    0x003A, 0x003C, 0x003F, 0x0001, 0x0003, 0x0006, 0x0008, 0x000A,
+    0x000C, 0x000B, 0x0009, 0x0007, 0x0004, 0x0002, 0x0000, 0x003D,
+    0x003B, 0x0038, 0x0035, 0x0033, 0x002F, 0x002D, 0x002A, 0x0026,
+    0x0024, 0x0020, 0x001D, 0x001A, 0x007D, 0x006D, 0x0062, 0x0057,
+    0x004F, 0x0044, 0x003C, 0x0015, 0x00E6, 0x00C6, 0x00A3, 0x008B,
+    0x007B, 0x006C, 0x01C9, 0x0181, 0x0141, 0x010A, 0x00DA, 0x031E,
+    0x0286, 0x0217, 0x0210, 0x0738, 0x0638, 0x0508, 0x036D, 0x0C7D,
+    0x0A1D, 0x0845, 0x1CE6, 0x18E6, 0x1426, 0x39CF, 0x31CF, 0x284E,
+    0x7393, 0x7390, 0x5091, 0xE723, 0xC724, 0xC725, 0xC722, 0xC723,
+    0xC721,
+};
+
+static const uint16_t bitalloc_129_codes_f[129] = {
+    0x762C, 0x3B17, 0x1555, 0x0608, 0x0AAB, 0x0FF2, 0x0305, 0x0307,
+    0x0763, 0x0046, 0x010C, 0x01BC, 0x02AB, 0x03B6, 0x03FD, 0x0080,
+    0x0087, 0x00DF, 0x0156, 0x01D9, 0x01F8, 0x01FF, 0x002A, 0x0041,
+    0x0061, 0x0094, 0x00D4, 0x00EA, 0x00F2, 0x00FD, 0x0009, 0x000B,
+    0x001A, 0x0026, 0x0031, 0x0040, 0x004B, 0x006B, 0x0073, 0x0077,
+    0x007A, 0x007C, 0x0000, 0x0002, 0x0006, 0x0008, 0x000B, 0x000E,
+    0x0011, 0x0014, 0x0016, 0x0019, 0x001C, 0x001E, 0x0021, 0x0023,
+    0x0026, 0x0028, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0036,
+    0x0038, 0x0037, 0x0034, 0x0032, 0x0030, 0x002E, 0x002C, 0x0029,
+    0x0027, 0x0024, 0x0022, 0x001F, 0x001D, 0x001A, 0x0017, 0x0015,
+    0x0012, 0x000F, 0x000C, 0x0009, 0x0007, 0x0003, 0x0001, 0x007D,
+    0x007B, 0x0078, 0x0074, 0x0072, 0x0054, 0x0041, 0x0036, 0x0027,
+    0x001B, 0x0014, 0x000A, 0x00FE, 0x00F3, 0x00EB, 0x00D5, 0x0095,
+    0x006E, 0x0042, 0x002B, 0x0010, 0x01F9, 0x01DA, 0x0157, 0x0154,
+    0x00C0, 0x0081, 0x0022, 0x03B7, 0x03B0, 0x01BD, 0x010D, 0x0047,
+    0x07F8, 0x0554, 0x0306, 0x0FF3, 0x0EC4, 0x0609, 0x1D8A, 0x1554,
+    0x762D,
+};
+
+static const uint16_t bitalloc_129_codes_g[129] = {
+    0x1E20, 0x1E5E, 0x031C, 0x051A, 0x0718, 0x0916, 0x0B14, 0x0D12,
+    0x0F11, 0x0090, 0x018F, 0x028E, 0x038D, 0x048C, 0x058B, 0x068A,
+    0x0789, 0x0049, 0x00C8, 0x0148, 0x01C7, 0x0247, 0x02C6, 0x0346,
+    0x03C5, 0x0025, 0x0065, 0x00A5, 0x00E4, 0x0124, 0x0164, 0x01A4,
+    0x01E3, 0x0013, 0x0033, 0x0053, 0x0073, 0x0093, 0x00B3, 0x00D3,
+    0x00F3, 0x000A, 0x001A, 0x002A, 0x003A, 0x004A, 0x005A, 0x006A,
+    0x007A, 0x0006, 0x000E, 0x0016, 0x001E, 0x0026, 0x002E, 0x0036,
+    0x003E, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C,
+    0x0000, 0x001D, 0x0019, 0x0015, 0x0011, 0x000D, 0x0009, 0x0005,
+    0x003F, 0x0037, 0x002F, 0x0027, 0x001F, 0x0017, 0x000F, 0x0007,
+    0x007B, 0x006B, 0x005B, 0x004B, 0x003B, 0x002B, 0x001B, 0x000B,
+    0x0008, 0x00F0, 0x00D0, 0x00B0, 0x0090, 0x0070, 0x0050, 0x0030,
+    0x01E4, 0x01A5, 0x0165, 0x0125, 0x00E5, 0x00E2, 0x00A2, 0x0062,
+    0x03CA, 0x0347, 0x02C7, 0x02C4, 0x0244, 0x0149, 0x00C9, 0x00C6,
+    0x0796, 0x068B, 0x0688, 0x048D, 0x048A, 0x028F, 0x028C, 0x0091,
+    0x0F2E, 0x0D13, 0x0B15, 0x0917, 0x0719, 0x051B, 0x031D, 0x1E5F,
+    0x1E21,
+};
+
+static const uint8_t bitalloc_129_bits_a[129] = {
+    11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  8,
+     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,  7,
+     7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  4,
+     4,  4,  4,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  7,  7,  7,
+     7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+     8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11,
+    11,
+};
+
+static const uint8_t bitalloc_129_bits_b[129] = {
+    14, 13, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10,  9,  9,  9,
+     9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+     8,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6,
+     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,
+     5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+     6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,
+     9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12,
+    14,
+};
+
+static const uint8_t bitalloc_129_bits_c[129] = {
+    13, 12, 11, 11, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  9,
+     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,
+     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,
+     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+     6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+     7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+     8,  8,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11,
+    13,
+};
+
+static const uint8_t bitalloc_129_bits_d[129] = {
+    16, 16, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13,
+    13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 10, 10, 10,
+    10, 10,  9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  7,  7,
+     7,  7,  7,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  4,  4,
+     4,  4,  4,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  7,  7,
+     7,  7,  7,  7,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9, 10,
+    10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13,
+    13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16,
+    16,
+};
+
+static const uint8_t bitalloc_129_bits_e[129] = {
+    16, 16, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12,
+    12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,
+     8,  8,  8,  8,  8,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,
+     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,
+     5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+     6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,
+     8,  8,  9,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11, 11, 12,
+    12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16,
+    16,
+};
+
+static const uint8_t bitalloc_129_bits_f[129] = {
+    15, 14, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 10, 10, 10,  9,
+     9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,
+     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6,
+     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
+     6,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,
+     7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,
+     9,  9,  9, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13,
+    15,
+};
+
+static const uint8_t bitalloc_129_bits_g[129] = {
+    13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11,
+    11, 10, 10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  9,
+     9,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,  7,  7,  7,
+     7,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,  5,
+     4,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,
+     7,  7,  7,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,
+     9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
+    11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13,
+    13,
+};
+
+static const uint8_t bitalloc_sizes[DCA_CODE_BOOKS] = {
+    3, 5, 7, 9, 13, 17, 25, 33, 65, 129
+};
+
+static const int8_t bitalloc_offsets[DCA_CODE_BOOKS] = {
+    -1, -2, -3, -4, -6, -8, -12, -16, -32, -64
+};
+
+static const uint8_t bitalloc_maxbits[DCA_CODE_BOOKS][7] = {
+    { 2 },
+    { 4, 3, 3 },
+    { 5, 5, 4 },
+    { 6, 5, 6 },
+    { 7, 6, 5 },
+    { 9, 8, 7, 9, 8, 8, 8 },
+    { 9, 9, 8, 9, 8, 9, 9 },
+    { 9, 9, 9, 9, 9, 9, 9 },
+    { 9, 9, 9, 9, 9, 9, 9 },
+    { 9, 9, 9, 9, 9, 9, 9 }
+};
+
+static const uint16_t *const bitalloc_codes[DCA_CODE_BOOKS][8] = {
+    { bitalloc_3_codes,     NULL },
+    { bitalloc_5_codes_a,   bitalloc_5_codes_b,   bitalloc_5_codes_c,   NULL },
+    { bitalloc_7_codes_a,   bitalloc_7_codes_b,   bitalloc_7_codes_c,   NULL },
+    { bitalloc_9_codes_a,   bitalloc_9_codes_b,   bitalloc_9_codes_c,   NULL },
+    { bitalloc_13_codes_a,  bitalloc_13_codes_b,  bitalloc_13_codes_c,  NULL },
+    { bitalloc_17_codes_a,  bitalloc_17_codes_b,  bitalloc_17_codes_c,  bitalloc_17_codes_d,
+      bitalloc_17_codes_e,  bitalloc_17_codes_f,  bitalloc_17_codes_g,  NULL },
+    { bitalloc_25_codes_a,  bitalloc_25_codes_b,  bitalloc_25_codes_c,  bitalloc_25_codes_d,
+      bitalloc_25_codes_e,  bitalloc_25_codes_f,  bitalloc_25_codes_g,  NULL },
+    { bitalloc_33_codes_a,  bitalloc_33_codes_b,  bitalloc_33_codes_c,  bitalloc_33_codes_d,
+      bitalloc_33_codes_e,  bitalloc_33_codes_f,  bitalloc_33_codes_g,  NULL },
+    { bitalloc_65_codes_a,  bitalloc_65_codes_b,  bitalloc_65_codes_c,  bitalloc_65_codes_d,
+      bitalloc_65_codes_e,  bitalloc_65_codes_f,  bitalloc_65_codes_g,  NULL },
+    { bitalloc_129_codes_a, bitalloc_129_codes_b, bitalloc_129_codes_c, bitalloc_129_codes_d,
+      bitalloc_129_codes_e, bitalloc_129_codes_f, bitalloc_129_codes_g, NULL }
+};
+
+static const uint8_t *const bitalloc_bits[DCA_CODE_BOOKS][8] = {
+    { bitalloc_3_bits,     NULL },
+    { bitalloc_5_bits_a,   bitalloc_5_bits_b,   bitalloc_5_bits_c,   NULL },
+    { bitalloc_7_bits_a,   bitalloc_7_bits_b,   bitalloc_7_bits_c,   NULL },
+    { bitalloc_9_bits_a,   bitalloc_9_bits_b,   bitalloc_9_bits_c,   NULL },
+    { bitalloc_13_bits_a,  bitalloc_13_bits_b,  bitalloc_13_bits_c,  NULL },
+    { bitalloc_17_bits_a,  bitalloc_17_bits_b,  bitalloc_17_bits_c,  bitalloc_17_bits_d,
+      bitalloc_17_bits_e,  bitalloc_17_bits_f,  bitalloc_17_bits_g,  NULL },
+    { bitalloc_25_bits_a,  bitalloc_25_bits_b,  bitalloc_25_bits_c,  bitalloc_25_bits_d,
+      bitalloc_25_bits_e,  bitalloc_25_bits_f,  bitalloc_25_bits_g,  NULL },
+    { bitalloc_33_bits_a,  bitalloc_33_bits_b,  bitalloc_33_bits_c,  bitalloc_33_bits_d,
+      bitalloc_33_bits_e,  bitalloc_33_bits_f,  bitalloc_33_bits_g,  NULL },
+    { bitalloc_65_bits_a,  bitalloc_65_bits_b,  bitalloc_65_bits_c,  bitalloc_65_bits_d,
+      bitalloc_65_bits_e,  bitalloc_65_bits_f,  bitalloc_65_bits_g,  NULL },
+    { bitalloc_129_bits_a, bitalloc_129_bits_b, bitalloc_129_bits_c, bitalloc_129_bits_d,
+      bitalloc_129_bits_e, bitalloc_129_bits_f, bitalloc_129_bits_g, NULL }
+};
+
+static const uint16_t tnl_grp_0_codes[37] = {
+    0x0000, 0x0003, 0x0004, 0x0007, 0x0001, 0x0009, 0x000a, 0x000d,
+    0x000e, 0x0006, 0x0012, 0x0005, 0x0015, 0x0016, 0x0022, 0x0025,
+    0x0035, 0x0076, 0x0002, 0x0042, 0x00b6, 0x0036, 0x00c2, 0x0136,
+    0x0182, 0x01c2, 0x03c2, 0x0482, 0x0682, 0x0082, 0x0882, 0x0a82,
+    0x0282, 0x2282, 0x3282, 0x1282, 0x5282,
+};
+
+static const uint16_t tnl_grp_1_codes[34] = {
+    0x0001, 0x0003, 0x0006, 0x0000, 0x0002, 0x0004, 0x0005, 0x0007,
+    0x0008, 0x000f, 0x001a, 0x001c, 0x001d, 0x000a, 0x002c, 0x002d,
+    0x000d, 0x002a, 0x004c, 0x004d, 0x006a, 0x008c, 0x00cd, 0x00ea,
+    0x000c, 0x010c, 0x01ea, 0x020c, 0x030c, 0x07ea, 0x0bea, 0x03ea,
+    0x13ea, 0x33ea,
+};
+
+static const uint16_t tnl_grp_2_codes[31] = {
+    0x0001, 0x0003, 0x0006, 0x0007, 0x0004, 0x0008, 0x000c, 0x0010,
+    0x0012, 0x001a, 0x0022, 0x0000, 0x000a, 0x0020, 0x0040, 0x004a,
+    0x006a, 0x0002, 0x002a, 0x0042, 0x0082, 0x00aa, 0x00e0, 0x0060,
+    0x00c2, 0x01c2, 0x0160, 0x0360, 0x0f60, 0x0760, 0x1760,
+};
+
+static const uint16_t tnl_grp_3_codes[28] = {
+    0x0001, 0x0006, 0x0008, 0x0014, 0x001c, 0x0000, 0x0002, 0x0004,
+    0x000a, 0x000c, 0x0010, 0x0012, 0x001a, 0x0020, 0x002a, 0x002c,
+    0x0032, 0x003a, 0x0022, 0x0030, 0x0062, 0x0064, 0x0070, 0x0024,
+    0x00a4, 0x01a4, 0x03a4, 0x07a4,
+};
+
+static const uint16_t tnl_grp_4_codes[23] = {
+    0x0001, 0x0000, 0x000a, 0x0006, 0x0012, 0x001e, 0x0022, 0x002e,
+    0x0036, 0x003e, 0x0002, 0x0016, 0x0032, 0x004e, 0x0056, 0x000e,
+    0x0042, 0x0072, 0x00c2, 0x00f2, 0x008e, 0x018e, 0x038e,
+};
+
+static const uint16_t tnl_scf_codes[20] = {
+    0x0000, 0x0001, 0x0002, 0x0005, 0x0006, 0x0007, 0x000b, 0x000c,
+    0x0013, 0x0014, 0x0003, 0x0004, 0x0023, 0x0064, 0x00a4, 0x0024,
+    0x0124, 0x0324, 0x0724, 0x0f24,
+};
+
+static const uint16_t damp_codes[7] = {
+    0x0001, 0x0000, 0x0002, 0x0006, 0x000e, 0x001e, 0x003e,
+};
+
+static const uint16_t dph_codes[9] = {
+    0x0000, 0x0002, 0x0003, 0x0001, 0x0009, 0x000d, 0x0005, 0x0015,
+    0x0035,
+};
+
+static const uint16_t fst_rsd_amp_codes[24] = {
+    0x0003, 0x0005, 0x0006, 0x0007, 0x0000, 0x0001, 0x0002, 0x0008,
+    0x0009, 0x000a, 0x0014, 0x0004, 0x001a, 0x001c, 0x0024, 0x002c,
+    0x003a, 0x000c, 0x003c, 0x004c, 0x00fc, 0x007c, 0x017c, 0x037c,
+};
+
+static const uint16_t rsd_apprx_codes[6] = {
+    0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f,
+};
+
+static const uint16_t rsd_amp_codes[33] = {
+    0x0001, 0x0000, 0x0002, 0x0003, 0x0004, 0x000e, 0x000f, 0x0016,
+    0x0007, 0x0027, 0x0037, 0x0026, 0x0066, 0x0006, 0x0017, 0x0046,
+    0x0097, 0x00d7, 0x0086, 0x00c6, 0x01c6, 0x0157, 0x0186, 0x0257,
+    0x0357, 0x0057, 0x0786, 0x0386, 0x0b86, 0x0457, 0x0c57, 0x1457,
+    0x1c57,
+};
+
+static const uint16_t avg_g3_codes[18] = {
+    0x0001, 0x0002, 0x0003, 0x0000, 0x000c, 0x0014, 0x0018, 0x0004,
+    0x0008, 0x0028, 0x0068, 0x0024, 0x00a4, 0x00e4, 0x0164, 0x0064,
+    0x0264, 0x0664,
+};
+
+static const uint16_t st_grid_codes[22] = {
+    0x0001, 0x0002, 0x0000, 0x0004, 0x0008, 0x001c, 0x004c, 0x006c,
+    0x000c, 0x002c, 0x008c, 0x00ac, 0x012c, 0x018c, 0x01ac, 0x038c,
+    0x03ac, 0x032c, 0x072c, 0x0f2c, 0x172c, 0x1f2c,
+};
+
+static const uint16_t grid_2_codes[20] = {
+    0x0000, 0x0002, 0x0003, 0x0001, 0x0005, 0x000d, 0x003d, 0x005d,
+    0x009d, 0x011d, 0x001d, 0x061d, 0x041d, 0x0c1d, 0x0a1d, 0x121d,
+    0x021d, 0x1a1d, 0x221d, 0x3a1d,
+};
+
+static const uint16_t grid_3_codes[13] = {
+    0x0001, 0x0002, 0x0000, 0x0004, 0x000c, 0x001c, 0x007c, 0x003c,
+    0x01bc, 0x00bc, 0x06bc, 0x02bc, 0x0abc,
+};
+
+static const uint16_t rsd_codes[9] = {
+    0x0001, 0x0003, 0x0000, 0x0002, 0x0006, 0x0004, 0x000c, 0x001c,
+    0x003c,
+};
+
+static const uint8_t tnl_grp_0_bitvals[74] = {
+     3,  5,  3,  9,  3,  4,  3,  6,  4, 10,  4, 13,  4,  7,  4, 11,
+     4,  8,  5, 12,  5, 14,  6, 15,  6, 18,  6,  1,  6, 17,  6, 16,
+     6, 21,  7, 20,  8, 19,  8, 22,  8, 25,  9, 26,  9, 23,  9,  3,
+     9, 24, 10, 29, 10, 27, 11, 28, 11, 30, 12, 33, 12, 31, 12, 32,
+    14, 34, 14, 37, 14, 36, 15, 35, 15,  0,
+};
+
+static const uint8_t tnl_grp_1_bitvals[68] = {
+     3,  9,  3,  6,  3,  5,  4,  4,  4,  8,  4, 10,  4,  1,  4, 11,
+     4,  7,  4, 13,  5, 12,  5, 14,  5, 17,  6, 16,  6, 15,  6, 18,
+     7, 20,  7, 19,  7, 21,  8, 25,  8, 23,  8, 22,  8, 24,  9, 26,
+    10,  3, 10, 29, 10, 30, 10, 27, 10, 28, 11, 31, 12, 32, 13, 33,
+    14, 34, 14,  0,
+};
+
+static const uint8_t tnl_grp_2_bitvals[62] = {
+     2,  1,  3,  6,  3,  5,  3,  7,  4,  9,  4,  8,  4,  4,  5, 10,
+     5, 11,  5, 13,  6, 12,  7, 14,  7, 16,  7, 15,  7, 17,  7, 18,
+     7, 19,  8, 22,  8, 20,  8, 21,  8,  3,  8, 24,  8, 25,  9, 23,
+     9, 26,  9, 27, 10, 28, 11, 29, 12, 31, 13, 30, 13,  0,
+};
+
+static const uint8_t tnl_grp_3_bitvals[56] = {
+     1,  1,  3,  6,  4,  5,  5,  9,  5,  4,  6,  8,  6, 14,  6, 10,
+     6, 21,  6, 13,  6,  7,  6,  3,  6, 16,  6,  2,  6, 18,  6, 17,
+     6, 11,  6, 15,  7, 19,  7, 23,  7, 24,  7, 22,  7, 12,  8, 20,
+     9, 25, 10, 26, 11, 27, 11,  0,
+};
+
+static const uint8_t tnl_grp_4_bitvals[46] = {
+     1,  1,  2,  2,  4,  4,  5,  5,  6,  6,  6,  8,  6,  3,  6, 19,
+     6, 20,  6,  9,  7,  7,  7, 11,  7, 13,  7, 17,  7, 10,  8, 12,
+     8, 15,  8, 14,  8, 21,  8, 18,  9, 16, 10, 22, 10,  0,
+};
+
+static const uint8_t tnl_scf_bitvals[40] = {
+     3,  3,  3,  1,  3,  2,  3,  5,  3,  4,  3,  6,  4,  8,  4,  7,
+     5, 10,  5,  9,  6, 12,  6, 11,  6, 13,  7, 14,  8, 15,  9, 16,
+    10, 17, 11, 18, 12, 19, 12,  0,
+};
+
+static const uint8_t damp_bitvals[14] = {
+     1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  6,  0,
+};
+
+static const uint8_t dph_bitvals[18] = {
+     2,  2,  2,  1,  2,  8,  4,  3,  4,  7,  4,  4,  5,  6,  6,  5,
+     6,  0,
+};
+
+static const uint8_t fst_rsd_amp_bitvals[48] = {
+     3, 13,  3, 15,  3, 16,  3, 14,  4, 12,  4, 10,  4, 11,  4, 17,
+     4, 18,  5, 19,  5,  9,  6,  1,  6,  7,  6,  6,  6,  8,  6,  5,
+     6,  4,  7, 20,  7,  2,  7,  3,  8, 21,  9, 22, 10, 23, 10,  0,
+};
+
+static const uint8_t rsd_apprx_bitvals[12] = {
+     1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  5,  0,
+};
+
+static const uint8_t rsd_amp_bitvals[66] = {
+     2,  3,  3,  2,  3,  5,  3,  4,  3,  1,  4,  7,  4,  6,  5,  9,
+     6,  8,  6, 11,  6, 10,  7, 12,  7, 13,  8, 14,  8, 18,  8, 16,
+     8, 15,  8, 22,  9, 20,  9, 24,  9, 17, 10, 28, 10, 26, 10, 21,
+    10, 23, 11, 30, 11, 19, 12, 25, 12, 32, 13, 36, 13, 29, 13, 34,
+    13,  0,
+};
+
+static const uint8_t avg_g3_bitvals[36] = {
+     2, 15,  2, 16,  2, 17,  4, 14,  4, 18,  5, 12,  5, 13,  6, 10,
+     6, 11,  7, 19,  7,  9,  8, 20,  8,  8,  8,  7,  9, 21, 10,  6,
+    11, 23, 11,  0,
+};
+
+static const uint8_t st_grid_bitvals[44] = {
+     1,  6,  2,  1,  4,  4,  4,  8,  4,  3,  5, 10,  7, 12,  7,  5,
+     8, 14,  9, 16,  9,  7,  9, 18, 10, 11, 10,  9, 10, 20, 10, 22,
+    10,  2, 11, 13, 13, 17, 13, 24, 13, 15, 13,  0,
+};
+
+static const uint8_t grid_2_bitvals[40] = {
+     2,  3,  2,  2,  2,  1,  3,  4,  4,  5,  5,  6,  6,  7,  7,  8,
+     8,  9,  9, 10, 11, 11, 11, 12, 12, 13, 12, 17, 13, 15, 13, 18,
+    14, 19, 14, 16, 14, 14, 14,  0,
+};
+
+static const uint8_t grid_3_bitvals[26] = {
+     1, 17,  2, 16,  3, 18,  4, 15,  5, 19,  6, 14,  7, 20,  8, 13,
+     9, 21, 10, 12, 11, 22, 12, 11, 12,  0,
+};
+
+static const uint8_t rsd_bitvals[18] = {
+     2,  2,  2,  3,  3,  1,  3,  4,  3,  0,  4,  5,  5,  6,  6,  7,
+     6,  4,
+};
+
+static const uint16_t vlc_offs[80] = {
+        0,   512,   640,   768,  1282,  1794,  2436,  3080,  3770,  4454,  5364,
+     5372,  5380,  5388,  5392,  5396,  5412,  5420,  5428,  5460,  5492,  5508,
+     5572,  5604,  5668,  5796,  5860,  5892,  6412,  6668,  6796,  7308,  7564,
+     7820,  8076,  8620,  9132,  9388,  9910, 10166, 10680, 11196, 11726, 12240,
+    12752, 13298, 13810, 14326, 14840, 15500, 16022, 16540, 17158, 17678, 18264,
+    18796, 19352, 19926, 20468, 21472, 22398, 23014, 23622, 24200, 24748, 25276,
+    25792, 26306, 26826, 26890, 26954, 27468, 27500, 28038, 28554, 29086, 29630,
+    30150, 30214
+};
+
+DCAVLC  ff_dca_vlc_bit_allocation;
+DCAVLC  ff_dca_vlc_transition_mode;
+DCAVLC  ff_dca_vlc_scale_factor;
+DCAVLC  ff_dca_vlc_quant_index[DCA_CODE_BOOKS];
+
+VLC     ff_dca_vlc_tnl_grp[5];
+VLC     ff_dca_vlc_tnl_scf;
+VLC     ff_dca_vlc_damp;
+VLC     ff_dca_vlc_dph;
+VLC     ff_dca_vlc_fst_rsd_amp;
+VLC     ff_dca_vlc_rsd_apprx;
+VLC     ff_dca_vlc_rsd_amp;
+VLC     ff_dca_vlc_avg_g3;
+VLC     ff_dca_vlc_st_grid;
+VLC     ff_dca_vlc_grid_2;
+VLC     ff_dca_vlc_grid_3;
+VLC     ff_dca_vlc_rsd;
+
+av_cold void ff_dca_init_vlcs(void)
+{
+    static VLC_TYPE dca_table[30214][2];
+    static int vlcs_initialized = 0;
+    int i, j, k = 0;
+
+    if (vlcs_initialized)
+        return;
+
+#define DCA_INIT_VLC(vlc, a, b, c, d)                                       \
+    do {                                                                    \
+        vlc.table           = &dca_table[vlc_offs[k]];                      \
+        vlc.table_allocated = vlc_offs[k + 1] - vlc_offs[k];                \
+        init_vlc(&vlc, a, b, c, 1, 1, d, 2, 2, INIT_VLC_USE_NEW_STATIC);    \
+        k++;                                                                \
+    } while (0)
+
+    ff_dca_vlc_bit_allocation.offset    = 1;
+    ff_dca_vlc_bit_allocation.max_depth = 2;
+    for (i = 0; i < 5; i++)
+        DCA_INIT_VLC(ff_dca_vlc_bit_allocation.vlc[i], bitalloc_12_vlc_bits[i], 12,
+                     bitalloc_12_bits[i], bitalloc_12_codes[i]);
+
+    ff_dca_vlc_scale_factor.offset    = -64;
+    ff_dca_vlc_scale_factor.max_depth = 2;
+    for (i = 0; i < 5; i++)
+        DCA_INIT_VLC(ff_dca_vlc_scale_factor.vlc[i], SCALES_VLC_BITS, 129,
+                     scales_bits[i], scales_codes[i]);
+
+    ff_dca_vlc_transition_mode.offset    = 0;
+    ff_dca_vlc_transition_mode.max_depth = 1;
+    for (i = 0; i < 4; i++)
+        DCA_INIT_VLC(ff_dca_vlc_transition_mode.vlc[i], tmode_vlc_bits[i], 4,
+                     tmode_bits[i], tmode_codes[i]);
+
+    for (i = 0; i < DCA_CODE_BOOKS; i++) {
+        ff_dca_vlc_quant_index[i].offset    = bitalloc_offsets[i];
+        ff_dca_vlc_quant_index[i].max_depth = 1 + (i > 4);
+        for (j = 0; bitalloc_codes[i][j]; j++)
+            DCA_INIT_VLC(ff_dca_vlc_quant_index[i].vlc[j], bitalloc_maxbits[i][j],
+                         bitalloc_sizes[i], bitalloc_bits[i][j], bitalloc_codes[i][j]);
+    }
+
+#define LBR_INIT_VLC(vlc, tab, nb_bits)                                 \
+    do {                                                                \
+        vlc.table           = &dca_table[vlc_offs[k]];                  \
+        vlc.table_allocated = vlc_offs[k + 1] - vlc_offs[k];            \
+        ff_init_vlc_sparse(&vlc, nb_bits, FF_ARRAY_ELEMS(tab##_codes),  \
+                           &tab##_bitvals[0], 2, 1,                     \
+                           tab##_codes, 2, 2,                           \
+                           &tab##_bitvals[1], 2, 1,                     \
+                           INIT_VLC_LE | INIT_VLC_USE_NEW_STATIC);      \
+        k++;                                                            \
+    } while (0)
+
+    LBR_INIT_VLC(ff_dca_vlc_tnl_grp[0],  tnl_grp_0,   9);
+    LBR_INIT_VLC(ff_dca_vlc_tnl_grp[1],  tnl_grp_1,   9);
+    LBR_INIT_VLC(ff_dca_vlc_tnl_grp[2],  tnl_grp_2,   9);
+    LBR_INIT_VLC(ff_dca_vlc_tnl_grp[3],  tnl_grp_3,   9);
+    LBR_INIT_VLC(ff_dca_vlc_tnl_grp[4],  tnl_grp_4,   9);
+    LBR_INIT_VLC(ff_dca_vlc_tnl_scf,     tnl_scf,     9);
+    LBR_INIT_VLC(ff_dca_vlc_damp,        damp,        6);
+    LBR_INIT_VLC(ff_dca_vlc_dph,         dph,         6);
+    LBR_INIT_VLC(ff_dca_vlc_fst_rsd_amp, fst_rsd_amp, 9);
+    LBR_INIT_VLC(ff_dca_vlc_rsd_apprx,   rsd_apprx,   5);
+    LBR_INIT_VLC(ff_dca_vlc_rsd_amp,     rsd_amp,     9);
+    LBR_INIT_VLC(ff_dca_vlc_avg_g3,      avg_g3,      9);
+    LBR_INIT_VLC(ff_dca_vlc_st_grid,     st_grid,     9);
+    LBR_INIT_VLC(ff_dca_vlc_grid_2,      grid_2,      9);
+    LBR_INIT_VLC(ff_dca_vlc_grid_3,      grid_3,      9);
+    LBR_INIT_VLC(ff_dca_vlc_rsd,         rsd,         6);
+
+    vlcs_initialized = 1;
+}
diff --git a/libavcodec/dcahuff.h b/libavcodec/dcahuff.h
index 9388b63..b1d5735 100644
--- a/libavcodec/dcahuff.h
+++ b/libavcodec/dcahuff.h
@@ -23,1019 +23,37 @@
 #ifndef AVCODEC_DCAHUFF_H
 #define AVCODEC_DCAHUFF_H
 
-#include <stdint.h>
-#include <stdlib.h>
-
-#define TMODE_COUNT 4
-static const uint8_t tmode_vlc_bits[TMODE_COUNT] = { 3, 3, 3, 2 };
-static const uint16_t tmode_codes[TMODE_COUNT][4] = {
-    { 0x0000, 0x0002, 0x0006, 0x0007 },
-    { 0x0002, 0x0006, 0x0007, 0x0000 },
-    { 0x0006, 0x0007, 0x0000, 0x0002 },
-    { 0x0000, 0x0001, 0x0002, 0x0003 }
-};
-
-static const uint8_t tmode_bits[TMODE_COUNT][4] = {
-    { 1, 2, 3, 3 },
-    { 2, 3, 3, 1 },
-    { 3, 3, 1, 2 },
-    { 2, 2, 2, 2 }
-};
-
-#define BITALLOC_12_COUNT    5
-#define BITALLOC_12_VLC_BITS 9
-static const uint8_t bitalloc_12_vlc_bits[BITALLOC_12_COUNT] = {
-    9, 7, 7, 9, 9
-};
-
-static const uint16_t bitalloc_12_codes[BITALLOC_12_COUNT][12] = {
-    { 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E, 0x00FF, 0x00FE,
-      0x01FB, 0x01FA, 0x01F9, 0x01F8, },
-    { 0x0001, 0x0000, 0x0002, 0x000F, 0x000C, 0x001D, 0x0039, 0x0038,
-      0x0037, 0x0036, 0x0035, 0x0034, },
-    { 0x0000, 0x0007, 0x0005, 0x0004, 0x0002, 0x000D, 0x000C, 0x0006,
-      0x000F, 0x001D, 0x0039, 0x0038, },
-    { 0x0003, 0x0002, 0x0000, 0x0002, 0x0006, 0x000E, 0x001E, 0x003E,
-      0x007E, 0x00FE, 0x01FF, 0x01FE, },
-    { 0x0001, 0x0000, 0x0002, 0x0006, 0x000E, 0x003F, 0x003D, 0x007C,
-      0x0079, 0x0078, 0x00FB, 0x00FA, }
-};
-
-static const uint8_t bitalloc_12_bits[BITALLOC_12_COUNT][12] = {
-    { 1, 2, 3, 4, 5, 6, 8, 8, 9, 9,  9,  9 },
-    { 1, 2, 3, 5, 5, 6, 7, 7, 7, 7,  7,  7 },
-    { 2, 3, 3, 3, 3, 4, 4, 4, 5, 6,  7,  7 },
-    { 2, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10 },
-    { 1, 2, 3, 4, 5, 7, 7, 8, 8, 8,  9,  9 }
-};
-
-#define SCALES_COUNT    5
-#define SCALES_VLC_BITS 9
-static const uint16_t scales_codes[SCALES_COUNT][129] = {
-    { 0x3AB0, 0x3AB2, 0x3AB4, 0x3AB6, 0x3AB8, 0x3ABA, 0x3ABC, 0x3ABE,
-      0x3AC0, 0x3AC2, 0x3AC4, 0x3AC6, 0x3AC8, 0x3ACA, 0x3ACC, 0x3ACE,
-      0x3AD0, 0x3AD2, 0x3AD4, 0x3AD6, 0x3AD8, 0x3ADA, 0x3ADC, 0x3ADE,
-      0x3AE0, 0x3AE2, 0x3AE4, 0x3AE6, 0x3AE8, 0x3AEA, 0x3AEC, 0x3AEE,
-      0x3AF0, 0x3AF2, 0x3AF4, 0x3AF6, 0x3AF8, 0x3AFA, 0x3AFC, 0x3AFE,
-      0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E,
-      0x0558, 0x055E, 0x02AD, 0x0154, 0x0754, 0x03A8, 0x0056, 0x0028,
-      0x00E8, 0x004A, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005,
-      0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x004B,
-      0x00E9, 0x0029, 0x0057, 0x03A9, 0x0755, 0x0155, 0x02AE, 0x055F,
-      0x0559, 0x054F, 0x054D, 0x054B, 0x0549, 0x0547, 0x0545, 0x0543,
-      0x0541, 0x3AFF, 0x3AFD, 0x3AFB, 0x3AF9, 0x3AF7, 0x3AF5, 0x3AF3,
-      0x3AF1, 0x3AEF, 0x3AED, 0x3AEB, 0x3AE9, 0x3AE7, 0x3AE5, 0x3AE3,
-      0x3AE1, 0x3ADF, 0x3ADD, 0x3ADB, 0x3AD9, 0x3AD7, 0x3AD5, 0x3AD3,
-      0x3AD1, 0x3ACF, 0x3ACD, 0x3ACB, 0x3AC9, 0x3AC7, 0x3AC5, 0x3AC3,
-      0x3AC1, 0x3ABF, 0x3ABD, 0x3ABB, 0x3AB9, 0x3AB7, 0x3AB5, 0x3AB3,
-      0x3AB1, },
-    { 0x0F60, 0x0F62, 0x0F64, 0x0F66, 0x0F68, 0x0F6A, 0x0F6C, 0x0F6E,
-      0x0F70, 0x0F72, 0x0F74, 0x0F76, 0x0F78, 0x0F7A, 0x0F7C, 0x0F7E,
-      0x0F80, 0x0F82, 0x0F84, 0x0F86, 0x0F88, 0x0F8A, 0x0F8C, 0x0F8E,
-      0x0F90, 0x0F92, 0x0F94, 0x0F96, 0x0F98, 0x0F9A, 0x0F9C, 0x0F9E,
-      0x0FA0, 0x0FA2, 0x0FA4, 0x0FA6, 0x0FA8, 0x0FAA, 0x0FAC, 0x0FAE,
-      0x0FB0, 0x0FB2, 0x0FB4, 0x0FB6, 0x0FB8, 0x0FBA, 0x0FBC, 0x0FBE,
-      0x07A0, 0x07A2, 0x03D2, 0x01EA, 0x00FC, 0x007F, 0x001C, 0x000C,
-      0x0004, 0x0034, 0x0010, 0x001B, 0x0009, 0x000B, 0x000E, 0x0001,
-      0x0003, 0x0002, 0x000F, 0x000C, 0x000A, 0x0000, 0x0011, 0x0035,
-      0x0005, 0x000D, 0x001D, 0x003C, 0x00FD, 0x01EB, 0x03D3, 0x07A3,
-      0x07A1, 0x0FBF, 0x0FBD, 0x0FBB, 0x0FB9, 0x0FB7, 0x0FB5, 0x0FB3,
-      0x0FB1, 0x0FAF, 0x0FAD, 0x0FAB, 0x0FA9, 0x0FA7, 0x0FA5, 0x0FA3,
-      0x0FA1, 0x0F9F, 0x0F9D, 0x0F9B, 0x0F99, 0x0F97, 0x0F95, 0x0F93,
-      0x0F91, 0x0F8F, 0x0F8D, 0x0F8B, 0x0F89, 0x0F87, 0x0F85, 0x0F83,
-      0x0F81, 0x0F7F, 0x0F7D, 0x0F7B, 0x0F79, 0x0F77, 0x0F75, 0x0F73,
-      0x0F71, 0x0F6F, 0x0F6D, 0x0F6B, 0x0F69, 0x0F67, 0x0F65, 0x0F63,
-      0x0F61, },
-    { 0x51D0, 0x51D2, 0x51D4, 0x51D6, 0x51D8, 0x51DA, 0x51DC, 0x51DE,
-      0x51E0, 0x51E2, 0x51E4, 0x51E6, 0x51E8, 0x51EA, 0x51EC, 0x51EE,
-      0x51F0, 0x51F2, 0x51F4, 0x51F6, 0x51F8, 0x51FA, 0x51FC, 0x51FE,
-      0x70C0, 0x70C2, 0x70C4, 0x70C6, 0x70C8, 0x70CA, 0x70CC, 0x70CE,
-      0x70EC, 0x10EA, 0x3868, 0x3877, 0x0876, 0x1C35, 0x0434, 0x0A34,
-      0x0E1B, 0x021B, 0x051B, 0x070F, 0x010F, 0x0380, 0x0080, 0x0140,
-      0x01C1, 0x0041, 0x00A1, 0x00E2, 0x0022, 0x0052, 0x0072, 0x0012,
-      0x002A, 0x003A, 0x000A, 0x0016, 0x001E, 0x0006, 0x000C, 0x0000,
-      0x0004, 0x0001, 0x000D, 0x0007, 0x001F, 0x0017, 0x000B, 0x003B,
-      0x002B, 0x0013, 0x0073, 0x0053, 0x0023, 0x00E3, 0x00A2, 0x0042,
-      0x01C2, 0x0141, 0x0081, 0x0381, 0x028C, 0x010C, 0x051C, 0x021C,
-      0x0E1C, 0x0A35, 0x0435, 0x1C3A, 0x0877, 0x0874, 0x3869, 0x10EB,
-      0x70ED, 0x70CF, 0x70CD, 0x70CB, 0x70C9, 0x70C7, 0x70C5, 0x70C3,
-      0x70C1, 0x51FF, 0x51FD, 0x51FB, 0x51F9, 0x51F7, 0x51F5, 0x51F3,
-      0x51F1, 0x51EF, 0x51ED, 0x51EB, 0x51E9, 0x51E7, 0x51E5, 0x51E3,
-      0x51E1, 0x51DF, 0x51DD, 0x51DB, 0x51D9, 0x51D7, 0x51D5, 0x51D3,
-      0x51D1, },
-    { 0x6F64, 0x6F66, 0x6F68, 0x6F6A, 0x6F6C, 0x6F6E, 0x6F70, 0x6F72,
-      0x6F74, 0x6F76, 0x6F78, 0x6F7A, 0x6F7C, 0x6F7E, 0x6F80, 0x6F82,
-      0x6F84, 0x6F86, 0x6F88, 0x6F8A, 0x6F8C, 0x6F8E, 0x6F90, 0x6F92,
-      0x6F94, 0x6F96, 0x6F98, 0x6F9A, 0x6F9C, 0x6F9E, 0x6FA0, 0x6FA2,
-      0x6FA4, 0x6FA6, 0x6FA8, 0x6FAA, 0x6FAC, 0x6FAE, 0x6FB0, 0x6FB2,
-      0x6FB4, 0x6FB6, 0x17B4, 0x37DC, 0x0BDB, 0x1BEF, 0x05EE, 0x0DF8,
-      0x02F8, 0x06FD, 0x017D, 0x037F, 0x00BF, 0x0040, 0x00C0, 0x0021,
-      0x0061, 0x0011, 0x0031, 0x0009, 0x0019, 0x0006, 0x000E, 0x0004,
-      0x0000, 0x0005, 0x000F, 0x0007, 0x001A, 0x000A, 0x0036, 0x0016,
-      0x006E, 0x002E, 0x00C1, 0x0041, 0x01BC, 0x00BC, 0x037A, 0x017A,
-      0x02F9, 0x0DF9, 0x05EF, 0x05EC, 0x1BD8, 0x37DD, 0x17B5, 0x6FB7,
-      0x6FB5, 0x6FB3, 0x6FB1, 0x6FAF, 0x6FAD, 0x6FAB, 0x6FA9, 0x6FA7,
-      0x6FA5, 0x6FA3, 0x6FA1, 0x6F9F, 0x6F9D, 0x6F9B, 0x6F99, 0x6F97,
-      0x6F95, 0x6F93, 0x6F91, 0x6F8F, 0x6F8D, 0x6F8B, 0x6F89, 0x6F87,
-      0x6F85, 0x6F83, 0x6F81, 0x6F7F, 0x6F7D, 0x6F7B, 0x6F79, 0x6F77,
-      0x6F75, 0x6F73, 0x6F71, 0x6F6F, 0x6F6D, 0x6F6B, 0x6F69, 0x6F67,
-      0x6F65, },
-    { 0xDF54, 0xDF56, 0xDFC8, 0xDFCA, 0xDFCC, 0xDFCE, 0xDFD0, 0xDFD2,
-      0xDFD4, 0xDFD6, 0xDFD8, 0xDFDA, 0xDFDC, 0xDFDE, 0xDFE0, 0xDFE2,
-      0x0FE8, 0x2FEA, 0x6FA8, 0x6FF6, 0x07F5, 0x07F7, 0x37D2, 0x37F9,
-      0x03F8, 0x0BF8, 0x0BFB, 0x1BEB, 0x01FA, 0x05FA, 0x09FA, 0x0DFA,
-      0x0DFF, 0x00FF, 0x02FF, 0x06FB, 0x007C, 0x017C, 0x027C, 0x027F,
-      0x003C, 0x00BC, 0x013C, 0x01BC, 0x001C, 0x005C, 0x009C, 0x00DC,
-      0x000C, 0x002C, 0x004C, 0x006C, 0x0004, 0x0014, 0x0024, 0x0034,
-      0x0000, 0x0008, 0x0010, 0x0018, 0x001E, 0x0002, 0x0006, 0x000A,
-      0x000E, 0x000B, 0x0007, 0x0003, 0x001F, 0x0019, 0x0011, 0x0009,
-      0x0001, 0x0035, 0x0025, 0x0015, 0x0005, 0x006D, 0x004D, 0x002D,
-      0x000D, 0x00DD, 0x009D, 0x005D, 0x001D, 0x01BD, 0x013D, 0x00BD,
-      0x003D, 0x037C, 0x027D, 0x017D, 0x007D, 0x06FC, 0x04FC, 0x02FC,
-      0x00FC, 0x0DFB, 0x09FB, 0x05FB, 0x01FB, 0x1BF8, 0x1BE8, 0x0BF9,
-      0x03F9, 0x37FA, 0x37D3, 0x17F4, 0x07F6, 0x6FF7, 0x6FA9, 0x2FEB,
-      0x0FE9, 0xDFE3, 0xDFE1, 0xDFDF, 0xDFDD, 0xDFDB, 0xDFD9, 0xDFD7,
-      0xDFD5, 0xDFD3, 0xDFD1, 0xDFCF, 0xDFCD, 0xDFCB, 0xDFC9, 0xDF57,
-      0xDF55, }
-};
-
-static const uint8_t scales_bits[SCALES_COUNT][129] = {
-    { 14, 14, 14, 14, 14, 14, 14, 14,
-      14, 14, 14, 14, 14, 14, 14, 14,
-      14, 14, 14, 14, 14, 14, 14, 14,
-      14, 14, 14, 14, 14, 14, 14, 14,
-      14, 14, 14, 14, 14, 14, 14, 14,
-      13, 13, 13, 13, 13, 13, 13, 13,
-      13, 13, 12, 11, 11, 10,  9,  8,
-       8,  7,  6,  6,  5,  4,  4,  3,
-       2,  3,  3,  4,  5,  5,  6,  7,
-       8,  8,  9, 10, 11, 11, 12, 13,
-      13, 13, 13, 13, 13, 13, 13, 13,
-      13, 14, 14, 14, 14, 14, 14, 14,
-      14, 14, 14, 14, 14, 14, 14, 14,
-      14, 14, 14, 14, 14, 14, 14, 14,
-      14, 14, 14, 14, 14, 14, 14, 14,
-      14, 14, 14, 14, 14, 14, 14, 14,
-      14, },
-    { 15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      14, 14, 13, 12, 11, 10,  8,  7,
-       6,  6,  5,  5,  4,  4,  4,  3,
-       3,  3,  4,  4,  4,  4,  5,  6,
-       6,  7,  8,  9, 11, 12, 13, 14,
-      14, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, },
-    { 15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 14, 14, 14, 13, 13, 12, 12,
-      12, 11, 11, 11, 10, 10,  9,  9,
-       9,  8,  8,  8,  7,  7,  7,  6,
-       6,  6,  5,  5,  5,  4,  4,  3,
-       3,  3,  4,  4,  5,  5,  5,  6,
-       6,  6,  7,  7,  7,  8,  8,  8,
-       9,  9,  9, 10, 10, 10, 11, 11,
-      12, 12, 12, 13, 13, 13, 14, 14,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, },
-    { 15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 14, 14, 13, 13, 12, 12,
-      11, 11, 10, 10,  9,  8,  8,  7,
-       7,  6,  6,  5,  5,  4,  4,  3,
-       2,  3,  4,  4,  5,  5,  6,  6,
-       7,  7,  8,  8,  9,  9, 10, 10,
-      11, 12, 12, 12, 13, 14, 14, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, 15, 15, 15, 15, 15, 15, 15,
-      15, },
-    { 16, 16, 16, 16, 16, 16, 16, 16,
-      16, 16, 16, 16, 16, 16, 16, 16,
-      15, 15, 15, 15, 14, 14, 14, 14,
-      13, 13, 13, 13, 12, 12, 12, 12,
-      12, 11, 11, 11, 10, 10, 10, 10,
-       9,  9,  9,  9,  8,  8,  8,  8,
-       7,  7,  7,  7,  6,  6,  6,  6,
-       5,  5,  5,  5,  5,  4,  4,  4,
-       4,  4,  4,  4,  5,  5,  5,  5,
-       5,  6,  6,  6,  6,  7,  7,  7,
-       7,  8,  8,  8,  8,  9,  9,  9,
-       9, 10, 10, 10, 10, 11, 11, 11,
-      11, 12, 12, 12, 12, 13, 13, 13,
-      13, 14, 14, 14, 14, 15, 15, 15,
-      15, 16, 16, 16, 16, 16, 16, 16,
-      16, 16, 16, 16, 16, 16, 16, 16,
-      16,
-    }
-};
-
-static const uint16_t bitalloc_3_codes[3] = {
-    0x0003, 0x0000, 0x0002,
-};
-
-static const uint8_t bitalloc_3_bits[3] = {
-    2,  1,  2,
-};
-
-static const uint16_t bitalloc_5_codes_a[5] = {
-    0x000F, 0x0006, 0x0000, 0x0002, 0x000E,
-};
-
-static const uint16_t bitalloc_5_codes_b[5] = {
-    0x0007, 0x0001, 0x0002, 0x0000, 0x0006,
-};
-
-static const uint16_t bitalloc_5_codes_c[5] = {
-    0x0007, 0x0005, 0x0000, 0x0004, 0x0006,
-};
-
-static const uint8_t bitalloc_5_bits_a[5] = {
-    4,  3,  1,  2,  4,
-};
-
-static const uint8_t bitalloc_5_bits_b[5] = {
-    3,  2,  2,  2,  3,
-};
-
-static const uint8_t bitalloc_5_bits_c[5] = {
-    3,  3,  1,  3,  3,
-};
-
-static const uint16_t bitalloc_7_codes_a[7] = {
-    0x001E, 0x000E, 0x0005, 0x0000, 0x0006, 0x0004, 0x001F,
-};
-
-static const uint16_t bitalloc_7_codes_b[7] = {
-    0x0014, 0x000B, 0x0000, 0x0003, 0x0001, 0x0004, 0x0015,
-};
-
-static const uint16_t bitalloc_7_codes_c[7] = {
-    0x0000, 0x0002, 0x0001, 0x0003, 0x0002, 0x0003, 0x0001,
-};
-
-static const uint8_t bitalloc_7_bits_a[7] = {
-    5,  4,  3,  1,  3,  3,  5,
-};
-
-static const uint8_t bitalloc_7_bits_b[7] = {
-    5,  4,  2,  2,  2,  3,  5,
-};
-
-static const uint8_t bitalloc_7_bits_c[7] = {
-    4,  4,  2,  2,  2,  4,  4,
-};
-
-static const uint16_t bitalloc_9_codes_a[9] = {
-    0x0030, 0x0019, 0x0009, 0x0005, 0x0000, 0x0007, 0x000D, 0x0008,
-    0x0031,
-};
-
-static const uint16_t bitalloc_9_codes_b[9] = {
-    0x0018, 0x001A, 0x0002, 0x0007, 0x0002, 0x0000, 0x0003, 0x001B,
-    0x0019,
-};
-
-static const uint16_t bitalloc_9_codes_c[9] = {
-    0x001C, 0x000F, 0x0002, 0x0007, 0x0002, 0x0000, 0x0006, 0x0006,
-    0x001D,
-};
-
-static const uint8_t bitalloc_9_bits_a[9] = {
-    6,  5,  4,  3,  1,  3,  4,  4,  6,
-};
-
-static const uint8_t bitalloc_9_bits_b[9] = {
-    5,  5,  3,  3,  2,  2,  3,  5,  5,
-};
-
-static const uint8_t bitalloc_9_bits_c[9] = {
-    6,  5,  3,  3,  2,  2,  3,  4,  6,
-};
-
-static const uint16_t bitalloc_13_codes_a[13] = {
-    0x0070, 0x002E, 0x0039, 0x001D, 0x000C, 0x000F, 0x0000, 0x0004,
-    0x000D, 0x000A, 0x0016, 0x002F, 0x0071,
-};
-
-static const uint16_t bitalloc_13_codes_b[13] = {
-    0x0038, 0x0010, 0x001D, 0x0007, 0x000F, 0x0005, 0x0000, 0x0006,
-    0x0002, 0x0009, 0x0006, 0x0011, 0x0039,
-};
-
-static const uint16_t bitalloc_13_codes_c[13] = {
-    0x0004, 0x001A, 0x0003, 0x000E, 0x0000, 0x0003, 0x0005, 0x0004,
-    0x0002, 0x000F, 0x000C, 0x001B, 0x0005,
-};
-
-static const uint8_t bitalloc_13_bits_a[13] = {
-     7,  6,  6,  5,  4,  4,  1,  3,  4,  4,  5,  6,  7,
-};
-
-static const uint8_t bitalloc_13_bits_b[13] = {
-     6,  5,  5,  4,  4,  3,  2,  3,  3,  4,  4,  5,  6,
-};
-
-static const uint8_t bitalloc_13_bits_c[13] = {
-     5,  5,  4,  4,  3,  3,  3,  3,  3,  4,  4,  5,  5,
-};
-
-static const uint16_t bitalloc_17_codes_a[17] = {
-    0x0154, 0x00AB, 0x002B, 0x000B, 0x0003, 0x000A, 0x0001, 0x0006,
-    0x0001, 0x0007, 0x0004, 0x000B, 0x0000, 0x0004, 0x0014, 0x0054,
-    0x0155,
-};
-
-static const uint16_t bitalloc_17_codes_b[17] = {
-    0x007C, 0x003F, 0x0019, 0x000D, 0x001C, 0x0008, 0x000F, 0x0005,
-    0x0000, 0x0006, 0x0002, 0x0009, 0x001D, 0x000E, 0x001E, 0x0018,
-    0x007D,
-};
-
-static const uint16_t bitalloc_17_codes_c[17] = {
-    0x002C, 0x0017, 0x0005, 0x001C, 0x0003, 0x000A, 0x000F, 0x0003,
-    0x0006, 0x0004, 0x0000, 0x000B, 0x0004, 0x001D, 0x000A, 0x0004,
-    0x002D,
-};
-
-static const uint16_t bitalloc_17_codes_d[17] = {
-    0x0100, 0x0102, 0x0082, 0x0042, 0x0022, 0x0012, 0x000A, 0x0006,
-    0x0000, 0x0007, 0x000B, 0x0013, 0x0023, 0x0043, 0x0083, 0x0103,
-    0x0101,
-};
-
-static const uint16_t bitalloc_17_codes_e[17] = {
-    0x00E8, 0x00F6, 0x0075, 0x0034, 0x003B, 0x001B, 0x001F, 0x0004,
-    0x0000, 0x0005, 0x000C, 0x001C, 0x003C, 0x0035, 0x007A, 0x00F7,
-    0x00E9,
-};
-
-static const uint16_t bitalloc_17_codes_f[17] = {
-    0x0004, 0x0003, 0x001E, 0x0001, 0x0001, 0x000E, 0x0001, 0x0004,
-    0x0006, 0x0005, 0x0002, 0x000F, 0x0006, 0x000E, 0x001F, 0x0000,
-    0x0005,
-};
-
-static const uint16_t bitalloc_17_codes_g[17] = {
-    0x0060, 0x007E, 0x0031, 0x0019, 0x000D, 0x0004, 0x0000, 0x0006,
-    0x0002, 0x0007, 0x0001, 0x0005, 0x000E, 0x001E, 0x003E, 0x007F,
-    0x0061,
-};
-
-static const uint8_t bitalloc_17_bits_a[17] = {
-    12, 11,  9,  7,  5,  4,  3,  3,  2,  3,  3,  4,  4,  6,  8, 10,
-    12,
-};
-
-static const uint8_t bitalloc_17_bits_b[17] = {
-    8,  7,  6,  5,  5,  4,  4,  3,  2,  3,  3,  4,  5,  5,  6,  6,
-    8,
-};
-
-static const uint8_t bitalloc_17_bits_c[17] = {
-    7,  6,  5,  5,  4,  4,  4,  3,  3,  3,  3,  4,  4,  5,  5,  5,
-    7,
-};
-
-static const uint8_t bitalloc_17_bits_d[17] = {
-    9,  9,  8,  7,  6,  5,  4,  3,  1,  3,  4,  5,  6,  7,  8,  9,
-    9,
-};
-
-static const uint8_t bitalloc_17_bits_e[17] = {
-    8,  8,  7,  6,  6,  5,  5,  3,  1,  3,  4,  5,  6,  6,  7,  8,
-    8,
-};
-
-static const uint8_t bitalloc_17_bits_f[17] = {
-    8,  7,  6,  5,  4,  4,  3,  3,  3,  3,  3,  4,  4,  5,  6,  6,
-    8,
-};
-
-static const uint8_t bitalloc_17_bits_g[17] = {
-    8,  8,  7,  6,  5,  4,  3,  3,  2,  3,  3,  4,  5,  6,  7,  8,
-    8,
-};
-
-static const uint16_t bitalloc_25_codes_a[25] = {
-    0x2854, 0x142B, 0x050B, 0x0143, 0x00A2, 0x0052, 0x002E, 0x0015,
-    0x0004, 0x000E, 0x0000, 0x0003, 0x0006, 0x0004, 0x0001, 0x000F,
-    0x0005, 0x0016, 0x002F, 0x0053, 0x00A3, 0x00A0, 0x0284, 0x0A14,
-    0x2855,
-};
-
-static const uint16_t bitalloc_25_codes_b[25] = {
-    0x001C, 0x000F, 0x0005, 0x0000, 0x0030, 0x0036, 0x000E, 0x0019,
-    0x0001, 0x0008, 0x000E, 0x0001, 0x0005, 0x0002, 0x000F, 0x0009,
-    0x0006, 0x001A, 0x000F, 0x0037, 0x0031, 0x0001, 0x0006, 0x0004,
-    0x001D,
-};
-
-static const uint16_t bitalloc_25_codes_c[25] = {
-    0x004C, 0x0027, 0x006D, 0x0028, 0x0037, 0x000E, 0x0015, 0x0000,
-    0x0005, 0x0008, 0x000B, 0x000E, 0x0001, 0x000F, 0x000C, 0x0009,
-    0x0006, 0x0001, 0x001A, 0x000F, 0x0008, 0x0029, 0x0012, 0x006C,
-    0x004D,
-};
-
-static const uint16_t bitalloc_25_codes_d[25] = {
-    0x0780, 0x0782, 0x03C2, 0x01E2, 0x00FE, 0x0079, 0x003D, 0x001C,
-    0x000C, 0x0004, 0x0000, 0x0006, 0x0002, 0x0007, 0x0001, 0x0005,
-    0x000D, 0x001D, 0x003E, 0x007E, 0x00FF, 0x01E3, 0x03C3, 0x0783,
-    0x0781,
-};
-
-static const uint16_t bitalloc_25_codes_e[25] = {
-    0x003C, 0x0092, 0x0018, 0x001F, 0x004E, 0x000D, 0x0025, 0x0004,
-    0x0010, 0x0000, 0x000A, 0x0002, 0x0003, 0x0003, 0x000B, 0x0001,
-    0x0011, 0x0005, 0x0026, 0x000E, 0x004F, 0x0048, 0x0019, 0x0093,
-    0x003D,
-};
-
-static const uint16_t bitalloc_25_codes_f[25] = {
-    0x0324, 0x0193, 0x00CE, 0x0065, 0x0024, 0x000C, 0x0013, 0x0004,
-    0x0007, 0x000A, 0x000D, 0x000F, 0x0001, 0x0000, 0x000E, 0x000B,
-    0x0008, 0x0005, 0x0018, 0x000D, 0x0025, 0x0066, 0x00CF, 0x00C8,
-    0x0325,
-};
-
-static const uint16_t bitalloc_25_codes_g[25] = {
-    0x03A8, 0x03AE, 0x01D5, 0x0094, 0x0014, 0x004B, 0x000B, 0x003B,
-    0x0013, 0x0003, 0x000F, 0x0005, 0x0001, 0x0006, 0x0000, 0x0008,
-    0x001C, 0x0004, 0x0024, 0x0074, 0x0015, 0x0095, 0x01D6, 0x03AF,
-    0x03A9,
-};
-
-static const uint8_t bitalloc_25_bits_a[25] = {
-    14, 13, 11,  9,  8,  7,  6,  5,  4,  4,  3,  3,  3,  3,  3,  4,
-     4,  5,  6,  7,  8,  8, 10, 12, 14,
-};
-
-static const uint8_t bitalloc_25_bits_b[25] = {
-    9,  8,  7,  6,  6,  6,  5,  5,  4,  4,  4,  3,  3,  3,  4,  4,
-    4,  5,  5,  6,  6,  6,  7,  7,  9,
-};
-
-static const uint8_t bitalloc_25_bits_c[25] = {
-    8,  7,  7,  6,  6,  5,  5,  4,  4,  4,  4,  4,  3,  4,  4,  4,
-    4,  4,  5,  5,  5,  6,  6,  7,  8,
-};
-
-static const uint8_t bitalloc_25_bits_d[25] = {
-    12, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  3,  2,  3,  3,  4,
-     5,  6,  7,  8,  9, 10, 11, 12, 12,
-};
-
-static const uint8_t bitalloc_25_bits_e[25] = {
-    8,  8,  7,  7,  7,  6,  6,  5,  5,  4,  4,  3,  2,  3,  4,  4,
-    5,  5,  6,  6,  7,  7,  7,  8,  8,
-};
-
-static const uint8_t bitalloc_25_bits_f[25] = {
-    10,  9,  8,  7,  6,  5,  5,  4,  4,  4,  4,  4,  3,  3,  4,  4,
-     4,  4,  5,  5,  6,  7,  8,  8, 10,
-};
-
-static const uint8_t bitalloc_25_bits_g[25] = {
-    10, 10,  9,  8,  7,  7,  6,  6,  5,  4,  4,  3,  2,  3,  3,  4,
-     5,  5,  6,  7,  7,  8,  9, 10, 10,
-};
-
-static const uint16_t bitalloc_33_codes_a[33] = {
-    0x1580, 0x1582, 0x0AC2, 0x0562, 0x02B2, 0x015E, 0x00AD, 0x0054,
-    0x001C, 0x003C, 0x000F, 0x001F, 0x0008, 0x000B, 0x000D, 0x0000,
-    0x0002, 0x0001, 0x000E, 0x000C, 0x0009, 0x0006, 0x0014, 0x003D,
-    0x001D, 0x0055, 0x00AE, 0x015F, 0x02B3, 0x0563, 0x0AC3, 0x1583,
-    0x1581,
-};
-
-static const uint16_t bitalloc_33_codes_b[33] = {
-    0x030C, 0x0187, 0x006D, 0x0028, 0x0037, 0x0066, 0x0015, 0x0031,
-    0x0000, 0x000B, 0x0012, 0x001A, 0x0001, 0x0007, 0x000A, 0x000E,
-    0x0001, 0x000F, 0x000B, 0x0008, 0x0004, 0x001B, 0x0013, 0x000C,
-    0x0001, 0x0032, 0x001A, 0x0067, 0x0060, 0x0029, 0x00C2, 0x006C,
-    0x030D,
-};
-
-static const uint16_t bitalloc_33_codes_c[33] = {
-    0x00CC, 0x0067, 0x0005, 0x0070, 0x0003, 0x001A, 0x0039, 0x003F,
-    0x000A, 0x0012, 0x0018, 0x001D, 0x0001, 0x0003, 0x0007, 0x000A,
-    0x000D, 0x000B, 0x0008, 0x0004, 0x0002, 0x001E, 0x0019, 0x0013,
-    0x000B, 0x0000, 0x003E, 0x001B, 0x0018, 0x0071, 0x0032, 0x0004,
-    0x00CD,
-};
-
-static const uint16_t bitalloc_33_codes_d[33] = {
-    0x3AF8, 0x3AFA, 0x1D7E, 0x0EBC, 0x075C, 0x03AC, 0x01D4, 0x0094,
-    0x0014, 0x004B, 0x000B, 0x003B, 0x0013, 0x0003, 0x000F, 0x0005,
-    0x0001, 0x0006, 0x0000, 0x0008, 0x001C, 0x0004, 0x0024, 0x0074,
-    0x0015, 0x0095, 0x01D5, 0x03AD, 0x075D, 0x0EBD, 0x1D7F, 0x3AFB,
-    0x3AF9,
-};
-
-static const uint16_t bitalloc_33_codes_e[33] = {
-    0x01C8, 0x01E6, 0x0064, 0x00E2, 0x00E5, 0x0030, 0x0033, 0x0073,
-    0x007A, 0x001A, 0x003A, 0x0002, 0x001A, 0x001F, 0x0007, 0x0001,
-    0x0002, 0x0002, 0x000C, 0x0000, 0x001B, 0x0003, 0x003B, 0x001B,
-    0x007B, 0x0078, 0x0070, 0x0031, 0x00F2, 0x00E3, 0x0065, 0x01E7,
-    0x01C9,
-};
-
-static const uint16_t bitalloc_33_codes_f[33] = {
-    0x0724, 0x0393, 0x01CE, 0x00E5, 0x002C, 0x0008, 0x0017, 0x003E,
-    0x0005, 0x0014, 0x001D, 0x0000, 0x0003, 0x0006, 0x0008, 0x000B,
-    0x000D, 0x000C, 0x0009, 0x0007, 0x0004, 0x0001, 0x001E, 0x0015,
-    0x000A, 0x003F, 0x0038, 0x0009, 0x002D, 0x00E6, 0x01CF, 0x01C8,
-    0x0725,
-};
-
-static const uint16_t bitalloc_33_codes_g[33] = {
-    0x0284, 0x0042, 0x0140, 0x0143, 0x003E, 0x00BE, 0x0011, 0x0051,
-    0x0009, 0x0029, 0x0005, 0x0015, 0x0000, 0x0008, 0x000E, 0x0002,
-    0x0006, 0x0003, 0x000F, 0x0009, 0x0001, 0x0016, 0x0006, 0x002E,
-    0x000E, 0x005E, 0x001E, 0x00BF, 0x003F, 0x0020, 0x0141, 0x0043,
-    0x0285,
-};
-
-static const uint8_t bitalloc_33_bits_a[33] = {
-    13, 13, 12, 11, 10,  9,  8,  7,  6,  6,  5,  5,  4,  4,  4,  3,
-     3,  3,  4,  4,  4,  4,  5,  6,  6,  7,  8,  9, 10, 11, 12, 13,
-    13,
-};
-
-static const uint8_t bitalloc_33_bits_b[33] = {
-    10,  9,  8,  7,  7,  7,  6,  6,  5,  5,  5,  5,  4,  4,  4,  4,
-     3,  4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  7,  7,  7,  8,  8,
-    10,
-};
-
-static const uint8_t bitalloc_33_bits_c[33] = {
-    9,  8,  7,  7,  6,  6,  6,  6,  5,  5,  5,  5,  4,  4,  4,  4,
-    4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  6,  6,  6,  7,  7,  7,
-    9,
-};
-
-static const uint8_t bitalloc_33_bits_d[33] = {
-    14, 14, 13, 12, 11, 10,  9,  8,  7,  7,  6,  6,  5,  4,  4,  3,
-     2,  3,  3,  4,  5,  5,  6,  7,  7,  8,  9, 10, 11, 12, 13, 14,
-    14,
-};
-
-static const uint8_t bitalloc_33_bits_e[33] = {
-    9,  9,  8,  8,  8,  7,  7,  7,  7,  6,  6,  5,  5,  5,  4,  3,
-    2,  3,  4,  4,  5,  5,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,
-    9,
-};
-
-static const uint8_t bitalloc_33_bits_f[33] = {
-    11, 10,  9,  8,  7,  6,  6,  6,  5,  5,  5,  4,  4,  4,  4,  4,
-     4,  4,  4,  4,  4,  4,  5,  5,  5,  6,  6,  6,  7,  8,  9,  9,
-    11,
-};
-
-static const uint8_t bitalloc_33_bits_g[33] = {
-    10,  9,  9,  9,  8,  8,  7,  7,  6,  6,  5,  5,  4,  4,  4,  3,
-     3,  3,  4,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8,  8,  9,  9,
-    10,
-};
-
-static const uint16_t bitalloc_65_codes_a[65] = {
-    0x9E5C, 0x9E5E, 0x4F2C, 0x2794, 0x13C4, 0x1E44, 0x09E3, 0x0F23,
-    0x04F3, 0x0792, 0x027E, 0x03CE, 0x013D, 0x01E5, 0x009C, 0x00CC,
-    0x0040, 0x0058, 0x0067, 0x001E, 0x0021, 0x002D, 0x003D, 0x0007,
-    0x0011, 0x0014, 0x0017, 0x001A, 0x001C, 0x001F, 0x0001, 0x0004,
-    0x0006, 0x0005, 0x0002, 0x0000, 0x001D, 0x001B, 0x0018, 0x0015,
-    0x0012, 0x000E, 0x0006, 0x0032, 0x0026, 0x001F, 0x0078, 0x0059,
-    0x0041, 0x00CD, 0x009D, 0x01E6, 0x013E, 0x03CF, 0x027F, 0x0793,
-    0x0790, 0x04F0, 0x09E4, 0x1E45, 0x13C5, 0x2795, 0x4F2D, 0x9E5F,
-    0x9E5D,
-};
-
-static const uint16_t bitalloc_65_codes_b[65] = {
-    0x0A8C, 0x0547, 0x01B5, 0x0008, 0x00DB, 0x0152, 0x0005, 0x000B,
-    0x008E, 0x00AE, 0x00E4, 0x0003, 0x0037, 0x0039, 0x0055, 0x006C,
-    0x0073, 0x0003, 0x0015, 0x001D, 0x0028, 0x0030, 0x0037, 0x003E,
-    0x0006, 0x000B, 0x000F, 0x0012, 0x0016, 0x0019, 0x001D, 0x0001,
-    0x0004, 0x0002, 0x001E, 0x001A, 0x0017, 0x0013, 0x0010, 0x000C,
-    0x0007, 0x003F, 0x0038, 0x0031, 0x0029, 0x0022, 0x001A, 0x0014,
-    0x0000, 0x006D, 0x0056, 0x0046, 0x0038, 0x0004, 0x00E5, 0x00AF,
-    0x008F, 0x006C, 0x000A, 0x0153, 0x0150, 0x0009, 0x02A2, 0x01B4,
-    0x0A8D,
-};
-
-static const uint16_t bitalloc_65_codes_c[65] = {
-    0x045C, 0x022F, 0x03F5, 0x01BC, 0x01FB, 0x0059, 0x00D0, 0x00DF,
-    0x000A, 0x002D, 0x002F, 0x0052, 0x0069, 0x0078, 0x007F, 0x000A,
-    0x0010, 0x001C, 0x0023, 0x002A, 0x0035, 0x003A, 0x003D, 0x0000,
-    0x0003, 0x0006, 0x0009, 0x000C, 0x000F, 0x0012, 0x0016, 0x0018,
-    0x001C, 0x0019, 0x0017, 0x0013, 0x0010, 0x000D, 0x000A, 0x0007,
-    0x0004, 0x0001, 0x003E, 0x003B, 0x0036, 0x002B, 0x0028, 0x001D,
-    0x0011, 0x000B, 0x0004, 0x0079, 0x006E, 0x0053, 0x0044, 0x002E,
-    0x000B, 0x00FC, 0x00D1, 0x008A, 0x0058, 0x01BD, 0x0116, 0x03F4,
-    0x045D,
-};
-
-static const uint16_t bitalloc_65_codes_d[65] = {
-    0x70B0, 0x70B2, 0x70B4, 0x2852, 0x385B, 0x142E, 0x1C2E, 0x0A15,
-    0x0E14, 0x0214, 0x0704, 0x0104, 0x010B, 0x0383, 0x0083, 0x0143,
-    0x01C3, 0x0043, 0x00A2, 0x00E2, 0x0022, 0x0052, 0x0072, 0x0012,
-    0x002A, 0x003A, 0x000A, 0x0016, 0x001E, 0x0006, 0x000C, 0x0000,
-    0x0004, 0x0001, 0x000D, 0x0007, 0x001F, 0x0017, 0x000B, 0x003B,
-    0x002B, 0x0013, 0x0073, 0x0053, 0x0023, 0x00E3, 0x00A3, 0x00A0,
-    0x0040, 0x01C0, 0x0084, 0x0384, 0x0284, 0x0105, 0x0705, 0x0215,
-    0x0E15, 0x0A16, 0x1C2F, 0x142F, 0x1428, 0x2853, 0x70B5, 0x70B3,
-    0x70B1,
-};
-
-static const uint16_t bitalloc_65_codes_e[65] = {
-    0x032C, 0x0332, 0x0378, 0x037E, 0x008C, 0x014A, 0x0188, 0x0197,
-    0x019E, 0x01BD, 0x0044, 0x0047, 0x00AA, 0x00C5, 0x00CD, 0x00DC,
-    0x001C, 0x002C, 0x0053, 0x0063, 0x0068, 0x0008, 0x000F, 0x0017,
-    0x002B, 0x0035, 0x0005, 0x0009, 0x0016, 0x001C, 0x0006, 0x000F,
-    0x0004, 0x0000, 0x0007, 0x001D, 0x0017, 0x000A, 0x0006, 0x0036,
-    0x0030, 0x0028, 0x0010, 0x0009, 0x0069, 0x0064, 0x0054, 0x002D,
-    0x001D, 0x00DD, 0x00CE, 0x00CA, 0x00AB, 0x00A4, 0x0045, 0x01BE,
-    0x019F, 0x0198, 0x0189, 0x014B, 0x008D, 0x037F, 0x0379, 0x0333,
-    0x032D,
-};
-
-static const uint16_t bitalloc_65_codes_f[65] = {
-    0x0FE0, 0x0FE2, 0x0FE8, 0x0FEA, 0x0FEC, 0x0FEE, 0x0FF0, 0x0FF2,
-    0x0FF4, 0x2FF2, 0x07F2, 0x07FB, 0x03F6, 0x0BFA, 0x0BFD, 0x01FF,
-    0x05FF, 0x02FC, 0x007C, 0x017C, 0x003C, 0x00BC, 0x001C, 0x005C,
-    0x000C, 0x002C, 0x0004, 0x0014, 0x0000, 0x0008, 0x000E, 0x0002,
-    0x0006, 0x0003, 0x000F, 0x0009, 0x0001, 0x0015, 0x0005, 0x002D,
-    0x000D, 0x005D, 0x001D, 0x00BD, 0x003D, 0x017D, 0x007D, 0x02FD,
-    0x00FC, 0x05FC, 0x01FA, 0x0BFB, 0x03F7, 0x17F8, 0x07F3, 0x2FF3,
-    0x0FF5, 0x0FF3, 0x0FF1, 0x0FEF, 0x0FED, 0x0FEB, 0x0FE9, 0x0FE3,
-    0x0FE1,
-};
-
-static const uint16_t bitalloc_65_codes_g[65] = {
-    0x010C, 0x038A, 0x0608, 0x0786, 0x0084, 0x0087, 0x0302, 0x0305,
-    0x0040, 0x00E0, 0x00E3, 0x0183, 0x001E, 0x005E, 0x009E, 0x00DE,
-    0x00F1, 0x0011, 0x0039, 0x0061, 0x0079, 0x0009, 0x001D, 0x0031,
-    0x003D, 0x0005, 0x000F, 0x0019, 0x001F, 0x0003, 0x0006, 0x000A,
-    0x000E, 0x000B, 0x0008, 0x0004, 0x0000, 0x001A, 0x0012, 0x000A,
-    0x0002, 0x0036, 0x0026, 0x0016, 0x0006, 0x006E, 0x004E, 0x002E,
-    0x000E, 0x00DF, 0x009F, 0x005F, 0x001F, 0x01E0, 0x0180, 0x00E1,
-    0x0041, 0x03C2, 0x0303, 0x01C4, 0x0085, 0x0787, 0x0609, 0x038B,
-    0x010D,
-};
-
-static const uint8_t bitalloc_65_bits_a[65] = {
-    16, 16, 15, 14, 13, 13, 12, 12, 11, 11, 10, 10,  9,  9,  8,  8,
-     7,  7,  7,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,  5,  4,  4,
-     4,  4,  4,  4,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  7,  7,
-     7,  8,  8,  9,  9, 10, 10, 11, 11, 11, 12, 13, 13, 14, 15, 16,
-    16,
-};
-
-static const uint8_t bitalloc_65_bits_b[65] = {
-    12, 11, 10,  9,  9,  9,  8,  8,  8,  8,  8,  7,  7,  7,  7,  7,
-     7,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,  5,  4,
-     4,  4,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,
-     6,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  9,  9,  9, 10, 10,
-    12,
-};
-
-static const uint8_t bitalloc_65_bits_c[65] = {
-    11, 10, 10,  9,  9,  8,  8,  8,  7,  7,  7,  7,  7,  7,  7,  6,
-     6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-     5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,
-     6,  6,  6,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  9,  9, 10,
-    11,
-};
-
-static const uint8_t bitalloc_65_bits_d[65] = {
-    15, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 10,  9,  9,
-     9,  8,  8,  8,  7,  7,  7,  6,  6,  6,  5,  5,  5,  4,  4,  3,
-     3,  3,  4,  4,  5,  5,  5,  6,  6,  6,  7,  7,  7,  8,  8,  8,
-     8,  9,  9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 15, 15,
-    15,
-};
-
-static const uint8_t bitalloc_65_bits_e[65] = {
-    10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,
-     7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  5,  5,  5,  5,  4,  4,
-     3,  3,  4,  5,  5,  5,  5,  6,  6,  6,  6,  6,  7,  7,  7,  7,
-     7,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9, 10, 10, 10,
-    10,
-};
-
-static const uint8_t bitalloc_65_bits_f[65] = {
-    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 11,
-    11, 10,  9,  9,  8,  8,  7,  7,  6,  6,  5,  5,  4,  4,  4,  3,
-     3,  3,  4,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8,  9,  9, 10,
-    10, 11, 11, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-    14,
-};
-
-static const uint8_t bitalloc_65_bits_g[65] = {
-    11, 11, 11, 11, 10, 10, 10, 10,  9,  9,  9,  9,  8,  8,  8,  8,
-     8,  7,  7,  7,  7,  6,  6,  6,  6,  5,  5,  5,  5,  4,  4,  4,
-     4,  4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,
-     7,  8,  8,  8,  8,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11,
-    11,
-};
-
-static const uint16_t bitalloc_129_codes_a[129] = {
-    0x0660, 0x0666, 0x06EC, 0x0722, 0x0760, 0x076E, 0x004C, 0x004E,
-    0x00F4, 0x010A, 0x0148, 0x0156, 0x01D4, 0x01F2, 0x0331, 0x0370,
-    0x0377, 0x0396, 0x03B1, 0x0024, 0x0064, 0x007B, 0x008A, 0x00A5,
-    0x00D4, 0x00EB, 0x00FA, 0x019A, 0x01B9, 0x01C9, 0x01D9, 0x0010,
-    0x0030, 0x0033, 0x0043, 0x0053, 0x006B, 0x007A, 0x00CA, 0x00D2,
-    0x00DE, 0x00E6, 0x00F6, 0x000E, 0x001F, 0x0023, 0x002B, 0x003B,
-    0x003F, 0x0067, 0x0070, 0x0077, 0x0005, 0x000D, 0x0012, 0x001B,
-    0x002C, 0x0035, 0x003A, 0x0004, 0x000B, 0x0017, 0x001F, 0x0009,
-    0x0008, 0x000A, 0x0000, 0x0018, 0x000C, 0x0005, 0x003C, 0x0036,
-    0x002D, 0x001C, 0x0013, 0x000E, 0x0006, 0x007A, 0x0071, 0x0068,
-    0x0064, 0x003C, 0x0034, 0x0028, 0x0020, 0x000F, 0x00F7, 0x00E7,
-    0x00DF, 0x00D3, 0x00CB, 0x007B, 0x0074, 0x0054, 0x0044, 0x003C,
-    0x0031, 0x0011, 0x01DA, 0x01CA, 0x01BA, 0x019B, 0x00FB, 0x00F8,
-    0x00D5, 0x00AA, 0x008B, 0x0084, 0x0065, 0x0025, 0x03B6, 0x0397,
-    0x0390, 0x0371, 0x0332, 0x01F3, 0x01D5, 0x0157, 0x0149, 0x010B,
-    0x00F5, 0x004F, 0x004D, 0x076F, 0x0761, 0x0723, 0x06ED, 0x0667,
-    0x0661,
-};
-
-static const uint16_t bitalloc_129_codes_b[129] = {
-    0x29DC, 0x14EF, 0x0455, 0x0E9C, 0x022B, 0x0489, 0x0740, 0x074F,
-    0x0172, 0x0245, 0x0247, 0x030A, 0x03A1, 0x001C, 0x008B, 0x00D6,
-    0x010C, 0x0148, 0x014F, 0x0186, 0x01D1, 0x0008, 0x000F, 0x0046,
-    0x005D, 0x0078, 0x0087, 0x0096, 0x00A5, 0x00BC, 0x00D8, 0x00DE,
-    0x00F6, 0x0005, 0x0014, 0x0024, 0x002F, 0x003A, 0x003D, 0x0049,
-    0x0050, 0x0058, 0x005F, 0x0066, 0x006D, 0x0075, 0x007C, 0x0004,
-    0x000B, 0x0013, 0x0018, 0x001B, 0x001F, 0x0022, 0x0026, 0x002A,
-    0x002D, 0x0031, 0x0034, 0x0038, 0x003B, 0x003F, 0x0003, 0x0006,
-    0x000A, 0x0007, 0x0004, 0x0000, 0x003C, 0x0039, 0x0035, 0x0032,
-    0x002E, 0x002B, 0x0027, 0x0023, 0x0020, 0x001C, 0x0019, 0x0016,
-    0x0010, 0x0005, 0x007D, 0x007A, 0x006E, 0x0067, 0x0060, 0x0059,
-    0x0051, 0x004A, 0x0042, 0x003B, 0x0034, 0x0025, 0x0015, 0x0006,
-    0x00F7, 0x00DF, 0x00D9, 0x00BD, 0x00A6, 0x0097, 0x0090, 0x0079,
-    0x006A, 0x0047, 0x0044, 0x0009, 0x01D2, 0x0187, 0x0184, 0x0149,
-    0x010D, 0x00D7, 0x00B8, 0x001D, 0x03A6, 0x030B, 0x029C, 0x0246,
-    0x0173, 0x0114, 0x0741, 0x053A, 0x0488, 0x0E9D, 0x0A76, 0x0454,
-    0x29DD,
-};
-
-static const uint16_t bitalloc_129_codes_c[129] = {
-    0x0E5C, 0x072F, 0x001D, 0x0724, 0x000F, 0x010D, 0x0324, 0x0393,
-    0x03E9, 0x0080, 0x0087, 0x00FA, 0x0164, 0x0193, 0x01DE, 0x01F5,
-    0x0010, 0x002A, 0x0041, 0x0064, 0x0073, 0x008E, 0x00A4, 0x00B3,
-    0x00D6, 0x00E5, 0x00F4, 0x00FB, 0x0002, 0x0009, 0x0013, 0x001E,
-    0x0026, 0x002C, 0x0033, 0x003F, 0x0041, 0x004C, 0x0053, 0x005E,
-    0x0065, 0x0070, 0x0073, 0x0078, 0x007B, 0x007E, 0x0002, 0x0005,
-    0x0007, 0x000B, 0x000D, 0x0011, 0x0014, 0x0017, 0x001A, 0x001D,
-    0x0021, 0x0024, 0x0027, 0x002A, 0x002D, 0x0030, 0x0033, 0x0036,
-    0x003A, 0x0037, 0x0034, 0x0031, 0x002E, 0x002B, 0x0028, 0x0025,
-    0x0022, 0x001E, 0x001B, 0x0018, 0x0015, 0x0012, 0x000E, 0x000C,
-    0x0008, 0x0006, 0x0003, 0x007F, 0x007C, 0x0079, 0x0076, 0x0071,
-    0x006A, 0x005F, 0x0058, 0x004D, 0x0046, 0x0040, 0x0038, 0x002D,
-    0x0027, 0x001F, 0x0014, 0x0012, 0x0003, 0x0000, 0x00F5, 0x00EE,
-    0x00D7, 0x00C8, 0x00A5, 0x008F, 0x007C, 0x0065, 0x0042, 0x002B,
-    0x0011, 0x0002, 0x01DF, 0x01C8, 0x0165, 0x00FB, 0x00E4, 0x0081,
-    0x0006, 0x03E8, 0x0325, 0x01CA, 0x010C, 0x0725, 0x0396, 0x001C,
-    0x0E5D,
-};
-
-static const uint16_t bitalloc_129_codes_d[129] = {
-    0xA598, 0xA59A, 0xA59C, 0xA59E, 0xC598, 0xE586, 0x3ACC, 0x52CA,
-    0x62CD, 0x0D48, 0x1D67, 0x2978, 0x3167, 0x3966, 0x06A5, 0x0EBC,
-    0x14BD, 0x1CB1, 0x0350, 0x0353, 0x075F, 0x0A5F, 0x0C5E, 0x0E5E,
-    0x01AE, 0x03AD, 0x052D, 0x062D, 0x072D, 0x00D5, 0x01D4, 0x0294,
-    0x0314, 0x0394, 0x0014, 0x0094, 0x0114, 0x0174, 0x01B4, 0x01F4,
-    0x000B, 0x004B, 0x008B, 0x00BB, 0x00DB, 0x00FB, 0x001B, 0x003B,
-    0x0053, 0x0063, 0x0073, 0x0003, 0x0013, 0x0023, 0x002F, 0x0037,
-    0x003F, 0x0007, 0x000F, 0x0015, 0x0019, 0x001D, 0x0001, 0x0005,
-    0x0009, 0x0006, 0x0002, 0x001E, 0x001A, 0x0016, 0x0010, 0x0008,
-    0x0000, 0x0038, 0x0030, 0x0028, 0x001C, 0x000C, 0x007C, 0x006C,
-    0x005C, 0x0044, 0x0024, 0x0004, 0x00E4, 0x00C4, 0x00A4, 0x0074,
-    0x0034, 0x01F5, 0x01B5, 0x0175, 0x0115, 0x0095, 0x0015, 0x0395,
-    0x0315, 0x0295, 0x01D5, 0x00D6, 0x072E, 0x062E, 0x052E, 0x03AE,
-    0x01AF, 0x0E5F, 0x0C5F, 0x0C58, 0x0A58, 0x0758, 0x0351, 0x1CB2,
-    0x18B2, 0x0EBD, 0x0EB2, 0x3967, 0x3960, 0x2979, 0x2964, 0x0D49,
-    0x72C2, 0x52CB, 0x3ACD, 0xE587, 0xC599, 0xA59F, 0xA59D, 0xA59B,
-    0xA599,
-};
-
-static const uint16_t bitalloc_129_codes_e[129] = {
-    0xA13C, 0xC720, 0xA13F, 0xA13E, 0xA13D, 0xE722, 0x5090, 0x6393,
-    0x7392, 0x2849, 0x31CE, 0x39CE, 0x1425, 0x18E5, 0x1CE5, 0x0844,
-    0x0A1C, 0x0C7C, 0x036C, 0x0423, 0x050F, 0x063F, 0x01B7, 0x0216,
-    0x0285, 0x031D, 0x039D, 0x0109, 0x0140, 0x0180, 0x01C8, 0x01CF,
-    0x007A, 0x008A, 0x00A2, 0x00C1, 0x00E5, 0x0014, 0x0037, 0x0043,
-    0x004E, 0x0056, 0x0061, 0x006C, 0x007C, 0x000B, 0x001C, 0x001F,
-    0x0023, 0x0025, 0x0029, 0x002C, 0x002E, 0x0032, 0x0034, 0x0037,
-    0x003A, 0x003C, 0x003F, 0x0001, 0x0003, 0x0006, 0x0008, 0x000A,
-    0x000C, 0x000B, 0x0009, 0x0007, 0x0004, 0x0002, 0x0000, 0x003D,
-    0x003B, 0x0038, 0x0035, 0x0033, 0x002F, 0x002D, 0x002A, 0x0026,
-    0x0024, 0x0020, 0x001D, 0x001A, 0x007D, 0x006D, 0x0062, 0x0057,
-    0x004F, 0x0044, 0x003C, 0x0015, 0x00E6, 0x00C6, 0x00A3, 0x008B,
-    0x007B, 0x006C, 0x01C9, 0x0181, 0x0141, 0x010A, 0x00DA, 0x031E,
-    0x0286, 0x0217, 0x0210, 0x0738, 0x0638, 0x0508, 0x036D, 0x0C7D,
-    0x0A1D, 0x0845, 0x1CE6, 0x18E6, 0x1426, 0x39CF, 0x31CF, 0x284E,
-    0x7393, 0x7390, 0x5091, 0xE723, 0xC724, 0xC725, 0xC722, 0xC723,
-    0xC721,
-};
-
-static const uint16_t bitalloc_129_codes_f[129] = {
-    0x762C, 0x3B17, 0x1555, 0x0608, 0x0AAB, 0x0FF2, 0x0305, 0x0307,
-    0x0763, 0x0046, 0x010C, 0x01BC, 0x02AB, 0x03B6, 0x03FD, 0x0080,
-    0x0087, 0x00DF, 0x0156, 0x01D9, 0x01F8, 0x01FF, 0x002A, 0x0041,
-    0x0061, 0x0094, 0x00D4, 0x00EA, 0x00F2, 0x00FD, 0x0009, 0x000B,
-    0x001A, 0x0026, 0x0031, 0x0040, 0x004B, 0x006B, 0x0073, 0x0077,
-    0x007A, 0x007C, 0x0000, 0x0002, 0x0006, 0x0008, 0x000B, 0x000E,
-    0x0011, 0x0014, 0x0016, 0x0019, 0x001C, 0x001E, 0x0021, 0x0023,
-    0x0026, 0x0028, 0x002B, 0x002D, 0x002F, 0x0031, 0x0033, 0x0036,
-    0x0038, 0x0037, 0x0034, 0x0032, 0x0030, 0x002E, 0x002C, 0x0029,
-    0x0027, 0x0024, 0x0022, 0x001F, 0x001D, 0x001A, 0x0017, 0x0015,
-    0x0012, 0x000F, 0x000C, 0x0009, 0x0007, 0x0003, 0x0001, 0x007D,
-    0x007B, 0x0078, 0x0074, 0x0072, 0x0054, 0x0041, 0x0036, 0x0027,
-    0x001B, 0x0014, 0x000A, 0x00FE, 0x00F3, 0x00EB, 0x00D5, 0x0095,
-    0x006E, 0x0042, 0x002B, 0x0010, 0x01F9, 0x01DA, 0x0157, 0x0154,
-    0x00C0, 0x0081, 0x0022, 0x03B7, 0x03B0, 0x01BD, 0x010D, 0x0047,
-    0x07F8, 0x0554, 0x0306, 0x0FF3, 0x0EC4, 0x0609, 0x1D8A, 0x1554,
-    0x762D,
-};
-
-static const uint16_t bitalloc_129_codes_g[129] = {
-    0x1E20, 0x1E5E, 0x031C, 0x051A, 0x0718, 0x0916, 0x0B14, 0x0D12,
-    0x0F11, 0x0090, 0x018F, 0x028E, 0x038D, 0x048C, 0x058B, 0x068A,
-    0x0789, 0x0049, 0x00C8, 0x0148, 0x01C7, 0x0247, 0x02C6, 0x0346,
-    0x03C5, 0x0025, 0x0065, 0x00A5, 0x00E4, 0x0124, 0x0164, 0x01A4,
-    0x01E3, 0x0013, 0x0033, 0x0053, 0x0073, 0x0093, 0x00B3, 0x00D3,
-    0x00F3, 0x000A, 0x001A, 0x002A, 0x003A, 0x004A, 0x005A, 0x006A,
-    0x007A, 0x0006, 0x000E, 0x0016, 0x001E, 0x0026, 0x002E, 0x0036,
-    0x003E, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C,
-    0x0000, 0x001D, 0x0019, 0x0015, 0x0011, 0x000D, 0x0009, 0x0005,
-    0x003F, 0x0037, 0x002F, 0x0027, 0x001F, 0x0017, 0x000F, 0x0007,
-    0x007B, 0x006B, 0x005B, 0x004B, 0x003B, 0x002B, 0x001B, 0x000B,
-    0x0008, 0x00F0, 0x00D0, 0x00B0, 0x0090, 0x0070, 0x0050, 0x0030,
-    0x01E4, 0x01A5, 0x0165, 0x0125, 0x00E5, 0x00E2, 0x00A2, 0x0062,
-    0x03CA, 0x0347, 0x02C7, 0x02C4, 0x0244, 0x0149, 0x00C9, 0x00C6,
-    0x0796, 0x068B, 0x0688, 0x048D, 0x048A, 0x028F, 0x028C, 0x0091,
-    0x0F2E, 0x0D13, 0x0B15, 0x0917, 0x0719, 0x051B, 0x031D, 0x1E5F,
-    0x1E21,
-};
-
-static const uint8_t bitalloc_129_bits_a[129] = {
-    11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-    10, 10, 10,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  8,
-     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,  7,
-     7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  4,
-     4,  4,  4,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  7,  7,  7,
-     7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-     8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10,
-    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11,
-    11,
-};
-
-static const uint8_t bitalloc_129_bits_b[129] = {
-    14, 13, 12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10,  9,  9,  9,
-     9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-     8,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6,
-     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,
-     5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-     6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,
-     9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12,
-    14,
-};
-
-static const uint8_t bitalloc_129_bits_c[129] = {
-    13, 12, 11, 11, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  9,
-     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,
-     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,
-     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-     6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-     7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-     8,  8,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11,
-    13,
-};
-
-static const uint8_t bitalloc_129_bits_d[129] = {
-    16, 16, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13,
-    13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 10, 10, 10,
-    10, 10,  9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  7,  7,
-     7,  7,  7,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  4,  4,
-     4,  4,  4,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  7,  7,
-     7,  7,  7,  7,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9, 10,
-    10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13,
-    13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16,
-    16,
-};
-
-static const uint8_t bitalloc_129_bits_e[129] = {
-    16, 16, 16, 16, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 13, 12,
-    12, 12, 11, 11, 11, 11, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,
-     8,  8,  8,  8,  8,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,
-     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,
-     5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-     6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,
-     8,  8,  9,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11, 11, 12,
-    12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16,
-    16,
-};
-
-static const uint8_t bitalloc_129_bits_f[129] = {
-    15, 14, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 10, 10, 10,  9,
-     9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,
-     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6,
-     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-     6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-     6,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-     7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,
-     9,  9,  9, 10, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13,
-    15,
-};
-
-static const uint8_t bitalloc_129_bits_g[129] = {
-    13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11,
-    11, 10, 10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  9,
-     9,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,  7,  7,  7,
-     7,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,  5,
-     4,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,
-     7,  7,  7,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,
-     9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
-    11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 13,
-    13,
-};
-
-static const uint8_t bitalloc_sizes[10] = {
-    3, 5, 7, 9, 13, 17, 25, 33, 65, 129
-};
-
-static const int8_t bitalloc_offsets[10] = {
-    -1, -2, -3, -4, -6, -8, -12, -16, -32, -64
-};
-
-static const uint8_t bitalloc_maxbits[10][7] = {
-    { 2 },
-    { 4, 3, 3 },
-    { 5, 5, 4 },
-    { 6, 5, 6 },
-    { 7, 6, 5 },
-    { 9, 8, 7, 9, 8, 8, 8 },
-    { 9, 9, 8, 9, 8, 9, 9 },
-    { 9, 9, 9, 9, 9, 9, 9 },
-    { 9, 9, 9, 9, 9, 9, 9 },
-    { 9, 9, 9, 9, 9, 9, 9 }
-};
-
-static const uint16_t *const bitalloc_codes[10][8] = {
-    { bitalloc_3_codes,     NULL },
-    { bitalloc_5_codes_a,   bitalloc_5_codes_b,   bitalloc_5_codes_c,   NULL },
-    { bitalloc_7_codes_a,   bitalloc_7_codes_b,   bitalloc_7_codes_c,   NULL },
-    { bitalloc_9_codes_a,   bitalloc_9_codes_b,   bitalloc_9_codes_c,   NULL },
-    { bitalloc_13_codes_a,  bitalloc_13_codes_b,  bitalloc_13_codes_c,  NULL },
-    { bitalloc_17_codes_a,  bitalloc_17_codes_b,  bitalloc_17_codes_c,  bitalloc_17_codes_d,
-      bitalloc_17_codes_e,  bitalloc_17_codes_f,  bitalloc_17_codes_g,  NULL },
-    { bitalloc_25_codes_a,  bitalloc_25_codes_b,  bitalloc_25_codes_c,  bitalloc_25_codes_d,
-      bitalloc_25_codes_e,  bitalloc_25_codes_f,  bitalloc_25_codes_g,  NULL },
-    { bitalloc_33_codes_a,  bitalloc_33_codes_b,  bitalloc_33_codes_c,  bitalloc_33_codes_d,
-      bitalloc_33_codes_e,  bitalloc_33_codes_f,  bitalloc_33_codes_g,  NULL },
-    { bitalloc_65_codes_a,  bitalloc_65_codes_b,  bitalloc_65_codes_c,  bitalloc_65_codes_d,
-      bitalloc_65_codes_e,  bitalloc_65_codes_f,  bitalloc_65_codes_g,  NULL },
-    { bitalloc_129_codes_a, bitalloc_129_codes_b, bitalloc_129_codes_c, bitalloc_129_codes_d,
-      bitalloc_129_codes_e, bitalloc_129_codes_f, bitalloc_129_codes_g, NULL }
-};
-
-static const uint8_t *const bitalloc_bits[10][8] = {
-    { bitalloc_3_bits,     NULL },
-    { bitalloc_5_bits_a,   bitalloc_5_bits_b,   bitalloc_5_bits_c,   NULL },
-    { bitalloc_7_bits_a,   bitalloc_7_bits_b,   bitalloc_7_bits_c,   NULL },
-    { bitalloc_9_bits_a,   bitalloc_9_bits_b,   bitalloc_9_bits_c,   NULL },
-    { bitalloc_13_bits_a,  bitalloc_13_bits_b,  bitalloc_13_bits_c,  NULL },
-    { bitalloc_17_bits_a,  bitalloc_17_bits_b,  bitalloc_17_bits_c,  bitalloc_17_bits_d,
-      bitalloc_17_bits_e,  bitalloc_17_bits_f,  bitalloc_17_bits_g,  NULL },
-    { bitalloc_25_bits_a,  bitalloc_25_bits_b,  bitalloc_25_bits_c,  bitalloc_25_bits_d,
-      bitalloc_25_bits_e,  bitalloc_25_bits_f,  bitalloc_25_bits_g,  NULL },
-    { bitalloc_33_bits_a,  bitalloc_33_bits_b,  bitalloc_33_bits_c,  bitalloc_33_bits_d,
-      bitalloc_33_bits_e,  bitalloc_33_bits_f,  bitalloc_33_bits_g,  NULL },
-    { bitalloc_65_bits_a,  bitalloc_65_bits_b,  bitalloc_65_bits_c,  bitalloc_65_bits_d,
-      bitalloc_65_bits_e,  bitalloc_65_bits_f,  bitalloc_65_bits_g,  NULL },
-    { bitalloc_129_bits_a, bitalloc_129_bits_b, bitalloc_129_bits_c, bitalloc_129_bits_d,
-      bitalloc_129_bits_e, bitalloc_129_bits_f, bitalloc_129_bits_g, NULL }
-};
+#include "libavutil/common.h"
+
+#include "avcodec.h"
+#include "get_bits.h"
+
+#define DCA_CODE_BOOKS      10
+
+typedef struct DCAVLC {
+    int offset;         ///< Code values offset
+    int max_depth;      ///< Parameter for get_vlc2()
+    VLC vlc[7];         ///< Actual codes
+} DCAVLC;
+
+extern DCAVLC   ff_dca_vlc_bit_allocation;
+extern DCAVLC   ff_dca_vlc_transition_mode;
+extern DCAVLC   ff_dca_vlc_scale_factor;
+extern DCAVLC   ff_dca_vlc_quant_index[DCA_CODE_BOOKS];
+
+extern VLC  ff_dca_vlc_tnl_grp[5];
+extern VLC  ff_dca_vlc_tnl_scf;
+extern VLC  ff_dca_vlc_damp;
+extern VLC  ff_dca_vlc_dph;
+extern VLC  ff_dca_vlc_fst_rsd_amp;
+extern VLC  ff_dca_vlc_rsd_apprx;
+extern VLC  ff_dca_vlc_rsd_amp;
+extern VLC  ff_dca_vlc_avg_g3;
+extern VLC  ff_dca_vlc_st_grid;
+extern VLC  ff_dca_vlc_grid_2;
+extern VLC  ff_dca_vlc_grid_3;
+extern VLC  ff_dca_vlc_rsd;
+
+av_cold void ff_dca_init_vlcs(void);
 
 #endif /* AVCODEC_DCAHUFF_H */
diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c
deleted file mode 100644
index e5ef837..0000000
--- a/libavcodec/dct-test.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * (c) 2001 Fabrice Bellard
- *     2007 Marc Hoffman <marc.hoffman at analog.com>
- *
- * 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
- * DCT test (c) 2001 Fabrice Bellard
- * Started from sample code by Juan J. Sierralta P.
- */
-
-#include "config.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <math.h>
-
-#include "libavutil/cpu.h"
-#include "libavutil/common.h"
-#include "libavutil/lfg.h"
-#include "libavutil/time.h"
-
-#include "dct.h"
-#include "idctdsp.h"
-#include "simple_idct.h"
-#include "xvididct.h"
-#include "aandcttab.h"
-#include "faandct.h"
-#include "faanidct.h"
-#include "dctref.h"
-
-struct algo {
-    const char *name;
-    void (*func)(int16_t *block);
-    enum idct_permutation_type perm_type;
-    int cpu_flag;
-    int nonspec;
-};
-
-static const struct algo fdct_tab[] = {
-    { "REF-DBL",     ff_ref_fdct,          FF_IDCT_PERM_NONE },
-    { "IJG-AAN-INT", ff_fdct_ifast,        FF_IDCT_PERM_NONE },
-    { "IJG-LLM-INT", ff_jpeg_fdct_islow_8, FF_IDCT_PERM_NONE },
-#if CONFIG_FAANDCT
-    { "FAAN",        ff_faandct,           FF_IDCT_PERM_NONE },
-#endif /* CONFIG_FAANDCT */
-};
-
-static void ff_prores_idct_wrap(int16_t *dst){
-    LOCAL_ALIGNED(16, int16_t, qmat, [64]);
-    int i;
-
-    for(i=0; i<64; i++){
-        qmat[i]=4;
-    }
-    ff_prores_idct(dst, qmat);
-    for(i=0; i<64; i++) {
-         dst[i] -= 512;
-    }
-}
-
-static const struct algo idct_tab[] = {
-    { "REF-DBL",     ff_ref_idct,          FF_IDCT_PERM_NONE },
-    { "INT",         ff_j_rev_dct,         FF_IDCT_PERM_LIBMPEG2 },
-    { "SIMPLE-C",    ff_simple_idct_8,     FF_IDCT_PERM_NONE },
-    { "SIMPLE-C10",  ff_simple_idct_10,    FF_IDCT_PERM_NONE },
-    { "SIMPLE-C12",  ff_simple_idct_12,    FF_IDCT_PERM_NONE, 0, 1 },
-    { "PR-C",        ff_prores_idct_wrap,  FF_IDCT_PERM_NONE, 0, 1 },
-#if CONFIG_FAANIDCT
-    { "FAANI",       ff_faanidct,          FF_IDCT_PERM_NONE },
-#endif /* CONFIG_FAANIDCT */
-#if CONFIG_MPEG4_DECODER
-    { "XVID",        ff_xvid_idct,         FF_IDCT_PERM_NONE, 0, 1 },
-#endif /* CONFIG_MPEG4_DECODER */
-};
-
-#if ARCH_ARM
-#include "arm/dct-test.c"
-#elif ARCH_PPC
-#include "ppc/dct-test.c"
-#elif ARCH_X86
-#include "x86/dct-test.c"
-#else
-static const struct algo fdct_tab_arch[] = { { 0 } };
-static const struct algo idct_tab_arch[] = { { 0 } };
-#endif
-
-#define AANSCALE_BITS 12
-
-#define NB_ITS 20000
-#define NB_ITS_SPEED 50000
-
-DECLARE_ALIGNED(16, static int16_t, block)[64];
-DECLARE_ALIGNED(8,  static int16_t, block1)[64];
-
-static void init_block(int16_t block[64], int test, int is_idct, AVLFG *prng, int vals)
-{
-    int i, j;
-
-    memset(block, 0, 64 * sizeof(*block));
-
-    switch (test) {
-    case 0:
-        for (i = 0; i < 64; i++)
-            block[i] = (av_lfg_get(prng) % (2*vals)) -vals;
-        if (is_idct) {
-            ff_ref_fdct(block);
-            for (i = 0; i < 64; i++)
-                block[i] >>= 3;
-        }
-        break;
-    case 1:
-        j = av_lfg_get(prng) % 10 + 1;
-        for (i = 0; i < j; i++) {
-            int idx = av_lfg_get(prng) % 64;
-            block[idx] = av_lfg_get(prng) % (2*vals) -vals;
-        }
-        break;
-    case 2:
-        block[ 0] = av_lfg_get(prng) % (16*vals) - (8*vals);
-        block[63] = (block[0] & 1) ^ 1;
-        break;
-    }
-}
-
-static void permute(int16_t dst[64], const int16_t src[64],
-                    enum idct_permutation_type perm_type)
-{
-    int i;
-
-#if ARCH_X86
-    if (permute_x86(dst, src, perm_type))
-        return;
-#endif
-
-    switch (perm_type) {
-    case FF_IDCT_PERM_LIBMPEG2:
-        for (i = 0; i < 64; i++)
-            dst[(i & 0x38) | ((i & 6) >> 1) | ((i & 1) << 2)] = src[i];
-        break;
-    case FF_IDCT_PERM_PARTTRANS:
-        for (i = 0; i < 64; i++)
-            dst[(i & 0x24) | ((i & 3) << 3) | ((i >> 3) & 3)] = src[i];
-        break;
-    case FF_IDCT_PERM_TRANSPOSE:
-        for (i = 0; i < 64; i++)
-            dst[(i>>3) | ((i<<3)&0x38)] = src[i];
-        break;
-    default:
-        for (i = 0; i < 64; i++)
-            dst[i] = src[i];
-        break;
-    }
-}
-
-static int dct_error(const struct algo *dct, int test, int is_idct, int speed, const int bits)
-{
-    void (*ref)(int16_t *block) = is_idct ? ff_ref_idct : ff_ref_fdct;
-    int it, i, scale;
-    int err_inf, v;
-    int64_t err2, ti, ti1, it1, err_sum = 0;
-    int64_t sysErr[64], sysErrMax = 0;
-    int maxout = 0;
-    int blockSumErrMax = 0, blockSumErr;
-    AVLFG prng;
-    const int vals=1<<bits;
-    double omse, ome;
-    int spec_err;
-
-    av_lfg_init(&prng, 1);
-
-    err_inf = 0;
-    err2 = 0;
-    for (i = 0; i < 64; i++)
-        sysErr[i] = 0;
-    for (it = 0; it < NB_ITS; it++) {
-        init_block(block1, test, is_idct, &prng, vals);
-        permute(block, block1, dct->perm_type);
-
-        dct->func(block);
-        emms_c();
-
-        if (!strcmp(dct->name, "IJG-AAN-INT")) {
-            for (i = 0; i < 64; i++) {
-                scale = 8 * (1 << (AANSCALE_BITS + 11)) / ff_aanscales[i];
-                block[i] = (block[i] * scale) >> AANSCALE_BITS;
-            }
-        }
-
-        ref(block1);
-        if (!strcmp(dct->name, "PR-SSE2"))
-            for (i = 0; i < 64; i++)
-                block1[i] = av_clip(block1[i], 4-512, 1019-512);
-
-        blockSumErr = 0;
-        for (i = 0; i < 64; i++) {
-            int err = block[i] - block1[i];
-            err_sum += err;
-            v = abs(err);
-            if (v > err_inf)
-                err_inf = v;
-            err2 += v * v;
-            sysErr[i] += block[i] - block1[i];
-            blockSumErr += v;
-            if (abs(block[i]) > maxout)
-                maxout = abs(block[i]);
-        }
-        if (blockSumErrMax < blockSumErr)
-            blockSumErrMax = blockSumErr;
-    }
-    for (i = 0; i < 64; i++)
-        sysErrMax = FFMAX(sysErrMax, FFABS(sysErr[i]));
-
-    for (i = 0; i < 64; i++) {
-        if (i % 8 == 0)
-            printf("\n");
-        printf("%7d ", (int) sysErr[i]);
-    }
-    printf("\n");
-
-    omse = (double) err2 / NB_ITS / 64;
-    ome  = (double) err_sum / NB_ITS / 64;
-
-    spec_err = is_idct && (err_inf > 1 || omse > 0.02 || fabs(ome) > 0.0015);
-
-    printf("%s %s: max_err=%d omse=%0.8f ome=%0.8f syserr=%0.8f maxout=%d blockSumErr=%d\n",
-           is_idct ? "IDCT" : "DCT", dct->name, err_inf,
-           omse, ome, (double) sysErrMax / NB_ITS,
-           maxout, blockSumErrMax);
-
-    if (spec_err && !dct->nonspec) {
-        printf("Failed!\n");
-        return 1;
-    }
-
-    if (!speed)
-        return 0;
-
-    /* speed test */
-
-    init_block(block, test, is_idct, &prng, vals);
-    permute(block1, block, dct->perm_type);
-
-    ti = av_gettime_relative();
-    it1 = 0;
-    do {
-        for (it = 0; it < NB_ITS_SPEED; it++) {
-            memcpy(block, block1, sizeof(block));
-            dct->func(block);
-        }
-        emms_c();
-        it1 += NB_ITS_SPEED;
-        ti1 = av_gettime_relative() - ti;
-    } while (ti1 < 1000000);
-
-    printf("%s %s: %0.1f kdct/s\n", is_idct ? "IDCT" : "DCT", dct->name,
-           (double) it1 * 1000.0 / (double) ti1);
-
-    return 0;
-}
-
-DECLARE_ALIGNED(8, static uint8_t, img_dest)[64];
-DECLARE_ALIGNED(8, static uint8_t, img_dest1)[64];
-
-static void idct248_ref(uint8_t *dest, int linesize, int16_t *block)
-{
-    static int init;
-    static double c8[8][8];
-    static double c4[4][4];
-    double block1[64], block2[64], block3[64];
-    double s, sum, v;
-    int i, j, k;
-
-    if (!init) {
-        init = 1;
-
-        for (i = 0; i < 8; i++) {
-            sum = 0;
-            for (j = 0; j < 8; j++) {
-                s = (i == 0) ? sqrt(1.0 / 8.0) : sqrt(1.0 / 4.0);
-                c8[i][j] = s * cos(M_PI * i * (j + 0.5) / 8.0);
-                sum += c8[i][j] * c8[i][j];
-            }
-        }
-
-        for (i = 0; i < 4; i++) {
-            sum = 0;
-            for (j = 0; j < 4; j++) {
-                s = (i == 0) ? sqrt(1.0 / 4.0) : sqrt(1.0 / 2.0);
-                c4[i][j] = s * cos(M_PI * i * (j + 0.5) / 4.0);
-                sum += c4[i][j] * c4[i][j];
-            }
-        }
-    }
-
-    /* butterfly */
-    s = 0.5 * sqrt(2.0);
-    for (i = 0; i < 4; i++) {
-        for (j = 0; j < 8; j++) {
-            block1[8 * (2 * i) + j] =
-                (block[8 * (2 * i) + j] + block[8 * (2 * i + 1) + j]) * s;
-            block1[8 * (2 * i + 1) + j] =
-                (block[8 * (2 * i) + j] - block[8 * (2 * i + 1) + j]) * s;
-        }
-    }
-
-    /* idct8 on lines */
-    for (i = 0; i < 8; i++) {
-        for (j = 0; j < 8; j++) {
-            sum = 0;
-            for (k = 0; k < 8; k++)
-                sum += c8[k][j] * block1[8 * i + k];
-            block2[8 * i + j] = sum;
-        }
-    }
-
-    /* idct4 */
-    for (i = 0; i < 8; i++) {
-        for (j = 0; j < 4; j++) {
-            /* top */
-            sum = 0;
-            for (k = 0; k < 4; k++)
-                sum += c4[k][j] * block2[8 * (2 * k) + i];
-            block3[8 * (2 * j) + i] = sum;
-
-            /* bottom */
-            sum = 0;
-            for (k = 0; k < 4; k++)
-                sum += c4[k][j] * block2[8 * (2 * k + 1) + i];
-            block3[8 * (2 * j + 1) + i] = sum;
-        }
-    }
-
-    /* clamp and store the result */
-    for (i = 0; i < 8; i++) {
-        for (j = 0; j < 8; j++) {
-            v = block3[8 * i + j];
-            if      (v < 0)   v = 0;
-            else if (v > 255) v = 255;
-            dest[i * linesize + j] = (int) rint(v);
-        }
-    }
-}
-
-static void idct248_error(const char *name,
-                          void (*idct248_put)(uint8_t *dest, int line_size,
-                                              int16_t *block),
-                          int speed)
-{
-    int it, i, it1, ti, ti1, err_max, v;
-    AVLFG prng;
-
-    av_lfg_init(&prng, 1);
-
-    /* just one test to see if code is correct (precision is less
-       important here) */
-    err_max = 0;
-    for (it = 0; it < NB_ITS; it++) {
-        /* XXX: use forward transform to generate values */
-        for (i = 0; i < 64; i++)
-            block1[i] = av_lfg_get(&prng) % 256 - 128;
-        block1[0] += 1024;
-
-        for (i = 0; i < 64; i++)
-            block[i] = block1[i];
-        idct248_ref(img_dest1, 8, block);
-
-        for (i = 0; i < 64; i++)
-            block[i] = block1[i];
-        idct248_put(img_dest, 8, block);
-
-        for (i = 0; i < 64; i++) {
-            v = abs((int) img_dest[i] - (int) img_dest1[i]);
-            if (v == 255)
-                printf("%d %d\n", img_dest[i], img_dest1[i]);
-            if (v > err_max)
-                err_max = v;
-        }
-#if 0
-        printf("ref=\n");
-        for(i=0;i<8;i++) {
-            int j;
-            for(j=0;j<8;j++) {
-                printf(" %3d", img_dest1[i*8+j]);
-            }
-            printf("\n");
-        }
-
-        printf("out=\n");
-        for(i=0;i<8;i++) {
-            int j;
-            for(j=0;j<8;j++) {
-                printf(" %3d", img_dest[i*8+j]);
-            }
-            printf("\n");
-        }
-#endif
-    }
-    printf("%s %s: err_inf=%d\n", 1 ? "IDCT248" : "DCT248", name, err_max);
-
-    if (!speed)
-        return;
-
-    ti = av_gettime_relative();
-    it1 = 0;
-    do {
-        for (it = 0; it < NB_ITS_SPEED; it++) {
-            for (i = 0; i < 64; i++)
-                block[i] = block1[i];
-            idct248_put(img_dest, 8, block);
-        }
-        emms_c();
-        it1 += NB_ITS_SPEED;
-        ti1 = av_gettime_relative() - ti;
-    } while (ti1 < 1000000);
-
-    printf("%s %s: %0.1f kdct/s\n", 1 ? "IDCT248" : "DCT248", name,
-           (double) it1 * 1000.0 / (double) ti1);
-}
-
-static void help(void)
-{
-    printf("dct-test [-i] [<test-number>] [<bits>]\n"
-           "test-number 0 -> test with random matrixes\n"
-           "            1 -> test with random sparse matrixes\n"
-           "            2 -> do 3. test from mpeg4 std\n"
-           "bits        Number of time domain bits to use, 8 is default\n"
-           "-i          test IDCT implementations\n"
-           "-4          test IDCT248 implementations\n"
-           "-t          speed test\n");
-}
-
-#if !HAVE_GETOPT
-#include "compat/getopt.c"
-#endif
-
-int main(int argc, char **argv)
-{
-    int test_idct = 0, test_248_dct = 0;
-    int c, i;
-    int test = 1;
-    int speed = 0;
-    int err = 0;
-    int bits=8;
-
-    ff_ref_dct_init();
-
-    for (;;) {
-        c = getopt(argc, argv, "ih4t");
-        if (c == -1)
-            break;
-        switch (c) {
-        case 'i':
-            test_idct = 1;
-            break;
-        case '4':
-            test_248_dct = 1;
-            break;
-        case 't':
-            speed = 1;
-            break;
-        default:
-        case 'h':
-            help();
-            return 0;
-        }
-    }
-
-    if (optind < argc)
-        test = atoi(argv[optind]);
-    if(optind+1 < argc) bits= atoi(argv[optind+1]);
-
-    printf("ffmpeg DCT/IDCT test\n");
-
-    if (test_248_dct) {
-        idct248_error("SIMPLE-C", ff_simple_idct248_put, speed);
-    } else {
-        const int cpu_flags = av_get_cpu_flags();
-        if (test_idct) {
-            for (i = 0; i < FF_ARRAY_ELEMS(idct_tab); i++)
-                err |= dct_error(&idct_tab[i], test, test_idct, speed, bits);
-
-            for (i = 0; idct_tab_arch[i].name; i++)
-                if (!(~cpu_flags & idct_tab_arch[i].cpu_flag))
-                    err |= dct_error(&idct_tab_arch[i], test, test_idct, speed, bits);
-        }
-#if CONFIG_FDCTDSP
-        else {
-            for (i = 0; i < FF_ARRAY_ELEMS(fdct_tab); i++)
-                err |= dct_error(&fdct_tab[i], test, test_idct, speed, bits);
-
-            for (i = 0; fdct_tab_arch[i].name; i++)
-                if (!(~cpu_flags & fdct_tab_arch[i].cpu_flag))
-                    err |= dct_error(&fdct_tab_arch[i], test, test_idct, speed, bits);
-        }
-#endif /* CONFIG_FDCTDSP */
-    }
-
-    if (err)
-        printf("Error: %d.\n", err);
-
-    return !!err;
-}
diff --git a/libavcodec/dds.c b/libavcodec/dds.c
index 9577b67..763371a 100644
--- a/libavcodec/dds.c
+++ b/libavcodec/dds.c
@@ -242,6 +242,10 @@ static int parse_pixel_format(AVCodecContext *avctx)
             ctx->paletted   = 1;
             avctx->pix_fmt  = AV_PIX_FMT_PAL8;
             break;
+        case MKTAG('G', '1', ' ', ' '):
+            ctx->compressed = 0;
+            avctx->pix_fmt  = AV_PIX_FMT_MONOBLACK;
+            break;
         case MKTAG('D', 'X', '1', '0'):
             /* DirectX 10 extra header */
             dxgi = bytestream2_get_le32(gbc);
@@ -353,11 +357,21 @@ static int parse_pixel_format(AVCodecContext *avctx)
         /*  8 bpp */
         if (bpp == 8 && r == 0xff && g == 0 && b == 0 && a == 0)
             avctx->pix_fmt = AV_PIX_FMT_GRAY8;
+        else if (bpp == 8 && r == 0 && g == 0 && b == 0 && a == 0xff)
+            avctx->pix_fmt = AV_PIX_FMT_GRAY8;
         /* 16 bpp */
         else if (bpp == 16 && r == 0xff && g == 0 && b == 0 && a == 0xff00)
             avctx->pix_fmt = AV_PIX_FMT_YA8;
+        else if (bpp == 16 && r == 0xff00 && g == 0 && b == 0 && a == 0xff) {
+            avctx->pix_fmt = AV_PIX_FMT_YA8;
+            ctx->postproc = DDS_SWAP_ALPHA;
+        }
         else if (bpp == 16 && r == 0xffff && g == 0 && b == 0 && a == 0)
             avctx->pix_fmt = AV_PIX_FMT_GRAY16LE;
+        else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0)
+            avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
+        else if (bpp == 16 && r == 0x7c00 && g == 0x3e0 && b == 0x1f && a == 0x8000)
+            avctx->pix_fmt = AV_PIX_FMT_RGB555LE; // alpha ignored
         else if (bpp == 16 && r == 0xf800 && g == 0x7e0 && b == 0x1f && a == 0)
             avctx->pix_fmt = AV_PIX_FMT_RGB565LE;
         /* 24 bpp */
@@ -387,8 +401,6 @@ static int parse_pixel_format(AVCodecContext *avctx)
         ctx->postproc = DDS_NORMAL_MAP;
     else if (ycocg_classic && !ctx->compressed)
         ctx->postproc = DDS_RAW_YCOCG;
-    else if (avctx->pix_fmt == AV_PIX_FMT_YA8)
-        ctx->postproc = DDS_SWAP_ALPHA;
 
     /* ATI/NVidia variants sometimes add swizzling in bpp. */
     switch (bpp) {
@@ -694,11 +706,7 @@ static int dds_decode(AVCodecContext *avctx, void *data,
     }
 
     /* Run any post processing here if needed. */
-    if (avctx->pix_fmt == AV_PIX_FMT_BGRA ||
-        avctx->pix_fmt == AV_PIX_FMT_RGBA ||
-        avctx->pix_fmt == AV_PIX_FMT_RGB0 ||
-        avctx->pix_fmt == AV_PIX_FMT_BGR0 ||
-        avctx->pix_fmt == AV_PIX_FMT_YA8)
+    if (ctx->postproc != DDS_NONE)
         run_postproc(avctx, frame);
 
     /* Frame is ready to be output. */
diff --git a/libavcodec/dirac.c b/libavcodec/dirac.c
index 527f015..027ce79 100644
--- a/libavcodec/dirac.c
+++ b/libavcodec/dirac.c
@@ -151,8 +151,8 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
     /* [DIRAC_STD] 10.3.2 Frame size. frame_size(video_params) */
     /* [DIRAC_STD] custom_dimensions_flag */
     if (get_bits1(gb)) {
-        dsh->width  = svq3_get_ue_golomb(gb); /* [DIRAC_STD] FRAME_WIDTH  */
-        dsh->height = svq3_get_ue_golomb(gb); /* [DIRAC_STD] FRAME_HEIGHT */
+        dsh->width  = get_interleaved_ue_golomb(gb); /* [DIRAC_STD] FRAME_WIDTH  */
+        dsh->height = get_interleaved_ue_golomb(gb); /* [DIRAC_STD] FRAME_HEIGHT */
     }
 
     /* [DIRAC_STD] 10.3.3 Chroma Sampling Format.
@@ -160,7 +160,7 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
     /* [DIRAC_STD] custom_chroma_format_flag */
     if (get_bits1(gb))
         /* [DIRAC_STD] CHROMA_FORMAT_INDEX */
-        dsh->chroma_format = svq3_get_ue_golomb(gb);
+        dsh->chroma_format = get_interleaved_ue_golomb(gb);
     if (dsh->chroma_format > 2U) {
         if (log_ctx)
             av_log(log_ctx, AV_LOG_ERROR, "Unknown chroma format %d\n",
@@ -172,22 +172,22 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
     /* [DIRAC_STD] custom_scan_format_flag */
     if (get_bits1(gb))
         /* [DIRAC_STD] SOURCE_SAMPLING */
-        dsh->interlaced = svq3_get_ue_golomb(gb);
+        dsh->interlaced = get_interleaved_ue_golomb(gb);
     if (dsh->interlaced > 1U)
         return AVERROR_INVALIDDATA;
 
     /* [DIRAC_STD] 10.3.5 Frame Rate. frame_rate(video_params) */
     if (get_bits1(gb)) { /* [DIRAC_STD] custom_frame_rate_flag */
-        dsh->frame_rate_index = svq3_get_ue_golomb(gb);
+        dsh->frame_rate_index = get_interleaved_ue_golomb(gb);
 
         if (dsh->frame_rate_index > 10U)
             return AVERROR_INVALIDDATA;
 
         if (!dsh->frame_rate_index) {
             /* [DIRAC_STD] FRAME_RATE_NUMER */
-            frame_rate.num = svq3_get_ue_golomb(gb);
+            frame_rate.num = get_interleaved_ue_golomb(gb);
             /* [DIRAC_STD] FRAME_RATE_DENOM */
-            frame_rate.den = svq3_get_ue_golomb(gb);
+            frame_rate.den = get_interleaved_ue_golomb(gb);
         }
     }
     /* [DIRAC_STD] preset_frame_rate(video_params, index) */
@@ -204,14 +204,14 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
      * pixel_aspect_ratio(video_params) */
     if (get_bits1(gb)) { /* [DIRAC_STD] custom_pixel_aspect_ratio_flag */
         /* [DIRAC_STD] index */
-        dsh->aspect_ratio_index = svq3_get_ue_golomb(gb);
+        dsh->aspect_ratio_index = get_interleaved_ue_golomb(gb);
 
         if (dsh->aspect_ratio_index > 6U)
             return AVERROR_INVALIDDATA;
 
         if (!dsh->aspect_ratio_index) {
-            dsh->sample_aspect_ratio.num = svq3_get_ue_golomb(gb);
-            dsh->sample_aspect_ratio.den = svq3_get_ue_golomb(gb);
+            dsh->sample_aspect_ratio.num = get_interleaved_ue_golomb(gb);
+            dsh->sample_aspect_ratio.den = get_interleaved_ue_golomb(gb);
         }
     }
     /* [DIRAC_STD] Take value from Table 10.4 Available preset pixel
@@ -223,13 +223,13 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
     /* [DIRAC_STD] 10.3.7 Clean area. clean_area(video_params) */
     if (get_bits1(gb)) { /* [DIRAC_STD] custom_clean_area_flag */
         /* [DIRAC_STD] CLEAN_WIDTH */
-        dsh->clean_width = svq3_get_ue_golomb(gb);
+        dsh->clean_width = get_interleaved_ue_golomb(gb);
         /* [DIRAC_STD] CLEAN_HEIGHT */
-        dsh->clean_height = svq3_get_ue_golomb(gb);
+        dsh->clean_height = get_interleaved_ue_golomb(gb);
         /* [DIRAC_STD] CLEAN_LEFT_OFFSET */
-        dsh->clean_left_offset = svq3_get_ue_golomb(gb);
+        dsh->clean_left_offset = get_interleaved_ue_golomb(gb);
         /* [DIRAC_STD] CLEAN_RIGHT_OFFSET */
-        dsh->clean_right_offset = svq3_get_ue_golomb(gb);
+        dsh->clean_right_offset = get_interleaved_ue_golomb(gb);
     }
 
     /* [DIRAC_STD] 10.3.8 Signal range. signal_range(video_params)
@@ -237,17 +237,17 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
      * AVCOL_RANGE_MPEG/JPEG values */
     if (get_bits1(gb)) { /* [DIRAC_STD] custom_signal_range_flag */
         /* [DIRAC_STD] index */
-        dsh->pixel_range_index = svq3_get_ue_golomb(gb);
+        dsh->pixel_range_index = get_interleaved_ue_golomb(gb);
 
         if (dsh->pixel_range_index > 4U)
             return AVERROR_INVALIDDATA;
 
         /* This assumes either fullrange or MPEG levels only */
         if (!dsh->pixel_range_index) {
-            luma_offset = svq3_get_ue_golomb(gb);
-            luma_depth  = av_log2(svq3_get_ue_golomb(gb)) + 1;
-            svq3_get_ue_golomb(gb); /* chroma offset    */
-            svq3_get_ue_golomb(gb); /* chroma excursion */
+            luma_offset = get_interleaved_ue_golomb(gb);
+            luma_depth  = av_log2(get_interleaved_ue_golomb(gb)) + 1;
+            get_interleaved_ue_golomb(gb); /* chroma offset    */
+            get_interleaved_ue_golomb(gb); /* chroma excursion */
             dsh->color_range = luma_offset ? AVCOL_RANGE_MPEG
                                            : AVCOL_RANGE_JPEG;
         }
@@ -279,7 +279,7 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
     /* [DIRAC_STD] 10.3.9 Colour specification. colour_spec(video_params) */
     if (get_bits1(gb)) { /* [DIRAC_STD] custom_colour_spec_flag */
         /* [DIRAC_STD] index */
-        idx = dsh->color_spec_index = svq3_get_ue_golomb(gb);
+        idx = dsh->color_spec_index = get_interleaved_ue_golomb(gb);
 
         if (dsh->color_spec_index > 4U)
             return AVERROR_INVALIDDATA;
@@ -291,20 +291,20 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
         if (!dsh->color_spec_index) {
             /* [DIRAC_STD] 10.3.9.1 Colour primaries */
             if (get_bits1(gb)) {
-                idx = svq3_get_ue_golomb(gb);
+                idx = get_interleaved_ue_golomb(gb);
                 if (idx < 3U)
                     dsh->color_primaries = dirac_primaries[idx];
             }
             /* [DIRAC_STD] 10.3.9.2 Colour matrix */
             if (get_bits1(gb)) {
-                idx = svq3_get_ue_golomb(gb);
+                idx = get_interleaved_ue_golomb(gb);
                 if (!idx)
                     dsh->colorspace = AVCOL_SPC_BT709;
                 else if (idx == 1)
                     dsh->colorspace = AVCOL_SPC_BT470BG;
             }
             /* [DIRAC_STD] 10.3.9.3 Transfer function */
-            if (get_bits1(gb) && !svq3_get_ue_golomb(gb))
+            if (get_bits1(gb) && !get_interleaved_ue_golomb(gb))
                 dsh->color_trc = AVCOL_TRC_BT709;
         }
     } else {
@@ -336,13 +336,13 @@ int av_dirac_parse_sequence_header(AVDiracSeqHeader **pdsh,
         goto fail;
 
     /* [DIRAC_SPEC] 10.1 Parse Parameters. parse_parameters() */
-    dsh->version.major = svq3_get_ue_golomb(&gb);
-    dsh->version.minor = svq3_get_ue_golomb(&gb);
-    dsh->profile   = svq3_get_ue_golomb(&gb);
-    dsh->level     = svq3_get_ue_golomb(&gb);
+    dsh->version.major = get_interleaved_ue_golomb(&gb);
+    dsh->version.minor = get_interleaved_ue_golomb(&gb);
+    dsh->profile   = get_interleaved_ue_golomb(&gb);
+    dsh->level     = get_interleaved_ue_golomb(&gb);
     /* [DIRAC_SPEC] sequence_header() -> base_video_format as defined in
      * 10.2 Base Video Format, table 10.1 Dirac predefined video formats */
-    video_format   = svq3_get_ue_golomb(&gb);
+    video_format = get_interleaved_ue_golomb(&gb);
 
     if (dsh->version.major < 2 && log_ctx)
         av_log(log_ctx, AV_LOG_WARNING, "Stream is old and may not work\n");
@@ -377,7 +377,7 @@ int av_dirac_parse_sequence_header(AVDiracSeqHeader **pdsh,
 
     /* [DIRAC_STD] picture_coding_mode shall be 0 for fields and 1 for frames
      * currently only used to signal field coding */
-    picture_coding_mode = svq3_get_ue_golomb(&gb);
+    picture_coding_mode = get_interleaved_ue_golomb(&gb);
     if (picture_coding_mode != 0) {
         if (log_ctx) {
             av_log(log_ctx, AV_LOG_ERROR, "Unsupported picture coding mode %d",
diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c
index 05c7900..c473e87 100644
--- a/libavcodec/diracdec.c
+++ b/libavcodec/diracdec.c
@@ -671,9 +671,9 @@ static void decode_component(DiracContext *s, int comp)
 
             align_get_bits(&s->gb);
             /* [DIRAC_STD] 13.4.2 subband() */
-            b->length = svq3_get_ue_golomb(&s->gb);
+            b->length = get_interleaved_ue_golomb(&s->gb);
             if (b->length) {
-                b->quant = svq3_get_ue_golomb(&s->gb);
+                b->quant = get_interleaved_ue_golomb(&s->gb);
                 align_get_bits(&s->gb);
                 b->coeff_data = s->gb.buffer + get_bits_count(&s->gb)/8;
                 b->length = FFMIN(b->length, FFMAX(get_bits_left(&s->gb)/8, 0));
@@ -903,8 +903,8 @@ static int decode_lowdelay(DiracContext *s)
     } else {
         for (slice_y = 0; bufsize > 0 && slice_y < s->num_y; slice_y++) {
             for (slice_x = 0; bufsize > 0 && slice_x < s->num_x; slice_x++) {
-                bytes = (slice_num+1) * s->lowdelay.bytes.num / s->lowdelay.bytes.den
-                    - slice_num    * s->lowdelay.bytes.num / s->lowdelay.bytes.den;
+                bytes = (slice_num+1) * (int64_t)s->lowdelay.bytes.num / s->lowdelay.bytes.den
+                       - slice_num    * (int64_t)s->lowdelay.bytes.num / s->lowdelay.bytes.den;
                 slices[slice_num].bytes   = bytes;
                 slices[slice_num].slice_x = slice_x;
                 slices[slice_num].slice_y = slice_y;
@@ -1001,7 +1001,7 @@ static int dirac_unpack_prediction_parameters(DiracContext *s)
     align_get_bits(gb);
     /* [DIRAC_STD] 11.2.2 Block parameters. block_parameters() */
     /* Luma and Chroma are equal. 11.2.3 */
-    idx = svq3_get_ue_golomb(gb); /* [DIRAC_STD] index */
+    idx = get_interleaved_ue_golomb(gb); /* [DIRAC_STD] index */
 
     if (idx > 4) {
         av_log(s->avctx, AV_LOG_ERROR, "Block prediction index too high\n");
@@ -1009,10 +1009,10 @@ static int dirac_unpack_prediction_parameters(DiracContext *s)
     }
 
     if (idx == 0) {
-        s->plane[0].xblen = svq3_get_ue_golomb(gb);
-        s->plane[0].yblen = svq3_get_ue_golomb(gb);
-        s->plane[0].xbsep = svq3_get_ue_golomb(gb);
-        s->plane[0].ybsep = svq3_get_ue_golomb(gb);
+        s->plane[0].xblen = get_interleaved_ue_golomb(gb);
+        s->plane[0].yblen = get_interleaved_ue_golomb(gb);
+        s->plane[0].xbsep = get_interleaved_ue_golomb(gb);
+        s->plane[0].ybsep = get_interleaved_ue_golomb(gb);
     } else {
         /*[DIRAC_STD] preset_block_params(index). Table 11.1 */
         s->plane[0].xblen = default_blen[idx-1];
@@ -1046,7 +1046,7 @@ static int dirac_unpack_prediction_parameters(DiracContext *s)
 
     /*[DIRAC_STD] 11.2.5 Motion vector precision. motion_vector_precision()
       Read motion vector precision */
-    s->mv_precision = svq3_get_ue_golomb(gb);
+    s->mv_precision = get_interleaved_ue_golomb(gb);
     if (s->mv_precision > 3) {
         av_log(s->avctx, AV_LOG_ERROR, "MV precision finer than eighth-pel\n");
         return AVERROR_INVALIDDATA;
@@ -1066,7 +1066,7 @@ static int dirac_unpack_prediction_parameters(DiracContext *s)
             /* [DIRAC_STD] zoom_rotate_shear(gparams)
                zoom/rotation/shear parameters */
             if (get_bits1(gb)) {
-                s->globalmc[ref].zrs_exp   = svq3_get_ue_golomb(gb);
+                s->globalmc[ref].zrs_exp   = get_interleaved_ue_golomb(gb);
                 s->globalmc[ref].zrs[0][0] = dirac_get_se_golomb(gb);
                 s->globalmc[ref].zrs[0][1] = dirac_get_se_golomb(gb);
                 s->globalmc[ref].zrs[1][0] = dirac_get_se_golomb(gb);
@@ -1077,7 +1077,7 @@ static int dirac_unpack_prediction_parameters(DiracContext *s)
             }
             /* [DIRAC_STD] perspective(gparams) */
             if (get_bits1(gb)) {
-                s->globalmc[ref].perspective_exp = svq3_get_ue_golomb(gb);
+                s->globalmc[ref].perspective_exp = get_interleaved_ue_golomb(gb);
                 s->globalmc[ref].perspective[0]  = dirac_get_se_golomb(gb);
                 s->globalmc[ref].perspective[1]  = dirac_get_se_golomb(gb);
             }
@@ -1086,7 +1086,7 @@ static int dirac_unpack_prediction_parameters(DiracContext *s)
 
     /*[DIRAC_STD] 11.2.7 Picture prediction mode. prediction_mode()
       Picture prediction mode, not currently used. */
-    if (svq3_get_ue_golomb(gb)) {
+    if (get_interleaved_ue_golomb(gb)) {
         av_log(s->avctx, AV_LOG_ERROR, "Unknown picture prediction mode\n");
         return AVERROR_INVALIDDATA;
     }
@@ -1098,7 +1098,7 @@ static int dirac_unpack_prediction_parameters(DiracContext *s)
     s->weight[1]        = 1;
 
     if (get_bits1(gb)) {
-        s->weight_log2denom = svq3_get_ue_golomb(gb);
+        s->weight_log2denom = get_interleaved_ue_golomb(gb);
         s->weight[0] = dirac_get_se_golomb(gb);
         if (s->num_refs == 2)
             s->weight[1] = dirac_get_se_golomb(gb);
@@ -1117,7 +1117,7 @@ static int dirac_unpack_idwt_params(DiracContext *s)
     unsigned tmp;
 
 #define CHECKEDREAD(dst, cond, errmsg) \
-    tmp = svq3_get_ue_golomb(gb); \
+    tmp = get_interleaved_ue_golomb(gb); \
     if (cond) { \
         av_log(s->avctx, AV_LOG_ERROR, errmsg); \
         return AVERROR_INVALIDDATA; \
@@ -1151,18 +1151,18 @@ static int dirac_unpack_idwt_params(DiracContext *s)
         }
     }
     else {
-        s->num_x        = svq3_get_ue_golomb(gb);
-        s->num_y        = svq3_get_ue_golomb(gb);
+        s->num_x        = get_interleaved_ue_golomb(gb);
+        s->num_y        = get_interleaved_ue_golomb(gb);
         if (s->ld_picture) {
-            s->lowdelay.bytes.num = svq3_get_ue_golomb(gb);
-            s->lowdelay.bytes.den = svq3_get_ue_golomb(gb);
+            s->lowdelay.bytes.num = get_interleaved_ue_golomb(gb);
+            s->lowdelay.bytes.den = get_interleaved_ue_golomb(gb);
             if (s->lowdelay.bytes.den <= 0) {
                 av_log(s->avctx,AV_LOG_ERROR,"Invalid lowdelay.bytes.den\n");
                 return AVERROR_INVALIDDATA;
             }
         } else if (s->hq_picture) {
-            s->highquality.prefix_bytes = svq3_get_ue_golomb(gb);
-            s->highquality.size_scaler  = svq3_get_ue_golomb(gb);
+            s->highquality.prefix_bytes = get_interleaved_ue_golomb(gb);
+            s->highquality.size_scaler  = get_interleaved_ue_golomb(gb);
             if (s->highquality.prefix_bytes >= INT_MAX / 8) {
                 av_log(s->avctx,AV_LOG_ERROR,"too many prefix bytes\n");
                 return AVERROR_INVALIDDATA;
@@ -1173,11 +1173,11 @@ static int dirac_unpack_idwt_params(DiracContext *s)
         if (get_bits1(gb)) {
             av_log(s->avctx,AV_LOG_DEBUG,"Low Delay: Has Custom Quantization Matrix!\n");
             /* custom quantization matrix */
-            s->lowdelay.quant[0][0] = svq3_get_ue_golomb(gb);
+            s->lowdelay.quant[0][0] = get_interleaved_ue_golomb(gb);
             for (level = 0; level < s->wavelet_depth; level++) {
-                s->lowdelay.quant[level][1] = svq3_get_ue_golomb(gb);
-                s->lowdelay.quant[level][2] = svq3_get_ue_golomb(gb);
-                s->lowdelay.quant[level][3] = svq3_get_ue_golomb(gb);
+                s->lowdelay.quant[level][1] = get_interleaved_ue_golomb(gb);
+                s->lowdelay.quant[level][2] = get_interleaved_ue_golomb(gb);
+                s->lowdelay.quant[level][3] = get_interleaved_ue_golomb(gb);
             }
         } else {
             if (s->wavelet_depth > 4) {
@@ -1388,7 +1388,7 @@ static int dirac_unpack_block_motion_data(DiracContext *s)
 
     /* [DIRAC_STD] 12.3.1 Superblock splitting modes. superblock_split_modes()
        decode superblock split modes */
-    ff_dirac_init_arith_decoder(arith, gb, svq3_get_ue_golomb(gb));     /* svq3_get_ue_golomb(gb) is the length */
+    ff_dirac_init_arith_decoder(arith, gb, get_interleaved_ue_golomb(gb));     /* get_interleaved_ue_golomb(gb) is the length */
     for (y = 0; y < s->sbheight; y++) {
         for (x = 0; x < s->sbwidth; x++) {
             unsigned int split  = dirac_get_arith_uint(arith, CTX_SB_F1, CTX_SB_DATA);
@@ -1400,13 +1400,13 @@ static int dirac_unpack_block_motion_data(DiracContext *s)
     }
 
     /* setup arith decoding */
-    ff_dirac_init_arith_decoder(arith, gb, svq3_get_ue_golomb(gb));
+    ff_dirac_init_arith_decoder(arith, gb, get_interleaved_ue_golomb(gb));
     for (i = 0; i < s->num_refs; i++) {
-        ff_dirac_init_arith_decoder(arith + 4 + 2 * i, gb, svq3_get_ue_golomb(gb));
-        ff_dirac_init_arith_decoder(arith + 5 + 2 * i, gb, svq3_get_ue_golomb(gb));
+        ff_dirac_init_arith_decoder(arith + 4 + 2 * i, gb, get_interleaved_ue_golomb(gb));
+        ff_dirac_init_arith_decoder(arith + 5 + 2 * i, gb, get_interleaved_ue_golomb(gb));
     }
     for (i = 0; i < 3; i++)
-        ff_dirac_init_arith_decoder(arith+1+i, gb, svq3_get_ue_golomb(gb));
+        ff_dirac_init_arith_decoder(arith+1+i, gb, get_interleaved_ue_golomb(gb));
 
     for (y = 0; y < s->sbheight; y++)
         for (x = 0; x < s->sbwidth; x++) {
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c
index e2ebeeb..aee4323 100644
--- a/libavcodec/dnxhdenc.c
+++ b/libavcodec/dnxhdenc.c
@@ -36,8 +36,7 @@
 #include "pixblockdsp.h"
 #include "dnxhdenc.h"
 
-
-// The largest value that will not lead to overflow for 10bit samples.
+// The largest value that will not lead to overflow for 10-bit samples.
 #define DNX10BIT_QMAT_SHIFT 18
 #define RC_VARIANCE 1 // use variance or ssd for fast rc
 #define LAMBDA_FRAC_BITS 10
@@ -761,7 +760,7 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg,
             ctx->mb_cmp[mb].mb    = mb;
         }
     } else { // 10-bit
-        int const linesize = ctx->m.linesize >> 1;
+        const int linesize = ctx->m.linesize >> 1;
         for (mb_x = 0; mb_x < ctx->m.mb_width; ++mb_x) {
             uint16_t *pix = (uint16_t *)ctx->thread[0]->src[0] +
                             ((mb_y << 4) * linesize) + (mb_x << 4);
@@ -776,7 +775,7 @@ static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg,
             for (i = 0; i < bh; ++i) {
                 for (j = 0; j < bw; ++j) {
                     // Turn 16-bit pixels into 10-bit ones.
-                    int const sample = (unsigned) pix[j] >> 6;
+                    const int sample = (unsigned) pix[j] >> 6;
                     sum   += sample;
                     sqsum += sample * sample;
                     // 2^10 * 2^10 * 16 * 16 = 2^28, which is less than INT_MAX
diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c
index 52a2c61..2edd4d5 100644
--- a/libavcodec/dpcm.c
+++ b/libavcodec/dpcm.c
@@ -1,6 +1,6 @@
 /*
  * Assorted DPCM codecs
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c
index af7276a..e4dd1b0 100644
--- a/libavcodec/dpx.c
+++ b/libavcodec/dpx.c
@@ -256,17 +256,21 @@ static int decode_frame(AVCodecContext *avctx,
         avctx->pix_fmt = AV_PIX_FMT_RGBA;
         break;
     case 50100:
-    case 51100:
     case 50101:
-    case 51101:
         avctx->pix_fmt = AV_PIX_FMT_GBRP10;
         break;
+    case 51100:
+    case 51101:
+        avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
+        break;
     case 50120:
-    case 51120:
     case 50121:
-    case 51121:
         avctx->pix_fmt = AV_PIX_FMT_GBRP12;
         break;
+    case 51120:
+    case 51121:
+        avctx->pix_fmt = AV_PIX_FMT_GBRAP12;
+        break;
     case 6161:
         avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
         break;
@@ -313,9 +317,10 @@ static int decode_frame(AVCodecContext *avctx,
     switch (bits_per_color) {
     case 10:
         for (x = 0; x < avctx->height; x++) {
-            uint16_t *dst[3] = {(uint16_t*)ptr[0],
+            uint16_t *dst[4] = {(uint16_t*)ptr[0],
                                 (uint16_t*)ptr[1],
-                                (uint16_t*)ptr[2]};
+                                (uint16_t*)ptr[2],
+                                (uint16_t*)ptr[3]};
             for (y = 0; y < avctx->width; y++) {
                 *dst[2]++ = read10in32(&buf, &rgbBuffer,
                                        &n_datum, endian);
@@ -323,21 +328,22 @@ static int decode_frame(AVCodecContext *avctx,
                                        &n_datum, endian);
                 *dst[1]++ = read10in32(&buf, &rgbBuffer,
                                        &n_datum, endian);
-                // For 10 bit, ignore alpha
                 if (elements == 4)
+                    *dst[3]++ =
                     read10in32(&buf, &rgbBuffer,
                                &n_datum, endian);
             }
             n_datum = 0;
-            for (i = 0; i < 3; i++)
+            for (i = 0; i < elements; i++)
                 ptr[i] += p->linesize[i];
         }
         break;
     case 12:
         for (x = 0; x < avctx->height; x++) {
-            uint16_t *dst[3] = {(uint16_t*)ptr[0],
+            uint16_t *dst[4] = {(uint16_t*)ptr[0],
                                 (uint16_t*)ptr[1],
-                                (uint16_t*)ptr[2]};
+                                (uint16_t*)ptr[2],
+                                (uint16_t*)ptr[3]};
             for (y = 0; y < avctx->width; y++) {
                 *dst[2] = read16(&buf, endian) >> 4;
                 dst[2]++;
@@ -345,11 +351,10 @@ static int decode_frame(AVCodecContext *avctx,
                 dst[0]++;
                 *dst[1] = read16(&buf, endian) >> 4;
                 dst[1]++;
-                // For 12 bit, ignore alpha
                 if (elements == 4)
-                    buf += 2;
+                    *dst[3]++ = read16(&buf, endian) >> 4;
             }
-            for (i = 0; i < 3; i++)
+            for (i = 0; i < elements; i++)
                 ptr[i] += p->linesize[i];
             // Jump to next aligned position
             buf += need_align;
diff --git a/libavcodec/dsd.c b/libavcodec/dsd.c
new file mode 100644
index 0000000..9104f38
--- /dev/null
+++ b/libavcodec/dsd.c
@@ -0,0 +1,86 @@
+/*
+ * Direct Stream Digital (DSD) decoder
+ * based on BSD licensed dsd2pcm by Sebastian Gesemann
+ * Copyright (c) 2009, 2011 Sebastian Gesemann. All rights reserved.
+ * Copyright (c) 2014 Peter Ross
+ *
+ * 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 "libavcodec/internal.h"
+#include "libavcodec/mathops.h"
+#include "avcodec.h"
+#include "dsd_tablegen.h"
+#include "dsd.h"
+
+static av_cold void dsd_ctables_tableinit(void)
+{
+    int t, e, m, sign;
+    double acc[CTABLES];
+    for (e = 0; e < 256; ++e) {
+        memset(acc, 0, sizeof(acc));
+        for (m = 0; m < 8; ++m) {
+            sign = (((e >> (7 - m)) & 1) * 2 - 1);
+            for (t = 0; t < CTABLES; ++t)
+                acc[t] += sign * htaps[t * 8 + m];
+        }
+        for (t = 0; t < CTABLES; ++t)
+            ctables[CTABLES - 1 - t][e] = acc[t];
+    }
+}
+
+av_cold void ff_init_dsd_data(void)
+{
+    static int done = 0;
+    if (done)
+        return;
+    dsd_ctables_tableinit();
+    done = 1;
+}
+
+void ff_dsd2pcm_translate(DSDContext* s, size_t samples, int lsbf,
+                          const unsigned char *src, ptrdiff_t src_stride,
+                          float *dst, ptrdiff_t dst_stride)
+{
+    unsigned pos, i;
+    unsigned char* p;
+    double sum;
+
+    pos = s->pos;
+
+    while (samples-- > 0) {
+        s->buf[pos] = lsbf ? ff_reverse[*src] : *src;
+        src += src_stride;
+
+        p = s->buf + ((pos - CTABLES) & FIFOMASK);
+        *p = ff_reverse[*p];
+
+        sum = 0.0;
+        for (i = 0; i < CTABLES; i++) {
+            unsigned char a = s->buf[(pos                   - i) & FIFOMASK];
+            unsigned char b = s->buf[(pos - (CTABLES*2 - 1) + i) & FIFOMASK];
+            sum += ctables[i][a] + ctables[i][b];
+        }
+
+        *dst = (float)sum;
+        dst += dst_stride;
+
+        pos = (pos + 1) & FIFOMASK;
+    }
+
+    s->pos = pos;
+}
diff --git a/libavcodec/dsd.h b/libavcodec/dsd.h
new file mode 100644
index 0000000..5ca4574
--- /dev/null
+++ b/libavcodec/dsd.h
@@ -0,0 +1,52 @@
+/*
+ * Direct Stream Digital (DSD) decoder
+ * based on BSD licensed dsd2pcm by Sebastian Gesemann
+ * Copyright (c) 2009, 2011 Sebastian Gesemann. All rights reserved.
+ * Copyright (c) 2014 Peter Ross
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_DSD_H
+#define AVCODEC_DSD_H
+
+#include "libavcodec/internal.h"
+#include "libavcodec/mathops.h"
+#include "avcodec.h"
+
+#define HTAPS   48               /** number of FIR constants */
+#define FIFOSIZE 16              /** must be a power of two */
+#define FIFOMASK (FIFOSIZE - 1)  /** bit mask for FIFO offsets */
+
+#if FIFOSIZE * 8 < HTAPS * 2
+#error "FIFOSIZE too small"
+#endif
+
+/**
+ * Per-channel buffer
+ */
+typedef struct DSDContext {
+    unsigned char buf[FIFOSIZE];
+    unsigned pos;
+} DSDContext;
+
+void ff_init_dsd_data(void);
+
+void ff_dsd2pcm_translate(DSDContext* s, size_t samples, int lsbf,
+                          const unsigned char *src, ptrdiff_t src_stride,
+                          float *dst, ptrdiff_t dst_stride);
+#endif /* AVCODEC_DSD_H */
diff --git a/libavcodec/dsd_tablegen.h b/libavcodec/dsd_tablegen.h
index 990d57a..e5da86a 100644
--- a/libavcodec/dsd_tablegen.h
+++ b/libavcodec/dsd_tablegen.h
@@ -25,6 +25,7 @@
 
 #include <stdint.h>
 #include "libavutil/attributes.h"
+#include "dsd.h"
 
 #define HTAPS   48                /** number of FIR constants */
 #define CTABLES ((HTAPS + 7) / 8) /** number of "8 MACs" lookup tables */
@@ -71,21 +72,4 @@ static const double htaps[HTAPS] = {
 };
 
 static float ctables[CTABLES][256];
-
-static av_cold void dsd_ctables_tableinit(void)
-{
-    int t, e, m, sign;
-    double acc[CTABLES];
-    for (e = 0; e < 256; ++e) {
-        memset(acc, 0, sizeof(acc));
-        for (m = 0; m < 8; ++m) {
-            sign = (((e >> (7 - m)) & 1) * 2 - 1);
-            for (t = 0; t < CTABLES; ++t)
-                acc[t] += sign * htaps[t * 8 + m];
-        }
-        for (t = 0; t < CTABLES; ++t)
-            ctables[CTABLES - 1 - t][e] = acc[t];
-    }
-}
-
 #endif /* AVCODEC_DSD_TABLEGEN_H */
diff --git a/libavcodec/dsddec.c b/libavcodec/dsddec.c
index f1dfd4b..880d691 100644
--- a/libavcodec/dsddec.c
+++ b/libavcodec/dsddec.c
@@ -29,71 +29,14 @@
 #include "libavcodec/internal.h"
 #include "libavcodec/mathops.h"
 #include "avcodec.h"
-#include "dsd_tablegen.h"
-
-#define FIFOSIZE 16              /** must be a power of two */
-#define FIFOMASK (FIFOSIZE - 1)  /** bit mask for FIFO offsets */
-
-#if FIFOSIZE * 8 < HTAPS * 2
-#error "FIFOSIZE too small"
-#endif
-
-/**
- * Per-channel buffer
- */
-typedef struct {
-    unsigned char buf[FIFOSIZE];
-    unsigned pos;
-} DSDContext;
-
-static void dsd2pcm_translate(DSDContext* s, size_t samples, int lsbf,
-                              const unsigned char *src, ptrdiff_t src_stride,
-                              float *dst, ptrdiff_t dst_stride)
-{
-    unsigned pos, i;
-    unsigned char* p;
-    double sum;
-
-    pos = s->pos;
-
-    while (samples-- > 0) {
-        s->buf[pos] = lsbf ? ff_reverse[*src] : *src;
-        src += src_stride;
-
-        p = s->buf + ((pos - CTABLES) & FIFOMASK);
-        *p = ff_reverse[*p];
-
-        sum = 0.0;
-        for (i = 0; i < CTABLES; i++) {
-            unsigned char a = s->buf[(pos                   - i) & FIFOMASK];
-            unsigned char b = s->buf[(pos - (CTABLES*2 - 1) + i) & FIFOMASK];
-            sum += ctables[i][a] + ctables[i][b];
-        }
-
-        *dst = (float)sum;
-        dst += dst_stride;
-
-        pos = (pos + 1) & FIFOMASK;
-    }
-
-    s->pos = pos;
-}
-
-static av_cold void init_static_data(void)
-{
-    static int done = 0;
-    if (done)
-        return;
-    dsd_ctables_tableinit();
-    done = 1;
-}
+#include "dsd.h"
 
 static av_cold int decode_init(AVCodecContext *avctx)
 {
     DSDContext * s;
     int i;
 
-    init_static_data();
+    ff_init_dsd_data();
 
     s = av_malloc_array(sizeof(DSDContext), avctx->channels);
     if (!s)
@@ -140,7 +83,7 @@ static int decode_frame(AVCodecContext *avctx, void *data,
 
     for (i = 0; i < avctx->channels; i++) {
         float * dst = ((float **)frame->extended_data)[i];
-        dsd2pcm_translate(&s[i], frame->nb_samples, lsbf,
+        ff_dsd2pcm_translate(&s[i], frame->nb_samples, lsbf,
             avpkt->data + i * src_next, src_stride,
             dst, 1);
     }
diff --git a/libavcodec/dss_sp.c b/libavcodec/dss_sp.c
index 7cf8489..ddea483 100644
--- a/libavcodec/dss_sp.c
+++ b/libavcodec/dss_sp.c
@@ -761,10 +761,8 @@ static int dss_sp_decode_frame(AVCodecContext *avctx, void *data,
     }
 
     frame->nb_samples = DSS_SP_SAMPLE_COUNT;
-    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n");
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
-    }
 
     out = (int16_t *)frame->data[0];
 
diff --git a/libavcodec/dstdec.c b/libavcodec/dstdec.c
new file mode 100644
index 0000000..368cb64
--- /dev/null
+++ b/libavcodec/dstdec.c
@@ -0,0 +1,374 @@
+/*
+ * Direct Stream Transfer (DST) decoder
+ * Copyright (c) 2014 Peter Ross <pross at xvid.org>
+ *
+ * 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
+ * Direct Stream Transfer (DST) decoder
+ * ISO/IEC 14496-3 Part 3 Subpart 10: Technical description of lossless coding of oversampled audio
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/intreadwrite.h"
+#include "internal.h"
+#include "get_bits.h"
+#include "avcodec.h"
+#include "golomb.h"
+#include "mathops.h"
+#include "dsd.h"
+
+#define DST_MAX_CHANNELS 6
+#define DST_MAX_ELEMENTS (2 * DST_MAX_CHANNELS)
+
+#define DSD_FS44(sample_rate) (sample_rate * 8 / 44100)
+
+#define DST_SAMPLES_PER_FRAME(sample_rate) (588 * DSD_FS44(sample_rate))
+
+static const int8_t fsets_code_pred_coeff[3][3] = {
+    {  -8 },
+    { -16,  8 },
+    {  -9, -5, 6 },
+};
+
+static const int8_t probs_code_pred_coeff[3][3] = {
+    {  -8 },
+    { -16,  8 },
+    { -24, 24, -8 },
+};
+
+typedef struct ArithCoder {
+    unsigned int a;
+    unsigned int c;
+} ArithCoder;
+
+typedef struct Table {
+    unsigned int elements;
+    unsigned int length[DST_MAX_ELEMENTS];
+    int coeff[DST_MAX_ELEMENTS][128];
+} Table;
+
+typedef struct DSTContext {
+    AVClass *class;
+
+    GetBitContext gb;
+    ArithCoder ac;
+    Table fsets, probs;
+    DECLARE_ALIGNED(64, uint8_t, status)[DST_MAX_CHANNELS][16];
+    DECLARE_ALIGNED(16, int16_t, filter)[DST_MAX_ELEMENTS][16][256];
+    DSDContext dsdctx[DST_MAX_CHANNELS];
+} DSTContext;
+
+static av_cold int decode_init(AVCodecContext *avctx)
+{
+    DSTContext *s = avctx->priv_data;
+    int i;
+
+    if (avctx->channels > DST_MAX_CHANNELS) {
+        avpriv_request_sample(avctx, "Channel count %d", avctx->channels);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
+
+    for (i = 0; i < avctx->channels; i++)
+        memset(s->dsdctx[i].buf, 0x69, sizeof(s->dsdctx[i].buf));
+
+    ff_init_dsd_data();
+
+    return 0;
+}
+
+static int read_map(GetBitContext *gb, Table *t, unsigned int map[DST_MAX_CHANNELS], int channels)
+{
+    int ch;
+    t->elements = 1;
+    map[0] = 0;
+    if (!get_bits1(gb)) {
+        for (ch = 1; ch < channels; ch++) {
+            int bits = av_log2(t->elements) + 1;
+            map[ch] = get_bits(gb, bits);
+            if (map[ch] == t->elements) {
+                t->elements++;
+                if (t->elements >= DST_MAX_ELEMENTS)
+                    return AVERROR_INVALIDDATA;
+            } else if (map[ch] > t->elements) {
+                return AVERROR_INVALIDDATA;
+            }
+        }
+    } else {
+        memset(map, 0, sizeof(*map) * DST_MAX_CHANNELS);
+    }
+    return 0;
+}
+
+static av_always_inline int get_sr_golomb_dst(GetBitContext *gb, unsigned int k)
+{
+    int v = get_ur_golomb(gb, k, get_bits_left(gb), 0);
+    if (v && get_bits1(gb))
+        v = -v;
+    return v;
+}
+
+static void read_uncoded_coeff(GetBitContext *gb, int *dst, unsigned int elements,
+                               int coeff_bits, int is_signed, int offset)
+{
+    int i;
+
+    for (i = 0; i < elements; i++) {
+        dst[i] = (is_signed ? get_sbits(gb, coeff_bits) : get_bits(gb, coeff_bits)) + offset;
+    }
+}
+
+static int read_table(GetBitContext *gb, Table *t, const int8_t code_pred_coeff[3][3],
+                      int length_bits, int coeff_bits, int is_signed, int offset)
+{
+    unsigned int i, j, k;
+    for (i = 0; i < t->elements; i++) {
+        t->length[i] = get_bits(gb, length_bits) + 1;
+        if (!get_bits1(gb)) {
+            read_uncoded_coeff(gb, t->coeff[i], t->length[i], coeff_bits, is_signed, offset);
+        } else {
+            int method = get_bits(gb, 2), lsb_size;
+            if (method == 3)
+                return AVERROR_INVALIDDATA;
+
+            read_uncoded_coeff(gb, t->coeff[i], method + 1, coeff_bits, is_signed, offset);
+
+            lsb_size  = get_bits(gb, 3);
+            for (j = method + 1; j < t->length[i]; j++) {
+                int c, x = 0;
+                for (k = 0; k < method + 1; k++)
+                    x += code_pred_coeff[method][k] * t->coeff[i][j - k - 1];
+                c = get_sr_golomb_dst(gb, lsb_size);
+                if (x >= 0)
+                    c -= (x + 4) / 8;
+                else
+                    c += (-x + 3) / 8;
+                t->coeff[i][j] = c;
+            }
+        }
+    }
+    return 0;
+}
+
+static void ac_init(ArithCoder *ac, GetBitContext *gb)
+{
+    ac->a = 4095;
+    ac->c = get_bits(gb, 12);
+}
+
+static av_always_inline void ac_get(ArithCoder *ac, GetBitContext *gb, int p, int *e)
+{
+    unsigned int k = (ac->a >> 8) | ((ac->a >> 7) & 1);
+    unsigned int q = k * p;
+    unsigned int a_q = ac->a - q;
+
+    *e = ac->c < a_q;
+    if (*e) {
+        ac->a  = a_q;
+    } else {
+        ac->a  = q;
+        ac->c -= a_q;
+    }
+
+    if (ac->a < 2048) {
+        int n = 11 - av_log2(ac->a);
+        ac->a <<= n;
+        ac->c = (ac->c << n) | get_bits(gb, n);
+    }
+}
+
+static uint8_t prob_dst_x_bit(int c)
+{
+    return (ff_reverse[c & 127] >> 1) + 1;
+}
+
+static void build_filter(int16_t table[DST_MAX_ELEMENTS][16][256], const Table *fsets)
+{
+    int i, j, k, l;
+
+    for (i = 0; i < fsets->elements; i++) {
+        int length = fsets->length[i];
+
+        for (j = 0; j < 16; j++) {
+            int total = av_clip(length - j * 8, 0, 8);
+
+            for (k = 0; k < 256; k++) {
+                int v = 0;
+
+                for (l = 0; l < total; l++)
+                    v += (((k >> l) & 1) * 2 - 1) * fsets->coeff[i][j * 8 + l];
+                table[i][j][k] = v;
+            }
+        }
+    }
+}
+
+static int decode_frame(AVCodecContext *avctx, void *data,
+                        int *got_frame_ptr, AVPacket *avpkt)
+{
+    unsigned samples_per_frame = DST_SAMPLES_PER_FRAME(avctx->sample_rate);
+    unsigned map_ch_to_felem[DST_MAX_CHANNELS];
+    unsigned map_ch_to_pelem[DST_MAX_CHANNELS];
+    unsigned i, ch, same_map, dst_x_bit;
+    unsigned half_prob[DST_MAX_CHANNELS];
+    const int channels = avctx->channels;
+    DSTContext *s = avctx->priv_data;
+    GetBitContext *gb = &s->gb;
+    ArithCoder *ac = &s->ac;
+    AVFrame *frame = data;
+    uint8_t *dsd;
+    float *pcm;
+    int ret;
+
+    if (avpkt->size <= 1)
+        return AVERROR_INVALIDDATA;
+
+    frame->nb_samples = samples_per_frame / 8;
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+        return ret;
+    dsd = frame->data[0];
+    pcm = (float *)frame->data[0];
+
+    if ((ret = init_get_bits8(gb, avpkt->data, avpkt->size)) < 0)
+        return ret;
+
+    if (!get_bits1(gb)) {
+        skip_bits1(gb);
+        if (get_bits(gb, 6))
+            return AVERROR_INVALIDDATA;
+        memcpy(frame->data[0], avpkt->data + 1, FFMIN(avpkt->size - 1, frame->nb_samples * avctx->channels));
+        goto dsd;
+    }
+
+    /* Segmentation (10.4, 10.5, 10.6) */
+
+    if (!get_bits1(gb)) {
+        avpriv_request_sample(avctx, "Not Same Segmentation");
+        return AVERROR_PATCHWELCOME;
+    }
+
+    if (!get_bits1(gb)) {
+        avpriv_request_sample(avctx, "Not Same Segmentation For All Channels");
+        return AVERROR_PATCHWELCOME;
+    }
+
+    if (!get_bits1(gb)) {
+        avpriv_request_sample(avctx, "Not End Of Channel Segmentation");
+        return AVERROR_PATCHWELCOME;
+    }
+
+    /* Mapping (10.7, 10.8, 10.9) */
+
+    same_map = get_bits1(gb);
+
+    if ((ret = read_map(gb, &s->fsets, map_ch_to_felem, avctx->channels)) < 0)
+        return ret;
+
+    if (same_map) {
+        s->probs.elements = s->fsets.elements;
+        memcpy(map_ch_to_pelem, map_ch_to_felem, sizeof(map_ch_to_felem));
+    } else {
+        avpriv_request_sample(avctx, "Not Same Mapping");
+        if ((ret = read_map(gb, &s->probs, map_ch_to_pelem, avctx->channels)) < 0)
+            return ret;
+    }
+
+    /* Half Probability (10.10) */
+
+    for (ch = 0; ch < avctx->channels; ch++)
+        half_prob[ch] = get_bits1(gb);
+
+    /* Filter Coef Sets (10.12) */
+
+    read_table(gb, &s->fsets, fsets_code_pred_coeff, 7, 9, 1, 0);
+
+    /* Probability Tables (10.13) */
+
+    read_table(gb, &s->probs, probs_code_pred_coeff, 6, 7, 0, 1);
+
+    /* Arithmetic Coded Data (10.11) */
+
+    if (get_bits1(gb))
+        return AVERROR_INVALIDDATA;
+    ac_init(ac, gb);
+
+    build_filter(s->filter, &s->fsets);
+
+    memset(s->status, 0xAA, sizeof(s->status));
+    memset(dsd, 0, frame->nb_samples * 4 * avctx->channels);
+
+    ac_get(ac, gb, prob_dst_x_bit(s->fsets.coeff[0][0]), &dst_x_bit);
+
+    for (i = 0; i < samples_per_frame; i++) {
+        for (ch = 0; ch < channels; ch++) {
+            const unsigned felem = map_ch_to_felem[ch];
+            int16_t (*filter)[256] = s->filter[felem];
+            uint8_t *status = s->status[ch];
+            int prob, residual, v;
+
+#define F(x) filter[(x)][status[(x)]]
+            const int16_t predict = F( 0) + F( 1) + F( 2) + F( 3) +
+                                    F( 4) + F( 5) + F( 6) + F( 7) +
+                                    F( 8) + F( 9) + F(10) + F(11) +
+                                    F(12) + F(13) + F(14) + F(15);
+#undef F
+
+            if (!half_prob[ch] || i >= s->fsets.length[felem]) {
+                unsigned pelem = map_ch_to_pelem[ch];
+                unsigned index = FFABS(predict) >> 3;
+                prob = s->probs.coeff[pelem][FFMIN(index, s->probs.length[pelem] - 1)];
+            } else {
+                prob = 128;
+            }
+
+            ac_get(ac, gb, prob, &residual);
+            v = ((predict >> 15) ^ residual) & 1;
+            dsd[((i >> 3) * channels + ch) << 2] |= v << (7 - (i & 0x7 ));
+
+            AV_WN64A(status + 8, (AV_RN64A(status + 8) << 1) | ((AV_RN64A(status) >> 63) & 1));
+            AV_WN64A(status, (AV_RN64A(status) << 1) | v);
+        }
+    }
+
+dsd:
+    for (i = 0; i < avctx->channels; i++) {
+        ff_dsd2pcm_translate(&s->dsdctx[i], frame->nb_samples, 0,
+                             frame->data[0] + i * 4,
+                             avctx->channels * 4, pcm + i, avctx->channels);
+    }
+
+    *got_frame_ptr = 1;
+
+    return avpkt->size;
+}
+
+AVCodec ff_dst_decoder = {
+    .name           = "dst",
+    .long_name      = NULL_IF_CONFIG_SMALL("DST (Digital Stream Transfer)"),
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = AV_CODEC_ID_DST,
+    .priv_data_size = sizeof(DSTContext),
+    .init           = decode_init,
+    .decode         = decode_frame,
+    .capabilities   = AV_CODEC_CAP_DR1,
+    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
+                                                      AV_SAMPLE_FMT_NONE },
+};
diff --git a/libavcodec/dump_extradata_bsf.c b/libavcodec/dump_extradata_bsf.c
index 08c4227..fa7bc86 100644
--- a/libavcodec/dump_extradata_bsf.c
+++ b/libavcodec/dump_extradata_bsf.c
@@ -21,34 +21,83 @@
 #include <string.h>
 
 #include "avcodec.h"
+#include "bsf.h"
+
+#include "libavutil/log.h"
 #include "libavutil/mem.h"
+#include "libavutil/opt.h"
+
+enum DumpFreq {
+    DUMP_FREQ_KEYFRAME,
+    DUMP_FREQ_ALL,
+};
+
+typedef struct DumpExtradataContext {
+    const AVClass *class;
+    int freq;
+} DumpExtradataContext;
+
+static int dump_extradata(AVBSFContext *ctx, AVPacket *out)
+{
+    DumpExtradataContext *s = ctx->priv_data;
+    AVPacket *in;
+    int ret = 0;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    if (ctx->par_in->extradata &&
+        (s->freq == DUMP_FREQ_ALL ||
+         (s->freq == DUMP_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY))) {
+        if (in->size >= INT_MAX - ctx->par_in->extradata_size) {
+            ret = AVERROR(ERANGE);
+            goto fail;
+        }
 
+        ret = av_new_packet(out, in->size + ctx->par_in->extradata_size);
+        if (ret < 0)
+            goto fail;
 
-static int dump_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    int cmd= args ? *args : 0;
-    /* cast to avoid warning about discarding qualifiers */
-    if(avctx->extradata){
-        if(  (keyframe && (avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER) && cmd == 'a')
-           ||(keyframe && (cmd=='k' || !cmd))
-           ||(cmd=='e')
-            /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){
-            int size= buf_size + avctx->extradata_size;
-            *poutbuf_size= size;
-            *poutbuf= av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!*poutbuf)
-                return AVERROR(ENOMEM);
-
-            memcpy(*poutbuf, avctx->extradata, avctx->extradata_size);
-            memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-            return 1;
+        ret = av_packet_copy_props(out, in);
+        if (ret < 0) {
+            av_packet_unref(out);
+            goto fail;
         }
+
+        memcpy(out->data, ctx->par_in->extradata, ctx->par_in->extradata_size);
+        memcpy(out->data + ctx->par_in->extradata_size, in->data, in->size);
+    } else {
+        av_packet_move_ref(out, in);
     }
-    return 0;
+
+fail:
+    av_packet_free(&in);
+
+    return ret;
 }
 
-AVBitStreamFilter ff_dump_extradata_bsf={
-    .name   = "dump_extra",
-    .filter = dump_extradata,
+#define OFFSET(x) offsetof(DumpExtradataContext, x)
+static const AVOption options[] = {
+    { "freq", "When do dump extradata", OFFSET(freq), AV_OPT_TYPE_INT,
+        { .i64 = DUMP_FREQ_KEYFRAME }, DUMP_FREQ_KEYFRAME, DUMP_FREQ_ALL, 0, "freq" },
+        { "k",        NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .unit = "freq" },
+        { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_KEYFRAME }, .unit = "freq" },
+        { "e",        NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL      }, .unit = "freq" },
+        { "all",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = DUMP_FREQ_ALL      }, .unit = "freq" },
+    { NULL },
+};
+
+static const AVClass dump_extradata_class = {
+    .class_name = "dump_extradata bsf",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_MAJOR,
+};
+
+const AVBitStreamFilter ff_dump_extradata_bsf = {
+    .name           = "dump_extra",
+    .priv_data_size = sizeof(DumpExtradataContext),
+    .priv_class     = &dump_extradata_class,
+    .filter         = dump_extradata,
 };
diff --git a/libavcodec/dv_tablegen.c b/libavcodec/dv_tablegen.c
index 2579341..d032101 100644
--- a/libavcodec/dv_tablegen.c
+++ b/libavcodec/dv_tablegen.c
@@ -27,7 +27,7 @@
 #include <inttypes.h>
 
 WRITE_1D_FUNC_ARGV(dv_vlc_pair, 7,
-                   "{0x%"PRIx32", %"PRId8"}", data[i].vlc, data[i].size)
+                   "{0x%"PRIx32", %"PRIu32"}", data[i].vlc, data[i].size)
 WRITE_2D_FUNC(dv_vlc_pair)
 
 int main(void)
diff --git a/libavcodec/dvaudiodec.c b/libavcodec/dvaudiodec.c
index faa9e5f..5aa2a95 100644
--- a/libavcodec/dvaudiodec.c
+++ b/libavcodec/dvaudiodec.c
@@ -52,7 +52,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
     }
 
     s->is_pal = s->block_size == 8640;
-    s->is_12bit = avctx->bits_per_raw_sample == 12;
+    s->is_12bit = avctx->bits_per_coded_sample == 12;
     avctx->sample_fmt = AV_SAMPLE_FMT_S16;
     avctx->channel_layout = AV_CH_LAYOUT_STEREO;
 
diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c
index a4663d9..e9f4765 100644
--- a/libavcodec/dvbsubdec.c
+++ b/libavcodec/dvbsubdec.c
@@ -827,7 +827,7 @@ static int save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_ou
     AVSubtitleRect *rect;
     DVBSubCLUT *clut;
     uint32_t *clut_table;
-    int i,j;
+    int i;
     int offset_x=0, offset_y=0;
     int ret = 0;
 
@@ -924,10 +924,13 @@ static int save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_ou
 
 #if FF_API_AVPICTURE
 FF_DISABLE_DEPRECATION_WARNINGS
+{
+            int j;
             for (j = 0; j < 4; j++) {
                 rect->pict.data[j] = rect->data[j];
                 rect->pict.linesize[j] = rect->linesize[j];
             }
+}
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
diff --git a/libavcodec/dvbtxt.h b/libavcodec/dvbtxt.h
new file mode 100644
index 0000000..ff88fcf
--- /dev/null
+++ b/libavcodec/dvbtxt.h
@@ -0,0 +1,41 @@
+/*
+ * DVB teletext common functions.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_DVBTXT_H
+#define AVCODEC_DVBTXT_H
+
+#include "libavutil/attributes.h"
+
+/* Returns true if data identifier matches a teletext stream according to EN
+ * 301 775 section 4.4.2 */
+static av_always_inline int ff_data_identifier_is_teletext(int data_identifier)
+{
+    return (data_identifier >= 0x10 && data_identifier <= 0x1F ||
+            data_identifier >= 0x99 && data_identifier <= 0x9B);
+}
+
+/* Returns true if data unit id matches EBU teletext data according to
+ * EN 301 775 section 4.4.2 */
+static av_always_inline int ff_data_unit_id_is_teletext(int data_unit_id)
+{
+    return (data_unit_id == 0x02 || data_unit_id == 0x03);
+}
+
+#endif /* AVCODEC_DVBTXT_H */
diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index 2cf57ad..f68df86 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -158,9 +158,15 @@ int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
                                                  ff_dxva2_get_surface(frame),
                                                  NULL);
 #endif
-        if (hr == E_PENDING)
-            av_usleep(2000);
-    } while (hr == E_PENDING && ++runs < 50);
+        if (hr != E_PENDING || ++runs > 50)
+            break;
+#if CONFIG_D3D11VA
+        if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
+            if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE)
+                ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex);
+#endif
+        av_usleep(2000);
+    } while(1);
 
     if (FAILED(hr)) {
         av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%lx\n", hr);
diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c
index 61cce3a..84a8e6c 100644
--- a/libavcodec/dxva2_h264.c
+++ b/libavcodec/dxva2_h264.c
@@ -1,5 +1,5 @@
 /*
- * DXVA2 H264 HW acceleration.
+ * DXVA2 H.264 HW acceleration.
  *
  * copyright (c) 2009 Laurent Aimar
  *
@@ -20,6 +20,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/avassert.h"
+
 #include "h264.h"
 #include "h264data.h"
 #include "mpegutils.h"
@@ -50,6 +52,8 @@ static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *
                                     DXVA_PicParams_H264 *pp)
 {
     const H264Picture *current_picture = h->cur_pic_ptr;
+    const SPS *sps = h->ps.sps;
+    const PPS *pps = h->ps.pps;
     int i, j;
 
     memset(pp, 0, sizeof(*pp));
@@ -94,30 +98,30 @@ static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *
 
     pp->wFrameWidthInMbsMinus1        = h->mb_width  - 1;
     pp->wFrameHeightInMbsMinus1       = h->mb_height - 1;
-    pp->num_ref_frames                = h->sps.ref_frame_count;
+    pp->num_ref_frames                = sps->ref_frame_count;
 
     pp->wBitFields                    = ((h->picture_structure != PICT_FRAME) <<  0) |
-                                        ((h->sps.mb_aff &&
+                                        ((sps->mb_aff &&
                                         (h->picture_structure == PICT_FRAME)) <<  1) |
-                                        (h->sps.residual_color_transform_flag <<  2) |
+                                        (sps->residual_color_transform_flag   <<  2) |
                                         /* sp_for_switch_flag (not implemented by FFmpeg) */
                                         (0                                    <<  3) |
-                                        (h->sps.chroma_format_idc             <<  4) |
+                                        (sps->chroma_format_idc               <<  4) |
                                         ((h->nal_ref_idc != 0)                <<  6) |
-                                        (h->pps.constrained_intra_pred        <<  7) |
-                                        (h->pps.weighted_pred                 <<  8) |
-                                        (h->pps.weighted_bipred_idc           <<  9) |
+                                        (pps->constrained_intra_pred          <<  7) |
+                                        (pps->weighted_pred                   <<  8) |
+                                        (pps->weighted_bipred_idc             <<  9) |
                                         /* MbsConsecutiveFlag */
                                         (1                                    << 11) |
-                                        (h->sps.frame_mbs_only_flag           << 12) |
-                                        (h->pps.transform_8x8_mode            << 13) |
-                                        ((h->sps.level_idc >= 31)             << 14) |
+                                        (sps->frame_mbs_only_flag             << 12) |
+                                        (pps->transform_8x8_mode              << 13) |
+                                        ((sps->level_idc >= 31)               << 14) |
                                         /* IntraPicFlag (Modified if we detect a non
                                          * intra slice in dxva2_h264_decode_slice) */
                                         (1                                    << 15);
 
-    pp->bit_depth_luma_minus8         = h->sps.bit_depth_luma - 8;
-    pp->bit_depth_chroma_minus8       = h->sps.bit_depth_chroma - 8;
+    pp->bit_depth_luma_minus8         = sps->bit_depth_luma - 8;
+    pp->bit_depth_chroma_minus8       = sps->bit_depth_chroma - 8;
     if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG)
         pp->Reserved16Bits            = 0;
     else if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
@@ -133,28 +137,28 @@ static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *
     if ((h->picture_structure & PICT_BOTTOM_FIELD) &&
         current_picture->field_poc[1] != INT_MAX)
         pp->CurrFieldOrderCnt[1] = current_picture->field_poc[1];
-    pp->pic_init_qs_minus26           = h->pps.init_qs - 26;
-    pp->chroma_qp_index_offset        = h->pps.chroma_qp_index_offset[0];
-    pp->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1];
+    pp->pic_init_qs_minus26           = pps->init_qs - 26;
+    pp->chroma_qp_index_offset        = pps->chroma_qp_index_offset[0];
+    pp->second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1];
     pp->ContinuationFlag              = 1;
-    pp->pic_init_qp_minus26           = h->pps.init_qp - 26;
-    pp->num_ref_idx_l0_active_minus1  = h->pps.ref_count[0] - 1;
-    pp->num_ref_idx_l1_active_minus1  = h->pps.ref_count[1] - 1;
+    pp->pic_init_qp_minus26           = pps->init_qp - 26;
+    pp->num_ref_idx_l0_active_minus1  = pps->ref_count[0] - 1;
+    pp->num_ref_idx_l1_active_minus1  = pps->ref_count[1] - 1;
     pp->Reserved8BitsA                = 0;
-    pp->frame_num                     = h->frame_num;
-    pp->log2_max_frame_num_minus4     = h->sps.log2_max_frame_num - 4;
-    pp->pic_order_cnt_type            = h->sps.poc_type;
-    if (h->sps.poc_type == 0)
-        pp->log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4;
-    else if (h->sps.poc_type == 1)
-        pp->delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag;
-    pp->direct_8x8_inference_flag     = h->sps.direct_8x8_inference_flag;
-    pp->entropy_coding_mode_flag      = h->pps.cabac;
-    pp->pic_order_present_flag        = h->pps.pic_order_present;
-    pp->num_slice_groups_minus1       = h->pps.slice_group_count - 1;
-    pp->slice_group_map_type          = h->pps.mb_slice_group_map_type;
-    pp->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
-    pp->redundant_pic_cnt_present_flag= h->pps.redundant_pic_cnt_present;
+    pp->frame_num                     = h->poc.frame_num;
+    pp->log2_max_frame_num_minus4     = sps->log2_max_frame_num - 4;
+    pp->pic_order_cnt_type            = sps->poc_type;
+    if (sps->poc_type == 0)
+        pp->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4;
+    else if (sps->poc_type == 1)
+        pp->delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag;
+    pp->direct_8x8_inference_flag     = sps->direct_8x8_inference_flag;
+    pp->entropy_coding_mode_flag      = pps->cabac;
+    pp->pic_order_present_flag        = pps->pic_order_present;
+    pp->num_slice_groups_minus1       = pps->slice_group_count - 1;
+    pp->slice_group_map_type          = pps->mb_slice_group_map_type;
+    pp->deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present;
+    pp->redundant_pic_cnt_present_flag= pps->redundant_pic_cnt_present;
     pp->Reserved8BitsB                = 0;
     pp->slice_group_change_rate_minus1= 0;  /* XXX not implemented by FFmpeg */
     //pp->SliceGroupMap[810];               /* XXX not implemented by FFmpeg */
@@ -162,25 +166,26 @@ static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *
 
 static void fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm)
 {
+    const PPS *pps = h->ps.pps;
     unsigned i, j;
     memset(qm, 0, sizeof(*qm));
     if (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) {
         for (i = 0; i < 6; i++)
             for (j = 0; j < 16; j++)
-                qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][j];
+                qm->bScalingLists4x4[i][j] = pps->scaling_matrix4[i][j];
 
         for (i = 0; i < 64; i++) {
-            qm->bScalingLists8x8[0][i] = h->pps.scaling_matrix8[0][i];
-            qm->bScalingLists8x8[1][i] = h->pps.scaling_matrix8[3][i];
+            qm->bScalingLists8x8[0][i] = pps->scaling_matrix8[0][i];
+            qm->bScalingLists8x8[1][i] = pps->scaling_matrix8[3][i];
         }
     } else {
         for (i = 0; i < 6; i++)
             for (j = 0; j < 16; j++)
-                qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][zigzag_scan[j]];
+                qm->bScalingLists4x4[i][j] = pps->scaling_matrix4[i][ff_zigzag_scan[j]];
 
         for (i = 0; i < 64; i++) {
-            qm->bScalingLists8x8[0][i] = h->pps.scaling_matrix8[0][ff_zigzag_direct[i]];
-            qm->bScalingLists8x8[1][i] = h->pps.scaling_matrix8[3][ff_zigzag_direct[i]];
+            qm->bScalingLists8x8[0][i] = pps->scaling_matrix8[0][ff_zigzag_direct[i]];
+            qm->bScalingLists8x8[1][i] = pps->scaling_matrix8[3][ff_zigzag_direct[i]];
         }
     }
 }
@@ -226,12 +231,12 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
 
     slice->first_mb_in_slice     = (sl->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + sl->mb_x;
     slice->NumMbsForSlice        = 0; /* XXX it is set once we have all slices */
-    slice->BitOffsetToSliceData  = get_bits_count(&sl->gb);
+    slice->BitOffsetToSliceData  = get_bits_count(&sl->gb) - 8;
     slice->slice_type            = ff_h264_get_slice_type(sl);
     if (sl->slice_type_fixed)
         slice->slice_type += 5;
-    slice->luma_log2_weight_denom       = sl->luma_log2_weight_denom;
-    slice->chroma_log2_weight_denom     = sl->chroma_log2_weight_denom;
+    slice->luma_log2_weight_denom       = sl->pwt.luma_log2_weight_denom;
+    slice->chroma_log2_weight_denom     = sl->pwt.chroma_log2_weight_denom;
     if (sl->list_count > 0)
         slice->num_ref_idx_l0_active_minus1 = sl->ref_count[0] - 1;
     if (sl->list_count > 1)
@@ -255,15 +260,15 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
                                    sl->ref_list[list][i].reference == PICT_BOTTOM_FIELD);
                 for (plane = 0; plane < 3; plane++) {
                     int w, o;
-                    if (plane == 0 && sl->luma_weight_flag[list]) {
-                        w = sl->luma_weight[i][list][0];
-                        o = sl->luma_weight[i][list][1];
-                    } else if (plane >= 1 && sl->chroma_weight_flag[list]) {
-                        w = sl->chroma_weight[i][list][plane-1][0];
-                        o = sl->chroma_weight[i][list][plane-1][1];
+                    if (plane == 0 && sl->pwt.luma_weight_flag[list]) {
+                        w = sl->pwt.luma_weight[i][list][0];
+                        o = sl->pwt.luma_weight[i][list][1];
+                    } else if (plane >= 1 && sl->pwt.chroma_weight_flag[list]) {
+                        w = sl->pwt.chroma_weight[i][list][plane-1][0];
+                        o = sl->pwt.chroma_weight[i][list][plane-1][1];
                     } else {
-                        w = 1 << (plane == 0 ? sl->luma_log2_weight_denom :
-                                               sl->chroma_log2_weight_denom);
+                        w = 1 << (plane == 0 ? sl->pwt.luma_log2_weight_denom :
+                                               sl->pwt.chroma_log2_weight_denom);
                         o = 0;
                     }
                     slice->Weights[list][i][plane][0] = w;
@@ -280,11 +285,11 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
         }
     }
     slice->slice_qs_delta    = 0; /* XXX not implemented by FFmpeg */
-    slice->slice_qp_delta    = sl->qscale - h->pps.init_qp;
+    slice->slice_qp_delta    = sl->qscale - h->ps.pps->init_qp;
     slice->redundant_pic_cnt = sl->redundant_pic_count;
     if (sl->slice_type == AV_PICTURE_TYPE_B)
         slice->direct_spatial_mv_pred_flag = sl->direct_spatial_mv_pred;
-    slice->cabac_init_idc = h->pps.cabac ? sl->cabac_init_idc : 0;
+    slice->cabac_init_idc = h->ps.pps->cabac ? sl->cabac_init_idc : 0;
     if (sl->deblocking_filter < 2)
         slice->disable_deblocking_filter_idc = 1 - sl->deblocking_filter;
     else
@@ -405,6 +410,8 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
         dsc11->NumMBsInBuffer       = mb_count;
 
         type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
+
+        av_assert0((dsc11->DataSize & 127) == 0);
     }
 #endif
 #if CONFIG_DXVA2
@@ -416,6 +423,8 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
         dsc2->NumMBsInBuffer       = mb_count;
 
         type = DXVA2_SliceControlBufferType;
+
+        av_assert0((dsc2->DataSize & 127) == 0);
     }
 #endif
 
@@ -426,7 +435,6 @@ static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
         slice_data = ctx_pic->slice_long;
         slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_long);
     }
-    assert((bs->DataSize & 127) == 0);
     return ff_dxva2_commit_buffer(avctx, ctx, sc,
                                   type,
                                   slice_data, slice_size, mb_count);
diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c
index ef815af..47e5aa6 100644
--- a/libavcodec/eac3dec.c
+++ b/libavcodec/eac3dec.c
@@ -305,7 +305,10 @@ static int ff_eac3_parse_header(AC3DecodeContext *s)
        application can select from. each independent stream can also contain
        dependent streams which are used to add or replace channels. */
     if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) {
-        avpriv_request_sample(s->avctx, "Dependent substream decoding");
+        if (!s->eac3_frame_dependent_found) {
+            s->eac3_frame_dependent_found = 1;
+            avpriv_request_sample(s->avctx, "Dependent substream decoding");
+        }
         return AAC_AC3_PARSE_ERROR_FRAME_TYPE;
     } else if (s->frame_type == EAC3_FRAME_TYPE_RESERVED) {
         av_log(s->avctx, AV_LOG_ERROR, "Reserved frame type\n");
@@ -317,7 +320,10 @@ static int ff_eac3_parse_header(AC3DecodeContext *s)
        associated to an independent stream have matching substream id's. */
     if (s->substreamid) {
         /* only decode substream with id=0. skip any additional substreams. */
-        avpriv_request_sample(s->avctx, "Additional substreams");
+        if (!s->eac3_subsbtreamid_found) {
+            s->eac3_subsbtreamid_found = 1;
+            avpriv_request_sample(s->avctx, "Additional substreams");
+        }
         return AAC_AC3_PARSE_ERROR_FRAME_TYPE;
     }
 
diff --git a/libavcodec/eamad.c b/libavcodec/eamad.c
index 4e202f9..bb0f005 100644
--- a/libavcodec/eamad.c
+++ b/libavcodec/eamad.c
@@ -41,8 +41,8 @@
 #include "mpeg12vlc.h"
 
 #define EA_PREAMBLE_SIZE    8
-#define MADk_TAG MKTAG('M', 'A', 'D', 'k')    /* MAD i-frame */
-#define MADm_TAG MKTAG('M', 'A', 'D', 'm')    /* MAD p-frame */
+#define MADk_TAG MKTAG('M', 'A', 'D', 'k')    /* MAD I-frame */
+#define MADm_TAG MKTAG('M', 'A', 'D', 'm')    /* MAD P-frame */
 #define MADe_TAG MKTAG('M', 'A', 'D', 'e')    /* MAD lqp-frame */
 
 typedef struct MadContext {
diff --git a/libavcodec/eatqi.c b/libavcodec/eatqi.c
index 2423e21..8fd5cdb 100644
--- a/libavcodec/eatqi.c
+++ b/libavcodec/eatqi.c
@@ -35,69 +35,89 @@
 #include "idctdsp.h"
 #include "internal.h"
 #include "mpeg12.h"
-#include "mpegvideo.h"
 
 typedef struct TqiContext {
-    MpegEncContext s;
+    AVCodecContext *avctx;
+    GetBitContext gb;
+    BlockDSPContext bdsp;
     BswapDSPContext bsdsp;
+    IDCTDSPContext idsp;
+    ScanTable intra_scantable;
+
     void *bitstream_buf;
     unsigned int bitstream_buf_size;
+
+    int mb_x, mb_y;
+    uint16_t intra_matrix[64];
+    int last_dc[3];
+
     DECLARE_ALIGNED(16, int16_t, block)[6][64];
 } TqiContext;
 
 static av_cold int tqi_decode_init(AVCodecContext *avctx)
 {
     TqiContext *t = avctx->priv_data;
-    MpegEncContext *s = &t->s;
-    s->avctx = avctx;
-    ff_blockdsp_init(&s->bdsp, avctx);
+
+    ff_blockdsp_init(&t->bdsp, avctx);
     ff_bswapdsp_init(&t->bsdsp);
-    ff_idctdsp_init(&s->idsp, avctx);
-    ff_init_scantable_permutation(s->idsp.idct_permutation, FF_IDCT_PERM_NONE);
-    ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct);
-    s->qscale = 1;
+    ff_idctdsp_init(&t->idsp, avctx);
+    ff_init_scantable_permutation(t->idsp.idct_permutation, FF_IDCT_PERM_NONE);
+    ff_init_scantable(t->idsp.idct_permutation, &t->intra_scantable, ff_zigzag_direct);
+
     avctx->framerate = (AVRational){ 15, 1 };
     avctx->pix_fmt = AV_PIX_FMT_YUV420P;
     ff_mpeg12_init_vlcs();
     return 0;
 }
 
-static int tqi_decode_mb(MpegEncContext *s, int16_t (*block)[64])
+static int tqi_decode_mb(TqiContext *t, int16_t (*block)[64])
 {
     int n;
-    s->bdsp.clear_blocks(block[0]);
-    for (n=0; n<6; n++)
-        if (ff_mpeg1_decode_block_intra(s, block[n], n) < 0)
+
+    t->bdsp.clear_blocks(block[0]);
+    for (n = 0; n < 6; n++) {
+        int ret = ff_mpeg1_decode_block_intra(&t->gb,
+                                              t->intra_matrix,
+                                              t->intra_scantable.permutated,
+                                              t->last_dc, block[n], n, 1);
+        if (ret < 0) {
+            av_log(t->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n",
+                   t->mb_x, t->mb_y);
             return -1;
+        }
+    }
 
     return 0;
 }
 
-static inline void tqi_idct_put(TqiContext *t, AVFrame *frame, int16_t (*block)[64])
+static inline void tqi_idct_put(AVCodecContext *avctx, AVFrame *frame,
+                                int16_t (*block)[64])
 {
-    MpegEncContext *s = &t->s;
+    TqiContext *t = avctx->priv_data;
     int linesize = frame->linesize[0];
-    uint8_t *dest_y  = frame->data[0] + (s->mb_y * 16* linesize            ) + s->mb_x * 16;
-    uint8_t *dest_cb = frame->data[1] + (s->mb_y * 8 * frame->linesize[1]) + s->mb_x * 8;
-    uint8_t *dest_cr = frame->data[2] + (s->mb_y * 8 * frame->linesize[2]) + s->mb_x * 8;
+    uint8_t *dest_y  = frame->data[0] + t->mb_y * 16 * linesize           + t->mb_x * 16;
+    uint8_t *dest_cb = frame->data[1] + t->mb_y *  8 * frame->linesize[1] + t->mb_x *  8;
+    uint8_t *dest_cr = frame->data[2] + t->mb_y *  8 * frame->linesize[2] + t->mb_x *  8;
 
     ff_ea_idct_put_c(dest_y                 , linesize, block[0]);
     ff_ea_idct_put_c(dest_y              + 8, linesize, block[1]);
     ff_ea_idct_put_c(dest_y + 8*linesize    , linesize, block[2]);
     ff_ea_idct_put_c(dest_y + 8*linesize + 8, linesize, block[3]);
-    if(!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
+
+    if (!(avctx->flags & AV_CODEC_FLAG_GRAY)) {
         ff_ea_idct_put_c(dest_cb, frame->linesize[1], block[4]);
         ff_ea_idct_put_c(dest_cr, frame->linesize[2], block[5]);
     }
 }
 
-static void tqi_calculate_qtable(MpegEncContext *s, int quant)
+static void tqi_calculate_qtable(TqiContext *t, int quant)
 {
     const int qscale = (215 - 2*quant)*5;
     int i;
-    s->intra_matrix[0] = (ff_inv_aanscales[0]*ff_mpeg1_default_intra_matrix[0])>>11;
+
+    t->intra_matrix[0] = (ff_inv_aanscales[0] * ff_mpeg1_default_intra_matrix[0]) >> 11;
     for(i=1; i<64; i++)
-        s->intra_matrix[i] = (ff_inv_aanscales[i]*ff_mpeg1_default_intra_matrix[i]*qscale + 32)>>14;
+        t->intra_matrix[i] = (ff_inv_aanscales[i] * ff_mpeg1_default_intra_matrix[i] * qscale + 32) >> 14;
 }
 
 static int tqi_decode_frame(AVCodecContext *avctx,
@@ -108,16 +128,17 @@ static int tqi_decode_frame(AVCodecContext *avctx,
     int buf_size = avpkt->size;
     const uint8_t *buf_end = buf+buf_size;
     TqiContext *t = avctx->priv_data;
-    MpegEncContext *s = &t->s;
     AVFrame *frame = data;
-    int ret;
+    int ret, w, h;
+
+    t->avctx = avctx;
 
-    s->width  = AV_RL16(&buf[0]);
-    s->height = AV_RL16(&buf[2]);
-    tqi_calculate_qtable(s, buf[4]);
+    w = AV_RL16(&buf[0]);
+    h = AV_RL16(&buf[2]);
+    tqi_calculate_qtable(t, buf[4]);
     buf += 8;
 
-    ret = ff_set_dimensions(s->avctx, s->width, s->height);
+    ret = ff_set_dimensions(avctx, w, h);
     if (ret < 0)
         return ret;
 
@@ -130,15 +151,17 @@ static int tqi_decode_frame(AVCodecContext *avctx,
         return AVERROR(ENOMEM);
     t->bsdsp.bswap_buf(t->bitstream_buf, (const uint32_t *) buf,
                        (buf_end - buf) / 4);
-    init_get_bits(&s->gb, t->bitstream_buf, 8*(buf_end-buf));
-
-    s->last_dc[0] = s->last_dc[1] = s->last_dc[2] = 0;
-    for (s->mb_y=0; s->mb_y<(avctx->height+15)/16; s->mb_y++)
-    for (s->mb_x=0; s->mb_x<(avctx->width+15)/16; s->mb_x++)
-    {
-        if (tqi_decode_mb(s, t->block) < 0)
-            goto end;
-        tqi_idct_put(t, frame, t->block);
+    init_get_bits(&t->gb, t->bitstream_buf, 8 * (buf_end - buf));
+
+    t->last_dc[0] =
+    t->last_dc[1] =
+    t->last_dc[2] = 0;
+    for (t->mb_y = 0; t->mb_y < (h + 15) / 16; t->mb_y++) {
+        for (t->mb_x = 0; t->mb_x < (w + 15) / 16; t->mb_x++) {
+            if (tqi_decode_mb(t, t->block) < 0)
+                goto end;
+            tqi_idct_put(avctx, frame, t->block);
+        }
     }
     end:
 
diff --git a/libavcodec/elbg.c b/libavcodec/elbg.c
index 23ae948..b6049c9 100644
--- a/libavcodec/elbg.c
+++ b/libavcodec/elbg.c
@@ -31,7 +31,7 @@
 #include "elbg.h"
 #include "avcodec.h"
 
-#define DELTA_ERR_MAX 0.1  ///< Precision of the ELBG algorithm (as percentual error)
+#define DELTA_ERR_MAX 0.1  ///< Precision of the ELBG algorithm (as percentage error)
 
 /**
  * In the ELBG jargon, a cell is the set of points that are closest to a
@@ -199,7 +199,7 @@ static void get_new_centroids(elbg_data *elbg, int huc, int *newcentroid_i,
 
 /**
  * Add the points in the low utility cell to its closest cell. Split the high
- * utility cell, putting the separate points in the (now empty) low utility
+ * utility cell, putting the separated points in the (now empty) low utility
  * cell.
  *
  * @param elbg         Internal elbg data
diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c
index 5a75fad..2790599 100644
--- a/libavcodec/error_resilience.c
+++ b/libavcodec/error_resilience.c
@@ -393,6 +393,8 @@ static void guess_mv(ERContext *s)
     set_mv_strides(s, &mot_step, &mot_stride);
 
     num_avail = 0;
+    if (s->last_pic.motion_val[0])
+        ff_thread_await_progress(s->last_pic.tf, mb_height-1, 0);
     for (i = 0; i < mb_width * mb_height; i++) {
         const int mb_xy = s->mb_index2xy[i];
         int f = 0;
@@ -580,24 +582,9 @@ skip_mean_and_median:
                     /* zero MV */
                     pred_count++;
 
-                    if (!fixed[mb_xy] && 0) {
-                        if (s->avctx->codec_id == AV_CODEC_ID_H264) {
-                            // FIXME
-                        } else {
-                            ff_thread_await_progress(s->last_pic.tf,
-                                                     mb_y, 0);
-                        }
-                        if (!s->last_pic.motion_val[0] ||
-                            !s->last_pic.ref_index[0])
-                            goto skip_last_mv;
-                        prev_x   = s->last_pic.motion_val[0][mot_index][0];
-                        prev_y   = s->last_pic.motion_val[0][mot_index][1];
-                        prev_ref = s->last_pic.ref_index[0][4 * mb_xy];
-                    } else {
-                        prev_x   = s->cur_pic.motion_val[0][mot_index][0];
-                        prev_y   = s->cur_pic.motion_val[0][mot_index][1];
-                        prev_ref = s->cur_pic.ref_index[0][4 * mb_xy];
-                    }
+                    prev_x   = s->cur_pic.motion_val[0][mot_index][0];
+                    prev_y   = s->cur_pic.motion_val[0][mot_index][1];
+                    prev_ref = s->cur_pic.ref_index[0][4 * mb_xy];
 
                     /* last MV */
                     mv_predictor[pred_count][0] = prev_x;
@@ -605,8 +592,6 @@ skip_mean_and_median:
                              ref[pred_count]    = prev_ref;
                     pred_count++;
 
-skip_last_mv:
-
                     for (j = 0; j < pred_count; j++) {
                         int *linesize = s->cur_pic.f->linesize;
                         int score = 0;
@@ -897,7 +882,7 @@ void ff_er_frame_end(ERContext *s)
 
     if (   mb_x == s->mb_width
         && s->avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO
-        && (s->avctx->height&16)
+        && (FFALIGN(s->avctx->height, 16)&16)
         && s->error_count == 3 * s->mb_width * (s->avctx->skip_top + s->avctx->skip_bottom + 1)
     ) {
         av_log(s->avctx, AV_LOG_DEBUG, "ignoring last missing slice\n");
@@ -1149,7 +1134,7 @@ void ff_er_frame_end(ERContext *s)
                 s->mv[0][0][1] = s->cur_pic.motion_val[dir][mb_x * 2 + mb_y * 2 * s->b8_stride][1];
             }
 
-            s->decode_mb(s->opaque, 0 /* FIXME h264 partitioned slices need this set */,
+            s->decode_mb(s->opaque, 0 /* FIXME H.264 partitioned slices need this set */,
                          mv_dir, mv_type, &s->mv, mb_x, mb_y, 0, 0);
         }
     }
diff --git a/libavcodec/error_resilience.h b/libavcodec/error_resilience.h
index 1f52f20..d444ec3 100644
--- a/libavcodec/error_resilience.h
+++ b/libavcodec/error_resilience.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -42,7 +41,7 @@ typedef struct ERPicture {
     AVFrame *f;
     ThreadFrame *tf;
 
-    // it's the caller's responsibility to allocate these buffers
+    // it is the caller's responsibility to allocate these buffers
     int16_t (*motion_val[2])[2];
     int8_t *ref_index[2];
 
diff --git a/libavcodec/escape124.c b/libavcodec/escape124.c
index 50a86c8..9a51bda 100644
--- a/libavcodec/escape124.c
+++ b/libavcodec/escape124.c
@@ -145,7 +145,7 @@ static MacroBlock decode_macroblock(Escape124Context* s, GetBitContext* gb,
     unsigned block_index, depth;
     int value = get_bits1(gb);
     if (value) {
-        static const char transitions[3][2] = { {2, 1}, {0, 2}, {1, 0} };
+        static const int8_t transitions[3][2] = { {2, 1}, {0, 2}, {1, 0} };
         value = get_bits1(gb);
         *codebook_index = transitions[*codebook_index][value];
     }
diff --git a/libavcodec/exif.c b/libavcodec/exif.c
index fa30f05..07ce174 100644
--- a/libavcodec/exif.c
+++ b/libavcodec/exif.c
@@ -41,14 +41,14 @@ static const char *exif_get_tag_name(uint16_t id)
 }
 
 
-static int exif_add_metadata(AVCodecContext *avctx, int count, int type,
+static int exif_add_metadata(void *logctx, int count, int type,
                              const char *name, const char *sep,
                              GetByteContext *gb, int le,
                              AVDictionary **metadata)
 {
     switch(type) {
     case 0:
-        av_log(avctx, AV_LOG_WARNING,
+        av_log(logctx, AV_LOG_WARNING,
                "Invalid TIFF tag type 0 found for %s with size %d\n",
                name, count);
         return 0;
@@ -64,13 +64,13 @@ static int exif_add_metadata(AVCodecContext *avctx, int count, int type,
     case TIFF_SLONG    :
     case TIFF_LONG     : return ff_tadd_long_metadata(count, name, sep, gb, le, metadata);
     default:
-        avpriv_request_sample(avctx, "TIFF tag type (%u)", type);
+        avpriv_request_sample(logctx, "TIFF tag type (%u)", type);
         return 0;
     };
 }
 
 
-static int exif_decode_tag(AVCodecContext *avctx, GetByteContext *gbytes, int le,
+static int exif_decode_tag(void *logctx, GetByteContext *gbytes, int le,
                            int depth, AVDictionary **metadata)
 {
     int ret, cur_pos;
@@ -92,7 +92,7 @@ static int exif_decode_tag(AVCodecContext *avctx, GetByteContext *gbytes, int le
     // store metadata or proceed with next IFD
     ret = ff_tis_ifd(id);
     if (ret) {
-        ret = avpriv_exif_decode_ifd(avctx, gbytes, le, depth + 1, metadata);
+        ret = avpriv_exif_decode_ifd(logctx, gbytes, le, depth + 1, metadata);
     } else {
         const char *name = exif_get_tag_name(id);
         char *use_name   = (char*) name;
@@ -105,7 +105,7 @@ static int exif_decode_tag(AVCodecContext *avctx, GetByteContext *gbytes, int le
             snprintf(use_name, 7, "0x%04X", id);
         }
 
-        ret = exif_add_metadata(avctx, count, type, use_name, NULL,
+        ret = exif_add_metadata(logctx, count, type, use_name, NULL,
                                 gbytes, le, metadata);
 
         if (!name) {
@@ -119,7 +119,7 @@ static int exif_decode_tag(AVCodecContext *avctx, GetByteContext *gbytes, int le
 }
 
 
-int avpriv_exif_decode_ifd(AVCodecContext *avctx, GetByteContext *gbytes, int le,
+int avpriv_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le,
                            int depth, AVDictionary **metadata)
 {
     int i, ret;
@@ -132,7 +132,7 @@ int avpriv_exif_decode_ifd(AVCodecContext *avctx, GetByteContext *gbytes, int le
     }
 
     for (i = 0; i < entries; i++) {
-        if ((ret = exif_decode_tag(avctx, gbytes, le, depth, metadata)) < 0) {
+        if ((ret = exif_decode_tag(logctx, gbytes, le, depth, metadata)) < 0) {
             return ret;
         }
     }
diff --git a/libavcodec/exif.h b/libavcodec/exif.h
index 2f509ba..5f09208 100644
--- a/libavcodec/exif.h
+++ b/libavcodec/exif.h
@@ -164,7 +164,7 @@ static const struct exif_tag tag_list[] = { // JEITA CP-3451 EXIF specification:
 
 /** Recursively decodes all IFD's and
  *  adds included TAGS into the metadata dictionary. */
-int avpriv_exif_decode_ifd(AVCodecContext *avctx, GetByteContext *gbytes, int le,
+int avpriv_exif_decode_ifd(void *logctx, GetByteContext *gbytes, int le,
                            int depth, AVDictionary **metadata);
 
 #endif /* AVCODEC_EXIF_H */
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index 9ec99d6..cabe329 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -1,7 +1,10 @@
 /*
  * OpenEXR (.exr) image decoder
+ * Copyright (c) 2006 Industrial Light & Magic, a division of Lucas Digital Ltd. LLC
  * Copyright (c) 2009 Jimmy Christensen
  *
+ * B44/B44A, Tile added by Jokyo Images support by CNC - French National Center for Cinema
+ *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -34,6 +37,7 @@
 #include <float.h>
 #include <zlib.h>
 
+#include "libavutil/common.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/intfloat.h"
 #include "libavutil/opt.h"
@@ -65,11 +69,31 @@ enum ExrPixelType {
     EXR_UNKNOWN,
 };
 
+enum ExrTileLevelMode {
+    EXR_TILE_LEVEL_ONE,
+    EXR_TILE_LEVEL_MIPMAP,
+    EXR_TILE_LEVEL_RIPMAP,
+    EXR_TILE_LEVEL_UNKNOWN,
+};
+
+enum ExrTileLevelRound {
+    EXR_TILE_ROUND_UP,
+    EXR_TILE_ROUND_DOWN,
+    EXR_TILE_ROUND_UNKNOWN,
+};
+
 typedef struct EXRChannel {
     int xsub, ysub;
     enum ExrPixelType pixel_type;
 } EXRChannel;
 
+typedef struct EXRTileAttribute {
+    int32_t xSize;
+    int32_t ySize;
+    enum ExrTileLevelMode level_mode;
+    enum ExrTileLevelRound level_round;
+} EXRTileAttribute;
+
 typedef struct EXRThreadData {
     uint8_t *uncompressed_data;
     int uncompressed_size;
@@ -79,6 +103,10 @@ typedef struct EXRThreadData {
 
     uint8_t *bitmap;
     uint16_t *lut;
+
+    int ysize, xsize;
+
+    int channel_line_size;
 } EXRThreadData;
 
 typedef struct EXRContext {
@@ -95,17 +123,19 @@ typedef struct EXRContext {
     uint32_t xmax, xmin;
     uint32_t ymax, ymin;
     uint32_t xdelta, ydelta;
-    int ysize;
 
-    uint64_t scan_line_size;
     int scan_lines_per_block;
 
+    EXRTileAttribute tile_attr; /* header data attribute of tile */
+    int is_tile; /* 0 if scanline, 1 if tile */
+
     GetByteContext gb;
     const uint8_t *buf;
     int buf_size;
 
     EXRChannel *channels;
     int nb_channels;
+    int current_channel_offset;
 
     EXRThreadData *thread_data;
 
@@ -161,13 +191,13 @@ static union av_intfloat32 exr_half2float(uint16_t hf)
                 mantissa <<= 1;
                 exp -= (1 << 23);
             }
-            // clamp the mantissa to 10-bits
+            // clamp the mantissa to 10 bits
             mantissa &= ((1 << 10) - 1);
-            // shift left to generate single-precision mantissa of 23-bits
+            // shift left to generate single-precision mantissa of 23 bits
             mantissa <<= 13;
         }
     } else {
-        // shift left to generate single-precision mantissa of 23-bits
+        // shift left to generate single-precision mantissa of 23 bits
         mantissa <<= 13;
         // generate single precision biased exponent value
         exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
@@ -492,7 +522,8 @@ static int huf_decode(const uint64_t *hcode, const HufDec *hdecod,
     uint16_t *outb    = out;
     uint16_t *oe      = out + no;
     const uint8_t *ie = gb->buffer + (nbits + 7) / 8; // input byte size
-    uint8_t cs, s;
+    uint8_t cs;
+    uint16_t s;
     int i, lc = 0;
 
     while (gb->buffer < ie) {
@@ -718,6 +749,9 @@ static int piz_uncompress(EXRContext *s, const uint8_t *src, int ssize,
     uint16_t *tmp = (uint16_t *)td->tmp;
     uint8_t *out;
     int ret, i, j;
+    int pixel_half_size;/* 1 for half, 2 for float and uint32 */
+    EXRChannel *channel;
+    int tmp_offset;
 
     if (!td->bitmap)
         td->bitmap = av_malloc(BITMAP_SIZE);
@@ -740,7 +774,7 @@ static int piz_uncompress(EXRContext *s, const uint8_t *src, int ssize,
     if (min_non_zero <= max_non_zero)
         bytestream2_get_buffer(&gb, td->bitmap + min_non_zero,
                                max_non_zero - min_non_zero + 1);
-    memset(td->bitmap + max_non_zero, 0, BITMAP_SIZE - max_non_zero);
+    memset(td->bitmap + max_non_zero + 1, 0, BITMAP_SIZE - max_non_zero - 1);
 
     maxval = reverse_lut(td->bitmap, td->lut);
 
@@ -750,24 +784,38 @@ static int piz_uncompress(EXRContext *s, const uint8_t *src, int ssize,
 
     ptr = tmp;
     for (i = 0; i < s->nb_channels; i++) {
-        EXRChannel *channel = &s->channels[i];
-        int size = channel->pixel_type;
+        channel = &s->channels[i];
+
+        if (channel->pixel_type == EXR_HALF)
+            pixel_half_size = 1;
+        else
+            pixel_half_size = 2;
 
-        for (j = 0; j < size; j++)
-            wav_decode(ptr + j, s->xdelta, size, s->ysize,
-                       s->xdelta * size, maxval);
-        ptr += s->xdelta * s->ysize * size;
+        for (j = 0; j < pixel_half_size; j++)
+            wav_decode(ptr + j, td->xsize, pixel_half_size, td->ysize,
+                       td->xsize * pixel_half_size, maxval);
+        ptr += td->xsize * td->ysize * pixel_half_size;
     }
 
     apply_lut(td->lut, tmp, dsize / sizeof(uint16_t));
 
     out = td->uncompressed_data;
-    for (i = 0; i < s->ysize; i++)
+    for (i = 0; i < td->ysize; i++) {
+        tmp_offset = 0;
         for (j = 0; j < s->nb_channels; j++) {
-            uint16_t *in = tmp + j * s->xdelta * s->ysize + i * s->xdelta;
-            memcpy(out, in, s->xdelta * 2);
-            out += s->xdelta * 2;
+            uint16_t *in;
+            EXRChannel *channel = &s->channels[j];
+            if (channel->pixel_type == EXR_HALF)
+                pixel_half_size = 1;
+            else
+                pixel_half_size = 2;
+
+            in = tmp + tmp_offset * td->xsize * td->ysize + i * td->xsize * pixel_half_size;
+            tmp_offset += pixel_half_size;
+            memcpy(out, in, td->xsize * 2 * pixel_half_size);
+            out += td->xsize * 2 * pixel_half_size;
         }
+    }
 
     return 0;
 }
@@ -776,17 +824,31 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src,
                             int compressed_size, int uncompressed_size,
                             EXRThreadData *td)
 {
-    unsigned long dest_len = uncompressed_size;
+    unsigned long dest_len, expected_len = 0;
     const uint8_t *in = td->tmp;
     uint8_t *out;
     int c, i, j;
 
-    if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK ||
-        dest_len != uncompressed_size)
+    for (i = 0; i < s->nb_channels; i++) {
+        if (s->channels[i].pixel_type == EXR_FLOAT) {
+            expected_len += (td->xsize * td->ysize * 3);/* PRX 24 store float in 24 bit instead of 32 */
+        } else if (s->channels[i].pixel_type == EXR_HALF) {
+            expected_len += (td->xsize * td->ysize * 2);
+        } else {//UINT 32
+            expected_len += (td->xsize * td->ysize * 4);
+        }
+    }
+
+    dest_len = expected_len;
+
+    if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK) {
         return AVERROR_INVALIDDATA;
+    } else if (dest_len != expected_len) {
+        return AVERROR_INVALIDDATA;
+    }
 
     out = td->uncompressed_data;
-    for (i = 0; i < s->ysize; i++)
+    for (i = 0; i < td->ysize; i++)
         for (c = 0; c < s->nb_channels; c++) {
             EXRChannel *channel = &s->channels[c];
             const uint8_t *ptr[4];
@@ -795,11 +857,11 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src,
             switch (channel->pixel_type) {
             case EXR_FLOAT:
                 ptr[0] = in;
-                ptr[1] = ptr[0] + s->xdelta;
-                ptr[2] = ptr[1] + s->xdelta;
-                in     = ptr[2] + s->xdelta;
+                ptr[1] = ptr[0] + td->xsize;
+                ptr[2] = ptr[1] + td->xsize;
+                in     = ptr[2] + td->xsize;
 
-                for (j = 0; j < s->xdelta; ++j) {
+                for (j = 0; j < td->xsize; ++j) {
                     uint32_t diff = (*(ptr[0]++) << 24) |
                                     (*(ptr[1]++) << 16) |
                                     (*(ptr[2]++) << 8);
@@ -809,9 +871,9 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src,
                 break;
             case EXR_HALF:
                 ptr[0] = in;
-                ptr[1] = ptr[0] + s->xdelta;
-                in     = ptr[1] + s->xdelta;
-                for (j = 0; j < s->xdelta; j++) {
+                ptr[1] = ptr[0] + td->xsize;
+                in     = ptr[1] + td->xsize;
+                for (j = 0; j < td->xsize; j++) {
                     uint32_t diff = (*(ptr[0]++) << 8) | *(ptr[1]++);
 
                     pixel += diff;
@@ -826,6 +888,134 @@ static int pxr24_uncompress(EXRContext *s, const uint8_t *src,
     return 0;
 }
 
+static void unpack_14(const uint8_t b[14], uint16_t s[16])
+{
+    unsigned short shift = (b[ 2] >> 2);
+    unsigned short bias = (0x20 << shift);
+    int i;
+
+    s[ 0] = (b[0] << 8) | b[1];
+
+    s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) - bias;
+    s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) - bias;
+    s[12] = s[ 8] +   ((b[ 4]                       & 0x3f) << shift) - bias;
+
+    s[ 1] = s[ 0] +   ((b[ 5] >> 2)                         << shift) - bias;
+    s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) - bias;
+    s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) - bias;
+    s[13] = s[12] +   ((b[ 7]                       & 0x3f) << shift) - bias;
+
+    s[ 2] = s[ 1] +   ((b[ 8] >> 2)                         << shift) - bias;
+    s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) - bias;
+    s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) - bias;
+    s[14] = s[13] +   ((b[10]                       & 0x3f) << shift) - bias;
+
+    s[ 3] = s[ 2] +   ((b[11] >> 2)                         << shift) - bias;
+    s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) - bias;
+    s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) - bias;
+    s[15] = s[14] +   ((b[13]                       & 0x3f) << shift) - bias;
+
+    for (i = 0; i < 16; ++i) {
+        if (s[i] & 0x8000)
+            s[i] &= 0x7fff;
+        else
+            s[i] = ~s[i];
+    }
+}
+
+static void unpack_3(const uint8_t b[3], uint16_t s[16])
+{
+    int i;
+
+    s[0] = (b[0] << 8) | b[1];
+
+    if (s[0] & 0x8000)
+        s[0] &= 0x7fff;
+    else
+        s[0] = ~s[0];
+
+    for (i = 1; i < 16; i++)
+        s[i] = s[0];
+}
+
+
+static int b44_uncompress(EXRContext *s, const uint8_t *src, int compressed_size,
+                          int uncompressed_size, EXRThreadData *td) {
+    const int8_t *sr = src;
+    int stayToUncompress = compressed_size;
+    int nbB44BlockW, nbB44BlockH;
+    int indexHgX, indexHgY, indexOut, indexTmp;
+    uint16_t tmpBuffer[16]; /* B44 use 4x4 half float pixel */
+    int c, iY, iX, y, x;
+    int target_channel_offset = 0;
+
+    /* calc B44 block count */
+    nbB44BlockW = td->xsize / 4;
+    if ((td->xsize % 4) != 0)
+        nbB44BlockW++;
+
+    nbB44BlockH = td->ysize / 4;
+    if ((td->ysize % 4) != 0)
+        nbB44BlockH++;
+
+    for (c = 0; c < s->nb_channels; c++) {
+        if (s->channels[c].pixel_type == EXR_HALF) {/* B44 only compress half float data */
+            for (iY = 0; iY < nbB44BlockH; iY++) {
+                for (iX = 0; iX < nbB44BlockW; iX++) {/* For each B44 block */
+                    if (stayToUncompress < 3) {
+                        av_log(s, AV_LOG_ERROR, "Not enough data for B44A block: %d", stayToUncompress);
+                        return AVERROR_INVALIDDATA;
+                    }
+
+                    if (src[compressed_size - stayToUncompress + 2] == 0xfc) { /* B44A block */
+                        unpack_3(sr, tmpBuffer);
+                        sr += 3;
+                        stayToUncompress -= 3;
+                    }  else {/* B44 Block */
+                        if (stayToUncompress < 14) {
+                            av_log(s, AV_LOG_ERROR, "Not enough data for B44 block: %d", stayToUncompress);
+                            return AVERROR_INVALIDDATA;
+                        }
+                        unpack_14(sr, tmpBuffer);
+                        sr += 14;
+                        stayToUncompress -= 14;
+                    }
+
+                    /* copy data to uncompress buffer (B44 block can exceed target resolution)*/
+                    indexHgX = iX * 4;
+                    indexHgY = iY * 4;
+
+                    for (y = indexHgY; y < FFMIN(indexHgY + 4, td->ysize); y++) {
+                        for (x = indexHgX; x < FFMIN(indexHgX + 4, td->xsize); x++) {
+                            indexOut = target_channel_offset * td->xsize + y * td->channel_line_size + 2 * x;
+                            indexTmp = (y-indexHgY) * 4 + (x-indexHgX);
+                            td->uncompressed_data[indexOut] = tmpBuffer[indexTmp] & 0xff;
+                            td->uncompressed_data[indexOut + 1] = tmpBuffer[indexTmp] >> 8;
+                        }
+                    }
+                }
+            }
+            target_channel_offset += 2;
+        } else {/* Float or UINT 32 channel */
+            if (stayToUncompress < td->ysize * td->xsize * 4) {
+                av_log(s, AV_LOG_ERROR, "Not enough data for uncompress channel: %d", stayToUncompress);
+                return AVERROR_INVALIDDATA;
+            }
+
+            for (y = 0; y < td->ysize; y++) {
+                indexOut = target_channel_offset * td->xsize + y * td->channel_line_size;
+                memcpy(&td->uncompressed_data[indexOut], sr, td->xsize * 4);
+                sr += td->xsize * 4;
+            }
+            target_channel_offset += 4;
+
+            stayToUncompress -= td->ysize * td->xsize * 4;
+        }
+    }
+
+    return 0;
+}
+
 static int decode_block(AVCodecContext *avctx, void *tdata,
                         int jobnr, int threadnr)
 {
@@ -835,46 +1025,94 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
     const uint8_t *channel_buffer[4] = { 0 };
     const uint8_t *buf = s->buf;
     uint64_t line_offset, uncompressed_size;
-    uint32_t xdelta = s->xdelta;
     uint16_t *ptr_x;
     uint8_t *ptr;
-    uint32_t data_size, line;
+    uint32_t data_size, line, col = 0;
+    uint32_t tileX, tileY, tileLevelX, tileLevelY;
     const uint8_t *src;
-    int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components;
-    int bxmin = s->xmin * 2 * s->desc->nb_components;
+    int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components; /* nb pixel to add at the right of the datawindow */
+    int bxmin = s->xmin * 2 * s->desc->nb_components; /* nb pixel to add at the left of the datawindow */
     int i, x, buf_size = s->buf_size;
     float one_gamma = 1.0f / s->gamma;
     avpriv_trc_function trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type);
     int ret;
 
     line_offset = AV_RL64(s->gb.buffer + jobnr * 8);
-    // Check if the buffer has the required bytes needed from the offset
-    if (line_offset > buf_size - 8)
-        return AVERROR_INVALIDDATA;
 
-    src  = buf + line_offset + 8;
-    line = AV_RL32(src - 8);
-    if (line < s->ymin || line > s->ymax)
-        return AVERROR_INVALIDDATA;
+    if (s->is_tile) {
+        if (line_offset > buf_size - 20)
+            return AVERROR_INVALIDDATA;
 
-    data_size = AV_RL32(src - 4);
-    if (data_size <= 0 || data_size > buf_size)
-        return AVERROR_INVALIDDATA;
+        src  = buf + line_offset + 20;
 
-    s->ysize          = FFMIN(s->scan_lines_per_block, s->ymax - line + 1);
-    uncompressed_size = s->scan_line_size * s->ysize;
-    if ((s->compression == EXR_RAW && (data_size != uncompressed_size ||
-                                 line_offset > buf_size - uncompressed_size)) ||
-        (s->compression != EXR_RAW && (data_size > uncompressed_size ||
-                                 line_offset > buf_size - data_size))) {
-        return AVERROR_INVALIDDATA;
+        tileX = AV_RL32(src - 20);
+        tileY = AV_RL32(src - 16);
+        tileLevelX = AV_RL32(src - 12);
+        tileLevelY = AV_RL32(src - 8);
+
+        data_size = AV_RL32(src - 4);
+        if (data_size <= 0 || data_size > buf_size)
+            return AVERROR_INVALIDDATA;
+
+        if (tileLevelX || tileLevelY) { /* tile level, is not the full res level */
+            avpriv_report_missing_feature(s->avctx, "Subres tile before full res tile");
+            return AVERROR_PATCHWELCOME;
+        }
+
+        line = s->tile_attr.ySize * tileY;
+        col = s->tile_attr.xSize * tileX;
+
+        td->ysize = FFMIN(s->tile_attr.ySize, s->ydelta - tileY * s->tile_attr.ySize);
+        td->xsize = FFMIN(s->tile_attr.xSize, s->xdelta - tileX * s->tile_attr.xSize);
+
+        if (col) { /* not the first tile of the line */
+            bxmin = 0; /* doesn't add pixel at the left of the datawindow */
+        }
+
+        if ((col + td->xsize) != s->xdelta)/* not the last tile of the line */
+            axmax = 0; /* doesn't add pixel at the right of the datawindow */
+
+        td->channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */
+        uncompressed_size = td->channel_line_size * (uint64_t)td->ysize;/* uncompress size of the block */
+    } else {
+        if (line_offset > buf_size - 8)
+            return AVERROR_INVALIDDATA;
+
+        src  = buf + line_offset + 8;
+        line = AV_RL32(src - 8);
+
+        if (line < s->ymin || line > s->ymax)
+            return AVERROR_INVALIDDATA;
+
+        data_size = AV_RL32(src - 4);
+        if (data_size <= 0 || data_size > buf_size)
+            return AVERROR_INVALIDDATA;
+
+        td->ysize          = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); /* s->ydelta - line ?? */
+        td->xsize          = s->xdelta;
+
+        td->channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */
+        uncompressed_size = td->channel_line_size * (uint64_t)td->ysize;/* uncompress size of the block */
+
+        if ((s->compression == EXR_RAW && (data_size != uncompressed_size ||
+                                           line_offset > buf_size - uncompressed_size)) ||
+            (s->compression != EXR_RAW && (data_size > uncompressed_size ||
+                                           line_offset > buf_size - data_size))) {
+            return AVERROR_INVALIDDATA;
+        }
+    }
+
+    if (data_size < uncompressed_size || s->is_tile) { /* td->tmp is use for tile reorganization */
+        av_fast_padded_malloc(&td->tmp, &td->tmp_size, uncompressed_size);
+        if (!td->tmp)
+            return AVERROR(ENOMEM);
     }
 
     if (data_size < uncompressed_size) {
         av_fast_padded_malloc(&td->uncompressed_data,
                               &td->uncompressed_size, uncompressed_size);
-        av_fast_padded_malloc(&td->tmp, &td->tmp_size, uncompressed_size);
-        if (!td->uncompressed_data || !td->tmp)
+
+        if (!td->uncompressed_data)
             return AVERROR(ENOMEM);
 
         ret = AVERROR_INVALIDDATA;
@@ -891,6 +1129,11 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
             break;
         case EXR_RLE:
             ret = rle_uncompress(src, data_size, uncompressed_size, td);
+            break;
+        case EXR_B44:
+        case EXR_B44A:
+            ret = b44_uncompress(s, src, data_size, uncompressed_size, td);
+            break;
         }
         if (ret < 0) {
             av_log(avctx, AV_LOG_ERROR, "decode_block() failed.\n");
@@ -899,16 +1142,17 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
         src = td->uncompressed_data;
     }
 
-    channel_buffer[0] = src + xdelta * s->channel_offsets[0];
-    channel_buffer[1] = src + xdelta * s->channel_offsets[1];
-    channel_buffer[2] = src + xdelta * s->channel_offsets[2];
+    channel_buffer[0] = src + td->xsize * s->channel_offsets[0];
+    channel_buffer[1] = src + td->xsize * s->channel_offsets[1];
+    channel_buffer[2] = src + td->xsize * s->channel_offsets[2];
     if (s->channel_offsets[3] >= 0)
-        channel_buffer[3] = src + xdelta * s->channel_offsets[3];
+        channel_buffer[3] = src + td->xsize * s->channel_offsets[3];
+
+    ptr = p->data[0] + line * p->linesize[0] + (col * s->desc->nb_components * 2);
 
-    ptr = p->data[0] + line * p->linesize[0];
     for (i = 0;
-         i < s->scan_lines_per_block && line + i <= s->ymax;
-         i++, ptr += p->linesize[0]) {
+         i < td->ysize; i++, ptr += p->linesize[0]) {
+
         const uint8_t *r, *g, *b, *a;
 
         r = channel_buffer[0];
@@ -922,10 +1166,11 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
         // Zero out the start if xmin is not 0
         memset(ptr_x, 0, bxmin);
         ptr_x += s->xmin * s->desc->nb_components;
+
         if (s->pixel_type == EXR_FLOAT) {
             // 32-bit
             if (trc_func) {
-                for (x = 0; x < xdelta; x++) {
+                for (x = 0; x < td->xsize; x++) {
                     union av_intfloat32 t;
                     t.i = bytestream_get_le32(&r);
                     t.f = trc_func(t.f);
@@ -942,7 +1187,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
                         *ptr_x++ = exr_flt2uint(bytestream_get_le32(&a));
                 }
             } else {
-                for (x = 0; x < xdelta; x++) {
+                for (x = 0; x < td->xsize; x++) {
                     union av_intfloat32 t;
                     t.i = bytestream_get_le32(&r);
                     if (t.f > 0.0f)  /* avoid negative values */
@@ -964,7 +1209,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
             }
         } else {
             // 16-bit
-            for (x = 0; x < xdelta; x++) {
+            for (x = 0; x < td->xsize; x++) {
                 *ptr_x++ = s->gamma_table[bytestream_get_le16(&r)];
                 *ptr_x++ = s->gamma_table[bytestream_get_le16(&g)];
                 *ptr_x++ = s->gamma_table[bytestream_get_le16(&b)];
@@ -976,11 +1221,11 @@ static int decode_block(AVCodecContext *avctx, void *tdata,
         // Zero out the end if xmax+1 is not w
         memset(ptr_x, 0, axmax);
 
-        channel_buffer[0] += s->scan_line_size;
-        channel_buffer[1] += s->scan_line_size;
-        channel_buffer[2] += s->scan_line_size;
+        channel_buffer[0] += td->channel_line_size;
+        channel_buffer[1] += td->channel_line_size;
+        channel_buffer[2] += td->channel_line_size;
         if (channel_buffer[3])
-            channel_buffer[3] += s->scan_line_size;
+            channel_buffer[3] += td->channel_line_size;
     }
 
     return 0;
@@ -1029,9 +1274,10 @@ static int check_header_variable(EXRContext *s,
 
 static int decode_header(EXRContext *s)
 {
-    int current_channel_offset = 0;
-    int magic_number, version, flags, i, sar = 0;
+    int magic_number, version, i, flags, sar = 0;
+    int layer_match = 0;
 
+    s->current_channel_offset = 0;
     s->xmin               = ~0;
     s->xmax               = ~0;
     s->ymin               = ~0;
@@ -1047,6 +1293,9 @@ static int decode_header(EXRContext *s)
     s->nb_channels        = 0;
     s->w                  = 0;
     s->h                  = 0;
+    s->tile_attr.xSize    = -1;
+    s->tile_attr.ySize    = -1;
+    s->is_tile            = 0;
 
     if (bytestream2_get_bytes_left(&s->gb) < 10) {
         av_log(s->avctx, AV_LOG_ERROR, "Header too short to parse.\n");
@@ -1068,8 +1317,13 @@ static int decode_header(EXRContext *s)
     }
 
     flags = bytestream2_get_le24(&s->gb);
-    if (flags & 0x02) {
-        avpriv_report_missing_feature(s->avctx, "Tile support");
+
+    if (flags == 0x00)
+        s->is_tile = 0;
+    else if (flags & 0x02)
+        s->is_tile = 1;
+    else{
+        avpriv_report_missing_feature(s->avctx, "flags %d", flags);
         return AVERROR_PATCHWELCOME;
     }
 
@@ -1092,31 +1346,39 @@ static int decode_header(EXRContext *s)
 
                 if (strcmp(s->layer, "") != 0) {
                     if (strncmp(ch_gb.buffer, s->layer, strlen(s->layer)) == 0) {
+                        layer_match = 1;
+                        av_log(s->avctx, AV_LOG_INFO,
+                               "Channel match layer : %s.\n", ch_gb.buffer);
                         ch_gb.buffer += strlen(s->layer);
                         if (*ch_gb.buffer == '.')
                             ch_gb.buffer++;         /* skip dot if not given */
+                    } else {
                         av_log(s->avctx, AV_LOG_INFO,
-                               "Layer %s.%s matched.\n", s->layer, ch_gb.buffer);
+                               "Channel doesn't match layer : %s.\n", ch_gb.buffer);
                     }
+                } else {
+                    layer_match = 1;
                 }
 
-                if (!strcmp(ch_gb.buffer, "R") ||
-                    !strcmp(ch_gb.buffer, "X") ||
-                    !strcmp(ch_gb.buffer, "U"))
-                    channel_index = 0;
-                else if (!strcmp(ch_gb.buffer, "G") ||
-                         !strcmp(ch_gb.buffer, "Y") ||
-                         !strcmp(ch_gb.buffer, "V"))
-                    channel_index = 1;
-                else if (!strcmp(ch_gb.buffer, "B") ||
-                         !strcmp(ch_gb.buffer, "Z") ||
-                         !strcmp(ch_gb.buffer, "W"))
-                    channel_index = 2;
-                else if (!strcmp(ch_gb.buffer, "A"))
-                    channel_index = 3;
-                else
-                    av_log(s->avctx, AV_LOG_WARNING,
-                           "Unsupported channel %.256s.\n", ch_gb.buffer);
+                if (layer_match) { /* only search channel if the layer match is valid */
+                    if (!strcmp(ch_gb.buffer, "R") ||
+                        !strcmp(ch_gb.buffer, "X") ||
+                        !strcmp(ch_gb.buffer, "U"))
+                        channel_index = 0;
+                    else if (!strcmp(ch_gb.buffer, "G") ||
+                             !strcmp(ch_gb.buffer, "Y") ||
+                             !strcmp(ch_gb.buffer, "V"))
+                        channel_index = 1;
+                    else if (!strcmp(ch_gb.buffer, "B") ||
+                             !strcmp(ch_gb.buffer, "Z") ||
+                             !strcmp(ch_gb.buffer, "W"))
+                        channel_index = 2;
+                    else if (!strcmp(ch_gb.buffer, "A"))
+                        channel_index = 3;
+                    else
+                        av_log(s->avctx, AV_LOG_WARNING,
+                               "Unsupported channel %.256s.\n", ch_gb.buffer);
+                }
 
                 /* skip until you get a 0 */
                 while (bytestream2_get_bytes_left(&ch_gb) > 0 &&
@@ -1145,15 +1407,17 @@ static int decode_header(EXRContext *s)
                     return AVERROR_PATCHWELCOME;
                 }
 
-                if (channel_index >= 0) {
-                    if (s->pixel_type != EXR_UNKNOWN &&
-                        s->pixel_type != current_pixel_type) {
-                        av_log(s->avctx, AV_LOG_ERROR,
-                               "RGB channels not of the same depth.\n");
-                        return AVERROR_INVALIDDATA;
+                if (s->channel_offsets[channel_index] == -1){/* channel have not been previously assign */
+                    if (channel_index >= 0) {
+                        if (s->pixel_type != EXR_UNKNOWN &&
+                            s->pixel_type != current_pixel_type) {
+                            av_log(s->avctx, AV_LOG_ERROR,
+                                   "RGB channels not of the same depth.\n");
+                            return AVERROR_INVALIDDATA;
+                        }
+                        s->pixel_type                     = current_pixel_type;
+                        s->channel_offsets[channel_index] = s->current_channel_offset;
                     }
-                    s->pixel_type                     = current_pixel_type;
-                    s->channel_offsets[channel_index] = current_channel_offset;
                 }
 
                 s->channels = av_realloc(s->channels,
@@ -1165,7 +1429,7 @@ static int decode_header(EXRContext *s)
                 channel->xsub       = xsub;
                 channel->ysub       = ysub;
 
-                current_channel_offset += 1 << current_pixel_type;
+                s->current_channel_offset += 1 << current_pixel_type;
             }
 
             /* Check if all channels are set with an offset or if the channels
@@ -1242,6 +1506,34 @@ static int decode_header(EXRContext *s)
                        "Found more than one compression attribute.\n");
 
             continue;
+        } else if ((var_size = check_header_variable(s, "tiles",
+                                                     "tiledesc", 22)) >= 0) {
+            char tileLevel;
+
+            if (!s->is_tile)
+                av_log(s->avctx, AV_LOG_WARNING,
+                       "Found tile attribute and scanline flags. Exr will be interpreted as scanline.\n");
+
+            s->tile_attr.xSize = bytestream2_get_le32(&s->gb);
+            s->tile_attr.ySize = bytestream2_get_le32(&s->gb);
+
+            tileLevel = bytestream2_get_byte(&s->gb);
+            s->tile_attr.level_mode = tileLevel & 0x0f;
+            s->tile_attr.level_round = (tileLevel >> 4) & 0x0f;
+
+            if (s->tile_attr.level_mode >= EXR_TILE_LEVEL_UNKNOWN){
+                avpriv_report_missing_feature(s->avctx, "Tile level mode %d",
+                                              s->tile_attr.level_mode);
+                return AVERROR_PATCHWELCOME;
+            }
+
+            if (s->tile_attr.level_round >= EXR_TILE_ROUND_UNKNOWN) {
+                avpriv_report_missing_feature(s->avctx, "Tile level round %d",
+                                              s->tile_attr.level_round);
+                return AVERROR_PATCHWELCOME;
+            }
+
+            continue;
         }
 
         // Check if there are enough bytes for a header
@@ -1264,7 +1556,13 @@ static int decode_header(EXRContext *s)
         av_log(s->avctx, AV_LOG_ERROR, "Missing compression attribute.\n");
         return AVERROR_INVALIDDATA;
     }
-    s->scan_line_size = s->xdelta * current_channel_offset;
+
+    if (s->is_tile) {
+        if (s->tile_attr.xSize < 1 || s->tile_attr.ySize < 1) {
+            av_log(s->avctx, AV_LOG_ERROR, "Invalid tile attribute.\n");
+            return AVERROR_INVALIDDATA;
+        }
+    }
 
     if (bytestream2_get_bytes_left(&s->gb) <= 0) {
         av_log(s->avctx, AV_LOG_ERROR, "Incomplete frame.\n");
@@ -1286,7 +1584,7 @@ static int decode_frame(AVCodecContext *avctx, void *data,
 
     int y, ret;
     int out_line_size;
-    int scan_line_blocks;
+    int nb_blocks;/* nb scanline or nb tile */
 
     bytestream2_init(&s->gb, avpkt->data, avpkt->size);
 
@@ -1323,6 +1621,8 @@ static int decode_frame(AVCodecContext *avctx, void *data,
         s->scan_lines_per_block = 16;
         break;
     case EXR_PIZ:
+    case EXR_B44:
+    case EXR_B44A:
         s->scan_lines_per_block = 32;
         break;
     default:
@@ -1348,13 +1648,19 @@ static int decode_frame(AVCodecContext *avctx, void *data,
     if (!s->desc)
         return AVERROR_INVALIDDATA;
     out_line_size    = avctx->width * 2 * s->desc->nb_components;
-    scan_line_blocks = (s->ydelta + s->scan_lines_per_block - 1) /
-                       s->scan_lines_per_block;
+
+    if (s->is_tile) {
+        nb_blocks = ((s->xdelta + s->tile_attr.xSize - 1) / s->tile_attr.xSize) *
+        ((s->ydelta + s->tile_attr.ySize - 1) / s->tile_attr.ySize);
+    } else { /* scanline */
+        nb_blocks = (s->ydelta + s->scan_lines_per_block - 1) /
+        s->scan_lines_per_block;
+    }
 
     if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
         return ret;
 
-    if (bytestream2_get_bytes_left(&s->gb) < scan_line_blocks * 8)
+    if (bytestream2_get_bytes_left(&s->gb) < nb_blocks * 8)
         return AVERROR_INVALIDDATA;
 
     // save pointer we are going to use in decode_block
@@ -1369,7 +1675,8 @@ static int decode_frame(AVCodecContext *avctx, void *data,
     }
 
     s->picture = picture;
-    avctx->execute2(avctx, decode_block, s->thread_data, NULL, scan_line_blocks);
+
+    avctx->execute2(avctx, decode_block, s->thread_data, NULL, nb_blocks);
 
     // Zero out the end if ymax+1 is not h
     for (y = s->ymax + 1; y < avctx->height; y++) {
@@ -1418,7 +1725,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
         }
     }
 
-    // allocate thread data, used for non EXR_RAW compreesion types
+    // allocate thread data, used for non EXR_RAW compression types
     s->thread_data = av_mallocz_array(avctx->thread_count, sizeof(EXRThreadData));
     if (!s->thread_data)
         return AVERROR_INVALIDDATA;
@@ -1430,7 +1737,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
 static int decode_init_thread_copy(AVCodecContext *avctx)
 {    EXRContext *s = avctx->priv_data;
 
-    // allocate thread data, used for non EXR_RAW compreesion types
+    // allocate thread data, used for non EXR_RAW compression types
     s->thread_data = av_mallocz_array(avctx->thread_count, sizeof(EXRThreadData));
     if (!s->thread_data)
         return AVERROR_INVALIDDATA;
diff --git a/libavcodec/faxcompr.h b/libavcodec/faxcompr.h
index 53d1168..aa29a7b 100644
--- a/libavcodec/faxcompr.h
+++ b/libavcodec/faxcompr.h
@@ -31,7 +31,7 @@
 #include "tiff.h"
 
 /**
- * initialize upacker code
+ * initialize unpacker code
  */
 void ff_ccitt_unpack_init(void);
 
diff --git a/libavcodec/ffjni.c b/libavcodec/ffjni.c
new file mode 100644
index 0000000..82ee5d3
--- /dev/null
+++ b/libavcodec/ffjni.c
@@ -0,0 +1,402 @@
+/*
+ * JNI utility functions
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * 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 <jni.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include "libavutil/bprint.h"
+#include "libavutil/log.h"
+
+#include "config.h"
+#include "jni.h"
+#include "ffjni.h"
+
+static JavaVM *java_vm = NULL;
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+JNIEnv *ff_jni_attach_env(int *attached, void *log_ctx)
+{
+    int ret = 0;
+    JNIEnv *env = NULL;
+
+    *attached = 0;
+
+    pthread_mutex_lock(&lock);
+    if (java_vm == NULL) {
+        java_vm = av_jni_get_java_vm(log_ctx);
+    }
+    pthread_mutex_unlock(&lock);
+
+    if (!java_vm) {
+        av_log(log_ctx, AV_LOG_ERROR, "No Java virtual machine has been registered\n");
+        return NULL;
+    }
+
+    ret = (*java_vm)->GetEnv(java_vm, (void **)&env, JNI_VERSION_1_6);
+    switch(ret) {
+    case JNI_EDETACHED:
+        if ((*java_vm)->AttachCurrentThread(java_vm, &env, NULL) != 0) {
+            av_log(log_ctx, AV_LOG_ERROR, "Failed to attach the JNI environment to the current thread\n");
+            env = NULL;
+        } else {
+            *attached = 1;
+        }
+        break;
+    case JNI_OK:
+        break;
+    case JNI_EVERSION:
+        av_log(log_ctx, AV_LOG_ERROR, "The specified JNI version is not supported\n");
+        break;
+    default:
+        av_log(log_ctx, AV_LOG_ERROR, "Failed to get the JNI environment attached to this thread");
+        break;
+    }
+
+    return env;
+}
+
+int ff_jni_detach_env(void *log_ctx)
+{
+    if (java_vm == NULL) {
+        av_log(log_ctx, AV_LOG_ERROR, "No Java virtual machine has been registered\n");
+        return AVERROR(EINVAL);
+    }
+
+    return (*java_vm)->DetachCurrentThread(java_vm);
+}
+
+char *ff_jni_jstring_to_utf_chars(JNIEnv *env, jstring string, void *log_ctx)
+{
+    char *ret = NULL;
+    const char *utf_chars = NULL;
+
+    jboolean copy = 0;
+
+    if (!string) {
+        return NULL;
+    }
+
+    utf_chars = (*env)->GetStringUTFChars(env, string, &copy);
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionClear(env);
+        av_log(log_ctx, AV_LOG_ERROR, "String.getStringUTFChars() threw an exception\n");
+        return NULL;
+    }
+
+    ret = av_strdup(utf_chars);
+
+    (*env)->ReleaseStringUTFChars(env, string, utf_chars);
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionClear(env);
+        av_log(log_ctx, AV_LOG_ERROR, "String.releaseStringUTFChars() threw an exception\n");
+        return NULL;
+    }
+
+    return ret;
+}
+
+jstring ff_jni_utf_chars_to_jstring(JNIEnv *env, const char *utf_chars, void *log_ctx)
+{
+    jstring ret;
+
+    ret = (*env)->NewStringUTF(env, utf_chars);
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionClear(env);
+        av_log(log_ctx, AV_LOG_ERROR, "NewStringUTF() threw an exception\n");
+        return NULL;
+    }
+
+    return ret;
+}
+
+int ff_jni_exception_get_summary(JNIEnv *env, jthrowable exception, char **error, void *log_ctx)
+{
+    int ret = 0;
+
+    AVBPrint bp;
+
+    char *name = NULL;
+    char *message = NULL;
+
+    jclass class_class = NULL;
+    jmethodID get_name_id = NULL;
+
+    jclass exception_class = NULL;
+    jmethodID get_message_id = NULL;
+
+    jstring string = NULL;
+
+    av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+
+    exception_class = (*env)->GetObjectClass(env, exception);
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionClear(env);
+        av_log(log_ctx, AV_LOG_ERROR, "Could not find Throwable class\n");
+        ret = AVERROR_EXTERNAL;
+        goto done;
+    }
+
+    class_class = (*env)->GetObjectClass(env, exception_class);
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionClear(env);
+        av_log(log_ctx, AV_LOG_ERROR, "Could not find Throwable class's class\n");
+        ret = AVERROR_EXTERNAL;
+        goto done;
+    }
+
+    get_name_id = (*env)->GetMethodID(env, class_class, "getName", "()Ljava/lang/String;");
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionClear(env);
+        av_log(log_ctx, AV_LOG_ERROR, "Could not find method Class.getName()\n");
+        ret = AVERROR_EXTERNAL;
+        goto done;
+    }
+
+    string = (*env)->CallObjectMethod(env, exception_class, get_name_id);
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionClear(env);
+        av_log(log_ctx, AV_LOG_ERROR, "Class.getName() threw an exception\n");
+        ret = AVERROR_EXTERNAL;
+        goto done;
+    }
+
+    if (string) {
+        name = ff_jni_jstring_to_utf_chars(env, string, log_ctx);
+        (*env)->DeleteLocalRef(env, string);
+        string = NULL;
+    }
+
+    get_message_id = (*env)->GetMethodID(env, exception_class, "getMessage", "()Ljava/lang/String;");
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionClear(env);
+        av_log(log_ctx, AV_LOG_ERROR, "Could not find method java/lang/Throwable.getMessage()\n");
+        ret = AVERROR_EXTERNAL;
+        goto done;
+    }
+
+    string = (*env)->CallObjectMethod(env, exception, get_message_id);
+    if ((*env)->ExceptionCheck(env)) {
+        (*env)->ExceptionClear(env);
+        av_log(log_ctx, AV_LOG_ERROR, "Throwable.getMessage() threw an exception\n");
+        ret = AVERROR_EXTERNAL;
+        goto done;
+    }
+
+    if (string) {
+        message = ff_jni_jstring_to_utf_chars(env, string, log_ctx);
+        (*env)->DeleteLocalRef(env, string);
+        string = NULL;
+    }
+
+    if (name && message) {
+        av_bprintf(&bp, "%s: %s", name, message);
+    } else if (name && !message) {
+        av_bprintf(&bp, "%s occurred", name);
+    } else if (!name && message) {
+        av_bprintf(&bp, "Exception: %s", message);
+    } else {
+        av_log(log_ctx, AV_LOG_WARNING, "Could not retreive exception name and message\n");
+        av_bprintf(&bp, "Exception occurred");
+    }
+
+    ret = av_bprint_finalize(&bp, error);
+done:
+
+    av_free(name);
+    av_free(message);
+
+    if (class_class) {
+        (*env)->DeleteLocalRef(env, class_class);
+    }
+
+    if (exception_class) {
+        (*env)->DeleteLocalRef(env, exception_class);
+    }
+
+    if (string) {
+        (*env)->DeleteLocalRef(env, string);
+    }
+
+    return ret;
+}
+
+int ff_jni_exception_check(JNIEnv *env, int log, void *log_ctx)
+{
+    int ret;
+
+    jthrowable exception;
+
+    char *message = NULL;
+
+    if (!(*(env))->ExceptionCheck((env))) {
+        return 0;
+    }
+
+    if (!log) {
+        (*(env))->ExceptionClear((env));
+        return -1;
+    }
+
+    exception = (*env)->ExceptionOccurred(env);
+    (*(env))->ExceptionClear((env));
+
+    if ((ret = ff_jni_exception_get_summary(env, exception, &message, log_ctx)) < 0) {
+        (*env)->DeleteLocalRef(env, exception);
+        return ret;
+    }
+
+    (*env)->DeleteLocalRef(env, exception);
+
+    av_log(log_ctx, AV_LOG_ERROR, "%s\n", message);
+    av_free(message);
+
+    return -1;
+}
+
+int ff_jni_init_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx)
+{
+    int i, ret = 0;
+    jclass last_clazz = NULL;
+
+    for (i = 0; jfields_mapping[i].name; i++) {
+        int mandatory = jfields_mapping[i].mandatory;
+        enum FFJniFieldType type = jfields_mapping[i].type;
+
+        if (type == FF_JNI_CLASS) {
+            jclass clazz;
+
+            last_clazz = NULL;
+
+            clazz = (*env)->FindClass(env, jfields_mapping[i].name);
+            if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) {
+                goto done;
+            }
+
+            last_clazz = *(jclass*)((uint8_t*)jfields + jfields_mapping[i].offset) =
+                    global ? (*env)->NewGlobalRef(env, clazz) : clazz;
+        } else {
+
+            if (!last_clazz) {
+                ret = AVERROR_EXTERNAL;
+                break;
+            }
+
+            switch(type) {
+            case FF_JNI_FIELD: {
+                jfieldID field_id = (*env)->GetFieldID(env, last_clazz, jfields_mapping[i].method, jfields_mapping[i].signature);
+                if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) {
+                    goto done;
+                }
+
+                *(jfieldID*)((uint8_t*)jfields + jfields_mapping[i].offset) = field_id;
+                break;
+            }
+            case FF_JNI_STATIC_FIELD: {
+                jfieldID field_id = (*env)->GetStaticFieldID(env, last_clazz, jfields_mapping[i].method, jfields_mapping[i].signature);
+                if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) {
+                    goto done;
+                }
+
+                *(jfieldID*)((uint8_t*)jfields + jfields_mapping[i].offset) = field_id;
+                break;
+            }
+            case FF_JNI_METHOD: {
+                jmethodID method_id = (*env)->GetMethodID(env, last_clazz, jfields_mapping[i].method, jfields_mapping[i].signature);
+                if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) {
+                    goto done;
+                }
+
+                *(jmethodID*)((uint8_t*)jfields + jfields_mapping[i].offset) = method_id;
+                break;
+            }
+            case FF_JNI_STATIC_METHOD: {
+                jmethodID method_id = (*env)->GetStaticMethodID(env, last_clazz, jfields_mapping[i].method, jfields_mapping[i].signature);
+                if ((ret = ff_jni_exception_check(env, mandatory, log_ctx)) < 0 && mandatory) {
+                    goto done;
+                }
+
+                *(jmethodID*)((uint8_t*)jfields + jfields_mapping[i].offset) = method_id;
+                break;
+            }
+            default:
+                av_log(log_ctx, AV_LOG_ERROR, "Unknown JNI field type\n");
+                ret = AVERROR(EINVAL);
+                goto done;
+            }
+        }
+    }
+
+done:
+    if (ret < 0) {
+        /* reset jfields in case of failure so it does not leak references */
+        ff_jni_reset_jfields(env, jfields, jfields_mapping, global, log_ctx);
+    }
+
+    return ret;
+}
+
+int ff_jni_reset_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx)
+{
+    int i;
+
+    for (i = 0; jfields_mapping[i].name; i++) {
+        enum FFJniFieldType type = jfields_mapping[i].type;
+
+        switch(type) {
+        case FF_JNI_CLASS: {
+            jclass clazz = *(jclass*)((uint8_t*)jfields + jfields_mapping[i].offset);
+            if (!clazz)
+                continue;
+
+            if (global) {
+                (*env)->DeleteGlobalRef(env, clazz);
+            } else {
+                (*env)->DeleteLocalRef(env, clazz);
+            }
+
+            *(jclass*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL;
+            break;
+        }
+        case FF_JNI_FIELD: {
+            *(jfieldID*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL;
+            break;
+        }
+        case FF_JNI_STATIC_FIELD: {
+            *(jfieldID*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL;
+            break;
+        }
+        case FF_JNI_METHOD: {
+            *(jmethodID*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL;
+            break;
+        }
+        case FF_JNI_STATIC_METHOD: {
+            *(jmethodID*)((uint8_t*)jfields + jfields_mapping[i].offset) = NULL;
+            break;
+        }
+        default:
+            av_log(log_ctx, AV_LOG_ERROR, "Unknown JNI field type\n");
+        }
+    }
+
+    return 0;
+}
diff --git a/libavcodec/ffjni.h b/libavcodec/ffjni.h
new file mode 100644
index 0000000..990c7b9
--- /dev/null
+++ b/libavcodec/ffjni.h
@@ -0,0 +1,150 @@
+/*
+ * JNI utility functions
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_FFJNI_H
+#define AVCODEC_FFJNI_H
+
+#include <jni.h>
+
+/*
+ * Attach a JNI environment to the current thread.
+ *
+ * @param attached pointer to an integer that will be set to 1 if the
+ * environment has been attached to the current thread or 0 if it is
+ * already attached.
+ * @param log_ctx context used for logging, can be NULL
+ * @return the JNI environment on success, NULL otherwise
+ */
+JNIEnv *ff_jni_attach_env(int *attached, void *log_ctx);
+
+/*
+ * Detach the JNI environment from the current thread.
+ *
+ * @param log_ctx context used for logging, can be NULL
+ * @return 0 on success, < 0 otherwise
+ */
+int ff_jni_detach_env(void *log_ctx);
+
+/*
+ * Convert a jstring to its utf characters equivalent.
+ *
+ * @param env JNI environment
+ * @param string Java string to convert
+ * @param log_ctx context used for logging, can be NULL
+ * @return a pointer to an array of unicode characters on success, NULL
+ * otherwise
+ */
+char *ff_jni_jstring_to_utf_chars(JNIEnv *env, jstring string, void *log_ctx);
+
+/*
+ * Convert utf chars to its jstring equivalent.
+ *
+ * @param env JNI environment
+ * @param utf_chars a pointer to an array of unicode characters
+ * @param log_ctx context used for logging, can be NULL
+ * @return a Java string object on success, NULL otherwise
+ */
+jstring ff_jni_utf_chars_to_jstring(JNIEnv *env, const char *utf_chars, void *log_ctx);
+
+/*
+ * Extract the error summary from a jthrowable in the form of "className: errorMessage"
+ *
+ * @param env JNI environment
+ * @param exception exception to get the summary from
+ * @param error address pointing to the error, the value is updated if a
+ * summary can be extracted
+ * @param log_ctx context used for logging, can be NULL
+ * @return 0 on success, < 0 otherwise
+ */
+int ff_jni_exception_get_summary(JNIEnv *env, jthrowable exception, char **error, void *log_ctx);
+
+/*
+ * Check if an exception has occurred,log it using av_log and clear it.
+ *
+ * @param env JNI environment
+ * @param log value used to enable logging if an exception has occurred,
+ * 0 disables logging, != 0 enables logging
+ * @param log_ctx context used for logging, can be NULL
+ */
+int ff_jni_exception_check(JNIEnv *env, int log, void *log_ctx);
+
+/*
+ * Jni field type.
+ */
+enum FFJniFieldType {
+
+    FF_JNI_CLASS,
+    FF_JNI_FIELD,
+    FF_JNI_STATIC_FIELD,
+    FF_JNI_METHOD,
+    FF_JNI_STATIC_METHOD
+
+};
+
+/*
+ * Jni field describing a class, a field or a method to be retrieved using
+ * the ff_jni_init_jfields method.
+ */
+struct FFJniField {
+
+    const char *name;
+    const char *method;
+    const char *signature;
+    enum FFJniFieldType type;
+    int offset;
+    int mandatory;
+
+};
+
+/*
+ * Retrieve class references, field ids and method ids to an arbitrary structure.
+ *
+ * @param env JNI environment
+ * @param jfields a pointer to an arbitrary structure where the different
+ * fields are declared and where the FFJNIField mapping table offsets are
+ * pointing to
+ * @param jfields_mapping null terminated array of FFJNIFields describing
+ * the class/field/method to be retrieved
+ * @param global make the classes references global. It is the caller
+ * responsibility to properly release global references.
+ * @param log_ctx context used for logging, can be NULL
+ * @return 0 on success, < 0 otherwise
+ */
+int ff_jni_init_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx);
+
+/*
+ * Delete class references, field ids and method ids of an arbitrary structure.
+ *
+ * @param env JNI environment
+ * @param jfields a pointer to an arbitrary structure where the different
+ * fields are declared and where the FFJNIField mapping table offsets are
+ * pointing to
+ * @param jfields_mapping null terminated array of FFJNIFields describing
+ * the class/field/method to be deleted
+ * @param global threat the classes references as global and delete them
+ * accordingly
+ * @param log_ctx context used for logging, can be NULL
+ * @return 0 on success, < 0 otherwise
+ */
+int ff_jni_reset_jfields(JNIEnv *env, void *jfields, const struct FFJniField *jfields_mapping, int global, void *log_ctx);
+
+#endif /* AVCODEC_FFJNI_H */
diff --git a/libavcodec/fft-fixed-test.c b/libavcodec/fft-fixed-test.c
deleted file mode 100644
index 330211e..0000000
--- a/libavcodec/fft-fixed-test.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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
- */
-
-#define FFT_FLOAT 0
-#include "fft-test.c"
diff --git a/libavcodec/fft-fixed32-test.c b/libavcodec/fft-fixed32-test.c
deleted file mode 100644
index 4bd11ce..0000000
--- a/libavcodec/fft-fixed32-test.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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
- */
-
-#define FFT_FLOAT 0
-#define FFT_FIXED_32 1
-#include "fft-test.c"
diff --git a/libavcodec/fft-test.c b/libavcodec/fft-test.c
deleted file mode 100644
index d647fde..0000000
--- a/libavcodec/fft-test.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * (c) 2002 Fabrice Bellard
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file
- * FFT and MDCT tests.
- */
-
-#include "config.h"
-
-#include <math.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "libavutil/cpu.h"
-#include "libavutil/lfg.h"
-#include "libavutil/log.h"
-#include "libavutil/mathematics.h"
-#include "libavutil/time.h"
-
-#include "fft.h"
-#if FFT_FLOAT
-#include "dct.h"
-#include "rdft.h"
-#endif
-
-/* reference fft */
-
-#define MUL16(a, b) ((a) * (b))
-
-#define CMAC(pre, pim, are, aim, bre, bim)          \
-    {                                               \
-        pre += (MUL16(are, bre) - MUL16(aim, bim)); \
-        pim += (MUL16(are, bim) + MUL16(bre, aim)); \
-    }
-
-#if FFT_FLOAT
-#define RANGE 1.0
-#define REF_SCALE(x, bits)  (x)
-#define FMT "%10.6f"
-#elif FFT_FIXED_32
-#define RANGE 8388608
-#define REF_SCALE(x, bits) (x)
-#define FMT "%6d"
-#else
-#define RANGE 16384
-#define REF_SCALE(x, bits) ((x) / (1 << (bits)))
-#define FMT "%6d"
-#endif
-
-static struct {
-    float re, im;
-} *exptab;
-
-static int fft_ref_init(int nbits, int inverse)
-{
-    int i, n = 1 << nbits;
-
-    exptab = av_malloc_array((n / 2), sizeof(*exptab));
-    if (!exptab)
-        return AVERROR(ENOMEM);
-
-    for (i = 0; i < (n / 2); i++) {
-        double alpha = 2 * M_PI * (float) i / (float) n;
-        double c1 = cos(alpha), s1 = sin(alpha);
-        if (!inverse)
-            s1 = -s1;
-        exptab[i].re = c1;
-        exptab[i].im = s1;
-    }
-    return 0;
-}
-
-static void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits)
-{
-    int i, j;
-    int n  = 1 << nbits;
-    int n2 = n >> 1;
-
-    for (i = 0; i < n; i++) {
-        double tmp_re = 0, tmp_im = 0;
-        FFTComplex *q = tab;
-        for (j = 0; j < n; j++) {
-            double s, c;
-            int k = (i * j) & (n - 1);
-            if (k >= n2) {
-                c = -exptab[k - n2].re;
-                s = -exptab[k - n2].im;
-            } else {
-                c = exptab[k].re;
-                s = exptab[k].im;
-            }
-            CMAC(tmp_re, tmp_im, c, s, q->re, q->im);
-            q++;
-        }
-        tabr[i].re = REF_SCALE(tmp_re, nbits);
-        tabr[i].im = REF_SCALE(tmp_im, nbits);
-    }
-}
-
-#if CONFIG_MDCT
-static void imdct_ref(FFTSample *out, FFTSample *in, int nbits)
-{
-    int i, k, n = 1 << nbits;
-
-    for (i = 0; i < n; i++) {
-        double sum = 0;
-        for (k = 0; k < n / 2; k++) {
-            int a = (2 * i + 1 + (n / 2)) * (2 * k + 1);
-            double f = cos(M_PI * a / (double) (2 * n));
-            sum += f * in[k];
-        }
-        out[i] = REF_SCALE(-sum, nbits - 2);
-    }
-}
-
-/* NOTE: no normalisation by 1 / N is done */
-static void mdct_ref(FFTSample *output, FFTSample *input, int nbits)
-{
-    int i, k, n = 1 << nbits;
-
-    /* do it by hand */
-    for (k = 0; k < n / 2; k++) {
-        double s = 0;
-        for (i = 0; i < n; i++) {
-            double a = (2 * M_PI * (2 * i + 1 + n / 2) * (2 * k + 1) / (4 * n));
-            s += input[i] * cos(a);
-        }
-        output[k] = REF_SCALE(s, nbits - 1);
-    }
-}
-#endif /* CONFIG_MDCT */
-
-#if FFT_FLOAT
-#if CONFIG_DCT
-static void idct_ref(FFTSample *output, FFTSample *input, int nbits)
-{
-    int i, k, n = 1 << nbits;
-
-    /* do it by hand */
-    for (i = 0; i < n; i++) {
-        double s = 0.5 * input[0];
-        for (k = 1; k < n; k++) {
-            double a = M_PI * k * (i + 0.5) / n;
-            s += input[k] * cos(a);
-        }
-        output[i] = 2 * s / n;
-    }
-}
-
-static void dct_ref(FFTSample *output, FFTSample *input, int nbits)
-{
-    int i, k, n = 1 << nbits;
-
-    /* do it by hand */
-    for (k = 0; k < n; k++) {
-        double s = 0;
-        for (i = 0; i < n; i++) {
-            double a = M_PI * k * (i + 0.5) / n;
-            s += input[i] * cos(a);
-        }
-        output[k] = s;
-    }
-}
-#endif /* CONFIG_DCT */
-#endif /* FFT_FLOAT */
-
-static FFTSample frandom(AVLFG *prng)
-{
-    return (int16_t) av_lfg_get(prng) / 32768.0 * RANGE;
-}
-
-static int check_diff(FFTSample *tab1, FFTSample *tab2, int n, double scale)
-{
-    int i, err = 0;
-    double error = 0, max = 0;
-
-    for (i = 0; i < n; i++) {
-        double e = fabs(tab1[i] - (tab2[i] / scale)) / RANGE;
-        if (e >= 1e-3) {
-            av_log(NULL, AV_LOG_ERROR, "ERROR %5d: "FMT" "FMT"\n",
-                   i, tab1[i], tab2[i]);
-            err = 1;
-        }
-        error += e * e;
-        if (e > max)
-            max = e;
-    }
-    av_log(NULL, AV_LOG_INFO, "max:%f e:%g\n", max, sqrt(error / n));
-    return err;
-}
-
-static void help(void)
-{
-    av_log(NULL, AV_LOG_INFO,
-           "usage: fft-test [-h] [-s] [-i] [-n b]\n"
-           "-h     print this help\n"
-           "-s     speed test\n"
-           "-m     (I)MDCT test\n"
-           "-d     (I)DCT test\n"
-           "-r     (I)RDFT test\n"
-           "-i     inverse transform test\n"
-           "-n b   set the transform size to 2^b\n"
-           "-f x   set scale factor for output data of (I)MDCT to x\n");
-}
-
-enum tf_transform {
-    TRANSFORM_FFT,
-    TRANSFORM_MDCT,
-    TRANSFORM_RDFT,
-    TRANSFORM_DCT,
-};
-
-#if !HAVE_GETOPT
-#include "compat/getopt.c"
-#endif
-
-int main(int argc, char **argv)
-{
-    FFTComplex *tab, *tab1, *tab_ref;
-    FFTSample *tab2;
-    enum tf_transform transform = TRANSFORM_FFT;
-    FFTContext m, s;
-#if FFT_FLOAT
-    RDFTContext r;
-    DCTContext d;
-#endif /* FFT_FLOAT */
-    int it, i, err = 1;
-    int do_speed = 0, do_inverse = 0;
-    int fft_nbits = 9, fft_size;
-    double scale = 1.0;
-    AVLFG prng;
-
-    av_lfg_init(&prng, 1);
-
-    for (;;) {
-        int c = getopt(argc, argv, "hsimrdn:f:c:");
-        if (c == -1)
-            break;
-        switch (c) {
-        case 'h':
-            help();
-            return 1;
-        case 's':
-            do_speed = 1;
-            break;
-        case 'i':
-            do_inverse = 1;
-            break;
-        case 'm':
-            transform = TRANSFORM_MDCT;
-            break;
-        case 'r':
-            transform = TRANSFORM_RDFT;
-            break;
-        case 'd':
-            transform = TRANSFORM_DCT;
-            break;
-        case 'n':
-            fft_nbits = atoi(optarg);
-            break;
-        case 'f':
-            scale = atof(optarg);
-            break;
-        case 'c':
-        {
-            unsigned cpuflags = av_get_cpu_flags();
-
-            if (av_parse_cpu_caps(&cpuflags, optarg) < 0)
-                return 1;
-
-            av_force_cpu_flags(cpuflags);
-            break;
-        }
-        }
-    }
-
-    fft_size = 1 << fft_nbits;
-    tab      = av_malloc_array(fft_size, sizeof(FFTComplex));
-    tab1     = av_malloc_array(fft_size, sizeof(FFTComplex));
-    tab_ref  = av_malloc_array(fft_size, sizeof(FFTComplex));
-    tab2     = av_malloc_array(fft_size, sizeof(FFTSample));
-
-    if (!(tab && tab1 && tab_ref && tab2))
-        goto cleanup;
-
-    switch (transform) {
-#if CONFIG_MDCT
-    case TRANSFORM_MDCT:
-        av_log(NULL, AV_LOG_INFO, "Scale factor is set to %f\n", scale);
-        if (do_inverse)
-            av_log(NULL, AV_LOG_INFO, "IMDCT");
-        else
-            av_log(NULL, AV_LOG_INFO, "MDCT");
-        ff_mdct_init(&m, fft_nbits, do_inverse, scale);
-        break;
-#endif /* CONFIG_MDCT */
-    case TRANSFORM_FFT:
-        if (do_inverse)
-            av_log(NULL, AV_LOG_INFO, "IFFT");
-        else
-            av_log(NULL, AV_LOG_INFO, "FFT");
-        ff_fft_init(&s, fft_nbits, do_inverse);
-        if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0)
-            goto cleanup;
-        break;
-#if FFT_FLOAT
-#    if CONFIG_RDFT
-    case TRANSFORM_RDFT:
-        if (do_inverse)
-            av_log(NULL, AV_LOG_INFO, "IDFT_C2R");
-        else
-            av_log(NULL, AV_LOG_INFO, "DFT_R2C");
-        ff_rdft_init(&r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C);
-        if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0)
-            goto cleanup;
-        break;
-#    endif /* CONFIG_RDFT */
-#    if CONFIG_DCT
-    case TRANSFORM_DCT:
-        if (do_inverse)
-            av_log(NULL, AV_LOG_INFO, "DCT_III");
-        else
-            av_log(NULL, AV_LOG_INFO, "DCT_II");
-        ff_dct_init(&d, fft_nbits, do_inverse ? DCT_III : DCT_II);
-        break;
-#    endif /* CONFIG_DCT */
-#endif /* FFT_FLOAT */
-    default:
-        av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n");
-        goto cleanup;
-    }
-    av_log(NULL, AV_LOG_INFO, " %d test\n", fft_size);
-
-    /* generate random data */
-
-    for (i = 0; i < fft_size; i++) {
-        tab1[i].re = frandom(&prng);
-        tab1[i].im = frandom(&prng);
-    }
-
-    /* checking result */
-    av_log(NULL, AV_LOG_INFO, "Checking...\n");
-
-    switch (transform) {
-#if CONFIG_MDCT
-    case TRANSFORM_MDCT:
-        if (do_inverse) {
-            imdct_ref(&tab_ref->re, &tab1->re, fft_nbits);
-            m.imdct_calc(&m, tab2, &tab1->re);
-            err = check_diff(&tab_ref->re, tab2, fft_size, scale);
-        } else {
-            mdct_ref(&tab_ref->re, &tab1->re, fft_nbits);
-            m.mdct_calc(&m, tab2, &tab1->re);
-            err = check_diff(&tab_ref->re, tab2, fft_size / 2, scale);
-        }
-        break;
-#endif /* CONFIG_MDCT */
-    case TRANSFORM_FFT:
-        memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
-        s.fft_permute(&s, tab);
-        s.fft_calc(&s, tab);
-
-        fft_ref(tab_ref, tab1, fft_nbits);
-        err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0);
-        break;
-#if FFT_FLOAT
-#if CONFIG_RDFT
-    case TRANSFORM_RDFT:
-    {
-        int fft_size_2 = fft_size >> 1;
-        if (do_inverse) {
-            tab1[0].im          = 0;
-            tab1[fft_size_2].im = 0;
-            for (i = 1; i < fft_size_2; i++) {
-                tab1[fft_size_2 + i].re =  tab1[fft_size_2 - i].re;
-                tab1[fft_size_2 + i].im = -tab1[fft_size_2 - i].im;
-            }
-
-            memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
-            tab2[1] = tab1[fft_size_2].re;
-
-            r.rdft_calc(&r, tab2);
-            fft_ref(tab_ref, tab1, fft_nbits);
-            for (i = 0; i < fft_size; i++) {
-                tab[i].re = tab2[i];
-                tab[i].im = 0;
-            }
-            err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 0.5);
-        } else {
-            for (i = 0; i < fft_size; i++) {
-                tab2[i]    = tab1[i].re;
-                tab1[i].im = 0;
-            }
-            r.rdft_calc(&r, tab2);
-            fft_ref(tab_ref, tab1, fft_nbits);
-            tab_ref[0].im = tab_ref[fft_size_2].re;
-            err = check_diff(&tab_ref->re, tab2, fft_size, 1.0);
-        }
-        break;
-    }
-#endif /* CONFIG_RDFT */
-#if CONFIG_DCT
-    case TRANSFORM_DCT:
-        memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
-        d.dct_calc(&d, &tab->re);
-        if (do_inverse)
-            idct_ref(&tab_ref->re, &tab1->re, fft_nbits);
-        else
-            dct_ref(&tab_ref->re, &tab1->re, fft_nbits);
-        err = check_diff(&tab_ref->re, &tab->re, fft_size, 1.0);
-        break;
-#endif /* CONFIG_DCT */
-#endif /* FFT_FLOAT */
-    }
-
-    /* do a speed test */
-
-    if (do_speed) {
-        int64_t time_start, duration;
-        int nb_its;
-
-        av_log(NULL, AV_LOG_INFO, "Speed test...\n");
-        /* we measure during about 1 seconds */
-        nb_its = 1;
-        for (;;) {
-            time_start = av_gettime_relative();
-            for (it = 0; it < nb_its; it++) {
-                switch (transform) {
-                case TRANSFORM_MDCT:
-                    if (do_inverse)
-                        m.imdct_calc(&m, &tab->re, &tab1->re);
-                    else
-                        m.mdct_calc(&m, &tab->re, &tab1->re);
-                    break;
-                case TRANSFORM_FFT:
-                    memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
-                    s.fft_calc(&s, tab);
-                    break;
-#if FFT_FLOAT
-                case TRANSFORM_RDFT:
-                    memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
-                    r.rdft_calc(&r, tab2);
-                    break;
-                case TRANSFORM_DCT:
-                    memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
-                    d.dct_calc(&d, tab2);
-                    break;
-#endif /* FFT_FLOAT */
-                }
-            }
-            duration = av_gettime_relative() - time_start;
-            if (duration >= 1000000)
-                break;
-            nb_its *= 2;
-        }
-        av_log(NULL, AV_LOG_INFO,
-               "time: %0.1f us/transform [total time=%0.2f s its=%d]\n",
-               (double) duration / nb_its,
-               (double) duration / 1000000.0,
-               nb_its);
-    }
-
-    switch (transform) {
-#if CONFIG_MDCT
-    case TRANSFORM_MDCT:
-        ff_mdct_end(&m);
-        break;
-#endif /* CONFIG_MDCT */
-    case TRANSFORM_FFT:
-        ff_fft_end(&s);
-        break;
-#if FFT_FLOAT
-#    if CONFIG_RDFT
-    case TRANSFORM_RDFT:
-        ff_rdft_end(&r);
-        break;
-#    endif /* CONFIG_RDFT */
-#    if CONFIG_DCT
-    case TRANSFORM_DCT:
-        ff_dct_end(&d);
-        break;
-#    endif /* CONFIG_DCT */
-#endif /* FFT_FLOAT */
-    }
-
-cleanup:
-    av_free(tab);
-    av_free(tab1);
-    av_free(tab2);
-    av_free(tab_ref);
-    av_free(exptab);
-
-    if (err)
-        printf("Error: %d.\n", err);
-
-    return !!err;
-}
diff --git a/libavcodec/fft.h b/libavcodec/fft.h
index 64f0f63..c858570 100644
--- a/libavcodec/fft.h
+++ b/libavcodec/fft.h
@@ -110,6 +110,7 @@ struct FFTContext {
     void (*mdct_calcw)(struct FFTContext *s, FFTDouble *output, const FFTSample *input);
     enum fft_permutation_type fft_permutation;
     enum mdct_permutation_type mdct_permutation;
+    uint32_t *revtab32;
 };
 
 #if CONFIG_HARDCODED_TABLES
@@ -134,7 +135,8 @@ extern COSTABLE(8192);
 extern COSTABLE(16384);
 extern COSTABLE(32768);
 extern COSTABLE(65536);
-extern COSTABLE_CONST FFTSample* const FFT_NAME(ff_cos_tabs)[17];
+extern COSTABLE(131072);
+extern COSTABLE_CONST FFTSample* const FFT_NAME(ff_cos_tabs)[18];
 
 #define ff_init_ff_cos_tabs FFT_NAME(ff_init_ff_cos_tabs)
 
diff --git a/libavcodec/fft_init_table.c b/libavcodec/fft_init_table.c
index 4d74f8a..c488018 100644
--- a/libavcodec/fft_init_table.c
+++ b/libavcodec/fft_init_table.c
@@ -54,137 +54,265 @@
 #include "libavcodec/fft_table.h"
 
 const int32_t ff_w_tab_sr[MAX_FFT_SIZE/(4*16)] = {
-    2147483647, 2147481121, 2147473542, 2147460908, 2147443222, 2147420483, 2147392690, 2147359845,
-    2147321946, 2147278995, 2147230991, 2147177934, 2147119825, 2147056664, 2146988450, 2146915184,
-    2146836866, 2146753497, 2146665076, 2146571603, 2146473080, 2146369505, 2146260881, 2146147205,
-    2146028480, 2145904705, 2145775880, 2145642006, 2145503083, 2145359112, 2145210092, 2145056025,
-    2144896910, 2144732748, 2144563539, 2144389283, 2144209982, 2144025635, 2143836244, 2143641807,
-    2143442326, 2143237802, 2143028234, 2142813624, 2142593971, 2142369276, 2142139541, 2141904764,
-    2141664948, 2141420092, 2141170197, 2140915264, 2140655293, 2140390284, 2140120240, 2139845159,
-    2139565043, 2139279892, 2138989708, 2138694490, 2138394240, 2138088958, 2137778644, 2137463301,
-    2137142927, 2136817525, 2136487095, 2136151637, 2135811153, 2135465642, 2135115107, 2134759548,
-    2134398966, 2134033361, 2133662734, 2133287087, 2132906420, 2132520734, 2132130030, 2131734309,
-    2131333572, 2130927819, 2130517052, 2130101272, 2129680480, 2129254676, 2128823862, 2128388038,
-    2127947206, 2127501367, 2127050522, 2126594672, 2126133817, 2125667960, 2125197100, 2124721240,
-    2124240380, 2123754522, 2123263666, 2122767814, 2122266967, 2121761126, 2121250292, 2120734467,
-    2120213651, 2119687847, 2119157054, 2118621275, 2118080511, 2117534762, 2116984031, 2116428319,
-    2115867626, 2115301954, 2114731305, 2114155680, 2113575080, 2112989506, 2112398960, 2111803444,
-    2111202959, 2110597505, 2109987085, 2109371700, 2108751352, 2108126041, 2107495770, 2106860540,
-    2106220352, 2105575208, 2104925109, 2104270057, 2103610054, 2102945101, 2102275199, 2101600350,
-    2100920556, 2100235819, 2099546139, 2098851519, 2098151960, 2097447464, 2096738032, 2096023667,
-    2095304370, 2094580142, 2093850985, 2093116901, 2092377892, 2091633960, 2090885105, 2090131331,
-    2089372638, 2088609029, 2087840505, 2087067068, 2086288720, 2085505463, 2084717298, 2083924228,
-    2083126254, 2082323379, 2081515603, 2080702930, 2079885360, 2079062896, 2078235540, 2077403294,
-    2076566160, 2075724139, 2074877233, 2074025446, 2073168777, 2072307231, 2071440808, 2070569511,
-    2069693342, 2068812302, 2067926394, 2067035621, 2066139983, 2065239484, 2064334124, 2063423908,
-    2062508835, 2061588910, 2060664133, 2059734508, 2058800036, 2057860719, 2056916560, 2055967560,
-    2055013723, 2054055050, 2053091544, 2052123207, 2051150040, 2050172048, 2049189231, 2048201592,
-    2047209133, 2046211857, 2045209767, 2044202863, 2043191150, 2042174628, 2041153301, 2040127172,
-    2039096241, 2038060512, 2037019988, 2035974670, 2034924562, 2033869665, 2032809982, 2031745516,
-    2030676269, 2029602243, 2028523442, 2027439867, 2026351522, 2025258408, 2024160529, 2023057887,
-    2021950484, 2020838323, 2019721407, 2018599739, 2017473321, 2016342155, 2015206245, 2014065592,
-    2012920201, 2011770073, 2010615210, 2009455617, 2008291295, 2007122248, 2005948478, 2004769987,
-    2003586779, 2002398857, 2001206222, 2000008879, 1998806829, 1997600076, 1996388622, 1995172471,
-    1993951625, 1992726087, 1991495860, 1990260946, 1989021350, 1987777073, 1986528118, 1985274489,
-    1984016189, 1982753220, 1981485585, 1980213288, 1978936331, 1977654717, 1976368450, 1975077532,
-    1973781967, 1972481757, 1971176906, 1969867417, 1968553292, 1967234535, 1965911148, 1964583136,
-    1963250501, 1961913246, 1960571375, 1959224890, 1957873796, 1956518093, 1955157788, 1953792881,
-    1952423377, 1951049279, 1949670589, 1948287312, 1946899451, 1945507008, 1944109987, 1942708392,
-    1941302225, 1939891490, 1938476190, 1937056329, 1935631910, 1934202936, 1932769411, 1931331338,
-    1929888720, 1928441561, 1926989864, 1925533633, 1924072871, 1922607581, 1921137767, 1919663432,
-    1918184581, 1916701216, 1915213340, 1913720958, 1912224073, 1910722688, 1909216806, 1907706433,
-    1906191570, 1904672222, 1903148392, 1901620084, 1900087301, 1898550047, 1897008325, 1895462140,
-    1893911494, 1892356392, 1890796837, 1889232832, 1887664383, 1886091491, 1884514161, 1882932397,
-    1881346202, 1879755580, 1878160535, 1876561070, 1874957189, 1873348897, 1871736196, 1870119091,
-    1868497586, 1866871683, 1865241388, 1863606704, 1861967634, 1860324183, 1858676355, 1857024153,
-    1855367581, 1853706643, 1852041343, 1850371686, 1848697674, 1847019312, 1845336604, 1843649553,
-    1841958164, 1840262441, 1838562388, 1836858008, 1835149306, 1833436286, 1831718951, 1829997307,
-    1828271356, 1826541103, 1824806552, 1823067707, 1821324572, 1819577151, 1817825449, 1816069469,
-    1814309216, 1812544694, 1810775906, 1809002858, 1807225553, 1805443995, 1803658189, 1801868139,
-    1800073849, 1798275323, 1796472565, 1794665580, 1792854372, 1791038946, 1789219305, 1787395453,
-    1785567396, 1783735137, 1781898681, 1780058032, 1778213194, 1776364172, 1774510970, 1772653593,
-    1770792044, 1768926328, 1767056450, 1765182414, 1763304224, 1761421885, 1759535401, 1757644777,
-    1755750017, 1753851126, 1751948107, 1750040966, 1748129707, 1746214334, 1744294853, 1742371267,
-    1740443581, 1738511799, 1736575927, 1734635968, 1732691928, 1730743810, 1728791620, 1726835361,
-    1724875040, 1722910659, 1720942225, 1718969740, 1716993211, 1715012642, 1713028037, 1711039401,
-    1709046739, 1707050055, 1705049355, 1703044642, 1701035922, 1699023199, 1697006479, 1694985765,
-    1692961062, 1690932376, 1688899711, 1686863072, 1684822463, 1682777890, 1680729357, 1678676870,
-    1676620432, 1674560049, 1672495725, 1670427466, 1668355276, 1666279161, 1664199124, 1662115172,
-    1660027308, 1657935539, 1655839867, 1653740300, 1651636841, 1649529496, 1647418269, 1645303166,
-    1643184191, 1641061349, 1638934646, 1636804087, 1634669676, 1632531418, 1630389319, 1628243383,
-    1626093616, 1623940023, 1621782608, 1619621377, 1617456335, 1615287487, 1613114838, 1610938393,
-    1608758157, 1606574136, 1604386335, 1602194758, 1599999411, 1597800299, 1595597428, 1593390801,
-    1591180426, 1588966306, 1586748447, 1584526854, 1582301533, 1580072489, 1577839726, 1575603251,
-    1573363068, 1571119183, 1568871601, 1566620327, 1564365367, 1562106725, 1559844408, 1557578421,
-    1555308768, 1553035455, 1550758488, 1548477872, 1546193612, 1543905714, 1541614183, 1539319024,
-    1537020244, 1534717846, 1532411837, 1530102222, 1527789007, 1525472197, 1523151797, 1520827813,
-    1518500250, 1516169114, 1513834411, 1511496145, 1509154322, 1506808949, 1504460029, 1502107570,
-    1499751576, 1497392053, 1495029006, 1492662441, 1490292364, 1487918781, 1485541696, 1483161115,
-    1480777044, 1478389489, 1475998456, 1473603949, 1471205974, 1468804538, 1466399645, 1463991302,
-    1461579514, 1459164286, 1456745625, 1454323536, 1451898025, 1449469098, 1447036760, 1444601017,
-    1442161874, 1439719338, 1437273414, 1434824109, 1432371426, 1429915374, 1427455956, 1424993180,
-    1422527051, 1420057574, 1417584755, 1415108601, 1412629117, 1410146309, 1407660183, 1405170745,
-    1402678000, 1400181954, 1397682613, 1395179984, 1392674072, 1390164882, 1387652422, 1385136696,
-    1382617710, 1380095472, 1377569986, 1375041258, 1372509294, 1369974101, 1367435685, 1364894050,
-    1362349204, 1359801152, 1357249901, 1354695455, 1352137822, 1349577007, 1347013017, 1344445857,
-    1341875533, 1339302052, 1336725419, 1334145641, 1331562723, 1328976672, 1326387494, 1323795195,
-    1321199781, 1318601257, 1315999631, 1313394909, 1310787095, 1308176198, 1305562222, 1302945174,
-    1300325060, 1297701886, 1295075659, 1292446384, 1289814068, 1287178717, 1284540337, 1281898935,
-    1279254516, 1276607086, 1273956653, 1271303222, 1268646800, 1265987392, 1263325005, 1260659646,
-    1257991320, 1255320034, 1252645794, 1249968606, 1247288478, 1244605414, 1241919421, 1239230506,
-    1236538675, 1233843935, 1231146291, 1228445750, 1225742318, 1223036002, 1220326809, 1217614743,
-    1214899813, 1212182024, 1209461382, 1206737894, 1204011567, 1201282407, 1198550419, 1195815612,
-    1193077991, 1190337562, 1187594332, 1184848308, 1182099496, 1179347902, 1176593533, 1173836395,
-    1171076495, 1168313840, 1165548435, 1162780288, 1160009405, 1157235792, 1154459456, 1151680403,
-    1148898640, 1146114174, 1143327011, 1140537158, 1137744621, 1134949406, 1132151521, 1129350972,
-    1126547765, 1123741908, 1120933406, 1118122267, 1115308496, 1112492101, 1109673089, 1106851465,
-    1104027237, 1101200410, 1098370993, 1095538991, 1092704411, 1089867259, 1087027544, 1084185270,
-    1081340445, 1078493076, 1075643169, 1072790730, 1069935768, 1067078288, 1064218296, 1061355801,
-    1058490808, 1055623324, 1052753357, 1049880912, 1047005996, 1044128617, 1041248781, 1038366495,
-    1035481766, 1032594600, 1029705004, 1026812985, 1023918550, 1021021705, 1018122458, 1015220816,
-    1012316784, 1009410370, 1006501581, 1003590424, 1000676905,  997761031,  994842810,  991922248,
-     988999351,  986074127,  983146583,  980216726,  977284562,  974350098,  971413342,  968474300,
-     965532978,  962589385,  959643527,  956695411,  953745043,  950792431,  947837582,  944880503,
-     941921200,  938959681,  935995952,  933030021,  930061894,  927091579,  924119082,  921144411,
-     918167572,  915188572,  912207419,  909224120,  906238681,  903251110,  900261413,  897269597,
-     894275671,  891279640,  888281512,  885281293,  882278992,  879274614,  876268167,  873259659,
-     870249095,  867236484,  864221832,  861205147,  858186435,  855165703,  852142959,  849118210,
-     846091463,  843062726,  840032004,  836999305,  833964638,  830928007,  827889422,  824848888,
-     821806413,  818762005,  815715670,  812667415,  809617249,  806565177,  803511207,  800455346,
-     797397602,  794337982,  791276492,  788213141,  785147934,  782080880,  779011986,  775941259,
-     772868706,  769794334,  766718151,  763640164,  760560380,  757478806,  754395449,  751310318,
-     748223418,  745134758,  742044345,  738952186,  735858287,  732762657,  729665303,  726566232,
-     723465451,  720362968,  717258790,  714152924,  711045377,  707936158,  704825272,  701712728,
-     698598533,  695482694,  692365218,  689246113,  686125387,  683003045,  679879097,  676753549,
-     673626408,  670497682,  667367379,  664235505,  661102068,  657967075,  654830535,  651692453,
-     648552838,  645411696,  642269036,  639124865,  635979190,  632832018,  629683357,  626533215,
-     623381598,  620228514,  617073971,  613917975,  610760536,  607601658,  604441352,  601279623,
-     598116479,  594951927,  591785976,  588618632,  585449903,  582279796,  579108320,  575935480,
-     572761285,  569585743,  566408860,  563230645,  560051104,  556870245,  553688076,  550504604,
-     547319836,  544133781,  540946445,  537757837,  534567963,  531376831,  528184449,  524990824,
-     521795963,  518599875,  515402566,  512204045,  509004318,  505803394,  502601279,  499397982,
-     496193509,  492987869,  489781069,  486573117,  483364019,  480153784,  476942419,  473729932,
-     470516330,  467301622,  464085813,  460868912,  457650927,  454431865,  451211734,  447990541,
-     444768294,  441545000,  438320667,  435095303,  431868915,  428641511,  425413098,  422183684,
-     418953276,  415721883,  412489512,  409256170,  406021865,  402786604,  399550396,  396313247,
-     393075166,  389836160,  386596237,  383355404,  380113669,  376871039,  373627523,  370383128,
-     367137861,  363891730,  360644742,  357396906,  354148230,  350898719,  347648383,  344397230,
-     341145265,  337892498,  334638936,  331384586,  328129457,  324873555,  321616889,  318359466,
-     315101295,  311842381,  308582734,  305322361,  302061269,  298799466,  295536961,  292273760,
-     289009871,  285745302,  282480061,  279214155,  275947592,  272680379,  269412525,  266144038,
-     262874923,  259605191,  256334847,  253063900,  249792358,  246520228,  243247518,  239974235,
-     236700388,  233425984,  230151030,  226875535,  223599506,  220322951,  217045878,  213768293,
-     210490206,  207211624,  203932553,  200653003,  197372981,  194092495,  190811551,  187530159,
-     184248325,  180966058,  177683365,  174400254,  171116733,  167832808,  164548489,  161263783,
-     157978697,  154693240,  151407418,  148121241,  144834714,  141547847,  138260647,  134973122,
-     131685278,  128397125,  125108670,  121819921,  118530885,  115241570,  111951983,  108662134,
-     105372028,  102081675,   98791081,   95500255,   92209205,   88917937,   85626460,   82334782,
-      79042909,   75750851,   72458615,   69166208,   65873638,   62580914,   59288042,   55995030,
-      52701887,   49408620,   46115236,   42821744,   39528151,   36234466,   32940695,   29646846,
-      26352928,   23058947,   19764913,   16470832,   13176712,    9882561,    6588387,    3294197
+2147483647, 2147483016, 2147481121, 2147477963, 2147473542, 2147467857, 2147460908, 2147452697,
+2147443222, 2147432484, 2147420483, 2147407218, 2147392690, 2147376899, 2147359845, 2147341527,
+2147321946, 2147301102, 2147278995, 2147255625, 2147230991, 2147205094, 2147177934, 2147149511,
+2147119825, 2147088876, 2147056664, 2147023188, 2146988450, 2146952448, 2146915184, 2146876656,
+2146836866, 2146795813, 2146753497, 2146709917, 2146665076, 2146618971, 2146571603, 2146522973,
+2146473080, 2146421924, 2146369505, 2146315824, 2146260881, 2146204674, 2146147205, 2146088474,
+2146028480, 2145967224, 2145904705, 2145840924, 2145775880, 2145709574, 2145642006, 2145573176,
+2145503083, 2145431729, 2145359112, 2145285233, 2145210092, 2145133690, 2145056025, 2144977098,
+2144896910, 2144815460, 2144732748, 2144648774, 2144563539, 2144477042, 2144389283, 2144300264,
+2144209982, 2144118439, 2144025635, 2143931570, 2143836244, 2143739656, 2143641807, 2143542697,
+2143442326, 2143340694, 2143237802, 2143133648, 2143028234, 2142921559, 2142813624, 2142704427,
+2142593971, 2142482254, 2142369276, 2142255039, 2142139541, 2142022783, 2141904764, 2141785486,
+2141664948, 2141543150, 2141420092, 2141295774, 2141170197, 2141043360, 2140915264, 2140785908,
+2140655293, 2140523418, 2140390284, 2140255892, 2140120240, 2139983329, 2139845159, 2139705730,
+2139565043, 2139423097, 2139279892, 2139135429, 2138989708, 2138842728, 2138694490, 2138544994,
+2138394240, 2138242228, 2138088958, 2137934430, 2137778644, 2137621601, 2137463301, 2137303743,
+2137142927, 2136980855, 2136817525, 2136652938, 2136487095, 2136319994, 2136151637, 2135982023,
+2135811153, 2135639026, 2135465642, 2135291003, 2135115107, 2134937956, 2134759548, 2134579885,
+2134398966, 2134216791, 2134033361, 2133848675, 2133662734, 2133475538, 2133287087, 2133097381,
+2132906420, 2132714204, 2132520734, 2132326009, 2132130030, 2131932796, 2131734309, 2131534567,
+2131333572, 2131131322, 2130927819, 2130723062, 2130517052, 2130309789, 2130101272, 2129891502,
+2129680480, 2129468204, 2129254676, 2129039895, 2128823862, 2128606576, 2128388038, 2128168248,
+2127947206, 2127724913, 2127501367, 2127276570, 2127050522, 2126823222, 2126594672, 2126364870,
+2126133817, 2125901514, 2125667960, 2125433155, 2125197100, 2124959795, 2124721240, 2124481435,
+2124240380, 2123998076, 2123754522, 2123509718, 2123263666, 2123016364, 2122767814, 2122518015,
+2122266967, 2122014670, 2121761126, 2121506333, 2121250292, 2120993003, 2120734467, 2120474683,
+2120213651, 2119951372, 2119687847, 2119423074, 2119157054, 2118889788, 2118621275, 2118351516,
+2118080511, 2117808259, 2117534762, 2117260020, 2116984031, 2116706797, 2116428319, 2116148595,
+2115867626, 2115585412, 2115301954, 2115017252, 2114731305, 2114444114, 2114155680, 2113866001,
+2113575080, 2113282914, 2112989506, 2112694855, 2112398960, 2112101824, 2111803444, 2111503822,
+2111202959, 2110900853, 2110597505, 2110292916, 2109987085, 2109680013, 2109371700, 2109062146,
+2108751352, 2108439317, 2108126041, 2107811526, 2107495770, 2107178775, 2106860540, 2106541065,
+2106220352, 2105898399, 2105575208, 2105250778, 2104925109, 2104598202, 2104270057, 2103940674,
+2103610054, 2103278196, 2102945101, 2102610768, 2102275199, 2101938393, 2101600350, 2101261071,
+2100920556, 2100578805, 2100235819, 2099891596, 2099546139, 2099199446, 2098851519, 2098502357,
+2098151960, 2097800329, 2097447464, 2097093365, 2096738032, 2096381466, 2096023667, 2095664635,
+2095304370, 2094942872, 2094580142, 2094216179, 2093850985, 2093484559, 2093116901, 2092748012,
+2092377892, 2092006541, 2091633960, 2091260147, 2090885105, 2090508833, 2090131331, 2089752599,
+2089372638, 2088991448, 2088609029, 2088225381, 2087840505, 2087454400, 2087067068, 2086678508,
+2086288720, 2085897705, 2085505463, 2085111994, 2084717298, 2084321376, 2083924228, 2083525854,
+2083126254, 2082725429, 2082323379, 2081920103, 2081515603, 2081109879, 2080702930, 2080294757,
+2079885360, 2079474740, 2079062896, 2078649830, 2078235540, 2077820028, 2077403294, 2076985338,
+2076566160, 2076145760, 2075724139, 2075301296, 2074877233, 2074451950, 2074025446, 2073597721,
+2073168777, 2072738614, 2072307231, 2071874629, 2071440808, 2071005769, 2070569511, 2070132035,
+2069693342, 2069253430, 2068812302, 2068369957, 2067926394, 2067481616, 2067035621, 2066588410,
+2066139983, 2065690341, 2065239484, 2064787411, 2064334124, 2063879623, 2063423908, 2062966978,
+2062508835, 2062049479, 2061588910, 2061127128, 2060664133, 2060199927, 2059734508, 2059267877,
+2058800036, 2058330983, 2057860719, 2057389244, 2056916560, 2056442665, 2055967560, 2055491246,
+2055013723, 2054534991, 2054055050, 2053573901, 2053091544, 2052607979, 2052123207, 2051637227,
+2051150040, 2050661647, 2050172048, 2049681242, 2049189231, 2048696014, 2048201592, 2047705965,
+2047209133, 2046711097, 2046211857, 2045711414, 2045209767, 2044706916, 2044202863, 2043697608,
+2043191150, 2042683490, 2042174628, 2041664565, 2041153301, 2040640837, 2040127172, 2039612306,
+2039096241, 2038578976, 2038060512, 2037540850, 2037019988, 2036497928, 2035974670, 2035450215,
+2034924562, 2034397712, 2033869665, 2033340422, 2032809982, 2032278347, 2031745516, 2031211490,
+2030676269, 2030139853, 2029602243, 2029063439, 2028523442, 2027982251, 2027439867, 2026896291,
+2026351522, 2025805561, 2025258408, 2024710064, 2024160529, 2023609803, 2023057887, 2022504780,
+2021950484, 2021394998, 2020838323, 2020280460, 2019721407, 2019161167, 2018599739, 2018037123,
+2017473321, 2016908331, 2016342155, 2015774793, 2015206245, 2014636511, 2014065592, 2013493489,
+2012920201, 2012345729, 2011770073, 2011193233, 2010615210, 2010036005, 2009455617, 2008874047,
+2008291295, 2007707362, 2007122248, 2006535953, 2005948478, 2005359822, 2004769987, 2004178973,
+2003586779, 2002993407, 2002398857, 2001803128, 2001206222, 2000608139, 2000008879, 1999408442,
+1998806829, 1998204040, 1997600076, 1996994937, 1996388622, 1995781134, 1995172471, 1994562635,
+1993951625, 1993339442, 1992726087, 1992111559, 1991495860, 1990878989, 1990260946, 1989641733,
+1989021350, 1988399796, 1987777073, 1987153180, 1986528118, 1985901888, 1985274489, 1984645923,
+1984016189, 1983385288, 1982753220, 1982119985, 1981485585, 1980850019, 1980213288, 1979575392,
+1978936331, 1978296106, 1977654717, 1977012165, 1976368450, 1975723572, 1975077532, 1974430331,
+1973781967, 1973132443, 1972481757, 1971829912, 1971176906, 1970522741, 1969867417, 1969210933,
+1968553292, 1967894492, 1967234535, 1966573420, 1965911148, 1965247720, 1964583136, 1963917396,
+1963250501, 1962582451, 1961913246, 1961242888, 1960571375, 1959898709, 1959224890, 1958549919,
+1957873796, 1957196520, 1956518093, 1955838516, 1955157788, 1954475909, 1953792881, 1953108703,
+1952423377, 1951736902, 1951049279, 1950360508, 1949670589, 1948979524, 1948287312, 1947593954,
+1946899451, 1946203802, 1945507008, 1944809070, 1944109987, 1943409761, 1942708392, 1942005880,
+1941302225, 1940597428, 1939891490, 1939184411, 1938476190, 1937766830, 1937056329, 1936344689,
+1935631910, 1934917992, 1934202936, 1933486742, 1932769411, 1932050943, 1931331338, 1930610597,
+1929888720, 1929165708, 1928441561, 1927716279, 1926989864, 1926262315, 1925533633, 1924803818,
+1924072871, 1923340791, 1922607581, 1921873239, 1921137767, 1920401165, 1919663432, 1918924571,
+1918184581, 1917443462, 1916701216, 1915957841, 1915213340, 1914467712, 1913720958, 1912973078,
+1912224073, 1911473942, 1910722688, 1909970309, 1909216806, 1908462181, 1907706433, 1906949562,
+1906191570, 1905432457, 1904672222, 1903910867, 1903148392, 1902384797, 1901620084, 1900854251,
+1900087301, 1899319232, 1898550047, 1897779744, 1897008325, 1896235790, 1895462140, 1894687374,
+1893911494, 1893134500, 1892356392, 1891577171, 1890796837, 1890015391, 1889232832, 1888449163,
+1887664383, 1886878492, 1886091491, 1885303381, 1884514161, 1883723833, 1882932397, 1882139853,
+1881346202, 1880551444, 1879755580, 1878958610, 1878160535, 1877361354, 1876561070, 1875759681,
+1874957189, 1874153594, 1873348897, 1872543097, 1871736196, 1870928194, 1870119091, 1869308888,
+1868497586, 1867685184, 1866871683, 1866057085, 1865241388, 1864424594, 1863606704, 1862787717,
+1861967634, 1861146456, 1860324183, 1859500816, 1858676355, 1857850800, 1857024153, 1856196413,
+1855367581, 1854537657, 1853706643, 1852874538, 1852041343, 1851207059, 1850371686, 1849535224,
+1848697674, 1847859036, 1847019312, 1846178501, 1845336604, 1844493621, 1843649553, 1842804401,
+1841958164, 1841110844, 1840262441, 1839412956, 1838562388, 1837710739, 1836858008, 1836004197,
+1835149306, 1834293336, 1833436286, 1832578158, 1831718951, 1830858668, 1829997307, 1829134869,
+1828271356, 1827406767, 1826541103, 1825674364, 1824806552, 1823937666, 1823067707, 1822196675,
+1821324572, 1820451397, 1819577151, 1818701835, 1817825449, 1816947994, 1816069469, 1815189877,
+1814309216, 1813427489, 1812544694, 1811660833, 1810775906, 1809889915, 1809002858, 1808114737,
+1807225553, 1806335305, 1805443995, 1804551623, 1803658189, 1802763694, 1801868139, 1800971523,
+1800073849, 1799175115, 1798275323, 1797374472, 1796472565, 1795569601, 1794665580, 1793760504,
+1792854372, 1791947186, 1791038946, 1790129652, 1789219305, 1788307905, 1787395453, 1786481950,
+1785567396, 1784651792, 1783735137, 1782817434, 1781898681, 1780978881, 1780058032, 1779136137,
+1778213194, 1777289206, 1776364172, 1775438094, 1774510970, 1773582803, 1772653593, 1771723340,
+1770792044, 1769859707, 1768926328, 1767991909, 1767056450, 1766119952, 1765182414, 1764243838,
+1763304224, 1762363573, 1761421885, 1760479161, 1759535401, 1758590607, 1757644777, 1756697914,
+1755750017, 1754801087, 1753851126, 1752900132, 1751948107, 1750995052, 1750040966, 1749085851,
+1748129707, 1747172535, 1746214334, 1745255107, 1744294853, 1743333573, 1742371267, 1741407936,
+1740443581, 1739478202, 1738511799, 1737544374, 1736575927, 1735606458, 1734635968, 1733664458,
+1732691928, 1731718378, 1730743810, 1729768224, 1728791620, 1727813999, 1726835361, 1725855708,
+1724875040, 1723893357, 1722910659, 1721926948, 1720942225, 1719956488, 1718969740, 1717981981,
+1716993211, 1716003431, 1715012642, 1714020844, 1713028037, 1712034223, 1711039401, 1710043573,
+1709046739, 1708048900, 1707050055, 1706050207, 1705049355, 1704047500, 1703044642, 1702040783,
+1701035922, 1700030061, 1699023199, 1698015339, 1697006479, 1695996621, 1694985765, 1693973912,
+1692961062, 1691947217, 1690932376, 1689916541, 1688899711, 1687881888, 1686863072, 1685843263,
+1684822463, 1683800672, 1682777890, 1681754118, 1680729357, 1679703608, 1678676870, 1677649144,
+1676620432, 1675590733, 1674560049, 1673528379, 1672495725, 1671462087, 1670427466, 1669391862,
+1668355276, 1667317709, 1666279161, 1665239632, 1664199124, 1663157637, 1662115172, 1661071729,
+1660027308, 1658981911, 1657935539, 1656888190, 1655839867, 1654790570, 1653740300, 1652689057,
+1651636841, 1650583654, 1649529496, 1648474367, 1647418269, 1646361202, 1645303166, 1644244162,
+1643184191, 1642123253, 1641061349, 1639998480, 1638934646, 1637869848, 1636804087, 1635737362,
+1634669676, 1633601027, 1632531418, 1631460848, 1630389319, 1629316830, 1628243383, 1627168978,
+1626093616, 1625017297, 1623940023, 1622861793, 1621782608, 1620702469, 1619621377, 1618539332,
+1617456335, 1616372386, 1615287487, 1614201637, 1613114838, 1612027089, 1610938393, 1609848749,
+1608758157, 1607666620, 1606574136, 1605480708, 1604386335, 1603291018, 1602194758, 1601097555,
+1599999411, 1598900325, 1597800299, 1596699333, 1595597428, 1594494583, 1593390801, 1592286082,
+1591180426, 1590073833, 1588966306, 1587857843, 1586748447, 1585638117, 1584526854, 1583414660,
+1582301533, 1581187476, 1580072489, 1578956572, 1577839726, 1576721952, 1575603251, 1574483623,
+1573363068, 1572241588, 1571119183, 1569995854, 1568871601, 1567746425, 1566620327, 1565493307,
+1564365367, 1563236506, 1562106725, 1560976026, 1559844408, 1558711873, 1557578421, 1556444052,
+1555308768, 1554172569, 1553035455, 1551897428, 1550758488, 1549618636, 1548477872, 1547336197,
+1546193612, 1545050118, 1543905714, 1542760402, 1541614183, 1540467057, 1539319024, 1538170087,
+1537020244, 1535869497, 1534717846, 1533565293, 1532411837, 1531257480, 1530102222, 1528946064,
+1527789007, 1526631051, 1525472197, 1524312445, 1523151797, 1521990252, 1520827813, 1519664478,
+1518500250, 1517335128, 1516169114, 1515002208, 1513834411, 1512665723, 1511496145, 1510325678,
+1509154322, 1507982079, 1506808949, 1505634932, 1504460029, 1503284242, 1502107570, 1500930014,
+1499751576, 1498572255, 1497392053, 1496210969, 1495029006, 1493846163, 1492662441, 1491477842,
+1490292364, 1489106011, 1487918781, 1486730675, 1485541696, 1484351842, 1483161115, 1481969516,
+1480777044, 1479583702, 1478389489, 1477194407, 1475998456, 1474801636, 1473603949, 1472405394,
+1471205974, 1470005688, 1468804538, 1467602523, 1466399645, 1465195904, 1463991302, 1462785838,
+1461579514, 1460372329, 1459164286, 1457955385, 1456745625, 1455535009, 1454323536, 1453111208,
+1451898025, 1450683988, 1449469098, 1448253355, 1447036760, 1445819314, 1444601017, 1443381870,
+1442161874, 1440941030, 1439719338, 1438496799, 1437273414, 1436049184, 1434824109, 1433598189,
+1432371426, 1431143821, 1429915374, 1428686085, 1427455956, 1426224988, 1424993180, 1423760534,
+1422527051, 1421292730, 1420057574, 1418821582, 1417584755, 1416347095, 1415108601, 1413869275,
+1412629117, 1411388129, 1410146309, 1408903661, 1407660183, 1406415878, 1405170745, 1403924785,
+1402678000, 1401430389, 1400181954, 1398932695, 1397682613, 1396431709, 1395179984, 1393927438,
+1392674072, 1391419886, 1390164882, 1388909060, 1387652422, 1386394966, 1385136696, 1383877610,
+1382617710, 1381356997, 1380095472, 1378833134, 1377569986, 1376306026, 1375041258, 1373775680,
+1372509294, 1371242101, 1369974101, 1368705296, 1367435685, 1366165269, 1364894050, 1363622028,
+1362349204, 1361075579, 1359801152, 1358525926, 1357249901, 1355973077, 1354695455, 1353417037,
+1352137822, 1350857812, 1349577007, 1348295409, 1347013017, 1345729833, 1344445857, 1343161090,
+1341875533, 1340589187, 1339302052, 1338014129, 1336725419, 1335435923, 1334145641, 1332854574,
+1331562723, 1330270089, 1328976672, 1327682474, 1326387494, 1325091734, 1323795195, 1322497877,
+1321199781, 1319900907, 1318601257, 1317300832, 1315999631, 1314697657, 1313394909, 1312091388,
+1310787095, 1309482032, 1308176198, 1306869594, 1305562222, 1304254082, 1302945174, 1301635500,
+1300325060, 1299013855, 1297701886, 1296389154, 1295075659, 1293761402, 1292446384, 1291130606,
+1289814068, 1288496772, 1287178717, 1285859905, 1284540337, 1283220013, 1281898935, 1280577102,
+1279254516, 1277931177, 1276607086, 1275282245, 1273956653, 1272630312, 1271303222, 1269975384,
+1268646800, 1267317469, 1265987392, 1264656571, 1263325005, 1261992697, 1260659646, 1259325853,
+1257991320, 1256656047, 1255320034, 1253983283, 1252645794, 1251307568, 1249968606, 1248628909,
+1247288478, 1245947312, 1244605414, 1243262783, 1241919421, 1240575329, 1239230506, 1237884955,
+1236538675, 1235191668, 1233843935, 1232495475, 1231146291, 1229796382, 1228445750, 1227094395,
+1225742318, 1224389521, 1223036002, 1221681765, 1220326809, 1218971135, 1217614743, 1216257636,
+1214899813, 1213541275, 1212182024, 1210822059, 1209461382, 1208099993, 1206737894, 1205375085,
+1204011567, 1202647340, 1201282407, 1199916766, 1198550419, 1197183368, 1195815612, 1194447153,
+1193077991, 1191708127, 1190337562, 1188966297, 1187594332, 1186221669, 1184848308, 1183474250,
+1182099496, 1180724046, 1179347902, 1177971064, 1176593533, 1175215310, 1173836395, 1172456790,
+1171076495, 1169695512, 1168313840, 1166931481, 1165548435, 1164164704, 1162780288, 1161395188,
+1160009405, 1158622939, 1157235792, 1155847964, 1154459456, 1153070269, 1151680403, 1150289860,
+1148898640, 1147506745, 1146114174, 1144720929, 1143327011, 1141932420, 1140537158, 1139141224,
+1137744621, 1136347348, 1134949406, 1133550797, 1132151521, 1130751579, 1129350972, 1127949701,
+1126547765, 1125145168, 1123741908, 1122337987, 1120933406, 1119528166, 1118122267, 1116715710,
+1115308496, 1113900627, 1112492101, 1111082922, 1109673089, 1108262603, 1106851465, 1105439676,
+1104027237, 1102614148, 1101200410, 1099786025, 1098370993, 1096955314, 1095538991, 1094122023,
+1092704411, 1091286156, 1089867259, 1088447722, 1087027544, 1085606726, 1084185270, 1082763176,
+1081340445, 1079917078, 1078493076, 1077068439, 1075643169, 1074217266, 1072790730, 1071363564,
+1069935768, 1068507342, 1067078288, 1065648605, 1064218296, 1062787361, 1061355801, 1059923616,
+1058490808, 1057057377, 1055623324, 1054188651, 1052753357, 1051317443, 1049880912, 1048443763,
+1047005996, 1045567615, 1044128617, 1042689006, 1041248781, 1039807944, 1038366495, 1036924436,
+1035481766, 1034038487, 1032594600, 1031150105, 1029705004, 1028259297, 1026812985, 1025366069,
+1023918550, 1022470428, 1021021705, 1019572382, 1018122458, 1016671936, 1015220816, 1013769098,
+1012316784, 1010863875, 1009410370, 1007956272, 1006501581, 1005046298, 1003590424, 1002133959,
+1000676905, 999219262, 997761031, 996302214, 994842810, 993382821, 991922248, 990461091,
+988999351, 987537030, 986074127, 984610645, 983146583, 981681943, 980216726, 978750932,
+977284562, 975817617, 974350098, 972882006, 971413342, 969944106, 968474300, 967003923,
+965532978, 964061465, 962589385, 961116739, 959643527, 958169751, 956695411, 955220508,
+953745043, 952269017, 950792431, 949315286, 947837582, 946359321, 944880503, 943401129,
+941921200, 940440717, 938959681, 937478092, 935995952, 934513261, 933030021, 931546231,
+930061894, 928577010, 927091579, 925605603, 924119082, 922632018, 921144411, 919656262,
+918167572, 916678342, 915188572, 913698265, 912207419, 910716038, 909224120, 907731667,
+906238681, 904745161, 903251110, 901756526, 900261413, 898765769, 897269597, 895772898,
+894275671, 892777918, 891279640, 889780838, 888281512, 886781663, 885281293, 883780402,
+882278992, 880777062, 879274614, 877771649, 876268167, 874764170, 873259659, 871754633,
+870249095, 868743045, 867236484, 865729413, 864221832, 862713743, 861205147, 859696043,
+858186435, 856676321, 855165703, 853654582, 852142959, 850630835, 849118210, 847605086,
+846091463, 844577343, 843062726, 841547612, 840032004, 838515901, 836999305, 835482217,
+833964638, 832446567, 830928007, 829408958, 827889422, 826369398, 824848888, 823327893,
+821806413, 820284450, 818762005, 817239078, 815715670, 814191782, 812667415, 811142571,
+809617249, 808091450, 806565177, 805038429, 803511207, 801983513, 800455346, 798926709,
+797397602, 795868026, 794337982, 792807470, 791276492, 789745049, 788213141, 786680769,
+785147934, 783614638, 782080880, 780546663, 779011986, 777476851, 775941259, 774405210,
+772868706, 771331747, 769794334, 768256469, 766718151, 765179382, 763640164, 762100496,
+760560380, 759019816, 757478806, 755937350, 754395449, 752853105, 751310318, 749767089,
+748223418, 746679308, 745134758, 743589770, 742044345, 740498483, 738952186, 737405453,
+735858287, 734310688, 732762657, 731214195, 729665303, 728115982, 726566232, 725016055,
+723465451, 721914422, 720362968, 718811090, 717258790, 715706067, 714152924, 712599360,
+711045377, 709490976, 707936158, 706380923, 704825272, 703269207, 701712728, 700155836,
+698598533, 697040818, 695482694, 693924160, 692365218, 690805869, 689246113, 687685952,
+686125387, 684564417, 683003045, 681441272, 679879097, 678316522, 676753549, 675190177,
+673626408, 672062243, 670497682, 668932727, 667367379, 665801638, 664235505, 662668981,
+661102068, 659534766, 657967075, 656398998, 654830535, 653261686, 651692453, 650122837,
+648552838, 646982457, 645411696, 643840556, 642269036, 640697139, 639124865, 637552215,
+635979190, 634405791, 632832018, 631257873, 629683357, 628108471, 626533215, 624957590,
+623381598, 621805239, 620228514, 618651424, 617073971, 615496154, 613917975, 612339436,
+610760536, 609181276, 607601658, 606021683, 604441352, 602860664, 601279623, 599698227,
+598116479, 596534378, 594951927, 593369126, 591785976, 590202477, 588618632, 587034440,
+585449903, 583865021, 582279796, 580694229, 579108320, 577522070, 575935480, 574348552,
+572761285, 571173682, 569585743, 567997469, 566408860, 564819919, 563230645, 561641039,
+560051104, 558460839, 556870245, 555279324, 553688076, 552096502, 550504604, 548912382,
+547319836, 545726969, 544133781, 542540273, 540946445, 539352300, 537757837, 536163058,
+534567963, 532972554, 531376831, 529780796, 528184449, 526587791, 524990824, 523393547,
+521795963, 520198072, 518599875, 517001373, 515402566, 513803457, 512204045, 510604332,
+509004318, 507404005, 505803394, 504202485, 502601279, 500999778, 499397982, 497795892,
+496193509, 494590835, 492987869, 491384614, 489781069, 488177236, 486573117, 484968710,
+483364019, 481759043, 480153784, 478548243, 476942419, 475336316, 473729932, 472123270,
+470516330, 468909114, 467301622, 465693854, 464085813, 462477499, 460868912, 459260055,
+457650927, 456041530, 454431865, 452821933, 451211734, 449601270, 447990541, 446379549,
+444768294, 443156777, 441545000, 439932963, 438320667, 436708113, 435095303, 433482236,
+431868915, 430255339, 428641511, 427027430, 425413098, 423798515, 422183684, 420568604,
+418953276, 417337703, 415721883, 414105819, 412489512, 410872962, 409256170, 407639137,
+406021865, 404404353, 402786604, 401168618, 399550396, 397931939, 396313247, 394694323,
+393075166, 391455778, 389836160, 388216313, 386596237, 384975934, 383355404, 381734649,
+380113669, 378492466, 376871039, 375249392, 373627523, 372005435, 370383128, 368760603,
+367137861, 365514903, 363891730, 362268343, 360644742, 359020930, 357396906, 355772673,
+354148230, 352523578, 350898719, 349273654, 347648383, 346022908, 344397230, 342771348,
+341145265, 339518981, 337892498, 336265816, 334638936, 333011859, 331384586, 329757119,
+328129457, 326501602, 324873555, 323245317, 321616889, 319988272, 318359466, 316730474,
+315101295, 313471930, 311842381, 310212649, 308582734, 306952638, 305322361, 303691904,
+302061269, 300430456, 298799466, 297168301, 295536961, 293905447, 292273760, 290641901,
+289009871, 287377671, 285745302, 284112765, 282480061, 280847190, 279214155, 277580955,
+275947592, 274314066, 272680379, 271046532, 269412525, 267778360, 266144038, 264509558,
+262874923, 261240134, 259605191, 257970095, 256334847, 254699448, 253063900, 251428203,
+249792358, 248156366, 246520228, 244883945, 243247518, 241610947, 239974235, 238337382,
+236700388, 235063255, 233425984, 231788575, 230151030, 228513350, 226875535, 225237587,
+223599506, 221961294, 220322951, 218684479, 217045878, 215407149, 213768293, 212129312,
+210490206, 208850976, 207211624, 205572149, 203932553, 202292838, 200653003, 199013051,
+197372981, 195732795, 194092495, 192452080, 190811551, 189170911, 187530159, 185889297,
+184248325, 182607245, 180966058, 179324764, 177683365, 176041861, 174400254, 172758544,
+171116733, 169474820, 167832808, 166190698, 164548489, 162906184, 161263783, 159621287,
+157978697, 156336015, 154693240, 153050374, 151407418, 149764374, 148121241, 146478021,
+144834714, 143191323, 141547847, 139904288, 138260647, 136616925, 134973122, 133329239,
+131685278, 130041240, 128397125, 126752935, 125108670, 123464332, 121819921, 120175438,
+118530885, 116886262, 115241570, 113596810, 111951983, 110307091, 108662134, 107017112,
+105372028, 103726882, 102081675, 100436408,  98791081,  97145697,  95500255,  93854758,
+ 92209205,  90563597,  88917937,  87272224,  85626460,  83980645,  82334782,  80688869,
+ 79042909,  77396903,  75750851,  74104755,  72458615,  70812432,  69166208,  67519943,
+ 65873638,  64227295,  62580914,  60934496,  59288042,  57641553,  55995030,  54348475,
+ 52701887,  51055268,  49408620,  47761942,  46115236,  44468503,  42821744,  41174960,
+ 39528151,  37881320,  36234466,  34587590,  32940695,  31293780,  29646846,  27999895,
+ 26352928,  24705945,  23058947,  21411936,  19764913,  18117878,  16470832,  14823776,
+ 13176712,  11529640,   9882561,   8235476,   6588387,   4941294,   3294197,   1647099
 };
 
-uint16_t ff_fft_offsets_lut[0x2aab];
+uint16_t ff_fft_offsets_lut[21845];
 
 void ff_fft_lut_init(uint16_t *table, int off, int size, int *index)
 {
diff --git a/libavcodec/fft_table.h b/libavcodec/fft_table.h
index e5e54b6..ed0a658 100644
--- a/libavcodec/fft_table.h
+++ b/libavcodec/fft_table.h
@@ -56,7 +56,7 @@
 
 #include "libavcodec/fft.h"
 
-#define MAX_LOG2_NFFT 16 //!< Specifies maximum allowed fft size
+#define MAX_LOG2_NFFT 17 //!< Specifies maximum allowed fft size
 #define MAX_FFT_SIZE (1 << MAX_LOG2_NFFT)
 
 extern const int32_t ff_w_tab_sr[];
diff --git a/libavcodec/fft_template.c b/libavcodec/fft_template.c
index 23ea453..480557f 100644
--- a/libavcodec/fft_template.c
+++ b/libavcodec/fft_template.c
@@ -51,6 +51,7 @@ COSTABLE(8192);
 COSTABLE(16384);
 COSTABLE(32768);
 COSTABLE(65536);
+COSTABLE(131072);
 #endif
 COSTABLE_CONST FFTSample * const FFT_NAME(ff_cos_tabs)[] = {
     NULL, NULL, NULL, NULL,
@@ -67,6 +68,7 @@ COSTABLE_CONST FFTSample * const FFT_NAME(ff_cos_tabs)[] = {
     FFT_NAME(ff_cos_16384),
     FFT_NAME(ff_cos_32768),
     FFT_NAME(ff_cos_65536),
+    FFT_NAME(ff_cos_131072),
 };
 
 #endif /* FFT_FIXED_32 */
@@ -141,14 +143,23 @@ av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse)
 {
     int i, j, n;
 
-    if (nbits < 2 || nbits > 16)
+    s->revtab = NULL;
+    s->revtab32 = NULL;
+
+    if (nbits < 2 || nbits > 17)
         goto fail;
     s->nbits = nbits;
     n = 1 << nbits;
 
-    s->revtab = av_malloc(n * sizeof(uint16_t));
-    if (!s->revtab)
-        goto fail;
+    if (nbits <= 16) {
+        s->revtab = av_malloc(n * sizeof(uint16_t));
+        if (!s->revtab)
+            goto fail;
+    } else {
+        s->revtab32 = av_malloc(n * sizeof(uint32_t));
+        if (!s->revtab32)
+            goto fail;
+    }
     s->tmp_buf = av_malloc(n * sizeof(FFTComplex));
     if (!s->tmp_buf)
         goto fail;
@@ -166,7 +177,7 @@ av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse)
 #if FFT_FIXED_32
     {
         int n=0;
-        ff_fft_lut_init(ff_fft_offsets_lut, 0, 1 << 16, &n);
+        ff_fft_lut_init(ff_fft_offsets_lut, 0, 1 << 17, &n);
     }
 #else /* FFT_FIXED_32 */
 #if FFT_FLOAT
@@ -190,16 +201,22 @@ av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse)
         fft_perm_avx(s);
     } else {
         for(i=0; i<n; i++) {
+            int k;
             j = i;
             if (s->fft_permutation == FF_FFT_PERM_SWAP_LSBS)
                 j = (j&~3) | ((j>>1)&1) | ((j<<1)&2);
-            s->revtab[-split_radix_permutation(i, n, s->inverse) & (n-1)] = j;
+            k = -split_radix_permutation(i, n, s->inverse) & (n-1);
+            if (s->revtab)
+                s->revtab[k] = j;
+            if (s->revtab32)
+                s->revtab32[k] = j;
         }
     }
 
     return 0;
  fail:
     av_freep(&s->revtab);
+    av_freep(&s->revtab32);
     av_freep(&s->tmp_buf);
     return -1;
 }
@@ -208,15 +225,21 @@ static void fft_permute_c(FFTContext *s, FFTComplex *z)
 {
     int j, np;
     const uint16_t *revtab = s->revtab;
+    const uint32_t *revtab32 = s->revtab32;
     np = 1 << s->nbits;
     /* TODO: handle split-radix permute in a more optimal way, probably in-place */
-    for(j=0;j<np;j++) s->tmp_buf[revtab[j]] = z[j];
+    if (revtab) {
+        for(j=0;j<np;j++) s->tmp_buf[revtab[j]] = z[j];
+    } else
+        for(j=0;j<np;j++) s->tmp_buf[revtab32[j]] = z[j];
+
     memcpy(z, s->tmp_buf, np * sizeof(FFTComplex));
 }
 
 av_cold void ff_fft_end(FFTContext *s)
 {
     av_freep(&s->revtab);
+    av_freep(&s->revtab32);
     av_freep(&s->tmp_buf);
 }
 
@@ -515,10 +538,11 @@ DECL_FFT(8192,4096,2048)
 DECL_FFT(16384,8192,4096)
 DECL_FFT(32768,16384,8192)
 DECL_FFT(65536,32768,16384)
+DECL_FFT(131072,65536,32768)
 
 static void (* const fft_dispatch[])(FFTComplex*) = {
     fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, fft1024,
-    fft2048, fft4096, fft8192, fft16384, fft32768, fft65536,
+    fft2048, fft4096, fft8192, fft16384, fft32768, fft65536, fft131072
 };
 
 static void fft_calc_c(FFTContext *s, FFTComplex *z)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 537409e..60eb523 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -32,6 +32,7 @@
 #include "libavutil/imgutils.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/timer.h"
+
 #include "avcodec.h"
 #include "internal.h"
 #include "rangecoder.h"
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index d2bf3a8..6a932b2 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -768,17 +768,18 @@ static int read_header(FFV1Context *f)
                    "chroma subsampling not supported in this colorspace\n");
             return AVERROR(ENOSYS);
         }
-        if (     f->avctx->bits_per_raw_sample ==  9)
+        if (     f->avctx->bits_per_raw_sample <=  8 && !f->transparency)
+            f->avctx->pix_fmt = AV_PIX_FMT_0RGB32;
+        else if (f->avctx->bits_per_raw_sample <=  8 && f->transparency)
+            f->avctx->pix_fmt = AV_PIX_FMT_RGB32;
+        else if (f->avctx->bits_per_raw_sample ==  9 && !f->transparency)
             f->avctx->pix_fmt = AV_PIX_FMT_GBRP9;
-        else if (f->avctx->bits_per_raw_sample == 10)
+        else if (f->avctx->bits_per_raw_sample == 10 && !f->transparency)
             f->avctx->pix_fmt = AV_PIX_FMT_GBRP10;
-        else if (f->avctx->bits_per_raw_sample == 12)
+        else if (f->avctx->bits_per_raw_sample == 12 && !f->transparency)
             f->avctx->pix_fmt = AV_PIX_FMT_GBRP12;
-        else if (f->avctx->bits_per_raw_sample == 14)
+        else if (f->avctx->bits_per_raw_sample == 14 && !f->transparency)
             f->avctx->pix_fmt = AV_PIX_FMT_GBRP14;
-        else
-        if (f->transparency) f->avctx->pix_fmt = AV_PIX_FMT_RGB32;
-        else                 f->avctx->pix_fmt = AV_PIX_FMT_0RGB32;
     } else {
         av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n");
         return AVERROR(ENOSYS);
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 9ee9921..948a230 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -32,6 +32,7 @@
 #include "libavutil/imgutils.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/timer.h"
+
 #include "avcodec.h"
 #include "internal.h"
 #include "put_bits.h"
@@ -1289,7 +1290,11 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     av_frame_unref(p);
     if ((ret = av_frame_ref(p, pict)) < 0)
         return ret;
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
     avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     if (avctx->gop_size == 0 || f->picture_number % avctx->gop_size == 0) {
         put_rac(c, &keystate, 1);
diff --git a/libavcodec/fic.c b/libavcodec/fic.c
index 7d698f0..d3952a4 100644
--- a/libavcodec/fic.c
+++ b/libavcodec/fic.c
@@ -309,7 +309,7 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data,
         return AVERROR_INVALIDDATA;
     }
 
-    if (!tsize)
+    if (!tsize || !AV_RL16(src + 37) || !AV_RL16(src + 39))
         skip_cursor = 1;
 
     if (!skip_cursor && tsize < 32) {
@@ -322,8 +322,8 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data,
     cur_x = AV_RL16(src + 33);
     cur_y = AV_RL16(src + 35);
     if (!skip_cursor && (cur_x > avctx->width || cur_y > avctx->height)) {
-        av_log(avctx, AV_LOG_WARNING,
-               "Invalid cursor position: (%d,%d). Skipping cusor.\n",
+        av_log(avctx, AV_LOG_DEBUG,
+               "Invalid cursor position: (%d,%d). Skipping cursor.\n",
                cur_x, cur_y);
         skip_cursor = 1;
     }
diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c
index 3723716..f5cc35a 100644
--- a/libavcodec/flac_parser.c
+++ b/libavcodec/flac_parser.c
@@ -40,7 +40,7 @@
 #include "flac.h"
 
 /** maximum number of adjacent headers that compare CRCs against each other   */
-#define FLAC_MAX_SEQUENTIAL_HEADERS 3
+#define FLAC_MAX_SEQUENTIAL_HEADERS 4
 /** minimum number of headers buffered and checked before returning frames    */
 #define FLAC_MIN_HEADERS 10
 /** estimate for average size of a FLAC frame                                 */
@@ -617,8 +617,8 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
 
         if (!av_fifo_space(fpc->fifo_buf) &&
             av_fifo_size(fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE >
-            fpc->nb_headers_buffered * 10) {
-            /* There is less than one valid flac header buffered for 10 headers
+            fpc->nb_headers_buffered * 20) {
+            /* There is less than one valid flac header buffered for 20 headers
              * buffered. Therefore the fifo is most likely filled with invalid
              * data and the input is not a flac file. */
             goto handle_error;
diff --git a/libavcodec/flicvideo.c b/libavcodec/flicvideo.c
index 3e0573a..c9c6c24 100644
--- a/libavcodec/flicvideo.c
+++ b/libavcodec/flicvideo.c
@@ -1,6 +1,6 @@
 /*
  * FLI/FLC Animation Video Decoder
- * Copyright (c) 2003, 2004 The FFmpeg Project
+ * Copyright (C) 2003, 2004 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -133,7 +133,7 @@ static av_cold int flic_decode_init(AVCodecContext *avctx)
         case 8  : avctx->pix_fmt = AV_PIX_FMT_PAL8; break;
         case 15 : avctx->pix_fmt = AV_PIX_FMT_RGB555; break;
         case 16 : avctx->pix_fmt = AV_PIX_FMT_RGB565; break;
-        case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; /* Supposedly BGR, but havent any files to test with */
+        case 24 : avctx->pix_fmt = AV_PIX_FMT_BGR24; /* Supposedly BGR, but no files to test with */
                   avpriv_request_sample(avctx, "24Bpp FLC/FLX");
                   return AVERROR_PATCHWELCOME;
         default :
@@ -423,7 +423,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
 
         case FLI_COPY:
             /* copy the chunk (uncompressed frame) */
-            if (chunk_size - 6 != s->avctx->width * s->avctx->height) {
+            if (chunk_size - 6 != FFALIGN(s->avctx->width, 4) * s->avctx->height) {
                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
                        "has incorrect size, skipping chunk\n", chunk_size - 6);
                 bytestream2_skip(&g2, chunk_size - 6);
@@ -432,6 +432,8 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx,
                      y_ptr += s->frame->linesize[0]) {
                     bytestream2_get_buffer(&g2, &pixels[y_ptr],
                                            s->avctx->width);
+                    if (s->avctx->width & 3)
+                        bytestream2_skip(&g2, 4 - (s->avctx->width & 3));
                 }
             }
             break;
@@ -711,7 +713,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
         case FLI_COPY:
         case FLI_DTA_COPY:
             /* copy the chunk (uncompressed frame) */
-            if (chunk_size - 6 > (unsigned int)(s->avctx->width * s->avctx->height)*2) {
+            if (chunk_size - 6 > (unsigned int)(FFALIGN(s->avctx->width, 2) * s->avctx->height)*2) {
                 av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \
                        "bigger than image, skipping chunk\n", chunk_size - 6);
                 bytestream2_skip(&g2, chunk_size - 6);
@@ -727,6 +729,8 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx,
                       pixel_ptr += 2;
                       pixel_countdown--;
                     }
+                    if (s->avctx->width & 1)
+                        bytestream2_skip(&g2, 2);
                 }
             }
             break;
@@ -789,7 +793,7 @@ static int flic_decode_frame(AVCodecContext *avctx,
 
     /* Should not get  here, ever as the pix_fmt is processed */
     /* in flic_decode_init and the above if should deal with */
-    /* the finite set of possibilites allowable by here. */
+    /* the finite set of possibilities allowable by here. */
     /* But in case we do, just error out. */
     av_log(avctx, AV_LOG_ERROR, "Unknown FLC format, my science cannot explain how this happened.\n");
     return AVERROR_BUG;
diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c
index a2cd399..15f794e 100644
--- a/libavcodec/flvenc.c
+++ b/libavcodec/flvenc.c
@@ -31,7 +31,7 @@ void ff_flv_encode_picture_header(MpegEncContext *s, int picture_number)
     avpriv_align_put_bits(&s->pb);
 
     put_bits(&s->pb, 17, 1);
-    /* 0: h263 escape codes 1: 11-bit escape codes */
+    /* 0: H.263 escape codes 1: 11-bit escape codes */
     put_bits(&s->pb, 5, (s->h263_flv - 1));
     put_bits(&s->pb, 8,
              (((int64_t) s->picture_number * 30 * s->avctx->time_base.num) /   // FIXME use timestamp
diff --git a/libavcodec/frame_thread_encoder.c b/libavcodec/frame_thread_encoder.c
index 04c9a0e..27ae356 100644
--- a/libavcodec/frame_thread_encoder.c
+++ b/libavcodec/frame_thread_encoder.c
@@ -89,7 +89,9 @@ static void * attribute_align_arg worker(void *v){
         pthread_mutex_unlock(&c->buffer_mutex);
         av_frame_free(&frame);
         if(got_packet) {
-            av_dup_packet(pkt);
+            int ret2 = av_dup_packet(pkt);
+            if (ret >= 0 && ret2 < 0)
+                ret = ret2;
         } else {
             pkt->data = NULL;
             pkt->size = 0;
diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c
index 51e8bbc..b0af3ec 100644
--- a/libavcodec/g2meet.c
+++ b/libavcodec/g2meet.c
@@ -900,7 +900,7 @@ static int epic_jb_decode_tile(G2MContext *c, int tile_x, int tile_y,
     }
 
     if (src_size < els_dsize) {
-        av_log(avctx, AV_LOG_ERROR, "ePIC: data too short, needed %zu, got %zu\n",
+        av_log(avctx, AV_LOG_ERROR, "ePIC: data too short, needed %"SIZE_SPECIFIER", got %"SIZE_SPECIFIER"\n",
                els_dsize, src_size);
         return AVERROR_INVALIDDATA;
     }
diff --git a/libavcodec/g723_1dec.c b/libavcodec/g723_1dec.c
index 3e8c489..6f283b4 100644
--- a/libavcodec/g723_1dec.c
+++ b/libavcodec/g723_1dec.c
@@ -466,7 +466,7 @@ static int comp_interp_index(G723_1_Context *p, int pitch_lag,
 }
 
 /**
- * Peform residual interpolation based on frame classification.
+ * Perform residual interpolation based on frame classification.
  *
  * @param buf   decoded excitation vector
  * @param out   output vector
@@ -914,7 +914,7 @@ static int g723_1_decode_frame(AVCodecContext *avctx, void *data,
             p->interp_index = comp_interp_index(p, p->pitch_lag[1],
                                                 &p->sid_gain, &p->cur_gain);
 
-            /* Peform pitch postfiltering */
+            /* Perform pitch postfiltering */
             if (p->postfilter) {
                 i = PITCH_MAX;
                 for (j = 0; j < SUBFRAMES; i += SUBFRAME_LEN, j++)
diff --git a/libavcodec/g726.c b/libavcodec/g726.c
index c3d018f..c7d138e 100644
--- a/libavcodec/g726.c
+++ b/libavcodec/g726.c
@@ -31,15 +31,15 @@
 #include "put_bits.h"
 
 /**
- * G.726 11bit float.
- * G.726 Standard uses rather odd 11bit floating point arithmetic for
+ * G.726 11-bit float.
+ * G.726 Standard uses rather odd 11-bit floating point arithmetic for
  * numerous occasions. It's a mystery to me why they did it this way
- * instead of simply using 32bit integer arithmetic.
+ * instead of simply using 32-bit integer arithmetic.
  */
 typedef struct Float11 {
-    uint8_t sign;   /**< 1bit sign */
-    uint8_t exp;    /**< 4bit exponent */
-    uint8_t mant;   /**< 6bit mantissa */
+    uint8_t sign;   /**< 1 bit sign */
+    uint8_t exp;    /**< 4 bits exponent */
+    uint8_t mant;   /**< 6 bits mantissa */
 } Float11;
 
 static inline Float11* i2f(int i, Float11* f)
@@ -98,7 +98,7 @@ typedef struct G726Context {
     int little_endian;  /**< little-endian bitstream as used in aiff and Sun AU */
 } G726Context;
 
-static const int quant_tbl16[] =                  /**< 16kbit/s 2bits per sample */
+static const int quant_tbl16[] =                  /**< 16kbit/s 2 bits per sample */
            { 260, INT_MAX };
 static const int16_t iquant_tbl16[] =
            { 116, 365, 365, 116 };
@@ -107,7 +107,7 @@ static const int16_t W_tbl16[] =
 static const uint8_t F_tbl16[] =
            { 0, 7, 7, 0 };
 
-static const int quant_tbl24[] =                  /**< 24kbit/s 3bits per sample */
+static const int quant_tbl24[] =                  /**< 24kbit/s 3 bits per sample */
            {  7, 217, 330, INT_MAX };
 static const int16_t iquant_tbl24[] =
            { INT16_MIN, 135, 273, 373, 373, 273, 135, INT16_MIN };
@@ -116,7 +116,7 @@ static const int16_t W_tbl24[] =
 static const uint8_t F_tbl24[] =
            { 0, 1, 2, 7, 7, 2, 1, 0 };
 
-static const int quant_tbl32[] =                  /**< 32kbit/s 4bits per sample */
+static const int quant_tbl32[] =                  /**< 32kbit/s 4 bits per sample */
            { -125,  79, 177, 245, 299, 348, 399, INT_MAX };
 static const int16_t iquant_tbl32[] =
          { INT16_MIN,   4, 135, 213, 273, 323, 373, 425,
@@ -127,7 +127,7 @@ static const int16_t W_tbl32[] =
 static const uint8_t F_tbl32[] =
            { 0, 0, 0, 1, 1, 1, 3, 7, 7, 3, 1, 1, 1, 0, 0, 0 };
 
-static const int quant_tbl40[] =                  /**< 40kbit/s 5bits per sample */
+static const int quant_tbl40[] =                  /**< 40kbit/s 5 bits per sample */
            { -122, -16,  67, 138, 197, 249, 297, 338,
               377, 412, 444, 474, 501, 527, 552, INT_MAX };
 static const int16_t iquant_tbl40[] =
@@ -152,7 +152,7 @@ static const G726Tables G726Tables_pool[] =
 
 
 /**
- * Para 4.2.2 page 18: Adaptive quantizer.
+ * Paragraph 4.2.2 page 18: Adaptive quantizer.
  */
 static inline uint8_t quant(G726Context* c, int d)
 {
@@ -178,14 +178,14 @@ static inline uint8_t quant(G726Context* c, int d)
 }
 
 /**
- * Para 4.2.3 page 22: Inverse adaptive quantizer.
+ * Paragraph 4.2.3 page 22: Inverse adaptive quantizer.
  */
 static inline int16_t inverse_quant(G726Context* c, int i)
 {
     int dql, dex, dqt;
 
     dql = c->tbls.iquant[i] + (c->y >> 2);
-    dex = (dql>>7) & 0xf;        /* 4bit exponent */
+    dex = (dql>>7) & 0xf;        /* 4-bit exponent */
     dqt = (1<<7) + (dql & 0x7f); /* log2 -> linear */
     return (dql < 0) ? 0 : ((dqt<<dex) >> 7);
 }
diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h
index 4cf61d6..0f183e0 100644
--- a/libavcodec/get_bits.h
+++ b/libavcodec/get_bits.h
@@ -33,6 +33,7 @@
 #include "libavutil/log.h"
 #include "libavutil/avassert.h"
 #include "mathops.h"
+#include "vlc.h"
 
 /*
  * Safe bitstream reading:
@@ -58,20 +59,6 @@ typedef struct GetBitContext {
     int size_in_bits_plus8;
 } GetBitContext;
 
-#define VLC_TYPE int16_t
-
-typedef struct VLC {
-    int bits;
-    VLC_TYPE (*table)[2]; ///< code, bits
-    int table_size, table_allocated;
-} VLC;
-
-typedef struct RL_VLC_ELEM {
-    int16_t level;
-    int8_t len;
-    uint8_t run;
-} RL_VLC_ELEM;
-
 /* Bitstream reader API docs:
  * name
  *   arbitrary name which is used as prefix for the internal variables
@@ -91,7 +78,7 @@ typedef struct RL_VLC_ELEM {
  *
  * GET_CACHE(name, gb)
  *   Will output the contents of the internal cache,
- *   next bit is MSB of 32 or 64 bit (FIXME 64bit).
+ *   next bit is MSB of 32 or 64 bits (FIXME 64 bits).
  *
  * SHOW_UBITS(name, gb, num)
  *   Will return the next num bits.
@@ -224,7 +211,7 @@ static inline void skip_bits_long(GetBitContext *s, int n)
 }
 
 /**
- * read mpeg1 dc style vlc (sign bit + mantissa with no MSB).
+ * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB).
  * if MSB not set it is negative
  * @param n length in bits
  */
@@ -398,11 +385,12 @@ static inline unsigned int show_bits_long(GetBitContext *s, int n)
     }
 }
 
-static inline int check_marker(GetBitContext *s, const char *msg)
+static inline int check_marker(void *logctx, GetBitContext *s, const char *msg)
 {
     int bit = get_bits1(s);
     if (!bit)
-        av_log(NULL, AV_LOG_INFO, "Marker bit missing at %d of %d %s\n", get_bits_count(s) - 1, s->size_in_bits, msg);
+        av_log(logctx, AV_LOG_INFO, "Marker bit missing at %d of %d %s\n",
+               get_bits_count(s) - 1, s->size_in_bits, msg);
 
     return bit;
 }
@@ -462,33 +450,6 @@ static inline const uint8_t *align_get_bits(GetBitContext *s)
     return s->buffer + (s->index >> 3);
 }
 
-#define init_vlc(vlc, nb_bits, nb_codes,                \
-                 bits, bits_wrap, bits_size,            \
-                 codes, codes_wrap, codes_size,         \
-                 flags)                                 \
-    ff_init_vlc_sparse(vlc, nb_bits, nb_codes,          \
-                       bits, bits_wrap, bits_size,      \
-                       codes, codes_wrap, codes_size,   \
-                       NULL, 0, 0, flags)
-
-int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
-                       const void *bits, int bits_wrap, int bits_size,
-                       const void *codes, int codes_wrap, int codes_size,
-                       const void *symbols, int symbols_wrap, int symbols_size,
-                       int flags);
-void ff_free_vlc(VLC *vlc);
-
-#define INIT_VLC_LE             2
-#define INIT_VLC_USE_NEW_STATIC 4
-
-#define INIT_VLC_STATIC(vlc, bits, a, b, c, d, e, f, g, static_size)       \
-    do {                                                                   \
-        static VLC_TYPE table[static_size][2];                             \
-        (vlc)->table           = table;                                    \
-        (vlc)->table_allocated = static_size;                              \
-        init_vlc(vlc, bits, a, b, c, d, e, f, g, INIT_VLC_USE_NEW_STATIC); \
-    } while (0)
-
 /**
  * If the vlc code is invalid and max_depth=1, then no bits will be removed.
  * If the vlc code is invalid and max_depth>1, then the number of bits removed
@@ -526,7 +487,7 @@ void ff_free_vlc(VLC *vlc);
         SKIP_BITS(name, gb, n);                                 \
     } while (0)
 
-#define GET_RL_VLC_INTERNAL(level, run, name, gb, table, bits,  \
+#define GET_RL_VLC(level, run, name, gb, table, bits,  \
                    max_depth, need_update)                      \
     do {                                                        \
         int n, nb_bits;                                         \
@@ -623,89 +584,4 @@ static inline int skip_1stop_8data_bits(GetBitContext *gb)
     return 0;
 }
 
-//#define TRACE
-
-#ifdef TRACE
-static inline void print_bin(int bits, int n)
-{
-    int i;
-
-    for (i = n - 1; i >= 0; i--)
-        av_log(NULL, AV_LOG_DEBUG, "%d", (bits >> i) & 1);
-    for (i = n; i < 24; i++)
-        av_log(NULL, AV_LOG_DEBUG, " ");
-}
-
-static inline int get_bits_trace(GetBitContext *s, int n, const char *file,
-                                 const char *func, int line)
-{
-    int r = get_bits(s, n);
-
-    print_bin(r, n);
-    av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d bit @%5d in %s %s:%d\n",
-           r, n, r, get_bits_count(s) - n, file, func, line);
-
-    return r;
-}
-
-static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2],
-                                int bits, int max_depth, const char *file,
-                                const char *func, int line)
-{
-    int show  = show_bits(s, 24);
-    int pos   = get_bits_count(s);
-    int r     = get_vlc2(s, table, bits, max_depth);
-    int len   = get_bits_count(s) - pos;
-    int bits2 = show >> (24 - len);
-
-    print_bin(bits2, len);
-
-    av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d vlc @%5d in %s %s:%d\n",
-           bits2, len, r, pos, file, func, line);
-
-    return r;
-}
-
-#define GET_RL_VLC(level, run, name, gb, table, bits,           \
-                   max_depth, need_update)                      \
-    do {                                                        \
-        int show  = SHOW_UBITS(name, gb, 24);                   \
-        int len;                                                \
-        int pos = name ## _index;                               \
-                                                                \
-        GET_RL_VLC_INTERNAL(level, run, name, gb, table, bits,max_depth, need_update); \
-                                                                \
-        len = name ## _index - pos + 1;                         \
-        show = show >> (24 - len);                              \
-                                                                \
-        print_bin(show, len);                                   \
-                                                                \
-        av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d/%-3d rlv @%5d in %s %s:%d\n",\
-               show, len, run-1, level, pos, __FILE__, __PRETTY_FUNCTION__, __LINE__);\
-    } while (0)                                                 \
-
-
-static inline int get_xbits_trace(GetBitContext *s, int n, const char *file,
-                                  const char *func, int line)
-{
-    int show = show_bits(s, n);
-    int r    = get_xbits(s, n);
-
-    print_bin(show, n);
-    av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d xbt @%5d in %s %s:%d\n",
-           show, n, r, get_bits_count(s) - n, file, func, line);
-
-    return r;
-}
-
-#define get_bits(s, n)  get_bits_trace(s , n, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define get_bits1(s)    get_bits_trace(s,  1, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define get_xbits(s, n) get_xbits_trace(s, n, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-
-#define get_vlc(s, vlc)             get_vlc_trace(s, (vlc)->table, (vlc)->bits,   3, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#define get_vlc2(s, tab, bits, max) get_vlc_trace(s,          tab,        bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__)
-#else //TRACE
-#define GET_RL_VLC GET_RL_VLC_INTERNAL
-#endif
-
 #endif /* AVCODEC_GET_BITS_H */
diff --git a/libavcodec/golomb-test.c b/libavcodec/golomb-test.c
deleted file mode 100644
index 2dfe917..0000000
--- a/libavcodec/golomb-test.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2003 Michael Niedermayer <michaelni at gmx.at>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include "libavutil/mem.h"
-
-#include "get_bits.h"
-#include "golomb.h"
-#include "put_bits.h"
-
-#define COUNT 8191
-#define SIZE (COUNT * 4)
-
-int main(void)
-{
-    int i, ret = 0;
-    uint8_t *temp;
-    PutBitContext pb;
-    GetBitContext gb;
-
-    temp = av_malloc(SIZE);
-    if (!temp)
-        return 2;
-
-    init_put_bits(&pb, temp, SIZE);
-    for (i = 0; i < COUNT; i++)
-        set_ue_golomb(&pb, i);
-    flush_put_bits(&pb);
-
-    init_get_bits(&gb, temp, 8 * SIZE);
-    for (i = 0; i < COUNT; i++) {
-        int j, s = show_bits(&gb, 25);
-
-        j = get_ue_golomb(&gb);
-        if (j != i) {
-            fprintf(stderr, "get_ue_golomb: expected %d, got %d. bits: %7x\n",
-                    i, j, s);
-            ret = 1;
-        }
-    }
-
-#define EXTEND(i) ((i) << 3 | (i) & 7)
-    init_put_bits(&pb, temp, SIZE);
-    for (i = 0; i < COUNT; i++)
-        set_ue_golomb(&pb, EXTEND(i));
-    flush_put_bits(&pb);
-
-    init_get_bits(&gb, temp, 8 * SIZE);
-    for (i = 0; i < COUNT; i++) {
-        int j, s = show_bits_long(&gb, 32);
-
-        j = get_ue_golomb_long(&gb);
-        if (j != EXTEND(i)) {
-            fprintf(stderr, "get_ue_golomb_long: expected %d, got %d. "
-                    "bits: %8x\n", EXTEND(i), j, s);
-            ret = 1;
-        }
-    }
-
-    init_put_bits(&pb, temp, SIZE);
-    for (i = 0; i < COUNT; i++)
-        set_se_golomb(&pb, i - COUNT / 2);
-    flush_put_bits(&pb);
-
-    init_get_bits(&gb, temp, 8 * SIZE);
-    for (i = 0; i < COUNT; i++) {
-        int j, s = show_bits(&gb, 25);
-
-        j = get_se_golomb(&gb);
-        if (j != i - COUNT / 2) {
-            fprintf(stderr, "get_se_golomb: expected %d, got %d. bits: %7x\n",
-                    i - COUNT / 2, j, s);
-            ret = 1;
-        }
-    }
-
-    av_free(temp);
-
-    return ret;
-}
diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h
index d4df0b3..917ea54 100644
--- a/libavcodec/golomb.h
+++ b/libavcodec/golomb.h
@@ -112,7 +112,7 @@ static inline int get_ue_golomb_31(GetBitContext *gb)
     return ff_ue_golomb_vlc_code[buf];
 }
 
-static inline unsigned svq3_get_ue_golomb(GetBitContext *gb)
+static inline unsigned get_interleaved_ue_golomb(GetBitContext *gb)
 {
     uint32_t buf;
 
@@ -219,7 +219,7 @@ static inline int get_se_golomb_long(GetBitContext *gb)
     return ((buf >> 1) ^ sign) + 1;
 }
 
-static inline int svq3_get_se_golomb(GetBitContext *gb)
+static inline int get_interleaved_se_golomb(GetBitContext *gb)
 {
     unsigned int buf;
 
@@ -254,7 +254,7 @@ static inline int svq3_get_se_golomb(GetBitContext *gb)
 
 static inline int dirac_get_se_golomb(GetBitContext *gb)
 {
-    uint32_t ret = svq3_get_ue_golomb(gb);
+    uint32_t ret = get_interleaved_ue_golomb(gb);
 
     if (ret) {
         int sign = -get_bits1(gb);
@@ -409,8 +409,6 @@ static inline int get_ue(GetBitContext *s, const char *file, const char *func,
     int len  = get_bits_count(s) - pos;
     int bits = show >> (24 - len);
 
-    print_bin(bits, len);
-
     av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d ue  @%5d in %s %s:%d\n",
            bits, len, i, pos, file, func, line);
 
@@ -426,8 +424,6 @@ static inline int get_se(GetBitContext *s, const char *file, const char *func,
     int len  = get_bits_count(s) - pos;
     int bits = show >> (24 - len);
 
-    print_bin(bits, len);
-
     av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d se  @%5d in %s %s:%d\n",
            bits, len, i, pos, file, func, line);
 
@@ -443,8 +439,6 @@ static inline int get_te(GetBitContext *s, int r, char *file, const char *func,
     int len  = get_bits_count(s) - pos;
     int bits = show >> (24 - len);
 
-    print_bin(bits, len);
-
     av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d te  @%5d in %s %s:%d\n",
            bits, len, i, pos, file, func, line);
 
diff --git a/libavcodec/h261.c b/libavcodec/h261.c
index f33d1a1..47bad4e 100644
--- a/libavcodec/h261.c
+++ b/libavcodec/h261.c
@@ -1,5 +1,5 @@
 /*
- * H261 common code
+ * H.261 common code
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  * Copyright (c) 2004 Maarten Daniels
  *
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * h261codec.
+ * H.261 codec
  */
 
 #include "avcodec.h"
diff --git a/libavcodec/h261.h b/libavcodec/h261.h
index 5586462..399a404 100644
--- a/libavcodec/h261.h
+++ b/libavcodec/h261.h
@@ -1,5 +1,5 @@
 /*
- * H261 decoder
+ * H.261 codec
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  * Copyright (c) 2004 Maarten Daniels
  *
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * h261codec.
+ * H.261 codec.
  */
 
 #ifndef AVCODEC_H261_H
diff --git a/libavcodec/h261_parser.c b/libavcodec/h261_parser.c
index 9c31557..2299c1c 100644
--- a/libavcodec/h261_parser.c
+++ b/libavcodec/h261_parser.c
@@ -1,5 +1,5 @@
 /*
- * H261 parser
+ * H.261 parser
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  * Copyright (c) 2004 Maarten Daniels
  *
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * h261codec.
+ * H.261 parser
  */
 
 #include "parser.h"
diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c
index df60ac5..7f2fff8 100644
--- a/libavcodec/h261dec.c
+++ b/libavcodec/h261dec.c
@@ -1,5 +1,5 @@
 /*
- * H261 decoder
+ * H.261 decoder
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  * Copyright (c) 2004 Maarten Daniels
  *
@@ -601,7 +601,7 @@ retry:
     init_get_bits(&s->gb, buf, buf_size * 8);
 
     if (!s->context_initialized)
-        // we need the IDCT permutaton for reading a custom matrix
+        // we need the IDCT permutation for reading a custom matrix
         ff_mpv_idct_init(s);
 
     ret = h261_decode_picture_header(h);
diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c
index 24ef577..315762c 100644
--- a/libavcodec/h261enc.c
+++ b/libavcodec/h261enc.c
@@ -1,5 +1,5 @@
 /*
- * H261 encoder
+ * H.261 encoder
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  * Copyright (c) 2004 Maarten Daniels
  *
diff --git a/libavcodec/h263.c b/libavcodec/h263.c
index 800387d..4720c56 100644
--- a/libavcodec/h263.c
+++ b/libavcodec/h263.c
@@ -1,7 +1,7 @@
 /*
- * H263/MPEG4 backend for encoder and decoder
+ * H.263/MPEG-4 backend for encoder and decoder
  * Copyright (c) 2000,2001 Fabrice Bellard
- * H263+ support.
+ * H.263+ support.
  * Copyright (c) 2001 Juan J. Sierralta P
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -24,7 +24,7 @@
 
 /**
  * @file
- * h263/mpeg4 codec.
+ * H.263/MPEG-4 codec.
  */
 
 #include <limits.h>
@@ -320,7 +320,7 @@ int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir,
     A = mot_val[ - 1];
     /* special case for first (slice) line */
     if (s->first_slice_line && block<3) {
-        // we can't just change some MVs to simulate that as we need them for the B frames (and ME)
+        // we can't just change some MVs to simulate that as we need them for the B-frames (and ME)
         // and if we ever support non rectangular objects than we need to do a few ifs here anyway :(
         if(block==0){ //most common case
             if(s->mb_x  == s->resync_mb_x){ //rare
diff --git a/libavcodec/h263.h b/libavcodec/h263.h
index 3c3f169..d154d36 100644
--- a/libavcodec/h263.h
+++ b/libavcodec/h263.h
@@ -1,5 +1,5 @@
 /*
- * H263 internal header
+ * H.263 internal header
  *
  * This file is part of FFmpeg.
  *
@@ -87,7 +87,7 @@ int ff_h263_decode_mb(MpegEncContext *s,
                       int16_t block[6][64]);
 
 /**
- * Return the value of the 3bit "source format" syntax element.
+ * Return the value of the 3-bit "source format" syntax element.
  * This represents some standard picture dimensions or indicates that
  * width&height are explicitly stored later.
  */
diff --git a/libavcodec/h263data.c b/libavcodec/h263data.c
index ceda80f..f649d58 100644
--- a/libavcodec/h263data.c
+++ b/libavcodec/h263data.c
@@ -1,5 +1,5 @@
 /*
- * H263+ tables
+ * H.263+ tables
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/h263data.h b/libavcodec/h263data.h
index 0ad2ef4..3da0e37 100644
--- a/libavcodec/h263data.h
+++ b/libavcodec/h263data.h
@@ -1,6 +1,6 @@
 /*
  * copyright (c) 2000,2001 Fabrice Bellard
- * H263+ support
+ * H.263+ support
  * copyright (c) 2001 Juan J. Sierralta P
  * copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 628546b..d0da1d3 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -129,7 +129,7 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
         if (avctx->extradata_size == 56 && avctx->extradata[0] == 1)
             s->ehc_mode = 1;
 
-    /* for h263, we allocate the images after having read the header */
+    /* for H.263, we allocate the images after having read the header */
     if (avctx->codec->id != AV_CODEC_ID_H263 &&
         avctx->codec->id != AV_CODEC_ID_H263P &&
         avctx->codec->id != AV_CODEC_ID_MPEG4) {
@@ -475,7 +475,7 @@ retry:
         return ret;
 
     if (!s->context_initialized)
-        // we need the idct permutaton for reading a custom matrix
+        // we need the idct permutation for reading a custom matrix
         ff_mpv_idct_init(s);
 
     /* let's go :-) */
@@ -536,9 +536,9 @@ retry:
             goto retry;
     }
 
-    /* After H263 & mpeg4 header decode we have the height, width,
+    /* After H.263 & MPEG-4 header decode we have the height, width,
      * and other parameters. So then we could init the picture.
-     * FIXME: By the way H263 decoder is evolving it should have
+     * FIXME: By the way H.263 decoder is evolving it should have
      * an H263EncContext */
     if (s->width  != avctx->coded_width  ||
         s->height != avctx->coded_height ||
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 88768af..a61379c 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 codec.
+ * H.264 / AVC / MPEG-4 part10 codec.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -34,11 +34,13 @@
 #include "libavutil/stereo3d.h"
 #include "libavutil/timer.h"
 #include "internal.h"
+#include "bytestream.h"
 #include "cabac.h"
 #include "cabac_functions.h"
 #include "error_resilience.h"
 #include "avcodec.h"
 #include "h264.h"
+#include "h2645_parse.h"
 #include "h264data.h"
 #include "h264chroma.h"
 #include "h264_mvpred.h"
@@ -48,7 +50,6 @@
 #include "mpegutils.h"
 #include "profiles.h"
 #include "rectangle.h"
-#include "svq3.h"
 #include "thread.h"
 #include "vdpau_compat.h"
 
@@ -59,7 +60,7 @@ const uint16_t ff_h264_mb_sizes[4] = { 256, 384, 512, 768 };
 int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx)
 {
     H264Context *h = avctx->priv_data;
-    return h ? h->sps.num_reorder_frames : 0;
+    return h && h->ps.sps ? h->ps.sps->num_reorder_frames : 0;
 }
 
 static void h264_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type,
@@ -133,228 +134,6 @@ void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl,
     }
 }
 
-/**
- * Check if the top & left blocks are available if needed and
- * change the dc mode so it only uses the available blocks.
- */
-int ff_h264_check_intra4x4_pred_mode(const H264Context *h, H264SliceContext *sl)
-{
-    static const int8_t top[12] = {
-        -1, 0, LEFT_DC_PRED, -1, -1, -1, -1, -1, 0
-    };
-    static const int8_t left[12] = {
-        0, -1, TOP_DC_PRED, 0, -1, -1, -1, 0, -1, DC_128_PRED
-    };
-    int i;
-
-    if (!(sl->top_samples_available & 0x8000)) {
-        for (i = 0; i < 4; i++) {
-            int status = top[sl->intra4x4_pred_mode_cache[scan8[0] + i]];
-            if (status < 0) {
-                av_log(h->avctx, AV_LOG_ERROR,
-                       "top block unavailable for requested intra4x4 mode %d at %d %d\n",
-                       status, sl->mb_x, sl->mb_y);
-                return AVERROR_INVALIDDATA;
-            } else if (status) {
-                sl->intra4x4_pred_mode_cache[scan8[0] + i] = status;
-            }
-        }
-    }
-
-    if ((sl->left_samples_available & 0x8888) != 0x8888) {
-        static const int mask[4] = { 0x8000, 0x2000, 0x80, 0x20 };
-        for (i = 0; i < 4; i++)
-            if (!(sl->left_samples_available & mask[i])) {
-                int status = left[sl->intra4x4_pred_mode_cache[scan8[0] + 8 * i]];
-                if (status < 0) {
-                    av_log(h->avctx, AV_LOG_ERROR,
-                           "left block unavailable for requested intra4x4 mode %d at %d %d\n",
-                           status, sl->mb_x, sl->mb_y);
-                    return AVERROR_INVALIDDATA;
-                } else if (status) {
-                    sl->intra4x4_pred_mode_cache[scan8[0] + 8 * i] = status;
-                }
-            }
-    }
-
-    return 0;
-} // FIXME cleanup like ff_h264_check_intra_pred_mode
-
-/**
- * Check if the top & left blocks are available if needed and
- * change the dc mode so it only uses the available blocks.
- */
-int ff_h264_check_intra_pred_mode(const H264Context *h, H264SliceContext *sl,
-                                  int mode, int is_chroma)
-{
-    static const int8_t top[4]  = { LEFT_DC_PRED8x8, 1, -1, -1 };
-    static const int8_t left[5] = { TOP_DC_PRED8x8, -1,  2, -1, DC_128_PRED8x8 };
-
-    if (mode > 3U) {
-        av_log(h->avctx, AV_LOG_ERROR,
-               "out of range intra chroma pred mode at %d %d\n",
-               sl->mb_x, sl->mb_y);
-        return AVERROR_INVALIDDATA;
-    }
-
-    if (!(sl->top_samples_available & 0x8000)) {
-        mode = top[mode];
-        if (mode < 0) {
-            av_log(h->avctx, AV_LOG_ERROR,
-                   "top block unavailable for requested intra mode at %d %d\n",
-                   sl->mb_x, sl->mb_y);
-            return AVERROR_INVALIDDATA;
-        }
-    }
-
-    if ((sl->left_samples_available & 0x8080) != 0x8080) {
-        mode = left[mode];
-        if (mode < 0) {
-            av_log(h->avctx, AV_LOG_ERROR,
-                   "left block unavailable for requested intra mode at %d %d\n",
-                   sl->mb_x, sl->mb_y);
-            return AVERROR_INVALIDDATA;
-        }
-        if (is_chroma && (sl->left_samples_available & 0x8080)) {
-            // mad cow disease mode, aka MBAFF + constrained_intra_pred
-            mode = ALZHEIMER_DC_L0T_PRED8x8 +
-                   (!(sl->left_samples_available & 0x8000)) +
-                   2 * (mode == DC_128_PRED8x8);
-        }
-    }
-
-    return mode;
-}
-
-const uint8_t *ff_h264_decode_nal(H264Context *h, H264SliceContext *sl,
-                                  const uint8_t *src,
-                                  int *dst_length, int *consumed, int length)
-{
-    int i, si, di;
-    uint8_t *dst;
-
-    // src[0]&0x80; // forbidden bit
-    h->nal_ref_idc   = src[0] >> 5;
-    h->nal_unit_type = src[0] & 0x1F;
-
-    src++;
-    length--;
-
-#define STARTCODE_TEST                                                  \
-    if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) {         \
-        if (src[i + 2] != 3 && src[i + 2] != 0) {                       \
-            /* startcode, so we must be past the end */                 \
-            length = i;                                                 \
-        }                                                               \
-        break;                                                          \
-    }
-
-#if HAVE_FAST_UNALIGNED
-#define FIND_FIRST_ZERO                                                 \
-    if (i > 0 && !src[i])                                               \
-        i--;                                                            \
-    while (src[i])                                                      \
-        i++
-
-#if HAVE_FAST_64BIT
-    for (i = 0; i + 1 < length; i += 9) {
-        if (!((~AV_RN64A(src + i) &
-               (AV_RN64A(src + i) - 0x0100010001000101ULL)) &
-              0x8000800080008080ULL))
-            continue;
-        FIND_FIRST_ZERO;
-        STARTCODE_TEST;
-        i -= 7;
-    }
-#else
-    for (i = 0; i + 1 < length; i += 5) {
-        if (!((~AV_RN32A(src + i) &
-               (AV_RN32A(src + i) - 0x01000101U)) &
-              0x80008080U))
-            continue;
-        FIND_FIRST_ZERO;
-        STARTCODE_TEST;
-        i -= 3;
-    }
-#endif
-#else
-    for (i = 0; i + 1 < length; i += 2) {
-        if (src[i])
-            continue;
-        if (i > 0 && src[i - 1] == 0)
-            i--;
-        STARTCODE_TEST;
-    }
-#endif
-
-    av_fast_padded_malloc(&sl->rbsp_buffer, &sl->rbsp_buffer_size, length+MAX_MBPAIR_SIZE);
-    dst = sl->rbsp_buffer;
-
-    if (!dst)
-        return NULL;
-
-    if(i>=length-1){ //no escaped 0
-        *dst_length= length;
-        *consumed= length+1; //+1 for the header
-        if(h->avctx->flags2 & AV_CODEC_FLAG2_FAST){
-            return src;
-        }else{
-            memcpy(dst, src, length);
-            return dst;
-        }
-    }
-
-    memcpy(dst, src, i);
-    si = di = i;
-    while (si + 2 < length) {
-        // remove escapes (very rare 1:2^22)
-        if (src[si + 2] > 3) {
-            dst[di++] = src[si++];
-            dst[di++] = src[si++];
-        } else if (src[si] == 0 && src[si + 1] == 0 && src[si + 2] != 0) {
-            if (src[si + 2] == 3) { // escape
-                dst[di++]  = 0;
-                dst[di++]  = 0;
-                si        += 3;
-                continue;
-            } else // next start code
-                goto nsc;
-        }
-
-        dst[di++] = src[si++];
-    }
-    while (si < length)
-        dst[di++] = src[si++];
-
-nsc:
-    memset(dst + di, 0, AV_INPUT_BUFFER_PADDING_SIZE);
-
-    *dst_length = di;
-    *consumed   = si + 1; // +1 for the header
-    /* FIXME store exact number of bits in the getbitcontext
-     * (it is needed for decoding) */
-    return dst;
-}
-
-/**
- * Identify the exact end of the bitstream
- * @return the length of the trailing, or 0 if damaged
- */
-static int decode_rbsp_trailing(H264Context *h, const uint8_t *src)
-{
-    int v = *src;
-    int r;
-
-    ff_tlog(h->avctx, "rbsp trailing %X\n", v);
-
-    for (r = 1; r < 9; r++) {
-        if (v & 1)
-            return r;
-        v >>= 1;
-    }
-    return 0;
-}
-
 void ff_h264_free_tables(H264Context *h)
 {
     int i;
@@ -401,7 +180,7 @@ void ff_h264_free_tables(H264Context *h)
 int ff_h264_alloc_tables(H264Context *h)
 {
     const int big_mb_num = h->mb_stride * (h->mb_height + 1);
-    const int row_mb_num = 2*h->mb_stride*FFMAX(h->avctx->thread_count, 1);
+    const int row_mb_num = 2*h->mb_stride*FFMAX(h->nb_slice_ctx, 1);
     int x, y;
 
     FF_ALLOCZ_ARRAY_OR_GOTO(h->avctx, h->intra4x4_pred_mode,
@@ -445,9 +224,6 @@ int ff_h264_alloc_tables(H264Context *h)
             h->mb2br_xy[mb_xy] = 8 * (FMO ? mb_xy : (mb_xy % (2 * h->mb_stride)));
         }
 
-    if (!h->dequant4_coeff[0])
-        ff_h264_init_dequant_tables(h);
-
     return 0;
 
 fail:
@@ -524,71 +300,6 @@ fail:
     return AVERROR(ENOMEM); // ff_h264_free_tables will clean up for us
 }
 
-static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
-                            int parse_extradata);
-
-int ff_h264_decode_extradata(H264Context *h, const uint8_t *buf, int size)
-{
-    AVCodecContext *avctx = h->avctx;
-    int ret;
-
-    if (!buf || size <= 0)
-        return -1;
-
-    if (buf[0] == 1) {
-        int i, cnt, nalsize;
-        const unsigned char *p = buf;
-
-        h->is_avc = 1;
-
-        if (size < 7) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "avcC %d too short\n", size);
-            return AVERROR_INVALIDDATA;
-        }
-        /* sps and pps in the avcC always have length coded with 2 bytes,
-         * so put a fake nal_length_size = 2 while parsing them */
-        h->nal_length_size = 2;
-        // Decode sps from avcC
-        cnt = *(p + 5) & 0x1f; // Number of sps
-        p  += 6;
-        for (i = 0; i < cnt; i++) {
-            nalsize = AV_RB16(p) + 2;
-            if(nalsize > size - (p-buf))
-                return AVERROR_INVALIDDATA;
-            ret = decode_nal_units(h, p, nalsize, 1);
-            if (ret < 0) {
-                av_log(avctx, AV_LOG_ERROR,
-                       "Decoding sps %d from avcC failed\n", i);
-                return ret;
-            }
-            p += nalsize;
-        }
-        // Decode pps from avcC
-        cnt = *(p++); // Number of pps
-        for (i = 0; i < cnt; i++) {
-            nalsize = AV_RB16(p) + 2;
-            if(nalsize > size - (p-buf))
-                return AVERROR_INVALIDDATA;
-            ret = decode_nal_units(h, p, nalsize, 1);
-            if (ret < 0) {
-                av_log(avctx, AV_LOG_ERROR,
-                       "Decoding pps %d from avcC failed\n", i);
-                return ret;
-            }
-            p += nalsize;
-        }
-        // Store right nal length size that will be used to parse all other nals
-        h->nal_length_size = (buf[4] & 0x03) + 1;
-    } else {
-        h->is_avc = 0;
-        ret = decode_nal_units(h, buf, size, 1);
-        if (ret < 0)
-            return ret;
-    }
-    return size;
-}
-
 static int h264_init_context(AVCodecContext *avctx, H264Context *h)
 {
     int i;
@@ -597,30 +308,28 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h)
     h->backup_width          = -1;
     h->backup_height         = -1;
     h->backup_pix_fmt        = AV_PIX_FMT_NONE;
-    h->dequant_coeff_pps     = -1;
     h->current_sps_id        = -1;
     h->cur_chroma_format_idc = -1;
 
     h->picture_structure     = PICT_FRAME;
-    h->slice_context_count   = 1;
     h->workaround_bugs       = avctx->workaround_bugs;
     h->flags                 = avctx->flags;
-    h->prev_poc_msb          = 1 << 16;
-    h->x264_build            = -1;
+    h->poc.prev_poc_msb      = 1 << 16;
     h->recovery_frame        = -1;
     h->frame_recovered       = 0;
-    h->prev_frame_num        = -1;
-    h->sei_fpa.frame_packing_arrangement_cancel_flag = -1;
+    h->poc.prev_frame_num    = -1;
+    h->sei.frame_packing.frame_packing_arrangement_cancel_flag = -1;
+    h->sei.unregistered.x264_build = -1;
 
     h->next_outputed_poc = INT_MIN;
     for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
         h->last_pocs[i] = INT_MIN;
 
-    ff_h264_reset_sei(h);
+    ff_h264_sei_uninit(&h->sei);
 
     avctx->chroma_sample_location = AVCHROMA_LOC_LEFT;
 
-    h->nb_slice_ctx = (avctx->active_thread_type & FF_THREAD_SLICE) ?  H264_MAX_THREADS : 1;
+    h->nb_slice_ctx = (avctx->active_thread_type & FF_THREAD_SLICE) ? avctx->thread_count : 1;
     h->slice_ctx = av_mallocz_array(h->nb_slice_ctx, sizeof(*h->slice_ctx));
     if (!h->slice_ctx) {
         h->nb_slice_ctx = 0;
@@ -647,6 +356,38 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h)
     return 0;
 }
 
+static av_cold int h264_decode_end(AVCodecContext *avctx)
+{
+    H264Context *h = avctx->priv_data;
+    int i;
+
+    ff_h264_remove_all_refs(h);
+    ff_h264_free_tables(h);
+
+    for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) {
+        ff_h264_unref_picture(h, &h->DPB[i]);
+        av_frame_free(&h->DPB[i].f);
+    }
+    memset(h->delayed_pic, 0, sizeof(h->delayed_pic));
+
+    h->cur_pic_ptr = NULL;
+
+    av_freep(&h->slice_ctx);
+    h->nb_slice_ctx = 0;
+
+    ff_h264_sei_uninit(&h->sei);
+    ff_h264_ps_uninit(&h->ps);
+
+    ff_h2645_packet_uninit(&h->pkt);
+
+    ff_h264_unref_picture(h, &h->cur_pic);
+    av_frame_free(&h->cur_pic.f);
+    ff_h264_unref_picture(h, &h->last_pic_for_ec);
+    av_frame_free(&h->last_pic_for_ec.f);
+
+    return 0;
+}
+
 static AVOnce h264_vlc_init = AV_ONCE_INIT;
 
 av_cold int ff_h264_decode_init(AVCodecContext *avctx)
@@ -658,10 +399,6 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx)
     if (ret < 0)
         return ret;
 
-    /* set defaults */
-    if (!avctx->has_b_frames)
-        h->low_delay = 1;
-
     ret = ff_thread_once(&h264_vlc_init, ff_h264_decode_init_vlc);
     if (ret != 0) {
         av_log(avctx, AV_LOG_ERROR, "pthread_once has failed.");
@@ -679,17 +416,18 @@ av_cold int ff_h264_decode_init(AVCodecContext *avctx)
     }
 
     if (avctx->extradata_size > 0 && avctx->extradata) {
-        ret = ff_h264_decode_extradata(h, avctx->extradata, avctx->extradata_size);
+        ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
+                                       &h->ps, &h->is_avc, &h->nal_length_size,
+                                       avctx->err_recognition, avctx);
         if (ret < 0) {
             h264_decode_end(avctx);
             return ret;
         }
     }
 
-    if (h->sps.bitstream_restriction_flag &&
-        h->avctx->has_b_frames < h->sps.num_reorder_frames) {
-        h->avctx->has_b_frames = h->sps.num_reorder_frames;
-        h->low_delay           = 0;
+    if (h->ps.sps && h->ps.sps->bitstream_restriction_flag &&
+        h->avctx->has_b_frames < h->ps.sps->num_reorder_frames) {
+        h->avctx->has_b_frames = h->ps.sps->num_reorder_frames;
     }
 
     avctx->internal->allocate_progress = 1;
@@ -739,12 +477,11 @@ static int decode_init_thread_copy(AVCodecContext *avctx)
  */
 static void decode_postinit(H264Context *h, int setup_finished)
 {
+    const SPS *sps = h->ps.sps;
     H264Picture *out = h->cur_pic_ptr;
     H264Picture *cur = h->cur_pic_ptr;
     int i, pics, out_of_order, out_idx;
 
-    h->cur_pic_ptr->f->pict_type = h->pict_type;
-
     if (h->next_output_pic)
         return;
 
@@ -768,8 +505,9 @@ static void decode_postinit(H264Context *h, int setup_finished)
     /* Prioritize picture timing SEI information over used
      * decoding process if it exists. */
 
-    if (h->sps.pic_struct_present_flag) {
-        switch (h->sei_pic_struct) {
+    if (sps->pic_struct_present_flag) {
+        H264SEIPictureTiming *pt = &h->sei.picture_timing;
+        switch (pt->pic_struct) {
         case SEI_PIC_STRUCT_FRAME:
             break;
         case SEI_PIC_STRUCT_TOP_FIELD:
@@ -799,9 +537,9 @@ static void decode_postinit(H264Context *h, int setup_finished)
             break;
         }
 
-        if ((h->sei_ct_type & 3) &&
-            h->sei_pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP)
-            cur->f->interlaced_frame = (h->sei_ct_type & (1 << 1)) != 0;
+        if ((pt->ct_type & 3) &&
+            pt->pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP)
+            cur->f->interlaced_frame = (pt->ct_type & (1 << 1)) != 0;
     } else {
         /* Derive interlacing flag from used decoding process. */
         cur->f->interlaced_frame = FIELD_OR_MBAFF_PICTURE(h);
@@ -812,11 +550,11 @@ static void decode_postinit(H264Context *h, int setup_finished)
         /* Derive top_field_first from field pocs. */
         cur->f->top_field_first = cur->field_poc[0] < cur->field_poc[1];
     } else {
-        if (h->sps.pic_struct_present_flag) {
+        if (sps->pic_struct_present_flag) {
             /* Use picture timing SEI information. Even if it is a
              * information of a past frame, better than nothing. */
-            if (h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM ||
-                h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP)
+            if (h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM ||
+                h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP)
                 cur->f->top_field_first = 1;
             else
                 cur->f->top_field_first = 0;
@@ -830,14 +568,14 @@ static void decode_postinit(H264Context *h, int setup_finished)
         }
     }
 
-    if (h->sei_frame_packing_present &&
-        h->frame_packing_arrangement_type >= 0 &&
-        h->frame_packing_arrangement_type <= 6 &&
-        h->content_interpretation_type > 0 &&
-        h->content_interpretation_type < 3) {
+    if (h->sei.frame_packing.present &&
+        h->sei.frame_packing.frame_packing_arrangement_type <= 6 &&
+        h->sei.frame_packing.content_interpretation_type > 0 &&
+        h->sei.frame_packing.content_interpretation_type < 3) {
+        H264SEIFramePacking *fp = &h->sei.frame_packing;
         AVStereo3D *stereo = av_stereo3d_create_side_data(cur->f);
         if (stereo) {
-        switch (h->frame_packing_arrangement_type) {
+        switch (fp->frame_packing_arrangement_type) {
         case 0:
             stereo->type = AV_STEREO3D_CHECKERBOARD;
             break;
@@ -848,7 +586,7 @@ static void decode_postinit(H264Context *h, int setup_finished)
             stereo->type = AV_STEREO3D_LINES;
             break;
         case 3:
-            if (h->quincunx_subsampling)
+            if (fp->quincunx_sampling_flag)
                 stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX;
             else
                 stereo->type = AV_STEREO3D_SIDEBYSIDE;
@@ -864,42 +602,46 @@ static void decode_postinit(H264Context *h, int setup_finished)
             break;
         }
 
-        if (h->content_interpretation_type == 2)
+        if (fp->content_interpretation_type == 2)
             stereo->flags = AV_STEREO3D_FLAG_INVERT;
         }
     }
 
-    if (h->sei_display_orientation_present &&
-        (h->sei_anticlockwise_rotation || h->sei_hflip || h->sei_vflip)) {
-        double angle = h->sei_anticlockwise_rotation * 360 / (double) (1 << 16);
+    if (h->sei.display_orientation.present &&
+        (h->sei.display_orientation.anticlockwise_rotation ||
+         h->sei.display_orientation.hflip ||
+         h->sei.display_orientation.vflip)) {
+        H264SEIDisplayOrientation *o = &h->sei.display_orientation;
+        double angle = o->anticlockwise_rotation * 360 / (double) (1 << 16);
         AVFrameSideData *rotation = av_frame_new_side_data(cur->f,
                                                            AV_FRAME_DATA_DISPLAYMATRIX,
                                                            sizeof(int32_t) * 9);
         if (rotation) {
             av_display_rotation_set((int32_t *)rotation->data, angle);
             av_display_matrix_flip((int32_t *)rotation->data,
-                                   h->sei_hflip, h->sei_vflip);
+                                   o->hflip, o->vflip);
         }
     }
 
-    if (h->sei_reguserdata_afd_present) {
+    if (h->sei.afd.present) {
         AVFrameSideData *sd = av_frame_new_side_data(cur->f, AV_FRAME_DATA_AFD,
                                                      sizeof(uint8_t));
 
         if (sd) {
-            *sd->data = h->active_format_description;
-            h->sei_reguserdata_afd_present = 0;
+            *sd->data = h->sei.afd.active_format_description;
+            h->sei.afd.present = 0;
         }
     }
 
-    if (h->a53_caption) {
+    if (h->sei.a53_caption.a53_caption) {
+        H264SEIA53Caption *a53 = &h->sei.a53_caption;
         AVFrameSideData *sd = av_frame_new_side_data(cur->f,
                                                      AV_FRAME_DATA_A53_CC,
-                                                     h->a53_caption_size);
+                                                     a53->a53_caption_size);
         if (sd)
-            memcpy(sd->data, h->a53_caption, h->a53_caption_size);
-        av_freep(&h->a53_caption);
-        h->a53_caption_size = 0;
+            memcpy(sd->data, a53->a53_caption, a53->a53_caption_size);
+        av_freep(&a53->a53_caption);
+        a53->a53_caption_size = 0;
         h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS;
     }
 
@@ -909,11 +651,10 @@ static void decode_postinit(H264Context *h, int setup_finished)
     // FIXME do something with unavailable reference frames
 
     /* Sort B-frames into display order */
-    if (h->sps.bitstream_restriction_flag ||
+    if (sps->bitstream_restriction_flag ||
         h->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
-        h->avctx->has_b_frames = FFMAX(h->avctx->has_b_frames, h->sps.num_reorder_frames);
+        h->avctx->has_b_frames = FFMAX(h->avctx->has_b_frames, sps->num_reorder_frames);
     }
-    h->low_delay = !h->avctx->has_b_frames;
 
     for (i = 0; 1; i++) {
         if(i == MAX_DELAYED_PIC_COUNT || cur->poc < h->last_pocs[i]){
@@ -934,10 +675,9 @@ static void decode_postinit(H264Context *h, int setup_finished)
             h->last_pocs[i] = INT_MIN;
         h->last_pocs[0] = cur->poc;
         cur->mmco_reset = 1;
-    } else if(h->avctx->has_b_frames < out_of_order && !h->sps.bitstream_restriction_flag){
+    } else if(h->avctx->has_b_frames < out_of_order && !sps->bitstream_restriction_flag){
         av_log(h->avctx, AV_LOG_INFO, "Increasing reorder buffer to %d\n", out_of_order);
         h->avctx->has_b_frames = out_of_order;
-        h->low_delay = 0;
     }
 
     pics = 0;
@@ -967,8 +707,6 @@ static void decode_postinit(H264Context *h, int setup_finished)
 
     if (out_of_order || pics > h->avctx->has_b_frames) {
         out->reference &= ~DELAYED_PIC_REF;
-        // for frame threading, the owner must be the second field's thread or
-        // else the first thread can release the picture and reuse it unsafely
         for (i = out_idx; h->delayed_pic[i]; i++)
             h->delayed_pic[i] = h->delayed_pic[i + 1];
     }
@@ -999,78 +737,6 @@ static void decode_postinit(H264Context *h, int setup_finished)
     }
 }
 
-int ff_pred_weight_table(H264Context *h, H264SliceContext *sl)
-{
-    int list, i;
-    int luma_def, chroma_def;
-
-    sl->use_weight             = 0;
-    sl->use_weight_chroma      = 0;
-    sl->luma_log2_weight_denom = get_ue_golomb(&sl->gb);
-    if (h->sps.chroma_format_idc)
-        sl->chroma_log2_weight_denom = get_ue_golomb(&sl->gb);
-
-    if (sl->luma_log2_weight_denom > 7U) {
-        av_log(h->avctx, AV_LOG_ERROR, "luma_log2_weight_denom %d is out of range\n", sl->luma_log2_weight_denom);
-        sl->luma_log2_weight_denom = 0;
-    }
-    if (sl->chroma_log2_weight_denom > 7U) {
-        av_log(h->avctx, AV_LOG_ERROR, "chroma_log2_weight_denom %d is out of range\n", sl->chroma_log2_weight_denom);
-        sl->chroma_log2_weight_denom = 0;
-    }
-
-    luma_def   = 1 << sl->luma_log2_weight_denom;
-    chroma_def = 1 << sl->chroma_log2_weight_denom;
-
-    for (list = 0; list < 2; list++) {
-        sl->luma_weight_flag[list]   = 0;
-        sl->chroma_weight_flag[list] = 0;
-        for (i = 0; i < sl->ref_count[list]; i++) {
-            int luma_weight_flag, chroma_weight_flag;
-
-            luma_weight_flag = get_bits1(&sl->gb);
-            if (luma_weight_flag) {
-                sl->luma_weight[i][list][0] = get_se_golomb(&sl->gb);
-                sl->luma_weight[i][list][1] = get_se_golomb(&sl->gb);
-                if (sl->luma_weight[i][list][0] != luma_def ||
-                    sl->luma_weight[i][list][1] != 0) {
-                    sl->use_weight             = 1;
-                    sl->luma_weight_flag[list] = 1;
-                }
-            } else {
-                sl->luma_weight[i][list][0] = luma_def;
-                sl->luma_weight[i][list][1] = 0;
-            }
-
-            if (h->sps.chroma_format_idc) {
-                chroma_weight_flag = get_bits1(&sl->gb);
-                if (chroma_weight_flag) {
-                    int j;
-                    for (j = 0; j < 2; j++) {
-                        sl->chroma_weight[i][list][j][0] = get_se_golomb(&sl->gb);
-                        sl->chroma_weight[i][list][j][1] = get_se_golomb(&sl->gb);
-                        if (sl->chroma_weight[i][list][j][0] != chroma_def ||
-                            sl->chroma_weight[i][list][j][1] != 0) {
-                            sl->use_weight_chroma        = 1;
-                            sl->chroma_weight_flag[list] = 1;
-                        }
-                    }
-                } else {
-                    int j;
-                    for (j = 0; j < 2; j++) {
-                        sl->chroma_weight[i][list][j][0] = chroma_def;
-                        sl->chroma_weight[i][list][j][1] = 0;
-                    }
-                }
-            }
-        }
-        if (sl->slice_type_nos != AV_PICTURE_TYPE_B)
-            break;
-    }
-    sl->use_weight = sl->use_weight || sl->use_weight_chroma;
-    return 0;
-}
-
 /**
  * instantaneous decoder refresh.
  */
@@ -1078,10 +744,10 @@ static void idr(H264Context *h)
 {
     int i;
     ff_h264_remove_all_refs(h);
-    h->prev_frame_num        =
-    h->prev_frame_num_offset = 0;
-    h->prev_poc_msb          = 1<<16;
-    h->prev_poc_lsb          = 0;
+    h->poc.prev_frame_num        =
+    h->poc.prev_frame_num_offset = 0;
+    h->poc.prev_poc_msb          = 1<<16;
+    h->poc.prev_poc_lsb          = 0;
     for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
         h->last_pocs[i] = INT_MIN;
 }
@@ -1095,7 +761,7 @@ void ff_h264_flush_change(H264Context *h)
     h->prev_interlaced_frame = 1;
     idr(h);
 
-    h->prev_frame_num = -1;
+    h->poc.prev_frame_num = -1;
     if (h->cur_pic_ptr) {
         h->cur_pic_ptr->reference = 0;
         for (j=i=0; h->delayed_pic[i]; i++)
@@ -1106,7 +772,7 @@ void ff_h264_flush_change(H264Context *h)
     ff_h264_unref_picture(h, &h->last_pic_for_ec);
 
     h->first_field = 0;
-    ff_h264_reset_sei(h);
+    ff_h264_sei_uninit(&h->sei);
     h->recovery_frame = -1;
     h->frame_recovered = 0;
     h->current_slice = 0;
@@ -1136,273 +802,92 @@ static void flush_dpb(AVCodecContext *avctx)
     h->context_initialized = 0;
 }
 
-int ff_init_poc(H264Context *h, int pic_field_poc[2], int *pic_poc)
-{
-    const int max_frame_num = 1 << h->sps.log2_max_frame_num;
-    int field_poc[2];
-
-    h->frame_num_offset = h->prev_frame_num_offset;
-    if (h->frame_num < h->prev_frame_num)
-        h->frame_num_offset += max_frame_num;
-
-    if (h->sps.poc_type == 0) {
-        const int max_poc_lsb = 1 << h->sps.log2_max_poc_lsb;
-
-        if (h->poc_lsb < h->prev_poc_lsb &&
-            h->prev_poc_lsb - h->poc_lsb >= max_poc_lsb / 2)
-            h->poc_msb = h->prev_poc_msb + max_poc_lsb;
-        else if (h->poc_lsb > h->prev_poc_lsb &&
-                 h->prev_poc_lsb - h->poc_lsb < -max_poc_lsb / 2)
-            h->poc_msb = h->prev_poc_msb - max_poc_lsb;
-        else
-            h->poc_msb = h->prev_poc_msb;
-        field_poc[0] =
-        field_poc[1] = h->poc_msb + h->poc_lsb;
-        if (h->picture_structure == PICT_FRAME)
-            field_poc[1] += h->delta_poc_bottom;
-    } else if (h->sps.poc_type == 1) {
-        int abs_frame_num, expected_delta_per_poc_cycle, expectedpoc;
-        int i;
-
-        if (h->sps.poc_cycle_length != 0)
-            abs_frame_num = h->frame_num_offset + h->frame_num;
-        else
-            abs_frame_num = 0;
-
-        if (h->nal_ref_idc == 0 && abs_frame_num > 0)
-            abs_frame_num--;
-
-        expected_delta_per_poc_cycle = 0;
-        for (i = 0; i < h->sps.poc_cycle_length; i++)
-            // FIXME integrate during sps parse
-            expected_delta_per_poc_cycle += h->sps.offset_for_ref_frame[i];
-
-        if (abs_frame_num > 0) {
-            int poc_cycle_cnt          = (abs_frame_num - 1) / h->sps.poc_cycle_length;
-            int frame_num_in_poc_cycle = (abs_frame_num - 1) % h->sps.poc_cycle_length;
-
-            expectedpoc = poc_cycle_cnt * expected_delta_per_poc_cycle;
-            for (i = 0; i <= frame_num_in_poc_cycle; i++)
-                expectedpoc = expectedpoc + h->sps.offset_for_ref_frame[i];
-        } else
-            expectedpoc = 0;
-
-        if (h->nal_ref_idc == 0)
-            expectedpoc = expectedpoc + h->sps.offset_for_non_ref_pic;
-
-        field_poc[0] = expectedpoc + h->delta_poc[0];
-        field_poc[1] = field_poc[0] + h->sps.offset_for_top_to_bottom_field;
-
-        if (h->picture_structure == PICT_FRAME)
-            field_poc[1] += h->delta_poc[1];
-    } else {
-        int poc = 2 * (h->frame_num_offset + h->frame_num);
-
-        if (!h->nal_ref_idc)
-            poc--;
-
-        field_poc[0] = poc;
-        field_poc[1] = poc;
-    }
-
-    if (h->picture_structure != PICT_BOTTOM_FIELD)
-        pic_field_poc[0] = field_poc[0];
-    if (h->picture_structure != PICT_TOP_FIELD)
-        pic_field_poc[1] = field_poc[1];
-    *pic_poc = FFMIN(pic_field_poc[0], pic_field_poc[1]);
-
-    return 0;
-}
-
-/**
- * Compute profile from profile_idc and constraint_set?_flags.
- *
- * @param sps SPS
- *
- * @return profile as defined by FF_PROFILE_H264_*
- */
-int ff_h264_get_profile(SPS *sps)
-{
-    int profile = sps->profile_idc;
-
-    switch (sps->profile_idc) {
-    case FF_PROFILE_H264_BASELINE:
-        // constraint_set1_flag set to 1
-        profile |= (sps->constraint_set_flags & 1 << 1) ? FF_PROFILE_H264_CONSTRAINED : 0;
-        break;
-    case FF_PROFILE_H264_HIGH_10:
-    case FF_PROFILE_H264_HIGH_422:
-    case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
-        // constraint_set3_flag set to 1
-        profile |= (sps->constraint_set_flags & 1 << 3) ? FF_PROFILE_H264_INTRA : 0;
-        break;
-    }
-
-    return profile;
-}
-
-int ff_set_ref_count(H264Context *h, H264SliceContext *sl)
-{
-    int ref_count[2], list_count;
-    int num_ref_idx_active_override_flag;
-
-    // set defaults, might be overridden a few lines later
-    ref_count[0] = h->pps.ref_count[0];
-    ref_count[1] = h->pps.ref_count[1];
-
-    if (sl->slice_type_nos != AV_PICTURE_TYPE_I) {
-        unsigned max[2];
-        max[0] = max[1] = h->picture_structure == PICT_FRAME ? 15 : 31;
-
-        if (sl->slice_type_nos == AV_PICTURE_TYPE_B)
-            sl->direct_spatial_mv_pred = get_bits1(&sl->gb);
-        num_ref_idx_active_override_flag = get_bits1(&sl->gb);
-
-        if (num_ref_idx_active_override_flag) {
-            ref_count[0] = get_ue_golomb(&sl->gb) + 1;
-            if (sl->slice_type_nos == AV_PICTURE_TYPE_B) {
-                ref_count[1] = get_ue_golomb(&sl->gb) + 1;
-            } else
-                // full range is spec-ok in this case, even for frames
-                ref_count[1] = 1;
-        }
-
-        if (ref_count[0]-1 > max[0] || ref_count[1]-1 > max[1]){
-            av_log(h->avctx, AV_LOG_ERROR, "reference overflow %u > %u or %u > %u\n", ref_count[0]-1, max[0], ref_count[1]-1, max[1]);
-            sl->ref_count[0] = sl->ref_count[1] = 0;
-            sl->list_count   = 0;
-            return AVERROR_INVALIDDATA;
-        }
-
-        if (sl->slice_type_nos == AV_PICTURE_TYPE_B)
-            list_count = 2;
-        else
-            list_count = 1;
-    } else {
-        list_count   = 0;
-        ref_count[0] = ref_count[1] = 0;
-    }
-
-    if (list_count   != sl->list_count   ||
-        ref_count[0] != sl->ref_count[0] ||
-        ref_count[1] != sl->ref_count[1]) {
-        sl->ref_count[0] = ref_count[0];
-        sl->ref_count[1] = ref_count[1];
-        sl->list_count   = list_count;
-        return 1;
-    }
-
-    return 0;
-}
-
+#if FF_API_CAP_VDPAU
 static const uint8_t start_code[] = { 0x00, 0x00, 0x01 };
+#endif
 
-static int get_bit_length(H264Context *h, const uint8_t *buf,
-                          const uint8_t *ptr, int dst_length,
-                          int i, int next_avc)
-{
-    if ((h->workaround_bugs & FF_BUG_AUTODETECT) && i + 3 < next_avc &&
-        buf[i]     == 0x00 && buf[i + 1] == 0x00 &&
-        buf[i + 2] == 0x01 && buf[i + 3] == 0xE0)
-        h->workaround_bugs |= FF_BUG_TRUNCATED;
-
-    if (!(h->workaround_bugs & FF_BUG_TRUNCATED))
-        while (dst_length > 0 && ptr[dst_length - 1] == 0)
-            dst_length--;
-
-    if (!dst_length)
-        return 0;
-
-    return 8 * dst_length - decode_rbsp_trailing(h, ptr + dst_length - 1);
-}
-
-static int get_last_needed_nal(H264Context *h, const uint8_t *buf, int buf_size)
+static int get_last_needed_nal(H264Context *h)
 {
-    int next_avc    = h->is_avc ? 0 : buf_size;
-    int nal_index   = 0;
-    int buf_index   = 0;
     int nals_needed = 0;
     int first_slice = 0;
+    int i;
+    int ret;
 
-    while(1) {
+    for (i = 0; i < h->pkt.nb_nals; i++) {
+        H2645NAL *nal = &h->pkt.nals[i];
         GetBitContext gb;
-        int nalsize = 0;
-        int dst_length, bit_length, consumed;
-        const uint8_t *ptr;
-
-        if (buf_index >= next_avc) {
-            nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
-            if (nalsize < 0)
-                break;
-            next_avc = buf_index + nalsize;
-        } else {
-            buf_index = find_start_code(buf, buf_size, buf_index, next_avc);
-            if (buf_index >= buf_size)
-                break;
-            if (buf_index >= next_avc)
-                continue;
-        }
-
-        ptr = ff_h264_decode_nal(h, &h->slice_ctx[0], buf + buf_index, &dst_length, &consumed,
-                                 next_avc - buf_index);
-
-        if (!ptr || dst_length < 0)
-            return AVERROR_INVALIDDATA;
-
-        buf_index += consumed;
-
-        bit_length = get_bit_length(h, buf, ptr, dst_length,
-                                    buf_index, next_avc);
-        nal_index++;
 
         /* packets can sometimes contain multiple PPS/SPS,
          * e.g. two PAFF field pictures in one packet, or a demuxer
          * which splits NALs strangely if so, when frame threading we
          * can't start the next thread until we've read all of them */
-        switch (h->nal_unit_type) {
+        switch (nal->type) {
         case NAL_SPS:
         case NAL_PPS:
-            nals_needed = nal_index;
+            nals_needed = i;
             break;
         case NAL_DPA:
         case NAL_IDR_SLICE:
         case NAL_SLICE:
-            init_get_bits(&gb, ptr, bit_length);
+            ret = init_get_bits8(&gb, nal->data + 1, (nal->size - 1));
+            if (ret < 0)
+                return ret;
             if (!get_ue_golomb_long(&gb) ||  // first_mb_in_slice
                 !first_slice ||
-                first_slice != h->nal_unit_type)
-                nals_needed = nal_index;
+                first_slice != nal->type)
+                nals_needed = i;
             if (!first_slice)
-                first_slice = h->nal_unit_type;
+                first_slice = nal->type;
         }
     }
 
     return nals_needed;
 }
 
-static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
-                            int parse_extradata)
+static void debug_green_metadata(const H264SEIGreenMetaData *gm, void *logctx)
+{
+    av_log(logctx, AV_LOG_DEBUG, "Green Metadata Info SEI message\n");
+    av_log(logctx, AV_LOG_DEBUG, "  green_metadata_type: %d\n", gm->green_metadata_type);
+
+    if (gm->green_metadata_type == 0) {
+        av_log(logctx, AV_LOG_DEBUG, "  green_metadata_period_type: %d\n", gm->period_type);
+
+        if (gm->period_type == 2)
+            av_log(logctx, AV_LOG_DEBUG, "  green_metadata_num_seconds: %d\n", gm->num_seconds);
+        else if (gm->period_type == 3)
+            av_log(logctx, AV_LOG_DEBUG, "  green_metadata_num_pictures: %d\n", gm->num_pictures);
+
+        av_log(logctx, AV_LOG_DEBUG, "  SEI GREEN Complexity Metrics: %f %f %f %f\n",
+               (float)gm->percent_non_zero_macroblocks/255,
+               (float)gm->percent_intra_coded_macroblocks/255,
+               (float)gm->percent_six_tap_filtering/255,
+               (float)gm->percent_alpha_point_deblocking_instance/255);
+
+    } else if (gm->green_metadata_type == 1) {
+        av_log(logctx, AV_LOG_DEBUG, "  xsd_metric_type: %d\n", gm->xsd_metric_type);
+
+        if (gm->xsd_metric_type == 0)
+            av_log(logctx, AV_LOG_DEBUG, "  xsd_metric_value: %f\n",
+                   (float)gm->xsd_metric_value/100);
+    }
+}
+
+static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
 {
     AVCodecContext *const avctx = h->avctx;
-    H264SliceContext *sl;
-    int buf_index;
-    unsigned context_count;
-    int next_avc;
+    unsigned context_count = 0;
     int nals_needed = 0; ///< number of NALs that need decoding before the next frame thread starts
-    int nal_index;
     int idr_cleared=0;
-    int ret = 0;
+    int i, ret = 0;
 
     h->nal_unit_type= 0;
 
-    if(!h->slice_context_count)
-         h->slice_context_count= 1;
-    h->max_contexts = h->slice_context_count;
+    h->max_contexts = h->nb_slice_ctx;
     if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS)) {
         h->current_slice = 0;
         if (!h->first_field)
             h->cur_pic_ptr = NULL;
-        ff_h264_reset_sei(h);
+        ff_h264_sei_uninit(&h->sei);
     }
 
     if (h->nal_length_size == 4) {
@@ -1412,262 +897,205 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,
             h->is_avc = 1;
     }
 
+    ret = ff_h2645_packet_split(&h->pkt, buf, buf_size, avctx, h->is_avc,
+                                h->nal_length_size, avctx->codec_id);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR,
+               "Error splitting the input into NAL units.\n");
+        return ret;
+    }
+
     if (avctx->active_thread_type & FF_THREAD_FRAME)
-        nals_needed = get_last_needed_nal(h, buf, buf_size);
-
-    {
-        buf_index     = 0;
-        context_count = 0;
-        next_avc      = h->is_avc ? 0 : buf_size;
-        nal_index     = 0;
-        for (;;) {
-            int consumed;
-            int dst_length;
-            int bit_length;
-            const uint8_t *ptr;
-            int nalsize = 0;
-            int err;
-
-            if (buf_index >= next_avc) {
-                nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
-                if (nalsize < 0)
-                    break;
-                next_avc = buf_index + nalsize;
-            } else {
-                buf_index = find_start_code(buf, buf_size, buf_index, next_avc);
-                if (buf_index >= buf_size)
-                    break;
-                if (buf_index >= next_avc)
-                    continue;
-            }
+        nals_needed = get_last_needed_nal(h);
+    if (nals_needed < 0)
+        return nals_needed;
 
-            sl = &h->slice_ctx[context_count];
+    for (i = 0; i < h->pkt.nb_nals; i++) {
+        H2645NAL *nal = &h->pkt.nals[i];
+        H264SliceContext *sl = &h->slice_ctx[context_count];
+        int err;
 
-            ptr = ff_h264_decode_nal(h, sl, buf + buf_index, &dst_length,
-                                     &consumed, next_avc - buf_index);
-            if (!ptr || dst_length < 0) {
+        if (avctx->skip_frame >= AVDISCARD_NONREF &&
+            nal->ref_idc == 0 && nal->type != NAL_SEI)
+            continue;
+
+again:
+        // FIXME these should stop being context-global variables
+        h->nal_ref_idc   = nal->ref_idc;
+        h->nal_unit_type = nal->type;
+
+        err = 0;
+        switch (nal->type) {
+        case NAL_IDR_SLICE:
+            if ((nal->data[1] & 0xFC) == 0x98) {
+                av_log(h->avctx, AV_LOG_ERROR, "Invalid inter IDR frame\n");
+                h->next_outputed_poc = INT_MIN;
                 ret = -1;
                 goto end;
             }
-
-            bit_length = get_bit_length(h, buf, ptr, dst_length,
-                                        buf_index + consumed, next_avc);
-
-            if (h->avctx->debug & FF_DEBUG_STARTCODE)
-                av_log(h->avctx, AV_LOG_DEBUG,
-                       "NAL %d/%d at %d/%d length %d\n",
-                       h->nal_unit_type, h->nal_ref_idc, buf_index, buf_size, dst_length);
-
-            if (h->is_avc && (nalsize != consumed) && nalsize)
-                av_log(h->avctx, AV_LOG_DEBUG,
-                       "AVC: Consumed only %d bytes instead of %d\n",
-                       consumed, nalsize);
-
-            buf_index += consumed;
-            nal_index++;
-
-            if (avctx->skip_frame >= AVDISCARD_NONREF &&
-                h->nal_ref_idc == 0 &&
-                h->nal_unit_type != NAL_SEI)
-                continue;
-
-again:
-            /* Ignore per frame NAL unit type during extradata
-             * parsing. Decoding slices is not possible in codec init
-             * with frame-mt */
-            if (parse_extradata) {
-                switch (h->nal_unit_type) {
-                case NAL_IDR_SLICE:
-                case NAL_SLICE:
-                case NAL_DPA:
-                case NAL_DPB:
-                case NAL_DPC:
-                    av_log(h->avctx, AV_LOG_WARNING,
-                           "Ignoring NAL %d in global header/extradata\n",
-                           h->nal_unit_type);
-                    // fall through to next case
-                case NAL_AUXILIARY_SLICE:
-                    h->nal_unit_type = NAL_FF_IGNORE;
-                }
+            if (nal->type != NAL_IDR_SLICE) {
+                av_log(h->avctx, AV_LOG_ERROR,
+                       "Invalid mix of idr and non-idr slices\n");
+                ret = -1;
+                goto end;
             }
-
-            err = 0;
-
-            switch (h->nal_unit_type) {
-            case NAL_IDR_SLICE:
-                if ((ptr[0] & 0xFC) == 0x98) {
-                    av_log(h->avctx, AV_LOG_ERROR, "Invalid inter IDR frame\n");
-                    h->next_outputed_poc = INT_MIN;
-                    ret = -1;
+            if(!idr_cleared) {
+                if (h->current_slice && (avctx->active_thread_type & FF_THREAD_SLICE)) {
+                    av_log(h, AV_LOG_ERROR, "invalid mixed IDR / non IDR frames cannot be decoded in slice multithreading mode\n");
+                    ret = AVERROR_INVALIDDATA;
                     goto end;
                 }
-                if (h->nal_unit_type != NAL_IDR_SLICE) {
-                    av_log(h->avctx, AV_LOG_ERROR,
-                           "Invalid mix of idr and non-idr slices\n");
-                    ret = -1;
-                    goto end;
-                }
-                if(!idr_cleared) {
-                    if (h->current_slice && (avctx->active_thread_type & FF_THREAD_SLICE)) {
-                        av_log(h, AV_LOG_ERROR, "invalid mixed IDR / non IDR frames cannot be decoded in slice multithreading mode\n");
-                        ret = AVERROR_INVALIDDATA;
-                        goto end;
-                    }
-                    idr(h); // FIXME ensure we don't lose some frames if there is reordering
-                }
-                idr_cleared = 1;
-                h->has_recovery_point = 1;
-            case NAL_SLICE:
-                init_get_bits(&sl->gb, ptr, bit_length);
+                idr(h); // FIXME ensure we don't lose some frames if there is reordering
+            }
+            idr_cleared = 1;
+            h->has_recovery_point = 1;
+        case NAL_SLICE:
+            sl->gb = nal->gb;
+            if (   nals_needed >= i
+                || (!(avctx->active_thread_type & FF_THREAD_FRAME) && !context_count))
+                h->au_pps_id = -1;
 
-                if (   nals_needed >= nal_index
-                    || (!(avctx->active_thread_type & FF_THREAD_FRAME) && !context_count))
-                    h->au_pps_id = -1;
+            if ((err = ff_h264_decode_slice_header(h, sl)))
+                break;
 
-                if ((err = ff_h264_decode_slice_header(h, sl)))
-                    break;
+            if (h->sei.recovery_point.recovery_frame_cnt >= 0) {
+                const int sei_recovery_frame_cnt = h->sei.recovery_point.recovery_frame_cnt;
 
-                if (h->sei_recovery_frame_cnt >= 0) {
-                    if (h->frame_num != h->sei_recovery_frame_cnt || sl->slice_type_nos != AV_PICTURE_TYPE_I)
-                        h->valid_recovery_point = 1;
+                if (h->poc.frame_num != sei_recovery_frame_cnt || sl->slice_type_nos != AV_PICTURE_TYPE_I)
+                    h->valid_recovery_point = 1;
 
-                    if (   h->recovery_frame < 0
-                        || av_mod_uintp2(h->recovery_frame - h->frame_num, h->sps.log2_max_frame_num) > h->sei_recovery_frame_cnt) {
-                        h->recovery_frame = av_mod_uintp2(h->frame_num + h->sei_recovery_frame_cnt, h->sps.log2_max_frame_num);
+                if (   h->recovery_frame < 0
+                    || av_mod_uintp2(h->recovery_frame - h->poc.frame_num, h->ps.sps->log2_max_frame_num) > sei_recovery_frame_cnt) {
+                    h->recovery_frame = av_mod_uintp2(h->poc.frame_num + sei_recovery_frame_cnt, h->ps.sps->log2_max_frame_num);
 
-                        if (!h->valid_recovery_point)
-                            h->recovery_frame = h->frame_num;
-                    }
+                    if (!h->valid_recovery_point)
+                        h->recovery_frame = h->poc.frame_num;
                 }
+            }
 
-                h->cur_pic_ptr->f->key_frame |=
-                    (h->nal_unit_type == NAL_IDR_SLICE);
+            h->cur_pic_ptr->f->key_frame |= (nal->type == NAL_IDR_SLICE);
 
-                if (h->nal_unit_type == NAL_IDR_SLICE ||
-                    h->recovery_frame == h->frame_num) {
-                    h->recovery_frame         = -1;
-                    h->cur_pic_ptr->recovered = 1;
-                }
-                // If we have an IDR, all frames after it in decoded order are
-                // "recovered".
-                if (h->nal_unit_type == NAL_IDR_SLICE)
-                    h->frame_recovered |= FRAME_RECOVERED_IDR;
+            if (nal->type == NAL_IDR_SLICE ||
+                (h->recovery_frame == h->poc.frame_num && nal->ref_idc)) {
+                h->recovery_frame         = -1;
+                h->cur_pic_ptr->recovered = 1;
+            }
+            // If we have an IDR, all frames after it in decoded order are
+            // "recovered".
+            if (nal->type == NAL_IDR_SLICE)
+                h->frame_recovered |= FRAME_RECOVERED_IDR;
 #if 1
-                h->cur_pic_ptr->recovered |= h->frame_recovered;
+            h->cur_pic_ptr->recovered |= h->frame_recovered;
 #else
-                h->cur_pic_ptr->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_IDR);
+            h->cur_pic_ptr->recovered |= !!(h->frame_recovered & FRAME_RECOVERED_IDR);
 #endif
 
-                if (h->current_slice == 1) {
-                    if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS))
-                        decode_postinit(h, nal_index >= nals_needed);
+            if (h->current_slice == 1) {
+                if (!(avctx->flags2 & AV_CODEC_FLAG2_CHUNKS))
+                    decode_postinit(h, i >= nals_needed);
 
-                    if (h->avctx->hwaccel &&
-                        (ret = h->avctx->hwaccel->start_frame(h->avctx, buf, buf_size)) < 0)
-                        goto end;
+                if (h->avctx->hwaccel &&
+                    (ret = h->avctx->hwaccel->start_frame(h->avctx, buf, buf_size)) < 0)
+                    goto end;
 #if FF_API_CAP_VDPAU
-                    if (CONFIG_H264_VDPAU_DECODER &&
-                        h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU)
-                        ff_vdpau_h264_picture_start(h);
+                if (CONFIG_H264_VDPAU_DECODER &&
+                    h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU)
+                    ff_vdpau_h264_picture_start(h);
 #endif
-                }
+            }
 
-                if (sl->redundant_pic_count == 0) {
-                    if (avctx->hwaccel) {
-                        ret = avctx->hwaccel->decode_slice(avctx,
-                                                           &buf[buf_index - consumed],
-                                                           consumed);
-                        if (ret < 0)
-                            goto end;
+            if (sl->redundant_pic_count == 0) {
+                if (avctx->hwaccel) {
+                    ret = avctx->hwaccel->decode_slice(avctx,
+                                                       nal->raw_data,
+                                                       nal->raw_size);
+                    if (ret < 0)
+                        goto end;
 #if FF_API_CAP_VDPAU
-                    } else if (CONFIG_H264_VDPAU_DECODER &&
-                               h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU) {
-                        ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0],
-                                                start_code,
-                                                sizeof(start_code));
-                        ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0],
-                                                &buf[buf_index - consumed],
-                                                consumed);
+                } else if (CONFIG_H264_VDPAU_DECODER &&
+                           h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU) {
+                    ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0],
+                                            start_code,
+                                            sizeof(start_code));
+                    ff_vdpau_add_data_chunk(h->cur_pic_ptr->f->data[0],
+                                            nal->raw_data,
+                                            nal->raw_size);
 #endif
-                    } else
-                        context_count++;
-                }
-                break;
-            case NAL_DPA:
-            case NAL_DPB:
-            case NAL_DPC:
-                avpriv_request_sample(avctx, "data partitioning");
+                } else
+                    context_count++;
+            }
+            break;
+        case NAL_DPA:
+        case NAL_DPB:
+        case NAL_DPC:
+            avpriv_request_sample(avctx, "data partitioning");
+            break;
+        case NAL_SEI:
+            ret = ff_h264_sei_decode(&h->sei, &nal->gb, &h->ps, avctx);
+            h->has_recovery_point = h->has_recovery_point || h->sei.recovery_point.recovery_frame_cnt != -1;
+            if (avctx->debug & FF_DEBUG_GREEN_MD)
+                debug_green_metadata(&h->sei.green_metadata, h->avctx);
+#if FF_API_AFD
+FF_DISABLE_DEPRECATION_WARNINGS
+            h->avctx->dtg_active_format = h->sei.afd.active_format_description;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif /* FF_API_AFD */
+            if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+                goto end;
+            break;
+        case NAL_SPS: {
+            GetBitContext tmp_gb = nal->gb;
+            if (ff_h264_decode_seq_parameter_set(&tmp_gb, avctx, &h->ps, 0) >= 0)
                 break;
-            case NAL_SEI:
-                init_get_bits(&h->gb, ptr, bit_length);
-                ret = ff_h264_decode_sei(h);
-                if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
-                    goto end;
+            av_log(h->avctx, AV_LOG_DEBUG,
+                   "SPS decoding failure, trying again with the complete NAL\n");
+            init_get_bits8(&tmp_gb, nal->raw_data + 1, nal->raw_size - 1);
+            if (ff_h264_decode_seq_parameter_set(&tmp_gb, avctx, &h->ps, 0) >= 0)
                 break;
-            case NAL_SPS:
-                init_get_bits(&h->gb, ptr, bit_length);
-                if (ff_h264_decode_seq_parameter_set(h, 0) >= 0)
-                    break;
-                if (h->is_avc ? nalsize : 1) {
-                    av_log(h->avctx, AV_LOG_DEBUG,
-                           "SPS decoding failure, trying again with the complete NAL\n");
-                    if (h->is_avc)
-                        av_assert0(next_avc - buf_index + consumed == nalsize);
-                    if ((next_avc - buf_index + consumed - 1) >= INT_MAX/8)
-                        break;
-                    init_get_bits(&h->gb, &buf[buf_index + 1 - consumed],
-                                  8*(next_avc - buf_index + consumed - 1));
-                    if (ff_h264_decode_seq_parameter_set(h, 0) >= 0)
-                        break;
-                }
-                init_get_bits(&h->gb, ptr, bit_length);
-                ff_h264_decode_seq_parameter_set(h, 1);
+            ff_h264_decode_seq_parameter_set(&nal->gb, avctx, &h->ps, 1);
+            break;
+        }
+        case NAL_PPS:
+            ret = ff_h264_decode_picture_parameter_set(&nal->gb, avctx, &h->ps,
+                                                       nal->size_bits);
+            if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+                goto end;
+            break;
+        case NAL_AUD:
+        case NAL_END_SEQUENCE:
+        case NAL_END_STREAM:
+        case NAL_FILLER_DATA:
+        case NAL_SPS_EXT:
+        case NAL_AUXILIARY_SLICE:
+            break;
+        case NAL_FF_IGNORE:
+            break;
+        default:
+            av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n",
+                   nal->type, nal->size_bits);
+        }
 
-                break;
-            case NAL_PPS:
-                init_get_bits(&h->gb, ptr, bit_length);
-                ret = ff_h264_decode_picture_parameter_set(h, bit_length);
-                if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
-                    goto end;
-                break;
-            case NAL_AUD:
-            case NAL_END_SEQUENCE:
-            case NAL_END_STREAM:
-            case NAL_FILLER_DATA:
-            case NAL_SPS_EXT:
-            case NAL_AUXILIARY_SLICE:
-                break;
-            case NAL_FF_IGNORE:
-                break;
-            default:
-                av_log(avctx, AV_LOG_DEBUG, "Unknown NAL code: %d (%d bits)\n",
-                       h->nal_unit_type, bit_length);
-            }
+        if (context_count == h->max_contexts) {
+            ret = ff_h264_execute_decode_slices(h, context_count);
+            if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+                goto end;
+            context_count = 0;
+        }
 
-            if (context_count == h->max_contexts) {
+        if (err < 0 || err == SLICE_SKIPED) {
+            if (err < 0)
+                av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n");
+            sl->ref_count[0] = sl->ref_count[1] = sl->list_count = 0;
+        } else if (err == SLICE_SINGLETHREAD) {
+            if (context_count > 0) {
                 ret = ff_h264_execute_decode_slices(h, context_count);
                 if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
                     goto end;
                 context_count = 0;
             }
-
-            if (err < 0 || err == SLICE_SKIPED) {
-                if (err < 0)
-                    av_log(h->avctx, AV_LOG_ERROR, "decode_slice_header error\n");
-                sl->ref_count[0] = sl->ref_count[1] = sl->list_count = 0;
-            } else if (err == SLICE_SINGLETHREAD) {
-                if (context_count > 1) {
-                    ret = ff_h264_execute_decode_slices(h, context_count - 1);
-                    if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
-                        goto end;
-                    context_count = 0;
-                }
-                /* Slice could not be decoded in parallel mode, restart. Note
-                 * that rbsp_buffer is not transferred, but since we no longer
-                 * run in parallel mode this should not be an issue. */
-                sl               = &h->slice_ctx[0];
-                goto again;
-            }
+            /* Slice could not be decoded in parallel mode, restart. */
+            sl               = &h->slice_ctx[0];
+            goto again;
         }
     }
     if (context_count) {
@@ -1680,7 +1108,6 @@ again:
 end:
 
 #if CONFIG_ERROR_RESILIENCE
-    sl = h->slice_ctx;
     /*
      * FIXME: Error handling code does not seem to support interlaced
      * when slices span multiple rows
@@ -1693,7 +1120,11 @@ end:
      * past end by one (callers fault) and resync_mb_y != 0
      * causes problems for the first MB line, too.
      */
-    if (!FIELD_PICTURE(h) && h->current_slice && !h->sps.new && h->enable_er) {
+    if (!FIELD_PICTURE(h) && h->current_slice &&
+        h->ps.sps == (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data &&
+        h->enable_er) {
+
+        H264SliceContext *sl = h->slice_ctx;
         int use_last_pic = h->last_pic_for_ec.f->buf[0] && !sl->ref_count[0];
 
         ff_h264_set_erpic(&sl->er.cur_pic, h->cur_pic_ptr);
@@ -1725,7 +1156,7 @@ end:
                                   h->picture_structure == PICT_BOTTOM_FIELD);
     }
 
-    return (ret < 0) ? ret : buf_index;
+    return (ret < 0) ? ret : buf_size;
 }
 
 /**
@@ -1750,7 +1181,7 @@ static int output_frame(H264Context *h, AVFrame *dst, H264Picture *srcp)
     if (ret < 0)
         return ret;
 
-    av_dict_set(&dst->metadata, "stereo_mode", ff_h264_sei_stereo_mode(h), 0);
+    av_dict_set(&dst->metadata, "stereo_mode", ff_h264_sei_stereo_mode(&h->sei.frame_packing), 0);
 
     h->backup_width   = h->avctx->width;
     h->backup_height  = h->avctx->height;
@@ -1864,14 +1295,18 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data,
         int side_size;
         uint8_t *side = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
         if (is_extra(side, side_size))
-            ff_h264_decode_extradata(h, side, side_size);
+            ff_h264_decode_extradata(side, side_size,
+                                     &h->ps, &h->is_avc, &h->nal_length_size,
+                                     avctx->err_recognition, avctx);
     }
     if(h->is_avc && buf_size >= 9 && buf[0]==1 && buf[2]==0 && (buf[4]&0xFC)==0xFC && (buf[5]&0x1F) && buf[8]==0x67){
         if (is_extra(buf, buf_size))
-            return ff_h264_decode_extradata(h, buf, buf_size);
+            return ff_h264_decode_extradata(buf, buf_size,
+                                            &h->ps, &h->is_avc, &h->nal_length_size,
+                                            avctx->err_recognition, avctx);
     }
 
-    buf_index = decode_nal_units(h, buf, buf_size, 0);
+    buf_index = decode_nal_units(h, buf, buf_size);
     if (buf_index < 0)
         return AVERROR_INVALIDDATA;
 
@@ -1936,7 +1371,7 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data,
                                     h->next_output_pic->mb_type,
                                     h->next_output_pic->qscale_table,
                                     h->next_output_pic->motion_val,
-                                    &h->low_delay,
+                                    NULL,
                                     h->mb_width, h->mb_height, h->mb_stride, 1);
             }
         }
@@ -1949,50 +1384,6 @@ static int h264_decode_frame(AVCodecContext *avctx, void *data,
     return get_consumed_bytes(buf_index, buf_size);
 }
 
-av_cold void ff_h264_free_context(H264Context *h)
-{
-    int i;
-
-    ff_h264_free_tables(h);
-
-    for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) {
-        ff_h264_unref_picture(h, &h->DPB[i]);
-        av_frame_free(&h->DPB[i].f);
-    }
-    memset(h->delayed_pic, 0, sizeof(h->delayed_pic));
-
-    h->cur_pic_ptr = NULL;
-
-    for (i = 0; i < h->nb_slice_ctx; i++)
-        av_freep(&h->slice_ctx[i].rbsp_buffer);
-    av_freep(&h->slice_ctx);
-    h->nb_slice_ctx = 0;
-
-    h->a53_caption_size = 0;
-    av_freep(&h->a53_caption);
-
-    for (i = 0; i < MAX_SPS_COUNT; i++)
-        av_freep(h->sps_buffers + i);
-
-    for (i = 0; i < MAX_PPS_COUNT; i++)
-        av_freep(h->pps_buffers + i);
-}
-
-static av_cold int h264_decode_end(AVCodecContext *avctx)
-{
-    H264Context *h = avctx->priv_data;
-
-    ff_h264_remove_all_refs(h);
-    ff_h264_free_context(h);
-
-    ff_h264_unref_picture(h, &h->cur_pic);
-    av_frame_free(&h->cur_pic.f);
-    ff_h264_unref_picture(h, &h->last_pic_for_ec);
-    av_frame_free(&h->last_pic_for_ec.f);
-
-    return 0;
-}
-
 #define OFFSET(x) offsetof(H264Context, x)
 #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
 static const AVOption h264_options[] = {
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index a5fc3a0..efe3555 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -21,18 +21,22 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 codec.
+ * H.264 / AVC / MPEG-4 part10 codec.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
 #ifndef AVCODEC_H264_H
 #define AVCODEC_H264_H
 
+#include "libavutil/buffer.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/thread.h"
 #include "cabac.h"
 #include "error_resilience.h"
 #include "get_bits.h"
+#include "h264_parse.h"
+#include "h264_sei.h"
+#include "h2645_parse.h"
 #include "h264chroma.h"
 #include "h264dsp.h"
 #include "h264pred.h"
@@ -45,7 +49,6 @@
 #include "videodsp.h"
 
 #define H264_MAX_PICTURE_COUNT 36
-#define H264_MAX_THREADS       32
 
 #define MAX_SPS_COUNT          32
 #define MAX_PPS_COUNT         256
@@ -92,12 +95,12 @@
 #define FIELD_OR_MBAFF_PICTURE(h) (FRAME_MBAFF(h) || FIELD_PICTURE(h))
 
 #ifndef CABAC
-#define CABAC(h) (h)->pps.cabac
+#define CABAC(h) (h)->ps.pps->cabac
 #endif
 
-#define CHROMA(h)    ((h)->sps.chroma_format_idc)
-#define CHROMA422(h) ((h)->sps.chroma_format_idc == 2)
-#define CHROMA444(h) ((h)->sps.chroma_format_idc == 3)
+#define CHROMA(h)    ((h)->ps.sps->chroma_format_idc)
+#define CHROMA422(h) ((h)->ps.sps->chroma_format_idc == 2)
+#define CHROMA444(h) ((h)->ps.sps->chroma_format_idc == 3)
 
 #define EXTENDED_SAR       255
 
@@ -128,48 +131,6 @@ enum {
 };
 
 /**
- * SEI message types
- */
-typedef enum {
-    SEI_TYPE_BUFFERING_PERIOD       = 0,   ///< buffering period (H.264, D.1.1)
-    SEI_TYPE_PIC_TIMING             = 1,   ///< picture timing
-    SEI_TYPE_USER_DATA_REGISTERED   = 4,   ///< registered user data as specified by Rec. ITU-T T.35
-    SEI_TYPE_USER_DATA_UNREGISTERED = 5,   ///< unregistered user data
-    SEI_TYPE_RECOVERY_POINT         = 6,   ///< recovery point (frame # to decoder sync)
-    SEI_TYPE_FRAME_PACKING          = 45,  ///< frame packing arrangement
-    SEI_TYPE_DISPLAY_ORIENTATION    = 47,  ///< display orientation
-    SEI_TYPE_GREEN_METADATA         = 56   ///< GreenMPEG information
-} SEI_Type;
-
-/**
- * pic_struct in picture timing SEI message
- */
-typedef enum {
-    SEI_PIC_STRUCT_FRAME             = 0, ///<  0: %frame
-    SEI_PIC_STRUCT_TOP_FIELD         = 1, ///<  1: top field
-    SEI_PIC_STRUCT_BOTTOM_FIELD      = 2, ///<  2: bottom field
-    SEI_PIC_STRUCT_TOP_BOTTOM        = 3, ///<  3: top field, bottom field, in that order
-    SEI_PIC_STRUCT_BOTTOM_TOP        = 4, ///<  4: bottom field, top field, in that order
-    SEI_PIC_STRUCT_TOP_BOTTOM_TOP    = 5, ///<  5: top field, bottom field, top field repeated, in that order
-    SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM = 6, ///<  6: bottom field, top field, bottom field repeated, in that order
-    SEI_PIC_STRUCT_FRAME_DOUBLING    = 7, ///<  7: %frame doubling
-    SEI_PIC_STRUCT_FRAME_TRIPLING    = 8  ///<  8: %frame tripling
-} SEI_PicStructType;
-
-/**
- * frame_packing_arrangement types
- */
-typedef enum {
-    SEI_FPA_TYPE_CHECKERBOARD        = 0,
-    SEI_FPA_TYPE_INTERLEAVE_COLUMN   = 1,
-    SEI_FPA_TYPE_INTERLEAVE_ROW      = 2,
-    SEI_FPA_TYPE_SIDE_BY_SIDE        = 3,
-    SEI_FPA_TYPE_TOP_BOTTOM          = 4,
-    SEI_FPA_TYPE_INTERLEAVE_TEMPORAL = 5,
-    SEI_FPA_TYPE_2D                  = 6,
-} SEI_FpaType;
-
-/**
  * Sequence parameter set
  */
 typedef struct SPS {
@@ -229,7 +190,6 @@ typedef struct SPS {
     int bit_depth_chroma;                 ///< bit_depth_chroma_minus8 + 8
     int residual_color_transform_flag;    ///< residual_colour_transform_flag
     int constraint_set_flags;             ///< constraint_set[0-3]_flag
-    int new;                              ///< flag to keep track if the decoder context needs re-init due to changed SPS
     uint8_t data[4096];
     size_t data_size;
 } SPS;
@@ -259,35 +219,24 @@ typedef struct PPS {
     int chroma_qp_diff;
     uint8_t data[4096];
     size_t data_size;
+
+    uint32_t dequant4_buffer[6][QP_MAX_NUM + 1][16];
+    uint32_t dequant8_buffer[6][QP_MAX_NUM + 1][64];
+    uint32_t(*dequant4_coeff[6])[16];
+    uint32_t(*dequant8_coeff[6])[64];
 } PPS;
 
-/**
- * Frame Packing Arrangement Type
- */
-typedef struct FPA {
-    int         frame_packing_arrangement_id;
-    int         frame_packing_arrangement_cancel_flag; ///< is previous arrangement canceled, -1 if never received
-    SEI_FpaType frame_packing_arrangement_type;
-    int         frame_packing_arrangement_repetition_period;
-    int         content_interpretation_type;
-    int         quincunx_sampling_flag;
-} FPA;
+typedef struct H264ParamSets {
+    AVBufferRef *sps_list[MAX_SPS_COUNT];
+    AVBufferRef *pps_list[MAX_PPS_COUNT];
 
-/**
- *     Green MetaData Information Type
- */
-typedef struct GreenMetaData {
-    uint8_t  green_metadata_type;
-    uint8_t  period_type;
-    uint16_t  num_seconds;
-    uint16_t  num_pictures;
-    uint8_t percent_non_zero_macroblocks;
-    uint8_t percent_intra_coded_macroblocks;
-    uint8_t percent_six_tap_filtering;
-    uint8_t percent_alpha_point_deblocking_instance;
-    uint8_t xsd_metric_type;
-    uint16_t xsd_metric_value;
-} GreenMetaData;
+    AVBufferRef *pps_ref;
+    AVBufferRef *sps_ref;
+    /* currently active parameters sets */
+    const PPS *pps;
+    // FIXME this should properly be const
+    SPS *sps;
+} H264ParamSets;
 
 /**
  * Memory management control operation opcode.
@@ -384,17 +333,7 @@ typedef struct H264SliceContext {
     int slice_alpha_c0_offset;
     int slice_beta_offset;
 
-    // Weighted pred stuff
-    int use_weight;
-    int use_weight_chroma;
-    int luma_log2_weight_denom;
-    int chroma_log2_weight_denom;
-    int luma_weight_flag[2];    ///< 7.4.3.2 luma_weight_lX_flag
-    int chroma_weight_flag[2];  ///< 7.4.3.2 chroma_weight_lX_flag
-    // The following 2 can be changed to int8_t but that causes 10cpu cycles speedloss
-    int luma_weight[48][2][2];
-    int chroma_weight[48][2][2][2];
-    int implicit_weight[48][48][2];
+    H264PredWeightTable pwt;
 
     int prev_mb_skipped;
     int next_mb_skipped;
@@ -467,7 +406,6 @@ typedef struct H264SliceContext {
     H264Ref ref_list[2][48];        /**< 0..15: frame refs, 16..47: mbaff field refs.
                                          *   Reordered version of default_ref_list
                                          *   according to picture reordering in slice header */
-    int ref2frm[MAX_SLICES][2][64];     ///< reference to frame number lists, used in the loop filter, the first 2 are for -2,-1
 
     const uint8_t *intra_pcm_ptr;
     int16_t *dc_val_base;
@@ -495,7 +433,7 @@ typedef struct H264SliceContext {
 
     DECLARE_ALIGNED(8, uint16_t, sub_mb_type)[4];
 
-    ///< as a dct coefficient is int32_t in high depth, we need to reserve twice the space.
+    ///< as a DCT coefficient is int32_t in high depth, we need to reserve twice the space.
     DECLARE_ALIGNED(16, int16_t, mb)[16 * 48 * 2];
     DECLARE_ALIGNED(16, int16_t, mb_luma_dc)[3][16 * 2];
     ///< as mb is addressed by scantable[i] and scantable is uint8_t we can either
@@ -510,17 +448,13 @@ typedef struct H264SliceContext {
     CABACContext cabac;
     uint8_t cabac_state[1024];
     int cabac_init_idc;
-
-    // rbsp buffer used for this slice
-    uint8_t *rbsp_buffer;
-    unsigned int rbsp_buffer_size;
 } H264SliceContext;
 
 /**
  * H264Context
  */
 typedef struct H264Context {
-    AVClass *av_class;
+    const AVClass *class;
     AVCodecContext *avctx;
     VideoDSPContext vdsp;
     H264DSPContext h264dsp;
@@ -536,7 +470,9 @@ typedef struct H264Context {
     H264SliceContext *slice_ctx;
     int            nb_slice_ctx;
 
-    int pixel_shift;    ///< 0 for 8-bit H264, 1 for high-bit-depth H264
+    H2645Packet pkt;
+
+    int pixel_shift;    ///< 0 for 8-bit H.264, 1 for high-bit-depth H.264
 
     /* coded dimensions -- 16 * mb w/h */
     int width, height;
@@ -552,11 +488,15 @@ typedef struct H264Context {
 
     int droppable;
     int coded_picture_number;
-    int low_delay;
 
     int context_initialized;
     int flags;
     int workaround_bugs;
+    /* Set when slice threading is used and at least one slice uses deblocking
+     * mode 1 (i.e. across slice boundaries). Then we disable the loop filter
+     * during normal MB decoding and execute it serially at the end.
+     */
+    int postpone_filter;
 
     int8_t(*intra4x4_pred_mode);
     H264PredContext hpc;
@@ -578,16 +518,9 @@ typedef struct H264Context {
 
 
     unsigned current_sps_id; ///< id of the current SPS
-    SPS sps; ///< current sps
-    PPS pps; ///< current pps
 
     int au_pps_id; ///< pps_id of current access unit
 
-    uint32_t dequant4_buffer[6][QP_MAX_NUM + 1][16]; // FIXME should these be moved down?
-    uint32_t dequant8_buffer[6][QP_MAX_NUM + 1][64];
-    uint32_t(*dequant4_coeff[6])[16];
-    uint32_t(*dequant8_coeff[6])[64];
-
     uint16_t *slice_table;      ///< slice_table_base + 2*mb_stride + 1
 
     // interlacing specific flags
@@ -618,8 +551,6 @@ typedef struct H264Context {
     uint8_t field_scan8x8_q0[64];
     uint8_t field_scan8x8_cavlc_q0[64];
 
-    int x264_build;
-
     int mb_y;
     int mb_height, mb_width;
     int mb_stride;
@@ -632,7 +563,7 @@ typedef struct H264Context {
     int nal_unit_type;
 
     /**
-     * Used to parse AVC variant of h264
+     * Used to parse AVC variant of H.264
      */
     int is_avc;           ///< this flag is != 0 if codec is avc1
     int nal_length_size;  ///< Number of bytes used for nal length (1, 2 or 4)
@@ -640,24 +571,11 @@ typedef struct H264Context {
     int bit_depth_luma;         ///< luma bit depth from sps to detect changes
     int chroma_format_idc;      ///< chroma format from sps to detect changes
 
-    SPS *sps_buffers[MAX_SPS_COUNT];
-    PPS *pps_buffers[MAX_PPS_COUNT];
-
-    int dequant_coeff_pps;      ///< reinit tables when pps changes
+    H264ParamSets ps;
 
     uint16_t *slice_table_base;
 
-    // POC stuff
-    int poc_lsb;
-    int poc_msb;
-    int delta_poc_bottom;
-    int delta_poc[2];
-    int frame_num;
-    int prev_poc_msb;           ///< poc_msb of the last reference pic for POC type 0
-    int prev_poc_lsb;           ///< poc_lsb of the last reference pic for POC type 0
-    int frame_num_offset;       ///< for POC type 2
-    int prev_frame_num_offset;  ///< for POC type 2
-    int prev_frame_num;         ///< frame_num of the last pic for POC type 1/2
+    H264POCContext poc;
 
     /**
      * frame_num for frames or 2 * frame_num + 1 for field pics.
@@ -704,24 +622,15 @@ typedef struct H264Context {
      */
     int max_contexts;
 
-    int slice_context_count;
-
     /**
      *  1 if the single thread fallback warning has already been
      *  displayed, 0 otherwise.
      */
     int single_decode_warning;
 
-    enum AVPictureType pict_type;
-
     /** @} */
 
     /**
-     * pic_struct in picture timing SEI message
-     */
-    SEI_PicStructType sei_pic_struct;
-
-    /**
      * Complement sei_pic_struct
      * SEI_PIC_STRUCT_TOP_BOTTOM and SEI_PIC_STRUCT_BOTTOM_TOP indicate interlaced frames.
      * However, soft telecined frames may have these values.
@@ -730,61 +639,10 @@ typedef struct H264Context {
     int prev_interlaced_frame;
 
     /**
-     * frame_packing_arrangment SEI message
-     */
-    int sei_frame_packing_present;
-    int frame_packing_arrangement_type;
-    int content_interpretation_type;
-    int quincunx_subsampling;
-
-    /**
-     * display orientation SEI message
-     */
-    int sei_display_orientation_present;
-    int sei_anticlockwise_rotation;
-    int sei_hflip, sei_vflip;
-
-    /**
-     * User data registered by Rec. ITU-T T.35 SEI
-     */
-    int sei_reguserdata_afd_present;
-    uint8_t active_format_description;
-    int a53_caption_size;
-    uint8_t *a53_caption;
-
-    /**
-     * Bit set of clock types for fields/frames in picture timing SEI message.
-     * For each found ct_type, appropriate bit is set (e.g., bit 1 for
-     * interlaced).
-     */
-    int sei_ct_type;
-
-    /**
-     * dpb_output_delay in picture timing SEI message, see H.264 C.2.2
-     */
-    int sei_dpb_output_delay;
-
-    /**
-     * cpb_removal_delay in picture timing SEI message, see H.264 C.1.2
-     */
-    int sei_cpb_removal_delay;
-
-    /**
-     * recovery_frame_cnt from SEI message
-     *
-     * Set to -1 if no recovery point SEI message found or to number of frames
-     * before playback synchronizes. Frames having recovery point are key
-     * frames.
-     */
-    int sei_recovery_frame_cnt;
-
-    /**
      * Are the SEI recovery points looking valid.
      */
     int valid_recovery_point;
 
-    FPA sei_fpa;
-
     /**
      * recovery_frame is the frame_num at which the next frame should
      * be fully constructed.
@@ -816,73 +674,40 @@ typedef struct H264Context {
      * slices) anymore */
     int setup_finished;
 
-    // Timestamp stuff
-    int sei_buffering_period_present;   ///< Buffering period SEI flag
-    int initial_cpb_removal_delay[32];  ///< Initial timestamps for CPBs
-
     int cur_chroma_format_idc;
     int cur_bit_depth_luma;
     int16_t slice_row[MAX_SLICES]; ///< to detect when MAX_SLICES is too low
 
-    uint8_t parse_history[6];
-    int parse_history_count;
-    int parse_last_mb;
-
     int enable_er;
 
+    H264SEIContext sei;
+
     AVBufferPool *qscale_table_pool;
     AVBufferPool *mb_type_pool;
     AVBufferPool *motion_val_pool;
     AVBufferPool *ref_index_pool;
-
-    /* Motion Estimation */
-    qpel_mc_func (*qpel_put)[16];
-    qpel_mc_func (*qpel_avg)[16];
-
-    /*Green Metadata */
-    GreenMetaData sei_green_metadata;
-
+    int ref2frm[MAX_SLICES][2][64];     ///< reference to frame number lists, used in the loop filter, the first 2 are for -2,-1
 } H264Context;
 
-extern const uint8_t ff_h264_chroma_qp[7][QP_MAX_NUM + 1]; ///< One chroma qp table for each possible bit depth (8-14).
 extern const uint16_t ff_h264_mb_sizes[4];
 
 /**
- * Decode SEI
+ * Uninit H264 param sets structure.
  */
-int ff_h264_decode_sei(H264Context *h);
 
-/**
- * Decode SPS
- */
-int ff_h264_decode_seq_parameter_set(H264Context *h, int ignore_truncation);
+void ff_h264_ps_uninit(H264ParamSets *ps);
 
 /**
- * compute profile from sps
+ * Decode SPS
  */
-int ff_h264_get_profile(SPS *sps);
+int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx,
+                                     H264ParamSets *ps, int ignore_truncation);
 
 /**
  * Decode PPS
  */
-int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length);
-
-/**
- * Decode a network abstraction layer unit.
- * @param consumed is the number of bytes used as input
- * @param length is the length of the array
- * @param dst_length is the number of decoded bytes FIXME here
- *                   or a decode rbsp tailing?
- * @return decoded bytes, might be src+1 if no escapes
- */
-const uint8_t *ff_h264_decode_nal(H264Context *h, H264SliceContext *sl, const uint8_t *src,
-                                  int *dst_length, int *consumed, int length);
-
-/**
- * Free any data that may have been allocated in the H264 context
- * like SPS, PPS etc.
- */
-void ff_h264_free_context(H264Context *h);
+int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avctx,
+                                         H264ParamSets *ps, int bit_length);
 
 /**
  * Reconstruct bitstream slice_type.
@@ -896,7 +721,7 @@ int ff_h264_get_slice_type(const H264SliceContext *sl);
 int ff_h264_alloc_tables(H264Context *h);
 
 int ff_h264_decode_ref_pic_list_reordering(H264Context *h, H264SliceContext *sl);
-void ff_h264_fill_mbaff_ref_list(H264Context *h, H264SliceContext *sl);
+void ff_h264_fill_mbaff_ref_list(H264SliceContext *sl);
 void ff_h264_remove_all_refs(H264Context *h);
 
 /**
@@ -909,21 +734,7 @@ int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb,
 
 int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice);
 
-/**
- * Check if the top & left blocks are available if needed & change the
- * dc mode so it only uses the available blocks.
- */
-int ff_h264_check_intra4x4_pred_mode(const H264Context *h, H264SliceContext *sl);
-
-/**
- * Check if the top & left blocks are available if needed & change the
- * dc mode so it only uses the available blocks.
- */
-int ff_h264_check_intra_pred_mode(const H264Context *h, H264SliceContext *sl,
-                                  int mode, int is_chroma);
-
 void ff_h264_hl_decode_mb(const H264Context *h, H264SliceContext *sl);
-int ff_h264_decode_extradata(H264Context *h, const uint8_t *buf, int size);
 int ff_h264_decode_init(AVCodecContext *avctx);
 void ff_h264_decode_init_vlc(void);
 
@@ -941,8 +752,6 @@ int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl);
 
 void ff_h264_init_cabac_states(const H264Context *h, H264SliceContext *sl);
 
-void ff_h264_init_dequant_tables(H264Context *h);
-
 void ff_h264_direct_dist_scale_factor(const H264Context *const h, H264SliceContext *sl);
 void ff_h264_direct_ref_list_init(const H264Context *const h, H264SliceContext *sl);
 void ff_h264_pred_direct_motion(const H264Context *const h, H264SliceContext *sl,
@@ -955,19 +764,6 @@ void ff_h264_filter_mb(const H264Context *h, H264SliceContext *sl, int mb_x, int
                        uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr,
                        unsigned int linesize, unsigned int uvlinesize);
 
-/**
- * Reset SEI values at the beginning of the frame.
- *
- * @param h H.264 context.
- */
-void ff_h264_reset_sei(H264Context *h);
-
-/**
- * Get stereo_mode string from the h264 frame_packing_arrangement
- * @param h H.264 context.
- */
-const char* ff_h264_sei_stereo_mode(H264Context *h);
-
 /*
  * o-o o-o
  *  / / /
@@ -1041,7 +837,7 @@ static av_always_inline uint16_t pack8to16(unsigned a, unsigned b)
  */
 static av_always_inline int get_chroma_qp(const H264Context *h, int t, int qscale)
 {
-    return h->pps.chroma_qp_table[t][qscale];
+    return h->ps.pps->chroma_qp_table[t][qscale];
 }
 
 /**
@@ -1164,7 +960,7 @@ static av_always_inline void write_back_motion(const H264Context *h,
 
 static av_always_inline int get_dct8x8_allowed(const H264Context *h, H264SliceContext *sl)
 {
-    if (h->sps.direct_8x8_inference_flag)
+    if (h->ps.sps->direct_8x8_inference_flag)
         return !(AV_RN64A(sl->sub_mb_type) &
                  ((MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_8x8) *
                   0x0001000100010001ULL));
@@ -1184,26 +980,6 @@ static inline int find_start_code(const uint8_t *buf, int buf_size,
     return FFMIN(buf_index, buf_size);
 }
 
-static inline int get_avc_nalsize(H264Context *h, const uint8_t *buf,
-                           int buf_size, int *buf_index)
-{
-    int i, nalsize = 0;
-
-    if (*buf_index >= buf_size - h->nal_length_size) {
-        // the end of the buffer is reached, refill it.
-        return AVERROR(EAGAIN);
-    }
-
-    for (i = 0; i < h->nal_length_size; i++)
-        nalsize = ((unsigned)nalsize << 8) | buf[(*buf_index)++];
-    if (nalsize <= 0 || nalsize > buf_size - *buf_index) {
-        av_log(h->avctx, AV_LOG_ERROR,
-               "AVC: nal size %d\n", nalsize);
-        return AVERROR_INVALIDDATA;
-    }
-    return nalsize;
-}
-
 int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup);
 
 int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src);
@@ -1212,9 +988,6 @@ void ff_h264_unref_picture(H264Context *h, H264Picture *pic);
 int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl);
 
 void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl, int y, int height);
-int ff_init_poc(H264Context *h, int pic_field_poc[2], int *pic_poc);
-int ff_pred_weight_table(H264Context *h, H264SliceContext *sl);
-int ff_set_ref_count(H264Context *h, H264SliceContext *sl);
 
 int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl);
 #define SLICE_SINGLETHREAD 1
diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c
new file mode 100644
index 0000000..9979b63
--- /dev/null
+++ b/libavcodec/h2645_parse.c
@@ -0,0 +1,376 @@
+/*
+ * H.264/HEVC common parsing code
+ *
+ * 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 <string.h>
+
+#include "config.h"
+
+#include "libavutil/intmath.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
+
+#include "hevc.h"
+#include "h2645_parse.h"
+
+int ff_h2645_extract_rbsp(const uint8_t *src, int length,
+                          H2645NAL *nal)
+{
+    int i, si, di;
+    uint8_t *dst;
+
+    nal->skipped_bytes = 0;
+#define STARTCODE_TEST                                                  \
+        if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) {     \
+            if (src[i + 2] != 3 && src[i + 2] != 0) {                   \
+                /* startcode, so we must be past the end */             \
+                length = i;                                             \
+            }                                                           \
+            break;                                                      \
+        }
+#if HAVE_FAST_UNALIGNED
+#define FIND_FIRST_ZERO                                                 \
+        if (i > 0 && !src[i])                                           \
+            i--;                                                        \
+        while (src[i])                                                  \
+            i++
+#if HAVE_FAST_64BIT
+    for (i = 0; i + 1 < length; i += 9) {
+        if (!((~AV_RN64A(src + i) &
+               (AV_RN64A(src + i) - 0x0100010001000101ULL)) &
+              0x8000800080008080ULL))
+            continue;
+        FIND_FIRST_ZERO;
+        STARTCODE_TEST;
+        i -= 7;
+    }
+#else
+    for (i = 0; i + 1 < length; i += 5) {
+        if (!((~AV_RN32A(src + i) &
+               (AV_RN32A(src + i) - 0x01000101U)) &
+              0x80008080U))
+            continue;
+        FIND_FIRST_ZERO;
+        STARTCODE_TEST;
+        i -= 3;
+    }
+#endif /* HAVE_FAST_64BIT */
+#else
+    for (i = 0; i + 1 < length; i += 2) {
+        if (src[i])
+            continue;
+        if (i > 0 && src[i - 1] == 0)
+            i--;
+        STARTCODE_TEST;
+    }
+#endif /* HAVE_FAST_UNALIGNED */
+
+    if (i >= length - 1) { // no escaped 0
+        nal->data     =
+        nal->raw_data = src;
+        nal->size     =
+        nal->raw_size = length;
+        return length;
+    }
+
+    av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size,
+                   length + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!nal->rbsp_buffer)
+        return AVERROR(ENOMEM);
+
+    dst = nal->rbsp_buffer;
+
+    memcpy(dst, src, i);
+    si = di = i;
+    while (si + 2 < length) {
+        // remove escapes (very rare 1:2^22)
+        if (src[si + 2] > 3) {
+            dst[di++] = src[si++];
+            dst[di++] = src[si++];
+        } else if (src[si] == 0 && src[si + 1] == 0 && src[si + 2] != 0) {
+            if (src[si + 2] == 3) { // escape
+                dst[di++] = 0;
+                dst[di++] = 0;
+                si       += 3;
+
+                if (nal->skipped_bytes_pos) {
+                    nal->skipped_bytes++;
+                    if (nal->skipped_bytes_pos_size < nal->skipped_bytes) {
+                        nal->skipped_bytes_pos_size *= 2;
+                        av_assert0(nal->skipped_bytes_pos_size >= nal->skipped_bytes);
+                        av_reallocp_array(&nal->skipped_bytes_pos,
+                                nal->skipped_bytes_pos_size,
+                                sizeof(*nal->skipped_bytes_pos));
+                        if (!nal->skipped_bytes_pos) {
+                            nal->skipped_bytes_pos_size = 0;
+                            return AVERROR(ENOMEM);
+                        }
+                    }
+                    if (nal->skipped_bytes_pos)
+                        nal->skipped_bytes_pos[nal->skipped_bytes-1] = di - 1;
+                }
+                continue;
+            } else // next start code
+                goto nsc;
+        }
+
+        dst[di++] = src[si++];
+    }
+    while (si < length)
+        dst[di++] = src[si++];
+
+nsc:
+    memset(dst + di, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+
+    nal->data = dst;
+    nal->size = di;
+    nal->raw_data = src;
+    nal->raw_size = si;
+    return si;
+}
+
+static const char *nal_unit_name(int nal_type)
+{
+    switch(nal_type) {
+    case NAL_TRAIL_N    : return "TRAIL_N";
+    case NAL_TRAIL_R    : return "TRAIL_R";
+    case NAL_TSA_N      : return "TSA_N";
+    case NAL_TSA_R      : return "TSA_R";
+    case NAL_STSA_N     : return "STSA_N";
+    case NAL_STSA_R     : return "STSA_R";
+    case NAL_RADL_N     : return "RADL_N";
+    case NAL_RADL_R     : return "RADL_R";
+    case NAL_RASL_N     : return "RASL_N";
+    case NAL_RASL_R     : return "RASL_R";
+    case NAL_BLA_W_LP   : return "BLA_W_LP";
+    case NAL_BLA_W_RADL : return "BLA_W_RADL";
+    case NAL_BLA_N_LP   : return "BLA_N_LP";
+    case NAL_IDR_W_RADL : return "IDR_W_RADL";
+    case NAL_IDR_N_LP   : return "IDR_N_LP";
+    case NAL_CRA_NUT    : return "CRA_NUT";
+    case NAL_VPS        : return "VPS";
+    case NAL_SPS        : return "SPS";
+    case NAL_PPS        : return "PPS";
+    case NAL_AUD        : return "AUD";
+    case NAL_EOS_NUT    : return "EOS_NUT";
+    case NAL_EOB_NUT    : return "EOB_NUT";
+    case NAL_FD_NUT     : return "FD_NUT";
+    case NAL_SEI_PREFIX : return "SEI_PREFIX";
+    case NAL_SEI_SUFFIX : return "SEI_SUFFIX";
+    default : return "?";
+    }
+}
+
+static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros)
+{
+    int size = nal->size;
+    int v;
+
+    while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0)
+        size--;
+
+    if (!size)
+        return 0;
+
+    v = nal->data[size - 1];
+
+    if (size > INT_MAX / 8)
+        return AVERROR(ERANGE);
+    size *= 8;
+
+    /* remove the stop bit and following trailing zeros,
+     * or nothing for damaged bitstreams */
+    if (v)
+        size -= ff_ctz(v) + 1;
+
+    return size;
+}
+
+/**
+ * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit,
+ * 0 if the unit should be skipped, 1 otherwise
+ */
+static int hevc_parse_nal_header(H2645NAL *nal, void *logctx)
+{
+    GetBitContext *gb = &nal->gb;
+    int nuh_layer_id;
+
+    if (get_bits1(gb) != 0)
+        return AVERROR_INVALIDDATA;
+
+    nal->type = get_bits(gb, 6);
+
+    nuh_layer_id   = get_bits(gb, 6);
+    nal->temporal_id = get_bits(gb, 3) - 1;
+    if (nal->temporal_id < 0)
+        return AVERROR_INVALIDDATA;
+
+    av_log(logctx, AV_LOG_DEBUG,
+           "nal_unit_type: %d(%s), nuh_layer_id: %d, temporal_id: %d\n",
+           nal->type, nal_unit_name(nal->type), nuh_layer_id, nal->temporal_id);
+
+    return nuh_layer_id == 0;
+}
+
+static int h264_parse_nal_header(H2645NAL *nal, void *logctx)
+{
+    GetBitContext *gb = &nal->gb;
+
+    if (get_bits1(gb) != 0)
+        return AVERROR_INVALIDDATA;
+
+    nal->ref_idc = get_bits(gb, 2);
+    nal->type    = get_bits(gb, 5);
+
+    av_log(logctx, AV_LOG_DEBUG,
+           "nal_unit_type: %d, nal_ref_idc: %d\n",
+           nal->type, nal->ref_idc);
+
+    return 1;
+}
+
+int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
+                          void *logctx, int is_nalff, int nal_length_size,
+                          enum AVCodecID codec_id)
+{
+    int consumed, ret = 0;
+    const uint8_t *next_avc = is_nalff ? buf : buf + length;
+
+    pkt->nb_nals = 0;
+    while (length >= 4) {
+        H2645NAL *nal;
+        int extract_length = 0;
+        int skip_trailing_zeros = 1;
+
+        if (buf >= next_avc) {
+            int i;
+            for (i = 0; i < nal_length_size; i++)
+                extract_length = (extract_length << 8) | buf[i];
+            buf    += nal_length_size;
+            length -= nal_length_size;
+
+            if (extract_length > length) {
+                av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit size.\n");
+                return AVERROR_INVALIDDATA;
+            }
+            next_avc = buf + extract_length;
+        } else {
+            /* search start code */
+            while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) {
+                ++buf;
+                --length;
+                if (length < 4) {
+                    if (pkt->nb_nals > 0) {
+                        // No more start codes: we discarded some irrelevant
+                        // bytes at the end of the packet.
+                        return 0;
+                    } else {
+                        av_log(logctx, AV_LOG_ERROR, "No start code is found.\n");
+                        return AVERROR_INVALIDDATA;
+                    }
+                } else if (buf >= (next_avc - 3))
+                    break;
+            }
+
+            buf           += 3;
+            length        -= 3;
+            extract_length = length;
+
+            if (buf >= next_avc) {
+                /* skip to the start of the next NAL */
+                int offset = next_avc - buf;
+                buf    += offset;
+                length -= offset;
+                continue;
+            }
+        }
+
+        if (pkt->nals_allocated < pkt->nb_nals + 1) {
+            int new_size = pkt->nals_allocated + 1;
+            void *tmp = av_realloc_array(pkt->nals, new_size, sizeof(*pkt->nals));
+
+            if (!tmp)
+                return AVERROR(ENOMEM);
+
+            pkt->nals = tmp;
+            memset(pkt->nals + pkt->nals_allocated, 0,
+                   (new_size - pkt->nals_allocated) * sizeof(*pkt->nals));
+
+            nal = &pkt->nals[pkt->nb_nals];
+            nal->skipped_bytes_pos_size = 1024; // initial buffer size
+            nal->skipped_bytes_pos = av_malloc_array(nal->skipped_bytes_pos_size, sizeof(*nal->skipped_bytes_pos));
+            if (!nal->skipped_bytes_pos)
+                return AVERROR(ENOMEM);
+
+            pkt->nals_allocated = new_size;
+        }
+        nal = &pkt->nals[pkt->nb_nals];
+
+        consumed = ff_h2645_extract_rbsp(buf, extract_length, nal);
+        if (consumed < 0)
+            return consumed;
+
+        if (is_nalff && (extract_length != consumed) && extract_length)
+            av_log(logctx, AV_LOG_DEBUG,
+                   "NALFF: Consumed only %d bytes instead of %d\n",
+                   consumed, extract_length);
+
+        pkt->nb_nals++;
+
+        /* see commit 3566042a0 */
+        if (consumed < length - 3 &&
+            buf[consumed]     == 0x00 && buf[consumed + 1] == 0x00 &&
+            buf[consumed + 2] == 0x01 && buf[consumed + 3] == 0xE0)
+            skip_trailing_zeros = 0;
+
+        nal->size_bits = get_bit_length(nal, skip_trailing_zeros);
+
+        ret = init_get_bits(&nal->gb, nal->data, nal->size_bits);
+        if (ret < 0)
+            return ret;
+
+        if (codec_id == AV_CODEC_ID_HEVC)
+            ret = hevc_parse_nal_header(nal, logctx);
+        else
+            ret = h264_parse_nal_header(nal, logctx);
+        if (ret <= 0 || nal->size <= 0) {
+            if (ret < 0) {
+                av_log(logctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n",
+                       nal->type);
+            }
+            pkt->nb_nals--;
+        }
+
+        buf    += consumed;
+        length -= consumed;
+    }
+
+    return 0;
+}
+
+void ff_h2645_packet_uninit(H2645Packet *pkt)
+{
+    int i;
+    for (i = 0; i < pkt->nals_allocated; i++) {
+        av_freep(&pkt->nals[i].rbsp_buffer);
+        av_freep(&pkt->nals[i].skipped_bytes_pos);
+    }
+    av_freep(&pkt->nals);
+    pkt->nals_allocated = 0;
+}
diff --git a/libavcodec/h2645_parse.h b/libavcodec/h2645_parse.h
new file mode 100644
index 0000000..a3c7e1f
--- /dev/null
+++ b/libavcodec/h2645_parse.h
@@ -0,0 +1,91 @@
+/*
+ * H.264/HEVC common parsing code
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_H2645_PARSE_H
+#define AVCODEC_H2645_PARSE_H
+
+#include <stdint.h>
+
+#include "avcodec.h"
+#include "get_bits.h"
+
+typedef struct H2645NAL {
+    uint8_t *rbsp_buffer;
+    int rbsp_buffer_size;
+
+    int size;
+    const uint8_t *data;
+
+    /**
+     * Size, in bits, of just the data, excluding the stop bit and any trailing
+     * padding. I.e. what HEVC calls SODB.
+     */
+    int size_bits;
+
+    int raw_size;
+    const uint8_t *raw_data;
+
+    GetBitContext gb;
+
+    /**
+     * NAL unit type
+     */
+    int type;
+
+    /**
+     * HEVC only, nuh_temporal_id_plus_1 - 1
+     */
+    int temporal_id;
+
+    int skipped_bytes;
+    int skipped_bytes_pos_size;
+    int *skipped_bytes_pos;
+    /**
+     * H.264 only, nal_ref_idc
+     */
+    int ref_idc;
+} H2645NAL;
+
+/* an input packet split into unescaped NAL units */
+typedef struct H2645Packet {
+    H2645NAL *nals;
+    int nb_nals;
+    int nals_allocated;
+} H2645Packet;
+
+/**
+ * Extract the raw (unescaped) bitstream.
+ */
+int ff_h2645_extract_rbsp(const uint8_t *src, int length,
+                          H2645NAL *nal);
+
+/**
+ * Split an input packet into NAL units.
+ */
+int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
+                          void *logctx, int is_nalff, int nal_length_size,
+                          enum AVCodecID codec_id);
+
+/**
+ * Free all the allocated memory in the packet.
+ */
+void ff_h2645_packet_uninit(H2645Packet *pkt);
+
+#endif /* AVCODEC_H2645_PARSE_H */
diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c
index deab35a..68d7282 100644
--- a/libavcodec/h264_cabac.c
+++ b/libavcodec/h264_cabac.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 cabac decoding.
+ * H.264 / AVC / MPEG-4 part10 cabac decoding.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -56,7 +56,7 @@ static const int8_t cabac_context_init_I[1024][2] =
     {  2,  54 }, {  3, 74 },  { -28,127 }, { -23, 104 },
     { -6,  53 }, { -1, 54 },  {  7,  51 },
 
-    /* 11 - 23 unsused for I */
+    /* 11 - 23 unused for I */
     { 0, 0 },    { 0, 0 },    { 0, 0 },      { 0, 0 },
     { 0, 0 },    { 0, 0 },    { 0, 0 },      { 0, 0 },
     { 0, 0 },    { 0, 0 },    { 0, 0 },      { 0, 0 },
@@ -1265,7 +1265,7 @@ void ff_h264_init_cabac_states(const H264Context *h, H264SliceContext *sl)
 {
     int i;
     const int8_t (*tab)[2];
-    const int slice_qp = av_clip(sl->qscale - 6*(h->sps.bit_depth_luma-8), 0, 51);
+    const int slice_qp = av_clip(sl->qscale - 6*(h->ps.sps->bit_depth_luma-8), 0, 51);
 
     if (sl->slice_type_nos == AV_PICTURE_TYPE_I) tab = cabac_context_init_I;
     else                                 tab = cabac_context_init_PB[sl->cabac_init_idc];
@@ -1876,7 +1876,7 @@ static av_always_inline void decode_cabac_luma_residual(const H264Context *h, H2
         decode_cabac_residual_dc(h, sl, sl->mb_luma_dc[p], ctx_cat[0][p], LUMA_DC_BLOCK_INDEX+p, scan, 16);
 
         if( cbp&15 ) {
-            qmul = h->dequant4_coeff[p][qscale];
+            qmul = h->ps.pps->dequant4_coeff[p][qscale];
             for( i4x4 = 0; i4x4 < 16; i4x4++ ) {
                 const int index = 16*p + i4x4;
                 decode_cabac_residual_nondc(h, sl, sl->mb + (16*index << pixel_shift), ctx_cat[1][p], index, scan + 1, qmul, 15);
@@ -1891,9 +1891,9 @@ static av_always_inline void decode_cabac_luma_residual(const H264Context *h, H2
                 if( IS_8x8DCT(mb_type) ) {
                     const int index = 16*p + 4*i8x8;
                     decode_cabac_residual_nondc(h, sl, sl->mb + (16*index << pixel_shift), ctx_cat[3][p], index,
-                                                scan8x8, h->dequant8_coeff[cqm][qscale], 64);
+                                                scan8x8, h->ps.pps->dequant8_coeff[cqm][qscale], 64);
                 } else {
-                    qmul = h->dequant4_coeff[cqm][qscale];
+                    qmul = h->ps.pps->dequant4_coeff[cqm][qscale];
                     for( i4x4 = 0; i4x4 < 4; i4x4++ ) {
                         const int index = 16*p + 4*i8x8 + i4x4;
 //START_TIMER
@@ -1914,15 +1914,16 @@ static av_always_inline void decode_cabac_luma_residual(const H264Context *h, H2
  */
 int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl)
 {
+    const SPS *sps = h->ps.sps;
     int mb_xy;
     int mb_type, partition_count, cbp = 0;
-    int dct8x8_allowed= h->pps.transform_8x8_mode;
-    int decode_chroma = h->sps.chroma_format_idc == 1 || h->sps.chroma_format_idc == 2;
+    int dct8x8_allowed= h->ps.pps->transform_8x8_mode;
+    int decode_chroma = sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2;
     const int pixel_shift = h->pixel_shift;
 
     mb_xy = sl->mb_xy = sl->mb_x + sl->mb_y*h->mb_stride;
 
-    ff_tlog(h->avctx, "pic:%d mb:%d/%d\n", h->frame_num, sl->mb_x, sl->mb_y);
+    ff_tlog(h->avctx, "pic:%d mb:%d/%d\n", h->poc.frame_num, sl->mb_x, sl->mb_y);
     if (sl->slice_type_nos != AV_PICTURE_TYPE_I) {
         int skip;
         /* a skipped mb needs the aff flag from the following mb */
@@ -1992,8 +1993,8 @@ int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl)
                 mb_type= bits - 4; /* B_L0_Bi_* through B_Bi_Bi_* */
             }
         }
-            partition_count= b_mb_type_info[mb_type].partition_count;
-            mb_type=         b_mb_type_info[mb_type].type;
+            partition_count = ff_h264_b_mb_type_info[mb_type].partition_count;
+            mb_type         = ff_h264_b_mb_type_info[mb_type].type;
     } else if (sl->slice_type_nos == AV_PICTURE_TYPE_P) {
         if( get_cabac_noinline( &sl->cabac, &sl->cabac_state[14] ) == 0 ) {
             /* P-type */
@@ -2004,8 +2005,8 @@ int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl)
                 /* P_L0_D8x16, P_L0_D16x8 */
                 mb_type= 2 - get_cabac_noinline( &sl->cabac, &sl->cabac_state[17] );
             }
-            partition_count= p_mb_type_info[mb_type].partition_count;
-            mb_type=         p_mb_type_info[mb_type].type;
+            partition_count = ff_h264_p_mb_type_info[mb_type].partition_count;
+            mb_type         = ff_h264_p_mb_type_info[mb_type].type;
         } else {
             mb_type = decode_cabac_intra_mb_type(sl, 17, 0);
             goto decode_intra_mb;
@@ -2017,9 +2018,9 @@ int ff_h264_decode_mb_cabac(const H264Context *h, H264SliceContext *sl)
         av_assert2(sl->slice_type_nos == AV_PICTURE_TYPE_I);
 decode_intra_mb:
         partition_count = 0;
-        cbp= i_mb_type_info[mb_type].cbp;
-        sl->intra16x16_pred_mode = i_mb_type_info[mb_type].pred_mode;
-        mb_type= i_mb_type_info[mb_type].type;
+        cbp                      = ff_h264_i_mb_type_info[mb_type].cbp;
+        sl->intra16x16_pred_mode = ff_h264_i_mb_type_info[mb_type].pred_mode;
+        mb_type                  = ff_h264_i_mb_type_info[mb_type].type;
     }
     if (MB_FIELD(sl))
         mb_type |= MB_TYPE_INTERLACED;
@@ -2027,8 +2028,8 @@ decode_intra_mb:
     h->slice_table[mb_xy] = sl->slice_num;
 
     if(IS_INTRA_PCM(mb_type)) {
-        const int mb_size = ff_h264_mb_sizes[h->sps.chroma_format_idc] *
-                            h->sps.bit_depth_luma >> 3;
+        const int mb_size = ff_h264_mb_sizes[sps->chroma_format_idc] *
+                            sps->bit_depth_luma >> 3;
         const uint8_t *ptr;
         int ret;
 
@@ -2085,16 +2086,20 @@ decode_intra_mb:
                 }
             }
             write_back_intra_pred_mode(h, sl);
-            if (ff_h264_check_intra4x4_pred_mode(h, sl) < 0 ) return -1;
+            if (ff_h264_check_intra4x4_pred_mode(sl->intra4x4_pred_mode_cache, h->avctx,
+                                                 sl->top_samples_available, sl->left_samples_available) < 0 )
+                return -1;
         } else {
-            sl->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h, sl, sl->intra16x16_pred_mode, 0);
+            sl->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h->avctx, sl->top_samples_available,
+                                                                     sl->left_samples_available, sl->intra16x16_pred_mode, 0);
             if (sl->intra16x16_pred_mode < 0) return -1;
         }
         if(decode_chroma){
             h->chroma_pred_mode_table[mb_xy] =
             pred_mode                        = decode_cabac_mb_chroma_pre_mode(h, sl);
 
-            pred_mode= ff_h264_check_intra_pred_mode(h, sl, pred_mode, 1 );
+            pred_mode= ff_h264_check_intra_pred_mode(h->avctx, sl->top_samples_available,
+                                                     sl->left_samples_available, pred_mode, 1 );
             if( pred_mode < 0 ) return -1;
             sl->chroma_pred_mode = pred_mode;
         } else {
@@ -2106,8 +2111,8 @@ decode_intra_mb:
         if (sl->slice_type_nos == AV_PICTURE_TYPE_B ) {
             for( i = 0; i < 4; i++ ) {
                 sl->sub_mb_type[i] = decode_cabac_b_mb_sub_type(sl);
-                sub_partition_count[i] = b_sub_mb_type_info[sl->sub_mb_type[i]].partition_count;
-                sl->sub_mb_type[i]     = b_sub_mb_type_info[sl->sub_mb_type[i]].type;
+                sub_partition_count[i] = ff_h264_b_sub_mb_type_info[sl->sub_mb_type[i]].partition_count;
+                sl->sub_mb_type[i]     = ff_h264_b_sub_mb_type_info[sl->sub_mb_type[i]].type;
             }
             if (IS_DIRECT(sl->sub_mb_type[0] | sl->sub_mb_type[1] |
                           sl->sub_mb_type[2] | sl->sub_mb_type[3])) {
@@ -2122,8 +2127,8 @@ decode_intra_mb:
         } else {
             for( i = 0; i < 4; i++ ) {
                 sl->sub_mb_type[i] = decode_cabac_p_mb_sub_type(sl);
-                sub_partition_count[i] = p_sub_mb_type_info[sl->sub_mb_type[i]].partition_count;
-                sl->sub_mb_type[i]     = p_sub_mb_type_info[sl->sub_mb_type[i]].type;
+                sub_partition_count[i] = ff_h264_p_sub_mb_type_info[sl->sub_mb_type[i]].partition_count;
+                sl->sub_mb_type[i]     = ff_h264_p_sub_mb_type_info[sl->sub_mb_type[i]].type;
             }
         }
 
@@ -2211,7 +2216,7 @@ decode_intra_mb:
         ff_h264_pred_direct_motion(h, sl, &mb_type);
         fill_rectangle(sl->mvd_cache[0][scan8[0]], 4, 4, 8, 0, 2);
         fill_rectangle(sl->mvd_cache[1][scan8[0]], 4, 4, 8, 0, 2);
-        dct8x8_allowed &= h->sps.direct_8x8_inference_flag;
+        dct8x8_allowed &= sps->direct_8x8_inference_flag;
     } else {
         int list, i;
         if(IS_16X16(mb_type)){
@@ -2378,7 +2383,7 @@ decode_intra_mb:
         if(get_cabac_noinline( &sl->cabac, &sl->cabac_state[60 + (sl->last_qscale_diff != 0)])){
             int val = 1;
             int ctx= 2;
-            const int max_qp = 51 + 6*(h->sps.bit_depth_luma-8);
+            const int max_qp = 51 + 6*(sps->bit_depth_luma-8);
 
             while( get_cabac_noinline( &sl->cabac, &sl->cabac_state[60 + ctx] ) ) {
                 ctx= 3;
@@ -2414,14 +2419,14 @@ decode_intra_mb:
                 for (c = 0; c < 2; c++)
                     decode_cabac_residual_dc_422(h, sl, sl->mb + ((256 + 16*16*c) << pixel_shift), 3,
                                                  CHROMA_DC_BLOCK_INDEX + c,
-                                                 chroma422_dc_scan, 8);
+                                                 ff_h264_chroma422_dc_scan, 8);
             }
 
             if( cbp&0x20 ) {
                 int c, i, i8x8;
                 for( c = 0; c < 2; c++ ) {
                     int16_t *mb = sl->mb + (16*(16 + 16*c) << pixel_shift);
-                    qmul = h->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[c]];
+                    qmul = h->ps.pps->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[c]];
                     for (i8x8 = 0; i8x8 < 2; i8x8++) {
                         for (i = 0; i < 4; i++) {
                             const int index = 16 + 16 * c + 8*i8x8 + i;
@@ -2438,13 +2443,14 @@ decode_intra_mb:
             if( cbp&0x30 ){
                 int c;
                 for (c = 0; c < 2; c++)
-                    decode_cabac_residual_dc(h, sl, sl->mb + ((256 + 16*16*c) << pixel_shift), 3, CHROMA_DC_BLOCK_INDEX+c, chroma_dc_scan, 4);
+                    decode_cabac_residual_dc(h, sl, sl->mb + ((256 + 16 * 16 * c) << pixel_shift),
+                                             3, CHROMA_DC_BLOCK_INDEX + c, ff_h264_chroma_dc_scan, 4);
             }
 
             if( cbp&0x20 ) {
                 int c, i;
                 for( c = 0; c < 2; c++ ) {
-                    qmul = h->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[c]];
+                    qmul = h->ps.pps->dequant4_coeff[c+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[c]];
                     for( i = 0; i < 4; i++ ) {
                         const int index = 16 + 16 * c + i;
                         decode_cabac_residual_nondc(h, sl, sl->mb + (16*index << pixel_shift), 4, index, scan + 1, qmul, 15);
diff --git a/libavcodec/h264_cavlc.c b/libavcodec/h264_cavlc.c
index b0251f4..3293c66 100644
--- a/libavcodec/h264_cavlc.c
+++ b/libavcodec/h264_cavlc.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 cavlc bitstream decoding.
+ * H.264 / AVC / MPEG-4 part10 cavlc bitstream decoding.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -31,8 +31,8 @@
 #include "internal.h"
 #include "avcodec.h"
 #include "h264.h"
-#include "h264data.h" // FIXME FIXME FIXME
 #include "h264_mvpred.h"
+#include "h264data.h"
 #include "golomb.h"
 #include "mpegutils.h"
 #include "libavutil/avassert.h"
@@ -413,9 +413,6 @@ av_cold void ff_h264_decode_init_vlc(void){
     }
 }
 
-/**
- *
- */
 static inline int get_level_prefix(GetBitContext *gb){
     unsigned int buf;
     int log;
@@ -425,10 +422,6 @@ static inline int get_level_prefix(GetBitContext *gb){
     buf=GET_CACHE(re, gb);
 
     log= 32 - av_log2(buf);
-#ifdef TRACE
-    print_bin(buf>>(32-log), log);
-    av_log(NULL, AV_LOG_DEBUG, "%5d %2d %3d lpr @%5d in %s get_level_prefix\n", buf>>(32-log), log, log-1, get_bits_count(gb), __FILE__);
-#endif
 
     LAST_SKIP_BITS(re, gb, log);
     CLOSE_READER(re, gb);
@@ -659,7 +652,7 @@ int decode_luma_residual(const H264Context *h, H264SliceContext *sl,
                 for(i4x4=0; i4x4<4; i4x4++){
                     const int index= i4x4 + 4*i8x8 + p*16;
                     if( decode_residual(h, sl, gb, sl->mb + (16*index << pixel_shift),
-                        index, scan + 1, h->dequant4_coeff[p][qscale], 15) < 0 ){
+                        index, scan + 1, h->ps.pps->dequant4_coeff[p][qscale], 15) < 0 ){
                         return -1;
                     }
                 }
@@ -681,7 +674,7 @@ int decode_luma_residual(const H264Context *h, H264SliceContext *sl,
                     for(i4x4=0; i4x4<4; i4x4++){
                         const int index= i4x4 + 4*i8x8 + p*16;
                         if( decode_residual(h, sl, gb, buf, index, scan8x8+16*i4x4,
-                                            h->dequant8_coeff[cqm][qscale], 16) < 0 )
+                                            h->ps.pps->dequant8_coeff[cqm][qscale], 16) < 0 )
                             return -1;
                     }
                     nnz = &sl->non_zero_count_cache[scan8[4 * i8x8 + p * 16]];
@@ -691,7 +684,7 @@ int decode_luma_residual(const H264Context *h, H264SliceContext *sl,
                     for(i4x4=0; i4x4<4; i4x4++){
                         const int index= i4x4 + 4*i8x8 + p*16;
                         if( decode_residual(h, sl, gb, sl->mb + (16*index << pixel_shift), index,
-                                            scan, h->dequant4_coeff[cqm][qscale], 16) < 0 ){
+                                            scan, h->ps.pps->dequant4_coeff[cqm][qscale], 16) < 0 ){
                             return -1;
                         }
                         new_cbp |= sl->non_zero_count_cache[scan8[index]] << i8x8;
@@ -711,13 +704,13 @@ int ff_h264_decode_mb_cavlc(const H264Context *h, H264SliceContext *sl)
     int mb_xy;
     int partition_count;
     unsigned int mb_type, cbp;
-    int dct8x8_allowed= h->pps.transform_8x8_mode;
-    int decode_chroma = h->sps.chroma_format_idc == 1 || h->sps.chroma_format_idc == 2;
+    int dct8x8_allowed= h->ps.pps->transform_8x8_mode;
+    int decode_chroma = h->ps.sps->chroma_format_idc == 1 || h->ps.sps->chroma_format_idc == 2;
     const int pixel_shift = h->pixel_shift;
 
     mb_xy = sl->mb_xy = sl->mb_x + sl->mb_y*h->mb_stride;
 
-    ff_tlog(h->avctx, "pic:%d mb:%d/%d\n", h->frame_num, sl->mb_x, sl->mb_y);
+    ff_tlog(h->avctx, "pic:%d mb:%d/%d\n", h->poc.frame_num, sl->mb_x, sl->mb_y);
     cbp = 0; /* avoid warning. FIXME: find a solution without slowing
                 down the code */
     if (sl->slice_type_nos != AV_PICTURE_TYPE_I) {
@@ -743,16 +736,16 @@ int ff_h264_decode_mb_cavlc(const H264Context *h, H264SliceContext *sl)
     mb_type= get_ue_golomb(&sl->gb);
     if (sl->slice_type_nos == AV_PICTURE_TYPE_B) {
         if(mb_type < 23){
-            partition_count= b_mb_type_info[mb_type].partition_count;
-            mb_type=         b_mb_type_info[mb_type].type;
+            partition_count = ff_h264_b_mb_type_info[mb_type].partition_count;
+            mb_type         = ff_h264_b_mb_type_info[mb_type].type;
         }else{
             mb_type -= 23;
             goto decode_intra_mb;
         }
     } else if (sl->slice_type_nos == AV_PICTURE_TYPE_P) {
         if(mb_type < 5){
-            partition_count= p_mb_type_info[mb_type].partition_count;
-            mb_type=         p_mb_type_info[mb_type].type;
+            partition_count = ff_h264_p_mb_type_info[mb_type].partition_count;
+            mb_type         = ff_h264_p_mb_type_info[mb_type].type;
         }else{
             mb_type -= 5;
             goto decode_intra_mb;
@@ -767,9 +760,9 @@ decode_intra_mb:
             return -1;
         }
         partition_count=0;
-        cbp= i_mb_type_info[mb_type].cbp;
-        sl->intra16x16_pred_mode = i_mb_type_info[mb_type].pred_mode;
-        mb_type= i_mb_type_info[mb_type].type;
+        cbp                      = ff_h264_i_mb_type_info[mb_type].cbp;
+        sl->intra16x16_pred_mode = ff_h264_i_mb_type_info[mb_type].pred_mode;
+        mb_type                  = ff_h264_i_mb_type_info[mb_type].type;
     }
 
     if (MB_FIELD(sl))
@@ -778,8 +771,8 @@ decode_intra_mb:
     h->slice_table[mb_xy] = sl->slice_num;
 
     if(IS_INTRA_PCM(mb_type)){
-        const int mb_size = ff_h264_mb_sizes[h->sps.chroma_format_idc] *
-                            h->sps.bit_depth_luma;
+        const int mb_size = ff_h264_mb_sizes[h->ps.sps->chroma_format_idc] *
+                            h->ps.sps->bit_depth_luma;
 
         // We assume these blocks are very rare so we do not optimize it.
         sl->intra_pcm_ptr = align_get_bits(&sl->gb);
@@ -828,15 +821,18 @@ decode_intra_mb:
                     sl->intra4x4_pred_mode_cache[scan8[i]] = mode;
             }
             write_back_intra_pred_mode(h, sl);
-            if (ff_h264_check_intra4x4_pred_mode(h, sl) < 0)
+            if (ff_h264_check_intra4x4_pred_mode(sl->intra4x4_pred_mode_cache, h->avctx,
+                                                 sl->top_samples_available, sl->left_samples_available) < 0)
                 return -1;
         }else{
-            sl->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h, sl, sl->intra16x16_pred_mode, 0);
+            sl->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h->avctx, sl->top_samples_available,
+                                                                     sl->left_samples_available, sl->intra16x16_pred_mode, 0);
             if (sl->intra16x16_pred_mode < 0)
                 return -1;
         }
         if(decode_chroma){
-            pred_mode= ff_h264_check_intra_pred_mode(h, sl, get_ue_golomb_31(&sl->gb), 1);
+            pred_mode= ff_h264_check_intra_pred_mode(h->avctx, sl->top_samples_available,
+                                                     sl->left_samples_available, get_ue_golomb_31(&sl->gb), 1);
             if(pred_mode < 0)
                 return -1;
             sl->chroma_pred_mode = pred_mode;
@@ -853,8 +849,8 @@ decode_intra_mb:
                     av_log(h->avctx, AV_LOG_ERROR, "B sub_mb_type %u out of range at %d %d\n", sl->sub_mb_type[i], sl->mb_x, sl->mb_y);
                     return -1;
                 }
-                sub_partition_count[i]= b_sub_mb_type_info[ sl->sub_mb_type[i] ].partition_count;
-                sl->sub_mb_type[i]=      b_sub_mb_type_info[ sl->sub_mb_type[i] ].type;
+                sub_partition_count[i] = ff_h264_b_sub_mb_type_info[sl->sub_mb_type[i]].partition_count;
+                sl->sub_mb_type[i]     = ff_h264_b_sub_mb_type_info[sl->sub_mb_type[i]].type;
             }
             if( IS_DIRECT(sl->sub_mb_type[0]|sl->sub_mb_type[1]|sl->sub_mb_type[2]|sl->sub_mb_type[3])) {
                 ff_h264_pred_direct_motion(h, sl, &mb_type);
@@ -871,8 +867,8 @@ decode_intra_mb:
                     av_log(h->avctx, AV_LOG_ERROR, "P sub_mb_type %u out of range at %d %d\n", sl->sub_mb_type[i], sl->mb_x, sl->mb_y);
                     return -1;
                 }
-                sub_partition_count[i]= p_sub_mb_type_info[ sl->sub_mb_type[i] ].partition_count;
-                sl->sub_mb_type[i]=      p_sub_mb_type_info[ sl->sub_mb_type[i] ].type;
+                sub_partition_count[i] = ff_h264_p_sub_mb_type_info[sl->sub_mb_type[i]].partition_count;
+                sl->sub_mb_type[i]     = ff_h264_p_sub_mb_type_info[sl->sub_mb_type[i]].type;
             }
         }
 
@@ -949,7 +945,7 @@ decode_intra_mb:
         }
     }else if(IS_DIRECT(mb_type)){
         ff_h264_pred_direct_motion(h, sl, &mb_type);
-        dct8x8_allowed &= h->sps.direct_8x8_inference_flag;
+        dct8x8_allowed &= h->ps.sps->direct_8x8_inference_flag;
     }else{
         int list, mx, my, i;
          //FIXME we should set ref_idx_l? to 0 if we use that later ...
@@ -1072,8 +1068,10 @@ decode_intra_mb:
                 av_log(h->avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, sl->mb_x, sl->mb_y);
                 return -1;
             }
-            if(IS_INTRA4x4(mb_type)) cbp= golomb_to_intra4x4_cbp[cbp];
-            else                     cbp= golomb_to_inter_cbp   [cbp];
+            if (IS_INTRA4x4(mb_type))
+                cbp = ff_h264_golomb_to_intra4x4_cbp[cbp];
+            else
+                cbp = ff_h264_golomb_to_inter_cbp[cbp];
         }else{
             if(cbp > 15){
                 av_log(h->avctx, AV_LOG_ERROR, "cbp too large (%u) at %d %d\n", cbp, sl->mb_x, sl->mb_y);
@@ -1102,7 +1100,7 @@ decode_intra_mb:
         int ret;
         GetBitContext *gb = &sl->gb;
         const uint8_t *scan, *scan8x8;
-        const int max_qp = 51 + 6*(h->sps.bit_depth_luma-8);
+        const int max_qp = 51 + 6 * (h->ps.sps->bit_depth_luma - 8);
 
         if(IS_INTERLACED(mb_type)){
             scan8x8 = sl->qscale ? h->field_scan8x8_cavlc : h->field_scan8x8_cavlc_q0;
@@ -1140,21 +1138,21 @@ decode_intra_mb:
                 return -1;
             }
         } else {
-            const int num_c8x8 = h->sps.chroma_format_idc;
+            const int num_c8x8 = h->ps.sps->chroma_format_idc;
 
             if(cbp&0x30){
                 for(chroma_idx=0; chroma_idx<2; chroma_idx++)
                     if (decode_residual(h, sl, gb, sl->mb + ((256 + 16*16*chroma_idx) << pixel_shift),
-                                        CHROMA_DC_BLOCK_INDEX+chroma_idx,
-                                        CHROMA422(h) ? chroma422_dc_scan : chroma_dc_scan,
-                                        NULL, 4*num_c8x8) < 0) {
+                                        CHROMA_DC_BLOCK_INDEX + chroma_idx,
+                                        CHROMA422(h) ? ff_h264_chroma422_dc_scan : ff_h264_chroma_dc_scan,
+                                        NULL, 4 * num_c8x8) < 0) {
                         return -1;
                     }
             }
 
             if(cbp&0x20){
                 for(chroma_idx=0; chroma_idx<2; chroma_idx++){
-                    const uint32_t *qmul = h->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[chroma_idx]];
+                    const uint32_t *qmul = h->ps.pps->dequant4_coeff[chroma_idx+1+(IS_INTRA( mb_type ) ? 0:3)][sl->chroma_qp[chroma_idx]];
                     int16_t *mb = sl->mb + (16*(16 + 16*chroma_idx) << pixel_shift);
                     for (i8x8 = 0; i8x8<num_c8x8; i8x8++) {
                         for (i4x4 = 0; i4x4 < 4; i4x4++) {
diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c
index 5f66a67..e137ff9 100644
--- a/libavcodec/h264_direct.c
+++ b/libavcodec/h264_direct.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 direct mb/block decoding.
+ * H.264 / AVC / MPEG-4 part10 direct mb/block decoding.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -315,7 +315,7 @@ single_col:
                 *mb_type |= MB_TYPE_DIRECT2 |
                             (mb_type_col[0] & (MB_TYPE_16x8 | MB_TYPE_8x16));
             } else {
-                if (!h->sps.direct_8x8_inference_flag) {
+                if (!h->ps.sps->direct_8x8_inference_flag) {
                     /* FIXME: Save sub mb types from previous frames (or derive
                      * from MVs) so we know exactly what block size to use. */
                     sub_mb_type += (MB_TYPE_8x8 - MB_TYPE_16x16); /* B_SUB_4x4 */
@@ -395,7 +395,7 @@ single_col:
              (l1ref0[0] < 0 && !l1ref1[0] &&
               FFABS(l1mv1[0][0]) <= 1 &&
               FFABS(l1mv1[0][1]) <= 1 &&
-              h->x264_build > 33U))) {
+              h->sei.unregistered.x264_build > 33U))) {
             a = b = 0;
             if (ref[0] > 0)
                 a = mv[0];
@@ -430,7 +430,7 @@ single_col:
                 (l1ref0[i8] == 0 ||
                  (l1ref0[i8] < 0 &&
                   l1ref1[i8] == 0 &&
-                  h->x264_build > 33U))) {
+                  h->sei.unregistered.x264_build > 33U))) {
                 const int16_t (*l1mv)[2] = l1ref0[i8] == 0 ? l1mv0 : l1mv1;
                 if (IS_SUB_8X8(sub_mb_type)) {
                     const int16_t *mv_col = l1mv[x8 * 3 + y8 * 3 * b4_stride];
@@ -538,7 +538,7 @@ single_col:
                 *mb_type |= MB_TYPE_L0L1 | MB_TYPE_DIRECT2 |
                             (mb_type_col[0] & (MB_TYPE_16x8 | MB_TYPE_8x16));
             } else {
-                if (!h->sps.direct_8x8_inference_flag) {
+                if (!h->ps.sps->direct_8x8_inference_flag) {
                     /* FIXME: save sub mb types from previous frames (or derive
                      * from MVs) so we know exactly what block size to use */
                     sub_mb_type = MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P0L1 |
@@ -579,7 +579,7 @@ single_col:
 
         if (IS_INTERLACED(*mb_type) != IS_INTERLACED(mb_type_col[0])) {
             int y_shift = 2 * !IS_INTERLACED(*mb_type);
-            assert(h->sps.direct_8x8_inference_flag);
+            assert(h->ps.sps->direct_8x8_inference_flag);
 
             for (i8 = 0; i8 < 4; i8++) {
                 const int x8 = i8 & 1;
diff --git a/libavcodec/h264_loopfilter.c b/libavcodec/h264_loopfilter.c
index 0014927..0ef0c12 100644
--- a/libavcodec/h264_loopfilter.c
+++ b/libavcodec/h264_loopfilter.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 loop filter.
+ * H.264 / AVC / MPEG-4 part10 loop filter.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -250,7 +250,7 @@ static av_always_inline void h264_filter_mb_fast_internal(const H264Context *h,
     int left_type = sl->left_type[LTOP];
     int top_type  = sl->top_type;
 
-    int qp_bd_offset = 6 * (h->sps.bit_depth_luma - 8);
+    int qp_bd_offset = 6 * (h->ps.sps->bit_depth_luma - 8);
     int a = 52 + sl->slice_alpha_c0_offset - qp_bd_offset;
     int b = 52 + sl->slice_beta_offset - qp_bd_offset;
 
@@ -420,7 +420,7 @@ void ff_h264_filter_mb_fast(const H264Context *h, H264SliceContext *sl,
                             unsigned int linesize, unsigned int uvlinesize)
 {
     av_assert2(!FRAME_MBAFF(h));
-    if(!h->h264dsp.h264_loop_filter_strength || h->pps.chroma_qp_diff) {
+    if(!h->h264dsp.h264_loop_filter_strength || h->ps.pps->chroma_qp_diff) {
         ff_h264_filter_mb(h, sl, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize);
         return;
     }
@@ -724,7 +724,7 @@ void ff_h264_filter_mb(const H264Context *h, H264SliceContext *sl,
     const int mvy_limit = IS_INTERLACED(mb_type) ? 2 : 4;
     int first_vertical_edge_done = 0;
     int chroma = CHROMA(h) && !(CONFIG_GRAY && (h->flags & AV_CODEC_FLAG_GRAY));
-    int qp_bd_offset = 6 * (h->sps.bit_depth_luma - 8);
+    int qp_bd_offset = 6 * (h->ps.sps->bit_depth_luma - 8);
     int a = 52 + sl->slice_alpha_c0_offset - qp_bd_offset;
     int b = 52 + sl->slice_beta_offset - qp_bd_offset;
 
@@ -767,7 +767,7 @@ void ff_h264_filter_mb(const H264Context *h, H264SliceContext *sl,
                     bS[i] = 4;
                 else{
                     bS[i] = 1 + !!(sl->non_zero_count_cache[12+8*(i>>1)] |
-                         ((!h->pps.cabac && IS_8x8DCT(mbn_type)) ?
+                         ((!h->ps.pps->cabac && IS_8x8DCT(mbn_type)) ?
                             (h->cbp_table[mbn_xy] & (((MB_FIELD(sl) ? (i&2) : (mb_y&1)) ? 8 : 2) << 12))
                                                                        :
                             h->non_zero_count[mbn_xy][ off[i] ]));
diff --git a/libavcodec/h264_mb.c b/libavcodec/h264_mb.c
index 8302de0..e33a59e 100644
--- a/libavcodec/h264_mb.c
+++ b/libavcodec/h264_mb.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 macroblock decoding
+ * H.264 / AVC / MPEG-4 part10 macroblock decoding
  */
 
 #include <stdint.h>
@@ -33,7 +33,6 @@
 #include "avcodec.h"
 #include "h264.h"
 #include "qpeldsp.h"
-#include "svq3.h"
 #include "thread.h"
 
 static inline int get_lowest_part_list_y(H264SliceContext *sl,
@@ -91,7 +90,7 @@ static inline void get_lowest_part_y(const H264Context *h, H264SliceContext *sl,
 /**
  * Wait until all reference frames are available for MC operations.
  *
- * @param h the H264 context
+ * @param h the H.264 context
  */
 static void await_references(const H264Context *h, H264SliceContext *sl)
 {
@@ -420,8 +419,8 @@ static av_always_inline void mc_part_weighted(const H264Context *h, H264SliceCon
                     x_offset, y_offset, qpix_put, chroma_put,
                     pixel_shift, chroma_idc);
 
-        if (sl->use_weight == 2) {
-            int weight0 = sl->implicit_weight[refn0][refn1][sl->mb_y & 1];
+        if (sl->pwt.use_weight == 2) {
+            int weight0 = sl->pwt.implicit_weight[refn0][refn1][sl->mb_y & 1];
             int weight1 = 64 - weight0;
             luma_weight_avg(dest_y, tmp_y, sl->mb_linesize,
                             height, 5, weight0, weight1, 0);
@@ -433,24 +432,24 @@ static av_always_inline void mc_part_weighted(const H264Context *h, H264SliceCon
             }
         } else {
             luma_weight_avg(dest_y, tmp_y, sl->mb_linesize, height,
-                            sl->luma_log2_weight_denom,
-                            sl->luma_weight[refn0][0][0],
-                            sl->luma_weight[refn1][1][0],
-                            sl->luma_weight[refn0][0][1] +
-                            sl->luma_weight[refn1][1][1]);
+                            sl->pwt.luma_log2_weight_denom,
+                            sl->pwt.luma_weight[refn0][0][0],
+                            sl->pwt.luma_weight[refn1][1][0],
+                            sl->pwt.luma_weight[refn0][0][1] +
+                            sl->pwt.luma_weight[refn1][1][1]);
             if (!CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) {
                 chroma_weight_avg(dest_cb, tmp_cb, sl->mb_uvlinesize, chroma_height,
-                                  sl->chroma_log2_weight_denom,
-                                  sl->chroma_weight[refn0][0][0][0],
-                                  sl->chroma_weight[refn1][1][0][0],
-                                  sl->chroma_weight[refn0][0][0][1] +
-                                  sl->chroma_weight[refn1][1][0][1]);
+                                  sl->pwt.chroma_log2_weight_denom,
+                                  sl->pwt.chroma_weight[refn0][0][0][0],
+                                  sl->pwt.chroma_weight[refn1][1][0][0],
+                                  sl->pwt.chroma_weight[refn0][0][0][1] +
+                                  sl->pwt.chroma_weight[refn1][1][0][1]);
                 chroma_weight_avg(dest_cr, tmp_cr, sl->mb_uvlinesize, chroma_height,
-                                  sl->chroma_log2_weight_denom,
-                                  sl->chroma_weight[refn0][0][1][0],
-                                  sl->chroma_weight[refn1][1][1][0],
-                                  sl->chroma_weight[refn0][0][1][1] +
-                                  sl->chroma_weight[refn1][1][1][1]);
+                                  sl->pwt.chroma_log2_weight_denom,
+                                  sl->pwt.chroma_weight[refn0][0][1][0],
+                                  sl->pwt.chroma_weight[refn1][1][1][0],
+                                  sl->pwt.chroma_weight[refn0][0][1][1] +
+                                  sl->pwt.chroma_weight[refn1][1][1][1]);
             }
         }
     } else {
@@ -462,19 +461,19 @@ static av_always_inline void mc_part_weighted(const H264Context *h, H264SliceCon
                     qpix_put, chroma_put, pixel_shift, chroma_idc);
 
         luma_weight_op(dest_y, sl->mb_linesize, height,
-                       sl->luma_log2_weight_denom,
-                       sl->luma_weight[refn][list][0],
-                       sl->luma_weight[refn][list][1]);
+                       sl->pwt.luma_log2_weight_denom,
+                       sl->pwt.luma_weight[refn][list][0],
+                       sl->pwt.luma_weight[refn][list][1]);
         if (!CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) {
-            if (sl->use_weight_chroma) {
+            if (sl->pwt.use_weight_chroma) {
                 chroma_weight_op(dest_cb, sl->mb_uvlinesize, chroma_height,
-                                 sl->chroma_log2_weight_denom,
-                                 sl->chroma_weight[refn][list][0][0],
-                                 sl->chroma_weight[refn][list][0][1]);
+                                 sl->pwt.chroma_log2_weight_denom,
+                                 sl->pwt.chroma_weight[refn][list][0][0],
+                                 sl->pwt.chroma_weight[refn][list][0][1]);
                 chroma_weight_op(dest_cr, sl->mb_uvlinesize, chroma_height,
-                                 sl->chroma_log2_weight_denom,
-                                 sl->chroma_weight[refn][list][1][0],
-                                 sl->chroma_weight[refn][list][1][1]);
+                                 sl->pwt.chroma_log2_weight_denom,
+                                 sl->pwt.chroma_weight[refn][list][1][0],
+                                 sl->pwt.chroma_weight[refn][list][1][1]);
             }
         }
     }
@@ -612,8 +611,7 @@ static av_always_inline void dctcoef_set(int16_t *mb, int high_bit_depth,
 
 static av_always_inline void hl_decode_mb_predict_luma(const H264Context *h,
                                                        H264SliceContext *sl,
-                                                       int mb_type, int is_h264,
-                                                       int simple,
+                                                       int mb_type, int simple,
                                                        int transform_bypass,
                                                        int pixel_shift,
                                                        const int *block_offset,
@@ -637,8 +635,8 @@ static av_always_inline void hl_decode_mb_predict_luma(const H264Context *h,
             for (i = 0; i < 16; i += 4) {
                 uint8_t *const ptr = dest_y + block_offset[i];
                 const int dir      = sl->intra4x4_pred_mode_cache[scan8[i]];
-                if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) {
-                    if (h->x264_build != -1) {
+                if (transform_bypass && h->ps.sps->profile_idc == 244 && dir <= 1) {
+                    if (h->sei.unregistered.x264_build != -1) {
                         h->hpc.pred8x8l_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize);
                     } else
                         h->hpc.pred8x8l_filter_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift),
@@ -668,7 +666,7 @@ static av_always_inline void hl_decode_mb_predict_luma(const H264Context *h,
                 uint8_t *const ptr = dest_y + block_offset[i];
                 const int dir      = sl->intra4x4_pred_mode_cache[scan8[i]];
 
-                if (transform_bypass && h->sps.profile_idc == 244 && dir <= 1) {
+                if (transform_bypass && h->ps.sps->profile_idc == 244 && dir <= 1) {
                     h->hpc.pred4x4_add[dir](ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize);
                 } else {
                     uint8_t *topright;
@@ -693,48 +691,40 @@ static av_always_inline void hl_decode_mb_predict_luma(const H264Context *h,
                     h->hpc.pred4x4[dir](ptr, topright, linesize);
                     nnz = sl->non_zero_count_cache[scan8[i + p * 16]];
                     if (nnz) {
-                        if (is_h264) {
-                            if (nnz == 1 && dctcoef_get(sl->mb, pixel_shift, i * 16 + p * 256))
-                                idct_dc_add(ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize);
-                            else
-                                idct_add(ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize);
-                        } else if (CONFIG_SVQ3_DECODER)
-                            ff_svq3_add_idct_c(ptr, sl->mb + i * 16 + p * 256, linesize, qscale, 0);
+                        if (nnz == 1 && dctcoef_get(sl->mb, pixel_shift, i * 16 + p * 256))
+                            idct_dc_add(ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize);
+                        else
+                            idct_add(ptr, sl->mb + (i * 16 + p * 256 << pixel_shift), linesize);
                     }
                 }
             }
         }
     } else {
         h->hpc.pred16x16[sl->intra16x16_pred_mode](dest_y, linesize);
-        if (is_h264) {
-            if (sl->non_zero_count_cache[scan8[LUMA_DC_BLOCK_INDEX + p]]) {
-                if (!transform_bypass)
-                    h->h264dsp.h264_luma_dc_dequant_idct(sl->mb + (p * 256 << pixel_shift),
-                                                         sl->mb_luma_dc[p],
-                                                         h->dequant4_coeff[p][qscale][0]);
-                else {
-                    static const uint8_t dc_mapping[16] = {
-                         0 * 16,  1 * 16,  4 * 16,  5 * 16,
-                         2 * 16,  3 * 16,  6 * 16,  7 * 16,
-                         8 * 16,  9 * 16, 12 * 16, 13 * 16,
-                        10 * 16, 11 * 16, 14 * 16, 15 * 16
-                    };
-                    for (i = 0; i < 16; i++)
-                        dctcoef_set(sl->mb + (p * 256 << pixel_shift),
-                                    pixel_shift, dc_mapping[i],
-                                    dctcoef_get(sl->mb_luma_dc[p],
-                                                pixel_shift, i));
-                }
+        if (sl->non_zero_count_cache[scan8[LUMA_DC_BLOCK_INDEX + p]]) {
+            if (!transform_bypass)
+                h->h264dsp.h264_luma_dc_dequant_idct(sl->mb + (p * 256 << pixel_shift),
+                                                     sl->mb_luma_dc[p],
+                                                     h->ps.pps->dequant4_coeff[p][qscale][0]);
+            else {
+                static const uint8_t dc_mapping[16] = {
+                     0 * 16,  1 * 16,  4 * 16,  5 * 16,
+                     2 * 16,  3 * 16,  6 * 16,  7 * 16,
+                     8 * 16,  9 * 16, 12 * 16, 13 * 16,
+                    10 * 16, 11 * 16, 14 * 16, 15 * 16
+                };
+                for (i = 0; i < 16; i++)
+                    dctcoef_set(sl->mb + (p * 256 << pixel_shift),
+                                pixel_shift, dc_mapping[i],
+                                dctcoef_get(sl->mb_luma_dc[p],
+                                            pixel_shift, i));
             }
-        } else if (CONFIG_SVQ3_DECODER)
-            ff_svq3_luma_dc_dequant_idct_c(sl->mb + p * 256,
-                                           sl->mb_luma_dc[p], qscale);
+        }
     }
 }
 
 static av_always_inline void hl_decode_mb_idct_luma(const H264Context *h, H264SliceContext *sl,
-                                                    int mb_type,
-                                                    int is_h264, int simple,
+                                                    int mb_type, int simple,
                                                     int transform_bypass,
                                                     int pixel_shift,
                                                     const int *block_offset,
@@ -745,60 +735,50 @@ static av_always_inline void hl_decode_mb_idct_luma(const H264Context *h, H264Sl
     int i;
     block_offset += 16 * p;
     if (!IS_INTRA4x4(mb_type)) {
-        if (is_h264) {
-            if (IS_INTRA16x16(mb_type)) {
-                if (transform_bypass) {
-                    if (h->sps.profile_idc == 244 &&
-                        (sl->intra16x16_pred_mode == VERT_PRED8x8 ||
-                         sl->intra16x16_pred_mode == HOR_PRED8x8)) {
-                        h->hpc.pred16x16_add[sl->intra16x16_pred_mode](dest_y, block_offset,
-                                                                      sl->mb + (p * 256 << pixel_shift),
-                                                                      linesize);
-                    } else {
-                        for (i = 0; i < 16; i++)
-                            if (sl->non_zero_count_cache[scan8[i + p * 16]] ||
-                                dctcoef_get(sl->mb, pixel_shift, i * 16 + p * 256))
-                                h->h264dsp.h264_add_pixels4_clear(dest_y + block_offset[i],
-                                                                  sl->mb + (i * 16 + p * 256 << pixel_shift),
-                                                                  linesize);
-                    }
-                } else {
-                    h->h264dsp.h264_idct_add16intra(dest_y, block_offset,
-                                                    sl->mb + (p * 256 << pixel_shift),
-                                                    linesize,
-                                                    sl->non_zero_count_cache + p * 5 * 8);
-                }
-            } else if (sl->cbp & 15) {
-                if (transform_bypass) {
-                    const int di = IS_8x8DCT(mb_type) ? 4 : 1;
-                    idct_add = IS_8x8DCT(mb_type) ? h->h264dsp.h264_add_pixels8_clear
-                                                  : h->h264dsp.h264_add_pixels4_clear;
-                    for (i = 0; i < 16; i += di)
-                        if (sl->non_zero_count_cache[scan8[i + p * 16]])
-                            idct_add(dest_y + block_offset[i],
-                                     sl->mb + (i * 16 + p * 256 << pixel_shift),
-                                     linesize);
+        if (IS_INTRA16x16(mb_type)) {
+            if (transform_bypass) {
+                if (h->ps.sps->profile_idc == 244 &&
+                    (sl->intra16x16_pred_mode == VERT_PRED8x8 ||
+                     sl->intra16x16_pred_mode == HOR_PRED8x8)) {
+                    h->hpc.pred16x16_add[sl->intra16x16_pred_mode](dest_y, block_offset,
+                                                                   sl->mb + (p * 256 << pixel_shift),
+                                                                   linesize);
                 } else {
-                    if (IS_8x8DCT(mb_type))
-                        h->h264dsp.h264_idct8_add4(dest_y, block_offset,
-                                                   sl->mb + (p * 256 << pixel_shift),
-                                                   linesize,
-                                                   sl->non_zero_count_cache + p * 5 * 8);
-                    else
-                        h->h264dsp.h264_idct_add16(dest_y, block_offset,
-                                                   sl->mb + (p * 256 << pixel_shift),
-                                                   linesize,
-                                                   sl->non_zero_count_cache + p * 5 * 8);
+                    for (i = 0; i < 16; i++)
+                        if (sl->non_zero_count_cache[scan8[i + p * 16]] ||
+                            dctcoef_get(sl->mb, pixel_shift, i * 16 + p * 256))
+                            h->h264dsp.h264_add_pixels4_clear(dest_y + block_offset[i],
+                                                              sl->mb + (i * 16 + p * 256 << pixel_shift),
+                                                              linesize);
                 }
+            } else {
+                h->h264dsp.h264_idct_add16intra(dest_y, block_offset,
+                                                sl->mb + (p * 256 << pixel_shift),
+                                                linesize,
+                                                sl->non_zero_count_cache + p * 5 * 8);
+            }
+        } else if (sl->cbp & 15) {
+            if (transform_bypass) {
+                const int di = IS_8x8DCT(mb_type) ? 4 : 1;
+                idct_add = IS_8x8DCT(mb_type) ? h->h264dsp.h264_add_pixels8_clear
+                    : h->h264dsp.h264_add_pixels4_clear;
+                for (i = 0; i < 16; i += di)
+                    if (sl->non_zero_count_cache[scan8[i + p * 16]])
+                        idct_add(dest_y + block_offset[i],
+                                 sl->mb + (i * 16 + p * 256 << pixel_shift),
+                                 linesize);
+            } else {
+                if (IS_8x8DCT(mb_type))
+                    h->h264dsp.h264_idct8_add4(dest_y, block_offset,
+                                               sl->mb + (p * 256 << pixel_shift),
+                                               linesize,
+                                               sl->non_zero_count_cache + p * 5 * 8);
+                else
+                    h->h264dsp.h264_idct_add16(dest_y, block_offset,
+                                               sl->mb + (p * 256 << pixel_shift),
+                                               linesize,
+                                               sl->non_zero_count_cache + p * 5 * 8);
             }
-        } else if (CONFIG_SVQ3_DECODER) {
-            for (i = 0; i < 16; i++)
-                if (sl->non_zero_count_cache[scan8[i + p * 16]] || sl->mb[i * 16 + p * 256]) {
-                    // FIXME benchmark weird rule, & below
-                    uint8_t *const ptr = dest_y + block_offset[i];
-                    ff_svq3_add_idct_c(ptr, sl->mb + i * 16 + p * 256, linesize,
-                                       sl->qscale, IS_INTRA(mb_type) ? 1 : 0);
-                }
         }
     }
 }
diff --git a/libavcodec/h264_mb_template.c b/libavcodec/h264_mb_template.c
index 54420b9..d5ea26a 100644
--- a/libavcodec/h264_mb_template.c
+++ b/libavcodec/h264_mb_template.c
@@ -19,8 +19,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "svq3.h"
-
 #undef FUNC
 #undef PIXEL_SHIFT
 
@@ -50,9 +48,7 @@ static av_noinline void FUNC(hl_decode_mb)(const H264Context *h, H264SliceContex
     int linesize, uvlinesize /*dct_offset*/;
     int i, j;
     const int *block_offset = &h->block_offset[0];
-    const int transform_bypass = !SIMPLE && (sl->qscale == 0 && h->sps.transform_bypass);
-    /* is_h264 should always be true if SVQ3 is disabled. */
-    const int is_h264 = !CONFIG_SVQ3_DECODER || SIMPLE || h->avctx->codec_id == AV_CODEC_ID_H264;
+    const int transform_bypass = !SIMPLE && (sl->qscale == 0 && h->ps.sps->transform_bypass);
     void (*idct_add)(uint8_t *dst, int16_t *block, int stride);
     const int block_h   = 16 >> h->chroma_y_shift;
     const int chroma422 = CHROMA422(h);
@@ -100,12 +96,12 @@ static av_noinline void FUNC(hl_decode_mb)(const H264Context *h, H264SliceContex
     }
 
     if (!SIMPLE && IS_INTRA_PCM(mb_type)) {
-        const int bit_depth = h->sps.bit_depth_luma;
+        const int bit_depth = h->ps.sps->bit_depth_luma;
         if (PIXEL_SHIFT) {
             int j;
             GetBitContext gb;
             init_get_bits(&gb, sl->intra_pcm_ptr,
-                          ff_h264_mb_sizes[h->sps.chroma_format_idc] * bit_depth);
+                          ff_h264_mb_sizes[h->ps.sps->chroma_format_idc] * bit_depth);
 
             for (i = 0; i < 16; i++) {
                 uint16_t *tmp_y = (uint16_t *)(dest_y + i * linesize);
@@ -113,7 +109,7 @@ static av_noinline void FUNC(hl_decode_mb)(const H264Context *h, H264SliceContex
                     tmp_y[j] = get_bits(&gb, bit_depth);
             }
             if (SIMPLE || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) {
-                if (!h->sps.chroma_format_idc) {
+                if (!h->ps.sps->chroma_format_idc) {
                     for (i = 0; i < block_h; i++) {
                         uint16_t *tmp_cb = (uint16_t *)(dest_cb + i * uvlinesize);
                         uint16_t *tmp_cr = (uint16_t *)(dest_cr + i * uvlinesize);
@@ -138,7 +134,7 @@ static av_noinline void FUNC(hl_decode_mb)(const H264Context *h, H264SliceContex
             for (i = 0; i < 16; i++)
                 memcpy(dest_y + i * linesize, sl->intra_pcm_ptr + i * 16, 16);
             if (SIMPLE || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) {
-                if (!h->sps.chroma_format_idc) {
+                if (!h->ps.sps->chroma_format_idc) {
                     for (i = 0; i < 8; i++) {
                         memset(dest_cb + i * uvlinesize, 1 << (bit_depth - 1), 8);
                         memset(dest_cr + i * uvlinesize, 1 << (bit_depth - 1), 8);
@@ -164,37 +160,41 @@ static av_noinline void FUNC(hl_decode_mb)(const H264Context *h, H264SliceContex
                 h->hpc.pred8x8[sl->chroma_pred_mode](dest_cr, uvlinesize);
             }
 
-            hl_decode_mb_predict_luma(h, sl, mb_type, is_h264, SIMPLE,
+            hl_decode_mb_predict_luma(h, sl, mb_type, SIMPLE,
                                       transform_bypass, PIXEL_SHIFT,
                                       block_offset, linesize, dest_y, 0);
 
             if (sl->deblocking_filter)
                 xchg_mb_border(h, sl, dest_y, dest_cb, dest_cr, linesize,
                                uvlinesize, 0, 0, SIMPLE, PIXEL_SHIFT);
-        } else if (is_h264) {
+        } else {
             if (chroma422) {
                 FUNC(hl_motion_422)(h, sl, dest_y, dest_cb, dest_cr,
-                              h->qpel_put, h->h264chroma.put_h264_chroma_pixels_tab,
-                              h->qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab,
+                              h->h264qpel.put_h264_qpel_pixels_tab,
+                              h->h264chroma.put_h264_chroma_pixels_tab,
+                              h->h264qpel.avg_h264_qpel_pixels_tab,
+                              h->h264chroma.avg_h264_chroma_pixels_tab,
                               h->h264dsp.weight_h264_pixels_tab,
                               h->h264dsp.biweight_h264_pixels_tab);
             } else {
                 FUNC(hl_motion_420)(h, sl, dest_y, dest_cb, dest_cr,
-                              h->qpel_put, h->h264chroma.put_h264_chroma_pixels_tab,
-                              h->qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab,
+                              h->h264qpel.put_h264_qpel_pixels_tab,
+                              h->h264chroma.put_h264_chroma_pixels_tab,
+                              h->h264qpel.avg_h264_qpel_pixels_tab,
+                              h->h264chroma.avg_h264_chroma_pixels_tab,
                               h->h264dsp.weight_h264_pixels_tab,
                               h->h264dsp.biweight_h264_pixels_tab);
             }
         }
 
-        hl_decode_mb_idct_luma(h, sl, mb_type, is_h264, SIMPLE, transform_bypass,
+        hl_decode_mb_idct_luma(h, sl, mb_type, SIMPLE, transform_bypass,
                                PIXEL_SHIFT, block_offset, linesize, dest_y, 0);
 
         if ((SIMPLE || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) &&
             (sl->cbp & 0x30)) {
             uint8_t *dest[2] = { dest_cb, dest_cr };
             if (transform_bypass) {
-                if (IS_INTRA(mb_type) && h->sps.profile_idc == 244 &&
+                if (IS_INTRA(mb_type) && h->ps.sps->profile_idc == 244 &&
                     (sl->chroma_pred_mode == VERT_PRED8x8 ||
                      sl->chroma_pred_mode == HOR_PRED8x8)) {
                     h->hpc.pred8x8_add[sl->chroma_pred_mode](dest[0],
@@ -225,39 +225,23 @@ static av_noinline void FUNC(hl_decode_mb)(const H264Context *h, H264SliceContex
                     }
                 }
             } else {
-                if (is_h264) {
-                    int qp[2];
-                    if (chroma422) {
-                        qp[0] = sl->chroma_qp[0] + 3;
-                        qp[1] = sl->chroma_qp[1] + 3;
-                    } else {
-                        qp[0] = sl->chroma_qp[0];
-                        qp[1] = sl->chroma_qp[1];
-                    }
-                    if (sl->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 0]])
-                        h->h264dsp.h264_chroma_dc_dequant_idct(sl->mb + (16 * 16 * 1 << PIXEL_SHIFT),
-                                                               h->dequant4_coeff[IS_INTRA(mb_type) ? 1 : 4][qp[0]][0]);
-                    if (sl->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 1]])
-                        h->h264dsp.h264_chroma_dc_dequant_idct(sl->mb + (16 * 16 * 2 << PIXEL_SHIFT),
-                                                               h->dequant4_coeff[IS_INTRA(mb_type) ? 2 : 5][qp[1]][0]);
-                    h->h264dsp.h264_idct_add8(dest, block_offset,
-                                              sl->mb, uvlinesize,
-                                              sl->non_zero_count_cache);
-                } else if (CONFIG_SVQ3_DECODER) {
-                    h->h264dsp.h264_chroma_dc_dequant_idct(sl->mb + 16 * 16 * 1,
-                                                           h->dequant4_coeff[IS_INTRA(mb_type) ? 1 : 4][sl->chroma_qp[0]][0]);
-                    h->h264dsp.h264_chroma_dc_dequant_idct(sl->mb + 16 * 16 * 2,
-                                                           h->dequant4_coeff[IS_INTRA(mb_type) ? 2 : 5][sl->chroma_qp[1]][0]);
-                    for (j = 1; j < 3; j++) {
-                        for (i = j * 16; i < j * 16 + 4; i++)
-                            if (sl->non_zero_count_cache[scan8[i]] || sl->mb[i * 16]) {
-                                uint8_t *const ptr = dest[j - 1] + block_offset[i];
-                                ff_svq3_add_idct_c(ptr, sl->mb + i * 16,
-                                                   uvlinesize,
-                                                   ff_h264_chroma_qp[0][sl->qscale + 12] - 12, 2);
-                            }
-                    }
+                int qp[2];
+                if (chroma422) {
+                    qp[0] = sl->chroma_qp[0] + 3;
+                    qp[1] = sl->chroma_qp[1] + 3;
+                } else {
+                    qp[0] = sl->chroma_qp[0];
+                    qp[1] = sl->chroma_qp[1];
                 }
+                if (sl->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 0]])
+                    h->h264dsp.h264_chroma_dc_dequant_idct(sl->mb + (16 * 16 * 1 << PIXEL_SHIFT),
+                                                           h->ps.pps->dequant4_coeff[IS_INTRA(mb_type) ? 1 : 4][qp[0]][0]);
+                if (sl->non_zero_count_cache[scan8[CHROMA_DC_BLOCK_INDEX + 1]])
+                    h->h264dsp.h264_chroma_dc_dequant_idct(sl->mb + (16 * 16 * 2 << PIXEL_SHIFT),
+                                                           h->ps.pps->dequant4_coeff[IS_INTRA(mb_type) ? 2 : 5][qp[1]][0]);
+                h->h264dsp.h264_idct_add8(dest, block_offset,
+                                          sl->mb, uvlinesize,
+                                          sl->non_zero_count_cache);
             }
         }
     }
@@ -279,7 +263,7 @@ static av_noinline void FUNC(hl_decode_mb_444)(const H264Context *h, H264SliceCo
     int linesize;
     int i, j, p;
     const int *block_offset = &h->block_offset[0];
-    const int transform_bypass = !SIMPLE && (sl->qscale == 0 && h->sps.transform_bypass);
+    const int transform_bypass = !SIMPLE && (sl->qscale == 0 && h->ps.sps->transform_bypass);
     const int plane_count      = (SIMPLE || !CONFIG_GRAY || !(h->flags & AV_CODEC_FLAG_GRAY)) ? 3 : 1;
 
     for (p = 0; p < plane_count; p++) {
@@ -321,7 +305,7 @@ static av_noinline void FUNC(hl_decode_mb_444)(const H264Context *h, H264SliceCo
 
     if (!SIMPLE && IS_INTRA_PCM(mb_type)) {
         if (PIXEL_SHIFT) {
-            const int bit_depth = h->sps.bit_depth_luma;
+            const int bit_depth = h->ps.sps->bit_depth_luma;
             GetBitContext gb;
             init_get_bits(&gb, sl->intra_pcm_ptr, 768 * bit_depth);
 
@@ -344,7 +328,7 @@ static av_noinline void FUNC(hl_decode_mb_444)(const H264Context *h, H264SliceCo
                                linesize, 1, 1, SIMPLE, PIXEL_SHIFT);
 
             for (p = 0; p < plane_count; p++)
-                hl_decode_mb_predict_luma(h, sl, mb_type, 1, SIMPLE,
+                hl_decode_mb_predict_luma(h, sl, mb_type, SIMPLE,
                                           transform_bypass, PIXEL_SHIFT,
                                           block_offset, linesize, dest[p], p);
 
@@ -353,14 +337,16 @@ static av_noinline void FUNC(hl_decode_mb_444)(const H264Context *h, H264SliceCo
                                linesize, 0, 1, SIMPLE, PIXEL_SHIFT);
         } else {
             FUNC(hl_motion_444)(h, sl, dest[0], dest[1], dest[2],
-                      h->qpel_put, h->h264chroma.put_h264_chroma_pixels_tab,
-                      h->qpel_avg, h->h264chroma.avg_h264_chroma_pixels_tab,
+                      h->h264qpel.put_h264_qpel_pixels_tab,
+                      h->h264chroma.put_h264_chroma_pixels_tab,
+                      h->h264qpel.avg_h264_qpel_pixels_tab,
+                      h->h264chroma.avg_h264_chroma_pixels_tab,
                       h->h264dsp.weight_h264_pixels_tab,
                       h->h264dsp.biweight_h264_pixels_tab);
         }
 
         for (p = 0; p < plane_count; p++)
-            hl_decode_mb_idct_luma(h, sl, mb_type, 1, SIMPLE, transform_bypass,
+            hl_decode_mb_idct_luma(h, sl, mb_type, SIMPLE, transform_bypass,
                                    PIXEL_SHIFT, block_offset, linesize,
                                    dest[p], p);
     }
diff --git a/libavcodec/h264_mc_template.c b/libavcodec/h264_mc_template.c
index e4333a7..cd4a04e 100644
--- a/libavcodec/h264_mc_template.c
+++ b/libavcodec/h264_mc_template.c
@@ -48,9 +48,9 @@ static void mc_part(const H264Context *h, H264SliceContext *sl,
                     const h264_biweight_func *weight_avg,
                     int list0, int list1)
 {
-    if ((sl->use_weight == 2 && list0 && list1 &&
-         (sl->implicit_weight[sl->ref_cache[0][scan8[n]]][sl->ref_cache[1][scan8[n]]][sl->mb_y & 1] != 32)) ||
-        sl->use_weight == 1)
+    if ((sl->pwt.use_weight == 2 && list0 && list1 &&
+         (sl->pwt.implicit_weight[sl->ref_cache[0][scan8[n]]][sl->ref_cache[1][scan8[n]]][sl->mb_y & 1] != 32)) ||
+        sl->pwt.use_weight == 1)
         mc_part_weighted(h, sl, n, square, height, delta, dest_y, dest_cb, dest_cr,
                          x_offset, y_offset, qpix_put, chroma_put,
                          weight_op[0], weight_op[1], weight_avg[0],
@@ -64,9 +64,9 @@ static void mc_part(const H264Context *h, H264SliceContext *sl,
 static void MCFUNC(hl_motion)(const H264Context *h, H264SliceContext *sl,
                               uint8_t *dest_y,
                               uint8_t *dest_cb, uint8_t *dest_cr,
-                              qpel_mc_func(*qpix_put)[16],
+                              const qpel_mc_func(*qpix_put)[16],
                               const h264_chroma_mc_func(*chroma_put),
-                              qpel_mc_func(*qpix_avg)[16],
+                              const qpel_mc_func(*qpix_avg)[16],
                               const h264_chroma_mc_func(*chroma_avg),
                               const h264_weight_func *weight_op,
                               const h264_biweight_func *weight_avg)
diff --git a/libavcodec/h264_mp4toannexb_bsf.c b/libavcodec/h264_mp4toannexb_bsf.c
index 2d447f7..163d0f5 100644
--- a/libavcodec/h264_mp4toannexb_bsf.c
+++ b/libavcodec/h264_mp4toannexb_bsf.c
@@ -23,7 +23,9 @@
 
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
+
 #include "avcodec.h"
+#include "bsf.h"
 
 typedef struct H264BSFContext {
     int32_t  sps_offset;
@@ -33,66 +35,53 @@ typedef struct H264BSFContext {
     uint8_t  idr_sps_seen;
     uint8_t  idr_pps_seen;
     int      extradata_parsed;
-
-    /* When private_spspps is zero then spspps_buf points to global extradata
-       and bsf does replace a global extradata to own-allocated version (default
-       behaviour).
-       When private_spspps is non-zero the bsf uses a private version of spspps buf.
-       This mode necessary when bsf uses in decoder, else bsf has issues after
-       decoder re-initialization. Use the "private_spspps_buf" argument to
-       activate this mode.
-     */
-    int      private_spspps;
-    uint8_t *spspps_buf;
-    uint32_t spspps_size;
 } H264BSFContext;
 
-static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size,
+static int alloc_and_copy(AVPacket *out,
                           const uint8_t *sps_pps, uint32_t sps_pps_size,
                           const uint8_t *in, uint32_t in_size)
 {
-    uint32_t offset         = *poutbuf_size;
+    uint32_t offset         = out->size;
     uint8_t nal_header_size = offset ? 3 : 4;
     int err;
 
-    *poutbuf_size += sps_pps_size + in_size + nal_header_size;
-    if ((err = av_reallocp(poutbuf,
-                           *poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
-        *poutbuf_size = 0;
+    err = av_grow_packet(out, sps_pps_size + in_size + nal_header_size);
+    if (err < 0)
         return err;
-    }
+
     if (sps_pps)
-        memcpy(*poutbuf + offset, sps_pps, sps_pps_size);
-    memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size);
+        memcpy(out->data + offset, sps_pps, sps_pps_size);
+    memcpy(out->data + sps_pps_size + nal_header_size + offset, in, in_size);
     if (!offset) {
-        AV_WB32(*poutbuf + sps_pps_size, 1);
+        AV_WB32(out->data + sps_pps_size, 1);
     } else {
-        (*poutbuf + offset + sps_pps_size)[0] =
-        (*poutbuf + offset + sps_pps_size)[1] = 0;
-        (*poutbuf + offset + sps_pps_size)[2] = 1;
+        (out->data + offset + sps_pps_size)[0] =
+        (out->data + offset + sps_pps_size)[1] = 0;
+        (out->data + offset + sps_pps_size)[2] = 1;
     }
 
     return 0;
 }
 
-static int h264_extradata_to_annexb(H264BSFContext *ctx, AVCodecContext *avctx, const int padding)
+static int h264_extradata_to_annexb(AVBSFContext *ctx, const int padding)
 {
+    H264BSFContext *s = ctx->priv_data;
     uint16_t unit_size;
     uint64_t total_size                 = 0;
     uint8_t *out                        = NULL, unit_nb, sps_done = 0,
              sps_seen                   = 0, pps_seen = 0;
-    const uint8_t *extradata            = avctx->extradata + 4;
+    const uint8_t *extradata            = ctx->par_in->extradata + 4;
     static const uint8_t nalu_header[4] = { 0, 0, 0, 1 };
     int length_size = (*extradata++ & 0x3) + 1; // retrieve length coded size
 
-    ctx->sps_offset = ctx->pps_offset = -1;
+    s->sps_offset = s->pps_offset = -1;
 
     /* retrieve sps and pps unit(s) */
     unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
     if (!unit_nb) {
         goto pps;
     } else {
-        ctx->sps_offset = 0;
+        s->sps_offset = 0;
         sps_seen = 1;
     }
 
@@ -102,13 +91,13 @@ static int h264_extradata_to_annexb(H264BSFContext *ctx, AVCodecContext *avctx,
         unit_size   = AV_RB16(extradata);
         total_size += unit_size + 4;
         if (total_size > INT_MAX - padding) {
-            av_log(avctx, AV_LOG_ERROR,
+            av_log(ctx, AV_LOG_ERROR,
                    "Too big extradata size, corrupted stream or invalid MP4/AVCC bitstream\n");
             av_free(out);
             return AVERROR(EINVAL);
         }
-        if (extradata + 2 + unit_size > avctx->extradata + avctx->extradata_size) {
-            av_log(avctx, AV_LOG_ERROR, "Packet header is not contained in global extradata, "
+        if (extradata + 2 + unit_size > ctx->par_in->extradata + ctx->par_in->extradata_size) {
+            av_log(ctx, AV_LOG_ERROR, "Packet header is not contained in global extradata, "
                    "corrupted stream or invalid MP4/AVCC bitstream\n");
             av_free(out);
             return AVERROR(EINVAL);
@@ -122,7 +111,7 @@ pps:
         if (!unit_nb && !sps_done++) {
             unit_nb = *extradata++; /* number of pps unit(s) */
             if (unit_nb) {
-                ctx->pps_offset = total_size;
+                s->pps_offset = total_size;
                 pps_seen = 1;
             }
         }
@@ -132,93 +121,109 @@ pps:
         memset(out + total_size, 0, padding);
 
     if (!sps_seen)
-        av_log(avctx, AV_LOG_WARNING,
+        av_log(ctx, AV_LOG_WARNING,
                "Warning: SPS NALU missing or invalid. "
                "The resulting stream may not play.\n");
 
     if (!pps_seen)
-        av_log(avctx, AV_LOG_WARNING,
+        av_log(ctx, AV_LOG_WARNING,
                "Warning: PPS NALU missing or invalid. "
                "The resulting stream may not play.\n");
 
-    if (!ctx->private_spspps) {
-        av_free(avctx->extradata);
-        avctx->extradata      = out;
-        avctx->extradata_size = total_size;
-    }
-    ctx->spspps_buf  = out;
-    ctx->spspps_size = total_size;
+    av_freep(&ctx->par_out->extradata);
+    ctx->par_out->extradata      = out;
+    ctx->par_out->extradata_size = total_size;
 
     return length_size;
 }
 
-static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
-                                   AVCodecContext *avctx, const char *args,
-                                   uint8_t **poutbuf, int *poutbuf_size,
-                                   const uint8_t *buf, int buf_size,
-                                   int keyframe)
+static int h264_mp4toannexb_init(AVBSFContext *ctx)
+{
+    H264BSFContext *s = ctx->priv_data;
+    int extra_size = ctx->par_in->extradata_size;
+    int ret;
+
+    /* retrieve sps and pps NAL units from extradata */
+    if (!extra_size                                               ||
+        (extra_size >= 3 && AV_RB24(ctx->par_in->extradata) == 1) ||
+        (extra_size >= 4 && AV_RB32(ctx->par_in->extradata) == 1)) {
+        av_log(ctx, AV_LOG_VERBOSE,
+               "The input looks like it is Annex B already\n");
+    } else if (extra_size >= 6) {
+        ret = h264_extradata_to_annexb(ctx, AV_INPUT_BUFFER_PADDING_SIZE);
+        if (ret < 0)
+            return ret;
+
+        s->length_size      = ret;
+        s->new_idr          = 1;
+        s->idr_sps_seen     = 0;
+        s->idr_pps_seen     = 0;
+        s->extradata_parsed = 1;
+    } else {
+        av_log(ctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extra_size);
+        return AVERROR_INVALIDDATA;
+    }
+
+    return 0;
+}
+
+static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
 {
-    H264BSFContext *ctx = bsfc->priv_data;
-    int i;
+    H264BSFContext *s = ctx->priv_data;
+
+    AVPacket *in;
     uint8_t unit_type;
     int32_t nal_size;
     uint32_t cumul_size    = 0;
-    const uint8_t *buf_end = buf + buf_size;
-    int ret = 0;
+    const uint8_t *buf;
+    const uint8_t *buf_end;
+    int            buf_size;
+    int ret = 0, i;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
 
     /* nothing to filter */
-    if (!avctx->extradata || avctx->extradata_size < 6) {
-        *poutbuf      = (uint8_t *)buf;
-        *poutbuf_size = buf_size;
+    if (!s->extradata_parsed) {
+        av_packet_move_ref(out, in);
+        av_packet_free(&in);
         return 0;
     }
 
-    /* retrieve sps and pps NAL units from extradata */
-    if (!ctx->extradata_parsed) {
-        if (args && strstr(args, "private_spspps_buf"))
-            ctx->private_spspps = 1;
-
-        ret = h264_extradata_to_annexb(ctx, avctx, AV_INPUT_BUFFER_PADDING_SIZE);
-        if (ret < 0)
-            return ret;
-        ctx->length_size      = ret;
-        ctx->new_idr          = 1;
-        ctx->idr_sps_seen     = 0;
-        ctx->idr_pps_seen     = 0;
-        ctx->extradata_parsed = 1;
-    }
+    buf      = in->data;
+    buf_size = in->size;
+    buf_end  = in->data + in->size;
 
-    *poutbuf_size = 0;
-    *poutbuf      = NULL;
     do {
         ret= AVERROR(EINVAL);
-        if (buf + ctx->length_size > buf_end)
+        if (buf + s->length_size > buf_end)
             goto fail;
 
-        for (nal_size = 0, i = 0; i<ctx->length_size; i++)
+        for (nal_size = 0, i = 0; i<s->length_size; i++)
             nal_size = (nal_size << 8) | buf[i];
 
-        buf      += ctx->length_size;
+        buf += s->length_size;
         unit_type = *buf & 0x1f;
 
         if (nal_size > buf_end - buf || nal_size < 0)
             goto fail;
 
         if (unit_type == 7)
-            ctx->idr_sps_seen = ctx->new_idr = 1;
+            s->idr_sps_seen = s->new_idr = 1;
         else if (unit_type == 8) {
-            ctx->idr_pps_seen = ctx->new_idr = 1;
+            s->idr_pps_seen = s->new_idr = 1;
             /* if SPS has not been seen yet, prepend the AVCC one to PPS */
-            if (!ctx->idr_sps_seen) {
-                if (ctx->sps_offset == -1)
-                    av_log(avctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
+            if (!s->idr_sps_seen) {
+                if (s->sps_offset == -1)
+                    av_log(ctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
                 else {
-                    if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
-                                         ctx->spspps_buf + ctx->sps_offset,
-                                         ctx->pps_offset != -1 ? ctx->pps_offset : ctx->spspps_size - ctx->sps_offset,
+                    if ((ret = alloc_and_copy(out,
+                                         ctx->par_out->extradata + s->sps_offset,
+                                         s->pps_offset != -1 ? s->pps_offset : ctx->par_out->extradata_size - s->sps_offset,
                                          buf, nal_size)) < 0)
                         goto fail;
-                    ctx->idr_sps_seen = 1;
+                    s->idr_sps_seen = 1;
                     goto next_nal;
                 }
             }
@@ -227,61 +232,61 @@ static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
         /* if this is a new IDR picture following an IDR picture, reset the idr flag.
          * Just check first_mb_in_slice to be 0 as this is the simplest solution.
          * This could be checking idr_pic_id instead, but would complexify the parsing. */
-        if (!ctx->new_idr && unit_type == 5 && (buf[1] & 0x80))
-            ctx->new_idr = 1;
+        if (!s->new_idr && unit_type == 5 && (buf[1] & 0x80))
+            s->new_idr = 1;
 
         /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
-        if (ctx->new_idr && unit_type == 5 && !ctx->idr_sps_seen && !ctx->idr_pps_seen) {
-            if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
-                               ctx->spspps_buf, ctx->spspps_size,
+        if (s->new_idr && unit_type == 5 && !s->idr_sps_seen && !s->idr_pps_seen) {
+            if ((ret=alloc_and_copy(out,
+                               ctx->par_out->extradata, ctx->par_out->extradata_size,
                                buf, nal_size)) < 0)
                 goto fail;
-            ctx->new_idr = 0;
+            s->new_idr = 0;
         /* if only SPS has been seen, also insert PPS */
-        } else if (ctx->new_idr && unit_type == 5 && ctx->idr_sps_seen && !ctx->idr_pps_seen) {
-            if (ctx->pps_offset == -1) {
-                av_log(avctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
-                if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
-                                     NULL, 0, buf, nal_size)) < 0)
+        } else if (s->new_idr && unit_type == 5 && s->idr_sps_seen && !s->idr_pps_seen) {
+            if (s->pps_offset == -1) {
+                av_log(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
+                if ((ret = alloc_and_copy(out, NULL, 0, buf, nal_size)) < 0)
                     goto fail;
-            } else if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
-                                        ctx->spspps_buf + ctx->pps_offset, ctx->spspps_size - ctx->pps_offset,
+            } else if ((ret = alloc_and_copy(out,
+                                        ctx->par_out->extradata + s->pps_offset, ctx->par_out->extradata_size - s->pps_offset,
                                         buf, nal_size)) < 0)
                 goto fail;
         } else {
-            if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
-                               NULL, 0, buf, nal_size)) < 0)
+            if ((ret=alloc_and_copy(out, NULL, 0, buf, nal_size)) < 0)
                 goto fail;
-            if (!ctx->new_idr && unit_type == 1) {
-                ctx->new_idr = 1;
-                ctx->idr_sps_seen = 0;
-                ctx->idr_pps_seen = 0;
+            if (!s->new_idr && unit_type == 1) {
+                s->new_idr = 1;
+                s->idr_sps_seen = 0;
+                s->idr_pps_seen = 0;
             }
         }
 
 next_nal:
         buf        += nal_size;
-        cumul_size += nal_size + ctx->length_size;
+        cumul_size += nal_size + s->length_size;
     } while (cumul_size < buf_size);
 
-    return 1;
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
 
 fail:
-    av_freep(poutbuf);
-    *poutbuf_size = 0;
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+
     return ret;
 }
 
-static void h264_mp4toannexb_filter_close(AVBitStreamFilterContext *bsfc)
-{
-    H264BSFContext *ctx = bsfc->priv_data;
-    if (ctx->private_spspps)
-        av_freep(&ctx->spspps_buf);
-}
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_H264, AV_CODEC_ID_NONE,
+};
 
-AVBitStreamFilter ff_h264_mp4toannexb_bsf = {
+const AVBitStreamFilter ff_h264_mp4toannexb_bsf = {
     .name           = "h264_mp4toannexb",
     .priv_data_size = sizeof(H264BSFContext),
+    .init           = h264_mp4toannexb_init,
     .filter         = h264_mp4toannexb_filter,
-    .close          = h264_mp4toannexb_filter_close,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/h264_mvpred.h b/libavcodec/h264_mvpred.h
index 763746c..be02e5a 100644
--- a/libavcodec/h264_mvpred.h
+++ b/libavcodec/h264_mvpred.h
@@ -1,5 +1,5 @@
 /*
- * H.26L/H.264/AVC/JVT/14496-10/... motion vector predicion
+ * H.26L/H.264/AVC/JVT/14496-10/... motion vector prediction
  * Copyright (c) 2003 Michael Niedermayer <michaelni at gmx.at>
  *
  * This file is part of FFmpeg.
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 motion vector predicion.
+ * H.264 / AVC / MPEG-4 part10 motion vector prediction.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -464,7 +464,7 @@ static void fill_decode_caches(const H264Context *h, H264SliceContext *sl, int m
 
     if (!IS_SKIP(mb_type)) {
         if (IS_INTRA(mb_type)) {
-            int type_mask = h->pps.constrained_intra_pred ? IS_INTRA(-1) : -1;
+            int type_mask = h->ps.pps->constrained_intra_pred ? IS_INTRA(-1) : -1;
             sl->topleft_samples_available     =
                 sl->top_samples_available     =
                     sl->left_samples_available = 0xFFFF;
diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c
new file mode 100644
index 0000000..a63530d
--- /dev/null
+++ b/libavcodec/h264_parse.c
@@ -0,0 +1,497 @@
+/*
+ * 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 "bytestream.h"
+#include "get_bits.h"
+#include "golomb.h"
+#include "h264.h"
+#include "h264_parse.h"
+
+int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
+                              const int *ref_count, int slice_type_nos,
+                              H264PredWeightTable *pwt, void *logctx)
+{
+    int list, i;
+    int luma_def, chroma_def;
+
+    pwt->use_weight             = 0;
+    pwt->use_weight_chroma      = 0;
+    pwt->luma_log2_weight_denom = get_ue_golomb(gb);
+    if (sps->chroma_format_idc)
+        pwt->chroma_log2_weight_denom = get_ue_golomb(gb);
+
+    if (pwt->luma_log2_weight_denom > 7U) {
+        av_log(logctx, AV_LOG_ERROR, "luma_log2_weight_denom %d is out of range\n", pwt->luma_log2_weight_denom);
+        pwt->luma_log2_weight_denom = 0;
+    }
+    if (pwt->chroma_log2_weight_denom > 7U) {
+        av_log(logctx, AV_LOG_ERROR, "chroma_log2_weight_denom %d is out of range\n", pwt->chroma_log2_weight_denom);
+        pwt->chroma_log2_weight_denom = 0;
+    }
+
+    luma_def   = 1 << pwt->luma_log2_weight_denom;
+    chroma_def = 1 << pwt->chroma_log2_weight_denom;
+
+    for (list = 0; list < 2; list++) {
+        pwt->luma_weight_flag[list]   = 0;
+        pwt->chroma_weight_flag[list] = 0;
+        for (i = 0; i < ref_count[list]; i++) {
+            int luma_weight_flag, chroma_weight_flag;
+
+            luma_weight_flag = get_bits1(gb);
+            if (luma_weight_flag) {
+                pwt->luma_weight[i][list][0] = get_se_golomb(gb);
+                pwt->luma_weight[i][list][1] = get_se_golomb(gb);
+                if (pwt->luma_weight[i][list][0] != luma_def ||
+                    pwt->luma_weight[i][list][1] != 0) {
+                    pwt->use_weight             = 1;
+                    pwt->luma_weight_flag[list] = 1;
+                }
+            } else {
+                pwt->luma_weight[i][list][0] = luma_def;
+                pwt->luma_weight[i][list][1] = 0;
+            }
+
+            if (sps->chroma_format_idc) {
+                chroma_weight_flag = get_bits1(gb);
+                if (chroma_weight_flag) {
+                    int j;
+                    for (j = 0; j < 2; j++) {
+                        pwt->chroma_weight[i][list][j][0] = get_se_golomb(gb);
+                        pwt->chroma_weight[i][list][j][1] = get_se_golomb(gb);
+                        if (pwt->chroma_weight[i][list][j][0] != chroma_def ||
+                            pwt->chroma_weight[i][list][j][1] != 0) {
+                            pwt->use_weight_chroma        = 1;
+                            pwt->chroma_weight_flag[list] = 1;
+                        }
+                    }
+                } else {
+                    int j;
+                    for (j = 0; j < 2; j++) {
+                        pwt->chroma_weight[i][list][j][0] = chroma_def;
+                        pwt->chroma_weight[i][list][j][1] = 0;
+                    }
+                }
+            }
+        }
+        if (slice_type_nos != AV_PICTURE_TYPE_B)
+            break;
+    }
+    pwt->use_weight = pwt->use_weight || pwt->use_weight_chroma;
+    return 0;
+}
+
+/**
+ * Check if the top & left blocks are available if needed and
+ * change the dc mode so it only uses the available blocks.
+ */
+int ff_h264_check_intra4x4_pred_mode(int8_t *pred_mode_cache, void *logctx,
+                                     int top_samples_available, int left_samples_available)
+{
+    static const int8_t top[12] = {
+        -1, 0, LEFT_DC_PRED, -1, -1, -1, -1, -1, 0
+    };
+    static const int8_t left[12] = {
+        0, -1, TOP_DC_PRED, 0, -1, -1, -1, 0, -1, DC_128_PRED
+    };
+    int i;
+
+    if (!(top_samples_available & 0x8000)) {
+        for (i = 0; i < 4; i++) {
+            int status = top[pred_mode_cache[scan8[0] + i]];
+            if (status < 0) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "top block unavailable for requested intra mode %d\n",
+                       status);
+                return AVERROR_INVALIDDATA;
+            } else if (status) {
+                pred_mode_cache[scan8[0] + i] = status;
+            }
+        }
+    }
+
+    if ((left_samples_available & 0x8888) != 0x8888) {
+        static const int mask[4] = { 0x8000, 0x2000, 0x80, 0x20 };
+        for (i = 0; i < 4; i++)
+            if (!(left_samples_available & mask[i])) {
+                int status = left[pred_mode_cache[scan8[0] + 8 * i]];
+                if (status < 0) {
+                    av_log(logctx, AV_LOG_ERROR,
+                           "left block unavailable for requested intra4x4 mode %d\n",
+                           status);
+                    return AVERROR_INVALIDDATA;
+                } else if (status) {
+                    pred_mode_cache[scan8[0] + 8 * i] = status;
+                }
+            }
+    }
+
+    return 0;
+}
+
+/**
+ * Check if the top & left blocks are available if needed and
+ * change the dc mode so it only uses the available blocks.
+ */
+int ff_h264_check_intra_pred_mode(void *logctx, int top_samples_available,
+                                  int left_samples_available,
+                                  int mode, int is_chroma)
+{
+    static const int8_t top[4]  = { LEFT_DC_PRED8x8, 1, -1, -1 };
+    static const int8_t left[5] = { TOP_DC_PRED8x8, -1,  2, -1, DC_128_PRED8x8 };
+
+    if (mode > 3U) {
+        av_log(logctx, AV_LOG_ERROR,
+               "out of range intra chroma pred mode\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (!(top_samples_available & 0x8000)) {
+        mode = top[mode];
+        if (mode < 0) {
+            av_log(logctx, AV_LOG_ERROR,
+                   "top block unavailable for requested intra mode\n");
+            return AVERROR_INVALIDDATA;
+        }
+    }
+
+    if ((left_samples_available & 0x8080) != 0x8080) {
+        mode = left[mode];
+        if (mode < 0) {
+            av_log(logctx, AV_LOG_ERROR,
+                   "left block unavailable for requested intra mode\n");
+            return AVERROR_INVALIDDATA;
+        }
+        if (is_chroma && (left_samples_available & 0x8080)) {
+            // mad cow disease mode, aka MBAFF + constrained_intra_pred
+            mode = ALZHEIMER_DC_L0T_PRED8x8 +
+                   (!(left_samples_available & 0x8000)) +
+                   2 * (mode == DC_128_PRED8x8);
+        }
+    }
+
+    return mode;
+}
+
+int ff_h264_parse_ref_count(int *plist_count, int ref_count[2],
+                            GetBitContext *gb, const PPS *pps,
+                            int slice_type_nos, int picture_structure, void *logctx)
+{
+    int list_count;
+    int num_ref_idx_active_override_flag;
+
+    // set defaults, might be overridden a few lines later
+    ref_count[0] = pps->ref_count[0];
+    ref_count[1] = pps->ref_count[1];
+
+    if (slice_type_nos != AV_PICTURE_TYPE_I) {
+        unsigned max[2];
+        max[0] = max[1] = picture_structure == PICT_FRAME ? 15 : 31;
+
+        num_ref_idx_active_override_flag = get_bits1(gb);
+
+        if (num_ref_idx_active_override_flag) {
+            ref_count[0] = get_ue_golomb(gb) + 1;
+            if (slice_type_nos == AV_PICTURE_TYPE_B) {
+                ref_count[1] = get_ue_golomb(gb) + 1;
+            } else
+                // full range is spec-ok in this case, even for frames
+                ref_count[1] = 1;
+        }
+
+        if (ref_count[0] - 1 > max[0] || ref_count[1] - 1 > max[1]) {
+            av_log(logctx, AV_LOG_ERROR, "reference overflow %u > %u or %u > %u\n",
+                   ref_count[0] - 1, max[0], ref_count[1] - 1, max[1]);
+            ref_count[0] = ref_count[1] = 0;
+            *plist_count = 0;
+            goto fail;
+        }
+
+        if (slice_type_nos == AV_PICTURE_TYPE_B)
+            list_count = 2;
+        else
+            list_count = 1;
+    } else {
+        list_count   = 0;
+        ref_count[0] = ref_count[1] = 0;
+    }
+
+    *plist_count = list_count;
+
+    return 0;
+fail:
+    *plist_count = 0;
+    ref_count[0] = 0;
+    ref_count[1] = 0;
+    return AVERROR_INVALIDDATA;
+}
+
+int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc,
+                     const SPS *sps, H264POCContext *pc,
+                     int picture_structure, int nal_ref_idc)
+{
+    const int max_frame_num = 1 << sps->log2_max_frame_num;
+    int field_poc[2];
+
+    pc->frame_num_offset = pc->prev_frame_num_offset;
+    if (pc->frame_num < pc->prev_frame_num)
+        pc->frame_num_offset += max_frame_num;
+
+    if (sps->poc_type == 0) {
+        const int max_poc_lsb = 1 << sps->log2_max_poc_lsb;
+
+        if (pc->poc_lsb < pc->prev_poc_lsb &&
+            pc->prev_poc_lsb - pc->poc_lsb >= max_poc_lsb / 2)
+            pc->poc_msb = pc->prev_poc_msb + max_poc_lsb;
+        else if (pc->poc_lsb > pc->prev_poc_lsb &&
+                 pc->prev_poc_lsb - pc->poc_lsb < -max_poc_lsb / 2)
+            pc->poc_msb = pc->prev_poc_msb - max_poc_lsb;
+        else
+            pc->poc_msb = pc->prev_poc_msb;
+        field_poc[0] =
+        field_poc[1] = pc->poc_msb + pc->poc_lsb;
+        if (picture_structure == PICT_FRAME)
+            field_poc[1] += pc->delta_poc_bottom;
+    } else if (sps->poc_type == 1) {
+        int abs_frame_num, expected_delta_per_poc_cycle, expectedpoc;
+        int i;
+
+        if (sps->poc_cycle_length != 0)
+            abs_frame_num = pc->frame_num_offset + pc->frame_num;
+        else
+            abs_frame_num = 0;
+
+        if (nal_ref_idc == 0 && abs_frame_num > 0)
+            abs_frame_num--;
+
+        expected_delta_per_poc_cycle = 0;
+        for (i = 0; i < sps->poc_cycle_length; i++)
+            // FIXME integrate during sps parse
+            expected_delta_per_poc_cycle += sps->offset_for_ref_frame[i];
+
+        if (abs_frame_num > 0) {
+            int poc_cycle_cnt          = (abs_frame_num - 1) / sps->poc_cycle_length;
+            int frame_num_in_poc_cycle = (abs_frame_num - 1) % sps->poc_cycle_length;
+
+            expectedpoc = poc_cycle_cnt * expected_delta_per_poc_cycle;
+            for (i = 0; i <= frame_num_in_poc_cycle; i++)
+                expectedpoc = expectedpoc + sps->offset_for_ref_frame[i];
+        } else
+            expectedpoc = 0;
+
+        if (nal_ref_idc == 0)
+            expectedpoc = expectedpoc + sps->offset_for_non_ref_pic;
+
+        field_poc[0] = expectedpoc + pc->delta_poc[0];
+        field_poc[1] = field_poc[0] + sps->offset_for_top_to_bottom_field;
+
+        if (picture_structure == PICT_FRAME)
+            field_poc[1] += pc->delta_poc[1];
+    } else {
+        int poc = 2 * (pc->frame_num_offset + pc->frame_num);
+
+        if (!nal_ref_idc)
+            poc--;
+
+        field_poc[0] = poc;
+        field_poc[1] = poc;
+    }
+
+    if (picture_structure != PICT_BOTTOM_FIELD)
+        pic_field_poc[0] = field_poc[0];
+    if (picture_structure != PICT_TOP_FIELD)
+        pic_field_poc[1] = field_poc[1];
+    *pic_poc = FFMIN(pic_field_poc[0], pic_field_poc[1]);
+
+    return 0;
+}
+
+static int decode_extradata_ps(const uint8_t *data, int size, H264ParamSets *ps,
+                               int is_avc, void *logctx)
+{
+    H2645Packet pkt = { 0 };
+    int i, ret = 0;
+
+    ret = ff_h2645_packet_split(&pkt, data, size, logctx, is_avc, 2, AV_CODEC_ID_H264);
+    if (ret < 0) {
+        ret = 0;
+        goto fail;
+    }
+
+    for (i = 0; i < pkt.nb_nals; i++) {
+        H2645NAL *nal = &pkt.nals[i];
+        switch (nal->type) {
+        case NAL_SPS:
+            ret = ff_h264_decode_seq_parameter_set(&nal->gb, logctx, ps, 0);
+            if (ret < 0)
+                goto fail;
+            break;
+        case NAL_PPS:
+            ret = ff_h264_decode_picture_parameter_set(&nal->gb, logctx, ps,
+                                                       nal->size_bits);
+            if (ret < 0)
+                goto fail;
+            break;
+        default:
+            av_log(logctx, AV_LOG_VERBOSE, "Ignoring NAL type %d in extradata\n",
+                   nal->type);
+            break;
+        }
+    }
+
+fail:
+    ff_h2645_packet_uninit(&pkt);
+    return ret;
+}
+
+/* There are (invalid) samples in the wild with mp4-style extradata, where the
+ * parameter sets are stored unescaped (i.e. as RBSP).
+ * This function catches the parameter set decoding failure and tries again
+ * after escaping it */
+static int decode_extradata_ps_mp4(const uint8_t *buf, int buf_size, H264ParamSets *ps,
+                                   int err_recognition, void *logctx)
+{
+    int ret;
+
+    ret = decode_extradata_ps(buf, buf_size, ps, 1, logctx);
+    if (ret < 0 && !(err_recognition & AV_EF_EXPLODE)) {
+        GetByteContext gbc;
+        PutByteContext pbc;
+        uint8_t *escaped_buf;
+        int escaped_buf_size;
+
+        av_log(logctx, AV_LOG_WARNING,
+               "SPS decoding failure, trying again after escaping the NAL\n");
+
+        if (buf_size / 2 >= (INT16_MAX - AV_INPUT_BUFFER_PADDING_SIZE) / 3)
+            return AVERROR(ERANGE);
+        escaped_buf_size = buf_size * 3 / 2 + AV_INPUT_BUFFER_PADDING_SIZE;
+        escaped_buf = av_mallocz(escaped_buf_size);
+        if (!escaped_buf)
+            return AVERROR(ENOMEM);
+
+        bytestream2_init(&gbc, buf, buf_size);
+        bytestream2_init_writer(&pbc, escaped_buf, escaped_buf_size);
+
+        while (bytestream2_get_bytes_left(&gbc)) {
+            if (bytestream2_get_bytes_left(&gbc) >= 3 &&
+                bytestream2_peek_be24(&gbc) <= 3) {
+                bytestream2_put_be24(&pbc, 3);
+                bytestream2_skip(&gbc, 2);
+            } else
+                bytestream2_put_byte(&pbc, bytestream2_get_byte(&gbc));
+        }
+
+        escaped_buf_size = bytestream2_tell_p(&pbc);
+        AV_WB16(escaped_buf, escaped_buf_size - 2);
+
+        ret = decode_extradata_ps(escaped_buf, escaped_buf_size, ps, 1, logctx);
+        av_freep(&escaped_buf);
+        if (ret < 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+int ff_h264_decode_extradata(const uint8_t *data, int size, H264ParamSets *ps,
+                             int *is_avc, int *nal_length_size,
+                             int err_recognition, void *logctx)
+{
+    int ret;
+
+    if (!data || size <= 0)
+        return -1;
+
+    if (data[0] == 1) {
+        int i, cnt, nalsize;
+        const uint8_t *p = data;
+
+        *is_avc = 1;
+
+        if (size < 7) {
+            av_log(logctx, AV_LOG_ERROR, "avcC %d too short\n", size);
+            return AVERROR_INVALIDDATA;
+        }
+
+        // Decode sps from avcC
+        cnt = *(p + 5) & 0x1f; // Number of sps
+        p  += 6;
+        for (i = 0; i < cnt; i++) {
+            nalsize = AV_RB16(p) + 2;
+            if (nalsize > size - (p - data))
+                return AVERROR_INVALIDDATA;
+            ret = decode_extradata_ps_mp4(p, nalsize, ps, err_recognition, logctx);
+            if (ret < 0) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "Decoding sps %d from avcC failed\n", i);
+                return ret;
+            }
+            p += nalsize;
+        }
+        // Decode pps from avcC
+        cnt = *(p++); // Number of pps
+        for (i = 0; i < cnt; i++) {
+            nalsize = AV_RB16(p) + 2;
+            if (nalsize > size - (p - data))
+                return AVERROR_INVALIDDATA;
+            ret = decode_extradata_ps_mp4(p, nalsize, ps, err_recognition, logctx);
+            if (ret < 0) {
+                av_log(logctx, AV_LOG_ERROR,
+                       "Decoding pps %d from avcC failed\n", i);
+                return ret;
+            }
+            p += nalsize;
+        }
+        // Store right nal length size that will be used to parse all other nals
+        *nal_length_size = (data[4] & 0x03) + 1;
+    } else {
+        *is_avc = 0;
+        ret = decode_extradata_ps(data, size, ps, 0, logctx);
+        if (ret < 0)
+            return ret;
+    }
+    return size;
+}
+
+/**
+ * Compute profile from profile_idc and constraint_set?_flags.
+ *
+ * @param sps SPS
+ *
+ * @return profile as defined by FF_PROFILE_H264_*
+ */
+int ff_h264_get_profile(const SPS *sps)
+{
+    int profile = sps->profile_idc;
+
+    switch (sps->profile_idc) {
+    case FF_PROFILE_H264_BASELINE:
+        // constraint_set1_flag set to 1
+        profile |= (sps->constraint_set_flags & 1 << 1) ? FF_PROFILE_H264_CONSTRAINED : 0;
+        break;
+    case FF_PROFILE_H264_HIGH_10:
+    case FF_PROFILE_H264_HIGH_422:
+    case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
+        // constraint_set3_flag set to 1
+        profile |= (sps->constraint_set_flags & 1 << 3) ? FF_PROFILE_H264_INTRA : 0;
+        break;
+    }
+
+    return profile;
+}
diff --git a/libavcodec/h264_parse.h b/libavcodec/h264_parse.h
new file mode 100644
index 0000000..40d88ed
--- /dev/null
+++ b/libavcodec/h264_parse.h
@@ -0,0 +1,95 @@
+/*
+ * 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
+ * H.264 decoder/parser shared code
+ */
+
+#ifndef AVCODEC_H264_PARSE_H
+#define AVCODEC_H264_PARSE_H
+
+#include "get_bits.h"
+
+typedef struct H264PredWeightTable {
+    int use_weight;
+    int use_weight_chroma;
+    int luma_log2_weight_denom;
+    int chroma_log2_weight_denom;
+    int luma_weight_flag[2];    ///< 7.4.3.2 luma_weight_lX_flag
+    int chroma_weight_flag[2];  ///< 7.4.3.2 chroma_weight_lX_flag
+    // The following 2 can be changed to int8_t but that causes a 10 CPU cycles speed loss
+    int luma_weight[48][2][2];
+    int chroma_weight[48][2][2][2];
+    int implicit_weight[48][48][2];
+} H264PredWeightTable;
+
+typedef struct H264POCContext {
+    int poc_lsb;
+    int poc_msb;
+    int delta_poc_bottom;
+    int delta_poc[2];
+    int frame_num;
+    int prev_poc_msb;           ///< poc_msb of the last reference pic for POC type 0
+    int prev_poc_lsb;           ///< poc_lsb of the last reference pic for POC type 0
+    int frame_num_offset;       ///< for POC type 2
+    int prev_frame_num_offset;  ///< for POC type 2
+    int prev_frame_num;         ///< frame_num of the last pic for POC type 1/2
+} H264POCContext;
+
+struct SPS;
+struct PPS;
+struct H264ParamSets;
+
+int ff_h264_pred_weight_table(GetBitContext *gb, const struct SPS *sps,
+                              const int *ref_count, int slice_type_nos,
+                              H264PredWeightTable *pwt, void *logctx);
+
+/**
+ * Check if the top & left blocks are available if needed & change the
+ * dc mode so it only uses the available blocks.
+ */
+int ff_h264_check_intra4x4_pred_mode(int8_t *pred_mode_cache, void *logctx,
+                                     int top_samples_available, int left_samples_available);
+
+/**
+ * Check if the top & left blocks are available if needed & change the
+ * dc mode so it only uses the available blocks.
+ */
+int ff_h264_check_intra_pred_mode(void *logctx, int top_samples_available,
+                                  int left_samples_available,
+                                  int mode, int is_chroma);
+
+int ff_h264_parse_ref_count(int *plist_count, int ref_count[2],
+                            GetBitContext *gb, const struct PPS *pps,
+                            int slice_type_nos, int picture_structure, void *logctx);
+
+int ff_h264_init_poc(int pic_field_poc[2], int *pic_poc,
+                     const struct SPS *sps, H264POCContext *poc,
+                     int picture_structure, int nal_ref_idc);
+
+int ff_h264_decode_extradata(const uint8_t *data, int size, struct H264ParamSets *ps,
+                             int *is_avc, int *nal_length_size,
+                             int err_recognition, void *logctx);
+
+/**
+ * compute profile from sps
+ */
+int ff_h264_get_profile(const struct SPS *sps);
+
+#endif /* AVCODEC_H264_PARSE_H */
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index 12d6397..ce4bab2 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -21,51 +21,70 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 parser.
+ * H.264 / AVC / MPEG-4 part10 parser.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
 #define UNCHECKED_BITSTREAM_READER 1
 
-#include "libavutil/attributes.h"
-#include "parser.h"
-#include "h264data.h"
+#include <assert.h>
+#include <stdint.h>
+
+#include "libavutil/avutil.h"
+#include "libavutil/error.h"
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+#include "libavutil/pixfmt.h"
+
+#include "get_bits.h"
 #include "golomb.h"
+#include "h264.h"
+#include "h264_sei.h"
+#include "h264data.h"
 #include "internal.h"
 #include "mpegutils.h"
+#include "parser.h"
 
 typedef struct H264ParseContext {
-    H264Context h;
     ParseContext pc;
+    H264ParamSets ps;
+    H264DSPContext h264dsp;
+    H264POCContext poc;
+    H264SEIContext sei;
+    int is_avc;
+    int nal_length_size;
     int got_first;
+    int picture_structure;
+    uint8_t parse_history[6];
+    int parse_history_count;
+    int parse_last_mb;
 } H264ParseContext;
 
 
 static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf,
-                               int buf_size)
+                               int buf_size, void *logctx)
 {
-    H264Context *h = &p->h;
     int i, j;
     uint32_t state;
     ParseContext *pc = &p->pc;
 
-    int next_avc= h->is_avc ? 0 : buf_size;
+    int next_avc = p->is_avc ? 0 : buf_size;
 //    mb_addr= pc->mb_addr - 1;
     state = pc->state;
     if (state > 13)
         state = 7;
 
-    if (h->is_avc && !h->nal_length_size)
-        av_log(h->avctx, AV_LOG_ERROR, "AVC-parser: nal length size invalid\n");
+    if (p->is_avc && !p->nal_length_size)
+        av_log(logctx, AV_LOG_ERROR, "AVC-parser: nal length size invalid\n");
 
     for (i = 0; i < buf_size; i++) {
         if (i >= next_avc) {
             int nalsize = 0;
             i = next_avc;
-            for (j = 0; j < h->nal_length_size; j++)
+            for (j = 0; j < p->nal_length_size; j++)
                 nalsize = (nalsize << 8) | buf[i++];
             if (nalsize <= 0 || nalsize > buf_size - i) {
-                av_log(h->avctx, AV_LOG_ERROR, "AVC-parser: nal size %d remaining %d\n", nalsize, buf_size - i);
+                av_log(logctx, AV_LOG_ERROR, "AVC-parser: nal size %d remaining %d\n", nalsize, buf_size - i);
                 return buf_size;
             }
             next_avc = i + nalsize;
@@ -73,7 +92,7 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf,
         }
 
         if (state == 7) {
-            i += h->h264dsp.startcode_find_candidate(buf + i, next_avc - i);
+            i += p->h264dsp.startcode_find_candidate(buf + i, next_avc - i);
             if (i < next_avc)
                 state = 2;
         } else if (state <= 2) {
@@ -98,15 +117,15 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf,
             }
             state = 7;
         } else {
-            h->parse_history[h->parse_history_count++]= buf[i];
-            if (h->parse_history_count>5) {
-                unsigned int mb, last_mb= h->parse_last_mb;
+            p->parse_history[p->parse_history_count++] = buf[i];
+            if (p->parse_history_count > 5) {
+                unsigned int mb, last_mb = p->parse_last_mb;
                 GetBitContext gb;
 
-                init_get_bits(&gb, h->parse_history, 8*h->parse_history_count);
-                h->parse_history_count=0;
+                init_get_bits(&gb, p->parse_history, 8*p->parse_history_count);
+                p->parse_history_count = 0;
                 mb= get_ue_golomb_long(&gb);
-                h->parse_last_mb= mb;
+                p->parse_last_mb = mb;
                 if (pc->frame_start_found) {
                     if (mb <= last_mb)
                         goto found;
@@ -117,52 +136,57 @@ static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf,
         }
     }
     pc->state = state;
-    if (h->is_avc)
+    if (p->is_avc)
         return next_avc;
     return END_NOT_FOUND;
 
 found:
     pc->state             = 7;
     pc->frame_start_found = 0;
-    if (h->is_avc)
+    if (p->is_avc)
         return next_avc;
     return i - (state & 5) - 5 * (state > 7);
 }
 
-static int scan_mmco_reset(AVCodecParserContext *s)
+static int scan_mmco_reset(AVCodecParserContext *s, GetBitContext *gb,
+                           void *logctx)
 {
+    H264PredWeightTable pwt;
+    int slice_type_nos = s->pict_type & 3;
     H264ParseContext *p = s->priv_data;
-    H264Context      *h = &p->h;
-    H264SliceContext *sl = &h->slice_ctx[0];
+    int list_count, ref_count[2];
 
-    sl->slice_type_nos = s->pict_type & 3;
 
-    if (h->pps.redundant_pic_cnt_present)
-        get_ue_golomb(&sl->gb); // redundant_pic_count
+    if (p->ps.pps->redundant_pic_cnt_present)
+        get_ue_golomb(gb); // redundant_pic_count
 
-    if (ff_set_ref_count(h, sl) < 0)
+    if (slice_type_nos == AV_PICTURE_TYPE_B)
+        get_bits1(gb); // direct_spatial_mv_pred
+
+    if (ff_h264_parse_ref_count(&list_count, ref_count, gb, p->ps.pps,
+                                slice_type_nos, p->picture_structure, logctx) < 0)
         return AVERROR_INVALIDDATA;
 
-    if (sl->slice_type_nos != AV_PICTURE_TYPE_I) {
+    if (slice_type_nos != AV_PICTURE_TYPE_I) {
         int list;
-        for (list = 0; list < sl->list_count; list++) {
-            if (get_bits1(&sl->gb)) {
+        for (list = 0; list < list_count; list++) {
+            if (get_bits1(gb)) {
                 int index;
                 for (index = 0; ; index++) {
-                    unsigned int reordering_of_pic_nums_idc = get_ue_golomb_31(&sl->gb);
+                    unsigned int reordering_of_pic_nums_idc = get_ue_golomb_31(gb);
 
                     if (reordering_of_pic_nums_idc < 3)
-                        get_ue_golomb_long(&sl->gb);
+                        get_ue_golomb_long(gb);
                     else if (reordering_of_pic_nums_idc > 3) {
-                        av_log(h->avctx, AV_LOG_ERROR,
+                        av_log(logctx, AV_LOG_ERROR,
                                "illegal reordering_of_pic_nums_idc %d\n",
                                reordering_of_pic_nums_idc);
                         return AVERROR_INVALIDDATA;
                     } else
                         break;
 
-                    if (index >= sl->ref_count[list]) {
-                        av_log(h->avctx, AV_LOG_ERROR,
+                    if (index >= ref_count[list]) {
+                        av_log(logctx, AV_LOG_ERROR,
                                "reference count %d overflow\n", index);
                         return AVERROR_INVALIDDATA;
                     }
@@ -171,16 +195,17 @@ static int scan_mmco_reset(AVCodecParserContext *s)
         }
     }
 
-    if ((h->pps.weighted_pred && sl->slice_type_nos == AV_PICTURE_TYPE_P) ||
-        (h->pps.weighted_bipred_idc == 1 && sl->slice_type_nos == AV_PICTURE_TYPE_B))
-        ff_pred_weight_table(h, sl);
+    if ((p->ps.pps->weighted_pred && slice_type_nos == AV_PICTURE_TYPE_P) ||
+        (p->ps.pps->weighted_bipred_idc == 1 && slice_type_nos == AV_PICTURE_TYPE_B))
+        ff_h264_pred_weight_table(gb, p->ps.sps, ref_count, slice_type_nos,
+                                  &pwt, logctx);
 
-    if (get_bits1(&sl->gb)) { // adaptive_ref_pic_marking_mode_flag
+    if (get_bits1(gb)) { // adaptive_ref_pic_marking_mode_flag
         int i;
         for (i = 0; i < MAX_MMCO_COUNT; i++) {
-            MMCOOpcode opcode = get_ue_golomb_31(&sl->gb);
+            MMCOOpcode opcode = get_ue_golomb_31(gb);
             if (opcode > (unsigned) MMCO_LONG) {
-                av_log(h->avctx, AV_LOG_ERROR,
+                av_log(logctx, AV_LOG_ERROR,
                        "illegal memory management control operation %d\n",
                        opcode);
                 return AVERROR_INVALIDDATA;
@@ -191,16 +216,36 @@ static int scan_mmco_reset(AVCodecParserContext *s)
                 return 1;
 
             if (opcode == MMCO_SHORT2UNUSED || opcode == MMCO_SHORT2LONG)
-                get_ue_golomb_long(&sl->gb); // difference_of_pic_nums_minus1
+                get_ue_golomb_long(gb); // difference_of_pic_nums_minus1
             if (opcode == MMCO_SHORT2LONG || opcode == MMCO_LONG2UNUSED ||
                 opcode == MMCO_LONG || opcode == MMCO_SET_MAX_LONG)
-                get_ue_golomb_31(&sl->gb);
+                get_ue_golomb_31(gb);
         }
     }
 
     return 0;
 }
 
+static inline int get_avc_nalsize(H264ParseContext *p, const uint8_t *buf,
+                                  int buf_size, int *buf_index, void *logctx)
+{
+    int i, nalsize = 0;
+
+    if (*buf_index >= buf_size - p->nal_length_size) {
+        // the end of the buffer is reached, refill it
+        return AVERROR(EAGAIN);
+    }
+
+    for (i = 0; i < p->nal_length_size; i++)
+        nalsize = ((unsigned)nalsize << 8) | buf[(*buf_index)++];
+    if (nalsize <= 0 || nalsize > buf_size - *buf_index) {
+        av_log(logctx, AV_LOG_ERROR,
+               "AVC: nal size %d\n", nalsize);
+        return AVERROR_INVALIDDATA;
+    }
+    return nalsize;
+}
+
 /**
  * Parse NAL units of found picture and decode some basic information.
  *
@@ -214,35 +259,34 @@ static inline int parse_nal_units(AVCodecParserContext *s,
                                   const uint8_t * const buf, int buf_size)
 {
     H264ParseContext *p = s->priv_data;
-    H264Context      *h = &p->h;
-    H264SliceContext *sl = &h->slice_ctx[0];
+    H2645NAL nal = { NULL };
     int buf_index, next_avc;
     unsigned int pps_id;
     unsigned int slice_type;
     int state = -1, got_reset = 0;
-    const uint8_t *ptr;
     int q264 = buf_size >=4 && !memcmp("Q264", buf, 4);
     int field_poc[2];
+    int ret;
 
     /* set some sane default values */
     s->pict_type         = AV_PICTURE_TYPE_I;
     s->key_frame         = 0;
     s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
 
-    h->avctx = avctx;
-    ff_h264_reset_sei(h);
-    h->sei_fpa.frame_packing_arrangement_cancel_flag = -1;
+    ff_h264_sei_uninit(&p->sei);
+    p->sei.frame_packing.frame_packing_arrangement_cancel_flag = -1;
 
     if (!buf_size)
         return 0;
 
     buf_index     = 0;
-    next_avc      = h->is_avc ? 0 : buf_size;
+    next_avc      = p->is_avc ? 0 : buf_size;
     for (;;) {
-        int src_length, dst_length, consumed, nalsize = 0;
+        const SPS *sps;
+        int src_length, consumed, nalsize = 0;
 
         if (buf_index >= next_avc) {
-            nalsize = get_avc_nalsize(h, buf, buf_size, &buf_index);
+            nalsize = get_avc_nalsize(p, buf, buf_size, &buf_index, avctx);
             if (nalsize < 0)
                 break;
             next_avc = buf_index + nalsize;
@@ -272,156 +316,166 @@ static inline int parse_nal_units(AVCodecParserContext *s,
             }
             break;
         }
-        ptr = ff_h264_decode_nal(h, sl, buf + buf_index, &dst_length,
-                                 &consumed, src_length);
-        if (!ptr || dst_length < 0)
+        consumed = ff_h2645_extract_rbsp(buf + buf_index, src_length, &nal);
+        if (consumed < 0)
             break;
 
         buf_index += consumed;
 
-        init_get_bits(&h->gb, ptr, 8 * dst_length);
-        switch (h->nal_unit_type) {
+        ret = init_get_bits8(&nal.gb, nal.data, nal.size);
+        if (ret < 0)
+            goto fail;
+        get_bits1(&nal.gb);
+        nal.ref_idc = get_bits(&nal.gb, 2);
+        nal.type    = get_bits(&nal.gb, 5);
+
+        switch (nal.type) {
         case NAL_SPS:
-            ff_h264_decode_seq_parameter_set(h, 0);
+            ff_h264_decode_seq_parameter_set(&nal.gb, avctx, &p->ps, 0);
             break;
         case NAL_PPS:
-            ff_h264_decode_picture_parameter_set(h, h->gb.size_in_bits);
+            ff_h264_decode_picture_parameter_set(&nal.gb, avctx, &p->ps,
+                                                 nal.size_bits);
             break;
         case NAL_SEI:
-            ff_h264_decode_sei(h);
+            ff_h264_sei_decode(&p->sei, &nal.gb, &p->ps, avctx);
             break;
         case NAL_IDR_SLICE:
             s->key_frame = 1;
 
-            h->prev_frame_num        = 0;
-            h->prev_frame_num_offset = 0;
-            h->prev_poc_msb          =
-            h->prev_poc_lsb          = 0;
+            p->poc.prev_frame_num        = 0;
+            p->poc.prev_frame_num_offset = 0;
+            p->poc.prev_poc_msb          =
+            p->poc.prev_poc_lsb          = 0;
         /* fall through */
         case NAL_SLICE:
-            init_get_bits(&sl->gb, ptr, 8 * dst_length);
-            get_ue_golomb_long(&sl->gb);  // skip first_mb_in_slice
-            slice_type   = get_ue_golomb_31(&sl->gb);
-            s->pict_type = golomb_to_pict_type[slice_type % 5];
-            if (h->sei_recovery_frame_cnt >= 0) {
+            get_ue_golomb_long(&nal.gb);  // skip first_mb_in_slice
+            slice_type   = get_ue_golomb_31(&nal.gb);
+            s->pict_type = ff_h264_golomb_to_pict_type[slice_type % 5];
+            if (p->sei.recovery_point.recovery_frame_cnt >= 0) {
                 /* key frame, since recovery_frame_cnt is set */
                 s->key_frame = 1;
             }
-            pps_id = get_ue_golomb(&sl->gb);
+            pps_id = get_ue_golomb(&nal.gb);
             if (pps_id >= MAX_PPS_COUNT) {
-                av_log(h->avctx, AV_LOG_ERROR,
+                av_log(avctx, AV_LOG_ERROR,
                        "pps_id %u out of range\n", pps_id);
-                return -1;
+                goto fail;
             }
-            if (!h->pps_buffers[pps_id]) {
-                av_log(h->avctx, AV_LOG_ERROR,
+            if (!p->ps.pps_list[pps_id]) {
+                av_log(avctx, AV_LOG_ERROR,
                        "non-existing PPS %u referenced\n", pps_id);
-                return -1;
+                goto fail;
             }
-            h->pps = *h->pps_buffers[pps_id];
-            if (!h->sps_buffers[h->pps.sps_id]) {
-                av_log(h->avctx, AV_LOG_ERROR,
-                       "non-existing SPS %u referenced\n", h->pps.sps_id);
-                return -1;
+            p->ps.pps = (const PPS*)p->ps.pps_list[pps_id]->data;
+            if (!p->ps.sps_list[p->ps.pps->sps_id]) {
+                av_log(avctx, AV_LOG_ERROR,
+                       "non-existing SPS %u referenced\n", p->ps.pps->sps_id);
+                goto fail;
             }
-            h->sps       = *h->sps_buffers[h->pps.sps_id];
-            h->frame_num = get_bits(&sl->gb, h->sps.log2_max_frame_num);
+            p->ps.sps = (SPS*)p->ps.sps_list[p->ps.pps->sps_id]->data;
+
+            sps = p->ps.sps;
 
-            if(h->sps.ref_frame_count <= 1 && h->pps.ref_count[0] <= 1 && s->pict_type == AV_PICTURE_TYPE_I)
+            // heuristic to detect non marked keyframes
+            if (p->ps.sps->ref_frame_count <= 1 && p->ps.pps->ref_count[0] <= 1 && s->pict_type == AV_PICTURE_TYPE_I)
                 s->key_frame = 1;
 
-            s->coded_width  = 16 * h->sps.mb_width;
-            s->coded_height = 16 * h->sps.mb_height;
-            s->width        = s->coded_width  - (h->sps.crop_right + h->sps.crop_left);
-            s->height       = s->coded_height - (h->sps.crop_top   + h->sps.crop_bottom);
+            p->poc.frame_num = get_bits(&nal.gb, sps->log2_max_frame_num);
+
+            s->coded_width  = 16 * sps->mb_width;
+            s->coded_height = 16 * sps->mb_height;
+            s->width        = s->coded_width  - (sps->crop_right + sps->crop_left);
+            s->height       = s->coded_height - (sps->crop_top   + sps->crop_bottom);
             if (s->width <= 0 || s->height <= 0) {
                 s->width  = s->coded_width;
                 s->height = s->coded_height;
             }
 
-            switch (h->sps.bit_depth_luma) {
+            switch (sps->bit_depth_luma) {
             case 9:
-                if (CHROMA444(h))      s->format = AV_PIX_FMT_YUV444P9;
-                else if (CHROMA422(h)) s->format = AV_PIX_FMT_YUV422P9;
-                else                   s->format = AV_PIX_FMT_YUV420P9;
+                if (sps->chroma_format_idc == 3)      s->format = AV_PIX_FMT_YUV444P9;
+                else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P9;
+                else                                  s->format = AV_PIX_FMT_YUV420P9;
                 break;
             case 10:
-                if (CHROMA444(h))      s->format = AV_PIX_FMT_YUV444P10;
-                else if (CHROMA422(h)) s->format = AV_PIX_FMT_YUV422P10;
-                else                   s->format = AV_PIX_FMT_YUV420P10;
+                if (sps->chroma_format_idc == 3)      s->format = AV_PIX_FMT_YUV444P10;
+                else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P10;
+                else                                  s->format = AV_PIX_FMT_YUV420P10;
                 break;
             case 8:
-                if (CHROMA444(h))      s->format = AV_PIX_FMT_YUV444P;
-                else if (CHROMA422(h)) s->format = AV_PIX_FMT_YUV422P;
-                else                   s->format = AV_PIX_FMT_YUV420P;
+                if (sps->chroma_format_idc == 3)      s->format = AV_PIX_FMT_YUV444P;
+                else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P;
+                else                                  s->format = AV_PIX_FMT_YUV420P;
                 break;
             default:
                 s->format = AV_PIX_FMT_NONE;
             }
 
-            avctx->profile = ff_h264_get_profile(&h->sps);
-            avctx->level   = h->sps.level_idc;
+            avctx->profile = ff_h264_get_profile(sps);
+            avctx->level   = sps->level_idc;
 
-            if (h->sps.frame_mbs_only_flag) {
-                h->picture_structure = PICT_FRAME;
+            if (sps->frame_mbs_only_flag) {
+                p->picture_structure = PICT_FRAME;
             } else {
-                if (get_bits1(&sl->gb)) { // field_pic_flag
-                    h->picture_structure = PICT_TOP_FIELD + get_bits1(&sl->gb); // bottom_field_flag
+                if (get_bits1(&nal.gb)) { // field_pic_flag
+                    p->picture_structure = PICT_TOP_FIELD + get_bits1(&nal.gb); // bottom_field_flag
                 } else {
-                    h->picture_structure = PICT_FRAME;
+                    p->picture_structure = PICT_FRAME;
                 }
             }
 
-            if (h->nal_unit_type == NAL_IDR_SLICE)
-                get_ue_golomb_long(&sl->gb); /* idr_pic_id */
-            if (h->sps.poc_type == 0) {
-                h->poc_lsb = get_bits(&sl->gb, h->sps.log2_max_poc_lsb);
+            if (nal.type == NAL_IDR_SLICE)
+                get_ue_golomb_long(&nal.gb); /* idr_pic_id */
+            if (sps->poc_type == 0) {
+                p->poc.poc_lsb = get_bits(&nal.gb, sps->log2_max_poc_lsb);
 
-                if (h->pps.pic_order_present == 1 &&
-                    h->picture_structure == PICT_FRAME)
-                    h->delta_poc_bottom = get_se_golomb(&sl->gb);
+                if (p->ps.pps->pic_order_present == 1 &&
+                    p->picture_structure == PICT_FRAME)
+                    p->poc.delta_poc_bottom = get_se_golomb(&nal.gb);
             }
 
-            if (h->sps.poc_type == 1 &&
-                !h->sps.delta_pic_order_always_zero_flag) {
-                h->delta_poc[0] = get_se_golomb(&sl->gb);
+            if (sps->poc_type == 1 &&
+                !sps->delta_pic_order_always_zero_flag) {
+                p->poc.delta_poc[0] = get_se_golomb(&nal.gb);
 
-                if (h->pps.pic_order_present == 1 &&
-                    h->picture_structure == PICT_FRAME)
-                    h->delta_poc[1] = get_se_golomb(&sl->gb);
+                if (p->ps.pps->pic_order_present == 1 &&
+                    p->picture_structure == PICT_FRAME)
+                    p->poc.delta_poc[1] = get_se_golomb(&nal.gb);
             }
 
             /* Decode POC of this picture.
              * The prev_ values needed for decoding POC of the next picture are not set here. */
             field_poc[0] = field_poc[1] = INT_MAX;
-            ff_init_poc(h, field_poc, &s->output_picture_number);
+            ff_h264_init_poc(field_poc, &s->output_picture_number, sps,
+                             &p->poc, p->picture_structure, nal.ref_idc);
 
             /* Continue parsing to check if MMCO_RESET is present.
              * FIXME: MMCO_RESET could appear in non-first slice.
              *        Maybe, we should parse all undisposable non-IDR slice of this
              *        picture until encountering MMCO_RESET in a slice of it. */
-            if (h->nal_ref_idc && h->nal_unit_type != NAL_IDR_SLICE) {
-                got_reset = scan_mmco_reset(s);
+            if (nal.ref_idc && nal.type != NAL_IDR_SLICE) {
+                got_reset = scan_mmco_reset(s, &nal.gb, avctx);
                 if (got_reset < 0)
-                    return got_reset;
+                    goto fail;
             }
 
             /* Set up the prev_ values for decoding POC of the next picture. */
-            h->prev_frame_num        = got_reset ? 0 : h->frame_num;
-            h->prev_frame_num_offset = got_reset ? 0 : h->frame_num_offset;
-            if (h->nal_ref_idc != 0) {
+            p->poc.prev_frame_num        = got_reset ? 0 : p->poc.frame_num;
+            p->poc.prev_frame_num_offset = got_reset ? 0 : p->poc.frame_num_offset;
+            if (nal.ref_idc != 0) {
                 if (!got_reset) {
-                    h->prev_poc_msb = h->poc_msb;
-                    h->prev_poc_lsb = h->poc_lsb;
+                    p->poc.prev_poc_msb = p->poc.poc_msb;
+                    p->poc.prev_poc_lsb = p->poc.poc_lsb;
                 } else {
-                    h->prev_poc_msb = 0;
-                    h->prev_poc_lsb =
-                        h->picture_structure == PICT_BOTTOM_FIELD ? 0 : field_poc[0];
+                    p->poc.prev_poc_msb = 0;
+                    p->poc.prev_poc_lsb =
+                        p->picture_structure == PICT_BOTTOM_FIELD ? 0 : field_poc[0];
                 }
             }
 
-            if (h->sps.pic_struct_present_flag) {
-                switch (h->sei_pic_struct) {
+            if (sps->pic_struct_present_flag) {
+                switch (p->sei.picture_timing.pic_struct) {
                 case SEI_PIC_STRUCT_TOP_FIELD:
                 case SEI_PIC_STRUCT_BOTTOM_FIELD:
                     s->repeat_pict = 0;
@@ -442,17 +496,17 @@ static inline int parse_nal_units(AVCodecParserContext *s,
                     s->repeat_pict = 5;
                     break;
                 default:
-                    s->repeat_pict = h->picture_structure == PICT_FRAME ? 1 : 0;
+                    s->repeat_pict = p->picture_structure == PICT_FRAME ? 1 : 0;
                     break;
                 }
             } else {
-                s->repeat_pict = h->picture_structure == PICT_FRAME ? 1 : 0;
+                s->repeat_pict = p->picture_structure == PICT_FRAME ? 1 : 0;
             }
 
-            if (h->picture_structure == PICT_FRAME) {
+            if (p->picture_structure == PICT_FRAME) {
                 s->picture_structure = AV_PICTURE_STRUCTURE_FRAME;
-                if (h->sps.pic_struct_present_flag) {
-                    switch (h->sei_pic_struct) {
+                if (sps->pic_struct_present_flag) {
+                    switch (p->sei.picture_timing.pic_struct) {
                     case SEI_PIC_STRUCT_TOP_BOTTOM:
                     case SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
                         s->field_order = AV_FIELD_TT;
@@ -474,20 +528,25 @@ static inline int parse_nal_units(AVCodecParserContext *s,
                         s->field_order = AV_FIELD_PROGRESSIVE;
                 }
             } else {
-                if (h->picture_structure == PICT_TOP_FIELD)
+                if (p->picture_structure == PICT_TOP_FIELD)
                     s->picture_structure = AV_PICTURE_STRUCTURE_TOP_FIELD;
                 else
                     s->picture_structure = AV_PICTURE_STRUCTURE_BOTTOM_FIELD;
                 s->field_order = AV_FIELD_UNKNOWN;
             }
 
+            av_freep(&nal.rbsp_buffer);
             return 0; /* no need to evaluate the rest */
         }
     }
-    if (q264)
+    if (q264) {
+        av_freep(&nal.rbsp_buffer);
         return 0;
+    }
     /* didn't find a picture! */
-    av_log(h->avctx, AV_LOG_ERROR, "missing picture in access unit with size %d\n", buf_size);
+    av_log(avctx, AV_LOG_ERROR, "missing picture in access unit with size %d\n", buf_size);
+fail:
+    av_freep(&nal.rbsp_buffer);
     return -1;
 }
 
@@ -497,28 +556,22 @@ static int h264_parse(AVCodecParserContext *s,
                       const uint8_t *buf, int buf_size)
 {
     H264ParseContext *p = s->priv_data;
-    H264Context      *h = &p->h;
     ParseContext *pc = &p->pc;
     int next;
 
     if (!p->got_first) {
         p->got_first = 1;
         if (avctx->extradata_size) {
-            h->avctx = avctx;
-            // must be done like in decoder, otherwise opening the parser,
-            // letting it create extradata and then closing and opening again
-            // will cause has_b_frames to be always set.
-            // Note that estimate_timings_from_pts does exactly this.
-            if (!avctx->has_b_frames)
-                h->low_delay = 1;
-            ff_h264_decode_extradata(h, avctx->extradata, avctx->extradata_size);
+            ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
+                                     &p->ps, &p->is_avc, &p->nal_length_size,
+                                     avctx->err_recognition, avctx);
         }
     }
 
     if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
         next = buf_size;
     } else {
-        next = h264_find_frame_end(p, buf, buf_size);
+        next = h264_find_frame_end(p, buf, buf_size, avctx);
 
         if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
             *poutbuf      = NULL;
@@ -528,7 +581,7 @@ static int h264_parse(AVCodecParserContext *s,
 
         if (next < 0 && next != END_NOT_FOUND) {
             av_assert1(pc->last_index + next >= 0);
-            h264_find_frame_end(p, &pc->buffer[pc->last_index + next], -next); // update state
+            h264_find_frame_end(p, &pc->buffer[pc->last_index + next], -next, avctx); // update state
         }
     }
 
@@ -536,10 +589,10 @@ static int h264_parse(AVCodecParserContext *s,
 
     if (avctx->framerate.num)
         avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1}));
-    if (h->sei_cpb_removal_delay >= 0) {
-        s->dts_sync_point    = h->sei_buffering_period_present;
-        s->dts_ref_dts_delta = h->sei_cpb_removal_delay;
-        s->pts_dts_delta     = h->sei_dpb_output_delay;
+    if (p->sei.picture_timing.cpb_removal_delay >= 0) {
+        s->dts_sync_point    = p->sei.buffering_period.present;
+        s->dts_ref_dts_delta = p->sei.picture_timing.cpb_removal_delay;
+        s->pts_dts_delta     = p->sei.picture_timing.dpb_output_delay;
     } else {
         s->dts_sync_point    = INT_MIN;
         s->dts_ref_dts_delta = INT_MIN;
@@ -595,25 +648,19 @@ static int h264_split(AVCodecContext *avctx,
 static void h264_close(AVCodecParserContext *s)
 {
     H264ParseContext *p = s->priv_data;
-    H264Context      *h = &p->h;
     ParseContext *pc = &p->pc;
 
     av_freep(&pc->buffer);
-    ff_h264_free_context(h);
+
+    ff_h264_sei_uninit(&p->sei);
+    ff_h264_ps_uninit(&p->ps);
 }
 
 static av_cold int init(AVCodecParserContext *s)
 {
     H264ParseContext *p = s->priv_data;
-    H264Context      *h = &p->h;
-
-    h->slice_ctx = av_mallocz(sizeof(*h->slice_ctx));
-    if (!h->slice_ctx)
-        return 0;
-    h->nb_slice_ctx = 1;
 
-    h->slice_context_count = 1;
-    ff_h264dsp_init(&h->h264dsp, 8, 1);
+    ff_h264dsp_init(&p->h264dsp, 8, 1);
     return 0;
 }
 
diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c
index c4b17c0..3e9b79a 100644
--- a/libavcodec/h264_picture.c
+++ b/libavcodec/h264_picture.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 codec.
+ * H.264 / AVC / MPEG-4 part10 codec.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -166,11 +166,11 @@ int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup)
     if (in_setup || !(avctx->active_thread_type & FF_THREAD_FRAME)) {
         if (!h->droppable) {
             err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index);
-            h->prev_poc_msb = h->poc_msb;
-            h->prev_poc_lsb = h->poc_lsb;
+            h->poc.prev_poc_msb = h->poc.poc_msb;
+            h->poc.prev_poc_lsb = h->poc.poc_lsb;
         }
-        h->prev_frame_num_offset = h->frame_num_offset;
-        h->prev_frame_num        = h->frame_num;
+        h->poc.prev_frame_num_offset = h->poc.frame_num_offset;
+        h->poc.prev_frame_num        = h->poc.frame_num;
     }
 
     if (avctx->hwaccel) {
diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c
index 0bca9c1..943d953 100644
--- a/libavcodec/h264_ps.c
+++ b/libavcodec/h264_ps.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 parameter set decoding.
+ * H.264 / AVC / MPEG-4 part10 parameter set decoding.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -29,6 +29,7 @@
 
 #include "libavutil/imgutils.h"
 #include "internal.h"
+#include "mathops.h"
 #include "avcodec.h"
 #include "h264.h"
 #include "h264data.h"
@@ -37,50 +38,6 @@
 #define MAX_LOG2_MAX_FRAME_NUM    (12 + 4)
 #define MIN_LOG2_MAX_FRAME_NUM    4
 
-#define QP(qP, depth) ((qP) + 6 * ((depth) - 8))
-
-#define CHROMA_QP_TABLE_END(d)                                          \
-    QP(0,  d), QP(1,  d), QP(2,  d), QP(3,  d), QP(4,  d), QP(5,  d),   \
-    QP(6,  d), QP(7,  d), QP(8,  d), QP(9,  d), QP(10, d), QP(11, d),   \
-    QP(12, d), QP(13, d), QP(14, d), QP(15, d), QP(16, d), QP(17, d),   \
-    QP(18, d), QP(19, d), QP(20, d), QP(21, d), QP(22, d), QP(23, d),   \
-    QP(24, d), QP(25, d), QP(26, d), QP(27, d), QP(28, d), QP(29, d),   \
-    QP(29, d), QP(30, d), QP(31, d), QP(32, d), QP(32, d), QP(33, d),   \
-    QP(34, d), QP(34, d), QP(35, d), QP(35, d), QP(36, d), QP(36, d),   \
-    QP(37, d), QP(37, d), QP(37, d), QP(38, d), QP(38, d), QP(38, d),   \
-    QP(39, d), QP(39, d), QP(39, d), QP(39, d)
-
-const uint8_t ff_h264_chroma_qp[7][QP_MAX_NUM + 1] = {
-    { CHROMA_QP_TABLE_END(8) },
-    { 0, 1, 2, 3, 4, 5,
-      CHROMA_QP_TABLE_END(9) },
-    { 0, 1, 2, 3,  4,  5,
-      6, 7, 8, 9, 10, 11,
-      CHROMA_QP_TABLE_END(10) },
-    { 0,  1, 2, 3,  4,  5,
-      6,  7, 8, 9, 10, 11,
-      12,13,14,15, 16, 17,
-      CHROMA_QP_TABLE_END(11) },
-    { 0,  1, 2, 3,  4,  5,
-      6,  7, 8, 9, 10, 11,
-      12,13,14,15, 16, 17,
-      18,19,20,21, 22, 23,
-      CHROMA_QP_TABLE_END(12) },
-    { 0,  1, 2, 3,  4,  5,
-      6,  7, 8, 9, 10, 11,
-      12,13,14,15, 16, 17,
-      18,19,20,21, 22, 23,
-      24,25,26,27, 28, 29,
-      CHROMA_QP_TABLE_END(13) },
-    { 0,  1, 2, 3,  4,  5,
-      6,  7, 8, 9, 10, 11,
-      12,13,14,15, 16, 17,
-      18,19,20,21, 22, 23,
-      24,25,26,27, 28, 29,
-      30,31,32,33, 34, 35,
-      CHROMA_QP_TABLE_END(14) },
-};
-
 static const uint8_t default_scaling4[2][16] = {
     {  6, 13, 20, 28, 13, 20, 28, 32,
       20, 28, 32, 37, 28, 32, 37, 42 },
@@ -127,47 +84,68 @@ static const int level_max_dpb_mbs[][2] = {
     { 52, 184320    },
 };
 
-static inline int decode_hrd_parameters(H264Context *h, SPS *sps)
+static void remove_pps(H264ParamSets *s, int id)
+{
+    av_buffer_unref(&s->pps_list[id]);
+}
+
+static void remove_sps(H264ParamSets *s, int id)
+{
+#if 0
+    int i;
+    if (s->sps_list[id]) {
+        /* drop all PPS that depend on this SPS */
+        for (i = 0; i < FF_ARRAY_ELEMS(s->pps_list); i++)
+            if (s->pps_list[i] && ((PPS*)s->pps_list[i]->data)->sps_id == id)
+                remove_pps(s, i);
+    }
+#endif
+    av_buffer_unref(&s->sps_list[id]);
+}
+
+static inline int decode_hrd_parameters(GetBitContext *gb, AVCodecContext *avctx,
+                                        SPS *sps)
 {
     int cpb_count, i;
-    cpb_count = get_ue_golomb_31(&h->gb) + 1;
+    cpb_count = get_ue_golomb_31(gb) + 1;
 
     if (cpb_count > 32U) {
-        av_log(h->avctx, AV_LOG_ERROR, "cpb_count %d invalid\n", cpb_count);
+        av_log(avctx, AV_LOG_ERROR, "cpb_count %d invalid\n", cpb_count);
         return AVERROR_INVALIDDATA;
     }
 
-    get_bits(&h->gb, 4); /* bit_rate_scale */
-    get_bits(&h->gb, 4); /* cpb_size_scale */
+    get_bits(gb, 4); /* bit_rate_scale */
+    get_bits(gb, 4); /* cpb_size_scale */
     for (i = 0; i < cpb_count; i++) {
-        get_ue_golomb_long(&h->gb); /* bit_rate_value_minus1 */
-        get_ue_golomb_long(&h->gb); /* cpb_size_value_minus1 */
-        get_bits1(&h->gb);          /* cbr_flag */
-    }
-    sps->initial_cpb_removal_delay_length = get_bits(&h->gb, 5) + 1;
-    sps->cpb_removal_delay_length         = get_bits(&h->gb, 5) + 1;
-    sps->dpb_output_delay_length          = get_bits(&h->gb, 5) + 1;
-    sps->time_offset_length               = get_bits(&h->gb, 5);
+        get_ue_golomb_long(gb); /* bit_rate_value_minus1 */
+        get_ue_golomb_long(gb); /* cpb_size_value_minus1 */
+        get_bits1(gb);          /* cbr_flag */
+    }
+    sps->initial_cpb_removal_delay_length = get_bits(gb, 5) + 1;
+    sps->cpb_removal_delay_length         = get_bits(gb, 5) + 1;
+    sps->dpb_output_delay_length          = get_bits(gb, 5) + 1;
+    sps->time_offset_length               = get_bits(gb, 5);
     sps->cpb_cnt                          = cpb_count;
     return 0;
 }
 
-static inline int decode_vui_parameters(H264Context *h, SPS *sps)
+static inline int decode_vui_parameters(GetBitContext *gb, AVCodecContext *avctx,
+                                        SPS *sps)
 {
     int aspect_ratio_info_present_flag;
     unsigned int aspect_ratio_idc;
 
-    aspect_ratio_info_present_flag = get_bits1(&h->gb);
+    aspect_ratio_info_present_flag = get_bits1(gb);
 
     if (aspect_ratio_info_present_flag) {
-        aspect_ratio_idc = get_bits(&h->gb, 8);
+        aspect_ratio_idc = get_bits(gb, 8);
         if (aspect_ratio_idc == EXTENDED_SAR) {
-            sps->sar.num = get_bits(&h->gb, 16);
-            sps->sar.den = get_bits(&h->gb, 16);
+            sps->sar.num = get_bits(gb, 16);
+            sps->sar.den = get_bits(gb, 16);
         } else if (aspect_ratio_idc < FF_ARRAY_ELEMS(ff_h264_pixel_aspect)) {
             sps->sar = ff_h264_pixel_aspect[aspect_ratio_idc];
         } else {
-            av_log(h->avctx, AV_LOG_ERROR, "illegal aspect ratio\n");
+            av_log(avctx, AV_LOG_ERROR, "illegal aspect ratio\n");
             return AVERROR_INVALIDDATA;
         }
     } else {
@@ -175,19 +153,19 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps)
         sps->sar.den = 0;
     }
 
-    if (get_bits1(&h->gb))      /* overscan_info_present_flag */
-        get_bits1(&h->gb);      /* overscan_appropriate_flag */
+    if (get_bits1(gb))      /* overscan_info_present_flag */
+        get_bits1(gb);      /* overscan_appropriate_flag */
 
-    sps->video_signal_type_present_flag = get_bits1(&h->gb);
+    sps->video_signal_type_present_flag = get_bits1(gb);
     if (sps->video_signal_type_present_flag) {
-        get_bits(&h->gb, 3);                 /* video_format */
-        sps->full_range = get_bits1(&h->gb); /* video_full_range_flag */
+        get_bits(gb, 3);                 /* video_format */
+        sps->full_range = get_bits1(gb); /* video_full_range_flag */
 
-        sps->colour_description_present_flag = get_bits1(&h->gb);
+        sps->colour_description_present_flag = get_bits1(gb);
         if (sps->colour_description_present_flag) {
-            sps->color_primaries = get_bits(&h->gb, 8); /* colour_primaries */
-            sps->color_trc       = get_bits(&h->gb, 8); /* transfer_characteristics */
-            sps->colorspace      = get_bits(&h->gb, 8); /* matrix_coefficients */
+            sps->color_primaries = get_bits(gb, 8); /* colour_primaries */
+            sps->color_trc       = get_bits(gb, 8); /* transfer_characteristics */
+            sps->colorspace      = get_bits(gb, 8); /* matrix_coefficients */
             if (sps->color_primaries >= AVCOL_PRI_NB)
                 sps->color_primaries = AVCOL_PRI_UNSPECIFIED;
             if (sps->color_trc >= AVCOL_TRC_NB)
@@ -198,23 +176,23 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps)
     }
 
     /* chroma_location_info_present_flag */
-    if (get_bits1(&h->gb)) {
+    if (get_bits1(gb)) {
         /* chroma_sample_location_type_top_field */
-        h->avctx->chroma_sample_location = get_ue_golomb(&h->gb) + 1;
-        get_ue_golomb(&h->gb);  /* chroma_sample_location_type_bottom_field */
+        avctx->chroma_sample_location = get_ue_golomb(gb) + 1;
+        get_ue_golomb(gb);  /* chroma_sample_location_type_bottom_field */
     }
 
-    if (show_bits1(&h->gb) && get_bits_left(&h->gb) < 10) {
-        av_log(h->avctx, AV_LOG_WARNING, "Truncated VUI\n");
+    if (show_bits1(gb) && get_bits_left(gb) < 10) {
+        av_log(avctx, AV_LOG_WARNING, "Truncated VUI\n");
         return 0;
     }
 
-    sps->timing_info_present_flag = get_bits1(&h->gb);
+    sps->timing_info_present_flag = get_bits1(gb);
     if (sps->timing_info_present_flag) {
-        unsigned num_units_in_tick = get_bits_long(&h->gb, 32);
-        unsigned time_scale        = get_bits_long(&h->gb, 32);
+        unsigned num_units_in_tick = get_bits_long(gb, 32);
+        unsigned time_scale        = get_bits_long(gb, 32);
         if (!num_units_in_tick || !time_scale) {
-            av_log(h->avctx, AV_LOG_ERROR,
+            av_log(avctx, AV_LOG_ERROR,
                    "time_scale/num_units_in_tick invalid or unsupported (%u/%u)\n",
                    time_scale, num_units_in_tick);
             sps->timing_info_present_flag = 0;
@@ -222,41 +200,41 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps)
             sps->num_units_in_tick = num_units_in_tick;
             sps->time_scale = time_scale;
         }
-        sps->fixed_frame_rate_flag = get_bits1(&h->gb);
+        sps->fixed_frame_rate_flag = get_bits1(gb);
     }
 
-    sps->nal_hrd_parameters_present_flag = get_bits1(&h->gb);
+    sps->nal_hrd_parameters_present_flag = get_bits1(gb);
     if (sps->nal_hrd_parameters_present_flag)
-        if (decode_hrd_parameters(h, sps) < 0)
+        if (decode_hrd_parameters(gb, avctx, sps) < 0)
             return AVERROR_INVALIDDATA;
-    sps->vcl_hrd_parameters_present_flag = get_bits1(&h->gb);
+    sps->vcl_hrd_parameters_present_flag = get_bits1(gb);
     if (sps->vcl_hrd_parameters_present_flag)
-        if (decode_hrd_parameters(h, sps) < 0)
+        if (decode_hrd_parameters(gb, avctx, sps) < 0)
             return AVERROR_INVALIDDATA;
     if (sps->nal_hrd_parameters_present_flag ||
         sps->vcl_hrd_parameters_present_flag)
-        get_bits1(&h->gb);     /* low_delay_hrd_flag */
-    sps->pic_struct_present_flag = get_bits1(&h->gb);
-    if (!get_bits_left(&h->gb))
+        get_bits1(gb);     /* low_delay_hrd_flag */
+    sps->pic_struct_present_flag = get_bits1(gb);
+    if (!get_bits_left(gb))
         return 0;
-    sps->bitstream_restriction_flag = get_bits1(&h->gb);
+    sps->bitstream_restriction_flag = get_bits1(gb);
     if (sps->bitstream_restriction_flag) {
-        get_bits1(&h->gb);     /* motion_vectors_over_pic_boundaries_flag */
-        get_ue_golomb(&h->gb); /* max_bytes_per_pic_denom */
-        get_ue_golomb(&h->gb); /* max_bits_per_mb_denom */
-        get_ue_golomb(&h->gb); /* log2_max_mv_length_horizontal */
-        get_ue_golomb(&h->gb); /* log2_max_mv_length_vertical */
-        sps->num_reorder_frames = get_ue_golomb(&h->gb);
-        get_ue_golomb(&h->gb); /*max_dec_frame_buffering*/
-
-        if (get_bits_left(&h->gb) < 0) {
+        get_bits1(gb);     /* motion_vectors_over_pic_boundaries_flag */
+        get_ue_golomb(gb); /* max_bytes_per_pic_denom */
+        get_ue_golomb(gb); /* max_bits_per_mb_denom */
+        get_ue_golomb(gb); /* log2_max_mv_length_horizontal */
+        get_ue_golomb(gb); /* log2_max_mv_length_vertical */
+        sps->num_reorder_frames = get_ue_golomb(gb);
+        get_ue_golomb(gb); /*max_dec_frame_buffering*/
+
+        if (get_bits_left(gb) < 0) {
             sps->num_reorder_frames         = 0;
             sps->bitstream_restriction_flag = 0;
         }
 
         if (sps->num_reorder_frames > 16U
             /* max_dec_frame_buffering || max_dec_frame_buffering > 16 */) {
-            av_log(h->avctx, AV_LOG_ERROR,
+            av_log(avctx, AV_LOG_ERROR,
                    "Clipping illegal num_reorder_frames %d\n",
                    sps->num_reorder_frames);
             sps->num_reorder_frames = 16;
@@ -267,18 +245,18 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps)
     return 0;
 }
 
-static void decode_scaling_list(H264Context *h, uint8_t *factors, int size,
+static void decode_scaling_list(GetBitContext *gb, uint8_t *factors, int size,
                                 const uint8_t *jvt_list,
                                 const uint8_t *fallback_list)
 {
     int i, last = 8, next = 8;
-    const uint8_t *scan = size == 16 ? zigzag_scan : ff_zigzag_direct;
-    if (!get_bits1(&h->gb)) /* matrix not written, we use the predicted one */
+    const uint8_t *scan = size == 16 ? ff_zigzag_scan : ff_zigzag_direct;
+    if (!get_bits1(gb)) /* matrix not written, we use the predicted one */
         memcpy(factors, fallback_list, size * sizeof(uint8_t));
     else
         for (i = 0; i < size; i++) {
             if (next)
-                next = (last + get_se_golomb(&h->gb)) & 0xff;
+                next = (last + get_se_golomb(gb)) & 0xff;
             if (!i && !next) { /* matrix not written, we use the preset one */
                 memcpy(factors, jvt_list, size * sizeof(uint8_t));
                 break;
@@ -287,7 +265,7 @@ static void decode_scaling_list(H264Context *h, uint8_t *factors, int size,
         }
 }
 
-static void decode_scaling_matrices(H264Context *h, SPS *sps,
+static void decode_scaling_matrices(GetBitContext *gb, SPS *sps,
                                     PPS *pps, int is_sps,
                                     uint8_t(*scaling_matrix4)[16],
                                     uint8_t(*scaling_matrix8)[64])
@@ -299,58 +277,78 @@ static void decode_scaling_matrices(H264Context *h, SPS *sps,
         fallback_sps ? sps->scaling_matrix8[0] : default_scaling8[0],
         fallback_sps ? sps->scaling_matrix8[3] : default_scaling8[1]
     };
-    if (get_bits1(&h->gb)) {
+    if (get_bits1(gb)) {
         sps->scaling_matrix_present |= is_sps;
-        decode_scaling_list(h, scaling_matrix4[0], 16, default_scaling4[0], fallback[0]);        // Intra, Y
-        decode_scaling_list(h, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0]); // Intra, Cr
-        decode_scaling_list(h, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1]); // Intra, Cb
-        decode_scaling_list(h, scaling_matrix4[3], 16, default_scaling4[1], fallback[1]);        // Inter, Y
-        decode_scaling_list(h, scaling_matrix4[4], 16, default_scaling4[1], scaling_matrix4[3]); // Inter, Cr
-        decode_scaling_list(h, scaling_matrix4[5], 16, default_scaling4[1], scaling_matrix4[4]); // Inter, Cb
+        decode_scaling_list(gb, scaling_matrix4[0], 16, default_scaling4[0], fallback[0]);        // Intra, Y
+        decode_scaling_list(gb, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0]); // Intra, Cr
+        decode_scaling_list(gb, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1]); // Intra, Cb
+        decode_scaling_list(gb, scaling_matrix4[3], 16, default_scaling4[1], fallback[1]);        // Inter, Y
+        decode_scaling_list(gb, scaling_matrix4[4], 16, default_scaling4[1], scaling_matrix4[3]); // Inter, Cr
+        decode_scaling_list(gb, scaling_matrix4[5], 16, default_scaling4[1], scaling_matrix4[4]); // Inter, Cb
         if (is_sps || pps->transform_8x8_mode) {
-            decode_scaling_list(h, scaling_matrix8[0], 64, default_scaling8[0], fallback[2]); // Intra, Y
-            decode_scaling_list(h, scaling_matrix8[3], 64, default_scaling8[1], fallback[3]); // Inter, Y
+            decode_scaling_list(gb, scaling_matrix8[0], 64, default_scaling8[0], fallback[2]); // Intra, Y
+            decode_scaling_list(gb, scaling_matrix8[3], 64, default_scaling8[1], fallback[3]); // Inter, Y
             if (sps->chroma_format_idc == 3) {
-                decode_scaling_list(h, scaling_matrix8[1], 64, default_scaling8[0], scaling_matrix8[0]); // Intra, Cr
-                decode_scaling_list(h, scaling_matrix8[4], 64, default_scaling8[1], scaling_matrix8[3]); // Inter, Cr
-                decode_scaling_list(h, scaling_matrix8[2], 64, default_scaling8[0], scaling_matrix8[1]); // Intra, Cb
-                decode_scaling_list(h, scaling_matrix8[5], 64, default_scaling8[1], scaling_matrix8[4]); // Inter, Cb
+                decode_scaling_list(gb, scaling_matrix8[1], 64, default_scaling8[0], scaling_matrix8[0]); // Intra, Cr
+                decode_scaling_list(gb, scaling_matrix8[4], 64, default_scaling8[1], scaling_matrix8[3]); // Inter, Cr
+                decode_scaling_list(gb, scaling_matrix8[2], 64, default_scaling8[0], scaling_matrix8[1]); // Intra, Cb
+                decode_scaling_list(gb, scaling_matrix8[5], 64, default_scaling8[1], scaling_matrix8[4]); // Inter, Cb
             }
         }
     }
 }
 
-int ff_h264_decode_seq_parameter_set(H264Context *h, int ignore_truncation)
+void ff_h264_ps_uninit(H264ParamSets *ps)
+{
+    int i;
+
+    for (i = 0; i < MAX_SPS_COUNT; i++)
+        av_buffer_unref(&ps->sps_list[i]);
+
+    for (i = 0; i < MAX_PPS_COUNT; i++)
+        av_buffer_unref(&ps->pps_list[i]);
+
+    av_buffer_unref(&ps->sps_ref);
+    av_buffer_unref(&ps->pps_ref);
+
+    ps->pps = NULL;
+    ps->sps = NULL;
+}
+
+int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx,
+                                     H264ParamSets *ps, int ignore_truncation)
 {
+    AVBufferRef *sps_buf;
     int profile_idc, level_idc, constraint_set_flags = 0;
     unsigned int sps_id;
     int i, log2_max_frame_num_minus4;
     SPS *sps;
 
-    sps = av_mallocz(sizeof(SPS));
-    if (!sps)
+    sps_buf = av_buffer_allocz(sizeof(*sps));
+    if (!sps_buf)
         return AVERROR(ENOMEM);
+    sps = (SPS*)sps_buf->data;
 
-    sps->data_size = h->gb.buffer_end - h->gb.buffer;
+    sps->data_size = gb->buffer_end - gb->buffer;
     if (sps->data_size > sizeof(sps->data)) {
-        av_log(h->avctx, AV_LOG_WARNING, "Truncating likely oversized SPS\n");
+        av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized SPS\n");
         sps->data_size = sizeof(sps->data);
     }
-    memcpy(sps->data, h->gb.buffer, sps->data_size);
-
-    profile_idc           = get_bits(&h->gb, 8);
-    constraint_set_flags |= get_bits1(&h->gb) << 0;   // constraint_set0_flag
-    constraint_set_flags |= get_bits1(&h->gb) << 1;   // constraint_set1_flag
-    constraint_set_flags |= get_bits1(&h->gb) << 2;   // constraint_set2_flag
-    constraint_set_flags |= get_bits1(&h->gb) << 3;   // constraint_set3_flag
-    constraint_set_flags |= get_bits1(&h->gb) << 4;   // constraint_set4_flag
-    constraint_set_flags |= get_bits1(&h->gb) << 5;   // constraint_set5_flag
-    skip_bits(&h->gb, 2);                             // reserved_zero_2bits
-    level_idc = get_bits(&h->gb, 8);
-    sps_id    = get_ue_golomb_31(&h->gb);
+    memcpy(sps->data, gb->buffer, sps->data_size);
+
+    profile_idc           = get_bits(gb, 8);
+    constraint_set_flags |= get_bits1(gb) << 0;   // constraint_set0_flag
+    constraint_set_flags |= get_bits1(gb) << 1;   // constraint_set1_flag
+    constraint_set_flags |= get_bits1(gb) << 2;   // constraint_set2_flag
+    constraint_set_flags |= get_bits1(gb) << 3;   // constraint_set3_flag
+    constraint_set_flags |= get_bits1(gb) << 4;   // constraint_set4_flag
+    constraint_set_flags |= get_bits1(gb) << 5;   // constraint_set5_flag
+    skip_bits(gb, 2);                             // reserved_zero_2bits
+    level_idc = get_bits(gb, 8);
+    sps_id    = get_ue_golomb_31(gb);
 
     if (sps_id >= MAX_SPS_COUNT) {
-        av_log(h->avctx, AV_LOG_ERROR, "sps_id %u out of range\n", sps_id);
+        av_log(avctx, AV_LOG_ERROR, "sps_id %u out of range\n", sps_id);
         goto fail;
     }
 
@@ -377,33 +375,33 @@ int ff_h264_decode_seq_parameter_set(H264Context *h, int ignore_truncation)
         sps->profile_idc == 128 ||  // Multiview High profile (MVC)
         sps->profile_idc == 138 ||  // Multiview Depth High profile (MVCD)
         sps->profile_idc == 144) {  // old High444 profile
-        sps->chroma_format_idc = get_ue_golomb_31(&h->gb);
+        sps->chroma_format_idc = get_ue_golomb_31(gb);
         if (sps->chroma_format_idc > 3U) {
-            avpriv_request_sample(h->avctx, "chroma_format_idc %u",
+            avpriv_request_sample(avctx, "chroma_format_idc %u",
                                   sps->chroma_format_idc);
             goto fail;
         } else if (sps->chroma_format_idc == 3) {
-            sps->residual_color_transform_flag = get_bits1(&h->gb);
+            sps->residual_color_transform_flag = get_bits1(gb);
             if (sps->residual_color_transform_flag) {
-                av_log(h->avctx, AV_LOG_ERROR, "separate color planes are not supported\n");
+                av_log(avctx, AV_LOG_ERROR, "separate color planes are not supported\n");
                 goto fail;
             }
         }
-        sps->bit_depth_luma   = get_ue_golomb(&h->gb) + 8;
-        sps->bit_depth_chroma = get_ue_golomb(&h->gb) + 8;
+        sps->bit_depth_luma   = get_ue_golomb(gb) + 8;
+        sps->bit_depth_chroma = get_ue_golomb(gb) + 8;
         if (sps->bit_depth_chroma != sps->bit_depth_luma) {
-            avpriv_request_sample(h->avctx,
+            avpriv_request_sample(avctx,
                                   "Different chroma and luma bit depth");
             goto fail;
         }
         if (sps->bit_depth_luma   < 8 || sps->bit_depth_luma   > 14 ||
             sps->bit_depth_chroma < 8 || sps->bit_depth_chroma > 14) {
-            av_log(h->avctx, AV_LOG_ERROR, "illegal bit depth value (%d, %d)\n",
+            av_log(avctx, AV_LOG_ERROR, "illegal bit depth value (%d, %d)\n",
                    sps->bit_depth_luma, sps->bit_depth_chroma);
             goto fail;
         }
-        sps->transform_bypass = get_bits1(&h->gb);
-        decode_scaling_matrices(h, sps, NULL, 1,
+        sps->transform_bypass = get_bits1(gb);
+        decode_scaling_matrices(gb, sps, NULL, 1,
                                 sps->scaling_matrix4, sps->scaling_matrix8);
     } else {
         sps->chroma_format_idc = 1;
@@ -411,89 +409,89 @@ int ff_h264_decode_seq_parameter_set(H264Context *h, int ignore_truncation)
         sps->bit_depth_chroma  = 8;
     }
 
-    log2_max_frame_num_minus4 = get_ue_golomb(&h->gb);
+    log2_max_frame_num_minus4 = get_ue_golomb(gb);
     if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 ||
         log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) {
-        av_log(h->avctx, AV_LOG_ERROR,
+        av_log(avctx, AV_LOG_ERROR,
                "log2_max_frame_num_minus4 out of range (0-12): %d\n",
                log2_max_frame_num_minus4);
         goto fail;
     }
     sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4;
 
-    sps->poc_type = get_ue_golomb_31(&h->gb);
+    sps->poc_type = get_ue_golomb_31(gb);
 
     if (sps->poc_type == 0) { // FIXME #define
-        unsigned t = get_ue_golomb(&h->gb);
+        unsigned t = get_ue_golomb(gb);
         if (t>12) {
-            av_log(h->avctx, AV_LOG_ERROR, "log2_max_poc_lsb (%d) is out of range\n", t);
+            av_log(avctx, AV_LOG_ERROR, "log2_max_poc_lsb (%d) is out of range\n", t);
             goto fail;
         }
         sps->log2_max_poc_lsb = t + 4;
     } else if (sps->poc_type == 1) { // FIXME #define
-        sps->delta_pic_order_always_zero_flag = get_bits1(&h->gb);
-        sps->offset_for_non_ref_pic           = get_se_golomb(&h->gb);
-        sps->offset_for_top_to_bottom_field   = get_se_golomb(&h->gb);
-        sps->poc_cycle_length                 = get_ue_golomb(&h->gb);
+        sps->delta_pic_order_always_zero_flag = get_bits1(gb);
+        sps->offset_for_non_ref_pic           = get_se_golomb(gb);
+        sps->offset_for_top_to_bottom_field   = get_se_golomb(gb);
+        sps->poc_cycle_length                 = get_ue_golomb(gb);
 
         if ((unsigned)sps->poc_cycle_length >=
             FF_ARRAY_ELEMS(sps->offset_for_ref_frame)) {
-            av_log(h->avctx, AV_LOG_ERROR,
+            av_log(avctx, AV_LOG_ERROR,
                    "poc_cycle_length overflow %d\n", sps->poc_cycle_length);
             goto fail;
         }
 
         for (i = 0; i < sps->poc_cycle_length; i++)
-            sps->offset_for_ref_frame[i] = get_se_golomb(&h->gb);
+            sps->offset_for_ref_frame[i] = get_se_golomb(gb);
     } else if (sps->poc_type != 2) {
-        av_log(h->avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type);
+        av_log(avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type);
         goto fail;
     }
 
-    sps->ref_frame_count = get_ue_golomb_31(&h->gb);
-    if (h->avctx->codec_tag == MKTAG('S', 'M', 'V', '2'))
+    sps->ref_frame_count = get_ue_golomb_31(gb);
+    if (avctx->codec_tag == MKTAG('S', 'M', 'V', '2'))
         sps->ref_frame_count = FFMAX(2, sps->ref_frame_count);
     if (sps->ref_frame_count > H264_MAX_PICTURE_COUNT - 2 ||
         sps->ref_frame_count > 16U) {
-        av_log(h->avctx, AV_LOG_ERROR,
+        av_log(avctx, AV_LOG_ERROR,
                "too many reference frames %d\n", sps->ref_frame_count);
         goto fail;
     }
-    sps->gaps_in_frame_num_allowed_flag = get_bits1(&h->gb);
-    sps->mb_width                       = get_ue_golomb(&h->gb) + 1;
-    sps->mb_height                      = get_ue_golomb(&h->gb) + 1;
+    sps->gaps_in_frame_num_allowed_flag = get_bits1(gb);
+    sps->mb_width                       = get_ue_golomb(gb) + 1;
+    sps->mb_height                      = get_ue_golomb(gb) + 1;
     if ((unsigned)sps->mb_width  >= INT_MAX / 16 ||
         (unsigned)sps->mb_height >= INT_MAX / 16 ||
         av_image_check_size(16 * sps->mb_width,
-                            16 * sps->mb_height, 0, h->avctx)) {
-        av_log(h->avctx, AV_LOG_ERROR, "mb_width/height overflow\n");
+                            16 * sps->mb_height, 0, avctx)) {
+        av_log(avctx, AV_LOG_ERROR, "mb_width/height overflow\n");
         goto fail;
     }
 
-    sps->frame_mbs_only_flag = get_bits1(&h->gb);
+    sps->frame_mbs_only_flag = get_bits1(gb);
     if (!sps->frame_mbs_only_flag)
-        sps->mb_aff = get_bits1(&h->gb);
+        sps->mb_aff = get_bits1(gb);
     else
         sps->mb_aff = 0;
 
-    sps->direct_8x8_inference_flag = get_bits1(&h->gb);
+    sps->direct_8x8_inference_flag = get_bits1(gb);
 
 #ifndef ALLOW_INTERLACE
     if (sps->mb_aff)
-        av_log(h->avctx, AV_LOG_ERROR,
+        av_log(avctx, AV_LOG_ERROR,
                "MBAFF support not included; enable it at compile-time.\n");
 #endif
-    sps->crop = get_bits1(&h->gb);
+    sps->crop = get_bits1(gb);
     if (sps->crop) {
-        unsigned int crop_left   = get_ue_golomb(&h->gb);
-        unsigned int crop_right  = get_ue_golomb(&h->gb);
-        unsigned int crop_top    = get_ue_golomb(&h->gb);
-        unsigned int crop_bottom = get_ue_golomb(&h->gb);
+        unsigned int crop_left   = get_ue_golomb(gb);
+        unsigned int crop_right  = get_ue_golomb(gb);
+        unsigned int crop_top    = get_ue_golomb(gb);
+        unsigned int crop_bottom = get_ue_golomb(gb);
         int width  = 16 * sps->mb_width;
         int height = 16 * sps->mb_height * (2 - sps->frame_mbs_only_flag);
 
-        if (h->avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) {
-            av_log(h->avctx, AV_LOG_DEBUG, "discarding sps cropping, original "
+        if (avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) {
+            av_log(avctx, AV_LOG_DEBUG, "discarding sps cropping, original "
                                            "values are l:%d r:%d t:%d b:%d\n",
                    crop_left, crop_right, crop_top, crop_bottom);
 
@@ -509,9 +507,9 @@ int ff_h264_decode_seq_parameter_set(H264Context *h, int ignore_truncation)
             int step_y = (2 - sps->frame_mbs_only_flag) << vsub;
 
             if (crop_left & (0x1F >> (sps->bit_depth_luma > 8)) &&
-                !(h->avctx->flags & AV_CODEC_FLAG_UNALIGNED)) {
+                !(avctx->flags & AV_CODEC_FLAG_UNALIGNED)) {
                 crop_left &= ~(0x1F >> (sps->bit_depth_luma > 8));
-                av_log(h->avctx, AV_LOG_WARNING,
+                av_log(avctx, AV_LOG_WARNING,
                        "Reducing left cropping to %d "
                        "chroma samples to preserve alignment.\n",
                        crop_left);
@@ -524,7 +522,7 @@ int ff_h264_decode_seq_parameter_set(H264Context *h, int ignore_truncation)
                 (crop_left + crop_right ) * step_x >= width ||
                 (crop_top  + crop_bottom) * step_y >= height
             ) {
-                av_log(h->avctx, AV_LOG_ERROR, "crop values invalid %d %d %d %d / %d %d\n", crop_left, crop_right, crop_top, crop_bottom, width, height);
+                av_log(avctx, AV_LOG_ERROR, "crop values invalid %d %d %d %d / %d %d\n", crop_left, crop_right, crop_top, crop_bottom, width, height);
                 goto fail;
             }
 
@@ -541,16 +539,16 @@ int ff_h264_decode_seq_parameter_set(H264Context *h, int ignore_truncation)
         sps->crop        = 0;
     }
 
-    sps->vui_parameters_present_flag = get_bits1(&h->gb);
+    sps->vui_parameters_present_flag = get_bits1(gb);
     if (sps->vui_parameters_present_flag) {
-        int ret = decode_vui_parameters(h, sps);
+        int ret = decode_vui_parameters(gb, avctx, sps);
         if (ret < 0)
             goto fail;
     }
 
-    if (get_bits_left(&h->gb) < 0) {
-        av_log(h->avctx, ignore_truncation ? AV_LOG_WARNING : AV_LOG_ERROR,
-               "Overread %s by %d bits\n", sps->vui_parameters_present_flag ? "VUI" : "SPS", -get_bits_left(&h->gb));
+    if (get_bits_left(gb) < 0) {
+        av_log(avctx, ignore_truncation ? AV_LOG_WARNING : AV_LOG_ERROR,
+               "Overread %s by %d bits\n", sps->vui_parameters_present_flag ? "VUI" : "SPS", -get_bits_left(gb));
         if (!ignore_truncation)
             goto fail;
     }
@@ -571,9 +569,9 @@ int ff_h264_decode_seq_parameter_set(H264Context *h, int ignore_truncation)
     if (!sps->sar.den)
         sps->sar.den = 1;
 
-    if (h->avctx->debug & FF_DEBUG_PICT_INFO) {
+    if (avctx->debug & FF_DEBUG_PICT_INFO) {
         static const char csp[4][5] = { "Gray", "420", "422", "444" };
-        av_log(h->avctx, AV_LOG_DEBUG,
+        av_log(avctx, AV_LOG_DEBUG,
                "sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%u/%u/%u/%u %s %s %"PRId32"/%"PRId32" b%d reo:%d\n",
                sps_id, sps->profile_idc, sps->level_idc,
                sps->poc_type,
@@ -591,18 +589,97 @@ int ff_h264_decode_seq_parameter_set(H264Context *h, int ignore_truncation)
                sps->bitstream_restriction_flag ? sps->num_reorder_frames : -1
                );
     }
-    sps->new = 1;
 
-    av_free(h->sps_buffers[sps_id]);
-    h->sps_buffers[sps_id] = sps;
+    /* check if this is a repeat of an already parsed SPS, then keep the
+     * original one.
+     * otherwise drop all PPSes that depend on it */
+    if (ps->sps_list[sps_id] &&
+        !memcmp(ps->sps_list[sps_id]->data, sps_buf->data, sps_buf->size)) {
+        av_buffer_unref(&sps_buf);
+    } else {
+        remove_sps(ps, sps_id);
+        ps->sps_list[sps_id] = sps_buf;
+    }
 
     return 0;
 
 fail:
-    av_free(sps);
+    av_buffer_unref(&sps_buf);
     return AVERROR_INVALIDDATA;
 }
 
+static void init_dequant8_coeff_table(PPS *pps, const SPS *sps)
+{
+    int i, j, q, x;
+    const int max_qp = 51 + 6 * (sps->bit_depth_luma - 8);
+
+    for (i = 0; i < 6; i++) {
+        pps->dequant8_coeff[i] = pps->dequant8_buffer[i];
+        for (j = 0; j < i; j++)
+            if (!memcmp(pps->scaling_matrix8[j], pps->scaling_matrix8[i],
+                        64 * sizeof(uint8_t))) {
+                pps->dequant8_coeff[i] = pps->dequant8_buffer[j];
+                break;
+            }
+        if (j < i)
+            continue;
+
+        for (q = 0; q < max_qp + 1; q++) {
+            int shift = ff_h264_quant_div6[q];
+            int idx   = ff_h264_quant_rem6[q];
+            for (x = 0; x < 64; x++)
+                pps->dequant8_coeff[i][q][(x >> 3) | ((x & 7) << 3)] =
+                    ((uint32_t)ff_h264_dequant8_coeff_init[idx][ff_h264_dequant8_coeff_init_scan[((x >> 1) & 12) | (x & 3)]] *
+                     pps->scaling_matrix8[i][x]) << shift;
+        }
+    }
+}
+
+static void init_dequant4_coeff_table(PPS *pps, const SPS *sps)
+{
+    int i, j, q, x;
+    const int max_qp = 51 + 6 * (sps->bit_depth_luma - 8);
+    for (i = 0; i < 6; i++) {
+        pps->dequant4_coeff[i] = pps->dequant4_buffer[i];
+        for (j = 0; j < i; j++)
+            if (!memcmp(pps->scaling_matrix4[j], pps->scaling_matrix4[i],
+                        16 * sizeof(uint8_t))) {
+                pps->dequant4_coeff[i] = pps->dequant4_buffer[j];
+                break;
+            }
+        if (j < i)
+            continue;
+
+        for (q = 0; q < max_qp + 1; q++) {
+            int shift = ff_h264_quant_div6[q] + 2;
+            int idx   = ff_h264_quant_rem6[q];
+            for (x = 0; x < 16; x++)
+                pps->dequant4_coeff[i][q][(x >> 2) | ((x << 2) & 0xF)] =
+                    ((uint32_t)ff_h264_dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] *
+                     pps->scaling_matrix4[i][x]) << shift;
+        }
+    }
+}
+
+static void init_dequant_tables(PPS *pps, const SPS *sps)
+{
+    int i, x;
+    init_dequant4_coeff_table(pps, sps);
+    memset(pps->dequant8_coeff, 0, sizeof(pps->dequant8_coeff));
+
+    if (pps->transform_8x8_mode)
+        init_dequant8_coeff_table(pps, sps);
+    if (sps->transform_bypass) {
+        for (i = 0; i < 6; i++)
+            for (x = 0; x < 16; x++)
+                pps->dequant4_coeff[i][0][x] = 1 << 6;
+        if (pps->transform_8x8_mode)
+            for (i = 0; i < 6; i++)
+                for (x = 0; x < 64; x++)
+                    pps->dequant8_coeff[i][0][x] = 1 << 6;
+    }
+}
+
 static void build_qp_table(PPS *pps, int t, int index, const int depth)
 {
     int i;
@@ -612,14 +689,13 @@ static void build_qp_table(PPS *pps, int t, int index, const int depth)
             ff_h264_chroma_qp[depth - 8][av_clip(i + index, 0, max_qp)];
 }
 
-static int more_rbsp_data_in_pps(H264Context *h, PPS *pps)
+static int more_rbsp_data_in_pps(const SPS *sps, void *logctx)
 {
-    const SPS *sps = h->sps_buffers[pps->sps_id];
     int profile_idc = sps->profile_idc;
 
     if ((profile_idc == 66 || profile_idc == 77 ||
          profile_idc == 88) && (sps->constraint_set_flags & 7)) {
-        av_log(h->avctx, AV_LOG_VERBOSE,
+        av_log(logctx, AV_LOG_VERBOSE,
                "Current profile doesn't provide more RBSP data in PPS, skipping\n");
         return 0;
     }
@@ -627,57 +703,62 @@ static int more_rbsp_data_in_pps(H264Context *h, PPS *pps)
     return 1;
 }
 
-int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length)
+int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avctx,
+                                         H264ParamSets *ps, int bit_length)
 {
-    const SPS *sps;
-    unsigned int pps_id = get_ue_golomb(&h->gb);
+    AVBufferRef *pps_buf;
+    SPS *sps;
+    unsigned int pps_id = get_ue_golomb(gb);
     PPS *pps;
     int qp_bd_offset;
     int bits_left;
     int ret;
 
     if (pps_id >= MAX_PPS_COUNT) {
-        av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id);
+        av_log(avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id);
         return AVERROR_INVALIDDATA;
     }
 
-    pps = av_mallocz(sizeof(PPS));
-    if (!pps)
+    pps_buf = av_buffer_allocz(sizeof(*pps));
+    if (!pps_buf)
         return AVERROR(ENOMEM);
-    pps->data_size = h->gb.buffer_end - h->gb.buffer;
+    pps = (PPS*)pps_buf->data;
+
+    pps->data_size = gb->buffer_end - gb->buffer;
     if (pps->data_size > sizeof(pps->data)) {
-        av_log(h->avctx, AV_LOG_WARNING, "Truncating likely oversized PPS\n");
+        av_log(avctx, AV_LOG_WARNING, "Truncating likely oversized PPS\n");
         pps->data_size = sizeof(pps->data);
     }
-    memcpy(pps->data, h->gb.buffer, pps->data_size);
-    pps->sps_id = get_ue_golomb_31(&h->gb);
+    memcpy(pps->data, gb->buffer, pps->data_size);
+
+    pps->sps_id = get_ue_golomb_31(gb);
     if ((unsigned)pps->sps_id >= MAX_SPS_COUNT ||
-        !h->sps_buffers[pps->sps_id]) {
-        av_log(h->avctx, AV_LOG_ERROR, "sps_id %u out of range\n", pps->sps_id);
+        !ps->sps_list[pps->sps_id]) {
+        av_log(avctx, AV_LOG_ERROR, "sps_id %u out of range\n", pps->sps_id);
         ret = AVERROR_INVALIDDATA;
         goto fail;
     }
-    sps = h->sps_buffers[pps->sps_id];
+    sps = (SPS*)ps->sps_list[pps->sps_id]->data;
     if (sps->bit_depth_luma > 14) {
-        av_log(h->avctx, AV_LOG_ERROR,
+        av_log(avctx, AV_LOG_ERROR,
                "Invalid luma bit depth=%d\n",
                sps->bit_depth_luma);
         ret = AVERROR_INVALIDDATA;
         goto fail;
     } else if (sps->bit_depth_luma == 11 || sps->bit_depth_luma == 13) {
-        av_log(h->avctx, AV_LOG_ERROR,
+        av_log(avctx, AV_LOG_ERROR,
                "Unimplemented luma bit depth=%d\n",
                sps->bit_depth_luma);
         ret = AVERROR_PATCHWELCOME;
         goto fail;
     }
 
-    pps->cabac             = get_bits1(&h->gb);
-    pps->pic_order_present = get_bits1(&h->gb);
-    pps->slice_group_count = get_ue_golomb(&h->gb) + 1;
+    pps->cabac             = get_bits1(gb);
+    pps->pic_order_present = get_bits1(gb);
+    pps->slice_group_count = get_ue_golomb(gb) + 1;
     if (pps->slice_group_count > 1) {
-        pps->mb_slice_group_map_type = get_ue_golomb(&h->gb);
-        av_log(h->avctx, AV_LOG_ERROR, "FMO not supported\n");
+        pps->mb_slice_group_map_type = get_ue_golomb(gb);
+        av_log(avctx, AV_LOG_ERROR, "FMO not supported\n");
         switch (pps->mb_slice_group_map_type) {
         case 0:
 #if 0
@@ -710,40 +791,38 @@ int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length)
             break;
         }
     }
-    pps->ref_count[0] = get_ue_golomb(&h->gb) + 1;
-    pps->ref_count[1] = get_ue_golomb(&h->gb) + 1;
+    pps->ref_count[0] = get_ue_golomb(gb) + 1;
+    pps->ref_count[1] = get_ue_golomb(gb) + 1;
     if (pps->ref_count[0] - 1 > 32 - 1 || pps->ref_count[1] - 1 > 32 - 1) {
-        av_log(h->avctx, AV_LOG_ERROR, "reference overflow (pps)\n");
+        av_log(avctx, AV_LOG_ERROR, "reference overflow (pps)\n");
         ret = AVERROR_INVALIDDATA;
         goto fail;
     }
 
     qp_bd_offset = 6 * (sps->bit_depth_luma - 8);
 
-    pps->weighted_pred                        = get_bits1(&h->gb);
-    pps->weighted_bipred_idc                  = get_bits(&h->gb, 2);
-    pps->init_qp                              = get_se_golomb(&h->gb) + 26 + qp_bd_offset;
-    pps->init_qs                              = get_se_golomb(&h->gb) + 26 + qp_bd_offset;
-    pps->chroma_qp_index_offset[0]            = get_se_golomb(&h->gb);
-    pps->deblocking_filter_parameters_present = get_bits1(&h->gb);
-    pps->constrained_intra_pred               = get_bits1(&h->gb);
-    pps->redundant_pic_cnt_present            = get_bits1(&h->gb);
+    pps->weighted_pred                        = get_bits1(gb);
+    pps->weighted_bipred_idc                  = get_bits(gb, 2);
+    pps->init_qp                              = get_se_golomb(gb) + 26 + qp_bd_offset;
+    pps->init_qs                              = get_se_golomb(gb) + 26 + qp_bd_offset;
+    pps->chroma_qp_index_offset[0]            = get_se_golomb(gb);
+    pps->deblocking_filter_parameters_present = get_bits1(gb);
+    pps->constrained_intra_pred               = get_bits1(gb);
+    pps->redundant_pic_cnt_present            = get_bits1(gb);
 
     pps->transform_8x8_mode = 0;
-    // contents of sps/pps can change even if id doesn't, so reinit
-    h->dequant_coeff_pps = -1;
-    memcpy(pps->scaling_matrix4, h->sps_buffers[pps->sps_id]->scaling_matrix4,
+    memcpy(pps->scaling_matrix4, sps->scaling_matrix4,
            sizeof(pps->scaling_matrix4));
-    memcpy(pps->scaling_matrix8, h->sps_buffers[pps->sps_id]->scaling_matrix8,
+    memcpy(pps->scaling_matrix8, sps->scaling_matrix8,
            sizeof(pps->scaling_matrix8));
 
-    bits_left = bit_length - get_bits_count(&h->gb);
-    if (bits_left > 0 && more_rbsp_data_in_pps(h, pps)) {
-        pps->transform_8x8_mode = get_bits1(&h->gb);
-        decode_scaling_matrices(h, h->sps_buffers[pps->sps_id], pps, 0,
+    bits_left = bit_length - get_bits_count(gb);
+    if (bits_left > 0 && more_rbsp_data_in_pps(sps, avctx)) {
+        pps->transform_8x8_mode = get_bits1(gb);
+        decode_scaling_matrices(gb, sps, pps, 0,
                                 pps->scaling_matrix4, pps->scaling_matrix8);
         // second_chroma_qp_index_offset
-        pps->chroma_qp_index_offset[1] = get_se_golomb(&h->gb);
+        pps->chroma_qp_index_offset[1] = get_se_golomb(gb);
     } else {
         pps->chroma_qp_index_offset[1] = pps->chroma_qp_index_offset[0];
     }
@@ -752,11 +831,14 @@ int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length)
                    sps->bit_depth_luma);
     build_qp_table(pps, 1, pps->chroma_qp_index_offset[1],
                    sps->bit_depth_luma);
+
+    init_dequant_tables(pps, sps);
+
     if (pps->chroma_qp_index_offset[0] != pps->chroma_qp_index_offset[1])
         pps->chroma_qp_diff = 1;
 
-    if (h->avctx->debug & FF_DEBUG_PICT_INFO) {
-        av_log(h->avctx, AV_LOG_DEBUG,
+    if (avctx->debug & FF_DEBUG_PICT_INFO) {
+        av_log(avctx, AV_LOG_DEBUG,
                "pps:%u sps:%u %s slice_groups:%d ref:%u/%u %s qp:%d/%d/%d/%d %s %s %s %s\n",
                pps_id, pps->sps_id,
                pps->cabac ? "CABAC" : "CAVLC",
@@ -770,11 +852,12 @@ int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length)
                pps->transform_8x8_mode ? "8x8DCT" : "");
     }
 
-    av_free(h->pps_buffers[pps_id]);
-    h->pps_buffers[pps_id] = pps;
+    remove_pps(ps, pps_id);
+    ps->pps_list[pps_id] = pps_buf;
+
     return 0;
 
 fail:
-    av_free(pps);
+    av_buffer_unref(&pps_buf);
     return ret;
 }
diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c
index d46d940..2f80de1 100644
--- a/libavcodec/h264_refs.c
+++ b/libavcodec/h264_refs.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10  reference picture handling.
+ * H.264 / AVC / MPEG-4 part10  reference picture handling.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -75,7 +75,7 @@ static int split_field_copy(H264Ref *dest, H264Picture *src, int parity, int id_
 }
 
 static int build_def_list(H264Ref *def, int def_len,
-                          H264Picture **in, int len, int is_long, int sel)
+                          H264Picture * const *in, int len, int is_long, int sel)
 {
     int  i[2] = { 0 };
     int index = 0;
@@ -100,7 +100,8 @@ static int build_def_list(H264Ref *def, int def_len,
     return index;
 }
 
-static int add_sorted(H264Picture **sorted, H264Picture **src, int len, int limit, int dir)
+static int add_sorted(H264Picture **sorted, H264Picture * const *src,
+                      int len, int limit, int dir)
 {
     int i, best_poc;
     int out_i = 0;
@@ -122,9 +123,9 @@ static int add_sorted(H264Picture **sorted, H264Picture **src, int len, int limi
     return out_i;
 }
 
-static int mismatches_ref(H264Context *h, H264Picture *pic)
+static int mismatches_ref(const H264Context *h, const H264Picture *pic)
 {
-    AVFrame *f = pic->f;
+    const AVFrame *f = pic->f;
     return (h->cur_pic_ptr->f->width  != f->width ||
             h->cur_pic_ptr->f->height != f->height ||
             h->cur_pic_ptr->f->format != f->format);
@@ -212,8 +213,39 @@ static void h264_initialise_ref_list(H264Context *h, H264SliceContext *sl)
         h->default_ref[i] = sl->ref_list[i][0];
 }
 
-static void print_short_term(H264Context *h);
-static void print_long_term(H264Context *h);
+/**
+ * print short term list
+ */
+static void print_short_term(const H264Context *h)
+{
+    uint32_t i;
+    if (h->avctx->debug & FF_DEBUG_MMCO) {
+        av_log(h->avctx, AV_LOG_DEBUG, "short term list:\n");
+        for (i = 0; i < h->short_ref_count; i++) {
+            H264Picture *pic = h->short_ref[i];
+            av_log(h->avctx, AV_LOG_DEBUG, "%"PRIu32" fn:%d poc:%d %p\n",
+                   i, pic->frame_num, pic->poc, pic->f->data[0]);
+        }
+    }
+}
+
+/**
+ * print long term list
+ */
+static void print_long_term(const H264Context *h)
+{
+    uint32_t i;
+    if (h->avctx->debug & FF_DEBUG_MMCO) {
+        av_log(h->avctx, AV_LOG_DEBUG, "long term list:\n");
+        for (i = 0; i < 16; i++) {
+            H264Picture *pic = h->long_ref[i];
+            if (pic) {
+                av_log(h->avctx, AV_LOG_DEBUG, "%"PRIu32" fn:%d poc:%d %p\n",
+                       i, pic->frame_num, pic->poc, pic->f->data[0]);
+            }
+        }
+    }
+}
 
 /**
  * Extract structure information about the picture described by pic_num in
@@ -225,7 +257,7 @@ static void print_long_term(H264Context *h);
  * @return frame number (short term) or long term index of picture
  *         described by pic_num
  */
-static int pic_num_extract(H264Context *h, int pic_num, int *structure)
+static int pic_num_extract(const H264Context *h, int pic_num, int *structure)
 {
     *structure = h->picture_structure;
     if (FIELD_PICTURE(h)) {
@@ -369,7 +401,7 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h, H264SliceContext *sl)
     return 0;
 }
 
-void ff_h264_fill_mbaff_ref_list(H264Context *h, H264SliceContext *sl)
+void ff_h264_fill_mbaff_ref_list(H264SliceContext *sl)
 {
     int list, i, j;
     for (list = 0; list < sl->list_count; list++) {
@@ -391,11 +423,11 @@ void ff_h264_fill_mbaff_ref_list(H264Context *h, H264SliceContext *sl)
             field[1].reference = PICT_BOTTOM_FIELD;
             field[1].poc       = field[1].parent->field_poc[1];
 
-            sl->luma_weight[16 + 2 * i][list][0] = sl->luma_weight[16 + 2 * i + 1][list][0] = sl->luma_weight[i][list][0];
-            sl->luma_weight[16 + 2 * i][list][1] = sl->luma_weight[16 + 2 * i + 1][list][1] = sl->luma_weight[i][list][1];
+            sl->pwt.luma_weight[16 + 2 * i][list][0] = sl->pwt.luma_weight[16 + 2 * i + 1][list][0] = sl->pwt.luma_weight[i][list][0];
+            sl->pwt.luma_weight[16 + 2 * i][list][1] = sl->pwt.luma_weight[16 + 2 * i + 1][list][1] = sl->pwt.luma_weight[i][list][1];
             for (j = 0; j < 2; j++) {
-                sl->chroma_weight[16 + 2 * i][list][j][0] = sl->chroma_weight[16 + 2 * i + 1][list][j][0] = sl->chroma_weight[i][list][j][0];
-                sl->chroma_weight[16 + 2 * i][list][j][1] = sl->chroma_weight[16 + 2 * i + 1][list][j][1] = sl->chroma_weight[i][list][j][1];
+                sl->pwt.chroma_weight[16 + 2 * i][list][j][0] = sl->pwt.chroma_weight[16 + 2 * i + 1][list][j][0] = sl->pwt.chroma_weight[i][list][j][0];
+                sl->pwt.chroma_weight[16 + 2 * i][list][j][1] = sl->pwt.chroma_weight[16 + 2 * i + 1][list][j][1] = sl->pwt.chroma_weight[i][list][j][1];
             }
         }
     }
@@ -467,7 +499,6 @@ static void remove_short_at_index(H264Context *h, int i)
 }
 
 /**
- *
  * @return the removed picture or NULL if an error occurs
  */
 static H264Picture *remove_short(H264Context *h, int frame_num, int ref_mask)
@@ -538,40 +569,6 @@ void ff_h264_remove_all_refs(H264Context *h)
     }
 }
 
-/**
- * print short term list
- */
-static void print_short_term(H264Context *h)
-{
-    uint32_t i;
-    if (h->avctx->debug & FF_DEBUG_MMCO) {
-        av_log(h->avctx, AV_LOG_DEBUG, "short term list:\n");
-        for (i = 0; i < h->short_ref_count; i++) {
-            H264Picture *pic = h->short_ref[i];
-            av_log(h->avctx, AV_LOG_DEBUG, "%"PRIu32" fn:%d poc:%d %p\n",
-                   i, pic->frame_num, pic->poc, pic->f->data[0]);
-        }
-    }
-}
-
-/**
- * print long term list
- */
-static void print_long_term(H264Context *h)
-{
-    uint32_t i;
-    if (h->avctx->debug & FF_DEBUG_MMCO) {
-        av_log(h->avctx, AV_LOG_DEBUG, "long term list:\n");
-        for (i = 0; i < 16; i++) {
-            H264Picture *pic = h->long_ref[i];
-            if (pic) {
-                av_log(h->avctx, AV_LOG_DEBUG, "%"PRIu32" fn:%d poc:%d %p\n",
-                       i, pic->frame_num, pic->poc, pic->f->data[0]);
-            }
-        }
-    }
-}
-
 static int check_opcodes(MMCO *mmco1, MMCO *mmco2, int n_mmcos)
 {
     int i;
@@ -593,7 +590,7 @@ int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice)
     int mmco_index = 0, i = 0;
 
     if (h->short_ref_count &&
-        h->long_ref_count + h->short_ref_count >= h->sps.ref_frame_count &&
+        h->long_ref_count + h->short_ref_count >= h->ps.sps->ref_frame_count &&
         !(FIELD_PICTURE(h) && !h->first_field && h->cur_pic_ptr->reference)) {
         mmco[0].opcode        = MMCO_SHORT2UNUSED;
         mmco[0].short_pic_num = h->short_ref[h->short_ref_count - 1]->frame_num;
@@ -622,7 +619,6 @@ int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice)
 int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count)
 {
     int i, av_uninit(j);
-    int pps_count;
     int pps_ref_count[2] = {0};
     int current_ref_assigned = 0, err = 0;
     H264Picture *av_uninit(pic);
@@ -678,7 +674,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count)
                 av_log(h->avctx, AV_LOG_DEBUG, "mmco: unref long failure\n");
             break;
         case MMCO_LONG:
-                    // Comment below left from previous code as it is an interresting note.
+                    // Comment below left from previous code as it is an interesting note.
                     /* First field in pair is in short term list or
                      * at a different long term index.
                      * This is not allowed; see 7.4.3.3, notes 2 and 3.
@@ -727,7 +723,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count)
             for (j = 0; j < 16; j++) {
                 remove_long(h, j, 0);
             }
-            h->frame_num  = h->cur_pic_ptr->frame_num = 0;
+            h->poc.frame_num = h->cur_pic_ptr->frame_num = 0;
             h->mmco_reset = 1;
             h->cur_pic_ptr->mmco_reset = 1;
             for (j = 0; j < MAX_DELAYED_PIC_COUNT; j++)
@@ -770,7 +766,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count)
         }
     }
 
-    if (h->long_ref_count + h->short_ref_count > FFMAX(h->sps.ref_frame_count, 1)) {
+    if (h->long_ref_count + h->short_ref_count > FFMAX(h->ps.sps->ref_frame_count, 1)) {
 
         /* We have too many reference frames, probably due to corrupted
          * stream. Need to discard one frame. Prevents overrun of the
@@ -779,7 +775,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count)
         av_log(h->avctx, AV_LOG_ERROR,
                "number of reference frames (%d+%d) exceeds max (%d; probably "
                "corrupt input), discarding one\n",
-               h->long_ref_count, h->short_ref_count, h->sps.ref_frame_count);
+               h->long_ref_count, h->short_ref_count, h->ps.sps->ref_frame_count);
         err = AVERROR_INVALIDDATA;
 
         if (h->long_ref_count && !h->short_ref_count) {
@@ -798,8 +794,8 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count)
     for (i = 0; i<h->short_ref_count; i++) {
         pic = h->short_ref[i];
         if (pic->invalid_gap) {
-            int d = av_mod_uintp2(h->cur_pic_ptr->frame_num - pic->frame_num, h->sps.log2_max_frame_num);
-            if (d > h->sps.ref_frame_count)
+            int d = av_mod_uintp2(h->cur_pic_ptr->frame_num - pic->frame_num, h->ps.sps->log2_max_frame_num);
+            if (d > h->ps.sps->ref_frame_count)
                 remove_short(h, pic->frame_num, 0);
         }
     }
@@ -807,11 +803,12 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count)
     print_short_term(h);
     print_long_term(h);
 
-    pps_count = 0;
-    for (i = 0; i < FF_ARRAY_ELEMS(h->pps_buffers); i++) {
-        pps_count += !!h->pps_buffers[i];
-        pps_ref_count[0] = FFMAX(pps_ref_count[0], h->pps.ref_count[0]);
-        pps_ref_count[1] = FFMAX(pps_ref_count[1], h->pps.ref_count[1]);
+    for (i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) {
+        if (h->ps.pps_list[i]) {
+            const PPS *pps = (const PPS *)h->ps.pps_list[i]->data;
+            pps_ref_count[0] = FFMAX(pps_ref_count[0], pps->ref_count[0]);
+            pps_ref_count[1] = FFMAX(pps_ref_count[1], pps->ref_count[1]);
+        }
     }
 
     if (   err >= 0
diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 77dd7b2..0bbd7e5 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -1,5 +1,5 @@
 /*
- * H.26L/H.264/AVC/JVT/14496-10/... sei decoding
+ * H.26L/H.264/AVC/JVT/14496-10/... SEI decoding
  * Copyright (c) 2003 Michael Niedermayer <michaelni at gmx.at>
  *
  * This file is part of FFmpeg.
@@ -21,124 +21,131 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 sei decoding.
+ * H.264 / AVC / MPEG-4 part10 SEI decoding.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
 #include "avcodec.h"
+#include "get_bits.h"
 #include "golomb.h"
 #include "h264.h"
+#include "h264_sei.h"
 #include "internal.h"
 
+#define AVERROR_PS_NOT_FOUND      FFERRTAG(0xF8,'?','P','S')
+
 static const uint8_t sei_num_clock_ts_table[9] = {
     1, 1, 1, 2, 2, 3, 3, 2, 3
 };
 
-void ff_h264_reset_sei(H264Context *h)
+void ff_h264_sei_uninit(H264SEIContext *h)
 {
-    h->sei_recovery_frame_cnt       = -1;
-    h->sei_dpb_output_delay         =  0;
-    h->sei_cpb_removal_delay        = -1;
-    h->sei_buffering_period_present =  0;
-    h->sei_frame_packing_present    =  0;
-    h->sei_display_orientation_present = 0;
-    h->sei_reguserdata_afd_present  =  0;
-
-    h->a53_caption_size = 0;
-    av_freep(&h->a53_caption);
+    h->recovery_point.recovery_frame_cnt = -1;
+
+    h->picture_timing.dpb_output_delay  = 0;
+    h->picture_timing.cpb_removal_delay = -1;
+
+    h->buffering_period.present    = 0;
+    h->frame_packing.present       = 0;
+    h->display_orientation.present = 0;
+    h->afd.present                 =  0;
+
+    h->a53_caption.a53_caption_size = 0;
+    av_freep(&h->a53_caption.a53_caption);
 }
 
-static int decode_picture_timing(H264Context *h)
+static int decode_picture_timing(H264SEIPictureTiming *h, GetBitContext *gb,
+                                 const H264ParamSets *ps, void *logctx)
 {
-    SPS *sps = &h->sps;
     int i;
+    const SPS *sps = ps->sps;
 
     for (i = 0; i<MAX_SPS_COUNT; i++)
-        if (!sps->log2_max_frame_num && h->sps_buffers[i])
-            sps = h->sps_buffers[i];
-
-    if (sps->nal_hrd_parameters_present_flag || sps->vcl_hrd_parameters_present_flag) {
-        h->sei_cpb_removal_delay = get_bits_long(&h->gb,
-                                                 sps->cpb_removal_delay_length);
-        h->sei_dpb_output_delay  = get_bits_long(&h->gb,
-                                                 sps->dpb_output_delay_length);
+        if ((!sps || !sps->log2_max_frame_num) && ps->sps_list[i])
+            sps = (const SPS *)ps->sps_list[i]->data;
+
+    if (!sps) {
+        av_log(logctx, AV_LOG_ERROR, "SPS unavailable in decode_picture_timing\n");
+        return AVERROR_PS_NOT_FOUND;
+    }
+
+    if (sps->nal_hrd_parameters_present_flag ||
+        sps->vcl_hrd_parameters_present_flag) {
+        h->cpb_removal_delay = get_bits_long(gb, sps->cpb_removal_delay_length);
+        h->dpb_output_delay  = get_bits_long(gb, sps->dpb_output_delay_length);
     }
     if (sps->pic_struct_present_flag) {
         unsigned int i, num_clock_ts;
 
-        h->sei_pic_struct = get_bits(&h->gb, 4);
-        h->sei_ct_type    = 0;
+        h->pic_struct = get_bits(gb, 4);
+        h->ct_type    = 0;
 
-        if (h->sei_pic_struct > SEI_PIC_STRUCT_FRAME_TRIPLING)
+        if (h->pic_struct > SEI_PIC_STRUCT_FRAME_TRIPLING)
             return AVERROR_INVALIDDATA;
 
-        num_clock_ts = sei_num_clock_ts_table[h->sei_pic_struct];
+        num_clock_ts = sei_num_clock_ts_table[h->pic_struct];
 
         for (i = 0; i < num_clock_ts; i++) {
-            if (get_bits(&h->gb, 1)) {                /* clock_timestamp_flag */
+            if (get_bits(gb, 1)) {                /* clock_timestamp_flag */
                 unsigned int full_timestamp_flag;
 
-                h->sei_ct_type |= 1 << get_bits(&h->gb, 2);
-                skip_bits(&h->gb, 1);                 /* nuit_field_based_flag */
-                skip_bits(&h->gb, 5);                 /* counting_type */
-                full_timestamp_flag = get_bits(&h->gb, 1);
-                skip_bits(&h->gb, 1);                 /* discontinuity_flag */
-                skip_bits(&h->gb, 1);                 /* cnt_dropped_flag */
-                skip_bits(&h->gb, 8);                 /* n_frames */
+                h->ct_type |= 1 << get_bits(gb, 2);
+                skip_bits(gb, 1);                 /* nuit_field_based_flag */
+                skip_bits(gb, 5);                 /* counting_type */
+                full_timestamp_flag = get_bits(gb, 1);
+                skip_bits(gb, 1);                 /* discontinuity_flag */
+                skip_bits(gb, 1);                 /* cnt_dropped_flag */
+                skip_bits(gb, 8);                 /* n_frames */
                 if (full_timestamp_flag) {
-                    skip_bits(&h->gb, 6);             /* seconds_value 0..59 */
-                    skip_bits(&h->gb, 6);             /* minutes_value 0..59 */
-                    skip_bits(&h->gb, 5);             /* hours_value 0..23 */
+                    skip_bits(gb, 6);             /* seconds_value 0..59 */
+                    skip_bits(gb, 6);             /* minutes_value 0..59 */
+                    skip_bits(gb, 5);             /* hours_value 0..23 */
                 } else {
-                    if (get_bits(&h->gb, 1)) {        /* seconds_flag */
-                        skip_bits(&h->gb, 6);         /* seconds_value range 0..59 */
-                        if (get_bits(&h->gb, 1)) {    /* minutes_flag */
-                            skip_bits(&h->gb, 6);     /* minutes_value 0..59 */
-                            if (get_bits(&h->gb, 1))  /* hours_flag */
-                                skip_bits(&h->gb, 5); /* hours_value 0..23 */
+                    if (get_bits(gb, 1)) {        /* seconds_flag */
+                        skip_bits(gb, 6);         /* seconds_value range 0..59 */
+                        if (get_bits(gb, 1)) {    /* minutes_flag */
+                            skip_bits(gb, 6);     /* minutes_value 0..59 */
+                            if (get_bits(gb, 1))  /* hours_flag */
+                                skip_bits(gb, 5); /* hours_value 0..23 */
                         }
                     }
                 }
                 if (sps->time_offset_length > 0)
-                    skip_bits(&h->gb,
+                    skip_bits(gb,
                               sps->time_offset_length); /* time_offset */
             }
         }
 
-        if (h->avctx->debug & FF_DEBUG_PICT_INFO)
-            av_log(h->avctx, AV_LOG_DEBUG, "ct_type:%X pic_struct:%d\n",
-                   h->sei_ct_type, h->sei_pic_struct);
+        av_log(logctx, AV_LOG_DEBUG, "ct_type:%X pic_struct:%d\n",
+               h->ct_type, h->pic_struct);
     }
     return 0;
 }
 
-static int decode_registered_user_data_afd(H264Context *h, int size)
+static int decode_registered_user_data_afd(H264SEIAFD *h, GetBitContext *gb, int size)
 {
     int flag;
 
     if (size-- < 1)
         return AVERROR_INVALIDDATA;
-    skip_bits(&h->gb, 1);               // 0
-    flag = get_bits(&h->gb, 1);         // active_format_flag
-    skip_bits(&h->gb, 6);               // reserved
+    skip_bits(gb, 1);               // 0
+    flag = get_bits(gb, 1);         // active_format_flag
+    skip_bits(gb, 6);               // reserved
 
     if (flag) {
         if (size-- < 1)
             return AVERROR_INVALIDDATA;
-        skip_bits(&h->gb, 4);           // reserved
-        h->active_format_description   = get_bits(&h->gb, 4);
-        h->sei_reguserdata_afd_present = 1;
-#if FF_API_AFD
-FF_DISABLE_DEPRECATION_WARNINGS
-        h->avctx->dtg_active_format = h->active_format_description;
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif /* FF_API_AFD */
+        skip_bits(gb, 4);           // reserved
+        h->active_format_description = get_bits(gb, 4);
+        h->present                   = 1;
     }
 
     return 0;
 }
 
-static int decode_registered_user_data_closed_caption(H264Context *h, int size)
+static int decode_registered_user_data_closed_caption(H264SEIA53Caption *h,
+                                                     GetBitContext *gb, void *logctx,
+                                                     int size)
 {
     int flag;
     int user_data_type_code;
@@ -147,15 +154,15 @@ static int decode_registered_user_data_closed_caption(H264Context *h, int size)
     if (size < 3)
         return AVERROR(EINVAL);
 
-    user_data_type_code = get_bits(&h->gb, 8);
+    user_data_type_code = get_bits(gb, 8);
     if (user_data_type_code == 0x3) {
-        skip_bits(&h->gb, 1);           // reserved
+        skip_bits(gb, 1);           // reserved
 
-        flag = get_bits(&h->gb, 1);     // process_cc_data_flag
+        flag = get_bits(gb, 1);     // process_cc_data_flag
         if (flag) {
-            skip_bits(&h->gb, 1);       // zero bit
-            cc_count = get_bits(&h->gb, 5);
-            skip_bits(&h->gb, 8);       // reserved
+            skip_bits(gb, 1);       // zero bit
+            cc_count = get_bits(gb, 5);
+            skip_bits(gb, 8);       // reserved
             size -= 2;
 
             if (cc_count && size >= cc_count * 3) {
@@ -172,24 +179,25 @@ static int decode_registered_user_data_closed_caption(H264Context *h, int size)
                     return ret;
 
                 for (i = 0; i < cc_count; i++) {
-                    h->a53_caption[h->a53_caption_size++] = get_bits(&h->gb, 8);
-                    h->a53_caption[h->a53_caption_size++] = get_bits(&h->gb, 8);
-                    h->a53_caption[h->a53_caption_size++] = get_bits(&h->gb, 8);
+                    h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
+                    h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
+                    h->a53_caption[h->a53_caption_size++] = get_bits(gb, 8);
                 }
 
-                skip_bits(&h->gb, 8);   // marker_bits
+                skip_bits(gb, 8);   // marker_bits
             }
         }
     } else {
         int i;
         for (i = 0; i < size - 1; i++)
-            skip_bits(&h->gb, 8);
+            skip_bits(gb, 8);
     }
 
     return 0;
 }
 
-static int decode_registered_user_data(H264Context *h, int size)
+static int decode_registered_user_data(H264SEIContext *h, GetBitContext *gb,
+                                       void *logctx, int size)
 {
     uint32_t country_code;
     uint32_t user_identifier;
@@ -198,31 +206,33 @@ static int decode_registered_user_data(H264Context *h, int size)
         return AVERROR_INVALIDDATA;
     size -= 7;
 
-    country_code = get_bits(&h->gb, 8); // itu_t_t35_country_code
+    country_code = get_bits(gb, 8); // itu_t_t35_country_code
     if (country_code == 0xFF) {
-        skip_bits(&h->gb, 8);           // itu_t_t35_country_code_extension_byte
+        skip_bits(gb, 8);           // itu_t_t35_country_code_extension_byte
         size--;
     }
 
     /* itu_t_t35_payload_byte follows */
-    skip_bits(&h->gb, 8);              // terminal provider code
-    skip_bits(&h->gb, 8);              // terminal provider oriented code
-    user_identifier = get_bits_long(&h->gb, 32);
+    skip_bits(gb, 8);              // terminal provider code
+    skip_bits(gb, 8);              // terminal provider oriented code
+    user_identifier = get_bits_long(gb, 32);
 
     switch (user_identifier) {
         case MKBETAG('D', 'T', 'G', '1'):       // afd_data
-            return decode_registered_user_data_afd(h, size);
+            return decode_registered_user_data_afd(&h->afd, gb, size);
         case MKBETAG('G', 'A', '9', '4'):       // closed captions
-            return decode_registered_user_data_closed_caption(h, size);
+            return decode_registered_user_data_closed_caption(&h->a53_caption, gb,
+                                                              logctx, size);
         default:
-            skip_bits(&h->gb, size * 8);
+            skip_bits(gb, size * 8);
             break;
     }
 
     return 0;
 }
 
-static int decode_unregistered_user_data(H264Context *h, int size)
+static int decode_unregistered_user_data(H264SEIUnregistered *h, GetBitContext *gb,
+                                         void *logctx, int size)
 {
     uint8_t *user_data;
     int e, build, i;
@@ -235,7 +245,7 @@ static int decode_unregistered_user_data(H264Context *h, int size)
         return AVERROR(ENOMEM);
 
     for (i = 0; i < size + 16; i++)
-        user_data[i] = get_bits(&h->gb, 8);
+        user_data[i] = get_bits(gb, 8);
 
     user_data[i] = 0;
     e = sscanf(user_data + 16, "x264 - core %d", &build);
@@ -245,280 +255,233 @@ static int decode_unregistered_user_data(H264Context *h, int size)
         h->x264_build = 67;
 
     if (strlen(user_data + 16) > 0)
-        av_log(h->avctx, AV_LOG_DEBUG, "user data:\"%s\"\n", user_data + 16);
+        av_log(logctx, AV_LOG_DEBUG, "user data:\"%s\"\n", user_data + 16);
 
     av_free(user_data);
     return 0;
 }
 
-static int decode_recovery_point(H264Context *h)
+static int decode_recovery_point(H264SEIRecoveryPoint *h, GetBitContext *gb)
 {
-    h->sei_recovery_frame_cnt = get_ue_golomb_long(&h->gb);
+    h->recovery_frame_cnt = get_ue_golomb_long(gb);
 
     /* 1b exact_match_flag,
      * 1b broken_link_flag,
      * 2b changing_slice_group_idc */
-    skip_bits(&h->gb, 4);
-
-    if (h->avctx->debug & FF_DEBUG_PICT_INFO)
-        av_log(h->avctx, AV_LOG_DEBUG, "sei_recovery_frame_cnt: %d\n", h->sei_recovery_frame_cnt);
-
-    h->has_recovery_point = 1;
+    skip_bits(gb, 4);
 
     return 0;
 }
 
-static int decode_buffering_period(H264Context *h)
+static int decode_buffering_period(H264SEIBufferingPeriod *h, GetBitContext *gb,
+                                   const H264ParamSets *ps, void *logctx)
 {
     unsigned int sps_id;
     int sched_sel_idx;
     SPS *sps;
 
-    sps_id = get_ue_golomb_31(&h->gb);
-    if (sps_id > 31 || !h->sps_buffers[sps_id]) {
-        av_log(h->avctx, AV_LOG_ERROR,
+    sps_id = get_ue_golomb_31(gb);
+    if (sps_id > 31 || !ps->sps_list[sps_id]) {
+        av_log(logctx, AV_LOG_ERROR,
                "non-existing SPS %d referenced in buffering period\n", sps_id);
-        return AVERROR_INVALIDDATA;
+        return sps_id > 31 ? AVERROR_INVALIDDATA : AVERROR_PS_NOT_FOUND;
     }
-    sps = h->sps_buffers[sps_id];
+    sps = (SPS*)ps->sps_list[sps_id]->data;
 
     // NOTE: This is really so duplicated in the standard... See H.264, D.1.1
     if (sps->nal_hrd_parameters_present_flag) {
         for (sched_sel_idx = 0; sched_sel_idx < sps->cpb_cnt; sched_sel_idx++) {
             h->initial_cpb_removal_delay[sched_sel_idx] =
-                get_bits_long(&h->gb, sps->initial_cpb_removal_delay_length);
+                get_bits_long(gb, sps->initial_cpb_removal_delay_length);
             // initial_cpb_removal_delay_offset
-            skip_bits(&h->gb, sps->initial_cpb_removal_delay_length);
+            skip_bits(gb, sps->initial_cpb_removal_delay_length);
         }
     }
     if (sps->vcl_hrd_parameters_present_flag) {
         for (sched_sel_idx = 0; sched_sel_idx < sps->cpb_cnt; sched_sel_idx++) {
             h->initial_cpb_removal_delay[sched_sel_idx] =
-                get_bits_long(&h->gb, sps->initial_cpb_removal_delay_length);
+                get_bits_long(gb, sps->initial_cpb_removal_delay_length);
             // initial_cpb_removal_delay_offset
-            skip_bits(&h->gb, sps->initial_cpb_removal_delay_length);
+            skip_bits(gb, sps->initial_cpb_removal_delay_length);
         }
     }
 
-    h->sei_buffering_period_present = 1;
+    h->present = 1;
     return 0;
 }
 
-static int decode_frame_packing_arrangement(H264Context *h)
+static int decode_frame_packing_arrangement(H264SEIFramePacking *h,
+                                            GetBitContext *gb)
 {
-    h->sei_fpa.frame_packing_arrangement_id          = get_ue_golomb_long(&h->gb);
-    h->sei_fpa.frame_packing_arrangement_cancel_flag = get_bits1(&h->gb);
-    h->sei_frame_packing_present = !h->sei_fpa.frame_packing_arrangement_cancel_flag;
-
-    if (h->sei_frame_packing_present) {
-        h->sei_fpa.frame_packing_arrangement_type =
-        h->frame_packing_arrangement_type = get_bits(&h->gb, 7);
-        h->sei_fpa.quincunx_sampling_flag         =
-        h->quincunx_subsampling           = get_bits1(&h->gb);
-        h->sei_fpa.content_interpretation_type    =
-        h->content_interpretation_type    = get_bits(&h->gb, 6);
+    h->frame_packing_arrangement_id          = get_ue_golomb_long(gb);
+    h->frame_packing_arrangement_cancel_flag = get_bits1(gb);
+    h->present = !h->frame_packing_arrangement_cancel_flag;
+
+    if (h->present) {
+        h->frame_packing_arrangement_type = get_bits(gb, 7);
+        h->quincunx_sampling_flag         = get_bits1(gb);
+        h->content_interpretation_type    = get_bits(gb, 6);
 
         // the following skips: spatial_flipping_flag, frame0_flipped_flag,
         // field_views_flag, current_frame_is_frame0_flag,
         // frame0_self_contained_flag, frame1_self_contained_flag
-        skip_bits(&h->gb, 6);
+        skip_bits(gb, 6);
 
-        if (!h->quincunx_subsampling && h->frame_packing_arrangement_type != 5)
-            skip_bits(&h->gb, 16);      // frame[01]_grid_position_[xy]
-        skip_bits(&h->gb, 8);           // frame_packing_arrangement_reserved_byte
-        h->sei_fpa.frame_packing_arrangement_repetition_period = get_ue_golomb_long(&h->gb);
+        if (!h->quincunx_sampling_flag && h->frame_packing_arrangement_type != 5)
+            skip_bits(gb, 16);      // frame[01]_grid_position_[xy]
+        skip_bits(gb, 8);           // frame_packing_arrangement_reserved_byte
+        h->frame_packing_arrangement_repetition_period = get_ue_golomb_long(gb);
     }
-    skip_bits1(&h->gb);                 // frame_packing_arrangement_extension_flag
-
-    if (h->avctx->debug & FF_DEBUG_PICT_INFO)
-        av_log(h->avctx, AV_LOG_DEBUG, "SEI FPA %d %d %d %d %d %d\n",
-                                       h->sei_fpa.frame_packing_arrangement_id,
-                                       h->sei_fpa.frame_packing_arrangement_cancel_flag,
-                                       h->sei_fpa.frame_packing_arrangement_type,
-                                       h->sei_fpa.quincunx_sampling_flag,
-                                       h->sei_fpa.content_interpretation_type,
-                                       h->sei_fpa.frame_packing_arrangement_repetition_period);
+    skip_bits1(gb);                 // frame_packing_arrangement_extension_flag
 
     return 0;
 }
 
-static int decode_display_orientation(H264Context *h)
+static int decode_display_orientation(H264SEIDisplayOrientation *h,
+                                      GetBitContext *gb)
 {
-    h->sei_display_orientation_present = !get_bits1(&h->gb);
+    h->present = !get_bits1(gb);
 
-    if (h->sei_display_orientation_present) {
-        h->sei_hflip = get_bits1(&h->gb);     // hor_flip
-        h->sei_vflip = get_bits1(&h->gb);     // ver_flip
+    if (h->present) {
+        h->hflip = get_bits1(gb);     // hor_flip
+        h->vflip = get_bits1(gb);     // ver_flip
 
-        h->sei_anticlockwise_rotation = get_bits(&h->gb, 16);
-        get_ue_golomb_long(&h->gb);  // display_orientation_repetition_period
-        skip_bits1(&h->gb);          // display_orientation_extension_flag
+        h->anticlockwise_rotation = get_bits(gb, 16);
+        get_ue_golomb_long(gb);       // display_orientation_repetition_period
+        skip_bits1(gb);               // display_orientation_extension_flag
     }
 
     return 0;
 }
 
-static int decode_GreenMetadata(H264Context *h)
+static int decode_green_metadata(H264SEIGreenMetaData *h, GetBitContext *gb)
 {
-    if (h->avctx->debug & FF_DEBUG_GREEN_MD)
-        av_log(h->avctx, AV_LOG_DEBUG,          "Green Metadata Info SEI message\n");
-
-    h->sei_green_metadata.green_metadata_type=get_bits(&h->gb, 8);
-
-    if (h->avctx->debug & FF_DEBUG_GREEN_MD)
-        av_log(h->avctx, AV_LOG_DEBUG,          "green_metadata_type                            = %d\n",
-               h->sei_green_metadata.green_metadata_type);
+    h->green_metadata_type = get_bits(gb, 8);
 
-    if (h->sei_green_metadata.green_metadata_type==0){
-        h->sei_green_metadata.period_type=get_bits(&h->gb, 8);
+    if (h->green_metadata_type == 0) {
+        h->period_type = get_bits(gb, 8);
 
-        if (h->avctx->debug & FF_DEBUG_GREEN_MD)
-            av_log(h->avctx, AV_LOG_DEBUG,      "green_metadata_period_type                     = %d\n",
-                   h->sei_green_metadata.period_type);
+        if (h->period_type == 2)
+            h->num_seconds = get_bits(gb, 16);
+        else if (h->period_type == 3)
+            h->num_pictures = get_bits(gb, 16);
 
-        if (h->sei_green_metadata.green_metadata_type==2){
-            h->sei_green_metadata.num_seconds = get_bits(&h->gb, 16);
-            if (h->avctx->debug & FF_DEBUG_GREEN_MD)
-                av_log(h->avctx, AV_LOG_DEBUG,  "green_metadata_num_seconds                     = %d\n",
-                       h->sei_green_metadata.num_seconds);
-        }
-        else if (h->sei_green_metadata.period_type==3){
-            h->sei_green_metadata.num_pictures = get_bits(&h->gb, 16);
-            if (h->avctx->debug & FF_DEBUG_GREEN_MD)
-                av_log(h->avctx, AV_LOG_DEBUG,  "green_metadata_num_pictures                    = %d\n",
-                       h->sei_green_metadata.num_pictures);
-        }
+        h->percent_non_zero_macroblocks            = get_bits(gb, 8);
+        h->percent_intra_coded_macroblocks         = get_bits(gb, 8);
+        h->percent_six_tap_filtering               = get_bits(gb, 8);
+        h->percent_alpha_point_deblocking_instance = get_bits(gb, 8);
 
-        h->sei_green_metadata.percent_non_zero_macroblocks=get_bits(&h->gb, 8);
-        h->sei_green_metadata.percent_intra_coded_macroblocks=get_bits(&h->gb, 8);
-        h->sei_green_metadata.percent_six_tap_filtering=get_bits(&h->gb, 8);
-        h->sei_green_metadata.percent_alpha_point_deblocking_instance=get_bits(&h->gb, 8);
-
-        if (h->avctx->debug & FF_DEBUG_GREEN_MD)
-            av_log(h->avctx, AV_LOG_DEBUG,      "SEI GREEN Complexity Metrics                   = %f %f %f %f\n",
-                                           (float)h->sei_green_metadata.percent_non_zero_macroblocks/255,
-                                           (float)h->sei_green_metadata.percent_intra_coded_macroblocks/255,
-                                           (float)h->sei_green_metadata.percent_six_tap_filtering/255,
-                                           (float)h->sei_green_metadata.percent_alpha_point_deblocking_instance/255);
-
-    }else if( h->sei_green_metadata.green_metadata_type==1){
-        h->sei_green_metadata.xsd_metric_type=get_bits(&h->gb, 8);
-        h->sei_green_metadata.xsd_metric_value=get_bits(&h->gb, 16);
-
-        if (h->avctx->debug & FF_DEBUG_GREEN_MD)
-            av_log(h->avctx, AV_LOG_DEBUG,      "xsd_metric_type                                = %d\n",
-                   h->sei_green_metadata.xsd_metric_type);
-        if ( h->sei_green_metadata.xsd_metric_type==0){
-            if (h->avctx->debug & FF_DEBUG_GREEN_MD)
-                av_log(h->avctx, AV_LOG_DEBUG,  "xsd_metric_value                               = %f\n",
-                       (float)h->sei_green_metadata.xsd_metric_value/100);
-        }
+    } else if (h->green_metadata_type == 1) {
+        h->xsd_metric_type  = get_bits(gb, 8);
+        h->xsd_metric_value = get_bits(gb, 16);
     }
 
     return 0;
 }
 
-int ff_h264_decode_sei(H264Context *h)
+int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb,
+                       const H264ParamSets *ps, void *logctx)
 {
-    while (get_bits_left(&h->gb) > 16 && show_bits(&h->gb, 16)) {
+    int master_ret = 0;
+
+    while (get_bits_left(gb) > 16 && show_bits(gb, 16)) {
         int type = 0;
         unsigned size = 0;
         unsigned next;
         int ret  = 0;
 
         do {
-            if (get_bits_left(&h->gb) < 8)
+            if (get_bits_left(gb) < 8)
                 return AVERROR_INVALIDDATA;
-            type += show_bits(&h->gb, 8);
-        } while (get_bits(&h->gb, 8) == 255);
+            type += show_bits(gb, 8);
+        } while (get_bits(gb, 8) == 255);
 
         do {
-            if (get_bits_left(&h->gb) < 8)
+            if (get_bits_left(gb) < 8)
                 return AVERROR_INVALIDDATA;
-            size += show_bits(&h->gb, 8);
-        } while (get_bits(&h->gb, 8) == 255);
-
-        if (h->avctx->debug&FF_DEBUG_STARTCODE)
-            av_log(h->avctx, AV_LOG_DEBUG, "SEI %d len:%d\n", type, size);
+            size += show_bits(gb, 8);
+        } while (get_bits(gb, 8) == 255);
 
-        if (size > get_bits_left(&h->gb) / 8) {
-            av_log(h->avctx, AV_LOG_ERROR, "SEI type %d size %d truncated at %d\n",
-                   type, 8*size, get_bits_left(&h->gb));
+        if (size > get_bits_left(gb) / 8) {
+            av_log(logctx, AV_LOG_ERROR, "SEI type %d size %d truncated at %d\n",
+                   type, 8*size, get_bits_left(gb));
             return AVERROR_INVALIDDATA;
         }
-        next = get_bits_count(&h->gb) + 8 * size;
+        next = get_bits_count(gb) + 8 * size;
 
         switch (type) {
         case SEI_TYPE_PIC_TIMING: // Picture timing SEI
-            ret = decode_picture_timing(h);
+            ret = decode_picture_timing(&h->picture_timing, gb, ps, logctx);
             break;
         case SEI_TYPE_USER_DATA_REGISTERED:
-            ret = decode_registered_user_data(h, size);
+            ret = decode_registered_user_data(h, gb, logctx, size);
             break;
         case SEI_TYPE_USER_DATA_UNREGISTERED:
-            ret = decode_unregistered_user_data(h, size);
+            ret = decode_unregistered_user_data(&h->unregistered, gb, logctx, size);
             break;
         case SEI_TYPE_RECOVERY_POINT:
-            ret = decode_recovery_point(h);
+            ret = decode_recovery_point(&h->recovery_point, gb);
             break;
         case SEI_TYPE_BUFFERING_PERIOD:
-            ret = decode_buffering_period(h);
+            ret = decode_buffering_period(&h->buffering_period, gb, ps, logctx);
             break;
         case SEI_TYPE_FRAME_PACKING:
-            ret = decode_frame_packing_arrangement(h);
+            ret = decode_frame_packing_arrangement(&h->frame_packing, gb);
             break;
         case SEI_TYPE_DISPLAY_ORIENTATION:
-            ret = decode_display_orientation(h);
+            ret = decode_display_orientation(&h->display_orientation, gb);
             break;
         case SEI_TYPE_GREEN_METADATA:
-            ret = decode_GreenMetadata(h);
+            ret = decode_green_metadata(&h->green_metadata, gb);
             break;
         default:
-            av_log(h->avctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type);
+            av_log(logctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type);
         }
-        if (ret < 0)
+        if (ret < 0 && ret != AVERROR_PS_NOT_FOUND)
             return ret;
+        if (ret < 0)
+            master_ret = ret;
 
-        skip_bits_long(&h->gb, next - get_bits_count(&h->gb));
+        skip_bits_long(gb, next - get_bits_count(gb));
 
         // FIXME check bits here
-        align_get_bits(&h->gb);
+        align_get_bits(gb);
     }
 
-    return 0;
+    return master_ret;
 }
 
-const char* ff_h264_sei_stereo_mode(H264Context *h)
+const char *ff_h264_sei_stereo_mode(const H264SEIFramePacking *h)
 {
-    if (h->sei_fpa.frame_packing_arrangement_cancel_flag == 0) {
-        switch (h->sei_fpa.frame_packing_arrangement_type) {
+    if (h->frame_packing_arrangement_cancel_flag == 0) {
+        switch (h->frame_packing_arrangement_type) {
             case SEI_FPA_TYPE_CHECKERBOARD:
-                if (h->sei_fpa.content_interpretation_type == 2)
+                if (h->content_interpretation_type == 2)
                     return "checkerboard_rl";
                 else
                     return "checkerboard_lr";
             case SEI_FPA_TYPE_INTERLEAVE_COLUMN:
-                if (h->sei_fpa.content_interpretation_type == 2)
+                if (h->content_interpretation_type == 2)
                     return "col_interleaved_rl";
                 else
                     return "col_interleaved_lr";
             case SEI_FPA_TYPE_INTERLEAVE_ROW:
-                if (h->sei_fpa.content_interpretation_type == 2)
+                if (h->content_interpretation_type == 2)
                     return "row_interleaved_rl";
                 else
                     return "row_interleaved_lr";
             case SEI_FPA_TYPE_SIDE_BY_SIDE:
-                if (h->sei_fpa.content_interpretation_type == 2)
+                if (h->content_interpretation_type == 2)
                     return "right_left";
                 else
                     return "left_right";
             case SEI_FPA_TYPE_TOP_BOTTOM:
-                if (h->sei_fpa.content_interpretation_type == 2)
+                if (h->content_interpretation_type == 2)
                     return "bottom_top";
                 else
                     return "top_bottom";
             case SEI_FPA_TYPE_INTERLEAVE_TEMPORAL:
-                if (h->sei_fpa.content_interpretation_type == 2)
+                if (h->content_interpretation_type == 2)
                     return "block_rl";
                 else
                     return "block_lr";
@@ -526,7 +489,7 @@ const char* ff_h264_sei_stereo_mode(H264Context *h)
             default:
                 return "mono";
         }
-    } else if (h->sei_fpa.frame_packing_arrangement_cancel_flag == 1) {
+    } else if (h->frame_packing_arrangement_cancel_flag == 1) {
         return "mono";
     } else {
         return NULL;
diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h
new file mode 100644
index 0000000..9197795
--- /dev/null
+++ b/libavcodec/h264_sei.h
@@ -0,0 +1,173 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_H264_SEI_H
+#define AVCODEC_H264_SEI_H
+
+#include "get_bits.h"
+
+/**
+ * SEI message types
+ */
+typedef enum {
+    SEI_TYPE_BUFFERING_PERIOD       = 0,   ///< buffering period (H.264, D.1.1)
+    SEI_TYPE_PIC_TIMING             = 1,   ///< picture timing
+    SEI_TYPE_USER_DATA_REGISTERED   = 4,   ///< registered user data as specified by Rec. ITU-T T.35
+    SEI_TYPE_USER_DATA_UNREGISTERED = 5,   ///< unregistered user data
+    SEI_TYPE_RECOVERY_POINT         = 6,   ///< recovery point (frame # to decoder sync)
+    SEI_TYPE_FRAME_PACKING          = 45,  ///< frame packing arrangement
+    SEI_TYPE_DISPLAY_ORIENTATION    = 47,  ///< display orientation
+    SEI_TYPE_GREEN_METADATA         = 56   ///< GreenMPEG information
+} SEI_Type;
+
+/**
+ * pic_struct in picture timing SEI message
+ */
+typedef enum {
+    SEI_PIC_STRUCT_FRAME             = 0, ///<  0: %frame
+    SEI_PIC_STRUCT_TOP_FIELD         = 1, ///<  1: top field
+    SEI_PIC_STRUCT_BOTTOM_FIELD      = 2, ///<  2: bottom field
+    SEI_PIC_STRUCT_TOP_BOTTOM        = 3, ///<  3: top field, bottom field, in that order
+    SEI_PIC_STRUCT_BOTTOM_TOP        = 4, ///<  4: bottom field, top field, in that order
+    SEI_PIC_STRUCT_TOP_BOTTOM_TOP    = 5, ///<  5: top field, bottom field, top field repeated, in that order
+    SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM = 6, ///<  6: bottom field, top field, bottom field repeated, in that order
+    SEI_PIC_STRUCT_FRAME_DOUBLING    = 7, ///<  7: %frame doubling
+    SEI_PIC_STRUCT_FRAME_TRIPLING    = 8  ///<  8: %frame tripling
+} SEI_PicStructType;
+
+/**
+ * frame_packing_arrangement types
+ */
+typedef enum {
+    SEI_FPA_TYPE_CHECKERBOARD        = 0,
+    SEI_FPA_TYPE_INTERLEAVE_COLUMN   = 1,
+    SEI_FPA_TYPE_INTERLEAVE_ROW      = 2,
+    SEI_FPA_TYPE_SIDE_BY_SIDE        = 3,
+    SEI_FPA_TYPE_TOP_BOTTOM          = 4,
+    SEI_FPA_TYPE_INTERLEAVE_TEMPORAL = 5,
+    SEI_FPA_TYPE_2D                  = 6,
+} SEI_FpaType;
+
+typedef struct H264SEIPictureTiming {
+    SEI_PicStructType pic_struct;
+
+    /**
+     * Bit set of clock types for fields/frames in picture timing SEI message.
+     * For each found ct_type, appropriate bit is set (e.g., bit 1 for
+     * interlaced).
+     */
+    int ct_type;
+
+    /**
+     * dpb_output_delay in picture timing SEI message, see H.264 C.2.2
+     */
+    int dpb_output_delay;
+
+    /**
+     * cpb_removal_delay in picture timing SEI message, see H.264 C.1.2
+     */
+    int cpb_removal_delay;
+} H264SEIPictureTiming;
+
+typedef struct H264SEIAFD {
+    int present;
+    uint8_t active_format_description;
+} H264SEIAFD;
+
+typedef struct H264SEIA53Caption {
+    int a53_caption_size;
+    uint8_t *a53_caption;
+} H264SEIA53Caption;
+
+typedef struct H264SEIUnregistered {
+    int x264_build;
+} H264SEIUnregistered;
+
+typedef struct H264SEIRecoveryPoint {
+    /**
+     * recovery_frame_cnt
+     *
+     * Set to -1 if no recovery point SEI message found or to number of frames
+     * before playback synchronizes. Frames having recovery point are key
+     * frames.
+     */
+    int recovery_frame_cnt;
+} H264SEIRecoveryPoint;
+
+typedef struct H264SEIBufferingPeriod {
+    int present;   ///< Buffering period SEI flag
+    int initial_cpb_removal_delay[32];  ///< Initial timestamps for CPBs
+} H264SEIBufferingPeriod;
+
+typedef struct H264SEIFramePacking {
+    int present;
+    int frame_packing_arrangement_id;
+    int frame_packing_arrangement_cancel_flag;  ///< is previous arrangement canceled, -1 if never received
+    SEI_FpaType frame_packing_arrangement_type;
+    int frame_packing_arrangement_repetition_period;
+    int content_interpretation_type;
+    int quincunx_sampling_flag;
+} H264SEIFramePacking;
+
+typedef struct H264SEIDisplayOrientation {
+    int present;
+    int anticlockwise_rotation;
+    int hflip, vflip;
+} H264SEIDisplayOrientation;
+
+typedef struct H264SEIGreenMetaData {
+    uint8_t green_metadata_type;
+    uint8_t period_type;
+    uint16_t num_seconds;
+    uint16_t num_pictures;
+    uint8_t percent_non_zero_macroblocks;
+    uint8_t percent_intra_coded_macroblocks;
+    uint8_t percent_six_tap_filtering;
+    uint8_t percent_alpha_point_deblocking_instance;
+    uint8_t xsd_metric_type;
+    uint16_t xsd_metric_value;
+} H264SEIGreenMetaData;
+
+typedef struct H264SEIContext {
+    H264SEIPictureTiming picture_timing;
+    H264SEIAFD afd;
+    H264SEIA53Caption a53_caption;
+    H264SEIUnregistered unregistered;
+    H264SEIRecoveryPoint recovery_point;
+    H264SEIBufferingPeriod buffering_period;
+    H264SEIFramePacking frame_packing;
+    H264SEIDisplayOrientation display_orientation;
+    H264SEIGreenMetaData green_metadata;
+} H264SEIContext;
+
+struct H264ParamSets;
+
+int ff_h264_sei_decode(H264SEIContext *h, GetBitContext *gb,
+                       const struct H264ParamSets *ps, void *logctx);
+
+/**
+ * Reset SEI values at the beginning of the frame.
+ */
+void ff_h264_sei_uninit(H264SEIContext *h);
+
+/**
+ * Get stereo_mode string from the h264 frame_packing_arrangement
+ */
+const char *ff_h264_sei_stereo_mode(const H264SEIFramePacking *h);
+
+#endif /* AVCODEC_H264_SEI_H */
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 0b3e040..474400b 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 codec.
+ * H.264 / AVC / MPEG-4 part10 codec.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -43,23 +43,6 @@
 #include "rectangle.h"
 #include "thread.h"
 
-
-static const uint8_t rem6[QP_MAX_NUM + 1] = {
-    0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2,
-    3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,
-    0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2,
-    3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,
-    0, 1, 2, 3,
-};
-
-static const uint8_t div6[QP_MAX_NUM + 1] = {
-    0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3,  3,  3,
-    3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,  6,  6,
-    7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10,
-   10,10,10,11,11,11,11,11,11,12,12,12,12,12,12,13,13,13, 13, 13, 13,
-   14,14,14,14,
-};
-
 static const uint8_t field_scan[16+1] = {
     0 + 0 * 4, 0 + 1 * 4, 1 + 0 * 4, 0 + 2 * 4,
     0 + 3 * 4, 1 + 1 * 4, 1 + 2 * 4, 1 + 3 * 4,
@@ -125,29 +108,6 @@ static const uint8_t zigzag_scan8x8_cavlc[64+1] = {
     5 + 5 * 8, 6 + 5 * 8, 6 + 6 * 8, 7 + 7 * 8,
 };
 
-static const uint8_t dequant4_coeff_init[6][3] = {
-    { 10, 13, 16 },
-    { 11, 14, 18 },
-    { 13, 16, 20 },
-    { 14, 18, 23 },
-    { 16, 20, 25 },
-    { 18, 23, 29 },
-};
-
-static const uint8_t dequant8_coeff_init_scan[16] = {
-    0, 3, 4, 3, 3, 1, 5, 1, 4, 5, 2, 5, 3, 1, 5, 1
-};
-
-static const uint8_t dequant8_coeff_init[6][6] = {
-    { 20, 18, 32, 19, 25, 24 },
-    { 22, 19, 35, 21, 28, 26 },
-    { 26, 23, 42, 24, 33, 31 },
-    { 28, 25, 45, 26, 35, 33 },
-    { 32, 28, 51, 30, 40, 38 },
-    { 36, 32, 58, 34, 46, 43 },
-};
-
-
 static void release_unused_pictures(H264Context *h, int remove_current)
 {
     int i;
@@ -168,7 +128,7 @@ static int alloc_scratch_buffers(H264SliceContext *sl, int linesize)
 
     av_fast_malloc(&sl->bipred_scratchpad, &sl->bipred_scratchpad_allocated, 16 * 6 * alloc_size);
     // edge emu needs blocksize + filter length - 1
-    // (= 21x21 for  h264)
+    // (= 21x21 for  H.264)
     av_fast_malloc(&sl->edge_emu_buffer, &sl->edge_emu_buffer_allocated, alloc_size * 2 * 21);
 
     av_fast_mallocz(&sl->top_borders[0], &sl->top_borders_allocated[0],
@@ -232,9 +192,9 @@ static int alloc_picture(H264Context *h, H264Picture *pic)
     if (ret < 0)
         goto fail;
 
-    pic->crop     = h->sps.crop;
-    pic->crop_top = h->sps.crop_top;
-    pic->crop_left= h->sps.crop_left;
+    pic->crop     = h->ps.sps->crop;
+    pic->crop_top = h->ps.sps->crop_top;
+    pic->crop_left= h->ps.sps->crop_left;
 
     if (h->avctx->hwaccel) {
         const AVHWAccel *hwaccel = h->avctx->hwaccel;
@@ -311,78 +271,6 @@ static int find_unused_picture(H264Context *h)
 }
 
 
-static void init_dequant8_coeff_table(H264Context *h)
-{
-    int i, j, q, x;
-    const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8);
-
-    for (i = 0; i < 6; i++) {
-        h->dequant8_coeff[i] = h->dequant8_buffer[i];
-        for (j = 0; j < i; j++)
-            if (!memcmp(h->pps.scaling_matrix8[j], h->pps.scaling_matrix8[i],
-                        64 * sizeof(uint8_t))) {
-                h->dequant8_coeff[i] = h->dequant8_buffer[j];
-                break;
-            }
-        if (j < i)
-            continue;
-
-        for (q = 0; q < max_qp + 1; q++) {
-            int shift = div6[q];
-            int idx   = rem6[q];
-            for (x = 0; x < 64; x++)
-                h->dequant8_coeff[i][q][(x >> 3) | ((x & 7) << 3)] =
-                    ((uint32_t)dequant8_coeff_init[idx][dequant8_coeff_init_scan[((x >> 1) & 12) | (x & 3)]] *
-                     h->pps.scaling_matrix8[i][x]) << shift;
-        }
-    }
-}
-
-static void init_dequant4_coeff_table(H264Context *h)
-{
-    int i, j, q, x;
-    const int max_qp = 51 + 6 * (h->sps.bit_depth_luma - 8);
-    for (i = 0; i < 6; i++) {
-        h->dequant4_coeff[i] = h->dequant4_buffer[i];
-        for (j = 0; j < i; j++)
-            if (!memcmp(h->pps.scaling_matrix4[j], h->pps.scaling_matrix4[i],
-                        16 * sizeof(uint8_t))) {
-                h->dequant4_coeff[i] = h->dequant4_buffer[j];
-                break;
-            }
-        if (j < i)
-            continue;
-
-        for (q = 0; q < max_qp + 1; q++) {
-            int shift = div6[q] + 2;
-            int idx   = rem6[q];
-            for (x = 0; x < 16; x++)
-                h->dequant4_coeff[i][q][(x >> 2) | ((x << 2) & 0xF)] =
-                    ((uint32_t)dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] *
-                     h->pps.scaling_matrix4[i][x]) << shift;
-        }
-    }
-}
-
-void ff_h264_init_dequant_tables(H264Context *h)
-{
-    int i, x;
-    init_dequant4_coeff_table(h);
-    memset(h->dequant8_coeff, 0, sizeof(h->dequant8_coeff));
-
-    if (h->pps.transform_8x8_mode)
-        init_dequant8_coeff_table(h);
-    if (h->sps.transform_bypass) {
-        for (i = 0; i < 6; i++)
-            for (x = 0; x < 16; x++)
-                h->dequant4_coeff[i][0][x] = 1 << 6;
-        if (h->pps.transform_8x8_mode)
-            for (i = 0; i < 6; i++)
-                for (x = 0; x < 64; x++)
-                    h->dequant8_coeff[i][0][x] = 1 << 6;
-    }
-}
-
 #define IN_RANGE(a, b, size) (((void*)(a) >= (void*)(b)) && ((void*)(a) < (void*)((b) + (size))))
 
 #define REBASE_PICTURE(pic, new_ctx, old_ctx)             \
@@ -404,30 +292,6 @@ static void copy_picture_range(H264Picture **to, H264Picture **from, int count,
     }
 }
 
-static int copy_parameter_set(void **to, void **from, int count, int size)
-{
-    int i;
-
-    for (i = 0; i < count; i++) {
-        if (to[i] && !from[i]) {
-            av_freep(&to[i]);
-        } else if (from[i] && !to[i]) {
-            to[i] = av_malloc(size);
-            if (!to[i])
-                return AVERROR(ENOMEM);
-        }
-
-        if (from[i])
-            memcpy(to[i], from[i], size);
-    }
-
-    return 0;
-}
-
-#define copy_fields(to, from, start_field, end_field)                   \
-    memcpy(&(to)->start_field, &(from)->start_field,                        \
-           (char *)&(to)->end_field - (char *)&(to)->start_field)
-
 static int h264_slice_header_init(H264Context *h);
 
 int ff_h264_update_thread_context(AVCodecContext *dst,
@@ -441,15 +305,19 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
     if (dst == src)
         return 0;
 
+    // We can't fail if SPS isn't set at it breaks current skip_frame code
+    //if (!h1->ps.sps)
+    //    return AVERROR_INVALIDDATA;
+
     if (inited &&
         (h->width                 != h1->width                 ||
          h->height                != h1->height                ||
          h->mb_width              != h1->mb_width              ||
          h->mb_height             != h1->mb_height             ||
-         h->sps.bit_depth_luma    != h1->sps.bit_depth_luma    ||
-         h->sps.chroma_format_idc != h1->sps.chroma_format_idc ||
-         h->sps.colorspace        != h1->sps.colorspace)) {
-
+         !h->ps.sps                                            ||
+         h->ps.sps->bit_depth_luma    != h1->ps.sps->bit_depth_luma    ||
+         h->ps.sps->chroma_format_idc != h1->ps.sps->chroma_format_idc ||
+         h->ps.sps->colorspace        != h1->ps.sps->colorspace)) {
         need_reinit = 1;
     }
 
@@ -457,16 +325,39 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
     memcpy(h->block_offset, h1->block_offset, sizeof(h->block_offset));
 
     // SPS/PPS
-    if ((ret = copy_parameter_set((void **)h->sps_buffers,
-                                  (void **)h1->sps_buffers,
-                                  MAX_SPS_COUNT, sizeof(SPS))) < 0)
-        return ret;
-    h->sps = h1->sps;
-    if ((ret = copy_parameter_set((void **)h->pps_buffers,
-                                  (void **)h1->pps_buffers,
-                                  MAX_PPS_COUNT, sizeof(PPS))) < 0)
-        return ret;
-    h->pps = h1->pps;
+    for (i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) {
+        av_buffer_unref(&h->ps.sps_list[i]);
+        if (h1->ps.sps_list[i]) {
+            h->ps.sps_list[i] = av_buffer_ref(h1->ps.sps_list[i]);
+            if (!h->ps.sps_list[i])
+                return AVERROR(ENOMEM);
+        }
+    }
+    for (i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) {
+        av_buffer_unref(&h->ps.pps_list[i]);
+        if (h1->ps.pps_list[i]) {
+            h->ps.pps_list[i] = av_buffer_ref(h1->ps.pps_list[i]);
+            if (!h->ps.pps_list[i])
+                return AVERROR(ENOMEM);
+        }
+    }
+
+    av_buffer_unref(&h->ps.pps_ref);
+    av_buffer_unref(&h->ps.sps_ref);
+    h->ps.pps = NULL;
+    h->ps.sps = NULL;
+    if (h1->ps.pps_ref) {
+        h->ps.pps_ref = av_buffer_ref(h1->ps.pps_ref);
+        if (!h->ps.pps_ref)
+            return AVERROR(ENOMEM);
+        h->ps.pps = (const PPS*)h->ps.pps_ref->data;
+    }
+    if (h1->ps.sps_ref) {
+        h->ps.sps_ref = av_buffer_ref(h1->ps.sps_ref);
+        if (!h->ps.sps_ref)
+            return AVERROR(ENOMEM);
+        h->ps.sps = (SPS*)h->ps.sps_ref->data;
+    }
 
     if (need_reinit || !inited) {
         h->width     = h1->width;
@@ -495,7 +386,6 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
     h->first_field          = h1->first_field;
     h->picture_structure    = h1->picture_structure;
     h->droppable            = h1->droppable;
-    h->low_delay            = h1->low_delay;
     h->backup_width         = h1->backup_width;
     h->backup_height        = h1->backup_height;
     h->backup_pix_fmt       = h1->backup_pix_fmt;
@@ -517,30 +407,32 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
 
     h->enable_er       = h1->enable_er;
     h->workaround_bugs = h1->workaround_bugs;
-    h->low_delay       = h1->low_delay;
     h->droppable       = h1->droppable;
 
     // extradata/NAL handling
     h->is_avc = h1->is_avc;
     h->nal_length_size = h1->nal_length_size;
-    h->x264_build      = h1->x264_build;
+    h->sei.unregistered.x264_build = h1->sei.unregistered.x264_build;
 
-    // Dequantization matrices
-    // FIXME these are big - can they be only copied when PPS changes?
-    copy_fields(h, h1, dequant4_buffer, dequant4_coeff);
+    memcpy(&h->poc,        &h1->poc,        sizeof(h->poc));
 
-    for (i = 0; i < 6; i++)
-        h->dequant4_coeff[i] = h->dequant4_buffer[0] +
-                               (h1->dequant4_coeff[i] - h1->dequant4_buffer[0]);
+    h->curr_pic_num      = h1->curr_pic_num;
+    h->max_pic_num       = h1->max_pic_num;
 
-    for (i = 0; i < 6; i++)
-        h->dequant8_coeff[i] = h->dequant8_buffer[0] +
-                               (h1->dequant8_coeff[i] - h1->dequant8_buffer[0]);
+    memcpy(h->default_ref, h1->default_ref, sizeof(h->default_ref));
+    memcpy(h->short_ref,   h1->short_ref,   sizeof(h->short_ref));
+    memcpy(h->long_ref,    h1->long_ref,    sizeof(h->long_ref));
+    memcpy(h->delayed_pic, h1->delayed_pic, sizeof(h->delayed_pic));
+    memcpy(h->last_pocs,   h1->last_pocs,   sizeof(h->last_pocs));
 
-    h->dequant_coeff_pps = h1->dequant_coeff_pps;
+    h->next_output_pic   = h1->next_output_pic;
+    h->next_outputed_poc = h1->next_outputed_poc;
 
-    // POC timing
-    copy_fields(h, h1, poc_lsb, current_slice);
+    memcpy(h->mmco, h1->mmco, sizeof(h->mmco));
+    h->mmco_index      = h1->mmco_index;
+    h->mmco_reset      = h1->mmco_reset;
+    h->long_ref_count  = h1->long_ref_count;
+    h->short_ref_count = h1->short_ref_count;
 
     copy_picture_range(h->short_ref, h1->short_ref, 32, h, h1);
     copy_picture_range(h->long_ref, h1->long_ref, 32, h, h1);
@@ -554,11 +446,11 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
 
     if (!h->droppable) {
         err = ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index);
-        h->prev_poc_msb = h->poc_msb;
-        h->prev_poc_lsb = h->poc_lsb;
+        h->poc.prev_poc_msb = h->poc.poc_msb;
+        h->poc.prev_poc_lsb = h->poc.poc_lsb;
     }
-    h->prev_frame_num_offset = h->frame_num_offset;
-    h->prev_frame_num        = h->frame_num;
+    h->poc.prev_frame_num_offset = h->poc.frame_num_offset;
+    h->poc.prev_frame_num        = h->poc.frame_num;
 
     h->recovery_frame        = h1->recovery_frame;
 
@@ -571,9 +463,9 @@ static int h264_frame_start(H264Context *h)
     int i, ret;
     const int pixel_shift = h->pixel_shift;
     int c[4] = {
-        1<<(h->sps.bit_depth_luma-1),
-        1<<(h->sps.bit_depth_chroma-1),
-        1<<(h->sps.bit_depth_chroma-1),
+        1<<(h->ps.sps->bit_depth_luma-1),
+        1<<(h->ps.sps->bit_depth_chroma-1),
+        1<<(h->ps.sps->bit_depth_chroma-1),
         -1
     };
 
@@ -595,8 +487,7 @@ static int h264_frame_start(H264Context *h)
     pic->reference              = h->droppable ? 0 : h->picture_structure;
     pic->f->coded_picture_number = h->coded_picture_number++;
     pic->field_picture          = h->picture_structure != PICT_FRAME;
-    pic->frame_num               = h->frame_num;
-
+    pic->frame_num               = h->poc.frame_num;
     /*
      * Zero key_frame here; IDR markings per slice in frame or fields are ORed
      * in later.
@@ -606,7 +497,9 @@ static int h264_frame_start(H264Context *h)
     pic->mmco_reset  = 0;
     pic->recovered   = 0;
     pic->invalid_gap = 0;
-    pic->sei_recovery_frame_cnt = h->sei_recovery_frame_cnt;
+    pic->sei_recovery_frame_cnt = h->sei.recovery_point.recovery_frame_cnt;
+
+    pic->f->pict_type = h->slice_ctx[0].slice_type;
 
     if ((ret = alloc_picture(h, pic)) < 0)
         return ret;
@@ -658,6 +551,8 @@ static int h264_frame_start(H264Context *h)
 
     h->next_output_pic = NULL;
 
+    h->postpone_filter = 0;
+
     assert(h->cur_pic_ptr->long_ref == 0);
 
     return 0;
@@ -770,8 +665,8 @@ static void implicit_weight_table(const H264Context *h, H264SliceContext *sl, in
     int ref0, ref1, i, cur_poc, ref_start, ref_count0, ref_count1;
 
     for (i = 0; i < 2; i++) {
-        sl->luma_weight_flag[i]   = 0;
-        sl->chroma_weight_flag[i] = 0;
+        sl->pwt.luma_weight_flag[i]   = 0;
+        sl->pwt.chroma_weight_flag[i] = 0;
     }
 
     if (field < 0) {
@@ -782,8 +677,8 @@ static void implicit_weight_table(const H264Context *h, H264SliceContext *sl, in
         }
         if (sl->ref_count[0] == 1 && sl->ref_count[1] == 1 && !FRAME_MBAFF(h) &&
             sl->ref_list[0][0].poc + (int64_t)sl->ref_list[1][0].poc == 2 * cur_poc) {
-            sl->use_weight        = 0;
-            sl->use_weight_chroma = 0;
+            sl->pwt.use_weight        = 0;
+            sl->pwt.use_weight_chroma = 0;
             return;
         }
         ref_start  = 0;
@@ -796,10 +691,10 @@ static void implicit_weight_table(const H264Context *h, H264SliceContext *sl, in
         ref_count1 = 16 + 2 * sl->ref_count[1];
     }
 
-    sl->use_weight               = 2;
-    sl->use_weight_chroma        = 2;
-    sl->luma_log2_weight_denom   = 5;
-    sl->chroma_log2_weight_denom = 5;
+    sl->pwt.use_weight               = 2;
+    sl->pwt.use_weight_chroma        = 2;
+    sl->pwt.luma_log2_weight_denom   = 5;
+    sl->pwt.chroma_log2_weight_denom = 5;
 
     for (ref0 = ref_start; ref0 < ref_count0; ref0++) {
         int64_t poc0 = sl->ref_list[0][ref0].poc;
@@ -817,10 +712,10 @@ static void implicit_weight_table(const H264Context *h, H264SliceContext *sl, in
                 }
             }
             if (field < 0) {
-                sl->implicit_weight[ref0][ref1][0] =
-                sl->implicit_weight[ref0][ref1][1] = w;
+                sl->pwt.implicit_weight[ref0][ref1][0] =
+                sl->pwt.implicit_weight[ref0][ref1][1] = w;
             } else {
-                sl->implicit_weight[ref0][ref1][field] = w;
+                sl->pwt.implicit_weight[ref0][ref1][field] = w;
             }
         }
     }
@@ -834,7 +729,7 @@ static void init_scan_tables(H264Context *h)
     int i;
     for (i = 0; i < 16; i++) {
 #define TRANSPOSE(x) ((x) >> 2) | (((x) << 2) & 0xF)
-        h->zigzag_scan[i] = TRANSPOSE(zigzag_scan[i]);
+        h->zigzag_scan[i] = TRANSPOSE(ff_zigzag_scan[i]);
         h->field_scan[i]  = TRANSPOSE(field_scan[i]);
 #undef TRANSPOSE
     }
@@ -846,8 +741,8 @@ static void init_scan_tables(H264Context *h)
         h->field_scan8x8_cavlc[i]  = TRANSPOSE(field_scan8x8_cavlc[i]);
 #undef TRANSPOSE
     }
-    if (h->sps.transform_bypass) { // FIXME same ugly
-        memcpy(h->zigzag_scan_q0          , zigzag_scan             , sizeof(h->zigzag_scan_q0         ));
+    if (h->ps.sps->transform_bypass) { // FIXME same ugly
+        memcpy(h->zigzag_scan_q0          , ff_zigzag_scan          , sizeof(h->zigzag_scan_q0         ));
         memcpy(h->zigzag_scan8x8_q0       , ff_zigzag_direct        , sizeof(h->zigzag_scan8x8_q0      ));
         memcpy(h->zigzag_scan8x8_cavlc_q0 , zigzag_scan8x8_cavlc    , sizeof(h->zigzag_scan8x8_cavlc_q0));
         memcpy(h->field_scan_q0           , field_scan              , sizeof(h->field_scan_q0          ));
@@ -875,7 +770,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
     const enum AVPixelFormat *choices = pix_fmts;
     int i;
 
-    switch (h->sps.bit_depth_luma) {
+    switch (h->ps.sps->bit_depth_luma) {
     case 9:
         if (CHROMA444(h)) {
             if (h->avctx->colorspace == AVCOL_SPC_RGB) {
@@ -963,7 +858,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
         break;
     default:
         av_log(h->avctx, AV_LOG_ERROR,
-               "Unsupported bit depth %d\n", h->sps.bit_depth_luma);
+               "Unsupported bit depth %d\n", h->ps.sps->bit_depth_luma);
         return AVERROR_INVALIDDATA;
     }
 
@@ -978,10 +873,11 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
 /* export coded and cropped frame dimensions to AVCodecContext */
 static int init_dimensions(H264Context *h)
 {
-    int width  = h->width  - (h->sps.crop_right + h->sps.crop_left);
-    int height = h->height - (h->sps.crop_top   + h->sps.crop_bottom);
-    av_assert0(h->sps.crop_right + h->sps.crop_left < (unsigned)h->width);
-    av_assert0(h->sps.crop_top + h->sps.crop_bottom < (unsigned)h->height);
+    SPS *sps = h->ps.sps;
+    int width  = h->width  - (sps->crop_right + sps->crop_left);
+    int height = h->height - (sps->crop_top   + sps->crop_bottom);
+    av_assert0(sps->crop_right + sps->crop_left < (unsigned)h->width);
+    av_assert0(sps->crop_top + sps->crop_bottom < (unsigned)h->height);
 
     /* handle container cropping */
     if (FFALIGN(h->avctx->width,  16) == FFALIGN(width,  16) &&
@@ -1000,11 +896,11 @@ static int init_dimensions(H264Context *h)
             return AVERROR_INVALIDDATA;
 
         av_log(h->avctx, AV_LOG_WARNING, "Ignoring cropping information.\n");
-        h->sps.crop_bottom =
-        h->sps.crop_top    =
-        h->sps.crop_right  =
-        h->sps.crop_left   =
-        h->sps.crop        = 0;
+        sps->crop_bottom =
+        sps->crop_top    =
+        sps->crop_right  =
+        sps->crop_left   =
+        sps->crop        = 0;
 
         width  = h->width;
         height = h->height;
@@ -1020,21 +916,19 @@ static int init_dimensions(H264Context *h)
 
 static int h264_slice_header_init(H264Context *h)
 {
-    int nb_slices = (HAVE_THREADS &&
-                     h->avctx->active_thread_type & FF_THREAD_SLICE) ?
-                    h->avctx->thread_count : 1;
+    const SPS *sps = h->ps.sps;
     int i, ret;
 
-    ff_set_sar(h->avctx, h->sps.sar);
+    ff_set_sar(h->avctx, sps->sar);
     av_pix_fmt_get_chroma_sub_sample(h->avctx->pix_fmt,
                                      &h->chroma_x_shift, &h->chroma_y_shift);
 
-    if (h->sps.timing_info_present_flag) {
-        int64_t den = h->sps.time_scale;
-        if (h->x264_build < 44U)
+    if (sps->timing_info_present_flag) {
+        int64_t den = sps->time_scale;
+        if (h->sei.unregistered.x264_build < 44U)
             den *= 2;
         av_reduce(&h->avctx->framerate.den, &h->avctx->framerate.num,
-                  h->sps.num_units_in_tick * h->avctx->ticks_per_frame, den, 1 << 30);
+                  sps->num_units_in_tick * h->avctx->ticks_per_frame, den, 1 << 30);
     }
 
     ff_h264_free_tables(h);
@@ -1052,7 +946,7 @@ static int h264_slice_header_init(H264Context *h)
 #if FF_API_CAP_VDPAU
     if (h->avctx->codec &&
         h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU &&
-        (h->sps.bit_depth_luma != 8 || h->sps.chroma_format_idc > 1)) {
+        (sps->bit_depth_luma != 8 || sps->chroma_format_idc > 1)) {
         av_log(h->avctx, AV_LOG_ERROR,
                 "VDPAU decoding does not support video colorspace.\n");
         ret = AVERROR_INVALIDDATA;
@@ -1060,42 +954,29 @@ static int h264_slice_header_init(H264Context *h)
     }
 #endif
 
-    if (h->sps.bit_depth_luma < 8 || h->sps.bit_depth_luma > 14 ||
-        h->sps.bit_depth_luma == 11 || h->sps.bit_depth_luma == 13
+    if (sps->bit_depth_luma < 8 || sps->bit_depth_luma > 14 ||
+        sps->bit_depth_luma == 11 || sps->bit_depth_luma == 13
     ) {
         av_log(h->avctx, AV_LOG_ERROR, "Unsupported bit depth %d\n",
-               h->sps.bit_depth_luma);
+               sps->bit_depth_luma);
         ret = AVERROR_INVALIDDATA;
         goto fail;
     }
 
     h->cur_bit_depth_luma         =
-    h->avctx->bits_per_raw_sample = h->sps.bit_depth_luma;
-    h->cur_chroma_format_idc      = h->sps.chroma_format_idc;
-    h->pixel_shift                = h->sps.bit_depth_luma > 8;
-    h->chroma_format_idc          = h->sps.chroma_format_idc;
-    h->bit_depth_luma             = h->sps.bit_depth_luma;
-
-    ff_h264dsp_init(&h->h264dsp, h->sps.bit_depth_luma,
-                    h->sps.chroma_format_idc);
-    ff_h264chroma_init(&h->h264chroma, h->sps.bit_depth_chroma);
-    ff_h264qpel_init(&h->h264qpel, h->sps.bit_depth_luma);
-    ff_h264_pred_init(&h->hpc, h->avctx->codec_id, h->sps.bit_depth_luma,
-                      h->sps.chroma_format_idc);
-    ff_videodsp_init(&h->vdsp, h->sps.bit_depth_luma);
-
-    if (nb_slices > H264_MAX_THREADS || (nb_slices > h->mb_height && h->mb_height)) {
-        int max_slices;
-        if (h->mb_height)
-            max_slices = FFMIN(H264_MAX_THREADS, h->mb_height);
-        else
-            max_slices = H264_MAX_THREADS;
-        av_log(h->avctx, AV_LOG_WARNING, "too many threads/slices %d,"
-               " reducing to %d\n", nb_slices, max_slices);
-        nb_slices = max_slices;
-    }
-    h->slice_context_count = nb_slices;
-    h->max_contexts = FFMIN(h->max_contexts, nb_slices);
+    h->avctx->bits_per_raw_sample = sps->bit_depth_luma;
+    h->cur_chroma_format_idc      = sps->chroma_format_idc;
+    h->pixel_shift                = sps->bit_depth_luma > 8;
+    h->chroma_format_idc          = sps->chroma_format_idc;
+    h->bit_depth_luma             = sps->bit_depth_luma;
+
+    ff_h264dsp_init(&h->h264dsp, sps->bit_depth_luma,
+                    sps->chroma_format_idc);
+    ff_h264chroma_init(&h->h264chroma, sps->bit_depth_chroma);
+    ff_h264qpel_init(&h->h264qpel, sps->bit_depth_luma);
+    ff_h264_pred_init(&h->hpc, h->avctx->codec_id, sps->bit_depth_luma,
+                      sps->chroma_format_idc);
+    ff_videodsp_init(&h->vdsp, sps->bit_depth_luma);
 
     if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_SLICE)) {
         ret = ff_h264_slice_context_init(h, &h->slice_ctx[0]);
@@ -1104,7 +985,7 @@ static int h264_slice_header_init(H264Context *h)
             goto fail;
         }
     } else {
-        for (i = 0; i < h->slice_context_count; i++) {
+        for (i = 0; i < h->nb_slice_ctx; i++) {
             H264SliceContext *sl = &h->slice_ctx[i];
 
             sl->h264               = h;
@@ -1141,14 +1022,16 @@ static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a)
 
 /**
  * Decode a slice header.
- * This will (re)intialize the decoder and call h264_frame_start() as needed.
+ * This will (re)initialize the decoder and call h264_frame_start() as needed.
  *
  * @param h h264context
  *
- * @return 0 if okay, <0 if an error occurred, 1 if decoding must not be multithreaded
+ * @return 0 if okay, <0 if an error occurred
  */
 int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
 {
+    const SPS *sps;
+    const PPS *pps;
     unsigned int first_mb_in_slice;
     unsigned int pps_id;
     int ret;
@@ -1160,14 +1043,10 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     int first_slice = sl == h->slice_ctx && !h->current_slice;
     int frame_num, droppable, picture_structure;
     int mb_aff_frame, last_mb_aff_frame;
-    PPS *pps;
 
     if (first_slice)
         av_assert0(!h->setup_finished);
 
-    h->qpel_put = h->h264qpel.put_h264_qpel_pixels_tab;
-    h->qpel_avg = h->h264qpel.avg_h264_qpel_pixels_tab;
-
     first_mb_in_slice = get_ue_golomb_long(&sl->gb);
 
     if (first_mb_in_slice == 0) { // FIXME better field boundary detection
@@ -1228,7 +1107,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     } else
         sl->slice_type_fixed = 0;
 
-    slice_type = golomb_to_pict_type[slice_type];
+    slice_type         = ff_h264_golomb_to_pict_type[slice_type];
     sl->slice_type     = slice_type;
     sl->slice_type_nos = slice_type & 3;
 
@@ -1243,22 +1122,18 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
             (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) ||
             (h->avctx->skip_frame >= AVDISCARD_BIDIR  && sl->slice_type_nos == AV_PICTURE_TYPE_B) ||
             (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) ||
-            (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != NAL_IDR_SLICE && h->sei_recovery_frame_cnt < 0) ||
+            (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) ||
             h->avctx->skip_frame >= AVDISCARD_ALL) {
             return SLICE_SKIPED;
         }
     }
 
-    // to make a few old functions happy, it's wrong though
-    if (!h->setup_finished)
-        h->pict_type = sl->slice_type;
-
     pps_id = get_ue_golomb(&sl->gb);
     if (pps_id >= MAX_PPS_COUNT) {
         av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id);
         return AVERROR_INVALIDDATA;
     }
-    if (!h->pps_buffers[pps_id]) {
+    if (!h->ps.pps_list[pps_id]) {
         av_log(h->avctx, AV_LOG_ERROR,
                "non-existing PPS %u referenced\n",
                pps_id);
@@ -1271,29 +1146,33 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
         return AVERROR_INVALIDDATA;
     }
 
-    pps = h->pps_buffers[pps_id];
+    pps = (const PPS*)h->ps.pps_list[pps_id]->data;
 
-    if (!h->sps_buffers[pps->sps_id]) {
+    if (!h->ps.sps_list[pps->sps_id]) {
         av_log(h->avctx, AV_LOG_ERROR,
                "non-existing SPS %u referenced\n",
-               h->pps.sps_id);
+               pps->sps_id);
         return AVERROR_INVALIDDATA;
     }
 
     if (first_slice) {
-        h->pps = *h->pps_buffers[pps_id];
+        av_buffer_unref(&h->ps.pps_ref);
+        h->ps.pps = NULL;
+        h->ps.pps_ref = av_buffer_ref(h->ps.pps_list[pps_id]);
+        if (!h->ps.pps_ref)
+            return AVERROR(ENOMEM);
+        h->ps.pps = (const PPS*)h->ps.pps_ref->data;
     } else {
-        if (h->pps.sps_id != pps->sps_id ||
-            h->pps.transform_8x8_mode != pps->transform_8x8_mode ||
-            (h->setup_finished && h->dequant_coeff_pps != pps_id)) {
+        if (h->ps.pps->sps_id != pps->sps_id ||
+            h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*||
+            (h->setup_finished && h->ps.pps != pps)*/) {
             av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
             return AVERROR_INVALIDDATA;
         }
     }
 
-    if (pps->sps_id != h->sps.sps_id ||
-        pps->sps_id != h->current_sps_id ||
-        h->sps_buffers[pps->sps_id]->new) {
+    if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data ||
+        pps->sps_id != h->current_sps_id) {
 
         if (!first_slice) {
             av_log(h->avctx, AV_LOG_ERROR,
@@ -1301,62 +1180,56 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
             return AVERROR_INVALIDDATA;
         }
 
-        h->sps = *h->sps_buffers[h->pps.sps_id];
-
-        if (h->mb_width  != h->sps.mb_width ||
-            h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) ||
-            h->cur_bit_depth_luma    != h->sps.bit_depth_luma ||
-            h->cur_chroma_format_idc != h->sps.chroma_format_idc
+        av_buffer_unref(&h->ps.sps_ref);
+        h->ps.sps = NULL;
+        h->ps.sps_ref = av_buffer_ref(h->ps.sps_list[h->ps.pps->sps_id]);
+        if (!h->ps.sps_ref)
+            return AVERROR(ENOMEM);
+        h->ps.sps = (const SPS*)h->ps.sps_ref->data;
+
+        if (h->mb_width  != h->ps.sps->mb_width ||
+            h->mb_height != h->ps.sps->mb_height * (2 - h->ps.sps->frame_mbs_only_flag) ||
+            h->cur_bit_depth_luma    != h->ps.sps->bit_depth_luma ||
+            h->cur_chroma_format_idc != h->ps.sps->chroma_format_idc
         )
             needs_reinit = 1;
 
-        if (h->bit_depth_luma    != h->sps.bit_depth_luma ||
-            h->chroma_format_idc != h->sps.chroma_format_idc)
+        if (h->bit_depth_luma    != h->ps.sps->bit_depth_luma ||
+            h->chroma_format_idc != h->ps.sps->chroma_format_idc)
             needs_reinit         = 1;
-
-        if (h->flags & AV_CODEC_FLAG_LOW_DELAY ||
-            (h->sps.bitstream_restriction_flag &&
-             !h->sps.num_reorder_frames)) {
-            if (h->avctx->has_b_frames > 1 || h->delayed_pic[0])
-                av_log(h->avctx, AV_LOG_WARNING, "Delayed frames seen. "
-                       "Reenabling low delay requires a codec flush.\n");
-            else
-                h->low_delay = 1;
-        }
-
-        if (h->avctx->has_b_frames < 2)
-            h->avctx->has_b_frames = !h->low_delay;
-
     }
 
+    pps = h->ps.pps;
+    sps = h->ps.sps;
+
     must_reinit = (h->context_initialized &&
-                    (   16*h->sps.mb_width != h->avctx->coded_width
-                     || 16*h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) != h->avctx->coded_height
-                     || h->cur_bit_depth_luma    != h->sps.bit_depth_luma
-                     || h->cur_chroma_format_idc != h->sps.chroma_format_idc
-                     || h->mb_width  != h->sps.mb_width
-                     || h->mb_height != h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag)
+                    (   16*sps->mb_width != h->avctx->coded_width
+                     || 16*sps->mb_height * (2 - sps->frame_mbs_only_flag) != h->avctx->coded_height
+                     || h->cur_bit_depth_luma    != sps->bit_depth_luma
+                     || h->cur_chroma_format_idc != sps->chroma_format_idc
+                     || h->mb_width  != sps->mb_width
+                     || h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag)
                     ));
     if (h->avctx->pix_fmt == AV_PIX_FMT_NONE
         || (non_j_pixfmt(h->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h, 0))))
         must_reinit = 1;
 
-    if (first_slice && av_cmp_q(h->sps.sar, h->avctx->sample_aspect_ratio))
+    if (first_slice && av_cmp_q(sps->sar, h->avctx->sample_aspect_ratio))
         must_reinit = 1;
 
     if (!h->setup_finished) {
-        h->avctx->profile = ff_h264_get_profile(&h->sps);
-        h->avctx->level   = h->sps.level_idc;
-        h->avctx->refs    = h->sps.ref_frame_count;
+        h->avctx->profile = ff_h264_get_profile(sps);
+        h->avctx->level   = sps->level_idc;
+        h->avctx->refs    = sps->ref_frame_count;
 
-        h->mb_width  = h->sps.mb_width;
-        h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag);
+        h->mb_width  = sps->mb_width;
+        h->mb_height = sps->mb_height * (2 - sps->frame_mbs_only_flag);
         h->mb_num    = h->mb_width * h->mb_height;
         h->mb_stride = h->mb_width + 1;
 
         h->b_stride = h->mb_width * 4;
 
-        h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p
+        h->chroma_y_shift = sps->chroma_format_idc <= 1; // 400 uses yuv420p
 
         h->width  = 16 * h->mb_width;
         h->height = 16 * h->mb_height;
@@ -1365,15 +1238,15 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
         if (ret < 0)
             return ret;
 
-        if (h->sps.video_signal_type_present_flag) {
-            h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG
+        if (sps->video_signal_type_present_flag) {
+            h->avctx->color_range = sps->full_range > 0 ? AVCOL_RANGE_JPEG
                                                         : AVCOL_RANGE_MPEG;
-            if (h->sps.colour_description_present_flag) {
-                if (h->avctx->colorspace != h->sps.colorspace)
+            if (sps->colour_description_present_flag) {
+                if (h->avctx->colorspace != sps->colorspace)
                     needs_reinit = 1;
-                h->avctx->color_primaries = h->sps.color_primaries;
-                h->avctx->color_trc       = h->sps.color_trc;
-                h->avctx->colorspace      = h->sps.colorspace;
+                h->avctx->color_primaries = sps->color_primaries;
+                h->avctx->color_trc       = sps->color_trc;
+                h->avctx->colorspace      = sps->colorspace;
             }
         }
     }
@@ -1426,22 +1299,17 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
         }
     }
 
-    if (!h->current_slice && h->dequant_coeff_pps != pps_id) {
-        h->dequant_coeff_pps = pps_id;
-        ff_h264_init_dequant_tables(h);
-    }
-
-    frame_num = get_bits(&sl->gb, h->sps.log2_max_frame_num);
+    frame_num = get_bits(&sl->gb, sps->log2_max_frame_num);
     if (!first_slice) {
-        if (h->frame_num != frame_num) {
+        if (h->poc.frame_num != frame_num) {
             av_log(h->avctx, AV_LOG_ERROR, "Frame num change from %d to %d\n",
-                   h->frame_num, frame_num);
+                   h->poc.frame_num, frame_num);
             return AVERROR_INVALIDDATA;
         }
     }
 
     if (!h->setup_finished)
-        h->frame_num = frame_num;
+        h->poc.frame_num = frame_num;
 
     sl->mb_mbaff       = 0;
     mb_aff_frame       = 0;
@@ -1450,10 +1318,10 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     last_pic_droppable = h->droppable;
 
     droppable = h->nal_ref_idc == 0;
-    if (h->sps.frame_mbs_only_flag) {
+    if (sps->frame_mbs_only_flag) {
         picture_structure = PICT_FRAME;
     } else {
-        if (!h->sps.direct_8x8_inference_flag && slice_type == AV_PICTURE_TYPE_B) {
+        if (!h->ps.sps->direct_8x8_inference_flag && slice_type == AV_PICTURE_TYPE_B) {
             av_log(h->avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n");
             return -1;
         }
@@ -1464,7 +1332,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
             picture_structure = PICT_TOP_FIELD + bottom_field_flag;
         } else {
             picture_structure = PICT_FRAME;
-            mb_aff_frame      = h->sps.mb_aff;
+            mb_aff_frame      = sps->mb_aff;
         }
     }
 
@@ -1494,19 +1362,19 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     if (h->current_slice == 0) {
         /* Shorten frame num gaps so we don't have to allocate reference
          * frames just to throw them away */
-        if (h->frame_num != h->prev_frame_num) {
-            int unwrap_prev_frame_num = h->prev_frame_num;
-            int max_frame_num         = 1 << h->sps.log2_max_frame_num;
+        if (h->poc.frame_num != h->poc.prev_frame_num) {
+            int unwrap_prev_frame_num = h->poc.prev_frame_num;
+            int max_frame_num         = 1 << sps->log2_max_frame_num;
 
-            if (unwrap_prev_frame_num > h->frame_num)
+            if (unwrap_prev_frame_num > h->poc.frame_num)
                 unwrap_prev_frame_num -= max_frame_num;
 
-            if ((h->frame_num - unwrap_prev_frame_num) > h->sps.ref_frame_count) {
-                unwrap_prev_frame_num = (h->frame_num - h->sps.ref_frame_count) - 1;
+            if ((h->poc.frame_num - unwrap_prev_frame_num) > sps->ref_frame_count) {
+                unwrap_prev_frame_num = (h->poc.frame_num - sps->ref_frame_count) - 1;
                 if (unwrap_prev_frame_num < 0)
                     unwrap_prev_frame_num += max_frame_num;
 
-                h->prev_frame_num = unwrap_prev_frame_num;
+                h->poc.prev_frame_num = unwrap_prev_frame_num;
             }
         }
 
@@ -1535,7 +1403,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
                                               last_pic_structure == PICT_TOP_FIELD);
                 }
             } else {
-                if (h->cur_pic_ptr->frame_num != h->frame_num) {
+                if (h->cur_pic_ptr->frame_num != h->poc.frame_num) {
                     /* This and previous field were reference, but had
                      * different frame_nums. Consider this field first in
                      * pair. Throw away previous field except for reference
@@ -1567,12 +1435,12 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
             }
         }
 
-        while (h->frame_num != h->prev_frame_num && !h->first_field &&
-               h->frame_num != (h->prev_frame_num + 1) % (1 << h->sps.log2_max_frame_num)) {
+        while (h->poc.frame_num != h->poc.prev_frame_num && !h->first_field &&
+               h->poc.frame_num != (h->poc.prev_frame_num + 1) % (1 << sps->log2_max_frame_num)) {
             H264Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL;
             av_log(h->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n",
-                   h->frame_num, h->prev_frame_num);
-            if (!h->sps.gaps_in_frame_num_allowed_flag)
+                   h->poc.frame_num, h->poc.prev_frame_num);
+            if (!sps->gaps_in_frame_num_allowed_flag)
                 for(i=0; i<FF_ARRAY_ELEMS(h->last_pocs); i++)
                     h->last_pocs[i] = INT_MIN;
             ret = h264_frame_start(h);
@@ -1581,10 +1449,10 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
                 return ret;
             }
 
-            h->prev_frame_num++;
-            h->prev_frame_num        %= 1 << h->sps.log2_max_frame_num;
-            h->cur_pic_ptr->frame_num = h->prev_frame_num;
-            h->cur_pic_ptr->invalid_gap = !h->sps.gaps_in_frame_num_allowed_flag;
+            h->poc.prev_frame_num++;
+            h->poc.prev_frame_num        %= 1 << sps->log2_max_frame_num;
+            h->cur_pic_ptr->frame_num = h->poc.prev_frame_num;
+            h->cur_pic_ptr->invalid_gap = !sps->gaps_in_frame_num_allowed_flag;
             ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0);
             ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1);
             ret = ff_generate_sliding_window_mmcos(h, 1);
@@ -1614,7 +1482,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
                                   prev->f->height);
                     h->short_ref[0]->poc = prev->poc + 2;
                 }
-                h->short_ref[0]->frame_num = h->prev_frame_num;
+                h->short_ref[0]->frame_num = h->poc.prev_frame_num;
             }
         }
 
@@ -1635,7 +1503,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
                 h->first_field = FIELD_PICTURE(h);
             } else {
                 h->missing_fields = 0;
-                if (h->cur_pic_ptr->frame_num != h->frame_num) {
+                if (h->cur_pic_ptr->frame_num != h->poc.frame_num) {
                     ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
                                               h->picture_structure==PICT_BOTTOM_FIELD);
                     /* This and the previous field had different frame_nums.
@@ -1686,50 +1554,56 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     av_assert1(sl->mb_y < h->mb_height);
 
     if (h->picture_structure == PICT_FRAME) {
-        h->curr_pic_num = h->frame_num;
-        h->max_pic_num  = 1 << h->sps.log2_max_frame_num;
+        h->curr_pic_num = h->poc.frame_num;
+        h->max_pic_num  = 1 << sps->log2_max_frame_num;
     } else {
-        h->curr_pic_num = 2 * h->frame_num + 1;
-        h->max_pic_num  = 1 << (h->sps.log2_max_frame_num + 1);
+        h->curr_pic_num = 2 * h->poc.frame_num + 1;
+        h->max_pic_num  = 1 << (sps->log2_max_frame_num + 1);
     }
 
     if (h->nal_unit_type == NAL_IDR_SLICE)
         get_ue_golomb_long(&sl->gb); /* idr_pic_id */
 
-    if (h->sps.poc_type == 0) {
-        int poc_lsb = get_bits(&sl->gb, h->sps.log2_max_poc_lsb);
+    if (sps->poc_type == 0) {
+        int poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb);
 
         if (!h->setup_finished)
-            h->poc_lsb = poc_lsb;
+            h->poc.poc_lsb = poc_lsb;
 
-        if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
+        if (pps->pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
             int delta_poc_bottom = get_se_golomb(&sl->gb);
             if (!h->setup_finished)
-                h->delta_poc_bottom = delta_poc_bottom;
+                h->poc.delta_poc_bottom = delta_poc_bottom;
         }
     }
 
-    if (h->sps.poc_type == 1 && !h->sps.delta_pic_order_always_zero_flag) {
+    if (sps->poc_type == 1 && !sps->delta_pic_order_always_zero_flag) {
         int delta_poc = get_se_golomb(&sl->gb);
 
         if (!h->setup_finished)
-            h->delta_poc[0] = delta_poc;
+            h->poc.delta_poc[0] = delta_poc;
 
-        if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
+        if (pps->pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
             delta_poc = get_se_golomb(&sl->gb);
 
             if (!h->setup_finished)
-                h->delta_poc[1] = delta_poc;
+                h->poc.delta_poc[1] = delta_poc;
         }
     }
 
     if (!h->setup_finished)
-        ff_init_poc(h, h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc);
+        ff_h264_init_poc(h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc,
+                         sps, &h->poc, h->picture_structure, h->nal_ref_idc);
 
-    if (h->pps.redundant_pic_cnt_present)
+    if (pps->redundant_pic_cnt_present)
         sl->redundant_pic_count = get_ue_golomb(&sl->gb);
 
-    ret = ff_set_ref_count(h, sl);
+    if (sl->slice_type_nos == AV_PICTURE_TYPE_B)
+        sl->direct_spatial_mv_pred = get_bits1(&sl->gb);
+
+    ret = ff_h264_parse_ref_count(&sl->list_count, sl->ref_count,
+                                  &sl->gb, pps, sl->slice_type_nos,
+                                  h->picture_structure, h->avctx);
     if (ret < 0)
         return ret;
 
@@ -1741,18 +1615,19 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
        }
     }
 
-    if ((h->pps.weighted_pred && sl->slice_type_nos == AV_PICTURE_TYPE_P) ||
-        (h->pps.weighted_bipred_idc == 1 &&
+    if ((pps->weighted_pred && sl->slice_type_nos == AV_PICTURE_TYPE_P) ||
+        (pps->weighted_bipred_idc == 1 &&
          sl->slice_type_nos == AV_PICTURE_TYPE_B))
-        ff_pred_weight_table(h, sl);
-    else if (h->pps.weighted_bipred_idc == 2 &&
+        ff_h264_pred_weight_table(&sl->gb, sps, sl->ref_count,
+                                  sl->slice_type_nos, &sl->pwt, h->avctx);
+    else if (pps->weighted_bipred_idc == 2 &&
              sl->slice_type_nos == AV_PICTURE_TYPE_B) {
         implicit_weight_table(h, sl, -1);
     } else {
-        sl->use_weight = 0;
+        sl->pwt.use_weight = 0;
         for (i = 0; i < 2; i++) {
-            sl->luma_weight_flag[i]   = 0;
-            sl->chroma_weight_flag[i] = 0;
+            sl->pwt.luma_weight_flag[i]   = 0;
+            sl->pwt.chroma_weight_flag[i] = 0;
         }
     }
 
@@ -1770,9 +1645,9 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     }
 
     if (FRAME_MBAFF(h)) {
-        ff_h264_fill_mbaff_ref_list(h, sl);
+        ff_h264_fill_mbaff_ref_list(sl);
 
-        if (h->pps.weighted_bipred_idc == 2 && sl->slice_type_nos == AV_PICTURE_TYPE_B) {
+        if (pps->weighted_bipred_idc == 2 && sl->slice_type_nos == AV_PICTURE_TYPE_B) {
             implicit_weight_table(h, sl, 0);
             implicit_weight_table(h, sl, 1);
         }
@@ -1782,7 +1657,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
         ff_h264_direct_dist_scale_factor(h, sl);
     ff_h264_direct_ref_list_init(h, sl);
 
-    if (sl->slice_type_nos != AV_PICTURE_TYPE_I && h->pps.cabac) {
+    if (sl->slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) {
         tmp = get_ue_golomb_31(&sl->gb);
         if (tmp > 2) {
             av_log(h->avctx, AV_LOG_ERROR, "cabac_init_idc %u overflow\n", tmp);
@@ -1792,8 +1667,8 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     }
 
     sl->last_qscale_diff = 0;
-    tmp = h->pps.init_qp + get_se_golomb(&sl->gb);
-    if (tmp > 51 + 6 * (h->sps.bit_depth_luma - 8)) {
+    tmp = pps->init_qp + get_se_golomb(&sl->gb);
+    if (tmp > 51 + 6 * (sps->bit_depth_luma - 8)) {
         av_log(h->avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp);
         return AVERROR_INVALIDDATA;
     }
@@ -1810,7 +1685,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     sl->deblocking_filter     = 1;
     sl->slice_alpha_c0_offset = 0;
     sl->slice_beta_offset     = 0;
-    if (h->pps.deblocking_filter_parameters_present) {
+    if (pps->deblocking_filter_parameters_present) {
         tmp = get_ue_golomb_31(&sl->gb);
         if (tmp > 2) {
             av_log(h->avctx, AV_LOG_ERROR,
@@ -1853,28 +1728,15 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
              * Do not bother to deblock across slices. */
             sl->deblocking_filter = 2;
         } else {
-            h->max_contexts = 1;
-            if (!h->single_decode_warning) {
-                av_log(h->avctx, AV_LOG_INFO,
-                       "Cannot parallelize slice decoding with deblocking filter type 1, decoding such frames in sequential order\n"
-                       "To parallelize slice decoding you need video encoded with disable_deblocking_filter_idc set to 2 (deblock only edges that do not cross slices).\n"
-                       "Setting the flags2 libavcodec option to +fast (-flags2 +fast) will disable deblocking across slices and enable parallel slice decoding "
-                       "but will generate non-standard-compliant output.\n");
-                h->single_decode_warning = 1;
-            }
-            if (sl != h->slice_ctx) {
-                av_log(h->avctx, AV_LOG_ERROR,
-                       "Deblocking switched inside frame.\n");
-                return SLICE_SINGLETHREAD;
-            }
+            h->postpone_filter = 1;
         }
     }
     sl->qp_thresh = 15 -
                    FFMIN(sl->slice_alpha_c0_offset, sl->slice_beta_offset) -
                    FFMAX3(0,
-                          h->pps.chroma_qp_index_offset[0],
-                          h->pps.chroma_qp_index_offset[1]) +
-                   6 * (h->sps.bit_depth_luma - 8);
+                          pps->chroma_qp_index_offset[0],
+                          pps->chroma_qp_index_offset[1]) +
+                   6 * (sps->bit_depth_luma - 8);
 
     sl->slice_num       = ++h->current_slice;
 
@@ -1889,7 +1751,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
 
     for (j = 0; j < 2; j++) {
         int id_list[16];
-        int *ref2frm = sl->ref2frm[sl->slice_num & (MAX_SLICES - 1)][j];
+        int *ref2frm = h->ref2frm[sl->slice_num & (MAX_SLICES - 1)][j];
         for (i = 0; i < 16; i++) {
             id_list[i] = 60;
             if (j < sl->list_count && i < sl->ref_count[j] &&
@@ -1921,9 +1783,7 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
     }
 
     h->au_pps_id = pps_id;
-    h->sps.new =
-    h->sps_buffers[h->pps.sps_id]->new = 0;
-    h->current_sps_id = h->pps.sps_id;
+    h->current_sps_id = h->ps.pps->sps_id;
 
     if (h->avctx->debug & FF_DEBUG_PICT_INFO) {
         av_log(h->avctx, AV_LOG_DEBUG,
@@ -1934,15 +1794,15 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
                av_get_picture_type_char(sl->slice_type),
                sl->slice_type_fixed ? " fix" : "",
                h->nal_unit_type == NAL_IDR_SLICE ? " IDR" : "",
-               pps_id, h->frame_num,
+               pps_id, h->poc.frame_num,
                h->cur_pic_ptr->field_poc[0],
                h->cur_pic_ptr->field_poc[1],
                sl->ref_count[0], sl->ref_count[1],
                sl->qscale,
                sl->deblocking_filter,
                sl->slice_alpha_c0_offset, sl->slice_beta_offset,
-               sl->use_weight,
-               sl->use_weight == 1 && sl->use_weight_chroma ? "c" : "",
+               sl->pwt.use_weight,
+               sl->pwt.use_weight == 1 && sl->pwt.use_weight_chroma ? "c" : "",
                sl->slice_type == AV_PICTURE_TYPE_B ? (sl->direct_spatial_mv_pred ? "SPAT" : "TEMP") : "");
     }
 
@@ -1982,7 +1842,7 @@ static av_always_inline void fill_filter_caches_inter(const H264Context *h,
         if (USES_LIST(top_type, list)) {
             const int b_xy  = h->mb2b_xy[top_xy] + 3 * b_stride;
             const int b8_xy = 4 * top_xy + 2;
-            int *ref2frm = sl->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][list] + (MB_MBAFF(sl) ? 20 : 2);
+            const int *ref2frm = h->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][list] + (MB_MBAFF(sl) ? 20 : 2);
             AV_COPY128(mv_dst - 1 * 8, h->cur_pic.motion_val[list][b_xy + 0]);
             ref_cache[0 - 1 * 8] =
             ref_cache[1 - 1 * 8] = ref2frm[h->cur_pic.ref_index[list][b8_xy + 0]];
@@ -1997,7 +1857,7 @@ static av_always_inline void fill_filter_caches_inter(const H264Context *h,
             if (USES_LIST(left_type[LTOP], list)) {
                 const int b_xy  = h->mb2b_xy[left_xy[LTOP]] + 3;
                 const int b8_xy = 4 * left_xy[LTOP] + 1;
-                int *ref2frm = sl->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][list] + (MB_MBAFF(sl) ? 20 : 2);
+                const int *ref2frm = h->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][list] + (MB_MBAFF(sl) ? 20 : 2);
                 AV_COPY32(mv_dst - 1 +  0, h->cur_pic.motion_val[list][b_xy + b_stride * 0]);
                 AV_COPY32(mv_dst - 1 +  8, h->cur_pic.motion_val[list][b_xy + b_stride * 1]);
                 AV_COPY32(mv_dst - 1 + 16, h->cur_pic.motion_val[list][b_xy + b_stride * 2]);
@@ -2030,7 +1890,7 @@ static av_always_inline void fill_filter_caches_inter(const H264Context *h,
 
     {
         int8_t *ref = &h->cur_pic.ref_index[list][4 * mb_xy];
-        int *ref2frm = sl->ref2frm[sl->slice_num & (MAX_SLICES - 1)][list] + (MB_MBAFF(sl) ? 20 : 2);
+        const int *ref2frm = h->ref2frm[sl->slice_num & (MAX_SLICES - 1)][list] + (MB_MBAFF(sl) ? 20 : 2);
         uint32_t ref01 = (pack16to32(ref2frm[ref[0]], ref2frm[ref[1]]) & 0x00FF00FF) * 0x0101;
         uint32_t ref23 = (pack16to32(ref2frm[ref[2]], ref2frm[ref[3]]) & 0x00FF00FF) * 0x0101;
         AV_WN32A(&ref_cache[0 * 8], ref01);
@@ -2049,7 +1909,6 @@ static av_always_inline void fill_filter_caches_inter(const H264Context *h,
 }
 
 /**
- *
  * @return non zero if the loop filter can be skipped
  */
 static int fill_filter_caches(const H264Context *h, H264SliceContext *sl, int mb_type)
@@ -2062,9 +1921,6 @@ static int fill_filter_caches(const H264Context *h, H264SliceContext *sl, int mb
 
     top_xy = mb_xy - (h->mb_stride << MB_FIELD(sl));
 
-    /* Wow, what a mess, why didn't they simplify the interlacing & intra
-     * stuff, I can't imagine that these complex rules are worth it. */
-
     left_xy[LBOT] = left_xy[LTOP] = mb_xy - 1;
     if (FRAME_MBAFF(h)) {
         const int left_mb_field_flag = IS_INTERLACED(h->cur_pic.mb_type[mb_xy - 1]);
@@ -2155,7 +2011,7 @@ static int fill_filter_caches(const H264Context *h, H264SliceContext *sl, int mb
 
     /* CAVLC 8x8dct requires NNZ values for residual decoding that differ
      * from what the loop filter needs */
-    if (!CABAC(h) && h->pps.transform_8x8_mode) {
+    if (!CABAC(h) && h->ps.pps->transform_8x8_mode) {
         if (IS_8x8DCT(top_type)) {
             nnz_cache[4 + 8 * 0] =
             nnz_cache[5 + 8 * 0] = (h->cbp_table[top_xy] & 0x4000) >> 12;
@@ -2206,14 +2062,15 @@ static void loop_filter(const H264Context *h, H264SliceContext *sl, int start_x,
     const int pixel_shift    = h->pixel_shift;
     const int block_h        = 16 >> h->chroma_y_shift;
 
+    if (h->postpone_filter)
+        return;
+
     if (sl->deblocking_filter) {
         for (mb_x = start_x; mb_x < end_x; mb_x++)
             for (mb_y = end_mb_y - FRAME_MBAFF(h); mb_y <= end_mb_y; mb_y++) {
                 int mb_xy, mb_type;
                 mb_xy         = sl->mb_xy = mb_x + mb_y * h->mb_stride;
-                sl->slice_num = h->slice_table[mb_xy];
                 mb_type       = h->cur_pic.mb_type[mb_xy];
-                sl->list_count = h->list_counts[mb_xy];
 
                 if (FRAME_MBAFF(h))
                     sl->mb_mbaff               =
@@ -2329,6 +2186,7 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
     H264SliceContext *sl = arg;
     const H264Context *h = sl->h264;
     int lf_x_start = sl->mb_x;
+    int orig_deblock = sl->deblocking_filter;
     int ret;
 
     sl->linesize   = h->cur_pic_ptr->f->linesize[0];
@@ -2342,6 +2200,9 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
 
     av_assert0(h->block_offset[15] == (4 * ((scan8[15] - scan8[0]) & 7) << h->pixel_shift) + 4 * sl->linesize * ((scan8[15] - scan8[0]) >> 3));
 
+    if (h->postpone_filter)
+        sl->deblocking_filter = 0;
+
     sl->is_complex = FRAME_MBAFF(h) || h->picture_structure != PICT_FRAME ||
                      avctx->codec_id != AV_CODEC_ID_H264 ||
                      (CONFIG_GRAY && (h->flags & AV_CODEC_FLAG_GRAY));
@@ -2356,7 +2217,7 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
         }
     }
 
-    if (h->pps.cabac) {
+    if (h->ps.pps->cabac) {
         /* realign */
         align_get_bits(&sl->gb);
 
@@ -2404,7 +2265,7 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
                              sl->mb_y, ER_MB_END);
                 if (sl->mb_x >= lf_x_start)
                     loop_filter(h, sl, lf_x_start, sl->mb_x + 1);
-                return 0;
+                goto finish;
             }
             if (sl->cabac.bytestream > sl->cabac.bytestream_end + 2 )
                 av_log(h->avctx, AV_LOG_DEBUG, "bytestream overread %"PTRDIFF_SPECIFIER"\n", sl->cabac.bytestream_end - sl->cabac.bytestream);
@@ -2437,7 +2298,7 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
                              sl->mb_y, ER_MB_END);
                 if (sl->mb_x > lf_x_start)
                     loop_filter(h, sl, lf_x_start, sl->mb_x);
-                return 0;
+                goto finish;
             }
         }
     } else {
@@ -2494,7 +2355,7 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
                         er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y,
                                      sl->mb_x - 1, sl->mb_y, ER_MB_END);
 
-                        return 0;
+                        goto finish;
                     } else {
                         er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y,
                                      sl->mb_x, sl->mb_y, ER_MB_END);
@@ -2514,7 +2375,7 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
                     if (sl->mb_x > lf_x_start)
                         loop_filter(h, sl, lf_x_start, sl->mb_x);
 
-                    return 0;
+                    goto finish;
                 } else {
                     er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x,
                                  sl->mb_y, ER_MB_ERROR);
@@ -2524,6 +2385,10 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
             }
         }
     }
+
+finish:
+    sl->deblocking_filter = orig_deblock;
+    return 0;
 }
 
 /**
@@ -2552,6 +2417,7 @@ int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count)
         int ret;
 
         h->slice_ctx[0].next_slice_idx = h->mb_width * h->mb_height;
+        h->postpone_filter = 0;
 
         ret = decode_slice(avctx, &h->slice_ctx[0]);
         h->mb_y = h->slice_ctx[0].mb_y;
@@ -2590,6 +2456,24 @@ int ff_h264_execute_decode_slices(H264Context *h, unsigned context_count)
             for (i = 1; i < context_count; i++)
                 h->slice_ctx[0].er.error_count += h->slice_ctx[i].er.error_count;
         }
+
+        if (h->postpone_filter) {
+            h->postpone_filter = 0;
+
+            for (i = 0; i < context_count; i++) {
+                int y_end, x_end;
+
+                sl = &h->slice_ctx[i];
+                y_end = FFMIN(sl->mb_y + 1, h->mb_height);
+                x_end = (sl->mb_y >= h->mb_height) ? h->mb_width : sl->mb_x;
+
+                for (j = sl->resync_mb_y; j < y_end; j += 1 + FIELD_OR_MBAFF_PICTURE(h)) {
+                    sl->mb_y = j;
+                    loop_filter(h, sl, j > sl->resync_mb_y ? 0 : sl->resync_mb_x,
+                                j == y_end - 1 ? x_end : h->mb_width);
+                }
+            }
+        }
     }
 
     return 0;
diff --git a/libavcodec/h264addpx_template.c b/libavcodec/h264addpx_template.c
index 046b6c2..b71aaea 100644
--- a/libavcodec/h264addpx_template.c
+++ b/libavcodec/h264addpx_template.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 DSP functions.
+ * H.264 / AVC / MPEG-4 part10 DSP functions.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
diff --git a/libavcodec/h264data.c b/libavcodec/h264data.c
new file mode 100644
index 0000000..da203a9
--- /dev/null
+++ b/libavcodec/h264data.c
@@ -0,0 +1,232 @@
+/*
+ * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder
+ * Copyright (c) 2003 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @brief
+ *     H.264 / AVC / MPEG-4 part10 codec data table
+ * @author Michael Niedermayer <michaelni at gmx.at>
+ */
+
+#include <stdint.h>
+
+#include "libavutil/avutil.h"
+
+#include "avcodec.h"
+#include "h264.h"
+#include "h264data.h"
+
+const uint8_t ff_h264_golomb_to_pict_type[5] = {
+    AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, AV_PICTURE_TYPE_I,
+    AV_PICTURE_TYPE_SP, AV_PICTURE_TYPE_SI
+};
+
+const uint8_t ff_h264_golomb_to_intra4x4_cbp[48] = {
+    47, 31, 15, 0,  23, 27, 29, 30, 7,  11, 13, 14, 39, 43, 45, 46,
+    16, 3,  5,  10, 12, 19, 21, 26, 28, 35, 37, 42, 44, 1,  2,  4,
+    8,  17, 18, 20, 24, 6,  9,  22, 25, 32, 33, 34, 36, 40, 38, 41
+};
+
+const uint8_t ff_h264_golomb_to_inter_cbp[48] = {
+    0,  16, 1,  2,  4,  8,  32, 3,  5,  10, 12, 15, 47, 7,  11, 13,
+    14, 6,  9,  31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46,
+    17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41
+};
+
+const uint8_t ff_h264_chroma_dc_scan[4] = {
+    (0 + 0 * 2) * 16, (1 + 0 * 2) * 16,
+    (0 + 1 * 2) * 16, (1 + 1 * 2) * 16,
+};
+
+const uint8_t ff_h264_chroma422_dc_scan[8] = {
+    (0 + 0 * 2) * 16, (0 + 1 * 2) * 16,
+    (1 + 0 * 2) * 16, (0 + 2 * 2) * 16,
+    (0 + 3 * 2) * 16, (1 + 1 * 2) * 16,
+    (1 + 2 * 2) * 16, (1 + 3 * 2) * 16,
+};
+
+const IMbInfo ff_h264_i_mb_type_info[26] = {
+    { MB_TYPE_INTRA4x4,  -1,  -1 },
+    { MB_TYPE_INTRA16x16, 2,   0 },
+    { MB_TYPE_INTRA16x16, 1,   0 },
+    { MB_TYPE_INTRA16x16, 0,   0 },
+    { MB_TYPE_INTRA16x16, 3,   0 },
+    { MB_TYPE_INTRA16x16, 2,  16 },
+    { MB_TYPE_INTRA16x16, 1,  16 },
+    { MB_TYPE_INTRA16x16, 0,  16 },
+    { MB_TYPE_INTRA16x16, 3,  16 },
+    { MB_TYPE_INTRA16x16, 2,  32 },
+    { MB_TYPE_INTRA16x16, 1,  32 },
+    { MB_TYPE_INTRA16x16, 0,  32 },
+    { MB_TYPE_INTRA16x16, 3,  32 },
+    { MB_TYPE_INTRA16x16, 2,  15 +  0 },
+    { MB_TYPE_INTRA16x16, 1,  15 +  0 },
+    { MB_TYPE_INTRA16x16, 0,  15 +  0 },
+    { MB_TYPE_INTRA16x16, 3,  15 +  0 },
+    { MB_TYPE_INTRA16x16, 2,  15 + 16 },
+    { MB_TYPE_INTRA16x16, 1,  15 + 16 },
+    { MB_TYPE_INTRA16x16, 0,  15 + 16 },
+    { MB_TYPE_INTRA16x16, 3,  15 + 16 },
+    { MB_TYPE_INTRA16x16, 2,  15 + 32 },
+    { MB_TYPE_INTRA16x16, 1,  15 + 32 },
+    { MB_TYPE_INTRA16x16, 0,  15 + 32 },
+    { MB_TYPE_INTRA16x16, 3,  15 + 32 },
+    { MB_TYPE_INTRA_PCM,  -1, -1 },
+};
+
+const PMbInfo ff_h264_p_mb_type_info[5] = {
+    { MB_TYPE_16x16 | MB_TYPE_P0L0,                               1 },
+    { MB_TYPE_16x8  | MB_TYPE_P0L0 | MB_TYPE_P1L0,                2 },
+    { MB_TYPE_8x16  | MB_TYPE_P0L0 | MB_TYPE_P1L0,                2 },
+    { MB_TYPE_8x8   | MB_TYPE_P0L0 | MB_TYPE_P1L0,                4 },
+    { MB_TYPE_8x8   | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_REF0, 4 },
+};
+
+const PMbInfo ff_h264_p_sub_mb_type_info[4] = {
+    { MB_TYPE_16x16 | MB_TYPE_P0L0, 1 },
+    { MB_TYPE_16x8  | MB_TYPE_P0L0, 2 },
+    { MB_TYPE_8x16  | MB_TYPE_P0L0, 2 },
+    { MB_TYPE_8x8   | MB_TYPE_P0L0, 4 },
+};
+
+const PMbInfo ff_h264_b_mb_type_info[23] = {
+    { MB_TYPE_DIRECT2 | MB_TYPE_L0L1,                                              1, },
+    { MB_TYPE_16x16   | MB_TYPE_P0L0,                                              1, },
+    { MB_TYPE_16x16   | MB_TYPE_P0L1,                                              1, },
+    { MB_TYPE_16x16   | MB_TYPE_P0L0 | MB_TYPE_P0L1,                               1, },
+    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               2, },
+    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               2, },
+    { MB_TYPE_16x8    | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               2, },
+    { MB_TYPE_8x16    | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               2, },
+    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P1L1,                               2, },
+    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P1L1,                               2, },
+    { MB_TYPE_16x8    | MB_TYPE_P0L1 | MB_TYPE_P1L0,                               2, },
+    { MB_TYPE_8x16    | MB_TYPE_P0L1 | MB_TYPE_P1L0,                               2, },
+    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1,                2, },
+    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1,                2, },
+    { MB_TYPE_16x8    | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1,                2, },
+    { MB_TYPE_8x16    | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1,                2, },
+    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0,                2, },
+    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0,                2, },
+    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1,                2, },
+    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1,                2, },
+    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, },
+    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, },
+    { MB_TYPE_8x8     | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 4, },
+};
+
+const PMbInfo ff_h264_b_sub_mb_type_info[13] = {
+    { MB_TYPE_DIRECT2,                                                           1, },
+    { MB_TYPE_16x16 | MB_TYPE_P0L0,                                              1, },
+    { MB_TYPE_16x16 | MB_TYPE_P0L1,                                              1, },
+    { MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1,                               1, },
+    { MB_TYPE_16x8  | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               2, },
+    { MB_TYPE_8x16  | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               2, },
+    { MB_TYPE_16x8  | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               2, },
+    { MB_TYPE_8x16  | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               2, },
+    { MB_TYPE_16x8  | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, },
+    { MB_TYPE_8x16  | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, },
+    { MB_TYPE_8x8   | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               4, },
+    { MB_TYPE_8x8   | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               4, },
+    { MB_TYPE_8x8   | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 4, },
+};
+
+const uint8_t ff_h264_dequant4_coeff_init[6][3] = {
+    { 10, 13, 16 },
+    { 11, 14, 18 },
+    { 13, 16, 20 },
+    { 14, 18, 23 },
+    { 16, 20, 25 },
+    { 18, 23, 29 },
+};
+
+const uint8_t ff_h264_dequant8_coeff_init_scan[16] = {
+    0, 3, 4, 3, 3, 1, 5, 1, 4, 5, 2, 5, 3, 1, 5, 1
+};
+
+const uint8_t ff_h264_dequant8_coeff_init[6][6] = {
+    { 20, 18, 32, 19, 25, 24 },
+    { 22, 19, 35, 21, 28, 26 },
+    { 26, 23, 42, 24, 33, 31 },
+    { 28, 25, 45, 26, 35, 33 },
+    { 32, 28, 51, 30, 40, 38 },
+    { 36, 32, 58, 34, 46, 43 },
+};
+
+const uint8_t ff_h264_quant_rem6[QP_MAX_NUM + 1] = {
+    0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2,
+    3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,
+    0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2,
+    3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,
+    0, 1, 2, 3,
+};
+
+const uint8_t ff_h264_quant_div6[QP_MAX_NUM + 1] = {
+    0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3,  3,  3,
+    3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,  6,  6,
+    7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10,
+   10,10,10,11,11,11,11,11,11,12,12,12,12,12,12,13,13,13, 13, 13, 13,
+   14,14,14,14,
+};
+
+#define QP(qP, depth) ((qP) + 6 * ((depth) - 8))
+
+#define CHROMA_QP_TABLE_END(d)                                          \
+    QP(0,  d), QP(1,  d), QP(2,  d), QP(3,  d), QP(4,  d), QP(5,  d),   \
+    QP(6,  d), QP(7,  d), QP(8,  d), QP(9,  d), QP(10, d), QP(11, d),   \
+    QP(12, d), QP(13, d), QP(14, d), QP(15, d), QP(16, d), QP(17, d),   \
+    QP(18, d), QP(19, d), QP(20, d), QP(21, d), QP(22, d), QP(23, d),   \
+    QP(24, d), QP(25, d), QP(26, d), QP(27, d), QP(28, d), QP(29, d),   \
+    QP(29, d), QP(30, d), QP(31, d), QP(32, d), QP(32, d), QP(33, d),   \
+    QP(34, d), QP(34, d), QP(35, d), QP(35, d), QP(36, d), QP(36, d),   \
+    QP(37, d), QP(37, d), QP(37, d), QP(38, d), QP(38, d), QP(38, d),   \
+    QP(39, d), QP(39, d), QP(39, d), QP(39, d)
+
+const uint8_t ff_h264_chroma_qp[7][QP_MAX_NUM + 1] = {
+    { CHROMA_QP_TABLE_END(8) },
+    { 0, 1, 2, 3, 4, 5,
+      CHROMA_QP_TABLE_END(9) },
+    { 0, 1, 2, 3,  4,  5,
+      6, 7, 8, 9, 10, 11,
+      CHROMA_QP_TABLE_END(10) },
+    { 0,  1, 2, 3,  4,  5,
+      6,  7, 8, 9, 10, 11,
+      12,13,14,15, 16, 17,
+      CHROMA_QP_TABLE_END(11) },
+    { 0,  1, 2, 3,  4,  5,
+      6,  7, 8, 9, 10, 11,
+      12,13,14,15, 16, 17,
+      18,19,20,21, 22, 23,
+      CHROMA_QP_TABLE_END(12) },
+    { 0,  1, 2, 3,  4,  5,
+      6,  7, 8, 9, 10, 11,
+      12,13,14,15, 16, 17,
+      18,19,20,21, 22, 23,
+      24,25,26,27, 28, 29,
+      CHROMA_QP_TABLE_END(13) },
+    { 0,  1, 2, 3,  4,  5,
+      6,  7, 8, 9, 10, 11,
+      12,13,14,15, 16, 17,
+      18,19,20,21, 22, 23,
+      24,25,26,27, 28, 29,
+      30,31,32,33, 34, 35,
+      CHROMA_QP_TABLE_END(14) },
+};
diff --git a/libavcodec/h264data.h b/libavcodec/h264data.h
index 95ea385..988352a 100644
--- a/libavcodec/h264data.h
+++ b/libavcodec/h264data.h
@@ -1,7 +1,4 @@
 /*
- * H26L/H264/AVC/JVT/14496-10/... encoder/decoder
- * Copyright (c) 2003 Michael Niedermayer <michaelni at gmx.at>
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -19,56 +16,19 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-/**
- * @file
- * @brief
- *     H264 / AVC / MPEG4 part10 codec data table
- * @author Michael Niedermayer <michaelni at gmx.at>
- */
-
 #ifndef AVCODEC_H264DATA_H
 #define AVCODEC_H264DATA_H
 
 #include <stdint.h>
 
-#include "libavutil/rational.h"
 #include "h264.h"
 
-static const uint8_t golomb_to_pict_type[5] = {
-    AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, AV_PICTURE_TYPE_I,
-    AV_PICTURE_TYPE_SP, AV_PICTURE_TYPE_SI
-};
-
-static const uint8_t golomb_to_intra4x4_cbp[48] = {
-    47, 31, 15, 0,  23, 27, 29, 30, 7,  11, 13, 14, 39, 43, 45, 46,
-    16, 3,  5,  10, 12, 19, 21, 26, 28, 35, 37, 42, 44, 1,  2,  4,
-    8,  17, 18, 20, 24, 6,  9,  22, 25, 32, 33, 34, 36, 40, 38, 41
-};
-
-static const uint8_t golomb_to_inter_cbp[48] = {
-    0,  16, 1,  2,  4,  8,  32, 3,  5,  10, 12, 15, 47, 7,  11, 13,
-    14, 6,  9,  31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46,
-    17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41
-};
-
-static const uint8_t zigzag_scan[16+1] = {
-    0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
-    1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
-    1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,
-    3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4,
-};
-
-static const uint8_t chroma_dc_scan[4] = {
-    (0 + 0 * 2) * 16, (1 + 0 * 2) * 16,
-    (0 + 1 * 2) * 16, (1 + 1 * 2) * 16,
-};
+extern const uint8_t ff_h264_golomb_to_pict_type[5];
+extern const uint8_t ff_h264_golomb_to_intra4x4_cbp[48];
+extern const uint8_t ff_h264_golomb_to_inter_cbp[48];
 
-static const uint8_t chroma422_dc_scan[8] = {
-    (0 + 0 * 2) * 16, (0 + 1 * 2) * 16,
-    (1 + 0 * 2) * 16, (0 + 2 * 2) * 16,
-    (0 + 3 * 2) * 16, (1 + 1 * 2) * 16,
-    (1 + 2 * 2) * 16, (1 + 3 * 2) * 16,
-};
+extern const uint8_t ff_h264_chroma_dc_scan[4];
+extern const uint8_t ff_h264_chroma422_dc_scan[8];
 
 typedef struct IMbInfo {
     uint16_t type;
@@ -76,96 +36,17 @@ typedef struct IMbInfo {
     uint8_t cbp;
 } IMbInfo;
 
-static const IMbInfo i_mb_type_info[26] = {
-    { MB_TYPE_INTRA4x4,  -1,  -1 },
-    { MB_TYPE_INTRA16x16, 2,   0 },
-    { MB_TYPE_INTRA16x16, 1,   0 },
-    { MB_TYPE_INTRA16x16, 0,   0 },
-    { MB_TYPE_INTRA16x16, 3,   0 },
-    { MB_TYPE_INTRA16x16, 2,  16 },
-    { MB_TYPE_INTRA16x16, 1,  16 },
-    { MB_TYPE_INTRA16x16, 0,  16 },
-    { MB_TYPE_INTRA16x16, 3,  16 },
-    { MB_TYPE_INTRA16x16, 2,  32 },
-    { MB_TYPE_INTRA16x16, 1,  32 },
-    { MB_TYPE_INTRA16x16, 0,  32 },
-    { MB_TYPE_INTRA16x16, 3,  32 },
-    { MB_TYPE_INTRA16x16, 2,  15 +  0 },
-    { MB_TYPE_INTRA16x16, 1,  15 +  0 },
-    { MB_TYPE_INTRA16x16, 0,  15 +  0 },
-    { MB_TYPE_INTRA16x16, 3,  15 +  0 },
-    { MB_TYPE_INTRA16x16, 2,  15 + 16 },
-    { MB_TYPE_INTRA16x16, 1,  15 + 16 },
-    { MB_TYPE_INTRA16x16, 0,  15 + 16 },
-    { MB_TYPE_INTRA16x16, 3,  15 + 16 },
-    { MB_TYPE_INTRA16x16, 2,  15 + 32 },
-    { MB_TYPE_INTRA16x16, 1,  15 + 32 },
-    { MB_TYPE_INTRA16x16, 0,  15 + 32 },
-    { MB_TYPE_INTRA16x16, 3,  15 + 32 },
-    { MB_TYPE_INTRA_PCM,  -1, -1 },
-};
+extern const IMbInfo ff_h264_i_mb_type_info[26];
 
 typedef struct PMbInfo {
     uint16_t type;
     uint8_t partition_count;
 } PMbInfo;
 
-static const PMbInfo p_mb_type_info[5] = {
-    { MB_TYPE_16x16 | MB_TYPE_P0L0,                               1 },
-    { MB_TYPE_16x8  | MB_TYPE_P0L0 | MB_TYPE_P1L0,                2 },
-    { MB_TYPE_8x16  | MB_TYPE_P0L0 | MB_TYPE_P1L0,                2 },
-    { MB_TYPE_8x8   | MB_TYPE_P0L0 | MB_TYPE_P1L0,                4 },
-    { MB_TYPE_8x8   | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_REF0, 4 },
-};
-
-static const PMbInfo p_sub_mb_type_info[4] = {
-    { MB_TYPE_16x16 | MB_TYPE_P0L0, 1 },
-    { MB_TYPE_16x8  | MB_TYPE_P0L0, 2 },
-    { MB_TYPE_8x16  | MB_TYPE_P0L0, 2 },
-    { MB_TYPE_8x8   | MB_TYPE_P0L0, 4 },
-};
-
-static const PMbInfo b_mb_type_info[23] = {
-    { MB_TYPE_DIRECT2 | MB_TYPE_L0L1,                                              1, },
-    { MB_TYPE_16x16   | MB_TYPE_P0L0,                                              1, },
-    { MB_TYPE_16x16   | MB_TYPE_P0L1,                                              1, },
-    { MB_TYPE_16x16   | MB_TYPE_P0L0 | MB_TYPE_P0L1,                               1, },
-    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               2, },
-    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               2, },
-    { MB_TYPE_16x8    | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               2, },
-    { MB_TYPE_8x16    | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               2, },
-    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P1L1,                               2, },
-    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P1L1,                               2, },
-    { MB_TYPE_16x8    | MB_TYPE_P0L1 | MB_TYPE_P1L0,                               2, },
-    { MB_TYPE_8x16    | MB_TYPE_P0L1 | MB_TYPE_P1L0,                               2, },
-    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1,                2, },
-    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_P1L1,                2, },
-    { MB_TYPE_16x8    | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1,                2, },
-    { MB_TYPE_8x16    | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1,                2, },
-    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0,                2, },
-    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0,                2, },
-    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1,                2, },
-    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L1,                2, },
-    { MB_TYPE_16x8    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, },
-    { MB_TYPE_8x16    | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, },
-    { MB_TYPE_8x8     | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 4, },
-};
-
-static const PMbInfo b_sub_mb_type_info[13] = {
-    { MB_TYPE_DIRECT2,                                                           1, },
-    { MB_TYPE_16x16 | MB_TYPE_P0L0,                                              1, },
-    { MB_TYPE_16x16 | MB_TYPE_P0L1,                                              1, },
-    { MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P0L1,                               1, },
-    { MB_TYPE_16x8  | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               2, },
-    { MB_TYPE_8x16  | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               2, },
-    { MB_TYPE_16x8  | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               2, },
-    { MB_TYPE_8x16  | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               2, },
-    { MB_TYPE_16x8  | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, },
-    { MB_TYPE_8x16  | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 2, },
-    { MB_TYPE_8x8   | MB_TYPE_P0L0 | MB_TYPE_P1L0,                               4, },
-    { MB_TYPE_8x8   | MB_TYPE_P0L1 | MB_TYPE_P1L1,                               4, },
-    { MB_TYPE_8x8   | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 4, },
-};
+extern const PMbInfo ff_h264_p_mb_type_info[5];
+extern const PMbInfo ff_h264_p_sub_mb_type_info[4];
+extern const PMbInfo ff_h264_b_mb_type_info[23];
+extern const PMbInfo ff_h264_b_sub_mb_type_info[13];
 
 static const AVRational ff_h264_pixel_aspect[17] = {
     {   0,  1 },
@@ -186,4 +67,13 @@ static const AVRational ff_h264_pixel_aspect[17] = {
     {   3,  2 },
     {   2,  1 },
 };
+
+extern const uint8_t ff_h264_dequant4_coeff_init[6][3];
+extern const uint8_t ff_h264_dequant8_coeff_init_scan[16];
+extern const uint8_t ff_h264_dequant8_coeff_init[6][6];
+extern const uint8_t ff_h264_quant_rem6[QP_MAX_NUM + 1];
+extern const uint8_t ff_h264_quant_div6[QP_MAX_NUM + 1];
+
+extern const uint8_t ff_h264_chroma_qp[7][QP_MAX_NUM + 1];
+
 #endif /* AVCODEC_H264DATA_H */
diff --git a/libavcodec/h264dsp.c b/libavcodec/h264dsp.c
index bfb6f1e..d26f552 100644
--- a/libavcodec/h264dsp.c
+++ b/libavcodec/h264dsp.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 DSP functions.
+ * H.264 / AVC / MPEG-4 part10 DSP functions.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h
index c232193..7f24376 100644
--- a/libavcodec/h264dsp.h
+++ b/libavcodec/h264dsp.h
@@ -70,7 +70,7 @@ typedef struct H264DSPContext {
                                             int stride, int alpha, int beta);
     void (*h264_h_loop_filter_chroma_mbaff_intra)(uint8_t *pix /*align 8*/,
                                                   int stride, int alpha, int beta);
-    // h264_loop_filter_strength: simd only. the C version is inlined in h264.c
+    // h264_loop_filter_strength: simd only. the C version is inlined in h264_loopfilter.c
     void (*h264_loop_filter_strength)(int16_t bS[2][4][4], uint8_t nnz[40],
                                       int8_t ref[2][40], int16_t mv[2][40][2],
                                       int bidir, int edges, int step,
diff --git a/libavcodec/h264dsp_template.c b/libavcodec/h264dsp_template.c
index 9b2cc24..d9dcf6b 100644
--- a/libavcodec/h264dsp_template.c
+++ b/libavcodec/h264dsp_template.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 DSP functions.
+ * H.264 / AVC / MPEG-4 part10 DSP functions.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c
index 8f15f71..5632a58 100644
--- a/libavcodec/h264pred.c
+++ b/libavcodec/h264pred.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 prediction functions.
+ * H.264 / AVC / MPEG-4 part10 prediction functions.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -556,7 +556,7 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id,
     h->pred16x16[TOP_DC_PRED8x8 ]= FUNCC(pred16x16_top_dc                 , depth);\
     h->pred16x16[DC_128_PRED8x8 ]= FUNCC(pred16x16_128_dc                 , depth);\
 \
-    /* special lossless h/v prediction for h264 */ \
+    /* special lossless h/v prediction for H.264 */ \
     h->pred4x4_add  [VERT_PRED   ]= FUNCC(pred4x4_vertical_add            , depth);\
     h->pred4x4_add  [ HOR_PRED   ]= FUNCC(pred4x4_horizontal_add          , depth);\
     h->pred8x8l_add [VERT_PRED   ]= FUNCC(pred8x8l_vertical_add           , depth);\
diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h
index 091dcbb..2863dc9 100644
--- a/libavcodec/h264pred.h
+++ b/libavcodec/h264pred.h
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 prediction functions.
+ * H.264 / AVC / MPEG-4 prediction functions.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
@@ -75,7 +75,7 @@
 #define TOP_DC_PRED8x8         5
 #define DC_128_PRED8x8         6
 
-// H264/SVQ3 (8x8) specific
+// H.264/SVQ3 (8x8) specific
 #define ALZHEIMER_DC_L0T_PRED8x8  7
 #define ALZHEIMER_DC_0LT_PRED8x8  8
 #define ALZHEIMER_DC_L00_PRED8x8  9
diff --git a/libavcodec/h264pred_template.c b/libavcodec/h264pred_template.c
index f684433..2b30fff 100644
--- a/libavcodec/h264pred_template.c
+++ b/libavcodec/h264pred_template.c
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 prediction functions.
+ * H.264 / AVC / MPEG-4 part10 prediction functions.
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
 
diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c
index 203f90a..b478065 100644
--- a/libavcodec/hevc.c
+++ b/libavcodec/hevc.c
@@ -347,7 +347,9 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps, enum AVPixelFormat pix_fm
 
     export_stream_params(s->avctx, &s->ps, sps);
 
-    if (sps->pix_fmt == AV_PIX_FMT_YUV420P || sps->pix_fmt == AV_PIX_FMT_YUVJ420P) {
+    switch (sps->pix_fmt) {
+    case AV_PIX_FMT_YUV420P:
+    case AV_PIX_FMT_YUVJ420P:
 #if CONFIG_HEVC_DXVA2_HWACCEL
         *fmt++ = AV_PIX_FMT_DXVA2_VLD;
 #endif
@@ -360,6 +362,15 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps, enum AVPixelFormat pix_fm
 #if CONFIG_HEVC_VDPAU_HWACCEL
         *fmt++ = AV_PIX_FMT_VDPAU;
 #endif
+        break;
+    case AV_PIX_FMT_YUV420P10:
+#if CONFIG_HEVC_DXVA2_HWACCEL
+        *fmt++ = AV_PIX_FMT_DXVA2_VLD;
+#endif
+#if CONFIG_HEVC_D3D11VA_HWACCEL
+        *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+#endif
+        break;
     }
 
     if (pix_fmt == AV_PIX_FMT_NONE) {
@@ -2437,7 +2448,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int
     return 0;
 }
 
-static int hls_slice_data_wpp(HEVCContext *s, const HEVCNAL *nal)
+static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
 {
     const uint8_t *data = nal->data;
     int length          = nal->size;
@@ -2703,7 +2714,7 @@ fail:
     return ret;
 }
 
-static int decode_nal_unit(HEVCContext *s, const HEVCNAL *nal)
+static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal)
 {
     HEVCLocalContext *lc = s->HEVClc;
     GetBitContext *gb    = &lc->gb;
@@ -2855,8 +2866,8 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length)
 
     /* split the input packet into NAL units, so we know the upper bound on the
      * number of slices in the frame */
-    ret = ff_hevc_split_packet(s, &s->pkt, buf, length, s->avctx, s->is_nalff,
-                               s->nal_length_size);
+    ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx, s->is_nalff,
+                                s->nal_length_size, s->avctx->codec_id);
     if (ret < 0) {
         av_log(s->avctx, AV_LOG_ERROR,
                "Error splitting the input into NAL units.\n");
@@ -3100,12 +3111,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
         s->HEVClc = NULL;
     av_freep(&s->HEVClcList[0]);
 
-    for (i = 0; i < s->pkt.nals_allocated; i++) {
-        av_freep(&s->pkt.nals[i].rbsp_buffer);
-        av_freep(&s->pkt.nals[i].skipped_bytes_pos);
-    }
-    av_freep(&s->pkt.nals);
-    s->pkt.nals_allocated = 0;
+    ff_h2645_packet_uninit(&s->pkt);
 
     return 0;
 }
@@ -3149,6 +3155,8 @@ static av_cold int hevc_init_context(AVCodecContext *avctx)
     s->context_initialized = 1;
     s->eos = 0;
 
+    ff_hevc_reset_sei(s);
+
     return 0;
 
 fail:
diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h
index c91f815..be91010 100644
--- a/libavcodec/hevc.h
+++ b/libavcodec/hevc.h
@@ -31,6 +31,7 @@
 #include "cabac.h"
 #include "get_bits.h"
 #include "hevcpred.h"
+#include "h2645_parse.h"
 #include "hevcdsp.h"
 #include "internal.h"
 #include "thread.h"
@@ -746,33 +747,6 @@ typedef struct HEVCFrame {
     uint8_t flags;
 } HEVCFrame;
 
-typedef struct HEVCNAL {
-    uint8_t *rbsp_buffer;
-    int rbsp_buffer_size;
-
-    int size;
-    const uint8_t *data;
-
-    int raw_size;
-    const uint8_t *raw_data;
-
-    GetBitContext gb;
-
-    enum NALUnitType type;
-    int temporal_id;
-
-    int skipped_bytes;
-    int skipped_bytes_pos_size;
-    int *skipped_bytes_pos;
-} HEVCNAL;
-
-/* an input packet split into unescaped NAL units */
-typedef struct HEVCPacket {
-    HEVCNAL *nals;
-    int nb_nals;
-    int nals_allocated;
-} HEVCPacket;
-
 typedef struct HEVCLocalContext {
     uint8_t cabac_state[HEVC_CONTEXTS];
 
@@ -906,7 +880,7 @@ typedef struct HEVCContext {
 
     const uint8_t *data;
 
-    HEVCPacket pkt;
+    H2645Packet pkt;
     // type of the first VCL NAL of the current frame
     enum NALUnitType first_nal_type;
 
@@ -1077,20 +1051,17 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
 void ff_hevc_hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size);
 
 
-/**
- * Extract the raw (unescaped) HEVC bitstream.
- */
-int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length,
-                         HEVCNAL *nal);
+int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id,
+                           uint8_t *buf, int buf_size);
 
 /**
- * Split an input packet into NAL units.
+ * Reset SEI values that are stored on the Context.
+ * e.g. Caption data that was extracted during NAL
+ * parsing.
+ *
+ * @param s HEVCContext.
  */
-int ff_hevc_split_packet(HEVCContext *s, HEVCPacket *pkt, const uint8_t *buf, int length,
-                         AVCodecContext *avctx, int is_nalff, int nal_length_size);
-
-int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id,
-                           uint8_t *buf, int buf_size);
+void ff_hevc_reset_sei(HEVCContext *s);
 
 extern const uint8_t ff_hevc_qpel_extra_before[4];
 extern const uint8_t ff_hevc_qpel_extra_after[4];
diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c
index d1bef83..05b2821 100644
--- a/libavcodec/hevc_cabac.c
+++ b/libavcodec/hevc_cabac.c
@@ -1039,7 +1039,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
     int trafo_size = 1 << log2_trafo_size;
     int i;
     int qp,shift,add,scale,scale_m;
-    const uint8_t level_scale[] = { 40, 45, 51, 57, 64, 72 };
+    static const uint8_t level_scale[] = { 40, 45, 51, 57, 64, 72 };
     const uint8_t *scale_matrix = NULL;
     uint8_t dc_scale;
     int pred_mode_intra = (c_idx == 0) ? lc->tu.intra_pred_mode :
diff --git a/libavcodec/hevc_mp4toannexb_bsf.c b/libavcodec/hevc_mp4toannexb_bsf.c
index d6feb99..5cc642b 100644
--- a/libavcodec/hevc_mp4toannexb_bsf.c
+++ b/libavcodec/hevc_mp4toannexb_bsf.c
@@ -25,6 +25,7 @@
 #include "libavutil/mem.h"
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "bytestream.h"
 #include "hevc.h"
 
@@ -33,23 +34,9 @@
 typedef struct HEVCBSFContext {
     uint8_t  length_size;
     int      extradata_parsed;
-
-    int logged_nonmp4_warning;
-
-    /* When private_spspps is zero then spspps_buf points to global extradata
-       and bsf does replace a global extradata to own-allocated version (default
-       behaviour).
-       When private_spspps is non-zero the bsf uses a private version of spspps buf.
-       This mode necessary when bsf uses in decoder, else bsf has issues after
-       decoder re-initialization. Use the "private_spspps_buf" argument to
-       activate this mode.
-     */
-    int      private_spspps;
-    uint8_t *spspps_buf;
-    uint32_t spspps_size;
 } HEVCBSFContext;
 
-static int hevc_extradata_to_annexb(HEVCBSFContext* ctx, AVCodecContext *avctx)
+static int hevc_extradata_to_annexb(AVBSFContext *ctx)
 {
     GetByteContext gb;
     int length_size, num_arrays, i, j;
@@ -58,7 +45,7 @@ static int hevc_extradata_to_annexb(HEVCBSFContext* ctx, AVCodecContext *avctx)
     uint8_t *new_extradata = NULL;
     size_t   new_extradata_size = 0;
 
-    bytestream2_init(&gb, avctx->extradata, avctx->extradata_size);
+    bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size);
 
     bytestream2_skip(&gb, 21);
     length_size = (bytestream2_get_byte(&gb) & 3) + 1;
@@ -70,7 +57,7 @@ static int hevc_extradata_to_annexb(HEVCBSFContext* ctx, AVCodecContext *avctx)
 
         if (!(type == NAL_VPS || type == NAL_SPS || type == NAL_PPS ||
               type == NAL_SEI_PREFIX || type == NAL_SEI_SUFFIX)) {
-            av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
+            av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
                    type);
             ret = AVERROR_INVALIDDATA;
             goto fail;
@@ -94,16 +81,12 @@ static int hevc_extradata_to_annexb(HEVCBSFContext* ctx, AVCodecContext *avctx)
         }
     }
 
-    if (!ctx->private_spspps) {
-        av_freep(&avctx->extradata);
-        avctx->extradata      = new_extradata;
-        avctx->extradata_size = new_extradata_size;
-    }
-    ctx->spspps_buf  = new_extradata;
-    ctx->spspps_size = new_extradata_size;
+    av_freep(&ctx->par_out->extradata);
+    ctx->par_out->extradata      = new_extradata;
+    ctx->par_out->extradata_size = new_extradata_size;
 
     if (!new_extradata_size)
-        av_log(avctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
+        av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
 
     return length_size;
 fail:
@@ -111,54 +94,54 @@ fail:
     return ret;
 }
 
-static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
-                                   AVCodecContext *avctx, const char *args,
-                                   uint8_t **poutbuf, int *poutbuf_size,
-                                   const uint8_t *buf, int buf_size,
-                                   int keyframe)
+static int hevc_mp4toannexb_init(AVBSFContext *ctx)
+{
+    HEVCBSFContext *s = ctx->priv_data;
+    int ret;
+
+    if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH ||
+        AV_RB24(ctx->par_in->extradata) == 1           ||
+        AV_RB32(ctx->par_in->extradata) == 1) {
+        av_log(ctx, AV_LOG_VERBOSE,
+               "The input looks like it is Annex B already\n");
+    } else {
+        ret = hevc_extradata_to_annexb(ctx);
+        if (ret < 0)
+            return ret;
+        s->length_size      = ret;
+        s->extradata_parsed = 1;
+    }
+
+    return 0;
+}
+
+static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
 {
-    HEVCBSFContext *ctx = bsfc->priv_data;
+    HEVCBSFContext *s = ctx->priv_data;
+    AVPacket *in;
     GetByteContext gb;
 
-    uint8_t *out = NULL;
-    size_t   out_size = 0;
     int got_irap = 0;
     int i, ret = 0;
 
-    if (!ctx->extradata_parsed) {
-        if (avctx->extradata_size < MIN_HEVCC_LENGTH ||
-            AV_RB24(avctx->extradata) == 1           ||
-            AV_RB32(avctx->extradata) == 1) {
-            if (!ctx->logged_nonmp4_warning) {
-                av_log(avctx, AV_LOG_VERBOSE,
-                       "The input looks like it is Annex B already\n");
-                ctx->logged_nonmp4_warning = 1;
-            }
-            *poutbuf      = (uint8_t *)buf;
-            *poutbuf_size = buf_size;
-            return 0;
-        }
-        if (args && strstr(args, "private_spspps_buf"))
-            ctx->private_spspps = 1;
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
 
-        ret = hevc_extradata_to_annexb(ctx, avctx);
-        if (ret < 0)
-            return ret;
-        ctx->length_size      = ret;
-        ctx->extradata_parsed = 1;
+    if (!s->extradata_parsed) {
+        av_packet_move_ref(out, in);
+        av_packet_free(&in);
+        return 0;
     }
 
-    *poutbuf_size = 0;
-    *poutbuf      = NULL;
-
-    bytestream2_init(&gb, buf, buf_size);
+    bytestream2_init(&gb, in->data, in->size);
 
     while (bytestream2_get_bytes_left(&gb)) {
         uint32_t nalu_size = 0;
         int      nalu_type;
-        int is_irap, add_extradata, extra_size;
+        int is_irap, add_extradata, extra_size, prev_size;
 
-        for (i = 0; i < ctx->length_size; i++)
+        for (i = 0; i < s->length_size; i++)
             nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
 
         nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
@@ -166,47 +149,47 @@ static int hevc_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
         /* prepend extradata to IRAP frames */
         is_irap       = nalu_type >= 16 && nalu_type <= 23;
         add_extradata = is_irap && !got_irap;
-        extra_size    = add_extradata * ctx->spspps_size;
+        extra_size    = add_extradata * ctx->par_out->extradata_size;
         got_irap     |= is_irap;
 
-        if (SIZE_MAX - out_size < 4             ||
-            SIZE_MAX - out_size - 4 < nalu_size ||
-            SIZE_MAX - out_size - 4 - nalu_size < extra_size) {
+        if (SIZE_MAX - nalu_size < 4 ||
+            SIZE_MAX - 4 - nalu_size < extra_size) {
             ret = AVERROR_INVALIDDATA;
             goto fail;
         }
 
-        ret = av_reallocp(&out, out_size + 4 + nalu_size + extra_size);
+        prev_size = out->size;
+
+        ret = av_grow_packet(out, 4 + nalu_size + extra_size);
         if (ret < 0)
             goto fail;
 
         if (add_extradata)
-            memcpy(out + out_size, ctx->spspps_buf, extra_size);
-        AV_WB32(out + out_size + extra_size, 1);
-        bytestream2_get_buffer(&gb, out + out_size + 4 + extra_size, nalu_size);
-        out_size += 4 + nalu_size + extra_size;
+            memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size);
+        AV_WB32(out->data + prev_size + extra_size, 1);
+        bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size);
     }
 
-    *poutbuf      = out;
-    *poutbuf_size = out_size;
-
-    return 1;
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
 
 fail:
-    av_freep(&out);
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+
     return ret;
 }
 
-static void hevc_mp4toannexb_close(AVBitStreamFilterContext *bsfc)
-{
-    HEVCBSFContext *ctx = bsfc->priv_data;
-    if (ctx->private_spspps)
-        av_freep(&ctx->spspps_buf);
-}
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE,
+};
 
-AVBitStreamFilter ff_hevc_mp4toannexb_bsf = {
-    "hevc_mp4toannexb",
-    sizeof(HEVCBSFContext),
-    hevc_mp4toannexb_filter,
-    hevc_mp4toannexb_close,
+const AVBitStreamFilter ff_hevc_mp4toannexb_bsf = {
+    .name           = "hevc_mp4toannexb",
+    .priv_data_size = sizeof(HEVCBSFContext),
+    .init           = hevc_mp4toannexb_init,
+    .filter         = hevc_mp4toannexb_filter,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/hevc_mvs.c b/libavcodec/hevc_mvs.c
index 00da575..4a6dde0 100644
--- a/libavcodec/hevc_mvs.c
+++ b/libavcodec/hevc_mvs.c
@@ -81,7 +81,7 @@ static av_always_inline int z_scan_block_avail(HEVCContext *s, int xCurr, int yC
     }
 }
 
-//check if the two luma locations belong to the same mostion estimation region
+//check if the two luma locations belong to the same motion estimation region
 static av_always_inline int is_diff_mer(HEVCContext *s, int xN, int yN, int xP, int yP)
 {
     uint8_t plevel = s->ps.pps->log2_parallel_merge_level;
diff --git a/libavcodec/hevc_parse.c b/libavcodec/hevc_parse.c
deleted file mode 100644
index d557cc7..0000000
--- a/libavcodec/hevc_parse.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * HEVC common code
- *
- * 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 <string.h>
-
-#include "config.h"
-
-#include "libavutil/intreadwrite.h"
-#include "libavutil/mem.h"
-
-#include "hevc.h"
-
-/* FIXME: This is adapted from ff_h264_decode_nal, avoiding duplication
- * between these functions would be nice. */
-int ff_hevc_extract_rbsp(HEVCContext *s, const uint8_t *src, int length,
-                         HEVCNAL *nal)
-{
-    int i, si, di;
-    uint8_t *dst;
-
-    if (s)
-        nal->skipped_bytes = 0;
-#define STARTCODE_TEST                                                  \
-        if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3) {     \
-            if (src[i + 2] != 3) {                                      \
-                /* startcode, so we must be past the end */             \
-                length = i;                                             \
-            }                                                           \
-            break;                                                      \
-        }
-#if HAVE_FAST_UNALIGNED
-#define FIND_FIRST_ZERO                                                 \
-        if (i > 0 && !src[i])                                           \
-            i--;                                                        \
-        while (src[i])                                                  \
-            i++
-#if HAVE_FAST_64BIT
-    for (i = 0; i + 1 < length; i += 9) {
-        if (!((~AV_RN64A(src + i) &
-               (AV_RN64A(src + i) - 0x0100010001000101ULL)) &
-              0x8000800080008080ULL))
-            continue;
-        FIND_FIRST_ZERO;
-        STARTCODE_TEST;
-        i -= 7;
-    }
-#else
-    for (i = 0; i + 1 < length; i += 5) {
-        if (!((~AV_RN32A(src + i) &
-               (AV_RN32A(src + i) - 0x01000101U)) &
-              0x80008080U))
-            continue;
-        FIND_FIRST_ZERO;
-        STARTCODE_TEST;
-        i -= 3;
-    }
-#endif /* HAVE_FAST_64BIT */
-#else
-    for (i = 0; i + 1 < length; i += 2) {
-        if (src[i])
-            continue;
-        if (i > 0 && src[i - 1] == 0)
-            i--;
-        STARTCODE_TEST;
-    }
-#endif /* HAVE_FAST_UNALIGNED */
-
-    if (i >= length - 1) { // no escaped 0
-        nal->data     =
-        nal->raw_data = src;
-        nal->size     =
-        nal->raw_size = length;
-        return length;
-    }
-
-    av_fast_malloc(&nal->rbsp_buffer, &nal->rbsp_buffer_size,
-                   length + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!nal->rbsp_buffer)
-        return AVERROR(ENOMEM);
-
-    dst = nal->rbsp_buffer;
-
-    memcpy(dst, src, i);
-    si = di = i;
-    while (si + 2 < length) {
-        // remove escapes (very rare 1:2^22)
-        if (src[si + 2] > 3) {
-            dst[di++] = src[si++];
-            dst[di++] = src[si++];
-        } else if (src[si] == 0 && src[si + 1] == 0) {
-            if (src[si + 2] == 3) { // escape
-                dst[di++] = 0;
-                dst[di++] = 0;
-                si       += 3;
-
-                if (s && nal->skipped_bytes_pos) {
-                    nal->skipped_bytes++;
-                    if (nal->skipped_bytes_pos_size < nal->skipped_bytes) {
-                        nal->skipped_bytes_pos_size *= 2;
-                        av_assert0(nal->skipped_bytes_pos_size >= nal->skipped_bytes);
-                        av_reallocp_array(&nal->skipped_bytes_pos,
-                                nal->skipped_bytes_pos_size,
-                                sizeof(*nal->skipped_bytes_pos));
-                        if (!nal->skipped_bytes_pos) {
-                            nal->skipped_bytes_pos_size = 0;
-                            return AVERROR(ENOMEM);
-                        }
-                    }
-                    if (nal->skipped_bytes_pos)
-                        nal->skipped_bytes_pos[nal->skipped_bytes-1] = di - 1;
-                }
-                continue;
-            } else // next start code
-                goto nsc;
-        }
-
-        dst[di++] = src[si++];
-    }
-    while (si < length)
-        dst[di++] = src[si++];
-
-nsc:
-    memset(dst + di, 0, AV_INPUT_BUFFER_PADDING_SIZE);
-
-    nal->data = dst;
-    nal->size = di;
-    nal->raw_data = src;
-    nal->raw_size = si;
-    return si;
-}
-
-static const char *nal_unit_name(int nal_type)
-{
-    switch(nal_type) {
-    case NAL_TRAIL_N    : return "TRAIL_N";
-    case NAL_TRAIL_R    : return "TRAIL_R";
-    case NAL_TSA_N      : return "TSA_N";
-    case NAL_TSA_R      : return "TSA_R";
-    case NAL_STSA_N     : return "STSA_N";
-    case NAL_STSA_R     : return "STSA_R";
-    case NAL_RADL_N     : return "RADL_N";
-    case NAL_RADL_R     : return "RADL_R";
-    case NAL_RASL_N     : return "RASL_N";
-    case NAL_RASL_R     : return "RASL_R";
-    case NAL_BLA_W_LP   : return "BLA_W_LP";
-    case NAL_BLA_W_RADL : return "BLA_W_RADL";
-    case NAL_BLA_N_LP   : return "BLA_N_LP";
-    case NAL_IDR_W_RADL : return "IDR_W_RADL";
-    case NAL_IDR_N_LP   : return "IDR_N_LP";
-    case NAL_CRA_NUT    : return "CRA_NUT";
-    case NAL_VPS        : return "VPS";
-    case NAL_SPS        : return "SPS";
-    case NAL_PPS        : return "PPS";
-    case NAL_AUD        : return "AUD";
-    case NAL_EOS_NUT    : return "EOS_NUT";
-    case NAL_EOB_NUT    : return "EOB_NUT";
-    case NAL_FD_NUT     : return "FD_NUT";
-    case NAL_SEI_PREFIX : return "SEI_PREFIX";
-    case NAL_SEI_SUFFIX : return "SEI_SUFFIX";
-    default : return "?";
-    }
-}
-
-/**
- * @return AVERROR_INVALIDDATA if the packet is not a valid NAL unit,
- * 0 if the unit should be skipped, 1 otherwise
- */
-static int hls_nal_unit(HEVCNAL *nal, AVCodecContext *avctx)
-{
-    GetBitContext *gb = &nal->gb;
-    int nuh_layer_id;
-
-    if (get_bits1(gb) != 0)
-        return AVERROR_INVALIDDATA;
-
-    nal->type = get_bits(gb, 6);
-
-    nuh_layer_id   = get_bits(gb, 6);
-    nal->temporal_id = get_bits(gb, 3) - 1;
-    if (nal->temporal_id < 0)
-        return AVERROR_INVALIDDATA;
-
-    av_log(avctx, AV_LOG_DEBUG,
-           "nal_unit_type: %d(%s), nuh_layer_id: %d, temporal_id: %d\n",
-           nal->type, nal_unit_name(nal->type), nuh_layer_id, nal->temporal_id);
-
-    return nuh_layer_id == 0;
-}
-
-
-int ff_hevc_split_packet(HEVCContext *s, HEVCPacket *pkt, const uint8_t *buf, int length,
-                         AVCodecContext *avctx, int is_nalff, int nal_length_size)
-{
-    int consumed, ret = 0;
-
-    pkt->nb_nals = 0;
-    while (length >= 4) {
-        HEVCNAL *nal;
-        int extract_length = 0;
-
-        if (is_nalff) {
-            int i;
-            for (i = 0; i < nal_length_size; i++)
-                extract_length = (extract_length << 8) | buf[i];
-            buf    += nal_length_size;
-            length -= nal_length_size;
-
-            if (extract_length > length) {
-                av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit size.\n");
-                return AVERROR_INVALIDDATA;
-            }
-        } else {
-            /* search start code */
-            while (buf[0] != 0 || buf[1] != 0 || buf[2] != 1) {
-                ++buf;
-                --length;
-                if (length < 4) {
-                    if (pkt->nb_nals > 0) {
-                        // No more start codes: we discarded some irrelevant
-                        // bytes at the end of the packet.
-                        return 0;
-                    } else {
-                        av_log(avctx, AV_LOG_ERROR, "No start code is found.\n");
-                        return AVERROR_INVALIDDATA;
-                    }
-                }
-            }
-
-            buf           += 3;
-            length        -= 3;
-            extract_length = length;
-        }
-
-        if (pkt->nals_allocated < pkt->nb_nals + 1) {
-            int new_size = pkt->nals_allocated + 1;
-            void *tmp = av_realloc_array(pkt->nals, new_size, sizeof(*pkt->nals));
-
-            if (!tmp)
-                return AVERROR(ENOMEM);
-
-            pkt->nals = tmp;
-            memset(pkt->nals + pkt->nals_allocated, 0,
-                   (new_size - pkt->nals_allocated) * sizeof(*pkt->nals));
-
-            nal = &pkt->nals[pkt->nb_nals];
-            nal->skipped_bytes_pos_size = 1024; // initial buffer size
-            nal->skipped_bytes_pos = av_malloc_array(nal->skipped_bytes_pos_size, sizeof(*nal->skipped_bytes_pos));
-            if (!nal->skipped_bytes_pos)
-                return AVERROR(ENOMEM);
-
-            pkt->nals_allocated = new_size;
-        }
-        nal = &pkt->nals[pkt->nb_nals];
-
-        consumed = ff_hevc_extract_rbsp(s, buf, extract_length, nal);
-        if (consumed < 0)
-            return consumed;
-
-        pkt->nb_nals++;
-
-        ret = init_get_bits8(&nal->gb, nal->data, nal->size);
-        if (ret < 0)
-            return ret;
-
-        ret = hls_nal_unit(nal, avctx);
-        if (ret <= 0) {
-            if (ret < 0) {
-                av_log(avctx, AV_LOG_ERROR, "Invalid NAL unit %d, skipping.\n",
-                       nal->type);
-            }
-            pkt->nb_nals--;
-        }
-
-        buf    += consumed;
-        length -= consumed;
-    }
-
-    return 0;
-}
-
diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c
index 4625e61..b5633f1 100644
--- a/libavcodec/hevc_parser.c
+++ b/libavcodec/hevc_parser.c
@@ -24,6 +24,7 @@
 
 #include "golomb.h"
 #include "hevc.h"
+#include "h2645_parse.h"
 #include "parser.h"
 
 #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
@@ -35,7 +36,7 @@
 typedef struct HEVCParserContext {
     ParseContext pc;
 
-    HEVCPacket pkt;
+    H2645Packet pkt;
     HEVCParamSets ps;
 
     int parsed_extradata;
@@ -46,7 +47,7 @@ typedef struct HEVCParserContext {
 } HEVCParserContext;
 
 #if !ADVANCED_PARSER
-static int hevc_parse_slice_header(AVCodecParserContext *s, HEVCNAL *nal,
+static int hevc_parse_slice_header(AVCodecParserContext *s, H2645NAL *nal,
                                    AVCodecContext *avctx)
 {
     HEVCParserContext *ctx = s->priv_data;
@@ -88,12 +89,13 @@ static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
     HEVCParserContext *ctx = s->priv_data;
     int ret, i;
 
-    ret = ff_hevc_split_packet(NULL, &ctx->pkt, buf, buf_size, avctx, 0, 0);
+    ret = ff_h2645_packet_split(&ctx->pkt, buf, buf_size, avctx, 0, 0,
+                                AV_CODEC_ID_HEVC);
     if (ret < 0)
         return ret;
 
     for (i = 0; i < ctx->pkt.nb_nals; i++) {
-        HEVCNAL *nal = &ctx->pkt.nals[i];
+        H2645NAL *nal = &ctx->pkt.nals[i];
 
         /* ignore everything except parameter sets and VCL NALUs */
         switch (nal->type) {
@@ -189,10 +191,10 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
     GetBitContext      *gb;
     SliceHeader        *sh = &h->sh;
     HEVCParamSets *ps = &h->ps;
-    HEVCPacket   *pkt = &ctx->pkt;
+    H2645Packet   *pkt = &ctx->pkt;
     const uint8_t *buf_end = buf + buf_size;
     int state = -1, i;
-    HEVCNAL *nal;
+    H2645NAL *nal;
     int is_global = buf == avctx->extradata;
 
     if (!h->HEVClc)
@@ -209,11 +211,13 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
 
     h->avctx = avctx;
 
+    ff_hevc_reset_sei(h);
+
     if (!buf_size)
         return 0;
 
     if (pkt->nals_allocated < 1) {
-        HEVCNAL *tmp = av_realloc_array(pkt->nals, 1, sizeof(*tmp));
+        H2645NAL *tmp = av_realloc_array(pkt->nals, 1, sizeof(*tmp));
         if (!tmp)
             return AVERROR(ENOMEM);
         pkt->nals = tmp;
@@ -239,7 +243,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
                 src_length = 20;
         }
 
-        consumed = ff_hevc_extract_rbsp(NULL, buf, src_length, nal);
+        consumed = ff_h2645_extract_rbsp(buf, src_length, nal);
         if (consumed < 0)
             return consumed;
 
@@ -471,12 +475,7 @@ static void hevc_parser_close(AVCodecParserContext *s)
 
     ctx->ps.sps = NULL;
 
-    for (i = 0; i < ctx->pkt.nals_allocated; i++) {
-        av_freep(&ctx->pkt.nals[i].rbsp_buffer);
-        av_freep(&ctx->pkt.nals[i].skipped_bytes_pos);
-    }
-    av_freep(&ctx->pkt.nals);
-    ctx->pkt.nals_allocated = 0;
+    ff_h2645_packet_uninit(&ctx->pkt);
 
     av_freep(&ctx->pc.buffer);
 }
diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c
index 64d6e2f..83f2ec2 100644
--- a/libavcodec/hevc_ps.c
+++ b/libavcodec/hevc_ps.c
@@ -280,7 +280,7 @@ static int parse_ptl(GetBitContext *gb, AVCodecContext *avctx,
 {
     int i;
     if (decode_profile_tier_level(gb, avctx, &ptl->general_ptl) < 0 ||
-        get_bits_left(gb) < 8 + 8*2) {
+        get_bits_left(gb) < 8 + (8*2 * (max_num_sub_layers - 1 > 0))) {
         av_log(avctx, AV_LOG_ERROR, "PTL information too short\n");
         return -1;
     }
@@ -561,6 +561,19 @@ static void decode_vui(GetBitContext *gb, AVCodecContext *avctx,
                 vui->transfer_characteristic = AVCOL_TRC_UNSPECIFIED;
             if (vui->matrix_coeffs >= AVCOL_SPC_NB)
                 vui->matrix_coeffs = AVCOL_SPC_UNSPECIFIED;
+            if (vui->matrix_coeffs == AVCOL_SPC_RGB) {
+                switch (sps->pix_fmt) {
+                case AV_PIX_FMT_YUV444P:
+                    sps->pix_fmt = AV_PIX_FMT_GBRP;
+                    break;
+                case AV_PIX_FMT_YUV444P10:
+                    sps->pix_fmt = AV_PIX_FMT_GBRP10;
+                    break;
+                case AV_PIX_FMT_YUV444P12:
+                    sps->pix_fmt = AV_PIX_FMT_GBRP12;
+                    break;
+                }
+            }
         }
     }
 
@@ -583,11 +596,12 @@ static void decode_vui(GetBitContext *gb, AVCodecContext *avctx,
     memcpy(&backup, gb, sizeof(backup));
 
     if (vui->default_display_window_flag) {
-        //TODO: * 2 is only valid for 420
-        vui->def_disp_win.left_offset   = get_ue_golomb_long(gb) * 2;
-        vui->def_disp_win.right_offset  = get_ue_golomb_long(gb) * 2;
-        vui->def_disp_win.top_offset    = get_ue_golomb_long(gb) * 2;
-        vui->def_disp_win.bottom_offset = get_ue_golomb_long(gb) * 2;
+        int vert_mult  = 1 + (sps->chroma_format_idc < 2);
+        int horiz_mult = 1 + (sps->chroma_format_idc < 3);
+        vui->def_disp_win.left_offset   = get_ue_golomb_long(gb) * horiz_mult;
+        vui->def_disp_win.right_offset  = get_ue_golomb_long(gb) * horiz_mult;
+        vui->def_disp_win.top_offset    = get_ue_golomb_long(gb) *  vert_mult;
+        vui->def_disp_win.bottom_offset = get_ue_golomb_long(gb) *  vert_mult;
 
         if (apply_defdispwin &&
             avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) {
@@ -856,11 +870,12 @@ int ff_hevc_parse_sps(HEVCSPS *sps, GetBitContext *gb, unsigned int *sps_id,
         return ret;
 
     if (get_bits1(gb)) { // pic_conformance_flag
-        //TODO: * 2 is only valid for 420
-        sps->pic_conf_win.left_offset   = get_ue_golomb_long(gb) * 2;
-        sps->pic_conf_win.right_offset  = get_ue_golomb_long(gb) * 2;
-        sps->pic_conf_win.top_offset    = get_ue_golomb_long(gb) * 2;
-        sps->pic_conf_win.bottom_offset = get_ue_golomb_long(gb) * 2;
+        int vert_mult  = 1 + (sps->chroma_format_idc < 2);
+        int horiz_mult = 1 + (sps->chroma_format_idc < 3);
+        sps->pic_conf_win.left_offset   = get_ue_golomb_long(gb) * horiz_mult;
+        sps->pic_conf_win.right_offset  = get_ue_golomb_long(gb) * horiz_mult;
+        sps->pic_conf_win.top_offset    = get_ue_golomb_long(gb) *  vert_mult;
+        sps->pic_conf_win.bottom_offset = get_ue_golomb_long(gb) *  vert_mult;
 
         if (avctx->flags2 & AV_CODEC_FLAG2_IGNORE_CROP) {
             av_log(avctx, AV_LOG_DEBUG,
diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c
index 40685fe..148f246 100644
--- a/libavcodec/hevc_sei.c
+++ b/libavcodec/hevc_sei.c
@@ -122,7 +122,7 @@ static int decode_nal_sei_frame_packing_arrangement(HEVCContext *s)
         if (!s->quincunx_subsampling && s->frame_packing_arrangement_type != 5)
             skip_bits(gb, 16);  // frame[01]_grid_position_[xy]
         skip_bits(gb, 8);       // frame_packing_arrangement_reserved_byte
-        skip_bits1(gb);         // frame_packing_arrangement_persistance_flag
+        skip_bits1(gb);         // frame_packing_arrangement_persistence_flag
     }
     skip_bits1(gb);             // upsampled_aspect_ratio_flag
     return 0;
@@ -373,3 +373,9 @@ int ff_hevc_decode_nal_sei(HEVCContext *s)
     } while (more_rbsp_data(&s->HEVClc->gb));
     return 1;
 }
+
+void ff_hevc_reset_sei(HEVCContext *s)
+{
+    s->a53_caption_size = 0;
+    av_freep(&s->a53_caption);
+}
diff --git a/libavcodec/hq_hqa.c b/libavcodec/hq_hqa.c
index 3ef83d4..8825f3d 100644
--- a/libavcodec/hq_hqa.c
+++ b/libavcodec/hq_hqa.c
@@ -154,7 +154,7 @@ static int hq_decode_frame(HQContext *ctx, AVFrame *pic,
             slice_off[slice] >= slice_off[slice + 1] ||
             slice_off[slice + 1] > data_size) {
             av_log(ctx->avctx, AV_LOG_ERROR,
-                   "Invalid slice size %zu.\n", data_size);
+                   "Invalid slice size %"SIZE_SPECIFIER".\n", data_size);
             break;
         }
         init_get_bits(&gb, src + slice_off[slice],
@@ -277,7 +277,7 @@ static int hqa_decode_frame(HQContext *ctx, AVFrame *pic, size_t data_size)
             slice_off[slice] >= slice_off[slice + 1] ||
             slice_off[slice + 1] > data_size) {
             av_log(ctx->avctx, AV_LOG_ERROR,
-                   "Invalid slice size %zu.\n", data_size);
+                   "Invalid slice size %"SIZE_SPECIFIER".\n", data_size);
             break;
         }
         init_get_bits(&gb, src + slice_off[slice],
diff --git a/libavcodec/huffman.c b/libavcodec/huffman.c
index d7403b8..a3d3920 100644
--- a/libavcodec/huffman.c
+++ b/libavcodec/huffman.c
@@ -27,9 +27,11 @@
 #include <stdint.h>
 
 #include "libavutil/qsort.h"
+#include"libavutil/common.h"
+
 #include "avcodec.h"
-#include "get_bits.h"
 #include "huffman.h"
+#include "vlc.h"
 
 /* symbol for Huffman tree node */
 #define HNODE -1
diff --git a/libavcodec/huffman.h b/libavcodec/huffman.h
index 6ab23ae..4f879e6 100644
--- a/libavcodec/huffman.h
+++ b/libavcodec/huffman.h
@@ -27,7 +27,7 @@
 #define AVCODEC_HUFFMAN_H
 
 #include "avcodec.h"
-#include "get_bits.h"
+#include "vlc.h"
 
 typedef struct Node {
     int16_t  sym;
diff --git a/libavcodec/idcinvideo.c b/libavcodec/idcinvideo.c
index 4a0a6fb..0870172 100644
--- a/libavcodec/idcinvideo.c
+++ b/libavcodec/idcinvideo.c
@@ -1,6 +1,6 @@
 /*
  * id Quake II CIN Video Decoder
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/iff.c b/libavcodec/iff.c
index 49df17c..ef9ce91 100644
--- a/libavcodec/iff.c
+++ b/libavcodec/iff.c
@@ -1,7 +1,8 @@
 /*
- * IFF ACBM/DEEP/ILBM/PBM bitmap decoder
+ * IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN bitmap decoder
  * Copyright (c) 2010 Peter Ross <pross at xvid.org>
  * Copyright (c) 2010 Sebastian Vater <cdgs.basty at googlemail.com>
+ * Copyright (c) 2016 Paul B Mahol
  *
  * This file is part of FFmpeg.
  *
@@ -22,16 +23,17 @@
 
 /**
  * @file
- * IFF ACBM/DEEP/ILBM/PBM bitmap decoder
+ * IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN bitmap decoder
  */
 
 #include <stdint.h>
 
 #include "libavutil/imgutils.h"
+
 #include "bytestream.h"
 #include "avcodec.h"
-#include "get_bits.h"
 #include "internal.h"
+#include "mathops.h"
 
 // TODO: masking bits
 typedef enum {
@@ -50,6 +52,9 @@ typedef struct IffContext {
     uint32_t *mask_buf;     ///< temporary buffer for palette indices
     uint32_t *mask_palbuf;  ///< masking palette table
     unsigned  compression;  ///< delta compression method used
+    unsigned  is_short;     ///< short compression method used
+    unsigned  is_interlaced;///< video is interlaced
+    unsigned  is_brush;     ///< video is in ANBR format
     unsigned  bpp;          ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
     unsigned  ham;          ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
     unsigned  flags;        ///< 1 for EHB, 0 is no extra half darkening
@@ -57,6 +62,10 @@ typedef struct IffContext {
     unsigned  masking;      ///< TODO: masking method used
     int init; // 1 if buffer and palette data already initialized, 0 otherwise
     int16_t   tvdc[16];     ///< TVDC lookup table
+    GetByteContext gb;
+    uint8_t *video[2];
+    unsigned video_size;
+    uint32_t *pal[2];
 } IffContext;
 
 #define LUT8_PART(plane, v)                             \
@@ -189,10 +198,11 @@ static int cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
  * @return >= 0 in case of success, a negative error code otherwise
  */
 static int extract_header(AVCodecContext *const avctx,
-                          const AVPacket *const avpkt) {
-    const uint8_t *buf;
-    unsigned buf_size;
+                          const AVPacket *const avpkt)
+{
     IffContext *s = avctx->priv_data;
+    const uint8_t *buf;
+    unsigned buf_size = 0;
     int i, palette_size;
 
     if (avctx->extradata_size < 2) {
@@ -201,20 +211,55 @@ static int extract_header(AVCodecContext *const avctx,
     }
     palette_size = avctx->extradata_size - AV_RB16(avctx->extradata);
 
-    if (avpkt) {
-        int image_size;
-        if (avpkt->size < 2)
-            return AVERROR_INVALIDDATA;
-        image_size = avpkt->size - AV_RB16(avpkt->data);
-        buf = avpkt->data;
-        buf_size = bytestream_get_be16(&buf);
-        if (buf_size <= 1 || image_size <= 1) {
-            av_log(avctx, AV_LOG_ERROR,
-                   "Invalid image size received: %u -> image data offset: %d\n",
-                   buf_size, image_size);
-            return AVERROR_INVALIDDATA;
+    if (avpkt && avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
+        uint32_t chunk_id;
+        uint64_t data_size;
+        GetByteContext *gb = &s->gb;
+
+        bytestream2_skip(gb, 4);
+        while (bytestream2_get_bytes_left(gb) >= 1) {
+            chunk_id  = bytestream2_get_le32(gb);
+            data_size = bytestream2_get_be32(gb);
+
+            if (chunk_id == MKTAG('B', 'M', 'H', 'D')) {
+                bytestream2_skip(gb, data_size + (data_size & 1));
+            } else if (chunk_id == MKTAG('A', 'N', 'H', 'D')) {
+                unsigned extra;
+                if (data_size < 40)
+                    return AVERROR_INVALIDDATA;
+
+                s->compression = (bytestream2_get_byte(gb) << 8) | (s->compression & 0xFF);
+                bytestream2_skip(gb, 19);
+                extra = bytestream2_get_be32(gb);
+                s->is_short = !(extra & 1);
+                s->is_brush = extra == 2;
+                s->is_interlaced = !!(extra & 0x40);
+                data_size -= 24;
+                bytestream2_skip(gb, data_size + (data_size & 1));
+            } else if (chunk_id == MKTAG('D', 'L', 'T', 'A') ||
+                       chunk_id == MKTAG('B', 'O', 'D', 'Y')) {
+                if (chunk_id == MKTAG('B','O','D','Y'))
+                    s->compression &= 0xFF;
+                break;
+            } else if (chunk_id == MKTAG('C', 'M', 'A', 'P')) {
+                int count = data_size / 3;
+                uint32_t *pal = s->pal[0];
+
+                if (count > 256)
+                    return AVERROR_INVALIDDATA;
+                if (s->ham) {
+                    for (i = 0; i < count; i++)
+                        pal[i] = 0xFF000000 | bytestream2_get_le24(gb);
+                } else {
+                    for (i = 0; i < count; i++)
+                        pal[i] = 0xFF000000 | bytestream2_get_be24(gb);
+                }
+                bytestream2_skip(gb, data_size & 1);
+            } else {
+                bytestream2_skip(gb, data_size + (data_size&1));
+            }
         }
-    } else {
+    } else if (!avpkt) {
         buf = avctx->extradata;
         buf_size = bytestream_get_be16(&buf);
         if (buf_size <= 1 || palette_size < 0) {
@@ -323,10 +368,13 @@ static int extract_header(AVCodecContext *const avctx,
 static av_cold int decode_end(AVCodecContext *avctx)
 {
     IffContext *s = avctx->priv_data;
-    av_frame_free(&s->frame);
     av_freep(&s->planebuf);
     av_freep(&s->ham_buf);
     av_freep(&s->ham_palbuf);
+    av_freep(&s->video[0]);
+    av_freep(&s->video[1]);
+    av_freep(&s->pal[0]);
+    av_freep(&s->pal[1]);
     return 0;
 }
 
@@ -371,10 +419,15 @@ static av_cold int decode_init(AVCodecContext *avctx)
         return AVERROR(ENOMEM);
 
     s->bpp = avctx->bits_per_coded_sample;
-    s->frame = av_frame_alloc();
-    if (!s->frame) {
-        decode_end(avctx);
-        return AVERROR(ENOMEM);
+
+    if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
+        s->video_size = FFALIGN(avctx->width, 2) * avctx->height * s->bpp;
+        s->video[0] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp);
+        s->video[1] = av_calloc(FFALIGN(avctx->width, 2) * avctx->height, s->bpp);
+        s->pal[0] = av_calloc(256, sizeof(*s->pal[0]));
+        s->pal[1] = av_calloc(256, sizeof(*s->pal[1]));
+        if (!s->video[0] || !s->video[1] || !s->pal[0] || !s->pal[1])
+            return AVERROR(ENOMEM);
     }
 
     if ((err = extract_header(avctx, NULL)) < 0)
@@ -480,20 +533,20 @@ static void lookup_pal_indicies(uint32_t *dst, const uint32_t *buf,
  * @return number of consumed bytes in byterun1 compressed bitstream
  */
 static int decode_byterun(uint8_t *dst, int dst_size,
-                          const uint8_t *buf, const uint8_t *const buf_end)
+                          GetByteContext *gb)
 {
-    const uint8_t *const buf_start = buf;
     unsigned x;
-    for (x = 0; x < dst_size && buf < buf_end;) {
+    for (x = 0; x < dst_size && bytestream2_get_bytes_left(gb) > 0;) {
         unsigned length;
-        const int8_t value = *buf++;
+        const int8_t value = bytestream2_get_byte(gb);
         if (value >= 0) {
-            length = FFMIN3(value + 1, dst_size - x, buf_end - buf);
-            memcpy(dst + x, buf, length);
-            buf += length;
+            length = FFMIN3(value + 1, dst_size - x, bytestream2_get_bytes_left(gb));
+            bytestream2_get_buffer(gb, dst + x, length);
+            if (length < value + 1)
+                bytestream2_skip(gb, value + 1 - length);
         } else if (value > -128) {
             length = FFMIN(-value + 1, dst_size - x);
-            memset(dst + x, *buf++, length);
+            memset(dst + x, bytestream2_get_byte(gb), length);
         } else { // noop
             continue;
         }
@@ -503,7 +556,7 @@ static int decode_byterun(uint8_t *dst, int dst_size,
         av_log(NULL, AV_LOG_WARNING, "decode_byterun ended before plane size\n");
         memset(dst+x, 0, dst_size - x);
     }
-    return buf - buf_start;
+    return bytestream2_tell(gb);
 }
 
 #define DECODE_RGBX_COMMON(type) \
@@ -660,10 +713,700 @@ static void decode_deep_tvdc32(uint8_t *dst, const uint8_t *src, int src_size, i
     }
 }
 
+static void decode_short_horizontal_delta(uint8_t *dst,
+                                          const uint8_t *buf, const uint8_t *buf_end,
+                                          int w, int bpp, int dst_size)
+{
+    int planepitch = FFALIGN(w, 16) >> 3;
+    int pitch = planepitch * bpp;
+    GetByteContext ptrs, gb;
+    PutByteContext pb;
+    unsigned ofssrc, pos;
+    int i, k;
+
+    bytestream2_init(&ptrs, buf, buf_end - buf);
+    bytestream2_init_writer(&pb, dst, dst_size);
+
+    for (k = 0; k < bpp; k++) {
+        ofssrc = bytestream2_get_be32(&ptrs);
+        pos = 0;
+
+        if (!ofssrc)
+            continue;
+
+        if (ofssrc >= buf_end - buf)
+            continue;
+
+        bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
+        while (bytestream2_peek_be16(&gb) != 0xFFFF && bytestream2_get_bytes_left(&gb) > 3) {
+            int16_t offset = bytestream2_get_be16(&gb);
+            unsigned noffset;
+
+            if (offset >= 0) {
+                unsigned data = bytestream2_get_be16(&gb);
+
+                pos += offset * 2;
+                noffset = (pos / planepitch) * pitch + (pos % planepitch) + k * planepitch;
+                bytestream2_seek_p(&pb, noffset, SEEK_SET);
+                bytestream2_put_be16(&pb, data);
+            } else {
+                uint16_t count = bytestream2_get_be16(&gb);
+
+                pos += 2 * -(offset + 2);
+                for (i = 0; i < count; i++) {
+                    uint16_t data = bytestream2_get_be16(&gb);
+
+                    pos += 2;
+                    noffset = (pos / planepitch) * pitch + (pos % planepitch) + k * planepitch;
+                    bytestream2_seek_p(&pb, noffset, SEEK_SET);
+                    bytestream2_put_be16(&pb, data);
+                }
+            }
+        }
+    }
+}
+
+static void decode_byte_vertical_delta(uint8_t *dst,
+                                       const uint8_t *buf, const uint8_t *buf_end,
+                                       int w, int xor, int bpp, int dst_size)
+{
+    int ncolumns = ((w + 15) / 16) * 2;
+    int dstpitch = ncolumns * bpp;
+    unsigned ofsdst, ofssrc, opcode, x;
+    GetByteContext ptrs, gb;
+    PutByteContext pb;
+    int i, j, k;
+
+    bytestream2_init(&ptrs, buf, buf_end - buf);
+    bytestream2_init_writer(&pb, dst, dst_size);
+
+    for (k = 0; k < bpp; k++) {
+        ofssrc = bytestream2_get_be32(&ptrs);
+
+        if (!ofssrc)
+            continue;
+
+        if (ofssrc >= buf_end - buf)
+            continue;
+
+        bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
+        for (j = 0; j < ncolumns; j++) {
+            ofsdst = j + k * ncolumns;
+
+            i = bytestream2_get_byte(&gb);
+            while (i > 0) {
+                opcode = bytestream2_get_byte(&gb);
+
+                if (opcode == 0) {
+                    opcode  = bytestream2_get_byte(&gb);
+                    x = bytestream2_get_byte(&gb);
+
+                    while (opcode) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        if (xor && ofsdst < dst_size) {
+                            bytestream2_put_byte(&pb, dst[ofsdst] ^ x);
+                        } else {
+                            bytestream2_put_byte(&pb, x);
+                        }
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                } else if (opcode < 0x80) {
+                    ofsdst += opcode * dstpitch;
+                } else {
+                    opcode &= 0x7f;
+
+                    while (opcode) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        if (xor && ofsdst < dst_size) {
+                            bytestream2_put_byte(&pb, dst[ofsdst] ^ bytestream2_get_byte(&gb));
+                        } else {
+                            bytestream2_put_byte(&pb, bytestream2_get_byte(&gb));
+                        }
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                }
+                i--;
+            }
+        }
+    }
+}
+
+static void decode_delta_j(uint8_t *dst,
+                           const uint8_t *buf, const uint8_t *buf_end,
+                           int w, int h, int bpp, int dst_size)
+{
+    int32_t pitch;
+    uint8_t *ptr;
+    uint32_t type, flag, cols, groups, rows, bytes;
+    uint32_t offset;
+    int planepitch_byte = (w + 7) / 8;
+    int planepitch = ((w + 15) / 16) * 2;
+    int kludge_j, b, g, r, d;
+    GetByteContext gb;
+
+    pitch = planepitch * bpp;
+    kludge_j = w < 320 ? (320 - w) / 8 / 2 : 0;
+
+    bytestream2_init(&gb, buf, buf_end - buf);
+
+    while (bytestream2_get_bytes_left(&gb) >= 2) {
+        type = bytestream2_get_be16(&gb);
+
+        switch (type) {
+        case 0:
+            return;
+        case 1:
+            flag   = bytestream2_get_be16(&gb);
+            cols   = bytestream2_get_be16(&gb);
+            groups = bytestream2_get_be16(&gb);
+
+            for (g = 0; g < groups; g++) {
+                offset = bytestream2_get_be16(&gb);
+
+                if (bytestream2_get_bytes_left(&gb) < 1)
+                    return;
+
+                if (kludge_j)
+                    offset = ((offset / (320 / 8)) * pitch) + (offset % (320 / 8)) - kludge_j;
+                else
+                    offset = ((offset / planepitch_byte) * pitch) + (offset % planepitch_byte);
+
+                for (b = 0; b < cols; b++) {
+                    for (d = 0; d < bpp; d++) {
+                        uint8_t value = bytestream2_get_byte(&gb);
+
+                        if (offset >= dst_size)
+                            return;
+                        ptr = dst + offset;
+
+                        if (flag)
+                            ptr[0] ^= value;
+                        else
+                            ptr[0]  = value;
+
+                        offset += planepitch;
+                    }
+                }
+                if ((cols * bpp) & 1)
+                    bytestream2_skip(&gb, 1);
+            }
+            break;
+        case 2:
+            flag   = bytestream2_get_be16(&gb);
+            rows   = bytestream2_get_be16(&gb);
+            bytes  = bytestream2_get_be16(&gb);
+            groups = bytestream2_get_be16(&gb);
+
+            for (g = 0; g < groups; g++) {
+                offset = bytestream2_get_be16(&gb);
+
+                if (kludge_j)
+                    offset = ((offset / (320 / 8)) * pitch) + (offset % (320/ 8)) - kludge_j;
+                else
+                    offset = ((offset / planepitch_byte) * pitch) + (offset % planepitch_byte);
+
+                for (r = 0; r < rows; r++) {
+                    for (d = 0; d < bpp; d++) {
+                        unsigned noffset = offset + (r * pitch) + d * planepitch;
+
+                        if (bytestream2_get_bytes_left(&gb) < 1)
+                            return;
+
+                        for (b = 0; b < bytes; b++) {
+                            uint8_t value = bytestream2_get_byte(&gb);
+
+                            if (noffset >= dst_size)
+                                return;
+                            ptr = dst + noffset;
+
+                            if (flag)
+                                ptr[0] ^= value;
+                            else
+                                ptr[0]  = value;
+
+                            noffset++;
+                        }
+                    }
+                }
+                if ((rows * bytes * bpp) & 1)
+                    bytestream2_skip(&gb, 1);
+            }
+            break;
+        default:
+            return;
+        }
+    }
+}
+
+static void decode_short_vertical_delta(uint8_t *dst,
+                                        const uint8_t *buf, const uint8_t *buf_end,
+                                        int w, int bpp, int dst_size)
+{
+    int ncolumns = (w + 15) >> 4;
+    int dstpitch = ncolumns * bpp * 2;
+    unsigned ofsdst, ofssrc, ofsdata, opcode, x;
+    GetByteContext ptrs, gb, dptrs, dgb;
+    PutByteContext pb;
+    int i, j, k;
+
+    if (buf_end - buf <= 64)
+        return;
+
+    bytestream2_init(&ptrs, buf, buf_end - buf);
+    bytestream2_init(&dptrs, buf + 32, (buf_end - buf) - 32);
+    bytestream2_init_writer(&pb, dst, dst_size);
+
+    for (k = 0; k < bpp; k++) {
+        ofssrc = bytestream2_get_be32(&ptrs);
+        ofsdata = bytestream2_get_be32(&dptrs);
+
+        if (!ofssrc)
+            continue;
+
+        if (ofssrc >= buf_end - buf)
+            return;
+
+        if (ofsdata >= buf_end - buf)
+            return;
+
+        bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
+        bytestream2_init(&dgb, buf + ofsdata, buf_end - (buf + ofsdata));
+        for (j = 0; j < ncolumns; j++) {
+            ofsdst = (j + k * ncolumns) * 2;
+
+            i = bytestream2_get_byte(&gb);
+            while (i > 0) {
+                opcode = bytestream2_get_byte(&gb);
+
+                if (opcode == 0) {
+                    opcode = bytestream2_get_byte(&gb);
+                    x = bytestream2_get_be16(&dgb);
+
+                    while (opcode) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        bytestream2_put_be16(&pb, x);
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                } else if (opcode < 0x80) {
+                    ofsdst += opcode * dstpitch;
+                } else {
+                    opcode &= 0x7f;
+
+                    while (opcode) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        bytestream2_put_be16(&pb, bytestream2_get_be16(&dgb));
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                }
+                i--;
+            }
+        }
+    }
+}
+
+static void decode_long_vertical_delta(uint8_t *dst,
+                                       const uint8_t *buf, const uint8_t *buf_end,
+                                       int w, int bpp, int dst_size)
+{
+    int ncolumns = (w + 31) >> 5;
+    int dstpitch = ((w + 15) / 16 * 2) * bpp;
+    unsigned ofsdst, ofssrc, ofsdata, opcode, x;
+    GetByteContext ptrs, gb, dptrs, dgb;
+    PutByteContext pb;
+    int i, j, k, h;
+
+    if (buf_end - buf <= 64)
+        return;
+
+    h = (((w + 15) / 16 * 2) != ((w + 31) / 32 * 4)) ? 1 : 0;
+    bytestream2_init(&ptrs, buf, buf_end - buf);
+    bytestream2_init(&dptrs, buf + 32, (buf_end - buf) - 32);
+    bytestream2_init_writer(&pb, dst, dst_size);
+
+    for (k = 0; k < bpp; k++) {
+        ofssrc = bytestream2_get_be32(&ptrs);
+        ofsdata = bytestream2_get_be32(&dptrs);
+
+        if (!ofssrc)
+            continue;
+
+        if (ofssrc >= buf_end - buf)
+            return;
+
+        if (ofsdata >= buf_end - buf)
+            return;
+
+        bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
+        bytestream2_init(&dgb, buf + ofsdata, buf_end - (buf + ofsdata));
+        for (j = 0; j < ncolumns; j++) {
+            ofsdst = (j + k * ncolumns) * 4 - h * (2 * k);
+
+            i = bytestream2_get_byte(&gb);
+            while (i > 0) {
+                opcode = bytestream2_get_byte(&gb);
+
+                if (opcode == 0) {
+                    opcode = bytestream2_get_byte(&gb);
+                    if (h && (j == (ncolumns - 1))) {
+                        x = bytestream2_get_be16(&dgb);
+                        bytestream2_skip(&dgb, 2);
+                    } else {
+                        x = bytestream2_get_be32(&dgb);
+                    }
+
+                    while (opcode) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        if (h && (j == (ncolumns - 1))) {
+                            bytestream2_put_be16(&pb, x);
+                        } else {
+                            bytestream2_put_be32(&pb, x);
+                        }
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                } else if (opcode < 0x80) {
+                    ofsdst += opcode * dstpitch;
+                } else {
+                    opcode &= 0x7f;
+
+                    while (opcode) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        if (h && (j == (ncolumns - 1))) {
+                            bytestream2_put_be16(&pb, bytestream2_get_be16(&dgb));
+                            bytestream2_skip(&dgb, 2);
+                        } else {
+                            bytestream2_put_be32(&pb, bytestream2_get_be32(&dgb));
+                        }
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                }
+                i--;
+            }
+        }
+    }
+}
+
+static void decode_short_vertical_delta2(uint8_t *dst,
+                                         const uint8_t *buf, const uint8_t *buf_end,
+                                         int w, int bpp, int dst_size)
+{
+    int ncolumns = (w + 15) >> 4;
+    int dstpitch = ncolumns * bpp * 2;
+    unsigned ofsdst, ofssrc, opcode, x;
+    GetByteContext ptrs, gb;
+    PutByteContext pb;
+    int i, j, k;
+
+    bytestream2_init(&ptrs, buf, buf_end - buf);
+    bytestream2_init_writer(&pb, dst, dst_size);
+
+    for (k = 0; k < bpp; k++) {
+        ofssrc = bytestream2_get_be32(&ptrs);
+
+        if (!ofssrc)
+            continue;
+
+        if (ofssrc >= buf_end - buf)
+            continue;
+
+        bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
+        for (j = 0; j < ncolumns; j++) {
+            ofsdst = (j + k * ncolumns) * 2;
+
+            i = bytestream2_get_be16(&gb);
+            while (i > 0 && bytestream2_get_bytes_left(&gb) > 4) {
+                opcode = bytestream2_get_be16(&gb);
+
+                if (opcode == 0) {
+                    opcode = bytestream2_get_be16(&gb);
+                    x = bytestream2_get_be16(&gb);
+
+                    while (opcode && bytestream2_get_bytes_left_p(&pb) > 1) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        bytestream2_put_be16(&pb, x);
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                } else if (opcode < 0x8000) {
+                    ofsdst += opcode * dstpitch;
+                } else {
+                    opcode &= 0x7fff;
+
+                    while (opcode && bytestream2_get_bytes_left(&gb) > 1 &&
+                           bytestream2_get_bytes_left_p(&pb) > 1) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        bytestream2_put_be16(&pb, bytestream2_get_be16(&gb));
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                }
+                i--;
+            }
+        }
+    }
+}
+
+static void decode_long_vertical_delta2(uint8_t *dst,
+                                        const uint8_t *buf, const uint8_t *buf_end,
+                                        int w, int bpp, int dst_size)
+{
+    int ncolumns = (w + 31) >> 5;
+    int dstpitch = ((w + 15) / 16 * 2) * bpp;
+    unsigned ofsdst, ofssrc, opcode, x;
+    unsigned skip = 0x80000000, mask = skip - 1;
+    GetByteContext ptrs, gb;
+    PutByteContext pb;
+    int i, j, k, h;
+
+    h = (((w + 15) / 16 * 2) != ((w + 31) / 32 * 4)) ? 1 : 0;
+    bytestream2_init(&ptrs, buf, buf_end - buf);
+    bytestream2_init_writer(&pb, dst, dst_size);
+
+    for (k = 0; k < bpp; k++) {
+        ofssrc = bytestream2_get_be32(&ptrs);
+
+        if (!ofssrc)
+            continue;
+
+        if (ofssrc >= buf_end - buf)
+            continue;
+
+        bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
+        for (j = 0; j < ncolumns; j++) {
+            ofsdst = (j + k * ncolumns) * 4 - h * (2 * k);
+
+            if (h && (j == (ncolumns - 1))) {
+                skip = 0x8000;
+                mask = skip - 1;
+            }
+
+            i = bytestream2_get_be32(&gb);
+            while (i > 0 && bytestream2_get_bytes_left(&gb) > 4) {
+                opcode = bytestream2_get_be32(&gb);
+
+                if (opcode == 0) {
+                    if (h && (j == ncolumns - 1)) {
+                        opcode = bytestream2_get_be16(&gb);
+                        x = bytestream2_get_be16(&gb);
+                    } else {
+                        opcode = bytestream2_get_be32(&gb);
+                        x = bytestream2_get_be32(&gb);
+                    }
+
+                    while (opcode && bytestream2_get_bytes_left_p(&pb) > 1) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        if (h && (j == ncolumns - 1))
+                            bytestream2_put_be16(&pb, x);
+                        else
+                            bytestream2_put_be32(&pb, x);
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                } else if (opcode < skip) {
+                    ofsdst += opcode * dstpitch;
+                } else {
+                    opcode &= mask;
+
+                    while (opcode && bytestream2_get_bytes_left(&gb) > 1 &&
+                           bytestream2_get_bytes_left_p(&pb) > 1) {
+                        bytestream2_seek_p(&pb, ofsdst, SEEK_SET);
+                        if (h && (j == ncolumns - 1)) {
+                            bytestream2_put_be16(&pb, bytestream2_get_be16(&gb));
+                        } else {
+                            bytestream2_put_be32(&pb, bytestream2_get_be32(&gb));
+                        }
+                        ofsdst += dstpitch;
+                        opcode--;
+                    }
+                }
+                i--;
+            }
+        }
+    }
+}
+
+static void decode_delta_d(uint8_t *dst,
+                           const uint8_t *buf, const uint8_t *buf_end,
+                           int w, int flag, int bpp, int dst_size)
+{
+    int planepitch = FFALIGN(w, 16) >> 3;
+    int pitch = planepitch * bpp;
+    int planepitch_byte = (w + 7) / 8;
+    unsigned entries, ofssrc;
+    GetByteContext gb, ptrs;
+    PutByteContext pb;
+    int k;
+
+    if (buf_end - buf <= 4 * bpp)
+        return;
+
+    bytestream2_init_writer(&pb, dst, dst_size);
+    bytestream2_init(&ptrs, buf, bpp * 4);
+
+    for (k = 0; k < bpp; k++) {
+        ofssrc = bytestream2_get_be32(&ptrs);
+
+        if (!ofssrc)
+            continue;
+
+        if (ofssrc >= buf_end - buf)
+            continue;
+
+        bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
+
+        entries = bytestream2_get_be32(&gb);
+        while (entries && bytestream2_get_bytes_left(&gb) >= 8) {
+            int32_t opcode  = bytestream2_get_be32(&gb);
+            unsigned offset = bytestream2_get_be32(&gb);
+
+            bytestream2_seek_p(&pb, (offset / planepitch_byte) * pitch + (offset % planepitch_byte) + k * planepitch, SEEK_SET);
+            if (opcode >= 0) {
+                uint32_t x = bytestream2_get_be32(&gb);
+                while (opcode && bytestream2_get_bytes_left_p(&pb) > 0) {
+                    bytestream2_put_be32(&pb, x);
+                    bytestream2_skip_p(&pb, pitch - 4);
+                    opcode--;
+                }
+            } else {
+                opcode = -opcode;
+                while (opcode && bytestream2_get_bytes_left(&gb) > 0) {
+                    bytestream2_put_be32(&pb, bytestream2_get_be32(&gb));
+                    bytestream2_skip_p(&pb, pitch - 4);
+                    opcode--;
+                }
+            }
+            entries--;
+        }
+    }
+}
+
+static void decode_delta_e(uint8_t *dst,
+                           const uint8_t *buf, const uint8_t *buf_end,
+                           int w, int flag, int bpp, int dst_size)
+{
+    int planepitch = FFALIGN(w, 16) >> 3;
+    int pitch = planepitch * bpp;
+    int planepitch_byte = (w + 7) / 8;
+    unsigned entries, ofssrc;
+    GetByteContext gb, ptrs;
+    PutByteContext pb;
+    int k;
+
+    if (buf_end - buf <= 4 * bpp)
+        return;
+
+    bytestream2_init_writer(&pb, dst, dst_size);
+    bytestream2_init(&ptrs, buf, bpp * 4);
+
+    for (k = 0; k < bpp; k++) {
+        ofssrc = bytestream2_get_be32(&ptrs);
+
+        if (!ofssrc)
+            continue;
+
+        if (ofssrc >= buf_end - buf)
+            continue;
+
+        bytestream2_init(&gb, buf + ofssrc, buf_end - (buf + ofssrc));
+
+        entries = bytestream2_get_be16(&gb);
+        while (entries && bytestream2_get_bytes_left(&gb) >= 6) {
+            int16_t opcode  = bytestream2_get_be16(&gb);
+            unsigned offset = bytestream2_get_be32(&gb);
+
+            bytestream2_seek_p(&pb, (offset / planepitch_byte) * pitch + (offset % planepitch_byte) + k * planepitch, SEEK_SET);
+            if (opcode >= 0) {
+                uint16_t x = bytestream2_get_be16(&gb);
+                while (opcode && bytestream2_get_bytes_left_p(&pb) > 0) {
+                    bytestream2_put_be16(&pb, x);
+                    bytestream2_skip_p(&pb, pitch - 2);
+                    opcode--;
+                }
+            } else {
+                opcode = -opcode;
+                while (opcode && bytestream2_get_bytes_left(&gb) > 0) {
+                    bytestream2_put_be16(&pb, bytestream2_get_be16(&gb));
+                    bytestream2_skip_p(&pb, pitch - 2);
+                    opcode--;
+                }
+            }
+            entries--;
+        }
+    }
+}
+
+static void decode_delta_l(uint8_t *dst,
+                           const uint8_t *buf, const uint8_t *buf_end,
+                           int w, int flag, int bpp, int dst_size)
+{
+    GetByteContext off0, off1, dgb, ogb;
+    PutByteContext pb;
+    unsigned poff0, poff1;
+    int i, k, dstpitch;
+    int planepitch_byte = (w + 7) / 8;
+    int planepitch = ((w + 15) / 16) * 2;
+    int pitch = planepitch * bpp;
+
+    if (buf_end - buf <= 64)
+        return;
+
+    bytestream2_init(&off0, buf, buf_end - buf);
+    bytestream2_init(&off1, buf + 32, buf_end - (buf + 32));
+    bytestream2_init_writer(&pb, dst, dst_size);
+
+    dstpitch = flag ? (((w + 7) / 8) * bpp): 2;
+
+    for (k = 0; k < bpp; k++) {
+        poff0 = bytestream2_get_be32(&off0);
+        poff1 = bytestream2_get_be32(&off1);
+
+        if (!poff0)
+            continue;
+
+        if (2LL * poff0 >= buf_end - buf)
+            return;
+
+        if (2LL * poff1 >= buf_end - buf)
+            return;
+
+        bytestream2_init(&dgb, buf + 2 * poff0, buf_end - (buf + 2 * poff0));
+        bytestream2_init(&ogb, buf + 2 * poff1, buf_end - (buf + 2 * poff1));
+
+        while ((bytestream2_peek_be16(&ogb)) != 0xFFFF && bytestream2_get_bytes_left(&ogb) >= 4) {
+            uint32_t offset = bytestream2_get_be16(&ogb);
+            int16_t cnt = bytestream2_get_be16(&ogb);
+            uint16_t data;
+
+            offset = ((2 * offset) / planepitch_byte) * pitch + ((2 * offset) % planepitch_byte) + k * planepitch;
+            if (cnt < 0) {
+                bytestream2_seek_p(&pb, offset, SEEK_SET);
+                cnt = -cnt;
+                data = bytestream2_get_be16(&dgb);
+                for (i = 0; i < cnt; i++) {
+                    bytestream2_put_be16(&pb, data);
+                    bytestream2_skip_p(&pb, dstpitch - 2);
+                }
+            } else {
+                bytestream2_seek_p(&pb, offset, SEEK_SET);
+                for (i = 0; i < cnt; i++) {
+                    data = bytestream2_get_be16(&dgb);
+                    bytestream2_put_be16(&pb, data);
+                    bytestream2_skip_p(&pb, dstpitch - 2);
+                }
+            }
+        }
+    }
+}
+
 static int unsupported(AVCodecContext *avctx)
 {
     IffContext *s = avctx->priv_data;
-    avpriv_request_sample(avctx, "bitmap (compression %i, bpp %i, ham %i)", s->compression, s->bpp, s->ham);
+    avpriv_request_sample(avctx, "bitmap (compression 0x%0x, bpp %i, ham %i, interlaced %i)", s->compression, s->bpp, s->ham, s->is_interlaced);
     return AVERROR_INVALIDDATA;
 }
 
@@ -672,23 +1415,30 @@ static int decode_frame(AVCodecContext *avctx,
                         AVPacket *avpkt)
 {
     IffContext *s          = avctx->priv_data;
-    const uint8_t *buf     = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
-    const int buf_size     = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
+    AVFrame *frame         = data;
+    const uint8_t *buf     = avpkt->data;
+    int buf_size           = avpkt->size;
     const uint8_t *buf_end = buf + buf_size;
     int y, plane, res;
-    GetByteContext gb;
+    GetByteContext *gb = &s->gb;
     const AVPixFmtDescriptor *desc;
 
+    bytestream2_init(gb, avpkt->data, avpkt->size);
+
     if ((res = extract_header(avctx, avpkt)) < 0)
         return res;
-    if ((res = ff_reget_buffer(avctx, s->frame)) < 0)
+
+    if ((res = ff_get_buffer(avctx, frame, 0)) < 0)
         return res;
+    s->frame = frame;
 
+    buf      += bytestream2_tell(gb);
+    buf_size -= bytestream2_tell(gb);
     desc = av_pix_fmt_desc_get(avctx->pix_fmt);
 
     if (!s->init && avctx->bits_per_coded_sample <= 8 &&
         avctx->pix_fmt == AV_PIX_FMT_PAL8) {
-        if ((res = cmap_read_palette(avctx, (uint32_t *)s->frame->data[1])) < 0)
+        if ((res = cmap_read_palette(avctx, (uint32_t *)frame->data[1])) < 0)
             return res;
     } else if (!s->init && avctx->bits_per_coded_sample <= 8 &&
                avctx->pix_fmt == AV_PIX_FMT_RGB32) {
@@ -697,22 +1447,27 @@ static int decode_frame(AVCodecContext *avctx,
     }
     s->init = 1;
 
+    if (s->compression <= 0xff && (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M'))) {
+        if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
+            memcpy(s->pal[0], s->frame->data[1], 256 * 4);
+    }
+
     switch (s->compression) {
-    case 0:
+    case 0x0:
         if (avctx->codec_tag == MKTAG('A', 'C', 'B', 'M')) {
             if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
-                memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]);
+                memset(frame->data[0], 0, avctx->height * frame->linesize[0]);
                 for (plane = 0; plane < s->bpp; plane++) {
                     for (y = 0; y < avctx->height && buf < buf_end; y++) {
-                        uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                        uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                         decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
                         buf += s->planesize;
                     }
                 }
             } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
-                memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]);
+                memset(frame->data[0], 0, avctx->height * frame->linesize[0]);
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memset(s->ham_buf, 0, s->planesize * 8);
                     for (plane = 0; plane < s->bpp; plane++) {
                         const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
@@ -728,7 +1483,7 @@ static int decode_frame(AVCodecContext *avctx,
             int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3);
             int x;
             for (y = 0; y < avctx->height && buf < buf_end; y++) {
-                uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                 memcpy(row, buf, FFMIN(raw_width, buf_end - buf));
                 buf += raw_width;
                 if (avctx->pix_fmt == AV_PIX_FMT_BGR32) {
@@ -736,10 +1491,13 @@ static int decode_frame(AVCodecContext *avctx,
                         row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4);
                 }
             }
-        } else if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M')) { // interleaved
+        } else if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') || // interleaved
+                   avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
+            if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M'))
+                memcpy(s->video[0], buf, FFMIN(buf_end - buf, s->video_size));
             if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memset(row, 0, avctx->width);
                     for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
                         decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
@@ -748,7 +1506,7 @@ static int decode_frame(AVCodecContext *avctx,
                 }
             } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memset(s->ham_buf, 0, s->planesize * 8);
                     for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
                         decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
@@ -758,7 +1516,7 @@ static int decode_frame(AVCodecContext *avctx,
                 }
             } else { // AV_PIX_FMT_BGR32
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memset(row, 0, avctx->width << 2);
                     for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
                         decodeplane32((uint32_t *)row, buf,
@@ -770,13 +1528,13 @@ static int decode_frame(AVCodecContext *avctx,
         } else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM
             if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
                 for (y = 0; y < avctx->height && buf_end > buf; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
                     buf += avctx->width + (avctx->width % 2); // padding if odd
                 }
             } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
                 for (y = 0; y < avctx->height && buf_end > buf; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
                     buf += avctx->width + (avctx->width & 1); // padding if odd
                     decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
@@ -785,43 +1543,55 @@ static int decode_frame(AVCodecContext *avctx,
                 return unsupported(avctx);
         }
         break;
-    case 1:
-        if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M')) { // interleaved
+    case 0x1:
+        if (avctx->codec_tag == MKTAG('I', 'L', 'B', 'M') || // interleaved
+            avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
             if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
+                uint8_t *video = s->video[0];
+
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memset(row, 0, avctx->width);
                     for (plane = 0; plane < s->bpp; plane++) {
-                        buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
+                        buf += decode_byterun(s->planebuf, s->planesize, gb);
+                        if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
+                            memcpy(video, s->planebuf, s->planesize);
+                            video += s->planesize;
+                        }
                         decodeplane8(row, s->planebuf, s->planesize, plane);
                     }
                 }
             } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
                     for (plane = 0; plane < s->bpp; plane++) {
-                        buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
+                        buf += decode_byterun(s->planebuf, s->planesize, gb);
                         decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
                     }
                     lookup_pal_indicies((uint32_t *)row, s->mask_buf, s->mask_palbuf, avctx->width);
                 }
             } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
+                uint8_t *video = s->video[0];
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memset(s->ham_buf, 0, s->planesize * 8);
                     for (plane = 0; plane < s->bpp; plane++) {
-                        buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
+                        buf += decode_byterun(s->planebuf, s->planesize, gb);
+                        if (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M')) {
+                            memcpy(video, s->planebuf, s->planesize);
+                            video += s->planesize;
+                        }
                         decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
                     }
                     decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
                 }
             } else { // AV_PIX_FMT_BGR32
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
                     memset(row, 0, avctx->width << 2);
                     for (plane = 0; plane < s->bpp; plane++) {
-                        buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
+                        buf += decode_byterun(s->planebuf, s->planesize, gb);
                         decodeplane32((uint32_t *)row, s->planebuf, s->planesize, plane);
                     }
                 }
@@ -829,48 +1599,152 @@ static int decode_frame(AVCodecContext *avctx,
         } else if (avctx->codec_tag == MKTAG('P', 'B', 'M', ' ')) { // IFF-PBM
             if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
-                    buf += decode_byterun(row, avctx->width, buf, buf_end);
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
+                    buf += decode_byterun(row, avctx->width, gb);
                 }
             } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
                 for (y = 0; y < avctx->height; y++) {
-                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
-                    buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
+                    uint8_t *row = &frame->data[0][y * frame->linesize[0]];
+                    buf += decode_byterun(s->ham_buf, avctx->width, gb);
                     decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
                 }
             } else
                 return unsupported(avctx);
         } else if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) { // IFF-DEEP
             if (av_get_bits_per_pixel(desc) == 32)
-                decode_deep_rle32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0]);
+                decode_deep_rle32(frame->data[0], buf, buf_size, avctx->width, avctx->height, frame->linesize[0]);
             else
                 return unsupported(avctx);
         }
         break;
-    case 4:
-        bytestream2_init(&gb, buf, buf_size);
+    case 0x4:
         if (avctx->codec_tag == MKTAG('R', 'G', 'B', '8') && avctx->pix_fmt == AV_PIX_FMT_RGB32)
-            decode_rgb8(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]);
+            decode_rgb8(gb, frame->data[0], avctx->width, avctx->height, frame->linesize[0]);
         else if (avctx->codec_tag == MKTAG('R', 'G', 'B', 'N') && avctx->pix_fmt == AV_PIX_FMT_RGB444)
-            decode_rgbn(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]);
+            decode_rgbn(gb, frame->data[0], avctx->width, avctx->height, frame->linesize[0]);
         else
             return unsupported(avctx);
         break;
-    case 5:
+    case 0x5:
         if (avctx->codec_tag == MKTAG('D', 'E', 'E', 'P')) {
             if (av_get_bits_per_pixel(desc) == 32)
-                decode_deep_tvdc32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0], s->tvdc);
+                decode_deep_tvdc32(frame->data[0], buf, buf_size, avctx->width, avctx->height, frame->linesize[0], s->tvdc);
             else
                 return unsupported(avctx);
         } else
             return unsupported(avctx);
         break;
+    case 0x300:
+    case 0x301:
+        decode_short_horizontal_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
+        break;
+    case 0x500:
+    case 0x501:
+        decode_byte_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->is_brush, s->bpp, s->video_size);
+        break;
+    case 0x700:
+    case 0x701:
+        if (s->is_short)
+            decode_short_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
+        else
+            decode_long_vertical_delta(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
+        break;
+    case 0x800:
+    case 0x801:
+        if (s->is_short)
+            decode_short_vertical_delta2(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
+        else
+            decode_long_vertical_delta2(s->video[0], buf, buf_end, avctx->width, s->bpp, s->video_size);
+        break;
+    case 0x4a00:
+    case 0x4a01:
+        decode_delta_j(s->video[0], buf, buf_end, avctx->width, avctx->height, s->bpp, s->video_size);
+        break;
+    case 0x6400:
+    case 0x6401:
+        if (s->is_interlaced)
+            return unsupported(avctx);
+        decode_delta_d(s->video[0], buf, buf_end, avctx->width, s->is_interlaced, s->bpp, s->video_size);
+        break;
+    case 0x6500:
+    case 0x6501:
+        if (s->is_interlaced)
+            return unsupported(avctx);
+        decode_delta_e(s->video[0], buf, buf_end, avctx->width, s->is_interlaced, s->bpp, s->video_size);
+        break;
+    case 0x6c00:
+    case 0x6c01:
+        decode_delta_l(s->video[0], buf, buf_end, avctx->width, s->is_short, s->bpp, s->video_size);
+        break;
     default:
         return unsupported(avctx);
     }
 
-    if ((res = av_frame_ref(data, s->frame)) < 0)
-        return res;
+    if (s->compression <= 0xff && (avctx->codec_tag == MKTAG('A', 'N', 'I', 'M'))) {
+        memcpy(s->pal[1], s->pal[0], 256 * 4);
+        memcpy(s->video[1], s->video[0], s->video_size);
+    }
+
+    if (s->compression > 0xff) {
+        if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
+            buf = s->video[0];
+            for (y = 0; y < avctx->height; y++) {
+                uint8_t *row = &frame->data[0][y * frame->linesize[0]];
+                memset(row, 0, avctx->width);
+                for (plane = 0; plane < s->bpp; plane++) {
+                    decodeplane8(row, buf, s->planesize, plane);
+                    buf += s->planesize;
+                }
+            }
+            memcpy(frame->data[1], s->pal[0], 256 * 4);
+        } else if (s->ham) {
+            int i, count = 1 << s->ham;
+
+            buf = s->video[0];
+            memset(s->ham_palbuf, 0, (1 << s->ham) * 2 * sizeof(uint32_t));
+            for (i = 0; i < count; i++) {
+                s->ham_palbuf[i*2+1] = s->pal[0][i];
+            }
+            for (i = 0; i < count; i++) {
+                uint32_t tmp = i << (8 - s->ham);
+                tmp |= tmp >> s->ham;
+                s->ham_palbuf[(i+count)*2]     = 0xFF00FFFF;
+                s->ham_palbuf[(i+count*2)*2]   = 0xFFFFFF00;
+                s->ham_palbuf[(i+count*3)*2]   = 0xFFFF00FF;
+                s->ham_palbuf[(i+count)*2+1]   = 0xFF000000 | tmp << 16;
+                s->ham_palbuf[(i+count*2)*2+1] = 0xFF000000 | tmp;
+                s->ham_palbuf[(i+count*3)*2+1] = 0xFF000000 | tmp << 8;
+            }
+            if (s->masking == MASK_HAS_MASK) {
+                for (i = 0; i < 8 * (1 << s->ham); i++)
+                    s->ham_palbuf[(1 << s->bpp) + i] = s->ham_palbuf[i] | 0xFF000000;
+            }
+            for (y = 0; y < avctx->height; y++) {
+                uint8_t *row = &frame->data[0][y * frame->linesize[0]];
+                memset(s->ham_buf, 0, s->planesize * 8);
+                for (plane = 0; plane < s->bpp; plane++) {
+                    decodeplane8(s->ham_buf, buf, s->planesize, plane);
+                    buf += s->planesize;
+                }
+                decode_ham_plane32((uint32_t *)row, s->ham_buf, s->ham_palbuf, s->planesize);
+            }
+        } else {
+            return unsupported(avctx);
+        }
+
+        if (!s->is_brush) {
+            FFSWAP(uint8_t *, s->video[0], s->video[1]);
+            FFSWAP(uint32_t *, s->pal[0], s->pal[1]);
+        }
+    }
+
+    if (avpkt->flags & AV_PKT_FLAG_KEY) {
+        frame->key_frame = 1;
+        frame->pict_type = AV_PICTURE_TYPE_I;
+    } else {
+        frame->key_frame = 0;
+        frame->pict_type = AV_PICTURE_TYPE_P;
+    }
 
     *got_frame = 1;
 
@@ -880,7 +1754,7 @@ static int decode_frame(AVCodecContext *avctx,
 #if CONFIG_IFF_ILBM_DECODER
 AVCodec ff_iff_ilbm_decoder = {
     .name           = "iff",
-    .long_name      = NULL_IF_CONFIG_SMALL("IFF"),
+    .long_name      = NULL_IF_CONFIG_SMALL("IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_IFF_ILBM,
     .priv_data_size = sizeof(IffContext),
diff --git a/libavcodec/iirfilter.c b/libavcodec/iirfilter.c
index cb5871c..a8c9b9b 100644
--- a/libavcodec/iirfilter.c
+++ b/libavcodec/iirfilter.c
@@ -24,27 +24,29 @@
  * different IIR filters implementation
  */
 
-#include "iirfilter.h"
 #include <math.h>
+
 #include "libavutil/attributes.h"
 #include "libavutil/common.h"
 
+#include "iirfilter.h"
+
 /**
  * IIR filter global parameters
  */
-typedef struct FFIIRFilterCoeffs{
+typedef struct FFIIRFilterCoeffs {
     int   order;
     float gain;
     int   *cx;
     float *cy;
-}FFIIRFilterCoeffs;
+} FFIIRFilterCoeffs;
 
 /**
  * IIR filter state
  */
-typedef struct FFIIRFilterState{
+typedef struct FFIIRFilterState {
     float x[1];
-}FFIIRFilterState;
+} FFIIRFilterState;
 
 /// maximum supported filter order
 #define MAXORDER 30
@@ -61,51 +63,50 @@ static av_cold int butterworth_init_coeffs(void *avc,
 
     if (filt_mode != FF_FILTER_MODE_LOWPASS) {
         av_log(avc, AV_LOG_ERROR, "Butterworth filter currently only supports "
-               "low-pass filter mode\n");
+                                  "low-pass filter mode\n");
         return -1;
     }
     if (order & 1) {
         av_log(avc, AV_LOG_ERROR, "Butterworth filter currently only supports "
-               "even filter orders\n");
+                                  "even filter orders\n");
         return -1;
     }
 
     wa = 2 * tan(M_PI * 0.5 * cutoff_ratio);
 
     c->cx[0] = 1;
-    for(i = 1; i < (order >> 1) + 1; i++)
+    for (i = 1; i < (order >> 1) + 1; i++)
         c->cx[i] = c->cx[i - 1] * (order - i + 1LL) / i;
 
     p[0][0] = 1.0;
     p[0][1] = 0.0;
-    for(i = 1; i <= order; i++)
+    for (i = 1; i <= order; i++)
         p[i][0] = p[i][1] = 0.0;
-    for(i = 0; i < order; i++){
+    for (i = 0; i < order; i++) {
         double zp[2];
         double th = (i + (order >> 1) + 0.5) * M_PI / order;
         double a_re, a_im, c_re, c_im;
         zp[0] = cos(th) * wa;
         zp[1] = sin(th) * wa;
-        a_re = zp[0] + 2.0;
-        c_re = zp[0] - 2.0;
-        a_im =
-        c_im = zp[1];
+        a_re  = zp[0] + 2.0;
+        c_re  = zp[0] - 2.0;
+        a_im  =
+        c_im  = zp[1];
         zp[0] = (a_re * c_re + a_im * c_im) / (c_re * c_re + c_im * c_im);
         zp[1] = (a_im * c_re - a_re * c_im) / (c_re * c_re + c_im * c_im);
 
-        for(j = order; j >= 1; j--)
-        {
-            a_re = p[j][0];
-            a_im = p[j][1];
-            p[j][0] = a_re*zp[0] - a_im*zp[1] + p[j-1][0];
-            p[j][1] = a_re*zp[1] + a_im*zp[0] + p[j-1][1];
+        for (j = order; j >= 1; j--) {
+            a_re    = p[j][0];
+            a_im    = p[j][1];
+            p[j][0] = a_re * zp[0] - a_im * zp[1] + p[j - 1][0];
+            p[j][1] = a_re * zp[1] + a_im * zp[0] + p[j - 1][1];
         }
-        a_re    = p[0][0]*zp[0] - p[0][1]*zp[1];
-        p[0][1] = p[0][0]*zp[1] + p[0][1]*zp[0];
+        a_re    = p[0][0] * zp[0] - p[0][1] * zp[1];
+        p[0][1] = p[0][0] * zp[1] + p[0][1] * zp[0];
         p[0][0] = a_re;
     }
     c->gain = p[order][0];
-    for(i = 0; i < order; i++){
+    for (i = 0; i < order; i++) {
         c->gain += p[i][0];
         c->cy[i] = (-p[i][0] * p[order][0] + -p[i][1] * p[order][1]) /
                    (p[order][0] * p[order][0] + p[order][1] * p[order][1]);
@@ -125,7 +126,7 @@ static av_cold int biquad_init_coeffs(void *avc, struct FFIIRFilterCoeffs *c,
     if (filt_mode != FF_FILTER_MODE_HIGHPASS &&
         filt_mode != FF_FILTER_MODE_LOWPASS) {
         av_log(avc, AV_LOG_ERROR, "Biquad filter currently only supports "
-               "high-pass and low-pass filter modes\n");
+                                  "high-pass and low-pass filter modes\n");
         return -1;
     }
     if (order != 2) {
@@ -158,11 +159,11 @@ static av_cold int biquad_init_coeffs(void *avc, struct FFIIRFilterCoeffs *c,
     return 0;
 }
 
-av_cold struct FFIIRFilterCoeffs* ff_iir_filter_init_coeffs(void *avc,
-                                                enum IIRFilterType filt_type,
-                                                enum IIRFilterMode filt_mode,
-                                                int order, float cutoff_ratio,
-                                                float stopband, float ripple)
+av_cold struct FFIIRFilterCoeffs *ff_iir_filter_init_coeffs(void *avc,
+                                                            enum IIRFilterType filt_type,
+                                                            enum IIRFilterMode filt_mode,
+                                                            int order, float cutoff_ratio,
+                                                            float stopband, float ripple)
 {
     FFIIRFilterCoeffs *c;
     int ret = 0;
@@ -170,12 +171,12 @@ av_cold struct FFIIRFilterCoeffs* ff_iir_filter_init_coeffs(void *avc,
     if (order <= 0 || order > MAXORDER || cutoff_ratio >= 1.0)
         return NULL;
 
-    FF_ALLOCZ_OR_GOTO(avc, c,     sizeof(FFIIRFilterCoeffs),
-                      init_fail);
-    FF_ALLOC_OR_GOTO (avc, c->cx, sizeof(c->cx[0]) * ((order >> 1) + 1),
-                      init_fail);
-    FF_ALLOC_OR_GOTO (avc, c->cy, sizeof(c->cy[0]) * order,
+    FF_ALLOCZ_OR_GOTO(avc, c, sizeof(FFIIRFilterCoeffs),
                       init_fail);
+    FF_ALLOC_OR_GOTO(avc, c->cx, sizeof(c->cx[0]) * ((order >> 1) + 1),
+                     init_fail);
+    FF_ALLOC_OR_GOTO(avc, c->cy, sizeof(c->cy[0]) * order,
+                     init_fail);
     c->order = order;
 
     switch (filt_type) {
@@ -200,9 +201,9 @@ init_fail:
     return NULL;
 }
 
-av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order)
+av_cold struct FFIIRFilterState *ff_iir_filter_init_state(int order)
 {
-    FFIIRFilterState* s = av_mallocz(sizeof(FFIIRFilterState) + sizeof(s->x[0]) * (order - 1));
+    FFIIRFilterState *s = av_mallocz(sizeof(FFIIRFilterState) + sizeof(s->x[0]) * (order - 1));
     return s;
 }
 
@@ -210,17 +211,19 @@ av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order)
 
 #define CONV_FLT(dest, source) dest = source;
 
-#define FILTER_BW_O4_1(i0, i1, i2, i3, fmt)         \
-    in = *src0 * c->gain                            \
-         + c->cy[0]*s->x[i0] + c->cy[1]*s->x[i1]    \
-         + c->cy[2]*s->x[i2] + c->cy[3]*s->x[i3];   \
-    res =  (s->x[i0] + in      )*1                  \
-         + (s->x[i1] + s->x[i3])*4                  \
-         +  s->x[i2]            *6;                 \
-    CONV_##fmt(*dst0, res)                          \
-    s->x[i0] = in;                                  \
-    src0 += sstep;                                  \
-    dst0 += dstep;
+#define FILTER_BW_O4_1(i0, i1, i2, i3, fmt)             \
+    in = *src0    * c->gain  +                          \
+         c->cy[0] * s->x[i0] +                          \
+         c->cy[1] * s->x[i1] +                          \
+         c->cy[2] * s->x[i2] +                          \
+         c->cy[3] * s->x[i3];                           \
+    res = (s->x[i0] + in)       * 1 +                   \
+          (s->x[i1] + s->x[i3]) * 4 +                   \
+           s->x[i2]             * 6;                    \
+    CONV_ ## fmt(*dst0, res)                            \
+    s->x[i0] = in;                                      \
+    src0    += sstep;                                   \
+    dst0    += dstep;
 
 #define FILTER_BW_O4(type, fmt) {           \
     int i;                                  \
@@ -243,17 +246,17 @@ av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order)
         int j;                                                              \
         float in, res;                                                      \
         in = *src0 * c->gain;                                               \
-        for(j = 0; j < c->order; j++)                                       \
+        for (j = 0; j < c->order; j++)                                      \
             in += c->cy[j] * s->x[j];                                       \
         res = s->x[0] + in + s->x[c->order >> 1] * c->cx[c->order >> 1];    \
-        for(j = 1; j < c->order >> 1; j++)                                  \
+        for (j = 1; j < c->order >> 1; j++)                                 \
             res += (s->x[j] + s->x[c->order - j]) * c->cx[j];               \
-        for(j = 0; j < c->order - 1; j++)                                   \
+        for (j = 0; j < c->order - 1; j++)                                  \
             s->x[j] = s->x[j + 1];                                          \
-        CONV_##fmt(*dst0, res)                                              \
+        CONV_ ## fmt(*dst0, res)                                            \
         s->x[c->order - 1] = in;                                            \
-        src0 += sstep;                                                      \
-        dst0 += dstep;                                                      \
+        src0              += sstep;                                         \
+        dst0              += dstep;                                         \
     }                                                                       \
 }
 
@@ -265,11 +268,11 @@ av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order)
         float in = *src0   * c->gain  +                                     \
                    s->x[0] * c->cy[0] +                                     \
                    s->x[1] * c->cy[1];                                      \
-        CONV_##fmt(*dst0, s->x[0] + in + s->x[1] * c->cx[1])                \
+        CONV_ ## fmt(*dst0, s->x[0] + in + s->x[1] * c->cx[1])              \
         s->x[0] = s->x[1];                                                  \
         s->x[1] = in;                                                       \
-        src0 += sstep;                                                      \
-        dst0 += dstep;                                                      \
+        src0   += sstep;                                                    \
+        dst0   += dstep;                                                    \
     }                                                                       \
 }
 
@@ -307,7 +310,7 @@ av_cold void ff_iir_filter_free_statep(struct FFIIRFilterState **state)
 av_cold void ff_iir_filter_free_coeffsp(struct FFIIRFilterCoeffs **coeffsp)
 {
     struct FFIIRFilterCoeffs *coeffs = *coeffsp;
-    if(coeffs){
+    if (coeffs) {
         av_freep(&coeffs->cx);
         av_freep(&coeffs->cy);
     }
@@ -320,36 +323,3 @@ void ff_iir_filter_init(FFIIRFilterContext *f) {
     if (HAVE_MIPSFPU)
         ff_iir_filter_init_mips(f);
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-#define FILT_ORDER 4
-#define SIZE 1024
-int main(void)
-{
-    struct FFIIRFilterCoeffs *fcoeffs = NULL;
-    struct FFIIRFilterState  *fstate  = NULL;
-    float cutoff_coeff = 0.4;
-    int16_t x[SIZE], y[SIZE];
-    int i;
-
-    fcoeffs = ff_iir_filter_init_coeffs(NULL, FF_FILTER_TYPE_BUTTERWORTH,
-                                        FF_FILTER_MODE_LOWPASS, FILT_ORDER,
-                                        cutoff_coeff, 0.0, 0.0);
-    fstate  = ff_iir_filter_init_state(FILT_ORDER);
-
-    for (i = 0; i < SIZE; i++) {
-        x[i] = lrint(0.75 * INT16_MAX * sin(0.5*M_PI*i*i/SIZE));
-    }
-
-    ff_iir_filter(fcoeffs, fstate, SIZE, x, 1, y, 1);
-
-    for (i = 0; i < SIZE; i++)
-        printf("%6d %6d\n", x[i], y[i]);
-
-    ff_iir_filter_free_coeffsp(&fcoeffs);
-    ff_iir_filter_free_statep(&fstate);
-    return 0;
-}
-#endif /* TEST */
diff --git a/libavcodec/imc.c b/libavcodec/imc.c
index f7eff63..ac20920 100644
--- a/libavcodec/imc.c
+++ b/libavcodec/imc.c
@@ -27,7 +27,6 @@
  *  A mdct based codec using a 256 points large transform
  *  divided into 32 bands with some mix of scale factors.
  *  Only mono is supported.
- *
  */
 
 
@@ -36,9 +35,9 @@
 #include <stdio.h>
 
 #include "libavutil/channel_layout.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/float_dsp.h"
 #include "libavutil/internal.h"
-#include "libavutil/libm.h"
 #include "avcodec.h"
 #include "bswapdsp.h"
 #include "get_bits.h"
@@ -71,7 +70,7 @@ typedef struct IMCChannel {
     int sumLenArr[BANDS];      ///< bits for all coeffs in band
     int skipFlagRaw[BANDS];    ///< skip flags are stored in raw form or not
     int skipFlagBits[BANDS];   ///< bits used to code skip flags
-    int skipFlagCount[BANDS];  ///< skipped coeffients per band
+    int skipFlagCount[BANDS];  ///< skipped coefficients per band
     int skipFlags[COEFFS];     ///< skip coefficient decoding or not
     int codewords[COEFFS];     ///< raw codewords read from bitstream
 
diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c
index 0035dc6..46fa780 100644
--- a/libavcodec/imgconvert.c
+++ b/libavcodec/imgconvert.c
@@ -231,33 +231,5 @@ int av_picture_pad(AVPicture *dst, const AVPicture *src, int height, int width,
 
     return 0;
 }
-
-#ifdef TEST
-
-int main(void){
-    int i;
-    int err=0;
-    int skip = 0;
-
-    for (i=0; i<AV_PIX_FMT_NB*2; i++) {
-        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i);
-        if(!desc || !desc->name) {
-            skip ++;
-            continue;
-        }
-        if (skip) {
-            av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip);
-            skip = 0;
-        }
-        av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc));
-        if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) {
-            av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n");
-            err = 1;
-        }
-    }
-    return err;
-}
-
-#endif
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif /* FF_API_AVPICTURE */
diff --git a/libavcodec/imx_dump_header_bsf.c b/libavcodec/imx_dump_header_bsf.c
index 3a69e98..9a9de05 100644
--- a/libavcodec/imx_dump_header_bsf.c
+++ b/libavcodec/imx_dump_header_bsf.c
@@ -26,35 +26,51 @@
  */
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "bytestream.h"
 
 
-static int imx_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                           uint8_t **poutbuf, int *poutbuf_size,
-                           const uint8_t *buf, int buf_size, int keyframe)
+static int imx_dump_header(AVBSFContext *ctx, AVPacket *out)
 {
     /* MXF essence element key */
     static const uint8_t imx_header[16] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x05,0x01,0x01,0x00 };
-    uint8_t *poutbufp;
-
-    if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO) {
-        av_log(avctx, AV_LOG_ERROR, "imx bitstream filter only applies to mpeg2video codec\n");
-        return 0;
-    }
-
-    *poutbuf = av_malloc(buf_size + 20 + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
-    poutbufp = *poutbuf;
-    bytestream_put_buffer(&poutbufp, imx_header, 16);
-    bytestream_put_byte(&poutbufp, 0x83); /* KLV BER long form */
-    bytestream_put_be24(&poutbufp, buf_size);
-    bytestream_put_buffer(&poutbufp, buf, buf_size);
-    *poutbuf_size = poutbufp - *poutbuf;
-    return 1;
+
+    AVPacket *in;
+    int ret = 0;
+    uint8_t *out_buf;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    ret = av_new_packet(out, in->size + 20);
+    if (ret < 0)
+        goto fail;
+
+    out_buf = out->data;
+
+    bytestream_put_buffer(&out_buf, imx_header, 16);
+    bytestream_put_byte(&out_buf, 0x83); /* KLV BER long form */
+    bytestream_put_be24(&out_buf, in->size);
+    bytestream_put_buffer(&out_buf, in->data, in->size);
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_imx_dump_header_bsf = {
-    .name   = "imxdump",
-    .filter = imx_dump_header,
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_imx_dump_header_bsf = {
+    .name      = "imxdump",
+    .filter    = imx_dump_header,
+    .codec_ids = codec_ids,
 };
diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c
index 3f31946..e161f83 100644
--- a/libavcodec/indeo3.c
+++ b/libavcodec/indeo3.c
@@ -53,7 +53,7 @@ enum {
 
 
 /* Some constants for parsing frame bitstream flags. */
-#define BS_8BIT_PEL     (1 << 1) ///< 8bit pixel bitdepth indicator
+#define BS_8BIT_PEL     (1 << 1) ///< 8-bit pixel bitdepth indicator
 #define BS_KEYFRAME     (1 << 2) ///< intra frame indicator
 #define BS_MV_Y_HALF    (1 << 4) ///< vertical mv halfpel resolution indicator
 #define BS_MV_X_HALF    (1 << 5) ///< horizontal mv halfpel resolution indicator
@@ -317,7 +317,7 @@ static inline uint32_t replicate32(uint32_t a) {
 }
 
 
-/* Fill n lines with 64bit pixel value pix */
+/* Fill n lines with 64-bit pixel value pix */
 static inline void fill_64(uint8_t *dst, const uint64_t pix, int32_t n,
                            int32_t row_offset)
 {
diff --git a/libavcodec/indeo3data.h b/libavcodec/indeo3data.h
index fe8f0ba..fbe76af 100644
--- a/libavcodec/indeo3data.h
+++ b/libavcodec/indeo3data.h
@@ -234,7 +234,7 @@
 
 
 /**
- * Pack two delta values (a,b) into one 16bit word
+ * Pack two delta values (a,b) into one 16-bit word
  * according with endianness of the host machine.
  */
 #if HAVE_BIGENDIAN
@@ -281,7 +281,7 @@ static const int16_t delta_tab_3_5[79]  = { TAB_3_5 };
 #undef PD
 
 /**
- * Pack four delta values (a,a,b,b) into one 32bit word
+ * Pack four delta values (a,a,b,b) into one 32-bit word
  * according with endianness of the host machine.
  */
 #if HAVE_BIGENDIAN
diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c
index 0065b52..69f78c9 100644
--- a/libavcodec/indeo4.c
+++ b/libavcodec/indeo4.c
@@ -119,17 +119,10 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx)
         return AVERROR_INVALIDDATA;
     }
 
-#if IVI4_STREAM_ANALYSER
     if (ctx->frame_type == IVI4_FRAMETYPE_BIDIR)
         ctx->has_b_frames = 1;
-#endif
 
-    ctx->transp_status = get_bits1(&ctx->gb);
-#if IVI4_STREAM_ANALYSER
-    if (ctx->transp_status) {
-        ctx->has_transp = 1;
-    }
-#endif
+    ctx->has_transp = get_bits1(&ctx->gb);
 
     /* unknown bit: Mac decoder ignores this bit, XANIM returns error */
     if (get_bits1(&ctx->gb)) {
@@ -163,12 +156,10 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx)
     }
 
     /* Decode tile dimensions. */
-    if (get_bits1(&ctx->gb)) {
+    ctx->uses_tiling = get_bits1(&ctx->gb);
+    if (ctx->uses_tiling) {
         pic_conf.tile_height = scale_tile_size(pic_conf.pic_height, get_bits(&ctx->gb, 4));
         pic_conf.tile_width  = scale_tile_size(pic_conf.pic_width,  get_bits(&ctx->gb, 4));
-#if IVI4_STREAM_ANALYSER
-        ctx->uses_tiling = 1;
-#endif
     } else {
         pic_conf.tile_height = pic_conf.pic_height;
         pic_conf.tile_width  = pic_conf.pic_width;
@@ -295,10 +286,8 @@ static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band,
                    band->is_halfpel);
             return AVERROR_INVALIDDATA;
         }
-#if IVI4_STREAM_ANALYSER
         if (!band->is_halfpel)
             ctx->uses_fullpel = 1;
-#endif
 
         band->checksum_present = get_bits1(&ctx->gb);
         if (band->checksum_present)
@@ -334,10 +323,8 @@ static int decode_band_hdr(IVI45DecContext *ctx, IVIBandDesc *band,
                 av_log(avctx, AV_LOG_ERROR, "wrong transform size!\n");
                 return AVERROR_INVALIDDATA;
             }
-#if IVI4_STREAM_ANALYSER
             if ((transform_id >= 0 && transform_id <= 2) || transform_id == 10)
                 ctx->uses_haar = 1;
-#endif
 
             band->inv_transform = transforms[transform_id].inv_trans;
             band->dc_transform  = transforms[transform_id].dc_trans;
@@ -683,6 +670,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
     ctx->is_nonnull_frame = is_nonnull_frame;
 
     ctx->is_indeo4 = 1;
+    ctx->show_indeo4_info = 1;
 
     ctx->dst_buf   = 0;
     ctx->ref_buf   = 1;
diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c
index fe8d185..ebf42c6 100644
--- a/libavcodec/intelh263dec.c
+++ b/libavcodec/intelh263dec.c
@@ -39,12 +39,12 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s)
     }
     s->picture_number = get_bits(&s->gb, 8); /* picture timestamp */
 
-    if (check_marker(&s->gb, "after picture_number") != 1) {
+    if (check_marker(s->avctx, &s->gb, "after picture_number") != 1) {
         return -1;      /* marker */
     }
     if (get_bits1(&s->gb) != 0) {
-        av_log(s->avctx, AV_LOG_ERROR, "Bad H263 id\n");
-        return -1;      /* h263 id */
+        av_log(s->avctx, AV_LOG_ERROR, "Bad H.263 id\n");
+        return -1;      /* H.263 id */
     }
     skip_bits1(&s->gb);         /* split screen off */
     skip_bits1(&s->gb);         /* camera  off */
@@ -52,7 +52,7 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s)
 
     format = get_bits(&s->gb, 3);
     if (format == 0 || format == 6) {
-        av_log(s->avctx, AV_LOG_ERROR, "Intel H263 free format not supported\n");
+        av_log(s->avctx, AV_LOG_ERROR, "Intel H.263 free format not supported\n");
         return -1;
     }
     s->h263_plus = 0;
@@ -77,7 +77,7 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s)
     } else {
         format = get_bits(&s->gb, 3);
         if(format == 0 || format == 7){
-            av_log(s->avctx, AV_LOG_ERROR, "Wrong Intel H263 format\n");
+            av_log(s->avctx, AV_LOG_ERROR, "Wrong Intel H.263 format\n");
             return -1;
         }
         if(get_bits(&s->gb, 2))
@@ -95,7 +95,7 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s)
     if(format == 6){
         int ar = get_bits(&s->gb, 4);
         skip_bits(&s->gb, 9); // display width
-        check_marker(&s->gb, "in dimensions");
+        check_marker(s->avctx, &s->gb, "in dimensions");
         skip_bits(&s->gb, 9); // display height
         if(ar == 15){
             s->avctx->sample_aspect_ratio.num = get_bits(&s->gb, 8); // aspect ratio - width
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 24d320c..000fe26 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -160,6 +160,19 @@ typedef struct AVCodecInternal {
      * hwaccel-specific private data
      */
     void *hwaccel_priv_data;
+
+    /**
+     * checks API usage: after codec draining, flush is required to resume operation
+     */
+    int draining;
+
+    /**
+     * buffers for using new encode/decode API through legacy API
+     */
+    AVPacket *buffer_pkt;
+    int buffer_pkt_valid; // encoding: packet without data can be valid
+    AVFrame *buffer_frame;
+    int draining_done;
 } AVCodecInternal;
 
 struct AVCodecDefault {
@@ -293,6 +306,8 @@ const uint8_t *avpriv_find_start_code(const uint8_t *p,
                                       const uint8_t *end,
                                       uint32_t *state);
 
+int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec);
+
 /**
  * Check that the provided frame dimensions are valid and set them on the codec
  * context.
@@ -330,4 +345,19 @@ AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx);
 
 int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type);
 
+/**
+ * Check AVFrame for A53 side data and allocate and fill SEI message with A53 info
+ *
+ * @param frame      Raw frame to get A53 side data from
+ * @param prefix_len Number of bytes to allocate before SEI message
+ * @param data       Pointer to a variable to store allocated memory
+ *                   Upon return the variable will hold NULL on error or if frame has no A53 info.
+ *                   Otherwise it will point to prefix_len uninitialized bytes followed by
+ *                   *sei_size SEI message
+ * @param sei_size   Pointer to a variable to store generated SEI message length
+ * @return           Zero on success, negative error code on failure
+ */
+int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len,
+                     void **data, size_t *sei_size);
+
 #endif /* AVCODEC_INTERNAL_H */
diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c
index 1460741..88c610d 100644
--- a/libavcodec/interplayvideo.c
+++ b/libavcodec/interplayvideo.c
@@ -1,6 +1,6 @@
 /*
  * Interplay MVE Video Decoder
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/intrax8.c b/libavcodec/intrax8.c
index cf01289..1e881fc 100644
--- a/libavcodec/intrax8.c
+++ b/libavcodec/intrax8.c
@@ -23,16 +23,16 @@
 
 #include "libavutil/avassert.h"
 #include "avcodec.h"
-#include "error_resilience.h"
 #include "get_bits.h"
 #include "idctdsp.h"
-#include "mpegvideo.h"
 #include "msmpeg4data.h"
 #include "intrax8huf.h"
 #include "intrax8.h"
 #include "intrax8dsp.h"
+#include "mpegutils.h"
 
-#define MAX_TABLE_DEPTH(table_bits, max_bits) ((max_bits+table_bits-1)/table_bits)
+#define MAX_TABLE_DEPTH(table_bits, max_bits) \
+    ((max_bits + table_bits - 1) / table_bits)
 
 #define DC_VLC_BITS 9
 #define AC_VLC_BITS 9
@@ -42,15 +42,16 @@
 #define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS)
 #define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS)
 
-static VLC j_ac_vlc[2][2][8];  //[quant<13],[intra/inter],[select]
-static VLC j_dc_vlc[2][8];     //[quant], [select]
-static VLC j_orient_vlc[2][4]; //[quant], [select]
+static VLC j_ac_vlc[2][2][8];  // [quant < 13], [intra / inter], [select]
+static VLC j_dc_vlc[2][8];     // [quant], [select]
+static VLC j_orient_vlc[2][4]; // [quant], [select]
 
-static av_cold void x8_vlc_init(void){
+static av_cold int x8_vlc_init(void)
+{
     int i;
     int offset = 0;
     int sizeidx = 0;
-    static const uint16_t sizes[8*4 + 8*2 + 2 + 4] = {
+    static const uint16_t sizes[8 * 4 + 8 * 2 + 2 + 4] = {
         576, 548, 582, 618, 546, 616, 560, 642,
         584, 582, 704, 664, 512, 544, 656, 640,
         512, 648, 582, 566, 532, 614, 596, 648,
@@ -59,735 +60,784 @@ static av_cold void x8_vlc_init(void){
         528, 528, 526, 528, 536, 528, 526, 544,
         544, 512, 512, 528, 528, 544, 512, 544,
 
-        128, 128, 128, 128, 128, 128};
+        128, 128, 128, 128, 128, 128,
+    };
 
     static VLC_TYPE table[28150][2];
 
-#define  init_ac_vlc(dst,src) \
-    dst.table = &table[offset]; \
-    dst.table_allocated = sizes[sizeidx]; \
-    offset += sizes[sizeidx++]; \
-       init_vlc(&dst, \
-              AC_VLC_BITS,77, \
-              &src[1],4,2, \
-              &src[0],4,2, \
-              INIT_VLC_USE_NEW_STATIC)
-//set ac tables
-    for(i=0;i<8;i++){
-        init_ac_vlc( j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0] );
-        init_ac_vlc( j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0] );
-        init_ac_vlc( j_ac_vlc[1][0][i], x8_ac0_lowquant_table [i][0] );
-        init_ac_vlc( j_ac_vlc[1][1][i], x8_ac1_lowquant_table [i][0] );
+// set ac tables
+#define init_ac_vlc(dst, src)                                                 \
+    do {                                                                      \
+        dst.table           = &table[offset];                                 \
+        dst.table_allocated = sizes[sizeidx];                                 \
+        offset             += sizes[sizeidx++];                               \
+        init_vlc(&dst, AC_VLC_BITS, 77, &src[1], 4, 2, &src[0], 4, 2,         \
+                 INIT_VLC_USE_NEW_STATIC);                                    \
+    } while(0)
+
+    for (i = 0; i < 8; i++) {
+        init_ac_vlc(j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0]);
+        init_ac_vlc(j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0]);
+        init_ac_vlc(j_ac_vlc[1][0][i], x8_ac0_lowquant_table[i][0]);
+        init_ac_vlc(j_ac_vlc[1][1][i], x8_ac1_lowquant_table[i][0]);
     }
 #undef init_ac_vlc
 
-//set dc tables
-#define init_dc_vlc(dst,src) \
-    dst.table = &table[offset]; \
-    dst.table_allocated = sizes[sizeidx]; \
-    offset += sizes[sizeidx++]; \
-        init_vlc(&dst, \
-        DC_VLC_BITS,34, \
-        &src[1],4,2, \
-        &src[0],4,2, \
-        INIT_VLC_USE_NEW_STATIC);
-    for(i=0;i<8;i++){
-        init_dc_vlc( j_dc_vlc[0][i], x8_dc_highquant_table[i][0]);
-        init_dc_vlc( j_dc_vlc[1][i], x8_dc_lowquant_table [i][0]);
+// set dc tables
+#define init_dc_vlc(dst, src)                                                 \
+    do {                                                                      \
+        dst.table           = &table[offset];                                 \
+        dst.table_allocated = sizes[sizeidx];                                 \
+        offset             += sizes[sizeidx++];                               \
+        init_vlc(&dst, DC_VLC_BITS, 34, &src[1], 4, 2, &src[0], 4, 2,         \
+                 INIT_VLC_USE_NEW_STATIC);                                    \
+    } while(0)
+
+    for (i = 0; i < 8; i++) {
+        init_dc_vlc(j_dc_vlc[0][i], x8_dc_highquant_table[i][0]);
+        init_dc_vlc(j_dc_vlc[1][i], x8_dc_lowquant_table[i][0]);
     }
 #undef init_dc_vlc
 
-//set orient tables
-#define init_or_vlc(dst,src) \
-    dst.table = &table[offset]; \
-    dst.table_allocated = sizes[sizeidx]; \
-    offset += sizes[sizeidx++]; \
-    init_vlc(&dst, \
-    OR_VLC_BITS,12, \
-    &src[1],4,2, \
-    &src[0],4,2, \
-    INIT_VLC_USE_NEW_STATIC);
-    for(i=0;i<2;i++){
-        init_or_vlc( j_orient_vlc[0][i], x8_orient_highquant_table[i][0]);
-    }
-    for(i=0;i<4;i++){
-        init_or_vlc( j_orient_vlc[1][i], x8_orient_lowquant_table [i][0])
+// set orient tables
+#define init_or_vlc(dst, src)                                                 \
+    do {                                                                      \
+        dst.table           = &table[offset];                                 \
+        dst.table_allocated = sizes[sizeidx];                                 \
+        offset             += sizes[sizeidx++];                               \
+        init_vlc(&dst, OR_VLC_BITS, 12, &src[1], 4, 2, &src[0], 4, 2,         \
+                 INIT_VLC_USE_NEW_STATIC);                                    \
+    } while(0)
+
+    for (i = 0; i < 2; i++)
+        init_or_vlc(j_orient_vlc[0][i], x8_orient_highquant_table[i][0]);
+    for (i = 0; i < 4; i++)
+        init_or_vlc(j_orient_vlc[1][i], x8_orient_lowquant_table[i][0]);
+#undef init_or_vlc
+
+    if (offset != sizeof(table) / sizeof(VLC_TYPE) / 2) {
+        av_log(NULL, AV_LOG_ERROR, "table size %zd does not match needed %i\n",
+               sizeof(table) / sizeof(VLC_TYPE) / 2, offset);
+        return AVERROR_INVALIDDATA;
     }
-    if (offset != sizeof(table)/sizeof(VLC_TYPE)/2)
-        av_log(NULL, AV_LOG_ERROR, "table size %i does not match needed %i\n", (int)(sizeof(table)/sizeof(VLC_TYPE)/2), offset);
+
+    return 0;
 }
-#undef init_or_vlc
 
-static void x8_reset_vlc_tables(IntraX8Context * w){
-    memset(w->j_dc_vlc,0,sizeof(w->j_dc_vlc));
-    memset(w->j_ac_vlc,0,sizeof(w->j_ac_vlc));
-    w->j_orient_vlc=NULL;
+static void x8_reset_vlc_tables(IntraX8Context *w)
+{
+    memset(w->j_dc_vlc, 0, sizeof(w->j_dc_vlc));
+    memset(w->j_ac_vlc, 0, sizeof(w->j_ac_vlc));
+    w->j_orient_vlc = NULL;
 }
 
-static inline void x8_select_ac_table(IntraX8Context * const w , int mode){
-    MpegEncContext * const s= w->s;
+static inline void x8_select_ac_table(IntraX8Context *const w, int mode)
+{
     int table_index;
 
-    av_assert2(mode<4);
+    av_assert2(mode < 4);
 
-    if( w->j_ac_vlc[mode] ) return;
+    if (w->j_ac_vlc[mode])
+        return;
 
-    table_index = get_bits(&s->gb, 3);
-    w->j_ac_vlc[mode] = &j_ac_vlc[w->quant<13][mode>>1][table_index];//2 modes use same tables
+    table_index       = get_bits(w->gb, 3);
+    // 2 modes use same tables
+    w->j_ac_vlc[mode] = &j_ac_vlc[w->quant < 13][mode >> 1][table_index];
     av_assert2(w->j_ac_vlc[mode]);
 }
 
-static inline int x8_get_orient_vlc(IntraX8Context * w){
-    MpegEncContext * const s= w->s;
-    int table_index;
-
-    if(!w->j_orient_vlc ){
-        table_index = get_bits(&s->gb, 1+(w->quant<13) );
-        w->j_orient_vlc = &j_orient_vlc[w->quant<13][table_index];
+static inline int x8_get_orient_vlc(IntraX8Context *w)
+{
+    if (!w->j_orient_vlc) {
+        int table_index = get_bits(w->gb, 1 + (w->quant < 13));
+        w->j_orient_vlc = &j_orient_vlc[w->quant < 13][table_index];
     }
 
-    return get_vlc2(&s->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD);
+    return get_vlc2(w->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD);
 }
 
-#define extra_bits(eb) (eb)
-#define extra_run   (0xFF<<8)
-#define extra_level (0x00<<8)
-#define   run_offset(r)    ((r)<<16)
-#define level_offset(l)    ((l)<<24)
-static const uint32_t ac_decode_table[]={
-    /*46*/ extra_bits(3) |  extra_run  | run_offset(16) | level_offset( 0),
-    /*47*/ extra_bits(3) |  extra_run  | run_offset(24) | level_offset( 0),
-    /*48*/ extra_bits(2) |  extra_run  | run_offset( 4) | level_offset( 1),
-    /*49*/ extra_bits(3) |  extra_run  | run_offset( 8) | level_offset( 1),
-
-    /*50*/ extra_bits(5) |  extra_run  | run_offset(32) | level_offset( 0),
-    /*51*/ extra_bits(4) |  extra_run  | run_offset(16) | level_offset( 1),
-
-    /*52*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4),
-    /*53*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 8),
-    /*54*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset(12),
-    /*55*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(16),
-    /*56*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(24),
-
-    /*57*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3),
-    /*58*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7),
-
-    /*59*/ extra_bits(2) |  extra_run  | run_offset(16) | level_offset( 0),
-    /*60*/ extra_bits(2) |  extra_run  | run_offset(20) | level_offset( 0),
-    /*61*/ extra_bits(2) |  extra_run  | run_offset(24) | level_offset( 0),
-    /*62*/ extra_bits(2) |  extra_run  | run_offset(28) | level_offset( 0),
-    /*63*/ extra_bits(4) |  extra_run  | run_offset(32) | level_offset( 0),
-    /*64*/ extra_bits(4) |  extra_run  | run_offset(48) | level_offset( 0),
-
-    /*65*/ extra_bits(2) |  extra_run  | run_offset( 4) | level_offset( 1),
-    /*66*/ extra_bits(3) |  extra_run  | run_offset( 8) | level_offset( 1),
-    /*67*/ extra_bits(4) |  extra_run  | run_offset(16) | level_offset( 1),
-
-    /*68*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4),
-    /*69*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset( 8),
-    /*70*/ extra_bits(4) | extra_level | run_offset( 0) | level_offset(16),
-
-    /*71*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3),
-    /*72*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7),
+#define extra_bits(eb)  (eb)        // 3 bits
+#define extra_run       (0xFF << 8) // 1 bit
+#define extra_level     (0x00 << 8) // 1 bit
+#define run_offset(r)   ((r) << 16) // 6 bits
+#define level_offset(l) ((l) << 24) // 5 bits
+static const uint32_t ac_decode_table[] = {
+    /* 46 */ extra_bits(3) | extra_run   | run_offset(16) | level_offset(0),
+    /* 47 */ extra_bits(3) | extra_run   | run_offset(24) | level_offset(0),
+    /* 48 */ extra_bits(2) | extra_run   | run_offset(4)  | level_offset(1),
+    /* 49 */ extra_bits(3) | extra_run   | run_offset(8)  | level_offset(1),
+
+    /* 50 */ extra_bits(5) | extra_run   | run_offset(32) | level_offset(0),
+    /* 51 */ extra_bits(4) | extra_run   | run_offset(16) | level_offset(1),
+
+    /* 52 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(4),
+    /* 53 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(8),
+    /* 54 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(12),
+    /* 55 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(16),
+    /* 56 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(24),
+
+    /* 57 */ extra_bits(2) | extra_level | run_offset(1)  | level_offset(3),
+    /* 58 */ extra_bits(3) | extra_level | run_offset(1)  | level_offset(7),
+
+    /* 59 */ extra_bits(2) | extra_run   | run_offset(16) | level_offset(0),
+    /* 60 */ extra_bits(2) | extra_run   | run_offset(20) | level_offset(0),
+    /* 61 */ extra_bits(2) | extra_run   | run_offset(24) | level_offset(0),
+    /* 62 */ extra_bits(2) | extra_run   | run_offset(28) | level_offset(0),
+    /* 63 */ extra_bits(4) | extra_run   | run_offset(32) | level_offset(0),
+    /* 64 */ extra_bits(4) | extra_run   | run_offset(48) | level_offset(0),
+
+    /* 65 */ extra_bits(2) | extra_run   | run_offset(4)  | level_offset(1),
+    /* 66 */ extra_bits(3) | extra_run   | run_offset(8)  | level_offset(1),
+    /* 67 */ extra_bits(4) | extra_run   | run_offset(16) | level_offset(1),
+
+    /* 68 */ extra_bits(2) | extra_level | run_offset(0)  | level_offset(4),
+    /* 69 */ extra_bits(3) | extra_level | run_offset(0)  | level_offset(8),
+    /* 70 */ extra_bits(4) | extra_level | run_offset(0)  | level_offset(16),
+
+    /* 71 */ extra_bits(2) | extra_level | run_offset(1)  | level_offset(3),
+    /* 72 */ extra_bits(3) | extra_level | run_offset(1)  | level_offset(7),
 };
-//extra_bits = 3bits; extra_run/level = 1 bit; run_offset = 6bits; level_offset = 5 bits;
 #undef extra_bits
 #undef extra_run
 #undef extra_level
 #undef run_offset
 #undef level_offset
 
-static void x8_get_ac_rlf(IntraX8Context * const w, const int mode,
-                     int * const run, int * const level, int * const final){
-    MpegEncContext *  const s= w->s;
-    int i,e;
+static void x8_get_ac_rlf(IntraX8Context *const w, const int mode,
+                          int *const run, int *const level, int *const final)
+{
+    int i, e;
 
-//    x8_select_ac_table(w,mode);
-    i = get_vlc2(&s->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD);
+//    x8_select_ac_table(w, mode);
+    i = get_vlc2(w->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD);
 
-    if(i<46){ //[0-45]
-        int t,l;
-        if(i<0){
-            (*level)=(*final)=//prevent 'may be used unilitialized'
-            (*run)=64;//this would cause error exit in the ac loop
+    if (i < 46) { // [0-45]
+        int t, l;
+        if (i < 0) {
+            *level =
+            *final =      // prevent 'may be used uninitialized'
+            *run   = 64;  // this would cause error exit in the ac loop
             return;
         }
 
-        (*final) = t = (i>22);
-        i-=23*t;
-/*
-  i== 0-15 r=0-15 l=0 ;r=i& %01111
-  i==16-19 r=0-3  l=1 ;r=i& %00011
-  i==20-21 r=0-1  l=2 ;r=i& %00001
-  i==22    r=0    l=3 ;r=i& %00000
-l=lut_l[i/2]={0,0,0,0,0,0,0,0,1,1,2,3}[i>>1];// 11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000
-t=lut_mask[l]={0x0f,0x03,0x01,0x00}[l]; as i<256 the higher bits do not matter */
-        l=(0xE50000>>(i&(0x1E)))&3;/*0x1E or (~1) or ((i>>1)<<1)*/
-        t=(0x01030F>>(l<<3));
-
-        (*run)   = i&t;
-        (*level) = l;
-    }else if(i<73){//[46-72]
+        /*
+         * i == 0-15  r = 0-15 l = 0; r = i & %01111
+         * i == 16-19 r = 0-3  l = 1; r = i & %00011
+         * i == 20-21 r = 0-1  l = 2; r = i & %00001
+         * i == 22    r = 0    l = 3; r = i & %00000
+         */
+
+        *final =
+        t      = i > 22;
+        i     -= 23 * t;
+
+        /* l = lut_l[i / 2] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3 }[i >> 1];
+         *     11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000 */
+        l = (0xE50000 >> (i & 0x1E)) & 3; // 0x1E or ~1 or (i >> 1 << 1)
+
+        /* t = lut_mask[l] = { 0x0f, 0x03, 0x01, 0x00 }[l];
+         *     as i < 256 the higher bits do not matter */
+        t = 0x01030F >> (l << 3);
+
+        *run   = i & t;
+        *level = l;
+    } else if (i < 73) { // [46-72]
         uint32_t sm;
         uint32_t mask;
 
-        i-=46;
-        sm=ac_decode_table[i];
-
-        e=get_bits(&s->gb,sm&0xF);sm>>=8;//3bits
-        mask=sm&0xff;sm>>=8;             //1bit
-
-        (*run)  =(sm&0xff) + (e&( mask));//6bits
-        (*level)=(sm>>8)   + (e&(~mask));//5bits
-        (*final)=i>(58-46);
-    }else if(i<75){//[73-74]
-        static const uint8_t crazy_mix_runlevel[32]={
-        0x22,0x32,0x33,0x53,0x23,0x42,0x43,0x63,
-        0x24,0x52,0x34,0x73,0x25,0x62,0x44,0x83,
-        0x26,0x72,0x35,0x54,0x27,0x82,0x45,0x64,
-        0x28,0x92,0x36,0x74,0x29,0xa2,0x46,0x84};
-
-        (*final)=!(i&1);
-        e=get_bits(&s->gb,5);//get the extra bits
-        (*run)  =crazy_mix_runlevel[e]>>4;
-        (*level)=crazy_mix_runlevel[e]&0x0F;
-    }else{
-        (*level)=get_bits( &s->gb, 7-3*(i&1));
-        (*run)  =get_bits( &s->gb, 6);
-        (*final)=get_bits1(&s->gb);
+        i -= 46;
+        sm = ac_decode_table[i];
+
+        e    = get_bits(w->gb, sm & 0xF);
+        sm >>= 8;                               // 3 bits
+        mask = sm & 0xff;
+        sm >>= 8;                               // 1 bit
+
+        *run   = (sm &  0xff) + (e &  mask);    // 6 bits
+        *level = (sm >>    8) + (e & ~mask);    // 5 bits
+        *final = i > (58 - 46);
+    } else if (i < 75) { // [73-74]
+        static const uint8_t crazy_mix_runlevel[32] = {
+            0x22, 0x32, 0x33, 0x53, 0x23, 0x42, 0x43, 0x63,
+            0x24, 0x52, 0x34, 0x73, 0x25, 0x62, 0x44, 0x83,
+            0x26, 0x72, 0x35, 0x54, 0x27, 0x82, 0x45, 0x64,
+            0x28, 0x92, 0x36, 0x74, 0x29, 0xa2, 0x46, 0x84,
+        };
+
+        *final = !(i & 1);
+        e      = get_bits(w->gb, 5); // get the extra bits
+        *run   = crazy_mix_runlevel[e] >> 4;
+        *level = crazy_mix_runlevel[e] & 0x0F;
+    } else {
+        *level = get_bits(w->gb, 7 - 3 * (i & 1));
+        *run   = get_bits(w->gb, 6);
+        *final = get_bits1(w->gb);
     }
     return;
 }
 
-//static const uint8_t dc_extra_sbits[]   ={0, 1,1, 1,1, 2,2, 3,3,   4,4,   5,5,   6,6,    7,7    };
-static const uint8_t dc_index_offset[]  ={ 0, 1,2, 3,4, 5,7, 9,13, 17,25, 33,49, 65,97, 129,193};
+/* static const uint8_t dc_extra_sbits[] = {
+ *     0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
+ * }; */
+static const uint8_t dc_index_offset[] = {
+    0, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+};
 
-static int x8_get_dc_rlf(IntraX8Context * const w,int const mode, int * const level, int * const final){
-    MpegEncContext * const s= w->s;
-    int i,e,c;
+static int x8_get_dc_rlf(IntraX8Context *const w, const int mode,
+                         int *const level, int *const final)
+{
+    int i, e, c;
 
-    av_assert2(mode<3);
-    if( !w->j_dc_vlc[mode] ) {
-        int table_index;
-        table_index = get_bits(&s->gb, 3);
-        //4 modes, same table
-        w->j_dc_vlc[mode]= &j_dc_vlc[w->quant<13][table_index];
+    av_assert2(mode < 3);
+    if (!w->j_dc_vlc[mode]) {
+        int table_index = get_bits(w->gb, 3);
+        // 4 modes, same table
+        w->j_dc_vlc[mode] = &j_dc_vlc[w->quant < 13][table_index];
     }
 
-    i=get_vlc2(&s->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD);
+    i = get_vlc2(w->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD);
 
-    /*(i>=17) {i-=17;final=1;}*/
-    c= i>16;
-    (*final)=c;
-    i-=17*c;
+    /* (i >= 17) { i -= 17; final =1; } */
+    c      = i > 16;
+    *final = c;
+    i      -= 17 * c;
 
-    if(i<=0){
-        (*level)=0;
+    if (i <= 0) {
+        *level = 0;
         return -i;
     }
-    c=(i+1)>>1;//hackish way to calculate dc_extra_sbits[]
-    c-=c>1;
+    c  = (i + 1) >> 1; // hackish way to calculate dc_extra_sbits[]
+    c -= c > 1;
 
-    e=get_bits(&s->gb,c);//get the extra bits
-    i=dc_index_offset[i]+(e>>1);
+    e = get_bits(w->gb, c); // get the extra bits
+    i = dc_index_offset[i] + (e >> 1);
 
-    e= -(e & 1);//0,0xffffff
-    (*level)= (i ^ e) - e;// (i^0)-0 , (i^0xff)-(-1)
+    e      = -(e & 1);     // 0, 0xffffff
+    *level =  (i ^ e) - e; // (i ^ 0) - 0, (i ^ 0xff) - (-1)
     return 0;
 }
-//end of huffman
 
-static int x8_setup_spatial_predictor(IntraX8Context * const w, const int chroma){
-    MpegEncContext * const s= w->s;
+// end of huffman
+
+static int x8_setup_spatial_predictor(IntraX8Context *const w, const int chroma)
+{
     int range;
     int sum;
     int quant;
 
-    w->dsp.setup_spatial_compensation(s->dest[chroma], s->sc.edge_emu_buffer,
-                                      s->current_picture.f->linesize[chroma>0],
+    w->dsp.setup_spatial_compensation(w->dest[chroma], w->scratchpad,
+                                      w->frame->linesize[chroma > 0],
                                       &range, &sum, w->edges);
-    if(chroma){
-        w->orient=w->chroma_orient;
-        quant=w->quant_dc_chroma;
-    }else{
-        quant=w->quant;
+    if (chroma) {
+        w->orient = w->chroma_orient;
+        quant     = w->quant_dc_chroma;
+    } else {
+        quant = w->quant;
     }
 
-    w->flat_dc=0;
-    if(range < quant || range < 3){
-        w->orient=0;
-        if(range < 3){//yep you read right, a +-1 idct error may break decoding!
-            w->flat_dc=1;
-            sum+=9;
-            w->predicted_dc = (sum*6899)>>17;//((1<<17)+9)/(8+8+1+2)=6899
+    w->flat_dc = 0;
+    if (range < quant || range < 3) {
+        w->orient = 0;
+
+        // yep you read right, a +-1 idct error may break decoding!
+        if (range < 3) {
+            w->flat_dc      = 1;
+            sum            += 9;
+            // ((1 << 17) + 9) / (8 + 8 + 1 + 2) = 6899
+            w->predicted_dc = sum * 6899 >> 17;
         }
     }
-    if(chroma)
+    if (chroma)
         return 0;
 
     av_assert2(w->orient < 3);
-    if(range < 2*w->quant){
-        if( (w->edges&3) == 0){
-            if(w->orient==1) w->orient=11;
-            if(w->orient==2) w->orient=10;
-        }else{
-            w->orient=0;
+    if (range < 2 * w->quant) {
+        if ((w->edges & 3) == 0) {
+            if (w->orient == 1)
+                w->orient = 11;
+            if (w->orient == 2)
+                w->orient = 10;
+        } else {
+            w->orient = 0;
         }
-        w->raw_orient=0;
-    }else{
-        static const uint8_t prediction_table[3][12]={
-            {0,8,4, 10,11, 2,6,9,1,3,5,7},
-            {4,0,8, 11,10, 3,5,2,6,9,1,7},
-            {8,0,4, 10,11, 1,7,2,6,9,3,5}
+        w->raw_orient = 0;
+    } else {
+        static const uint8_t prediction_table[3][12] = {
+            { 0, 8, 4, 10, 11, 2, 6, 9, 1, 3, 5, 7 },
+            { 4, 0, 8, 11, 10, 3, 5, 2, 6, 9, 1, 7 },
+            { 8, 0, 4, 10, 11, 1, 7, 2, 6, 9, 3, 5 },
         };
-        w->raw_orient=x8_get_orient_vlc(w);
-        if(w->raw_orient<0) return -1;
-        av_assert2(w->raw_orient < 12 );
-        av_assert2(w->orient<3);
+        w->raw_orient = x8_get_orient_vlc(w);
+        if (w->raw_orient < 0)
+            return -1;
+        av_assert2(w->raw_orient < 12);
+        av_assert2(w->orient < 3);
         w->orient=prediction_table[w->orient][w->raw_orient];
     }
     return 0;
 }
 
-static void x8_update_predictions(IntraX8Context * const w, const int orient, const int est_run ){
-    MpegEncContext * const s= w->s;
-
-    w->prediction_table[s->mb_x*2+(s->mb_y&1)] = (est_run<<2) + 1*(orient==4) + 2*(orient==8);
+static void x8_update_predictions(IntraX8Context *const w, const int orient,
+                                  const int est_run)
+{
+    w->prediction_table[w->mb_x * 2 + (w->mb_y & 1)] = (est_run << 2) + 1 * (orient == 4) + 2 * (orient == 8);
 /*
-  y=2n+0 ->//0 2 4
-  y=2n+1 ->//1 3 5
-*/
+ * y = 2n + 0 -> // 0 2 4
+ * y = 2n + 1 -> // 1 3 5
+ */
 }
-static void x8_get_prediction_chroma(IntraX8Context * const w){
-    MpegEncContext * const s= w->s;
-
-    w->edges = 1*( !(s->mb_x>>1) );
-    w->edges|= 2*( !(s->mb_y>>1) );
-    w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) );//mb_x for chroma would always be odd
 
-    w->raw_orient=0;
-    if(w->edges&3){//lut_co[8]={inv,4,8,8, inv,4,8,8}<- =>{1,1,0,0;1,1,0,0} => 0xCC
-        w->chroma_orient=4<<((0xCC>>w->edges)&1);
+static void x8_get_prediction_chroma(IntraX8Context *const w)
+{
+    w->edges  = 1 * !(w->mb_x >> 1);
+    w->edges |= 2 * !(w->mb_y >> 1);
+    w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1)); // mb_x for chroma would always be odd
+
+    w->raw_orient = 0;
+    // lut_co[8] = {inv,4,8,8, inv,4,8,8} <- => {1,1,0,0;1,1,0,0} => 0xCC
+    if (w->edges & 3) {
+        w->chroma_orient = 4 << ((0xCC >> w->edges) & 1);
         return;
     }
-    w->chroma_orient = (w->prediction_table[2*s->mb_x-2] & 0x03)<<2;//block[x-1][y|1-1)]
+    // block[x - 1][y | 1 - 1)]
+    w->chroma_orient = (w->prediction_table[2 * w->mb_x - 2] & 0x03) << 2;
 }
 
-static void x8_get_prediction(IntraX8Context * const w){
-    MpegEncContext * const s= w->s;
-    int a,b,c,i;
-
-    w->edges = 1*( !s->mb_x );
-    w->edges|= 2*( !s->mb_y );
-    w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) );
-
-    switch(w->edges&3){
-        case 0:
-            break;
-        case 1:
-            //take the one from the above block[0][y-1]
-            w->est_run = w->prediction_table[!(s->mb_y&1)]>>2;
-            w->orient  = 1;
-            return;
-        case 2:
-            //take the one from the previous block[x-1][0]
-            w->est_run = w->prediction_table[2*s->mb_x-2]>>2;
-            w->orient  = 2;
-            return;
-        case 3:
-            w->est_run = 16;
-            w->orient  = 0;
-            return;
+static void x8_get_prediction(IntraX8Context *const w)
+{
+    int a, b, c, i;
+
+    w->edges  = 1 * !w->mb_x;
+    w->edges |= 2 * !w->mb_y;
+    w->edges |= 4 * (w->mb_x >= (2 * w->mb_width - 1));
+
+    switch (w->edges & 3) {
+    case 0:
+        break;
+    case 1:
+        // take the one from the above block[0][y - 1]
+        w->est_run = w->prediction_table[!(w->mb_y & 1)] >> 2;
+        w->orient  = 1;
+        return;
+    case 2:
+        // take the one from the previous block[x - 1][0]
+        w->est_run = w->prediction_table[2 * w->mb_x - 2] >> 2;
+        w->orient  = 2;
+        return;
+    case 3:
+        w->est_run = 16;
+        w->orient  = 0;
+        return;
     }
-    //no edge cases
-    b= w->prediction_table[2*s->mb_x   + !(s->mb_y&1) ];//block[x  ][y-1]
-    a= w->prediction_table[2*s->mb_x-2 +  (s->mb_y&1) ];//block[x-1][y  ]
-    c= w->prediction_table[2*s->mb_x-2 + !(s->mb_y&1) ];//block[x-1][y-1]
+    // no edge cases
+    b = w->prediction_table[2 * w->mb_x     + !(w->mb_y & 1)]; // block[x    ][y - 1]
+    a = w->prediction_table[2 * w->mb_x - 2 +  (w->mb_y & 1)]; // block[x - 1][y    ]
+    c = w->prediction_table[2 * w->mb_x - 2 + !(w->mb_y & 1)]; // block[x - 1][y - 1]
 
-    w->est_run = FFMIN(b,a);
+    w->est_run = FFMIN(b, a);
     /* This condition has nothing to do with w->edges, even if it looks
-       similar it would trigger if e.g. x=3;y=2;
-       I guess somebody wrote something wrong and it became standard. */
-    if( (s->mb_x & s->mb_y) != 0 ) w->est_run=FFMIN(c,w->est_run);
-    w->est_run>>=2;
-
-    a&=3;
-    b&=3;
-    c&=3;
-
-    i=( 0xFFEAF4C4>>(2*b+8*a) )&3;
-    if(i!=3) w->orient=i;
-    else     w->orient=( 0xFFEAD8>>(2*c+8*(w->quant>12)) )&3;
+     * similar it would trigger if e.g. x = 3; y = 2;
+     * I guess somebody wrote something wrong and it became standard. */
+    if ((w->mb_x & w->mb_y) != 0)
+        w->est_run = FFMIN(c, w->est_run);
+    w->est_run >>= 2;
+
+    a &= 3;
+    b &= 3;
+    c &= 3;
+
+    i = (0xFFEAF4C4 >> (2 * b + 8 * a)) & 3;
+    if (i != 3)
+        w->orient = i;
+    else
+        w->orient = (0xFFEAD8 >> (2 * c + 8 * (w->quant > 12))) & 3;
 /*
-lut1[b][a]={
-->{0, 1, 0, pad},
-  {0, 1, X, pad},
-  {2, 2, 2, pad}}
-   pad 2   2  2; pad X  1  0; pad 0  1  0 <-
--> 11 10 '10 10 '11 11'01 00 '11 00'01 00=>0xEAF4C4
-
-lut2[q>12][c]={
-  ->{0,2,1,pad},
-    {2,2,2,pad}}
-   pad 2  2  2; pad 1  2  0 <-
--> 11 10'10 10 '11 01'10 00=>0xEAD8
-*/
+ * lut1[b][a] = {
+ * ->{ 0, 1, 0, pad },
+ *   { 0, 1, X, pad },
+ *   { 2, 2, 2, pad }
+ * }
+ * pad 2  2  2;
+ * pad X  1  0;
+ * pad 0  1  0 <-
+ * -> 11 10 '10 10 '11 11'01 00 '11 00'01 00 => 0xEAF4C4
+ *
+ * lut2[q>12][c] = {
+ * ->{ 0, 2, 1, pad},
+ *   { 2, 2, 2, pad}
+ * }
+ * pad 2  2  2;
+ * pad 1  2  0 <-
+ * -> 11 10'10 10 '11 01'10 00 => 0xEAD8
+ */
 }
 
-
-static void x8_ac_compensation(IntraX8Context * const w, int const direction, int const dc_level){
-    MpegEncContext * const s= w->s;
+static void x8_ac_compensation(IntraX8Context *const w, const int direction,
+                               const int dc_level)
+{
     int t;
-#define B(x,y)  s->block[0][w->idct_permutation[(x)+(y)*8]]
+#define B(x,y)  w->block[0][w->idct_permutation[(x) + (y) * 8]]
 #define T(x)  ((x) * dc_level + 0x8000) >> 16;
-    switch(direction){
+    switch (direction) {
     case 0:
-        t = T(3811);//h
-        B(1,0) -= t;
-        B(0,1) -= t;
-
-        t = T(487);//e
-        B(2,0) -= t;
-        B(0,2) -= t;
-
-        t = T(506);//f
-        B(3,0) -= t;
-        B(0,3) -= t;
-
-        t = T(135);//c
-        B(4,0) -= t;
-        B(0,4) -= t;
-        B(2,1) += t;
-        B(1,2) += t;
-        B(3,1) += t;
-        B(1,3) += t;
-
-        t = T(173);//d
-        B(5,0) -= t;
-        B(0,5) -= t;
-
-        t = T(61);//b
-        B(6,0) -= t;
-        B(0,6) -= t;
-        B(5,1) += t;
-        B(1,5) += t;
-
-        t = T(42); //a
-        B(7,0) -= t;
-        B(0,7) -= t;
-        B(4,1) += t;
-        B(1,4) += t;
-        B(4,4) += t;
-
-        t = T(1084);//g
-        B(1,1) += t;
-
-        s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8);
+        t        = T(3811); // h
+        B(1, 0) -= t;
+        B(0, 1) -= t;
+
+        t        = T(487); // e
+        B(2, 0) -= t;
+        B(0, 2) -= t;
+
+        t        = T(506); // f
+        B(3, 0) -= t;
+        B(0, 3) -= t;
+
+        t        = T(135); // c
+        B(4, 0) -= t;
+        B(0, 4) -= t;
+        B(2, 1) += t;
+        B(1, 2) += t;
+        B(3, 1) += t;
+        B(1, 3) += t;
+
+        t        = T(173); // d
+        B(5, 0) -= t;
+        B(0, 5) -= t;
+
+        t        = T(61); // b
+        B(6, 0) -= t;
+        B(0, 6) -= t;
+        B(5, 1) += t;
+        B(1, 5) += t;
+
+        t        = T(42); // a
+        B(7, 0) -= t;
+        B(0, 7) -= t;
+        B(4, 1) += t;
+        B(1, 4) += t;
+        B(4, 4) += t;
+
+        t        = T(1084); // g
+        B(1, 1) += t;
+
+        w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8);
         break;
     case 1:
-        B(0,1) -= T(6269);
-        B(0,3) -= T( 708);
-        B(0,5) -= T( 172);
-        B(0,7) -= T(  73);
+        B(0, 1) -= T(6269);
+        B(0, 3) -= T(708);
+        B(0, 5) -= T(172);
+        B(0, 7) -= T(73);
 
-        s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8);
+        w->block_last_index[0] = FFMAX(w->block_last_index[0], 7 * 8);
         break;
     case 2:
-        B(1,0) -= T(6269);
-        B(3,0) -= T( 708);
-        B(5,0) -= T( 172);
-        B(7,0) -= T(  73);
+        B(1, 0) -= T(6269);
+        B(3, 0) -= T(708);
+        B(5, 0) -= T(172);
+        B(7, 0) -= T(73);
 
-        s->block_last_index[0] = FFMAX(s->block_last_index[0], 7);
+        w->block_last_index[0] = FFMAX(w->block_last_index[0], 7);
         break;
     }
 #undef B
 #undef T
 }
 
-static void dsp_x8_put_solidcolor(uint8_t const pix, uint8_t * dst, int const linesize){
+static void dsp_x8_put_solidcolor(const uint8_t pix, uint8_t *dst,
+                                  const int linesize)
+{
     int k;
-    for(k=0;k<8;k++){
-        memset(dst,pix,8);
-        dst+=linesize;
+    for (k = 0; k < 8; k++) {
+        memset(dst, pix, 8);
+        dst += linesize;
     }
 }
 
 static const int16_t quant_table[64] = {
-    256, 256, 256, 256,  256, 256, 259, 262,
-    265, 269, 272, 275,  278, 282, 285, 288,
-    292, 295, 299, 303,  306, 310, 314, 317,
-    321, 325, 329, 333,  337, 341, 345, 349,
-    353, 358, 362, 366,  371, 375, 379, 384,
-    389, 393, 398, 403,  408, 413, 417, 422,
-    428, 433, 438, 443,  448, 454, 459, 465,
-    470, 476, 482, 488,  493, 499, 505, 511
+    256, 256, 256, 256, 256, 256, 259, 262,
+    265, 269, 272, 275, 278, 282, 285, 288,
+    292, 295, 299, 303, 306, 310, 314, 317,
+    321, 325, 329, 333, 337, 341, 345, 349,
+    353, 358, 362, 366, 371, 375, 379, 384,
+    389, 393, 398, 403, 408, 413, 417, 422,
+    428, 433, 438, 443, 448, 454, 459, 465,
+    470, 476, 482, 488, 493, 499, 505, 511,
 };
 
-static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){
-    MpegEncContext * const s= w->s;
-
-    uint8_t * scantable;
-    int final,run,level;
-    int ac_mode,dc_mode,est_run,dc_level;
-    int pos,n;
+static int x8_decode_intra_mb(IntraX8Context *const w, const int chroma)
+{
+    uint8_t *scantable;
+    int final, run, level;
+    int ac_mode, dc_mode, est_run, dc_level;
+    int pos, n;
     int zeros_only;
     int use_quant_matrix;
     int sign;
 
-    av_assert2(w->orient<12);
-    s->bdsp.clear_block(s->block[0]);
-
-    if(chroma){
-        dc_mode=2;
-    }else{
-        dc_mode=!!w->est_run;//0,1
-    }
-
-    if(x8_get_dc_rlf(w, dc_mode, &dc_level, &final)) return -1;
-    n=0;
-    zeros_only=0;
-    if(!final){//decode ac
-        use_quant_matrix=w->use_quant_matrix;
-        if(chroma){
+    av_assert2(w->orient < 12);
+    w->bdsp.clear_block(w->block[0]);
+
+    if (chroma)
+        dc_mode = 2;
+    else
+        dc_mode = !!w->est_run; // 0, 1
+
+    if (x8_get_dc_rlf(w, dc_mode, &dc_level, &final))
+        return -1;
+    n          = 0;
+    zeros_only = 0;
+    if (!final) { // decode ac
+        use_quant_matrix = w->use_quant_matrix;
+        if (chroma) {
             ac_mode = 1;
-            est_run = 64;//not used
-        }else{
-            if (w->raw_orient < 3){
+            est_run = 64; // not used
+        } else {
+            if (w->raw_orient < 3)
                 use_quant_matrix = 0;
-            }
-            if(w->raw_orient > 4){
+
+            if (w->raw_orient > 4) {
                 ac_mode = 0;
                 est_run = 64;
-            }else{
-                if(w->est_run > 1){
+            } else {
+                if (w->est_run > 1) {
                     ac_mode = 2;
-                    est_run=w->est_run;
-                }else{
+                    est_run = w->est_run;
+                } else {
                     ac_mode = 3;
                     est_run = 64;
                 }
             }
         }
-        x8_select_ac_table(w,ac_mode);
-        /*scantable_selector[12]={0,2,0,1,1,1,0,2,2,0,1,2};<-
-        -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 =>0x928548 */
-        scantable = w->scantable[ (0x928548>>(2*w->orient))&3 ].permutated;
-        pos=0;
+        x8_select_ac_table(w, ac_mode);
+        /* scantable_selector[12] = { 0, 2, 0, 1, 1, 1, 0, 2, 2, 0, 1, 2 }; <-
+         * -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 => 0x928548 */
+        scantable = w->scantable[(0x928548 >> (2 * w->orient)) & 3].permutated;
+        pos       = 0;
         do {
             n++;
-            if( n >= est_run ){
-                ac_mode=3;
-                x8_select_ac_table(w,3);
+            if (n >= est_run) {
+                ac_mode = 3;
+                x8_select_ac_table(w, 3);
             }
 
-            x8_get_ac_rlf(w,ac_mode,&run,&level,&final);
+            x8_get_ac_rlf(w, ac_mode, &run, &level, &final);
 
-            pos+=run+1;
-            if(pos>63){
-                //this also handles vlc error in x8_get_ac_rlf
+            pos += run + 1;
+            if (pos > 63) {
+                // this also handles vlc error in x8_get_ac_rlf
                 return -1;
             }
-            level= (level+1) * w->dquant;
-            level+= w->qsum;
+            level  = (level + 1) * w->dquant;
+            level += w->qsum;
 
-            sign = - get_bits1(&s->gb);
+            sign  = -get_bits1(w->gb);
             level = (level ^ sign) - sign;
 
-            if(use_quant_matrix){
-                level = (level*quant_table[pos])>>8;
-            }
-            s->block[0][ scantable[pos] ]=level;
-        }while(!final);
+            if (use_quant_matrix)
+                level = (level * quant_table[pos]) >> 8;
+
+            w->block[0][scantable[pos]] = level;
+        } while (!final);
 
-        s->block_last_index[0]=pos;
-    }else{//DC only
-        s->block_last_index[0]=0;
-        if(w->flat_dc && ((unsigned)(dc_level+1)) < 3){//[-1;1]
-            int32_t divide_quant= !chroma ? w->divide_quant_dc_luma:
-                                            w->divide_quant_dc_chroma;
-            int32_t dc_quant    = !chroma ? w->quant:
-                                            w->quant_dc_chroma;
+        w->block_last_index[0] = pos;
+    } else { // DC only
+        w->block_last_index[0] = 0;
+        if (w->flat_dc && ((unsigned) (dc_level + 1)) < 3) { // [-1; 1]
+            int32_t divide_quant = !chroma ? w->divide_quant_dc_luma
+                                           : w->divide_quant_dc_chroma;
+            int32_t dc_quant     = !chroma ? w->quant
+                                           : w->quant_dc_chroma;
 
-            //original intent dc_level+=predicted_dc/quant; but it got lost somewhere in the rounding
-            dc_level+= (w->predicted_dc*divide_quant + (1<<12) )>>13;
+            // original intent dc_level += predicted_dc/quant;
+            // but it got lost somewhere in the rounding
+            dc_level += (w->predicted_dc * divide_quant + (1 << 12)) >> 13;
 
-            dsp_x8_put_solidcolor( av_clip_uint8((dc_level*dc_quant+4)>>3),
-                                   s->dest[chroma], s->current_picture.f->linesize[!!chroma]);
+            dsp_x8_put_solidcolor(av_clip_uint8((dc_level * dc_quant + 4) >> 3),
+                                  w->dest[chroma],
+                                  w->frame->linesize[!!chroma]);
 
             goto block_placed;
         }
-        zeros_only = (dc_level == 0);
-    }
-    if(!chroma){
-        s->block[0][0] = dc_level*w->quant;
-    }else{
-        s->block[0][0] = dc_level*w->quant_dc_chroma;
+        zeros_only = dc_level == 0;
     }
+    if (!chroma)
+        w->block[0][0] = dc_level * w->quant;
+    else
+        w->block[0][0] = dc_level * w->quant_dc_chroma;
 
-    //there is !zero_only check in the original, but dc_level check is enough
-    if( (unsigned int)(dc_level+1) >= 3 && (w->edges&3) != 3 ){
+    // there is !zero_only check in the original, but dc_level check is enough
+    if ((unsigned int) (dc_level + 1) >= 3 && (w->edges & 3) != 3) {
         int direction;
-        /*ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 };<-
-        -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 =>0x6A017C */
-        direction= (0x6A017C>>(w->orient*2))&3;
-        if (direction != 3){
-            x8_ac_compensation(w, direction, s->block[0][0]);//modify block_last[]
+        /* ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 }; <-
+         * -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 => 0x6A017C */
+        direction = (0x6A017C >> (w->orient * 2)) & 3;
+        if (direction != 3) {
+            // modify block_last[]
+            x8_ac_compensation(w, direction, w->block[0][0]);
         }
     }
 
-    if(w->flat_dc){
-        dsp_x8_put_solidcolor(w->predicted_dc, s->dest[chroma], s->current_picture.f->linesize[!!chroma]);
-    }else{
-        w->dsp.spatial_compensation[w->orient]( s->sc.edge_emu_buffer,
-                                            s->dest[chroma],
-                                            s->current_picture.f->linesize[!!chroma] );
+    if (w->flat_dc) {
+        dsp_x8_put_solidcolor(w->predicted_dc, w->dest[chroma],
+                              w->frame->linesize[!!chroma]);
+    } else {
+        w->dsp.spatial_compensation[w->orient](w->scratchpad,
+                                               w->dest[chroma],
+                                               w->frame->linesize[!!chroma]);
     }
-    if(!zeros_only)
-        w->wdsp.idct_add(s->dest[chroma],
-                         s->current_picture.f->linesize[!!chroma],
-                         s->block[0]);
+    if (!zeros_only)
+        w->wdsp.idct_add(w->dest[chroma],
+                         w->frame->linesize[!!chroma],
+                         w->block[0]);
 
 block_placed:
+    if (!chroma)
+        x8_update_predictions(w, w->orient, n);
 
-    if(!chroma){
-        x8_update_predictions(w,w->orient,n);
-    }
-
-    if(s->loop_filter){
-        uint8_t* ptr = s->dest[chroma];
-        int linesize = s->current_picture.f->linesize[!!chroma];
+    if (w->loopfilter) {
+        uint8_t *ptr = w->dest[chroma];
+        int linesize = w->frame->linesize[!!chroma];
 
-        if(!( (w->edges&2) || ( zeros_only && (w->orient|4)==4 ) )){
+        if (!((w->edges & 2) || (zeros_only && (w->orient | 4) == 4)))
             w->dsp.h_loop_filter(ptr, linesize, w->quant);
-        }
-        if(!( (w->edges&1) || ( zeros_only && (w->orient|8)==8 ) )){
+
+        if (!((w->edges & 1) || (zeros_only && (w->orient | 8) == 8)))
             w->dsp.v_loop_filter(ptr, linesize, w->quant);
-        }
     }
     return 0;
 }
 
-static void x8_init_block_index(MpegEncContext *s){ //FIXME maybe merge with ff_*
-//not s->linesize as this would be wrong for field pics
-//not that IntraX8 has interlacing support ;)
-    const int linesize   = s->current_picture.f->linesize[0];
-    const int uvlinesize = s->current_picture.f->linesize[1];
-
-    s->dest[0] = s->current_picture.f->data[0];
-    s->dest[1] = s->current_picture.f->data[1];
-    s->dest[2] = s->current_picture.f->data[2];
-
-    s->dest[0] +=   s->mb_y        *   linesize << 3;
-    s->dest[1] += ( s->mb_y&(~1) ) * uvlinesize << 2;//chroma blocks are on add rows
-    s->dest[2] += ( s->mb_y&(~1) ) * uvlinesize << 2;
+// FIXME maybe merge with ff_*
+static void x8_init_block_index(IntraX8Context *w, AVFrame *frame)
+{
+    // not parent codec linesize as this would be wrong for field pics
+    // not that IntraX8 has interlacing support ;)
+    const int linesize   = frame->linesize[0];
+    const int uvlinesize = frame->linesize[1];
+
+    w->dest[0] = frame->data[0];
+    w->dest[1] = frame->data[1];
+    w->dest[2] = frame->data[2];
+
+    w->dest[0] +=  w->mb_y       * linesize   << 3;
+    // chroma blocks are on add rows
+    w->dest[1] += (w->mb_y & ~1) * uvlinesize << 2;
+    w->dest[2] += (w->mb_y & ~1) * uvlinesize << 2;
 }
 
-/**
- * Initialize IntraX8 frame decoder.
- * Requires valid MpegEncContext with valid s->mb_width before calling.
- * @param w pointer to IntraX8Context
- * @param s pointer to MpegEncContext of the parent codec
- */
-av_cold void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s){
-
-    w->s=s;
-    x8_vlc_init();
-    av_assert0(s->mb_width>0);
-    w->prediction_table=av_mallocz(s->mb_width*2*2);//two rows, 2 blocks per cannon mb
+av_cold int ff_intrax8_common_init(AVCodecContext *avctx,
+                                   IntraX8Context *w, IDCTDSPContext *idsp,
+                                   int16_t (*block)[64],
+                                   int block_last_index[12],
+                                   int mb_width, int mb_height)
+{
+    int ret = x8_vlc_init();
+    if (ret < 0)
+        return ret;
+
+    w->avctx = avctx;
+    w->idsp = *idsp;
+    w->mb_width  = mb_width;
+    w->mb_height = mb_height;
+    w->block = block;
+    w->block_last_index = block_last_index;
+
+    // two rows, 2 blocks per cannon mb
+    w->prediction_table = av_mallocz(w->mb_width * 2 * 2);
+    if (!w->prediction_table)
+        return AVERROR(ENOMEM);
 
     ff_wmv2dsp_init(&w->wdsp);
+
     ff_init_scantable_permutation(w->idct_permutation,
                                   w->wdsp.idct_perm);
 
-    ff_init_scantable(w->idct_permutation, &w->scantable[0], ff_wmv1_scantable[0]);
-    ff_init_scantable(w->idct_permutation, &w->scantable[1], ff_wmv1_scantable[2]);
-    ff_init_scantable(w->idct_permutation, &w->scantable[2], ff_wmv1_scantable[3]);
+    ff_init_scantable(w->idct_permutation, &w->scantable[0],
+                      ff_wmv1_scantable[0]);
+    ff_init_scantable(w->idct_permutation, &w->scantable[1],
+                      ff_wmv1_scantable[2]);
+    ff_init_scantable(w->idct_permutation, &w->scantable[2],
+                      ff_wmv1_scantable[3]);
 
     ff_intrax8dsp_init(&w->dsp);
+    ff_blockdsp_init(&w->bdsp, avctx);
+
+    return 0;
 }
 
-/**
- * Destroy IntraX8 frame structure.
- * @param w pointer to IntraX8Context
- */
-av_cold void ff_intrax8_common_end(IntraX8Context * w)
+av_cold void ff_intrax8_common_end(IntraX8Context *w)
 {
     av_freep(&w->prediction_table);
 }
 
-/**
- * Decode single IntraX8 frame.
- * The parent codec must fill s->loopfilter and s->gb (bitstream).
- * The parent codec must call ff_mpv_frame_start(), ff_er_frame_start() before calling this function.
- * The parent codec must call ff_er_frame_end(), ff_mpv_frame_end() after calling this function.
- * This function does not use ff_mpv_decode_mb().
- * lowres decoding is theoretically impossible.
- * @param w pointer to IntraX8Context
- * @param dquant doubled quantizer, it would be odd in case of VC-1 halfpq==1.
- * @param quant_offset offset away from zero
- */
-int ff_intrax8_decode_picture(IntraX8Context * const w, int dquant, int quant_offset){
-    MpegEncContext * const s= w->s;
+int ff_intrax8_decode_picture(IntraX8Context *const w, Picture *pict,
+                              GetBitContext *gb, int *mb_x, int *mb_y,
+                              int dquant, int quant_offset,
+                              int loopfilter, int lowdelay)
+{
     int mb_xy;
-    w->use_quant_matrix = get_bits1(&s->gb);
 
+    w->gb     = gb;
     w->dquant = dquant;
     w->quant  = dquant >> 1;
     w->qsum   = quant_offset;
+    w->frame  = pict->f;
+    w->loopfilter = loopfilter;
+    w->use_quant_matrix = get_bits1(w->gb);
 
-    w->divide_quant_dc_luma = ((1<<16) + (w->quant>>1)) / w->quant;
-    if(w->quant < 5){
-        w->quant_dc_chroma =  w->quant;
+    w->mb_x = *mb_x;
+    w->mb_y = *mb_y;
+
+    w->divide_quant_dc_luma = ((1 << 16) + (w->quant >> 1)) / w->quant;
+    if (w->quant < 5) {
+        w->quant_dc_chroma        = w->quant;
         w->divide_quant_dc_chroma = w->divide_quant_dc_luma;
-    }else{
-        w->quant_dc_chroma =  w->quant+((w->quant+3)>>3);
-        w->divide_quant_dc_chroma = ((1<<16) + (w->quant_dc_chroma>>1)) / w->quant_dc_chroma;
+    } else {
+        w->quant_dc_chroma        = w->quant + ((w->quant + 3) >> 3);
+        w->divide_quant_dc_chroma = ((1 << 16) + (w->quant_dc_chroma >> 1)) / w->quant_dc_chroma;
     }
     x8_reset_vlc_tables(w);
 
-    s->resync_mb_x=0;
-    s->resync_mb_y=0;
-
-    for(s->mb_y=0; s->mb_y < s->mb_height*2; s->mb_y++){
-        x8_init_block_index(s);
-        mb_xy=(s->mb_y>>1)*s->mb_stride;
-
-        for(s->mb_x=0; s->mb_x < s->mb_width*2; s->mb_x++){
+    for (w->mb_y = 0; w->mb_y < w->mb_height * 2; w->mb_y++) {
+        x8_init_block_index(w, w->frame);
+        mb_xy = (w->mb_y >> 1) * (w->mb_width + 1);
+        for (w->mb_x = 0; w->mb_x < w->mb_width * 2; w->mb_x++) {
             x8_get_prediction(w);
-            if(x8_setup_spatial_predictor(w,0)) goto error;
-            if(x8_decode_intra_mb(w,0)) goto error;
+            if (x8_setup_spatial_predictor(w, 0))
+                goto error;
+            if (x8_decode_intra_mb(w, 0))
+                goto error;
 
-            if( s->mb_x & s->mb_y & 1 ){
+            if (w->mb_x & w->mb_y & 1) {
                 x8_get_prediction_chroma(w);
 
-                /*when setting up chroma, no vlc is read,
-                so no error condition can be reached*/
-                x8_setup_spatial_predictor(w,1);
-                if(x8_decode_intra_mb(w,1)) goto error;
+                /* when setting up chroma, no vlc is read,
+                 * so no error condition can be reached */
+                x8_setup_spatial_predictor(w, 1);
+                if (x8_decode_intra_mb(w, 1))
+                    goto error;
 
-                x8_setup_spatial_predictor(w,2);
-                if(x8_decode_intra_mb(w,2)) goto error;
+                x8_setup_spatial_predictor(w, 2);
+                if (x8_decode_intra_mb(w, 2))
+                    goto error;
 
-                s->dest[1]+= 8;
-                s->dest[2]+= 8;
+                w->dest[1] += 8;
+                w->dest[2] += 8;
 
-                /*emulate MB info in the relevant tables*/
-                s->mbskip_table [mb_xy]=0;
-                s->mbintra_table[mb_xy]=1;
-                s->current_picture.qscale_table[mb_xy] = w->quant;
+                pict->qscale_table[mb_xy] = w->quant;
                 mb_xy++;
             }
-            s->dest[0]+= 8;
-        }
-        if(s->mb_y&1){
-            ff_mpeg_draw_horiz_band(s, (s->mb_y-1)*8, 16);
+            w->dest[0] += 8;
         }
+        if (w->mb_y & 1)
+            ff_draw_horiz_band(w->avctx, w->frame, w->frame,
+                               (w->mb_y - 1) * 8, 16,
+                               PICT_FRAME, 0, lowdelay);
     }
 
 error:
-    ff_er_add_slice(&s->er, s->resync_mb_x, s->resync_mb_y,
-                        (s->mb_x>>1)-1, (s->mb_y>>1)-1,
-                        ER_MB_END );
+    *mb_x = w->mb_x;
+    *mb_y = w->mb_y;
+
     return 0;
 }
diff --git a/libavcodec/intrax8.h b/libavcodec/intrax8.h
index 9981785..5b8946e 100644
--- a/libavcodec/intrax8.h
+++ b/libavcodec/intrax8.h
@@ -19,33 +19,48 @@
 #ifndef AVCODEC_INTRAX8_H
 #define AVCODEC_INTRAX8_H
 
+#include "blockdsp.h"
 #include "get_bits.h"
-#include "mpegvideo.h"
+#include "idctdsp.h"
 #include "intrax8dsp.h"
 #include "wmv2dsp.h"
+#include "mpegpicture.h"
 
 typedef struct IntraX8Context {
-    VLC * j_ac_vlc[4];//they point to the static j_mb_vlc
-    VLC * j_orient_vlc;
-    VLC * j_dc_vlc[3];
+    VLC *j_ac_vlc[4]; // they point to the static j_mb_vlc
+    VLC *j_orient_vlc;
+    VLC *j_dc_vlc[3];
 
     int use_quant_matrix;
-//set by ff_intrax8_common_init
-    uint8_t * prediction_table;//2*(mb_w*2)
+
+    // set by ff_intrax8_common_init
+    uint8_t *prediction_table; // 2 * (mb_w * 2)
     ScanTable scantable[3];
     WMV2DSPContext wdsp;
     uint8_t idct_permutation[64];
-//set by the caller codec
-    MpegEncContext * s;
+    AVCodecContext *avctx;
+    int *block_last_index;  ///< last nonzero coefficient in block
+    int16_t (*block)[64];
+
+    // set by the caller codec
     IntraX8DSPContext dsp;
+    IDCTDSPContext idsp;
+    BlockDSPContext bdsp;
     int quant;
     int dquant;
     int qsum;
-//calculated per frame
+    int loopfilter;
+    AVFrame *frame;
+    GetBitContext *gb;
+
+    // calculated per frame
     int quant_dc_chroma;
     int divide_quant_dc_luma;
     int divide_quant_dc_chroma;
-//changed per block
+    uint8_t *dest[3];
+    uint8_t scratchpad[42]; // size of the block is fixed (8x8 plus padding)
+
+    // changed per block
     int edges;
     int flat_dc;
     int predicted_dc;
@@ -53,10 +68,50 @@ typedef struct IntraX8Context {
     int chroma_orient;
     int orient;
     int est_run;
+
+    // block props
+    int mb_x, mb_y;
+    int mb_width, mb_height;
 } IntraX8Context;
 
-void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s);
-void ff_intrax8_common_end(IntraX8Context * w);
-int  ff_intrax8_decode_picture(IntraX8Context * w, int quant, int halfpq);
+/**
+ * Initialize IntraX8 frame decoder.
+ * @param avctx pointer to AVCodecContext
+ * @param w pointer to IntraX8Context
+ * @param idsp pointer to IDCTDSPContext
+ * @param block pointer to block array
+ * @param block_last_index pointer to index array
+ * @param mb_width macroblock width
+ * @param mb_height macroblock height
+ * @return 0 on success, a negative AVERROR value on error
+ */
+int ff_intrax8_common_init(AVCodecContext *avctx,
+                           IntraX8Context *w, IDCTDSPContext *idsp,
+                           int16_t (*block)[64],
+                           int block_last_index[12],
+                           int mb_width, int mb_height);
+
+/**
+ * Destroy IntraX8 frame structure.
+ * @param w pointer to IntraX8Context
+ */
+void ff_intrax8_common_end(IntraX8Context *w);
+
+/**
+ * Decode single IntraX8 frame.
+ * lowres decoding is theoretically impossible.
+ * @param w pointer to IntraX8Context
+ * @param pict the output Picture containing an AVFrame
+ * @param gb open bitstream reader
+ * @param mb_x pointer to the x coordinate of the current macroblock
+ * @param mb_y pointer to the y coordinate of the current macroblock
+ * @param dquant doubled quantizer, it would be odd in case of VC-1 halfpq==1.
+ * @param quant_offset offset away from zero
+ * @param loopfilter enable filter after decoding a block
+ */
+int ff_intrax8_decode_picture(IntraX8Context *w, Picture *pict,
+                              GetBitContext *gb, int *mb_x, int *mb_y,
+                              int quant, int halfpq,
+                              int loopfilter, int lowdelay);
 
 #endif /* AVCODEC_INTRAX8_H */
diff --git a/libavcodec/intrax8dsp.c b/libavcodec/intrax8dsp.c
index 1b34f89..5520e3c 100644
--- a/libavcodec/intrax8dsp.c
+++ b/libavcodec/intrax8dsp.c
@@ -17,7 +17,7 @@
  */
 
 /**
-* @file
+ * @file
  *@brief IntraX8 frame subdecoder image manipulation routines
  */
 
@@ -25,27 +25,27 @@
 #include "libavutil/common.h"
 
 /*
-area positions, #3 is 1 pixel only, other are 8 pixels
-   |66666666|
-  3|44444444|55555555|
-- -+--------+--------+
-1 2|XXXXXXXX|
-1 2|XXXXXXXX|
-1 2|XXXXXXXX|
-1 2|XXXXXXXX|
-1 2|XXXXXXXX|
-1 2|XXXXXXXX|
-1 2|XXXXXXXX|
-1 2|XXXXXXXX|
-^-start
-*/
+ * area positions, #3 is 1 pixel only, other are 8 pixels
+ *    |66666666|
+ *   3|44444444|55555555|
+ * - -+--------+--------+
+ * 1 2|XXXXXXXX|
+ * 1 2|XXXXXXXX|
+ * 1 2|XXXXXXXX|
+ * 1 2|XXXXXXXX|
+ * 1 2|XXXXXXXX|
+ * 1 2|XXXXXXXX|
+ * 1 2|XXXXXXXX|
+ * 1 2|XXXXXXXX|
+ * ^-start
+ */
 
 #define area1 (0)
 #define area2 (8)
-#define area3 (8+8)
-#define area4 (8+8+1)
-#define area5 (8+8+1+8)
-#define area6 (8+8+1+16)
+#define area3 (8 + 8)
+#define area4 (8 + 8 + 1)
+#define area5 (8 + 8 + 1 + 8)
+#define area6 (8 + 8 + 1 + 16)
 
 /**
  Collect statistics and prepare the edge pixels required by the other spatial compensation functions.
@@ -61,372 +61,404 @@ area positions, #3 is 1 pixel only, other are 8 pixels
                 2   - mb_y==0 - first row, interpolate area #3,#4,#5,#6;
         note:   1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas;
                 4   - mb_x>= (mb_width-1) last block in the row, interpolate area #5;
-*/
-static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize,
-           int * range, int * psum,  int edges){
-    uint8_t * ptr;
+-*/
+static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst,
+                                          int linesize, int *range, int *psum,
+                                          int edges)
+{
+    uint8_t *ptr;
     int sum;
     int i;
-    int min_pix,max_pix;
+    int min_pix, max_pix;
     uint8_t c;
 
-    if((edges&3)==3){
-        *psum=0x80*(8+1+8+2);
-        *range=0;
-        memset(dst,0x80,16+1+16+8);
-        //this triggers flat_dc for sure.
-        //flat_dc avoids all (other) prediction modes, but requires dc_level decoding.
+    if ((edges & 3) == 3) {
+        *psum  = 0x80 * (8 + 1 + 8 + 2);
+        *range = 0;
+        memset(dst, 0x80, 16 + 1 + 16 + 8);
+        /* this triggers flat_dc for sure. flat_dc avoids all (other)
+         * prediction modes, but requires dc_level decoding. */
         return;
     }
 
-    min_pix=256;
-    max_pix=-1;
+    min_pix = 256;
+    max_pix = -1;
 
-    sum=0;
+    sum = 0;
 
-    if(!(edges&1)){//(mb_x!=0)//there is previous block on this row
-        ptr=src-1;//left column, area 2
-        for(i=7;i>=0;i--){
-            c=*(ptr-1);//area1, same mb as area2, no need to check
-            dst[area1+i]=c;
-            c=*(ptr);
+    if (!(edges & 1)) { // (mb_x != 0) // there is previous block on this row
+        ptr = src - 1; // left column, area 2
+        for (i = 7; i >= 0; i--) {
+            c              = *(ptr - 1); // area1, same mb as area2, no need to check
+            dst[area1 + i] = c;
+            c              = *ptr;
 
-            sum+=c;
-            min_pix=FFMIN(min_pix,c);
-            max_pix=FFMAX(max_pix,c);
-            dst[area2+i]=c;
+            sum           += c;
+            min_pix        = FFMIN(min_pix, c);
+            max_pix        = FFMAX(max_pix, c);
+            dst[area2 + i] = c;
 
-            ptr+=linesize;
+            ptr += linesize;
         }
     }
 
-    if(!(edges&2)){  //(mb_y!=0)//there is row above
-        ptr=src-linesize;//top line
-        for(i=0;i<8;i++){
-            c=*(ptr+i);
-            sum+=c;
-            min_pix=FFMIN(min_pix, c);
-            max_pix=FFMAX(max_pix, c);
+    if (!(edges & 2)) { // (mb_y != 0) // there is row above
+        ptr = src - linesize; // top line
+        for (i = 0; i < 8; i++) {
+            c       = *(ptr + i);
+            sum    += c;
+            min_pix = FFMIN(min_pix, c);
+            max_pix = FFMAX(max_pix, c);
         }
-        if(edges&4){//last block on the row?
-            memset(dst+area5,c,8);//set with last pixel fr
-            memcpy(dst+area4, ptr, 8);
-        }else{
-            memcpy(dst+area4, ptr, 16);//both area4 and 5
+        if (edges & 4) { // last block on the row?
+            memset(dst + area5, c, 8); // set with last pixel fr
+            memcpy(dst + area4, ptr, 8);
+        } else {
+            memcpy(dst + area4, ptr, 16); // both area4 and 5
         }
-        memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block
+        // area6 always present in the above block
+        memcpy(dst + area6, ptr - linesize, 8);
     }
-    //now calculate the stuff we need
-    if(edges&3){//mb_x==0 || mb_y==0){
-        int avg=(sum+4)>>3;
-        if(edges&1){ //(mb_x==0) {//implies mb_y!=0
-            memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged
-        }else{//implies y==0 x!=0
-            memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6
-        }
-        sum+=avg*9;
-    }else{
-        uint8_t c=*(src-1-linesize);//the edge pixel, in the top line and left column
-        dst[area3]=c;
-        sum+=c;
-        //edge pixel is not part of min/max
+    // now calculate the stuff we need
+    if (edges & 3) { // mb_x ==0 || mb_y == 0) {
+        int avg = (sum + 4) >> 3;
+
+        if (edges & 1) // (mb_x == 0) { // implies mb_y !=0
+            memset(dst + area1, avg, 8 + 8 + 1); // areas 1, 2, 3 are averaged
+        else // implies y == 0 x != 0
+            memset(dst + area3, avg, 1 + 16 + 8); // areas 3, 4, 5, 6
+
+        sum += avg * 9;
+    } else {
+        // the edge pixel, in the top line and left column
+        uint8_t c = *(src - 1 - linesize);
+        dst[area3] = c;
+        sum       += c;
+        // edge pixel is not part of min/max
     }
-    (*range) = max_pix - min_pix;
-    sum += *(dst+area5) + *(dst+area5+1);
-    *psum = sum;
+    *range = max_pix - min_pix;
+    sum   += *(dst + area5) + *(dst + area5 + 1);
+    *psum  = sum;
 }
 
-
-static const uint16_t zero_prediction_weights[64*2] = {
-    640,  640,  669,  480,  708,  354,  748, 257,  792, 198,  760, 143,  808, 101,  772,  72,
-    480,  669,  537,  537,  598,  416,  661, 316,  719, 250,  707, 185,  768, 134,  745,  97,
-    354,  708,  416,  598,  488,  488,  564, 388,  634, 317,  642, 241,  716, 179,  706, 132,
-    257,  748,  316,  661,  388,  564,  469, 469,  543, 395,  571, 311,  655, 238,  660, 180,
-    198,  792,  250,  719,  317,  634,  395, 543,  469, 469,  507, 380,  597, 299,  616, 231,
-    161,  855,  206,  788,  266,  710,  340, 623,  411, 548,  455, 455,  548, 366,  576, 288,
-    122,  972,  159,  914,  211,  842,  276, 758,  341, 682,  389, 584,  483, 483,  520, 390,
-    110, 1172,  144, 1107,  193, 1028,  254, 932,  317, 846,  366, 731,  458, 611,  499, 499
+static const uint16_t zero_prediction_weights[64 * 2] = {
+    640,  640, 669,  480, 708,  354, 748, 257,
+    792,  198, 760,  143, 808,  101, 772,  72,
+    480,  669, 537,  537, 598,  416, 661, 316,
+    719,  250, 707,  185, 768,  134, 745,  97,
+    354,  708, 416,  598, 488,  488, 564, 388,
+    634,  317, 642,  241, 716,  179, 706, 132,
+    257,  748, 316,  661, 388,  564, 469, 469,
+    543,  395, 571,  311, 655,  238, 660, 180,
+    198,  792, 250,  719, 317,  634, 395, 543,
+    469,  469, 507,  380, 597,  299, 616, 231,
+    161,  855, 206,  788, 266,  710, 340, 623,
+    411,  548, 455,  455, 548,  366, 576, 288,
+    122,  972, 159,  914, 211,  842, 276, 758,
+    341,  682, 389,  584, 483,  483, 520, 390,
+    110, 1172, 144, 1107, 193, 1028, 254, 932,
+    317,  846, 366,  731, 458,  611, 499, 499,
 };
 
-static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){
-    int i,j;
-    int x,y;
-    unsigned int p;//power divided by 2
+static void spatial_compensation_0(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int i, j;
+    int x, y;
+    unsigned int p; // power divided by 2
     int a;
     uint16_t left_sum[2][8] = { { 0 } };
     uint16_t  top_sum[2][8] = { { 0 } };
 
-    for(i=0;i<8;i++){
-        a=src[area2+7-i]<<4;
-        for(j=0;j<8;j++){
-            p=abs(i-j);
-            left_sum[p&1][j]+= a>>(p>>1);
+    for (i = 0; i < 8; i++) {
+        a = src[area2 + 7 - i] << 4;
+        for (j = 0; j < 8; j++) {
+            p                   = abs(i - j);
+            left_sum[p & 1][j] += a >> (p >> 1);
         }
     }
 
-    for(i=0;i<8;i++){
-        a=src[area4+i]<<4;
-        for(j=0;j<8;j++){
-            p=abs(i-j);
-            top_sum[p&1][j]+=   a>>(p>>1);
+    for (i = 0; i < 8; i++) {
+        a = src[area4 + i] << 4;
+        for (j = 0; j < 8; j++) {
+            p                  = abs(i - j);
+            top_sum[p & 1][j] += a >> (p >> 1);
         }
     }
-    for(;i<10;i++){
-        a=src[area4+i]<<4;
-        for(j=5;j<8;j++){
-            p=abs(i-j);
-            top_sum[p&1][j]+=   a>>(p>>1);
+    for (; i < 10; i++) {
+        a = src[area4 + i] << 4;
+        for (j = 5; j < 8; j++) {
+            p                  = abs(i - j);
+            top_sum[p & 1][j] += a >> (p >> 1);
         }
     }
-    for(;i<12;i++){
-        a=src[area4+i]<<4;
-        for(j=7;j<8;j++){
-            p=abs(i-j);
-            top_sum[p&1][j]+=   a>>(p>>1);
+    for (; i < 12; i++) {
+        a = src[area4 + i] << 4;
+        for (j = 7; j < 8; j++) {
+            p                  = abs(i - j);
+            top_sum[p & 1][j] += a >> (p >> 1);
         }
     }
 
-    for(i=0;i<8;i++){
-        top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2
-        left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
+    for (i = 0; i < 8; i++) {
+        top_sum[0][i]  +=  (top_sum[1][i] * 181 + 128) >> 8; // 181 is sqrt(2)/2
+        left_sum[0][i] += (left_sum[1][i] * 181 + 128) >> 8;
     }
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x] = (
-                      (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
-                      (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
-                       0x8000
-                      )>>16;
-        }
-        dst+=linesize;
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = ((uint32_t)  top_sum[0][x] * zero_prediction_weights[y * 16 + x * 2 + 0] +
+                      (uint32_t) left_sum[0][y] * zero_prediction_weights[y * 16 + x * 2 + 1] +
+                      0x8000) >> 16;
+        dst += linesize;
     }
 }
-static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
 
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
-        }
-        dst+=linesize;
+static void spatial_compensation_1(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = src[area4 + FFMIN(2 * y + x + 2, 15)];
+        dst += linesize;
     }
 }
-static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
 
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x]=src[area4 +1+y+x];
-        }
-        dst+=linesize;
+static void spatial_compensation_2(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = src[area4 + 1 + y + x];
+        dst += linesize;
     }
 }
-static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
 
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x]=src[area4 +((y+1)>>1)+x];
-        }
-        dst+=linesize;
+static void spatial_compensation_3(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = src[area4 + ((y + 1) >> 1) + x];
+        dst += linesize;
     }
 }
-static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
 
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
-        }
-        dst+=linesize;
+static void spatial_compensation_4(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = (src[area4 + x] + src[area6 + x] + 1) >> 1;
+        dst += linesize;
     }
 }
-static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
-
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            if(2*x-y<0){
-                dst[x]=src[area2+9+2*x-y];
-            }else{
-                dst[x]=src[area4 +x-((y+1)>>1)];
-            }
+
+static void spatial_compensation_5(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++) {
+            if (2 * x - y < 0)
+                dst[x] = src[area2 + 9 + 2 * x - y];
+            else
+                dst[x] = src[area4 + x - ((y + 1) >> 1)];
         }
-        dst+=linesize;
+        dst += linesize;
     }
 }
-static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
 
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x]=src[area3+x-y];
-        }
-        dst+=linesize;
+static void spatial_compensation_6(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = src[area3 + x - y];
+        dst += linesize;
     }
 }
-static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
-
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            if(x-2*y>0){
-                dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
-            }else{
-                dst[x]=src[area2+8-y +(x>>1)];
-            }
+
+static void spatial_compensation_7(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++) {
+            if (x - 2 * y > 0)
+                dst[x] = (src[area3 - 1 + x - 2 * y] + src[area3 + x - 2 * y] + 1) >> 1;
+            else
+                dst[x] = src[area2 + 8 - y + (x >> 1)];
         }
-        dst+=linesize;
+        dst += linesize;
     }
 }
-static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
 
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
-        }
-        dst+=linesize;
+static void spatial_compensation_8(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = (src[area1 + 7 - y] + src[area2 + 7 - y] + 1) >> 1;
+        dst += linesize;
     }
 }
-static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
 
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x]=src[area2+6-FFMIN(x+y,6)];
-        }
-        dst+=linesize;
+static void spatial_compensation_9(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = src[area2 + 6 - FFMIN(x + y, 6)];
+        dst += linesize;
     }
 }
-static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
 
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
-        }
-        dst+=linesize;
+static void spatial_compensation_10(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = (src[area2 + 7 - y] * (8 - x) + src[area4 + x] * x + 4) >> 3;
+        dst += linesize;
     }
 }
-static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
-    int x,y;
 
-    for(y=0;y<8;y++){
-        for(x=0;x<8;x++){
-            dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
-        }
-        dst+=linesize;
+static void spatial_compensation_11(uint8_t *src, uint8_t *dst, int linesize)
+{
+    int x, y;
+
+    for (y = 0; y < 8; y++) {
+        for (x = 0; x < 8; x++)
+            dst[x] = (src[area2 + 7 - y] * y + src[area4 + x] * (8 - y) + 4) >> 3;
+        dst += linesize;
     }
 }
 
-static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
-    int i,t;
-    int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
-    int ql=(quant+10)>>3;
-
-    for(i=0; i<8; i++,ptr+=b_stride){
-        p0=ptr[-5*a_stride];
-        p1=ptr[-4*a_stride];
-        p2=ptr[-3*a_stride];
-        p3=ptr[-2*a_stride];
-        p4=ptr[-1*a_stride];
-        p5=ptr[ 0         ];
-        p6=ptr[ 1*a_stride];
-        p7=ptr[ 2*a_stride];
-        p8=ptr[ 3*a_stride];
-        p9=ptr[ 4*a_stride];
-
-        t=
-            (FFABS(p1-p2) <= ql) +
-            (FFABS(p2-p3) <= ql) +
-            (FFABS(p3-p4) <= ql) +
-            (FFABS(p4-p5) <= ql);
-        if(t>0){//You need at least 1 to be able to reach a total score of 6.
-            t+=
-                (FFABS(p5-p6) <= ql) +
-                (FFABS(p6-p7) <= ql) +
-                (FFABS(p7-p8) <= ql) +
-                (FFABS(p8-p9) <= ql) +
-                (FFABS(p0-p1) <= ql);
-            if(t>=6){
-                int min,max;
-
-                min=max=p1;
-                min=FFMIN(min,p3); max=FFMAX(max,p3);
-                min=FFMIN(min,p5); max=FFMAX(max,p5);
-                min=FFMIN(min,p8); max=FFMAX(max,p8);
-                if(max-min<2*quant){//early stop
-                    min=FFMIN(min,p2); max=FFMAX(max,p2);
-                    min=FFMIN(min,p4); max=FFMAX(max,p4);
-                    min=FFMIN(min,p6); max=FFMAX(max,p6);
-                    min=FFMIN(min,p7); max=FFMAX(max,p7);
-                    if(max-min<2*quant){
-                        ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
-                        ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
-                        ptr[ 0         ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
-                        ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
+static void x8_loop_filter(uint8_t *ptr, const int a_stride, const int b_stride, int quant)
+{
+    int i, t;
+    int p0, p1, p2, p3, p4, p5, p6, p7, p8, p9;
+    int ql = (quant + 10) >> 3;
+
+    for (i = 0; i < 8; i++, ptr += b_stride) {
+        p0 = ptr[-5 * a_stride];
+        p1 = ptr[-4 * a_stride];
+        p2 = ptr[-3 * a_stride];
+        p3 = ptr[-2 * a_stride];
+        p4 = ptr[-1 * a_stride];
+        p5 = ptr[0];
+        p6 = ptr[1 * a_stride];
+        p7 = ptr[2 * a_stride];
+        p8 = ptr[3 * a_stride];
+        p9 = ptr[4 * a_stride];
+
+        t = (FFABS(p1 - p2) <= ql) +
+            (FFABS(p2 - p3) <= ql) +
+            (FFABS(p3 - p4) <= ql) +
+            (FFABS(p4 - p5) <= ql);
+
+        // You need at least 1 to be able to reach a total score of 6.
+        if (t > 0) {
+            t += (FFABS(p5 - p6) <= ql) +
+                 (FFABS(p6 - p7) <= ql) +
+                 (FFABS(p7 - p8) <= ql) +
+                 (FFABS(p8 - p9) <= ql) +
+                 (FFABS(p0 - p1) <= ql);
+            if (t >= 6) {
+                int min, max;
+
+                min = max = p1;
+                min = FFMIN(min, p3);
+                max = FFMAX(max, p3);
+                min = FFMIN(min, p5);
+                max = FFMAX(max, p5);
+                min = FFMIN(min, p8);
+                max = FFMAX(max, p8);
+                if (max - min < 2 * quant) { // early stop
+                    min = FFMIN(min, p2);
+                    max = FFMAX(max, p2);
+                    min = FFMIN(min, p4);
+                    max = FFMAX(max, p4);
+                    min = FFMIN(min, p6);
+                    max = FFMAX(max, p6);
+                    min = FFMIN(min, p7);
+                    max = FFMAX(max, p7);
+                    if (max - min < 2 * quant) {
+                        ptr[-2 * a_stride] = (4 * p2 + 3 * p3 + 1 * p7 + 4) >> 3;
+                        ptr[-1 * a_stride] = (3 * p2 + 3 * p4 + 2 * p7 + 4) >> 3;
+                        ptr[0]             = (2 * p2 + 3 * p5 + 3 * p7 + 4) >> 3;
+                        ptr[1 * a_stride]  = (1 * p2 + 3 * p6 + 4 * p7 + 4) >> 3;
                         continue;
-                    };
+                    }
                 }
             }
         }
         {
-            int x,x0,x1,x2;
+            int x, x0, x1, x2;
             int m;
 
-            x0 =   (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
-            if(FFABS(x0) < quant){
-                x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
-                x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
+            x0 = (2 * p3 - 5 * p4 + 5 * p5 - 2 * p6 + 4) >> 3;
+            if (FFABS(x0) < quant) {
+                x1 = (2 * p1 - 5 * p2 + 5 * p3 - 2 * p4 + 4) >> 3;
+                x2 = (2 * p5 - 5 * p6 + 5 * p7 - 2 * p8 + 4) >> 3;
 
-                x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
-                m=p4-p5;
+                x = FFABS(x0) - FFMIN(FFABS(x1), FFABS(x2));
+                m = p4 - p5;
 
-                if( x > 0 && (m^x0) <0){
+                if (x > 0 && (m ^ x0) < 0) {
                     int32_t sign;
 
-                    sign=m>>31;
-                    m=(m^sign)-sign;//abs(m)
-                    m>>=1;
+                    sign = m >> 31;
+                    m    = (m ^ sign) - sign; // abs(m)
+                    m  >>= 1;
 
-                    x=(5*x)>>3;
+                    x = 5 * x >> 3;
 
-                    if(x>m) x=m;
+                    if (x > m)
+                        x = m;
 
-                    x=(x^sign)-sign;
+                    x = (x ^ sign) - sign;
 
-                    ptr[-1*a_stride] -= x;
-                    ptr[ 0]          += x;
+                    ptr[-1 * a_stride] -= x;
+                    ptr[0]             += x;
                 }
             }
         }
     }
 }
 
-static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
+static void x8_h_loop_filter(uint8_t *src, int stride, int qscale)
+{
     x8_loop_filter(src, stride, 1, qscale);
 }
 
-static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
+static void x8_v_loop_filter(uint8_t *src, int stride, int qscale)
+{
     x8_loop_filter(src, 1, stride, qscale);
 }
 
 av_cold void ff_intrax8dsp_init(IntraX8DSPContext *dsp)
 {
-    dsp->h_loop_filter=x8_h_loop_filter;
-    dsp->v_loop_filter=x8_v_loop_filter;
-    dsp->setup_spatial_compensation=x8_setup_spatial_compensation;
-    dsp->spatial_compensation[0]=spatial_compensation_0;
-    dsp->spatial_compensation[1]=spatial_compensation_1;
-    dsp->spatial_compensation[2]=spatial_compensation_2;
-    dsp->spatial_compensation[3]=spatial_compensation_3;
-    dsp->spatial_compensation[4]=spatial_compensation_4;
-    dsp->spatial_compensation[5]=spatial_compensation_5;
-    dsp->spatial_compensation[6]=spatial_compensation_6;
-    dsp->spatial_compensation[7]=spatial_compensation_7;
-    dsp->spatial_compensation[8]=spatial_compensation_8;
-    dsp->spatial_compensation[9]=spatial_compensation_9;
-    dsp->spatial_compensation[10]=spatial_compensation_10;
-    dsp->spatial_compensation[11]=spatial_compensation_11;
+    dsp->h_loop_filter              = x8_h_loop_filter;
+    dsp->v_loop_filter              = x8_v_loop_filter;
+    dsp->setup_spatial_compensation = x8_setup_spatial_compensation;
+    dsp->spatial_compensation[0]    = spatial_compensation_0;
+    dsp->spatial_compensation[1]    = spatial_compensation_1;
+    dsp->spatial_compensation[2]    = spatial_compensation_2;
+    dsp->spatial_compensation[3]    = spatial_compensation_3;
+    dsp->spatial_compensation[4]    = spatial_compensation_4;
+    dsp->spatial_compensation[5]    = spatial_compensation_5;
+    dsp->spatial_compensation[6]    = spatial_compensation_6;
+    dsp->spatial_compensation[7]    = spatial_compensation_7;
+    dsp->spatial_compensation[8]    = spatial_compensation_8;
+    dsp->spatial_compensation[9]    = spatial_compensation_9;
+    dsp->spatial_compensation[10]   = spatial_compensation_10;
+    dsp->spatial_compensation[11]   = spatial_compensation_11;
 }
diff --git a/libavcodec/intrax8dsp.h b/libavcodec/intrax8dsp.h
index 1e4a3af..b5d1607 100644
--- a/libavcodec/intrax8dsp.h
+++ b/libavcodec/intrax8dsp.h
@@ -25,9 +25,9 @@ typedef struct IntraX8DSPContext {
     void (*v_loop_filter)(uint8_t *src, int stride, int qscale);
     void (*h_loop_filter)(uint8_t *src, int stride, int qscale);
 
-    void (*spatial_compensation[12])(uint8_t *src , uint8_t *dst, int linesize);
+    void (*spatial_compensation[12])(uint8_t *src, uint8_t *dst, int linesize);
     void (*setup_spatial_compensation)(uint8_t *src, uint8_t *dst, int linesize,
-                                       int *range, int *sum,  int edges);
+                                       int *range, int *sum, int edges);
 } IntraX8DSPContext;
 
 void ff_intrax8dsp_init(IntraX8DSPContext *dsp);
diff --git a/libavcodec/intrax8huf.h b/libavcodec/intrax8huf.h
index 375906b..558d0e5 100644
--- a/libavcodec/intrax8huf.h
+++ b/libavcodec/intrax8huf.h
@@ -21,897 +21,940 @@
 
 #include <inttypes.h>
 
-
-static const uint16_t x8_orient_lowquant_table[4][12][2]={
-    {//0
-        {0x0000,  1}, {0x0004,  3}, {0x0005,  3}, {0x000C,  4},
-        {0x000D,  4}, {0x0038,  6}, {0x001D,  5}, {0x0039,  6},
-        {0x003C,  6}, {0x003D,  6}, {0x003E,  6}, {0x003F,  6},
-    },{//1
-        {0x0000,  5}, {0x0001,  5}, {0x0002,  5}, {0x0001,  2},
-        {0x0002,  2}, {0x0002,  4}, {0x0003,  5}, {0x0006,  3},
-        {0x0003,  4}, {0x000E,  4}, {0x001E,  5}, {0x001F,  5},
-    },{//2
-        {0x0000,  2}, {0x0001,  2}, {0x0004,  3}, {0x0005,  3},
-        {0x0006,  3}, {0x0038,  6}, {0x0039,  6}, {0x001D,  5},
-        {0x003C,  6}, {0x003D,  6}, {0x003E,  6}, {0x003F,  6},
-    },{//3
-        {0x0000,  3}, {0x0002,  4}, {0x0003,  4}, {0x0001,  2},
-        {0x0002,  2}, {0x0018,  5}, {0x0019,  5}, {0x000D,  4},
-        {0x001C,  5}, {0x001D,  5}, {0x001E,  5}, {0x001F,  5},
-    }
+static const uint16_t x8_orient_lowquant_table[4][12][2] = {
+    { // 0
+        { 0x0000, 1 }, { 0x0004, 3 }, { 0x0005, 3 }, { 0x000C, 4 },
+        { 0x000D, 4 }, { 0x0038, 6 }, { 0x001D, 5 }, { 0x0039, 6 },
+        { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, { 0x003F, 6 },
+    },
+    { // 1
+        { 0x0000, 5 }, { 0x0001, 5 }, { 0x0002, 5 }, { 0x0001, 2 },
+        { 0x0002, 2 }, { 0x0002, 4 }, { 0x0003, 5 }, { 0x0006, 3 },
+        { 0x0003, 4 }, { 0x000E, 4 }, { 0x001E, 5 }, { 0x001F, 5 },
+    },
+    { // 2
+        { 0x0000, 2 }, { 0x0001, 2 }, { 0x0004, 3 }, { 0x0005, 3 },
+        { 0x0006, 3 }, { 0x0038, 6 }, { 0x0039, 6 }, { 0x001D, 5 },
+        { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, { 0x003F, 6 },
+    },
+    { // 3
+        { 0x0000, 3 }, { 0x0002, 4 }, { 0x0003, 4 }, { 0x0001, 2 },
+        { 0x0002, 2 }, { 0x0018, 5 }, { 0x0019, 5 }, { 0x000D, 4 },
+        { 0x001C, 5 }, { 0x001D, 5 }, { 0x001E, 5 }, { 0x001F, 5 },
+    },
 };
 
-static const uint16_t x8_orient_highquant_table[2][12][2]={
-    {//0
-        {0x0000,  2}, {0x0001,  2}, {0x0004,  3}, {0x0005,  3},
-        {0x0006,  3}, {0x0038,  6}, {0x001D,  5}, {0x0039,  6},
-        {0x003C,  6}, {0x003D,  6}, {0x003E,  6}, {0x003F,  6},
-    },{//1
-        {0x0000,  1}, {0x0002,  2}, {0x0006,  3}, {0x001C,  5},
-        {0x001D,  5}, {0x0078,  7}, {0x003D,  6}, {0x0079,  7},
-        {0x007C,  7}, {0x007D,  7}, {0x007E,  7}, {0x007F,  7},
-    }
+static const uint16_t x8_orient_highquant_table[2][12][2] = {
+    { // 0
+        { 0x0000, 2 }, { 0x0001, 2 }, { 0x0004, 3 }, { 0x0005, 3 },
+        { 0x0006, 3 }, { 0x0038, 6 }, { 0x001D, 5 }, { 0x0039, 6 },
+        { 0x003C, 6 }, { 0x003D, 6 }, { 0x003E, 6 }, { 0x003F, 6 },
+    },
+    { // 1
+        { 0x0000, 1 }, { 0x0002, 2 }, { 0x0006, 3 }, { 0x001C, 5 },
+        { 0x001D, 5 }, { 0x0078, 7 }, { 0x003D, 6 }, { 0x0079, 7 },
+        { 0x007C, 7 }, { 0x007D, 7 }, { 0x007E, 7 }, { 0x007F, 7 },
+    },
 };
 #define MAX_OR_VLC_BITS 7
 
-
-static const uint16_t x8_dc_lowquant_table[8][34][2]={
-    {//0
-        {0x0000,  5}, {0x0001,  4}, {0x0001,  5}, {0x0004,  5},
-        {0x0005,  5}, {0x0006,  5}, {0x000E,  6}, {0x000F,  6},
-        {0x0040,  8}, {0x0041,  8}, {0x0840, 13}, {0x0841, 13},
-        {0x0842, 13}, {0x0843, 13}, {0x0844, 13}, {0x0845, 13},
-        {0x0846, 13}, {0x0002,  2}, {0x0003,  2}, {0x0003,  3},
-        {0x0005,  4}, {0x0009,  5}, {0x0011,  6}, {0x0043,  8},
-        {0x0085,  9}, {0x0847, 13}, {0x0848, 13}, {0x0849, 13},
-        {0x084A, 13}, {0x084B, 13}, {0x084C, 13}, {0x084D, 13},
-        {0x084E, 13}, {0x084F, 13},
-    },{//1
-        {0x0000,  4}, {0x0001,  3}, {0x0002,  3}, {0x0001,  4},
-        {0x0006,  4}, {0x0004,  3}, {0x0007,  4}, {0x0005,  3},
-        {0x000C,  4}, {0x000D,  4}, {0x001C,  5}, {0x003A,  6},
-        {0x01D8,  9}, {0x01D9,  9}, {0x1DA0, 13}, {0x1DA1, 13},
-        {0x1DA2, 13}, {0x003C,  6}, {0x003D,  6}, {0x003E,  6},
-        {0x0077,  7}, {0x01DB,  9}, {0x007E,  7}, {0x00FE,  8},
-        {0x01FE,  9}, {0x1DA3, 13}, {0x1DA4, 13}, {0x1DA5, 13},
-        {0x0ED3, 12}, {0x0ED4, 12}, {0x01FF,  9}, {0x0ED5, 12},
-        {0x0ED6, 12}, {0x0ED7, 12},
-    },{//2
-        {0x0000,  4}, {0x0001,  3}, {0x0002,  3}, {0x0001,  4},
-        {0x0006,  4}, {0x0007,  4}, {0x0008,  4}, {0x0009,  4},
-        {0x0028,  6}, {0x0029,  6}, {0x0054,  7}, {0x0055,  7},
-        {0x0AC0, 12}, {0x0AC1, 12}, {0x0AC2, 12}, {0x0AC3, 12},
-        {0x0AC4, 12}, {0x000B,  4}, {0x0006,  3}, {0x000E,  4},
-        {0x001E,  5}, {0x003E,  6}, {0x003F,  6}, {0x0057,  7},
-        {0x00AD,  8}, {0x0AC5, 12}, {0x0AC6, 12}, {0x0AC7, 12},
-        {0x0AC8, 12}, {0x0AC9, 12}, {0x0ACA, 12}, {0x0ACB, 12},
-        {0x0566, 11}, {0x0567, 11},
-    },{//3
-        {0x0000,  4}, {0x0001,  2}, {0x0001,  3}, {0x0004,  3},
-        {0x0005,  3}, {0x0006,  3}, {0x0001,  4}, {0x000E,  4},
-        {0x003C,  6}, {0x003D,  6}, {0x007C,  7}, {0x00FA,  8},
-        {0x3EC0, 14}, {0x3EC1, 14}, {0x3EC2, 14}, {0x3EC3, 14},
-        {0x1F62, 13}, {0x01F7,  9}, {0x007E,  7}, {0x00FE,  8},
-        {0x00FF,  8}, {0x1F63, 13}, {0x1F64, 13}, {0x1F65, 13},
-        {0x1F66, 13}, {0x1F67, 13}, {0x1F68, 13}, {0x1F69, 13},
-        {0x1F6A, 13}, {0x1F6B, 13}, {0x1F6C, 13}, {0x1F6D, 13},
-        {0x1F6E, 13}, {0x1F6F, 13},
-    },{//4
-        {0x0000,  7}, {0x0001,  7}, {0x0002,  7}, {0x0003,  7},
-        {0x0004,  7}, {0x0005,  7}, {0x0006,  7}, {0x0007,  7},
-        {0x0008,  7}, {0x0009,  7}, {0x000A,  7}, {0x000B,  7},
-        {0x000C,  7}, {0x000D,  7}, {0x000E,  7}, {0x000F,  7},
-        {0x0010,  7}, {0x0001,  1}, {0x0001,  2}, {0x0011,  7},
-        {0x0012,  7}, {0x0013,  7}, {0x0014,  7}, {0x0015,  7},
-        {0x0016,  7}, {0x0017,  7}, {0x0018,  7}, {0x0019,  7},
-        {0x001A,  7}, {0x001B,  7}, {0x001C,  7}, {0x001D,  7},
-        {0x001E,  7}, {0x001F,  7},
-    },{//5
-        {0x0000,  5}, {0x0001,  4}, {0x0001,  5}, {0x0008,  6},
-        {0x0009,  6}, {0x000A,  6}, {0x0016,  7}, {0x000C,  6},
-        {0x0017,  7}, {0x000D,  6}, {0x0038,  8}, {0x001D,  7},
-        {0x0039,  8}, {0x0780, 13}, {0x0781, 13}, {0x0782, 13},
-        {0x0783, 13}, {0x0002,  3}, {0x0001,  1}, {0x0003,  3},
-        {0x001F,  7}, {0x003D,  8}, {0x0079,  9}, {0x0784, 13},
-        {0x0785, 13}, {0x0786, 13}, {0x0787, 13}, {0x0788, 13},
-        {0x0789, 13}, {0x078A, 13}, {0x078B, 13}, {0x078C, 13},
-        {0x078D, 13}, {0x03C7, 12},
-    },{//6
-        {0x0000,  4}, {0x0001,  2}, {0x0001,  3}, {0x0004,  3},
-        {0x0001,  4}, {0x000A,  4}, {0x0016,  5}, {0x002E,  6},
-        {0x005E,  7}, {0x005F,  7}, {0x00C0,  8}, {0x3040, 14},
-        {0x3041, 14}, {0x0305, 10}, {0x0183,  9}, {0x3042, 14},
-        {0x3043, 14}, {0x000D,  4}, {0x0007,  3}, {0x0019,  5},
-        {0x0031,  6}, {0x00C2,  8}, {0x00C3,  8}, {0x3044, 14},
-        {0x3045, 14}, {0x3046, 14}, {0x3047, 14}, {0x3048, 14},
-        {0x3049, 14}, {0x304A, 14}, {0x304B, 14}, {0x304C, 14},
-        {0x304D, 14}, {0x1827, 13},
-    },{//7
-        {0x0000,  6}, {0x0001,  6}, {0x0002,  6}, {0x0006,  7},
-        {0x0007,  7}, {0x0004,  6}, {0x0005,  6}, {0x0006,  6},
-        {0x000E,  7}, {0x001E,  8}, {0x001F,  8}, {0x0040,  9},
-        {0x0082, 10}, {0x0830, 14}, {0x0831, 14}, {0x0832, 14},
-        {0x0833, 14}, {0x0001,  1}, {0x0001,  2}, {0x0003,  4},
-        {0x0005,  5}, {0x0009,  6}, {0x0011,  7}, {0x0021,  8},
-        {0x0834, 14}, {0x0835, 14}, {0x0836, 14}, {0x0837, 14},
-        {0x0838, 14}, {0x0839, 14}, {0x083A, 14}, {0x083B, 14},
-        {0x041E, 13}, {0x041F, 13},
-    }
+static const uint16_t x8_dc_lowquant_table[8][34][2] = {
+    { // 0
+        { 0x0000,  5 }, { 0x0001,  4 }, { 0x0001,  5 }, { 0x0004,  5 },
+        { 0x0005,  5 }, { 0x0006,  5 }, { 0x000E,  6 }, { 0x000F,  6 },
+        { 0x0040,  8 }, { 0x0041,  8 }, { 0x0840, 13 }, { 0x0841, 13 },
+        { 0x0842, 13 }, { 0x0843, 13 }, { 0x0844, 13 }, { 0x0845, 13 },
+        { 0x0846, 13 }, { 0x0002,  2 }, { 0x0003,  2 }, { 0x0003,  3 },
+        { 0x0005,  4 }, { 0x0009,  5 }, { 0x0011,  6 }, { 0x0043,  8 },
+        { 0x0085,  9 }, { 0x0847, 13 }, { 0x0848, 13 }, { 0x0849, 13 },
+        { 0x084A, 13 }, { 0x084B, 13 }, { 0x084C, 13 }, { 0x084D, 13 },
+        { 0x084E, 13 }, { 0x084F, 13 },
+    },
+    { // 1
+        { 0x0000,  4 }, { 0x0001,  3 }, { 0x0002,  3 }, { 0x0001,  4 },
+        { 0x0006,  4 }, { 0x0004,  3 }, { 0x0007,  4 }, { 0x0005,  3 },
+        { 0x000C,  4 }, { 0x000D,  4 }, { 0x001C,  5 }, { 0x003A,  6 },
+        { 0x01D8,  9 }, { 0x01D9,  9 }, { 0x1DA0, 13 }, { 0x1DA1, 13 },
+        { 0x1DA2, 13 }, { 0x003C,  6 }, { 0x003D,  6 }, { 0x003E,  6 },
+        { 0x0077,  7 }, { 0x01DB,  9 }, { 0x007E,  7 }, { 0x00FE,  8 },
+        { 0x01FE,  9 }, { 0x1DA3, 13 }, { 0x1DA4, 13 }, { 0x1DA5, 13 },
+        { 0x0ED3, 12 }, { 0x0ED4, 12 }, { 0x01FF,  9 }, { 0x0ED5, 12 },
+        { 0x0ED6, 12 }, { 0x0ED7, 12 },
+    },
+    { // 2
+        { 0x0000,  4 }, { 0x0001,  3 }, { 0x0002,  3 }, { 0x0001,  4 },
+        { 0x0006,  4 }, { 0x0007,  4 }, { 0x0008,  4 }, { 0x0009,  4 },
+        { 0x0028,  6 }, { 0x0029,  6 }, { 0x0054,  7 }, { 0x0055,  7 },
+        { 0x0AC0, 12 }, { 0x0AC1, 12 }, { 0x0AC2, 12 }, { 0x0AC3, 12 },
+        { 0x0AC4, 12 }, { 0x000B,  4 }, { 0x0006,  3 }, { 0x000E,  4 },
+        { 0x001E,  5 }, { 0x003E,  6 }, { 0x003F,  6 }, { 0x0057,  7 },
+        { 0x00AD,  8 }, { 0x0AC5, 12 }, { 0x0AC6, 12 }, { 0x0AC7, 12 },
+        { 0x0AC8, 12 }, { 0x0AC9, 12 }, { 0x0ACA, 12 }, { 0x0ACB, 12 },
+        { 0x0566, 11 }, { 0x0567, 11 },
+    },
+    { // 3
+        { 0x0000,  4 }, { 0x0001,  2 }, { 0x0001,  3 }, { 0x0004,  3 },
+        { 0x0005,  3 }, { 0x0006,  3 }, { 0x0001,  4 }, { 0x000E,  4 },
+        { 0x003C,  6 }, { 0x003D,  6 }, { 0x007C,  7 }, { 0x00FA,  8 },
+        { 0x3EC0, 14 }, { 0x3EC1, 14 }, { 0x3EC2, 14 }, { 0x3EC3, 14 },
+        { 0x1F62, 13 }, { 0x01F7,  9 }, { 0x007E,  7 }, { 0x00FE,  8 },
+        { 0x00FF,  8 }, { 0x1F63, 13 }, { 0x1F64, 13 }, { 0x1F65, 13 },
+        { 0x1F66, 13 }, { 0x1F67, 13 }, { 0x1F68, 13 }, { 0x1F69, 13 },
+        { 0x1F6A, 13 }, { 0x1F6B, 13 }, { 0x1F6C, 13 }, { 0x1F6D, 13 },
+        { 0x1F6E, 13 }, { 0x1F6F, 13 },
+    },
+    { // 4
+        { 0x0000,  7 }, { 0x0001,  7 }, { 0x0002,  7 }, { 0x0003,  7 },
+        { 0x0004,  7 }, { 0x0005,  7 }, { 0x0006,  7 }, { 0x0007,  7 },
+        { 0x0008,  7 }, { 0x0009,  7 }, { 0x000A,  7 }, { 0x000B,  7 },
+        { 0x000C,  7 }, { 0x000D,  7 }, { 0x000E,  7 }, { 0x000F,  7 },
+        { 0x0010,  7 }, { 0x0001,  1 }, { 0x0001,  2 }, { 0x0011,  7 },
+        { 0x0012,  7 }, { 0x0013,  7 }, { 0x0014,  7 }, { 0x0015,  7 },
+        { 0x0016,  7 }, { 0x0017,  7 }, { 0x0018,  7 }, { 0x0019,  7 },
+        { 0x001A,  7 }, { 0x001B,  7 }, { 0x001C,  7 }, { 0x001D,  7 },
+        { 0x001E,  7 }, { 0x001F,  7 },
+    },
+    { // 5
+        { 0x0000,  5 }, { 0x0001,  4 }, { 0x0001,  5 }, { 0x0008,  6 },
+        { 0x0009,  6 }, { 0x000A,  6 }, { 0x0016,  7 }, { 0x000C,  6 },
+        { 0x0017,  7 }, { 0x000D,  6 }, { 0x0038,  8 }, { 0x001D,  7 },
+        { 0x0039,  8 }, { 0x0780, 13 }, { 0x0781, 13 }, { 0x0782, 13 },
+        { 0x0783, 13 }, { 0x0002,  3 }, { 0x0001,  1 }, { 0x0003,  3 },
+        { 0x001F,  7 }, { 0x003D,  8 }, { 0x0079,  9 }, { 0x0784, 13 },
+        { 0x0785, 13 }, { 0x0786, 13 }, { 0x0787, 13 }, { 0x0788, 13 },
+        { 0x0789, 13 }, { 0x078A, 13 }, { 0x078B, 13 }, { 0x078C, 13 },
+        { 0x078D, 13 }, { 0x03C7, 12 },
+    },
+    { // 6
+        { 0x0000,  4 }, { 0x0001,  2 }, { 0x0001,  3 }, { 0x0004,  3 },
+        { 0x0001,  4 }, { 0x000A,  4 }, { 0x0016,  5 }, { 0x002E,  6 },
+        { 0x005E,  7 }, { 0x005F,  7 }, { 0x00C0,  8 }, { 0x3040, 14 },
+        { 0x3041, 14 }, { 0x0305, 10 }, { 0x0183,  9 }, { 0x3042, 14 },
+        { 0x3043, 14 }, { 0x000D,  4 }, { 0x0007,  3 }, { 0x0019,  5 },
+        { 0x0031,  6 }, { 0x00C2,  8 }, { 0x00C3,  8 }, { 0x3044, 14 },
+        { 0x3045, 14 }, { 0x3046, 14 }, { 0x3047, 14 }, { 0x3048, 14 },
+        { 0x3049, 14 }, { 0x304A, 14 }, { 0x304B, 14 }, { 0x304C, 14 },
+        { 0x304D, 14 }, { 0x1827, 13 },
+    },
+    { // 7
+        { 0x0000,  6 }, { 0x0001,  6 }, { 0x0002,  6 }, { 0x0006,  7 },
+        { 0x0007,  7 }, { 0x0004,  6 }, { 0x0005,  6 }, { 0x0006,  6 },
+        { 0x000E,  7 }, { 0x001E,  8 }, { 0x001F,  8 }, { 0x0040,  9 },
+        { 0x0082, 10 }, { 0x0830, 14 }, { 0x0831, 14 }, { 0x0832, 14 },
+        { 0x0833, 14 }, { 0x0001,  1 }, { 0x0001,  2 }, { 0x0003,  4 },
+        { 0x0005,  5 }, { 0x0009,  6 }, { 0x0011,  7 }, { 0x0021,  8 },
+        { 0x0834, 14 }, { 0x0835, 14 }, { 0x0836, 14 }, { 0x0837, 14 },
+        { 0x0838, 14 }, { 0x0839, 14 }, { 0x083A, 14 }, { 0x083B, 14 },
+        { 0x041E, 13 }, { 0x041F, 13 },
+    },
 };
 
-static const uint16_t x8_dc_highquant_table[8][34][2]={
-    {//0
-        {0x0000,  5}, {0x0001,  4}, {0x0002,  4}, {0x0001,  5},
-        {0x0006,  5}, {0x0004,  4}, {0x0007,  5}, {0x000A,  5},
-        {0x002C,  7}, {0x002D,  7}, {0x05C0, 12}, {0x05C1, 12},
-        {0x05C2, 12}, {0x05C3, 12}, {0x05C4, 12}, {0x05C5, 12},
-        {0x05C6, 12}, {0x0003,  3}, {0x0002,  2}, {0x0006,  3},
-        {0x000E,  4}, {0x001E,  5}, {0x001F,  5}, {0x002F,  7},
-        {0x005D,  8}, {0x05C7, 12}, {0x05C8, 12}, {0x05C9, 12},
-        {0x05CA, 12}, {0x05CB, 12}, {0x05CC, 12}, {0x05CD, 12},
-        {0x05CE, 12}, {0x05CF, 12},
-    },{//1
-        {0x0000,  3}, {0x0001,  3}, {0x0002,  3}, {0x0006,  4},
-        {0x0007,  4}, {0x0004,  3}, {0x000A,  4}, {0x000B,  4},
-        {0x0030,  6}, {0x0062,  7}, {0x0063,  7}, {0x0640, 11},
-        {0x0641, 11}, {0x0642, 11}, {0x0643, 11}, {0x0644, 11},
-        {0x0645, 11}, {0x0033,  6}, {0x000D,  4}, {0x001C,  5},
-        {0x001D,  5}, {0x003C,  6}, {0x001F,  5}, {0x0065,  7},
-        {0x007A,  7}, {0x0646, 11}, {0x007B,  7}, {0x0647, 11},
-        {0x0648, 11}, {0x0649, 11}, {0x064A, 11}, {0x064B, 11},
-        {0x0326, 10}, {0x0327, 10},
-    },{//2
-        {0x0000,  7}, {0x0001,  7}, {0x0001,  6}, {0x0004,  7},
-        {0x0003,  6}, {0x0005,  7}, {0x0010,  8}, {0x0011,  8},
-        {0x0240, 13}, {0x0241, 13}, {0x0242, 13}, {0x0243, 13},
-        {0x0244, 13}, {0x0245, 13}, {0x0246, 13}, {0x0247, 13},
-        {0x0124, 12}, {0x0001,  1}, {0x0001,  2}, {0x0001,  3},
-        {0x0003,  5}, {0x0005,  6}, {0x0013,  8}, {0x0125, 12},
-        {0x0126, 12}, {0x0127, 12}, {0x0128, 12}, {0x0129, 12},
-        {0x012A, 12}, {0x012B, 12}, {0x012C, 12}, {0x012D, 12},
-        {0x012E, 12}, {0x012F, 12},
-    },{//3
-        {0x0000,  4}, {0x0001,  3}, {0x0002,  3}, {0x0001,  4},
-        {0x0006,  4}, {0x0004,  3}, {0x0005,  3}, {0x0006,  3},
-        {0x000E,  5}, {0x000F,  5}, {0x0070,  7}, {0x0710, 11},
-        {0x0711, 11}, {0x0712, 11}, {0x0713, 11}, {0x0714, 11},
-        {0x0715, 11}, {0x001D,  5}, {0x0072,  7}, {0x003C,  6},
-        {0x003D,  6}, {0x0073,  7}, {0x007C,  7}, {0x007D,  7},
-        {0x007E,  7}, {0x0716, 11}, {0x0717, 11}, {0x0718, 11},
-        {0x007F,  7}, {0x0719, 11}, {0x071A, 11}, {0x071B, 11},
-        {0x038E, 10}, {0x038F, 10},
-    },{//4
-        {0x0000,  8}, {0x0001,  7}, {0x0002,  7}, {0x0003,  7},
-        {0x0002,  9}, {0x0008,  8}, {0x0003,  9}, {0x0240, 14},
-        {0x0241, 14}, {0x0242, 14}, {0x0243, 14}, {0x0244, 14},
-        {0x0245, 14}, {0x0246, 14}, {0x0247, 14}, {0x0124, 13},
-        {0x0125, 13}, {0x0001,  2}, {0x0001,  1}, {0x0001,  3},
-        {0x0001,  4}, {0x0003,  6}, {0x0005,  7}, {0x0013,  9},
-        {0x0126, 13}, {0x0127, 13}, {0x0128, 13}, {0x0129, 13},
-        {0x012A, 13}, {0x012B, 13}, {0x012C, 13}, {0x012D, 13},
-        {0x012E, 13}, {0x012F, 13},
-    },{//5
-        {0x0000,  7}, {0x0001,  7}, {0x0001,  6}, {0x0002,  6},
-        {0x0003,  6}, {0x0004,  6}, {0x0005,  6}, {0x0006,  6},
-        {0x0007,  6}, {0x0008,  6}, {0x0009,  6}, {0x000A,  6},
-        {0x000B,  6}, {0x000C,  6}, {0x000D,  6}, {0x000E,  6},
-        {0x000F,  6}, {0x0010,  6}, {0x0011,  6}, {0x0012,  6},
-        {0x0013,  6}, {0x0014,  6}, {0x0015,  6}, {0x0016,  6},
-        {0x0017,  6}, {0x0018,  6}, {0x0019,  6}, {0x0001,  1},
-        {0x001A,  6}, {0x001B,  6}, {0x001C,  6}, {0x001D,  6},
-        {0x001E,  6}, {0x001F,  6},
-    },{//6
-        {0x0000,  5}, {0x0001,  4}, {0x0001,  5}, {0x0004,  5},
-        {0x000A,  6}, {0x0006,  5}, {0x000B,  6}, {0x000E,  6},
-        {0x003C,  8}, {0x003D,  8}, {0x07C0, 13}, {0x07C1, 13},
-        {0x07C2, 13}, {0x07C3, 13}, {0x07C4, 13}, {0x07C5, 13},
-        {0x07C6, 13}, {0x0001,  2}, {0x0002,  2}, {0x0006,  3},
-        {0x000E,  4}, {0x001E,  5}, {0x001F,  5}, {0x003F,  8},
-        {0x007D,  9}, {0x07C7, 13}, {0x07C8, 13}, {0x07C9, 13},
-        {0x07CA, 13}, {0x07CB, 13}, {0x07CC, 13}, {0x07CD, 13},
-        {0x07CE, 13}, {0x07CF, 13},
-    },{//7
-        {0x0000,  7}, {0x0001,  7}, {0x0002,  7}, {0x0003,  7},
-        {0x0004,  7}, {0x0005,  7}, {0x0006,  7}, {0x0007,  7},
-        {0x0008,  7}, {0x0009,  7}, {0x000A,  7}, {0x000B,  7},
-        {0x000C,  7}, {0x000D,  7}, {0x000E,  7}, {0x000F,  7},
-        {0x0010,  7}, {0x0001,  1}, {0x0001,  2}, {0x0011,  7},
-        {0x0012,  7}, {0x0013,  7}, {0x0014,  7}, {0x0015,  7},
-        {0x0016,  7}, {0x0017,  7}, {0x0018,  7}, {0x0019,  7},
-        {0x001A,  7}, {0x001B,  7}, {0x001C,  7}, {0x001D,  7},
-        {0x001E,  7}, {0x001F,  7},
-    }
+static const uint16_t x8_dc_highquant_table[8][34][2] = {
+    { // 0
+        { 0x0000,  5 }, { 0x0001,  4 }, { 0x0002,  4 }, { 0x0001,  5 },
+        { 0x0006,  5 }, { 0x0004,  4 }, { 0x0007,  5 }, { 0x000A,  5 },
+        { 0x002C,  7 }, { 0x002D,  7 }, { 0x05C0, 12 }, { 0x05C1, 12 },
+        { 0x05C2, 12 }, { 0x05C3, 12 }, { 0x05C4, 12 }, { 0x05C5, 12 },
+        { 0x05C6, 12 }, { 0x0003,  3 }, { 0x0002,  2 }, { 0x0006,  3 },
+        { 0x000E,  4 }, { 0x001E,  5 }, { 0x001F,  5 }, { 0x002F,  7 },
+        { 0x005D,  8 }, { 0x05C7, 12 }, { 0x05C8, 12 }, { 0x05C9, 12 },
+        { 0x05CA, 12 }, { 0x05CB, 12 }, { 0x05CC, 12 }, { 0x05CD, 12 },
+        { 0x05CE, 12 }, { 0x05CF, 12 },
+    },
+    { // 1
+        { 0x0000,  3 }, { 0x0001,  3 }, { 0x0002,  3 }, { 0x0006,  4 },
+        { 0x0007,  4 }, { 0x0004,  3 }, { 0x000A,  4 }, { 0x000B,  4 },
+        { 0x0030,  6 }, { 0x0062,  7 }, { 0x0063,  7 }, { 0x0640, 11 },
+        { 0x0641, 11 }, { 0x0642, 11 }, { 0x0643, 11 }, { 0x0644, 11 },
+        { 0x0645, 11 }, { 0x0033,  6 }, { 0x000D,  4 }, { 0x001C,  5 },
+        { 0x001D,  5 }, { 0x003C,  6 }, { 0x001F,  5 }, { 0x0065,  7 },
+        { 0x007A,  7 }, { 0x0646, 11 }, { 0x007B,  7 }, { 0x0647, 11 },
+        { 0x0648, 11 }, { 0x0649, 11 }, { 0x064A, 11 }, { 0x064B, 11 },
+        { 0x0326, 10 }, { 0x0327, 10 },
+    },
+    { // 2
+        { 0x0000,  7 }, { 0x0001,  7 }, { 0x0001,  6 }, { 0x0004,  7 },
+        { 0x0003,  6 }, { 0x0005,  7 }, { 0x0010,  8 }, { 0x0011,  8 },
+        { 0x0240, 13 }, { 0x0241, 13 }, { 0x0242, 13 }, { 0x0243, 13 },
+        { 0x0244, 13 }, { 0x0245, 13 }, { 0x0246, 13 }, { 0x0247, 13 },
+        { 0x0124, 12 }, { 0x0001,  1 }, { 0x0001,  2 }, { 0x0001,  3 },
+        { 0x0003,  5 }, { 0x0005,  6 }, { 0x0013,  8 }, { 0x0125, 12 },
+        { 0x0126, 12 }, { 0x0127, 12 }, { 0x0128, 12 }, { 0x0129, 12 },
+        { 0x012A, 12 }, { 0x012B, 12 }, { 0x012C, 12 }, { 0x012D, 12 },
+        { 0x012E, 12 }, { 0x012F, 12 },
+    },
+    { // 3
+        { 0x0000,  4 }, { 0x0001,  3 }, { 0x0002,  3 }, { 0x0001,  4 },
+        { 0x0006,  4 }, { 0x0004,  3 }, { 0x0005,  3 }, { 0x0006,  3 },
+        { 0x000E,  5 }, { 0x000F,  5 }, { 0x0070,  7 }, { 0x0710, 11 },
+        { 0x0711, 11 }, { 0x0712, 11 }, { 0x0713, 11 }, { 0x0714, 11 },
+        { 0x0715, 11 }, { 0x001D,  5 }, { 0x0072,  7 }, { 0x003C,  6 },
+        { 0x003D,  6 }, { 0x0073,  7 }, { 0x007C,  7 }, { 0x007D,  7 },
+        { 0x007E,  7 }, { 0x0716, 11 }, { 0x0717, 11 }, { 0x0718, 11 },
+        { 0x007F,  7 }, { 0x0719, 11 }, { 0x071A, 11 }, { 0x071B, 11 },
+        { 0x038E, 10 }, { 0x038F, 10 },
+    },
+    { // 4
+        { 0x0000,  8 }, { 0x0001,  7 }, { 0x0002,  7 }, { 0x0003,  7 },
+        { 0x0002,  9 }, { 0x0008,  8 }, { 0x0003,  9 }, { 0x0240, 14 },
+        { 0x0241, 14 }, { 0x0242, 14 }, { 0x0243, 14 }, { 0x0244, 14 },
+        { 0x0245, 14 }, { 0x0246, 14 }, { 0x0247, 14 }, { 0x0124, 13 },
+        { 0x0125, 13 }, { 0x0001,  2 }, { 0x0001,  1 }, { 0x0001,  3 },
+        { 0x0001,  4 }, { 0x0003,  6 }, { 0x0005,  7 }, { 0x0013,  9 },
+        { 0x0126, 13 }, { 0x0127, 13 }, { 0x0128, 13 }, { 0x0129, 13 },
+        { 0x012A, 13 }, { 0x012B, 13 }, { 0x012C, 13 }, { 0x012D, 13 },
+        { 0x012E, 13 }, { 0x012F, 13 },
+    },
+    { // 5
+        { 0x0000,  7 }, { 0x0001,  7 }, { 0x0001,  6 }, { 0x0002,  6 },
+        { 0x0003,  6 }, { 0x0004,  6 }, { 0x0005,  6 }, { 0x0006,  6 },
+        { 0x0007,  6 }, { 0x0008,  6 }, { 0x0009,  6 }, { 0x000A,  6 },
+        { 0x000B,  6 }, { 0x000C,  6 }, { 0x000D,  6 }, { 0x000E,  6 },
+        { 0x000F,  6 }, { 0x0010,  6 }, { 0x0011,  6 }, { 0x0012,  6 },
+        { 0x0013,  6 }, { 0x0014,  6 }, { 0x0015,  6 }, { 0x0016,  6 },
+        { 0x0017,  6 }, { 0x0018,  6 }, { 0x0019,  6 }, { 0x0001,  1 },
+        { 0x001A,  6 }, { 0x001B,  6 }, { 0x001C,  6 }, { 0x001D,  6 },
+        { 0x001E,  6 }, { 0x001F,  6 },
+    },
+    { // 6
+        { 0x0000,  5 }, { 0x0001,  4 }, { 0x0001,  5 }, { 0x0004,  5 },
+        { 0x000A,  6 }, { 0x0006,  5 }, { 0x000B,  6 }, { 0x000E,  6 },
+        { 0x003C,  8 }, { 0x003D,  8 }, { 0x07C0, 13 }, { 0x07C1, 13 },
+        { 0x07C2, 13 }, { 0x07C3, 13 }, { 0x07C4, 13 }, { 0x07C5, 13 },
+        { 0x07C6, 13 }, { 0x0001,  2 }, { 0x0002,  2 }, { 0x0006,  3 },
+        { 0x000E,  4 }, { 0x001E,  5 }, { 0x001F,  5 }, { 0x003F,  8 },
+        { 0x007D,  9 }, { 0x07C7, 13 }, { 0x07C8, 13 }, { 0x07C9, 13 },
+        { 0x07CA, 13 }, { 0x07CB, 13 }, { 0x07CC, 13 }, { 0x07CD, 13 },
+        { 0x07CE, 13 }, { 0x07CF, 13 },
+    },
+    { // 7
+        { 0x0000,  7 }, { 0x0001,  7 }, { 0x0002,  7 }, { 0x0003,  7 },
+        { 0x0004,  7 }, { 0x0005,  7 }, { 0x0006,  7 }, { 0x0007,  7 },
+        { 0x0008,  7 }, { 0x0009,  7 }, { 0x000A,  7 }, { 0x000B,  7 },
+        { 0x000C,  7 }, { 0x000D,  7 }, { 0x000E,  7 }, { 0x000F,  7 },
+        { 0x0010,  7 }, { 0x0001,  1 }, { 0x0001,  2 }, { 0x0011,  7 },
+        { 0x0012,  7 }, { 0x0013,  7 }, { 0x0014,  7 }, { 0x0015,  7 },
+        { 0x0016,  7 }, { 0x0017,  7 }, { 0x0018,  7 }, { 0x0019,  7 },
+        { 0x001A,  7 }, { 0x001B,  7 }, { 0x001C,  7 }, { 0x001D,  7 },
+        { 0x001E,  7 }, { 0x001F,  7 },
+    },
 };
 #define MAX_DC_VLC_BITS 14
 
-
-static const uint16_t x8_ac0_lowquant_table[8][77][2]={
-    {//0
-        {0x0000,  2}, {0x0002,  3}, {0x0006,  4}, {0x000E,  5},
-        {0x001E,  6}, {0x003E,  7}, {0x003F,  7}, {0x0040,  7},
-        {0x0104,  9}, {0x0083,  8}, {0x0084,  8}, {0x0085,  8},
-        {0x020A, 10}, {0x020B, 10}, {0x0218, 10}, {0x0219, 10},
-        {0x0009,  4}, {0x0044,  7}, {0x010D,  9}, {0x021C, 10},
-        {0x0023,  6}, {0x0045,  7}, {0x0050,  7}, {0x000B,  4},
-        {0x000C,  4}, {0x0015,  5}, {0x001A,  5}, {0x001B,  5},
-        {0x0029,  6}, {0x0038,  6}, {0x0039,  6}, {0x003A,  6},
-        {0x0051,  7}, {0x0076,  7}, {0x0077,  7}, {0x0078,  7},
-        {0x0079,  7}, {0x007A,  7}, {0x007B,  7}, {0x00F8,  8},
-        {0x010F,  9}, {0x021D, 10}, {0x3E40, 14}, {0x3E41, 14},
-        {0x3E42, 14}, {0x3E43, 14}, {0x03E5, 10}, {0x3E44, 14},
-        {0x01F3,  9}, {0x3E45, 14}, {0x3E46, 14}, {0x3E47, 14},
-        {0x00FA,  8}, {0x3E48, 14}, {0x3E49, 14}, {0x3E4A, 14},
-        {0x3E4B, 14}, {0x03EC, 10}, {0x3E4C, 14}, {0x007E,  7},
-        {0x00FE,  8}, {0x00FF,  8}, {0x01F7,  9}, {0x3E4D, 14},
-        {0x3E4E, 14}, {0x3E4F, 14}, {0x3ED0, 14}, {0x3ED1, 14},
-        {0x3ED2, 14}, {0x3ED3, 14}, {0x3ED4, 14}, {0x3ED5, 14},
-        {0x1F6B, 13}, {0x1F6C, 13}, {0x1F6D, 13}, {0x1F6E, 13},
-        {0x1F6F, 13},
-    },{//1
-        {0x0000,  3}, {0x0004,  5}, {0x0014,  7}, {0x000B,  6},
-        {0x000C,  6}, {0x002A,  8}, {0x002B,  8}, {0x0034,  8},
-        {0x0D40, 14}, {0x0D41, 14}, {0x001B,  7}, {0x0D42, 14},
-        {0x0D43, 14}, {0x0D44, 14}, {0x0D45, 14}, {0x0D46, 14},
-        {0x000E,  6}, {0x003C,  8}, {0x0D47, 14}, {0x003D,  8},
-        {0x0D48, 14}, {0x0D49, 14}, {0x0D4A, 14}, {0x0001,  2},
-        {0x0004,  3}, {0x0014,  5}, {0x000B,  4}, {0x000C,  4},
-        {0x000D,  4}, {0x002A,  6}, {0x001F,  7}, {0x0056,  7},
-        {0x0057,  7}, {0x0070,  7}, {0x00E2,  8}, {0x0072,  7},
-        {0x003A,  6}, {0x003B,  6}, {0x003C,  6}, {0x003D,  6},
-        {0x00E3,  8}, {0x0D4B, 14}, {0x00E6,  8}, {0x00E7,  8},
-        {0x00F8,  8}, {0x0D4C, 14}, {0x0D4D, 14}, {0x0D4E, 14},
-        {0x00F9,  8}, {0x0D4F, 14}, {0x0D50, 14}, {0x0D51, 14},
-        {0x06A9, 13}, {0x06AA, 13}, {0x06AB, 13}, {0x06AC, 13},
-        {0x06AD, 13}, {0x06AE, 13}, {0x06AF, 13}, {0x003F,  6},
-        {0x06B0, 13}, {0x06B1, 13}, {0x06B2, 13}, {0x06B3, 13},
-        {0x06B4, 13}, {0x007D,  7}, {0x06B5, 13}, {0x06B6, 13},
-        {0x06B7, 13}, {0x06B8, 13}, {0x06B9, 13}, {0x06BA, 13},
-        {0x06BB, 13}, {0x06BC, 13}, {0x06BD, 13}, {0x06BE, 13},
-        {0x06BF, 13},
-    },{//2
-        {0x0000,  2}, {0x0002,  3}, {0x0003,  3}, {0x0008,  4},
-        {0x0012,  5}, {0x0013,  5}, {0x0028,  6}, {0x0029,  6},
-        {0x0054,  7}, {0x0055,  7}, {0x0056,  7}, {0x00AE,  8},
-        {0x00AF,  8}, {0x00B0,  8}, {0x0162,  9}, {0x02C6, 10},
-        {0x000C,  4}, {0x002D,  6}, {0x00B2,  8}, {0x0166,  9},
-        {0x002E,  6}, {0x0167,  9}, {0x00BC,  8}, {0x001A,  5},
-        {0x0036,  6}, {0x0037,  6}, {0x0038,  6}, {0x005F,  7},
-        {0x0072,  7}, {0x0073,  7}, {0x0074,  7}, {0x0075,  7},
-        {0x0076,  7}, {0x0077,  7}, {0x0078,  7}, {0x0079,  7},
-        {0x007A,  7}, {0x007B,  7}, {0x00BD,  8}, {0xB1C0, 16},
-        {0xB1C1, 16}, {0x58E1, 15}, {0x0B1D, 12}, {0x58E2, 15},
-        {0x58E3, 15}, {0x58E4, 15}, {0x00F8,  8}, {0x03E4, 10},
-        {0x01F3,  9}, {0x0B1E, 12}, {0x58E5, 15}, {0x58E6, 15},
-        {0x00FA,  8}, {0x58E7, 15}, {0x58F8, 15}, {0x58F9, 15},
-        {0x58FA, 15}, {0x01F6,  9}, {0x58FB, 15}, {0x007E,  7},
-        {0x00FE,  8}, {0x00FF,  8}, {0x07CA, 11}, {0x0F96, 12},
-        {0x58FC, 15}, {0x58FD, 15}, {0x58FE, 15}, {0x58FF, 15},
-        {0x7CB8, 15}, {0x7CB9, 15}, {0x7CBA, 15}, {0x7CBB, 15},
-        {0x7CBC, 15}, {0x01F7,  9}, {0x7CBD, 15}, {0x7CBE, 15},
-        {0x7CBF, 15},
-    },{//3
-        {0x0000,  2}, {0x0002,  3}, {0x0006,  4}, {0x000E,  5},
-        {0x000F,  5}, {0x0020,  6}, {0x0021,  6}, {0x0044,  7},
-        {0x0045,  7}, {0x008C,  8}, {0x008D,  8}, {0x011C,  9},
-        {0x011D,  9}, {0x011E,  9}, {0x023E, 10}, {0x023F, 10},
-        {0x0005,  3}, {0x0012,  5}, {0x004C,  7}, {0x004D,  7},
-        {0x000C,  4}, {0x004E,  7}, {0x001A,  5}, {0x0036,  6},
-        {0x004F,  7}, {0x006E,  7}, {0x006F,  7}, {0x00E0,  8},
-        {0x00E1,  8}, {0x00E2,  8}, {0x00E3,  8}, {0x00E4,  8},
-        {0x00E5,  8}, {0x01CC,  9}, {0x00E7,  8}, {0x00E8,  8},
-        {0x00E9,  8}, {0x01CD,  9}, {0x0750, 11}, {0x03A9, 10},
-        {0x0751, 11}, {0x7540, 15}, {0x03AB, 10}, {0x7541, 15},
-        {0x7542, 15}, {0x7543, 15}, {0x01D6,  9}, {0x0755, 11},
-        {0x0076,  7}, {0x0EA9, 12}, {0x7544, 15}, {0x7545, 15},
-        {0x001E,  5}, {0x0077,  7}, {0x00F8,  8}, {0x03AE, 10},
-        {0x075E, 11}, {0x007D,  7}, {0x03E4, 10}, {0x00FC,  8},
-        {0x00FD,  8}, {0x03E5, 10}, {0x03E6, 10}, {0x0EBE, 12},
-        {0x7546, 15}, {0x07CE, 11}, {0x7547, 15}, {0x75F8, 15},
-        {0x75F9, 15}, {0x75FA, 15}, {0x75FB, 15}, {0x75FC, 15},
-        {0x75FD, 15}, {0x007F,  7}, {0x3AFF, 14}, {0x0F9E, 12},
-        {0x0F9F, 12},
-    },{//4
-        {0x0000,  3}, {0x0002,  4}, {0x0003,  4}, {0x0008,  5},
-        {0x0012,  6}, {0x0013,  6}, {0x0014,  6}, {0x002A,  7},
-        {0x0016,  6}, {0x002B,  7}, {0x005C,  8}, {0x005D,  8},
-        {0x005E,  8}, {0x00BE,  9}, {0x00BF,  9}, {0x0060,  8},
-        {0x0007,  4}, {0x000D,  5}, {0x0019,  6}, {0x0020,  6},
-        {0x0009,  4}, {0x0021,  6}, {0x0011,  5}, {0x0014,  5},
-        {0x002A,  6}, {0x002B,  6}, {0x002C,  6}, {0x002D,  6},
-        {0x002E,  6}, {0x002F,  6}, {0x0030,  6}, {0x0031,  7},
-        {0x0062,  7}, {0x0063,  7}, {0x0064,  7}, {0x0065,  7},
-        {0x0066,  7}, {0x0061,  8}, {0x0670, 11}, {0x0068,  7},
-        {0x0069,  7}, {0x00CF,  8}, {0x019D,  9}, {0x01A8,  9},
-        {0x01A9,  9}, {0x0339, 10}, {0x01AA,  9}, {0x0356, 10},
-        {0x0036,  6}, {0x00D6,  8}, {0x6710, 15}, {0x6711, 15},
-        {0x000E,  4}, {0x006E,  7}, {0x01AE,  9}, {0x6712, 15},
-        {0x6713, 15}, {0x003C,  6}, {0x0357, 10}, {0x006F,  7},
-        {0x00F4,  8}, {0x00F5,  8}, {0x035E, 10}, {0x01EC,  9},
-        {0x6714, 15}, {0x01ED,  9}, {0x035F, 10}, {0x03DC, 10},
-        {0x03DD, 10}, {0x6715, 15}, {0x338B, 14}, {0x338C, 14},
-        {0x338D, 14}, {0x001F,  5}, {0x01EF,  9}, {0x338E, 14},
-        {0x338F, 14},
-    },{//5
-        {0x0000,  2}, {0x0004,  4}, {0x000A,  5}, {0x000B,  5},
-        {0x0018,  6}, {0x0019,  6}, {0x0034,  7}, {0x006A,  8},
-        {0x006B,  8}, {0x006C,  8}, {0x00DA,  9}, {0x036C, 11},
-        {0x006E,  8}, {0x01B7, 10}, {0x036D, 11}, {0x3780, 15},
-        {0x0004,  3}, {0x000E,  5}, {0x001E,  6}, {0x003E,  7},
-        {0x000A,  4}, {0x002C,  6}, {0x0017,  5}, {0x002D,  6},
-        {0x003F,  7}, {0x00C0,  8}, {0x0061,  7}, {0x00C1,  8},
-        {0x0062,  7}, {0x00C6,  8}, {0x0064,  7}, {0x00C7,  8},
-        {0x00CA,  8}, {0x00DF,  9}, {0x0196,  9}, {0x0197,  9},
-        {0x0198,  9}, {0x0199,  9}, {0x0379, 11}, {0x019A,  9},
-        {0x01BD, 10}, {0x066C, 11}, {0x3781, 15}, {0x0337, 10},
-        {0x066D, 11}, {0x0670, 11}, {0x0339, 10}, {0x0671, 11},
-        {0x0034,  6}, {0x00CF,  8}, {0x3782, 15}, {0x3783, 15},
-        {0x000E,  4}, {0x001B,  5}, {0x006A,  7}, {0x006B,  7},
-        {0x019D,  9}, {0x003C,  6}, {0x00F4,  8}, {0x00F5,  8},
-        {0x03D8, 10}, {0x07B2, 11}, {0x3784, 15}, {0x03DA, 10},
-        {0x3785, 15}, {0x03DB, 10}, {0x03DC, 10}, {0x3786, 15},
-        {0x3787, 15}, {0x1BC4, 14}, {0x1BC5, 14}, {0x1BC6, 14},
-        {0x1BC7, 14}, {0x001F,  5}, {0x03DD, 10}, {0x07B3, 11},
-        {0x01EF,  9},
-    },{//6
-        {0x0000,  2}, {0x0004,  4}, {0x000A,  5}, {0x0016,  6},
-        {0x0017,  6}, {0x0060,  8}, {0x00C2,  9}, {0x0186, 10},
-        {0x0187, 10}, {0x00C4,  9}, {0x3140, 15}, {0x3141, 15},
-        {0x018B, 10}, {0x3142, 15}, {0x018C, 10}, {0x3143, 15},
-        {0x0007,  4}, {0x000D,  5}, {0x0064,  8}, {0x0065,  8},
-        {0x0010,  5}, {0x00C7,  9}, {0x0066,  8}, {0x0005,  3},
-        {0x0006,  3}, {0x0009,  4}, {0x0011,  5}, {0x0038,  6},
-        {0x0039,  6}, {0x0074,  7}, {0x0075,  7}, {0x0076,  7},
-        {0x0067,  8}, {0x00EE,  8}, {0x01DE,  9}, {0x00F0,  8},
-        {0x018D, 10}, {0x3144, 15}, {0x01DF,  9}, {0x003D,  6},
-        {0x003E,  6}, {0x01E2,  9}, {0x03C6, 10}, {0x00F2,  8},
-        {0x00F3,  8}, {0x03C7, 10}, {0x3145, 15}, {0x3146, 15},
-        {0x01F8,  9}, {0x3147, 15}, {0x3148, 15}, {0x3149, 15},
-        {0x00FD,  8}, {0x314A, 15}, {0x314B, 15}, {0x314C, 15},
-        {0x314D, 15}, {0x01F9,  9}, {0x314E, 15}, {0x01FC,  9},
-        {0x314F, 15}, {0x3150, 15}, {0x3151, 15}, {0x3152, 15},
-        {0x3153, 15}, {0x03FA, 10}, {0x03FB, 10}, {0x3154, 15},
-        {0x3155, 15}, {0x3156, 15}, {0x3157, 15}, {0x3158, 15},
-        {0x3159, 15}, {0x00FF,  8}, {0x18AD, 14}, {0x18AE, 14},
-        {0x18AF, 14},
-    },{//7
-        {0x0000,  4}, {0x0080, 11}, {0x0081, 11}, {0x0082, 11},
-        {0x0083, 11}, {0x0084, 11}, {0x0085, 11}, {0x0086, 11},
-        {0x0087, 11}, {0x0088, 11}, {0x0089, 11}, {0x008A, 11},
-        {0x008B, 11}, {0x008C, 11}, {0x008D, 11}, {0x008E, 11},
-        {0x008F, 11}, {0x0048, 10}, {0x0049, 10}, {0x004A, 10},
-        {0x004B, 10}, {0x004C, 10}, {0x004D, 10}, {0x0001,  1},
-        {0x0001,  2}, {0x004E, 10}, {0x0002,  4}, {0x0003,  4},
-        {0x004F, 10}, {0x0050, 10}, {0x0051, 10}, {0x0052, 10},
-        {0x0053, 10}, {0x0054, 10}, {0x0055, 10}, {0x0056, 10},
-        {0x0057, 10}, {0x0058, 10}, {0x0059, 10}, {0x005A, 10},
-        {0x005B, 10}, {0x005C, 10}, {0x005D, 10}, {0x005E, 10},
-        {0x005F, 10}, {0x0060, 10}, {0x0061, 10}, {0x0062, 10},
-        {0x0063, 10}, {0x0064, 10}, {0x0065, 10}, {0x0066, 10},
-        {0x0067, 10}, {0x0068, 10}, {0x0069, 10}, {0x006A, 10},
-        {0x006B, 10}, {0x006C, 10}, {0x006D, 10}, {0x006E, 10},
-        {0x006F, 10}, {0x0070, 10}, {0x0071, 10}, {0x0072, 10},
-        {0x0073, 10}, {0x0074, 10}, {0x0075, 10}, {0x0076, 10},
-        {0x0077, 10}, {0x0078, 10}, {0x0079, 10}, {0x007A, 10},
-        {0x007B, 10}, {0x007C, 10}, {0x007D, 10}, {0x007E, 10},
-        {0x007F, 10},
-    }
+static const uint16_t x8_ac0_lowquant_table[8][77][2] = {
+    { // 0
+        { 0x0000,  2 }, { 0x0002,  3 }, { 0x0006,  4 }, { 0x000E,  5 },
+        { 0x001E,  6 }, { 0x003E,  7 }, { 0x003F,  7 }, { 0x0040,  7 },
+        { 0x0104,  9 }, { 0x0083,  8 }, { 0x0084,  8 }, { 0x0085,  8 },
+        { 0x020A, 10 }, { 0x020B, 10 }, { 0x0218, 10 }, { 0x0219, 10 },
+        { 0x0009,  4 }, { 0x0044,  7 }, { 0x010D,  9 }, { 0x021C, 10 },
+        { 0x0023,  6 }, { 0x0045,  7 }, { 0x0050,  7 }, { 0x000B,  4 },
+        { 0x000C,  4 }, { 0x0015,  5 }, { 0x001A,  5 }, { 0x001B,  5 },
+        { 0x0029,  6 }, { 0x0038,  6 }, { 0x0039,  6 }, { 0x003A,  6 },
+        { 0x0051,  7 }, { 0x0076,  7 }, { 0x0077,  7 }, { 0x0078,  7 },
+        { 0x0079,  7 }, { 0x007A,  7 }, { 0x007B,  7 }, { 0x00F8,  8 },
+        { 0x010F,  9 }, { 0x021D, 10 }, { 0x3E40, 14 }, { 0x3E41, 14 },
+        { 0x3E42, 14 }, { 0x3E43, 14 }, { 0x03E5, 10 }, { 0x3E44, 14 },
+        { 0x01F3,  9 }, { 0x3E45, 14 }, { 0x3E46, 14 }, { 0x3E47, 14 },
+        { 0x00FA,  8 }, { 0x3E48, 14 }, { 0x3E49, 14 }, { 0x3E4A, 14 },
+        { 0x3E4B, 14 }, { 0x03EC, 10 }, { 0x3E4C, 14 }, { 0x007E,  7 },
+        { 0x00FE,  8 }, { 0x00FF,  8 }, { 0x01F7,  9 }, { 0x3E4D, 14 },
+        { 0x3E4E, 14 }, { 0x3E4F, 14 }, { 0x3ED0, 14 }, { 0x3ED1, 14 },
+        { 0x3ED2, 14 }, { 0x3ED3, 14 }, { 0x3ED4, 14 }, { 0x3ED5, 14 },
+        { 0x1F6B, 13 }, { 0x1F6C, 13 }, { 0x1F6D, 13 }, { 0x1F6E, 13 },
+        { 0x1F6F, 13 },
+    },
+    { // 1
+        { 0x0000,  3 }, { 0x0004,  5 }, { 0x0014,  7 }, { 0x000B,  6 },
+        { 0x000C,  6 }, { 0x002A,  8 }, { 0x002B,  8 }, { 0x0034,  8 },
+        { 0x0D40, 14 }, { 0x0D41, 14 }, { 0x001B,  7 }, { 0x0D42, 14 },
+        { 0x0D43, 14 }, { 0x0D44, 14 }, { 0x0D45, 14 }, { 0x0D46, 14 },
+        { 0x000E,  6 }, { 0x003C,  8 }, { 0x0D47, 14 }, { 0x003D,  8 },
+        { 0x0D48, 14 }, { 0x0D49, 14 }, { 0x0D4A, 14 }, { 0x0001,  2 },
+        { 0x0004,  3 }, { 0x0014,  5 }, { 0x000B,  4 }, { 0x000C,  4 },
+        { 0x000D,  4 }, { 0x002A,  6 }, { 0x001F,  7 }, { 0x0056,  7 },
+        { 0x0057,  7 }, { 0x0070,  7 }, { 0x00E2,  8 }, { 0x0072,  7 },
+        { 0x003A,  6 }, { 0x003B,  6 }, { 0x003C,  6 }, { 0x003D,  6 },
+        { 0x00E3,  8 }, { 0x0D4B, 14 }, { 0x00E6,  8 }, { 0x00E7,  8 },
+        { 0x00F8,  8 }, { 0x0D4C, 14 }, { 0x0D4D, 14 }, { 0x0D4E, 14 },
+        { 0x00F9,  8 }, { 0x0D4F, 14 }, { 0x0D50, 14 }, { 0x0D51, 14 },
+        { 0x06A9, 13 }, { 0x06AA, 13 }, { 0x06AB, 13 }, { 0x06AC, 13 },
+        { 0x06AD, 13 }, { 0x06AE, 13 }, { 0x06AF, 13 }, { 0x003F,  6 },
+        { 0x06B0, 13 }, { 0x06B1, 13 }, { 0x06B2, 13 }, { 0x06B3, 13 },
+        { 0x06B4, 13 }, { 0x007D,  7 }, { 0x06B5, 13 }, { 0x06B6, 13 },
+        { 0x06B7, 13 }, { 0x06B8, 13 }, { 0x06B9, 13 }, { 0x06BA, 13 },
+        { 0x06BB, 13 }, { 0x06BC, 13 }, { 0x06BD, 13 }, { 0x06BE, 13 },
+        { 0x06BF, 13 },
+    },
+    { // 2
+        { 0x0000,  2 }, { 0x0002,  3 }, { 0x0003,  3 }, { 0x0008,  4 },
+        { 0x0012,  5 }, { 0x0013,  5 }, { 0x0028,  6 }, { 0x0029,  6 },
+        { 0x0054,  7 }, { 0x0055,  7 }, { 0x0056,  7 }, { 0x00AE,  8 },
+        { 0x00AF,  8 }, { 0x00B0,  8 }, { 0x0162,  9 }, { 0x02C6, 10 },
+        { 0x000C,  4 }, { 0x002D,  6 }, { 0x00B2,  8 }, { 0x0166,  9 },
+        { 0x002E,  6 }, { 0x0167,  9 }, { 0x00BC,  8 }, { 0x001A,  5 },
+        { 0x0036,  6 }, { 0x0037,  6 }, { 0x0038,  6 }, { 0x005F,  7 },
+        { 0x0072,  7 }, { 0x0073,  7 }, { 0x0074,  7 }, { 0x0075,  7 },
+        { 0x0076,  7 }, { 0x0077,  7 }, { 0x0078,  7 }, { 0x0079,  7 },
+        { 0x007A,  7 }, { 0x007B,  7 }, { 0x00BD,  8 }, { 0xB1C0, 16 },
+        { 0xB1C1, 16 }, { 0x58E1, 15 }, { 0x0B1D, 12 }, { 0x58E2, 15 },
+        { 0x58E3, 15 }, { 0x58E4, 15 }, { 0x00F8,  8 }, { 0x03E4, 10 },
+        { 0x01F3,  9 }, { 0x0B1E, 12 }, { 0x58E5, 15 }, { 0x58E6, 15 },
+        { 0x00FA,  8 }, { 0x58E7, 15 }, { 0x58F8, 15 }, { 0x58F9, 15 },
+        { 0x58FA, 15 }, { 0x01F6,  9 }, { 0x58FB, 15 }, { 0x007E,  7 },
+        { 0x00FE,  8 }, { 0x00FF,  8 }, { 0x07CA, 11 }, { 0x0F96, 12 },
+        { 0x58FC, 15 }, { 0x58FD, 15 }, { 0x58FE, 15 }, { 0x58FF, 15 },
+        { 0x7CB8, 15 }, { 0x7CB9, 15 }, { 0x7CBA, 15 }, { 0x7CBB, 15 },
+        { 0x7CBC, 15 }, { 0x01F7,  9 }, { 0x7CBD, 15 }, { 0x7CBE, 15 },
+        { 0x7CBF, 15 },
+    },
+    { // 3
+        { 0x0000,  2 }, { 0x0002,  3 }, { 0x0006,  4 }, { 0x000E,  5 },
+        { 0x000F,  5 }, { 0x0020,  6 }, { 0x0021,  6 }, { 0x0044,  7 },
+        { 0x0045,  7 }, { 0x008C,  8 }, { 0x008D,  8 }, { 0x011C,  9 },
+        { 0x011D,  9 }, { 0x011E,  9 }, { 0x023E, 10 }, { 0x023F, 10 },
+        { 0x0005,  3 }, { 0x0012,  5 }, { 0x004C,  7 }, { 0x004D,  7 },
+        { 0x000C,  4 }, { 0x004E,  7 }, { 0x001A,  5 }, { 0x0036,  6 },
+        { 0x004F,  7 }, { 0x006E,  7 }, { 0x006F,  7 }, { 0x00E0,  8 },
+        { 0x00E1,  8 }, { 0x00E2,  8 }, { 0x00E3,  8 }, { 0x00E4,  8 },
+        { 0x00E5,  8 }, { 0x01CC,  9 }, { 0x00E7,  8 }, { 0x00E8,  8 },
+        { 0x00E9,  8 }, { 0x01CD,  9 }, { 0x0750, 11 }, { 0x03A9, 10 },
+        { 0x0751, 11 }, { 0x7540, 15 }, { 0x03AB, 10 }, { 0x7541, 15 },
+        { 0x7542, 15 }, { 0x7543, 15 }, { 0x01D6,  9 }, { 0x0755, 11 },
+        { 0x0076,  7 }, { 0x0EA9, 12 }, { 0x7544, 15 }, { 0x7545, 15 },
+        { 0x001E,  5 }, { 0x0077,  7 }, { 0x00F8,  8 }, { 0x03AE, 10 },
+        { 0x075E, 11 }, { 0x007D,  7 }, { 0x03E4, 10 }, { 0x00FC,  8 },
+        { 0x00FD,  8 }, { 0x03E5, 10 }, { 0x03E6, 10 }, { 0x0EBE, 12 },
+        { 0x7546, 15 }, { 0x07CE, 11 }, { 0x7547, 15 }, { 0x75F8, 15 },
+        { 0x75F9, 15 }, { 0x75FA, 15 }, { 0x75FB, 15 }, { 0x75FC, 15 },
+        { 0x75FD, 15 }, { 0x007F,  7 }, { 0x3AFF, 14 }, { 0x0F9E, 12 },
+        { 0x0F9F, 12 },
+    },
+    { // 4
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0003,  4 }, { 0x0008,  5 },
+        { 0x0012,  6 }, { 0x0013,  6 }, { 0x0014,  6 }, { 0x002A,  7 },
+        { 0x0016,  6 }, { 0x002B,  7 }, { 0x005C,  8 }, { 0x005D,  8 },
+        { 0x005E,  8 }, { 0x00BE,  9 }, { 0x00BF,  9 }, { 0x0060,  8 },
+        { 0x0007,  4 }, { 0x000D,  5 }, { 0x0019,  6 }, { 0x0020,  6 },
+        { 0x0009,  4 }, { 0x0021,  6 }, { 0x0011,  5 }, { 0x0014,  5 },
+        { 0x002A,  6 }, { 0x002B,  6 }, { 0x002C,  6 }, { 0x002D,  6 },
+        { 0x002E,  6 }, { 0x002F,  6 }, { 0x0030,  6 }, { 0x0031,  7 },
+        { 0x0062,  7 }, { 0x0063,  7 }, { 0x0064,  7 }, { 0x0065,  7 },
+        { 0x0066,  7 }, { 0x0061,  8 }, { 0x0670, 11 }, { 0x0068,  7 },
+        { 0x0069,  7 }, { 0x00CF,  8 }, { 0x019D,  9 }, { 0x01A8,  9 },
+        { 0x01A9,  9 }, { 0x0339, 10 }, { 0x01AA,  9 }, { 0x0356, 10 },
+        { 0x0036,  6 }, { 0x00D6,  8 }, { 0x6710, 15 }, { 0x6711, 15 },
+        { 0x000E,  4 }, { 0x006E,  7 }, { 0x01AE,  9 }, { 0x6712, 15 },
+        { 0x6713, 15 }, { 0x003C,  6 }, { 0x0357, 10 }, { 0x006F,  7 },
+        { 0x00F4,  8 }, { 0x00F5,  8 }, { 0x035E, 10 }, { 0x01EC,  9 },
+        { 0x6714, 15 }, { 0x01ED,  9 }, { 0x035F, 10 }, { 0x03DC, 10 },
+        { 0x03DD, 10 }, { 0x6715, 15 }, { 0x338B, 14 }, { 0x338C, 14 },
+        { 0x338D, 14 }, { 0x001F,  5 }, { 0x01EF,  9 }, { 0x338E, 14 },
+        { 0x338F, 14 },
+    },
+    { // 5
+        { 0x0000,  2 }, { 0x0004,  4 }, { 0x000A,  5 }, { 0x000B,  5 },
+        { 0x0018,  6 }, { 0x0019,  6 }, { 0x0034,  7 }, { 0x006A,  8 },
+        { 0x006B,  8 }, { 0x006C,  8 }, { 0x00DA,  9 }, { 0x036C, 11 },
+        { 0x006E,  8 }, { 0x01B7, 10 }, { 0x036D, 11 }, { 0x3780, 15 },
+        { 0x0004,  3 }, { 0x000E,  5 }, { 0x001E,  6 }, { 0x003E,  7 },
+        { 0x000A,  4 }, { 0x002C,  6 }, { 0x0017,  5 }, { 0x002D,  6 },
+        { 0x003F,  7 }, { 0x00C0,  8 }, { 0x0061,  7 }, { 0x00C1,  8 },
+        { 0x0062,  7 }, { 0x00C6,  8 }, { 0x0064,  7 }, { 0x00C7,  8 },
+        { 0x00CA,  8 }, { 0x00DF,  9 }, { 0x0196,  9 }, { 0x0197,  9 },
+        { 0x0198,  9 }, { 0x0199,  9 }, { 0x0379, 11 }, { 0x019A,  9 },
+        { 0x01BD, 10 }, { 0x066C, 11 }, { 0x3781, 15 }, { 0x0337, 10 },
+        { 0x066D, 11 }, { 0x0670, 11 }, { 0x0339, 10 }, { 0x0671, 11 },
+        { 0x0034,  6 }, { 0x00CF,  8 }, { 0x3782, 15 }, { 0x3783, 15 },
+        { 0x000E,  4 }, { 0x001B,  5 }, { 0x006A,  7 }, { 0x006B,  7 },
+        { 0x019D,  9 }, { 0x003C,  6 }, { 0x00F4,  8 }, { 0x00F5,  8 },
+        { 0x03D8, 10 }, { 0x07B2, 11 }, { 0x3784, 15 }, { 0x03DA, 10 },
+        { 0x3785, 15 }, { 0x03DB, 10 }, { 0x03DC, 10 }, { 0x3786, 15 },
+        { 0x3787, 15 }, { 0x1BC4, 14 }, { 0x1BC5, 14 }, { 0x1BC6, 14 },
+        { 0x1BC7, 14 }, { 0x001F,  5 }, { 0x03DD, 10 }, { 0x07B3, 11 },
+        { 0x01EF,  9 },
+    },
+    { // 6
+        { 0x0000,  2 }, { 0x0004,  4 }, { 0x000A,  5 }, { 0x0016,  6 },
+        { 0x0017,  6 }, { 0x0060,  8 }, { 0x00C2,  9 }, { 0x0186, 10 },
+        { 0x0187, 10 }, { 0x00C4,  9 }, { 0x3140, 15 }, { 0x3141, 15 },
+        { 0x018B, 10 }, { 0x3142, 15 }, { 0x018C, 10 }, { 0x3143, 15 },
+        { 0x0007,  4 }, { 0x000D,  5 }, { 0x0064,  8 }, { 0x0065,  8 },
+        { 0x0010,  5 }, { 0x00C7,  9 }, { 0x0066,  8 }, { 0x0005,  3 },
+        { 0x0006,  3 }, { 0x0009,  4 }, { 0x0011,  5 }, { 0x0038,  6 },
+        { 0x0039,  6 }, { 0x0074,  7 }, { 0x0075,  7 }, { 0x0076,  7 },
+        { 0x0067,  8 }, { 0x00EE,  8 }, { 0x01DE,  9 }, { 0x00F0,  8 },
+        { 0x018D, 10 }, { 0x3144, 15 }, { 0x01DF,  9 }, { 0x003D,  6 },
+        { 0x003E,  6 }, { 0x01E2,  9 }, { 0x03C6, 10 }, { 0x00F2,  8 },
+        { 0x00F3,  8 }, { 0x03C7, 10 }, { 0x3145, 15 }, { 0x3146, 15 },
+        { 0x01F8,  9 }, { 0x3147, 15 }, { 0x3148, 15 }, { 0x3149, 15 },
+        { 0x00FD,  8 }, { 0x314A, 15 }, { 0x314B, 15 }, { 0x314C, 15 },
+        { 0x314D, 15 }, { 0x01F9,  9 }, { 0x314E, 15 }, { 0x01FC,  9 },
+        { 0x314F, 15 }, { 0x3150, 15 }, { 0x3151, 15 }, { 0x3152, 15 },
+        { 0x3153, 15 }, { 0x03FA, 10 }, { 0x03FB, 10 }, { 0x3154, 15 },
+        { 0x3155, 15 }, { 0x3156, 15 }, { 0x3157, 15 }, { 0x3158, 15 },
+        { 0x3159, 15 }, { 0x00FF,  8 }, { 0x18AD, 14 }, { 0x18AE, 14 },
+        { 0x18AF, 14 },
+    },
+    { // 7
+        { 0x0000,  4 }, { 0x0080, 11 }, { 0x0081, 11 }, { 0x0082, 11 },
+        { 0x0083, 11 }, { 0x0084, 11 }, { 0x0085, 11 }, { 0x0086, 11 },
+        { 0x0087, 11 }, { 0x0088, 11 }, { 0x0089, 11 }, { 0x008A, 11 },
+        { 0x008B, 11 }, { 0x008C, 11 }, { 0x008D, 11 }, { 0x008E, 11 },
+        { 0x008F, 11 }, { 0x0048, 10 }, { 0x0049, 10 }, { 0x004A, 10 },
+        { 0x004B, 10 }, { 0x004C, 10 }, { 0x004D, 10 }, { 0x0001,  1 },
+        { 0x0001,  2 }, { 0x004E, 10 }, { 0x0002,  4 }, { 0x0003,  4 },
+        { 0x004F, 10 }, { 0x0050, 10 }, { 0x0051, 10 }, { 0x0052, 10 },
+        { 0x0053, 10 }, { 0x0054, 10 }, { 0x0055, 10 }, { 0x0056, 10 },
+        { 0x0057, 10 }, { 0x0058, 10 }, { 0x0059, 10 }, { 0x005A, 10 },
+        { 0x005B, 10 }, { 0x005C, 10 }, { 0x005D, 10 }, { 0x005E, 10 },
+        { 0x005F, 10 }, { 0x0060, 10 }, { 0x0061, 10 }, { 0x0062, 10 },
+        { 0x0063, 10 }, { 0x0064, 10 }, { 0x0065, 10 }, { 0x0066, 10 },
+        { 0x0067, 10 }, { 0x0068, 10 }, { 0x0069, 10 }, { 0x006A, 10 },
+        { 0x006B, 10 }, { 0x006C, 10 }, { 0x006D, 10 }, { 0x006E, 10 },
+        { 0x006F, 10 }, { 0x0070, 10 }, { 0x0071, 10 }, { 0x0072, 10 },
+        { 0x0073, 10 }, { 0x0074, 10 }, { 0x0075, 10 }, { 0x0076, 10 },
+        { 0x0077, 10 }, { 0x0078, 10 }, { 0x0079, 10 }, { 0x007A, 10 },
+        { 0x007B, 10 }, { 0x007C, 10 }, { 0x007D, 10 }, { 0x007E, 10 },
+        { 0x007F, 10 },
+    },
 };
 
-static const uint16_t x8_ac0_highquant_table[8][77][2]={
-    {//0
-        {0x0000,  3}, {0x0002,  4}, {0x000C,  6}, {0x000D,  6},
-        {0x001C,  7}, {0x000F,  6}, {0x1D00, 15}, {0x003B,  8},
-        {0x1D01, 15}, {0x0075,  9}, {0x1D02, 15}, {0x0080,  9},
-        {0x1D03, 15}, {0x1D04, 15}, {0x1D05, 15}, {0x0E83, 14},
-        {0x0009,  5}, {0x0011,  6}, {0x0081,  9}, {0x0082,  9},
-        {0x0021,  7}, {0x0028,  7}, {0x0083,  9}, {0x0002,  2},
-        {0x0003,  3}, {0x000C,  4}, {0x000D,  4}, {0x000B,  5},
-        {0x0015,  6}, {0x0052,  8}, {0x0070,  7}, {0x0039,  6},
-        {0x0071,  7}, {0x0053,  8}, {0x0E84, 14}, {0x0074,  7},
-        {0x0075,  7}, {0x0076,  7}, {0x01DC,  9}, {0x001E,  5},
-        {0x003E,  6}, {0x01DD,  9}, {0x00EF,  8}, {0x01F8,  9},
-        {0x01F9,  9}, {0x0E85, 14}, {0x0E86, 14}, {0x0E87, 14},
-        {0x00FD,  8}, {0x0E88, 14}, {0x0E89, 14}, {0x0E8A, 14},
-        {0x0E8B, 14}, {0x0E8C, 14}, {0x0E8D, 14}, {0x0E8E, 14},
-        {0x0E8F, 14}, {0x0E90, 14}, {0x0E91, 14}, {0x01FC,  9},
-        {0x0E92, 14}, {0x0E93, 14}, {0x0E94, 14}, {0x0E95, 14},
-        {0x0E96, 14}, {0x0E97, 14}, {0x01FD,  9}, {0x0E98, 14},
-        {0x01FE,  9}, {0x0E99, 14}, {0x0E9A, 14}, {0x0E9B, 14},
-        {0x0E9C, 14}, {0x01FF,  9}, {0x0E9D, 14}, {0x0E9E, 14},
-        {0x0E9F, 14},
-    },{//1
-        {0x0000,  3}, {0x0002,  4}, {0x0003,  4}, {0x0008,  5},
-        {0x0012,  6}, {0x0013,  6}, {0x0014,  6}, {0x0015,  6},
-        {0x002C,  7}, {0x005A,  8}, {0x005B,  8}, {0x005C,  8},
-        {0x005D,  8}, {0x1780, 14}, {0x0179, 10}, {0x017A, 10},
-        {0x0006,  4}, {0x000E,  5}, {0x001E,  6}, {0x003E,  7},
-        {0x0010,  5}, {0x0022,  6}, {0x0012,  5}, {0x000A,  4},
-        {0x0013,  5}, {0x0016,  5}, {0x0023,  6}, {0x002E,  6},
-        {0x002F,  6}, {0x0030,  6}, {0x0031,  6}, {0x003F,  7},
-        {0x005F,  8}, {0x00C8,  8}, {0x0065,  7}, {0x0066,  7},
-        {0x0067,  7}, {0x0068,  7}, {0x00C9,  8}, {0x0069,  7},
-        {0x006A,  7}, {0x00D6,  8}, {0x00D7,  8}, {0x00D8,  8},
-        {0x1781, 14}, {0x017B, 10}, {0x01B2,  9}, {0x1782, 14},
-        {0x001C,  5}, {0x01B3,  9}, {0x1783, 14}, {0x1784, 14},
-        {0x001D,  5}, {0x00DA,  8}, {0x1785, 14}, {0x1786, 14},
-        {0x1787, 14}, {0x0037,  6}, {0x00DB,  8}, {0x0078,  7},
-        {0x00F2,  8}, {0x01E6,  9}, {0x00F4,  8}, {0x1788, 14},
-        {0x1789, 14}, {0x00F5,  8}, {0x01E7,  9}, {0x178A, 14},
-        {0x178B, 14}, {0x178C, 14}, {0x178D, 14}, {0x01EC,  9},
-        {0x178E, 14}, {0x001F,  5}, {0x00F7,  8}, {0x01ED,  9},
-        {0x178F, 14},
-    },{//2
-        {0x0000,  4}, {0x0002,  5}, {0x0180, 12}, {0x0181, 12},
-        {0x0182, 12}, {0x0183, 12}, {0x0184, 12}, {0x0185, 12},
-        {0x0186, 12}, {0x0187, 12}, {0x0188, 12}, {0x0189, 12},
-        {0x00C5, 11}, {0x00C6, 11}, {0x00C7, 11}, {0x00C8, 11},
-        {0x00C9, 11}, {0x00CA, 11}, {0x00CB, 11}, {0x00CC, 11},
-        {0x00CD, 11}, {0x00CE, 11}, {0x00CF, 11}, {0x0001,  1},
-        {0x0001,  2}, {0x0004,  5}, {0x0005,  5}, {0x0006,  5},
-        {0x00D0, 11}, {0x00D1, 11}, {0x00D2, 11}, {0x00D3, 11},
-        {0x00D4, 11}, {0x00D5, 11}, {0x00D6, 11}, {0x00D7, 11},
-        {0x00D8, 11}, {0x00D9, 11}, {0x00DA, 11}, {0x0007,  5},
-        {0x00DB, 11}, {0x00DC, 11}, {0x00DD, 11}, {0x00DE, 11},
-        {0x00DF, 11}, {0x00E0, 11}, {0x00E1, 11}, {0x00E2, 11},
-        {0x00E3, 11}, {0x00E4, 11}, {0x00E5, 11}, {0x00E6, 11},
-        {0x00E7, 11}, {0x00E8, 11}, {0x00E9, 11}, {0x00EA, 11},
-        {0x00EB, 11}, {0x00EC, 11}, {0x00ED, 11}, {0x00EE, 11},
-        {0x00EF, 11}, {0x00F0, 11}, {0x00F1, 11}, {0x00F2, 11},
-        {0x00F3, 11}, {0x00F4, 11}, {0x00F5, 11}, {0x00F6, 11},
-        {0x00F7, 11}, {0x00F8, 11}, {0x00F9, 11}, {0x00FA, 11},
-        {0x00FB, 11}, {0x00FC, 11}, {0x00FD, 11}, {0x00FE, 11},
-        {0x00FF, 11},
-    },{//3
-        {0x0000,  8}, {0x0001,  8}, {0x0002,  8}, {0x0003,  8},
-        {0x0004,  8}, {0x0005,  8}, {0x0006,  8}, {0x0007,  8},
-        {0x0008,  8}, {0x0009,  8}, {0x000A,  8}, {0x000B,  8},
-        {0x000C,  8}, {0x000D,  8}, {0x000E,  8}, {0x000F,  8},
-        {0x0010,  8}, {0x0011,  8}, {0x0012,  8}, {0x0013,  8},
-        {0x0014,  8}, {0x0015,  8}, {0x0016,  8}, {0x0001,  1},
-        {0x0017,  8}, {0x000C,  7}, {0x000D,  7}, {0x000E,  7},
-        {0x000F,  7}, {0x0010,  7}, {0x0011,  7}, {0x0012,  7},
-        {0x0013,  7}, {0x0014,  7}, {0x0015,  7}, {0x0016,  7},
-        {0x0017,  7}, {0x0018,  7}, {0x0019,  7}, {0x001A,  7},
-        {0x001B,  7}, {0x001C,  7}, {0x001D,  7}, {0x001E,  7},
-        {0x001F,  7}, {0x0020,  7}, {0x0021,  7}, {0x0022,  7},
-        {0x0023,  7}, {0x0024,  7}, {0x0025,  7}, {0x0026,  7},
-        {0x0027,  7}, {0x0028,  7}, {0x0029,  7}, {0x002A,  7},
-        {0x002B,  7}, {0x002C,  7}, {0x002D,  7}, {0x002E,  7},
-        {0x002F,  7}, {0x0030,  7}, {0x0031,  7}, {0x0032,  7},
-        {0x0033,  7}, {0x0034,  7}, {0x0035,  7}, {0x0036,  7},
-        {0x0037,  7}, {0x0038,  7}, {0x0039,  7}, {0x003A,  7},
-        {0x003B,  7}, {0x003C,  7}, {0x003D,  7}, {0x003E,  7},
-        {0x003F,  7},
-    },{//4
-        {0x0000,  9}, {0x0001,  9}, {0x0002,  9}, {0x0003,  9},
-        {0x0004,  9}, {0x0005,  9}, {0x0006,  9}, {0x0007,  9},
-        {0x0008,  9}, {0x0009,  9}, {0x000A,  9}, {0x000B,  9},
-        {0x000C,  9}, {0x000D,  9}, {0x000E,  9}, {0x000F,  9},
-        {0x0010,  9}, {0x0011,  9}, {0x0012,  9}, {0x0013,  9},
-        {0x0014,  9}, {0x0015,  9}, {0x000B,  8}, {0x0001,  2},
-        {0x0001,  1}, {0x000C,  8}, {0x000D,  8}, {0x000E,  8},
-        {0x000F,  8}, {0x0010,  8}, {0x0011,  8}, {0x0012,  8},
-        {0x0013,  8}, {0x0014,  8}, {0x0015,  8}, {0x0016,  8},
-        {0x0017,  8}, {0x0018,  8}, {0x0019,  8}, {0x001A,  8},
-        {0x001B,  8}, {0x001C,  8}, {0x001D,  8}, {0x001E,  8},
-        {0x001F,  8}, {0x0020,  8}, {0x0021,  8}, {0x0022,  8},
-        {0x0023,  8}, {0x0024,  8}, {0x0025,  8}, {0x0026,  8},
-        {0x0027,  8}, {0x0028,  8}, {0x0029,  8}, {0x002A,  8},
-        {0x002B,  8}, {0x002C,  8}, {0x002D,  8}, {0x002E,  8},
-        {0x002F,  8}, {0x0030,  8}, {0x0031,  8}, {0x0032,  8},
-        {0x0033,  8}, {0x0034,  8}, {0x0035,  8}, {0x0036,  8},
-        {0x0037,  8}, {0x0038,  8}, {0x0039,  8}, {0x003A,  8},
-        {0x003B,  8}, {0x003C,  8}, {0x003D,  8}, {0x003E,  8},
-        {0x003F,  8},
-    },{//5
-        {0x0000, 10}, {0x0001, 10}, {0x0002, 10}, {0x0003, 10},
-        {0x0004, 10}, {0x0005, 10}, {0x0006, 10}, {0x0007, 10},
-        {0x0008, 10}, {0x0009, 10}, {0x000A, 10}, {0x000B, 10},
-        {0x000C, 10}, {0x000D, 10}, {0x000E, 10}, {0x000F, 10},
-        {0x0010, 10}, {0x0011, 10}, {0x0012, 10}, {0x0013, 10},
-        {0x000A,  9}, {0x000B,  9}, {0x000C,  9}, {0x0001,  1},
-        {0x0001,  3}, {0x000D,  9}, {0x000E,  9}, {0x0001,  2},
-        {0x000F,  9}, {0x0010,  9}, {0x0011,  9}, {0x0012,  9},
-        {0x0013,  9}, {0x0014,  9}, {0x0015,  9}, {0x0016,  9},
-        {0x0017,  9}, {0x0018,  9}, {0x0019,  9}, {0x001A,  9},
-        {0x001B,  9}, {0x001C,  9}, {0x001D,  9}, {0x001E,  9},
-        {0x001F,  9}, {0x0020,  9}, {0x0021,  9}, {0x0022,  9},
-        {0x0023,  9}, {0x0024,  9}, {0x0025,  9}, {0x0026,  9},
-        {0x0027,  9}, {0x0028,  9}, {0x0029,  9}, {0x002A,  9},
-        {0x002B,  9}, {0x002C,  9}, {0x002D,  9}, {0x002E,  9},
-        {0x002F,  9}, {0x0030,  9}, {0x0031,  9}, {0x0032,  9},
-        {0x0033,  9}, {0x0034,  9}, {0x0035,  9}, {0x0036,  9},
-        {0x0037,  9}, {0x0038,  9}, {0x0039,  9}, {0x003A,  9},
-        {0x003B,  9}, {0x003C,  9}, {0x003D,  9}, {0x003E,  9},
-        {0x003F,  9},
-    },{//6
-        {0x0000,  2}, {0x0004,  4}, {0x000A,  5}, {0x000B,  5},
-        {0x0018,  6}, {0x0019,  6}, {0x0034,  7}, {0x006A,  8},
-        {0x006B,  8}, {0x006C,  8}, {0x00DA,  9}, {0x00DB,  9},
-        {0x01B8, 10}, {0x00DD,  9}, {0x01B9, 10}, {0x3780, 15},
-        {0x0004,  3}, {0x000E,  5}, {0x001E,  6}, {0x001F,  6},
-        {0x000A,  4}, {0x0058,  7}, {0x0017,  5}, {0x0018,  5},
-        {0x0059,  7}, {0x005A,  7}, {0x005B,  7}, {0x00C8,  8},
-        {0x0065,  7}, {0x0066,  7}, {0x00C9,  8}, {0x00CE,  8},
-        {0x00CF,  8}, {0x00D0,  8}, {0x00D1,  8}, {0x00D2,  8},
-        {0x00D3,  8}, {0x00DF,  9}, {0x00D4,  8}, {0x00D5,  8},
-        {0x00D6,  8}, {0x01AE,  9}, {0x3781, 15}, {0x01BD, 10},
-        {0x035E, 10}, {0x035F, 10}, {0x3782, 15}, {0x0360, 10},
-        {0x0037,  6}, {0x01B1,  9}, {0x3783, 15}, {0x3784, 15},
-        {0x000E,  4}, {0x003C,  6}, {0x0361, 10}, {0x3785, 15},
-        {0x1BC3, 14}, {0x003D,  6}, {0x00D9,  8}, {0x1BC4, 14},
-        {0x0368, 10}, {0x1BC5, 14}, {0x1BC6, 14}, {0x1BC7, 14},
-        {0x1BC8, 14}, {0x00DB,  8}, {0x0369, 10}, {0x036A, 10},
-        {0x1BC9, 14}, {0x1BCA, 14}, {0x1BCB, 14}, {0x1BCC, 14},
-        {0x1BCD, 14}, {0x001F,  5}, {0x036B, 10}, {0x1BCE, 14},
-        {0x1BCF, 14},
-    },{//7
-        {0x0000,  3}, {0x0002,  4}, {0x0006,  5}, {0x0007,  5},
-        {0x0010,  6}, {0x0044,  8}, {0x0023,  7}, {0x0012,  6},
-        {0x0026,  7}, {0x08A0, 13}, {0x004E,  8}, {0x004F,  8},
-        {0x08A1, 13}, {0x08A2, 13}, {0x08A3, 13}, {0x0050,  8},
-        {0x0006,  4}, {0x000B,  5}, {0x0029,  7}, {0x0015,  6},
-        {0x001C,  6}, {0x003A,  7}, {0x001E,  6}, {0x0004,  3},
-        {0x0014,  5}, {0x0015,  5}, {0x000B,  4}, {0x001F,  6},
-        {0x0030,  6}, {0x0031,  6}, {0x0019,  5}, {0x0051,  8},
-        {0x0034,  6}, {0x0035,  6}, {0x0036,  6}, {0x0037,  6},
-        {0x0076,  8}, {0x0077,  8}, {0x0070,  7}, {0x001D,  5},
-        {0x0071,  7}, {0x0072,  7}, {0x08A4, 13}, {0x0073,  7},
-        {0x00F0,  8}, {0x08A5, 13}, {0x08A6, 13}, {0x08A7, 13},
-        {0x0079,  7}, {0x007A,  7}, {0x08A8, 13}, {0x08A9, 13},
-        {0x00F1,  8}, {0x08AA, 13}, {0x08AB, 13}, {0x08AC, 13},
-        {0x08AD, 13}, {0x00F6,  8}, {0x08AE, 13}, {0x007C,  7},
-        {0x00F7,  8}, {0x08AF, 13}, {0x08B0, 13}, {0x08B1, 13},
-        {0x08B2, 13}, {0x00FA,  8}, {0x08B3, 13}, {0x08B4, 13},
-        {0x08B5, 13}, {0x08B6, 13}, {0x08B7, 13}, {0x00FB,  8},
-        {0x045C, 12}, {0x003F,  6}, {0x045D, 12}, {0x045E, 12},
-        {0x045F, 12},
-    }
+static const uint16_t x8_ac0_highquant_table[8][77][2] = {
+    { // 0
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x000C,  6 }, { 0x000D,  6 },
+        { 0x001C,  7 }, { 0x000F,  6 }, { 0x1D00, 15 }, { 0x003B,  8 },
+        { 0x1D01, 15 }, { 0x0075,  9 }, { 0x1D02, 15 }, { 0x0080,  9 },
+        { 0x1D03, 15 }, { 0x1D04, 15 }, { 0x1D05, 15 }, { 0x0E83, 14 },
+        { 0x0009,  5 }, { 0x0011,  6 }, { 0x0081,  9 }, { 0x0082,  9 },
+        { 0x0021,  7 }, { 0x0028,  7 }, { 0x0083,  9 }, { 0x0002,  2 },
+        { 0x0003,  3 }, { 0x000C,  4 }, { 0x000D,  4 }, { 0x000B,  5 },
+        { 0x0015,  6 }, { 0x0052,  8 }, { 0x0070,  7 }, { 0x0039,  6 },
+        { 0x0071,  7 }, { 0x0053,  8 }, { 0x0E84, 14 }, { 0x0074,  7 },
+        { 0x0075,  7 }, { 0x0076,  7 }, { 0x01DC,  9 }, { 0x001E,  5 },
+        { 0x003E,  6 }, { 0x01DD,  9 }, { 0x00EF,  8 }, { 0x01F8,  9 },
+        { 0x01F9,  9 }, { 0x0E85, 14 }, { 0x0E86, 14 }, { 0x0E87, 14 },
+        { 0x00FD,  8 }, { 0x0E88, 14 }, { 0x0E89, 14 }, { 0x0E8A, 14 },
+        { 0x0E8B, 14 }, { 0x0E8C, 14 }, { 0x0E8D, 14 }, { 0x0E8E, 14 },
+        { 0x0E8F, 14 }, { 0x0E90, 14 }, { 0x0E91, 14 }, { 0x01FC,  9 },
+        { 0x0E92, 14 }, { 0x0E93, 14 }, { 0x0E94, 14 }, { 0x0E95, 14 },
+        { 0x0E96, 14 }, { 0x0E97, 14 }, { 0x01FD,  9 }, { 0x0E98, 14 },
+        { 0x01FE,  9 }, { 0x0E99, 14 }, { 0x0E9A, 14 }, { 0x0E9B, 14 },
+        { 0x0E9C, 14 }, { 0x01FF,  9 }, { 0x0E9D, 14 }, { 0x0E9E, 14 },
+        { 0x0E9F, 14 },
+    },
+    { // 1
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0003,  4 }, { 0x0008,  5 },
+        { 0x0012,  6 }, { 0x0013,  6 }, { 0x0014,  6 }, { 0x0015,  6 },
+        { 0x002C,  7 }, { 0x005A,  8 }, { 0x005B,  8 }, { 0x005C,  8 },
+        { 0x005D,  8 }, { 0x1780, 14 }, { 0x0179, 10 }, { 0x017A, 10 },
+        { 0x0006,  4 }, { 0x000E,  5 }, { 0x001E,  6 }, { 0x003E,  7 },
+        { 0x0010,  5 }, { 0x0022,  6 }, { 0x0012,  5 }, { 0x000A,  4 },
+        { 0x0013,  5 }, { 0x0016,  5 }, { 0x0023,  6 }, { 0x002E,  6 },
+        { 0x002F,  6 }, { 0x0030,  6 }, { 0x0031,  6 }, { 0x003F,  7 },
+        { 0x005F,  8 }, { 0x00C8,  8 }, { 0x0065,  7 }, { 0x0066,  7 },
+        { 0x0067,  7 }, { 0x0068,  7 }, { 0x00C9,  8 }, { 0x0069,  7 },
+        { 0x006A,  7 }, { 0x00D6,  8 }, { 0x00D7,  8 }, { 0x00D8,  8 },
+        { 0x1781, 14 }, { 0x017B, 10 }, { 0x01B2,  9 }, { 0x1782, 14 },
+        { 0x001C,  5 }, { 0x01B3,  9 }, { 0x1783, 14 }, { 0x1784, 14 },
+        { 0x001D,  5 }, { 0x00DA,  8 }, { 0x1785, 14 }, { 0x1786, 14 },
+        { 0x1787, 14 }, { 0x0037,  6 }, { 0x00DB,  8 }, { 0x0078,  7 },
+        { 0x00F2,  8 }, { 0x01E6,  9 }, { 0x00F4,  8 }, { 0x1788, 14 },
+        { 0x1789, 14 }, { 0x00F5,  8 }, { 0x01E7,  9 }, { 0x178A, 14 },
+        { 0x178B, 14 }, { 0x178C, 14 }, { 0x178D, 14 }, { 0x01EC,  9 },
+        { 0x178E, 14 }, { 0x001F,  5 }, { 0x00F7,  8 }, { 0x01ED,  9 },
+        { 0x178F, 14 },
+    },
+    { // 2
+        { 0x0000,  4 }, { 0x0002,  5 }, { 0x0180, 12 }, { 0x0181, 12 },
+        { 0x0182, 12 }, { 0x0183, 12 }, { 0x0184, 12 }, { 0x0185, 12 },
+        { 0x0186, 12 }, { 0x0187, 12 }, { 0x0188, 12 }, { 0x0189, 12 },
+        { 0x00C5, 11 }, { 0x00C6, 11 }, { 0x00C7, 11 }, { 0x00C8, 11 },
+        { 0x00C9, 11 }, { 0x00CA, 11 }, { 0x00CB, 11 }, { 0x00CC, 11 },
+        { 0x00CD, 11 }, { 0x00CE, 11 }, { 0x00CF, 11 }, { 0x0001,  1 },
+        { 0x0001,  2 }, { 0x0004,  5 }, { 0x0005,  5 }, { 0x0006,  5 },
+        { 0x00D0, 11 }, { 0x00D1, 11 }, { 0x00D2, 11 }, { 0x00D3, 11 },
+        { 0x00D4, 11 }, { 0x00D5, 11 }, { 0x00D6, 11 }, { 0x00D7, 11 },
+        { 0x00D8, 11 }, { 0x00D9, 11 }, { 0x00DA, 11 }, { 0x0007,  5 },
+        { 0x00DB, 11 }, { 0x00DC, 11 }, { 0x00DD, 11 }, { 0x00DE, 11 },
+        { 0x00DF, 11 }, { 0x00E0, 11 }, { 0x00E1, 11 }, { 0x00E2, 11 },
+        { 0x00E3, 11 }, { 0x00E4, 11 }, { 0x00E5, 11 }, { 0x00E6, 11 },
+        { 0x00E7, 11 }, { 0x00E8, 11 }, { 0x00E9, 11 }, { 0x00EA, 11 },
+        { 0x00EB, 11 }, { 0x00EC, 11 }, { 0x00ED, 11 }, { 0x00EE, 11 },
+        { 0x00EF, 11 }, { 0x00F0, 11 }, { 0x00F1, 11 }, { 0x00F2, 11 },
+        { 0x00F3, 11 }, { 0x00F4, 11 }, { 0x00F5, 11 }, { 0x00F6, 11 },
+        { 0x00F7, 11 }, { 0x00F8, 11 }, { 0x00F9, 11 }, { 0x00FA, 11 },
+        { 0x00FB, 11 }, { 0x00FC, 11 }, { 0x00FD, 11 }, { 0x00FE, 11 },
+        { 0x00FF, 11 },
+    },
+    { // 3
+        { 0x0000,  8 }, { 0x0001,  8 }, { 0x0002,  8 }, { 0x0003,  8 },
+        { 0x0004,  8 }, { 0x0005,  8 }, { 0x0006,  8 }, { 0x0007,  8 },
+        { 0x0008,  8 }, { 0x0009,  8 }, { 0x000A,  8 }, { 0x000B,  8 },
+        { 0x000C,  8 }, { 0x000D,  8 }, { 0x000E,  8 }, { 0x000F,  8 },
+        { 0x0010,  8 }, { 0x0011,  8 }, { 0x0012,  8 }, { 0x0013,  8 },
+        { 0x0014,  8 }, { 0x0015,  8 }, { 0x0016,  8 }, { 0x0001,  1 },
+        { 0x0017,  8 }, { 0x000C,  7 }, { 0x000D,  7 }, { 0x000E,  7 },
+        { 0x000F,  7 }, { 0x0010,  7 }, { 0x0011,  7 }, { 0x0012,  7 },
+        { 0x0013,  7 }, { 0x0014,  7 }, { 0x0015,  7 }, { 0x0016,  7 },
+        { 0x0017,  7 }, { 0x0018,  7 }, { 0x0019,  7 }, { 0x001A,  7 },
+        { 0x001B,  7 }, { 0x001C,  7 }, { 0x001D,  7 }, { 0x001E,  7 },
+        { 0x001F,  7 }, { 0x0020,  7 }, { 0x0021,  7 }, { 0x0022,  7 },
+        { 0x0023,  7 }, { 0x0024,  7 }, { 0x0025,  7 }, { 0x0026,  7 },
+        { 0x0027,  7 }, { 0x0028,  7 }, { 0x0029,  7 }, { 0x002A,  7 },
+        { 0x002B,  7 }, { 0x002C,  7 }, { 0x002D,  7 }, { 0x002E,  7 },
+        { 0x002F,  7 }, { 0x0030,  7 }, { 0x0031,  7 }, { 0x0032,  7 },
+        { 0x0033,  7 }, { 0x0034,  7 }, { 0x0035,  7 }, { 0x0036,  7 },
+        { 0x0037,  7 }, { 0x0038,  7 }, { 0x0039,  7 }, { 0x003A,  7 },
+        { 0x003B,  7 }, { 0x003C,  7 }, { 0x003D,  7 }, { 0x003E,  7 },
+        { 0x003F,  7 },
+    },
+    { // 4
+        { 0x0000,  9 }, { 0x0001,  9 }, { 0x0002,  9 }, { 0x0003,  9 },
+        { 0x0004,  9 }, { 0x0005,  9 }, { 0x0006,  9 }, { 0x0007,  9 },
+        { 0x0008,  9 }, { 0x0009,  9 }, { 0x000A,  9 }, { 0x000B,  9 },
+        { 0x000C,  9 }, { 0x000D,  9 }, { 0x000E,  9 }, { 0x000F,  9 },
+        { 0x0010,  9 }, { 0x0011,  9 }, { 0x0012,  9 }, { 0x0013,  9 },
+        { 0x0014,  9 }, { 0x0015,  9 }, { 0x000B,  8 }, { 0x0001,  2 },
+        { 0x0001,  1 }, { 0x000C,  8 }, { 0x000D,  8 }, { 0x000E,  8 },
+        { 0x000F,  8 }, { 0x0010,  8 }, { 0x0011,  8 }, { 0x0012,  8 },
+        { 0x0013,  8 }, { 0x0014,  8 }, { 0x0015,  8 }, { 0x0016,  8 },
+        { 0x0017,  8 }, { 0x0018,  8 }, { 0x0019,  8 }, { 0x001A,  8 },
+        { 0x001B,  8 }, { 0x001C,  8 }, { 0x001D,  8 }, { 0x001E,  8 },
+        { 0x001F,  8 }, { 0x0020,  8 }, { 0x0021,  8 }, { 0x0022,  8 },
+        { 0x0023,  8 }, { 0x0024,  8 }, { 0x0025,  8 }, { 0x0026,  8 },
+        { 0x0027,  8 }, { 0x0028,  8 }, { 0x0029,  8 }, { 0x002A,  8 },
+        { 0x002B,  8 }, { 0x002C,  8 }, { 0x002D,  8 }, { 0x002E,  8 },
+        { 0x002F,  8 }, { 0x0030,  8 }, { 0x0031,  8 }, { 0x0032,  8 },
+        { 0x0033,  8 }, { 0x0034,  8 }, { 0x0035,  8 }, { 0x0036,  8 },
+        { 0x0037,  8 }, { 0x0038,  8 }, { 0x0039,  8 }, { 0x003A,  8 },
+        { 0x003B,  8 }, { 0x003C,  8 }, { 0x003D,  8 }, { 0x003E,  8 },
+        { 0x003F,  8 },
+    },
+    { // 5
+        { 0x0000, 10 }, { 0x0001, 10 }, { 0x0002, 10 }, { 0x0003, 10 },
+        { 0x0004, 10 }, { 0x0005, 10 }, { 0x0006, 10 }, { 0x0007, 10 },
+        { 0x0008, 10 }, { 0x0009, 10 }, { 0x000A, 10 }, { 0x000B, 10 },
+        { 0x000C, 10 }, { 0x000D, 10 }, { 0x000E, 10 }, { 0x000F, 10 },
+        { 0x0010, 10 }, { 0x0011, 10 }, { 0x0012, 10 }, { 0x0013, 10 },
+        { 0x000A,  9 }, { 0x000B,  9 }, { 0x000C,  9 }, { 0x0001,  1 },
+        { 0x0001,  3 }, { 0x000D,  9 }, { 0x000E,  9 }, { 0x0001,  2 },
+        { 0x000F,  9 }, { 0x0010,  9 }, { 0x0011,  9 }, { 0x0012,  9 },
+        { 0x0013,  9 }, { 0x0014,  9 }, { 0x0015,  9 }, { 0x0016,  9 },
+        { 0x0017,  9 }, { 0x0018,  9 }, { 0x0019,  9 }, { 0x001A,  9 },
+        { 0x001B,  9 }, { 0x001C,  9 }, { 0x001D,  9 }, { 0x001E,  9 },
+        { 0x001F,  9 }, { 0x0020,  9 }, { 0x0021,  9 }, { 0x0022,  9 },
+        { 0x0023,  9 }, { 0x0024,  9 }, { 0x0025,  9 }, { 0x0026,  9 },
+        { 0x0027,  9 }, { 0x0028,  9 }, { 0x0029,  9 }, { 0x002A,  9 },
+        { 0x002B,  9 }, { 0x002C,  9 }, { 0x002D,  9 }, { 0x002E,  9 },
+        { 0x002F,  9 }, { 0x0030,  9 }, { 0x0031,  9 }, { 0x0032,  9 },
+        { 0x0033,  9 }, { 0x0034,  9 }, { 0x0035,  9 }, { 0x0036,  9 },
+        { 0x0037,  9 }, { 0x0038,  9 }, { 0x0039,  9 }, { 0x003A,  9 },
+        { 0x003B,  9 }, { 0x003C,  9 }, { 0x003D,  9 }, { 0x003E,  9 },
+        { 0x003F,  9 },
+    },
+    { // 6
+        { 0x0000,  2 }, { 0x0004,  4 }, { 0x000A,  5 }, { 0x000B,  5 },
+        { 0x0018,  6 }, { 0x0019,  6 }, { 0x0034,  7 }, { 0x006A,  8 },
+        { 0x006B,  8 }, { 0x006C,  8 }, { 0x00DA,  9 }, { 0x00DB,  9 },
+        { 0x01B8, 10 }, { 0x00DD,  9 }, { 0x01B9, 10 }, { 0x3780, 15 },
+        { 0x0004,  3 }, { 0x000E,  5 }, { 0x001E,  6 }, { 0x001F,  6 },
+        { 0x000A,  4 }, { 0x0058,  7 }, { 0x0017,  5 }, { 0x0018,  5 },
+        { 0x0059,  7 }, { 0x005A,  7 }, { 0x005B,  7 }, { 0x00C8,  8 },
+        { 0x0065,  7 }, { 0x0066,  7 }, { 0x00C9,  8 }, { 0x00CE,  8 },
+        { 0x00CF,  8 }, { 0x00D0,  8 }, { 0x00D1,  8 }, { 0x00D2,  8 },
+        { 0x00D3,  8 }, { 0x00DF,  9 }, { 0x00D4,  8 }, { 0x00D5,  8 },
+        { 0x00D6,  8 }, { 0x01AE,  9 }, { 0x3781, 15 }, { 0x01BD, 10 },
+        { 0x035E, 10 }, { 0x035F, 10 }, { 0x3782, 15 }, { 0x0360, 10 },
+        { 0x0037,  6 }, { 0x01B1,  9 }, { 0x3783, 15 }, { 0x3784, 15 },
+        { 0x000E,  4 }, { 0x003C,  6 }, { 0x0361, 10 }, { 0x3785, 15 },
+        { 0x1BC3, 14 }, { 0x003D,  6 }, { 0x00D9,  8 }, { 0x1BC4, 14 },
+        { 0x0368, 10 }, { 0x1BC5, 14 }, { 0x1BC6, 14 }, { 0x1BC7, 14 },
+        { 0x1BC8, 14 }, { 0x00DB,  8 }, { 0x0369, 10 }, { 0x036A, 10 },
+        { 0x1BC9, 14 }, { 0x1BCA, 14 }, { 0x1BCB, 14 }, { 0x1BCC, 14 },
+        { 0x1BCD, 14 }, { 0x001F,  5 }, { 0x036B, 10 }, { 0x1BCE, 14 },
+        { 0x1BCF, 14 },
+    },
+    { // 7
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0006,  5 }, { 0x0007,  5 },
+        { 0x0010,  6 }, { 0x0044,  8 }, { 0x0023,  7 }, { 0x0012,  6 },
+        { 0x0026,  7 }, { 0x08A0, 13 }, { 0x004E,  8 }, { 0x004F,  8 },
+        { 0x08A1, 13 }, { 0x08A2, 13 }, { 0x08A3, 13 }, { 0x0050,  8 },
+        { 0x0006,  4 }, { 0x000B,  5 }, { 0x0029,  7 }, { 0x0015,  6 },
+        { 0x001C,  6 }, { 0x003A,  7 }, { 0x001E,  6 }, { 0x0004,  3 },
+        { 0x0014,  5 }, { 0x0015,  5 }, { 0x000B,  4 }, { 0x001F,  6 },
+        { 0x0030,  6 }, { 0x0031,  6 }, { 0x0019,  5 }, { 0x0051,  8 },
+        { 0x0034,  6 }, { 0x0035,  6 }, { 0x0036,  6 }, { 0x0037,  6 },
+        { 0x0076,  8 }, { 0x0077,  8 }, { 0x0070,  7 }, { 0x001D,  5 },
+        { 0x0071,  7 }, { 0x0072,  7 }, { 0x08A4, 13 }, { 0x0073,  7 },
+        { 0x00F0,  8 }, { 0x08A5, 13 }, { 0x08A6, 13 }, { 0x08A7, 13 },
+        { 0x0079,  7 }, { 0x007A,  7 }, { 0x08A8, 13 }, { 0x08A9, 13 },
+        { 0x00F1,  8 }, { 0x08AA, 13 }, { 0x08AB, 13 }, { 0x08AC, 13 },
+        { 0x08AD, 13 }, { 0x00F6,  8 }, { 0x08AE, 13 }, { 0x007C,  7 },
+        { 0x00F7,  8 }, { 0x08AF, 13 }, { 0x08B0, 13 }, { 0x08B1, 13 },
+        { 0x08B2, 13 }, { 0x00FA,  8 }, { 0x08B3, 13 }, { 0x08B4, 13 },
+        { 0x08B5, 13 }, { 0x08B6, 13 }, { 0x08B7, 13 }, { 0x00FB,  8 },
+        { 0x045C, 12 }, { 0x003F,  6 }, { 0x045D, 12 }, { 0x045E, 12 },
+        { 0x045F, 12 },
+    },
 };
 
-static const uint16_t x8_ac1_lowquant_table[8][77][2]={
-    {//0
-        {0x0000,  3}, {0x0002,  4}, {0x0003,  4}, {0x0008,  5},
-        {0x0012,  6}, {0x0026,  7}, {0x0014,  6}, {0x004E,  8},
-        {0x004F,  8}, {0x00A8,  9}, {0x0152, 10}, {0x00AA,  9},
-        {0x00AB,  9}, {0x00AC,  9}, {0x2A60, 15}, {0x02A7, 11},
-        {0x0006,  4}, {0x000B,  5}, {0x001C,  6}, {0x003A,  7},
-        {0x000F,  5}, {0x003B,  7}, {0x0010,  5}, {0x0005,  3},
-        {0x0009,  4}, {0x0011,  5}, {0x0018,  5}, {0x0019,  5},
-        {0x001A,  5}, {0x0036,  6}, {0x0037,  6}, {0x0070,  7},
-        {0x0057,  8}, {0x00E2,  8}, {0x00E3,  8}, {0x00E4,  8},
-        {0x00E5,  8}, {0x00AD,  9}, {0x0398, 10}, {0x003A,  6},
-        {0x0076,  7}, {0x00E7,  8}, {0x00EE,  8}, {0x00EF,  8},
-        {0x0732, 11}, {0x039A, 10}, {0x0733, 11}, {0x2A61, 15},
-        {0x0078,  7}, {0x1531, 14}, {0x1532, 14}, {0x1533, 14},
-        {0x003D,  6}, {0x039B, 10}, {0x1534, 14}, {0x1535, 14},
-        {0x1536, 14}, {0x0079,  7}, {0x1537, 14}, {0x00F8,  8},
-        {0x01F2,  9}, {0x07CC, 11}, {0x03E7, 10}, {0x07CD, 11},
-        {0x3E80, 14}, {0x00FB,  8}, {0x03E9, 10}, {0x3E81, 14},
-        {0x3E82, 14}, {0x3E83, 14}, {0x3E84, 14}, {0x3E85, 14},
-        {0x3E86, 14}, {0x003F,  6}, {0x01F5,  9}, {0x07D1, 11},
-        {0x3E87, 14},
-    },{//1
-        {0x0000,  2}, {0x0002,  3}, {0x0006,  4}, {0x000E,  5},
-        {0x001E,  6}, {0x001F,  6}, {0x0040,  7}, {0x0082,  8},
-        {0x0083,  8}, {0x0084,  8}, {0x010A,  9}, {0x010B,  9},
-        {0x0430, 11}, {0x0431, 11}, {0x0432, 11}, {0x0433, 11},
-        {0x0005,  3}, {0x0011,  5}, {0x0024,  6}, {0x004A,  7},
-        {0x000C,  4}, {0x0026,  6}, {0x000D,  4}, {0x0087,  8},
-        {0x010D,  9}, {0x0258, 10}, {0x012D,  9}, {0x0259, 10},
-        {0x025C, 10}, {0x0974, 12}, {0x025E, 10}, {0x025F, 10},
-        {0x0270, 10}, {0x0271, 10}, {0x04BB, 11}, {0x0975, 12},
-        {0x0272, 10}, {0x09CC, 12}, {0x09CD, 12}, {0x4E70, 15},
-        {0x4E71, 15}, {0x4E72, 15}, {0x4E73, 15}, {0x273A, 14},
-        {0x273B, 14}, {0x273C, 14}, {0x04E8, 11}, {0x04E9, 11},
-        {0x009E,  8}, {0x0275, 10}, {0x09D8, 12}, {0x273D, 14},
-        {0x000E,  4}, {0x003C,  6}, {0x007A,  7}, {0x009F,  8},
-        {0x0277, 10}, {0x003E,  6}, {0x00F6,  8}, {0x04ED, 11},
-        {0x03DC, 10}, {0x273E, 14}, {0x07BA, 11}, {0x09D9, 12},
-        {0x273F, 14}, {0x3DD8, 14}, {0x3DD9, 14}, {0x3DDA, 14},
-        {0x3DDB, 14}, {0x3DDC, 14}, {0x3DDD, 14}, {0x3DDE, 14},
-        {0x3DDF, 14}, {0x003F,  6}, {0x07BC, 11}, {0x07BD, 11},
-        {0x03DF, 10},
-    },{//2
-        {0x0000,  3}, {0x0002,  4}, {0x0006,  5}, {0x000E,  6},
-        {0x001E,  7}, {0x003E,  8}, {0x003F,  8}, {0x0040,  8},
-        {0x0104, 10}, {0x0083,  9}, {0x0105, 10}, {0x0108, 10},
-        {0x4240, 16}, {0x010A, 10}, {0x010B, 10}, {0x4241, 16},
-        {0x0003,  3}, {0x0009,  5}, {0x0011,  6}, {0x0043,  8},
-        {0x0004,  3}, {0x000A,  5}, {0x000A,  4}, {0x002C,  7},
-        {0x00B4,  9}, {0x00B5,  9}, {0x00B6,  9}, {0x00B7,  9},
-        {0x00B8,  9}, {0x0172, 10}, {0x0173, 10}, {0x0174, 10},
-        {0x0175, 10}, {0x0176, 10}, {0x0177, 10}, {0x00BC,  9},
-        {0x017A, 10}, {0x0213, 11}, {0x4242, 16}, {0x017B, 10},
-        {0x02F8, 11}, {0x017D, 10}, {0x02F9, 11}, {0x017E, 10},
-        {0x4243, 16}, {0x02FE, 11}, {0x2122, 15}, {0x2123, 15},
-        {0x0058,  7}, {0x0164,  9}, {0x2124, 15}, {0x2125, 15},
-        {0x0006,  3}, {0x000E,  4}, {0x002D,  6}, {0x002E,  6},
-        {0x00B3,  8}, {0x001E,  5}, {0x005E,  7}, {0x2126, 15},
-        {0x2127, 15}, {0x2128, 15}, {0x2129, 15}, {0x02FF, 11},
-        {0x212A, 15}, {0x0594, 11}, {0x0595, 11}, {0x0596, 11},
-        {0x212B, 15}, {0x212C, 15}, {0x212D, 15}, {0x212E, 15},
-        {0x212F, 15}, {0x001F,  5}, {0x0597, 11}, {0x00BE,  8},
-        {0x00BF,  8},
-    },{//3
-        {0x0000,  2}, {0x0002,  3}, {0x0006,  4}, {0x0007,  4},
-        {0x0010,  5}, {0x0011,  5}, {0x0024,  6}, {0x0025,  6},
-        {0x0026,  6}, {0x0027,  6}, {0x0050,  7}, {0x0051,  7},
-        {0x00A4,  8}, {0x00A5,  8}, {0x00A6,  8}, {0x014E,  9},
-        {0x000B,  4}, {0x002A,  6}, {0x0056,  7}, {0x014F,  9},
-        {0x0030,  6}, {0x00AE,  8}, {0x0062,  7}, {0x0032,  6},
-        {0x0033,  6}, {0x0034,  6}, {0x0035,  6}, {0x0036,  6},
-        {0x0063,  7}, {0x006E,  7}, {0x006F,  7}, {0x0070,  7},
-        {0x0071,  7}, {0x0072,  7}, {0x0073,  7}, {0x0074,  7},
-        {0x00AF,  8}, {0x00EA,  8}, {0x01D6,  9}, {0x075C, 11},
-        {0x03AF, 10}, {0x75D0, 15}, {0x75D1, 15}, {0x75D2, 15},
-        {0x75D3, 15}, {0x75D4, 15}, {0x0076,  7}, {0x00EE,  8},
-        {0x00EF,  8}, {0x0EBB, 12}, {0x01E0,  9}, {0x75D5, 15},
-        {0x0079,  7}, {0x01E1,  9}, {0x75D6, 15}, {0x75D7, 15},
-        {0x7880, 15}, {0x00F4,  8}, {0x0789, 11}, {0x003E,  6},
-        {0x007B,  7}, {0x00F5,  8}, {0x00FC,  8}, {0x007F,  7},
-        {0x01E3,  9}, {0x078A, 11}, {0x078B, 11}, {0x7881, 15},
-        {0x7882, 15}, {0x7883, 15}, {0x3C42, 14}, {0x3C43, 14},
-        {0x3C44, 14}, {0x00FD,  8}, {0x3C45, 14}, {0x3C46, 14},
-        {0x3C47, 14},
-    },{//4
-        {0x0000,  2}, {0x0004,  4}, {0x000A,  5}, {0x0016,  6},
-        {0x0017,  6}, {0x0030,  7}, {0x0031,  7}, {0x0064,  8},
-        {0x0065,  8}, {0x0066,  8}, {0x00CE,  9}, {0x00CF,  9},
-        {0x01A0, 10}, {0x01A1, 10}, {0x1A20, 14}, {0x0689, 12},
-        {0x0004,  3}, {0x000E,  5}, {0x001B,  6}, {0x0035,  7},
-        {0x000A,  4}, {0x001E,  6}, {0x0016,  5}, {0x0017,  5},
-        {0x001F,  6}, {0x0030,  6}, {0x0031,  6}, {0x0064,  7},
-        {0x0065,  7}, {0x0069,  8}, {0x0066,  7}, {0x00CE,  8},
-        {0x00CF,  8}, {0x00D0,  8}, {0x00D1,  8}, {0x00D2,  8},
-        {0x01A6,  9}, {0x01A3, 10}, {0x034E, 10}, {0x006A,  7},
-        {0x00D6,  8}, {0x01AE,  9}, {0x01AF,  9}, {0x034F, 10},
-        {0x0345, 11}, {0x01B0,  9}, {0x01B1,  9}, {0x0364, 10},
-        {0x006D,  7}, {0x00DC,  8}, {0x0D94, 12}, {0x0D95, 12},
-        {0x000E,  4}, {0x003C,  6}, {0x00DD,  8}, {0x00DE,  8},
-        {0x01B3,  9}, {0x003D,  6}, {0x00DF,  8}, {0x01F0,  9},
-        {0x03E2, 10}, {0x03E3, 10}, {0x06CB, 11}, {0x03E4, 10},
-        {0x07CA, 11}, {0x01F3,  9}, {0x01F4,  9}, {0x07CB, 11},
-        {0x07D4, 11}, {0x1A21, 14}, {0x1A22, 14}, {0x07D5, 11},
-        {0x1A23, 14}, {0x003F,  6}, {0x01F6,  9}, {0x01F7,  9},
-        {0x03EB, 10},
-    },{//5
-        {0x0000,  2}, {0x0002,  3}, {0x0006,  4}, {0x000E,  5},
-        {0x000F,  5}, {0x0020,  6}, {0x0021,  6}, {0x0044,  7},
-        {0x0045,  7}, {0x0046,  7}, {0x008E,  8}, {0x008F,  8},
-        {0x0090,  8}, {0x0122,  9}, {0x0246, 10}, {0x0124,  9},
-        {0x0005,  3}, {0x0013,  5}, {0x004A,  7}, {0x0093,  8},
-        {0x0018,  5}, {0x004B,  7}, {0x0032,  6}, {0x001A,  5},
-        {0x0033,  6}, {0x006C,  7}, {0x006D,  7}, {0x006E,  7},
-        {0x00DE,  8}, {0x00DF,  8}, {0x0070,  7}, {0x00E2,  8},
-        {0x00E3,  8}, {0x00E4,  8}, {0x00E5,  8}, {0x00E6,  8},
-        {0x00E7,  8}, {0x0125,  9}, {0x01D0,  9}, {0x048E, 11},
-        {0x091E, 12}, {0x091F, 12}, {0x7440, 15}, {0x1D11, 13},
-        {0x7441, 15}, {0x7442, 15}, {0x00E9,  8}, {0x01D4,  9},
-        {0x00EB,  8}, {0x03A3, 10}, {0x01D5,  9}, {0x1D12, 13},
-        {0x001E,  5}, {0x0076,  7}, {0x01DC,  9}, {0x01DD,  9},
-        {0x7443, 15}, {0x007C,  7}, {0x0745, 11}, {0x00EF,  8},
-        {0x00FA,  8}, {0x00FB,  8}, {0x01F8,  9}, {0x00FD,  8},
-        {0x07E4, 11}, {0x0FCA, 12}, {0x1D13, 13}, {0x7E58, 15},
-        {0x7E59, 15}, {0x7E5A, 15}, {0x7E5B, 15}, {0x7E5C, 15},
-        {0x7E5D, 15}, {0x007F,  7}, {0x3F2F, 14}, {0x07E6, 11},
-        {0x07E7, 11},
-    },{//6
-        {0x0000,  3}, {0x0002,  4}, {0x0003,  4}, {0x0008,  5},
-        {0x0009,  5}, {0x0014,  6}, {0x0015,  6}, {0x002C,  7},
-        {0x005A,  8}, {0x005B,  8}, {0x005C,  8}, {0x00BA,  9},
-        {0x00BB,  9}, {0x00BC,  9}, {0x02F4, 11}, {0x05EA, 12},
-        {0x0003,  3}, {0x0010,  5}, {0x0022,  6}, {0x0046,  7},
-        {0x0009,  4}, {0x0028,  6}, {0x0015,  5}, {0x000B,  4},
-        {0x0018,  5}, {0x0029,  6}, {0x0032,  6}, {0x0047,  7},
-        {0x0066,  7}, {0x0067,  7}, {0x0068,  7}, {0x0069,  7},
-        {0x006A,  7}, {0x005F,  8}, {0x00D6,  8}, {0x00D7,  8},
-        {0x01B0,  9}, {0x00D9,  8}, {0x017B, 10}, {0x006D,  7},
-        {0x00DC,  8}, {0x01B1,  9}, {0x06E8, 11}, {0x01BB,  9},
-        {0x0375, 10}, {0x05EB, 12}, {0x01BC,  9}, {0x6E90, 15},
-        {0x0038,  6}, {0x0072,  7}, {0x6E91, 15}, {0x6E92, 15},
-        {0x001D,  5}, {0x0073,  7}, {0x01BD,  9}, {0x06F8, 11},
-        {0x6E93, 15}, {0x003C,  6}, {0x01BF,  9}, {0x00F4,  8},
-        {0x01EA,  9}, {0x037D, 10}, {0x03D6, 10}, {0x06F9, 11},
-        {0x6E94, 15}, {0x00F6,  8}, {0x01EE,  9}, {0x6E95, 15},
-        {0x6E96, 15}, {0x6E97, 15}, {0x374C, 14}, {0x374D, 14},
-        {0x374E, 14}, {0x001F,  5}, {0x03D7, 10}, {0x01EF,  9},
-        {0x374F, 14},
-    },{//7
-        {0x0000,  2}, {0x0004,  4}, {0x000A,  5}, {0x0016,  6},
-        {0x002E,  7}, {0x002F,  7}, {0x0060,  8}, {0x0061,  8},
-        {0x00C4,  9}, {0x00C5,  9}, {0x00C6,  9}, {0x018E, 10},
-        {0x31E0, 15}, {0x31E1, 15}, {0x31E2, 15}, {0x31E3, 15},
-        {0x0004,  3}, {0x000D,  5}, {0x0019,  6}, {0x0038,  7},
-        {0x000A,  4}, {0x001D,  6}, {0x000B,  4}, {0x0072,  8},
-        {0x0073,  8}, {0x00F0,  9}, {0x01E2, 10}, {0x00F2,  9},
-        {0x01E3, 10}, {0x00F3,  9}, {0x01E8, 10}, {0x01E9, 10},
-        {0x31E4, 15}, {0x01EA, 10}, {0x031F, 11}, {0x03D6, 11},
-        {0x31E5, 15}, {0x01EC, 10}, {0x31E6, 15}, {0x00F7,  9},
-        {0x03D7, 11}, {0x31E7, 15}, {0x31E8, 15}, {0x03DA, 11},
-        {0x03DB, 11}, {0x31E9, 15}, {0x03E0, 11}, {0x31EA, 15},
-        {0x003F,  7}, {0x01F1, 10}, {0x31EB, 15}, {0x31EC, 15},
-        {0x0006,  3}, {0x001C,  5}, {0x0074,  7}, {0x0075,  7},
-        {0x00F9,  9}, {0x001E,  5}, {0x0076,  7}, {0x00FA,  9},
-        {0x03E1, 11}, {0x31ED, 15}, {0x18F7, 14}, {0x1F60, 14},
-        {0x1F61, 14}, {0x01DC,  9}, {0x01DD,  9}, {0x1F62, 14},
-        {0x1F63, 14}, {0x1F64, 14}, {0x1F65, 14}, {0x1F66, 14},
-        {0x1F67, 14}, {0x001F,  5}, {0x03ED, 11}, {0x00EF,  8},
-        {0x01F7, 10},
-    }
+static const uint16_t x8_ac1_lowquant_table[8][77][2] = {
+    { // 0
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0003,  4 }, { 0x0008,  5 },
+        { 0x0012,  6 }, { 0x0026,  7 }, { 0x0014,  6 }, { 0x004E,  8 },
+        { 0x004F,  8 }, { 0x00A8,  9 }, { 0x0152, 10 }, { 0x00AA,  9 },
+        { 0x00AB,  9 }, { 0x00AC,  9 }, { 0x2A60, 15 }, { 0x02A7, 11 },
+        { 0x0006,  4 }, { 0x000B,  5 }, { 0x001C,  6 }, { 0x003A,  7 },
+        { 0x000F,  5 }, { 0x003B,  7 }, { 0x0010,  5 }, { 0x0005,  3 },
+        { 0x0009,  4 }, { 0x0011,  5 }, { 0x0018,  5 }, { 0x0019,  5 },
+        { 0x001A,  5 }, { 0x0036,  6 }, { 0x0037,  6 }, { 0x0070,  7 },
+        { 0x0057,  8 }, { 0x00E2,  8 }, { 0x00E3,  8 }, { 0x00E4,  8 },
+        { 0x00E5,  8 }, { 0x00AD,  9 }, { 0x0398, 10 }, { 0x003A,  6 },
+        { 0x0076,  7 }, { 0x00E7,  8 }, { 0x00EE,  8 }, { 0x00EF,  8 },
+        { 0x0732, 11 }, { 0x039A, 10 }, { 0x0733, 11 }, { 0x2A61, 15 },
+        { 0x0078,  7 }, { 0x1531, 14 }, { 0x1532, 14 }, { 0x1533, 14 },
+        { 0x003D,  6 }, { 0x039B, 10 }, { 0x1534, 14 }, { 0x1535, 14 },
+        { 0x1536, 14 }, { 0x0079,  7 }, { 0x1537, 14 }, { 0x00F8,  8 },
+        { 0x01F2,  9 }, { 0x07CC, 11 }, { 0x03E7, 10 }, { 0x07CD, 11 },
+        { 0x3E80, 14 }, { 0x00FB,  8 }, { 0x03E9, 10 }, { 0x3E81, 14 },
+        { 0x3E82, 14 }, { 0x3E83, 14 }, { 0x3E84, 14 }, { 0x3E85, 14 },
+        { 0x3E86, 14 }, { 0x003F,  6 }, { 0x01F5,  9 }, { 0x07D1, 11 },
+        { 0x3E87, 14 },
+    },
+    { // 1
+        { 0x0000,  2 }, { 0x0002,  3 }, { 0x0006,  4 }, { 0x000E,  5 },
+        { 0x001E,  6 }, { 0x001F,  6 }, { 0x0040,  7 }, { 0x0082,  8 },
+        { 0x0083,  8 }, { 0x0084,  8 }, { 0x010A,  9 }, { 0x010B,  9 },
+        { 0x0430, 11 }, { 0x0431, 11 }, { 0x0432, 11 }, { 0x0433, 11 },
+        { 0x0005,  3 }, { 0x0011,  5 }, { 0x0024,  6 }, { 0x004A,  7 },
+        { 0x000C,  4 }, { 0x0026,  6 }, { 0x000D,  4 }, { 0x0087,  8 },
+        { 0x010D,  9 }, { 0x0258, 10 }, { 0x012D,  9 }, { 0x0259, 10 },
+        { 0x025C, 10 }, { 0x0974, 12 }, { 0x025E, 10 }, { 0x025F, 10 },
+        { 0x0270, 10 }, { 0x0271, 10 }, { 0x04BB, 11 }, { 0x0975, 12 },
+        { 0x0272, 10 }, { 0x09CC, 12 }, { 0x09CD, 12 }, { 0x4E70, 15 },
+        { 0x4E71, 15 }, { 0x4E72, 15 }, { 0x4E73, 15 }, { 0x273A, 14 },
+        { 0x273B, 14 }, { 0x273C, 14 }, { 0x04E8, 11 }, { 0x04E9, 11 },
+        { 0x009E,  8 }, { 0x0275, 10 }, { 0x09D8, 12 }, { 0x273D, 14 },
+        { 0x000E,  4 }, { 0x003C,  6 }, { 0x007A,  7 }, { 0x009F,  8 },
+        { 0x0277, 10 }, { 0x003E,  6 }, { 0x00F6,  8 }, { 0x04ED, 11 },
+        { 0x03DC, 10 }, { 0x273E, 14 }, { 0x07BA, 11 }, { 0x09D9, 12 },
+        { 0x273F, 14 }, { 0x3DD8, 14 }, { 0x3DD9, 14 }, { 0x3DDA, 14 },
+        { 0x3DDB, 14 }, { 0x3DDC, 14 }, { 0x3DDD, 14 }, { 0x3DDE, 14 },
+        { 0x3DDF, 14 }, { 0x003F,  6 }, { 0x07BC, 11 }, { 0x07BD, 11 },
+        { 0x03DF, 10 },
+    },
+    { // 2
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0006,  5 }, { 0x000E,  6 },
+        { 0x001E,  7 }, { 0x003E,  8 }, { 0x003F,  8 }, { 0x0040,  8 },
+        { 0x0104, 10 }, { 0x0083,  9 }, { 0x0105, 10 }, { 0x0108, 10 },
+        { 0x4240, 16 }, { 0x010A, 10 }, { 0x010B, 10 }, { 0x4241, 16 },
+        { 0x0003,  3 }, { 0x0009,  5 }, { 0x0011,  6 }, { 0x0043,  8 },
+        { 0x0004,  3 }, { 0x000A,  5 }, { 0x000A,  4 }, { 0x002C,  7 },
+        { 0x00B4,  9 }, { 0x00B5,  9 }, { 0x00B6,  9 }, { 0x00B7,  9 },
+        { 0x00B8,  9 }, { 0x0172, 10 }, { 0x0173, 10 }, { 0x0174, 10 },
+        { 0x0175, 10 }, { 0x0176, 10 }, { 0x0177, 10 }, { 0x00BC,  9 },
+        { 0x017A, 10 }, { 0x0213, 11 }, { 0x4242, 16 }, { 0x017B, 10 },
+        { 0x02F8, 11 }, { 0x017D, 10 }, { 0x02F9, 11 }, { 0x017E, 10 },
+        { 0x4243, 16 }, { 0x02FE, 11 }, { 0x2122, 15 }, { 0x2123, 15 },
+        { 0x0058,  7 }, { 0x0164,  9 }, { 0x2124, 15 }, { 0x2125, 15 },
+        { 0x0006,  3 }, { 0x000E,  4 }, { 0x002D,  6 }, { 0x002E,  6 },
+        { 0x00B3,  8 }, { 0x001E,  5 }, { 0x005E,  7 }, { 0x2126, 15 },
+        { 0x2127, 15 }, { 0x2128, 15 }, { 0x2129, 15 }, { 0x02FF, 11 },
+        { 0x212A, 15 }, { 0x0594, 11 }, { 0x0595, 11 }, { 0x0596, 11 },
+        { 0x212B, 15 }, { 0x212C, 15 }, { 0x212D, 15 }, { 0x212E, 15 },
+        { 0x212F, 15 }, { 0x001F,  5 }, { 0x0597, 11 }, { 0x00BE,  8 },
+        { 0x00BF,  8 },
+    },
+    { // 3
+        { 0x0000,  2 }, { 0x0002,  3 }, { 0x0006,  4 }, { 0x0007,  4 },
+        { 0x0010,  5 }, { 0x0011,  5 }, { 0x0024,  6 }, { 0x0025,  6 },
+        { 0x0026,  6 }, { 0x0027,  6 }, { 0x0050,  7 }, { 0x0051,  7 },
+        { 0x00A4,  8 }, { 0x00A5,  8 }, { 0x00A6,  8 }, { 0x014E,  9 },
+        { 0x000B,  4 }, { 0x002A,  6 }, { 0x0056,  7 }, { 0x014F,  9 },
+        { 0x0030,  6 }, { 0x00AE,  8 }, { 0x0062,  7 }, { 0x0032,  6 },
+        { 0x0033,  6 }, { 0x0034,  6 }, { 0x0035,  6 }, { 0x0036,  6 },
+        { 0x0063,  7 }, { 0x006E,  7 }, { 0x006F,  7 }, { 0x0070,  7 },
+        { 0x0071,  7 }, { 0x0072,  7 }, { 0x0073,  7 }, { 0x0074,  7 },
+        { 0x00AF,  8 }, { 0x00EA,  8 }, { 0x01D6,  9 }, { 0x075C, 11 },
+        { 0x03AF, 10 }, { 0x75D0, 15 }, { 0x75D1, 15 }, { 0x75D2, 15 },
+        { 0x75D3, 15 }, { 0x75D4, 15 }, { 0x0076,  7 }, { 0x00EE,  8 },
+        { 0x00EF,  8 }, { 0x0EBB, 12 }, { 0x01E0,  9 }, { 0x75D5, 15 },
+        { 0x0079,  7 }, { 0x01E1,  9 }, { 0x75D6, 15 }, { 0x75D7, 15 },
+        { 0x7880, 15 }, { 0x00F4,  8 }, { 0x0789, 11 }, { 0x003E,  6 },
+        { 0x007B,  7 }, { 0x00F5,  8 }, { 0x00FC,  8 }, { 0x007F,  7 },
+        { 0x01E3,  9 }, { 0x078A, 11 }, { 0x078B, 11 }, { 0x7881, 15 },
+        { 0x7882, 15 }, { 0x7883, 15 }, { 0x3C42, 14 }, { 0x3C43, 14 },
+        { 0x3C44, 14 }, { 0x00FD,  8 }, { 0x3C45, 14 }, { 0x3C46, 14 },
+        { 0x3C47, 14 },
+    },
+    { // 4
+        { 0x0000,  2 }, { 0x0004,  4 }, { 0x000A,  5 }, { 0x0016,  6 },
+        { 0x0017,  6 }, { 0x0030,  7 }, { 0x0031,  7 }, { 0x0064,  8 },
+        { 0x0065,  8 }, { 0x0066,  8 }, { 0x00CE,  9 }, { 0x00CF,  9 },
+        { 0x01A0, 10 }, { 0x01A1, 10 }, { 0x1A20, 14 }, { 0x0689, 12 },
+        { 0x0004,  3 }, { 0x000E,  5 }, { 0x001B,  6 }, { 0x0035,  7 },
+        { 0x000A,  4 }, { 0x001E,  6 }, { 0x0016,  5 }, { 0x0017,  5 },
+        { 0x001F,  6 }, { 0x0030,  6 }, { 0x0031,  6 }, { 0x0064,  7 },
+        { 0x0065,  7 }, { 0x0069,  8 }, { 0x0066,  7 }, { 0x00CE,  8 },
+        { 0x00CF,  8 }, { 0x00D0,  8 }, { 0x00D1,  8 }, { 0x00D2,  8 },
+        { 0x01A6,  9 }, { 0x01A3, 10 }, { 0x034E, 10 }, { 0x006A,  7 },
+        { 0x00D6,  8 }, { 0x01AE,  9 }, { 0x01AF,  9 }, { 0x034F, 10 },
+        { 0x0345, 11 }, { 0x01B0,  9 }, { 0x01B1,  9 }, { 0x0364, 10 },
+        { 0x006D,  7 }, { 0x00DC,  8 }, { 0x0D94, 12 }, { 0x0D95, 12 },
+        { 0x000E,  4 }, { 0x003C,  6 }, { 0x00DD,  8 }, { 0x00DE,  8 },
+        { 0x01B3,  9 }, { 0x003D,  6 }, { 0x00DF,  8 }, { 0x01F0,  9 },
+        { 0x03E2, 10 }, { 0x03E3, 10 }, { 0x06CB, 11 }, { 0x03E4, 10 },
+        { 0x07CA, 11 }, { 0x01F3,  9 }, { 0x01F4,  9 }, { 0x07CB, 11 },
+        { 0x07D4, 11 }, { 0x1A21, 14 }, { 0x1A22, 14 }, { 0x07D5, 11 },
+        { 0x1A23, 14 }, { 0x003F,  6 }, { 0x01F6,  9 }, { 0x01F7,  9 },
+        { 0x03EB, 10 },
+    },
+    { // 5
+        { 0x0000,  2 }, { 0x0002,  3 }, { 0x0006,  4 }, { 0x000E,  5 },
+        { 0x000F,  5 }, { 0x0020,  6 }, { 0x0021,  6 }, { 0x0044,  7 },
+        { 0x0045,  7 }, { 0x0046,  7 }, { 0x008E,  8 }, { 0x008F,  8 },
+        { 0x0090,  8 }, { 0x0122,  9 }, { 0x0246, 10 }, { 0x0124,  9 },
+        { 0x0005,  3 }, { 0x0013,  5 }, { 0x004A,  7 }, { 0x0093,  8 },
+        { 0x0018,  5 }, { 0x004B,  7 }, { 0x0032,  6 }, { 0x001A,  5 },
+        { 0x0033,  6 }, { 0x006C,  7 }, { 0x006D,  7 }, { 0x006E,  7 },
+        { 0x00DE,  8 }, { 0x00DF,  8 }, { 0x0070,  7 }, { 0x00E2,  8 },
+        { 0x00E3,  8 }, { 0x00E4,  8 }, { 0x00E5,  8 }, { 0x00E6,  8 },
+        { 0x00E7,  8 }, { 0x0125,  9 }, { 0x01D0,  9 }, { 0x048E, 11 },
+        { 0x091E, 12 }, { 0x091F, 12 }, { 0x7440, 15 }, { 0x1D11, 13 },
+        { 0x7441, 15 }, { 0x7442, 15 }, { 0x00E9,  8 }, { 0x01D4,  9 },
+        { 0x00EB,  8 }, { 0x03A3, 10 }, { 0x01D5,  9 }, { 0x1D12, 13 },
+        { 0x001E,  5 }, { 0x0076,  7 }, { 0x01DC,  9 }, { 0x01DD,  9 },
+        { 0x7443, 15 }, { 0x007C,  7 }, { 0x0745, 11 }, { 0x00EF,  8 },
+        { 0x00FA,  8 }, { 0x00FB,  8 }, { 0x01F8,  9 }, { 0x00FD,  8 },
+        { 0x07E4, 11 }, { 0x0FCA, 12 }, { 0x1D13, 13 }, { 0x7E58, 15 },
+        { 0x7E59, 15 }, { 0x7E5A, 15 }, { 0x7E5B, 15 }, { 0x7E5C, 15 },
+        { 0x7E5D, 15 }, { 0x007F,  7 }, { 0x3F2F, 14 }, { 0x07E6, 11 },
+        { 0x07E7, 11 },
+    },
+    { // 6
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0003,  4 }, { 0x0008,  5 },
+        { 0x0009,  5 }, { 0x0014,  6 }, { 0x0015,  6 }, { 0x002C,  7 },
+        { 0x005A,  8 }, { 0x005B,  8 }, { 0x005C,  8 }, { 0x00BA,  9 },
+        { 0x00BB,  9 }, { 0x00BC,  9 }, { 0x02F4, 11 }, { 0x05EA, 12 },
+        { 0x0003,  3 }, { 0x0010,  5 }, { 0x0022,  6 }, { 0x0046,  7 },
+        { 0x0009,  4 }, { 0x0028,  6 }, { 0x0015,  5 }, { 0x000B,  4 },
+        { 0x0018,  5 }, { 0x0029,  6 }, { 0x0032,  6 }, { 0x0047,  7 },
+        { 0x0066,  7 }, { 0x0067,  7 }, { 0x0068,  7 }, { 0x0069,  7 },
+        { 0x006A,  7 }, { 0x005F,  8 }, { 0x00D6,  8 }, { 0x00D7,  8 },
+        { 0x01B0,  9 }, { 0x00D9,  8 }, { 0x017B, 10 }, { 0x006D,  7 },
+        { 0x00DC,  8 }, { 0x01B1,  9 }, { 0x06E8, 11 }, { 0x01BB,  9 },
+        { 0x0375, 10 }, { 0x05EB, 12 }, { 0x01BC,  9 }, { 0x6E90, 15 },
+        { 0x0038,  6 }, { 0x0072,  7 }, { 0x6E91, 15 }, { 0x6E92, 15 },
+        { 0x001D,  5 }, { 0x0073,  7 }, { 0x01BD,  9 }, { 0x06F8, 11 },
+        { 0x6E93, 15 }, { 0x003C,  6 }, { 0x01BF,  9 }, { 0x00F4,  8 },
+        { 0x01EA,  9 }, { 0x037D, 10 }, { 0x03D6, 10 }, { 0x06F9, 11 },
+        { 0x6E94, 15 }, { 0x00F6,  8 }, { 0x01EE,  9 }, { 0x6E95, 15 },
+        { 0x6E96, 15 }, { 0x6E97, 15 }, { 0x374C, 14 }, { 0x374D, 14 },
+        { 0x374E, 14 }, { 0x001F,  5 }, { 0x03D7, 10 }, { 0x01EF,  9 },
+        { 0x374F, 14 },
+    },
+    { // 7
+        { 0x0000,  2 }, { 0x0004,  4 }, { 0x000A,  5 }, { 0x0016,  6 },
+        { 0x002E,  7 }, { 0x002F,  7 }, { 0x0060,  8 }, { 0x0061,  8 },
+        { 0x00C4,  9 }, { 0x00C5,  9 }, { 0x00C6,  9 }, { 0x018E, 10 },
+        { 0x31E0, 15 }, { 0x31E1, 15 }, { 0x31E2, 15 }, { 0x31E3, 15 },
+        { 0x0004,  3 }, { 0x000D,  5 }, { 0x0019,  6 }, { 0x0038,  7 },
+        { 0x000A,  4 }, { 0x001D,  6 }, { 0x000B,  4 }, { 0x0072,  8 },
+        { 0x0073,  8 }, { 0x00F0,  9 }, { 0x01E2, 10 }, { 0x00F2,  9 },
+        { 0x01E3, 10 }, { 0x00F3,  9 }, { 0x01E8, 10 }, { 0x01E9, 10 },
+        { 0x31E4, 15 }, { 0x01EA, 10 }, { 0x031F, 11 }, { 0x03D6, 11 },
+        { 0x31E5, 15 }, { 0x01EC, 10 }, { 0x31E6, 15 }, { 0x00F7,  9 },
+        { 0x03D7, 11 }, { 0x31E7, 15 }, { 0x31E8, 15 }, { 0x03DA, 11 },
+        { 0x03DB, 11 }, { 0x31E9, 15 }, { 0x03E0, 11 }, { 0x31EA, 15 },
+        { 0x003F,  7 }, { 0x01F1, 10 }, { 0x31EB, 15 }, { 0x31EC, 15 },
+        { 0x0006,  3 }, { 0x001C,  5 }, { 0x0074,  7 }, { 0x0075,  7 },
+        { 0x00F9,  9 }, { 0x001E,  5 }, { 0x0076,  7 }, { 0x00FA,  9 },
+        { 0x03E1, 11 }, { 0x31ED, 15 }, { 0x18F7, 14 }, { 0x1F60, 14 },
+        { 0x1F61, 14 }, { 0x01DC,  9 }, { 0x01DD,  9 }, { 0x1F62, 14 },
+        { 0x1F63, 14 }, { 0x1F64, 14 }, { 0x1F65, 14 }, { 0x1F66, 14 },
+        { 0x1F67, 14 }, { 0x001F,  5 }, { 0x03ED, 11 }, { 0x00EF,  8 },
+        { 0x01F7, 10 },
+    },
 };
 
-static const uint16_t x8_ac1_highquant_table[8][77][2]={
-    {//0
-        {0x0000,  3}, {0x0002,  4}, {0x0006,  5}, {0x0007,  5},
-        {0x0008,  5}, {0x0009,  5}, {0x0014,  6}, {0x002A,  7},
-        {0x0016,  6}, {0x002B,  7}, {0x005C,  8}, {0x002F,  7},
-        {0x0030,  7}, {0x005D,  8}, {0x0062,  8}, {0x00C6,  9},
-        {0x0007,  4}, {0x0019,  6}, {0x001A,  6}, {0x0036,  7},
-        {0x0010,  5}, {0x006E,  8}, {0x0022,  6}, {0x0009,  4},
-        {0x000A,  4}, {0x0016,  5}, {0x0023,  6}, {0x002E,  6},
-        {0x002F,  6}, {0x0030,  6}, {0x0062,  7}, {0x0063,  7},
-        {0x0064,  7}, {0x0065,  7}, {0x0066,  7}, {0x0067,  7},
-        {0x0068,  7}, {0x0069,  7}, {0x006A,  7}, {0x006B,  7},
-        {0x006C,  7}, {0x00C7,  9}, {0x00DE,  9}, {0x00DF,  9},
-        {0x06D0, 11}, {0x01B5,  9}, {0x0037,  6}, {0x00DB,  8},
-        {0x001C,  5}, {0x0074,  7}, {0x01D4,  9}, {0x01D5,  9},
-        {0x0076,  7}, {0x0369, 10}, {0x3688, 14}, {0x3689, 14},
-        {0x368A, 14}, {0x0077,  7}, {0x03AC, 10}, {0x0078,  7},
-        {0x00F2,  8}, {0x01D7,  9}, {0x00F3,  8}, {0x007A,  7},
-        {0x368B, 14}, {0x007B,  7}, {0x007C,  7}, {0x03AD, 10},
-        {0x03E8, 10}, {0x368C, 14}, {0x368D, 14}, {0x03E9, 10},
-        {0x368E, 14}, {0x003F,  6}, {0x01F5,  9}, {0x00FB,  8},
-        {0x368F, 14},
-    },{//1
-        {0x0000,  2}, {0x0004,  4}, {0x000A,  5}, {0x000B,  5},
-        {0x0018,  6}, {0x0032,  7}, {0x0033,  7}, {0x0034,  7},
-        {0x006A,  8}, {0x00D6,  9}, {0x00D7,  9}, {0x00D8,  9},
-        {0x00D9,  9}, {0x3680, 15}, {0x01B5, 10}, {0x0369, 11},
-        {0x0004,  3}, {0x000E,  5}, {0x001E,  6}, {0x0037,  7},
-        {0x000A,  4}, {0x0016,  5}, {0x000C,  4}, {0x001F,  6},
-        {0x005C,  7}, {0x005D,  7}, {0x00BC,  8}, {0x00BD,  8},
-        {0x005F,  7}, {0x00D0,  8}, {0x00DB,  9}, {0x00D1,  8},
-        {0x01A4,  9}, {0x01A5,  9}, {0x01A6,  9}, {0x01A7,  9},
-        {0x0350, 10}, {0x06A2, 11}, {0x06A3, 11}, {0x01A9,  9},
-        {0x01AA,  9}, {0x06AC, 11}, {0x3681, 15}, {0x0357, 10},
-        {0x3682, 15}, {0x3683, 15}, {0x3684, 15}, {0x3685, 15},
-        {0x0036,  6}, {0x00D6,  8}, {0x3686, 15}, {0x3687, 15},
-        {0x000E,  4}, {0x006E,  7}, {0x00D7,  8}, {0x06AD, 11},
-        {0x3688, 15}, {0x001E,  5}, {0x00DE,  8}, {0x06F8, 11},
-        {0x037D, 10}, {0x3689, 15}, {0x368A, 15}, {0x368B, 15},
-        {0x368C, 15}, {0x01BF,  9}, {0x368D, 15}, {0x1B47, 14},
-        {0x37C8, 14}, {0x37C9, 14}, {0x37CA, 14}, {0x37CB, 14},
-        {0x37CC, 14}, {0x001F,  5}, {0x37CD, 14}, {0x37CE, 14},
-        {0x37CF, 14},
-    },{//2
-        {0x0000,  3}, {0x0002,  4}, {0x0003,  4}, {0x0008,  5},
-        {0x0012,  6}, {0x0026,  7}, {0x0014,  6}, {0x0027,  7},
-        {0x00A8,  9}, {0x00A9,  9}, {0x0055,  8}, {0x2B00, 15},
-        {0x00AD,  9}, {0x2B01, 15}, {0x2B02, 15}, {0x2B03, 15},
-        {0x0003,  3}, {0x000B,  5}, {0x0040,  7}, {0x0041,  7},
-        {0x0009,  4}, {0x0021,  6}, {0x0011,  5}, {0x000A,  4},
-        {0x000B,  4}, {0x0018,  5}, {0x0032,  6}, {0x0033,  6},
-        {0x0034,  6}, {0x0035,  6}, {0x006C,  7}, {0x0057,  8},
-        {0x006D,  7}, {0x00DC,  8}, {0x0159, 10}, {0x00DD,  8},
-        {0x01BC,  9}, {0x037A, 10}, {0x037B, 10}, {0x0038,  6},
-        {0x0072,  7}, {0x01BE,  9}, {0x01BF,  9}, {0x00E6,  8},
-        {0x039C, 10}, {0x01CF,  9}, {0x2B04, 15}, {0x2B05, 15},
-        {0x0074,  7}, {0x01D4,  9}, {0x2B06, 15}, {0x2B07, 15},
-        {0x001E,  5}, {0x00EB,  8}, {0x1584, 14}, {0x1585, 14},
-        {0x1586, 14}, {0x003B,  6}, {0x01D5,  9}, {0x01F0,  9},
-        {0x039D, 10}, {0x03E2, 10}, {0x1587, 14}, {0x1588, 14},
-        {0x1589, 14}, {0x00F9,  8}, {0x158A, 14}, {0x158B, 14},
-        {0x03E3, 10}, {0x158C, 14}, {0x158D, 14}, {0x01F4,  9},
-        {0x158E, 14}, {0x003F,  6}, {0x00FB,  8}, {0x01F5,  9},
-        {0x158F, 14},
-    },{//3
-        {0x0000,  3}, {0x0002,  4}, {0x0006,  5}, {0x0007,  5},
-        {0x0010,  6}, {0x0011,  6}, {0x0024,  7}, {0x0025,  7},
-        {0x0013,  6}, {0x0014,  6}, {0x002A,  7}, {0x002B,  7},
-        {0x00B0,  9}, {0x00B1,  9}, {0x002D,  7}, {0x0059,  8},
-        {0x000C,  5}, {0x0017,  6}, {0x00D0,  9}, {0x0035,  7},
-        {0x001B,  6}, {0x0038,  7}, {0x0039,  7}, {0x0004,  3},
-        {0x0005,  3}, {0x000F,  5}, {0x0018,  5}, {0x001D,  6},
-        {0x0032,  6}, {0x0033,  6}, {0x0068,  7}, {0x0069,  7},
-        {0x0069,  8}, {0x00D4,  8}, {0x00D5,  8}, {0x00D6,  8},
-        {0x006C,  7}, {0x0037,  6}, {0x006D,  7}, {0x0070,  7},
-        {0x0039,  6}, {0x00D7,  8}, {0x00D1,  9}, {0x3880, 14},
-        {0x3881, 14}, {0x3882, 14}, {0x0074,  7}, {0x01C5,  9},
-        {0x0075,  7}, {0x00E3,  8}, {0x3883, 14}, {0x3884, 14},
-        {0x00EC,  8}, {0x3885, 14}, {0x1C43, 13}, {0x1C44, 13},
-        {0x1C45, 13}, {0x00ED,  8}, {0x1C46, 13}, {0x003C,  6},
-        {0x0077,  7}, {0x01E8,  9}, {0x003E,  6}, {0x007B,  7},
-        {0x1C47, 13}, {0x007E,  7}, {0x007F,  7}, {0x1C48, 13},
-        {0x1C49, 13}, {0x1C4A, 13}, {0x1C4B, 13}, {0x1C4C, 13},
-        {0x1C4D, 13}, {0x00F5,  8}, {0x1C4E, 13}, {0x01E9,  9},
-        {0x1C4F, 13},
-    },{//4
-        {0x0000,  2}, {0x0004,  4}, {0x000A,  5}, {0x000B,  5},
-        {0x0018,  6}, {0x0019,  6}, {0x0034,  7}, {0x0035,  7},
-        {0x0036,  7}, {0x006E,  8}, {0x00DE,  9}, {0x00DF,  9},
-        {0x01C0, 10}, {0x01C1, 10}, {0x01C2, 10}, {0x3860, 15},
-        {0x0004,  3}, {0x000F,  5}, {0x001D,  6}, {0x0039,  7},
-        {0x000A,  4}, {0x002C,  6}, {0x002D,  6}, {0x000C,  4},
-        {0x0017,  5}, {0x0034,  6}, {0x0035,  6}, {0x0036,  6},
-        {0x006E,  7}, {0x006F,  7}, {0x0070,  7}, {0x0071,  7},
-        {0x0071,  8}, {0x00E4,  8}, {0x00E5,  8}, {0x00E6,  8},
-        {0x00E7,  8}, {0x00E8,  8}, {0x03A4, 10}, {0x0075,  7},
-        {0x00EC,  8}, {0x01D3,  9}, {0x01DA,  9}, {0x03A5, 10},
-        {0x03B6, 10}, {0x070D, 12}, {0x03B7, 10}, {0x070E, 12},
-        {0x003C,  6}, {0x00EE,  8}, {0x3861, 15}, {0x3862, 15},
-        {0x003D,  6}, {0x01DE,  9}, {0x3863, 15}, {0x3864, 15},
-        {0x3865, 15}, {0x007C,  7}, {0x070F, 12}, {0x03BE, 10},
-        {0x03BF, 10}, {0x3866, 15}, {0x0FA0, 12}, {0x07D1, 11},
-        {0x3867, 15}, {0x00FB,  8}, {0x01F5,  9}, {0x7D08, 15},
-        {0x0FA4, 12}, {0x7D09, 15}, {0x7D0A, 15}, {0x7D0B, 15},
-        {0x3E86, 14}, {0x003F,  6}, {0x0FA5, 12}, {0x07D3, 11},
-        {0x3E87, 14},
-    },{//5
-        {0x0000,  3}, {0x0002,  4}, {0x0003,  4}, {0x0008,  5},
-        {0x0009,  5}, {0x0014,  6}, {0x002A,  7}, {0x0056,  8},
-        {0x02B8, 11}, {0x00AF,  9}, {0x02B9, 11}, {0x015D, 10},
-        {0x02C0, 11}, {0x2C10, 15}, {0x2C11, 15}, {0x2C12, 15},
-        {0x0006,  4}, {0x000E,  5}, {0x0017,  6}, {0x002D,  7},
-        {0x000F,  5}, {0x0040,  7}, {0x0021,  6}, {0x0005,  3},
-        {0x0009,  4}, {0x0011,  5}, {0x0018,  5}, {0x0019,  5},
-        {0x001A,  5}, {0x0036,  6}, {0x0037,  6}, {0x0041,  7},
-        {0x0059,  8}, {0x00E0,  8}, {0x00E1,  8}, {0x0071,  7},
-        {0x00E4,  8}, {0x00B1,  9}, {0x02C2, 11}, {0x001D,  5},
-        {0x0073,  7}, {0x00E5,  8}, {0x00F0,  8}, {0x0079,  7},
-        {0x03C4, 10}, {0x01E3,  9}, {0x01E8,  9}, {0x2C13, 15},
-        {0x007B,  7}, {0x2C14, 15}, {0x2C15, 15}, {0x2C16, 15},
-        {0x007C,  7}, {0x02C3, 11}, {0x2C17, 15}, {0x160C, 14},
-        {0x160D, 14}, {0x007D,  7}, {0x160E, 14}, {0x01E9,  9},
-        {0x03C5, 10}, {0x03D4, 10}, {0x01EB,  9}, {0x160F, 14},
-        {0x3D50, 14}, {0x00FC,  8}, {0x07AB, 11}, {0x3D51, 14},
-        {0x3D52, 14}, {0x3D53, 14}, {0x3D54, 14}, {0x01FA,  9},
-        {0x3D55, 14}, {0x007F,  7}, {0x01FB,  9}, {0x3D56, 14},
-        {0x3D57, 14},
-    },{//6
-        {0x0000,  3}, {0x0002,  4}, {0x0003,  4}, {0x0008,  5},
-        {0x0009,  5}, {0x000A,  5}, {0x000B,  5}, {0x0018,  6},
-        {0x0032,  7}, {0x000D,  5}, {0x0033,  7}, {0x0E00, 13},
-        {0x0039,  7}, {0x0E01, 13}, {0x003A,  7}, {0x0E02, 13},
-        {0x0008,  4}, {0x001E,  6}, {0x003B,  7}, {0x003E,  7},
-        {0x0012,  5}, {0x003F,  7}, {0x0013,  5}, {0x0028,  6},
-        {0x0029,  6}, {0x0054,  7}, {0x002B,  6}, {0x0055,  7},
-        {0x0058,  7}, {0x0E03, 13}, {0x0059,  7}, {0x005A,  7},
-        {0x0E04, 13}, {0x0E05, 13}, {0x0703, 12}, {0x005B,  7},
-        {0x005C,  7}, {0x0704, 12}, {0x0705, 12}, {0x005D,  7},
-        {0x0706, 12}, {0x0707, 12}, {0x0708, 12}, {0x0709, 12},
-        {0x070A, 12}, {0x070B, 12}, {0x0018,  5}, {0x002F,  6},
-        {0x000D,  4}, {0x0019,  5}, {0x070C, 12}, {0x0070,  7},
-        {0x001D,  5}, {0x070D, 12}, {0x070E, 12}, {0x070F, 12},
-        {0x0710, 12}, {0x0039,  6}, {0x0711, 12}, {0x003C,  6},
-        {0x0712, 12}, {0x0713, 12}, {0x0714, 12}, {0x0715, 12},
-        {0x0716, 12}, {0x003D,  6}, {0x0717, 12}, {0x0718, 12},
-        {0x0719, 12}, {0x071A, 12}, {0x071B, 12}, {0x071C, 12},
-        {0x071D, 12}, {0x001F,  5}, {0x071E, 12}, {0x0071,  7},
-        {0x071F, 12},
-    },{//7
-        {0x0000,  3}, {0x0002,  4}, {0x0006,  5}, {0x000E,  6},
-        {0x000F,  6}, {0x0040,  8}, {0x0041,  8}, {0x0042,  8},
-        {0x0218, 11}, {0x2190, 15}, {0x2191, 15}, {0x2192, 15},
-        {0x2193, 15}, {0x2194, 15}, {0x2195, 15}, {0x2196, 15},
-        {0x0005,  4}, {0x0011,  6}, {0x0024,  7}, {0x0087,  9},
-        {0x000C,  5}, {0x004A,  8}, {0x004B,  8}, {0x0002,  2},
-        {0x0006,  3}, {0x000D,  5}, {0x000E,  5}, {0x000F,  5},
-        {0x0013,  6}, {0x0038,  6}, {0x00E4,  8}, {0x00E5,  8},
-        {0x01CC,  9}, {0x00E7,  8}, {0x0074,  7}, {0x00EA,  8},
-        {0x01CD,  9}, {0x021A, 11}, {0x2197, 15}, {0x001E,  5},
-        {0x0076,  7}, {0x00EB,  8}, {0x01DC,  9}, {0x00EF,  8},
-        {0x01DD,  9}, {0x01F0,  9}, {0x2198, 15}, {0x2199, 15},
-        {0x00F9,  8}, {0x03E2, 10}, {0x219A, 15}, {0x219B, 15},
-        {0x00FA,  8}, {0x219C, 15}, {0x219D, 15}, {0x219E, 15},
-        {0x219F, 15}, {0x01F6,  9}, {0x21B0, 15}, {0x00FC,  8},
-        {0x01F7,  9}, {0x21B1, 15}, {0x21B2, 15}, {0x21B3, 15},
-        {0x21B4, 15}, {0x01FA,  9}, {0x21B5, 15}, {0x21B6, 15},
-        {0x21B7, 15}, {0x21B8, 15}, {0x21B9, 15}, {0x03E3, 10},
-        {0x10DD, 14}, {0x007F,  7}, {0x01FB,  9}, {0x10DE, 14},
-        {0x10DF, 14},
-    }
+static const uint16_t x8_ac1_highquant_table[8][77][2] = {
+    { // 0
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0006,  5 }, { 0x0007,  5 },
+        { 0x0008,  5 }, { 0x0009,  5 }, { 0x0014,  6 }, { 0x002A,  7 },
+        { 0x0016,  6 }, { 0x002B,  7 }, { 0x005C,  8 }, { 0x002F,  7 },
+        { 0x0030,  7 }, { 0x005D,  8 }, { 0x0062,  8 }, { 0x00C6,  9 },
+        { 0x0007,  4 }, { 0x0019,  6 }, { 0x001A,  6 }, { 0x0036,  7 },
+        { 0x0010,  5 }, { 0x006E,  8 }, { 0x0022,  6 }, { 0x0009,  4 },
+        { 0x000A,  4 }, { 0x0016,  5 }, { 0x0023,  6 }, { 0x002E,  6 },
+        { 0x002F,  6 }, { 0x0030,  6 }, { 0x0062,  7 }, { 0x0063,  7 },
+        { 0x0064,  7 }, { 0x0065,  7 }, { 0x0066,  7 }, { 0x0067,  7 },
+        { 0x0068,  7 }, { 0x0069,  7 }, { 0x006A,  7 }, { 0x006B,  7 },
+        { 0x006C,  7 }, { 0x00C7,  9 }, { 0x00DE,  9 }, { 0x00DF,  9 },
+        { 0x06D0, 11 }, { 0x01B5,  9 }, { 0x0037,  6 }, { 0x00DB,  8 },
+        { 0x001C,  5 }, { 0x0074,  7 }, { 0x01D4,  9 }, { 0x01D5,  9 },
+        { 0x0076,  7 }, { 0x0369, 10 }, { 0x3688, 14 }, { 0x3689, 14 },
+        { 0x368A, 14 }, { 0x0077,  7 }, { 0x03AC, 10 }, { 0x0078,  7 },
+        { 0x00F2,  8 }, { 0x01D7,  9 }, { 0x00F3,  8 }, { 0x007A,  7 },
+        { 0x368B, 14 }, { 0x007B,  7 }, { 0x007C,  7 }, { 0x03AD, 10 },
+        { 0x03E8, 10 }, { 0x368C, 14 }, { 0x368D, 14 }, { 0x03E9, 10 },
+        { 0x368E, 14 }, { 0x003F,  6 }, { 0x01F5,  9 }, { 0x00FB,  8 },
+        { 0x368F, 14 },
+    },
+    { // 1
+        { 0x0000,  2 }, { 0x0004,  4 }, { 0x000A,  5 }, { 0x000B,  5 },
+        { 0x0018,  6 }, { 0x0032,  7 }, { 0x0033,  7 }, { 0x0034,  7 },
+        { 0x006A,  8 }, { 0x00D6,  9 }, { 0x00D7,  9 }, { 0x00D8,  9 },
+        { 0x00D9,  9 }, { 0x3680, 15 }, { 0x01B5, 10 }, { 0x0369, 11 },
+        { 0x0004,  3 }, { 0x000E,  5 }, { 0x001E,  6 }, { 0x0037,  7 },
+        { 0x000A,  4 }, { 0x0016,  5 }, { 0x000C,  4 }, { 0x001F,  6 },
+        { 0x005C,  7 }, { 0x005D,  7 }, { 0x00BC,  8 }, { 0x00BD,  8 },
+        { 0x005F,  7 }, { 0x00D0,  8 }, { 0x00DB,  9 }, { 0x00D1,  8 },
+        { 0x01A4,  9 }, { 0x01A5,  9 }, { 0x01A6,  9 }, { 0x01A7,  9 },
+        { 0x0350, 10 }, { 0x06A2, 11 }, { 0x06A3, 11 }, { 0x01A9,  9 },
+        { 0x01AA,  9 }, { 0x06AC, 11 }, { 0x3681, 15 }, { 0x0357, 10 },
+        { 0x3682, 15 }, { 0x3683, 15 }, { 0x3684, 15 }, { 0x3685, 15 },
+        { 0x0036,  6 }, { 0x00D6,  8 }, { 0x3686, 15 }, { 0x3687, 15 },
+        { 0x000E,  4 }, { 0x006E,  7 }, { 0x00D7,  8 }, { 0x06AD, 11 },
+        { 0x3688, 15 }, { 0x001E,  5 }, { 0x00DE,  8 }, { 0x06F8, 11 },
+        { 0x037D, 10 }, { 0x3689, 15 }, { 0x368A, 15 }, { 0x368B, 15 },
+        { 0x368C, 15 }, { 0x01BF,  9 }, { 0x368D, 15 }, { 0x1B47, 14 },
+        { 0x37C8, 14 }, { 0x37C9, 14 }, { 0x37CA, 14 }, { 0x37CB, 14 },
+        { 0x37CC, 14 }, { 0x001F,  5 }, { 0x37CD, 14 }, { 0x37CE, 14 },
+        { 0x37CF, 14 },
+    },
+    { // 2
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0003,  4 }, { 0x0008,  5 },
+        { 0x0012,  6 }, { 0x0026,  7 }, { 0x0014,  6 }, { 0x0027,  7 },
+        { 0x00A8,  9 }, { 0x00A9,  9 }, { 0x0055,  8 }, { 0x2B00, 15 },
+        { 0x00AD,  9 }, { 0x2B01, 15 }, { 0x2B02, 15 }, { 0x2B03, 15 },
+        { 0x0003,  3 }, { 0x000B,  5 }, { 0x0040,  7 }, { 0x0041,  7 },
+        { 0x0009,  4 }, { 0x0021,  6 }, { 0x0011,  5 }, { 0x000A,  4 },
+        { 0x000B,  4 }, { 0x0018,  5 }, { 0x0032,  6 }, { 0x0033,  6 },
+        { 0x0034,  6 }, { 0x0035,  6 }, { 0x006C,  7 }, { 0x0057,  8 },
+        { 0x006D,  7 }, { 0x00DC,  8 }, { 0x0159, 10 }, { 0x00DD,  8 },
+        { 0x01BC,  9 }, { 0x037A, 10 }, { 0x037B, 10 }, { 0x0038,  6 },
+        { 0x0072,  7 }, { 0x01BE,  9 }, { 0x01BF,  9 }, { 0x00E6,  8 },
+        { 0x039C, 10 }, { 0x01CF,  9 }, { 0x2B04, 15 }, { 0x2B05, 15 },
+        { 0x0074,  7 }, { 0x01D4,  9 }, { 0x2B06, 15 }, { 0x2B07, 15 },
+        { 0x001E,  5 }, { 0x00EB,  8 }, { 0x1584, 14 }, { 0x1585, 14 },
+        { 0x1586, 14 }, { 0x003B,  6 }, { 0x01D5,  9 }, { 0x01F0,  9 },
+        { 0x039D, 10 }, { 0x03E2, 10 }, { 0x1587, 14 }, { 0x1588, 14 },
+        { 0x1589, 14 }, { 0x00F9,  8 }, { 0x158A, 14 }, { 0x158B, 14 },
+        { 0x03E3, 10 }, { 0x158C, 14 }, { 0x158D, 14 }, { 0x01F4,  9 },
+        { 0x158E, 14 }, { 0x003F,  6 }, { 0x00FB,  8 }, { 0x01F5,  9 },
+        { 0x158F, 14 },
+    },
+    { // 3
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0006,  5 }, { 0x0007,  5 },
+        { 0x0010,  6 }, { 0x0011,  6 }, { 0x0024,  7 }, { 0x0025,  7 },
+        { 0x0013,  6 }, { 0x0014,  6 }, { 0x002A,  7 }, { 0x002B,  7 },
+        { 0x00B0,  9 }, { 0x00B1,  9 }, { 0x002D,  7 }, { 0x0059,  8 },
+        { 0x000C,  5 }, { 0x0017,  6 }, { 0x00D0,  9 }, { 0x0035,  7 },
+        { 0x001B,  6 }, { 0x0038,  7 }, { 0x0039,  7 }, { 0x0004,  3 },
+        { 0x0005,  3 }, { 0x000F,  5 }, { 0x0018,  5 }, { 0x001D,  6 },
+        { 0x0032,  6 }, { 0x0033,  6 }, { 0x0068,  7 }, { 0x0069,  7 },
+        { 0x0069,  8 }, { 0x00D4,  8 }, { 0x00D5,  8 }, { 0x00D6,  8 },
+        { 0x006C,  7 }, { 0x0037,  6 }, { 0x006D,  7 }, { 0x0070,  7 },
+        { 0x0039,  6 }, { 0x00D7,  8 }, { 0x00D1,  9 }, { 0x3880, 14 },
+        { 0x3881, 14 }, { 0x3882, 14 }, { 0x0074,  7 }, { 0x01C5,  9 },
+        { 0x0075,  7 }, { 0x00E3,  8 }, { 0x3883, 14 }, { 0x3884, 14 },
+        { 0x00EC,  8 }, { 0x3885, 14 }, { 0x1C43, 13 }, { 0x1C44, 13 },
+        { 0x1C45, 13 }, { 0x00ED,  8 }, { 0x1C46, 13 }, { 0x003C,  6 },
+        { 0x0077,  7 }, { 0x01E8,  9 }, { 0x003E,  6 }, { 0x007B,  7 },
+        { 0x1C47, 13 }, { 0x007E,  7 }, { 0x007F,  7 }, { 0x1C48, 13 },
+        { 0x1C49, 13 }, { 0x1C4A, 13 }, { 0x1C4B, 13 }, { 0x1C4C, 13 },
+        { 0x1C4D, 13 }, { 0x00F5,  8 }, { 0x1C4E, 13 }, { 0x01E9,  9 },
+        { 0x1C4F, 13 },
+    },
+    { // 4
+        { 0x0000,  2 }, { 0x0004,  4 }, { 0x000A,  5 }, { 0x000B,  5 },
+        { 0x0018,  6 }, { 0x0019,  6 }, { 0x0034,  7 }, { 0x0035,  7 },
+        { 0x0036,  7 }, { 0x006E,  8 }, { 0x00DE,  9 }, { 0x00DF,  9 },
+        { 0x01C0, 10 }, { 0x01C1, 10 }, { 0x01C2, 10 }, { 0x3860, 15 },
+        { 0x0004,  3 }, { 0x000F,  5 }, { 0x001D,  6 }, { 0x0039,  7 },
+        { 0x000A,  4 }, { 0x002C,  6 }, { 0x002D,  6 }, { 0x000C,  4 },
+        { 0x0017,  5 }, { 0x0034,  6 }, { 0x0035,  6 }, { 0x0036,  6 },
+        { 0x006E,  7 }, { 0x006F,  7 }, { 0x0070,  7 }, { 0x0071,  7 },
+        { 0x0071,  8 }, { 0x00E4,  8 }, { 0x00E5,  8 }, { 0x00E6,  8 },
+        { 0x00E7,  8 }, { 0x00E8,  8 }, { 0x03A4, 10 }, { 0x0075,  7 },
+        { 0x00EC,  8 }, { 0x01D3,  9 }, { 0x01DA,  9 }, { 0x03A5, 10 },
+        { 0x03B6, 10 }, { 0x070D, 12 }, { 0x03B7, 10 }, { 0x070E, 12 },
+        { 0x003C,  6 }, { 0x00EE,  8 }, { 0x3861, 15 }, { 0x3862, 15 },
+        { 0x003D,  6 }, { 0x01DE,  9 }, { 0x3863, 15 }, { 0x3864, 15 },
+        { 0x3865, 15 }, { 0x007C,  7 }, { 0x070F, 12 }, { 0x03BE, 10 },
+        { 0x03BF, 10 }, { 0x3866, 15 }, { 0x0FA0, 12 }, { 0x07D1, 11 },
+        { 0x3867, 15 }, { 0x00FB,  8 }, { 0x01F5,  9 }, { 0x7D08, 15 },
+        { 0x0FA4, 12 }, { 0x7D09, 15 }, { 0x7D0A, 15 }, { 0x7D0B, 15 },
+        { 0x3E86, 14 }, { 0x003F,  6 }, { 0x0FA5, 12 }, { 0x07D3, 11 },
+        { 0x3E87, 14 },
+    },
+    { // 5
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0003,  4 }, { 0x0008,  5 },
+        { 0x0009,  5 }, { 0x0014,  6 }, { 0x002A,  7 }, { 0x0056,  8 },
+        { 0x02B8, 11 }, { 0x00AF,  9 }, { 0x02B9, 11 }, { 0x015D, 10 },
+        { 0x02C0, 11 }, { 0x2C10, 15 }, { 0x2C11, 15 }, { 0x2C12, 15 },
+        { 0x0006,  4 }, { 0x000E,  5 }, { 0x0017,  6 }, { 0x002D,  7 },
+        { 0x000F,  5 }, { 0x0040,  7 }, { 0x0021,  6 }, { 0x0005,  3 },
+        { 0x0009,  4 }, { 0x0011,  5 }, { 0x0018,  5 }, { 0x0019,  5 },
+        { 0x001A,  5 }, { 0x0036,  6 }, { 0x0037,  6 }, { 0x0041,  7 },
+        { 0x0059,  8 }, { 0x00E0,  8 }, { 0x00E1,  8 }, { 0x0071,  7 },
+        { 0x00E4,  8 }, { 0x00B1,  9 }, { 0x02C2, 11 }, { 0x001D,  5 },
+        { 0x0073,  7 }, { 0x00E5,  8 }, { 0x00F0,  8 }, { 0x0079,  7 },
+        { 0x03C4, 10 }, { 0x01E3,  9 }, { 0x01E8,  9 }, { 0x2C13, 15 },
+        { 0x007B,  7 }, { 0x2C14, 15 }, { 0x2C15, 15 }, { 0x2C16, 15 },
+        { 0x007C,  7 }, { 0x02C3, 11 }, { 0x2C17, 15 }, { 0x160C, 14 },
+        { 0x160D, 14 }, { 0x007D,  7 }, { 0x160E, 14 }, { 0x01E9,  9 },
+        { 0x03C5, 10 }, { 0x03D4, 10 }, { 0x01EB,  9 }, { 0x160F, 14 },
+        { 0x3D50, 14 }, { 0x00FC,  8 }, { 0x07AB, 11 }, { 0x3D51, 14 },
+        { 0x3D52, 14 }, { 0x3D53, 14 }, { 0x3D54, 14 }, { 0x01FA,  9 },
+        { 0x3D55, 14 }, { 0x007F,  7 }, { 0x01FB,  9 }, { 0x3D56, 14 },
+        { 0x3D57, 14 },
+    },
+    { // 6
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0003,  4 }, { 0x0008,  5 },
+        { 0x0009,  5 }, { 0x000A,  5 }, { 0x000B,  5 }, { 0x0018,  6 },
+        { 0x0032,  7 }, { 0x000D,  5 }, { 0x0033,  7 }, { 0x0E00, 13 },
+        { 0x0039,  7 }, { 0x0E01, 13 }, { 0x003A,  7 }, { 0x0E02, 13 },
+        { 0x0008,  4 }, { 0x001E,  6 }, { 0x003B,  7 }, { 0x003E,  7 },
+        { 0x0012,  5 }, { 0x003F,  7 }, { 0x0013,  5 }, { 0x0028,  6 },
+        { 0x0029,  6 }, { 0x0054,  7 }, { 0x002B,  6 }, { 0x0055,  7 },
+        { 0x0058,  7 }, { 0x0E03, 13 }, { 0x0059,  7 }, { 0x005A,  7 },
+        { 0x0E04, 13 }, { 0x0E05, 13 }, { 0x0703, 12 }, { 0x005B,  7 },
+        { 0x005C,  7 }, { 0x0704, 12 }, { 0x0705, 12 }, { 0x005D,  7 },
+        { 0x0706, 12 }, { 0x0707, 12 }, { 0x0708, 12 }, { 0x0709, 12 },
+        { 0x070A, 12 }, { 0x070B, 12 }, { 0x0018,  5 }, { 0x002F,  6 },
+        { 0x000D,  4 }, { 0x0019,  5 }, { 0x070C, 12 }, { 0x0070,  7 },
+        { 0x001D,  5 }, { 0x070D, 12 }, { 0x070E, 12 }, { 0x070F, 12 },
+        { 0x0710, 12 }, { 0x0039,  6 }, { 0x0711, 12 }, { 0x003C,  6 },
+        { 0x0712, 12 }, { 0x0713, 12 }, { 0x0714, 12 }, { 0x0715, 12 },
+        { 0x0716, 12 }, { 0x003D,  6 }, { 0x0717, 12 }, { 0x0718, 12 },
+        { 0x0719, 12 }, { 0x071A, 12 }, { 0x071B, 12 }, { 0x071C, 12 },
+        { 0x071D, 12 }, { 0x001F,  5 }, { 0x071E, 12 }, { 0x0071,  7 },
+        { 0x071F, 12 },
+    },
+    { // 7
+        { 0x0000,  3 }, { 0x0002,  4 }, { 0x0006,  5 }, { 0x000E,  6 },
+        { 0x000F,  6 }, { 0x0040,  8 }, { 0x0041,  8 }, { 0x0042,  8 },
+        { 0x0218, 11 }, { 0x2190, 15 }, { 0x2191, 15 }, { 0x2192, 15 },
+        { 0x2193, 15 }, { 0x2194, 15 }, { 0x2195, 15 }, { 0x2196, 15 },
+        { 0x0005,  4 }, { 0x0011,  6 }, { 0x0024,  7 }, { 0x0087,  9 },
+        { 0x000C,  5 }, { 0x004A,  8 }, { 0x004B,  8 }, { 0x0002,  2 },
+        { 0x0006,  3 }, { 0x000D,  5 }, { 0x000E,  5 }, { 0x000F,  5 },
+        { 0x0013,  6 }, { 0x0038,  6 }, { 0x00E4,  8 }, { 0x00E5,  8 },
+        { 0x01CC,  9 }, { 0x00E7,  8 }, { 0x0074,  7 }, { 0x00EA,  8 },
+        { 0x01CD,  9 }, { 0x021A, 11 }, { 0x2197, 15 }, { 0x001E,  5 },
+        { 0x0076,  7 }, { 0x00EB,  8 }, { 0x01DC,  9 }, { 0x00EF,  8 },
+        { 0x01DD,  9 }, { 0x01F0,  9 }, { 0x2198, 15 }, { 0x2199, 15 },
+        { 0x00F9,  8 }, { 0x03E2, 10 }, { 0x219A, 15 }, { 0x219B, 15 },
+        { 0x00FA,  8 }, { 0x219C, 15 }, { 0x219D, 15 }, { 0x219E, 15 },
+        { 0x219F, 15 }, { 0x01F6,  9 }, { 0x21B0, 15 }, { 0x00FC,  8 },
+        { 0x01F7,  9 }, { 0x21B1, 15 }, { 0x21B2, 15 }, { 0x21B3, 15 },
+        { 0x21B4, 15 }, { 0x01FA,  9 }, { 0x21B5, 15 }, { 0x21B6, 15 },
+        { 0x21B7, 15 }, { 0x21B8, 15 }, { 0x21B9, 15 }, { 0x03E3, 10 },
+        { 0x10DD, 14 }, { 0x007F,  7 }, { 0x01FB,  9 }, { 0x10DE, 14 },
+        { 0x10DF, 14 },
+    },
 };
 #define MAX_AC_VLC_BITS 16
 
diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c
index 2e449f8..a26244f 100644
--- a/libavcodec/ituh263dec.c
+++ b/libavcodec/ituh263dec.c
@@ -1,7 +1,7 @@
 /*
- * ITU H263 bitstream decoder
+ * ITU H.263 bitstream decoder
  * Copyright (c) 2000,2001 Fabrice Bellard
- * H263+ support.
+ * H.263+ support.
  * Copyright (c) 2001 Juan J. Sierralta P
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -24,7 +24,7 @@
 
 /**
  * @file
- * h263 decoder.
+ * H.263 decoder.
  */
 
 #define UNCHECKED_BITSTREAM_READER 1
@@ -167,7 +167,7 @@ static int h263_decode_gob_header(MpegEncContext *s)
         /* We have a GBSC probably with GSTUFF */
     skip_bits(&s->gb, 16); /* Drop the zeros */
     left= get_bits_left(&s->gb);
-    //MN: we must check the bits left or we might end in a infinite loop (or segfault)
+    //MN: we must check the bits left or we might end in an infinite loop (or segfault)
     for(;left>13; left--){
         if(get_bits1(&s->gb)) break; /* Seek the '1' bit */
     }
@@ -175,17 +175,17 @@ static int h263_decode_gob_header(MpegEncContext *s)
         return -1;
 
     if(s->h263_slice_structured){
-        if(check_marker(&s->gb, "before MBA")==0)
+        if(check_marker(s->avctx, &s->gb, "before MBA")==0)
             return -1;
 
         ff_h263_decode_mba(s);
 
         if(s->mb_num > 1583)
-            if(check_marker(&s->gb, "after MBA")==0)
+            if(check_marker(s->avctx, &s->gb, "after MBA")==0)
                 return -1;
 
         s->qscale = get_bits(&s->gb, 5); /* SQUANT */
-        if(check_marker(&s->gb, "after SQUANT")==0)
+        if(check_marker(s->avctx, &s->gb, "after SQUANT")==0)
             return -1;
         skip_bits(&s->gb, 2); /* GFID */
     }else{
@@ -277,7 +277,7 @@ int ff_h263_decode_motion(MpegEncContext * s, int pred, int f_code)
     if (!s->h263_long_vectors) {
         val = sign_extend(val, 5 + f_code);
     } else {
-        /* horrible h263 long vector mode */
+        /* horrible H.263 long vector mode */
         if (pred < -31 && val < -63)
             val += 64;
         if (pred > 32 && val > 63)
@@ -313,7 +313,7 @@ static int h263p_decode_umotion(MpegEncContext * s, int pred)
 }
 
 /**
- * read the next MVs for OBMC. yes this is a ugly hack, feel free to send a patch :)
+ * read the next MVs for OBMC. yes this is an ugly hack, feel free to send a patch :)
  */
 static void preview_obmc(MpegEncContext *s){
     GetBitContext gb= s->gb;
@@ -872,7 +872,7 @@ end:
     return SLICE_OK;
 }
 
-/* most is hardcoded. should extend to handle all h263 streams */
+/* Most is hardcoded; should extend to handle all H.263 streams. */
 int ff_h263_decode_picture_header(MpegEncContext *s)
 {
     int format, width, height, i, ret;
@@ -904,12 +904,12 @@ int ff_h263_decode_picture_header(MpegEncContext *s)
     s->picture_number= (s->picture_number&~0xFF) + i;
 
     /* PTYPE starts here */
-    if (check_marker(&s->gb, "in PTYPE") != 1) {
+    if (check_marker(s->avctx, &s->gb, "in PTYPE") != 1) {
         return -1;
     }
     if (get_bits1(&s->gb) != 0) {
-        av_log(s->avctx, AV_LOG_ERROR, "Bad H263 id\n");
-        return -1;      /* h263 id */
+        av_log(s->avctx, AV_LOG_ERROR, "Bad H.263 id\n");
+        return -1;      /* H.263 id */
     }
     skip_bits1(&s->gb);         /* split screen off */
     skip_bits1(&s->gb);         /* camera  off */
@@ -936,7 +936,7 @@ int ff_h263_decode_picture_header(MpegEncContext *s)
         s->h263_long_vectors = get_bits1(&s->gb);
 
         if (get_bits1(&s->gb) != 0) {
-            av_log(s->avctx, AV_LOG_ERROR, "H263 SAC not supported\n");
+            av_log(s->avctx, AV_LOG_ERROR, "H.263 SAC not supported\n");
             return -1; /* SAC: off */
         }
         s->obmc= get_bits1(&s->gb); /* Advanced prediction mode */
@@ -1025,11 +1025,11 @@ int ff_h263_decode_picture_header(MpegEncContext *s)
                 6-14 - reserved
                 */
                 width = (get_bits(&s->gb, 9) + 1) * 4;
-                check_marker(&s->gb, "in dimensions");
+                check_marker(s->avctx, &s->gb, "in dimensions");
                 height = get_bits(&s->gb, 9) * 4;
                 ff_dlog(s->avctx, "\nH.263+ Custom picture: %dx%d\n",width,height);
                 if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) {
-                    /* aspected dimensions */
+                    /* expected dimensions */
                     s->avctx->sample_aspect_ratio.num= get_bits(&s->gb, 8);
                     s->avctx->sample_aspect_ratio.den= get_bits(&s->gb, 8);
                 }else{
@@ -1120,13 +1120,13 @@ int ff_h263_decode_picture_header(MpegEncContext *s)
         return AVERROR_INVALIDDATA;
 
     if(s->h263_slice_structured){
-        if (check_marker(&s->gb, "SEPB1") != 1) {
+        if (check_marker(s->avctx, &s->gb, "SEPB1") != 1) {
             return -1;
         }
 
         ff_h263_decode_mba(s);
 
-        if (check_marker(&s->gb, "SEPB2") != 1) {
+        if (check_marker(s->avctx, &s->gb, "SEPB2") != 1) {
             return -1;
         }
     }
diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c
index d9596c9..a8bfe91 100644
--- a/libavcodec/ituh263enc.c
+++ b/libavcodec/ituh263enc.c
@@ -1,7 +1,7 @@
 /*
- * ITU H263 bitstream encoder
+ * ITU H.263 bitstream encoder
  * Copyright (c) 2000,2001 Fabrice Bellard
- * H263+ support.
+ * H.263+ support.
  * Copyright (c) 2001 Juan J. Sierralta P
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -24,7 +24,7 @@
 
 /**
  * @file
- * h263 bitstream encoder.
+ * H.263 bitstream encoder.
  */
 
 #include <limits.h>
@@ -135,7 +135,7 @@ void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number)
     put_sbits(&s->pb, 8, temp_ref); /* TemporalReference */
 
     put_bits(&s->pb, 1, 1);     /* marker */
-    put_bits(&s->pb, 1, 0);     /* h263 id */
+    put_bits(&s->pb, 1, 0);     /* H.263 id */
     put_bits(&s->pb, 1, 0);     /* split screen off */
     put_bits(&s->pb, 1, 0);     /* camera  off */
     put_bits(&s->pb, 1, 0);     /* freeze picture release off */
@@ -151,7 +151,7 @@ void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number)
         put_bits(&s->pb, 1, 0);         /* Unrestricted Motion Vector: off */
         put_bits(&s->pb, 1, 0);         /* SAC: off */
         put_bits(&s->pb, 1, s->obmc);   /* Advanced Prediction */
-        put_bits(&s->pb, 1, 0);         /* only I/P frames, no PB frame */
+        put_bits(&s->pb, 1, 0);         /* only I/P-frames, no PB-frame */
         put_bits(&s->pb, 5, s->qscale);
         put_bits(&s->pb, 1, 0);         /* Continuous Presence Multipoint mode: off */
     } else {
@@ -262,7 +262,7 @@ void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line)
 }
 
 /**
- * modify qscale so that encoding is actually possible in h263 (limit difference to -2..2)
+ * modify qscale so that encoding is actually possible in H.263 (limit difference to -2..2)
  */
 void ff_clean_h263_qscales(MpegEncContext *s){
     int i;
@@ -774,7 +774,7 @@ av_cold void ff_h263_encode_init(MpegEncContext *s)
 
         init_mv_penalty_and_fcode(s);
     }
-    s->me.mv_penalty= mv_penalty; //FIXME exact table for msmpeg4 & h263p
+    s->me.mv_penalty= mv_penalty; // FIXME exact table for MSMPEG4 & H.263+
 
     s->intra_ac_vlc_length     =s->inter_ac_vlc_length     = uni_h263_inter_rl_len;
     s->intra_ac_vlc_last_length=s->inter_ac_vlc_last_length= uni_h263_inter_rl_len + 128*64;
@@ -784,7 +784,7 @@ av_cold void ff_h263_encode_init(MpegEncContext *s)
     }
     s->ac_esc_length= 7+1+6+8;
 
-    // use fcodes >1 only for mpeg4 & h263 & h263p FIXME
+    // use fcodes >1 only for MPEG-4 & H.263 & H.263+ FIXME
     switch(s->codec_id){
     case AV_CODEC_ID_MPEG4:
         s->fcode_tab= fcode_tab;
@@ -800,7 +800,7 @@ av_cold void ff_h263_encode_init(MpegEncContext *s)
             s->max_qcoeff=  127;
         }
         break;
-        //Note for mpeg4 & h263 the dc-scale table will be set per frame as needed later
+        // Note for MPEG-4 & H.263 the dc-scale table will be set per frame as needed later
     case AV_CODEC_ID_FLV1:
         if (s->h263_flv > 1) {
             s->min_qcoeff= -1023;
diff --git a/libavcodec/ivi.c b/libavcodec/ivi.c
index e779900..a1eab94 100644
--- a/libavcodec/ivi.c
+++ b/libavcodec/ivi.c
@@ -1172,6 +1172,22 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         }
     }
 
+    if (ctx->show_indeo4_info) {
+        if (ctx->is_scalable)
+            av_log(avctx, AV_LOG_DEBUG, "This video uses scalability mode\n");
+        if (ctx->uses_tiling)
+            av_log(avctx, AV_LOG_DEBUG, "This video uses local decoding\n");
+        if (ctx->has_b_frames)
+            av_log(avctx, AV_LOG_DEBUG, "This video contains B-frames\n");
+        if (ctx->has_transp)
+            av_log(avctx, AV_LOG_DEBUG, "Transparency mode is enabled\n");
+        if (ctx->uses_haar)
+            av_log(avctx, AV_LOG_DEBUG, "This video uses Haar transform\n");
+        if (ctx->uses_fullpel)
+            av_log(avctx, AV_LOG_DEBUG, "This video uses fullpel motion vectors\n");
+        ctx->show_indeo4_info = 0;
+    }
+
     return buf_size;
 }
 
@@ -1187,23 +1203,6 @@ av_cold int ff_ivi_decode_close(AVCodecContext *avctx)
     if (ctx->mb_vlc.cust_tab.table)
         ff_free_vlc(&ctx->mb_vlc.cust_tab);
 
-#if IVI4_STREAM_ANALYSER
-    if (ctx->is_indeo4) {
-    if (ctx->is_scalable)
-        av_log(avctx, AV_LOG_ERROR, "This video uses scalability mode!\n");
-    if (ctx->uses_tiling)
-        av_log(avctx, AV_LOG_ERROR, "This video uses local decoding!\n");
-    if (ctx->has_b_frames)
-        av_log(avctx, AV_LOG_ERROR, "This video contains B-frames!\n");
-    if (ctx->has_transp)
-        av_log(avctx, AV_LOG_ERROR, "Transparency mode is enabled!\n");
-    if (ctx->uses_haar)
-        av_log(avctx, AV_LOG_ERROR, "This video uses Haar transform!\n");
-    if (ctx->uses_fullpel)
-        av_log(avctx, AV_LOG_ERROR, "This video uses fullpel motion vectors!\n");
-    }
-#endif
-
     av_frame_free(&ctx->p_frame);
 
     return 0;
diff --git a/libavcodec/ivi.h b/libavcodec/ivi.h
index abe4346..3571808 100644
--- a/libavcodec/ivi.h
+++ b/libavcodec/ivi.h
@@ -47,7 +47,6 @@ enum {
 };
 
 #define IVI_VLC_BITS 13 ///< max number of bits of the ivi's huffman codes
-#define IVI4_STREAM_ANALYSER    0
 #define IVI5_IS_PROTECTED       0x20
 
 /**
@@ -220,7 +219,6 @@ typedef struct IVI45DecContext {
     int             prev_frame_type; ///< frame type of the previous frame
     uint32_t        data_size;       ///< size of the frame data in bytes from picture header
     int             is_scalable;
-    int             transp_status;   ///< transparency mode status: 1 - enabled
     const uint8_t   *frame_data;     ///< input frame data pointer
     int             inter_scal;      ///< signals a sequence of scalable inter frames
     uint32_t        frame_size;      ///< frame size in bytes
@@ -250,13 +248,12 @@ typedef struct IVI45DecContext {
     uint8_t         gop_flags;
     uint32_t        lock_word;
 
-#if IVI4_STREAM_ANALYSER
+    int             show_indeo4_info;
     uint8_t         has_b_frames;
-    uint8_t         has_transp;
+    uint8_t         has_transp;      ///< transparency mode status: 1 - enabled
     uint8_t         uses_tiling;
     uint8_t         uses_haar;
     uint8_t         uses_fullpel;
-#endif
 
     int             (*decode_pic_hdr)  (struct IVI45DecContext *ctx, AVCodecContext *avctx);
     int             (*decode_band_hdr) (struct IVI45DecContext *ctx, IVIBandDesc *band, AVCodecContext *avctx);
diff --git a/libavcodec/ivi_dsp.c b/libavcodec/ivi_dsp.c
index 4b97399..bc9de1a 100644
--- a/libavcodec/ivi_dsp.c
+++ b/libavcodec/ivi_dsp.c
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * DSP functions (inverse transforms, motion compensation, wavelet recompostions)
+ * DSP functions (inverse transforms, motion compensation, wavelet recompositions)
  * for Indeo Video Interactive codecs.
  */
 
diff --git a/libavcodec/ivi_dsp.h b/libavcodec/ivi_dsp.h
index f64c718..c38bb3b 100644
--- a/libavcodec/ivi_dsp.h
+++ b/libavcodec/ivi_dsp.h
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * DSP functions (inverse transforms, motion compensations, wavelet recompostion)
+ * DSP functions (inverse transforms, motion compensations, wavelet recomposition)
  * for Indeo Video Interactive codecs.
  */
 
diff --git a/libavcodec/jacosubdec.c b/libavcodec/jacosubdec.c
index 0c97eb8..cdb372a 100644
--- a/libavcodec/jacosubdec.c
+++ b/libavcodec/jacosubdec.c
@@ -167,6 +167,7 @@ static int jacosub_decode_frame(AVCodecContext *avctx,
     int ret;
     AVSubtitle *sub = data;
     const char *ptr = avpkt->data;
+    FFASSDecoderContext *s = avctx->priv_data;
 
     if (avpkt->size <= 0)
         goto end;
@@ -181,7 +182,7 @@ static int jacosub_decode_frame(AVCodecContext *avctx,
 
         av_bprint_init(&buffer, JSS_MAX_LINESIZE, JSS_MAX_LINESIZE);
         jacosub_to_ass(avctx, &buffer, ptr);
-        ret = ff_ass_add_rect_bprint(sub, &buffer, avpkt->pts, avpkt->duration);
+        ret = ff_ass_add_rect(sub, buffer.str, s->readorder++, 0, NULL, NULL);
         av_bprint_finalize(&buffer, NULL);
         if (ret < 0)
             return ret;
@@ -199,4 +200,6 @@ AVCodec ff_jacosub_decoder = {
     .id             = AV_CODEC_ID_JACOSUB,
     .init           = ff_ass_subtitle_header_default,
     .decode         = jacosub_decode_frame,
+    .flush          = ff_ass_decoder_flush,
+    .priv_data_size = sizeof(FFASSDecoderContext),
 };
diff --git a/libavcodec/jni.c b/libavcodec/jni.c
new file mode 100644
index 0000000..32456f5
--- /dev/null
+++ b/libavcodec/jni.c
@@ -0,0 +1,80 @@
+/*
+ * JNI public API functions
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * 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 <stdlib.h>
+
+#include "config.h"
+#include "jni.h"
+
+#if CONFIG_JNI
+
+#include <errno.h>
+#include <jni.h>
+#include <pthread.h>
+
+#include "libavutil/log.h"
+#include "libavutil/error.h"
+#include "ffjni.h"
+
+void *java_vm;
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+int av_jni_set_java_vm(void *vm, void *log_ctx)
+{
+    int ret = 0;
+
+    pthread_mutex_lock(&lock);
+    if (java_vm == NULL) {
+        java_vm = vm;
+    } else if (java_vm != vm) {
+        ret = AVERROR(EINVAL);
+        av_log(log_ctx, AV_LOG_ERROR, "A Java virtual machine has already been set");
+    }
+    pthread_mutex_unlock(&lock);
+
+    return ret;
+}
+
+void *av_jni_get_java_vm(void *log_ctx)
+{
+    void *vm;
+
+    pthread_mutex_lock(&lock);
+    vm = java_vm;
+    pthread_mutex_unlock(&lock);
+
+    return vm;
+}
+
+#else
+
+int av_jni_set_java_vm(void *vm, void *log_ctx)
+{
+    return 0;
+}
+
+void *av_jni_get_java_vm(void *log_ctx)
+{
+    return NULL;
+}
+
+#endif
diff --git a/libavcodec/jni.h b/libavcodec/jni.h
new file mode 100644
index 0000000..dd99e92
--- /dev/null
+++ b/libavcodec/jni.h
@@ -0,0 +1,46 @@
+/*
+ * JNI public API functions
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_JNI_H
+#define AVCODEC_JNI_H
+
+/*
+ * Manually set a Java virtual machine which will be used to retrieve the JNI
+ * environment. Once a Java VM is set it cannot be changed afterwards, meaning
+ * you can call multiple times av_jni_set_java_vm with the same Java VM pointer
+ * however it will error out if you try to set a different Java VM.
+ *
+ * @param vm Java virtual machine
+ * @param log_ctx context used for logging, can be NULL
+ * @return 0 on success, < 0 otherwise
+ */
+int av_jni_set_java_vm(void *vm, void *log_ctx);
+
+/*
+ * Get the Java virtual machine which has been set with av_jni_set_java_vm.
+ *
+ * @param vm Java virtual machine
+ * @return a pointer to the Java virtual machine
+ */
+void *av_jni_get_java_vm(void *log_ctx);
+
+#endif /* AVCODEC_JNI_H */
diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index b5b2dbf..94efc94 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -249,7 +249,7 @@ static void init_band_stepsize(AVCodecContext *avctx,
 
     band->i_stepsize = band->f_stepsize * (1 << 15);
 
-    /* FIXME: In openjepg code stespize = stepsize * 0.5. Why?
+    /* FIXME: In OpenJPEG code stepsize = stepsize * 0.5. Why?
      * If not set output of entropic decoder is not correct. */
     if (!av_codec_is_encoder(avctx->codec))
         band->f_stepsize *= 0.5;
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index c13670e..e9f5f51 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -737,9 +737,9 @@ static int get_sot(Jpeg2000DecoderContext *s, int n)
     bytestream2_get_byteu(&s->g);               // TNsot
 
     if (!Psot)
-        Psot = bytestream2_get_bytes_left(&s->g) + n + 2;
+        Psot = bytestream2_get_bytes_left(&s->g) - 2 + n + 2;
 
-    if (Psot > bytestream2_get_bytes_left(&s->g) + n + 2) {
+    if (Psot > bytestream2_get_bytes_left(&s->g) - 2 + n + 2) {
         av_log(s->avctx, AV_LOG_ERROR, "Psot %"PRIu32" too big\n", Psot);
         return AVERROR_INVALIDDATA;
     }
@@ -1755,9 +1755,12 @@ WRITE_FRAME(16, uint16_t)
 
 #undef WRITE_FRAME
 
-static int jpeg2000_decode_tile(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile,
-                                AVFrame *picture)
+static int jpeg2000_decode_tile(AVCodecContext *avctx, void *td,
+                                int jobnr, int threadnr)
 {
+    Jpeg2000DecoderContext *s = avctx->priv_data;
+    AVFrame *picture = td;
+    Jpeg2000Tile *tile = s->tile + jobnr;
     int x;
 
     tile_codeblocks(s, tile);
@@ -2067,7 +2070,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
     Jpeg2000DecoderContext *s = avctx->priv_data;
     ThreadFrame frame = { .f = data };
     AVFrame *picture = data;
-    int tileno, ret;
+    int ret;
 
     s->avctx     = avctx;
     bytestream2_init(&s->g, avpkt->data, avpkt->size);
@@ -2114,9 +2117,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data,
     if (ret = jpeg2000_read_bitstream_packets(s))
         goto end;
 
-    for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++)
-        if (ret = jpeg2000_decode_tile(s, s->tile + tileno, picture))
-            goto end;
+    avctx->execute2(avctx, jpeg2000_decode_tile, picture, NULL, s->numXtiles * s->numYtiles);
 
     jpeg2000_dec_cleanup(s);
 
@@ -2159,7 +2160,7 @@ AVCodec ff_jpeg2000_decoder = {
     .long_name        = NULL_IF_CONFIG_SMALL("JPEG 2000"),
     .type             = AVMEDIA_TYPE_VIDEO,
     .id               = AV_CODEC_ID_JPEG2000,
-    .capabilities     = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1,
+    .capabilities     = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1,
     .priv_data_size   = sizeof(Jpeg2000DecoderContext),
     .init_static_data = jpeg2000_init_static_data,
     .init             = jpeg2000_decode_init,
diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c
index a46c93a..188cc26 100644
--- a/libavcodec/jpeg2000dwt.c
+++ b/libavcodec/jpeg2000dwt.c
@@ -622,125 +622,3 @@ void ff_dwt_destroy(DWTContext *s)
     av_freep(&s->f_linebuf);
     av_freep(&s->i_linebuf);
 }
-
-#ifdef TEST
-
-#include "libavutil/lfg.h"
-
-#define MAX_W 256
-
-static int test_dwt(int *array, int *ref, int border[2][2], int decomp_levels, int type, int max_diff) {
-    int ret, j;
-    DWTContext s1={{{0}}}, *s= &s1;
-    int64_t err2 = 0;
-
-    ret = ff_jpeg2000_dwt_init(s,  border, decomp_levels, type);
-    if (ret < 0) {
-        fprintf(stderr, "ff_jpeg2000_dwt_init failed\n");
-        return 1;
-    }
-    ret = ff_dwt_encode(s, array);
-    if (ret < 0) {
-        fprintf(stderr, "ff_dwt_encode failed\n");
-        return 1;
-    }
-    ret = ff_dwt_decode(s, array);
-    if (ret < 0) {
-        fprintf(stderr, "ff_dwt_encode failed\n");
-        return 1;
-    }
-    for (j = 0; j<MAX_W * MAX_W; j++) {
-        if (FFABS(array[j] - ref[j]) > max_diff) {
-            fprintf(stderr, "missmatch at %d (%d != %d) decomp:%d border %d %d %d %d\n",
-                    j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]);
-            return 2;
-        }
-        err2 += (array[j] - ref[j]) * (array[j] - ref[j]);
-        array[j] = ref[j];
-    }
-    ff_dwt_destroy(s);
-
-    printf("%s, decomp:%2d border %3d %3d %3d %3d milli-err2:%9"PRId64"\n",
-           type == FF_DWT53 ? "5/3i" : "9/7i",
-           decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1],
-           1000*err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0])));
-
-    return 0;
-}
-
-static int test_dwtf(float *array, float *ref, int border[2][2], int decomp_levels, float max_diff) {
-    int ret, j;
-    DWTContext s1={{{0}}}, *s= &s1;
-    double err2 = 0;
-
-    ret = ff_jpeg2000_dwt_init(s,  border, decomp_levels, FF_DWT97);
-    if (ret < 0) {
-        fprintf(stderr, "ff_jpeg2000_dwt_init failed\n");
-        return 1;
-    }
-    ret = ff_dwt_encode(s, array);
-    if (ret < 0) {
-        fprintf(stderr, "ff_dwt_encode failed\n");
-        return 1;
-    }
-    ret = ff_dwt_decode(s, array);
-    if (ret < 0) {
-        fprintf(stderr, "ff_dwt_encode failed\n");
-        return 1;
-    }
-    for (j = 0; j<MAX_W * MAX_W; j++) {
-        if (FFABS(array[j] - ref[j]) > max_diff) {
-            fprintf(stderr, "missmatch at %d (%f != %f) decomp:%d border %d %d %d %d\n",
-                    j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]);
-            return 2;
-        }
-        err2 += (array[j] - ref[j]) * (array[j] - ref[j]);
-        array[j] = ref[j];
-    }
-    ff_dwt_destroy(s);
-
-    printf("9/7f, decomp:%2d border %3d %3d %3d %3d err2:%20.3f\n",
-           decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1],
-           err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0])));
-
-    return 0;
-}
-
-static int array[MAX_W * MAX_W];
-static int ref  [MAX_W * MAX_W];
-static float arrayf[MAX_W * MAX_W];
-static float reff  [MAX_W * MAX_W];
-
-int main(void) {
-    AVLFG prng;
-    int i,j;
-    int border[2][2];
-    int ret, decomp_levels;
-
-    av_lfg_init(&prng, 1);
-
-    for (i = 0; i<MAX_W * MAX_W; i++)
-        arrayf[i] = reff[i] = array[i] = ref[i] =  av_lfg_get(&prng) % 2048;
-
-    for (i = 0; i < 100; i++) {
-        for (j=0; j<4; j++)
-            border[j>>1][j&1] = av_lfg_get(&prng) % MAX_W;
-        if (border[0][0] >= border[0][1] || border[1][0] >= border[1][1])
-            continue;
-        decomp_levels = av_lfg_get(&prng) % FF_DWT_MAX_DECLVLS;
-
-        ret = test_dwt(array, ref, border, decomp_levels, FF_DWT53, 0);
-        if (ret)
-            return ret;
-        ret = test_dwt(array, ref, border, decomp_levels, FF_DWT97_INT, FFMIN(7+5*decomp_levels, 15+3*decomp_levels));
-        if (ret)
-            return ret;
-        ret = test_dwtf(arrayf, reff, border, decomp_levels, 0.05);
-        if (ret)
-            return ret;
-    }
-
-    return 0;
-}
-
-#endif
diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c
index cd16184..1208cda 100644
--- a/libavcodec/jpeglsenc.c
+++ b/libavcodec/jpeglsenc.c
@@ -386,7 +386,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
     av_freep(&state);
 
     /* the specification says that after doing 0xff escaping unused bits in
-     * the last byte must be set to 0, so just append 7 "optional" zero-bits
+     * the last byte must be set to 0, so just append 7 "optional" zero bits
      * to avoid special-casing. */
     put_bits(&pb2, 7, 0);
     size = put_bits_count(&pb2);
diff --git a/libavcodec/lagarith.c b/libavcodec/lagarith.c
index 94d723d..93d1344 100644
--- a/libavcodec/lagarith.c
+++ b/libavcodec/lagarith.c
@@ -59,11 +59,11 @@ typedef struct LagarithContext {
 } LagarithContext;
 
 /**
- * Compute the 52bit mantissa of 1/(double)denom.
+ * Compute the 52-bit mantissa of 1/(double)denom.
  * This crazy format uses floats in an entropy coder and we have to match x86
  * rounding exactly, thus ordinary floats aren't portable enough.
  * @param denom denominator
- * @return 52bit mantissa
+ * @return 52-bit mantissa
  * @see softfloat_mul
  */
 static uint64_t softfloat_reciprocal(uint32_t denom)
@@ -80,9 +80,9 @@ static uint64_t softfloat_reciprocal(uint32_t denom)
 /**
  * (uint32_t)(x*f), where f has the given mantissa, and exponent 0
  * Used in combination with softfloat_reciprocal computes x/(double)denom.
- * @param x 32bit integer factor
+ * @param x 32-bit integer factor
  * @param mantissa mantissa of f with exponent 0
- * @return 32bit integer value (x*f)
+ * @return 32-bit integer value (x*f)
  * @see softfloat_reciprocal
  */
 static uint32_t softfloat_mul(uint32_t x, uint64_t mantissa)
@@ -234,7 +234,7 @@ static void add_lag_median_prediction(uint8_t *dst, uint8_t *src1,
                                       int *left_top)
 {
     /* This is almost identical to add_hfyu_median_pred in huffyuvdsp.h.
-     * However the &0xFF on the gradient predictor yealds incorrect output
+     * However the &0xFF on the gradient predictor yields incorrect output
      * for lagarith.
      */
     int i;
diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c
index c04ed5e..b1335e1 100644
--- a/libavcodec/lcldec.c
+++ b/libavcodec/lcldec.c
@@ -35,7 +35,6 @@
  *   http://www.pcisys.net/~melanson/codecs
  *
  * Supports: BGR24 (RGB 24bpp)
- *
  */
 
 #include <stdio.h>
@@ -52,9 +51,6 @@
 #include <zlib.h>
 #endif
 
-/*
- * Decoder context
- */
 typedef struct LclDecContext {
     // Image type
     int imgtype;
@@ -158,11 +154,6 @@ static int zlib_decomp(AVCodecContext *avctx, const uint8_t *src, int src_len, i
 #endif
 
 
-/*
- *
- * Decode a frame
- *
- */
 static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
 {
     AVFrame *frame = data;
@@ -473,11 +464,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
     return buf_size;
 }
 
-/*
- *
- * Init lcl decoder
- *
- */
 static av_cold int decode_init(AVCodecContext *avctx)
 {
     LclDecContext * const c = avctx->priv_data;
@@ -632,11 +618,6 @@ static av_cold int decode_init(AVCodecContext *avctx)
     return 0;
 }
 
-/*
- *
- * Uninit lcl decoder
- *
- */
 static av_cold int decode_end(AVCodecContext *avctx)
 {
     LclDecContext * const c = avctx->priv_data;
diff --git a/libavcodec/lclenc.c b/libavcodec/lclenc.c
index 1b1e08b..357313d 100644
--- a/libavcodec/lclenc.c
+++ b/libavcodec/lclenc.c
@@ -35,7 +35,6 @@
  *   http://www.pcisys.net/~melanson/codecs
  *
  * Supports: BGR24 (RGB 24bpp)
- *
  */
 
 #include <stdio.h>
@@ -50,9 +49,6 @@
 
 #include <zlib.h>
 
-/*
- * Decoder context
- */
 typedef struct LclEncContext {
 
     AVCodecContext *avctx;
@@ -66,11 +62,6 @@ typedef struct LclEncContext {
     z_stream zstream;
 } LclEncContext;
 
-/*
- *
- * Encode a frame
- *
- */
 static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                         const AVFrame *p, int *got_packet)
 {
@@ -117,11 +108,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     return 0;
 }
 
-/*
- *
- * Init lcl encoder
- *
- */
 static av_cold int encode_init(AVCodecContext *avctx)
 {
     LclEncContext *c = avctx->priv_data;
@@ -171,11 +157,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
     return 0;
 }
 
-/*
- *
- * Uninit lcl encoder
- *
- */
 static av_cold int encode_end(AVCodecContext *avctx)
 {
     LclEncContext *c = avctx->priv_data;
diff --git a/libavcodec/libdcadec.c b/libavcodec/libdcadec.c
deleted file mode 100644
index 7d1f931..0000000
--- a/libavcodec/libdcadec.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * libdcadec decoder wrapper
- * Copyright (C) 2015 Hendrik Leppkes
- *
- * 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 <libdcadec/dca_context.h>
-
-#include "libavutil/channel_layout.h"
-#include "libavutil/common.h"
-#include "libavutil/opt.h"
-
-#include "avcodec.h"
-#include "dca.h"
-#include "dca_syncwords.h"
-#include "internal.h"
-#include "profiles.h"
-
-typedef struct DCADecContext {
-    const AVClass *class;
-    struct dcadec_context *ctx;
-    uint8_t *buffer;
-    int buffer_size;
-    int lfe_filter;
-    int core_only;
-} DCADecContext;
-
-static void my_log_cb(int level, const char *file, int line,
-                      const char *message, void *cbarg)
-{
-    int av_level;
-
-    switch (level) {
-    case DCADEC_LOG_ERROR:
-        av_level = AV_LOG_ERROR;
-        break;
-    case DCADEC_LOG_WARNING:
-        av_level = AV_LOG_WARNING;
-        break;
-    case DCADEC_LOG_INFO:
-        av_level = AV_LOG_INFO;
-        break;
-    case DCADEC_LOG_VERBOSE:
-        av_level = AV_LOG_VERBOSE;
-        break;
-    case DCADEC_LOG_DEBUG:
-    default:
-        av_level = AV_LOG_DEBUG;
-        break;
-    }
-
-    av_log(cbarg, av_level, "%s\n", message);
-}
-
-static int dcadec_decode_frame(AVCodecContext *avctx, void *data,
-                               int *got_frame_ptr, AVPacket *avpkt)
-{
-    DCADecContext *s = avctx->priv_data;
-    AVFrame *frame = data;
-    struct dcadec_exss_info *exss;
-    int ret, i, k;
-    int **samples, nsamples, channel_mask, sample_rate, bits_per_sample, profile;
-    uint32_t mrk;
-    uint8_t *input = avpkt->data;
-    int input_size = avpkt->size;
-
-    /* convert bytestream syntax to RAW BE format if required */
-    if (input_size < 8) {
-        av_log(avctx, AV_LOG_ERROR, "Input size too small\n");
-        return AVERROR_INVALIDDATA;
-    }
-    mrk = AV_RB32(input);
-    if (mrk != DCA_SYNCWORD_CORE_BE && mrk != DCA_SYNCWORD_SUBSTREAM) {
-        s->buffer = av_fast_realloc(s->buffer, &s->buffer_size, avpkt->size + AV_INPUT_BUFFER_PADDING_SIZE);
-        if (!s->buffer)
-            return AVERROR(ENOMEM);
-
-        for (i = 0, ret = AVERROR_INVALIDDATA; i < input_size - 3 && ret < 0; i++)
-            ret = avpriv_dca_convert_bitstream(input + i, input_size - i, s->buffer, s->buffer_size);
-
-        if (ret < 0)
-            return ret;
-
-        input      = s->buffer;
-        input_size = ret;
-    }
-
-    if ((ret = dcadec_context_parse(s->ctx, input, input_size)) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "dcadec_context_parse() failed: %d (%s)\n", -ret, dcadec_strerror(ret));
-        return AVERROR_EXTERNAL;
-    }
-    if ((ret = dcadec_context_filter(s->ctx, &samples, &nsamples, &channel_mask,
-                                     &sample_rate, &bits_per_sample, &profile)) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "dcadec_context_filter() failed: %d (%s)\n", -ret, dcadec_strerror(ret));
-        return AVERROR_EXTERNAL;
-    }
-
-    avctx->channels       = av_get_channel_layout_nb_channels(channel_mask);
-    avctx->channel_layout = channel_mask;
-    avctx->sample_rate    = sample_rate;
-
-    if (bits_per_sample == 16)
-        avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
-    else if (bits_per_sample > 16 && bits_per_sample <= 24)
-        avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
-    else {
-        av_log(avctx, AV_LOG_ERROR, "Unsupported number of bits per sample: %d\n",
-               bits_per_sample);
-        return AVERROR(ENOSYS);
-    }
-
-    avctx->bits_per_raw_sample = bits_per_sample;
-
-    switch (profile) {
-    case DCADEC_PROFILE_DS:
-        avctx->profile = FF_PROFILE_DTS;
-        break;
-    case DCADEC_PROFILE_DS_96_24:
-        avctx->profile = FF_PROFILE_DTS_96_24;
-        break;
-    case DCADEC_PROFILE_DS_ES:
-        avctx->profile = FF_PROFILE_DTS_ES;
-        break;
-    case DCADEC_PROFILE_HD_HRA:
-        avctx->profile = FF_PROFILE_DTS_HD_HRA;
-        break;
-    case DCADEC_PROFILE_HD_MA:
-        avctx->profile = FF_PROFILE_DTS_HD_MA;
-        break;
-    case DCADEC_PROFILE_EXPRESS:
-        avctx->profile = FF_PROFILE_DTS_EXPRESS;
-        break;
-    case DCADEC_PROFILE_UNKNOWN:
-    default:
-        avctx->profile = FF_PROFILE_UNKNOWN;
-        break;
-    }
-
-    /* bitrate is only meaningful if there are no HD extensions, as they distort the bitrate */
-    if (profile == DCADEC_PROFILE_DS || profile == DCADEC_PROFILE_DS_96_24 || profile == DCADEC_PROFILE_DS_ES) {
-        struct dcadec_core_info *info = dcadec_context_get_core_info(s->ctx);
-        avctx->bit_rate = info->bit_rate;
-        dcadec_context_free_core_info(info);
-    } else
-        avctx->bit_rate = 0;
-
-    if (exss = dcadec_context_get_exss_info(s->ctx)) {
-        enum AVMatrixEncoding matrix_encoding = AV_MATRIX_ENCODING_NONE;
-
-        switch(exss->matrix_encoding) {
-        case DCADEC_MATRIX_ENCODING_SURROUND:
-            matrix_encoding = AV_MATRIX_ENCODING_DOLBY;
-            break;
-        case DCADEC_MATRIX_ENCODING_HEADPHONE:
-            matrix_encoding = AV_MATRIX_ENCODING_DOLBYHEADPHONE;
-            break;
-        }
-        dcadec_context_free_exss_info(exss);
-
-        if (matrix_encoding != AV_MATRIX_ENCODING_NONE &&
-            (ret = ff_side_data_update_matrix_encoding(frame, matrix_encoding)) < 0)
-            return ret;
-    }
-
-    frame->nb_samples = nsamples;
-    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
-        return ret;
-
-    for (i = 0; i < avctx->channels; i++) {
-        if (frame->format == AV_SAMPLE_FMT_S16P) {
-            int16_t *plane = (int16_t *)frame->extended_data[i];
-            for (k = 0; k < nsamples; k++)
-                plane[k] = samples[i][k];
-        } else {
-            int32_t *plane = (int32_t *)frame->extended_data[i];
-            int shift = 32 - bits_per_sample;
-            for (k = 0; k < nsamples; k++)
-                plane[k] = samples[i][k] << shift;
-        }
-    }
-
-    *got_frame_ptr = 1;
-
-    return avpkt->size;
-}
-
-static av_cold void dcadec_flush(AVCodecContext *avctx)
-{
-    DCADecContext *s = avctx->priv_data;
-    dcadec_context_clear(s->ctx);
-}
-
-static av_cold int dcadec_close(AVCodecContext *avctx)
-{
-    DCADecContext *s = avctx->priv_data;
-
-    dcadec_context_destroy(s->ctx);
-    s->ctx = NULL;
-
-    av_freep(&s->buffer);
-
-    return 0;
-}
-
-static av_cold int dcadec_init(AVCodecContext *avctx)
-{
-    DCADecContext *s = avctx->priv_data;
-    int flags = 0;
-
-    /* Affects only lossy DTS profiles. DTS-HD MA is always bitexact */
-    if (avctx->flags & AV_CODEC_FLAG_BITEXACT)
-        flags |= DCADEC_FLAG_CORE_BIT_EXACT;
-
-    if (avctx->err_recognition & AV_EF_EXPLODE)
-        flags |= DCADEC_FLAG_STRICT;
-
-    if (avctx->request_channel_layout) {
-        switch (avctx->request_channel_layout) {
-        case AV_CH_LAYOUT_STEREO:
-        case AV_CH_LAYOUT_STEREO_DOWNMIX:
-            flags |= DCADEC_FLAG_KEEP_DMIX_2CH;
-            break;
-        case AV_CH_LAYOUT_5POINT1:
-            flags |= DCADEC_FLAG_KEEP_DMIX_6CH;
-            break;
-        case AV_CH_LAYOUT_NATIVE:
-            flags |= DCADEC_FLAG_NATIVE_LAYOUT;
-            break;
-        default:
-            av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n");
-            break;
-        }
-    }
-
-    if (s->core_only)
-        flags |= DCADEC_FLAG_CORE_ONLY;
-
-    switch (s->lfe_filter) {
-#if DCADEC_API_VERSION >= DCADEC_VERSION_CODE(0, 1, 0)
-    case 1:
-        flags |= DCADEC_FLAG_CORE_LFE_IIR;
-        break;
-#endif
-    case 2:
-        flags |= DCADEC_FLAG_CORE_LFE_FIR;
-        break;
-    }
-
-    s->ctx = dcadec_context_create(flags);
-    if (!s->ctx)
-        return AVERROR(ENOMEM);
-
-    dcadec_context_set_log_cb(s->ctx, my_log_cb, avctx);
-
-    avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
-    avctx->bits_per_raw_sample = 24;
-
-    return 0;
-}
-
-#define OFFSET(x) offsetof(DCADecContext, x)
-#define PARAM AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM
-
-static const AVOption dcadec_options[] = {
-    { "lfe_filter", "Lossy LFE channel interpolation filter", OFFSET(lfe_filter), AV_OPT_TYPE_INT,   { .i64 = 0 }, 0,       2,       PARAM, "lfe_filter" },
-    { "default",    "Library default",                        0,                  AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, PARAM, "lfe_filter" },
-    { "iir",        "IIR filter",                             0,                  AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, PARAM, "lfe_filter" },
-    { "fir",        "FIR filter",                             0,                  AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, PARAM, "lfe_filter" },
-    { "core_only",  "Decode core only without extensions",    OFFSET(core_only),  AV_OPT_TYPE_BOOL,  { .i64 = 0 }, 0,       1,       PARAM },
-    { NULL }
-};
-
-static const AVClass dcadec_class = {
-    .class_name = "libdcadec decoder",
-    .item_name  = av_default_item_name,
-    .option     = dcadec_options,
-    .version    = LIBAVUTIL_VERSION_INT,
-    .category   = AV_CLASS_CATEGORY_DECODER,
-};
-
-AVCodec ff_libdcadec_decoder = {
-    .name           = "libdcadec",
-    .long_name      = NULL_IF_CONFIG_SMALL("dcadec DCA decoder"),
-    .type           = AVMEDIA_TYPE_AUDIO,
-    .id             = AV_CODEC_ID_DTS,
-    .priv_data_size = sizeof(DCADecContext),
-    .init           = dcadec_init,
-    .decode         = dcadec_decode_frame,
-    .close          = dcadec_close,
-    .flush          = dcadec_flush,
-    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
-    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_S16P,
-                                                      AV_SAMPLE_FMT_NONE },
-    .priv_class     = &dcadec_class,
-    .profiles       = NULL_IF_CONFIG_SMALL(ff_dca_profiles),
-};
diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c
index f0e3426..8545ffe 100644
--- a/libavcodec/libopencore-amr.c
+++ b/libavcodec/libopencore-amr.c
@@ -1,6 +1,6 @@
 /*
  * AMR Audio decoder stub
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -19,6 +19,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <inttypes.h>
+
 #include "libavutil/avstring.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/common.h"
@@ -111,13 +113,13 @@ static int amr_nb_decode_frame(AVCodecContext *avctx, void *data,
     packet_size = block_size[dec_mode] + 1;
 
     if (packet_size > buf_size) {
-        av_log(avctx, AV_LOG_ERROR, "amr frame too short (%u, should be %u)\n",
+        av_log(avctx, AV_LOG_ERROR, "AMR frame too short (%d, should be %d)\n",
                buf_size, packet_size);
         return AVERROR_INVALIDDATA;
     }
 
-    ff_dlog(avctx, "packet_size=%d buf= 0x%X %X %X %X\n",
-              packet_size, buf[0], buf[1], buf[2], buf[3]);
+    ff_dlog(avctx, "packet_size=%d buf= 0x%"PRIx8" %"PRIx8" %"PRIx8" %"PRIx8"\n",
+            packet_size, buf[0], buf[1], buf[2], buf[3]);
     /* call decoder */
     Decoder_Interface_Decode(s->dec_state, buf, (short *)frame->data[0], 0);
 
@@ -149,7 +151,7 @@ typedef struct AMR_bitrates {
 /* Match desired bitrate */
 static int get_bitrate_mode(int bitrate, void *log_ctx)
 {
-    /* make the correspondance between bitrate and mode */
+    /* make the correspondence between bitrate and mode */
     static const AMR_bitrates rates[] = {
         { 4750, MR475 }, { 5150, MR515 }, {  5900, MR59  }, {  6700, MR67  },
         { 7400, MR74 },  { 7950, MR795 }, { 10200, MR102 }, { 12200, MR122 }
@@ -339,7 +341,7 @@ static int amr_wb_decode_frame(AVCodecContext *avctx, void *data,
     packet_size = block_size[mode];
 
     if (packet_size > buf_size) {
-        av_log(avctx, AV_LOG_ERROR, "amr frame too short (%u, should be %u)\n",
+        av_log(avctx, AV_LOG_ERROR, "AMR frame too short (%d, should be %d)\n",
                buf_size, packet_size + 1);
         return AVERROR_INVALIDDATA;
     }
diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c
index 6850568..24bc228 100644
--- a/libavcodec/libopenh264enc.c
+++ b/libavcodec/libopenh264enc.c
@@ -85,7 +85,7 @@ static int libopenh264_to_ffmpeg_log_level(int libopenh264_log_level)
 //
 //        typedef void (*WelsTraceCallback) (void* ctx, int level, const char* string);
 
-static void libopenh264_trace_callback(void *ctx, int level, char const *msg)
+static void libopenh264_trace_callback(void *ctx, int level, const char *msg)
 {
     // The message will be logged only if the requested EQUIVALENT ffmpeg log level is
     // less than or equal to the current ffmpeg log level.
diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c
index cae3d20..65167e6 100644
--- a/libavcodec/libopenjpegdec.c
+++ b/libavcodec/libopenjpegdec.c
@@ -126,10 +126,12 @@ typedef struct BufferReader {
 static OPJ_SIZE_T stream_read(void *out_buffer, OPJ_SIZE_T nb_bytes, void *user_data)
 {
     BufferReader *reader = user_data;
+    int remaining;
+
     if (reader->pos == reader->size) {
         return (OPJ_SIZE_T)-1;
     }
-    int remaining = reader->size - reader->pos;
+    remaining = reader->size - reader->pos;
     if (nb_bytes > remaining) {
         nb_bytes = remaining;
     }
@@ -149,10 +151,12 @@ static OPJ_OFF_T stream_skip(OPJ_OFF_T nb_bytes, void *user_data)
             nb_bytes = -reader->pos;
         }
     } else {
+        int remaining;
+
         if (reader->pos == reader->size) {
             return (OPJ_SIZE_T)-1;
         }
-        int remaining = reader->size - reader->pos;
+        remaining = reader->size - reader->pos;
         if (nb_bytes > remaining) {
             nb_bytes = remaining;
         }
diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c
index b67c320..1443551 100644
--- a/libavcodec/libopenjpegenc.c
+++ b/libavcodec/libopenjpegenc.c
@@ -352,6 +352,12 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx)
     ctx->enc_params.cp_cinema = ctx->cinema_mode;
 #endif
 
+    if (!ctx->numresolution) {
+        ctx->numresolution = 6;
+        while (FFMIN(avctx->width, avctx->height) >> ctx->numresolution < 1)
+            ctx->numresolution --;
+    }
+
     ctx->enc_params.mode = !!avctx->global_quality;
     ctx->enc_params.prog_order = ctx->prog_order;
     ctx->enc_params.numresolution = ctx->numresolution;
@@ -595,6 +601,7 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 #else // OPENJPEG_MAJOR_VERSION == 2
     opj_codec_t *compress   = NULL;
     opj_stream_t *stream    = NULL;
+    PacketWriter writer     = { 0 };
 #endif // OPENJPEG_MAJOR_VERSION == 1
     int cpyresult = 0;
     int ret;
@@ -746,7 +753,7 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 
     memcpy(pkt->data, stream->buffer, len);
 #else // OPENJPEG_MAJOR_VERSION == 2
-    PacketWriter writer = {0, pkt};
+    writer.packet = pkt;
     opj_stream_set_write_function(stream, stream_write);
     opj_stream_set_skip_function(stream, stream_skip);
     opj_stream_set_seek_function(stream, stream_seek);
@@ -814,7 +821,7 @@ static const AVOption options[] = {
     { "rpcl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(RPCL)    }, 0,         0,           VE, "prog_order"  },
     { "pcrl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(PCRL)    }, 0,         0,           VE, "prog_order"  },
     { "cprl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(CPRL)    }, 0,         0,           VE, "prog_order"  },
-    { "numresolution", NULL,                OFFSET(numresolution), AV_OPT_TYPE_INT,   { .i64 = 6           }, 1,         INT_MAX,     VE                },
+    { "numresolution", NULL,                OFFSET(numresolution), AV_OPT_TYPE_INT,   { .i64 = 0           }, 0,         INT_MAX,     VE                },
     { "numlayers",     NULL,                OFFSET(numlayers),     AV_OPT_TYPE_INT,   { .i64 = 1           }, 1,         10,          VE                },
     { "disto_alloc",   NULL,                OFFSET(disto_alloc),   AV_OPT_TYPE_INT,   { .i64 = 1           }, 0,         1,           VE                },
     { "fixed_alloc",   NULL,                OFFSET(fixed_alloc),   AV_OPT_TYPE_INT,   { .i64 = 0           }, 0,         1,           VE                },
diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c
index 1e97604..acc62f1 100644
--- a/libavcodec/libopusdec.c
+++ b/libavcodec/libopusdec.c
@@ -22,9 +22,9 @@
 #include <opus.h>
 #include <opus_multistream.h>
 
-#include "libavutil/avassert.h"
 #include "libavutil/internal.h"
 #include "libavutil/intreadwrite.h"
+
 #include "avcodec.h"
 #include "internal.h"
 #include "vorbis.h"
@@ -79,7 +79,7 @@ static av_cold int libopus_decode_init(AVCodecContext *avc)
         const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1];
         int ch;
 
-        /* Remap channels from vorbis order to ffmpeg order */
+        /* Remap channels from Vorbis order to ffmpeg order */
         for (ch = 0; ch < avc->channels; ch++)
             mapping_arr[ch] = mapping[vorbis_offset[ch]];
         mapping = mapping_arr;
diff --git a/libavcodec/libschroedingerenc.c b/libavcodec/libschroedingerenc.c
index d5da6fc..cf4baa1 100644
--- a/libavcodec/libschroedingerenc.c
+++ b/libavcodec/libschroedingerenc.c
@@ -354,7 +354,7 @@ static int libschroedinger_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                 p_frame_output->key_frame = 1;
 
             /* Parse the coded frame number from the bitstream. Bytes 14
-             * through 17 represesent the frame number. */
+             * through 17 represent the frame number. */
             p_frame_output->frame_num = AV_RB32(enc_buf->data + 13);
 
             ff_schro_queue_push_back(&p_schro_params->enc_frame_queue,
diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c
index 65a84dc..4bdb961 100644
--- a/libavcodec/libspeexenc.c
+++ b/libavcodec/libspeexenc.c
@@ -216,7 +216,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
     if (s->vad)
         speex_encoder_ctl(s->enc_state, SPEEX_SET_VAD, &s->vad);
 
-    /* Activiting Discontinuous Transmission */
+    /* Activating Discontinuous Transmission */
     if (s->dtx) {
         speex_encoder_ctl(s->enc_state, SPEEX_SET_DTX, &s->dtx);
         if (!(s->abr || s->vad || s->header.vbr))
diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c
index c581b34..fae55e8 100644
--- a/libavcodec/libtheoraenc.c
+++ b/libavcodec/libtheoraenc.c
@@ -253,7 +253,7 @@ static av_cold int encode_init(AVCodecContext* avc_context)
         Output first header packet consisting of theora
         header, comment, and tables.
 
-        Each one is prefixed with a 16bit size, then they
+        Each one is prefixed with a 16-bit size, then they
         are concatenated together into libavcodec's extradata.
     */
     offset = 0;
diff --git a/libavcodec/libutvideo.h b/libavcodec/libutvideo.h
deleted file mode 100644
index 0c03097..0000000
--- a/libavcodec/libutvideo.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Derek Buitenhuis
- *
- * 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;
- * version 2 of the License.
- *
- * 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
- * Known FOURCCs:
- *     'ULY0' (YCbCr 4:2:0), 'ULY2' (YCbCr 4:2:2), 'ULRG' (RGB), 'ULRA' (RGBA),
- *     'ULH0' (YCbCr 4:2:0 BT.709), 'ULH2' (YCbCr 4:2:2 BT.709)
- */
-
-#ifndef AVCODEC_LIBUTVIDEO_H
-#define AVCODEC_LIBUTVIDEO_H
-
-#include <stdlib.h>
-#include <utvideo/utvideo.h>
-#include <utvideo/Codec.h>
-
-/*
- * Ut Video version 12.0.0 changed the RGB format names and removed
- * the _WIN names, so if the new names are absent, define them
- * against the old names so compatibility with pre-v12 versions
- * is maintained.
- */
-#if !defined(UTVF_NFCC_BGR_BU)
-#define UTVF_NFCC_BGR_BU UTVF_RGB24_WIN
-#endif
-
-#if !defined(UTVF_NFCC_BGRA_BU)
-#define UTVF_NFCC_BGRA_BU UTVF_RGB32_WIN
-#endif
-
-/*
- * Ut Video version 13.0.1 introduced new BT.709 variants.
- * Special-case these and only use them if v13 is detected.
- */
-#if defined(UTVF_HDYC)
-#define UTV_BT709
-#endif
-
-typedef struct {
-    uint32_t version;
-    uint32_t original_format;
-    uint32_t frameinfo_size;
-    uint32_t flags;
-} UtVideoExtra;
-
-typedef struct {
-    const AVClass *c;
-    CCodec *codec;
-    unsigned int buf_size;
-    uint8_t *buffer;
-    int pred;
-} UtVideoContext;
-
-#endif /* AVCODEC_LIBUTVIDEO_H */
diff --git a/libavcodec/libutvideodec.cpp b/libavcodec/libutvideodec.cpp
deleted file mode 100644
index a456735..0000000
--- a/libavcodec/libutvideodec.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (c) 2011 Derek Buitenhuis
- *
- * 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;
- * version 2 of the License.
- *
- * 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
- * Known FOURCCs:
- *     'ULY0' (YCbCr 4:2:0), 'ULY2' (YCbCr 4:2:2), 'ULRG' (RGB), 'ULRA' (RGBA),
- *     'ULH0' (YCbCr 4:2:0 BT.709), 'ULH2' (YCbCr 4:2:2 BT.709)
- */
-
-extern "C" {
-#include "avcodec.h"
-#include "libavutil/imgutils.h"
-}
-
-#include "libutvideo.h"
-#include "get_bits.h"
-
-static av_cold int utvideo_decode_init(AVCodecContext *avctx)
-{
-    UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
-    UtVideoExtra info;
-    int format;
-    int begin_ret;
-
-    if (avctx->extradata_size != 16 && avctx->extradata_size != 8 ) {
-        av_log(avctx, AV_LOG_ERROR, "Extradata size (%d) mismatch.\n", avctx->extradata_size);
-        return -1;
-    }
-
-    /* Read extradata */
-    info.version = AV_RL32(avctx->extradata);
-    info.original_format = AV_RL32(avctx->extradata + 4);
-    info.frameinfo_size = AV_RL32(avctx->extradata + 8);
-    info.flags = AV_RL32(avctx->extradata + 12);
-
-    /* Pick format based on FOURCC */
-    switch (avctx->codec_tag) {
-#ifdef UTV_BT709
-    case MKTAG('U', 'L', 'H', '0'):
-        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
-        avctx->colorspace = AVCOL_SPC_BT709;
-        format = UTVF_YV12;
-        break;
-    case MKTAG('U', 'L', 'H', '2'):
-        avctx->pix_fmt = AV_PIX_FMT_YUYV422;
-        avctx->colorspace = AVCOL_SPC_BT709;
-        format = UTVF_YUY2;
-        break;
-#endif
-    case MKTAG('U', 'L', 'Y', '0'):
-        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
-        format = UTVF_YV12;
-        break;
-    case MKTAG('U', 'L', 'Y', '2'):
-        avctx->pix_fmt = AV_PIX_FMT_YUYV422;
-        format = UTVF_YUY2;
-        break;
-    case MKTAG('U', 'L', 'R', 'G'):
-        avctx->pix_fmt = AV_PIX_FMT_BGR24;
-        format = UTVF_NFCC_BGR_BU;
-        break;
-    case MKTAG('U', 'L', 'R', 'A'):
-        avctx->pix_fmt = AV_PIX_FMT_RGB32;
-        format = UTVF_NFCC_BGRA_BU;
-        break;
-#ifdef UTVF_UQY2
-    case MKTAG('U', 'Q', 'Y', '2'):
-        avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
-        format = UTVF_v210;
-        break;
-#endif
-    default:
-        av_log(avctx, AV_LOG_ERROR,
-              "Not a Ut Video FOURCC: %X\n", avctx->codec_tag);
-        return -1;
-    }
-
-    /* Only allocate the buffer once */
-    utv->buf_size = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1);
-#ifdef UTVF_UQY2
-    if (format == UTVF_v210)
-        utv->buf_size += avctx->height * ((avctx->width + 47) / 48) * 128; // the linesize used by the decoder, this does not seem to be exported
-#endif
-    utv->buffer = (uint8_t *)av_malloc(utv->buf_size * sizeof(uint8_t));
-
-    if (utv->buffer == NULL) {
-        av_log(avctx, AV_LOG_ERROR, "Unable to allocate output buffer.\n");
-        return -1;
-    }
-
-    /* Allocate the output frame */
-    avctx->coded_frame = av_frame_alloc();
-
-    /* Ut Video only supports 8-bit */
-    avctx->bits_per_raw_sample = 8;
-
-    /* Is it interlaced? */
-    avctx->coded_frame->interlaced_frame = info.flags & 0x800 ? 1 : 0;
-
-    /* Apparently Ut Video doesn't store this info... */
-    avctx->coded_frame->top_field_first = 1;
-
-    /*
-     * Create a Ut Video instance. Since the function wants
-     * an "interface name" string, pass it the name of the lib.
-     */
-    utv->codec = CCodec::CreateInstance(UNFCC(avctx->codec_tag), "libavcodec");
-
-    /* Initialize Decoding */
-    begin_ret = utv->codec->DecodeBegin(format, avctx->width, avctx->height,
-                            CBGROSSWIDTH_WINDOWS, &info, sizeof(UtVideoExtra));
-
-    /* Check to see if the decoder initlized properly */
-    if (begin_ret != 0) {
-        av_log(avctx, AV_LOG_ERROR,
-               "Could not initialize decoder: %d\n", begin_ret);
-        return -1;
-    }
-
-    return 0;
-}
-
-static int utvideo_decode_frame(AVCodecContext *avctx, void *data,
-                                int *got_frame, AVPacket *avpkt)
-{
-    UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
-    AVFrame *pic = avctx->coded_frame;
-    int w = avctx->width, h = avctx->height;
-
-    /* Set flags */
-    pic->pict_type = AV_PICTURE_TYPE_I;
-    pic->key_frame = 1;
-
-    /* Decode the frame */
-    utv->codec->DecodeFrame(utv->buffer, avpkt->data, true);
-
-    /* Set the output data depending on the colorspace */
-    switch (avctx->pix_fmt) {
-    case AV_PIX_FMT_YUV420P:
-        pic->linesize[0] = w;
-        pic->linesize[1] = pic->linesize[2] = w / 2;
-        pic->data[0] = utv->buffer;
-        pic->data[2] = utv->buffer + (w * h);
-        pic->data[1] = pic->data[2] + (w * h / 4);
-        break;
-    case AV_PIX_FMT_YUYV422:
-        pic->linesize[0] = w * 2;
-        pic->data[0] = utv->buffer;
-        break;
-    case AV_PIX_FMT_YUV422P10: {
-        uint16_t *y, *u, *v;
-        int i,j;
-        int linesize = ((w + 47) / 48) * 128;
-
-        pic->linesize[0] = w * 2;
-        pic->linesize[1] =
-        pic->linesize[2] = w;
-        pic->data[0] = utv->buffer + linesize * h;
-        pic->data[1] = pic->data[0] + h*pic->linesize[0];
-        pic->data[2] = pic->data[1] + h*pic->linesize[1];
-        y = (uint16_t*)pic->data[0];
-        u = (uint16_t*)pic->data[1];
-        v = (uint16_t*)pic->data[2];
-        for (j = 0; j < h; j++) {
-            const uint8_t *in = utv->buffer + j * linesize;
-
-            for (i = 0; i + 1 < w; i += 6, in += 4) {
-                unsigned a,b;
-                a = AV_RL32(in);
-                in += 4;
-                b = AV_RL32(in);
-                *u++ = (a    ) & 0x3FF;
-                *y++ = (a>>10) & 0x3FF;
-                *v++ = (a>>20) & 0x3FF;
-                *y++ = (b    ) & 0x3FF;
-
-                if (i + 3 >= w)
-                    break;
-
-                in += 4;
-                a = AV_RL32(in);
-                *u++ = (b>>10) & 0x3FF;
-                *y++ = (b>>20) & 0x3FF;
-                *v++ = (a    ) & 0x3FF;
-                *y++ = (a>>10) & 0x3FF;
-
-                if (i + 5 >= w)
-                    break;
-
-                in += 4;
-                b = AV_RL32(in);
-                *u++ = (a>>20) & 0x3FF;
-                *y++ = (b    ) & 0x3FF;
-                *v++ = (b>>10) & 0x3FF;
-                *y++ = (b>>20) & 0x3FF;
-            }
-        }
-        break;
-    }
-    case AV_PIX_FMT_BGR24:
-    case AV_PIX_FMT_RGB32:
-        /* Make the linesize negative, since Ut Video uses bottom-up BGR */
-        pic->linesize[0] = -1 * w * (avctx->pix_fmt == AV_PIX_FMT_BGR24 ? 3 : 4);
-        pic->data[0] = utv->buffer + utv->buf_size + pic->linesize[0];
-        break;
-    }
-    pic->width  = w;
-    pic->height = h;
-    pic->format = avctx->pix_fmt;
-
-    if (avctx->refcounted_frames) {
-        int ret = av_frame_ref((AVFrame*)data, pic);
-        if (ret < 0)
-             return ret;
-    } else {
-        av_frame_move_ref((AVFrame*)data, pic);
-    }
-
-    *got_frame = 1;
-
-    return avpkt->size;
-}
-
-static av_cold int utvideo_decode_close(AVCodecContext *avctx)
-{
-    UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
-
-    /* Free output */
-    av_frame_free(&avctx->coded_frame);
-    av_freep(&utv->buffer);
-
-    /* Finish decoding and clean up the instance */
-    utv->codec->DecodeEnd();
-    CCodec::DeleteInstance(utv->codec);
-
-    return 0;
-}
-
-AVCodec ff_libutvideo_decoder = {
-    "libutvideo",
-    NULL_IF_CONFIG_SMALL("Ut Video"),
-    AVMEDIA_TYPE_VIDEO,
-    AV_CODEC_ID_UTVIDEO,
-    0,    //capabilities
-    NULL, //supported_framerates
-    NULL, //pix_fmts
-    NULL, //supported_samplerates
-    NULL, //sample_fmts
-    NULL, //channel_layouts
-    0,    //max_lowres
-    NULL, //priv_class
-    NULL, //profiles
-    sizeof(UtVideoContext),
-    NULL, //next
-    NULL, //init_thread_copy
-    NULL, //update_thread_context
-    NULL, //defaults
-    NULL, //init_static_data
-    utvideo_decode_init,
-    NULL, //encode
-    NULL, //encode2
-    utvideo_decode_frame,
-    utvideo_decode_close,
-};
diff --git a/libavcodec/libutvideoenc.cpp b/libavcodec/libutvideoenc.cpp
deleted file mode 100644
index d5dfef9..0000000
--- a/libavcodec/libutvideoenc.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) 2012 Derek Buitenhuis
- *
- * 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;
- * version 2 of the License.
- *
- * 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
- * Known FOURCCs:
- *     'ULY0' (YCbCr 4:2:0), 'ULY2' (YCbCr 4:2:2), 'ULRG' (RGB), 'ULRA' (RGBA),
- *     'ULH0' (YCbCr 4:2:0 BT.709), 'ULH2' (YCbCr 4:2:2 BT.709)
- */
-
-extern "C" {
-#include "libavutil/opt.h"
-#include "libavutil/avassert.h"
-#include "libavutil/imgutils.h"
-#include "avcodec.h"
-#include "internal.h"
-}
-
-#include "libutvideo.h"
-#include "put_bits.h"
-
-static av_cold int utvideo_encode_init(AVCodecContext *avctx)
-{
-    UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
-    UtVideoExtra *info;
-    uint32_t flags, in_format;
-    int ret;
-
-    switch (avctx->pix_fmt) {
-    case AV_PIX_FMT_YUV420P:
-        in_format = UTVF_YV12;
-        avctx->bits_per_coded_sample = 12;
-        if (avctx->colorspace == AVCOL_SPC_BT709)
-            avctx->codec_tag = MKTAG('U', 'L', 'H', '0');
-        else
-            avctx->codec_tag = MKTAG('U', 'L', 'Y', '0');
-        break;
-    case AV_PIX_FMT_YUYV422:
-        in_format = UTVF_YUYV;
-        avctx->bits_per_coded_sample = 16;
-        if (avctx->colorspace == AVCOL_SPC_BT709)
-            avctx->codec_tag = MKTAG('U', 'L', 'H', '2');
-        else
-            avctx->codec_tag = MKTAG('U', 'L', 'Y', '2');
-        break;
-    case AV_PIX_FMT_BGR24:
-        in_format = UTVF_NFCC_BGR_BU;
-        avctx->bits_per_coded_sample = 24;
-        avctx->codec_tag = MKTAG('U', 'L', 'R', 'G');
-        break;
-    case AV_PIX_FMT_RGB32:
-        in_format = UTVF_NFCC_BGRA_BU;
-        avctx->bits_per_coded_sample = 32;
-        avctx->codec_tag = MKTAG('U', 'L', 'R', 'A');
-        break;
-    default:
-        return AVERROR(EINVAL);
-    }
-
-#if FF_API_PRIVATE_OPT
-FF_DISABLE_DEPRECATION_WARNINGS
-    if (avctx->prediction_method)
-        utv->pred = avctx->prediction_method;
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
-
-    /* Check before we alloc anything */
-    if (utv->pred != 0 && utv->pred != 2) {
-        av_log(avctx, AV_LOG_ERROR, "Invalid prediction method.\n");
-        return AVERROR(EINVAL);
-    }
-
-    flags = ((utv->pred + 1) << 8) | (avctx->thread_count - 1);
-
-    avctx->priv_data = utv;
-
-    /* Alloc extradata buffer */
-    info = (UtVideoExtra *)av_malloc(sizeof(*info));
-
-    if (!info) {
-        av_log(avctx, AV_LOG_ERROR, "Could not allocate extradata buffer.\n");
-        return AVERROR(ENOMEM);
-    }
-
-    /*
-     * We use this buffer to hold the data that Ut Video returns,
-     * since we cannot decode planes separately with it.
-     */
-    ret = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1);
-    if (ret < 0) {
-        av_free(info);
-        return ret;
-    }
-    utv->buf_size = ret;
-
-    utv->buffer = (uint8_t *)av_malloc(utv->buf_size);
-
-    if (utv->buffer == NULL) {
-        av_log(avctx, AV_LOG_ERROR, "Could not allocate output buffer.\n");
-        av_free(info);
-        return AVERROR(ENOMEM);
-    }
-
-    /*
-     * Create a Ut Video instance. Since the function wants
-     * an "interface name" string, pass it the name of the lib.
-     */
-    utv->codec = CCodec::CreateInstance(UNFCC(avctx->codec_tag), "libavcodec");
-
-    /* Initialize encoder */
-    utv->codec->EncodeBegin(in_format, avctx->width, avctx->height,
-                            CBGROSSWIDTH_WINDOWS);
-
-    /* Get extradata from encoder */
-    avctx->extradata_size = utv->codec->EncodeGetExtraDataSize();
-    utv->codec->EncodeGetExtraData(info, avctx->extradata_size, in_format,
-                                   avctx->width, avctx->height,
-                                   CBGROSSWIDTH_WINDOWS);
-    avctx->extradata = (uint8_t *)info;
-
-    /* Set flags */
-    utv->codec->SetState(&flags, sizeof(flags));
-
-    return 0;
-}
-
-static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
-                                const AVFrame *pic, int *got_packet)
-{
-    UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
-    int w = avctx->width, h = avctx->height;
-    int ret, rgb_size, i;
-    bool keyframe;
-    uint8_t *y, *u, *v;
-    uint8_t *dst;
-
-    /* Alloc buffer */
-    if ((ret = ff_alloc_packet2(avctx, pkt, utv->buf_size, 0)) < 0)
-        return ret;
-
-    dst = pkt->data;
-
-    /* Move input if needed data into Ut Video friendly buffer */
-    switch (avctx->pix_fmt) {
-    case AV_PIX_FMT_YUV420P:
-        y = utv->buffer;
-        u = y + w * h;
-        v = u + w * h / 4;
-        for (i = 0; i < h; i++) {
-            memcpy(y, pic->data[0] + i * pic->linesize[0], w);
-            y += w;
-        }
-        for (i = 0; i < h / 2; i++) {
-            memcpy(u, pic->data[2] + i * pic->linesize[2], w >> 1);
-            memcpy(v, pic->data[1] + i * pic->linesize[1], w >> 1);
-            u += w >> 1;
-            v += w >> 1;
-        }
-        break;
-    case AV_PIX_FMT_YUYV422:
-        for (i = 0; i < h; i++)
-            memcpy(utv->buffer + i * (w << 1),
-                   pic->data[0] + i * pic->linesize[0], w << 1);
-        break;
-    case AV_PIX_FMT_BGR24:
-    case AV_PIX_FMT_RGB32:
-        /* Ut Video takes bottom-up BGR */
-        rgb_size = avctx->pix_fmt == AV_PIX_FMT_BGR24 ? 3 : 4;
-        for (i = 0; i < h; i++)
-            memcpy(utv->buffer + (h - i - 1) * w * rgb_size,
-                   pic->data[0] + i * pic->linesize[0],
-                   w * rgb_size);
-        break;
-    default:
-        return AVERROR(EINVAL);
-    }
-
-    /* Encode frame */
-    pkt->size = utv->codec->EncodeFrame(dst, &keyframe, utv->buffer);
-
-    if (!pkt->size) {
-        av_log(avctx, AV_LOG_ERROR, "EncodeFrame failed!\n");
-        return AVERROR_INVALIDDATA;
-    }
-
-    /*
-     * Ut Video is intra-only and every frame is a keyframe,
-     * and the API always returns true. In case something
-     * durastic changes in the future, such as inter support,
-     * assert that this is true.
-     */
-    av_assert2(keyframe == true);
-
-    pkt->flags |= AV_PKT_FLAG_KEY;
-    *got_packet = 1;
-    return 0;
-}
-
-static av_cold int utvideo_encode_close(AVCodecContext *avctx)
-{
-    UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
-
-    av_freep(&avctx->extradata);
-    av_freep(&utv->buffer);
-
-    utv->codec->EncodeEnd();
-    CCodec::DeleteInstance(utv->codec);
-
-    return 0;
-}
-
-#define OFFSET(x) offsetof(UtVideoContext, x)
-#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
-static const AVOption options[] = {
-    { "pred", "Prediction method", OFFSET(pred), AV_OPT_TYPE_INT, 0, 0, 2, VE, "pred" },
-    { "left",   NULL, 0, AV_OPT_TYPE_CONST, 0, INT_MIN, INT_MAX, VE, "pred" },
-    { "median",   NULL, 0, AV_OPT_TYPE_CONST, 2, INT_MIN, INT_MAX, VE, "pred" },
-    { NULL },
-};
-
-static const AVClass utvideo_class = {
-    "libutvideo",
-    av_default_item_name,
-    options,
-    LIBAVUTIL_VERSION_INT,
-    0,
-    0,
-    NULL,
-    NULL,
-    AV_CLASS_CATEGORY_NA,
-    NULL,
-    NULL,
-};
-
-AVCodec ff_libutvideo_encoder = {
-    "libutvideo",
-    NULL_IF_CONFIG_SMALL("Ut Video"),
-    AVMEDIA_TYPE_VIDEO,
-    AV_CODEC_ID_UTVIDEO,
-    AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_LOSSLESS | AV_CODEC_CAP_INTRA_ONLY,
-    NULL, /* supported_framerates */
-    (const enum AVPixelFormat[]) {
-        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUYV422, AV_PIX_FMT_BGR24,
-        AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE
-    },
-    NULL, /* supported_samplerates */
-    NULL, /* sample_fmts */
-    NULL, /* channel_layouts */
-    0,    /* max_lowres */
-    &utvideo_class, /* priv_class */
-    NULL, /* profiles */
-    sizeof(UtVideoContext),
-    NULL, /* next */
-    NULL, /* init_thread_copy */
-    NULL, /* update_thread_context */
-    NULL, /* defaults */
-    NULL, /* init_static_data */
-    utvideo_encode_init,
-    NULL, /* encode */
-    utvideo_encode_frame,
-    NULL, /* decode */
-    utvideo_encode_close,
-    NULL, /* flush */
-};
diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c
index 92fa185..2a15650 100644
--- a/libavcodec/libvo-amrwbenc.c
+++ b/libavcodec/libvo-amrwbenc.c
@@ -1,6 +1,6 @@
 /*
  * AMR Audio encoder stub
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -51,7 +51,7 @@ static const AVClass amrwb_class = {
 
 static int get_wb_bitrate_mode(int bitrate, void *log_ctx)
 {
-    /* make the correspondance between bitrate and mode */
+    /* make the correspondence between bitrate and mode */
     static const int rates[] = {  6600,  8850, 12650, 14250, 15850, 18250,
                                  19850, 23050, 23850 };
     int i, best = -1, min_diff = 0;
diff --git a/libavcodec/libvpx.c b/libavcodec/libvpx.c
index a60d186..55edc7e 100644
--- a/libavcodec/libvpx.c
+++ b/libavcodec/libvpx.c
@@ -38,6 +38,9 @@ static const enum AVPixelFormat vp9_pix_fmts_highcol[] = {
     AV_PIX_FMT_YUV422P,
     AV_PIX_FMT_YUV440P,
     AV_PIX_FMT_YUV444P,
+#if VPX_IMAGE_ABI_VERSION >= 3
+    AV_PIX_FMT_GBRP,
+#endif
     AV_PIX_FMT_NONE
 };
 
@@ -46,14 +49,19 @@ static const enum AVPixelFormat vp9_pix_fmts_highbd[] = {
     AV_PIX_FMT_YUV422P,
     AV_PIX_FMT_YUV440P,
     AV_PIX_FMT_YUV444P,
-    AV_PIX_FMT_YUV420P10LE,
-    AV_PIX_FMT_YUV422P10LE,
-    AV_PIX_FMT_YUV440P10LE,
-    AV_PIX_FMT_YUV444P10LE,
-    AV_PIX_FMT_YUV420P12LE,
-    AV_PIX_FMT_YUV422P12LE,
-    AV_PIX_FMT_YUV440P12LE,
-    AV_PIX_FMT_YUV444P12LE,
+    AV_PIX_FMT_YUV420P10,
+    AV_PIX_FMT_YUV422P10,
+    AV_PIX_FMT_YUV440P10,
+    AV_PIX_FMT_YUV444P10,
+    AV_PIX_FMT_YUV420P12,
+    AV_PIX_FMT_YUV422P12,
+    AV_PIX_FMT_YUV440P12,
+    AV_PIX_FMT_YUV444P12,
+#if VPX_IMAGE_ABI_VERSION >= 3
+    AV_PIX_FMT_GBRP,
+    AV_PIX_FMT_GBRP10,
+    AV_PIX_FMT_GBRP12,
+#endif
     AV_PIX_FMT_NONE
 };
 #endif
diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c
index b51bfa2..adbc6d0 100644
--- a/libavcodec/libvpxdec.c
+++ b/libavcodec/libvpxdec.c
@@ -108,10 +108,10 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img)
     case VPX_IMG_FMT_I42016:
         avctx->profile = FF_PROFILE_VP9_2;
         if (img->bit_depth == 10) {
-            avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE;
+            avctx->pix_fmt = AV_PIX_FMT_YUV420P10;
             return 0;
         } else if (img->bit_depth == 12) {
-            avctx->pix_fmt = AV_PIX_FMT_YUV420P12LE;
+            avctx->pix_fmt = AV_PIX_FMT_YUV420P12;
             return 0;
         } else {
             return AVERROR_INVALIDDATA;
@@ -119,10 +119,10 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img)
     case VPX_IMG_FMT_I42216:
         avctx->profile = FF_PROFILE_VP9_3;
         if (img->bit_depth == 10) {
-            avctx->pix_fmt = AV_PIX_FMT_YUV422P10LE;
+            avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
             return 0;
         } else if (img->bit_depth == 12) {
-            avctx->pix_fmt = AV_PIX_FMT_YUV422P12LE;
+            avctx->pix_fmt = AV_PIX_FMT_YUV422P12;
             return 0;
         } else {
             return AVERROR_INVALIDDATA;
@@ -131,10 +131,10 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img)
     case VPX_IMG_FMT_I44016:
         avctx->profile = FF_PROFILE_VP9_3;
         if (img->bit_depth == 10) {
-            avctx->pix_fmt = AV_PIX_FMT_YUV440P10LE;
+            avctx->pix_fmt = AV_PIX_FMT_YUV440P10;
             return 0;
         } else if (img->bit_depth == 12) {
-            avctx->pix_fmt = AV_PIX_FMT_YUV440P12LE;
+            avctx->pix_fmt = AV_PIX_FMT_YUV440P12;
             return 0;
         } else {
             return AVERROR_INVALIDDATA;
@@ -145,17 +145,17 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img)
         if (img->bit_depth == 10) {
 #if VPX_IMAGE_ABI_VERSION >= 3
             avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ?
-                             AV_PIX_FMT_GBRP10LE : AV_PIX_FMT_YUV444P10LE;
+                             AV_PIX_FMT_GBRP10 : AV_PIX_FMT_YUV444P10;
 #else
-            avctx->pix_fmt = AV_PIX_FMT_YUV444P10LE;
+            avctx->pix_fmt = AV_PIX_FMT_YUV444P10;
 #endif
             return 0;
         } else if (img->bit_depth == 12) {
 #if VPX_IMAGE_ABI_VERSION >= 3
             avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ?
-                             AV_PIX_FMT_GBRP12LE : AV_PIX_FMT_YUV444P12LE;
+                             AV_PIX_FMT_GBRP12 : AV_PIX_FMT_YUV444P12;
 #else
-            avctx->pix_fmt = AV_PIX_FMT_YUV444P12LE;
+            avctx->pix_fmt = AV_PIX_FMT_YUV444P12;
 #endif
             return 0;
         } else {
diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c
index 8992497..4ea932d 100644
--- a/libavcodec/libvpxenc.c
+++ b/libavcodec/libvpxenc.c
@@ -106,6 +106,7 @@ typedef struct VP8EncoderContext {
     int aq_mode;
     int drop_threshold;
     int noise_sensitivity;
+    int vpx_cs;
 } VP8Context;
 
 /** String mappings for enum vp8e_enc_control_id */
@@ -277,6 +278,7 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps,
                        struct vpx_codec_enc_cfg *enccfg, vpx_codec_flags_t *flags,
                        vpx_img_fmt_t *img_fmt)
 {
+    VP8Context av_unused *ctx = avctx->priv_data;
 #ifdef VPX_IMG_FMT_HIGHBITDEPTH
     enccfg->g_bit_depth = enccfg->g_input_bit_depth = 8;
 #endif
@@ -294,28 +296,30 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps,
         enccfg->g_profile = 1;
         *img_fmt = VPX_IMG_FMT_I440;
         return 0;
+    case AV_PIX_FMT_GBRP:
+        ctx->vpx_cs = VPX_CS_SRGB;
 #endif
     case AV_PIX_FMT_YUV444P:
         enccfg->g_profile = 1;
         *img_fmt = VPX_IMG_FMT_I444;
         return 0;
 #ifdef VPX_IMG_FMT_HIGHBITDEPTH
-    case AV_PIX_FMT_YUV420P10LE:
-    case AV_PIX_FMT_YUV420P12LE:
+    case AV_PIX_FMT_YUV420P10:
+    case AV_PIX_FMT_YUV420P12:
         if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) {
             enccfg->g_bit_depth = enccfg->g_input_bit_depth =
-                avctx->pix_fmt == AV_PIX_FMT_YUV420P10LE ? 10 : 12;
+                avctx->pix_fmt == AV_PIX_FMT_YUV420P10 ? 10 : 12;
             enccfg->g_profile = 2;
             *img_fmt = VPX_IMG_FMT_I42016;
             *flags |= VPX_CODEC_USE_HIGHBITDEPTH;
             return 0;
         }
         break;
-    case AV_PIX_FMT_YUV422P10LE:
-    case AV_PIX_FMT_YUV422P12LE:
+    case AV_PIX_FMT_YUV422P10:
+    case AV_PIX_FMT_YUV422P12:
         if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) {
             enccfg->g_bit_depth = enccfg->g_input_bit_depth =
-                avctx->pix_fmt == AV_PIX_FMT_YUV422P10LE ? 10 : 12;
+                avctx->pix_fmt == AV_PIX_FMT_YUV422P10 ? 10 : 12;
             enccfg->g_profile = 3;
             *img_fmt = VPX_IMG_FMT_I42216;
             *flags |= VPX_CODEC_USE_HIGHBITDEPTH;
@@ -323,23 +327,27 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps,
         }
         break;
 #if VPX_IMAGE_ABI_VERSION >= 3
-    case AV_PIX_FMT_YUV440P10LE:
-    case AV_PIX_FMT_YUV440P12LE:
+    case AV_PIX_FMT_YUV440P10:
+    case AV_PIX_FMT_YUV440P12:
         if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) {
             enccfg->g_bit_depth = enccfg->g_input_bit_depth =
-                avctx->pix_fmt == AV_PIX_FMT_YUV440P10LE ? 10 : 12;
+                avctx->pix_fmt == AV_PIX_FMT_YUV440P10 ? 10 : 12;
             enccfg->g_profile = 3;
             *img_fmt = VPX_IMG_FMT_I44016;
             *flags |= VPX_CODEC_USE_HIGHBITDEPTH;
             return 0;
         }
         break;
+    case AV_PIX_FMT_GBRP10:
+    case AV_PIX_FMT_GBRP12:
+        ctx->vpx_cs = VPX_CS_SRGB;
 #endif
-    case AV_PIX_FMT_YUV444P10LE:
-    case AV_PIX_FMT_YUV444P12LE:
+    case AV_PIX_FMT_YUV444P10:
+    case AV_PIX_FMT_YUV444P12:
         if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH) {
             enccfg->g_bit_depth = enccfg->g_input_bit_depth =
-                avctx->pix_fmt == AV_PIX_FMT_YUV444P10LE ? 10 : 12;
+                avctx->pix_fmt == AV_PIX_FMT_YUV444P10 ||
+                avctx->pix_fmt == AV_PIX_FMT_GBRP10 ? 10 : 12;
             enccfg->g_profile = 3;
             *img_fmt = VPX_IMG_FMT_I44416;
             *flags |= VPX_CODEC_USE_HIGHBITDEPTH;
@@ -358,20 +366,25 @@ static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps,
 static void set_colorspace(AVCodecContext *avctx)
 {
     enum vpx_color_space vpx_cs;
+    VP8Context *ctx = avctx->priv_data;
 
-    switch (avctx->colorspace) {
-    case AVCOL_SPC_RGB:         vpx_cs = VPX_CS_SRGB;      break;
-    case AVCOL_SPC_BT709:       vpx_cs = VPX_CS_BT_709;    break;
-    case AVCOL_SPC_UNSPECIFIED: vpx_cs = VPX_CS_UNKNOWN;   break;
-    case AVCOL_SPC_RESERVED:    vpx_cs = VPX_CS_RESERVED;  break;
-    case AVCOL_SPC_BT470BG:     vpx_cs = VPX_CS_BT_601;    break;
-    case AVCOL_SPC_SMPTE170M:   vpx_cs = VPX_CS_SMPTE_170; break;
-    case AVCOL_SPC_SMPTE240M:   vpx_cs = VPX_CS_SMPTE_240; break;
-    case AVCOL_SPC_BT2020_NCL:  vpx_cs = VPX_CS_BT_2020;   break;
-    default:
-        av_log(avctx, AV_LOG_WARNING, "Unsupported colorspace (%d)\n",
-               avctx->colorspace);
-        return;
+    if (ctx->vpx_cs) {
+        vpx_cs = ctx->vpx_cs;
+    } else {
+        switch (avctx->colorspace) {
+        case AVCOL_SPC_RGB:         vpx_cs = VPX_CS_SRGB;      break;
+        case AVCOL_SPC_BT709:       vpx_cs = VPX_CS_BT_709;    break;
+        case AVCOL_SPC_UNSPECIFIED: vpx_cs = VPX_CS_UNKNOWN;   break;
+        case AVCOL_SPC_RESERVED:    vpx_cs = VPX_CS_RESERVED;  break;
+        case AVCOL_SPC_BT470BG:     vpx_cs = VPX_CS_BT_601;    break;
+        case AVCOL_SPC_SMPTE170M:   vpx_cs = VPX_CS_SMPTE_170; break;
+        case AVCOL_SPC_SMPTE240M:   vpx_cs = VPX_CS_SMPTE_240; break;
+        case AVCOL_SPC_BT2020_NCL:  vpx_cs = VPX_CS_BT_2020;   break;
+        default:
+            av_log(avctx, AV_LOG_WARNING, "Unsupported colorspace (%d)\n",
+                   avctx->colorspace);
+            return;
+        }
     }
     codecctl_int(avctx, VP9E_SET_COLOR_SPACE, vpx_cs);
 }
diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c
index 61ecae8..91bf64c 100644
--- a/libavcodec/libwebpenc_animencoder.c
+++ b/libavcodec/libwebpenc_animencoder.c
@@ -41,7 +41,7 @@ static av_cold int libwebp_anim_encode_init(AVCodecContext *avctx)
     int ret = ff_libwebp_encode_init_common(avctx);
     if (!ret) {
         LibWebPAnimContext *s = avctx->priv_data;
-        WebPAnimEncoderOptions enc_options = { 0 };
+        WebPAnimEncoderOptions enc_options = { { 0 } };
         WebPAnimEncoderOptionsInit(&enc_options);
         enc_options.verbose = av_log_get_level() >= AV_LOG_VERBOSE;
         // TODO(urvang): Expose some options on command-line perhaps.
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 5030d65..c8f2380 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -244,11 +244,23 @@ static void reconfig_encoder(AVCodecContext *ctx, const AVFrame *frame)
         case AV_STEREO3D_FRAMESEQUENCE:
             fpa_type = 5;
             break;
+#if X264_BUILD >= 145
+        case AV_STEREO3D_2D:
+            fpa_type = 6;
+            break;
+#endif
         default:
             fpa_type = -1;
             break;
         }
 
+        /* Inverted mode is not supported by x264 */
+        if (stereo->flags & AV_STEREO3D_FLAG_INVERT) {
+            av_log(ctx, AV_LOG_WARNING,
+                   "Ignoring unsupported inverted stereo value %d\n", fpa_type);
+            fpa_type = -1;
+        }
+
         if (fpa_type != x4->params.i_frame_packing) {
             x4->params.i_frame_packing = fpa_type;
             x264_encoder_reconfig(x4->enc, &x4->params);
@@ -264,7 +276,6 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
     int nnal, i, ret;
     x264_picture_t pic_out = {0};
     int pict_type;
-    AVFrameSideData *side_data;
 
     x264_picture_init( &x4->pic );
     x4->pic.img.i_csp   = x4->params.i_csp;
@@ -298,46 +309,29 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
         reconfig_encoder(ctx, frame);
 
         if (x4->a53_cc) {
-            side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC);
-            if (side_data) {
+            void *sei_data;
+            size_t sei_size;
+
+            ret = ff_alloc_a53_sei(frame, 0, &sei_data, &sei_size);
+            if (ret < 0) {
+                av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");
+            } else if (sei_data) {
                 x4->pic.extra_sei.payloads = av_mallocz(sizeof(x4->pic.extra_sei.payloads[0]));
                 if (x4->pic.extra_sei.payloads == NULL) {
                     av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");
-                    goto skip_a53cc;
+                    av_free(sei_data);
+                } else {
+                    x4->pic.extra_sei.sei_free = av_free;
+
+                    x4->pic.extra_sei.payloads[0].payload_size = sei_size;
+                    x4->pic.extra_sei.payloads[0].payload = sei_data;
+                    x4->pic.extra_sei.num_payloads = 1;
+                    x4->pic.extra_sei.payloads[0].payload_type = 4;
                 }
-                x4->pic.extra_sei.sei_free = av_free;
-
-                x4->pic.extra_sei.payloads[0].payload_size = side_data->size + 11;
-                x4->pic.extra_sei.payloads[0].payload = av_mallocz(x4->pic.extra_sei.payloads[0].payload_size);
-                if (x4->pic.extra_sei.payloads[0].payload == NULL) {
-                    av_log(ctx, AV_LOG_ERROR, "Not enough memory for closed captions, skipping\n");
-                    av_freep(&x4->pic.extra_sei.payloads);
-                    goto skip_a53cc;
-                }
-                x4->pic.extra_sei.num_payloads = 1;
-                x4->pic.extra_sei.payloads[0].payload_type = 4;
-                memcpy(x4->pic.extra_sei.payloads[0].payload + 10, side_data->data, side_data->size);
-                x4->pic.extra_sei.payloads[0].payload[0] = 181;
-                x4->pic.extra_sei.payloads[0].payload[1] = 0;
-                x4->pic.extra_sei.payloads[0].payload[2] = 49;
-
-                /**
-                 * 'GA94' is standard in North America for ATSC, but hard coding
-                 * this style may not be the right thing to do -- other formats
-                 * do exist. This information is not available in the side_data
-                 * so we are going with this right now.
-                 */
-                AV_WL32(x4->pic.extra_sei.payloads[0].payload + 3,
-                    MKTAG('G', 'A', '9', '4'));
-                x4->pic.extra_sei.payloads[0].payload[7] = 3;
-                x4->pic.extra_sei.payloads[0].payload[8] =
-                    ((side_data->size/3) & 0x1f) | 0x40;
-                x4->pic.extra_sei.payloads[0].payload[9] = 0;
-                x4->pic.extra_sei.payloads[0].payload[side_data->size+10] = 255;
             }
         }
     }
-skip_a53cc:
+
     do {
         if (x264_encoder_encode(x4->enc, &nal, &nnal, frame? &x4->pic: NULL, &pic_out) < 0)
             return AVERROR_EXTERNAL;
@@ -430,7 +424,7 @@ static int convert_pix_fmt(enum AVPixelFormat pix_fmt)
     case AV_PIX_FMT_YUVJ444P:
     case AV_PIX_FMT_YUV444P9:
     case AV_PIX_FMT_YUV444P10: return X264_CSP_I444;
-#ifdef X264_CSP_BGR
+#if CONFIG_LIBX264RGB_ENCODER
     case AV_PIX_FMT_BGR0:
         return X264_CSP_BGRA;
     case AV_PIX_FMT_BGR24:
@@ -884,14 +878,14 @@ static const enum AVPixelFormat pix_fmts_10bit[] = {
     AV_PIX_FMT_NV20,
     AV_PIX_FMT_NONE
 };
+#if CONFIG_LIBX264RGB_ENCODER
 static const enum AVPixelFormat pix_fmts_8bit_rgb[] = {
-#ifdef X264_CSP_BGR
     AV_PIX_FMT_BGR0,
     AV_PIX_FMT_BGR24,
     AV_PIX_FMT_RGB24,
-#endif
     AV_PIX_FMT_NONE
 };
+#endif
 
 static av_cold void X264_init_static(AVCodec *codec)
 {
@@ -1035,13 +1029,6 @@ static const AVClass x264_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-static const AVClass rgbclass = {
-    .class_name = "libx264rgb",
-    .item_name  = av_default_item_name,
-    .option     = options,
-    .version    = LIBAVUTIL_VERSION_INT,
-};
-
 AVCodec ff_libx264_encoder = {
     .name             = "libx264",
     .long_name        = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
@@ -1058,6 +1045,15 @@ AVCodec ff_libx264_encoder = {
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
                         FF_CODEC_CAP_INIT_CLEANUP,
 };
+#endif
+
+#if CONFIG_LIBX264RGB_ENCODER
+static const AVClass rgbclass = {
+    .class_name = "libx264rgb",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
 
 AVCodec ff_libx264rgb_encoder = {
     .name           = "libx264rgb",
diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c
index 68c7fba..11088b2 100644
--- a/libavcodec/libx265.c
+++ b/libavcodec/libx265.c
@@ -154,6 +154,12 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx)
     case AV_PIX_FMT_YUV422P12:
         ctx->params->internalCsp = X265_CSP_I422;
         break;
+    case AV_PIX_FMT_GBRP:
+    case AV_PIX_FMT_GBRP10:
+    case AV_PIX_FMT_GBRP12:
+        ctx->params->vui.matrixCoeffs = AVCOL_SPC_RGB;
+        ctx->params->vui.bEnableVideoSignalTypePresentFlag  = 1;
+        ctx->params->vui.bEnableColorDescriptionPresentFlag = 1;
     case AV_PIX_FMT_YUV444P:
     case AV_PIX_FMT_YUV444P10:
     case AV_PIX_FMT_YUV444P12:
@@ -318,6 +324,7 @@ static const enum AVPixelFormat x265_csp_eight[] = {
     AV_PIX_FMT_YUV420P,
     AV_PIX_FMT_YUV422P,
     AV_PIX_FMT_YUV444P,
+    AV_PIX_FMT_GBRP,
     AV_PIX_FMT_NONE
 };
 
@@ -325,9 +332,11 @@ static const enum AVPixelFormat x265_csp_ten[] = {
     AV_PIX_FMT_YUV420P,
     AV_PIX_FMT_YUV422P,
     AV_PIX_FMT_YUV444P,
+    AV_PIX_FMT_GBRP,
     AV_PIX_FMT_YUV420P10,
     AV_PIX_FMT_YUV422P10,
     AV_PIX_FMT_YUV444P10,
+    AV_PIX_FMT_GBRP10,
     AV_PIX_FMT_NONE
 };
 
@@ -335,12 +344,15 @@ static const enum AVPixelFormat x265_csp_twelve[] = {
     AV_PIX_FMT_YUV420P,
     AV_PIX_FMT_YUV422P,
     AV_PIX_FMT_YUV444P,
+    AV_PIX_FMT_GBRP,
     AV_PIX_FMT_YUV420P10,
     AV_PIX_FMT_YUV422P10,
     AV_PIX_FMT_YUV444P10,
+    AV_PIX_FMT_GBRP10,
     AV_PIX_FMT_YUV420P12,
     AV_PIX_FMT_YUV422P12,
     AV_PIX_FMT_YUV444P12,
+    AV_PIX_FMT_GBRP12,
     AV_PIX_FMT_NONE
 };
 
diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c
index 6fd4e16..d916f11 100644
--- a/libavcodec/libxvid.c
+++ b/libavcodec/libxvid.c
@@ -1,5 +1,5 @@
 /*
- * Interface to xvidcore for mpeg4 encoding
+ * Interface to xvidcore for MPEG-4 encoding
  * Copyright (c) 2004 Adam Thayer <krevnik at comcast.net>
  *
  * This file is part of FFmpeg.
@@ -84,7 +84,7 @@ struct xvid_context {
     int ssim_acc;                  /**< SSIM accuracy. 0: accurate. 4: fast. */
     int gmc;
     int me_quality;                /**< Motion estimation quality. 0: fast 6: best. */
-    int mpeg_quant;                /**< Quantization type. 0: H263, 1: MPEG */
+    int mpeg_quant;                /**< Quantization type. 0: H.263, 1: MPEG */
 };
 
 /**
@@ -96,6 +96,9 @@ struct xvid_ff_pass1 {
 };
 
 static int xvid_encode_close(AVCodecContext *avctx);
+static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+                             const AVFrame *picture, int *got_packet);
+
 
 /*
  * Xvid 2-Pass Kludge Section
@@ -142,7 +145,7 @@ static int xvid_ff_2pass_create(xvid_plg_create_t *param, void **handle)
  * Destroy the two-pass plugin context.
  *
  * @param ref Context pointer for the plugin
- * @param param Destrooy context
+ * @param param Destroy context
  * @return Returns 0, success guaranteed
  */
 static int xvid_ff_2pass_destroy(struct xvid_context *ref,
@@ -541,7 +544,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
         rc2pass2.version = XVID_VERSION;
         rc2pass2.bitrate = avctx->bit_rate;
 
-        fd = av_tempfile("xvidff.", &x->twopassfile, 0, avctx);
+        fd = avpriv_tempfile("xvidff.", &x->twopassfile, 0, avctx);
         if (fd < 0) {
             av_log(avctx, AV_LOG_ERROR, "Xvid: Cannot write 2-pass pipe\n");
             return fd;
@@ -688,7 +691,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
     avctx->extradata      = NULL;
     avctx->extradata_size = 0;
     if (xvid_flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
-        /* In this case, we are claiming to be MPEG4 */
+        /* In this case, we are claiming to be MPEG-4 */
         x->quicktime_format = 1;
         avctx->codec_id     = AV_CODEC_ID_MPEG4;
     } else {
@@ -707,6 +710,43 @@ FF_ENABLE_DEPRECATION_WARNINGS
 
     av_assert0(xvid_enc_create.num_plugins + (!!x->ssim) + (!!x->variance_aq) + (!!x->lumi_aq) <= FF_ARRAY_ELEMS(plugins));
 
+    /* Encode a dummy frame to get the extradata immediately */
+    if (x->quicktime_format) {
+        AVFrame *picture;
+        AVPacket packet = {0};
+        int size, got_packet, ret;
+
+        av_init_packet(&packet);
+
+        picture = av_frame_alloc();
+        if (!picture)
+            return AVERROR(ENOMEM);
+
+        xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);
+        if( xerr ) {
+            av_frame_free(&picture);
+            av_log(avctx, AV_LOG_ERROR, "Xvid: Could not create encoder reference\n");
+            return AVERROR_EXTERNAL;
+        }
+        x->encoder_handle = xvid_enc_create.handle;
+        size = ((avctx->width + 1) & ~1) * ((avctx->height + 1) & ~1);
+        picture->data[0] = av_malloc(size + size / 2);
+        if (!picture->data[0]) {
+            av_frame_free(&picture);
+            return AVERROR(ENOMEM);
+        }
+        picture->data[1] = picture->data[0] + size;
+        picture->data[2] = picture->data[1] + size / 4;
+        memset(picture->data[0], 0, size);
+        memset(picture->data[1], 128, size / 2);
+        ret = xvid_encode_frame(avctx, &packet, picture, &got_packet);
+        if (!ret && got_packet)
+            av_packet_unref(&packet);
+        av_free(picture->data[0]);
+        av_frame_free(&picture);
+        xvid_encore(x->encoder_handle, XVID_ENC_DESTROY, NULL, NULL);
+    }
+
     /* Create encoder context */
     xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);
     if (xerr) {
diff --git a/libavcodec/libxvid.h b/libavcodec/libxvid.h
index bffe07d..ef9a5a9 100644
--- a/libavcodec/libxvid.h
+++ b/libavcodec/libxvid.h
@@ -26,6 +26,4 @@
  * common functions for use with the Xvid wrappers
  */
 
-int ff_tempfile(const char *prefix, char **filename);
-
 #endif /* AVCODEC_LIBXVID_H */
diff --git a/libavcodec/libxvid_rc.c b/libavcodec/libxvid_rc.c
index 0fd030c..0e25a07 100644
--- a/libavcodec/libxvid_rc.c
+++ b/libavcodec/libxvid_rc.c
@@ -33,7 +33,7 @@
 #include <xvid.h>
 
 #include "libavutil/attributes.h"
-#include "libavutil/file.h"
+#include "libavutil/internal.h"
 
 #include "avcodec.h"
 #include "libxvid.h"
@@ -46,7 +46,7 @@ av_cold int ff_xvid_rate_control_init(MpegEncContext *s)
     xvid_plg_create_t xvid_plg_create = { 0 };
     xvid_plugin_2pass2_t xvid_2pass2  = { 0 };
 
-    fd = av_tempfile("xvidrc.", &tmp_name, 0, s->avctx);
+    fd = avpriv_tempfile("xvidrc.", &tmp_name, 0, s->avctx);
     if (fd < 0) {
         av_log(NULL, AV_LOG_ERROR, "Can't create temporary pass2 file.\n");
         return fd;
diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c
index 308f735..d1f0a9f 100644
--- a/libavcodec/libzvbi-teletextdec.c
+++ b/libavcodec/libzvbi-teletextdec.c
@@ -20,6 +20,7 @@
 
 #include "avcodec.h"
 #include "libavcodec/ass.h"
+#include "libavcodec/dvbtxt.h"
 #include "libavutil/opt.h"
 #include "libavutil/bprint.h"
 #include "libavutil/internal.h"
@@ -73,6 +74,8 @@ typedef struct TeletextContext
     vbi_export *    ex;
 #endif
     vbi_sliced      sliced[MAX_SLICES];
+
+    int             readorder;
 } TeletextContext;
 
 static int chop_spaces_utf8(const unsigned char* t, int len)
@@ -94,37 +97,20 @@ static void subtitle_rect_free(AVSubtitleRect **sub_rect)
     av_freep(sub_rect);
 }
 
-static int create_ass_text(TeletextContext *ctx, const char *text, char **ass)
+static char *create_ass_text(TeletextContext *ctx, const char *text)
 {
-    int ret;
-    AVBPrint buf, buf2;
-    const int ts_start    = av_rescale_q(ctx->pts,          AV_TIME_BASE_Q,        (AVRational){1, 100});
-    const int ts_duration = av_rescale_q(ctx->sub_duration, (AVRational){1, 1000}, (AVRational){1, 100});
+    char *dialog;
+    AVBPrint buf;
 
-    /* First we escape the plain text into buf. */
     av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
     ff_ass_bprint_text_event(&buf, text, strlen(text), "", 0);
-    av_bprintf(&buf, "\r\n");
-
     if (!av_bprint_is_complete(&buf)) {
         av_bprint_finalize(&buf, NULL);
-        return AVERROR(ENOMEM);
+        return NULL;
     }
-
-    /* Then we create the ass dialog line in buf2 from the escaped text in buf. */
-    av_bprint_init(&buf2, 0, AV_BPRINT_SIZE_UNLIMITED);
-    ff_ass_bprint_dialog(&buf2, buf.str, ts_start, ts_duration, 0);
+    dialog = ff_ass_get_dialog(ctx->readorder++, 0, NULL, NULL, buf.str);
     av_bprint_finalize(&buf, NULL);
-
-    if (!av_bprint_is_complete(&buf2)) {
-        av_bprint_finalize(&buf2, NULL);
-        return AVERROR(ENOMEM);
-    }
-
-    if ((ret = av_bprint_finalize(&buf2, ass)) < 0)
-        return ret;
-
-    return 0;
+    return dialog;
 }
 
 /* Draw a page as text */
@@ -180,11 +166,12 @@ static int gen_sub_text(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page
     }
 
     if (buf.len) {
-        int ret;
         sub_rect->type = SUBTITLE_ASS;
-        if ((ret = create_ass_text(ctx, buf.str, &sub_rect->ass)) < 0) {
+        sub_rect->ass = create_ass_text(ctx, buf.str);
+
+        if (!sub_rect->ass) {
             av_bprint_finalize(&buf, NULL);
-            return ret;
+            return AVERROR(ENOMEM);
         }
         av_log(ctx, AV_LOG_DEBUG, "subtext:%s:txetbus\n", sub_rect->ass);
     } else {
@@ -368,12 +355,6 @@ static void handler(vbi_event *ev, void *user_data)
     vbi_unref_page(&page);
 }
 
-static inline int data_identifier_is_teletext(int data_identifier) {
-    /* See EN 301 775 section 4.4.2. */
-    return (data_identifier >= 0x10 && data_identifier <= 0x1F ||
-            data_identifier >= 0x99 && data_identifier <= 0x9B);
-}
-
 static int slice_to_vbi_lines(TeletextContext *ctx, uint8_t* buf, int size)
 {
     int lines = 0;
@@ -382,7 +363,7 @@ static int slice_to_vbi_lines(TeletextContext *ctx, uint8_t* buf, int size)
         int data_unit_length = buf[1];
         if (data_unit_length + 2 > size)
             return AVERROR_INVALIDDATA;
-        if (data_unit_id == 0x02 || data_unit_id == 0x03) {
+        if (ff_data_unit_id_is_teletext(data_unit_id)) {
             if (data_unit_length != 0x2c)
                 return AVERROR_INVALIDDATA;
             else {
@@ -434,7 +415,7 @@ static int teletext_decode_frame(AVCodecContext *avctx, void *data, int *data_si
 
         ctx->handler_ret = pkt->size;
 
-        if (data_identifier_is_teletext(*pkt->data)) {
+        if (ff_data_identifier_is_teletext(*pkt->data)) {
             if ((lines = slice_to_vbi_lines(ctx, pkt->data + 1, pkt->size - 1)) < 0)
                 return lines;
             ff_dlog(avctx, "ctx=%p buf_size=%d lines=%u pkt_pts=%7.3f\n",
@@ -546,6 +527,8 @@ static int teletext_close_decoder(AVCodecContext *avctx)
     vbi_decoder_delete(ctx->vbi);
     ctx->vbi = NULL;
     ctx->pts = AV_NOPTS_VALUE;
+    if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
+        ctx->readorder = 0;
     return 0;
 }
 
diff --git a/libavcodec/lossless_audiodsp.c b/libavcodec/lossless_audiodsp.c
index 32f4c9e..3a9f9b2 100644
--- a/libavcodec/lossless_audiodsp.c
+++ b/libavcodec/lossless_audiodsp.c
@@ -29,16 +29,34 @@ static int32_t scalarproduct_and_madd_int16_c(int16_t *v1, const int16_t *v2,
 {
     int res = 0;
 
-    while (order--) {
+    do {
         res   += *v1 * *v2++;
         *v1++ += mul * *v3++;
-    }
+        res   += *v1 * *v2++;
+        *v1++ += mul * *v3++;
+    } while (order-=2);
+    return res;
+}
+
+static int32_t scalarproduct_and_madd_int32_c(int16_t *v1, const int32_t *v2,
+                                              const int16_t *v3,
+                                              int order, int mul)
+{
+    int res = 0;
+
+    do {
+        res   += *v1 * (uint32_t)*v2++;
+        *v1++ += mul * *v3++;
+        res   += *v1 * (uint32_t)*v2++;
+        *v1++ += mul * *v3++;
+    } while (order-=2);
     return res;
 }
 
 av_cold void ff_llauddsp_init(LLAudDSPContext *c)
 {
     c->scalarproduct_and_madd_int16 = scalarproduct_and_madd_int16_c;
+    c->scalarproduct_and_madd_int32 = scalarproduct_and_madd_int32_c;
 
     if (ARCH_ARM)
         ff_llauddsp_init_arm(c);
diff --git a/libavcodec/lossless_audiodsp.h b/libavcodec/lossless_audiodsp.h
index 79ca30d..eea5d49 100644
--- a/libavcodec/lossless_audiodsp.h
+++ b/libavcodec/lossless_audiodsp.h
@@ -36,6 +36,11 @@ typedef struct LLAudDSPContext {
                                             const int16_t *v2,
                                             const int16_t *v3,
                                             int len, int mul);
+
+    int32_t (*scalarproduct_and_madd_int32)(int16_t *v1 /* align 16 */,
+                                            const int32_t *v2,
+                                            const int16_t *v3,
+                                            int len, int mul);
 } LLAudDSPContext;
 
 void ff_llauddsp_init(LLAudDSPContext *c);
diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c
index 3839119..052aeaa 100644
--- a/libavcodec/lpc.c
+++ b/libavcodec/lpc.c
@@ -176,9 +176,10 @@ double ff_lpc_calc_ref_coefs_f(LPCContext *s, const float *samples, int len,
     const double a = 0.5f, b = 1.0f - a;
 
     /* Apply windowing */
-    for (i = 0; i < len; i++) {
+    for (i = 0; i <= len / 2; i++) {
         double weight = a - b*cos((2*M_PI*i)/(len - 1));
         s->windowed_samples[i] = weight*samples[i];
+        s->windowed_samples[len-1-i] = weight*samples[len-1-i];
     }
 
     s->lpc_compute_autocorr(s->windowed_samples, len, order, autoc);
diff --git a/libavcodec/lsp.c b/libavcodec/lsp.c
index 17f59ea..9aba020 100644
--- a/libavcodec/lsp.c
+++ b/libavcodec/lsp.c
@@ -34,7 +34,7 @@ void ff_acelp_reorder_lsf(int16_t* lsfq, int lsfq_min_distance, int lsfq_min, in
 {
     int i, j;
 
-    /* sort lsfq in ascending order. float bubble agorithm,
+    /* sort lsfq in ascending order. float bubble algorithm,
        O(n) if data already sorted, O(n^2) - otherwise */
     for(i=0; i<lp_order-1; i++)
         for(j=i; j>=0 && lsfq[j] > lsfq[j+1]; j--)
diff --git a/libavcodec/lsp.h b/libavcodec/lsp.h
index 46a2d47..621ebea 100644
--- a/libavcodec/lsp.h
+++ b/libavcodec/lsp.h
@@ -102,7 +102,7 @@ void ff_acelp_lp_decode(int16_t* lp_1st, int16_t* lp_2nd, const int16_t* lsp_2nd
  * @param lp_half_order half the number of the amount of LPCs to be
  *        reconstructed, need to be smaller or equal to MAX_LP_HALF_ORDER
  *
- * @note buffers should have a minimux size of 2*lp_half_order elements.
+ * @note buffers should have a minimum size of 2*lp_half_order elements.
  *
  * TIA/EIA/IS-733 2.4.3.3.5
  */
diff --git a/libavcodec/m101.c b/libavcodec/m101.c
new file mode 100644
index 0000000..939d337
--- /dev/null
+++ b/libavcodec/m101.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2016 Michael Niedermayer
+ *
+ * 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/intreadwrite.h"
+
+#include "avcodec.h"
+#include "internal.h"
+
+
+static av_cold int m101_decode_init(AVCodecContext *avctx)
+{
+    if (avctx->extradata_size < 6*4) {
+        avpriv_request_sample(avctx, "Missing or too small extradata (size %d)\n", avctx->extradata_size);
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (avctx->extradata[2*4] == 10)
+        avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
+    else if (avctx->extradata[2*4] == 8) {
+        avctx->pix_fmt = AV_PIX_FMT_YUYV422;
+    } else {
+        avpriv_request_sample(avctx, "BPS %d\n", avctx->extradata[2*4]);
+        return AVERROR_INVALIDDATA;
+    }
+
+    return 0;
+}
+
+static int m101_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
+                      AVPacket *avpkt)
+{
+    const uint8_t *buf = avpkt->data;
+    int stride, ret;
+    int x, y;
+    int min_stride = 2 * avctx->width;
+    int bits = avctx->extradata[2*4];
+    AVFrame *frame = data;
+
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+        return ret;
+    frame->pict_type = AV_PICTURE_TYPE_I;
+    frame->key_frame = 1;
+
+    stride = AV_RL32(avctx->extradata + 5*4);
+
+    if (avctx->pix_fmt == AV_PIX_FMT_YUV422P10)
+        min_stride = (avctx->width + 15) / 16 * 20;
+
+    if (stride < min_stride || avpkt->size < stride * (uint64_t)avctx->height) {
+        av_log(avctx, AV_LOG_ERROR, "stride (%d) is invalid for packet sized %d\n",
+               stride, avpkt->size);
+        return AVERROR_INVALIDDATA;
+    }
+
+    frame->interlaced_frame = ((avctx->extradata[3*4] & 3) != 3);
+    if (frame->interlaced_frame)
+        frame->top_field_first = avctx->extradata[3*4] & 1;
+
+    for (y = 0; y < avctx->height; y++) {
+        int src_y = y;
+        if (frame->interlaced_frame)
+            src_y = ((y&1)^frame->top_field_first) ? y/2 : (y/2 + avctx->height/2);
+        if (bits == 8) {
+            uint8_t *line = frame->data[0] + y*frame->linesize[0];
+            memcpy(line, buf + src_y*stride, 2*avctx->width);
+        } else {
+            int block;
+            uint16_t *luma = (uint16_t*)&frame->data[0][y*frame->linesize[0]];
+            uint16_t *cb   = (uint16_t*)&frame->data[1][y*frame->linesize[1]];
+            uint16_t *cr   = (uint16_t*)&frame->data[2][y*frame->linesize[2]];
+            for (block = 0; 16*block < avctx->width; block ++) {
+                const uint8_t *buf_src = buf + src_y*stride + 40*block;
+                for (x = 0; x < 16 && x + 16*block < avctx->width; x++) {
+                    int xd = x + 16*block;
+                    if (x&1) {
+                        luma [xd] = (4*buf_src[2*x + 0]) + ((buf_src[32 + (x>>1)]>>4)&3);
+                    } else {
+                        luma [xd] = (4*buf_src[2*x + 0]) +  (buf_src[32 + (x>>1)]    &3);
+                        cb[xd>>1] = (4*buf_src[2*x + 1]) + ((buf_src[32 + (x>>1)]>>2)&3);
+                        cr[xd>>1] = (4*buf_src[2*x + 3]) +  (buf_src[32 + (x>>1)]>>6);
+                    }
+                }
+            }
+        }
+    }
+
+    *got_frame = 1;
+    return avpkt->size;
+}
+
+AVCodec ff_m101_decoder = {
+    .name           = "m101",
+    .long_name      = NULL_IF_CONFIG_SMALL("Matrox Uncompressed SD"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_M101,
+    .init           = m101_decode_init,
+    .decode         = m101_decode_frame,
+    .capabilities   = AV_CODEC_CAP_DR1,
+};
diff --git a/libavcodec/magicyuv.c b/libavcodec/magicyuv.c
new file mode 100644
index 0000000..3bb4c5a
--- /dev/null
+++ b/libavcodec/magicyuv.c
@@ -0,0 +1,479 @@
+/*
+ * MagicYUV decoder
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libavutil/qsort.h"
+#include "avcodec.h"
+#include "bytestream.h"
+#include "get_bits.h"
+#include "huffyuvdsp.h"
+#include "internal.h"
+#include "thread.h"
+
+typedef struct Slice {
+    uint32_t start;
+    uint32_t size;
+} Slice;
+
+typedef enum Prediction {
+    LEFT = 1,
+    GRADIENT,
+    MEDIAN,
+} Prediction;
+
+typedef struct MagicYUVContext {
+    AVFrame            *p;
+    int                 slice_height;
+    int                 nb_slices;
+    int                 planes;         // number of encoded planes in bitstream
+    int                 decorrelate;    // postprocessing work
+    int                 interlaced;     // video is interlaced
+    uint8_t             *buf;           // pointer to AVPacket->data
+    int                 hshift[4];
+    int                 vshift[4];
+    Slice               *slices[4];     // slice positions and size in bitstream for each plane
+    int                 slices_size[4];
+    uint8_t             len[4][256];    // table of code lengths for each plane
+    VLC                 vlc[4];         // VLC for each plane
+    HuffYUVDSPContext   hdsp;
+} MagicYUVContext;
+
+static av_cold int decode_init(AVCodecContext *avctx)
+{
+    MagicYUVContext *s = avctx->priv_data;
+    ff_huffyuvdsp_init(&s->hdsp);
+    return 0;
+}
+
+typedef struct HuffEntry {
+    uint8_t  sym;
+    uint8_t  len;
+    uint32_t code;
+} HuffEntry;
+
+static int ff_magy_huff_cmp_len(const void *a, const void *b)
+{
+    const HuffEntry *aa = a, *bb = b;
+    return (aa->len - bb->len) * 256 + aa->sym - bb->sym;
+}
+
+static int build_huff(VLC *vlc, uint8_t *len)
+{
+    HuffEntry he[256];
+    uint32_t codes[256];
+    uint8_t bits[256];
+    uint8_t syms[256];
+    uint32_t code;
+    int i;
+
+    for (i = 0; i < 256; i++) {
+        he[i].sym = 255 - i;
+        he[i].len = len[i];
+    }
+    AV_QSORT(he, 256, HuffEntry, ff_magy_huff_cmp_len);
+
+    code = 1;
+    for (i = 255; i >= 0; i--) {
+        codes[i] = code >> (32 - he[i].len);
+        bits[i]  = he[i].len;
+        syms[i]  = he[i].sym;
+        code += 0x80000000u >> (he[i].len - 1);
+    }
+
+    ff_free_vlc(vlc);
+    return ff_init_vlc_sparse(vlc, FFMIN(he[255].len, 12), 256,
+                              bits,  sizeof(*bits),  sizeof(*bits),
+                              codes, sizeof(*codes), sizeof(*codes),
+                              syms,  sizeof(*syms),  sizeof(*syms), 0);
+}
+
+static int decode_slice(AVCodecContext *avctx, void *tdata,
+                        int j, int threadnr)
+{
+    MagicYUVContext *s = avctx->priv_data;
+    int interlaced = s->interlaced;
+    AVFrame *p = s->p;
+    int i, k, x, ret;
+    GetBitContext b;
+    uint8_t *dst;
+
+    for (i = 0; i < s->planes; i++) {
+        int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height), s->vshift[i]);
+        int width = AV_CEIL_RSHIFT(avctx->coded_width, s->hshift[i]);
+        int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]);
+        int fake_stride = p->linesize[i] * (1 + interlaced);
+        int stride = p->linesize[i];
+        int flags, pred;
+
+        if ((ret = init_get_bits8(&b, s->buf + s->slices[i][j].start, s->slices[i][j].size)) < 0)
+            return ret;
+
+        flags = get_bits(&b, 8);
+        pred  = get_bits(&b, 8);
+
+        dst = p->data[i] + j * sheight * stride;
+        if (flags & 1) {
+            for (k = 0; k < height; k++) {
+                for (x = 0; x < width; x++) {
+                    dst[x] = get_bits(&b, 8);
+                }
+                dst += stride;
+            }
+        } else {
+            for (k = 0; k < height; k++) {
+                for (x = 0; x < width; x++) {
+                    int pix;
+                    if (get_bits_left(&b) <= 0) {
+                        return AVERROR_INVALIDDATA;
+                    }
+                    pix = get_vlc2(&b, s->vlc[i].table, s->vlc[i].bits, 3);
+                    if (pix < 0) {
+                        return AVERROR_INVALIDDATA;
+                    }
+                    dst[x] = 255 - pix;
+                }
+                dst += stride;
+            }
+        }
+
+        if (pred == LEFT) {
+            dst = p->data[i] + j * sheight * stride;
+            s->hdsp.add_hfyu_left_pred(dst, dst, width, 0);
+            dst += stride;
+            if (interlaced) {
+                s->hdsp.add_hfyu_left_pred(dst, dst, width, 0);
+                dst += stride;
+            }
+            for (k = 1 + interlaced; k < height; k++) {
+                s->hdsp.add_hfyu_left_pred(dst, dst, width, dst[-fake_stride]);
+                dst += stride;
+            }
+        } else if (pred == GRADIENT) {
+            int left, lefttop, top;
+
+            dst = p->data[i] + j * sheight * stride;
+            s->hdsp.add_hfyu_left_pred(dst, dst, width, 0);
+            left = lefttop = 0;
+            dst += stride;
+            if (interlaced) {
+                s->hdsp.add_hfyu_left_pred(dst, dst, width, 0);
+                left = lefttop = 0;
+                dst += stride;
+            }
+            for (k = 1 + interlaced; k < height; k++) {
+                top = dst[-fake_stride];
+                left = top + dst[0];
+                dst[0] = left;
+                for (x = 1; x < width; x++) {
+                    top = dst[x - fake_stride];
+                    lefttop = dst[x - (fake_stride + 1)];
+                    left += top - lefttop + dst[x];
+                    dst[x] = left;
+                }
+                dst += stride;
+            }
+        } else if (pred == MEDIAN) {
+            int left, lefttop;
+
+            dst = p->data[i] + j * sheight * stride;
+            lefttop = left = dst[0];
+            s->hdsp.add_hfyu_left_pred(dst, dst, width, 0);
+            dst += stride;
+            if (interlaced) {
+                lefttop = left = dst[0];
+                s->hdsp.add_hfyu_left_pred(dst, dst, width, 0);
+                dst += stride;
+            }
+            for (k = 1 + interlaced; k < height; k++) {
+                s->hdsp.add_hfyu_median_pred(dst, dst - fake_stride, dst, width, &left, &lefttop);
+                lefttop = left = dst[0];
+                dst += stride;
+            }
+        } else {
+            avpriv_request_sample(avctx, "unknown prediction: %d", pred);
+        }
+    }
+
+    if (s->decorrelate) {
+        int height = FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height);
+        int width = avctx->coded_width;
+        uint8_t *b = p->data[0] + j * s->slice_height * p->linesize[0];
+        uint8_t *g = p->data[1] + j * s->slice_height * p->linesize[1];
+        uint8_t *r = p->data[2] + j * s->slice_height * p->linesize[2];
+
+        for (i = 0; i < height; i++) {
+            s->hdsp.add_bytes(b, g, width);
+            s->hdsp.add_bytes(r, g, width);
+            b += p->linesize[0];
+            g += p->linesize[1];
+            r += p->linesize[2];
+        }
+    }
+
+    return 0;
+}
+
+static int decode_frame(AVCodecContext *avctx,
+                        void *data, int *got_frame,
+                        AVPacket *avpkt)
+{
+    uint32_t first_offset, offset, next_offset, header_size, slice_width;
+    int ret, format, version, table_size;
+    MagicYUVContext *s = avctx->priv_data;
+    ThreadFrame frame = { .f = data };
+    AVFrame *p = data;
+    GetByteContext gb;
+    GetBitContext b;
+    int i, j, k, width, height;
+
+    bytestream2_init(&gb, avpkt->data, avpkt->size);
+    if (bytestream2_get_le32(&gb) != MKTAG('M','A','G','Y'))
+        return AVERROR_INVALIDDATA;
+
+    header_size = bytestream2_get_le32(&gb);
+    if (header_size < 32 || header_size >= avpkt->size)
+        return AVERROR_INVALIDDATA;
+
+    version = bytestream2_get_byte(&gb);
+    if (version != 7) {
+        avpriv_request_sample(avctx, "unsupported version: %d", version);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    s->hshift[1] = s->vshift[1] = 0;
+    s->hshift[2] = s->vshift[2] = 0;
+    s->decorrelate = 0;
+
+    format = bytestream2_get_byte(&gb);
+    switch (format) {
+    case 0x65:
+        avctx->pix_fmt = AV_PIX_FMT_GBRP;
+        s->decorrelate = 1;
+        s->planes = 3;
+        break;
+    case 0x66:
+        avctx->pix_fmt = AV_PIX_FMT_GBRAP;
+        s->decorrelate = 1;
+        s->planes = 4;
+        break;
+    case 0x67:
+        avctx->pix_fmt = AV_PIX_FMT_YUV444P;
+        s->planes = 3;
+        break;
+    case 0x68:
+        avctx->pix_fmt = AV_PIX_FMT_YUV422P;
+        s->planes = 3;
+        s->hshift[1] = s->hshift[2] = 1;
+        break;
+    case 0x69:
+        avctx->pix_fmt = AV_PIX_FMT_YUV420P;
+        s->planes = 3;
+        s->hshift[1] = s->vshift[1] = 1;
+        s->hshift[2] = s->vshift[2] = 1;
+        break;
+    case 0x6a:
+        avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
+        s->planes = 4;
+        break;
+    case 0x6b:
+        avctx->pix_fmt = AV_PIX_FMT_GRAY8;
+        s->planes = 1;
+        break;
+    default:
+        avpriv_request_sample(avctx, "unsupported format: 0x%X", format);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    bytestream2_skip(&gb, 2);
+    s->interlaced = !!(bytestream2_get_byte(&gb) & 2);
+    bytestream2_skip(&gb, 3);
+
+    width  = bytestream2_get_le32(&gb);
+    height = bytestream2_get_le32(&gb);
+    if ((ret = ff_set_dimensions(avctx, width, height)) < 0)
+        return ret;
+
+    slice_width = bytestream2_get_le32(&gb);
+    if (slice_width != avctx->coded_width) {
+        avpriv_request_sample(avctx, "unsupported slice width: %d", slice_width);
+        return AVERROR_PATCHWELCOME;
+    }
+    s->slice_height = bytestream2_get_le32(&gb);
+    if ((s->slice_height <= 0) || (s->slice_height > INT_MAX - avctx->coded_height)) {
+        av_log(avctx, AV_LOG_ERROR, "invalid slice height: %d\n", s->slice_height);
+        return AVERROR_INVALIDDATA;
+    }
+
+    bytestream2_skip(&gb, 4);
+
+    s->nb_slices = (avctx->coded_height + s->slice_height - 1) / s->slice_height;
+    if (s->nb_slices > INT_MAX / sizeof(Slice)) {
+        av_log(avctx, AV_LOG_ERROR, "invalid number of slices: %d\n", s->nb_slices);
+        return AVERROR_INVALIDDATA;
+    }
+
+    for (i = 0; i < s->planes; i++) {
+        av_fast_malloc(&s->slices[i], &s->slices_size[i], s->nb_slices * sizeof(Slice));
+        if (!s->slices[i])
+            return AVERROR(ENOMEM);
+
+        offset = bytestream2_get_le32(&gb);
+        if (offset >= avpkt->size - header_size)
+            return AVERROR_INVALIDDATA;
+
+        if (i == 0)
+            first_offset = offset;
+
+        for (j = 0; j < s->nb_slices - 1; j++) {
+            s->slices[i][j].start = offset + header_size;
+            next_offset = bytestream2_get_le32(&gb);
+            s->slices[i][j].size  = next_offset - offset;
+            offset = next_offset;
+
+            if (offset >= avpkt->size - header_size)
+                return AVERROR_INVALIDDATA;
+        }
+
+        s->slices[i][j].start = offset + header_size;
+        s->slices[i][j].size  = avpkt->size - s->slices[i][j].start;
+    }
+
+    if (bytestream2_get_byte(&gb) != s->planes)
+        return AVERROR_INVALIDDATA;
+
+    bytestream2_skip(&gb, s->nb_slices * s->planes);
+
+    table_size = header_size + first_offset - bytestream2_tell(&gb);
+    if (table_size < 2)
+        return AVERROR_INVALIDDATA;
+
+    if ((ret = init_get_bits8(&b, avpkt->data + bytestream2_tell(&gb), table_size)) < 0)
+        return ret;
+
+    memset(s->len, 0, sizeof(s->len));
+    j = i = 0;
+    while (get_bits_left(&b) >= 8) {
+        int l = get_bits(&b, 4);
+        int x = get_bits(&b, 4);
+        int L = get_bitsz(&b, l) + 1;
+
+        for (k = 0; k < L; k++) {
+            if (j + k < 256)
+                s->len[i][j + k] = x;
+        }
+
+        j += L;
+        if (j == 256) {
+            j = 0;
+            if (build_huff(&s->vlc[i], s->len[i])) {
+                av_log(avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
+                return AVERROR_INVALIDDATA;
+            }
+            i++;
+            if (i == s->planes) {
+                break;
+            }
+        } else if (j > 256) {
+            return AVERROR_INVALIDDATA;
+        }
+    }
+
+    if (i != s->planes) {
+        av_log(avctx, AV_LOG_ERROR, "Huffman tables too short\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    p->pict_type = AV_PICTURE_TYPE_I;
+    p->key_frame = 1;
+
+    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
+        return ret;
+
+    s->buf = avpkt->data;
+    s->p = p;
+    avctx->execute2(avctx, decode_slice, NULL, NULL, s->nb_slices);
+
+    if (avctx->pix_fmt == AV_PIX_FMT_GBRP ||
+        avctx->pix_fmt == AV_PIX_FMT_GBRAP) {
+        FFSWAP(uint8_t*, p->data[0], p->data[1]);
+        FFSWAP(int, p->linesize[0], p->linesize[1]);
+    }
+
+    *got_frame = 1;
+
+    if (ret < 0)
+        return ret;
+    return avpkt->size;
+}
+
+#if HAVE_THREADS
+static int decode_init_thread_copy(AVCodecContext *avctx)
+{
+    MagicYUVContext *s = avctx->priv_data;
+
+    s->slices[0] = 0;
+    s->slices[1] = 0;
+    s->slices[2] = 0;
+    s->slices[3] = 0;
+    s->slices_size[0] = 0;
+    s->slices_size[1] = 0;
+    s->slices_size[2] = 0;
+    s->slices_size[3] = 0;
+
+    return 0;
+}
+#endif
+
+static av_cold int decode_end(AVCodecContext *avctx)
+{
+    MagicYUVContext * const s = avctx->priv_data;
+
+    av_freep(&s->slices[0]);
+    av_freep(&s->slices[1]);
+    av_freep(&s->slices[2]);
+    av_freep(&s->slices[3]);
+    s->slices_size[0] = 0;
+    s->slices_size[1] = 0;
+    s->slices_size[2] = 0;
+    s->slices_size[3] = 0;
+    ff_free_vlc(&s->vlc[0]);
+    ff_free_vlc(&s->vlc[1]);
+    ff_free_vlc(&s->vlc[2]);
+    ff_free_vlc(&s->vlc[3]);
+
+    return 0;
+}
+
+AVCodec ff_magicyuv_decoder = {
+    .name             = "magicyuv",
+    .long_name        = NULL_IF_CONFIG_SMALL("MagicYUV Lossless Video"),
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_MAGICYUV,
+    .priv_data_size   = sizeof(MagicYUVContext),
+    .init             = decode_init,
+    .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
+    .close            = decode_end,
+    .decode           = decode_frame,
+    .capabilities     = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS,
+};
diff --git a/libavcodec/mathops.c b/libavcodec/mathops.c
deleted file mode 100644
index 31c8e69..0000000
--- a/libavcodec/mathops.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "mathops.h"
-
-#ifdef TEST
-
-#include <stdlib.h>
-
-int main(void)
-{
-    unsigned u;
-
-    for(u=0; u<65536; u++) {
-        unsigned s = u*u;
-        unsigned root = ff_sqrt(s);
-        unsigned root_m1 = ff_sqrt(s-1);
-        if (s && root != u) {
-            fprintf(stderr, "ff_sqrt failed at %u with %u\n", s, root);
-            return 1;
-        }
-        if (u && root_m1 != u - 1) {
-            fprintf(stderr, "ff_sqrt failed at %u with %u\n", s, root);
-            return 1;
-        }
-    }
-    return 0;
-}
-#endif /* TEST */
diff --git a/libavcodec/mathops.h b/libavcodec/mathops.h
index 4988f1d..5168dc2 100644
--- a/libavcodec/mathops.h
+++ b/libavcodec/mathops.h
@@ -33,6 +33,7 @@ extern const uint32_t ff_inverse[257];
 extern const uint8_t ff_sqrt_tab[256];
 extern const uint8_t ff_crop_tab[256 + 2 * MAX_NEG_CROP];
 extern const uint8_t ff_zigzag_direct[64];
+extern const uint8_t ff_zigzag_scan[16+1];
 
 #if   ARCH_ARM
 #   include "arm/mathops.h"
diff --git a/libavcodec/mathtables.c b/libavcodec/mathtables.c
index 7b5efb8..81eabc7 100644
--- a/libavcodec/mathtables.c
+++ b/libavcodec/mathtables.c
@@ -105,3 +105,10 @@ const uint8_t ff_zigzag_direct[64] = {
     58, 59, 52, 45, 38, 31, 39, 46,
     53, 60, 61, 54, 47, 55, 62, 63
 };
+
+const uint8_t ff_zigzag_scan[16+1] = {
+    0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
+    1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
+    1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,
+    3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4,
+};
diff --git a/libavcodec/mediacodec_sw_buffer.c b/libavcodec/mediacodec_sw_buffer.c
new file mode 100644
index 0000000..7baf120
--- /dev/null
+++ b/libavcodec/mediacodec_sw_buffer.c
@@ -0,0 +1,339 @@
+/*
+ * Android MediaCodec software buffer copy functions
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * 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 <string.h>
+#include <sys/types.h>
+
+#include "libavutil/frame.h"
+#include "libavutil/mem.h"
+
+#include "avcodec.h"
+#include "mediacodecdec.h"
+#include "mediacodec_wrapper.h"
+#include "mediacodec_sw_buffer.h"
+
+#define QCOM_TILE_WIDTH 64
+#define QCOM_TILE_HEIGHT 32
+#define QCOM_TILE_SIZE (QCOM_TILE_WIDTH * QCOM_TILE_HEIGHT)
+#define QCOM_TILE_GROUP_SIZE (4 * QCOM_TILE_SIZE)
+
+/**
+ * The code handling the various YUV color formats is taken from the
+ * GStreamer project.
+ *
+ * Gstreamer reference:
+ * https://cgit.freedesktop.org/gstreamer/gst-plugins-bad/tree/sys/androidmedia/
+ *
+ * Copyright (C) 2012, Collabora Ltd.
+ *   Author: Sebastian Dröge <sebastian.droege at collabora.co.uk>
+ *
+ * Copyright (C) 2012, Rafaël Carré <funman at videolanorg>
+ *
+ * Copyright (C) 2015, Sebastian Dröge <sebastian at centricular.com>
+ *
+ * Copyright (C) 2014-2015, Collabora Ltd.
+ *   Author: Matthieu Bouron <matthieu.bouron at gcollabora.com>
+ *
+ * Copyright (C) 2015, Edward Hervey
+ *   Author: Edward Hervey <bilboed at gmail.com>
+ *
+ * Copyright (C) 2015, Matthew Waters <matthew at centricular.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+void ff_mediacodec_sw_buffer_copy_yuv420_planar(AVCodecContext *avctx,
+                                                MediaCodecDecContext *s,
+                                                uint8_t *data,
+                                                size_t size,
+                                                FFAMediaCodecBufferInfo *info,
+                                                AVFrame *frame)
+{
+    int i;
+    uint8_t *src = NULL;
+
+    for (i = 0; i < 3; i++) {
+        int stride = s->stride;
+        int height;
+
+        src = data + info->offset;
+        if (i == 0) {
+            height = avctx->height;
+
+            src += s->crop_top * s->stride;
+            src += s->crop_left;
+        } else {
+            height = avctx->height / 2;
+            stride = (s->stride + 1) / 2;
+
+            src += s->slice_height * s->stride;
+
+            if (i == 2) {
+                src += ((s->slice_height + 1) / 2) * stride;
+            }
+
+            src += s->crop_top * stride;
+            src += (s->crop_left / 2);
+        }
+
+        if (frame->linesize[i] == stride) {
+            memcpy(frame->data[i], src, height * stride);
+        } else {
+            int j, width;
+            uint8_t *dst = frame->data[i];
+
+            if (i == 0) {
+                width = avctx->width;
+            } else if (i >= 1) {
+                width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2) / 2);
+            }
+
+            for (j = 0; j < height; j++) {
+                memcpy(dst, src, width);
+                src += stride;
+                dst += frame->linesize[i];
+            }
+        }
+    }
+}
+
+void ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx,
+                                                     MediaCodecDecContext *s,
+                                                     uint8_t *data,
+                                                     size_t size,
+                                                     FFAMediaCodecBufferInfo *info,
+                                                     AVFrame *frame)
+{
+    int i;
+    uint8_t *src = NULL;
+
+    for (i = 0; i < 2; i++) {
+        int height;
+
+        src = data + info->offset;
+        if (i == 0) {
+            height = avctx->height;
+
+            src += s->crop_top * s->stride;
+            src += s->crop_left;
+        } else if (i == 1) {
+            height = avctx->height / 2;
+
+            src += s->slice_height * s->stride;
+            src += s->crop_top * s->stride;
+            src += s->crop_left;
+        }
+
+        if (frame->linesize[i] == s->stride) {
+            memcpy(frame->data[i], src, height * s->stride);
+        } else {
+            int j, width;
+            uint8_t *dst = frame->data[i];
+
+            if (i == 0) {
+                width = avctx->width;
+            } else if (i == 1) {
+                width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2));
+            }
+
+            for (j = 0; j < height; j++) {
+                memcpy(dst, src, width);
+                src += s->stride;
+                dst += frame->linesize[i];
+            }
+        }
+    }
+}
+
+
+
+void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(AVCodecContext *avctx,
+                                                            MediaCodecDecContext *s,
+                                                            uint8_t *data,
+                                                            size_t size,
+                                                            FFAMediaCodecBufferInfo *info,
+                                                            AVFrame *frame)
+{
+    int i;
+    uint8_t *src = NULL;
+
+    for (i = 0; i < 2; i++) {
+        int height;
+
+        src = data + info->offset;
+        if (i == 0) {
+            height = avctx->height;
+        } else if (i == 1) {
+            height = avctx->height / 2;
+
+            src += (s->slice_height - s->crop_top / 2) * s->stride;
+
+            src += s->crop_top * s->stride;
+            src += s->crop_left;
+        }
+
+        if (frame->linesize[i] == s->stride) {
+            memcpy(frame->data[i], src, height * s->stride);
+        } else {
+            int j, width;
+            uint8_t *dst = frame->data[i];
+
+            if (i == 0) {
+                width = avctx->width;
+            } else if (i == 1) {
+                width = FFMIN(frame->linesize[i], FFALIGN(avctx->width, 2));
+            }
+
+            for (j = 0; j < height; j++) {
+                memcpy(dst, src, width);
+                src += s->stride;
+                dst += frame->linesize[i];
+            }
+        }
+    }
+}
+
+/**
+ * The code handling the QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka
+ * color format is taken from the VLC project.
+ *
+ * VLC reference:
+ * http://git.videolan.org/?p=vlc.git;a=blob;f=modules/codec/omxil/qcom.c;hb=HEAD
+ *
+ * VLC copyright notice:
+ *
+ *****************************************************************************
+ * qcom.c : pixel format translation for Qualcomm tiled nv12
+ *****************************************************************************
+ * Copyright © 2012 Rafaël Carré
+ *
+ * Authors: Rafaël Carré <funman at videolanorg>
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *
+ */
+
+static size_t qcom_tile_pos(size_t x, size_t y, size_t w, size_t h)
+{
+  size_t flim = x + (y & ~1) * w;
+
+  if (y & 1) {
+    flim += (x & ~3) + 2;
+  } else if ((h & 1) == 0 || y != (h - 1)) {
+    flim += (x + 2) & ~3;
+  }
+
+  return flim;
+}
+
+void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(AVCodecContext *avctx,
+                                                                           MediaCodecDecContext *s,
+                                                                           uint8_t *data,
+                                                                           size_t size,
+                                                                           FFAMediaCodecBufferInfo *info,
+                                                                           AVFrame *frame)
+{
+    size_t width = frame->width;
+    size_t linesize = frame->linesize[0];
+    size_t height = frame->height;
+
+    const size_t tile_w = (width - 1) / QCOM_TILE_WIDTH + 1;
+    const size_t tile_w_align = (tile_w + 1) & ~1;
+    const size_t tile_h_luma = (height - 1) / QCOM_TILE_HEIGHT + 1;
+    const size_t tile_h_chroma = (height / 2 - 1) / QCOM_TILE_HEIGHT + 1;
+
+    size_t luma_size = tile_w_align * tile_h_luma * QCOM_TILE_SIZE;
+    if((luma_size % QCOM_TILE_GROUP_SIZE) != 0)
+        luma_size = (((luma_size - 1) / QCOM_TILE_GROUP_SIZE) + 1) * QCOM_TILE_GROUP_SIZE;
+
+    for(size_t y = 0; y < tile_h_luma; y++) {
+        size_t row_width = width;
+        for(size_t x = 0; x < tile_w; x++) {
+            size_t tile_width = row_width;
+            size_t tile_height = height;
+            /* dest luma memory index for this tile */
+            size_t luma_idx = y * QCOM_TILE_HEIGHT * linesize + x * QCOM_TILE_WIDTH;
+            /* dest chroma memory index for this tile */
+            /* XXX: remove divisions */
+            size_t chroma_idx = (luma_idx / linesize) * linesize / 2 + (luma_idx % linesize);
+
+            /* luma source pointer for this tile */
+            const uint8_t *src_luma  = data
+                + qcom_tile_pos(x, y,tile_w_align, tile_h_luma) * QCOM_TILE_SIZE;
+
+            /* chroma source pointer for this tile */
+            const uint8_t *src_chroma = data + luma_size
+                + qcom_tile_pos(x, y/2, tile_w_align, tile_h_chroma) * QCOM_TILE_SIZE;
+            if (y & 1)
+                src_chroma += QCOM_TILE_SIZE/2;
+
+            /* account for right columns */
+            if (tile_width > QCOM_TILE_WIDTH)
+                tile_width = QCOM_TILE_WIDTH;
+
+            /* account for bottom rows */
+            if (tile_height > QCOM_TILE_HEIGHT)
+                tile_height = QCOM_TILE_HEIGHT;
+
+            tile_height /= 2;
+            while (tile_height--) {
+                memcpy(frame->data[0] + luma_idx, src_luma, tile_width);
+                src_luma += QCOM_TILE_WIDTH;
+                luma_idx += linesize;
+
+                memcpy(frame->data[0] + luma_idx, src_luma, tile_width);
+                src_luma += QCOM_TILE_WIDTH;
+                luma_idx += linesize;
+
+                memcpy(frame->data[1] + chroma_idx, src_chroma, tile_width);
+                src_chroma += QCOM_TILE_WIDTH;
+                chroma_idx += linesize;
+            }
+            row_width -= QCOM_TILE_WIDTH;
+        }
+        height -= QCOM_TILE_HEIGHT;
+    }
+}
diff --git a/libavcodec/mediacodec_sw_buffer.h b/libavcodec/mediacodec_sw_buffer.h
new file mode 100644
index 0000000..c29de08
--- /dev/null
+++ b/libavcodec/mediacodec_sw_buffer.h
@@ -0,0 +1,62 @@
+/*
+ * Android MediaCodec software buffer copy functions
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_MEDIACODEC_SW_BUFFER_H
+#define AVCODEC_MEDIACODEC_SW_BUFFER_H
+
+#include <sys/types.h>
+
+#include "libavutil/frame.h"
+
+#include "avcodec.h"
+#include "mediacodecdec.h"
+#include "mediacodec_wrapper.h"
+
+void ff_mediacodec_sw_buffer_copy_yuv420_planar(AVCodecContext *avctx,
+                                                MediaCodecDecContext *s,
+                                                uint8_t *data,
+                                                size_t size,
+                                                FFAMediaCodecBufferInfo *info,
+                                                AVFrame *frame);
+
+void ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(AVCodecContext *avctx,
+                                                     MediaCodecDecContext *s,
+                                                     uint8_t *data,
+                                                     size_t size,
+                                                     FFAMediaCodecBufferInfo *info,
+                                                     AVFrame *frame);
+
+void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(AVCodecContext *avctx,
+                                                     MediaCodecDecContext *s,
+                                                     uint8_t *data,
+                                                     size_t size,
+                                                     FFAMediaCodecBufferInfo *info,
+                                                     AVFrame *frame);
+
+void ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(AVCodecContext *avctx,
+                                                     MediaCodecDecContext *s,
+                                                     uint8_t *data,
+                                                     size_t size,
+                                                     FFAMediaCodecBufferInfo *info,
+                                                     AVFrame *frame);
+
+#endif /* AVCODEC_MEDIACODEC_SW_BUFFER_H */
diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c
new file mode 100644
index 0000000..546768f
--- /dev/null
+++ b/libavcodec/mediacodec_wrapper.c
@@ -0,0 +1,1808 @@
+/*
+ * Android MediaCodec Wrapper
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * 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 <jni.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/mem.h"
+#include "libavutil/avstring.h"
+
+#include "avcodec.h"
+#include "ffjni.h"
+#include "version.h"
+#include "mediacodec_wrapper.h"
+
+struct JNIAMediaCodecListFields {
+
+    jclass mediacodec_list_class;
+    jmethodID init_id;
+    jmethodID find_decoder_for_format_id;
+
+    jmethodID get_codec_count_id;
+    jmethodID get_codec_info_at_id;
+
+    jclass mediacodec_info_class;
+    jmethodID get_name_id;
+    jmethodID get_codec_capabilities_id;
+    jmethodID get_supported_types_id;
+    jmethodID is_encoder_id;
+
+    jclass codec_capabilities_class;
+    jfieldID color_formats_id;
+    jfieldID profile_levels_id;
+
+    jclass codec_profile_level_class;
+    jfieldID profile_id;
+    jfieldID level_id;
+
+    jfieldID avc_profile_baseline_id;
+    jfieldID avc_profile_main_id;
+    jfieldID avc_profile_extended_id;
+    jfieldID avc_profile_high_id;
+    jfieldID avc_profile_high10_id;
+    jfieldID avc_profile_high422_id;
+    jfieldID avc_profile_high444_id;
+
+} JNIAMediaCodecListFields;
+
+static const struct FFJniField jni_amediacodeclist_mapping[] = {
+    { "android/media/MediaCodecList", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_list_class), 1 },
+        { "android/media/MediaCodecList", "<init>", "(I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, init_id), 0 },
+        { "android/media/MediaCodecList", "findDecoderForFormat", "(Landroid/media/MediaFormat;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, find_decoder_for_format_id), 0 },
+
+        { "android/media/MediaCodecList", "getCodecCount", "()I", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_count_id), 1 },
+        { "android/media/MediaCodecList", "getCodecInfoAt", "(I)Landroid/media/MediaCodecInfo;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_info_at_id), 1 },
+
+    { "android/media/MediaCodecInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, mediacodec_info_class), 1 },
+        { "android/media/MediaCodecInfo", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_name_id), 1 },
+        { "android/media/MediaCodecInfo", "getCapabilitiesForType", "(Ljava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_codec_capabilities_id), 1 },
+        { "android/media/MediaCodecInfo", "getSupportedTypes", "()[Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, get_supported_types_id), 1 },
+        { "android/media/MediaCodecInfo", "isEncoder", "()Z", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecListFields, is_encoder_id), 1 },
+
+    { "android/media/MediaCodecInfo$CodecCapabilities", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, codec_capabilities_class), 1 },
+        { "android/media/MediaCodecInfo$CodecCapabilities", "colorFormats", "[I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, color_formats_id), 1 },
+        { "android/media/MediaCodecInfo$CodecCapabilities", "profileLevels", "[Landroid/media/MediaCodecInfo$CodecProfileLevel;", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, profile_levels_id), 1 },
+
+    { "android/media/MediaCodecInfo$CodecProfileLevel", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecListFields, codec_profile_level_class), 1 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "profile", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, profile_id), 1 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "level", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecListFields, level_id), 1 },
+
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileBaseline", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_baseline_id), 1 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileMain", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_main_id), 1 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileExtended", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_extended_id), 1 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high_id), 1 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh10", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high10_id), 1 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh422", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high422_id), 1 },
+        { "android/media/MediaCodecInfo$CodecProfileLevel", "AVCProfileHigh444", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecListFields, avc_profile_high444_id), 1 },
+
+    { NULL }
+};
+
+struct JNIAMediaFormatFields {
+
+    jclass mediaformat_class;
+
+    jmethodID init_id;
+
+    jmethodID get_integer_id;
+    jmethodID get_long_id;
+    jmethodID get_float_id;
+    jmethodID get_bytebuffer_id;
+    jmethodID get_string_id;
+
+    jmethodID set_integer_id;
+    jmethodID set_long_id;
+    jmethodID set_float_id;
+    jmethodID set_bytebuffer_id;
+    jmethodID set_string_id;
+
+    jmethodID to_string_id;
+
+} JNIAMediaFormatFields;
+
+static const struct FFJniField jni_amediaformat_mapping[] = {
+    { "android/media/MediaFormat", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaFormatFields, mediaformat_class), 1 },
+
+        { "android/media/MediaFormat", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, init_id), 1 },
+
+        { "android/media/MediaFormat", "getInteger", "(Ljava/lang/String;)I", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_integer_id), 1 },
+        { "android/media/MediaFormat", "getLong", "(Ljava/lang/String;)J", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_long_id), 1 },
+        { "android/media/MediaFormat", "getFloat", "(Ljava/lang/String;)F", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_float_id), 1 },
+        { "android/media/MediaFormat", "getByteBuffer", "(Ljava/lang/String;)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_bytebuffer_id), 1 },
+        { "android/media/MediaFormat", "getString", "(Ljava/lang/String;)Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, get_string_id), 1 },
+
+        { "android/media/MediaFormat", "setInteger", "(Ljava/lang/String;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_integer_id), 1 },
+        { "android/media/MediaFormat", "setLong", "(Ljava/lang/String;J)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_long_id), 1 },
+        { "android/media/MediaFormat", "setFloat", "(Ljava/lang/String;F)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_float_id), 1 },
+        { "android/media/MediaFormat", "setByteBuffer", "(Ljava/lang/String;Ljava/nio/ByteBuffer;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_bytebuffer_id), 1 },
+        { "android/media/MediaFormat", "setString", "(Ljava/lang/String;Ljava/lang/String;)V", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, set_string_id), 1 },
+
+        { "android/media/MediaFormat", "toString", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaFormatFields, to_string_id), 1 },
+
+    { NULL }
+};
+
+static const AVClass amediaformat_class = {
+    .class_name = "amediaformat",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVCODEC_VERSION_INT,
+};
+
+struct FFAMediaFormat {
+
+    const AVClass *class;
+    struct JNIAMediaFormatFields jfields;
+    jobject object;
+};
+
+struct JNIAMediaCodecFields {
+
+    jclass mediacodec_class;
+
+    jfieldID info_try_again_later_id;
+    jfieldID info_output_buffers_changed_id;
+    jfieldID info_output_format_changed_id;
+
+    jfieldID buffer_flag_codec_config_id;
+    jfieldID buffer_flag_end_of_stream_id;
+    jfieldID buffer_flag_key_frame_id;
+
+    jfieldID configure_flag_encode_id;
+
+    jmethodID create_by_codec_name_id;
+    jmethodID create_decoder_by_type_id;
+    jmethodID create_encoder_by_type_id;
+
+    jmethodID get_name_id;
+
+    jmethodID configure_id;
+    jmethodID start_id;
+    jmethodID flush_id;
+    jmethodID stop_id;
+    jmethodID release_id;
+
+    jmethodID get_output_format_id;
+
+    jmethodID dequeue_input_buffer_id;
+    jmethodID queue_input_buffer_id;
+    jmethodID get_input_buffer_id;
+    jmethodID get_input_buffers_id;
+
+    jmethodID dequeue_output_buffer_id;
+    jmethodID get_output_buffer_id;
+    jmethodID get_output_buffers_id;
+    jmethodID release_output_buffer_id;
+    jmethodID release_output_buffer_at_time_id;
+
+    jclass mediainfo_class;
+
+    jmethodID init_id;
+
+    jfieldID flags_id;
+    jfieldID offset_id;
+    jfieldID presentation_time_us_id;
+    jfieldID size_id;
+
+} JNIAMediaCodecFields;
+
+static const struct FFJniField jni_amediacodec_mapping[] = {
+    { "android/media/MediaCodec", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediacodec_class), 1 },
+
+        { "android/media/MediaCodec", "INFO_TRY_AGAIN_LATER", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_try_again_later_id), 1 },
+        { "android/media/MediaCodec", "INFO_OUTPUT_BUFFERS_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_buffers_changed_id), 1 },
+        { "android/media/MediaCodec", "INFO_OUTPUT_FORMAT_CHANGED", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, info_output_format_changed_id), 1 },
+
+        { "android/media/MediaCodec", "BUFFER_FLAG_CODEC_CONFIG", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_codec_config_id), 1 },
+        { "android/media/MediaCodec", "BUFFER_FLAG_END_OF_STREAM", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_end_of_stream_id), 1 },
+        { "android/media/MediaCodec", "BUFFER_FLAG_KEY_FRAME", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, buffer_flag_key_frame_id), 0 },
+
+        { "android/media/MediaCodec", "CONFIGURE_FLAG_ENCODE", "I", FF_JNI_STATIC_FIELD, offsetof(struct JNIAMediaCodecFields, configure_flag_encode_id), 1 },
+
+        { "android/media/MediaCodec", "createByCodecName", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_by_codec_name_id), 1 },
+        { "android/media/MediaCodec", "createDecoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_decoder_by_type_id), 1 },
+        { "android/media/MediaCodec", "createEncoderByType", "(Ljava/lang/String;)Landroid/media/MediaCodec;", FF_JNI_STATIC_METHOD, offsetof(struct JNIAMediaCodecFields, create_encoder_by_type_id), 1 },
+
+        { "android/media/MediaCodec", "getName", "()Ljava/lang/String;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_name_id), 1 },
+
+        { "android/media/MediaCodec", "configure", "(Landroid/media/MediaFormat;Landroid/view/Surface;Landroid/media/MediaCrypto;I)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, configure_id), 1 },
+        { "android/media/MediaCodec", "start", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, start_id), 1 },
+        { "android/media/MediaCodec", "flush", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, flush_id), 1 },
+        { "android/media/MediaCodec", "stop", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, stop_id), 1 },
+        { "android/media/MediaCodec", "release", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_id), 1 },
+
+        { "android/media/MediaCodec", "getOutputFormat", "()Landroid/media/MediaFormat;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_format_id), 1 },
+
+        { "android/media/MediaCodec", "dequeueInputBuffer", "(J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_input_buffer_id), 1 },
+        { "android/media/MediaCodec", "queueInputBuffer", "(IIIJI)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, queue_input_buffer_id), 1 },
+        { "android/media/MediaCodec", "getInputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffer_id), 0 },
+        { "android/media/MediaCodec", "getInputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_input_buffers_id), 1 },
+
+        { "android/media/MediaCodec", "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, dequeue_output_buffer_id), 1 },
+        { "android/media/MediaCodec", "getOutputBuffer", "(I)Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffer_id), 0 },
+        { "android/media/MediaCodec", "getOutputBuffers", "()[Ljava/nio/ByteBuffer;", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, get_output_buffers_id), 1 },
+        { "android/media/MediaCodec", "releaseOutputBuffer", "(IZ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_id), 1 },
+        { "android/media/MediaCodec", "releaseOutputBuffer", "(IJ)V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, release_output_buffer_at_time_id), 0 },
+
+    { "android/media/MediaCodec$BufferInfo", NULL, NULL, FF_JNI_CLASS, offsetof(struct JNIAMediaCodecFields, mediainfo_class), 1 },
+
+        { "android/media/MediaCodec.BufferInfo", "<init>", "()V", FF_JNI_METHOD, offsetof(struct JNIAMediaCodecFields, init_id), 1 },
+        { "android/media/MediaCodec.BufferInfo", "flags", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, flags_id), 1 },
+        { "android/media/MediaCodec.BufferInfo", "offset", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, offset_id), 1 },
+        { "android/media/MediaCodec.BufferInfo", "presentationTimeUs", "J", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, presentation_time_us_id), 1 },
+        { "android/media/MediaCodec.BufferInfo", "size", "I", FF_JNI_FIELD, offsetof(struct JNIAMediaCodecFields, size_id), 1 },
+
+    { NULL }
+};
+
+static const AVClass amediacodec_class = {
+    .class_name = "amediacodec",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVCODEC_VERSION_INT,
+};
+
+struct FFAMediaCodec {
+
+    const AVClass *class;
+
+    struct JNIAMediaCodecFields jfields;
+
+    jobject object;
+
+    jobject input_buffers;
+    jobject output_buffers;
+
+    int INFO_TRY_AGAIN_LATER;
+    int INFO_OUTPUT_BUFFERS_CHANGED;
+    int INFO_OUTPUT_FORMAT_CHANGED;
+
+    int BUFFER_FLAG_CODEC_CONFIG;
+    int BUFFER_FLAG_END_OF_STREAM;
+    int BUFFER_FLAG_KEY_FRAME;
+
+    int CONFIGURE_FLAG_ENCODE;
+
+    int has_get_i_o_buffer;
+};
+
+#define JNI_ATTACH_ENV_OR_RETURN(env, attached, log_ctx, ret) do { \
+    (env) = ff_jni_attach_env(attached, log_ctx);                  \
+    if (!(env)) {                                                  \
+        return ret;                                                \
+    }                                                              \
+} while (0)
+
+#define JNI_ATTACH_ENV_OR_RETURN_VOID(env, attached, log_ctx) do { \
+    (env) = ff_jni_attach_env(attached, log_ctx);              \
+    if (!(env)) {                                                  \
+        return;                                                    \
+    }                                                              \
+} while (0)
+
+#define JNI_DETACH_ENV(attached, log_ctx) do { \
+    if (attached)                              \
+        ff_jni_detach_env(log_ctx);            \
+} while (0)
+
+
+
+int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx)
+{
+    int ret = -1;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+    struct JNIAMediaCodecListFields jfields = { 0 };
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, avctx, -1);
+
+    if (ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx) < 0) {
+        goto done;
+    }
+
+    if (avctx->codec_id == AV_CODEC_ID_H264) {
+        jfieldID field_id = 0;
+
+        switch(avctx->profile) {
+        case FF_PROFILE_H264_BASELINE:
+        case FF_PROFILE_H264_CONSTRAINED_BASELINE:
+            field_id = jfields.avc_profile_baseline_id;
+            break;
+        case FF_PROFILE_H264_MAIN:
+            field_id = jfields.avc_profile_main_id;
+            break;
+        case FF_PROFILE_H264_EXTENDED:
+            field_id = jfields.avc_profile_extended_id;
+            break;
+        case FF_PROFILE_H264_HIGH:
+            field_id = jfields.avc_profile_high_id;
+            break;
+        case FF_PROFILE_H264_HIGH_10:
+        case FF_PROFILE_H264_HIGH_10_INTRA:
+            field_id = jfields.avc_profile_high10_id;
+            break;
+        case FF_PROFILE_H264_HIGH_422:
+        case FF_PROFILE_H264_HIGH_422_INTRA:
+            field_id = jfields.avc_profile_high422_id;
+            break;
+        case FF_PROFILE_H264_HIGH_444:
+        case FF_PROFILE_H264_HIGH_444_INTRA:
+        case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
+            field_id = jfields.avc_profile_high444_id;
+            break;
+        }
+
+        if (field_id) {
+            ret = (*env)->GetStaticIntField(env, jfields.codec_profile_level_class, field_id);
+            if (ff_jni_exception_check(env, 1, avctx) < 0) {
+                ret = -1;
+                goto done;
+            }
+        }
+    }
+
+done:
+    ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, avctx);
+
+    JNI_DETACH_ENV(attached, avctx);
+
+    return ret;
+}
+
+char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int encoder, void *log_ctx)
+{
+    int ret;
+    int i;
+    int codec_count;
+    int found_codec = 0;
+    char *name = NULL;
+    char *supported_type = NULL;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+    struct JNIAMediaCodecListFields jfields = { 0 };
+    struct JNIAMediaFormatFields mediaformat_jfields = { 0 };
+
+    jobject format = NULL;
+    jobject codec = NULL;
+    jobject codec_name = NULL;
+
+    jobject info = NULL;
+    jobject type = NULL;
+    jobjectArray types = NULL;
+
+    jobject capabilities = NULL;
+    jobject profile_level = NULL;
+    jobjectArray profile_levels = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, log_ctx, NULL);
+
+    if ((ret = ff_jni_init_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx)) < 0) {
+        goto done;
+    }
+
+    if ((ret = ff_jni_init_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx)) < 0) {
+        goto done;
+    }
+
+    codec_count = (*env)->CallStaticIntMethod(env, jfields.mediacodec_list_class, jfields.get_codec_count_id);
+    if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+        goto done;
+    }
+
+    for(i = 0; i < codec_count; i++) {
+        int j;
+        int type_count;
+        int is_encoder;
+
+        info = (*env)->CallStaticObjectMethod(env, jfields.mediacodec_list_class, jfields.get_codec_info_at_id, i);
+        if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+            goto done;
+        }
+
+        types = (*env)->CallObjectMethod(env, info, jfields.get_supported_types_id);
+        if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+            goto done;
+        }
+
+        is_encoder = (*env)->CallBooleanMethod(env, info, jfields.is_encoder_id);
+        if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+            goto done;
+        }
+
+        if (is_encoder != encoder) {
+            goto done_with_info;
+        }
+
+        type_count = (*env)->GetArrayLength(env, types);
+        for (j = 0; j < type_count; j++) {
+            int k;
+            int profile_count;
+
+            type = (*env)->GetObjectArrayElement(env, types, j);
+            if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+                goto done;
+            }
+
+            supported_type = ff_jni_jstring_to_utf_chars(env, type, log_ctx);
+            if (!supported_type) {
+                goto done;
+            }
+
+            if (!av_strcasecmp(supported_type, mime)) {
+                codec_name = (*env)->CallObjectMethod(env, info, jfields.get_name_id);
+                if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+                    goto done;
+                }
+
+                name = ff_jni_jstring_to_utf_chars(env, codec_name, log_ctx);
+                if (!name) {
+                    goto done;
+                }
+
+                if (strstr(name, "OMX.google")) {
+                    av_freep(&name);
+                    goto done_with_type;
+                }
+
+                capabilities = (*env)->CallObjectMethod(env, info, jfields.get_codec_capabilities_id, type);
+                if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+                    goto done;
+                }
+
+                profile_levels = (*env)->GetObjectField(env, capabilities, jfields.profile_levels_id);
+                if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+                    goto done;
+                }
+
+                profile_count = (*env)->GetArrayLength(env, profile_levels);
+                for (k = 0; k < profile_count; k++) {
+                    int supported_profile = 0;
+
+                    if (profile < 0) {
+                        found_codec = 1;
+                        break;
+                    }
+
+                    profile_level = (*env)->GetObjectArrayElement(env, profile_levels, k);
+                    if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+                        goto done;
+                    }
+
+                    supported_profile = (*env)->GetIntField(env, profile_level, jfields.profile_id);
+                    if (ff_jni_exception_check(env, 1, log_ctx) < 0) {
+                        goto done;
+                    }
+
+                    found_codec = profile == supported_profile;
+
+                    if (profile_level) {
+                        (*env)->DeleteLocalRef(env, profile_level);
+                        profile_level = NULL;
+                    }
+
+                    if (found_codec) {
+                        break;
+                    }
+                }
+            }
+
+done_with_type:
+            if (profile_levels) {
+                (*env)->DeleteLocalRef(env, profile_levels);
+                profile_levels = NULL;
+            }
+
+            if (capabilities) {
+                (*env)->DeleteLocalRef(env, capabilities);
+                capabilities = NULL;
+            }
+
+            if (type) {
+                (*env)->DeleteLocalRef(env, type);
+                type = NULL;
+            }
+
+            av_freep(&supported_type);
+
+            if (found_codec) {
+                break;
+            }
+
+            av_freep(&name);
+        }
+
+done_with_info:
+        if (info) {
+            (*env)->DeleteLocalRef(env, info);
+            info = NULL;
+        }
+
+        if (types) {
+            (*env)->DeleteLocalRef(env, types);
+            types = NULL;
+        }
+
+        if (found_codec) {
+            break;
+        }
+    }
+
+done:
+    if (format) {
+        (*env)->DeleteLocalRef(env, format);
+    }
+
+    if (codec) {
+        (*env)->DeleteLocalRef(env, codec);
+    }
+
+    if (codec_name) {
+        (*env)->DeleteLocalRef(env, codec_name);
+    }
+
+    if (info) {
+        (*env)->DeleteLocalRef(env, info);
+    }
+
+    if (type) {
+        (*env)->DeleteLocalRef(env, type);
+    }
+
+    if (types) {
+        (*env)->DeleteLocalRef(env, types);
+    }
+
+    if (capabilities) {
+        (*env)->DeleteLocalRef(env, capabilities);
+    }
+
+    if (profile_level) {
+        (*env)->DeleteLocalRef(env, profile_level);
+    }
+
+    if (profile_levels) {
+        (*env)->DeleteLocalRef(env, profile_levels);
+    }
+
+    av_freep(&supported_type);
+
+    ff_jni_reset_jfields(env, &jfields, jni_amediacodeclist_mapping, 0, log_ctx);
+    ff_jni_reset_jfields(env, &mediaformat_jfields, jni_amediaformat_mapping, 0, log_ctx);
+
+    JNI_DETACH_ENV(attached, log_ctx);
+
+    if (!found_codec) {
+        av_freep(&name);
+    }
+
+    return name;
+}
+
+FFAMediaFormat *ff_AMediaFormat_new(void)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    FFAMediaFormat *format = NULL;
+
+    format = av_mallocz(sizeof(FFAMediaFormat));
+    if (!format) {
+        return NULL;
+    }
+    format->class = &amediaformat_class;
+
+    env = ff_jni_attach_env(&attached, format);
+    if (!env) {
+        av_freep(&format);
+        return NULL;
+    }
+
+    if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
+        goto fail;
+    }
+
+    format->object = (*env)->NewObject(env, format->jfields.mediaformat_class, format->jfields.init_id);
+    if (!format->object) {
+        goto fail;
+    }
+
+    format->object = (*env)->NewGlobalRef(env, format->object);
+    if (!format->object) {
+        goto fail;
+    }
+
+    JNI_DETACH_ENV(attached, format);
+
+    return format;
+fail:
+    ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
+
+    JNI_DETACH_ENV(attached, format);
+
+    av_freep(&format);
+
+    return NULL;
+}
+
+static FFAMediaFormat *ff_AMediaFormat_newFromObject(void *object)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    FFAMediaFormat *format = NULL;
+
+    format = av_mallocz(sizeof(FFAMediaFormat));
+    if (!format) {
+        return NULL;
+    }
+    format->class = &amediaformat_class;
+
+    env = ff_jni_attach_env(&attached, format);
+    if (!env) {
+        av_freep(&format);
+        return NULL;
+    }
+
+    if (ff_jni_init_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format) < 0) {
+        goto fail;
+    }
+
+    format->object = (*env)->NewGlobalRef(env, object);
+    if (!format->object) {
+        goto fail;
+    }
+
+    JNI_DETACH_ENV(attached, format);
+
+    return format;
+fail:
+    ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
+
+    JNI_DETACH_ENV(attached, format);
+
+    av_freep(&format);
+
+    return NULL;
+}
+
+int ff_AMediaFormat_delete(FFAMediaFormat* format)
+{
+    int ret = 0;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    if (!format) {
+        return 0;
+    }
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, AVERROR_EXTERNAL);
+
+    (*env)->DeleteGlobalRef(env, format->object);
+    format->object = NULL;
+
+    ff_jni_reset_jfields(env, &format->jfields, jni_amediaformat_mapping, 1, format);
+
+    JNI_DETACH_ENV(attached, format);
+
+    av_freep(&format);
+
+    return ret;
+}
+
+char* ff_AMediaFormat_toString(FFAMediaFormat* format)
+{
+    char *ret = NULL;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring description = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, NULL);
+
+    description = (*env)->CallObjectMethod(env, format->object, format->jfields.to_string_id);
+    if (ff_jni_exception_check(env, 1, NULL) < 0) {
+        goto fail;
+    }
+
+    ret = ff_jni_jstring_to_utf_chars(env, description, format);
+fail:
+
+    if (description) {
+        (*env)->DeleteLocalRef(env, description);
+    }
+
+    JNI_DETACH_ENV(attached, format);
+
+    return ret;
+}
+
+int ff_AMediaFormat_getInt32(FFAMediaFormat* format, const char *name, int32_t *out)
+{
+    int ret = 1;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        ret = 0;
+        goto fail;
+    }
+
+    *out = (*env)->CallIntMethod(env, format->object, format->jfields.get_integer_id, key);
+    if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
+        ret = 0;
+        goto fail;
+    }
+
+    ret = 1;
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    JNI_DETACH_ENV(attached, format);
+
+    return ret;
+}
+
+int ff_AMediaFormat_getInt64(FFAMediaFormat* format, const char *name, int64_t *out)
+{
+    int ret = 1;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        ret = 0;
+        goto fail;
+    }
+
+    *out = (*env)->CallLongMethod(env, format->object, format->jfields.get_long_id, key);
+    if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
+        ret = 0;
+        goto fail;
+    }
+
+    ret = 1;
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    JNI_DETACH_ENV(attached, format);
+
+    return ret;
+}
+
+int ff_AMediaFormat_getFloat(FFAMediaFormat* format, const char *name, float *out)
+{
+    int ret = 1;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        ret = 0;
+        goto fail;
+    }
+
+    *out = (*env)->CallFloatMethod(env, format->object, format->jfields.get_float_id, key);
+    if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
+        ret = 0;
+        goto fail;
+    }
+
+    ret = 1;
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    JNI_DETACH_ENV(attached, format);
+
+    return ret;
+}
+
+int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** data, size_t *size)
+{
+    int ret = 1;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+    jobject result = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        ret = 0;
+        goto fail;
+    }
+
+    result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_bytebuffer_id, key);
+    if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
+        ret = 0;
+        goto fail;
+    }
+
+    *data = (*env)->GetDirectBufferAddress(env, result);
+    *size = (*env)->GetDirectBufferCapacity(env, result);
+
+    if (*data && *size) {
+        void *src = *data;
+        *data = av_malloc(*size);
+        if (!*data) {
+            ret = 0;
+            goto fail;
+        }
+
+        memcpy(*data, src, *size);
+    }
+
+    ret = 1;
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    if (result) {
+        (*env)->DeleteLocalRef(env, result);
+    }
+
+    JNI_DETACH_ENV(attached, format);
+
+    return ret;
+}
+
+int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const char **out)
+{
+    int ret = 1;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+    jstring result = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, format, 0);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        ret = 0;
+        goto fail;
+    }
+
+    result = (*env)->CallObjectMethod(env, format->object, format->jfields.get_string_id, key);
+    if ((ret = ff_jni_exception_check(env, 1, format)) < 0) {
+        ret = 0;
+        goto fail;
+    }
+
+    *out = ff_jni_jstring_to_utf_chars(env, result, format);
+    if (!*out) {
+        ret = 0;
+        goto fail;
+    }
+
+    ret = 1;
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    if (result) {
+        (*env)->DeleteLocalRef(env, result);
+    }
+
+    JNI_DETACH_ENV(attached, format);
+
+    return ret;
+}
+
+void ff_AMediaFormat_setInt32(FFAMediaFormat* format, const char* name, int32_t value)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        goto fail;
+    }
+
+    (*env)->CallVoidMethod(env, format->object, format->jfields.set_integer_id, key, value);
+    if (ff_jni_exception_check(env, 1, format) < 0) {
+        goto fail;
+    }
+
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    JNI_DETACH_ENV(attached, format);
+}
+
+void ff_AMediaFormat_setInt64(FFAMediaFormat* format, const char* name, int64_t value)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        goto fail;
+    }
+
+    (*env)->CallVoidMethod(env, format->object, format->jfields.set_long_id, key, value);
+    if (ff_jni_exception_check(env, 1, format) < 0) {
+        goto fail;
+    }
+
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    JNI_DETACH_ENV(attached, NULL);
+}
+
+void ff_AMediaFormat_setFloat(FFAMediaFormat* format, const char* name, float value)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        goto fail;
+    }
+
+    (*env)->CallVoidMethod(env, format->object, format->jfields.set_float_id, key, value);
+    if (ff_jni_exception_check(env, 1, format) < 0) {
+        goto fail;
+    }
+
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    JNI_DETACH_ENV(attached, NULL);
+}
+
+void ff_AMediaFormat_setString(FFAMediaFormat* format, const char* name, const char* value)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+    jstring string = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        goto fail;
+    }
+
+    string = ff_jni_utf_chars_to_jstring(env, value, format);
+    if (!string) {
+        goto fail;
+    }
+
+    (*env)->CallVoidMethod(env, format->object, format->jfields.set_string_id, key, string);
+    if (ff_jni_exception_check(env, 1, format) < 0) {
+        goto fail;
+    }
+
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    if (string) {
+        (*env)->DeleteLocalRef(env, string);
+    }
+
+    JNI_DETACH_ENV(attached, format);
+}
+
+void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* data, size_t size)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jstring key = NULL;
+    jobject buffer = NULL;
+    void *buffer_data = NULL;
+
+    av_assert0(format != NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN_VOID(env, &attached, format);
+
+    key = ff_jni_utf_chars_to_jstring(env, name, format);
+    if (!key) {
+        goto fail;
+    }
+
+    if (!data || !size) {
+        goto fail;
+    }
+
+    buffer_data = av_malloc(size);
+    if (!buffer_data) {
+        goto fail;
+    }
+
+    memcpy(buffer_data, data, size);
+
+    buffer = (*env)->NewDirectByteBuffer(env, buffer_data, size);
+    if (!buffer) {
+        goto fail;
+    }
+
+    (*env)->CallVoidMethod(env, format->object, format->jfields.set_bytebuffer_id, key, buffer);
+    if (ff_jni_exception_check(env, 1, format) < 0) {
+        goto fail;
+    }
+
+fail:
+    if (key) {
+        (*env)->DeleteLocalRef(env, key);
+    }
+
+    if (buffer) {
+        (*env)->DeleteLocalRef(env, buffer);
+    }
+
+    JNI_DETACH_ENV(attached, format);
+}
+
+static int codec_init_static_fields(FFAMediaCodec *codec)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
+    if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
+        goto fail;
+    }
+
+    codec->BUFFER_FLAG_CODEC_CONFIG = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_codec_config_id);
+    if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
+        goto fail;
+    }
+
+    codec->BUFFER_FLAG_END_OF_STREAM = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_end_of_stream_id);
+    if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
+        goto fail;
+    }
+
+    if (codec->jfields.buffer_flag_key_frame_id) {
+        codec->BUFFER_FLAG_KEY_FRAME = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.buffer_flag_key_frame_id);
+        if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
+            goto fail;
+        }
+    }
+
+    codec->CONFIGURE_FLAG_ENCODE = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.configure_flag_encode_id);
+    if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
+        goto fail;
+    }
+
+    codec->INFO_TRY_AGAIN_LATER = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_try_again_later_id);
+    if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
+        goto fail;
+    }
+
+    codec->INFO_OUTPUT_BUFFERS_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_buffers_changed_id);
+    if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
+        goto fail;
+    }
+
+    codec->INFO_OUTPUT_FORMAT_CHANGED = (*env)->GetStaticIntField(env, codec->jfields.mediacodec_class, codec->jfields.info_output_format_changed_id);
+    if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
+        goto fail;
+    }
+
+fail:
+    JNI_DETACH_ENV(attached, NULL);
+
+    return ret;
+}
+
+FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    FFAMediaCodec *codec = NULL;
+    jstring codec_name = NULL;
+
+    codec = av_mallocz(sizeof(FFAMediaCodec));
+    if (!codec) {
+        return NULL;
+    }
+    codec->class = &amediacodec_class;
+
+    env = ff_jni_attach_env(&attached, codec);
+    if (!env) {
+        av_freep(&codec);
+        return NULL;
+    }
+
+    if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
+        goto fail;
+    }
+
+    codec_name = ff_jni_utf_chars_to_jstring(env, name, codec);
+    if (!codec_name) {
+        goto fail;
+    }
+
+    codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_by_codec_name_id, codec_name);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        goto fail;
+    }
+
+    codec->object = (*env)->NewGlobalRef(env, codec->object);
+    if (!codec->object) {
+        goto fail;
+    }
+
+    if (codec_init_static_fields(codec) < 0) {
+        goto fail;
+    }
+
+    if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) {
+        codec->has_get_i_o_buffer = 1;
+    }
+
+    JNI_DETACH_ENV(attached, codec);
+
+    return codec;
+fail:
+    ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
+
+    if (codec_name) {
+        (*env)->DeleteLocalRef(env, codec_name);
+    }
+
+    JNI_DETACH_ENV(attached, codec);
+
+    av_freep(&codec);
+
+    return NULL;
+}
+
+FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    FFAMediaCodec *codec = NULL;
+    jstring mime_type = NULL;
+
+    codec = av_mallocz(sizeof(FFAMediaCodec));
+    if (!codec) {
+        return NULL;
+    }
+    codec->class = &amediacodec_class;
+
+    env = ff_jni_attach_env(&attached, codec);
+    if (!env) {
+        av_freep(&codec);
+        return NULL;
+    }
+
+    if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
+        goto fail;
+    }
+
+    mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
+    if (!mime_type) {
+        goto fail;
+    }
+
+    codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_decoder_by_type_id, mime_type);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        goto fail;
+    }
+
+    codec->object = (*env)->NewGlobalRef(env, codec->object);
+    if (!codec->object) {
+        goto fail;
+    }
+
+    if (codec_init_static_fields(codec) < 0) {
+        goto fail;
+    }
+
+    if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) {
+        codec->has_get_i_o_buffer = 1;
+    }
+
+    JNI_DETACH_ENV(attached, codec);
+
+    return codec;
+fail:
+    ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
+
+    if (mime_type) {
+        (*env)->DeleteLocalRef(env, mime_type);
+    }
+
+    JNI_DETACH_ENV(attached, codec);
+
+    av_freep(&codec);
+
+    return NULL;
+}
+
+FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime)
+{
+    int attached = 0;
+    JNIEnv *env = NULL;
+    FFAMediaCodec *codec = NULL;
+    jstring mime_type = NULL;
+
+    codec = av_mallocz(sizeof(FFAMediaCodec));
+    if (!codec) {
+        return NULL;
+    }
+    codec->class = &amediacodec_class;
+
+    env = ff_jni_attach_env(&attached, codec);
+    if (!env) {
+        av_freep(&codec);
+        return NULL;
+    }
+
+    if (ff_jni_init_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec) < 0) {
+        goto fail;
+    }
+
+    mime_type = ff_jni_utf_chars_to_jstring(env, mime, codec);
+    if (!mime_type) {
+        goto fail;
+    }
+
+    codec->object = (*env)->CallStaticObjectMethod(env, codec->jfields.mediacodec_class, codec->jfields.create_encoder_by_type_id, mime_type);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        goto fail;
+    }
+
+    codec->object = (*env)->NewGlobalRef(env, codec->object);
+    if (!codec->object) {
+        goto fail;
+    }
+
+    if (codec_init_static_fields(codec) < 0) {
+        goto fail;
+    }
+
+    if (codec->jfields.get_input_buffer_id && codec->jfields.get_output_buffer_id) {
+        codec->has_get_i_o_buffer = 1;
+    }
+
+    JNI_DETACH_ENV(attached, NULL);
+
+    return codec;
+fail:
+    ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
+
+    if (mime_type) {
+        (*env)->DeleteLocalRef(env, mime_type);
+    }
+
+    JNI_DETACH_ENV(attached, codec);
+
+    av_freep(&codec);
+
+    return NULL;
+}
+
+int ff_AMediaCodec_delete(FFAMediaCodec* codec)
+{
+    int ret = 0;
+
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    if (!codec) {
+        return 0;
+    }
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+    }
+
+    (*env)->DeleteGlobalRef(env, codec->object);
+    codec->object = NULL;
+
+    ff_jni_reset_jfields(env, &codec->jfields, jni_amediacodec_mapping, 1, codec);
+
+    JNI_DETACH_ENV(attached, codec);
+
+    av_freep(&codec);
+
+    return ret;
+}
+
+char *ff_AMediaCodec_getName(FFAMediaCodec *codec)
+{
+    char *ret = NULL;
+    int attached = 0;
+    JNIEnv *env = NULL;
+    jobject *name = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
+
+    name = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_name_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        goto fail;
+    }
+
+    ret = ff_jni_jstring_to_utf_chars(env, name, codec);
+
+fail:
+    JNI_DETACH_ENV(attached, NULL);
+
+    return ret;
+}
+
+int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    /* TODO: implement surface handling */
+    av_assert0(surface == NULL);
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.configure_id, format->object, NULL, NULL, flags);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+fail:
+    JNI_DETACH_ENV(attached, NULL);
+
+    return ret;
+}
+
+int ff_AMediaCodec_start(FFAMediaCodec* codec)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.start_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+fail:
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+int ff_AMediaCodec_stop(FFAMediaCodec* codec)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.stop_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+fail:
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+int ff_AMediaCodec_flush(FFAMediaCodec* codec)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.flush_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+fail:
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_id, idx, render);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+fail:
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.release_output_buffer_at_time_id, idx, timestampNs);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+fail:
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_input_buffer_id, timeoutUs);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+fail:
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    (*env)->CallVoidMethod(env, codec->object, codec->jfields.queue_input_buffer_id, idx, offset, size, time, flags);
+    if ((ret = ff_jni_exception_check(env, 1, codec)) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+fail:
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+ssize_t ff_AMediaCodec_dequeueOutputBuffer(FFAMediaCodec* codec, FFAMediaCodecBufferInfo *info, int64_t timeoutUs)
+{
+    int ret = 0;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    jobject mediainfo = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, AVERROR_EXTERNAL);
+
+    mediainfo = (*env)->NewObject(env, codec->jfields.mediainfo_class, codec->jfields.init_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    ret = (*env)->CallIntMethod(env, codec->object, codec->jfields.dequeue_output_buffer_id, mediainfo, timeoutUs);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    info->flags = (*env)->GetIntField(env, mediainfo, codec->jfields.flags_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    info->offset = (*env)->GetIntField(env, mediainfo, codec->jfields.offset_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    info->presentationTimeUs = (*env)->GetLongField(env, mediainfo, codec->jfields.presentation_time_us_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    info->size = (*env)->GetIntField(env, mediainfo, codec->jfields.size_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+fail:
+    if (mediainfo) {
+        (*env)->DeleteLocalRef(env, mediainfo);
+    }
+
+    JNI_DETACH_ENV(attached, NULL);
+
+    return ret;
+}
+
+uint8_t* ff_AMediaCodec_getInputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size)
+{
+    uint8_t *ret = NULL;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    jobject buffer = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
+
+    if (codec->has_get_i_o_buffer) {
+        buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffer_id, idx);
+        if (ff_jni_exception_check(env, 1, codec) < 0) {
+            goto fail;
+        }
+    } else {
+        if (!codec->input_buffers) {
+            codec->input_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_input_buffers_id);
+            if (ff_jni_exception_check(env, 1, codec) < 0) {
+                goto fail;
+            }
+
+            codec->input_buffers = (*env)->NewGlobalRef(env, codec->input_buffers);
+            if (ff_jni_exception_check(env, 1, codec) < 0) {
+                goto fail;
+            }
+        }
+
+        buffer = (*env)->GetObjectArrayElement(env, codec->input_buffers, idx);
+        if (ff_jni_exception_check(env, 1, codec) < 0) {
+            goto fail;
+        }
+    }
+
+    ret = (*env)->GetDirectBufferAddress(env, buffer);
+    *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
+fail:
+    if (buffer) {
+        (*env)->DeleteLocalRef(env, buffer);
+    }
+
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+uint8_t* ff_AMediaCodec_getOutputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size)
+{
+    uint8_t *ret = NULL;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    jobject buffer = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
+
+    if (codec->has_get_i_o_buffer) {
+        buffer = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffer_id, idx);
+        if (ff_jni_exception_check(env, 1, codec) < 0) {
+            goto fail;
+        }
+    } else {
+        if (!codec->output_buffers) {
+            codec->output_buffers = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_buffers_id);
+            if (ff_jni_exception_check(env, 1, codec) < 0) {
+                goto fail;
+            }
+
+            codec->output_buffers = (*env)->NewGlobalRef(env, codec->output_buffers);
+            if (ff_jni_exception_check(env, 1, codec) < 0) {
+                goto fail;
+            }
+        }
+
+        buffer = (*env)->GetObjectArrayElement(env, codec->output_buffers, idx);
+        if (ff_jni_exception_check(env, 1, codec) < 0) {
+            goto fail;
+        }
+    }
+
+    ret = (*env)->GetDirectBufferAddress(env, buffer);
+    *out_size = (*env)->GetDirectBufferCapacity(env, buffer);
+fail:
+    if (buffer) {
+        (*env)->DeleteLocalRef(env, buffer);
+    }
+
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+FFAMediaFormat* ff_AMediaCodec_getOutputFormat(FFAMediaCodec* codec)
+{
+    FFAMediaFormat *ret = NULL;
+    int attached = 0;
+    JNIEnv *env = NULL;
+
+    jobject mediaformat = NULL;
+
+    JNI_ATTACH_ENV_OR_RETURN(env, &attached, codec, NULL);
+
+    mediaformat = (*env)->CallObjectMethod(env, codec->object, codec->jfields.get_output_format_id);
+    if (ff_jni_exception_check(env, 1, codec) < 0) {
+        goto fail;
+    }
+
+    ret = ff_AMediaFormat_newFromObject(mediaformat);
+fail:
+    if (mediaformat) {
+        (*env)->DeleteLocalRef(env, mediaformat);
+    }
+
+    JNI_DETACH_ENV(attached, codec);
+
+    return ret;
+}
+
+int ff_AMediaCodec_infoTryAgainLater(FFAMediaCodec *codec, ssize_t idx)
+{
+    return idx == codec->INFO_TRY_AGAIN_LATER;
+}
+
+int ff_AMediaCodec_infoOutputBuffersChanged(FFAMediaCodec *codec, ssize_t idx)
+{
+    return idx == codec->INFO_OUTPUT_BUFFERS_CHANGED;
+}
+
+int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec *codec, ssize_t idx)
+{
+    return idx == codec->INFO_OUTPUT_FORMAT_CHANGED;
+}
+
+int ff_AMediaCodec_getBufferFlagCodecConfig(FFAMediaCodec *codec)
+{
+    return codec->BUFFER_FLAG_CODEC_CONFIG;
+}
+
+int ff_AMediaCodec_getBufferFlagEndOfStream(FFAMediaCodec *codec)
+{
+    return codec->BUFFER_FLAG_END_OF_STREAM;
+}
+
+int ff_AMediaCodec_getBufferFlagKeyFrame(FFAMediaCodec *codec)
+{
+    return codec->BUFFER_FLAG_KEY_FRAME;
+}
+
+int ff_AMediaCodec_getConfigureFlagEncode(FFAMediaCodec *codec)
+{
+    return codec->CONFIGURE_FLAG_ENCODE;
+}
+
+int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec)
+{
+    int ret = 0;
+
+    if (!codec->has_get_i_o_buffer) {
+        if (codec->output_buffers) {
+            int attached = 0;
+            JNIEnv *env = NULL;
+
+            env = ff_jni_attach_env(&attached, codec);
+            if (!env) {
+                ret = AVERROR_EXTERNAL;
+                goto fail;
+            }
+
+            (*env)->DeleteGlobalRef(env, codec->output_buffers);
+            codec->output_buffers = NULL;
+
+            JNI_DETACH_ENV(attached, codec);
+        }
+    }
+
+fail:
+    return ret;
+}
diff --git a/libavcodec/mediacodec_wrapper.h b/libavcodec/mediacodec_wrapper.h
new file mode 100644
index 0000000..cddd420
--- /dev/null
+++ b/libavcodec/mediacodec_wrapper.h
@@ -0,0 +1,127 @@
+/*
+ * Android MediaCodec Wrapper
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_MEDIACODEC_WRAPPER_H
+#define AVCODEC_MEDIACODEC_WRAPPER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+/**
+ * The following API around MediaCodec and MediaFormat is based on the
+ * NDK one provided by Google since Android 5.0.
+ *
+ * Differences from the NDK API:
+ *
+ * Buffers returned by ff_AMediaFormat_toString and ff_AMediaFormat_getString
+ * are newly allocated buffer and must be freed by the user after use.
+ *
+ * The MediaCrypto API is not implemented.
+ *
+ * ff_AMediaCodec_infoTryAgainLater, ff_AMediaCodec_infoOutputBuffersChanged,
+ * ff_AMediaCodec_infoOutputFormatChanged, ff_AMediaCodec_cleanOutputBuffers
+ * ff_AMediaCodec_getName and ff_AMediaCodec_getBufferFlagEndOfStream are not
+ * part of the original NDK API and are convenience functions to hide JNI
+ * implementation.
+ *
+ * The API around MediaCodecList is not part of the NDK (and is lacking as
+ * we still need to retreive the codec name to work around faulty decoders
+ * and encoders).
+ *
+ * For documentation, please refers to NdkMediaCodec.h NdkMediaFormat.h and
+ * http://developer.android.com/reference/android/media/MediaCodec.html.
+ *
+ */
+
+int ff_AMediaCodecProfile_getProfileFromAVCodecContext(AVCodecContext *avctx);
+
+char *ff_AMediaCodecList_getCodecNameByType(const char *mime, int profile, int encoder, void *log_ctx);
+
+struct FFAMediaFormat;
+typedef struct FFAMediaFormat FFAMediaFormat;
+
+FFAMediaFormat *ff_AMediaFormat_new(void);
+int ff_AMediaFormat_delete(FFAMediaFormat* format);
+
+char* ff_AMediaFormat_toString(FFAMediaFormat* format);
+
+int ff_AMediaFormat_getInt32(FFAMediaFormat* format, const char *name, int32_t *out);
+int ff_AMediaFormat_getInt64(FFAMediaFormat* format, const char *name, int64_t *out);
+int ff_AMediaFormat_getFloat(FFAMediaFormat* format, const char *name, float *out);
+int ff_AMediaFormat_getBuffer(FFAMediaFormat* format, const char *name, void** data, size_t *size);
+int ff_AMediaFormat_getString(FFAMediaFormat* format, const char *name, const char **out);
+
+void ff_AMediaFormat_setInt32(FFAMediaFormat* format, const char* name, int32_t value);
+void ff_AMediaFormat_setInt64(FFAMediaFormat* format, const char* name, int64_t value);
+void ff_AMediaFormat_setFloat(FFAMediaFormat* format, const char* name, float value);
+void ff_AMediaFormat_setString(FFAMediaFormat* format, const char* name, const char* value);
+void ff_AMediaFormat_setBuffer(FFAMediaFormat* format, const char* name, void* data, size_t size);
+
+struct FFAMediaCodec;
+typedef struct FFAMediaCodec FFAMediaCodec;
+typedef struct FFAMediaCodecCryptoInfo FFAMediaCodecCryptoInfo;
+
+struct FFAMediaCodecBufferInfo {
+    int32_t offset;
+    int32_t size;
+    int64_t presentationTimeUs;
+    uint32_t flags;
+};
+typedef struct FFAMediaCodecBufferInfo FFAMediaCodecBufferInfo;
+
+char *ff_AMediaCodec_getName(FFAMediaCodec *codec);
+
+FFAMediaCodec* ff_AMediaCodec_createCodecByName(const char *name);
+FFAMediaCodec* ff_AMediaCodec_createDecoderByType(const char *mime_type);
+FFAMediaCodec* ff_AMediaCodec_createEncoderByType(const char *mime_type);
+
+int ff_AMediaCodec_configure(FFAMediaCodec* codec, const FFAMediaFormat* format, void* surface, void *crypto, uint32_t flags);
+int ff_AMediaCodec_start(FFAMediaCodec* codec);
+int ff_AMediaCodec_stop(FFAMediaCodec* codec);
+int ff_AMediaCodec_flush(FFAMediaCodec* codec);
+int ff_AMediaCodec_delete(FFAMediaCodec* codec);
+
+uint8_t* ff_AMediaCodec_getInputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size);
+uint8_t* ff_AMediaCodec_getOutputBuffer(FFAMediaCodec* codec, size_t idx, size_t *out_size);
+
+ssize_t ff_AMediaCodec_dequeueInputBuffer(FFAMediaCodec* codec, int64_t timeoutUs);
+int ff_AMediaCodec_queueInputBuffer(FFAMediaCodec* codec, size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags);
+
+ssize_t ff_AMediaCodec_dequeueOutputBuffer(FFAMediaCodec* codec, FFAMediaCodecBufferInfo *info, int64_t timeoutUs);
+FFAMediaFormat* ff_AMediaCodec_getOutputFormat(FFAMediaCodec* codec);
+
+int ff_AMediaCodec_releaseOutputBuffer(FFAMediaCodec* codec, size_t idx, int render);
+int ff_AMediaCodec_releaseOutputBufferAtTime(FFAMediaCodec *codec, size_t idx, int64_t timestampNs);
+
+int ff_AMediaCodec_infoTryAgainLater(FFAMediaCodec *codec, ssize_t idx);
+int ff_AMediaCodec_infoOutputBuffersChanged(FFAMediaCodec *codec, ssize_t idx);
+int ff_AMediaCodec_infoOutputFormatChanged(FFAMediaCodec *codec, ssize_t indx);
+
+int ff_AMediaCodec_getBufferFlagCodecConfig (FFAMediaCodec *codec);
+int ff_AMediaCodec_getBufferFlagEndOfStream(FFAMediaCodec *codec);
+int ff_AMediaCodec_getBufferFlagKeyFrame(FFAMediaCodec *codec);
+
+int ff_AMediaCodec_getConfigureFlagEncode(FFAMediaCodec *codec);
+
+int ff_AMediaCodec_cleanOutputBuffers(FFAMediaCodec *codec);
+
+#endif /* AVCODEC_MEDIACODEC_WRAPPER_H */
diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c
new file mode 100644
index 0000000..e29637e
--- /dev/null
+++ b/libavcodec/mediacodecdec.c
@@ -0,0 +1,580 @@
+/*
+ * Android MediaCodec decoder
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * 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 <string.h>
+#include <sys/types.h>
+
+#include "libavutil/common.h"
+#include "libavutil/mem.h"
+#include "libavutil/log.h"
+#include "libavutil/pixfmt.h"
+#include "libavutil/time.h"
+#include "libavutil/timestamp.h"
+
+#include "avcodec.h"
+#include "internal.h"
+
+#include "mediacodec_sw_buffer.h"
+#include "mediacodec_wrapper.h"
+#include "mediacodecdec.h"
+
+/**
+ * OMX.k3.video.decoder.avc, OMX.NVIDIA.* OMX.SEC.avc.dec and OMX.google
+ * codec workarounds used in various place are taken from the Gstreamer
+ * project.
+ *
+ * Gstreamer references:
+ * https://cgit.freedesktop.org/gstreamer/gst-plugins-bad/tree/sys/androidmedia/
+ *
+ * Gstreamer copyright notice:
+ *
+ * Copyright (C) 2012, Collabora Ltd.
+ *   Author: Sebastian Dröge <sebastian.droege at collabora.co.uk>
+ *
+ * Copyright (C) 2012, Rafaël Carré <funman at videolanorg>
+ *
+ * Copyright (C) 2015, Sebastian Dröge <sebastian at centricular.com>
+ *
+ * Copyright (C) 2014-2015, Collabora Ltd.
+ *   Author: Matthieu Bouron <matthieu.bouron at gcollabora.com>
+ *
+ * Copyright (C) 2015, Edward Hervey
+ *   Author: Edward Hervey <bilboed at gmail.com>
+ *
+ * Copyright (C) 2015, Matthew Waters <matthew at centricular.com>
+ *
+ * This library 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
+ * version 2.1 of the License.
+ *
+ * This library 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#define INPUT_DEQUEUE_TIMEOUT_US 8000
+#define OUTPUT_DEQUEUE_TIMEOUT_US 8000
+#define OUTPUT_DEQUEUE_BLOCK_TIMEOUT_US 1000000
+
+enum {
+    COLOR_FormatYUV420Planar                              = 0x13,
+    COLOR_FormatYUV420SemiPlanar                          = 0x15,
+    COLOR_FormatYCbYCr                                    = 0x19,
+    COLOR_FormatAndroidOpaque                             = 0x7F000789,
+    COLOR_QCOM_FormatYUV420SemiPlanar                     = 0x7fa30c00,
+    COLOR_QCOM_FormatYUV420SemiPlanar32m                  = 0x7fa30c04,
+    COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7fa30c03,
+    COLOR_TI_FormatYUV420PackedSemiPlanar                 = 0x7f000100,
+    COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced       = 0x7f000001,
+};
+
+static const struct {
+
+    int color_format;
+    enum AVPixelFormat pix_fmt;
+
+} color_formats[] = {
+
+    { COLOR_FormatYUV420Planar,                              AV_PIX_FMT_YUV420P },
+    { COLOR_FormatYUV420SemiPlanar,                          AV_PIX_FMT_NV12    },
+    { COLOR_QCOM_FormatYUV420SemiPlanar,                     AV_PIX_FMT_NV12    },
+    { COLOR_QCOM_FormatYUV420SemiPlanar32m,                  AV_PIX_FMT_NV12    },
+    { COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, AV_PIX_FMT_NV12    },
+    { COLOR_TI_FormatYUV420PackedSemiPlanar,                 AV_PIX_FMT_NV12    },
+    { COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced,       AV_PIX_FMT_NV12    },
+    { 0 }
+};
+
+static enum AVPixelFormat mcdec_map_color_format(AVCodecContext *avctx,
+                                                 MediaCodecDecContext *s,
+                                                 int color_format)
+{
+    int i;
+    enum AVPixelFormat ret = AV_PIX_FMT_NONE;
+
+    if (!strcmp(s->codec_name, "OMX.k3.video.decoder.avc") && color_format == COLOR_FormatYCbYCr) {
+        s->color_format = color_format = COLOR_TI_FormatYUV420PackedSemiPlanar;
+    }
+
+    for (i = 0; i < FF_ARRAY_ELEMS(color_formats); i++) {
+        if (color_formats[i].color_format == color_format) {
+            return color_formats[i].pix_fmt;
+        }
+    }
+
+    av_log(avctx, AV_LOG_ERROR, "Output color format 0x%x (value=%d) is not supported\n",
+        color_format, color_format);
+
+    return ret;
+}
+
+static int mediacodec_wrap_buffer(AVCodecContext *avctx,
+                                  MediaCodecDecContext *s,
+                                  uint8_t *data,
+                                  size_t size,
+                                  ssize_t index,
+                                  FFAMediaCodecBufferInfo *info,
+                                  AVFrame *frame)
+{
+    int ret = 0;
+    int status = 0;
+
+    frame->width = avctx->width;
+    frame->height = avctx->height;
+    frame->format = avctx->pix_fmt;
+
+    /* MediaCodec buffers needs to be copied to our own refcounted buffers
+     * because the flush command invalidates all input and output buffers.
+     */
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer\n");
+        goto done;
+    }
+
+    /* Override frame->pkt_pts as ff_get_buffer will override its value based
+     * on the last avpacket received which is not in sync with the frame:
+     *   * N avpackets can be pushed before 1 frame is actually returned
+     *   * 0-sized avpackets are pushed to flush remaining frames at EOS */
+    frame->pkt_pts = info->presentationTimeUs;
+    frame->pkt_dts = AV_NOPTS_VALUE;
+
+    av_log(avctx, AV_LOG_DEBUG,
+            "Frame: width=%d stride=%d height=%d slice-height=%d "
+            "crop-top=%d crop-bottom=%d crop-left=%d crop-right=%d encoder=%s\n"
+            "destination linesizes=%d,%d,%d\n" ,
+            avctx->width, s->stride, avctx->height, s->slice_height,
+            s->crop_top, s->crop_bottom, s->crop_left, s->crop_right, s->codec_name,
+            frame->linesize[0], frame->linesize[1], frame->linesize[2]);
+
+    switch (s->color_format) {
+    case COLOR_FormatYUV420Planar:
+        ff_mediacodec_sw_buffer_copy_yuv420_planar(avctx, s, data, size, info, frame);
+        break;
+    case COLOR_FormatYUV420SemiPlanar:
+    case COLOR_QCOM_FormatYUV420SemiPlanar:
+    case COLOR_QCOM_FormatYUV420SemiPlanar32m:
+        ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(avctx, s, data, size, info, frame);
+        break;
+    case COLOR_TI_FormatYUV420PackedSemiPlanar:
+    case COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced:
+        ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(avctx, s, data, size, info, frame);
+        break;
+    case COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka:
+        ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(avctx, s, data, size, info, frame);
+        break;
+    default:
+        av_log(avctx, AV_LOG_ERROR, "Unsupported color format 0x%x (value=%d)\n",
+            s->color_format, s->color_format);
+        ret = AVERROR(EINVAL);
+        goto done;
+    }
+
+    ret = 0;
+done:
+    status = ff_AMediaCodec_releaseOutputBuffer(s->codec, index, 0);
+    if (status < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to release output buffer\n");
+        ret = AVERROR_EXTERNAL;
+    }
+
+    return ret;
+}
+
+static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecContext *s)
+{
+    int width = 0;
+    int height = 0;
+    int32_t value = 0;
+    char *format = NULL;
+
+    if (!s->format) {
+        av_log(avctx, AV_LOG_ERROR, "Output MediaFormat is not set\n");
+        return AVERROR(EINVAL);
+    }
+
+    format = ff_AMediaFormat_toString(s->format);
+    if (!format) {
+        return AVERROR_EXTERNAL;
+    }
+    av_log(avctx, AV_LOG_DEBUG, "Parsing MediaFormat %s\n", format);
+    av_freep(&format);
+
+    /* Mandatory fields */
+    if (!ff_AMediaFormat_getInt32(s->format, "width", &value)) {
+        format = ff_AMediaFormat_toString(s->format);
+        av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "width", format);
+        av_freep(&format);
+        return AVERROR_EXTERNAL;
+    }
+    s->width = value;
+
+    if (!ff_AMediaFormat_getInt32(s->format, "height", &value)) {
+        format = ff_AMediaFormat_toString(s->format);
+        av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "height", format);
+        av_freep(&format);
+        return AVERROR_EXTERNAL;
+    }
+    s->height = value;
+
+    if (!ff_AMediaFormat_getInt32(s->format, "stride", &value)) {
+        format = ff_AMediaFormat_toString(s->format);
+        av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "stride", format);
+        av_freep(&format);
+        return AVERROR_EXTERNAL;
+    }
+    s->stride = value > 0 ? value : s->width;
+
+    if (!ff_AMediaFormat_getInt32(s->format, "slice-height", &value)) {
+        format = ff_AMediaFormat_toString(s->format);
+        av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "slice-height", format);
+        av_freep(&format);
+        return AVERROR_EXTERNAL;
+    }
+    s->slice_height = value > 0 ? value : s->height;
+
+    if (strstr(s->codec_name, "OMX.Nvidia.")) {
+        s->slice_height = FFALIGN(s->height, 16);
+    } else if (strstr(s->codec_name, "OMX.SEC.avc.dec")) {
+        s->slice_height = avctx->height;
+        s->stride = avctx->width;
+    }
+
+    if (!ff_AMediaFormat_getInt32(s->format, "color-format", &value)) {
+        format = ff_AMediaFormat_toString(s->format);
+        av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "color-format", format);
+        av_freep(&format);
+        return AVERROR_EXTERNAL;
+    }
+    s->color_format = value;
+
+    s->pix_fmt = avctx->pix_fmt = mcdec_map_color_format(avctx, s, value);
+    if (avctx->pix_fmt == AV_PIX_FMT_NONE) {
+        av_log(avctx, AV_LOG_ERROR, "Output color format is not supported\n");
+        return AVERROR(EINVAL);
+    }
+
+    /* Optional fields */
+    if (ff_AMediaFormat_getInt32(s->format, "crop-top", &value))
+        s->crop_top = value;
+
+    if (ff_AMediaFormat_getInt32(s->format, "crop-bottom", &value))
+        s->crop_bottom = value;
+
+    if (ff_AMediaFormat_getInt32(s->format, "crop-left", &value))
+        s->crop_left = value;
+
+    if (ff_AMediaFormat_getInt32(s->format, "crop-right", &value))
+        s->crop_right = value;
+
+    width = s->crop_right + 1 - s->crop_left;
+    height = s->crop_bottom + 1 - s->crop_top;
+
+    av_log(avctx, AV_LOG_INFO,
+        "Output crop parameters top=%d bottom=%d left=%d right=%d, "
+        "resulting dimensions width=%d height=%d\n",
+        s->crop_top, s->crop_bottom, s->crop_left, s->crop_right,
+        width, height);
+
+    return ff_set_dimensions(avctx, width, height);
+}
+
+int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s,
+                           const char *mime, FFAMediaFormat *format)
+{
+    int ret = 0;
+    int status;
+    int profile;
+
+    s->first_buffer_at = av_gettime();
+
+    profile = ff_AMediaCodecProfile_getProfileFromAVCodecContext(avctx);
+    if (profile < 0) {
+        av_log(avctx, AV_LOG_WARNING, "Unsupported or unknown profile");
+    }
+
+    s->codec_name = ff_AMediaCodecList_getCodecNameByType(mime, profile, 0, avctx);
+    if (!s->codec_name) {
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "Found decoder %s\n", s->codec_name);
+    s->codec = ff_AMediaCodec_createCodecByName(s->codec_name);
+    if (!s->codec) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to create media decoder for type %s and name %s\n", mime, s->codec_name);
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    status = ff_AMediaCodec_configure(s->codec, format, NULL, NULL, 0);
+    if (status < 0) {
+        char *desc = ff_AMediaFormat_toString(format);
+        av_log(avctx, AV_LOG_ERROR,
+            "Failed to configure codec (status = %d) with format %s\n",
+            status, desc);
+        av_freep(&desc);
+
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    status = ff_AMediaCodec_start(s->codec);
+    if (status < 0) {
+        char *desc = ff_AMediaFormat_toString(format);
+        av_log(avctx, AV_LOG_ERROR,
+            "Failed to start codec (status = %d) with format %s\n",
+            status, desc);
+        av_freep(&desc);
+        ret = AVERROR_EXTERNAL;
+        goto fail;
+    }
+
+    s->format = ff_AMediaCodec_getOutputFormat(s->codec);
+    if (s->format) {
+        if ((ret = mediacodec_dec_parse_format(avctx, s)) < 0) {
+            av_log(avctx, AV_LOG_ERROR,
+                "Failed to configure context\n");
+            goto fail;
+        }
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "MediaCodec %p started successfully\n", s->codec);
+
+    return 0;
+
+fail:
+    av_log(avctx, AV_LOG_ERROR, "MediaCodec %p failed to start\n", s->codec);
+    ff_mediacodec_dec_close(avctx, s);
+    return ret;
+}
+
+int ff_mediacodec_dec_decode(AVCodecContext *avctx, MediaCodecDecContext *s,
+                             AVFrame *frame, int *got_frame,
+                             AVPacket *pkt)
+{
+    int ret;
+    int offset = 0;
+    int need_flushing = 0;
+    uint8_t *data;
+    ssize_t index;
+    size_t size;
+    FFAMediaCodec *codec = s->codec;
+    FFAMediaCodecBufferInfo info = { 0 };
+
+    int status;
+
+    int64_t input_dequeue_timeout_us = INPUT_DEQUEUE_TIMEOUT_US;
+    int64_t output_dequeue_timeout_us = OUTPUT_DEQUEUE_TIMEOUT_US;
+
+    if (pkt->size == 0) {
+        need_flushing = 1;
+    }
+
+    if (s->flushing && s->eos) {
+        return 0;
+    }
+
+    while (offset < pkt->size || (need_flushing && !s->flushing)) {
+        int size;
+
+        index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us);
+        if (ff_AMediaCodec_infoTryAgainLater(codec, index)) {
+            break;
+        }
+
+        if (index < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to dequeue input buffer (status=%zd)\n", index);
+            return AVERROR_EXTERNAL;
+        }
+
+        data = ff_AMediaCodec_getInputBuffer(codec, index, &size);
+        if (!data) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to get input buffer\n");
+            return AVERROR_EXTERNAL;
+        }
+
+        if (need_flushing) {
+            uint32_t flags = ff_AMediaCodec_getBufferFlagEndOfStream(codec);
+
+            av_log(avctx, AV_LOG_DEBUG, "Sending End Of Stream signal\n");
+
+            status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, 0, pkt->pts, flags);
+            if (status < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to queue input empty buffer (status = %d)\n", status);
+                return AVERROR_EXTERNAL;
+            }
+
+            s->flushing = 1;
+            break;
+        } else {
+            size = FFMIN(pkt->size - offset, size);
+
+            memcpy(data, pkt->data + offset, size);
+            offset += size;
+
+            status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, size, pkt->pts, 0);
+            if (status < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to queue input buffer (status = %d)\n", status);
+                return AVERROR_EXTERNAL;
+            }
+        }
+    }
+
+    if (need_flushing || s->flushing) {
+        /* If the codec is flushing or need to be flushed, block for a fair
+         * amount of time to ensure we got a frame */
+        output_dequeue_timeout_us = OUTPUT_DEQUEUE_BLOCK_TIMEOUT_US;
+    } else if (s->dequeued_buffer_nb == 0) {
+        /* If the codec hasn't produced any frames, do not block so we
+         * can push data to it as fast as possible, and get the first
+         * frame */
+        output_dequeue_timeout_us = 0;
+    }
+
+    index = ff_AMediaCodec_dequeueOutputBuffer(codec, &info, output_dequeue_timeout_us);
+    if (index >= 0) {
+        int ret;
+
+        if (!s->first_buffer++) {
+            av_log(avctx, AV_LOG_DEBUG, "Got first buffer after %fms\n", (av_gettime() - s->first_buffer_at) / 1000);
+        }
+
+        av_log(avctx, AV_LOG_DEBUG, "Got output buffer %zd"
+                " offset=%" PRIi32 " size=%" PRIi32 " ts=%" PRIi64
+                " flags=%" PRIu32 "\n", index, info.offset, info.size,
+                info.presentationTimeUs, info.flags);
+
+        if (info.flags & ff_AMediaCodec_getBufferFlagEndOfStream(codec)) {
+            s->eos = 1;
+        }
+
+        if (info.size) {
+            data = ff_AMediaCodec_getOutputBuffer(codec, index, &size);
+            if (!data) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to get output buffer\n");
+                return AVERROR_EXTERNAL;
+            }
+
+            if ((ret = mediacodec_wrap_buffer(avctx, s, data, size, index, &info, frame)) < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to wrap MediaCodec buffer\n");
+                return ret;
+            }
+
+            *got_frame = 1;
+            s->dequeued_buffer_nb++;
+        } else {
+            status = ff_AMediaCodec_releaseOutputBuffer(codec, index, 0);
+            if (status < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to release output buffer\n");
+            }
+        }
+
+    } else if (ff_AMediaCodec_infoOutputFormatChanged(codec, index)) {
+        char *format = NULL;
+
+        if (s->format) {
+            status = ff_AMediaFormat_delete(s->format);
+            if (status < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to delete MediaFormat %p\n", s->format);
+            }
+        }
+
+        s->format = ff_AMediaCodec_getOutputFormat(codec);
+        if (!s->format) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to get output format\n");
+            return AVERROR_EXTERNAL;
+        }
+
+        format = ff_AMediaFormat_toString(s->format);
+        if (!format) {
+            return AVERROR_EXTERNAL;
+        }
+        av_log(avctx, AV_LOG_INFO, "Output MediaFormat changed to %s\n", format);
+        av_freep(&format);
+
+        if ((ret = mediacodec_dec_parse_format(avctx, s)) < 0) {
+            return ret;
+        }
+
+    } else if (ff_AMediaCodec_infoOutputBuffersChanged(codec, index)) {
+        ff_AMediaCodec_cleanOutputBuffers(codec);
+    } else if (ff_AMediaCodec_infoTryAgainLater(codec, index)) {
+        if (s->flushing) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to dequeue output buffer within %" PRIi64 "ms "
+                                        "while flushing remaining frames, output will probably lack frames\n",
+                                        output_dequeue_timeout_us / 1000);
+        } else {
+            av_log(avctx, AV_LOG_DEBUG, "No output buffer available, try again later\n");
+        }
+    } else {
+        av_log(avctx, AV_LOG_ERROR, "Failed to dequeue output buffer (status=%zd)\n", index);
+        return AVERROR_EXTERNAL;
+    }
+
+    return offset;
+}
+
+int ff_mediacodec_dec_flush(AVCodecContext *avctx, MediaCodecDecContext *s)
+{
+    FFAMediaCodec *codec = s->codec;
+    int status;
+
+    s->dequeued_buffer_nb = 0;
+
+    s->flushing = 0;
+    s->eos = 0;
+
+    status = ff_AMediaCodec_flush(codec);
+    if (status < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to flush codec\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->first_buffer = 0;
+    s->first_buffer_at = av_gettime();
+
+    return 0;
+}
+
+int ff_mediacodec_dec_close(AVCodecContext *avctx, MediaCodecDecContext *s)
+{
+    if (s->codec) {
+        ff_AMediaCodec_delete(s->codec);
+        s->codec = NULL;
+    }
+
+    if (s->format) {
+        ff_AMediaFormat_delete(s->format);
+        s->format = NULL;
+    }
+
+    av_freep(&s->codec_name);
+
+    return 0;
+}
diff --git a/libavcodec/mediacodecdec.h b/libavcodec/mediacodecdec.h
new file mode 100644
index 0000000..646b628
--- /dev/null
+++ b/libavcodec/mediacodecdec.h
@@ -0,0 +1,81 @@
+/*
+ * Android MediaCodec decoder
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_MEDIACODECDEC_H
+#define AVCODEC_MEDIACODECDEC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "libavutil/frame.h"
+#include "libavutil/pixfmt.h"
+
+#include "avcodec.h"
+#include "mediacodec_wrapper.h"
+
+typedef struct MediaCodecDecContext {
+
+    char *codec_name;
+
+    FFAMediaCodec *codec;
+    FFAMediaFormat *format;
+
+    int started;
+    int flushing;
+    int eos;
+
+    int width;
+    int height;
+    int stride;
+    int slice_height;
+    int color_format;
+    enum AVPixelFormat pix_fmt;
+    int crop_top;
+    int crop_bottom;
+    int crop_left;
+    int crop_right;
+
+    uint64_t dequeued_buffer_nb;
+
+    int first_buffer;
+    double first_buffer_at;
+
+} MediaCodecDecContext;
+
+int ff_mediacodec_dec_init(AVCodecContext *avctx,
+                           MediaCodecDecContext *s,
+                           const char *mime,
+                           FFAMediaFormat *format);
+
+int ff_mediacodec_dec_decode(AVCodecContext *avctx,
+                             MediaCodecDecContext *s,
+                             AVFrame *frame,
+                             int *got_frame,
+                             AVPacket *pkt);
+
+int ff_mediacodec_dec_flush(AVCodecContext *avctx,
+                            MediaCodecDecContext *s);
+
+int ff_mediacodec_dec_close(AVCodecContext *avctx,
+                            MediaCodecDecContext *s);
+
+#endif /* AVCODEC_MEDIACODECDEC_H */
diff --git a/libavcodec/mediacodecdec_h264.c b/libavcodec/mediacodecdec_h264.c
new file mode 100644
index 0000000..0664e49
--- /dev/null
+++ b/libavcodec/mediacodecdec_h264.c
@@ -0,0 +1,289 @@
+/*
+ * Android MediaCodec H.264 decoder
+ *
+ * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/common.h"
+#include "libavutil/fifo.h"
+#include "libavutil/opt.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/pixfmt.h"
+#include "libavutil/atomic.h"
+
+#include "avcodec.h"
+#include "h264.h"
+#include "internal.h"
+#include "mediacodecdec.h"
+#include "mediacodec_wrapper.h"
+
+#define CODEC_MIME "video/avc"
+
+typedef struct MediaCodecH264DecContext {
+
+    MediaCodecDecContext ctx;
+
+    AVBSFContext *bsf;
+
+    AVFifoBuffer *fifo;
+
+    AVPacket filtered_pkt;
+
+} MediaCodecH264DecContext;
+
+static av_cold int mediacodec_decode_close(AVCodecContext *avctx)
+{
+    MediaCodecH264DecContext *s = avctx->priv_data;
+
+    ff_mediacodec_dec_close(avctx, &s->ctx);
+
+    av_fifo_free(s->fifo);
+
+    av_bsf_free(&s->bsf);
+    av_packet_unref(&s->filtered_pkt);
+
+    return 0;
+}
+
+static av_cold int mediacodec_decode_init(AVCodecContext *avctx)
+{
+    int i;
+    int ret;
+
+    H264ParamSets ps;
+    const PPS *pps = NULL;
+    const SPS *sps = NULL;
+    int is_avc = 0;
+    int nal_length_size = 0;
+
+    FFAMediaFormat *format = NULL;
+    MediaCodecH264DecContext *s = avctx->priv_data;
+
+    memset(&ps, 0, sizeof(ps));
+
+    format = ff_AMediaFormat_new();
+    if (!format) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to create media format\n");
+        ret = AVERROR_EXTERNAL;
+        goto done;
+    }
+
+    ff_AMediaFormat_setString(format, "mime", CODEC_MIME);
+    ff_AMediaFormat_setInt32(format, "width", avctx->width);
+    ff_AMediaFormat_setInt32(format, "height", avctx->height);
+
+    ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
+                                   &ps, &is_avc, &nal_length_size, 0, avctx);
+    if (ret < 0) {
+        goto done;
+    }
+
+    for (i = 0; i < MAX_PPS_COUNT; i++) {
+        if (ps.pps_list[i]) {
+            pps = (const PPS*)ps.pps_list[i]->data;
+            break;
+        }
+    }
+
+    if (pps) {
+        if (ps.sps_list[pps->sps_id]) {
+            sps = (const SPS*)ps.sps_list[pps->sps_id]->data;
+        }
+    }
+
+    if (pps && sps) {
+        static const uint8_t nal_headers[] = { 0x00, 0x00, 0x00, 0x01 };
+
+        uint8_t *data = NULL;
+        size_t data_size = sizeof(nal_headers) + FFMAX(sps->data_size, pps->data_size);
+
+        data = av_mallocz(data_size);
+        if (!data) {
+            ret = AVERROR(ENOMEM);
+            goto done;
+        }
+
+        memcpy(data, nal_headers, sizeof(nal_headers));
+        memcpy(data + sizeof(nal_headers), sps->data, sps->data_size);
+        ff_AMediaFormat_setBuffer(format, "csd-0", (void*)data, sizeof(nal_headers) + sps->data_size);
+
+        memcpy(data + sizeof(nal_headers), pps->data, pps->data_size);
+        ff_AMediaFormat_setBuffer(format, "csd-1", (void*)data, sizeof(nal_headers) + pps->data_size);
+
+        av_freep(&data);
+    } else {
+        av_log(avctx, AV_LOG_ERROR, "Could not extract PPS/SPS from extradata");
+        ret = AVERROR_INVALIDDATA;
+        goto done;
+    }
+
+    if ((ret = ff_mediacodec_dec_init(avctx, &s->ctx, CODEC_MIME, format)) < 0) {
+        goto done;
+    }
+
+    av_log(avctx, AV_LOG_INFO, "MediaCodec started successfully, ret = %d\n", ret);
+
+    s->fifo = av_fifo_alloc(sizeof(AVPacket));
+    if (!s->fifo) {
+        ret = AVERROR(ENOMEM);
+        goto done;
+    }
+
+    const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");
+    if(!bsf) {
+        ret = AVERROR_BSF_NOT_FOUND;
+        goto done;
+    }
+
+    if ((ret = av_bsf_alloc(bsf, &s->bsf))) {
+        goto done;
+    }
+
+    if (((ret = avcodec_parameters_from_context(s->bsf->par_in, avctx)) < 0) ||
+        ((ret = av_bsf_init(s->bsf)) < 0)) {
+          goto done;
+    }
+
+    av_init_packet(&s->filtered_pkt);
+
+done:
+    if (format) {
+        ff_AMediaFormat_delete(format);
+    }
+
+    if (ret < 0) {
+        mediacodec_decode_close(avctx);
+    }
+
+    ff_h264_ps_uninit(&ps);
+
+    return ret;
+}
+
+
+static int mediacodec_process_data(AVCodecContext *avctx, AVFrame *frame,
+                                   int *got_frame, AVPacket *pkt)
+{
+    MediaCodecH264DecContext *s = avctx->priv_data;
+
+    return ff_mediacodec_dec_decode(avctx, &s->ctx, frame, got_frame, pkt);
+}
+
+static int mediacodec_decode_frame(AVCodecContext *avctx, void *data,
+                                   int *got_frame, AVPacket *avpkt)
+{
+    MediaCodecH264DecContext *s = avctx->priv_data;
+    AVFrame *frame    = data;
+    int ret;
+
+    /* buffer the input packet */
+    if (avpkt->size) {
+        AVPacket input_pkt = { 0 };
+
+        if (av_fifo_space(s->fifo) < sizeof(input_pkt)) {
+            ret = av_fifo_realloc2(s->fifo,
+                                   av_fifo_size(s->fifo) + sizeof(input_pkt));
+            if (ret < 0)
+                return ret;
+        }
+
+        ret = av_packet_ref(&input_pkt, avpkt);
+        if (ret < 0)
+            return ret;
+        av_fifo_generic_write(s->fifo, &input_pkt, sizeof(input_pkt), NULL);
+    }
+
+    /* process buffered data */
+    while (!*got_frame) {
+        /* prepare the input data -- convert to Annex B if needed */
+        if (s->filtered_pkt.size <= 0) {
+            AVPacket input_pkt = { 0 };
+
+            av_packet_unref(&s->filtered_pkt);
+
+            /* no more data */
+            if (av_fifo_size(s->fifo) < sizeof(AVPacket)) {
+                return avpkt->size ? avpkt->size :
+                    ff_mediacodec_dec_decode(avctx, &s->ctx, frame, got_frame, avpkt);
+            }
+
+            av_fifo_generic_read(s->fifo, &input_pkt, sizeof(input_pkt), NULL);
+
+            ret = av_bsf_send_packet(s->bsf, &input_pkt);
+            if (ret < 0) {
+                return ret;
+            }
+
+            ret = av_bsf_receive_packet(s->bsf, &s->filtered_pkt);
+            if (ret == AVERROR(EAGAIN)) {
+                goto done;
+            }
+
+            /* h264_mp4toannexb is used here and does not requires flushing */
+            av_assert0(ret != AVERROR_EOF);
+
+            if (ret < 0) {
+                return ret;
+            }
+        }
+
+        ret = mediacodec_process_data(avctx, frame, got_frame, &s->filtered_pkt);
+        if (ret < 0)
+            return ret;
+
+        s->filtered_pkt.size -= ret;
+        s->filtered_pkt.data += ret;
+    }
+done:
+    return avpkt->size;
+}
+
+static void mediacodec_decode_flush(AVCodecContext *avctx)
+{
+    MediaCodecH264DecContext *s = avctx->priv_data;
+
+    while (av_fifo_size(s->fifo)) {
+        AVPacket pkt;
+        av_fifo_generic_read(s->fifo, &pkt, sizeof(pkt), NULL);
+        av_packet_unref(&pkt);
+    }
+    av_fifo_reset(s->fifo);
+
+    av_packet_unref(&s->filtered_pkt);
+
+    ff_mediacodec_dec_flush(avctx, &s->ctx);
+}
+
+AVCodec ff_h264_mediacodec_decoder = {
+    .name           = "h264_mediacodec",
+    .long_name      = NULL_IF_CONFIG_SMALL("H.264 Android MediaCodec decoder"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .priv_data_size = sizeof(MediaCodecH264DecContext),
+    .init           = mediacodec_decode_init,
+    .decode         = mediacodec_decode_frame,
+    .flush          = mediacodec_decode_flush,
+    .close          = mediacodec_decode_close,
+    .capabilities   = CODEC_CAP_DELAY,
+    .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS,
+};
diff --git a/libavcodec/microdvddec.c b/libavcodec/microdvddec.c
index 46d6d14..e8d2719 100644
--- a/libavcodec/microdvddec.c
+++ b/libavcodec/microdvddec.c
@@ -280,6 +280,7 @@ static int microdvd_decode_frame(AVCodecContext *avctx,
     AVBPrint new_line;
     char *line = avpkt->data;
     char *end = avpkt->data + avpkt->size;
+    FFASSDecoderContext *s = avctx->priv_data;
     struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}};
 
     if (avpkt->size <= 0)
@@ -308,14 +309,7 @@ static int microdvd_decode_frame(AVCodecContext *avctx,
         }
     }
     if (new_line.len) {
-        int ret;
-            int64_t start    = avpkt->pts;
-            int64_t duration = avpkt->duration;
-            int ts_start     = av_rescale_q(start,    avctx->time_base, (AVRational){1,100});
-            int ts_duration  = duration != -1 ?
-                av_rescale_q(duration, avctx->time_base, (AVRational){1,100}) : -1;
-
-        ret = ff_ass_add_rect_bprint(sub, &new_line, ts_start, ts_duration);
+        int ret = ff_ass_add_rect(sub, new_line.str, s->readorder++, 0, NULL, NULL);
         av_bprint_finalize(&new_line, NULL);
         if (ret < 0)
             return ret;
@@ -381,4 +375,6 @@ AVCodec ff_microdvd_decoder = {
     .id           = AV_CODEC_ID_MICRODVD,
     .init         = microdvd_init,
     .decode       = microdvd_decode_frame,
+    .flush        = ff_ass_decoder_flush,
+    .priv_data_size = sizeof(FFASSDecoderContext),
 };
diff --git a/libavcodec/mips/Makefile b/libavcodec/mips/Makefile
index f66017a..3c43600 100644
--- a/libavcodec/mips/Makefile
+++ b/libavcodec/mips/Makefile
@@ -77,3 +77,4 @@ MMI-OBJS-$(CONFIG_MPEG4_DECODER)          += mips/xvid_idct_mmi.o
 MMI-OBJS-$(CONFIG_BLOCKDSP)               += mips/blockdsp_mmi.o
 MMI-OBJS-$(CONFIG_PIXBLOCKDSP)            += mips/pixblockdsp_mmi.o
 MMI-OBJS-$(CONFIG_H264QPEL)               += mips/h264qpel_mmi.o
+MMI-OBJS-$(CONFIG_HPELDSP)                += mips/hpeldsp_mmi.o
diff --git a/libavcodec/mips/blockdsp_mmi.c b/libavcodec/mips/blockdsp_mmi.c
index 63eaf69..6eb2bd7 100644
--- a/libavcodec/mips/blockdsp_mmi.c
+++ b/libavcodec/mips/blockdsp_mmi.c
@@ -22,126 +22,137 @@
  */
 
 #include "blockdsp_mips.h"
+#include "libavutil/mips/asmdefs.h"
 
 void ff_fill_block16_mmi(uint8_t *block, uint8_t value, int line_size, int h)
 {
+    double ftmp[1];
+
     __asm__ volatile (
-        "move $8, %3                \r\n"
-        "move $9, %0                \r\n"
-        "dmtc1 %1, $f2              \r\n"
-        "punpcklbh $f2, $f2, $f2    \r\n"
-        "punpcklbh $f2, $f2, $f2    \r\n"
-        "punpcklbh $f2, $f2, $f2    \r\n"
-        "1:                         \r\n"
-        "gssdlc1 $f2, 7($9)         \r\n"
-        "gssdrc1 $f2, 0($9)         \r\n"
-        "gssdlc1 $f2, 15($9)        \r\n"
-        "gssdrc1 $f2, 8($9)         \r\n"
-        "daddi $8, $8, -1           \r\n"
-        "daddu $9, $9, %2           \r\n"
-        "bnez $8, 1b                \r\n"
-        ::"r"(block),"r"(value),"r"(line_size),"r"(h)
-        : "$8","$9"
+        "mtc1       %[value],   %[ftmp0]                                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "1:                                                             \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[block])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[block])                          \n\t"
+        PTR_ADDI    "%[h],      %[h],           -0x01                   \n\t"
+        "gssdlc1    %[ftmp0],   0x0f(%[block])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x08(%[block])                          \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[line_size]            \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [block]"+&r"(block),              [h]"+&r"(h),
+          [ftmp0]"=&f"(ftmp[0])
+        : [value]"r"(value),                [line_size]"r"((mips_reg)line_size)
+        : "memory"
     );
 }
 
 void ff_fill_block8_mmi(uint8_t *block, uint8_t value, int line_size, int h)
 {
+    double ftmp0;
+
     __asm__ volatile (
-        "move $8, %3                \r\n"
-        "move $9, %0                \r\n"
-        "dmtc1 %1, $f2              \r\n"
-        "punpcklbh $f2, $f2, $f2    \r\n"
-        "punpcklbh $f2, $f2, $f2    \r\n"
-        "punpcklbh $f2, $f2, $f2    \r\n"
-        "1:                         \r\n"
-        "gssdlc1 $f2, 7($9)         \r\n"
-        "gssdrc1 $f2, 0($9)         \r\n"
-        "daddi $8, $8, -1           \r\n"
-        "daddu $9, $9, %2           \r\n"
-        "bnez $8, 1b                \r\n"
-        ::"r"(block),"r"(value),"r"(line_size),"r"(h)
-        : "$8","$9"
+        "mtc1       %[value],   %[ftmp0]                                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "1:                                                             \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[block])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[block])                          \n\t"
+        PTR_ADDI   "%[h],       %[h],           -0x01                   \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[line_size]            \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [block]"+&r"(block),              [h]"+&r"(h),
+          [ftmp0]"=&f"(ftmp0)
+        : [value]"r"(value),                [line_size]"r"((mips_reg)line_size)
+        : "memory"
     );
 }
 
 void ff_clear_block_mmi(int16_t *block)
 {
+    double ftmp[2];
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0              \r\n"
-        "xor $f2, $f2, $f2              \r\n"
-        "gssqc1 $f0, $f2,   0(%0)       \r\n"
-        "gssqc1 $f0, $f2,  16(%0)       \r\n"
-        "gssqc1 $f0, $f2,  32(%0)       \r\n"
-        "gssqc1 $f0, $f2,  48(%0)       \r\n"
-        "gssqc1 $f0, $f2,  64(%0)       \r\n"
-        "gssqc1 $f0, $f2,  80(%0)       \r\n"
-        "gssqc1 $f0, $f2,  96(%0)       \r\n"
-        "gssqc1 $f0, $f2, 112(%0)       \r\n"
-        ::"r"(block)
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x00(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x10(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x20(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x30(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x40(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x50(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x60(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x70(%[block])          \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1])
+        : [block]"r"(block)
         : "memory"
     );
 }
 
 void ff_clear_blocks_mmi(int16_t *block)
 {
+    double ftmp[2];
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0              \r\n"
-        "xor $f2, $f2, $f2              \r\n"
-        "gssqc1 $f0, $f2,   0(%0)       \r\n"
-        "gssqc1 $f0, $f2,  16(%0)       \r\n"
-        "gssqc1 $f0, $f2,  32(%0)       \r\n"
-        "gssqc1 $f0, $f2,  48(%0)       \r\n"
-        "gssqc1 $f0, $f2,  64(%0)       \r\n"
-        "gssqc1 $f0, $f2,  80(%0)       \r\n"
-        "gssqc1 $f0, $f2,  96(%0)       \r\n"
-        "gssqc1 $f0, $f2, 112(%0)       \r\n"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x00(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x10(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x20(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x30(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x40(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x50(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x60(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x70(%[block])          \n\t"
 
-        "gssqc1 $f0, $f2, 128(%0)       \r\n"
-        "gssqc1 $f0, $f2, 144(%0)       \r\n"
-        "gssqc1 $f0, $f2, 160(%0)       \r\n"
-        "gssqc1 $f0, $f2, 176(%0)       \r\n"
-        "gssqc1 $f0, $f2, 192(%0)       \r\n"
-        "gssqc1 $f0, $f2, 208(%0)       \r\n"
-        "gssqc1 $f0, $f2, 224(%0)       \r\n"
-        "gssqc1 $f0, $f2, 240(%0)       \r\n"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x80(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x90(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0xa0(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0xb0(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0xc0(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0xd0(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0xe0(%[block])          \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0xf0(%[block])          \n\t"
 
-        "gssqc1 $f0, $f2, 256(%0)       \r\n"
-        "gssqc1 $f0, $f2, 272(%0)       \r\n"
-        "gssqc1 $f0, $f2, 288(%0)       \r\n"
-        "gssqc1 $f0, $f2, 304(%0)       \r\n"
-        "gssqc1 $f0, $f2, 320(%0)       \r\n"
-        "gssqc1 $f0, $f2, 336(%0)       \r\n"
-        "gssqc1 $f0, $f2, 352(%0)       \r\n"
-        "gssqc1 $f0, $f2, 368(%0)       \r\n"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x100(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x110(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x120(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x130(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x140(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x150(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x160(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x170(%[block])         \n\t"
 
-        "gssqc1 $f0, $f2, 384(%0)       \r\n"
-        "gssqc1 $f0, $f2, 400(%0)       \r\n"
-        "gssqc1 $f0, $f2, 416(%0)       \r\n"
-        "gssqc1 $f0, $f2, 432(%0)       \r\n"
-        "gssqc1 $f0, $f2, 448(%0)       \r\n"
-        "gssqc1 $f0, $f2, 464(%0)       \r\n"
-        "gssqc1 $f0, $f2, 480(%0)       \r\n"
-        "gssqc1 $f0, $f2, 496(%0)       \r\n"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x180(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x190(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x1a0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x1b0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x1c0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x1d0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x1e0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x1f0(%[block])         \n\t"
 
-        "gssqc1 $f0, $f2, 512(%0)       \r\n"
-        "gssqc1 $f0, $f2, 528(%0)       \r\n"
-        "gssqc1 $f0, $f2, 544(%0)       \r\n"
-        "gssqc1 $f0, $f2, 560(%0)       \r\n"
-        "gssqc1 $f0, $f2, 576(%0)       \r\n"
-        "gssqc1 $f0, $f2, 592(%0)       \r\n"
-        "gssqc1 $f0, $f2, 608(%0)       \r\n"
-        "gssqc1 $f0, $f2, 624(%0)       \r\n"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x200(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x210(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x220(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x230(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x240(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x250(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x260(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x270(%[block])         \n\t"
 
-        "gssqc1 $f0, $f2, 640(%0)       \r\n"
-        "gssqc1 $f0, $f2, 656(%0)       \r\n"
-        "gssqc1 $f0, $f2, 672(%0)       \r\n"
-        "gssqc1 $f0, $f2, 688(%0)       \r\n"
-        "gssqc1 $f0, $f2, 704(%0)       \r\n"
-        "gssqc1 $f0, $f2, 720(%0)       \r\n"
-        "gssqc1 $f0, $f2, 736(%0)       \r\n"
-        "gssqc1 $f0, $f2, 752(%0)       \r\n"
-        ::"r"(block)
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x280(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x290(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x2a0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x2b0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x2c0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x2d0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x2e0(%[block])         \n\t"
+        "gssqc1     %[ftmp0],   %[ftmp1],       0x2f0(%[block])         \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1])
+        : [block]"r"((mips_reg)block)
         : "memory"
     );
 }
diff --git a/libavcodec/mips/constants.c b/libavcodec/mips/constants.c
index f8130d9..3503fad 100644
--- a/libavcodec/mips/constants.c
+++ b/libavcodec/mips/constants.c
@@ -24,6 +24,7 @@
 #include "constants.h"
 
 DECLARE_ALIGNED(8, const uint64_t, ff_pw_1) =       {0x0001000100010001ULL};
+DECLARE_ALIGNED(8, const uint64_t, ff_pw_2) =       {0x0002000200020002ULL};
 DECLARE_ALIGNED(8, const uint64_t, ff_pw_3) =       {0x0003000300030003ULL};
 DECLARE_ALIGNED(8, const uint64_t, ff_pw_4) =       {0x0004000400040004ULL};
 DECLARE_ALIGNED(8, const uint64_t, ff_pw_5) =       {0x0005000500050005ULL};
diff --git a/libavcodec/mips/constants.h b/libavcodec/mips/constants.h
index 0a4effd..19d2d73 100644
--- a/libavcodec/mips/constants.h
+++ b/libavcodec/mips/constants.h
@@ -25,6 +25,7 @@
 #include <stdint.h>
 
 extern const uint64_t ff_pw_1;
+extern const uint64_t ff_pw_2;
 extern const uint64_t ff_pw_3;
 extern const uint64_t ff_pw_4;
 extern const uint64_t ff_pw_5;
diff --git a/libavcodec/mips/fft_mips.c b/libavcodec/mips/fft_mips.c
index 3cb1a4c..03dcbad 100644
--- a/libavcodec/mips/fft_mips.c
+++ b/libavcodec/mips/fft_mips.c
@@ -72,7 +72,7 @@ static void ff_fft_calc_mips(FFTContext *s, FFTComplex *z)
     FFTComplex * tmpz_n2, * tmpz_n34, * tmpz_n4;
     FFTComplex * tmpz_n2_i, * tmpz_n34_i, * tmpz_n4_i, * tmpz_i;
 
-    num_transforms = (0x2aab >> (16 - s->nbits)) | 1;
+    num_transforms = (21845 >> (17 - s->nbits)) | 1;
 
     for (n=0; n<num_transforms; n++) {
         offset = ff_fft_offsets_lut[n] << 2;
@@ -251,8 +251,8 @@ static void ff_fft_calc_mips(FFTContext *s, FFTComplex *z)
                 : "memory"
             );
 
-            w_re_ptr = (float*)(ff_cos_65536 + step);
-            w_im_ptr = (float*)(ff_cos_65536 + MAX_FFT_SIZE/4 - step);
+            w_re_ptr = (float*)(ff_cos_131072 + step);
+            w_im_ptr = (float*)(ff_cos_131072 + MAX_FFT_SIZE/4 - step);
 
             for (i=1; i<n4; i++) {
                 w_re = w_re_ptr[0];
@@ -502,8 +502,8 @@ av_cold void ff_fft_init_mips(FFTContext *s)
 {
     int n=0;
 
-    ff_fft_lut_init(ff_fft_offsets_lut, 0, 1 << 16, &n);
-    ff_init_ff_cos_tabs(16);
+    ff_fft_lut_init(ff_fft_offsets_lut, 0, 1 << 17, &n);
+    ff_init_ff_cos_tabs(17);
 
 #if HAVE_INLINE_ASM
 #if !HAVE_MIPS32R6 && !HAVE_MIPS64R6
diff --git a/libavcodec/mips/h264chroma_mmi.c b/libavcodec/mips/h264chroma_mmi.c
index ef29476..3dd123d 100644
--- a/libavcodec/mips/h264chroma_mmi.c
+++ b/libavcodec/mips/h264chroma_mmi.c
@@ -23,6 +23,8 @@
  */
 
 #include "h264chroma_mips.h"
+#include "constants.h"
+#include "libavutil/mips/asmdefs.h"
 
 void ff_put_h264_chroma_mc8_mmi(uint8_t *dst, uint8_t *src, int stride,
         int h, int x, int y)
@@ -32,171 +34,177 @@ void ff_put_h264_chroma_mc8_mmi(uint8_t *dst, uint8_t *src, int stride,
     const int C = (8 - x) * y;
     const int D = x * y;
     const int E = B + C;
-    int i;
-
-    av_assert2(x<8 && y<8 && x>=0 && y>=0);
+    double ftmp[10];
+    uint64_t tmp[1];
+    mips_reg addr[1];
 
     if (D) {
-        for (i=0; i<h; i++) {
-            __asm__ volatile (
-                "ldl $2, %2                 \r\n"
-                "ldr $2, %1                 \r\n"
-                "ldl $3, %4                 \r\n"
-                "ldr $3, %3                 \r\n"
-                "ldl $4, %6                 \r\n"
-                "ldr $4, %5                 \r\n"
-                "ldl $5, %8                 \r\n"
-                "ldr $5, %7                 \r\n"
-                "daddiu $6, $0, 32          \r\n"
-                "mtc1 %9, $f6               \r\n"
-                "mtc1 %10, $f8              \r\n"
-                "mtc1 %11, $f10             \r\n"
-                "mtc1 %12, $f12             \r\n"
-                "mtc1 $0, $f20              \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "mtc1 $4, $f16              \r\n"
-                "mtc1 $5, $f18              \r\n"
-                "mtc1 $6, $f14              \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pshufh $f6, $f6, $f20      \r\n"
-                "pshufh $f8, $f8, $f20      \r\n"
-                "pshufh $f10, $f10, $f20    \r\n"
-                "pshufh $f12, $f12, $f20    \r\n"
-                "pshufh $f14, $f14, $f20    \r\n"
-                "punpcklbh $f16, $f16, $f20 \r\n"
-                "punpcklbh $f18, $f18, $f20 \r\n"
-                "daddiu $6, $0, 6           \r\n"
-                "mtc1 $6, $f22              \r\n"
-                "dsrl32 $2, $2, 0           \r\n"
-                "dsrl32 $3, $3, 0           \r\n"
-                "dsrl32 $4, $4, 0           \r\n"
-                "dsrl32 $5, $5, 0           \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "pmullh $f16, $f10, $f16    \r\n"
-                "pmullh $f18, $f12, $f18    \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f4, $f4, $f16       \r\n"
-                "paddh $f2, $f2, $f18       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f24, $f2, $f22      \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "mtc1 $4, $f16              \r\n"
-                "mtc1 $5, $f18              \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "punpcklbh $f16, $f16, $f20 \r\n"
-                "punpcklbh $f18, $f18, $f20 \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "pmullh $f16, $f10, $f16    \r\n"
-                "pmullh $f18, $f12, $f18    \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f4, $f4, $f16       \r\n"
-                "paddh $f2, $f2, $f18       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f2, $f2, $f22       \r\n"
-                "packushb $f2, $f24, $f2    \r\n"
-                "sdc1 $f2, %0               \r\n"
-                : "=m"(*dst)
-                : "m"(*src),"m"(*(src+7)),"m"(*(src+1)),"m"(*(src+8)),
-                  "m"(*(src+stride)),"m"(*(src+stride+7)),
-                  "m"(*(src+stride+1)),"m"(*(src+stride+8)),
-                  "r"(A),"r"(B),"r"(C),"r"(D)
-                : "$2","$3","$4","$5","$6"
-            );
-
-            dst += stride;
-            src += stride;
-        }
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "pshufh     %[B],       %[B],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp9]                            \n\t"
+            "pshufh     %[C],       %[C],           %[ftmp0]            \n\t"
+            "pshufh     %[D],       %[D],           %[ftmp0]            \n\t"
+            "1:                                                         \n\t"
+            PTR_ADDU   "%[addr0],   %[src],         %[stride]           \n\t"
+            "gsldlc1    %[ftmp1],   0x07(%[src])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x00(%[src])                        \n\t"
+            "gsldlc1    %[ftmp2],   0x08(%[src])                        \n\t"
+            "gsldrc1    %[ftmp2],   0x01(%[src])                        \n\t"
+            "gsldlc1    %[ftmp3],   0x07(%[addr0])                      \n\t"
+            "gsldrc1    %[ftmp3],   0x00(%[addr0])                      \n\t"
+            "gsldlc1    %[ftmp4],   0x08(%[addr0])                      \n\t"
+            "gsldrc1    %[ftmp4],   0x01(%[addr0])                      \n\t"
+
+            "punpcklbh  %[ftmp5],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp6],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp7],   %[ftmp2],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp8],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[A]                \n\t"
+            "pmullh     %[ftmp7],   %[ftmp7],       %[B]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[A]                \n\t"
+            "pmullh     %[ftmp8],   %[ftmp8],       %[B]                \n\t"
+            "paddh      %[ftmp2],   %[ftmp6],       %[ftmp8]            \n\t"
+
+            "punpcklbh  %[ftmp5],   %[ftmp3],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp6],   %[ftmp3],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp7],   %[ftmp4],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp8],   %[ftmp4],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[C]                \n\t"
+            "pmullh     %[ftmp7],   %[ftmp7],       %[D]                \n\t"
+            "paddh      %[ftmp3],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[C]                \n\t"
+            "pmullh     %[ftmp8],   %[ftmp8],       %[D]                \n\t"
+            "paddh      %[ftmp4],   %[ftmp6],       %[ftmp8]            \n\t"
+
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp9]            \n\t"
+            "psrlh      %[ftmp2],   %[ftmp2],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [ftmp8]"=&f"(ftmp[8]),        [ftmp9]"=&f"(ftmp[9]),
+              [tmp0]"=&r"(tmp[0]),
+              [addr0]"=&r"(addr[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h)
+            : [stride]"r"((mips_reg)stride),[ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A),                    [B]"f"(B),
+              [C]"f"(C),                    [D]"f"(D)
+            : "memory"
+        );
     } else if (E) {
         const int step = C ? stride : 1;
 
-        for (i=0; i<h; i++) {
-            __asm__ volatile (
-                "daddiu $6, $0, 32          \r\n"
-                "ldl $2, %2                 \r\n"
-                "ldr $2, %1                 \r\n"
-                "ldl $3, %4                 \r\n"
-                "ldr $3, %3                 \r\n"
-                "mtc1 $6, $f14              \r\n"
-                "mtc1 %5, $f6               \r\n"
-                "mtc1 %6, $f8               \r\n"
-                "mtc1 $0, $f20              \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "daddiu $6, $0, 6           \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pshufh $f6, $f6, $f20      \r\n"
-                "pshufh $f8, $f8, $f20      \r\n"
-                "pshufh $f14, $f14, $f20    \r\n"
-                "mtc1 $6, $f22              \r\n"
-                "dsrl32 $2, $2, 0           \r\n"
-                "dsrl32 $3, $3, 0           \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f24, $f2, $f22      \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f2, $f2, $f22       \r\n"
-                "packushb $f2, $f24, $f2    \r\n"
-                "sdc1 $f2, %0               \r\n"
-                : "=m"(*dst)
-                : "m"(*(src)),"m"(*(src+7)),
-                  "m"(*(src+step)),"m"(*(src+step+7)),
-                  "r"(A),"r"(E)
-                : "$2","$3","$4","$5","$6"
-            );
-
-            dst += stride;
-            src += stride;
-        }
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "pshufh     %[E],       %[E],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp7]                            \n\t"
+            "1:                                                         \n\t"
+            PTR_ADDU   "%[addr0],   %[src],         %[step]             \n\t"
+            "gsldlc1    %[ftmp1],   0x07(%[src])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x00(%[src])                        \n\t"
+            "gsldlc1    %[ftmp2],   0x07(%[addr0])                      \n\t"
+            "gsldrc1    %[ftmp2],   0x00(%[addr0])                      \n\t"
+
+            "punpcklbh  %[ftmp3],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp4],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp2],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp6],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp3],   %[ftmp3],       %[A]                \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[E]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp3],       %[ftmp5]            \n\t"
+            "pmullh     %[ftmp4],   %[ftmp4],       %[A]                \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[E]                \n\t"
+            "paddh      %[ftmp2],   %[ftmp4],       %[ftmp6]            \n\t"
+
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "psrlh      %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [tmp0]"=&r"(tmp[0]),
+              [addr0]"=&r"(addr[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h)
+            : [stride]"r"((mips_reg)stride),[step]"r"((mips_reg)step),
+              [ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A),                    [E]"f"(E)
+            : "memory"
+        );
     } else {
-        for (i = 0; i < h; i++) {
-            __asm__ volatile (
-                "daddiu $6, $0, 32          \r\n"
-                "ldl $2, %2                 \r\n"
-                "ldr $2, %1                 \r\n"
-                "mtc1 $6, $f14              \r\n"
-                "mtc1 %3, $f6               \r\n"
-                "mtc1 $0, $f20              \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "daddiu $6, $0, 6           \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "pshufh $f6, $f6, $f20      \r\n"
-                "pshufh $f14, $f14, $f20    \r\n"
-                "mtc1 $6, $f22              \r\n"
-                "dsrl32 $2, $2, 0           \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "psrah $f24, $f2, $f22      \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "psrah $f2, $f2, $f22       \r\n"
-                "packushb $f2, $f24, $f2    \r\n"
-                "sdc1 $f2, %0               \r\n"
-                :"=m"(*dst)
-                :"m"(*src),"m"(*(src+7)),"r"(A)
-                :"$2"
-            );
-
-            dst += stride;
-            src += stride;
-        }
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp4]                            \n\t"
+            "1:                                                         \n\t"
+            "gsldlc1    %[ftmp1],   0x07(%[src])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x00(%[src])                        \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp3],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp2],       %[A]                \n\t"
+            "pmullh     %[ftmp2],   %[ftmp3],       %[A]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp4]            \n\t"
+            "psrlh      %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "gsldlc1    %[ftmp1],   0x07(%[src])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x00(%[src])                        \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp3],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp2],       %[A]                \n\t"
+            "pmullh     %[ftmp2],   %[ftmp3],       %[A]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp4]            \n\t"
+            "psrlh      %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "addi       %[h],       %[h],           -0x02               \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),
+              [tmp0]"=&r"(tmp[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h)
+            : [stride]"r"((mips_reg)stride),[ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A)
+            : "memory"
+        );
     }
 }
 
@@ -208,140 +216,185 @@ void ff_avg_h264_chroma_mc8_mmi(uint8_t *dst, uint8_t *src, int stride,
     const int C = (8 - x) * y;
     const int D = x * y;
     const int E = B + C;
-    int i;
-
-    av_assert2(x<8 && y<8 && x>=0 && y>=0);
+    double ftmp[10];
+    uint64_t tmp[1];
+    mips_reg addr[1];
 
     if (D) {
-        for (i=0; i<h; i++) {
-            __asm__ volatile (
-                "ldl $2, %2                 \r\n"
-                "ldr $2, %1                 \r\n"
-                "ldl $3, %4                 \r\n"
-                "ldr $3, %3                 \r\n"
-                "ldl $4, %6                 \r\n"
-                "ldr $4, %5                 \r\n"
-                "ldl $5, %8                 \r\n"
-                "ldr $5, %7                 \r\n"
-                "daddiu $6, $0, 32          \r\n"
-                "mtc1 %9, $f6               \r\n"
-                "mtc1 %10, $f8              \r\n"
-                "mtc1 %11, $f10             \r\n"
-                "mtc1 %12, $f12             \r\n"
-                "mtc1 $0, $f20              \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "mtc1 $4, $f16              \r\n"
-                "mtc1 $5, $f18              \r\n"
-                "mtc1 $6, $f14              \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pshufh $f6, $f6, $f20      \r\n"
-                "pshufh $f8, $f8, $f20      \r\n"
-                "pshufh $f10, $f10, $f20    \r\n"
-                "pshufh $f12, $f12, $f20    \r\n"
-                "pshufh $f14, $f14, $f20    \r\n"
-                "punpcklbh $f16, $f16, $f20 \r\n"
-                "punpcklbh $f18, $f18, $f20 \r\n"
-                "daddiu $6, $0, 6           \r\n"
-                "mtc1 $6, $f22              \r\n"
-                "dsrl32 $2, $2, 0           \r\n"
-                "dsrl32 $3, $3, 0           \r\n"
-                "dsrl32 $4, $4, 0           \r\n"
-                "dsrl32 $5, $5, 0           \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "pmullh $f16, $f10, $f16    \r\n"
-                "pmullh $f18, $f12, $f18    \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f4, $f4, $f16       \r\n"
-                "paddh $f2, $f2, $f18       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f24, $f2, $f22      \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "mtc1 $4, $f16              \r\n"
-                "mtc1 $5, $f18              \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "punpcklbh $f16, $f16, $f20 \r\n"
-                "punpcklbh $f18, $f18, $f20 \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "pmullh $f16, $f10, $f16    \r\n"
-                "pmullh $f18, $f12, $f18    \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f4, $f4, $f16       \r\n"
-                "paddh $f2, $f2, $f18       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f2, $f2, $f22       \r\n"
-                "packushb $f2, $f24, $f2    \r\n"
-                "ldc1 $f4, %0               \r\n"
-                "pavgb $f2, $f2, $f4        \r\n"
-                "sdc1 $f2, %0               \r\n"
-                : "=m"(*dst)
-                : "m"(*(src)),"m"(*(src+7)),"m"(*(src+1)),"m"(*(src+8)),
-                  "m"(*(src+stride)),"m"(*(src+stride+7)),
-                  "m"(*(src+stride+1)),"m"(*(src+stride+8)),
-                  "r"(A),"r"(B),"r"(C),"r"(D)
-                : "$2","$3","$4","$5","$6"
-            );
-
-            dst += stride;
-            src += stride;
-        }
-    } else {
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "pshufh     %[B],       %[B],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp9]                            \n\t"
+            "pshufh     %[C],       %[C],           %[ftmp0]            \n\t"
+            "pshufh     %[D],       %[D],           %[ftmp0]            \n\t"
+            "1:                                                         \n\t"
+            PTR_ADDU   "%[addr0],   %[src],         %[stride]           \n\t"
+            "gsldlc1    %[ftmp1],   0x07(%[src])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x00(%[src])                        \n\t"
+            "gsldlc1    %[ftmp2],   0x08(%[src])                        \n\t"
+            "gsldrc1    %[ftmp2],   0x01(%[src])                        \n\t"
+            "gsldlc1    %[ftmp3],   0x07(%[addr0])                      \n\t"
+            "gsldrc1    %[ftmp3],   0x00(%[addr0])                      \n\t"
+            "gsldlc1    %[ftmp4],   0x08(%[addr0])                      \n\t"
+            "gsldrc1    %[ftmp4],   0x01(%[addr0])                      \n\t"
+
+            "punpcklbh  %[ftmp5],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp6],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp7],   %[ftmp2],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp8],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[A]                \n\t"
+            "pmullh     %[ftmp7],   %[ftmp7],       %[B]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[A]                \n\t"
+            "pmullh     %[ftmp8],   %[ftmp8],       %[B]                \n\t"
+            "paddh      %[ftmp2],   %[ftmp6],       %[ftmp8]            \n\t"
+
+            "punpcklbh  %[ftmp5],   %[ftmp3],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp6],   %[ftmp3],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp7],   %[ftmp4],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp8],   %[ftmp4],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[C]                \n\t"
+            "pmullh     %[ftmp7],   %[ftmp7],       %[D]                \n\t"
+            "paddh      %[ftmp3],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[C]                \n\t"
+            "pmullh     %[ftmp8],   %[ftmp8],       %[D]                \n\t"
+            "paddh      %[ftmp4],   %[ftmp6],       %[ftmp8]            \n\t"
+
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp9]            \n\t"
+            "psrlh      %[ftmp2],   %[ftmp2],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "ldc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [ftmp8]"=&f"(ftmp[8]),        [ftmp9]"=&f"(ftmp[9]),
+              [tmp0]"=&r"(tmp[0]),
+              [addr0]"=&r"(addr[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h)
+            : [stride]"r"((mips_reg)stride),[ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A),                    [B]"f"(B),
+              [C]"f"(C),                    [D]"f"(D)
+            : "memory"
+        );
+    } else if (E) {
         const int step = C ? stride : 1;
 
-        for (i=0; i<h; i++) {
-            __asm__ volatile (
-                "daddiu $6, $0, 32          \r\n"
-                "ldl $2, %2                 \r\n"
-                "ldr $2, %1                 \r\n"
-                "ldl $3, %4                 \r\n"
-                "ldr $3, %3                 \r\n"
-                "mtc1 $6, $f14              \r\n"
-                "mtc1 %5, $f6               \r\n"
-                "mtc1 %6, $f8               \r\n"
-                "mtc1 $0, $f20              \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "daddiu $6, $0, 6           \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pshufh $f6, $f6, $f20      \r\n"
-                "pshufh $f8, $f8, $f20      \r\n"
-                "pshufh $f14, $f14, $f20    \r\n"
-                "mtc1 $6, $f22              \r\n"
-                "dsrl32 $2, $2, 0           \r\n"
-                "dsrl32 $3, $3, 0           \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f24, $f2, $f22      \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f2, $f2, $f22       \r\n"
-                "packushb $f2, $f24, $f2    \r\n"
-                "ldc1 $f4, %0               \r\n"
-                "pavgb $f2, $f2, $f4        \r\n"
-                "sdc1 $f2, %0               \r\n"
-                : "=m"(*dst)
-                : "m"(*(src)),"m"(*(src+7)),
-                  "m"(*(src+step)),"m"(*(src+step+7)),"r"(A),"r"(E)
-                : "$2","$3","$4","$5","$6"
-            );
-
-            dst += stride;
-            src += stride;
-        }
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "pshufh     %[E],       %[E],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp7]                            \n\t"
+            "1:                                                         \n\t"
+            PTR_ADDU   "%[addr0],   %[src],         %[step]             \n\t"
+            "gsldlc1    %[ftmp1],   0x07(%[src])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x00(%[src])                        \n\t"
+            "gsldlc1    %[ftmp2],   0x07(%[addr0])                      \n\t"
+            "gsldrc1    %[ftmp2],   0x00(%[addr0])                      \n\t"
+
+            "punpcklbh  %[ftmp3],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp4],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp2],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp6],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp3],   %[ftmp3],       %[A]                \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[E]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp3],       %[ftmp5]            \n\t"
+            "pmullh     %[ftmp4],   %[ftmp4],       %[A]                \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[E]                \n\t"
+            "paddh      %[ftmp2],   %[ftmp4],       %[ftmp6]            \n\t"
+
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "psrlh      %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "ldc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [tmp0]"=&r"(tmp[0]),
+              [addr0]"=&r"(addr[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h)
+            : [stride]"r"((mips_reg)stride),[step]"r"((mips_reg)step),
+              [ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A),                    [E]"f"(E)
+            : "memory"
+        );
+    } else {
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp4]                            \n\t"
+            "1:                                                         \n\t"
+            "gsldlc1    %[ftmp1],   0x07(%[src])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x00(%[src])                        \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp3],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp2],       %[A]                \n\t"
+            "pmullh     %[ftmp2],   %[ftmp3],       %[A]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp4]            \n\t"
+            "psrlh      %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "ldc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+
+            "gsldlc1    %[ftmp1],   0x07(%[src])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x00(%[src])                        \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp3],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp2],       %[A]                \n\t"
+            "pmullh     %[ftmp2],   %[ftmp3],       %[A]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp4]            \n\t"
+            "psrlh      %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "ldc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "addi       %[h],       %[h],           -0x02               \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),
+              [tmp0]"=&r"(tmp[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h)
+            : [stride]"r"((mips_reg)stride),[ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A)
+            : "memory"
+        );
     }
 }
 
@@ -353,118 +406,150 @@ void ff_put_h264_chroma_mc4_mmi(uint8_t *dst, uint8_t *src, int stride,
     const int C = (8 - x) *  y;
     const int D = x *  y;
     const int E = B + C;
-    int i;
-
-    av_assert2(x<8 && y<8 && x>=0 && y>=0);
+    double ftmp[8];
+    uint64_t tmp[1];
+    mips_reg addr[1];
+    uint64_t low32;
 
     if (D) {
-        for (i=0; i<h; i++) {
-            __asm__ volatile (
-                "ldl $2, %2                 \r\n"
-                "ldr $2, %1                 \r\n"
-                "ldl $3, %4                 \r\n"
-                "ldr $3, %3                 \r\n"
-                "ldl $4, %6                 \r\n"
-                "ldr $4, %5                 \r\n"
-                "ldl $5, %8                 \r\n"
-                "ldr $5, %7                 \r\n"
-                "daddiu $6, $0, 32          \r\n"
-                "mtc1 %9, $f6               \r\n"
-                "mtc1 %10, $f8              \r\n"
-                "mtc1 %11, $f10             \r\n"
-                "mtc1 %12, $f12             \r\n"
-                "mtc1 $0, $f20              \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "mtc1 $4, $f16              \r\n"
-                "mtc1 $5, $f18              \r\n"
-                "mtc1 $6, $f14              \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pshufh $f6, $f6, $f20      \r\n"
-                "pshufh $f8, $f8, $f20      \r\n"
-                "pshufh $f10, $f10, $f20    \r\n"
-                "pshufh $f12, $f12, $f20    \r\n"
-                "pshufh $f14, $f14, $f20    \r\n"
-                "punpcklbh $f16, $f16, $f20 \r\n"
-                "punpcklbh $f18, $f18, $f20 \r\n"
-                "daddiu $6, $0, 6           \r\n"
-                "mtc1 $6, $f22              \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "pmullh $f16, $f10, $f16    \r\n"
-                "pmullh $f18, $f12, $f18    \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f4, $f4, $f16       \r\n"
-                "paddh $f2, $f2, $f18       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f2, $f2, $f22       \r\n"
-                "packushb $f2, $f2, $f2     \r\n"
-                "swc1 $f2, %0               \r\n"
-                : "=m"(*dst)
-                : "m"(*(src)),"m"(*(src+7)),"m"(*(src+1)),"m"(*(src+8)),
-                  "m"(*(src+stride)),"m"(*(src+stride+7)),
-                  "m"(*(src+stride+1)),"m"(*(src+stride+8)),
-                  "r"(A),"r"(B),"r"(C),"r"(D)
-                : "$2","$3","$4","$5","$6"
-            );
-
-            dst += stride;
-            src += stride;
-        }
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "pshufh     %[B],       %[B],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp7]                            \n\t"
+            "pshufh     %[C],       %[C],           %[ftmp0]            \n\t"
+            "pshufh     %[D],       %[D],           %[ftmp0]            \n\t"
+            "1:                                                         \n\t"
+            PTR_ADDU   "%[addr0],   %[src],         %[stride]           \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "uld        %[low32],   0x01(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "uld        %[low32],   0x00(%[addr0])                      \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            "uld        %[low32],   0x01(%[addr0])                      \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+
+            "punpcklbh  %[ftmp5],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp6],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[A]                \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[B]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp5],       %[ftmp6]            \n\t"
+
+            "punpcklbh  %[ftmp5],   %[ftmp3],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp6],   %[ftmp4],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[C]                \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[D]                \n\t"
+            "paddh      %[ftmp2],   %[ftmp5],       %[ftmp6]            \n\t"
+
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            "swc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [tmp0]"=&r"(tmp[0]),
+              [addr0]"=&r"(addr[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h),
+              [low32]"=&r"(low32)
+            : [stride]"r"((mips_reg)stride),[ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A),                    [B]"f"(B),
+              [C]"f"(C),                    [D]"f"(D)
+            : "memory"
+        );
     } else if (E) {
         const int step = C ? stride : 1;
 
-        for (i=0; i<h; i++) {
-            __asm__ volatile (
-                "ldl $2, %2                 \r\n"
-                "ldr $2, %1                 \r\n"
-                "ldl $3, %4                 \r\n"
-                "ldr $3, %3                 \r\n"
-                "daddiu $4, $0, 32          \r\n"
-                "mtc1 %5, $f6               \r\n"
-                "mtc1 %6, $f8               \r\n"
-                "mtc1 $0, $f20              \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "mtc1 $4, $f10              \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pshufh $f6, $f6, $f20      \r\n"
-                "pshufh $f8, $f8, $f20      \r\n"
-                "pshufh $f10, $f10, $f20    \r\n"
-                "daddiu $4, $0, 6           \r\n"
-                "mtc1 $4, $f22              \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "paddh $f2, $f2, $f10       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f2, $f2, $f22       \r\n"
-                "packushb $f2, $f2, $f20    \r\n"
-                "swc1 $f2, %0               \r\n"
-                : "=m"(*dst)
-                : "m"(*(src)),"m"(*(src+7)),"m"(*(src+step)),
-                  "m"(*(src+step+7)),"r"(A),"r"(E)
-                : "$2","$3","$4","$5","$6"
-            );
-
-            dst += stride;
-            src += stride;
-        }
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "pshufh     %[E],       %[E],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp5]                            \n\t"
+            "1:                                                         \n\t"
+            PTR_ADDU   "%[addr0],   %[src],         %[step]             \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "uld        %[low32],   0x00(%[addr0])                      \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+
+            "punpcklbh  %[ftmp3],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp3],   %[ftmp3],       %[A]                \n\t"
+            "pmullh     %[ftmp4],   %[ftmp4],       %[E]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp3],       %[ftmp4]            \n\t"
+
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            "swc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [tmp0]"=&r"(tmp[0]),
+              [addr0]"=&r"(addr[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h),
+              [low32]"=&r"(low32)
+            : [stride]"r"((mips_reg)stride),[step]"r"((mips_reg)step),
+              [ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A),                    [E]"f"(E)
+            : "memory"
+        );
     } else {
-        for (i=0; i<h; i++) {
-            __asm__ volatile (
-                "lwl $2, %2                 \r\n"
-                "lwr $2, %1                 \r\n"
-                "sw $2, %0                  \r\n"
-                : "=m"(*dst)
-                : "m"(*src),"m"(*(src+3))
-                : "$2"
-            );
-
-            dst += stride;
-            src += stride;
-        }
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp3]                            \n\t"
+            "1:                                                         \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp2],       %[A]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            "swc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp2],       %[A]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "addi       %[h],       %[h],           -0x02               \n\t"
+            "swc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [tmp0]"=&r"(tmp[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h),
+              [low32]"=&r"(low32)
+            : [stride]"r"((mips_reg)stride),[ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A)
+            : "memory"
+        );
     }
 }
 
@@ -475,108 +560,158 @@ void ff_avg_h264_chroma_mc4_mmi(uint8_t *dst, uint8_t *src, int stride,
     const int B = x * (8 - y);
     const int C = (8 - x) * y;
     const int D = x * y;
-    int i;
-
-    av_assert2(x<8 && y<8 && x>=0 && y>=0);
+    const int E = B + C;
+    double ftmp[8];
+    uint64_t tmp[1];
+    mips_reg addr[1];
+    uint64_t low32;
 
     if (D) {
-        for (i=0; i<h; i++) {
-            __asm__ volatile (
-                "ldl $2, %2                 \r\n"
-                "ldr $2, %1                 \r\n"
-                "ldl $3, %4                 \r\n"
-                "ldr $3, %3                 \r\n"
-                "ldl $4, %6                 \r\n"
-                "ldr $4, %5                 \r\n"
-                "ldl $5, %8                 \r\n"
-                "ldr $5, %7                 \r\n"
-                "daddiu $6, $0, 32          \r\n"
-                "mtc1 %9, $f6               \r\n"
-                "mtc1 %10, $f8              \r\n"
-                "mtc1 %11, $f10             \r\n"
-                "mtc1 %12, $f12             \r\n"
-                "mtc1 $0, $f20              \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "mtc1 $4, $f16              \r\n"
-                "mtc1 $5, $f18              \r\n"
-                "mtc1 $6, $f14              \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pshufh $f6, $f6, $f20      \r\n"
-                "pshufh $f8, $f8, $f20      \r\n"
-                "pshufh $f10, $f10, $f20    \r\n"
-                "pshufh $f12, $f12, $f20    \r\n"
-                "pshufh $f14, $f14, $f20    \r\n"
-                "punpcklbh $f16, $f16, $f20 \r\n"
-                "punpcklbh $f18, $f18, $f20 \r\n"
-                "daddiu $6, $0, 6           \r\n"
-                "mtc1 $6, $f22              \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "pmullh $f16, $f10, $f16    \r\n"
-                "pmullh $f18, $f12, $f18    \r\n"
-                "paddh $f2, $f2, $f14       \r\n"
-                "paddh $f4, $f4, $f16       \r\n"
-                "paddh $f2, $f2, $f18       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f2, $f2, $f22       \r\n"
-                "packushb $f2, $f2, $f2     \r\n"
-                "lwc1 $f4, %0               \r\n"
-                "pavgb $f2, $f2, $f4        \r\n"
-                "swc1 $f2, %0               \r\n"
-                : "=m"(*dst)
-                : "m"(*(src)),"m"(*(src+7)),"m"(*(src+1)),"m"(*(src+8)),
-                  "m"(*(src+stride)),"m"(*(src+stride+7)),
-                  "m"(*(src+stride+1)),"m"(*(src+stride+8)),
-                  "r"(A),"r"(B),"r"(C),"r"(D)
-                : "$2","$3","$4","$5","$6"
-            );
-
-            dst += stride;
-            src += stride;
-        }
-    } else {
-        const int E = B + C;
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "pshufh     %[B],       %[B],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp7]                            \n\t"
+            "pshufh     %[C],       %[C],           %[ftmp0]            \n\t"
+            "pshufh     %[D],       %[D],           %[ftmp0]            \n\t"
+            "1:                                                         \n\t"
+            PTR_ADDU   "%[addr0],   %[src],         %[stride]           \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "uld        %[low32],   0x01(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "uld        %[low32],   0x00(%[addr0])                      \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            "uld        %[low32],   0x01(%[addr0])                      \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+
+            "punpcklbh  %[ftmp5],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp6],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[A]                \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[B]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp5],       %[ftmp6]            \n\t"
+
+            "punpcklbh  %[ftmp5],   %[ftmp3],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp6],   %[ftmp4],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp5],   %[ftmp5],       %[C]                \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[D]                \n\t"
+            "paddh      %[ftmp2],   %[ftmp5],       %[ftmp6]            \n\t"
+
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "lwc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            "swc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [tmp0]"=&r"(tmp[0]),
+              [addr0]"=&r"(addr[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h),
+              [low32]"=&r"(low32)
+            : [stride]"r"((mips_reg)stride),[ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A),                    [B]"f"(B),
+              [C]"f"(C),                    [D]"f"(D)
+            : "memory"
+        );
+    } else if (E) {
         const int step = C ? stride : 1;
 
-        for (i=0; i<h; i++) {
-            __asm__ volatile (
-                "ldl $2, %2                 \r\n"
-                "ldr $2, %1                 \r\n"
-                "ldl $3, %4                 \r\n"
-                "ldr $3, %3                 \r\n"
-                "daddiu $4, $0, 32          \r\n"
-                "mtc1 %5, $f6               \r\n"
-                "mtc1 %6, $f8               \r\n"
-                "mtc1 $0, $f20              \r\n"
-                "mtc1 $2, $f2               \r\n"
-                "mtc1 $3, $f4               \r\n"
-                "mtc1 $4, $f10              \r\n"
-                "punpcklbh $f2, $f2, $f20   \r\n"
-                "punpcklbh $f4, $f4, $f20   \r\n"
-                "pshufh $f6, $f6, $f20      \r\n"
-                "pshufh $f8, $f8, $f20      \r\n"
-                "pshufh $f10, $f10, $f20    \r\n"
-                "daddiu $4, $0, 6           \r\n"
-                "mtc1 $4, $f22              \r\n"
-                "pmullh $f2, $f2, $f6       \r\n"
-                "pmullh $f4, $f4, $f8       \r\n"
-                "paddh $f2, $f2, $f10       \r\n"
-                "paddh $f2, $f2, $f4        \r\n"
-                "psrah $f2, $f2, $f22       \r\n"
-                "packushb $f2, $f2, $f20    \r\n"
-                "lwc1 $f4, %0               \r\n"
-                "pavgb $f2, $f2, $f4        \r\n"
-                "swc1 $f2, %0               \r\n"
-                : "=m"(*dst)
-                : "m"(*(src)),"m"(*(src+7)),"m"(*(src+step)),
-                  "m"(*(src+step+7)),"r"(A),"r"(E)
-                : "$2","$3","$4","$5","$6"
-            );
-
-            dst += stride;
-            src += stride;
-        }
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "pshufh     %[E],       %[E],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp5]                            \n\t"
+            "1:                                                         \n\t"
+            PTR_ADDU   "%[addr0],   %[src],         %[step]             \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "uld        %[low32],   0x00(%[addr0])                      \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+
+            "punpcklbh  %[ftmp3],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp3],   %[ftmp3],       %[A]                \n\t"
+            "pmullh     %[ftmp4],   %[ftmp4],       %[E]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp3],       %[ftmp4]            \n\t"
+
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "lwc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            "swc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [tmp0]"=&r"(tmp[0]),
+              [addr0]"=&r"(addr[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h),
+              [low32]"=&r"(low32)
+            : [stride]"r"((mips_reg)stride),[step]"r"((mips_reg)step),
+              [ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A),                    [E]"f"(E)
+            : "memory"
+        );
+    } else {
+        __asm__ volatile (
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "pshufh     %[A],       %[A],           %[ftmp0]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp3]                            \n\t"
+            "1:                                                         \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp2],       %[A]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "lwc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            "swc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp2],       %[A]                \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_32]         \n\t"
+            "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "lwc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "addi       %[h],       %[h],           -0x02               \n\t"
+            "swc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+
+            PTR_ADDU   "%[src],     %[src],         %[stride]           \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[stride]           \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [tmp0]"=&r"(tmp[0]),
+              [dst]"+&r"(dst),              [src]"+&r"(src),
+              [h]"+&r"(h),
+              [low32]"=&r"(low32)
+            : [stride]"r"((mips_reg)stride),[ff_pw_32]"f"(ff_pw_32),
+              [A]"f"(A)
+            : "memory"
+        );
     }
 }
diff --git a/libavcodec/mips/h264dsp_mmi.c b/libavcodec/mips/h264dsp_mmi.c
index 14c4a43..a62bbab 100644
--- a/libavcodec/mips/h264dsp_mmi.c
+++ b/libavcodec/mips/h264dsp_mmi.c
@@ -25,38 +25,57 @@
 
 #include "libavcodec/bit_depth_template.c"
 #include "h264dsp_mips.h"
+#include "libavutil/mips/asmdefs.h"
 
 void ff_h264_add_pixels4_8_mmi(uint8_t *dst, int16_t *src, int stride)
 {
+    double ftmp[9];
+    uint64_t low32;
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0              \r\n"
-        "ldc1 $f2, 0(%[src])            \r\n"
-        "ldc1 $f4, 8(%[src])            \r\n"
-        "ldc1 $f6, 16(%[src])           \r\n"
-        "ldc1 $f8, 24(%[src])           \r\n"
-        "lwc1 $f10, 0(%[dst0])          \r\n"
-        "lwc1 $f12, 0(%[dst1])          \r\n"
-        "lwc1 $f14, 0(%[dst2])          \r\n"
-        "lwc1 $f16, 0(%[dst3])          \r\n"
-        "punpcklbh $f10, $f10, $f0      \r\n"
-        "punpcklbh $f12, $f12, $f0      \r\n"
-        "punpcklbh $f14, $f14, $f0      \r\n"
-        "punpcklbh $f16, $f16, $f0      \r\n"
-        "paddh $f2, $f2, $f10           \r\n"
-        "paddh $f4, $f4, $f12           \r\n"
-        "paddh $f6, $f6, $f14           \r\n"
-        "paddh $f8, $f8, $f16           \r\n"
-        "packushb $f2, $f2, $f0         \r\n"
-        "packushb $f4, $f4, $f0         \r\n"
-        "packushb $f6, $f6, $f0         \r\n"
-        "packushb $f8, $f8, $f0         \r\n"
-        "swc1 $f2, 0(%[dst0])           \r\n"
-        "swc1 $f4, 0(%[dst1])           \r\n"
-        "swc1 $f6, 0(%[dst2])           \r\n"
-        "swc1 $f8, 0(%[dst3])           \r\n"
-        ::[dst0]"r"(dst),[dst1]"r"(dst+stride),[dst2]"r"(dst+2*stride),
-          [dst3]"r"(dst+3*stride),[src]"r"(src)
-        : "$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "ldc1       %[ftmp1],   0x00(%[src])                            \n\t"
+        "ldc1       %[ftmp2],   0x08(%[src])                            \n\t"
+        "ldc1       %[ftmp3],   0x10(%[src])                            \n\t"
+        "ldc1       %[ftmp4],   0x18(%[src])                            \n\t"
+        "uld        %[low32],   0x00(%[dst0])                           \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        "uld        %[low32],   0x00(%[dst1])                           \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        "uld        %[low32],   0x00(%[dst2])                           \n\t"
+        "mtc1       %[low32],   %[ftmp7]                                \n\t"
+        "uld        %[low32],   0x00(%[dst3])                           \n\t"
+        "mtc1       %[low32],   %[ftmp8]                                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp7],   %[ftmp7],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp8],   %[ftmp8],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp8]                \n\t"
+        "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[dst0])                           \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[dst0])                           \n\t"
+        "gsswlc1    %[ftmp2],   0x03(%[dst1])                           \n\t"
+        "gsswrc1    %[ftmp2],   0x00(%[dst1])                           \n\t"
+        "gsswlc1    %[ftmp3],   0x03(%[dst2])                           \n\t"
+        "gsswrc1    %[ftmp3],   0x00(%[dst2])                           \n\t"
+        "gsswlc1    %[ftmp4],   0x03(%[dst3])                           \n\t"
+        "gsswrc1    %[ftmp4],   0x00(%[dst3])                           \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),
+          [low32]"=&r"(low32)
+        : [dst0]"r"(dst),                   [dst1]"r"(dst+stride),
+          [dst2]"r"(dst+2*stride),          [dst3]"r"(dst+3*stride),
+          [src]"r"(src)
+        : "memory"
     );
 
     memset(src, 0, 32);
@@ -64,79 +83,94 @@ void ff_h264_add_pixels4_8_mmi(uint8_t *dst, int16_t *src, int stride)
 
 void ff_h264_idct_add_8_mmi(uint8_t *dst, int16_t *block, int stride)
 {
+    double ftmp[12];
+    uint64_t tmp[1];
+    uint64_t low32;
+
     __asm__ volatile (
-        "dli $8, 1                              \r\n"
-        "ldc1 $f0, 0(%[block])                  \r\n"
-        "dmtc1 $8, $f16                         \r\n"
-        "ldc1 $f2, 8(%[block])                  \r\n"
-        "dli $8, 6                              \r\n"
-        "ldc1 $f4, 16(%[block])                 \r\n"
-        "dmtc1 $8, $f18                         \r\n"
-        "psrah $f8, $f2, $f16                   \r\n"
-        "ldc1 $f6, 24(%[block])                 \r\n"
-        "psrah $f10, $f6, $f16                  \r\n"
-        "psubh $f8, $f8, $f6                    \r\n"
-        "paddh $f10, $f10, $f2                  \r\n"
-        "paddh $f20, $f4, $f0                   \r\n"
-        "psubh $f0, $f0, $f4                    \r\n"
-        "paddh $f22, $f10, $f20                 \r\n"
-        "psubh $f4, $f20, $f10                  \r\n"
-        "paddh $f20, $f8, $f0                   \r\n"
-        "psubh $f0, $f0, $f8                    \r\n"
-        "punpckhhw $f2, $f22, $f20              \r\n"
-        "punpcklhw $f10, $f22, $f20             \r\n"
-        "punpckhhw $f8, $f0, $f4                \r\n"
-        "punpcklhw $f0, $f0, $f4                \r\n"
-        "punpckhwd $f4, $f10, $f0               \r\n"
-        "punpcklwd $f10, $f10, $f0              \r\n"
-        "punpcklwd $f20, $f2, $f8               \r\n"
-        "punpckhwd $f0, $f2, $f8                \r\n"
-        "paddh $f10, $f10, %[ff_pw_32]          \r\n"
-        "psrah $f8, $f4, $f16                   \r\n"
-        "psrah $f6, $f0, $f16                   \r\n"
-        "psubh $f8, $f8, $f0                    \r\n"
-        "paddh $f6, $f6, $f4                    \r\n"
-        "paddh $f2, $f20, $f10                  \r\n"
-        "psubh $f10, $f10, $f20                 \r\n"
-        "paddh $f20, $f6, $f2                   \r\n"
-        "psubh $f2, $f2, $f6                    \r\n"
-        "paddh $f22, $f8, $f10                  \r\n"
-        "xor $f14, $f14, $f14                   \r\n"
-        "psubh $f10, $f10, $f8                  \r\n"
-        "sdc1 $f14, 0(%[block])                 \r\n"
-        "sdc1 $f14, 8(%[block])                 \r\n"
-        "sdc1 $f14, 16(%[block])                \r\n"
-        "sdc1 $f14, 24(%[block])                \r\n"
-        "lwc1 $f4, 0(%[dst])                    \r\n"
-        "psrah $f6, $f20, $f18                  \r\n"
-        "gslwxc1 $f0, 0(%[dst], %[stride])      \r\n"
-        "psrah $f8, $f22, $f18                  \r\n"
-        "punpcklbh $f4, $f4, $f14               \r\n"
-        "punpcklbh $f0, $f0, $f14               \r\n"
-        "paddh $f4, $f4, $f6                    \r\n"
-        "paddh $f0, $f0, $f8                    \r\n"
-        "packushb $f4, $f4, $f14                \r\n"
-        "packushb $f0, $f0, $f14                \r\n"
-        "swc1 $f4, 0(%[dst])                    \r\n"
-        "gsswxc1 $f0, 0(%[dst], %[stride])      \r\n"
-        "daddu %[dst], %[dst], %[stride]        \r\n"
-        "daddu %[dst], %[dst], %[stride]        \r\n"
-        "lwc1 $f4, 0(%[dst])                    \r\n"
-        "psrah $f10, $f10, $f18                 \r\n"
-        "gslwxc1 $f0, 0(%[dst], %[stride])      \r\n"
-        "psrah $f2, $f2, $f18                   \r\n"
-        "punpcklbh $f4, $f4, $f14               \r\n"
-        "punpcklbh $f0, $f0, $f14               \r\n"
-        "paddh $f4, $f4, $f10                   \r\n"
-        "paddh $f0, $f0, $f2                    \r\n"
-        "packushb $f4, $f4, $f14                \r\n"
-        "swc1 $f4, 0(%[dst])                    \r\n"
-        "packushb $f0, $f0, $f14                \r\n"
-        "gsswxc1 $f0, 0(%[dst], %[stride])      \r\n"
-        ::[dst]"r"(dst),[block]"r"(block),[stride]"r"((uint64_t)stride),
-          [ff_pw_32]"f"(ff_pw_32)
-        : "$8","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18","$f20","$f22"
+        "dli        %[tmp0],    0x01                                    \n\t"
+        "ldc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "mtc1       %[tmp0],    %[ftmp8]                                \n\t"
+        "ldc1       %[ftmp1],   0x08(%[block])                          \n\t"
+        "dli        %[tmp0],    0x06                                    \n\t"
+        "ldc1       %[ftmp2],   0x10(%[block])                          \n\t"
+        "mtc1       %[tmp0],    %[ftmp9]                                \n\t"
+        "psrah      %[ftmp4],   %[ftmp1],       %[ftmp8]                \n\t"
+        "ldc1       %[ftmp3],   0x18(%[block])                          \n\t"
+        "psrah      %[ftmp5],   %[ftmp3],       %[ftmp8]                \n\t"
+        "psubh      %[ftmp4],   %[ftmp4],       %[ftmp3]                \n\t"
+        "paddh      %[ftmp5],   %[ftmp5],       %[ftmp1]                \n\t"
+        "paddh      %[ftmp10],  %[ftmp2],       %[ftmp0]                \n\t"
+        "psubh      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp11],  %[ftmp5],       %[ftmp10]               \n\t"
+        "psubh      %[ftmp2],   %[ftmp10],      %[ftmp5]                \n\t"
+        "paddh      %[ftmp10],  %[ftmp4],       %[ftmp0]                \n\t"
+        "psubh      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp11],      %[ftmp10]               \n\t"
+        "punpcklhw  %[ftmp5],   %[ftmp11],      %[ftmp10]               \n\t"
+        "punpckhhw  %[ftmp4],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhwd  %[ftmp2],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklwd  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklwd  %[ftmp10],  %[ftmp1],       %[ftmp4]                \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp1],       %[ftmp4]                \n\t"
+        "paddh      %[ftmp5],   %[ftmp5],       %[ff_pw_32]             \n\t"
+        "psrah      %[ftmp4],   %[ftmp2],       %[ftmp8]                \n\t"
+        "psrah      %[ftmp3],   %[ftmp0],       %[ftmp8]                \n\t"
+        "psubh      %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp1],   %[ftmp10],      %[ftmp5]                \n\t"
+        "psubh      %[ftmp5],   %[ftmp5],       %[ftmp10]               \n\t"
+        "paddh      %[ftmp10],  %[ftmp3],       %[ftmp1]                \n\t"
+        "psubh      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "paddh      %[ftmp11],  %[ftmp4],       %[ftmp5]                \n\t"
+        "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "psubh      %[ftmp5],   %[ftmp5],       %[ftmp4]                \n\t"
+        "sdc1       %[ftmp7],   0x00(%[block])                          \n\t"
+        "sdc1       %[ftmp7],   0x08(%[block])                          \n\t"
+        "sdc1       %[ftmp7],   0x10(%[block])                          \n\t"
+        "sdc1       %[ftmp7],   0x18(%[block])                          \n\t"
+        "uld        %[low32],   0x00(%[dst])                            \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "psrah      %[ftmp3],   %[ftmp10],      %[ftmp9]                \n\t"
+        "gslwxc1    %[ftmp0],   0x00(%[dst],    %[stride])              \n\t"
+        "psrah      %[ftmp4],   %[ftmp11],      %[ftmp9]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "paddh      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "packushb   %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "packushb   %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "gsswlc1    %[ftmp2],   0x03(%[dst])                            \n\t"
+        "gsswrc1    %[ftmp2],   0x00(%[dst])                            \n\t"
+        "gsswxc1    %[ftmp0],   0x00(%[dst],    %[stride])              \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[stride]               \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[stride]               \n\t"
+        "uld        %[low32],   0x00(%[dst])                            \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "psrah      %[ftmp5],   %[ftmp5],       %[ftmp9]                \n\t"
+        "gslwxc1    %[ftmp0],   0x00(%[dst],    %[stride])              \n\t"
+        "psrah      %[ftmp1],   %[ftmp1],       %[ftmp9]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "paddh      %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "packushb   %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "gsswlc1    %[ftmp2],   0x03(%[dst])                            \n\t"
+        "gsswrc1    %[ftmp2],   0x00(%[dst])                            \n\t"
+        "packushb   %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "gsswxc1    %[ftmp0],   0x00(%[dst],    %[stride])              \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),          [ftmp11]"=&f"(ftmp[11]),
+          [tmp0]"=&r"(tmp[0]),
+          [low32]"=&r"(low32)
+        : [dst]"r"(dst),                    [block]"r"(block),
+          [stride]"r"((mips_reg)stride),    [ff_pw_32]"f"(ff_pw_32)
+        : "memory"
     );
 
     memset(block, 0, 32);
@@ -144,448 +178,482 @@ void ff_h264_idct_add_8_mmi(uint8_t *dst, int16_t *block, int stride)
 
 void ff_h264_idct8_add_8_mmi(uint8_t *dst, int16_t *block, int stride)
 {
+    double ftmp[16];
+    uint64_t tmp[8];
+    mips_reg addr[1];
+    uint64_t low32;
+
     __asm__ volatile (
-        "lhu $10, 0x0(%[block])                     \r\n"
-        "daddiu $29, $29, -0x20                     \r\n"
-        "daddiu $10, $10, 0x20                      \r\n"
-        "ldc1 $f2, 0x10(%[block])                   \r\n"
-        "sh $10, 0x0(%[block])                      \r\n"
-        "ldc1 $f4, 0x20(%[block])                   \r\n"
-        "dli $10, 0x1                               \r\n"
-        "ldc1 $f6, 0x30(%[block])                   \r\n"
-        "dmtc1 $10, $f16                            \r\n"
-        "ldc1 $f10, 0x50(%[block])                  \r\n"
-        "ldc1 $f12, 0x60(%[block])                  \r\n"
-        "ldc1 $f14, 0x70(%[block])                  \r\n"
-        "mov.d $f0, $f2                             \r\n"
-        "psrah $f2, $f2, $f16                       \r\n"
-        "psrah $f8, $f10, $f16                      \r\n"
-        "paddh $f2, $f2, $f0                        \r\n"
-        "paddh $f8, $f8, $f10                       \r\n"
-        "paddh $f2, $f2, $f10                       \r\n"
-        "paddh $f8, $f8, $f14                       \r\n"
-        "paddh $f2, $f2, $f6                        \r\n"
-        "psubh $f8, $f8, $f0                        \r\n"
-        "psubh $f0, $f0, $f6                        \r\n"
-        "psubh $f10, $f10, $f6                      \r\n"
-        "psrah $f6, $f6, $f16                       \r\n"
-        "paddh $f0, $f0, $f14                       \r\n"
-        "psubh $f10, $f10, $f14                     \r\n"
-        "psrah $f14, $f14, $f16                     \r\n"
-        "psubh $f0, $f0, $f6                        \r\n"
-        "dli $10, 0x2                               \r\n"
-        "psubh $f10, $f10, $f14                     \r\n"
-        "dmtc1 $10, $f18                            \r\n"
-        "mov.d $f14, $f2                            \r\n"
-        "psrah $f2, $f2, $f18                       \r\n"
-        "psrah $f6, $f8, $f18                       \r\n"
-        "paddh $f6, $f6, $f0                        \r\n"
-        "psrah $f0, $f0, $f18                       \r\n"
-        "paddh $f2, $f2, $f10                       \r\n"
-        "psrah $f10, $f10, $f18                     \r\n"
-        "psubh $f0, $f0, $f8                        \r\n"
-        "psubh $f14, $f14, $f10                     \r\n"
-        "mov.d $f10, $f12                           \r\n"
-        "psrah $f12, $f12, $f16                     \r\n"
-        "psrah $f8, $f4, $f16                       \r\n"
-        "paddh $f12, $f12, $f4                      \r\n"
-        "psubh $f8, $f8, $f10                       \r\n"
-        "ldc1 $f4, 0x0(%[block])                    \r\n"
-        "ldc1 $f10, 0x40(%[block])                  \r\n"
-        "paddh $f10, $f10, $f4                      \r\n"
-        "paddh $f4, $f4, $f4                        \r\n"
-        "paddh $f12, $f12, $f10                     \r\n"
-        "psubh $f4, $f4, $f10                       \r\n"
-        "paddh $f10, $f10, $f10                     \r\n"
-        "paddh $f8, $f8, $f4                        \r\n"
-        "psubh $f10, $f10, $f12                     \r\n"
-        "paddh $f4, $f4, $f4                        \r\n"
-        "paddh $f14, $f14, $f12                     \r\n"
-        "psubh $f4, $f4, $f8                        \r\n"
-        "paddh $f12, $f12, $f12                     \r\n"
-        "paddh $f0, $f0, $f8                        \r\n"
-        "psubh $f12, $f12, $f14                     \r\n"
-        "paddh $f8, $f8, $f8                        \r\n"
-        "paddh $f6, $f6, $f4                        \r\n"
-        "psubh $f8, $f8, $f0                        \r\n"
-        "paddh $f4, $f4, $f4                        \r\n"
-        "paddh $f2, $f2, $f10                       \r\n"
-        "psubh $f4, $f4, $f6                        \r\n"
-        "paddh $f10, $f10, $f10                     \r\n"
-        "sdc1 $f12, 0x0(%[block])                   \r\n"
-        "psubh $f10, $f10, $f2                      \r\n"
-        "punpckhhw $f12, $f14, $f0                  \r\n"
-        "punpcklhw $f14, $f14, $f0                  \r\n"
-        "punpckhhw $f0, $f6, $f2                    \r\n"
-        "punpcklhw $f6, $f6, $f2                    \r\n"
-        "punpckhwd $f2, $f14, $f6                   \r\n"
-        "punpcklwd $f14, $f14, $f6                  \r\n"
-        "punpckhwd $f6, $f12, $f0                   \r\n"
-        "punpcklwd $f12, $f12, $f0                  \r\n"
-        "ldc1 $f0, 0x0(%[block])                    \r\n"
-        "sdc1 $f14, 0x0($29)                        \r\n"
-        "sdc1 $f2, 0x10($29)                        \r\n"
-        "dmfc1 $8, $f12                             \r\n"
-        "dmfc1 $11, $f6                             \r\n"
-        "punpckhhw $f6, $f10, $f4                   \r\n"
-        "punpcklhw $f10, $f10, $f4                  \r\n"
-        "punpckhhw $f4, $f8, $f0                    \r\n"
-        "punpcklhw $f8, $f8, $f0                    \r\n"
-        "punpckhwd $f0, $f10, $f8                   \r\n"
-        "punpcklwd $f10, $f10, $f8                  \r\n"
-        "punpckhwd $f8, $f6, $f4                    \r\n"
-        "punpcklwd $f6, $f6, $f4                    \r\n"
-        "sdc1 $f10, 0x8($29)                        \r\n"
-        "sdc1 $f0, 0x18($29)                        \r\n"
-        "dmfc1 $9, $f6                              \r\n"
-        "dmfc1 $12, $f8                             \r\n"
-        "ldc1 $f2, 0x18(%[block])                   \r\n"
-        "ldc1 $f12, 0x28(%[block])                  \r\n"
-        "ldc1 $f4, 0x38(%[block])                   \r\n"
-        "ldc1 $f0, 0x58(%[block])                   \r\n"
-        "ldc1 $f6, 0x68(%[block])                   \r\n"
-        "ldc1 $f8, 0x78(%[block])                   \r\n"
-        "mov.d $f14, $f2                            \r\n"
-        "psrah $f10, $f0, $f16                      \r\n"
-        "psrah $f2, $f2, $f16                       \r\n"
-        "paddh $f10, $f10, $f0                      \r\n"
-        "paddh $f2, $f2, $f14                       \r\n"
-        "paddh $f10, $f10, $f8                      \r\n"
-        "paddh $f2, $f2, $f0                        \r\n"
-        "psubh $f10, $f10, $f14                     \r\n"
-        "paddh $f2, $f2, $f4                        \r\n"
-        "psubh $f14, $f14, $f4                      \r\n"
-        "psubh $f0, $f0, $f4                        \r\n"
-        "psrah $f4, $f4, $f16                       \r\n"
-        "paddh $f14, $f14, $f8                      \r\n"
-        "psubh $f0, $f0, $f8                        \r\n"
-        "psrah $f8, $f8, $f16                       \r\n"
-        "psubh $f14, $f14, $f4                      \r\n"
-        "psubh $f0, $f0, $f8                        \r\n"
-        "mov.d $f8, $f2                             \r\n"
-        "psrah $f4, $f10, $f18                      \r\n"
-        "psrah $f2, $f2, $f18                       \r\n"
-        "paddh $f4, $f4, $f14                       \r\n"
-        "psrah $f14, $f14, $f18                     \r\n"
-        "paddh $f2, $f2, $f0                        \r\n"
-        "psrah $f0, $f0, $f18                       \r\n"
-        "psubh $f14, $f14, $f10                     \r\n"
-        "psubh $f8, $f8, $f0                        \r\n"
-        "mov.d $f0, $f6                             \r\n"
-        "psrah $f6, $f6, $f16                       \r\n"
-        "psrah $f10, $f12, $f16                     \r\n"
-        "paddh $f6, $f6, $f12                       \r\n"
-        "psubh $f10, $f10, $f0                      \r\n"
-        "ldc1 $f12, 0x8(%[block])                   \r\n"
-        "ldc1 $f0, 0x48(%[block])                   \r\n"
-        "paddh $f0, $f0, $f12                       \r\n"
-        "paddh $f12, $f12, $f12                     \r\n"
-        "paddh $f6, $f6, $f0                        \r\n"
-        "psubh $f12, $f12, $f0                      \r\n"
-        "paddh $f0, $f0, $f0                        \r\n"
-        "paddh $f10, $f10, $f12                     \r\n"
-        "psubh $f0, $f0, $f6                        \r\n"
-        "paddh $f12, $f12, $f12                     \r\n"
-        "paddh $f8, $f8, $f6                        \r\n"
-        "psubh $f12, $f12, $f10                     \r\n"
-        "paddh $f6, $f6, $f6                        \r\n"
-        "paddh $f14, $f14, $f10                     \r\n"
-        "psubh $f6, $f6, $f8                        \r\n"
-        "paddh $f10, $f10, $f10                     \r\n"
-        "paddh $f4, $f4, $f12                       \r\n"
-        "psubh $f10, $f10, $f14                     \r\n"
-        "paddh $f12, $f12, $f12                     \r\n"
-        "paddh $f2, $f2, $f0                        \r\n"
-        "psubh $f12, $f12, $f4                      \r\n"
-        "paddh $f0, $f0, $f0                        \r\n"
-        "sdc1 $f6, 0x8(%[block])                    \r\n"
-        "psubh $f0, $f0, $f2                        \r\n"
-        "punpckhhw $f6, $f8, $f14                   \r\n"
-        "punpcklhw $f8, $f8, $f14                   \r\n"
-        "punpckhhw $f14, $f4, $f2                   \r\n"
-        "punpcklhw $f4, $f4, $f2                    \r\n"
-        "punpckhwd $f2, $f8, $f4                    \r\n"
-        "punpcklwd $f8, $f8, $f4                    \r\n"
-        "punpckhwd $f4, $f6, $f14                   \r\n"
-        "punpcklwd $f6, $f6, $f14                   \r\n"
-        "ldc1 $f14, 0x8(%[block])                   \r\n"
-        "dmfc1 $13, $f8                             \r\n"
-        "dmfc1 $15, $f2                             \r\n"
-        "mov.d $f24, $f6                            \r\n"
-        "mov.d $f28, $f4                            \r\n"
-        "punpckhhw $f4, $f0, $f12                   \r\n"
-        "punpcklhw $f0, $f0, $f12                   \r\n"
-        "punpckhhw $f12, $f10, $f14                 \r\n"
-        "punpcklhw $f10, $f10, $f14                 \r\n"
-        "punpckhwd $f14, $f0, $f10                  \r\n"
-        "punpcklwd $f0, $f0, $f10                   \r\n"
-        "punpckhwd $f10, $f4, $f12                  \r\n"
-        "punpcklwd $f4, $f4, $f12                   \r\n"
-        "dmfc1 $14, $f0                             \r\n"
-        "mov.d $f22, $f14                           \r\n"
-        "mov.d $f26, $f4                            \r\n"
-        "mov.d $f30, $f10                           \r\n"
-        "daddiu $10, %[dst], 0x4                    \r\n"
-        "dmtc1 $15, $f14                            \r\n"
-        "dmtc1 $11, $f12                            \r\n"
-        "ldc1 $f2, 0x10($29)                        \r\n"
-        "dmtc1 $8, $f6                              \r\n"
-        "mov.d $f8, $f2                             \r\n"
-        "psrah $f2, $f2, $f16                       \r\n"
-        "psrah $f0, $f14, $f16                      \r\n"
-        "paddh $f2, $f2, $f8                        \r\n"
-        "paddh $f0, $f0, $f14                       \r\n"
-        "paddh $f2, $f2, $f14                       \r\n"
-        "paddh $f0, $f0, $f28                       \r\n"
-        "paddh $f2, $f2, $f12                       \r\n"
-        "psubh $f0, $f0, $f8                        \r\n"
-        "psubh $f8, $f8, $f12                       \r\n"
-        "psubh $f14, $f14, $f12                     \r\n"
-        "psrah $f12, $f12, $f16                     \r\n"
-        "paddh $f8, $f8, $f28                       \r\n"
-        "psubh $f14, $f14, $f28                     \r\n"
-        "psrah $f10, $f28, $f16                     \r\n"
-        "psubh $f8, $f8, $f12                       \r\n"
-        "psubh $f14, $f14, $f10                     \r\n"
-        "mov.d $f10, $f2                            \r\n"
-        "psrah $f2, $f2, $f18                       \r\n"
-        "psrah $f12, $f0, $f18                      \r\n"
-        "paddh $f2, $f2, $f14                       \r\n"
-        "paddh $f12, $f12, $f8                      \r\n"
-        "psrah $f8, $f8, $f18                       \r\n"
-        "psrah $f14, $f14, $f18                     \r\n"
-        "psubh $f8, $f8, $f0                        \r\n"
-        "psubh $f10, $f10, $f14                     \r\n"
-        "mov.d $f14, $f24                           \r\n"
-        "psrah $f4, $f24, $f16                      \r\n"
-        "psrah $f0, $f6, $f16                       \r\n"
-        "paddh $f4, $f4, $f6                        \r\n"
-        "psubh $f0, $f0, $f14                       \r\n"
-        "ldc1 $f6, 0x0($29)                         \r\n"
-        "dmtc1 $13, $f14                            \r\n"
-        "paddh $f14, $f14, $f6                      \r\n"
-        "paddh $f6, $f6, $f6                        \r\n"
-        "paddh $f4, $f4, $f14                       \r\n"
-        "psubh $f6, $f6, $f14                       \r\n"
-        "paddh $f14, $f14, $f14                     \r\n"
-        "paddh $f0, $f0, $f6                        \r\n"
-        "psubh $f14, $f14, $f4                      \r\n"
-        "paddh $f6, $f6, $f6                        \r\n"
-        "paddh $f10, $f10, $f4                      \r\n"
-        "psubh $f6, $f6, $f0                        \r\n"
-        "paddh $f4, $f4, $f4                        \r\n"
-        "paddh $f8, $f8, $f0                        \r\n"
-        "psubh $f4, $f4, $f10                       \r\n"
-        "paddh $f0, $f0, $f0                        \r\n"
-        "paddh $f12, $f12, $f6                      \r\n"
-        "psubh $f0, $f0, $f8                        \r\n"
-        "paddh $f6, $f6, $f6                        \r\n"
-        "paddh $f2, $f2, $f14                       \r\n"
-        "psubh $f6, $f6, $f12                       \r\n"
-        "paddh $f14, $f14, $f14                     \r\n"
-        "sdc1 $f6, 0x0($29)                         \r\n"
-        "psubh $f14, $f14, $f2                      \r\n"
-        "sdc1 $f0, 0x10($29)                        \r\n"
-        "dmfc1 $8, $f4                              \r\n"
-        "xor $f4, $f4, $f4                          \r\n"
-        "sdc1 $f4, 0x0(%[block])                    \r\n"
-        "sdc1 $f4, 0x8(%[block])                    \r\n"
-        "sdc1 $f4, 0x10(%[block])                   \r\n"
-        "sdc1 $f4, 0x18(%[block])                   \r\n"
-        "sdc1 $f4, 0x20(%[block])                   \r\n"
-        "sdc1 $f4, 0x28(%[block])                   \r\n"
-        "sdc1 $f4, 0x30(%[block])                   \r\n"
-        "sdc1 $f4, 0x38(%[block])                   \r\n"
-        "sdc1 $f4, 0x40(%[block])                   \r\n"
-        "sdc1 $f4, 0x48(%[block])                   \r\n"
-        "sdc1 $f4, 0x50(%[block])                   \r\n"
-        "sdc1 $f4, 0x58(%[block])                   \r\n"
-        "sdc1 $f4, 0x60(%[block])                   \r\n"
-        "sdc1 $f4, 0x68(%[block])                   \r\n"
-        "sdc1 $f4, 0x70(%[block])                   \r\n"
-        "sdc1 $f4, 0x78(%[block])                   \r\n"
-        "dli $11, 0x6                               \r\n"
-        "lwc1 $f6, 0x0(%[dst])                      \r\n"
-        "dmtc1 $11, $f20                            \r\n"
-        "gslwxc1 $f0, 0x0(%[dst], %[stride])        \r\n"
-        "psrah $f10, $f10, $f20                     \r\n"
-        "psrah $f8, $f8, $f20                       \r\n"
-        "punpcklbh $f6, $f6, $f4                    \r\n"
-        "punpcklbh $f0, $f0, $f4                    \r\n"
-        "paddh $f6, $f6, $f10                       \r\n"
-        "paddh $f0, $f0, $f8                        \r\n"
-        "packushb $f6, $f6, $f4                     \r\n"
-        "packushb $f0, $f0, $f4                     \r\n"
-        "swc1 $f6, 0x0(%[dst])                      \r\n"
-        "gsswxc1 $f0, 0x0(%[dst], %[stride])        \r\n"
-        "daddu %[dst], %[dst], %[stride]            \r\n"
-        "daddu %[dst], %[dst], %[stride]            \r\n"
-        "lwc1 $f6, 0x0(%[dst])                      \r\n"
-        "gslwxc1 $f0, 0x0(%[dst], %[stride])        \r\n"
-        "psrah $f12, $f12, $f20                     \r\n"
-        "psrah $f2, $f2, $f20                       \r\n"
-        "punpcklbh $f6, $f6, $f4                    \r\n"
-        "punpcklbh $f0, $f0, $f4                    \r\n"
-        "paddh $f6, $f6, $f12                       \r\n"
-        "paddh $f0, $f0, $f2                        \r\n"
-        "packushb $f6, $f6, $f4                     \r\n"
-        "packushb $f0, $f0, $f4                     \r\n"
-        "swc1 $f6, 0x0(%[dst])                      \r\n"
-        "gsswxc1 $f0, 0x0(%[dst], %[stride])        \r\n"
-        "ldc1 $f10, 0x0($29)                        \r\n"
-        "ldc1 $f8, 0x10($29)                        \r\n"
-        "dmtc1 $8, $f12                             \r\n"
-        "daddu %[dst], %[dst], %[stride]            \r\n"
-        "daddu %[dst], %[dst], %[stride]            \r\n"
-        "lwc1 $f6, 0x0(%[dst])                      \r\n"
-        "gslwxc1 $f0, 0x0(%[dst], %[stride])        \r\n"
-        "psrah $f14, $f14, $f20                     \r\n"
-        "psrah $f10, $f10, $f20                     \r\n"
-        "punpcklbh $f6, $f6, $f4                    \r\n"
-        "punpcklbh $f0, $f0, $f4                    \r\n"
-        "paddh $f6, $f6, $f14                       \r\n"
-        "paddh $f0, $f0, $f10                       \r\n"
-        "packushb $f6, $f6, $f4                     \r\n"
-        "packushb $f0, $f0, $f4                     \r\n"
-        "swc1 $f6, 0x0(%[dst])                      \r\n"
-        "gsswxc1 $f0, 0x0(%[dst], %[stride])        \r\n"
-        "daddu %[dst], %[dst], %[stride]            \r\n"
-        "daddu %[dst], %[dst], %[stride]            \r\n"
-        "lwc1 $f6, 0x0(%[dst])                      \r\n"
-        "gslwxc1 $f0, 0x0(%[dst], %[stride])        \r\n"
-        "psrah $f8, $f8, $f20                       \r\n"
-        "psrah $f12, $f12, $f20                     \r\n"
-        "punpcklbh $f6, $f6, $f4                    \r\n"
-        "punpcklbh $f0, $f0, $f4                    \r\n"
-        "paddh $f6, $f6, $f8                        \r\n"
-        "paddh $f0, $f0, $f12                       \r\n"
-        "packushb $f6, $f6, $f4                     \r\n"
-        "packushb $f0, $f0, $f4                     \r\n"
-        "swc1 $f6, 0x0(%[dst])                      \r\n"
-        "gsswxc1 $f0, 0x0(%[dst], %[stride])        \r\n"
-        "dmtc1 $12, $f2                             \r\n"
-        "dmtc1 $9, $f12                             \r\n"
-        "ldc1 $f8, 0x18($29)                        \r\n"
-        "mov.d $f10, $f8                            \r\n"
-        "psrah $f8, $f8, $f16                       \r\n"
-        "psrah $f14, $f22, $f16                     \r\n"
-        "paddh $f14, $f14, $f22                     \r\n"
-        "paddh $f8, $f8, $f10                       \r\n"
-        "paddh $f14, $f14, $f30                     \r\n"
-        "paddh $f8, $f8, $f22                       \r\n"
-        "psubh $f14, $f14, $f10                     \r\n"
-        "paddh $f8, $f8, $f2                        \r\n"
-        "psubh $f10, $f10, $f2                      \r\n"
-        "psubh $f6, $f22, $f2                       \r\n"
-        "psrah $f2, $f2, $f16                       \r\n"
-        "paddh $f10, $f10, $f30                     \r\n"
-        "psubh $f6, $f6, $f30                       \r\n"
-        "psrah $f4, $f30, $f16                      \r\n"
-        "psubh $f10, $f10, $f2                      \r\n"
-        "psubh $f6, $f6, $f4                        \r\n"
-        "mov.d $f4, $f8                             \r\n"
-        "psrah $f8, $f8, $f18                       \r\n"
-        "psrah $f2, $f14, $f18                      \r\n"
-        "paddh $f8, $f8, $f6                        \r\n"
-        "paddh $f2, $f2, $f10                       \r\n"
-        "psrah $f10, $f10, $f18                     \r\n"
-        "psrah $f6, $f6, $f18                       \r\n"
-        "psubh $f10, $f10, $f14                     \r\n"
-        "psubh $f4, $f4, $f6                        \r\n"
-        "mov.d $f6, $f26                            \r\n"
-        "psrah $f0, $f26, $f16                      \r\n"
-        "psrah $f14, $f12, $f16                     \r\n"
-        "paddh $f0, $f0, $f12                       \r\n"
-        "psubh $f14, $f14, $f6                      \r\n"
-        "ldc1 $f12, 0x8($29)                        \r\n"
-        "dmtc1 $14, $f6                             \r\n"
-        "paddh $f6, $f6, $f12                       \r\n"
-        "paddh $f12, $f12, $f12                     \r\n"
-        "paddh $f0, $f0, $f6                        \r\n"
-        "psubh $f12, $f12, $f6                      \r\n"
-        "paddh $f6, $f6, $f6                        \r\n"
-        "paddh $f14, $f14, $f12                     \r\n"
-        "psubh $f6, $f6, $f0                        \r\n"
-        "paddh $f12, $f12, $f12                     \r\n"
-        "paddh $f4, $f4, $f0                        \r\n"
-        "psubh $f12, $f12, $f14                     \r\n"
-        "paddh $f0, $f0, $f0                        \r\n"
-        "paddh $f10, $f10, $f14                     \r\n"
-        "psubh $f0, $f0, $f4                        \r\n"
-        "paddh $f14, $f14, $f14                     \r\n"
-        "paddh $f2, $f2, $f12                       \r\n"
-        "psubh $f14, $f14, $f10                     \r\n"
-        "paddh $f12, $f12, $f12                     \r\n"
-        "paddh $f8, $f8, $f6                        \r\n"
-        "psubh $f12, $f12, $f2                      \r\n"
-        "paddh $f6, $f6, $f6                        \r\n"
-        "sdc1 $f12, 0x8($29)                        \r\n"
-        "psubh $f6, $f6, $f8                        \r\n"
-        "sdc1 $f14, 0x18($29)                       \r\n"
-        "dmfc1 $9, $f0                              \r\n"
-        "xor $f0, $f0, $f0                          \r\n"
-        "lwc1 $f12, 0x0($10)                        \r\n"
-        "gslwxc1 $f14, 0x0($10, %[stride])          \r\n"
-        "psrah $f4, $f4, $f20                       \r\n"
-        "psrah $f10, $f10, $f20                     \r\n"
-        "punpcklbh $f12, $f12, $f0                  \r\n"
-        "punpcklbh $f14, $f14, $f0                  \r\n"
-        "paddh $f12, $f12, $f4                      \r\n"
-        "paddh $f14, $f14, $f10                     \r\n"
-        "packushb $f12, $f12, $f0                   \r\n"
-        "packushb $f14, $f14, $f0                   \r\n"
-        "swc1 $f12, 0x0($10)                        \r\n"
-        "gsswxc1 $f14, 0x0($10, %[stride])          \r\n"
-        "daddu $10, $10, %[stride]                  \r\n"
-        "daddu $10, $10, %[stride]                  \r\n"
-        "lwc1 $f12, 0x0($10)                        \r\n"
-        "gslwxc1 $f14, 0x0($10, %[stride])          \r\n"
-        "psrah $f2, $f2, $f20                       \r\n"
-        "psrah $f8, $f8, $f20                       \r\n"
-        "punpcklbh $f12, $f12, $f0                  \r\n"
-        "punpcklbh $f14, $f14, $f0                  \r\n"
-        "paddh $f12, $f12, $f2                      \r\n"
-        "paddh $f14, $f14, $f8                      \r\n"
-        "packushb $f12, $f12, $f0                   \r\n"
-        "packushb $f14, $f14, $f0                   \r\n"
-        "swc1 $f12, 0x0($10)                        \r\n"
-        "gsswxc1 $f14, 0x0($10, %[stride])          \r\n"
-        "ldc1 $f4, 0x8($29)                         \r\n"
-        "ldc1 $f10, 0x18($29)                       \r\n"
-        "daddu $10, $10, %[stride]                  \r\n"
-        "dmtc1 $9, $f2                              \r\n"
-        "daddu $10, $10, %[stride]                  \r\n"
-        "lwc1 $f12, 0x0($10)                        \r\n"
-        "gslwxc1 $f14, 0x0($10, %[stride])          \r\n"
-        "psrah $f6, $f6, $f20                       \r\n"
-        "psrah $f4, $f4, $f20                       \r\n"
-        "punpcklbh $f12, $f12, $f0                  \r\n"
-        "punpcklbh $f14, $f14, $f0                  \r\n"
-        "paddh $f12, $f12, $f6                      \r\n"
-        "paddh $f14, $f14, $f4                      \r\n"
-        "packushb $f12, $f12, $f0                   \r\n"
-        "packushb $f14, $f14, $f0                   \r\n"
-        "swc1 $f12, 0x0($10)                        \r\n"
-        "gsswxc1 $f14, 0x0($10, %[stride])          \r\n"
-        "daddu $10, $10, %[stride]                  \r\n"
-        "daddu $10, $10, %[stride]                  \r\n"
-        "lwc1 $f12, 0x0($10)                        \r\n"
-        "gslwxc1 $f14, 0x0($10, %[stride])          \r\n"
-        "psrah $f10, $f10, $f20                     \r\n"
-        "psrah $f2, $f2, $f20                       \r\n"
-        "punpcklbh $f12, $f12, $f0                  \r\n"
-        "punpcklbh $f14, $f14, $f0                  \r\n"
-        "paddh $f12, $f12, $f10                     \r\n"
-        "paddh $f14, $f14, $f2                      \r\n"
-        "packushb $f12, $f12, $f0                   \r\n"
-        "packushb $f14, $f14, $f0                   \r\n"
-        "swc1 $f12, 0x0($10)                        \r\n"
-        "gsswxc1 $f14, 0x0($10, %[stride])          \r\n"
-        "daddiu $29, $29, 0x20                      \r\n"
-        ::[dst]"r"(dst),[block]"r"(block),[stride]"r"((uint64_t)stride)
-        :"$8","$9","$10","$11","$12","$13","$14","$15","$29","$f0","$f2","$f4",
-         "$f8","$f10","$f12","$f14","$f16","$f18","$f20","$f22","$f24","$f26",
-         "$f28","$f30"
+        "lhu       %[tmp0],     0x00(%[block])                          \n\t"
+        PTR_ADDI  "$29,         $29,            -0x20                   \n\t"
+        PTR_ADDIU "%[tmp0],     %[tmp0],        0x20                    \n\t"
+        "ldc1      %[ftmp1],    0x10(%[block])                          \n\t"
+        "sh        %[tmp0],     0x00(%[block])                          \n\t"
+        "ldc1      %[ftmp2],    0x20(%[block])                          \n\t"
+        "dli       %[tmp0],     0x01                                    \n\t"
+        "ldc1      %[ftmp3],    0x30(%[block])                          \n\t"
+        "mtc1      %[tmp0],     %[ftmp8]                                \n\t"
+        "ldc1      %[ftmp5],    0x50(%[block])                          \n\t"
+        "ldc1      %[ftmp6],    0x60(%[block])                          \n\t"
+        "ldc1      %[ftmp7],    0x70(%[block])                          \n\t"
+        "mov.d     %[ftmp0],    %[ftmp1]                                \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp8]                \n\t"
+        "psrah     %[ftmp4],    %[ftmp5],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp3]                \n\t"
+        "psubh     %[ftmp4],    %[ftmp4],       %[ftmp0]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp3]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp3]                \n\t"
+        "psrah     %[ftmp3],    %[ftmp3],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp7]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp7]                \n\t"
+        "psrah     %[ftmp7],    %[ftmp7],       %[ftmp8]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp3]                \n\t"
+        "dli       %[tmp0],     0x02                                    \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp7]                \n\t"
+        "mtc1      %[tmp0],     %[ftmp9]                                \n\t"
+        "mov.d     %[ftmp7],    %[ftmp1]                                \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp9]                \n\t"
+        "psrah     %[ftmp3],    %[ftmp4],       %[ftmp9]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp0]                \n\t"
+        "psrah     %[ftmp0],    %[ftmp0],       %[ftmp9]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp5]                \n\t"
+        "psrah     %[ftmp5],    %[ftmp5],       %[ftmp9]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp4]                \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp5]                \n\t"
+        "mov.d     %[ftmp5],    %[ftmp6]                                \n\t"
+        "psrah     %[ftmp6],    %[ftmp6],       %[ftmp8]                \n\t"
+        "psrah     %[ftmp4],    %[ftmp2],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp2]                \n\t"
+        "psubh     %[ftmp4],    %[ftmp4],       %[ftmp5]                \n\t"
+        "ldc1      %[ftmp2],    0x00(%[block])                          \n\t"
+        "ldc1      %[ftmp5],    0x40(%[block])                          \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp2],    %[ftmp2],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp5]                \n\t"
+        "psubh     %[ftmp2],    %[ftmp2],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp2]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp2],    %[ftmp2],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp2],    %[ftmp2],       %[ftmp4]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp4]                \n\t"
+        "psubh     %[ftmp6],    %[ftmp6],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp4]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "psubh     %[ftmp4],    %[ftmp4],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp2],    %[ftmp2],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp5]                \n\t"
+        "psubh     %[ftmp2],    %[ftmp2],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp5]                \n\t"
+        "sdc1      %[ftmp6],    0x00(%[block])                          \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp1]                \n\t"
+        "punpckhhw %[ftmp6],    %[ftmp7],       %[ftmp0]                \n\t"
+        "punpcklhw %[ftmp7],    %[ftmp7],       %[ftmp0]                \n\t"
+        "punpckhhw %[ftmp0],    %[ftmp3],       %[ftmp1]                \n\t"
+        "punpcklhw %[ftmp3],    %[ftmp3],       %[ftmp1]                \n\t"
+        "punpckhwd %[ftmp1],    %[ftmp7],       %[ftmp3]                \n\t"
+        "punpcklwd %[ftmp7],    %[ftmp7],       %[ftmp3]                \n\t"
+        "punpckhwd %[ftmp3],    %[ftmp6],       %[ftmp0]                \n\t"
+        "punpcklwd %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "ldc1      %[ftmp0],    0x00(%[block])                          \n\t"
+        "sdc1      %[ftmp7],    0x00($29)                               \n\t"
+        "sdc1      %[ftmp1],    0x10($29)                               \n\t"
+        "dmfc1     %[tmp1],     %[ftmp6]                                \n\t"
+        "dmfc1     %[tmp3],     %[ftmp3]                                \n\t"
+        "punpckhhw %[ftmp3],    %[ftmp5],       %[ftmp2]                \n\t"
+        "punpcklhw %[ftmp5],    %[ftmp5],       %[ftmp2]                \n\t"
+        "punpckhhw %[ftmp2],    %[ftmp4],       %[ftmp0]                \n\t"
+        "punpcklhw %[ftmp4],    %[ftmp4],       %[ftmp0]                \n\t"
+        "punpckhwd %[ftmp0],    %[ftmp5],       %[ftmp4]                \n\t"
+        "punpcklwd %[ftmp5],    %[ftmp5],       %[ftmp4]                \n\t"
+        "punpckhwd %[ftmp4],    %[ftmp3],       %[ftmp2]                \n\t"
+        "punpcklwd %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "sdc1      %[ftmp5],    0x08($29)                               \n\t"
+        "sdc1      %[ftmp0],    0x18($29)                               \n\t"
+        "dmfc1     %[tmp2],     %[ftmp3]                                \n\t"
+        "dmfc1     %[tmp4],     %[ftmp4]                                \n\t"
+        "ldc1      %[ftmp1],    0x18(%[block])                          \n\t"
+        "ldc1      %[ftmp6],    0x28(%[block])                          \n\t"
+        "ldc1      %[ftmp2],    0x38(%[block])                          \n\t"
+        "ldc1      %[ftmp0],    0x58(%[block])                          \n\t"
+        "ldc1      %[ftmp3],    0x68(%[block])                          \n\t"
+        "ldc1      %[ftmp4],    0x78(%[block])                          \n\t"
+        "mov.d     %[ftmp7],    %[ftmp1]                                \n\t"
+        "psrah     %[ftmp5],    %[ftmp0],       %[ftmp8]                \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp4]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp0]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp2]                \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp2]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "psrah     %[ftmp2],    %[ftmp2],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp4]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp4]                \n\t"
+        "psrah     %[ftmp4],    %[ftmp4],       %[ftmp8]                \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp2]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp4]                \n\t"
+        "mov.d     %[ftmp4],    %[ftmp1]                                \n\t"
+        "psrah     %[ftmp2],    %[ftmp5],       %[ftmp9]                \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp9]                \n\t"
+        "paddh     %[ftmp2],    %[ftmp2],       %[ftmp7]                \n\t"
+        "psrah     %[ftmp7],    %[ftmp7],       %[ftmp9]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp0]                \n\t"
+        "psrah     %[ftmp0],    %[ftmp0],       %[ftmp9]                \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp5]                \n\t"
+        "psubh     %[ftmp4],    %[ftmp4],       %[ftmp0]                \n\t"
+        "mov.d     %[ftmp0],    %[ftmp3]                                \n\t"
+        "psrah     %[ftmp3],    %[ftmp3],       %[ftmp8]                \n\t"
+        "psrah     %[ftmp5],    %[ftmp6],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp0]                \n\t"
+        "ldc1      %[ftmp6],    0x08(%[block])                          \n\t"
+        "ldc1      %[ftmp0],    0x48(%[block])                          \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp0]                \n\t"
+        "psubh     %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp3]                \n\t"
+        "psubh     %[ftmp6],    %[ftmp6],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp5]                \n\t"
+        "psubh     %[ftmp3],    %[ftmp3],       %[ftmp4]                \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp2],    %[ftmp2],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp0]                \n\t"
+        "psubh     %[ftmp6],    %[ftmp6],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp0]                \n\t"
+        "sdc1      %[ftmp3],    0x08(%[block])                          \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp1]                \n\t"
+        "punpckhhw %[ftmp3],    %[ftmp4],       %[ftmp7]                \n\t"
+        "punpcklhw %[ftmp4],    %[ftmp4],       %[ftmp7]                \n\t"
+        "punpckhhw %[ftmp7],    %[ftmp2],       %[ftmp1]                \n\t"
+        "punpcklhw %[ftmp2],    %[ftmp2],       %[ftmp1]                \n\t"
+        "punpckhwd %[ftmp1],    %[ftmp4],       %[ftmp2]                \n\t"
+        "punpcklwd %[ftmp4],    %[ftmp4],       %[ftmp2]                \n\t"
+        "punpckhwd %[ftmp2],    %[ftmp3],       %[ftmp7]                \n\t"
+        "punpcklwd %[ftmp3],    %[ftmp3],       %[ftmp7]                \n\t"
+        "ldc1      %[ftmp7],    0x08(%[block])                          \n\t"
+        "dmfc1     %[tmp5],     %[ftmp4]                                \n\t"
+        "dmfc1     %[tmp7],     %[ftmp1]                                \n\t"
+        "mov.d     %[ftmp12],   %[ftmp3]                                \n\t"
+        "mov.d     %[ftmp14],   %[ftmp2]                                \n\t"
+        "punpckhhw %[ftmp2],    %[ftmp0],       %[ftmp6]                \n\t"
+        "punpcklhw %[ftmp0],    %[ftmp0],       %[ftmp6]                \n\t"
+        "punpckhhw %[ftmp6],    %[ftmp5],       %[ftmp7]                \n\t"
+        "punpcklhw %[ftmp5],    %[ftmp5],       %[ftmp7]                \n\t"
+        "punpckhwd %[ftmp7],    %[ftmp0],       %[ftmp5]                \n\t"
+        "punpcklwd %[ftmp0],    %[ftmp0],       %[ftmp5]                \n\t"
+        "punpckhwd %[ftmp5],    %[ftmp2],       %[ftmp6]                \n\t"
+        "punpcklwd %[ftmp2],    %[ftmp2],       %[ftmp6]                \n\t"
+        "dmfc1     %[tmp6],     %[ftmp0]                                \n\t"
+        "mov.d     %[ftmp11],   %[ftmp7]                                \n\t"
+        "mov.d     %[ftmp13],   %[ftmp2]                                \n\t"
+        "mov.d     %[ftmp15],   %[ftmp5]                                \n\t"
+        PTR_ADDIU "%[addr0],    %[dst],         0x04                    \n\t"
+        "dmtc1     %[tmp7],     %[ftmp7]                                \n\t"
+        "dmtc1     %[tmp3],     %[ftmp6]                                \n\t"
+        "ldc1      %[ftmp1],    0x10($29)                               \n\t"
+        "dmtc1     %[tmp1],     %[ftmp3]                                \n\t"
+        "mov.d     %[ftmp4],    %[ftmp1]                                \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp8]                \n\t"
+        "psrah     %[ftmp0],    %[ftmp7],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp4]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp14]               \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp4]                \n\t"
+        "psubh     %[ftmp4],    %[ftmp4],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp6]                \n\t"
+        "psrah     %[ftmp6],    %[ftmp6],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp14]               \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp14]               \n\t"
+        "psrah     %[ftmp5],    %[ftmp14],      %[ftmp8]                \n\t"
+        "psubh     %[ftmp4],    %[ftmp4],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp5]                \n\t"
+        "mov.d     %[ftmp5],    %[ftmp1]                                \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp9]                \n\t"
+        "psrah     %[ftmp6],    %[ftmp0],       %[ftmp9]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp4]                \n\t"
+        "psrah     %[ftmp4],    %[ftmp4],       %[ftmp9]                \n\t"
+        "psrah     %[ftmp7],    %[ftmp7],       %[ftmp9]                \n\t"
+        "psubh     %[ftmp4],    %[ftmp4],       %[ftmp0]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp7]                \n\t"
+        "mov.d     %[ftmp7],    %[ftmp12]                               \n\t"
+        "psrah     %[ftmp2],    %[ftmp12],      %[ftmp8]                \n\t"
+        "psrah     %[ftmp0],    %[ftmp3],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp2],    %[ftmp2],       %[ftmp3]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp7]                \n\t"
+        "ldc1      %[ftmp3],    0x00($29)                               \n\t"
+        "dmtc1     %[tmp5],     %[ftmp7]                                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp2],    %[ftmp2],       %[ftmp7]                \n\t"
+        "psubh     %[ftmp3],    %[ftmp3],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp3]                \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp2]                \n\t"
+        "psubh     %[ftmp3],    %[ftmp3],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp2],    %[ftmp2],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp0]                \n\t"
+        "psubh     %[ftmp2],    %[ftmp2],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp3]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp4]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp7]                \n\t"
+        "psubh     %[ftmp3],    %[ftmp3],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp7]                \n\t"
+        "sdc1      %[ftmp3],    0x00($29)                               \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp1]                \n\t"
+        "sdc1      %[ftmp0],    0x10($29)                               \n\t"
+        "dmfc1     %[tmp1],     %[ftmp2]                                \n\t"
+        "xor       %[ftmp2],    %[ftmp2],       %[ftmp2]                \n\t"
+        "sdc1      %[ftmp2],    0x00(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x08(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x10(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x18(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x20(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x28(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x30(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x38(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x40(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x48(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x50(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x58(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x60(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x68(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x70(%[block])                          \n\t"
+        "sdc1      %[ftmp2],    0x78(%[block])                          \n\t"
+        "dli       %[tmp3],     0x06                                    \n\t"
+        "uld       %[low32],    0x00(%[dst])                            \n\t"
+        "mtc1      %[low32],    %[ftmp3]                                \n\t"
+        "mtc1      %[tmp3],     %[ftmp10]                               \n\t"
+        "gslwxc1   %[ftmp0],    0x00(%[dst],    %[stride])              \n\t"
+        "psrah     %[ftmp5],    %[ftmp5],       %[ftmp10]               \n\t"
+        "psrah     %[ftmp4],    %[ftmp4],       %[ftmp10]               \n\t"
+        "punpcklbh %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "punpcklbh %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp4]                \n\t"
+        "packushb  %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "packushb  %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "gsswlc1   %[ftmp3],    0x03(%[dst])                            \n\t"
+        "gsswrc1   %[ftmp3],    0x00(%[dst])                            \n\t"
+        "gsswxc1   %[ftmp0],    0x00(%[dst],    %[stride])              \n\t"
+        PTR_ADDU  "%[dst],      %[dst],         %[stride]               \n\t"
+        PTR_ADDU  "%[dst],      %[dst],         %[stride]               \n\t"
+        "uld       %[low32],    0x00(%[dst])                            \n\t"
+        "mtc1      %[low32],    %[ftmp3]                                \n\t"
+        "gslwxc1   %[ftmp0],    0x00(%[dst],    %[stride])              \n\t"
+        "psrah     %[ftmp6],    %[ftmp6],       %[ftmp10]               \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp10]               \n\t"
+        "punpcklbh %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "punpcklbh %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp1]                \n\t"
+        "packushb  %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "packushb  %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "gsswlc1   %[ftmp3],    0x03(%[dst])                            \n\t"
+        "gsswrc1   %[ftmp3],    0x00(%[dst])                            \n\t"
+        "gsswxc1   %[ftmp0],    0x00(%[dst],    %[stride])              \n\t"
+        "ldc1      %[ftmp5],    0x00($29)                               \n\t"
+        "ldc1      %[ftmp4],    0x10($29)                               \n\t"
+        "dmtc1     %[tmp1],     %[ftmp6]                                \n\t"
+        PTR_ADDU  "%[dst],      %[dst],         %[stride]               \n\t"
+        PTR_ADDU  "%[dst],      %[dst],         %[stride]               \n\t"
+        "uld       %[low32],    0x00(%[dst])                            \n\t"
+        "mtc1      %[low32],    %[ftmp3]                                \n\t"
+        "gslwxc1   %[ftmp0],    0x00(%[dst],    %[stride])              \n\t"
+        "psrah     %[ftmp7],    %[ftmp7],       %[ftmp10]               \n\t"
+        "psrah     %[ftmp5],    %[ftmp5],       %[ftmp10]               \n\t"
+        "punpcklbh %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "punpcklbh %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp5]                \n\t"
+        "packushb  %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "packushb  %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "gsswlc1   %[ftmp3],    0x03(%[dst])                            \n\t"
+        "gsswrc1   %[ftmp3],    0x00(%[dst])                            \n\t"
+        "gsswxc1   %[ftmp0],    0x00(%[dst],    %[stride])              \n\t"
+        PTR_ADDU  "%[dst],      %[dst],         %[stride]               \n\t"
+        PTR_ADDU  "%[dst],      %[dst],         %[stride]               \n\t"
+        "uld       %[low32],    0x00(%[dst])                            \n\t"
+        "mtc1      %[low32],    %[ftmp3]                                \n\t"
+        "gslwxc1   %[ftmp0],    0x00(%[dst],    %[stride])              \n\t"
+        "psrah     %[ftmp4],    %[ftmp4],       %[ftmp10]               \n\t"
+        "psrah     %[ftmp6],    %[ftmp6],       %[ftmp10]               \n\t"
+        "punpcklbh %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "punpcklbh %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp4]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp6]                \n\t"
+        "packushb  %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "packushb  %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "gsswlc1   %[ftmp3],    0x03(%[dst])                            \n\t"
+        "gsswrc1   %[ftmp3],    0x00(%[dst])                            \n\t"
+        "gsswxc1   %[ftmp0],    0x00(%[dst],    %[stride])              \n\t"
+        "dmtc1     %[tmp4],     %[ftmp1]                                \n\t"
+        "dmtc1     %[tmp2],     %[ftmp6]                                \n\t"
+        "ldc1      %[ftmp4],    0x18($29)                               \n\t"
+        "mov.d     %[ftmp5],    %[ftmp4]                                \n\t"
+        "psrah     %[ftmp4],    %[ftmp4],       %[ftmp8]                \n\t"
+        "psrah     %[ftmp7],    %[ftmp11],      %[ftmp8]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp11]               \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp15]               \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp11]               \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp1]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp1]                \n\t"
+        "psubh     %[ftmp3],    %[ftmp11],      %[ftmp1]                \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp15]               \n\t"
+        "psubh     %[ftmp3],    %[ftmp3],       %[ftmp15]               \n\t"
+        "psrah     %[ftmp2],    %[ftmp15],      %[ftmp8]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp1]                \n\t"
+        "psubh     %[ftmp3],    %[ftmp3],       %[ftmp2]                \n\t"
+        "mov.d     %[ftmp2],    %[ftmp4]                                \n\t"
+        "psrah     %[ftmp4],    %[ftmp4],       %[ftmp9]                \n\t"
+        "psrah     %[ftmp1],    %[ftmp7],       %[ftmp9]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp5]                \n\t"
+        "psrah     %[ftmp5],    %[ftmp5],       %[ftmp9]                \n\t"
+        "psrah     %[ftmp3],    %[ftmp3],       %[ftmp9]                \n\t"
+        "psubh     %[ftmp5],    %[ftmp5],       %[ftmp7]                \n\t"
+        "psubh     %[ftmp2],    %[ftmp2],       %[ftmp3]                \n\t"
+        "mov.d     %[ftmp3],    %[ftmp13]                               \n\t"
+        "psrah     %[ftmp0],    %[ftmp13],      %[ftmp8]                \n\t"
+        "psrah     %[ftmp7],    %[ftmp6],       %[ftmp8]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp3]                \n\t"
+        "ldc1      %[ftmp6],    0x08($29)                               \n\t"
+        "dmtc1     %[tmp6],     %[ftmp3]                                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp3]                \n\t"
+        "psubh     %[ftmp6],    %[ftmp6],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp3],    %[ftmp3],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp2],    %[ftmp2],       %[ftmp0]                \n\t"
+        "psubh     %[ftmp6],    %[ftmp6],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp0],    %[ftmp0],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp5],    %[ftmp5],       %[ftmp7]                \n\t"
+        "psubh     %[ftmp0],    %[ftmp0],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp7]                \n\t"
+        "paddh     %[ftmp1],    %[ftmp1],       %[ftmp6]                \n\t"
+        "psubh     %[ftmp7],    %[ftmp7],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp6]                \n\t"
+        "paddh     %[ftmp4],    %[ftmp4],       %[ftmp3]                \n\t"
+        "psubh     %[ftmp6],    %[ftmp6],       %[ftmp1]                \n\t"
+        "paddh     %[ftmp3],    %[ftmp3],       %[ftmp3]                \n\t"
+        "sdc1      %[ftmp6],    0x08($29)                               \n\t"
+        "psubh     %[ftmp3],    %[ftmp3],       %[ftmp4]                \n\t"
+        "sdc1      %[ftmp7],    0x18($29)                               \n\t"
+        "dmfc1     %[tmp2],     %[ftmp0]                                \n\t"
+        "xor       %[ftmp0],    %[ftmp0],       %[ftmp0]                \n\t"
+        "uld       %[low32],    0x00(%[addr0])                          \n\t"
+        "mtc1      %[low32],    %[ftmp6]                                \n\t"
+        "gslwxc1   %[ftmp7],    0x00(%[addr0],  %[stride])              \n\t"
+        "psrah     %[ftmp2],    %[ftmp2],       %[ftmp10]               \n\t"
+        "psrah     %[ftmp5],    %[ftmp5],       %[ftmp10]               \n\t"
+        "punpcklbh %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "punpcklbh %[ftmp7],    %[ftmp7],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp2]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp5]                \n\t"
+        "packushb  %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "packushb  %[ftmp7],    %[ftmp7],       %[ftmp0]                \n\t"
+        "gsswlc1   %[ftmp6],    0x03(%[addr0])                          \n\t"
+        "gsswrc1   %[ftmp6],    0x00(%[addr0])                          \n\t"
+        "gsswxc1   %[ftmp7],    0x00(%[addr0],  %[stride])              \n\t"
+        PTR_ADDU  "%[addr0],    %[addr0],       %[stride]               \n\t"
+        PTR_ADDU  "%[addr0],    %[addr0],       %[stride]               \n\t"
+        "uld       %[low32],    0x00(%[addr0])                          \n\t"
+        "mtc1      %[low32],    %[ftmp6]                                \n\t"
+        "gslwxc1   %[ftmp7],    0x00(%[addr0],  %[stride])              \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp10]               \n\t"
+        "psrah     %[ftmp4],    %[ftmp4],       %[ftmp10]               \n\t"
+        "punpcklbh %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "punpcklbh %[ftmp7],    %[ftmp7],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp1]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp4]                \n\t"
+        "packushb  %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "packushb  %[ftmp7],    %[ftmp7],       %[ftmp0]                \n\t"
+        "gsswlc1   %[ftmp6],    0x03(%[addr0])                          \n\t"
+        "gsswrc1   %[ftmp6],    0x00(%[addr0])                          \n\t"
+        "gsswxc1   %[ftmp7],    0x00(%[addr0],  %[stride])              \n\t"
+        "ldc1      %[ftmp2],    0x08($29)                               \n\t"
+        "ldc1      %[ftmp5],    0x18($29)                               \n\t"
+        PTR_ADDU  "%[addr0],    %[addr0],       %[stride]               \n\t"
+        "dmtc1     %[tmp2],     %[ftmp1]                                \n\t"
+        PTR_ADDU  "%[addr0],    %[addr0],       %[stride]               \n\t"
+        "uld       %[low32],    0x00(%[addr0])                          \n\t"
+        "mtc1      %[low32],    %[ftmp6]                                \n\t"
+        "gslwxc1   %[ftmp7],    0x00(%[addr0],  %[stride])              \n\t"
+        "psrah     %[ftmp3],    %[ftmp3],       %[ftmp10]               \n\t"
+        "psrah     %[ftmp2],    %[ftmp2],       %[ftmp10]               \n\t"
+        "punpcklbh %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "punpcklbh %[ftmp7],    %[ftmp7],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp3]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp2]                \n\t"
+        "packushb  %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "packushb  %[ftmp7],    %[ftmp7],       %[ftmp0]                \n\t"
+        "gsswlc1   %[ftmp6],    0x03(%[addr0])                          \n\t"
+        "gsswrc1   %[ftmp6],    0x00(%[addr0])                          \n\t"
+        "gsswxc1   %[ftmp7],    0x00(%[addr0],  %[stride])              \n\t"
+        PTR_ADDU  "%[addr0],    %[addr0],       %[stride]               \n\t"
+        PTR_ADDU  "%[addr0],    %[addr0],       %[stride]               \n\t"
+        "uld       %[low32],    0x00(%[addr0])                          \n\t"
+        "mtc1      %[low32],    %[ftmp6]                                \n\t"
+        "gslwxc1   %[ftmp7],    0x00(%[addr0],  %[stride])              \n\t"
+        "psrah     %[ftmp5],    %[ftmp5],       %[ftmp10]               \n\t"
+        "psrah     %[ftmp1],    %[ftmp1],       %[ftmp10]               \n\t"
+        "punpcklbh %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "punpcklbh %[ftmp7],    %[ftmp7],       %[ftmp0]                \n\t"
+        "paddh     %[ftmp6],    %[ftmp6],       %[ftmp5]                \n\t"
+        "paddh     %[ftmp7],    %[ftmp7],       %[ftmp1]                \n\t"
+        "packushb  %[ftmp6],    %[ftmp6],       %[ftmp0]                \n\t"
+        "packushb  %[ftmp7],    %[ftmp7],       %[ftmp0]                \n\t"
+        "gsswlc1   %[ftmp6],    0x03(%[addr0])                          \n\t"
+        "gsswrc1   %[ftmp6],    0x00(%[addr0])                          \n\t"
+        "gsswxc1   %[ftmp7],    0x00(%[addr0],  %[stride])              \n\t"
+        PTR_ADDIU "$29,         $29,            0x20                    \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),          [ftmp11]"=&f"(ftmp[11]),
+          [ftmp12]"=&f"(ftmp[12]),          [ftmp13]"=&f"(ftmp[13]),
+          [ftmp14]"=&f"(ftmp[14]),          [ftmp15]"=&f"(ftmp[15]),
+          [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [tmp2]"=&r"(tmp[2]),              [tmp3]"=&r"(tmp[3]),
+          [tmp4]"=&r"(tmp[4]),              [tmp5]"=&r"(tmp[5]),
+          [tmp6]"=&r"(tmp[6]),              [tmp7]"=&r"(tmp[7]),
+          [addr0]"=&r"(addr[0]),
+          [low32]"=&r"(low32)
+        : [dst]"r"(dst),                    [block]"r"(block),
+          [stride]"r"((mips_reg)stride)
+        : "$29","memory"
     );
 
     memset(block, 0, 128);
@@ -593,91 +661,134 @@ void ff_h264_idct8_add_8_mmi(uint8_t *dst, int16_t *block, int stride)
 
 void ff_h264_idct_dc_add_8_mmi(uint8_t *dst, int16_t *block, int stride)
 {
+    int dc = (block[0] + 32) >> 6;
+    double ftmp[6];
+    uint64_t low32;
+
+    block[0] = 0;
+
     __asm__ volatile (
-        "lh $8, 0x0(%[block])                       \r\n"
-        "sd $0, 0x0(%[block])                       \r\n"
-        "daddiu $8, $8, 0x20                        \r\n"
-        "daddu $10, %[stride], %[stride]            \r\n"
-        "dsra $8, $8, 0x6                           \r\n"
-        "xor $f2, $f2, $f2                          \r\n"
-        "mtc1 $8, $f0                               \r\n"
-        "pshufh $f0, $f0, $f2                       \r\n"
-        "daddu $8, $10, %[stride]                   \r\n"
-        "psubh $f2, $f2, $f0                        \r\n"
-        "packushb $f0, $f0, $f0                     \r\n"
-        "packushb $f2, $f2, $f2                     \r\n"
-        "lwc1 $f4, 0x0(%[dst])                      \r\n"
-        "gslwxc1 $f6, 0x0(%[dst], %[stride])        \r\n"
-        "gslwxc1 $f8, 0x0(%[dst], $10)              \r\n"
-        "gslwxc1 $f10, 0x0(%[dst], $8)              \r\n"
-        "paddusb $f4, $f4, $f0                      \r\n"
-        "paddusb $f6, $f6, $f0                      \r\n"
-        "paddusb $f8, $f8, $f0                      \r\n"
-        "paddusb $f10, $f10, $f0                    \r\n"
-        "psubusb $f4, $f4, $f2                      \r\n"
-        "psubusb $f6, $f6, $f2                      \r\n"
-        "psubusb $f8, $f8, $f2                      \r\n"
-        "psubusb $f10, $f10, $f2                    \r\n"
-        "swc1 $f4, 0x0(%[dst])                      \r\n"
-        "gsswxc1 $f6, 0x0(%[dst], %[stride])        \r\n"
-        "gsswxc1 $f8, 0x0(%[dst], $10)              \r\n"
-        "gsswxc1 $f10, 0x0(%[dst], $8)              \r\n"
-        ::[dst]"r"(dst),[block]"r"(block),[stride]"r"((uint64_t)stride)
-        : "$8","$10","$f0","$f2","$f4","$f6","$f8","$f10"
+        "mtc1       %[dc],      %[ftmp5]                                \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "uld        %[low32],   0x00(%[dst0])                           \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   0x00(%[dst1])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "uld        %[low32],   0x00(%[dst2])                           \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "uld        %[low32],   0x00(%[dst3])                           \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[dst0])                           \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[dst0])                           \n\t"
+        "gsswlc1    %[ftmp2],   0x03(%[dst1])                           \n\t"
+        "gsswrc1    %[ftmp2],   0x00(%[dst1])                           \n\t"
+        "gsswlc1    %[ftmp3],   0x03(%[dst2])                           \n\t"
+        "gsswrc1    %[ftmp3],   0x00(%[dst2])                           \n\t"
+        "gsswlc1    %[ftmp4],   0x03(%[dst3])                           \n\t"
+        "gsswrc1    %[ftmp4],   0x00(%[dst3])                           \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [low32]"=&r"(low32)
+        : [dst0]"r"(dst),                   [dst1]"r"(dst+stride),
+          [dst2]"r"(dst+2*stride),          [dst3]"r"(dst+3*stride),
+          [dc]"r"(dc)
+        : "memory"
     );
 }
 
 void ff_h264_idct8_dc_add_8_mmi(uint8_t *dst, int16_t *block, int stride)
 {
+    int dc = (block[0] + 32) >> 6;
+    double ftmp[10];
+
+    block[0] = 0;
+
     __asm__ volatile (
-        "lh $8, 0x0(%[block])                       \r\n"
-        "sd $0, 0x0(%[block])                       \r\n"
-        "daddiu $8, $8, 0x20                        \r\n"
-        "daddu $10, %[stride], %[stride]            \r\n"
-        "dsra $8, $8, 0x6                           \r\n"
-        "xor $f2, $f2, $f2                          \r\n"
-        "mtc1 $8, $f0                               \r\n"
-        "pshufh $f0, $f0, $f2                       \r\n"
-        "daddu $8, $10, %[stride]                   \r\n"
-        "psubh $f2, $f2, $f0                        \r\n"
-        "packushb $f0, $f0, $f0                     \r\n"
-        "packushb $f2, $f2, $f2                     \r\n"
-        "ldc1 $f4, 0x0(%[dst])                      \r\n"
-        "gsldxc1 $f6, 0x0(%[dst], %[stride])        \r\n"
-        "gsldxc1 $f8, 0x0(%[dst], $10)              \r\n"
-        "gsldxc1 $f10, 0x0(%[dst], $8)              \r\n"
-        "paddusb $f4, $f4, $f0                      \r\n"
-        "paddusb $f6, $f6, $f0                      \r\n"
-        "paddusb $f8, $f8, $f0                      \r\n"
-        "paddusb $f10, $f10, $f0                    \r\n"
-        "psubusb $f4, $f4, $f2                      \r\n"
-        "psubusb $f6, $f6, $f2                      \r\n"
-        "psubusb $f8, $f8, $f2                      \r\n"
-        "psubusb $f10, $f10, $f2                    \r\n"
-        "sdc1 $f4, 0x0(%[dst])                      \r\n"
-        "gssdxc1 $f6, 0x0(%[dst], %[stride])        \r\n"
-        "gssdxc1 $f8, 0x0(%[dst], $10)              \r\n"
-        "daddu $9, $10, $10                         \r\n"
-        "gssdxc1 $f10, 0x0(%[dst], $8)              \r\n"
-        "daddu %[dst], %[dst], $9                   \r\n"
-        "ldc1 $f4, 0x0(%[dst])                      \r\n"
-        "gsldxc1 $f6, 0x0(%[dst], %[stride])        \r\n"
-        "gsldxc1 $f8, 0x0(%[dst], $10)              \r\n"
-        "gsldxc1 $f10, 0x0(%[dst], $8)              \r\n"
-        "paddusb $f4, $f4, $f0                      \r\n"
-        "paddusb $f6, $f6, $f0                      \r\n"
-        "paddusb $f8, $f8, $f0                      \r\n"
-        "paddusb $f10, $f10, $f0                    \r\n"
-        "psubusb $f4, $f4, $f2                      \r\n"
-        "psubusb $f6, $f6, $f2                      \r\n"
-        "psubusb $f8, $f8, $f2                      \r\n"
-        "psubusb $f10, $f10, $f2                    \r\n"
-        "sdc1 $f4, 0x0(%[dst])                      \r\n"
-        "gssdxc1 $f6, 0x0(%[dst], %[stride])        \r\n"
-        "gssdxc1 $f8, 0x0(%[dst], $10)              \r\n"
-        "gssdxc1 $f10, 0x0(%[dst], $8)              \r\n"
-        ::[dst]"r"(dst),[block]"r"(block),[stride]"r"((uint64_t)stride)
-        : "$8","$9","$10","$f0","$f2","$f4","$f6","$f8","$f10"
+        "mtc1       %[dc],      %[ftmp5]                                \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "ldc1       %[ftmp1],   0x00(%[dst0])                           \n\t"
+        "ldc1       %[ftmp2],   0x00(%[dst1])                           \n\t"
+        "ldc1       %[ftmp3],   0x00(%[dst2])                           \n\t"
+        "ldc1       %[ftmp4],   0x00(%[dst3])                           \n\t"
+        "punpckhbh  %[ftmp6],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp8],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp9],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp6],   %[ftmp6],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp9],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "packushb   %[ftmp1],   %[ftmp1],       %[ftmp6]                \n\t"
+        "packushb   %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "packushb   %[ftmp3],   %[ftmp3],       %[ftmp8]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp4],       %[ftmp9]                \n\t"
+        "sdc1       %[ftmp1],   0x00(%[dst0])                           \n\t"
+        "sdc1       %[ftmp2],   0x00(%[dst1])                           \n\t"
+        "sdc1       %[ftmp3],   0x00(%[dst2])                           \n\t"
+        "sdc1       %[ftmp4],   0x00(%[dst3])                           \n\t"
+
+        "ldc1       %[ftmp1],   0x00(%[dst4])                           \n\t"
+        "ldc1       %[ftmp2],   0x00(%[dst5])                           \n\t"
+        "ldc1       %[ftmp3],   0x00(%[dst6])                           \n\t"
+        "ldc1       %[ftmp4],   0x00(%[dst7])                           \n\t"
+        "punpckhbh  %[ftmp6],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp8],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp9],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp6],   %[ftmp6],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp9],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "packushb   %[ftmp1],   %[ftmp1],       %[ftmp6]                \n\t"
+        "packushb   %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "packushb   %[ftmp3],   %[ftmp3],       %[ftmp8]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp4],       %[ftmp9]                \n\t"
+        "sdc1       %[ftmp1],   0x00(%[dst4])                           \n\t"
+        "sdc1       %[ftmp2],   0x00(%[dst5])                           \n\t"
+        "sdc1       %[ftmp3],   0x00(%[dst6])                           \n\t"
+        "sdc1       %[ftmp4],   0x00(%[dst7])                           \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9])
+        : [dst0]"r"(dst),                   [dst1]"r"(dst+stride),
+          [dst2]"r"(dst+2*stride),          [dst3]"r"(dst+3*stride),
+          [dst4]"r"(dst+4*stride),          [dst5]"r"(dst+5*stride),
+          [dst6]"r"(dst+6*stride),          [dst7]"r"(dst+7*stride),
+          [dc]"r"(dc)
+        : "memory"
     );
 }
 
@@ -775,212 +886,222 @@ void ff_h264_idct_add8_422_8_mmi(uint8_t **dest, const int *block_offset,
 void ff_h264_luma_dc_dequant_idct_8_mmi(int16_t *output, int16_t *input,
         int qmul)
 {
+    double ftmp[10];
+    uint64_t tmp[2];
+
     __asm__ volatile (
-        ".set noreorder                                 \r\n"
-        "dli $10, 0x8                                   \r\n"
-        "ldc1 $f6, 0x18(%[input])                       \r\n"
-        "dmtc1 $10, $f16                                \r\n"
-        "ldc1 $f4, 0x10(%[input])                       \r\n"
-        "dli $10, 0x20                                  \r\n"
-        "ldc1 $f2, 0x8(%[input])                        \r\n"
-        "dmtc1 $10, $f18                                \r\n"
-        "ldc1 $f0, 0x0(%[input])                        \r\n"
-        "mov.d $f8, $f6                                 \r\n"
-        "paddh $f6, $f6, $f4                            \r\n"
-        "psubh $f4, $f4, $f8                            \r\n"
-        "mov.d $f8, $f2                                 \r\n"
-        "paddh $f2, $f2, $f0                            \r\n"
-        "psubh $f0, $f0, $f8                            \r\n"
-        "mov.d $f8, $f6                                 \r\n"
-        "paddh $f6, $f6, $f2                            \r\n"
-        "psubh $f2, $f2, $f8                            \r\n"
-        "mov.d $f8, $f4                                 \r\n"
-        "paddh $f4, $f4, $f0                            \r\n"
-        "psubh $f0, $f0, $f8                            \r\n"
-        "mov.d $f8, $f6                                 \r\n"
-        "punpcklhw $f6, $f6, $f2                        \r\n"
-        "punpckhhw $f8, $f8, $f2                        \r\n"
-        "punpckhhw $f2, $f0, $f4                        \r\n"
-        "punpcklhw $f0, $f0, $f4                        \r\n"
-        "punpckhwd $f4, $f6, $f0                        \r\n"
-        "punpcklwd $f6, $f6, $f0                        \r\n"
-        "mov.d $f0, $f8                                 \r\n"
-        "punpcklwd $f8, $f8, $f2                        \r\n"
-        "punpckhwd $f0, $f0, $f2                        \r\n"
-        "mov.d $f2, $f0                                 \r\n"
-        "paddh $f0, $f0, $f8                            \r\n"
-        "psubh $f8, $f8, $f2                            \r\n"
-        "mov.d $f2, $f4                                 \r\n"
-        "paddh $f4, $f4, $f6                            \r\n"
-        "psubh $f6, $f6, $f2                            \r\n"
-        "mov.d $f2, $f0                                 \r\n"
-        "paddh $f0, $f0, $f4                            \r\n"
-        "psubh $f4, $f4, $f2                            \r\n"
-        "mov.d $f2, $f8                                 \r\n"
-        "daddiu $10, %[qmul], -0x7fff                   \r\n"
-        "paddh $f8, $f8, $f6                            \r\n"
-        "bgtz $10, 1f                                   \r\n"
-        "psubh $f6, $f6, $f2                            \r\n"
-        "ori $10, $0, 0x80                              \r\n"
-        "dsll $10, $10, 0x10                            \r\n"
-        "punpckhhw $f2, $f0, %[ff_pw_1]                 \r\n"
-        "daddu %[qmul], %[qmul], $10                    \r\n"
-        "punpcklhw $f0, $f0, %[ff_pw_1]                 \r\n"
-        "punpckhhw $f10, $f4, %[ff_pw_1]                \r\n"
-        "punpcklhw $f4, $f4, %[ff_pw_1]                 \r\n"
-        "mtc1 %[qmul], $f14                             \r\n"
-        "punpcklwd $f14, $f14, $f14                     \r\n"
-        "pmaddhw $f0, $f0, $f14                         \r\n"
-        "pmaddhw $f4, $f4, $f14                         \r\n"
-        "pmaddhw $f2, $f2, $f14                         \r\n"
-        "pmaddhw $f10, $f10, $f14                       \r\n"
-        "psraw $f0, $f0, $f16                           \r\n"
-        "psraw $f4, $f4, $f16                           \r\n"
-        "psraw $f2, $f2, $f16                           \r\n"
-        "psraw $f10, $f10, $f16                         \r\n"
-        "packsswh $f0, $f0, $f2                         \r\n"
-        "packsswh $f4, $f4, $f10                        \r\n"
-        "mfc1 $9, $f0                                   \r\n"
-        "dsrl $f0, $f0, $f18                            \r\n"
-        "mfc1 %[input], $f0                             \r\n"
-        "sh $9, 0x0(%[output])                          \r\n"
-        "sh %[input], 0x80(%[output])                   \r\n"
-        "dsrl $9, $9, 0x10                              \r\n"
-        "dsrl %[input], %[input], 0x10                  \r\n"
-        "sh $9, 0x20(%[output])                         \r\n"
-        "sh %[input], 0xa0(%[output])                   \r\n"
-        "mfc1 $9, $f4                                   \r\n"
-        "dsrl $f4, $f4, $f18                            \r\n"
-        "mfc1 %[input], $f4                             \r\n"
-        "sh $9, 0x40(%[output])                         \r\n"
-        "sh %[input], 0xc0(%[output])                   \r\n"
-        "dsrl $9, $9, 0x10                              \r\n"
-        "dsrl %[input], %[input], 0x10                  \r\n"
-        "sh $9, 0x60(%[output])                         \r\n"
-        "sh %[input], 0xe0(%[output])                   \r\n"
-        "punpckhhw $f2, $f6, %[ff_pw_1]                 \r\n"
-        "punpcklhw $f6, $f6, %[ff_pw_1]                 \r\n"
-        "punpckhhw $f10, $f8, %[ff_pw_1]                \r\n"
-        "punpcklhw $f8, $f8, %[ff_pw_1]                 \r\n"
-        "mtc1 %[qmul], $f14                             \r\n"
-        "punpcklwd $f14, $f14, $f14                     \r\n"
-        "pmaddhw $f6, $f6, $f14                         \r\n"
-        "pmaddhw $f8, $f8, $f14                         \r\n"
-        "pmaddhw $f2, $f2, $f14                         \r\n"
-        "pmaddhw $f10, $f10, $f14                       \r\n"
-        "psraw $f6, $f6, $f16                           \r\n"
-        "psraw $f8, $f8, $f16                           \r\n"
-        "psraw $f2, $f2, $f16                           \r\n"
-        "psraw $f10, $f10, $f16                         \r\n"
-        "packsswh $f6, $f6, $f2                         \r\n"
-        "packsswh $f8, $f8, $f10                        \r\n"
-        "mfc1 $9, $f6                                   \r\n"
-        "dsrl $f6, $f6, $f18                            \r\n"
-        "mfc1 %[input], $f6                             \r\n"
-        "sh $9, 0x100(%[output])                        \r\n"
-        "sh %[input], 0x180(%[output])                  \r\n"
-        "dsrl $9, $9, 0x10                              \r\n"
-        "dsrl %[input], %[input], 0x10                  \r\n"
-        "sh $9, 0x120(%[output])                        \r\n"
-        "sh %[input], 0x1a0(%[output])                  \r\n"
-        "mfc1 $9, $f8                                   \r\n"
-        "dsrl $f8, $f8, $f18                            \r\n"
-        "mfc1 %[input], $f8                             \r\n"
-        "sh $9, 0x140(%[output])                        \r\n"
-        "sh %[input], 0x1c0(%[output])                  \r\n"
-        "dsrl $9, $9, 0x10                              \r\n"
-        "dsrl %[input], %[input], 0x10                  \r\n"
-        "sh $9, 0x160(%[output])                        \r\n"
-        "jr $31                                         \r\n"
-        "sh %[input], 0x1e0(%[output])                  \r\n"
-        "1:                                             \r\n"
-        "ori $10, $0, 0x1f                              \r\n"
-        "clz $9, %[qmul]                                \r\n"
-        "ori %[input], $0, 0x7                          \r\n"
-        "dsubu $9, $10, $9                              \r\n"
-        "ori $10, $0, 0x80                              \r\n"
-        "dsll $10, $10, 0x10                            \r\n"
-        "daddu %[qmul], %[qmul], $10                    \r\n"
-        "dsubu $10, $9, %[input]                        \r\n"
-        "movn $9, %[input], $10                         \r\n"
-        "daddiu %[input], %[input], 0x1                 \r\n"
-        "andi $10, $9, 0xff                             \r\n"
-        "dsrlv %[qmul], %[qmul], $10                    \r\n"
-        "dsubu %[input], %[input], $9                   \r\n"
-        "mtc1 %[input], $f12                            \r\n"
-        "punpckhhw $f2, $f0, %[ff_pw_1]                 \r\n"
-        "punpcklhw $f0, $f0, %[ff_pw_1]                 \r\n"
-        "punpckhhw $f10, $f4, %[ff_pw_1]                \r\n"
-        "punpcklhw $f4, $f4, %[ff_pw_1]                 \r\n"
-        "mtc1 %[qmul], $f14                             \r\n"
-        "punpcklwd $f14, $f14, $f14                     \r\n"
-        "pmaddhw $f0, $f0, $f14                         \r\n"
-        "pmaddhw $f4, $f4, $f14                         \r\n"
-        "pmaddhw $f2, $f2, $f14                         \r\n"
-        "pmaddhw $f10, $f10, $f14                       \r\n"
-        "psraw $f0, $f0, $f12                           \r\n"
-        "psraw $f4, $f4, $f12                           \r\n"
-        "psraw $f2, $f2, $f12                           \r\n"
-        "psraw $f10, $f10, $f12                         \r\n"
-        "packsswh $f0, $f0, $f2                         \r\n"
-        "packsswh $f4, $f4, $f10                        \r\n"
-        "mfc1 $9, $f0                                   \r\n"
-        "dsrl $f0, $f0, $f18                            \r\n"
-        "sh $9, 0x0(%[output])                          \r\n"
-        "mfc1 %[input], $f0                             \r\n"
-        "dsrl $9, $9, 0x10                              \r\n"
-        "sh %[input], 0x80(%[output])                   \r\n"
-        "sh $9, 0x20(%[output])                         \r\n"
-        "dsrl %[input], %[input], 0x10                  \r\n"
-        "mfc1 $9, $f4                                   \r\n"
-        "sh %[input], 0xa0(%[output])                   \r\n"
-        "dsrl $f4, $f4, $f18                            \r\n"
-        "sh $9, 0x40(%[output])                         \r\n"
-        "mfc1 %[input], $f4                             \r\n"
-        "dsrl $9, $9, 0x10                              \r\n"
-        "sh %[input], 0xc0(%[output])                   \r\n"
-        "sh $9, 0x60(%[output])                         \r\n"
-        "dsrl %[input], %[input], 0x10                  \r\n"
-        "sh %[input], 0xe0(%[output])                   \r\n"
-        "punpckhhw $f2, $f6, %[ff_pw_1]                 \r\n"
-        "punpcklhw $f6, $f6, %[ff_pw_1]                 \r\n"
-        "punpckhhw $f10, $f8, %[ff_pw_1]                \r\n"
-        "punpcklhw $f8, $f8, %[ff_pw_1]                 \r\n"
-        "mtc1 %[qmul], $f14                             \r\n"
-        "punpcklwd $f14, $f14, $f14                     \r\n"
-        "pmaddhw $f6, $f6, $f14                         \r\n"
-        "pmaddhw $f8, $f8, $f14                         \r\n"
-        "pmaddhw $f2, $f2, $f14                         \r\n"
-        "pmaddhw $f10, $f10, $f14                       \r\n"
-        "psraw $f6, $f6, $f12                           \r\n"
-        "psraw $f8, $f8, $f12                           \r\n"
-        "psraw $f2, $f2, $f12                           \r\n"
-        "psraw $f10, $f10, $f12                         \r\n"
-        "packsswh $f6, $f6, $f2                         \r\n"
-        "packsswh $f8, $f8, $f10                        \r\n"
-        "mfc1 $9, $f6                                   \r\n"
-        "dsrl $f6, $f6, $f18                            \r\n"
-        "mfc1 %[input], $f6                             \r\n"
-        "sh $9, 0x100(%[output])                        \r\n"
-        "sh %[input], 0x180(%[output])                  \r\n"
-        "dsrl $9, $9, 0x10                              \r\n"
-        "dsrl %[input], %[input], 0x10                  \r\n"
-        "sh $9, 0x120(%[output])                        \r\n"
-        "sh %[input], 0x1a0(%[output])                  \r\n"
-        "mfc1 $9, $f8                                   \r\n"
-        "dsrl $f8, $f8, $f18                            \r\n"
-        "mfc1 %[input], $f8                             \r\n"
-        "sh $9, 0x140(%[output])                        \r\n"
-        "sh %[input], 0x1c0(%[output])                  \r\n"
-        "dsrl $9, $9, 0x10                              \r\n"
-        "dsrl %[input], %[input], 0x10                  \r\n"
-        "sh $9, 0x160(%[output])                        \r\n"
-        "sh %[input], 0x1e0(%[output])                  \r\n"
-        ".set reorder                                   \r\n"
-        ::[output]"r"(output),[input]"r"(input),[qmul]"r"((uint64_t)qmul),
-          [ff_pw_1]"f"(ff_pw_1)
-        : "$9","$10","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18"
+        ".set       noreorder                                           \n\t"
+        "dli        %[tmp0],    0x08                                    \n\t"
+        "ldc1       %[ftmp3],   0x18(%[input])                          \n\t"
+        "mtc1       %[tmp0],    %[ftmp8]                                \n\t"
+        "ldc1       %[ftmp2],   0x10(%[input])                          \n\t"
+        "dli        %[tmp0],    0x20                                    \n\t"
+        "ldc1       %[ftmp1],   0x08(%[input])                          \n\t"
+        "mtc1       %[tmp0],    %[ftmp9]                                \n\t"
+        "ldc1       %[ftmp0],   0x00(%[input])                          \n\t"
+        "mov.d      %[ftmp4],   %[ftmp3]                                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "mov.d      %[ftmp4],   %[ftmp1]                                \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "psubh      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "mov.d      %[ftmp4],   %[ftmp3]                                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "psubh      %[ftmp1],   %[ftmp1],       %[ftmp4]                \n\t"
+        "mov.d      %[ftmp4],   %[ftmp2]                                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "psubh      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "mov.d      %[ftmp4],   %[ftmp3]                                \n\t"
+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "punpckhhw  %[ftmp4],   %[ftmp4],       %[ftmp1]                \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhwd  %[ftmp2],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "mov.d      %[ftmp0],   %[ftmp4]                                \n\t"
+        "punpcklwd  %[ftmp4],   %[ftmp4],       %[ftmp1]                \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "mov.d      %[ftmp1],   %[ftmp0]                                \n\t"
+        "paddh      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "psubh      %[ftmp4],   %[ftmp4],       %[ftmp1]                \n\t"
+        "mov.d      %[ftmp1],   %[ftmp2]                                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "mov.d      %[ftmp1],   %[ftmp0]                                \n\t"
+        "paddh      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp1]                \n\t"
+        "mov.d      %[ftmp1],   %[ftmp4]                                \n\t"
+        "daddi      %[tmp0],    %[qmul],        -0x7fff                 \n\t"
+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp3]                \n\t"
+        "bgtz       %[tmp0],    1f                                      \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "ori        %[tmp0],    $0,             0x80                    \n\t"
+        "dsll       %[tmp0],    %[tmp0],        0x10                    \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp0],       %[ff_pw_1]              \n\t"
+        "daddu      %[qmul],    %[qmul],        %[tmp0]                 \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ff_pw_1]              \n\t"
+        "punpckhhw  %[ftmp5],   %[ftmp2],       %[ff_pw_1]              \n\t"
+        "punpcklhw  %[ftmp2],   %[ftmp2],       %[ff_pw_1]              \n\t"
+        "mtc1       %[qmul],    %[ftmp7]                                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psraw      %[ftmp0],   %[ftmp0],       %[ftmp8]                \n\t"
+        "psraw      %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "psraw      %[ftmp1],   %[ftmp1],       %[ftmp8]                \n\t"
+        "psraw      %[ftmp5],   %[ftmp5],       %[ftmp8]                \n\t"
+        "packsswh   %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "packsswh   %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "dmfc1      %[tmp1],    %[ftmp0]                                \n\t"
+        "dsrl       %[ftmp0],   %[ftmp0],       %[ftmp9]                \n\t"
+        "mfc1       %[input],   %[ftmp0]                                \n\t"
+        "sh         %[tmp1],    0x00(%[output])                         \n\t"
+        "sh         %[input],   0x80(%[output])                         \n\t"
+        "dsrl       %[tmp1],    %[tmp1],        0x10                    \n\t"
+        PTR_SRL    "%[input],   %[input],       0x10                    \n\t"
+        "sh         %[tmp1],    0x20(%[output])                         \n\t"
+        "sh         %[input],   0xa0(%[output])                         \n\t"
+        "dmfc1      %[tmp1],    %[ftmp2]                                \n\t"
+        "dsrl       %[ftmp2],   %[ftmp2],       %[ftmp9]                \n\t"
+        "mfc1       %[input],   %[ftmp2]                                \n\t"
+        "sh         %[tmp1],    0x40(%[output])                         \n\t"
+        "sh         %[input],   0xc0(%[output])                         \n\t"
+        "dsrl       %[tmp1],    %[tmp1],        0x10                    \n\t"
+        PTR_SRL    "%[input],   %[input],       0x10                    \n\t"
+        "sh         %[tmp1],    0x60(%[output])                         \n\t"
+        "sh         %[input],   0xe0(%[output])                         \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp3],       %[ff_pw_1]              \n\t"
+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ff_pw_1]              \n\t"
+        "punpckhhw  %[ftmp5],   %[ftmp4],       %[ff_pw_1]              \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ff_pw_1]              \n\t"
+        "mtc1       %[qmul],    %[ftmp7]                                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp4],   %[ftmp4],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psraw      %[ftmp3],   %[ftmp3],       %[ftmp8]                \n\t"
+        "psraw      %[ftmp4],   %[ftmp4],       %[ftmp8]                \n\t"
+        "psraw      %[ftmp1],   %[ftmp1],       %[ftmp8]                \n\t"
+        "psraw      %[ftmp5],   %[ftmp5],       %[ftmp8]                \n\t"
+        "packsswh   %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "packsswh   %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "dmfc1      %[tmp1],    %[ftmp3]                                \n\t"
+        "dsrl       %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "mfc1       %[input],   %[ftmp3]                                \n\t"
+        "sh         %[tmp1],    0x100(%[output])                        \n\t"
+        "sh         %[input],   0x180(%[output])                        \n\t"
+        "dsrl       %[tmp1],    %[tmp1],        0x10                    \n\t"
+        PTR_SRL    "%[input],   %[input],       0x10                    \n\t"
+        "sh         %[tmp1],    0x120(%[output])                        \n\t"
+        "sh         %[input],   0x1a0(%[output])                        \n\t"
+        "dmfc1      %[tmp1],    %[ftmp4]                                \n\t"
+        "dsrl       %[ftmp4],   %[ftmp4],       %[ftmp9]                \n\t"
+        "mfc1       %[input],   %[ftmp4]                                \n\t"
+        "sh         %[tmp1],    0x140(%[output])                        \n\t"
+        "sh         %[input],   0x1c0(%[output])                        \n\t"
+        "dsrl       %[tmp1],    %[tmp1],        0x10                    \n\t"
+        PTR_SRL    "%[input],   %[input],       0x10                    \n\t"
+        "sh         %[tmp1],    0x160(%[output])                        \n\t"
+        "j          2f                                                  \n\t"
+        "sh         %[input],   0x1e0(%[output])                        \n\t"
+        "1:                                                             \n\t"
+        "ori        %[tmp0],    $0,             0x1f                    \n\t"
+        "clz        %[tmp1],    %[qmul]                                 \n\t"
+        "ori        %[input],   $0,             0x07                    \n\t"
+        "dsubu      %[tmp1],    %[tmp0],        %[tmp1]                 \n\t"
+        "ori        %[tmp0],    $0,             0x80                    \n\t"
+        "dsll       %[tmp0],    %[tmp0],        0x10                    \n\t"
+        "daddu      %[qmul],    %[qmul],        %[tmp0]                 \n\t"
+        "dsubu      %[tmp0],    %[tmp1],        %[input]                \n\t"
+        "movn       %[tmp1],    %[input],       %[tmp0]                 \n\t"
+        PTR_ADDIU  "%[input],   %[input],       0x01                    \n\t"
+        "andi       %[tmp0],    %[tmp1],        0xff                    \n\t"
+        "srlv       %[qmul],    %[qmul],        %[tmp0]                 \n\t"
+        PTR_SUBU   "%[input],   %[input],       %[tmp1]                 \n\t"
+        "mtc1       %[input],   %[ftmp6]                                \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp0],       %[ff_pw_1]              \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ff_pw_1]              \n\t"
+        "punpckhhw  %[ftmp5],   %[ftmp2],       %[ff_pw_1]              \n\t"
+        "punpcklhw  %[ftmp2],   %[ftmp2],       %[ff_pw_1]              \n\t"
+        "mtc1       %[qmul],    %[ftmp7]                                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psraw      %[ftmp0],   %[ftmp0],       %[ftmp6]                \n\t"
+        "psraw      %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "psraw      %[ftmp1],   %[ftmp1],       %[ftmp6]                \n\t"
+        "psraw      %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "packsswh   %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "packsswh   %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "dmfc1      %[tmp1],    %[ftmp0]                                \n\t"
+        "dsrl       %[ftmp0],   %[ftmp0],       %[ftmp9]                \n\t"
+        "sh         %[tmp1],    0x00(%[output])                         \n\t"
+        "mfc1       %[input],   %[ftmp0]                                \n\t"
+        "dsrl       %[tmp1],    %[tmp1],        0x10                    \n\t"
+        "sh         %[input],   0x80(%[output])                         \n\t"
+        "sh         %[tmp1],    0x20(%[output])                         \n\t"
+        PTR_SRL    "%[input],   %[input],       0x10                    \n\t"
+        "dmfc1      %[tmp1],    %[ftmp2]                                \n\t"
+        "sh         %[input],   0xa0(%[output])                         \n\t"
+        "dsrl       %[ftmp2],   %[ftmp2],       %[ftmp9]                \n\t"
+        "sh         %[tmp1],    0x40(%[output])                         \n\t"
+        "mfc1       %[input],   %[ftmp2]                                \n\t"
+        "dsrl       %[tmp1],    %[tmp1],        0x10                    \n\t"
+        "sh         %[input],   0xc0(%[output])                         \n\t"
+        "sh         %[tmp1],    0x60(%[output])                         \n\t"
+        PTR_SRL    "%[input],   %[input],       0x10                    \n\t"
+        "sh         %[input],   0xe0(%[output])                         \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp3],       %[ff_pw_1]              \n\t"
+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ff_pw_1]              \n\t"
+        "punpckhhw  %[ftmp5],   %[ftmp4],       %[ff_pw_1]              \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ff_pw_1]              \n\t"
+        "mtc1       %[qmul],    %[ftmp7]                                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp4],   %[ftmp4],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "pmaddhw    %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psraw      %[ftmp3],   %[ftmp3],       %[ftmp6]                \n\t"
+        "psraw      %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "psraw      %[ftmp1],   %[ftmp1],       %[ftmp6]                \n\t"
+        "psraw      %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "packsswh   %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "packsswh   %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "dmfc1      %[tmp1],    %[ftmp3]                                \n\t"
+        "dsrl       %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "mfc1       %[input],   %[ftmp3]                                \n\t"
+        "sh         %[tmp1],    0x100(%[output])                        \n\t"
+        "sh         %[input],   0x180(%[output])                        \n\t"
+        "dsrl       %[tmp1],    %[tmp1],        0x10                    \n\t"
+        PTR_SRL    "%[input],   %[input],       0x10                    \n\t"
+        "sh         %[tmp1],    0x120(%[output])                        \n\t"
+        "sh         %[input],   0x1a0(%[output])                        \n\t"
+        "dmfc1      %[tmp1],    %[ftmp4]                                \n\t"
+        "dsrl       %[ftmp4],   %[ftmp4],       %[ftmp9]                \n\t"
+        "mfc1       %[input],   %[ftmp4]                                \n\t"
+        "sh         %[tmp1],    0x140(%[output])                        \n\t"
+        "sh         %[input],   0x1c0(%[output])                        \n\t"
+        "dsrl       %[tmp1],    %[tmp1],        0x10                    \n\t"
+        PTR_SRL    "%[input],   %[input],       0x10                    \n\t"
+        "sh         %[tmp1],    0x160(%[output])                        \n\t"
+        "sh         %[input],   0x1e0(%[output])                        \n\t"
+        "2:                                                             \n\t"
+        ".set       reorder                                             \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [output]"+&r"(output),            [input]"+&r"(input),
+          [qmul]"+&r"(qmul)
+        : [ff_pw_1]"f"(ff_pw_1)
+        : "memory"
     );
 }
 
@@ -1031,10 +1152,11 @@ void ff_h264_chroma_dc_dequant_idct_8_mmi(int16_t *block, int qmul)
     block[48]= ((d-b)*qmul) >> 7;
 }
 
-void ff_h264_weight_pixels16_8_mmi(uint8_t *block, int stride,
-        int height, int log2_denom, int weight, int offset)
+void ff_h264_weight_pixels16_8_mmi(uint8_t *block, int stride, int height,
+        int log2_denom, int weight, int offset)
 {
     int y;
+    double ftmp[8];
 
     offset <<= log2_denom;
 
@@ -1043,97 +1165,110 @@ void ff_h264_weight_pixels16_8_mmi(uint8_t *block, int stride,
 
     for (y=0; y<height; y++, block+=stride) {
         __asm__ volatile (
-            "ldc1 $f2, %0                   \r\n"
-            "ldc1 $f4, %1                   \r\n"
-            "dmtc1 $0, $f20                 \r\n"
-            "mtc1 %2, $f6                   \r\n"
-            "mtc1 %3, $f8                   \r\n"
-            "mtc1 %4, $f10                  \r\n"
-            "pshufh $f6, $f6, $f20          \r\n"
-            "pshufh $f8, $f8, $f20          \r\n"
-            "punpckhbh $f14, $f2, $f20      \r\n"
-            "punpckhbh $f16, $f4, $f20      \r\n"
-            "punpcklbh $f2, $f2, $f20       \r\n"
-            "punpcklbh $f4, $f4, $f20       \r\n"
-            "pmullh $f14, $f14, $f6         \r\n"
-            "pmullh $f16, $f16, $f6         \r\n"
-            "pmullh $f2, $f2, $f6           \r\n"
-            "pmullh $f4, $f4, $f6           \r\n"
-            "paddsh $f14, $f14, $f8         \r\n"
-            "paddsh $f16, $f16, $f8         \r\n"
-            "paddsh $f2, $f2, $f8           \r\n"
-            "paddsh $f4, $f4, $f8           \r\n"
-            "psrah $f14, $f14, $f10         \r\n"
-            "psrah $f16, $f16, $f10         \r\n"
-            "psrah $f2, $f2, $f10           \r\n"
-            "psrah $f4, $f4, $f10           \r\n"
-            "packushb $f2, $f2, $f14        \r\n"
-            "packushb $f4, $f4, $f16        \r\n"
-            "sdc1 $f2, %0                   \r\n"
-            "sdc1 $f4, %1                   \r\n"
-            : "=m"(*block),"=m"(*(block + 8))
-            : "r"(weight),"r"(offset),"r"(log2_denom)
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "ldc1       %[ftmp1],   0x00(%[block0])                     \n\t"
+            "ldc1       %[ftmp2],   0x00(%[block1])                     \n\t"
+            "mtc1       %[weight],  %[ftmp3]                            \n\t"
+            "mtc1       %[offset],  %[ftmp4]                            \n\t"
+            "mtc1       %[log2_denom],              %[ftmp5]            \n\t"
+            "pshufh     %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"
+            "pshufh     %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp6],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp7],   %[ftmp2],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp7],   %[ftmp7],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp2],   %[ftmp2],       %[ftmp3]            \n\t"
+            "paddsh     %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "paddsh     %[ftmp7],   %[ftmp7],       %[ftmp4]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp4]            \n\t"
+            "paddsh     %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp7],   %[ftmp7],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp2],   %[ftmp2],       %[ftmp5]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp6]            \n\t"
+            "packushb   %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "sdc1       %[ftmp1],   0x00(%[block0])                     \n\t"
+            "sdc1       %[ftmp2],   0x00(%[block1])                     \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7])
+            : [block0]"r"(block),           [block1]"r"(block+8),
+              [weight]"r"(weight),          [offset]"r"(offset),
+              [log2_denom]"r"(log2_denom)
+            : "memory"
         );
     }
 }
 
-void ff_h264_biweight_pixels16_8_mmi(uint8_t *dst, uint8_t *src,
-        int stride, int height, int log2_denom, int weightd, int weights,
-        int offset)
+void ff_h264_biweight_pixels16_8_mmi(uint8_t *dst, uint8_t *src, int stride,
+        int height, int log2_denom, int weightd, int weights, int offset)
 {
     int y;
+    double ftmp[9];
 
     offset = ((offset + 1) | 1) << log2_denom;
 
     for (y=0; y<height; y++, dst+=stride, src+=stride) {
         __asm__ volatile (
-            "ldc1 $f2, %2                   \r\n"
-            "ldc1 $f4, %3                   \r\n"
-            "dmtc1 $0, $f20                 \r\n"
-            "mtc1 %6, $f6                   \r\n"
-            "mtc1 %7, $f8                   \r\n"
-            "mtc1 %8, $f10                  \r\n"
-            "mtc1 %9, $f12                  \r\n"
-            "pshufh $f6, $f6, $f20          \r\n"
-            "pshufh $f8, $f8, $f20          \r\n"
-            "pshufh $f10, $f10, $f20        \r\n"
-            "punpckhbh $f14, $f2, $f20      \r\n"
-            "punpckhbh $f16, $f4, $f20      \r\n"
-            "punpcklbh $f2, $f2, $f20       \r\n"
-            "punpcklbh $f4, $f4, $f20       \r\n"
-            "pmullh $f14, $f14, $f6         \r\n"
-            "pmullh $f16, $f16, $f8         \r\n"
-            "pmullh $f2, $f2, $f6           \r\n"
-            "pmullh $f4, $f4, $f8           \r\n"
-            "paddsh $f14, $f14, $f10        \r\n"
-            "paddsh $f2, $f2, $f10          \r\n"
-            "paddsh $f14, $f14, $f16        \r\n"
-            "paddsh $f2, $f2, $f4           \r\n"
-            "psrah $f14, $f14, $f12         \r\n"
-            "psrah $f2, $f2, $f12           \r\n"
-            "packushb $f2, $f2, $f14        \r\n"
-            "sdc1 $f2, %0                   \r\n"
-            "ldc1 $f2, %4                   \r\n"
-            "ldc1 $f4, %5                   \r\n"
-            "punpckhbh $f14, $f2, $f20      \r\n"
-            "punpckhbh $f16, $f4, $f20      \r\n"
-            "punpcklbh $f2, $f2, $f20       \r\n"
-            "punpcklbh $f4, $f4, $f20       \r\n"
-            "pmullh $f14, $f14, $f6         \r\n"
-            "pmullh $f16, $f16, $f8         \r\n"
-            "pmullh $f2, $f2, $f6           \r\n"
-            "pmullh $f4, $f4, $f8           \r\n"
-            "paddsh $f14, $f14, $f10        \r\n"
-            "paddsh $f2, $f2, $f10          \r\n"
-            "paddsh $f14, $f14, $f16        \r\n"
-            "paddsh $f2, $f2, $f4           \r\n"
-            "psrah $f14, $f14, $f12         \r\n"
-            "psrah $f2, $f2, $f12           \r\n"
-            "packushb $f2, $f2, $f14        \r\n"
-            "sdc1 $f2, %1                   \r\n"
-            : "=m"(*dst),"=m"(*(dst+8))
-            : "m"(*src),"m"(*dst),"m"(*(src+8)),"m"(*(dst+8)),
-              "r"(weights),"r"(weightd),"r"(offset),"r"(log2_denom+1)
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "ldc1       %[ftmp1],   0x00(%[src0])                       \n\t"
+            "ldc1       %[ftmp2],   0x00(%[dst0])                       \n\t"
+            "mtc1       %[weights], %[ftmp3]                            \n\t"
+            "mtc1       %[weightd], %[ftmp4]                            \n\t"
+            "mtc1       %[offset],  %[ftmp5]                            \n\t"
+            "mtc1       %[log2_denom],              %[ftmp6]            \n\t"
+            "pshufh     %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"
+            "pshufh     %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"
+            "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp7],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp8],   %[ftmp2],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp7],   %[ftmp7],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp8],   %[ftmp8],       %[ftmp4]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "paddsh     %[ftmp7],   %[ftmp7],       %[ftmp5]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"
+            "paddsh     %[ftmp7],   %[ftmp7],       %[ftmp8]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "psrah      %[ftmp7],   %[ftmp7],       %[ftmp6]            \n\t"
+            "psrah      %[ftmp1],   %[ftmp1],       %[ftmp6]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst0])                       \n\t"
+            "ldc1       %[ftmp1],   0x00(%[src1])                       \n\t"
+            "ldc1       %[ftmp2],   0x00(%[dst1])                       \n\t"
+            "punpckhbh  %[ftmp7],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp8],   %[ftmp2],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp7],   %[ftmp7],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp8],   %[ftmp8],       %[ftmp4]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "paddsh     %[ftmp7],   %[ftmp7],       %[ftmp5]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"
+            "paddsh     %[ftmp7],   %[ftmp7],       %[ftmp8]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "psrah      %[ftmp7],   %[ftmp7],       %[ftmp6]            \n\t"
+            "psrah      %[ftmp1],   %[ftmp1],       %[ftmp6]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst1])                       \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [ftmp8]"=&f"(ftmp[8])
+            : [dst0]"r"(dst),               [dst1]"r"(dst+8),
+              [src0]"r"(src),               [src1]"r"(src+8),
+              [weights]"r"(weights),        [weightd]"r"(weightd),
+              [offset]"r"(offset),          [log2_denom]"r"(log2_denom+1)
+            : "memory"
         );
     }
 }
@@ -1142,6 +1277,7 @@ void ff_h264_weight_pixels8_8_mmi(uint8_t *block, int stride, int height,
         int log2_denom, int weight, int offset)
 {
     int y;
+    double ftmp[6];
 
     offset <<= log2_denom;
 
@@ -1150,68 +1286,78 @@ void ff_h264_weight_pixels8_8_mmi(uint8_t *block, int stride, int height,
 
     for (y=0; y<height; y++, block+=stride) {
         __asm__ volatile (
-            "ldc1 $f2, %0                   \r\n"
-            "mtc1 %1, $f6                   \r\n"
-            "mtc1 %2, $f8                   \r\n"
-            "mtc1 %3, $f10                  \r\n"
-            "dmtc1 $0, $f20                 \r\n"
-            "pshufh $f6, $f6, $f20          \r\n"
-            "pshufh $f8, $f8, $f20          \r\n"
-            "punpckhbh $f14, $f2, $f20      \r\n"
-            "punpcklbh $f2, $f2, $f20       \r\n"
-            "pmullh $f14, $f14, $f6         \r\n"
-            "pmullh $f2, $f2, $f6           \r\n"
-            "paddsh $f14, $f14, $f8         \r\n"
-            "paddsh $f2, $f2, $f8           \r\n"
-            "psrah $f14, $f14, $f10         \r\n"
-            "psrah $f2, $f2, $f10           \r\n"
-            "packushb $f2, $f2, $f14        \r\n"
-            "sdc1 $f2, %0                   \r\n"
-            : "=m"(*block)
-            : "r"(weight),"r"(offset),"r"(log2_denom)
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "ldc1       %[ftmp1],   0x00(%[block])                      \n\t"
+            "mtc1       %[weight],  %[ftmp2]                            \n\t"
+            "mtc1       %[offset],  %[ftmp3]                            \n\t"
+            "mtc1       %[log2_denom],              %[ftmp5]            \n\t"
+            "pshufh     %[ftmp2],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pshufh     %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp4],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp4],   %[ftmp4],       %[ftmp2]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "paddsh     %[ftmp4],   %[ftmp4],       %[ftmp3]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "psrah      %[ftmp4],   %[ftmp4],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp4]            \n\t"
+            "sdc1       %[ftmp1],   0x00(%[block])                      \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5])
+            : [block]"r"(block),            [weight]"r"(weight),
+              [offset]"r"(offset),          [log2_denom]"r"(log2_denom)
+            : "memory"
         );
     }
 }
 
-void ff_h264_biweight_pixels8_8_mmi(uint8_t *dst, uint8_t *src,
-        int stride, int height, int log2_denom, int weightd, int weights,
-        int offset)
+void ff_h264_biweight_pixels8_8_mmi(uint8_t *dst, uint8_t *src, int stride,
+        int height, int log2_denom, int weightd, int weights, int offset)
 {
     int y;
+    double ftmp[9];
 
     offset = ((offset + 1) | 1) << log2_denom;
 
     for (y=0; y<height; y++, dst+=stride, src+=stride) {
         __asm__ volatile (
-            "ldc1 $f2, %1                   \r\n"
-            "ldc1 $f4, %2                   \r\n"
-            "dmtc1 $0, $f20                 \r\n"
-            "mtc1 %3, $f6                   \r\n"
-            "mtc1 %4, $f8                   \r\n"
-            "mtc1 %5, $f10                  \r\n"
-            "mtc1 %6, $f12                  \r\n"
-            "pshufh $f6, $f6, $f20          \r\n"
-            "pshufh $f8, $f8, $f20          \r\n"
-            "pshufh $f10, $f10, $f20        \r\n"
-            "punpckhbh $f14, $f2, $f20      \r\n"
-            "punpckhbh $f16, $f4, $f20      \r\n"
-            "punpcklbh $f2, $f2, $f20       \r\n"
-            "punpcklbh $f4, $f4, $f20       \r\n"
-            "pmullh $f14, $f14, $f6         \r\n"
-            "pmullh $f16, $f16, $f8         \r\n"
-            "pmullh $f2, $f2, $f6           \r\n"
-            "pmullh $f4, $f4, $f8           \r\n"
-            "paddsh $f14, $f14, $f10        \r\n"
-            "paddsh $f2, $f2, $f10          \r\n"
-            "paddsh $f14, $f14, $f16        \r\n"
-            "paddsh $f2, $f2, $f4           \r\n"
-            "psrah $f14, $f14, $f12         \r\n"
-            "psrah $f2, $f2, $f12           \r\n"
-            "packushb $f2, $f2, $f14        \r\n"
-            "sdc1 $f2, %0                   \r\n"
-            : "=m"(*dst)
-            : "m"(*src),"m"(*dst),"r"(weights),
-              "r"(weightd),"r"(offset),"r"(log2_denom+1)
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "ldc1       %[ftmp1],   0x00(%[src])                        \n\t"
+            "ldc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "mtc1       %[weights], %[ftmp3]                            \n\t"
+            "mtc1       %[weightd], %[ftmp4]                            \n\t"
+            "mtc1       %[offset],  %[ftmp5]                            \n\t"
+            "mtc1       %[log2_denom],              %[ftmp6]            \n\t"
+            "pshufh     %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"
+            "pshufh     %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"
+            "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp7],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpckhbh  %[ftmp8],   %[ftmp2],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp7],   %[ftmp7],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp8],   %[ftmp8],       %[ftmp4]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "paddsh     %[ftmp7],   %[ftmp7],       %[ftmp5]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"
+            "paddsh     %[ftmp7],   %[ftmp7],       %[ftmp8]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "psrah      %[ftmp7],   %[ftmp7],       %[ftmp6]            \n\t"
+            "psrah      %[ftmp1],   %[ftmp1],       %[ftmp6]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "sdc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [ftmp8]"=&f"(ftmp[8])
+            : [dst]"r"(dst),                [src]"r"(src),
+              [weights]"r"(weights),        [weightd]"r"(weightd),
+              [offset]"r"(offset),          [log2_denom]"r"(log2_denom+1)
+            : "memory"
         );
     }
 }
@@ -1220,6 +1366,8 @@ void ff_h264_weight_pixels4_8_mmi(uint8_t *block, int stride, int height,
         int log2_denom, int weight, int offset)
 {
     int y;
+    double ftmp[5];
+    uint64_t low32;
 
     offset <<= log2_denom;
 
@@ -1228,745 +1376,883 @@ void ff_h264_weight_pixels4_8_mmi(uint8_t *block, int stride, int height,
 
     for (y=0; y<height; y++, block+=stride) {
         __asm__ volatile (
-            "lwc1 $f2, %0                   \r\n"
-            "mtc1 %1, $f6                   \r\n"
-            "mtc1 %2, $f8                   \r\n"
-            "mtc1 %3, $f10                  \r\n"
-            "dmtc1 $0, $f20                 \r\n"
-            "pshufh $f6, $f6, $f20          \r\n"
-            "pshufh $f8, $f8, $f20          \r\n"
-            "punpcklbh $f2, $f2, $f20       \r\n"
-            "pmullh $f2, $f2, $f6           \r\n"
-            "paddsh $f2, $f2, $f8           \r\n"
-            "psrah $f2, $f2, $f10           \r\n"
-            "packushb $f2, $f2, $f20        \r\n"
-            "swc1 $f2, %0                   \r\n"
-            : "=m"(*block)
-            : "r"(weight),"r"(offset),"r"(log2_denom)
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "uld        %[low32],   0x00(%[block])                      \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "mtc1       %[weight],  %[ftmp2]                            \n\t"
+            "mtc1       %[offset],  %[ftmp3]                            \n\t"
+            "mtc1       %[log2_denom],              %[ftmp4]            \n\t"
+            "pshufh     %[ftmp2],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pshufh     %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "psrah      %[ftmp1],   %[ftmp1],       %[ftmp4]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "gsswlc1    %[ftmp1],   0x03(%[block])                      \n\t"
+            "gsswrc1    %[ftmp1],   0x00(%[block])                      \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),
+              [low32]"=&r"(low32)
+            : [block]"r"(block),            [weight]"r"(weight),
+              [offset]"r"(offset),          [log2_denom]"r"(log2_denom)
+            : "memory"
         );
     }
 }
 
-void ff_h264_biweight_pixels4_8_mmi(uint8_t *dst, uint8_t *src,
-        int stride, int height, int log2_denom, int weightd, int weights,
-        int offset)
+void ff_h264_biweight_pixels4_8_mmi(uint8_t *dst, uint8_t *src, int stride,
+        int height, int log2_denom, int weightd, int weights, int offset)
 {
     int y;
+    double ftmp[7];
+    uint64_t low32;
 
     offset = ((offset + 1) | 1) << log2_denom;
 
     for (y=0; y<height; y++, dst+=stride, src+=stride) {
         __asm__ volatile (
-            "lwc1 $f2, %1                   \r\n"
-            "lwc1 $f4, %2                   \r\n"
-            "dmtc1 $0, $f20                 \r\n"
-            "mtc1 %3, $f6                   \r\n"
-            "mtc1 %4, $f8                   \r\n"
-            "mtc1 %5, $f10                  \r\n"
-            "mtc1 %6, $f12                  \r\n"
-            "pshufh $f6, $f6, $f20          \r\n"
-            "pshufh $f8, $f8, $f20          \r\n"
-            "pshufh $f10, $f10, $f20        \r\n"
-            "punpcklbh $f2, $f2, $f20       \r\n"
-            "punpcklbh $f4, $f4, $f20       \r\n"
-            "pmullh $f2, $f2, $f6           \r\n"
-            "pmullh $f4, $f4, $f8           \r\n"
-            "paddsh $f2, $f2, $f10          \r\n"
-            "paddsh $f2, $f2, $f4           \r\n"
-            "psrah $f2, $f2, $f12           \r\n"
-            "packushb $f2, $f2, $f20        \r\n"
-            "swc1 $f2, %0                   \r\n"
-            : "=m"(*dst)
-            : "m"(*src),"m"(*dst),"r"(weights),
-              "r"(weightd),"r"(offset),"r"(log2_denom+1)
+            "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "uld        %[low32],   0x00(%[dst])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "mtc1       %[weight],  %[ftmp3]                            \n\t"
+            "mtc1       %[weightd], %[ftmp4]                            \n\t"
+            "mtc1       %[offset],  %[ftmp5]                            \n\t"
+            "mtc1       %[log2_denom],              %[ftmp6]            \n\t"
+            "pshufh     %[ftmp3],   %[ftmp3],       %[ftmp0]            \n\t"
+            "pshufh     %[ftmp4],   %[ftmp4],       %[ftmp0]            \n\t"
+            "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]            \n\t"
+            "pmullh     %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "pmullh     %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp5]            \n\t"
+            "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp2]            \n\t"
+            "psrah      %[ftmp1],   %[ftmp1],       %[ftmp6]            \n\t"
+            "packushb   %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "gsswlc1    %[ftmp1],   0x03(%[dst])                        \n\t"
+            "gsswrc1    %[ftmp1],   0x00(%[dst])                        \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),
+              [low32]"=&r"(low32)
+            : [dst]"r"(dst),                [src]"r"(src),
+              [weight]"r"(weights),         [weightd]"r"(weightd),
+              [offset]"r"(offset),          [log2_denom]"r"(log2_denom+1)
+            : "memory"
         );
     }
 }
 
-static void inline chroma_inter_body_mmi(uint8_t *pix, int stride,
-        int alpha, int beta, int8_t *tc0)
-{
-    __asm__ volatile (
-        "xor $f16, $f16, $f16                           \r\n"
-        "mtc1 %[alpha], $f8                             \r\n"
-        "mtc1 %[beta], $f10                             \r\n"
-        "pshufh $f8, $f8, $f16                          \r\n"
-        "pshufh $f10, $f10, $f16                        \r\n"
-        "packushb $f8, $f8, $f8                         \r\n"
-        "packushb $f10, $f10, $f10                      \r\n"
-        "psubusb $f12, $f4, $f2                         \r\n"
-        "psubusb $f14, $f2, $f4                         \r\n"
-        "or $f14, $f14, $f12                            \r\n"
-        "psubusb $f14, $f14, $f8                        \r\n"
-        "psubusb $f12, $f2, $f0                         \r\n"
-        "psubusb $f8, $f0, $f2                          \r\n"
-        "or $f8, $f8, $f12                              \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "or $f14, $f14, $f8                             \r\n"
-        "psubusb $f12, $f4, $f6                         \r\n"
-        "psubusb $f8, $f6, $f4                          \r\n"
-        "or $f8, $f8, $f12                              \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "or $f14, $f14, $f8                             \r\n"
-        "xor $f12, $f12, $f12                           \r\n"
-        "pcmpeqb $f14, $f14, $f12                       \r\n"
-        "lwc1 $f12, 0x0(%[tc0])                         \r\n"
-        "punpcklbh $f12, $f12, $f12                     \r\n"
-        "and $f14, $f14, $f12                           \r\n"
-        "pcmpeqb $f8, $f8, $f8                          \r\n"
-        "xor $f10, $f2, $f4                             \r\n"
-        "xor $f6, $f6, $f8                              \r\n"
-        "and $f10, $f10, %[ff_pb_1]                     \r\n"
-        "pavgb $f6, $f6, $f0                            \r\n"
-        "xor $f8, $f8, $f2                              \r\n"
-        "pavgb $f6, $f6, %[ff_pb_3]                     \r\n"
-        "pavgb $f8, $f8, $f4                            \r\n"
-        "pavgb $f6, $f6, $f10                           \r\n"
-        "paddusb $f6, $f6, $f8                          \r\n"
-        "psubusb $f12, %[ff_pb_A1], $f6                 \r\n"
-        "psubusb $f6, $f6, %[ff_pb_A1]                  \r\n"
-        "pminub $f12, $f12, $f14                        \r\n"
-        "pminub $f6, $f6, $f14                          \r\n"
-        "psubusb $f2, $f2, $f12                         \r\n"
-        "psubusb $f4, $f4, $f6                          \r\n"
-        "paddusb $f2, $f2, $f6                          \r\n"
-        "paddusb $f4, $f4, $f12                         \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride),
-          [alpha]"r"((int64_t)alpha),[beta]"r"((int64_t)beta),[tc0]"r"(tc0),
-          [ff_pb_1]"f"(ff_pb_1),[ff_pb_3]"f"(ff_pb_3),[ff_pb_A1]"f"(ff_pb_A1)
-        : "$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16"
-    );
-}
-
-static void inline chroma_intra_body_mmi(uint8_t *pix, int stride,
-        int alpha, int beta)
-{
-    __asm__ volatile (
-        "xor $f16, $f16, $f16                           \r\n"
-        "mtc1 %[alpha], $f8                             \r\n"
-        "mtc1 %[beta], $f10                             \r\n"
-        "pshufh $f8, $f8, $f16                          \r\n"
-        "pshufh $f10, $f10, $f16                        \r\n"
-        "packushb $f8, $f8, $f8                         \r\n"
-        "packushb $f10, $f10, $f10                      \r\n"
-        "psubusb $f12, $f4, $f2                         \r\n"
-        "psubusb $f14, $f2, $f4                         \r\n"
-        "or $f14, $f14, $f12                            \r\n"
-        "psubusb $f14, $f14, $f8                        \r\n"
-        "psubusb $f12, $f2, $f0                         \r\n"
-        "psubusb $f8, $f0, $f2                          \r\n"
-        "or $f8, $f8, $f12                              \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "or $f14, $f14, $f8                             \r\n"
-        "psubusb $f12, $f4, $f6                         \r\n"
-        "psubusb $f8, $f6, $f4                          \r\n"
-        "or $f8, $f8, $f12                              \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "or $f14, $f14, $f8                             \r\n"
-        "xor $f12, $f12, $f12                           \r\n"
-        "pcmpeqb $f14, $f14, $f12                       \r\n"
-        "mov.d $f10, $f2                                \r\n"
-        "mov.d $f12, $f4                                \r\n"
-        "xor $f8, $f2, $f6                              \r\n"
-        "and $f8, $f8, %[ff_pb_1]                       \r\n"
-        "pavgb $f2, $f2, $f6                            \r\n"
-        "psubusb $f2, $f2, $f8                          \r\n"
-        "pavgb $f2, $f2, $f0                            \r\n"
-        "xor $f8, $f4, $f0                              \r\n"
-        "and $f8, $f8, %[ff_pb_1]                       \r\n"
-        "pavgb $f4, $f4, $f0                            \r\n"
-        "psubusb $f4, $f4, $f8                          \r\n"
-        "pavgb $f4, $f4, $f6                            \r\n"
-        "psubb $f2, $f2, $f10                           \r\n"
-        "psubb $f4, $f4, $f12                           \r\n"
-        "and $f2, $f2, $f14                             \r\n"
-        "and $f4, $f4, $f14                             \r\n"
-        "paddb $f2, $f2, $f10                           \r\n"
-        "paddb $f4, $f4, $f12                           \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride),
-          [alpha]"r"((int64_t)alpha),[beta]"r"((int64_t)beta),
-          [ff_pb_1]"f"(ff_pb_1)
-        : "$f0","$f2","$f4","$f8","$f10","$f12","$f14","$f16"
-    );
-}
-
 void ff_deblock_v8_luma_8_mmi(uint8_t *pix, int stride, int alpha, int beta,
         int8_t *tc0)
 {
+    double ftmp[12];
+    mips_reg addr[2];
+    uint64_t low32;
+
     __asm__ volatile (
-        "daddu $8, %[stride], %[stride]                 \r\n"
-        "xor $f16, $f16, $f16                           \r\n"
-        "daddu $9, %[stride], $8                        \r\n"
-        "daddiu %[alpha], %[alpha], -0x1                \r\n"
-        "dsubu $9, $0, $9                               \r\n"
-        "daddiu %[beta], %[beta], -0x1                  \r\n"
-        "daddu $9, $9, %[pix]                           \r\n"
-        "ldc1 $f4, 0x0(%[pix])                          \r\n"
-        "gsldxc1 $f0, 0x0($9, %[stride])                \r\n"
-        "gsldxc1 $f2, 0x0($9, $8)                       \r\n"
-        "gsldxc1 $f6, 0x0(%[pix], %[stride])            \r\n"
-        "mtc1 %[alpha], $f8                             \r\n"
-        "mtc1 %[beta], $f10                             \r\n"
-        "pshufh $f8, $f8, $f16                          \r\n"
-        "pshufh $f10, $f10, $f16                        \r\n"
-        "packushb $f8, $f8, $f8                         \r\n"
-        "packushb $f10, $f10, $f10                      \r\n"
-        "psubusb $f12, $f4, $f2                         \r\n"
-        "psubusb $f14, $f2, $f4                         \r\n"
-        "or $f14, $f14, $f12                            \r\n"
-        "psubusb $f12, $f2, $f0                         \r\n"
-        "psubusb $f14, $f14, $f8                        \r\n"
-        "psubusb $f8, $f0, $f2                          \r\n"
-        "or $f8, $f8, $f12                              \r\n"
-        "psubusb $f12, $f4, $f6                         \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "or $f14, $f14, $f8                             \r\n"
-        "psubusb $f8, $f6, $f4                          \r\n"
-        "or $f8, $f8, $f12                              \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "or $f14, $f14, $f8                             \r\n"
-        "pcmpeqb $f14, $f14, $f16                       \r\n"
-        "pcmpeqb $f6, $f6, $f6                          \r\n"
-        "gslwlc1 $f8, 0x3(%[tc0])                       \r\n"
-        "gslwrc1 $f8, 0x0(%[tc0])                       \r\n"
-        "punpcklbh $f8, $f8, $f8                        \r\n"
-        "punpcklbh $f18, $f8, $f8                       \r\n"
-        "pcmpgtb $f8, $f18, $f6                         \r\n"
-        "ldc1 $f6, 0x0($9)                              \r\n"
-        "and $f20, $f8, $f14                            \r\n"
-        "psubusb $f14, $f6, $f2                         \r\n"
-        "psubusb $f12, $f2, $f6                         \r\n"
-        "psubusb $f14, $f14, $f10                       \r\n"
-        "psubusb $f12, $f12, $f10                       \r\n"
-        "pcmpeqb $f12, $f12, $f14                       \r\n"
-        "and $f12, $f12, $f20                           \r\n"
-        "and $f8, $f20, $f18                            \r\n"
-        "psubb $f14, $f8, $f12                          \r\n"
-        "and $f12, $f12, $f8                            \r\n"
-        "pavgb $f8, $f2, $f4                            \r\n"
-        "ldc1 $f22, 0x0($9)                             \r\n"
-        "pavgb $f6, $f6, $f8                            \r\n"
-        "xor $f8, $f8, $f22                             \r\n"
-        "and $f8, $f8, %[ff_pb_1]                       \r\n"
-        "psubusb $f6, $f6, $f8                          \r\n"
-        "psubusb $f8, $f0, $f12                         \r\n"
-        "paddusb $f12, $f12, $f0                        \r\n"
-        "pmaxub $f6, $f6, $f8                           \r\n"
-        "pminub $f6, $f6, $f12                          \r\n"
-        "gssdxc1 $f6, 0x0($9, %[stride])                \r\n"
-        "gsldxc1 $f8, 0x0(%[pix], $8)                   \r\n"
-        "psubusb $f6, $f8, $f4                          \r\n"
-        "psubusb $f12, $f4, $f8                         \r\n"
-        "psubusb $f6, $f6, $f10                         \r\n"
-        "psubusb $f12, $f12, $f10                       \r\n"
-        "pcmpeqb $f12, $f12, $f6                        \r\n"
-        "and $f12, $f12, $f20                           \r\n"
-        "psubb $f14, $f14, $f12                         \r\n"
-        "and $f10, $f18, $f12                           \r\n"
-        "gsldxc1 $f6, 0x0(%[pix], %[stride])            \r\n"
-        "pavgb $f12, $f2, $f4                           \r\n"
-        "gsldxc1 $f22, 0x0(%[pix], $8)                  \r\n"
-        "pavgb $f8, $f8, $f12                           \r\n"
-        "xor $f12, $f12, $f22                           \r\n"
-        "and $f12, $f12, %[ff_pb_1]                     \r\n"
-        "psubusb $f8, $f8, $f12                         \r\n"
-        "psubusb $f12, $f6, $f10                        \r\n"
-        "paddusb $f10, $f10, $f6                        \r\n"
-        "pmaxub $f8, $f8, $f12                          \r\n"
-        "pminub $f8, $f8, $f10                          \r\n"
-        "gssdxc1 $f8, 0x0(%[pix], %[stride])            \r\n"
-        "xor $f10, $f2, $f4                             \r\n"
-        "pcmpeqb $f8, $f8, $f8                          \r\n"
-        "and $f10, $f10, %[ff_pb_1]                     \r\n"
-        "xor $f6, $f6, $f8                              \r\n"
-        "xor $f8, $f8, $f2                              \r\n"
-        "pavgb $f6, $f6, $f0                            \r\n"
-        "pavgb $f6, $f6, %[ff_pb_3]                     \r\n"
-        "pavgb $f8, $f8, $f4                            \r\n"
-        "pavgb $f6, $f6, $f10                           \r\n"
-        "paddusb $f6, $f6, $f8                          \r\n"
-        "psubusb $f12, %[ff_pb_A1], $f6                 \r\n"
-        "psubusb $f6, $f6, %[ff_pb_A1]                  \r\n"
-        "pminub $f12, $f12, $f14                        \r\n"
-        "pminub $f6, $f6, $f14                          \r\n"
-        "psubusb $f2, $f2, $f12                         \r\n"
-        "psubusb $f4, $f4, $f6                          \r\n"
-        "paddusb $f2, $f2, $f6                          \r\n"
-        "paddusb $f4, $f4, $f12                         \r\n"
-        "gssdxc1 $f2, 0x0($9, $8)                       \r\n"
-        "sdc1 $f4, 0x0(%[pix])                          \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride),
-          [alpha]"r"((int64_t)alpha),[beta]"r"((int64_t)beta),[tc0]"r"(tc0),
-          [ff_pb_1]"f"(ff_pb_1),[ff_pb_3]"f"(ff_pb_3),[ff_pb_A1]"f"(ff_pb_A1)
-        : "$8","$9","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18","$f20","$f22"
+        PTR_ADDU   "%[addr0],   %[stride],      %[stride]               \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        PTR_ADDU   "%[addr1],   %[stride],      %[addr0]                \n\t"
+        "addi       %[alpha],   %[alpha],       -0x01                   \n\t"
+        PTR_SUBU   "%[addr1],   $0,             %[addr1]                \n\t"
+        "addi       %[beta],    %[beta],        -0x01                   \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[pix]                  \n\t"
+        "ldc1       %[ftmp3],   0x00(%[pix])                            \n\t"
+        "gsldxc1    %[ftmp1],   0x00(%[addr1],  %[stride])              \n\t"
+        "gsldxc1    %[ftmp2],   0x00(%[addr1],  %[addr0])               \n\t"
+        "gsldxc1    %[ftmp4],   0x00(%[pix],    %[stride])              \n\t"
+        "mtc1       %[alpha],   %[ftmp5]                                \n\t"
+        "mtc1       %[beta],    %[ftmp6]                                \n\t"
+        "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "pshufh     %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp3],       %[ftmp2]                \n\t"
+        "psubusb    %[ftmp8],   %[ftmp2],       %[ftmp3]                \n\t"
+        "or         %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp2],       %[ftmp1]                \n\t"
+        "psubusb    %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp1],       %[ftmp2]                \n\t"
+        "or         %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "or         %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp4],       %[ftmp3]                \n\t"
+        "or         %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "or         %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "pcmpeqb    %[ftmp8],   %[ftmp8],       %[ftmp0]                \n\t"
+        "pcmpeqb    %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        "uld        %[low32],   0x00(%[tc0])                            \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp9],   %[ftmp5],       %[ftmp5]                \n\t"
+        "pcmpgtb    %[ftmp5],   %[ftmp9],       %[ftmp4]                \n\t"
+        "ldc1       %[ftmp4],   0x00(%[addr1])                          \n\t"
+        "and        %[ftmp10],  %[ftmp5],       %[ftmp8]                \n\t"
+        "psubusb    %[ftmp8],   %[ftmp4],       %[ftmp2]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp2],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp8],   %[ftmp8],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+        "pcmpeqb    %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+        "and        %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+        "and        %[ftmp5],   %[ftmp10],      %[ftmp9]                \n\t"
+        "psubb      %[ftmp8],   %[ftmp5],       %[ftmp7]                \n\t"
+        "and        %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+        "pavgb      %[ftmp5],   %[ftmp2],       %[ftmp3]                \n\t"
+        "ldc1       %[ftmp11],  0x00(%[addr1])                          \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "xor        %[ftmp5],   %[ftmp5],       %[ftmp11]               \n\t"
+        "and        %[ftmp5],   %[ftmp5],       %[ff_pb_1]              \n\t"
+        "psubusb    %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp1],       %[ftmp7]                \n\t"
+        "paddusb    %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "pmaxub     %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "pminub     %[ftmp4],   %[ftmp4],       %[ftmp7]                \n\t"
+        "gssdxc1    %[ftmp4],   0x00(%[addr1],  %[stride])              \n\t"
+        "gsldxc1    %[ftmp5],   0x00(%[pix],    %[addr0])               \n\t"
+        "psubusb    %[ftmp4],   %[ftmp5],       %[ftmp3]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp3],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+        "pcmpeqb    %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+        "and        %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+        "psubb      %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+        "and        %[ftmp6],   %[ftmp9],       %[ftmp7]                \n\t"
+        "gsldxc1    %[ftmp4],   0x00(%[pix],    %[stride])              \n\t"
+        "pavgb      %[ftmp7],   %[ftmp2],       %[ftmp3]                \n\t"
+        "gsldxc1    %[ftmp11],  0x00(%[pix],    %[addr0])               \n\t"
+        "pavgb      %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "xor        %[ftmp7],   %[ftmp7],       %[ftmp11]               \n\t"
+        "and        %[ftmp7],   %[ftmp7],       %[ff_pb_1]              \n\t"
+        "psubusb    %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp4],       %[ftmp6]                \n\t"
+        "paddusb    %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+        "pmaxub     %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "pminub     %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "gssdxc1    %[ftmp5],   0x00(%[pix],    %[stride])              \n\t"
+        "xor        %[ftmp6],   %[ftmp2],       %[ftmp3]                \n\t"
+        "pcmpeqb    %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        "and        %[ftmp6],   %[ftmp6],       %[ff_pb_1]              \n\t"
+        "xor        %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "xor        %[ftmp5],   %[ftmp5],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp1]                \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ff_pb_3]              \n\t"
+        "pavgb      %[ftmp5],   %[ftmp5],       %[ftmp3]                \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "paddusb    %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp7],   %[ff_pb_A1],    %[ftmp4]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp4],       %[ff_pb_A1]             \n\t"
+        "pminub     %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+        "pminub     %[ftmp4],   %[ftmp4],       %[ftmp8]                \n\t"
+        "psubusb    %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "paddusb    %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "paddusb    %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "gssdxc1    %[ftmp2],   0x00(%[addr1],  %[addr0])               \n\t"
+        "sdc1       %[ftmp3],   0x00(%[pix])                            \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),          [ftmp11]"=&f"(ftmp[11]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [low32]"=&r"(low32)
+        : [pix]"r"(pix),                    [stride]"r"((mips_reg)stride),
+          [alpha]"r"((mips_reg)alpha),      [beta]"r"((mips_reg)beta),
+          [tc0]"r"(tc0),                    [ff_pb_1]"f"(ff_pb_1),
+          [ff_pb_3]"f"(ff_pb_3),            [ff_pb_A1]"f"(ff_pb_A1)
+        : "memory"
     );
 }
 
-void ff_deblock_v8_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha,
+static void deblock_v8_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha,
         int beta)
 {
-    uint64_t stack[0xa];
-
-    __asm__ volatile (
-        "ori $8, $0, 0x1                                \r\n"
-        "xor $f30, $f30, $f30                           \r\n"
-        "dmtc1 $8, $f16                                 \r\n"
-        "dsll $8, %[stride], 2                          \r\n"
-        "daddu $10, %[stride], %[stride]                \r\n"
-        "daddiu %[alpha], %[alpha], -0x1                \r\n"
-        "dsll $f20, $f16, $f16                          \r\n"
-        "bltz %[alpha], 1f                              \r\n"
-        "daddu $9, $10, %[stride]                       \r\n"
-        "daddiu %[beta], %[beta], -0x1                  \r\n"
-        "bltz %[beta], 1f                               \r\n"
-        "dsubu $8, $0, $8                               \r\n"
-        "daddu $8, $8, %[pix]                           \r\n"
-        "ldc1 $f4, 0x0(%[pix])                          \r\n"
-        "gsldxc1 $f0, 0x0($8, $10)                      \r\n"
-        "gsldxc1 $f2, 0x0($8, $9)                       \r\n"
-        "gsldxc1 $f6, 0x0(%[pix], %[stride])            \r\n"
-        "mtc1 %[alpha], $f8                             \r\n"
-        "mtc1 %[beta], $f10                             \r\n"
-        "pshufh $f8, $f8, $f30                          \r\n"
-        "pshufh $f10, $f10, $f30                        \r\n"
-        "packushb $f8, $f8, $f8                         \r\n"
-        "psubusb $f12, $f4, $f2                         \r\n"
-        "psubusb $f14, $f2, $f4                         \r\n"
-        "packushb $f10, $f10, $f10                      \r\n"
-        "or $f14, $f14, $f12                            \r\n"
-        "sdc1 $f8, 0x10+%[stack]                        \r\n"
-        "psubusb $f14, $f14, $f8                        \r\n"
-        "psubusb $f12, $f2, $f0                         \r\n"
-        "psubusb $f8, $f0, $f2                          \r\n"
-        "or $f8, $f8, $f12                              \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "or $f14, $f14, $f8                             \r\n"
-        "psubusb $f12, $f4, $f6                         \r\n"
-        "psubusb $f8, $f6, $f4                          \r\n"
-        "or $f8, $f8, $f12                              \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "or $f14, $f14, $f8                             \r\n"
-        "xor $f12, $f12, $f12                           \r\n"
-        "ldc1 $f8, 0x10+%[stack]                        \r\n"
-        "pcmpeqb $f14, $f14, $f12                       \r\n"
-        "sdc1 $f14, 0x20+%[stack]                       \r\n"
-        "pavgb $f8, $f8, $f30                           \r\n"
-        "psubusb $f14, $f4, $f2                         \r\n"
-        "pavgb $f8, $f8, %[ff_pb_1]                     \r\n"
-        "psubusb $f12, $f2, $f4                         \r\n"
-        "psubusb $f14, $f14, $f8                        \r\n"
-        "psubusb $f12, $f12, $f8                        \r\n"
-        "ldc1 $f28, 0x20+%[stack]                       \r\n"
-        "pcmpeqb $f12, $f12, $f14                       \r\n"
-        "and $f12, $f12, $f28                           \r\n"
-        "gsldxc1 $f28, 0x0($8, %[stride])               \r\n"
-        "psubusb $f14, $f28, $f2                        \r\n"
-        "psubusb $f8, $f2, $f28                         \r\n"
-        "psubusb $f14, $f14, $f10                       \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "pcmpeqb $f8, $f8, $f14                         \r\n"
-        "and $f8, $f8, $f12                             \r\n"
-        "gsldxc1 $f26, 0x0(%[pix], $10)                 \r\n"
-        "sdc1 $f8, 0x30+%[stack]                        \r\n"
-        "psubusb $f14, $f26, $f4                        \r\n"
-        "psubusb $f8, $f4, $f26                         \r\n"
-        "psubusb $f14, $f14, $f10                       \r\n"
-        "psubusb $f8, $f8, $f10                         \r\n"
-        "pcmpeqb $f8, $f8, $f14                         \r\n"
-        "and $f8, $f8, $f12                             \r\n"
-        "sdc1 $f8, 0x40+%[stack]                        \r\n"
-        "pavgb $f8, $f28, $f0                           \r\n"
-        "pavgb $f10, $f2, $f4                           \r\n"
-        "pavgb $f8, $f8, $f10                           \r\n"
-        "sdc1 $f10, 0x10+%[stack]                       \r\n"
-        "paddb $f12, $f28, $f0                          \r\n"
-        "paddb $f14, $f2, $f4                           \r\n"
-        "paddb $f12, $f12, $f14                         \r\n"
-        "mov.d $f14, $f12                               \r\n"
-        "sdc1 $f12, 0x0+%[stack]                        \r\n"
-        "psrlh $f12, $f12, $f16                         \r\n"
-        "pavgb $f12, $f12, $f30                         \r\n"
-        "xor $f12, $f12, $f8                            \r\n"
-        "and $f12, $f12, %[ff_pb_1]                     \r\n"
-        "psubb $f8, $f8, $f12                           \r\n"
-        "pavgb $f10, $f28, $f6                          \r\n"
-        "psubb $f12, $f28, $f6                          \r\n"
-        "paddb $f14, $f14, $f14                         \r\n"
-        "psubb $f14, $f14, $f12                         \r\n"
-        "and $f12, $f12, %[ff_pb_1]                     \r\n"
-        "psubb $f10, $f10, $f12                         \r\n"
-        "ldc1 $f24, 0x10+%[stack]                       \r\n"
-        "pavgb $f10, $f10, $f0                          \r\n"
-        "psrlh $f14, $f14, $f20                         \r\n"
-        "pavgb $f10, $f10, $f24                         \r\n"
-        "pavgb $f14, $f14, $f30                         \r\n"
-        "xor $f14, $f14, $f10                           \r\n"
-        "and $f14, $f14, %[ff_pb_1]                     \r\n"
-        "psubb $f10, $f10, $f14                         \r\n"
-        "xor $f14, $f2, $f6                             \r\n"
-        "pavgb $f12, $f2, $f6                           \r\n"
-        "and $f14, $f14, %[ff_pb_1]                     \r\n"
-        "psubb $f12, $f12, $f14                         \r\n"
-        "ldc1 $f24, 0x30+%[stack]                       \r\n"
-        "pavgb $f12, $f12, $f0                          \r\n"
-        "ldc1 $f22, 0x20+%[stack]                       \r\n"
-        "xor $f10, $f10, $f12                           \r\n"
-        "xor $f12, $f12, $f2                            \r\n"
-        "and $f10, $f10, $f24                           \r\n"
-        "and $f12, $f12, $f22                           \r\n"
-        "xor $f10, $f10, $f12                           \r\n"
-        "xor $f10, $f10, $f2                            \r\n"
-        "gssdxc1 $f10, 0x0($8, $9)                      \r\n"
-        "ldc1 $f10, 0x0($8)                             \r\n"
-        "paddb $f12, $f28, $f10                         \r\n"
-        "pavgb $f10, $f10, $f28                         \r\n"
-        "ldc1 $f22, 0x0+%[stack]                        \r\n"
-        "pavgb $f10, $f10, $f8                          \r\n"
-        "paddb $f12, $f12, $f12                         \r\n"
-        "paddb $f12, $f12, $f22                         \r\n"
-        "psrlh $f12, $f12, $f20                         \r\n"
-        "pavgb $f12, $f12, $f30                         \r\n"
-        "xor $f12, $f12, $f10                           \r\n"
-        "and $f12, $f12, %[ff_pb_1]                     \r\n"
-        "ldc1 $f22, 0x30+%[stack]                       \r\n"
-        "psubb $f10, $f10, $f12                         \r\n"
-        "xor $f8, $f8, $f0                              \r\n"
-        "xor $f10, $f10, $f28                           \r\n"
-        "and $f8, $f8, $f22                             \r\n"
-        "and $f10, $f10, $f22                           \r\n"
-        "xor $f8, $f8, $f0                              \r\n"
-        "xor $f10, $f10, $f28                           \r\n"
-        "gssdxc1 $f8, 0x0($8, $10)                      \r\n"
-        "gssdxc1 $f10, 0x0($8, %[stride])               \r\n"
-        "pavgb $f8, $f26, $f6                           \r\n"
-        "pavgb $f10, $f4, $f2                           \r\n"
-        "pavgb $f8, $f8, $f10                           \r\n"
-        "sdc1 $f10, 0x10+%[stack]                       \r\n"
-        "paddb $f12, $f26, $f6                          \r\n"
-        "paddb $f14, $f4, $f2                           \r\n"
-        "paddb $f12, $f12, $f14                         \r\n"
-        "mov.d $f14, $f12                               \r\n"
-        "sdc1 $f12, 0x0+%[stack]                        \r\n"
-        "psrlh $f12, $f12, $f16                         \r\n"
-        "pavgb $f12, $f12, $f30                         \r\n"
-        "xor $f12, $f12, $f8                            \r\n"
-        "and $f12, $f12, %[ff_pb_1]                     \r\n"
-        "psubb $f8, $f8, $f12                           \r\n"
-        "pavgb $f10, $f26, $f0                          \r\n"
-        "paddb $f14, $f14, $f14                         \r\n"
-        "psubb $f12, $f26, $f0                          \r\n"
-        "psubb $f14, $f14, $f12                         \r\n"
-        "and $f12, $f12, %[ff_pb_1]                     \r\n"
-        "psubb $f10, $f10, $f12                         \r\n"
-        "ldc1 $f22, 0x10+%[stack]                       \r\n"
-        "pavgb $f10, $f10, $f6                          \r\n"
-        "pavgb $f10, $f10, $f22                         \r\n"
-        "psrlh $f14, $f14, $f20                         \r\n"
-        "pavgb $f14, $f14, $f30                         \r\n"
-        "xor $f14, $f14, $f10                           \r\n"
-        "and $f14, $f14, %[ff_pb_1]                     \r\n"
-        "psubb $f10, $f10, $f14                         \r\n"
-        "xor $f14, $f4, $f0                             \r\n"
-        "pavgb $f12, $f4, $f0                           \r\n"
-        "and $f14, $f14, %[ff_pb_1]                     \r\n"
-        "ldc1 $f22, 0x40+%[stack]                       \r\n"
-        "psubb $f12, $f12, $f14                         \r\n"
-        "ldc1 $f24, 0x20+%[stack]                       \r\n"
-        "pavgb $f12, $f12, $f6                          \r\n"
-        "xor $f10, $f10, $f12                           \r\n"
-        "xor $f12, $f12, $f4                            \r\n"
-        "and $f10, $f10, $f22                           \r\n"
-        "and $f12, $f12, $f24                           \r\n"
-        "xor $f10, $f10, $f12                           \r\n"
-        "xor $f10, $f10, $f4                            \r\n"
-        "sdc1 $f10, 0x0(%[pix])                         \r\n"
-        "gsldxc1 $f10, 0x0(%[pix], $9)                  \r\n"
-        "paddb $f12, $f26, $f10                         \r\n"
-        "pavgb $f10, $f10, $f26                         \r\n"
-        "ldc1 $f22, 0x0+%[stack]                        \r\n"
-        "pavgb $f10, $f10, $f8                          \r\n"
-        "paddb $f12, $f12, $f12                         \r\n"
-        "paddb $f12, $f12, $f22                         \r\n"
-        "psrlh $f12, $f12, $f20                         \r\n"
-        "pavgb $f12, $f12, $f30                         \r\n"
-        "xor $f12, $f12, $f10                           \r\n"
-        "and $f12, $f12, %[ff_pb_1]                     \r\n"
-        "ldc1 $f22, 0x40+%[stack]                       \r\n"
-        "psubb $f10, $f10, $f12                         \r\n"
-        "xor $f8, $f8, $f6                              \r\n"
-        "xor $f10, $f10, $f26                           \r\n"
-        "and $f8, $f8, $f22                             \r\n"
-        "and $f10, $f10, $f22                           \r\n"
-        "xor $f8, $f8, $f6                              \r\n"
-        "xor $f10, $f10, $f26                           \r\n"
-        "gssdxc1 $f8, 0x0(%[pix], %[stride])            \r\n"
-        "gssdxc1 $f10, 0x0(%[pix], $10)                 \r\n"
-        "1:                                             \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride),
-          [alpha]"r"((int64_t)alpha),[beta]"r"((int64_t)beta),
-          [stack]"m"(stack[0]),[ff_pb_1]"f"(ff_pb_1)
-        : "$8","$9","$10","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14",
-          "$f16","$f18","$f20","$f22","$f24","$f26","$f28","$f30"
-    );
+    DECLARE_ALIGNED(8, const uint64_t, stack[0x0a]);
+    double ftmp[16];
+    uint64_t tmp[1];
+    mips_reg addr[3];
+
+__asm__ volatile (
+"ori        %[tmp0],    $0,             0x01                    \n\t"
+"xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+"mtc1       %[tmp0],    %[ftmp9]                                \n\t"
+PTR_SLL    "%[addr0],   %[stride],      0x02                    \n\t"
+PTR_ADDU   "%[addr2],   %[stride],      %[stride]               \n\t"
+PTR_ADDIU  "%[alpha],   %[alpha],       -0x01                   \n\t"
+PTR_SLL    "%[ftmp11],  %[ftmp9],       %[ftmp9]                \n\t"
+"bltz       %[alpha],   1f                                      \n\t"
+PTR_ADDU   "%[addr1],   %[addr2],       %[stride]               \n\t"
+PTR_ADDIU  "%[beta],    %[beta],        -0x01                   \n\t"
+"bltz       %[beta],    1f                                      \n\t"
+PTR_SUBU   "%[addr0],   $0,             %[addr0]                \n\t"
+PTR_ADDU   "%[addr0],   %[addr0],       %[pix]                  \n\t"
+"ldc1       %[ftmp3],   0x00(%[pix])                            \n\t"
+"gsldxc1    %[ftmp1],   0x00(%[addr0],  %[addr2])               \n\t"
+"gsldxc1    %[ftmp2],   0x00(%[addr0],  %[addr1])               \n\t"
+"gsldxc1    %[ftmp4],   0x00(%[pix],    %[stride])              \n\t"
+"mtc1       %[alpha],   %[ftmp5]                                \n\t"
+"mtc1       %[beta],    %[ftmp6]                                \n\t"
+"pshufh     %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+"pshufh     %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+"packushb   %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+"psubusb    %[ftmp7],   %[ftmp3],       %[ftmp2]                \n\t"
+"psubusb    %[ftmp8],   %[ftmp2],       %[ftmp3]                \n\t"
+"packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+"or         %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+"sdc1       %[ftmp5],   0x10+%[stack]                           \n\t"
+"psubusb    %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+"psubusb    %[ftmp7],   %[ftmp2],       %[ftmp1]                \n\t"
+"psubusb    %[ftmp5],   %[ftmp1],       %[ftmp2]                \n\t"
+"or         %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+"psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+"or         %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+"psubusb    %[ftmp7],   %[ftmp3],       %[ftmp4]                \n\t"
+"psubusb    %[ftmp5],   %[ftmp4],       %[ftmp3]                \n\t"
+"or         %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+"psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+"or         %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+"xor        %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+"ldc1       %[ftmp5],   0x10+%[stack]                           \n\t"
+"pcmpeqb    %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+"ldc1       %[ftmp10],  %[ff_pb_1]                              \n\t"
+"sdc1       %[ftmp8],   0x20+%[stack]                           \n\t"
+"pavgb      %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+"psubusb    %[ftmp8],   %[ftmp3],       %[ftmp2]                \n\t"
+"pavgb      %[ftmp5],   %[ftmp5],       %[ftmp10]               \n\t"
+"psubusb    %[ftmp7],   %[ftmp2],       %[ftmp3]                \n\t"
+"psubusb    %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+"psubusb    %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+"ldc1       %[ftmp15],  0x20+%[stack]                           \n\t"
+"pcmpeqb    %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+"and        %[ftmp7],   %[ftmp7],       %[ftmp15]               \n\t"
+"gsldxc1    %[ftmp15],  0x00(%[addr0],  %[stride])              \n\t"
+"psubusb    %[ftmp8],   %[ftmp15],      %[ftmp2]                \n\t"
+"psubusb    %[ftmp5],   %[ftmp2],       %[ftmp15]               \n\t"
+"psubusb    %[ftmp8],   %[ftmp8],       %[ftmp6]                \n\t"
+"psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+"pcmpeqb    %[ftmp5],   %[ftmp5],       %[ftmp8]                \n\t"
+"and        %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+"gsldxc1    %[ftmp14],  0x00(%[pix],    %[addr2])               \n\t"
+"sdc1       %[ftmp5],   0x30+%[stack]                           \n\t"
+"psubusb    %[ftmp8],   %[ftmp14],      %[ftmp3]                \n\t"
+"psubusb    %[ftmp5],   %[ftmp3],       %[ftmp14]               \n\t"
+"psubusb    %[ftmp8],   %[ftmp8],       %[ftmp6]                \n\t"
+"psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+"pcmpeqb    %[ftmp5],   %[ftmp5],       %[ftmp8]                \n\t"
+"and        %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+"sdc1       %[ftmp5],   0x40+%[stack]                           \n\t"
+"pavgb      %[ftmp5],   %[ftmp15],      %[ftmp1]                \n\t"
+"pavgb      %[ftmp6],   %[ftmp2],       %[ftmp3]                \n\t"
+"pavgb      %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+"sdc1       %[ftmp6],   0x10+%[stack]                           \n\t"
+"paddb      %[ftmp7],   %[ftmp15],      %[ftmp1]                \n\t"
+"paddb      %[ftmp8],   %[ftmp2],       %[ftmp3]                \n\t"
+"paddb      %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+"mov.d      %[ftmp8],   %[ftmp7]                                \n\t"
+"sdc1       %[ftmp7],   0x00+%[stack]                           \n\t"
+"psrlh      %[ftmp7],   %[ftmp7],       %[ftmp9]                \n\t"
+"pavgb      %[ftmp7],   %[ftmp7],       %[ftmp0]                \n\t"
+"xor        %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+"and        %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+"psubb      %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+"pavgb      %[ftmp6],   %[ftmp15],      %[ftmp4]                \n\t"
+"psubb      %[ftmp7],   %[ftmp15],      %[ftmp4]                \n\t"
+"paddb      %[ftmp8],   %[ftmp8],       %[ftmp8]                \n\t"
+"psubb      %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+"and        %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+"psubb      %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+"ldc1       %[ftmp13],  0x10+%[stack]                           \n\t"
+"pavgb      %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+"psrlh      %[ftmp8],   %[ftmp8],       %[ftmp11]               \n\t"
+"pavgb      %[ftmp6],   %[ftmp6],       %[ftmp13]               \n\t"
+"pavgb      %[ftmp8],   %[ftmp8],       %[ftmp0]                \n\t"
+"xor        %[ftmp8],   %[ftmp8],       %[ftmp6]                \n\t"
+"and        %[ftmp8],   %[ftmp8],       %[ftmp10]               \n\t"
+"psubb      %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+"xor        %[ftmp8],   %[ftmp2],       %[ftmp4]                \n\t"
+"pavgb      %[ftmp7],   %[ftmp2],       %[ftmp4]                \n\t"
+"and        %[ftmp8],   %[ftmp8],       %[ftmp10]               \n\t"
+"psubb      %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+"ldc1       %[ftmp13],  0x30+%[stack]                           \n\t"
+"pavgb      %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+"ldc1       %[ftmp12],  0x20+%[stack]                           \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+"xor        %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+"and        %[ftmp6],   %[ftmp6],       %[ftmp13]               \n\t"
+"and        %[ftmp7],   %[ftmp7],       %[ftmp12]               \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp2]                \n\t"
+"gssdxc1    %[ftmp6],   0x00(%[addr0],  %[addr1])               \n\t"
+"ldc1       %[ftmp6],   0x00(%[addr0])                          \n\t"
+"paddb      %[ftmp7],   %[ftmp15],      %[ftmp6]                \n\t"
+"pavgb      %[ftmp6],   %[ftmp6],       %[ftmp15]               \n\t"
+"ldc1       %[ftmp12],  0x00+%[stack]                           \n\t"
+"pavgb      %[ftmp6],   %[ftmp6],       %[ftmp5]                \n\t"
+"paddb      %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+"paddb      %[ftmp7],   %[ftmp7],       %[ftmp12]               \n\t"
+"psrlh      %[ftmp7],   %[ftmp7],       %[ftmp11]               \n\t"
+"pavgb      %[ftmp7],   %[ftmp7],       %[ftmp0]                \n\t"
+"xor        %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+"and        %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+"ldc1       %[ftmp12],  0x30+%[stack]                           \n\t"
+"psubb      %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+"xor        %[ftmp5],   %[ftmp5],       %[ftmp1]                \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp15]               \n\t"
+"and        %[ftmp5],   %[ftmp5],       %[ftmp12]               \n\t"
+"and        %[ftmp6],   %[ftmp6],       %[ftmp12]               \n\t"
+"xor        %[ftmp5],   %[ftmp5],       %[ftmp1]                \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp15]               \n\t"
+"gssdxc1    %[ftmp5],   0x00(%[addr0],  %[addr2])               \n\t"
+"gssdxc1    %[ftmp6],   0x00(%[addr0],  %[stride])              \n\t"
+"pavgb      %[ftmp5],   %[ftmp14],      %[ftmp4]                \n\t"
+"pavgb      %[ftmp6],   %[ftmp3],       %[ftmp2]                \n\t"
+"pavgb      %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+"sdc1       %[ftmp6],   0x10+%[stack]                           \n\t"
+"paddb      %[ftmp7],   %[ftmp14],      %[ftmp4]                \n\t"
+"paddb      %[ftmp8],   %[ftmp3],       %[ftmp2]                \n\t"
+"paddb      %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+"mov.d      %[ftmp8],   %[ftmp7]                                \n\t"
+"sdc1       %[ftmp7],   0x00+%[stack]                           \n\t"
+"psrlh      %[ftmp7],   %[ftmp7],       %[ftmp9]                \n\t"
+"pavgb      %[ftmp7],   %[ftmp7],       %[ftmp0]                \n\t"
+"xor        %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+"and        %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+"psubb      %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+"pavgb      %[ftmp6],   %[ftmp14],      %[ftmp1]                \n\t"
+"paddb      %[ftmp8],   %[ftmp8],       %[ftmp8]                \n\t"
+"psubb      %[ftmp7],   %[ftmp14],      %[ftmp1]                \n\t"
+"psubb      %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+"and        %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+"psubb      %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+"ldc1       %[ftmp12],  0x10+%[stack]                           \n\t"
+"pavgb      %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+"pavgb      %[ftmp6],   %[ftmp6],       %[ftmp12]               \n\t"
+"psrlh      %[ftmp8],   %[ftmp8],       %[ftmp11]               \n\t"
+"pavgb      %[ftmp8],   %[ftmp8],       %[ftmp0]                \n\t"
+"xor        %[ftmp8],   %[ftmp8],       %[ftmp6]                \n\t"
+"and        %[ftmp8],   %[ftmp8],       %[ftmp10]               \n\t"
+"psubb      %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+"xor        %[ftmp8],   %[ftmp3],       %[ftmp1]                \n\t"
+"pavgb      %[ftmp7],   %[ftmp3],       %[ftmp1]                \n\t"
+"and        %[ftmp8],   %[ftmp8],       %[ftmp10]               \n\t"
+"ldc1       %[ftmp12],  0x40+%[stack]                           \n\t"
+"psubb      %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+"ldc1       %[ftmp13],  0x20+%[stack]                           \n\t"
+"pavgb      %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+"xor        %[ftmp7],   %[ftmp7],       %[ftmp3]                \n\t"
+"and        %[ftmp6],   %[ftmp6],       %[ftmp12]               \n\t"
+"and        %[ftmp7],   %[ftmp7],       %[ftmp13]               \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp3]                \n\t"
+"sdc1       %[ftmp6],   0x00(%[pix])                            \n\t"
+"gsldxc1    %[ftmp6],   0x00(%[pix],    %[addr1])               \n\t"
+"paddb      %[ftmp7],   %[ftmp14],      %[ftmp6]                \n\t"
+"pavgb      %[ftmp6],   %[ftmp6],       %[ftmp14]               \n\t"
+"ldc1       %[ftmp12],  0x00+%[stack]                           \n\t"
+"pavgb      %[ftmp6],   %[ftmp6],       %[ftmp5]                \n\t"
+"paddb      %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+"paddb      %[ftmp7],   %[ftmp7],       %[ftmp12]               \n\t"
+"psrlh      %[ftmp7],   %[ftmp7],       %[ftmp11]               \n\t"
+"pavgb      %[ftmp7],   %[ftmp7],       %[ftmp0]                \n\t"
+"xor        %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+"and        %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+"ldc1       %[ftmp12],  0x40+%[stack]                           \n\t"
+"psubb      %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+"xor        %[ftmp5],   %[ftmp5],       %[ftmp4]                \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp14]               \n\t"
+"and        %[ftmp5],   %[ftmp5],       %[ftmp12]               \n\t"
+"and        %[ftmp6],   %[ftmp6],       %[ftmp12]               \n\t"
+"xor        %[ftmp5],   %[ftmp5],       %[ftmp4]                \n\t"
+"xor        %[ftmp6],   %[ftmp6],       %[ftmp14]               \n\t"
+"gssdxc1    %[ftmp5],   0x00(%[pix],    %[stride])              \n\t"
+"gssdxc1    %[ftmp6],   0x00(%[pix],    %[addr2])               \n\t"
+"1:                                                             \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),          [ftmp11]"=&f"(ftmp[11]),
+          [ftmp12]"=&f"(ftmp[12]),          [ftmp13]"=&f"(ftmp[13]),
+          [ftmp14]"=&f"(ftmp[14]),          [ftmp15]"=&f"(ftmp[15]),
+  [tmp0]"=&r"(tmp[0]),
+  [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+  [addr2]"=&r"(addr[2]),
+  [alpha]"+&r"(alpha),              [beta]"+&r"(beta)
+        : [pix]"r"(pix),                    [stride]"r"((mips_reg)stride),
+  [stack]"m"(stack[0]),             [ff_pb_1]"m"(ff_pb_1)
+: "memory"
+);
 }
 
 void ff_deblock_v_chroma_8_mmi(uint8_t *pix, int stride, int alpha, int beta,
         int8_t *tc0)
 {
-    __asm__ volatile (
-        "daddiu %[alpha], %[alpha], -0x1                \r\n"
-        "daddiu %[beta], %[beta], -0x1                  \r\n"
-        "or $16, $0, %[pix]                             \r\n"
-        "dsubu $16, $16, %[stride]                      \r\n"
-        "dsubu $16, $16, %[stride]                      \r\n"
-        "ldc1 $f0, 0x0($16)                             \r\n"
-        "gsldxc1 $f2, 0x0($16, %[stride])               \r\n"
-        "ldc1 $f4, 0x0(%[pix])                          \r\n"
-        "gsldxc1 $f6, 0x0(%[pix], %[stride])            \r\n"
-        : [pix]"+r"(pix),[stride]"+r"(stride),[alpha]"+r"(alpha),
-          [beta]"+r"(beta)
-        : [tc0]"r"(tc0)
-        : "$16","$f2","$f4"
-    );
-
-    chroma_inter_body_mmi(pix, stride, alpha, beta, tc0);
+    double ftmp[9];
+    mips_reg addr[1];
+    uint64_t low32;
 
     __asm__ volatile (
-        "gssdxc1 $f2, 0x0($16, %[stride])               \r\n"
-        "sdc1 $f4, 0x0(%[pix])                          \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride)
-        : "$16","$f2","$f4"
+        "addi       %[alpha],   %[alpha],       -0x01                   \n\t"
+        "addi       %[beta],    %[beta],        -0x01                   \n\t"
+        "or         %[addr0],   $0,             %[pix]                  \n\t"
+        PTR_SUBU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        PTR_SUBU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "ldc1       %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldxc1    %[ftmp2],   0x00(%[addr0],  %[stride])              \n\t"
+        "ldc1       %[ftmp3],   0x00(%[pix])                            \n\t"
+        "gsldxc1    %[ftmp4],   0x00(%[pix],    %[stride])              \n\t"
+
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "mtc1       %[alpha],   %[ftmp5]                                \n\t"
+        "mtc1       %[beta],    %[ftmp6]                                \n\t"
+        "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "pshufh     %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp3],       %[ftmp2]                \n\t"
+        "psubusb    %[ftmp8],   %[ftmp2],       %[ftmp3]                \n\t"
+        "or         %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp2],       %[ftmp1]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp1],       %[ftmp2]                \n\t"
+        "or         %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "or         %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp4],       %[ftmp3]                \n\t"
+        "or         %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "or         %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "pcmpeqb    %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+        "uld        %[low32],   0x00(%[tc0])                            \n\t"
+        "mtc1       %[low32],   %[ftmp7]                                \n\t"
+        "punpcklbh  %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "and        %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+        "pcmpeqb    %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        "xor        %[ftmp6],   %[ftmp2],       %[ftmp3]                \n\t"
+        "xor        %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "and        %[ftmp6],   %[ftmp6],       %[ff_pb_1]              \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp1]                \n\t"
+        "xor        %[ftmp5],   %[ftmp5],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ff_pb_3]              \n\t"
+        "pavgb      %[ftmp5],   %[ftmp5],       %[ftmp3]                \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "paddusb    %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp7],   %[ff_pb_A1],    %[ftmp4]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp4],       %[ff_pb_A1]             \n\t"
+        "pminub     %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+        "pminub     %[ftmp4],   %[ftmp4],       %[ftmp8]                \n\t"
+        "psubusb    %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "paddusb    %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "paddusb    %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+
+        "gssdxc1    %[ftmp2],   0x00(%[addr0],  %[stride])              \n\t"
+        "sdc1       %[ftmp3],   0x00(%[pix])                            \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),
+          [addr0]"=&r"(addr[0]),
+          [low32]"=&r"(low32)
+        : [pix]"r"(pix),                    [stride]"r"((mips_reg)stride),
+          [alpha]"r"(alpha),                [beta]"r"(beta),
+          [tc0]"r"(tc0),                    [ff_pb_1]"f"(ff_pb_1),
+          [ff_pb_3]"f"(ff_pb_3),            [ff_pb_A1]"f"(ff_pb_A1)
+        : "memory"
     );
 }
 
 void ff_deblock_v_chroma_intra_8_mmi(uint8_t *pix, int stride, int alpha,
         int beta)
 {
-    __asm__ volatile (
-        "daddiu %[alpha], %[alpha], -0x1                \r\n"
-        "daddiu %[beta], %[beta], -0x1                  \r\n"
-        "or $16, $0, %[pix]                             \r\n"
-        "dsubu $16, $16, %[stride]                      \r\n"
-        "dsubu $16, $16, %[stride]                      \r\n"
-        "ldc1 $f0, 0x0($16)                             \r\n"
-        "gsldxc1 $f2, 0x0($16, %[stride])               \r\n"
-        "ldc1 $f4, 0x0(%[pix])                          \r\n"
-        "gsldxc1 $f6, 0x0(%[pix], %[stride])            \r\n"
-        : [pix]"+r"(pix),[stride]"+r"(stride),[alpha]"+r"(alpha),
-          [beta]"+r"(beta)
-        ::"$16","$f0","$f2","$f4","$f6"
-    );
-
-    chroma_intra_body_mmi(pix, stride, alpha, beta);
+    double ftmp[9];
+    mips_reg addr[1];
 
     __asm__ volatile (
-        "gssdxc1 $f2, 0x0($16, %[stride])               \r\n"
-        "sdc1 $f4, 0x0(%[pix])                          \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride)
-        : "$16","$f2","$f4"
+        "addi       %[alpha],   %[alpha],       -0x01                   \n\t"
+        "addi       %[beta],    %[beta],        -0x01                   \n\t"
+        "or         %[addr0],   $0,             %[pix]                  \n\t"
+        PTR_SUBU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        PTR_SUBU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "ldc1       %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldxc1    %[ftmp2],   0x00(%[addr0],  %[stride])              \n\t"
+        "ldc1       %[ftmp3],   0x00(%[pix])                            \n\t"
+        "gsldxc1    %[ftmp4],   0x00(%[pix],    %[stride])              \n\t"
+
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "mtc1       %[alpha],   %[ftmp5]                                \n\t"
+        "mtc1       %[beta],    %[ftmp6]                                \n\t"
+        "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "pshufh     %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp3],       %[ftmp2]                \n\t"
+        "psubusb    %[ftmp8],   %[ftmp2],       %[ftmp3]                \n\t"
+        "or         %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp2],       %[ftmp1]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp1],       %[ftmp2]                \n\t"
+        "or         %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "or         %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp4],       %[ftmp3]                \n\t"
+        "or         %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "or         %[ftmp8],   %[ftmp8],       %[ftmp5]                \n\t"
+        "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "pcmpeqb    %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+        "mov.d      %[ftmp6],   %[ftmp2]                                \n\t"
+        "mov.d      %[ftmp7],   %[ftmp3]                                \n\t"
+        "xor        %[ftmp5],   %[ftmp2],       %[ftmp4]                \n\t"
+        "and        %[ftmp5],   %[ftmp5],       %[ff_pb_1]              \n\t"
+        "pavgb      %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "pavgb      %[ftmp2],   %[ftmp2],       %[ftmp1]                \n\t"
+        "xor        %[ftmp5],   %[ftmp3],       %[ftmp1]                \n\t"
+        "and        %[ftmp5],   %[ftmp5],       %[ff_pb_1]              \n\t"
+        "pavgb      %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "psubusb    %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "pavgb      %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubb      %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "psubb      %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "and        %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "and        %[ftmp3],   %[ftmp3],       %[ftmp8]                \n\t"
+        "paddb      %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "paddb      %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+
+        "gssdxc1    %[ftmp2],   0x00(%[addr0],  %[stride])              \n\t"
+        "sdc1       %[ftmp3],   0x00(%[pix])                            \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),
+          [addr0]"=&r"(addr[0])
+        : [pix]"r"(pix),                    [stride]"r"((mips_reg)stride),
+          [alpha]"r"(alpha),                [beta]"r"(beta),
+          [ff_pb_1]"f"(ff_pb_1)
+        : "memory"
     );
 }
 
 void ff_deblock_h_chroma_8_mmi(uint8_t *pix, int stride, int alpha, int beta,
         int8_t *tc0)
 {
-    __asm__ volatile (
-        "daddiu %[alpha], %[alpha], -0x1                \r\n"
-        "daddiu %[beta], %[beta], -0x1                  \r\n"
-        "daddu $16, %[stride], %[stride]                \r\n"
-        "daddiu %[pix], %[pix], -0x2                    \r\n"
-        "daddu $17, $16, %[stride]                      \r\n"
-        "daddu $19, $16, $16                            \r\n"
-        "or $18, $0, %[pix]                             \r\n"
-        "daddu %[pix], %[pix], $17                      \r\n"
-        "gslwlc1 $f0, 0x3($18)                          \r\n"
-        "daddu $12, $18, %[stride]                      \r\n"
-        "gslwrc1 $f0, 0x0($18)                          \r\n"
-        "gslwlc1 $f4, 0x3($12)                          \r\n"
-        "daddu $13, $18, $16                            \r\n"
-        "gslwrc1 $f4, 0x0($12)                          \r\n"
-        "gslwlc1 $f2, 0x3($13)                          \r\n"
-        "gslwrc1 $f2, 0x0($13)                          \r\n"
-        "gslwlc1 $f6, 0x3(%[pix])                       \r\n"
-        "gslwrc1 $f6, 0x0(%[pix])                       \r\n"
-        "punpcklbh $f0, $f0, $f4                        \r\n"
-        "punpcklbh $f2, $f2, $f6                        \r\n"
-        "daddu $12, %[pix], %[stride]                   \r\n"
-        "punpckhhw $f4, $f0, $f2                        \r\n"
-        "punpcklhw $f0, $f0, $f2                        \r\n"
-        "gslwlc1 $f8, 0x3($12)                          \r\n"
-        "daddu $13, %[pix], $16                         \r\n"
-        "gslwrc1 $f8, 0x0($12)                          \r\n"
-        "gslwlc1 $f12, 0x3($13)                         \r\n"
-        "daddu $12, %[pix], $17                         \r\n"
-        "gslwrc1 $f12, 0x0($13)                         \r\n"
-        "gslwlc1 $f10, 0x3($12)                         \r\n"
-        "daddu $13, %[pix], $19                         \r\n"
-        "gslwrc1 $f10, 0x0($12)                         \r\n"
-        "gslwlc1 $f14, 0x3($13)                         \r\n"
-        "gslwrc1 $f14, 0x0($13)                         \r\n"
-        "punpcklbh $f8, $f8, $f12                       \r\n"
-        "punpcklbh $f10, $f10, $f14                     \r\n"
-        "mov.d $f12, $f8                                \r\n"
-        "punpcklhw $f8, $f8, $f10                       \r\n"
-        "punpckhhw $f12, $f12, $f10                     \r\n"
-        "punpckhwd $f2, $f0, $f8                        \r\n"
-        "punpckhwd $f6, $f4, $f12                       \r\n"
-        "punpcklwd $f0, $f0, $f8                        \r\n"
-        "punpcklwd $f4, $f4, $f12                       \r\n"
-        "mov.d $f20, $f0                                \r\n"
-        "mov.d $f22, $f6                                \r\n"
-        : [pix]"+r"(pix),[stride]"+r"(stride),[alpha]"+r"(alpha),
-          [beta]"+r"(beta)
-        ::"$12","$13","$16","$17","$18","$19","$f0","$f2","$f4","$f6","$f8",
-          "$f10","$f12","$f14","$f20","$f22"
-    );
-
-    chroma_inter_body_mmi(pix, stride, alpha, beta, tc0);
+    double ftmp[11];
+    mips_reg addr[6];
+    uint64_t low32;
 
     __asm__ volatile (
-        "punpckhwd $f8, $f20, $f20                      \r\n"
-        "punpckhwd $f10, $f2, $f2                       \r\n"
-        "punpckhwd $f12, $f4, $f4                       \r\n"
-        "punpcklbh $f0, $f20, $f2                       \r\n"
-        "punpcklbh $f4, $f4, $f22                       \r\n"
-        "punpcklhw $f2, $f0, $f4                        \r\n"
-        "punpckhhw $f0, $f0, $f4                        \r\n"
-        "gsswlc1 $f2, 0x3($18)                          \r\n"
-        "gsswrc1 $f2, 0x0($18)                          \r\n"
-        "daddu $12, $18, %[stride]                      \r\n"
-        "punpckhwd $f2, $f2, $f2                        \r\n"
-        "gsswlc1 $f2, 0x3($12)                          \r\n"
-        "daddu $13, $18, $16                            \r\n"
-        "gsswrc1 $f2, 0x0($12)                          \r\n"
-        "gsswlc1 $f0, 0x3($13)                          \r\n"
-        "gsswrc1 $f0, 0x0($13)                          \r\n"
-        "punpckhwd $f0, $f0, $f0                        \r\n"
-        "punpckhwd $f6, $f22, $f22                      \r\n"
-        "gsswlc1 $f0, 0x3(%[pix])                       \r\n"
-        "gsswrc1 $f0, 0x0(%[pix])                       \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "punpcklbh $f12, $f12, $f6                      \r\n"
-        "daddu $12, %[pix], %[stride]                   \r\n"
-        "punpcklhw $f10, $f8, $f12                      \r\n"
-        "punpckhhw $f8, $f8, $f12                       \r\n"
-        "gsswlc1 $f10, 0x3($12)                         \r\n"
-        "gsswrc1 $f10, 0x0($12)                         \r\n"
-        "punpckhwd $f10, $f10, $f10                     \r\n"
-        "daddu $12, %[pix], $16                         \r\n"
-        "daddu $13, %[pix], $17                         \r\n"
-        "gsswlc1 $f10, 0x3($12)                         \r\n"
-        "gsswrc1 $f10, 0x0($12)                         \r\n"
-        "gsswlc1 $f8, 0x3($13)                          \r\n"
-        "daddu $12, %[pix], $19                         \r\n"
-        "punpckhwd $f20, $f8, $f8                       \r\n"
-        "gsswrc1 $f8, 0x0($13)                          \r\n"
-        "gsswlc1 $f20, 0x3($12)                         \r\n"
-        "gsswrc1 $f20, 0x0($12)                         \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride)
-        : "$12","$13","$16","$17","$18","$19","$f0","$f2","$f4","$f6","$f8",
-          "$f10","$f12","$f20"
+        "addi       %[alpha],   %[alpha],       -0x01                   \n\t"
+        "addi       %[beta],    %[beta],        -0x01                   \n\t"
+        PTR_ADDU   "%[addr0],   %[stride],      %[stride]               \n\t"
+        PTR_ADDI   "%[pix],     %[pix],         -0x02                   \n\t"
+        PTR_ADDU   "%[addr1],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr2],   %[addr0],       %[addr0]                \n\t"
+        "or         %[addr5],   $0,             %[pix]                  \n\t"
+        PTR_ADDU   "%[pix],     %[pix],         %[addr1]                \n\t"
+        "uld        %[low32],   0x00(%[addr5])                          \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        PTR_ADDU   "%[addr3],   %[addr5],       %[stride]               \n\t"
+        "uld        %[low32],   0x00(%[addr3])                          \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        PTR_ADDU   "%[addr4],   %[addr5],       %[addr0]                \n\t"
+        "uld        %[low32],   0x00(%[addr4])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   0x00(%[pix])                            \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[stride]               \n\t"
+        "punpckhhw  %[ftmp2],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "uld        %[low32],   0x00(%[addr3])                          \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        PTR_ADDU   "%[addr4],   %[pix],         %[addr0]                \n\t"
+        "uld        %[low32],   0x00(%[addr4])                          \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[addr1]                \n\t"
+        "uld        %[low32],   0x00(%[addr3])                          \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        PTR_ADDU   "%[addr4],   %[pix],         %[addr2]                \n\t"
+        "uld        %[low32],   0x00(%[addr4])                          \n\t"
+        "mtc1       %[low32],   %[ftmp7]                                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "mov.d      %[ftmp6],   %[ftmp4]                                \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpckhhw  %[ftmp6],   %[ftmp6],       %[ftmp5]                \n\t"
+        "punpckhwd  %[ftmp1],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpckhwd  %[ftmp3],   %[ftmp2],       %[ftmp6]                \n\t"
+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpcklwd  %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "mov.d      %[ftmp9],   %[ftmp0]                                \n\t"
+        "mov.d      %[ftmp10],  %[ftmp3]                                \n\t"
+
+        "xor        %[ftmp8],   %[ftmp8],       %[ftmp8]                \n\t"
+        "mtc1       %[alpha],   %[ftmp4]                                \n\t"
+        "mtc1       %[beta],    %[ftmp5]                                \n\t"
+        "pshufh     %[ftmp4],   %[ftmp4],       %[ftmp8]                \n\t"
+        "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp8]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        "packushb   %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp6],   %[ftmp2],       %[ftmp1]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp1],       %[ftmp2]                \n\t"
+        "or         %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp6],   %[ftmp1],       %[ftmp0]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp0],       %[ftmp1]                \n\t"
+        "or         %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "or         %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp6],   %[ftmp2],       %[ftmp3]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp3],       %[ftmp2]                \n\t"
+        "or         %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "or         %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+        "xor        %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "pcmpeqb    %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+        "uld        %[low32],   0x00(%[tc0])                            \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "and        %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+        "pcmpeqb    %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        "xor        %[ftmp5],   %[ftmp1],       %[ftmp2]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "and        %[ftmp5],   %[ftmp5],       %[ff_pb_1]              \n\t"
+        "pavgb      %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "xor        %[ftmp4],   %[ftmp4],       %[ftmp1]                \n\t"
+        "pavgb      %[ftmp3],   %[ftmp3],       %[ff_pb_3]              \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "paddusb    %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp6],   %[ff_pb_A1],    %[ftmp3]                \n\t"
+        "psubusb    %[ftmp3],   %[ftmp3],       %[ff_pb_A1]             \n\t"
+        "pminub     %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+        "pminub     %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "psubusb    %[ftmp1],   %[ftmp1],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "paddusb    %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "paddusb    %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+
+        "punpckhwd  %[ftmp4],   %[ftmp9],       %[ftmp9]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp1],       %[ftmp1]                \n\t"
+        "punpckhwd  %[ftmp6],   %[ftmp2],       %[ftmp2]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp9],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp10]               \n\t"
+        "punpcklhw  %[ftmp1],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[addr5])                          \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr5],       %[stride]               \n\t"
+        "punpckhwd  %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr4],   %[addr5],       %[addr0]                \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[addr3])                          \n\t"
+        "gsswlc1    %[ftmp0],   0x03(%[addr4])                          \n\t"
+        "gsswrc1    %[ftmp0],   0x00(%[addr4])                          \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpckhwd  %[ftmp3],   %[ftmp10],      %[ftmp10]               \n\t"
+        "gsswlc1    %[ftmp0],   0x03(%[pix])                            \n\t"
+        "gsswrc1    %[ftmp0],   0x00(%[pix])                            \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[stride]               \n\t"
+        "punpcklhw  %[ftmp5],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpckhhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "gsswlc1    %[ftmp5],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp5],   0x00(%[addr3])                          \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[addr0]                \n\t"
+        PTR_ADDU   "%[addr4],   %[pix],         %[addr1]                \n\t"
+        "gsswlc1    %[ftmp5],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp5],   0x00(%[addr3])                          \n\t"
+        "gsswlc1    %[ftmp4],   0x03(%[addr4])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[addr2]                \n\t"
+        "punpckhwd  %[ftmp9],   %[ftmp4],       %[ftmp4]                \n\t"
+        "gsswrc1    %[ftmp4],   0x00(%[addr4])                          \n\t"
+        "gsswlc1    %[ftmp9],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp9],   0x00(%[addr3])                          \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),            [addr5]"=&r"(addr[5]),
+          [pix]"+&r"(pix),
+          [low32]"=&r"(low32)
+        : [alpha]"r"(alpha),                [beta]"r"(beta),
+          [stride]"r"((mips_reg)stride),    [tc0]"r"(tc0),
+          [ff_pb_1]"f"(ff_pb_1),            [ff_pb_3]"f"(ff_pb_3),
+          [ff_pb_A1]"f"(ff_pb_A1)
+        : "memory"
     );
 }
 
 void ff_deblock_h_chroma_intra_8_mmi(uint8_t *pix, int stride, int alpha,
         int beta)
 {
-    __asm__ volatile (
-        "daddiu %[alpha], %[alpha], -0x1                \r\n"
-        "daddiu %[beta], %[beta], -0x1                  \r\n"
-        "daddu $16, %[stride], %[stride]                \r\n"
-        "daddiu %[pix], %[pix], -0x2                    \r\n"
-        "daddu $17, $16, %[stride]                      \r\n"
-        "daddu $19, $16, $16                            \r\n"
-        "or $18, $0, %[pix]                             \r\n"
-        "daddu %[pix], %[pix], $17                      \r\n"
-        "gslwlc1 $f0, 0x3($18)                          \r\n"
-        "daddu $12, $18, %[stride]                      \r\n"
-        "gslwrc1 $f0, 0x0($18)                          \r\n"
-        "gslwlc1 $f4, 0x3($12)                          \r\n"
-        "daddu $13, $18, $16                            \r\n"
-        "gslwrc1 $f4, 0x0($12)                          \r\n"
-        "gslwlc1 $f2, 0x3($13)                          \r\n"
-        "gslwrc1 $f2, 0x0($13)                          \r\n"
-        "gslwlc1 $f6, 0x3(%[pix])                       \r\n"
-        "gslwrc1 $f6, 0x0(%[pix])                       \r\n"
-        "punpcklbh $f0, $f0, $f4                        \r\n"
-        "punpcklbh $f2, $f2, $f6                        \r\n"
-        "daddu $12, %[pix], %[stride]                   \r\n"
-        "punpckhhw $f4, $f0, $f2                        \r\n"
-        "punpcklhw $f0, $f0, $f2                        \r\n"
-        "gslwlc1 $f8, 0x3($12)                          \r\n"
-        "daddu $13, %[pix], $16                         \r\n"
-        "gslwrc1 $f8, 0x0($12)                          \r\n"
-        "gslwlc1 $f12, 0x3($13)                         \r\n"
-        "daddu $12, %[pix], $17                         \r\n"
-        "gslwrc1 $f12, 0x0($13)                         \r\n"
-        "gslwlc1 $f10, 0x3($12)                         \r\n"
-        "daddu $13, %[pix], $19                         \r\n"
-        "gslwrc1 $f10, 0x0($12)                         \r\n"
-        "gslwlc1 $f14, 0x3($13)                         \r\n"
-        "gslwrc1 $f14, 0x0($13)                         \r\n"
-        "punpcklbh $f8, $f8, $f12                       \r\n"
-        "punpcklbh $f10, $f10, $f14                     \r\n"
-        "mov.d $f12, $f8                                \r\n"
-        "punpcklhw $f8, $f8, $f10                       \r\n"
-        "punpckhhw $f12, $f12, $f10                     \r\n"
-        "punpckhwd $f2, $f0, $f8                        \r\n"
-        "punpckhwd $f6, $f4, $f12                       \r\n"
-        "punpcklwd $f0, $f0, $f8                        \r\n"
-        "punpcklwd $f4, $f4, $f12                       \r\n"
-        : [pix]"+r"(pix),[stride]"+r"(stride),[alpha]"+r"(alpha),
-          [beta]"+r"(beta)
-        ::"$12","$13","$16","$17","$18","$19","$f0","$f2","$f4","$f6","$f8",
-          "$f10","$f12","$f14","$f20","$f22"
-    );
-
-    chroma_intra_body_mmi(pix, stride, alpha, beta);
+    double ftmp[11];
+    mips_reg addr[6];
+    uint64_t low32;
 
     __asm__ volatile (
-        "punpckhwd $f8, $f0, $f0                        \r\n"
-        "punpckhwd $f10, $f2, $f2                       \r\n"
-        "punpckhwd $f12, $f4, $f4                       \r\n"
-        "punpcklbh $f0, $f0, $f2                        \r\n"
-        "punpcklbh $f4, $f4, $f6                        \r\n"
-        "punpcklhw $f2, $f0, $f4                        \r\n"
-        "punpckhhw $f0, $f0, $f4                        \r\n"
-        "gsswlc1 $f2, 0x3($18)                          \r\n"
-        "gsswrc1 $f2, 0x0($18)                          \r\n"
-        "daddu $12, $18, %[stride]                      \r\n"
-        "punpckhwd $f2, $f2, $f2                        \r\n"
-        "gsswlc1 $f2, 0x3($12)                          \r\n"
-        "daddu $13, $18, $16                            \r\n"
-        "gsswrc1 $f2, 0x0($12)                          \r\n"
-        "gsswlc1 $f0, 0x3($13)                          \r\n"
-        "gsswrc1 $f0, 0x0($13)                          \r\n"
-        "punpckhwd $f0, $f0, $f0                        \r\n"
-        "punpckhwd $f6, $f6, $f6                        \r\n"
-        "gsswlc1 $f0, 0x3(%[pix])                       \r\n"
-        "gsswrc1 $f0, 0x0(%[pix])                       \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "punpcklbh $f12, $f12, $f6                      \r\n"
-        "daddu $12, %[pix], %[stride]                   \r\n"
-        "punpcklhw $f10, $f8, $f12                      \r\n"
-        "punpckhhw $f8, $f8, $f12                       \r\n"
-        "gsswlc1 $f10, 0x3($12)                         \r\n"
-        "gsswrc1 $f10, 0x0($12)                         \r\n"
-        "punpckhwd $f10, $f10, $f10                     \r\n"
-        "daddu $12, %[pix], $16                         \r\n"
-        "daddu $13, %[pix], $17                         \r\n"
-        "gsswlc1 $f10, 0x3($12)                         \r\n"
-        "gsswrc1 $f10, 0x0($12)                         \r\n"
-        "gsswlc1 $f8, 0x3($13)                          \r\n"
-        "daddu $12, %[pix], $19                         \r\n"
-        "punpckhwd $f20, $f8, $f8                       \r\n"
-        "gsswrc1 $f8, 0x0($13)                          \r\n"
-        "gsswlc1 $f20, 0x3($12)                         \r\n"
-        "gsswrc1 $f20, 0x0($12)                         \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride)
-        : "$12","$13","$16","$17","$18","$19","$f0","$f2","$f4","$f6","$f8",
-          "$f10","$f12","$f20"
+        "addi       %[alpha],   %[alpha],       -0x01                   \n\t"
+        "addi       %[beta],    %[beta],        -0x01                   \n\t"
+        PTR_ADDU   "%[addr0],   %[stride],      %[stride]               \n\t"
+        PTR_ADDI   "%[pix],     %[pix],         -0x02                   \n\t"
+        PTR_ADDU   "%[addr1],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr2],   %[addr0],       %[addr0]                \n\t"
+        "or         %[addr5],   $0,             %[pix]                  \n\t"
+        PTR_ADDU   "%[pix],     %[pix],         %[addr1]                \n\t"
+        "uld        %[low32],   0x00(%[addr5])                          \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        PTR_ADDU   "%[addr3],   %[addr5],       %[stride]               \n\t"
+        "uld        %[low32],   0x00(%[addr3])                          \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        PTR_ADDU   "%[addr4],   %[addr5],       %[addr0]                \n\t"
+        "uld        %[low32],   0x00(%[addr4])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   0x00(%[pix])                            \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[stride]               \n\t"
+        "punpckhhw  %[ftmp2],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "uld        %[low32],   0x00(%[addr3])                          \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        PTR_ADDU   "%[addr4],   %[pix],         %[addr0]                \n\t"
+        "uld        %[low32],   0x00(%[addr4])                          \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[addr1]                \n\t"
+        "uld        %[low32],   0x00(%[addr3])                          \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        PTR_ADDU   "%[addr4],   %[pix],         %[addr2]                \n\t"
+        "uld        %[low32],   0x00(%[addr4])                          \n\t"
+        "mtc1       %[low32],   %[ftmp7]                                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "mov.d      %[ftmp6],   %[ftmp4]                                \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpckhhw  %[ftmp6],   %[ftmp6],       %[ftmp5]                \n\t"
+        "punpckhwd  %[ftmp1],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpckhwd  %[ftmp3],   %[ftmp2],       %[ftmp6]                \n\t"
+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpcklwd  %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+
+        "xor        %[ftmp8],   %[ftmp8],       %[ftmp8]                \n\t"
+        "mtc1       %[alpha],   %[ftmp4]                                \n\t"
+        "mtc1       %[beta],    %[ftmp5]                                \n\t"
+        "pshufh     %[ftmp4],   %[ftmp4],       %[ftmp8]                \n\t"
+        "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp8]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        "packushb   %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        "psubusb    %[ftmp6],   %[ftmp2],       %[ftmp1]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp1],       %[ftmp2]                \n\t"
+        "or         %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp6],   %[ftmp1],       %[ftmp0]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp0],       %[ftmp1]                \n\t"
+        "or         %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "or         %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+        "psubusb    %[ftmp6],   %[ftmp2],       %[ftmp3]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp3],       %[ftmp2]                \n\t"
+        "or         %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "psubusb    %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "or         %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+        "xor        %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "pcmpeqb    %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+        "mov.d      %[ftmp5],   %[ftmp1]                                \n\t"
+        "mov.d      %[ftmp6],   %[ftmp2]                                \n\t"
+        "xor        %[ftmp4],   %[ftmp1],       %[ftmp3]                \n\t"
+        "and        %[ftmp4],   %[ftmp4],       %[ff_pb_1]              \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "psubusb    %[ftmp1],   %[ftmp1],       %[ftmp4]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "xor        %[ftmp4],   %[ftmp2],       %[ftmp0]                \n\t"
+        "and        %[ftmp4],   %[ftmp4],       %[ff_pb_1]              \n\t"
+        "pavgb      %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "psubusb    %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "pavgb      %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "psubb      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "psubb      %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "and        %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "and        %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "paddb      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "paddb      %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+
+        "punpckhwd  %[ftmp4],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp1],       %[ftmp1]                \n\t"
+        "punpckhwd  %[ftmp6],   %[ftmp2],       %[ftmp2]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpcklhw  %[ftmp1],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[addr5])                          \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr5],       %[stride]               \n\t"
+        "punpckhwd  %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr4],   %[addr5],       %[addr0]                \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[addr3])                          \n\t"
+        "gsswlc1    %[ftmp0],   0x03(%[addr4])                          \n\t"
+        "gsswrc1    %[ftmp0],   0x00(%[addr4])                          \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpckhwd  %[ftmp3],   %[ftmp3],       %[ftmp3]                \n\t"
+        "gsswlc1    %[ftmp0],   0x03(%[pix])                            \n\t"
+        "gsswrc1    %[ftmp0],   0x00(%[pix])                            \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[stride]               \n\t"
+        "punpcklhw  %[ftmp5],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpckhhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "gsswlc1    %[ftmp5],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp5],   0x00(%[addr3])                          \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[addr0]                \n\t"
+        PTR_ADDU   "%[addr4],   %[pix],         %[addr1]                \n\t"
+        "gsswlc1    %[ftmp5],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp5],   0x00(%[addr3])                          \n\t"
+        "gsswlc1    %[ftmp4],   0x03(%[addr4])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[pix],         %[addr2]                \n\t"
+        "punpckhwd  %[ftmp9],   %[ftmp4],       %[ftmp4]                \n\t"
+        "gsswrc1    %[ftmp4],   0x00(%[addr4])                          \n\t"
+        "gsswlc1    %[ftmp9],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp9],   0x00(%[addr3])                          \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),            [addr5]"=&r"(addr[5]),
+          [pix]"+&r"(pix),
+          [low32]"=&r"(low32)
+        : [alpha]"r"(alpha),                [beta]"r"(beta),
+          [stride]"r"((mips_reg)stride),    [ff_pb_1]"f"(ff_pb_1)
+        : "memory"
     );
 }
 
@@ -1982,233 +2268,253 @@ void ff_deblock_v_luma_8_mmi(uint8_t *pix, int stride, int alpha, int beta,
 void ff_deblock_v_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha,
         int beta)
 {
-    ff_deblock_v8_luma_intra_8_mmi(pix + 0, stride, alpha, beta);
-    ff_deblock_v8_luma_intra_8_mmi(pix + 8, stride, alpha, beta);
+    deblock_v8_luma_intra_8_mmi(pix + 0, stride, alpha, beta);
+    deblock_v8_luma_intra_8_mmi(pix + 8, stride, alpha, beta);
 }
 
 void ff_deblock_h_luma_8_mmi(uint8_t *pix, int stride, int alpha, int beta,
         int8_t *tc0)
 {
     uint64_t stack[0xd];
+    double ftmp[9];
+    mips_reg addr[8];
 
     __asm__ volatile (
-        "daddu $15, %[stride], %[stride]                \r\n"
-        "daddiu $8, %[pix], -0x4                        \r\n"
-        "daddu $9, %[stride], $15                       \r\n"
-        "gsldlc1 $f0, 0x7($8)                           \r\n"
-        "gsldrc1 $f0, 0x0($8)                           \r\n"
-        "daddu $12, $8, %[stride]                       \r\n"
-        "daddu $10, $8, $9                              \r\n"
-        "gsldlc1 $f2, 0x7($12)                          \r\n"
-        "daddu $11, $8, $15                             \r\n"
-        "gsldrc1 $f2, 0x0($12)                          \r\n"
-        "gsldlc1 $f4, 0x7($11)                          \r\n"
-        "gsldrc1 $f4, 0x0($11)                          \r\n"
-        "gsldlc1 $f6, 0x7($10)                          \r\n"
-        "daddu $12, $10, %[stride]                      \r\n"
-        "gsldrc1 $f6, 0x0($10)                          \r\n"
-        "gsldlc1 $f8, 0x7($12)                          \r\n"
-        "daddu $11, $10, $15                            \r\n"
-        "gsldrc1 $f8, 0x0($12)                          \r\n"
-        "gsldlc1 $f10, 0x7($11)                         \r\n"
-        "daddu $12, $10, $9                             \r\n"
-        "gsldrc1 $f10, 0x0($11)                         \r\n"
-        "gsldlc1 $f12, 0x7($12)                         \r\n"
-        "gsldrc1 $f12, 0x0($12)                         \r\n"
-        "daddu $14, $15, $15                            \r\n"
-        "punpckhbh $f14, $f0, $f2                       \r\n"
-        "punpcklbh $f0, $f0, $f2                        \r\n"
-        "punpckhbh $f2, $f4, $f6                        \r\n"
-        "punpcklbh $f4, $f4, $f6                        \r\n"
-        "punpckhbh $f6, $f8, $f10                       \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "daddu $12, $10, $14                            \r\n"
-        "sdc1 $f2, 0x10+%[stack]                        \r\n"
-        "gsldlc1 $f16, 0x7($12)                         \r\n"
-        "gsldrc1 $f16, 0x0($12)                         \r\n"
-        "daddu $13, $14, $14                            \r\n"
-        "punpckhbh $f10, $f12, $f16                     \r\n"
-        "punpcklbh $f12, $f12, $f16                     \r\n"
-        "punpckhhw $f2, $f0, $f4                        \r\n"
-        "punpcklhw $f0, $f0, $f4                        \r\n"
-        "punpckhhw $f4, $f8, $f12                       \r\n"
-        "punpcklhw $f8, $f8, $f12                       \r\n"
-        "ldc1 $f16, 0x10+%[stack]                       \r\n"
-        "punpckhwd $f0, $f0, $f8                        \r\n"
-        "sdc1 $f0, 0x0+%[stack]                         \r\n"
-        "punpckhhw $f12, $f14, $f16                     \r\n"
-        "punpcklhw $f14, $f14, $f16                     \r\n"
-        "punpckhhw $f0, $f6, $f10                       \r\n"
-        "punpcklhw $f6, $f6, $f10                       \r\n"
-        "punpcklwd $f12, $f12, $f0                      \r\n"
-        "punpckhwd $f10, $f14, $f6                      \r\n"
-        "punpcklwd $f14, $f14, $f6                      \r\n"
-        "punpckhwd $f6, $f2, $f4                        \r\n"
-        "punpcklwd $f2, $f2, $f4                        \r\n"
-        "sdc1 $f2, 0x10+%[stack]                        \r\n"
-        "sdc1 $f6, 0x20+%[stack]                        \r\n"
-        "sdc1 $f14, 0x30+%[stack]                       \r\n"
-        "sdc1 $f10, 0x40+%[stack]                       \r\n"
-        "sdc1 $f12, 0x50+%[stack]                       \r\n"
-        "daddu $8, $8, $13                              \r\n"
-        "daddu $10, $10, $13                            \r\n"
-        "gsldlc1 $f0, 0x7($8)                           \r\n"
-        "daddu $12, $8, %[stride]                       \r\n"
-        "gsldrc1 $f0, 0x0($8)                           \r\n"
-        "gsldlc1 $f2, 0x7($12)                          \r\n"
-        "daddu $11, $8, $15                             \r\n"
-        "gsldrc1 $f2, 0x0($12)                          \r\n"
-        "gsldlc1 $f4, 0x7($11)                          \r\n"
-        "gsldrc1 $f4, 0x0($11)                          \r\n"
-        "gsldlc1 $f6, 0x7($10)                          \r\n"
-        "daddu $12, $10, %[stride]                      \r\n"
-        "gsldrc1 $f6, 0x0($10)                          \r\n"
-        "gsldlc1 $f8, 0x7($12)                          \r\n"
-        "daddu $11, $10, $15                            \r\n"
-        "gsldrc1 $f8, 0x0($12)                          \r\n"
-        "gsldlc1 $f10, 0x7($11)                         \r\n"
-        "daddu $12, $10, $9                             \r\n"
-        "gsldrc1 $f10, 0x0($11)                         \r\n"
-        "gsldlc1 $f12, 0x7($12)                         \r\n"
-        "gsldrc1 $f12, 0x0($12)                         \r\n"
-        "punpckhbh $f14, $f0, $f2                       \r\n"
-        "punpcklbh $f0, $f0, $f2                        \r\n"
-        "punpckhbh $f2, $f4, $f6                        \r\n"
-        "punpcklbh $f4, $f4, $f6                        \r\n"
-        "punpckhbh $f6, $f8, $f10                       \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "daddu $12, $10, $14                            \r\n"
-        "sdc1 $f2, 0x18+%[stack]                        \r\n"
-        "gsldlc1 $f16, 0x7($12)                         \r\n"
-        "gsldrc1 $f16, 0x0($12)                         \r\n"
-        "punpckhhw $f2, $f0, $f4                        \r\n"
-        "punpckhbh $f10, $f12, $f16                     \r\n"
-        "punpcklbh $f12, $f12, $f16                     \r\n"
-        "punpcklhw $f0, $f0, $f4                        \r\n"
-        "punpckhhw $f4, $f8, $f12                       \r\n"
-        "punpcklhw $f8, $f8, $f12                       \r\n"
-        "punpckhwd $f0, $f0, $f8                        \r\n"
-        "ldc1 $f16, 0x18+%[stack]                       \r\n"
-        "sdc1 $f0, 0x8+%[stack]                         \r\n"
-        "punpckhhw $f12, $f14, $f16                     \r\n"
-        "punpcklhw $f14, $f14, $f16                     \r\n"
-        "punpckhhw $f0, $f6, $f10                       \r\n"
-        "punpcklhw $f6, $f6, $f10                       \r\n"
-        "punpckhwd $f10, $f14, $f6                      \r\n"
-        "punpcklwd $f14, $f14, $f6                      \r\n"
-        "punpckhwd $f6, $f2, $f4                        \r\n"
-        "punpcklwd $f2, $f2, $f4                        \r\n"
-        "punpcklwd $f12, $f12, $f0                      \r\n"
-        "sdc1 $f2, 0x18+%[stack]                        \r\n"
-        "sdc1 $f6, 0x28+%[stack]                        \r\n"
-        "sdc1 $f14, 0x38+%[stack]                       \r\n"
-        "sdc1 $f10, 0x48+%[stack]                       \r\n"
-        "sdc1 $f12, 0x58+%[stack]                       \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride),[stack]"m"(stack[0])
-        : "$8","$9","$10","$11","$12","$13","$14","$15","$f0","$f2","$f4",
-          "$f6","$f8","$f10","$f12","$f14","$f16"
+        PTR_ADDU   "%[addr0],   %[stride],      %[stride]               \n\t"
+        PTR_ADDI   "%[addr1],   %[pix],         -0x4                    \n\t"
+        PTR_ADDU   "%[addr2],   %[stride],      %[addr0]                \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr1],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr4],   %[addr1],       %[addr2]                \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[addr0]                \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr3])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr4])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[stride]               \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr4])                          \n\t"
+        "gsldlc1    %[ftmp4],   0x07(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr0]                \n\t"
+        "gsldrc1    %[ftmp4],   0x00(%[addr3])                          \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[addr2]                \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp6],   0x07(%[addr3])                          \n\t"
+        "gsldrc1    %[ftmp6],   0x00(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr0],       %[addr0]                \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpckhbh  %[ftmp1],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[addr6]                \n\t"
+        "sdc1       %[ftmp1],   0x10(%[stack])                          \n\t"
+        "gsldlc1    %[ftmp8],   0x07(%[addr3])                          \n\t"
+        "gsldrc1    %[ftmp8],   0x00(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr7],   %[addr6],       %[addr6]                \n\t"
+        "punpckhbh  %[ftmp5],   %[ftmp6],       %[ftmp8]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp2],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "ldc1       %[ftmp8],   0x10(%[stack])                          \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[stack])                          \n\t"
+        "punpckhhw  %[ftmp6],   %[ftmp7],       %[ftmp8]                \n\t"
+        "punpcklhw  %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+        "punpckhhw  %[ftmp0],   %[ftmp3],       %[ftmp5]                \n\t"
+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "punpcklwd  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp7],       %[ftmp3]                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp3]                \n\t"
+        "punpckhwd  %[ftmp3],   %[ftmp1],       %[ftmp2]                \n\t"
+        "punpcklwd  %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "sdc1       %[ftmp1],   0x10(%[stack])                          \n\t"
+        "sdc1       %[ftmp3],   0x20(%[stack])                          \n\t"
+        "sdc1       %[ftmp7],   0x30(%[stack])                          \n\t"
+        "sdc1       %[ftmp5],   0x40(%[stack])                          \n\t"
+        "sdc1       %[ftmp6],   0x50(%[stack])                          \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[addr7]                \n\t"
+        PTR_ADDU   "%[addr4],   %[addr4],       %[addr7]                \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr1],       %[stride]               \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[addr1])                          \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[addr0]                \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr3])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr4])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[stride]               \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr4])                          \n\t"
+        "gsldlc1    %[ftmp4],   0x07(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr0]                \n\t"
+        "gsldrc1    %[ftmp4],   0x00(%[addr3])                          \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[addr2]                \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp6],   0x07(%[addr3])                          \n\t"
+        "gsldrc1    %[ftmp6],   0x00(%[addr3])                          \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpckhbh  %[ftmp1],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[addr6]                \n\t"
+        "sdc1       %[ftmp1],   0x18(%[stack])                          \n\t"
+        "gsldlc1    %[ftmp8],   0x07(%[addr3])                          \n\t"
+        "gsldrc1    %[ftmp8],   0x00(%[addr3])                          \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhbh  %[ftmp5],   %[ftmp6],       %[ftmp8]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp2],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "ldc1       %[ftmp8],   0x18(%[stack])                          \n\t"
+        "sdc1       %[ftmp0],   0x08(%[stack])                          \n\t"
+        "punpckhhw  %[ftmp6],   %[ftmp7],       %[ftmp8]                \n\t"
+        "punpcklhw  %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+        "punpckhhw  %[ftmp0],   %[ftmp3],       %[ftmp5]                \n\t"
+        "punpcklhw  %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp7],       %[ftmp3]                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp3]                \n\t"
+        "punpckhwd  %[ftmp3],   %[ftmp1],       %[ftmp2]                \n\t"
+        "punpcklwd  %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "punpcklwd  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "sdc1       %[ftmp1],   0x18(%[stack])                          \n\t"
+        "sdc1       %[ftmp3],   0x28(%[stack])                          \n\t"
+        "sdc1       %[ftmp7],   0x38(%[stack])                          \n\t"
+        "sdc1       %[ftmp5],   0x48(%[stack])                          \n\t"
+        "sdc1       %[ftmp6],   0x58(%[stack])                          \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),            [addr5]"=&r"(addr[5]),
+          [addr6]"=&r"(addr[6]),            [addr7]"=&r"(addr[7])
+        : [pix]"r"(pix),                    [stride]"r"((mips_reg)stride),
+          [stack]"r"(stack)
+        : "memory"
     );
 
     ff_deblock_v_luma_8_mmi((uint8_t *) &stack[6], 0x10, alpha, beta, tc0);
 
     __asm__ volatile (
-        "daddu $15, %[stride], %[stride]                \r\n"
-        "daddiu $8, %[pix], -0x2                        \r\n"
-        "daddu $14, $15, $15                            \r\n"
-        "daddu $9, $15, %[stride]                       \r\n"
-        "daddu $13, $14, $14                            \r\n"
-        "daddu $10, $8, $9                              \r\n"
-        "ldc1 $f0, 0x10+%[stack]                        \r\n"
-        "ldc1 $f2, 0x20+%[stack]                        \r\n"
-        "ldc1 $f4, 0x30+%[stack]                        \r\n"
-        "ldc1 $f6, 0x40+%[stack]                        \r\n"
-        "punpckhwd $f8, $f0, $f0                        \r\n"
-        "punpckhwd $f10, $f2, $f2                       \r\n"
-        "punpckhwd $f12, $f4, $f4                       \r\n"
-        "punpcklbh $f0, $f0, $f2                        \r\n"
-        "punpcklbh $f4, $f4, $f6                        \r\n"
-        "punpcklhw $f2, $f0, $f4                        \r\n"
-        "punpckhhw $f0, $f0, $f4                        \r\n"
-        "gsswlc1 $f2, 0x3($8)                           \r\n"
-        "gsswrc1 $f2, 0x0($8)                           \r\n"
-        "daddu $12, $8, %[stride]                       \r\n"
-        "punpckhwd $f2, $f2, $f2                        \r\n"
-        "daddu $11, $8, $15                             \r\n"
-        "gsswlc1 $f2, 0x3($12)                          \r\n"
-        "gsswrc1 $f2, 0x0($12)                          \r\n"
-        "gsswlc1 $f0, 0x3($11)                          \r\n"
-        "gsswrc1 $f0, 0x0($11)                          \r\n"
-        "punpckhwd $f0, $f0, $f0                        \r\n"
-        "punpckhwd $f6, $f6, $f6                        \r\n"
-        "gsswlc1 $f0, 0x3($10)                          \r\n"
-        "gsswrc1 $f0, 0x0($10)                          \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "punpcklbh $f12, $f12, $f6                      \r\n"
-        "punpcklhw $f10, $f8, $f12                      \r\n"
-        "daddu $12, $10, %[stride]                      \r\n"
-        "punpckhhw $f8, $f8, $f12                       \r\n"
-        "gsswlc1 $f10, 0x3($12)                         \r\n"
-        "gsswrc1 $f10, 0x0($12)                         \r\n"
-        "daddu $12, $10, $15                            \r\n"
-        "punpckhwd $f10, $f10, $f10                     \r\n"
-        "daddu $11, $10, $9                             \r\n"
-        "gsswlc1 $f10, 0x3($12)                         \r\n"
-        "gsswrc1 $f10, 0x0($12)                         \r\n"
-        "gsswlc1 $f8, 0x3($11)                          \r\n"
-        "gsswrc1 $f8, 0x0($11)                          \r\n"
-        "daddu $12, $10, $14                            \r\n"
-        "punpckhwd $f8, $f8, $f8                        \r\n"
-        "daddu $8, $8, $13                              \r\n"
-        "gsswlc1 $f8, 0x3($12)                          \r\n"
-        "gsswrc1 $f8, 0x0($12)                          \r\n"
-        "daddu $10, $10, $13                            \r\n"
-        "ldc1 $f0, 0x18+%[stack]                        \r\n"
-        "ldc1 $f2, 0x28+%[stack]                        \r\n"
-        "ldc1 $f4, 0x38+%[stack]                        \r\n"
-        "ldc1 $f6, 0x48+%[stack]                        \r\n"
-        "daddu $15, %[stride], %[stride]                \r\n"
-        "punpckhwd $f8, $f0, $f0                        \r\n"
-        "daddu $14, $15, $15                            \r\n"
-        "punpckhwd $f10, $f2, $f2                       \r\n"
-        "punpckhwd $f12, $f4, $f4                       \r\n"
-        "punpcklbh $f0, $f0, $f2                        \r\n"
-        "punpcklbh $f4, $f4, $f6                        \r\n"
-        "daddu $12, $8, %[stride]                       \r\n"
-        "punpcklhw $f2, $f0, $f4                        \r\n"
-        "punpckhhw $f0, $f0, $f4                        \r\n"
-        "gsswlc1 $f2, 0x3($8)                           \r\n"
-        "gsswrc1 $f2, 0x0($8)                           \r\n"
-        "punpckhwd $f2, $f2, $f2                        \r\n"
-        "daddu $11, $8, $15                             \r\n"
-        "gsswlc1 $f2, 0x3($12)                          \r\n"
-        "gsswrc1 $f2, 0x0($12)                          \r\n"
-        "gsswlc1 $f0, 0x3($11)                          \r\n"
-        "gsswrc1 $f0, 0x0($11)                          \r\n"
-        "punpckhwd $f0, $f0, $f0                        \r\n"
-        "punpckhwd $f6, $f6, $f6                        \r\n"
-        "gsswlc1 $f0, 0x3($10)                          \r\n"
-        "gsswrc1 $f0, 0x0($10)                          \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "punpcklbh $f12, $f12, $f6                      \r\n"
-        "daddu $12, $10, %[stride]                      \r\n"
-        "punpcklhw $f10, $f8, $f12                      \r\n"
-        "punpckhhw $f8, $f8, $f12                       \r\n"
-        "gsswlc1 $f10, 0x3($12)                         \r\n"
-        "gsswrc1 $f10, 0x0($12)                         \r\n"
-        "daddu $12, $10, $15                            \r\n"
-        "punpckhwd $f10, $f10, $f10                     \r\n"
-        "daddu $11, $10, $9                             \r\n"
-        "gsswlc1 $f10, 0x3($12)                         \r\n"
-        "gsswrc1 $f10, 0x0($12)                         \r\n"
-        "gsswlc1 $f8, 0x3($11)                          \r\n"
-        "gsswrc1 $f8, 0x0($11)                          \r\n"
-        "daddu $12, $10, $14                            \r\n"
-        "punpckhwd $f8, $f8, $f8                        \r\n"
-        "gsswlc1 $f8, 0x3($12)                          \r\n"
-        "gsswrc1 $f8, 0x0($12)                          \r\n"
-        ::[pix]"r"(pix),[stride]"r"((int64_t)stride),[stack]"m"(stack[0])
-        : "$8","$9","$10","$11","$12","$13","$14","$15","$f0","$f2","$f4",
-          "$f6","$f8","$f10","$f12","$f14","$f16"
+        PTR_ADDU   "%[addr0],   %[stride],      %[stride]               \n\t"
+        PTR_ADDI   "%[addr1],   %[pix],          -0x02                  \n\t"
+        PTR_ADDU   "%[addr6],   %[addr0],       %[addr0]                \n\t"
+        PTR_ADDU   "%[addr2],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr7],   %[addr6],       %[addr6]                \n\t"
+        PTR_ADDU   "%[addr4],   %[addr1],       %[addr2]                \n\t"
+        "ldc1       %[ftmp0],   0x10(%[stack])                          \n\t"
+        "ldc1       %[ftmp1],   0x20(%[stack])                          \n\t"
+        "ldc1       %[ftmp2],   0x30(%[stack])                          \n\t"
+        "ldc1       %[ftmp3],   0x40(%[stack])                          \n\t"
+        "punpckhwd  %[ftmp4],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp1],       %[ftmp1]                \n\t"
+        "punpckhwd  %[ftmp6],   %[ftmp2],       %[ftmp2]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpcklhw  %[ftmp1],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[addr1])                          \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr1],       %[stride]               \n\t"
+        "punpckhwd  %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[addr0]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[addr3])                          \n\t"
+        "gsswlc1    %[ftmp0],   0x03(%[addr5])                          \n\t"
+        "gsswrc1    %[ftmp0],   0x00(%[addr5])                          \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpckhwd  %[ftmp3],   %[ftmp3],       %[ftmp3]                \n\t"
+        "gsswlc1    %[ftmp0],   0x03(%[addr4])                          \n\t"
+        "gsswrc1    %[ftmp0],   0x00(%[addr4])                          \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp3]                \n\t"
+        "punpcklhw  %[ftmp5],   %[ftmp4],       %[ftmp6]                \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[stride]               \n\t"
+        "punpckhhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "gsswlc1    %[ftmp5],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp5],   0x00(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[addr0]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr2]                \n\t"
+        "gsswlc1    %[ftmp5],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp5],   0x00(%[addr3])                          \n\t"
+        "gsswlc1    %[ftmp4],   0x03(%[addr5])                          \n\t"
+        "gsswrc1    %[ftmp4],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[addr6]                \n\t"
+        "punpckhwd  %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[addr7]                \n\t"
+        "gsswlc1    %[ftmp4],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp4],   0x00(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr4],   %[addr4],       %[addr7]                \n\t"
+        "ldc1       %[ftmp0],   0x18(%[stack])                          \n\t"
+        "ldc1       %[ftmp1],   0x28(%[stack])                          \n\t"
+        "ldc1       %[ftmp2],   0x38(%[stack])                          \n\t"
+        "ldc1       %[ftmp3],   0x48(%[stack])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[stride],      %[stride]               \n\t"
+        "punpckhwd  %[ftmp4],   %[ftmp0],       %[ftmp0]                \n\t"
+        PTR_ADDU   "%[addr6],   %[addr0],       %[addr0]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp1],       %[ftmp1]                \n\t"
+        "punpckhwd  %[ftmp6],   %[ftmp2],       %[ftmp2]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr3],   %[addr1],       %[stride]               \n\t"
+        "punpcklhw  %[ftmp1],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[addr1])                          \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[addr1])                          \n\t"
+        "punpckhwd  %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[addr0]                \n\t"
+        "gsswlc1    %[ftmp1],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp1],   0x00(%[addr3])                          \n\t"
+        "gsswlc1    %[ftmp0],   0x03(%[addr5])                          \n\t"
+        "gsswrc1    %[ftmp0],   0x00(%[addr5])                          \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "punpckhwd  %[ftmp3],   %[ftmp3],       %[ftmp3]                \n\t"
+        "gsswlc1    %[ftmp0],   0x03(%[addr4])                          \n\t"
+        "gsswrc1    %[ftmp0],   0x00(%[addr4])                          \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[stride]               \n\t"
+        "punpcklhw  %[ftmp5],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpckhhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "gsswlc1    %[ftmp5],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp5],   0x00(%[addr3])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[addr0]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr2]                \n\t"
+        "gsswlc1    %[ftmp5],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp5],   0x00(%[addr3])                          \n\t"
+        "gsswlc1    %[ftmp4],   0x03(%[addr5])                          \n\t"
+        "gsswrc1    %[ftmp4],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr4],       %[addr6]                \n\t"
+        "punpckhwd  %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        "gsswlc1    %[ftmp4],   0x03(%[addr3])                          \n\t"
+        "gsswrc1    %[ftmp4],   0x00(%[addr3])                          \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),            [addr5]"=&r"(addr[5]),
+          [addr6]"=&r"(addr[6]),            [addr7]"=&r"(addr[7])
+        : [pix]"r"(pix),                    [stride]"r"((mips_reg)stride),
+          [stack]"r"(stack)
+        : "memory"
     );
 }
 
@@ -2217,284 +2523,302 @@ void ff_deblock_h_luma_intra_8_mmi(uint8_t *pix, int stride, int alpha,
 {
     uint64_t ptmp[0x11];
     uint64_t pdat[4];
+    double ftmp[9];
+    mips_reg addr[7];
 
     __asm__ volatile (
-        "daddu $12, %[stride], %[stride]                \r\n"
-        "daddiu $10, %[pix], -0x4                       \r\n"
-        "daddu $11, $12, %[stride]                      \r\n"
-        "daddu $13, $12, $12                            \r\n"
-        "daddu $9, $10, $11                             \r\n"
-        "daddu $8, $10, %[stride]                       \r\n"
-        "gsldlc1 $f0, 0x7($10)                          \r\n"
-        "gsldrc1 $f0, 0x0($10)                          \r\n"
-        "daddu $14, $10, $12                            \r\n"
-        "gsldlc1 $f2, 0x7($8)                           \r\n"
-        "gsldrc1 $f2, 0x0($8)                           \r\n"
-        "gsldlc1 $f4, 0x7($14)                          \r\n"
-        "gsldrc1 $f4, 0x0($14)                          \r\n"
-        "daddu $8, $9, %[stride]                        \r\n"
-        "gsldlc1 $f6, 0x7($9)                           \r\n"
-        "gsldrc1 $f6, 0x0($9)                           \r\n"
-        "daddu $14, $9, $12                             \r\n"
-        "gsldlc1 $f8, 0x7($8)                           \r\n"
-        "gsldrc1 $f8, 0x0($8)                           \r\n"
-        "daddu $8, $9, $11                              \r\n"
-        "gsldlc1 $f10, 0x7($14)                         \r\n"
-        "gsldrc1 $f10, 0x0($14)                         \r\n"
-        "gsldlc1 $f12, 0x7($8)                          \r\n"
-        "gsldrc1 $f12, 0x0($8)                          \r\n"
-        "daddu $8, $9, $13                              \r\n"
-        "punpckhbh $f14, $f0, $f2                       \r\n"
-        "punpcklbh $f0, $f0, $f2                        \r\n"
-        "punpckhbh $f2, $f4, $f6                        \r\n"
-        "punpcklbh $f4, $f4, $f6                        \r\n"
-        "punpckhbh $f6, $f8, $f10                       \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "gsldlc1 $f16, 0x7($8)                          \r\n"
-        "gsldrc1 $f16, 0x0($8)                          \r\n"
-        "punpckhbh $f10, $f12, $f16                     \r\n"
-        "punpcklbh $f12, $f12, $f16                     \r\n"
-        "sdc1 $f6, 0x0+%[ptmp]                          \r\n"
-        "punpckhhw $f6, $f0, $f4                        \r\n"
-        "punpcklhw $f0, $f0, $f4                        \r\n"
-        "punpckhhw $f4, $f8, $f12                       \r\n"
-        "punpcklhw $f8, $f8, $f12                       \r\n"
-        "punpckhhw $f12, $f14, $f2                      \r\n"
-        "punpcklhw $f14, $f14, $f2                      \r\n"
-        "sdc1 $f4, 0x20+%[ptmp]                         \r\n"
-        "ldc1 $f4, 0x0+%[ptmp]                          \r\n"
-        "punpckhhw $f2, $f4, $f10                       \r\n"
-        "punpcklhw $f4, $f4, $f10                       \r\n"
-        "punpckhwd $f10, $f0, $f8                       \r\n"
-        "punpcklwd $f0, $f0, $f8                        \r\n"
-        "punpckhwd $f8, $f14, $f4                       \r\n"
-        "punpcklwd $f14, $f14, $f4                      \r\n"
-        "sdc1 $f0, 0x0+%[ptmp]                          \r\n"
-        "sdc1 $f10, 0x10+%[ptmp]                        \r\n"
-        "sdc1 $f14, 0x40+%[ptmp]                        \r\n"
-        "sdc1 $f8, 0x50+%[ptmp]                         \r\n"
-        "ldc1 $f16, 0x20+%[ptmp]                        \r\n"
-        "punpckhwd $f0, $f6, $f16                       \r\n"
-        "punpcklwd $f6, $f6, $f16                       \r\n"
-        "punpckhwd $f10, $f12, $f2                      \r\n"
-        "punpcklwd $f12, $f12, $f2                      \r\n"
-        "daddu $8, $13, $13                             \r\n"
-        "sdc1 $f6, 0x20+%[ptmp]                         \r\n"
-        "sdc1 $f0, 0x30+%[ptmp]                         \r\n"
-        "sdc1 $f12, 0x60+%[ptmp]                        \r\n"
-        "sdc1 $f10, 0x70+%[ptmp]                        \r\n"
-        "daddu $10, $10, $8                             \r\n"
-        "daddu $9, $9, $8                               \r\n"
-        "daddu $8, $10, %[stride]                       \r\n"
-        "gsldlc1 $f0, 0x7($10)                          \r\n"
-        "gsldrc1 $f0, 0x0($10)                          \r\n"
-        "daddu $14, $10, $12                            \r\n"
-        "gsldlc1 $f2, 0x7($8)                           \r\n"
-        "gsldrc1 $f2, 0x0($8)                           \r\n"
-        "gsldlc1 $f4, 0x7($14)                          \r\n"
-        "gsldrc1 $f4, 0x0($14)                          \r\n"
-        "daddu $8, $9, %[stride]                        \r\n"
-        "gsldlc1 $f6, 0x7($9)                           \r\n"
-        "gsldrc1 $f6, 0x0($9)                           \r\n"
-        "daddu $14, $9, $12                             \r\n"
-        "gsldlc1 $f8, 0x7($8)                           \r\n"
-        "gsldrc1 $f8, 0x0($8)                           \r\n"
-        "daddu $8, $9, $11                              \r\n"
-        "gsldlc1 $f10, 0x7($14)                         \r\n"
-        "gsldrc1 $f10, 0x0($14)                         \r\n"
-        "gsldlc1 $f12, 0x7($8)                          \r\n"
-        "gsldrc1 $f12, 0x0($8)                          \r\n"
-        "daddu $8, $9, $13                              \r\n"
-        "punpckhbh $f14, $f0, $f2                       \r\n"
-        "punpcklbh $f0, $f0, $f2                        \r\n"
-        "punpckhbh $f2, $f4, $f6                        \r\n"
-        "punpcklbh $f4, $f4, $f6                        \r\n"
-        "punpckhbh $f6, $f8, $f10                       \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "gsldlc1 $f16, 0x7($8)                          \r\n"
-        "gsldrc1 $f16, 0x0($8)                          \r\n"
-        "punpckhbh $f10, $f12, $f16                     \r\n"
-        "punpcklbh $f12, $f12, $f16                     \r\n"
-        "sdc1 $f6, 0x8+%[ptmp]                          \r\n"
-        "punpckhhw $f6, $f0, $f4                        \r\n"
-        "punpcklhw $f0, $f0, $f4                        \r\n"
-        "punpckhhw $f4, $f8, $f12                       \r\n"
-        "punpcklhw $f8, $f8, $f12                       \r\n"
-        "punpckhhw $f12, $f14, $f2                      \r\n"
-        "punpcklhw $f14, $f14, $f2                      \r\n"
-        "sdc1 $f4, 0x28+%[ptmp]                         \r\n"
-        "ldc1 $f4, 0x8+%[ptmp]                          \r\n"
-        "punpckhhw $f2, $f4, $f10                       \r\n"
-        "punpcklhw $f4, $f4, $f10                       \r\n"
-        "punpckhwd $f10, $f0, $f8                       \r\n"
-        "punpcklwd $f0, $f0, $f8                        \r\n"
-        "punpckhwd $f8, $f14, $f4                       \r\n"
-        "punpcklwd $f14, $f14, $f4                      \r\n"
-        "sdc1 $f0, 0x8+%[ptmp]                          \r\n"
-        "sdc1 $f10, 0x18+%[ptmp]                        \r\n"
-        "sdc1 $f14, 0x48+%[ptmp]                        \r\n"
-        "sdc1 $f8, 0x58+%[ptmp]                         \r\n"
-        "ldc1 $f16, 0x28+%[ptmp]                        \r\n"
-        "punpckhwd $f0, $f6, $f16                       \r\n"
-        "punpcklwd $f6, $f6, $f16                       \r\n"
-        "punpckhwd $f10, $f12, $f2                      \r\n"
-        "punpcklwd $f12, $f12, $f2                      \r\n"
-        "sdc1 $f6, 0x28+%[ptmp]                         \r\n"
-        "sdc1 $f0, 0x38+%[ptmp]                         \r\n"
-        "sdc1 $f12, 0x68+%[ptmp]                        \r\n"
-        "sdc1 $f10, 0x78+%[ptmp]                        \r\n"
-        "sd $10, 0x00+%[pdat]                           \r\n"
-        "sd $11, 0x08+%[pdat]                           \r\n"
-        "sd $12, 0x10+%[pdat]                           \r\n"
-        "sd $13, 0x18+%[pdat]                           \r\n"
-        ::[pix]"r"(pix),[stride]"r"((uint64_t)stride),[ptmp]"m"(ptmp[0]),
-          [pdat]"m"(pdat[0])
-        : "$8","$9","$10","$11","$12","$13","$14","$f0","$f2","$f4","$f6",
-          "$f8","$f10","$f12","$f14","$f16"
+        PTR_ADDU   "%[addr0],   %[stride],      %[stride]               \n\t"
+        PTR_ADDI   "%[addr1],   %[pix],         -0x04                   \n\t"
+        PTR_ADDU   "%[addr2],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr3],   %[addr0],       %[addr0]                \n\t"
+        PTR_ADDU   "%[addr4],   %[addr1],       %[addr2]                \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[stride]               \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr1],       %[addr0]                \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[addr6])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[addr6])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[stride]               \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr4])                          \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr4])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr4],       %[addr0]                \n\t"
+        "gsldlc1    %[ftmp4],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp4],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr2]                \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[addr6])                          \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[addr6])                          \n\t"
+        "gsldlc1    %[ftmp6],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp6],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr3]                \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpckhbh  %[ftmp1],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "gsldlc1    %[ftmp8],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp8],   0x00(%[addr5])                          \n\t"
+        "punpckhbh  %[ftmp5],   %[ftmp6],       %[ftmp8]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "sdc1       %[ftmp3],   0x00(%[ptmp])                           \n\t"
+        "punpckhhw  %[ftmp3],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp2],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpckhhw  %[ftmp6],   %[ftmp7],       %[ftmp1]                \n\t"
+        "punpcklhw  %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "sdc1       %[ftmp2],   0x20(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp2],   0x00(%[ptmp])                           \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp2],       %[ftmp5]                \n\t"
+        "punpcklhw  %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpckhwd  %[ftmp4],   %[ftmp7],       %[ftmp2]                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp5],   0x10(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp7],   0x40(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp4],   0x50(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp8],   0x20(%[ptmp])                           \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp3],       %[ftmp8]                \n\t"
+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp8]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp6],       %[ftmp1]                \n\t"
+        "punpcklwd  %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        PTR_ADDU   "%[addr5],   %[addr3],       %[addr3]                \n\t"
+        "sdc1       %[ftmp3],   0x20(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp0],   0x30(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp6],   0x60(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp5],   0x70(%[ptmp])                           \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[addr5]                \n\t"
+        PTR_ADDU   "%[addr4],   %[addr4],       %[addr5]                \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[stride]               \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr1],       %[addr0]                \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[addr6])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[addr6])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[stride]               \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr4])                          \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr4])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr4],       %[addr0]                \n\t"
+        "gsldlc1    %[ftmp4],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp4],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr2]                \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[addr6])                          \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[addr6])                          \n\t"
+        "gsldlc1    %[ftmp6],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp6],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr3]                \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpckhbh  %[ftmp1],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "gsldlc1    %[ftmp8],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp8],   0x00(%[addr5])                          \n\t"
+        "punpckhbh  %[ftmp5],   %[ftmp6],       %[ftmp8]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "sdc1       %[ftmp3],   0x08(%[ptmp])                           \n\t"
+        "punpckhhw  %[ftmp3],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp2],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpckhhw  %[ftmp6],   %[ftmp7],       %[ftmp1]                \n\t"
+        "punpcklhw  %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "sdc1       %[ftmp2],   0x28(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp2],   0x08(%[ptmp])                           \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp2],       %[ftmp5]                \n\t"
+        "punpcklhw  %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpckhwd  %[ftmp4],   %[ftmp7],       %[ftmp2]                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        "sdc1       %[ftmp0],   0x08(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp5],   0x18(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp7],   0x48(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp4],   0x58(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp8],   0x28(%[ptmp])                           \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp3],       %[ftmp8]                \n\t"
+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp8]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp6],       %[ftmp1]                \n\t"
+        "punpcklwd  %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "sdc1       %[ftmp3],   0x28(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp0],   0x38(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp6],   0x68(%[ptmp])                           \n\t"
+        "sdc1       %[ftmp5],   0x78(%[ptmp])                           \n\t"
+        PTR_S      "%[addr1],   0x00(%[pdat])                           \n\t"
+        PTR_S      "%[addr2],   0x08(%[pdat])                           \n\t"
+        PTR_S      "%[addr0],   0x10(%[pdat])                           \n\t"
+        PTR_S      "%[addr3],   0x18(%[pdat])                           \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),            [addr5]"=&r"(addr[5]),
+          [addr6]"=&r"(addr[6])
+        : [pix]"r"(pix),                    [stride]"r"((mips_reg)stride),
+          [ptmp]"r"(ptmp),                  [pdat]"r"(pdat)
+        : "memory"
     );
 
     ff_deblock_v_luma_intra_8_mmi((uint8_t *) &ptmp[8], 0x10, alpha, beta);
 
     __asm__ volatile (
-        "ld $10, 0x00+%[pdat]                           \r\n"
-        "ld $11, 0x08+%[pdat]                           \r\n"
-        "ld $12, 0x10+%[pdat]                           \r\n"
-        "ld $13, 0x18+%[pdat]                           \r\n"
-        "daddu $9, $10, $11                             \r\n"
-        "ldc1 $f0, 0x8+%[ptmp]                          \r\n"
-        "ldc1 $f2, 0x18+%[ptmp]                         \r\n"
-        "ldc1 $f4, 0x28+%[ptmp]                         \r\n"
-        "ldc1 $f6, 0x38+%[ptmp]                         \r\n"
-        "ldc1 $f8, 0x48+%[ptmp]                         \r\n"
-        "ldc1 $f10, 0x58+%[ptmp]                        \r\n"
-        "ldc1 $f12, 0x68+%[ptmp]                        \r\n"
-        "punpckhbh $f14, $f0, $f2                       \r\n"
-        "punpcklbh $f0, $f0, $f2                        \r\n"
-        "punpckhbh $f2, $f4, $f6                        \r\n"
-        "punpcklbh $f4, $f4, $f6                        \r\n"
-        "punpckhbh $f6, $f8, $f10                       \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "ldc1 $f16, 0x78+%[ptmp]                        \r\n"
-        "punpckhbh $f10, $f12, $f16                     \r\n"
-        "punpcklbh $f12, $f12, $f16                     \r\n"
-        "gssdlc1 $f6, 0x7($10)                          \r\n"
-        "gssdrc1 $f6, 0x0($10)                          \r\n"
-        "daddu $8, $10, $12                             \r\n"
-        "punpckhhw $f6, $f0, $f4                        \r\n"
-        "punpcklhw $f0, $f0, $f4                        \r\n"
-        "punpckhhw $f4, $f8, $f12                       \r\n"
-        "punpcklhw $f8, $f8, $f12                       \r\n"
-        "punpckhhw $f12, $f14, $f2                      \r\n"
-        "punpcklhw $f14, $f14, $f2                      \r\n"
-        "gssdlc1 $f4, 0x7($8)                           \r\n"
-        "gssdrc1 $f4, 0x0($8)                           \r\n"
-        "gsldlc1 $f4, 0x7($10)                          \r\n"
-        "gsldrc1 $f4, 0x0($10)                          \r\n"
-        "punpckhhw $f2, $f4, $f10                       \r\n"
-        "punpcklhw $f4, $f4, $f10                       \r\n"
-        "punpckhwd $f10, $f0, $f8                       \r\n"
-        "punpcklwd $f0, $f0, $f8                        \r\n"
-        "punpckhwd $f8, $f14, $f4                       \r\n"
-        "punpcklwd $f14, $f14, $f4                      \r\n"
-        "daddu $8, $10, %[stride]                       \r\n"
-        "gssdlc1 $f0, 0x7($10)                          \r\n"
-        "gssdrc1 $f0, 0x0($10)                          \r\n"
-        "daddu $14, $9, %[stride]                       \r\n"
-        "gssdlc1 $f10, 0x7($8)                          \r\n"
-        "gssdrc1 $f10, 0x0($8)                          \r\n"
-        "daddu $8, $9, $12                              \r\n"
-        "gssdlc1 $f14, 0x7($14)                         \r\n"
-        "gssdrc1 $f14, 0x0($14)                         \r\n"
-        "daddu $14, $10, $12                            \r\n"
-        "gssdlc1 $f8, 0x7($8)                           \r\n"
-        "gssdrc1 $f8, 0x0($8)                           \r\n"
-        "gsldlc1 $f16, 0x7($14)                         \r\n"
-        "gsldrc1 $f16, 0x0($14)                         \r\n"
-        "daddu $8, $10, $12                             \r\n"
-        "punpckhwd $f0, $f6, $f16                       \r\n"
-        "punpcklwd $f6, $f6, $f16                       \r\n"
-        "punpckhwd $f10, $f12, $f2                      \r\n"
-        "punpcklwd $f12, $f12, $f2                      \r\n"
-        "gssdlc1 $f6, 0x7($8)                           \r\n"
-        "gssdrc1 $f6, 0x0($8)                           \r\n"
-        "daddu $8, $9, $11                              \r\n"
-        "gssdlc1 $f0, 0x7($9)                           \r\n"
-        "gssdrc1 $f0, 0x0($9)                           \r\n"
-        "daddu $14, $9, $13                             \r\n"
-        "gssdlc1 $f12, 0x7($8)                          \r\n"
-        "gssdrc1 $f12, 0x0($8)                          \r\n"
-        "daddu $8, $13, $13                             \r\n"
-        "gssdlc1 $f10, 0x7($14)                         \r\n"
-        "gssdrc1 $f10, 0x0($14)                         \r\n"
-        "dsubu $10, $10, $8                             \r\n"
-        "dsubu $9, $9, $8                               \r\n"
-        "ldc1 $f0, 0x0+%[ptmp]                          \r\n"
-        "ldc1 $f2, 0x10+%[ptmp]                         \r\n"
-        "ldc1 $f4, 0x20+%[ptmp]                         \r\n"
-        "ldc1 $f6, 0x30+%[ptmp]                         \r\n"
-        "ldc1 $f8, 0x40+%[ptmp]                         \r\n"
-        "ldc1 $f10, 0x50+%[ptmp]                        \r\n"
-        "ldc1 $f12, 0x60+%[ptmp]                        \r\n"
-        "punpckhbh $f14, $f0, $f2                       \r\n"
-        "punpcklbh $f0, $f0, $f2                        \r\n"
-        "punpckhbh $f2, $f4, $f6                        \r\n"
-        "punpcklbh $f4, $f4, $f6                        \r\n"
-        "punpckhbh $f6, $f8, $f10                       \r\n"
-        "punpcklbh $f8, $f8, $f10                       \r\n"
-        "ldc1 $f16, 0x70+%[ptmp]                        \r\n"
-        "punpckhbh $f10, $f12, $f16                     \r\n"
-        "punpcklbh $f12, $f12, $f16                     \r\n"
-        "gssdlc1 $f6, 0x7($10)                          \r\n"
-        "gssdrc1 $f6, 0x0($10)                          \r\n"
-        "daddu $8, $10, $12                             \r\n"
-        "punpckhhw $f6, $f0, $f4                        \r\n"
-        "punpcklhw $f0, $f0, $f4                        \r\n"
-        "punpckhhw $f4, $f8, $f12                       \r\n"
-        "punpcklhw $f8, $f8, $f12                       \r\n"
-        "punpckhhw $f12, $f14, $f2                      \r\n"
-        "punpcklhw $f14, $f14, $f2                      \r\n"
-        "gssdlc1 $f4, 0x7($8)                           \r\n"
-        "gssdrc1 $f4, 0x0($8)                           \r\n"
-        "gsldlc1 $f4, 0x7($10)                          \r\n"
-        "gsldrc1 $f4, 0x0($10)                          \r\n"
-        "punpckhhw $f2, $f4, $f10                       \r\n"
-        "punpcklhw $f4, $f4, $f10                       \r\n"
-        "punpckhwd $f10, $f0, $f8                       \r\n"
-        "punpcklwd $f0, $f0, $f8                        \r\n"
-        "punpckhwd $f8, $f14, $f4                       \r\n"
-        "punpcklwd $f14, $f14, $f4                      \r\n"
-        "daddu $8, $10, %[stride]                       \r\n"
-        "gssdlc1 $f0, 0x7($10)                          \r\n"
-        "gssdrc1 $f0, 0x0($10)                          \r\n"
-        "daddu $14, $9, %[stride]                       \r\n"
-        "gssdlc1 $f10, 0x7($8)                          \r\n"
-        "gssdrc1 $f10, 0x0($8)                          \r\n"
-        "daddu $8, $9, $12                              \r\n"
-        "gssdlc1 $f14, 0x7($14)                         \r\n"
-        "gssdrc1 $f14, 0x0($14)                         \r\n"
-        "daddu $14, $10, $12                            \r\n"
-        "gssdlc1 $f8, 0x7($8)                           \r\n"
-        "gssdrc1 $f8, 0x0($8)                           \r\n"
-        "gsldlc1 $f16, 0x7($14)                         \r\n"
-        "gsldrc1 $f16, 0x0($14)                         \r\n"
-        "daddu $8, $10, $12                             \r\n"
-        "punpckhwd $f0, $f6, $f16                       \r\n"
-        "punpcklwd $f6, $f6, $f16                       \r\n"
-        "punpckhwd $f10, $f12, $f2                      \r\n"
-        "punpcklwd $f12, $f12, $f2                      \r\n"
-        "gssdlc1 $f6, 0x7($8)                           \r\n"
-        "gssdrc1 $f6, 0x0($8)                           \r\n"
-        "daddu $8, $9, $11                              \r\n"
-        "gssdlc1 $f0, 0x7($9)                           \r\n"
-        "gssdrc1 $f0, 0x0($9)                           \r\n"
-        "daddu $14, $9, $13                             \r\n"
-        "gssdlc1 $f12, 0x7($8)                          \r\n"
-        "gssdrc1 $f12, 0x0($8)                          \r\n"
-        "gssdlc1 $f10, 0x7($14)                         \r\n"
-        "gssdrc1 $f10, 0x0($14)                         \r\n"
-        ::[pix]"r"(pix),[stride]"r"((uint64_t)stride),[ptmp]"m"(ptmp[0]),
-          [pdat]"m"(pdat[0])
-        : "$8","$9","$10","$11","$12","$13","$14","$f0","$f2","$f4","$f6",
-          "$f8","$f10","$f12","$f14","$f16"
+        PTR_L      "%[addr1],   0x00(%[pdat])                           \n\t"
+        PTR_L      "%[addr2],   0x08(%[pdat])                           \n\t"
+        PTR_L      "%[addr0],   0x10(%[pdat])                           \n\t"
+        PTR_L      "%[addr3],   0x18(%[pdat])                           \n\t"
+        PTR_ADDU   "%[addr4],   %[addr1],       %[addr2]                \n\t"
+        "ldc1       %[ftmp0],   0x08(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp1],   0x18(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp2],   0x28(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp3],   0x38(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp4],   0x48(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp5],   0x58(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp6],   0x68(%[ptmp])                           \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpckhbh  %[ftmp1],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "ldc1       %[ftmp8],   0x78(%[ptmp])                           \n\t"
+        "punpckhbh  %[ftmp5],   %[ftmp6],       %[ftmp8]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "gssdlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        "gssdrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[addr0]                \n\t"
+        "punpckhhw  %[ftmp3],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp2],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpckhhw  %[ftmp6],   %[ftmp7],       %[ftmp1]                \n\t"
+        "punpcklhw  %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "gssdlc1    %[ftmp2],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp2],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[addr1])                          \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp2],       %[ftmp5]                \n\t"
+        "punpcklhw  %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpckhwd  %[ftmp4],   %[ftmp7],       %[ftmp2]                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[addr1])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr4],       %[stride]               \n\t"
+        "gssdlc1    %[ftmp5],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp5],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr0]                \n\t"
+        "gssdlc1    %[ftmp7],   0x07(%[addr6])                          \n\t"
+        "gssdrc1    %[ftmp7],   0x00(%[addr6])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr1],       %[addr0]                \n\t"
+        "gssdlc1    %[ftmp4],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp4],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp8],   0x07(%[addr6])                          \n\t"
+        "gsldrc1    %[ftmp8],   0x00(%[addr6])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[addr0]                \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp3],       %[ftmp8]                \n\t"
+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp8]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp6],       %[ftmp1]                \n\t"
+        "punpcklwd  %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "gssdlc1    %[ftmp3],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp3],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr2]                \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[addr4])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[addr4])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr4],       %[addr3]                \n\t"
+        "gssdlc1    %[ftmp6],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp6],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr3],       %[addr3]                \n\t"
+        "gssdlc1    %[ftmp5],   0x07(%[addr6])                          \n\t"
+        "gssdrc1    %[ftmp5],   0x00(%[addr6])                          \n\t"
+        PTR_SUBU   "%[addr1],   %[addr1],       %[addr5]                \n\t"
+        PTR_SUBU   "%[addr4],   %[addr4],       %[addr5]                \n\t"
+        "ldc1       %[ftmp0],   0x00(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp1],   0x10(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp2],   0x20(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp3],   0x30(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp4],   0x40(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp5],   0x50(%[ptmp])                           \n\t"
+        "ldc1       %[ftmp6],   0x60(%[ptmp])                           \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "punpckhbh  %[ftmp1],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp4],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "ldc1       %[ftmp8],   0x70(%[ptmp])                           \n\t"
+        "punpckhbh  %[ftmp5],   %[ftmp6],       %[ftmp8]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "gssdlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        "gssdrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[addr0]                \n\t"
+        "punpckhhw  %[ftmp3],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpcklhw  %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "punpckhhw  %[ftmp2],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpcklhw  %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "punpckhhw  %[ftmp6],   %[ftmp7],       %[ftmp1]                \n\t"
+        "punpcklhw  %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "gssdlc1    %[ftmp2],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp2],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[addr1])                          \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp2],       %[ftmp5]                \n\t"
+        "punpcklhw  %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpcklwd  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpckhwd  %[ftmp4],   %[ftmp7],       %[ftmp2]                \n\t"
+        "punpcklwd  %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[addr1])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr4],       %[stride]               \n\t"
+        "gssdlc1    %[ftmp5],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp5],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr0]                \n\t"
+        "gssdlc1    %[ftmp7],   0x07(%[addr6])                          \n\t"
+        "gssdrc1    %[ftmp7],   0x00(%[addr6])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr1],       %[addr0]                \n\t"
+        "gssdlc1    %[ftmp4],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp4],   0x00(%[addr5])                          \n\t"
+        "gsldlc1    %[ftmp8],   0x07(%[addr6])                          \n\t"
+        "gsldrc1    %[ftmp8],   0x00(%[addr6])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr1],       %[addr0]                \n\t"
+        "punpckhwd  %[ftmp0],   %[ftmp3],       %[ftmp8]                \n\t"
+        "punpcklwd  %[ftmp3],   %[ftmp3],       %[ftmp8]                \n\t"
+        "punpckhwd  %[ftmp5],   %[ftmp6],       %[ftmp1]                \n\t"
+        "punpcklwd  %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "gssdlc1    %[ftmp3],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp3],   0x00(%[addr5])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr4],       %[addr2]                \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[addr4])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[addr4])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr4],       %[addr3]                \n\t"
+        "gssdlc1    %[ftmp6],   0x07(%[addr5])                          \n\t"
+        "gssdrc1    %[ftmp6],   0x00(%[addr5])                          \n\t"
+        "gssdlc1    %[ftmp5],   0x07(%[addr6])                          \n\t"
+        "gssdrc1    %[ftmp5],   0x00(%[addr6])                          \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),            [addr5]"=&r"(addr[5]),
+          [addr6]"=&r"(addr[6])
+        : [pix]"r"(pix),                    [stride]"r"((mips_reg)stride),
+          [ptmp]"r"(ptmp),                  [pdat]"r"(pdat)
+        : "memory"
     );
 }
diff --git a/libavcodec/mips/h264pred_init_mips.c b/libavcodec/mips/h264pred_init_mips.c
index 93a2409..c33d8f7 100644
--- a/libavcodec/mips/h264pred_init_mips.c
+++ b/libavcodec/mips/h264pred_init_mips.c
@@ -115,23 +115,22 @@ static av_cold void h264_pred_init_mmi(H264PredContext *h, int codec_id,
         h->pred8x8l [TOP_DC_PRED            ] = ff_pred8x8l_top_dc_8_mmi;
         h->pred8x8l [DC_PRED                ] = ff_pred8x8l_dc_8_mmi;
 
+#if ARCH_MIPS64
         switch (codec_id) {
         case AV_CODEC_ID_SVQ3:
             h->pred16x16[PLANE_PRED8x8      ] = ff_pred16x16_plane_svq3_8_mmi;
-            ;
             break;
         case AV_CODEC_ID_RV40:
             h->pred16x16[PLANE_PRED8x8      ] = ff_pred16x16_plane_rv40_8_mmi;
-            ;
             break;
         case AV_CODEC_ID_VP7:
         case AV_CODEC_ID_VP8:
-            ;
             break;
         default:
             h->pred16x16[PLANE_PRED8x8      ] = ff_pred16x16_plane_h264_8_mmi;
             break;
         }
+#endif
 
         if (codec_id == AV_CODEC_ID_SVQ3 || codec_id == AV_CODEC_ID_H264) {
             if (chroma_format_idc == 1) {
diff --git a/libavcodec/mips/h264pred_mmi.c b/libavcodec/mips/h264pred_mmi.c
index e949d11..bb795a1 100644
--- a/libavcodec/mips/h264pred_mmi.c
+++ b/libavcodec/mips/h264pred_mmi.c
@@ -23,87 +23,134 @@
  */
 
 #include "h264pred_mips.h"
+#include "libavcodec/bit_depth_template.c"
+#include "libavutil/mips/asmdefs.h"
+#include "constants.h"
 
 void ff_pred16x16_vertical_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
+    double ftmp[2];
+    uint64_t tmp[1];
+
     __asm__ volatile (
-        "dli $8, 16                         \r\n"
-        "gsldlc1 $f2, 7(%[srcA])            \r\n"
-        "gsldrc1 $f2, 0(%[srcA])            \r\n"
-        "gsldlc1 $f4, 15(%[srcA])           \r\n"
-        "gsldrc1 $f4, 8(%[srcA])            \r\n"
-        "1:                                 \r\n"
-        "gssdlc1 $f2, 7(%[src])             \r\n"
-        "gssdrc1 $f2, 0(%[src])             \r\n"
-        "gssdlc1 $f4, 15(%[src])            \r\n"
-        "gssdrc1 $f4, 8(%[src])             \r\n"
-        "daddu %[src], %[src], %[stride]    \r\n"
-        "daddi $8, $8, -1                   \r\n"
-        "bnez $8, 1b                        \r\n"
-        : [src]"+&r"(src)
-        : [stride]"r"(stride),[srcA]"r"(src-stride)
-        : "$8","$f2","$f4"
+        "dli        %[tmp0],    0x08                                    \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[srcA])                           \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[srcA])                           \n\t"
+        "gsldlc1    %[ftmp1],   0x0f(%[srcA])                           \n\t"
+        "gsldrc1    %[ftmp1],   0x08(%[srcA])                           \n\t"
+        "1:                                                             \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "gssdlc1    %[ftmp1],   0x0f(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x08(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "gssdlc1    %[ftmp1],   0x0f(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x08(%[src])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [tmp0]"=&r"(tmp[0]),
+          [src]"+&r"(src)
+        : [stride]"r"((mips_reg)stride),    [srcA]"r"((mips_reg)(src-stride))
+        : "memory"
     );
 }
 
 void ff_pred16x16_horizontal_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
+    uint64_t tmp[3];
+    mips_reg addr[2];
+
     __asm__ volatile (
-        "daddiu $2, %[src], -1              \r\n"
-        "daddu $3, %[src], $0               \r\n"
-        "dli $6, 0x10                       \r\n"
-        "1:                                 \r\n"
-        "lbu $4, 0($2)                      \r\n"
-        "dmul $5, $4, %[ff_pb_1]            \r\n"
-        "sdl $5, 7($3)                      \r\n"
-        "sdr $5, 0($3)                      \r\n"
-        "sdl $5, 15($3)                     \r\n"
-        "sdr $5, 8($3)                      \r\n"
-        "daddu $2, %[stride]                \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "daddiu $6, -1                      \r\n"
-        "bnez $6, 1b                        \r\n"
-        ::[src]"r"(src),[stride]"r"(stride),[ff_pb_1]"r"(ff_pb_1)
-        : "$2","$3","$4","$5","$6"
+        PTR_ADDI   "%[addr0],   %[src],         -0x01                   \n\t"
+        PTR_ADDU   "%[addr1],   %[src],         $0                      \n\t"
+        "dli        %[tmp2],    0x08                                    \n\t"
+        "1:                                                             \n\t"
+        "lbu        %[tmp0],    0x00(%[addr0])                          \n\t"
+        "dmul       %[tmp1],    %[tmp0],        %[ff_pb_1]              \n\t"
+        "swl        %[tmp1],    0x07(%[addr1])                          \n\t"
+        "swr        %[tmp1],    0x00(%[addr1])                          \n\t"
+        "swl        %[tmp1],    0x0f(%[addr1])                          \n\t"
+        "swr        %[tmp1],    0x08(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[stride]               \n\t"
+        "lbu        %[tmp0],    0x00(%[addr0])                          \n\t"
+        "dmul       %[tmp1],    %[tmp0],        %[ff_pb_1]              \n\t"
+        "swl        %[tmp1],    0x07(%[addr1])                          \n\t"
+        "swr        %[tmp1],    0x00(%[addr1])                          \n\t"
+        "swl        %[tmp1],    0x0f(%[addr1])                          \n\t"
+        "swr        %[tmp1],    0x08(%[addr1])                          \n\t"
+        "daddi      %[tmp2],    %[tmp2],        -0x01                   \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[stride]               \n\t"
+        "bnez       %[tmp2],    1b                                      \n\t"
+        : [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [tmp2]"=&r"(tmp[2]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1])
+        : [src]"r"((mips_reg)src),          [stride]"r"((mips_reg)stride),
+          [ff_pb_1]"r"(ff_pb_1)
+        : "memory"
     );
 }
 
 void ff_pred16x16_dc_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
+    uint64_t tmp[4];
+    mips_reg addr[2];
+
     __asm__ volatile (
-        "daddiu $2, %[src], -1              \r\n"
-        "dli $6, 0x10                       \r\n"
-        "xor $8, $8, $8                     \r\n"
-        "1:                                 \r\n"
-        "lbu $4, 0($2)                      \r\n"
-        "daddu $8, $8, $4                   \r\n"
-        "daddu $2, $2, %[stride]            \r\n"
-        "daddiu $6, $6, -1                  \r\n"
-        "bnez $6, 1b                        \r\n"
-        "dli $6, 0x10                       \r\n"
-        "negu $3, %[stride]                 \r\n"
-        "daddu $2, %[src], $3               \r\n"
-        "2:                                 \r\n"
-        "lbu $4, 0($2)                      \r\n"
-        "daddu $8, $8, $4                   \r\n"
-        "daddiu $2, $2, 1                   \r\n"
-        "daddiu $6, $6, -1                  \r\n"
-        "bnez $6, 2b                        \r\n"
-        "daddiu $8, $8, 0x10                \r\n"
-        "dsra $8, 5                         \r\n"
-        "dmul $5, $8, %[ff_pb_1]            \r\n"
-        "daddu $2, %[src], $0               \r\n"
-        "dli $6, 0x10                       \r\n"
-        "3:                                 \r\n"
-        "sdl $5, 7($2)                      \r\n"
-        "sdr $5, 0($2)                      \r\n"
-        "sdl $5, 15($2)                     \r\n"
-        "sdr $5, 8($2)                      \r\n"
-        "daddu $2, $2, %[stride]            \r\n"
-        "daddiu $6, $6, -1                  \r\n"
-        "bnez $6, 3b                        \r\n"
-        ::[src]"r"(src),[stride]"r"(stride),[ff_pb_1]"r"(ff_pb_1)
-        : "$2","$3","$4","$5","$6","$8"
+        PTR_ADDI   "%[addr0],   %[src],         -0x01                   \n\t"
+        "dli        %[tmp0],    0x08                                    \n\t"
+        "xor        %[tmp3],    %[tmp3],        %[tmp3]                 \n\t"
+        "1:                                                             \n\t"
+        "lbu        %[tmp1],    0x00(%[addr0])                          \n\t"
+        "daddu      %[tmp3],    %[tmp3],        %[tmp1]                 \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp1],    0x00(%[addr0])                          \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        "daddu      %[tmp3],    %[tmp3],        %[tmp1]                 \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+
+        "dli        %[tmp0],    0x08                                    \n\t"
+        PTR_SUBU   "%[addr0],   %[src],         %[stride]               \n\t"
+        "2:                                                             \n\t"
+        "lbu        %[tmp1],    0x00(%[addr0])                          \n\t"
+        "daddu      %[tmp3],    %[tmp3],        %[tmp1]                 \n\t"
+        PTR_ADDIU  "%[addr0],   %[addr0],       0x01                    \n\t"
+        "lbu        %[tmp1],    0x00(%[addr0])                          \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        "daddu      %[tmp3],    %[tmp3],        %[tmp1]                 \n\t"
+        PTR_ADDIU  "%[addr0],   %[addr0],       0x01                    \n\t"
+        "bnez       %[tmp0],    2b                                      \n\t"
+
+        "daddiu     %[tmp3],    %[tmp3],        0x10                    \n\t"
+        "dsra       %[tmp3],    0x05                                    \n\t"
+        "dmul       %[tmp2],    %[tmp3],        %[ff_pb_1]              \n\t"
+        PTR_ADDU   "%[addr0],   %[src],         $0                      \n\t"
+        "dli        %[tmp0],    0x08                                    \n\t"
+        "3:                                                             \n\t"
+        "swl        %[tmp2],    0x07(%[addr0])                          \n\t"
+        "swr        %[tmp2],    0x00(%[addr0])                          \n\t"
+        "swl        %[tmp2],    0x0f(%[addr0])                          \n\t"
+        "swr        %[tmp2],    0x08(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "swl        %[tmp2],    0x07(%[addr0])                          \n\t"
+        "swr        %[tmp2],    0x00(%[addr0])                          \n\t"
+        "swl        %[tmp2],    0x0f(%[addr0])                          \n\t"
+        "swr        %[tmp2],    0x08(%[addr0])                          \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "bnez       %[tmp0],    3b                                      \n\t"
+        : [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [tmp2]"=&r"(tmp[2]),              [tmp3]"=&r"(tmp[3]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1])
+        : [src]"r"((mips_reg)src),          [stride]"r"((mips_reg)stride),
+          [ff_pb_1]"r"(ff_pb_1)
+        : "memory"
     );
 }
 
@@ -111,76 +158,95 @@ void ff_pred8x8l_top_dc_8_mmi(uint8_t *src, int has_topleft,
         int has_topright, ptrdiff_t stride)
 {
     uint32_t dc;
+    double ftmp[11];
+    mips_reg tmp[3];
 
     __asm__ volatile (
-        "ldl $8, 7(%[srcA])                 \r\n"
-        "ldr $8, 0(%[srcA])                 \r\n"
-        "ldl $9, 7(%[src0])                 \r\n"
-        "ldr $9, 0(%[src0])                 \r\n"
-        "ldl $10, 7(%[src1])                \r\n"
-        "ldr $10, 0(%[src1])                \r\n"
-        "dmtc1 $8, $f2                      \r\n"
-        "dmtc1 $9, $f4                      \r\n"
-        "dmtc1 $10, $f6                     \r\n"
-        "dmtc1 $0, $f0                      \r\n"
-        "punpcklbh $f8, $f2, $f0            \r\n"
-        "punpckhbh $f10, $f2, $f0           \r\n"
-        "punpcklbh $f12, $f4, $f0           \r\n"
-        "punpckhbh $f14, $f4, $f0           \r\n"
-        "punpcklbh $f16, $f6, $f0           \r\n"
-        "punpckhbh $f18, $f6, $f0           \r\n"
-        "bnez %[has_topleft], 1f            \r\n"
-        "pinsrh_0 $f8, $f8, $f12            \r\n"
-        "1:                                 \r\n"
-        "bnez %[has_topright], 2f           \r\n"
-        "pinsrh_3 $f18, $f18, $f14          \r\n"
-        "2:                                 \r\n"
-        "daddiu $8, $0, 2                   \r\n"
-        "dmtc1 $8, $f20                     \r\n"
-        "pshufh $f22, $f20, $f0             \r\n"
-        "pmullh $f12, $f12, $f22            \r\n"
-        "pmullh $f14, $f14, $f22            \r\n"
-        "paddh $f8, $f8, $f12               \r\n"
-        "paddh $f10, $f10, $f14             \r\n"
-        "paddh $f8, $f8, $f16               \r\n"
-        "paddh $f10, $f10, $f18             \r\n"
-        "paddh $f8, $f8, $f22               \r\n"
-        "paddh $f10, $f10, $f22             \r\n"
-        "psrah $f8, $f8, $f20               \r\n"
-        "psrah $f10, $f10, $f20             \r\n"
-        "packushb $f4, $f8, $f10            \r\n"
-        "biadd $f2, $f4                     \r\n"
-        "mfc1 $9, $f2                       \r\n"
-        "addiu $9, $9, 4                    \r\n"
-        "dsrl $9, $9, 3                     \r\n"
-        "mul %[dc], $9, %[ff_pb_1]          \r\n"
-        : [dc]"=r"(dc)
-        : [srcA]"r"(src-stride-1),[src0]"r"(src-stride),
-          [src1]"r"(src-stride+1),[has_topleft]"r"(has_topleft),
-          [has_topright]"r"(has_topright),[ff_pb_1]"r"(ff_pb_1)
-        : "$8","$9","$10","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18","$f20","$f22"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "gsldlc1    %[ftmp10],  0x07(%[srcA])                           \n\t"
+        "gsldrc1    %[ftmp10],  0x00(%[srcA])                           \n\t"
+        "gsldlc1    %[ftmp9],   0x07(%[src0])                           \n\t"
+        "gsldrc1    %[ftmp9],   0x00(%[src0])                           \n\t"
+        "gsldlc1    %[ftmp8],   0x07(%[src1])                           \n\t"
+        "gsldrc1    %[ftmp8],   0x00(%[src1])                           \n\t"
+
+        "punpcklbh  %[ftmp7],   %[ftmp10],      %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp6],   %[ftmp10],      %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp9],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp4],   %[ftmp9],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp8],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp2],   %[ftmp8],       %[ftmp0]                \n\t"
+        "bnez       %[has_topleft],             1f                      \n\t"
+        "pinsrh_0   %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+
+        "1:                                                             \n\t"
+        "bnez       %[has_topright],            2f                      \n\t"
+        "pinsrh_3   %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+
+        "2:                                                             \n\t"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "mtc1       %[tmp0],    %[ftmp1]                                \n\t"
+        "pmullh     %[ftmp5],   %[ftmp5],       %[ff_pw_2]              \n\t"
+        "pmullh     %[ftmp4],   %[ftmp4],       %[ff_pw_2]              \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp3]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ff_pw_2]              \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ff_pw_2]              \n\t"
+        "psrah      %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "psrah      %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "packushb   %[ftmp9],   %[ftmp7],       %[ftmp6]                \n\t"
+        "biadd      %[ftmp10],  %[ftmp9]                                \n\t"
+        "mfc1       %[tmp1],    %[ftmp10]                               \n\t"
+        "addiu      %[tmp1],    %[tmp1],        0x04                    \n\t"
+        "srl        %[tmp1],    %[tmp1],        0x03                    \n\t"
+        "mul        %[dc],      %[tmp1],        %[ff_pb_1]              \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),
+          [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [dc]"=r"(dc)
+        : [srcA]"r"((mips_reg)(src-stride-1)),
+          [src0]"r"((mips_reg)(src-stride)),
+          [src1]"r"((mips_reg)(src-stride+1)),
+          [has_topleft]"r"(has_topleft),    [has_topright]"r"(has_topright),
+          [ff_pb_1]"r"(ff_pb_1),            [ff_pw_2]"f"(ff_pw_2)
+        : "memory"
     );
 
     __asm__ volatile (
-        "dli $8, 8                          \r\n"
-        "1:                                 \r\n"
-        "punpcklwd $f2, %[dc], %[dc]        \r\n"
-        "gssdlc1 $f2, 7(%[src])             \r\n"
-        "gssdrc1 $f2, 0(%[src])             \r\n"
-        "daddu %[src], %[src], %[stride]    \r\n"
-        "daddi $8, $8, -1                   \r\n"
-        "bnez $8, 1b                        \r\n"
-        : [src]"+&r"(src)
-        : [dc]"f"(dc),[stride]"r"(stride)
-        : "$8","$f2"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "punpcklwd  %[ftmp0],   %[dc],          %[dc]                   \n\t"
+        "1:                                                             \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "gssdxc1    %[ftmp0],   0x00(%[src],    %[stride])              \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "gssdxc1    %[ftmp0],   0x00(%[src],    %[stride])              \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [tmp0]"=&r"(tmp[0]),
+          [src]"+&r"(src)
+        : [dc]"f"(dc),                      [stride]"r"((mips_reg)stride)
+        : "memory"
     );
 }
 
-void ff_pred8x8l_dc_8_mmi(uint8_t *src, int has_topleft,
-        int has_topright, ptrdiff_t stride)
+void ff_pred8x8l_dc_8_mmi(uint8_t *src, int has_topleft, int has_topright,
+        ptrdiff_t stride)
 {
     uint32_t dc, dc1, dc2;
+    double ftmp[14];
+    mips_reg tmp[1];
 
     const int l0 = ((has_topleft ? src[-1+-1*stride] : src[-1+0*stride]) + 2*src[-1+0*stride] + src[-1+1*stride] + 2) >> 2;
     const int l1 = (src[-1+0*stride] + 2*src[-1+1*stride] + src[-1+2*stride] + 2) >> 2;
@@ -192,140 +258,170 @@ void ff_pred8x8l_dc_8_mmi(uint8_t *src, int has_topleft,
     const int l7 = (src[-1+6*stride] + 2*src[-1+7*stride] + src[-1+7*stride] + 2) >> 2;
 
     __asm__ volatile (
-        "ldl $8, 7(%[srcA])                 \r\n"
-        "ldr $8, 0(%[srcA])                 \r\n"
-        "ldl $9, 7(%[src0])                 \r\n"
-        "ldr $9, 0(%[src0])                 \r\n"
-        "ldl $10, 7(%[src1])                \r\n"
-        "ldr $10, 0(%[src1])                \r\n"
-        "dmtc1 $8, $f2                      \r\n"
-        "dmtc1 $9, $f4                      \r\n"
-        "dmtc1 $10, $f6                     \r\n"
-        "dmtc1 $0, $f0                      \r\n"
-        "punpcklbh $f8, $f2, $f0            \r\n"
-        "punpckhbh $f10, $f2, $f0           \r\n"
-        "punpcklbh $f12, $f4, $f0           \r\n"
-        "punpckhbh $f14, $f4, $f0           \r\n"
-        "punpcklbh $f16, $f6, $f0           \r\n"
-        "punpckhbh $f18, $f6, $f0           \r\n"
-        "daddiu $8, $0, 3                   \r\n"
-        "dmtc1 $8, $f20                     \r\n"
-        "pshufh $f28, $f10, $f20            \r\n"
-        "pshufh $f30, $f18, $f20            \r\n"
-        "pinsrh_3 $f10, $f10, $f30          \r\n"
-        "pinsrh_3 $f18, $f18, $f28          \r\n"
-        "bnez %[has_topleft], 1f            \r\n"
-        "pinsrh_0 $f8, $f8, $f12            \r\n"
-        "1:                                 \r\n"
-        "bnez %[has_topright], 2f           \r\n"
-        "pshufh $f30, $f14, $f20            \r\n"
-        "pinsrh_3 $f10, $f10, $f30          \r\n"
-        "2:                                 \r\n"
-        "daddiu $8, $0, 2                   \r\n"
-        "dmtc1 $8, $f20                     \r\n"
-        "pshufh $f22, $f20, $f0             \r\n"
-        "pmullh $f12, $f12, $f22            \r\n"
-        "pmullh $f14, $f14, $f22            \r\n"
-        "paddh $f8, $f8, $f12               \r\n"
-        "paddh $f10, $f10, $f14             \r\n"
-        "paddh $f8, $f8, $f16               \r\n"
-        "paddh $f10, $f10, $f18             \r\n"
-        "paddh $f8, $f8, $f22               \r\n"
-        "paddh $f10, $f10, $f22             \r\n"
-        "psrah $f8, $f8, $f20               \r\n"
-        "psrah $f10, $f10, $f20             \r\n"
-        "packushb $f4, $f8, $f10            \r\n"
-        "biadd $f2, $f4                     \r\n"
-        "mfc1 %[dc2], $f2                   \r\n"
-        : [dc2]"=r"(dc2)
-        : [srcA]"r"(src-stride-1),[src0]"r"(src-stride),
-          [src1]"r"(src-stride+1),[has_topleft]"r"(has_topleft),
-          [has_topright]"r"(has_topright)
-        : "$8","$9","$10","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18","$f20","$f22"
+        "gsldlc1    %[ftmp4],   0x07(%[srcA])                           \n\t"
+        "gsldrc1    %[ftmp4],   0x00(%[srcA])                           \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[src0])                           \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[src0])                           \n\t"
+        "gsldlc1    %[ftmp6],   0x07(%[src1])                           \n\t"
+        "gsldrc1    %[ftmp6],   0x00(%[src1])                           \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dli        %[tmp0],    0x03                                    \n\t"
+        "punpcklbh  %[ftmp7],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp8],   %[ftmp4],       %[ftmp0]                \n\t"
+        "mtc1       %[tmp0],    %[ftmp1]                                \n\t"
+        "punpcklbh  %[ftmp9],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp10],  %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp11],  %[ftmp6],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp12],  %[ftmp6],       %[ftmp0]                \n\t"
+        "pshufh     %[ftmp3],   %[ftmp8],       %[ftmp1]                \n\t"
+        "pshufh     %[ftmp13],  %[ftmp12],      %[ftmp1]                \n\t"
+        "pinsrh_3   %[ftmp8],   %[ftmp8],       %[ftmp13]               \n\t"
+        "pinsrh_3   %[ftmp12],  %[ftmp12],      %[ftmp3]                \n\t"
+        "bnez       %[has_topleft],             1f                      \n\t"
+        "pinsrh_0   %[ftmp7],   %[ftmp7],       %[ftmp9]                \n\t"
+
+        "1:                                                             \n\t"
+        "bnez       %[has_topright],            2f                      \n\t"
+        "pshufh     %[ftmp13],  %[ftmp10],      %[ftmp1]                \n\t"
+        "pinsrh_3   %[ftmp8],   %[ftmp8],       %[ftmp13]               \n\t"
+
+        "2:                                                             \n\t"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "mtc1       %[tmp0],    %[ftmp1]                                \n\t"
+        "pshufh     %[ftmp2],   %[ftmp1],       %[ftmp0]                \n\t"
+        "pmullh     %[ftmp9],   %[ftmp9],       %[ftmp2]                \n\t"
+        "pmullh     %[ftmp10],  %[ftmp10],      %[ftmp2]                \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddh      %[ftmp8],   %[ftmp8],       %[ftmp10]               \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp11]               \n\t"
+        "paddh      %[ftmp8],   %[ftmp8],       %[ftmp12]               \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp8],   %[ftmp8],       %[ftmp2]                \n\t"
+        "psrah      %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "psrah      %[ftmp8],   %[ftmp8],       %[ftmp1]                \n\t"
+        "packushb   %[ftmp5],   %[ftmp7],       %[ftmp8]                \n\t"
+        "biadd      %[ftmp4],   %[ftmp5]                                \n\t"
+        "mfc1       %[dc2],     %[ftmp4]                                \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),          [ftmp11]"=&f"(ftmp[11]),
+          [ftmp12]"=&f"(ftmp[12]),          [ftmp13]"=&f"(ftmp[13]),
+          [tmp0]"=&r"(tmp[0]),              [dc2]"=r"(dc2)
+        : [srcA]"r"((mips_reg)(src-stride-1)),
+          [src0]"r"((mips_reg)(src-stride)),
+          [src1]"r"((mips_reg)(src-stride+1)),
+          [has_topleft]"r"(has_topleft),    [has_topright]"r"(has_topright)
+        : "memory"
     );
 
     dc1 = l0+l1+l2+l3+l4+l5+l6+l7;
     dc = ((dc1+dc2+8)>>4)*0x01010101U;
 
     __asm__ volatile (
-        "dli $8, 8                          \r\n"
-        "1:                                 \r\n"
-        "punpcklwd $f2, %[dc], %[dc]        \r\n"
-        "gssdlc1 $f2, 7(%[src])             \r\n"
-        "gssdrc1 $f2, 0(%[src])             \r\n"
-        "daddu %[src], %[src], %[stride]    \r\n"
-        "daddi $8, $8, -1                   \r\n"
-        "bnez $8, 1b                        \r\n"
-        : [src]"+&r"(src)
-        : [dc]"f"(dc),[stride]"r"(stride)
-        : "$8","$f2"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "punpcklwd  %[ftmp0],   %[dc],          %[dc]                   \n\t"
+        "1:                                                             \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "gssdxc1    %[ftmp0],   0x00(%[src],    %[stride])              \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "gssdxc1    %[ftmp0],   0x00(%[src],    %[stride])              \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [tmp0]"=&r"(tmp[0]),
+          [src]"+&r"(src)
+        : [dc]"f"(dc),                      [stride]"r"((mips_reg)stride)
+        : "memory"
     );
 }
 
 void ff_pred8x8l_vertical_8_mmi(uint8_t *src, int has_topleft,
         int has_topright, ptrdiff_t stride)
 {
+    double ftmp[12];
+    mips_reg tmp[1];
+
     __asm__ volatile (
-        "ldl $8, 7(%[srcA])                 \r\n"
-        "ldr $8, 0(%[srcA])                 \r\n"
-        "ldl $9, 7(%[src0])                 \r\n"
-        "ldr $9, 0(%[src0])                 \r\n"
-        "ldl $10, 7(%[src1])                \r\n"
-        "ldr $10, 0(%[src1])                \r\n"
-        "dmtc1 $8, $f2                      \r\n"
-        "dmtc1 $9, $f4                      \r\n"
-        "dmtc1 $10, $f6                     \r\n"
-        "dmtc1 $0, $f0                      \r\n"
-        "punpcklbh $f8, $f2, $f0            \r\n"
-        "punpckhbh $f10, $f2, $f0           \r\n"
-        "punpcklbh $f12, $f4, $f0           \r\n"
-        "punpckhbh $f14, $f4, $f0           \r\n"
-        "punpcklbh $f16, $f6, $f0           \r\n"
-        "punpckhbh $f18, $f6, $f0           \r\n"
-        "bnez %[has_topleft], 1f            \r\n"
-        "pinsrh_0 $f8, $f8, $f12            \r\n"
-        "1:                                 \r\n"
-        "bnez %[has_topright], 2f           \r\n"
-        "pinsrh_3 $f18, $f18, $f14          \r\n"
-        "2:                                 \r\n"
-        "daddiu $8, $0, 2                   \r\n"
-        "dmtc1 $8, $f20                     \r\n"
-        "pshufh $f22, $f20, $f0             \r\n"
-        "pmullh $f12, $f12, $f22            \r\n"
-        "pmullh $f14, $f14, $f22            \r\n"
-        "paddh $f8, $f8, $f12               \r\n"
-        "paddh $f10, $f10, $f14             \r\n"
-        "paddh $f8, $f8, $f16               \r\n"
-        "paddh $f10, $f10, $f18             \r\n"
-        "paddh $f8, $f8, $f22               \r\n"
-        "paddh $f10, $f10, $f22             \r\n"
-        "psrah $f8, $f8, $f20               \r\n"
-        "psrah $f10, $f10, $f20             \r\n"
-        "packushb $f4, $f8, $f10            \r\n"
-        "sdc1 $f4, 0(%[src])                \r\n"
-        : [src]"=r"(src)
-        : [srcA]"r"(src-stride-1),[src0]"r"(src-stride),
-          [src1]"r"(src-stride+1),[has_topleft]"r"(has_topleft),
-          [has_topright]"r"(has_topright)
-        : "$8","$9","$10","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18","$f20","$f22"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[srcA])                           \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[srcA])                           \n\t"
+        "gsldlc1    %[ftmp4],   0x07(%[src0])                           \n\t"
+        "gsldrc1    %[ftmp4],   0x00(%[src0])                           \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[src1])                           \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[src1])                           \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp8],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp9],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp10],  %[ftmp5],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp11],  %[ftmp5],       %[ftmp0]                \n\t"
+        "bnez       %[has_topleft],             1f                      \n\t"
+        "pinsrh_0   %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+
+        "1:                                                             \n\t"
+        "bnez       %[has_topright],            2f                      \n\t"
+        "pinsrh_3   %[ftmp11],  %[ftmp11],      %[ftmp9]                \n\t"
+
+        "2:                                                             \n\t"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "mtc1       %[tmp0],    %[ftmp1]                                \n\t"
+        "pshufh     %[ftmp2],   %[ftmp1],       %[ftmp0]                \n\t"
+        "pmullh     %[ftmp8],   %[ftmp8],       %[ftmp2]                \n\t"
+        "pmullh     %[ftmp9],   %[ftmp9],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp10]               \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp11]               \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        "psrah      %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "psrah      %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp6],       %[ftmp7]                \n\t"
+        "sdc1       %[ftmp4],   0x00(%[src])                            \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),          [ftmp11]"=&f"(ftmp[11]),
+          [tmp0]"=&r"(tmp[0]),
+          [src]"=r"(src)
+        : [srcA]"r"((mips_reg)(src-stride-1)),
+          [src0]"r"((mips_reg)(src-stride)),
+          [src1]"r"((mips_reg)(src-stride+1)),
+          [has_topleft]"r"(has_topleft),    [has_topright]"r"(has_topright)
+        : "memory"
     );
 
     __asm__ volatile (
-        "dli $8, 7                          \r\n"
-        "gsldlc1 $f2, 7(%[src])             \r\n"
-        "gsldrc1 $f2, 0(%[src])             \r\n"
-        "dadd %[src], %[src], %[stride]     \r\n"
-        "1:                                 \r\n"
-        "gssdlc1 $f2, 7(%[src])             \r\n"
-        "gssdrc1 $f2, 0(%[src])             \r\n"
-        "daddu %[src], %[src], %[stride]    \r\n"
-        "daddi $8, $8, -1                   \r\n"
-        "bnez $8, 1b                        \r\n"
-        : [src]"+&r"(src)
-        : [stride]"r"(stride)
-        : "$8","$f2"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "1:                                                             \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [tmp0]"=&r"(tmp[0]),
+          [src]"+&r"(src)
+        : [stride]"r"((mips_reg)stride)
+        : "memory"
     );
 }
 
@@ -335,446 +431,562 @@ void ff_pred4x4_dc_8_mmi(uint8_t *src, const uint8_t *topright,
     const int dc = (src[-stride] + src[1-stride] + src[2-stride]
                  + src[3-stride] + src[-1+0*stride] + src[-1+1*stride]
                  + src[-1+2*stride] + src[-1+3*stride] + 4) >>3;
+    uint64_t tmp[2];
+    mips_reg addr[1];
 
     __asm__ volatile (
-        "daddu $2, %[dc], $0                \r\n"
-        "dmul $3, $2, %[ff_pb_1]            \r\n"
-        "xor $4, $4, $4                     \r\n"
-        "gsswx $3, 0(%[src],$4)             \r\n"
-        "daddu $4, %[stride]                \r\n"
-        "gsswx $3, 0(%[src],$4)             \r\n"
-        "daddu $4, %[stride]                \r\n"
-        "gsswx $3, 0(%[src],$4)             \r\n"
-        "daddu $4, %[stride]                \r\n"
-        "gsswx $3, 0(%[src],$4)             \r\n"
-        ::[src]"r"(src),[stride]"r"(stride),[dc]"r"(dc),[ff_pb_1]"r"(ff_pb_1)
-        : "$2","$3","$4"
+        PTR_ADDU   "%[tmp0],    %[dc],          $0                      \n\t"
+        "dmul       %[tmp1],    %[tmp0],        %[ff_pb_1]              \n\t"
+        "xor        %[addr0],   %[addr0],       %[addr0]                \n\t"
+        "gsswx      %[tmp1],    0x00(%[src],    %[addr0])               \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "gsswx      %[tmp1],    0x00(%[src],    %[addr0])               \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "gsswx      %[tmp1],    0x00(%[src],    %[addr0])               \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "gsswx      %[tmp1],    0x00(%[src],    %[addr0])               \n\t"
+        : [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [addr0]"=&r"(addr[0])
+        : [src]"r"((mips_reg)src),          [stride]"r"((mips_reg)stride),
+          [dc]"r"(dc),                      [ff_pb_1]"r"(ff_pb_1)
+        : "memory"
     );
 }
 
 void ff_pred8x8_vertical_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
+    uint64_t tmp[2];
+    mips_reg addr[2];
+
     __asm__ volatile (
-        "dsubu $2, %[src], %[stride]        \r\n"
-        "daddu $3, %[src], $0               \r\n"
-        "ldl $4, 7($2)                      \r\n"
-        "ldr $4, 0($2)                      \r\n"
-        "dli $5, 0x8                        \r\n"
-        "1:                                 \r\n"
-        "sdl $4, 7($3)                      \r\n"
-        "sdr $4, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "daddiu $5, -1                      \r\n"
-        "bnez $5, 1b                        \r\n"
-        ::[src]"r"(src),[stride]"r"(stride)
-        : "$2","$3","$4","$5"
+        PTR_SUBU   "%[addr0],   %[src],         %[stride]               \n\t"
+        PTR_ADDU   "%[addr1],   %[src],         $0                      \n\t"
+        "ldl        %[tmp0],    0x07(%[addr0])                          \n\t"
+        "ldr        %[tmp0],    0x00(%[addr0])                          \n\t"
+        "dli        %[tmp1],    0x04                                    \n\t"
+        "1:                                                             \n\t"
+        "sdl        %[tmp0],    0x07(%[addr1])                          \n\t"
+        "sdr        %[tmp0],    0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr1],   %[stride]                               \n\t"
+        "sdl        %[tmp0],    0x07(%[addr1])                          \n\t"
+        "sdr        %[tmp0],    0x00(%[addr1])                          \n\t"
+        "daddi      %[tmp1],    -0x01                                   \n\t"
+        PTR_ADDU   "%[addr1],   %[stride]                               \n\t"
+        "bnez       %[tmp1],    1b                                      \n\t"
+        : [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1])
+        : [src]"r"((mips_reg)src),          [stride]"r"((mips_reg)stride)
+        : "memory"
     );
 }
 
 void ff_pred8x8_horizontal_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
+    uint64_t tmp[3];
+    mips_reg addr[2];
+
     __asm__ volatile (
-        "daddiu $2, %[src], -1              \r\n"
-        "daddu $3, %[src], $0               \r\n"
-        "dli $6, 0x8                        \r\n"
-        "1:                                 \r\n"
-        "lbu $4, 0($2)                      \r\n"
-        "dmul $5, $4, %[ff_pb_1]            \r\n"
-        "sdl $5, 7($3)                      \r\n"
-        "sdr $5, 0($3)                      \r\n"
-        "daddu $2, %[stride]                \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "daddiu $6, -1                      \r\n"
-        "bnez $6, 1b                        \r\n"
-        ::[src]"r"(src),[stride]"r"(stride),[ff_pb_1]"r"(ff_pb_1)
-        : "$2","$3","$4","$5","$6"
+        PTR_ADDI   "%[addr0],   %[src],         -0x01                   \n\t"
+        PTR_ADDU   "%[addr1],   %[src],         $0                      \n\t"
+        "dli        %[tmp0],    0x04                                    \n\t"
+        "1:                                                             \n\t"
+        "lbu        %[tmp1],    0x00(%[addr0])                          \n\t"
+        "dmul       %[tmp2],    %[tmp1],        %[ff_pb_1]              \n\t"
+        "swl        %[tmp2],    0x07(%[addr1])                          \n\t"
+        "swr        %[tmp2],    0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[stride]               \n\t"
+        "lbu        %[tmp1],    0x00(%[addr0])                          \n\t"
+        "dmul       %[tmp2],    %[tmp1],        %[ff_pb_1]              \n\t"
+        "swl        %[tmp2],    0x07(%[addr1])                          \n\t"
+        "swr        %[tmp2],    0x00(%[addr1])                          \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[stride]               \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [tmp2]"=&r"(tmp[2]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1])
+        : [src]"r"((mips_reg)src),          [stride]"r"((mips_reg)stride),
+          [ff_pb_1]"r"(ff_pb_1)
+        : "memory"
     );
 }
 
-static void ff_pred16x16_plane_compat_8_mmi(uint8_t *src, ptrdiff_t stride,
-        const int svq3, const int rv40)
+void ff_pred8x8_top_dc_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
+    double ftmp[4];
+    uint64_t tmp[1];
+    mips_reg addr[1];
+
     __asm__ volatile (
-        "negu $2, %[stride]                 \r\n"
-        "daddu $3, %[src], $2               \r\n"
-        "xor $f8, $f8, $f8                  \r\n"
-        "gslwlc1 $f0, 2($3)                 \r\n"
-        "gslwrc1 $f0, -1($3)                \r\n"
-        "gslwlc1 $f2, 6($3)                 \r\n"
-        "gslwrc1 $f2, 3($3)                 \r\n"
-        "gslwlc1 $f4, 11($3)                \r\n"
-        "gslwrc1 $f4, 8($3)                 \r\n"
-        "gslwlc1 $f6, 15($3)                \r\n"
-        "gslwrc1 $f6, 12($3)                \r\n"
-        "punpcklbh $f0, $f0, $f8            \r\n"
-        "punpcklbh $f2, $f2, $f8            \r\n"
-        "punpcklbh $f4, $f4, $f8            \r\n"
-        "punpcklbh $f6, $f6, $f8            \r\n"
-        "dmtc1 %[ff_pw_m8tom5], $f20        \r\n"
-        "dmtc1 %[ff_pw_m4tom1], $f22        \r\n"
-        "dmtc1 %[ff_pw_1to4], $f24          \r\n"
-        "dmtc1 %[ff_pw_5to8], $f26          \r\n"
-        "pmullh $f0, $f0, $f20              \r\n"
-        "pmullh $f2, $f2, $f22              \r\n"
-        "pmullh $f4, $f4, $f24              \r\n"
-        "pmullh $f6, $f6, $f26              \r\n"
-        "paddsh $f0, $f0, $f4               \r\n"
-        "paddsh $f2, $f2, $f6               \r\n"
-        "paddsh $f0, $f0, $f2               \r\n"
-        "dli $4, 0xE                        \r\n"
-        "dmtc1 $4, $f28                     \r\n"
-        "pshufh $f2, $f0, $f28              \r\n"
-        "paddsh $f0, $f0, $f2               \r\n"
-        "dli $4, 0x1                        \r\n"
-        "dmtc1 $4, $f30                     \r\n"
-        "pshufh $f2, $f0, $f30              \r\n"
-        "paddsh $f10, $f0, $f2              \r\n"
-        "daddiu $3, %[src], -1              \r\n"
-        "daddu $3, $2                       \r\n"
-        "lbu $4, 0($3)                      \r\n"
-        "lbu $8, 16($3)                     \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $5, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $6, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $7, 0($3)                      \r\n"
-        "dsll $5, 16                        \r\n"
-        "dsll $6, 32                        \r\n"
-        "dsll $7, 48                        \r\n"
-        "or $6, $7                          \r\n"
-        "or $4, $5                          \r\n"
-        "or $4, $6                          \r\n"
-        "dmtc1 $4, $f0                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $4, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $5, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $6, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $7, 0($3)                      \r\n"
-        "dsll $5, 16                        \r\n"
-        "dsll $6, 32                        \r\n"
-        "dsll $7, 48                        \r\n"
-        "or $6, $7                          \r\n"
-        "or $4, $5                          \r\n"
-        "or $4, $6                          \r\n"
-        "dmtc1 $4, $f2                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $4, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $5, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $6, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $7, 0($3)                      \r\n"
-        "dsll $5, 16                        \r\n"
-        "dsll $6, 32                        \r\n"
-        "dsll $7, 48                        \r\n"
-        "or $6, $7                          \r\n"
-        "or $4, $5                          \r\n"
-        "or $4, $6                          \r\n"
-        "dmtc1 $4, $f4                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $4, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $5, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $6, 0($3)                      \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "lbu $7, 0($3)                      \r\n"
-        "daddu $8, $7                       \r\n"
-        "daddiu $8, 1                       \r\n"
-        "dsll $8, 4                         \r\n"
-        "dsll $5, 16                        \r\n"
-        "dsll $6, 32                        \r\n"
-        "dsll $7, 48                        \r\n"
-        "or $6, $7                          \r\n"
-        "or $4, $5                          \r\n"
-        "or $4, $6                          \r\n"
-        "dmtc1 $4, $f6                      \r\n"
-        "pmullh $f0, $f0, $f20              \r\n"
-        "pmullh $f2, $f2, $f22              \r\n"
-        "pmullh $f4, $f4, $f24              \r\n"
-        "pmullh $f6, $f6, $f26              \r\n"
-        "paddsh $f0, $f0, $f4               \r\n"
-        "paddsh $f2, $f2, $f6               \r\n"
-        "paddsh $f0, $f0, $f2               \r\n"
-        "pshufh $f2, $f0, $f28              \r\n"
-        "paddsh $f0, $f0, $f2               \r\n"
-        "pshufh $f2, $f0, $f30              \r\n"
-        "paddsh $f12, $f0, $f2              \r\n"
-        "dmfc1 $2, $f10                     \r\n"
-        "dsll $2, 48                        \r\n"
-        "dsra $2, 48                        \r\n"
-        "dmfc1 $3, $f12                     \r\n"
-        "dsll $3, 48                        \r\n"
-        "dsra $3, 48                        \r\n"
-        "beqz %[svq3], 1f                   \r\n"
-        "dli $4, 4                          \r\n"
-        "ddiv $2, $4                        \r\n"
-        "ddiv $3, $4                        \r\n"
-        "dli $4, 5                          \r\n"
-        "dmul $2, $4                        \r\n"
-        "dmul $3, $4                        \r\n"
-        "dli $4, 16                         \r\n"
-        "ddiv $2, $4                        \r\n"
-        "ddiv $3, $4                        \r\n"
-        "daddu $4, $2, $0                   \r\n"
-        "daddu $2, $3, $0                   \r\n"
-        "daddu $3, $4, $0                   \r\n"
-        "b 2f                               \r\n"
-        "1:                                 \r\n"
-        "beqz %[rv40], 1f                   \r\n"
-        "dsra $4, $2, 2                     \r\n"
-        "daddu $2, $4                       \r\n"
-        "dsra $4, $3, 2                     \r\n"
-        "daddu $3, $4                       \r\n"
-        "dsra $2, 4                         \r\n"
-        "dsra $3, 4                         \r\n"
-        "b 2f                               \r\n"
-        "1:                                 \r\n"
-        "dli $4, 5                          \r\n"
-        "dmul $2, $4                        \r\n"
-        "dmul $3, $4                        \r\n"
-        "daddiu $2, 32                      \r\n"
-        "daddiu $3, 32                      \r\n"
-        "dsra $2, 6                         \r\n"
-        "dsra $3, 6                         \r\n"
-        "2:                                 \r\n"
-        "daddu $5, $2, $3                   \r\n"
-        "dli $4, 7                          \r\n"
-        "dmul $5, $4                        \r\n"
-        "dsubu $8, $5                       \r\n"
-        "dmtc1 $0, $f8                      \r\n"
-        "dmtc1 $2, $f0                      \r\n"
-        "pshufh $f0, $f0, $f8               \r\n"
-        "dmtc1 $3, $f10                     \r\n"
-        "pshufh $f10, $f10, $f8             \r\n"
-        "dmtc1 $8, $f12                     \r\n"
-        "pshufh $f12, $f12, $f8             \r\n"
-        "dli $4, 5                          \r\n"
-        "dmtc1 $4, $f14                     \r\n"
-        "pmullh $f2, %[ff_pw_0to3], $f0     \r\n"
-        "pmullh $f4, %[ff_pw_4to7], $f0     \r\n"
-        "pmullh $f6, %[ff_pw_8tob], $f0     \r\n"
-        "pmullh $f8, %[ff_pw_ctof], $f0     \r\n"
-        "daddu $3, %[src], $0               \r\n"
-        "dli $2, 16                         \r\n"
-        "1:                                 \r\n"
-        "paddsh $f16, $f2, $f12             \r\n"
-        "psrah $f16, $f16, $f14             \r\n"
-        "paddsh $f18, $f4, $f12             \r\n"
-        "psrah $f18, $f18, $f14             \r\n"
-        "packushb $f20, $f16, $f18          \r\n"
-        "gssdlc1 $f20, 7($3)                \r\n"
-        "gssdrc1 $f20, 0($3)                \r\n"
-        "paddsh $f16, $f6, $f12             \r\n"
-        "psrah $f16, $f16, $f14             \r\n"
-        "paddsh $f18, $f8, $f12             \r\n"
-        "psrah $f18, $f18, $f14             \r\n"
-        "packushb $f20, $f16, $f18          \r\n"
-        "gssdlc1 $f20, 15($3)               \r\n"
-        "gssdrc1 $f20, 8($3)                \r\n"
-        "paddsh $f12, $f12, $f10            \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "daddiu $2, -1                      \r\n"
-        "bnez $2, 1b                        \r\n"
-        ::[src]"r"(src),[stride]"r"(stride),[svq3]"r"(svq3),[rv40]"r"(rv40),
-          [ff_pw_m8tom5]"r"(ff_pw_m8tom5),[ff_pw_m4tom1]"r"(ff_pw_m4tom1),
-          [ff_pw_1to4]"r"(ff_pw_1to4),[ff_pw_5to8]"r"(ff_pw_5to8),
-          [ff_pw_0to3]"f"(ff_pw_0to3),[ff_pw_4to7]"f"(ff_pw_4to7),
-          [ff_pw_8tob]"f"(ff_pw_8tob),[ff_pw_ctof]"f"(ff_pw_ctof)
-        : "$2","$3","$4","$5","$6","$7","$8","$f0","$f2","$f4","$f6","$f8",
-          "$f10","$f12","$f14","$f16","$f18","$f20","$f22","$f24","$f26",
-          "$f28","$f30"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        PTR_SUBU   "%[addr0],   %[src],         %[stride]               \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp1],       %[ftmp0]                \n\t"
+        "biadd      %[ftmp2],   %[ftmp2]                                \n\t"
+        "biadd      %[ftmp3],   %[ftmp3]                                \n\t"
+        "mtc1       %[tmp0],    %[ftmp1]                                \n\t"
+        "pshufh     %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "pshufh     %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "pshufh     %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "paddush    %[ftmp2],   %[ftmp2],       %[ftmp1]                \n\t"
+        "paddush    %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "mtc1       %[tmp0],    %[ftmp1]                                \n\t"
+        "psrlh      %[ftmp2],   %[ftmp2],       %[ftmp1]                \n\t"
+        "psrlh      %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "packushb   %[ftmp1],   %[ftmp2],       %[ftmp3]                \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [tmp0]"=&r"(tmp[0]),
+          [addr0]"=&r"(addr[0]),
+          [src]"+&r"(src)
+        : [stride]"r"((mips_reg)stride)
+        : "memory"
     );
 }
 
-void ff_pred16x16_plane_svq3_8_mmi(uint8_t *src, ptrdiff_t stride)
+void ff_pred8x8_dc_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
-    ff_pred16x16_plane_compat_8_mmi(src, stride, 1, 0);
-}
+    double ftmp[5];
+    mips_reg addr[7];
 
-void ff_pred16x16_plane_rv40_8_mmi(uint8_t *src, ptrdiff_t stride)
-{
-    ff_pred16x16_plane_compat_8_mmi(src, stride, 0, 1);
+    __asm__ volatile (
+        "negu       %[addr0],   %[stride]                               \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[src]                  \n\t"
+        PTR_ADDIU  "%[addr1],   %[addr0],       0x04                    \n\t"
+        "lbu        %[addr2],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr3],   $0,             %[addr2]                \n\t"
+        PTR_ADDIU  "%[addr0],   0x01                                    \n\t"
+        "lbu        %[addr2],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr4],   $0,             %[addr2]                \n\t"
+        PTR_ADDIU  "%[addr1],   0x01                                    \n\t"
+        "lbu        %[addr2],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr3],       %[addr2]                \n\t"
+        PTR_ADDIU  "%[addr0],   0x01                                    \n\t"
+        "lbu        %[addr2],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr4],   %[addr4],       %[addr2]                \n\t"
+        PTR_ADDIU  "%[addr1],   0x01                                    \n\t"
+        "lbu        %[addr2],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr3],       %[addr2]                \n\t"
+        PTR_ADDIU  "%[addr0],   0x01                                    \n\t"
+        "lbu        %[addr2],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr4],   %[addr4],       %[addr2]                \n\t"
+        PTR_ADDIU  "%[addr1],   0x01                                    \n\t"
+        "lbu        %[addr2],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr3],   %[addr3],       %[addr2]                \n\t"
+        PTR_ADDIU  "%[addr0],   0x01                                    \n\t"
+        "lbu        %[addr2],   0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr4],   %[addr4],       %[addr2]                \n\t"
+        PTR_ADDIU  "%[addr1],   0x01                                    \n\t"
+        "dli        %[addr2],  -0x01                                    \n\t"
+        PTR_ADDU   "%[addr2],   %[addr2],       %[src]                  \n\t"
+        "lbu        %[addr1],   0x00(%[addr2])                          \n\t"
+        PTR_ADDU   "%[addr5],   $0,             %[addr1]                \n\t"
+        PTR_ADDU   "%[addr2],   %[addr2],       %[stride]               \n\t"
+        "lbu        %[addr1],   0x00(%[addr2])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr5],       %[addr1]                \n\t"
+        PTR_ADDU   "%[addr2],   %[addr2],       %[stride]               \n\t"
+        "lbu        %[addr1],   0x00(%[addr2])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr5],       %[addr1]                \n\t"
+        PTR_ADDU   "%[addr2],   %[addr2],       %[stride]               \n\t"
+        "lbu        %[addr1],   0x00(%[addr2])                          \n\t"
+        PTR_ADDU   "%[addr5],   %[addr5],       %[addr1]                \n\t"
+        PTR_ADDU   "%[addr2],   %[addr2],       %[stride]               \n\t"
+        "lbu        %[addr1],   0x00(%[addr2])                          \n\t"
+        PTR_ADDU   "%[addr6],   $0,             %[addr1]                \n\t"
+        PTR_ADDU   "%[addr2],   %[addr2],       %[stride]               \n\t"
+        "lbu        %[addr1],   0x00(%[addr2])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr6],       %[addr1]                \n\t"
+        PTR_ADDU   "%[addr2],   %[addr2],       %[stride]               \n\t"
+        "lbu        %[addr1],   0x00(%[addr2])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr6],       %[addr1]                \n\t"
+        PTR_ADDU   "%[addr2],   %[addr2],       %[stride]               \n\t"
+        "lbu        %[addr1],   0x00(%[addr2])                          \n\t"
+        PTR_ADDU   "%[addr6],   %[addr6],       %[addr1]                \n\t"
+        PTR_ADDU   "%[addr3],   %[addr3],       %[addr5]                \n\t"
+        PTR_ADDIU  "%[addr3],   %[addr3],       0x04                    \n\t"
+        PTR_ADDIU  "%[addr4],   %[addr4],       0x02                    \n\t"
+        PTR_ADDIU  "%[addr1],   %[addr6],       0x02                    \n\t"
+        PTR_ADDU   "%[addr2],   %[addr4],       %[addr1]                \n\t"
+        PTR_SRL    "%[addr3],   0x03                                    \n\t"
+        PTR_SRL    "%[addr4],   0x02                                    \n\t"
+        PTR_SRL    "%[addr1],   0x02                                    \n\t"
+        PTR_SRL    "%[addr2],   0x03                                    \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dmtc1      %[addr3],   %[ftmp1]                                \n\t"
+        "pshufh     %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "dmtc1      %[addr4],   %[ftmp2]                                \n\t"
+        "pshufh     %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "dmtc1      %[addr1],   %[ftmp3]                                \n\t"
+        "pshufh     %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "dmtc1      %[addr2],   %[ftmp4]                                \n\t"
+        "pshufh     %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "packushb   %[ftmp2],   %[ftmp3],       %[ftmp4]                \n\t"
+        PTR_ADDU   "%[addr0],   $0,             %[src]                  \n\t"
+        "sdc1       %[ftmp1],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "sdc1       %[ftmp1],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "sdc1       %[ftmp1],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "sdc1       %[ftmp1],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "sdc1       %[ftmp2],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "sdc1       %[ftmp2],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "sdc1       %[ftmp2],   0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "sdc1       %[ftmp2],   0x00(%[addr0])                          \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),            [addr5]"=&r"(addr[5]),
+          [addr6]"=&r"(addr[6])
+        : [src]"r"((mips_reg)src),          [stride]"r"((mips_reg)stride)
+        : "memory"
+    );
 }
 
-void ff_pred16x16_plane_h264_8_mmi(uint8_t *src, ptrdiff_t stride)
+void ff_pred8x16_vertical_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
-    ff_pred16x16_plane_compat_8_mmi(src, stride, 0, 0);
-}
+    double ftmp[1];
+    uint64_t tmp[1];
 
-void ff_pred8x8_top_dc_8_mmi(uint8_t *src, ptrdiff_t stride)
-{
     __asm__ volatile (
-        "dli $2, 2                          \r\n"
-        "xor $f0, $f0, $f0                  \r\n"
-        "xor $f2, $f2, $f2                  \r\n"
-        "xor $f30, $f30, $f30               \r\n"
-        "negu $3, %[stride]                 \r\n"
-        "daddu $3, $3, %[src]               \r\n"
-        "gsldlc1 $f4, 7($3)                 \r\n"
-        "gsldrc1 $f4, 0($3)                 \r\n"
-        "punpcklbh $f0, $f4, $f30           \r\n"
-        "punpckhbh $f2, $f4, $f30           \r\n"
-        "biadd $f0, $f0                     \r\n"
-        "biadd $f2, $f2                     \r\n"
-        "pshufh $f0, $f0, $f30              \r\n"
-        "pshufh $f2, $f2, $f30              \r\n"
-        "dmtc1 $2, $f4                      \r\n"
-        "pshufh $f4, $f4, $f30              \r\n"
-        "paddush $f0, $f0, $f4              \r\n"
-        "paddush $f2, $f2, $f4              \r\n"
-        "dmtc1 $2, $f4                      \r\n"
-        "psrlh $f0, $f0, $f4                \r\n"
-        "psrlh $f2, $f2, $f4                \r\n"
-        "packushb $f4, $f0, $f2             \r\n"
-        "dli $2, 8                          \r\n"
-        "1:                                 \r\n"
-        "gssdlc1 $f4, 7(%[src])             \r\n"
-        "gssdrc1 $f4, 0(%[src])             \r\n"
-        "daddu %[src], %0, %[stride]        \r\n"
-        "daddiu $2, $2, -1                  \r\n"
-        "bnez $2, 1b                        \r\n"
-        ::[src]"r"(src),[stride]"r"(stride)
-        : "$2","$3","$f0","$f2","$f4","$f30"
+        "gsldlc1    %[ftmp0],   0x07(%[srcA])                           \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[srcA])                           \n\t"
+        "dli        %[tmp0],    0x04                                    \n\t"
+        "1:                                                             \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[stride]               \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),
+          [tmp0]"=&r"(tmp[0]),
+          [src]"+&r"(src)
+        : [stride]"r"((mips_reg)stride),    [srcA]"r"((mips_reg)(src-stride))
+        : "memory"
     );
 }
 
-void ff_pred8x8_dc_8_mmi(uint8_t *src, ptrdiff_t stride)
+void ff_pred8x16_horizontal_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
+    uint64_t tmp[3];
+    mips_reg addr[2];
+
     __asm__ volatile (
-        "negu $2, %[stride]                 \r\n"
-        "daddu $2, $2, %[src]               \r\n"
-        "daddiu $5, $2, 4                   \r\n"
-        "lbu $6, 0($2)                      \r\n"
-        "daddu $3, $0, $6                   \r\n"
-        "daddiu $2, 1                       \r\n"
-        "lbu $6, 0($5)                      \r\n"
-        "daddu $4, $0, $6                   \r\n"
-        "daddiu $5, 1                       \r\n"
-        "lbu $6, 0($2)                      \r\n"
-        "daddu $3, $3, $6                   \r\n"
-        "daddiu $2, 1                       \r\n"
-        "lbu $6, 0($5)                      \r\n"
-        "daddu $4, $4, $6                   \r\n"
-        "daddiu $5, 1                       \r\n"
-        "lbu $6, 0($2)                      \r\n"
-        "daddu $3, $3, $6                   \r\n"
-        "daddiu $2, 1                       \r\n"
-        "lbu $6, 0($5)                      \r\n"
-        "daddu $4, $4, $6                   \r\n"
-        "daddiu $5, 1                       \r\n"
-        "lbu $6, 0($2)                      \r\n"
-        "daddu $3, $3, $6                   \r\n"
-        "daddiu $2, 1                       \r\n"
-        "lbu $6, 0($5)                      \r\n"
-        "daddu $4, $4, $6                   \r\n"
-        "daddiu $5, 1                       \r\n"
-        "dli $6, -1                         \r\n"
-        "daddu $6, $6, %[src]               \r\n"
-        "lbu $5, 0($6)                      \r\n"
-        "daddu $7, $0, $5                   \r\n"
-        "daddu $6, $6, %[stride]            \r\n"
-        "lbu $5, 0($6)                      \r\n"
-        "daddu $7, $7, $5                   \r\n"
-        "daddu $6, $6, %[stride]            \r\n"
-        "lbu $5, 0($6)                      \r\n"
-        "daddu $7, $7, $5                   \r\n"
-        "daddu $6, $6, %[stride]            \r\n"
-        "lbu $5, 0($6)                      \r\n"
-        "daddu $7, $7, $5                   \r\n"
-        "daddu $6, $6, %[stride]            \r\n"
-        "lbu $5, 0($6)                      \r\n"
-        "daddu $8, $0, $5                   \r\n"
-        "daddu $6, $6, %[stride]            \r\n"
-        "lbu $5, 0($6)                      \r\n"
-        "daddu $8, $8, $5                   \r\n"
-        "daddu $6, $6, %[stride]            \r\n"
-        "lbu $5, 0($6)                      \r\n"
-        "daddu $8, $8, $5                   \r\n"
-        "daddu $6, $6, %[stride]            \r\n"
-        "lbu $5, 0($6)                      \r\n"
-        "daddu $8, $8, $5                   \r\n"
-        "daddu $3, $3, $7                   \r\n"
-        "daddiu $3, $3, 4                   \r\n"
-        "daddiu $4, $4, 2                   \r\n"
-        "daddiu $5, $8, 2                   \r\n"
-        "daddu $6, $4, $5                   \r\n"
-        "dsrl $3, 3                         \r\n"
-        "dsrl $4, 2                         \r\n"
-        "dsrl $5, 2                         \r\n"
-        "dsrl $6, 3                         \r\n"
-        "xor $f30, $f30, $f30               \r\n"
-        "dmtc1 $3, $f0                      \r\n"
-        "pshufh $f0, $f0, $f30              \r\n"
-        "dmtc1 $4, $f2                      \r\n"
-        "pshufh $f2, $f2, $f30              \r\n"
-        "dmtc1 $5, $f4                      \r\n"
-        "pshufh $f4, $f4, $f30              \r\n"
-        "dmtc1 $6, $f6                      \r\n"
-        "pshufh $f6, $f6, $f30              \r\n"
-        "packushb $f0, $f0, $f2             \r\n"
-        "packushb $f2, $f4, $f6             \r\n"
-        "daddu $2, $0, %[src]               \r\n"
-        "sdc1 $f0, 0($2)                    \r\n"
-        "daddu $2, $2, %[stride]            \r\n"
-        "sdc1 $f0, 0($2)                    \r\n"
-        "daddu $2, $2, %[stride]            \r\n"
-        "sdc1 $f0, 0($2)                    \r\n"
-        "daddu $2, $2, %[stride]            \r\n"
-        "sdc1 $f0, 0($2)                    \r\n"
-        "daddu $2, $2, %[stride]            \r\n"
-        "sdc1 $f2, 0($2)                    \r\n"
-        "daddu $2, $2, %[stride]            \r\n"
-        "sdc1 $f2, 0($2)                    \r\n"
-        "daddu $2, $2, %[stride]            \r\n"
-        "sdc1 $f2, 0($2)                    \r\n"
-        "daddu $2, $2, %[stride]            \r\n"
-        "sdc1 $f2, 0($2)                    \r\n"
-        ::[src]"r"(src),[stride]"r"(stride)
-        : "$2","$3","$4","$5","$6","$7","$8","$f0","$f2","$f4","$f6","$f30"
+        PTR_ADDI   "%[addr0],   %[src],         -0x01                   \n\t"
+        PTR_ADDU   "%[addr1],   %[src],         $0                      \n\t"
+        "dli        %[tmp0],    0x08                                    \n\t"
+        "1:                                                             \n\t"
+        "lbu        %[tmp1],    0x00(%[addr0])                          \n\t"
+        "dmul       %[tmp2],    %[tmp1],        %[ff_pb_1]              \n\t"
+        "swl        %[tmp2],    0x07(%[addr1])                          \n\t"
+        "swr        %[tmp2],    0x00(%[addr1])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[stride]               \n\t"
+        "lbu        %[tmp1],    0x00(%[addr0])                          \n\t"
+        "dmul       %[tmp2],    %[tmp1],        %[ff_pb_1]              \n\t"
+        "swl        %[tmp2],    0x07(%[addr1])                          \n\t"
+        "swr        %[tmp2],    0x00(%[addr1])                          \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr1],   %[addr1],       %[stride]               \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [tmp2]"=&r"(tmp[2]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1])
+        : [src]"r"((mips_reg)src),          [stride]"r"((mips_reg)stride),
+          [ff_pb_1]"r"(ff_pb_1)
+        : "memory"
     );
 }
 
-void ff_pred8x16_vertical_8_mmi(uint8_t *src, ptrdiff_t stride)
+static inline void pred16x16_plane_compat_mmi(uint8_t *src, int stride,
+        const int svq3, const int rv40)
 {
-    __asm__ volatile (
-        "gsldlc1 $f2, 7(%[srcA])            \r\n"
-        "gsldrc1 $f2, 0(%[srcA])            \r\n"
-        "dli $8, 16                         \r\n"
-        "1:                                 \r\n"
-        "gssdlc1 $f2, 7(%[src])             \r\n"
-        "gssdrc1 $f2, 0(%[src])             \r\n"
-        "daddu %[src], %[src], %[stride]    \r\n"
-        "daddi $8, $8, -1                   \r\n"
-        "bnez $8, 1b                        \r\n"
-        : [src]"+&r"(src)
-        : [stride]"r"(stride),[srcA]"r"(src-stride)
-        : "$8","$f2"
+    double ftmp[11];
+    uint64_t tmp[7];
+    mips_reg addr[1];
+
+    __asm__ volatile(
+        PTR_SUBU   "%[addr0],   %[src],         %[stride]               \n\t"
+        "dli        %[tmp2],    0x20                                    \n\t"
+        "dmtc1      %[tmp2],    %[ftmp4]                                \n\t"
+        "gsldlc1    %[ftmp0],   0x06(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x0f(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp0],   -0x01(%[addr0])                         \n\t"
+        "gsldrc1    %[ftmp2],   0x08(%[addr0])                          \n\t"
+        "dsrl       %[ftmp1],   %[ftmp0],       %[ftmp4]                \n\t"
+        "dsrl       %[ftmp3],   %[ftmp2],       %[ftmp4]                \n\t"
+        "xor        %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp4]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "pmullh     %[ftmp0],   %[ftmp0],       %[ff_pw_m8tom5]         \n\t"
+        "pmullh     %[ftmp1],   %[ftmp1],       %[ff_pw_m4tom1]         \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[ff_pw_1to4]           \n\t"
+        "pmullh     %[ftmp3],   %[ftmp3],       %[ff_pw_5to8]           \n\t"
+        "paddsh     %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "paddsh     %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "dli        %[tmp2],    0x0e                                    \n\t"
+        "dmtc1      %[tmp2],    %[ftmp4]                                \n\t"
+        "pshufh     %[ftmp1],   %[ftmp0],       %[ftmp4]                \n\t"
+        "paddsh     %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "dli        %[tmp2],    0x01                                    \n\t"
+        "dmtc1      %[tmp2],    %[ftmp4]                                \n\t"
+        "pshufh     %[ftmp1],   %[ftmp0],       %[ftmp4]                \n\t"
+        "paddsh     %[ftmp5],   %[ftmp0],       %[ftmp1]                \n\t"
+
+        PTR_ADDIU  "%[addr0],   %[src],         -0x01                   \n\t"
+        PTR_SUBU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp2],    0x00(%[addr0])                          \n\t"
+        "lbu        %[tmp6],    0x10(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp3],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp4],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp5],    0x00(%[addr0])                          \n\t"
+        "dsll       %[tmp3],    %[tmp3],        0x10                    \n\t"
+        "dsll       %[tmp4],    %[tmp4],        0x20                    \n\t"
+        "dsll       %[tmp5],    %[tmp5],        0x30                    \n\t"
+        "or         %[tmp4],    %[tmp4],        %[tmp5]                 \n\t"
+        "or         %[tmp2],    %[tmp2],        %[tmp3]                 \n\t"
+        "or         %[tmp2],    %[tmp2],        %[tmp4]                 \n\t"
+        "dmtc1      %[tmp2],    %[ftmp0]                                \n\t"
+
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp2],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp3],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp4],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp5],    0x00(%[addr0])                          \n\t"
+        "dsll       %[tmp3],    %[tmp3],        0x10                    \n\t"
+        "dsll       %[tmp4],    %[tmp4],        0x20                    \n\t"
+        "dsll       %[tmp5],    %[tmp5],        0x30                    \n\t"
+        "or         %[tmp4],    %[tmp4],        %[tmp5]                 \n\t"
+        "or         %[tmp2],    %[tmp2],        %[tmp3]                 \n\t"
+        "or         %[tmp2],    %[tmp2],        %[tmp4]                 \n\t"
+        "dmtc1      %[tmp2],    %[ftmp1]                                \n\t"
+
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp2],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp3],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp4],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp5],    0x00(%[addr0])                          \n\t"
+        "dsll       %[tmp3],    %[tmp3],        0x10                    \n\t"
+        "dsll       %[tmp4],    %[tmp4],        0x20                    \n\t"
+        "dsll       %[tmp5],    %[tmp5],        0x30                    \n\t"
+        "or         %[tmp4],    %[tmp4],        %[tmp5]                 \n\t"
+        "or         %[tmp2],    %[tmp2],        %[tmp3]                 \n\t"
+        "or         %[tmp2],    %[tmp2],        %[tmp4]                 \n\t"
+        "dmtc1      %[tmp2],    %[ftmp2]                                \n\t"
+
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp2],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp3],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp4],    0x00(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "lbu        %[tmp5],    0x00(%[addr0])                          \n\t"
+        "daddu      %[tmp6],    %[tmp6],        %[tmp5]                 \n\t"
+        "daddiu     %[tmp6],    %[tmp6],        0x01                    \n\t"
+        "dsll       %[tmp6],    %[tmp6],        0x04                    \n\t"
+
+        "dsll       %[tmp3],    %[tmp3],        0x10                    \n\t"
+        "dsll       %[tmp4],    %[tmp4],        0x20                    \n\t"
+        "dsll       %[tmp5],    %[tmp5],        0x30                    \n\t"
+        "or         %[tmp4],    %[tmp4],        %[tmp5]                 \n\t"
+        "or         %[tmp2],    %[tmp2],        %[tmp3]                 \n\t"
+        "or         %[tmp2],    %[tmp2],        %[tmp4]                 \n\t"
+        "dmtc1      %[tmp2],    %[ftmp3]                                \n\t"
+
+        "pmullh     %[ftmp0],   %[ftmp0],       %[ff_pw_m8tom5]         \n\t"
+        "pmullh     %[ftmp1],   %[ftmp1],       %[ff_pw_m4tom1]         \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[ff_pw_1to4]           \n\t"
+        "pmullh     %[ftmp3],   %[ftmp3],       %[ff_pw_5to8]           \n\t"
+        "paddsh     %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "paddsh     %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "paddsh     %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "dli        %[tmp2],    0x0e                                    \n\t"
+        "dmtc1      %[tmp2],    %[ftmp4]                                \n\t"
+        "pshufh     %[ftmp1],   %[ftmp0],       %[ftmp4]                \n\t"
+        "paddsh     %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+
+        "dli        %[tmp2],    0x01                                    \n\t"
+        "dmtc1      %[tmp2],    %[ftmp4]                                \n\t"
+        "pshufh     %[ftmp1],   %[ftmp0],       %[ftmp4]                \n\t"
+        "paddsh     %[ftmp6],   %[ftmp0],       %[ftmp1]                \n\t"
+
+        "dmfc1      %[tmp0],    %[ftmp5]                                \n\t"
+        "dsll       %[tmp0],    %[tmp0],        0x30                    \n\t"
+        "dsra       %[tmp0],    %[tmp0],        0x30                    \n\t"
+        "dmfc1      %[tmp1],    %[ftmp6]                                \n\t"
+        "dsll       %[tmp1],    %[tmp1],        0x30                    \n\t"
+        "dsra       %[tmp1],    %[tmp1],        0x30                    \n\t"
+
+        "beqz       %[svq3],    1f                                      \n\t"
+        "dli        %[tmp2],    0x04                                    \n\t"
+        "ddiv       %[tmp0],    %[tmp0],        %[tmp2]                 \n\t"
+        "ddiv       %[tmp1],    %[tmp1],        %[tmp2]                 \n\t"
+        "dli        %[tmp2],    0x05                                    \n\t"
+        "dmul       %[tmp0],    %[tmp0],        %[tmp2]                 \n\t"
+        "dmul       %[tmp1],    %[tmp1],        %[tmp2]                 \n\t"
+        "dli        %[tmp2],    0x10                                    \n\t"
+        "ddiv       %[tmp0],    %[tmp0],        %[tmp2]                 \n\t"
+        "ddiv       %[tmp1],    %[tmp1],        %[tmp2]                 \n\t"
+        "daddu      %[tmp2],    %[tmp0],        $0                      \n\t"
+        "daddu      %[tmp0],    %[tmp1],        $0                      \n\t"
+        "daddu      %[tmp1],    %[tmp2],        $0                      \n\t"
+        "b          2f                                                  \n\t"
+
+        "1:                                                             \n\t"
+        "beqz       %[rv40],    1f                                      \n\t"
+        "dsra       %[tmp2],    %[tmp0],        0x02                    \n\t"
+        "daddu      %[tmp0],    %[tmp0],        %[tmp2]                 \n\t"
+        "dsra       %[tmp2],    %[tmp1],        0x02                    \n\t"
+        "daddu      %[tmp1],    %[tmp1],        %[tmp2]                 \n\t"
+        "dsra       %[tmp0],    %[tmp0],        0x04                    \n\t"
+        "dsra       %[tmp1],    %[tmp1],        0x04                    \n\t"
+        "b          2f                                                  \n\t"
+
+        "1:                                                             \n\t"
+        "dli        %[tmp2],    0x05                                    \n\t"
+        "dmul       %[tmp0],    %[tmp0],        %[tmp2]                 \n\t"
+        "dmul       %[tmp1],    %[tmp1],        %[tmp2]                 \n\t"
+        "daddiu     %[tmp0],    %[tmp0],        0x20                    \n\t"
+        "daddiu     %[tmp1],    %[tmp1],        0x20                    \n\t"
+        "dsra       %[tmp0],    %[tmp0],        0x06                    \n\t"
+        "dsra       %[tmp1],    %[tmp1],        0x06                    \n\t"
+
+        "2:                                                             \n\t"
+        "daddu      %[tmp3],    %[tmp0],        %[tmp1]                 \n\t"
+        "dli        %[tmp2],    0x07                                    \n\t"
+        "dmul       %[tmp3],    %[tmp3],        %[tmp2]                 \n\t"
+        "dsubu      %[tmp6],    %[tmp6],        %[tmp3]                 \n\t"
+
+        "xor        %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        "dmtc1      %[tmp0],    %[ftmp0]                                \n\t"
+        "pshufh     %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "dmtc1      %[tmp1],    %[ftmp5]                                \n\t"
+        "pshufh     %[ftmp5],   %[ftmp5],       %[ftmp4]                \n\t"
+        "dmtc1      %[tmp6],    %[ftmp6]                                \n\t"
+        "pshufh     %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+        "dli        %[tmp2],    0x05                                    \n\t"
+        "dmtc1      %[tmp2],    %[ftmp7]                                \n\t"
+        "pmullh     %[ftmp1],   %[ff_pw_0to3],  %[ftmp0]                \n\t"
+        "dmtc1      %[ff_pw_4to7],              %[ftmp2]                \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "dmtc1      %[ff_pw_8tob],              %[ftmp3]                \n\t"
+        "pmullh     %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "dmtc1      %[ff_pw_ctof],              %[ftmp4]                \n\t"
+        "pmullh     %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+
+        "dli        %[tmp0],    0x10                                    \n\t"
+        PTR_ADDU   "%[addr0],   %[src],         $0                      \n\t"
+        "1:                                                             \n\t"
+        "paddsh     %[ftmp8],   %[ftmp1],       %[ftmp6]                \n\t"
+        "psrah      %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp2],       %[ftmp6]                \n\t"
+        "psrah      %[ftmp9],   %[ftmp9],       %[ftmp7]                \n\t"
+        "packushb   %[ftmp0],   %[ftmp8],       %[ftmp9]                \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[addr0])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[addr0])                          \n\t"
+
+        "paddsh     %[ftmp8],   %[ftmp3],       %[ftmp6]                \n\t"
+        "psrah      %[ftmp8],   %[ftmp8],       %[ftmp7]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp4],       %[ftmp6]                \n\t"
+        "psrah      %[ftmp9],   %[ftmp9],       %[ftmp7]                \n\t"
+        "packushb   %[ftmp0],   %[ftmp8],       %[ftmp9]                \n\t"
+        "gssdlc1    %[ftmp0],   0x0f(%[addr0])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x08(%[addr0])                          \n\t"
+
+        "paddsh     %[ftmp6],   %[ftmp6],       %[ftmp5]                \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[stride]               \n\t"
+        "daddiu     %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [tmp2]"=&r"(tmp[2]),              [tmp3]"=&r"(tmp[3]),
+          [tmp4]"=&r"(tmp[4]),              [tmp5]"=&r"(tmp[5]),
+          [tmp6]"=&r"(tmp[6]),
+          [addr0]"=&r"(addr[0])
+        : [src]"r"(src),                    [stride]"r"((mips_reg)stride),
+          [svq3]"r"(svq3),                  [rv40]"r"(rv40),
+          [ff_pw_m8tom5]"f"(ff_pw_m8tom5),  [ff_pw_m4tom1]"f"(ff_pw_m4tom1),
+          [ff_pw_1to4]"f"(ff_pw_1to4),      [ff_pw_5to8]"f"(ff_pw_5to8),
+          [ff_pw_0to3]"f"(ff_pw_0to3),      [ff_pw_4to7]"r"(ff_pw_4to7),
+          [ff_pw_8tob]"r"(ff_pw_8tob),      [ff_pw_ctof]"r"(ff_pw_ctof)
+        : "memory"
     );
 }
 
-void ff_pred8x16_horizontal_8_mmi(uint8_t *src, ptrdiff_t stride)
+void ff_pred16x16_plane_h264_8_mmi(uint8_t *src, ptrdiff_t stride)
 {
-    __asm__ volatile (
-        "daddiu $2, %[src], -1              \r\n"
-        "daddu $3, %[src], $0               \r\n"
-        "dli $6, 0x10                       \r\n"
-        "1:                                 \r\n"
-        "lbu $4, 0($2)                      \r\n"
-        "dmul $5, $4, %[ff_pb_1]            \r\n"
-        "sdl $5, 7($3)                      \r\n"
-        "sdr $5, 0($3)                      \r\n"
-        "daddu $2, %[stride]                \r\n"
-        "daddu $3, %[stride]                \r\n"
-        "daddiu $6, -1                      \r\n"
-        "bnez $6, 1b                        \r\n"
-        ::[src]"r"(src),[stride]"r"(stride),[ff_pb_1]"r"(ff_pb_1)
-        : "$2","$3","$4","$5","$6"
-    );
+    pred16x16_plane_compat_mmi(src, stride, 0, 0);
+}
+
+void ff_pred16x16_plane_svq3_8_mmi(uint8_t *src, ptrdiff_t stride)
+{
+    pred16x16_plane_compat_mmi(src, stride, 1, 0);
+}
+
+void ff_pred16x16_plane_rv40_8_mmi(uint8_t *src, ptrdiff_t stride)
+{
+    pred16x16_plane_compat_mmi(src, stride, 0, 1);
 }
diff --git a/libavcodec/mips/h264qpel_mmi.c b/libavcodec/mips/h264qpel_mmi.c
index e04a2d5..b4e83e4 100644
--- a/libavcodec/mips/h264qpel_mmi.c
+++ b/libavcodec/mips/h264qpel_mmi.c
@@ -22,421 +22,225 @@
  */
 
 #include "h264dsp_mips.h"
+#include "hpeldsp_mips.h"
 #include "libavcodec/bit_depth_template.c"
+#include "libavutil/mips/asmdefs.h"
 
 static inline void copy_block4_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride, int h)
 {
+    double ftmp[1];
+    uint64_t low32;
+
     __asm__ volatile (
-        "1:                                     \r\n"
-        "gslwlc1 $f2, 3(%[src])                 \r\n"
-        "gslwrc1 $f2, 0(%[src])                 \r\n"
-        "gsswlc1 $f2, 3(%[dst])                 \r\n"
-        "gsswrc1 $f2, 0(%[dst])                 \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "dadd %[dst], %[dst], %[dstStride]      \r\n"
-        "daddi %[h], %[h], -1                   \r\n"
-        "bnez %[h], 1b                          \r\n"
-        : [dst]"+&r"(dst),[src]"+&r"(src)
-        : [dstStride]"r"(dstStride),[srcStride]"r"(srcStride),[h]"r"(h)
-        : "$f2"
+        "1:                                                             \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        "gsswlc1    %[ftmp0],   0x03(%[dst])                            \n\t"
+        "gsswrc1    %[ftmp0],   0x00(%[dst])                            \n\t"
+        "addi       %[h],       %[h],           -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),
+          [dst]"+&r"(dst),                  [src]"+&r"(src),
+          [h]"+&r"(h),
+          [low32]"=&r"(low32)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [srcStride]"r"((mips_reg)srcStride)
+        : "memory"
     );
 }
 
 static inline void copy_block8_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride, int h)
 {
+    double ftmp[1];
+
     __asm__ volatile (
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 7(%[src])                 \r\n"
-        "gsldrc1 $f2, 0(%[src])                 \r\n"
-        "gssdlc1 $f2, 7(%[dst])                 \r\n"
-        "gssdrc1 $f2, 0(%[dst])                 \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "dadd %[dst], %[dst], %[dstStride]      \r\n"
-        "daddi %[h], %[h], -1                   \r\n"
-        "bnez %[h], 1b                          \r\n"
-        : [dst]"+&r"(dst),[src]"+&r"(src)
-        : [dstStride]"r"(dstStride),[srcStride]"r"(srcStride),[h]"r"(h)
-        : "$f2"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[dst])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[dst])                            \n\t"
+        "addi       %[h],       %[h],           -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),
+          [dst]"+&r"(dst),                  [src]"+&r"(src),
+          [h]"+&r"(h)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [srcStride]"r"((mips_reg)srcStride)
+        : "memory"
     );
 }
 
 static inline void copy_block16_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride, int h)
 {
-    __asm__ volatile (
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 7(%[src])                 \r\n"
-        "gsldrc1 $f2, 0(%[src])                 \r\n"
-        "gsldlc1 $f4, 15(%[src])                \r\n"
-        "gsldrc1 $f4, 8(%[src])                 \r\n"
-        "gssdlc1 $f2, 7(%[dst])                 \r\n"
-        "gssdrc1 $f2, 0(%[dst])                 \r\n"
-        "gssdlc1 $f4, 15(%[dst])                \r\n"
-        "gssdrc1 $f4, 8(%[dst])                 \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "dadd %[dst], %[dst], %[dstStride]      \r\n"
-        "daddi %[h], %[h], -1                   \r\n"
-        "bnez %[h], 1b                          \r\n"
-        : [dst]"+&r"(dst),[src]"+&r"(src)
-        : [dstStride]"r"(dstStride),[srcStride]"r"(srcStride),[h]"r"(h)
-        : "$f2","$f4"
-    );
-}
+    double ftmp[1];
+    uint64_t tmp[1];
 
-#define op_put(a, b) a = b
-#define op_avg(a, b) a = rnd_avg_pixel4(a, b)
-static inline void put_pixels4_mmi(uint8_t *block, const uint8_t *pixels,
-        ptrdiff_t line_size, int h)
-{
     __asm__ volatile (
-        "1:                                     \r\n"
-        "gslwlc1 $f2, 3(%[pixels])              \r\n"
-        "gslwrc1 $f2, 0(%[pixels])              \r\n"
-        "gsswlc1 $f2, 3(%[block])               \r\n"
-        "gsswrc1 $f2, 0(%[block])               \r\n"
-        "dadd %[pixels], %[pixels], %[line_size]\r\n"
-        "dadd %[block], %[block], %[line_size]  \r\n"
-        "daddi %[h], %[h], -1                   \r\n"
-        "bnez %[h], 1b                          \r\n"
-        : [block]"+&r"(block),[pixels]"+&r"(pixels)
-        : [line_size]"r"(line_size),[h]"r"(h)
-        : "$f2"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[src])                            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src])                            \n\t"
+        "ldl        %[tmp0],    0x0f(%[src])                            \n\t"
+        "ldr        %[tmp0],    0x08(%[src])                            \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[dst])                            \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[dst])                            \n\t"
+        "sdl        %[tmp0],    0x0f(%[dst])                            \n\t"
+        "sdr        %[tmp0],    0x08(%[dst])                            \n\t"
+        "addi       %[h],       %[h],           -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),
+          [tmp0]"=&r"(tmp[0]),
+          [dst]"+&r"(dst),                  [src]"+&r"(src),
+          [h]"+&r"(h)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [srcStride]"r"((mips_reg)srcStride)
+        : "memory"
     );
 }
 
-static inline void put_pixels8_mmi(uint8_t *block, const uint8_t *pixels,
-        ptrdiff_t line_size, int h)
-{
-    __asm__ volatile (
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 7(%[pixels])              \r\n"
-        "gsldrc1 $f2, 0(%[pixels])              \r\n"
-        "gssdlc1 $f2, 7(%[block])               \r\n"
-        "gssdrc1 $f2, 0(%[block])               \r\n"
-        "dadd %[pixels], %[pixels], %[line_size]\r\n"
-        "dadd %[block], %[block], %[line_size]  \r\n"
-        "daddi %[h], %[h], -1                   \r\n"
-        "bnez %[h], 1b                          \r\n"
-        : [block]"+&r"(block),[pixels]"+&r"(pixels)
-        : [line_size]"r"(line_size),[h]"r"(h)
-        : "$f2"
-    );
-}
-
-static inline void put_pixels16_mmi(uint8_t *block, const uint8_t *pixels,
-        ptrdiff_t line_size, int h)
-{
-    __asm__ volatile (
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 7(%[pixels])              \r\n"
-        "gsldrc1 $f2, 0(%[pixels])              \r\n"
-        "gsldlc1 $f4, 15(%[pixels])             \r\n"
-        "gsldrc1 $f4, 8(%[pixels])              \r\n"
-        "gssdlc1 $f2, 7(%[block])               \r\n"
-        "gssdrc1 $f2, 0(%[block])               \r\n"
-        "gssdlc1 $f4, 15(%[block])              \r\n"
-        "gssdrc1 $f4, 8(%[block])               \r\n"
-        "dadd %[pixels], %[pixels], %[line_size]\r\n"
-        "dadd %[block], %[block], %[line_size]  \r\n"
-        "daddi %[h], %[h], -1                   \r\n"
-        "bnez %[h], 1b                          \r\n"
-        : [block]"+&r"(block),[pixels]"+&r"(pixels)
-        : [line_size]"r"(line_size),[h]"r"(h)
-        : "$f2","$f4"
-    );
-}
-
-static inline void avg_pixels4_mmi(uint8_t *block, const uint8_t *pixels,
-        ptrdiff_t line_size, int h)
-{
-    __asm__ volatile (
-        "1:                                     \r\n"
-        "gslwlc1 $f2, 3(%[pixels])              \r\n"
-        "gslwrc1 $f2, 0(%[pixels])              \r\n"
-        "gslwlc1 $f4, 3(%[block])               \r\n"
-        "gslwrc1 $f4, 0(%[block])               \r\n"
-        "pavgb $f2, $f2, $f4                    \r\n"
-        "gsswlc1 $f2, 3(%[block])               \r\n"
-        "gsswrc1 $f2, 0(%[block])               \r\n"
-        "dadd %[pixels], %[pixels], %[line_size]\r\n"
-        "dadd %[block], %[block], %[line_size]  \r\n"
-        "daddi %[h], %[h], -1                   \r\n"
-        "bnez %[h], 1b                          \r\n"
-        : [block]"+&r"(block),[pixels]"+&r"(pixels)
-        : [line_size]"r"(line_size),[h]"r"(h)
-        : "$f2","$f4"
-    );
-}
-
-static inline void avg_pixels8_mmi(uint8_t *block, const uint8_t *pixels,
-        ptrdiff_t line_size, int h)
-{
-    __asm__ volatile (
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 7(%[block])               \r\n"
-        "gsldrc1 $f2, 0(%[block])               \r\n"
-        "gsldlc1 $f4, 7(%[pixels])              \r\n"
-        "gsldrc1 $f4, 0(%[pixels])              \r\n"
-        "pavgb $f2, $f2, $f4                    \r\n"
-        "gssdlc1 $f2, 7(%[block])               \r\n"
-        "gssdrc1 $f2, 0(%[block])               \r\n"
-        "dadd %[pixels], %[pixels], %[line_size]\r\n"
-        "dadd %[block], %[block], %[line_size]  \r\n"
-        "daddi %[h], %[h], -1                   \r\n"
-        "bnez %[h], 1b                          \r\n"
-        : [block]"+&r"(block),[pixels]"+&r"(pixels)
-        : [line_size]"r"(line_size),[h]"r"(h)
-        : "$f2","$f4"
-    );
-}
-
-static inline void avg_pixels16_mmi(uint8_t *block, const uint8_t *pixels,
-        ptrdiff_t line_size, int h)
-{
-    __asm__ volatile (
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 7(%[block])               \r\n"
-        "gsldrc1 $f2, 0(%[block])               \r\n"
-        "gsldlc1 $f4, 15(%[block])              \r\n"
-        "gsldrc1 $f4, 8(%[block])               \r\n"
-        "gsldlc1 $f6, 7(%[pixels])              \r\n"
-        "gsldrc1 $f6, 0(%[pixels])              \r\n"
-        "gsldlc1 $f8, 15(%[pixels])             \r\n"
-        "gsldrc1 $f8, 8(%[pixels])              \r\n"
-        "pavgb $f2, $f2, $f6                    \r\n"
-        "pavgb $f4, $f4, $f8                    \r\n"
-        "gssdlc1 $f2, 7(%[block])               \r\n"
-        "gssdrc1 $f2, 0(%[block])               \r\n"
-        "gssdlc1 $f4, 15(%[block])              \r\n"
-        "gssdrc1 $f4, 8(%[block])               \r\n"
-        "dadd %[pixels], %[pixels], %[line_size]\r\n"
-        "dadd %[block], %[block], %[line_size]  \r\n"
-        "daddi %[h], %[h], -1                   \r\n"
-        "bnez %[h], 1b                          \r\n"
-        : [block]"+&r"(block),[pixels]"+&r"(pixels)
-        : [line_size]"r"(line_size),[h]"r"(h)
-        : "$f2","$f4","$f6","$f8"
-    );
-}
-
-static inline void put_pixels4_l2_mmi(uint8_t *dst, const uint8_t *src1,
-        const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
-        int h)
-{
-    int i;
-    for (i = 0; i < h; i++) {
-        pixel4 a, b;
-        a = AV_RN4P(&src1[i * src_stride1]);
-        b = AV_RN4P(&src2[i * src_stride2]);
-        op_put(*((pixel4 *) &dst[i * dst_stride]), rnd_avg_pixel4(a, b));
-    }
-}
-
-static inline void put_pixels8_l2_mmi(uint8_t *dst, const uint8_t *src1,
-        const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
-        int h)
-{
-    int i;
-    for (i = 0; i < h; i++) {
-        pixel4 a, b;
-        a = AV_RN4P(&src1[i * src_stride1]);
-        b = AV_RN4P(&src2[i * src_stride2]);
-        op_put(*((pixel4 *) &dst[i * dst_stride]), rnd_avg_pixel4(a, b));
-        a = AV_RN4P(&src1[i * src_stride1 + 4]);
-        b = AV_RN4P(&src2[i * src_stride2 + 4]);
-        op_put(*((pixel4 *) &dst[i * dst_stride + 4]), rnd_avg_pixel4(a, b));
-    }
-}
-
-static inline void put_pixels16_l2_mmi(uint8_t *dst, const uint8_t *src1,
-        const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
-        int h)
-{
-    int i;
-    for (i = 0; i < h; i++) {
-        pixel4 a, b;
-        a = AV_RN4P(&src1[i * src_stride1]);
-        b = AV_RN4P(&src2[i * src_stride2]);
-        op_put(*((pixel4 *) &dst[i * dst_stride]), rnd_avg_pixel4(a, b));
-        a = AV_RN4P(&src1[i * src_stride1 + 4]);
-        b = AV_RN4P(&src2[i * src_stride2 + 4]);
-        op_put(*((pixel4 *) &dst[i * dst_stride + 4]), rnd_avg_pixel4(a, b));
-        a = AV_RN4P(&src1[i * src_stride1 + 8]);
-        b = AV_RN4P(&src2[i * src_stride2 + 8]);
-        op_put(*((pixel4 *) &dst[i * dst_stride + 8]), rnd_avg_pixel4(a, b));
-        a = AV_RN4P(&src1[i * src_stride1 + 12]);
-        b = AV_RN4P(&src2[i * src_stride2 + 12]);
-        op_put(*((pixel4 *) &dst[i * dst_stride + 12]), rnd_avg_pixel4(a, b));
-    }
-}
-
-static inline void avg_pixels4_l2_mmi(uint8_t *dst, const uint8_t *src1,
-        const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
-        int h)
-{
-    int i;
-    for (i = 0; i < h; i++) {
-        pixel4 a, b;
-        a = AV_RN4P(&src1[i * src_stride1]);
-        b = AV_RN4P(&src2[i * src_stride2]);
-        op_avg(*((pixel4 *) &dst[i * dst_stride]), rnd_avg_pixel4(a, b));
-    }
-}
-
-static inline void avg_pixels8_l2_mmi(uint8_t *dst, const uint8_t *src1,
-        const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
-        int h)
-{
-    int i;
-    for (i = 0; i < h; i++) {
-        pixel4 a, b;
-        a = AV_RN4P(&src1[i * src_stride1]);
-        b = AV_RN4P(&src2[i * src_stride2]);
-        op_avg(*((pixel4 *) &dst[i * dst_stride]), rnd_avg_pixel4(a, b));
-        a = AV_RN4P(&src1[i * src_stride1 + 4]);
-        b = AV_RN4P(&src2[i * src_stride2 + 4]);
-        op_avg(*((pixel4 *) &dst[i * dst_stride + 4]), rnd_avg_pixel4(a, b));
-    }
-}
-
-static inline void avg_pixels16_l2_mmi(uint8_t *dst, const uint8_t *src1,
-        const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
-        int h)
-{
-    int i;
-    for (i = 0; i < h; i++) {
-        pixel4 a, b;
-        a = AV_RN4P(&src1[i * src_stride1]);
-        b = AV_RN4P(&src2[i * src_stride2]);
-        op_avg(*((pixel4 *) &dst[i * dst_stride]), rnd_avg_pixel4(a, b));
-        a = AV_RN4P(&src1[i * src_stride1 + 4]);
-        b = AV_RN4P(&src2[i * src_stride2 + 4]);
-        op_avg(*((pixel4 *) &dst[i * dst_stride + 4]), rnd_avg_pixel4(a, b));
-        a = AV_RN4P(&src1[i * src_stride1 + 8]);
-        b = AV_RN4P(&src2[i * src_stride2 + 8]);
-        op_avg(*((pixel4 *) &dst[i * dst_stride + 8]), rnd_avg_pixel4(a, b));
-        a = AV_RN4P(&src1[i * src_stride1 + 12]);
-        b = AV_RN4P(&src2[i * src_stride2 + 12]);
-        op_avg(*((pixel4 *) &dst[i * dst_stride + 12]), rnd_avg_pixel4(a, b));
-
-    }
-}
-#undef op_put
-#undef op_avg
-
 #define op2_avg(a, b)  a = (((a)+CLIP(((b) + 512)>>10)+1)>>1)
 #define op2_put(a, b)  a = CLIP(((b) + 512)>>10)
 static void put_h264_qpel4_h_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
+    double ftmp[10];
+    uint64_t tmp[1];
+    uint64_t low32;
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "dli $8, 4                              \r\n"
-        "1:                                     \r\n"
-        "gslwlc1 $f2, 1(%[src])                 \r\n"
-        "gslwrc1 $f2, -2(%[src])                \r\n"
-        "gslwlc1 $f4, 2(%[src])                 \r\n"
-        "gslwrc1 $f4, -1(%[src])                \r\n"
-        "gslwlc1 $f6, 3(%[src])                 \r\n"
-        "gslwrc1 $f6, 0(%[src])                 \r\n"
-        "gslwlc1 $f8, 4(%[src])                 \r\n"
-        "gslwrc1 $f8, 1(%[src])                 \r\n"
-        "gslwlc1 $f10, 5(%[src])                \r\n"
-        "gslwrc1 $f10, 2(%[src])                \r\n"
-        "gslwlc1 $f12, 6(%[src])                \r\n"
-        "gslwrc1 $f12, 3(%[src])                \r\n"
-        "punpcklbh $f2, $f2, $f0                \r\n"
-        "punpcklbh $f4, $f4, $f0                \r\n"
-        "punpcklbh $f6, $f6, $f0                \r\n"
-        "punpcklbh $f8, $f8, $f0                \r\n"
-        "punpcklbh $f10, $f10, $f0              \r\n"
-        "punpcklbh $f12, $f12, $f0              \r\n"
-        "paddsh $f14, $f6, $f8                  \r\n"
-        "paddsh $f16, $f4, $f10                 \r\n"
-        "paddsh $f18, $f2, $f12                 \r\n"
-        "pmullh $f14, $f14, %[ff_pw_20]         \r\n"
-        "pmullh $f16, $f16, %[ff_pw_5]          \r\n"
-        "psubsh $f14, $f14, $f16                \r\n"
-        "paddsh $f18, $f14, $f18                \r\n"
-        "paddsh $f18, $f18, %[ff_pw_16]         \r\n"
-        "psrah $f18, $f18, %[ff_pw_5]           \r\n"
-        "packushb $f18, $f18, $f0               \r\n"
-        "gsswlc1 $f18, 3(%[dst])                \r\n"
-        "gsswrc1 $f18, 0(%[dst])                \r\n"
-        "dadd %[dst], %[dst], %[dstStride]      \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "daddi $8, $8, -1                       \r\n"
-        "bnez $8, 1b                            \r\n"
-        : [dst]"+&r"(dst),[src]"+&r"(src)
-        : [dstStride]"r"(dstStride),[srcStride]"r"(srcStride),
-          [ff_pw_20]"f"(ff_pw_20),[ff_pw_5]"f"(ff_pw_5),[ff_pw_16]"f"(ff_pw_16)
-        : "$8","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dli        %[tmp0],    0x04                                    \n\t"
+        "1:                                                             \n\t"
+        "uld        %[low32],   -0x02(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   -0x01(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "uld        %[low32],   0x01(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        "uld        %[low32],   0x02(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        "uld        %[low32],   0x03(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp7],   %[ftmp3],       %[ftmp4]                \n\t"
+        "paddsh     %[ftmp8],   %[ftmp2],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp1],       %[ftmp6]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ff_pw_20]             \n\t"
+        "pmullh     %[ftmp8],   %[ftmp8],       %[ff_pw_5]              \n\t"
+        "psubsh     %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp9],       %[ff_pw_16]             \n\t"
+        "psrah      %[ftmp9],   %[ftmp9],       %[ff_pw_5]              \n\t"
+        "packushb   %[ftmp9],   %[ftmp9],       %[ftmp0]                \n\t"
+        "gsswlc1    %[ftmp9],   0x03(%[dst])                            \n\t"
+        "gsswrc1    %[ftmp9],   0x00(%[dst])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp[0]),
+          [dst]"+&r"(dst),                  [src]"+&r"(src),
+          [low32]"=&r"(low32)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [srcStride]"r"((mips_reg)srcStride),
+          [ff_pw_20]"f"(ff_pw_20),          [ff_pw_5]"f"(ff_pw_5),
+          [ff_pw_16]"f"(ff_pw_16)
+        : "memory"
     );
 }
 
 static void put_h264_qpel8_h_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
+    double ftmp[11];
+    uint64_t tmp[1];
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "dli $8, 8                              \r\n"
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 5(%[src])                 \r\n"
-        "gsldrc1 $f2, -2(%[src])                \r\n"
-        "gsldlc1 $f4, 6(%[src])                 \r\n"
-        "gsldrc1 $f4, -1(%[src])                \r\n"
-        "gsldlc1 $f6, 7(%[src])                 \r\n"
-        "gsldrc1 $f6, 0(%[src])                 \r\n"
-        "gsldlc1 $f8, 8(%[src])                 \r\n"
-        "gsldrc1 $f8, 1(%[src])                 \r\n"
-        "gsldlc1 $f10, 9(%[src])                \r\n"
-        "gsldrc1 $f10, 2(%[src])                \r\n"
-        "gsldlc1 $f12, 10(%[src])               \r\n"
-        "gsldrc1 $f12, 3(%[src])                \r\n"
-        "punpcklbh $f14, $f6, $f0               \r\n"
-        "punpckhbh $f16, $f6, $f0               \r\n"
-        "punpcklbh $f18, $f8, $f0               \r\n"
-        "punpckhbh $f20, $f8, $f0               \r\n"
-        "paddsh $f6, $f14, $f18                 \r\n"
-        "paddsh $f8, $f16, $f20                 \r\n"
-        "pmullh $f6, $f6, %[ff_pw_20]           \r\n"
-        "pmullh $f8, $f8, %[ff_pw_20]           \r\n"
-        "punpcklbh $f14, $f4, $f0               \r\n"
-        "punpckhbh $f16, $f4, $f0               \r\n"
-        "punpcklbh $f18, $f10, $f0              \r\n"
-        "punpckhbh $f20, $f10, $f0              \r\n"
-        "paddsh $f4, $f14, $f18                 \r\n"
-        "paddsh $f10, $f16, $f20                \r\n"
-        "pmullh $f4, $f4, %[ff_pw_5]            \r\n"
-        "pmullh $f10, $f10, %[ff_pw_5]          \r\n"
-        "punpcklbh $f14, $f2, $f0               \r\n"
-        "punpckhbh $f16, $f2, $f0               \r\n"
-        "punpcklbh $f18, $f12, $f0              \r\n"
-        "punpckhbh $f20, $f12, $f0              \r\n"
-        "paddsh $f2, $f14, $f18                 \r\n"
-        "paddsh $f12, $f16, $f20                \r\n"
-        "psubsh $f6, $f6, $f4                   \r\n"
-        "psubsh $f8, $f8, $f10                  \r\n"
-        "paddsh $f6, $f6, $f2                   \r\n"
-        "paddsh $f8, $f8, $f12                  \r\n"
-        "paddsh $f6, $f6, %[ff_pw_16]           \r\n"
-        "paddsh $f8, $f8, %[ff_pw_16]           \r\n"
-        "psrah $f6, $f6, %[ff_pw_5]             \r\n"
-        "psrah $f8, $f8, %[ff_pw_5]             \r\n"
-        "packushb $f18, $f6, $f8                \r\n"
-        "sdc1 $f18, 0(%[dst])                   \r\n"
-        "dadd %[dst], %[dst], %[dstStride]      \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "daddi $8, $8, -1                       \r\n"
-        "bnez $8, 1b                            \r\n"
-        : [dst]"+&r"(dst),[src]"+&r"(src)
-        : [dstStride]"r"(dstStride),[srcStride]"r"(srcStride),
-          [ff_pw_20]"f"(ff_pw_20),[ff_pw_5]"f"(ff_pw_5),[ff_pw_16]"f"(ff_pw_16)
-        : "$8","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18","$f20"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dli        %[tmp0],    0x08                                    \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp1],   0x05(%[src])                            \n\t"
+        "gsldrc1    %[ftmp1],   -0x02(%[src])                           \n\t"
+        "gsldlc1    %[ftmp2],   0x06(%[src])                            \n\t"
+        "gsldrc1    %[ftmp2],   -0x01(%[src])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[src])                            \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[src])                            \n\t"
+        "gsldlc1    %[ftmp4],   0x08(%[src])                            \n\t"
+        "gsldrc1    %[ftmp4],   0x01(%[src])                            \n\t"
+        "gsldlc1    %[ftmp5],   0x09(%[src])                            \n\t"
+        "gsldrc1    %[ftmp5],   0x02(%[src])                            \n\t"
+        "gsldlc1    %[ftmp6],   0x0a(%[src])                            \n\t"
+        "gsldrc1    %[ftmp6],   0x03(%[src])                            \n\t"
+        "punpcklbh  %[ftmp7],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp8],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp9],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp10],  %[ftmp4],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp3],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddsh     %[ftmp4],   %[ftmp8],       %[ftmp10]               \n\t"
+        "pmullh     %[ftmp3],   %[ftmp3],       %[ff_pw_20]             \n\t"
+        "pmullh     %[ftmp4],   %[ftmp4],       %[ff_pw_20]             \n\t"
+        "punpcklbh  %[ftmp7],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp8],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp9],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp10],  %[ftmp5],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp2],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddsh     %[ftmp5],   %[ftmp8],       %[ftmp10]               \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[ff_pw_5]              \n\t"
+        "pmullh     %[ftmp5],   %[ftmp5],       %[ff_pw_5]              \n\t"
+        "punpcklbh  %[ftmp7],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp8],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp9],   %[ftmp6],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp10],  %[ftmp6],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp1],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddsh     %[ftmp6],   %[ftmp8],       %[ftmp10]               \n\t"
+        "psubsh     %[ftmp3],   %[ftmp3],       %[ftmp2]                \n\t"
+        "psubsh     %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "paddsh     %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "paddsh     %[ftmp3],   %[ftmp3],       %[ff_pw_16]             \n\t"
+        "paddsh     %[ftmp4],   %[ftmp4],       %[ff_pw_16]             \n\t"
+        "psrah      %[ftmp3],   %[ftmp3],       %[ff_pw_5]              \n\t"
+        "psrah      %[ftmp4],   %[ftmp4],       %[ff_pw_5]              \n\t"
+        "packushb   %[ftmp9],   %[ftmp3],       %[ftmp4]                \n\t"
+        "gssdlc1    %[ftmp9],   0x07(%[dst])                            \n\t"
+        "gssdrc1    %[ftmp9],   0x00(%[dst])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),
+          [tmp0]"=&r"(tmp[0]),
+          [dst]"+&r"(dst),                  [src]"+&r"(src)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [srcStride]"r"((mips_reg)srcStride),
+          [ff_pw_20]"f"(ff_pw_20),          [ff_pw_5]"f"(ff_pw_5),
+          [ff_pw_16]"f"(ff_pw_16)
+        : "memory"
     );
 }
 
@@ -454,116 +258,140 @@ static void put_h264_qpel16_h_lowpass_mmi(uint8_t *dst, const uint8_t *src,
 static void avg_h264_qpel4_h_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
+    double ftmp[11];
+    uint64_t tmp[1];
+    uint64_t low32;
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "dli $8, 4                              \r\n"
-        "1:                                     \r\n"
-        "gslwlc1 $f2, 1(%[src])                 \r\n"
-        "gslwrc1 $f2, -2(%[src])                \r\n"
-        "gslwlc1 $f4, 2(%[src])                 \r\n"
-        "gslwrc1 $f4, -1(%[src])                \r\n"
-        "gslwlc1 $f6, 3(%[src])                 \r\n"
-        "gslwrc1 $f6, 0(%[src])                 \r\n"
-        "gslwlc1 $f8, 4(%[src])                 \r\n"
-        "gslwrc1 $f8, 1(%[src])                 \r\n"
-        "gslwlc1 $f10, 5(%[src])                \r\n"
-        "gslwrc1 $f10, 2(%[src])                \r\n"
-        "gslwlc1 $f12, 6(%[src])                \r\n"
-        "gslwrc1 $f12, 3(%[src])                \r\n"
-        "punpcklbh $f2, $f2, $f0                \r\n"
-        "punpcklbh $f4, $f4, $f0                \r\n"
-        "punpcklbh $f6, $f6, $f0                \r\n"
-        "punpcklbh $f8, $f8, $f0                \r\n"
-        "punpcklbh $f10, $f10, $f0              \r\n"
-        "punpcklbh $f12, $f12, $f0              \r\n"
-        "paddsh $f14, $f6, $f8                  \r\n"
-        "paddsh $f16, $f4, $f10                 \r\n"
-        "paddsh $f18, $f2, $f12                 \r\n"
-        "pmullh $f14, $f14, %[ff_pw_20]         \r\n"
-        "pmullh $f16, $f16, %[ff_pw_5]          \r\n"
-        "psubsh $f14, $f14, $f16                \r\n"
-        "paddsh $f18, $f14, $f18                \r\n"
-        "paddsh $f18, $f18, %[ff_pw_16]         \r\n"
-        "psrah $f18, $f18, %[ff_pw_5]           \r\n"
-        "packushb $f18, $f18, $f0               \r\n"
-        "lwc1 $f20, 0(%[dst])                   \r\n"
-        "pavgb $f18, $f18, $f20                 \r\n"
-        "gsswlc1 $f18, 3(%[dst])                \r\n"
-        "gsswrc1 $f18, 0(%[dst])                \r\n"
-        "dadd %[dst], %[dst], %[dstStride]      \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "daddi $8, $8, -1                       \r\n"
-        "bnez $8, 1b                            \r\n"
-        : [dst]"+&r"(dst),[src]"+&r"(src)
-        : [dstStride]"r"(dstStride),[srcStride]"r"(srcStride),
-          [ff_pw_20]"f"(ff_pw_20),[ff_pw_5]"f"(ff_pw_5),[ff_pw_16]"f"(ff_pw_16)
-        : "$8","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18","$f20"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dli        %[tmp0],    0x04                                    \n\t"
+        "1:                                                             \n\t"
+        "uld        %[low32],   -0x02(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   -0x01(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "uld        %[low32],   0x01(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        "uld        %[low32],   0x02(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        "uld        %[low32],   0x03(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp7],   %[ftmp3],       %[ftmp4]                \n\t"
+        "paddsh     %[ftmp8],   %[ftmp2],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp1],       %[ftmp6]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ff_pw_20]             \n\t"
+        "pmullh     %[ftmp8],   %[ftmp8],       %[ff_pw_5]              \n\t"
+        "psubsh     %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp9],       %[ff_pw_16]             \n\t"
+        "psrah      %[ftmp9],   %[ftmp9],       %[ff_pw_5]              \n\t"
+        "packushb   %[ftmp9],   %[ftmp9],       %[ftmp0]                \n\t"
+        "lwc1       %[ftmp10],  0x00(%[dst])                            \n\t"
+        "pavgb      %[ftmp9],   %[ftmp9],       %[ftmp10]               \n\t"
+        "gsswlc1    %[ftmp9],   0x03(%[dst])                            \n\t"
+        "gsswrc1    %[ftmp9],   0x00(%[dst])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),
+          [tmp0]"=&r"(tmp[0]),
+          [dst]"+&r"(dst),                  [src]"+&r"(src),
+          [low32]"=&r"(low32)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [srcStride]"r"((mips_reg)srcStride),
+          [ff_pw_20]"f"(ff_pw_20),          [ff_pw_5]"f"(ff_pw_5),
+          [ff_pw_16]"f"(ff_pw_16)
+        : "memory"
     );
 }
 
 static void avg_h264_qpel8_h_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
+    double ftmp[11];
+    uint64_t tmp[1];
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "dli $8, 8                              \r\n"
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 5(%[src])                 \r\n"
-        "gsldrc1 $f2, -2(%[src])                \r\n"
-        "gsldlc1 $f4, 6(%[src])                 \r\n"
-        "gsldrc1 $f4, -1(%[src])                \r\n"
-        "gsldlc1 $f6, 7(%[src])                 \r\n"
-        "gsldrc1 $f6, 0(%[src])                 \r\n"
-        "gsldlc1 $f8, 8(%[src])                 \r\n"
-        "gsldrc1 $f8, 1(%[src])                 \r\n"
-        "gsldlc1 $f10, 9(%[src])                \r\n"
-        "gsldrc1 $f10, 2(%[src])                \r\n"
-        "gsldlc1 $f12, 10(%[src])               \r\n"
-        "gsldrc1 $f12, 3(%[src])                \r\n"
-        "punpcklbh $f14, $f6, $f0               \r\n"
-        "punpckhbh $f16, $f6, $f0               \r\n"
-        "punpcklbh $f18, $f8, $f0               \r\n"
-        "punpckhbh $f20, $f8, $f0               \r\n"
-        "paddsh $f6, $f14, $f18                 \r\n"
-        "paddsh $f8, $f16, $f20                 \r\n"
-        "pmullh $f6, $f6, %[ff_pw_20]           \r\n"
-        "pmullh $f8, $f8, %[ff_pw_20]           \r\n"
-        "punpcklbh $f14, $f4, $f0               \r\n"
-        "punpckhbh $f16, $f4, $f0               \r\n"
-        "punpcklbh $f18, $f10, $f0              \r\n"
-        "punpckhbh $f20, $f10, $f0              \r\n"
-        "paddsh $f4, $f14, $f18                 \r\n"
-        "paddsh $f10, $f16, $f20                \r\n"
-        "pmullh $f4, $f4, %[ff_pw_5]            \r\n"
-        "pmullh $f10, $f10, %[ff_pw_5]          \r\n"
-        "punpcklbh $f14, $f2, $f0               \r\n"
-        "punpckhbh $f16, $f2, $f0               \r\n"
-        "punpcklbh $f18, $f12, $f0              \r\n"
-        "punpckhbh $f20, $f12, $f0              \r\n"
-        "paddsh $f2, $f14, $f18                 \r\n"
-        "paddsh $f12, $f16, $f20                \r\n"
-        "psubsh $f6, $f6, $f4                   \r\n"
-        "psubsh $f8, $f8, $f10                  \r\n"
-        "paddsh $f6, $f6, $f2                   \r\n"
-        "paddsh $f8, $f8, $f12                  \r\n"
-        "paddsh $f6, $f6, %[ff_pw_16]           \r\n"
-        "paddsh $f8, $f8, %[ff_pw_16]           \r\n"
-        "psrah $f6, $f6, %[ff_pw_5]             \r\n"
-        "psrah $f8, $f8, %[ff_pw_5]             \r\n"
-        "packushb $f18, $f6, $f8                \r\n"
-        "ldc1 $f20, 0(%[dst])                   \r\n"
-        "pavgb $f18, $f18, $f20                 \r\n"
-        "sdc1 $f18, 0(%[dst])                   \r\n"
-        "dadd %[dst], %[dst], %[dstStride]      \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "daddi $8, $8, -1                       \r\n"
-        "bnez $8, 1b                            \r\n"
-        : [dst]"+&r"(dst),[src]"+&r"(src)
-        : [dstStride]"r"(dstStride),[srcStride]"r"(srcStride),
-          [ff_pw_20]"f"(ff_pw_20),[ff_pw_5]"f"(ff_pw_5),[ff_pw_16]"f"(ff_pw_16)
-        : "$8","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18","$f20"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dli        %[tmp0],    0x08                                    \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp1],   0x05(%[src])                            \n\t"
+        "gsldrc1    %[ftmp1],   -0x02(%[src])                           \n\t"
+        "gsldlc1    %[ftmp2],   0x06(%[src])                            \n\t"
+        "gsldrc1    %[ftmp2],   -0x01(%[src])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[src])                            \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[src])                            \n\t"
+        "gsldlc1    %[ftmp4],   0x08(%[src])                            \n\t"
+        "gsldrc1    %[ftmp4],   0x01(%[src])                            \n\t"
+        "gsldlc1    %[ftmp5],   0x09(%[src])                            \n\t"
+        "gsldrc1    %[ftmp5],   0x02(%[src])                            \n\t"
+        "gsldlc1    %[ftmp6],   0x0a(%[src])                            \n\t"
+        "gsldrc1    %[ftmp6],   0x03(%[src])                            \n\t"
+        "punpcklbh  %[ftmp7],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp8],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp9],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp10],  %[ftmp4],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp3],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddsh     %[ftmp4],   %[ftmp8],       %[ftmp10]               \n\t"
+        "pmullh     %[ftmp3],   %[ftmp3],       %[ff_pw_20]             \n\t"
+        "pmullh     %[ftmp4],   %[ftmp4],       %[ff_pw_20]             \n\t"
+        "punpcklbh  %[ftmp7],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp8],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp9],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp10],  %[ftmp5],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp2],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddsh     %[ftmp5],   %[ftmp8],       %[ftmp10]               \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[ff_pw_5]              \n\t"
+        "pmullh     %[ftmp5],   %[ftmp5],       %[ff_pw_5]              \n\t"
+        "punpcklbh  %[ftmp7],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp8],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp9],   %[ftmp6],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp10],  %[ftmp6],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp1],   %[ftmp7],       %[ftmp9]                \n\t"
+        "paddsh     %[ftmp6],   %[ftmp8],       %[ftmp10]               \n\t"
+        "psubsh     %[ftmp3],   %[ftmp3],       %[ftmp2]                \n\t"
+        "psubsh     %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "paddsh     %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "paddsh     %[ftmp3],   %[ftmp3],       %[ff_pw_16]             \n\t"
+        "paddsh     %[ftmp4],   %[ftmp4],       %[ff_pw_16]             \n\t"
+        "psrah      %[ftmp3],   %[ftmp3],       %[ff_pw_5]              \n\t"
+        "psrah      %[ftmp4],   %[ftmp4],       %[ff_pw_5]              \n\t"
+        "packushb   %[ftmp9],   %[ftmp3],       %[ftmp4]                \n\t"
+        "ldc1       %[ftmp10],  0x00(%[dst])                            \n\t"
+        "pavgb      %[ftmp9],   %[ftmp9],       %[ftmp10]               \n\t"
+        "sdc1       %[ftmp9],   0x00(%[dst])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),
+          [tmp0]"=&r"(tmp[0]),
+          [dst]"+&r"(dst),                  [src]"+&r"(src)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [srcStride]"r"((mips_reg)srcStride),
+          [ff_pw_20]"f"(ff_pw_20),          [ff_pw_5]"f"(ff_pw_5),
+          [ff_pw_16]"f"(ff_pw_16)
+        : "memory"
     );
 }
 
@@ -581,342 +409,438 @@ static void avg_h264_qpel16_h_lowpass_mmi(uint8_t *dst, const uint8_t *src,
 static void put_h264_qpel4_v_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
+    double ftmp[12];
+    uint64_t tmp[1];
+    uint64_t low32;
+
+    src -= 2 * srcStride;
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "gslwlc1 $f2, 3(%[srcB])                \r\n"
-        "gslwrc1 $f2, 0(%[srcB])                \r\n"
-        "gslwlc1 $f4, 3(%[srcA])                \r\n"
-        "gslwrc1 $f4, 0(%[srcA])                \r\n"
-        "gslwlc1 $f6, 3(%[src0])                \r\n"
-        "gslwrc1 $f6, 0(%[src0])                \r\n"
-        "gslwlc1 $f8, 3(%[src1])                \r\n"
-        "gslwrc1 $f8, 0(%[src1])                \r\n"
-        "gslwlc1 $f10, 3(%[src2])               \r\n"
-        "gslwrc1 $f10, 0(%[src2])               \r\n"
-        "gslwlc1 $f12, 3(%[src3])               \r\n"
-        "gslwrc1 $f12, 0(%[src3])               \r\n"
-        "gslwlc1 $f14, 3(%[src4])               \r\n"
-        "gslwrc1 $f14, 0(%[src4])               \r\n"
-        "gslwlc1 $f16, 3(%[src5])               \r\n"
-        "gslwrc1 $f16, 0(%[src5])               \r\n"
-        "gslwlc1 $f18, 3(%[src6])               \r\n"
-        "gslwrc1 $f18, 0(%[src6])               \r\n"
-        "punpcklbh $f2, $f2, $f0                \r\n"
-        "punpcklbh $f4, $f4, $f0                \r\n"
-        "punpcklbh $f6, $f6, $f0                \r\n"
-        "punpcklbh $f8, $f8, $f0                \r\n"
-        "punpcklbh $f10, $f10, $f0              \r\n"
-        "punpcklbh $f12, $f12, $f0              \r\n"
-        "punpcklbh $f14, $f14, $f0              \r\n"
-        "punpcklbh $f16, $f16, $f0              \r\n"
-        "punpcklbh $f18, $f18, $f0              \r\n"
-        "paddsh $f20, $f6, $f8                  \r\n"
-        "pmullh $f20, $f20, %[ff_pw_20]         \r\n"
-        "paddsh $f22, $f4, $f10                 \r\n"
-        "pmullh $f22, $f22, %[ff_pw_5]          \r\n"
-        "psubsh $f24, $f20, $f22                \r\n"
-        "paddsh $f24, $f24, $f2                 \r\n"
-        "paddsh $f24, $f24, $f12                \r\n"
-        "paddsh $f20, $f8, $f10                 \r\n"
-        "pmullh $f20, $f20, %[ff_pw_20]         \r\n"
-        "paddsh $f22, $f6, $f12                 \r\n"
-        "pmullh $f22, $f22, %[ff_pw_5]          \r\n"
-        "psubsh $f26, $f20, $f22                \r\n"
-        "paddsh $f26, $f26, $f4                 \r\n"
-        "paddsh $f26, $f26, $f14                \r\n"
-        "paddsh $f20, $f10, $f12                \r\n"
-        "pmullh $f20, $f20, %[ff_pw_20]         \r\n"
-        "paddsh $f22, $f8, $f14                 \r\n"
-        "pmullh $f22, $f22, %[ff_pw_5]          \r\n"
-        "psubsh $f28, $f20, $f22                \r\n"
-        "paddsh $f28, $f28, $f6                 \r\n"
-        "paddsh $f28, $f28, $f16                \r\n"
-        "paddsh $f20, $f12, $f14                \r\n"
-        "pmullh $f20, $f20, %[ff_pw_20]         \r\n"
-        "paddsh $f22, $f10, $f16                \r\n"
-        "pmullh $f22, $f22, %[ff_pw_5]          \r\n"
-        "psubsh $f30, $f20, $f22                \r\n"
-        "paddsh $f30, $f30, $f8                 \r\n"
-        "paddsh $f30, $f30, $f18                \r\n"
-        "paddsh $f24, $f24, %[ff_pw_16]         \r\n"
-        "paddsh $f26, $f26, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "paddsh $f30, $f30, %[ff_pw_16]         \r\n"
-        "psrah $f24, $f24, %[ff_pw_5]           \r\n"
-        "psrah $f26, $f26, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "psrah $f30, $f30, %[ff_pw_5]           \r\n"
-        "packushb $f24, $f24, $f0               \r\n"
-        "packushb $f26, $f26, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "packushb $f30, $f30, $f0               \r\n"
-        "swc1 $f24, 0(%[dst0])                  \r\n"
-        "swc1 $f26, 0(%[dst1])                  \r\n"
-        "swc1 $f28, 0(%[dst2])                  \r\n"
-        "swc1 $f30, 0(%[dst3])                  \r\n"
-        ::[dst0]"r"(dst),               [dst1]"r"(dst+dstStride),
-          [dst2]"r"(dst+2*dstStride),   [dst3]"r"(dst+3*dstStride),
-          [srcB]"r"(src-2*srcStride),   [srcA]"r"(src-srcStride),
-          [src0]"r"(src),               [src1]"r"(src+srcStride),
-          [src2]"r"(src+2*srcStride),   [src3]"r"(src+3*srcStride),
-          [src4]"r"(src+4*srcStride),   [src5]"r"(src+5*srcStride),
-          [src6]"r"(src+6*srcStride),   [ff_pw_20]"f"(ff_pw_20),
-          [ff_pw_5]"f"(ff_pw_5),        [ff_pw_16]"f"(ff_pw_16)
-        : "$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16","$f18",
-          "$f20","$f22","$f24","$f26","$f28","$f30"
+        ".set       push                                                \n\t"
+        ".set       noreorder                                           \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "mtc1       %[tmp0],    %[ftmp10]                               \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "dli        %[tmp0],    0x05                                    \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "mtc1       %[tmp0],    %[ftmp11]                               \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        "paddh      %[ftmp7],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psllh      %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+        "psubh      %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        "psubh      %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ff_pw_5]              \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]             \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp6]                \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "psrah      %[ftmp7],   %[ftmp7],       %[ftmp11]               \n\t"
+        "packushb   %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "swc1       %[ftmp7],   0x00(%[dst])                            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "paddh      %[ftmp7],   %[ftmp4],       %[ftmp5]                \n\t"
+        "psllh      %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+        "psubh      %[ftmp7],   %[ftmp7],       %[ftmp3]                \n\t"
+        "psubh      %[ftmp7],   %[ftmp7],       %[ftmp6]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ff_pw_5]              \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]             \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]                \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        "psrah      %[ftmp7],   %[ftmp7],       %[ftmp11]               \n\t"
+        "packushb   %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "swc1       %[ftmp7],   0x00(%[dst])                            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "paddh      %[ftmp7],   %[ftmp5],       %[ftmp6]                \n\t"
+        "psllh      %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+        "psubh      %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+        "psubh      %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ff_pw_5]              \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]             \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp3]                \n\t"
+        "psrah      %[ftmp7],   %[ftmp7],       %[ftmp11]               \n\t"
+        "packushb   %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "swc1       %[ftmp7],   0x00(%[dst])                            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "paddh      %[ftmp7],   %[ftmp6],       %[ftmp1]                \n\t"
+        "psllh      %[ftmp7],   %[ftmp7],       %[ftmp10]               \n\t"
+        "psubh      %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+        "psubh      %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ff_pw_5]              \n\t"
+        "paddh      %[ftmp4],   %[ftmp4],       %[ff_pw_16]             \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp3]                \n\t"
+        "paddh      %[ftmp7],   %[ftmp7],       %[ftmp4]                \n\t"
+        "psrah      %[ftmp7],   %[ftmp7],       %[ftmp11]               \n\t"
+        "packushb   %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "swc1       %[ftmp7],   0x00(%[dst])                            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        ".set       pop                                                 \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [ftmp10]"=&f"(ftmp[10]),          [ftmp11]"=&f"(ftmp[11]),
+          [tmp0]"=&r"(tmp[0]),
+          [dst]"+&r"(dst),                  [src]"+&r"(src),
+          [low32]"=&r"(low32)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [srcStride]"r"((mips_reg)srcStride),
+          [ff_pw_5]"f"(ff_pw_5),            [ff_pw_16]"f"(ff_pw_16)
+        : "memory"
     );
 }
 
 static void put_h264_qpel8_v_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
-    __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "gsldlc1 $f2, 7(%[srcB])                \r\n"
-        "gsldrc1 $f2, 0(%[srcB])                \r\n"
-        "gsldlc1 $f4, 7(%[srcA])                \r\n"
-        "gsldrc1 $f4, 0(%[srcA])                \r\n"
-        "gsldlc1 $f6, 7(%[src0])                \r\n"
-        "gsldrc1 $f6, 0(%[src0])                \r\n"
-        "gsldlc1 $f8, 7(%[src1])                \r\n"
-        "gsldrc1 $f8, 0(%[src1])                \r\n"
-        "gsldlc1 $f10, 7(%[src2])               \r\n"
-        "gsldrc1 $f10, 0(%[src2])               \r\n"
-        "gsldlc1 $f12, 7(%[src3])               \r\n"
-        "gsldrc1 $f12, 0(%[src3])               \r\n"
-        "gsldlc1 $f14, 7(%[src4])               \r\n"
-        "gsldrc1 $f14, 0(%[src4])               \r\n"
-        "gsldlc1 $f16, 7(%[src5])               \r\n"
-        "gsldrc1 $f16, 0(%[src5])               \r\n"
-        "gsldlc1 $f18, 7(%[src6])               \r\n"
-        "gsldrc1 $f18, 0(%[src6])               \r\n"
-        "gsldlc1 $f20, 7(%[src7])               \r\n"
-        "gsldrc1 $f20, 0(%[src7])               \r\n"
-        "gsldlc1 $f22, 7(%[src8])               \r\n"
-        "gsldrc1 $f22, 0(%[src8])               \r\n"
-        "gsldlc1 $f24, 7(%[src9])               \r\n"
-        "gsldrc1 $f24, 0(%[src9])               \r\n"
-        "gsldlc1 $f26, 7(%[src10])              \r\n"
-        "gsldrc1 $f26, 0(%[src10])              \r\n"
-        "punpcklbh $f1, $f2, $f0                \r\n"
-        "punpckhbh $f2, $f2, $f0                \r\n"
-        "punpcklbh $f3, $f4, $f0                \r\n"
-        "punpckhbh $f4, $f4, $f0                \r\n"
-        "punpcklbh $f5, $f6, $f0                \r\n"
-        "punpckhbh $f6, $f6, $f0                \r\n"
-        "punpcklbh $f7, $f8, $f0                \r\n"
-        "punpckhbh $f8, $f8, $f0                \r\n"
-        "punpcklbh $f9, $f10, $f0               \r\n"
-        "punpckhbh $f10, $f10, $f0              \r\n"
-        "punpcklbh $f11, $f12, $f0              \r\n"
-        "punpckhbh $f12, $f12, $f0              \r\n"
-        "punpcklbh $f13, $f14, $f0              \r\n"
-        "punpckhbh $f14, $f14, $f0              \r\n"
-        "punpcklbh $f15, $f16, $f0              \r\n"
-        "punpckhbh $f16, $f16, $f0              \r\n"
-        "punpcklbh $f17, $f18, $f0              \r\n"
-        "punpckhbh $f18, $f18, $f0              \r\n"
-        "punpcklbh $f19, $f20, $f0              \r\n"
-        "punpckhbh $f20, $f20, $f0              \r\n"
-        "punpcklbh $f21, $f22, $f0              \r\n"
-        "punpckhbh $f22, $f22, $f0              \r\n"
-        "punpcklbh $f23, $f24, $f0              \r\n"
-        "punpckhbh $f24, $f24, $f0              \r\n"
-        "punpcklbh $f25, $f26, $f0              \r\n"
-        "punpckhbh $f26, $f26, $f0              \r\n"
-        "paddsh $f27, $f5, $f7                  \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f6, $f8                  \r\n"//src0+src1
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f3                 \r\n"
-        "psubsh $f28, $f28, $f4                 \r\n"
-        "psubsh $f27, $f27, $f9                 \r\n"
-        "psubsh $f28, $f28, $f10                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f1                 \r\n"
-        "paddsh $f28, $f28, $f2                 \r\n"
-        "paddsh $f27, $f27, $f11                \r\n"
-        "paddsh $f28, $f28, $f12                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f2, $f27, $f28              \r\n"
-        "sdc1 $f2, 0(%[dst0])                   \r\n"
-        "paddsh $f27, $f7, $f9                  \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f8, $f10                 \r\n"//src1+src2
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f5                 \r\n"
-        "psubsh $f28, $f28, $f6                 \r\n"
-        "psubsh $f27, $f27, $f11                \r\n"
-        "psubsh $f28, $f28, $f12                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f3                 \r\n"
-        "paddsh $f28, $f28, $f4                 \r\n"
-        "paddsh $f27, $f27, $f13                \r\n"
-        "paddsh $f28, $f28, $f14                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f4, $f27, $f28              \r\n"
-        "sdc1 $f4, 0(%[dst1])                   \r\n"
-        "paddsh $f27, $f9, $f11                 \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f10, $f12                \r\n"//src2+src3
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f7                 \r\n"
-        "psubsh $f28, $f28, $f8                 \r\n"
-        "psubsh $f27, $f27, $f13                \r\n"
-        "psubsh $f28, $f28, $f14                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f5                 \r\n"
-        "paddsh $f28, $f28, $f6                 \r\n"
-        "paddsh $f27, $f27, $f15                \r\n"
-        "paddsh $f28, $f28, $f16                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f6, $f27, $f28              \r\n"
-        "sdc1 $f6, 0(%[dst2])                   \r\n"
-        "paddsh $f27, $f11, $f13                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f12, $f14                \r\n"//src3+src4
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f9                 \r\n"
-        "psubsh $f28, $f28, $f10                \r\n"
-        "psubsh $f27, $f27, $f15                \r\n"
-        "psubsh $f28, $f28, $f16                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f7                 \r\n"
-        "paddsh $f28, $f28, $f8                 \r\n"
-        "paddsh $f27, $f27, $f17                \r\n"
-        "paddsh $f28, $f28, $f18                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f8, $f27, $f28              \r\n"
-        "sdc1 $f8, 0(%[dst3])                   \r\n"
-        "paddsh $f27, $f13, $f15                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f14, $f16                \r\n"//src4+src5
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f11                \r\n"
-        "psubsh $f28, $f28, $f12                \r\n"
-        "psubsh $f27, $f27, $f17                \r\n"
-        "psubsh $f28, $f28, $f18                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f9                 \r\n"
-        "paddsh $f28, $f28, $f10                \r\n"
-        "paddsh $f27, $f27, $f19                \r\n"
-        "paddsh $f28, $f28, $f20                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f10, $f27, $f28             \r\n"
-        "sdc1 $f10, 0(%[dst4])                  \r\n"
-
-        "paddsh $f27, $f15, $f17                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f16, $f18                \r\n"//src5+src6
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f13                \r\n"
-        "psubsh $f28, $f28, $f14                \r\n"
-        "psubsh $f27, $f27, $f19                \r\n"
-        "psubsh $f28, $f28, $f20                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f11                \r\n"
-        "paddsh $f28, $f28, $f12                \r\n"
-        "paddsh $f27, $f27, $f21                \r\n"
-        "paddsh $f28, $f28, $f22                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f12, $f27, $f28             \r\n"
-        "sdc1 $f12, 0(%[dst5])                  \r\n"
-        "paddsh $f27, $f17, $f19                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f18, $f20                \r\n"//src6+src7
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f15                \r\n"
-        "psubsh $f28, $f28, $f16                \r\n"
-        "psubsh $f27, $f27, $f21                \r\n"
-        "psubsh $f28, $f28, $f22                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f13                \r\n"
-        "paddsh $f28, $f28, $f14                \r\n"
-        "paddsh $f27, $f27, $f23                \r\n"
-        "paddsh $f28, $f28, $f24                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f14, $f27, $f28             \r\n"
-        "sdc1 $f14, 0(%[dst6])                  \r\n"
-        "paddsh $f27, $f19, $f21                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f20, $f22                \r\n"//src7+src8
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f17                \r\n"
-        "psubsh $f28, $f28, $f18                \r\n"
-        "psubsh $f27, $f27, $f23                \r\n"
-        "psubsh $f28, $f28, $f24                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f15                \r\n"
-        "paddsh $f28, $f28, $f16                \r\n"
-        "paddsh $f27, $f27, $f25                \r\n"
-        "paddsh $f28, $f28, $f26                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f16, $f27, $f28             \r\n"
-        "sdc1 $f16, 0(%[dst7])                  \r\n"
-        ::[dst0]"r"(dst),               [dst1]"r"(dst+dstStride),
-          [dst2]"r"(dst+2*dstStride),   [dst3]"r"(dst+3*dstStride),
-          [dst4]"r"(dst+4*dstStride),   [dst5]"r"(dst+5*dstStride),
-          [dst6]"r"(dst+6*dstStride),   [dst7]"r"(dst+7*dstStride),
-          [srcB]"r"(src-2*srcStride),   [srcA]"r"(src-srcStride),
-          [src0]"r"(src),               [src1]"r"(src+srcStride),
-          [src2]"r"(src+2*srcStride),   [src3]"r"(src+3*srcStride),
-          [src4]"r"(src+4*srcStride),   [src5]"r"(src+5*srcStride),
-          [src6]"r"(src+6*srcStride),   [src7]"r"(src+7*srcStride),
-          [src8]"r"(src+8*srcStride),   [src9]"r"(src+9*srcStride),
-          [src10]"r"(src+10*srcStride), [ff_pw_4]"f"(ff_pw_4),
-          [ff_pw_5]"f"(ff_pw_5),        [ff_pw_16]"f"(ff_pw_16)
-        : "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7","$f8","$f9","$f10",
-          "$f11","$f12","$f13","$f14","$f15","$f16","$f17","$f18","$f19",
-          "$f20","$f21","$f22","$f23","$f24","$f25","$f26","$f27","$f28"
-    );
+    int w = 2;
+    int h = 8;
+    double ftmp[10];
+    uint64_t tmp[1];
+    uint64_t low32;
+
+    src -= 2 * srcStride;
+
+    while (w--) {
+        __asm__ volatile (
+            ".set       push                                            \n\t"
+            ".set       noreorder                                       \n\t"
+            "dli        %[tmp0],    0x02                                \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "mtc1       %[tmp0],    %[ftmp8]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "dli        %[tmp0],    0x05                                \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "mtc1       %[tmp0],    %[ftmp9]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp7]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp5]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]         \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp0],       %[ftmp1]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "punpcklbh  %[ftmp3] ,  %[ftmp3],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ftmp3]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp1],       %[ftmp2]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ftmp4]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp5]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "bne        %[h],       0x10,           2f                  \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]         \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp0],       %[ftmp1]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ftmp3]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp1],       %[ftmp2]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ftmp4]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp5]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]            \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "2:                                                         \n\t"
+            ".set       pop                                             \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [ftmp8]"=&f"(ftmp[8]),        [ftmp9]"=&f"(ftmp[9]),
+              [tmp0]"=&r"(tmp[0]),
+              [src]"+&r"(src),              [dst]"+&r"(dst),
+              [h]"+&r"(h),
+              [low32]"=&r"(low32)
+            : [dstStride]"r"((mips_reg)dstStride),
+              [srcStride]"r"((mips_reg)srcStride),
+              [ff_pw_5]"f"(ff_pw_5),        [ff_pw_16]"f"(ff_pw_16)
+            : "memory"
+        );
+
+        src += 4 - (h + 5) * srcStride;
+        dst += 4 - h * dstStride;
+    }
 }
 
 static void put_h264_qpel16_v_lowpass_mmi(uint8_t *dst, const uint8_t *src,
@@ -933,365 +857,466 @@ static void put_h264_qpel16_v_lowpass_mmi(uint8_t *dst, const uint8_t *src,
 static void avg_h264_qpel4_v_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
+    double ftmp[10];
+    uint64_t tmp[1];
+
+    src -= 2 * srcStride;
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "gslwlc1 $f2, 3(%[srcB])                \r\n"
-        "gslwrc1 $f2, 0(%[srcB])                \r\n"
-        "gslwlc1 $f4, 3(%[srcA])                \r\n"
-        "gslwrc1 $f4, 0(%[srcA])                \r\n"
-        "gslwlc1 $f6, 3(%[src0])                \r\n"
-        "gslwrc1 $f6, 0(%[src0])                \r\n"
-        "gslwlc1 $f8, 3(%[src1])                \r\n"
-        "gslwrc1 $f8, 0(%[src1])                \r\n"
-        "gslwlc1 $f10, 3(%[src2])               \r\n"
-        "gslwrc1 $f10, 0(%[src2])               \r\n"
-        "gslwlc1 $f12, 3(%[src3])               \r\n"
-        "gslwrc1 $f12, 0(%[src3])               \r\n"
-        "gslwlc1 $f14, 3(%[src4])               \r\n"
-        "gslwrc1 $f14, 0(%[src4])               \r\n"
-        "gslwlc1 $f16, 3(%[src5])               \r\n"
-        "gslwrc1 $f16, 0(%[src5])               \r\n"
-        "gslwlc1 $f18, 3(%[src6])               \r\n"
-        "gslwrc1 $f18, 0(%[src6])               \r\n"
-        "punpcklbh $f2, $f2, $f0                \r\n"
-        "punpcklbh $f4, $f4, $f0                \r\n"
-        "punpcklbh $f6, $f6, $f0                \r\n"
-        "punpcklbh $f8, $f8, $f0                \r\n"
-        "punpcklbh $f10, $f10, $f0              \r\n"
-        "punpcklbh $f12, $f12, $f0              \r\n"
-        "punpcklbh $f14, $f14, $f0              \r\n"
-        "punpcklbh $f16, $f16, $f0              \r\n"
-        "punpcklbh $f18, $f18, $f0              \r\n"
-        "paddsh $f20, $f6, $f8                  \r\n"
-        "pmullh $f20, $f20, %[ff_pw_20]         \r\n"
-        "paddsh $f22, $f4, $f10                 \r\n"
-        "pmullh $f22, $f22, %[ff_pw_5]          \r\n"
-        "psubsh $f24, $f20, $f22                \r\n"
-        "paddsh $f24, $f24, $f2                 \r\n"
-        "paddsh $f24, $f24, $f12                \r\n"
-        "paddsh $f20, $f8, $f10                 \r\n"
-        "pmullh $f20, $f20, %[ff_pw_20]         \r\n"
-        "paddsh $f22, $f6, $f12                 \r\n"
-        "pmullh $f22, $f22, %[ff_pw_5]          \r\n"
-        "psubsh $f26, $f20, $f22                \r\n"
-        "paddsh $f26, $f26, $f4                 \r\n"
-        "paddsh $f26, $f26, $f14                \r\n"
-        "paddsh $f20, $f10, $f12                \r\n"
-        "pmullh $f20, $f20, %[ff_pw_20]         \r\n"
-        "paddsh $f22, $f8, $f14                 \r\n"
-        "pmullh $f22, $f22, %[ff_pw_5]          \r\n"
-        "psubsh $f28, $f20, $f22                \r\n"
-        "paddsh $f28, $f28, $f6                 \r\n"
-        "paddsh $f28, $f28, $f16                \r\n"
-        "paddsh $f20, $f12, $f14                \r\n"
-        "pmullh $f20, $f20, %[ff_pw_20]         \r\n"
-        "paddsh $f22, $f10, $f16                \r\n"
-        "pmullh $f22, $f22, %[ff_pw_5]          \r\n"
-        "psubsh $f30, $f20, $f22                \r\n"
-        "paddsh $f30, $f30, $f8                 \r\n"
-        "paddsh $f30, $f30, $f18                \r\n"
-        "paddsh $f24, $f24, %[ff_pw_16]         \r\n"
-        "paddsh $f26, $f26, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "paddsh $f30, $f30, %[ff_pw_16]         \r\n"
-        "psrah $f24, $f24, %[ff_pw_5]           \r\n"
-        "psrah $f26, $f26, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "psrah $f30, $f30, %[ff_pw_5]           \r\n"
-        "packushb $f24, $f24, $f0               \r\n"
-        "packushb $f26, $f26, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "packushb $f30, $f30, $f0               \r\n"
-        "lwc1 $f2, 0(%[dst0])                   \r\n"
-        "lwc1 $f4, 0(%[dst1])                   \r\n"
-        "lwc1 $f6, 0(%[dst2])                   \r\n"
-        "lwc1 $f8, 0(%[dst3])                   \r\n"
-        "pavgb $f24, $f2, $f24                  \r\n"
-        "pavgb $f26, $f4, $f26                  \r\n"
-        "pavgb $f28, $f6, $f28                  \r\n"
-        "pavgb $f30, $f8, $f30                  \r\n"
-        "swc1 $f24, 0(%[dst0])                  \r\n"
-        "swc1 $f26, 0(%[dst1])                  \r\n"
-        "swc1 $f28, 0(%[dst2])                  \r\n"
-        "swc1 $f30, 0(%[dst3])                  \r\n"
-        ::[dst0]"r"(dst),               [dst1]"r"(dst+dstStride),
-          [dst2]"r"(dst+2*dstStride),   [dst3]"r"(dst+3*dstStride),
-          [srcB]"r"(src-2*srcStride),   [srcA]"r"(src-srcStride),
-          [src0]"r"(src),               [src1]"r"(src+srcStride),
-          [src2]"r"(src+2*srcStride),   [src3]"r"(src+3*srcStride),
-          [src4]"r"(src+4*srcStride),   [src5]"r"(src+5*srcStride),
-          [src6]"r"(src+6*srcStride),   [ff_pw_20]"f"(ff_pw_20),
+        ".set       push                                                \n\t"
+        ".set       noreorder                                           \n\t"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "mtc1       %[tmp0],    %[ftmp9]                                \n\t"
+        "dli        %[tmp0],    0x05                                    \n\t"
+        "lwc1       %[ftmp0],   0x00(%[src])                            \n\t"
+        "mtc1       %[tmp0],    %[ftmp8]                                \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "lwc1       %[ftmp1],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "lwc1       %[ftmp2],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "lwc1       %[ftmp3],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "lwc1       %[ftmp4],   0x00(%[src])                            \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]                \n\t"
+        "lwc1       %[ftmp5],   0x00(%[src])                            \n\t"
+        "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]                \n\t"
+        "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]                \n\t"
+        "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]              \n\t"
+        "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]             \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "lwc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "swc1       %[ftmp6],   0x00(%[dst])                            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "lwc1       %[ftmp0],   0x00(%[src])                            \n\t"
+        "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]                \n\t"
+        "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]                \n\t"
+        "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]              \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]             \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "lwc1       %[ftmp1],   0x00(%[dst])                            \n\t"
+        "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "swc1       %[ftmp6],   0x00(%[dst])                            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "lwc1       %[ftmp1],   0x00(%[src])                            \n\t"
+        "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]                \n\t"
+        "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]                \n\t"
+        "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]                \n\t"
+        "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]              \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]             \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]                \n\t"
+        "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "lwc1       %[ftmp2],   0x00(%[dst])                            \n\t"
+        "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp2]                \n\t"
+        "swc1       %[ftmp6],   0x00(%[dst])                            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        "lwc1       %[ftmp2],   0x00(%[src])                            \n\t"
+        "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]                \n\t"
+        "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]                \n\t"
+        "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+        "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]              \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]             \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]                \n\t"
+        "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "lwc1       %[ftmp3],   0x00(%[dst])                            \n\t"
+        "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp3]                \n\t"
+        "swc1       %[ftmp6],   0x00(%[dst])                            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        ".set       pop                                                 \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),        [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp[0]),
+          [src]"+&r"(src),              [dst]"+&r"(dst)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [srcStride]"r"((mips_reg)srcStride),
           [ff_pw_5]"f"(ff_pw_5),        [ff_pw_16]"f"(ff_pw_16)
-        : "$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16","$f18",
-          "$f20","$f22","$f24","$f26","$f28","$f30"
+        : "memory"
     );
 }
 
 static void avg_h264_qpel8_v_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
-    __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "gsldlc1 $f2, 7(%[srcB])                \r\n"
-        "gsldrc1 $f2, 0(%[srcB])                \r\n"
-        "gsldlc1 $f4, 7(%[srcA])                \r\n"
-        "gsldrc1 $f4, 0(%[srcA])                \r\n"
-        "gsldlc1 $f6, 7(%[src0])                \r\n"
-        "gsldrc1 $f6, 0(%[src0])                \r\n"
-        "gsldlc1 $f8, 7(%[src1])                \r\n"
-        "gsldrc1 $f8, 0(%[src1])                \r\n"
-        "gsldlc1 $f10, 7(%[src2])               \r\n"
-        "gsldrc1 $f10, 0(%[src2])               \r\n"
-        "gsldlc1 $f12, 7(%[src3])               \r\n"
-        "gsldrc1 $f12, 0(%[src3])               \r\n"
-        "gsldlc1 $f14, 7(%[src4])               \r\n"
-        "gsldrc1 $f14, 0(%[src4])               \r\n"
-        "gsldlc1 $f16, 7(%[src5])               \r\n"
-        "gsldrc1 $f16, 0(%[src5])               \r\n"
-        "gsldlc1 $f18, 7(%[src6])               \r\n"
-        "gsldrc1 $f18, 0(%[src6])               \r\n"
-        "gsldlc1 $f20, 7(%[src7])               \r\n"
-        "gsldrc1 $f20, 0(%[src7])               \r\n"
-        "gsldlc1 $f22, 7(%[src8])               \r\n"
-        "gsldrc1 $f22, 0(%[src8])               \r\n"
-        "gsldlc1 $f24, 7(%[src9])               \r\n"
-        "gsldrc1 $f24, 0(%[src9])               \r\n"
-        "gsldlc1 $f26, 7(%[src10])              \r\n"
-        "gsldrc1 $f26, 0(%[src10])              \r\n"
-        "punpcklbh $f1, $f2, $f0                \r\n"
-        "punpckhbh $f2, $f2, $f0                \r\n"
-        "punpcklbh $f3, $f4, $f0                \r\n"
-        "punpckhbh $f4, $f4, $f0                \r\n"
-        "punpcklbh $f5, $f6, $f0                \r\n"
-        "punpckhbh $f6, $f6, $f0                \r\n"
-        "punpcklbh $f7, $f8, $f0                \r\n"
-        "punpckhbh $f8, $f8, $f0                \r\n"
-        "punpcklbh $f9, $f10, $f0               \r\n"
-        "punpckhbh $f10, $f10, $f0              \r\n"
-        "punpcklbh $f11, $f12, $f0              \r\n"
-        "punpckhbh $f12, $f12, $f0              \r\n"
-        "punpcklbh $f13, $f14, $f0              \r\n"
-        "punpckhbh $f14, $f14, $f0              \r\n"
-        "punpcklbh $f15, $f16, $f0              \r\n"
-        "punpckhbh $f16, $f16, $f0              \r\n"
-        "punpcklbh $f17, $f18, $f0              \r\n"
-        "punpckhbh $f18, $f18, $f0              \r\n"
-        "punpcklbh $f19, $f20, $f0              \r\n"
-        "punpckhbh $f20, $f20, $f0              \r\n"
-        "punpcklbh $f21, $f22, $f0              \r\n"
-        "punpckhbh $f22, $f22, $f0              \r\n"
-        "punpcklbh $f23, $f24, $f0              \r\n"
-        "punpckhbh $f24, $f24, $f0              \r\n"
-        "punpcklbh $f25, $f26, $f0              \r\n"
-        "punpckhbh $f26, $f26, $f0              \r\n"
-        "paddsh $f27, $f5, $f7                  \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f6, $f8                  \r\n"//src0+src1
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f3                 \r\n"
-        "psubsh $f28, $f28, $f4                 \r\n"
-        "psubsh $f27, $f27, $f9                 \r\n"
-        "psubsh $f28, $f28, $f10                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f1                 \r\n"
-        "paddsh $f28, $f28, $f2                 \r\n"
-        "paddsh $f27, $f27, $f11                \r\n"
-        "paddsh $f28, $f28, $f12                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f2, $f27, $f28              \r\n"
-        "ldc1 $f28, 0(%[dst0])                  \r\n"
-        "pavgb $f2, $f2, $f28                   \r\n"
-        "sdc1 $f2, 0(%[dst0])                   \r\n"
-        "paddsh $f27, $f7, $f9                  \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f8, $f10                 \r\n"//src1+src2
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f5                 \r\n"
-        "psubsh $f28, $f28, $f6                 \r\n"
-        "psubsh $f27, $f27, $f11                \r\n"
-        "psubsh $f28, $f28, $f12                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f3                 \r\n"
-        "paddsh $f28, $f28, $f4                 \r\n"
-        "paddsh $f27, $f27, $f13                \r\n"
-        "paddsh $f28, $f28, $f14                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f4, $f27, $f28              \r\n"
-        "ldc1 $f28, 0(%[dst1])                  \r\n"
-        "pavgb $f4, $f4, $f28                   \r\n"
-        "sdc1 $f4, 0(%[dst1])                   \r\n"
-        "paddsh $f27, $f9, $f11                 \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f10, $f12                \r\n"//src2+src3
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f7                 \r\n"
-        "psubsh $f28, $f28, $f8                 \r\n"
-        "psubsh $f27, $f27, $f13                \r\n"
-        "psubsh $f28, $f28, $f14                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f5                 \r\n"
-        "paddsh $f28, $f28, $f6                 \r\n"
-        "paddsh $f27, $f27, $f15                \r\n"
-        "paddsh $f28, $f28, $f16                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f6, $f27, $f28              \r\n"
-        "ldc1 $f28, 0(%[dst2])                  \r\n"
-        "pavgb $f6, $f6, $f28                   \r\n"
-        "sdc1 $f6, 0(%[dst2])                   \r\n"
-        "paddsh $f27, $f11, $f13                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f12, $f14                \r\n"//src3+src4
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f9                 \r\n"
-        "psubsh $f28, $f28, $f10                \r\n"
-        "psubsh $f27, $f27, $f15                \r\n"
-        "psubsh $f28, $f28, $f16                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f7                 \r\n"
-        "paddsh $f28, $f28, $f8                 \r\n"
-        "paddsh $f27, $f27, $f17                \r\n"
-        "paddsh $f28, $f28, $f18                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f8, $f27, $f28              \r\n"
-        "ldc1 $f28, 0(%[dst3])                  \r\n"
-        "pavgb $f8, $f8, $f28                   \r\n"
-        "sdc1 $f8, 0(%[dst3])                   \r\n"
-        "paddsh $f27, $f13, $f15                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f14, $f16                \r\n"//src4+src5
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f11                \r\n"
-        "psubsh $f28, $f28, $f12                \r\n"
-        "psubsh $f27, $f27, $f17                \r\n"
-        "psubsh $f28, $f28, $f18                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f9                 \r\n"
-        "paddsh $f28, $f28, $f10                \r\n"
-        "paddsh $f27, $f27, $f19                \r\n"
-        "paddsh $f28, $f28, $f20                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f10, $f27, $f28             \r\n"
-        "ldc1 $f28, 0(%[dst4])                  \r\n"
-        "pavgb $f10, $f10, $f28                 \r\n"
-        "sdc1 $f10, 0(%[dst4])                  \r\n"
-        "paddsh $f27, $f15, $f17                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f16, $f18                \r\n"//src5+src6
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f13                \r\n"
-        "psubsh $f28, $f28, $f14                \r\n"
-        "psubsh $f27, $f27, $f19                \r\n"
-        "psubsh $f28, $f28, $f20                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f11                \r\n"
-        "paddsh $f28, $f28, $f12                \r\n"
-        "paddsh $f27, $f27, $f21                \r\n"
-        "paddsh $f28, $f28, $f22                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f12, $f27, $f28             \r\n"
-        "ldc1 $f28, 0(%[dst5])                  \r\n"
-        "pavgb $f12, $f12, $f28                 \r\n"
-        "sdc1 $f12, 0(%[dst5])                  \r\n"
-        "paddsh $f27, $f17, $f19                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f18, $f20                \r\n"//src6+src7
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f15                \r\n"
-        "psubsh $f28, $f28, $f16                \r\n"
-        "psubsh $f27, $f27, $f21                \r\n"
-        "psubsh $f28, $f28, $f22                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f13                \r\n"
-        "paddsh $f28, $f28, $f14                \r\n"
-        "paddsh $f27, $f27, $f23                \r\n"
-        "paddsh $f28, $f28, $f24                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f14, $f27, $f28             \r\n"
-        "ldc1 $f28, 0(%[dst6])                  \r\n"
-        "pavgb $f14, $f14, $f28                 \r\n"
-        "sdc1 $f14, 0(%[dst6])                  \r\n"
-        "paddsh $f27, $f19, $f21                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_4]          \r\n"
-        "paddsh $f28, $f20, $f22                \r\n"//src7+src8
-        "pmullh $f28, $f28, %[ff_pw_4]          \r\n"
-        "psubsh $f27, $f27, $f17                \r\n"
-        "psubsh $f28, $f28, $f18                \r\n"
-        "psubsh $f27, $f27, $f23                \r\n"
-        "psubsh $f28, $f28, $f24                \r\n"
-        "pmullh $f27, $f27, %[ff_pw_5]          \r\n"
-        "pmullh $f28, $f28, %[ff_pw_5]          \r\n"
-        "paddsh $f27, $f27, $f15                \r\n"
-        "paddsh $f28, $f28, $f16                \r\n"
-        "paddsh $f27, $f27, $f25                \r\n"
-        "paddsh $f28, $f28, $f26                \r\n"
-        "paddsh $f27, $f27, %[ff_pw_16]         \r\n"
-        "paddsh $f28, $f28, %[ff_pw_16]         \r\n"
-        "psrah $f27, $f27, %[ff_pw_5]           \r\n"
-        "psrah $f28, $f28, %[ff_pw_5]           \r\n"
-        "packushb $f27, $f27, $f0               \r\n"
-        "packushb $f28, $f28, $f0               \r\n"
-        "punpcklwd $f16, $f27, $f28             \r\n"
-        "ldc1 $f28, 0(%[dst7])                  \r\n"
-        "pavgb $f16, $f16, $f28                 \r\n"
-        "sdc1 $f16, 0(%[dst7])                  \r\n"
-        ::[dst0]"r"(dst),               [dst1]"r"(dst+dstStride),
-          [dst2]"r"(dst+2*dstStride),   [dst3]"r"(dst+3*dstStride),
-          [dst4]"r"(dst+4*dstStride),   [dst5]"r"(dst+5*dstStride),
-          [dst6]"r"(dst+6*dstStride),   [dst7]"r"(dst+7*dstStride),
-          [srcB]"r"(src-2*srcStride),   [srcA]"r"(src-srcStride),
-          [src0]"r"(src),               [src1]"r"(src+srcStride),
-          [src2]"r"(src+2*srcStride),   [src3]"r"(src+3*srcStride),
-          [src4]"r"(src+4*srcStride),   [src5]"r"(src+5*srcStride),
-          [src6]"r"(src+6*srcStride),   [src7]"r"(src+7*srcStride),
-          [src8]"r"(src+8*srcStride),   [src9]"r"(src+9*srcStride),
-          [src10]"r"(src+10*srcStride), [ff_pw_4]"f"(ff_pw_4),
-          [ff_pw_5]"f"(ff_pw_5),        [ff_pw_16]"f"(ff_pw_16)
-        : "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7","$f8","$f9","$f10",
-          "$f11","$f12","$f13","$f14","$f15","$f16","$f17","$f18","$f19",
-          "$f20","$f21","$f22","$f23","$f24","$f25","$f26","$f27","$f28"
-    );
+    int w = 2;
+    int h = 8;
+    double ftmp[10];
+    uint64_t tmp[1];
+    uint64_t low32;
+
+    src -= 2 * srcStride;
+
+    while (w--) {
+        __asm__ volatile (
+            ".set       push                                            \n\t"
+            ".set       noreorder                                       \n\t"
+            "dli        %[tmp0],    0x02                                \n\t"
+            "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]            \n\t"
+            "mtc1       %[tmp0],    %[ftmp9]                            \n\t"
+            "dli        %[tmp0],    0x05                                \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "mtc1       %[tmp0],    %[ftmp8]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp7]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp5]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp0],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp3],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp0],       %[ftmp1]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ftmp3]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp4],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp1],       %[ftmp2]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ftmp4]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp5],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp5]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp0],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "bne        %[h],       0x10,           2f                  \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp3],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp0],       %[ftmp1]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ftmp3]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp4],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp1],       %[ftmp2]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ftmp4]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp5],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp5]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp0],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp1],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp2],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]         \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psrah      %[ftmp6],   %[ftmp6],       %[ftmp8]            \n\t"
+            "packushb   %[ftmp6],   %[ftmp6],       %[ftmp6]            \n\t"
+            "lwc1       %[ftmp3],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "swc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "2:                                                         \n\t"
+            ".set       pop                                             \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [ftmp8]"=&f"(ftmp[8]),        [ftmp9]"=&f"(ftmp[9]),
+              [tmp0]"=&r"(tmp[0]),
+              [src]"+&r"(src),              [dst]"+&r"(dst),
+              [h]"+&r"(h),
+              [low32]"=&r"(low32)
+            : [dstStride]"r"((mips_reg)dstStride),
+              [srcStride]"r"((mips_reg)srcStride),
+              [ff_pw_5]"f"(ff_pw_5),        [ff_pw_16]"f"(ff_pw_16)
+            : "memory"
+        );
+
+        src += 4 - (h + 5) * srcStride;
+        dst += 4 - h * dstStride;
+    }
 }
 
 static void avg_h264_qpel16_v_lowpass_mmi(uint8_t *dst, const uint8_t *src,
@@ -1308,53 +1333,67 @@ static void avg_h264_qpel16_v_lowpass_mmi(uint8_t *dst, const uint8_t *src,
 static void put_h264_qpel4_hv_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
+    INIT_CLIP
     int i;
     int16_t _tmp[36];
     int16_t *tmp = _tmp;
+    double ftmp[10];
+    uint64_t tmp0;
+    uint64_t low32;
+
     src -= 2*srcStride;
+
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "dli $8, 9                              \r\n"
-        "1:                                     \r\n"
-        "gslwlc1 $f2, 1(%[src])                 \r\n"
-        "gslwrc1 $f2, -2(%[src])                \r\n"
-        "gslwlc1 $f4, 2(%[src])                 \r\n"
-        "gslwrc1 $f4, -1(%[src])                \r\n"
-        "gslwlc1 $f6, 3(%[src])                 \r\n"
-        "gslwrc1 $f6, 0(%[src])                 \r\n"
-        "gslwlc1 $f8, 4(%[src])                 \r\n"
-        "gslwrc1 $f8, 1(%[src])                 \r\n"
-        "gslwlc1 $f10, 5(%[src])                \r\n"
-        "gslwrc1 $f10, 2(%[src])                \r\n"
-        "gslwlc1 $f12, 6(%[src])                \r\n"
-        "gslwrc1 $f12, 3(%[src])                \r\n"
-        "punpcklbh $f2, $f2, $f0                \r\n"
-        "punpcklbh $f4, $f4, $f0                \r\n"
-        "punpcklbh $f6, $f6, $f0                \r\n"
-        "punpcklbh $f8, $f8, $f0                \r\n"
-        "punpcklbh $f10, $f10, $f0              \r\n"
-        "punpcklbh $f12, $f12, $f0              \r\n"
-        "paddsh $f14, $f6, $f8                  \r\n"
-        "paddsh $f16, $f4, $f10                 \r\n"
-        "paddsh $f18, $f2, $f12                 \r\n"
-        "pmullh $f14, $f14, %[ff_pw_20]         \r\n"
-        "pmullh $f16, $f16, %[ff_pw_5]          \r\n"
-        "psubsh $f14, $f14, $f16                \r\n"
-        "paddsh $f18, $f14, $f18                \r\n"
-        "sdc1 $f18, 0(%[tmp])                   \r\n"
-        "dadd %[tmp], %[tmp], %[tmpStride]      \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "daddi $8, $8, -1                       \r\n"
-        "bnez $8, 1b                            \r\n"
-        : [tmp]"+&r"(tmp),[src]"+&r"(src)
-        : [tmpStride]"r"(8),[srcStride]"r"(srcStride),
-          [ff_pw_20]"f"(ff_pw_20),[ff_pw_5]"f"(ff_pw_5)
-        : "$8","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16","$f18"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dli        %[tmp0],    0x09                                    \n\t"
+        "1:                                                             \n\t"
+        "uld        %[low32],   -0x02(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   -0x01(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "uld        %[low32],   0x01(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        "uld        %[low32],   0x02(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        "uld        %[low32],   0x03(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp7],   %[ftmp3],       %[ftmp4]                \n\t"
+        "paddsh     %[ftmp8],   %[ftmp2],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp1],       %[ftmp6]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ff_pw_20]             \n\t"
+        "pmullh     %[ftmp8],   %[ftmp8],       %[ff_pw_5]              \n\t"
+        "psubsh     %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp7],       %[ftmp9]                \n\t"
+        "sdc1       %[ftmp9],   0x00(%[tmp])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        PTR_ADDU   "%[tmp],     %[tmp],         %[tmpStride]            \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp0),
+          [tmp]"+&r"(tmp),                  [src]"+&r"(src),
+          [low32]"=&r"(low32)
+        : [tmpStride]"r"(8),
+          [srcStride]"r"((mips_reg)srcStride),
+          [ff_pw_20]"f"(ff_pw_20),          [ff_pw_5]"f"(ff_pw_5)
+        : "memory"
     );
 
     tmp -= 28;
 
-    for(i=0; i<4; i++) {
+    for (i=0; i<4; i++) {
         const int16_t tmpB= tmp[-8];
         const int16_t tmpA= tmp[-4];
         const int16_t tmp0= tmp[ 0];
@@ -1373,161 +1412,590 @@ static void put_h264_qpel4_hv_lowpass_mmi(uint8_t *dst, const uint8_t *src,
     }
 }
 
-static void put_h264_qpel8_hv_lowpass_mmi(uint8_t *dst, const uint8_t *src,
-        int dstStride, int srcStride)
-{
-    int16_t _tmp[104];
-    int16_t *tmp = _tmp;
-    int i;
-    src -= 2*srcStride;
+static void put_h264_qpel8or16_hv1_lowpass_mmi(int16_t *tmp,
+        const uint8_t *src, ptrdiff_t tmpStride, ptrdiff_t srcStride, int size)
+{
+    int w = (size + 8) >> 2;
+    double ftmp[11];
+    uint64_t tmp0;
+    uint64_t low32;
+
+    src -= 2 * srcStride + 2;
+
+    while (w--) {
+        __asm__ volatile (
+            "dli        %[tmp0],    0x02                                \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "mtc1       %[tmp0],    %[ftmp10]                           \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp7]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp5]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "sdc1       %[ftmp6],   0x00(%[tmp])                        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "sdc1       %[ftmp6],   0x30(%[tmp])                        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "sdc1       %[ftmp6],   0x60(%[tmp])                        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "sdc1       %[ftmp6],   0x90(%[tmp])                        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp0],       %[ftmp1]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ftmp3]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "sdc1       %[ftmp6],   0xc0(%[tmp])                        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp1],       %[ftmp2]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ftmp4]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "sdc1       %[ftmp6],   0xf0(%[tmp])                        \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp5]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "sdc1       %[ftmp6],   0x120(%[tmp])                       \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "sdc1       %[ftmp6],   0x150(%[tmp])                       \n\t"
+            "bne        %[size],    0x10,           2f                  \n\t"
+
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "sdc1       %[ftmp6],   0x180(%[tmp])                       \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "sdc1       %[ftmp6],   0x1b0(%[tmp])                       \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp3]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp0],       %[ftmp1]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ftmp3]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "sdc1       %[ftmp6],   0x1e0(%[tmp])                       \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp4]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp1],       %[ftmp2]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ftmp4]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "sdc1       %[ftmp6],   0x210(%[tmp])                       \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp5]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp2],       %[ftmp3]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "sdc1       %[ftmp6],   0x240(%[tmp])                       \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp0]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp3],       %[ftmp4]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp5]            \n\t"
+            "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "sdc1       %[ftmp6],   0x270(%[tmp])                       \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp1]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp4],       %[ftmp5]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp0]            \n\t"
+            "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp1]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp2]            \n\t"
+            "sdc1       %[ftmp6],   0x2a0(%[tmp])                       \n\t"
+            "uld        %[low32],   0x00(%[src])                        \n\t"
+            "mtc1       %[low32],   %[ftmp2]                            \n\t"
+            "paddh      %[ftmp6],   %[ftmp5],       %[ftmp0]            \n\t"
+            "psllh      %[ftmp6],   %[ftmp6],       %[ftmp10]           \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]         \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp4]            \n\t"
+            "psubh      %[ftmp6],   %[ftmp6],       %[ftmp1]            \n\t"
+            "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "pmullh     %[ftmp6],   %[ftmp6],       %[ff_pw_5]          \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp2]            \n\t"
+            PTR_ADDU   "%[src],     %[src],         %[srcStride]        \n\t"
+            "paddh      %[ftmp6],   %[ftmp6],       %[ftmp3]            \n\t"
+            "sdc1       %[ftmp6],   0x2d0(%[tmp])                       \n\t"
+            "2:                                                         \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [ftmp8]"=&f"(ftmp[8]),        [ftmp9]"=&f"(ftmp[9]),
+              [ftmp10]"=&f"(ftmp[10]),
+              [tmp0]"=&r"(tmp0),
+              [src]"+&r"(src),
+              [low32]"=&r"(low32)
+            : [tmp]"r"(tmp),                [size]"r"(size),
+              [srcStride]"r"((mips_reg)srcStride),
+              [ff_pw_5]"f"(ff_pw_5),        [ff_pw_16]"f"(ff_pw_16)
+            : "memory"
+        );
+
+        tmp += 4;
+        src += 4 - (size + 5) * srcStride;
+    }
+}
+
+static void put_h264_qpel8or16_hv2_lowpass_mmi(uint8_t *dst,
+        int16_t *tmp, ptrdiff_t dstStride, ptrdiff_t tmpStride, int size)
+{
+    int w = size >> 4;
+    double ftmp[10];
+    uint64_t tmp0;
+
+    do {
+        int h = size;
+
+        __asm__ volatile (
+            "dli        %[tmp0],    0x02                                \n\t"
+            "mtc1       %[tmp0],    %[ftmp8]                            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "mtc1       %[tmp0],    %[ftmp9]                            \n\t"
+            "1:                                                         \n\t"
+            "ldc1       %[ftmp0],   0x00(%[tmp])                        \n\t"
+            "ldc1       %[ftmp3],   0x08(%[tmp])                        \n\t"
+            "ldc1       %[ftmp6],   0x10(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp1],   0x09(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x02(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp4],   0x11(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp4],   0x0a(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp5],   0x19(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp5],   0x12(%[tmp])                        \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp4]            \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp5]            \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ftmp6]            \n\t"
+            "gsldlc1    %[ftmp2],   0x0b(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp2],   0x04(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp6],   0x0d(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp6],   0x06(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp5],   0x13(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp5],   0x0c(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp7],   0x15(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp7],   0x0e(%[tmp])                        \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp6]            \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ftmp7]            \n\t"
+            "psubh      %[ftmp0],   %[ftmp0],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp3],   %[ftmp3],       %[ftmp4]            \n\t"
+            "psrah      %[ftmp0],   %[ftmp0],       %[ftmp8]            \n\t"
+            "psrah      %[ftmp3],   %[ftmp3],       %[ftmp8]            \n\t"
+            "psubh      %[ftmp0],   %[ftmp0],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp3],   %[ftmp3],       %[ftmp4]            \n\t"
+            "paddsh     %[ftmp0],   %[ftmp0],       %[ftmp2]            \n\t"
+            "paddsh     %[ftmp3] ,  %[ftmp3],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp0],   %[ftmp0],       %[ftmp8]            \n\t"
+            "psrah      %[ftmp3],   %[ftmp3],       %[ftmp8]            \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp0],   %[ftmp0],       %[ftmp9]            \n\t"
+            "psrah      %[ftmp3],   %[ftmp3],       %[ftmp9]            \n\t"
+            "packushb   %[ftmp0],   %[ftmp0],       %[ftmp3]            \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            "gssdlc1    %[ftmp0],   0x07(%[dst])                        \n\t"
+            "gssdrc1    %[ftmp0],   0x00(%[dst])                        \n\t"
+            PTR_ADDIU  "%[tmp],     %[tmp],         0x30                \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [ftmp8]"=&f"(ftmp[8]),        [ftmp9]"=&f"(ftmp[9]),
+              [tmp0]"=&r"(tmp0),
+              [tmp]"+&r"(tmp),              [dst]"+&r"(dst),
+              [h]"+&r"(h)
+            : [dstStride]"r"((mips_reg)dstStride)
+            : "memory"
+        );
+
+        tmp += 8 - size * 24;
+        dst += 8 - size * dstStride;
+    } while (w--);
+}
+
+static void put_h264_qpel8or16_hv_lowpass_mmi(uint8_t *dst, int16_t *tmp,
+        const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t tmpStride,
+        ptrdiff_t srcStride, int size)
+{
+    put_h264_qpel8or16_hv1_lowpass_mmi(tmp, src, tmpStride, srcStride, size);
+    put_h264_qpel8or16_hv2_lowpass_mmi(dst, tmp, dstStride, tmpStride, size);
+}
+
+static void put_h264_qpel8_hv_lowpass_mmi(uint8_t *dst, int16_t *tmp,
+        const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t tmpStride,
+        ptrdiff_t srcStride)
+{
+    put_h264_qpel8or16_hv_lowpass_mmi(dst, tmp, src, dstStride, tmpStride,
+            srcStride, 8);
+}
+
+static void put_h264_qpel16_hv_lowpass_mmi(uint8_t *dst, int16_t *tmp,
+        const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t tmpStride,
+        ptrdiff_t srcStride)
+{
+    put_h264_qpel8or16_hv_lowpass_mmi(dst, tmp, src, dstStride, tmpStride,
+            srcStride, 16);
+}
+
+static void put_h264_qpel8_h_lowpass_l2_mmi(uint8_t *dst, const uint8_t *src,
+        const uint8_t *src2, ptrdiff_t dstStride, ptrdiff_t src2Stride)
+{
+    int h = 8;
+    double ftmp[9];
+    uint64_t tmp[1];
+    uint64_t low32;
 
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "dli $8, 13                             \r\n"
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 5(%[src])                 \r\n"
-        "gsldrc1 $f2, -2(%[src])                \r\n"
-        "gsldlc1 $f4, 6(%[src])                 \r\n"
-        "gsldrc1 $f4, -1(%[src])                \r\n"
-        "gsldlc1 $f6, 7(%[src])                 \r\n"
-        "gsldrc1 $f6, 0(%[src])                 \r\n"
-        "gsldlc1 $f8, 8(%[src])                 \r\n"
-        "gsldrc1 $f8, 1(%[src])                 \r\n"
-        "gsldlc1 $f10, 9(%[src])                \r\n"
-        "gsldrc1 $f10, 2(%[src])                \r\n"
-        "gsldlc1 $f12, 10(%[src])               \r\n"
-        "gsldrc1 $f12, 3(%[src])                \r\n"
-        "punpcklbh $f1, $f2, $f0                \r\n"
-        "punpcklbh $f3, $f4, $f0                \r\n"
-        "punpcklbh $f5, $f6, $f0                \r\n"
-        "punpcklbh $f7, $f8, $f0                \r\n"
-        "punpcklbh $f9, $f10, $f0               \r\n"
-        "punpcklbh $f11, $f12, $f0              \r\n"
-        "punpckhbh $f2, $f2, $f0                \r\n"
-        "punpckhbh $f4, $f4, $f0                \r\n"
-        "punpckhbh $f6, $f6, $f0                \r\n"
-        "punpckhbh $f8, $f8, $f0                \r\n"
-        "punpckhbh $f10, $f10, $f0              \r\n"
-        "punpckhbh $f12, $f12, $f0              \r\n"
-        "paddsh $f13, $f5, $f7                  \r\n"
-        "paddsh $f15, $f3, $f9                 \r\n"
-        "paddsh $f17, $f1, $f11                 \r\n"
-        "pmullh $f13, $f13, %[ff_pw_20]         \r\n"
-        "pmullh $f15, $f15, %[ff_pw_5]          \r\n"
-        "psubsh $f13, $f13, $f15                \r\n"
-        "paddsh $f17, $f13, $f17                \r\n"
-        "paddsh $f14, $f6, $f8                  \r\n"
-        "paddsh $f16, $f4, $f10                 \r\n"
-        "paddsh $f18, $f2, $f12                 \r\n"
-        "pmullh $f14, $f14, %[ff_pw_20]         \r\n"
-        "pmullh $f16, $f16, %[ff_pw_5]          \r\n"
-        "psubsh $f14, $f14, $f16                \r\n"
-        "paddsh $f18, $f14, $f18                \r\n"
-        "sdc1 $f17, 0(%[tmp])                   \r\n"
-        "sdc1 $f18, 8(%[tmp])                   \r\n"
-        "dadd %[tmp], %[tmp], %[tmpStride]      \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "daddi $8, $8, -1                       \r\n"
-        "bnez $8, 1b                            \r\n"
-        : [tmp]"+&r"(tmp),[src]"+&r"(src)
-        : [tmpStride]"r"(16),[srcStride]"r"(srcStride),
-          [ff_pw_20]"f"(ff_pw_20),[ff_pw_5]"f"(ff_pw_5)
-        : "$8","$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7","$f8","$f9",
-          "$f10","$f11","$f12","$f13","$f14","$f15","$f16","$f17","$f18"
+        "dli        %[tmp0],    0x02                                    \n\t"
+        "mtc1       %[tmp0],    %[ftmp7]                                \n\t"
+        "dli        %[tmp0],    0x05                                    \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "mtc1       %[tmp0],    %[ftmp8]                                \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        "gsldlc1    %[ftmp3],   0x08(%[src])                            \n\t"
+        "gsldrc1    %[ftmp3],   0x01(%[src])                            \n\t"
+        "punpckhbh  %[ftmp2],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp4],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "psllh      %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "psllh      %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "gsldlc1    %[ftmp3],   0x06(%[src])                            \n\t"
+        "gsldrc1    %[ftmp3],   -0x01(%[src])                           \n\t"
+        "gsldlc1    %[ftmp5],   0x09(%[src])                            \n\t"
+        "gsldrc1    %[ftmp5],   0x02(%[src])                            \n\t"
+        "punpckhbh  %[ftmp4],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp6],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "psubh      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[ff_pw_5]              \n\t"
+        "pmullh     %[ftmp1],   %[ftmp1],       %[ff_pw_5]              \n\t"
+        "uld        %[low32],   -0x02(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "uld        %[low32],   0x07(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "paddh      %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ff_pw_16]             \n\t"
+        "paddh      %[ftmp5],   %[ftmp5],       %[ff_pw_16]             \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "psrah      %[ftmp1],   %[ftmp1],       %[ftmp8]                \n\t"
+        "psrah      %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[src2])                           \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[src2])                           \n\t"
+        "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[dstStride]            \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        PTR_ADDU   "%[h],       %[h],           -0x01                   \n\t"
+        "sdc1       %[ftmp1],   0x00(%[dst])                            \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[src2Stride]           \n\t"
+        "bgtz       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),
+          [tmp0]"=&r"(tmp[0]),
+          [src]"+&r"(src),                  [dst]"+&r"(dst),
+          [src2]"+&r"(src2),                [h]"+&r"(h),
+          [low32]"=&r"(low32)
+        : [src2Stride]"r"((mips_reg)src2Stride),
+          [dstStride]"r"((mips_reg)dstStride),
+          [ff_pw_5]"f"(ff_pw_5),            [ff_pw_16]"f"(ff_pw_16)
+        : "memory"
     );
-
-    tmp -= 88;
-
-    for(i=0; i<8; i++) {
-        const int tmpB= tmp[-16];
-        const int tmpA= tmp[ -8];
-        const int tmp0= tmp[  0];
-        const int tmp1= tmp[  8];
-        const int tmp2= tmp[ 16];
-        const int tmp3= tmp[ 24];
-        const int tmp4= tmp[ 32];
-        const int tmp5= tmp[ 40];
-        const int tmp6= tmp[ 48];
-        const int tmp7= tmp[ 56];
-        const int tmp8= tmp[ 64];
-        const int tmp9= tmp[ 72];
-        const int tmp10=tmp[ 80];
-        op2_put(dst[0*dstStride], (tmp0+tmp1)*20 - (tmpA+tmp2)*5 + (tmpB+tmp3));
-        op2_put(dst[1*dstStride], (tmp1+tmp2)*20 - (tmp0+tmp3)*5 + (tmpA+tmp4));
-        op2_put(dst[2*dstStride], (tmp2+tmp3)*20 - (tmp1+tmp4)*5 + (tmp0+tmp5));
-        op2_put(dst[3*dstStride], (tmp3+tmp4)*20 - (tmp2+tmp5)*5 + (tmp1+tmp6));
-        op2_put(dst[4*dstStride], (tmp4+tmp5)*20 - (tmp3+tmp6)*5 + (tmp2+tmp7));
-        op2_put(dst[5*dstStride], (tmp5+tmp6)*20 - (tmp4+tmp7)*5 + (tmp3+tmp8));
-        op2_put(dst[6*dstStride], (tmp6+tmp7)*20 - (tmp5+tmp8)*5 + (tmp4+tmp9));
-        op2_put(dst[7*dstStride], (tmp7+tmp8)*20 - (tmp6+tmp9)*5 + (tmp5+tmp10));
-        dst++;
-        tmp++;
-    }
 }
 
-static void put_h264_qpel16_hv_lowpass_mmi(uint8_t *dst, const uint8_t *src,
-        int dstStride, int srcStride)
-{
-    put_h264_qpel8_hv_lowpass_mmi(dst, src, dstStride, srcStride);
-    put_h264_qpel8_hv_lowpass_mmi(dst+8, src+8, dstStride, srcStride);
-    src += 8*srcStride;
-    dst += 8*dstStride;
-    put_h264_qpel8_hv_lowpass_mmi(dst, src, dstStride, srcStride);
-    put_h264_qpel8_hv_lowpass_mmi(dst+8, src+8, dstStride, srcStride);
+static void put_pixels8_l2_shift5_mmi(uint8_t *dst, int16_t *src16,
+        const uint8_t *src8, ptrdiff_t dstStride, ptrdiff_t src8Stride, int h)
+{
+    double ftmp[7];
+    uint64_t tmp0;
+
+    do {
+        __asm__ volatile (
+            "dli        %[tmp0],    0x05                                \n\t"
+            "gsldlc1    %[ftmp0],   0x07(%[src16])                      \n\t"
+            "gsldrc1    %[ftmp0],   0x00(%[src16])                      \n\t"
+            "mtc1       %[tmp0],    %[ftmp6]                            \n\t"
+            "gsldlc1    %[ftmp1],   0x0f(%[src16])                      \n\t"
+            "gsldrc1    %[ftmp1],   0x08(%[src16])                      \n\t"
+            "gsldlc1    %[ftmp2],   0x37(%[src16])                      \n\t"
+            "gsldrc1    %[ftmp2],   0x30(%[src16])                      \n\t"
+            "gsldlc1    %[ftmp3],   0x3f(%[src16])                      \n\t"
+            "gsldrc1    %[ftmp3],   0x38(%[src16])                      \n\t"
+            "psrah      %[ftmp0],   %[ftmp0],       %[ftmp6]            \n\t"
+            "psrah      %[ftmp1],   %[ftmp1],       %[ftmp6]            \n\t"
+            "psrah      %[ftmp2],   %[ftmp2],       %[ftmp6]            \n\t"
+            "psrah      %[ftmp3],   %[ftmp3],       %[ftmp6]            \n\t"
+            "packushb   %[ftmp0],   %[ftmp0],       %[ftmp1]            \n\t"
+            "packushb   %[ftmp2],   %[ftmp2],       %[ftmp3]            \n\t"
+            "ldc1       %[ftmp5],   0x00(%[src8])                       \n\t"
+            "gsldxc1    %[ftmp4],   0x00(%[src8],   %[src8Stride])      \n\t"
+            "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp5]            \n\t"
+            "pavgb      %[ftmp2],   %[ftmp2],       %[ftmp4]            \n\t"
+            "sdc1       %[ftmp0],   0x00(%[dst])                        \n\t"
+            "gssdxc1    %[ftmp2],   0x00(%[dst],    %[dstStride])       \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),
+              [tmp0]"=&r"(tmp0)
+            : [src8]"r"(src8),              [src16]"r"(src16),
+              [dst]"r"(dst),
+              [src8Stride]"r"((mips_reg)src8Stride),
+              [dstStride]"r"((mips_reg)dstStride)
+            : "memory"
+        );
+
+        src8  += 2 * src8Stride;
+        src16 += 48;
+        dst   += 2 * dstStride;
+    } while (h -= 2);
+}
+
+static void put_h264_qpel16_h_lowpass_l2_mmi(uint8_t *dst, const uint8_t *src,
+        const uint8_t *src2, ptrdiff_t dstStride, ptrdiff_t src2Stride)
+{
+    put_h264_qpel8_h_lowpass_l2_mmi(dst, src, src2, dstStride, src2Stride);
+    put_h264_qpel8_h_lowpass_l2_mmi(dst + 8, src + 8, src2 + 8, dstStride,
+            src2Stride);
+
+    src += 8 * dstStride;
+    dst += 8 * dstStride;
+    src2 += 8 * src2Stride;
+
+    put_h264_qpel8_h_lowpass_l2_mmi(dst, src, src2, dstStride, src2Stride);
+    put_h264_qpel8_h_lowpass_l2_mmi(dst + 8, src + 8, src2 + 8, dstStride,
+            src2Stride);
+}
+
+static void put_pixels16_l2_shift5_mmi(uint8_t *dst, int16_t *src16,
+        const uint8_t *src8, ptrdiff_t dstStride, ptrdiff_t src8Stride, int h)
+{
+    put_pixels8_l2_shift5_mmi(dst, src16, src8, dstStride, src8Stride, h);
+    put_pixels8_l2_shift5_mmi(dst + 8, src16 + 8, src8 + 8, dstStride,
+            src8Stride, h);
 }
 
 static void avg_h264_qpel4_hv_lowpass_mmi(uint8_t *dst, const uint8_t *src,
         int dstStride, int srcStride)
 {
+    INIT_CLIP
     int i;
     int16_t _tmp[36];
     int16_t *tmp = _tmp;
+    double ftmp[10];
+    uint64_t tmp0;
+    uint64_t low32;
+
     src -= 2*srcStride;
 
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "dli $8, 9                              \r\n"
-        "1:                                     \r\n"
-        "gslwlc1 $f2, 1(%[src])                 \r\n"
-        "gslwrc1 $f2, -2(%[src])                \r\n"
-        "gslwlc1 $f4, 2(%[src])                 \r\n"
-        "gslwrc1 $f4, -1(%[src])                \r\n"
-        "gslwlc1 $f6, 3(%[src])                 \r\n"
-        "gslwrc1 $f6, 0(%[src])                 \r\n"
-        "gslwlc1 $f8, 4(%[src])                 \r\n"
-        "gslwrc1 $f8, 1(%[src])                 \r\n"
-        "gslwlc1 $f10, 5(%[src])                \r\n"
-        "gslwrc1 $f10, 2(%[src])                \r\n"
-        "gslwlc1 $f12, 6(%[src])                \r\n"
-        "gslwrc1 $f12, 3(%[src])                \r\n"
-        "punpcklbh $f2, $f2, $f0                \r\n"
-        "punpcklbh $f4, $f4, $f0                \r\n"
-        "punpcklbh $f6, $f6, $f0                \r\n"
-        "punpcklbh $f8, $f8, $f0                \r\n"
-        "punpcklbh $f10, $f10, $f0              \r\n"
-        "punpcklbh $f12, $f12, $f0              \r\n"
-        "paddsh $f14, $f6, $f8                  \r\n"
-        "paddsh $f16, $f4, $f10                 \r\n"
-        "paddsh $f18, $f2, $f12                 \r\n"
-        "pmullh $f14, $f14, %[ff_pw_20]         \r\n"
-        "pmullh $f16, $f16, %[ff_pw_5]          \r\n"
-        "psubsh $f14, $f14, $f16                \r\n"
-        "paddsh $f18, $f14, $f18                \r\n"
-        "sdc1 $f18, 0(%[tmp])                   \r\n"
-        "dadd %[tmp], %[tmp], %[tmpStride]      \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "daddi $8, $8, -1                       \r\n"
-        "bnez $8, 1b                            \r\n"
-        : [tmp]"+&r"(tmp),[src]"+&r"(src)
-        : [tmpStride]"r"(8),[srcStride]"r"(srcStride),
-          [ff_pw_20]"f"(ff_pw_20),[ff_pw_5]"f"(ff_pw_5)
-        : "$8","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16","$f18"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dli        %[tmp0],    0x09                                    \n\t"
+        "1:                                                             \n\t"
+        "uld        %[low32],   -0x02(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   -0x01(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "uld        %[low32],   0x00(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "uld        %[low32],   0x01(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        "uld        %[low32],   0x02(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        "uld        %[low32],   0x03(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "paddsh     %[ftmp7],   %[ftmp3],       %[ftmp4]                \n\t"
+        "paddsh     %[ftmp8],   %[ftmp2],       %[ftmp5]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp1],       %[ftmp6]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ff_pw_20]             \n\t"
+        "pmullh     %[ftmp8],   %[ftmp8],       %[ff_pw_5]              \n\t"
+        "psubsh     %[ftmp7],   %[ftmp7],       %[ftmp8]                \n\t"
+        "paddsh     %[ftmp9],   %[ftmp7],       %[ftmp9]                \n\t"
+        "sdc1       %[ftmp9],   0x00(%[tmp])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[srcStride]            \n\t"
+        PTR_ADDU   "%[tmp],     %[tmp],         %[tmpStride]            \n\t"
+        "bnez       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp0),
+          [tmp]"+&r"(tmp),                  [src]"+&r"(src),
+          [low32]"=&r"(low32)
+        : [tmpStride]"r"(8),
+          [srcStride]"r"((mips_reg)srcStride),
+          [ff_pw_20]"f"(ff_pw_20),          [ff_pw_5]"f"(ff_pw_5)
+        : "memory"
     );
 
     tmp -= 28;
 
-    for(i=0; i<4; i++)
-    {
+    for (i=0; i<4; i++) {
         const int16_t tmpB= tmp[-8];
         const int16_t tmpA= tmp[-4];
         const int16_t tmp0= tmp[ 0];
@@ -1546,114 +2014,272 @@ static void avg_h264_qpel4_hv_lowpass_mmi(uint8_t *dst, const uint8_t *src,
     }
 }
 
-static void avg_h264_qpel8_hv_lowpass_mmi(uint8_t *dst, const uint8_t *src,
-        int dstStride, int srcStride)
-{
-    int16_t _tmp[104];
-    int16_t *tmp = _tmp;
-    int i;
-    src -= 2*srcStride;
+static void avg_h264_qpel8or16_hv2_lowpass_mmi(uint8_t *dst,
+        int16_t *tmp, ptrdiff_t dstStride, ptrdiff_t tmpStride, int size)
+{
+    int w = size >> 4;
+    double ftmp[11];
+    uint64_t tmp0;
+
+    do {
+        int h = size;
+        __asm__ volatile (
+            "dli        %[tmp0],    0x02                                \n\t"
+            "mtc1       %[tmp0],    %[ftmp9]                            \n\t"
+            "dli        %[tmp0],    0x06                                \n\t"
+            "mtc1       %[tmp0],    %[ftmp10]                           \n\t"
+            "1:                                                         \n\t"
+            "ldc1       %[ftmp0],   0x00(%[tmp])                        \n\t"
+            "ldc1       %[ftmp3],   0x08(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp1],   0x09(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp1],   0x02(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp4],   0x11(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp4],   0x0a(%[tmp])                        \n\t"
+            "ldc1       %[ftmp7],   0x10(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp8],   0x19(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp8],   0x12(%[tmp])                        \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp4]            \n\t"
+            "paddh      %[ftmp1],   %[ftmp1],       %[ftmp3]            \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp8]            \n\t"
+            "paddh      %[ftmp4],   %[ftmp4],       %[ftmp7]            \n\t"
+            "gsldlc1    %[ftmp2],   0x0b(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp2],   0x04(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp5],   0x13(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp5],   0x0c(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp7],   0x0d(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp7],   0x06(%[tmp])                        \n\t"
+            "gsldlc1    %[ftmp8],   0x15(%[tmp])                        \n\t"
+            "gsldrc1    %[ftmp8],   0x0e(%[tmp])                        \n\t"
+            "paddh      %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "paddh      %[ftmp5],   %[ftmp5],       %[ftmp8]            \n\t"
+            "psubh      %[ftmp0],   %[ftmp0],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp3],   %[ftmp3],       %[ftmp4]            \n\t"
+            "psrah      %[ftmp0],   %[ftmp0],       %[ftmp9]            \n\t"
+            "psrah      %[ftmp3],   %[ftmp3],       %[ftmp9]            \n\t"
+            "psubh      %[ftmp0],   %[ftmp0],       %[ftmp1]            \n\t"
+            "psubh      %[ftmp3],   %[ftmp3],       %[ftmp4]            \n\t"
+            "paddsh     %[ftmp0],   %[ftmp0],       %[ftmp2]            \n\t"
+            "paddsh     %[ftmp3],   %[ftmp3],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp0],   %[ftmp0],       %[ftmp9]            \n\t"
+            "psrah      %[ftmp3],   %[ftmp3],       %[ftmp9]            \n\t"
+            "paddh      %[ftmp0],   %[ftmp0],       %[ftmp2]            \n\t"
+            "paddh      %[ftmp3],   %[ftmp3],       %[ftmp5]            \n\t"
+            "psrah      %[ftmp0],   %[ftmp0],       %[ftmp10]           \n\t"
+            "psrah      %[ftmp3],   %[ftmp3],       %[ftmp10]           \n\t"
+            "packushb   %[ftmp0],   %[ftmp0],       %[ftmp3]            \n\t"
+            "ldc1       %[ftmp6],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp6]            \n\t"
+            "sdc1       %[ftmp0],   0x00(%[dst])                        \n\t"
+            "addi       %[h],       %[h],           -0x01               \n\t"
+            PTR_ADDI   "%[tmp],     %[tmp],         0x30                \n\t"
+            PTR_ADDU   "%[dst],     %[dst],         %[dstStride]        \n\t"
+            "bnez       %[h],       1b                                  \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [ftmp8]"=&f"(ftmp[8]),        [ftmp9]"=&f"(ftmp[9]),
+              [ftmp10]"=&f"(ftmp[10]),
+              [tmp0]"=&r"(tmp0),
+              [tmp]"+&r"(tmp),              [dst]"+&r"(dst),
+              [h]"+&r"(h)
+            : [dstStride]"r"((mips_reg)dstStride)
+            : "memory"
+        );
+
+        tmp += 8 - size * 24;
+        dst += 8 - size * dstStride;
+    } while (w--);
+}
+
+static void avg_h264_qpel8or16_hv_lowpass_mmi(uint8_t *dst, int16_t *tmp,
+        const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t tmpStride,
+        ptrdiff_t srcStride, int size)
+{
+    put_h264_qpel8or16_hv1_lowpass_mmi(tmp, src, tmpStride, srcStride, size);
+    avg_h264_qpel8or16_hv2_lowpass_mmi(dst, tmp, dstStride, tmpStride, size);
+}
+
+static void avg_h264_qpel8_hv_lowpass_mmi(uint8_t *dst, int16_t *tmp,
+        const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t tmpStride,
+        ptrdiff_t srcStride)
+{
+    avg_h264_qpel8or16_hv_lowpass_mmi(dst, tmp, src, dstStride, tmpStride,
+            srcStride, 8);
+}
+
+static void avg_h264_qpel16_hv_lowpass_mmi(uint8_t *dst, int16_t *tmp,
+        const uint8_t *src, ptrdiff_t dstStride, ptrdiff_t tmpStride,
+        ptrdiff_t srcStride)
+{
+    avg_h264_qpel8or16_hv_lowpass_mmi(dst, tmp, src, dstStride, tmpStride,
+            srcStride, 16);
+}
+
+static void avg_h264_qpel8_h_lowpass_l2_mmi(uint8_t *dst, const uint8_t *src,
+        const uint8_t *src2, ptrdiff_t dstStride, ptrdiff_t src2Stride)
+{
+    double ftmp[10];
+    uint64_t tmp[2];
+    uint64_t low32;
 
     __asm__ volatile (
-        "xor $f0, $f0, $f0                      \r\n"
-        "dli $8, 13                             \r\n"
-        "1:                                     \r\n"
-        "gsldlc1 $f2, 5(%[src])                 \r\n"
-        "gsldrc1 $f2, -2(%[src])                \r\n"
-        "gsldlc1 $f4, 6(%[src])                 \r\n"
-        "gsldrc1 $f4, -1(%[src])                \r\n"
-        "gsldlc1 $f6, 7(%[src])                 \r\n"
-        "gsldrc1 $f6, 0(%[src])                 \r\n"
-        "gsldlc1 $f8, 8(%[src])                 \r\n"
-        "gsldrc1 $f8, 1(%[src])                 \r\n"
-        "gsldlc1 $f10, 9(%[src])                \r\n"
-        "gsldrc1 $f10, 2(%[src])                \r\n"
-        "gsldlc1 $f12, 10(%[src])               \r\n"
-        "gsldrc1 $f12, 3(%[src])                \r\n"
-        "punpcklbh $f1, $f2, $f0                \r\n"
-        "punpcklbh $f3, $f4, $f0                \r\n"
-        "punpcklbh $f5, $f6, $f0                \r\n"
-        "punpcklbh $f7, $f8, $f0                \r\n"
-        "punpcklbh $f9, $f10, $f0               \r\n"
-        "punpcklbh $f11, $f12, $f0              \r\n"
-        "punpckhbh $f2, $f2, $f0                \r\n"
-        "punpckhbh $f4, $f4, $f0                \r\n"
-        "punpckhbh $f6, $f6, $f0                \r\n"
-        "punpckhbh $f8, $f8, $f0                \r\n"
-        "punpckhbh $f10, $f10, $f0              \r\n"
-        "punpckhbh $f12, $f12, $f0              \r\n"
-        "paddsh $f13, $f5, $f7                  \r\n"
-        "paddsh $f15, $f3, $f9                 \r\n"
-        "paddsh $f17, $f1, $f11                 \r\n"
-        "pmullh $f13, $f13, %[ff_pw_20]         \r\n"
-        "pmullh $f15, $f15, %[ff_pw_5]          \r\n"
-        "psubsh $f13, $f13, $f15                \r\n"
-        "paddsh $f17, $f13, $f17                \r\n"
-        "paddsh $f14, $f6, $f8                  \r\n"
-        "paddsh $f16, $f4, $f10                 \r\n"
-        "paddsh $f18, $f2, $f12                 \r\n"
-        "pmullh $f14, $f14, %[ff_pw_20]         \r\n"
-        "pmullh $f16, $f16, %[ff_pw_5]          \r\n"
-        "psubsh $f14, $f14, $f16                \r\n"
-        "paddsh $f18, $f14, $f18                \r\n"
-
-        "sdc1 $f17, 0(%[tmp])                   \r\n"
-        "sdc1 $f18, 8(%[tmp])                   \r\n"
-        "dadd %[tmp], %[tmp], %[tmpStride]      \r\n"
-        "dadd %[src], %[src], %[srcStride]      \r\n"
-        "daddi $8, $8, -1                       \r\n"
-        "bnez $8, 1b                            \r\n"
-        : [tmp]"+&r"(tmp),[src]"+&r"(src)
-        : [tmpStride]"r"(16),[srcStride]"r"(srcStride),
-          [ff_pw_20]"f"(ff_pw_20),[ff_pw_5]"f"(ff_pw_5)
-        : "$8","$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7","$f8","$f9",
-          "$f10","$f11","$f12","$f13","$f14","$f15","$f16","$f17","$f18"
+        "dli        %[tmp1],    0x02                                    \n\t"
+        "ori        %[tmp0],    $0,             0x8                     \n\t"
+        "mtc1       %[tmp1],    %[ftmp7]                                \n\t"
+        "dli        %[tmp1],    0x05                                    \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "mtc1       %[tmp1],    %[ftmp8]                                \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[src])                            \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[src])                            \n\t"
+        "gsldlc1    %[ftmp2],   0x08(%[src])                            \n\t"
+        "gsldrc1    %[ftmp2],   0x01(%[src])                            \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp4],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psllh      %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "psllh      %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "gsldlc1    %[ftmp2],   0x06(%[src])                            \n\t"
+        "gsldrc1    %[ftmp2],   -0x01(%[src])                           \n\t"
+        "gsldlc1    %[ftmp5],   0x09(%[src])                            \n\t"
+        "gsldrc1    %[ftmp5],   0x02(%[src])                            \n\t"
+        "punpckhbh  %[ftmp4],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp6],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp5]                \n\t"
+        "paddh      %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+        "psubh      %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp6]                \n\t"
+        "pmullh     %[ftmp1],   %[ftmp1],       %[ff_pw_5]              \n\t"
+        "pmullh     %[ftmp3],   %[ftmp3],       %[ff_pw_5]              \n\t"
+        "uld        %[low32],   -0x02(%[src])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "uld        %[low32],   0x07(%[src])                            \n\t"
+        "mtc1       %[low32],   %[ftmp6]                                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "paddh      %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ff_pw_16]             \n\t"
+        "paddh      %[ftmp5],   %[ftmp5],       %[ff_pw_16]             \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "psrah      %[ftmp1],   %[ftmp1],       %[ftmp8]                \n\t"
+        "psrah      %[ftmp3],   %[ftmp3],       %[ftmp8]                \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[src2])                           \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[src2])                           \n\t"
+        "packushb   %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "ldc1       %[ftmp9],   0x00(%[dst])                            \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp9]                \n\t"
+        PTR_ADDU   "%[src],     %[src],         %[dstStride]            \n\t"
+        "sdc1       %[ftmp1],   0x00(%[dst])                            \n\t"
+        "daddi      %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[dstStride]            \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[src2Stride]           \n\t"
+        "bgtz       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [dst]"+&r"(dst),                  [src]"+&r"(src),
+          [src2]"+&r"(src2),
+          [low32]"=&r"(low32)
+        : [dstStride]"r"((mips_reg)dstStride),
+          [src2Stride]"r"((mips_reg)src2Stride),
+          [ff_pw_5]"f"(ff_pw_5),            [ff_pw_16]"f"(ff_pw_16)
+        : "memory"
     );
-
-    tmp -= 88;
-
-    for(i=0; i<8; i++) {
-        const int tmpB= tmp[-16];
-        const int tmpA= tmp[ -8];
-        const int tmp0= tmp[  0];
-        const int tmp1= tmp[  8];
-        const int tmp2= tmp[ 16];
-        const int tmp3= tmp[ 24];
-        const int tmp4= tmp[ 32];
-        const int tmp5= tmp[ 40];
-        const int tmp6= tmp[ 48];
-        const int tmp7= tmp[ 56];
-        const int tmp8= tmp[ 64];
-        const int tmp9= tmp[ 72];
-        const int tmp10=tmp[ 80];
-        op2_avg(dst[0*dstStride], (tmp0+tmp1)*20 - (tmpA+tmp2)*5 + (tmpB+tmp3));
-        op2_avg(dst[1*dstStride], (tmp1+tmp2)*20 - (tmp0+tmp3)*5 + (tmpA+tmp4));
-        op2_avg(dst[2*dstStride], (tmp2+tmp3)*20 - (tmp1+tmp4)*5 + (tmp0+tmp5));
-        op2_avg(dst[3*dstStride], (tmp3+tmp4)*20 - (tmp2+tmp5)*5 + (tmp1+tmp6));
-        op2_avg(dst[4*dstStride], (tmp4+tmp5)*20 - (tmp3+tmp6)*5 + (tmp2+tmp7));
-        op2_avg(dst[5*dstStride], (tmp5+tmp6)*20 - (tmp4+tmp7)*5 + (tmp3+tmp8));
-        op2_avg(dst[6*dstStride], (tmp6+tmp7)*20 - (tmp5+tmp8)*5 + (tmp4+tmp9));
-        op2_avg(dst[7*dstStride], (tmp7+tmp8)*20 - (tmp6+tmp9)*5 + (tmp5+tmp10));
-        dst++;
-        tmp++;
-    }
 }
 
-static void avg_h264_qpel16_hv_lowpass_mmi(uint8_t *dst, const uint8_t *src,
-        int dstStride, int srcStride){
-    avg_h264_qpel8_hv_lowpass_mmi(dst, src, dstStride, srcStride);
-    avg_h264_qpel8_hv_lowpass_mmi(dst+8, src+8, dstStride, srcStride);
-    src += 8*srcStride;
-    dst += 8*dstStride;
-    avg_h264_qpel8_hv_lowpass_mmi(dst, src, dstStride, srcStride);
-    avg_h264_qpel8_hv_lowpass_mmi(dst+8, src+8, dstStride, srcStride);
+static void avg_h264_qpel16_h_lowpass_l2_mmi(uint8_t *dst, const uint8_t *src,
+        const uint8_t *src2, ptrdiff_t dstStride, ptrdiff_t src2Stride)
+{
+    avg_h264_qpel8_h_lowpass_l2_mmi(dst, src, src2, dstStride, src2Stride);
+    avg_h264_qpel8_h_lowpass_l2_mmi(dst + 8, src + 8, src2 + 8, dstStride,
+            src2Stride);
+
+    src += 8 * dstStride;
+    dst += 8 * dstStride;
+    src2 += 8 * src2Stride;
+
+    avg_h264_qpel8_h_lowpass_l2_mmi(dst, src, src2, dstStride, src2Stride);
+    avg_h264_qpel8_h_lowpass_l2_mmi(dst + 8, src + 8, src2 + 8, dstStride,
+            src2Stride);
+}
+
+static void avg_pixels8_l2_shift5_mmi(uint8_t *dst, int16_t *src16,
+        const uint8_t *src8, ptrdiff_t dstStride, ptrdiff_t src8Stride, int b)
+{
+    double ftmp[8];
+    uint64_t tmp0;
+
+    do {
+        __asm__ volatile (
+            "dli        %[tmp0],    0x05                                \n\t"
+            "gsldlc1    %[ftmp0],   0x07(%[src16])                      \n\t"
+            "gsldrc1    %[ftmp0],   0x00(%[src16])                      \n\t"
+            "mtc1       %[tmp0],    %[ftmp6]                            \n\t"
+            "gsldlc1    %[ftmp1],   0x0f(%[src16])                      \n\t"
+            "gsldrc1    %[ftmp1],   0x08(%[src16])                      \n\t"
+            "gsldlc1    %[ftmp2],   0x37(%[src16])                      \n\t"
+            "gsldrc1    %[ftmp2],   0x30(%[src16])                      \n\t"
+            "gsldlc1    %[ftmp3],   0x3f(%[src16])                      \n\t"
+            "gsldrc1    %[ftmp3],   0x38(%[src16])                      \n\t"
+            "psrah      %[ftmp0],   %[ftmp0],       %[ftmp6]            \n\t"
+            "psrah      %[ftmp1],   %[ftmp1],       %[ftmp6]            \n\t"
+            "psrah      %[ftmp2],   %[ftmp2],       %[ftmp6]            \n\t"
+            "psrah      %[ftmp3],   %[ftmp3],       %[ftmp6]            \n\t"
+            "packushb   %[ftmp0],   %[ftmp0],       %[ftmp1]            \n\t"
+            "ldc1       %[ftmp4],   0x00(%[src8])                       \n\t"
+            "gsldxc1    %[ftmp5],   0x00(%[src8],   %[src8Stride])      \n\t"
+            "packushb   %[ftmp2],   %[ftmp2],       %[ftmp3]            \n\t"
+            "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp4]            \n\t"
+            "pavgb      %[ftmp2],   %[ftmp2],       %[ftmp5]            \n\t"
+            "ldc1       %[ftmp7],   0x00(%[dst])                        \n\t"
+            "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp7]            \n\t"
+            "sdc1       %[ftmp0],   0x00(%[dst])                        \n\t"
+            "gsldxc1    %[ftmp7],   0x00(%[dst],    %[dstStride])       \n\t"
+            "pavgb      %[ftmp2],   %[ftmp2],       %[ftmp7]            \n\t"
+            "gssdxc1    %[ftmp2],   0x00(%[dst],    %[dstStride])       \n\t"
+            : [ftmp0]"=&f"(ftmp[0]),        [ftmp1]"=&f"(ftmp[1]),
+              [ftmp2]"=&f"(ftmp[2]),        [ftmp3]"=&f"(ftmp[3]),
+              [ftmp4]"=&f"(ftmp[4]),        [ftmp5]"=&f"(ftmp[5]),
+              [ftmp6]"=&f"(ftmp[6]),        [ftmp7]"=&f"(ftmp[7]),
+              [tmp0]"=&r"(tmp0)
+            : [src8]"r"(src8),              [src16]"r"(src16),
+              [dst]"r"(dst),
+              [src8Stride]"r"((mips_reg)src8Stride),
+              [dstStride]"r"((mips_reg)dstStride)
+            : "memory"
+        );
+
+        src8  += 2 * src8Stride;
+        src16 += 48;
+        dst   += 2 * dstStride;
+    } while (b -= 2);
+}
+
+static void avg_pixels16_l2_shift5_mmi(uint8_t *dst, int16_t *src16,
+        const uint8_t *src8, ptrdiff_t dstStride, ptrdiff_t src8Stride, int b)
+{
+    avg_pixels8_l2_shift5_mmi(dst, src16, src8, dstStride, src8Stride, b);
+    avg_pixels8_l2_shift5_mmi(dst + 8, src16 + 8, src8 + 8, dstStride,
+            src8Stride, b);
 }
 
 //DEF_H264_MC_MMI(put_, 4)
 void ff_put_h264_qpel4_mc00_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    put_pixels4_mmi(dst, src, stride, 4);
+    ff_put_pixels4_8_mmi(dst, src, stride, 4);
 }
 
 void ff_put_h264_qpel4_mc10_mmi(uint8_t *dst, const uint8_t *src,
@@ -1661,7 +2287,7 @@ void ff_put_h264_qpel4_mc10_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[16];
     put_h264_qpel4_h_lowpass_mmi(half, src, 4, stride);
-    put_pixels4_l2_mmi(dst, src, half, stride, stride, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, src, half, stride, stride, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc20_mmi(uint8_t *dst, const uint8_t *src,
@@ -1675,7 +2301,7 @@ void ff_put_h264_qpel4_mc30_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[16];
     put_h264_qpel4_h_lowpass_mmi(half, src, 4, stride);
-    put_pixels4_l2_mmi(dst, src+1, half, stride, stride, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, src+1, half, stride, stride, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc01_mmi(uint8_t *dst, const uint8_t *src,
@@ -1686,7 +2312,7 @@ void ff_put_h264_qpel4_mc01_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[16];
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(half, full_mid, 4, 4);
-    put_pixels4_l2_mmi(dst, full_mid, half, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, full_mid, half, stride, 4, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc02_mmi(uint8_t *dst, const uint8_t *src,
@@ -1706,7 +2332,7 @@ void ff_put_h264_qpel4_mc03_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[16];
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(half, full_mid, 4, 4);
-    put_pixels4_l2_mmi(dst, full_mid+4, half, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, full_mid+4, half, stride, 4, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc11_mmi(uint8_t *dst, const uint8_t *src,
@@ -1719,7 +2345,7 @@ void ff_put_h264_qpel4_mc11_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel4_h_lowpass_mmi(halfH, src, 4, stride);
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
-    put_pixels4_l2_mmi(dst, halfH, halfV, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, halfH, halfV, stride, 4, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc31_mmi(uint8_t *dst, const uint8_t *src,
@@ -1732,7 +2358,7 @@ void ff_put_h264_qpel4_mc31_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel4_h_lowpass_mmi(halfH, src, 4, stride);
     copy_block4_mmi(full, src - stride*2 + 1, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
-    put_pixels4_l2_mmi(dst, halfH, halfV, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, halfH, halfV, stride, 4, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc13_mmi(uint8_t *dst, const uint8_t *src,
@@ -1745,7 +2371,7 @@ void ff_put_h264_qpel4_mc13_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel4_h_lowpass_mmi(halfH, src + stride, 4, stride);
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
-    put_pixels4_l2_mmi(dst, halfH, halfV, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, halfH, halfV, stride, 4, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc33_mmi(uint8_t *dst, const uint8_t *src,
@@ -1758,7 +2384,7 @@ void ff_put_h264_qpel4_mc33_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel4_h_lowpass_mmi(halfH, src + stride, 4, stride);
     copy_block4_mmi(full, src - stride*2 + 1, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
-    put_pixels4_l2_mmi(dst, halfH, halfV, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, halfH, halfV, stride, 4, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc22_mmi(uint8_t *dst, const uint8_t *src,
@@ -1774,7 +2400,7 @@ void ff_put_h264_qpel4_mc21_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t halfHV[16];
     put_h264_qpel4_h_lowpass_mmi(halfH, src, 4, stride);
     put_h264_qpel4_hv_lowpass_mmi(halfHV, src, 4, stride);
-    put_pixels4_l2_mmi(dst, halfH, halfHV, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, halfH, halfHV, stride, 4, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc23_mmi(uint8_t *dst, const uint8_t *src,
@@ -1784,7 +2410,7 @@ void ff_put_h264_qpel4_mc23_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t halfHV[16];
     put_h264_qpel4_h_lowpass_mmi(halfH, src + stride, 4, stride);
     put_h264_qpel4_hv_lowpass_mmi(halfHV, src, 4, stride);
-    put_pixels4_l2_mmi(dst, halfH, halfHV, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, halfH, halfHV, stride, 4, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc12_mmi(uint8_t *dst, const uint8_t *src,
@@ -1797,7 +2423,7 @@ void ff_put_h264_qpel4_mc12_mmi(uint8_t *dst, const uint8_t *src,
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
     put_h264_qpel4_hv_lowpass_mmi(halfHV, src, 4, stride);
-    put_pixels4_l2_mmi(dst, halfV, halfHV, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, halfV, halfHV, stride, 4, 4, 4);
 }
 
 void ff_put_h264_qpel4_mc32_mmi(uint8_t *dst, const uint8_t *src,
@@ -1810,14 +2436,14 @@ void ff_put_h264_qpel4_mc32_mmi(uint8_t *dst, const uint8_t *src,
     copy_block4_mmi(full, src - stride*2 + 1, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
     put_h264_qpel4_hv_lowpass_mmi(halfHV, src, 4, stride);
-    put_pixels4_l2_mmi(dst, halfV, halfHV, stride, 4, 4, 4);
+    ff_put_pixels4_l2_8_mmi(dst, halfV, halfHV, stride, 4, 4, 4);
 }
 
 //DEF_H264_MC_MMI(avg_, 4)
 void ff_avg_h264_qpel4_mc00_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    avg_pixels4_mmi(dst, src, stride, 4);
+    ff_avg_pixels4_8_mmi(dst, src, stride, 4);
 }
 
 void ff_avg_h264_qpel4_mc10_mmi(uint8_t *dst, const uint8_t *src,
@@ -1825,7 +2451,7 @@ void ff_avg_h264_qpel4_mc10_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[16];
     put_h264_qpel4_h_lowpass_mmi(half, src, 4, stride);
-    avg_pixels4_l2_mmi(dst, src, half, stride, stride, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, src, half, stride, stride, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc20_mmi(uint8_t *dst, const uint8_t *src,
@@ -1839,7 +2465,7 @@ void ff_avg_h264_qpel4_mc30_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[16];
     put_h264_qpel4_h_lowpass_mmi(half, src, 4, stride);
-    avg_pixels4_l2_mmi(dst, src+1, half, stride, stride, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, src+1, half, stride, stride, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc01_mmi(uint8_t *dst, const uint8_t *src,
@@ -1850,7 +2476,7 @@ void ff_avg_h264_qpel4_mc01_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[16];
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(half, full_mid, 4, 4);
-    avg_pixels4_l2_mmi(dst, full_mid, half, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, full_mid, half, stride, 4, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc02_mmi(uint8_t *dst, const uint8_t *src,
@@ -1870,7 +2496,7 @@ void ff_avg_h264_qpel4_mc03_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[16];
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(half, full_mid, 4, 4);
-    avg_pixels4_l2_mmi(dst, full_mid+4, half, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, full_mid+4, half, stride, 4, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc11_mmi(uint8_t *dst, const uint8_t *src,
@@ -1883,7 +2509,7 @@ void ff_avg_h264_qpel4_mc11_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel4_h_lowpass_mmi(halfH, src, 4, stride);
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
-    avg_pixels4_l2_mmi(dst, halfH, halfV, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, halfH, halfV, stride, 4, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc31_mmi(uint8_t *dst, const uint8_t *src,
@@ -1896,7 +2522,7 @@ void ff_avg_h264_qpel4_mc31_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel4_h_lowpass_mmi(halfH, src, 4, stride);
     copy_block4_mmi(full, src - stride*2 + 1, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
-    avg_pixels4_l2_mmi(dst, halfH, halfV, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, halfH, halfV, stride, 4, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc13_mmi(uint8_t *dst, const uint8_t *src,
@@ -1909,7 +2535,7 @@ void ff_avg_h264_qpel4_mc13_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel4_h_lowpass_mmi(halfH, src + stride, 4, stride);
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
-    avg_pixels4_l2_mmi(dst, halfH, halfV, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, halfH, halfV, stride, 4, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc33_mmi(uint8_t *dst, const uint8_t *src,
@@ -1922,7 +2548,7 @@ void ff_avg_h264_qpel4_mc33_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel4_h_lowpass_mmi(halfH, src + stride, 4, stride);
     copy_block4_mmi(full, src - stride*2 + 1, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
-    avg_pixels4_l2_mmi(dst, halfH, halfV, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, halfH, halfV, stride, 4, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc22_mmi(uint8_t *dst, const uint8_t *src,
@@ -1938,7 +2564,7 @@ void ff_avg_h264_qpel4_mc21_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t halfHV[16];
     put_h264_qpel4_h_lowpass_mmi(halfH, src, 4, stride);
     put_h264_qpel4_hv_lowpass_mmi(halfHV, src, 4, stride);
-    avg_pixels4_l2_mmi(dst, halfH, halfHV, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, halfH, halfHV, stride, 4, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc23_mmi(uint8_t *dst, const uint8_t *src,
@@ -1948,7 +2574,7 @@ void ff_avg_h264_qpel4_mc23_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t halfHV[16];
     put_h264_qpel4_h_lowpass_mmi(halfH, src + stride, 4, stride);
     put_h264_qpel4_hv_lowpass_mmi(halfHV, src, 4, stride);
-    avg_pixels4_l2_mmi(dst, halfH, halfHV, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, halfH, halfHV, stride, 4, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc12_mmi(uint8_t *dst, const uint8_t *src,
@@ -1961,7 +2587,7 @@ void ff_avg_h264_qpel4_mc12_mmi(uint8_t *dst, const uint8_t *src,
     copy_block4_mmi(full, src - stride*2, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
     put_h264_qpel4_hv_lowpass_mmi(halfHV, src, 4, stride);
-    avg_pixels4_l2_mmi(dst, halfV, halfHV, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, halfV, halfHV, stride, 4, 4, 4);
 }
 
 void ff_avg_h264_qpel4_mc32_mmi(uint8_t *dst, const uint8_t *src,
@@ -1974,14 +2600,14 @@ void ff_avg_h264_qpel4_mc32_mmi(uint8_t *dst, const uint8_t *src,
     copy_block4_mmi(full, src - stride*2 + 1, 4,  stride, 9);
     put_h264_qpel4_v_lowpass_mmi(halfV, full_mid, 4, 4);
     put_h264_qpel4_hv_lowpass_mmi(halfHV, src, 4, stride);
-    avg_pixels4_l2_mmi(dst, halfV, halfHV, stride, 4, 4, 4);
+    ff_avg_pixels4_l2_8_mmi(dst, halfV, halfHV, stride, 4, 4, 4);
 }
 
 //DEF_H264_MC_MMI(put_, 8)
 void ff_put_h264_qpel8_mc00_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    put_pixels8_mmi(dst, src, stride, 8);
+    ff_put_pixels8_8_mmi(dst, src, stride, 8);
 }
 
 void ff_put_h264_qpel8_mc10_mmi(uint8_t *dst, const uint8_t *src,
@@ -1989,7 +2615,7 @@ void ff_put_h264_qpel8_mc10_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[64];
     put_h264_qpel8_h_lowpass_mmi(half, src, 8, stride);
-    put_pixels8_l2_mmi(dst, src, half, stride, stride, 8, 8);
+    ff_put_pixels8_l2_8_mmi(dst, src, half, stride, stride, 8, 8);
 }
 
 void ff_put_h264_qpel8_mc20_mmi(uint8_t *dst, const uint8_t *src,
@@ -2003,7 +2629,7 @@ void ff_put_h264_qpel8_mc30_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[64];
     put_h264_qpel8_h_lowpass_mmi(half, src, 8, stride);
-    put_pixels8_l2_mmi(dst, src+1, half, stride, stride, 8, 8);
+    ff_put_pixels8_l2_8_mmi(dst, src+1, half, stride, stride, 8, 8);
 }
 
 void ff_put_h264_qpel8_mc01_mmi(uint8_t *dst, const uint8_t *src,
@@ -2014,7 +2640,7 @@ void ff_put_h264_qpel8_mc01_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[64];
     copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(half, full_mid, 8, 8);
-    put_pixels8_l2_mmi(dst, full_mid, half, stride, 8, 8, 8);
+    ff_put_pixels8_l2_8_mmi(dst, full_mid, half, stride, 8, 8, 8);
 }
 
 void ff_put_h264_qpel8_mc02_mmi(uint8_t *dst, const uint8_t *src,
@@ -2034,7 +2660,7 @@ void ff_put_h264_qpel8_mc03_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[64];
     copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(half, full_mid, 8, 8);
-    put_pixels8_l2_mmi(dst, full_mid+8, half, stride, 8, 8, 8);
+    ff_put_pixels8_l2_8_mmi(dst, full_mid+8, half, stride, 8, 8, 8);
 }
 
 void ff_put_h264_qpel8_mc11_mmi(uint8_t *dst, const uint8_t *src,
@@ -2047,7 +2673,7 @@ void ff_put_h264_qpel8_mc11_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel8_h_lowpass_mmi(halfH, src, 8, stride);
     copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    put_pixels8_l2_mmi(dst, halfH, halfV, stride, 8, 8, 8);
+    ff_put_pixels8_l2_8_mmi(dst, halfH, halfV, stride, 8, 8, 8);
 }
 
 void ff_put_h264_qpel8_mc31_mmi(uint8_t *dst, const uint8_t *src,
@@ -2060,7 +2686,7 @@ void ff_put_h264_qpel8_mc31_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel8_h_lowpass_mmi(halfH, src, 8, stride);
     copy_block8_mmi(full, src - stride*2 + 1, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    put_pixels8_l2_mmi(dst, halfH, halfV, stride, 8, 8, 8);
+    ff_put_pixels8_l2_8_mmi(dst, halfH, halfV, stride, 8, 8, 8);
 }
 
 void ff_put_h264_qpel8_mc13_mmi(uint8_t *dst, const uint8_t *src,
@@ -2073,7 +2699,7 @@ void ff_put_h264_qpel8_mc13_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel8_h_lowpass_mmi(halfH, src + stride, 8, stride);
     copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    put_pixels8_l2_mmi(dst, halfH, halfV, stride, 8, 8, 8);
+    ff_put_pixels8_l2_8_mmi(dst, halfH, halfV, stride, 8, 8, 8);
 }
 
 void ff_put_h264_qpel8_mc33_mmi(uint8_t *dst, const uint8_t *src,
@@ -2086,66 +2712,66 @@ void ff_put_h264_qpel8_mc33_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel8_h_lowpass_mmi(halfH, src + stride, 8, stride);
     copy_block8_mmi(full, src - stride*2 + 1, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    put_pixels8_l2_mmi(dst, halfH, halfV, stride, 8, 8, 8);
+    ff_put_pixels8_l2_8_mmi(dst, halfH, halfV, stride, 8, 8, 8);
 }
 
 void ff_put_h264_qpel8_mc22_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    put_h264_qpel8_hv_lowpass_mmi(dst, src, stride, stride);
+    uint16_t __attribute__ ((aligned(8))) temp[192];
+
+    put_h264_qpel8_hv_lowpass_mmi(dst, temp, src, stride, 8, stride);
 }
 
 void ff_put_h264_qpel8_mc21_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t halfH[64];
-    uint8_t halfHV[64];
-    put_h264_qpel8_h_lowpass_mmi(halfH, src, 8, stride);
-    put_h264_qpel8_hv_lowpass_mmi(halfHV, src, 8, stride);
-    put_pixels8_l2_mmi(dst, halfH, halfHV, stride, 8, 8, 8);
+    uint8_t __attribute__ ((aligned(8))) temp[448];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 64);
+
+    put_h264_qpel8_hv_lowpass_mmi(halfHV, halfV, src, 8, 8, stride);
+    put_h264_qpel8_h_lowpass_l2_mmi(dst, src, halfHV, stride, 8);
 }
 
 void ff_put_h264_qpel8_mc23_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t halfH[64];
-    uint8_t halfHV[64];
-    put_h264_qpel8_h_lowpass_mmi(halfH, src + stride, 8, stride);
-    put_h264_qpel8_hv_lowpass_mmi(halfHV, src, 8, stride);
-    put_pixels8_l2_mmi(dst, halfH, halfHV, stride, 8, 8, 8);
+    uint8_t __attribute__ ((aligned(8))) temp[448];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 64);
+
+    put_h264_qpel8_hv_lowpass_mmi(halfHV, halfV, src, 8, 8, stride);
+    put_h264_qpel8_h_lowpass_l2_mmi(dst, src + stride, halfHV, stride, 8);
 }
 
 void ff_put_h264_qpel8_mc12_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t full[104];
-    uint8_t * const full_mid= full + 16;
-    uint8_t halfV[64];
-    uint8_t halfHV[64];
-    copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
-    put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    put_h264_qpel8_hv_lowpass_mmi(halfHV, src, 8, stride);
-    put_pixels8_l2_mmi(dst, halfV, halfHV, stride, 8, 8, 8);
+    uint8_t __attribute__ ((aligned(8))) temp[448];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 64);
+
+    put_h264_qpel8_hv_lowpass_mmi(halfHV, halfV, src, 8, 8, stride);
+    put_pixels8_l2_shift5_mmi(dst, halfV + 2, halfHV, stride, 8, 8);
 }
 
 void ff_put_h264_qpel8_mc32_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t full[104];
-    uint8_t * const full_mid= full + 16;
-    uint8_t halfV[64];
-    uint8_t halfHV[64];
-    copy_block8_mmi(full, src - stride*2 + 1, 8,  stride, 13);
-    put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    put_h264_qpel8_hv_lowpass_mmi(halfHV, src, 8, stride);
-    put_pixels8_l2_mmi(dst, halfV, halfHV, stride, 8, 8, 8);
+    uint8_t __attribute__ ((aligned(8))) temp[448];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 64);
+
+    put_h264_qpel8_hv_lowpass_mmi(halfHV, halfV, src, 8, 8, stride);
+    put_pixels8_l2_shift5_mmi(dst, halfV + 3, halfHV, stride, 8, 8);
 }
 
 //DEF_H264_MC_MMI(avg_, 8)
 void ff_avg_h264_qpel8_mc00_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    avg_pixels8_mmi(dst, src, stride, 8);
+    ff_avg_pixels8_8_mmi(dst, src, stride, 8);
 }
 
 void ff_avg_h264_qpel8_mc10_mmi(uint8_t *dst, const uint8_t *src,
@@ -2153,7 +2779,7 @@ void ff_avg_h264_qpel8_mc10_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[64];
     put_h264_qpel8_h_lowpass_mmi(half, src, 8, stride);
-    avg_pixels8_l2_mmi(dst, src, half, stride, stride, 8, 8);
+    ff_avg_pixels8_l2_8_mmi(dst, src, half, stride, stride, 8, 8);
 }
 
 void ff_avg_h264_qpel8_mc20_mmi(uint8_t *dst, const uint8_t *src,
@@ -2167,7 +2793,7 @@ void ff_avg_h264_qpel8_mc30_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[64];
     put_h264_qpel8_h_lowpass_mmi(half, src, 8, stride);
-    avg_pixels8_l2_mmi(dst, src+1, half, stride, stride, 8, 8);
+    ff_avg_pixels8_l2_8_mmi(dst, src+1, half, stride, stride, 8, 8);
 }
 
 void ff_avg_h264_qpel8_mc01_mmi(uint8_t *dst, const uint8_t *src,
@@ -2178,7 +2804,7 @@ void ff_avg_h264_qpel8_mc01_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[64];
     copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(half, full_mid, 8, 8);
-    avg_pixels8_l2_mmi(dst, full_mid, half, stride, 8, 8, 8);
+    ff_avg_pixels8_l2_8_mmi(dst, full_mid, half, stride, 8, 8, 8);
 }
 
 void ff_avg_h264_qpel8_mc02_mmi(uint8_t *dst, const uint8_t *src,
@@ -2198,7 +2824,7 @@ void ff_avg_h264_qpel8_mc03_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[64];
     copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(half, full_mid, 8, 8);
-    avg_pixels8_l2_mmi(dst, full_mid+8, half, stride, 8, 8, 8);
+    ff_avg_pixels8_l2_8_mmi(dst, full_mid+8, half, stride, 8, 8, 8);
 }
 
 void ff_avg_h264_qpel8_mc11_mmi(uint8_t *dst, const uint8_t *src,
@@ -2211,7 +2837,7 @@ void ff_avg_h264_qpel8_mc11_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel8_h_lowpass_mmi(halfH, src, 8, stride);
     copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    avg_pixels8_l2_mmi(dst, halfH, halfV, stride, 8, 8, 8);
+    ff_avg_pixels8_l2_8_mmi(dst, halfH, halfV, stride, 8, 8, 8);
 }
 
 void ff_avg_h264_qpel8_mc31_mmi(uint8_t *dst, const uint8_t *src,
@@ -2224,7 +2850,7 @@ void ff_avg_h264_qpel8_mc31_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel8_h_lowpass_mmi(halfH, src, 8, stride);
     copy_block8_mmi(full, src - stride*2 + 1, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    avg_pixels8_l2_mmi(dst, halfH, halfV, stride, 8, 8, 8);
+    ff_avg_pixels8_l2_8_mmi(dst, halfH, halfV, stride, 8, 8, 8);
 }
 
 void ff_avg_h264_qpel8_mc13_mmi(uint8_t *dst, const uint8_t *src,
@@ -2237,7 +2863,7 @@ void ff_avg_h264_qpel8_mc13_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel8_h_lowpass_mmi(halfH, src + stride, 8, stride);
     copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    avg_pixels8_l2_mmi(dst, halfH, halfV, stride, 8, 8, 8);
+    ff_avg_pixels8_l2_8_mmi(dst, halfH, halfV, stride, 8, 8, 8);
 }
 
 void ff_avg_h264_qpel8_mc33_mmi(uint8_t *dst, const uint8_t *src,
@@ -2250,66 +2876,66 @@ void ff_avg_h264_qpel8_mc33_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel8_h_lowpass_mmi(halfH, src + stride, 8, stride);
     copy_block8_mmi(full, src - stride*2 + 1, 8,  stride, 13);
     put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    avg_pixels8_l2_mmi(dst, halfH, halfV, stride, 8, 8, 8);
+    ff_avg_pixels8_l2_8_mmi(dst, halfH, halfV, stride, 8, 8, 8);
 }
 
 void ff_avg_h264_qpel8_mc22_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    avg_h264_qpel8_hv_lowpass_mmi(dst, src, stride, stride);
+    uint16_t __attribute__ ((aligned(8))) temp[192];
+
+    avg_h264_qpel8_hv_lowpass_mmi(dst, temp, src, stride, 8, stride);
 }
 
 void ff_avg_h264_qpel8_mc21_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t halfH[64];
-    uint8_t halfHV[64];
-    put_h264_qpel8_h_lowpass_mmi(halfH, src, 8, stride);
-    put_h264_qpel8_hv_lowpass_mmi(halfHV, src, 8, stride);
-    avg_pixels8_l2_mmi(dst, halfH, halfHV, stride, 8, 8, 8);
+    uint8_t __attribute__ ((aligned(8))) temp[448];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 64);
+
+    put_h264_qpel8_hv_lowpass_mmi(halfHV, halfV, src, 8, 8, stride);
+    avg_h264_qpel8_h_lowpass_l2_mmi(dst, src, halfHV, stride, 8);
 }
 
 void ff_avg_h264_qpel8_mc23_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t halfH[64];
-    uint8_t halfHV[64];
-    put_h264_qpel8_h_lowpass_mmi(halfH, src + stride, 8, stride);
-    put_h264_qpel8_hv_lowpass_mmi(halfHV, src, 8, stride);
-    avg_pixels8_l2_mmi(dst, halfH, halfHV, stride, 8, 8, 8);
+    uint8_t __attribute__ ((aligned(8))) temp[448];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 64);
+
+    put_h264_qpel8_hv_lowpass_mmi(halfHV, halfV, src, 8, 8, stride);
+    avg_h264_qpel8_h_lowpass_l2_mmi(dst, src + stride, halfHV, stride, 8);
 }
 
 void ff_avg_h264_qpel8_mc12_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t full[104];
-    uint8_t * const full_mid= full + 16;
-    uint8_t halfV[64];
-    uint8_t halfHV[64];
-    copy_block8_mmi(full, src - stride*2, 8,  stride, 13);
-    put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    put_h264_qpel8_hv_lowpass_mmi(halfHV, src, 8, stride);
-    avg_pixels8_l2_mmi(dst, halfV, halfHV, stride, 8, 8, 8);
+    uint8_t __attribute__ ((aligned(8))) temp[448];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 64);
+
+    put_h264_qpel8_hv_lowpass_mmi(halfHV, halfV, src, 8, 8, stride);
+    avg_pixels8_l2_shift5_mmi(dst, halfV + 2, halfHV, stride, 8, 8);
 }
 
 void ff_avg_h264_qpel8_mc32_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t full[104];
-    uint8_t * const full_mid= full + 16;
-    uint8_t halfV[64];
-    uint8_t halfHV[64];
-    copy_block8_mmi(full, src - stride*2 + 1, 8,  stride, 13);
-    put_h264_qpel8_v_lowpass_mmi(halfV, full_mid, 8, 8);
-    put_h264_qpel8_hv_lowpass_mmi(halfHV, src, 8, stride);
-    avg_pixels8_l2_mmi(dst, halfV, halfHV, stride, 8, 8, 8);
+    uint8_t __attribute__ ((aligned(8))) temp[448];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 64);
+
+    put_h264_qpel8_hv_lowpass_mmi(halfHV, halfV, src, 8, 8, stride);
+    avg_pixels8_l2_shift5_mmi(dst, halfV + 3, halfHV, stride, 8, 8);
 }
 
 //DEF_H264_MC_MMI(put_, 16)
 void ff_put_h264_qpel16_mc00_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    put_pixels16_mmi(dst, src, stride, 16);
+    ff_put_pixels16_8_mmi(dst, src, stride, 16);
 }
 
 void ff_put_h264_qpel16_mc10_mmi(uint8_t *dst, const uint8_t *src,
@@ -2317,7 +2943,7 @@ void ff_put_h264_qpel16_mc10_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[256];
     put_h264_qpel16_h_lowpass_mmi(half, src, 16, stride);
-    put_pixels16_l2_mmi(dst, src, half, stride, stride, 16, 16);
+    ff_put_pixels16_l2_8_mmi(dst, src, half, stride, stride, 16, 16);
 }
 
 void ff_put_h264_qpel16_mc20_mmi(uint8_t *dst, const uint8_t *src,
@@ -2331,7 +2957,7 @@ void ff_put_h264_qpel16_mc30_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[256];
     put_h264_qpel16_h_lowpass_mmi(half, src, 16, stride);
-    put_pixels16_l2_mmi(dst, src+1, half, stride, stride, 16, 16);
+    ff_put_pixels16_l2_8_mmi(dst, src+1, half, stride, stride, 16, 16);
 }
 
 void ff_put_h264_qpel16_mc01_mmi(uint8_t *dst, const uint8_t *src,
@@ -2342,7 +2968,7 @@ void ff_put_h264_qpel16_mc01_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[256];
     copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(half, full_mid, 16, 16);
-    put_pixels16_l2_mmi(dst, full_mid, half, stride, 16, 16, 16);
+    ff_put_pixels16_l2_8_mmi(dst, full_mid, half, stride, 16, 16, 16);
 }
 
 void ff_put_h264_qpel16_mc02_mmi(uint8_t *dst, const uint8_t *src,
@@ -2362,7 +2988,7 @@ void ff_put_h264_qpel16_mc03_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[256];
     copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(half, full_mid, 16, 16);
-    put_pixels16_l2_mmi(dst, full_mid+16, half, stride, 16, 16, 16);
+    ff_put_pixels16_l2_8_mmi(dst, full_mid+16, half, stride, 16, 16, 16);
 }
 
 void ff_put_h264_qpel16_mc11_mmi(uint8_t *dst, const uint8_t *src,
@@ -2375,7 +3001,7 @@ void ff_put_h264_qpel16_mc11_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel16_h_lowpass_mmi(halfH, src, 16, stride);
     copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    put_pixels16_l2_mmi(dst, halfH, halfV, stride, 16, 16, 16);
+    ff_put_pixels16_l2_8_mmi(dst, halfH, halfV, stride, 16, 16, 16);
 }
 
 void ff_put_h264_qpel16_mc31_mmi(uint8_t *dst, const uint8_t *src,
@@ -2388,7 +3014,7 @@ void ff_put_h264_qpel16_mc31_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel16_h_lowpass_mmi(halfH, src, 16, stride);
     copy_block16_mmi(full, src - stride*2 + 1, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    put_pixels16_l2_mmi(dst, halfH, halfV, stride, 16, 16, 16);
+    ff_put_pixels16_l2_8_mmi(dst, halfH, halfV, stride, 16, 16, 16);
 }
 
 void ff_put_h264_qpel16_mc13_mmi(uint8_t *dst, const uint8_t *src,
@@ -2401,7 +3027,7 @@ void ff_put_h264_qpel16_mc13_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel16_h_lowpass_mmi(halfH, src + stride, 16, stride);
     copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    put_pixels16_l2_mmi(dst, halfH, halfV, stride, 16, 16, 16);
+    ff_put_pixels16_l2_8_mmi(dst, halfH, halfV, stride, 16, 16, 16);
 }
 
 void ff_put_h264_qpel16_mc33_mmi(uint8_t *dst, const uint8_t *src,
@@ -2414,66 +3040,66 @@ void ff_put_h264_qpel16_mc33_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel16_h_lowpass_mmi(halfH, src + stride, 16, stride);
     copy_block16_mmi(full, src - stride*2 + 1, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    put_pixels16_l2_mmi(dst, halfH, halfV, stride, 16, 16, 16);
+    ff_put_pixels16_l2_8_mmi(dst, halfH, halfV, stride, 16, 16, 16);
 }
 
 void ff_put_h264_qpel16_mc22_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    put_h264_qpel16_hv_lowpass_mmi(dst, src, stride, stride);
+    uint16_t __attribute__ ((aligned(8))) temp[384];
+
+    put_h264_qpel16_hv_lowpass_mmi(dst, temp, src, stride, 16, stride);
 }
 
 void ff_put_h264_qpel16_mc21_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t halfH[256];
-    uint8_t halfHV[256];
-    put_h264_qpel16_h_lowpass_mmi(halfH, src, 16, stride);
-    put_h264_qpel16_hv_lowpass_mmi(halfHV, src, 16, stride);
-    put_pixels16_l2_mmi(dst, halfH, halfHV, stride, 16, 16, 16);
+    uint8_t __attribute__ ((aligned(8))) temp[1024];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 256);
+
+    put_h264_qpel16_hv_lowpass_mmi(halfHV, halfV, src, 16, 16, stride);
+    put_h264_qpel16_h_lowpass_l2_mmi(dst, src, halfHV, stride, 16);
 }
 
 void ff_put_h264_qpel16_mc23_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t halfH[256];
-    uint8_t halfHV[256];
-    put_h264_qpel16_h_lowpass_mmi(halfH, src + stride, 16, stride);
-    put_h264_qpel16_hv_lowpass_mmi(halfHV, src, 16, stride);
-    put_pixels16_l2_mmi(dst, halfH, halfHV, stride, 16, 16, 16);
+    uint8_t __attribute__ ((aligned(8))) temp[1024];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 256);
+
+    put_h264_qpel16_hv_lowpass_mmi(halfHV, halfV, src, 16, 16, stride);
+    put_h264_qpel16_h_lowpass_l2_mmi(dst, src + stride, halfHV, stride, 16);
 }
 
 void ff_put_h264_qpel16_mc12_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t full[336];
-    uint8_t * const full_mid= full + 32;
-    uint8_t halfV[256];
-    uint8_t halfHV[256];
-    copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
-    put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    put_h264_qpel16_hv_lowpass_mmi(halfHV, src, 16, stride);
-    put_pixels16_l2_mmi(dst, halfV, halfHV, stride, 16, 16, 16);
+    uint8_t __attribute__ ((aligned(8))) temp[1024];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 256);
+
+    put_h264_qpel16_hv_lowpass_mmi(halfHV, halfV, src, 16, 16, stride);
+    put_pixels16_l2_shift5_mmi(dst, halfV + 2, halfHV, stride, 16, 16);
 }
 
 void ff_put_h264_qpel16_mc32_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t full[336];
-    uint8_t * const full_mid= full + 32;
-    uint8_t halfV[256];
-    uint8_t halfHV[256];
-    copy_block16_mmi(full, src - stride*2 + 1, 16,  stride, 21);
-    put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    put_h264_qpel16_hv_lowpass_mmi(halfHV, src, 16, stride);
-    put_pixels16_l2_mmi(dst, halfV, halfHV, stride, 16, 16, 16);
+    uint8_t __attribute__ ((aligned(8))) temp[1024];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 256);
+
+    put_h264_qpel16_hv_lowpass_mmi(halfHV, halfV, src, 16, 16, stride);
+    put_pixels16_l2_shift5_mmi(dst, halfV + 3, halfHV, stride, 16, 16);
 }
 
 //DEF_H264_MC_MMI(avg_, 16)
 void ff_avg_h264_qpel16_mc00_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    avg_pixels16_mmi(dst, src, stride, 16);
+    ff_avg_pixels16_8_mmi(dst, src, stride, 16);
 }
 
 void ff_avg_h264_qpel16_mc10_mmi(uint8_t *dst, const uint8_t *src,
@@ -2481,7 +3107,7 @@ void ff_avg_h264_qpel16_mc10_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[256];
     put_h264_qpel16_h_lowpass_mmi(half, src, 16, stride);
-    avg_pixels16_l2_mmi(dst, src, half, stride, stride, 16, 16);
+    ff_avg_pixels16_l2_8_mmi(dst, src, half, stride, stride, 16, 16);
 }
 
 void ff_avg_h264_qpel16_mc20_mmi(uint8_t *dst, const uint8_t *src,
@@ -2495,7 +3121,7 @@ void ff_avg_h264_qpel16_mc30_mmi(uint8_t *dst, const uint8_t *src,
 {
     uint8_t half[256];
     put_h264_qpel16_h_lowpass_mmi(half, src, 16, stride);
-    avg_pixels16_l2_mmi(dst, src+1, half, stride, stride, 16, 16);
+    ff_avg_pixels16_l2_8_mmi(dst, src+1, half, stride, stride, 16, 16);
 }
 
 void ff_avg_h264_qpel16_mc01_mmi(uint8_t *dst, const uint8_t *src,
@@ -2506,7 +3132,7 @@ void ff_avg_h264_qpel16_mc01_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[256];
     copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(half, full_mid, 16, 16);
-    avg_pixels16_l2_mmi(dst, full_mid, half, stride, 16, 16, 16);
+    ff_avg_pixels16_l2_8_mmi(dst, full_mid, half, stride, 16, 16, 16);
 }
 
 void ff_avg_h264_qpel16_mc02_mmi(uint8_t *dst, const uint8_t *src,
@@ -2526,7 +3152,7 @@ void ff_avg_h264_qpel16_mc03_mmi(uint8_t *dst, const uint8_t *src,
     uint8_t half[256];
     copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(half, full_mid, 16, 16);
-    avg_pixels16_l2_mmi(dst, full_mid+16, half, stride, 16, 16, 16);
+    ff_avg_pixels16_l2_8_mmi(dst, full_mid+16, half, stride, 16, 16, 16);
 }
 
 void ff_avg_h264_qpel16_mc11_mmi(uint8_t *dst, const uint8_t *src,
@@ -2539,7 +3165,7 @@ void ff_avg_h264_qpel16_mc11_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel16_h_lowpass_mmi(halfH, src, 16, stride);
     copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    avg_pixels16_l2_mmi(dst, halfH, halfV, stride, 16, 16, 16);
+    ff_avg_pixels16_l2_8_mmi(dst, halfH, halfV, stride, 16, 16, 16);
 }
 
 void ff_avg_h264_qpel16_mc31_mmi(uint8_t *dst, const uint8_t *src,
@@ -2552,7 +3178,7 @@ void ff_avg_h264_qpel16_mc31_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel16_h_lowpass_mmi(halfH, src, 16, stride);
     copy_block16_mmi(full, src - stride*2 + 1, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    avg_pixels16_l2_mmi(dst, halfH, halfV, stride, 16, 16, 16);
+    ff_avg_pixels16_l2_8_mmi(dst, halfH, halfV, stride, 16, 16, 16);
 }
 
 void ff_avg_h264_qpel16_mc13_mmi(uint8_t *dst, const uint8_t *src,
@@ -2565,7 +3191,7 @@ void ff_avg_h264_qpel16_mc13_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel16_h_lowpass_mmi(halfH, src + stride, 16, stride);
     copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    avg_pixels16_l2_mmi(dst, halfH, halfV, stride, 16, 16, 16);
+    ff_avg_pixels16_l2_8_mmi(dst, halfH, halfV, stride, 16, 16, 16);
 }
 
 void ff_avg_h264_qpel16_mc33_mmi(uint8_t *dst, const uint8_t *src,
@@ -2578,59 +3204,59 @@ void ff_avg_h264_qpel16_mc33_mmi(uint8_t *dst, const uint8_t *src,
     put_h264_qpel16_h_lowpass_mmi(halfH, src + stride, 16, stride);
     copy_block16_mmi(full, src - stride*2 + 1, 16,  stride, 21);
     put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    avg_pixels16_l2_mmi(dst, halfH, halfV, stride, 16, 16, 16);
+    ff_avg_pixels16_l2_8_mmi(dst, halfH, halfV, stride, 16, 16, 16);
 }
 
 void ff_avg_h264_qpel16_mc22_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    avg_h264_qpel16_hv_lowpass_mmi(dst, src, stride, stride);
+    uint16_t __attribute__ ((aligned(8))) temp[384];
+
+    avg_h264_qpel16_hv_lowpass_mmi(dst, temp, src, stride, 16, stride);
 }
 
 void ff_avg_h264_qpel16_mc21_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t halfH[256];
-    uint8_t halfHV[256];
-    put_h264_qpel16_h_lowpass_mmi(halfH, src, 16, stride);
-    put_h264_qpel16_hv_lowpass_mmi(halfHV, src, 16, stride);
-    avg_pixels16_l2_mmi(dst, halfH, halfHV, stride, 16, 16, 16);
+    uint8_t __attribute__ ((aligned(8))) temp[1024];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 256);
+
+    put_h264_qpel16_hv_lowpass_mmi(halfHV, halfV, src, 16, 16, stride);
+    avg_h264_qpel16_h_lowpass_l2_mmi(dst, src, halfHV, stride, 16);
 }
 
 void ff_avg_h264_qpel16_mc23_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t halfH[256];
-    uint8_t halfHV[256];
-    put_h264_qpel16_h_lowpass_mmi(halfH, src + stride, 16, stride);
-    put_h264_qpel16_hv_lowpass_mmi(halfHV, src, 16, stride);
-    avg_pixels16_l2_mmi(dst, halfH, halfHV, stride, 16, 16, 16);
+    uint8_t __attribute__ ((aligned(8))) temp[1024];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 256);
+
+    put_h264_qpel16_hv_lowpass_mmi(halfHV, halfV, src, 16, 16, stride);
+    avg_h264_qpel16_h_lowpass_l2_mmi(dst, src + stride, halfHV, stride, 16);
 }
 
 void ff_avg_h264_qpel16_mc12_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t full[336];
-    uint8_t * const full_mid= full + 32;
-    uint8_t halfV[256];
-    uint8_t halfHV[256];
-    copy_block16_mmi(full, src - stride*2, 16,  stride, 21);
-    put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    put_h264_qpel16_hv_lowpass_mmi(halfHV, src, 16, stride);
-    avg_pixels16_l2_mmi(dst, halfV, halfHV, stride, 16, 16, 16);
+    uint8_t __attribute__ ((aligned(8))) temp[1024];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 256);
+
+    put_h264_qpel16_hv_lowpass_mmi(halfHV, halfV, src, 16, 16, stride);
+    avg_pixels16_l2_shift5_mmi(dst, halfV + 2, halfHV, stride, 16, 16);
 }
 
 void ff_avg_h264_qpel16_mc32_mmi(uint8_t *dst, const uint8_t *src,
         ptrdiff_t stride)
 {
-    uint8_t full[336];
-    uint8_t * const full_mid= full + 32;
-    uint8_t halfV[256];
-    uint8_t halfHV[256];
-    copy_block16_mmi(full, src - stride*2 + 1, 16,  stride, 21);
-    put_h264_qpel16_v_lowpass_mmi(halfV, full_mid, 16, 16);
-    put_h264_qpel16_hv_lowpass_mmi(halfHV, src, 16, stride);
-    avg_pixels16_l2_mmi(dst, halfV, halfHV, stride, 16, 16, 16);
+    uint8_t __attribute__ ((aligned(8))) temp[1024];
+    uint8_t *const halfHV = temp;
+    int16_t *const halfV = (int16_t *) (temp + 256);
+
+    put_h264_qpel16_hv_lowpass_mmi(halfHV, halfV, src, 16, 16, stride);
+    avg_pixels16_l2_shift5_mmi(dst, halfV + 3, halfHV, stride, 16, 16);
 }
 
 #undef op2_avg
diff --git a/libavcodec/mips/hpeldsp_init_mips.c b/libavcodec/mips/hpeldsp_init_mips.c
index 82f2310..363a045 100644
--- a/libavcodec/mips/hpeldsp_init_mips.c
+++ b/libavcodec/mips/hpeldsp_init_mips.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015 Parag Salasakar (Parag.Salasakar at imgtec.com)
+ * Copyright (c) 2016 Zhou Xiaoyong <zhouxiaoyong at loongson.cn>
  *
  * This file is part of FFmpeg.
  *
@@ -65,9 +66,57 @@ static void ff_hpeldsp_init_msa(HpelDSPContext *c, int flags)
 }
 #endif  // #if HAVE_MSA
 
+#if HAVE_MMI
+static void ff_hpeldsp_init_mmi(HpelDSPContext *c, int flags)
+{
+    c->put_pixels_tab[0][0] = ff_put_pixels16_8_mmi;
+    c->put_pixels_tab[0][1] = ff_put_pixels16_x2_8_mmi;
+    c->put_pixels_tab[0][2] = ff_put_pixels16_y2_8_mmi;
+    c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_8_mmi;
+
+    c->put_pixels_tab[1][0] = ff_put_pixels8_8_mmi;
+    c->put_pixels_tab[1][1] = ff_put_pixels8_x2_8_mmi;
+    c->put_pixels_tab[1][2] = ff_put_pixels8_y2_8_mmi;
+    c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_8_mmi;
+
+    c->put_pixels_tab[2][0] = ff_put_pixels4_8_mmi;
+    c->put_pixels_tab[2][1] = ff_put_pixels4_x2_8_mmi;
+    c->put_pixels_tab[2][2] = ff_put_pixels4_y2_8_mmi;
+    c->put_pixels_tab[2][3] = ff_put_pixels4_xy2_8_mmi;
+
+    c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_8_mmi;
+    c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_8_mmi;
+    c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_8_mmi;
+    c->put_no_rnd_pixels_tab[0][3] = ff_put_no_rnd_pixels16_xy2_8_mmi;
+
+    c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_8_mmi;
+    c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_8_mmi;
+    c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_8_mmi;
+    c->put_no_rnd_pixels_tab[1][3] = ff_put_no_rnd_pixels8_xy2_8_mmi;
+
+    c->avg_pixels_tab[0][0] = ff_avg_pixels16_8_mmi;
+    c->avg_pixels_tab[0][1] = ff_avg_pixels16_x2_8_mmi;
+    c->avg_pixels_tab[0][2] = ff_avg_pixels16_y2_8_mmi;
+    c->avg_pixels_tab[0][3] = ff_avg_pixels16_xy2_8_mmi;
+
+    c->avg_pixels_tab[1][0] = ff_avg_pixels8_8_mmi;
+    c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_8_mmi;
+    c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_8_mmi;
+    c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_8_mmi;
+
+    c->avg_pixels_tab[2][0] = ff_avg_pixels4_8_mmi;
+    c->avg_pixels_tab[2][1] = ff_avg_pixels4_x2_8_mmi;
+    c->avg_pixels_tab[2][2] = ff_avg_pixels4_y2_8_mmi;
+    c->avg_pixels_tab[2][3] = ff_avg_pixels4_xy2_8_mmi;
+}
+#endif  // #if HAVE_MMI
+
 void ff_hpeldsp_init_mips(HpelDSPContext *c, int flags)
 {
 #if HAVE_MSA
     ff_hpeldsp_init_msa(c, flags);
 #endif  // #if HAVE_MSA
+#if HAVE_MMI
+    ff_hpeldsp_init_mmi(c, flags);
+#endif  // #if HAVE_MMI
 }
diff --git a/libavcodec/mips/hpeldsp_mips.h b/libavcodec/mips/hpeldsp_mips.h
index f4ab53e..f527c1d 100644
--- a/libavcodec/mips/hpeldsp_mips.h
+++ b/libavcodec/mips/hpeldsp_mips.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015 Parag Salasakar (Parag.Salasakar at imgtec.com)
+ * Copyright (c) 2016 Zhou Xiaoyong <zhouxiaoyong at loongson.cn>
  *
  * This file is part of FFmpeg.
  *
@@ -84,4 +85,90 @@ void ff_avg_pixels4_y2_msa(uint8_t *block, const uint8_t *pixels,
 void ff_avg_pixels4_xy2_msa(uint8_t *block, const uint8_t *pixels,
                             ptrdiff_t line_size, int32_t h);
 
+void ff_put_pixels16_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h);
+void ff_put_pixels8_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h);
+void ff_put_pixels4_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h);
+void ff_avg_pixels16_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h);
+void ff_avg_pixels8_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h);
+void ff_avg_pixels4_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h);
+void ff_put_no_rnd_pixels16_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h);
+void ff_put_no_rnd_pixels8_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h);
+
+void ff_put_pixels16_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels16_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels16_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels16_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels8_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels8_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels8_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels8_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels4_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels4_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels4_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_pixels4_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_no_rnd_pixels16_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_no_rnd_pixels16_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_no_rnd_pixels16_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_no_rnd_pixels8_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_no_rnd_pixels8_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_put_no_rnd_pixels8_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels16_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels16_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels16_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels16_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels8_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels8_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels8_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels8_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels4_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels4_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels4_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+void ff_avg_pixels4_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int32_t h);
+
 #endif  // #ifndef AVCODEC_MIPS_HPELDSP_MIPS_H
diff --git a/libavcodec/mips/hpeldsp_mmi.c b/libavcodec/mips/hpeldsp_mmi.c
new file mode 100644
index 0000000..4c46f00
--- /dev/null
+++ b/libavcodec/mips/hpeldsp_mmi.c
@@ -0,0 +1,1257 @@
+/*
+ * Loongson SIMD optimized qpeldsp
+ *
+ * Copyright (c) 2016 Loongson Technology Corporation Limited
+ * Copyright (c) 2016 Zhou Xiaoyong <zhouxiaoyong at loongson.cn>
+ *
+ * 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 "hpeldsp_mips.h"
+#include "libavcodec/bit_depth_template.c"
+#include "libavutil/mips/asmdefs.h"
+#include "constants.h"
+
+void ff_put_pixels4_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    double ftmp[2];
+    mips_reg addr[2];
+    uint64_t low32;
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr1],   %[line_size],   %[line_size]            \n\t"
+        "1:                                                             \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "uld        %[low32],   0x00(%[pixels])                         \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        "uld        %[low32],   0x00(%[addr0])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "swc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gsswxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr1]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr1]                \n\t"
+
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "uld        %[low32],   0x00(%[pixels])                         \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        "uld        %[low32],   0x00(%[addr0])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "swc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gsswxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr1]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr1]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [low32]"=&r"(low32),
+          [block]"+&r"(block),              [pixels]"+&r"(pixels),
+          [h]"+&r"(h)
+        : [line_size]"r"((mips_reg)line_size)
+        : "memory"
+    );
+}
+
+void ff_put_pixels8_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    double ftmp[2];
+    mips_reg addr[2];
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr1],   %[line_size],   %[line_size]            \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "sdc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr1]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr1]                \n\t"
+
+        "gsldlc1    %[ftmp0],   0x07(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "sdc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr1]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr1]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [block]"+&r"(block),              [pixels]"+&r"(pixels),
+          [h]"+&r"(h)
+        : [line_size]"r"((mips_reg)line_size)
+        : "memory"
+    );
+}
+
+void ff_put_pixels16_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    double ftmp[4];
+    mips_reg addr[2];
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr1],   %[line_size],   %[line_size]            \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp2],   0x0f(%[pixels])                         \n\t"
+        "gsldrc1    %[ftmp2],   0x08(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp3],   0x0f(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp3],   0x08(%[addr0])                          \n\t"
+        "sdc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        "sdc1       %[ftmp2],   0x08(%[block])                          \n\t"
+        "gssdxc1    %[ftmp3],   0x08(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr1]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr1]                \n\t"
+
+        "gsldlc1    %[ftmp0],   0x07(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp2],   0x0f(%[pixels])                         \n\t"
+        "gsldrc1    %[ftmp2],   0x08(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp3],   0x0f(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp3],   0x08(%[addr0])                          \n\t"
+        "sdc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        "sdc1       %[ftmp2],   0x08(%[block])                          \n\t"
+        "gssdxc1    %[ftmp3],   0x08(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr1]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr1]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [block]"+&r"(block),              [pixels]"+&r"(pixels),
+          [h]"+&r"(h)
+        : [line_size]"r"((mips_reg)line_size)
+        : "memory"
+    );
+}
+
+void ff_avg_pixels4_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    double ftmp[4];
+    mips_reg addr[3];
+    uint64_t low32;
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr2],   %[line_size],   %[line_size]            \n\t"
+        "1:                                                             \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "uld        %[low32],   0x00(%[pixels])                         \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        "uld        %[low32],   0x00(%[addr0])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        PTR_ADDU   "%[addr1],   %[block],       %[line_size]            \n\t"
+        "uld        %[low32],   0x00(%[block])                          \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "uld        %[low32],   0x00(%[addr1])                          \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "swc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gsswxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr2]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr2]                \n\t"
+
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "uld        %[low32],   0x00(%[pixels])                         \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        "uld        %[low32],   0x00(%[addr0])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        PTR_ADDU   "%[addr1],   %[block],       %[line_size]            \n\t"
+        "uld        %[low32],   0x00(%[block])                          \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        "uld        %[low32],   0x00(%[addr1])                          \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "swc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gsswxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr2]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr2]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),
+          [low32]"=&r"(low32),
+          [block]"+&r"(block),              [pixels]"+&r"(pixels),
+          [h]"+&r"(h)
+        : [line_size]"r"((mips_reg)line_size)
+        : "memory"
+    );
+}
+
+void ff_avg_pixels8_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    double ftmp[4];
+    mips_reg addr[3];
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr2],   %[line_size],   %[line_size]            \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr1],   %[block],       %[line_size]            \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[block])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[block])                          \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr2]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr2]                \n\t"
+
+        "gsldlc1    %[ftmp0],   0x07(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        PTR_ADDU   "%[addr1],   %[block],       %[line_size]            \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[block])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[block])                          \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr2]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr2]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),
+          [block]"+&r"(block),              [pixels]"+&r"(pixels),
+          [h]"+&r"(h)
+        : [line_size]"r"((mips_reg)line_size)
+        : "memory"
+    );
+}
+
+void ff_avg_pixels16_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    double ftmp[8];
+    mips_reg addr[3];
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr2],   %[line_size],   %[line_size]            \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp4],   0x0f(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr1],   %[block],       %[line_size]            \n\t"
+        "gsldrc1    %[ftmp4],   0x08(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp5],   0x0f(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp5],   0x08(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[block])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[block])                          \n\t"
+        "gsldlc1    %[ftmp6],   0x0f(%[block])                          \n\t"
+        "gsldrc1    %[ftmp6],   0x08(%[block])                          \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "gsldlc1    %[ftmp7],   0x0f(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp7],   0x08(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "pavgb      %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        "sdc1       %[ftmp4],   0x08(%[block])                          \n\t"
+        "gssdxc1    %[ftmp5],   0x08(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr2]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr2]                \n\t"
+
+        "gsldlc1    %[ftmp0],   0x07(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp4],   0x0f(%[pixels])                         \n\t"
+        PTR_ADDU   "%[addr1],   %[block],       %[line_size]            \n\t"
+        "gsldrc1    %[ftmp4],   0x08(%[pixels])                         \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp5],   0x0f(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp5],   0x08(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[block])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[block])                          \n\t"
+        "gsldlc1    %[ftmp6],   0x0f(%[block])                          \n\t"
+        "gsldrc1    %[ftmp6],   0x08(%[block])                          \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "gsldlc1    %[ftmp7],   0x0f(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp7],   0x08(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "pavgb      %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[block],  %[line_size])           \n\t"
+        "sdc1       %[ftmp4],   0x08(%[block])                          \n\t"
+        "gssdxc1    %[ftmp5],   0x08(%[block],  %[line_size])           \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[addr2]                \n\t"
+        PTR_ADDU   "%[block],   %[block],       %[addr2]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),
+          [block]"+&r"(block),              [pixels]"+&r"(pixels),
+          [h]"+&r"(h)
+        : [line_size]"r"((mips_reg)line_size)
+        : "memory"
+    );
+}
+
+inline void ff_put_pixels4_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h)
+{
+    double ftmp[4];
+    mips_reg addr[5];
+    uint64_t low32;
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr2],   %[src_stride1], %[src_stride1]          \n\t"
+        PTR_ADDU   "%[addr3],   %[src_stride2], %[src_stride2]          \n\t"
+        PTR_ADDU   "%[addr4],   %[dst_stride],  %[dst_stride]           \n\t"
+        "1:                                                             \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "uld        %[low32],   0x00(%[src1])                           \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        "uld        %[low32],   0x00(%[addr0])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   0x00(%[src2])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "uld        %[low32],   0x00(%[addr1])                          \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "swc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gsswxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "uld        %[low32],   0x00(%[src1])                           \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        "uld        %[low32],   0x00(%[addr0])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   0x00(%[src2])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "uld        %[low32],   0x00(%[addr1])                          \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "swc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gsswxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),
+          [low32]"=&r"(low32),
+          [dst]"+&r"(dst),                  [src1]"+&r"(src1),
+          [src2]"+&r"(src2),                [h]"+&r"(h)
+        : [dst_stride]"r"((mips_reg)dst_stride),
+          [src_stride1]"r"((mips_reg)src_stride1),
+          [src_stride2]"r"((mips_reg)src_stride2)
+        : "memory"
+    );
+}
+
+inline void ff_put_pixels8_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h)
+{
+    double ftmp[4];
+    mips_reg addr[5];
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr2],   %[src_stride1], %[src_stride1]          \n\t"
+        PTR_ADDU   "%[addr3],   %[src_stride2], %[src_stride2]          \n\t"
+        PTR_ADDU   "%[addr4],   %[dst_stride],  %[dst_stride]           \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[src1])                           \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[src2])                           \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        "gsldlc1    %[ftmp0],   0x07(%[src1])                           \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[src2])                           \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),
+          [dst]"+&r"(dst),                  [src1]"+&r"(src1),
+          [src2]"+&r"(src2),                [h]"+&r"(h)
+        : [dst_stride]"r"((mips_reg)dst_stride),
+          [src_stride1]"r"((mips_reg)src_stride1),
+          [src_stride2]"r"((mips_reg)src_stride2)
+        : "memory"
+    );
+}
+
+inline void ff_put_pixels16_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h)
+{
+    double ftmp[8];
+    mips_reg addr[5];
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr2],   %[src_stride1], %[src_stride1]          \n\t"
+        PTR_ADDU   "%[addr3],   %[src_stride2], %[src_stride2]          \n\t"
+        PTR_ADDU   "%[addr4],   %[dst_stride],  %[dst_stride]           \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[src1])                           \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp4],   0x0f(%[src1])                           \n\t"
+        "gsldrc1    %[ftmp4],   0x08(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp5],   0x0f(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp5],   0x08(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[src2])                           \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp6],   0x0f(%[src2])                           \n\t"
+        "gsldrc1    %[ftmp6],   0x08(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "gsldlc1    %[ftmp7],   0x0f(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp7],   0x08(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "pavgb      %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        "sdc1       %[ftmp4],   0x08(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp5],   0x08(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        "gsldlc1    %[ftmp0],   0x07(%[src1])                           \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp4],   0x0f(%[src1])                           \n\t"
+        "gsldrc1    %[ftmp4],   0x08(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp5],   0x0f(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp5],   0x08(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[src2])                           \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp6],   0x0f(%[src2])                           \n\t"
+        "gsldrc1    %[ftmp6],   0x08(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "gsldlc1    %[ftmp7],   0x0f(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp7],   0x08(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "pavgb      %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        "sdc1       %[ftmp4],   0x08(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp5],   0x08(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),
+          [dst]"+&r"(dst),                  [src1]"+&r"(src1),
+          [src2]"+&r"(src2),                [h]"+&r"(h)
+        : [dst_stride]"r"((mips_reg)dst_stride),
+          [src_stride1]"r"((mips_reg)src_stride1),
+          [src_stride2]"r"((mips_reg)src_stride2)
+        : "memory"
+    );
+}
+
+inline void ff_avg_pixels4_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h)
+{
+    double ftmp[6];
+    mips_reg addr[6];
+    uint64_t low32;
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr2],   %[src_stride1], %[src_stride1]          \n\t"
+        PTR_ADDU   "%[addr3],   %[src_stride2], %[src_stride2]          \n\t"
+        PTR_ADDU   "%[addr4],   %[dst_stride],  %[dst_stride]           \n\t"
+        "1:                                                             \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "uld        %[low32],   0x00(%[src1])                           \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        "uld        %[low32],   0x00(%[addr0])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   0x00(%[src2])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "uld        %[low32],   0x00(%[addr1])                          \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr5],   %[dst],         %[dst_stride]           \n\t"
+        "uld        %[low32],   0x00(%[dst])                            \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        "uld        %[low32],   0x00(%[addr5])                          \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "swc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gsswxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "uld        %[low32],   0x00(%[src1])                           \n\t"
+        "mtc1       %[low32],   %[ftmp0]                                \n\t"
+        "uld        %[low32],   0x00(%[addr0])                          \n\t"
+        "mtc1       %[low32],   %[ftmp1]                                \n\t"
+        "uld        %[low32],   0x00(%[src2])                           \n\t"
+        "mtc1       %[low32],   %[ftmp2]                                \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "uld        %[low32],   0x00(%[addr1])                          \n\t"
+        "mtc1       %[low32],   %[ftmp3]                                \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr5],   %[dst],         %[dst_stride]           \n\t"
+        "uld        %[low32],   0x00(%[dst])                            \n\t"
+        "mtc1       %[low32],   %[ftmp4]                                \n\t"
+        "uld        %[low32],   0x00(%[addr5])                          \n\t"
+        "mtc1       %[low32],   %[ftmp5]                                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "swc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gsswxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),            [addr5]"=&r"(addr[5]),
+          [low32]"=&r"(low32),
+          [dst]"+&r"(dst),                  [src1]"+&r"(src1),
+          [src2]"+&r"(src2),                [h]"+&r"(h)
+        : [dst_stride]"r"((mips_reg)dst_stride),
+          [src_stride1]"r"((mips_reg)src_stride1),
+          [src_stride2]"r"((mips_reg)src_stride2)
+        : "memory"
+    );
+}
+
+inline void ff_avg_pixels8_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h)
+{
+    double ftmp[6];
+    mips_reg addr[6];
+
+    __asm__ volatile (
+        PTR_ADDU   "%[addr2],   %[src_stride1], %[src_stride1]          \n\t"
+        PTR_ADDU   "%[addr3],   %[src_stride2], %[src_stride2]          \n\t"
+        PTR_ADDU   "%[addr4],   %[dst_stride],  %[dst_stride]           \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[src1])                           \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[src2])                           \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr5],   %[dst],         %[dst_stride]           \n\t"
+        "gsldlc1    %[ftmp4],   0x07(%[dst])                            \n\t"
+        "gsldrc1    %[ftmp4],   0x00(%[dst])                            \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[addr5])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        "gsldlc1    %[ftmp0],   0x07(%[src1])                           \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[src2])                           \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        PTR_ADDU   "%[addr5],   %[dst],         %[dst_stride]           \n\t"
+        "gsldlc1    %[ftmp4],   0x07(%[dst])                            \n\t"
+        "gsldrc1    %[ftmp4],   0x00(%[dst])                            \n\t"
+        "gsldlc1    %[ftmp5],   0x07(%[addr5])                          \n\t"
+        "gsldrc1    %[ftmp5],   0x00(%[addr5])                          \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),            [addr5]"=&r"(addr[5]),
+          [dst]"+&r"(dst),                  [src1]"+&r"(src1),
+          [src2]"+&r"(src2),                [h]"+&r"(h)
+        : [dst_stride]"r"((mips_reg)dst_stride),
+          [src_stride1]"r"((mips_reg)src_stride1),
+          [src_stride2]"r"((mips_reg)src_stride2)
+        : "memory"
+    );
+}
+
+inline void ff_avg_pixels16_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h)
+{
+    ff_avg_pixels8_l2_8_mmi(dst, src1, src2, dst_stride, src_stride1,
+            src_stride2, h);
+    ff_avg_pixels8_l2_8_mmi(dst + 8, src1 + 8, src2 + 8, dst_stride,
+            src_stride1, src_stride2, h);
+}
+
+void ff_put_pixels4_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_pixels4_l2_8_mmi(block, pixels, pixels + 1, line_size, line_size,
+            line_size, h);
+}
+
+void ff_put_pixels8_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_pixels8_l2_8_mmi(block, pixels, pixels + 1, line_size, line_size,
+            line_size, h);
+}
+
+void ff_put_pixels16_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_pixels16_l2_8_mmi(block, pixels, pixels + 1, line_size, line_size,
+            line_size, h);
+}
+
+void ff_avg_pixels4_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_avg_pixels4_l2_8_mmi(block, pixels, pixels + 1, line_size, line_size,
+            line_size, h);
+}
+
+void ff_avg_pixels8_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_avg_pixels8_l2_8_mmi(block, pixels, pixels + 1, line_size, line_size,
+            line_size, h);
+}
+
+void ff_avg_pixels16_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_avg_pixels8_x2_8_mmi(block, pixels, line_size, h);
+    ff_avg_pixels8_x2_8_mmi(block + 8, pixels + 8, line_size, h);
+}
+
+inline void ff_put_no_rnd_pixels8_l2_8_mmi(uint8_t *dst, const uint8_t *src1,
+    const uint8_t *src2, int dst_stride, int src_stride1, int src_stride2,
+    int h)
+{
+    double ftmp[5];
+    mips_reg addr[5];
+
+    __asm__ volatile (
+        "pcmpeqb    %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        PTR_ADDU   "%[addr2],   %[src_stride1], %[src_stride1]          \n\t"
+        PTR_ADDU   "%[addr3],   %[src_stride2], %[src_stride2]          \n\t"
+        PTR_ADDU   "%[addr4],   %[dst_stride],  %[dst_stride]           \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[src1])                           \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[src2])                           \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp4]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp4]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        "gsldlc1    %[ftmp0],   0x07(%[src1])                           \n\t"
+        PTR_ADDU   "%[addr0],   %[src1],        %[src_stride1]          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src1])                           \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[src2])                           \n\t"
+        PTR_ADDU   "%[addr1],   %[src2],        %[src_stride2]          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[src2])                           \n\t"
+        "gsldlc1    %[ftmp3],   0x07(%[addr1])                          \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[addr2]                \n\t"
+        "gsldrc1    %[ftmp3],   0x00(%[addr1])                          \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp4]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "pavgb      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "pavgb      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp4]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[dst])                            \n\t"
+        "gssdxc1    %[ftmp1],   0x00(%[dst],    %[dst_stride])          \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[addr3]                \n\t"
+        PTR_ADDU   "%[dst],     %[dst],         %[addr4]                \n\t"
+
+        PTR_ADDI   "%[h],       %[h],           -0x04                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [addr2]"=&r"(addr[2]),            [addr3]"=&r"(addr[3]),
+          [addr4]"=&r"(addr[4]),
+          [dst]"+&r"(dst),                  [src1]"+&r"(src1),
+          [src2]"+&r"(src2),                [h]"+&r"(h)
+        : [dst_stride]"r"((mips_reg)dst_stride),
+          [src_stride1]"r"((mips_reg)src_stride1),
+          [src_stride2]"r"((mips_reg)src_stride2)
+        : "memory"
+    );
+}
+
+void ff_put_no_rnd_pixels8_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_no_rnd_pixels8_l2_8_mmi(block, pixels, pixels + 1, line_size,
+            line_size, line_size, h);
+}
+
+void ff_put_no_rnd_pixels16_x2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_no_rnd_pixels8_x2_8_mmi(block, pixels, line_size, h);
+    ff_put_no_rnd_pixels8_x2_8_mmi(block + 8, pixels + 8, line_size, h);
+}
+
+void ff_put_pixels4_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_pixels4_l2_8_mmi(block, pixels, pixels + line_size, line_size,
+            line_size, line_size, h);
+}
+
+void ff_put_pixels8_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_pixels8_l2_8_mmi(block, pixels, pixels + line_size, line_size,
+            line_size, line_size, h);
+}
+
+void ff_put_pixels16_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_pixels16_l2_8_mmi(block, pixels, pixels + line_size, line_size,
+            line_size, line_size, h);
+}
+
+void ff_avg_pixels4_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_avg_pixels4_l2_8_mmi(block, pixels, pixels + line_size, line_size,
+            line_size, line_size, h);
+}
+
+void ff_avg_pixels8_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_avg_pixels8_l2_8_mmi(block, pixels, pixels + line_size, line_size,
+            line_size, line_size, h);
+}
+
+void ff_avg_pixels16_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_avg_pixels8_y2_8_mmi(block, pixels, line_size, h);
+    ff_avg_pixels8_y2_8_mmi(block + 8, pixels + 8, line_size, h);
+}
+
+void ff_put_no_rnd_pixels8_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_no_rnd_pixels8_l2_8_mmi(block, pixels, pixels + line_size,
+            line_size, line_size, line_size, h);
+}
+
+void ff_put_no_rnd_pixels16_y2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_no_rnd_pixels8_y2_8_mmi(block, pixels, line_size, h);
+    ff_put_no_rnd_pixels8_y2_8_mmi(block + 8 , pixels + 8, line_size, h);
+}
+
+void ff_put_pixels4_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    /* FIXME HIGH BIT DEPTH */
+    int i;
+    const uint32_t a = AV_RN32(pixels);
+    const uint32_t b = AV_RN32(pixels + 1);
+    uint32_t l0 = (a & 0x03030303UL) +
+                  (b & 0x03030303UL) +
+                       0x02020202UL;
+    uint32_t h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+                  ((b & 0xFCFCFCFCUL) >> 2);
+    uint32_t l1, h1;
+
+    pixels += line_size;
+    for (i = 0; i < h; i += 2) {
+        uint32_t a = AV_RN32(pixels);
+        uint32_t b = AV_RN32(pixels + 1);
+        l1 = (a & 0x03030303UL) +
+             (b & 0x03030303UL);
+        h1 = ((a & 0xFCFCFCFCUL) >> 2) +
+             ((b & 0xFCFCFCFCUL) >> 2);
+        *((uint32_t *) block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
+        pixels += line_size;
+        block  += line_size;
+        a  = AV_RN32(pixels);
+        b  = AV_RN32(pixels + 1);
+        l0 = (a & 0x03030303UL) +
+             (b & 0x03030303UL) +
+                  0x02020202UL;
+        h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+             ((b & 0xFCFCFCFCUL) >> 2);
+        *((uint32_t *) block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
+        pixels += line_size;
+        block  += line_size;
+    }
+}
+
+void ff_put_pixels8_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+#if 1
+    double ftmp[10];
+    mips_reg addr[2];
+
+    __asm__ volatile (
+        "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "dli        %[addr0],   0x0f                                    \n\t"
+        "pcmpeqw    %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "dmtc1      %[addr0],   %[ftmp8]                                \n\t"
+        "dli        %[addr0],   0x01                                    \n\t"
+        "psrlh      %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+        "dmtc1      %[addr0],   %[ftmp8]                                \n\t"
+        "psllh      %[ftmp6],   %[ftmp6],       %[ftmp8]                \n\t"
+
+        "dli        %[addr0],   0x02                                    \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[pixels])                         \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "dmtc1      %[addr0],   %[ftmp9]                                \n\t"
+        "gsldlc1    %[ftmp4],   0x08(%[pixels])                         \n\t"
+        "gsldrc1    %[ftmp4],   0x01(%[pixels])                         \n\t"
+        "mov.d      %[ftmp1],   %[ftmp0]                                \n\t"
+        "mov.d      %[ftmp5],   %[ftmp4]                                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]                \n\t"
+        "punpckhbh  %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "punpckhbh  %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "paddush    %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "paddush    %[ftmp5],   %[ftmp5],       %[ftmp1]                \n\t"
+        "xor        %[addr0],   %[addr0],       %[addr0]                \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[line_size]            \n\t"
+        ".p2align   3                                                   \n\t"
+        "1:                                                             \n\t"
+        PTR_ADDU   "%[addr1],   %[pixels],      %[addr0]                \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[addr1])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x08(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x01(%[addr1])                          \n\t"
+        "mov.d      %[ftmp1],   %[ftmp0]                                \n\t"
+        "mov.d      %[ftmp3],   %[ftmp2]                                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp7]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "punpckhbh  %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "paddush    %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "paddush    %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "paddush    %[ftmp4],   %[ftmp4],       %[ftmp6]                \n\t"
+        "paddush    %[ftmp5],   %[ftmp5],       %[ftmp6]                \n\t"
+        "paddush    %[ftmp4],   %[ftmp4],       %[ftmp0]                \n\t"
+        "paddush    %[ftmp5],   %[ftmp5],       %[ftmp1]                \n\t"
+        "psrlh      %[ftmp4],   %[ftmp4],       %[ftmp9]                \n\t"
+        "psrlh      %[ftmp5],   %[ftmp5],       %[ftmp9]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "gssdxc1    %[ftmp4],   0x00(%[block],  %[addr0])               \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[line_size]            \n\t"
+        PTR_ADDU   "%[addr1],   %[pixels],      %[addr0]                \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[addr1])                          \n\t"
+        "gsldlc1    %[ftmp4],   0x08(%[addr1])                          \n\t"
+        "gsldrc1    %[ftmp4],   0x01(%[addr1])                          \n\t"
+        "mov.d      %[ftmp3],   %[ftmp2]                                \n\t"
+        "mov.d      %[ftmp5],   %[ftmp4]                                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "punpcklbh  %[ftmp4],   %[ftmp4],       %[ftmp7]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "punpckhbh  %[ftmp5],   %[ftmp5],       %[ftmp7]                \n\t"
+        "paddush    %[ftmp4],   %[ftmp4],       %[ftmp2]                \n\t"
+        "paddush    %[ftmp5],   %[ftmp5],       %[ftmp3]                \n\t"
+        "paddush    %[ftmp0],   %[ftmp0],       %[ftmp6]                \n\t"
+        "paddush    %[ftmp1],   %[ftmp1],       %[ftmp6]                \n\t"
+        "paddush    %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "paddush    %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "psrlh      %[ftmp0],   %[ftmp0],       %[ftmp9]                \n\t"
+        "psrlh      %[ftmp1],   %[ftmp1],       %[ftmp9]                \n\t"
+        "packushb   %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "gssdxc1    %[ftmp0],   0x00(%[block],  %[addr0])               \n\t"
+        PTR_ADDU   "%[addr0],   %[addr0],       %[line_size]            \n\t"
+        PTR_ADDU   "%[h],       %[h],           -0x02                   \n\t"
+        "bnez       %[h],       1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [addr0]"=&r"(addr[0]),            [addr1]"=&r"(addr[1]),
+          [h]"+&r"(h),                      [pixels]"+&r"(pixels)
+        : [block]"r"(block),                [line_size]"r"((mips_reg)line_size)
+        : "memory"
+    );
+#else
+    /* FIXME HIGH BIT DEPTH */
+    int j;
+
+    for (j = 0; j < 2; j++) {
+        int i;
+        const uint32_t a = AV_RN32(pixels);
+        const uint32_t b = AV_RN32(pixels + 1);
+        uint32_t l0 = (a & 0x03030303UL) +
+                      (b & 0x03030303UL) +
+                           0x02020202UL;
+        uint32_t h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+                      ((b & 0xFCFCFCFCUL) >> 2);
+        uint32_t l1, h1;
+
+        pixels += line_size;
+        for (i = 0; i < h; i += 2) {
+            uint32_t a = AV_RN32(pixels);
+            uint32_t b = AV_RN32(pixels + 1);
+            l1 = (a & 0x03030303UL) +
+                 (b & 0x03030303UL);
+            h1 = ((a & 0xFCFCFCFCUL) >> 2) +
+                 ((b & 0xFCFCFCFCUL) >> 2);
+            *((uint32_t *) block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
+            pixels += line_size;
+            block  += line_size;
+            a  = AV_RN32(pixels);
+            b  = AV_RN32(pixels + 1);
+            l0 = (a & 0x03030303UL) +
+                 (b & 0x03030303UL) +
+                      0x02020202UL;
+            h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+                 ((b & 0xFCFCFCFCUL) >> 2);
+            *((uint32_t *) block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
+            pixels += line_size;
+            block  += line_size;
+        }
+        pixels += 4 - line_size * (h + 1);
+        block  += 4 - line_size * h;
+    }
+#endif
+}
+
+void ff_put_pixels16_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_pixels8_xy2_8_mmi(block, pixels, line_size, h);
+    ff_put_pixels8_xy2_8_mmi(block + 8, pixels + 8, line_size, h);
+}
+
+void ff_avg_pixels4_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    /* FIXME HIGH BIT DEPTH */
+    int i;
+    const uint32_t a = AV_RN32(pixels);
+    const uint32_t b = AV_RN32(pixels + 1);
+    uint32_t l0 = (a & 0x03030303UL) +
+                  (b & 0x03030303UL) +
+                       0x02020202UL;
+    uint32_t h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+                  ((b & 0xFCFCFCFCUL) >> 2);
+    uint32_t l1, h1;
+
+    pixels += line_size;
+    for (i = 0; i < h; i += 2) {
+        uint32_t a = AV_RN32(pixels);
+        uint32_t b = AV_RN32(pixels + 1);
+        l1 = (a & 0x03030303UL) +
+             (b & 0x03030303UL);
+        h1 = ((a & 0xFCFCFCFCUL) >> 2) +
+             ((b & 0xFCFCFCFCUL) >> 2);
+        *((uint32_t *) block) = rnd_avg32(*((uint32_t *) block), h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL));
+        pixels += line_size;
+        block  += line_size;
+        a  = AV_RN32(pixels);
+        b  = AV_RN32(pixels + 1);
+        l0 = (a & 0x03030303UL) +
+             (b & 0x03030303UL) +
+                  0x02020202UL;
+        h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+             ((b & 0xFCFCFCFCUL) >> 2);
+        *((uint32_t *) block) = rnd_avg32(*((uint32_t *) block), h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL));
+        pixels += line_size;
+        block  += line_size;
+    }
+}
+
+void ff_avg_pixels8_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    /* FIXME HIGH BIT DEPTH */
+    int j;
+
+    for (j = 0; j < 2; j++) {
+        int i;
+        const uint32_t a = AV_RN32(pixels);
+        const uint32_t b = AV_RN32(pixels + 1);
+        uint32_t l0 = (a & 0x03030303UL) +
+                      (b & 0x03030303UL) +
+                           0x02020202UL;
+        uint32_t h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+                      ((b & 0xFCFCFCFCUL) >> 2);
+        uint32_t l1, h1;
+
+        pixels += line_size;
+        for (i = 0; i < h; i += 2) {
+            uint32_t a = AV_RN32(pixels);
+            uint32_t b = AV_RN32(pixels + 1);
+            l1 = (a & 0x03030303UL) +
+                 (b & 0x03030303UL);
+            h1 = ((a & 0xFCFCFCFCUL) >> 2) +
+                 ((b & 0xFCFCFCFCUL) >> 2);
+            *((uint32_t *) block) = rnd_avg32(*((uint32_t *) block), h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL));
+            pixels += line_size;
+            block  += line_size;
+            a  = AV_RN32(pixels);
+            b  = AV_RN32(pixels + 1);
+            l0 = (a & 0x03030303UL) +
+                 (b & 0x03030303UL) +
+                      0x02020202UL;
+            h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+                 ((b & 0xFCFCFCFCUL) >> 2);
+            *((uint32_t *) block) = rnd_avg32(*((uint32_t *) block), h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL));
+            pixels += line_size;
+            block  += line_size;
+        }
+        pixels += 4 - line_size * (h + 1);
+        block  += 4 - line_size * h;
+    }
+}
+
+void ff_avg_pixels16_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_avg_pixels8_xy2_8_mmi(block, pixels, line_size, h);
+    ff_avg_pixels8_xy2_8_mmi(block + 8, pixels + 8, line_size, h);
+}
+
+void ff_put_no_rnd_pixels8_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    /* FIXME HIGH BIT DEPTH */
+    int j;
+
+    for (j = 0; j < 2; j++) {
+        int i;
+        const uint32_t a = AV_RN32(pixels);
+        const uint32_t b = AV_RN32(pixels + 1);
+        uint32_t l0 = (a & 0x03030303UL) +
+                      (b & 0x03030303UL) +
+                           0x01010101UL;
+        uint32_t h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+                      ((b & 0xFCFCFCFCUL) >> 2);
+        uint32_t l1, h1;
+
+        pixels += line_size;
+        for (i = 0; i < h; i += 2) {
+            uint32_t a = AV_RN32(pixels);
+            uint32_t b = AV_RN32(pixels + 1);
+            l1 = (a & 0x03030303UL) +
+                 (b & 0x03030303UL);
+            h1 = ((a & 0xFCFCFCFCUL) >> 2) +
+                 ((b & 0xFCFCFCFCUL) >> 2);
+            *((uint32_t *) block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
+            pixels += line_size;
+            block  += line_size;
+            a  = AV_RN32(pixels);
+            b  = AV_RN32(pixels + 1);
+            l0 = (a & 0x03030303UL) +
+                 (b & 0x03030303UL) +
+                      0x01010101UL;
+            h0 = ((a & 0xFCFCFCFCUL) >> 2) +
+                 ((b & 0xFCFCFCFCUL) >> 2);
+            *((uint32_t *) block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
+            pixels += line_size;
+            block  += line_size;
+        }
+        pixels += 4 - line_size * (h + 1);
+        block  += 4 - line_size * h;
+    }
+}
+
+void ff_put_no_rnd_pixels16_xy2_8_mmi(uint8_t *block, const uint8_t *pixels,
+    ptrdiff_t line_size, int h)
+{
+    ff_put_no_rnd_pixels8_xy2_8_mmi(block, pixels, line_size, h);
+    ff_put_no_rnd_pixels8_xy2_8_mmi(block + 8, pixels + 8, line_size, h);
+}
diff --git a/libavcodec/mips/idctdsp_mmi.c b/libavcodec/mips/idctdsp_mmi.c
index 25476f3..24beb62 100644
--- a/libavcodec/mips/idctdsp_mmi.c
+++ b/libavcodec/mips/idctdsp_mmi.c
@@ -23,63 +23,75 @@
 
 #include "idctdsp_mips.h"
 #include "constants.h"
+#include "libavutil/mips/asmdefs.h"
 
 void ff_put_pixels_clamped_mmi(const int16_t *block,
         uint8_t *av_restrict pixels, ptrdiff_t line_size)
 {
-    const int16_t *p;
-    uint8_t *pix;
-
-    p = block;
-    pix = pixels;
+    double ftmp[8];
+    mips_reg addr[1];
 
     __asm__ volatile (
-        "ldc1 $f0, 0+%3                 \r\n"
-        "ldc1 $f2, 8+%3                 \r\n"
-        "ldc1 $f4, 16+%3                \r\n"
-        "ldc1 $f6, 24+%3                \r\n"
-        "ldc1 $f8, 32+%3                \r\n"
-        "ldc1 $f10, 40+%3               \r\n"
-        "ldc1 $f12, 48+%3               \r\n"
-        "ldc1 $f14, 56+%3               \r\n"
-        "dadd $10, %0, %1               \r\n"
-        "packushb $f0, $f0, $f2         \r\n"
-        "packushb $f4, $f4, $f6         \r\n"
-        "packushb $f8, $f8, $f10        \r\n"
-        "packushb $f12, $f12, $f14      \r\n"
-        "sdc1 $f0, 0(%0)                \r\n"
-        "sdc1 $f4, 0($10)               \r\n"
-        "gssdxc1 $f8, 0($10, %1)        \r\n"
-        "gssdxc1 $f12, 0(%0, %2)        \r\n"
-        ::"r"(pix),"r"((int)line_size),
-          "r"((int)line_size*3),"m"(*p)
-        : "$10","memory"
+        "ldc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "ldc1       %[ftmp1],   0x08(%[block])                          \n\t"
+        "ldc1       %[ftmp2],   0x10(%[block])                          \n\t"
+        "ldc1       %[ftmp3],   0x18(%[block])                          \n\t"
+        "ldc1       %[ftmp4],   0x20(%[block])                          \n\t"
+        "ldc1       %[ftmp5],   0x28(%[block])                          \n\t"
+        "ldc1       %[ftmp6],   0x30(%[block])                          \n\t"
+        "ldc1       %[ftmp7],   0x38(%[block])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "packushb   %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "packushb   %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "packushb   %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "sdc1       %[ftmp2],   0x00(%[addr0])                          \n\t"
+        "gssdxc1    %[ftmp4],   0x00(%[addr0],  %[line_size])           \n\t"
+        "gssdxc1    %[ftmp6],   0x00(%[pixels], %[line_sizex3])         \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [addr0]"=&r"(addr[0]),
+          [pixels]"+&r"(pixels)
+        : [line_size]"r"((mips_reg)line_size),
+          [line_sizex3]"r"((mips_reg)(line_size*3)),
+          [block]"r"(block)
+        : "memory"
     );
 
-    pix += line_size*4;
-    p += 32;
+    pixels += line_size*4;
+    block += 32;
 
     __asm__ volatile (
-        "ldc1 $f0, 0+%3                 \r\n"
-        "ldc1 $f2, 8+%3                 \r\n"
-        "ldc1 $f4, 16+%3                \r\n"
-        "ldc1 $f6, 24+%3                \r\n"
-        "ldc1 $f8, 32+%3                \r\n"
-        "ldc1 $f10, 40+%3               \r\n"
-        "ldc1 $f12, 48+%3               \r\n"
-        "ldc1 $f14, 56+%3               \r\n"
-        "dadd $10, %0, %1               \r\n"
-        "packushb $f0, $f0, $f2         \r\n"
-        "packushb $f4, $f4, $f6         \r\n"
-        "packushb $f8, $f8, $f10        \r\n"
-        "packushb $f12, $f12, $f14      \r\n"
-        "sdc1 $f0, 0(%0)                \r\n"
-        "sdc1 $f4, 0($10)               \r\n"
-        "gssdxc1 $f8, 0($10, %1)        \r\n"
-        "gssdxc1 $f12, 0(%0, %2)        \r\n"
-        ::"r"(pix),"r"((int)line_size),
-          "r"((int)line_size*3),"m"(*p)
-        : "$10","memory"
+        "ldc1       %[ftmp0],   0x00(%[block])                          \n\t"
+        "ldc1       %[ftmp1],   0x08(%[block])                          \n\t"
+        "ldc1       %[ftmp2],   0x10(%[block])                          \n\t"
+        "ldc1       %[ftmp3],   0x18(%[block])                          \n\t"
+        "ldc1       %[ftmp4],   0x20(%[block])                          \n\t"
+        "ldc1       %[ftmp5],   0x28(%[block])                          \n\t"
+        "ldc1       %[ftmp6],   0x30(%[block])                          \n\t"
+        "ldc1       %[ftmp7],   0x38(%[block])                          \n\t"
+        PTR_ADDU   "%[addr0],   %[pixels],      %[line_size]            \n\t"
+        "packushb   %[ftmp0],   %[ftmp0],       %[ftmp1]                \n\t"
+        "packushb   %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "packushb   %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "packushb   %[ftmp6],   %[ftmp6],       %[ftmp7]                \n\t"
+        "sdc1       %[ftmp0],   0x00(%[pixels])                         \n\t"
+        "sdc1       %[ftmp2],   0x00(%[addr0])                          \n\t"
+        "gssdxc1    %[ftmp4],   0x00(%[addr0],  %[line_size])           \n\t"
+        "gssdxc1    %[ftmp6],   0x00(%[pixels], %[line_sizex3])         \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [addr0]"=&r"(addr[0]),
+          [pixels]"+&r"(pixels)
+        : [line_size]"r"((mips_reg)line_size),
+          [line_sizex3]"r"((mips_reg)(line_size*3)),
+          [block]"r"(block)
+        : "memory"
     );
 }
 
@@ -87,104 +99,110 @@ void ff_put_signed_pixels_clamped_mmi(const int16_t *block,
     uint8_t *av_restrict pixels, ptrdiff_t line_size)
 {
     int64_t line_skip = line_size;
-    int64_t line_skip3;
+    int64_t line_skip3 = 0;
+    double ftmp[5];
+    mips_reg addr[1];
 
     __asm__ volatile (
-        "dmtc1 %4, $f0                  \n\t"
-        "daddu %1, %3, %3               \n\t"
-        "ldc1 $f2, 0(%2)                \n\t"
-        "ldc1 $f10, 8(%2)               \n\t"
-        "packsshb $f2, $f2, $f10        \n\t"
-        "ldc1 $f4, 16(%2)               \n\t"
-        "ldc1 $f10, 24(%2)              \n\t"
-        "packsshb $f4, $f4, $f10        \n\t"
-        "ldc1 $f6, 32(%2)               \n\t"
-        "ldc1 $f10, 40(%2)              \n\t"
-        "packsshb $f6, $f6, $f10        \n\t"
-        "ldc1 $f8, 48(%2)               \n\t"
-        "ldc1 $f10, 56(%2)              \n\t"
-        "packsshb $f8, $f8, $f10        \n\t"
-        "paddb $f2, $f2, $f0            \n\t"
-        "paddb $f4, $f4, $f0            \n\t"
-        "paddb $f6, $f6, $f0            \n\t"
-        "paddb $f8, $f8, $f0            \n\t"
-        "sdc1 $f2, 0(%0)                \n\t"
-        "gssdxc1 $f4, 0(%0, %3)         \n\t"
-        "gssdxc1 $f6, 0(%0, %1)         \n\t"
-        "daddu %1, %1, %3               \n\t"
-        "gssdxc1 $f8, 0(%0, %1)         \n\t"
-        "daddu $10, %1, %3              \n\t"
-        "daddu %0, %0, $10              \n\t"
-        "ldc1 $f2, 64(%2)               \n\t"
-        "ldc1 $f10, 8+64(%2)            \n\t"
-        "packsshb  $f2, $f2, $f10       \n\t"
-        "ldc1 $f4, 16+64(%2)            \n\t"
-        "ldc1 $f10, 24+64(%2)           \n\t"
-        "packsshb $f4, $f4, $f10        \n\t"
-        "ldc1 $f6, 32+64(%2)            \n\t"
-        "ldc1 $f10, 40+64(%2)           \n\t"
-        "packsshb $f6, $f6, $f10        \n\t"
-        "ldc1 $f8, 48+64(%2)            \n\t"
-        "ldc1 $f10, 56+64(%2)           \n\t"
-        "packsshb $f8, $f8, $f10        \n\t"
-        "paddb $f2, $f2, $f0            \n\t"
-        "paddb $f4, $f4, $f0            \n\t"
-        "paddb $f6, $f6, $f0            \n\t"
-        "paddb $f8, $f8, $f0            \n\t"
-        "sdc1 $f2, 0(%0)                \n\t"
-        "gssdxc1 $f4, 0(%0, %3)         \n\t"
-        "daddu $10, %3, %3              \n\t"
-        "gssdxc1 $f6, 0(%0, $10)        \n\t"
-        "gssdxc1 $f8, 0(%0, %1)         \n\t"
-        : "+&r"(pixels),"=&r"(line_skip3)
-        : "r"(block),"r"(line_skip),"r"(ff_pb_80)
-        : "$10","memory"
+        PTR_ADDU   "%[line_skip3],  %[line_skip],   %[line_skip]        \n\t"
+        "ldc1       %[ftmp1],       0x00(%[block])                      \n\t"
+        "ldc1       %[ftmp0],       0x08(%[block])                      \n\t"
+        "packsshb   %[ftmp1],       %[ftmp1],       %[ftmp0]            \n\t"
+        "ldc1       %[ftmp2],       0x10(%[block])                      \n\t"
+        "ldc1       %[ftmp0],       0x18(%[block])                      \n\t"
+        "packsshb   %[ftmp2],       %[ftmp2],       %[ftmp0]            \n\t"
+        "ldc1       %[ftmp3],       0x20(%[block])                      \n\t"
+        "ldc1       %[ftmp0],       0x28(%[block])                      \n\t"
+        "packsshb   %[ftmp3],       %[ftmp3],       %[ftmp0]            \n\t"
+        "ldc1       %[ftmp4],       48(%[block])                        \n\t"
+        "ldc1       %[ftmp0],       56(%[block])                        \n\t"
+        "packsshb   %[ftmp4],       %[ftmp4],       %[ftmp0]            \n\t"
+        "paddb      %[ftmp1],       %[ftmp1],       %[ff_pb_80]         \n\t"
+        "paddb      %[ftmp2],       %[ftmp2],       %[ff_pb_80]         \n\t"
+        "paddb      %[ftmp3],       %[ftmp3],       %[ff_pb_80]         \n\t"
+        "paddb      %[ftmp4],       %[ftmp4],       %[ff_pb_80]         \n\t"
+        "sdc1       %[ftmp1],       0x00(%[pixels])                     \n\t"
+        "gssdxc1    %[ftmp2],       0x00(%[pixels], %[line_skip])       \n\t"
+        "gssdxc1    %[ftmp3],       0x00(%[pixels], %[line_skip3])      \n\t"
+        PTR_ADDU   "%[line_skip3],  %[line_skip3],  %[line_skip]        \n\t"
+        "gssdxc1    %[ftmp4],       0x00(%[pixels], %[line_skip3])      \n\t"
+        PTR_ADDU   "%[addr0],       %[line_skip3],  %[line_skip]        \n\t"
+        PTR_ADDU   "%[pixels],      %[pixels],      %[addr0]            \n\t"
+        "ldc1       %[ftmp1],       0x40(%[block])                      \n\t"
+        "ldc1       %[ftmp0],       0x48(%[block])                      \n\t"
+        "packsshb   %[ftmp1],       %[ftmp1],       %[ftmp0]            \n\t"
+        "ldc1       %[ftmp2],       0x50(%[block])                      \n\t"
+        "ldc1       %[ftmp0],       0x58(%[block])                      \n\t"
+        "packsshb   %[ftmp2],       %[ftmp2],       %[ftmp0]            \n\t"
+        "ldc1       %[ftmp3],       0x60(%[block])                      \n\t"
+        "ldc1       %[ftmp0],       0x68(%[block])                      \n\t"
+        "packsshb   %[ftmp3],       %[ftmp3],       %[ftmp0]            \n\t"
+        "ldc1       %[ftmp4],       0x70(%[block])                      \n\t"
+        "ldc1       %[ftmp0],       0x78(%[block])                      \n\t"
+        "packsshb   %[ftmp4],       %[ftmp4],       %[ftmp0]            \n\t"
+        "paddb      %[ftmp1],       %[ftmp1],       %[ff_pb_80]         \n\t"
+        "paddb      %[ftmp2],       %[ftmp2],       %[ff_pb_80]         \n\t"
+        "paddb      %[ftmp3],       %[ftmp3],       %[ff_pb_80]         \n\t"
+        "paddb      %[ftmp4],       %[ftmp4],       %[ff_pb_80]         \n\t"
+        "sdc1       %[ftmp1],       0x00(%[pixels])                     \n\t"
+        "gssdxc1    %[ftmp2],       0x00(%[pixels], %[line_skip])       \n\t"
+        PTR_ADDU   "%[addr0],       %[line_skip],   %[line_skip]        \n\t"
+        "gssdxc1    %[ftmp3],       0x00(%[pixels], %[addr0])           \n\t"
+        "gssdxc1    %[ftmp4],       0x00(%[pixels], %[line_skip3])      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),
+          [addr0]"=&r"(addr[0]),
+          [pixels]"+&r"(pixels),            [line_skip3]"+&r"(line_skip3)
+        : [block]"r"(block),
+          [line_skip]"r"((mips_reg)line_skip),
+          [ff_pb_80]"f"(ff_pb_80)
+        : "memory"
     );
 }
 
 void ff_add_pixels_clamped_mmi(const int16_t *block,
         uint8_t *av_restrict pixels, ptrdiff_t line_size)
 {
-    const int16_t *p;
-    uint8_t *pix;
-    int i = 4;
-
-    p = block;
-    pix = pixels;
+    double ftmp[8];
+    uint64_t tmp[1];
 
     __asm__ volatile (
-        "xor $f14, $f14, $f14           \r\n"
-        ::
+        "li         %[tmp0],    0x04                                    \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "1:                                                             \n\t"
+        "ldc1       %[ftmp1],   0x00(%[block])                          \n\t"
+        "ldc1       %[ftmp2],   0x08(%[block])                          \n\t"
+        "ldc1       %[ftmp3],   0x10(%[block])                          \n\t"
+        "ldc1       %[ftmp4],   0x18(%[block])                          \n\t"
+        "ldc1       %[ftmp5],   0x00(%[pixels])                         \n\t"
+        "gsldxc1    %[ftmp6],   0x00(%[pixels], %[line_size])           \n\t"
+        "mov.d      %[ftmp7],   %[ftmp5]                                \n\t"
+        "punpcklbh  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp7],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp7]                \n\t"
+        "mov.d      %[ftmp7],   %[ftmp6]                                \n\t"
+        "punpcklbh  %[ftmp6],   %[ftmp6],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp7],   %[ftmp7],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp6]                \n\t"
+        "paddh      %[ftmp4],   %[ftmp4],       %[ftmp7]                \n\t"
+        "packushb   %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "packushb   %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "sdc1       %[ftmp1],   0x00(%[pixels])                         \n\t"
+        "gssdxc1    %[ftmp3],   0x00(%[pixels], %[line_size])           \n\t"
+        "addi       %[tmp0],    %[tmp0],        -0x01                   \n\t"
+        PTR_ADDIU  "%[block],   %[block],       0x20                    \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[line_size]            \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[line_size]            \n\t"
+        "bnez       %[tmp0],    1b"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [tmp0]"=&r"(tmp[0]),
+          [pixels]"+&r"(pixels),            [block]"+&r"(block)
+        : [line_size]"r"((mips_reg)line_size)
+        : "memory"
     );
-
-    do {
-        __asm__ volatile (
-            "ldc1 $f0, 0+%2             \r\n"
-            "ldc1 $f2, 8+%2             \r\n"
-            "ldc1 $f4, 16+%2            \r\n"
-            "ldc1 $f6, 24+%2            \r\n"
-            "ldc1 $f8, %0               \r\n"
-            "ldc1 $f12, %1              \r\n"
-            "mov.d $f10, $f8            \r\n"
-            "punpcklbh $f8, $f8, $f14   \r\n"
-            "punpckhbh $f10, $f10, $f14 \r\n"
-            "paddsh $f0, $f0, $f8       \r\n"
-            "paddsh $f2, $f2, $f10      \r\n"
-            "mov.d $f10, $f12           \r\n"
-            "punpcklbh $f12, $f12, $f14 \r\n"
-            "punpckhbh $f10, $f10, $f14 \r\n"
-            "paddsh $f4, $f4, $f12      \r\n"
-            "paddsh $f6, $f6, $f10      \r\n"
-            "packushb $f0, $f0, $f2     \r\n"
-            "packushb $f4, $f4, $f6     \r\n"
-            "sdc1 $f0, %0               \r\n"
-            "sdc1 $f4, %1               \r\n"
-            : "+m"(*pix),"+m"(*(pix+line_size))
-            : "m"(*p)
-            : "memory"
-        );
-
-        pix += line_size*2;
-        p += 16;
-    } while (--i);
 }
diff --git a/libavcodec/mips/mpegvideo_mmi.c b/libavcodec/mips/mpegvideo_mmi.c
index 94781e6..450a18c 100644
--- a/libavcodec/mips/mpegvideo_mmi.c
+++ b/libavcodec/mips/mpegvideo_mmi.c
@@ -23,11 +23,14 @@
  */
 
 #include "mpegvideo_mips.h"
+#include "libavutil/mips/asmdefs.h"
 
 void ff_dct_unquantize_h263_intra_mmi(MpegEncContext *s, int16_t *block,
         int n, int qscale)
 {
     int64_t level, qmul, qadd, nCoeffs;
+    double ftmp[6];
+    mips_reg addr[1];
 
     qmul = qscale << 1;
     av_assert2(s->block_last_index[n]>=0 || s->h263_aic);
@@ -49,48 +52,50 @@ void ff_dct_unquantize_h263_intra_mmi(MpegEncContext *s, int16_t *block,
         nCoeffs = s->inter_scantable.raster_end[s->block_last_index[n]];
 
     __asm__ volatile (
-        "xor $f12, $f12, $f12           \r\n"
-        "lwc1 $f12, %1                  \n\r"
-        "xor $f10, $f10, $f10           \r\n"
-        "lwc1 $f10, %2                  \r\n"
-        "xor $f14, $f14, $f14           \r\n"
-        "packsswh $f12, $f12, $f12      \r\n"
-        "packsswh $f12, $f12, $f12      \r\n"
-        "packsswh $f10, $f10, $f10      \r\n"
-        "packsswh $f10, $f10, $f10      \r\n"
-        "psubh $f14, $f14, $f10         \r\n"
-        "xor $f8, $f8, $f8              \r\n"
-        ".p2align 4                     \r\n"
-        "1:                             \r\n"
-        "daddu $8, %0, %3               \r\n"
-        "gsldlc1 $f0, 7($8)             \r\n"
-        "gsldrc1 $f0, 0($8)             \r\n"
-        "gsldlc1 $f2, 15($8)            \r\n"
-        "gsldrc1 $f2, 8($8)             \r\n"
-        "mov.d $f4, $f0                 \r\n"
-        "mov.d $f6, $f2                 \r\n"
-        "pmullh $f0, $f0, $f12          \r\n"
-        "pmullh $f2, $f2, $f12          \r\n"
-        "pcmpgth $f4, $f4, $f8          \r\n"
-        "pcmpgth $f6, $f6, $f8          \r\n"
-        "xor $f0, $f0, $f4              \r\n"
-        "xor $f2, $f2, $f6              \r\n"
-        "paddh $f0, $f0, $f14           \r\n"
-        "paddh $f2, $f2, $f14           \r\n"
-        "xor $f4, $f4, $f0              \r\n"
-        "xor $f6, $f6, $f2              \r\n"
-        "pcmpeqh $f0, $f0, $f14         \r\n"
-        "pcmpeqh $f2, $f2, $f14         \r\n"
-        "pandn $f0, $f0, $f4            \r\n"
-        "pandn $f2, $f2, $f6            \r\n"
-        "gssdlc1 $f0, 7($8)             \r\n"
-        "gssdrc1 $f0, 0($8)             \r\n"
-        "gssdlc1 $f2, 15($8)            \r\n"
-        "gssdrc1 $f2, 8($8)             \r\n"
-        "addi %3, %3, 16                \r\n"
-        "blez %3, 1b                    \r\n"
-        ::"r"(block+nCoeffs),"m"(qmul),"m"(qadd),"r"(2*(-nCoeffs))
-        :"$8","memory"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "packsswh   %[qmul],    %[qmul],        %[qmul]                 \n\t"
+        "packsswh   %[qmul],    %[qmul],        %[qmul]                 \n\t"
+        "packsswh   %[qadd],    %[qadd],        %[qadd]                 \n\t"
+        "packsswh   %[qadd],    %[qadd],        %[qadd]                 \n\t"
+        "psubh      %[ftmp0],   %[ftmp0],       %[qadd]                 \n\t"
+        "xor        %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        ".p2align   4                                                   \n\t"
+        "1:                                                             \n\t"
+        PTR_ADDU   "%[addr0],   %[block],       %[nCoeffs]              \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x0f(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x08(%[addr0])                          \n\t"
+        "mov.d      %[ftmp3],   %[ftmp1]                                \n\t"
+        "mov.d      %[ftmp4],   %[ftmp2]                                \n\t"
+        "pmullh     %[ftmp1],   %[ftmp1],       %[qmul]                 \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[qmul]                 \n\t"
+        "pcmpgth    %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "pcmpgth    %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "xor        %[ftmp4],   %[ftmp4],       %[ftmp2]                \n\t"
+        "pcmpeqh    %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "pcmpeqh    %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "pandn      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "pandn      %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        PTR_ADDIU  "%[nCoeffs], %[nCoeffs],     0x10                    \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gssdlc1    %[ftmp2],   0x0f(%[addr0])                          \n\t"
+        "gssdrc1    %[ftmp2],   0x08(%[addr0])                          \n\t"
+        "blez       %[nCoeffs], 1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [addr0]"=&r"(addr[0])
+        : [block]"r"((mips_reg)(block+nCoeffs)),
+          [nCoeffs]"r"((mips_reg)(2*(-nCoeffs))),
+          [qmul]"f"(qmul),                  [qadd]"f"(qadd)
+        : "memory"
     );
 
     block[0] = level;
@@ -100,6 +105,8 @@ void ff_dct_unquantize_h263_inter_mmi(MpegEncContext *s, int16_t *block,
         int n, int qscale)
 {
     int64_t qmul, qadd, nCoeffs;
+    double ftmp[6];
+    mips_reg addr[1];
 
     qmul = qscale << 1;
     qadd = (qscale - 1) | 1;
@@ -107,48 +114,50 @@ void ff_dct_unquantize_h263_inter_mmi(MpegEncContext *s, int16_t *block,
     nCoeffs = s->inter_scantable.raster_end[s->block_last_index[n]];
 
     __asm__ volatile (
-        "xor $f12, $f12, $f12           \r\n"
-        "lwc1 $f12, %1                  \r\n"
-        "xor $f10, $f10, $f10           \r\n"
-        "lwc1 $f10, %2                  \r\n"
-        "packsswh $f12, $f12, $f12      \r\n"
-        "packsswh $f12, $f12, $f12      \r\n"
-        "xor $f14, $f14, $f14           \r\n"
-        "packsswh $f10, $f10, $f10      \r\n"
-        "packsswh $f10, $f10, $f10      \r\n"
-        "psubh $f14, $f14, $f10         \r\n"
-        "xor $f8, $f8, $f8              \r\n"
-        ".p2align 4                     \r\n"
-        "1:                             \r\n"
-        "daddu $8, %0, %3               \r\n"
-        "gsldlc1 $f0, 7($8)             \r\n"
-        "gsldrc1 $f0, 0($8)             \r\n"
-        "gsldlc1 $f2, 15($8)            \r\n"
-        "gsldrc1 $f2, 8($8)             \r\n"
-        "mov.d $f4, $f0                 \r\n"
-        "mov.d $f6, $f2                 \r\n"
-        "pmullh $f0, $f0, $f12          \r\n"
-        "pmullh $f2, $f2, $f12          \r\n"
-        "pcmpgth $f4, $f4, $f8          \r\n"
-        "pcmpgth $f6, $f6, $f8          \r\n"
-        "xor $f0, $f0, $f4              \r\n"
-        "xor $f2, $f2, $f6              \r\n"
-        "paddh $f0, $f0, $f14           \r\n"
-        "paddh $f2, $f2, $f14           \r\n"
-        "xor $f4, $f4, $f0              \r\n"
-        "xor $f6, $f6, $f2              \r\n"
-        "pcmpeqh $f0, $f0, $f14         \r\n"
-        "pcmpeqh $f2, $f2, $f14         \r\n"
-        "pandn $f0, $f0, $f4            \r\n"
-        "pandn $f2, $f2, $f6            \r\n"
-        "gssdlc1 $f0, 7($8)             \r\n"
-        "gssdrc1 $f0, 0($8)             \r\n"
-        "gssdlc1 $f2, 15($8)            \r\n"
-        "gssdrc1 $f2, 8($8)             \r\n"
-        "addi %3, %3, 16                \r\n"
-        "blez %3, 1b                    \r\n"
-        ::"r"(block+nCoeffs),"m"(qmul),"m"(qadd),"r"(2*(-nCoeffs))
-        : "$8","memory"
+        "packsswh   %[qmul],    %[qmul],        %[qmul]                 \n\t"
+        "packsswh   %[qmul],    %[qmul],        %[qmul]                 \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "packsswh   %[qadd],    %[qadd],        %[qadd]                 \n\t"
+        "packsswh   %[qadd],    %[qadd],        %[qadd]                 \n\t"
+        "psubh      %[ftmp0],   %[ftmp0],       %[qadd]                 \n\t"
+        "xor        %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        ".p2align   4                                                   \n\t"
+        "1:                                                             \n\t"
+        PTR_ADDU   "%[addr0],   %[block],       %[nCoeffs]              \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gsldlc1    %[ftmp2],   0x0f(%[addr0])                          \n\t"
+        "gsldrc1    %[ftmp2],   0x08(%[addr0])                          \n\t"
+        "mov.d      %[ftmp3],   %[ftmp1]                                \n\t"
+        "mov.d      %[ftmp4],   %[ftmp2]                                \n\t"
+        "pmullh     %[ftmp1],   %[ftmp1],       %[qmul]                 \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[qmul]                 \n\t"
+        "pcmpgth    %[ftmp3],   %[ftmp3],       %[ftmp5]                \n\t"
+        "pcmpgth    %[ftmp4],   %[ftmp4],       %[ftmp5]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "paddh      %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp1]                \n\t"
+        "xor        %[ftmp4],   %[ftmp4],       %[ftmp2]                \n\t"
+        "pcmpeqh    %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "pcmpeqh    %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "pandn      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "pandn      %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        PTR_ADDIU  "%[nCoeffs], %[nCoeffs],     0x10                    \n\t"
+        "gssdlc1    %[ftmp1],   0x07(%[addr0])                          \n\t"
+        "gssdrc1    %[ftmp1],   0x00(%[addr0])                          \n\t"
+        "gssdlc1    %[ftmp2],   0x0f(%[addr0])                          \n\t"
+        "gssdrc1    %[ftmp2],   0x08(%[addr0])                          \n\t"
+        "blez       %[nCoeffs], 1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [addr0]"=&r"(addr[0])
+        : [block]"r"((mips_reg)(block+nCoeffs)),
+          [nCoeffs]"r"((mips_reg)(2*(-nCoeffs))),
+          [qmul]"f"(qmul),                  [qadd]"f"(qadd)
+        : "memory"
     );
 }
 
@@ -158,6 +167,9 @@ void ff_dct_unquantize_mpeg1_intra_mmi(MpegEncContext *s, int16_t *block,
     int64_t nCoeffs;
     const uint16_t *quant_matrix;
     int block0;
+    double ftmp[10];
+    uint64_t tmp[1];
+    mips_reg addr[1];
 
     av_assert2(s->block_last_index[n]>=0);
     nCoeffs = s->intra_scantable.raster_end[s->block_last_index[n]] + 1;
@@ -171,60 +183,68 @@ void ff_dct_unquantize_mpeg1_intra_mmi(MpegEncContext *s, int16_t *block,
     quant_matrix = s->intra_matrix;
 
     __asm__ volatile (
-        "pcmpeqh $f14, $f14, $f14       \r\n"
-        "dli $10, 15                    \r\n"
-        "dmtc1 $10, $f16                \r\n"
-        "xor $f12, $f12, $f12           \r\n"
-        "lwc1 $f12, %2                  \r\n"
-        "psrlh $f14, $f14, $f16         \r\n"
-        "packsswh $f12, $f12, $f12      \r\n"
-        "packsswh $f12, $f12, $f12      \r\n"
-        "or $8, %3, $0                  \r\n"
-        ".p2align 4                     \r\n"
-        "1:                             \r\n"
-        "gsldxc1 $f0, 0($8, %0)         \r\n"
-        "gsldxc1 $f2, 8($8, %0)         \r\n"
-        "mov.d $f16, $f0                \r\n"
-        "mov.d $f18, $f2                \r\n"
-        "gsldxc1 $f8, 0($8, %1)         \r\n"
-        "gsldxc1 $f10, 8($8, %1)        \r\n"
-        "pmullh $f8, $f8, $f12          \r\n"
-        "pmullh $f10, $f10, $f12        \r\n"
-        "xor $f4, $f4, $f4              \r\n"
-        "xor $f6, $f6, $f6              \r\n"
-        "pcmpgth $f4, $f4, $f0          \r\n"
-        "pcmpgth $f6, $f6, $f2          \r\n"
-        "xor $f0, $f0, $f4              \r\n"
-        "xor $f2, $f2, $f6              \r\n"
-        "psubh $f0, $f0, $f4            \r\n"
-        "psubh $f2, $f2, $f6            \r\n"
-        "pmullh $f0, $f0, $f8           \r\n"
-        "pmullh $f2, $f2, $f10          \r\n"
-        "xor $f8, $f8, $f8              \r\n"
-        "xor $f10, $f10, $f10           \r\n"
-        "pcmpeqh $f8, $f8, $f16         \r\n"
-        "pcmpeqh $f10, $f10, $f18       \r\n"
-        "dli $10, 3                     \r\n"
-        "dmtc1 $10, $f16                \r\n"
-        "psrah $f0, $f0, $f16           \r\n"
-        "psrah $f2, $f2, $f16           \r\n"
-        "psubh $f0, $f0, $f14           \r\n"
-        "psubh $f2, $f2, $f14           \r\n"
-        "or $f0, $f0, $f14              \r\n"
-        "or $f2, $f2, $f14              \r\n"
-        "xor $f0, $f0, $f4              \r\n"
-        "xor $f2, $f2, $f6              \r\n"
-        "psubh $f0, $f0, $f4            \r\n"
-        "psubh $f2, $f2, $f6            \r\n"
-        "pandn $f8, $f8, $f0            \r\n"
-        "pandn $f10, $f10, $f2          \r\n"
-        "gssdxc1 $f8, 0($8, %0)         \r\n"
-        "gssdxc1 $f10, 8($8, %0)        \r\n"
-        "addi $8, $8, 16                \r\n"
-        "bltz $8, 1b                    \r\n"
-        ::"r"(block+nCoeffs),"r"(quant_matrix+nCoeffs),"m"(qscale),
-          "g"(-2*nCoeffs)
-        : "$8","$10","memory"
+        "dli        %[tmp0],    0x0f                                    \n\t"
+        "pcmpeqh    %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dmtc1      %[tmp0],    %[ftmp4]                                \n\t"
+        "dmtc1      %[qscale],  %[ftmp1]                                \n\t"
+        "psrlh      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "packsswh   %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        "packsswh   %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        "or         %[addr0],   %[nCoeffs],     $0                      \n\t"
+        ".p2align   4                                                   \n\t"
+        "1:                                                             \n\t"
+        "gsldxc1    %[ftmp2],   0x00(%[addr0],  %[block])               \n\t"
+        "gsldxc1    %[ftmp3],   0x08(%[addr0],  %[block])               \n\t"
+        "mov.d      %[ftmp4],   %[ftmp2]                                \n\t"
+        "mov.d      %[ftmp5],   %[ftmp3]                                \n\t"
+        "gsldxc1    %[ftmp6],   0x00(%[addr0],  %[quant])               \n\t"
+        "gsldxc1    %[ftmp7],   0x08(%[addr0],  %[quant])               \n\t"
+        "pmullh     %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "xor        %[ftmp8],   %[ftmp8],       %[ftmp8]                \n\t"
+        "xor        %[ftmp9],   %[ftmp9],       %[ftmp9]                \n\t"
+        "pcmpgth    %[ftmp8],   %[ftmp8],       %[ftmp2]                \n\t"
+        "pcmpgth    %[ftmp9],   %[ftmp9],       %[ftmp3]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "pmullh     %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "xor        %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "pcmpeqh    %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+        "dli        %[tmp0],    0x03                                    \n\t"
+        "pcmpeqh    %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+        "dmtc1      %[tmp0],    %[ftmp4]                                \n\t"
+        "psrah      %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "psrah      %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "or         %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "or         %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "pandn      %[ftmp6],   %[ftmp6],       %[ftmp2]                \n\t"
+        "pandn      %[ftmp7],   %[ftmp7],       %[ftmp3]                \n\t"
+        "gssdxc1    %[ftmp6],   0x00(%[addr0],  %[block])               \n\t"
+        "gssdxc1    %[ftmp7],   0x08(%[addr0],  %[block])               \n\t"
+        PTR_ADDIU  "%[addr0],   %[addr0],       0x10                    \n\t"
+        "bltz       %[addr0],   1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp[0]),
+          [addr0]"=&r"(addr[0])
+        : [block]"r"((mips_reg)(block+nCoeffs)),
+          [quant]"r"((mips_reg)(quant_matrix+nCoeffs)),
+          [nCoeffs]"r"((mips_reg)(2*(-nCoeffs))),
+          [qscale]"r"(qscale)
+        : "memory"
     );
 
     block[0] = block0;
@@ -235,132 +255,81 @@ void ff_dct_unquantize_mpeg1_inter_mmi(MpegEncContext *s, int16_t *block,
 {
     int64_t nCoeffs;
     const uint16_t *quant_matrix;
+    double ftmp[10];
+    uint64_t tmp[1];
+    mips_reg addr[1];
 
     av_assert2(s->block_last_index[n] >= 0);
     nCoeffs = s->intra_scantable.raster_end[s->block_last_index[n]] + 1;
     quant_matrix = s->inter_matrix;
 
     __asm__ volatile (
-        "pcmpeqh $f14, $f14, $f14       \r\n"
-        "dli $10, 15                    \r\n"
-        "dmtc1 $10, $f16                \r\n"
-        "xor $f12, $f12, $f12           \r\n"
-        "lwc1 $f12, %2                  \r\n"
-        "psrlh $f14, $f14, $f16         \r\n"
-        "packsswh $f12, $f12, $f12      \r\n"
-        "packsswh $f12, $f12, $f12      \r\n"
-        "or $8, %3, $0                  \r\n"
-        ".p2align 4                     \r\n"
-        "1:                             \r\n"
-        "gsldxc1 $f0, 0($8, %0)         \r\n"
-        "gsldxc1 $f2, 8($8, %0)         \r\n"
-        "mov.d $f16, $f0                \r\n"
-        "mov.d $f18, $f2                \r\n"
-        "gsldxc1 $f8, 0($8, %1)         \r\n"
-        "gsldxc1 $f10, 8($8, %1)        \r\n"
-        "pmullh $f8, $f8, $f12          \r\n"
-        "pmullh $f10, $f10, $f12        \r\n"
-        "xor $f4, $f4, $f4              \r\n"
-        "xor $f6, $f6, $f6              \r\n"
-        "pcmpgth $f4, $f4, $f0          \r\n"
-        "pcmpgth $f6, $f6, $f2          \r\n"
-        "xor $f0, $f0, $f4              \r\n"
-        "xor $f2, $f2, $f6              \r\n"
-        "psubh $f0, $f0, $f4            \r\n"
-        "psubh $f2, $f2, $f6            \r\n"
-        "paddh $f0, $f0, $f0            \r\n"
-        "paddh $f2, $f2, $f2            \r\n"
-        "paddh $f0, $f0, $f14           \r\n"
-        "paddh $f2, $f2, $f14           \r\n"
-        "pmullh $f0, $f0, $f8           \r\n"
-        "pmullh $f2, $f2, $f10          \r\n"
-        "xor $f8, $f8, $f8              \r\n"
-        "xor $f10, $f10, $f10           \r\n"
-        "pcmpeqh $f8, $f8, $f16         \r\n"
-        "pcmpeqh $f10, $f10, $f18       \r\n"
-        "dli $10, 4                     \r\n"
-        "dmtc1 $10, $f16                \r\n"
-        "psrah $f0, $f0, $f16           \r\n"
-        "psrah $f2, $f2, $f16           \r\n"
-        "psubh $f0, $f0, $f14           \r\n"
-        "psubh $f2, $f2, $f14           \r\n"
-        "or $f0, $f0, $f14              \r\n"
-        "or $f2, $f2, $f14              \r\n"
-        "xor $f0, $f0, $f4              \r\n"
-        "xor $f2, $f2, $f6              \r\n"
-        "psubh $f0, $f0, $f4            \r\n"
-        "psubh $f2, $f2, $f6            \r\n"
-        "pandn $f8, $f8, $f0            \r\n"
-        "pandn $f10, $f10, $f2          \r\n"
-        "gssdxc1 $f8, 0($8, %0)         \r\n"
-        "gssdxc1 $f10, 8($8, %0)        \r\n"
-        "addi $8, $8, 16                \r\n"
-        "bltz $8, 1b                    \r\n"
-        ::"r"(block+nCoeffs),"r"(quant_matrix+nCoeffs),"m"(qscale),
-          "g"(-2*nCoeffs)
-        :"$8","$10","memory"
-    );
-}
-
-void ff_denoise_dct_mmi(MpegEncContext *s, int16_t *block)
-{
-    const int intra = s->mb_intra;
-    int *sum = s->dct_error_sum[intra];
-    uint16_t *offset = s->dct_offset[intra];
-
-    s->dct_count[intra]++;
-
-    __asm__ volatile(
-        "xor $f14, $f14, $f14               \r\n"
-        "1:                                 \r\n"
-        "ldc1 $f4, 0(%[block])              \r\n"
-        "xor $f0, $f0, $f0                  \r\n"
-        "ldc1 $f6, 8(%[block])              \r\n"
-        "xor $f2, $f2, $f2                  \r\n"
-        "pcmpgth $f0, $f0, $f4              \r\n"
-        "pcmpgth $f2, $f2, $f6              \r\n"
-        "xor $f4, $f4, $f0                  \r\n"
-        "xor $f6, $f6, $f2                  \r\n"
-        "psubh $f4, $f4, $f0                \r\n"
-        "psubh $f6, $f6, $f2                \r\n"
-        "ldc1 $f12, 0(%[offset])            \r\n"
-        "mov.d $f8, $f4                     \r\n"
-        "psubush $f4, $f4, $f12             \r\n"
-        "ldc1 $f12, 8(%[offset])            \r\n"
-        "mov.d $f10, $f6                    \r\n"
-        "psubush $f6, $f6, $f12             \r\n"
-        "xor $f4, $f4, $f0                  \r\n"
-        "xor $f6, $f6, $f2                  \r\n"
-        "psubh $f4, $f4, $f0                \r\n"
-        "psubh $f6, $f6, $f2                \r\n"
-        "sdc1 $f4, 0(%[block])              \r\n"
-        "sdc1 $f6, 8(%[block])              \r\n"
-        "mov.d $f4, $f8                     \r\n"
-        "mov.d $f6, $f10                    \r\n"
-        "punpcklhw $f8, $f8, $f14           \r\n"
-        "punpckhhw $f4, $f4, $f14           \r\n"
-        "punpcklhw $f10, $f10, $f14         \r\n"
-        "punpckhhw $f6, $f6, $f14           \r\n"
-        "ldc1 $f0, 0(%[sum])                \r\n"
-        "paddw $f8, $f8, $f0                \r\n"
-        "ldc1 $f0, 8(%[sum])                \r\n"
-        "paddw $f4, $f4, $f0                \r\n"
-        "ldc1 $f0, 16(%[sum])               \r\n"
-        "paddw $f10, $f10, $f0              \r\n"
-        "ldc1 $f0, 24(%[sum])               \r\n"
-        "paddw $f6, $f6, $f0                \r\n"
-        "sdc1 $f8, 0(%[sum])                \r\n"
-        "sdc1 $f4, 8(%[sum])                \r\n"
-        "sdc1 $f10, 16(%[sum])              \r\n"
-        "sdc1 $f6, 24(%[sum])               \r\n"
-        "daddiu %[block], %[block], 16      \r\n"
-        "daddiu %[sum], %[sum], 32          \r\n"
-        "daddiu %[offset], %[offset], 16    \r\n"
-        "dsubu $8, %[block1], %[block]      \r\n"
-        "bgtz $8, 1b                        \r\n"
-        : [block]"+r"(block),[sum]"+r"(sum),[offset]"+r"(offset)
-        : [block1]"r"(block+64)
-        : "$8","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14"
+        "dli        %[tmp0],    0x0f                                    \n\t"
+        "pcmpeqh    %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "dmtc1      %[tmp0],    %[ftmp4]                                \n\t"
+        "dmtc1      %[qscale],  %[ftmp1]                                \n\t"
+        "psrlh      %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "packsswh   %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        "packsswh   %[ftmp1],   %[ftmp1],       %[ftmp1]                \n\t"
+        "or         %[addr0],   %[nCoeffs],     $0                      \n\t"
+        ".p2align   4                                                   \n\t"
+        "1:                                                             \n\t"
+        "gsldxc1    %[ftmp2],   0x00(%[addr0],  %[block])               \n\t"
+        "gsldxc1    %[ftmp3],   0x08(%[addr0],  %[block])               \n\t"
+        "mov.d      %[ftmp4],   %[ftmp2]                                \n\t"
+        "mov.d      %[ftmp5],   %[ftmp3]                                \n\t"
+        "gsldxc1    %[ftmp6],   0x00(%[addr0],  %[quant])               \n\t"
+        "gsldxc1    %[ftmp7],   0x08(%[addr0],  %[quant])               \n\t"
+        "pmullh     %[ftmp6],   %[ftmp6],       %[ftmp1]                \n\t"
+        "pmullh     %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "xor        %[ftmp8],   %[ftmp8],       %[ftmp8]                \n\t"
+        "xor        %[ftmp9],   %[ftmp9],       %[ftmp9]                \n\t"
+        "pcmpgth    %[ftmp8],   %[ftmp8],       %[ftmp2]                \n\t"
+        "pcmpgth    %[ftmp9],   %[ftmp9],       %[ftmp3]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp2]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp3]                \n\t"
+        "paddh      %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "paddh      %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "pmullh     %[ftmp3],   %[ftmp3],       %[ftmp7]                \n\t"
+        "xor        %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "pcmpeqh    %[ftmp6],   %[ftmp6],       %[ftmp4]                \n\t"
+        "dli        %[tmp0],    0x04                                    \n\t"
+        "pcmpeqh    %[ftmp7],   %[ftmp7],       %[ftmp5]                \n\t"
+        "dmtc1      %[tmp0],    %[ftmp4]                                \n\t"
+        "psrah      %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "psrah      %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "or         %[ftmp2],   %[ftmp2],       %[ftmp0]                \n\t"
+        "or         %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp9]                \n\t"
+        "pandn      %[ftmp6],   %[ftmp6],       %[ftmp2]                \n\t"
+        "pandn      %[ftmp7],   %[ftmp7],       %[ftmp3]                \n\t"
+        "gssdxc1    %[ftmp6],   0x00(%[addr0],  %[block])               \n\t"
+        "gssdxc1    %[ftmp7],   0x08(%[addr0],  %[block])               \n\t"
+        PTR_ADDIU  "%[addr0],   %[addr0],       0x10                    \n\t"
+        "bltz       %[addr0],   1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp[0]),
+          [addr0]"=&r"(addr[0])
+        : [block]"r"((mips_reg)(block+nCoeffs)),
+          [quant]"r"((mips_reg)(quant_matrix+nCoeffs)),
+          [nCoeffs]"r"((mips_reg)(2*(-nCoeffs))),
+          [qscale]"r"(qscale)
+        : "memory"
     );
 }
 
@@ -370,6 +339,9 @@ void ff_dct_unquantize_mpeg2_intra_mmi(MpegEncContext *s, int16_t *block,
     uint64_t nCoeffs;
     const uint16_t *quant_matrix;
     int block0;
+    double ftmp[10];
+    uint64_t tmp[1];
+    mips_reg addr[1];
 
     assert(s->block_last_index[n]>=0);
 
@@ -386,58 +358,135 @@ void ff_dct_unquantize_mpeg2_intra_mmi(MpegEncContext *s, int16_t *block,
     quant_matrix = s->intra_matrix;
 
     __asm__ volatile (
-        "pcmpeqh $f14, $f14, $f14           \r\n"
-        "dli $10, 15                        \r\n"
-        "dmtc1 $10, $f16                    \r\n"
-        "xor $f12, $f12, $f12               \r\n"
-        "lwc1 $f12, %[qscale]               \r\n"
-        "psrlh $f14, $f14, $f16             \r\n"
-        "packsswh $f12, $f12, $f12          \r\n"
-        "packsswh $f12, $f12, $f12          \r\n"
-        "or $8, %[ncoeffs], $0              \r\n"
-        ".p2align 4                         \r\n"
-        "1:                                 \r\n"
-        "gsldxc1 $f0, 0($8, %[block])       \r\n"
-        "gsldxc1 $f2, 8($8, %[block])       \r\n"
-        "mov.d $f16, $f0                    \r\n"
-        "mov.d $f18, $f2                    \r\n"
-        "gsldxc1 $f8, 0($8, %[quant])       \r\n"
-        "gsldxc1 $f10, 0($8, %[quant])      \r\n"
-        "pmullh $f8, $f8, $f12              \r\n"
-        "pmullh $f10, $f10, $f12            \r\n"
-        "xor $f4, $f4, $f4                  \r\n"
-        "xor $f6, $f6, $f6                  \r\n"
-        "pcmpgth $f4, $f4, $f0              \r\n"
-        "pcmpgth $f6, $f6, $f2              \r\n"
-        "xor $f0, $f0, $f4                  \r\n"
-        "xor $f2, $f2, $f6                  \r\n"
-        "psubh $f0, $f0, $f4                \r\n"
-        "psubh $f2, $f2, $f6                \r\n"
-        "pmullh $f0, $f0, $f8               \r\n"
-        "pmullh $f2, $f2, $f10              \r\n"
-        "xor $f8, $f8, $f8                  \r\n"
-        "xor $f10, $f10, $f10               \r\n"
-        "pcmpeqh $f8, $f8, $f16             \r\n"
-        "pcmpeqh $f10 ,$f10, $f18           \r\n"
-        "dli $10, 3                         \r\n"
-        "dmtc1 $10, $f16                    \r\n"
-        "psrah $f0, $f0, $f16               \r\n"
-        "psrah $f2, $f2, $f16               \r\n"
-        "xor $f0, $f0, $f4                  \r\n"
-        "xor $f2, $f2, $f6                  \r\n"
-        "psubh $f0, $f0, $f4                \r\n"
-        "psubh $f2, $f2, $f6                \r\n"
-        "pandn $f8, $f8, $f0                \r\n"
-        "pandn $f10, $f10, $f2              \r\n"
-        "gssdxc1 $f8, 0($8, %[block])       \r\n"
-        "gssdxc1 $f10, 8($8, %[block])      \r\n"
-        "daddiu $8, $8, 16                  \r\n"
-        "blez $8, 1b                        \r\n"
-        ::[block]"r"(block+nCoeffs),[quant]"r"(quant_matrix+nCoeffs),
-          [qscale]"m"(qscale),[ncoeffs]"g"(-2*nCoeffs)
-        : "$8","$10","$f0","$f2","$f4","$f6","$f8","$f10","$f12","$f14","$f16",
-          "$f18"
+        "dli        %[tmp0],    0x0f                                    \n\t"
+        "pcmpeqh    %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "mtc1       %[tmp0],    %[ftmp3]                                \n\t"
+        "mtc1       %[qscale],  %[ftmp9]                                \n\t"
+        "psrlh      %[ftmp0],   %[ftmp0],       %[ftmp3]                \n\t"
+        "packsswh   %[ftmp9],   %[ftmp9],       %[ftmp9]                \n\t"
+        "packsswh   %[ftmp9],   %[ftmp9],       %[ftmp9]                \n\t"
+        "or         %[addr0],   %[nCoeffs],     $0                      \n\t"
+        ".p2align   4                                                   \n\t"
+        "1:                                                             \n\t"
+        "gsldxc1    %[ftmp1],   0x00(%[addr0],  %[block])               \n\t"
+        "gsldxc1    %[ftmp2],   0x08(%[addr0],  %[block])               \n\t"
+        "mov.d      %[ftmp3],   %[ftmp1]                                \n\t"
+        "mov.d      %[ftmp4],   %[ftmp2]                                \n\t"
+        "gsldxc1    %[ftmp5],   0x00(%[addr0],  %[quant])               \n\t"
+        "gsldxc1    %[ftmp6],   0x00(%[addr0],  %[quant])               \n\t"
+        "pmullh     %[ftmp5],   %[ftmp5],       %[ftmp9]                \n\t"
+        "pmullh     %[ftmp6],   %[ftmp6],       %[ftmp9]                \n\t"
+        "xor        %[ftmp7],   %[ftmp7],       %[ftmp7]                \n\t"
+        "xor        %[ftmp8],   %[ftmp8],       %[ftmp8]                \n\t"
+        "pcmpgth    %[ftmp7],   %[ftmp7],       %[ftmp1]                \n\t"
+        "pcmpgth    %[ftmp8],   %[ftmp8],       %[ftmp2]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "psubh      %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "pmullh     %[ftmp1],   %[ftmp1],       %[ftmp5]                \n\t"
+        "pmullh     %[ftmp2],   %[ftmp2],       %[ftmp6]                \n\t"
+        "xor        %[ftmp5],   %[ftmp5],       %[ftmp5]                \n\t"
+        "xor        %[ftmp6],   %[ftmp6],       %[ftmp6]                \n\t"
+        "pcmpeqh    %[ftmp5],   %[ftmp5],       %[ftmp3]                \n\t"
+        "dli        %[tmp0],    0x03                                    \n\t"
+        "pcmpeqh    %[ftmp6] ,  %[ftmp6],       %[ftmp4]                \n\t"
+        "mtc1       %[tmp0],    %[ftmp3]                                \n\t"
+        "psrah      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "psrah      %[ftmp2],   %[ftmp2],       %[ftmp3]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "psubh      %[ftmp1],   %[ftmp1],       %[ftmp7]                \n\t"
+        "psubh      %[ftmp2],   %[ftmp2],       %[ftmp8]                \n\t"
+        "pandn      %[ftmp5],   %[ftmp5],       %[ftmp1]                \n\t"
+        "pandn      %[ftmp6],   %[ftmp6],       %[ftmp2]                \n\t"
+        PTR_ADDIU  "%[addr0],   %[addr0],       0x10                    \n\t"
+        "gssdxc1    %[ftmp5],   0x00(%[addr0],  %[block])               \n\t"
+        "gssdxc1    %[ftmp6],   0x08(%[addr0],  %[block])               \n\t"
+        "blez       %[addr0],   1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [ftmp8]"=&f"(ftmp[8]),            [ftmp9]"=&f"(ftmp[9]),
+          [tmp0]"=&r"(tmp[0]),
+          [addr0]"=&r"(addr[0])
+        : [block]"r"((mips_reg)(block+nCoeffs)),
+          [quant]"r"((mips_reg)(quant_matrix+nCoeffs)),
+          [nCoeffs]"r"((mips_reg)(2*(-nCoeffs))),
+          [qscale]"r"(qscale)
+        : "memory"
     );
 
     block[0]= block0;
 }
+
+void ff_denoise_dct_mmi(MpegEncContext *s, int16_t *block)
+{
+    const int intra = s->mb_intra;
+    int *sum = s->dct_error_sum[intra];
+    uint16_t *offset = s->dct_offset[intra];
+    double ftmp[8];
+    mips_reg addr[1];
+
+    s->dct_count[intra]++;
+
+    __asm__ volatile(
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "1:                                                             \n\t"
+        "ldc1       %[ftmp1],   0x00(%[block])                          \n\t"
+        "xor        %[ftmp2],   %[ftmp2],       %[ftmp2]                \n\t"
+        "ldc1       %[ftmp3],   0x08(%[block])                          \n\t"
+        "xor        %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        "pcmpgth    %[ftmp2],   %[ftmp2],       %[ftmp1]                \n\t"
+        "pcmpgth    %[ftmp4],   %[ftmp4],       %[ftmp3]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubh      %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "ldc1       %[ftmp6],   0x00(%[offset])                         \n\t"
+        "mov.d      %[ftmp5],   %[ftmp1]                                \n\t"
+        "psubush    %[ftmp1],   %[ftmp1],       %[ftmp6]                \n\t"
+        "ldc1       %[ftmp6],   0x08(%[offset])                         \n\t"
+        "mov.d      %[ftmp7],   %[ftmp3]                                \n\t"
+        "psubush    %[ftmp3],   %[ftmp3],       %[ftmp6]                \n\t"
+        "xor        %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "xor        %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubh      %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "psubh      %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "sdc1       %[ftmp1],   0x00(%[block])                          \n\t"
+        "sdc1       %[ftmp3],   0x08(%[block])                          \n\t"
+        "mov.d      %[ftmp1],   %[ftmp5]                                \n\t"
+        "mov.d      %[ftmp3],   %[ftmp7]                                \n\t"
+        "punpcklhw  %[ftmp5],   %[ftmp5],       %[ftmp0]                \n\t"
+        "punpckhhw  %[ftmp1],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpcklhw  %[ftmp7],   %[ftmp7],       %[ftmp0]                \n\t"
+        "punpckhhw  %[ftmp3],   %[ftmp3],       %[ftmp0]                \n\t"
+        "ldc1       %[ftmp2],   0x00(%[sum])                            \n\t"
+        "paddw      %[ftmp5],   %[ftmp5],       %[ftmp2]                \n\t"
+        "ldc1       %[ftmp2],   0x08(%[sum])                            \n\t"
+        "paddw      %[ftmp1],   %[ftmp1],       %[ftmp2]                \n\t"
+        "ldc1       %[ftmp2],   0x10(%[sum])                            \n\t"
+        "paddw      %[ftmp7],   %[ftmp7],       %[ftmp2]                \n\t"
+        "ldc1       %[ftmp2],   0x18(%[sum])                            \n\t"
+        "paddw      %[ftmp3],   %[ftmp3],       %[ftmp2]                \n\t"
+        "sdc1       %[ftmp5],   0x00(%[sum])                            \n\t"
+        "sdc1       %[ftmp1],   0x08(%[sum])                            \n\t"
+        "sdc1       %[ftmp7],   0x10(%[sum])                            \n\t"
+        "sdc1       %[ftmp3],   0x18(%[sum])                            \n\t"
+        PTR_ADDIU  "%[block],   %[block],       0x10                    \n\t"
+        PTR_ADDIU  "%[sum],     %[sum],         0x20                    \n\t"
+        PTR_SUBU   "%[addr0],   %[block1],      %[block]                \n\t"
+        PTR_ADDIU  "%[offset],  %[offset],      0x10                    \n\t"
+        "bgtz       %[addr0],   1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [ftmp6]"=&f"(ftmp[6]),            [ftmp7]"=&f"(ftmp[7]),
+          [addr0]"=&r"(addr[0]),
+          [block]"+&r"(block),              [sum]"+&r"(sum),
+          [offset]"+&r"(offset)
+        : [block1]"r"(block+64)
+        : "memory"
+    );
+}
diff --git a/libavcodec/mips/pixblockdsp_mmi.c b/libavcodec/mips/pixblockdsp_mmi.c
index 30631d8..3ff84c0 100644
--- a/libavcodec/mips/pixblockdsp_mmi.c
+++ b/libavcodec/mips/pixblockdsp_mmi.c
@@ -22,58 +22,77 @@
  */
 
 #include "pixblockdsp_mips.h"
+#include "libavutil/mips/asmdefs.h"
 
 void ff_get_pixels_8_mmi(int16_t *av_restrict block, const uint8_t *pixels,
         ptrdiff_t line_size)
 {
+    double ftmp[6];
+    mips_reg tmp[2];
+
     __asm__ volatile (
-        "move $8, $0                    \n\t"
-        "xor $f0, $f0, $f0              \n\t"
-        "1:                             \n\t"
-        "gsldlc1 $f2, 7(%1)             \n\t"
-        "gsldrc1 $f2, 0(%1)             \n\t"
-        "punpcklbh $f4, $f2, $f0        \n\t"
-        "punpckhbh $f6, $f2, $f0        \n\t"
-        "gssdxc1 $f4, 0(%0, $8)         \n\t"
-        "gssdxc1 $f6, 8(%0, $8)         \n\t"
-        "daddiu $8, $8, 16              \n\t"
-        "daddu %1, %1, %2               \n\t"
-        "daddi %3, %3, -1               \n\t"
-        "bnez %3, 1b                    \n\t"
-        ::"r"((uint8_t *)block),"r"(pixels),"r"(line_size),"r"(8)
-        : "$8","memory"
+        "li         %[tmp1],    0x08                                    \n\t"
+        "move       %[tmp0],    $0                                      \n\t"
+        "xor        %[ftmp0],   %[ftmp0],       %[ftmp0]                \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp1],   0x07(%[pixels])                         \n\t"
+        "gsldrc1    %[ftmp1],   0x00(%[pixels])                         \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp1],       %[ftmp0]                \n\t"
+        "punpckhbh  %[ftmp5],   %[ftmp1],       %[ftmp0]                \n\t"
+        "gssdxc1    %[ftmp2],   0x00(%[block],  %[tmp0])                \n\t"
+        "gssdxc1    %[ftmp5],   0x08(%[block],  %[tmp0])                \n\t"
+        PTR_ADDI   "%[tmp1],    %[tmp1],       -0x01                    \n\t"
+        PTR_ADDIU  "%[tmp0],    %[tmp0],        0x10                    \n\t"
+        PTR_ADDU   "%[pixels],  %[pixels],      %[line_size]            \n\t"
+        "bnez       %[tmp1],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),            [ftmp5]"=&f"(ftmp[5]),
+          [tmp0]"=&r"(tmp[0]),              [tmp1]"=&r"(tmp[1]),
+          [pixels]"+&r"(pixels)
+        : [block]"r"((mips_reg)block),      [line_size]"r"((mips_reg)line_size)
+        : "memory"
     );
 }
 
 void ff_diff_pixels_mmi(int16_t *av_restrict block, const uint8_t *src1,
         const uint8_t *src2, int stride)
 {
+    double ftmp[5];
+    mips_reg tmp[1];
+
     __asm__ volatile (
-        "dli $2, 8                     \n\t"
-        "xor $f14, $f14, $f14          \n\t"
-        "1:                            \n\t"
-        "gsldlc1 $f0, 7(%1)            \n\t"
-        "gsldrc1 $f0, 0(%1)            \n\t"
-        "or $f2, $f0, $f0              \n\t"
-        "gsldlc1 $f4, 7(%2)            \n\t"
-        "gsldrc1 $f4, 0(%2)            \n\t"
-        "or $f6, $f4, $f4              \n\t"
-        "punpcklbh $f0, $f0, $f14      \n\t"
-        "punpckhbh $f2, $f2, $f14      \n\t"
-        "punpcklbh $f4, $f4, $f14      \n\t"
-        "punpckhbh $f6, $f6, $f14      \n\t"
-        "psubh $f0, $f0, $f4           \n\t"
-        "psubh $f2, $f2, $f6           \n\t"
-        "gssdlc1 $f0, 7(%0)            \n\t"
-        "gssdrc1 $f0, 0(%0)            \n\t"
-        "gssdlc1 $f2, 15(%0)           \n\t"
-        "gssdrc1 $f2, 8(%0)            \n\t"
-        "daddi %0, %0, 16              \n\t"
-        "daddu %1, %1, %3              \n\t"
-        "daddu %2, %2, %3              \n\t"
-        "daddi $2, $2, -1              \n\t"
-        "bgtz $2, 1b                   \n\t"
-        ::"r"(block),"r"(src1),"r"(src2),"r"(stride)
-        : "$2","memory"
+        "li         %[tmp0],    0x08                                    \n\t"
+        "xor        %[ftmp4],   %[ftmp4],       %[ftmp4]                \n\t"
+        "1:                                                             \n\t"
+        "gsldlc1    %[ftmp0],   0x07(%[src1])                           \n\t"
+        "gsldrc1    %[ftmp0],   0x00(%[src1])                           \n\t"
+        "or         %[ftmp1],   %[ftmp0],       %[ftmp0]                \n\t"
+        "gsldlc1    %[ftmp2],   0x07(%[src2])                           \n\t"
+        "gsldrc1    %[ftmp2],   0x00(%[src2])                           \n\t"
+        "or         %[ftmp3],   %[ftmp2],       %[ftmp2]                \n\t"
+        "punpcklbh  %[ftmp0],   %[ftmp0],       %[ftmp4]                \n\t"
+        "punpckhbh  %[ftmp1],   %[ftmp1],       %[ftmp4]                \n\t"
+        "punpcklbh  %[ftmp2],   %[ftmp2],       %[ftmp4]                \n\t"
+        "punpckhbh  %[ftmp3],   %[ftmp3],       %[ftmp4]                \n\t"
+        "psubh      %[ftmp0],   %[ftmp0],       %[ftmp2]                \n\t"
+        "psubh      %[ftmp1],   %[ftmp1],       %[ftmp3]                \n\t"
+        "gssdlc1    %[ftmp0],   0x07(%[block])                          \n\t"
+        "gssdrc1    %[ftmp0],   0x00(%[block])                          \n\t"
+        "gssdlc1    %[ftmp1],   0x0f(%[block])                          \n\t"
+        "gssdrc1    %[ftmp1],   0x08(%[block])                          \n\t"
+        PTR_ADDI   "%[tmp0],    %[tmp0], -0x01                          \n\t"
+        PTR_ADDIU  "%[block],   %[block], 0x10                          \n\t"
+        PTR_ADDU   "%[src1],    %[src1],        %[stride]               \n\t"
+        PTR_ADDU   "%[src2],    %[src2],        %[stride]               \n\t"
+        "bgtz       %[tmp0],    1b                                      \n\t"
+        : [ftmp0]"=&f"(ftmp[0]),            [ftmp1]"=&f"(ftmp[1]),
+          [ftmp2]"=&f"(ftmp[2]),            [ftmp3]"=&f"(ftmp[3]),
+          [ftmp4]"=&f"(ftmp[4]),
+          [tmp0]"=&r"(tmp[0]),
+          [block]"+&r"(block),              [src1]"+&r"(src1),
+          [src2]"+&r"(src2)
+        : [stride]"r"((mips_reg)stride)
+        : "memory"
     );
 }
diff --git a/libavcodec/mjpeg2jpeg_bsf.c b/libavcodec/mjpeg2jpeg_bsf.c
index 92dc3ca..6f02bc0 100644
--- a/libavcodec/mjpeg2jpeg_bsf.c
+++ b/libavcodec/mjpeg2jpeg_bsf.c
@@ -31,6 +31,7 @@
 #include "libavutil/intreadwrite.h"
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "jpegtables.h"
 #include "mjpeg.h"
 
@@ -77,46 +78,66 @@ static uint8_t *append_dht_segment(uint8_t *buf)
     return buf;
 }
 
-static int mjpeg2jpeg_filter(AVBitStreamFilterContext *bsfc,
-                             AVCodecContext *avctx, const char *args,
-                             uint8_t **poutbuf, int *poutbuf_size,
-                             const uint8_t *buf, int buf_size,
-                             int keyframe)
+static int mjpeg2jpeg_filter(AVBSFContext *ctx, AVPacket *out)
 {
+    AVPacket *in;
+    int ret = 0;
     int input_skip, output_size;
-    uint8_t *output, *out;
+    uint8_t *output;
 
-    if (buf_size < 12) {
-        av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
-        return AVERROR_INVALIDDATA;
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    if (in->size < 12) {
+        av_log(ctx, AV_LOG_ERROR, "input is truncated\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
     }
-    if (AV_RB16(buf) != 0xffd8) {
-        av_log(avctx, AV_LOG_ERROR, "input is not MJPEG\n");
-        return AVERROR_INVALIDDATA;
+    if (AV_RB16(in->data) != 0xffd8) {
+        av_log(ctx, AV_LOG_ERROR, "input is not MJPEG\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
     }
-    if (buf[2] == 0xff && buf[3] == APP0) {
-        input_skip = (buf[4] << 8) + buf[5] + 4;
+    if (in->data[2] == 0xff && in->data[3] == APP0) {
+        input_skip = (in->data[4] << 8) + in->data[5] + 4;
     } else {
         input_skip = 2;
     }
-    if (buf_size < input_skip) {
-        av_log(avctx, AV_LOG_ERROR, "input is truncated\n");
-        return AVERROR_INVALIDDATA;
+    if (in->size < input_skip) {
+        av_log(ctx, AV_LOG_ERROR, "input is truncated\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
     }
-    output_size = buf_size - input_skip +
+    output_size = in->size - input_skip +
                   sizeof(jpeg_header) + dht_segment_size;
-    output = out = av_malloc(output_size);
-    if (!output)
-        return AVERROR(ENOMEM);
-    out = append(out, jpeg_header, sizeof(jpeg_header));
-    out = append_dht_segment(out);
-    out = append(out, buf + input_skip, buf_size - input_skip);
-    *poutbuf = output;
-    *poutbuf_size = output_size;
-    return 1;
+    ret = av_new_packet(out, output_size);
+    if (ret < 0)
+        goto fail;
+
+    output = out->data;
+
+    output = append(output, jpeg_header, sizeof(jpeg_header));
+    output = append_dht_segment(output);
+    output = append(output, in->data + input_skip, in->size - input_skip);
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_mjpeg2jpeg_bsf = {
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_mjpeg2jpeg_bsf = {
     .name           = "mjpeg2jpeg",
     .filter         = mjpeg2jpeg_filter,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/mjpega_dump_header_bsf.c b/libavcodec/mjpega_dump_header_bsf.c
index d6d41e6..ca5fb3a 100644
--- a/libavcodec/mjpega_dump_header_bsf.c
+++ b/libavcodec/mjpega_dump_header_bsf.c
@@ -26,70 +26,83 @@
  */
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "bytestream.h"
 #include "mjpeg.h"
 
 
-static int mjpega_dump_header(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                              uint8_t **poutbuf, int *poutbuf_size,
-                              const uint8_t *buf, int buf_size, int keyframe)
+static int mjpega_dump_header(AVBSFContext *ctx, AVPacket *out)
 {
-    uint8_t *poutbufp;
+    AVPacket *in;
+    uint8_t *out_buf;
     unsigned dqt = 0, dht = 0, sof0 = 0;
-    int i;
+    int ret = 0, i;
 
-    if (avctx->codec_id != AV_CODEC_ID_MJPEG) {
-        av_log(avctx, AV_LOG_ERROR, "mjpega bitstream filter only applies to mjpeg codec\n");
-        return 0;
-    }
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    ret = av_new_packet(out, in->size + 44);
+    if (ret < 0)
+        goto fail;
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
 
-    *poutbuf_size = 0;
-    *poutbuf = av_malloc(buf_size + 44 + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
-    poutbufp = *poutbuf;
-    bytestream_put_byte(&poutbufp, 0xff);
-    bytestream_put_byte(&poutbufp, SOI);
-    bytestream_put_byte(&poutbufp, 0xff);
-    bytestream_put_byte(&poutbufp, APP1);
-    bytestream_put_be16(&poutbufp, 42); /* size */
-    bytestream_put_be32(&poutbufp, 0);
-    bytestream_put_buffer(&poutbufp, "mjpg", 4);
-    bytestream_put_be32(&poutbufp, buf_size + 44); /* field size */
-    bytestream_put_be32(&poutbufp, buf_size + 44); /* pad field size */
-    bytestream_put_be32(&poutbufp, 0);             /* next ptr */
+    out_buf = out->data;
+    bytestream_put_byte(&out_buf, 0xff);
+    bytestream_put_byte(&out_buf, SOI);
+    bytestream_put_byte(&out_buf, 0xff);
+    bytestream_put_byte(&out_buf, APP1);
+    bytestream_put_be16(&out_buf, 42); /* size */
+    bytestream_put_be32(&out_buf, 0);
+    bytestream_put_buffer(&out_buf, "mjpg", 4);
+    bytestream_put_be32(&out_buf, in->size + 44); /* field size */
+    bytestream_put_be32(&out_buf, in->size + 44); /* pad field size */
+    bytestream_put_be32(&out_buf, 0);             /* next ptr */
 
-    for (i = 0; i < buf_size - 1; i++) {
-        if (buf[i] == 0xff) {
-            switch (buf[i + 1]) {
+    for (i = 0; i < in->size - 1; i++) {
+        if (in->data[i] == 0xff) {
+            switch (in->data[i + 1]) {
             case DQT:  dqt  = i + 46; break;
             case DHT:  dht  = i + 46; break;
             case SOF0: sof0 = i + 46; break;
             case SOS:
-                bytestream_put_be32(&poutbufp, dqt); /* quant off */
-                bytestream_put_be32(&poutbufp, dht); /* huff off */
-                bytestream_put_be32(&poutbufp, sof0); /* image off */
-                bytestream_put_be32(&poutbufp, i + 46); /* scan off */
-                bytestream_put_be32(&poutbufp, i + 46 + AV_RB16(buf + i + 2)); /* data off */
-                bytestream_put_buffer(&poutbufp, buf + 2, buf_size - 2); /* skip already written SOI */
-                *poutbuf_size = poutbufp - *poutbuf;
-                return 1;
+                bytestream_put_be32(&out_buf, dqt); /* quant off */
+                bytestream_put_be32(&out_buf, dht); /* huff off */
+                bytestream_put_be32(&out_buf, sof0); /* image off */
+                bytestream_put_be32(&out_buf, i + 46); /* scan off */
+                bytestream_put_be32(&out_buf, i + 46 + AV_RB16(in->data + i + 2)); /* data off */
+                bytestream_put_buffer(&out_buf, in->data + 2, in->size - 2); /* skip already written SOI */
+
+                out->size = out_buf - out->data;
+                av_packet_free(&in);
+                return 0;
             case APP1:
-                if (i + 8 < buf_size && AV_RL32(buf + i + 8) == AV_RL32("mjpg")) {
-                    av_log(avctx, AV_LOG_ERROR, "bitstream already formatted\n");
-                    memcpy(*poutbuf, buf, buf_size);
-                    *poutbuf_size = buf_size;
-                    return 1;
+                if (i + 8 < in->size && AV_RL32(in->data + i + 8) == AV_RL32("mjpg")) {
+                    av_log(ctx, AV_LOG_ERROR, "bitstream already formatted\n");
+                    av_packet_unref(out);
+                    av_packet_move_ref(out, in);
+                    av_packet_free(&in);
+                    return 0;
                 }
             }
         }
     }
-    av_freep(poutbuf);
-    av_log(avctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n");
-    return 0;
+    av_log(ctx, AV_LOG_ERROR, "could not find SOS marker in bitstream\n");
+fail:
+    av_packet_unref(out);
+    av_packet_free(&in);
+    return AVERROR_INVALIDDATA;
 }
 
-AVBitStreamFilter ff_mjpega_dump_header_bsf = {
-    .name   = "mjpegadump",
-    .filter = mjpega_dump_header,
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_mjpega_dump_header_bsf = {
+    .name      = "mjpegadump",
+    .filter    = mjpega_dump_header,
+    .codec_ids = codec_ids,
 };
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index bce5496..633a8f0 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -166,7 +166,7 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
 /* quantize tables */
 int ff_mjpeg_decode_dqt(MJpegDecodeContext *s)
 {
-    int len, index, i, j;
+    int len, index, i;
 
     len = get_bits(&s->gb, 16) - 2;
 
@@ -187,13 +187,12 @@ int ff_mjpeg_decode_dqt(MJpegDecodeContext *s)
         av_log(s->avctx, AV_LOG_DEBUG, "index=%d\n", index);
         /* read quant table */
         for (i = 0; i < 64; i++) {
-            j = s->scantable.permutated[i];
-            s->quant_matrixes[index][j] = get_bits(&s->gb, pr ? 16 : 8);
+            s->quant_matrixes[index][i] = get_bits(&s->gb, pr ? 16 : 8);
         }
 
-        // XXX FIXME finetune, and perhaps add dc too
-        s->qscale[index] = FFMAX(s->quant_matrixes[index][s->scantable.permutated[1]],
-                                 s->quant_matrixes[index][s->scantable.permutated[8]]) >> 1;
+        // XXX FIXME fine-tune, and perhaps add dc too
+        s->qscale[index] = FFMAX(s->quant_matrixes[index][1],
+                                 s->quant_matrixes[index][8]) >> 1;
         av_log(s->avctx, AV_LOG_DEBUG, "qscale[%d]: %d\n",
                index, s->qscale[index]);
         len -= 1 + 64 * (1+pr);
@@ -282,7 +281,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
     }
 
     if (s->avctx->bits_per_raw_sample != bits) {
-        av_log(s->avctx, AV_LOG_INFO, "Changing bps to %d\n", bits);
+        av_log(s->avctx, s->avctx->bits_per_raw_sample > 0 ? AV_LOG_INFO : AV_LOG_DEBUG, "Changing bps from %d to %d\n", s->avctx->bits_per_raw_sample, bits);
         s->avctx->bits_per_raw_sample = bits;
         init_idct(s->avctx);
     }
@@ -614,6 +613,13 @@ unk_pixfmt:
         return AVERROR_BUG;
     }
 
+    if (s->avctx->skip_frame == AVDISCARD_ALL) {
+        s->picture_ptr->pict_type = AV_PICTURE_TYPE_I;
+        s->picture_ptr->key_frame = 1;
+        s->got_picture            = 1;
+        return 0;
+    }
+
     av_frame_unref(s->picture_ptr);
     if (ff_get_buffer(s->avctx, s->picture_ptr, AV_GET_BUFFER_FLAG_REF) < 0)
         return -1;
@@ -716,7 +722,7 @@ static int decode_block(MJpegDecodeContext *s, int16_t *block, int component,
                 return AVERROR_INVALIDDATA;
             }
             j        = s->scantable.permutated[i];
-            block[j] = level * quant_matrix[j];
+            block[j] = level * quant_matrix[i];
         }
     } while (i < 63);
     CLOSE_READER(re, &s->gb);}
@@ -778,14 +784,14 @@ static int decode_block_progressive(MJpegDecodeContext *s, int16_t *block,
                 if (i >= se) {
                     if (i == se) {
                         j = s->scantable.permutated[se];
-                        block[j] = level * (quant_matrix[j] << Al);
+                        block[j] = level * (quant_matrix[se] << Al);
                         break;
                     }
                     av_log(s->avctx, AV_LOG_ERROR, "error count: %d\n", i);
                     return AVERROR_INVALIDDATA;
                 }
                 j = s->scantable.permutated[i];
-                block[j] = level * (quant_matrix[j] << Al);
+                block[j] = level * (quant_matrix[i] << Al);
             } else {
                 if (run == 0xF) {// ZRL - skip 15 coefficients
                     i += 15;
@@ -818,7 +824,7 @@ static int decode_block_progressive(MJpegDecodeContext *s, int16_t *block,
     UPDATE_CACHE(re, &s->gb);                                       \
     sign = block[j] >> 15;                                          \
     block[j] += SHOW_UBITS(re, &s->gb, 1) *                         \
-                ((quant_matrix[j] ^ sign) - sign) << Al;            \
+                ((quant_matrix[i] ^ sign) - sign) << Al;            \
     LAST_SKIP_BITS(re, &s->gb, 1);                                  \
 }
 
@@ -864,7 +870,7 @@ static int decode_block_refinement(MJpegDecodeContext *s, int16_t *block,
                 ZERO_RUN;
                 j = s->scantable.permutated[i];
                 val--;
-                block[j] = ((quant_matrix[j] << Al) ^ val) - val;
+                block[j] = ((quant_matrix[i] << Al) ^ val) - val;
                 if (i == se) {
                     if (i > *last_nnz)
                         *last_nnz = i;
@@ -1369,11 +1375,7 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss,
     int mb_x, mb_y;
     int EOBRUN = 0;
     int c = s->comp_index[0];
-    uint8_t *data = s->picture_ptr->data[c];
-    int linesize  = s->linesize[c];
-    int last_scan = 0;
     int16_t *quant_matrix = s->quant_matrixes[s->quant_sindex[0]];
-    int bytes_per_pixel = 1 + (s->bits > 8);
 
     av_assert0(ss>=0 && Ah>=0 && Al>=0);
     if (se < ss || se > 63) {
@@ -1384,15 +1386,10 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss,
     // s->coefs_finished is a bitmask for coefficients coded
     // ss and se are parameters telling start and end coefficients
     s->coefs_finished[c] |= (2ULL << se) - (1ULL << ss);
-    last_scan = !Al && !~s->coefs_finished[c];
-
-    if (s->interlaced && s->bottom_field)
-        data += linesize >> 1;
 
     s->restart_count = 0;
 
     for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
-        uint8_t *ptr     = data + (mb_y * linesize * 8 >> s->avctx->lowres);
         int block_idx    = mb_y * s->block_stride[c];
         int16_t (*block)[64] = &s->blocks[c][block_idx];
         uint8_t *last_nnz    = &s->last_nnz[c][block_idx];
@@ -1413,12 +1410,6 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss,
                     return AVERROR_INVALIDDATA;
                 }
 
-            if (last_scan) {
-                    s->idsp.idct_put(ptr, linesize, *block);
-                    if (s->bits & 7)
-                        shift_output(s, ptr, linesize);
-                    ptr += bytes_per_pixel*8 >> s->avctx->lowres;
-            }
             if (handle_rstn(s, 0))
                 EOBRUN = 0;
         }
@@ -1426,6 +1417,41 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss,
     return 0;
 }
 
+static void mjpeg_idct_scan_progressive_ac(MJpegDecodeContext *s)
+{
+    int mb_x, mb_y;
+    int c;
+    const int bytes_per_pixel = 1 + (s->bits > 8);
+    const int block_size = s->lossless ? 1 : 8;
+
+    for (c = 0; c < s->nb_components; c++) {
+        uint8_t *data = s->picture_ptr->data[c];
+        int linesize  = s->linesize[c];
+        int h = s->h_max / s->h_count[c];
+        int v = s->v_max / s->v_count[c];
+        int mb_width     = (s->width  + h * block_size - 1) / (h * block_size);
+        int mb_height    = (s->height + v * block_size - 1) / (v * block_size);
+
+        if (~s->coefs_finished[c])
+            av_log(s->avctx, AV_LOG_WARNING, "component %d is incomplete\n", c);
+
+        if (s->interlaced && s->bottom_field)
+            data += linesize >> 1;
+
+        for (mb_y = 0; mb_y < mb_height; mb_y++) {
+            uint8_t *ptr     = data + (mb_y * linesize * 8 >> s->avctx->lowres);
+            int block_idx    = mb_y * s->block_stride[c];
+            int16_t (*block)[64] = &s->blocks[c][block_idx];
+            for (mb_x = 0; mb_x < mb_width; mb_x++, block++) {
+                s->idsp.idct_put(ptr, linesize, *block);
+                if (s->bits & 7)
+                    shift_output(s, ptr, linesize);
+                ptr += bytes_per_pixel*8 >> s->avctx->lowres;
+            }
+        }
+    }
+}
+
 int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask,
                         int mb_bitmask_size, const AVFrame *reference)
 {
@@ -1675,7 +1701,11 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
         goto out;
     }
 
-    if (id == AV_RB32("Adob") && (get_bits(&s->gb, 8) == 'e')) {
+    if (   id == AV_RB32("Adob")
+        && len >= 7
+        && show_bits(&s->gb, 8) == 'e'
+        && show_bits_long(&s->gb, 32) != AV_RB32("e_CM")) {
+        skip_bits(&s->gb,  8); /* 'e' */
         skip_bits(&s->gb, 16); /* version */
         skip_bits(&s->gb, 16); /* flags0 */
         skip_bits(&s->gb, 16); /* flags1 */
@@ -1846,32 +1876,35 @@ static int mjpeg_decode_com(MJpegDecodeContext *s)
 {
     int len = get_bits(&s->gb, 16);
     if (len >= 2 && 8 * len - 16 <= get_bits_left(&s->gb)) {
+        int i;
         char *cbuf = av_malloc(len - 1);
-        if (cbuf) {
-            int i;
-            for (i = 0; i < len - 2; i++)
-                cbuf[i] = get_bits(&s->gb, 8);
-            if (i > 0 && cbuf[i - 1] == '\n')
-                cbuf[i - 1] = 0;
-            else
-                cbuf[i] = 0;
+        if (!cbuf)
+            return AVERROR(ENOMEM);
 
-            if (s->avctx->debug & FF_DEBUG_PICT_INFO)
-                av_log(s->avctx, AV_LOG_INFO, "comment: '%s'\n", cbuf);
-
-            /* buggy avid, it puts EOI only at every 10th frame */
-            if (!strncmp(cbuf, "AVID", 4)) {
-                parse_avid(s, cbuf, len);
-            } else if (!strcmp(cbuf, "CS=ITU601"))
-                s->cs_itu601 = 1;
-            else if ((!strncmp(cbuf, "Intel(R) JPEG Library, version 1", 32) && s->avctx->codec_tag) ||
-                     (!strncmp(cbuf, "Metasoft MJPEG Codec", 20)))
-                s->flipped = 1;
-            else if (!strcmp(cbuf, "MULTISCOPE II"))
-                s->multiscope = 2;
-
-            av_free(cbuf);
+        for (i = 0; i < len - 2; i++)
+            cbuf[i] = get_bits(&s->gb, 8);
+        if (i > 0 && cbuf[i - 1] == '\n')
+            cbuf[i - 1] = 0;
+        else
+            cbuf[i] = 0;
+
+        if (s->avctx->debug & FF_DEBUG_PICT_INFO)
+            av_log(s->avctx, AV_LOG_INFO, "comment: '%s'\n", cbuf);
+
+        /* buggy avid, it puts EOI only at every 10th frame */
+        if (!strncmp(cbuf, "AVID", 4)) {
+            parse_avid(s, cbuf, len);
+        } else if (!strcmp(cbuf, "CS=ITU601"))
+            s->cs_itu601 = 1;
+        else if ((!strncmp(cbuf, "Intel(R) JPEG Library, version 1", 32) && s->avctx->codec_tag) ||
+                 (!strncmp(cbuf, "Metasoft MJPEG Codec", 20)))
+            s->flipped = 1;
+        else if (!strcmp(cbuf, "MULTISCOPE II")) {
+            s->avctx->sample_aspect_ratio = (AVRational) { 1, 2 };
+            s->multiscope = 2;
         }
+
+        av_free(cbuf);
     }
 
     return 0;
@@ -2082,8 +2115,11 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         else if (start_code >= APP0 && start_code <= APP15)
             mjpeg_decode_app(s);
             /* Comment */
-        else if (start_code == COM)
-            mjpeg_decode_com(s);
+        else if (start_code == COM) {
+            ret = mjpeg_decode_com(s);
+            if (ret < 0)
+                return ret;
+        }
 
         ret = -1;
 
@@ -2162,6 +2198,8 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
             break;
         case EOI:
 eoi_parser:
+            if (avctx->skip_frame != AVDISCARD_ALL && s->progressive && s->cur_scan && s->got_picture)
+                mjpeg_idct_scan_progressive_ac(s);
             s->cur_scan = 0;
             if (!s->got_picture) {
                 av_log(avctx, AV_LOG_WARNING,
@@ -2262,7 +2300,8 @@ the_end:
                    avctx->pix_fmt == AV_PIX_FMT_GBRAP
                   );
         avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
-        for (p = 0; p<4; p++) {
+        av_assert0(s->nb_components == av_pix_fmt_count_planes(s->picture_ptr->format));
+        for (p = 0; p<s->nb_components; p++) {
             uint8_t *line = s->picture_ptr->data[p];
             int w = s->width;
             int h = s->height;
@@ -2320,7 +2359,8 @@ the_end:
                    avctx->pix_fmt == AV_PIX_FMT_GBRAP
                    );
         avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
-        for (p = 0; p < 4; p++) {
+        av_assert0(s->nb_components == av_pix_fmt_count_planes(s->picture_ptr->format));
+        for (p = 0; p < s->nb_components; p++) {
             uint8_t *dst;
             int w = s->width;
             int h = s->height;
@@ -2347,7 +2387,8 @@ the_end:
     if (s->flipped) {
         int j;
         avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
-        for (index=0; index<4; index++) {
+        av_assert0(s->nb_components == av_pix_fmt_count_planes(s->picture_ptr->format));
+        for (index=0; index<s->nb_components; index++) {
             uint8_t *dst = s->picture_ptr->data[index];
             int w = s->picture_ptr->width;
             int h = s->picture_ptr->height;
@@ -2369,6 +2410,7 @@ the_end:
     if (s->adobe_transform == 0 && s->avctx->pix_fmt == AV_PIX_FMT_GBRAP) {
         int w = s->picture_ptr->width;
         int h = s->picture_ptr->height;
+        av_assert0(s->nb_components == 4);
         for (i=0; i<h; i++) {
             int j;
             uint8_t *dst[4];
@@ -2391,6 +2433,7 @@ the_end:
     if (s->adobe_transform == 2 && s->avctx->pix_fmt == AV_PIX_FMT_YUVA444P) {
         int w = s->picture_ptr->width;
         int h = s->picture_ptr->height;
+        av_assert0(s->nb_components == 4);
         for (i=0; i<h; i++) {
             int j;
             uint8_t *dst[4];
diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h
index 4d77e16..60cd566 100644
--- a/libavcodec/mjpegenc.h
+++ b/libavcodec/mjpegenc.h
@@ -40,7 +40,7 @@
 #include "put_bits.h"
 
 typedef struct MJpegContext {
-    uint8_t huff_size_dc_luminance[12]; //FIXME use array [3] instead of lumi / chrom, for easier addressing
+    uint8_t huff_size_dc_luminance[12]; //FIXME use array [3] instead of lumi / chroma, for easier addressing
     uint16_t huff_code_dc_luminance[12];
     uint8_t huff_size_dc_chrominance[12];
     uint16_t huff_code_dc_chrominance[12];
diff --git a/libavcodec/mlp_parser.h b/libavcodec/mlp_parser.h
index 0c0109e..c5a2883 100644
--- a/libavcodec/mlp_parser.h
+++ b/libavcodec/mlp_parser.h
@@ -42,9 +42,9 @@ typedef struct MLPHeaderInfo
 
     int channel_arrangement;
 
-    int channel_modifier_thd_stream0;       ///< Channel modifier for substream 0 of TrueHD sreams ("2-channel presentation")
-    int channel_modifier_thd_stream1;       ///< Channel modifier for substream 1 of TrueHD sreams ("6-channel presentation")
-    int channel_modifier_thd_stream2;       ///< Channel modifier for substream 2 of TrueHD sreams ("8-channel presentation")
+    int channel_modifier_thd_stream0;       ///< Channel modifier for substream 0 of TrueHD streams ("2-channel presentation")
+    int channel_modifier_thd_stream1;       ///< Channel modifier for substream 1 of TrueHD streams ("6-channel presentation")
+    int channel_modifier_thd_stream2;       ///< Channel modifier for substream 2 of TrueHD streams ("8-channel presentation")
 
     int channels_mlp;                       ///< Channel count for MLP streams
     int channels_thd_stream1;               ///< Channel count for substream 1 of TrueHD streams ("6-channel presentation")
diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c
index 30861d9..099a8c5 100644
--- a/libavcodec/mmaldec.c
+++ b/libavcodec/mmaldec.c
@@ -38,6 +38,7 @@
 #include "libavutil/avassert.h"
 #include "libavutil/buffer.h"
 #include "libavutil/common.h"
+#include "libavutil/imgutils.h"
 #include "libavutil/opt.h"
 #include "libavutil/log.h"
 
@@ -356,19 +357,19 @@ static av_cold int ffmmal_init_decoder(AVCodecContext *avctx)
     format_in = decoder->input[0]->format;
     format_in->type = MMAL_ES_TYPE_VIDEO;
     switch (avctx->codec_id) {
-        case AV_CODEC_ID_MPEG2VIDEO:
-            format_in->encoding = MMAL_ENCODING_MP2V;
-            break;
-        case AV_CODEC_ID_MPEG4:
-            format_in->encoding = MMAL_ENCODING_MP4V;
-            break;
-        case AV_CODEC_ID_VC1:
-            format_in->encoding = MMAL_ENCODING_WVC1;
-            break;
-        case AV_CODEC_ID_H264:
-        default:
-            format_in->encoding = MMAL_ENCODING_H264;
-            break;
+    case AV_CODEC_ID_MPEG2VIDEO:
+        format_in->encoding = MMAL_ENCODING_MP2V;
+        break;
+    case AV_CODEC_ID_MPEG4:
+        format_in->encoding = MMAL_ENCODING_MP4V;
+        break;
+    case AV_CODEC_ID_VC1:
+        format_in->encoding = MMAL_ENCODING_WVC1;
+        break;
+    case AV_CODEC_ID_H264:
+    default:
+        format_in->encoding = MMAL_ENCODING_H264;
+        break;
     }
     format_in->es->video.width = FFALIGN(avctx->width, 32);
     format_in->es->video.height = FFALIGN(avctx->height, 16);
@@ -383,10 +384,12 @@ static av_cold int ffmmal_init_decoder(AVCodecContext *avctx)
     av_get_codec_tag_string(tmp, sizeof(tmp), format_in->encoding);
     av_log(avctx, AV_LOG_DEBUG, "Using MMAL %s encoding.\n", tmp);
 
+#if HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS
     if (mmal_port_parameter_set_uint32(decoder->input[0], MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS,
                                        -1 - ctx->extra_decoder_buffers)) {
         av_log(avctx, AV_LOG_WARNING, "Could not set input buffering limit.\n");
     }
+#endif
 
     if ((status = mmal_port_format_commit(decoder->input[0])))
         goto fail;
@@ -618,24 +621,17 @@ static int ffmal_copy_frame(AVCodecContext *avctx,  AVFrame *frame,
     } else {
         int w = FFALIGN(avctx->width, 32);
         int h = FFALIGN(avctx->height, 16);
-        char *ptr;
-        int plane;
-        int i;
+        uint8_t *src[4];
+        int linesize[4];
 
         if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
             goto done;
 
-        ptr = buffer->data + buffer->type->video.offset[0];
-        for (i = 0; i < avctx->height; i++)
-            memcpy(frame->data[0] + frame->linesize[0] * i, ptr + w * i, avctx->width);
-
-        ptr += w * h;
-
-        for (plane = 1; plane < 3; plane++) {
-            for (i = 0; i < avctx->height / 2; i++)
-                memcpy(frame->data[plane] + frame->linesize[plane] * i, ptr + w / 2 * i, (avctx->width + 1) / 2);
-            ptr += w / 2 * h / 2;
-        }
+        av_image_fill_arrays(src, linesize,
+                             buffer->data + buffer->type->video.offset[0],
+                             avctx->pix_fmt, w, h, 1);
+        av_image_copy(frame->data, frame->linesize, src, linesize,
+                      avctx->pix_fmt, avctx->width, avctx->height);
     }
 
     frame->pkt_pts = buffer->pts == MMAL_TIME_UNKNOWN ? AV_NOPTS_VALUE : buffer->pts;
@@ -664,7 +660,7 @@ static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_fra
         // being busy from decoder waiting for input. So just poll at the start and
         // keep feeding new data to the buffer.
         // We are pretty sure the decoder will produce output if we sent more input
-        // frames than what a h264 decoder could logically delay. This avoids too
+        // frames than what a H.264 decoder could logically delay. This avoids too
         // excessive buffering.
         // We also wait if we sent eos, but didn't receive it yet (think of decoding
         // stream with a very low number of frames).
diff --git a/libavcodec/motion-test.c b/libavcodec/motion-test.c
deleted file mode 100644
index ebcf4aa..0000000
--- a/libavcodec/motion-test.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * (c) 2001 Fabrice Bellard
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file
- * motion test.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "config.h"
-#include "me_cmp.h"
-#include "libavutil/internal.h"
-#include "libavutil/lfg.h"
-#include "libavutil/mem.h"
-#include "libavutil/time.h"
-
-#undef printf
-
-#define WIDTH 64
-#define HEIGHT 64
-
-static uint8_t img1[WIDTH * HEIGHT];
-static uint8_t img2[WIDTH * HEIGHT];
-
-static void fill_random(uint8_t *tab, int size)
-{
-    int i;
-    AVLFG prng;
-
-    av_lfg_init(&prng, 1);
-    for(i=0;i<size;i++) {
-        tab[i] = av_lfg_get(&prng) % 256;
-    }
-}
-
-static void help(void)
-{
-    printf("motion-test [-h]\n"
-           "test motion implementations\n");
-}
-
-#define NB_ITS 500
-
-int dummy;
-
-static void test_motion(const char *name,
-                 me_cmp_func test_func, me_cmp_func ref_func)
-{
-    int x, y, d1, d2, it;
-    uint8_t *ptr;
-    int64_t ti;
-    printf("testing '%s'\n", name);
-
-    /* test correctness */
-    for(it=0;it<20;it++) {
-
-        fill_random(img1, WIDTH * HEIGHT);
-        fill_random(img2, WIDTH * HEIGHT);
-
-        for(y=0;y<HEIGHT-17;y++) {
-            for(x=0;x<WIDTH-17;x++) {
-                ptr = img2 + y * WIDTH + x;
-                d1 = test_func(NULL, img1, ptr, WIDTH, 8);
-                d2 = ref_func(NULL, img1, ptr, WIDTH, 8);
-                if (d1 != d2) {
-                    printf("error: mmx=%d c=%d\n", d1, d2);
-                }
-            }
-        }
-    }
-    emms_c();
-
-    /* speed test */
-    ti = av_gettime_relative();
-    d1 = 0;
-    for(it=0;it<NB_ITS;it++) {
-        for(y=0;y<HEIGHT-17;y++) {
-            for(x=0;x<WIDTH-17;x++) {
-                ptr = img2 + y * WIDTH + x;
-                d1 += test_func(NULL, img1, ptr, WIDTH, 8);
-            }
-        }
-    }
-    emms_c();
-    dummy = d1; /* avoid optimization */
-    ti = av_gettime_relative() - ti;
-
-    printf("  %0.0f kop/s\n",
-           (double)NB_ITS * (WIDTH - 16) * (HEIGHT - 16) /
-           (double)(ti / 1000.0));
-}
-
-
-int main(int argc, char **argv)
-{
-    AVCodecContext *ctx;
-    int c;
-    MECmpContext cctx, mmxctx;
-    int flags[2] = { AV_CPU_FLAG_MMX, AV_CPU_FLAG_MMXEXT };
-    int flags_size = HAVE_MMXEXT ? 2 : 1;
-
-    if (argc > 1) {
-        help();
-        return 1;
-    }
-
-    printf("ffmpeg motion test\n");
-
-    ctx = avcodec_alloc_context3(NULL);
-    ctx->flags |= AV_CODEC_FLAG_BITEXACT;
-    av_force_cpu_flags(0);
-    memset(&cctx, 0, sizeof(cctx));
-    ff_me_cmp_init(&cctx, ctx);
-    for (c = 0; c < flags_size; c++) {
-        int x;
-        av_force_cpu_flags(flags[c]);
-        memset(&mmxctx, 0, sizeof(mmxctx));
-        ff_me_cmp_init(&mmxctx, ctx);
-
-        for (x = 0; x < 2; x++) {
-            printf("%s for %dx%d pixels\n", c ? "mmx2" : "mmx",
-                   x ? 8 : 16, x ? 8 : 16);
-            test_motion("mmx",     mmxctx.pix_abs[x][0], cctx.pix_abs[x][0]);
-            test_motion("mmx_x2",  mmxctx.pix_abs[x][1], cctx.pix_abs[x][1]);
-            test_motion("mmx_y2",  mmxctx.pix_abs[x][2], cctx.pix_abs[x][2]);
-            test_motion("mmx_xy2", mmxctx.pix_abs[x][3], cctx.pix_abs[x][3]);
-        }
-    }
-    av_free(ctx);
-
-    return 0;
-}
diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c
index 5236938..257d00b 100644
--- a/libavcodec/motion_est.c
+++ b/libavcodec/motion_est.c
@@ -205,7 +205,7 @@ static av_always_inline int cmp_inline(MpegEncContext *s, const int x, const int
                     cx= (cx>>1)|(cx&1);
                     cy= (cy>>1)|(cy&1);
                     uvdxy= (cx&1) + 2*(cy&1);
-                    //FIXME x/y wrong, but mpeg4 qpel is sick anyway, we should drop as much of it as possible in favor for h264
+                    // FIXME x/y wrong, but MPEG-4 qpel is sick anyway, we should drop as much of it as possible in favor for H.264
                 }
             }else{
                 c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h);
@@ -556,7 +556,7 @@ static inline void get_limits(MpegEncContext *s, int x, int y)
         c->xmax = - x + s->width;
         c->ymax = - y + s->height;
     } else if (s->out_format == FMT_H261){
-        // Search range of H261 is different from other codec standards
+        // Search range of H.261 is different from other codec standards
         c->xmin = (x > 15) ? - 15 : 0;
         c->ymin = (y > 15) ? - 15 : 0;
         c->xmax = (x < s->mb_width * 16 - 16) ? 15 : 0;
@@ -966,7 +966,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s,
             if (s->out_format == FMT_H263) {
                 c->pred_x = P_MEDIAN[0];
                 c->pred_y = P_MEDIAN[1];
-            } else { /* mpeg1 at least */
+            } else { /* MPEG-1 at least */
                 c->pred_x = P_LEFT[0];
                 c->pred_y = P_LEFT[1];
             }
@@ -1536,7 +1536,7 @@ void ff_estimate_b_frame_motion(MpegEncContext * s,
         dmin= direct_search(s, mb_x, mb_y);
     else
         dmin= INT_MAX;
-//FIXME penalty stuff for non mpeg4
+// FIXME penalty stuff for non-MPEG-4
     c->skip=0;
     fmin = estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) +
            3 * penalty_factor;
@@ -1714,7 +1714,6 @@ void ff_fix_long_p_mvs(MpegEncContext * s)
 }
 
 /**
- *
  * @param truncate 1 for truncation, 0 for using intra
  */
 void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select,
diff --git a/libavcodec/motion_est_template.c b/libavcodec/motion_est_template.c
index 327a24b..0c21bbf 100644
--- a/libavcodec/motion_est_template.c
+++ b/libavcodec/motion_est_template.c
@@ -299,7 +299,7 @@ static int qpel_motion_search(MpegEncContext * s,
             const int cy2= b + t - 2*c;
             int cxy;
 
-            if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME
+            if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == ((my-1)<<ME_MAP_MV_BITS) + (mx-1) + map_generation){
                 tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
             }else{
                 tl= cmp(s, mx-1, my-1, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);//FIXME wrong if chroma me is different
@@ -413,7 +413,7 @@ if( (y)>(ymax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymax" #v, ymax,
     const int shift= 1+qpel;\
 
 static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
-                                       int src_index, int ref_index, int const penalty_factor,
+                                       int src_index, int ref_index, const int penalty_factor,
                                        int size, int h, int flags)
 {
     MotionEstContext * const c= &s->me;
@@ -429,7 +429,7 @@ static av_always_inline int small_diamond_search(MpegEncContext * s, int *best,
     { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
         const unsigned key = ((unsigned)best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
         const int index= (((unsigned)best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
-        if(map[index]!=key){ //this will be executed only very rarey
+        if (map[index] != key) { // this will be executed only very rarely
             score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
             map[index]= key;
         }
@@ -454,7 +454,7 @@ static av_always_inline int small_diamond_search(MpegEncContext * s, int *best,
 }
 
 static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
-                                       int src_index, int ref_index, int const penalty_factor,
+                                       int src_index, int ref_index, const int penalty_factor,
                                        int size, int h, int flags)
 {
     MotionEstContext * const c= &s->me;
@@ -496,7 +496,7 @@ static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
 }
 
 static int hex_search(MpegEncContext * s, int *best, int dmin,
-                                       int src_index, int ref_index, int const penalty_factor,
+                                       int src_index, int ref_index, const int penalty_factor,
                                        int size, int h, int flags, int dia_size)
 {
     MotionEstContext * const c= &s->me;
@@ -530,7 +530,7 @@ static int hex_search(MpegEncContext * s, int *best, int dmin,
 }
 
 static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
-                                       int src_index, int ref_index, int const penalty_factor,
+                                       int src_index, int ref_index, const int penalty_factor,
                                        int size, int h, int flags)
 {
     MotionEstContext * const c= &s->me;
@@ -568,7 +568,7 @@ static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
 }
 
 static int umh_search(MpegEncContext * s, int *best, int dmin,
-                                       int src_index, int ref_index, int const penalty_factor,
+                                       int src_index, int ref_index, const int penalty_factor,
                                        int size, int h, int flags)
 {
     MotionEstContext * const c= &s->me;
@@ -615,7 +615,7 @@ static int umh_search(MpegEncContext * s, int *best, int dmin,
 }
 
 static int full_search(MpegEncContext * s, int *best, int dmin,
-                                       int src_index, int ref_index, int const penalty_factor,
+                                       int src_index, int ref_index, const int penalty_factor,
                                        int size, int h, int flags)
 {
     MotionEstContext * const c= &s->me;
@@ -678,7 +678,7 @@ static int full_search(MpegEncContext * s, int *best, int dmin,
 
 #define MAX_SAB_SIZE ME_MAP_SIZE
 static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
-                                       int src_index, int ref_index, int const penalty_factor,
+                                       int src_index, int ref_index, const int penalty_factor,
                                        int size, int h, int flags)
 {
     MotionEstContext * const c= &s->me;
@@ -758,7 +758,7 @@ static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
     if(   best[0] < xmax && best[0] > xmin
        && best[1] < ymax && best[1] > ymin){
         int d;
-        //ensure that the refernece samples for hpel refinement are in the map
+        // ensure that the reference samples for hpel refinement are in the map
         CHECK_MV(best[0]-1, best[1])
         CHECK_MV(best[0]+1, best[1])
         CHECK_MV(best[0], best[1]-1)
@@ -768,7 +768,7 @@ static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
 }
 
 static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
-                                       int src_index, int ref_index, int const penalty_factor,
+                                       int src_index, int ref_index, const int penalty_factor,
                                        int size, int h, int flags)
 {
     MotionEstContext * const c= &s->me;
@@ -829,7 +829,7 @@ static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
 }
 
 static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
-                                       int src_index, int ref_index, int const penalty_factor,
+                                       int src_index, int ref_index, const int penalty_factor,
                                        int size, int h, int flags){
     MotionEstContext * const c= &s->me;
     if(c->dia_size==-1)
@@ -871,7 +871,7 @@ static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int
     unsigned map_generation;
     int penalty_factor;
     const int ref_mv_stride= s->mb_stride; //pass as arg  FIXME
-    const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME
+    const int ref_mv_xy = s->mb_x + s->mb_y * ref_mv_stride; // add to last_mv before passing FIXME
     me_cmp_func cmpf, chroma_cmpf;
 
     LOAD_COMMON
@@ -972,7 +972,7 @@ static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int
     return dmin;
 }
 
-//this function is dedicated to the braindamaged gcc
+//this function is dedicated to the brain damaged gcc
 int ff_epzs_motion_search(MpegEncContext *s, int *mx_ptr, int *my_ptr,
                           int P[10][2], int src_index, int ref_index,
                           int16_t (*last_mv)[2], int ref_mv_scale,
diff --git a/libavcodec/motionpixels_tablegen.c b/libavcodec/motionpixels_tablegen.c
index 14b7b9b..1bebaf1 100644
--- a/libavcodec/motionpixels_tablegen.c
+++ b/libavcodec/motionpixels_tablegen.c
@@ -1,5 +1,5 @@
 /*
- * Generate a header file for hardcoded motionpixels RGB to YUV table
+ * Generate a header file for hardcoded motion pixels RGB to YUV table
  *
  * Copyright (c) 2009 Reimar Döffinger <Reimar.Doeffinger at gmx.de>
  *
diff --git a/libavcodec/motionpixels_tablegen.h b/libavcodec/motionpixels_tablegen.h
index 4ffe74c..9239b6a 100644
--- a/libavcodec/motionpixels_tablegen.h
+++ b/libavcodec/motionpixels_tablegen.h
@@ -1,5 +1,5 @@
 /*
- * Header file for hardcoded motionpixels RGB to YUV table
+ * Header file for hardcoded motion pixels RGB to YUV table
  *
  * Copyright (c) 2009 Reimar Döffinger <Reimar.Doeffinger at gmx.de>
  *
diff --git a/libavcodec/movsub_bsf.c b/libavcodec/movsub_bsf.c
index 8ee7a3a..3cb1183 100644
--- a/libavcodec/movsub_bsf.c
+++ b/libavcodec/movsub_bsf.c
@@ -21,39 +21,79 @@
 #include "libavutil/common.h"
 #include "libavutil/intreadwrite.h"
 #include "avcodec.h"
+#include "bsf.h"
 
+static int text2movsub(AVBSFContext *ctx, AVPacket *out)
+{
+    AVPacket *in;
+    int ret = 0;
 
-static int text2movsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    if (buf_size > 0xffff) return 0;
-    *poutbuf_size = buf_size + 2;
-    *poutbuf = av_malloc(*poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
-    AV_WB16(*poutbuf, buf_size);
-    memcpy(*poutbuf + 2, buf, buf_size);
-    return 1;
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    if (in->size > 0xffff) {
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
+    }
+
+    ret = av_new_packet(out, in->size + 2);
+    if (ret < 0) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+    AV_WB16(out->data, in->size);
+    memcpy(out->data + 2, in->data, in->size);
+
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_text2movsub_bsf={
+const AVBitStreamFilter ff_text2movsub_bsf = {
     .name   = "text2movsub",
     .filter = text2movsub,
 };
 
-static int mov2textsub(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    if (buf_size < 2) return 0;
-    *poutbuf_size = FFMIN(buf_size - 2, AV_RB16(buf));
-    *poutbuf = av_malloc(*poutbuf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
-    memcpy(*poutbuf, buf + 2, *poutbuf_size);
-    return 1;
+static int mov2textsub(AVBSFContext *ctx, AVPacket *out)
+{
+    AVPacket *in;
+    int ret = 0;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    if (in->size < 2) {
+       ret = AVERROR_INVALIDDATA;
+       goto fail;
+    }
+
+    ret = av_new_packet(out, FFMIN(in->size - 2, AV_RB16(in->data)));
+    if (ret < 0)
+        goto fail;
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+    memcpy(out->data, in->data + 2, out->size);
+
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_mov2textsub_bsf={
+const AVBitStreamFilter ff_mov2textsub_bsf = {
     .name   = "mov2textsub",
     .filter = mov2textsub,
 };
diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c
index 8d0e814..abf8711 100644
--- a/libavcodec/movtextdec.c
+++ b/libavcodec/movtextdec.c
@@ -99,6 +99,7 @@ typedef struct {
     uint64_t tracksize;
     int size_var;
     int count_s, count_f;
+    int readorder;
 } MovTextContext;
 
 typedef struct {
@@ -424,7 +425,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
 {
     AVSubtitle *sub = data;
     MovTextContext *m = avctx->priv_data;
-    int ret, ts_start, ts_end;
+    int ret;
     AVBPrint buf;
     char *ptr = avpkt->data;
     char *end;
@@ -454,13 +455,6 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
     end = ptr + FFMIN(2 + text_length, avpkt->size);
     ptr += 2;
 
-    ts_start = av_rescale_q(avpkt->pts,
-                            avctx->time_base,
-                            (AVRational){1,100});
-    ts_end   = av_rescale_q(avpkt->pts + avpkt->duration,
-                            avctx->time_base,
-                            (AVRational){1,100});
-
     tsmb_size = 0;
     m->tracksize = 2 + text_length;
     m->style_entries = 0;
@@ -506,7 +500,7 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
     } else
         text_to_ass(&buf, ptr, end, m);
 
-    ret = ff_ass_add_rect_bprint(sub, &buf, ts_start, ts_end - ts_start);
+    ret = ff_ass_add_rect(sub, buf.str, m->readorder++, 0, NULL, NULL);
     av_bprint_finalize(&buf, NULL);
     if (ret < 0)
         return ret;
@@ -521,6 +515,13 @@ static int mov_text_decode_close(AVCodecContext *avctx)
     return 0;
 }
 
+static void mov_text_flush(AVCodecContext *avctx)
+{
+    MovTextContext *m = avctx->priv_data;
+    if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
+        m->readorder = 0;
+}
+
 AVCodec ff_movtext_decoder = {
     .name         = "mov_text",
     .long_name    = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
@@ -530,4 +531,5 @@ AVCodec ff_movtext_decoder = {
     .init         = mov_text_init,
     .decode       = mov_text_decode_frame,
     .close        = mov_text_decode_close,
+    .flush        = mov_text_flush,
 };
diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c
index 6d42d5f..20e01e2 100644
--- a/libavcodec/movtextenc.c
+++ b/libavcodec/movtextenc.c
@@ -324,7 +324,7 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
 {
     MovTextContext *s = avctx->priv_data;
     ASSDialog *dialog;
-    int i, num, length;
+    int i, length;
     size_t j;
 
     s->text_pos = 0;
@@ -332,16 +332,30 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
     s->box_flags = 0;
     s->style_entries = 0;
     for (i = 0; i < sub->num_rects; i++) {
+        const char *ass = sub->rects[i]->ass;
 
         if (sub->rects[i]->type != SUBTITLE_ASS) {
             av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
             return AVERROR(ENOSYS);
         }
 
-        dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num);
-        for (; dialog && num--; dialog++) {
+#if FF_API_ASS_TIMING
+        if (!strncmp(ass, "Dialogue: ", 10)) {
+            int num;
+            dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num);
+            for (; dialog && num--; dialog++) {
+                ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text);
+            }
+        } else {
+#endif
+            dialog = ff_ass_split_dialog2(s->ass_ctx, ass);
+            if (!dialog)
+                return AVERROR(ENOMEM);
             ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text);
+            ff_ass_free_dialog(&dialog);
+#if FF_API_ASS_TIMING
         }
+#endif
 
         for (j = 0; j < box_count; j++) {
             box_types[j].encode(s, box_types[j].type);
diff --git a/libavcodec/mp3_header_decompress_bsf.c b/libavcodec/mp3_header_decompress_bsf.c
index 95c0b5b..22c1ef0 100644
--- a/libavcodec/mp3_header_decompress_bsf.c
+++ b/libavcodec/mp3_header_decompress_bsf.c
@@ -21,32 +21,43 @@
 #include "libavutil/common.h"
 #include "libavutil/intreadwrite.h"
 #include "avcodec.h"
+#include "bsf.h"
 #include "mpegaudiodecheader.h"
 #include "mpegaudiodata.h"
 
 
-static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
+static int mp3_header_decompress(AVBSFContext *ctx, AVPacket *out)
+{
+    AVPacket *in;
     uint32_t header;
-    int sample_rate= avctx->sample_rate;
+    int sample_rate= ctx->par_in->sample_rate;
     int sample_rate_index=0;
-    int lsf, mpeg25, bitrate_index, frame_size;
+    int lsf, mpeg25, bitrate_index, frame_size, ret;
+    uint8_t *buf;
+    int buf_size;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    buf      = in->data;
+    buf_size = in->size;
 
     header = AV_RB32(buf);
     if(ff_mpa_check_header(header) >= 0){
-        *poutbuf= (uint8_t *) buf;
-        *poutbuf_size= buf_size;
+        av_packet_move_ref(out, in);
+        av_packet_free(&in);
 
         return 0;
     }
 
-    if(avctx->extradata_size != 15 || strcmp(avctx->extradata, "FFCMP3 0.0")){
-        av_log(avctx, AV_LOG_ERROR, "Extradata invalid %d\n", avctx->extradata_size);
-        return -1;
+    if(ctx->par_in->extradata_size != 15 || strcmp(ctx->par_in->extradata, "FFCMP3 0.0")){
+        av_log(ctx, AV_LOG_ERROR, "Extradata invalid %d\n", ctx->par_in->extradata_size);
+        ret = AVERROR(EINVAL);
+        goto fail;
     }
 
-    header= AV_RB32(avctx->extradata+11) & MP3_MASK;
+    header= AV_RB32(ctx->par_in->extradata+11) & MP3_MASK;
 
     lsf     = sample_rate < (24000+32000)/2;
     mpeg25  = sample_rate < (12000+16000)/2;
@@ -62,20 +73,27 @@ static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext
             break;
     }
     if(bitrate_index == 30){
-        av_log(avctx, AV_LOG_ERROR, "Could not find bitrate_index.\n");
-        return -1;
+        av_log(ctx, AV_LOG_ERROR, "Could not find bitrate_index.\n");
+        ret = AVERROR(EINVAL);
+        goto fail;
     }
 
     header |= (bitrate_index&1)<<9;
     header |= (bitrate_index>>1)<<12;
     header |= (frame_size == buf_size + 4)<<16; //FIXME actually set a correct crc instead of 0
 
-    *poutbuf_size= frame_size;
-    *poutbuf= av_malloc(frame_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    memcpy(*poutbuf + frame_size - buf_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    ret = av_new_packet(out, frame_size);
+    if (ret < 0)
+        goto fail;
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0) {
+        av_packet_free(&out);
+        goto fail;
+    }
+    memcpy(out->data + frame_size - buf_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
 
-    if(avctx->channels==2){
-        uint8_t *p= *poutbuf + frame_size - buf_size;
+    if(ctx->par_in->channels==2){
+        uint8_t *p= out->data + frame_size - buf_size;
         if(lsf){
             FFSWAP(int, p[1], p[2]);
             header |= (p[1] & 0xC0)>>2;
@@ -86,12 +104,21 @@ static int mp3_header_decompress(AVBitStreamFilterContext *bsfc, AVCodecContext
         }
     }
 
-    AV_WB32(*poutbuf, header);
+    AV_WB32(out->data, header);
 
-    return 1;
+    ret = 0;
+
+fail:
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_mp3_header_decompress_bsf={
-    .name   = "mp3decomp",
-    .filter = mp3_header_decompress,
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MP3, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_mp3_header_decompress_bsf = {
+    .name      = "mp3decomp",
+    .filter    = mp3_header_decompress,
+    .codec_ids = codec_ids,
 };
diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c
index a8feb6c..8894457 100644
--- a/libavcodec/mpc8.c
+++ b/libavcodec/mpc8.c
@@ -415,10 +415,14 @@ static int mpc8_decode_frame(AVCodecContext * avctx, void *data,
     c->cur_frame++;
 
     c->last_bits_used = get_bits_count(gb);
-    if(get_bits_left(gb) < 8) // we have only padding left
-        c->last_bits_used = buf_size << 3;
     if(c->cur_frame >= c->frames)
         c->cur_frame = 0;
+    if(c->cur_frame == 0 && get_bits_left(gb) < 8) {// we have only padding left
+        c->last_bits_used = buf_size << 3;
+    } else if (get_bits_left(gb) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Overread %d\n", -get_bits_left(gb));
+        c->last_bits_used = buf_size << 3;
+    }
 
     *got_frame_ptr = 1;
 
diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c
index e8a4048..7c14052 100644
--- a/libavcodec/mpeg12.c
+++ b/libavcodec/mpeg12.c
@@ -243,3 +243,98 @@ int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size,
     return END_NOT_FOUND;
 }
 
+#define MAX_INDEX (64 - 1)
+
+int ff_mpeg1_decode_block_intra(GetBitContext *gb,
+                                const uint16_t *quant_matrix,
+                                uint8_t *const scantable, int last_dc[3],
+                                int16_t *block, int index, int qscale)
+{
+    int dc, diff, i = 0, component;
+    RLTable *rl = &ff_rl_mpeg1;
+
+    /* DC coefficient */
+    component = index <= 3 ? 0 : index - 4 + 1;
+
+    diff = decode_dc(gb, component);
+    if (diff >= 0xffff)
+        return AVERROR_INVALIDDATA;
+
+    dc  = last_dc[component];
+    dc += diff;
+    last_dc[component] = dc;
+
+    block[0] = dc * quant_matrix[0];
+
+    {
+        OPEN_READER(re, gb);
+        UPDATE_CACHE(re, gb);
+        if (((int32_t)GET_CACHE(re, gb)) <= (int32_t)0xBFFFFFFF)
+            goto end;
+
+        /* now quantify & encode AC coefficients */
+        while (1) {
+            int level, run, j;
+
+            GET_RL_VLC(level, run, re, gb, rl->rl_vlc[0],
+                       TEX_VLC_BITS, 2, 0);
+
+            if (level != 0) {
+                i += run;
+                if (i > MAX_INDEX)
+                    break;
+
+                j = scantable[i];
+                level = (level * qscale * quant_matrix[j]) >> 4;
+                level = (level - 1) | 1;
+                level = (level ^ SHOW_SBITS(re, gb, 1)) -
+                        SHOW_SBITS(re, gb, 1);
+                SKIP_BITS(re, gb, 1);
+            } else {
+                /* escape */
+                run = SHOW_UBITS(re, gb, 6) + 1;
+                LAST_SKIP_BITS(re, gb, 6);
+                UPDATE_CACHE(re, gb);
+                level = SHOW_SBITS(re, gb, 8);
+                SKIP_BITS(re, gb, 8);
+
+                if (level == -128) {
+                    level = SHOW_UBITS(re, gb, 8) - 256;
+                    SKIP_BITS(re, gb, 8);
+                } else if (level == 0) {
+                    level = SHOW_UBITS(re, gb, 8);
+                    SKIP_BITS(re, gb, 8);
+                }
+
+                i += run;
+                if (i > MAX_INDEX)
+                    break;
+
+                j = scantable[i];
+                if (level < 0) {
+                    level = -level;
+                    level = (level * qscale * quant_matrix[j]) >> 4;
+                    level = (level - 1) | 1;
+                    level = -level;
+                } else {
+                    level = (level * qscale * quant_matrix[j]) >> 4;
+                    level = (level - 1) | 1;
+                }
+            }
+
+            block[j] = level;
+            if (((int32_t)GET_CACHE(re, gb)) <= (int32_t)0xBFFFFFFF)
+               break;
+
+            UPDATE_CACHE(re, gb);
+        }
+end:
+        LAST_SKIP_BITS(re, gb, 2);
+        CLOSE_READER(re, gb);
+    }
+
+    if (i > MAX_INDEX)
+        i = AVERROR_INVALIDDATA;
+
+    return i;
+}
diff --git a/libavcodec/mpeg12.h b/libavcodec/mpeg12.h
index 16ca195..ad9b00c 100644
--- a/libavcodec/mpeg12.h
+++ b/libavcodec/mpeg12.h
@@ -1,5 +1,5 @@
 /*
- * MPEG1/2 common code
+ * MPEG-1/2 common code
  * Copyright (c) 2007 Aurelien Jacobs <aurel at gnuage.org>
  *
  * This file is part of FFmpeg.
@@ -50,7 +50,11 @@ static inline int decode_dc(GetBitContext *gb, int component)
     return diff;
 }
 
-int ff_mpeg1_decode_block_intra(MpegEncContext *s, int16_t *block, int n);
+int ff_mpeg1_decode_block_intra(GetBitContext *gb,
+                                const uint16_t *quant_matrix,
+                                uint8_t *const scantable, int last_dc[3],
+                                int16_t *block, int index, int qscale);
+
 void ff_mpeg1_clean_buffers(MpegEncContext *s);
 int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, AVCodecParserContext *s);
 
diff --git a/libavcodec/mpeg12data.c b/libavcodec/mpeg12data.c
index e8c4a5d..416bbb8 100644
--- a/libavcodec/mpeg12data.c
+++ b/libavcodec/mpeg12data.c
@@ -1,5 +1,5 @@
 /*
- * MPEG1/2 tables
+ * MPEG-1/2 tables
  * copyright (c) 2000,2001 Fabrice Bellard
  * copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * MPEG1/2 tables.
+ * MPEG-1/2 tables.
  */
 
 #include "mpeg12data.h"
diff --git a/libavcodec/mpeg12data.h b/libavcodec/mpeg12data.h
index 65b9485..f51faf4 100644
--- a/libavcodec/mpeg12data.h
+++ b/libavcodec/mpeg12data.h
@@ -1,5 +1,5 @@
 /*
- * MPEG1/2 tables
+ * MPEG-1/2 tables
  * copyright (c) 2000,2001 Fabrice Bellard
  * copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * MPEG1/2 tables.
+ * MPEG-1/2 tables.
  */
 
 #ifndef AVCODEC_MPEG12DATA_H
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index cc8ace8..204a578 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -124,103 +124,16 @@ static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred)
     return sign_extend(val, 5 + shift);
 }
 
+#define MAX_INDEX (64 - 1)
 #define check_scantable_index(ctx, x)                                         \
     do {                                                                      \
-        if ((x) > 63) {                                                       \
+        if ((x) > MAX_INDEX) {                                                \
             av_log(ctx->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n",     \
                    ctx->mb_x, ctx->mb_y);                                     \
             return AVERROR_INVALIDDATA;                                       \
         }                                                                     \
     } while (0)
 
-static inline int mpeg1_decode_block_intra(MpegEncContext *s,
-                                           int16_t *block, int n)
-{
-    int level, dc, diff, i, j, run;
-    int component;
-    RLTable *rl                  = &ff_rl_mpeg1;
-    uint8_t *const scantable     = s->intra_scantable.permutated;
-    const uint16_t *quant_matrix = s->intra_matrix;
-    const int qscale             = s->qscale;
-
-    /* DC coefficient */
-    component = (n <= 3 ? 0 : n - 4 + 1);
-    diff = decode_dc(&s->gb, component);
-    if (diff >= 0xffff)
-        return AVERROR_INVALIDDATA;
-    dc  = s->last_dc[component];
-    dc += diff;
-    s->last_dc[component] = dc;
-    block[0] = dc * quant_matrix[0];
-    ff_tlog(s->avctx, "dc=%d diff=%d\n", dc, diff);
-    i = 0;
-    {
-        OPEN_READER(re, &s->gb);
-        UPDATE_CACHE(re, &s->gb);
-        if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF)
-            goto end;
-
-        /* now quantify & encode AC coefficients */
-        for (;;) {
-            GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0],
-                       TEX_VLC_BITS, 2, 0);
-
-            if (level != 0) {
-                i += run;
-                check_scantable_index(s, i);
-                j = scantable[i];
-                level = (level * qscale * quant_matrix[j]) >> 4;
-                level = (level - 1) | 1;
-                level = (level ^ SHOW_SBITS(re, &s->gb, 1)) -
-                        SHOW_SBITS(re, &s->gb, 1);
-                SKIP_BITS(re, &s->gb, 1);
-            } else {
-                /* escape */
-                run = SHOW_UBITS(re, &s->gb, 6) + 1;
-                LAST_SKIP_BITS(re, &s->gb, 6);
-                UPDATE_CACHE(re, &s->gb);
-                level = SHOW_SBITS(re, &s->gb, 8);
-                SKIP_BITS(re, &s->gb, 8);
-                if (level == -128) {
-                    level = SHOW_UBITS(re, &s->gb, 8) - 256;
-                    SKIP_BITS(re, &s->gb, 8);
-                } else if (level == 0) {
-                    level = SHOW_UBITS(re, &s->gb, 8);
-                    SKIP_BITS(re, &s->gb, 8);
-                }
-                i += run;
-                check_scantable_index(s, i);
-                j = scantable[i];
-                if (level < 0) {
-                    level = -level;
-                    level = (level * qscale * quant_matrix[j]) >> 4;
-                    level = (level - 1) | 1;
-                    level = -level;
-                } else {
-                    level = (level * qscale * quant_matrix[j]) >> 4;
-                    level = (level - 1) | 1;
-                }
-            }
-
-            block[j] = level;
-            if (((int32_t)GET_CACHE(re, &s->gb)) <= (int32_t)0xBFFFFFFF)
-               break;
-
-            UPDATE_CACHE(re, &s->gb);
-        }
-end:
-        LAST_SKIP_BITS(re, &s->gb, 2);
-        CLOSE_READER(re, &s->gb);
-    }
-    s->block_last_index[n] = i;
-    return 0;
-}
-
-int ff_mpeg1_decode_block_intra(MpegEncContext *s, int16_t *block, int n)
-{
-    return mpeg1_decode_block_intra(s, block, n);
-}
-
 static inline int mpeg1_decode_block_inter(MpegEncContext *s,
                                            int16_t *block, int n)
 {
@@ -253,7 +166,8 @@ static inline int mpeg1_decode_block_inter(MpegEncContext *s,
 
             if (level != 0) {
                 i += run;
-                check_scantable_index(s, i);
+                if (i > MAX_INDEX)
+                    break;
                 j = scantable[i];
                 level = ((level * 2 + 1) * qscale * quant_matrix[j]) >> 5;
                 level = (level - 1) | 1;
@@ -275,7 +189,8 @@ static inline int mpeg1_decode_block_inter(MpegEncContext *s,
                     SKIP_BITS(re, &s->gb, 8);
                 }
                 i += run;
-                check_scantable_index(s, i);
+                if (i > MAX_INDEX)
+                    break;
                 j = scantable[i];
                 if (level < 0) {
                     level = -level;
@@ -297,6 +212,9 @@ end:
         LAST_SKIP_BITS(re, &s->gb, 2);
         CLOSE_READER(re, &s->gb);
     }
+
+    check_scantable_index(s, i);
+
     s->block_last_index[n] = i;
     return 0;
 }
@@ -338,7 +256,8 @@ static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s,
 
             if (level != 0) {
                 i += run;
-                check_scantable_index(s, i);
+                if (i > MAX_INDEX)
+                    break;
                 j = scantable[i];
                 level = ((level * 2 + 1) * qscale) >> 1;
                 level = (level - 1) | 1;
@@ -360,7 +279,8 @@ static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s,
                     SKIP_BITS(re, &s->gb, 8);
                 }
                 i += run;
-                check_scantable_index(s, i);
+                if (i > MAX_INDEX)
+                    break;
                 j = scantable[i];
                 if (level < 0) {
                     level = -level;
@@ -382,6 +302,9 @@ end:
         LAST_SKIP_BITS(re, &s->gb, 2);
         CLOSE_READER(re, &s->gb);
     }
+
+    check_scantable_index(s, i);
+
     s->block_last_index[n] = i;
     return 0;
 }
@@ -427,7 +350,8 @@ static inline int mpeg2_decode_block_non_intra(MpegEncContext *s,
 
             if (level != 0) {
                 i += run;
-                check_scantable_index(s, i);
+                if (i > MAX_INDEX)
+                    break;
                 j = scantable[i];
                 level = ((level * 2 + 1) * qscale * quant_matrix[j]) >> 5;
                 level = (level ^ SHOW_SBITS(re, &s->gb, 1)) -
@@ -442,7 +366,8 @@ static inline int mpeg2_decode_block_non_intra(MpegEncContext *s,
                 SKIP_BITS(re, &s->gb, 12);
 
                 i += run;
-                check_scantable_index(s, i);
+                if (i > MAX_INDEX)
+                    break;
                 j = scantable[i];
                 if (level < 0) {
                     level = ((-level * 2 + 1) * qscale * quant_matrix[j]) >> 5;
@@ -464,6 +389,8 @@ end:
     }
     block[63] ^= (mismatch & 1);
 
+    check_scantable_index(s, i);
+
     s->block_last_index[n] = i;
     return 0;
 }
@@ -502,6 +429,8 @@ static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s,
 
         if (level != 0) {
             i += run;
+            if (i > MAX_INDEX)
+                break;
             j = scantable[i];
             level = ((level * 2 + 1) * qscale) >> 1;
             level = (level ^ SHOW_SBITS(re, &s->gb, 1)) -
@@ -516,6 +445,8 @@ static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s,
             SKIP_BITS(re, &s->gb, 12);
 
             i += run;
+            if (i > MAX_INDEX)
+                break;
             j = scantable[i];
             if (level < 0) {
                 level = ((-level * 2 + 1) * qscale) >> 1;
@@ -534,6 +465,9 @@ static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s,
 end:
     LAST_SKIP_BITS(re, &s->gb, 2);
     CLOSE_READER(re, &s->gb);
+
+    check_scantable_index(s, i);
+
     s->block_last_index[n] = i;
     return 0;
 }
@@ -584,7 +518,8 @@ static inline int mpeg2_decode_block_intra(MpegEncContext *s,
                 break;
             } else if (level != 0) {
                 i += run;
-                check_scantable_index(s, i);
+                if (i > MAX_INDEX)
+                    break;
                 j = scantable[i];
                 level = (level * qscale * quant_matrix[j]) >> 4;
                 level = (level ^ SHOW_SBITS(re, &s->gb, 1)) -
@@ -598,7 +533,8 @@ static inline int mpeg2_decode_block_intra(MpegEncContext *s,
                 level = SHOW_SBITS(re, &s->gb, 12);
                 SKIP_BITS(re, &s->gb, 12);
                 i += run;
-                check_scantable_index(s, i);
+                if (i > MAX_INDEX)
+                    break;
                 j = scantable[i];
                 if (level < 0) {
                     level = (-level * qscale * quant_matrix[j]) >> 4;
@@ -615,6 +551,8 @@ static inline int mpeg2_decode_block_intra(MpegEncContext *s,
     }
     block[63] ^= mismatch & 1;
 
+    check_scantable_index(s, i);
+
     s->block_last_index[n] = i;
     return 0;
 }
@@ -694,6 +632,8 @@ static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s,
         CLOSE_READER(re, &s->gb);
     }
 
+    check_scantable_index(s, i);
+
     s->block_last_index[n] = i;
     return 0;
 }
@@ -768,7 +708,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64])
         if (get_bits1(&s->gb) == 0) {
             if (get_bits1(&s->gb) == 0) {
                 av_log(s->avctx, AV_LOG_ERROR,
-                       "invalid mb type in I Frame at %d %d\n",
+                       "Invalid mb type in I-frame at %d %d\n",
                        s->mb_x, s->mb_y);
                 return AVERROR_INVALIDDATA;
             }
@@ -781,7 +721,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64])
         mb_type = get_vlc2(&s->gb, ff_mb_ptype_vlc.table, MB_PTYPE_VLC_BITS, 1);
         if (mb_type < 0) {
             av_log(s->avctx, AV_LOG_ERROR,
-                   "invalid mb type in P Frame at %d %d\n", s->mb_x, s->mb_y);
+                   "Invalid mb type in P-frame at %d %d\n", s->mb_x, s->mb_y);
             return AVERROR_INVALIDDATA;
         }
         mb_type = ptype2mb_type[mb_type];
@@ -790,7 +730,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64])
         mb_type = get_vlc2(&s->gb, ff_mb_btype_vlc.table, MB_BTYPE_VLC_BITS, 1);
         if (mb_type < 0) {
             av_log(s->avctx, AV_LOG_ERROR,
-                   "invalid mb type in B Frame at %d %d\n", s->mb_x, s->mb_y);
+                   "Invalid mb type in B-frame at %d %d\n", s->mb_x, s->mb_y);
             return AVERROR_INVALIDDATA;
         }
         mb_type = btype2mb_type[mb_type];
@@ -827,7 +767,7 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64])
             s->last_mv[0][1][1] = mpeg_decode_motion(s, s->mpeg_f_code[0][1],
                                                      s->last_mv[0][0][1]);
 
-            check_marker(&s->gb, "after concealment_motion_vectors");
+            check_marker(s->avctx, &s->gb, "after concealment_motion_vectors");
         } else {
             /* reset mv prediction */
             memset(s->last_mv, 0, sizeof(s->last_mv));
@@ -847,9 +787,20 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64])
                         return ret;
             }
         } else {
-            for (i = 0; i < 6; i++)
-                if ((ret = mpeg1_decode_block_intra(s, *s->pblocks[i], i)) < 0)
+            for (i = 0; i < 6; i++) {
+                ret = ff_mpeg1_decode_block_intra(&s->gb,
+                                                  s->intra_matrix,
+                                                  s->intra_scantable.permutated,
+                                                  s->last_dc, *s->pblocks[i],
+                                                  i, s->qscale);
+                if (ret < 0) {
+                    av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n",
+                           s->mb_x, s->mb_y);
                     return ret;
+                }
+
+                s->block_last_index[i] = ret;
+            }
         }
     } else {
         if (mb_type & MB_TYPE_ZERO_MV) {
@@ -1488,7 +1439,7 @@ static void mpeg_decode_sequence_extension(Mpeg1Context *s1)
     s->height |= (vert_size_ext  << 12);
     bit_rate_ext = get_bits(&s->gb, 12);  /* XXX: handle it */
     s->bit_rate += (bit_rate_ext << 18) * 400LL;
-    check_marker(&s->gb, "after bit rate extension");
+    check_marker(s->avctx, &s->gb, "after bit rate extension");
     s->avctx->rc_buffer_size += get_bits(&s->gb, 8) * 1024 * 16 << 10;
 
     s->low_delay = get_bits1(&s->gb);
@@ -1920,6 +1871,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y,
 
         if (++s->mb_x >= s->mb_width) {
             const int mb_size = 16 >> s->avctx->lowres;
+            int left;
 
             ff_mpeg_draw_horiz_band(s, mb_size * (s->mb_y >> field_pic), mb_size);
             ff_mpv_report_decode_progress(s);
@@ -1944,13 +1896,17 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y,
                         av_log(avctx, AV_LOG_DEBUG, "Invalid MXF data found in video stream\n");
                         is_d10 = 1;
                     }
+                    if (left > 32 && show_bits_long(&gb, 32) == 0x201) {
+                        av_log(avctx, AV_LOG_DEBUG, "skipping m704 alpha (unsupported)\n");
+                        goto eos;
+                    }
                 }
 
                 if (left < 0 ||
                     (left && show_bits(&s->gb, FFMIN(left, 23)) && !is_d10) ||
                     ((avctx->err_recognition & (AV_EF_BITSTREAM | AV_EF_AGGRESSIVE)) && left > 8)) {
-                    av_log(avctx, AV_LOG_ERROR, "end mismatch left=%d %0X\n",
-                           left, left>0 ? show_bits(&s->gb, FFMIN(left, 23)) : 0);
+                    av_log(avctx, AV_LOG_ERROR, "end mismatch left=%d %0X at %d %d\n",
+                           left, left>0 ? show_bits(&s->gb, FFMIN(left, 23)) : 0, s->mb_x, s->mb_y);
                     return AVERROR_INVALIDDATA;
                 } else
                     goto eos;
@@ -1959,12 +1915,13 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y,
             // in cases where the slice is completely outside the visible
             // area, we detect this here instead of running into the end expecting
             // more data
+            left = get_bits_left(&s->gb);
             if (s->mb_y >= ((s->height + 15) >> 4) &&
                 !s->progressive_sequence &&
-                get_bits_left(&s->gb) <= 8 &&
-                get_bits_left(&s->gb) >= 0 &&
+                left <= 25 &&
+                left >= 0 &&
                 s->mb_skip_run == -1 &&
-                show_bits(&s->gb, 8) == 0)
+                (!left || show_bits(&s->gb, left) == 0))
                 goto eos;
 
             ff_init_block_index(s);
@@ -2001,7 +1958,7 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y,
                 int i;
                 if (s->pict_type == AV_PICTURE_TYPE_I) {
                     av_log(s->avctx, AV_LOG_ERROR,
-                           "skipped MB in I frame at %d %d\n", s->mb_x, s->mb_y);
+                           "skipped MB in I-frame at %d %d\n", s->mb_x, s->mb_y);
                     return AVERROR_INVALIDDATA;
                 }
 
@@ -2173,7 +2130,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx,
         s->frame_rate_index = 1;
     }
     s->bit_rate = get_bits(&s->gb, 18) * 400LL;
-    if (check_marker(&s->gb, "in sequence header") == 0) {
+    if (check_marker(s->avctx, &s->gb, "in sequence header") == 0) {
         return AVERROR_INVALIDDATA;
     }
 
@@ -2309,7 +2266,7 @@ static int mpeg_decode_a53_cc(AVCodecContext *avctx,
         int cc_count = 0;
         int i;
         // There is a caption count field in the data, but it is often
-        // incorect.  So count the number of captions present.
+        // incorrect.  So count the number of captions present.
         for (i = 5; i + 6 <= buf_size && ((p[i] & 0xfe) == 0xfe); i += 6)
             cc_count++;
         // Transform the DVD format into A53 Part 4 format
diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c
index ea45c07..f45598a 100644
--- a/libavcodec/mpeg12enc.c
+++ b/libavcodec/mpeg12enc.c
@@ -1,5 +1,5 @@
 /*
- * MPEG1/2 encoder
+ * MPEG-1/2 encoder
  * Copyright (c) 2000,2001 Fabrice Bellard
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * MPEG1/2 encoder
+ * MPEG-1/2 encoder
  */
 
 #include <stdint.h>
@@ -144,12 +144,12 @@ static av_cold int encode_init(AVCodecContext *avctx)
 
     if (find_frame_rate_index(s) < 0) {
         if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
-            av_log(avctx, AV_LOG_ERROR, "MPEG1/2 does not support %d/%d fps\n",
+            av_log(avctx, AV_LOG_ERROR, "MPEG-1/2 does not support %d/%d fps\n",
                    avctx->time_base.den, avctx->time_base.num);
             return -1;
         } else {
             av_log(avctx, AV_LOG_INFO,
-                   "MPEG1/2 does not support %d/%d fps, there may be AV sync issues\n",
+                   "MPEG-1/2 does not support %d/%d fps, there may be AV sync issues\n",
                    avctx->time_base.den, avctx->time_base.num);
         }
     }
@@ -249,7 +249,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s)
     if (s->current_picture.f->key_frame) {
         AVRational framerate = ff_mpeg12_frame_rate_tab[s->frame_rate_index];
 
-        /* mpeg1 header repeated every gop */
+        /* MPEG-1 header repeated every GOP */
         put_header(s, SEQ_START_CODE);
 
         put_sbits(&s->pb, 12, s->width  & 0xFFF);
@@ -423,7 +423,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
     AVFrameSideData *side_data;
     mpeg1_encode_sequence_header(s);
 
-    /* mpeg1 picture header */
+    /* MPEG-1 picture header */
     put_header(s, PICTURE_START_CODE);
     /* temporal reference */
 
diff --git a/libavcodec/mpeg12vlc.h b/libavcodec/mpeg12vlc.h
index 31888fd..ca06e56 100644
--- a/libavcodec/mpeg12vlc.h
+++ b/libavcodec/mpeg12vlc.h
@@ -1,5 +1,5 @@
 /*
- * MPEG1/2 VLC
+ * MPEG-1/2 VLC
  * copyright (c) 2000,2001 Fabrice Bellard
  * copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * MPEG1/2 VLC.
+ * MPEG-1/2 VLC.
  */
 
 #ifndef AVCODEC_MPEG12VLC_H
diff --git a/libavcodec/mpeg4_unpack_bframes_bsf.c b/libavcodec/mpeg4_unpack_bframes_bsf.c
index df49d3f..0615621 100644
--- a/libavcodec/mpeg4_unpack_bframes_bsf.c
+++ b/libavcodec/mpeg4_unpack_bframes_bsf.c
@@ -20,12 +20,12 @@
  */
 
 #include "avcodec.h"
+#include "bsf.h"
 #include "mpeg4video.h"
 
 typedef struct UnpackBFramesBSFContext {
     uint8_t *b_frame_buf;
     int      b_frame_buf_size;
-    int      updated_extradata;
 } UnpackBFramesBSFContext;
 
 /* search next start code */
@@ -83,112 +83,109 @@ static uint8_t *create_new_buffer(const uint8_t *src, int size) {
     return dst;
 }
 
-static int mpeg4_unpack_bframes_filter(AVBitStreamFilterContext *bsfc,
-                                       AVCodecContext *avctx, const char *args,
-                                       uint8_t  **poutbuf, int *poutbuf_size,
-                                       const uint8_t *buf, int      buf_size,
-                                       int keyframe)
+static int mpeg4_unpack_bframes_filter(AVBSFContext *ctx, AVPacket *out)
 {
-    UnpackBFramesBSFContext *ctx = bsfc->priv_data;
+    UnpackBFramesBSFContext *s = ctx->priv_data;
     int pos_p = -1, nb_vop = 0, pos_vop2 = -1, ret = 0;
+    AVPacket *in;
 
-    if (avctx->codec_id != AV_CODEC_ID_MPEG4) {
-        av_log(avctx, AV_LOG_ERROR,
-               "The mpeg4_unpack_bframes bitstream filter is only useful for mpeg4.\n");
-        return AVERROR(EINVAL);
-    }
-
-    if (!ctx->updated_extradata && avctx->extradata) {
-        int pos_p_ext = -1;
-        scan_buffer(avctx->extradata, avctx->extradata_size, &pos_p_ext, NULL, NULL);
-        if (pos_p_ext >= 0) {
-            av_log(avctx, AV_LOG_DEBUG,
-                   "Updating DivX userdata (remove trailing 'p') in extradata.\n");
-            avctx->extradata[pos_p_ext] = '\0';
-        }
-        ctx->updated_extradata = 1;
-    }
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
 
-    scan_buffer(buf, buf_size, &pos_p, &nb_vop, &pos_vop2);
-    av_log(avctx, AV_LOG_DEBUG, "Found %d VOP startcode(s) in this packet.\n", nb_vop);
+    scan_buffer(in->data, in->size, &pos_p, &nb_vop, &pos_vop2);
+    av_log(ctx, AV_LOG_DEBUG, "Found %d VOP startcode(s) in this packet.\n", nb_vop);
 
     if (pos_vop2 >= 0) {
-        if (ctx->b_frame_buf) {
-            av_log(avctx, AV_LOG_WARNING,
+        if (s->b_frame_buf) {
+            av_log(ctx, AV_LOG_WARNING,
                    "Missing one N-VOP packet, discarding one B-frame.\n");
-            av_freep(&ctx->b_frame_buf);
-            ctx->b_frame_buf_size = 0;
+            av_freep(&s->b_frame_buf);
+            s->b_frame_buf_size = 0;
         }
         /* store the packed B-frame in the BSFContext */
-        ctx->b_frame_buf_size = buf_size - pos_vop2;
-        ctx->b_frame_buf      = create_new_buffer(buf + pos_vop2, ctx->b_frame_buf_size);
-        if (!ctx->b_frame_buf) {
-            ctx->b_frame_buf_size = 0;
+        s->b_frame_buf_size = in->size - pos_vop2;
+        s->b_frame_buf      = create_new_buffer(in->data + pos_vop2, s->b_frame_buf_size);
+        if (!s->b_frame_buf) {
+            s->b_frame_buf_size = 0;
+            av_packet_free(&in);
             return AVERROR(ENOMEM);
         }
     }
 
     if (nb_vop > 2) {
-        av_log(avctx, AV_LOG_WARNING,
+        av_log(ctx, AV_LOG_WARNING,
        "Found %d VOP headers in one packet, only unpacking one.\n", nb_vop);
     }
 
-    if (nb_vop == 1 && ctx->b_frame_buf) {
+    if (nb_vop == 1 && s->b_frame_buf) {
         /* use frame from BSFContext */
-        *poutbuf      = ctx->b_frame_buf;
-        *poutbuf_size = ctx->b_frame_buf_size;
-        /* the output buffer is distinct from the input buffer */
-        ret = 1;
-        if (buf_size <= MAX_NVOP_SIZE) {
+        av_packet_from_data(out, s->b_frame_buf, s->b_frame_buf_size);
+        if (in->size <= MAX_NVOP_SIZE) {
             /* N-VOP */
-            av_log(avctx, AV_LOG_DEBUG, "Skipping N-VOP.\n");
-            ctx->b_frame_buf      = NULL;
-            ctx->b_frame_buf_size = 0;
+            av_log(ctx, AV_LOG_DEBUG, "Skipping N-VOP.\n");
+            s->b_frame_buf      = NULL;
+            s->b_frame_buf_size = 0;
         } else {
             /* copy packet into BSFContext */
-            ctx->b_frame_buf_size = buf_size;
-            ctx->b_frame_buf      = create_new_buffer(buf , buf_size);
-            if (!ctx->b_frame_buf) {
-                ctx->b_frame_buf_size = 0;
-                av_freep(poutbuf);
-                *poutbuf_size = 0;
+            s->b_frame_buf_size = in->size;
+            s->b_frame_buf      = create_new_buffer(in->data, in->size);
+            if (!s->b_frame_buf) {
+                s->b_frame_buf_size = 0;
+                av_packet_unref(out);
+                av_packet_free(&in);
                 return AVERROR(ENOMEM);
             }
         }
     } else if (nb_vop >= 2) {
         /* use first frame of the packet */
-        *poutbuf      = (uint8_t *) buf;
-        *poutbuf_size = pos_vop2;
+        av_packet_move_ref(out, in);
+        out->size = pos_vop2;
     } else if (pos_p >= 0) {
-        av_log(avctx, AV_LOG_DEBUG, "Updating DivX userdata (remove trailing 'p').\n");
-        *poutbuf_size = buf_size;
-        *poutbuf      = create_new_buffer(buf, buf_size);
-        if (!*poutbuf) {
-            *poutbuf_size = 0;
-            return AVERROR(ENOMEM);
-        }
+        av_log(ctx, AV_LOG_DEBUG, "Updating DivX userdata (remove trailing 'p').\n");
+        av_packet_move_ref(out, in);
         /* remove 'p' (packed) from the end of the (DivX) userdata string */
-        (*poutbuf)[pos_p] = '\0';
-        /* the output buffer is distinct from the input buffer */
-        ret = 1;
+        out->data[pos_p] = '\0';
     } else {
         /* copy packet */
-        *poutbuf      = (uint8_t *) buf;
-        *poutbuf_size = buf_size;
+        av_packet_move_ref(out, in);
+    }
+
+    av_packet_free(&in);
+
+    return 0;
+}
+
+static int mpeg4_unpack_bframes_init(AVBSFContext *ctx)
+{
+    if (ctx->par_in->extradata) {
+        int pos_p_ext = -1;
+        scan_buffer(ctx->par_in->extradata, ctx->par_in->extradata_size, &pos_p_ext, NULL, NULL);
+        if (pos_p_ext >= 0) {
+            av_log(ctx, AV_LOG_DEBUG,
+                   "Updating DivX userdata (remove trailing 'p') in extradata.\n");
+            ctx->par_out->extradata[pos_p_ext] = '\0';
+        }
     }
 
-    return ret;
+    return 0;
 }
 
-static void mpeg4_unpack_bframes_close(AVBitStreamFilterContext *bsfc)
+static void mpeg4_unpack_bframes_close(AVBSFContext *bsfc)
 {
     UnpackBFramesBSFContext *ctx = bsfc->priv_data;
     av_freep(&ctx->b_frame_buf);
 }
 
-AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf = {
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_MPEG4, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf = {
     .name           = "mpeg4_unpack_bframes",
     .priv_data_size = sizeof(UnpackBFramesBSFContext),
+    .init           = mpeg4_unpack_bframes_init,
     .filter         = mpeg4_unpack_bframes_filter,
-    .close          = mpeg4_unpack_bframes_close
+    .close          = mpeg4_unpack_bframes_close,
+    .codec_ids      = codec_ids,
 };
diff --git a/libavcodec/mpeg4data.h b/libavcodec/mpeg4data.h
index 1ac5840..b7c3fab 100644
--- a/libavcodec/mpeg4data.h
+++ b/libavcodec/mpeg4data.h
@@ -1,6 +1,6 @@
 /*
  * copyright (c) 2000,2001 Fabrice Bellard
- * H263+ support
+ * H.263+ support
  * copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
  * This file is part of FFmpeg.
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * mpeg4 tables.
+ * MPEG-4 tables.
  */
 
 #ifndef AVCODEC_MPEG4DATA_H
@@ -31,7 +31,7 @@
 #include <stdint.h>
 #include "mpegvideo.h"
 
-/* dc encoding for mpeg4 */
+/* dc encoding for MPEG-4 */
 const uint8_t ff_mpeg4_DCtab_lum[13][2] =
 {
     {3,3}, {3,2}, {2,2}, {2,3}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7},
diff --git a/libavcodec/mpeg4video.c b/libavcodec/mpeg4video.c
index d7c6fe7..2aaa9f7 100644
--- a/libavcodec/mpeg4video.c
+++ b/libavcodec/mpeg4video.c
@@ -1,5 +1,5 @@
 /*
- * MPEG4 decoder / encoder common code.
+ * MPEG-4 decoder / encoder common code
  * Copyright (c) 2000,2001 Fabrice Bellard
  * Copyright (c) 2002-2010 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -57,7 +57,7 @@ void ff_mpeg4_clean_buffers(MpegEncContext *s)
     memset(s->ac_val[2] + c_xy, 0, (c_wrap     + 1) * 16 * sizeof(int16_t));
 
     /* clean MV */
-    // we can't clear the MVs as they might be needed by a b frame
+    // we can't clear the MVs as they might be needed by a B-frame
     s->last_mv[0][0][0] =
     s->last_mv[0][0][1] =
     s->last_mv[1][0][0] =
@@ -67,7 +67,7 @@ void ff_mpeg4_clean_buffers(MpegEncContext *s)
 #define tab_size ((signed)FF_ARRAY_ELEMS(s->direct_scale_mv[0]))
 #define tab_bias (tab_size / 2)
 
-// used by mpeg4 and rv10 decoder
+// used by MPEG-4 and rv10 decoder
 void ff_mpeg4_init_direct_mv(MpegEncContext *s)
 {
     int i;
diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h
index 5998c71..515b008 100644
--- a/libavcodec/mpeg4video.h
+++ b/libavcodec/mpeg4video.h
@@ -1,5 +1,5 @@
 /*
- * MPEG4 encoder/decoder internal header.
+ * MPEG-4 encoder/decoder internal header.
  * Copyright (c) 2000,2001 Fabrice Bellard
  * Copyright (c) 2002-2010 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -107,7 +107,7 @@ typedef struct Mpeg4DecContext {
     int cplx_estimation_trash_b;
 } Mpeg4DecContext;
 
-/* dc encoding for mpeg4 */
+/* dc encoding for MPEG-4 */
 extern const uint8_t ff_mpeg4_DCtab_lum[13][2];
 extern const uint8_t ff_mpeg4_DCtab_chrom[13][2];
 
@@ -158,7 +158,6 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx);
 int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size);
 
 /**
- *
  * @return the mb_type
  */
 int ff_mpeg4_set_direct_mv(MpegEncContext *s, int mx, int my);
diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c
index aa5e87a..b7d6da1 100644
--- a/libavcodec/mpeg4video_parser.c
+++ b/libavcodec/mpeg4video_parser.c
@@ -1,5 +1,5 @@
 /*
- * MPEG4 Video frame extraction
+ * MPEG-4 video frame extraction
  * Copyright (c) 2003 Fabrice Bellard
  * Copyright (c) 2003 Michael Niedermayer
  *
diff --git a/libavcodec/mpeg4video_parser.h b/libavcodec/mpeg4video_parser.h
index 50f8b44..8008e69 100644
--- a/libavcodec/mpeg4video_parser.h
+++ b/libavcodec/mpeg4video_parser.h
@@ -1,5 +1,5 @@
 /*
- * MPEG4 video parser prototypes
+ * MPEG-4 video parser prototypes
  * Copyright (c) 2003 Fabrice Bellard
  * Copyright (c) 2003 Michael Niedermayer
  *
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 527cbe9..3adf28d 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -1,5 +1,5 @@
 /*
- * MPEG4 decoder.
+ * MPEG-4 decoder
  * Copyright (c) 2000,2001 Fabrice Bellard
  * Copyright (c) 2002-2010 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -196,13 +196,13 @@ static int mpeg4_decode_sprite_trajectory(Mpeg4DecContext *ctx, GetBitContext *g
             x = get_xbits(gb, length);
 
         if (!(ctx->divx_version == 500 && ctx->divx_build == 413))
-            check_marker(gb, "before sprite_trajectory");
+            check_marker(s->avctx, gb, "before sprite_trajectory");
 
         length = get_vlc2(gb, sprite_trajectory.table, SPRITE_TRAJ_VLC_BITS, 3);
         if (length > 0)
             y = get_xbits(gb, length);
 
-        check_marker(gb, "after sprite_trajectory");
+        check_marker(s->avctx, gb, "after sprite_trajectory");
         ctx->sprite_traj[i][0] = d[i][0] = x;
         ctx->sprite_traj[i][1] = d[i][1] = y;
     }
@@ -212,7 +212,7 @@ static int mpeg4_decode_sprite_trajectory(Mpeg4DecContext *ctx, GetBitContext *g
     while ((1 << alpha) < w)
         alpha++;
     while ((1 << beta) < h)
-        beta++;  /* typo in the mpeg4 std for the definition of w' and h' */
+        beta++;  /* typo in the MPEG-4 std for the definition of w' and h' */
     w2 = 1 << alpha;
     h2 = 1 << beta;
 
@@ -235,7 +235,7 @@ static int mpeg4_decode_sprite_trajectory(Mpeg4DecContext *ctx, GetBitContext *g
     /* sprite_ref[3][0] = (a >> 1) * (2 * vop_ref[3][0] + d[0][0] + d[1][0] + d[2][0] + d[3][0]);
      * sprite_ref[3][1] = (a >> 1) * (2 * vop_ref[3][1] + d[0][1] + d[1][1] + d[2][1] + d[3][1]); */
 
-    /* this is mostly identical to the mpeg4 std (and is totally unreadable
+    /* This is mostly identical to the MPEG-4 std (and is totally unreadable
      * because of that...). Perhaps it should be reordered to be more readable.
      * The idea behind this virtual_ref mess is to be able to use shifts later
      * per pixel instead of divides so the distance between points is converted
@@ -381,12 +381,13 @@ static int mpeg4_decode_sprite_trajectory(Mpeg4DecContext *ctx, GetBitContext *g
 }
 
 static int decode_new_pred(Mpeg4DecContext *ctx, GetBitContext *gb) {
+    MpegEncContext *s = &ctx->m;
     int len = FFMIN(ctx->time_increment_bits + 3, 15);
 
     get_bits(gb, len);
     if (get_bits1(gb))
         get_bits(gb, len);
-    check_marker(gb, "after new_pred");
+    check_marker(s->avctx, gb, "after new_pred");
 
     return 0;
 }
@@ -445,9 +446,9 @@ int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx)
         while (get_bits1(&s->gb) != 0)
             time_incr++;
 
-        check_marker(&s->gb, "before time_increment in video packed header");
+        check_marker(s->avctx, &s->gb, "before time_increment in video packed header");
         skip_bits(&s->gb, ctx->time_increment_bits);      /* time_increment */
-        check_marker(&s->gb, "before vop_coding_type in video packed header");
+        check_marker(s->avctx, &s->gb, "before vop_coding_type in video packed header");
 
         skip_bits(&s->gb, 2); /* vop coding type */
         // FIXME not rect stuff here
@@ -1459,7 +1460,7 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64])
             ff_thread_await_progress(&s->next_picture_ptr->tf, s->mb_y, 0);
         }
 
-        /* if we skipped it in the future P Frame than skip it now too */
+        /* if we skipped it in the future P-frame than skip it now too */
         s->mb_skipped = s->next_picture.mbskip_table[s->mb_y * s->mb_stride + s->mb_x];  // Note, skiptab=0 if last was GMC
 
         if (s->mb_skipped) {
@@ -1685,7 +1686,7 @@ static int mpeg4_decode_gop_header(MpegEncContext *s, GetBitContext *gb)
 
     hours   = get_bits(gb, 5);
     minutes = get_bits(gb, 6);
-    check_marker(gb, "in gop_header");
+    check_marker(s->avctx, gb, "in gop_header");
     seconds = get_bits(gb, 6);
 
     s->time_base = seconds + 60*(minutes + 60*hours);
@@ -1740,22 +1741,30 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
         s->low_delay = get_bits1(gb);
         if (get_bits1(gb)) {    /* vbv parameters */
             get_bits(gb, 15);   /* first_half_bitrate */
-            check_marker(gb, "after first_half_bitrate");
+            check_marker(s->avctx, gb, "after first_half_bitrate");
             get_bits(gb, 15);   /* latter_half_bitrate */
-            check_marker(gb, "after latter_half_bitrate");
+            check_marker(s->avctx, gb, "after latter_half_bitrate");
             get_bits(gb, 15);   /* first_half_vbv_buffer_size */
-            check_marker(gb, "after first_half_vbv_buffer_size");
+            check_marker(s->avctx, gb, "after first_half_vbv_buffer_size");
             get_bits(gb, 3);    /* latter_half_vbv_buffer_size */
             get_bits(gb, 11);   /* first_half_vbv_occupancy */
-            check_marker(gb, "after first_half_vbv_occupancy");
+            check_marker(s->avctx, gb, "after first_half_vbv_occupancy");
             get_bits(gb, 15);   /* latter_half_vbv_occupancy */
-            check_marker(gb, "after latter_half_vbv_occupancy");
+            check_marker(s->avctx, gb, "after latter_half_vbv_occupancy");
         }
     } else {
         /* is setting low delay flag only once the smartest thing to do?
-         * low delay detection won't be overridden. */
-        if (s->picture_number == 0)
-            s->low_delay = 0;
+         * low delay detection will not be overridden. */
+        if (s->picture_number == 0) {
+            switch(s->vo_type) {
+            case SIMPLE_VO_TYPE:
+            case ADV_SIMPLE_VO_TYPE:
+                s->low_delay = 1;
+                break;
+            default:
+                s->low_delay = 0;
+            }
+        }
     }
 
     ctx->shape = get_bits(gb, 2); /* vol shape */
@@ -1766,7 +1775,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
         skip_bits(gb, 4);  /* video_object_layer_shape_extension */
     }
 
-    check_marker(gb, "before time_increment_resolution");
+    check_marker(s->avctx, gb, "before time_increment_resolution");
 
     s->avctx->framerate.num = get_bits(gb, 16);
     if (!s->avctx->framerate.num) {
@@ -1778,7 +1787,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
     if (ctx->time_increment_bits < 1)
         ctx->time_increment_bits = 1;
 
-    check_marker(gb, "before fixed_vop_rate");
+    check_marker(s->avctx, gb, "before fixed_vop_rate");
 
     if (get_bits1(gb) != 0)     /* fixed_vop_rate  */
         s->avctx->framerate.den = get_bits(gb, ctx->time_increment_bits);
@@ -1791,11 +1800,11 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
 
     if (ctx->shape != BIN_ONLY_SHAPE) {
         if (ctx->shape == RECT_SHAPE) {
-            check_marker(gb, "before width");
+            check_marker(s->avctx, gb, "before width");
             width = get_bits(gb, 13);
-            check_marker(gb, "before height");
+            check_marker(s->avctx, gb, "before height");
             height = get_bits(gb, 13);
-            check_marker(gb, "after height");
+            check_marker(s->avctx, gb, "after height");
             if (width && height &&  /* they should be non zero but who knows */
                 !(s->width && s->codec_tag == AV_RL32("MP4S"))) {
                 if (s->width && s->height &&
@@ -1811,7 +1820,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
         s->interlaced_dct        = 0;
         if (!get_bits1(gb) && (s->avctx->debug & FF_DEBUG_PICT_INFO))
             av_log(s->avctx, AV_LOG_INFO,           /* OBMC Disable */
-                   "MPEG4 OBMC not supported (very likely buggy encoder)\n");
+                   "MPEG-4 OBMC not supported (very likely buggy encoder)\n");
         if (vo_ver_id == 1)
             ctx->vol_sprite_usage = get_bits1(gb);    /* vol_sprite_usage */
         else
@@ -1823,13 +1832,13 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
             ctx->vol_sprite_usage == GMC_SPRITE) {
             if (ctx->vol_sprite_usage == STATIC_SPRITE) {
                 skip_bits(gb, 13); // sprite_width
-                check_marker(gb, "after sprite_width");
+                check_marker(s->avctx, gb, "after sprite_width");
                 skip_bits(gb, 13); // sprite_height
-                check_marker(gb, "after sprite_height");
+                check_marker(s->avctx, gb, "after sprite_height");
                 skip_bits(gb, 13); // sprite_left
-                check_marker(gb, "after sprite_left");
+                check_marker(s->avctx, gb, "after sprite_left");
                 skip_bits(gb, 13); // sprite_top
-                check_marker(gb, "after sprite_top");
+                check_marker(s->avctx, gb, "after sprite_top");
             }
             ctx->num_sprite_warping_points = get_bits(gb, 6);
             if (ctx->num_sprite_warping_points > 3) {
@@ -1954,7 +1963,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
                     ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* intra_cae */
                     ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* inter_cae */
                     ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* no_update */
-                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* upampling */
+                    ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* upsampling */
                 }
                 if (!get_bits1(gb)) {
                     ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* intra_blocks */
@@ -1962,7 +1971,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
                     ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* inter4v_blocks */
                     ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* not coded blocks */
                 }
-                if (!check_marker(gb, "in complexity estimation part 1")) {
+                if (!check_marker(s->avctx, gb, "in complexity estimation part 1")) {
                     skip_bits_long(gb, pos - get_bits_count(gb));
                     goto no_cplx_est;
                 }
@@ -1980,7 +1989,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb)
                     ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* halfpel2 */
                     ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* halfpel4 */
                 }
-                if (!check_marker(gb, "in complexity estimation part 2")) {
+                if (!check_marker(s->avctx, gb, "in complexity estimation part 2")) {
                     skip_bits_long(gb, pos - get_bits_count(gb));
                     goto no_cplx_est;
                 }
@@ -2052,11 +2061,12 @@ no_cplx_est:
     }
 
     if (s->avctx->debug&FF_DEBUG_PICT_INFO) {
-        av_log(s->avctx, AV_LOG_DEBUG, "tb %d/%d, tincrbits:%d, qp_prec:%d, ps:%d,  %s%s%s%s\n",
+        av_log(s->avctx, AV_LOG_DEBUG, "tb %d/%d, tincrbits:%d, qp_prec:%d, ps:%d, low_delay:%d  %s%s%s%s\n",
                s->avctx->framerate.den, s->avctx->framerate.num,
                ctx->time_increment_bits,
                s->quant_precision,
                s->progressive_sequence,
+               s->low_delay,
                ctx->scalability ? "scalability " :"" , s->quarter_sample ? "qpel " : "",
                s->data_partitioning ? "partition " : "", ctx->rvlc ? "rvlc " : ""
         );
@@ -2253,7 +2263,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
     while (get_bits1(gb) != 0)
         time_incr++;
 
-    check_marker(gb, "before time_increment");
+    check_marker(s->avctx, gb, "before time_increment");
 
     if (ctx->time_increment_bits == 0 ||
         !(show_bits(gb, ctx->time_increment_bits + 1) & 1)) {
@@ -2305,7 +2315,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
         if (s->pp_time <= s->pb_time ||
             s->pp_time <= s->pp_time - s->pb_time ||
             s->pp_time <= 0) {
-            /* messed up order, maybe after seeking? skipping current b-frame */
+            /* messed up order, maybe after seeking? skipping current B-frame */
             return FRAME_SKIPPED;
         }
         ff_mpeg4_init_direct_mv(s);
@@ -2332,7 +2342,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
         pts = AV_NOPTS_VALUE;
     ff_dlog(s->avctx, "MPEG4 PTS: %"PRId64"\n", pts);
 
-    check_marker(gb, "before vop_coded");
+    check_marker(s->avctx, gb, "before vop_coded");
 
     /* vop coded */
     if (get_bits1(gb) != 1) {
@@ -2357,11 +2367,11 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
     if (ctx->shape != RECT_SHAPE) {
         if (ctx->vol_sprite_usage != 1 || s->pict_type != AV_PICTURE_TYPE_I) {
             skip_bits(gb, 13);  /* width */
-            check_marker(gb, "after width");
+            check_marker(s->avctx, gb, "after width");
             skip_bits(gb, 13);  /* height */
-            check_marker(gb, "after height");
+            check_marker(s->avctx, gb, "after height");
             skip_bits(gb, 13);  /* hor_spat_ref */
-            check_marker(gb, "after hor_spat_ref");
+            check_marker(s->avctx, gb, "after hor_spat_ref");
             skip_bits(gb, 13);  /* ver_spat_ref */
         }
         skip_bits1(gb);         /* change_CR_disable */
@@ -2419,7 +2429,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
         s->chroma_qscale = s->qscale = get_bits(gb, s->quant_precision);
         if (s->qscale == 0) {
             av_log(s->avctx, AV_LOG_ERROR,
-                   "Error, header damaged or not MPEG4 header (qscale=0)\n");
+                   "Error, header damaged or not MPEG-4 header (qscale=0)\n");
             return AVERROR_INVALIDDATA;  // makes no sense to continue, as there is nothing left from the image then
         }
 
@@ -2427,7 +2437,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
             s->f_code = get_bits(gb, 3);        /* fcode_for */
             if (s->f_code == 0) {
                 av_log(s->avctx, AV_LOG_ERROR,
-                       "Error, header damaged or not MPEG4 header (f_code=0)\n");
+                       "Error, header damaged or not MPEG-4 header (f_code=0)\n");
                 s->f_code = 1;
                 return AVERROR_INVALIDDATA;  // makes no sense to continue, as there is nothing left from the image then
             }
@@ -2477,7 +2487,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
         }
     }
     /* detect buggy encoders which don't set the low_delay flag
-     * (divx4/xvid/opendivx). Note we cannot detect divx5 without b-frames
+     * (divx4/xvid/opendivx). Note we cannot detect divx5 without B-frames
      * easily (although it's buggy too) */
     if (s->vo_type == 0 && ctx->vol_control_parameters == 0 &&
         ctx->divx_version == -1 && s->picture_number == 0) {
@@ -2500,7 +2510,7 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb)
 }
 
 /**
- * Decode mpeg4 headers.
+ * Decode MPEG-4 headers.
  * @return <0 if no VOP found (or a damaged one)
  *         FRAME_SKIPPED if a not coded VOP is found
  *         0 if a VOP is found
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index 1ba9238..3149310 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -1,5 +1,5 @@
 /*
- * MPEG4 encoder.
+ * MPEG-4 encoder
  * Copyright (c) 2000,2001 Fabrice Bellard
  * Copyright (c) 2002-2010 Michael Niedermayer <michaelni at gmx.at>
  *
@@ -29,7 +29,7 @@
 #include "mpeg4video.h"
 
 /* The uni_DCtab_* tables below contain unified bits+length tables to encode DC
- * differences in mpeg4. Unified in the sense that the specification specifies
+ * differences in MPEG-4. Unified in the sense that the specification specifies
  * this encoding in several steps. */
 static uint8_t  uni_DCtab_lum_len[512];
 static uint8_t  uni_DCtab_chrom_len[512];
@@ -47,7 +47,7 @@ static uint8_t  uni_mpeg4_inter_rl_len[64 * 64 * 2 * 2];
 //#define UNI_MPEG4_ENC_INDEX(last, run, level) ((last) * 128 * 64 + (run) + (level) * 64)
 #define UNI_MPEG4_ENC_INDEX(last, run, level) ((last) * 128 * 64 + (run) * 128 + (level))
 
-/* mpeg4
+/* MPEG-4
  * inter
  * max level: 24/6
  * max run: 53/63
@@ -120,7 +120,7 @@ static inline void restore_ac_coeffs(MpegEncContext *s, int16_t block[6][64],
 }
 
 /**
- * Return the optimal value (0 or 1) for the ac_pred element for the given MB in mpeg4.
+ * Return the optimal value (0 or 1) for the ac_pred element for the given MB in MPEG-4.
  * This function will also update s->block_last_index and s->ac_val.
  * @param[in,out] block MB coefficients, these will be updated if 1 is returned
  * @param[in] dir ac prediction direction for each 8x8 block
@@ -208,7 +208,7 @@ static inline int decide_ac_pred(MpegEncContext *s, int16_t block[6][64],
 }
 
 /**
- * modify mb_type & qscale so that encoding is actually possible in mpeg4
+ * modify mb_type & qscale so that encoding is actually possible in MPEG-4
  */
 void ff_clean_mpeg4_qscales(MpegEncContext *s)
 {
@@ -220,7 +220,7 @@ void ff_clean_mpeg4_qscales(MpegEncContext *s)
     if (s->pict_type == AV_PICTURE_TYPE_B) {
         int odd = 0;
         /* ok, come on, this isn't funny anymore, there's more code for
-         * handling this mpeg4 mess than for the actual adaptive quantization */
+         * handling this MPEG-4 mess than for the actual adaptive quantization */
 
         for (i = 0; i < s->mb_num; i++) {
             int mb_xy = s->mb_index2xy[i];
@@ -318,7 +318,7 @@ static inline void mpeg4_encode_block(MpegEncContext *s,
     const int last_index = s->block_last_index[n];
 
     if (s->mb_intra) {  // Note gcc (3.2.1 at least) will optimize this away
-        /* mpeg4 based DC predictor */
+        /* MPEG-4 based DC predictor */
         mpeg4_encode_dc(dc_pb, intra_dc, n);
         if (last_index < 1)
             return;
@@ -378,7 +378,7 @@ static int mpeg4_get_block_length(MpegEncContext *s,
     int len = 0;
 
     if (s->mb_intra) {  // Note gcc (3.2.1 at least) will optimize this away
-        /* mpeg4 based DC predictor */
+        /* MPEG-4 based DC predictor */
         len += mpeg4_get_dc_length(intra_dc, n);
         if (last_index < 1)
             return len;
@@ -529,7 +529,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64],
             av_assert2((s->dquant & 1) == 0);
             av_assert2(mb_type >= 0);
 
-            /* nothing to do if this MB was skipped in the next P Frame */
+            /* nothing to do if this MB was skipped in the next P-frame */
             if (s->next_picture.mbskip_table[s->mb_y * s->mb_stride + s->mb_x]) {  // FIXME avoid DCT & ...
                 s->skip_count++;
                 s->mv[0][0][0] =
@@ -659,7 +659,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64],
 
             if ((cbp | motion_x | motion_y | s->dquant) == 0 &&
                 s->mv_type == MV_TYPE_16X16) {
-                /* check if the B frames can skip it too, as we must skip it
+                /* Check if the B-frames can skip it too, as we must skip it
                  * if we skip here why didn't they just compress
                  * the skip-mb bits instead of reusing them ?! */
                 if (s->max_b_frames > 0) {
@@ -886,7 +886,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64],
 }
 
 /**
- * add mpeg4 stuffing bits (01...1)
+ * add MPEG-4 stuffing bits (01...1)
  */
 void ff_mpeg4_stuffing(PutBitContext *pbc)
 {
@@ -1054,7 +1054,7 @@ static void mpeg4_encode_vol_header(MpegEncContext *s,
         put_bits(&s->pb, 2, 0);       /* sprite enable */
 
     put_bits(&s->pb, 1, 0);             /* not 8 bit == false */
-    put_bits(&s->pb, 1, s->mpeg_quant); /* quant type= (0=h263 style)*/
+    put_bits(&s->pb, 1, s->mpeg_quant); /* quant type = (0 = H.263 style) */
 
     if (s->mpeg_quant) {
         ff_write_quant_matrix(&s->pb, s->avctx->intra_matrix);
@@ -1085,7 +1085,7 @@ static void mpeg4_encode_vol_header(MpegEncContext *s,
     }
 }
 
-/* write mpeg4 VOP header */
+/* write MPEG-4 VOP header */
 int ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number)
 {
     uint64_t time_incr;
diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c
index 5e3fe7e..1114428 100644
--- a/libavcodec/mpegaudiodec_template.c
+++ b/libavcodec/mpegaudiodec_template.c
@@ -71,6 +71,7 @@ typedef struct MPADecodeContext {
     MPA_DECODE_HEADER
     uint8_t last_buf[LAST_BUF_SIZE];
     int last_buf_size;
+    int extrasize;
     /* next header (used in free format parsing) */
     uint32_t free_format_next_header;
     GetBitContext gb;
@@ -819,9 +820,10 @@ static void exponents_from_scale_factors(MPADecodeContext *s, GranuleDef *g,
 static void switch_buffer(MPADecodeContext *s, int *pos, int *end_pos,
                           int *end_pos2)
 {
-    if (s->in_gb.buffer && *pos >= s->gb.size_in_bits) {
+    if (s->in_gb.buffer && *pos >= s->gb.size_in_bits - s->extrasize * 8) {
         s->gb           = s->in_gb;
         s->in_gb.buffer = NULL;
+        s->extrasize    = 0;
         av_assert2((get_bits_count(&s->gb) & 7) == 0);
         skip_bits_long(&s->gb, *pos - *end_pos);
         *end_pos2 =
@@ -830,7 +832,7 @@ static void switch_buffer(MPADecodeContext *s, int *pos, int *end_pos,
     }
 }
 
-/* Following is a optimized code for
+/* Following is an optimized code for
             INTFLOAT v = *src
             if(get_bits1(&s->gb))
                 v = -v;
@@ -853,7 +855,7 @@ static int huffman_decode(MPADecodeContext *s, GranuleDef *g,
     int i;
     int last_pos, bits_left;
     VLC *vlc;
-    int end_pos = FFMIN(end_pos2, s->gb.size_in_bits);
+    int end_pos = FFMIN(end_pos2, s->gb.size_in_bits - s->extrasize * 8);
 
     /* low frequencies (called big values) */
     s_index = 0;
@@ -1387,18 +1389,16 @@ static int mp_decode_layer3(MPADecodeContext *s)
     if (!s->adu_mode) {
         int skip;
         const uint8_t *ptr = s->gb.buffer + (get_bits_count(&s->gb)>>3);
-        int extrasize = av_clip(get_bits_left(&s->gb) >> 3, 0, EXTRABYTES);
+        s->extrasize = av_clip((get_bits_left(&s->gb) >> 3) - s->extrasize, 0,
+                               FFMAX(0, LAST_BUF_SIZE - s->last_buf_size));
         av_assert1((get_bits_count(&s->gb) & 7) == 0);
         /* now we get bits from the main_data_begin offset */
         ff_dlog(s->avctx, "seekback:%d, lastbuf:%d\n",
                 main_data_begin, s->last_buf_size);
 
-        memcpy(s->last_buf + s->last_buf_size, ptr, extrasize);
+        memcpy(s->last_buf + s->last_buf_size, ptr, s->extrasize);
         s->in_gb = s->gb;
-        init_get_bits(&s->gb, s->last_buf, s->last_buf_size*8);
-#if !UNCHECKED_BITSTREAM_READER
-        s->gb.size_in_bits_plus8 += FFMAX(extrasize, LAST_BUF_SIZE - s->last_buf_size) * 8;
-#endif
+        init_get_bits(&s->gb, s->last_buf, (s->last_buf_size + s->extrasize) * 8);
         s->last_buf_size <<= 3;
         for (gr = 0; gr < nb_granules && (s->last_buf_size >> 3) < main_data_begin; gr++) {
             for (ch = 0; ch < s->nb_channels; ch++) {
@@ -1409,15 +1409,17 @@ static int mp_decode_layer3(MPADecodeContext *s)
             }
         }
         skip = s->last_buf_size - 8 * main_data_begin;
-        if (skip >= s->gb.size_in_bits && s->in_gb.buffer) {
-            skip_bits_long(&s->in_gb, skip - s->gb.size_in_bits);
+        if (skip >= s->gb.size_in_bits - s->extrasize * 8 && s->in_gb.buffer) {
+            skip_bits_long(&s->in_gb, skip - s->gb.size_in_bits + s->extrasize * 8);
             s->gb           = s->in_gb;
             s->in_gb.buffer = NULL;
+            s->extrasize    = 0;
         } else {
             skip_bits_long(&s->gb, skip);
         }
     } else {
         gr = 0;
+        s->extrasize = 0;
     }
 
     for (; gr < nb_granules; gr++) {
@@ -1429,7 +1431,7 @@ static int mp_decode_layer3(MPADecodeContext *s)
                 uint8_t *sc;
                 int slen, slen1, slen2;
 
-                /* MPEG1 scale factors */
+                /* MPEG-1 scale factors */
                 slen1 = slen_table[0][g->scalefac_compress];
                 slen2 = slen_table[1][g->scalefac_compress];
                 ff_dlog(s->avctx, "slen1=%d slen2=%d\n", slen1, slen2);
@@ -1582,7 +1584,7 @@ static int mp_decode_frame(MPADecodeContext *s, OUT_INT **samples,
         s->last_buf_size=0;
         if (s->in_gb.buffer) {
             align_get_bits(&s->gb);
-            i = get_bits_left(&s->gb)>>3;
+            i = (get_bits_left(&s->gb) >> 3) - s->extrasize;
             if (i >= 0 && i <= BACKSTEP_SIZE) {
                 memmove(s->last_buf, s->gb.buffer + (get_bits_count(&s->gb)>>3), i);
                 s->last_buf_size=i;
@@ -1590,12 +1592,12 @@ static int mp_decode_frame(MPADecodeContext *s, OUT_INT **samples,
                 av_log(s->avctx, AV_LOG_ERROR, "invalid old backstep %d\n", i);
             s->gb           = s->in_gb;
             s->in_gb.buffer = NULL;
+            s->extrasize    = 0;
         }
 
         align_get_bits(&s->gb);
         av_assert1((get_bits_count(&s->gb) & 7) == 0);
-        i = get_bits_left(&s->gb) >> 3;
-
+        i = (get_bits_left(&s->gb) >> 3) - s->extrasize;
         if (i < 0 || i > BACKSTEP_SIZE || nb_frames < 0) {
             if (i < 0)
                 av_log(s->avctx, AV_LOG_ERROR, "invalid new backstep %d\n", i);
diff --git a/libavcodec/mpegaudiodecheader.h b/libavcodec/mpegaudiodecheader.h
index 55d5a15..952ba17 100644
--- a/libavcodec/mpegaudiodecheader.h
+++ b/libavcodec/mpegaudiodecheader.h
@@ -52,7 +52,7 @@ typedef struct MPADecodeHeader {
    that the frame size must be computed externally */
 int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header);
 
-/* useful helper to get mpeg audio stream infos. Return -1 if error in
+/* useful helper to get MPEG audio stream info. Return -1 if error in
    header, otherwise the coded frame size in bytes */
 int ff_mpa_decode_header(uint32_t head, int *sample_rate,
                          int *channels, int *frame_size, int *bitrate, enum AVCodecID *codec_id);
diff --git a/libavcodec/mpegaudioenc_template.c b/libavcodec/mpegaudioenc_template.c
index b91d0a8..93363fe 100644
--- a/libavcodec/mpegaudioenc_template.c
+++ b/libavcodec/mpegaudioenc_template.c
@@ -599,7 +599,7 @@ static void compute_bit_allocation(MpegAudioContext *s,
 }
 
 /*
- * Output the mpeg audio layer 2 frame. Note how the code is small
+ * Output the MPEG audio layer 2 frame. Note how the code is small
  * compared to other encoders :-)
  */
 static void encode_frame(MpegAudioContext *s,
@@ -614,7 +614,7 @@ static void encode_frame(MpegAudioContext *s,
     /* header */
 
     put_bits(p, 12, 0xfff);
-    put_bits(p, 1, 1 - s->lsf); /* 1 = mpeg1 ID, 0 = mpeg2 lsf ID */
+    put_bits(p, 1, 1 - s->lsf); /* 1 = MPEG-1 ID, 0 = MPEG-2 lsf ID */
     put_bits(p, 2, 4-2);  /* layer 2 */
     put_bits(p, 1, 1); /* no error protection */
     put_bits(p, 4, s->bitrate_index);
diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c
index 16b8f52..6748fc2 100644
--- a/libavcodec/mpegpicture.c
+++ b/libavcodec/mpegpicture.c
@@ -71,8 +71,8 @@ int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me,
     }
 
     // edge emu needs blocksize + filter length - 1
-    // (= 17x17 for  halfpel / 21x21 for  h264)
-    // VC1 computes luma and chroma simultaneously and needs 19X19 + 9x9
+    // (= 17x17 for  halfpel / 21x21 for H.264)
+    // VC-1 computes luma and chroma simultaneously and needs 19X19 + 9x9
     // at uvlinesize. It supports only YUV420 so 24x24 is enough
     // linesize * interlaced * MBsize
     // we also use this buffer for encoding in encode_mb_internal() needig an additional 32 lines
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 236987b..eb14b8c 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -59,7 +59,7 @@ static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s,
     nCoeffs= s->block_last_index[n];
 
     block[0] *= n < 4 ? s->y_dc_scale : s->c_dc_scale;
-    /* XXX: only mpeg1 */
+    /* XXX: only MPEG-1 */
     quant_matrix = s->intra_matrix;
     for(i=1;i<=nCoeffs;i++) {
         int j= s->intra_scantable.permutated[i];
@@ -567,7 +567,7 @@ do {\
     s->workaround_bugs      = s1->workaround_bugs;
     s->padding_bug_score    = s1->padding_bug_score;
 
-    // MPEG4 timing info
+    // MPEG-4 timing info
     memcpy(&s->last_time_base, &s1->last_time_base,
            (char *) &s1->pb_field_time + sizeof(s1->pb_field_time) -
            (char *) &s1->last_time_base);
@@ -598,7 +598,7 @@ do {\
                AV_INPUT_BUFFER_PADDING_SIZE);
     }
 
-    // linesize dependend scratch buffer allocation
+    // linesize-dependent scratch buffer allocation
     if (!s->sc.edge_emu_buffer)
         if (s1->linesize) {
             if (ff_mpeg_framesize_alloc(s->avctx, &s->me,
@@ -612,7 +612,7 @@ do {\
                    "be allocated due to unknown size.\n");
         }
 
-    // MPEG2/interlacing info
+    // MPEG-2/interlacing info
     memcpy(&s->progressive_sequence, &s1->progressive_sequence,
            (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence);
 
@@ -705,7 +705,8 @@ static int init_context_frame(MpegEncContext *s)
     if (s->mb_height & 1)
         yc_size += 2*s->b8_stride + 2*s->mb_stride;
 
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int), fail); // error ressilience code looks cleaner with this
+    FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int),
+                      fail); // error resilience code looks cleaner with this
     for (y = 0; y < s->mb_height; y++)
         for (x = 0; x < s->mb_width; x++)
             s->mb_index2xy[x + y * s->mb_width] = x + y * s->mb_stride;
@@ -772,7 +773,7 @@ static int init_context_frame(MpegEncContext *s)
 
     if (s->h263_pred || s->h263_plus || !s->encoding) {
         /* dc values */
-        // MN: we need these for  error resilience of intra-frames
+        // MN: we need these for error resilience of intra-frames
         FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base, yc_size * sizeof(int16_t), fail);
         s->dc_val[0] = s->dc_val_base + s->b8_stride + 1;
         s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1;
@@ -781,13 +782,13 @@ static int init_context_frame(MpegEncContext *s)
             s->dc_val_base[i] = 1024;
     }
 
-    /* which mb is a intra block */
+    /* which mb is an intra block */
     FF_ALLOCZ_OR_GOTO(s->avctx, s->mbintra_table, mb_array_size, fail);
     memset(s->mbintra_table, 1, mb_array_size);
 
     /* init macroblock skip table */
     FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size + 2, fail);
-    // Note the + 1 is for  a quicker mpeg4 slice_end detection
+    // Note the + 1 is for a quicker MPEG-4 slice_end detection
 
     return ff_mpeg_er_init(s);
 fail:
@@ -822,9 +823,7 @@ static void clear_context(MpegEncContext *s)
     s->sc.b_scratchpad =
     s->sc.obmc_scratchpad = NULL;
 
-    s->parse_context.buffer = NULL;
-    s->parse_context.buffer_size = 0;
-    s->parse_context.overread = 0;
+
     s->bitstream_buffer = NULL;
     s->allocated_bitstream_buffer_size = 0;
     s->picture          = NULL;
@@ -1206,7 +1205,7 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     }
 
     /* release forgotten pictures */
-    /* if (mpeg124/h263) */
+    /* if (MPEG-124 / H.263) */
     for (i = 0; i < MAX_PICTURE_COUNT; i++) {
         if (&s->picture[i] != s->last_picture_ptr &&
             &s->picture[i] != s->next_picture_ptr &&
@@ -1216,6 +1215,8 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     }
 
     ff_mpeg_unref_picture(s->avctx, &s->current_picture);
+    ff_mpeg_unref_picture(s->avctx, &s->last_picture);
+    ff_mpeg_unref_picture(s->avctx, &s->next_picture);
 
     /* release non reference frames */
     for (i = 0; i < MAX_PICTURE_COUNT; i++) {
@@ -1224,7 +1225,7 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     }
 
     if (s->current_picture_ptr && !s->current_picture_ptr->f->buf[0]) {
-        // we already have a unused image
+        // we already have an unused image
         // (maybe it was set before reading the header)
         pic = s->current_picture_ptr;
     } else {
@@ -1367,14 +1368,12 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     memset(s->next_picture.f->data, 0, sizeof(s->next_picture.f->data));
 #endif
     if (s->last_picture_ptr) {
-        ff_mpeg_unref_picture(s->avctx, &s->last_picture);
         if (s->last_picture_ptr->f->buf[0] &&
             (ret = ff_mpeg_ref_picture(s->avctx, &s->last_picture,
                                        s->last_picture_ptr)) < 0)
             return ret;
     }
     if (s->next_picture_ptr) {
-        ff_mpeg_unref_picture(s->avctx, &s->next_picture);
         if (s->next_picture_ptr->f->buf[0] &&
             (ret = ff_mpeg_ref_picture(s->avctx, &s->next_picture,
                                        s->next_picture_ptr)) < 0)
@@ -1398,8 +1397,8 @@ int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     }
 
     /* set dequantizer, we can't do it during init as
-     * it might change for mpeg4 and we can't do it in the header
-     * decode as init is not called for mpeg4 there yet */
+     * it might change for MPEG-4 and we can't do it in the header
+     * decode as init is not called for MPEG-4 there yet */
     if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
         s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra;
         s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter;
@@ -1759,7 +1758,8 @@ void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_
         const int mv_stride      = (mb_width << mv_sample_log2) +
                                    (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1);
 
-        *low_delay = 0; // needed to see the vectors without trashing the buffers
+        if (low_delay)
+            *low_delay = 0; // needed to see the vectors without trashing the buffers
 
         avcodec_get_chroma_sub_sample(avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift);
 
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index df5e4bf..a1f3d4b 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -81,16 +81,16 @@ typedef struct MpegEncContext {
     int y_dc_scale, c_dc_scale;
     int ac_pred;
     int block_last_index[12];  ///< last non zero coefficient in block
-    int h263_aic;              ///< Advanded INTRA Coding (AIC)
+    int h263_aic;              ///< Advanced INTRA Coding (AIC)
 
     /* scantables */
-    ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce tha cache usage
+    ScanTable inter_scantable; ///< if inter == intra then intra should be used to reduce the cache usage
     ScanTable intra_scantable;
     ScanTable intra_h_scantable;
     ScanTable intra_v_scantable;
 
     /* WARNING: changes above this line require updates to hardcoded
-     *          offsets used in asm. */
+     *          offsets used in ASM. */
 
     struct AVCodecContext *avctx;
     /* the following parameters must be initialized before encoding */
@@ -99,20 +99,20 @@ typedef struct MpegEncContext {
     int intra_only;   ///< if true, only intra pictures are generated
     int64_t bit_rate; ///< wanted bit rate
     enum OutputFormat out_format; ///< output format
-    int h263_pred;    ///< use mpeg4/h263 ac/dc predictions
-    int pb_frame;     ///< PB frame mode (0 = none, 1 = base, 2 = improved)
+    int h263_pred;    ///< use MPEG-4/H.263 ac/dc predictions
+    int pb_frame;     ///< PB-frame mode (0 = none, 1 = base, 2 = improved)
 
 /* the following codec id fields are deprecated in favor of codec_id */
-    int h263_plus;    ///< h263 plus headers
-    int h263_flv;     ///< use flv h263 header
+    int h263_plus;    ///< H.263+ headers
+    int h263_flv;     ///< use flv H.263 header
 
     enum AVCodecID codec_id;     /* see AV_CODEC_ID_xxx */
     int fixed_qscale; ///< fixed qscale if non zero
     int encoding;     ///< true if we are encoding (vs decoding)
-    int max_b_frames; ///< max number of b-frames for encoding
+    int max_b_frames; ///< max number of B-frames for encoding
     int luma_elim_threshold;
     int chroma_elim_threshold;
-    int strict_std_compliance; ///< strictly follow the std (MPEG4, ...)
+    int strict_std_compliance; ///< strictly follow the std (MPEG-4, ...)
     int workaround_bugs;       ///< workaround bugs in encoders which cannot be detected automatically
     int codec_tag;             ///< internal codec_tag upper case converted from avctx codec_tag
     /* the following fields are managed internally by the encoder */
@@ -132,7 +132,7 @@ typedef struct MpegEncContext {
     ptrdiff_t uvlinesize;      ///< line size, for chroma in bytes, may be different from width
     Picture *picture;          ///< main picture buffer
     Picture **input_picture;   ///< next pictures on display order for encoding
-    Picture **reordered_input_picture; ///< pointer to the next pictures in codedorder for encoding
+    Picture **reordered_input_picture; ///< pointer to the next pictures in coded order for encoding
 
     int64_t user_specified_pts; ///< last non-zero pts from AVFrame which was passed into avcodec_encode_video2()
     /**
@@ -179,19 +179,19 @@ typedef struct MpegEncContext {
     Picture *last_picture_ptr;     ///< pointer to the previous picture.
     Picture *next_picture_ptr;     ///< pointer to the next picture (for bidir pred)
     Picture *current_picture_ptr;  ///< pointer to the current picture
-    int last_dc[3];                ///< last DC values for MPEG1
+    int last_dc[3];                ///< last DC values for MPEG-1
     int16_t *dc_val_base;
-    int16_t *dc_val[3];            ///< used for mpeg4 DC prediction, all 3 arrays must be continuous
+    int16_t *dc_val[3];            ///< used for MPEG-4 DC prediction, all 3 arrays must be continuous
     const uint8_t *y_dc_scale_table;     ///< qscale -> y_dc_scale table
     const uint8_t *c_dc_scale_table;     ///< qscale -> c_dc_scale table
-    const uint8_t *chroma_qscale_table;  ///< qscale -> chroma_qscale (h263)
+    const uint8_t *chroma_qscale_table;  ///< qscale -> chroma_qscale (H.263)
     uint8_t *coded_block_base;
     uint8_t *coded_block;          ///< used for coded block pattern prediction (msmpeg4v3, wmv1)
     int16_t (*ac_val_base)[16];
-    int16_t (*ac_val[3])[16];      ///< used for mpeg4 AC prediction, all 3 arrays must be continuous
+    int16_t (*ac_val[3])[16];      ///< used for MPEG-4 AC prediction, all 3 arrays must be continuous
     int mb_skipped;                ///< MUST BE SET only during DECODING
     uint8_t *mbskip_table;        /**< used to avoid copy if macroblock skipped (for black regions for example)
-                                   and used for b-frame encoding & decoding (contains skip table of next P Frame) */
+                                   and used for B-frame encoding & decoding (contains skip table of next P-frame) */
     uint8_t *mbintra_table;       ///< used to avoid setting {ac, dc, cbp}-pred stuff to zero on inter MB decoding
     uint8_t *cbp_table;           ///< used to store cbp, ac_pred for partitioned decoding
     uint8_t *pred_dir_table;      ///< used to store pred_dir for partitioned decoding
@@ -200,7 +200,7 @@ typedef struct MpegEncContext {
 
     int qscale;                 ///< QP
     int chroma_qscale;          ///< chroma QP
-    unsigned int lambda;        ///< lagrange multipler used in rate distortion
+    unsigned int lambda;        ///< Lagrange multiplier used in rate distortion
     unsigned int lambda2;       ///< (lambda*lambda) >> FF_LAMBDA_SHIFT
     int *lambda_table;
     int adaptive_quant;         ///< use adaptive quantization
@@ -209,7 +209,7 @@ typedef struct MpegEncContext {
     int pict_type;              ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ...
     int vbv_delay;
     int last_pict_type; //FIXME removes
-    int last_non_b_pict_type;   ///< used for mpeg4 gmc b-frames & ratecontrol
+    int last_non_b_pict_type;   ///< used for MPEG-4 gmc B-frames & ratecontrol
     int droppable;
     int frame_rate_index;
     AVRational mpeg2_frame_rate_ext;
@@ -218,7 +218,7 @@ typedef struct MpegEncContext {
 
     /* motion compensation */
     int unrestricted_mv;        ///< mv can point outside of the coded picture
-    int h263_long_vectors;      ///< use horrible h263v1 long vector mode
+    int h263_long_vectors;      ///< use horrible H.263v1 long vector mode
 
     BlockDSPContext bdsp;
     FDCTDSPContext fdsp;
@@ -233,7 +233,7 @@ typedef struct MpegEncContext {
     VideoDSPContext vdsp;
     H263DSPContext h263dsp;
     int f_code;                 ///< forward MV resolution
-    int b_code;                 ///< backward MV resolution for B Frames (mpeg4)
+    int b_code;                 ///< backward MV resolution for B-frames (MPEG-4)
     int16_t (*p_mv_table_base)[2];
     int16_t (*b_forw_mv_table_base)[2];
     int16_t (*b_back_mv_table_base)[2];
@@ -242,14 +242,14 @@ typedef struct MpegEncContext {
     int16_t (*b_direct_mv_table_base)[2];
     int16_t (*p_field_mv_table_base[2][2])[2];
     int16_t (*b_field_mv_table_base[2][2][2])[2];
-    int16_t (*p_mv_table)[2];            ///< MV table (1MV per MB) p-frame encoding
-    int16_t (*b_forw_mv_table)[2];       ///< MV table (1MV per MB) forward mode b-frame encoding
-    int16_t (*b_back_mv_table)[2];       ///< MV table (1MV per MB) backward mode b-frame encoding
-    int16_t (*b_bidir_forw_mv_table)[2]; ///< MV table (1MV per MB) bidir mode b-frame encoding
-    int16_t (*b_bidir_back_mv_table)[2]; ///< MV table (1MV per MB) bidir mode b-frame encoding
-    int16_t (*b_direct_mv_table)[2];     ///< MV table (1MV per MB) direct mode b-frame encoding
-    int16_t (*p_field_mv_table[2][2])[2];   ///< MV table (2MV per MB) interlaced p-frame encoding
-    int16_t (*b_field_mv_table[2][2][2])[2];///< MV table (4MV per MB) interlaced b-frame encoding
+    int16_t (*p_mv_table)[2];            ///< MV table (1MV per MB) P-frame encoding
+    int16_t (*b_forw_mv_table)[2];       ///< MV table (1MV per MB) forward mode B-frame encoding
+    int16_t (*b_back_mv_table)[2];       ///< MV table (1MV per MB) backward mode B-frame encoding
+    int16_t (*b_bidir_forw_mv_table)[2]; ///< MV table (1MV per MB) bidir mode B-frame encoding
+    int16_t (*b_bidir_back_mv_table)[2]; ///< MV table (1MV per MB) bidir mode B-frame encoding
+    int16_t (*b_direct_mv_table)[2];     ///< MV table (1MV per MB) direct mode B-frame encoding
+    int16_t (*p_field_mv_table[2][2])[2];   ///< MV table (2MV per MB) interlaced P-frame encoding
+    int16_t (*b_field_mv_table[2][2][2])[2];///< MV table (4MV per MB) interlaced B-frame encoding
     uint8_t (*p_field_select_table[2]);
     uint8_t (*b_field_select_table[2][2]);
 #if FF_API_MOTION_EST
@@ -261,10 +261,10 @@ typedef struct MpegEncContext {
     int mv_dir;
 #define MV_DIR_FORWARD   1
 #define MV_DIR_BACKWARD  2
-#define MV_DIRECT        4 ///< bidirectional mode where the difference equals the MV of the last P/S/I-Frame (mpeg4)
+#define MV_DIRECT        4 ///< bidirectional mode where the difference equals the MV of the last P/S/I-Frame (MPEG-4)
     int mv_type;
 #define MV_TYPE_16X16       0   ///< 1 vector for the whole mb
-#define MV_TYPE_8X8         1   ///< 4 vectors (h263, mpeg4 4MV)
+#define MV_TYPE_8X8         1   ///< 4 vectors (H.263, MPEG-4 4MV)
 #define MV_TYPE_16X8        2   ///< 2 vectors, one per 16x8 block
 #define MV_TYPE_FIELD       3   ///< 2 vectors, one per field
 #define MV_TYPE_DMV         4   ///< 2 vectors, special mpeg2 Dual Prime Vectors
@@ -275,14 +275,14 @@ typedef struct MpegEncContext {
     */
     int mv[2][4][2];
     int field_select[2][2];
-    int last_mv[2][2][2];             ///< last MV, used for MV prediction in MPEG1 & B-frame MPEG4
+    int last_mv[2][2][2];             ///< last MV, used for MV prediction in MPEG-1 & B-frame MPEG-4
     uint8_t *fcode_tab;               ///< smallest fcode needed for each MV
     int16_t direct_scale_mv[2][64];   ///< precomputed to avoid divisions in ff_mpeg4_set_direct_mv
 
     MotionEstContext me;
 
-    int no_rounding;  /**< apply no rounding to motion compensation (MPEG4, msmpeg4, ...)
-                        for b-frames rounding mode is always 0 */
+    int no_rounding;  /**< apply no rounding to motion compensation (MPEG-4, msmpeg4, ...)
+                        for B-frames rounding mode is always 0 */
 
     /* macroblock layer */
     int mb_x, mb_y;
@@ -357,7 +357,7 @@ typedef struct MpegEncContext {
     int resync_mb_y;                 ///< y position of last resync marker
     GetBitContext last_resync_gb;    ///< used to search for the next resync marker
     int mb_num_left;                 ///< number of MBs left in this video packet (for partitioned Slices only)
-    int next_p_frame_damaged;        ///< set if the next p frame is damaged, to avoid showing trashed b frames
+    int next_p_frame_damaged;        ///< set if the next p frame is damaged, to avoid showing trashed B-frames
 
     ParseContext parse_context;
 
@@ -372,7 +372,7 @@ typedef struct MpegEncContext {
     int rc_strategy;
 
     /* H.263+ specific */
-    int umvplus;                    ///< == H263+ && unrestricted_mv
+    int umvplus;                    ///< == H.263+ && unrestricted_mv
     int h263_aic_dir;               ///< AIC direction: 0 = left, 1 = top
     int h263_slice_structured;
     int alt_inter_vlc;              ///< alternative inter vlc
@@ -380,7 +380,7 @@ typedef struct MpegEncContext {
     int loop_filter;
     int custom_pcf;
 
-    /* mpeg4 specific */
+    /* MPEG-4 specific */
     ///< number of bits to represent the fractional part of time (encoder only)
     int time_increment_bits;
     int last_time_base;
@@ -401,12 +401,12 @@ typedef struct MpegEncContext {
     int sprite_warping_accuracy;
     int data_partitioning;           ///< data partitioning flag from header
     int partitioned_frame;           ///< is current frame partitioned
-    int low_delay;                   ///< no reordering needed / has no b-frames
+    int low_delay;                   ///< no reordering needed / has no B-frames
     int vo_type;
     PutBitContext tex_pb;            ///< used for data partitioned VOPs
     PutBitContext pb2;               ///< used for data partitioned VOPs
     int mpeg_quant;
-    int padding_bug_score;             ///< used to detect the VERY common padding bug in MPEG4
+    int padding_bug_score;             ///< used to detect the VERY common padding bug in MPEG-4
 
     /* divx specific, used to workaround (many) bugs in divx5 */
     int divx_packed;
@@ -430,7 +430,7 @@ typedef struct MpegEncContext {
     int dc_table_index;
     int use_skip_mb_code;
     int slice_height;      ///< in macroblocks
-    int first_slice_line;  ///< used in mpeg4 too to handle resync markers
+    int first_slice_line;  ///< used in MPEG-4 too to handle resync markers
     int flipflop_rounding;
     int msmpeg4_version;   ///< 0=not msmpeg4, 1=mp41, 2=mp42, 3=mp43/divx3 4=wmv1/7 5=wmv2/8
     int per_mb_rl_table;
@@ -444,9 +444,9 @@ typedef struct MpegEncContext {
     /* decompression specific */
     GetBitContext gb;
 
-    /* Mpeg1 specific */
-    int gop_picture_number;  ///< index of the first picture of a GOP based on fake_pic_num & mpeg1 specific
-    int last_mv_dir;         ///< last mv_dir, used for b frame encoding
+    /* MPEG-1 specific */
+    int gop_picture_number;  ///< index of the first picture of a GOP based on fake_pic_num & MPEG-1 specific
+    int last_mv_dir;         ///< last mv_dir, used for B-frame encoding
     uint8_t *vbv_delay_ptr;  ///< pointer to vbv_delay in the bitstream
 
     /* MPEG-2-specific - I wished not to have to support this mess. */
@@ -514,9 +514,9 @@ typedef struct MpegEncContext {
                            int16_t *block/*align 16*/, int n, int qscale);
     void (*dct_unquantize_h263_inter)(struct MpegEncContext *s,
                            int16_t *block/*align 16*/, int n, int qscale);
-    void (*dct_unquantize_intra)(struct MpegEncContext *s, // unquantizer to use (mpeg4 can use both)
+    void (*dct_unquantize_intra)(struct MpegEncContext *s, // unquantizer to use (MPEG-4 can use both)
                            int16_t *block/*align 16*/, int n, int qscale);
-    void (*dct_unquantize_inter)(struct MpegEncContext *s, // unquantizer to use (mpeg4 can use both)
+    void (*dct_unquantize_inter)(struct MpegEncContext *s, // unquantizer to use (MPEG-4 can use both)
                            int16_t *block/*align 16*/, int n, int qscale);
     int (*dct_quantize)(struct MpegEncContext *s, int16_t *block/*align 16*/, int n, int qscale, int *overflow);
     int (*fast_dct_quantize)(struct MpegEncContext *s, int16_t *block/*align 16*/, int n, int qscale, int *overflow);
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 297ff78..87d7954 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -538,7 +538,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
         s->codec_id != AV_CODEC_ID_MPEG4      &&
         s->codec_id != AV_CODEC_ID_MPEG1VIDEO &&
         s->codec_id != AV_CODEC_ID_MPEG2VIDEO) {
-        av_log(avctx, AV_LOG_ERROR, "b frames not supported by codec\n");
+        av_log(avctx, AV_LOG_ERROR, "B-frames not supported by codec\n");
         return -1;
     }
     if (s->max_b_frames < 0) {
@@ -664,7 +664,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
         }
         if (s->max_b_frames != 0) {
             av_log(avctx, AV_LOG_ERROR,
-                   "b frames cannot be used with low delay\n");
+                   "B-frames cannot be used with low delay\n");
             return -1;
         }
     }
@@ -1005,7 +1005,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
             s->intra_matrix[j] =
             s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i];
         } else {
-            /* mpeg1/2 */
+            /* MPEG-1/2 */
             s->chroma_intra_matrix[j] =
             s->intra_matrix[j] = ff_mpeg1_default_intra_matrix[i];
             s->inter_matrix[j] = ff_mpeg1_default_non_intra_matrix[i];
@@ -1327,7 +1327,7 @@ static int load_input_picture(MpegEncContext *s, const AVFrame *pic_arg)
             return ret;
 
         pic->f->display_picture_number = display_picture_number;
-        pic->f->pts = pts; // we set this here to avoid modifiying pic_arg
+        pic->f->pts = pts; // we set this here to avoid modifying pic_arg
     } else {
         /* Flushing: When we have not received enough input frames,
          * ensure s->input_picture[0] contains the first picture */
@@ -1518,8 +1518,7 @@ static int estimate_best_b_count(MpegEncContext *s)
         }
     }
 
-    avcodec_close(c);
-    av_freep(&c);
+    avcodec_free_context(&c);
 
     return best_b_count;
 }
@@ -1538,7 +1537,7 @@ static int select_input_picture(MpegEncContext *s)
             if (s->picture_in_gop_number < s->gop_size &&
                 s->next_picture_ptr &&
                 skip_check(s, s->input_picture[0], s->next_picture_ptr)) {
-                // FIXME check that te gop check above is +-1 correct
+                // FIXME check that the gop check above is +-1 correct
                 av_frame_unref(s->input_picture[0]->f);
 
                 ff_vbv_update(s, 0);
@@ -1614,7 +1613,7 @@ static int select_input_picture(MpegEncContext *s)
             if (s->input_picture[b_frames]->f->pict_type == AV_PICTURE_TYPE_B &&
                 b_frames == s->max_b_frames) {
                 av_log(s->avctx, AV_LOG_ERROR,
-                       "warning, too many b frames in a row\n");
+                       "warning, too many B-frames in a row\n");
             }
 
             if (s->picture_in_gop_number + b_frames >= s->gop_size) {
@@ -1658,7 +1657,7 @@ no_output_pic:
             return ret;
 
         if (s->reordered_input_picture[0]->shared || s->avctx->rc_buffer_size) {
-            // input is a shared pix, so we can't modifiy it -> alloc a new
+            // input is a shared pix, so we can't modify it -> allocate a new
             // one & ensure that the shared one is reuseable
 
             Picture *pic;
@@ -2009,7 +2008,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
             s->frame_bits  = put_bits_count(&s->pb);
         }
 
-        /* update mpeg1/2 vbv_delay for CBR */
+        /* update MPEG-1/2 vbv_delay for CBR */
         if (s->avctx->rc_max_rate                          &&
             s->avctx->rc_min_rate == s->avctx->rc_max_rate &&
             s->out_format == FMT_MPEG1                     &&
@@ -2607,7 +2606,7 @@ static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext
 
     memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop?
 
-    /* mpeg1 */
+    /* MPEG-1 */
     d->mb_skip_run= s->mb_skip_run;
     for(i=0; i<3; i++)
         d->last_dc[i] = s->last_dc[i];
@@ -2636,7 +2635,7 @@ static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext *
     memcpy(d->mv, s->mv, 2*4*2*sizeof(int));
     memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop?
 
-    /* mpeg1 */
+    /* MPEG-1 */
     d->mb_skip_run= s->mb_skip_run;
     for(i=0; i<3; i++)
         d->last_dc[i] = s->last_dc[i];
@@ -2932,7 +2931,7 @@ int ff_mpv_reallocate_putbitbuffer(MpegEncContext *s, size_t threshold, size_t s
 
 static int encode_thread(AVCodecContext *c, void *arg){
     MpegEncContext *s= *(void**)arg;
-    int mb_x, mb_y, pdif = 0;
+    int mb_x, mb_y;
     int chr_h= 16>>s->chroma_y_shift;
     int i, j;
     MpegEncContext best_s = { 0 }, backup_s;
@@ -3527,7 +3526,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
                 ff_mpv_decode_mb(s, s->block);
             }
 
-            /* clean the MV table in IPS frames for direct mode in B frames */
+            /* clean the MV table in IPS frames for direct mode in B-frames */
             if(s->mb_intra /* && I,P,S_TYPE */){
                 s->p_mv_table[xy][0]=0;
                 s->p_mv_table[xy][1]=0;
@@ -3570,7 +3569,7 @@ FF_DISABLE_DEPRECATION_WARNINGS
     /* Send the last GOB if RTP */
     if (s->avctx->rtp_callback) {
         int number_mb = (mb_y - s->resync_mb_y)*s->mb_width - s->resync_mb_x;
-        pdif = put_bits_ptr(&s->pb) - s->ptr_lastgob;
+        int pdif = put_bits_ptr(&s->pb) - s->ptr_lastgob;
         /* Call the RTP callback to send the last GOB */
         emms_c();
         s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, pdif, number_mb);
@@ -3683,7 +3682,7 @@ static int encode_picture(MpegEncContext *s, int picture_number)
     s->me.mb_var_sum_temp    =
     s->me.mc_mb_var_sum_temp = 0;
 
-    /* we need to initialize some time vars before we can encode b-frames */
+    /* we need to initialize some time vars before we can encode B-frames */
     // RAL: Condition added for MPEG1VIDEO
     if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || (s->h263_pred && !s->msmpeg4_version))
         set_frame_distances(s);
@@ -4121,7 +4120,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s,
             } else if(s->out_format == FMT_MJPEG) {
                 j = s->idsp.idct_permutation[scantable[i]];
                 unquant_coeff = alevel * matrix[j] * 8;
-            }else{ //MPEG1
+            }else{ // MPEG-1
                 j = s->idsp.idct_permutation[scantable[i]]; // FIXME: optimize
                 if(s->mb_intra){
                         unquant_coeff = (int)(  alevel  * mpeg2_qscale * matrix[j]) >> 4;
@@ -4191,7 +4190,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s,
 
         score_tab[i+1]= best_score;
 
-        //Note: there is a vlc code in mpeg4 which is 1 bit shorter then another one with a shorter run and the same level
+        // Note: there is a vlc code in MPEG-4 which is 1 bit shorter then another one with a shorter run and the same level
         if(last_non_zero <= 27){
             for(; survivor_count; survivor_count--){
                 if(score_tab[ survivor[survivor_count-1] ] <= best_score)
@@ -4211,7 +4210,8 @@ static int dct_quantize_trellis_c(MpegEncContext *s,
         last_score= 256*256*256*120;
         for(i= survivor[0]; i<=last_non_zero + 1; i++){
             int score= score_tab[i];
-            if(i) score += lambda*2; //FIXME exacter?
+            if (i)
+                score += lambda * 2; // FIXME more exact?
 
             if(score < last_score){
                 last_score= score;
@@ -4242,7 +4242,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s,
 
             if(s->out_format == FMT_H263 || s->out_format == FMT_H261){
                     unquant_coeff= (alevel*qmul + qadd)>>3;
-            }else{ //MPEG1
+            } else{ // MPEG-1
                     unquant_coeff = (((  alevel  << 1) + 1) * mpeg2_qscale * ((int) matrix[0])) >> 5;
                     unquant_coeff =   (unquant_coeff - 1) | 1;
             }
@@ -4370,7 +4370,7 @@ static int messed_sign=0;
 #endif
     dc += (1<<(RECON_SHIFT-1));
     for(i=0; i<64; i++){
-        rem[i]= dc - (orig[i]<<RECON_SHIFT); //FIXME  use orig dirrectly instead of copying to rem[]
+        rem[i] = dc - (orig[i] << RECON_SHIFT); // FIXME use orig directly instead of copying to rem[]
     }
 #ifdef REFINE_STATS
 STOP_TIMER("memset rem[]")}
@@ -4681,7 +4681,7 @@ STOP_TIMER("iterative search")
 }
 
 /**
- * Permute an 8x8 block according to permuatation.
+ * Permute an 8x8 block according to permutation.
  * @param block the block which will be permuted according to
  *              the given permutation vector
  * @param permutation the permutation vector
diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c
index 51ba435..c29810f 100644
--- a/libavcodec/mpegvideo_motion.c
+++ b/libavcodec/mpegvideo_motion.c
@@ -544,7 +544,7 @@ static inline void qpel_motion(MpegEncContext *s,
         s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr_y,
                                  s->linesize, s->linesize,
                                  17, 17 + field_based,
-                                 src_x, src_y << field_based,
+                                 src_x, src_y * (1 << field_based),
                                  s->h_edge_pos, s->v_edge_pos);
         ptr_y = s->sc.edge_emu_buffer;
         if (!CONFIG_GRAY || !(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
@@ -553,12 +553,12 @@ static inline void qpel_motion(MpegEncContext *s,
             s->vdsp.emulated_edge_mc(ubuf, ptr_cb,
                                      s->uvlinesize, s->uvlinesize,
                                      9, 9 + field_based,
-                                     uvsrc_x, uvsrc_y << field_based,
+                                     uvsrc_x, uvsrc_y * (1 << field_based),
                                      s->h_edge_pos >> 1, s->v_edge_pos >> 1);
             s->vdsp.emulated_edge_mc(vbuf, ptr_cr,
                                      s->uvlinesize, s->uvlinesize,
                                      9, 9 + field_based,
-                                     uvsrc_x, uvsrc_y << field_based,
+                                     uvsrc_x, uvsrc_y * (1 << field_based),
                                      s->h_edge_pos >> 1, s->v_edge_pos >> 1);
             ptr_cb = ubuf;
             ptr_cr = vbuf;
@@ -591,7 +591,7 @@ static inline void qpel_motion(MpegEncContext *s,
 }
 
 /**
- * h263 chroma 4mv motion compensation.
+ * H.263 chroma 4mv motion compensation.
  */
 static void chroma_4mv_motion(MpegEncContext *s,
                               uint8_t *dest_cb, uint8_t *dest_cr,
diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c
index 1f74bfb..206f268 100644
--- a/libavcodec/mpegvideo_parser.c
+++ b/libavcodec/mpegvideo_parser.c
@@ -1,5 +1,5 @@
 /*
- * MPEG1 / MPEG2 video parser
+ * MPEG-1 / MPEG-2 video parser
  * Copyright (c) 2000,2001 Fabrice Bellard
  * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
  *
diff --git a/libavcodec/mpl2dec.c b/libavcodec/mpl2dec.c
index ca95dc8..409e4b3 100644
--- a/libavcodec/mpl2dec.c
+++ b/libavcodec/mpl2dec.c
@@ -69,13 +69,11 @@ static int mpl2_decode_frame(AVCodecContext *avctx, void *data,
     AVBPrint buf;
     AVSubtitle *sub = data;
     const char *ptr = avpkt->data;
-    const int ts_start     = av_rescale_q(avpkt->pts,      avctx->time_base, (AVRational){1,100});
-    const int ts_duration  = avpkt->duration != -1 ?
-                             av_rescale_q(avpkt->duration, avctx->time_base, (AVRational){1,100}) : -1;
+    FFASSDecoderContext *s = avctx->priv_data;
 
     av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
     if (ptr && avpkt->size > 0 && *ptr && !mpl2_event_to_ass(&buf, ptr))
-        ret = ff_ass_add_rect_bprint(sub, &buf, ts_start, ts_duration);
+        ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL);
     av_bprint_finalize(&buf, NULL);
     if (ret < 0)
         return ret;
@@ -90,4 +88,6 @@ AVCodec ff_mpl2_decoder = {
     .id             = AV_CODEC_ID_MPL2,
     .decode         = mpl2_decode_frame,
     .init           = ff_ass_subtitle_header_default,
+    .flush          = ff_ass_decoder_flush,
+    .priv_data_size = sizeof(FFASSDecoderContext),
 };
diff --git a/libavcodec/mqc.h b/libavcodec/mqc.h
index 39104b1..8bf7223 100644
--- a/libavcodec/mqc.h
+++ b/libavcodec/mqc.h
@@ -66,7 +66,7 @@ int ff_mqc_flush_to(MqcState *mqc, uint8_t *dst, int *dst_len);
 /**
  * Initialize MQ-decoder.
  * @param mqc   MQ decoder state
- * @param bp    byte poiter
+ * @param bp    byte pointer
  * @param raw   raw mode
  * @param reset reset states
  */
@@ -76,7 +76,7 @@ void ff_mqc_initdec(MqcState *mqc, uint8_t *bp, int raw, int reset);
  * MQ decoder.
  * @param mqc       MQ decoder state
  * @param cxstate   Context
- * @return          Decision (0 ot 1)
+ * @return          Decision (0 to 1)
  */
 int ff_mqc_decode(MqcState *mqc, uint8_t *cxstate);
 
diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c
index c9a2108..920f50f 100644
--- a/libavcodec/msmpeg4.c
+++ b/libavcodec/msmpeg4.c
@@ -40,14 +40,14 @@
 #include "libavutil/imgutils.h"
 
 /*
- * You can also call this codec : MPEG4 with a twist !
+ * You can also call this codec: MPEG-4 with a twist!
  *
  * TODO:
  *        - (encoding) select best mv table (two choices)
  *        - (encoding) select best vlc/dc table
  */
 
-/* This table is practically identical to the one from h263
+/* This table is practically identical to the one from H.263
  * except that it is inverted. */
 static av_cold void init_h263_dc_for_msmpeg4(void)
 {
@@ -71,7 +71,7 @@ static av_cold void init_h263_dc_for_msmpeg4(void)
             else
                 l= level;
 
-            /* luminance h263 */
+            /* luminance H.263 */
             uni_code= ff_mpeg4_DCtab_lum[size][0];
             uni_len = ff_mpeg4_DCtab_lum[size][1];
             uni_code ^= (1<<uni_len)-1; //M$ does not like compatibility
@@ -87,7 +87,7 @@ static av_cold void init_h263_dc_for_msmpeg4(void)
             ff_v2_dc_lum_table[level + 256][0] = uni_code;
             ff_v2_dc_lum_table[level + 256][1] = uni_len;
 
-            /* chrominance h263 */
+            /* chrominance H.263 */
             uni_code= ff_mpeg4_DCtab_chrom[size][0];
             uni_len = ff_mpeg4_DCtab_chrom[size][1];
             uni_code ^= (1<<uni_len)-1; //M$ does not like compatibility
@@ -252,7 +252,7 @@ int ff_msmpeg4_pred_dc(MpegEncContext *s, int n,
         c = FASTDIV((c + (scale >> 1)), scale);
     }
 #endif
-    /* XXX: WARNING: they did not choose the same test as MPEG4. This
+    /* XXX: WARNING: they did not choose the same test as MPEG-4. This
        is very important ! */
     if(s->msmpeg4_version>3){
         if(s->inter_intra_pred){
diff --git a/libavcodec/msmpeg4data.c b/libavcodec/msmpeg4data.c
index 8eb07e9..b9c1d8e 100644
--- a/libavcodec/msmpeg4data.c
+++ b/libavcodec/msmpeg4data.c
@@ -41,1959 +41,1921 @@ VLC ff_msmp4_dc_chroma_vlc[2];
 
 /* intra picture macroblock coded block pattern */
 const uint16_t ff_msmp4_mb_i_table[64][2] = {
-{  0x1, 1 },{  0x17,  6 },{   0x9,  5 },{   0x5,  5 },
-{  0x6, 5 },{  0x47,  9 },{  0x20,  7 },{  0x10,  7 },
-{  0x2, 5 },{  0x7c,  9 },{  0x3a,  7 },{  0x1d,  7 },
-{  0x2, 6 },{  0xec,  9 },{  0x77,  8 },{   0x0,  8 },
-{  0x3, 5 },{  0xb7,  9 },{  0x2c,  7 },{  0x13,  7 },
-{  0x1, 6 },{ 0x168, 10 },{  0x46,  8 },{  0x3f,  8 },
-{ 0x1e, 6 },{ 0x712, 13 },{  0xb5,  9 },{  0x42,  8 },
-{ 0x22, 7 },{ 0x1c5, 11 },{ 0x11e, 10 },{  0x87,  9 },
-{  0x6, 4 },{   0x3,  9 },{  0x1e,  7 },{  0x1c,  6 },
-{ 0x12, 7 },{ 0x388, 12 },{  0x44,  9 },{  0x70,  9 },
-{ 0x1f, 6 },{ 0x23e, 11 },{  0x39,  8 },{  0x8e,  9 },
-{  0x1, 7 },{ 0x1c6, 11 },{  0xb6,  9 },{  0x45,  9 },
-{ 0x14, 6 },{ 0x23f, 11 },{  0x7d,  9 },{  0x18,  9 },
-{  0x7, 7 },{ 0x1c7, 11 },{  0x86,  9 },{  0x19,  9 },
-{ 0x15, 6 },{ 0x1db, 10 },{   0x2,  9 },{  0x46,  9 },
-{  0xd, 8 },{ 0x713, 13 },{ 0x1da, 10 },{ 0x169, 10 },
+    {  0x1, 1 }, {  0x17,  6 }, {   0x9,  5 }, {   0x5,  5 },
+    {  0x6, 5 }, {  0x47,  9 }, {  0x20,  7 }, {  0x10,  7 },
+    {  0x2, 5 }, {  0x7c,  9 }, {  0x3a,  7 }, {  0x1d,  7 },
+    {  0x2, 6 }, {  0xec,  9 }, {  0x77,  8 }, {   0x0,  8 },
+    {  0x3, 5 }, {  0xb7,  9 }, {  0x2c,  7 }, {  0x13,  7 },
+    {  0x1, 6 }, { 0x168, 10 }, {  0x46,  8 }, {  0x3f,  8 },
+    { 0x1e, 6 }, { 0x712, 13 }, {  0xb5,  9 }, {  0x42,  8 },
+    { 0x22, 7 }, { 0x1c5, 11 }, { 0x11e, 10 }, {  0x87,  9 },
+    {  0x6, 4 }, {   0x3,  9 }, {  0x1e,  7 }, {  0x1c,  6 },
+    { 0x12, 7 }, { 0x388, 12 }, {  0x44,  9 }, {  0x70,  9 },
+    { 0x1f, 6 }, { 0x23e, 11 }, {  0x39,  8 }, {  0x8e,  9 },
+    {  0x1, 7 }, { 0x1c6, 11 }, {  0xb6,  9 }, {  0x45,  9 },
+    { 0x14, 6 }, { 0x23f, 11 }, {  0x7d,  9 }, {  0x18,  9 },
+    {  0x7, 7 }, { 0x1c7, 11 }, {  0x86,  9 }, {  0x19,  9 },
+    { 0x15, 6 }, { 0x1db, 10 }, {   0x2,  9 }, {  0x46,  9 },
+    {  0xd, 8 }, { 0x713, 13 }, { 0x1da, 10 }, { 0x169, 10 },
 };
 
 /* non intra picture macroblock coded block pattern + mb type */
 const uint32_t ff_table_mb_non_intra[128][2] = {
-{   0x40,  7 },{   0x13c9, 13 },{   0x9fd, 12 },{   0x1fc, 15 },
-{  0x9fc, 12 },{    0xa83, 18 },{ 0x12d34, 17 },{  0x83bc, 16 },
-{  0x83a, 12 },{    0x7f8, 17 },{   0x3fd, 16 },{   0x3ff, 16 },
-{   0x79, 13 },{    0xa82, 18 },{  0x969d, 16 },{   0x2a4, 16 },
-{  0x978, 12 },{    0x543, 17 },{  0x41df, 15 },{   0x7f9, 17 },
-{ 0x12f3, 13 },{  0x25a6b, 18 },{ 0x25ef9, 18 },{   0x3fa, 16 },
-{ 0x20ee, 14 },{  0x969ab, 20 },{  0x969c, 16 },{ 0x25ef8, 18 },
-{ 0x12d2, 13 },{    0xa85, 18 },{  0x969e, 16 },{  0x4bc8, 15 },
-{   0x3d, 12 },{  0x12f7f, 17 },{   0x2a2, 16 },{  0x969f, 16 },
-{ 0x25ee, 14 },{ 0x12d355, 21 },{ 0x12f7d, 17 },{ 0x12f7e, 17 },
-{  0x9e5, 12 },{    0xa81, 18 },{ 0x4b4d4, 19 },{  0x83bd, 16 },
-{   0x78, 13 },{   0x969b, 16 },{   0x3fe, 16 },{   0x2a5, 16 },
-{   0x7e, 13 },{    0xa80, 18 },{   0x2a3, 16 },{   0x3fb, 16 },
-{ 0x1076, 13 },{    0xa84, 18 },{   0x153, 15 },{  0x4bc9, 15 },
-{   0x55, 13 },{ 0x12d354, 21 },{  0x4bde, 15 },{  0x25e5, 14 },
-{  0x25b, 10 },{   0x4b4c, 15 },{   0x96b, 12 },{   0x96a, 12 },
-{    0x1,  2 },{      0x0,  7 },{    0x26,  6 },{   0x12b,  9 },
-{    0x7,  3 },{    0x20f, 10 },{     0x4,  9 },{    0x28, 12 },
-{    0x6,  3 },{    0x20a, 10 },{   0x128,  9 },{    0x2b, 12 },
-{   0x11,  5 },{     0x1b, 11 },{   0x13a,  9 },{   0x4ff, 11 },
-{    0x3,  4 },{    0x277, 10 },{   0x106,  9 },{   0x839, 12 },
-{    0xb,  4 },{    0x27b, 10 },{   0x12c,  9 },{   0x4bf, 11 },
-{    0x9,  6 },{     0x35, 12 },{   0x27e, 10 },{  0x13c8, 13 },
-{    0x1,  6 },{    0x4aa, 11 },{   0x208, 10 },{    0x29, 12 },
-{    0x1,  4 },{    0x254, 10 },{   0x12e,  9 },{   0x838, 12 },
-{   0x24,  6 },{    0x4f3, 11 },{   0x276, 10 },{  0x12f6, 13 },
-{    0x1,  5 },{    0x27a, 10 },{   0x13e,  9 },{    0x3e, 12 },
-{    0x8,  6 },{    0x413, 11 },{     0xc, 10 },{   0x4be, 11 },
-{   0x14,  5 },{    0x412, 11 },{   0x253, 10 },{   0x97a, 12 },
-{   0x21,  6 },{    0x4ab, 11 },{   0x20b, 10 },{    0x34, 12 },
-{   0x15,  5 },{    0x278, 10 },{   0x252, 10 },{   0x968, 12 },
-{    0x5,  5 },{      0xb, 10 },{    0x9c,  8 },{     0xe, 10 },
+    {   0x40,  7 }, {   0x13c9, 13 }, {   0x9fd, 12 }, {   0x1fc, 15 },
+    {  0x9fc, 12 }, {    0xa83, 18 }, { 0x12d34, 17 }, {  0x83bc, 16 },
+    {  0x83a, 12 }, {    0x7f8, 17 }, {   0x3fd, 16 }, {   0x3ff, 16 },
+    {   0x79, 13 }, {    0xa82, 18 }, {  0x969d, 16 }, {   0x2a4, 16 },
+    {  0x978, 12 }, {    0x543, 17 }, {  0x41df, 15 }, {   0x7f9, 17 },
+    { 0x12f3, 13 }, {  0x25a6b, 18 }, { 0x25ef9, 18 }, {   0x3fa, 16 },
+    { 0x20ee, 14 }, {  0x969ab, 20 }, {  0x969c, 16 }, { 0x25ef8, 18 },
+    { 0x12d2, 13 }, {    0xa85, 18 }, {  0x969e, 16 }, {  0x4bc8, 15 },
+    {   0x3d, 12 }, {  0x12f7f, 17 }, {   0x2a2, 16 }, {  0x969f, 16 },
+    { 0x25ee, 14 }, { 0x12d355, 21 }, { 0x12f7d, 17 }, { 0x12f7e, 17 },
+    {  0x9e5, 12 }, {    0xa81, 18 }, { 0x4b4d4, 19 }, {  0x83bd, 16 },
+    {   0x78, 13 }, {   0x969b, 16 }, {   0x3fe, 16 }, {   0x2a5, 16 },
+    {   0x7e, 13 }, {    0xa80, 18 }, {   0x2a3, 16 }, {   0x3fb, 16 },
+    { 0x1076, 13 }, {    0xa84, 18 }, {   0x153, 15 }, {  0x4bc9, 15 },
+    {   0x55, 13 }, { 0x12d354, 21 }, {  0x4bde, 15 }, {  0x25e5, 14 },
+    {  0x25b, 10 }, {   0x4b4c, 15 }, {   0x96b, 12 }, {   0x96a, 12 },
+    {    0x1,  2 }, {      0x0,  7 }, {    0x26,  6 }, {   0x12b,  9 },
+    {    0x7,  3 }, {    0x20f, 10 }, {     0x4,  9 }, {    0x28, 12 },
+    {    0x6,  3 }, {    0x20a, 10 }, {   0x128,  9 }, {    0x2b, 12 },
+    {   0x11,  5 }, {     0x1b, 11 }, {   0x13a,  9 }, {   0x4ff, 11 },
+    {    0x3,  4 }, {    0x277, 10 }, {   0x106,  9 }, {   0x839, 12 },
+    {    0xb,  4 }, {    0x27b, 10 }, {   0x12c,  9 }, {   0x4bf, 11 },
+    {    0x9,  6 }, {     0x35, 12 }, {   0x27e, 10 }, {  0x13c8, 13 },
+    {    0x1,  6 }, {    0x4aa, 11 }, {   0x208, 10 }, {    0x29, 12 },
+    {    0x1,  4 }, {    0x254, 10 }, {   0x12e,  9 }, {   0x838, 12 },
+    {   0x24,  6 }, {    0x4f3, 11 }, {   0x276, 10 }, {  0x12f6, 13 },
+    {    0x1,  5 }, {    0x27a, 10 }, {   0x13e,  9 }, {    0x3e, 12 },
+    {    0x8,  6 }, {    0x413, 11 }, {     0xc, 10 }, {   0x4be, 11 },
+    {   0x14,  5 }, {    0x412, 11 }, {   0x253, 10 }, {   0x97a, 12 },
+    {   0x21,  6 }, {    0x4ab, 11 }, {   0x20b, 10 }, {    0x34, 12 },
+    {   0x15,  5 }, {    0x278, 10 }, {   0x252, 10 }, {   0x968, 12 },
+    {    0x5,  5 }, {      0xb, 10 }, {    0x9c,  8 }, {     0xe, 10 },
 };
 
 /* dc table 0 */
 
 const uint32_t ff_table0_dc_lum[120][2] = {
-{     0x1,  1 },{      0x1, 2 },{     0x1,  4 },{     0x1,  5 },
-{     0x5,  5 },{      0x7, 5 },{     0x8,  6 },{     0xc,  6 },
-{     0x0,  7 },{      0x2, 7 },{    0x12,  7 },{    0x1a,  7 },
-{     0x3,  8 },{      0x7, 8 },{    0x27,  8 },{    0x37,  8 },
-{     0x5,  9 },{     0x4c, 9 },{    0x6c,  9 },{    0x6d,  9 },
-{     0x8, 10 },{    0x19, 10 },{    0x9b, 10 },{    0x1b, 10 },
-{    0x9a, 10 },{    0x13, 11 },{    0x34, 11 },{    0x35, 11 },
-{    0x61, 12 },{    0x48, 13 },{    0xc4, 13 },{    0x4a, 13 },
-{    0xc6, 13 },{    0xc7, 13 },{    0x92, 14 },{   0x18b, 14 },
-{    0x93, 14 },{   0x183, 14 },{   0x182, 14 },{    0x96, 14 },
-{    0x97, 14 },{   0x180, 14 },{   0x314, 15 },{   0x315, 15 },
-{   0x605, 16 },{   0x604, 16 },{   0x606, 16 },{   0xc0e, 17 },
-{ 0x303cd, 23 },{ 0x303c9, 23 },{ 0x303c8, 23 },{ 0x303ca, 23 },
-{ 0x303cb, 23 },{ 0x303cc, 23 },{ 0x303ce, 23 },{ 0x303cf, 23 },
-{ 0x303d0, 23 },{ 0x303d1, 23 },{ 0x303d2, 23 },{ 0x303d3, 23 },
-{ 0x303d4, 23 },{ 0x303d5, 23 },{ 0x303d6, 23 },{ 0x303d7, 23 },
-{ 0x303d8, 23 },{ 0x303d9, 23 },{ 0x303da, 23 },{ 0x303db, 23 },
-{ 0x303dc, 23 },{ 0x303dd, 23 },{ 0x303de, 23 },{ 0x303df, 23 },
-{ 0x303e0, 23 },{ 0x303e1, 23 },{ 0x303e2, 23 },{ 0x303e3, 23 },
-{ 0x303e4, 23 },{ 0x303e5, 23 },{ 0x303e6, 23 },{ 0x303e7, 23 },
-{ 0x303e8, 23 },{ 0x303e9, 23 },{ 0x303ea, 23 },{ 0x303eb, 23 },
-{ 0x303ec, 23 },{ 0x303ed, 23 },{ 0x303ee, 23 },{ 0x303ef, 23 },
-{ 0x303f0, 23 },{ 0x303f1, 23 },{ 0x303f2, 23 },{ 0x303f3, 23 },
-{ 0x303f4, 23 },{ 0x303f5, 23 },{ 0x303f6, 23 },{ 0x303f7, 23 },
-{ 0x303f8, 23 },{ 0x303f9, 23 },{ 0x303fa, 23 },{ 0x303fb, 23 },
-{ 0x303fc, 23 },{ 0x303fd, 23 },{ 0x303fe, 23 },{ 0x303ff, 23 },
-{ 0x60780, 24 },{ 0x60781, 24 },{ 0x60782, 24 },{ 0x60783, 24 },
-{ 0x60784, 24 },{ 0x60785, 24 },{ 0x60786, 24 },{ 0x60787, 24 },
-{ 0x60788, 24 },{ 0x60789, 24 },{ 0x6078a, 24 },{ 0x6078b, 24 },
-{ 0x6078c, 24 },{ 0x6078d, 24 },{ 0x6078e, 24 },{ 0x6078f, 24 },
+    {     0x1,  1 }, {     0x1,  2 }, {     0x1,  4 }, {     0x1,  5 },
+    {     0x5,  5 }, {     0x7,  5 }, {     0x8,  6 }, {     0xc,  6 },
+    {     0x0,  7 }, {     0x2,  7 }, {    0x12,  7 }, {    0x1a,  7 },
+    {     0x3,  8 }, {     0x7,  8 }, {    0x27,  8 }, {    0x37,  8 },
+    {     0x5,  9 }, {    0x4c,  9 }, {    0x6c,  9 }, {    0x6d,  9 },
+    {     0x8, 10 }, {    0x19, 10 }, {    0x9b, 10 }, {    0x1b, 10 },
+    {    0x9a, 10 }, {    0x13, 11 }, {    0x34, 11 }, {    0x35, 11 },
+    {    0x61, 12 }, {    0x48, 13 }, {    0xc4, 13 }, {    0x4a, 13 },
+    {    0xc6, 13 }, {    0xc7, 13 }, {    0x92, 14 }, {   0x18b, 14 },
+    {    0x93, 14 }, {   0x183, 14 }, {   0x182, 14 }, {    0x96, 14 },
+    {    0x97, 14 }, {   0x180, 14 }, {   0x314, 15 }, {   0x315, 15 },
+    {   0x605, 16 }, {   0x604, 16 }, {   0x606, 16 }, {   0xc0e, 17 },
+    { 0x303cd, 23 }, { 0x303c9, 23 }, { 0x303c8, 23 }, { 0x303ca, 23 },
+    { 0x303cb, 23 }, { 0x303cc, 23 }, { 0x303ce, 23 }, { 0x303cf, 23 },
+    { 0x303d0, 23 }, { 0x303d1, 23 }, { 0x303d2, 23 }, { 0x303d3, 23 },
+    { 0x303d4, 23 }, { 0x303d5, 23 }, { 0x303d6, 23 }, { 0x303d7, 23 },
+    { 0x303d8, 23 }, { 0x303d9, 23 }, { 0x303da, 23 }, { 0x303db, 23 },
+    { 0x303dc, 23 }, { 0x303dd, 23 }, { 0x303de, 23 }, { 0x303df, 23 },
+    { 0x303e0, 23 }, { 0x303e1, 23 }, { 0x303e2, 23 }, { 0x303e3, 23 },
+    { 0x303e4, 23 }, { 0x303e5, 23 }, { 0x303e6, 23 }, { 0x303e7, 23 },
+    { 0x303e8, 23 }, { 0x303e9, 23 }, { 0x303ea, 23 }, { 0x303eb, 23 },
+    { 0x303ec, 23 }, { 0x303ed, 23 }, { 0x303ee, 23 }, { 0x303ef, 23 },
+    { 0x303f0, 23 }, { 0x303f1, 23 }, { 0x303f2, 23 }, { 0x303f3, 23 },
+    { 0x303f4, 23 }, { 0x303f5, 23 }, { 0x303f6, 23 }, { 0x303f7, 23 },
+    { 0x303f8, 23 }, { 0x303f9, 23 }, { 0x303fa, 23 }, { 0x303fb, 23 },
+    { 0x303fc, 23 }, { 0x303fd, 23 }, { 0x303fe, 23 }, { 0x303ff, 23 },
+    { 0x60780, 24 }, { 0x60781, 24 }, { 0x60782, 24 }, { 0x60783, 24 },
+    { 0x60784, 24 }, { 0x60785, 24 }, { 0x60786, 24 }, { 0x60787, 24 },
+    { 0x60788, 24 }, { 0x60789, 24 }, { 0x6078a, 24 }, { 0x6078b, 24 },
+    { 0x6078c, 24 }, { 0x6078d, 24 }, { 0x6078e, 24 }, { 0x6078f, 24 },
 };
 
 const uint32_t ff_table0_dc_chroma[120][2] = {
-{      0x0,  2 },{      0x1,  2 },{      0x5,  3 },{      0x9,  4 },
-{      0xd,  4 },{     0x11,  5 },{     0x1d,  5 },{     0x1f,  5 },
-{     0x21,  6 },{     0x31,  6 },{     0x38,  6 },{     0x33,  6 },
-{     0x39,  6 },{     0x3d,  6 },{     0x61,  7 },{     0x79,  7 },
-{     0x80,  8 },{     0xc8,  8 },{     0xca,  8 },{     0xf0,  8 },
-{     0x81,  8 },{     0xc0,  8 },{     0xc9,  8 },{    0x107,  9 },
-{    0x106,  9 },{    0x196,  9 },{    0x183,  9 },{    0x1e3,  9 },
-{    0x1e2,  9 },{    0x20a, 10 },{    0x20b, 10 },{    0x609, 11 },
-{    0x412, 11 },{    0x413, 11 },{    0x60b, 11 },{    0x411, 11 },
-{    0x60a, 11 },{    0x65f, 11 },{    0x410, 11 },{    0x65d, 11 },
-{    0x65e, 11 },{    0xcb8, 12 },{    0xc10, 12 },{    0xcb9, 12 },
-{   0x1823, 13 },{   0x3045, 14 },{   0x6089, 15 },{   0xc110, 16 },
-{ 0x304448, 22 },{ 0x304449, 22 },{ 0x30444a, 22 },{ 0x30444b, 22 },
-{ 0x30444c, 22 },{ 0x30444d, 22 },{ 0x30444e, 22 },{ 0x30444f, 22 },
-{ 0x304450, 22 },{ 0x304451, 22 },{ 0x304452, 22 },{ 0x304453, 22 },
-{ 0x304454, 22 },{ 0x304455, 22 },{ 0x304456, 22 },{ 0x304457, 22 },
-{ 0x304458, 22 },{ 0x304459, 22 },{ 0x30445a, 22 },{ 0x30445b, 22 },
-{ 0x30445c, 22 },{ 0x30445d, 22 },{ 0x30445e, 22 },{ 0x30445f, 22 },
-{ 0x304460, 22 },{ 0x304461, 22 },{ 0x304462, 22 },{ 0x304463, 22 },
-{ 0x304464, 22 },{ 0x304465, 22 },{ 0x304466, 22 },{ 0x304467, 22 },
-{ 0x304468, 22 },{ 0x304469, 22 },{ 0x30446a, 22 },{ 0x30446b, 22 },
-{ 0x30446c, 22 },{ 0x30446d, 22 },{ 0x30446e, 22 },{ 0x30446f, 22 },
-{ 0x304470, 22 },{ 0x304471, 22 },{ 0x304472, 22 },{ 0x304473, 22 },
-{ 0x304474, 22 },{ 0x304475, 22 },{ 0x304476, 22 },{ 0x304477, 22 },
-{ 0x304478, 22 },{ 0x304479, 22 },{ 0x30447a, 22 },{ 0x30447b, 22 },
-{ 0x30447c, 22 },{ 0x30447d, 22 },{ 0x30447e, 22 },{ 0x30447f, 22 },
-{ 0x608880, 23 },{ 0x608881, 23 },{ 0x608882, 23 },{ 0x608883, 23 },
-{ 0x608884, 23 },{ 0x608885, 23 },{ 0x608886, 23 },{ 0x608887, 23 },
-{ 0x608888, 23 },{ 0x608889, 23 },{ 0x60888a, 23 },{ 0x60888b, 23 },
-{ 0x60888c, 23 },{ 0x60888d, 23 },{ 0x60888e, 23 },{ 0x60888f, 23 },
+    {      0x0,  2 }, {      0x1,  2 }, {      0x5,  3 }, {      0x9,  4 },
+    {      0xd,  4 }, {     0x11,  5 }, {     0x1d,  5 }, {     0x1f,  5 },
+    {     0x21,  6 }, {     0x31,  6 }, {     0x38,  6 }, {     0x33,  6 },
+    {     0x39,  6 }, {     0x3d,  6 }, {     0x61,  7 }, {     0x79,  7 },
+    {     0x80,  8 }, {     0xc8,  8 }, {     0xca,  8 }, {     0xf0,  8 },
+    {     0x81,  8 }, {     0xc0,  8 }, {     0xc9,  8 }, {    0x107,  9 },
+    {    0x106,  9 }, {    0x196,  9 }, {    0x183,  9 }, {    0x1e3,  9 },
+    {    0x1e2,  9 }, {    0x20a, 10 }, {    0x20b, 10 }, {    0x609, 11 },
+    {    0x412, 11 }, {    0x413, 11 }, {    0x60b, 11 }, {    0x411, 11 },
+    {    0x60a, 11 }, {    0x65f, 11 }, {    0x410, 11 }, {    0x65d, 11 },
+    {    0x65e, 11 }, {    0xcb8, 12 }, {    0xc10, 12 }, {    0xcb9, 12 },
+    {   0x1823, 13 }, {   0x3045, 14 }, {   0x6089, 15 }, {   0xc110, 16 },
+    { 0x304448, 22 }, { 0x304449, 22 }, { 0x30444a, 22 }, { 0x30444b, 22 },
+    { 0x30444c, 22 }, { 0x30444d, 22 }, { 0x30444e, 22 }, { 0x30444f, 22 },
+    { 0x304450, 22 }, { 0x304451, 22 }, { 0x304452, 22 }, { 0x304453, 22 },
+    { 0x304454, 22 }, { 0x304455, 22 }, { 0x304456, 22 }, { 0x304457, 22 },
+    { 0x304458, 22 }, { 0x304459, 22 }, { 0x30445a, 22 }, { 0x30445b, 22 },
+    { 0x30445c, 22 }, { 0x30445d, 22 }, { 0x30445e, 22 }, { 0x30445f, 22 },
+    { 0x304460, 22 }, { 0x304461, 22 }, { 0x304462, 22 }, { 0x304463, 22 },
+    { 0x304464, 22 }, { 0x304465, 22 }, { 0x304466, 22 }, { 0x304467, 22 },
+    { 0x304468, 22 }, { 0x304469, 22 }, { 0x30446a, 22 }, { 0x30446b, 22 },
+    { 0x30446c, 22 }, { 0x30446d, 22 }, { 0x30446e, 22 }, { 0x30446f, 22 },
+    { 0x304470, 22 }, { 0x304471, 22 }, { 0x304472, 22 }, { 0x304473, 22 },
+    { 0x304474, 22 }, { 0x304475, 22 }, { 0x304476, 22 }, { 0x304477, 22 },
+    { 0x304478, 22 }, { 0x304479, 22 }, { 0x30447a, 22 }, { 0x30447b, 22 },
+    { 0x30447c, 22 }, { 0x30447d, 22 }, { 0x30447e, 22 }, { 0x30447f, 22 },
+    { 0x608880, 23 }, { 0x608881, 23 }, { 0x608882, 23 }, { 0x608883, 23 },
+    { 0x608884, 23 }, { 0x608885, 23 }, { 0x608886, 23 }, { 0x608887, 23 },
+    { 0x608888, 23 }, { 0x608889, 23 }, { 0x60888a, 23 }, { 0x60888b, 23 },
+    { 0x60888c, 23 }, { 0x60888d, 23 }, { 0x60888e, 23 }, { 0x60888f, 23 },
 };
 
 /* dc table 1 */
 
 const uint32_t ff_table1_dc_lum[120][2] = {
-{      0x2,  2 },{      0x3,  2 },{      0x3,  3 },{      0x2,  4 },
-{      0x5,  4 },{      0x1,  5 },{      0x3,  5 },{      0x8,  5 },
-{      0x0,  6 },{      0x5,  6 },{      0xd,  6 },{      0xf,  6 },
-{     0x13,  6 },{      0x8,  7 },{     0x18,  7 },{     0x1c,  7 },
-{     0x24,  7 },{      0x4,  8 },{      0x6,  8 },{     0x12,  8 },
-{     0x32,  8 },{     0x3b,  8 },{     0x4a,  8 },{     0x4b,  8 },
-{      0xb,  9 },{     0x26,  9 },{     0x27,  9 },{     0x66,  9 },
-{     0x74,  9 },{     0x75,  9 },{     0x14, 10 },{     0x1c, 10 },
-{     0x1f, 10 },{     0x1d, 10 },{     0x2b, 11 },{     0x3d, 11 },
-{    0x19d, 11 },{    0x19f, 11 },{     0x54, 12 },{    0x339, 12 },
-{    0x338, 12 },{    0x33d, 12 },{     0xab, 13 },{     0xf1, 13 },
-{    0x678, 13 },{     0xf2, 13 },{    0x1e0, 14 },{    0x1e1, 14 },
-{    0x154, 14 },{    0xcf2, 14 },{    0x3cc, 15 },{    0x2ab, 15 },
-{   0x19e7, 15 },{    0x3ce, 15 },{   0x19e6, 15 },{    0x554, 16 },
-{    0x79f, 16 },{    0x555, 16 },{    0xf3d, 17 },{    0xf37, 17 },
-{    0xf3c, 17 },{    0xf35, 17 },{   0x1e6d, 18 },{   0x1e68, 18 },
-{   0x3cd8, 19 },{   0x3cd3, 19 },{   0x3cd9, 19 },{   0x79a4, 20 },
-{  0xf34ba, 25 },{  0xf34b4, 25 },{  0xf34b5, 25 },{  0xf34b6, 25 },
-{  0xf34b7, 25 },{  0xf34b8, 25 },{  0xf34b9, 25 },{  0xf34bb, 25 },
-{  0xf34bc, 25 },{  0xf34bd, 25 },{  0xf34be, 25 },{  0xf34bf, 25 },
-{ 0x1e6940, 26 },{ 0x1e6941, 26 },{ 0x1e6942, 26 },{ 0x1e6943, 26 },
-{ 0x1e6944, 26 },{ 0x1e6945, 26 },{ 0x1e6946, 26 },{ 0x1e6947, 26 },
-{ 0x1e6948, 26 },{ 0x1e6949, 26 },{ 0x1e694a, 26 },{ 0x1e694b, 26 },
-{ 0x1e694c, 26 },{ 0x1e694d, 26 },{ 0x1e694e, 26 },{ 0x1e694f, 26 },
-{ 0x1e6950, 26 },{ 0x1e6951, 26 },{ 0x1e6952, 26 },{ 0x1e6953, 26 },
-{ 0x1e6954, 26 },{ 0x1e6955, 26 },{ 0x1e6956, 26 },{ 0x1e6957, 26 },
-{ 0x1e6958, 26 },{ 0x1e6959, 26 },{ 0x1e695a, 26 },{ 0x1e695b, 26 },
-{ 0x1e695c, 26 },{ 0x1e695d, 26 },{ 0x1e695e, 26 },{ 0x1e695f, 26 },
-{ 0x1e6960, 26 },{ 0x1e6961, 26 },{ 0x1e6962, 26 },{ 0x1e6963, 26 },
-{ 0x1e6964, 26 },{ 0x1e6965, 26 },{ 0x1e6966, 26 },{ 0x1e6967, 26 },
+    {      0x2,  2 }, {      0x3,  2 }, {      0x3,  3 }, {      0x2,  4 },
+    {      0x5,  4 }, {      0x1,  5 }, {      0x3,  5 }, {      0x8,  5 },
+    {      0x0,  6 }, {      0x5,  6 }, {      0xd,  6 }, {      0xf,  6 },
+    {     0x13,  6 }, {      0x8,  7 }, {     0x18,  7 }, {     0x1c,  7 },
+    {     0x24,  7 }, {      0x4,  8 }, {      0x6,  8 }, {     0x12,  8 },
+    {     0x32,  8 }, {     0x3b,  8 }, {     0x4a,  8 }, {     0x4b,  8 },
+    {      0xb,  9 }, {     0x26,  9 }, {     0x27,  9 }, {     0x66,  9 },
+    {     0x74,  9 }, {     0x75,  9 }, {     0x14, 10 }, {     0x1c, 10 },
+    {     0x1f, 10 }, {     0x1d, 10 }, {     0x2b, 11 }, {     0x3d, 11 },
+    {    0x19d, 11 }, {    0x19f, 11 }, {     0x54, 12 }, {    0x339, 12 },
+    {    0x338, 12 }, {    0x33d, 12 }, {     0xab, 13 }, {     0xf1, 13 },
+    {    0x678, 13 }, {     0xf2, 13 }, {    0x1e0, 14 }, {    0x1e1, 14 },
+    {    0x154, 14 }, {    0xcf2, 14 }, {    0x3cc, 15 }, {    0x2ab, 15 },
+    {   0x19e7, 15 }, {    0x3ce, 15 }, {   0x19e6, 15 }, {    0x554, 16 },
+    {    0x79f, 16 }, {    0x555, 16 }, {    0xf3d, 17 }, {    0xf37, 17 },
+    {    0xf3c, 17 }, {    0xf35, 17 }, {   0x1e6d, 18 }, {   0x1e68, 18 },
+    {   0x3cd8, 19 }, {   0x3cd3, 19 }, {   0x3cd9, 19 }, {   0x79a4, 20 },
+    {  0xf34ba, 25 }, {  0xf34b4, 25 }, {  0xf34b5, 25 }, {  0xf34b6, 25 },
+    {  0xf34b7, 25 }, {  0xf34b8, 25 }, {  0xf34b9, 25 }, {  0xf34bb, 25 },
+    {  0xf34bc, 25 }, {  0xf34bd, 25 }, {  0xf34be, 25 }, {  0xf34bf, 25 },
+    { 0x1e6940, 26 }, { 0x1e6941, 26 }, { 0x1e6942, 26 }, { 0x1e6943, 26 },
+    { 0x1e6944, 26 }, { 0x1e6945, 26 }, { 0x1e6946, 26 }, { 0x1e6947, 26 },
+    { 0x1e6948, 26 }, { 0x1e6949, 26 }, { 0x1e694a, 26 }, { 0x1e694b, 26 },
+    { 0x1e694c, 26 }, { 0x1e694d, 26 }, { 0x1e694e, 26 }, { 0x1e694f, 26 },
+    { 0x1e6950, 26 }, { 0x1e6951, 26 }, { 0x1e6952, 26 }, { 0x1e6953, 26 },
+    { 0x1e6954, 26 }, { 0x1e6955, 26 }, { 0x1e6956, 26 }, { 0x1e6957, 26 },
+    { 0x1e6958, 26 }, { 0x1e6959, 26 }, { 0x1e695a, 26 }, { 0x1e695b, 26 },
+    { 0x1e695c, 26 }, { 0x1e695d, 26 }, { 0x1e695e, 26 }, { 0x1e695f, 26 },
+    { 0x1e6960, 26 }, { 0x1e6961, 26 }, { 0x1e6962, 26 }, { 0x1e6963, 26 },
+    { 0x1e6964, 26 }, { 0x1e6965, 26 }, { 0x1e6966, 26 }, { 0x1e6967, 26 },
 };
 
 const uint32_t ff_table1_dc_chroma[120][2] = {
-{       0x0,  2 },{       0x1,  2 },{       0x4,  3 },{       0x7,  3 },
-{       0xb,  4 },{       0xd,  4 },{      0x15,  5 },{      0x28,  6 },
-{      0x30,  6 },{      0x32,  6 },{      0x52,  7 },{      0x62,  7 },
-{      0x66,  7 },{      0xa6,  8 },{      0xc6,  8 },{      0xcf,  8 },
-{     0x14f,  9 },{     0x18e,  9 },{     0x19c,  9 },{     0x29d, 10 },
-{     0x33a, 10 },{     0x538, 11 },{     0x63c, 11 },{     0x63e, 11 },
-{     0x63f, 11 },{     0x676, 11 },{     0xa73, 12 },{     0xc7a, 12 },
-{     0xcef, 12 },{    0x14e5, 13 },{    0x19dd, 13 },{    0x29c8, 14 },
-{    0x29c9, 14 },{    0x63dd, 15 },{    0x33b8, 14 },{    0x33b9, 14 },
-{    0xc7b6, 16 },{    0x63d8, 15 },{    0x63df, 15 },{    0xc7b3, 16 },
-{    0xc7b4, 16 },{    0xc7b5, 16 },{    0x63de, 15 },{    0xc7b7, 16 },
-{    0xc7b8, 16 },{    0xc7b9, 16 },{   0x18f65, 17 },{   0x31ec8, 18 },
-{  0xc7b248, 24 },{  0xc7b249, 24 },{  0xc7b24a, 24 },{  0xc7b24b, 24 },
-{  0xc7b24c, 24 },{  0xc7b24d, 24 },{  0xc7b24e, 24 },{  0xc7b24f, 24 },
-{  0xc7b250, 24 },{  0xc7b251, 24 },{  0xc7b252, 24 },{  0xc7b253, 24 },
-{  0xc7b254, 24 },{  0xc7b255, 24 },{  0xc7b256, 24 },{  0xc7b257, 24 },
-{  0xc7b258, 24 },{  0xc7b259, 24 },{  0xc7b25a, 24 },{  0xc7b25b, 24 },
-{  0xc7b25c, 24 },{  0xc7b25d, 24 },{  0xc7b25e, 24 },{  0xc7b25f, 24 },
-{  0xc7b260, 24 },{  0xc7b261, 24 },{  0xc7b262, 24 },{  0xc7b263, 24 },
-{  0xc7b264, 24 },{  0xc7b265, 24 },{  0xc7b266, 24 },{  0xc7b267, 24 },
-{  0xc7b268, 24 },{  0xc7b269, 24 },{  0xc7b26a, 24 },{  0xc7b26b, 24 },
-{  0xc7b26c, 24 },{  0xc7b26d, 24 },{  0xc7b26e, 24 },{  0xc7b26f, 24 },
-{  0xc7b270, 24 },{  0xc7b271, 24 },{  0xc7b272, 24 },{  0xc7b273, 24 },
-{  0xc7b274, 24 },{  0xc7b275, 24 },{  0xc7b276, 24 },{  0xc7b277, 24 },
-{  0xc7b278, 24 },{  0xc7b279, 24 },{  0xc7b27a, 24 },{  0xc7b27b, 24 },
-{  0xc7b27c, 24 },{  0xc7b27d, 24 },{  0xc7b27e, 24 },{  0xc7b27f, 24 },
-{ 0x18f6480, 25 },{ 0x18f6481, 25 },{ 0x18f6482, 25 },{ 0x18f6483, 25 },
-{ 0x18f6484, 25 },{ 0x18f6485, 25 },{ 0x18f6486, 25 },{ 0x18f6487, 25 },
-{ 0x18f6488, 25 },{ 0x18f6489, 25 },{ 0x18f648a, 25 },{ 0x18f648b, 25 },
-{ 0x18f648c, 25 },{ 0x18f648d, 25 },{ 0x18f648e, 25 },{ 0x18f648f, 25 },
+    {       0x0,  2 }, {       0x1,  2 }, {       0x4,  3 }, {       0x7,  3 },
+    {       0xb,  4 }, {       0xd,  4 }, {      0x15,  5 }, {      0x28,  6 },
+    {      0x30,  6 }, {      0x32,  6 }, {      0x52,  7 }, {      0x62,  7 },
+    {      0x66,  7 }, {      0xa6,  8 }, {      0xc6,  8 }, {      0xcf,  8 },
+    {     0x14f,  9 }, {     0x18e,  9 }, {     0x19c,  9 }, {     0x29d, 10 },
+    {     0x33a, 10 }, {     0x538, 11 }, {     0x63c, 11 }, {     0x63e, 11 },
+    {     0x63f, 11 }, {     0x676, 11 }, {     0xa73, 12 }, {     0xc7a, 12 },
+    {     0xcef, 12 }, {    0x14e5, 13 }, {    0x19dd, 13 }, {    0x29c8, 14 },
+    {    0x29c9, 14 }, {    0x63dd, 15 }, {    0x33b8, 14 }, {    0x33b9, 14 },
+    {    0xc7b6, 16 }, {    0x63d8, 15 }, {    0x63df, 15 }, {    0xc7b3, 16 },
+    {    0xc7b4, 16 }, {    0xc7b5, 16 }, {    0x63de, 15 }, {    0xc7b7, 16 },
+    {    0xc7b8, 16 }, {    0xc7b9, 16 }, {   0x18f65, 17 }, {   0x31ec8, 18 },
+    {  0xc7b248, 24 }, {  0xc7b249, 24 }, {  0xc7b24a, 24 }, {  0xc7b24b, 24 },
+    {  0xc7b24c, 24 }, {  0xc7b24d, 24 }, {  0xc7b24e, 24 }, {  0xc7b24f, 24 },
+    {  0xc7b250, 24 }, {  0xc7b251, 24 }, {  0xc7b252, 24 }, {  0xc7b253, 24 },
+    {  0xc7b254, 24 }, {  0xc7b255, 24 }, {  0xc7b256, 24 }, {  0xc7b257, 24 },
+    {  0xc7b258, 24 }, {  0xc7b259, 24 }, {  0xc7b25a, 24 }, {  0xc7b25b, 24 },
+    {  0xc7b25c, 24 }, {  0xc7b25d, 24 }, {  0xc7b25e, 24 }, {  0xc7b25f, 24 },
+    {  0xc7b260, 24 }, {  0xc7b261, 24 }, {  0xc7b262, 24 }, {  0xc7b263, 24 },
+    {  0xc7b264, 24 }, {  0xc7b265, 24 }, {  0xc7b266, 24 }, {  0xc7b267, 24 },
+    {  0xc7b268, 24 }, {  0xc7b269, 24 }, {  0xc7b26a, 24 }, {  0xc7b26b, 24 },
+    {  0xc7b26c, 24 }, {  0xc7b26d, 24 }, {  0xc7b26e, 24 }, {  0xc7b26f, 24 },
+    {  0xc7b270, 24 }, {  0xc7b271, 24 }, {  0xc7b272, 24 }, {  0xc7b273, 24 },
+    {  0xc7b274, 24 }, {  0xc7b275, 24 }, {  0xc7b276, 24 }, {  0xc7b277, 24 },
+    {  0xc7b278, 24 }, {  0xc7b279, 24 }, {  0xc7b27a, 24 }, {  0xc7b27b, 24 },
+    {  0xc7b27c, 24 }, {  0xc7b27d, 24 }, {  0xc7b27e, 24 }, {  0xc7b27f, 24 },
+    { 0x18f6480, 25 }, { 0x18f6481, 25 }, { 0x18f6482, 25 }, { 0x18f6483, 25 },
+    { 0x18f6484, 25 }, { 0x18f6485, 25 }, { 0x18f6486, 25 }, { 0x18f6487, 25 },
+    { 0x18f6488, 25 }, { 0x18f6489, 25 }, { 0x18f648a, 25 }, { 0x18f648b, 25 },
+    { 0x18f648c, 25 }, { 0x18f648d, 25 }, { 0x18f648e, 25 }, { 0x18f648f, 25 },
 };
 
 /* vlc table 0, for intra luma */
 
 static const uint16_t table0_vlc[133][2] = {
-{   0x1,  2 },{   0x6,  3 },{   0xf,  4 },{  0x16,  5 },
-{  0x20,  6 },{  0x18,  7 },{   0x8,  8 },{  0x9a,  8 },
-{  0x56,  9 },{ 0x13e,  9 },{  0xf0, 10 },{ 0x3a5, 10 },
-{  0x77, 11 },{ 0x1ef, 11 },{  0x9a, 12 },{  0x5d, 13 },
-{   0x1,  4 },{  0x11,  5 },{   0x2,  7 },{   0xb,  8 },
-{  0x12,  9 },{ 0x1d6,  9 },{ 0x27e, 10 },{ 0x191, 11 },
-{  0xea, 12 },{ 0x3dc, 12 },{ 0x13b, 13 },{   0x4,  5 },
-{  0x14,  7 },{  0x9e,  8 },{   0x9, 10 },{ 0x1ac, 11 },
-{ 0x1e2, 11 },{ 0x3ca, 12 },{  0x5f, 13 },{  0x17,  5 },
-{  0x4e,  7 },{  0x5e,  9 },{  0xf3, 10 },{ 0x1ad, 11 },
-{  0xec, 12 },{ 0x5f0, 13 },{   0xe,  6 },{  0xe1,  8 },
-{ 0x3a4, 10 },{  0x9c, 12 },{ 0x13d, 13 },{  0x3b,  6 },
-{  0x1c,  9 },{  0x14, 11 },{ 0x9be, 12 },{   0x6,  7 },
-{  0x7a,  9 },{ 0x190, 11 },{ 0x137, 13 },{  0x1b,  7 },
-{   0x8, 10 },{ 0x75c, 11 },{  0x71,  7 },{  0xd7, 10 },
-{ 0x9bf, 12 },{   0x7,  8 },{  0xaf, 10 },{ 0x4cc, 11 },
-{  0x34,  8 },{ 0x265, 10 },{  0x9f, 12 },{  0xe0,  8 },
-{  0x16, 11 },{ 0x327, 12 },{  0x15,  9 },{ 0x17d, 11 },
-{ 0xebb, 12 },{  0x14,  9 },{  0xf6, 10 },{ 0x1e4, 11 },
-{  0xcb, 10 },{ 0x99d, 12 },{  0xca, 10 },{ 0x2fc, 12 },
-{ 0x17f, 11 },{ 0x4cd, 11 },{ 0x2fd, 12 },{ 0x4fe, 11 },
-{ 0x13a, 13 },{   0xa,  4 },{  0x42,  7 },{ 0x1d3,  9 },
-{ 0x4dd, 11 },{  0x12,  5 },{  0xe8,  8 },{  0x4c, 11 },
-{ 0x136, 13 },{  0x39,  6 },{ 0x264, 10 },{ 0xeba, 12 },
-{   0x0,  7 },{  0xae, 10 },{ 0x99c, 12 },{  0x1f,  7 },
-{ 0x4de, 11 },{  0x43,  7 },{ 0x4dc, 11 },{   0x3,  8 },
-{ 0x3cb, 12 },{   0x6,  8 },{ 0x99e, 12 },{  0x2a,  8 },
-{ 0x5f1, 13 },{   0xf,  8 },{ 0x9fe, 12 },{  0x33,  8 },
-{ 0x9ff, 12 },{  0x98,  8 },{ 0x99f, 12 },{  0xea,  8 },
-{ 0x13c, 13 },{  0x2e,  8 },{ 0x192, 11 },{ 0x136,  9 },
-{  0x6a,  9 },{  0x15, 11 },{ 0x3af, 10 },{ 0x1e3, 11 },
-{  0x74, 11 },{  0xeb, 12 },{ 0x2f9, 12 },{  0x5c, 13 },
-{  0xed, 12 },{ 0x3dd, 12 },{ 0x326, 12 },{  0x5e, 13 },
-{  0x16,  7 },
+    {   0x1,  2 }, {   0x6,  3 }, {   0xf,  4 }, {  0x16,  5 },
+    {  0x20,  6 }, {  0x18,  7 }, {   0x8,  8 }, {  0x9a,  8 },
+    {  0x56,  9 }, { 0x13e,  9 }, {  0xf0, 10 }, { 0x3a5, 10 },
+    {  0x77, 11 }, { 0x1ef, 11 }, {  0x9a, 12 }, {  0x5d, 13 },
+    {   0x1,  4 }, {  0x11,  5 }, {   0x2,  7 }, {   0xb,  8 },
+    {  0x12,  9 }, { 0x1d6,  9 }, { 0x27e, 10 }, { 0x191, 11 },
+    {  0xea, 12 }, { 0x3dc, 12 }, { 0x13b, 13 }, {   0x4,  5 },
+    {  0x14,  7 }, {  0x9e,  8 }, {   0x9, 10 }, { 0x1ac, 11 },
+    { 0x1e2, 11 }, { 0x3ca, 12 }, {  0x5f, 13 }, {  0x17,  5 },
+    {  0x4e,  7 }, {  0x5e,  9 }, {  0xf3, 10 }, { 0x1ad, 11 },
+    {  0xec, 12 }, { 0x5f0, 13 }, {   0xe,  6 }, {  0xe1,  8 },
+    { 0x3a4, 10 }, {  0x9c, 12 }, { 0x13d, 13 }, {  0x3b,  6 },
+    {  0x1c,  9 }, {  0x14, 11 }, { 0x9be, 12 }, {   0x6,  7 },
+    {  0x7a,  9 }, { 0x190, 11 }, { 0x137, 13 }, {  0x1b,  7 },
+    {   0x8, 10 }, { 0x75c, 11 }, {  0x71,  7 }, {  0xd7, 10 },
+    { 0x9bf, 12 }, {   0x7,  8 }, {  0xaf, 10 }, { 0x4cc, 11 },
+    {  0x34,  8 }, { 0x265, 10 }, {  0x9f, 12 }, {  0xe0,  8 },
+    {  0x16, 11 }, { 0x327, 12 }, {  0x15,  9 }, { 0x17d, 11 },
+    { 0xebb, 12 }, {  0x14,  9 }, {  0xf6, 10 }, { 0x1e4, 11 },
+    {  0xcb, 10 }, { 0x99d, 12 }, {  0xca, 10 }, { 0x2fc, 12 },
+    { 0x17f, 11 }, { 0x4cd, 11 }, { 0x2fd, 12 }, { 0x4fe, 11 },
+    { 0x13a, 13 }, {   0xa,  4 }, {  0x42,  7 }, { 0x1d3,  9 },
+    { 0x4dd, 11 }, {  0x12,  5 }, {  0xe8,  8 }, {  0x4c, 11 },
+    { 0x136, 13 }, {  0x39,  6 }, { 0x264, 10 }, { 0xeba, 12 },
+    {   0x0,  7 }, {  0xae, 10 }, { 0x99c, 12 }, {  0x1f,  7 },
+    { 0x4de, 11 }, {  0x43,  7 }, { 0x4dc, 11 }, {   0x3,  8 },
+    { 0x3cb, 12 }, {   0x6,  8 }, { 0x99e, 12 }, {  0x2a,  8 },
+    { 0x5f1, 13 }, {   0xf,  8 }, { 0x9fe, 12 }, {  0x33,  8 },
+    { 0x9ff, 12 }, {  0x98,  8 }, { 0x99f, 12 }, {  0xea,  8 },
+    { 0x13c, 13 }, {  0x2e,  8 }, { 0x192, 11 }, { 0x136,  9 },
+    {  0x6a,  9 }, {  0x15, 11 }, { 0x3af, 10 }, { 0x1e3, 11 },
+    {  0x74, 11 }, {  0xeb, 12 }, { 0x2f9, 12 }, {  0x5c, 13 },
+    {  0xed, 12 }, { 0x3dd, 12 }, { 0x326, 12 }, {  0x5e, 13 },
+    {  0x16,  7 },
 };
 
 static const int8_t table0_level[132] = {
-  1,  2,  3,  4,  5,  6,  7,  8,
-  9, 10, 11, 12, 13, 14, 15, 16,
-  1,  2,  3,  4,  5,  6,  7,  8,
-  9, 10, 11,  1,  2,  3,  4,  5,
-  6,  7,  8,  1,  2,  3,  4,  5,
-  6,  7,  1,  2,  3,  4,  5,  1,
-  2,  3,  4,  1,  2,  3,  4,  1,
-  2,  3,  1,  2,  3,  1,  2,  3,
-  1,  2,  3,  1,  2,  3,  1,  2,
-  3,  1,  2,  3,  1,  2,  1,  2,
-  1,  1,  1,  1,  1,  1,  2,  3,
-  4,  1,  2,  3,  4,  1,  2,  3,
-  1,  2,  3,  1,  2,  1,  2,  1,
-  2,  1,  2,  1,  2,  1,  2,  1,
-  2,  1,  2,  1,  2,  1,  2,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,
+    1,  2,  3,  4,  5,  6,  7,  8,
+    9, 10, 11, 12, 13, 14, 15, 16,
+    1,  2,  3,  4,  5,  6,  7,  8,
+    9, 10, 11,  1,  2,  3,  4,  5,
+    6,  7,  8,  1,  2,  3,  4,  5,
+    6,  7,  1,  2,  3,  4,  5,  1,
+    2,  3,  4,  1,  2,  3,  4,  1,
+    2,  3,  1,  2,  3,  1,  2,  3,
+    1,  2,  3,  1,  2,  3,  1,  2,
+    3,  1,  2,  3,  1,  2,  1,  2,
+    1,  1,  1,  1,  1,  1,  2,  3,
+    4,  1,  2,  3,  4,  1,  2,  3,
+    1,  2,  3,  1,  2,  1,  2,  1,
+    2,  1,  2,  1,  2,  1,  2,  1,
+    2,  1,  2,  1,  2,  1,  2,  1,
+    1,  1,  1,  1,  1,  1,  1,  1,
+    1,  1,  1,  1,
 };
 
 static const int8_t table0_run[132] = {
-  0,  0,  0,  0,  0,  0,  0,  0,
-  0,  0,  0,  0,  0,  0,  0,  0,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  2,  2,  2,  2,  2,
-  2,  2,  2,  3,  3,  3,  3,  3,
-  3,  3,  4,  4,  4,  4,  4,  5,
-  5,  5,  5,  6,  6,  6,  6,  7,
-  7,  7,  8,  8,  8,  9,  9,  9,
- 10, 10, 10, 11, 11, 11, 12, 12,
- 12, 13, 13, 13, 14, 14, 15, 15,
- 16, 17, 18, 19, 20,  0,  0,  0,
-  0,  1,  1,  1,  1,  2,  2,  2,
-  3,  3,  3,  4,  4,  5,  5,  6,
-  6,  7,  7,  8,  8,  9,  9, 10,
- 10, 11, 11, 12, 12, 13, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  2,  2,  2,  2,  2,
+     2,  2,  2,  3,  3,  3,  3,  3,
+     3,  3,  4,  4,  4,  4,  4,  5,
+     5,  5,  5,  6,  6,  6,  6,  7,
+     7,  7,  8,  8,  8,  9,  9,  9,
+    10, 10, 10, 11, 11, 11, 12, 12,
+    12, 13, 13, 13, 14, 14, 15, 15,
+    16, 17, 18, 19, 20,  0,  0,  0,
+     0,  1,  1,  1,  1,  2,  2,  2,
+     3,  3,  3,  4,  4,  5,  5,  6,
+     6,  7,  7,  8,  8,  9,  9, 10,
+    10, 11, 11, 12, 12, 13, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22,
+    23, 24, 25, 26,
 };
 
 /* vlc table 1, for intra chroma and P macroblocks */
 
 static const uint16_t table1_vlc[149][2] = {
-{    0x4,  3 },{   0x14,  5 },{   0x17,  7 },{   0x7f,  8 },
-{  0x154,  9 },{  0x1f2, 10 },{   0xbf, 11 },{   0x65, 12 },
-{  0xaaa, 12 },{  0x630, 13 },{ 0x1597, 13 },{  0x3b7, 14 },
-{ 0x2b22, 14 },{  0xbe6, 15 },{    0xb,  4 },{   0x37,  7 },
-{   0x62,  9 },{    0x7, 11 },{  0x166, 12 },{   0xce, 13 },
-{ 0x1590, 13 },{  0x5f6, 14 },{  0xbe7, 15 },{    0x7,  5 },
-{   0x6d,  8 },{    0x3, 11 },{  0x31f, 12 },{  0x5f2, 14 },
-{    0x2,  6 },{   0x61,  9 },{   0x55, 12 },{  0x1df, 14 },
-{   0x1a,  6 },{   0x1e, 10 },{  0xac9, 12 },{ 0x2b23, 14 },
-{   0x1e,  6 },{   0x1f, 10 },{  0xac3, 12 },{ 0x2b2b, 14 },
-{    0x6,  7 },{    0x4, 11 },{  0x2f8, 13 },{   0x19,  7 },
-{    0x6, 11 },{  0x63d, 13 },{   0x57,  7 },{  0x182, 11 },
-{ 0x2aa2, 14 },{    0x4,  8 },{  0x180, 11 },{  0x59c, 14 },
-{   0x7d,  8 },{  0x164, 12 },{  0x76d, 15 },{    0x2,  9 },
-{  0x18d, 11 },{ 0x1581, 13 },{   0xad,  8 },{   0x60, 12 },
-{  0xc67, 14 },{   0x1c,  9 },{   0xee, 13 },{    0x3,  9 },
-{  0x2cf, 13 },{   0xd9,  9 },{ 0x1580, 13 },{    0x2, 11 },
-{  0x183, 11 },{   0x57, 12 },{   0x61, 12 },{   0x31, 11 },
-{   0x66, 12 },{  0x631, 13 },{  0x632, 13 },{   0xac, 13 },
-{  0x31d, 12 },{   0x76, 12 },{   0x3a, 11 },{  0x165, 12 },
-{  0xc66, 14 },{    0x3,  2 },{   0x54,  7 },{  0x2ab, 10 },
-{   0x16, 13 },{  0x5f7, 14 },{    0x5,  4 },{   0xf8,  9 },
-{  0xaa9, 12 },{   0x5f, 15 },{    0x4,  4 },{   0x1c, 10 },
-{ 0x1550, 13 },{    0x4,  5 },{   0x77, 11 },{  0x76c, 15 },
-{    0xe,  5 },{    0xa, 12 },{    0xc,  5 },{  0x562, 11 },
-{    0x4,  6 },{  0x31c, 12 },{    0x6,  6 },{   0xc8, 13 },
-{    0xd,  6 },{  0x1da, 13 },{    0x7,  6 },{   0xc9, 13 },
-{    0x1,  7 },{   0x2e, 14 },{   0x14,  7 },{ 0x1596, 13 },
-{    0xa,  7 },{  0xac2, 12 },{   0x16,  7 },{  0x15b, 14 },
-{   0x15,  7 },{  0x15a, 14 },{    0xf,  8 },{   0x5e, 15 },
-{   0x7e,  8 },{   0xab,  8 },{   0x2d,  9 },{   0xd8,  9 },
-{    0xb,  9 },{   0x14, 10 },{  0x2b3, 10 },{  0x1f3, 10 },
-{   0x3a, 10 },{    0x0, 10 },{   0x58, 10 },{   0x2e,  9 },
-{   0x5e, 10 },{  0x563, 11 },{   0xec, 12 },{   0x54, 12 },
-{  0xac1, 12 },{ 0x1556, 13 },{  0x2fa, 13 },{  0x181, 11 },
-{ 0x1557, 13 },{  0x59d, 14 },{ 0x2aa3, 14 },{ 0x2b2a, 14 },
-{  0x1de, 14 },{  0x63c, 13 },{   0xcf, 13 },{ 0x1594, 13 },
-{    0xd,  9 },
+    {    0x4,  3 }, {   0x14,  5 }, {   0x17,  7 }, {   0x7f,  8 },
+    {  0x154,  9 }, {  0x1f2, 10 }, {   0xbf, 11 }, {   0x65, 12 },
+    {  0xaaa, 12 }, {  0x630, 13 }, { 0x1597, 13 }, {  0x3b7, 14 },
+    { 0x2b22, 14 }, {  0xbe6, 15 }, {    0xb,  4 }, {   0x37,  7 },
+    {   0x62,  9 }, {    0x7, 11 }, {  0x166, 12 }, {   0xce, 13 },
+    { 0x1590, 13 }, {  0x5f6, 14 }, {  0xbe7, 15 }, {    0x7,  5 },
+    {   0x6d,  8 }, {    0x3, 11 }, {  0x31f, 12 }, {  0x5f2, 14 },
+    {    0x2,  6 }, {   0x61,  9 }, {   0x55, 12 }, {  0x1df, 14 },
+    {   0x1a,  6 }, {   0x1e, 10 }, {  0xac9, 12 }, { 0x2b23, 14 },
+    {   0x1e,  6 }, {   0x1f, 10 }, {  0xac3, 12 }, { 0x2b2b, 14 },
+    {    0x6,  7 }, {    0x4, 11 }, {  0x2f8, 13 }, {   0x19,  7 },
+    {    0x6, 11 }, {  0x63d, 13 }, {   0x57,  7 }, {  0x182, 11 },
+    { 0x2aa2, 14 }, {    0x4,  8 }, {  0x180, 11 }, {  0x59c, 14 },
+    {   0x7d,  8 }, {  0x164, 12 }, {  0x76d, 15 }, {    0x2,  9 },
+    {  0x18d, 11 }, { 0x1581, 13 }, {   0xad,  8 }, {   0x60, 12 },
+    {  0xc67, 14 }, {   0x1c,  9 }, {   0xee, 13 }, {    0x3,  9 },
+    {  0x2cf, 13 }, {   0xd9,  9 }, { 0x1580, 13 }, {    0x2, 11 },
+    {  0x183, 11 }, {   0x57, 12 }, {   0x61, 12 }, {   0x31, 11 },
+    {   0x66, 12 }, {  0x631, 13 }, {  0x632, 13 }, {   0xac, 13 },
+    {  0x31d, 12 }, {   0x76, 12 }, {   0x3a, 11 }, {  0x165, 12 },
+    {  0xc66, 14 }, {    0x3,  2 }, {   0x54,  7 }, {  0x2ab, 10 },
+    {   0x16, 13 }, {  0x5f7, 14 }, {    0x5,  4 }, {   0xf8,  9 },
+    {  0xaa9, 12 }, {   0x5f, 15 }, {    0x4,  4 }, {   0x1c, 10 },
+    { 0x1550, 13 }, {    0x4,  5 }, {   0x77, 11 }, {  0x76c, 15 },
+    {    0xe,  5 }, {    0xa, 12 }, {    0xc,  5 }, {  0x562, 11 },
+    {    0x4,  6 }, {  0x31c, 12 }, {    0x6,  6 }, {   0xc8, 13 },
+    {    0xd,  6 }, {  0x1da, 13 }, {    0x7,  6 }, {   0xc9, 13 },
+    {    0x1,  7 }, {   0x2e, 14 }, {   0x14,  7 }, { 0x1596, 13 },
+    {    0xa,  7 }, {  0xac2, 12 }, {   0x16,  7 }, {  0x15b, 14 },
+    {   0x15,  7 }, {  0x15a, 14 }, {    0xf,  8 }, {   0x5e, 15 },
+    {   0x7e,  8 }, {   0xab,  8 }, {   0x2d,  9 }, {   0xd8,  9 },
+    {    0xb,  9 }, {   0x14, 10 }, {  0x2b3, 10 }, {  0x1f3, 10 },
+    {   0x3a, 10 }, {    0x0, 10 }, {   0x58, 10 }, {   0x2e,  9 },
+    {   0x5e, 10 }, {  0x563, 11 }, {   0xec, 12 }, {   0x54, 12 },
+    {  0xac1, 12 }, { 0x1556, 13 }, {  0x2fa, 13 }, {  0x181, 11 },
+    { 0x1557, 13 }, {  0x59d, 14 }, { 0x2aa3, 14 }, { 0x2b2a, 14 },
+    {  0x1de, 14 }, {  0x63c, 13 }, {   0xcf, 13 }, { 0x1594, 13 },
+    {    0xd,  9 },
 };
 
 static const int8_t table1_level[148] = {
-  1,  2,  3,  4,  5,  6,  7,  8,
-  9, 10, 11, 12, 13, 14,  1,  2,
-  3,  4,  5,  6,  7,  8,  9,  1,
-  2,  3,  4,  5,  1,  2,  3,  4,
-  1,  2,  3,  4,  1,  2,  3,  4,
-  1,  2,  3,  1,  2,  3,  1,  2,
-  3,  1,  2,  3,  1,  2,  3,  1,
-  2,  3,  1,  2,  3,  1,  2,  1,
-  2,  1,  2,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  2,  3,  4,  5,  1,  2,
-  3,  4,  1,  2,  3,  1,  2,  3,
-  1,  2,  1,  2,  1,  2,  1,  2,
-  1,  2,  1,  2,  1,  2,  1,  2,
-  1,  2,  1,  2,  1,  2,  1,  2,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,
+    1,  2,  3,  4,  5,  6, 7, 8,
+    9, 10, 11, 12, 13, 14, 1, 2,
+    3,  4,  5,  6,  7,  8, 9, 1,
+    2,  3,  4,  5,  1,  2, 3, 4,
+    1,  2,  3,  4,  1,  2, 3, 4,
+    1,  2,  3,  1,  2,  3, 1, 2,
+    3,  1,  2,  3,  1,  2, 3, 1,
+    2,  3,  1,  2,  3,  1, 2, 1,
+    2,  1,  2,  1,  1,  1, 1, 1,
+    1,  1,  1,  1,  1,  1, 1, 1,
+    1,  1,  2,  3,  4,  5, 1, 2,
+    3,  4,  1,  2,  3,  1, 2, 3,
+    1,  2,  1,  2,  1,  2, 1, 2,
+    1,  2,  1,  2,  1,  2, 1, 2,
+    1,  2,  1,  2,  1,  2, 1, 2,
+    1,  1,  1,  1,  1,  1, 1, 1,
+    1,  1,  1,  1,  1,  1, 1, 1,
+    1,  1,  1,  1,  1,  1, 1, 1,
+    1,  1,  1,  1,
 };
 
 static const int8_t table1_run[148] = {
-  0,  0,  0,  0,  0,  0,  0,  0,
-  0,  0,  0,  0,  0,  0,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  2,
-  2,  2,  2,  2,  3,  3,  3,  3,
-  4,  4,  4,  4,  5,  5,  5,  5,
-  6,  6,  6,  7,  7,  7,  8,  8,
-  8,  9,  9,  9, 10, 10, 10, 11,
- 11, 11, 12, 12, 12, 13, 13, 14,
- 14, 15, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 27, 28,
- 29,  0,  0,  0,  0,  0,  1,  1,
-  1,  1,  2,  2,  2,  3,  3,  3,
-  4,  4,  5,  5,  6,  6,  7,  7,
-  8,  8,  9,  9, 10, 10, 11, 11,
- 12, 12, 13, 13, 14, 14, 15, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  2,
+     2,  2,  2,  2,  3,  3,  3,  3,
+     4,  4,  4,  4,  5,  5,  5,  5,
+     6,  6,  6,  7,  7,  7,  8,  8,
+     8,  9,  9,  9, 10, 10, 10, 11,
+    11, 11, 12, 12, 12, 13, 13, 14,
+    14, 15, 15, 16, 17, 18, 19, 20,
+    21, 22, 23, 24, 25, 26, 27, 28,
+    29,  0,  0,  0,  0,  0,  1,  1,
+     1,  1,  2,  2,  2,  3,  3,  3,
+     4,  4,  5,  5,  6,  6,  7,  7,
+     8,  8,  9,  9, 10, 10, 11, 11,
+    12, 12, 13, 13, 14, 14, 15, 15,
+    16, 17, 18, 19, 20, 21, 22, 23,
+    24, 25, 26, 27, 28, 29, 30, 31,
+    32, 33, 34, 35, 36, 37, 38, 39,
+    40, 41, 42, 43,
 };
 
 /* third vlc table */
 
 static const uint16_t table2_vlc[186][2] = {
-{    0x1,  2 },{    0x5,  3 },{    0xd,  4 },{   0x12,  5 },
-{    0xe,  6 },{   0x15,  7 },{   0x13,  8 },{   0x3f,  8 },
-{   0x4b,  9 },{  0x11f,  9 },{   0xb8, 10 },{  0x3e3, 10 },
-{  0x172, 11 },{  0x24d, 12 },{  0x3da, 12 },{  0x2dd, 13 },
-{ 0x1f55, 13 },{  0x5b9, 14 },{ 0x3eae, 14 },{    0x0,  4 },
-{   0x10,  5 },{    0x8,  7 },{   0x20,  8 },{   0x29,  9 },
-{  0x1f4,  9 },{  0x233, 10 },{  0x1e0, 11 },{  0x12a, 12 },
-{  0x3dd, 12 },{  0x50a, 13 },{ 0x1f29, 13 },{  0xa42, 14 },
-{ 0x1272, 15 },{ 0x1737, 15 },{    0x3,  5 },{   0x11,  7 },
-{   0xc4,  8 },{   0x4b, 10 },{   0xb4, 11 },{  0x7d4, 11 },
-{  0x345, 12 },{  0x2d7, 13 },{  0x7bf, 13 },{  0x938, 14 },
-{  0xbbb, 14 },{  0x95e, 15 },{   0x13,  5 },{   0x78,  7 },
-{   0x69,  9 },{  0x232, 10 },{  0x461, 11 },{  0x3ec, 12 },
-{  0x520, 13 },{ 0x1f2a, 13 },{ 0x3e50, 14 },{ 0x3e51, 14 },
-{ 0x1486, 15 },{    0xc,  6 },{   0x24,  9 },{   0x94, 11 },
-{  0x8c0, 12 },{  0xf09, 14 },{ 0x1ef0, 15 },{   0x3d,  6 },
-{   0x53,  9 },{  0x1a0, 11 },{  0x2d6, 13 },{  0xf08, 14 },
-{   0x13,  7 },{   0x7c,  9 },{  0x7c1, 11 },{  0x4ac, 14 },
-{   0x1b,  7 },{   0xa0, 10 },{  0x344, 12 },{  0xf79, 14 },
-{   0x79,  7 },{  0x3e1, 10 },{  0x2d4, 13 },{ 0x2306, 14 },
-{   0x21,  8 },{  0x23c, 10 },{  0xfae, 12 },{ 0x23de, 14 },
-{   0x35,  8 },{  0x175, 11 },{  0x7b3, 13 },{   0xc5,  8 },
-{  0x174, 11 },{  0x785, 13 },{   0x48,  9 },{  0x1a3, 11 },
-{  0x49e, 13 },{   0x2c,  9 },{   0xfa, 10 },{  0x7d6, 11 },
-{   0x92, 10 },{  0x5cc, 13 },{ 0x1ef1, 15 },{   0xa3, 10 },
-{  0x3ed, 12 },{  0x93e, 14 },{  0x1e2, 11 },{ 0x1273, 15 },
-{  0x7c4, 11 },{ 0x1487, 15 },{  0x291, 12 },{  0x293, 12 },
-{  0xf8a, 12 },{  0x509, 13 },{  0x508, 13 },{  0x78d, 13 },
-{  0x7be, 13 },{  0x78c, 13 },{  0x4ae, 14 },{  0xbba, 14 },
-{ 0x2307, 14 },{  0xb9a, 14 },{ 0x1736, 15 },{    0xe,  4 },
-{   0x45,  7 },{  0x1f3,  9 },{  0x47a, 11 },{  0x5dc, 13 },
-{ 0x23df, 14 },{   0x19,  5 },{   0x28,  9 },{  0x176, 11 },
-{  0x49d, 13 },{ 0x23dd, 14 },{   0x30,  6 },{   0xa2, 10 },
-{  0x2ef, 12 },{  0x5b8, 14 },{   0x3f,  6 },{   0xa5, 10 },
-{  0x3db, 12 },{  0x93f, 14 },{   0x44,  7 },{  0x7cb, 11 },
-{  0x95f, 15 },{   0x63,  7 },{  0x3c3, 12 },{   0x15,  8 },
-{  0x8f6, 12 },{   0x17,  8 },{  0x498, 13 },{   0x2c,  8 },
-{  0x7b2, 13 },{   0x2f,  8 },{ 0x1f54, 13 },{   0x8d,  8 },
-{  0x7bd, 13 },{   0x8e,  8 },{ 0x1182, 13 },{   0xfb,  8 },
-{  0x50b, 13 },{   0x2d,  8 },{  0x7c0, 11 },{   0x79,  9 },
-{ 0x1f5f, 13 },{   0x7a,  9 },{ 0x1f56, 13 },{  0x231, 10 },
-{  0x3e4, 10 },{  0x1a1, 11 },{  0x143, 11 },{  0x1f7, 11 },
-{  0x16f, 12 },{  0x292, 12 },{  0x2e7, 12 },{  0x16c, 12 },
-{  0x16d, 12 },{  0x3dc, 12 },{  0xf8b, 12 },{  0x499, 13 },
-{  0x3d8, 12 },{  0x78e, 13 },{  0x2d5, 13 },{ 0x1f5e, 13 },
-{ 0x1f2b, 13 },{  0x78f, 13 },{  0x4ad, 14 },{ 0x3eaf, 14 },
-{ 0x23dc, 14 },{   0x4a,  9 },
+    {    0x1,  2 }, {    0x5,  3 }, {    0xd,  4 }, {   0x12,  5 },
+    {    0xe,  6 }, {   0x15,  7 }, {   0x13,  8 }, {   0x3f,  8 },
+    {   0x4b,  9 }, {  0x11f,  9 }, {   0xb8, 10 }, {  0x3e3, 10 },
+    {  0x172, 11 }, {  0x24d, 12 }, {  0x3da, 12 }, {  0x2dd, 13 },
+    { 0x1f55, 13 }, {  0x5b9, 14 }, { 0x3eae, 14 }, {    0x0,  4 },
+    {   0x10,  5 }, {    0x8,  7 }, {   0x20,  8 }, {   0x29,  9 },
+    {  0x1f4,  9 }, {  0x233, 10 }, {  0x1e0, 11 }, {  0x12a, 12 },
+    {  0x3dd, 12 }, {  0x50a, 13 }, { 0x1f29, 13 }, {  0xa42, 14 },
+    { 0x1272, 15 }, { 0x1737, 15 }, {    0x3,  5 }, {   0x11,  7 },
+    {   0xc4,  8 }, {   0x4b, 10 }, {   0xb4, 11 }, {  0x7d4, 11 },
+    {  0x345, 12 }, {  0x2d7, 13 }, {  0x7bf, 13 }, {  0x938, 14 },
+    {  0xbbb, 14 }, {  0x95e, 15 }, {   0x13,  5 }, {   0x78,  7 },
+    {   0x69,  9 }, {  0x232, 10 }, {  0x461, 11 }, {  0x3ec, 12 },
+    {  0x520, 13 }, { 0x1f2a, 13 }, { 0x3e50, 14 }, { 0x3e51, 14 },
+    { 0x1486, 15 }, {    0xc,  6 }, {   0x24,  9 }, {   0x94, 11 },
+    {  0x8c0, 12 }, {  0xf09, 14 }, { 0x1ef0, 15 }, {   0x3d,  6 },
+    {   0x53,  9 }, {  0x1a0, 11 }, {  0x2d6, 13 }, {  0xf08, 14 },
+    {   0x13,  7 }, {   0x7c,  9 }, {  0x7c1, 11 }, {  0x4ac, 14 },
+    {   0x1b,  7 }, {   0xa0, 10 }, {  0x344, 12 }, {  0xf79, 14 },
+    {   0x79,  7 }, {  0x3e1, 10 }, {  0x2d4, 13 }, { 0x2306, 14 },
+    {   0x21,  8 }, {  0x23c, 10 }, {  0xfae, 12 }, { 0x23de, 14 },
+    {   0x35,  8 }, {  0x175, 11 }, {  0x7b3, 13 }, {   0xc5,  8 },
+    {  0x174, 11 }, {  0x785, 13 }, {   0x48,  9 }, {  0x1a3, 11 },
+    {  0x49e, 13 }, {   0x2c,  9 }, {   0xfa, 10 }, {  0x7d6, 11 },
+    {   0x92, 10 }, {  0x5cc, 13 }, { 0x1ef1, 15 }, {   0xa3, 10 },
+    {  0x3ed, 12 }, {  0x93e, 14 }, {  0x1e2, 11 }, { 0x1273, 15 },
+    {  0x7c4, 11 }, { 0x1487, 15 }, {  0x291, 12 }, {  0x293, 12 },
+    {  0xf8a, 12 }, {  0x509, 13 }, {  0x508, 13 }, {  0x78d, 13 },
+    {  0x7be, 13 }, {  0x78c, 13 }, {  0x4ae, 14 }, {  0xbba, 14 },
+    { 0x2307, 14 }, {  0xb9a, 14 }, { 0x1736, 15 }, {    0xe,  4 },
+    {   0x45,  7 }, {  0x1f3,  9 }, {  0x47a, 11 }, {  0x5dc, 13 },
+    { 0x23df, 14 }, {   0x19,  5 }, {   0x28,  9 }, {  0x176, 11 },
+    {  0x49d, 13 }, { 0x23dd, 14 }, {   0x30,  6 }, {   0xa2, 10 },
+    {  0x2ef, 12 }, {  0x5b8, 14 }, {   0x3f,  6 }, {   0xa5, 10 },
+    {  0x3db, 12 }, {  0x93f, 14 }, {   0x44,  7 }, {  0x7cb, 11 },
+    {  0x95f, 15 }, {   0x63,  7 }, {  0x3c3, 12 }, {   0x15,  8 },
+    {  0x8f6, 12 }, {   0x17,  8 }, {  0x498, 13 }, {   0x2c,  8 },
+    {  0x7b2, 13 }, {   0x2f,  8 }, { 0x1f54, 13 }, {   0x8d,  8 },
+    {  0x7bd, 13 }, {   0x8e,  8 }, { 0x1182, 13 }, {   0xfb,  8 },
+    {  0x50b, 13 }, {   0x2d,  8 }, {  0x7c0, 11 }, {   0x79,  9 },
+    { 0x1f5f, 13 }, {   0x7a,  9 }, { 0x1f56, 13 }, {  0x231, 10 },
+    {  0x3e4, 10 }, {  0x1a1, 11 }, {  0x143, 11 }, {  0x1f7, 11 },
+    {  0x16f, 12 }, {  0x292, 12 }, {  0x2e7, 12 }, {  0x16c, 12 },
+    {  0x16d, 12 }, {  0x3dc, 12 }, {  0xf8b, 12 }, {  0x499, 13 },
+    {  0x3d8, 12 }, {  0x78e, 13 }, {  0x2d5, 13 }, { 0x1f5e, 13 },
+    { 0x1f2b, 13 }, {  0x78f, 13 }, {  0x4ad, 14 }, { 0x3eaf, 14 },
+    { 0x23dc, 14 }, {   0x4a,  9 },
 };
 
 static const int8_t table2_level[185] = {
-  1,  2,  3,  4,  5,  6,  7,  8,
-  9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19,  1,  2,  3,  4,  5,
-  6,  7,  8,  9, 10, 11, 12, 13,
- 14, 15,  1,  2,  3,  4,  5,  6,
-  7,  8,  9, 10, 11, 12,  1,  2,
-  3,  4,  5,  6,  7,  8,  9, 10,
- 11,  1,  2,  3,  4,  5,  6,  1,
-  2,  3,  4,  5,  1,  2,  3,  4,
-  1,  2,  3,  4,  1,  2,  3,  4,
-  1,  2,  3,  4,  1,  2,  3,  1,
-  2,  3,  1,  2,  3,  1,  2,  3,
-  1,  2,  3,  1,  2,  3,  1,  2,
-  1,  2,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  2,  3,  4,  5,  6,  1,  2,  3,
-  4,  5,  1,  2,  3,  4,  1,  2,
-  3,  4,  1,  2,  3,  1,  2,  1,
-  2,  1,  2,  1,  2,  1,  2,  1,
-  2,  1,  2,  1,  2,  1,  2,  1,
-  2,  1,  2,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,
+     1,  2,  3,  4,  5,  6,  7,  8,
+     9, 10, 11, 12, 13, 14, 15, 16,
+    17, 18, 19,  1,  2,  3,  4,  5,
+     6,  7,  8,  9, 10, 11, 12, 13,
+    14, 15,  1,  2,  3,  4,  5,  6,
+     7,  8,  9, 10, 11, 12,  1,  2,
+     3,  4,  5,  6,  7,  8,  9, 10,
+    11,  1,  2,  3,  4,  5,  6,  1,
+     2,  3,  4,  5,  1,  2,  3,  4,
+     1,  2,  3,  4,  1,  2,  3,  4,
+     1,  2,  3,  4,  1,  2,  3,  1,
+     2,  3,  1,  2,  3,  1,  2,  3,
+     1,  2,  3,  1,  2,  3,  1,  2,
+     1,  2,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     2,  3,  4,  5,  6,  1,  2,  3,
+     4,  5,  1,  2,  3,  4,  1,  2,
+     3,  4,  1,  2,  3,  1,  2,  1,
+     2,  1,  2,  1,  2,  1,  2,  1,
+     2,  1,  2,  1,  2,  1,  2,  1,
+     2,  1,  2,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,
 };
 
 static const int8_t table2_run[185] = {
-  0,  0,  0,  0,  0,  0,  0,  0,
-  0,  0,  0,  0,  0,  0,  0,  0,
-  0,  0,  0,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  2,  2,  2,  2,  2,  2,
-  2,  2,  2,  2,  2,  2,  3,  3,
-  3,  3,  3,  3,  3,  3,  3,  3,
-  3,  4,  4,  4,  4,  4,  4,  5,
-  5,  5,  5,  5,  6,  6,  6,  6,
-  7,  7,  7,  7,  8,  8,  8,  8,
-  9,  9,  9,  9, 10, 10, 10, 11,
- 11, 11, 12, 12, 12, 13, 13, 13,
- 14, 14, 14, 15, 15, 15, 16, 16,
- 17, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30,  0,
-  0,  0,  0,  0,  0,  1,  1,  1,
-  1,  1,  2,  2,  2,  2,  3,  3,
-  3,  3,  4,  4,  4,  5,  5,  6,
-  6,  7,  7,  8,  8,  9,  9, 10,
- 10, 11, 11, 12, 12, 13, 13, 14,
- 14, 15, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36,
- 37,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  2,  2,  2,  2,  2,  2,
+     2,  2,  2,  2,  2,  2,  3,  3,
+     3,  3,  3,  3,  3,  3,  3,  3,
+     3,  4,  4,  4,  4,  4,  4,  5,
+     5,  5,  5,  5,  6,  6,  6,  6,
+     7,  7,  7,  7,  8,  8,  8,  8,
+     9,  9,  9,  9, 10, 10, 10, 11,
+    11, 11, 12, 12, 12, 13, 13, 13,
+    14, 14, 14, 15, 15, 15, 16, 16,
+    17, 17, 18, 19, 20, 21, 22, 23,
+    24, 25, 26, 27, 28, 29, 30,  0,
+     0,  0,  0,  0,  0,  1,  1,  1,
+     1,  1,  2,  2,  2,  2,  3,  3,
+     3,  3,  4,  4,  4,  5,  5,  6,
+     6,  7,  7,  8,  8,  9,  9, 10,
+    10, 11, 11, 12, 12, 13, 13, 14,
+    14, 15, 15, 16, 17, 18, 19, 20,
+    21, 22, 23, 24, 25, 26, 27, 28,
+    29, 30, 31, 32, 33, 34, 35, 36,
+    37,
 };
 
 /* second non intra vlc table */
 static const uint16_t table4_vlc[169][2] = {
-{    0x0,  3 },{    0x3,  4 },{    0xb,  5 },{   0x14,  6 },
-{   0x3f,  6 },{   0x5d,  7 },{   0xa2,  8 },{   0xac,  9 },
-{  0x16e,  9 },{  0x20a, 10 },{  0x2e2, 10 },{  0x432, 11 },
-{  0x5c9, 11 },{  0x827, 12 },{  0xb54, 12 },{  0x4e6, 13 },
-{ 0x105f, 13 },{ 0x172a, 13 },{ 0x20b2, 14 },{ 0x2d4e, 14 },
-{ 0x39f0, 14 },{ 0x4175, 15 },{ 0x5a9e, 15 },{    0x4,  4 },
-{   0x1e,  5 },{   0x42,  7 },{   0xb6,  8 },{  0x173,  9 },
-{  0x395, 10 },{  0x72e, 11 },{  0xb94, 12 },{ 0x16a4, 13 },
-{ 0x20b3, 14 },{ 0x2e45, 14 },{    0x5,  5 },{   0x40,  7 },
-{   0x49,  9 },{  0x28f, 10 },{  0x5cb, 11 },{  0x48a, 13 },
-{  0x9dd, 14 },{ 0x73e2, 15 },{   0x18,  5 },{   0x25,  8 },
-{   0x8a, 10 },{  0x51b, 11 },{  0xe5f, 12 },{  0x9c9, 14 },
-{ 0x139c, 15 },{   0x29,  6 },{   0x4f,  9 },{  0x412, 11 },
-{  0x48d, 13 },{ 0x2e41, 14 },{   0x38,  6 },{  0x10e,  9 },
-{  0x5a8, 11 },{ 0x105c, 13 },{ 0x39f2, 14 },{   0x58,  7 },
-{  0x21f, 10 },{  0xe7e, 12 },{ 0x39ff, 14 },{   0x23,  8 },
-{  0x2e3, 10 },{  0x4e5, 13 },{ 0x2e40, 14 },{   0xa1,  8 },
-{  0x5be, 11 },{  0x9c8, 14 },{   0x83,  8 },{  0x13a, 11 },
-{ 0x1721, 13 },{   0x44,  9 },{  0x276, 12 },{ 0x39f6, 14 },
-{   0x8b, 10 },{  0x4ef, 13 },{ 0x5a9b, 15 },{  0x208, 10 },
-{ 0x1cfe, 13 },{  0x399, 10 },{ 0x1cb4, 13 },{  0x39e, 10 },
-{ 0x39f3, 14 },{  0x5ab, 11 },{ 0x73e3, 15 },{  0x737, 11 },
-{ 0x5a9f, 15 },{  0x82d, 12 },{  0xe69, 12 },{  0xe68, 12 },
-{  0x433, 11 },{  0xb7b, 12 },{ 0x2df8, 14 },{ 0x2e56, 14 },
-{ 0x2e57, 14 },{ 0x39f7, 14 },{ 0x51a5, 15 },{    0x3,  3 },
-{   0x2a,  6 },{   0xe4,  8 },{  0x28e, 10 },{  0x735, 11 },
-{ 0x1058, 13 },{ 0x1cfa, 13 },{ 0x2df9, 14 },{ 0x4174, 15 },
-{    0x9,  4 },{   0x54,  8 },{  0x398, 10 },{  0x48b, 13 },
-{ 0x139d, 15 },{    0xd,  4 },{   0xad,  9 },{  0x826, 12 },
-{ 0x2d4c, 14 },{   0x11,  5 },{  0x16b,  9 },{  0xb7f, 12 },
-{ 0x51a4, 15 },{   0x19,  5 },{  0x21b, 10 },{ 0x16fd, 13 },
-{   0x1d,  5 },{  0x394, 10 },{ 0x28d3, 14 },{   0x2b,  6 },
-{  0x5bc, 11 },{ 0x5a9a, 15 },{   0x2f,  6 },{  0x247, 12 },
-{   0x10,  7 },{  0xa35, 12 },{   0x3e,  6 },{  0xb7a, 12 },
-{   0x59,  7 },{ 0x105e, 13 },{   0x26,  8 },{  0x9cf, 14 },
-{   0x55,  8 },{ 0x1cb5, 13 },{   0x57,  8 },{  0xe5b, 12 },
-{   0xa0,  8 },{ 0x1468, 13 },{  0x170,  9 },{   0x90, 10 },
-{  0x1ce,  9 },{  0x21a, 10 },{  0x218, 10 },{  0x168,  9 },
-{  0x21e, 10 },{  0x244, 12 },{  0x736, 11 },{  0x138, 11 },
-{  0x519, 11 },{  0xe5e, 12 },{  0x72c, 11 },{  0xb55, 12 },
-{  0x9dc, 14 },{ 0x20bb, 14 },{  0x48c, 13 },{ 0x1723, 13 },
-{ 0x2e44, 14 },{ 0x16a5, 13 },{  0x518, 11 },{ 0x39fe, 14 },
-{  0x169,  9 },
+    {    0x0,  3 }, {    0x3,  4 }, {    0xb,  5 }, {   0x14,  6 },
+    {   0x3f,  6 }, {   0x5d,  7 }, {   0xa2,  8 }, {   0xac,  9 },
+    {  0x16e,  9 }, {  0x20a, 10 }, {  0x2e2, 10 }, {  0x432, 11 },
+    {  0x5c9, 11 }, {  0x827, 12 }, {  0xb54, 12 }, {  0x4e6, 13 },
+    { 0x105f, 13 }, { 0x172a, 13 }, { 0x20b2, 14 }, { 0x2d4e, 14 },
+    { 0x39f0, 14 }, { 0x4175, 15 }, { 0x5a9e, 15 }, {    0x4,  4 },
+    {   0x1e,  5 }, {   0x42,  7 }, {   0xb6,  8 }, {  0x173,  9 },
+    {  0x395, 10 }, {  0x72e, 11 }, {  0xb94, 12 }, { 0x16a4, 13 },
+    { 0x20b3, 14 }, { 0x2e45, 14 }, {    0x5,  5 }, {   0x40,  7 },
+    {   0x49,  9 }, {  0x28f, 10 }, {  0x5cb, 11 }, {  0x48a, 13 },
+    {  0x9dd, 14 }, { 0x73e2, 15 }, {   0x18,  5 }, {   0x25,  8 },
+    {   0x8a, 10 }, {  0x51b, 11 }, {  0xe5f, 12 }, {  0x9c9, 14 },
+    { 0x139c, 15 }, {   0x29,  6 }, {   0x4f,  9 }, {  0x412, 11 },
+    {  0x48d, 13 }, { 0x2e41, 14 }, {   0x38,  6 }, {  0x10e,  9 },
+    {  0x5a8, 11 }, { 0x105c, 13 }, { 0x39f2, 14 }, {   0x58,  7 },
+    {  0x21f, 10 }, {  0xe7e, 12 }, { 0x39ff, 14 }, {   0x23,  8 },
+    {  0x2e3, 10 }, {  0x4e5, 13 }, { 0x2e40, 14 }, {   0xa1,  8 },
+    {  0x5be, 11 }, {  0x9c8, 14 }, {   0x83,  8 }, {  0x13a, 11 },
+    { 0x1721, 13 }, {   0x44,  9 }, {  0x276, 12 }, { 0x39f6, 14 },
+    {   0x8b, 10 }, {  0x4ef, 13 }, { 0x5a9b, 15 }, {  0x208, 10 },
+    { 0x1cfe, 13 }, {  0x399, 10 }, { 0x1cb4, 13 }, {  0x39e, 10 },
+    { 0x39f3, 14 }, {  0x5ab, 11 }, { 0x73e3, 15 }, {  0x737, 11 },
+    { 0x5a9f, 15 }, {  0x82d, 12 }, {  0xe69, 12 }, {  0xe68, 12 },
+    {  0x433, 11 }, {  0xb7b, 12 }, { 0x2df8, 14 }, { 0x2e56, 14 },
+    { 0x2e57, 14 }, { 0x39f7, 14 }, { 0x51a5, 15 }, {    0x3,  3 },
+    {   0x2a,  6 }, {   0xe4,  8 }, {  0x28e, 10 }, {  0x735, 11 },
+    { 0x1058, 13 }, { 0x1cfa, 13 }, { 0x2df9, 14 }, { 0x4174, 15 },
+    {    0x9,  4 }, {   0x54,  8 }, {  0x398, 10 }, {  0x48b, 13 },
+    { 0x139d, 15 }, {    0xd,  4 }, {   0xad,  9 }, {  0x826, 12 },
+    { 0x2d4c, 14 }, {   0x11,  5 }, {  0x16b,  9 }, {  0xb7f, 12 },
+    { 0x51a4, 15 }, {   0x19,  5 }, {  0x21b, 10 }, { 0x16fd, 13 },
+    {   0x1d,  5 }, {  0x394, 10 }, { 0x28d3, 14 }, {   0x2b,  6 },
+    {  0x5bc, 11 }, { 0x5a9a, 15 }, {   0x2f,  6 }, {  0x247, 12 },
+    {   0x10,  7 }, {  0xa35, 12 }, {   0x3e,  6 }, {  0xb7a, 12 },
+    {   0x59,  7 }, { 0x105e, 13 }, {   0x26,  8 }, {  0x9cf, 14 },
+    {   0x55,  8 }, { 0x1cb5, 13 }, {   0x57,  8 }, {  0xe5b, 12 },
+    {   0xa0,  8 }, { 0x1468, 13 }, {  0x170,  9 }, {   0x90, 10 },
+    {  0x1ce,  9 }, {  0x21a, 10 }, {  0x218, 10 }, {  0x168,  9 },
+    {  0x21e, 10 }, {  0x244, 12 }, {  0x736, 11 }, {  0x138, 11 },
+    {  0x519, 11 }, {  0xe5e, 12 }, {  0x72c, 11 }, {  0xb55, 12 },
+    {  0x9dc, 14 }, { 0x20bb, 14 }, {  0x48c, 13 }, { 0x1723, 13 },
+    { 0x2e44, 14 }, { 0x16a5, 13 }, {  0x518, 11 }, { 0x39fe, 14 },
+    {  0x169,  9 },
 };
 
 static const int8_t table4_level[168] = {
-  1,  2,  3,  4,  5,  6,  7,  8,
-  9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23,  1,
-  2,  3,  4,  5,  6,  7,  8,  9,
- 10, 11,  1,  2,  3,  4,  5,  6,
-  7,  8,  1,  2,  3,  4,  5,  6,
-  7,  1,  2,  3,  4,  5,  1,  2,
-  3,  4,  5,  1,  2,  3,  4,  1,
-  2,  3,  4,  1,  2,  3,  1,  2,
-  3,  1,  2,  3,  1,  2,  3,  1,
-  2,  1,  2,  1,  2,  1,  2,  1,
-  2,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  2,  3,  4,  5,
-  6,  7,  8,  9,  1,  2,  3,  4,
-  5,  1,  2,  3,  4,  1,  2,  3,
-  4,  1,  2,  3,  1,  2,  3,  1,
-  2,  3,  1,  2,  1,  2,  1,  2,
-  1,  2,  1,  2,  1,  2,  1,  2,
-  1,  2,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
+     1,  2,  3,  4,  5,  6,  7,  8,
+     9, 10, 11, 12, 13, 14, 15, 16,
+    17, 18, 19, 20, 21, 22, 23,  1,
+     2,  3,  4,  5,  6,  7,  8,  9,
+    10, 11,  1,  2,  3,  4,  5,  6,
+     7,  8,  1,  2,  3,  4,  5,  6,
+     7,  1,  2,  3,  4,  5,  1,  2,
+     3,  4,  5,  1,  2,  3,  4,  1,
+     2,  3,  4,  1,  2,  3,  1,  2,
+     3,  1,  2,  3,  1,  2,  3,  1,
+     2,  1,  2,  1,  2,  1,  2,  1,
+     2,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  2,  3,  4,  5,
+     6,  7,  8,  9,  1,  2,  3,  4,
+     5,  1,  2,  3,  4,  1,  2,  3,
+     4,  1,  2,  3,  1,  2,  3,  1,
+     2,  3,  1,  2,  1,  2,  1,  2,
+     1,  2,  1,  2,  1,  2,  1,  2,
+     1,  2,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
 };
 
 static const int8_t table4_run[168] = {
-  0,  0,  0,  0,  0,  0,  0,  0,
-  0,  0,  0,  0,  0,  0,  0,  0,
-  0,  0,  0,  0,  0,  0,  0,  1,
-  1,  1,  1,  1,  1,  1,  1,  1,
-  1,  1,  2,  2,  2,  2,  2,  2,
-  2,  2,  3,  3,  3,  3,  3,  3,
-  3,  4,  4,  4,  4,  4,  5,  5,
-  5,  5,  5,  6,  6,  6,  6,  7,
-  7,  7,  7,  8,  8,  8,  9,  9,
-  9, 10, 10, 10, 11, 11, 11, 12,
- 12, 13, 13, 14, 14, 15, 15, 16,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26,  0,  0,  0,  0,  0,
-  0,  0,  0,  0,  1,  1,  1,  1,
-  1,  2,  2,  2,  2,  3,  3,  3,
-  3,  4,  4,  4,  5,  5,  5,  6,
-  6,  6,  7,  7,  8,  8,  9,  9,
- 10, 10, 11, 11, 12, 12, 13, 13,
- 14, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  2,  2,  2,  2,  2,  2,
+     2,  2,  3,  3,  3,  3,  3,  3,
+     3,  4,  4,  4,  4,  4,  5,  5,
+     5,  5,  5,  6,  6,  6,  6,  7,
+     7,  7,  7,  8,  8,  8,  9,  9,
+     9, 10, 10, 10, 11, 11, 11, 12,
+    12, 13, 13, 14, 14, 15, 15, 16,
+    16, 17, 18, 19, 20, 21, 22, 23,
+    24, 25, 26,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  1,  1,  1,  1,
+     1,  2,  2,  2,  2,  3,  3,  3,
+     3,  4,  4,  4,  5,  5,  5,  6,
+     6,  6,  7,  7,  8,  8,  9,  9,
+    10, 10, 11, 11, 12, 12, 13, 13,
+    14, 14, 15, 16, 17, 18, 19, 20,
+    21, 22, 23, 24, 25, 26, 27, 28,
+    29, 30, 31, 32, 33, 34, 35, 36,
 };
 
 RLTable ff_rl_table[NB_RL_TABLES] = {
     /* intra luminance tables */
     /* low motion  */
-    {
-        132,
-        85,
-        table0_vlc,
-        table0_run,
-        table0_level,
-    },
+    { 132,
+      85,
+      table0_vlc,
+      table0_run,
+      table0_level, },
     /* high motion */
-    {
-        185,
-        119,
-        table2_vlc,
-        table2_run,
-        table2_level,
-    },
+    { 185,
+      119,
+      table2_vlc,
+      table2_run,
+      table2_level, },
     /* mid-rate */
-    {
-        102,
-        67,
-        ff_mpeg4_intra_vlc,
-        ff_mpeg4_intra_run,
-        ff_mpeg4_intra_level,
-    },
+    { 102,
+      67,
+      ff_mpeg4_intra_vlc,
+      ff_mpeg4_intra_run,
+      ff_mpeg4_intra_level, },
     /* intra chrominance / non intra tables */
     /* low motion inter */
-    {
-        148,
-        81,
-        table1_vlc,
-        table1_run,
-        table1_level,
-    },
+    { 148,
+      81,
+      table1_vlc,
+      table1_run,
+      table1_level, },
     /* high motion inter */
-    {
-        168,
-        99,
-        table4_vlc,
-        table4_run,
-        table4_level,
-    },
+    { 168,
+      99,
+      table4_vlc,
+      table4_run,
+      table4_level, },
     /* mid rate inter */
-    {
-        102,
-        58,
-        ff_inter_vlc,
-        ff_inter_run,
-        ff_inter_level,
-    },
+    { 102,
+      58,
+      ff_inter_vlc,
+      ff_inter_run,
+      ff_inter_level, },
 };
 
 /* motion vector table 0 */
 
 static const uint16_t table0_mv_code[1100] = {
- 0x0001, 0x0003, 0x0005, 0x0007, 0x0003, 0x0008, 0x000c, 0x0001,
- 0x0002, 0x001b, 0x0006, 0x000b, 0x0015, 0x0002, 0x000e, 0x000f,
- 0x0014, 0x0020, 0x0022, 0x0025, 0x0027, 0x0029, 0x002d, 0x004b,
- 0x004d, 0x0003, 0x0022, 0x0023, 0x0025, 0x0027, 0x0042, 0x0048,
- 0x0049, 0x0050, 0x005c, 0x0091, 0x009f, 0x000e, 0x0043, 0x004c,
- 0x0054, 0x0056, 0x008c, 0x0098, 0x009a, 0x009b, 0x00b1, 0x00b2,
- 0x0120, 0x0121, 0x0126, 0x0133, 0x0139, 0x01a1, 0x01a4, 0x01a5,
- 0x01a6, 0x01a7, 0x01ae, 0x01af, 0x000b, 0x0019, 0x0085, 0x0090,
- 0x009b, 0x00aa, 0x00af, 0x010c, 0x010e, 0x011c, 0x011e, 0x0133,
- 0x0144, 0x0160, 0x0174, 0x0175, 0x0177, 0x0178, 0x0249, 0x024b,
- 0x0252, 0x0261, 0x0265, 0x0270, 0x0352, 0x0353, 0x0355, 0x0359,
- 0x0010, 0x0011, 0x0013, 0x0034, 0x0035, 0x0036, 0x0037, 0x003d,
- 0x003e, 0x0109, 0x0126, 0x0156, 0x021a, 0x021e, 0x023a, 0x023e,
- 0x028e, 0x028f, 0x02cf, 0x0491, 0x0494, 0x049f, 0x04a0, 0x04a3,
- 0x04a6, 0x04a7, 0x04ad, 0x04ae, 0x04c0, 0x04c4, 0x04c6, 0x04c8,
- 0x04c9, 0x04f5, 0x04f6, 0x04f7, 0x0680, 0x0682, 0x0683, 0x0688,
- 0x0689, 0x068d, 0x068e, 0x068f, 0x06a2, 0x06a3, 0x06a9, 0x06b0,
- 0x06b1, 0x06b4, 0x06b5, 0x0024, 0x0060, 0x0063, 0x0078, 0x0079,
- 0x0211, 0x0244, 0x0245, 0x0247, 0x0248, 0x0249, 0x024a, 0x024b,
- 0x026b, 0x02af, 0x02b8, 0x02bb, 0x0436, 0x0476, 0x0477, 0x047e,
- 0x04c8, 0x04c9, 0x04ca, 0x0514, 0x0586, 0x0587, 0x0598, 0x059d,
- 0x05d9, 0x05da, 0x0920, 0x0921, 0x093b, 0x093c, 0x093d, 0x0942,
- 0x0943, 0x0944, 0x0945, 0x0959, 0x095e, 0x095f, 0x0982, 0x0983,
- 0x098e, 0x098f, 0x09c4, 0x09e7, 0x09e8, 0x09e9, 0x0d02, 0x0d17,
- 0x0d18, 0x0d19, 0x0d41, 0x0d42, 0x0d43, 0x0d50, 0x0d5f, 0x0d6d,
- 0x0d6e, 0x0d6f, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
- 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x041e, 0x041f, 0x0420, 0x0421,
- 0x048c, 0x048d, 0x04d3, 0x04d4, 0x04d5, 0x055c, 0x055d, 0x0572,
- 0x0573, 0x0574, 0x0575, 0x08de, 0x08df, 0x08fe, 0x08ff, 0x0996,
- 0x0a36, 0x0a37, 0x0b08, 0x0b09, 0x0b0a, 0x0b0b, 0x0b32, 0x0b33,
- 0x0b34, 0x0b35, 0x0b36, 0x0b37, 0x0b38, 0x0b39, 0x0bb0, 0x0bf7,
- 0x0bf8, 0x0bf9, 0x0bfa, 0x0bfb, 0x0bfc, 0x0bfd, 0x0bfe, 0x0bff,
- 0x1254, 0x1255, 0x1256, 0x1257, 0x1270, 0x1271, 0x1272, 0x1273,
- 0x1274, 0x1275, 0x12ab, 0x12ac, 0x12ad, 0x12ae, 0x12af, 0x12b0,
- 0x12b1, 0x1315, 0x1316, 0x1317, 0x13bf, 0x13c0, 0x13c1, 0x13c2,
- 0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, 0x13c8, 0x13c9, 0x13ca,
- 0x13cb, 0x13cc, 0x13cd, 0x1a06, 0x1a07, 0x1a28, 0x1a29, 0x1a2a,
- 0x1a2b, 0x1a2c, 0x1a2d, 0x1a80, 0x1abb, 0x1abc, 0x1abd, 0x1ad8,
- 0x1ad9, 0x0094, 0x0095, 0x0096, 0x0097, 0x00a0, 0x00a1, 0x00a2,
- 0x00a3, 0x0831, 0x0832, 0x0833, 0x0834, 0x0835, 0x0836, 0x0837,
- 0x0838, 0x0839, 0x083a, 0x083b, 0x0939, 0x093a, 0x093b, 0x093c,
- 0x093d, 0x093e, 0x093f, 0x09a0, 0x09a1, 0x09a2, 0x09a3, 0x09a4,
- 0x09a5, 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2,
- 0x11b3, 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba,
- 0x11bb, 0x132f, 0x1454, 0x1455, 0x1456, 0x1457, 0x1458, 0x1459,
- 0x145a, 0x145b, 0x145c, 0x145d, 0x145e, 0x145f, 0x1460, 0x1461,
- 0x1462, 0x1463, 0x1464, 0x1465, 0x1466, 0x1467, 0x1468, 0x1469,
- 0x146a, 0x146b, 0x17de, 0x17df, 0x17e0, 0x17e1, 0x17e2, 0x17e3,
- 0x17e4, 0x17e5, 0x17e6, 0x17e7, 0x17e8, 0x17e9, 0x17ea, 0x17eb,
- 0x17ec, 0x17ed, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545,
- 0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d,
- 0x254e, 0x254f, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555,
- 0x2628, 0x2766, 0x2767, 0x2768, 0x2769, 0x276a, 0x276b, 0x276c,
- 0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2772, 0x2773, 0x2774,
- 0x2775, 0x2776, 0x2777, 0x2778, 0x2779, 0x277a, 0x277b, 0x277c,
- 0x277d, 0x3503, 0x3544, 0x3545, 0x3546, 0x3547, 0x3560, 0x3561,
- 0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569,
- 0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f, 0x3570, 0x3571,
- 0x3572, 0x3573, 0x3574, 0x3575, 0x03f0, 0x103d, 0x103e, 0x103f,
- 0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
- 0x1048, 0x1049, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f,
- 0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
- 0x1058, 0x1059, 0x105a, 0x105b, 0x105c, 0x105d, 0x105e, 0x105f,
- 0x1060, 0x1061, 0x1270, 0x1271, 0x21b8, 0x21b9, 0x21ba, 0x21bb,
- 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x21f0, 0x21f1, 0x21f2, 0x21f3,
- 0x21f4, 0x21f5, 0x21f6, 0x21f7, 0x21f8, 0x21f9, 0x21fa, 0x21fb,
- 0x21fc, 0x21fd, 0x21fe, 0x21ff, 0x2340, 0x2341, 0x2342, 0x2343,
- 0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234a, 0x234b,
- 0x234c, 0x234d, 0x234e, 0x234f, 0x2350, 0x2351, 0x2352, 0x2353,
- 0x2354, 0x2355, 0x2356, 0x2357, 0x265c, 0x2f88, 0x2f89, 0x2f8a,
- 0x2f8b, 0x2f8c, 0x2f8d, 0x2f8e, 0x2f8f, 0x2f90, 0x2f91, 0x2f92,
- 0x2f93, 0x2f94, 0x2f95, 0x2f96, 0x2f97, 0x2f98, 0x2f99, 0x2f9a,
- 0x2f9b, 0x2f9c, 0x2f9d, 0x2f9e, 0x2f9f, 0x2fa0, 0x2fa1, 0x2fa2,
- 0x2fa3, 0x2fa4, 0x2fa5, 0x2fa6, 0x2fa7, 0x2fa8, 0x2fa9, 0x2faa,
- 0x2fab, 0x2fac, 0x2fad, 0x2fae, 0x2faf, 0x2fb0, 0x2fb1, 0x2fb2,
- 0x2fb3, 0x2fb4, 0x2fb5, 0x2fb6, 0x2fb7, 0x2fb8, 0x2fb9, 0x2fba,
- 0x2fbb, 0x4c52, 0x4c53, 0x4e28, 0x4e29, 0x4e2a, 0x4e2b, 0x4e2c,
- 0x4e2d, 0x4e2e, 0x4e2f, 0x4e30, 0x4e31, 0x4e32, 0x4e33, 0x4e34,
- 0x4e35, 0x4e36, 0x4e37, 0x4e38, 0x4e39, 0x4e3a, 0x4e3b, 0x4e3c,
- 0x4e3d, 0x4e3e, 0x4e3f, 0x4e80, 0x4e81, 0x4e82, 0x4e83, 0x4e84,
- 0x4e85, 0x4e86, 0x4e87, 0x4e88, 0x4e89, 0x4e8a, 0x4e8b, 0x4e8c,
- 0x4e8d, 0x4e8e, 0x4e8f, 0x4e90, 0x4e91, 0x4e92, 0x4e93, 0x4e94,
- 0x4e95, 0x4e96, 0x4e97, 0x4e98, 0x4e99, 0x4e9a, 0x4e9b, 0x4e9c,
- 0x4e9d, 0x4e9e, 0x4e9f, 0x4ea0, 0x4ea1, 0x4ea2, 0x4ea3, 0x4ea4,
- 0x4ea5, 0x4ea6, 0x4ea7, 0x4ea8, 0x4ea9, 0x4eaa, 0x4eab, 0x4eac,
- 0x4ead, 0x4eae, 0x4eaf, 0x4eb0, 0x4eb1, 0x4eb2, 0x4eb3, 0x4eb4,
- 0x4eb5, 0x4eb6, 0x4eb7, 0x4eb8, 0x4eb9, 0x4eba, 0x4ebb, 0x4ebc,
- 0x4ebd, 0x4ebe, 0x4ebf, 0x4ec0, 0x4ec1, 0x4ec2, 0x4ec3, 0x4ec4,
- 0x4ec5, 0x4ec6, 0x4ec7, 0x4ec8, 0x4ec9, 0x4eca, 0x4ecb, 0x6a04,
- 0x6a05, 0x07e2, 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8,
- 0x07e9, 0x07ea, 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0,
- 0x07f1, 0x07f2, 0x07f3, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8,
- 0x07f9, 0x07fa, 0x07fb, 0x07fc, 0x07fd, 0x07fe, 0x07ff, 0x2000,
- 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
- 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x200e, 0x200f, 0x2010,
- 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018,
- 0x2019, 0x201a, 0x201b, 0x201c, 0x201d, 0x201e, 0x201f, 0x2020,
- 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2028,
- 0x2029, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e, 0x202f, 0x2030,
- 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038,
- 0x2039, 0x203a, 0x203b, 0x203c, 0x203d, 0x203e, 0x203f, 0x2040,
- 0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, 0x2048,
- 0x2049, 0x204a, 0x204b, 0x204c, 0x204d, 0x204e, 0x204f, 0x2050,
- 0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058,
- 0x2059, 0x205a, 0x205b, 0x205c, 0x205d, 0x205e, 0x205f, 0x2060,
- 0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, 0x2068,
- 0x2069, 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0x2070,
- 0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078,
- 0x2079, 0x4cba, 0x4cbb, 0x5d88, 0x5d89, 0x5d8a, 0x5d8b, 0x5d8c,
- 0x5d8d, 0x5d8e, 0x5d8f, 0x5db0, 0x5db1, 0x5db2, 0x5db3, 0x5db4,
- 0x5db5, 0x5db6, 0x5db7, 0x5db8, 0x5db9, 0x5dba, 0x5dbb, 0x5dbc,
- 0x5dbd, 0x5dbe, 0x5dbf, 0x5e40, 0x5e41, 0x5e42, 0x5e43, 0x5e44,
- 0x5e45, 0x5e46, 0x5e47, 0x5e48, 0x5e49, 0x5e4a, 0x5e4b, 0x5e4c,
- 0x5e4d, 0x5e4e, 0x5e4f, 0x5e50, 0x5e51, 0x5e52, 0x5e53, 0x5e54,
- 0x5e55, 0x5e56, 0x5e57, 0x5e58, 0x5e59, 0x5e5a, 0x5e5b, 0x5e5c,
- 0x5e5d, 0x5e5e, 0x5e5f, 0x5e60, 0x5e61, 0x5e62, 0x5e63, 0x5e64,
- 0x5e65, 0x5e66, 0x5e67, 0x5e68, 0x5e69, 0x5e6a, 0x5e6b, 0x5e6c,
- 0x5e6d, 0x5e6e, 0x5e6f, 0x5e70, 0x5e71, 0x5e72, 0x5e73, 0x5e74,
- 0x5e75, 0x5e76, 0x5e77, 0x5e78, 0x5e79, 0x5e7a, 0x5e7b, 0x5e7c,
- 0x5e7d, 0x5e7e, 0x5e7f, 0x5e80, 0x5e81, 0x5e82, 0x5e83, 0x5e84,
- 0x5e85, 0x5e86, 0x5e87, 0x5e88, 0x5e89, 0x5e8a, 0x5e8b, 0x5e8c,
- 0x5e8d, 0x5e8e, 0x5e8f, 0x5e90, 0x5e91, 0x5e92, 0x5e93, 0x5e94,
- 0x5e95, 0x5e96, 0x5e97, 0x5e98, 0x5e99, 0x5e9a, 0x5e9b, 0x5e9c,
- 0x5e9d, 0x5e9e, 0x5e9f, 0x5ea0, 0x5ea1, 0x5ea2, 0x5ea3, 0x5ea4,
- 0x5ea5, 0x5ea6, 0x5ea7, 0x5ea8, 0x5ea9, 0x5eaa, 0x5eab, 0x5eac,
- 0x5ead, 0x5eae, 0x5eaf, 0x5eb0, 0x5eb1, 0x5eb2, 0x5eb3, 0x5eb4,
- 0x5eb5, 0x5eb6, 0x5eb7, 0x5eb8, 0x5eb9, 0x5eba, 0x5ebb, 0x5ebc,
- 0x5ebd, 0x5ebe, 0x5ebf, 0x5ec0, 0x5ec1, 0x5ec2, 0x5ec3, 0x5ec4,
- 0x5ec5, 0x5ec6, 0x5ec7, 0x5ec8, 0x5ec9, 0x5eca, 0x5ecb, 0x5ecc,
- 0x5ecd, 0x5ece, 0x5ecf, 0x5ed0, 0x5ed1, 0x5ed2, 0x5ed3, 0x5ed4,
- 0x5ed5, 0x5ed6, 0x5ed7, 0x5ed8, 0x5ed9, 0x5eda, 0x5edb, 0x5edc,
- 0x5edd, 0x5ede, 0x5edf, 0x5ee0, 0x5ee1, 0x5ee2, 0x5ee3, 0x5ee4,
- 0x5ee5, 0x5ee6, 0x5ee7, 0x5ee8, 0x5ee9, 0x5eea, 0x5eeb, 0x5eec,
- 0x5eed, 0x5eee, 0x5eef, 0x5ef0, 0x5ef1, 0x5ef2, 0x5ef3, 0x5ef4,
- 0x5ef5, 0x5ef6, 0x5ef7, 0x5ef8, 0x5ef9, 0x5efa, 0x5efb, 0x5efc,
- 0x5efd, 0x5efe, 0x5eff, 0x5f00, 0x5f01, 0x5f02, 0x5f03, 0x5f04,
- 0x5f05, 0x5f06, 0x5f07, 0x5f08, 0x5f09, 0x5f0a, 0x5f0b, 0x5f0c,
- 0x5f0d, 0x5f0e, 0x5f0f, 0x0000,
+    0x0001, 0x0003, 0x0005, 0x0007, 0x0003, 0x0008, 0x000c, 0x0001,
+    0x0002, 0x001b, 0x0006, 0x000b, 0x0015, 0x0002, 0x000e, 0x000f,
+    0x0014, 0x0020, 0x0022, 0x0025, 0x0027, 0x0029, 0x002d, 0x004b,
+    0x004d, 0x0003, 0x0022, 0x0023, 0x0025, 0x0027, 0x0042, 0x0048,
+    0x0049, 0x0050, 0x005c, 0x0091, 0x009f, 0x000e, 0x0043, 0x004c,
+    0x0054, 0x0056, 0x008c, 0x0098, 0x009a, 0x009b, 0x00b1, 0x00b2,
+    0x0120, 0x0121, 0x0126, 0x0133, 0x0139, 0x01a1, 0x01a4, 0x01a5,
+    0x01a6, 0x01a7, 0x01ae, 0x01af, 0x000b, 0x0019, 0x0085, 0x0090,
+    0x009b, 0x00aa, 0x00af, 0x010c, 0x010e, 0x011c, 0x011e, 0x0133,
+    0x0144, 0x0160, 0x0174, 0x0175, 0x0177, 0x0178, 0x0249, 0x024b,
+    0x0252, 0x0261, 0x0265, 0x0270, 0x0352, 0x0353, 0x0355, 0x0359,
+    0x0010, 0x0011, 0x0013, 0x0034, 0x0035, 0x0036, 0x0037, 0x003d,
+    0x003e, 0x0109, 0x0126, 0x0156, 0x021a, 0x021e, 0x023a, 0x023e,
+    0x028e, 0x028f, 0x02cf, 0x0491, 0x0494, 0x049f, 0x04a0, 0x04a3,
+    0x04a6, 0x04a7, 0x04ad, 0x04ae, 0x04c0, 0x04c4, 0x04c6, 0x04c8,
+    0x04c9, 0x04f5, 0x04f6, 0x04f7, 0x0680, 0x0682, 0x0683, 0x0688,
+    0x0689, 0x068d, 0x068e, 0x068f, 0x06a2, 0x06a3, 0x06a9, 0x06b0,
+    0x06b1, 0x06b4, 0x06b5, 0x0024, 0x0060, 0x0063, 0x0078, 0x0079,
+    0x0211, 0x0244, 0x0245, 0x0247, 0x0248, 0x0249, 0x024a, 0x024b,
+    0x026b, 0x02af, 0x02b8, 0x02bb, 0x0436, 0x0476, 0x0477, 0x047e,
+    0x04c8, 0x04c9, 0x04ca, 0x0514, 0x0586, 0x0587, 0x0598, 0x059d,
+    0x05d9, 0x05da, 0x0920, 0x0921, 0x093b, 0x093c, 0x093d, 0x0942,
+    0x0943, 0x0944, 0x0945, 0x0959, 0x095e, 0x095f, 0x0982, 0x0983,
+    0x098e, 0x098f, 0x09c4, 0x09e7, 0x09e8, 0x09e9, 0x0d02, 0x0d17,
+    0x0d18, 0x0d19, 0x0d41, 0x0d42, 0x0d43, 0x0d50, 0x0d5f, 0x0d6d,
+    0x0d6e, 0x0d6f, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+    0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x041e, 0x041f, 0x0420, 0x0421,
+    0x048c, 0x048d, 0x04d3, 0x04d4, 0x04d5, 0x055c, 0x055d, 0x0572,
+    0x0573, 0x0574, 0x0575, 0x08de, 0x08df, 0x08fe, 0x08ff, 0x0996,
+    0x0a36, 0x0a37, 0x0b08, 0x0b09, 0x0b0a, 0x0b0b, 0x0b32, 0x0b33,
+    0x0b34, 0x0b35, 0x0b36, 0x0b37, 0x0b38, 0x0b39, 0x0bb0, 0x0bf7,
+    0x0bf8, 0x0bf9, 0x0bfa, 0x0bfb, 0x0bfc, 0x0bfd, 0x0bfe, 0x0bff,
+    0x1254, 0x1255, 0x1256, 0x1257, 0x1270, 0x1271, 0x1272, 0x1273,
+    0x1274, 0x1275, 0x12ab, 0x12ac, 0x12ad, 0x12ae, 0x12af, 0x12b0,
+    0x12b1, 0x1315, 0x1316, 0x1317, 0x13bf, 0x13c0, 0x13c1, 0x13c2,
+    0x13c3, 0x13c4, 0x13c5, 0x13c6, 0x13c7, 0x13c8, 0x13c9, 0x13ca,
+    0x13cb, 0x13cc, 0x13cd, 0x1a06, 0x1a07, 0x1a28, 0x1a29, 0x1a2a,
+    0x1a2b, 0x1a2c, 0x1a2d, 0x1a80, 0x1abb, 0x1abc, 0x1abd, 0x1ad8,
+    0x1ad9, 0x0094, 0x0095, 0x0096, 0x0097, 0x00a0, 0x00a1, 0x00a2,
+    0x00a3, 0x0831, 0x0832, 0x0833, 0x0834, 0x0835, 0x0836, 0x0837,
+    0x0838, 0x0839, 0x083a, 0x083b, 0x0939, 0x093a, 0x093b, 0x093c,
+    0x093d, 0x093e, 0x093f, 0x09a0, 0x09a1, 0x09a2, 0x09a3, 0x09a4,
+    0x09a5, 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2,
+    0x11b3, 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba,
+    0x11bb, 0x132f, 0x1454, 0x1455, 0x1456, 0x1457, 0x1458, 0x1459,
+    0x145a, 0x145b, 0x145c, 0x145d, 0x145e, 0x145f, 0x1460, 0x1461,
+    0x1462, 0x1463, 0x1464, 0x1465, 0x1466, 0x1467, 0x1468, 0x1469,
+    0x146a, 0x146b, 0x17de, 0x17df, 0x17e0, 0x17e1, 0x17e2, 0x17e3,
+    0x17e4, 0x17e5, 0x17e6, 0x17e7, 0x17e8, 0x17e9, 0x17ea, 0x17eb,
+    0x17ec, 0x17ed, 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545,
+    0x2546, 0x2547, 0x2548, 0x2549, 0x254a, 0x254b, 0x254c, 0x254d,
+    0x254e, 0x254f, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555,
+    0x2628, 0x2766, 0x2767, 0x2768, 0x2769, 0x276a, 0x276b, 0x276c,
+    0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2772, 0x2773, 0x2774,
+    0x2775, 0x2776, 0x2777, 0x2778, 0x2779, 0x277a, 0x277b, 0x277c,
+    0x277d, 0x3503, 0x3544, 0x3545, 0x3546, 0x3547, 0x3560, 0x3561,
+    0x3562, 0x3563, 0x3564, 0x3565, 0x3566, 0x3567, 0x3568, 0x3569,
+    0x356a, 0x356b, 0x356c, 0x356d, 0x356e, 0x356f, 0x3570, 0x3571,
+    0x3572, 0x3573, 0x3574, 0x3575, 0x03f0, 0x103d, 0x103e, 0x103f,
+    0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047,
+    0x1048, 0x1049, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f,
+    0x1050, 0x1051, 0x1052, 0x1053, 0x1054, 0x1055, 0x1056, 0x1057,
+    0x1058, 0x1059, 0x105a, 0x105b, 0x105c, 0x105d, 0x105e, 0x105f,
+    0x1060, 0x1061, 0x1270, 0x1271, 0x21b8, 0x21b9, 0x21ba, 0x21bb,
+    0x21bc, 0x21bd, 0x21be, 0x21bf, 0x21f0, 0x21f1, 0x21f2, 0x21f3,
+    0x21f4, 0x21f5, 0x21f6, 0x21f7, 0x21f8, 0x21f9, 0x21fa, 0x21fb,
+    0x21fc, 0x21fd, 0x21fe, 0x21ff, 0x2340, 0x2341, 0x2342, 0x2343,
+    0x2344, 0x2345, 0x2346, 0x2347, 0x2348, 0x2349, 0x234a, 0x234b,
+    0x234c, 0x234d, 0x234e, 0x234f, 0x2350, 0x2351, 0x2352, 0x2353,
+    0x2354, 0x2355, 0x2356, 0x2357, 0x265c, 0x2f88, 0x2f89, 0x2f8a,
+    0x2f8b, 0x2f8c, 0x2f8d, 0x2f8e, 0x2f8f, 0x2f90, 0x2f91, 0x2f92,
+    0x2f93, 0x2f94, 0x2f95, 0x2f96, 0x2f97, 0x2f98, 0x2f99, 0x2f9a,
+    0x2f9b, 0x2f9c, 0x2f9d, 0x2f9e, 0x2f9f, 0x2fa0, 0x2fa1, 0x2fa2,
+    0x2fa3, 0x2fa4, 0x2fa5, 0x2fa6, 0x2fa7, 0x2fa8, 0x2fa9, 0x2faa,
+    0x2fab, 0x2fac, 0x2fad, 0x2fae, 0x2faf, 0x2fb0, 0x2fb1, 0x2fb2,
+    0x2fb3, 0x2fb4, 0x2fb5, 0x2fb6, 0x2fb7, 0x2fb8, 0x2fb9, 0x2fba,
+    0x2fbb, 0x4c52, 0x4c53, 0x4e28, 0x4e29, 0x4e2a, 0x4e2b, 0x4e2c,
+    0x4e2d, 0x4e2e, 0x4e2f, 0x4e30, 0x4e31, 0x4e32, 0x4e33, 0x4e34,
+    0x4e35, 0x4e36, 0x4e37, 0x4e38, 0x4e39, 0x4e3a, 0x4e3b, 0x4e3c,
+    0x4e3d, 0x4e3e, 0x4e3f, 0x4e80, 0x4e81, 0x4e82, 0x4e83, 0x4e84,
+    0x4e85, 0x4e86, 0x4e87, 0x4e88, 0x4e89, 0x4e8a, 0x4e8b, 0x4e8c,
+    0x4e8d, 0x4e8e, 0x4e8f, 0x4e90, 0x4e91, 0x4e92, 0x4e93, 0x4e94,
+    0x4e95, 0x4e96, 0x4e97, 0x4e98, 0x4e99, 0x4e9a, 0x4e9b, 0x4e9c,
+    0x4e9d, 0x4e9e, 0x4e9f, 0x4ea0, 0x4ea1, 0x4ea2, 0x4ea3, 0x4ea4,
+    0x4ea5, 0x4ea6, 0x4ea7, 0x4ea8, 0x4ea9, 0x4eaa, 0x4eab, 0x4eac,
+    0x4ead, 0x4eae, 0x4eaf, 0x4eb0, 0x4eb1, 0x4eb2, 0x4eb3, 0x4eb4,
+    0x4eb5, 0x4eb6, 0x4eb7, 0x4eb8, 0x4eb9, 0x4eba, 0x4ebb, 0x4ebc,
+    0x4ebd, 0x4ebe, 0x4ebf, 0x4ec0, 0x4ec1, 0x4ec2, 0x4ec3, 0x4ec4,
+    0x4ec5, 0x4ec6, 0x4ec7, 0x4ec8, 0x4ec9, 0x4eca, 0x4ecb, 0x6a04,
+    0x6a05, 0x07e2, 0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8,
+    0x07e9, 0x07ea, 0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0,
+    0x07f1, 0x07f2, 0x07f3, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8,
+    0x07f9, 0x07fa, 0x07fb, 0x07fc, 0x07fd, 0x07fe, 0x07ff, 0x2000,
+    0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
+    0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x200e, 0x200f, 0x2010,
+    0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018,
+    0x2019, 0x201a, 0x201b, 0x201c, 0x201d, 0x201e, 0x201f, 0x2020,
+    0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2028,
+    0x2029, 0x202a, 0x202b, 0x202c, 0x202d, 0x202e, 0x202f, 0x2030,
+    0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038,
+    0x2039, 0x203a, 0x203b, 0x203c, 0x203d, 0x203e, 0x203f, 0x2040,
+    0x2041, 0x2042, 0x2043, 0x2044, 0x2045, 0x2046, 0x2047, 0x2048,
+    0x2049, 0x204a, 0x204b, 0x204c, 0x204d, 0x204e, 0x204f, 0x2050,
+    0x2051, 0x2052, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058,
+    0x2059, 0x205a, 0x205b, 0x205c, 0x205d, 0x205e, 0x205f, 0x2060,
+    0x2061, 0x2062, 0x2063, 0x2064, 0x2065, 0x2066, 0x2067, 0x2068,
+    0x2069, 0x206a, 0x206b, 0x206c, 0x206d, 0x206e, 0x206f, 0x2070,
+    0x2071, 0x2072, 0x2073, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078,
+    0x2079, 0x4cba, 0x4cbb, 0x5d88, 0x5d89, 0x5d8a, 0x5d8b, 0x5d8c,
+    0x5d8d, 0x5d8e, 0x5d8f, 0x5db0, 0x5db1, 0x5db2, 0x5db3, 0x5db4,
+    0x5db5, 0x5db6, 0x5db7, 0x5db8, 0x5db9, 0x5dba, 0x5dbb, 0x5dbc,
+    0x5dbd, 0x5dbe, 0x5dbf, 0x5e40, 0x5e41, 0x5e42, 0x5e43, 0x5e44,
+    0x5e45, 0x5e46, 0x5e47, 0x5e48, 0x5e49, 0x5e4a, 0x5e4b, 0x5e4c,
+    0x5e4d, 0x5e4e, 0x5e4f, 0x5e50, 0x5e51, 0x5e52, 0x5e53, 0x5e54,
+    0x5e55, 0x5e56, 0x5e57, 0x5e58, 0x5e59, 0x5e5a, 0x5e5b, 0x5e5c,
+    0x5e5d, 0x5e5e, 0x5e5f, 0x5e60, 0x5e61, 0x5e62, 0x5e63, 0x5e64,
+    0x5e65, 0x5e66, 0x5e67, 0x5e68, 0x5e69, 0x5e6a, 0x5e6b, 0x5e6c,
+    0x5e6d, 0x5e6e, 0x5e6f, 0x5e70, 0x5e71, 0x5e72, 0x5e73, 0x5e74,
+    0x5e75, 0x5e76, 0x5e77, 0x5e78, 0x5e79, 0x5e7a, 0x5e7b, 0x5e7c,
+    0x5e7d, 0x5e7e, 0x5e7f, 0x5e80, 0x5e81, 0x5e82, 0x5e83, 0x5e84,
+    0x5e85, 0x5e86, 0x5e87, 0x5e88, 0x5e89, 0x5e8a, 0x5e8b, 0x5e8c,
+    0x5e8d, 0x5e8e, 0x5e8f, 0x5e90, 0x5e91, 0x5e92, 0x5e93, 0x5e94,
+    0x5e95, 0x5e96, 0x5e97, 0x5e98, 0x5e99, 0x5e9a, 0x5e9b, 0x5e9c,
+    0x5e9d, 0x5e9e, 0x5e9f, 0x5ea0, 0x5ea1, 0x5ea2, 0x5ea3, 0x5ea4,
+    0x5ea5, 0x5ea6, 0x5ea7, 0x5ea8, 0x5ea9, 0x5eaa, 0x5eab, 0x5eac,
+    0x5ead, 0x5eae, 0x5eaf, 0x5eb0, 0x5eb1, 0x5eb2, 0x5eb3, 0x5eb4,
+    0x5eb5, 0x5eb6, 0x5eb7, 0x5eb8, 0x5eb9, 0x5eba, 0x5ebb, 0x5ebc,
+    0x5ebd, 0x5ebe, 0x5ebf, 0x5ec0, 0x5ec1, 0x5ec2, 0x5ec3, 0x5ec4,
+    0x5ec5, 0x5ec6, 0x5ec7, 0x5ec8, 0x5ec9, 0x5eca, 0x5ecb, 0x5ecc,
+    0x5ecd, 0x5ece, 0x5ecf, 0x5ed0, 0x5ed1, 0x5ed2, 0x5ed3, 0x5ed4,
+    0x5ed5, 0x5ed6, 0x5ed7, 0x5ed8, 0x5ed9, 0x5eda, 0x5edb, 0x5edc,
+    0x5edd, 0x5ede, 0x5edf, 0x5ee0, 0x5ee1, 0x5ee2, 0x5ee3, 0x5ee4,
+    0x5ee5, 0x5ee6, 0x5ee7, 0x5ee8, 0x5ee9, 0x5eea, 0x5eeb, 0x5eec,
+    0x5eed, 0x5eee, 0x5eef, 0x5ef0, 0x5ef1, 0x5ef2, 0x5ef3, 0x5ef4,
+    0x5ef5, 0x5ef6, 0x5ef7, 0x5ef8, 0x5ef9, 0x5efa, 0x5efb, 0x5efc,
+    0x5efd, 0x5efe, 0x5eff, 0x5f00, 0x5f01, 0x5f02, 0x5f03, 0x5f04,
+    0x5f05, 0x5f06, 0x5f07, 0x5f08, 0x5f09, 0x5f0a, 0x5f0b, 0x5f0c,
+    0x5f0d, 0x5f0e, 0x5f0f, 0x0000,
 };
 
 static const uint8_t table0_mv_bits[1100] = {
-  1,  4,  4,  4,  5,  5,  5,  6,
-  6,  6,  7,  7,  7,  8,  8,  8,
-  8,  8,  8,  8,  8,  8,  8,  8,
-  8,  9,  9,  9,  9,  9,  9,  9,
-  9,  9,  9,  9,  9, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17,  8,
+     1,  4,  4,  4,  5,  5,  5,  6,
+     6,  6,  7,  7,  7,  8,  8,  8,
+     8,  8,  8,  8,  8,  8,  8,  8,
+     8,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17, 17, 17, 17, 17, 17,
+    17, 17, 17,  8,
 };
 
 static const uint8_t table0_mvx[1099] = {
- 32, 32, 31, 32, 33, 31, 33, 31,
- 33, 32, 34, 32, 30, 32, 31, 34,
- 35, 32, 34, 33, 29, 33, 30, 30,
- 31, 31, 35, 29, 33, 35, 33, 34,
- 31, 29, 30, 34, 30, 36, 28, 32,
- 34, 37, 30, 27, 32, 25, 39, 32,
- 34, 32, 35, 35, 35, 31, 35, 29,
- 32, 29, 30, 29, 37, 27, 36, 38,
- 37, 33, 32, 31, 29, 31, 28, 36,
- 33, 30, 34, 33, 33, 28, 27, 25,
- 31, 26, 39, 32, 32, 31, 33, 39,
- 31, 38, 28, 36, 21, 23, 43, 36,
- 34, 41, 30, 25, 28, 31, 30, 34,
- 38, 35, 61, 34, 28, 30, 37, 37,
- 35, 27, 36,  3, 59, 38, 37, 32,
- 31, 29, 26, 33, 37, 33, 27, 27,
- 35, 34, 34, 40, 42, 33, 32, 29,
-  4,  5, 28, 24, 25, 35, 39, 38,
- 32, 23, 27, 32, 30, 35, 26, 34,
- 60, 36, 29, 22, 26, 41,  7, 30,
- 38, 30, 36, 29, 30, 41, 26, 25,
- 32, 34, 24, 39,  1, 25, 39, 32,
- 28, 29, 32, 38, 26, 36, 28, 63,
- 28, 39, 23, 21, 26, 35, 31, 35,
- 57, 31, 29, 29, 28, 30, 27, 35,
-  2, 38, 40, 34, 37, 29, 38, 43,
- 26, 32, 33, 42, 24, 40, 28, 32,
- 32, 32, 36, 32, 43, 25, 21, 31,
- 30, 31, 41, 29, 33, 37, 26, 37,
- 27, 59, 23, 33, 35, 31, 31, 37,
- 38, 39, 32, 23, 32, 27, 37, 36,
- 31, 40, 25, 27, 38, 31, 36, 28,
- 31, 36, 25, 45,  3, 34, 38, 39,
- 40, 38, 30, 32, 19, 24, 25, 26,
- 45, 20, 24, 33, 33, 31, 41, 34,
- 39, 47, 40, 58, 59, 41, 33,  3,
- 17, 61, 42, 30, 26, 29, 36, 61,
- 33, 37, 62, 28, 25, 38, 25, 38,
- 17, 23, 34, 33, 21, 33, 49, 27,
- 32, 23, 27, 22, 24, 22, 39, 43,
- 27, 37,  6, 42, 47, 26, 30, 31,
- 41, 39, 33, 22, 45, 36, 32, 45,
- 19, 22, 30,  5,  5, 17, 29, 22,
- 31, 31, 43, 37, 27, 32, 32, 32,
- 33, 34, 43, 35, 29, 26, 22, 32,
- 19, 32, 25, 31, 41, 49, 28, 34,
- 28, 39, 34, 19, 37, 38, 29, 21,
- 36, 42, 24, 48, 16, 28, 49, 22,
- 34, 31, 38, 39, 44, 11, 35, 30,
- 33, 33, 23, 28, 33, 46, 15, 13,
- 24, 41, 24, 34, 34, 30, 26, 24,
- 14, 60, 21, 29, 39, 23, 35, 37,
- 63, 45, 33, 34, 47, 41, 22, 42,
- 35, 35, 23, 32, 35, 43, 32,  7,
- 31, 41, 20, 31, 16, 13, 63, 25,
- 30, 32, 35, 30, 30, 31, 42, 47,
- 39, 38, 40, 40, 51, 55, 56, 18,
- 21, 39, 39, 33, 17, 41, 23, 24,
- 43, 25, 31, 20, 19, 45,  1, 34,
- 31, 22, 35, 15, 46, 46, 35, 31,
- 28, 29, 29, 23, 41, 27, 14, 53,
- 53, 27, 24, 32, 57, 32, 17, 42,
- 37, 29, 33,  1, 25, 32, 32, 63,
- 26, 40, 44, 36, 31, 39, 20, 20,
- 44, 23, 33, 34, 35, 33, 33, 28,
- 41, 23, 41, 41, 29, 25, 26, 49,
- 29, 24, 37, 49, 50, 51, 51, 26,
- 39, 25, 26, 15, 39, 18, 42, 17,
-  4, 31, 32, 32, 60,  1, 42, 32,
-  0, 12, 19, 35, 21, 41, 17, 26,
- 20, 45, 46, 32, 37, 22, 47, 29,
- 31, 27, 29, 30, 21, 33, 35, 18,
- 25, 33, 50, 51, 42,  2, 15, 51,
- 53, 33, 25, 29, 55, 37, 38, 33,
- 38, 59, 38, 33, 39, 13, 32, 40,
- 61, 61, 32,  9, 44,  3, 31, 29,
- 25, 31, 27, 23,  9, 25,  9, 29,
- 20, 30, 30, 42, 18, 28, 25, 28,
- 28, 21, 29, 43, 29, 43, 26, 44,
- 44, 21, 38, 21, 24, 45, 45, 35,
- 39, 22, 35, 36, 34, 34, 45, 34,
- 29, 31, 46, 25, 46, 16, 17, 31,
- 20, 32, 47, 47, 47, 32, 49, 49,
- 49, 31,  1, 27, 28, 39, 39, 21,
- 36, 23, 51,  2, 40, 51, 32, 53,
- 24, 30, 24, 30, 21, 40, 57, 57,
- 31, 41, 58, 32, 12,  4, 32, 34,
- 59, 31, 32, 13,  9, 35, 26, 35,
- 37, 61, 37, 63, 26, 29, 41, 38,
- 23, 20, 41, 26, 41, 42, 42, 42,
- 26, 26, 26, 26,  1, 26, 37, 37,
- 37, 23, 34, 42, 27, 43, 34, 27,
- 31, 24, 33, 16,  3, 31, 24, 33,
- 24,  4, 44, 44, 11, 44, 31, 13,
- 13, 44, 45, 13, 25, 22, 38, 26,
- 38, 38, 39, 32, 30, 39, 30, 22,
- 32, 26, 30, 47, 47, 47, 19, 47,
- 30, 31, 35,  8, 23, 47, 47, 27,
- 35, 47, 31, 48, 35, 19, 36, 49,
- 49, 33, 31, 39, 27, 39, 49, 49,
- 50, 50, 50, 39, 31, 51, 51, 39,
- 28, 33, 33, 21, 40, 31, 52, 53,
- 40, 53,  9, 33, 31, 53, 54, 54,
- 54, 55, 55, 34, 15, 56, 25, 56,
- 21, 21, 40, 40, 25, 40, 58, 36,
-  5, 41, 41, 12, 60, 41, 41, 37,
- 22, 61, 18, 29, 29, 30, 61, 30,
- 61, 62, 62, 30, 30, 63, 18, 13,
- 30, 23, 19, 20, 20, 41, 13,  2,
-  5,  5,  1,  5, 32,  6, 32, 35,
- 20, 35, 27, 35, 35, 36, 36, 13,
- 36, 41, 41, 41,  3, 30, 42, 27,
- 20, 30, 27, 28, 30, 21, 33, 33,
- 14, 24, 30, 42, 24, 33, 25, 42,
- 43, 14, 43, 43, 14, 43,  7, 36,
- 37, 37, 37, 37,  7, 14, 25, 43,
- 43, 44, 15, 37,  7,  7,  3,  1,
-  8, 15, 15,  8, 44, 44, 44, 45,
- 45, 45, 45,  8,  8, 45, 21, 45,
- 28, 28, 28, 21, 28, 28, 22, 37,
- 46, 46, 37,  8, 29, 37, 29, 22,
- 46, 37, 22, 29, 47, 47, 38, 38,
- 16, 38, 38, 33, 38, 22, 47, 47,
- 29, 25, 16,  0, 48,  1, 34, 48,
- 48, 34, 25, 26, 26, 49, 49, 26,
-  1, 49,  4, 26,  4, 49,  1,  9,
- 49, 49, 49, 10, 49, 17, 38, 17,
- 17, 50, 38, 50, 50, 22, 38, 51,
- 38, 38, 51, 39, 39, 18, 22, 39,
- 51, 22, 52, 52, 52, 39, 53, 53,
- 10, 23, 18, 29, 10, 53, 29, 54,
- 11, 54, 11, 11, 55,  1, 18, 55,
- 55, 55, 55, 55, 55, 29, 34, 18,
- 29, 56, 56, 34, 57, 34, 34, 29,
- 29, 57, 57, 35, 35, 35, 35, 35,
- 39, 35, 59, 59, 18, 59, 39, 30,
- 18, 40, 60, 60, 61, 30, 18, 61,
- 61, 19, 19,
+    32, 32, 31, 32, 33, 31, 33, 31,
+    33, 32, 34, 32, 30, 32, 31, 34,
+    35, 32, 34, 33, 29, 33, 30, 30,
+    31, 31, 35, 29, 33, 35, 33, 34,
+    31, 29, 30, 34, 30, 36, 28, 32,
+    34, 37, 30, 27, 32, 25, 39, 32,
+    34, 32, 35, 35, 35, 31, 35, 29,
+    32, 29, 30, 29, 37, 27, 36, 38,
+    37, 33, 32, 31, 29, 31, 28, 36,
+    33, 30, 34, 33, 33, 28, 27, 25,
+    31, 26, 39, 32, 32, 31, 33, 39,
+    31, 38, 28, 36, 21, 23, 43, 36,
+    34, 41, 30, 25, 28, 31, 30, 34,
+    38, 35, 61, 34, 28, 30, 37, 37,
+    35, 27, 36,  3, 59, 38, 37, 32,
+    31, 29, 26, 33, 37, 33, 27, 27,
+    35, 34, 34, 40, 42, 33, 32, 29,
+     4,  5, 28, 24, 25, 35, 39, 38,
+    32, 23, 27, 32, 30, 35, 26, 34,
+    60, 36, 29, 22, 26, 41,  7, 30,
+    38, 30, 36, 29, 30, 41, 26, 25,
+    32, 34, 24, 39,  1, 25, 39, 32,
+    28, 29, 32, 38, 26, 36, 28, 63,
+    28, 39, 23, 21, 26, 35, 31, 35,
+    57, 31, 29, 29, 28, 30, 27, 35,
+     2, 38, 40, 34, 37, 29, 38, 43,
+    26, 32, 33, 42, 24, 40, 28, 32,
+    32, 32, 36, 32, 43, 25, 21, 31,
+    30, 31, 41, 29, 33, 37, 26, 37,
+    27, 59, 23, 33, 35, 31, 31, 37,
+    38, 39, 32, 23, 32, 27, 37, 36,
+    31, 40, 25, 27, 38, 31, 36, 28,
+    31, 36, 25, 45,  3, 34, 38, 39,
+    40, 38, 30, 32, 19, 24, 25, 26,
+    45, 20, 24, 33, 33, 31, 41, 34,
+    39, 47, 40, 58, 59, 41, 33,  3,
+    17, 61, 42, 30, 26, 29, 36, 61,
+    33, 37, 62, 28, 25, 38, 25, 38,
+    17, 23, 34, 33, 21, 33, 49, 27,
+    32, 23, 27, 22, 24, 22, 39, 43,
+    27, 37,  6, 42, 47, 26, 30, 31,
+    41, 39, 33, 22, 45, 36, 32, 45,
+    19, 22, 30,  5,  5, 17, 29, 22,
+    31, 31, 43, 37, 27, 32, 32, 32,
+    33, 34, 43, 35, 29, 26, 22, 32,
+    19, 32, 25, 31, 41, 49, 28, 34,
+    28, 39, 34, 19, 37, 38, 29, 21,
+    36, 42, 24, 48, 16, 28, 49, 22,
+    34, 31, 38, 39, 44, 11, 35, 30,
+    33, 33, 23, 28, 33, 46, 15, 13,
+    24, 41, 24, 34, 34, 30, 26, 24,
+    14, 60, 21, 29, 39, 23, 35, 37,
+    63, 45, 33, 34, 47, 41, 22, 42,
+    35, 35, 23, 32, 35, 43, 32,  7,
+    31, 41, 20, 31, 16, 13, 63, 25,
+    30, 32, 35, 30, 30, 31, 42, 47,
+    39, 38, 40, 40, 51, 55, 56, 18,
+    21, 39, 39, 33, 17, 41, 23, 24,
+    43, 25, 31, 20, 19, 45,  1, 34,
+    31, 22, 35, 15, 46, 46, 35, 31,
+    28, 29, 29, 23, 41, 27, 14, 53,
+    53, 27, 24, 32, 57, 32, 17, 42,
+    37, 29, 33,  1, 25, 32, 32, 63,
+    26, 40, 44, 36, 31, 39, 20, 20,
+    44, 23, 33, 34, 35, 33, 33, 28,
+    41, 23, 41, 41, 29, 25, 26, 49,
+    29, 24, 37, 49, 50, 51, 51, 26,
+    39, 25, 26, 15, 39, 18, 42, 17,
+     4, 31, 32, 32, 60,  1, 42, 32,
+     0, 12, 19, 35, 21, 41, 17, 26,
+    20, 45, 46, 32, 37, 22, 47, 29,
+    31, 27, 29, 30, 21, 33, 35, 18,
+    25, 33, 50, 51, 42,  2, 15, 51,
+    53, 33, 25, 29, 55, 37, 38, 33,
+    38, 59, 38, 33, 39, 13, 32, 40,
+    61, 61, 32,  9, 44,  3, 31, 29,
+    25, 31, 27, 23,  9, 25,  9, 29,
+    20, 30, 30, 42, 18, 28, 25, 28,
+    28, 21, 29, 43, 29, 43, 26, 44,
+    44, 21, 38, 21, 24, 45, 45, 35,
+    39, 22, 35, 36, 34, 34, 45, 34,
+    29, 31, 46, 25, 46, 16, 17, 31,
+    20, 32, 47, 47, 47, 32, 49, 49,
+    49, 31,  1, 27, 28, 39, 39, 21,
+    36, 23, 51,  2, 40, 51, 32, 53,
+    24, 30, 24, 30, 21, 40, 57, 57,
+    31, 41, 58, 32, 12,  4, 32, 34,
+    59, 31, 32, 13,  9, 35, 26, 35,
+    37, 61, 37, 63, 26, 29, 41, 38,
+    23, 20, 41, 26, 41, 42, 42, 42,
+    26, 26, 26, 26,  1, 26, 37, 37,
+    37, 23, 34, 42, 27, 43, 34, 27,
+    31, 24, 33, 16,  3, 31, 24, 33,
+    24,  4, 44, 44, 11, 44, 31, 13,
+    13, 44, 45, 13, 25, 22, 38, 26,
+    38, 38, 39, 32, 30, 39, 30, 22,
+    32, 26, 30, 47, 47, 47, 19, 47,
+    30, 31, 35,  8, 23, 47, 47, 27,
+    35, 47, 31, 48, 35, 19, 36, 49,
+    49, 33, 31, 39, 27, 39, 49, 49,
+    50, 50, 50, 39, 31, 51, 51, 39,
+    28, 33, 33, 21, 40, 31, 52, 53,
+    40, 53,  9, 33, 31, 53, 54, 54,
+    54, 55, 55, 34, 15, 56, 25, 56,
+    21, 21, 40, 40, 25, 40, 58, 36,
+     5, 41, 41, 12, 60, 41, 41, 37,
+    22, 61, 18, 29, 29, 30, 61, 30,
+    61, 62, 62, 30, 30, 63, 18, 13,
+    30, 23, 19, 20, 20, 41, 13,  2,
+     5,  5,  1,  5, 32,  6, 32, 35,
+    20, 35, 27, 35, 35, 36, 36, 13,
+    36, 41, 41, 41,  3, 30, 42, 27,
+    20, 30, 27, 28, 30, 21, 33, 33,
+    14, 24, 30, 42, 24, 33, 25, 42,
+    43, 14, 43, 43, 14, 43,  7, 36,
+    37, 37, 37, 37,  7, 14, 25, 43,
+    43, 44, 15, 37,  7,  7,  3,  1,
+     8, 15, 15,  8, 44, 44, 44, 45,
+    45, 45, 45,  8,  8, 45, 21, 45,
+    28, 28, 28, 21, 28, 28, 22, 37,
+    46, 46, 37,  8, 29, 37, 29, 22,
+    46, 37, 22, 29, 47, 47, 38, 38,
+    16, 38, 38, 33, 38, 22, 47, 47,
+    29, 25, 16,  0, 48,  1, 34, 48,
+    48, 34, 25, 26, 26, 49, 49, 26,
+     1, 49,  4, 26,  4, 49,  1,  9,
+    49, 49, 49, 10, 49, 17, 38, 17,
+    17, 50, 38, 50, 50, 22, 38, 51,
+    38, 38, 51, 39, 39, 18, 22, 39,
+    51, 22, 52, 52, 52, 39, 53, 53,
+    10, 23, 18, 29, 10, 53, 29, 54,
+    11, 54, 11, 11, 55,  1, 18, 55,
+    55, 55, 55, 55, 55, 29, 34, 18,
+    29, 56, 56, 34, 57, 34, 34, 29,
+    29, 57, 57, 35, 35, 35, 35, 35,
+    39, 35, 59, 59, 18, 59, 39, 30,
+    18, 40, 60, 60, 61, 30, 18, 61,
+    61, 19, 19,
 };
 
 static const uint8_t table0_mvy[1099] = {
- 32, 31, 32, 33, 32, 31, 31, 33,
- 33, 34, 32, 30, 32, 35, 34, 31,
- 32, 29, 33, 30, 32, 34, 33, 31,
- 30, 35, 31, 31, 29, 33, 35, 30,
- 29, 33, 34, 34, 30, 32, 32, 36,
- 29, 32, 35, 32, 28, 32, 32, 27,
- 35, 37, 34, 29, 30, 36, 35, 34,
- 25, 30, 29, 35, 33, 31, 31, 32,
- 31, 28, 39, 28, 29, 37, 31, 33,
- 27, 36, 28, 36, 37, 33, 33, 31,
- 27, 32, 31, 38, 26, 25, 25, 33,
- 39, 31, 34, 30, 32, 32, 32, 34,
- 36, 32, 28, 33, 30, 38, 37, 27,
- 33, 28, 32, 37, 35, 38, 29, 34,
- 27, 29, 29, 32, 32, 34, 35,  3,
- 26, 36, 31, 38, 30, 26, 35, 34,
- 37, 26, 25, 32, 32, 39, 23, 37,
- 32, 32, 29, 32, 29, 36, 29, 30,
- 41, 31, 30, 21, 39, 25, 34, 38,
- 32, 35, 39, 32, 33, 33, 32, 27,
- 29, 25, 28, 27, 26, 31, 30, 35,
- 24, 24, 31, 34, 32, 30, 35, 40,
- 28, 38,  5, 35, 29, 36, 36, 32,
- 38, 30, 33, 31, 35, 26, 23, 38,
- 32, 41, 28, 25, 37, 40, 37, 39,
- 32, 36, 33, 39, 25, 26, 28, 31,
- 28, 42, 23, 31, 33, 31, 39,  1,
- 59, 22, 27,  4, 33, 34, 33, 24,
- 41,  3, 35, 41, 41, 28, 36, 36,
- 28, 33, 35, 21, 23, 21, 22, 37,
- 27, 27, 43, 29, 60, 39, 27, 25,
- 59, 34, 27, 27, 26, 40, 37, 27,
- 61, 26, 39, 33, 31, 22, 37, 25,
- 30, 25, 24, 61, 31, 34, 25, 38,
- 32, 32, 30,  3, 61, 43, 29, 23,
- 28, 32, 28, 32, 31, 34,  5, 33,
- 32, 33, 33, 42, 37, 23, 38, 31,
- 40, 26, 32, 26, 37, 38, 36, 24,
- 29, 30, 20, 22, 29, 24, 32, 41,
-  2, 34, 25, 33, 29, 31, 39, 35,
- 36, 24, 32, 30, 33, 27, 44, 60,
- 30, 36, 19, 34, 31, 24, 16, 35,
- 32, 38, 21, 33, 31, 31, 21, 35,
-  5, 17, 29, 38, 38, 18, 58, 19,
- 43, 41, 30, 41, 43, 39, 29,  7,
- 29, 17, 28, 19, 28, 31, 25, 19,
- 40, 26, 21, 33, 39, 23, 40, 30,
- 39, 34, 35, 32, 32, 24, 33, 30,
- 40, 47, 39, 37, 32, 33, 24, 23,
- 45, 47, 27, 23, 42, 32, 32, 33,
- 36, 37, 37, 17, 18, 22, 40, 38,
- 32, 31, 35, 24, 17, 25, 17, 23,
- 33, 34, 51, 42, 31, 36, 36, 29,
- 21, 22, 37, 44, 43, 25, 47, 33,
- 45, 27, 31, 58, 31, 32, 31, 38,
- 43, 20, 47, 45, 54,  1, 26, 34,
- 38, 14, 22, 24, 33, 34, 32, 32,
- 37, 21, 23, 49, 35, 23, 28, 39,
- 39, 23, 55, 33, 30, 30, 63, 16,
- 42, 28, 13, 33, 33, 35, 19, 46,
- 43, 17, 19, 36, 39, 24, 31, 32,
- 33, 26, 28, 62, 33, 63, 33, 39,
- 19, 49, 17, 31, 43, 13, 15, 29,
- 25, 35, 33, 23, 49, 41, 28, 29,
- 34, 38,  7, 61, 11, 50, 13, 41,
- 19, 47, 25, 26, 15, 42, 41, 29,
- 45, 27, 17, 35, 32, 29, 32, 24,
- 13, 26, 26, 31, 24, 33, 28, 30,
- 31, 11, 45, 46, 33, 33, 35, 57,
- 32, 32, 35, 45, 34, 11, 37, 42,
- 39, 37, 31, 49, 21, 27, 29, 47,
- 53, 40, 51, 16, 26,  1, 40, 30,
- 41, 44, 34, 25, 27, 31, 35, 35,
- 31, 15, 49,  1, 35, 40,  5, 58,
- 21, 29, 22, 59, 45, 31,  9, 26,
-  9, 29, 11, 32, 30,  3, 13, 20,
- 18, 20, 11,  3, 29, 40, 31, 53,
- 30, 17, 20, 37, 31, 42, 47, 47,
- 54, 38,  9, 34, 13, 37, 21, 25,
- 27, 43, 42, 45, 40, 25, 27, 46,
- 22, 25, 53, 20,  2, 14, 39, 15,
- 22, 44, 34, 21, 38, 33, 27, 48,
- 34, 52, 35, 47, 49, 54,  2, 13,
- 23, 52, 29, 45, 22, 49, 54, 21,
- 40, 42, 31, 30, 29, 34,  0, 25,
- 23, 51, 24, 59, 28, 38, 29, 31,
-  2, 13, 31,  8, 31, 33, 12, 45,
- 41,  7, 14, 30, 25, 18, 43, 20,
- 43, 35, 44,  1, 49, 42, 42, 18,
- 41, 38, 41, 44, 53, 11, 20, 25,
- 45, 46, 47, 48, 39, 52, 46, 49,
- 63, 55, 44, 38, 13, 13, 57, 22,
- 51, 16, 12, 28, 35, 57, 25, 20,
- 26, 28, 28, 29, 32, 31, 62, 34,
- 35, 35, 19, 49, 48, 39, 40, 18,
- 43, 46, 11,  6, 48, 19, 49, 41,
- 10, 23, 58, 17, 21, 23, 34, 30,
- 60,  0, 44, 34, 26, 37, 46, 43,
- 49, 59,  4, 34, 59, 37, 22, 25,
- 28, 46,  6, 40, 59, 42, 36, 61,
- 28, 30, 31, 43, 10, 22, 23, 47,
- 20, 52, 55, 36, 25, 16,  1, 11,
- 27, 29,  5, 63, 18, 41, 31, 34,
- 38,  1,  5, 13, 28, 31, 17, 38,
- 39, 41, 36, 37, 22, 39, 33, 43,
- 43, 15, 17, 49, 30, 21, 22, 20,
- 10, 17, 25, 54, 57,  3, 34,  8,
- 36, 25, 31, 14, 15, 19, 29, 25,
- 18, 39, 53, 22, 27, 20, 29, 33,
- 41, 42, 35, 62, 50, 29, 53, 50,
- 35, 55, 42, 61, 63,  4,  7, 42,
- 21, 46, 47, 49, 27, 46, 17, 55,
- 41, 50, 63,  4, 56, 18,  8, 10,
- 18, 51, 63, 36, 55, 18,  5, 55,
-  9, 29, 17, 21, 30, 27,  1, 59,
-  7, 11, 12, 15,  5, 42, 24, 41,
- 43,  7, 27, 22, 25, 31, 30, 37,
- 22, 39, 53, 29, 36, 37, 48,  0,
-  5, 13, 17, 31, 32, 26, 46, 28,
- 44, 45, 46, 53, 49, 51,  3, 41,
-  3, 22, 42, 33,  5, 45,  7, 22,
- 40, 53, 24, 14, 25, 27, 10, 12,
- 34, 16, 17, 53, 20, 26, 39, 45,
- 18, 45, 35, 33, 31, 49,  4, 39,
- 42, 11, 51,  5, 13, 26, 27, 17,
- 52, 30,  0, 22, 12, 34, 62, 36,
- 38, 41, 47, 30, 63, 38, 41, 43,
- 59, 33, 45, 37, 38, 40, 47, 24,
- 48, 49, 30,  1, 10, 22, 49, 15,
- 39, 59, 31, 32, 33, 18, 13, 15,
- 31, 21, 27, 44, 42, 39, 46, 17,
- 26, 32, 30, 31,  0, 30, 34,  9,
- 12, 13, 25, 31, 32, 55, 43, 35,
- 61, 33, 35, 46, 25, 47, 48, 62,
- 63, 38, 61,  1,  2,  5,  7,  9,
- 46, 10, 34, 35, 36, 55, 51,  7,
- 40, 23, 34, 37,  5, 13, 42, 18,
- 25, 27, 28,
+    32, 31, 32, 33, 32, 31, 31, 33,
+    33, 34, 32, 30, 32, 35, 34, 31,
+    32, 29, 33, 30, 32, 34, 33, 31,
+    30, 35, 31, 31, 29, 33, 35, 30,
+    29, 33, 34, 34, 30, 32, 32, 36,
+    29, 32, 35, 32, 28, 32, 32, 27,
+    35, 37, 34, 29, 30, 36, 35, 34,
+    25, 30, 29, 35, 33, 31, 31, 32,
+    31, 28, 39, 28, 29, 37, 31, 33,
+    27, 36, 28, 36, 37, 33, 33, 31,
+    27, 32, 31, 38, 26, 25, 25, 33,
+    39, 31, 34, 30, 32, 32, 32, 34,
+    36, 32, 28, 33, 30, 38, 37, 27,
+    33, 28, 32, 37, 35, 38, 29, 34,
+    27, 29, 29, 32, 32, 34, 35,  3,
+    26, 36, 31, 38, 30, 26, 35, 34,
+    37, 26, 25, 32, 32, 39, 23, 37,
+    32, 32, 29, 32, 29, 36, 29, 30,
+    41, 31, 30, 21, 39, 25, 34, 38,
+    32, 35, 39, 32, 33, 33, 32, 27,
+    29, 25, 28, 27, 26, 31, 30, 35,
+    24, 24, 31, 34, 32, 30, 35, 40,
+    28, 38,  5, 35, 29, 36, 36, 32,
+    38, 30, 33, 31, 35, 26, 23, 38,
+    32, 41, 28, 25, 37, 40, 37, 39,
+    32, 36, 33, 39, 25, 26, 28, 31,
+    28, 42, 23, 31, 33, 31, 39,  1,
+    59, 22, 27,  4, 33, 34, 33, 24,
+    41,  3, 35, 41, 41, 28, 36, 36,
+    28, 33, 35, 21, 23, 21, 22, 37,
+    27, 27, 43, 29, 60, 39, 27, 25,
+    59, 34, 27, 27, 26, 40, 37, 27,
+    61, 26, 39, 33, 31, 22, 37, 25,
+    30, 25, 24, 61, 31, 34, 25, 38,
+    32, 32, 30,  3, 61, 43, 29, 23,
+    28, 32, 28, 32, 31, 34,  5, 33,
+    32, 33, 33, 42, 37, 23, 38, 31,
+    40, 26, 32, 26, 37, 38, 36, 24,
+    29, 30, 20, 22, 29, 24, 32, 41,
+     2, 34, 25, 33, 29, 31, 39, 35,
+    36, 24, 32, 30, 33, 27, 44, 60,
+    30, 36, 19, 34, 31, 24, 16, 35,
+    32, 38, 21, 33, 31, 31, 21, 35,
+     5, 17, 29, 38, 38, 18, 58, 19,
+    43, 41, 30, 41, 43, 39, 29,  7,
+    29, 17, 28, 19, 28, 31, 25, 19,
+    40, 26, 21, 33, 39, 23, 40, 30,
+    39, 34, 35, 32, 32, 24, 33, 30,
+    40, 47, 39, 37, 32, 33, 24, 23,
+    45, 47, 27, 23, 42, 32, 32, 33,
+    36, 37, 37, 17, 18, 22, 40, 38,
+    32, 31, 35, 24, 17, 25, 17, 23,
+    33, 34, 51, 42, 31, 36, 36, 29,
+    21, 22, 37, 44, 43, 25, 47, 33,
+    45, 27, 31, 58, 31, 32, 31, 38,
+    43, 20, 47, 45, 54,  1, 26, 34,
+    38, 14, 22, 24, 33, 34, 32, 32,
+    37, 21, 23, 49, 35, 23, 28, 39,
+    39, 23, 55, 33, 30, 30, 63, 16,
+    42, 28, 13, 33, 33, 35, 19, 46,
+    43, 17, 19, 36, 39, 24, 31, 32,
+    33, 26, 28, 62, 33, 63, 33, 39,
+    19, 49, 17, 31, 43, 13, 15, 29,
+    25, 35, 33, 23, 49, 41, 28, 29,
+    34, 38,  7, 61, 11, 50, 13, 41,
+    19, 47, 25, 26, 15, 42, 41, 29,
+    45, 27, 17, 35, 32, 29, 32, 24,
+    13, 26, 26, 31, 24, 33, 28, 30,
+    31, 11, 45, 46, 33, 33, 35, 57,
+    32, 32, 35, 45, 34, 11, 37, 42,
+    39, 37, 31, 49, 21, 27, 29, 47,
+    53, 40, 51, 16, 26,  1, 40, 30,
+    41, 44, 34, 25, 27, 31, 35, 35,
+    31, 15, 49,  1, 35, 40,  5, 58,
+    21, 29, 22, 59, 45, 31,  9, 26,
+     9, 29, 11, 32, 30,  3, 13, 20,
+    18, 20, 11,  3, 29, 40, 31, 53,
+    30, 17, 20, 37, 31, 42, 47, 47,
+    54, 38,  9, 34, 13, 37, 21, 25,
+    27, 43, 42, 45, 40, 25, 27, 46,
+    22, 25, 53, 20,  2, 14, 39, 15,
+    22, 44, 34, 21, 38, 33, 27, 48,
+    34, 52, 35, 47, 49, 54,  2, 13,
+    23, 52, 29, 45, 22, 49, 54, 21,
+    40, 42, 31, 30, 29, 34,  0, 25,
+    23, 51, 24, 59, 28, 38, 29, 31,
+     2, 13, 31,  8, 31, 33, 12, 45,
+    41,  7, 14, 30, 25, 18, 43, 20,
+    43, 35, 44,  1, 49, 42, 42, 18,
+    41, 38, 41, 44, 53, 11, 20, 25,
+    45, 46, 47, 48, 39, 52, 46, 49,
+    63, 55, 44, 38, 13, 13, 57, 22,
+    51, 16, 12, 28, 35, 57, 25, 20,
+    26, 28, 28, 29, 32, 31, 62, 34,
+    35, 35, 19, 49, 48, 39, 40, 18,
+    43, 46, 11,  6, 48, 19, 49, 41,
+    10, 23, 58, 17, 21, 23, 34, 30,
+    60,  0, 44, 34, 26, 37, 46, 43,
+    49, 59,  4, 34, 59, 37, 22, 25,
+    28, 46,  6, 40, 59, 42, 36, 61,
+    28, 30, 31, 43, 10, 22, 23, 47,
+    20, 52, 55, 36, 25, 16,  1, 11,
+    27, 29,  5, 63, 18, 41, 31, 34,
+    38,  1,  5, 13, 28, 31, 17, 38,
+    39, 41, 36, 37, 22, 39, 33, 43,
+    43, 15, 17, 49, 30, 21, 22, 20,
+    10, 17, 25, 54, 57,  3, 34,  8,
+    36, 25, 31, 14, 15, 19, 29, 25,
+    18, 39, 53, 22, 27, 20, 29, 33,
+    41, 42, 35, 62, 50, 29, 53, 50,
+    35, 55, 42, 61, 63,  4,  7, 42,
+    21, 46, 47, 49, 27, 46, 17, 55,
+    41, 50, 63,  4, 56, 18,  8, 10,
+    18, 51, 63, 36, 55, 18,  5, 55,
+     9, 29, 17, 21, 30, 27,  1, 59,
+     7, 11, 12, 15,  5, 42, 24, 41,
+    43,  7, 27, 22, 25, 31, 30, 37,
+    22, 39, 53, 29, 36, 37, 48,  0,
+     5, 13, 17, 31, 32, 26, 46, 28,
+    44, 45, 46, 53, 49, 51,  3, 41,
+     3, 22, 42, 33,  5, 45,  7, 22,
+    40, 53, 24, 14, 25, 27, 10, 12,
+    34, 16, 17, 53, 20, 26, 39, 45,
+    18, 45, 35, 33, 31, 49,  4, 39,
+    42, 11, 51,  5, 13, 26, 27, 17,
+    52, 30,  0, 22, 12, 34, 62, 36,
+    38, 41, 47, 30, 63, 38, 41, 43,
+    59, 33, 45, 37, 38, 40, 47, 24,
+    48, 49, 30,  1, 10, 22, 49, 15,
+    39, 59, 31, 32, 33, 18, 13, 15,
+    31, 21, 27, 44, 42, 39, 46, 17,
+    26, 32, 30, 31,  0, 30, 34,  9,
+    12, 13, 25, 31, 32, 55, 43, 35,
+    61, 33, 35, 46, 25, 47, 48, 62,
+    63, 38, 61,  1,  2,  5,  7,  9,
+    46, 10, 34, 35, 36, 55, 51,  7,
+    40, 23, 34, 37,  5, 13, 42, 18,
+    25, 27, 28,
 };
 
 /* motion vector table 1 */
 static const uint16_t table1_mv_code[1100] = {
- 0x0000, 0x0007, 0x0009, 0x000f, 0x000a, 0x0011, 0x001a, 0x001c,
- 0x0011, 0x0031, 0x0025, 0x002d, 0x002f, 0x006f, 0x0075, 0x0041,
- 0x004c, 0x004e, 0x005c, 0x0060, 0x0062, 0x0066, 0x0068, 0x0069,
- 0x006b, 0x00a6, 0x00c1, 0x00cb, 0x00cc, 0x00ce, 0x00da, 0x00e8,
- 0x00ee, 0x0087, 0x0090, 0x009e, 0x009f, 0x00ba, 0x00ca, 0x00d8,
- 0x00db, 0x00df, 0x0104, 0x0109, 0x010c, 0x0143, 0x0145, 0x014a,
- 0x0156, 0x015c, 0x01b3, 0x01d3, 0x01da, 0x0103, 0x0109, 0x010b,
- 0x0122, 0x0127, 0x0134, 0x0161, 0x0164, 0x0176, 0x0184, 0x018d,
- 0x018e, 0x018f, 0x0190, 0x0193, 0x0196, 0x019d, 0x019e, 0x019f,
- 0x01a9, 0x01b2, 0x01b4, 0x01ba, 0x01bb, 0x01bc, 0x0201, 0x0202,
- 0x0205, 0x0207, 0x020d, 0x0210, 0x0211, 0x0215, 0x021b, 0x021f,
- 0x0281, 0x0285, 0x0290, 0x029c, 0x029d, 0x02a2, 0x02a7, 0x02a8,
- 0x02aa, 0x02b0, 0x02b1, 0x02b4, 0x02bc, 0x02bf, 0x0320, 0x0326,
- 0x0327, 0x0329, 0x032a, 0x0336, 0x0360, 0x0362, 0x0363, 0x0372,
- 0x03b2, 0x03bc, 0x03bd, 0x0203, 0x0205, 0x021a, 0x0249, 0x024a,
- 0x024c, 0x02c7, 0x02ca, 0x02ce, 0x02ef, 0x030d, 0x0322, 0x0325,
- 0x0338, 0x0373, 0x037a, 0x0409, 0x0415, 0x0416, 0x0418, 0x0428,
- 0x042d, 0x042f, 0x0434, 0x0508, 0x0509, 0x0510, 0x0511, 0x051c,
- 0x051e, 0x0524, 0x0541, 0x0543, 0x0546, 0x0547, 0x054d, 0x0557,
- 0x055f, 0x056a, 0x056c, 0x056d, 0x056f, 0x0576, 0x0577, 0x057a,
- 0x057b, 0x057c, 0x057d, 0x0600, 0x0601, 0x0603, 0x0614, 0x0616,
- 0x0617, 0x061c, 0x061f, 0x0642, 0x0648, 0x0649, 0x064a, 0x064b,
- 0x0657, 0x0668, 0x0669, 0x066b, 0x066e, 0x067f, 0x06c2, 0x06c8,
- 0x06cb, 0x06de, 0x06df, 0x06e2, 0x06e3, 0x06ef, 0x0748, 0x074b,
- 0x076e, 0x076f, 0x077c, 0x0409, 0x0423, 0x0428, 0x0429, 0x042a,
- 0x042b, 0x0432, 0x0433, 0x0496, 0x049a, 0x04d5, 0x04db, 0x0581,
- 0x0582, 0x058b, 0x058c, 0x058d, 0x0598, 0x0599, 0x059a, 0x059e,
- 0x05dd, 0x0619, 0x0632, 0x0633, 0x0648, 0x0672, 0x06a1, 0x06a2,
- 0x06a3, 0x06af, 0x06e2, 0x06e3, 0x06e4, 0x0800, 0x0801, 0x0802,
- 0x0803, 0x081a, 0x081b, 0x0829, 0x082f, 0x0832, 0x083e, 0x083f,
- 0x0852, 0x0853, 0x0858, 0x086b, 0x0877, 0x0878, 0x0879, 0x087a,
- 0x087b, 0x0a00, 0x0a01, 0x0a0d, 0x0a0e, 0x0a0f, 0x0a24, 0x0a37,
- 0x0a3a, 0x0a3b, 0x0a3e, 0x0a46, 0x0a47, 0x0a4a, 0x0a4b, 0x0a5f,
- 0x0a79, 0x0a7a, 0x0a7b, 0x0a80, 0x0a81, 0x0a84, 0x0a85, 0x0a99,
- 0x0aa5, 0x0aa6, 0x0ab8, 0x0aba, 0x0abb, 0x0abc, 0x0abd, 0x0ac8,
- 0x0ace, 0x0acf, 0x0ad7, 0x0adc, 0x0aeb, 0x0c04, 0x0c25, 0x0c26,
- 0x0c27, 0x0c2a, 0x0c2b, 0x0c3a, 0x0c3b, 0x0c3c, 0x0c3d, 0x0ca0,
- 0x0cad, 0x0cd4, 0x0cd5, 0x0cfc, 0x0cfd, 0x0d86, 0x0d92, 0x0d93,
- 0x0d94, 0x0d95, 0x0db0, 0x0db8, 0x0db9, 0x0dba, 0x0dbb, 0x0dc0,
- 0x0dc2, 0x0dc3, 0x0dda, 0x0ddb, 0x0ddc, 0x0ddd, 0x0e92, 0x0e93,
- 0x0e94, 0x0e95, 0x0ec7, 0x0ecc, 0x0ece, 0x0ecf, 0x0ed8, 0x0ed9,
- 0x0eda, 0x0edb, 0x0808, 0x0809, 0x080a, 0x0810, 0x0811, 0x0844,
- 0x0845, 0x0861, 0x0862, 0x0863, 0x086c, 0x0922, 0x0923, 0x092e,
- 0x092f, 0x0936, 0x0937, 0x09b1, 0x09b2, 0x09b3, 0x09b4, 0x09b5,
- 0x09b8, 0x09b9, 0x09ba, 0x09bb, 0x09bc, 0x09bd, 0x09be, 0x09bf,
- 0x0b00, 0x0b15, 0x0b2c, 0x0b2d, 0x0b2e, 0x0b2f, 0x0b36, 0x0bb9,
- 0x0c28, 0x0c2a, 0x0c2b, 0x0c2c, 0x0c2d, 0x0c2e, 0x0c2f, 0x0c30,
- 0x0c31, 0x0c38, 0x0c60, 0x0c61, 0x0c62, 0x0c63, 0x0c8d, 0x0c8e,
- 0x0c8f, 0x0c92, 0x0cbe, 0x0cbf, 0x0ce6, 0x0ce7, 0x0d40, 0x0d41,
- 0x0d57, 0x0d58, 0x0d59, 0x0d5a, 0x0d5b, 0x0d5c, 0x0d5d, 0x0d98,
- 0x0d99, 0x0d9a, 0x0d9b, 0x0d9c, 0x0d9d, 0x0dad, 0x0dae, 0x0daf,
- 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3, 0x0dca, 0x0dcb, 0x0dec, 0x0ded,
- 0x0dee, 0x0def, 0x1018, 0x1022, 0x1023, 0x1030, 0x1031, 0x1032,
- 0x1033, 0x1050, 0x1051, 0x105c, 0x1074, 0x1075, 0x1076, 0x1077,
- 0x1078, 0x1079, 0x107a, 0x107b, 0x10b2, 0x10b3, 0x10b8, 0x10b9,
- 0x10ba, 0x10bb, 0x10d4, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x1404,
- 0x1405, 0x1406, 0x1407, 0x1410, 0x1411, 0x1412, 0x1413, 0x1414,
- 0x1415, 0x1416, 0x1417, 0x1418, 0x1419, 0x1466, 0x1467, 0x1468,
- 0x1469, 0x146a, 0x146b, 0x146c, 0x146d, 0x147e, 0x147f, 0x1488,
- 0x1489, 0x148a, 0x148b, 0x14b6, 0x14b7, 0x14b8, 0x14b9, 0x14ba,
- 0x14bb, 0x14bc, 0x14bd, 0x14f0, 0x14f1, 0x14f8, 0x14f9, 0x14fa,
- 0x14fb, 0x14fc, 0x14fd, 0x14fe, 0x14ff, 0x152a, 0x152b, 0x152c,
- 0x152d, 0x152e, 0x152f, 0x1530, 0x1531, 0x1548, 0x1549, 0x154e,
- 0x154f, 0x1558, 0x1559, 0x155a, 0x155b, 0x1572, 0x159a, 0x159b,
- 0x15ac, 0x15ba, 0x15bb, 0x15d0, 0x15d1, 0x15d2, 0x15d3, 0x15d4,
- 0x15d5, 0x181d, 0x181e, 0x181f, 0x1840, 0x1841, 0x1842, 0x1843,
- 0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x1861, 0x1862,
- 0x1863, 0x1864, 0x1865, 0x1866, 0x1867, 0x1868, 0x1869, 0x186a,
- 0x186b, 0x186c, 0x186d, 0x186e, 0x191b, 0x191c, 0x191d, 0x191e,
- 0x191f, 0x1942, 0x1943, 0x1944, 0x1945, 0x1946, 0x1947, 0x1958,
- 0x1959, 0x19ed, 0x19ee, 0x19ef, 0x19f0, 0x19f1, 0x19f2, 0x19f3,
- 0x19f4, 0x19f5, 0x19f6, 0x19f7, 0x1b0e, 0x1b0f, 0x1b62, 0x1b63,
- 0x1b64, 0x1b65, 0x1b66, 0x1b67, 0x1b68, 0x1b69, 0x1b6a, 0x1b6b,
- 0x1b6c, 0x1b6d, 0x1b6e, 0x1b6f, 0x1b82, 0x1ba8, 0x1ba9, 0x1baa,
- 0x1bab, 0x1bac, 0x1bad, 0x1bae, 0x1baf, 0x1bb0, 0x1bb1, 0x1bb2,
- 0x1bb3, 0x1d80, 0x1d81, 0x1d82, 0x1d83, 0x1d84, 0x1d85, 0x1d86,
- 0x1d87, 0x1d88, 0x1d89, 0x1d8a, 0x1d8b, 0x1d8c, 0x1d8d, 0x1007,
- 0x1008, 0x1009, 0x100a, 0x100b, 0x100c, 0x100d, 0x100e, 0x100f,
- 0x1016, 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086,
- 0x1087, 0x10c0, 0x123a, 0x123b, 0x123c, 0x123d, 0x123e, 0x123f,
- 0x1240, 0x1241, 0x1242, 0x1243, 0x1350, 0x1352, 0x1353, 0x1358,
- 0x1359, 0x135a, 0x135b, 0x135c, 0x135d, 0x135e, 0x135f, 0x1360,
- 0x1361, 0x1602, 0x1603, 0x160c, 0x160d, 0x160e, 0x160f, 0x1620,
- 0x1621, 0x1622, 0x1623, 0x1624, 0x1625, 0x1626, 0x1627, 0x1628,
- 0x1629, 0x166e, 0x166f, 0x167c, 0x167d, 0x167e, 0x167f, 0x1770,
- 0x1771, 0x1852, 0x1853, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876,
- 0x1877, 0x1878, 0x1879, 0x187a, 0x187b, 0x187c, 0x187d, 0x187e,
- 0x187f, 0x1918, 0x1919, 0x1926, 0x1927, 0x1970, 0x1971, 0x1972,
- 0x1973, 0x1974, 0x1975, 0x1976, 0x1977, 0x1978, 0x1979, 0x197a,
- 0x197b, 0x1aa0, 0x1aa1, 0x1aa2, 0x1aa3, 0x1aa4, 0x1aa5, 0x1aa6,
- 0x1aa7, 0x1aa8, 0x1aa9, 0x1aaa, 0x1aab, 0x1aac, 0x1aad, 0x1b3c,
- 0x1b3d, 0x1b3e, 0x1b3f, 0x1b50, 0x1b51, 0x1b52, 0x1b53, 0x1b54,
- 0x1b55, 0x1b56, 0x1b57, 0x1b58, 0x1b59, 0x2032, 0x2033, 0x2034,
- 0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203a, 0x203b, 0x203c,
- 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043, 0x20ba,
- 0x20bb, 0x20cc, 0x20cd, 0x20ce, 0x20cf, 0x20e0, 0x20e1, 0x20e2,
- 0x20e3, 0x20e4, 0x20e5, 0x20e6, 0x20e7, 0x21aa, 0x21ab, 0x21c0,
- 0x21c1, 0x21c2, 0x21c3, 0x21c4, 0x21c5, 0x21c6, 0x21c7, 0x21c8,
- 0x21c9, 0x21ca, 0x21cb, 0x21cc, 0x21cd, 0x21ce, 0x21cf, 0x21d0,
- 0x21d1, 0x21d2, 0x21d3, 0x2894, 0x2895, 0x2896, 0x2897, 0x2898,
- 0x2899, 0x289a, 0x289b, 0x289c, 0x289d, 0x289e, 0x289f, 0x28c0,
- 0x28c1, 0x28c2, 0x28c3, 0x28c4, 0x28c5, 0x28c6, 0x28c7, 0x28c8,
- 0x28c9, 0x28ca, 0x28cb, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934,
- 0x2935, 0x2936, 0x2937, 0x2938, 0x2939, 0x293a, 0x293b, 0x293c,
- 0x293d, 0x293e, 0x293f, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964,
- 0x2965, 0x2966, 0x2967, 0x2968, 0x2969, 0x296a, 0x296b, 0x2a40,
- 0x2a41, 0x2a42, 0x2a43, 0x2a44, 0x2a45, 0x2a46, 0x2a47, 0x2a48,
- 0x2a49, 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4d, 0x2a4e, 0x2a4f, 0x2a50,
- 0x2a51, 0x2a52, 0x2a53, 0x2ae6, 0x2ae7, 0x2b24, 0x2b25, 0x2b26,
- 0x2b27, 0x2b28, 0x2b29, 0x2b2a, 0x2b2b, 0x2b2c, 0x2b2d, 0x2b2e,
- 0x2b2f, 0x2b30, 0x2b31, 0x2b32, 0x2b33, 0x2b5a, 0x2b5b, 0x3014,
- 0x3015, 0x3016, 0x3017, 0x3020, 0x3021, 0x3022, 0x3023, 0x3024,
- 0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0x302a, 0x302b, 0x302c,
- 0x302d, 0x302e, 0x302f, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034,
- 0x3035, 0x3036, 0x3037, 0x3038, 0x3039, 0x30c0, 0x30c1, 0x30de,
- 0x30df, 0x3218, 0x3219, 0x321a, 0x321b, 0x321c, 0x321d, 0x321e,
- 0x321f, 0x3220, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, 0x3226,
- 0x3227, 0x3228, 0x3229, 0x322a, 0x322b, 0x322c, 0x322d, 0x322e,
- 0x322f, 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3378,
- 0x3379, 0x337a, 0x337b, 0x337c, 0x337d, 0x337e, 0x337f, 0x33c0,
- 0x33c1, 0x33c2, 0x33c3, 0x33c4, 0x33c5, 0x33c6, 0x33c7, 0x33c8,
- 0x33c9, 0x33ca, 0x33cb, 0x33cc, 0x33cd, 0x33ce, 0x33cf, 0x33d0,
- 0x33d1, 0x33d2, 0x33d3, 0x33d4, 0x33d5, 0x33d6, 0x33d7, 0x33d8,
- 0x33d9, 0x3706, 0x3707, 0x3730, 0x3731, 0x3732, 0x3733, 0x3734,
- 0x3735, 0x3736, 0x3737, 0x3738, 0x3739, 0x373a, 0x373b, 0x373c,
- 0x373d, 0x373e, 0x373f, 0x3740, 0x3741, 0x3742, 0x3743, 0x3744,
- 0x3745, 0x3746, 0x3747, 0x3748, 0x3749, 0x374a, 0x374b, 0x374c,
- 0x374d, 0x374e, 0x374f, 0x3b34, 0x3b35, 0x3b36, 0x3b37, 0x3be8,
- 0x3be9, 0x3bea, 0x3beb, 0x3bec, 0x3bed, 0x3bee, 0x3bef, 0x3bf0,
- 0x3bf1, 0x3bf2, 0x3bf3, 0x3bf4, 0x3bf5, 0x3bf6, 0x3bf7, 0x3bf8,
- 0x3bf9, 0x3bfa, 0x3bfb, 0x3bfc, 0x3bfd, 0x3bfe, 0x3bff, 0x2000,
- 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
- 0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x202e, 0x202f, 0x2182,
- 0x2183, 0x21b4, 0x21b5, 0x21b6, 0x21b7, 0x21b8, 0x21b9, 0x21ba,
- 0x21bb, 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x2460, 0x2461, 0x2462,
- 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246a,
- 0x246b, 0x246c, 0x246d, 0x246e, 0x246f, 0x2470, 0x2471, 0x2472,
- 0x2473, 0x26a2, 0x26a3, 0x000b,
+    0x0000, 0x0007, 0x0009, 0x000f, 0x000a, 0x0011, 0x001a, 0x001c,
+    0x0011, 0x0031, 0x0025, 0x002d, 0x002f, 0x006f, 0x0075, 0x0041,
+    0x004c, 0x004e, 0x005c, 0x0060, 0x0062, 0x0066, 0x0068, 0x0069,
+    0x006b, 0x00a6, 0x00c1, 0x00cb, 0x00cc, 0x00ce, 0x00da, 0x00e8,
+    0x00ee, 0x0087, 0x0090, 0x009e, 0x009f, 0x00ba, 0x00ca, 0x00d8,
+    0x00db, 0x00df, 0x0104, 0x0109, 0x010c, 0x0143, 0x0145, 0x014a,
+    0x0156, 0x015c, 0x01b3, 0x01d3, 0x01da, 0x0103, 0x0109, 0x010b,
+    0x0122, 0x0127, 0x0134, 0x0161, 0x0164, 0x0176, 0x0184, 0x018d,
+    0x018e, 0x018f, 0x0190, 0x0193, 0x0196, 0x019d, 0x019e, 0x019f,
+    0x01a9, 0x01b2, 0x01b4, 0x01ba, 0x01bb, 0x01bc, 0x0201, 0x0202,
+    0x0205, 0x0207, 0x020d, 0x0210, 0x0211, 0x0215, 0x021b, 0x021f,
+    0x0281, 0x0285, 0x0290, 0x029c, 0x029d, 0x02a2, 0x02a7, 0x02a8,
+    0x02aa, 0x02b0, 0x02b1, 0x02b4, 0x02bc, 0x02bf, 0x0320, 0x0326,
+    0x0327, 0x0329, 0x032a, 0x0336, 0x0360, 0x0362, 0x0363, 0x0372,
+    0x03b2, 0x03bc, 0x03bd, 0x0203, 0x0205, 0x021a, 0x0249, 0x024a,
+    0x024c, 0x02c7, 0x02ca, 0x02ce, 0x02ef, 0x030d, 0x0322, 0x0325,
+    0x0338, 0x0373, 0x037a, 0x0409, 0x0415, 0x0416, 0x0418, 0x0428,
+    0x042d, 0x042f, 0x0434, 0x0508, 0x0509, 0x0510, 0x0511, 0x051c,
+    0x051e, 0x0524, 0x0541, 0x0543, 0x0546, 0x0547, 0x054d, 0x0557,
+    0x055f, 0x056a, 0x056c, 0x056d, 0x056f, 0x0576, 0x0577, 0x057a,
+    0x057b, 0x057c, 0x057d, 0x0600, 0x0601, 0x0603, 0x0614, 0x0616,
+    0x0617, 0x061c, 0x061f, 0x0642, 0x0648, 0x0649, 0x064a, 0x064b,
+    0x0657, 0x0668, 0x0669, 0x066b, 0x066e, 0x067f, 0x06c2, 0x06c8,
+    0x06cb, 0x06de, 0x06df, 0x06e2, 0x06e3, 0x06ef, 0x0748, 0x074b,
+    0x076e, 0x076f, 0x077c, 0x0409, 0x0423, 0x0428, 0x0429, 0x042a,
+    0x042b, 0x0432, 0x0433, 0x0496, 0x049a, 0x04d5, 0x04db, 0x0581,
+    0x0582, 0x058b, 0x058c, 0x058d, 0x0598, 0x0599, 0x059a, 0x059e,
+    0x05dd, 0x0619, 0x0632, 0x0633, 0x0648, 0x0672, 0x06a1, 0x06a2,
+    0x06a3, 0x06af, 0x06e2, 0x06e3, 0x06e4, 0x0800, 0x0801, 0x0802,
+    0x0803, 0x081a, 0x081b, 0x0829, 0x082f, 0x0832, 0x083e, 0x083f,
+    0x0852, 0x0853, 0x0858, 0x086b, 0x0877, 0x0878, 0x0879, 0x087a,
+    0x087b, 0x0a00, 0x0a01, 0x0a0d, 0x0a0e, 0x0a0f, 0x0a24, 0x0a37,
+    0x0a3a, 0x0a3b, 0x0a3e, 0x0a46, 0x0a47, 0x0a4a, 0x0a4b, 0x0a5f,
+    0x0a79, 0x0a7a, 0x0a7b, 0x0a80, 0x0a81, 0x0a84, 0x0a85, 0x0a99,
+    0x0aa5, 0x0aa6, 0x0ab8, 0x0aba, 0x0abb, 0x0abc, 0x0abd, 0x0ac8,
+    0x0ace, 0x0acf, 0x0ad7, 0x0adc, 0x0aeb, 0x0c04, 0x0c25, 0x0c26,
+    0x0c27, 0x0c2a, 0x0c2b, 0x0c3a, 0x0c3b, 0x0c3c, 0x0c3d, 0x0ca0,
+    0x0cad, 0x0cd4, 0x0cd5, 0x0cfc, 0x0cfd, 0x0d86, 0x0d92, 0x0d93,
+    0x0d94, 0x0d95, 0x0db0, 0x0db8, 0x0db9, 0x0dba, 0x0dbb, 0x0dc0,
+    0x0dc2, 0x0dc3, 0x0dda, 0x0ddb, 0x0ddc, 0x0ddd, 0x0e92, 0x0e93,
+    0x0e94, 0x0e95, 0x0ec7, 0x0ecc, 0x0ece, 0x0ecf, 0x0ed8, 0x0ed9,
+    0x0eda, 0x0edb, 0x0808, 0x0809, 0x080a, 0x0810, 0x0811, 0x0844,
+    0x0845, 0x0861, 0x0862, 0x0863, 0x086c, 0x0922, 0x0923, 0x092e,
+    0x092f, 0x0936, 0x0937, 0x09b1, 0x09b2, 0x09b3, 0x09b4, 0x09b5,
+    0x09b8, 0x09b9, 0x09ba, 0x09bb, 0x09bc, 0x09bd, 0x09be, 0x09bf,
+    0x0b00, 0x0b15, 0x0b2c, 0x0b2d, 0x0b2e, 0x0b2f, 0x0b36, 0x0bb9,
+    0x0c28, 0x0c2a, 0x0c2b, 0x0c2c, 0x0c2d, 0x0c2e, 0x0c2f, 0x0c30,
+    0x0c31, 0x0c38, 0x0c60, 0x0c61, 0x0c62, 0x0c63, 0x0c8d, 0x0c8e,
+    0x0c8f, 0x0c92, 0x0cbe, 0x0cbf, 0x0ce6, 0x0ce7, 0x0d40, 0x0d41,
+    0x0d57, 0x0d58, 0x0d59, 0x0d5a, 0x0d5b, 0x0d5c, 0x0d5d, 0x0d98,
+    0x0d99, 0x0d9a, 0x0d9b, 0x0d9c, 0x0d9d, 0x0dad, 0x0dae, 0x0daf,
+    0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3, 0x0dca, 0x0dcb, 0x0dec, 0x0ded,
+    0x0dee, 0x0def, 0x1018, 0x1022, 0x1023, 0x1030, 0x1031, 0x1032,
+    0x1033, 0x1050, 0x1051, 0x105c, 0x1074, 0x1075, 0x1076, 0x1077,
+    0x1078, 0x1079, 0x107a, 0x107b, 0x10b2, 0x10b3, 0x10b8, 0x10b9,
+    0x10ba, 0x10bb, 0x10d4, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x1404,
+    0x1405, 0x1406, 0x1407, 0x1410, 0x1411, 0x1412, 0x1413, 0x1414,
+    0x1415, 0x1416, 0x1417, 0x1418, 0x1419, 0x1466, 0x1467, 0x1468,
+    0x1469, 0x146a, 0x146b, 0x146c, 0x146d, 0x147e, 0x147f, 0x1488,
+    0x1489, 0x148a, 0x148b, 0x14b6, 0x14b7, 0x14b8, 0x14b9, 0x14ba,
+    0x14bb, 0x14bc, 0x14bd, 0x14f0, 0x14f1, 0x14f8, 0x14f9, 0x14fa,
+    0x14fb, 0x14fc, 0x14fd, 0x14fe, 0x14ff, 0x152a, 0x152b, 0x152c,
+    0x152d, 0x152e, 0x152f, 0x1530, 0x1531, 0x1548, 0x1549, 0x154e,
+    0x154f, 0x1558, 0x1559, 0x155a, 0x155b, 0x1572, 0x159a, 0x159b,
+    0x15ac, 0x15ba, 0x15bb, 0x15d0, 0x15d1, 0x15d2, 0x15d3, 0x15d4,
+    0x15d5, 0x181d, 0x181e, 0x181f, 0x1840, 0x1841, 0x1842, 0x1843,
+    0x1844, 0x1845, 0x1846, 0x1847, 0x1848, 0x1849, 0x1861, 0x1862,
+    0x1863, 0x1864, 0x1865, 0x1866, 0x1867, 0x1868, 0x1869, 0x186a,
+    0x186b, 0x186c, 0x186d, 0x186e, 0x191b, 0x191c, 0x191d, 0x191e,
+    0x191f, 0x1942, 0x1943, 0x1944, 0x1945, 0x1946, 0x1947, 0x1958,
+    0x1959, 0x19ed, 0x19ee, 0x19ef, 0x19f0, 0x19f1, 0x19f2, 0x19f3,
+    0x19f4, 0x19f5, 0x19f6, 0x19f7, 0x1b0e, 0x1b0f, 0x1b62, 0x1b63,
+    0x1b64, 0x1b65, 0x1b66, 0x1b67, 0x1b68, 0x1b69, 0x1b6a, 0x1b6b,
+    0x1b6c, 0x1b6d, 0x1b6e, 0x1b6f, 0x1b82, 0x1ba8, 0x1ba9, 0x1baa,
+    0x1bab, 0x1bac, 0x1bad, 0x1bae, 0x1baf, 0x1bb0, 0x1bb1, 0x1bb2,
+    0x1bb3, 0x1d80, 0x1d81, 0x1d82, 0x1d83, 0x1d84, 0x1d85, 0x1d86,
+    0x1d87, 0x1d88, 0x1d89, 0x1d8a, 0x1d8b, 0x1d8c, 0x1d8d, 0x1007,
+    0x1008, 0x1009, 0x100a, 0x100b, 0x100c, 0x100d, 0x100e, 0x100f,
+    0x1016, 0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086,
+    0x1087, 0x10c0, 0x123a, 0x123b, 0x123c, 0x123d, 0x123e, 0x123f,
+    0x1240, 0x1241, 0x1242, 0x1243, 0x1350, 0x1352, 0x1353, 0x1358,
+    0x1359, 0x135a, 0x135b, 0x135c, 0x135d, 0x135e, 0x135f, 0x1360,
+    0x1361, 0x1602, 0x1603, 0x160c, 0x160d, 0x160e, 0x160f, 0x1620,
+    0x1621, 0x1622, 0x1623, 0x1624, 0x1625, 0x1626, 0x1627, 0x1628,
+    0x1629, 0x166e, 0x166f, 0x167c, 0x167d, 0x167e, 0x167f, 0x1770,
+    0x1771, 0x1852, 0x1853, 0x1872, 0x1873, 0x1874, 0x1875, 0x1876,
+    0x1877, 0x1878, 0x1879, 0x187a, 0x187b, 0x187c, 0x187d, 0x187e,
+    0x187f, 0x1918, 0x1919, 0x1926, 0x1927, 0x1970, 0x1971, 0x1972,
+    0x1973, 0x1974, 0x1975, 0x1976, 0x1977, 0x1978, 0x1979, 0x197a,
+    0x197b, 0x1aa0, 0x1aa1, 0x1aa2, 0x1aa3, 0x1aa4, 0x1aa5, 0x1aa6,
+    0x1aa7, 0x1aa8, 0x1aa9, 0x1aaa, 0x1aab, 0x1aac, 0x1aad, 0x1b3c,
+    0x1b3d, 0x1b3e, 0x1b3f, 0x1b50, 0x1b51, 0x1b52, 0x1b53, 0x1b54,
+    0x1b55, 0x1b56, 0x1b57, 0x1b58, 0x1b59, 0x2032, 0x2033, 0x2034,
+    0x2035, 0x2036, 0x2037, 0x2038, 0x2039, 0x203a, 0x203b, 0x203c,
+    0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043, 0x20ba,
+    0x20bb, 0x20cc, 0x20cd, 0x20ce, 0x20cf, 0x20e0, 0x20e1, 0x20e2,
+    0x20e3, 0x20e4, 0x20e5, 0x20e6, 0x20e7, 0x21aa, 0x21ab, 0x21c0,
+    0x21c1, 0x21c2, 0x21c3, 0x21c4, 0x21c5, 0x21c6, 0x21c7, 0x21c8,
+    0x21c9, 0x21ca, 0x21cb, 0x21cc, 0x21cd, 0x21ce, 0x21cf, 0x21d0,
+    0x21d1, 0x21d2, 0x21d3, 0x2894, 0x2895, 0x2896, 0x2897, 0x2898,
+    0x2899, 0x289a, 0x289b, 0x289c, 0x289d, 0x289e, 0x289f, 0x28c0,
+    0x28c1, 0x28c2, 0x28c3, 0x28c4, 0x28c5, 0x28c6, 0x28c7, 0x28c8,
+    0x28c9, 0x28ca, 0x28cb, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934,
+    0x2935, 0x2936, 0x2937, 0x2938, 0x2939, 0x293a, 0x293b, 0x293c,
+    0x293d, 0x293e, 0x293f, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964,
+    0x2965, 0x2966, 0x2967, 0x2968, 0x2969, 0x296a, 0x296b, 0x2a40,
+    0x2a41, 0x2a42, 0x2a43, 0x2a44, 0x2a45, 0x2a46, 0x2a47, 0x2a48,
+    0x2a49, 0x2a4a, 0x2a4b, 0x2a4c, 0x2a4d, 0x2a4e, 0x2a4f, 0x2a50,
+    0x2a51, 0x2a52, 0x2a53, 0x2ae6, 0x2ae7, 0x2b24, 0x2b25, 0x2b26,
+    0x2b27, 0x2b28, 0x2b29, 0x2b2a, 0x2b2b, 0x2b2c, 0x2b2d, 0x2b2e,
+    0x2b2f, 0x2b30, 0x2b31, 0x2b32, 0x2b33, 0x2b5a, 0x2b5b, 0x3014,
+    0x3015, 0x3016, 0x3017, 0x3020, 0x3021, 0x3022, 0x3023, 0x3024,
+    0x3025, 0x3026, 0x3027, 0x3028, 0x3029, 0x302a, 0x302b, 0x302c,
+    0x302d, 0x302e, 0x302f, 0x3030, 0x3031, 0x3032, 0x3033, 0x3034,
+    0x3035, 0x3036, 0x3037, 0x3038, 0x3039, 0x30c0, 0x30c1, 0x30de,
+    0x30df, 0x3218, 0x3219, 0x321a, 0x321b, 0x321c, 0x321d, 0x321e,
+    0x321f, 0x3220, 0x3221, 0x3222, 0x3223, 0x3224, 0x3225, 0x3226,
+    0x3227, 0x3228, 0x3229, 0x322a, 0x322b, 0x322c, 0x322d, 0x322e,
+    0x322f, 0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3378,
+    0x3379, 0x337a, 0x337b, 0x337c, 0x337d, 0x337e, 0x337f, 0x33c0,
+    0x33c1, 0x33c2, 0x33c3, 0x33c4, 0x33c5, 0x33c6, 0x33c7, 0x33c8,
+    0x33c9, 0x33ca, 0x33cb, 0x33cc, 0x33cd, 0x33ce, 0x33cf, 0x33d0,
+    0x33d1, 0x33d2, 0x33d3, 0x33d4, 0x33d5, 0x33d6, 0x33d7, 0x33d8,
+    0x33d9, 0x3706, 0x3707, 0x3730, 0x3731, 0x3732, 0x3733, 0x3734,
+    0x3735, 0x3736, 0x3737, 0x3738, 0x3739, 0x373a, 0x373b, 0x373c,
+    0x373d, 0x373e, 0x373f, 0x3740, 0x3741, 0x3742, 0x3743, 0x3744,
+    0x3745, 0x3746, 0x3747, 0x3748, 0x3749, 0x374a, 0x374b, 0x374c,
+    0x374d, 0x374e, 0x374f, 0x3b34, 0x3b35, 0x3b36, 0x3b37, 0x3be8,
+    0x3be9, 0x3bea, 0x3beb, 0x3bec, 0x3bed, 0x3bee, 0x3bef, 0x3bf0,
+    0x3bf1, 0x3bf2, 0x3bf3, 0x3bf4, 0x3bf5, 0x3bf6, 0x3bf7, 0x3bf8,
+    0x3bf9, 0x3bfa, 0x3bfb, 0x3bfc, 0x3bfd, 0x3bfe, 0x3bff, 0x2000,
+    0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008,
+    0x2009, 0x200a, 0x200b, 0x200c, 0x200d, 0x202e, 0x202f, 0x2182,
+    0x2183, 0x21b4, 0x21b5, 0x21b6, 0x21b7, 0x21b8, 0x21b9, 0x21ba,
+    0x21bb, 0x21bc, 0x21bd, 0x21be, 0x21bf, 0x2460, 0x2461, 0x2462,
+    0x2463, 0x2464, 0x2465, 0x2466, 0x2467, 0x2468, 0x2469, 0x246a,
+    0x246b, 0x246c, 0x246d, 0x246e, 0x246f, 0x2470, 0x2471, 0x2472,
+    0x2473, 0x26a2, 0x26a3, 0x000b,
 };
 
 static const uint8_t table1_mv_bits[1100] = {
-  2,  4,  4,  4,  5,  5,  5,  5,
-  6,  6,  7,  7,  7,  7,  7,  8,
-  8,  8,  8,  8,  8,  8,  8,  8,
-  8,  8,  8,  8,  8,  8,  8,  8,
-  8,  9,  9,  9,  9,  9,  9,  9,
-  9,  9,  9,  9,  9,  9,  9,  9,
-  9,  9,  9,  9,  9, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15,  4,
+     2,  4,  4,  4,  5,  5,  5,  5,
+     6,  6,  7,  7,  7,  7,  7,  8,
+     8,  8,  8,  8,  8,  8,  8,  8,
+     8,  8,  8,  8,  8,  8,  8,  8,
+     8,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15,  4,
 };
 
 static const uint8_t table1_mvx[1099] = {
- 32, 31, 32, 31, 33, 32, 33, 33,
- 31, 34, 30, 32, 32, 34, 35, 32,
- 34, 33, 29, 30, 30, 32, 31, 31,
- 33, 35, 35, 33, 31, 29, 29, 33,
- 34, 30, 31, 28, 36, 30, 34, 32,
- 32, 37, 32, 32, 25, 27, 39, 32,
- 32, 32, 38, 35, 36, 32, 37, 61,
- 26, 32, 34, 35,  3, 35, 27, 28,
- 29, 34, 28, 37, 31, 36, 32, 27,
- 31, 30, 29, 39, 33, 29, 33, 35,
- 25, 25, 29, 33, 31, 31, 31, 33,
- 32, 30, 32, 32, 41, 39, 33, 36,
- 32, 28, 34, 36, 38, 24, 60, 31,
- 23, 28, 32, 33, 59, 32, 40, 30,
-  5, 34, 32, 38, 32, 30, 43,  4,
- 32, 32, 42, 31, 31, 32, 26, 38,
- 26, 22, 21, 37, 61, 63, 37, 31,
- 32, 33,  2,  1, 23, 33, 41, 27,
- 35, 30, 38, 23, 33,  3, 28, 34,
- 34, 27, 41, 29, 39, 35, 36, 29,
- 32, 27, 30, 32, 24, 61, 37, 26,
- 59, 25, 35, 27, 36, 37, 30, 31,
- 34, 40,  3, 28, 34, 39, 32, 31,
- 32, 30, 24, 28, 35, 36, 26, 32,
- 31, 33, 29, 33, 39, 25, 30, 24,
- 35, 59, 29, 34, 25, 30, 21, 35,
- 43, 40, 32, 29,  5, 28, 31, 62,
- 33, 33, 25, 31, 21, 31, 43, 31,
- 34, 33, 20, 40, 39, 31, 31, 57,
- 38, 32, 42, 33, 32, 31, 32, 29,
- 30, 44,  5, 31, 22, 34, 36, 17,
- 38, 58, 38, 35, 32, 60, 35, 24,
- 32, 38, 16, 45, 42, 32, 31, 29,
-  4, 30, 17, 40, 46, 48, 63, 32,
- 42, 19, 41, 22, 28, 36, 45, 33,
- 33, 32, 29,  7, 41, 42, 18, 33,
- 33, 32, 22, 37,  1, 26, 22, 23,
- 49, 28, 26, 27, 32, 33, 27, 23,
- 28, 36, 15,  6, 34, 27, 31, 26,
- 23,  2, 33, 32, 34, 41, 28, 32,
- 41,  0, 36, 38, 34, 31, 47, 32,
- 17, 31, 39, 33, 37, 51, 30, 47,
- 32, 50, 32, 19, 63, 30, 25, 27,
- 33, 62, 24, 31, 27, 30, 37, 31,
- 45, 32, 39, 20, 46, 47, 35, 19,
- 34,  1, 49, 21, 21, 14, 51, 26,
- 23, 31, 36, 35, 58, 29, 29, 21,
- 20, 42, 13, 28, 12, 40, 31, 33,
- 39, 60, 32, 44, 33, 31, 28, 37,
- 29, 32, 30, 49, 43, 28, 39, 25,
- 32, 48,  2, 15, 20, 25, 31, 28,
- 21, 24, 25, 15, 31, 17, 37, 43,
- 18, 32, 33, 24, 33, 36, 13, 33,
- 31, 39, 11, 31, 33, 32, 39, 37,
- 32, 32, 29, 17, 44, 46, 36, 35,
- 26, 37, 58, 32, 34, 38,  8, 38,
- 38, 22, 29, 25, 16, 35, 32, 35,
- 33, 43, 18, 46, 38, 50, 33, 18,
- 53, 60, 13, 32, 36, 33, 51, 36,
- 43, 45, 27, 42, 29, 24, 30, 25,
- 31, 52, 31, 35, 38,  9, 22, 34,
-  4, 17, 28, 55, 42, 25, 17, 20,
- 47, 34, 33, 16, 40, 25, 16, 30,
- 53, 29, 10, 11, 14, 26, 33,  4,
- 35, 44, 26, 16, 31, 26, 34, 38,
- 29, 31, 30, 24, 22, 61, 32,  9,
- 45, 34, 31, 19,  9, 31, 46, 31,
- 35, 54, 29, 57, 30, 50,  3, 31,
- 63, 34, 47, 41, 51, 18, 31, 14,
- 37, 38, 31, 24, 32, 31, 50, 33,
- 31, 54, 27,  9, 33, 23, 19, 32,
- 29, 29, 33, 28, 47, 49, 30, 47,
- 33, 27, 25, 54, 44, 45, 50, 58,
- 51, 48, 33, 59, 33, 34, 57, 13,
- 26, 33, 13, 48, 30, 11,  7, 56,
- 34, 55, 26,  0, 26, 35,  1, 51,
- 33, 53, 31, 45, 12, 29, 29, 51,
- 31, 48,  2,  6, 34, 30, 28, 33,
- 60, 40, 27, 46, 31,  9, 35, 29,
- 31, 39, 55, 46, 19, 37, 62, 34,
- 30, 16, 19, 49, 41, 41, 39, 37,
- 14,  5, 13, 35, 55, 30, 40, 40,
- 42,  8, 20, 25, 45, 35, 33, 36,
- 54, 38, 27, 37, 62, 40, 15, 59,
- 49, 31, 29, 34, 34, 39, 24, 29,
- 25, 29, 21, 29, 10, 61, 33, 49,
- 35, 34,  3, 38, 39, 29,  7, 41,
-  1, 35,  4, 23, 15, 23, 11, 37,
- 28, 35, 30, 30, 24,  1, 43, 56,
-  8, 34, 42, 24, 45, 30, 20, 23,
-  8, 38, 22, 33, 17, 52, 34, 22,
- 53, 43, 44,  1, 27, 31, 41, 43,
- 41, 30, 31, 36, 30,  5, 55, 31,
- 33, 30, 40, 23, 15, 29, 34, 34,
- 59, 34, 30, 11, 13, 38,  5,  0,
- 30, 42,  5, 30, 29, 34, 10, 44,
- 30, 63, 35, 12,  3, 26, 15, 17,
- 25, 34, 43, 39, 34, 56, 29, 23,
- 30, 12, 30, 10, 35,  9, 24, 58,
- 10, 12, 54, 33, 37, 20, 41, 35,
- 29, 18, 61, 30, 40, 24, 39, 53,
- 62, 26, 29, 33, 34, 53, 49, 21,
- 27, 11, 63, 20, 26, 23,  7, 13,
-  6, 47, 29, 30,  9, 51, 22, 34,
- 21, 25, 33, 56, 57, 30, 38, 51,
- 51, 38, 63, 28, 40, 35, 33, 18,
- 33, 33, 24, 58, 58, 34, 49, 29,
- 43,  4,  1,  4, 42, 35, 35, 30,
- 17,  5, 56, 61, 25, 37, 36, 55,
- 28, 35, 29, 50, 48, 52,  2, 42,
- 34, 40, 46, 46, 43, 35, 29, 48,
- 20, 29, 31, 41,  7, 30, 35, 19,
- 14, 21,  8, 39, 39, 40, 46, 55,
- 34,  6, 30, 34, 37, 25, 37, 33,
- 22, 44, 52, 17, 35, 29, 36, 35,
- 40, 37, 28, 30, 50, 14, 28, 55,
-  6, 23, 19, 14, 30,  3, 30, 28,
- 28, 61, 61, 47, 45, 48, 40, 40,
- 34, 34, 25, 30, 29, 35,  4, 26,
- 53, 50, 26, 41, 27, 59, 27, 38,
- 39,  3, 50, 43, 47, 23, 33, 55,
- 35, 21, 23, 35, 61, 33, 46, 52,
- 35, 34, 24, 30, 43, 16, 37, 21,
-  2, 24, 45, 34, 30, 55, 55,  1,
- 29, 29, 26, 28, 25, 31, 36, 22,
- 17, 30, 52,  2, 44, 44, 57, 26,
- 62, 41, 39, 57, 26, 46, 49, 11,
- 16, 19,  5, 59, 38, 39, 58, 38,
- 25, 49, 50, 22, 28, 59,  9, 59,
-  7, 28, 55, 17,  4, 35, 50, 21,
- 29, 44, 47, 18, 24, 19, 25, 42,
- 35,  3, 51, 35, 16, 35, 30, 63,
- 57, 39, 39, 25, 35, 38,  9, 16,
- 36, 45, 31, 60, 14, 34, 42, 24,
-  0, 37, 18, 61, 57, 37, 28, 53,
- 20, 46, 14, 47, 38, 38, 38,  9,
- 34, 39, 43, 17, 39, 59,  5, 27,
-  0, 12, 27,
+    32, 31, 32, 31, 33, 32, 33, 33,
+    31, 34, 30, 32, 32, 34, 35, 32,
+    34, 33, 29, 30, 30, 32, 31, 31,
+    33, 35, 35, 33, 31, 29, 29, 33,
+    34, 30, 31, 28, 36, 30, 34, 32,
+    32, 37, 32, 32, 25, 27, 39, 32,
+    32, 32, 38, 35, 36, 32, 37, 61,
+    26, 32, 34, 35,  3, 35, 27, 28,
+    29, 34, 28, 37, 31, 36, 32, 27,
+    31, 30, 29, 39, 33, 29, 33, 35,
+    25, 25, 29, 33, 31, 31, 31, 33,
+    32, 30, 32, 32, 41, 39, 33, 36,
+    32, 28, 34, 36, 38, 24, 60, 31,
+    23, 28, 32, 33, 59, 32, 40, 30,
+     5, 34, 32, 38, 32, 30, 43,  4,
+    32, 32, 42, 31, 31, 32, 26, 38,
+    26, 22, 21, 37, 61, 63, 37, 31,
+    32, 33,  2,  1, 23, 33, 41, 27,
+    35, 30, 38, 23, 33,  3, 28, 34,
+    34, 27, 41, 29, 39, 35, 36, 29,
+    32, 27, 30, 32, 24, 61, 37, 26,
+    59, 25, 35, 27, 36, 37, 30, 31,
+    34, 40,  3, 28, 34, 39, 32, 31,
+    32, 30, 24, 28, 35, 36, 26, 32,
+    31, 33, 29, 33, 39, 25, 30, 24,
+    35, 59, 29, 34, 25, 30, 21, 35,
+    43, 40, 32, 29,  5, 28, 31, 62,
+    33, 33, 25, 31, 21, 31, 43, 31,
+    34, 33, 20, 40, 39, 31, 31, 57,
+    38, 32, 42, 33, 32, 31, 32, 29,
+    30, 44,  5, 31, 22, 34, 36, 17,
+    38, 58, 38, 35, 32, 60, 35, 24,
+    32, 38, 16, 45, 42, 32, 31, 29,
+     4, 30, 17, 40, 46, 48, 63, 32,
+    42, 19, 41, 22, 28, 36, 45, 33,
+    33, 32, 29,  7, 41, 42, 18, 33,
+    33, 32, 22, 37,  1, 26, 22, 23,
+    49, 28, 26, 27, 32, 33, 27, 23,
+    28, 36, 15,  6, 34, 27, 31, 26,
+    23,  2, 33, 32, 34, 41, 28, 32,
+    41,  0, 36, 38, 34, 31, 47, 32,
+    17, 31, 39, 33, 37, 51, 30, 47,
+    32, 50, 32, 19, 63, 30, 25, 27,
+    33, 62, 24, 31, 27, 30, 37, 31,
+    45, 32, 39, 20, 46, 47, 35, 19,
+    34,  1, 49, 21, 21, 14, 51, 26,
+    23, 31, 36, 35, 58, 29, 29, 21,
+    20, 42, 13, 28, 12, 40, 31, 33,
+    39, 60, 32, 44, 33, 31, 28, 37,
+    29, 32, 30, 49, 43, 28, 39, 25,
+    32, 48,  2, 15, 20, 25, 31, 28,
+    21, 24, 25, 15, 31, 17, 37, 43,
+    18, 32, 33, 24, 33, 36, 13, 33,
+    31, 39, 11, 31, 33, 32, 39, 37,
+    32, 32, 29, 17, 44, 46, 36, 35,
+    26, 37, 58, 32, 34, 38,  8, 38,
+    38, 22, 29, 25, 16, 35, 32, 35,
+    33, 43, 18, 46, 38, 50, 33, 18,
+    53, 60, 13, 32, 36, 33, 51, 36,
+    43, 45, 27, 42, 29, 24, 30, 25,
+    31, 52, 31, 35, 38,  9, 22, 34,
+     4, 17, 28, 55, 42, 25, 17, 20,
+    47, 34, 33, 16, 40, 25, 16, 30,
+    53, 29, 10, 11, 14, 26, 33,  4,
+    35, 44, 26, 16, 31, 26, 34, 38,
+    29, 31, 30, 24, 22, 61, 32,  9,
+    45, 34, 31, 19,  9, 31, 46, 31,
+    35, 54, 29, 57, 30, 50,  3, 31,
+    63, 34, 47, 41, 51, 18, 31, 14,
+    37, 38, 31, 24, 32, 31, 50, 33,
+    31, 54, 27,  9, 33, 23, 19, 32,
+    29, 29, 33, 28, 47, 49, 30, 47,
+    33, 27, 25, 54, 44, 45, 50, 58,
+    51, 48, 33, 59, 33, 34, 57, 13,
+    26, 33, 13, 48, 30, 11,  7, 56,
+    34, 55, 26,  0, 26, 35,  1, 51,
+    33, 53, 31, 45, 12, 29, 29, 51,
+    31, 48,  2,  6, 34, 30, 28, 33,
+    60, 40, 27, 46, 31,  9, 35, 29,
+    31, 39, 55, 46, 19, 37, 62, 34,
+    30, 16, 19, 49, 41, 41, 39, 37,
+    14,  5, 13, 35, 55, 30, 40, 40,
+    42,  8, 20, 25, 45, 35, 33, 36,
+    54, 38, 27, 37, 62, 40, 15, 59,
+    49, 31, 29, 34, 34, 39, 24, 29,
+    25, 29, 21, 29, 10, 61, 33, 49,
+    35, 34,  3, 38, 39, 29,  7, 41,
+     1, 35,  4, 23, 15, 23, 11, 37,
+    28, 35, 30, 30, 24,  1, 43, 56,
+     8, 34, 42, 24, 45, 30, 20, 23,
+     8, 38, 22, 33, 17, 52, 34, 22,
+    53, 43, 44,  1, 27, 31, 41, 43,
+    41, 30, 31, 36, 30,  5, 55, 31,
+    33, 30, 40, 23, 15, 29, 34, 34,
+    59, 34, 30, 11, 13, 38,  5,  0,
+    30, 42,  5, 30, 29, 34, 10, 44,
+    30, 63, 35, 12,  3, 26, 15, 17,
+    25, 34, 43, 39, 34, 56, 29, 23,
+    30, 12, 30, 10, 35,  9, 24, 58,
+    10, 12, 54, 33, 37, 20, 41, 35,
+    29, 18, 61, 30, 40, 24, 39, 53,
+    62, 26, 29, 33, 34, 53, 49, 21,
+    27, 11, 63, 20, 26, 23,  7, 13,
+     6, 47, 29, 30,  9, 51, 22, 34,
+    21, 25, 33, 56, 57, 30, 38, 51,
+    51, 38, 63, 28, 40, 35, 33, 18,
+    33, 33, 24, 58, 58, 34, 49, 29,
+    43,  4,  1,  4, 42, 35, 35, 30,
+    17,  5, 56, 61, 25, 37, 36, 55,
+    28, 35, 29, 50, 48, 52,  2, 42,
+    34, 40, 46, 46, 43, 35, 29, 48,
+    20, 29, 31, 41,  7, 30, 35, 19,
+    14, 21,  8, 39, 39, 40, 46, 55,
+    34,  6, 30, 34, 37, 25, 37, 33,
+    22, 44, 52, 17, 35, 29, 36, 35,
+    40, 37, 28, 30, 50, 14, 28, 55,
+     6, 23, 19, 14, 30,  3, 30, 28,
+    28, 61, 61, 47, 45, 48, 40, 40,
+    34, 34, 25, 30, 29, 35,  4, 26,
+    53, 50, 26, 41, 27, 59, 27, 38,
+    39,  3, 50, 43, 47, 23, 33, 55,
+    35, 21, 23, 35, 61, 33, 46, 52,
+    35, 34, 24, 30, 43, 16, 37, 21,
+     2, 24, 45, 34, 30, 55, 55,  1,
+    29, 29, 26, 28, 25, 31, 36, 22,
+    17, 30, 52,  2, 44, 44, 57, 26,
+    62, 41, 39, 57, 26, 46, 49, 11,
+    16, 19,  5, 59, 38, 39, 58, 38,
+    25, 49, 50, 22, 28, 59,  9, 59,
+     7, 28, 55, 17,  4, 35, 50, 21,
+    29, 44, 47, 18, 24, 19, 25, 42,
+    35,  3, 51, 35, 16, 35, 30, 63,
+    57, 39, 39, 25, 35, 38,  9, 16,
+    36, 45, 31, 60, 14, 34, 42, 24,
+     0, 37, 18, 61, 57, 37, 28, 53,
+    20, 46, 14, 47, 38, 38, 38,  9,
+    34, 39, 43, 17, 39, 59,  5, 27,
+     0, 12, 27,
 };
 
 static const uint8_t table1_mvy[1099] = {
- 32, 32, 31, 31, 32, 33, 31, 33,
- 33, 32, 32, 30, 34, 31, 32, 29,
- 33, 30, 32, 33, 31, 35, 34, 30,
- 34, 31, 33, 29, 29, 31, 33, 35,
- 30, 30, 35, 32, 32, 34, 34, 28,
- 25, 32, 36, 27, 32, 32, 32, 37,
- 39,  3, 32, 30, 31, 26, 31, 32,
- 32, 38, 29, 29, 32, 34, 31, 31,
- 34, 35, 33, 33, 28, 33,  1, 33,
- 27, 29, 30, 31, 28, 29, 37, 35,
- 31, 33, 35, 27, 36, 37, 25, 25,
- 61, 35,  4,  5, 32, 33, 36, 30,
- 23, 30, 28, 34, 31, 32, 32, 39,
- 32, 34, 21, 39, 32, 59, 32, 28,
- 32, 36, 60, 33, 24, 36, 32, 32,
- 41,  2, 32, 38, 26, 22, 33, 30,
- 31, 32, 32, 30, 31, 32, 29,  3,
- 40, 38, 32, 32, 33, 26, 31, 34,
- 28, 38, 34, 31,  3, 31, 35, 38,
- 27, 35, 33, 28, 29, 27, 29, 27,
- 43, 29, 37, 63, 31, 33, 34, 30,
- 31, 30, 37, 30, 35, 35, 26, 41,
- 37, 31, 33, 28, 26, 30, 42, 24,
-  7, 27, 33, 29, 36, 28, 34, 57,
- 23, 41, 36, 23, 35, 34, 25, 30,
- 25, 33, 25, 25, 29, 24, 33, 39,
- 33, 33,  0, 37, 31, 36, 21, 32,
- 61, 24, 35, 61, 31,  5, 31, 59,
- 39, 21, 32, 30, 34, 22, 40, 32,
- 29, 16, 31,  5, 62,  2, 20, 39,
- 39, 32, 33,  1, 31, 24, 36, 32,
- 36, 32, 28, 26,  6, 31, 38, 34,
- 58, 35, 32, 33, 33, 17, 43, 26,
- 31, 40, 31, 34, 32, 32, 31, 19,
- 30, 32, 29, 33, 38, 38, 32, 59,
- 40, 18, 38, 32, 35, 34, 32, 17,
-  1, 15, 30, 28, 31, 28, 34, 29,
- 32, 27, 35, 27, 49, 22, 37, 34,
- 37, 26, 32, 32, 22, 28, 45, 29,
- 30, 31, 43, 46, 41, 30, 26, 13,
- 34, 32, 27, 38, 42, 42, 33, 47,
- 33, 60, 27, 42, 25, 32, 22, 32,
- 48, 32, 45, 33, 33, 41, 27, 25,
- 19, 31, 35, 19, 36, 42, 27, 17,
- 31, 44, 28, 33, 33, 31, 23, 31,
- 40, 33, 31, 34, 30, 32, 33, 36,
- 35, 47, 37, 41, 31, 23, 41, 29,
- 30, 35, 32, 25, 32, 28, 58,  2,
- 37, 33, 14, 33, 49, 20, 39, 36,
- 21,  9, 23, 33, 35, 24, 39, 37,
- 11, 33, 30, 31, 31, 28, 51, 40,
- 35, 29, 25, 33, 46, 35, 37, 30,
- 30,  8, 63, 28, 15, 40, 33, 45,
- 49, 25, 32,  4, 47, 51, 36, 39,
- 53, 10, 24, 29, 30, 31, 25, 40,
- 38, 38, 33, 56, 23, 27, 32, 37,
- 26, 29, 43, 36, 33, 24, 55, 43,
-  9, 29, 34, 34, 24, 33, 18, 33,
- 33, 30, 31, 50, 24, 60, 30, 39,
- 34, 30, 39, 28, 22, 38,  2, 26,
- 63, 32, 57, 21, 39, 33, 28, 18,
- 30, 34, 22, 33, 29, 41, 30, 34,
- 35, 21, 13, 34, 35, 39, 30, 46,
- 32, 42, 32, 31, 33, 26, 11, 33,
- 22, 31, 25, 31, 53, 27, 43, 25,
- 40, 50, 21, 36, 38, 30, 12, 31,
- 34, 20, 15, 29, 32, 62, 30, 13,
- 17, 32, 19, 31, 20, 31, 30,  7,
-  1, 17, 34, 37, 31, 31, 44, 34,
- 26, 40, 16, 37, 52, 48, 30, 20,
- 18, 33, 38, 29,  7, 25, 30, 54,
- 45, 47, 46, 41, 29, 29, 16, 30,
- 14, 26, 38, 34, 34, 29, 34, 30,
- 29, 30, 57, 30,  4, 46, 33, 29,
- 39, 44, 30, 31, 50, 33, 31, 32,
- 19, 32, 40, 31, 37, 47,  1, 35,
- 16, 31,  0, 35, 33,  1, 17, 34,
-  9, 34, 33, 31, 49, 43, 42, 51,
- 34, 29, 23, 29, 14, 30, 45, 49,
- 11, 24, 31, 28, 35, 41, 30, 44,
- 18, 29, 34, 35, 36, 25, 26, 21,
- 31, 30, 34, 19, 34, 44, 36, 38,
- 25, 31, 28, 23, 37,  3, 55, 41,
- 30, 22, 41, 24, 33, 26, 35, 35,
- 30, 55, 51, 47, 48, 38, 24, 15,
- 21, 50, 25, 46, 30, 29, 10, 34,
- 42, 45, 29, 42, 22,  3, 33, 27,
- 34,  1, 34, 28, 34, 36, 35, 23,
- 23, 13, 58,  3, 26, 63, 25, 31,
- 34, 61, 38, 39, 25, 61, 29, 37,
- 30, 41, 26, 48, 28, 33, 50, 35,
- 30, 37, 29, 29, 40,  6, 39, 28,
- 28, 19,  8, 22, 45, 34, 35, 10,
- 58, 17, 37, 39, 30, 18, 54, 14,
- 29, 16, 59, 30, 35, 23, 35, 30,
- 47, 36, 29, 55, 20, 12, 31, 35,
- 14, 29, 18, 34, 34, 24, 29, 26,
- 22,  2, 27, 23,  8, 30, 55, 38,
- 60, 31,  4, 34, 49, 34, 27, 34,
- 33, 30, 31, 54, 42, 35, 38, 46,
- 44, 26, 27,  9, 39, 25, 21, 29,
- 28, 42, 13,  0,  5, 34, 37, 28,
- 24, 29, 63, 26, 22, 27, 29, 25,
- 33, 25, 61,  0, 35, 25, 36, 15,
- 27, 40, 53, 33,  3, 10, 16, 37,
- 38, 18, 30, 46, 27,  9,  6, 29,
- 62,  8, 42, 28, 29,  3, 25, 16,
- 26, 29, 35, 28, 27, 51, 61, 48,
- 37,  9, 34,  7, 49, 45, 20, 29,
- 21,  5,  5, 29, 28, 34, 29, 24,
- 10, 24, 35, 36, 38, 55, 11, 36,
- 38, 53, 54, 26, 30, 49, 20, 27,
- 30, 39, 33, 41, 49, 22, 38, 38,
-  4, 30,  8,  9,  3, 24, 22, 50,
- 37, 36, 31, 27,  2,  9, 42, 63,
- 25, 19, 44,  1, 28, 28, 48, 30,
- 34, 41, 41, 38, 12, 27, 15,  0,
- 16, 34, 35, 38, 28, 29, 40, 42,
- 51, 52, 45, 54, 59, 59, 42, 44,
- 37, 26, 46, 24, 15, 39, 22, 46,
- 19, 35, 38, 17, 37, 23, 52, 55,
- 50, 37, 26, 11, 37, 12, 24, 30,
- 16, 13, 22, 13, 36, 35, 40, 41,
- 34, 41, 26, 53, 51,  5, 21, 30,
-  2, 63, 41, 20,  1, 56, 21, 24,
- 25,  5, 28, 35, 26, 28, 30, 18,
- 29, 23, 40, 34, 20, 42, 39, 34,
- 28, 61, 38, 27, 62,  9, 36, 17,
-  9, 49, 24, 25, 54, 34, 39, 37,
-  3,  1, 25, 38, 38, 44, 35, 36,
- 12, 60, 36, 38, 40, 25, 43, 39,
- 53, 28, 39, 57, 46, 10, 52, 27,
- 35, 42, 45, 59, 15, 60, 38, 24,
- 23, 39, 12, 29, 24,  0, 20, 16,
- 28, 43, 35, 28,  1, 49,  4, 21,
- 42, 39, 29,  3, 44, 21, 53, 55,
- 11,  5,  3, 39, 53, 28, 25, 19,
- 34, 28, 21,
+    32, 32, 31, 31, 32, 33, 31, 33,
+    33, 32, 32, 30, 34, 31, 32, 29,
+    33, 30, 32, 33, 31, 35, 34, 30,
+    34, 31, 33, 29, 29, 31, 33, 35,
+    30, 30, 35, 32, 32, 34, 34, 28,
+    25, 32, 36, 27, 32, 32, 32, 37,
+    39,  3, 32, 30, 31, 26, 31, 32,
+    32, 38, 29, 29, 32, 34, 31, 31,
+    34, 35, 33, 33, 28, 33,  1, 33,
+    27, 29, 30, 31, 28, 29, 37, 35,
+    31, 33, 35, 27, 36, 37, 25, 25,
+    61, 35,  4,  5, 32, 33, 36, 30,
+    23, 30, 28, 34, 31, 32, 32, 39,
+    32, 34, 21, 39, 32, 59, 32, 28,
+    32, 36, 60, 33, 24, 36, 32, 32,
+    41,  2, 32, 38, 26, 22, 33, 30,
+    31, 32, 32, 30, 31, 32, 29,  3,
+    40, 38, 32, 32, 33, 26, 31, 34,
+    28, 38, 34, 31,  3, 31, 35, 38,
+    27, 35, 33, 28, 29, 27, 29, 27,
+    43, 29, 37, 63, 31, 33, 34, 30,
+    31, 30, 37, 30, 35, 35, 26, 41,
+    37, 31, 33, 28, 26, 30, 42, 24,
+     7, 27, 33, 29, 36, 28, 34, 57,
+    23, 41, 36, 23, 35, 34, 25, 30,
+    25, 33, 25, 25, 29, 24, 33, 39,
+    33, 33,  0, 37, 31, 36, 21, 32,
+    61, 24, 35, 61, 31,  5, 31, 59,
+    39, 21, 32, 30, 34, 22, 40, 32,
+    29, 16, 31,  5, 62,  2, 20, 39,
+    39, 32, 33,  1, 31, 24, 36, 32,
+    36, 32, 28, 26,  6, 31, 38, 34,
+    58, 35, 32, 33, 33, 17, 43, 26,
+    31, 40, 31, 34, 32, 32, 31, 19,
+    30, 32, 29, 33, 38, 38, 32, 59,
+    40, 18, 38, 32, 35, 34, 32, 17,
+     1, 15, 30, 28, 31, 28, 34, 29,
+    32, 27, 35, 27, 49, 22, 37, 34,
+    37, 26, 32, 32, 22, 28, 45, 29,
+    30, 31, 43, 46, 41, 30, 26, 13,
+    34, 32, 27, 38, 42, 42, 33, 47,
+    33, 60, 27, 42, 25, 32, 22, 32,
+    48, 32, 45, 33, 33, 41, 27, 25,
+    19, 31, 35, 19, 36, 42, 27, 17,
+    31, 44, 28, 33, 33, 31, 23, 31,
+    40, 33, 31, 34, 30, 32, 33, 36,
+    35, 47, 37, 41, 31, 23, 41, 29,
+    30, 35, 32, 25, 32, 28, 58,  2,
+    37, 33, 14, 33, 49, 20, 39, 36,
+    21,  9, 23, 33, 35, 24, 39, 37,
+    11, 33, 30, 31, 31, 28, 51, 40,
+    35, 29, 25, 33, 46, 35, 37, 30,
+    30,  8, 63, 28, 15, 40, 33, 45,
+    49, 25, 32,  4, 47, 51, 36, 39,
+    53, 10, 24, 29, 30, 31, 25, 40,
+    38, 38, 33, 56, 23, 27, 32, 37,
+    26, 29, 43, 36, 33, 24, 55, 43,
+     9, 29, 34, 34, 24, 33, 18, 33,
+    33, 30, 31, 50, 24, 60, 30, 39,
+    34, 30, 39, 28, 22, 38,  2, 26,
+    63, 32, 57, 21, 39, 33, 28, 18,
+    30, 34, 22, 33, 29, 41, 30, 34,
+    35, 21, 13, 34, 35, 39, 30, 46,
+    32, 42, 32, 31, 33, 26, 11, 33,
+    22, 31, 25, 31, 53, 27, 43, 25,
+    40, 50, 21, 36, 38, 30, 12, 31,
+    34, 20, 15, 29, 32, 62, 30, 13,
+    17, 32, 19, 31, 20, 31, 30,  7,
+     1, 17, 34, 37, 31, 31, 44, 34,
+    26, 40, 16, 37, 52, 48, 30, 20,
+    18, 33, 38, 29,  7, 25, 30, 54,
+    45, 47, 46, 41, 29, 29, 16, 30,
+    14, 26, 38, 34, 34, 29, 34, 30,
+    29, 30, 57, 30,  4, 46, 33, 29,
+    39, 44, 30, 31, 50, 33, 31, 32,
+    19, 32, 40, 31, 37, 47,  1, 35,
+    16, 31,  0, 35, 33,  1, 17, 34,
+     9, 34, 33, 31, 49, 43, 42, 51,
+    34, 29, 23, 29, 14, 30, 45, 49,
+    11, 24, 31, 28, 35, 41, 30, 44,
+    18, 29, 34, 35, 36, 25, 26, 21,
+    31, 30, 34, 19, 34, 44, 36, 38,
+    25, 31, 28, 23, 37,  3, 55, 41,
+    30, 22, 41, 24, 33, 26, 35, 35,
+    30, 55, 51, 47, 48, 38, 24, 15,
+    21, 50, 25, 46, 30, 29, 10, 34,
+    42, 45, 29, 42, 22,  3, 33, 27,
+    34,  1, 34, 28, 34, 36, 35, 23,
+    23, 13, 58,  3, 26, 63, 25, 31,
+    34, 61, 38, 39, 25, 61, 29, 37,
+    30, 41, 26, 48, 28, 33, 50, 35,
+    30, 37, 29, 29, 40,  6, 39, 28,
+    28, 19,  8, 22, 45, 34, 35, 10,
+    58, 17, 37, 39, 30, 18, 54, 14,
+    29, 16, 59, 30, 35, 23, 35, 30,
+    47, 36, 29, 55, 20, 12, 31, 35,
+    14, 29, 18, 34, 34, 24, 29, 26,
+    22,  2, 27, 23,  8, 30, 55, 38,
+    60, 31,  4, 34, 49, 34, 27, 34,
+    33, 30, 31, 54, 42, 35, 38, 46,
+    44, 26, 27,  9, 39, 25, 21, 29,
+    28, 42, 13,  0,  5, 34, 37, 28,
+    24, 29, 63, 26, 22, 27, 29, 25,
+    33, 25, 61,  0, 35, 25, 36, 15,
+    27, 40, 53, 33,  3, 10, 16, 37,
+    38, 18, 30, 46, 27,  9,  6, 29,
+    62,  8, 42, 28, 29,  3, 25, 16,
+    26, 29, 35, 28, 27, 51, 61, 48,
+    37,  9, 34,  7, 49, 45, 20, 29,
+    21,  5,  5, 29, 28, 34, 29, 24,
+    10, 24, 35, 36, 38, 55, 11, 36,
+    38, 53, 54, 26, 30, 49, 20, 27,
+    30, 39, 33, 41, 49, 22, 38, 38,
+     4, 30,  8,  9,  3, 24, 22, 50,
+    37, 36, 31, 27,  2,  9, 42, 63,
+    25, 19, 44,  1, 28, 28, 48, 30,
+    34, 41, 41, 38, 12, 27, 15,  0,
+    16, 34, 35, 38, 28, 29, 40, 42,
+    51, 52, 45, 54, 59, 59, 42, 44,
+    37, 26, 46, 24, 15, 39, 22, 46,
+    19, 35, 38, 17, 37, 23, 52, 55,
+    50, 37, 26, 11, 37, 12, 24, 30,
+    16, 13, 22, 13, 36, 35, 40, 41,
+    34, 41, 26, 53, 51,  5, 21, 30,
+     2, 63, 41, 20,  1, 56, 21, 24,
+    25,  5, 28, 35, 26, 28, 30, 18,
+    29, 23, 40, 34, 20, 42, 39, 34,
+    28, 61, 38, 27, 62,  9, 36, 17,
+     9, 49, 24, 25, 54, 34, 39, 37,
+     3,  1, 25, 38, 38, 44, 35, 36,
+    12, 60, 36, 38, 40, 25, 43, 39,
+    53, 28, 39, 57, 46, 10, 52, 27,
+    35, 42, 45, 59, 15, 60, 38, 24,
+    23, 39, 12, 29, 24,  0, 20, 16,
+    28, 43, 35, 28,  1, 49,  4, 21,
+    42, 39, 29,  3, 44, 21, 53, 55,
+    11,  5,  3, 39, 53, 28, 25, 19,
+    34, 28, 21,
 };
 
 MVTable ff_mv_tables[2] = {
-    {
-        1099,
-        table0_mv_code,
-        table0_mv_bits,
-        table0_mvx,
-        table0_mvy,
-    },
-    {
-        1099,
-        table1_mv_code,
-        table1_mv_bits,
-        table1_mvx,
-        table1_mvy,
-    }
+    { 1099,
+      table0_mv_code,
+      table0_mv_bits,
+      table0_mvx,
+      table0_mvy, },
+    { 1099,
+      table1_mv_code,
+      table1_mv_bits,
+      table1_mvx,
+      table1_mvy, }
 };
 
 const uint8_t ff_v2_mb_type[8][2] = {
- {1, 1}, {0   , 2}, {3   , 3}, {9   , 5},
- {5, 4}, {0x21, 7}, {0x20, 7}, {0x11, 6},
+    { 1, 1 }, {    0, 2 }, {    3, 3 }, {    9, 5 },
+    { 5, 4 }, { 0x21, 7 }, { 0x20, 7 }, { 0x11, 6 },
 };
 
 const uint8_t ff_v2_intra_cbpc[4][2] = {
- {1, 1}, {0, 3}, {1, 3}, {1, 2},
+    { 1, 1 }, { 0, 3 }, { 1, 3 }, { 1, 2 },
 };
 
-const uint8_t ff_wmv1_y_dc_scale_table[32]={
-//  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
-    0, 8, 8, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21
+const uint8_t ff_wmv1_y_dc_scale_table[32] = {
+     0,  8,  8,  8,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13,
+    14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21
 };
-const uint8_t ff_wmv1_c_dc_scale_table[32]={
-//  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
-    0, 8, 8, 8, 8, 9, 9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22
+const uint8_t ff_wmv1_c_dc_scale_table[32] = {
+     0,  8,  8,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13, 14,
+    14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22
 };
 
-const uint8_t ff_old_ff_y_dc_scale_table[32]={
-//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-    0, 8, 8, 8, 8,10,12,14,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39
+const uint8_t ff_old_ff_y_dc_scale_table[32] = {
+     0,  8,  8,  8,  8, 10, 12, 14, 16, 17, 18, 19, 20, 21, 22, 23,
+    24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
 };
 
-const uint8_t ff_wmv1_scantable[WMV1_SCANTABLE_COUNT][64]={
-  {
-    0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11,
-    0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28,
-    0x30, 0x38, 0x29, 0x21, 0x1A, 0x13, 0x0C, 0x05,
-    0x06, 0x0D, 0x14, 0x1B, 0x22, 0x31, 0x39, 0x3A,
-    0x32, 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F,
-    0x16, 0x1D, 0x24, 0x2B, 0x33, 0x3B, 0x3C, 0x34,
-    0x2C, 0x25, 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x35,
-    0x3D, 0x3E, 0x36, 0x2E, 0x27, 0x2F, 0x37, 0x3F,
-  },
-  {
-    0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11,
-    0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28,
-    0x21, 0x30, 0x1A, 0x13, 0x0C, 0x05, 0x06, 0x0D,
-    0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39, 0x2A,
-    0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F, 0x16, 0x1D,
-    0x24, 0x2B, 0x32, 0x3A, 0x33, 0x3B, 0x2C, 0x25,
-    0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3C, 0x35,
-    0x3D, 0x2E, 0x27, 0x2F, 0x36, 0x3E, 0x37, 0x3F,
-  },
-  {
-    0x00, 0x01, 0x08, 0x02, 0x03, 0x09, 0x10, 0x18,
-    0x11, 0x0A, 0x04, 0x05, 0x0B, 0x12, 0x19, 0x20,
-    0x28, 0x30, 0x21, 0x1A, 0x13, 0x0C, 0x06, 0x07,
-    0x0D, 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39,
-    0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x0F, 0x16, 0x1D,
-    0x24, 0x2B, 0x32, 0x3A, 0x33, 0x2C, 0x25, 0x1E,
-    0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3B, 0x3C, 0x35,
-    0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F,
-  },
-  {
-    0x00, 0x08, 0x10, 0x01, 0x18, 0x20, 0x28, 0x09,
-    0x02, 0x03, 0x0A, 0x11, 0x19, 0x30, 0x38, 0x29,
-    0x21, 0x1A, 0x12, 0x0B, 0x04, 0x05, 0x0C, 0x13,
-    0x1B, 0x22, 0x31, 0x39, 0x32, 0x2A, 0x23, 0x1C,
-    0x14, 0x0D, 0x06, 0x07, 0x0E, 0x15, 0x1D, 0x24,
-    0x2B, 0x33, 0x3A, 0x3B, 0x34, 0x2C, 0x25, 0x1E,
-    0x16, 0x0F, 0x17, 0x1F, 0x26, 0x2D, 0x3C, 0x35,
-    0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F,
-  }
+const uint8_t ff_wmv1_scantable[WMV1_SCANTABLE_COUNT][64] = {
+    { 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11,
+      0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28,
+      0x30, 0x38, 0x29, 0x21, 0x1A, 0x13, 0x0C, 0x05,
+      0x06, 0x0D, 0x14, 0x1B, 0x22, 0x31, 0x39, 0x3A,
+      0x32, 0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F,
+      0x16, 0x1D, 0x24, 0x2B, 0x33, 0x3B, 0x3C, 0x34,
+      0x2C, 0x25, 0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x35,
+      0x3D, 0x3E, 0x36, 0x2E, 0x27, 0x2F, 0x37, 0x3F, },
+    { 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11,
+      0x0A, 0x03, 0x04, 0x0B, 0x12, 0x19, 0x20, 0x28,
+      0x21, 0x30, 0x1A, 0x13, 0x0C, 0x05, 0x06, 0x0D,
+      0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39, 0x2A,
+      0x23, 0x1C, 0x15, 0x0E, 0x07, 0x0F, 0x16, 0x1D,
+      0x24, 0x2B, 0x32, 0x3A, 0x33, 0x3B, 0x2C, 0x25,
+      0x1E, 0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3C, 0x35,
+      0x3D, 0x2E, 0x27, 0x2F, 0x36, 0x3E, 0x37, 0x3F, },
+    { 0x00, 0x01, 0x08, 0x02, 0x03, 0x09, 0x10, 0x18,
+      0x11, 0x0A, 0x04, 0x05, 0x0B, 0x12, 0x19, 0x20,
+      0x28, 0x30, 0x21, 0x1A, 0x13, 0x0C, 0x06, 0x07,
+      0x0D, 0x14, 0x1B, 0x22, 0x29, 0x38, 0x31, 0x39,
+      0x2A, 0x23, 0x1C, 0x15, 0x0E, 0x0F, 0x16, 0x1D,
+      0x24, 0x2B, 0x32, 0x3A, 0x33, 0x2C, 0x25, 0x1E,
+      0x17, 0x1F, 0x26, 0x2D, 0x34, 0x3B, 0x3C, 0x35,
+      0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, },
+    { 0x00, 0x08, 0x10, 0x01, 0x18, 0x20, 0x28, 0x09,
+      0x02, 0x03, 0x0A, 0x11, 0x19, 0x30, 0x38, 0x29,
+      0x21, 0x1A, 0x12, 0x0B, 0x04, 0x05, 0x0C, 0x13,
+      0x1B, 0x22, 0x31, 0x39, 0x32, 0x2A, 0x23, 0x1C,
+      0x14, 0x0D, 0x06, 0x07, 0x0E, 0x15, 0x1D, 0x24,
+      0x2B, 0x33, 0x3A, 0x3B, 0x34, 0x2C, 0x25, 0x1E,
+      0x16, 0x0F, 0x17, 0x1F, 0x26, 0x2D, 0x3C, 0x35,
+      0x2E, 0x27, 0x2F, 0x36, 0x3D, 0x3E, 0x37, 0x3F, }
 };
 
-const uint8_t ff_table_inter_intra[4][2]={
-    {0,1} /*Luma-Left Chroma-Left*/,
-    {2,2} /*Luma-Top  Chroma-Left*/,
-    {6,3} /*luma-Left Chroma-Top */,
-    {7,3} /*luma-Top  Chroma-Top */
+const uint8_t ff_table_inter_intra[4][2] = {
+    { 0, 1 } /* Luma-Left Chroma-Left */,
+    { 2, 2 } /* Luma-Top  Chroma-Left */,
+    { 6, 3 } /* luma-Left Chroma-Top  */,
+    { 7, 3 } /* luma-Top  Chroma-Top  */
 };
 
 static const uint32_t table_mb_non_intra2[128][2] = {
-{0x0000A7, 14}, {0x01B2B8, 18}, {0x01B28E, 18}, {0x036575, 19},
-{0x006CAC, 16}, {0x000A69, 18}, {0x002934, 20}, {0x00526B, 21},
-{0x006CA1, 16}, {0x01B2B9, 18}, {0x0029AD, 20}, {0x029353, 24},
-{0x006CA7, 16}, {0x006CAB, 16}, {0x01B2BB, 18}, {0x00029B, 16},
-{0x00D944, 17}, {0x000A6A, 18}, {0x0149A8, 23}, {0x03651F, 19},
-{0x006CAF, 16}, {0x000A4C, 18}, {0x03651E, 19}, {0x000A48, 18},
-{0x00299C, 20}, {0x00299F, 20}, {0x029352, 24}, {0x0029AC, 20},
-{0x000296, 16}, {0x00D946, 17}, {0x000A68, 18}, {0x000298, 16},
-{0x000527, 17}, {0x00D94D, 17}, {0x0014D7, 19}, {0x036574, 19},
-{0x000A5C, 18}, {0x01B299, 18}, {0x00299D, 20}, {0x00299E, 20},
-{0x000525, 17}, {0x000A66, 18}, {0x00A4D5, 22}, {0x00149B, 19},
-{0x000295, 16}, {0x006CAD, 16}, {0x000A49, 18}, {0x000521, 17},
-{0x006CAA, 16}, {0x00D945, 17}, {0x01B298, 18}, {0x00052F, 17},
-{0x003654, 15}, {0x006CA0, 16}, {0x000532, 17}, {0x000291, 16},
-{0x003652, 15}, {0x000520, 17}, {0x000A5D, 18}, {0x000294, 16},
-{0x00009B, 11}, {0x0006E2, 12}, {0x000028, 12}, {0x0001B0, 10},
-{0x000001,  3}, {0x000010,  8}, {0x00002F,  6}, {0x00004C, 10},
-{0x00000D,  4}, {0x000000, 10}, {0x000006,  9}, {0x000134, 12},
-{0x00000C,  4}, {0x000007, 10}, {0x000007,  9}, {0x0006E1, 12},
-{0x00000E,  5}, {0x0000DA,  9}, {0x000022,  9}, {0x000364, 11},
-{0x00000F,  4}, {0x000006, 10}, {0x00000F,  9}, {0x000135, 12},
-{0x000014,  5}, {0x0000DD,  9}, {0x000004,  9}, {0x000015, 11},
-{0x00001A,  6}, {0x0001B3, 10}, {0x000005, 10}, {0x0006E3, 12},
-{0x00000C,  5}, {0x0000B9,  8}, {0x000004,  8}, {0x0000DB,  9},
-{0x00000E,  4}, {0x00000B, 10}, {0x000023,  9}, {0x0006CB, 12},
-{0x000005,  6}, {0x0001B1, 10}, {0x000001, 10}, {0x0006E0, 12},
-{0x000011,  5}, {0x0000DF,  9}, {0x00000E,  9}, {0x000373, 11},
-{0x000003,  5}, {0x0000B8,  8}, {0x000006,  8}, {0x000175,  9},
-{0x000015,  5}, {0x000174,  9}, {0x000027,  9}, {0x000372, 11},
-{0x000010,  5}, {0x0000BB,  8}, {0x000005,  8}, {0x0000DE,  9},
-{0x00000F,  5}, {0x000001,  9}, {0x000012,  8}, {0x000004, 10},
-{0x000002,  3}, {0x000016,  5}, {0x000009,  4}, {0x000001,  5},
+    { 0x0000A7, 14 }, { 0x01B2B8, 18 }, { 0x01B28E, 18 }, { 0x036575, 19 },
+    { 0x006CAC, 16 }, { 0x000A69, 18 }, { 0x002934, 20 }, { 0x00526B, 21 },
+    { 0x006CA1, 16 }, { 0x01B2B9, 18 }, { 0x0029AD, 20 }, { 0x029353, 24 },
+    { 0x006CA7, 16 }, { 0x006CAB, 16 }, { 0x01B2BB, 18 }, { 0x00029B, 16 },
+    { 0x00D944, 17 }, { 0x000A6A, 18 }, { 0x0149A8, 23 }, { 0x03651F, 19 },
+    { 0x006CAF, 16 }, { 0x000A4C, 18 }, { 0x03651E, 19 }, { 0x000A48, 18 },
+    { 0x00299C, 20 }, { 0x00299F, 20 }, { 0x029352, 24 }, { 0x0029AC, 20 },
+    { 0x000296, 16 }, { 0x00D946, 17 }, { 0x000A68, 18 }, { 0x000298, 16 },
+    { 0x000527, 17 }, { 0x00D94D, 17 }, { 0x0014D7, 19 }, { 0x036574, 19 },
+    { 0x000A5C, 18 }, { 0x01B299, 18 }, { 0x00299D, 20 }, { 0x00299E, 20 },
+    { 0x000525, 17 }, { 0x000A66, 18 }, { 0x00A4D5, 22 }, { 0x00149B, 19 },
+    { 0x000295, 16 }, { 0x006CAD, 16 }, { 0x000A49, 18 }, { 0x000521, 17 },
+    { 0x006CAA, 16 }, { 0x00D945, 17 }, { 0x01B298, 18 }, { 0x00052F, 17 },
+    { 0x003654, 15 }, { 0x006CA0, 16 }, { 0x000532, 17 }, { 0x000291, 16 },
+    { 0x003652, 15 }, { 0x000520, 17 }, { 0x000A5D, 18 }, { 0x000294, 16 },
+    { 0x00009B, 11 }, { 0x0006E2, 12 }, { 0x000028, 12 }, { 0x0001B0, 10 },
+    { 0x000001,  3 }, { 0x000010,  8 }, { 0x00002F,  6 }, { 0x00004C, 10 },
+    { 0x00000D,  4 }, { 0x000000, 10 }, { 0x000006,  9 }, { 0x000134, 12 },
+    { 0x00000C,  4 }, { 0x000007, 10 }, { 0x000007,  9 }, { 0x0006E1, 12 },
+    { 0x00000E,  5 }, { 0x0000DA,  9 }, { 0x000022,  9 }, { 0x000364, 11 },
+    { 0x00000F,  4 }, { 0x000006, 10 }, { 0x00000F,  9 }, { 0x000135, 12 },
+    { 0x000014,  5 }, { 0x0000DD,  9 }, { 0x000004,  9 }, { 0x000015, 11 },
+    { 0x00001A,  6 }, { 0x0001B3, 10 }, { 0x000005, 10 }, { 0x0006E3, 12 },
+    { 0x00000C,  5 }, { 0x0000B9,  8 }, { 0x000004,  8 }, { 0x0000DB,  9 },
+    { 0x00000E,  4 }, { 0x00000B, 10 }, { 0x000023,  9 }, { 0x0006CB, 12 },
+    { 0x000005,  6 }, { 0x0001B1, 10 }, { 0x000001, 10 }, { 0x0006E0, 12 },
+    { 0x000011,  5 }, { 0x0000DF,  9 }, { 0x00000E,  9 }, { 0x000373, 11 },
+    { 0x000003,  5 }, { 0x0000B8,  8 }, { 0x000006,  8 }, { 0x000175,  9 },
+    { 0x000015,  5 }, { 0x000174,  9 }, { 0x000027,  9 }, { 0x000372, 11 },
+    { 0x000010,  5 }, { 0x0000BB,  8 }, { 0x000005,  8 }, { 0x0000DE,  9 },
+    { 0x00000F,  5 }, { 0x000001,  9 }, { 0x000012,  8 }, { 0x000004, 10 },
+    { 0x000002,  3 }, { 0x000016,  5 }, { 0x000009,  4 }, { 0x000001,  5 },
 };
 
 static const uint32_t table_mb_non_intra3[128][2] = {
-{0x0002A1, 10}, {0x005740, 15}, {0x01A0BF, 18}, {0x015D19, 17},
-{0x001514, 13}, {0x00461E, 15}, {0x015176, 17}, {0x015177, 17},
-{0x0011AD, 13}, {0x00682E, 16}, {0x0682F9, 20}, {0x03417D, 19},
-{0x001A36, 14}, {0x002A2D, 14}, {0x00D05E, 17}, {0x006824, 16},
-{0x001515, 13}, {0x00545C, 15}, {0x0230E9, 18}, {0x011AFA, 17},
-{0x0015D7, 13}, {0x005747, 15}, {0x008D79, 16}, {0x006825, 16},
-{0x002BA2, 14}, {0x00A8BA, 16}, {0x0235F6, 18}, {0x015D18, 17},
-{0x0011AE, 13}, {0x00346F, 15}, {0x008C3B, 16}, {0x00346E, 15},
-{0x000D1A, 13}, {0x00461F, 15}, {0x0682F8, 20}, {0x011875, 17},
-{0x002BA1, 14}, {0x008D61, 16}, {0x0235F7, 18}, {0x0230E8, 18},
-{0x001513, 13}, {0x008D7B, 16}, {0x011AF4, 17}, {0x011AF5, 17},
-{0x001185, 13}, {0x0046BF, 15}, {0x008D60, 16}, {0x008D7C, 16},
-{0x001512, 13}, {0x00461C, 15}, {0x00AE8D, 16}, {0x008D78, 16},
-{0x000D0E, 13}, {0x003413, 15}, {0x0046B1, 15}, {0x003416, 15},
-{0x000AEA, 12}, {0x002A2C, 14}, {0x005741, 15}, {0x002A2F, 14},
-{0x000158,  9}, {0x0008D2, 12}, {0x00054C, 11}, {0x000686, 12},
-{0x000000,  2}, {0x000069,  8}, {0x00006B,  8}, {0x00068C, 12},
-{0x000007,  3}, {0x00015E,  9}, {0x0002A3, 10}, {0x000AE9, 12},
-{0x000006,  3}, {0x000231, 10}, {0x0002B8, 10}, {0x001A08, 14},
-{0x000010,  5}, {0x0001A9, 10}, {0x000342, 11}, {0x000A88, 12},
-{0x000004,  4}, {0x0001A2, 10}, {0x0002A4, 10}, {0x001184, 13},
-{0x000012,  5}, {0x000232, 10}, {0x0002B2, 10}, {0x000680, 12},
-{0x00001B,  6}, {0x00046A, 11}, {0x00068E, 12}, {0x002359, 14},
-{0x000016,  5}, {0x00015F,  9}, {0x0002A0, 10}, {0x00054D, 11},
-{0x000005,  4}, {0x000233, 10}, {0x0002B9, 10}, {0x0015D6, 13},
-{0x000022,  6}, {0x000468, 11}, {0x000683, 12}, {0x001A0A, 14},
-{0x000013,  5}, {0x000236, 10}, {0x0002BB, 10}, {0x001186, 13},
-{0x000017,  5}, {0x0001AB, 10}, {0x0002A7, 10}, {0x0008D3, 12},
-{0x000014,  5}, {0x000237, 10}, {0x000460, 11}, {0x000D0F, 13},
-{0x000019,  6}, {0x0001AA, 10}, {0x0002B3, 10}, {0x000681, 12},
-{0x000018,  6}, {0x0001A8, 10}, {0x0002A5, 10}, {0x00068F, 12},
-{0x000007,  4}, {0x000055,  7}, {0x000047,  7}, {0x0000AD,  8},
+    { 0x0002A1, 10 }, { 0x005740, 15 }, { 0x01A0BF, 18 }, { 0x015D19, 17 },
+    { 0x001514, 13 }, { 0x00461E, 15 }, { 0x015176, 17 }, { 0x015177, 17 },
+    { 0x0011AD, 13 }, { 0x00682E, 16 }, { 0x0682F9, 20 }, { 0x03417D, 19 },
+    { 0x001A36, 14 }, { 0x002A2D, 14 }, { 0x00D05E, 17 }, { 0x006824, 16 },
+    { 0x001515, 13 }, { 0x00545C, 15 }, { 0x0230E9, 18 }, { 0x011AFA, 17 },
+    { 0x0015D7, 13 }, { 0x005747, 15 }, { 0x008D79, 16 }, { 0x006825, 16 },
+    { 0x002BA2, 14 }, { 0x00A8BA, 16 }, { 0x0235F6, 18 }, { 0x015D18, 17 },
+    { 0x0011AE, 13 }, { 0x00346F, 15 }, { 0x008C3B, 16 }, { 0x00346E, 15 },
+    { 0x000D1A, 13 }, { 0x00461F, 15 }, { 0x0682F8, 20 }, { 0x011875, 17 },
+    { 0x002BA1, 14 }, { 0x008D61, 16 }, { 0x0235F7, 18 }, { 0x0230E8, 18 },
+    { 0x001513, 13 }, { 0x008D7B, 16 }, { 0x011AF4, 17 }, { 0x011AF5, 17 },
+    { 0x001185, 13 }, { 0x0046BF, 15 }, { 0x008D60, 16 }, { 0x008D7C, 16 },
+    { 0x001512, 13 }, { 0x00461C, 15 }, { 0x00AE8D, 16 }, { 0x008D78, 16 },
+    { 0x000D0E, 13 }, { 0x003413, 15 }, { 0x0046B1, 15 }, { 0x003416, 15 },
+    { 0x000AEA, 12 }, { 0x002A2C, 14 }, { 0x005741, 15 }, { 0x002A2F, 14 },
+    { 0x000158,  9 }, { 0x0008D2, 12 }, { 0x00054C, 11 }, { 0x000686, 12 },
+    { 0x000000,  2 }, { 0x000069,  8 }, { 0x00006B,  8 }, { 0x00068C, 12 },
+    { 0x000007,  3 }, { 0x00015E,  9 }, { 0x0002A3, 10 }, { 0x000AE9, 12 },
+    { 0x000006,  3 }, { 0x000231, 10 }, { 0x0002B8, 10 }, { 0x001A08, 14 },
+    { 0x000010,  5 }, { 0x0001A9, 10 }, { 0x000342, 11 }, { 0x000A88, 12 },
+    { 0x000004,  4 }, { 0x0001A2, 10 }, { 0x0002A4, 10 }, { 0x001184, 13 },
+    { 0x000012,  5 }, { 0x000232, 10 }, { 0x0002B2, 10 }, { 0x000680, 12 },
+    { 0x00001B,  6 }, { 0x00046A, 11 }, { 0x00068E, 12 }, { 0x002359, 14 },
+    { 0x000016,  5 }, { 0x00015F,  9 }, { 0x0002A0, 10 }, { 0x00054D, 11 },
+    { 0x000005,  4 }, { 0x000233, 10 }, { 0x0002B9, 10 }, { 0x0015D6, 13 },
+    { 0x000022,  6 }, { 0x000468, 11 }, { 0x000683, 12 }, { 0x001A0A, 14 },
+    { 0x000013,  5 }, { 0x000236, 10 }, { 0x0002BB, 10 }, { 0x001186, 13 },
+    { 0x000017,  5 }, { 0x0001AB, 10 }, { 0x0002A7, 10 }, { 0x0008D3, 12 },
+    { 0x000014,  5 }, { 0x000237, 10 }, { 0x000460, 11 }, { 0x000D0F, 13 },
+    { 0x000019,  6 }, { 0x0001AA, 10 }, { 0x0002B3, 10 }, { 0x000681, 12 },
+    { 0x000018,  6 }, { 0x0001A8, 10 }, { 0x0002A5, 10 }, { 0x00068F, 12 },
+    { 0x000007,  4 }, { 0x000055,  7 }, { 0x000047,  7 }, { 0x0000AD,  8 },
 };
 
 static const uint32_t table_mb_non_intra4[128][2] = {
-{0x0000D4,  8}, {0x0021C5, 14}, {0x00F18A, 16}, {0x00D5BC, 16},
-{0x000879, 12}, {0x00354D, 14}, {0x010E3F, 17}, {0x010F54, 17},
-{0x000866, 12}, {0x00356E, 14}, {0x010F55, 17}, {0x010E3E, 17},
-{0x0010CE, 13}, {0x003C84, 14}, {0x00D5BD, 16}, {0x00F18B, 16},
-{0x000868, 12}, {0x00438C, 15}, {0x0087AB, 16}, {0x00790B, 15},
-{0x000F10, 12}, {0x00433D, 15}, {0x006AD3, 15}, {0x00790A, 15},
-{0x001AA7, 13}, {0x0043D4, 15}, {0x00871E, 16}, {0x006ADF, 15},
-{0x000D7C, 12}, {0x003C94, 14}, {0x00438D, 15}, {0x006AD2, 15},
-{0x0006BC, 11}, {0x0021E9, 14}, {0x006ADA, 15}, {0x006A99, 15},
-{0x0010F7, 13}, {0x004389, 15}, {0x006ADB, 15}, {0x0078C4, 15},
-{0x000D56, 12}, {0x0035F7, 14}, {0x00438E, 15}, {0x006A98, 15},
-{0x000D52, 12}, {0x003C95, 14}, {0x004388, 15}, {0x00433C, 15},
-{0x000D54, 12}, {0x001E4B, 13}, {0x003C63, 14}, {0x003C83, 14},
-{0x000861, 12}, {0x0021EB, 14}, {0x00356C, 14}, {0x0035F6, 14},
-{0x000863, 12}, {0x00219F, 14}, {0x003568, 14}, {0x003C82, 14},
-{0x0001AE,  9}, {0x0010C0, 13}, {0x000F11, 12}, {0x001AFA, 13},
-{0x000000,  1}, {0x0000F0,  8}, {0x0001AD,  9}, {0x0010C1, 13},
-{0x00000A,  4}, {0x0003C5, 10}, {0x000789, 11}, {0x001AB5, 13},
-{0x000009,  4}, {0x000435, 11}, {0x000793, 11}, {0x001E40, 13},
-{0x00001D,  5}, {0x0003CB, 10}, {0x000878, 12}, {0x001AAF, 13},
-{0x00000B,  4}, {0x0003C7, 10}, {0x000791, 11}, {0x001AAB, 13},
-{0x00001F,  5}, {0x000436, 11}, {0x0006BF, 11}, {0x000F19, 12},
-{0x00003D,  6}, {0x000D51, 12}, {0x0010C4, 13}, {0x0021E8, 14},
-{0x000036,  6}, {0x000437, 11}, {0x0006AF, 11}, {0x0010C5, 13},
-{0x00000C,  4}, {0x000432, 11}, {0x000794, 11}, {0x001E30, 13},
-{0x000042,  7}, {0x000870, 12}, {0x000F24, 12}, {0x001E43, 13},
-{0x000020,  6}, {0x00043E, 11}, {0x000795, 11}, {0x001AAA, 13},
-{0x000037,  6}, {0x0006AC, 11}, {0x0006AE, 11}, {0x0010F6, 13},
-{0x000034,  6}, {0x00043A, 11}, {0x000D50, 12}, {0x001AAE, 13},
-{0x000039,  6}, {0x00043F, 11}, {0x00078D, 11}, {0x0010D2, 13},
-{0x000038,  6}, {0x00043B, 11}, {0x0006BD, 11}, {0x0010D3, 13},
-{0x000011,  5}, {0x0001AC,  9}, {0x0000F3,  8}, {0x000439, 11},
+    { 0x0000D4,  8 }, { 0x0021C5, 14 }, { 0x00F18A, 16 }, { 0x00D5BC, 16 },
+    { 0x000879, 12 }, { 0x00354D, 14 }, { 0x010E3F, 17 }, { 0x010F54, 17 },
+    { 0x000866, 12 }, { 0x00356E, 14 }, { 0x010F55, 17 }, { 0x010E3E, 17 },
+    { 0x0010CE, 13 }, { 0x003C84, 14 }, { 0x00D5BD, 16 }, { 0x00F18B, 16 },
+    { 0x000868, 12 }, { 0x00438C, 15 }, { 0x0087AB, 16 }, { 0x00790B, 15 },
+    { 0x000F10, 12 }, { 0x00433D, 15 }, { 0x006AD3, 15 }, { 0x00790A, 15 },
+    { 0x001AA7, 13 }, { 0x0043D4, 15 }, { 0x00871E, 16 }, { 0x006ADF, 15 },
+    { 0x000D7C, 12 }, { 0x003C94, 14 }, { 0x00438D, 15 }, { 0x006AD2, 15 },
+    { 0x0006BC, 11 }, { 0x0021E9, 14 }, { 0x006ADA, 15 }, { 0x006A99, 15 },
+    { 0x0010F7, 13 }, { 0x004389, 15 }, { 0x006ADB, 15 }, { 0x0078C4, 15 },
+    { 0x000D56, 12 }, { 0x0035F7, 14 }, { 0x00438E, 15 }, { 0x006A98, 15 },
+    { 0x000D52, 12 }, { 0x003C95, 14 }, { 0x004388, 15 }, { 0x00433C, 15 },
+    { 0x000D54, 12 }, { 0x001E4B, 13 }, { 0x003C63, 14 }, { 0x003C83, 14 },
+    { 0x000861, 12 }, { 0x0021EB, 14 }, { 0x00356C, 14 }, { 0x0035F6, 14 },
+    { 0x000863, 12 }, { 0x00219F, 14 }, { 0x003568, 14 }, { 0x003C82, 14 },
+    { 0x0001AE,  9 }, { 0x0010C0, 13 }, { 0x000F11, 12 }, { 0x001AFA, 13 },
+    { 0x000000,  1 }, { 0x0000F0,  8 }, { 0x0001AD,  9 }, { 0x0010C1, 13 },
+    { 0x00000A,  4 }, { 0x0003C5, 10 }, { 0x000789, 11 }, { 0x001AB5, 13 },
+    { 0x000009,  4 }, { 0x000435, 11 }, { 0x000793, 11 }, { 0x001E40, 13 },
+    { 0x00001D,  5 }, { 0x0003CB, 10 }, { 0x000878, 12 }, { 0x001AAF, 13 },
+    { 0x00000B,  4 }, { 0x0003C7, 10 }, { 0x000791, 11 }, { 0x001AAB, 13 },
+    { 0x00001F,  5 }, { 0x000436, 11 }, { 0x0006BF, 11 }, { 0x000F19, 12 },
+    { 0x00003D,  6 }, { 0x000D51, 12 }, { 0x0010C4, 13 }, { 0x0021E8, 14 },
+    { 0x000036,  6 }, { 0x000437, 11 }, { 0x0006AF, 11 }, { 0x0010C5, 13 },
+    { 0x00000C,  4 }, { 0x000432, 11 }, { 0x000794, 11 }, { 0x001E30, 13 },
+    { 0x000042,  7 }, { 0x000870, 12 }, { 0x000F24, 12 }, { 0x001E43, 13 },
+    { 0x000020,  6 }, { 0x00043E, 11 }, { 0x000795, 11 }, { 0x001AAA, 13 },
+    { 0x000037,  6 }, { 0x0006AC, 11 }, { 0x0006AE, 11 }, { 0x0010F6, 13 },
+    { 0x000034,  6 }, { 0x00043A, 11 }, { 0x000D50, 12 }, { 0x001AAE, 13 },
+    { 0x000039,  6 }, { 0x00043F, 11 }, { 0x00078D, 11 }, { 0x0010D2, 13 },
+    { 0x000038,  6 }, { 0x00043B, 11 }, { 0x0006BD, 11 }, { 0x0010D3, 13 },
+    { 0x000011,  5 }, { 0x0001AC,  9 }, { 0x0000F3,  8 }, { 0x000439, 11 },
 };
 
-const uint32_t (* const ff_wmv2_inter_table[WMV2_INTER_CBP_TABLE_COUNT])[2]={
+const uint32_t (*const ff_wmv2_inter_table[WMV2_INTER_CBP_TABLE_COUNT])[2] = {
     table_mb_non_intra2,
     table_mb_non_intra3,
     table_mb_non_intra4,
     ff_table_mb_non_intra,
 };
-
-const uint8_t ff_wmv2_scantableA[64]={
-0x00, 0x01, 0x02, 0x08, 0x03, 0x09, 0x0A, 0x10,
-0x04, 0x0B, 0x11, 0x18, 0x12, 0x0C, 0x05, 0x13,
-0x19, 0x0D, 0x14, 0x1A, 0x1B, 0x06, 0x15, 0x1C,
-0x0E, 0x16, 0x1D, 0x07, 0x1E, 0x0F, 0x17, 0x1F,
-};
-
-const uint8_t ff_wmv2_scantableB[64]={
-0x00, 0x08, 0x01, 0x10, 0x09, 0x18, 0x11, 0x02,
-0x20, 0x0A, 0x19, 0x28, 0x12, 0x30, 0x21, 0x1A,
-0x38, 0x29, 0x22, 0x03, 0x31, 0x39, 0x0B, 0x2A,
-0x13, 0x32, 0x1B, 0x3A, 0x23, 0x2B, 0x33, 0x3B,
-};
diff --git a/libavcodec/msmpeg4data.h b/libavcodec/msmpeg4data.h
index 24a10d9..52fecec 100644
--- a/libavcodec/msmpeg4data.h
+++ b/libavcodec/msmpeg4data.h
@@ -84,7 +84,4 @@ extern const uint32_t ff_table1_dc_chroma[120][2];
 #define WMV2_INTER_CBP_TABLE_COUNT 4
 extern const uint32_t (* const ff_wmv2_inter_table[WMV2_INTER_CBP_TABLE_COUNT])[2];
 
-extern const uint8_t ff_wmv2_scantableA[64];
-extern const uint8_t ff_wmv2_scantableB[64];
-
 #endif /* AVCODEC_MSMPEG4DATA_H */
diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c
index aaadd9c..2f90877 100644
--- a/libavcodec/msmpeg4dec.c
+++ b/libavcodec/msmpeg4dec.c
@@ -28,7 +28,6 @@
 #include "mpegvideo.h"
 #include "msmpeg4.h"
 #include "libavutil/imgutils.h"
-#include "libavutil/x86/asm.h"
 #include "h263.h"
 #include "mpeg4video.h"
 #include "msmpeg4data.h"
@@ -70,7 +69,7 @@ static VLC v2_mb_type_vlc;
 static VLC v2_mv_vlc;
 VLC ff_inter_intra_vlc;
 
-/* This is identical to h263 except that its range is multiplied by 2. */
+/* This is identical to H.263 except that its range is multiplied by 2. */
 static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code)
 {
     int code, val, sign, shift;
@@ -572,7 +571,7 @@ int ff_msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size)
     }
     else
     {
-        av_log(s->avctx, AV_LOG_ERROR, "I frame too long, ignoring ext header\n");
+        av_log(s->avctx, AV_LOG_ERROR, "I-frame too long, ignoring ext header\n");
     }
 
     return 0;
diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c
index e1ade24..07241e8 100644
--- a/libavcodec/msmpeg4enc.c
+++ b/libavcodec/msmpeg4enc.c
@@ -235,8 +235,8 @@ void ff_msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
     }
 
     s->dc_table_index = 1;
-    s->mv_table_index = 1; /* only if P frame */
-    s->use_skip_mb_code = 1; /* only if P frame */
+    s->mv_table_index = 1; /* only if P-frame */
+    s->use_skip_mb_code = 1; /* only if P-frame */
     s->per_mb_rl_table = 0;
     if(s->msmpeg4_version==4)
         s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE && s->pict_type==AV_PICTURE_TYPE_P);
@@ -577,9 +577,8 @@ static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr
     }
 }
 
-/* Encoding of a block. Very similar to MPEG4 except for a different
-   escape coding (same as H263) and more vlc tables.
- */
+/* Encoding of a block; very similar to MPEG-4 except for a different
+ * escape coding (same as H.263) and more VLC tables. */
 void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n)
 {
     int level, run, last, i, j, last_index;
diff --git a/libavcodec/msrle.c b/libavcodec/msrle.c
index 3090a91..c2f6242 100644
--- a/libavcodec/msrle.c
+++ b/libavcodec/msrle.c
@@ -1,6 +1,6 @@
 /*
  * Microsoft RLE video decoder
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/mss12.c b/libavcodec/mss12.c
index 6b58aa2..d42093b 100644
--- a/libavcodec/mss12.c
+++ b/libavcodec/mss12.c
@@ -581,8 +581,8 @@ av_cold int ff_mss12_decode_init(MSS12Context *c, int version,
         return AVERROR_INVALIDDATA;
     }
 
-    avctx->coded_width  = AV_RB32(avctx->extradata + 20);
-    avctx->coded_height = AV_RB32(avctx->extradata + 24);
+    avctx->coded_width  = FFMAX(AV_RB32(avctx->extradata + 20), avctx->width);
+    avctx->coded_height = FFMAX(AV_RB32(avctx->extradata + 24), avctx->height);
     if (avctx->coded_width > 4096 || avctx->coded_height > 4096) {
         av_log(avctx, AV_LOG_ERROR, "Frame dimensions %dx%d too large",
                avctx->coded_width, avctx->coded_height);
diff --git a/libavcodec/mss2.c b/libavcodec/mss2.c
index c640934..d255dd4 100644
--- a/libavcodec/mss2.c
+++ b/libavcodec/mss2.c
@@ -28,9 +28,9 @@
 #include "internal.h"
 #include "mpeg_er.h"
 #include "msmpeg4.h"
-#include "msmpeg4data.h"
 #include "qpeldsp.h"
 #include "vc1.h"
+#include "wmv2data.h"
 #include "mss12.h"
 #include "mss2dsp.h"
 
diff --git a/libavcodec/msvideo1.c b/libavcodec/msvideo1.c
index 891675f..1d14172 100644
--- a/libavcodec/msvideo1.c
+++ b/libavcodec/msvideo1.c
@@ -1,6 +1,6 @@
 /*
  * Microsoft Video-1 Decoder
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -24,7 +24,6 @@
  * Microsoft Video-1 Decoder by Mike Melanson (melanson at pcisys.net)
  * For more information about the MS Video-1 format, visit:
  *   http://www.pcisys.net/~melanson/codecs/
- *
  */
 
 #include <stdio.h>
diff --git a/libavcodec/mvcdec.c b/libavcodec/mvcdec.c
index 74f279a..e507674 100644
--- a/libavcodec/mvcdec.c
+++ b/libavcodec/mvcdec.c
@@ -31,7 +31,6 @@
 #include "internal.h"
 
 typedef struct MvcContext {
-    AVFrame *frame;
     int vflip;
 } MvcContext;
 
@@ -53,10 +52,6 @@ static av_cold int mvc_decode_init(AVCodecContext *avctx)
 
     avctx->pix_fmt = (avctx->codec_id == AV_CODEC_ID_MVC1) ? AV_PIX_FMT_RGB555
                                                            : AV_PIX_FMT_RGB32;
-    s->frame       = av_frame_alloc();
-    if (!s->frame)
-        return AVERROR(ENOMEM);
-
     s->vflip = avctx->extradata_size >= 9 &&
                !memcmp(avctx->extradata + avctx->extradata_size - 9, "BottomUp", 9);
     return 0;
@@ -231,39 +226,32 @@ static int mvc_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
                             AVPacket *avpkt)
 {
     MvcContext *s = avctx->priv_data;
+    AVFrame *frame = data;
     GetByteContext gb;
     int ret;
 
-    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
 
     bytestream2_init(&gb, avpkt->data, avpkt->size);
     if (avctx->codec_id == AV_CODEC_ID_MVC1)
-        ret = decode_mvc1(avctx, &gb, s->frame->data[0],
-                          avctx->width, avctx->height, s->frame->linesize[0]);
+        ret = decode_mvc1(avctx, &gb, frame->data[0],
+                          avctx->width, avctx->height, frame->linesize[0]);
     else
-        ret = decode_mvc2(avctx, &gb, s->frame->data[0],
-                          avctx->width, avctx->height, s->frame->linesize[0],
+        ret = decode_mvc2(avctx, &gb, frame->data[0],
+                          avctx->width, avctx->height, frame->linesize[0],
                           s->vflip);
     if (ret < 0)
         return ret;
 
+    frame->pict_type = AV_PICTURE_TYPE_I;
+    frame->key_frame = 1;
+
     *got_frame = 1;
-    if ((ret = av_frame_ref(data, s->frame)) < 0)
-        return ret;
 
     return avpkt->size;
 }
 
-static av_cold int mvc_decode_end(AVCodecContext *avctx)
-{
-    MvcContext *s = avctx->priv_data;
-
-    av_frame_free(&s->frame);
-
-    return 0;
-}
-
 #if CONFIG_MVC1_DECODER
 AVCodec ff_mvc1_decoder = {
     .name           = "mvc1",
@@ -272,7 +260,6 @@ AVCodec ff_mvc1_decoder = {
     .id             = AV_CODEC_ID_MVC1,
     .priv_data_size = sizeof(MvcContext),
     .init           = mvc_decode_init,
-    .close          = mvc_decode_end,
     .decode         = mvc_decode_frame,
     .capabilities   = AV_CODEC_CAP_DR1,
 };
@@ -286,7 +273,6 @@ AVCodec ff_mvc2_decoder = {
     .id             = AV_CODEC_ID_MVC2,
     .priv_data_size = sizeof(MvcContext),
     .init           = mvc_decode_init,
-    .close          = mvc_decode_end,
     .decode         = mvc_decode_frame,
     .capabilities   = AV_CODEC_CAP_DR1,
 };
diff --git a/libavcodec/noise_bsf.c b/libavcodec/noise_bsf.c
index 556ad5c..0aebee1 100644
--- a/libavcodec/noise_bsf.c
+++ b/libavcodec/noise_bsf.c
@@ -22,34 +22,70 @@
 #include <string.h>
 
 #include "avcodec.h"
+#include "bsf.h"
+
+#include "libavutil/log.h"
 #include "libavutil/mem.h"
+#include "libavutil/opt.h"
 
+typedef struct NoiseContext {
+    const AVClass *class;
+    int amount;
+    unsigned int state;
+} NoiseContext;
 
-static int noise(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    unsigned int *state= bsfc->priv_data;
-    int amount= args ? atoi(args) : (*state % 10001+1);
-    int i;
+static int noise(AVBSFContext *ctx, AVPacket *out)
+{
+    NoiseContext *s = ctx->priv_data;
+    AVPacket *in;
+    int amount = s->amount > 0 ? s->amount : (s->state % 10001 + 1);
+    int i, ret = 0;
 
-    if(amount <= 0)
+    if (amount <= 0)
         return AVERROR(EINVAL);
 
-    *poutbuf= av_malloc(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!*poutbuf)
-        return AVERROR(ENOMEM);
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    ret = av_new_packet(out, in->size);
+    if (ret < 0)
+        goto fail;
+
+    ret = av_packet_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+    memcpy(out->data, in->data, in->size);
 
-    memcpy(*poutbuf, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    for(i=0; i<buf_size; i++){
-        (*state) += (*poutbuf)[i] + 1;
-        if(*state % amount == 0)
-            (*poutbuf)[i] = *state;
+    for (i = 0; i < out->size; i++) {
+        s->state += out->data[i] + 1;
+        if (s->state % amount == 0)
+            out->data[i] = s->state;
     }
-    return 1;
+fail:
+    if (ret < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return ret;
 }
 
-AVBitStreamFilter ff_noise_bsf={
+#define OFFSET(x) offsetof(NoiseContext, x)
+static const AVOption options[] = {
+    { "amount", NULL, OFFSET(amount), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX },
+    { NULL },
+};
+
+static const AVClass noise_class = {
+    .class_name = "noise",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const AVBitStreamFilter ff_noise_bsf = {
     .name           = "noise",
-    .priv_data_size = sizeof(int),
+    .priv_data_size = sizeof(NoiseContext),
+    .priv_class     = &noise_class,
     .filter         = noise,
 };
diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c
index ade3310..ad6c029 100644
--- a/libavcodec/nuv.c
+++ b/libavcodec/nuv.c
@@ -179,7 +179,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     // codec data (rtjpeg quant tables)
     if (buf[0] == 'D' && buf[1] == 'R') {
         int ret;
-        // skip rest of the frameheader.
+        // Skip the rest of the frame header.
         buf       = &buf[12];
         buf_size -= 12;
         ret       = get_quant(avctx, c, buf, buf_size);
@@ -207,7 +207,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         break;
     }
 retry:
-    // skip rest of the frameheader.
+    // Skip the rest of the frame header.
     buf       = &buf[12];
     buf_size -= 12;
     if (comptype == NUV_RTJPEG_IN_LZO || comptype == NUV_LZO) {
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index a3b02fa..984dd3b 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -19,664 +19,847 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "config.h"
+
 #if defined(_WIN32)
 #include <windows.h>
+
+#define CUDA_LIBNAME TEXT("nvcuda.dll")
+#if ARCH_X86_64
+#define NVENC_LIBNAME TEXT("nvEncodeAPI64.dll")
 #else
-#include <dlfcn.h>
+#define NVENC_LIBNAME TEXT("nvEncodeAPI.dll")
 #endif
 
-#include <nvEncodeAPI.h>
+#define dlopen(filename, flags) LoadLibrary((filename))
+#define dlsym(handle, symbol)   GetProcAddress(handle, symbol)
+#define dlclose(handle)         FreeLibrary(handle)
+#else
+#include <dlfcn.h>
+
+#define CUDA_LIBNAME "libcuda.so"
+#define NVENC_LIBNAME "libnvidia-encode.so"
+#endif
 
-#include "libavutil/internal.h"
+#include "libavutil/hwcontext.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/avassert.h"
-#include "libavutil/opt.h"
 #include "libavutil/mem.h"
-#include "avcodec.h"
 #include "internal.h"
-#include "thread.h"
-
-#if defined(_WIN32)
-#define CUDAAPI __stdcall
-#else
-#define CUDAAPI
-#endif
-
-#if defined(_WIN32)
-#define LOAD_FUNC(l, s) GetProcAddress(l, s)
-#define DL_CLOSE_FUNC(l) FreeLibrary(l)
-#else
-#define LOAD_FUNC(l, s) dlsym(l, s)
-#define DL_CLOSE_FUNC(l) dlclose(l)
+#include "nvenc.h"
+
+#define NVENC_CAP 0x30
+#define IS_CBR(rc) (rc == NV_ENC_PARAMS_RC_CBR ||               \
+                    rc == NV_ENC_PARAMS_RC_2_PASS_QUALITY ||    \
+                    rc == NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP)
+
+#define LOAD_LIBRARY(l, path)                   \
+    do {                                        \
+        if (!((l) = dlopen(path, RTLD_LAZY))) { \
+            av_log(avctx, AV_LOG_ERROR,         \
+                   "Cannot load %s\n",          \
+                   path);                       \
+            return AVERROR_UNKNOWN;             \
+        }                                       \
+    } while (0)
+
+#define LOAD_SYMBOL(fun, lib, symbol)        \
+    do {                                     \
+        if (!((fun) = dlsym(lib, symbol))) { \
+            av_log(avctx, AV_LOG_ERROR,      \
+                   "Cannot load %s\n",       \
+                   symbol);                  \
+            return AVERROR_UNKNOWN;          \
+        }                                    \
+    } while (0)
+
+const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
+    AV_PIX_FMT_YUV420P,
+    AV_PIX_FMT_NV12,
+    AV_PIX_FMT_YUV444P,
+#if CONFIG_CUDA
+    AV_PIX_FMT_CUDA,
 #endif
+    AV_PIX_FMT_NONE
+};
 
-typedef enum cudaError_enum {
-    CUDA_SUCCESS = 0
-} CUresult;
-typedef int CUdevice;
-typedef void* CUcontext;
-
-typedef CUresult(CUDAAPI *PCUINIT)(unsigned int Flags);
-typedef CUresult(CUDAAPI *PCUDEVICEGETCOUNT)(int *count);
-typedef CUresult(CUDAAPI *PCUDEVICEGET)(CUdevice *device, int ordinal);
-typedef CUresult(CUDAAPI *PCUDEVICEGETNAME)(char *name, int len, CUdevice dev);
-typedef CUresult(CUDAAPI *PCUDEVICECOMPUTECAPABILITY)(int *major, int *minor, CUdevice dev);
-typedef CUresult(CUDAAPI *PCUCTXCREATE)(CUcontext *pctx, unsigned int flags, CUdevice dev);
-typedef CUresult(CUDAAPI *PCUCTXPOPCURRENT)(CUcontext *pctx);
-typedef CUresult(CUDAAPI *PCUCTXDESTROY)(CUcontext ctx);
-
-typedef NVENCSTATUS (NVENCAPI* PNVENCODEAPICREATEINSTANCE)(NV_ENCODE_API_FUNCTION_LIST *functionList);
-
-typedef struct NvencInputSurface
-{
-    NV_ENC_INPUT_PTR input_surface;
-    int width;
-    int height;
-
-    int lockCount;
-
-    NV_ENC_BUFFER_FORMAT format;
-} NvencInputSurface;
-
-typedef struct NvencOutputSurface
-{
-    NV_ENC_OUTPUT_PTR output_surface;
-    int size;
-
-    NvencInputSurface* input_surface;
-
-    int busy;
-} NvencOutputSurface;
+static const struct {
+    NVENCSTATUS nverr;
+    int         averr;
+    const char *desc;
+} nvenc_errors[] = {
+    { NV_ENC_SUCCESS,                      0,                "success"                  },
+    { NV_ENC_ERR_NO_ENCODE_DEVICE,         AVERROR(ENOENT),  "no encode device"         },
+    { NV_ENC_ERR_UNSUPPORTED_DEVICE,       AVERROR(ENOSYS),  "unsupported device"       },
+    { NV_ENC_ERR_INVALID_ENCODERDEVICE,    AVERROR(EINVAL),  "invalid encoder device"   },
+    { NV_ENC_ERR_INVALID_DEVICE,           AVERROR(EINVAL),  "invalid device"           },
+    { NV_ENC_ERR_DEVICE_NOT_EXIST,         AVERROR(EIO),     "device does not exist"    },
+    { NV_ENC_ERR_INVALID_PTR,              AVERROR(EFAULT),  "invalid ptr"              },
+    { NV_ENC_ERR_INVALID_EVENT,            AVERROR(EINVAL),  "invalid event"            },
+    { NV_ENC_ERR_INVALID_PARAM,            AVERROR(EINVAL),  "invalid param"            },
+    { NV_ENC_ERR_INVALID_CALL,             AVERROR(EINVAL),  "invalid call"             },
+    { NV_ENC_ERR_OUT_OF_MEMORY,            AVERROR(ENOMEM),  "out of memory"            },
+    { NV_ENC_ERR_ENCODER_NOT_INITIALIZED,  AVERROR(EINVAL),  "encoder not initialized"  },
+    { NV_ENC_ERR_UNSUPPORTED_PARAM,        AVERROR(ENOSYS),  "unsupported param"        },
+    { NV_ENC_ERR_LOCK_BUSY,                AVERROR(EAGAIN),  "lock busy"                },
+    { NV_ENC_ERR_NOT_ENOUGH_BUFFER,        AVERROR(ENOBUFS), "not enough buffer"        },
+    { NV_ENC_ERR_INVALID_VERSION,          AVERROR(EINVAL),  "invalid version"          },
+    { NV_ENC_ERR_MAP_FAILED,               AVERROR(EIO),     "map failed"               },
+    { NV_ENC_ERR_NEED_MORE_INPUT,          AVERROR(EAGAIN),  "need more input"          },
+    { NV_ENC_ERR_ENCODER_BUSY,             AVERROR(EAGAIN),  "encoder busy"             },
+    { NV_ENC_ERR_EVENT_NOT_REGISTERD,      AVERROR(EBADF),   "event not registered"     },
+    { NV_ENC_ERR_GENERIC,                  AVERROR_UNKNOWN,  "generic error"            },
+    { NV_ENC_ERR_INCOMPATIBLE_CLIENT_KEY,  AVERROR(EINVAL),  "incompatible client key"  },
+    { NV_ENC_ERR_UNIMPLEMENTED,            AVERROR(ENOSYS),  "unimplemented"            },
+    { NV_ENC_ERR_RESOURCE_REGISTER_FAILED, AVERROR(EIO),     "resource register failed" },
+    { NV_ENC_ERR_RESOURCE_NOT_REGISTERED,  AVERROR(EBADF),   "resource not registered"  },
+    { NV_ENC_ERR_RESOURCE_NOT_MAPPED,      AVERROR(EBADF),   "resource not mapped"      },
+};
 
-typedef struct NvencData
+static int nvenc_map_error(NVENCSTATUS err, const char **desc)
 {
-    union {
-        int64_t timestamp;
-        NvencOutputSurface *surface;
-    } u;
-} NvencData;
+    int i;
+    for (i = 0; i < FF_ARRAY_ELEMS(nvenc_errors); i++) {
+        if (nvenc_errors[i].nverr == err) {
+            if (desc)
+                *desc = nvenc_errors[i].desc;
+            return nvenc_errors[i].averr;
+        }
+    }
+    if (desc)
+        *desc = "unknown error";
+    return AVERROR_UNKNOWN;
+}
 
-typedef struct NvencDataList
+static int nvenc_print_error(void *log_ctx, NVENCSTATUS err,
+                                     const char *error_string)
 {
-    NvencData* data;
-
-    uint32_t pos;
-    uint32_t count;
-    uint32_t size;
-} NvencDataList;
+    const char *desc;
+    int ret;
+    ret = nvenc_map_error(err, &desc);
+    av_log(log_ctx, AV_LOG_ERROR, "%s: %s (%d)\n", error_string, desc, err);
+    return ret;
+}
 
-typedef struct NvencDynLoadFunctions
+static av_cold int nvenc_load_libraries(AVCodecContext *avctx)
 {
-    PCUINIT cu_init;
-    PCUDEVICEGETCOUNT cu_device_get_count;
-    PCUDEVICEGET cu_device_get;
-    PCUDEVICEGETNAME cu_device_get_name;
-    PCUDEVICECOMPUTECAPABILITY cu_device_compute_capability;
-    PCUCTXCREATE cu_ctx_create;
-    PCUCTXPOPCURRENT cu_ctx_pop_current;
-    PCUCTXDESTROY cu_ctx_destroy;
-
-    NV_ENCODE_API_FUNCTION_LIST nvenc_funcs;
-    int nvenc_device_count;
-    CUdevice nvenc_devices[16];
-
-#if defined(_WIN32)
-    HMODULE cuda_lib;
-    HMODULE nvenc_lib;
+    NvencContext *ctx = avctx->priv_data;
+    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    PNVENCODEAPICREATEINSTANCE nvenc_create_instance;
+    NVENCSTATUS err;
+
+#if CONFIG_CUDA
+    dl_fn->cu_init                      = cuInit;
+    dl_fn->cu_device_get_count          = cuDeviceGetCount;
+    dl_fn->cu_device_get                = cuDeviceGet;
+    dl_fn->cu_device_get_name           = cuDeviceGetName;
+    dl_fn->cu_device_compute_capability = cuDeviceComputeCapability;
+    dl_fn->cu_ctx_create                = cuCtxCreate_v2;
+    dl_fn->cu_ctx_pop_current           = cuCtxPopCurrent_v2;
+    dl_fn->cu_ctx_destroy               = cuCtxDestroy_v2;
 #else
-    void* cuda_lib;
-    void* nvenc_lib;
+    LOAD_LIBRARY(dl_fn->cuda, CUDA_LIBNAME);
+
+    LOAD_SYMBOL(dl_fn->cu_init, dl_fn->cuda, "cuInit");
+    LOAD_SYMBOL(dl_fn->cu_device_get_count, dl_fn->cuda, "cuDeviceGetCount");
+    LOAD_SYMBOL(dl_fn->cu_device_get, dl_fn->cuda, "cuDeviceGet");
+    LOAD_SYMBOL(dl_fn->cu_device_get_name, dl_fn->cuda, "cuDeviceGetName");
+    LOAD_SYMBOL(dl_fn->cu_device_compute_capability, dl_fn->cuda,
+                "cuDeviceComputeCapability");
+    LOAD_SYMBOL(dl_fn->cu_ctx_create, dl_fn->cuda, "cuCtxCreate_v2");
+    LOAD_SYMBOL(dl_fn->cu_ctx_pop_current, dl_fn->cuda, "cuCtxPopCurrent_v2");
+    LOAD_SYMBOL(dl_fn->cu_ctx_destroy, dl_fn->cuda, "cuCtxDestroy_v2");
 #endif
-} NvencDynLoadFunctions;
 
-typedef struct NvencValuePair
-{
-    const char *str;
-    uint32_t num;
-} NvencValuePair;
+    LOAD_LIBRARY(dl_fn->nvenc, NVENC_LIBNAME);
 
-typedef struct NvencContext
-{
-    AVClass *avclass;
-
-    NvencDynLoadFunctions nvenc_dload_funcs;
-
-    NV_ENC_INITIALIZE_PARAMS init_encode_params;
-    NV_ENC_CONFIG encode_config;
-    CUcontext cu_context;
-
-    int max_surface_count;
-    NvencInputSurface *input_surfaces;
-    NvencOutputSurface *output_surfaces;
-
-    NvencDataList output_surface_queue;
-    NvencDataList output_surface_ready_queue;
-    NvencDataList timestamp_list;
-    int64_t last_dts;
-
-    void *nvencoder;
-
-    char *preset;
-    char *profile;
-    char *level;
-    char *tier;
-    int cbr;
-    int twopass;
-    int gpu;
-    int buffer_delay;
-} NvencContext;
-
-static const NvencValuePair nvenc_h264_level_pairs[] = {
-    { "auto", NV_ENC_LEVEL_AUTOSELECT },
-    { "1"   , NV_ENC_LEVEL_H264_1     },
-    { "1.0" , NV_ENC_LEVEL_H264_1     },
-    { "1b"  , NV_ENC_LEVEL_H264_1b    },
-    { "1.0b", NV_ENC_LEVEL_H264_1b    },
-    { "1.1" , NV_ENC_LEVEL_H264_11    },
-    { "1.2" , NV_ENC_LEVEL_H264_12    },
-    { "1.3" , NV_ENC_LEVEL_H264_13    },
-    { "2"   , NV_ENC_LEVEL_H264_2     },
-    { "2.0" , NV_ENC_LEVEL_H264_2     },
-    { "2.1" , NV_ENC_LEVEL_H264_21    },
-    { "2.2" , NV_ENC_LEVEL_H264_22    },
-    { "3"   , NV_ENC_LEVEL_H264_3     },
-    { "3.0" , NV_ENC_LEVEL_H264_3     },
-    { "3.1" , NV_ENC_LEVEL_H264_31    },
-    { "3.2" , NV_ENC_LEVEL_H264_32    },
-    { "4"   , NV_ENC_LEVEL_H264_4     },
-    { "4.0" , NV_ENC_LEVEL_H264_4     },
-    { "4.1" , NV_ENC_LEVEL_H264_41    },
-    { "4.2" , NV_ENC_LEVEL_H264_42    },
-    { "5"   , NV_ENC_LEVEL_H264_5     },
-    { "5.0" , NV_ENC_LEVEL_H264_5     },
-    { "5.1" , NV_ENC_LEVEL_H264_51    },
-    { NULL }
-};
+    LOAD_SYMBOL(nvenc_create_instance, dl_fn->nvenc,
+                "NvEncodeAPICreateInstance");
 
-static const NvencValuePair nvenc_hevc_level_pairs[] = {
-    { "auto", NV_ENC_LEVEL_AUTOSELECT },
-    { "1"   , NV_ENC_LEVEL_HEVC_1     },
-    { "1.0" , NV_ENC_LEVEL_HEVC_1     },
-    { "2"   , NV_ENC_LEVEL_HEVC_2     },
-    { "2.0" , NV_ENC_LEVEL_HEVC_2     },
-    { "2.1" , NV_ENC_LEVEL_HEVC_21    },
-    { "3"   , NV_ENC_LEVEL_HEVC_3     },
-    { "3.0" , NV_ENC_LEVEL_HEVC_3     },
-    { "3.1" , NV_ENC_LEVEL_HEVC_31    },
-    { "4"   , NV_ENC_LEVEL_HEVC_4     },
-    { "4.0" , NV_ENC_LEVEL_HEVC_4     },
-    { "4.1" , NV_ENC_LEVEL_HEVC_41    },
-    { "5"   , NV_ENC_LEVEL_HEVC_5     },
-    { "5.0" , NV_ENC_LEVEL_HEVC_5     },
-    { "5.1" , NV_ENC_LEVEL_HEVC_51    },
-    { "5.2" , NV_ENC_LEVEL_HEVC_52    },
-    { "6"   , NV_ENC_LEVEL_HEVC_6     },
-    { "6.0" , NV_ENC_LEVEL_HEVC_6     },
-    { "6.1" , NV_ENC_LEVEL_HEVC_61    },
-    { "6.2" , NV_ENC_LEVEL_HEVC_62    },
-    { NULL }
-};
+    dl_fn->nvenc_funcs.version = NV_ENCODE_API_FUNCTION_LIST_VER;
 
-static int input_string_to_uint32(AVCodecContext *avctx, const NvencValuePair *pair, const char *input, uint32_t *output)
-{
-    for (; pair->str; ++pair) {
-        if (!strcmp(input, pair->str)) {
-            *output = pair->num;
-            return 0;
-        }
-    }
+    err = nvenc_create_instance(&dl_fn->nvenc_funcs);
+    if (err != NV_ENC_SUCCESS)
+        return nvenc_print_error(avctx, err, "Failed to create nvenc instance");
+
+    av_log(avctx, AV_LOG_VERBOSE, "Nvenc initialized successfully\n");
 
-    return AVERROR(EINVAL);
+    return 0;
 }
 
-static NvencData* data_queue_dequeue(NvencDataList* queue)
+static av_cold int nvenc_open_session(AVCodecContext *avctx)
 {
-    uint32_t mask;
-    uint32_t read_pos;
-
-    av_assert0(queue);
-    av_assert0(queue->size);
-    av_assert0(queue->data);
+    NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS params = { 0 };
+    NvencContext *ctx = avctx->priv_data;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
+    NVENCSTATUS ret;
 
-    if (!queue->count)
-        return NULL;
+    params.version    = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
+    params.apiVersion = NVENCAPI_VERSION;
+    params.device     = ctx->cu_context;
+    params.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
 
-    /* Size always is a multiple of two */
-    mask = queue->size - 1;
-    read_pos = (queue->pos - queue->count) & mask;
-    queue->count--;
+    ret = p_nvenc->nvEncOpenEncodeSessionEx(&params, &ctx->nvencoder);
+    if (ret != NV_ENC_SUCCESS) {
+        ctx->nvencoder = NULL;
+        return nvenc_print_error(avctx, ret, "OpenEncodeSessionEx failed");
+    }
 
-    return &queue->data[read_pos];
+    return 0;
 }
 
-static int data_queue_enqueue(NvencDataList* queue, NvencData *data)
+static int nvenc_check_codec_support(AVCodecContext *avctx)
 {
-    NvencDataList new_queue;
-    NvencData* tmp_data;
-    uint32_t mask;
+    NvencContext *ctx = avctx->priv_data;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
+    int i, ret, count = 0;
+    GUID *guids = NULL;
 
-    if (!queue->size) {
-        /* size always has to be a multiple of two */
-        queue->size = 4;
-        queue->pos = 0;
-        queue->count = 0;
+    ret = p_nvenc->nvEncGetEncodeGUIDCount(ctx->nvencoder, &count);
 
-        queue->data = av_malloc(queue->size * sizeof(*(queue->data)));
+    if (ret != NV_ENC_SUCCESS || !count)
+        return AVERROR(ENOSYS);
 
-        if (!queue->data) {
-            queue->size = 0;
-            return AVERROR(ENOMEM);
-        }
+    guids = av_malloc(count * sizeof(GUID));
+    if (!guids)
+        return AVERROR(ENOMEM);
+
+    ret = p_nvenc->nvEncGetEncodeGUIDs(ctx->nvencoder, guids, count, &count);
+    if (ret != NV_ENC_SUCCESS) {
+        ret = AVERROR(ENOSYS);
+        goto fail;
     }
 
-    if (queue->count == queue->size) {
-        new_queue.size = queue->size << 1;
-        new_queue.pos = 0;
-        new_queue.count = 0;
-        new_queue.data = av_malloc(new_queue.size * sizeof(*(queue->data)));
+    ret = AVERROR(ENOSYS);
+    for (i = 0; i < count; i++) {
+        if (!memcmp(&guids[i], &ctx->init_encode_params.encodeGUID, sizeof(*guids))) {
+            ret = 0;
+            break;
+        }
+    }
 
-        if (!new_queue.data)
-            return AVERROR(ENOMEM);
+fail:
+    av_free(guids);
 
-        while (tmp_data = data_queue_dequeue(queue))
-            data_queue_enqueue(&new_queue, tmp_data);
+    return ret;
+}
 
-        av_free(queue->data);
-        *queue = new_queue;
-    }
+static int nvenc_check_cap(AVCodecContext *avctx, NV_ENC_CAPS cap)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &ctx->nvenc_dload_funcs.nvenc_funcs;
+    NV_ENC_CAPS_PARAM params        = { 0 };
+    int ret, val = 0;
 
-    mask = queue->size - 1;
+    params.version     = NV_ENC_CAPS_PARAM_VER;
+    params.capsToQuery = cap;
 
-    queue->data[queue->pos] = *data;
-    queue->pos = (queue->pos + 1) & mask;
-    queue->count++;
+    ret = p_nvenc->nvEncGetEncodeCaps(ctx->nvencoder, ctx->init_encode_params.encodeGUID, &params, &val);
 
+    if (ret == NV_ENC_SUCCESS)
+        return val;
     return 0;
 }
 
-static int out_surf_queue_enqueue(NvencDataList* queue, NvencOutputSurface* surface)
+static int nvenc_check_capabilities(AVCodecContext *avctx)
 {
-    NvencData data;
-    data.u.surface = surface;
+    NvencContext *ctx = avctx->priv_data;
+    int ret;
 
-    return data_queue_enqueue(queue, &data);
-}
+    ret = nvenc_check_codec_support(avctx);
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_VERBOSE, "Codec not supported\n");
+        return ret;
+    }
 
-static NvencOutputSurface* out_surf_queue_dequeue(NvencDataList* queue)
-{
-    NvencData* res = data_queue_dequeue(queue);
+    ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_YUV444_ENCODE);
+    if (ctx->data_pix_fmt == AV_PIX_FMT_YUV444P && ret <= 0) {
+        av_log(avctx, AV_LOG_VERBOSE, "YUV444P not supported\n");
+        return AVERROR(ENOSYS);
+    }
 
-    if (!res)
-        return NULL;
+    ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);
+    if (ctx->preset >= PRESET_LOSSLESS_DEFAULT && ret <= 0) {
+        av_log(avctx, AV_LOG_VERBOSE, "Lossless encoding not supported\n");
+        return AVERROR(ENOSYS);
+    }
 
-    return res->u.surface;
-}
+    ret = nvenc_check_cap(avctx, NV_ENC_CAPS_WIDTH_MAX);
+    if (ret < avctx->width) {
+        av_log(avctx, AV_LOG_VERBOSE, "Width %d exceeds %d\n",
+               avctx->width, ret);
+        return AVERROR(ENOSYS);
+    }
 
-static int timestamp_queue_enqueue(NvencDataList* queue, int64_t timestamp)
-{
-    NvencData data;
-    data.u.timestamp = timestamp;
+    ret = nvenc_check_cap(avctx, NV_ENC_CAPS_HEIGHT_MAX);
+    if (ret < avctx->height) {
+        av_log(avctx, AV_LOG_VERBOSE, "Height %d exceeds %d\n",
+               avctx->height, ret);
+        return AVERROR(ENOSYS);
+    }
 
-    return data_queue_enqueue(queue, &data);
-}
+    ret = nvenc_check_cap(avctx, NV_ENC_CAPS_NUM_MAX_BFRAMES);
+    if (ret < avctx->max_b_frames) {
+        av_log(avctx, AV_LOG_VERBOSE, "Max B-frames %d exceed %d\n",
+               avctx->max_b_frames, ret);
 
-static int64_t timestamp_queue_dequeue(NvencDataList* queue)
-{
-    NvencData* res = data_queue_dequeue(queue);
+        return AVERROR(ENOSYS);
+    }
 
-    if (!res)
-        return AV_NOPTS_VALUE;
+    ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_FIELD_ENCODING);
+    if (ret < 1 && avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
+        av_log(avctx, AV_LOG_VERBOSE,
+               "Interlaced encoding is not supported. Supported level: %d\n",
+               ret);
+        return AVERROR(ENOSYS);
+    }
 
-    return res->u.timestamp;
+    return 0;
 }
 
-#define CHECK_LOAD_FUNC(t, f, s) \
-do { \
-    (f) = (t)LOAD_FUNC(dl_fn->cuda_lib, s); \
-    if (!(f)) { \
-        av_log(avctx, AV_LOG_FATAL, "Failed loading %s from CUDA library\n", s); \
-        goto error; \
-    } \
-} while (0)
-
-static av_cold int nvenc_dyload_cuda(AVCodecContext *avctx)
+static av_cold int nvenc_check_device(AVCodecContext *avctx, int idx)
 {
     NvencContext *ctx = avctx->priv_data;
     NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
+    char name[128] = { 0};
+    int major, minor, ret;
+    CUresult cu_res;
+    CUdevice cu_device;
+    CUcontext dummy;
+    int loglevel = AV_LOG_VERBOSE;
 
-    if (dl_fn->cuda_lib)
-        return 1;
+    if (ctx->device == LIST_DEVICES)
+        loglevel = AV_LOG_INFO;
 
-#if defined(_WIN32)
-    dl_fn->cuda_lib = LoadLibrary(TEXT("nvcuda.dll"));
-#else
-    dl_fn->cuda_lib = dlopen("libcuda.so", RTLD_LAZY);
-#endif
+    cu_res = dl_fn->cu_device_get(&cu_device, idx);
+    if (cu_res != CUDA_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR,
+               "Cannot access the CUDA device %d\n",
+               idx);
+        return -1;
+    }
 
-    if (!dl_fn->cuda_lib) {
-        av_log(avctx, AV_LOG_FATAL, "Failed loading CUDA library\n");
-        goto error;
+    cu_res = dl_fn->cu_device_get_name(name, sizeof(name), cu_device);
+    if (cu_res != CUDA_SUCCESS)
+        return -1;
+
+    cu_res = dl_fn->cu_device_compute_capability(&major, &minor, cu_device);
+    if (cu_res != CUDA_SUCCESS)
+        return -1;
+
+    av_log(avctx, loglevel, "[ GPU #%d - < %s > has Compute SM %d.%d ]\n", idx, name, major, minor);
+    if (((major << 4) | minor) < NVENC_CAP) {
+        av_log(avctx, loglevel, "does not support NVENC\n");
+        goto fail;
     }
 
-    CHECK_LOAD_FUNC(PCUINIT, dl_fn->cu_init, "cuInit");
-    CHECK_LOAD_FUNC(PCUDEVICEGETCOUNT, dl_fn->cu_device_get_count, "cuDeviceGetCount");
-    CHECK_LOAD_FUNC(PCUDEVICEGET, dl_fn->cu_device_get, "cuDeviceGet");
-    CHECK_LOAD_FUNC(PCUDEVICEGETNAME, dl_fn->cu_device_get_name, "cuDeviceGetName");
-    CHECK_LOAD_FUNC(PCUDEVICECOMPUTECAPABILITY, dl_fn->cu_device_compute_capability, "cuDeviceComputeCapability");
-    CHECK_LOAD_FUNC(PCUCTXCREATE, dl_fn->cu_ctx_create, "cuCtxCreate_v2");
-    CHECK_LOAD_FUNC(PCUCTXPOPCURRENT, dl_fn->cu_ctx_pop_current, "cuCtxPopCurrent_v2");
-    CHECK_LOAD_FUNC(PCUCTXDESTROY, dl_fn->cu_ctx_destroy, "cuCtxDestroy_v2");
+    cu_res = dl_fn->cu_ctx_create(&ctx->cu_context_internal, 0, cu_device);
+    if (cu_res != CUDA_SUCCESS) {
+        av_log(avctx, AV_LOG_FATAL, "Failed creating CUDA context for NVENC: 0x%x\n", (int)cu_res);
+        goto fail;
+    }
 
-    return 1;
+    ctx->cu_context = ctx->cu_context_internal;
 
-error:
+    cu_res = dl_fn->cu_ctx_pop_current(&dummy);
+    if (cu_res != CUDA_SUCCESS) {
+        av_log(avctx, AV_LOG_FATAL, "Failed popping CUDA context: 0x%x\n", (int)cu_res);
+        goto fail2;
+    }
 
-    if (dl_fn->cuda_lib)
-        DL_CLOSE_FUNC(dl_fn->cuda_lib);
+    if ((ret = nvenc_open_session(avctx)) < 0)
+        goto fail2;
 
-    dl_fn->cuda_lib = NULL;
+    if ((ret = nvenc_check_capabilities(avctx)) < 0)
+        goto fail3;
 
-    return 0;
-}
+    av_log(avctx, loglevel, "supports NVENC\n");
 
-static av_cold int check_cuda_errors(AVCodecContext *avctx, CUresult err, const char *func)
-{
-    if (err != CUDA_SUCCESS) {
-        av_log(avctx, AV_LOG_FATAL, ">> %s - failed with error code 0x%x\n", func, err);
+    dl_fn->nvenc_device_count++;
+
+    if (ctx->device == dl_fn->nvenc_device_count - 1 || ctx->device == ANY_DEVICE)
         return 0;
-    }
-    return 1;
+
+fail3:
+    p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
+    ctx->nvencoder = NULL;
+
+fail2:
+    dl_fn->cu_ctx_destroy(ctx->cu_context_internal);
+    ctx->cu_context_internal = NULL;
+
+fail:
+    return AVERROR(ENOSYS);
 }
-#define check_cuda_errors(f) if (!check_cuda_errors(avctx, f, #f)) goto error
 
-static av_cold int nvenc_check_cuda(AVCodecContext *avctx)
+static av_cold int nvenc_setup_device(AVCodecContext *avctx)
 {
-    int device_count = 0;
-    CUdevice cu_device = 0;
-    char gpu_name[128];
-    int smminor = 0, smmajor = 0;
-    int i, smver, target_smver;
-
     NvencContext *ctx = avctx->priv_data;
     NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
 
     switch (avctx->codec->id) {
     case AV_CODEC_ID_H264:
-        target_smver = avctx->pix_fmt == AV_PIX_FMT_YUV444P ? 0x52 : 0x30;
+        ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_H264_GUID;
         break;
-    case AV_CODEC_ID_H265:
-        target_smver = 0x52;
+    case AV_CODEC_ID_HEVC:
+        ctx->init_encode_params.encodeGUID = NV_ENC_CODEC_HEVC_GUID;
         break;
     default:
-        av_log(avctx, AV_LOG_FATAL, "Unknown codec name\n");
-        goto error;
+        return AVERROR_BUG;
     }
 
-    if (!nvenc_dyload_cuda(avctx))
-        return 0;
-
-    if (dl_fn->nvenc_device_count > 0)
-        return 1;
+    if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
+#if CONFIG_CUDA
+        AVHWFramesContext   *frames_ctx;
+        AVCUDADeviceContext *device_hwctx;
+        int ret;
 
-    check_cuda_errors(dl_fn->cu_init(0));
+        if (!avctx->hw_frames_ctx)
+            return AVERROR(EINVAL);
 
-    check_cuda_errors(dl_fn->cu_device_get_count(&device_count));
+        frames_ctx   = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
+        device_hwctx = frames_ctx->device_ctx->hwctx;
 
-    if (!device_count) {
-        av_log(avctx, AV_LOG_FATAL, "No CUDA capable devices found\n");
-        goto error;
-    }
+        ctx->cu_context = device_hwctx->cuda_ctx;
 
-    av_log(avctx, AV_LOG_VERBOSE, "%d CUDA capable devices found\n", device_count);
+        ret = nvenc_open_session(avctx);
+        if (ret < 0)
+            return ret;
 
-    dl_fn->nvenc_device_count = 0;
+        ret = nvenc_check_capabilities(avctx);
+        if (ret < 0) {
+            av_log(avctx, AV_LOG_FATAL, "Provided device doesn't support required NVENC features\n");
+            return ret;
+        }
+#else
+        return AVERROR_BUG;
+#endif
+    } else {
+        int i, nb_devices = 0;
 
-    for (i = 0; i < device_count; ++i) {
-        check_cuda_errors(dl_fn->cu_device_get(&cu_device, i));
-        check_cuda_errors(dl_fn->cu_device_get_name(gpu_name, sizeof(gpu_name), cu_device));
-        check_cuda_errors(dl_fn->cu_device_compute_capability(&smmajor, &smminor, cu_device));
+        if ((dl_fn->cu_init(0)) != CUDA_SUCCESS) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Cannot init CUDA\n");
+            return AVERROR_UNKNOWN;
+        }
 
-        smver = (smmajor << 4) | smminor;
+        if ((dl_fn->cu_device_get_count(&nb_devices)) != CUDA_SUCCESS) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "Cannot enumerate the CUDA devices\n");
+            return AVERROR_UNKNOWN;
+        }
 
-        av_log(avctx, AV_LOG_VERBOSE, "[ GPU #%d - < %s > has Compute SM %d.%d, NVENC %s ]\n", i, gpu_name, smmajor, smminor, (smver >= target_smver) ? "Available" : "Not Available");
+        if (!nb_devices) {
+            av_log(avctx, AV_LOG_FATAL, "No CUDA capable devices found\n");
+                return AVERROR_EXTERNAL;
+        }
 
-        if (smver >= target_smver)
-            dl_fn->nvenc_devices[dl_fn->nvenc_device_count++] = cu_device;
-    }
+        av_log(avctx, AV_LOG_VERBOSE, "%d CUDA capable devices found\n", nb_devices);
 
-    if (!dl_fn->nvenc_device_count) {
-        av_log(avctx, AV_LOG_FATAL, "No NVENC capable devices found\n");
-        goto error;
-    }
+        dl_fn->nvenc_device_count = 0;
+        for (i = 0; i < nb_devices; ++i) {
+            if ((nvenc_check_device(avctx, i)) >= 0 && ctx->device != LIST_DEVICES)
+                return 0;
+        }
 
-    return 1;
+        if (ctx->device == LIST_DEVICES)
+            return AVERROR_EXIT;
 
-error:
+        if (!dl_fn->nvenc_device_count) {
+            av_log(avctx, AV_LOG_FATAL, "No NVENC capable devices found\n");
+            return AVERROR_EXTERNAL;
+        }
 
-    dl_fn->nvenc_device_count = 0;
+        av_log(avctx, AV_LOG_FATAL, "Requested GPU %d, but only %d GPUs are available!\n", ctx->device, dl_fn->nvenc_device_count);
+        return AVERROR(EINVAL);
+    }
 
     return 0;
 }
 
-static av_cold int nvenc_dyload_nvenc(AVCodecContext *avctx)
+typedef struct GUIDTuple {
+    const GUID guid;
+    int flags;
+} GUIDTuple;
+
+static void nvenc_map_preset(NvencContext *ctx)
 {
-    PNVENCODEAPICREATEINSTANCE nvEncodeAPICreateInstance = 0;
-    NVENCSTATUS nvstatus;
+    GUIDTuple presets[] = {
+        { NV_ENC_PRESET_DEFAULT_GUID },
+        { NV_ENC_PRESET_HQ_GUID,                  NVENC_TWO_PASSES }, /* slow */
+        { NV_ENC_PRESET_HQ_GUID,                  NVENC_ONE_PASS }, /* medium */
+        { NV_ENC_PRESET_HP_GUID,                  NVENC_ONE_PASS }, /* fast */
+        { NV_ENC_PRESET_HP_GUID },
+        { NV_ENC_PRESET_HQ_GUID },
+        { NV_ENC_PRESET_BD_GUID },
+        { NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID, NVENC_LOWLATENCY },
+        { NV_ENC_PRESET_LOW_LATENCY_HQ_GUID,      NVENC_LOWLATENCY },
+        { NV_ENC_PRESET_LOW_LATENCY_HP_GUID,      NVENC_LOWLATENCY },
+        { NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID,    NVENC_LOSSLESS },
+        { NV_ENC_PRESET_LOSSLESS_HP_GUID,         NVENC_LOSSLESS },
+    };
+
+    GUIDTuple *t = &presets[ctx->preset];
+
+    ctx->init_encode_params.presetGUID = t->guid;
+    ctx->flags = t->flags;
+}
 
+static av_cold void set_constqp(AVCodecContext *avctx)
+{
     NvencContext *ctx = avctx->priv_data;
-    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
 
-    if (!nvenc_check_cuda(avctx))
-        return 0;
+    rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
+    rc->constQP.qpInterB = avctx->global_quality;
+    rc->constQP.qpInterP = avctx->global_quality;
+    rc->constQP.qpIntra = avctx->global_quality;
 
-    if (dl_fn->nvenc_lib)
-        return 1;
+    avctx->qmin = -1;
+    avctx->qmax = -1;
+}
 
-#if defined(_WIN32)
-    if (sizeof(void*) == 8) {
-        dl_fn->nvenc_lib = LoadLibrary(TEXT("nvEncodeAPI64.dll"));
-    } else {
-        dl_fn->nvenc_lib = LoadLibrary(TEXT("nvEncodeAPI.dll"));
-    }
-#else
-    dl_fn->nvenc_lib = dlopen("libnvidia-encode.so.1", RTLD_LAZY);
-#endif
+static av_cold void set_vbr(AVCodecContext *avctx)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
+    int qp_inter_p;
 
-    if (!dl_fn->nvenc_lib) {
-        av_log(avctx, AV_LOG_FATAL, "Failed loading the nvenc library\n");
-        goto error;
-    }
+    if (avctx->qmin >= 0 && avctx->qmax >= 0) {
+        rc->enableMinQP = 1;
+        rc->enableMaxQP = 1;
 
-    nvEncodeAPICreateInstance = (PNVENCODEAPICREATEINSTANCE)LOAD_FUNC(dl_fn->nvenc_lib, "NvEncodeAPICreateInstance");
+        rc->minQP.qpInterB = avctx->qmin;
+        rc->minQP.qpInterP = avctx->qmin;
+        rc->minQP.qpIntra = avctx->qmin;
 
-    if (!nvEncodeAPICreateInstance) {
-        av_log(avctx, AV_LOG_FATAL, "Failed to load nvenc entrypoint\n");
-        goto error;
-    }
+        rc->maxQP.qpInterB = avctx->qmax;
+        rc->maxQP.qpInterP = avctx->qmax;
+        rc->maxQP.qpIntra = avctx->qmax;
 
-    dl_fn->nvenc_funcs.version = NV_ENCODE_API_FUNCTION_LIST_VER;
+        qp_inter_p = (avctx->qmax + 3 * avctx->qmin) / 4; // biased towards Qmin
+    } else if (avctx->qmin >= 0) {
+        rc->enableMinQP = 1;
 
-    nvstatus = nvEncodeAPICreateInstance(&dl_fn->nvenc_funcs);
+        rc->minQP.qpInterB = avctx->qmin;
+        rc->minQP.qpInterP = avctx->qmin;
+        rc->minQP.qpIntra = avctx->qmin;
 
-    if (nvstatus != NV_ENC_SUCCESS) {
-        av_log(avctx, AV_LOG_FATAL, "Failed to create nvenc instance\n");
-        goto error;
+        qp_inter_p = avctx->qmin;
+    } else {
+        qp_inter_p = 26; // default to 26
     }
 
-    av_log(avctx, AV_LOG_VERBOSE, "Nvenc initialized successfully\n");
+    rc->enableInitialRCQP = 1;
+    rc->initialRCQP.qpInterP  = qp_inter_p;
 
-    return 1;
+    if (avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
+        rc->initialRCQP.qpIntra = av_clip(
+            qp_inter_p * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51);
+        rc->initialRCQP.qpInterB = av_clip(
+            qp_inter_p * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51);
+    } else {
+        rc->initialRCQP.qpIntra = qp_inter_p;
+        rc->initialRCQP.qpInterB = qp_inter_p;
+    }
+}
 
-error:
-    if (dl_fn->nvenc_lib)
-        DL_CLOSE_FUNC(dl_fn->nvenc_lib);
+static av_cold void set_lossless(AVCodecContext *avctx)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
 
-    dl_fn->nvenc_lib = NULL;
+    rc->rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
+    rc->constQP.qpInterB = 0;
+    rc->constQP.qpInterP = 0;
+    rc->constQP.qpIntra = 0;
 
-    return 0;
+    avctx->qmin = -1;
+    avctx->qmax = -1;
 }
 
-static av_cold void nvenc_unload_nvenc(AVCodecContext *avctx)
+static void nvenc_override_rate_control(AVCodecContext *avctx)
+{
+    NvencContext *ctx    = avctx->priv_data;
+    NV_ENC_RC_PARAMS *rc = &ctx->encode_config.rcParams;
+
+    switch (ctx->rc) {
+    case NV_ENC_PARAMS_RC_CONSTQP:
+        if (avctx->global_quality <= 0) {
+            av_log(avctx, AV_LOG_WARNING,
+                   "The constant quality rate-control requires "
+                   "the 'global_quality' option set.\n");
+            return;
+        }
+        set_constqp(avctx);
+        return;
+    case NV_ENC_PARAMS_RC_2_PASS_VBR:
+    case NV_ENC_PARAMS_RC_VBR:
+        if (avctx->qmin < 0 && avctx->qmax < 0) {
+            av_log(avctx, AV_LOG_WARNING,
+                   "The variable bitrate rate-control requires "
+                   "the 'qmin' and/or 'qmax' option set.\n");
+            set_vbr(avctx);
+            return;
+        }
+    case NV_ENC_PARAMS_RC_VBR_MINQP:
+        if (avctx->qmin < 0) {
+            av_log(avctx, AV_LOG_WARNING,
+                   "The variable bitrate rate-control requires "
+                   "the 'qmin' option set.\n");
+            set_vbr(avctx);
+            return;
+        }
+        set_vbr(avctx);
+        break;
+    case NV_ENC_PARAMS_RC_CBR:
+    case NV_ENC_PARAMS_RC_2_PASS_QUALITY:
+    case NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP:
+        break;
+    }
+
+    rc->rateControlMode = ctx->rc;
+}
+
+static av_cold void nvenc_setup_rate_control(AVCodecContext *avctx)
 {
     NvencContext *ctx = avctx->priv_data;
-    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
 
-    DL_CLOSE_FUNC(dl_fn->nvenc_lib);
-    dl_fn->nvenc_lib = NULL;
+    if (avctx->bit_rate > 0) {
+        ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate;
+    } else if (ctx->encode_config.rcParams.averageBitRate > 0) {
+        ctx->encode_config.rcParams.maxBitRate = ctx->encode_config.rcParams.averageBitRate;
+    }
+
+    if (avctx->rc_max_rate > 0)
+        ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
 
-    dl_fn->nvenc_device_count = 0;
+    if (ctx->rc < 0) {
+        if (ctx->flags & NVENC_ONE_PASS)
+            ctx->twopass = 0;
+        if (ctx->flags & NVENC_TWO_PASSES)
+            ctx->twopass = 1;
 
-    DL_CLOSE_FUNC(dl_fn->cuda_lib);
-    dl_fn->cuda_lib = NULL;
+        if (ctx->twopass < 0)
+            ctx->twopass = (ctx->flags & NVENC_LOWLATENCY) != 0;
 
-    dl_fn->cu_init = NULL;
-    dl_fn->cu_device_get_count = NULL;
-    dl_fn->cu_device_get = NULL;
-    dl_fn->cu_device_get_name = NULL;
-    dl_fn->cu_device_compute_capability = NULL;
-    dl_fn->cu_ctx_create = NULL;
-    dl_fn->cu_ctx_pop_current = NULL;
-    dl_fn->cu_ctx_destroy = NULL;
+        if (ctx->cbr) {
+            if (ctx->twopass) {
+                ctx->rc = NV_ENC_PARAMS_RC_2_PASS_QUALITY;
+            } else {
+                ctx->rc = NV_ENC_PARAMS_RC_CBR;
+            }
+        } else if (avctx->global_quality > 0) {
+            ctx->rc = NV_ENC_PARAMS_RC_CONSTQP;
+        } else if (ctx->twopass) {
+            ctx->rc = NV_ENC_PARAMS_RC_2_PASS_VBR;
+        } else if (avctx->qmin >= 0 && avctx->qmax >= 0) {
+            ctx->rc = NV_ENC_PARAMS_RC_VBR_MINQP;
+        }
+    }
 
-    av_log(avctx, AV_LOG_VERBOSE, "Nvenc unloaded\n");
+    if (ctx->flags & NVENC_LOSSLESS) {
+        set_lossless(avctx);
+    } else if (ctx->rc >= 0) {
+        nvenc_override_rate_control(avctx);
+    } else {
+        ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR;
+        set_vbr(avctx);
+    }
+
+    if (avctx->rc_buffer_size > 0) {
+        ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size;
+    } else if (ctx->encode_config.rcParams.averageBitRate > 0) {
+        ctx->encode_config.rcParams.vbvBufferSize = 2 * ctx->encode_config.rcParams.averageBitRate;
+    }
 }
 
-static av_cold int nvenc_encode_init(AVCodecContext *avctx)
+static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx)
 {
-    NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS encode_session_params = { 0 };
-    NV_ENC_PRESET_CONFIG preset_config = { 0 };
-    CUcontext cu_context_curr;
-    CUresult cu_res;
-    GUID encoder_preset = NV_ENC_PRESET_HQ_GUID;
-    GUID codec;
-    NVENCSTATUS nv_status = NV_ENC_SUCCESS;
-    AVCPBProperties *cpb_props;
-    int surfaceCount = 0;
-    int i, num_mbs;
-    int isLL = 0;
-    int lossless = 0;
-    int res = 0;
-    int dw, dh;
-    int qp_inter_p;
+    NvencContext *ctx                      = avctx->priv_data;
+    NV_ENC_CONFIG *cc                      = &ctx->encode_config;
+    NV_ENC_CONFIG_H264 *h264               = &cc->encodeCodecConfig.h264Config;
+    NV_ENC_CONFIG_H264_VUI_PARAMETERS *vui = &h264->h264VUIParameters;
 
-    NvencContext *ctx = avctx->priv_data;
-    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
-    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
+    vui->colourMatrix = avctx->colorspace;
+    vui->colourPrimaries = avctx->color_primaries;
+    vui->transferCharacteristics = avctx->color_trc;
+    vui->videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
+        || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
 
-    if (!nvenc_dyload_nvenc(avctx))
-        return AVERROR_EXTERNAL;
+    vui->colourDescriptionPresentFlag =
+        (avctx->colorspace != 2 || avctx->color_primaries != 2 || avctx->color_trc != 2);
 
-    ctx->last_dts = AV_NOPTS_VALUE;
+    vui->videoSignalTypePresentFlag =
+        (vui->colourDescriptionPresentFlag
+        || vui->videoFormat != 5
+        || vui->videoFullRangeFlag != 0);
 
-    ctx->encode_config.version = NV_ENC_CONFIG_VER;
-    ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;
-    preset_config.version = NV_ENC_PRESET_CONFIG_VER;
-    preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
-    encode_session_params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
-    encode_session_params.apiVersion = NVENCAPI_VERSION;
+    h264->sliceMode = 3;
+    h264->sliceModeData = 1;
 
-    if (ctx->gpu >= dl_fn->nvenc_device_count) {
-        av_log(avctx, AV_LOG_FATAL, "Requested GPU %d, but only %d GPUs are available!\n", ctx->gpu, dl_fn->nvenc_device_count);
-        res = AVERROR(EINVAL);
-        goto error;
+    h264->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
+    h264->repeatSPSPPS  = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
+    h264->outputAUD     = 1;
+
+    if (avctx->refs >= 0) {
+        /* 0 means "let the hardware decide" */
+        h264->maxNumRefFrames = avctx->refs;
+    }
+    if (avctx->gop_size >= 0) {
+        h264->idrPeriod = cc->gopLength;
     }
 
-    ctx->cu_context = NULL;
-    cu_res = dl_fn->cu_ctx_create(&ctx->cu_context, 4, dl_fn->nvenc_devices[ctx->gpu]); // CU_CTX_SCHED_BLOCKING_SYNC=4, avoid CPU spins
+    if (IS_CBR(cc->rcParams.rateControlMode)) {
+        h264->outputBufferingPeriodSEI = 1;
+        h264->outputPictureTimingSEI   = 1;
+    }
 
-    if (cu_res != CUDA_SUCCESS) {
-        av_log(avctx, AV_LOG_FATAL, "Failed creating CUDA context for NVENC: 0x%x\n", (int)cu_res);
-        res = AVERROR_EXTERNAL;
-        goto error;
+    if (cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_2_PASS_QUALITY ||
+        cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP ||
+        cc->rcParams.rateControlMode == NV_ENC_PARAMS_RC_2_PASS_VBR) {
+        h264->adaptiveTransformMode = NV_ENC_H264_ADAPTIVE_TRANSFORM_ENABLE;
+        h264->fmoMode = NV_ENC_H264_FMO_DISABLE;
     }
 
-    cu_res = dl_fn->cu_ctx_pop_current(&cu_context_curr);
+    if (ctx->flags & NVENC_LOSSLESS) {
+        h264->qpPrimeYZeroTransformBypassFlag = 1;
+    } else {
+        switch(ctx->profile) {
+        case NV_ENC_H264_PROFILE_BASELINE:
+            cc->profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
+            avctx->profile = FF_PROFILE_H264_BASELINE;
+            break;
+        case NV_ENC_H264_PROFILE_MAIN:
+            cc->profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
+            avctx->profile = FF_PROFILE_H264_MAIN;
+            break;
+        case NV_ENC_H264_PROFILE_HIGH:
+            cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
+            avctx->profile = FF_PROFILE_H264_HIGH;
+            break;
+        case NV_ENC_H264_PROFILE_HIGH_444P:
+            cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
+            avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;
+            break;
+        }
+    }
 
-    if (cu_res != CUDA_SUCCESS) {
-        av_log(avctx, AV_LOG_FATAL, "Failed popping CUDA context: 0x%x\n", (int)cu_res);
-        res = AVERROR_EXTERNAL;
-        goto error;
+    // force setting profile as high444p if input is AV_PIX_FMT_YUV444P
+    if (ctx->data_pix_fmt == AV_PIX_FMT_YUV444P) {
+        cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
+        avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;
     }
 
-    encode_session_params.device = ctx->cu_context;
-    encode_session_params.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
+    h264->chromaFormatIDC = avctx->profile == FF_PROFILE_H264_HIGH_444_PREDICTIVE ? 3 : 1;
 
-    nv_status = p_nvenc->nvEncOpenEncodeSessionEx(&encode_session_params, &ctx->nvencoder);
-    if (nv_status != NV_ENC_SUCCESS) {
-        ctx->nvencoder = NULL;
-        av_log(avctx, AV_LOG_FATAL, "OpenEncodeSessionEx failed: 0x%x\n", (int)nv_status);
-        res = AVERROR_EXTERNAL;
-        goto error;
-    }
+    h264->level = ctx->level;
 
-    if (ctx->preset) {
-        if (!strcmp(ctx->preset, "slow")) {
-            encoder_preset = NV_ENC_PRESET_HQ_GUID;
-            ctx->twopass = 1;
-        } else if (!strcmp(ctx->preset, "medium")) {
-            encoder_preset = NV_ENC_PRESET_HQ_GUID;
-            ctx->twopass = 0;
-        } else if (!strcmp(ctx->preset, "fast")) {
-            encoder_preset = NV_ENC_PRESET_HP_GUID;
-            ctx->twopass = 0;
-        } else if (!strcmp(ctx->preset, "hq")) {
-            encoder_preset = NV_ENC_PRESET_HQ_GUID;
-        } else if (!strcmp(ctx->preset, "hp")) {
-            encoder_preset = NV_ENC_PRESET_HP_GUID;
-        } else if (!strcmp(ctx->preset, "bd")) {
-            encoder_preset = NV_ENC_PRESET_BD_GUID;
-        } else if (!strcmp(ctx->preset, "ll")) {
-            encoder_preset = NV_ENC_PRESET_LOW_LATENCY_DEFAULT_GUID;
-            isLL = 1;
-        } else if (!strcmp(ctx->preset, "llhp")) {
-            encoder_preset = NV_ENC_PRESET_LOW_LATENCY_HP_GUID;
-            isLL = 1;
-        } else if (!strcmp(ctx->preset, "llhq")) {
-            encoder_preset = NV_ENC_PRESET_LOW_LATENCY_HQ_GUID;
-            isLL = 1;
-        } else if (!strcmp(ctx->preset, "lossless")) {
-            encoder_preset = NV_ENC_PRESET_LOSSLESS_DEFAULT_GUID;
-            lossless = 1;
-        } else if (!strcmp(ctx->preset, "losslesshp")) {
-            encoder_preset = NV_ENC_PRESET_LOSSLESS_HP_GUID;
-            lossless = 1;
-        } else if (!strcmp(ctx->preset, "default")) {
-            encoder_preset = NV_ENC_PRESET_DEFAULT_GUID;
-        } else {
-            av_log(avctx, AV_LOG_FATAL, "Preset \"%s\" is unknown! Supported presets: slow, medium, high, hp, hq, bd, ll, llhp, llhq, lossless, losslesshp, default\n", ctx->preset);
-            res = AVERROR(EINVAL);
-            goto error;
-        }
+    return 0;
+}
+
+static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
+{
+    NvencContext *ctx                      = avctx->priv_data;
+    NV_ENC_CONFIG *cc                      = &ctx->encode_config;
+    NV_ENC_CONFIG_HEVC *hevc               = &cc->encodeCodecConfig.hevcConfig;
+    NV_ENC_CONFIG_HEVC_VUI_PARAMETERS *vui = &hevc->hevcVUIParameters;
+
+    vui->colourMatrix = avctx->colorspace;
+    vui->colourPrimaries = avctx->color_primaries;
+    vui->transferCharacteristics = avctx->color_trc;
+    vui->videoFullRangeFlag = (avctx->color_range == AVCOL_RANGE_JPEG
+        || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ420P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ422P || ctx->data_pix_fmt == AV_PIX_FMT_YUVJ444P);
+
+    vui->colourDescriptionPresentFlag =
+        (avctx->colorspace != 2 || avctx->color_primaries != 2 || avctx->color_trc != 2);
+
+    vui->videoSignalTypePresentFlag =
+        (vui->colourDescriptionPresentFlag
+        || vui->videoFormat != 5
+        || vui->videoFullRangeFlag != 0);
+
+    hevc->sliceMode = 3;
+    hevc->sliceModeData = 1;
+
+    hevc->disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
+    hevc->repeatSPSPPS  = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
+    hevc->outputAUD     = 1;
+
+    if (avctx->refs >= 0) {
+        /* 0 means "let the hardware decide" */
+        hevc->maxNumRefFramesInDPB = avctx->refs;
+    }
+    if (avctx->gop_size >= 0) {
+        hevc->idrPeriod = cc->gopLength;
     }
 
-    if (ctx->twopass < 0) {
-        ctx->twopass = isLL;
+    if (IS_CBR(cc->rcParams.rateControlMode)) {
+        hevc->outputBufferingPeriodSEI = 1;
+        hevc->outputPictureTimingSEI   = 1;
     }
 
+    /* No other profile is supported in the current SDK version 5 */
+    cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;
+    avctx->profile = FF_PROFILE_HEVC_MAIN;
+
+    hevc->level = ctx->level;
+
+    hevc->tier = ctx->tier;
+
+    return 0;
+}
+
+static av_cold int nvenc_setup_codec_config(AVCodecContext *avctx)
+{
     switch (avctx->codec->id) {
     case AV_CODEC_ID_H264:
-        codec = NV_ENC_CODEC_H264_GUID;
-        break;
-    case AV_CODEC_ID_H265:
-        codec = NV_ENC_CODEC_HEVC_GUID;
-        break;
-    default:
-        av_log(avctx, AV_LOG_ERROR, "Unknown codec name\n");
-        res = AVERROR(EINVAL);
-        goto error;
+        return nvenc_setup_h264_config(avctx);
+    case AV_CODEC_ID_HEVC:
+        return nvenc_setup_hevc_config(avctx);
+    /* Earlier switch/case will return if unknown codec is passed. */
     }
 
-    nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder, codec, encoder_preset, &preset_config);
-    if (nv_status != NV_ENC_SUCCESS) {
-        av_log(avctx, AV_LOG_FATAL, "GetEncodePresetConfig failed: 0x%x\n", (int)nv_status);
-        res = AVERROR_EXTERNAL;
-        goto error;
-    }
+    return 0;
+}
+
+static av_cold int nvenc_setup_encoder(AVCodecContext *avctx)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
+
+    NV_ENC_PRESET_CONFIG preset_config = { 0 };
+    NVENCSTATUS nv_status = NV_ENC_SUCCESS;
+    AVCPBProperties *cpb_props;
+    int res = 0;
+    int dw, dh;
+
+    ctx->encode_config.version = NV_ENC_CONFIG_VER;
+    ctx->init_encode_params.version = NV_ENC_INITIALIZE_PARAMS_VER;
 
-    ctx->init_encode_params.encodeGUID = codec;
     ctx->init_encode_params.encodeHeight = avctx->height;
     ctx->init_encode_params.encodeWidth = avctx->width;
 
+    ctx->init_encode_params.encodeConfig = &ctx->encode_config;
+
+    nvenc_map_preset(ctx);
+
+    preset_config.version = NV_ENC_PRESET_CONFIG_VER;
+    preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
+
+    nv_status = p_nvenc->nvEncGetEncodePresetConfig(ctx->nvencoder,
+                                                    ctx->init_encode_params.encodeGUID,
+                                                    ctx->init_encode_params.presetGUID,
+                                                    &preset_config);
+    if (nv_status != NV_ENC_SUCCESS)
+        return nvenc_print_error(avctx, nv_status, "Cannot get the preset configuration");
+
+    memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config));
+
+    ctx->encode_config.version = NV_ENC_CONFIG_VER;
+
     if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den &&
         (avctx->sample_aspect_ratio.num != 1 || avctx->sample_aspect_ratio.num != 1)) {
         av_reduce(&dw, &dh,
@@ -705,457 +888,570 @@ static av_cold int nvenc_encode_init(AVCodecContext *avctx)
     ctx->init_encode_params.frameRateNum = avctx->time_base.den;
     ctx->init_encode_params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame;
 
-    num_mbs = ((avctx->width + 15) >> 4) * ((avctx->height + 15) >> 4);
-    ctx->max_surface_count = (num_mbs >= 8160) ? 32 : 48;
-
-    if (ctx->buffer_delay >= ctx->max_surface_count)
-        ctx->buffer_delay = ctx->max_surface_count - 1;
-
     ctx->init_encode_params.enableEncodeAsync = 0;
     ctx->init_encode_params.enablePTD = 1;
 
-    ctx->init_encode_params.presetGUID = encoder_preset;
-
-    ctx->init_encode_params.encodeConfig = &ctx->encode_config;
-    memcpy(&ctx->encode_config, &preset_config.presetCfg, sizeof(ctx->encode_config));
-    ctx->encode_config.version = NV_ENC_CONFIG_VER;
-
-    if (avctx->refs >= 0) {
-        /* 0 means "let the hardware decide" */
-        switch (avctx->codec->id) {
-        case AV_CODEC_ID_H264:
-            ctx->encode_config.encodeCodecConfig.h264Config.maxNumRefFrames = avctx->refs;
-            break;
-        case AV_CODEC_ID_H265:
-            ctx->encode_config.encodeCodecConfig.hevcConfig.maxNumRefFramesInDPB = avctx->refs;
-            break;
-        /* Earlier switch/case will return if unknown codec is passed. */
-        }
-    }
-
     if (avctx->gop_size > 0) {
         if (avctx->max_b_frames >= 0) {
-            /* 0 is intra-only, 1 is I/P only, 2 is one B Frame, 3 two B frames, and so on. */
+            /* 0 is intra-only, 1 is I/P only, 2 is one B-Frame, 3 two B-frames, and so on. */
             ctx->encode_config.frameIntervalP = avctx->max_b_frames + 1;
         }
 
         ctx->encode_config.gopLength = avctx->gop_size;
-        switch (avctx->codec->id) {
-        case AV_CODEC_ID_H264:
-            ctx->encode_config.encodeCodecConfig.h264Config.idrPeriod = avctx->gop_size;
-            break;
-        case AV_CODEC_ID_H265:
-            ctx->encode_config.encodeCodecConfig.hevcConfig.idrPeriod = avctx->gop_size;
-            break;
-        /* Earlier switch/case will return if unknown codec is passed. */
-        }
     } else if (avctx->gop_size == 0) {
         ctx->encode_config.frameIntervalP = 0;
         ctx->encode_config.gopLength = 1;
-        switch (avctx->codec->id) {
-        case AV_CODEC_ID_H264:
-            ctx->encode_config.encodeCodecConfig.h264Config.idrPeriod = 1;
-            break;
-        case AV_CODEC_ID_H265:
-            ctx->encode_config.encodeCodecConfig.hevcConfig.idrPeriod = 1;
-            break;
-        /* Earlier switch/case will return if unknown codec is passed. */
+    }
+
+    ctx->initial_pts[0] = AV_NOPTS_VALUE;
+    ctx->initial_pts[1] = AV_NOPTS_VALUE;
+
+    nvenc_setup_rate_control(avctx);
+
+    if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
+        ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
+    } else {
+        ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;
+    }
+
+    res = nvenc_setup_codec_config(avctx);
+    if (res)
+        return res;
+
+    nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params);
+    if (nv_status != NV_ENC_SUCCESS) {
+        return nvenc_print_error(avctx, nv_status, "InitializeEncoder failed");
+    }
+
+    if (ctx->encode_config.frameIntervalP > 1)
+        avctx->has_b_frames = 2;
+
+    if (ctx->encode_config.rcParams.averageBitRate > 0)
+        avctx->bit_rate = ctx->encode_config.rcParams.averageBitRate;
+
+    cpb_props = ff_add_cpb_side_data(avctx);
+    if (!cpb_props)
+        return AVERROR(ENOMEM);
+    cpb_props->max_bitrate = ctx->encode_config.rcParams.maxBitRate;
+    cpb_props->avg_bitrate = avctx->bit_rate;
+    cpb_props->buffer_size = ctx->encode_config.rcParams.vbvBufferSize;
+
+    return 0;
+}
+
+static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
+
+    NVENCSTATUS nv_status;
+    NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 };
+    allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;
+
+    switch (ctx->data_pix_fmt) {
+    case AV_PIX_FMT_YUV420P:
+        ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YV12_PL;
+        break;
+
+    case AV_PIX_FMT_NV12:
+        ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_NV12_PL;
+        break;
+
+    case AV_PIX_FMT_YUV444P:
+        ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_PL;
+        break;
+
+    default:
+        av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format\n");
+        return AVERROR(EINVAL);
+    }
+
+    if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
+        ctx->surfaces[idx].in_ref = av_frame_alloc();
+        if (!ctx->surfaces[idx].in_ref)
+            return AVERROR(ENOMEM);
+    } else {
+        NV_ENC_CREATE_INPUT_BUFFER allocSurf = { 0 };
+        allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER;
+        allocSurf.width = (avctx->width + 31) & ~31;
+        allocSurf.height = (avctx->height + 31) & ~31;
+        allocSurf.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;
+        allocSurf.bufferFmt = ctx->surfaces[idx].format;
+
+        nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf);
+        if (nv_status != NV_ENC_SUCCESS) {
+            return nvenc_print_error(avctx, nv_status, "CreateInputBuffer failed");
         }
+
+        ctx->surfaces[idx].input_surface = allocSurf.inputBuffer;
+        ctx->surfaces[idx].width = allocSurf.width;
+        ctx->surfaces[idx].height = allocSurf.height;
     }
 
-    /* when there're b frames, set dts offset */
-    if (ctx->encode_config.frameIntervalP >= 2)
-        ctx->last_dts = -2;
+    ctx->surfaces[idx].lockCount = 0;
 
-    if (avctx->bit_rate > 0) {
-        ctx->encode_config.rcParams.averageBitRate = avctx->bit_rate;
-    } else if (ctx->encode_config.rcParams.averageBitRate > 0) {
-        ctx->encode_config.rcParams.maxBitRate = ctx->encode_config.rcParams.averageBitRate;
+    /* 1MB is large enough to hold most output frames.
+     * NVENC increases this automaticaly if it is not enough. */
+    allocOut.size = 1024 * 1024;
+
+    allocOut.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;
+
+    nv_status = p_nvenc->nvEncCreateBitstreamBuffer(ctx->nvencoder, &allocOut);
+    if (nv_status != NV_ENC_SUCCESS) {
+        int err = nvenc_print_error(avctx, nv_status, "CreateBitstreamBuffer failed");
+        if (avctx->pix_fmt != AV_PIX_FMT_CUDA)
+            p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[idx].input_surface);
+        av_frame_free(&ctx->surfaces[idx].in_ref);
+        return err;
     }
 
-    if (avctx->rc_max_rate > 0)
-        ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
+    ctx->surfaces[idx].output_surface = allocOut.bitstreamBuffer;
+    ctx->surfaces[idx].size = allocOut.size;
 
-    if (lossless) {
-        if (avctx->codec->id == AV_CODEC_ID_H264)
-            ctx->encode_config.encodeCodecConfig.h264Config.qpPrimeYZeroTransformBypassFlag = 1;
+    return 0;
+}
 
-        ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
-        ctx->encode_config.rcParams.constQP.qpInterB = 0;
-        ctx->encode_config.rcParams.constQP.qpInterP = 0;
-        ctx->encode_config.rcParams.constQP.qpIntra = 0;
+static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx)
+{
+    NvencContext *ctx = avctx->priv_data;
+    int i, res;
+    int num_mbs = ((avctx->width + 15) >> 4) * ((avctx->height + 15) >> 4);
+    ctx->nb_surfaces = FFMAX((num_mbs >= 8160) ? 32 : 48,
+                             ctx->nb_surfaces);
+    ctx->async_depth = FFMIN(ctx->async_depth, ctx->nb_surfaces - 1);
 
-        avctx->qmin = -1;
-        avctx->qmax = -1;
-    } else if (ctx->cbr) {
-        if (!ctx->twopass) {
-            ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CBR;
-        } else {
-            ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_2_PASS_QUALITY;
 
-            if (avctx->codec->id == AV_CODEC_ID_H264) {
-                ctx->encode_config.encodeCodecConfig.h264Config.adaptiveTransformMode = NV_ENC_H264_ADAPTIVE_TRANSFORM_ENABLE;
-                ctx->encode_config.encodeCodecConfig.h264Config.fmoMode = NV_ENC_H264_FMO_DISABLE;
+    ctx->surfaces = av_mallocz_array(ctx->nb_surfaces, sizeof(*ctx->surfaces));
+    if (!ctx->surfaces)
+        return AVERROR(ENOMEM);
+
+    ctx->timestamp_list = av_fifo_alloc(ctx->nb_surfaces * sizeof(int64_t));
+    if (!ctx->timestamp_list)
+        return AVERROR(ENOMEM);
+    ctx->output_surface_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(NvencSurface*));
+    if (!ctx->output_surface_queue)
+        return AVERROR(ENOMEM);
+    ctx->output_surface_ready_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(NvencSurface*));
+    if (!ctx->output_surface_ready_queue)
+        return AVERROR(ENOMEM);
+
+    for (i = 0; i < ctx->nb_surfaces; i++) {
+        if ((res = nvenc_alloc_surface(avctx, i)) < 0)
+            return res;
+    }
+
+    return 0;
+}
+
+static av_cold int nvenc_setup_extradata(AVCodecContext *avctx)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
+
+    NVENCSTATUS nv_status;
+    uint32_t outSize = 0;
+    char tmpHeader[256];
+    NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 };
+    payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER;
+
+    payload.spsppsBuffer = tmpHeader;
+    payload.inBufferSize = sizeof(tmpHeader);
+    payload.outSPSPPSPayloadSize = &outSize;
+
+    nv_status = p_nvenc->nvEncGetSequenceParams(ctx->nvencoder, &payload);
+    if (nv_status != NV_ENC_SUCCESS) {
+        return nvenc_print_error(avctx, nv_status, "GetSequenceParams failed");
+    }
+
+    avctx->extradata_size = outSize;
+    avctx->extradata = av_mallocz(outSize + AV_INPUT_BUFFER_PADDING_SIZE);
+
+    if (!avctx->extradata) {
+        return AVERROR(ENOMEM);
+    }
+
+    memcpy(avctx->extradata, tmpHeader, outSize);
+
+    return 0;
+}
+
+av_cold int ff_nvenc_encode_close(AVCodecContext *avctx)
+{
+    NvencContext *ctx               = avctx->priv_data;
+    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
+    int i;
+
+    /* the encoder has to be flushed before it can be closed */
+    if (ctx->nvencoder) {
+        NV_ENC_PIC_PARAMS params        = { .version        = NV_ENC_PIC_PARAMS_VER,
+                                            .encodePicFlags = NV_ENC_PIC_FLAG_EOS };
+
+        p_nvenc->nvEncEncodePicture(ctx->nvencoder, &params);
+    }
+
+    av_fifo_freep(&ctx->timestamp_list);
+    av_fifo_freep(&ctx->output_surface_ready_queue);
+    av_fifo_freep(&ctx->output_surface_queue);
+
+    if (ctx->surfaces && avctx->pix_fmt == AV_PIX_FMT_CUDA) {
+        for (i = 0; i < ctx->nb_surfaces; ++i) {
+            if (ctx->surfaces[i].input_surface) {
+                 p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, ctx->surfaces[i].in_map.mappedResource);
             }
         }
-    } else if (avctx->global_quality > 0) {
-        ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
-        ctx->encode_config.rcParams.constQP.qpInterB = avctx->global_quality;
-        ctx->encode_config.rcParams.constQP.qpInterP = avctx->global_quality;
-        ctx->encode_config.rcParams.constQP.qpIntra = avctx->global_quality;
-
-        avctx->qmin = -1;
-        avctx->qmax = -1;
+        for (i = 0; i < ctx->nb_registered_frames; i++) {
+            if (ctx->registered_frames[i].regptr)
+                p_nvenc->nvEncUnregisterResource(ctx->nvencoder, ctx->registered_frames[i].regptr);
+        }
+        ctx->nb_registered_frames = 0;
+    }
+
+    if (ctx->surfaces) {
+        for (i = 0; i < ctx->nb_surfaces; ++i) {
+            if (avctx->pix_fmt != AV_PIX_FMT_CUDA)
+                p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->surfaces[i].input_surface);
+            av_frame_free(&ctx->surfaces[i].in_ref);
+            p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->surfaces[i].output_surface);
+        }
+    }
+    av_freep(&ctx->surfaces);
+    ctx->nb_surfaces = 0;
+
+    if (ctx->nvencoder)
+        p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
+    ctx->nvencoder = NULL;
+
+    if (ctx->cu_context_internal)
+        dl_fn->cu_ctx_destroy(ctx->cu_context_internal);
+    ctx->cu_context = ctx->cu_context_internal = NULL;
+
+    if (dl_fn->nvenc)
+        dlclose(dl_fn->nvenc);
+    dl_fn->nvenc = NULL;
+
+    dl_fn->nvenc_device_count = 0;
+
+#if !CONFIG_CUDA
+    if (dl_fn->cuda)
+        dlclose(dl_fn->cuda);
+    dl_fn->cuda = NULL;
+#endif
+
+    dl_fn->cu_init = NULL;
+    dl_fn->cu_device_get_count = NULL;
+    dl_fn->cu_device_get = NULL;
+    dl_fn->cu_device_get_name = NULL;
+    dl_fn->cu_device_compute_capability = NULL;
+    dl_fn->cu_ctx_create = NULL;
+    dl_fn->cu_ctx_pop_current = NULL;
+    dl_fn->cu_ctx_destroy = NULL;
+
+    av_log(avctx, AV_LOG_VERBOSE, "Nvenc unloaded\n");
+
+    return 0;
+}
+
+av_cold int ff_nvenc_encode_init(AVCodecContext *avctx)
+{
+    NvencContext *ctx = avctx->priv_data;
+    int ret;
+
+    if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
+        AVHWFramesContext *frames_ctx;
+        if (!avctx->hw_frames_ctx) {
+            av_log(avctx, AV_LOG_ERROR,
+                   "hw_frames_ctx must be set when using GPU frames as input\n");
+            return AVERROR(EINVAL);
+        }
+        frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
+        ctx->data_pix_fmt = frames_ctx->sw_format;
     } else {
-        if (avctx->qmin >= 0 && avctx->qmax >= 0) {
-            ctx->encode_config.rcParams.enableMinQP = 1;
-            ctx->encode_config.rcParams.enableMaxQP = 1;
-
-            ctx->encode_config.rcParams.minQP.qpInterB = avctx->qmin;
-            ctx->encode_config.rcParams.minQP.qpInterP = avctx->qmin;
-            ctx->encode_config.rcParams.minQP.qpIntra = avctx->qmin;
-
-            ctx->encode_config.rcParams.maxQP.qpInterB = avctx->qmax;
-            ctx->encode_config.rcParams.maxQP.qpInterP = avctx->qmax;
-            ctx->encode_config.rcParams.maxQP.qpIntra = avctx->qmax;
+        ctx->data_pix_fmt = avctx->pix_fmt;
+    }
 
-            qp_inter_p = (avctx->qmax + 3 * avctx->qmin) / 4; // biased towards Qmin
+    if ((ret = nvenc_load_libraries(avctx)) < 0)
+        return ret;
 
-            if (ctx->twopass) {
-                ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_2_PASS_VBR;
-                if (avctx->codec->id == AV_CODEC_ID_H264) {
-                    ctx->encode_config.encodeCodecConfig.h264Config.adaptiveTransformMode = NV_ENC_H264_ADAPTIVE_TRANSFORM_ENABLE;
-                    ctx->encode_config.encodeCodecConfig.h264Config.fmoMode = NV_ENC_H264_FMO_DISABLE;
-                }
-            } else {
-                ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR_MINQP;
-            }
-        } else {
-            qp_inter_p = 26; // default to 26
+    if ((ret = nvenc_setup_device(avctx)) < 0)
+        return ret;
 
-            if (ctx->twopass) {
-                ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_2_PASS_VBR;
-            } else {
-                ctx->encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_VBR;
-            }
-        }
+    if ((ret = nvenc_setup_encoder(avctx)) < 0)
+        return ret;
 
-        ctx->encode_config.rcParams.enableInitialRCQP = 1;
-        ctx->encode_config.rcParams.initialRCQP.qpInterP  = qp_inter_p;
+    if ((ret = nvenc_setup_surfaces(avctx)) < 0)
+        return ret;
 
-        if(avctx->i_quant_factor != 0.0 && avctx->b_quant_factor != 0.0) {
-            ctx->encode_config.rcParams.initialRCQP.qpIntra = av_clip(
-                qp_inter_p * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51);
-            ctx->encode_config.rcParams.initialRCQP.qpInterB = av_clip(
-                qp_inter_p * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51);
-        } else {
-            ctx->encode_config.rcParams.initialRCQP.qpIntra = qp_inter_p;
-            ctx->encode_config.rcParams.initialRCQP.qpInterB = qp_inter_p;
-        }
+    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+        if ((ret = nvenc_setup_extradata(avctx)) < 0)
+            return ret;
     }
 
-    if (avctx->rc_buffer_size > 0) {
-        ctx->encode_config.rcParams.vbvBufferSize = avctx->rc_buffer_size;
-    } else if (ctx->encode_config.rcParams.averageBitRate > 0) {
-        ctx->encode_config.rcParams.vbvBufferSize = 2 * ctx->encode_config.rcParams.averageBitRate;
-    }
+    return 0;
+}
 
-    if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
-        ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
-    } else {
-        ctx->encode_config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;
-    }
+static NvencSurface *get_free_frame(NvencContext *ctx)
+{
+    int i;
 
-    switch (avctx->codec->id) {
-    case AV_CODEC_ID_H264:
-        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourDescriptionPresentFlag = 1;
-        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoSignalTypePresentFlag = 1;
-
-        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourMatrix = avctx->colorspace;
-        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.colourPrimaries = avctx->color_primaries;
-        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.transferCharacteristics = avctx->color_trc;
-
-        ctx->encode_config.encodeCodecConfig.h264Config.h264VUIParameters.videoFullRangeFlag = avctx->color_range == AVCOL_RANGE_JPEG;
-
-        ctx->encode_config.encodeCodecConfig.h264Config.sliceMode = 3;
-        ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData = 1;
-
-        ctx->encode_config.encodeCodecConfig.h264Config.disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
-        ctx->encode_config.encodeCodecConfig.h264Config.repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
-
-        if (!ctx->profile) {
-            switch (avctx->profile) {
-            case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
-                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
-                break;
-            case FF_PROFILE_H264_BASELINE:
-                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
-                break;
-            case FF_PROFILE_H264_MAIN:
-                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
-                break;
-            case FF_PROFILE_H264_HIGH:
-            case FF_PROFILE_UNKNOWN:
-                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
-                break;
-            default:
-                av_log(avctx, AV_LOG_WARNING, "Unsupported profile requested, falling back to high\n");
-                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
-                break;
-            }
-        } else {
-            if (!strcmp(ctx->profile, "high")) {
-                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
-                avctx->profile = FF_PROFILE_H264_HIGH;
-            } else if (!strcmp(ctx->profile, "main")) {
-                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_MAIN_GUID;
-                avctx->profile = FF_PROFILE_H264_MAIN;
-            } else if (!strcmp(ctx->profile, "baseline")) {
-                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_BASELINE_GUID;
-                avctx->profile = FF_PROFILE_H264_BASELINE;
-            } else if (!strcmp(ctx->profile, "high444p")) {
-                ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
-                avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;
-            } else {
-                av_log(avctx, AV_LOG_FATAL, "Profile \"%s\" is unknown! Supported profiles: high, main, baseline\n", ctx->profile);
-                res = AVERROR(EINVAL);
-                goto error;
-            }
+    for (i = 0; i < ctx->nb_surfaces; ++i) {
+        if (!ctx->surfaces[i].lockCount) {
+            ctx->surfaces[i].lockCount = 1;
+            return &ctx->surfaces[i];
         }
+    }
 
-        // force setting profile as high444p if input is AV_PIX_FMT_YUV444P
-        if (avctx->pix_fmt == AV_PIX_FMT_YUV444P) {
-            ctx->encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
-            avctx->profile = FF_PROFILE_H264_HIGH_444_PREDICTIVE;
-        }
+    return NULL;
+}
 
-        ctx->encode_config.encodeCodecConfig.h264Config.chromaFormatIDC = avctx->profile == FF_PROFILE_H264_HIGH_444_PREDICTIVE ? 3 : 1;
+static int nvenc_copy_frame(AVCodecContext *avctx, NvencSurface *inSurf,
+            NV_ENC_LOCK_INPUT_BUFFER *lockBufferParams, const AVFrame *frame)
+{
+    uint8_t *buf = lockBufferParams->bufferDataPtr;
+    int off = inSurf->height * lockBufferParams->pitch;
 
-        if (ctx->level) {
-            res = input_string_to_uint32(avctx, nvenc_h264_level_pairs, ctx->level, &ctx->encode_config.encodeCodecConfig.h264Config.level);
+    if (frame->format == AV_PIX_FMT_YUV420P) {
+        av_image_copy_plane(buf, lockBufferParams->pitch,
+            frame->data[0], frame->linesize[0],
+            avctx->width, avctx->height);
 
-            if (res) {
-                av_log(avctx, AV_LOG_FATAL, "Level \"%s\" is unknown! Supported levels: auto, 1, 1b, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1, 3.2, 4, 4.1, 4.2, 5, 5.1\n", ctx->level);
-                goto error;
-            }
-        } else {
-            ctx->encode_config.encodeCodecConfig.h264Config.level = NV_ENC_LEVEL_AUTOSELECT;
-        }
+        buf += off;
 
-        break;
-    case AV_CODEC_ID_H265:
-        ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode = 3;
-        ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData = 1;
+        av_image_copy_plane(buf, lockBufferParams->pitch >> 1,
+            frame->data[2], frame->linesize[2],
+            avctx->width >> 1, avctx->height >> 1);
 
-        ctx->encode_config.encodeCodecConfig.hevcConfig.disableSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0;
-        ctx->encode_config.encodeCodecConfig.hevcConfig.repeatSPSPPS = (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ? 0 : 1;
+        buf += off >> 2;
 
-        /* No other profile is supported in the current SDK version 5 */
-        ctx->encode_config.profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;
-        avctx->profile = FF_PROFILE_HEVC_MAIN;
+        av_image_copy_plane(buf, lockBufferParams->pitch >> 1,
+            frame->data[1], frame->linesize[1],
+            avctx->width >> 1, avctx->height >> 1);
+    } else if (frame->format == AV_PIX_FMT_NV12) {
+        av_image_copy_plane(buf, lockBufferParams->pitch,
+            frame->data[0], frame->linesize[0],
+            avctx->width, avctx->height);
 
-        if (ctx->level) {
-            res = input_string_to_uint32(avctx, nvenc_hevc_level_pairs, ctx->level, &ctx->encode_config.encodeCodecConfig.hevcConfig.level);
+        buf += off;
 
-            if (res) {
-                av_log(avctx, AV_LOG_FATAL, "Level \"%s\" is unknown! Supported levels: auto, 1, 2, 2.1, 3, 3.1, 4, 4.1, 5, 5.1, 5.2, 6, 6.1, 6.2\n", ctx->level);
-                goto error;
-            }
-        } else {
-            ctx->encode_config.encodeCodecConfig.hevcConfig.level = NV_ENC_LEVEL_AUTOSELECT;
-        }
+        av_image_copy_plane(buf, lockBufferParams->pitch,
+            frame->data[1], frame->linesize[1],
+            avctx->width, avctx->height >> 1);
+    } else if (frame->format == AV_PIX_FMT_YUV444P) {
+        av_image_copy_plane(buf, lockBufferParams->pitch,
+            frame->data[0], frame->linesize[0],
+            avctx->width, avctx->height);
 
-        if (ctx->tier) {
-            if (!strcmp(ctx->tier, "main")) {
-                ctx->encode_config.encodeCodecConfig.hevcConfig.tier = NV_ENC_TIER_HEVC_MAIN;
-            } else if (!strcmp(ctx->tier, "high")) {
-                ctx->encode_config.encodeCodecConfig.hevcConfig.tier = NV_ENC_TIER_HEVC_HIGH;
-            } else {
-                av_log(avctx, AV_LOG_FATAL, "Tier \"%s\" is unknown! Supported tiers: main, high\n", ctx->tier);
-                res = AVERROR(EINVAL);
-                goto error;
-            }
-        }
+        buf += off;
 
-        break;
-    /* Earlier switch/case will return if unknown codec is passed. */
-    }
+        av_image_copy_plane(buf, lockBufferParams->pitch,
+            frame->data[1], frame->linesize[1],
+            avctx->width, avctx->height);
 
-    nv_status = p_nvenc->nvEncInitializeEncoder(ctx->nvencoder, &ctx->init_encode_params);
-    if (nv_status != NV_ENC_SUCCESS) {
-        av_log(avctx, AV_LOG_FATAL, "InitializeEncoder failed: 0x%x\n", (int)nv_status);
-        res = AVERROR_EXTERNAL;
-        goto error;
+        buf += off;
+
+        av_image_copy_plane(buf, lockBufferParams->pitch,
+            frame->data[2], frame->linesize[2],
+            avctx->width, avctx->height);
+    } else {
+        av_log(avctx, AV_LOG_FATAL, "Invalid pixel format!\n");
+        return AVERROR(EINVAL);
     }
 
-    ctx->input_surfaces = av_malloc(ctx->max_surface_count * sizeof(*ctx->input_surfaces));
+    return 0;
+}
 
-    if (!ctx->input_surfaces) {
-        res = AVERROR(ENOMEM);
-        goto error;
-    }
+static int nvenc_find_free_reg_resource(AVCodecContext *avctx)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
 
-    ctx->output_surfaces = av_malloc(ctx->max_surface_count * sizeof(*ctx->output_surfaces));
+    int i;
 
-    if (!ctx->output_surfaces) {
-        res = AVERROR(ENOMEM);
-        goto error;
+    if (ctx->nb_registered_frames == FF_ARRAY_ELEMS(ctx->registered_frames)) {
+        for (i = 0; i < ctx->nb_registered_frames; i++) {
+            if (!ctx->registered_frames[i].mapped) {
+                if (ctx->registered_frames[i].regptr) {
+                    p_nvenc->nvEncUnregisterResource(ctx->nvencoder,
+                                                ctx->registered_frames[i].regptr);
+                    ctx->registered_frames[i].regptr = NULL;
+                }
+                return i;
+            }
+        }
+    } else {
+        return ctx->nb_registered_frames++;
     }
 
-    for (surfaceCount = 0; surfaceCount < ctx->max_surface_count; ++surfaceCount) {
-        NV_ENC_CREATE_INPUT_BUFFER allocSurf = { 0 };
-        NV_ENC_CREATE_BITSTREAM_BUFFER allocOut = { 0 };
-        allocSurf.version = NV_ENC_CREATE_INPUT_BUFFER_VER;
-        allocOut.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;
-
-        allocSurf.width = (avctx->width + 31) & ~31;
-        allocSurf.height = (avctx->height + 31) & ~31;
+    av_log(avctx, AV_LOG_ERROR, "Too many registered CUDA frames\n");
+    return AVERROR(ENOMEM);
+}
 
-        allocSurf.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;
+static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
 
-        switch (avctx->pix_fmt) {
-        case AV_PIX_FMT_YUV420P:
-            allocSurf.bufferFmt = NV_ENC_BUFFER_FORMAT_YV12_PL;
-            break;
+    AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
+    NV_ENC_REGISTER_RESOURCE reg;
+    int i, idx, ret;
 
-        case AV_PIX_FMT_NV12:
-            allocSurf.bufferFmt = NV_ENC_BUFFER_FORMAT_NV12_PL;
-            break;
+    for (i = 0; i < ctx->nb_registered_frames; i++) {
+        if (ctx->registered_frames[i].ptr == (CUdeviceptr)frame->data[0])
+            return i;
+    }
 
-        case AV_PIX_FMT_YUV444P:
-            allocSurf.bufferFmt = NV_ENC_BUFFER_FORMAT_YUV444_PL;
-            break;
+    idx = nvenc_find_free_reg_resource(avctx);
+    if (idx < 0)
+        return idx;
+
+    reg.version            = NV_ENC_REGISTER_RESOURCE_VER;
+    reg.resourceType       = NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR;
+    reg.width              = frames_ctx->width;
+    reg.height             = frames_ctx->height;
+    reg.bufferFormat       = ctx->surfaces[0].format;
+    reg.pitch              = frame->linesize[0];
+    reg.resourceToRegister = frame->data[0];
+
+    ret = p_nvenc->nvEncRegisterResource(ctx->nvencoder, &reg);
+    if (ret != NV_ENC_SUCCESS) {
+        nvenc_print_error(avctx, ret, "Error registering an input resource");
+        return AVERROR_UNKNOWN;
+    }
 
-        default:
-            av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format\n");
-            res = AVERROR(EINVAL);
-            goto error;
-        }
+    ctx->registered_frames[idx].ptr    = (CUdeviceptr)frame->data[0];
+    ctx->registered_frames[idx].regptr = reg.registeredResource;
+    return idx;
+}
 
-        nv_status = p_nvenc->nvEncCreateInputBuffer(ctx->nvencoder, &allocSurf);
-        if (nv_status != NV_ENC_SUCCESS) {
-            av_log(avctx, AV_LOG_FATAL, "CreateInputBuffer failed\n");
-            res = AVERROR_EXTERNAL;
-            goto error;
-        }
+static int nvenc_upload_frame(AVCodecContext *avctx, const AVFrame *frame,
+                                      NvencSurface *nvenc_frame)
+{
+    NvencContext *ctx = avctx->priv_data;
+    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
+    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
 
-        ctx->input_surfaces[surfaceCount].lockCount = 0;
-        ctx->input_surfaces[surfaceCount].input_surface = allocSurf.inputBuffer;
-        ctx->input_surfaces[surfaceCount].format = allocSurf.bufferFmt;
-        ctx->input_surfaces[surfaceCount].width = allocSurf.width;
-        ctx->input_surfaces[surfaceCount].height = allocSurf.height;
+    int res;
+    NVENCSTATUS nv_status;
 
-        /* 1MB is large enough to hold most output frames. NVENC increases this automaticaly if it's not enough. */
-        allocOut.size = 1024 * 1024;
+    if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
+        int reg_idx = nvenc_register_frame(avctx, frame);
+        if (reg_idx < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Could not register an input CUDA frame\n");
+            return reg_idx;
+        }
 
-        allocOut.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_CACHED;
+        res = av_frame_ref(nvenc_frame->in_ref, frame);
+        if (res < 0)
+            return res;
 
-        nv_status = p_nvenc->nvEncCreateBitstreamBuffer(ctx->nvencoder, &allocOut);
+        nvenc_frame->in_map.version = NV_ENC_MAP_INPUT_RESOURCE_VER;
+        nvenc_frame->in_map.registeredResource = ctx->registered_frames[reg_idx].regptr;
+        nv_status = p_nvenc->nvEncMapInputResource(ctx->nvencoder, &nvenc_frame->in_map);
         if (nv_status != NV_ENC_SUCCESS) {
-            av_log(avctx, AV_LOG_FATAL, "CreateBitstreamBuffer failed\n");
-            ctx->output_surfaces[surfaceCount++].output_surface = NULL;
-            res = AVERROR_EXTERNAL;
-            goto error;
+            av_frame_unref(nvenc_frame->in_ref);
+            return nvenc_print_error(avctx, nv_status, "Error mapping an input resource");
         }
 
-        ctx->output_surfaces[surfaceCount].output_surface = allocOut.bitstreamBuffer;
-        ctx->output_surfaces[surfaceCount].size = allocOut.size;
-        ctx->output_surfaces[surfaceCount].busy = 0;
-    }
-
-    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
-        uint32_t outSize = 0;
-        char tmpHeader[256];
-        NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = { 0 };
-        payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER;
+        ctx->registered_frames[reg_idx].mapped = 1;
+        nvenc_frame->reg_idx                   = reg_idx;
+        nvenc_frame->input_surface             = nvenc_frame->in_map.mappedResource;
+        return 0;
+    } else {
+        NV_ENC_LOCK_INPUT_BUFFER lockBufferParams = { 0 };
 
-        payload.spsppsBuffer = tmpHeader;
-        payload.inBufferSize = sizeof(tmpHeader);
-        payload.outSPSPPSPayloadSize = &outSize;
+        lockBufferParams.version = NV_ENC_LOCK_INPUT_BUFFER_VER;
+        lockBufferParams.inputBuffer = nvenc_frame->input_surface;
 
-        nv_status = p_nvenc->nvEncGetSequenceParams(ctx->nvencoder, &payload);
+        nv_status = p_nvenc->nvEncLockInputBuffer(ctx->nvencoder, &lockBufferParams);
         if (nv_status != NV_ENC_SUCCESS) {
-            av_log(avctx, AV_LOG_FATAL, "GetSequenceParams failed\n");
-            goto error;
+            return nvenc_print_error(avctx, nv_status, "Failed locking nvenc input buffer");
         }
 
-        avctx->extradata_size = outSize;
-        avctx->extradata = av_mallocz(outSize + AV_INPUT_BUFFER_PADDING_SIZE);
+        res = nvenc_copy_frame(avctx, nvenc_frame, &lockBufferParams, frame);
 
-        if (!avctx->extradata) {
-            res = AVERROR(ENOMEM);
-            goto error;
+        nv_status = p_nvenc->nvEncUnlockInputBuffer(ctx->nvencoder, nvenc_frame->input_surface);
+        if (nv_status != NV_ENC_SUCCESS) {
+            return nvenc_print_error(avctx, nv_status, "Failed unlocking input buffer!");
         }
 
-        memcpy(avctx->extradata, tmpHeader, outSize);
+        return res;
     }
+}
 
-    if (ctx->encode_config.frameIntervalP > 1)
-        avctx->has_b_frames = 2;
-
-    if (ctx->encode_config.rcParams.averageBitRate > 0)
-        avctx->bit_rate = ctx->encode_config.rcParams.averageBitRate;
-
-    cpb_props = ff_add_cpb_side_data(avctx);
-    if (!cpb_props)
-        return AVERROR(ENOMEM);
-    cpb_props->max_bitrate = ctx->encode_config.rcParams.maxBitRate;
-    cpb_props->avg_bitrate = avctx->bit_rate;
-    cpb_props->buffer_size = ctx->encode_config.rcParams.vbvBufferSize;
-
-    return 0;
-
-error:
+static void nvenc_codec_specific_pic_params(AVCodecContext *avctx,
+                                            NV_ENC_PIC_PARAMS *params)
+{
+    NvencContext *ctx = avctx->priv_data;
 
-    for (i = 0; i < surfaceCount; ++i) {
-        p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->input_surfaces[i].input_surface);
-        if (ctx->output_surfaces[i].output_surface)
-            p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->output_surfaces[i].output_surface);
+    switch (avctx->codec->id) {
+    case AV_CODEC_ID_H264:
+        params->codecPicParams.h264PicParams.sliceMode =
+            ctx->encode_config.encodeCodecConfig.h264Config.sliceMode;
+        params->codecPicParams.h264PicParams.sliceModeData =
+            ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData;
+      break;
+    case AV_CODEC_ID_HEVC:
+        params->codecPicParams.hevcPicParams.sliceMode =
+            ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode;
+        params->codecPicParams.hevcPicParams.sliceModeData =
+            ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData;
+        break;
     }
+}
 
-    if (ctx->nvencoder)
-        p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
-
-    if (ctx->cu_context)
-        dl_fn->cu_ctx_destroy(ctx->cu_context);
-
-    nvenc_unload_nvenc(avctx);
+static inline void timestamp_queue_enqueue(AVFifoBuffer* queue, int64_t timestamp)
+{
+    av_fifo_generic_write(queue, &timestamp, sizeof(timestamp), NULL);
+}
 
-    ctx->nvencoder = NULL;
-    ctx->cu_context = NULL;
+static inline int64_t timestamp_queue_dequeue(AVFifoBuffer* queue)
+{
+    int64_t timestamp = AV_NOPTS_VALUE;
+    if (av_fifo_size(queue) > 0)
+        av_fifo_generic_read(queue, &timestamp, sizeof(timestamp), NULL);
 
-    return res;
+    return timestamp;
 }
 
-static av_cold int nvenc_encode_close(AVCodecContext *avctx)
+static int nvenc_set_timestamp(AVCodecContext *avctx,
+                               NV_ENC_LOCK_BITSTREAM *params,
+                               AVPacket *pkt)
 {
     NvencContext *ctx = avctx->priv_data;
-    NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
-    NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
-    int i;
 
-    av_freep(&ctx->timestamp_list.data);
-    av_freep(&ctx->output_surface_ready_queue.data);
-    av_freep(&ctx->output_surface_queue.data);
+    pkt->pts = params->outputTimeStamp;
 
-    for (i = 0; i < ctx->max_surface_count; ++i) {
-        p_nvenc->nvEncDestroyInputBuffer(ctx->nvencoder, ctx->input_surfaces[i].input_surface);
-        p_nvenc->nvEncDestroyBitstreamBuffer(ctx->nvencoder, ctx->output_surfaces[i].output_surface);
-    }
-    ctx->max_surface_count = 0;
+    /* generate the first dts by linearly extrapolating the
+     * first two pts values to the past */
+    if (avctx->max_b_frames > 0 && !ctx->first_packet_output &&
+        ctx->initial_pts[1] != AV_NOPTS_VALUE) {
+        int64_t ts0 = ctx->initial_pts[0], ts1 = ctx->initial_pts[1];
+        int64_t delta;
 
-    p_nvenc->nvEncDestroyEncoder(ctx->nvencoder);
-    ctx->nvencoder = NULL;
+        if ((ts0 < 0 && ts1 > INT64_MAX + ts0) ||
+            (ts0 > 0 && ts1 < INT64_MIN + ts0))
+            return AVERROR(ERANGE);
+        delta = ts1 - ts0;
 
-    dl_fn->cu_ctx_destroy(ctx->cu_context);
-    ctx->cu_context = NULL;
+        if ((delta < 0 && ts0 > INT64_MAX + delta) ||
+            (delta > 0 && ts0 < INT64_MIN + delta))
+            return AVERROR(ERANGE);
+        pkt->dts = ts0 - delta;
+
+        ctx->first_packet_output = 1;
+        return 0;
+    }
 
-    nvenc_unload_nvenc(avctx);
+    pkt->dts = timestamp_queue_dequeue(ctx->timestamp_list);
 
     return 0;
 }
 
-static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencOutputSurface *tmpoutsurf)
+static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSurface *tmpoutsurf)
 {
     NvencContext *ctx = avctx->priv_data;
     NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
@@ -1167,6 +1463,8 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencOut
     NVENCSTATUS nv_status;
     int res = 0;
 
+    enum AVPictureType pict_type;
+
     switch (avctx->codec->id) {
     case AV_CODEC_ID_H264:
       slice_mode_data = ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData;
@@ -1182,7 +1480,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencOut
     slice_offsets = av_mallocz(slice_mode_data * sizeof(*slice_offsets));
 
     if (!slice_offsets)
-        return AVERROR(ENOMEM);
+        goto error;
 
     lock_params.version = NV_ENC_LOCK_BITSTREAM_VER;
 
@@ -1192,8 +1490,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencOut
 
     nv_status = p_nvenc->nvEncLockBitstream(ctx->nvencoder, &lock_params);
     if (nv_status != NV_ENC_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Failed locking bitstream buffer\n");
-        res = AVERROR_EXTERNAL;
+        res = nvenc_print_error(avctx, nv_status, "Failed locking bitstream buffer");
         goto error;
     }
 
@@ -1206,67 +1503,89 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencOut
 
     nv_status = p_nvenc->nvEncUnlockBitstream(ctx->nvencoder, tmpoutsurf->output_surface);
     if (nv_status != NV_ENC_SUCCESS)
-        av_log(avctx, AV_LOG_ERROR, "Failed unlocking bitstream buffer, expect the gates of mordor to open\n");
+        nvenc_print_error(avctx, nv_status, "Failed unlocking bitstream buffer, expect the gates of mordor to open");
+
+
+    if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
+        p_nvenc->nvEncUnmapInputResource(ctx->nvencoder, tmpoutsurf->in_map.mappedResource);
+        av_frame_unref(tmpoutsurf->in_ref);
+        ctx->registered_frames[tmpoutsurf->reg_idx].mapped = 0;
+
+        tmpoutsurf->input_surface = NULL;
+    }
 
     switch (lock_params.pictureType) {
     case NV_ENC_PIC_TYPE_IDR:
         pkt->flags |= AV_PKT_FLAG_KEY;
-#if FF_API_CODED_FRAME
-FF_DISABLE_DEPRECATION_WARNINGS
     case NV_ENC_PIC_TYPE_I:
-        avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
+        pict_type = AV_PICTURE_TYPE_I;
         break;
     case NV_ENC_PIC_TYPE_P:
-        avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P;
+        pict_type = AV_PICTURE_TYPE_P;
         break;
     case NV_ENC_PIC_TYPE_B:
-        avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B;
+        pict_type = AV_PICTURE_TYPE_B;
         break;
     case NV_ENC_PIC_TYPE_BI:
-        avctx->coded_frame->pict_type = AV_PICTURE_TYPE_BI;
+        pict_type = AV_PICTURE_TYPE_BI;
         break;
     default:
         av_log(avctx, AV_LOG_ERROR, "Unknown picture type encountered, expect the output to be broken.\n");
         av_log(avctx, AV_LOG_ERROR, "Please report this error and include as much information on how to reproduce it as possible.\n");
         res = AVERROR_EXTERNAL;
         goto error;
-FF_ENABLE_DEPRECATION_WARNINGS
-#endif
     }
 
-    pkt->pts = lock_params.outputTimeStamp;
-    pkt->dts = timestamp_queue_dequeue(&ctx->timestamp_list);
-
-    /* when there're b frame(s), set dts offset */
-    if (ctx->encode_config.frameIntervalP >= 2)
-        pkt->dts -= 1;
-
-    if (pkt->dts > pkt->pts)
-        pkt->dts = pkt->pts;
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+    avctx->coded_frame->pict_type = pict_type;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
-    if (ctx->last_dts != AV_NOPTS_VALUE && pkt->dts <= ctx->last_dts)
-        pkt->dts = ctx->last_dts + 1;
+    ff_side_data_set_encoder_stats(pkt,
+        (lock_params.frameAvgQP - 1) * FF_QP2LAMBDA, NULL, 0, pict_type);
 
-    ctx->last_dts = pkt->dts;
+    res = nvenc_set_timestamp(avctx, &lock_params, pkt);
+    if (res < 0)
+        goto error2;
 
     av_free(slice_offsets);
 
     return 0;
 
 error:
+    timestamp_queue_dequeue(ctx->timestamp_list);
 
+error2:
     av_free(slice_offsets);
-    timestamp_queue_dequeue(&ctx->timestamp_list);
 
     return res;
 }
 
-static int nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
-    const AVFrame *frame, int *got_packet)
+static int output_ready(AVCodecContext *avctx, int flush)
+{
+    NvencContext *ctx = avctx->priv_data;
+    int nb_ready, nb_pending;
+
+    /* when B-frames are enabled, we wait for two initial timestamps to
+     * calculate the first dts */
+    if (!flush && avctx->max_b_frames > 0 &&
+        (ctx->initial_pts[0] == AV_NOPTS_VALUE || ctx->initial_pts[1] == AV_NOPTS_VALUE))
+        return 0;
+
+    nb_ready   = av_fifo_size(ctx->output_surface_ready_queue)   / sizeof(NvencSurface*);
+    nb_pending = av_fifo_size(ctx->output_surface_queue)         / sizeof(NvencSurface*);
+    if (flush)
+        return nb_ready > 0;
+    return (nb_ready > 0) && (nb_ready + nb_pending >= ctx->async_depth);
+}
+
+int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+                          const AVFrame *frame, int *got_packet)
 {
     NVENCSTATUS nv_status;
-    NvencOutputSurface *tmpoutsurf;
-    int res, i = 0;
+    NvencSurface *tmpoutsurf, *inSurf;
+    int res;
 
     NvencContext *ctx = avctx->priv_data;
     NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
@@ -1276,188 +1595,74 @@ static int nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     pic_params.version = NV_ENC_PIC_PARAMS_VER;
 
     if (frame) {
-        NV_ENC_LOCK_INPUT_BUFFER lockBufferParams = { 0 };
-        NvencInputSurface *inSurf = NULL;
-
-        for (i = 0; i < ctx->max_surface_count; ++i) {
-            if (!ctx->input_surfaces[i].lockCount) {
-                inSurf = &ctx->input_surfaces[i];
-                break;
-            }
-        }
-
-        av_assert0(inSurf);
-
-        inSurf->lockCount = 1;
-
-        lockBufferParams.version = NV_ENC_LOCK_INPUT_BUFFER_VER;
-        lockBufferParams.inputBuffer = inSurf->input_surface;
-
-        nv_status = p_nvenc->nvEncLockInputBuffer(ctx->nvencoder, &lockBufferParams);
-        if (nv_status != NV_ENC_SUCCESS) {
-            av_log(avctx, AV_LOG_ERROR, "Failed locking nvenc input buffer\n");
-            return 0;
-        }
-
-        if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
-            uint8_t *buf = lockBufferParams.bufferDataPtr;
-
-            av_image_copy_plane(buf, lockBufferParams.pitch,
-                frame->data[0], frame->linesize[0],
-                avctx->width, avctx->height);
-
-            buf += inSurf->height * lockBufferParams.pitch;
-
-            av_image_copy_plane(buf, lockBufferParams.pitch >> 1,
-                frame->data[2], frame->linesize[2],
-                avctx->width >> 1, avctx->height >> 1);
-
-            buf += (inSurf->height * lockBufferParams.pitch) >> 2;
-
-            av_image_copy_plane(buf, lockBufferParams.pitch >> 1,
-                frame->data[1], frame->linesize[1],
-                avctx->width >> 1, avctx->height >> 1);
-        } else if (avctx->pix_fmt == AV_PIX_FMT_NV12) {
-            uint8_t *buf = lockBufferParams.bufferDataPtr;
-
-            av_image_copy_plane(buf, lockBufferParams.pitch,
-                frame->data[0], frame->linesize[0],
-                avctx->width, avctx->height);
-
-            buf += inSurf->height * lockBufferParams.pitch;
-
-            av_image_copy_plane(buf, lockBufferParams.pitch,
-                frame->data[1], frame->linesize[1],
-                avctx->width, avctx->height >> 1);
-        } else if (avctx->pix_fmt == AV_PIX_FMT_YUV444P) {
-            uint8_t *buf = lockBufferParams.bufferDataPtr;
-
-            av_image_copy_plane(buf, lockBufferParams.pitch,
-                frame->data[0], frame->linesize[0],
-                avctx->width, avctx->height);
-
-            buf += inSurf->height * lockBufferParams.pitch;
-
-            av_image_copy_plane(buf, lockBufferParams.pitch,
-                frame->data[1], frame->linesize[1],
-                avctx->width, avctx->height);
-
-            buf += inSurf->height * lockBufferParams.pitch;
-
-            av_image_copy_plane(buf, lockBufferParams.pitch,
-                frame->data[2], frame->linesize[2],
-                avctx->width, avctx->height);
-        } else {
-            av_log(avctx, AV_LOG_FATAL, "Invalid pixel format!\n");
-            return AVERROR(EINVAL);
-        }
-
-        nv_status = p_nvenc->nvEncUnlockInputBuffer(ctx->nvencoder, inSurf->input_surface);
-        if (nv_status != NV_ENC_SUCCESS) {
-            av_log(avctx, AV_LOG_FATAL, "Failed unlocking input buffer!\n");
-            return AVERROR_EXTERNAL;
+        inSurf = get_free_frame(ctx);
+        if (!inSurf) {
+            av_log(avctx, AV_LOG_ERROR, "No free surfaces\n");
+            return AVERROR_BUG;
         }
 
-        for (i = 0; i < ctx->max_surface_count; ++i)
-            if (!ctx->output_surfaces[i].busy)
-                break;
-
-        if (i == ctx->max_surface_count) {
+        res = nvenc_upload_frame(avctx, frame, inSurf);
+        if (res) {
             inSurf->lockCount = 0;
-            av_log(avctx, AV_LOG_FATAL, "No free output surface found!\n");
-            return AVERROR_EXTERNAL;
+            return res;
         }
 
-        ctx->output_surfaces[i].input_surface = inSurf;
-
         pic_params.inputBuffer = inSurf->input_surface;
         pic_params.bufferFmt = inSurf->format;
         pic_params.inputWidth = avctx->width;
         pic_params.inputHeight = avctx->height;
-        pic_params.outputBitstream = ctx->output_surfaces[i].output_surface;
-        pic_params.completionEvent = 0;
+        pic_params.outputBitstream = inSurf->output_surface;
 
         if (avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
-            if (frame->top_field_first) {
+            if (frame->top_field_first)
                 pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_TOP_BOTTOM;
-            } else {
+            else
                 pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FIELD_BOTTOM_TOP;
-            }
         } else {
             pic_params.pictureStruct = NV_ENC_PIC_STRUCT_FRAME;
         }
 
         pic_params.encodePicFlags = 0;
         pic_params.inputTimeStamp = frame->pts;
-        pic_params.inputDuration = 0;
-        switch (avctx->codec->id) {
-        case AV_CODEC_ID_H264:
-          pic_params.codecPicParams.h264PicParams.sliceMode = ctx->encode_config.encodeCodecConfig.h264Config.sliceMode;
-          pic_params.codecPicParams.h264PicParams.sliceModeData = ctx->encode_config.encodeCodecConfig.h264Config.sliceModeData;
-          break;
-        case AV_CODEC_ID_H265:
-          pic_params.codecPicParams.hevcPicParams.sliceMode = ctx->encode_config.encodeCodecConfig.hevcConfig.sliceMode;
-          pic_params.codecPicParams.hevcPicParams.sliceModeData = ctx->encode_config.encodeCodecConfig.hevcConfig.sliceModeData;
-          break;
-        default:
-          av_log(avctx, AV_LOG_ERROR, "Unknown codec name\n");
-          return AVERROR(EINVAL);
-        }
-
-        res = timestamp_queue_enqueue(&ctx->timestamp_list, frame->pts);
 
-        if (res)
-            return res;
+        nvenc_codec_specific_pic_params(avctx, &pic_params);
     } else {
         pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
     }
 
     nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params);
+    if (nv_status != NV_ENC_SUCCESS &&
+        nv_status != NV_ENC_ERR_NEED_MORE_INPUT)
+        return nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
 
-    if (frame && nv_status == NV_ENC_ERR_NEED_MORE_INPUT) {
-        res = out_surf_queue_enqueue(&ctx->output_surface_queue, &ctx->output_surfaces[i]);
-
-        if (res)
-            return res;
-
-        ctx->output_surfaces[i].busy = 1;
-    }
+    if (frame) {
+        av_fifo_generic_write(ctx->output_surface_queue, &inSurf, sizeof(inSurf), NULL);
+        timestamp_queue_enqueue(ctx->timestamp_list, frame->pts);
 
-    if (nv_status != NV_ENC_SUCCESS && nv_status != NV_ENC_ERR_NEED_MORE_INPUT) {
-        av_log(avctx, AV_LOG_ERROR, "EncodePicture failed!\n");
-        return AVERROR_EXTERNAL;
+        if (ctx->initial_pts[0] == AV_NOPTS_VALUE)
+            ctx->initial_pts[0] = frame->pts;
+        else if (ctx->initial_pts[1] == AV_NOPTS_VALUE)
+            ctx->initial_pts[1] = frame->pts;
     }
 
-    if (nv_status != NV_ENC_ERR_NEED_MORE_INPUT) {
-        while (ctx->output_surface_queue.count) {
-            tmpoutsurf = out_surf_queue_dequeue(&ctx->output_surface_queue);
-            res = out_surf_queue_enqueue(&ctx->output_surface_ready_queue, tmpoutsurf);
-
-            if (res)
-                return res;
-        }
-
-        if (frame) {
-            res = out_surf_queue_enqueue(&ctx->output_surface_ready_queue, &ctx->output_surfaces[i]);
-
-            if (res)
-                return res;
-
-            ctx->output_surfaces[i].busy = 1;
+    /* all the pending buffers are now ready for output */
+    if (nv_status == NV_ENC_SUCCESS) {
+        while (av_fifo_size(ctx->output_surface_queue) > 0) {
+            av_fifo_generic_read(ctx->output_surface_queue, &tmpoutsurf, sizeof(tmpoutsurf), NULL);
+            av_fifo_generic_write(ctx->output_surface_ready_queue, &tmpoutsurf, sizeof(tmpoutsurf), NULL);
         }
     }
 
-    if (ctx->output_surface_ready_queue.count && (!frame || ctx->output_surface_ready_queue.count + ctx->output_surface_queue.count >= ctx->buffer_delay)) {
-        tmpoutsurf = out_surf_queue_dequeue(&ctx->output_surface_ready_queue);
+    if (output_ready(avctx, !frame)) {
+        av_fifo_generic_read(ctx->output_surface_ready_queue, &tmpoutsurf, sizeof(tmpoutsurf), NULL);
 
         res = process_output_surface(avctx, pkt, tmpoutsurf);
 
         if (res)
             return res;
 
-        tmpoutsurf->busy = 0;
-        av_assert0(tmpoutsurf->input_surface->lockCount);
-        tmpoutsurf->input_surface->lockCount--;
+        av_assert0(tmpoutsurf->lockCount);
+        tmpoutsurf->lockCount--;
 
         *got_packet = 1;
     } else {
@@ -1466,109 +1671,3 @@ static int nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 
     return 0;
 }
-
-static const enum AVPixelFormat pix_fmts_nvenc[] = {
-    AV_PIX_FMT_YUV420P,
-    AV_PIX_FMT_NV12,
-    AV_PIX_FMT_YUV444P,
-    AV_PIX_FMT_NONE
-};
-
-#define OFFSET(x) offsetof(NvencContext, x)
-#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
-static const AVOption options[] = {
-    { "preset", "Set the encoding preset (one of slow = hq 2pass, medium = hq, fast = hp, hq, hp, bd, ll, llhq, llhp, default)", OFFSET(preset), AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE },
-    { "profile", "Set the encoding profile (high, main, baseline or high444p)", OFFSET(profile), AV_OPT_TYPE_STRING, { .str = "main" }, 0, 0, VE },
-    { "level", "Set the encoding level restriction (auto, 1.0, 1.0b, 1.1, 1.2, ..., 4.2, 5.0, 5.1)", OFFSET(level), AV_OPT_TYPE_STRING, { .str = "auto" }, 0, 0, VE },
-    { "tier", "Set the encoding tier (main or high)", OFFSET(tier), AV_OPT_TYPE_STRING, { .str = "main" }, 0, 0, VE },
-    { "cbr", "Use cbr encoding mode", OFFSET(cbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
-    { "2pass", "Use 2pass encoding mode", OFFSET(twopass), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE },
-    { "gpu", "Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on.", OFFSET(gpu), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
-    { "delay", "Delays frame output by the given amount of frames.", OFFSET(buffer_delay), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE },
-    { NULL }
-};
-
-static const AVCodecDefault nvenc_defaults[] = {
-    { "b", "2M" },
-    { "qmin", "-1" },
-    { "qmax", "-1" },
-    { "qdiff", "-1" },
-    { "qblur", "-1" },
-    { "qcomp", "-1" },
-    { "g", "250" },
-    { "bf", "0" },
-    { NULL },
-};
-
-#if CONFIG_NVENC_ENCODER
-static const AVClass nvenc_class = {
-    .class_name = "nvenc",
-    .item_name = av_default_item_name,
-    .option = options,
-    .version = LIBAVUTIL_VERSION_INT,
-};
-
-AVCodec ff_nvenc_encoder = {
-    .name = "nvenc",
-    .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC h264 encoder"),
-    .type = AVMEDIA_TYPE_VIDEO,
-    .id = AV_CODEC_ID_H264,
-    .priv_data_size = sizeof(NvencContext),
-    .init = nvenc_encode_init,
-    .encode2 = nvenc_encode_frame,
-    .close = nvenc_encode_close,
-    .capabilities = AV_CODEC_CAP_DELAY,
-    .priv_class = &nvenc_class,
-    .defaults = nvenc_defaults,
-    .pix_fmts = pix_fmts_nvenc,
-};
-#endif
-
-/* Add an alias for nvenc_h264 */
-#if CONFIG_NVENC_H264_ENCODER
-static const AVClass nvenc_h264_class = {
-    .class_name = "nvenc_h264",
-    .item_name = av_default_item_name,
-    .option = options,
-    .version = LIBAVUTIL_VERSION_INT,
-};
-
-AVCodec ff_nvenc_h264_encoder = {
-    .name = "nvenc_h264",
-    .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC h264 encoder"),
-    .type = AVMEDIA_TYPE_VIDEO,
-    .id = AV_CODEC_ID_H264,
-    .priv_data_size = sizeof(NvencContext),
-    .init = nvenc_encode_init,
-    .encode2 = nvenc_encode_frame,
-    .close = nvenc_encode_close,
-    .capabilities = AV_CODEC_CAP_DELAY,
-    .priv_class = &nvenc_h264_class,
-    .defaults = nvenc_defaults,
-    .pix_fmts = pix_fmts_nvenc,
-};
-#endif
-
-#if CONFIG_NVENC_HEVC_ENCODER
-static const AVClass nvenc_hevc_class = {
-    .class_name = "nvenc_hevc",
-    .item_name = av_default_item_name,
-    .option = options,
-    .version = LIBAVUTIL_VERSION_INT,
-};
-
-AVCodec ff_nvenc_hevc_encoder = {
-    .name = "nvenc_hevc",
-    .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC hevc encoder"),
-    .type = AVMEDIA_TYPE_VIDEO,
-    .id = AV_CODEC_ID_H265,
-    .priv_data_size = sizeof(NvencContext),
-    .init = nvenc_encode_init,
-    .encode2 = nvenc_encode_frame,
-    .close = nvenc_encode_close,
-    .capabilities = AV_CODEC_CAP_DELAY,
-    .priv_class = &nvenc_hevc_class,
-    .defaults = nvenc_defaults,
-    .pix_fmts = pix_fmts_nvenc,
-};
-#endif
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
new file mode 100644
index 0000000..961cbc7
--- /dev/null
+++ b/libavcodec/nvenc.h
@@ -0,0 +1,188 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_NVENC_H
+#define AVCODEC_NVENC_H
+
+#include <nvEncodeAPI.h>
+
+#include "config.h"
+
+#include "libavutil/fifo.h"
+#include "libavutil/opt.h"
+
+#include "avcodec.h"
+
+#if CONFIG_CUDA
+#include "libavutil/hwcontext_cuda.h"
+#else
+
+#if defined(_WIN32)
+#define CUDAAPI __stdcall
+#else
+#define CUDAAPI
+#endif
+
+typedef enum cudaError_enum {
+    CUDA_SUCCESS = 0
+} CUresult;
+typedef int CUdevice;
+typedef void* CUcontext;
+typedef void* CUdeviceptr;
+#endif
+
+#define MAX_REGISTERED_FRAMES 64
+
+typedef struct NvencSurface
+{
+    NV_ENC_INPUT_PTR input_surface;
+    AVFrame *in_ref;
+    NV_ENC_MAP_INPUT_RESOURCE in_map;
+    int reg_idx;
+    int width;
+    int height;
+
+    NV_ENC_OUTPUT_PTR output_surface;
+    NV_ENC_BUFFER_FORMAT format;
+    int size;
+    int lockCount;
+} NvencSurface;
+
+typedef CUresult(CUDAAPI *PCUINIT)(unsigned int Flags);
+typedef CUresult(CUDAAPI *PCUDEVICEGETCOUNT)(int *count);
+typedef CUresult(CUDAAPI *PCUDEVICEGET)(CUdevice *device, int ordinal);
+typedef CUresult(CUDAAPI *PCUDEVICEGETNAME)(char *name, int len, CUdevice dev);
+typedef CUresult(CUDAAPI *PCUDEVICECOMPUTECAPABILITY)(int *major, int *minor, CUdevice dev);
+typedef CUresult(CUDAAPI *PCUCTXCREATE)(CUcontext *pctx, unsigned int flags, CUdevice dev);
+typedef CUresult(CUDAAPI *PCUCTXPOPCURRENT)(CUcontext *pctx);
+typedef CUresult(CUDAAPI *PCUCTXDESTROY)(CUcontext ctx);
+
+typedef NVENCSTATUS (NVENCAPI *PNVENCODEAPICREATEINSTANCE)(NV_ENCODE_API_FUNCTION_LIST *functionList);
+
+typedef struct NvencDynLoadFunctions
+{
+#if !CONFIG_CUDA
+    void *cuda;
+#endif
+    void *nvenc;
+
+    PCUINIT cu_init;
+    PCUDEVICEGETCOUNT cu_device_get_count;
+    PCUDEVICEGET cu_device_get;
+    PCUDEVICEGETNAME cu_device_get_name;
+    PCUDEVICECOMPUTECAPABILITY cu_device_compute_capability;
+    PCUCTXCREATE cu_ctx_create;
+    PCUCTXPOPCURRENT cu_ctx_pop_current;
+    PCUCTXDESTROY cu_ctx_destroy;
+
+    NV_ENCODE_API_FUNCTION_LIST nvenc_funcs;
+    int nvenc_device_count;
+} NvencDynLoadFunctions;
+
+enum {
+    PRESET_DEFAULT = 0,
+    PRESET_SLOW,
+    PRESET_MEDIUM,
+    PRESET_FAST,
+    PRESET_HP,
+    PRESET_HQ,
+    PRESET_BD ,
+    PRESET_LOW_LATENCY_DEFAULT ,
+    PRESET_LOW_LATENCY_HQ ,
+    PRESET_LOW_LATENCY_HP,
+    PRESET_LOSSLESS_DEFAULT, // lossless presets must be the last ones
+    PRESET_LOSSLESS_HP,
+};
+
+enum {
+    NV_ENC_H264_PROFILE_BASELINE,
+    NV_ENC_H264_PROFILE_MAIN,
+    NV_ENC_H264_PROFILE_HIGH,
+    NV_ENC_H264_PROFILE_HIGH_444P,
+};
+
+enum {
+    NVENC_LOWLATENCY = 1,
+    NVENC_LOSSLESS   = 2,
+    NVENC_ONE_PASS   = 4,
+    NVENC_TWO_PASSES = 8,
+};
+
+enum {
+    LIST_DEVICES = -2,
+    ANY_DEVICE,
+};
+
+typedef struct NvencContext
+{
+    AVClass *avclass;
+
+    NvencDynLoadFunctions nvenc_dload_funcs;
+
+    NV_ENC_INITIALIZE_PARAMS init_encode_params;
+    NV_ENC_CONFIG encode_config;
+    CUcontext cu_context;
+    CUcontext cu_context_internal;
+
+    int nb_surfaces;
+    NvencSurface *surfaces;
+
+    AVFifoBuffer *output_surface_queue;
+    AVFifoBuffer *output_surface_ready_queue;
+    AVFifoBuffer *timestamp_list;
+
+    struct {
+        CUdeviceptr ptr;
+        NV_ENC_REGISTERED_PTR regptr;
+        int mapped;
+    } registered_frames[MAX_REGISTERED_FRAMES];
+    int nb_registered_frames;
+
+    /* the actual data pixel format, different from
+     * AVCodecContext.pix_fmt when using hwaccel frames on input */
+    enum AVPixelFormat data_pix_fmt;
+
+    /* timestamps of the first two frames, for computing the first dts
+     * when B-frames are present */
+    int64_t initial_pts[2];
+    int first_packet_output;
+
+    void *nvencoder;
+
+    int preset;
+    int profile;
+    int level;
+    int tier;
+    int rc;
+    int cbr;
+    int twopass;
+    int device;
+    int flags;
+    int async_depth;
+} NvencContext;
+
+int ff_nvenc_encode_init(AVCodecContext *avctx);
+
+int ff_nvenc_encode_close(AVCodecContext *avctx);
+
+int ff_nvenc_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+                          const AVFrame *frame, int *got_packet);
+
+extern const enum AVPixelFormat ff_nvenc_pix_fmts[];
+
+#endif /* AVCODEC_NVENC_H */
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
new file mode 100644
index 0000000..b576f15
--- /dev/null
+++ b/libavcodec/nvenc_h264.c
@@ -0,0 +1,183 @@
+/*
+ * 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/internal.h"
+
+#include "avcodec.h"
+#include "internal.h"
+
+#include "nvenc.h"
+
+#define OFFSET(x) offsetof(NvencContext, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "preset",   "Set the encoding preset",              OFFSET(preset),      AV_OPT_TYPE_INT,    { .i64 = PRESET_MEDIUM }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, VE, "preset" },
+    { "default",    "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_DEFAULT }, 0, 0, VE, "preset" },
+    { "slow",       "hq 2 passes",                        0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_SLOW }, 0, 0, VE, "preset" },
+    { "medium",     "hq 1 pass",                          0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_MEDIUM }, 0, 0, VE, "preset" },
+    { "fast",       "hp 1 pass",                          0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_FAST }, 0, 0, VE, "preset" },
+    { "hp",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_HP }, 0, 0, VE, "preset" },
+    { "hq",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_HQ }, 0, 0, VE, "preset" },
+    { "bd",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_BD }, 0, 0, VE, "preset" },
+    { "ll",         "low latency",                        0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_DEFAULT }, 0, 0, VE, "preset" },
+    { "llhq",       "low latency hq",                     0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_HQ }, 0, 0, VE, "preset" },
+    { "llhp",       "low latency hp",                     0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_HP }, 0, 0, VE, "preset" },
+    { "lossless",   NULL,                                 0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOSSLESS_DEFAULT }, 0, 0, VE, "preset" },
+    { "losslesshp", NULL,                                 0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOSSLESS_HP }, 0, 0, VE, "preset" },
+    { "profile",  "Set the encoding profile",             OFFSET(profile),     AV_OPT_TYPE_INT,    { .i64 = NV_ENC_H264_PROFILE_MAIN }, NV_ENC_H264_PROFILE_BASELINE, NV_ENC_H264_PROFILE_HIGH_444P, VE, "profile" },
+    { "baseline", "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_H264_PROFILE_BASELINE },            0, 0, VE, "profile" },
+    { "main",     "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_H264_PROFILE_MAIN },                0, 0, VE, "profile" },
+    { "high",     "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_H264_PROFILE_HIGH },                0, 0, VE, "profile" },
+    { "high444p", "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_H264_PROFILE_HIGH_444P },            0, 0, VE, "profile" },
+    { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_H264_51, VE, "level" },
+    { "auto",     "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_AUTOSELECT },  0, 0, VE,  "level" },
+    { "1",        "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_1 },  0, 0, VE,  "level" },
+    { "1.0",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_1 },  0, 0, VE,  "level" },
+    { "1b",       "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_1b }, 0, 0, VE,  "level" },
+    { "1.0b",     "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_1b }, 0, 0, VE,  "level" },
+    { "1.1",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_11 }, 0, 0, VE,  "level" },
+    { "1.2",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_12 }, 0, 0, VE,  "level" },
+    { "1.3",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_13 }, 0, 0, VE,  "level" },
+    { "2",        "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_2 },  0, 0, VE,  "level" },
+    { "2.0",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_2 },  0, 0, VE,  "level" },
+    { "2.1",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_21 }, 0, 0, VE,  "level" },
+    { "2.2",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_22 }, 0, 0, VE,  "level" },
+    { "3",        "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_3 },  0, 0, VE,  "level" },
+    { "3.0",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_3 },  0, 0, VE,  "level" },
+    { "3.1",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_31 }, 0, 0, VE,  "level" },
+    { "3.2",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_32 }, 0, 0, VE,  "level" },
+    { "4",        "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_4 },  0, 0, VE,  "level" },
+    { "4.0",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_4 },  0, 0, VE,  "level" },
+    { "4.1",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_41 }, 0, 0, VE,  "level" },
+    { "4.2",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_42 }, 0, 0, VE,  "level" },
+    { "5",        "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_5 },  0, 0, VE,  "level" },
+    { "5.0",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_5 },  0, 0, VE,  "level" },
+    { "5.1",      "",                                     0,                   AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_H264_51 }, 0, 0, VE,  "level" },
+    { "rc",       "Override the preset rate-control",     OFFSET(rc),          AV_OPT_TYPE_INT,    { .i64 = -1 },                   -1, INT_MAX, VE, "rc" },
+    { "constqp",          "Constant QP mode",                                                            0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_CONSTQP },              0, 0, VE, "rc" },
+    { "vbr",              "Variable bitrate mode",                                                       0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_VBR },                  0, 0, VE, "rc" },
+    { "cbr",              "Constant bitrate mode",                                                       0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_CBR },                  0, 0, VE, "rc" },
+    { "vbr_minqp",        "Variable bitrate mode with MinQP",                                            0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_VBR_MINQP },            0, 0, VE, "rc" },
+    { "ll_2pass_quality", "Multi-pass optimized for image quality (only for low-latency presets)",       0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_2_PASS_QUALITY },       0, 0, VE, "rc" },
+    { "ll_2pass_size",    "Multi-pass optimized for constant frame size (only for low-latency presets)", 0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP }, 0, 0, VE, "rc" },
+    { "vbr_2pass",        "Multi-pass variable bitrate mode",                                            0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_2_PASS_VBR },           0, 0, VE, "rc" },
+    { "surfaces", "Number of concurrent surfaces",        OFFSET(nb_surfaces), AV_OPT_TYPE_INT,    { .i64 = 32 },                   0, INT_MAX, VE },
+    { "cbr", "Use cbr encoding mode", OFFSET(cbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+    { "2pass", "Use 2pass encoding mode", OFFSET(twopass), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE },
+    { "gpu", "Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on.", OFFSET(device), AV_OPT_TYPE_INT, { .i64 = ANY_DEVICE }, -2, INT_MAX, VE, "gpu" },
+    { "any",      "Pick the first device available",      0,                   AV_OPT_TYPE_CONST,  { .i64 = ANY_DEVICE },           0, 0, VE, "gpu" },
+    { "list",     "List the available devices",           0,                   AV_OPT_TYPE_CONST,  { .i64 = LIST_DEVICES },         0, 0, VE, "gpu" },
+    { "delay",    "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE },
+    { NULL }
+};
+
+static const AVCodecDefault defaults[] = {
+    { "b", "2M" },
+    { "qmin", "-1" },
+    { "qmax", "-1" },
+    { "qdiff", "-1" },
+    { "qblur", "-1" },
+    { "qcomp", "-1" },
+    { "g", "250" },
+    { "bf", "0" },
+    { NULL },
+};
+
+#if FF_API_NVENC_OLD_NAME
+
+static av_cold int nvenc_old_init(AVCodecContext *avctx)
+{
+    av_log(avctx, AV_LOG_WARNING, "This encoder is deprecated, use 'h264_nvenc' instead\n");
+    return ff_nvenc_encode_init(avctx);
+}
+
+#if CONFIG_NVENC_ENCODER
+static const AVClass nvenc_class = {
+    .class_name = "nvenc",
+    .item_name = av_default_item_name,
+    .option = options,
+    .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_nvenc_encoder = {
+    .name           = "nvenc",
+    .long_name      = NULL_IF_CONFIG_SMALL("NVIDIA NVENC H.264 encoder"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .init           = nvenc_old_init,
+    .encode2        = ff_nvenc_encode_frame,
+    .close          = ff_nvenc_encode_close,
+    .priv_data_size = sizeof(NvencContext),
+    .priv_class     = &nvenc_class,
+    .defaults       = defaults,
+    .capabilities   = AV_CODEC_CAP_DELAY,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .pix_fmts       = ff_nvenc_pix_fmts,
+};
+#endif
+
+/* Add an alias for nvenc_h264 */
+#if CONFIG_NVENC_H264_ENCODER
+static const AVClass nvenc_h264_class = {
+    .class_name = "nvenc_h264",
+    .item_name = av_default_item_name,
+    .option = options,
+    .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_nvenc_h264_encoder = {
+    .name           = "nvenc_h264",
+    .long_name      = NULL_IF_CONFIG_SMALL("NVIDIA NVENC H.264 encoder"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .init           = nvenc_old_init,
+    .encode2        = ff_nvenc_encode_frame,
+    .close          = ff_nvenc_encode_close,
+    .priv_data_size = sizeof(NvencContext),
+    .priv_class     = &nvenc_h264_class,
+    .defaults       = defaults,
+    .capabilities   = AV_CODEC_CAP_DELAY,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .pix_fmts       = ff_nvenc_pix_fmts,
+};
+#endif
+
+#endif
+
+static const AVClass h264_nvenc_class = {
+    .class_name = "h264_nvenc",
+    .item_name = av_default_item_name,
+    .option = options,
+    .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_h264_nvenc_encoder = {
+    .name           = "h264_nvenc",
+    .long_name      = NULL_IF_CONFIG_SMALL("NVIDIA NVENC H.264 encoder"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .init           = ff_nvenc_encode_init,
+    .encode2        = ff_nvenc_encode_frame,
+    .close          = ff_nvenc_encode_close,
+    .priv_data_size = sizeof(NvencContext),
+    .priv_class     = &h264_nvenc_class,
+    .defaults       = defaults,
+    .capabilities   = AV_CODEC_CAP_DELAY,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .pix_fmts       = ff_nvenc_pix_fmts,
+};
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
new file mode 100644
index 0000000..1ce7c89
--- /dev/null
+++ b/libavcodec/nvenc_hevc.c
@@ -0,0 +1,152 @@
+/*
+ * 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/internal.h"
+
+#include "avcodec.h"
+#include "internal.h"
+
+#include "nvenc.h"
+
+#define OFFSET(x) offsetof(NvencContext, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "preset",   "Set the encoding preset",              OFFSET(preset),      AV_OPT_TYPE_INT,    { .i64 = PRESET_MEDIUM }, PRESET_DEFAULT, PRESET_LOSSLESS_HP, VE, "preset" },
+    { "default",    "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_DEFAULT }, 0, 0, VE, "preset" },
+    { "slow",       "hq 2 passes",                        0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_SLOW }, 0, 0, VE, "preset" },
+    { "medium",     "hq 1 pass",                          0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_MEDIUM }, 0, 0, VE, "preset" },
+    { "fast",       "hp 1 pass",                          0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_FAST }, 0, 0, VE, "preset" },
+    { "hp",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_HP }, 0, 0, VE, "preset" },
+    { "hq",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_HQ }, 0, 0, VE, "preset" },
+    { "bd",         "",                                   0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_BD }, 0, 0, VE, "preset" },
+    { "ll",         "low latency",                        0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_DEFAULT }, 0, 0, VE, "preset" },
+    { "llhq",       "low latency hq",                     0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_HQ }, 0, 0, VE, "preset" },
+    { "llhp",       "low latency hp",                     0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOW_LATENCY_HP }, 0, 0, VE, "preset" },
+    { "lossless",   "lossless",                           0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOSSLESS_DEFAULT }, 0, 0, VE, "preset" },
+    { "losslesshp", "lossless hp",                        0,                   AV_OPT_TYPE_CONST,  { .i64 = PRESET_LOSSLESS_HP }, 0, 0, VE, "preset" },
+    { "profile", "Set the encoding profile",             OFFSET(profile),      AV_OPT_TYPE_INT,    { .i64 = FF_PROFILE_HEVC_MAIN }, FF_PROFILE_HEVC_MAIN, FF_PROFILE_HEVC_MAIN, VE, "profile" },
+    { "main",    "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = FF_PROFILE_HEVC_MAIN }, 0, 0, VE, "profile" },
+    { "level",   "Set the encoding level restriction",   OFFSET(level),        AV_OPT_TYPE_INT,    { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_HEVC_62, VE, "level" },
+    { "auto",    "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_AUTOSELECT },  0, 0, VE,  "level" },
+    { "1",       "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_1 },  0, 0, VE,  "level" },
+    { "1.0",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_1 },  0, 0, VE,  "level" },
+    { "2",       "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_2 },  0, 0, VE,  "level" },
+    { "2.0",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_2 },  0, 0, VE,  "level" },
+    { "2.1",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_21 }, 0, 0, VE,  "level" },
+    { "3",       "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_3 },  0, 0, VE,  "level" },
+    { "3.0",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_3 },  0, 0, VE,  "level" },
+    { "3.1",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_31 }, 0, 0, VE,  "level" },
+    { "4",       "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_4 },  0, 0, VE,  "level" },
+    { "4.0",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_4 },  0, 0, VE,  "level" },
+    { "4.1",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_41 }, 0, 0, VE,  "level" },
+    { "5",       "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_5 },  0, 0, VE,  "level" },
+    { "5.0",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_5 },  0, 0, VE,  "level" },
+    { "5.1",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_51 }, 0, 0, VE,  "level" },
+    { "5.2",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_52 }, 0, 0, VE,  "level" },
+    { "6",       "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_6 },  0, 0, VE,  "level" },
+    { "6.0",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_6 },  0, 0, VE,  "level" },
+    { "6.1",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_61 }, 0, 0, VE,  "level" },
+    { "6.2",     "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_LEVEL_HEVC_62 }, 0, 0, VE,  "level" },
+    { "tier",    "Set the encoding tier",                OFFSET(tier),         AV_OPT_TYPE_INT,    { .i64 = NV_ENC_TIER_HEVC_MAIN }, NV_ENC_TIER_HEVC_MAIN, NV_ENC_TIER_HEVC_HIGH, VE, "tier"},
+    { "main",    "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_TIER_HEVC_MAIN }, 0, 0, VE, "tier" },
+    { "high",    "",                                     0,                    AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_TIER_HEVC_HIGH }, 0, 0, VE, "tier" },
+    { "rc",      "Override the preset rate-control",     OFFSET(rc),           AV_OPT_TYPE_INT,    { .i64 = -1 },                   -1, INT_MAX, VE, "rc" },
+    { "constqp",          "Constant QP mode",                                                            0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_CONSTQP },              0, 0, VE, "rc" },
+    { "vbr",              "Variable bitrate mode",                                                       0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_VBR },                  0, 0, VE, "rc" },
+    { "cbr",              "Constant bitrate mode",                                                       0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_CBR },                  0, 0, VE, "rc" },
+    { "vbr_minqp",        "Variable bitrate mode with MinQP",                                            0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_VBR_MINQP },            0, 0, VE, "rc" },
+    { "ll_2pass_quality", "Multi-pass optimized for image quality (only for low-latency presets)",       0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_2_PASS_QUALITY },       0, 0, VE, "rc" },
+    { "ll_2pass_size",    "Multi-pass optimized for constant frame size (only for low-latency presets)", 0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_2_PASS_FRAMESIZE_CAP }, 0, 0, VE, "rc" },
+    { "vbr_2pass",        "Multi-pass variable bitrate mode",                                            0, AV_OPT_TYPE_CONST,  { .i64 = NV_ENC_PARAMS_RC_2_PASS_VBR },           0, 0, VE, "rc" },
+    { "surfaces", "Number of concurrent surfaces",        OFFSET(nb_surfaces), AV_OPT_TYPE_INT,    { .i64 = 32 },                   0, INT_MAX, VE },
+    { "cbr", "Use cbr encoding mode", OFFSET(cbr), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+    { "2pass", "Use 2pass encoding mode", OFFSET(twopass), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, VE },
+    { "gpu", "Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on.", OFFSET(device), AV_OPT_TYPE_INT, { .i64 = ANY_DEVICE }, -2, INT_MAX, VE },
+    { "any",      "Pick the first device available",      0,                   AV_OPT_TYPE_CONST,  { .i64 = ANY_DEVICE },           0, 0, VE, "device" },
+    { "list",     "List the available devices",           0,                   AV_OPT_TYPE_CONST,  { .i64 = LIST_DEVICES },         0, 0, VE, "device" },
+    { "delay",    "Delay frame output by the given amount of frames", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 0, INT_MAX, VE },
+    { NULL }
+};
+
+static const AVCodecDefault defaults[] = {
+    { "b", "2M" },
+    { "qmin", "-1" },
+    { "qmax", "-1" },
+    { "qdiff", "-1" },
+    { "qblur", "-1" },
+    { "qcomp", "-1" },
+    { "g", "250" },
+    { "bf", "0" },
+    { NULL },
+};
+
+#if FF_API_NVENC_OLD_NAME
+
+static av_cold int nvenc_old_init(AVCodecContext *avctx)
+{
+    av_log(avctx, AV_LOG_WARNING, "This encoder is deprecated, use 'hevc_nvenc' instead\n");
+    return ff_nvenc_encode_init(avctx);
+}
+
+static const AVClass nvenc_hevc_class = {
+    .class_name = "nvenc_hevc",
+    .item_name = av_default_item_name,
+    .option = options,
+    .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_nvenc_hevc_encoder = {
+    .name           = "nvenc_hevc",
+    .long_name      = NULL_IF_CONFIG_SMALL("NVIDIA NVENC hevc encoder"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_HEVC,
+    .init           = nvenc_old_init,
+    .encode2        = ff_nvenc_encode_frame,
+    .close          = ff_nvenc_encode_close,
+    .priv_data_size = sizeof(NvencContext),
+    .priv_class     = &nvenc_hevc_class,
+    .defaults       = defaults,
+    .pix_fmts       = ff_nvenc_pix_fmts,
+    .capabilities   = AV_CODEC_CAP_DELAY,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+};
+
+#endif
+
+static const AVClass hevc_nvenc_class = {
+    .class_name = "hevc_nvenc",
+    .item_name = av_default_item_name,
+    .option = options,
+    .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_hevc_nvenc_encoder = {
+    .name           = "hevc_nvenc",
+    .long_name      = NULL_IF_CONFIG_SMALL("NVIDIA NVENC hevc encoder"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_HEVC,
+    .init           = ff_nvenc_encode_init,
+    .encode2        = ff_nvenc_encode_frame,
+    .close          = ff_nvenc_encode_close,
+    .priv_data_size = sizeof(NvencContext),
+    .priv_class     = &hevc_nvenc_class,
+    .defaults       = defaults,
+    .pix_fmts       = ff_nvenc_pix_fmts,
+    .capabilities   = AV_CODEC_CAP_DELAY,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+};
diff --git a/libavcodec/omx.c b/libavcodec/omx.c
new file mode 100644
index 0000000..1b2ae0d
--- /dev/null
+++ b/libavcodec/omx.c
@@ -0,0 +1,931 @@
+/*
+ * OMX Video encoder
+ * Copyright (C) 2011 Martin Storsjo
+ *
+ * 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 "config.h"
+
+#if CONFIG_OMX_RPI
+#define OMX_SKIP64BIT
+#endif
+
+#include <dlfcn.h>
+#include <OMX_Core.h>
+#include <OMX_Component.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "libavutil/avstring.h"
+#include "libavutil/avutil.h"
+#include "libavutil/common.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+
+#include "avcodec.h"
+#include "h264.h"
+#include "internal.h"
+
+#ifdef OMX_SKIP64BIT
+static OMX_TICKS to_omx_ticks(int64_t value)
+{
+    OMX_TICKS s;
+    s.nLowPart  = value & 0xffffffff;
+    s.nHighPart = value >> 32;
+    return s;
+}
+static int64_t from_omx_ticks(OMX_TICKS value)
+{
+    return (((int64_t)value.nHighPart) << 32) | value.nLowPart;
+}
+#else
+#define to_omx_ticks(x) (x)
+#define from_omx_ticks(x) (x)
+#endif
+
+#define INIT_STRUCT(x) do {                                               \
+        x.nSize = sizeof(x);                                              \
+        x.nVersion = s->version;                                          \
+    } while (0)
+#define CHECK(x) do {                                                     \
+        if (x != OMX_ErrorNone) {                                         \
+            av_log(avctx, AV_LOG_ERROR,                                   \
+                   "err %x (%d) on line %d\n", x, x, __LINE__);           \
+            return AVERROR_UNKNOWN;                                       \
+        }                                                                 \
+    } while (0)
+
+typedef struct OMXContext {
+    void *lib;
+    void *lib2;
+    OMX_ERRORTYPE (*ptr_Init)(void);
+    OMX_ERRORTYPE (*ptr_Deinit)(void);
+    OMX_ERRORTYPE (*ptr_ComponentNameEnum)(OMX_STRING, OMX_U32, OMX_U32);
+    OMX_ERRORTYPE (*ptr_GetHandle)(OMX_HANDLETYPE*, OMX_STRING, OMX_PTR, OMX_CALLBACKTYPE*);
+    OMX_ERRORTYPE (*ptr_FreeHandle)(OMX_HANDLETYPE);
+    OMX_ERRORTYPE (*ptr_GetComponentsOfRole)(OMX_STRING, OMX_U32*, OMX_U8**);
+    OMX_ERRORTYPE (*ptr_GetRolesOfComponent)(OMX_STRING, OMX_U32*, OMX_U8**);
+    void (*host_init)(void);
+} OMXContext;
+
+static av_cold void *dlsym_prefixed(void *handle, const char *symbol, const char *prefix)
+{
+    char buf[50];
+    snprintf(buf, sizeof(buf), "%s%s", prefix ? prefix : "", symbol);
+    return dlsym(handle, buf);
+}
+
+static av_cold int omx_try_load(OMXContext *s, void *logctx,
+                                const char *libname, const char *prefix,
+                                const char *libname2)
+{
+    if (libname2) {
+        s->lib2 = dlopen(libname2, RTLD_NOW | RTLD_GLOBAL);
+        if (!s->lib2) {
+            av_log(logctx, AV_LOG_WARNING, "%s not found\n", libname);
+            return AVERROR_ENCODER_NOT_FOUND;
+        }
+        s->host_init = dlsym(s->lib2, "bcm_host_init");
+        if (!s->host_init) {
+            av_log(logctx, AV_LOG_WARNING, "bcm_host_init not found\n");
+            dlclose(s->lib2);
+            s->lib2 = NULL;
+            return AVERROR_ENCODER_NOT_FOUND;
+        }
+    }
+    s->lib = dlopen(libname, RTLD_NOW | RTLD_GLOBAL);
+    if (!s->lib) {
+        av_log(logctx, AV_LOG_WARNING, "%s not found\n", libname);
+        return AVERROR_ENCODER_NOT_FOUND;
+    }
+    s->ptr_Init                = dlsym_prefixed(s->lib, "OMX_Init", prefix);
+    s->ptr_Deinit              = dlsym_prefixed(s->lib, "OMX_Deinit", prefix);
+    s->ptr_ComponentNameEnum   = dlsym_prefixed(s->lib, "OMX_ComponentNameEnum", prefix);
+    s->ptr_GetHandle           = dlsym_prefixed(s->lib, "OMX_GetHandle", prefix);
+    s->ptr_FreeHandle          = dlsym_prefixed(s->lib, "OMX_FreeHandle", prefix);
+    s->ptr_GetComponentsOfRole = dlsym_prefixed(s->lib, "OMX_GetComponentsOfRole", prefix);
+    s->ptr_GetRolesOfComponent = dlsym_prefixed(s->lib, "OMX_GetRolesOfComponent", prefix);
+    if (!s->ptr_Init || !s->ptr_Deinit || !s->ptr_ComponentNameEnum ||
+        !s->ptr_GetHandle || !s->ptr_FreeHandle ||
+        !s->ptr_GetComponentsOfRole || !s->ptr_GetRolesOfComponent) {
+        av_log(logctx, AV_LOG_WARNING, "Not all functions found in %s\n", libname);
+        dlclose(s->lib);
+        s->lib = NULL;
+        if (s->lib2)
+            dlclose(s->lib2);
+        s->lib2 = NULL;
+        return AVERROR_ENCODER_NOT_FOUND;
+    }
+    return 0;
+}
+
+static av_cold OMXContext *omx_init(void *logctx, const char *libname, const char *prefix)
+{
+    static const char * const libnames[] = {
+#if CONFIG_OMX_RPI
+        "/opt/vc/lib/libopenmaxil.so", "/opt/vc/lib/libbcm_host.so",
+#else
+        "libOMX_Core.so", NULL,
+        "libOmxCore.so", NULL,
+#endif
+        NULL
+    };
+    const char* const* nameptr;
+    int ret = AVERROR_ENCODER_NOT_FOUND;
+    OMXContext *omx_context;
+
+    omx_context = av_mallocz(sizeof(*omx_context));
+    if (!omx_context)
+        return NULL;
+    if (libname) {
+        ret = omx_try_load(omx_context, logctx, libname, prefix, NULL);
+        if (ret < 0) {
+            av_free(omx_context);
+            return NULL;
+        }
+    } else {
+        for (nameptr = libnames; *nameptr; nameptr += 2)
+            if (!(ret = omx_try_load(omx_context, logctx, nameptr[0], prefix, nameptr[1])))
+                break;
+        if (!*nameptr) {
+            av_free(omx_context);
+            return NULL;
+        }
+    }
+
+    if (omx_context->host_init)
+        omx_context->host_init();
+    omx_context->ptr_Init();
+    return omx_context;
+}
+
+static av_cold void omx_deinit(OMXContext *omx_context)
+{
+    if (!omx_context)
+        return;
+    omx_context->ptr_Deinit();
+    dlclose(omx_context->lib);
+    av_free(omx_context);
+}
+
+typedef struct OMXCodecContext {
+    const AVClass *class;
+    char *libname;
+    char *libprefix;
+    OMXContext *omx_context;
+
+    AVCodecContext *avctx;
+
+    char component_name[OMX_MAX_STRINGNAME_SIZE];
+    OMX_VERSIONTYPE version;
+    OMX_HANDLETYPE handle;
+    int in_port, out_port;
+    OMX_COLOR_FORMATTYPE color_format;
+    int stride, plane_size;
+
+    int num_in_buffers, num_out_buffers;
+    OMX_BUFFERHEADERTYPE **in_buffer_headers;
+    OMX_BUFFERHEADERTYPE **out_buffer_headers;
+    int num_free_in_buffers;
+    OMX_BUFFERHEADERTYPE **free_in_buffers;
+    int num_done_out_buffers;
+    OMX_BUFFERHEADERTYPE **done_out_buffers;
+    pthread_mutex_t input_mutex;
+    pthread_cond_t input_cond;
+    pthread_mutex_t output_mutex;
+    pthread_cond_t output_cond;
+
+    pthread_mutex_t state_mutex;
+    pthread_cond_t state_cond;
+    OMX_STATETYPE state;
+    OMX_ERRORTYPE error;
+
+    int mutex_cond_inited;
+
+    int num_in_frames, num_out_frames;
+
+    uint8_t *output_buf;
+    int output_buf_size;
+
+    int input_zerocopy;
+} OMXCodecContext;
+
+static void append_buffer(pthread_mutex_t *mutex, pthread_cond_t *cond,
+                          int* array_size, OMX_BUFFERHEADERTYPE **array,
+                          OMX_BUFFERHEADERTYPE *buffer)
+{
+    pthread_mutex_lock(mutex);
+    array[(*array_size)++] = buffer;
+    pthread_cond_broadcast(cond);
+    pthread_mutex_unlock(mutex);
+}
+
+static OMX_BUFFERHEADERTYPE *get_buffer(pthread_mutex_t *mutex, pthread_cond_t *cond,
+                                        int* array_size, OMX_BUFFERHEADERTYPE **array,
+                                        int wait)
+{
+    OMX_BUFFERHEADERTYPE *buffer;
+    pthread_mutex_lock(mutex);
+    if (wait) {
+        while (!*array_size)
+           pthread_cond_wait(cond, mutex);
+    }
+    if (*array_size > 0) {
+        buffer = array[0];
+        (*array_size)--;
+        memmove(&array[0], &array[1], (*array_size) * sizeof(OMX_BUFFERHEADERTYPE*));
+    } else {
+        buffer = NULL;
+    }
+    pthread_mutex_unlock(mutex);
+    return buffer;
+}
+
+static OMX_ERRORTYPE event_handler(OMX_HANDLETYPE component, OMX_PTR app_data, OMX_EVENTTYPE event,
+                                   OMX_U32 data1, OMX_U32 data2, OMX_PTR event_data)
+{
+    OMXCodecContext *s = app_data;
+    // This uses casts in the printfs, since OMX_U32 actually is a typedef for
+    // unsigned long in official header versions (but there are also modified
+    // versions where it is something else).
+    switch (event) {
+    case OMX_EventError:
+        pthread_mutex_lock(&s->state_mutex);
+        av_log(s->avctx, AV_LOG_ERROR, "OMX error %"PRIx32"\n", (uint32_t) data1);
+        s->error = data1;
+        pthread_cond_broadcast(&s->state_cond);
+        pthread_mutex_unlock(&s->state_mutex);
+        break;
+    case OMX_EventCmdComplete:
+        if (data1 == OMX_CommandStateSet) {
+            pthread_mutex_lock(&s->state_mutex);
+            s->state = data2;
+            av_log(s->avctx, AV_LOG_VERBOSE, "OMX state changed to %"PRIu32"\n", (uint32_t) data2);
+            pthread_cond_broadcast(&s->state_cond);
+            pthread_mutex_unlock(&s->state_mutex);
+        } else if (data1 == OMX_CommandPortDisable) {
+            av_log(s->avctx, AV_LOG_VERBOSE, "OMX port %"PRIu32" disabled\n", (uint32_t) data2);
+        } else if (data1 == OMX_CommandPortEnable) {
+            av_log(s->avctx, AV_LOG_VERBOSE, "OMX port %"PRIu32" enabled\n", (uint32_t) data2);
+        } else {
+            av_log(s->avctx, AV_LOG_VERBOSE, "OMX command complete, command %"PRIu32", value %"PRIu32"\n",
+                                             (uint32_t) data1, (uint32_t) data2);
+        }
+        break;
+    case OMX_EventPortSettingsChanged:
+        av_log(s->avctx, AV_LOG_VERBOSE, "OMX port %"PRIu32" settings changed\n", (uint32_t) data1);
+        break;
+    default:
+        av_log(s->avctx, AV_LOG_VERBOSE, "OMX event %d %"PRIx32" %"PRIx32"\n",
+                                         event, (uint32_t) data1, (uint32_t) data2);
+        break;
+    }
+    return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE empty_buffer_done(OMX_HANDLETYPE component, OMX_PTR app_data,
+                                       OMX_BUFFERHEADERTYPE *buffer)
+{
+    OMXCodecContext *s = app_data;
+    if (s->input_zerocopy) {
+        if (buffer->pAppPrivate) {
+            if (buffer->pOutputPortPrivate)
+                av_free(buffer->pAppPrivate);
+            else
+                av_frame_free((AVFrame**)&buffer->pAppPrivate);
+            buffer->pAppPrivate = NULL;
+        }
+    }
+    append_buffer(&s->input_mutex, &s->input_cond,
+                  &s->num_free_in_buffers, s->free_in_buffers, buffer);
+    return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE fill_buffer_done(OMX_HANDLETYPE component, OMX_PTR app_data,
+                                      OMX_BUFFERHEADERTYPE *buffer)
+{
+    OMXCodecContext *s = app_data;
+    append_buffer(&s->output_mutex, &s->output_cond,
+                  &s->num_done_out_buffers, s->done_out_buffers, buffer);
+    return OMX_ErrorNone;
+}
+
+static const OMX_CALLBACKTYPE callbacks = {
+    event_handler,
+    empty_buffer_done,
+    fill_buffer_done
+};
+
+static av_cold int find_component(OMXContext *omx_context, void *logctx,
+                                  const char *role, char *str, int str_size)
+{
+    OMX_U32 i, num = 0;
+    char **components;
+    int ret = 0;
+
+#if CONFIG_OMX_RPI
+    if (av_strstart(role, "video_encoder.", NULL)) {
+        av_strlcpy(str, "OMX.broadcom.video_encode", str_size);
+        return 0;
+    }
+#endif
+    omx_context->ptr_GetComponentsOfRole((OMX_STRING) role, &num, NULL);
+    if (!num) {
+        av_log(logctx, AV_LOG_WARNING, "No component for role %s found\n", role);
+        return AVERROR_ENCODER_NOT_FOUND;
+    }
+    components = av_mallocz(sizeof(char*) * num);
+    if (!components)
+        return AVERROR(ENOMEM);
+    for (i = 0; i < num; i++) {
+        components[i] = av_mallocz(OMX_MAX_STRINGNAME_SIZE);
+        if (!components) {
+            ret = AVERROR(ENOMEM);
+            goto end;
+        }
+    }
+    omx_context->ptr_GetComponentsOfRole((OMX_STRING) role, &num, (OMX_U8**) components);
+    av_strlcpy(str, components[0], str_size);
+end:
+    for (i = 0; i < num; i++)
+        av_free(components[i]);
+    av_free(components);
+    return ret;
+}
+
+static av_cold int wait_for_state(OMXCodecContext *s, OMX_STATETYPE state)
+{
+    int ret = 0;
+    pthread_mutex_lock(&s->state_mutex);
+    while (s->state != state && s->error == OMX_ErrorNone)
+        pthread_cond_wait(&s->state_cond, &s->state_mutex);
+    if (s->error != OMX_ErrorNone)
+        ret = AVERROR_ENCODER_NOT_FOUND;
+    pthread_mutex_unlock(&s->state_mutex);
+    return ret;
+}
+
+static av_cold int omx_component_init(AVCodecContext *avctx, const char *role)
+{
+    OMXCodecContext *s = avctx->priv_data;
+    OMX_PARAM_COMPONENTROLETYPE role_params = { 0 };
+    OMX_PORT_PARAM_TYPE video_port_params = { 0 };
+    OMX_PARAM_PORTDEFINITIONTYPE in_port_params = { 0 }, out_port_params = { 0 };
+    OMX_VIDEO_PARAM_PORTFORMATTYPE video_port_format = { 0 };
+    OMX_VIDEO_PARAM_BITRATETYPE vid_param_bitrate = { 0 };
+    OMX_ERRORTYPE err;
+    int i;
+
+    s->version.s.nVersionMajor = 1;
+    s->version.s.nVersionMinor = 1;
+    s->version.s.nRevision     = 2;
+
+    err = s->omx_context->ptr_GetHandle(&s->handle, s->component_name, s, (OMX_CALLBACKTYPE*) &callbacks);
+    if (err != OMX_ErrorNone) {
+        av_log(avctx, AV_LOG_ERROR, "OMX_GetHandle(%s) failed: %x\n", s->component_name, err);
+        return AVERROR_UNKNOWN;
+    }
+
+    // This one crashes the mediaserver on qcom, if used over IOMX
+    INIT_STRUCT(role_params);
+    av_strlcpy(role_params.cRole, role, sizeof(role_params.cRole));
+    // Intentionally ignore errors on this one
+    OMX_SetParameter(s->handle, OMX_IndexParamStandardComponentRole, &role_params);
+
+    INIT_STRUCT(video_port_params);
+    err = OMX_GetParameter(s->handle, OMX_IndexParamVideoInit, &video_port_params);
+    CHECK(err);
+
+    s->in_port = s->out_port = -1;
+    for (i = 0; i < video_port_params.nPorts; i++) {
+        int port = video_port_params.nStartPortNumber + i;
+        OMX_PARAM_PORTDEFINITIONTYPE port_params = { 0 };
+        INIT_STRUCT(port_params);
+        port_params.nPortIndex = port;
+        err = OMX_GetParameter(s->handle, OMX_IndexParamPortDefinition, &port_params);
+        if (err != OMX_ErrorNone) {
+            av_log(avctx, AV_LOG_WARNING, "port %d error %x\n", port, err);
+            break;
+        }
+        if (port_params.eDir == OMX_DirInput && s->in_port < 0) {
+            in_port_params = port_params;
+            s->in_port = port;
+        } else if (port_params.eDir == OMX_DirOutput && s->out_port < 0) {
+            out_port_params = port_params;
+            s->out_port = port;
+        }
+    }
+    if (s->in_port < 0 || s->out_port < 0) {
+        av_log(avctx, AV_LOG_ERROR, "No in or out port found (in %d out %d)\n", s->in_port, s->out_port);
+        return AVERROR_UNKNOWN;
+    }
+
+    s->color_format = 0;
+    for (i = 0; ; i++) {
+        INIT_STRUCT(video_port_format);
+        video_port_format.nIndex = i;
+        video_port_format.nPortIndex = s->in_port;
+        if (OMX_GetParameter(s->handle, OMX_IndexParamVideoPortFormat, &video_port_format) != OMX_ErrorNone)
+            break;
+        if (video_port_format.eColorFormat == OMX_COLOR_FormatYUV420Planar ||
+            video_port_format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar) {
+            s->color_format = video_port_format.eColorFormat;
+            break;
+        }
+    }
+    if (s->color_format == 0) {
+        av_log(avctx, AV_LOG_ERROR, "No supported pixel formats (%d formats available)\n", i);
+        return AVERROR_UNKNOWN;
+    }
+
+    in_port_params.bEnabled   = OMX_TRUE;
+    in_port_params.bPopulated = OMX_FALSE;
+    in_port_params.eDomain    = OMX_PortDomainVideo;
+
+    in_port_params.format.video.pNativeRender         = NULL;
+    in_port_params.format.video.bFlagErrorConcealment = OMX_FALSE;
+    in_port_params.format.video.eColorFormat          = s->color_format;
+    s->stride     = avctx->width;
+    s->plane_size = avctx->height;
+    // If specific codecs need to manually override the stride/plane_size,
+    // that can be done here.
+    in_port_params.format.video.nStride      = s->stride;
+    in_port_params.format.video.nSliceHeight = s->plane_size;
+    in_port_params.format.video.nFrameWidth  = avctx->width;
+    in_port_params.format.video.nFrameHeight = avctx->height;
+    if (avctx->framerate.den > 0 && avctx->framerate.num > 0)
+        in_port_params.format.video.xFramerate = (1 << 16) * avctx->framerate.num / avctx->framerate.den;
+    else
+        in_port_params.format.video.xFramerate = (1 << 16) * avctx->time_base.den / avctx->time_base.num;
+
+    err = OMX_SetParameter(s->handle, OMX_IndexParamPortDefinition, &in_port_params);
+    CHECK(err);
+    err = OMX_GetParameter(s->handle, OMX_IndexParamPortDefinition, &in_port_params);
+    CHECK(err);
+    s->stride         = in_port_params.format.video.nStride;
+    s->plane_size     = in_port_params.format.video.nSliceHeight;
+    s->num_in_buffers = in_port_params.nBufferCountActual;
+
+    err = OMX_GetParameter(s->handle, OMX_IndexParamPortDefinition, &out_port_params);
+    out_port_params.bEnabled   = OMX_TRUE;
+    out_port_params.bPopulated = OMX_FALSE;
+    out_port_params.eDomain    = OMX_PortDomainVideo;
+    out_port_params.format.video.pNativeRender = NULL;
+    out_port_params.format.video.nFrameWidth   = avctx->width;
+    out_port_params.format.video.nFrameHeight  = avctx->height;
+    out_port_params.format.video.nStride       = 0;
+    out_port_params.format.video.nSliceHeight  = 0;
+    out_port_params.format.video.nBitrate      = avctx->bit_rate;
+    out_port_params.format.video.xFramerate    = in_port_params.format.video.xFramerate;
+    out_port_params.format.video.bFlagErrorConcealment  = OMX_FALSE;
+    if (avctx->codec->id == AV_CODEC_ID_MPEG4)
+        out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
+    else if (avctx->codec->id == AV_CODEC_ID_H264)
+        out_port_params.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+
+    err = OMX_SetParameter(s->handle, OMX_IndexParamPortDefinition, &out_port_params);
+    CHECK(err);
+    err = OMX_GetParameter(s->handle, OMX_IndexParamPortDefinition, &out_port_params);
+    CHECK(err);
+    s->num_out_buffers = out_port_params.nBufferCountActual;
+
+    INIT_STRUCT(vid_param_bitrate);
+    vid_param_bitrate.nPortIndex     = s->out_port;
+    vid_param_bitrate.eControlRate   = OMX_Video_ControlRateVariable;
+    vid_param_bitrate.nTargetBitrate = avctx->bit_rate;
+    err = OMX_SetParameter(s->handle, OMX_IndexParamVideoBitrate, &vid_param_bitrate);
+    if (err != OMX_ErrorNone)
+        av_log(avctx, AV_LOG_WARNING, "Unable to set video bitrate parameter\n");
+
+    if (avctx->codec->id == AV_CODEC_ID_H264) {
+        OMX_VIDEO_PARAM_AVCTYPE avc = { 0 };
+        INIT_STRUCT(avc);
+        avc.nPortIndex = s->out_port;
+        err = OMX_GetParameter(s->handle, OMX_IndexParamVideoAvc, &avc);
+        CHECK(err);
+        avc.nBFrames = 0;
+        avc.nPFrames = avctx->gop_size - 1;
+        err = OMX_SetParameter(s->handle, OMX_IndexParamVideoAvc, &avc);
+        CHECK(err);
+    }
+
+    err = OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateIdle, NULL);
+    CHECK(err);
+
+    s->in_buffer_headers  = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_in_buffers);
+    s->free_in_buffers    = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_in_buffers);
+    s->out_buffer_headers = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers);
+    s->done_out_buffers   = av_mallocz(sizeof(OMX_BUFFERHEADERTYPE*) * s->num_out_buffers);
+    if (!s->in_buffer_headers || !s->free_in_buffers || !s->out_buffer_headers || !s->done_out_buffers)
+        return AVERROR(ENOMEM);
+    for (i = 0; i < s->num_in_buffers && err == OMX_ErrorNone; i++) {
+        if (s->input_zerocopy)
+            err = OMX_UseBuffer(s->handle, &s->in_buffer_headers[i], s->in_port, s, in_port_params.nBufferSize, NULL);
+        else
+            err = OMX_AllocateBuffer(s->handle, &s->in_buffer_headers[i],  s->in_port,  s, in_port_params.nBufferSize);
+        if (err == OMX_ErrorNone)
+            s->in_buffer_headers[i]->pAppPrivate = s->in_buffer_headers[i]->pOutputPortPrivate = NULL;
+    }
+    CHECK(err);
+    s->num_in_buffers = i;
+    for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; i++)
+        err = OMX_AllocateBuffer(s->handle, &s->out_buffer_headers[i], s->out_port, s, out_port_params.nBufferSize);
+    CHECK(err);
+    s->num_out_buffers = i;
+
+    if (wait_for_state(s, OMX_StateIdle) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Didn't get OMX_StateIdle\n");
+        return AVERROR_UNKNOWN;
+    }
+    err = OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateExecuting, NULL);
+    CHECK(err);
+    if (wait_for_state(s, OMX_StateExecuting) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Didn't get OMX_StateExecuting\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    for (i = 0; i < s->num_out_buffers && err == OMX_ErrorNone; i++)
+        err = OMX_FillThisBuffer(s->handle, s->out_buffer_headers[i]);
+    if (err != OMX_ErrorNone) {
+        for (; i < s->num_out_buffers; i++)
+            s->done_out_buffers[s->num_done_out_buffers++] = s->out_buffer_headers[i];
+    }
+    for (i = 0; i < s->num_in_buffers; i++)
+        s->free_in_buffers[s->num_free_in_buffers++] = s->in_buffer_headers[i];
+    return err != OMX_ErrorNone ? AVERROR_UNKNOWN : 0;
+}
+
+static av_cold void cleanup(OMXCodecContext *s)
+{
+    int i, executing;
+
+    pthread_mutex_lock(&s->state_mutex);
+    executing = s->state == OMX_StateExecuting;
+    pthread_mutex_unlock(&s->state_mutex);
+
+    if (executing) {
+        OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateIdle, NULL);
+        wait_for_state(s, OMX_StateIdle);
+        OMX_SendCommand(s->handle, OMX_CommandStateSet, OMX_StateLoaded, NULL);
+        for (i = 0; i < s->num_in_buffers; i++) {
+            OMX_BUFFERHEADERTYPE *buffer = get_buffer(&s->input_mutex, &s->input_cond,
+                                                      &s->num_free_in_buffers, s->free_in_buffers, 1);
+            if (s->input_zerocopy)
+                buffer->pBuffer = NULL;
+            OMX_FreeBuffer(s->handle, s->in_port, buffer);
+        }
+        for (i = 0; i < s->num_out_buffers; i++) {
+            OMX_BUFFERHEADERTYPE *buffer = get_buffer(&s->output_mutex, &s->output_cond,
+                                                      &s->num_done_out_buffers, s->done_out_buffers, 1);
+            OMX_FreeBuffer(s->handle, s->out_port, buffer);
+        }
+        wait_for_state(s, OMX_StateLoaded);
+    }
+    if (s->handle) {
+        s->omx_context->ptr_FreeHandle(s->handle);
+        s->handle = NULL;
+    }
+
+    omx_deinit(s->omx_context);
+    s->omx_context = NULL;
+    if (s->mutex_cond_inited) {
+        pthread_cond_destroy(&s->state_cond);
+        pthread_mutex_destroy(&s->state_mutex);
+        pthread_cond_destroy(&s->input_cond);
+        pthread_mutex_destroy(&s->input_mutex);
+        pthread_cond_destroy(&s->output_cond);
+        pthread_mutex_destroy(&s->output_mutex);
+        s->mutex_cond_inited = 0;
+    }
+    av_freep(&s->in_buffer_headers);
+    av_freep(&s->out_buffer_headers);
+    av_freep(&s->free_in_buffers);
+    av_freep(&s->done_out_buffers);
+    av_freep(&s->output_buf);
+}
+
+static av_cold int omx_encode_init(AVCodecContext *avctx)
+{
+    OMXCodecContext *s = avctx->priv_data;
+    int ret = AVERROR_ENCODER_NOT_FOUND;
+    const char *role;
+    OMX_BUFFERHEADERTYPE *buffer;
+    OMX_ERRORTYPE err;
+
+#if CONFIG_OMX_RPI
+    s->input_zerocopy = 1;
+#endif
+
+    s->omx_context = omx_init(avctx, s->libname, s->libprefix);
+    if (!s->omx_context)
+        return AVERROR_ENCODER_NOT_FOUND;
+
+    pthread_mutex_init(&s->state_mutex, NULL);
+    pthread_cond_init(&s->state_cond, NULL);
+    pthread_mutex_init(&s->input_mutex, NULL);
+    pthread_cond_init(&s->input_cond, NULL);
+    pthread_mutex_init(&s->output_mutex, NULL);
+    pthread_cond_init(&s->output_cond, NULL);
+    s->mutex_cond_inited = 1;
+    s->avctx = avctx;
+    s->state = OMX_StateLoaded;
+    s->error = OMX_ErrorNone;
+
+    switch (avctx->codec->id) {
+    case AV_CODEC_ID_MPEG4:
+        role = "video_encoder.mpeg4";
+        break;
+    case AV_CODEC_ID_H264:
+        role = "video_encoder.avc";
+        break;
+    default:
+        return AVERROR(ENOSYS);
+    }
+
+    if ((ret = find_component(s->omx_context, avctx, role, s->component_name, sizeof(s->component_name))) < 0)
+        goto fail;
+
+    av_log(avctx, AV_LOG_INFO, "Using %s\n", s->component_name);
+
+    if ((ret = omx_component_init(avctx, role)) < 0)
+        goto fail;
+
+    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+        while (1) {
+            buffer = get_buffer(&s->output_mutex, &s->output_cond,
+                                &s->num_done_out_buffers, s->done_out_buffers, 1);
+            if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+                if ((ret = av_reallocp(&avctx->extradata, avctx->extradata_size + buffer->nFilledLen + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
+                    avctx->extradata_size = 0;
+                    goto fail;
+                }
+                memcpy(avctx->extradata + avctx->extradata_size, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen);
+                avctx->extradata_size += buffer->nFilledLen;
+                memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+            }
+            err = OMX_FillThisBuffer(s->handle, buffer);
+            if (err != OMX_ErrorNone) {
+                append_buffer(&s->output_mutex, &s->output_cond,
+                              &s->num_done_out_buffers, s->done_out_buffers, buffer);
+                av_log(avctx, AV_LOG_ERROR, "OMX_FillThisBuffer failed: %x\n", err);
+                ret = AVERROR_UNKNOWN;
+                goto fail;
+            }
+            if (avctx->codec->id == AV_CODEC_ID_H264) {
+                // For H.264, the extradata can be returned in two separate buffers
+                // (the videocore encoder on raspberry pi does this);
+                // therefore check that we have got both SPS and PPS before continuing.
+                int nals[32] = { 0 };
+                int i;
+                for (i = 0; i + 4 < avctx->extradata_size; i++) {
+                     if (!avctx->extradata[i + 0] &&
+                         !avctx->extradata[i + 1] &&
+                         !avctx->extradata[i + 2] &&
+                         avctx->extradata[i + 3] == 1) {
+                         nals[avctx->extradata[i + 4] & 0x1f]++;
+                     }
+                }
+                if (nals[NAL_SPS] && nals[NAL_PPS])
+                    break;
+            } else {
+                if (avctx->extradata_size > 0)
+                    break;
+            }
+        }
+    }
+
+    return 0;
+fail:
+    return ret;
+}
+
+
+static int omx_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+                            const AVFrame *frame, int *got_packet)
+{
+    OMXCodecContext *s = avctx->priv_data;
+    int ret = 0;
+    OMX_BUFFERHEADERTYPE* buffer;
+    OMX_ERRORTYPE err;
+
+    if (frame) {
+        uint8_t *dst[4];
+        int linesize[4];
+        int need_copy;
+        buffer = get_buffer(&s->input_mutex, &s->input_cond,
+                            &s->num_free_in_buffers, s->free_in_buffers, 1);
+
+        buffer->nFilledLen = av_image_fill_arrays(dst, linesize, buffer->pBuffer, avctx->pix_fmt, s->stride, s->plane_size, 1);
+
+        if (s->input_zerocopy) {
+            uint8_t *src[4] = { NULL };
+            int src_linesize[4];
+            av_image_fill_arrays(src, src_linesize, frame->data[0], avctx->pix_fmt, s->stride, s->plane_size, 1);
+            if (frame->linesize[0] == src_linesize[0] &&
+                frame->linesize[1] == src_linesize[1] &&
+                frame->linesize[2] == src_linesize[2] &&
+                frame->data[1] == src[1] &&
+                frame->data[2] == src[2]) {
+                // If the input frame happens to have all planes stored contiguously,
+                // with the right strides, just clone the frame and set the OMX
+                // buffer header to point to it
+                AVFrame *local = av_frame_clone(frame);
+                if (!local) {
+                    // Return the buffer to the queue so it's not lost
+                    append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer);
+                    return AVERROR(ENOMEM);
+                } else {
+                    buffer->pAppPrivate = local;
+                    buffer->pOutputPortPrivate = NULL;
+                    buffer->pBuffer = local->data[0];
+                    need_copy = 0;
+                }
+            } else {
+                // If not, we need to allocate a new buffer with the right
+                // size and copy the input frame into it.
+                uint8_t *buf = av_malloc(av_image_get_buffer_size(avctx->pix_fmt, s->stride, s->plane_size, 1));
+                if (!buf) {
+                    // Return the buffer to the queue so it's not lost
+                    append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer);
+                    return AVERROR(ENOMEM);
+                } else {
+                    buffer->pAppPrivate = buf;
+                    // Mark that pAppPrivate is an av_malloc'ed buffer, not an AVFrame
+                    buffer->pOutputPortPrivate = (void*) 1;
+                    buffer->pBuffer = buf;
+                    need_copy = 1;
+                    buffer->nFilledLen = av_image_fill_arrays(dst, linesize, buffer->pBuffer, avctx->pix_fmt, s->stride, s->plane_size, 1);
+                }
+            }
+        } else {
+            need_copy = 1;
+        }
+        if (need_copy)
+            av_image_copy(dst, linesize, (const uint8_t**) frame->data, frame->linesize, avctx->pix_fmt, avctx->width, avctx->height);
+        buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
+        buffer->nOffset = 0;
+        // Convert the timestamps to microseconds; some encoders can ignore
+        // the framerate and do VFR bit allocation based on timestamps.
+        buffer->nTimeStamp = to_omx_ticks(av_rescale_q(frame->pts, avctx->time_base, AV_TIME_BASE_Q));
+        err = OMX_EmptyThisBuffer(s->handle, buffer);
+        if (err != OMX_ErrorNone) {
+            append_buffer(&s->input_mutex, &s->input_cond, &s->num_free_in_buffers, s->free_in_buffers, buffer);
+            av_log(avctx, AV_LOG_ERROR, "OMX_EmptyThisBuffer failed: %x\n", err);
+            return AVERROR_UNKNOWN;
+        }
+        s->num_in_frames++;
+    }
+
+    while (!*got_packet && ret == 0) {
+        // Only wait for output if flushing and not all frames have been output
+        buffer = get_buffer(&s->output_mutex, &s->output_cond,
+                            &s->num_done_out_buffers, s->done_out_buffers,
+                            !frame && s->num_out_frames < s->num_in_frames);
+        if (!buffer)
+            break;
+
+        if (buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG && avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+            if ((ret = av_reallocp(&avctx->extradata, avctx->extradata_size + buffer->nFilledLen + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
+                avctx->extradata_size = 0;
+                goto end;
+            }
+            memcpy(avctx->extradata + avctx->extradata_size, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen);
+            avctx->extradata_size += buffer->nFilledLen;
+            memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+        } else {
+            if (buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME)
+                s->num_out_frames++;
+            if (!(buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) || !pkt->data) {
+                // If the output packet isn't preallocated, just concatenate everything in our
+                // own buffer
+                int newsize = s->output_buf_size + buffer->nFilledLen + AV_INPUT_BUFFER_PADDING_SIZE;
+                if ((ret = av_reallocp(&s->output_buf, newsize)) < 0) {
+                    s->output_buf_size = 0;
+                    goto end;
+                }
+                memcpy(s->output_buf + s->output_buf_size, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen);
+                s->output_buf_size += buffer->nFilledLen;
+                if (buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) {
+                    if ((ret = av_packet_from_data(pkt, s->output_buf, s->output_buf_size)) < 0) {
+                        av_freep(&s->output_buf);
+                        s->output_buf_size = 0;
+                        goto end;
+                    }
+                    s->output_buf = NULL;
+                    s->output_buf_size = 0;
+                }
+            } else {
+                // End of frame, and the caller provided a preallocated frame
+                if ((ret = ff_alloc_packet2(avctx, pkt, s->output_buf_size + buffer->nFilledLen, 0)) < 0) {
+                    av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n",
+                           (int)(s->output_buf_size + buffer->nFilledLen));
+                    goto end;
+                }
+                memcpy(pkt->data, s->output_buf, s->output_buf_size);
+                memcpy(pkt->data + s->output_buf_size, buffer->pBuffer + buffer->nOffset, buffer->nFilledLen);
+                av_freep(&s->output_buf);
+                s->output_buf_size = 0;
+            }
+            if (buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME) {
+                pkt->pts = av_rescale_q(from_omx_ticks(buffer->nTimeStamp), AV_TIME_BASE_Q, avctx->time_base);
+                // We don't currently enable B-frames for the encoders, so set
+                // pkt->dts = pkt->pts. (The calling code behaves worse if the encoder
+                // doesn't set the dts).
+                pkt->dts = pkt->pts;
+                if (buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME)
+                    pkt->flags |= AV_PKT_FLAG_KEY;
+                *got_packet = 1;
+            }
+        }
+end:
+        err = OMX_FillThisBuffer(s->handle, buffer);
+        if (err != OMX_ErrorNone) {
+            append_buffer(&s->output_mutex, &s->output_cond, &s->num_done_out_buffers, s->done_out_buffers, buffer);
+            av_log(avctx, AV_LOG_ERROR, "OMX_FillThisBuffer failed: %x\n", err);
+            ret = AVERROR_UNKNOWN;
+        }
+    }
+    return ret;
+}
+
+static av_cold int omx_encode_end(AVCodecContext *avctx)
+{
+    OMXCodecContext *s = avctx->priv_data;
+
+    cleanup(s);
+    return 0;
+}
+
+#define OFFSET(x) offsetof(OMXCodecContext, x)
+#define VDE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+#define VE  AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "omx_libname", "OpenMAX library name", OFFSET(libname), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
+    { "omx_libprefix", "OpenMAX library prefix", OFFSET(libprefix), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VDE },
+    { "zerocopy", "Try to avoid copying input frames if possible", OFFSET(input_zerocopy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
+    { NULL }
+};
+
+static const enum AVPixelFormat omx_encoder_pix_fmts[] = {
+    AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE
+};
+
+static const AVClass omx_mpeg4enc_class = {
+    .class_name = "mpeg4_omx",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+AVCodec ff_mpeg4_omx_encoder = {
+    .name             = "mpeg4_omx",
+    .long_name        = NULL_IF_CONFIG_SMALL("OpenMAX IL MPEG-4 video encoder"),
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_MPEG4,
+    .priv_data_size   = sizeof(OMXCodecContext),
+    .init             = omx_encode_init,
+    .encode2          = omx_encode_frame,
+    .close            = omx_encode_end,
+    .pix_fmts         = omx_encoder_pix_fmts,
+    .capabilities     = AV_CODEC_CAP_DELAY,
+    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
+    .priv_class       = &omx_mpeg4enc_class,
+};
+
+static const AVClass omx_h264enc_class = {
+    .class_name = "h264_omx",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+AVCodec ff_h264_omx_encoder = {
+    .name             = "h264_omx",
+    .long_name        = NULL_IF_CONFIG_SMALL("OpenMAX IL H.264 video encoder"),
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_H264,
+    .priv_data_size   = sizeof(OMXCodecContext),
+    .init             = omx_encode_init,
+    .encode2          = omx_encode_frame,
+    .close            = omx_encode_end,
+    .pix_fmts         = omx_encoder_pix_fmts,
+    .capabilities     = AV_CODEC_CAP_DELAY,
+    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
+    .priv_class       = &omx_h264enc_class,
+};
diff --git a/libavcodec/on2avc.c b/libavcodec/on2avc.c
index 62c71cc..3064c6f 100644
--- a/libavcodec/on2avc.c
+++ b/libavcodec/on2avc.c
@@ -21,8 +21,8 @@
  */
 
 #include "libavutil/channel_layout.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/float_dsp.h"
-#include "libavutil/internal.h"
 #include "avcodec.h"
 #include "bytestream.h"
 #include "fft.h"
diff --git a/libavcodec/options.c b/libavcodec/options.c
index ea2563b..d8e3dbf 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -89,7 +89,7 @@ static const AVClass av_codec_context_class = {
     .get_category            = get_category,
 };
 
-int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec)
+static int init_context_defaults(AVCodecContext *s, const AVCodec *codec)
 {
     int flags=0;
     memset(s, 0, sizeof(AVCodecContext));
@@ -146,6 +146,13 @@ int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec)
     return 0;
 }
 
+#if FF_API_GET_CONTEXT_DEFAULTS
+int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec)
+{
+    return init_context_defaults(s, codec);
+}
+#endif
+
 AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)
 {
     AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));
@@ -153,7 +160,7 @@ AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)
     if (!avctx)
         return NULL;
 
-    if(avcodec_get_context_defaults3(avctx, codec) < 0){
+    if (init_context_defaults(avctx, codec) < 0) {
         av_free(avctx);
         return NULL;
     }
@@ -179,6 +186,7 @@ void avcodec_free_context(AVCodecContext **pavctx)
     av_freep(pavctx);
 }
 
+#if FF_API_COPY_CONTEXT
 int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src)
 {
     const AVCodec *orig_codec = dest->codec;
@@ -225,6 +233,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
     dest->inter_matrix    = NULL;
     dest->rc_override     = NULL;
     dest->subtitle_header = NULL;
+    dest->hw_frames_ctx   = NULL;
 
 #define alloc_and_copy_or_fail(obj, size, pad) \
     if (src->obj && size > 0) { \
@@ -245,19 +254,27 @@ FF_ENABLE_DEPRECATION_WARNINGS
     av_assert0(dest->subtitle_header_size == src->subtitle_header_size);
 #undef alloc_and_copy_or_fail
 
+    if (src->hw_frames_ctx) {
+        dest->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
+        if (!dest->hw_frames_ctx)
+            goto fail;
+    }
+
     return 0;
 
 fail:
+    av_freep(&dest->subtitle_header);
     av_freep(&dest->rc_override);
     av_freep(&dest->intra_matrix);
     av_freep(&dest->inter_matrix);
     av_freep(&dest->extradata);
-    av_freep(&dest->subtitle_header);
+    av_buffer_unref(&dest->hw_frames_ctx);
     dest->subtitle_header_size = 0;
     dest->extradata_size = 0;
     av_opt_free(dest);
     return AVERROR(ENOMEM);
 }
+#endif
 
 const AVClass *avcodec_get_class(void)
 {
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index aa8bfac..adfbe72 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -90,6 +90,7 @@ static const AVOption avcodec_options[] = {
 {"showall", "Show all frames before the first keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_SHOW_ALL }, INT_MIN, INT_MAX, V|D, "flags2"},
 {"export_mvs", "export motion vectors through frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_EXPORT_MVS}, INT_MIN, INT_MAX, V|D, "flags2"},
 {"skip_manual", "do not skip samples and export skip information as frame side data", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_SKIP_MANUAL}, INT_MIN, INT_MAX, V|D, "flags2"},
+{"ass_ro_flush_noop", "do not reset ASS ReadOrder field on flush", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG2_RO_FLUSH_NOOP}, INT_MIN, INT_MAX, S|D, "flags2"},
 #if FF_API_MOTION_EST
 {"me_method", "set motion estimation method", OFFSET(me_method), AV_OPT_TYPE_INT, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method"},
 {"zero", "zero motion estimation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_ZERO }, INT_MIN, INT_MAX, V|E, "me_method" },
@@ -120,7 +121,7 @@ static const AVOption avcodec_options[] = {
 {"qmin", "minimum video quantizer scale (VBR)", OFFSET(qmin), AV_OPT_TYPE_INT, {.i64 = 2 }, -1, 69, V|E},
 {"qmax", "maximum video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.i64 = 31 }, -1, 1024, V|E},
 {"qdiff", "maximum difference between the quantizer scales (VBR)", OFFSET(max_qdiff), AV_OPT_TYPE_INT, {.i64 = 3 }, INT_MIN, INT_MAX, V|E},
-{"bf", "set maximum number of B frames between non-B-frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, -1, INT_MAX, V|E},
+{"bf", "set maximum number of B-frames between non-B-frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, -1, INT_MAX, V|E},
 {"b_qfactor", "QP factor between P- and B-frames", OFFSET(b_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E},
 #if FF_API_RC_STRATEGY
 {"rc_strategy", "ratecontrol method", OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
@@ -163,11 +164,11 @@ static const AVOption avcodec_options[] = {
 {"ms", "work around various bugs in Microsoft's broken decoders", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_MS }, INT_MIN, INT_MAX, V|D, "bug"},
 {"trunc", "truncated frames", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_TRUNCATED}, INT_MIN, INT_MAX, V|D, "bug"},
 {"strict", "how strictly to follow the standards", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
-{"very", "strictly conform to a older more strict version of the spec or reference software", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_VERY_STRICT }, INT_MIN, INT_MAX, V|D|E, "strict"},
-{"strict", "strictly conform to all the things in the spec no matter what the consequences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_STRICT }, INT_MIN, INT_MAX, V|D|E, "strict"},
-{"normal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_NORMAL }, INT_MIN, INT_MAX, V|D|E, "strict"},
-{"unofficial", "allow unofficial extensions", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_UNOFFICIAL }, INT_MIN, INT_MAX, V|D|E, "strict"},
-{"experimental", "allow non-standardized experimental things", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, V|D|E, "strict"},
+{"very", "strictly conform to a older more strict version of the spec or reference software", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_VERY_STRICT }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
+{"strict", "strictly conform to all the things in the spec no matter what the consequences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_STRICT }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
+{"normal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_NORMAL }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
+{"unofficial", "allow unofficial extensions", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_UNOFFICIAL }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
+{"experimental", "allow non-standardized experimental things", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, A|V|D|E, "strict"},
 {"b_qoffset", "QP offset between P- and B-frames", OFFSET(b_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E},
 {"err_detect", "set error detection flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 {"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
@@ -253,6 +254,7 @@ static const AVOption avcodec_options[] = {
 {"median", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PRED_MEDIAN }, INT_MIN, INT_MAX, V|E, "pred"},
 #endif
 {"aspect", "sample aspect ratio", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10, V|E},
+{"sar",    "sample aspect ratio", OFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 10, V|E},
 {"debug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, V|A|S|E|D, "debug"},
 {"pict", "picture info", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_PICT_INFO }, INT_MIN, INT_MAX, V|D, "debug"},
 {"rc", "rate control", 0, AV_OPT_TYPE_CONST, {.i64 = FF_DEBUG_RC }, INT_MIN, INT_MAX, V|E, "debug"},
@@ -519,6 +521,15 @@ static const AVOption avcodec_options[] = {
 {"do_nothing",  NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_DO_NOTHING},  INT_MIN, INT_MAX, S|D, "sub_charenc_mode"},
 {"auto",        NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC},   INT_MIN, INT_MAX, S|D, "sub_charenc_mode"},
 {"pre_decoder", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_PRE_DECODER}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"},
+#if FF_API_ASS_TIMING
+{"sub_text_format", "set decoded text subtitle format", OFFSET(sub_text_format), AV_OPT_TYPE_INT, {.i64 = FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS}, 0, 1, S|D, "sub_text_format"},
+#else
+{"sub_text_format", "set decoded text subtitle format", OFFSET(sub_text_format), AV_OPT_TYPE_INT, {.i64 = FF_SUB_TEXT_FMT_ASS}, 0, 1, S|D, "sub_text_format"},
+#endif
+{"ass",              NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_TEXT_FMT_ASS},              INT_MIN, INT_MAX, S|D, "sub_text_format"},
+#if FF_API_ASS_TIMING
+{"ass_with_timings", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS}, INT_MIN, INT_MAX, S|D, "sub_text_format"},
+#endif
 {"refcounted_frames", NULL, OFFSET(refcounted_frames), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, A|V|D },
 #if FF_API_SIDEDATA_ONLY_PKT
 {"side_data_only_packets", NULL, OFFSET(side_data_only_packets), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, A|V|E },
diff --git a/libavcodec/opus.c b/libavcodec/opus.c
index f2b8ecc..703d2e8 100644
--- a/libavcodec/opus.c
+++ b/libavcodec/opus.c
@@ -27,7 +27,7 @@
 #include <stdint.h>
 
 #include "libavutil/error.h"
-#include "libavutil/internal.h"
+#include "libavutil/ffmath.h"
 
 #include "opus.h"
 #include "vorbis.h"
@@ -265,7 +265,7 @@ int ff_opus_parse_packet(OpusPacket *pkt, const uint8_t *buf, int buf_size,
     } else {
         pkt->mode = OPUS_MODE_CELT;
         pkt->bandwidth = (pkt->config - 16) >> 2;
-        /* skip mediumband */
+        /* skip medium band */
         if (pkt->bandwidth)
             pkt->bandwidth++;
     }
@@ -397,7 +397,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
             return AVERROR_INVALIDDATA;
         }
 
-        /* check that we din't see this index yet */
+        /* check that we did not see this index yet */
         map->copy = 0;
         for (j = 0; j < i; j++)
             if (channel_map[channel_reorder(channels, j)] == idx) {
diff --git a/libavcodec/opus_silk.c b/libavcodec/opus_silk.c
index 73526f9..9c30b12 100644
--- a/libavcodec/opus_silk.c
+++ b/libavcodec/opus_silk.c
@@ -1323,7 +1323,7 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
         if (lag_absolute) {
             /* primary lag is coded absolute */
             int highbits, lowbits;
-            const uint16_t *model[] = {
+            static const uint16_t *model[] = {
                 silk_model_pitch_lowbits_nb, silk_model_pitch_lowbits_mb,
                 silk_model_pitch_lowbits_wb
             };
@@ -1357,11 +1357,11 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
         ltpfilter = opus_rc_getsymbol(rc, silk_model_ltp_filter);
         for (i = 0; i < s->subframes; i++) {
             int index, j;
-            const uint16_t *filter_sel[] = {
+            static const uint16_t *filter_sel[] = {
                 silk_model_ltp_filter0_sel, silk_model_ltp_filter1_sel,
                 silk_model_ltp_filter2_sel
             };
-            const int8_t (*filter_taps[])[5] = {
+            static const int8_t (*filter_taps[])[5] = {
                 silk_ltp_filter0_taps, silk_ltp_filter1_taps, silk_ltp_filter2_taps
             };
             index = opus_rc_getsymbol(rc, filter_sel[ltpfilter]);
diff --git a/libavcodec/parser.c b/libavcodec/parser.c
index d25d261..2c8fc69 100644
--- a/libavcodec/parser.c
+++ b/libavcodec/parser.c
@@ -141,6 +141,8 @@ int av_parser_parse2(AVCodecParserContext *s, AVCodecContext *avctx,
     int index, i;
     uint8_t dummy_buf[AV_INPUT_BUFFER_PADDING_SIZE];
 
+    av_assert1(avctx->codec_id != AV_CODEC_ID_NONE);
+
     /* Parsers only work for the specified codec ids. */
     av_assert1(avctx->codec_id == s->parser->codec_ids[0] ||
                avctx->codec_id == s->parser->codec_ids[1] ||
diff --git a/libavcodec/pcm-dvd.c b/libavcodec/pcm-dvd.c
index a78c05d..04c321e 100644
--- a/libavcodec/pcm-dvd.c
+++ b/libavcodec/pcm-dvd.c
@@ -33,7 +33,7 @@ typedef struct PCMDVDContext {
     int block_size;          // Size of a block of samples in bytes
     int last_block_size;     // Size of the last block of samples in bytes
     int samples_per_block;   // Number of samples per channel per block
-    int groups_per_block;    // Number of 20/24bit sample groups per block
+    int groups_per_block;    // Number of 20/24-bit sample groups per block
     uint8_t *extra_samples;  // Pointer to leftover samples from a frame
     int extra_sample_count;  // Number of leftover samples in the buffer
 } PCMDVDContext;
@@ -106,7 +106,7 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header)
                       avctx->sample_rate *
                       avctx->bits_per_coded_sample;
 
-    /* 4 samples form a group in 20/24bit PCM on DVD Video.
+    /* 4 samples form a group in 20/24-bit PCM on DVD Video.
      * A block is formed by the number of groups that are
      * needed to complete a set of samples for each channel. */
     if (avctx->bits_per_coded_sample == 16) {
diff --git a/libavcodec/pcm_tablegen.h b/libavcodec/pcm_tablegen.h
index 7269977..7ce147f 100644
--- a/libavcodec/pcm_tablegen.h
+++ b/libavcodec/pcm_tablegen.h
@@ -36,10 +36,7 @@
 
 #define         BIAS            (0x84)      /* Bias for linear code. */
 
-/*
- * alaw2linear() - Convert an A-law value to 16-bit linear PCM
- *
- */
+/* alaw2linear() - Convert an A-law value to 16-bit linear PCM */
 static av_cold int alaw2linear(unsigned char a_val)
 {
         int t;
diff --git a/libavcodec/pcxenc.c b/libavcodec/pcxenc.c
index f0ffedf..6135944 100644
--- a/libavcodec/pcxenc.c
+++ b/libavcodec/pcxenc.c
@@ -23,7 +23,7 @@
  * @file
  * PCX image encoder
  * @author Daniel Verkamp
- * @see http://www.qzx.com/pc-gpe/pcx.txt
+ * @see http://bespin.org/~qz/pc-gpe/pcx.txt
  */
 
 #include "avcodec.h"
diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c
index 133d08b..cef477d 100644
--- a/libavcodec/pgssubdec.c
+++ b/libavcodec/pgssubdec.c
@@ -354,7 +354,7 @@ static int parse_palette_segment(AVCodecContext *avctx,
         cb        = bytestream_get_byte(&buf);
         alpha     = bytestream_get_byte(&buf);
 
-        /* Default to BT.709 colorimetry. In case of <= 576 height use BT.601 */
+        /* Default to BT.709 colorspace. In case of <= 576 height use BT.601 */
         if (avctx->height <= 0 || avctx->height > 576) {
             YUV_TO_RGB1_CCIR_BT709(cb, cr);
         } else {
@@ -529,8 +529,6 @@ static int display_end_segment(AVCodecContext *avctx, void *data,
     }
     for (i = 0; i < ctx->presentation.object_count; i++) {
         PGSSubObject *object;
-        AVSubtitleRect *rect;
-        int j;
 
         sub->rects[i]  = av_mallocz(sizeof(*sub->rects[0]));
         if (!sub->rects[i]) {
@@ -597,11 +595,15 @@ static int display_end_segment(AVCodecContext *avctx, void *data,
 
 #if FF_API_AVPICTURE
 FF_DISABLE_DEPRECATION_WARNINGS
+{
+        AVSubtitleRect *rect;
+        int j;
         rect = sub->rects[i];
         for (j = 0; j < 4; j++) {
             rect->pict.data[j] = rect->data[j];
             rect->pict.linesize[j] = rect->linesize[j];
         }
+}
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
     }
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index 24318fb..36275ae 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -1258,7 +1258,7 @@ exit_loop:
         }
     }
 
-    /* handle p-frames only if a predecessor frame is available */
+    /* handle P-frames only if a predecessor frame is available */
     if (s->last_picture.f->data[0]) {
         if (   !(avpkt->flags & AV_PKT_FLAG_KEY) && avctx->codec_tag != AV_RL32("MPNG")
             && s->last_picture.f->width == p->width
diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c
index e9e8bc2..00c830e 100644
--- a/libavcodec/pngenc.c
+++ b/libavcodec/pngenc.c
@@ -766,7 +766,11 @@ static int apng_encode_frame(AVCodecContext *avctx, const AVFrame *pict,
 
             // Do disposal
             if (last_fctl_chunk.dispose_op != APNG_DISPOSE_OP_PREVIOUS) {
-                av_frame_copy(diffFrame, s->last_frame);
+                diffFrame->width = pict->width;
+                diffFrame->height = pict->height;
+                ret = av_frame_copy(diffFrame, s->last_frame);
+                if (ret < 0)
+                    goto fail;
 
                 if (last_fctl_chunk.dispose_op == APNG_DISPOSE_OP_BACKGROUND) {
                     for (y = last_fctl_chunk.y_offset; y < last_fctl_chunk.y_offset + last_fctl_chunk.height; ++y) {
@@ -778,7 +782,11 @@ static int apng_encode_frame(AVCodecContext *avctx, const AVFrame *pict,
                 if (!s->prev_frame)
                     continue;
 
-                av_frame_copy(diffFrame, s->prev_frame);
+                diffFrame->width = pict->width;
+                diffFrame->height = pict->height;
+                ret = av_frame_copy(diffFrame, s->prev_frame);
+                if (ret < 0)
+                    goto fail;
             }
 
             // Do inverse blending
diff --git a/libavcodec/pnm_parser.c b/libavcodec/pnm_parser.c
index a7d70b9..43dbfc7 100644
--- a/libavcodec/pnm_parser.c
+++ b/libavcodec/pnm_parser.c
@@ -66,6 +66,8 @@ retry:
         }
 #endif
         next = END_NOT_FOUND;
+    } else if (pnmctx.type < 4) {
+        next = END_NOT_FOUND;
     } else {
         next = pnmctx.bytestream - pnmctx.bytestream_start
                + av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1);
diff --git a/libavcodec/ppc/Makefile b/libavcodec/ppc/Makefile
index bd4f427..56a1398 100644
--- a/libavcodec/ppc/Makefile
+++ b/libavcodec/ppc/Makefile
@@ -4,13 +4,13 @@ OBJS-$(CONFIG_BLOCKDSP)                += ppc/blockdsp.o
 OBJS-$(CONFIG_FFT)                     += ppc/fft_init.o                \
                                           ppc/fft_altivec.o             \
                                           ppc/fft_vsx.o
+OBJS-$(CONFIG_FDCTDSP)                 += ppc/fdctdsp.o
 OBJS-$(CONFIG_FMTCONVERT)              += ppc/fmtconvert_altivec.o
 OBJS-$(CONFIG_H264CHROMA)              += ppc/h264chroma_init.o
 OBJS-$(CONFIG_H264DSP)                 += ppc/h264dsp.o ppc/hpeldsp_altivec.o
 OBJS-$(CONFIG_H264QPEL)                += ppc/h264qpel.o
 OBJS-$(CONFIG_HPELDSP)                 += ppc/hpeldsp_altivec.o
 OBJS-$(CONFIG_HUFFYUVDSP)              += ppc/huffyuvdsp_altivec.o
-OBJS-$(CONFIG_FDCTDSP)                 += ppc/fdctdsp.o
 OBJS-$(CONFIG_IDCTDSP)                 += ppc/idctdsp.o
 OBJS-$(CONFIG_ME_CMP)                  += ppc/me_cmp.o
 OBJS-$(CONFIG_MPEGAUDIODSP)            += ppc/mpegaudiodsp_altivec.o
@@ -18,6 +18,7 @@ OBJS-$(CONFIG_MPEGVIDEO)               += ppc/mpegvideo_altivec.o      \
                                           ppc/mpegvideodsp.o
 OBJS-$(CONFIG_MPEGVIDEOENC)            += ppc/mpegvideoencdsp.o
 OBJS-$(CONFIG_PIXBLOCKDSP)             += ppc/pixblockdsp.o
+OBJS-$(CONFIG_VC1DSP)                  += ppc/vc1dsp_altivec.o
 OBJS-$(CONFIG_VIDEODSP)                += ppc/videodsp_ppc.o
 OBJS-$(CONFIG_VP3DSP)                  += ppc/vp3dsp_altivec.o
 OBJS-$(CONFIG_VP8DSP)                  += ppc/vp8dsp_altivec.o
@@ -25,6 +26,5 @@ OBJS-$(CONFIG_VP8DSP)                  += ppc/vp8dsp_altivec.o
 # decoders/encoders
 OBJS-$(CONFIG_LLAUDDSP)                += ppc/lossless_audiodsp_altivec.o
 OBJS-$(CONFIG_SVQ1_ENCODER)            += ppc/svq1enc_altivec.o
-OBJS-$(CONFIG_VC1_DECODER)             += ppc/vc1dsp_altivec.o
 OBJS-$(CONFIG_VORBIS_DECODER)          += ppc/vorbisdsp_altivec.o
 OBJS-$(CONFIG_VP7_DECODER)             += ppc/vp8dsp_altivec.o
diff --git a/libavcodec/ppc/asm.S b/libavcodec/ppc/asm.S
index a3edeed..700aa0d 100644
--- a/libavcodec/ppc/asm.S
+++ b/libavcodec/ppc/asm.S
@@ -53,7 +53,7 @@ L(\name):
 .endm
 
 .macro movrel rd, sym, gp
-    ld      \rd, \sym at got(r2)
+    ld      \rd, \sym at got(2)
 .endm
 
 .macro get_got rd
diff --git a/libavcodec/ppc/dct-test.c b/libavcodec/ppc/dct-test.c
deleted file mode 100644
index 2328516..0000000
--- a/libavcodec/ppc/dct-test.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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 "config.h"
-
-#include "fdct.h"
-
-static const struct algo fdct_tab_arch[] = {
-#if HAVE_ALTIVEC
-    { "altivecfdct", ff_fdct_altivec, FF_IDCT_PERM_NONE, AV_CPU_FLAG_ALTIVEC },
-#endif
-    { 0 }
-};
-
-static const struct algo idct_tab_arch[] = {
-    { 0 }
-};
diff --git a/libavcodec/ppc/fft_altivec.S b/libavcodec/ppc/fft_altivec.S
index aab669e..e0149a4 100644
--- a/libavcodec/ppc/fft_altivec.S
+++ b/libavcodec/ppc/fft_altivec.S
@@ -40,7 +40,7 @@
 
 #include "config.h"
 
-#if HAVE_GNU_AS && HAVE_ALTIVEC
+#if HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN
 
 #include "asm.S"
 
@@ -354,14 +354,14 @@ fft_data:
 .macro fft_calc interleave
 extfunc ff_fft_calc\interleave\()_altivec
     mflr    r0
-    stp     r0, 2*PS(r1)
-    stpu    r1, -(160+16*PS)(r1)
+    stp     r0, 2*PS(1)
+    stpu    r1, -(160+16*PS)(1)
     get_got r11
     addi    r6, r1, 16*PS
     stvm    r6, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
     mfvrsave r0
-    stw     r0, 15*PS(r1)
-    li      r6, 0xfffffffc
+    stw     r0, 15*PS(1)
+    li      r6, -4  #0xfffffffc
     mtvrsave r6
 
     movrel  r6, fft_data, r11
@@ -372,7 +372,7 @@ extfunc ff_fft_calc\interleave\()_altivec
     movrel  r12, X(ff_cos_tabs), r11
 
     movrel  r6, fft_dispatch_tab\interleave\()_altivec, r11
-    lwz     r3, 0(r3)
+    lwz     r3, 0(3)
     subi    r3, r3, 2
     slwi    r3, r3, 2+ARCH_PPC64
     lpx     r3, r3, r6
@@ -382,10 +382,10 @@ extfunc ff_fft_calc\interleave\()_altivec
 
     addi    r6, r1, 16*PS
     lvm     r6, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29
-    lwz     r6, 15*PS(r1)
+    lwz     r6, 15*PS(1)
     mtvrsave r6
-    lp      r1, 0(r1)
-    lp      r0, 2*PS(r1)
+    lp      r1, 0(1)
+    lp      r0, 2*PS(1)
     mtlr    r0
     blr
 .endm
@@ -393,15 +393,15 @@ extfunc ff_fft_calc\interleave\()_altivec
 .macro DECL_FFT suffix, bits, n, n2, n4
 fft\n\suffix\()_altivec:
     mflr  r0
-    stp   r0,PS*(\bits-3)(r1)
+    stp   r0,PS*(\bits-3)(1)
     bl    fft\n2\()_altivec
     addi2 r3,\n*4
     bl    fft\n4\()_altivec
     addi2 r3,\n*2
     bl    fft\n4\()_altivec
     addi2 r3,\n*-6
-    lp    r0,PS*(\bits-3)(r1)
-    lp    r4,\bits*PS(r12)
+    lp    r0,PS*(\bits-3)(1)
+    lp    r4,\bits*PS(12)
     mtlr  r0
     li    r5,\n/16
     b     fft_pass\suffix\()_altivec
@@ -451,4 +451,4 @@ fft_dispatch_tab\suffix\()_altivec:
 DECL_FFTS 0
 DECL_FFTS 1, _interleave
 
-#endif /* HAVE_GNU_AS && HAVE_ALTIVEC */
+#endif /* HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN */
diff --git a/libavcodec/ppc/fft_init.c b/libavcodec/ppc/fft_init.c
index 675fa33..cbeaf98 100644
--- a/libavcodec/ppc/fft_init.c
+++ b/libavcodec/ppc/fft_init.c
@@ -147,7 +147,7 @@ static void imdct_calc_altivec(FFTContext *s, FFTSample *output, const FFTSample
         p1[k]    = vec_perm(b, b, vcprm(3,2,1,0));
     }
 }
-#endif /* HAVE_GNU_AS && HAVE_ALTIVEC */
+#endif /* HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN */
 
 av_cold void ff_fft_init_ppc(FFTContext *s)
 {
@@ -164,5 +164,5 @@ av_cold void ff_fft_init_ppc(FFTContext *s)
         s->imdct_calc = imdct_calc_altivec;
         s->imdct_half = imdct_half_altivec;
     }
-#endif /* HAVE_GNU_AS && HAVE_ALTIVEC */
+#endif /* HAVE_GNU_AS && HAVE_ALTIVEC && HAVE_BIGENDIAN */
 }
diff --git a/libavcodec/ppc/h264dsp.c b/libavcodec/ppc/h264dsp.c
index 4a048a1..1bc8058 100644
--- a/libavcodec/ppc/h264dsp.c
+++ b/libavcodec/ppc/h264dsp.c
@@ -19,13 +19,19 @@
  */
 
 #include "config.h"
+
+#include <stdint.h>
+#include <string.h>
+
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
 #include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
 #include "libavutil/ppc/cpu.h"
 #include "libavutil/ppc/types_altivec.h"
 #include "libavutil/ppc/util_altivec.h"
-#include "libavcodec/h264data.h"
+
+#include "libavcodec/h264.h"
 #include "libavcodec/h264dsp.h"
 
 #if HAVE_ALTIVEC
diff --git a/libavcodec/profiles.c b/libavcodec/profiles.c
index 94069fd..da745e1 100644
--- a/libavcodec/profiles.c
+++ b/libavcodec/profiles.c
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h
index 7e1f74d..c86c683 100644
--- a/libavcodec/profiles.h
+++ b/libavcodec/profiles.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -32,4 +31,4 @@ extern const AVProfile ff_mpeg4_video_profiles[];
 extern const AVProfile ff_vc1_profiles[];
 extern const AVProfile ff_vp9_profiles[];
 
-#endif
+#endif /* AVCODEC_PROFILES_H */
diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c
index 2d47a13..a3a1ebd 100644
--- a/libavcodec/proresdec2.c
+++ b/libavcodec/proresdec2.c
@@ -578,7 +578,7 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int
     if (ret < 0)
         return ret;
 
-    if (!(avctx->flags & AV_CODEC_FLAG_GRAY)) {
+    if (!(avctx->flags & AV_CODEC_FLAG_GRAY) && (u_data_size + v_data_size) > 0) {
         ret = decode_slice_chroma(avctx, slice, (uint16_t*)dest_u, chroma_stride,
                                   buf + y_data_size, u_data_size,
                                   qmat_chroma_scaled, log2_chroma_blocks_per_mb);
@@ -591,6 +591,15 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int
         if (ret < 0)
             return ret;
     }
+    else {
+        size_t mb_max_x = slice->mb_count << (mb_x_shift - 1);
+        for (size_t i = 0; i < 16; ++i)
+            for (size_t j = 0; j < mb_max_x; ++j) {
+                *(uint16_t*)(dest_u + (i * chroma_stride) + (j << 1)) = 511;
+                *(uint16_t*)(dest_v + (i * chroma_stride) + (j << 1)) = 511;
+            }
+    }
+
     /* decode alpha plane if available */
     if (ctx->alpha_info && pic->data[3] && a_data_size)
         decode_slice_alpha(ctx, (uint16_t*)dest_a, luma_stride,
diff --git a/libavcodec/psymodel.c b/libavcodec/psymodel.c
index 6274a49..2b5f111 100644
--- a/libavcodec/psymodel.c
+++ b/libavcodec/psymodel.c
@@ -120,7 +120,12 @@ av_cold struct FFPsyPreprocessContext* ff_psy_preprocess_init(AVCodecContext *av
                                                  FF_FILTER_MODE_LOWPASS, FILT_ORDER,
                                                  cutoff_coeff, 0.0, 0.0);
         if (ctx->fcoeffs) {
-            ctx->fstate = av_mallocz(sizeof(ctx->fstate[0]) * avctx->channels);
+            ctx->fstate = av_mallocz_array(sizeof(ctx->fstate[0]), avctx->channels);
+            if (!ctx->fstate) {
+                av_free(ctx->fcoeffs);
+                av_free(ctx);
+                return NULL;
+            }
             for (i = 0; i < avctx->channels; i++)
                 ctx->fstate[i] = ff_iir_filter_init_state(FILT_ORDER);
         }
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index b77dd1e..7ef5e9f 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -93,6 +93,8 @@ typedef struct PerThreadContext {
 
     const enum AVPixelFormat *available_formats; ///< Format array for get_format()
     enum AVPixelFormat result_format;            ///< get_format() result
+
+    int die;                        ///< Set when the thread should exit.
 } PerThreadContext;
 
 /**
@@ -111,8 +113,6 @@ typedef struct FrameThreadContext {
                                     * Set for the first N packets, where N is the number of threads.
                                     * While it is set, ff_thread_en/decode_frame won't return any results.
                                     */
-
-    int die;                       ///< Set when threads should exit.
 } FrameThreadContext;
 
 #define THREAD_SAFE_CALLBACKS(avctx) \
@@ -128,16 +128,15 @@ typedef struct FrameThreadContext {
 static attribute_align_arg void *frame_worker_thread(void *arg)
 {
     PerThreadContext *p = arg;
-    FrameThreadContext *fctx = p->parent;
     AVCodecContext *avctx = p->avctx;
     const AVCodec *codec = avctx->codec;
 
     pthread_mutex_lock(&p->mutex);
     while (1) {
-            while (p->state == STATE_INPUT_READY && !fctx->die)
+            while (p->state == STATE_INPUT_READY && !p->die)
                 pthread_cond_wait(&p->input_cond, &p->mutex);
 
-        if (fctx->die) break;
+        if (p->die) break;
 
         if (!codec->update_thread_context && THREAD_SAFE_CALLBACKS(avctx))
             ff_thread_finish_setup(avctx);
@@ -553,12 +552,11 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
             fctx->threads->avctx->internal->is_copy = 1;
         }
 
-    fctx->die = 1;
-
     for (i = 0; i < thread_count; i++) {
         PerThreadContext *p = &fctx->threads[i];
 
         pthread_mutex_lock(&p->mutex);
+        p->die = 1;
         pthread_cond_signal(&p->input_cond);
         pthread_mutex_unlock(&p->mutex);
 
diff --git a/libavcodec/pthread_internal.h b/libavcodec/pthread_internal.h
index 6a2f378..d2115cb 100644
--- a/libavcodec/pthread_internal.h
+++ b/libavcodec/pthread_internal.h
@@ -21,7 +21,7 @@
 
 #include "avcodec.h"
 
-/* H264 slice threading seems to be buggy with more than 16 threads,
+/* H.264 slice threading seems to be buggy with more than 16 threads,
  * limit the number of threads to 16 for automatic detection */
 #define MAX_AUTO_THREADS 16
 
diff --git a/libavcodec/qcelpdec.c b/libavcodec/qcelpdec.c
index adb3e82..b4afda2 100644
--- a/libavcodec/qcelpdec.c
+++ b/libavcodec/qcelpdec.c
@@ -603,7 +603,7 @@ static qcelp_packet_rate buf_size2bitrate(const int buf_size)
  *
  * @param avctx the AV codec context
  * @param buf_size length of the buffer
- * @param buf the bufffer
+ * @param buf the buffer
  *
  * @return the bitrate on success,
  *         I_F_Q  if the bitrate cannot be satisfactorily determined
diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c
index 0b6dcd6..074aafd 100644
--- a/libavcodec/qdm2.c
+++ b/libavcodec/qdm2.c
@@ -235,7 +235,7 @@ static int qdm2_get_se_vlc(const VLC *vlc, GetBitContext *gb, int depth)
 /**
  * QDM2 checksum
  *
- * @param data      pointer to data to be checksum'ed
+ * @param data      pointer to data to be checksummed
  * @param length    data length
  * @param value     checksum value
  *
@@ -635,7 +635,6 @@ static void fill_coding_method_array(sb_int8_array tone_level_idx,
 }
 
 /**
- *
  * Called by process_subpacket_11 to process more data from subpacket 11
  * with sb 0-8.
  * Called by process_subpacket_12 to process data from subpacket 12 with
@@ -1832,7 +1831,7 @@ static int qdm2_decode(QDM2Context *q, const uint8_t *in, int16_t *out)
 
     q->sub_packet = (q->sub_packet + 1) % 16;
 
-    /* clip and convert output float[] to 16bit signed samples */
+    /* clip and convert output float[] to 16-bit signed samples */
     for (i = 0; i < frame_size; i++) {
         int value = (int)q->output_buffer[i];
 
diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c
index 0a31b41..828cfea 100644
--- a/libavcodec/qdrw.c
+++ b/libavcodec/qdrw.c
@@ -281,10 +281,8 @@ static int decode_frame(AVCodecContext *avctx,
                 avpriv_request_sample(avctx, "Pack type %d", pack_type);
                 return AVERROR_PATCHWELCOME;
             }
-            if ((ret = ff_get_buffer(avctx, p, 0)) < 0) {
-                av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+            if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
                 return ret;
-            }
 
             /* jump to data */
             bytestream2_skip(&gbc, 30);
diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index 4c8e6b0..11d453d 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -187,22 +187,6 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
     if (ret < 0)
         return ret;
 
-    MFXQueryIMPL(qs->session, &impl);
-
-    switch (MFX_IMPL_BASETYPE(impl)) {
-    case MFX_IMPL_SOFTWARE:
-        desc = "software";
-        break;
-    case MFX_IMPL_HARDWARE:
-    case MFX_IMPL_HARDWARE2:
-    case MFX_IMPL_HARDWARE3:
-    case MFX_IMPL_HARDWARE4:
-        desc = "hardware accelerated";
-        break;
-    default:
-        desc = "unknown";
-    }
-
     if (load_plugins && *load_plugins) {
         while (*load_plugins) {
             mfxPluginUID uid;
@@ -235,6 +219,8 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs,
                 goto load_plugin_fail;
             }
 
+            if (*load_plugins)
+                load_plugins++;
 load_plugin_fail:
             av_freep(&plugin);
             if (err < 0)
@@ -242,6 +228,22 @@ load_plugin_fail:
         }
     }
 
+    MFXQueryIMPL(qs->session, &impl);
+
+    switch (MFX_IMPL_BASETYPE(impl)) {
+    case MFX_IMPL_SOFTWARE:
+        desc = "software";
+        break;
+    case MFX_IMPL_HARDWARE:
+    case MFX_IMPL_HARDWARE2:
+    case MFX_IMPL_HARDWARE3:
+    case MFX_IMPL_HARDWARE4:
+        desc = "hardware accelerated";
+        break;
+    default:
+        desc = "unknown";
+    }
+
     av_log(avctx, AV_LOG_VERBOSE,
            "Initialized an internal MFX session using %s implementation\n",
            desc);
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index c235e07..f289a2b 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -40,6 +40,8 @@
 
 #include "libavutil/frame.h"
 
+#include "avcodec.h"
+
 #define QSV_VERSION_MAJOR 1
 #define QSV_VERSION_MINOR 9
 
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 9125700..c17606d 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -142,7 +142,7 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q, AVPacket *avpkt
      */
     if (!q->async_fifo) {
         q->async_fifo = av_fifo_alloc((1 + 16) *
-                                      (sizeof(mfxSyncPoint) + sizeof(QSVFrame*)));
+                                      (sizeof(mfxSyncPoint*) + sizeof(QSVFrame*)));
         if (!q->async_fifo)
             return AVERROR(ENOMEM);
     }
@@ -297,6 +297,16 @@ static void close_decoder(QSVContext *q)
     if (q->session)
         MFXVideoDECODE_Close(q->session);
 
+    while (q->async_fifo && av_fifo_size(q->async_fifo)) {
+        QSVFrame *out_frame;
+        mfxSyncPoint *sync;
+
+        av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
+        av_fifo_generic_read(q->async_fifo, &sync,      sizeof(sync),      NULL);
+
+        av_freep(&sync);
+    }
+
     cur = q->work_frames;
     while (cur) {
         q->work_frames = cur->next;
@@ -316,7 +326,7 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
     QSVFrame *out_frame;
     mfxFrameSurface1 *insurf;
     mfxFrameSurface1 *outsurf;
-    mfxSyncPoint sync;
+    mfxSyncPoint *sync;
     mfxBitstream bs = { { { 0 } } };
     int ret;
     int n_out_frames;
@@ -349,13 +359,19 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
         bs.TimeStamp  = avpkt->pts;
     }
 
+    sync = av_mallocz(sizeof(*sync));
+    if (!sync) {
+        av_freep(&sync);
+        return AVERROR(ENOMEM);
+    }
+
     while (1) {
         ret = get_surface(avctx, q, &insurf);
         if (ret < 0)
             return ret;
         do {
             ret = MFXVideoDECODE_DecodeFrameAsync(q->session, flush ? NULL : &bs,
-                                                  insurf, &outsurf, &sync);
+                                                  insurf, &outsurf, sync);
             if (ret != MFX_WRN_DEVICE_BUSY)
                 break;
             av_usleep(500);
@@ -369,10 +385,11 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
             continue;
         }
 
-        if (sync) {
+        if (*sync) {
             QSVFrame *out_frame = find_frame(q, outsurf);
 
             if (!out_frame) {
+                av_freep(&sync);
                 av_log(avctx, AV_LOG_ERROR,
                        "The returned surface does not correspond to any frame\n");
                 return AVERROR_BUG;
@@ -383,6 +400,8 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
             av_fifo_generic_write(q->async_fifo, &sync,      sizeof(sync),      NULL);
 
             continue;
+        } else {
+            av_freep(&sync);
         }
         if (MFX_ERR_MORE_SURFACE != ret && ret < 0)
             break;
@@ -390,7 +409,7 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
 
     /* make sure we do not enter an infinite loop if the SDK
      * did not consume any data and did not return anything */
-    if (!sync && !bs.DataOffset && !flush) {
+    if (!*sync && !bs.DataOffset && !flush) {
         av_log(avctx, AV_LOG_WARNING, "A decode call did not consume any data\n");
         bs.DataOffset = avpkt->size;
     }
@@ -404,6 +423,7 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
     }
 
     if (MFX_ERR_MORE_DATA!=ret && ret < 0) {
+        av_freep(&sync);
         av_log(avctx, AV_LOG_ERROR, "Error %d during QSV decoding.\n", ret);
         return ff_qsv_error(ret);
     }
@@ -417,9 +437,11 @@ static int do_qsv_decode(AVCodecContext *avctx, QSVContext *q,
         out_frame->queued = 0;
 
         do {
-            ret = MFXVideoCORE_SyncOperation(q->session, sync, 1000);
+            ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000);
         } while (ret == MFX_WRN_IN_EXECUTION);
 
+        av_freep(&sync);
+
         src_frame = out_frame->frame;
 
         ret = av_frame_ref(frame, src_frame);
diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c
index a396f31..fda827c 100644
--- a/libavcodec/qsvdec_h2645.c
+++ b/libavcodec/qsvdec_h2645.c
@@ -82,9 +82,11 @@ static av_cold int qsv_decode_init(AVCodecContext *avctx)
         }
     }
 
-    if (avctx->codec_id == AV_CODEC_ID_H264)
+    if (avctx->codec_id == AV_CODEC_ID_H264) {
         s->bsf = av_bitstream_filter_init("h264_mp4toannexb");
-    else
+        //regarding ticks_per_frame description, should be 2 for h.264:
+        avctx->ticks_per_frame = 2;
+    } else
         s->bsf = av_bitstream_filter_init("hevc_mp4toannexb");
     if (!s->bsf) {
         ret = AVERROR(ENOMEM);
diff --git a/libavcodec/qsvdec_mpeg2.c b/libavcodec/qsvdec_mpeg2.c
index d9052e0..70ccbc5 100644
--- a/libavcodec/qsvdec_mpeg2.c
+++ b/libavcodec/qsvdec_mpeg2.c
@@ -1,5 +1,5 @@
 /*
- * Intel MediaSDK QSV based MPEG2 video decoder
+ * Intel MediaSDK QSV based MPEG-2 video decoder
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index 3bac8cf..f56cb61 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -460,8 +460,14 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q)
     if (avctx->codec_id != AV_CODEC_ID_HEVC) {
         q->extco.Header.BufferId      = MFX_EXTBUFF_CODING_OPTION;
         q->extco.Header.BufferSz      = sizeof(q->extco);
-        q->extco.CAVLC                = avctx->coder_type == FF_CODER_TYPE_VLC ?
-                                        MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
+#if FF_API_CODER_TYPE
+FF_DISABLE_DEPRECATION_WARNINGS
+        if (avctx->coder_type != 0)
+            q->cavlc = avctx->coder_type == FF_CODER_TYPE_VLC;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+        q->extco.CAVLC = q->cavlc ? MFX_CODINGOPTION_ON
+                                  : MFX_CODINGOPTION_UNKNOWN;
 
         q->extco.PicTimingSEI         = q->pic_timing_sei ?
                                         MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
@@ -676,7 +682,7 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
     q->param.AsyncDepth = q->async_depth;
 
     q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
-                                  (sizeof(AVPacket) + sizeof(mfxSyncPoint) + sizeof(mfxBitstream*)));
+                                  (sizeof(AVPacket) + sizeof(mfxSyncPoint*) + sizeof(mfxBitstream*)));
     if (!q->async_fifo)
         return AVERROR(ENOMEM);
 
@@ -775,9 +781,7 @@ static void free_encoder_ctrl_payloads(mfxEncodeCtrl* enc_ctrl)
     if (enc_ctrl) {
         int i;
         for (i = 0; i < enc_ctrl->NumPayload && i < QSV_MAX_ENC_PAYLOAD; i++) {
-            mfxPayload* pay = enc_ctrl->Payload[i];
-            av_free(enc_ctrl->Payload[i]->Data);
-            av_free(pay);
+            av_free(enc_ctrl->Payload[i]);
         }
         enc_ctrl->NumPayload = 0;
     }
@@ -920,7 +924,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
     mfxBitstream *bs;
 
     mfxFrameSurface1 *surf = NULL;
-    mfxSyncPoint sync      = NULL;
+    mfxSyncPoint *sync      = NULL;
     QSVFrame *qsv_frame = NULL;
     mfxEncodeCtrl* enc_ctrl = NULL;
     int ret;
@@ -955,8 +959,15 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
         q->set_encode_ctrl_cb(avctx, frame, &qsv_frame->enc_ctrl);
     }
 
+    sync = av_mallocz(sizeof(*sync));
+    if (!sync) {
+        av_freep(&bs);
+        av_packet_unref(&new_pkt);
+        return AVERROR(ENOMEM);
+    }
+
     do {
-        ret = MFXVideoENCODE_EncodeFrameAsync(q->session, enc_ctrl, surf, bs, &sync);
+        ret = MFXVideoENCODE_EncodeFrameAsync(q->session, enc_ctrl, surf, bs, sync);
         if (ret == MFX_WRN_DEVICE_BUSY) {
             av_usleep(500);
             continue;
@@ -985,6 +996,7 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q,
         av_fifo_generic_write(q->async_fifo, &sync,    sizeof(sync),    NULL);
         av_fifo_generic_write(q->async_fifo, &bs,      sizeof(bs),    NULL);
     } else {
+        av_freep(&sync);
         av_packet_unref(&new_pkt);
         av_freep(&bs);
     }
@@ -1005,14 +1017,14 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
         (!frame && av_fifo_size(q->async_fifo))) {
         AVPacket new_pkt;
         mfxBitstream *bs;
-        mfxSyncPoint sync;
+        mfxSyncPoint *sync;
 
         av_fifo_generic_read(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
         av_fifo_generic_read(q->async_fifo, &sync,    sizeof(sync),    NULL);
         av_fifo_generic_read(q->async_fifo, &bs,      sizeof(bs),      NULL);
 
         do {
-            ret = MFXVideoCORE_SyncOperation(q->session, sync, 1000);
+            ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000);
         } while (ret == MFX_WRN_IN_EXECUTION);
 
         new_pkt.dts  = av_rescale_q(bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base);
@@ -1035,6 +1047,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
         av_freep(&bs);
+        av_freep(&sync);
 
         if (pkt->data) {
             if (pkt->size < new_pkt.size) {
@@ -1081,13 +1094,14 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
 
     while (q->async_fifo && av_fifo_size(q->async_fifo)) {
         AVPacket pkt;
-        mfxSyncPoint sync;
+        mfxSyncPoint *sync;
         mfxBitstream *bs;
 
         av_fifo_generic_read(q->async_fifo, &pkt,  sizeof(pkt),  NULL);
         av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
         av_fifo_generic_read(q->async_fifo, &bs,   sizeof(bs),   NULL);
 
+        av_freep(&sync);
         av_freep(&bs);
         av_packet_unref(&pkt);
     }
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 806dc06..2d7bd32 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -69,6 +69,7 @@
 { "adaptive_i",     "Adaptive I-frame placement",             OFFSET(qsv.adaptive_i),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 { "adaptive_b",     "Adaptive B-frame placement",             OFFSET(qsv.adaptive_b),     AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
 { "b_strategy",     "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy),    AV_OPT_TYPE_INT, { .i64 = -1 }, -1,          1, VE },                         \
+{ "cavlc",          "Enable CAVLC",                           OFFSET(qsv.cavlc),          AV_OPT_TYPE_INT, { .i64 = 0 },   0,          1, VE },                         \
 
 typedef int SetEncodeCtrlCB (AVCodecContext *avctx,
                              const AVFrame *frame, mfxEncodeCtrl* enc_ctrl);
@@ -129,6 +130,7 @@ typedef struct QSVEncContext {
     int adaptive_i;
     int adaptive_b;
     int b_strategy;
+    int cavlc;
 
     int int_ref_type;
     int int_ref_cycle_size;
diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c
index 66e5ee8..3fb5ca3 100644
--- a/libavcodec/qsvenc_h264.c
+++ b/libavcodec/qsvenc_h264.c
@@ -43,63 +43,33 @@ typedef struct QSVH264EncContext {
 static int qsv_h264_set_encode_ctrl(AVCodecContext *avctx,
                                     const AVFrame *frame, mfxEncodeCtrl* enc_ctrl)
 {
-    AVFrameSideData *side_data = NULL;
     QSVH264EncContext *qh264 = avctx->priv_data;
     QSVEncContext *q = &qh264->qsv;
 
     if (q->a53_cc && frame) {
-        side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC);
-        if (side_data) {
-
-            int sei_payload_size = 0;
-            mfxU8* sei_data = NULL;
-            mfxPayload* payload = NULL;
-
-            sei_payload_size = side_data->size + 13;
-
-            sei_data = av_mallocz(sei_payload_size);
-            if (!sei_data) {
-                av_log(avctx, AV_LOG_ERROR, "No memory for CC, skipping...\n");
-                return AVERROR(ENOMEM);
-            }
-
-            // SEI header
-            sei_data[0] = 4;
-            sei_data[1] = sei_payload_size - 2; // size of SEI data
-
-            // country code
-            sei_data[2] = 181;
-            sei_data[3] = 0;
-            sei_data[4] = 49;
-
-            // ATSC_identifier - using 'GA94' only
-            AV_WL32(sei_data + 5,
-                MKTAG('G', 'A', '9', '4'));
-            sei_data[9] = 3;
-            sei_data[10] =
-                ((side_data->size/3) & 0x1f) | 0xC0;
-
-            sei_data[11] = 0xFF; // reserved
-
-            memcpy(sei_data + 12, side_data->data, side_data->size);
-
-            sei_data[side_data->size+12] = 255;
-
-            payload = av_mallocz(sizeof(mfxPayload));
-            if (!payload) {
-                av_log(avctx, AV_LOG_ERROR, "No memory, skipping captions\n");
-                av_freep(&sei_data);
-                return AVERROR(ENOMEM);
-            }
-            payload->BufSize = side_data->size + 13;
-            payload->NumBit = payload->BufSize * 8;
-            payload->Type = 4;
-            payload->Data = sei_data;
-
-            enc_ctrl->NumExtParam = 0;
-            enc_ctrl->NumPayload = 1;
-            enc_ctrl->Payload[0] = payload;
-        }
+        mfxPayload* payload;
+        mfxU8* sei_data;
+        size_t sei_size;
+        int res;
+
+        res = ff_alloc_a53_sei(frame, sizeof(mfxPayload) + 2, (void**)&payload, &sei_size);
+        if (res < 0)
+            return res;
+
+        sei_data = (mfxU8*)(payload + 1);
+        // SEI header
+        sei_data[0] = 4;
+        sei_data[1] = (mfxU8)sei_size; // size of SEI data
+        // SEI data filled in by ff_alloc_a53_sei
+
+        payload->BufSize = sei_size + 2;
+        payload->NumBit = payload->BufSize * 8;
+        payload->Type = 4;
+        payload->Data = sei_data;
+
+        enc_ctrl->NumExtParam = 0;
+        enc_ctrl->NumPayload = 1;
+        enc_ctrl->Payload[0] = payload;
     }
     return 0;
 }
diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
index 30fde72..1d1e801 100644
--- a/libavcodec/qsvenc_hevc.c
+++ b/libavcodec/qsvenc_hevc.c
@@ -31,6 +31,7 @@
 #include "bytestream.h"
 #include "get_bits.h"
 #include "hevc.h"
+#include "h2645_parse.h"
 #include "internal.h"
 #include "qsv.h"
 #include "qsv_internal.h"
@@ -54,7 +55,7 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx)
     PutByteContext pbc;
 
     GetBitContext gb;
-    HEVCNAL sps_nal = { NULL };
+    H2645NAL sps_nal = { NULL };
     HEVCSPS sps = { 0 };
     HEVCVPS vps = { 0 };
     uint8_t vps_buf[128], vps_rbsp_buf[128];
@@ -68,7 +69,7 @@ static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx)
     }
 
     /* parse the SPS */
-    ret = ff_hevc_extract_rbsp(NULL, avctx->extradata + 4, avctx->extradata_size - 4, &sps_nal);
+    ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 4, &sps_nal);
     if (ret < 0) {
         av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n");
         return ret;
diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c
index 3f482f4..d9d27f0 100644
--- a/libavcodec/qtrle.c
+++ b/libavcodec/qtrle.c
@@ -1,6 +1,6 @@
 /*
  * Quicktime Animation (RLE) Video Decoder
- * Copyright (c) 2004 The FFmpeg Project
+ * Copyright (C) 2004 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c
index a4ed85a..cdd864b 100644
--- a/libavcodec/qtrleenc.c
+++ b/libavcodec/qtrleenc.c
@@ -138,7 +138,7 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui
     int i;
     signed char rlecode;
 
-    /* This will be the number of pixels equal to the preivous frame one's
+    /* This will be the number of pixels equal to the previous frame one's
      * starting from the ith pixel */
     unsigned int skipcount;
     /* This will be the number of consecutive equal pixels in the current
@@ -264,7 +264,7 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui
         prev_line -= s->pixel_size;
     }
 
-    /* Good ! Now we have the best sequence for this line, let's output it */
+    /* Good! Now we have the best sequence for this line, let's output it. */
 
     /* We do a special case for the first pixel so that we avoid testing it in
      * the whole loop */
@@ -363,7 +363,6 @@ static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                               const AVFrame *pict, int *got_packet)
 {
     QtrleEncContext * const s = avctx->priv_data;
-    enum AVPictureType pict_type;
     int ret;
 
     if ((ret = ff_alloc_packet2(avctx, pkt, s->max_buf_size, 0)) < 0)
@@ -371,11 +370,9 @@ static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 
     if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) {
         /* I-Frame */
-        pict_type = AV_PICTURE_TYPE_I;
         s->key_frame = 1;
     } else {
         /* P-Frame */
-        pict_type = AV_PICTURE_TYPE_P;
         s->key_frame = 0;
     }
 
@@ -392,7 +389,7 @@ static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 #if FF_API_CODED_FRAME
 FF_DISABLE_DEPRECATION_WARNINGS
     avctx->coded_frame->key_frame = s->key_frame;
-    avctx->coded_frame->pict_type = pict_type;
+    avctx->coded_frame->pict_type = s->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
diff --git a/libavcodec/ra144.c b/libavcodec/ra144.c
index 696a49e..ceec32d 100644
--- a/libavcodec/ra144.c
+++ b/libavcodec/ra144.c
@@ -1,6 +1,6 @@
 /*
  * Real Audio 1.0 (14.4K)
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/ra144.h b/libavcodec/ra144.h
index df74790..19a4ce0 100644
--- a/libavcodec/ra144.h
+++ b/libavcodec/ra144.h
@@ -1,6 +1,6 @@
 /*
  * Real Audio 1.0 (14.4K)
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/ra144enc.c b/libavcodec/ra144enc.c
index 32755d2..d3a7fff 100644
--- a/libavcodec/ra144enc.c
+++ b/libavcodec/ra144enc.c
@@ -128,7 +128,7 @@ static void orthogonalize(float *v, const float *u)
 
 /**
  * Calculate match score and gain of an LPC-filtered vector with respect to
- * input data, possibly othogonalizing it to up to 2 other vectors
+ * input data, possibly orthogonalizing it to up to two other vectors.
  *
  * @param work array used to calculate the filtered vector
  * @param coefs coefficients of the LPC filter
@@ -229,8 +229,8 @@ static int adaptive_cb_search(const int16_t *adapt_cb, float *work,
 
 /**
  * Find the best vector of a fixed codebook by applying an LPC filter to
- * codebook entries, possibly othogonalizing them to up to 2 other vectors and
- * matching the results with input data
+ * codebook entries, possibly orthogonalizing them to up to two other vectors
+ * and matching the results with input data.
  *
  * @param work array used to calculate the filtered vectors
  * @param coefs coefficients of the LPC filter
diff --git a/libavcodec/ra288.c b/libavcodec/ra288.c
index 8f5a7f2..e141bb3 100644
--- a/libavcodec/ra288.c
+++ b/libavcodec/ra288.c
@@ -1,6 +1,6 @@
 /*
  * RealAudio 2.0 (28.8K)
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/ra288.h b/libavcodec/ra288.h
index d30e49a..fa0b528 100644
--- a/libavcodec/ra288.h
+++ b/libavcodec/ra288.h
@@ -1,6 +1,6 @@
 /*
  * RealAudio 2.0 (28.8K)
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/ralf.c b/libavcodec/ralf.c
index 8cd9f88..3f7953c 100644
--- a/libavcodec/ralf.c
+++ b/libavcodec/ralf.c
@@ -479,7 +479,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr,
     init_get_bits(&gb, src + 2, table_size);
     ctx->num_blocks = 0;
     while (get_bits_left(&gb) > 0) {
-        ctx->block_size[ctx->num_blocks] = get_bits(&gb, 15);
+        ctx->block_size[ctx->num_blocks] = get_bits(&gb, 13 + avctx->channels);
         if (get_bits1(&gb)) {
             ctx->block_pts[ctx->num_blocks] = get_bits(&gb, 9);
         } else {
diff --git a/libavcodec/rangecoder.c b/libavcodec/rangecoder.c
index 200217a..9c6ef75 100644
--- a/libavcodec/rangecoder.c
+++ b/libavcodec/rangecoder.c
@@ -28,7 +28,6 @@
  *     G. N. N. Martin                  Presented in March 1979 to the Video &
  *                                      Data Recording Conference,
  *     IBM UK Scientific Center         held in Southampton July 24-27 1979."
- *
  */
 
 #include <string.h>
@@ -57,7 +56,7 @@ av_cold void ff_init_range_decoder(RangeCoder *c, const uint8_t *buf,
     /* cast to avoid compiler warning */
     ff_init_range_encoder(c, (uint8_t *)buf, buf_size);
 
-    c->low = AV_RB16(c->bytestream);
+    c->low         = AV_RB16(c->bytestream);
     c->bytestream += 2;
 }
 
@@ -115,48 +114,3 @@ int ff_rac_terminate(RangeCoder *c)
 
     return c->bytestream - c->bytestream_start;
 }
-
-#ifdef TEST
-#define SIZE 10240
-
-#include "libavutil/lfg.h"
-#include "libavutil/log.h"
-
-static uint8_t b[9 * SIZE];
-static uint8_t r[9 * SIZE];
-
-int main(void)
-{
-    RangeCoder c;
-    int i;
-    uint8_t state[10];
-    AVLFG prng;
-
-    av_lfg_init(&prng, 1);
-
-    ff_init_range_encoder(&c, b, SIZE);
-    ff_build_rac_states(&c, (1LL << 32) / 20, 128 + 64 + 32 + 16);
-
-    memset(state, 128, sizeof(state));
-
-    for (i = 0; i < SIZE; i++)
-        r[i] = av_lfg_get(&prng) % 7;
-
-    for (i = 0; i < SIZE; i++)
-        put_rac(&c, state, r[i] & 1);
-
-    ff_rac_terminate(&c);
-
-    ff_init_range_decoder(&c, b, SIZE);
-
-    memset(state, 128, sizeof(state));
-
-    for (i = 0; i < SIZE; i++)
-        if ((r[i] & 1) != get_rac(&c, state)) {
-            av_log(NULL, AV_LOG_ERROR, "rac failure at %d\n", i);
-            return 1;
-        }
-
-    return 0;
-}
-#endif /* TEST */
diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c
index 6c2b4af..3a8ac22 100644
--- a/libavcodec/ratecontrol.c
+++ b/libavcodec/ratecontrol.c
@@ -182,8 +182,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
             return AVERROR(ENOMEM);
         rcc->num_entries = i;
 
-        /* init all to skipped p frames
-         * (with b frames we might have a not encoded frame at the end FIXME) */
+        /* init all to skipped P-frames
+         * (with B-frames we might have a not encoded frame at the end FIXME) */
         for (i = 0; i < rcc->num_entries; i++) {
             RateControlEntry *rce = &rcc->entry[i];
 
@@ -203,7 +203,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
 
             next = strchr(p, ';');
             if (next) {
-                (*next) = 0; // sscanf in unbelievably slow on looong strings // FIXME copy / do not write
+                (*next) = 0; // sscanf is unbelievably slow on looong strings // FIXME copy / do not write
                 next++;
             }
             e = sscanf(p, " in:%d ", &picture_number);
@@ -652,9 +652,9 @@ static void adaptive_quantization(MpegEncContext *s, double q)
         int mb_distance;
         float mb_factor = 0.0;
         if (spat_cplx < 4)
-            spat_cplx = 4;              // FIXME finetune
+            spat_cplx = 4;              // FIXME fine-tune
         if (temp_cplx < 4)
-            temp_cplx = 4;              // FIXME finetune
+            temp_cplx = 4;              // FIXME fine-tune
 
         if ((s->mb_type[mb_xy] & CANDIDATE_MB_TYPE_INTRA)) { // FIXME hq mode
             cplx   = spat_cplx;
diff --git a/libavcodec/ratecontrol.h b/libavcodec/ratecontrol.h
index eeb4bb9..c15f9e2 100644
--- a/libavcodec/ratecontrol.h
+++ b/libavcodec/ratecontrol.h
@@ -68,7 +68,7 @@ typedef struct RateControlContext{
     double short_term_qsum;       ///< sum of recent qscales
     double short_term_qcount;     ///< count of recent qscales
     double pass1_rc_eq_output_sum;///< sum of the output of the rc equation, this is used for normalization
-    double pass1_wanted_bits;     ///< bits which should have been outputed by the pass1 code (including complexity init)
+    double pass1_wanted_bits;     ///< bits which should have been output by the pass1 code (including complexity init)
     double last_qscale;
     double last_qscale_for[5];    ///< last qscale for a specific pict type, used for max_diff & ipb factor stuff
     int64_t last_mc_mb_var_sum;
diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c
index 287be96..765e567 100644
--- a/libavcodec/rawdec.c
+++ b/libavcodec/rawdec.c
@@ -128,10 +128,6 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx)
         avctx->pix_fmt   == AV_PIX_FMT_YUYV422)
         context->is_yuv2 = 1;
 
-    /* Temporary solution until PAL8 is implemented in nut */
-    if (context->is_pal8 && avctx->bits_per_coded_sample == 1)
-        avctx->pix_fmt = AV_PIX_FMT_NONE;
-
     return 0;
 }
 
@@ -206,21 +202,6 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame,
         return AVERROR_INVALIDDATA;
     }
 
-    /* Temporary solution until PAL8 is implemented in nut */
-    if (avctx->pix_fmt == AV_PIX_FMT_NONE &&
-        avctx->bits_per_coded_sample == 1 &&
-        avctx->frame_number == 0 &&
-        context->palette &&
-        AV_RB64(context->palette->data) == 0xFFFFFFFF00000000
-    ) {
-        const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
-        if (!pal) {
-            avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
-            context->is_pal8 = 0;
-            context->is_mono = 1;
-        } else
-            avctx->pix_fmt = AV_PIX_FMT_PAL8;
-    }
     desc = av_pix_fmt_desc_get(avctx->pix_fmt);
 
     if ((avctx->bits_per_coded_sample == 8 || avctx->bits_per_coded_sample == 4
@@ -384,7 +365,6 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame,
     if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
         const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE,
                                                      NULL);
-
         if (pal) {
             av_buffer_unref(&context->palette);
             context->palette = av_buffer_alloc(AVPALETTE_SIZE);
@@ -394,14 +374,22 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame,
             }
             memcpy(context->palette->data, pal, AVPALETTE_SIZE);
             frame->palette_has_changed = 1;
+        } else if (context->is_nut_pal8) {
+            int vid_size = avctx->width * avctx->height;
+            if (avpkt->size - vid_size) {
+                pal = avpkt->data + vid_size;
+                memcpy(context->palette->data, pal, avpkt->size - vid_size);
+                frame->palette_has_changed = 1;
+            }
         }
     }
 
-    if ((avctx->pix_fmt==AV_PIX_FMT_BGR24    ||
-        avctx->pix_fmt==AV_PIX_FMT_GRAY8    ||
-        avctx->pix_fmt==AV_PIX_FMT_RGB555LE ||
-        avctx->pix_fmt==AV_PIX_FMT_RGB555BE ||
-        avctx->pix_fmt==AV_PIX_FMT_RGB565LE ||
+    if ((avctx->pix_fmt==AV_PIX_FMT_RGB24    ||
+        avctx->pix_fmt==AV_PIX_FMT_BGR24     ||
+        avctx->pix_fmt==AV_PIX_FMT_GRAY8     ||
+        avctx->pix_fmt==AV_PIX_FMT_RGB555LE  ||
+        avctx->pix_fmt==AV_PIX_FMT_RGB555BE  ||
+        avctx->pix_fmt==AV_PIX_FMT_RGB565LE  ||
         avctx->pix_fmt==AV_PIX_FMT_MONOWHITE ||
         avctx->pix_fmt==AV_PIX_FMT_MONOBLACK ||
         avctx->pix_fmt==AV_PIX_FMT_PAL8) &&
diff --git a/libavcodec/realtextdec.c b/libavcodec/realtextdec.c
index 870953b..5084781 100644
--- a/libavcodec/realtextdec.c
+++ b/libavcodec/realtextdec.c
@@ -61,13 +61,12 @@ static int realtext_decode_frame(AVCodecContext *avctx,
     int ret = 0;
     AVSubtitle *sub = data;
     const char *ptr = avpkt->data;
+    FFASSDecoderContext *s = avctx->priv_data;
     AVBPrint buf;
 
     av_bprint_init(&buf, 0, 4096);
-    // note: no need to rescale pts & duration since they are in the same
-    // timebase as ASS (1/100)
     if (ptr && avpkt->size > 0 && !rt_event_to_ass(&buf, ptr))
-        ret = ff_ass_add_rect_bprint(sub, &buf, avpkt->pts, avpkt->duration);
+        ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL);
     av_bprint_finalize(&buf, NULL);
     if (ret < 0)
         return ret;
@@ -82,4 +81,6 @@ AVCodec ff_realtext_decoder = {
     .id             = AV_CODEC_ID_REALTEXT,
     .decode         = realtext_decode_frame,
     .init           = ff_ass_subtitle_header_default,
+    .flush          = ff_ass_decoder_flush,
+    .priv_data_size = sizeof(FFASSDecoderContext),
 };
diff --git a/libavcodec/rectangle.h b/libavcodec/rectangle.h
index 594a760..df7c18a 100644
--- a/libavcodec/rectangle.h
+++ b/libavcodec/rectangle.h
@@ -65,7 +65,7 @@ static av_always_inline void fill_rectangle(void *vp, int w, int h, int stride,
         *(uint32_t*)(p + 2*stride)= v;
         *(uint32_t*)(p + 3*stride)= v;
     }else if(w==8){
-    //gcc can't optimize 64bit math on x86_32
+    // gcc cannot optimize 64-bit math on x86_32
 #if HAVE_FAST_64BIT
         const uint64_t v=  size==2 ? val*0x0001000100010001ULL : val*0x0100000001ULL;
         *(uint64_t*)(p + 0*stride)= v;
diff --git a/libavcodec/remove_extradata_bsf.c b/libavcodec/remove_extradata_bsf.c
index 6bb3576..dd4cf17 100644
--- a/libavcodec/remove_extradata_bsf.c
+++ b/libavcodec/remove_extradata_bsf.c
@@ -18,38 +18,103 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+
 #include "avcodec.h"
+#include "bsf.h"
 
+enum RemoveFreq {
+    REMOVE_FREQ_KEYFRAME,
+    REMOVE_FREQ_ALL,
+    REMOVE_FREQ_NONKEYFRAME,
+};
 
-static int remove_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
-                     uint8_t **poutbuf, int *poutbuf_size,
-                     const uint8_t *buf, int buf_size, int keyframe){
-    int cmd= args ? *args : 0;
-    AVCodecParserContext *s;
+typedef struct RemoveExtradataContext {
+    const AVClass *class;
+    int freq;
 
-    if(!bsfc->parser){
-        bsfc->parser= av_parser_init(avctx->codec_id);
-    }
-    s= bsfc->parser;
-
-    if(s && s->parser->split){
-        if(  (((avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) ||
-               (avctx->flags2 & AV_CODEC_FLAG2_LOCAL_HEADER)) && cmd == 'a')
-           ||(!keyframe && cmd=='k')
-           ||(cmd=='e' || !cmd)
-          ){
-            int i= s->parser->split(avctx, buf, buf_size);
-            buf += i;
-            buf_size -= i;
+    AVCodecParserContext *parser;
+    AVCodecContext *avctx;
+} RemoveExtradataContext;
+
+static int remove_extradata(AVBSFContext *ctx, AVPacket *out)
+{
+    RemoveExtradataContext *s = ctx->priv_data;
+
+    AVPacket *in;
+    int ret;
+
+    ret = ff_bsf_get_packet(ctx, &in);
+    if (ret < 0)
+        return ret;
+
+    if (s->parser && s->parser->parser->split) {
+        if (s->freq == REMOVE_FREQ_ALL ||
+            (s->freq == REMOVE_FREQ_NONKEYFRAME && !(in->flags & AV_PKT_FLAG_KEY)) ||
+            (s->freq == REMOVE_FREQ_KEYFRAME && in->flags & AV_PKT_FLAG_KEY)) {
+            int i = s->parser->parser->split(s->avctx, in->data, in->size);
+            in->data += i;
+            in->size -= i;
         }
     }
-    *poutbuf= (uint8_t *) buf;
-    *poutbuf_size= buf_size;
+
+    av_packet_move_ref(out, in);
+    av_packet_free(&in);
 
     return 0;
 }
 
-AVBitStreamFilter ff_remove_extradata_bsf={
-    .name   = "remove_extra",
-    .filter = remove_extradata,
+static int remove_extradata_init(AVBSFContext *ctx)
+{
+    RemoveExtradataContext *s = ctx->priv_data;
+    int ret;
+
+    s->parser = av_parser_init(ctx->par_in->codec_id);
+
+    if (s->parser) {
+        s->avctx = avcodec_alloc_context3(NULL);
+        if (!s->avctx)
+            return AVERROR(ENOMEM);
+
+        ret = avcodec_parameters_to_context(s->avctx, ctx->par_in);
+        if (ret < 0)
+            return ret;
+    }
+
+    return 0;
+}
+
+static void remove_extradata_close(AVBSFContext *ctx)
+{
+    RemoveExtradataContext *s = ctx->priv_data;
+
+    avcodec_free_context(&s->avctx);
+    av_parser_close(s->parser);
+}
+
+#define OFFSET(x) offsetof(RemoveExtradataContext, x)
+static const AVOption options[] = {
+    { "freq", NULL, OFFSET(freq), AV_OPT_TYPE_INT, { .i64 = REMOVE_FREQ_KEYFRAME }, REMOVE_FREQ_KEYFRAME, REMOVE_FREQ_ALL, 0, "freq" },
+        { "k",        NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_NONKEYFRAME }, .unit = "freq" },
+        { "keyframe", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_KEYFRAME }, .unit = "freq" },
+        { "e",        NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL      }, .unit = "freq" },
+        { "all",      NULL, 0, AV_OPT_TYPE_CONST, { .i64 = REMOVE_FREQ_ALL      }, .unit = "freq" },
+    { NULL },
+};
+
+static const AVClass remove_extradata_class = {
+    .class_name = "remove_extradata",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const AVBitStreamFilter ff_remove_extradata_bsf = {
+    .name           = "remove_extra",
+    .priv_data_size = sizeof(RemoveExtradataContext),
+    .priv_class     = &remove_extradata_class,
+    .init           = remove_extradata_init,
+    .close          = remove_extradata_close,
+    .filter         = remove_extradata,
 };
diff --git a/libavcodec/rl.c b/libavcodec/rl.c
index b206c6f..6eac306 100644
--- a/libavcodec/rl.c
+++ b/libavcodec/rl.c
@@ -17,8 +17,10 @@
  */
 
 #include <stdint.h>
+#include <string.h>
 
 #include "libavutil/attributes.h"
+#include "libavutil/avassert.h"
 #include "libavutil/mem.h"
 
 #include "rl.h"
diff --git a/libavcodec/rl.h b/libavcodec/rl.h
index 33f4ef8..9a767bc 100644
--- a/libavcodec/rl.h
+++ b/libavcodec/rl.h
@@ -28,7 +28,8 @@
 #define AVCODEC_RL_H
 
 #include <stdint.h>
-#include "get_bits.h"
+
+#include "vlc.h"
 
 /* run length table */
 #define MAX_RUN    64
@@ -48,7 +49,6 @@ typedef struct RLTable {
 } RLTable;
 
 /**
- *
  * @param static_store static uint8_t array[2][2*MAX_RUN + MAX_LEVEL + 3] which will hold
  *                     the level and run tables, if this is NULL av_malloc() will be used
  */
diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c
index 5f0b204..4c5dec5 100644
--- a/libavcodec/roqvideodec.c
+++ b/libavcodec/roqvideodec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c
index b6ed1f9..038a63d 100644
--- a/libavcodec/roqvideoenc.c
+++ b/libavcodec/roqvideoenc.c
@@ -1094,7 +1094,7 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         return ret;
     enc->out_buf = pkt->data;
 
-    /* Check for I frame */
+    /* Check for I-frame */
     if (enc->framesSinceKeyframe == avctx->gop_size)
         enc->framesSinceKeyframe = 0;
 
diff --git a/libavcodec/rpza.c b/libavcodec/rpza.c
index 315ad23..b71ebd1 100644
--- a/libavcodec/rpza.c
+++ b/libavcodec/rpza.c
@@ -1,6 +1,6 @@
 /*
  * Quicktime Video (RPZA) Video Decoder
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -92,7 +92,7 @@ static int rpza_decode_stream(RpzaContext *s)
         av_log(s->avctx, AV_LOG_ERROR, "First chunk byte is 0x%02x instead of 0xe1\n",
                bytestream2_peek_byte(&s->gb));
 
-    /* Get chunk size, ingnoring first byte */
+    /* Get chunk size, ignoring first byte */
     chunk_size = bytestream2_get_be32(&s->gb) & 0x00FFFFFF;
 
     /* If length mismatch use size from MOV file and try to decode anyway */
diff --git a/libavcodec/rscc.c b/libavcodec/rscc.c
index a2f7a0d..fe0df2e 100644
--- a/libavcodec/rscc.c
+++ b/libavcodec/rscc.c
@@ -31,7 +31,7 @@
  * and it can be deflated or not. Similarly, pixel data comes after the header
  * and a variable size value, and it can be deflated or just raw.
  *
- * Supports: BGRA
+ * Supports: BGRA, BGR24, RGB555, RGB8
  */
 
 #include <stdint.h>
@@ -57,6 +57,7 @@ typedef struct RsccContext {
     AVFrame *reference;
     Tile *tiles;
     unsigned int tiles_size;
+    int component_size;
 
     /* zlib interaction */
     uint8_t *inflated_buf;
@@ -80,14 +81,38 @@ static av_cold int rscc_init(AVCodecContext *avctx)
     if (!ctx->reference)
         return AVERROR(ENOMEM);
 
-    if (avctx->codec_tag == MKTAG('I','S','C','C')) {
+    /* Get pixel format and the size of the pixel */
+    if (avctx->codec_tag == MKTAG('I', 'S', 'C', 'C')) {
         avctx->pix_fmt = AV_PIX_FMT_BGRA;
+        ctx->component_size = 4;
+    } else if (avctx->codec_tag == MKTAG('R', 'S', 'C', 'C')) {
+        ctx->component_size = avctx->bits_per_coded_sample / 8;
+        switch (avctx->bits_per_coded_sample) {
+        case 8:
+            avpriv_report_missing_feature(avctx, "8 bits per pixel");
+            return AVERROR_PATCHWELCOME;
+        case 16:
+            avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
+            break;
+        case 24:
+            avctx->pix_fmt = AV_PIX_FMT_BGR24;
+            break;
+        case 32:
+            avctx->pix_fmt = AV_PIX_FMT_BGRA;
+            break;
+        default:
+            av_log(avctx, AV_LOG_ERROR, "Invalid bits per pixel value (%d)\n",
+                   avctx->bits_per_coded_sample);
+            return AVERROR_INVALIDDATA;
+        }
     } else {
         avctx->pix_fmt = AV_PIX_FMT_BGR0;
+        ctx->component_size = 4;
+        av_log(avctx, AV_LOG_WARNING, "Invalid codec tag\n");
     }
 
     /* Store the value to check for keyframes */
-    ctx->inflated_size = avctx->width * avctx->height * 4;
+    ctx->inflated_size = avctx->width * avctx->height * ctx->component_size;
 
     /* Allocate maximum size possible, a full frame */
     ctx->inflated_buf = av_malloc(ctx->inflated_size);
@@ -184,7 +209,7 @@ static int rscc_decode_frame(AVCodecContext *avctx, void *data,
         ctx->tiles[i].y = bytestream2_get_le16(gbc);
         ctx->tiles[i].h = bytestream2_get_le16(gbc);
 
-        pixel_size += ctx->tiles[i].w * ctx->tiles[i].h * 4;
+        pixel_size += ctx->tiles[i].w * ctx->tiles[i].h * ctx->component_size;
 
         ff_dlog(avctx, "tile %d orig(%d,%d) %dx%d.\n", i,
                 ctx->tiles[i].x, ctx->tiles[i].y,
@@ -223,6 +248,12 @@ static int rscc_decode_frame(AVCodecContext *avctx, void *data,
 
     ff_dlog(avctx, "pixel_size %d packed_size %d.\n", pixel_size, packed_size);
 
+    if (packed_size < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid tile size %d\n", packed_size);
+        ret = AVERROR_INVALIDDATA;
+        goto end;
+    }
+
     /* Get pixels buffer, it may be deflated or just raw */
     if (pixel_size == packed_size) {
         if (bytestream2_get_bytes_left(gbc) < pixel_size) {
@@ -233,6 +264,11 @@ static int rscc_decode_frame(AVCodecContext *avctx, void *data,
         pixels = gbc->buffer;
     } else {
         uLongf len = ctx->inflated_size;
+        if (bytestream2_get_bytes_left(gbc) < packed_size) {
+            av_log(avctx, AV_LOG_ERROR, "Insufficient input for %d\n", packed_size);
+            ret = AVERROR_INVALIDDATA;
+            goto end;
+        }
         ret = uncompress(ctx->inflated_buf, &len, gbc->buffer, packed_size);
         if (ret) {
             av_log(avctx, AV_LOG_ERROR, "Pixel deflate error %d.\n", ret);
@@ -252,11 +288,12 @@ static int rscc_decode_frame(AVCodecContext *avctx, void *data,
     for (i = 0; i < tiles_nb; i++) {
         uint8_t *dst = ctx->reference->data[0] + ctx->reference->linesize[0] *
                        (avctx->height - ctx->tiles[i].y - 1) +
-                       ctx->tiles[i].x * 4;
+                       ctx->tiles[i].x * ctx->component_size;
         av_image_copy_plane(dst, -1 * ctx->reference->linesize[0],
-                            raw, ctx->tiles[i].w * 4,
-                            ctx->tiles[i].w * 4, ctx->tiles[i].h);
-        raw += ctx->tiles[i].w * 4 * ctx->tiles[i].h;
+                            raw, ctx->tiles[i].w * ctx->component_size,
+                            ctx->tiles[i].w * ctx->component_size,
+                            ctx->tiles[i].h);
+        raw += ctx->tiles[i].w * ctx->component_size * ctx->tiles[i].h;
     }
 
     /* Frame is ready to be output */
diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c
index b56bb58..81aa9ae 100644
--- a/libavcodec/rv10.c
+++ b/libavcodec/rv10.c
@@ -265,7 +265,7 @@ static int rv10_decode_picture_header(MpegEncContext *s)
     ff_dlog(s->avctx, "pict_type=%d pb_frame=%d\n", s->pict_type, pb_frame);
 
     if (pb_frame) {
-        avpriv_request_sample(s->avctx, "pb frame");
+        avpriv_request_sample(s->avctx, "PB-frame");
         return AVERROR_PATCHWELCOME;
     }
 
@@ -431,7 +431,7 @@ static int rv20_decode_picture_header(RVDecContext *rv)
     if (s->pict_type == AV_PICTURE_TYPE_B) {
         if (s->pp_time <=s->pb_time || s->pp_time <= s->pp_time - s->pb_time || s->pp_time<=0) {
             av_log(s->avctx, AV_LOG_DEBUG,
-                   "messed up order, possible from seeking? skipping current b frame\n");
+                   "messed up order, possible from seeking? skipping current B-frame\n");
 #define ERROR_SKIP_FRAME -123
             return ERROR_SKIP_FRAME;
         }
diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c
index b17acbc..8691d18 100644
--- a/libavcodec/rv10enc.c
+++ b/libavcodec/rv10enc.c
@@ -39,7 +39,7 @@ int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number)
 
     put_bits(&s->pb, 1, (s->pict_type == AV_PICTURE_TYPE_P));
 
-    put_bits(&s->pb, 1, 0);     /* not PB frame */
+    put_bits(&s->pb, 1, 0);     /* not PB-mframe */
 
     put_bits(&s->pb, 5, s->qscale);
 
diff --git a/libavcodec/rv30.c b/libavcodec/rv30.c
index 3b9868c..ddaaac6 100644
--- a/libavcodec/rv30.c
+++ b/libavcodec/rv30.c
@@ -89,7 +89,7 @@ static int rv30_decode_intra_types(RV34DecContext *r, GetBitContext *gb, int8_t
 
     for(i = 0; i < 4; i++, dst += r->intra_types_stride - 4){
         for(j = 0; j < 4; j+= 2){
-            unsigned code = svq3_get_ue_golomb(gb) << 1;
+            unsigned code = get_interleaved_ue_golomb(gb) << 1;
             if (code > 80U*2U) {
                 av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction code\n");
                 return -1;
@@ -117,7 +117,7 @@ static int rv30_decode_mb_info(RV34DecContext *r)
     static const int rv30_b_types[6] = { RV34_MB_SKIP, RV34_MB_B_DIRECT, RV34_MB_B_FORWARD, RV34_MB_B_BACKWARD, RV34_MB_TYPE_INTRA, RV34_MB_TYPE_INTRA16x16 };
     MpegEncContext *s = &r->s;
     GetBitContext *gb = &s->gb;
-    unsigned code     = svq3_get_ue_golomb(gb);
+    unsigned code = get_interleaved_ue_golomb(gb);
 
     if (code > 11) {
         av_log(s->avctx, AV_LOG_ERROR, "Incorrect MB type code\n");
diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c
index c2e84a3..aca8382 100644
--- a/libavcodec/rv34.c
+++ b/libavcodec/rv34.c
@@ -864,8 +864,8 @@ static int rv34_decode_mv(RV34DecContext *r, int block_type)
 
     memset(r->dmv, 0, sizeof(r->dmv));
     for(i = 0; i < num_mvs[block_type]; i++){
-        r->dmv[i][0] = svq3_get_se_golomb(gb);
-        r->dmv[i][1] = svq3_get_se_golomb(gb);
+        r->dmv[i][0] = get_interleaved_se_golomb(gb);
+        r->dmv[i][1] = get_interleaved_se_golomb(gb);
     }
     switch(block_type){
     case RV34_MB_TYPE_INTRA:
@@ -1478,7 +1478,7 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int
     return s->mb_y == s->mb_height;
 }
 
-/** @} */ // recons group end
+/** @} */ // reconstruction group end
 
 /**
  * Initialize decoder.
diff --git a/libavcodec/rv34.h b/libavcodec/rv34.h
index e2f40c8..efff94a 100644
--- a/libavcodec/rv34.h
+++ b/libavcodec/rv34.h
@@ -101,12 +101,12 @@ typedef struct RV34DecContext{
     int is16;                ///< current block has additional 16x16 specific features or not
     int dmv[4][2];           ///< differential motion vectors for the current macroblock
 
-    int rv30;                ///< indicates which RV variasnt is currently decoded
+    int rv30;                ///< indicates which RV variant is currently decoded
     int max_rpr;
 
     int cur_pts, last_pts, next_pts;
     int scaled_weight;
-    int weight1, weight2;    ///< B frame distance fractions (0.14) used in motion compensation
+    int weight1, weight2;    ///< B-frame distance fractions (0.14) used in motion compensation
     int mv_weight1, mv_weight2;
 
     int orig_width, orig_height;
diff --git a/libavcodec/rv40.c b/libavcodec/rv40.c
index 3ff1554..465011a 100644
--- a/libavcodec/rv40.c
+++ b/libavcodec/rv40.c
@@ -231,7 +231,7 @@ static int rv40_decode_mb_info(RV34DecContext *r)
     int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
 
     if(!r->s.mb_skip_run) {
-        r->s.mb_skip_run = svq3_get_ue_golomb(gb) + 1;
+        r->s.mb_skip_run = get_interleaved_ue_golomb(gb) + 1;
         if(r->s.mb_skip_run > (unsigned)s->mb_num)
             return -1;
     }
diff --git a/libavcodec/samidec.c b/libavcodec/samidec.c
index 95f35ab..16f3f58 100644
--- a/libavcodec/samidec.c
+++ b/libavcodec/samidec.c
@@ -35,6 +35,7 @@ typedef struct {
     AVBPrint encoded_source;
     AVBPrint encoded_content;
     AVBPrint full;
+    int readorder;
 } SAMIContext;
 
 static int sami_paragraph_to_ass(AVCodecContext *avctx, const char *src)
@@ -131,10 +132,8 @@ static int sami_decode_frame(AVCodecContext *avctx,
     SAMIContext *sami = avctx->priv_data;
 
     if (ptr && avpkt->size > 0 && !sami_paragraph_to_ass(avctx, ptr)) {
-        int ts_start     = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1,100});
-        int ts_duration  = avpkt->duration != -1 ?
-                           av_rescale_q(avpkt->duration, avctx->time_base, (AVRational){1,100}) : -1;
-        int ret = ff_ass_add_rect_bprint(sub, &sami->full, ts_start, ts_duration);
+        // TODO: pass escaped sami->encoded_source.str as source
+        int ret = ff_ass_add_rect(sub, sami->full.str, sami->readorder++, 0, NULL, NULL);
         if (ret < 0)
             return ret;
     }
@@ -164,6 +163,13 @@ static av_cold int sami_close(AVCodecContext *avctx)
     return 0;
 }
 
+static void sami_flush(AVCodecContext *avctx)
+{
+    SAMIContext *sami = avctx->priv_data;
+    if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
+        sami->readorder = 0;
+}
+
 AVCodec ff_sami_decoder = {
     .name           = "sami",
     .long_name      = NULL_IF_CONFIG_SMALL("SAMI subtitle"),
@@ -173,4 +179,5 @@ AVCodec ff_sami_decoder = {
     .init           = sami_init,
     .close          = sami_close,
     .decode         = sami_decode_frame,
+    .flush          = sami_flush,
 };
diff --git a/libavcodec/screenpresso.c b/libavcodec/screenpresso.c
index 2c4bb19..34efb03 100644
--- a/libavcodec/screenpresso.c
+++ b/libavcodec/screenpresso.c
@@ -30,7 +30,7 @@
  * rebuilt frame (not the reference), and since there is no coordinate system
  * they contain exactly as many pixel as the keyframe.
  *
- * Supports: BGR24
+ * Supports: BGRA, BGR24, RGB555
  */
 
 #include <stdint.h>
@@ -47,7 +47,7 @@
 typedef struct ScreenpressoContext {
     AVFrame *current;
 
-    /* zlib interation */
+    /* zlib interaction */
     uint8_t *inflated_buf;
     uLongf inflated_size;
 } ScreenpressoContext;
@@ -79,10 +79,8 @@ static av_cold int screenpresso_init(AVCodecContext *avctx)
     if (!ctx->current)
         return AVERROR(ENOMEM);
 
-    avctx->pix_fmt = AV_PIX_FMT_BGR24;
-
-    /* Allocate maximum size possible, a full frame */
-    ctx->inflated_size = avctx->width * avctx->height * 3;
+    /* Allocate maximum size possible, a full RGBA frame */
+    ctx->inflated_size = avctx->width * avctx->height * 4;
     ctx->inflated_buf  = av_malloc(ctx->inflated_size);
     if (!ctx->inflated_buf)
         return AVERROR(ENOMEM);
@@ -108,7 +106,7 @@ static int screenpresso_decode_frame(AVCodecContext *avctx, void *data,
     ScreenpressoContext *ctx = avctx->priv_data;
     AVFrame *frame = data;
     uLongf length = ctx->inflated_size;
-    int keyframe;
+    int keyframe, component_size, src_linesize;
     int ret;
 
     /* Size check */
@@ -117,13 +115,27 @@ static int screenpresso_decode_frame(AVCodecContext *avctx, void *data,
         return AVERROR_INVALIDDATA;
     }
 
-    /* Basic sanity check, but not really harmful */
-    if ((avpkt->data[0] != 0x73 && avpkt->data[0] != 0x72) ||
-        avpkt->data[1] != 8) { // bpp probably
-        av_log(avctx, AV_LOG_WARNING, "Unknown header 0x%02X%02X\n",
-               avpkt->data[0], avpkt->data[1]);
+    /* Compression level (4 bits) and keyframe information (1 bit) */
+    av_log(avctx, AV_LOG_DEBUG, "Compression level %d\n", avpkt->data[0] >> 4);
+    keyframe = avpkt->data[0] & 1;
+
+    /* Pixel size */
+    component_size = ((avpkt->data[1] >> 2) & 0x03) + 1;
+    switch (component_size) {
+    case 2:
+        avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
+        break;
+    case 3:
+        avctx->pix_fmt = AV_PIX_FMT_BGR24;
+        break;
+    case 4:
+        avctx->pix_fmt = AV_PIX_FMT_BGRA;
+        break;
+    default:
+        av_log(avctx, AV_LOG_ERROR, "Invalid bits per pixel value (%d)\n",
+               component_size);
+        return AVERROR_INVALIDDATA;
     }
-    keyframe = (avpkt->data[0] == 0x73);
 
     /* Inflate the frame after the 2 byte header */
     ret = uncompress(ctx->inflated_buf, &length,
@@ -137,18 +149,21 @@ static int screenpresso_decode_frame(AVCodecContext *avctx, void *data,
     if (ret < 0)
         return ret;
 
+    /* Codec has aligned strides */
+    src_linesize = FFALIGN(avctx->width * component_size, 4);
+
     /* When a keyframe is found, copy it (flipped) */
     if (keyframe)
         av_image_copy_plane(ctx->current->data[0] +
                             ctx->current->linesize[0] * (avctx->height - 1),
                             -1 * ctx->current->linesize[0],
-                            ctx->inflated_buf, avctx->width * 3,
-                            avctx->width * 3, avctx->height);
+                            ctx->inflated_buf, src_linesize,
+                            avctx->width * component_size, avctx->height);
     /* Otherwise sum the delta on top of the current frame */
     else
         sum_delta_flipped(ctx->current->data[0], ctx->current->linesize[0],
-                          ctx->inflated_buf, avctx->width * 3,
-                          avctx->width * 3, avctx->height);
+                          ctx->inflated_buf, src_linesize,
+                          avctx->width * component_size, avctx->height);
 
     /* Frame is ready to be output */
     ret = av_frame_ref(frame, ctx->current);
diff --git a/libavcodec/sgirledec.c b/libavcodec/sgirledec.c
index e7b281a..aa4f0e7 100644
--- a/libavcodec/sgirledec.c
+++ b/libavcodec/sgirledec.c
@@ -31,17 +31,9 @@
 #include "avcodec.h"
 #include "internal.h"
 
-typedef struct SGIRLEContext {
-    AVFrame *frame;
-} SGIRLEContext;
-
 static av_cold int sgirle_decode_init(AVCodecContext *avctx)
 {
-    SGIRLEContext *s = avctx->priv_data;
     avctx->pix_fmt = AV_PIX_FMT_BGR8;
-    s->frame = av_frame_alloc();
-    if (!s->frame)
-        return AVERROR(ENOMEM);
     return 0;
 }
 
@@ -120,41 +112,31 @@ static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst,
 static int sgirle_decode_frame(AVCodecContext *avctx, void *data,
                                int *got_frame, AVPacket *avpkt)
 {
-    SGIRLEContext *s = avctx->priv_data;
+    AVFrame *frame = data;
     int ret;
 
-    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
 
-    ret = decode_sgirle8(avctx, s->frame->data[0], avpkt->data, avpkt->size,
-                         avctx->width, avctx->height, s->frame->linesize[0]);
+    ret = decode_sgirle8(avctx, frame->data[0], avpkt->data, avpkt->size,
+                         avctx->width, avctx->height, frame->linesize[0]);
     if (ret < 0)
         return ret;
 
+    frame->pict_type = AV_PICTURE_TYPE_I;
+    frame->key_frame = 1;
+
     *got_frame = 1;
-    if ((ret = av_frame_ref(data, s->frame)) < 0)
-        return ret;
 
     return avpkt->size;
 }
 
-static av_cold int sgirle_decode_end(AVCodecContext *avctx)
-{
-    SGIRLEContext *s = avctx->priv_data;
-
-    av_frame_free(&s->frame);
-
-    return 0;
-}
-
 AVCodec ff_sgirle_decoder = {
     .name           = "sgirle",
     .long_name      = NULL_IF_CONFIG_SMALL("Silicon Graphics RLE 8-bit video"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_SGIRLE,
-    .priv_data_size = sizeof(SGIRLEContext),
     .init           = sgirle_decode_init,
-    .close          = sgirle_decode_end,
     .decode         = sgirle_decode_frame,
     .capabilities   = AV_CODEC_CAP_DR1,
 };
diff --git a/libavcodec/sheervideo.c b/libavcodec/sheervideo.c
new file mode 100644
index 0000000..2f08b7b
--- /dev/null
+++ b/libavcodec/sheervideo.c
@@ -0,0 +1,3156 @@
+/*
+ * BitJazz SheerVideo decoder
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libavutil/intreadwrite.h"
+#include "avcodec.h"
+#include "get_bits.h"
+#include "internal.h"
+#include "thread.h"
+
+typedef struct SheerVideoContext {
+    unsigned format;
+    VLC vlc[2];
+    void (*decode_frame)(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb);
+} SheerVideoContext;
+
+static const uint8_t l_r_rgb[256] = {
+     3,  3,  4,  4,  5,  5,  5,  6,  6,  6,  7,  7,  7,  7,  7,  8,
+     8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10,
+    10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10,
+    10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  9,  8,  8,  8,
+     8,  8,  8,  7,  7,  7,  7,  7,  6,  6,  6,  5,  5,  4,  4,  4,
+};
+
+static const uint8_t l_r_rgbi[256] = {
+     3,  4,  4,  4,  5,  5,  5,  6,  6,  6,  7,  7,  7,  7,  7,  7,
+     8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10,  9,  9,  9,  9,  9,  9,  9,  8,  8,  8,  8,  8,  8,  8,
+     8,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  5,  5,  4,  4,  4,
+};
+
+static const uint8_t l_g_rgbi[256] = {
+     1,  3,  4,  5,  6,  7,  7,  8,  9,  9, 10, 10, 10, 10, 11, 11,
+    11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
+    14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14,
+    14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12,
+    11, 11, 11, 10, 10, 10,  9,  9,  9,  8,  8,  7,  6,  5,  5,  3,
+};
+
+static const uint8_t l_g_rgb[256] = {
+     2,  2,  4,  4,  6,  7,  9,  9, 10, 11, 11, 11, 12, 12, 12, 13,
+    13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13,
+    13, 13, 12, 12, 12, 11, 11, 11, 10,  9,  9,  8,  6,  4,  3,  3,
+};
+
+static const uint8_t l_y_ybr[256] = {
+     3,  3,  4,  4,  5,  5,  6,  6,  6,  7,  7,  7,  7,  7,  8,  8,
+     8,  8,  8,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10,
+    10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  8,  8,
+     8,  8,  8,  8,  7,  7,  7,  7,  6,  6,  6,  6,  5,  4,  4,  3,
+};
+
+static const uint8_t l_u_ybr[256] = {
+     1,  2,  4,  6,  9, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14,
+    14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15,
+    14, 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 11, 10,  8,  5,  3,
+};
+
+static const uint8_t l_y_ybyr[256] = {
+     3,  3,  4,  4,  5,  5,  5,  6,  6,  6,  7,  7,  7,  7,  7,  8,
+     8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10,
+    10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10,
+    10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  9,  8,  8,  8,
+     8,  8,  8,  7,  7,  7,  7,  7,  6,  6,  6,  5,  5,  4,  4,  4,
+};
+
+static const uint8_t l_u_ybyr[256] = {
+     1,  2,  4,  6,  8,  9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14,
+    14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14,
+    14, 14, 13, 13, 13, 12, 12, 11, 11, 10, 10,  9,  8,  7,  6,  3,
+};
+
+static const uint8_t l_y_byry[256] = {
+     3,  3,  4,  4,  5,  5,  6,  6,  6,  7,  7,  7,  7,  7,  8,  8,
+     8,  8,  8,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10,
+    10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11,
+    11, 10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  8,  8,
+     8,  8,  8,  8,  7,  7,  7,  7,  6,  6,  6,  6,  5,  4,  4,  3,
+};
+
+static const uint8_t l_u_byry[256] = {
+     1,  2,  4,  6,  8,  9,  9, 10, 11, 11, 12, 12, 13, 13, 13, 14,
+    14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14,
+    14, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10,  9,  8,  7,  6,  3,
+};
+
+static const uint8_t l_y_ybr10i[1024] = {
+     3,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,
+     7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+     8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,
+     7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,
+};
+
+static const uint8_t l_y_ybr10[1024] = {
+     4,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  7,  7,  7,
+     7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+     8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,
+     7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,
+};
+
+static const uint8_t l_u_ybr10i[1024] = {
+     2,  3,  4,  4,  5,  5,  6,  7,  7,  8,  8,  9,  9,  9,  9, 10,
+    10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 10, 10,
+    10, 10, 10,  9,  9,  9,  8,  8,  8,  7,  6,  5,  5,  4,  4,  3,
+};
+
+static const uint8_t l_u_ybr10[1024] = {
+     2,  3,  3,  4,  5,  5,  6,  7,  8,  9,  9, 10, 10, 10, 11, 11,
+    12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12,
+    12, 11, 11, 11, 10, 10,  9,  9,  8,  8,  7,  6,  5,  4,  4,  3,
+};
+
+static const uint8_t l_r_rgbx[1024] = {
+     4,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  7,  7,  7,
+     7,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+     8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  8,  8,  8,
+     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,  7,  7,
+     7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,
+};
+
+static const uint8_t l_g_rgbx[1024] = {
+     3,  4,  4,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,
+     8,  8,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12,
+    12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12,
+    12, 12, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10,  9,  9,  9,  9,
+     8,  7,  7,  7,  6,  6,  6,  6,  6,  5,  5,  5,  5,  4,  4,  4,
+};
+
+static const uint8_t l_y_yry10[1024] = {
+     4,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  7,  7,  7,
+     7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+     8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,
+     7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,
+};
+
+static const uint8_t l_y_yry10i[1024] = {
+     3,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,
+     7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
+     8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  7,  7,  7,  7,
+     7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,
+};
+
+static const uint8_t l_u_yry10[1024] = {
+     2,  3,  3,  4,  5,  6,  7,  7,  8,  8,  8,  9,  9, 10, 10, 10,
+    10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+    13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13,
+    13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11,
+    10, 10, 10, 10,  9,  9,  9,  8,  8,  7,  7,  6,  5,  4,  4,  3,
+};
+
+static const uint8_t l_u_yry10i[1024] = {
+     2,  4,  4,  4,  5,  6,  6,  6,  7,  7,  7,  8,  8,  8,  9,  9,
+     9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11,
+    11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11,
+    11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10,  9,  9,  9,
+     9,  9,  8,  8,  8,  8,  7,  7,  7,  6,  6,  5,  5,  4,  4,  3,
+};
+
+static const uint8_t l_y_ybri[256] = {
+     3,  3,  4,  4,  5,  5,  6,  6,  6,  7,  7,  7,  7,  7,  8,  8,
+     8,  8,  8,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10,
+    10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  9,  8,  8,
+     8,  8,  8,  7,  7,  7,  7,  7,  6,  6,  6,  5,  5,  5,  4,  3,
+};
+
+static const uint8_t l_u_ybri[256] = {
+     1,  3,  5,  6,  8,  8,  9, 10, 10, 11, 11, 12, 12, 13, 13, 13,
+    14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14,
+    14, 13, 13, 13, 12, 12, 11, 11, 10, 10,  9,  8,  8,  6,  5,  2,
+};
+
+static const uint8_t l_y_byryi[256] = {
+     3,  3,  4,  4,  5,  5,  6,  6,  7,  7,  7,  7,  7,  7,  8,  8,
+     8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10,
+    10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10,
+    10, 10, 10, 10, 10, 10, 10,  9,  9,  9,  9,  9,  9,  9,  8,  8,
+     8,  8,  8,  7,  7,  7,  7,  7,  7,  6,  6,  6,  5,  4,  4,  3,
+};
+
+static const uint8_t l_u_byryi[256] = {
+     1,  3,  4,  6,  6,  7,  8,  8,  9,  9, 10, 10, 10, 11, 11, 11,
+    12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15,
+    15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15,
+    15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 13, 12, 12, 12,
+    12, 11, 11, 11, 10, 10, 10,  9,  9,  8,  8,  7,  7,  5,  4,  3,
+};
+
+static const uint8_t l_r_rgbxi[1024] = {
+     3,  4,  4,  4,  5,  5,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,
+     8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
+     9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+    11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  9,  9,
+     9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  8,  8,  8,
+     8,  8,  8,  8,  7,  7,  7,  7,  6,  6,  6,  5,  5,  4,  4,  4,
+};
+
+static const uint8_t l_g_rgbxi[1024] = {
+     2,  3,  4,  4,  6,  6,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,
+     9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11,
+    11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,
+    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14,
+    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+    15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+    14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+    13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11,
+    11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10,  9,  9,  9,
+     9,  8,  8,  8,  8,  7,  7,  7,  7,  7,  7,  6,  6,  4,  4,  3,
+};
+
+static void decode_ca4i(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_y, *dst_u, *dst_v, *dst_a;
+    int x, y;
+
+    dst_a = (uint16_t *)p->data[3];
+    dst_y = (uint16_t *)p->data[0];
+    dst_u = (uint16_t *)p->data[1];
+    dst_v = (uint16_t *)p->data[2];
+
+    for (y = 0; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_a[x] = get_bits(gb, 10);
+                dst_y[x] = get_bits(gb, 10);
+                dst_u[x] = get_bits(gb, 10);
+                dst_v[x] = get_bits(gb, 10);
+            }
+        } else {
+            int pred[4] = { 502, 512, 512, 502 };
+
+            for (x = 0; x < avctx->width; x++) {
+                int y, u, v, a;
+
+                a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_a[x] = pred[3] = (a + pred[3]) & 0x3ff;
+                dst_y[x] = pred[0] = (y + pred[0]) & 0x3ff;
+                dst_u[x] = pred[1] = (u + pred[1]) & 0x3ff;
+                dst_v[x] = pred[2] = (v + pred[2]) & 0x3ff;
+            }
+        }
+
+        dst_y += p->linesize[0] / 2;
+        dst_u += p->linesize[1] / 2;
+        dst_v += p->linesize[2] / 2;
+        dst_a += p->linesize[3] / 2;
+    }
+}
+
+static void decode_ca4p(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_y, *dst_u, *dst_v, *dst_a;
+    int x, y;
+
+    dst_a = (uint16_t *)p->data[3];
+    dst_y = (uint16_t *)p->data[0];
+    dst_u = (uint16_t *)p->data[1];
+    dst_v = (uint16_t *)p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst_a[x] = get_bits(gb, 10);
+            dst_y[x] = get_bits(gb, 10);
+            dst_u[x] = get_bits(gb, 10);
+            dst_v[x] = get_bits(gb, 10);
+        }
+    } else {
+        int pred[4] = { 502, 512, 512, 502 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int y, u, v, a;
+
+            a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_a[x] = pred[3] = (a + pred[3]) & 0x3ff;
+            dst_y[x] = pred[0] = (y + pred[0]) & 0x3ff;
+            dst_u[x] = pred[1] = (u + pred[1]) & 0x3ff;
+            dst_v[x] = pred[2] = (v + pred[2]) & 0x3ff;
+        }
+    }
+
+    dst_y += p->linesize[0] / 2;
+    dst_u += p->linesize[1] / 2;
+    dst_v += p->linesize[2] / 2;
+    dst_a += p->linesize[3] / 2;
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_a[x] = get_bits(gb, 10);
+                dst_y[x] = get_bits(gb, 10);
+                dst_u[x] = get_bits(gb, 10);
+                dst_v[x] = get_bits(gb, 10);
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int y, u, v, a;
+
+            pred_TL[0] = pred_L[0] = dst_y[-p->linesize[0] / 2];
+            pred_TL[1] = pred_L[1] = dst_u[-p->linesize[1] / 2];
+            pred_TL[2] = pred_L[2] = dst_v[-p->linesize[2] / 2];
+            pred_TL[3] = pred_L[3] = dst_a[-p->linesize[3] / 2];
+
+            for (x = 0; x < avctx->width; x++) {
+                pred_T[0] = dst_y[-p->linesize[0] / 2 + x];
+                pred_T[1] = dst_u[-p->linesize[1] / 2 + x];
+                pred_T[2] = dst_v[-p->linesize[2] / 2 + x];
+                pred_T[3] = dst_a[-p->linesize[3] / 2 + x];
+
+                a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_a[x] = pred_L[3] = (a + ((3 * (pred_T[3] + pred_L[3]) - 2 * pred_TL[3]) >> 2)) & 0x3ff;
+                dst_y[x] = pred_L[0] = (y + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff;
+                dst_u[x] = pred_L[1] = (u + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0x3ff;
+                dst_v[x] = pred_L[2] = (v + ((3 * (pred_T[2] + pred_L[2]) - 2 * pred_TL[2]) >> 2)) & 0x3ff;
+
+                pred_TL[0] = pred_T[0];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+                pred_TL[3] = pred_T[3];
+            }
+        }
+
+        dst_y += p->linesize[0] / 2;
+        dst_u += p->linesize[1] / 2;
+        dst_v += p->linesize[2] / 2;
+        dst_a += p->linesize[3] / 2;
+    }
+}
+
+static void decode_ybr10i(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_y = (uint16_t *)p->data[0];
+    dst_u = (uint16_t *)p->data[1];
+    dst_v = (uint16_t *)p->data[2];
+
+    for (y = 0; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_y[x] = get_bits(gb, 10);
+                dst_u[x] = get_bits(gb, 10);
+                dst_v[x] = get_bits(gb, 10);
+            }
+        } else {
+            int pred[4] = { 502, 512, 512, 512 };
+
+            for (x = 0; x < avctx->width; x++) {
+                int y, u, v;
+
+                y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x] = pred[0] = (y + pred[0]) & 0x3ff;
+                dst_u[x] = pred[1] = (u + pred[1]) & 0x3ff;
+                dst_v[x] = pred[2] = (v + pred[2]) & 0x3ff;
+            }
+        }
+
+        dst_y += p->linesize[0] / 2;
+        dst_u += p->linesize[1] / 2;
+        dst_v += p->linesize[2] / 2;
+    }
+}
+
+static void decode_ybr10(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_y = (uint16_t *)p->data[0];
+    dst_u = (uint16_t *)p->data[1];
+    dst_v = (uint16_t *)p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst_y[x] = get_bits(gb, 10);
+            dst_u[x] = get_bits(gb, 10);
+            dst_v[x] = get_bits(gb, 10);
+        }
+    } else {
+        int pred[4] = { 502, 512, 512, 512 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int y, u, v;
+
+            y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_y[x] = pred[0] = (y + pred[0]) & 0x3ff;
+            dst_u[x] = pred[1] = (u + pred[1]) & 0x3ff;
+            dst_v[x] = pred[2] = (v + pred[2]) & 0x3ff;
+        }
+    }
+
+    dst_y += p->linesize[0] / 2;
+    dst_u += p->linesize[1] / 2;
+    dst_v += p->linesize[2] / 2;
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_y[x] = get_bits(gb, 10);
+                dst_u[x] = get_bits(gb, 10);
+                dst_v[x] = get_bits(gb, 10);
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int y, u, v;
+
+            pred_TL[0] = pred_L[0] = dst_y[-p->linesize[0] / 2];
+            pred_TL[1] = pred_L[1] = dst_u[-p->linesize[1] / 2];
+            pred_TL[2] = pred_L[2] = dst_v[-p->linesize[2] / 2];
+
+            for (x = 0; x < avctx->width; x++) {
+                pred_T[0] = dst_y[-p->linesize[0] / 2 + x];
+                pred_T[1] = dst_u[-p->linesize[1] / 2 + x];
+                pred_T[2] = dst_v[-p->linesize[2] / 2 + x];
+
+                y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x] = pred_L[0] = (y + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff;
+                dst_u[x] = pred_L[1] = (u + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0x3ff;
+                dst_v[x] = pred_L[2] = (v + ((3 * (pred_T[2] + pred_L[2]) - 2 * pred_TL[2]) >> 2)) & 0x3ff;
+
+                pred_TL[0] = pred_T[0];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+            }
+        }
+
+        dst_y += p->linesize[0] / 2;
+        dst_u += p->linesize[1] / 2;
+        dst_v += p->linesize[2] / 2;
+    }
+}
+
+static void decode_yry10i(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_y = (uint16_t *)p->data[0];
+    dst_u = (uint16_t *)p->data[1];
+    dst_v = (uint16_t *)p->data[2];
+
+    for (y = 0; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x += 2) {
+                dst_y[x    ] = get_bits(gb, 10);
+                dst_u[x / 2] = get_bits(gb, 10);
+                dst_y[x + 1] = get_bits(gb, 10);
+                dst_v[x / 2] = get_bits(gb, 10);
+            }
+        } else {
+            int pred[4] = { 502, 512, 512, 0 };
+
+            for (x = 0; x < avctx->width; x += 2) {
+                int y1, y2, u, v;
+
+                y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x    ] = pred[0] = (y1 + pred[0]) & 0x3ff;
+                dst_u[x / 2] = pred[1] = (u  + pred[1]) & 0x3ff;
+                dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0x3ff;
+                dst_v[x / 2] = pred[2] = (v  + pred[2]) & 0x3ff;
+            }
+        }
+
+        dst_y += p->linesize[0] / 2;
+        dst_u += p->linesize[1] / 2;
+        dst_v += p->linesize[2] / 2;
+    }
+}
+
+static void decode_yry10(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_y = (uint16_t *)p->data[0];
+    dst_u = (uint16_t *)p->data[1];
+    dst_v = (uint16_t *)p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x += 2) {
+            dst_y[x    ] = get_bits(gb, 10);
+            dst_u[x / 2] = get_bits(gb, 10);
+            dst_y[x + 1] = get_bits(gb, 10);
+            dst_v[x / 2] = get_bits(gb, 10);
+        }
+    } else {
+        int pred[4] = { 502, 512, 512, 0 };
+
+        for (x = 0; x < avctx->width; x += 2) {
+            int y1, y2, u, v;
+
+            y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_y[x    ] = pred[0] = (y1 + pred[0]) & 0x3ff;
+            dst_u[x / 2] = pred[1] = (u  + pred[1]) & 0x3ff;
+            dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0x3ff;
+            dst_v[x / 2] = pred[2] = (v  + pred[2]) & 0x3ff;
+        }
+    }
+
+    dst_y += p->linesize[0] / 2;
+    dst_u += p->linesize[1] / 2;
+    dst_v += p->linesize[2] / 2;
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x += 2) {
+                dst_y[x    ] = get_bits(gb, 10);
+                dst_u[x / 2] = get_bits(gb, 10);
+                dst_y[x + 1] = get_bits(gb, 10);
+                dst_v[x / 2] = get_bits(gb, 10);
+            }
+        } else {
+            int pred_TL[6], pred_L[6], pred_T[6];
+            int y1, y2, u, v;
+
+            pred_TL[0] = pred_L[0] = dst_y[-p->linesize[0] / 2];
+            pred_TL[1] = pred_L[1] = dst_u[-p->linesize[1] / 2];
+            pred_TL[2] = pred_L[2] = dst_v[-p->linesize[2] / 2];
+
+            for (x = 0; x < avctx->width; x += 2) {
+                pred_T[0] = dst_y[-p->linesize[0] / 2 + x];
+                pred_T[3] = dst_y[-p->linesize[0] / 2 + x + 1];
+                pred_T[1] = dst_u[-p->linesize[1] / 2 + x / 2];
+                pred_T[2] = dst_v[-p->linesize[2] / 2 + x / 2];
+
+                y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x    ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff;
+                dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0x3ff;
+                dst_y[x + 1] = pred_L[0] = (y2 + ((3 * (pred_T[3] + pred_L[0]) - 2 * pred_T[0]) >> 2)) & 0x3ff;
+                dst_v[x / 2] = pred_L[2] = (v + (((pred_L[2] - pred_TL[2]) >> 1) + pred_T[2])) & 0x3ff;
+
+                pred_TL[0] = pred_T[3];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+            }
+        }
+
+        dst_y += p->linesize[0] / 2;
+        dst_u += p->linesize[1] / 2;
+        dst_v += p->linesize[2] / 2;
+    }
+}
+
+static void decode_ca2i(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_y, *dst_u, *dst_v, *dst_a;
+    int x, y;
+
+    dst_y = (uint16_t *)p->data[0];
+    dst_u = (uint16_t *)p->data[1];
+    dst_v = (uint16_t *)p->data[2];
+    dst_a = (uint16_t *)p->data[3];
+
+    for (y = 0; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x += 2) {
+                dst_a[x    ] = get_bits(gb, 10);
+                dst_y[x    ] = get_bits(gb, 10);
+                dst_u[x / 2] = get_bits(gb, 10);
+                dst_a[x + 1] = get_bits(gb, 10);
+                dst_y[x + 1] = get_bits(gb, 10);
+                dst_v[x / 2] = get_bits(gb, 10);
+            }
+        } else {
+            int pred[4] = { 502, 512, 512, 502 };
+
+            for (x = 0; x < avctx->width; x += 2) {
+                int y1, y2, u, v, a1, a2;
+
+                a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x    ] = pred[0] = (y1 + pred[0]) & 0x3ff;
+                dst_u[x / 2] = pred[1] = (u  + pred[1]) & 0x3ff;
+                dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0x3ff;
+                dst_a[x    ] = pred[3] = (a1 + pred[3]) & 0x3ff;
+                dst_v[x / 2] = pred[2] = (v  + pred[2]) & 0x3ff;
+                dst_a[x + 1] = pred[3] = (a2 + pred[3]) & 0x3ff;
+            }
+        }
+
+        dst_y += p->linesize[0] / 2;
+        dst_u += p->linesize[1] / 2;
+        dst_v += p->linesize[2] / 2;
+        dst_a += p->linesize[3] / 2;
+    }
+}
+
+static void decode_ca2p(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_y, *dst_u, *dst_v, *dst_a;
+    int x, y;
+
+    dst_y = (uint16_t *)p->data[0];
+    dst_u = (uint16_t *)p->data[1];
+    dst_v = (uint16_t *)p->data[2];
+    dst_a = (uint16_t *)p->data[3];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x += 2) {
+            dst_a[x    ] = get_bits(gb, 10);
+            dst_y[x    ] = get_bits(gb, 10);
+            dst_u[x / 2] = get_bits(gb, 10);
+            dst_a[x + 1] = get_bits(gb, 10);
+            dst_y[x + 1] = get_bits(gb, 10);
+            dst_v[x / 2] = get_bits(gb, 10);
+        }
+    } else {
+        int pred[4] = { 502, 512, 512, 502 };
+
+        for (x = 0; x < avctx->width; x += 2) {
+            int y1, y2, u, v, a1, a2;
+
+            a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_y[x    ] = pred[0] = (y1 + pred[0]) & 0x3ff;
+            dst_u[x / 2] = pred[1] = (u  + pred[1]) & 0x3ff;
+            dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0x3ff;
+            dst_a[x    ] = pred[3] = (a1 + pred[3]) & 0x3ff;
+            dst_v[x / 2] = pred[2] = (v  + pred[2]) & 0x3ff;
+            dst_a[x + 1] = pred[3] = (a2 + pred[3]) & 0x3ff;
+        }
+    }
+
+    dst_y += p->linesize[0] / 2;
+    dst_u += p->linesize[1] / 2;
+    dst_v += p->linesize[2] / 2;
+    dst_a += p->linesize[3] / 2;
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x += 2) {
+                dst_a[x    ] = get_bits(gb, 10);
+                dst_y[x    ] = get_bits(gb, 10);
+                dst_u[x / 2] = get_bits(gb, 10);
+                dst_a[x + 1] = get_bits(gb, 10);
+                dst_y[x + 1] = get_bits(gb, 10);
+                dst_v[x / 2] = get_bits(gb, 10);
+            }
+        } else {
+            int pred_TL[6], pred_L[6], pred_T[6];
+            int y1, y2, u, v, a1, a2;
+
+            pred_TL[0] = pred_L[0] = dst_y[-p->linesize[0] / 2];
+            pred_TL[1] = pred_L[1] = dst_u[-p->linesize[1] / 2];
+            pred_TL[2] = pred_L[2] = dst_v[-p->linesize[2] / 2];
+            pred_TL[4] = pred_L[4] = dst_a[-p->linesize[3] / 2];
+
+            for (x = 0; x < avctx->width; x += 2) {
+                pred_T[0] = dst_y[-p->linesize[0] / 2 + x];
+                pred_T[3] = dst_y[-p->linesize[0] / 2 + x + 1];
+                pred_T[1] = dst_u[-p->linesize[1] / 2 + x / 2];
+                pred_T[2] = dst_v[-p->linesize[2] / 2 + x / 2];
+                pred_T[4] = dst_a[-p->linesize[3] / 2 + x];
+                pred_T[5] = dst_a[-p->linesize[3] / 2 + x + 1];
+
+                a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x    ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff;
+                dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0x3ff;
+                dst_y[x + 1] = pred_L[0] = (y2 + ((3 * (pred_T[3] + pred_L[0]) - 2 * pred_T[0]) >> 2)) & 0x3ff;
+                dst_v[x / 2] = pred_L[2] = (v + (((pred_L[2] - pred_TL[2]) >> 1) + pred_T[2])) & 0x3ff;
+                dst_a[x    ] = pred_L[4] = (a1 + ((3 * (pred_T[4] + pred_L[4]) - 2 * pred_TL[4]) >> 2)) & 0x3ff;
+                dst_a[x + 1] = pred_L[4] = (a2 + ((3 * (pred_T[5] + pred_L[4]) - 2 * pred_T[4]) >> 2)) & 0x3ff;
+
+                pred_TL[0] = pred_T[3];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+                pred_TL[4] = pred_T[5];
+            }
+        }
+
+        dst_y += p->linesize[0] / 2;
+        dst_u += p->linesize[1] / 2;
+        dst_v += p->linesize[2] / 2;
+        dst_a += p->linesize[3] / 2;
+    }
+}
+
+static void decode_c82i(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst_y, *dst_u, *dst_v, *dst_a;
+    int x, y;
+
+    dst_y = p->data[0];
+    dst_u = p->data[1];
+    dst_v = p->data[2];
+    dst_a = p->data[3];
+
+    for (y = 0; y < avctx->height; y += 1) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x += 2) {
+                dst_a[x    ] = get_bits(gb, 8);
+                dst_y[x    ] = get_bits(gb, 8);
+                dst_u[x / 2] = get_bits(gb, 8);
+                dst_a[x + 1] = get_bits(gb, 8);
+                dst_y[x + 1] = get_bits(gb, 8);
+                dst_v[x / 2] = get_bits(gb, 8);
+            }
+        } else {
+            int pred[4] = { 125, -128, -128, 125 };
+
+            for (x = 0; x < avctx->width; x += 2) {
+                int y1, y2, u, v, a1, a2;
+
+                a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x    ] = pred[0] = (y1 + pred[0]) & 0xff;
+                dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0xff;
+                dst_u[x / 2] = pred[1] = (u  + pred[1]) & 0xff;
+                dst_v[x / 2] = pred[2] = (v  + pred[2]) & 0xff;
+                dst_a[x    ] = pred[3] = (a1 + pred[3]) & 0xff;
+                dst_a[x + 1] = pred[3] = (a2 + pred[3]) & 0xff;
+            }
+        }
+
+        dst_y += p->linesize[0];
+        dst_u += p->linesize[1];
+        dst_v += p->linesize[2];
+        dst_a += p->linesize[3];
+    }
+}
+
+static void decode_c82p(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst_y, *dst_u, *dst_v, *dst_a;
+    int x, y;
+
+    dst_y = p->data[0];
+    dst_u = p->data[1];
+    dst_v = p->data[2];
+    dst_a = p->data[3];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x += 2) {
+            dst_a[x    ] = get_bits(gb, 8);
+            dst_y[x    ] = get_bits(gb, 8);
+            dst_u[x / 2] = get_bits(gb, 8);
+            dst_a[x + 1] = get_bits(gb, 8);
+            dst_y[x + 1] = get_bits(gb, 8);
+            dst_v[x / 2] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { 125, -128, -128, 125 };
+
+        for (x = 0; x < avctx->width; x += 2) {
+            int y1, y2, u, v, a1, a2;
+
+            a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_y[x    ] = pred[0] = (y1 + pred[0]) & 0xff;
+            dst_u[x / 2] = pred[1] = (u  + pred[1]) & 0xff;
+            dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0xff;
+            dst_a[x    ] = pred[3] = (a1 + pred[3]) & 0xff;
+            dst_v[x / 2] = pred[2] = (v  + pred[2]) & 0xff;
+            dst_a[x + 1] = pred[3] = (a2 + pred[3]) & 0xff;
+        }
+    }
+
+    dst_y += p->linesize[0];
+    dst_u += p->linesize[1];
+    dst_v += p->linesize[2];
+    dst_a += p->linesize[3];
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x += 2) {
+                dst_a[x    ] = get_bits(gb, 8);
+                dst_y[x    ] = get_bits(gb, 8);
+                dst_u[x / 2] = get_bits(gb, 8);
+                dst_a[x + 1] = get_bits(gb, 8);
+                dst_y[x + 1] = get_bits(gb, 8);
+                dst_v[x / 2] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_TL[6], pred_L[6], pred_T[6];
+            int y1, y2, u, v, a1, a2;
+
+            pred_TL[0] = pred_L[0] = dst_y[-p->linesize[0]];
+            pred_TL[1] = pred_L[1] = dst_u[-p->linesize[1]];
+            pred_TL[2] = pred_L[2] = dst_v[-p->linesize[2]];
+            pred_TL[4] = pred_L[4] = dst_a[-p->linesize[3]];
+
+            for (x = 0; x < avctx->width; x += 2) {
+                pred_T[0] = dst_y[-p->linesize[0] + x];
+                pred_T[3] = dst_y[-p->linesize[0] + x + 1];
+                pred_T[1] = dst_u[-p->linesize[1] + x / 2];
+                pred_T[2] = dst_v[-p->linesize[2] + x / 2];
+                pred_T[4] = dst_a[-p->linesize[3] + x];
+                pred_T[5] = dst_a[-p->linesize[3] + x + 1];
+
+                a1 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                a2 = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x    ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff;
+                dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0xff;
+                dst_y[x + 1] = pred_L[0] = (y2 + ((3 * (pred_T[3] + pred_L[0]) - 2 * pred_T[0]) >> 2)) & 0xff;
+                dst_v[x / 2] = pred_L[2] = (v + (((pred_L[2] - pred_TL[2]) >> 1) + pred_T[2])) & 0xff;
+                dst_a[x    ] = pred_L[4] = (a1 + ((3 * (pred_T[4] + pred_L[4]) - 2 * pred_TL[4]) >> 2)) & 0xff;
+                dst_a[x + 1] = pred_L[4] = (a2 + ((3 * (pred_T[5] + pred_L[4]) - 2 * pred_T[4]) >> 2)) & 0xff;
+
+                pred_TL[0] = pred_T[3];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+                pred_TL[4] = pred_T[5];
+            }
+        }
+
+        dst_y += p->linesize[0];
+        dst_u += p->linesize[1];
+        dst_v += p->linesize[2];
+        dst_a += p->linesize[3];
+    }
+}
+
+static void decode_ybyr(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_y = p->data[0];
+    dst_u = p->data[1];
+    dst_v = p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x += 2) {
+            dst_y[x    ] = get_bits(gb, 8);
+            dst_u[x / 2] = get_bits(gb, 8) + 128;
+            dst_y[x + 1] = get_bits(gb, 8);
+            dst_v[x / 2] = get_bits(gb, 8) + 128;
+        }
+    } else {
+        int pred[4] = { -128, 128, 128, 0 };
+
+        for (x = 0; x < avctx->width; x += 2) {
+            int y1, y2, u, v;
+
+            y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_y[x    ] = pred[0] = (y1 + pred[0]) & 0xff;
+            dst_u[x / 2] = pred[1] = (u  + pred[1]) & 0xff;
+            dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0xff;
+            dst_v[x / 2] = pred[2] = (v  + pred[2]) & 0xff;
+        }
+    }
+
+    dst_y += p->linesize[0];
+    dst_u += p->linesize[1];
+    dst_v += p->linesize[2];
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x += 2) {
+                dst_y[x    ] = get_bits(gb, 8);
+                dst_u[x / 2] = get_bits(gb, 8) + 128;
+                dst_y[x + 1] = get_bits(gb, 8);
+                dst_v[x / 2] = get_bits(gb, 8) + 128;
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int y1, y2, u, v;
+
+            pred_TL[0] = pred_L[0] = dst_y[-p->linesize[0]];
+            pred_TL[1] = pred_L[1] = dst_u[-p->linesize[1]];
+            pred_TL[2] = pred_L[2] = dst_v[-p->linesize[2]];
+
+            for (x = 0; x < avctx->width; x += 2) {
+                pred_T[0] = dst_y[-p->linesize[0] + x];
+                pred_T[3] = dst_y[-p->linesize[0] + x + 1];
+                pred_T[1] = dst_u[-p->linesize[1] + x / 2];
+                pred_T[2] = dst_v[-p->linesize[2] + x / 2];
+
+                y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x    ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff;
+                dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0xff;
+                dst_y[x + 1] = pred_L[0] = (y2 + ((3 * (pred_T[3] + pred_L[0]) - 2 * pred_T[0]) >> 2)) & 0xff;
+                dst_v[x / 2] = pred_L[2] = (v + (((pred_L[2] - pred_TL[2]) >> 1) + pred_T[2])) & 0xff;
+
+                pred_TL[0] = pred_T[3];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+            }
+        }
+
+        dst_y += p->linesize[0];
+        dst_u += p->linesize[1];
+        dst_v += p->linesize[2];
+    }
+}
+
+static void decode_byryi(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_y = p->data[0];
+    dst_u = p->data[1];
+    dst_v = p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x += 2) {
+            dst_y[x    ] = get_bits(gb, 8);
+            dst_u[x / 2] = get_bits(gb, 8);
+            dst_y[x + 1] = get_bits(gb, 8);
+            dst_v[x / 2] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { 125, -128, -128, 0 };
+
+        for (x = 0; x < avctx->width; x += 2) {
+            int y1, y2, u, v;
+
+            y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_y[x    ] = pred[0] = (y1 + pred[0]) & 0xff;
+            dst_u[x / 2] = pred[1] = (u  + pred[1]) & 0xff;
+            dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0xff;
+            dst_v[x / 2] = pred[2] = (v  + pred[2]) & 0xff;
+        }
+    }
+
+    dst_y += p->linesize[0];
+    dst_u += p->linesize[1];
+    dst_v += p->linesize[2];
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x += 2) {
+                dst_y[x    ] = get_bits(gb, 8);
+                dst_u[x / 2] = get_bits(gb, 8);
+                dst_y[x + 1] = get_bits(gb, 8);
+                dst_v[x / 2] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_L[4];
+            int y1, y2, u, v;
+
+            pred_L[0] = dst_y[-p->linesize[0]];
+            pred_L[1] = dst_u[-p->linesize[1]];
+            pred_L[2] = dst_v[-p->linesize[2]];
+
+            for (x = 0; x < avctx->width; x += 2) {
+                y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x    ] = pred_L[0] = (y1 + pred_L[0]) & 0xff;
+                dst_u[x / 2] = pred_L[1] = (u  + pred_L[1]) & 0xff;
+                dst_y[x + 1] = pred_L[0] = (y2 + pred_L[0]) & 0xff;
+                dst_v[x / 2] = pred_L[2] = (v +  pred_L[2]) & 0xff;
+            }
+        }
+
+        dst_y += p->linesize[0];
+        dst_u += p->linesize[1];
+        dst_v += p->linesize[2];
+    }
+}
+
+static void decode_byry(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_y = p->data[0];
+    dst_u = p->data[1];
+    dst_v = p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x += 2) {
+            dst_y[x    ] = get_bits(gb, 8);
+            dst_u[x / 2] = get_bits(gb, 8);
+            dst_y[x + 1] = get_bits(gb, 8);
+            dst_v[x / 2] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { 125, -128, -128, 0 };
+
+        for (x = 0; x < avctx->width; x += 2) {
+            int y1, y2, u, v;
+
+            y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_y[x    ] = pred[0] = (y1 + pred[0]) & 0xff;
+            dst_u[x / 2] = pred[1] = (u  + pred[1]) & 0xff;
+            dst_y[x + 1] = pred[0] = (y2 + pred[0]) & 0xff;
+            dst_v[x / 2] = pred[2] = (v  + pred[2]) & 0xff;
+        }
+    }
+
+    dst_y += p->linesize[0];
+    dst_u += p->linesize[1];
+    dst_v += p->linesize[2];
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x += 2) {
+                dst_y[x    ] = get_bits(gb, 8);
+                dst_u[x / 2] = get_bits(gb, 8);
+                dst_y[x + 1] = get_bits(gb, 8);
+                dst_v[x / 2] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int y1, y2, u, v;
+
+            pred_TL[0] = pred_L[0] = dst_y[-p->linesize[0]];
+            pred_TL[1] = pred_L[1] = dst_u[-p->linesize[1]];
+            pred_TL[2] = pred_L[2] = dst_v[-p->linesize[2]];
+
+            for (x = 0; x < avctx->width; x += 2) {
+                pred_T[0] = dst_y[-p->linesize[0] + x];
+                pred_T[3] = dst_y[-p->linesize[0] + x + 1];
+                pred_T[1] = dst_u[-p->linesize[1] + x / 2];
+                pred_T[2] = dst_v[-p->linesize[2] + x / 2];
+
+                y1 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y2 = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                v  = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x    ] = pred_L[0] = (y1 + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff;
+                dst_u[x / 2] = pred_L[1] = (u + (((pred_L[1] - pred_TL[1]) >> 1) + pred_T[1])) & 0xff;
+                dst_y[x + 1] = pred_L[0] = (y2 + ((3 * (pred_T[3] + pred_L[0]) - 2 * pred_T[0]) >> 2)) & 0xff;
+                dst_v[x / 2] = pred_L[2] = (v + (((pred_L[2] - pred_TL[2]) >> 1) + pred_T[2])) & 0xff;
+
+                pred_TL[0] = pred_T[3];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+            }
+        }
+
+        dst_y += p->linesize[0];
+        dst_u += p->linesize[1];
+        dst_v += p->linesize[2];
+    }
+}
+
+static void decode_ybri(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_y = p->data[0];
+    dst_u = p->data[1];
+    dst_v = p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst_y[x] = get_bits(gb, 8);
+            dst_u[x] = get_bits(gb, 8);
+            dst_v[x] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { 125, -128, -128, -128 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int y, u, v;
+
+            y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_y[x] = pred[0] = (y + pred[0]) & 0xff;
+            dst_u[x] = pred[1] = (u + pred[1]) & 0xff;
+            dst_v[x] = pred[2] = (v + pred[2]) & 0xff;
+        }
+    }
+
+    dst_y += p->linesize[0];
+    dst_u += p->linesize[1];
+    dst_v += p->linesize[2];
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_y[x] = get_bits(gb, 8);
+                dst_u[x] = get_bits(gb, 8);
+                dst_v[x] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_L[4];
+            int y, u, v;
+
+            pred_L[0] = dst_y[-p->linesize[0]];
+            pred_L[1] = dst_u[-p->linesize[1]];
+            pred_L[2] = dst_v[-p->linesize[2]];
+
+            for (x = 0; x < avctx->width; x++) {
+                y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x] = pred_L[0] = (y + pred_L[0]) & 0xff;
+                dst_u[x] = pred_L[1] = (u + pred_L[1]) & 0xff;
+                dst_v[x] = pred_L[2] = (v + pred_L[2]) & 0xff;
+            }
+        }
+
+        dst_y += p->linesize[0];
+        dst_u += p->linesize[1];
+        dst_v += p->linesize[2];
+    }
+}
+
+static void decode_ybr(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_y = p->data[0];
+    dst_u = p->data[1];
+    dst_v = p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst_y[x] = get_bits(gb, 8);
+            dst_u[x] = get_bits(gb, 8);
+            dst_v[x] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { 125, -128, -128, -128 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int y, u, v;
+
+            y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_y[x] = pred[0] = (y + pred[0]) & 0xff;
+            dst_u[x] = pred[1] = (u + pred[1]) & 0xff;
+            dst_v[x] = pred[2] = (v + pred[2]) & 0xff;
+        }
+    }
+
+    dst_y += p->linesize[0];
+    dst_u += p->linesize[1];
+    dst_v += p->linesize[2];
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_y[x] = get_bits(gb, 8);
+                dst_u[x] = get_bits(gb, 8);
+                dst_v[x] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int y, u, v;
+
+            pred_TL[0] = pred_L[0] = dst_y[-p->linesize[0]];
+            pred_TL[1] = pred_L[1] = dst_u[-p->linesize[1]];
+            pred_TL[2] = pred_L[2] = dst_v[-p->linesize[2]];
+
+            for (x = 0; x < avctx->width; x++) {
+                pred_T[0] = dst_y[-p->linesize[0] + x];
+                pred_T[1] = dst_u[-p->linesize[1] + x];
+                pred_T[2] = dst_v[-p->linesize[2] + x];
+
+                y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_y[x] = pred_L[0] = (y + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff;
+                dst_u[x] = pred_L[1] = (u + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0xff;
+                dst_v[x] = pred_L[2] = (v + ((3 * (pred_T[2] + pred_L[2]) - 2 * pred_TL[2]) >> 2)) & 0xff;
+
+                pred_TL[0] = pred_T[0];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+            }
+        }
+
+        dst_y += p->linesize[0];
+        dst_u += p->linesize[1];
+        dst_v += p->linesize[2];
+    }
+}
+
+static void decode_aybri(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst_a, *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_a = p->data[3];
+    dst_y = p->data[0];
+    dst_u = p->data[1];
+    dst_v = p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst_a[x] = get_bits(gb, 8);
+            dst_y[x] = get_bits(gb, 8);
+            dst_u[x] = get_bits(gb, 8);
+            dst_v[x] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { 125, 125, -128, -128 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int a, y, u, v;
+
+            a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_a[x] = pred[0] = (a + pred[0]) & 0xff;
+            dst_y[x] = pred[1] = (y + pred[1]) & 0xff;
+            dst_u[x] = pred[2] = (u + pred[2]) & 0xff;
+            dst_v[x] = pred[3] = (v + pred[3]) & 0xff;
+        }
+    }
+
+    dst_a += p->linesize[3];
+    dst_y += p->linesize[0];
+    dst_u += p->linesize[1];
+    dst_v += p->linesize[2];
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_a[x] = get_bits(gb, 8);
+                dst_y[x] = get_bits(gb, 8);
+                dst_u[x] = get_bits(gb, 8);
+                dst_v[x] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_L[4];
+            int a, y, u, v;
+
+            pred_L[0] = dst_a[-p->linesize[3]];
+            pred_L[1] = dst_y[-p->linesize[0]];
+            pred_L[2] = dst_u[-p->linesize[1]];
+            pred_L[3] = dst_v[-p->linesize[2]];
+
+            for (x = 0; x < avctx->width; x++) {
+                a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_a[x] = pred_L[0] = (a + pred_L[0]) & 0xff;
+                dst_y[x] = pred_L[1] = (y + pred_L[1]) & 0xff;
+                dst_u[x] = pred_L[2] = (u + pred_L[2]) & 0xff;
+                dst_v[x] = pred_L[3] = (v + pred_L[3]) & 0xff;
+            }
+        }
+
+        dst_a += p->linesize[3];
+        dst_y += p->linesize[0];
+        dst_u += p->linesize[1];
+        dst_v += p->linesize[2];
+    }
+}
+
+static void decode_aybr(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst_a, *dst_y, *dst_u, *dst_v;
+    int x, y;
+
+    dst_a = p->data[3];
+    dst_y = p->data[0];
+    dst_u = p->data[1];
+    dst_v = p->data[2];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst_a[x] = get_bits(gb, 8);
+            dst_y[x] = get_bits(gb, 8);
+            dst_u[x] = get_bits(gb, 8);
+            dst_v[x] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { 125, 125, -128, -128 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int a, y, u, v;
+
+            a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_a[x] = pred[0] = (a + pred[0]) & 0xff;
+            dst_y[x] = pred[1] = (y + pred[1]) & 0xff;
+            dst_u[x] = pred[2] = (u + pred[2]) & 0xff;
+            dst_v[x] = pred[3] = (v + pred[3]) & 0xff;
+        }
+    }
+
+    dst_a += p->linesize[3];
+    dst_y += p->linesize[0];
+    dst_u += p->linesize[1];
+    dst_v += p->linesize[2];
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_a[x] = get_bits(gb, 8);
+                dst_y[x] = get_bits(gb, 8);
+                dst_u[x] = get_bits(gb, 8);
+                dst_v[x] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int a, y, u, v;
+
+            pred_TL[0] = pred_L[0] = dst_a[-p->linesize[3]];
+            pred_TL[1] = pred_L[1] = dst_y[-p->linesize[0]];
+            pred_TL[2] = pred_L[2] = dst_u[-p->linesize[1]];
+            pred_TL[3] = pred_L[3] = dst_v[-p->linesize[2]];
+
+            for (x = 0; x < avctx->width; x++) {
+                pred_T[0] = dst_a[-p->linesize[3] + x];
+                pred_T[1] = dst_y[-p->linesize[0] + x];
+                pred_T[2] = dst_u[-p->linesize[1] + x];
+                pred_T[3] = dst_v[-p->linesize[2] + x];
+
+                a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                y = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                u = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                v = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_a[x] = pred_L[0] = (a + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff;
+                dst_y[x] = pred_L[1] = (y + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0xff;
+                dst_u[x] = pred_L[2] = (u + ((3 * (pred_T[2] + pred_L[2]) - 2 * pred_TL[2]) >> 2)) & 0xff;
+                dst_v[x] = pred_L[3] = (v + ((3 * (pred_T[3] + pred_L[3]) - 2 * pred_TL[3]) >> 2)) & 0xff;
+
+                pred_TL[0] = pred_T[0];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+                pred_TL[3] = pred_T[3];
+            }
+        }
+
+        dst_a += p->linesize[3];
+        dst_y += p->linesize[0];
+        dst_u += p->linesize[1];
+        dst_v += p->linesize[2];
+    }
+}
+
+static void decode_argxi(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_r, *dst_g, *dst_b, *dst_a;
+    int x, y;
+
+    dst_r = (uint16_t *)p->data[2];
+    dst_g = (uint16_t *)p->data[0];
+    dst_b = (uint16_t *)p->data[1];
+    dst_a = (uint16_t *)p->data[3];
+
+    for (y = 0; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_a[x] = get_bits(gb, 10);
+                dst_r[x] = get_bits(gb, 10);
+                dst_g[x] = get_bits(gb, 10);
+                dst_b[x] = get_bits(gb, 10);
+            }
+        } else {
+            int pred[4] = { 512, 512, 512, 512 };
+
+            for (x = 0; x < avctx->width; x++) {
+                int r, g, b, a;
+
+                a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_a[x] = pred[3] = (a + pred[3]) & 0x3ff;
+                dst_r[x] = pred[0] = (r + pred[0]) & 0x3ff;
+                dst_g[x] = pred[1] = (r + g + pred[1]) & 0x3ff;
+                dst_b[x] = pred[2] = (r + g + b + pred[2]) & 0x3ff;
+            }
+        }
+
+        dst_r += p->linesize[2] / 2;
+        dst_g += p->linesize[0] / 2;
+        dst_b += p->linesize[1] / 2;
+        dst_a += p->linesize[3] / 2;
+    }
+}
+
+static void decode_argx(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_r, *dst_g, *dst_b, *dst_a;
+    int x, y;
+
+    dst_r = (uint16_t *)p->data[2];
+    dst_g = (uint16_t *)p->data[0];
+    dst_b = (uint16_t *)p->data[1];
+    dst_a = (uint16_t *)p->data[3];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst_a[x] = get_bits(gb, 10);
+            dst_r[x] = get_bits(gb, 10);
+            dst_g[x] = get_bits(gb, 10);
+            dst_b[x] = get_bits(gb, 10);
+        }
+    } else {
+        int pred[4] = { 512, 512, 512, 512 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int r, g, b, a;
+
+            a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_a[x] = pred[3] = (a + pred[3]) & 0x3ff;
+            dst_r[x] = pred[0] = (r + pred[0]) & 0x3ff;
+            dst_g[x] = pred[1] = (r + g + pred[1]) & 0x3ff;
+            dst_b[x] = pred[2] = (r + g + b + pred[2]) & 0x3ff;
+        }
+    }
+
+    dst_r += p->linesize[2] / 2;
+    dst_g += p->linesize[0] / 2;
+    dst_b += p->linesize[1] / 2;
+    dst_a += p->linesize[3] / 2;
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_a[x] = get_bits(gb, 10);
+                dst_r[x] = get_bits(gb, 10);
+                dst_g[x] = get_bits(gb, 10);
+                dst_b[x] = get_bits(gb, 10);
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int r, g, b, a;
+
+            pred_TL[0] = pred_L[0] = dst_r[-p->linesize[2] / 2];
+            pred_TL[1] = pred_L[1] = dst_g[-p->linesize[0] / 2];
+            pred_TL[2] = pred_L[2] = dst_b[-p->linesize[1] / 2];
+            pred_TL[3] = pred_L[3] = dst_a[-p->linesize[3] / 2];
+
+            for (x = 0; x < avctx->width; x++) {
+                pred_T[0] = dst_r[-p->linesize[2] / 2 + x];
+                pred_T[1] = dst_g[-p->linesize[0] / 2 + x];
+                pred_T[2] = dst_b[-p->linesize[1] / 2 + x];
+                pred_T[3] = dst_a[-p->linesize[3] / 2 + x];
+
+                a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_a[x] = pred_L[3] = (a + ((3 * (pred_T[3] + pred_L[3]) - 2 * pred_TL[3]) >> 2)) & 0x3ff;
+                dst_r[x] = pred_L[0] = (r + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff;
+                dst_g[x] = pred_L[1] = (r + g + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0x3ff;
+                dst_b[x] = pred_L[2] = (r + g + b + ((3 * (pred_T[2] + pred_L[2]) - 2 * pred_TL[2]) >> 2)) & 0x3ff;
+
+                pred_TL[0] = pred_T[0];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+                pred_TL[3] = pred_T[3];
+            }
+        }
+
+        dst_r += p->linesize[2] / 2;
+        dst_g += p->linesize[0] / 2;
+        dst_b += p->linesize[1] / 2;
+        dst_a += p->linesize[3] / 2;
+    }
+}
+
+static void decode_rgbxi(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_r, *dst_g, *dst_b;
+    int x, y;
+
+    dst_r = (uint16_t *)p->data[2];
+    dst_g = (uint16_t *)p->data[0];
+    dst_b = (uint16_t *)p->data[1];
+
+    for (y = 0; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_r[x] = get_bits(gb, 10);
+                dst_g[x] = get_bits(gb, 10);
+                dst_b[x] = get_bits(gb, 10);
+            }
+        } else {
+            int pred[4] = { 512, 512, 512, 0 };
+
+            for (x = 0; x < avctx->width; x++) {
+                int r, g, b;
+
+                r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_r[x] = pred[0] = (r + pred[0]) & 0x3ff;
+                dst_g[x] = pred[1] = (r + g + pred[1]) & 0x3ff;
+                dst_b[x] = pred[2] = (r + g + b + pred[2]) & 0x3ff;
+            }
+        }
+
+        dst_r += p->linesize[2] / 2;
+        dst_g += p->linesize[0] / 2;
+        dst_b += p->linesize[1] / 2;
+    }
+}
+
+static void decode_rgbx(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint16_t *dst_r, *dst_g, *dst_b;
+    int x, y;
+
+    dst_r = (uint16_t *)p->data[2];
+    dst_g = (uint16_t *)p->data[0];
+    dst_b = (uint16_t *)p->data[1];
+
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst_r[x] = get_bits(gb, 10);
+            dst_g[x] = get_bits(gb, 10);
+            dst_b[x] = get_bits(gb, 10);
+        }
+    } else {
+        int pred[4] = { 512, 512, 512, 0 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int r, g, b;
+
+            r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst_r[x] = pred[0] = (r + pred[0]) & 0x3ff;
+            dst_g[x] = pred[1] = (r + g + pred[1]) & 0x3ff;
+            dst_b[x] = pred[2] = (r + g + b + pred[2]) & 0x3ff;
+        }
+    }
+
+    dst_r += p->linesize[2] / 2;
+    dst_g += p->linesize[0] / 2;
+    dst_b += p->linesize[1] / 2;
+
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst_r[x] = get_bits(gb, 10);
+                dst_g[x] = get_bits(gb, 10);
+                dst_b[x] = get_bits(gb, 10);
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int r, g, b;
+
+            pred_TL[0] = pred_L[0] = dst_r[-p->linesize[2] / 2];
+            pred_TL[1] = pred_L[1] = dst_g[-p->linesize[0] / 2];
+            pred_TL[2] = pred_L[2] = dst_b[-p->linesize[1] / 2];
+
+            for (x = 0; x < avctx->width; x++) {
+                pred_T[0] = dst_r[-p->linesize[2] / 2 + x];
+                pred_T[1] = dst_g[-p->linesize[0] / 2 + x];
+                pred_T[2] = dst_b[-p->linesize[1] / 2 + x];
+
+                r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst_r[x] = pred_L[0] = (r + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0x3ff;
+                dst_g[x] = pred_L[1] = (r + g + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0x3ff;
+                dst_b[x] = pred_L[2] = (r + g + b + ((3 * (pred_T[2] + pred_L[2]) - 2 * pred_TL[2]) >> 2)) & 0x3ff;
+
+                pred_TL[0] = pred_T[0];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+            }
+        }
+
+        dst_r += p->linesize[2] / 2;
+        dst_g += p->linesize[0] / 2;
+        dst_b += p->linesize[1] / 2;
+    }
+}
+
+static void decode_argbi(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst;
+    int x, y;
+
+    dst = p->data[0];
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst[x * 4 + 0] = get_bits(gb, 8);
+            dst[x * 4 + 1] = get_bits(gb, 8);
+            dst[x * 4 + 2] = get_bits(gb, 8);
+            dst[x * 4 + 3] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { -128, -128, -128, -128 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int a, r, g, b;
+
+            a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst[4 * x + 0] = pred[0] = (a + pred[0]) & 0xff;
+            dst[4 * x + 1] = pred[1] = (r + pred[1]) & 0xff;
+            dst[4 * x + 2] = pred[2] = (r + g + pred[2]) & 0xff;
+            dst[4 * x + 3] = pred[3] = (r + g + b + pred[3]) & 0xff;
+        }
+    }
+
+    dst += p->linesize[0];
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst[x * 4 + 0] = get_bits(gb, 8);
+                dst[x * 4 + 1] = get_bits(gb, 8);
+                dst[x * 4 + 2] = get_bits(gb, 8);
+                dst[x * 4 + 3] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_L[4];
+            int a, r, g, b;
+
+            pred_L[0] = dst[-p->linesize[0] + 0];
+            pred_L[1] = dst[-p->linesize[0] + 1];
+            pred_L[2] = dst[-p->linesize[0] + 2];
+            pred_L[3] = dst[-p->linesize[0] + 3];
+
+            for (x = 0; x < avctx->width; x++) {
+                a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst[4 * x + 0] = pred_L[0] = (a + pred_L[0]) & 0xff;
+                dst[4 * x + 1] = pred_L[1] = (r + pred_L[1]) & 0xff;
+                dst[4 * x + 2] = pred_L[2] = (r + g + pred_L[2]) & 0xff;
+                dst[4 * x + 3] = pred_L[3] = (r + g + b + pred_L[3]) & 0xff;
+            }
+        }
+        dst += p->linesize[0];
+    }
+}
+
+static void decode_argb(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst;
+    int x, y;
+
+    dst = p->data[0];
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst[x * 4 + 0] = get_bits(gb, 8);
+            dst[x * 4 + 1] = get_bits(gb, 8);
+            dst[x * 4 + 2] = get_bits(gb, 8);
+            dst[x * 4 + 3] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { -128, -128, -128, -128 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int a, r, g, b;
+
+            a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst[4 * x + 0] = pred[0] = (a + pred[0]) & 0xff;
+            dst[4 * x + 1] = pred[1] = (r + pred[1]) & 0xff;
+            dst[4 * x + 2] = pred[2] = (r + g + pred[2]) & 0xff;
+            dst[4 * x + 3] = pred[3] = (r + g + b + pred[3]) & 0xff;
+        }
+    }
+
+    dst += p->linesize[0];
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst[x * 4 + 0] = get_bits(gb, 8);
+                dst[x * 4 + 1] = get_bits(gb, 8);
+                dst[x * 4 + 2] = get_bits(gb, 8);
+                dst[x * 4 + 3] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int a, r, g, b;
+
+            pred_TL[0] = pred_L[0] = dst[-p->linesize[0] + 0];
+            pred_TL[1] = pred_L[1] = dst[-p->linesize[0] + 1];
+            pred_TL[2] = pred_L[2] = dst[-p->linesize[0] + 2];
+            pred_TL[3] = pred_L[3] = dst[-p->linesize[0] + 3];
+
+            for (x = 0; x < avctx->width; x++) {
+                pred_T[0] = dst[-p->linesize[0] + 4 * x + 0];
+                pred_T[1] = dst[-p->linesize[0] + 4 * x + 1];
+                pred_T[2] = dst[-p->linesize[0] + 4 * x + 2];
+                pred_T[3] = dst[-p->linesize[0] + 4 * x + 3];
+
+                a = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst[4 * x + 0] = pred_L[0] = (a + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff;
+                dst[4 * x + 1] = pred_L[1] = (r + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0xff;
+                dst[4 * x + 2] = pred_L[2] = (r + g + ((3 * (pred_T[2] + pred_L[2]) - 2 * pred_TL[2]) >> 2)) & 0xff;
+                dst[4 * x + 3] = pred_L[3] = (r + g + b + ((3 * (pred_T[3] + pred_L[3]) - 2 * pred_TL[3]) >> 2)) & 0xff;
+
+                pred_TL[0] = pred_T[0];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+                pred_TL[3] = pred_T[3];
+            }
+        }
+        dst += p->linesize[0];
+    }
+}
+
+static void decode_rgbi(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst;
+    int x, y;
+
+    dst = p->data[0];
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst[x * 4 + 0] = get_bits(gb, 8);
+            dst[x * 4 + 1] = get_bits(gb, 8);
+            dst[x * 4 + 2] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { -128, -128, -128, -128 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int r, g, b;
+
+            r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst[4 * x + 0] = pred[0] = (r + pred[0]) & 0xff;
+            dst[4 * x + 1] = pred[1] = (r + g + pred[1]) & 0xff;
+            dst[4 * x + 2] = pred[2] = (r + g + b + pred[2]) & 0xff;
+        }
+    }
+
+    dst += p->linesize[0];
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst[x * 4 + 0] = get_bits(gb, 8);
+                dst[x * 4 + 1] = get_bits(gb, 8);
+                dst[x * 4 + 2] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_L[4];
+            int r, g, b;
+
+            pred_L[0] = dst[-p->linesize[0] + 0];
+            pred_L[1] = dst[-p->linesize[0] + 1];
+            pred_L[2] = dst[-p->linesize[0] + 2];
+
+            for (x = 0; x < avctx->width; x++) {
+                r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst[4 * x + 0] = pred_L[0] = (r + pred_L[0]) & 0xff;
+                dst[4 * x + 1] = pred_L[1] = (r + g + pred_L[1]) & 0xff;
+                dst[4 * x + 2] = pred_L[2] = (r + g + b + pred_L[2]) & 0xff;
+            }
+        }
+        dst += p->linesize[0];
+    }
+}
+
+static void decode_rgb(AVCodecContext *avctx, AVFrame *p, GetBitContext *gb)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    uint8_t *dst;
+    int x, y;
+
+    dst = p->data[0];
+    if (get_bits1(gb)) {
+        for (x = 0; x < avctx->width; x++) {
+            dst[x * 4 + 0] = get_bits(gb, 8);
+            dst[x * 4 + 1] = get_bits(gb, 8);
+            dst[x * 4 + 2] = get_bits(gb, 8);
+        }
+    } else {
+        int pred[4] = { -128, -128, -128, -128 };
+
+        for (x = 0; x < avctx->width; x++) {
+            int r, g, b;
+
+            r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+            g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+            b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+            dst[4 * x + 0] = pred[0] = (r + pred[0]) & 0xff;
+            dst[4 * x + 1] = pred[1] = (r + g + pred[1]) & 0xff;
+            dst[4 * x + 2] = pred[2] = (r + g + b + pred[2]) & 0xff;
+        }
+    }
+
+    dst += p->linesize[0];
+    for (y = 1; y < avctx->height; y++) {
+        if (get_bits1(gb)) {
+            for (x = 0; x < avctx->width; x++) {
+                dst[x * 4 + 0] = get_bits(gb, 8);
+                dst[x * 4 + 1] = get_bits(gb, 8);
+                dst[x * 4 + 2] = get_bits(gb, 8);
+            }
+        } else {
+            int pred_TL[4], pred_L[4], pred_T[4];
+            int r, g, b;
+
+            pred_TL[0] = pred_L[0] = dst[-p->linesize[0] + 0];
+            pred_TL[1] = pred_L[1] = dst[-p->linesize[0] + 1];
+            pred_TL[2] = pred_L[2] = dst[-p->linesize[0] + 2];
+
+            for (x = 0; x < avctx->width; x++) {
+                pred_T[0] = dst[-p->linesize[0] + 4 * x + 0];
+                pred_T[1] = dst[-p->linesize[0] + 4 * x + 1];
+                pred_T[2] = dst[-p->linesize[0] + 4 * x + 2];
+
+                r = get_vlc2(gb, s->vlc[0].table, s->vlc[0].bits, 2);
+                g = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+                b = get_vlc2(gb, s->vlc[1].table, s->vlc[1].bits, 2);
+
+                dst[4 * x + 0] = pred_L[0] = (r + ((3 * (pred_T[0] + pred_L[0]) - 2 * pred_TL[0]) >> 2)) & 0xff;
+                dst[4 * x + 1] = pred_L[1] = (r + g + ((3 * (pred_T[1] + pred_L[1]) - 2 * pred_TL[1]) >> 2)) & 0xff;
+                dst[4 * x + 2] = pred_L[2] = (r + g + b + ((3 * (pred_T[2] + pred_L[2]) - 2 * pred_TL[2]) >> 2)) & 0xff;
+
+                pred_TL[0] = pred_T[0];
+                pred_TL[1] = pred_T[1];
+                pred_TL[2] = pred_T[2];
+            }
+        }
+        dst += p->linesize[0];
+    }
+}
+
+static int build_vlc(VLC *vlc, const uint8_t *len, int count)
+{
+    uint32_t codes[1024];
+    uint8_t bits[1024];
+    uint16_t syms[1024];
+    uint64_t index;
+    int i;
+
+    index = 0;
+    for (i = 0; i < count; i++) {
+        codes[i]  = index >> (32 - len[i]);
+        bits[i] = len[i];
+        syms[i]  = i;
+        index += 1ULL << (32 - len[i]);
+    }
+
+    ff_free_vlc(vlc);
+    return ff_init_vlc_sparse(vlc, 16, count,
+                              bits,  sizeof(*bits),  sizeof(*bits),
+                              codes, sizeof(*codes), sizeof(*codes),
+                              syms,  sizeof(*syms),  sizeof(*syms), 0);
+}
+
+static int decode_frame(AVCodecContext *avctx,
+                        void *data, int *got_frame,
+                        AVPacket *avpkt)
+{
+    SheerVideoContext *s = avctx->priv_data;
+    ThreadFrame frame = { .f = data };
+    AVFrame *p = data;
+    GetBitContext gb;
+    unsigned format;
+    int ret;
+
+    if (avpkt->size <= 20)
+        return AVERROR_INVALIDDATA;
+
+    if (AV_RL32(avpkt->data) != MKTAG('S','h','i','r') &&
+        AV_RL32(avpkt->data) != MKTAG('Z','w','a','k'))
+        return AVERROR_INVALIDDATA;
+
+    format = AV_RL32(avpkt->data + 16);
+    switch (format) {
+    case MKTAG(' ', 'R', 'G', 'B'):
+        avctx->pix_fmt = AV_PIX_FMT_RGB0;
+        s->decode_frame = decode_rgb;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_r_rgb, 256);
+            ret |= build_vlc(&s->vlc[1], l_g_rgb, 256);
+        }
+        break;
+    case MKTAG(' ', 'r', 'G', 'B'):
+        avctx->pix_fmt = AV_PIX_FMT_RGB0;
+        s->decode_frame = decode_rgbi;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_r_rgbi, 256);
+            ret |= build_vlc(&s->vlc[1], l_g_rgbi, 256);
+        }
+        break;
+    case MKTAG('A', 'R', 'G', 'X'):
+        avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
+        s->decode_frame = decode_argx;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_r_rgbx, 1024);
+            ret |= build_vlc(&s->vlc[1], l_g_rgbx, 1024);
+        }
+        break;
+    case MKTAG('A', 'r', 'G', 'X'):
+        avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
+        s->decode_frame = decode_argxi;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_r_rgbxi, 1024);
+            ret |= build_vlc(&s->vlc[1], l_g_rgbxi, 1024);
+        }
+        break;
+    case MKTAG('R', 'G', 'B', 'X'):
+        avctx->pix_fmt = AV_PIX_FMT_GBRP10;
+        s->decode_frame = decode_rgbx;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_r_rgbx, 1024);
+            ret |= build_vlc(&s->vlc[1], l_g_rgbx, 1024);
+        }
+        break;
+    case MKTAG('r', 'G', 'B', 'X'):
+        avctx->pix_fmt = AV_PIX_FMT_GBRP10;
+        s->decode_frame = decode_rgbxi;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_r_rgbxi, 1024);
+            ret |= build_vlc(&s->vlc[1], l_g_rgbxi, 1024);
+        }
+        break;
+    case MKTAG('A', 'R', 'G', 'B'):
+        avctx->pix_fmt = AV_PIX_FMT_ARGB;
+        s->decode_frame = decode_argb;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_r_rgb, 256);
+            ret |= build_vlc(&s->vlc[1], l_g_rgb, 256);
+        }
+        break;
+    case MKTAG('A', 'r', 'G', 'B'):
+        avctx->pix_fmt = AV_PIX_FMT_ARGB;
+        s->decode_frame = decode_argbi;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_r_rgbi, 256);
+            ret |= build_vlc(&s->vlc[1], l_g_rgbi, 256);
+        }
+        break;
+    case MKTAG('A', 'Y', 'B', 'R'):
+    case MKTAG('A', 'Y', 'b', 'R'):
+        avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
+        s->decode_frame = decode_aybr;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_ybr, 256);
+            ret |= build_vlc(&s->vlc[1], l_u_ybr, 256);
+        }
+        break;
+    case MKTAG('A', 'y', 'B', 'R'):
+    case MKTAG('A', 'y', 'b', 'R'):
+        avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
+        s->decode_frame = decode_aybri;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_ybri, 256);
+            ret |= build_vlc(&s->vlc[1], l_u_ybri, 256);
+        }
+        break;
+    case MKTAG(' ', 'Y', 'B', 'R'):
+    case MKTAG(' ', 'Y', 'b', 'R'):
+        avctx->pix_fmt = AV_PIX_FMT_YUV444P;
+        s->decode_frame = decode_ybr;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_ybr, 256);
+            ret |= build_vlc(&s->vlc[1], l_u_ybr, 256);
+        }
+        break;
+    case MKTAG(' ', 'y', 'B', 'R'):
+    case MKTAG(' ', 'y', 'b', 'R'):
+        avctx->pix_fmt = AV_PIX_FMT_YUV444P;
+        s->decode_frame = decode_ybri;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_ybri, 256);
+            ret |= build_vlc(&s->vlc[1], l_u_ybri, 256);
+        }
+        break;
+    case MKTAG('Y', 'B', 'R', 0x0a):
+        avctx->pix_fmt = AV_PIX_FMT_YUV444P10;
+        s->decode_frame = decode_ybr10;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_ybr10, 1024);
+            ret |= build_vlc(&s->vlc[1], l_u_ybr10, 1024);
+        }
+        break;
+    case MKTAG('y', 'B', 'R', 0x0a):
+        avctx->pix_fmt = AV_PIX_FMT_YUV444P10;
+        s->decode_frame = decode_ybr10i;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_ybr10i, 1024);
+            ret |= build_vlc(&s->vlc[1], l_u_ybr10i, 1024);
+        }
+        break;
+    case MKTAG('C', 'A', '4', 'p'):
+        avctx->pix_fmt = AV_PIX_FMT_YUVA444P10;
+        s->decode_frame = decode_ca4p;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_ybr10, 1024);
+            ret |= build_vlc(&s->vlc[1], l_u_ybr10, 1024);
+        }
+        break;
+    case MKTAG('C', 'A', '4', 'i'):
+        avctx->pix_fmt = AV_PIX_FMT_YUVA444P10;
+        s->decode_frame = decode_ca4i;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_ybr10i, 1024);
+            ret |= build_vlc(&s->vlc[1], l_u_ybr10i, 1024);
+        }
+        break;
+    case MKTAG('B', 'Y', 'R', 'Y'):
+        avctx->pix_fmt = AV_PIX_FMT_YUV422P;
+        s->decode_frame = decode_byry;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_byry, 256);
+            ret |= build_vlc(&s->vlc[1], l_u_byry, 256);
+        }
+        break;
+    case MKTAG('B', 'Y', 'R', 'y'):
+        avctx->pix_fmt = AV_PIX_FMT_YUV422P;
+        s->decode_frame = decode_byryi;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_byryi, 256);
+            ret |= build_vlc(&s->vlc[1], l_u_byryi, 256);
+        }
+        break;
+    case MKTAG('Y', 'b', 'Y', 'r'):
+        avctx->pix_fmt = AV_PIX_FMT_YUV422P;
+        s->decode_frame = decode_ybyr;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_ybyr, 256);
+            ret |= build_vlc(&s->vlc[1], l_u_ybyr, 256);
+        }
+        break;
+    case MKTAG('C', '8', '2', 'p'):
+        avctx->pix_fmt = AV_PIX_FMT_YUVA422P;
+        s->decode_frame = decode_c82p;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_byry, 256);
+            ret |= build_vlc(&s->vlc[1], l_u_byry, 256);
+        }
+        break;
+    case MKTAG('C', '8', '2', 'i'):
+        avctx->pix_fmt = AV_PIX_FMT_YUVA422P;
+        s->decode_frame = decode_c82i;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_byryi, 256);
+            ret |= build_vlc(&s->vlc[1], l_u_byryi, 256);
+        }
+        break;
+    case MKTAG(0xa2, 'Y', 'R', 'Y'):
+        avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
+        s->decode_frame = decode_yry10;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_yry10, 1024);
+            ret |= build_vlc(&s->vlc[1], l_u_yry10, 1024);
+        }
+        break;
+    case MKTAG(0xa2, 'Y', 'R', 'y'):
+        avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
+        s->decode_frame = decode_yry10i;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_yry10i, 1024);
+            ret |= build_vlc(&s->vlc[1], l_u_yry10i, 1024);
+        }
+        break;
+    case MKTAG('C', 'A', '2', 'p'):
+        avctx->pix_fmt = AV_PIX_FMT_YUVA422P10;
+        s->decode_frame = decode_ca2p;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_yry10, 1024);
+            ret |= build_vlc(&s->vlc[1], l_u_yry10, 1024);
+        }
+        break;
+    case MKTAG('C', 'A', '2', 'i'):
+        avctx->pix_fmt = AV_PIX_FMT_YUVA422P10;
+        s->decode_frame = decode_ca2i;
+        if (s->format != format) {
+            ret  = build_vlc(&s->vlc[0], l_y_yry10i, 1024);
+            ret |= build_vlc(&s->vlc[1], l_u_yry10i, 1024);
+        }
+        break;
+    default:
+        avpriv_request_sample(avctx, "unsupported format: 0x%X", format);
+        return AVERROR_PATCHWELCOME;
+    }
+
+    if (s->format != format) {
+        if (ret < 0)
+            return ret;
+        s->format = format;
+    }
+
+    p->pict_type = AV_PICTURE_TYPE_I;
+    p->key_frame = 1;
+
+    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
+        return ret;
+
+    if ((ret = init_get_bits8(&gb, avpkt->data + 20, avpkt->size - 20)) < 0)
+        return ret;
+
+    s->decode_frame(avctx, p, &gb);
+
+    *got_frame = 1;
+
+    return avpkt->size;
+}
+
+#if HAVE_THREADS
+static int decode_init_thread_copy(AVCodecContext *avctx)
+{
+    SheerVideoContext *s = avctx->priv_data;
+
+    s->format = 0;
+    memset(&s->vlc[0], 0, sizeof(s->vlc[0]));
+    memset(&s->vlc[1], 0, sizeof(s->vlc[1]));
+
+    return 0;
+}
+#endif
+
+static av_cold int decode_end(AVCodecContext *avctx)
+{
+    SheerVideoContext *s = avctx->priv_data;
+
+    ff_free_vlc(&s->vlc[0]);
+    ff_free_vlc(&s->vlc[1]);
+
+    return 0;
+}
+
+AVCodec ff_sheervideo_decoder = {
+    .name             = "sheervideo",
+    .long_name        = NULL_IF_CONFIG_SMALL("BitJazz SheerVideo"),
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_SHEERVIDEO,
+    .priv_data_size   = sizeof(SheerVideoContext),
+    .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
+    .close            = decode_end,
+    .decode           = decode_frame,
+    .capabilities     = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+};
diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c
index 0f5be96..e4cef61 100644
--- a/libavcodec/shorten.c
+++ b/libavcodec/shorten.c
@@ -23,7 +23,6 @@
  * @file
  * Shorten decoder
  * @author Jeff Muizelaar
- *
  */
 
 #include <limits.h>
@@ -165,9 +164,13 @@ static void fix_bitshift(ShortenContext *s, int32_t *buffer)
 {
     int i;
 
-    if (s->bitshift != 0)
+    if (s->bitshift == 32) {
+        for (i = 0; i < s->blocksize; i++)
+            buffer[i] = 0;
+    } else if (s->bitshift != 0) {
         for (i = 0; i < s->blocksize; i++)
             buffer[i] <<= s->bitshift;
+    }
 }
 
 static int init_offset(ShortenContext *s)
@@ -196,6 +199,70 @@ static int init_offset(ShortenContext *s)
     return 0;
 }
 
+static int decode_aiff_header(AVCodecContext *avctx, const uint8_t *header,
+                              int header_size)
+{
+    int len, bps, exp;
+    GetByteContext gb;
+    uint64_t val;
+    uint32_t tag;
+
+    bytestream2_init(&gb, header, header_size);
+
+    if (bytestream2_get_le32(&gb) != MKTAG('F', 'O', 'R', 'M')) {
+        av_log(avctx, AV_LOG_ERROR, "missing FORM tag\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    bytestream2_skip(&gb, 4); /* chunk size */
+
+    tag = bytestream2_get_le32(&gb);
+    if (tag != MKTAG('A', 'I', 'F', 'F')) {
+        av_log(avctx, AV_LOG_ERROR, "missing AIFF tag\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    while (bytestream2_get_le32(&gb) != MKTAG('C', 'O', 'M', 'M')) {
+        len = bytestream2_get_be32(&gb);
+        bytestream2_skip(&gb, len + (len & 1));
+        if (len < 0 || bytestream2_get_bytes_left(&gb) < 18) {
+            av_log(avctx, AV_LOG_ERROR, "no COMM chunk found\n");
+            return AVERROR_INVALIDDATA;
+        }
+    }
+    len = bytestream2_get_be32(&gb);
+
+    if (len < 18) {
+        av_log(avctx, AV_LOG_ERROR, "COMM chunk was too short\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    bytestream2_skip(&gb, 6);
+    bps = bytestream2_get_be16(&gb);
+    avctx->bits_per_coded_sample = bps;
+
+    if (bps != 16 && bps != 8) {
+        av_log(avctx, AV_LOG_ERROR, "unsupported number of bits per sample: %d\n", bps);
+        return AVERROR(ENOSYS);
+    }
+
+    exp = bytestream2_get_be16(&gb) - 16383 - 63;
+    val = bytestream2_get_be64(&gb);
+    if (exp < -63 || exp > 63) {
+        av_log(avctx, AV_LOG_ERROR, "exp %d is out of range\n", exp);
+        return AVERROR_INVALIDDATA;
+    }
+    if (exp >= 0)
+        avctx->sample_rate = val << exp;
+    else
+        avctx->sample_rate = (val + (1ULL<<(-exp-1))) >> -exp;
+    len -= 18;
+    if (len > 0)
+        av_log(avctx, AV_LOG_INFO, "%d header bytes unparsed\n", len);
+
+    return 0;
+}
+
 static int decode_wave_header(AVCodecContext *avctx, const uint8_t *header,
                               int header_size)
 {
@@ -388,6 +455,9 @@ static int read_header(ShortenContext *s)
     if (s->version > 1)
         s->lpcqoffset = V2LPCQOFFSET;
 
+    if (s->avctx->extradata_size > 0)
+        goto end;
+
     if (get_ur_golomb_shorten(&s->gb, FNSIZE) != FN_VERBATIM) {
         av_log(s->avctx, AV_LOG_ERROR,
                "missing verbatim section at beginning of stream\n");
@@ -405,9 +475,18 @@ static int read_header(ShortenContext *s)
     for (i = 0; i < s->header_size; i++)
         s->header[i] = (char)get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE);
 
-    if ((ret = decode_wave_header(s->avctx, s->header, s->header_size)) < 0)
-        return ret;
+    if (AV_RL32(s->header) == MKTAG('R','I','F','F')) {
+        if ((ret = decode_wave_header(s->avctx, s->header, s->header_size)) < 0)
+            return ret;
+    } else if (AV_RL32(s->header) == MKTAG('F','O','R','M')) {
+        if ((ret = decode_aiff_header(s->avctx, s->header, s->header_size)) < 0)
+            return ret;
+    } else {
+        avpriv_report_missing_feature(s->avctx, "unsupported bit packing %X", AV_RL32(s->header));
+        return AVERROR_PATCHWELCOME;
+    }
 
+end:
     s->cur_chan = 0;
     s->bitshift = 0;
 
@@ -433,6 +512,7 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data,
         tmp_ptr = av_fast_realloc(s->bitstream, &s->allocated_bitstream_size,
                                   s->max_framesize + AV_INPUT_BUFFER_PADDING_SIZE);
         if (!tmp_ptr) {
+            s->max_framesize = 0;
             av_log(avctx, AV_LOG_ERROR, "error allocating bitstream buffer\n");
             return AVERROR(ENOMEM);
         }
@@ -441,29 +521,27 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data,
     }
 
     /* append current packet data to bitstream buffer */
-    if (1 && s->max_framesize) { //FIXME truncated
-        buf_size       = FFMIN(buf_size, s->max_framesize - s->bitstream_size);
-        input_buf_size = buf_size;
-
-        if (s->bitstream_index + s->bitstream_size + buf_size + AV_INPUT_BUFFER_PADDING_SIZE >
-            s->allocated_bitstream_size) {
-            memmove(s->bitstream, &s->bitstream[s->bitstream_index],
-                    s->bitstream_size);
-            s->bitstream_index = 0;
-        }
-        if (buf)
-            memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf,
-                   buf_size);
-        buf               = &s->bitstream[s->bitstream_index];
-        buf_size         += s->bitstream_size;
-        s->bitstream_size = buf_size;
-
-        /* do not decode until buffer has at least max_framesize bytes or
-         * the end of the file has been reached */
-        if (buf_size < s->max_framesize && avpkt->data) {
-            *got_frame_ptr = 0;
-            return input_buf_size;
-        }
+    buf_size       = FFMIN(buf_size, s->max_framesize - s->bitstream_size);
+    input_buf_size = buf_size;
+
+    if (s->bitstream_index + s->bitstream_size + buf_size + AV_INPUT_BUFFER_PADDING_SIZE >
+        s->allocated_bitstream_size) {
+        memmove(s->bitstream, &s->bitstream[s->bitstream_index],
+                s->bitstream_size);
+        s->bitstream_index = 0;
+    }
+    if (buf)
+        memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf,
+               buf_size);
+    buf               = &s->bitstream[s->bitstream_index];
+    buf_size         += s->bitstream_size;
+    s->bitstream_size = buf_size;
+
+    /* do not decode until buffer has at least max_framesize bytes or
+     * the end of the file has been reached */
+    if (buf_size < s->max_framesize && avpkt->data) {
+        *got_frame_ptr = 0;
+        return input_buf_size;
     }
     /* init and position bitstream reader */
     if ((ret = init_get_bits8(&s->gb, buf, buf_size)) < 0)
@@ -472,10 +550,26 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data,
 
     /* process header or next subblock */
     if (!s->got_header) {
+
         if ((ret = read_header(s)) < 0)
             return ret;
-        *got_frame_ptr = 0;
-        goto finish_frame;
+
+        if (avpkt->size) {
+            int max_framesize;
+            void *tmp_ptr;
+
+            max_framesize = FFMAX(s->max_framesize, s->blocksize * s->channels * 8);
+            tmp_ptr = av_fast_realloc(s->bitstream, &s->allocated_bitstream_size,
+                                      max_framesize + AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!tmp_ptr) {
+                av_log(avctx, AV_LOG_ERROR, "error allocating bitstream buffer\n");
+                return AVERROR(ENOMEM);
+            }
+            s->bitstream = tmp_ptr;
+            s->max_framesize = max_framesize;
+            *got_frame_ptr = 0;
+            goto finish_frame;
+        }
     }
 
     /* if quit command was read previously, don't decode anything */
@@ -512,7 +606,7 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data,
                 break;
             case FN_BITSHIFT: {
                 unsigned bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE);
-                if (bitshift > 31) {
+                if (bitshift > 32) {
                     av_log(avctx, AV_LOG_ERROR, "bitshift %d is invalid\n",
                            bitshift);
                     return AVERROR_INVALIDDATA;
@@ -539,10 +633,8 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data,
                 s->got_quit_command = 1;
                 break;
             }
-            if (cmd == FN_BLOCKSIZE || cmd == FN_QUIT) {
-                *got_frame_ptr = 0;
+            if (cmd == FN_QUIT)
                 break;
-            }
         } else {
             /* process audio command */
             int residual_size = 0;
@@ -592,7 +684,7 @@ static int shorten_decode_frame(AVCodecContext *avctx, void *data,
                 if (s->version < 2)
                     s->offset[channel][s->nmean - 1] = sum / s->blocksize;
                 else
-                    s->offset[channel][s->nmean - 1] = (sum / s->blocksize) << s->bitshift;
+                    s->offset[channel][s->nmean - 1] = s->bitshift == 32 ? 0 : (sum / s->blocksize) << s->bitshift;
             }
 
             /* copy wrap samples for use with next block */
@@ -680,7 +772,7 @@ AVCodec ff_shorten_decoder = {
     .init           = shorten_decode_init,
     .close          = shorten_decode_close,
     .decode         = shorten_decode_frame,
-    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
+    .capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
     .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
                                                       AV_SAMPLE_FMT_U8P,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/simple_idct_template.c b/libavcodec/simple_idct_template.c
index 0585679..f5744e0 100644
--- a/libavcodec/simple_idct_template.c
+++ b/libavcodec/simple_idct_template.c
@@ -25,10 +25,8 @@
  * simpleidct in C.
  */
 
-/*
-  based upon some outcommented c code from mpeg2dec (idct_mmx.c
-  written by Aaron Holtzman <aholtzma at ess.engr.uvic.ca>)
- */
+/* Based upon some commented-out C code from mpeg2dec (idct_mmx.c
+ * written by Aaron Holtzman <aholtzma at ess.engr.uvic.ca>). */
 
 #include "simple_idct.h"
 
@@ -118,7 +116,7 @@ static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift)
 
 #if HAVE_FAST_64BIT
 #define ROW0_MASK (0xffffLL << 48 * HAVE_BIGENDIAN)
-    if (((((uint64_t *)row)[0] & ~ROW0_MASK) | ((uint64_t *)row)[1]) == 0) {
+    if (((AV_RN64A(row) & ~ROW0_MASK) | AV_RN64A(row+4)) == 0) {
         uint64_t temp;
         if (DC_SHIFT - extra_shift >= 0) {
             temp = (row[0] * (1 << (DC_SHIFT - extra_shift))) & 0xffff;
@@ -127,14 +125,14 @@ static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift)
         }
         temp += temp * (1 << 16);
         temp += temp * ((uint64_t) 1 << 32);
-        ((uint64_t *)row)[0] = temp;
-        ((uint64_t *)row)[1] = temp;
+        AV_WN64A(row, temp);
+        AV_WN64A(row + 4, temp);
         return;
     }
 #else
-    if (!(((uint32_t*)row)[1] |
-          ((uint32_t*)row)[2] |
-          ((uint32_t*)row)[3] |
+    if (!(AV_RN32A(row+2) |
+          AV_RN32A(row+4) |
+          AV_RN32A(row+6) |
           row[1])) {
         uint32_t temp;
         if (DC_SHIFT - extra_shift >= 0) {
@@ -143,8 +141,10 @@ static inline void FUNC(idctRowCondDC)(int16_t *row, int extra_shift)
             temp = ((row[0] + (1<<(extra_shift - DC_SHIFT-1))) >> (extra_shift - DC_SHIFT)) & 0xffff;
         }
         temp += temp * (1 << 16);
-        ((uint32_t*)row)[0]=((uint32_t*)row)[1] =
-            ((uint32_t*)row)[2]=((uint32_t*)row)[3] = temp;
+        AV_WN32A(row, temp);
+        AV_WN32A(row+2, temp);
+        AV_WN32A(row+4, temp);
+        AV_WN32A(row+6, temp);
         return;
     }
 #endif
diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
index 4014e8d..f4fc16c 100644
--- a/libavcodec/smacker.c
+++ b/libavcodec/smacker.c
@@ -43,9 +43,7 @@
 #define SMKTREE_BITS 9
 #define SMK_NODE 0x80000000
 
-/*
- * Decoder context
- */
+
 typedef struct SmackVContext {
     AVCodecContext *avctx;
     AVFrame *pic;
@@ -549,12 +547,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 }
 
 
-
-/*
- *
- * Uninit smacker decoder
- *
- */
 static av_cold int decode_end(AVCodecContext *avctx)
 {
     SmackVContext * const smk = avctx->priv_data;
@@ -570,11 +562,6 @@ static av_cold int decode_end(AVCodecContext *avctx)
 }
 
 
-/*
- *
- * Init smacker decoder
- *
- */
 static av_cold int decode_init(AVCodecContext *avctx)
 {
     SmackVContext * const c = avctx->priv_data;
diff --git a/libavcodec/smc.c b/libavcodec/smc.c
index a423c45..69d78ad 100644
--- a/libavcodec/smc.c
+++ b/libavcodec/smc.c
@@ -1,6 +1,6 @@
 /*
  * Quicktime Graphics (SMC) Video Decoder
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -92,7 +92,7 @@ static void smc_decode_stream(SmcContext *s)
     unsigned int color_flags_b;
     unsigned int flag_mask;
 
-    unsigned char *pixels = s->frame->data[0];
+    unsigned char * const pixels = s->frame->data[0];
 
     int image_size = height * s->frame->linesize[0];
     int row_ptr = 0;
diff --git a/libavcodec/snow.h b/libavcodec/snow.h
index d126d68..59c710b 100644
--- a/libavcodec/snow.h
+++ b/libavcodec/snow.h
@@ -48,14 +48,14 @@
 #define LOG2_OBMC_MAX 8
 #define OBMC_MAX (1<<(LOG2_OBMC_MAX))
 typedef struct BlockNode{
-    int16_t mx;
-    int16_t my;
-    uint8_t ref;
-    uint8_t color[3];
-    uint8_t type;
+    int16_t mx;                 ///< Motion vector component X, see mv_scale
+    int16_t my;                 ///< Motion vector component Y, see mv_scale
+    uint8_t ref;                ///< Reference frame index
+    uint8_t color[3];           ///< Color for intra
+    uint8_t type;               ///< Bitfield of BLOCK_*
 //#define TYPE_SPLIT    1
-#define BLOCK_INTRA   1
-#define BLOCK_OPT     2
+#define BLOCK_INTRA   1         ///< Intra block, inter otherwise
+#define BLOCK_OPT     2         ///< Block needs no checks in this round of iterative motion estiation
 //#define TYPE_NOCOLOR  4
     uint8_t level; //FIXME merge into type?
 }BlockNode;
@@ -250,30 +250,6 @@ int ff_snow_get_buffer(SnowContext *s, AVFrame *frame);
 /* common inline functions */
 //XXX doublecheck all of them should stay inlined
 
-static inline void snow_set_blocks(SnowContext *s, int level, int x, int y, int l, int cb, int cr, int mx, int my, int ref, int type){
-    const int w= s->b_width << s->block_max_depth;
-    const int rem_depth= s->block_max_depth - level;
-    const int index= (x + y*w) << rem_depth;
-    const int block_w= 1<<rem_depth;
-    BlockNode block;
-    int i,j;
-
-    block.color[0]= l;
-    block.color[1]= cb;
-    block.color[2]= cr;
-    block.mx= mx;
-    block.my= my;
-    block.ref= ref;
-    block.type= type;
-    block.level= level;
-
-    for(j=0; j<block_w; j++){
-        for(i=0; i<block_w; i++){
-            s->block[index + i + j*w]= block;
-        }
-    }
-}
-
 static inline void pred_mv(SnowContext *s, int *mx, int *my, int ref,
                            const BlockNode *left, const BlockNode *top, const BlockNode *tr){
     if(s->ref_frames == 1){
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index b1d177d..00aef57 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -1955,132 +1955,3 @@ AVCodec ff_snow_encoder = {
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
 };
-
-
-#ifdef TEST
-#undef malloc
-#undef free
-#undef printf
-
-#include "libavutil/lfg.h"
-#include "libavutil/mathematics.h"
-
-int main(void){
-#define width  256
-#define height 256
-    int buffer[2][width*height];
-    SnowContext s;
-    int i;
-    AVLFG prng;
-    s.spatial_decomposition_count=6;
-    s.spatial_decomposition_type=1;
-
-    s.temp_dwt_buffer  = av_mallocz_array(width, sizeof(DWTELEM));
-    s.temp_idwt_buffer = av_mallocz_array(width, sizeof(IDWTELEM));
-
-    if (!s.temp_dwt_buffer || !s.temp_idwt_buffer) {
-        fprintf(stderr, "Failed to allocate memory\n");
-        return 1;
-    }
-
-    av_lfg_init(&prng, 1);
-
-    printf("testing 5/3 DWT\n");
-    for(i=0; i<width*height; i++)
-        buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
-
-    ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-    ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-
-    for(i=0; i<width*height; i++)
-        if(buffer[0][i]!= buffer[1][i]) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
-
-    printf("testing 9/7 DWT\n");
-    s.spatial_decomposition_type=0;
-    for(i=0; i<width*height; i++)
-        buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
-
-    ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-    ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-
-    for(i=0; i<width*height; i++)
-        if(FFABS(buffer[0][i] - buffer[1][i])>20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
-
-    {
-    int level, orientation, x, y;
-    int64_t errors[8][4];
-    int64_t g=0;
-
-        memset(errors, 0, sizeof(errors));
-        s.spatial_decomposition_count=3;
-        s.spatial_decomposition_type=0;
-        for(level=0; level<s.spatial_decomposition_count; level++){
-            for(orientation=level ? 1 : 0; orientation<4; orientation++){
-                int w= width  >> (s.spatial_decomposition_count-level);
-                int h= height >> (s.spatial_decomposition_count-level);
-                int stride= width  << (s.spatial_decomposition_count-level);
-                DWTELEM *buf= buffer[0];
-                int64_t error=0;
-
-                if(orientation&1) buf+=w;
-                if(orientation>1) buf+=stride>>1;
-
-                memset(buffer[0], 0, sizeof(int)*width*height);
-                buf[w/2 + h/2*stride]= 256*256;
-                ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-                for(y=0; y<height; y++){
-                    for(x=0; x<width; x++){
-                        int64_t d= buffer[0][x + y*width];
-                        error += d*d;
-                        if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9 && level==2) printf("%8"PRId64" ", d);
-                    }
-                    if(FFABS(height/2-y)<9 && level==2) printf("\n");
-                }
-                error= (int)(sqrt(error)+0.5);
-                errors[level][orientation]= error;
-                if(g) g=av_gcd(g, error);
-                else g= error;
-            }
-        }
-        printf("static int const visual_weight[][4]={\n");
-        for(level=0; level<s.spatial_decomposition_count; level++){
-            printf("  {");
-            for(orientation=0; orientation<4; orientation++){
-                printf("%8"PRId64",", errors[level][orientation]/g);
-            }
-            printf("},\n");
-        }
-        printf("};\n");
-        {
-            int level=2;
-            int w= width  >> (s.spatial_decomposition_count-level);
-            //int h= height >> (s.spatial_decomposition_count-level);
-            int stride= width  << (s.spatial_decomposition_count-level);
-            DWTELEM *buf= buffer[0];
-            int64_t error=0;
-
-            buf+=w;
-            buf+=stride>>1;
-
-            memset(buffer[0], 0, sizeof(int)*width*height);
-            for(y=0; y<height; y++){
-                for(x=0; x<width; x++){
-                    int tab[4]={0,2,3,1};
-                    buffer[0][x+width*y]= 256*256*tab[(x&1) + 2*(y&1)];
-                }
-            }
-            ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
-            for(y=0; y<height; y++){
-                for(x=0; x<width; x++){
-                    int64_t d= buffer[0][x + y*width];
-                    error += d*d;
-                    if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9) printf("%8"PRId64" ", d);
-                }
-                if(FFABS(height/2-y)<9) printf("\n");
-            }
-        }
-
-    }
-    return 0;
-}
-#endif /* TEST */
diff --git a/libavcodec/sp5x.h b/libavcodec/sp5x.h
index ecd6e8d..21c4571 100644
--- a/libavcodec/sp5x.h
+++ b/libavcodec/sp5x.h
@@ -1,6 +1,6 @@
 /*
  * Sunplus JPEG tables
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/srtdec.c b/libavcodec/srtdec.c
index 542dd35..30930c8 100644
--- a/libavcodec/srtdec.c
+++ b/libavcodec/srtdec.c
@@ -57,9 +57,10 @@ static int srt_decode_frame(AVCodecContext *avctx,
 {
     AVSubtitle *sub = data;
     AVBPrint buffer;
-    int ts_start, ts_end, x1 = -1, y1 = -1, x2 = -1, y2 = -1;
+    int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
     int size, ret;
     const uint8_t *p = av_packet_get_side_data(avpkt, AV_PKT_DATA_SUBTITLE_POSITION, &size);
+    FFASSDecoderContext *s = avctx->priv_data;
 
     if (p && size == 16) {
         x1 = AV_RL32(p     );
@@ -73,16 +74,8 @@ static int srt_decode_frame(AVCodecContext *avctx,
 
     av_bprint_init(&buffer, 0, AV_BPRINT_SIZE_UNLIMITED);
 
-    // Do final divide-by-10 outside rescale to force rounding down.
-    ts_start = av_rescale_q(avpkt->pts,
-                            avctx->time_base,
-                            (AVRational){1,100});
-    ts_end   = av_rescale_q(avpkt->pts + avpkt->duration,
-                            avctx->time_base,
-                            (AVRational){1,100});
-
     srt_to_ass(avctx, &buffer, avpkt->data, x1, y1, x2, y2);
-    ret = ff_ass_add_rect_bprint(sub, &buffer, ts_start, ts_end-ts_start);
+    ret = ff_ass_add_rect(sub, buffer.str, s->readorder++, 0, NULL, NULL);
     av_bprint_finalize(&buffer, NULL);
     if (ret < 0)
         return ret;
@@ -100,6 +93,8 @@ AVCodec ff_srt_decoder = {
     .id           = AV_CODEC_ID_SUBRIP,
     .init         = ff_ass_subtitle_header_default,
     .decode       = srt_decode_frame,
+    .flush        = ff_ass_decoder_flush,
+    .priv_data_size = sizeof(FFASSDecoderContext),
 };
 #endif
 
@@ -111,5 +106,7 @@ AVCodec ff_subrip_decoder = {
     .id           = AV_CODEC_ID_SUBRIP,
     .init         = ff_ass_subtitle_header_default,
     .decode       = srt_decode_frame,
+    .flush        = ff_ass_decoder_flush,
+    .priv_data_size = sizeof(FFASSDecoderContext),
 };
 #endif
diff --git a/libavcodec/srtenc.c b/libavcodec/srtenc.c
index 0a6875a..34f0f0d 100644
--- a/libavcodec/srtenc.c
+++ b/libavcodec/srtenc.c
@@ -232,23 +232,41 @@ static int encode_frame(AVCodecContext *avctx,
 {
     SRTContext *s = avctx->priv_data;
     ASSDialog *dialog;
-    int i, num;
+    int i;
 
     av_bprint_clear(&s->buffer);
 
     for (i=0; i<sub->num_rects; i++) {
+        const char *ass = sub->rects[i]->ass;
 
         if (sub->rects[i]->type != SUBTITLE_ASS) {
             av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
             return AVERROR(ENOSYS);
         }
 
-        dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num);
-        for (; dialog && num--; dialog++) {
+#if FF_API_ASS_TIMING
+        if (!strncmp(ass, "Dialogue: ", 10)) {
+            int num;
+            dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num);
+            for (; dialog && num--; dialog++) {
+                s->alignment_applied = 0;
+                if (avctx->codec_id == AV_CODEC_ID_SUBRIP)
+                    srt_style_apply(s, dialog->style);
+                ff_ass_split_override_codes(cb, s, dialog->text);
+            }
+        } else {
+#endif
+            dialog = ff_ass_split_dialog2(s->ass_ctx, ass);
+            if (!dialog)
+                return AVERROR(ENOMEM);
             s->alignment_applied = 0;
-            srt_style_apply(s, dialog->style);
+            if (avctx->codec_id == AV_CODEC_ID_SUBRIP)
+                srt_style_apply(s, dialog->style);
             ff_ass_split_override_codes(cb, s, dialog->text);
+            ff_ass_free_dialog(&dialog);
+#if FF_API_ASS_TIMING
         }
+#endif
     }
 
     if (!av_bprint_is_complete(&s->buffer))
diff --git a/libavcodec/subviewerdec.c b/libavcodec/subviewerdec.c
index a008828..805c7dd 100644
--- a/libavcodec/subviewerdec.c
+++ b/libavcodec/subviewerdec.c
@@ -52,13 +52,12 @@ static int subviewer_decode_frame(AVCodecContext *avctx,
     int ret = 0;
     AVSubtitle *sub = data;
     const char *ptr = avpkt->data;
+    FFASSDecoderContext *s = avctx->priv_data;
     AVBPrint buf;
 
     av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
-    // note: no need to rescale pts & duration since they are in the same
-    // timebase as ASS (1/100)
     if (ptr && avpkt->size > 0 && !subviewer_event_to_ass(&buf, ptr))
-        ret = ff_ass_add_rect_bprint(sub, &buf, avpkt->pts, avpkt->duration);
+        ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL);
     av_bprint_finalize(&buf, NULL);
     if (ret < 0)
         return ret;
@@ -73,4 +72,6 @@ AVCodec ff_subviewer_decoder = {
     .id             = AV_CODEC_ID_SUBVIEWER,
     .decode         = subviewer_decode_frame,
     .init           = ff_ass_subtitle_header_default,
+    .flush          = ff_ass_decoder_flush,
+    .priv_data_size = sizeof(FFASSDecoderContext),
 };
diff --git a/libavcodec/svq1.c b/libavcodec/svq1.c
index 909b0bf..cc214f9 100644
--- a/libavcodec/svq1.c
+++ b/libavcodec/svq1.c
@@ -3,8 +3,8 @@
  * ported to MPlayer by Arpi <arpi at thot.banki.hu>
  * ported to libavcodec by Nick Kurshev <nickols_k at mail.ru>
  *
- * Copyright (c) 2002 The Xine Project
- * Copyright (c) 2002 The FFmpeg Project
+ * Copyright (c) 2002 The Xine project
+ * Copyright (c) 2002 The FFmpeg project
  *
  * SVQ1 Encoder (c) 2004 Mike Melanson <melanson at pcisys.net>
  *
diff --git a/libavcodec/svq1.h b/libavcodec/svq1.h
index 88d61d1..63c0479 100644
--- a/libavcodec/svq1.h
+++ b/libavcodec/svq1.h
@@ -3,8 +3,8 @@
  * ported to MPlayer by Arpi <arpi at thot.banki.hu>
  * ported to libavcodec by Nick Kurshev <nickols_k at mail.ru>
  *
- * Copyright (c) 2002 The Xine Project
- * Copyright (c) 2002 The FFmpeg Project
+ * Copyright (c) 2002 The Xine project
+ * Copyright (c) 2002 The FFmpeg project
  *
  * SVQ1 Encoder (c) 2004 Mike Melanson <melanson at pcisys.net>
  *
diff --git a/libavcodec/svq1_cb.h b/libavcodec/svq1_cb.h
index 41485d2..11f7969 100644
--- a/libavcodec/svq1_cb.h
+++ b/libavcodec/svq1_cb.h
@@ -3,8 +3,8 @@
  * ported to MPlayer by Arpi <arpi at thot.banki.hu>
  * ported to libavcodec by Nick Kurshev <nickols_k at mail.ru>
  *
- * Copyright (c) 2002 The Xine Project
- * Copyright (c) 2002 The FFmpeg Project
+ * Copyright (c) 2002 The Xine project
+ * Copyright (c) 2002 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/svq1_vlc.h b/libavcodec/svq1_vlc.h
index f5d298d..06e3509 100644
--- a/libavcodec/svq1_vlc.h
+++ b/libavcodec/svq1_vlc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c
index dca99fa..2b72e08 100644
--- a/libavcodec/svq1dec.c
+++ b/libavcodec/svq1dec.c
@@ -3,8 +3,8 @@
  * ported to MPlayer by Arpi <arpi at thot.banki.hu>
  * ported to libavcodec by Nick Kurshev <nickols_k at mail.ru>
  *
- * Copyright (c) 2002 The Xine Project
- * Copyright (c) 2002 The FFmpeg Project
+ * Copyright (c) 2002 The Xine project
+ * Copyright (c) 2002 The FFmpeg project
  *
  * SVQ1 Encoder (c) 2004 Mike Melanson <melanson at pcisys.net>
  *
diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c
index d968d36..cb7c4a1 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -152,7 +152,7 @@ static int encode_block(SVQ1EncContext *s, uint8_t *src, uint8_t *ref,
                 vector = codebook + stage * size * 16 + i * size;
                 sqr    = s->ssd_int8_vs_int16(vector, block[stage], size);
                 diff   = block_sum[stage] - sum;
-                score  = sqr - (diff * (int64_t)diff >> (level + 3)); // FIXME: 64bit slooow
+                score  = sqr - (diff * (int64_t)diff >> (level + 3)); // FIXME: 64 bits slooow
                 if (score < best_vector_score) {
                     int mean = diff + (size >> 1) >> (level + 3);
                     av_assert2(mean > -300 && mean < 300);
diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c
index 57205c6..a927063 100644
--- a/libavcodec/svq3.c
+++ b/libavcodec/svq3.c
@@ -47,12 +47,10 @@
 #include "avcodec.h"
 #include "mpegutils.h"
 #include "h264.h"
-
-#include "h264data.h" // FIXME FIXME FIXME
-
-#include "h264_mvpred.h"
+#include "h264data.h"
 #include "golomb.h"
 #include "hpeldsp.h"
+#include "mathops.h"
 #include "rectangle.h"
 #include "tpeldsp.h"
 #include "vdpau_internal.h"
@@ -62,7 +60,6 @@
 #endif
 
 #include "svq1.h"
-#include "svq3.h"
 
 /**
  * @file
@@ -70,16 +67,24 @@
  */
 
 typedef struct SVQ3Context {
-    H264Context h;
+    AVCodecContext *avctx;
+
+    H264DSPContext  h264dsp;
+    H264PredContext hpc;
     HpelDSPContext hdsp;
     TpelDSPContext tdsp;
+    VideoDSPContext vdsp;
+
     H264Picture *cur_pic;
     H264Picture *next_pic;
     H264Picture *last_pic;
+    GetBitContext gb;
+    GetBitContext gb_slice;
+    uint8_t *slice_buf;
+    int slice_size;
     int halfpel_flag;
     int thirdpel_flag;
     int has_watermark;
-    int next_slice_index;
     uint32_t watermark_key;
     uint8_t *buf;
     int buf_size;
@@ -88,6 +93,44 @@ typedef struct SVQ3Context {
     int h_edge_pos;
     int v_edge_pos;
     int last_frame_output;
+    int slice_num;
+    int qscale;
+    int cbp;
+    int frame_num;
+    int frame_num_offset;
+    int prev_frame_num_offset;
+    int prev_frame_num;
+
+    enum AVPictureType pict_type;
+    int low_delay;
+
+    int mb_x, mb_y;
+    int mb_xy;
+    int mb_width, mb_height;
+    int mb_stride, mb_num;
+    int b_stride;
+
+    uint32_t *mb2br_xy;
+
+    int chroma_pred_mode;
+    int intra16x16_pred_mode;
+
+    int8_t   intra4x4_pred_mode_cache[5 * 8];
+    int8_t (*intra4x4_pred_mode);
+
+    unsigned int top_samples_available;
+    unsigned int topright_samples_available;
+    unsigned int left_samples_available;
+
+    uint8_t *edge_emu_buffer;
+
+    DECLARE_ALIGNED(16, int16_t, mv_cache)[2][5 * 8][2];
+    DECLARE_ALIGNED(8,  int8_t, ref_cache)[2][5 * 8];
+    DECLARE_ALIGNED(16, int16_t, mb)[16 * 48 * 2];
+    DECLARE_ALIGNED(16, int16_t, mb_luma_dc)[3][16 * 2];
+    DECLARE_ALIGNED(8, uint8_t, non_zero_count_cache)[15 * 8];
+    uint32_t dequant4_coeff[QP_MAX_NUM + 1][16];
+    int block_offset[2 * (16 * 3)];
 } SVQ3Context;
 
 #define FULLPEL_MODE  1
@@ -95,7 +138,7 @@ typedef struct SVQ3Context {
 #define THIRDPEL_MODE 3
 #define PREDICT_MODE  4
 
-/* dual scan (from some older h264 draft)
+/* dual scan (from some older H.264 draft)
  * o-->o-->o   o
  *         |  /|
  * o   o   o / o
@@ -164,7 +207,7 @@ static const uint32_t svq3_dequant_coeff[32] = {
 
 static int svq3_decode_end(AVCodecContext *avctx);
 
-void ff_svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp)
+static void svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp)
 {
     const int qmul = svq3_dequant_coeff[qp];
 #define stride 16
@@ -199,8 +242,8 @@ void ff_svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp)
 }
 #undef stride
 
-void ff_svq3_add_idct_c(uint8_t *dst, int16_t *block,
-                        int stride, int qp, int dc)
+static void svq3_add_idct_c(uint8_t *dst, int16_t *block,
+                            int stride, int qp, int dc)
 {
     const int qmul = svq3_dequant_coeff[qp];
     int i;
@@ -242,8 +285,9 @@ void ff_svq3_add_idct_c(uint8_t *dst, int16_t *block,
 static inline int svq3_decode_block(GetBitContext *gb, int16_t *block,
                                     int index, const int type)
 {
-    static const uint8_t *const scan_patterns[4] =
-    { luma_dc_zigzag_scan, zigzag_scan, svq3_scan, chroma_dc_scan };
+    static const uint8_t *const scan_patterns[4] = {
+        luma_dc_zigzag_scan, ff_zigzag_scan, svq3_scan, ff_h264_chroma_dc_scan
+    };
 
     int run, level, sign, limit;
     unsigned vlc;
@@ -251,7 +295,7 @@ static inline int svq3_decode_block(GetBitContext *gb, int16_t *block,
     const uint8_t *const scan = scan_patterns[type];
 
     for (limit = (16 >> intra); index < 16; index = limit, limit += 8) {
-        for (; (vlc = svq3_get_ue_golomb(gb)) != 0; index++) {
+        for (; (vlc = get_interleaved_ue_golomb(gb)) != 0; index++) {
             if ((int32_t)vlc < 0)
                 return -1;
 
@@ -297,17 +341,88 @@ static inline int svq3_decode_block(GetBitContext *gb, int16_t *block,
     return 0;
 }
 
+static av_always_inline int
+svq3_fetch_diagonal_mv(const SVQ3Context *s, const int16_t **C,
+                       int i, int list, int part_width)
+{
+    const int topright_ref = s->ref_cache[list][i - 8 + part_width];
+
+    if (topright_ref != PART_NOT_AVAILABLE) {
+        *C = s->mv_cache[list][i - 8 + part_width];
+        return topright_ref;
+    } else {
+        *C = s->mv_cache[list][i - 8 - 1];
+        return s->ref_cache[list][i - 8 - 1];
+    }
+}
+
+/**
+ * Get the predicted MV.
+ * @param n the block index
+ * @param part_width the width of the partition (4, 8,16) -> (1, 2, 4)
+ * @param mx the x component of the predicted motion vector
+ * @param my the y component of the predicted motion vector
+ */
+static av_always_inline void svq3_pred_motion(const SVQ3Context *s, int n,
+                                              int part_width, int list,
+                                              int ref, int *const mx, int *const my)
+{
+    const int index8       = scan8[n];
+    const int top_ref      = s->ref_cache[list][index8 - 8];
+    const int left_ref     = s->ref_cache[list][index8 - 1];
+    const int16_t *const A = s->mv_cache[list][index8 - 1];
+    const int16_t *const B = s->mv_cache[list][index8 - 8];
+    const int16_t *C;
+    int diagonal_ref, match_count;
+
+/* mv_cache
+ * B . . A T T T T
+ * U . . L . . , .
+ * U . . L . . . .
+ * U . . L . . , .
+ * . . . L . . . .
+ */
+
+    diagonal_ref = svq3_fetch_diagonal_mv(s, &C, index8, list, part_width);
+    match_count  = (diagonal_ref == ref) + (top_ref == ref) + (left_ref == ref);
+    if (match_count > 1) { //most common
+        *mx = mid_pred(A[0], B[0], C[0]);
+        *my = mid_pred(A[1], B[1], C[1]);
+    } else if (match_count == 1) {
+        if (left_ref == ref) {
+            *mx = A[0];
+            *my = A[1];
+        } else if (top_ref == ref) {
+            *mx = B[0];
+            *my = B[1];
+        } else {
+            *mx = C[0];
+            *my = C[1];
+        }
+    } else {
+        if (top_ref      == PART_NOT_AVAILABLE &&
+            diagonal_ref == PART_NOT_AVAILABLE &&
+            left_ref     != PART_NOT_AVAILABLE) {
+            *mx = A[0];
+            *my = A[1];
+        } else {
+            *mx = mid_pred(A[0], B[0], C[0]);
+            *my = mid_pred(A[1], B[1], C[1]);
+        }
+    }
+}
+
 static inline void svq3_mc_dir_part(SVQ3Context *s,
                                     int x, int y, int width, int height,
                                     int mx, int my, int dxy,
                                     int thirdpel, int dir, int avg)
 {
-    H264Context *h = &s->h;
-    H264SliceContext *sl = &h->slice_ctx[0];
     const H264Picture *pic = (dir == 0) ? s->last_pic : s->next_pic;
     uint8_t *src, *dest;
     int i, emu = 0;
     int blocksize = 2 - (width >> 3); // 16->0, 8->1, 4->2
+    int linesize   = s->cur_pic->f->linesize[0];
+    int uvlinesize = s->cur_pic->f->linesize[1];
 
     mx += x;
     my += y;
@@ -320,26 +435,26 @@ static inline void svq3_mc_dir_part(SVQ3Context *s,
     }
 
     /* form component predictions */
-    dest = h->cur_pic.f->data[0] + x + y * sl->linesize;
-    src  = pic->f->data[0] + mx + my * sl->linesize;
+    dest = s->cur_pic->f->data[0] + x + y * linesize;
+    src  = pic->f->data[0] + mx + my * linesize;
 
     if (emu) {
-        h->vdsp.emulated_edge_mc(sl->edge_emu_buffer, src,
-                                 sl->linesize, sl->linesize,
+        s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src,
+                                 linesize, linesize,
                                  width + 1, height + 1,
                                  mx, my, s->h_edge_pos, s->v_edge_pos);
-        src = sl->edge_emu_buffer;
+        src = s->edge_emu_buffer;
     }
     if (thirdpel)
         (avg ? s->tdsp.avg_tpel_pixels_tab
-             : s->tdsp.put_tpel_pixels_tab)[dxy](dest, src, sl->linesize,
+             : s->tdsp.put_tpel_pixels_tab)[dxy](dest, src, linesize,
                                                  width, height);
     else
         (avg ? s->hdsp.avg_pixels_tab
-             : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src, sl->linesize,
+             : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src, linesize,
                                                        height);
 
-    if (!(h->flags & AV_CODEC_FLAG_GRAY)) {
+    if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
         mx     = mx + (mx < (int) x) >> 1;
         my     = my + (my < (int) y) >> 1;
         width  = width  >> 1;
@@ -347,26 +462,26 @@ static inline void svq3_mc_dir_part(SVQ3Context *s,
         blocksize++;
 
         for (i = 1; i < 3; i++) {
-            dest = h->cur_pic.f->data[i] + (x >> 1) + (y >> 1) * sl->uvlinesize;
-            src  = pic->f->data[i] + mx + my * sl->uvlinesize;
+            dest = s->cur_pic->f->data[i] + (x >> 1) + (y >> 1) * uvlinesize;
+            src  = pic->f->data[i] + mx + my * uvlinesize;
 
             if (emu) {
-                h->vdsp.emulated_edge_mc(sl->edge_emu_buffer, src,
-                                         sl->uvlinesize, sl->uvlinesize,
+                s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src,
+                                         uvlinesize, uvlinesize,
                                          width + 1, height + 1,
                                          mx, my, (s->h_edge_pos >> 1),
                                          s->v_edge_pos >> 1);
-                src = sl->edge_emu_buffer;
+                src = s->edge_emu_buffer;
             }
             if (thirdpel)
                 (avg ? s->tdsp.avg_tpel_pixels_tab
                      : s->tdsp.put_tpel_pixels_tab)[dxy](dest, src,
-                                                         sl->uvlinesize,
+                                                         uvlinesize,
                                                          width, height);
             else
                 (avg ? s->hdsp.avg_pixels_tab
                      : s->hdsp.put_pixels_tab)[blocksize][dxy](dest, src,
-                                                               sl->uvlinesize,
+                                                               uvlinesize,
                                                                height);
         }
     }
@@ -376,8 +491,6 @@ static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode,
                               int dir, int avg)
 {
     int i, j, k, mx, my, dx, dy, x, y;
-    H264Context *h          = &s->h;
-    H264SliceContext *sl    = &h->slice_ctx[0];
     const int part_width    = ((size & 5) == 4) ? 4 : 16 >> (size & 1);
     const int part_height   = 16 >> ((unsigned)(size + 1) / 3);
     const int extra_width   = (mode == PREDICT_MODE) ? -16 * 6 : 0;
@@ -386,30 +499,30 @@ static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode,
 
     for (i = 0; i < 16; i += part_height)
         for (j = 0; j < 16; j += part_width) {
-            const int b_xy = (4 * sl->mb_x + (j >> 2)) +
-                             (4 * sl->mb_y + (i >> 2)) * h->b_stride;
+            const int b_xy = (4 * s->mb_x + (j >> 2)) +
+                             (4 * s->mb_y + (i >> 2)) * s->b_stride;
             int dxy;
-            x = 16 * sl->mb_x + j;
-            y = 16 * sl->mb_y + i;
+            x = 16 * s->mb_x + j;
+            y = 16 * s->mb_y + i;
             k = (j >> 2 & 1) + (i >> 1 & 2) +
                 (j >> 1 & 4) + (i      & 8);
 
             if (mode != PREDICT_MODE) {
-                pred_motion(h, sl, k, part_width >> 2, dir, 1, &mx, &my);
+                svq3_pred_motion(s, k, part_width >> 2, dir, 1, &mx, &my);
             } else {
                 mx = s->next_pic->motion_val[0][b_xy][0] << 1;
                 my = s->next_pic->motion_val[0][b_xy][1] << 1;
 
                 if (dir == 0) {
-                    mx = mx * h->frame_num_offset /
-                         h->prev_frame_num_offset + 1 >> 1;
-                    my = my * h->frame_num_offset /
-                         h->prev_frame_num_offset + 1 >> 1;
+                    mx = mx * s->frame_num_offset /
+                         s->prev_frame_num_offset + 1 >> 1;
+                    my = my * s->frame_num_offset /
+                         s->prev_frame_num_offset + 1 >> 1;
                 } else {
-                    mx = mx * (h->frame_num_offset - h->prev_frame_num_offset) /
-                         h->prev_frame_num_offset + 1 >> 1;
-                    my = my * (h->frame_num_offset - h->prev_frame_num_offset) /
-                         h->prev_frame_num_offset + 1 >> 1;
+                    mx = mx * (s->frame_num_offset - s->prev_frame_num_offset) /
+                         s->prev_frame_num_offset + 1 >> 1;
+                    my = my * (s->frame_num_offset - s->prev_frame_num_offset) /
+                         s->prev_frame_num_offset + 1 >> 1;
                 }
             }
 
@@ -421,11 +534,11 @@ static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode,
             if (mode == PREDICT_MODE) {
                 dx = dy = 0;
             } else {
-                dy = svq3_get_se_golomb(&h->gb);
-                dx = svq3_get_se_golomb(&h->gb);
+                dy = get_interleaved_se_golomb(&s->gb_slice);
+                dx = get_interleaved_se_golomb(&s->gb_slice);
 
                 if (dx == INVALID_VLC || dy == INVALID_VLC) {
-                    av_log(h->avctx, AV_LOG_ERROR, "invalid MV vlc\n");
+                    av_log(s->avctx, AV_LOG_ERROR, "invalid MV vlc\n");
                     return -1;
                 }
             }
@@ -467,49 +580,154 @@ static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode,
                 int32_t mv = pack16to32(mx, my);
 
                 if (part_height == 8 && i < 8) {
-                    AV_WN32A(sl->mv_cache[dir][scan8[k] + 1 * 8], mv);
+                    AV_WN32A(s->mv_cache[dir][scan8[k] + 1 * 8], mv);
 
                     if (part_width == 8 && j < 8)
-                        AV_WN32A(sl->mv_cache[dir][scan8[k] + 1 + 1 * 8], mv);
+                        AV_WN32A(s->mv_cache[dir][scan8[k] + 1 + 1 * 8], mv);
                 }
                 if (part_width == 8 && j < 8)
-                    AV_WN32A(sl->mv_cache[dir][scan8[k] + 1], mv);
+                    AV_WN32A(s->mv_cache[dir][scan8[k] + 1], mv);
                 if (part_width == 4 || part_height == 4)
-                    AV_WN32A(sl->mv_cache[dir][scan8[k]], mv);
+                    AV_WN32A(s->mv_cache[dir][scan8[k]], mv);
             }
 
             /* write back motion vectors */
-            fill_rectangle(h->cur_pic.motion_val[dir][b_xy],
-                           part_width >> 2, part_height >> 2, h->b_stride,
+            fill_rectangle(s->cur_pic->motion_val[dir][b_xy],
+                           part_width >> 2, part_height >> 2, s->b_stride,
                            pack16to32(mx, my), 4);
         }
 
     return 0;
 }
 
+static av_always_inline void hl_decode_mb_idct_luma(SVQ3Context *s,
+                                                    int mb_type, const int *block_offset,
+                                                    int linesize, uint8_t *dest_y)
+{
+    int i;
+    if (!IS_INTRA4x4(mb_type)) {
+        for (i = 0; i < 16; i++)
+            if (s->non_zero_count_cache[scan8[i]] || s->mb[i * 16]) {
+                uint8_t *const ptr = dest_y + block_offset[i];
+                svq3_add_idct_c(ptr, s->mb + i * 16, linesize,
+                                s->qscale, IS_INTRA(mb_type) ? 1 : 0);
+            }
+    }
+}
+
+static av_always_inline int dctcoef_get(int16_t *mb, int index)
+{
+    return AV_RN16A(mb + index);
+}
+
+static av_always_inline void hl_decode_mb_predict_luma(SVQ3Context *s,
+                                                       int mb_type,
+                                                       const int *block_offset,
+                                                       int linesize,
+                                                       uint8_t *dest_y)
+{
+    int i;
+    int qscale = s->qscale;
+
+    if (IS_INTRA4x4(mb_type)) {
+        for (i = 0; i < 16; i++) {
+            uint8_t *const ptr = dest_y + block_offset[i];
+            const int dir      = s->intra4x4_pred_mode_cache[scan8[i]];
+
+            uint8_t *topright;
+            int nnz, tr;
+            if (dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED) {
+                const int topright_avail = (s->topright_samples_available << i) & 0x8000;
+                av_assert2(s->mb_y || linesize <= block_offset[i]);
+                if (!topright_avail) {
+                    tr       = ptr[3 - linesize] * 0x01010101u;
+                    topright = (uint8_t *)&tr;
+                } else
+                    topright = ptr + 4 - linesize;
+            } else
+                topright = NULL;
+
+            s->hpc.pred4x4[dir](ptr, topright, linesize);
+            nnz = s->non_zero_count_cache[scan8[i]];
+            if (nnz) {
+                svq3_add_idct_c(ptr, s->mb + i * 16, linesize, qscale, 0);
+            }
+        }
+    } else {
+        s->hpc.pred16x16[s->intra16x16_pred_mode](dest_y, linesize);
+        svq3_luma_dc_dequant_idct_c(s->mb, s->mb_luma_dc[0], qscale);
+    }
+}
+
+static void hl_decode_mb(SVQ3Context *s)
+{
+    const int mb_x    = s->mb_x;
+    const int mb_y    = s->mb_y;
+    const int mb_xy   = s->mb_xy;
+    const int mb_type = s->cur_pic->mb_type[mb_xy];
+    uint8_t *dest_y, *dest_cb, *dest_cr;
+    int linesize, uvlinesize;
+    int i, j;
+    const int *block_offset = &s->block_offset[0];
+    const int block_h   = 16 >> 1;
+
+    linesize   = s->cur_pic->f->linesize[0];
+    uvlinesize = s->cur_pic->f->linesize[1];
+
+    dest_y  = s->cur_pic->f->data[0] + (mb_x     + mb_y * linesize)  * 16;
+    dest_cb = s->cur_pic->f->data[1] +  mb_x * 8 + mb_y * uvlinesize * block_h;
+    dest_cr = s->cur_pic->f->data[2] +  mb_x * 8 + mb_y * uvlinesize * block_h;
+
+    s->vdsp.prefetch(dest_y  + (s->mb_x & 3) * 4 * linesize   + 64, linesize,      4);
+    s->vdsp.prefetch(dest_cb + (s->mb_x & 7)     * uvlinesize + 64, dest_cr - dest_cb, 2);
+
+    if (IS_INTRA(mb_type)) {
+        s->hpc.pred8x8[s->chroma_pred_mode](dest_cb, uvlinesize);
+        s->hpc.pred8x8[s->chroma_pred_mode](dest_cr, uvlinesize);
+
+        hl_decode_mb_predict_luma(s, mb_type, block_offset, linesize, dest_y);
+    }
+
+    hl_decode_mb_idct_luma(s, mb_type, block_offset, linesize, dest_y);
+
+    if (s->cbp & 0x30) {
+        uint8_t *dest[2] = { dest_cb, dest_cr };
+        s->h264dsp.h264_chroma_dc_dequant_idct(s->mb + 16 * 16 * 1,
+                                               s->dequant4_coeff[4][0]);
+        s->h264dsp.h264_chroma_dc_dequant_idct(s->mb + 16 * 16 * 2,
+                                               s->dequant4_coeff[4][0]);
+        for (j = 1; j < 3; j++) {
+            for (i = j * 16; i < j * 16 + 4; i++)
+                if (s->non_zero_count_cache[scan8[i]] || s->mb[i * 16]) {
+                    uint8_t *const ptr = dest[j - 1] + block_offset[i];
+                    svq3_add_idct_c(ptr, s->mb + i * 16,
+                                    uvlinesize, ff_h264_chroma_qp[0][s->qscale + 12] - 12, 2);
+                }
+        }
+    }
+}
+
 static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
 {
-    H264Context *h = &s->h;
-    H264SliceContext *sl = &h->slice_ctx[0];
     int i, j, k, m, dir, mode;
     int cbp = 0;
     uint32_t vlc;
     int8_t *top, *left;
-    const int mb_xy         = sl->mb_xy;
-    const int b_xy          = 4 * sl->mb_x + 4 * sl->mb_y * h->b_stride;
+    const int mb_xy = s->mb_xy;
+    const int b_xy  = 4 * s->mb_x + 4 * s->mb_y * s->b_stride;
 
-    sl->top_samples_available      = (sl->mb_y == 0) ? 0x33FF : 0xFFFF;
-    sl->left_samples_available     = (sl->mb_x == 0) ? 0x5F5F : 0xFFFF;
-    sl->topright_samples_available = 0xFFFF;
+    s->top_samples_available      = (s->mb_y == 0) ? 0x33FF : 0xFFFF;
+    s->left_samples_available     = (s->mb_x == 0) ? 0x5F5F : 0xFFFF;
+    s->topright_samples_available = 0xFFFF;
 
     if (mb_type == 0) {           /* SKIP */
-        if (h->pict_type == AV_PICTURE_TYPE_P ||
+        if (s->pict_type == AV_PICTURE_TYPE_P ||
             s->next_pic->mb_type[mb_xy] == -1) {
-            svq3_mc_dir_part(s, 16 * sl->mb_x, 16 * sl->mb_y, 16, 16,
+            svq3_mc_dir_part(s, 16 * s->mb_x, 16 * s->mb_y, 16, 16,
                              0, 0, 0, 0, 0, 0);
 
-            if (h->pict_type == AV_PICTURE_TYPE_B)
-                svq3_mc_dir_part(s, 16 * sl->mb_x, 16 * sl->mb_y, 16, 16,
+            if (s->pict_type == AV_PICTURE_TYPE_B)
+                svq3_mc_dir_part(s, 16 * s->mb_x, 16 * s->mb_y, 16, 16,
                                  0, 0, 0, 0, 1, 1);
 
             mb_type = MB_TYPE_SKIP;
@@ -523,10 +741,10 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
             mb_type = MB_TYPE_16x16;
         }
     } else if (mb_type < 8) {     /* INTER */
-        if (s->thirdpel_flag && s->halfpel_flag == !get_bits1(&h->gb))
+        if (s->thirdpel_flag && s->halfpel_flag == !get_bits1(&s->gb_slice))
             mode = THIRDPEL_MODE;
         else if (s->halfpel_flag &&
-                 s->thirdpel_flag == !get_bits1(&h->gb))
+                 s->thirdpel_flag == !get_bits1(&s->gb_slice))
             mode = HALFPEL_MODE;
         else
             mode = FULLPEL_MODE;
@@ -541,46 +759,46 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
          */
 
         for (m = 0; m < 2; m++) {
-            if (sl->mb_x > 0 && sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - 1] + 6] != -1) {
+            if (s->mb_x > 0 && s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - 1] + 6] != -1) {
                 for (i = 0; i < 4; i++)
-                    AV_COPY32(sl->mv_cache[m][scan8[0] - 1 + i * 8],
-                              h->cur_pic.motion_val[m][b_xy - 1 + i * h->b_stride]);
+                    AV_COPY32(s->mv_cache[m][scan8[0] - 1 + i * 8],
+                              s->cur_pic->motion_val[m][b_xy - 1 + i * s->b_stride]);
             } else {
                 for (i = 0; i < 4; i++)
-                    AV_ZERO32(sl->mv_cache[m][scan8[0] - 1 + i * 8]);
+                    AV_ZERO32(s->mv_cache[m][scan8[0] - 1 + i * 8]);
             }
-            if (sl->mb_y > 0) {
-                memcpy(sl->mv_cache[m][scan8[0] - 1 * 8],
-                       h->cur_pic.motion_val[m][b_xy - h->b_stride],
+            if (s->mb_y > 0) {
+                memcpy(s->mv_cache[m][scan8[0] - 1 * 8],
+                       s->cur_pic->motion_val[m][b_xy - s->b_stride],
                        4 * 2 * sizeof(int16_t));
-                memset(&sl->ref_cache[m][scan8[0] - 1 * 8],
-                       (sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1, 4);
-
-                if (sl->mb_x < h->mb_width - 1) {
-                    AV_COPY32(sl->mv_cache[m][scan8[0] + 4 - 1 * 8],
-                              h->cur_pic.motion_val[m][b_xy - h->b_stride + 4]);
-                    sl->ref_cache[m][scan8[0] + 4 - 1 * 8] =
-                        (sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride + 1] + 6] == -1 ||
-                         sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1;
+                memset(&s->ref_cache[m][scan8[0] - 1 * 8],
+                       (s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1, 4);
+
+                if (s->mb_x < s->mb_width - 1) {
+                    AV_COPY32(s->mv_cache[m][scan8[0] + 4 - 1 * 8],
+                              s->cur_pic->motion_val[m][b_xy - s->b_stride + 4]);
+                    s->ref_cache[m][scan8[0] + 4 - 1 * 8] =
+                        (s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride + 1] + 6] == -1 ||
+                         s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1;
                 } else
-                    sl->ref_cache[m][scan8[0] + 4 - 1 * 8] = PART_NOT_AVAILABLE;
-                if (sl->mb_x > 0) {
-                    AV_COPY32(sl->mv_cache[m][scan8[0] - 1 - 1 * 8],
-                              h->cur_pic.motion_val[m][b_xy - h->b_stride - 1]);
-                    sl->ref_cache[m][scan8[0] - 1 - 1 * 8] =
-                        (sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride - 1] + 3] == -1) ? PART_NOT_AVAILABLE : 1;
+                    s->ref_cache[m][scan8[0] + 4 - 1 * 8] = PART_NOT_AVAILABLE;
+                if (s->mb_x > 0) {
+                    AV_COPY32(s->mv_cache[m][scan8[0] - 1 - 1 * 8],
+                              s->cur_pic->motion_val[m][b_xy - s->b_stride - 1]);
+                    s->ref_cache[m][scan8[0] - 1 - 1 * 8] =
+                        (s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride - 1] + 3] == -1) ? PART_NOT_AVAILABLE : 1;
                 } else
-                    sl->ref_cache[m][scan8[0] - 1 - 1 * 8] = PART_NOT_AVAILABLE;
+                    s->ref_cache[m][scan8[0] - 1 - 1 * 8] = PART_NOT_AVAILABLE;
             } else
-                memset(&sl->ref_cache[m][scan8[0] - 1 * 8 - 1],
+                memset(&s->ref_cache[m][scan8[0] - 1 * 8 - 1],
                        PART_NOT_AVAILABLE, 8);
 
-            if (h->pict_type != AV_PICTURE_TYPE_B)
+            if (s->pict_type != AV_PICTURE_TYPE_B)
                 break;
         }
 
         /* decode motion vector(s) and form prediction(s) */
-        if (h->pict_type == AV_PICTURE_TYPE_P) {
+        if (s->pict_type == AV_PICTURE_TYPE_P) {
             if (svq3_mc_dir(s, mb_type - 1, mode, 0, 0) < 0)
                 return -1;
         } else {        /* AV_PICTURE_TYPE_B */
@@ -589,7 +807,7 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
                     return -1;
             } else {
                 for (i = 0; i < 4; i++)
-                    memset(h->cur_pic.motion_val[0][b_xy + i * h->b_stride],
+                    memset(s->cur_pic->motion_val[0][b_xy + i * s->b_stride],
                            0, 4 * 2 * sizeof(int16_t));
             }
             if (mb_type != 1) {
@@ -597,128 +815,137 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
                     return -1;
             } else {
                 for (i = 0; i < 4; i++)
-                    memset(h->cur_pic.motion_val[1][b_xy + i * h->b_stride],
+                    memset(s->cur_pic->motion_val[1][b_xy + i * s->b_stride],
                            0, 4 * 2 * sizeof(int16_t));
             }
         }
 
         mb_type = MB_TYPE_16x16;
     } else if (mb_type == 8 || mb_type == 33) {   /* INTRA4x4 */
-        memset(sl->intra4x4_pred_mode_cache, -1, 8 * 5 * sizeof(int8_t));
+        int8_t *i4x4       = s->intra4x4_pred_mode + s->mb2br_xy[s->mb_xy];
+        int8_t *i4x4_cache = s->intra4x4_pred_mode_cache;
+
+        memset(s->intra4x4_pred_mode_cache, -1, 8 * 5 * sizeof(int8_t));
 
         if (mb_type == 8) {
-            if (sl->mb_x > 0) {
+            if (s->mb_x > 0) {
                 for (i = 0; i < 4; i++)
-                    sl->intra4x4_pred_mode_cache[scan8[0] - 1 + i * 8] = sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - 1] + 6 - i];
-                if (sl->intra4x4_pred_mode_cache[scan8[0] - 1] == -1)
-                    sl->left_samples_available = 0x5F5F;
+                    s->intra4x4_pred_mode_cache[scan8[0] - 1 + i * 8] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - 1] + 6 - i];
+                if (s->intra4x4_pred_mode_cache[scan8[0] - 1] == -1)
+                    s->left_samples_available = 0x5F5F;
             }
-            if (sl->mb_y > 0) {
-                sl->intra4x4_pred_mode_cache[4 + 8 * 0] = sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 0];
-                sl->intra4x4_pred_mode_cache[5 + 8 * 0] = sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 1];
-                sl->intra4x4_pred_mode_cache[6 + 8 * 0] = sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 2];
-                sl->intra4x4_pred_mode_cache[7 + 8 * 0] = sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride] + 3];
-
-                if (sl->intra4x4_pred_mode_cache[4 + 8 * 0] == -1)
-                    sl->top_samples_available = 0x33FF;
+            if (s->mb_y > 0) {
+                s->intra4x4_pred_mode_cache[4 + 8 * 0] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride] + 0];
+                s->intra4x4_pred_mode_cache[5 + 8 * 0] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride] + 1];
+                s->intra4x4_pred_mode_cache[6 + 8 * 0] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride] + 2];
+                s->intra4x4_pred_mode_cache[7 + 8 * 0] = s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride] + 3];
+
+                if (s->intra4x4_pred_mode_cache[4 + 8 * 0] == -1)
+                    s->top_samples_available = 0x33FF;
             }
 
             /* decode prediction codes for luma blocks */
             for (i = 0; i < 16; i += 2) {
-                vlc = svq3_get_ue_golomb(&h->gb);
+                vlc = get_interleaved_ue_golomb(&s->gb_slice);
 
                 if (vlc >= 25U) {
-                    av_log(h->avctx, AV_LOG_ERROR,
+                    av_log(s->avctx, AV_LOG_ERROR,
                            "luma prediction:%"PRIu32"\n", vlc);
                     return -1;
                 }
 
-                left = &sl->intra4x4_pred_mode_cache[scan8[i] - 1];
-                top  = &sl->intra4x4_pred_mode_cache[scan8[i] - 8];
+                left = &s->intra4x4_pred_mode_cache[scan8[i] - 1];
+                top  = &s->intra4x4_pred_mode_cache[scan8[i] - 8];
 
                 left[1] = svq3_pred_1[top[0] + 1][left[0] + 1][svq3_pred_0[vlc][0]];
                 left[2] = svq3_pred_1[top[1] + 1][left[1] + 1][svq3_pred_0[vlc][1]];
 
                 if (left[1] == -1 || left[2] == -1) {
-                    av_log(h->avctx, AV_LOG_ERROR, "weird prediction\n");
+                    av_log(s->avctx, AV_LOG_ERROR, "weird prediction\n");
                     return -1;
                 }
             }
         } else {    /* mb_type == 33, DC_128_PRED block type */
             for (i = 0; i < 4; i++)
-                memset(&sl->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_PRED, 4);
+                memset(&s->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_PRED, 4);
         }
 
-        write_back_intra_pred_mode(h, sl);
+        AV_COPY32(i4x4, i4x4_cache + 4 + 8 * 4);
+        i4x4[4] = i4x4_cache[7 + 8 * 3];
+        i4x4[5] = i4x4_cache[7 + 8 * 2];
+        i4x4[6] = i4x4_cache[7 + 8 * 1];
 
         if (mb_type == 8) {
-            ff_h264_check_intra4x4_pred_mode(h, sl);
+            ff_h264_check_intra4x4_pred_mode(s->intra4x4_pred_mode_cache,
+                                             s->avctx, s->top_samples_available,
+                                             s->left_samples_available);
 
-            sl->top_samples_available  = (sl->mb_y == 0) ? 0x33FF : 0xFFFF;
-            sl->left_samples_available = (sl->mb_x == 0) ? 0x5F5F : 0xFFFF;
+            s->top_samples_available  = (s->mb_y == 0) ? 0x33FF : 0xFFFF;
+            s->left_samples_available = (s->mb_x == 0) ? 0x5F5F : 0xFFFF;
         } else {
             for (i = 0; i < 4; i++)
-                memset(&sl->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_128_PRED, 4);
+                memset(&s->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_128_PRED, 4);
 
-            sl->top_samples_available  = 0x33FF;
-            sl->left_samples_available = 0x5F5F;
+            s->top_samples_available  = 0x33FF;
+            s->left_samples_available = 0x5F5F;
         }
 
         mb_type = MB_TYPE_INTRA4x4;
     } else {                      /* INTRA16x16 */
-        dir = i_mb_type_info[mb_type - 8].pred_mode;
+        dir = ff_h264_i_mb_type_info[mb_type - 8].pred_mode;
         dir = (dir >> 1) ^ 3 * (dir & 1) ^ 1;
 
-        if ((sl->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h, sl, dir, 0)) < 0) {
-            av_log(h->avctx, AV_LOG_ERROR, "ff_h264_check_intra_pred_mode < 0\n");
-            return sl->intra16x16_pred_mode;
+        if ((s->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(s->avctx, s->top_samples_available,
+                                                                     s->left_samples_available, dir, 0)) < 0) {
+            av_log(s->avctx, AV_LOG_ERROR, "ff_h264_check_intra_pred_mode < 0\n");
+            return s->intra16x16_pred_mode;
         }
 
-        cbp     = i_mb_type_info[mb_type - 8].cbp;
+        cbp     = ff_h264_i_mb_type_info[mb_type - 8].cbp;
         mb_type = MB_TYPE_INTRA16x16;
     }
 
-    if (!IS_INTER(mb_type) && h->pict_type != AV_PICTURE_TYPE_I) {
+    if (!IS_INTER(mb_type) && s->pict_type != AV_PICTURE_TYPE_I) {
         for (i = 0; i < 4; i++)
-            memset(h->cur_pic.motion_val[0][b_xy + i * h->b_stride],
+            memset(s->cur_pic->motion_val[0][b_xy + i * s->b_stride],
                    0, 4 * 2 * sizeof(int16_t));
-        if (h->pict_type == AV_PICTURE_TYPE_B) {
+        if (s->pict_type == AV_PICTURE_TYPE_B) {
             for (i = 0; i < 4; i++)
-                memset(h->cur_pic.motion_val[1][b_xy + i * h->b_stride],
+                memset(s->cur_pic->motion_val[1][b_xy + i * s->b_stride],
                        0, 4 * 2 * sizeof(int16_t));
         }
     }
     if (!IS_INTRA4x4(mb_type)) {
-        memset(sl->intra4x4_pred_mode + h->mb2br_xy[mb_xy], DC_PRED, 8);
+        memset(s->intra4x4_pred_mode + s->mb2br_xy[mb_xy], DC_PRED, 8);
     }
-    if (!IS_SKIP(mb_type) || h->pict_type == AV_PICTURE_TYPE_B) {
-        memset(sl->non_zero_count_cache + 8, 0, 14 * 8 * sizeof(uint8_t));
+    if (!IS_SKIP(mb_type) || s->pict_type == AV_PICTURE_TYPE_B) {
+        memset(s->non_zero_count_cache + 8, 0, 14 * 8 * sizeof(uint8_t));
     }
 
     if (!IS_INTRA16x16(mb_type) &&
-        (!IS_SKIP(mb_type) || h->pict_type == AV_PICTURE_TYPE_B)) {
-        if ((vlc = svq3_get_ue_golomb(&h->gb)) >= 48U){
-            av_log(h->avctx, AV_LOG_ERROR, "cbp_vlc=%"PRIu32"\n", vlc);
+        (!IS_SKIP(mb_type) || s->pict_type == AV_PICTURE_TYPE_B)) {
+        if ((vlc = get_interleaved_ue_golomb(&s->gb_slice)) >= 48U){
+            av_log(s->avctx, AV_LOG_ERROR, "cbp_vlc=%"PRIu32"\n", vlc);
             return -1;
         }
 
-        cbp = IS_INTRA(mb_type) ? golomb_to_intra4x4_cbp[vlc]
-                                : golomb_to_inter_cbp[vlc];
+        cbp = IS_INTRA(mb_type) ? ff_h264_golomb_to_intra4x4_cbp[vlc]
+                                : ff_h264_golomb_to_inter_cbp[vlc];
     }
     if (IS_INTRA16x16(mb_type) ||
-        (h->pict_type != AV_PICTURE_TYPE_I && s->adaptive_quant && cbp)) {
-        sl->qscale += svq3_get_se_golomb(&h->gb);
+        (s->pict_type != AV_PICTURE_TYPE_I && s->adaptive_quant && cbp)) {
+        s->qscale += get_interleaved_se_golomb(&s->gb_slice);
 
-        if (sl->qscale > 31u) {
-            av_log(h->avctx, AV_LOG_ERROR, "qscale:%d\n", sl->qscale);
+        if (s->qscale > 31u) {
+            av_log(s->avctx, AV_LOG_ERROR, "qscale:%d\n", s->qscale);
             return -1;
         }
     }
     if (IS_INTRA16x16(mb_type)) {
-        AV_ZERO128(sl->mb_luma_dc[0] + 0);
-        AV_ZERO128(sl->mb_luma_dc[0] + 8);
-        if (svq3_decode_block(&h->gb, sl->mb_luma_dc[0], 0, 1)) {
-            av_log(h->avctx, AV_LOG_ERROR,
+        AV_ZERO128(s->mb_luma_dc[0] + 0);
+        AV_ZERO128(s->mb_luma_dc[0] + 8);
+        if (svq3_decode_block(&s->gb_slice, s->mb_luma_dc[0], 0, 1)) {
+            av_log(s->avctx, AV_LOG_ERROR,
                    "error while decoding intra luma dc\n");
             return -1;
         }
@@ -726,7 +953,7 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
 
     if (cbp) {
         const int index = IS_INTRA16x16(mb_type) ? 1 : 0;
-        const int type  = ((sl->qscale < 24 && IS_INTRA4x4(mb_type)) ? 2 : 1);
+        const int type  = ((s->qscale < 24 && IS_INTRA4x4(mb_type)) ? 2 : 1);
 
         for (i = 0; i < 4; i++)
             if ((cbp & (1 << i))) {
@@ -734,10 +961,10 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
                     k = index ? (1 * (j & 1) + 2 * (i & 1) +
                                  2 * (j & 2) + 4 * (i & 2))
                               : (4 * i + j);
-                    sl->non_zero_count_cache[scan8[k]] = 1;
+                    s->non_zero_count_cache[scan8[k]] = 1;
 
-                    if (svq3_decode_block(&h->gb, &sl->mb[16 * k], index, type)) {
-                        av_log(h->avctx, AV_LOG_ERROR,
+                    if (svq3_decode_block(&s->gb_slice, &s->mb[16 * k], index, type)) {
+                        av_log(s->avctx, AV_LOG_ERROR,
                                "error while decoding block\n");
                         return -1;
                     }
@@ -746,8 +973,8 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
 
         if ((cbp & 0x30)) {
             for (i = 1; i < 3; ++i)
-                if (svq3_decode_block(&h->gb, &sl->mb[16 * 16 * i], 0, 3)) {
-                    av_log(h->avctx, AV_LOG_ERROR,
+                if (svq3_decode_block(&s->gb_slice, &s->mb[16 * 16 * i], 0, 3)) {
+                    av_log(s->avctx, AV_LOG_ERROR,
                            "error while decoding chroma dc block\n");
                     return -1;
                 }
@@ -756,10 +983,10 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
                 for (i = 1; i < 3; i++) {
                     for (j = 0; j < 4; j++) {
                         k                                 = 16 * i + j;
-                        sl->non_zero_count_cache[scan8[k]] = 1;
+                        s->non_zero_count_cache[scan8[k]] = 1;
 
-                        if (svq3_decode_block(&h->gb, &sl->mb[16 * k], 1, 1)) {
-                            av_log(h->avctx, AV_LOG_ERROR,
+                        if (svq3_decode_block(&s->gb_slice, &s->mb[16 * k], 1, 1)) {
+                            av_log(s->avctx, AV_LOG_ERROR,
                                    "error while decoding chroma ac block\n");
                             return -1;
                         }
@@ -769,11 +996,12 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
         }
     }
 
-    sl->cbp                   = cbp;
-    h->cur_pic.mb_type[mb_xy] = mb_type;
+    s->cbp                     = cbp;
+    s->cur_pic->mb_type[mb_xy] = mb_type;
 
     if (IS_INTRA(mb_type))
-        sl->chroma_pred_mode = ff_h264_check_intra_pred_mode(h, sl, DC_PRED8x8, 1);
+        s->chroma_pred_mode = ff_h264_check_intra_pred_mode(s->avctx, s->top_samples_available,
+                                                            s->left_samples_available, DC_PRED8x8, 1);
 
     return 0;
 }
@@ -781,101 +1009,115 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type)
 static int svq3_decode_slice_header(AVCodecContext *avctx)
 {
     SVQ3Context *s = avctx->priv_data;
-    H264Context *h    = &s->h;
-    H264SliceContext *sl = &h->slice_ctx[0];
-    const int mb_xy   = sl->mb_xy;
+    const int mb_xy   = s->mb_xy;
     int i, header;
     unsigned slice_id;
 
-    header = get_bits(&h->gb, 8);
+    header = get_bits(&s->gb, 8);
 
     if (((header & 0x9F) != 1 && (header & 0x9F) != 2) || (header & 0x60) == 0) {
         /* TODO: what? */
         av_log(avctx, AV_LOG_ERROR, "unsupported slice header (%02X)\n", header);
         return -1;
     } else {
+        int slice_bits, slice_bytes, slice_length;
         int length = header >> 5 & 3;
 
-        s->next_slice_index = get_bits_count(&h->gb) +
-                              8 * show_bits(&h->gb, 8 * length) +
-                              8 * length;
+        slice_length = show_bits(&s->gb, 8 * length);
+        slice_bits   = slice_length * 8;
+        slice_bytes  = slice_length + length - 1;
 
-        if (s->next_slice_index > h->gb.size_in_bits) {
+        if (slice_bytes > get_bits_left(&s->gb)) {
             av_log(avctx, AV_LOG_ERROR, "slice after bitstream end\n");
             return -1;
         }
 
-        h->gb.size_in_bits = s->next_slice_index - 8 * (length - 1);
-        skip_bits(&h->gb, 8);
+        skip_bits(&s->gb, 8);
+
+        av_fast_malloc(&s->slice_buf, &s->slice_size, slice_bytes + AV_INPUT_BUFFER_PADDING_SIZE);
+        if (!s->slice_buf)
+            return AVERROR(ENOMEM);
+
+        memcpy(s->slice_buf, s->gb.buffer + s->gb.index / 8, slice_bytes);
+
+        init_get_bits(&s->gb_slice, s->slice_buf, slice_bits);
 
         if (s->watermark_key) {
-            uint32_t header = AV_RL32(&h->gb.buffer[(get_bits_count(&h->gb) >> 3) + 1]);
-            AV_WL32(&h->gb.buffer[(get_bits_count(&h->gb) >> 3) + 1],
-                    header ^ s->watermark_key);
+            uint32_t header = AV_RL32(&s->gb_slice.buffer[1]);
+            AV_WL32(&s->gb_slice.buffer[1], header ^ s->watermark_key);
         }
         if (length > 0) {
-            memmove((uint8_t *) &h->gb.buffer[get_bits_count(&h->gb) >> 3],
-                    &h->gb.buffer[h->gb.size_in_bits >> 3], length - 1);
+            memmove(s->slice_buf, &s->slice_buf[slice_length], length - 1);
         }
-        skip_bits_long(&h->gb, 0);
+        skip_bits_long(&s->gb, slice_bytes * 8);
     }
 
-    if ((slice_id = svq3_get_ue_golomb(&h->gb)) >= 3) {
-        av_log(h->avctx, AV_LOG_ERROR, "illegal slice type %u \n", slice_id);
+    if ((slice_id = get_interleaved_ue_golomb(&s->gb_slice)) >= 3) {
+        av_log(s->avctx, AV_LOG_ERROR, "illegal slice type %u \n", slice_id);
         return -1;
     }
 
-    sl->slice_type = golomb_to_pict_type[slice_id];
+    s->pict_type = ff_h264_golomb_to_pict_type[slice_id];
 
     if ((header & 0x9F) == 2) {
-        i              = (h->mb_num < 64) ? 6 : (1 + av_log2(h->mb_num - 1));
-        sl->mb_skip_run = get_bits(&h->gb, i) -
-                         (sl->mb_y * h->mb_width + sl->mb_x);
+        i = (s->mb_num < 64) ? 6 : (1 + av_log2(s->mb_num - 1));
+        get_bits(&s->gb_slice, i);
     } else {
-        skip_bits1(&h->gb);
-        sl->mb_skip_run = 0;
+        skip_bits1(&s->gb_slice);
     }
 
-    sl->slice_num     = get_bits(&h->gb, 8);
-    sl->qscale        = get_bits(&h->gb, 5);
-    s->adaptive_quant = get_bits1(&h->gb);
+    s->slice_num      = get_bits(&s->gb_slice, 8);
+    s->qscale         = get_bits(&s->gb_slice, 5);
+    s->adaptive_quant = get_bits1(&s->gb_slice);
 
     /* unknown fields */
-    skip_bits1(&h->gb);
+    skip_bits1(&s->gb_slice);
 
     if (s->has_watermark)
-        skip_bits1(&h->gb);
+        skip_bits1(&s->gb_slice);
 
-    skip_bits1(&h->gb);
-    skip_bits(&h->gb, 2);
+    skip_bits1(&s->gb_slice);
+    skip_bits(&s->gb_slice, 2);
 
-    if (skip_1stop_8data_bits(&h->gb) < 0)
+    if (skip_1stop_8data_bits(&s->gb_slice) < 0)
         return AVERROR_INVALIDDATA;
 
     /* reset intra predictors and invalidate motion vector references */
-    if (sl->mb_x > 0) {
-        memset(sl->intra4x4_pred_mode + h->mb2br_xy[mb_xy - 1] + 3,
+    if (s->mb_x > 0) {
+        memset(s->intra4x4_pred_mode + s->mb2br_xy[mb_xy - 1] + 3,
                -1, 4 * sizeof(int8_t));
-        memset(sl->intra4x4_pred_mode + h->mb2br_xy[mb_xy - sl->mb_x],
-               -1, 8 * sizeof(int8_t) * sl->mb_x);
+        memset(s->intra4x4_pred_mode + s->mb2br_xy[mb_xy - s->mb_x],
+               -1, 8 * sizeof(int8_t) * s->mb_x);
     }
-    if (sl->mb_y > 0) {
-        memset(sl->intra4x4_pred_mode + h->mb2br_xy[mb_xy - h->mb_stride],
-               -1, 8 * sizeof(int8_t) * (h->mb_width - sl->mb_x));
+    if (s->mb_y > 0) {
+        memset(s->intra4x4_pred_mode + s->mb2br_xy[mb_xy - s->mb_stride],
+               -1, 8 * sizeof(int8_t) * (s->mb_width - s->mb_x));
 
-        if (sl->mb_x > 0)
-            sl->intra4x4_pred_mode[h->mb2br_xy[mb_xy - h->mb_stride - 1] + 3] = -1;
+        if (s->mb_x > 0)
+            s->intra4x4_pred_mode[s->mb2br_xy[mb_xy - s->mb_stride - 1] + 3] = -1;
     }
 
     return 0;
 }
 
+static void init_dequant4_coeff_table(SVQ3Context *s)
+{
+    int q, x;
+    const int max_qp = 51;
+
+    for (q = 0; q < max_qp + 1; q++) {
+        int shift = ff_h264_quant_div6[q] + 2;
+        int idx   = ff_h264_quant_rem6[q];
+        for (x = 0; x < 16; x++)
+            s->dequant4_coeff[q][(x >> 2) | ((x << 2) & 0xF)] =
+                ((uint32_t)ff_h264_dequant4_coeff_init[idx][(x & 1) + ((x >> 2) & 1)] * 16) << shift;
+    }
+}
+
 static av_cold int svq3_decode_init(AVCodecContext *avctx)
 {
     SVQ3Context *s = avctx->priv_data;
-    H264Context *h = &s->h;
-    H264SliceContext *sl;
-    int m;
+    int m, x, y;
     unsigned char *extradata;
     unsigned char *extradata_end;
     unsigned int size;
@@ -896,41 +1138,20 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx)
     if (!s->cur_pic->f || !s->last_pic->f || !s->next_pic->f)
         return AVERROR(ENOMEM);
 
-    if ((ret = ff_h264_decode_init(avctx)) < 0)
-        goto fail;
-
-    // we will overwrite it later during decoding
-    av_frame_free(&h->cur_pic.f);
-
-    av_frame_free(&h->last_pic_for_ec.f);
+    ff_h264dsp_init(&s->h264dsp, 8, 1);
+    ff_h264_pred_init(&s->hpc, AV_CODEC_ID_SVQ3, 8, 1);
+    ff_videodsp_init(&s->vdsp, 8);
 
-    ff_h264dsp_init(&h->h264dsp, 8, 1);
-    av_assert0(h->sps.bit_depth_chroma == 0);
-    ff_h264_pred_init(&h->hpc, AV_CODEC_ID_SVQ3, 8, 1);
-    ff_videodsp_init(&h->vdsp, 8);
-
-    memset(h->pps.scaling_matrix4, 16, 6 * 16 * sizeof(uint8_t));
-    memset(h->pps.scaling_matrix8, 16, 2 * 64 * sizeof(uint8_t));
 
     avctx->bits_per_raw_sample = 8;
-    h->sps.bit_depth_luma = 8;
-    h->chroma_format_idc = 1;
 
     ff_hpeldsp_init(&s->hdsp, avctx->flags);
     ff_tpeldsp_init(&s->tdsp);
 
-    sl = h->slice_ctx;
-
-    h->flags           = avctx->flags;
-    sl->is_complex     = 1;
-    h->sps.chroma_format_idc = 1;
-    h->picture_structure = PICT_FRAME;
     avctx->pix_fmt     = AV_PIX_FMT_YUVJ420P;
     avctx->color_range = AVCOL_RANGE_JPEG;
 
-    h->slice_ctx[0].chroma_qp[0] = h->slice_ctx[0].chroma_qp[1] = 4;
-    h->chroma_x_shift = h->chroma_y_shift = 1;
-
+    s->avctx         = avctx;
     s->halfpel_flag  = 1;
     s->thirdpel_flag = 1;
     s->has_watermark = 0;
@@ -1007,7 +1228,7 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx)
         unk2 = get_bits1(&gb);
         unk3 = get_bits1(&gb);
 
-        h->low_delay = get_bits1(&gb);
+        s->low_delay = get_bits1(&gb);
 
         /* unknown field */
         unk4 = get_bits1(&gb);
@@ -1021,15 +1242,15 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx)
         }
 
         s->has_watermark  = get_bits1(&gb);
-        avctx->has_b_frames = !h->low_delay;
+        avctx->has_b_frames = !s->low_delay;
         if (s->has_watermark) {
 #if CONFIG_ZLIB
-            unsigned watermark_width  = svq3_get_ue_golomb(&gb);
-            unsigned watermark_height = svq3_get_ue_golomb(&gb);
-            int u1                    = svq3_get_ue_golomb(&gb);
+            unsigned watermark_width  = get_interleaved_ue_golomb(&gb);
+            unsigned watermark_height = get_interleaved_ue_golomb(&gb);
+            int u1                    = get_interleaved_ue_golomb(&gb);
             int u2                    = get_bits(&gb, 8);
             int u3                    = get_bits(&gb, 2);
-            int u4                    = svq3_get_ue_golomb(&gb);
+            int u4                    = get_interleaved_ue_golomb(&gb);
             unsigned long buf_len     = watermark_width *
                                         watermark_height * 4;
             int offset                = get_bits_count(&gb) + 7 >> 3;
@@ -1073,20 +1294,31 @@ static av_cold int svq3_decode_init(AVCodecContext *avctx)
         }
     }
 
-    h->width  = avctx->width;
-    h->height = avctx->height;
-    h->mb_width  = (h->width + 15) / 16;
-    h->mb_height = (h->height + 15) / 16;
-    h->mb_stride = h->mb_width + 1;
-    h->mb_num    = h->mb_width * h->mb_height;
-    h->b_stride = 4 * h->mb_width;
-    s->h_edge_pos = h->mb_width * 16;
-    s->v_edge_pos = h->mb_height * 16;
-
-    if ((ret = ff_h264_alloc_tables(h)) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "svq3 memory allocation failed\n");
-        goto fail;
-    }
+    s->mb_width   = (avctx->width + 15) / 16;
+    s->mb_height  = (avctx->height + 15) / 16;
+    s->mb_stride  = s->mb_width + 1;
+    s->mb_num     = s->mb_width * s->mb_height;
+    s->b_stride   = 4 * s->mb_width;
+    s->h_edge_pos = s->mb_width * 16;
+    s->v_edge_pos = s->mb_height * 16;
+
+    s->intra4x4_pred_mode = av_mallocz(s->mb_stride * 2 * 8);
+    if (!s->intra4x4_pred_mode)
+        return AVERROR(ENOMEM);
+
+    s->mb2br_xy = av_mallocz(s->mb_stride * (s->mb_height + 1) *
+                             sizeof(*s->mb2br_xy));
+    if (!s->mb2br_xy)
+        return AVERROR(ENOMEM);
+
+    for (y = 0; y < s->mb_height; y++)
+        for (x = 0; x < s->mb_width; x++) {
+            const int mb_xy = x + y * s->mb_stride;
+
+            s->mb2br_xy[mb_xy] = 8 * (mb_xy % (2 * s->mb_stride));
+        }
+
+    init_dequant4_coeff_table(s);
 
     return 0;
 fail:
@@ -1109,21 +1341,19 @@ static void free_picture(AVCodecContext *avctx, H264Picture *pic)
 static int get_buffer(AVCodecContext *avctx, H264Picture *pic)
 {
     SVQ3Context *s = avctx->priv_data;
-    H264Context *h = &s->h;
-    H264SliceContext *sl = &h->slice_ctx[0];
-    const int big_mb_num    = h->mb_stride * (h->mb_height + 1) + 1;
-    const int mb_array_size = h->mb_stride * h->mb_height;
-    const int b4_stride     = h->mb_width * 4 + 1;
-    const int b4_array_size = b4_stride * h->mb_height * 4;
+    const int big_mb_num    = s->mb_stride * (s->mb_height + 1) + 1;
+    const int mb_array_size = s->mb_stride * s->mb_height;
+    const int b4_stride     = s->mb_width * 4 + 1;
+    const int b4_array_size = b4_stride * s->mb_height * 4;
     int ret;
 
     if (!pic->motion_val_buf[0]) {
         int i;
 
-        pic->mb_type_buf = av_buffer_allocz((big_mb_num + h->mb_stride) * sizeof(uint32_t));
+        pic->mb_type_buf = av_buffer_allocz((big_mb_num + s->mb_stride) * sizeof(uint32_t));
         if (!pic->mb_type_buf)
             return AVERROR(ENOMEM);
-        pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * h->mb_stride + 1;
+        pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * s->mb_stride + 1;
 
         for (i = 0; i < 2; i++) {
             pic->motion_val_buf[i] = av_buffer_allocz(2 * (b4_array_size + 4) * sizeof(int16_t));
@@ -1137,22 +1367,19 @@ static int get_buffer(AVCodecContext *avctx, H264Picture *pic)
             pic->ref_index[i]  = pic->ref_index_buf[i]->data;
         }
     }
-    pic->reference = !(h->pict_type == AV_PICTURE_TYPE_B);
+    pic->reference = !(s->pict_type == AV_PICTURE_TYPE_B);
 
     ret = ff_get_buffer(avctx, pic->f,
                         pic->reference ? AV_GET_BUFFER_FLAG_REF : 0);
     if (ret < 0)
         goto fail;
 
-    if (!sl->edge_emu_buffer) {
-        sl->edge_emu_buffer = av_mallocz_array(pic->f->linesize[0], 17);
-        if (!sl->edge_emu_buffer)
+    if (!s->edge_emu_buffer) {
+        s->edge_emu_buffer = av_mallocz_array(pic->f->linesize[0], 17);
+        if (!s->edge_emu_buffer)
             return AVERROR(ENOMEM);
     }
 
-    sl->linesize   = pic->f->linesize[0];
-    sl->uvlinesize = pic->f->linesize[1];
-
     return 0;
 fail:
     free_picture(avctx, pic);
@@ -1163,8 +1390,6 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
                              int *got_frame, AVPacket *avpkt)
 {
     SVQ3Context *s     = avctx->priv_data;
-    H264Context *h     = &s->h;
-    H264SliceContext *sl = &h->slice_ctx[0];
     int buf_size       = avpkt->size;
     int left;
     uint8_t *buf;
@@ -1172,7 +1397,7 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
 
     /* special case for last picture */
     if (buf_size == 0) {
-        if (s->next_pic->f->data[0] && !h->low_delay && !s->last_frame_output) {
+        if (s->next_pic->f->data[0] && !s->low_delay && !s->last_frame_output) {
             ret = av_frame_ref(data, s->next_pic->f);
             if (ret < 0)
                 return ret;
@@ -1182,7 +1407,7 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
         return 0;
     }
 
-    sl->mb_x = sl->mb_y = sl->mb_xy = 0;
+    s->mb_x = s->mb_y = s->mb_xy = 0;
 
     if (s->watermark_key) {
         av_fast_padded_malloc(&s->buf, &s->buf_size, buf_size);
@@ -1194,41 +1419,38 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
         buf = avpkt->data;
     }
 
-    init_get_bits(&h->gb, buf, 8 * buf_size);
+    ret = init_get_bits(&s->gb, buf, 8 * buf_size);
+    if (ret < 0)
+        return ret;
 
     if (svq3_decode_slice_header(avctx))
         return -1;
 
-    h->pict_type = sl->slice_type;
-
-    if (h->pict_type != AV_PICTURE_TYPE_B)
+    if (s->pict_type != AV_PICTURE_TYPE_B)
         FFSWAP(H264Picture*, s->next_pic, s->last_pic);
 
     av_frame_unref(s->cur_pic->f);
 
     /* for skipping the frame */
-    s->cur_pic->f->pict_type = h->pict_type;
-    s->cur_pic->f->key_frame = (h->pict_type == AV_PICTURE_TYPE_I);
+    s->cur_pic->f->pict_type = s->pict_type;
+    s->cur_pic->f->key_frame = (s->pict_type == AV_PICTURE_TYPE_I);
 
     ret = get_buffer(avctx, s->cur_pic);
     if (ret < 0)
         return ret;
 
-    h->cur_pic_ptr = s->cur_pic;
-    h->cur_pic     = *s->cur_pic;
-
     for (i = 0; i < 16; i++) {
-        h->block_offset[i]           = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * sl->linesize * ((scan8[i] - scan8[0]) >> 3);
-        h->block_offset[48 + i]      = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * sl->linesize * ((scan8[i] - scan8[0]) >> 3);
+        s->block_offset[i]           = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * s->cur_pic->f->linesize[0] * ((scan8[i] - scan8[0]) >> 3);
+        s->block_offset[48 + i]      = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * s->cur_pic->f->linesize[0] * ((scan8[i] - scan8[0]) >> 3);
     }
     for (i = 0; i < 16; i++) {
-        h->block_offset[16 + i]      =
-        h->block_offset[32 + i]      = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * sl->uvlinesize * ((scan8[i] - scan8[0]) >> 3);
-        h->block_offset[48 + 16 + i] =
-        h->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * sl->uvlinesize * ((scan8[i] - scan8[0]) >> 3);
+        s->block_offset[16 + i]      =
+        s->block_offset[32 + i]      = (4 * ((scan8[i] - scan8[0]) & 7)) + 4 * s->cur_pic->f->linesize[1] * ((scan8[i] - scan8[0]) >> 3);
+        s->block_offset[48 + 16 + i] =
+        s->block_offset[48 + 32 + i] = (4 * ((scan8[i] - scan8[0]) & 7)) + 8 * s->cur_pic->f->linesize[1] * ((scan8[i] - scan8[0]) >> 3);
     }
 
-    if (h->pict_type != AV_PICTURE_TYPE_I) {
+    if (s->pict_type != AV_PICTURE_TYPE_I) {
         if (!s->last_pic->f->data[0]) {
             av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
             av_frame_unref(s->last_pic->f);
@@ -1242,7 +1464,7 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
                    s->last_pic->f->linesize[2]);
         }
 
-        if (h->pict_type == AV_PICTURE_TYPE_B && !s->next_pic->f->data[0]) {
+        if (s->pict_type == AV_PICTURE_TYPE_B && !s->next_pic->f->data[0]) {
             av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
             av_frame_unref(s->next_pic->f);
             ret = get_buffer(avctx, s->next_pic);
@@ -1257,41 +1479,41 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
     }
 
     if (avctx->debug & FF_DEBUG_PICT_INFO)
-        av_log(h->avctx, AV_LOG_DEBUG,
+        av_log(s->avctx, AV_LOG_DEBUG,
                "%c hpel:%d, tpel:%d aqp:%d qp:%d, slice_num:%02X\n",
-               av_get_picture_type_char(h->pict_type),
+               av_get_picture_type_char(s->pict_type),
                s->halfpel_flag, s->thirdpel_flag,
-               s->adaptive_quant, h->slice_ctx[0].qscale, sl->slice_num);
+               s->adaptive_quant, s->qscale, s->slice_num);
 
-    if (avctx->skip_frame >= AVDISCARD_NONREF && h->pict_type == AV_PICTURE_TYPE_B ||
-        avctx->skip_frame >= AVDISCARD_NONKEY && h->pict_type != AV_PICTURE_TYPE_I ||
+    if (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B ||
+        avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type != AV_PICTURE_TYPE_I ||
         avctx->skip_frame >= AVDISCARD_ALL)
         return 0;
 
     if (s->next_p_frame_damaged) {
-        if (h->pict_type == AV_PICTURE_TYPE_B)
+        if (s->pict_type == AV_PICTURE_TYPE_B)
             return 0;
         else
             s->next_p_frame_damaged = 0;
     }
 
-    if (h->pict_type == AV_PICTURE_TYPE_B) {
-        h->frame_num_offset = sl->slice_num - h->prev_frame_num;
+    if (s->pict_type == AV_PICTURE_TYPE_B) {
+        s->frame_num_offset = s->slice_num - s->prev_frame_num;
 
-        if (h->frame_num_offset < 0)
-            h->frame_num_offset += 256;
-        if (h->frame_num_offset == 0 ||
-            h->frame_num_offset >= h->prev_frame_num_offset) {
-            av_log(h->avctx, AV_LOG_ERROR, "error in B-frame picture id\n");
+        if (s->frame_num_offset < 0)
+            s->frame_num_offset += 256;
+        if (s->frame_num_offset == 0 ||
+            s->frame_num_offset >= s->prev_frame_num_offset) {
+            av_log(s->avctx, AV_LOG_ERROR, "error in B-frame picture id\n");
             return -1;
         }
     } else {
-        h->prev_frame_num        = h->frame_num;
-        h->frame_num             = sl->slice_num;
-        h->prev_frame_num_offset = h->frame_num - h->prev_frame_num;
+        s->prev_frame_num        = s->frame_num;
+        s->frame_num             = s->slice_num;
+        s->prev_frame_num_offset = s->frame_num - s->prev_frame_num;
 
-        if (h->prev_frame_num_offset < 0)
-            h->prev_frame_num_offset += 256;
+        if (s->prev_frame_num_offset < 0)
+            s->prev_frame_num_offset += 256;
     }
 
     for (m = 0; m < 2; m++) {
@@ -1299,59 +1521,57 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
         for (i = 0; i < 4; i++) {
             int j;
             for (j = -1; j < 4; j++)
-                sl->ref_cache[m][scan8[0] + 8 * i + j] = 1;
+                s->ref_cache[m][scan8[0] + 8 * i + j] = 1;
             if (i < 3)
-                sl->ref_cache[m][scan8[0] + 8 * i + j] = PART_NOT_AVAILABLE;
+                s->ref_cache[m][scan8[0] + 8 * i + j] = PART_NOT_AVAILABLE;
         }
     }
 
-    for (sl->mb_y = 0; sl->mb_y < h->mb_height; sl->mb_y++) {
-        for (sl->mb_x = 0; sl->mb_x < h->mb_width; sl->mb_x++) {
+    for (s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
+        for (s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
             unsigned mb_type;
-            sl->mb_xy = sl->mb_x + sl->mb_y * h->mb_stride;
+            s->mb_xy = s->mb_x + s->mb_y * s->mb_stride;
 
-            if ((get_bits_count(&h->gb) + 7) >= h->gb.size_in_bits &&
-                ((get_bits_count(&h->gb) & 7) == 0 ||
-                 show_bits(&h->gb, -get_bits_count(&h->gb) & 7) == 0)) {
-                skip_bits(&h->gb, s->next_slice_index - get_bits_count(&h->gb));
-                h->gb.size_in_bits = 8 * buf_size;
-
-                if (svq3_decode_slice_header(avctx))
-                    return -1;
+            if ((get_bits_left(&s->gb_slice)) <= 7) {
+                if (((get_bits_count(&s->gb_slice) & 7) == 0 ||
+                    show_bits(&s->gb_slice, get_bits_left(&s->gb_slice) & 7) == 0)) {
 
+                    if (svq3_decode_slice_header(avctx))
+                        return -1;
+                }
                 /* TODO: support s->mb_skip_run */
             }
 
-            mb_type = svq3_get_ue_golomb(&h->gb);
+            mb_type = get_interleaved_ue_golomb(&s->gb_slice);
 
-            if (h->pict_type == AV_PICTURE_TYPE_I)
+            if (s->pict_type == AV_PICTURE_TYPE_I)
                 mb_type += 8;
-            else if (h->pict_type == AV_PICTURE_TYPE_B && mb_type >= 4)
+            else if (s->pict_type == AV_PICTURE_TYPE_B && mb_type >= 4)
                 mb_type += 4;
             if (mb_type > 33 || svq3_decode_mb(s, mb_type)) {
-                av_log(h->avctx, AV_LOG_ERROR,
-                       "error while decoding MB %d %d\n", sl->mb_x, sl->mb_y);
+                av_log(s->avctx, AV_LOG_ERROR,
+                       "error while decoding MB %d %d\n", s->mb_x, s->mb_y);
                 return -1;
             }
 
-            if (mb_type != 0 || sl->cbp)
-                ff_h264_hl_decode_mb(h, &h->slice_ctx[0]);
+            if (mb_type != 0 || s->cbp)
+                hl_decode_mb(s);
 
-            if (h->pict_type != AV_PICTURE_TYPE_B && !h->low_delay)
-                h->cur_pic.mb_type[sl->mb_x + sl->mb_y * h->mb_stride] =
-                    (h->pict_type == AV_PICTURE_TYPE_P && mb_type < 8) ? (mb_type - 1) : -1;
+            if (s->pict_type != AV_PICTURE_TYPE_B && !s->low_delay)
+                s->cur_pic->mb_type[s->mb_x + s->mb_y * s->mb_stride] =
+                    (s->pict_type == AV_PICTURE_TYPE_P && mb_type < 8) ? (mb_type - 1) : -1;
         }
 
         ff_draw_horiz_band(avctx, s->cur_pic->f,
                            s->last_pic->f->data[0] ? s->last_pic->f : NULL,
-                           16 * sl->mb_y, 16, h->picture_structure, 0,
-                           h->low_delay);
+                           16 * s->mb_y, 16, PICT_FRAME, 0,
+                           s->low_delay);
     }
 
-    left = buf_size*8 - get_bits_count(&h->gb);
+    left = buf_size*8 - get_bits_count(&s->gb_slice);
 
-    if (sl->mb_y != h->mb_height || sl->mb_x != h->mb_width) {
-        av_log(avctx, AV_LOG_INFO, "frame num %d incomplete pic x %d y %d left %d\n", avctx->frame_number, sl->mb_y, sl->mb_x, left);
+    if (s->mb_y != s->mb_height || s->mb_x != s->mb_width) {
+        av_log(avctx, AV_LOG_INFO, "frame num %d incomplete pic x %d y %d left %d\n", avctx->frame_number, s->mb_y, s->mb_x, left);
         //av_hex_dump(stderr, buf+buf_size-8, 8);
     }
 
@@ -1360,7 +1580,7 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
         return -1;
     }
 
-    if (h->pict_type == AV_PICTURE_TYPE_B || h->low_delay)
+    if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay)
         ret = av_frame_ref(data, s->cur_pic->f);
     else if (s->last_pic->f->data[0])
         ret = av_frame_ref(data, s->last_pic->f);
@@ -1368,10 +1588,10 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
         return ret;
 
     /* Do not output the last pic after seeking. */
-    if (s->last_pic->f->data[0] || h->low_delay)
+    if (s->last_pic->f->data[0] || s->low_delay)
         *got_frame = 1;
 
-    if (h->pict_type != AV_PICTURE_TYPE_B) {
+    if (s->pict_type != AV_PICTURE_TYPE_B) {
         FFSWAP(H264Picture*, s->cur_pic, s->next_pic);
     } else {
         av_frame_unref(s->cur_pic->f);
@@ -1383,7 +1603,6 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
 static av_cold int svq3_decode_end(AVCodecContext *avctx)
 {
     SVQ3Context *s = avctx->priv_data;
-    H264Context *h = &s->h;
 
     free_picture(avctx, s->cur_pic);
     free_picture(avctx, s->next_pic);
@@ -1394,10 +1613,11 @@ static av_cold int svq3_decode_end(AVCodecContext *avctx)
     av_freep(&s->cur_pic);
     av_freep(&s->next_pic);
     av_freep(&s->last_pic);
+    av_freep(&s->slice_buf);
+    av_freep(&s->intra4x4_pred_mode);
+    av_freep(&s->edge_emu_buffer);
+    av_freep(&s->mb2br_xy);
 
-    memset(&h->cur_pic, 0, sizeof(h->cur_pic));
-
-    ff_h264_free_context(h);
 
     av_freep(&s->buf);
     s->buf_size = 0;
diff --git a/libavcodec/svq3.h b/libavcodec/svq3.h
deleted file mode 100644
index 5007a8c..0000000
--- a/libavcodec/svq3.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVCODEC_SVQ3_H
-#define AVCODEC_SVQ3_H
-
-#include <stdint.h>
-
-void ff_svq3_luma_dc_dequant_idct_c(int16_t *output, int16_t *input, int qp);
-void ff_svq3_add_idct_c(uint8_t *dst, int16_t *block, int stride, int qp, int dc);
-
-#endif /* AVCODEC_SVQ3_H */
diff --git a/libavcodec/tak_parser.c b/libavcodec/tak_parser.c
index 4f2149a..1417fb4 100644
--- a/libavcodec/tak_parser.c
+++ b/libavcodec/tak_parser.c
@@ -59,7 +59,7 @@ static int tak_parse(AVCodecParserContext *s, AVCodecContext *avctx,
 
     while (buf_size || t->index + needed <= pc->index) {
         if (buf_size && t->index + TAK_MAX_FRAME_HEADER_BYTES > pc->index) {
-            int tmp_buf_size       = FFMIN(2 * TAK_MAX_FRAME_HEADER_BYTES,
+            int tmp_buf_size       = FFMIN(TAK_MAX_FRAME_HEADER_BYTES,
                                            buf_size);
             const uint8_t *tmp_buf = buf;
 
diff --git a/libavcodec/takdec.c b/libavcodec/takdec.c
index 001086b..023bc87 100644
--- a/libavcodec/takdec.c
+++ b/libavcodec/takdec.c
@@ -163,8 +163,17 @@ static int set_bps_params(AVCodecContext *avctx)
 static void set_sample_rate_params(AVCodecContext *avctx)
 {
     TAKDecContext *s  = avctx->priv_data;
-    int shift         = 3 - (avctx->sample_rate / 11025);
-    shift             = FFMAX(0, shift);
+    int shift;
+
+    if (avctx->sample_rate < 11025) {
+        shift = 3;
+    } else if (avctx->sample_rate < 22050) {
+        shift = 2;
+    } else if (avctx->sample_rate < 44100) {
+        shift = 1;
+    } else {
+        shift = 0;
+    }
     s->uval           = FFALIGN(avctx->sample_rate + 511 >> 9, 4) << shift;
     s->subframe_scale = FFALIGN(avctx->sample_rate + 511 >> 9, 4) << 1;
 }
diff --git a/libavcodec/tdsc.c b/libavcodec/tdsc.c
index 63cd443..d1265a0 100644
--- a/libavcodec/tdsc.c
+++ b/libavcodec/tdsc.c
@@ -56,7 +56,7 @@ typedef struct TDSCContext {
     AVFrame *jpgframe;          // decoded JPEG tile
     uint8_t *tilebuffer;        // buffer containing tile data
 
-    /* zlib interation */
+    /* zlib interaction */
     uint8_t *deflatebuffer;
     uLongf deflatelen;
 
@@ -365,7 +365,7 @@ static int tdsc_decode_jpeg_tile(AVCodecContext *avctx, int tile_size,
             return 0;
     }
 
-    /* Let's paint ont the buffer */
+    /* Let's paint onto the buffer */
     tdsc_blit(ctx->refframe->data[0] + x * 3 + ctx->refframe->linesize[0] * y,
               ctx->refframe->linesize[0],
               ctx->jpgframe->data[0], ctx->jpgframe->linesize[0],
diff --git a/libavcodec/tests/arm/dct.c b/libavcodec/tests/arm/dct.c
new file mode 100644
index 0000000..596d369
--- /dev/null
+++ b/libavcodec/tests/arm/dct.c
@@ -0,0 +1,40 @@
+/*
+ * 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 "config.h"
+
+#include "libavcodec/arm/idct.h"
+
+static const struct algo fdct_tab_arch[] = {
+    { 0 }
+};
+
+static const struct algo idct_tab_arch[] = {
+    { "SIMPLE-ARM",     ff_simple_idct_arm,     FF_IDCT_PERM_NONE },
+    { "INT-ARM",        ff_j_rev_dct_arm,       FF_IDCT_PERM_LIBMPEG2 },
+#if HAVE_ARMV5TE
+    { "SIMPLE-ARMV5TE", ff_simple_idct_armv5te, FF_IDCT_PERM_NONE,      AV_CPU_FLAG_ARMV5TE },
+#endif
+#if HAVE_ARMV6
+    { "SIMPLE-ARMV6",   ff_simple_idct_armv6,   FF_IDCT_PERM_LIBMPEG2,  AV_CPU_FLAG_ARMV6 },
+#endif
+#if HAVE_NEON
+    { "SIMPLE-NEON",    ff_simple_idct_neon,    FF_IDCT_PERM_PARTTRANS, AV_CPU_FLAG_NEON },
+#endif
+    { 0 }
+};
diff --git a/libavcodec/tests/avfft.c b/libavcodec/tests/avfft.c
new file mode 100644
index 0000000..6bc48ea
--- /dev/null
+++ b/libavcodec/tests/avfft.c
@@ -0,0 +1,53 @@
+/*
+ * 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 "config.h"
+#include "libavutil/mem.h"
+#include "libavcodec/avfft.h"
+
+int main(int argc, char **argv)
+{
+    int i;
+#define LEN 1024
+    FFTSample *ref  = av_malloc_array(LEN, sizeof(*ref));
+    FFTSample *data = av_malloc_array(LEN, sizeof(*data));
+    RDFTContext *rdft_context  = av_rdft_init(10, DFT_R2C);
+    RDFTContext *irdft_context = av_rdft_init(10, IDFT_C2R);
+
+    if (!ref || !data || !rdft_context || !irdft_context)
+        return 2;
+    for (i=0; i<LEN; i++) {
+        ref[i] = data[i] = i*456 + 123 + i*i;
+    }
+    av_rdft_calc(rdft_context, data);
+    av_rdft_calc(irdft_context, data);
+
+    for (i=0; i<LEN; i++) {
+        if (fabs(ref[i] - data[i]/LEN*2) > 1) {
+            fprintf(stderr, "Failed at %d (%f %f)\n", i, ref[i], data[i]/LEN*2);
+            return 1;
+        }
+    }
+
+    av_rdft_end(rdft_context);
+    av_rdft_end(irdft_context);
+    av_free(data);
+    av_free(ref);
+
+    return 0;
+}
diff --git a/libavcodec/tests/cabac.c b/libavcodec/tests/cabac.c
new file mode 100644
index 0000000..affe4eb
--- /dev/null
+++ b/libavcodec/tests/cabac.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2003 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/cabac.c"
+
+#define SIZE 10240
+
+#include "libavutil/lfg.h"
+#include "libavcodec/avcodec.h"
+
+static inline void put_cabac_bit(CABACContext *c, int b){
+    put_bits(&c->pb, 1, b);
+    for(;c->outstanding_count; c->outstanding_count--){
+        put_bits(&c->pb, 1, 1-b);
+    }
+}
+
+static inline void renorm_cabac_encoder(CABACContext *c){
+    while(c->range < 0x100){
+        //FIXME optimize
+        if(c->low<0x100){
+            put_cabac_bit(c, 0);
+        }else if(c->low<0x200){
+            c->outstanding_count++;
+            c->low -= 0x100;
+        }else{
+            put_cabac_bit(c, 1);
+            c->low -= 0x200;
+        }
+
+        c->range+= c->range;
+        c->low += c->low;
+    }
+}
+
+static void put_cabac(CABACContext *c, uint8_t * const state, int bit){
+    int RangeLPS= ff_h264_lps_range[2*(c->range&0xC0) + *state];
+
+    if(bit == ((*state)&1)){
+        c->range -= RangeLPS;
+        *state    = ff_h264_mlps_state[128 + *state];
+    }else{
+        c->low += c->range - RangeLPS;
+        c->range = RangeLPS;
+        *state= ff_h264_mlps_state[127 - *state];
+    }
+
+    renorm_cabac_encoder(c);
+}
+
+/**
+ * @param bit 0 -> write zero bit, !=0 write one bit
+ */
+static void put_cabac_bypass(CABACContext *c, int bit){
+    c->low += c->low;
+
+    if(bit){
+        c->low += c->range;
+    }
+//FIXME optimize
+    if(c->low<0x200){
+        put_cabac_bit(c, 0);
+    }else if(c->low<0x400){
+        c->outstanding_count++;
+        c->low -= 0x200;
+    }else{
+        put_cabac_bit(c, 1);
+        c->low -= 0x400;
+    }
+}
+
+/**
+ *
+ * @return the number of bytes written
+ */
+static int put_cabac_terminate(CABACContext *c, int bit){
+    c->range -= 2;
+
+    if(!bit){
+        renorm_cabac_encoder(c);
+    }else{
+        c->low += c->range;
+        c->range= 2;
+
+        renorm_cabac_encoder(c);
+
+        av_assert0(c->low <= 0x1FF);
+        put_cabac_bit(c, c->low>>9);
+        put_bits(&c->pb, 2, ((c->low>>7)&3)|1);
+
+        flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong
+    }
+
+    return (put_bits_count(&c->pb)+7)>>3;
+}
+
+int main(void){
+    CABACContext c;
+    uint8_t b[9*SIZE];
+    uint8_t r[9*SIZE];
+    int i, ret = 0;
+    uint8_t state[10]= {0};
+    AVLFG prng;
+
+    av_lfg_init(&prng, 1);
+    ff_init_cabac_encoder(&c, b, SIZE);
+
+    for(i=0; i<SIZE; i++){
+        if(2*i<SIZE) r[i] = av_lfg_get(&prng) % 7;
+        else         r[i] = (i>>8)&1;
+    }
+
+    for(i=0; i<SIZE; i++){
+        put_cabac_bypass(&c, r[i]&1);
+    }
+
+    for(i=0; i<SIZE; i++){
+        put_cabac(&c, state, r[i]&1);
+    }
+
+    i= put_cabac_terminate(&c, 1);
+    b[i++] = av_lfg_get(&prng);
+    b[i  ] = av_lfg_get(&prng);
+
+    ff_init_cabac_decoder(&c, b, SIZE);
+
+    memset(state, 0, sizeof(state));
+
+    for(i=0; i<SIZE; i++){
+        if( (r[i]&1) != get_cabac_bypass(&c) ) {
+            av_log(NULL, AV_LOG_ERROR, "CABAC bypass failure at %d\n", i);
+            ret = 1;
+        }
+    }
+
+    for(i=0; i<SIZE; i++){
+        if( (r[i]&1) != get_cabac_noinline(&c, state) ) {
+            av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i);
+            ret = 1;
+        }
+    }
+    if(!get_cabac_terminate(&c)) {
+        av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n");
+        ret = 1;
+    }
+
+    return ret;
+}
diff --git a/libavcodec/tests/dct.c b/libavcodec/tests/dct.c
new file mode 100644
index 0000000..5303fdf
--- /dev/null
+++ b/libavcodec/tests/dct.c
@@ -0,0 +1,523 @@
+/*
+ * (c) 2001 Fabrice Bellard
+ *     2007 Marc Hoffman <marc.hoffman at analog.com>
+ *
+ * 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
+ * DCT test (c) 2001 Fabrice Bellard
+ * Started from sample code by Juan J. Sierralta P.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <math.h>
+
+#include "libavutil/cpu.h"
+#include "libavutil/common.h"
+#include "libavutil/internal.h"
+#include "libavutil/lfg.h"
+#include "libavutil/time.h"
+
+#include "libavcodec/dct.h"
+#include "libavcodec/idctdsp.h"
+#include "libavcodec/simple_idct.h"
+#include "libavcodec/xvididct.h"
+#include "libavcodec/aandcttab.h"
+#include "libavcodec/faandct.h"
+#include "libavcodec/faanidct.h"
+#include "libavcodec/dctref.h"
+
+struct algo {
+    const char *name;
+    void (*func)(int16_t *block);
+    enum idct_permutation_type perm_type;
+    int cpu_flag;
+    int nonspec;
+};
+
+static const struct algo fdct_tab[] = {
+    { "REF-DBL",     ff_ref_fdct,          FF_IDCT_PERM_NONE },
+    { "IJG-AAN-INT", ff_fdct_ifast,        FF_IDCT_PERM_NONE },
+    { "IJG-LLM-INT", ff_jpeg_fdct_islow_8, FF_IDCT_PERM_NONE },
+#if CONFIG_FAANDCT
+    { "FAAN",        ff_faandct,           FF_IDCT_PERM_NONE },
+#endif /* CONFIG_FAANDCT */
+};
+
+static void ff_prores_idct_wrap(int16_t *dst){
+    LOCAL_ALIGNED(16, int16_t, qmat, [64]);
+    int i;
+
+    for(i=0; i<64; i++){
+        qmat[i]=4;
+    }
+    ff_prores_idct(dst, qmat);
+    for(i=0; i<64; i++) {
+         dst[i] -= 512;
+    }
+}
+
+static const struct algo idct_tab[] = {
+    { "REF-DBL",     ff_ref_idct,          FF_IDCT_PERM_NONE },
+    { "INT",         ff_j_rev_dct,         FF_IDCT_PERM_LIBMPEG2 },
+    { "SIMPLE-C",    ff_simple_idct_8,     FF_IDCT_PERM_NONE },
+    { "SIMPLE-C10",  ff_simple_idct_10,    FF_IDCT_PERM_NONE },
+    { "SIMPLE-C12",  ff_simple_idct_12,    FF_IDCT_PERM_NONE, 0, 1 },
+    { "PR-C",        ff_prores_idct_wrap,  FF_IDCT_PERM_NONE, 0, 1 },
+#if CONFIG_FAANIDCT
+    { "FAANI",       ff_faanidct,          FF_IDCT_PERM_NONE },
+#endif /* CONFIG_FAANIDCT */
+#if CONFIG_MPEG4_DECODER
+    { "XVID",        ff_xvid_idct,         FF_IDCT_PERM_NONE, 0, 1 },
+#endif /* CONFIG_MPEG4_DECODER */
+};
+
+#if ARCH_ARM
+#include "arm/dct.c"
+#elif ARCH_PPC
+#include "ppc/dct.c"
+#elif ARCH_X86
+#include "x86/dct.c"
+#else
+static const struct algo fdct_tab_arch[] = { { 0 } };
+static const struct algo idct_tab_arch[] = { { 0 } };
+#endif
+
+#define AANSCALE_BITS 12
+
+#define NB_ITS 20000
+#define NB_ITS_SPEED 50000
+
+DECLARE_ALIGNED(16, static int16_t, block)[64];
+DECLARE_ALIGNED(8,  static int16_t, block1)[64];
+
+static void init_block(int16_t block[64], int test, int is_idct, AVLFG *prng, int vals)
+{
+    int i, j;
+
+    memset(block, 0, 64 * sizeof(*block));
+
+    switch (test) {
+    case 0:
+        for (i = 0; i < 64; i++)
+            block[i] = (av_lfg_get(prng) % (2*vals)) -vals;
+        if (is_idct) {
+            ff_ref_fdct(block);
+            for (i = 0; i < 64; i++)
+                block[i] >>= 3;
+        }
+        break;
+    case 1:
+        j = av_lfg_get(prng) % 10 + 1;
+        for (i = 0; i < j; i++) {
+            int idx = av_lfg_get(prng) % 64;
+            block[idx] = av_lfg_get(prng) % (2*vals) -vals;
+        }
+        break;
+    case 2:
+        block[ 0] = av_lfg_get(prng) % (16*vals) - (8*vals);
+        block[63] = (block[0] & 1) ^ 1;
+        break;
+    }
+}
+
+static void permute(int16_t dst[64], const int16_t src[64],
+                    enum idct_permutation_type perm_type)
+{
+    int i;
+
+#if ARCH_X86
+    if (permute_x86(dst, src, perm_type))
+        return;
+#endif
+
+    switch (perm_type) {
+    case FF_IDCT_PERM_LIBMPEG2:
+        for (i = 0; i < 64; i++)
+            dst[(i & 0x38) | ((i & 6) >> 1) | ((i & 1) << 2)] = src[i];
+        break;
+    case FF_IDCT_PERM_PARTTRANS:
+        for (i = 0; i < 64; i++)
+            dst[(i & 0x24) | ((i & 3) << 3) | ((i >> 3) & 3)] = src[i];
+        break;
+    case FF_IDCT_PERM_TRANSPOSE:
+        for (i = 0; i < 64; i++)
+            dst[(i>>3) | ((i<<3)&0x38)] = src[i];
+        break;
+    default:
+        for (i = 0; i < 64; i++)
+            dst[i] = src[i];
+        break;
+    }
+}
+
+static int dct_error(const struct algo *dct, int test, int is_idct, int speed, const int bits)
+{
+    void (*ref)(int16_t *block) = is_idct ? ff_ref_idct : ff_ref_fdct;
+    int it, i, scale;
+    int err_inf, v;
+    int64_t err2, ti, ti1, it1, err_sum = 0;
+    int64_t sysErr[64], sysErrMax = 0;
+    int maxout = 0;
+    int blockSumErrMax = 0, blockSumErr;
+    AVLFG prng;
+    const int vals=1<<bits;
+    double omse, ome;
+    int spec_err;
+
+    av_lfg_init(&prng, 1);
+
+    err_inf = 0;
+    err2 = 0;
+    for (i = 0; i < 64; i++)
+        sysErr[i] = 0;
+    for (it = 0; it < NB_ITS; it++) {
+        init_block(block1, test, is_idct, &prng, vals);
+        permute(block, block1, dct->perm_type);
+
+        dct->func(block);
+        emms_c();
+
+        if (!strcmp(dct->name, "IJG-AAN-INT")) {
+            for (i = 0; i < 64; i++) {
+                scale = 8 * (1 << (AANSCALE_BITS + 11)) / ff_aanscales[i];
+                block[i] = (block[i] * scale) >> AANSCALE_BITS;
+            }
+        }
+
+        ref(block1);
+        if (!strcmp(dct->name, "PR-SSE2"))
+            for (i = 0; i < 64; i++)
+                block1[i] = av_clip(block1[i], 4-512, 1019-512);
+
+        blockSumErr = 0;
+        for (i = 0; i < 64; i++) {
+            int err = block[i] - block1[i];
+            err_sum += err;
+            v = abs(err);
+            if (v > err_inf)
+                err_inf = v;
+            err2 += v * v;
+            sysErr[i] += block[i] - block1[i];
+            blockSumErr += v;
+            if (abs(block[i]) > maxout)
+                maxout = abs(block[i]);
+        }
+        if (blockSumErrMax < blockSumErr)
+            blockSumErrMax = blockSumErr;
+    }
+    for (i = 0; i < 64; i++)
+        sysErrMax = FFMAX(sysErrMax, FFABS(sysErr[i]));
+
+    for (i = 0; i < 64; i++) {
+        if (i % 8 == 0)
+            printf("\n");
+        printf("%7d ", (int) sysErr[i]);
+    }
+    printf("\n");
+
+    omse = (double) err2 / NB_ITS / 64;
+    ome  = (double) err_sum / NB_ITS / 64;
+
+    spec_err = is_idct && (err_inf > 1 || omse > 0.02 || fabs(ome) > 0.0015);
+
+    printf("%s %s: max_err=%d omse=%0.8f ome=%0.8f syserr=%0.8f maxout=%d blockSumErr=%d\n",
+           is_idct ? "IDCT" : "DCT", dct->name, err_inf,
+           omse, ome, (double) sysErrMax / NB_ITS,
+           maxout, blockSumErrMax);
+
+    if (spec_err && !dct->nonspec) {
+        printf("Failed!\n");
+        return 1;
+    }
+
+    if (!speed)
+        return 0;
+
+    /* speed test */
+
+    init_block(block, test, is_idct, &prng, vals);
+    permute(block1, block, dct->perm_type);
+
+    ti = av_gettime_relative();
+    it1 = 0;
+    do {
+        for (it = 0; it < NB_ITS_SPEED; it++) {
+            memcpy(block, block1, sizeof(block));
+            dct->func(block);
+        }
+        emms_c();
+        it1 += NB_ITS_SPEED;
+        ti1 = av_gettime_relative() - ti;
+    } while (ti1 < 1000000);
+
+    printf("%s %s: %0.1f kdct/s\n", is_idct ? "IDCT" : "DCT", dct->name,
+           (double) it1 * 1000.0 / (double) ti1);
+
+    return 0;
+}
+
+DECLARE_ALIGNED(8, static uint8_t, img_dest)[64];
+DECLARE_ALIGNED(8, static uint8_t, img_dest1)[64];
+
+static void idct248_ref(uint8_t *dest, int linesize, int16_t *block)
+{
+    static int init;
+    static double c8[8][8];
+    static double c4[4][4];
+    double block1[64], block2[64], block3[64];
+    double s, sum, v;
+    int i, j, k;
+
+    if (!init) {
+        init = 1;
+
+        for (i = 0; i < 8; i++) {
+            sum = 0;
+            for (j = 0; j < 8; j++) {
+                s = (i == 0) ? sqrt(1.0 / 8.0) : sqrt(1.0 / 4.0);
+                c8[i][j] = s * cos(M_PI * i * (j + 0.5) / 8.0);
+                sum += c8[i][j] * c8[i][j];
+            }
+        }
+
+        for (i = 0; i < 4; i++) {
+            sum = 0;
+            for (j = 0; j < 4; j++) {
+                s = (i == 0) ? sqrt(1.0 / 4.0) : sqrt(1.0 / 2.0);
+                c4[i][j] = s * cos(M_PI * i * (j + 0.5) / 4.0);
+                sum += c4[i][j] * c4[i][j];
+            }
+        }
+    }
+
+    /* butterfly */
+    s = 0.5 * sqrt(2.0);
+    for (i = 0; i < 4; i++) {
+        for (j = 0; j < 8; j++) {
+            block1[8 * (2 * i) + j] =
+                (block[8 * (2 * i) + j] + block[8 * (2 * i + 1) + j]) * s;
+            block1[8 * (2 * i + 1) + j] =
+                (block[8 * (2 * i) + j] - block[8 * (2 * i + 1) + j]) * s;
+        }
+    }
+
+    /* idct8 on lines */
+    for (i = 0; i < 8; i++) {
+        for (j = 0; j < 8; j++) {
+            sum = 0;
+            for (k = 0; k < 8; k++)
+                sum += c8[k][j] * block1[8 * i + k];
+            block2[8 * i + j] = sum;
+        }
+    }
+
+    /* idct4 */
+    for (i = 0; i < 8; i++) {
+        for (j = 0; j < 4; j++) {
+            /* top */
+            sum = 0;
+            for (k = 0; k < 4; k++)
+                sum += c4[k][j] * block2[8 * (2 * k) + i];
+            block3[8 * (2 * j) + i] = sum;
+
+            /* bottom */
+            sum = 0;
+            for (k = 0; k < 4; k++)
+                sum += c4[k][j] * block2[8 * (2 * k + 1) + i];
+            block3[8 * (2 * j + 1) + i] = sum;
+        }
+    }
+
+    /* clamp and store the result */
+    for (i = 0; i < 8; i++) {
+        for (j = 0; j < 8; j++) {
+            v = block3[8 * i + j];
+            if      (v < 0)   v = 0;
+            else if (v > 255) v = 255;
+            dest[i * linesize + j] = (int) rint(v);
+        }
+    }
+}
+
+static void idct248_error(const char *name,
+                          void (*idct248_put)(uint8_t *dest, int line_size,
+                                              int16_t *block),
+                          int speed)
+{
+    int it, i, it1, ti, ti1, err_max, v;
+    AVLFG prng;
+
+    av_lfg_init(&prng, 1);
+
+    /* just one test to see if code is correct (precision is less
+       important here) */
+    err_max = 0;
+    for (it = 0; it < NB_ITS; it++) {
+        /* XXX: use forward transform to generate values */
+        for (i = 0; i < 64; i++)
+            block1[i] = av_lfg_get(&prng) % 256 - 128;
+        block1[0] += 1024;
+
+        for (i = 0; i < 64; i++)
+            block[i] = block1[i];
+        idct248_ref(img_dest1, 8, block);
+
+        for (i = 0; i < 64; i++)
+            block[i] = block1[i];
+        idct248_put(img_dest, 8, block);
+
+        for (i = 0; i < 64; i++) {
+            v = abs((int) img_dest[i] - (int) img_dest1[i]);
+            if (v == 255)
+                printf("%d %d\n", img_dest[i], img_dest1[i]);
+            if (v > err_max)
+                err_max = v;
+        }
+#if 0
+        printf("ref=\n");
+        for(i=0;i<8;i++) {
+            int j;
+            for(j=0;j<8;j++) {
+                printf(" %3d", img_dest1[i*8+j]);
+            }
+            printf("\n");
+        }
+
+        printf("out=\n");
+        for(i=0;i<8;i++) {
+            int j;
+            for(j=0;j<8;j++) {
+                printf(" %3d", img_dest[i*8+j]);
+            }
+            printf("\n");
+        }
+#endif
+    }
+    printf("%s %s: err_inf=%d\n", 1 ? "IDCT248" : "DCT248", name, err_max);
+
+    if (!speed)
+        return;
+
+    ti = av_gettime_relative();
+    it1 = 0;
+    do {
+        for (it = 0; it < NB_ITS_SPEED; it++) {
+            for (i = 0; i < 64; i++)
+                block[i] = block1[i];
+            idct248_put(img_dest, 8, block);
+        }
+        emms_c();
+        it1 += NB_ITS_SPEED;
+        ti1 = av_gettime_relative() - ti;
+    } while (ti1 < 1000000);
+
+    printf("%s %s: %0.1f kdct/s\n", 1 ? "IDCT248" : "DCT248", name,
+           (double) it1 * 1000.0 / (double) ti1);
+}
+
+static void help(void)
+{
+    printf("dct-test [-i] [<test-number>] [<bits>]\n"
+           "test-number 0 -> test with random matrixes\n"
+           "            1 -> test with random sparse matrixes\n"
+           "            2 -> do 3. test from MPEG-4 std\n"
+           "bits        Number of time domain bits to use, 8 is default\n"
+           "-i          test IDCT implementations\n"
+           "-4          test IDCT248 implementations\n"
+           "-t          speed test\n");
+}
+
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+int main(int argc, char **argv)
+{
+    int test_idct = 0, test_248_dct = 0;
+    int c, i;
+    int test = 1;
+    int speed = 0;
+    int err = 0;
+    int bits=8;
+
+    ff_ref_dct_init();
+
+    for (;;) {
+        c = getopt(argc, argv, "ih4t");
+        if (c == -1)
+            break;
+        switch (c) {
+        case 'i':
+            test_idct = 1;
+            break;
+        case '4':
+            test_248_dct = 1;
+            break;
+        case 't':
+            speed = 1;
+            break;
+        default:
+        case 'h':
+            help();
+            return 0;
+        }
+    }
+
+    if (optind < argc)
+        test = atoi(argv[optind]);
+    if(optind+1 < argc) bits= atoi(argv[optind+1]);
+
+    printf("ffmpeg DCT/IDCT test\n");
+
+    if (test_248_dct) {
+        idct248_error("SIMPLE-C", ff_simple_idct248_put, speed);
+    } else {
+        const int cpu_flags = av_get_cpu_flags();
+        if (test_idct) {
+            for (i = 0; i < FF_ARRAY_ELEMS(idct_tab); i++)
+                err |= dct_error(&idct_tab[i], test, test_idct, speed, bits);
+
+            for (i = 0; idct_tab_arch[i].name; i++)
+                if (!(~cpu_flags & idct_tab_arch[i].cpu_flag))
+                    err |= dct_error(&idct_tab_arch[i], test, test_idct, speed, bits);
+        }
+#if CONFIG_FDCTDSP
+        else {
+            for (i = 0; i < FF_ARRAY_ELEMS(fdct_tab); i++)
+                err |= dct_error(&fdct_tab[i], test, test_idct, speed, bits);
+
+            for (i = 0; fdct_tab_arch[i].name; i++)
+                if (!(~cpu_flags & fdct_tab_arch[i].cpu_flag))
+                    err |= dct_error(&fdct_tab_arch[i], test, test_idct, speed, bits);
+        }
+#endif /* CONFIG_FDCTDSP */
+    }
+
+    if (err)
+        printf("Error: %d.\n", err);
+
+    return !!err;
+}
diff --git a/libavcodec/tests/fft-fixed.c b/libavcodec/tests/fft-fixed.c
new file mode 100644
index 0000000..fe1b57a
--- /dev/null
+++ b/libavcodec/tests/fft-fixed.c
@@ -0,0 +1,20 @@
+/*
+ * 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
+ */
+
+#define FFT_FLOAT 0
+#include "fft.c"
diff --git a/libavcodec/tests/fft-fixed32.c b/libavcodec/tests/fft-fixed32.c
new file mode 100644
index 0000000..f33494f
--- /dev/null
+++ b/libavcodec/tests/fft-fixed32.c
@@ -0,0 +1,21 @@
+/*
+ * 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
+ */
+
+#define FFT_FLOAT 0
+#define FFT_FIXED_32 1
+#include "fft.c"
diff --git a/libavcodec/tests/fft.c b/libavcodec/tests/fft.c
new file mode 100644
index 0000000..4717303
--- /dev/null
+++ b/libavcodec/tests/fft.c
@@ -0,0 +1,519 @@
+/*
+ * (c) 2002 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * FFT and MDCT tests.
+ */
+
+#include "config.h"
+
+#include <math.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libavutil/cpu.h"
+#include "libavutil/lfg.h"
+#include "libavutil/log.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/time.h"
+
+#include "libavcodec/fft.h"
+#if FFT_FLOAT
+#include "libavcodec/dct.h"
+#include "libavcodec/rdft.h"
+#endif
+
+/* reference fft */
+
+#define MUL16(a, b) ((a) * (b))
+
+#define CMAC(pre, pim, are, aim, bre, bim)          \
+    {                                               \
+        pre += (MUL16(are, bre) - MUL16(aim, bim)); \
+        pim += (MUL16(are, bim) + MUL16(bre, aim)); \
+    }
+
+#if FFT_FLOAT
+#define RANGE 1.0
+#define REF_SCALE(x, bits)  (x)
+#define FMT "%10.6f"
+#elif FFT_FIXED_32
+#define RANGE 8388608
+#define REF_SCALE(x, bits) (x)
+#define FMT "%6d"
+#else
+#define RANGE 16384
+#define REF_SCALE(x, bits) ((x) / (1 << (bits)))
+#define FMT "%6d"
+#endif
+
+static struct {
+    float re, im;
+} *exptab;
+
+static int fft_ref_init(int nbits, int inverse)
+{
+    int i, n = 1 << nbits;
+
+    exptab = av_malloc_array((n / 2), sizeof(*exptab));
+    if (!exptab)
+        return AVERROR(ENOMEM);
+
+    for (i = 0; i < (n / 2); i++) {
+        double alpha = 2 * M_PI * (float) i / (float) n;
+        double c1 = cos(alpha), s1 = sin(alpha);
+        if (!inverse)
+            s1 = -s1;
+        exptab[i].re = c1;
+        exptab[i].im = s1;
+    }
+    return 0;
+}
+
+static void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits)
+{
+    int i, j;
+    int n  = 1 << nbits;
+    int n2 = n >> 1;
+
+    for (i = 0; i < n; i++) {
+        double tmp_re = 0, tmp_im = 0;
+        FFTComplex *q = tab;
+        for (j = 0; j < n; j++) {
+            double s, c;
+            int k = (i * j) & (n - 1);
+            if (k >= n2) {
+                c = -exptab[k - n2].re;
+                s = -exptab[k - n2].im;
+            } else {
+                c = exptab[k].re;
+                s = exptab[k].im;
+            }
+            CMAC(tmp_re, tmp_im, c, s, q->re, q->im);
+            q++;
+        }
+        tabr[i].re = REF_SCALE(tmp_re, nbits);
+        tabr[i].im = REF_SCALE(tmp_im, nbits);
+    }
+}
+
+#if CONFIG_MDCT
+static void imdct_ref(FFTSample *out, FFTSample *in, int nbits)
+{
+    int i, k, n = 1 << nbits;
+
+    for (i = 0; i < n; i++) {
+        double sum = 0;
+        for (k = 0; k < n / 2; k++) {
+            int a = (2 * i + 1 + (n / 2)) * (2 * k + 1);
+            double f = cos(M_PI * a / (double) (2 * n));
+            sum += f * in[k];
+        }
+        out[i] = REF_SCALE(-sum, nbits - 2);
+    }
+}
+
+/* NOTE: no normalisation by 1 / N is done */
+static void mdct_ref(FFTSample *output, FFTSample *input, int nbits)
+{
+    int i, k, n = 1 << nbits;
+
+    /* do it by hand */
+    for (k = 0; k < n / 2; k++) {
+        double s = 0;
+        for (i = 0; i < n; i++) {
+            double a = (2 * M_PI * (2 * i + 1 + n / 2) * (2 * k + 1) / (4 * n));
+            s += input[i] * cos(a);
+        }
+        output[k] = REF_SCALE(s, nbits - 1);
+    }
+}
+#endif /* CONFIG_MDCT */
+
+#if FFT_FLOAT
+#if CONFIG_DCT
+static void idct_ref(FFTSample *output, FFTSample *input, int nbits)
+{
+    int i, k, n = 1 << nbits;
+
+    /* do it by hand */
+    for (i = 0; i < n; i++) {
+        double s = 0.5 * input[0];
+        for (k = 1; k < n; k++) {
+            double a = M_PI * k * (i + 0.5) / n;
+            s += input[k] * cos(a);
+        }
+        output[i] = 2 * s / n;
+    }
+}
+
+static void dct_ref(FFTSample *output, FFTSample *input, int nbits)
+{
+    int i, k, n = 1 << nbits;
+
+    /* do it by hand */
+    for (k = 0; k < n; k++) {
+        double s = 0;
+        for (i = 0; i < n; i++) {
+            double a = M_PI * k * (i + 0.5) / n;
+            s += input[i] * cos(a);
+        }
+        output[k] = s;
+    }
+}
+#endif /* CONFIG_DCT */
+#endif /* FFT_FLOAT */
+
+static FFTSample frandom(AVLFG *prng)
+{
+    return (int16_t) av_lfg_get(prng) / 32768.0 * RANGE;
+}
+
+static int check_diff(FFTSample *tab1, FFTSample *tab2, int n, double scale)
+{
+    int i, err = 0;
+    double error = 0, max = 0;
+
+    for (i = 0; i < n; i++) {
+        double e = fabs(tab1[i] - (tab2[i] / scale)) / RANGE;
+        if (e >= 1e-3) {
+            av_log(NULL, AV_LOG_ERROR, "ERROR %5d: "FMT" "FMT"\n",
+                   i, tab1[i], tab2[i]);
+            err = 1;
+        }
+        error += e * e;
+        if (e > max)
+            max = e;
+    }
+    av_log(NULL, AV_LOG_INFO, "max:%f e:%g\n", max, sqrt(error / n));
+    return err;
+}
+
+static void help(void)
+{
+    av_log(NULL, AV_LOG_INFO,
+           "usage: fft-test [-h] [-s] [-i] [-n b]\n"
+           "-h     print this help\n"
+           "-s     speed test\n"
+           "-m     (I)MDCT test\n"
+           "-d     (I)DCT test\n"
+           "-r     (I)RDFT test\n"
+           "-i     inverse transform test\n"
+           "-n b   set the transform size to 2^b\n"
+           "-f x   set scale factor for output data of (I)MDCT to x\n");
+}
+
+enum tf_transform {
+    TRANSFORM_FFT,
+    TRANSFORM_MDCT,
+    TRANSFORM_RDFT,
+    TRANSFORM_DCT,
+};
+
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+int main(int argc, char **argv)
+{
+    FFTComplex *tab, *tab1, *tab_ref;
+    FFTSample *tab2;
+    enum tf_transform transform = TRANSFORM_FFT;
+    FFTContext m, s;
+#if FFT_FLOAT
+    RDFTContext r;
+    DCTContext d;
+#endif /* FFT_FLOAT */
+    int it, i, err = 1;
+    int do_speed = 0, do_inverse = 0;
+    int fft_nbits = 9, fft_size;
+    double scale = 1.0;
+    AVLFG prng;
+
+    av_lfg_init(&prng, 1);
+
+    for (;;) {
+        int c = getopt(argc, argv, "hsimrdn:f:c:");
+        if (c == -1)
+            break;
+        switch (c) {
+        case 'h':
+            help();
+            return 1;
+        case 's':
+            do_speed = 1;
+            break;
+        case 'i':
+            do_inverse = 1;
+            break;
+        case 'm':
+            transform = TRANSFORM_MDCT;
+            break;
+        case 'r':
+            transform = TRANSFORM_RDFT;
+            break;
+        case 'd':
+            transform = TRANSFORM_DCT;
+            break;
+        case 'n':
+            fft_nbits = atoi(optarg);
+            break;
+        case 'f':
+            scale = atof(optarg);
+            break;
+        case 'c':
+        {
+            unsigned cpuflags = av_get_cpu_flags();
+
+            if (av_parse_cpu_caps(&cpuflags, optarg) < 0)
+                return 1;
+
+            av_force_cpu_flags(cpuflags);
+            break;
+        }
+        }
+    }
+
+    fft_size = 1 << fft_nbits;
+    tab      = av_malloc_array(fft_size, sizeof(FFTComplex));
+    tab1     = av_malloc_array(fft_size, sizeof(FFTComplex));
+    tab_ref  = av_malloc_array(fft_size, sizeof(FFTComplex));
+    tab2     = av_malloc_array(fft_size, sizeof(FFTSample));
+
+    if (!(tab && tab1 && tab_ref && tab2))
+        goto cleanup;
+
+    switch (transform) {
+#if CONFIG_MDCT
+    case TRANSFORM_MDCT:
+        av_log(NULL, AV_LOG_INFO, "Scale factor is set to %f\n", scale);
+        if (do_inverse)
+            av_log(NULL, AV_LOG_INFO, "IMDCT");
+        else
+            av_log(NULL, AV_LOG_INFO, "MDCT");
+        ff_mdct_init(&m, fft_nbits, do_inverse, scale);
+        break;
+#endif /* CONFIG_MDCT */
+    case TRANSFORM_FFT:
+        if (do_inverse)
+            av_log(NULL, AV_LOG_INFO, "IFFT");
+        else
+            av_log(NULL, AV_LOG_INFO, "FFT");
+        ff_fft_init(&s, fft_nbits, do_inverse);
+        if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0)
+            goto cleanup;
+        break;
+#if FFT_FLOAT
+#    if CONFIG_RDFT
+    case TRANSFORM_RDFT:
+        if (do_inverse)
+            av_log(NULL, AV_LOG_INFO, "IDFT_C2R");
+        else
+            av_log(NULL, AV_LOG_INFO, "DFT_R2C");
+        ff_rdft_init(&r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C);
+        if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0)
+            goto cleanup;
+        break;
+#    endif /* CONFIG_RDFT */
+#    if CONFIG_DCT
+    case TRANSFORM_DCT:
+        if (do_inverse)
+            av_log(NULL, AV_LOG_INFO, "DCT_III");
+        else
+            av_log(NULL, AV_LOG_INFO, "DCT_II");
+        ff_dct_init(&d, fft_nbits, do_inverse ? DCT_III : DCT_II);
+        break;
+#    endif /* CONFIG_DCT */
+#endif /* FFT_FLOAT */
+    default:
+        av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n");
+        goto cleanup;
+    }
+    av_log(NULL, AV_LOG_INFO, " %d test\n", fft_size);
+
+    /* generate random data */
+
+    for (i = 0; i < fft_size; i++) {
+        tab1[i].re = frandom(&prng);
+        tab1[i].im = frandom(&prng);
+    }
+
+    /* checking result */
+    av_log(NULL, AV_LOG_INFO, "Checking...\n");
+
+    switch (transform) {
+#if CONFIG_MDCT
+    case TRANSFORM_MDCT:
+        if (do_inverse) {
+            imdct_ref(&tab_ref->re, &tab1->re, fft_nbits);
+            m.imdct_calc(&m, tab2, &tab1->re);
+            err = check_diff(&tab_ref->re, tab2, fft_size, scale);
+        } else {
+            mdct_ref(&tab_ref->re, &tab1->re, fft_nbits);
+            m.mdct_calc(&m, tab2, &tab1->re);
+            err = check_diff(&tab_ref->re, tab2, fft_size / 2, scale);
+        }
+        break;
+#endif /* CONFIG_MDCT */
+    case TRANSFORM_FFT:
+        memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
+        s.fft_permute(&s, tab);
+        s.fft_calc(&s, tab);
+
+        fft_ref(tab_ref, tab1, fft_nbits);
+        err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0);
+        break;
+#if FFT_FLOAT
+#if CONFIG_RDFT
+    case TRANSFORM_RDFT:
+    {
+        int fft_size_2 = fft_size >> 1;
+        if (do_inverse) {
+            tab1[0].im          = 0;
+            tab1[fft_size_2].im = 0;
+            for (i = 1; i < fft_size_2; i++) {
+                tab1[fft_size_2 + i].re =  tab1[fft_size_2 - i].re;
+                tab1[fft_size_2 + i].im = -tab1[fft_size_2 - i].im;
+            }
+
+            memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
+            tab2[1] = tab1[fft_size_2].re;
+
+            r.rdft_calc(&r, tab2);
+            fft_ref(tab_ref, tab1, fft_nbits);
+            for (i = 0; i < fft_size; i++) {
+                tab[i].re = tab2[i];
+                tab[i].im = 0;
+            }
+            err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 0.5);
+        } else {
+            for (i = 0; i < fft_size; i++) {
+                tab2[i]    = tab1[i].re;
+                tab1[i].im = 0;
+            }
+            r.rdft_calc(&r, tab2);
+            fft_ref(tab_ref, tab1, fft_nbits);
+            tab_ref[0].im = tab_ref[fft_size_2].re;
+            err = check_diff(&tab_ref->re, tab2, fft_size, 1.0);
+        }
+        break;
+    }
+#endif /* CONFIG_RDFT */
+#if CONFIG_DCT
+    case TRANSFORM_DCT:
+        memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
+        d.dct_calc(&d, &tab->re);
+        if (do_inverse)
+            idct_ref(&tab_ref->re, &tab1->re, fft_nbits);
+        else
+            dct_ref(&tab_ref->re, &tab1->re, fft_nbits);
+        err = check_diff(&tab_ref->re, &tab->re, fft_size, 1.0);
+        break;
+#endif /* CONFIG_DCT */
+#endif /* FFT_FLOAT */
+    }
+
+    /* do a speed test */
+
+    if (do_speed) {
+        int64_t time_start, duration;
+        int nb_its;
+
+        av_log(NULL, AV_LOG_INFO, "Speed test...\n");
+        /* we measure during about 1 seconds */
+        nb_its = 1;
+        for (;;) {
+            time_start = av_gettime_relative();
+            for (it = 0; it < nb_its; it++) {
+                switch (transform) {
+                case TRANSFORM_MDCT:
+                    if (do_inverse)
+                        m.imdct_calc(&m, &tab->re, &tab1->re);
+                    else
+                        m.mdct_calc(&m, &tab->re, &tab1->re);
+                    break;
+                case TRANSFORM_FFT:
+                    memcpy(tab, tab1, fft_size * sizeof(FFTComplex));
+                    s.fft_calc(&s, tab);
+                    break;
+#if FFT_FLOAT
+                case TRANSFORM_RDFT:
+                    memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
+                    r.rdft_calc(&r, tab2);
+                    break;
+                case TRANSFORM_DCT:
+                    memcpy(tab2, tab1, fft_size * sizeof(FFTSample));
+                    d.dct_calc(&d, tab2);
+                    break;
+#endif /* FFT_FLOAT */
+                }
+            }
+            duration = av_gettime_relative() - time_start;
+            if (duration >= 1000000)
+                break;
+            nb_its *= 2;
+        }
+        av_log(NULL, AV_LOG_INFO,
+               "time: %0.1f us/transform [total time=%0.2f s its=%d]\n",
+               (double) duration / nb_its,
+               (double) duration / 1000000.0,
+               nb_its);
+    }
+
+    switch (transform) {
+#if CONFIG_MDCT
+    case TRANSFORM_MDCT:
+        ff_mdct_end(&m);
+        break;
+#endif /* CONFIG_MDCT */
+    case TRANSFORM_FFT:
+        ff_fft_end(&s);
+        break;
+#if FFT_FLOAT
+#    if CONFIG_RDFT
+    case TRANSFORM_RDFT:
+        ff_rdft_end(&r);
+        break;
+#    endif /* CONFIG_RDFT */
+#    if CONFIG_DCT
+    case TRANSFORM_DCT:
+        ff_dct_end(&d);
+        break;
+#    endif /* CONFIG_DCT */
+#endif /* FFT_FLOAT */
+    }
+
+cleanup:
+    av_free(tab);
+    av_free(tab1);
+    av_free(tab2);
+    av_free(tab_ref);
+    av_free(exptab);
+
+    if (err)
+        printf("Error: %d.\n", err);
+
+    return !!err;
+}
diff --git a/libavcodec/tests/golomb.c b/libavcodec/tests/golomb.c
new file mode 100644
index 0000000..965367b
--- /dev/null
+++ b/libavcodec/tests/golomb.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2003 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "libavutil/mem.h"
+
+#include "libavcodec/get_bits.h"
+#include "libavcodec/golomb.h"
+#include "libavcodec/put_bits.h"
+
+#define COUNT 8191
+#define SIZE (COUNT * 4)
+
+int main(void)
+{
+    int i, ret = 0;
+    uint8_t *temp;
+    PutBitContext pb;
+    GetBitContext gb;
+
+    temp = av_malloc(SIZE);
+    if (!temp)
+        return 2;
+
+    init_put_bits(&pb, temp, SIZE);
+    for (i = 0; i < COUNT; i++)
+        set_ue_golomb(&pb, i);
+    flush_put_bits(&pb);
+
+    init_get_bits(&gb, temp, 8 * SIZE);
+    for (i = 0; i < COUNT; i++) {
+        int j, s = show_bits(&gb, 25);
+
+        j = get_ue_golomb(&gb);
+        if (j != i) {
+            fprintf(stderr, "get_ue_golomb: expected %d, got %d. bits: %7x\n",
+                    i, j, s);
+            ret = 1;
+        }
+    }
+
+#define EXTEND(i) ((i) << 3 | (i) & 7)
+    init_put_bits(&pb, temp, SIZE);
+    for (i = 0; i < COUNT; i++)
+        set_ue_golomb(&pb, EXTEND(i));
+    flush_put_bits(&pb);
+
+    init_get_bits(&gb, temp, 8 * SIZE);
+    for (i = 0; i < COUNT; i++) {
+        int j, s = show_bits_long(&gb, 32);
+
+        j = get_ue_golomb_long(&gb);
+        if (j != EXTEND(i)) {
+            fprintf(stderr, "get_ue_golomb_long: expected %d, got %d. "
+                    "bits: %8x\n", EXTEND(i), j, s);
+            ret = 1;
+        }
+    }
+
+    init_put_bits(&pb, temp, SIZE);
+    for (i = 0; i < COUNT; i++)
+        set_se_golomb(&pb, i - COUNT / 2);
+    flush_put_bits(&pb);
+
+    init_get_bits(&gb, temp, 8 * SIZE);
+    for (i = 0; i < COUNT; i++) {
+        int j, s = show_bits(&gb, 25);
+
+        j = get_se_golomb(&gb);
+        if (j != i - COUNT / 2) {
+            fprintf(stderr, "get_se_golomb: expected %d, got %d. bits: %7x\n",
+                    i - COUNT / 2, j, s);
+            ret = 1;
+        }
+    }
+
+    av_free(temp);
+
+    return ret;
+}
diff --git a/libavcodec/tests/iirfilter.c b/libavcodec/tests/iirfilter.c
new file mode 100644
index 0000000..60cc6fc
--- /dev/null
+++ b/libavcodec/tests/iirfilter.c
@@ -0,0 +1,54 @@
+/*
+ * 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 <math.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "libavutil/libm.h"
+
+#include "libavcodec/iirfilter.h"
+
+#define FILT_ORDER 4
+#define SIZE 1024
+
+int main(void)
+{
+    struct FFIIRFilterCoeffs *fcoeffs = NULL;
+    struct FFIIRFilterState  *fstate  = NULL;
+    float cutoff_coeff = 0.4;
+    int16_t x[SIZE], y[SIZE];
+    int i;
+
+    fcoeffs = ff_iir_filter_init_coeffs(NULL, FF_FILTER_TYPE_BUTTERWORTH,
+                                        FF_FILTER_MODE_LOWPASS, FILT_ORDER,
+                                        cutoff_coeff, 0.0, 0.0);
+    fstate  = ff_iir_filter_init_state(FILT_ORDER);
+
+    for (i = 0; i < SIZE; i++)
+        x[i] = lrint(0.75 * INT16_MAX * sin(0.5 * M_PI * i * i / SIZE));
+
+    ff_iir_filter(fcoeffs, fstate, SIZE, x, 1, y, 1);
+
+    for (i = 0; i < SIZE; i++)
+        printf("%6d %6d\n", x[i], y[i]);
+
+    ff_iir_filter_free_coeffsp(&fcoeffs);
+    ff_iir_filter_free_statep(&fstate);
+    return 0;
+}
diff --git a/libavcodec/tests/imgconvert.c b/libavcodec/tests/imgconvert.c
new file mode 100644
index 0000000..c598d46
--- /dev/null
+++ b/libavcodec/tests/imgconvert.c
@@ -0,0 +1,50 @@
+/*
+ * Misc image conversion routines
+ * Copyright (c) 2001, 2002, 2003 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/imgconvert.c"
+
+#if FF_API_AVPICTURE
+FF_DISABLE_DEPRECATION_WARNINGS
+int main(void){
+    int i;
+    int err=0;
+    int skip = 0;
+
+    for (i=0; i<AV_PIX_FMT_NB*2; i++) {
+        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i);
+        if(!desc || !desc->name) {
+            skip ++;
+            continue;
+        }
+        if (skip) {
+            av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip);
+            skip = 0;
+        }
+        av_log(NULL, AV_LOG_INFO, "pix fmt %s yuv_plan:%d avg_bpp:%d\n", desc->name, is_yuv_planar(desc), av_get_padded_bits_per_pixel(desc));
+        if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) {
+            av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n");
+            err = 1;
+        }
+    }
+    return err;
+}
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif /* FF_API_AVPICTURE */
diff --git a/libavcodec/tests/jpeg2000dwt.c b/libavcodec/tests/jpeg2000dwt.c
new file mode 100644
index 0000000..80b33be
--- /dev/null
+++ b/libavcodec/tests/jpeg2000dwt.c
@@ -0,0 +1,141 @@
+/*
+ * Discrete wavelet transform
+ * Copyright (c) 2007 Kamil Nowosad
+ * Copyright (c) 2013 Nicolas Bertrand <nicoinattendu at gmail.com>
+ *
+ * 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 "libavcodec/jpeg2000dwt.c"
+
+#include "libavutil/lfg.h"
+
+#define MAX_W 256
+
+static int test_dwt(int *array, int *ref, int border[2][2], int decomp_levels, int type, int max_diff) {
+    int ret, j;
+    DWTContext s1={{{0}}}, *s= &s1;
+    int64_t err2 = 0;
+
+    ret = ff_jpeg2000_dwt_init(s,  border, decomp_levels, type);
+    if (ret < 0) {
+        fprintf(stderr, "ff_jpeg2000_dwt_init failed\n");
+        return 1;
+    }
+    ret = ff_dwt_encode(s, array);
+    if (ret < 0) {
+        fprintf(stderr, "ff_dwt_encode failed\n");
+        return 1;
+    }
+    ret = ff_dwt_decode(s, array);
+    if (ret < 0) {
+        fprintf(stderr, "ff_dwt_encode failed\n");
+        return 1;
+    }
+    for (j = 0; j<MAX_W * MAX_W; j++) {
+        if (FFABS(array[j] - ref[j]) > max_diff) {
+            fprintf(stderr, "missmatch at %d (%d != %d) decomp:%d border %d %d %d %d\n",
+                    j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]);
+            return 2;
+        }
+        err2 += (array[j] - ref[j]) * (array[j] - ref[j]);
+        array[j] = ref[j];
+    }
+    ff_dwt_destroy(s);
+
+    printf("%s, decomp:%2d border %3d %3d %3d %3d milli-err2:%9"PRId64"\n",
+           type == FF_DWT53 ? "5/3i" : "9/7i",
+           decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1],
+           1000*err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0])));
+
+    return 0;
+}
+
+static int test_dwtf(float *array, float *ref, int border[2][2], int decomp_levels, float max_diff) {
+    int ret, j;
+    DWTContext s1={{{0}}}, *s= &s1;
+    double err2 = 0;
+
+    ret = ff_jpeg2000_dwt_init(s,  border, decomp_levels, FF_DWT97);
+    if (ret < 0) {
+        fprintf(stderr, "ff_jpeg2000_dwt_init failed\n");
+        return 1;
+    }
+    ret = ff_dwt_encode(s, array);
+    if (ret < 0) {
+        fprintf(stderr, "ff_dwt_encode failed\n");
+        return 1;
+    }
+    ret = ff_dwt_decode(s, array);
+    if (ret < 0) {
+        fprintf(stderr, "ff_dwt_encode failed\n");
+        return 1;
+    }
+    for (j = 0; j<MAX_W * MAX_W; j++) {
+        if (FFABS(array[j] - ref[j]) > max_diff) {
+            fprintf(stderr, "missmatch at %d (%f != %f) decomp:%d border %d %d %d %d\n",
+                    j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]);
+            return 2;
+        }
+        err2 += (array[j] - ref[j]) * (array[j] - ref[j]);
+        array[j] = ref[j];
+    }
+    ff_dwt_destroy(s);
+
+    printf("9/7f, decomp:%2d border %3d %3d %3d %3d err2:%20.3f\n",
+           decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1],
+           err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0])));
+
+    return 0;
+}
+
+static int array[MAX_W * MAX_W];
+static int ref  [MAX_W * MAX_W];
+static float arrayf[MAX_W * MAX_W];
+static float reff  [MAX_W * MAX_W];
+
+int main(void) {
+    AVLFG prng;
+    int i,j;
+    int border[2][2];
+    int ret, decomp_levels;
+
+    av_lfg_init(&prng, 1);
+
+    for (i = 0; i<MAX_W * MAX_W; i++)
+        arrayf[i] = reff[i] = array[i] = ref[i] =  av_lfg_get(&prng) % 2048;
+
+    for (i = 0; i < 100; i++) {
+        for (j=0; j<4; j++)
+            border[j>>1][j&1] = av_lfg_get(&prng) % MAX_W;
+        if (border[0][0] >= border[0][1] || border[1][0] >= border[1][1])
+            continue;
+        decomp_levels = av_lfg_get(&prng) % FF_DWT_MAX_DECLVLS;
+
+        ret = test_dwt(array, ref, border, decomp_levels, FF_DWT53, 0);
+        if (ret)
+            return ret;
+        ret = test_dwt(array, ref, border, decomp_levels, FF_DWT97_INT, FFMIN(7+5*decomp_levels, 15+3*decomp_levels));
+        if (ret)
+            return ret;
+        ret = test_dwtf(arrayf, reff, border, decomp_levels, 0.05);
+        if (ret)
+            return ret;
+    }
+
+    return 0;
+}
diff --git a/libavcodec/tests/mathops.c b/libavcodec/tests/mathops.c
new file mode 100644
index 0000000..33a059c
--- /dev/null
+++ b/libavcodec/tests/mathops.c
@@ -0,0 +1,41 @@
+/*
+ * 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 "libavcodec/mathops.h"
+
+#include <stdlib.h>
+
+int main(void)
+{
+    unsigned u;
+
+    for(u=0; u<65536; u++) {
+        unsigned s = u*u;
+        unsigned root = ff_sqrt(s);
+        unsigned root_m1 = ff_sqrt(s-1);
+        if (s && root != u) {
+            fprintf(stderr, "ff_sqrt failed at %u with %u\n", s, root);
+            return 1;
+        }
+        if (u && root_m1 != u - 1) {
+            fprintf(stderr, "ff_sqrt failed at %u with %u\n", s, root);
+            return 1;
+        }
+    }
+    return 0;
+}
diff --git a/libavcodec/tests/motion.c b/libavcodec/tests/motion.c
new file mode 100644
index 0000000..d89f940
--- /dev/null
+++ b/libavcodec/tests/motion.c
@@ -0,0 +1,152 @@
+/*
+ * (c) 2001 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * motion test.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+#include "libavcodec/me_cmp.h"
+#include "libavutil/internal.h"
+#include "libavutil/lfg.h"
+#include "libavutil/mem.h"
+#include "libavutil/time.h"
+
+#undef printf
+
+#define WIDTH 64
+#define HEIGHT 64
+
+static uint8_t img1[WIDTH * HEIGHT];
+static uint8_t img2[WIDTH * HEIGHT];
+
+static void fill_random(uint8_t *tab, int size)
+{
+    int i;
+    AVLFG prng;
+
+    av_lfg_init(&prng, 1);
+    for(i=0;i<size;i++) {
+        tab[i] = av_lfg_get(&prng) % 256;
+    }
+}
+
+static void help(void)
+{
+    printf("motion-test [-h]\n"
+           "test motion implementations\n");
+}
+
+#define NB_ITS 500
+
+int dummy;
+
+static void test_motion(const char *name,
+                 me_cmp_func test_func, me_cmp_func ref_func)
+{
+    int x, y, d1, d2, it;
+    uint8_t *ptr;
+    int64_t ti;
+    printf("testing '%s'\n", name);
+
+    /* test correctness */
+    for(it=0;it<20;it++) {
+
+        fill_random(img1, WIDTH * HEIGHT);
+        fill_random(img2, WIDTH * HEIGHT);
+
+        for(y=0;y<HEIGHT-17;y++) {
+            for(x=0;x<WIDTH-17;x++) {
+                ptr = img2 + y * WIDTH + x;
+                d1 = test_func(NULL, img1, ptr, WIDTH, 8);
+                d2 = ref_func(NULL, img1, ptr, WIDTH, 8);
+                if (d1 != d2) {
+                    printf("error: mmx=%d c=%d\n", d1, d2);
+                }
+            }
+        }
+    }
+    emms_c();
+
+    /* speed test */
+    ti = av_gettime_relative();
+    d1 = 0;
+    for(it=0;it<NB_ITS;it++) {
+        for(y=0;y<HEIGHT-17;y++) {
+            for(x=0;x<WIDTH-17;x++) {
+                ptr = img2 + y * WIDTH + x;
+                d1 += test_func(NULL, img1, ptr, WIDTH, 8);
+            }
+        }
+    }
+    emms_c();
+    dummy = d1; /* avoid optimization */
+    ti = av_gettime_relative() - ti;
+
+    printf("  %0.0f kop/s\n",
+           (double)NB_ITS * (WIDTH - 16) * (HEIGHT - 16) /
+           (double)(ti / 1000.0));
+}
+
+
+int main(int argc, char **argv)
+{
+    AVCodecContext *ctx;
+    int c;
+    MECmpContext cctx, mmxctx;
+    int flags[2] = { AV_CPU_FLAG_MMX, AV_CPU_FLAG_MMXEXT };
+    int flags_size = HAVE_MMXEXT ? 2 : 1;
+
+    if (argc > 1) {
+        help();
+        return 1;
+    }
+
+    printf("ffmpeg motion test\n");
+
+    ctx = avcodec_alloc_context3(NULL);
+    ctx->flags |= AV_CODEC_FLAG_BITEXACT;
+    av_force_cpu_flags(0);
+    memset(&cctx, 0, sizeof(cctx));
+    ff_me_cmp_init(&cctx, ctx);
+    for (c = 0; c < flags_size; c++) {
+        int x;
+        av_force_cpu_flags(flags[c]);
+        memset(&mmxctx, 0, sizeof(mmxctx));
+        ff_me_cmp_init(&mmxctx, ctx);
+
+        for (x = 0; x < 2; x++) {
+            printf("%s for %dx%d pixels\n", c ? "mmx2" : "mmx",
+                   x ? 8 : 16, x ? 8 : 16);
+            test_motion("mmx",     mmxctx.pix_abs[x][0], cctx.pix_abs[x][0]);
+            test_motion("mmx_x2",  mmxctx.pix_abs[x][1], cctx.pix_abs[x][1]);
+            test_motion("mmx_y2",  mmxctx.pix_abs[x][2], cctx.pix_abs[x][2]);
+            test_motion("mmx_xy2", mmxctx.pix_abs[x][3], cctx.pix_abs[x][3]);
+        }
+    }
+    av_free(ctx);
+
+    return 0;
+}
diff --git a/libavcodec/tests/options.c b/libavcodec/tests/options.c
new file mode 100644
index 0000000..2e19a6e
--- /dev/null
+++ b/libavcodec/tests/options.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2001 Fabrice Bellard
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/options.c"
+
+static int dummy_init(AVCodecContext *ctx)
+{
+    //TODO: this code should set every possible pointer that could be set by codec and is not an option;
+    ctx->extradata_size = 8;
+    ctx->extradata = av_malloc(ctx->extradata_size);
+    return 0;
+}
+
+static int dummy_close(AVCodecContext *ctx)
+{
+    av_freep(&ctx->extradata);
+    ctx->extradata_size = 0;
+    return 0;
+}
+
+static int dummy_encode(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
+{
+    return AVERROR(ENOSYS);
+}
+
+typedef struct Dummy12Context {
+    AVClass  *av_class;
+    int      num;
+    char*    str;
+} Dummy12Context;
+
+typedef struct Dummy3Context {
+    void     *fake_av_class;
+    int      num;
+    char*    str;
+} Dummy3Context;
+
+#define OFFSET(x) offsetof(Dummy12Context, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption dummy_options[] = {
+    { "str", "set str", OFFSET(str), AV_OPT_TYPE_STRING, { .str = "i'm src default value" }, 0, 0, VE},
+    { "num", "set num", OFFSET(num), AV_OPT_TYPE_INT,    { .i64 = 1500100900 },    0, INT_MAX, VE},
+    { NULL },
+};
+
+static const AVClass dummy_v1_class = {
+    .class_name = "dummy_v1_class",
+    .item_name  = av_default_item_name,
+    .option     = dummy_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static const AVClass dummy_v2_class = {
+    .class_name = "dummy_v2_class",
+    .item_name  = av_default_item_name,
+    .option     = dummy_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+/* codec with options */
+static AVCodec dummy_v1_encoder = {
+    .name             = "dummy_v1_codec",
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_NONE - 1,
+    .encode2          = dummy_encode,
+    .init             = dummy_init,
+    .close            = dummy_close,
+    .priv_class       = &dummy_v1_class,
+    .priv_data_size   = sizeof(Dummy12Context),
+};
+
+/* codec with options, different class */
+static AVCodec dummy_v2_encoder = {
+    .name             = "dummy_v2_codec",
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_NONE - 2,
+    .encode2          = dummy_encode,
+    .init             = dummy_init,
+    .close            = dummy_close,
+    .priv_class       = &dummy_v2_class,
+    .priv_data_size   = sizeof(Dummy12Context),
+};
+
+/* codec with priv data, but no class */
+static AVCodec dummy_v3_encoder = {
+    .name             = "dummy_v3_codec",
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_NONE - 3,
+    .encode2          = dummy_encode,
+    .init             = dummy_init,
+    .close            = dummy_close,
+    .priv_data_size   = sizeof(Dummy3Context),
+};
+
+/* codec without priv data */
+static AVCodec dummy_v4_encoder = {
+    .name             = "dummy_v4_codec",
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_NONE - 4,
+    .encode2          = dummy_encode,
+    .init             = dummy_init,
+    .close            = dummy_close,
+};
+
+static void test_copy_print_codec(const AVCodecContext *ctx)
+{
+    printf("%-14s: %dx%d prv: %s",
+           ctx->codec ? ctx->codec->name : "NULL",
+           ctx->width, ctx->height,
+           ctx->priv_data ? "set" : "null");
+    if (ctx->codec && ctx->codec->priv_class && ctx->codec->priv_data_size) {
+        int64_t i64;
+        char *str = NULL;
+        av_opt_get_int(ctx->priv_data, "num", 0, &i64);
+        av_opt_get(ctx->priv_data, "str", 0, (uint8_t**)&str);
+        printf(" opts: %"PRId64" %s", i64, str);
+        av_free(str);
+    }
+    printf("\n");
+}
+
+static void test_copy(const AVCodec *c1, const AVCodec *c2)
+{
+    AVCodecContext *ctx1, *ctx2;
+    printf("%s -> %s\nclosed:\n", c1 ? c1->name : "NULL", c2 ? c2->name : "NULL");
+    ctx1 = avcodec_alloc_context3(c1);
+    ctx2 = avcodec_alloc_context3(c2);
+    ctx1->width = ctx1->height = 128;
+    ctx1->time_base = (AVRational){12,34};
+    if (ctx2->codec && ctx2->codec->priv_class && ctx2->codec->priv_data_size) {
+        av_opt_set(ctx2->priv_data, "num", "667", 0);
+        av_opt_set(ctx2->priv_data, "str", "i'm dest value before copy", 0);
+    }
+    avcodec_copy_context(ctx2, ctx1);
+    test_copy_print_codec(ctx1);
+    test_copy_print_codec(ctx2);
+    if (ctx1->codec) {
+        int ret;
+        printf("opened:\n");
+        ret = avcodec_open2(ctx1, ctx1->codec, NULL);
+        if (ret < 0) {
+            fprintf(stderr, "avcodec_open2 failed\n");
+            exit(1);
+        }
+        if (ctx2->codec && ctx2->codec->priv_class && ctx2->codec->priv_data_size) {
+            av_opt_set(ctx2->priv_data, "num", "667", 0);
+            av_opt_set(ctx2->priv_data, "str", "i'm dest value before copy", 0);
+        }
+        avcodec_copy_context(ctx2, ctx1);
+        test_copy_print_codec(ctx1);
+        test_copy_print_codec(ctx2);
+        avcodec_close(ctx1);
+    }
+    avcodec_free_context(&ctx1);
+    avcodec_free_context(&ctx2);
+}
+
+int main(void)
+{
+    AVCodec *dummy_codec[] = {
+        &dummy_v1_encoder,
+        &dummy_v2_encoder,
+        &dummy_v3_encoder,
+        &dummy_v4_encoder,
+        NULL,
+    };
+    int i, j;
+
+    for (i = 0; dummy_codec[i]; i++)
+        avcodec_register(dummy_codec[i]);
+
+    printf("testing avcodec_copy_context()\n");
+    for (i = 0; i < FF_ARRAY_ELEMS(dummy_codec); i++)
+        for (j = 0; j < FF_ARRAY_ELEMS(dummy_codec); j++)
+            test_copy(dummy_codec[i], dummy_codec[j]);
+    return 0;
+}
diff --git a/libavcodec/tests/ppc/dct.c b/libavcodec/tests/ppc/dct.c
new file mode 100644
index 0000000..d95db52
--- /dev/null
+++ b/libavcodec/tests/ppc/dct.c
@@ -0,0 +1,32 @@
+/*
+ * 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 "config.h"
+
+#include "libavcodec/ppc/fdct.h"
+
+static const struct algo fdct_tab_arch[] = {
+#if HAVE_ALTIVEC
+    { "altivecfdct", ff_fdct_altivec, FF_IDCT_PERM_NONE, AV_CPU_FLAG_ALTIVEC },
+#endif
+    { 0 }
+};
+
+static const struct algo idct_tab_arch[] = {
+    { 0 }
+};
diff --git a/libavcodec/tests/rangecoder.c b/libavcodec/tests/rangecoder.c
new file mode 100644
index 0000000..2da5c0c
--- /dev/null
+++ b/libavcodec/tests/rangecoder.c
@@ -0,0 +1,64 @@
+/*
+ * 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 <stdint.h>
+#include <string.h>
+
+#include "libavutil/lfg.h"
+#include "libavutil/log.h"
+
+#include "libavcodec/rangecoder.h"
+
+#define SIZE 10240
+
+int main(void)
+{
+    RangeCoder c;
+    uint8_t b[9 * SIZE];
+    uint8_t r[9 * SIZE];
+    int i;
+    uint8_t state[10];
+    AVLFG prng;
+
+    av_lfg_init(&prng, 1);
+
+    ff_init_range_encoder(&c, b, SIZE);
+    ff_build_rac_states(&c, (1LL << 32) / 20, 128 + 64 + 32 + 16);
+
+    memset(state, 128, sizeof(state));
+
+    for (i = 0; i < SIZE; i++)
+        r[i] = av_lfg_get(&prng) % 7;
+
+    for (i = 0; i < SIZE; i++)
+        put_rac(&c, state, r[i] & 1);
+
+    ff_rac_terminate(&c);
+
+    ff_init_range_decoder(&c, b, SIZE);
+
+    memset(state, 128, sizeof(state));
+
+    for (i = 0; i < SIZE; i++)
+        if ((r[i] & 1) != get_rac(&c, state)) {
+            av_log(NULL, AV_LOG_ERROR, "rac failure at %d\n", i);
+            return 1;
+        }
+
+    return 0;
+}
diff --git a/libavcodec/tests/snowenc.c b/libavcodec/tests/snowenc.c
new file mode 100644
index 0000000..d5f94e8
--- /dev/null
+++ b/libavcodec/tests/snowenc.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2004 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavcodec/snowenc.c"
+
+#undef malloc
+#undef free
+#undef printf
+
+#include "libavutil/lfg.h"
+#include "libavutil/mathematics.h"
+
+int main(void){
+#define width  256
+#define height 256
+    int buffer[2][width*height];
+    SnowContext s;
+    int i;
+    AVLFG prng;
+    s.spatial_decomposition_count=6;
+    s.spatial_decomposition_type=1;
+
+    s.temp_dwt_buffer  = av_mallocz_array(width, sizeof(DWTELEM));
+    s.temp_idwt_buffer = av_mallocz_array(width, sizeof(IDWTELEM));
+
+    if (!s.temp_dwt_buffer || !s.temp_idwt_buffer) {
+        fprintf(stderr, "Failed to allocate memory\n");
+        return 1;
+    }
+
+    av_lfg_init(&prng, 1);
+
+    printf("testing 5/3 DWT\n");
+    for(i=0; i<width*height; i++)
+        buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
+
+    ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+    ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+
+    for(i=0; i<width*height; i++)
+        if(buffer[0][i]!= buffer[1][i]) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
+
+    printf("testing 9/7 DWT\n");
+    s.spatial_decomposition_type=0;
+    for(i=0; i<width*height; i++)
+        buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
+
+    ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+    ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+
+    for(i=0; i<width*height; i++)
+        if(FFABS(buffer[0][i] - buffer[1][i])>20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
+
+    {
+    int level, orientation, x, y;
+    int64_t errors[8][4];
+    int64_t g=0;
+
+        memset(errors, 0, sizeof(errors));
+        s.spatial_decomposition_count=3;
+        s.spatial_decomposition_type=0;
+        for(level=0; level<s.spatial_decomposition_count; level++){
+            for(orientation=level ? 1 : 0; orientation<4; orientation++){
+                int w= width  >> (s.spatial_decomposition_count-level);
+                int h= height >> (s.spatial_decomposition_count-level);
+                int stride= width  << (s.spatial_decomposition_count-level);
+                DWTELEM *buf= buffer[0];
+                int64_t error=0;
+
+                if(orientation&1) buf+=w;
+                if(orientation>1) buf+=stride>>1;
+
+                memset(buffer[0], 0, sizeof(int)*width*height);
+                buf[w/2 + h/2*stride]= 256*256;
+                ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+                for(y=0; y<height; y++){
+                    for(x=0; x<width; x++){
+                        int64_t d= buffer[0][x + y*width];
+                        error += d*d;
+                        if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9 && level==2) printf("%8"PRId64" ", d);
+                    }
+                    if(FFABS(height/2-y)<9 && level==2) printf("\n");
+                }
+                error= (int)(sqrt(error)+0.5);
+                errors[level][orientation]= error;
+                if(g) g=av_gcd(g, error);
+                else g= error;
+            }
+        }
+        printf("static int const visual_weight[][4]={\n");
+        for(level=0; level<s.spatial_decomposition_count; level++){
+            printf("  {");
+            for(orientation=0; orientation<4; orientation++){
+                printf("%8"PRId64",", errors[level][orientation]/g);
+            }
+            printf("},\n");
+        }
+        printf("};\n");
+        {
+            int level=2;
+            int w= width  >> (s.spatial_decomposition_count-level);
+            //int h= height >> (s.spatial_decomposition_count-level);
+            int stride= width  << (s.spatial_decomposition_count-level);
+            DWTELEM *buf= buffer[0];
+            int64_t error=0;
+
+            buf+=w;
+            buf+=stride>>1;
+
+            memset(buffer[0], 0, sizeof(int)*width*height);
+            for(y=0; y<height; y++){
+                for(x=0; x<width; x++){
+                    int tab[4]={0,2,3,1};
+                    buffer[0][x+width*y]= 256*256*tab[(x&1) + 2*(y&1)];
+                }
+            }
+            ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
+            for(y=0; y<height; y++){
+                for(x=0; x<width; x++){
+                    int64_t d= buffer[0][x + y*width];
+                    error += d*d;
+                    if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9) printf("%8"PRId64" ", d);
+                }
+                if(FFABS(height/2-y)<9) printf("\n");
+            }
+        }
+
+    }
+    return 0;
+}
diff --git a/libavcodec/tests/utils.c b/libavcodec/tests/utils.c
new file mode 100644
index 0000000..e2891fb
--- /dev/null
+++ b/libavcodec/tests/utils.c
@@ -0,0 +1,37 @@
+/*
+ * 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 "libavcodec/avcodec.h"
+
+int main(void){
+    AVCodec *codec = NULL;
+    int ret = 0;
+    avcodec_register_all();
+
+    while (codec = av_codec_next(codec)) {
+        if (av_codec_is_encoder(codec)) {
+            if (codec->type == AVMEDIA_TYPE_AUDIO) {
+                if (!codec->sample_fmts) {
+                    av_log(NULL, AV_LOG_FATAL, "Encoder %s is missing the sample_fmts field\n", codec->name);
+                    ret = 1;
+                }
+            }
+        }
+    }
+    return ret;
+}
diff --git a/libavcodec/tests/x86/dct.c b/libavcodec/tests/x86/dct.c
new file mode 100644
index 0000000..b6cdfb3
--- /dev/null
+++ b/libavcodec/tests/x86/dct.c
@@ -0,0 +1,133 @@
+/*
+ * 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 "config.h"
+
+#include "libavcodec/x86/fdct.h"
+#include "libavcodec/x86/xvididct.h"
+#include "libavcodec/x86/simple_idct.h"
+
+#if (CONFIG_PRORES_DECODER || CONFIG_PRORES_LGPL_DECODER) && ARCH_X86_64 && HAVE_YASM
+void ff_prores_idct_put_10_sse2(uint16_t *dst, int linesize,
+                                int16_t *block, int16_t *qmat);
+
+#define PR_WRAP(INSN) \
+static void ff_prores_idct_put_10_##INSN##_wrap(int16_t *dst){ \
+    LOCAL_ALIGNED(16, int16_t, qmat, [64]); \
+    LOCAL_ALIGNED(16, int16_t, tmp, [64]); \
+    int i; \
+ \
+    for(i=0; i<64; i++){ \
+        qmat[i]=4; \
+        tmp[i]= dst[i]; \
+    } \
+    ff_prores_idct_put_10_##INSN (dst, 16, tmp, qmat); \
+ \
+    for(i=0; i<64; i++) { \
+         dst[i] -= 512; \
+    } \
+}
+
+PR_WRAP(sse2)
+
+# if HAVE_AVX_EXTERNAL
+void ff_prores_idct_put_10_avx(uint16_t *dst, int linesize,
+                               int16_t *block, int16_t *qmat);
+PR_WRAP(avx)
+# endif
+
+#endif
+
+static const struct algo fdct_tab_arch[] = {
+#if HAVE_MMX_INLINE
+    { "MMX",    ff_fdct_mmx,    FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMX },
+#endif
+#if HAVE_MMXEXT_INLINE
+    { "MMXEXT", ff_fdct_mmxext, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMXEXT },
+#endif
+#if HAVE_SSE2_INLINE
+    { "SSE2",   ff_fdct_sse2,   FF_IDCT_PERM_NONE, AV_CPU_FLAG_SSE2 },
+#endif
+    { 0 }
+};
+
+static const struct algo idct_tab_arch[] = {
+#if HAVE_MMX_INLINE
+    { "SIMPLE-MMX",  ff_simple_idct_mmx,  FF_IDCT_PERM_SIMPLE, AV_CPU_FLAG_MMX },
+#endif
+#if CONFIG_MPEG4_DECODER && HAVE_YASM
+#if ARCH_X86_32
+    { "XVID-MMX",    ff_xvid_idct_mmx,    FF_IDCT_PERM_NONE,   AV_CPU_FLAG_MMX,    1 },
+    { "XVID-MMXEXT", ff_xvid_idct_mmxext, FF_IDCT_PERM_NONE,   AV_CPU_FLAG_MMXEXT, 1 },
+#endif
+#if HAVE_SSE2_EXTERNAL
+    { "XVID-SSE2",   ff_xvid_idct_sse2,   FF_IDCT_PERM_SSE2,   AV_CPU_FLAG_SSE2,   1 },
+#endif
+#endif /* CONFIG_MPEG4_DECODER && HAVE_YASM */
+#if (CONFIG_PRORES_DECODER || CONFIG_PRORES_LGPL_DECODER) && ARCH_X86_64 && HAVE_YASM
+    { "PR-SSE2",     ff_prores_idct_put_10_sse2_wrap, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2, 1 },
+# if HAVE_AVX_EXTERNAL
+    { "PR-AVX",      ff_prores_idct_put_10_avx_wrap, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_AVX, 1 },
+# endif
+#endif
+#if HAVE_YASM
+#if ARCH_X86_64
+#if HAVE_SSE2_EXTERNAL
+    { "SIMPLE10-SSE2",  ff_simple_idct10_sse2, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2},
+    { "SIMPLE12-SSE2",  ff_simple_idct12_sse2, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2, 1 },
+#endif
+#if HAVE_AVX_EXTERNAL
+    { "SIMPLE10-AVX",   ff_simple_idct10_avx,  FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_AVX},
+    { "SIMPLE12-AVX",   ff_simple_idct12_avx,  FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_AVX,  1 },
+#endif
+#endif
+#endif
+    { 0 }
+};
+
+static const uint8_t idct_simple_mmx_perm[64] = {
+    0x00, 0x08, 0x04, 0x09, 0x01, 0x0C, 0x05, 0x0D,
+    0x10, 0x18, 0x14, 0x19, 0x11, 0x1C, 0x15, 0x1D,
+    0x20, 0x28, 0x24, 0x29, 0x21, 0x2C, 0x25, 0x2D,
+    0x12, 0x1A, 0x16, 0x1B, 0x13, 0x1E, 0x17, 0x1F,
+    0x02, 0x0A, 0x06, 0x0B, 0x03, 0x0E, 0x07, 0x0F,
+    0x30, 0x38, 0x34, 0x39, 0x31, 0x3C, 0x35, 0x3D,
+    0x22, 0x2A, 0x26, 0x2B, 0x23, 0x2E, 0x27, 0x2F,
+    0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F,
+};
+
+static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 };
+
+static int permute_x86(int16_t dst[64], const int16_t src[64],
+                       enum idct_permutation_type perm_type)
+{
+    int i;
+
+    switch (perm_type) {
+    case FF_IDCT_PERM_SIMPLE:
+        for (i = 0; i < 64; i++)
+            dst[idct_simple_mmx_perm[i]] = src[i];
+        return 1;
+    case FF_IDCT_PERM_SSE2:
+        for (i = 0; i < 64; i++)
+            dst[(i & 0x38) | idct_sse2_row_perm[i & 7]] = src[i];
+        return 1;
+    }
+
+    return 0;
+}
diff --git a/libavcodec/textdec.c b/libavcodec/textdec.c
index a6c8722..964da72 100644
--- a/libavcodec/textdec.c
+++ b/libavcodec/textdec.c
@@ -32,6 +32,7 @@ typedef struct {
     AVClass *class;
     const char *linebreaks;
     int keep_ass_markup;
+    int readorder;
 } TextContext;
 
 #define OFFSET(x) offsetof(TextContext, x)
@@ -48,15 +49,12 @@ static int text_decode_frame(AVCodecContext *avctx, void *data,
     AVBPrint buf;
     AVSubtitle *sub = data;
     const char *ptr = avpkt->data;
-    const TextContext *text = avctx->priv_data;
-    const int ts_start     = av_rescale_q(avpkt->pts,      avctx->time_base, (AVRational){1,100});
-    const int ts_duration  = avpkt->duration != -1 ?
-                             av_rescale_q(avpkt->duration, avctx->time_base, (AVRational){1,100}) : -1;
+    TextContext *text = avctx->priv_data;
 
     av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
     if (ptr && avpkt->size > 0 && *ptr) {
         ff_ass_bprint_text_event(&buf, ptr, avpkt->size, text->linebreaks, text->keep_ass_markup);
-        ret = ff_ass_add_rect_bprint(sub, &buf, ts_start, ts_duration);
+        ret = ff_ass_add_rect(sub, buf.str, text->readorder++, 0, NULL, NULL);
     }
     av_bprint_finalize(&buf, NULL);
     if (ret < 0)
@@ -65,6 +63,13 @@ static int text_decode_frame(AVCodecContext *avctx, void *data,
     return avpkt->size;
 }
 
+static void text_flush(AVCodecContext *avctx)
+{
+    TextContext *text = avctx->priv_data;
+    if (!(avctx->flags2 & AV_CODEC_FLAG2_RO_FLUSH_NOOP))
+        text->readorder = 0;
+}
+
 #define DECLARE_CLASS(decname) static const AVClass decname ## _decoder_class = {   \
     .class_name = #decname " decoder",      \
     .item_name  = av_default_item_name,     \
@@ -85,6 +90,7 @@ AVCodec ff_text_decoder = {
     .decode         = text_decode_frame,
     .init           = ff_ass_subtitle_header_default,
     .priv_class     = &text_decoder_class,
+    .flush          = text_flush,
 };
 #endif
 
@@ -110,6 +116,7 @@ AVCodec ff_vplayer_decoder = {
     .decode         = text_decode_frame,
     .init           = linebreak_init,
     .priv_class     = &vplayer_decoder_class,
+    .flush          = text_flush,
 };
 #endif
 
@@ -126,6 +133,7 @@ AVCodec ff_stl_decoder = {
     .decode         = text_decode_frame,
     .init           = linebreak_init,
     .priv_class     = &stl_decoder_class,
+    .flush          = text_flush,
 };
 #endif
 
@@ -142,6 +150,7 @@ AVCodec ff_pjs_decoder = {
     .decode         = text_decode_frame,
     .init           = linebreak_init,
     .priv_class     = &pjs_decoder_class,
+    .flush          = text_flush,
 };
 #endif
 
@@ -158,6 +167,7 @@ AVCodec ff_subviewer1_decoder = {
     .decode         = text_decode_frame,
     .init           = linebreak_init,
     .priv_class     = &subviewer1_decoder_class,
+    .flush          = text_flush,
 };
 #endif
 
diff --git a/libavcodec/texturedsp.c b/libavcodec/texturedsp.c
index c5e6cc6..5012245 100644
--- a/libavcodec/texturedsp.c
+++ b/libavcodec/texturedsp.c
@@ -167,7 +167,7 @@ static inline void dxt3_block_internal(uint8_t *dst, ptrdiff_t stride,
     }
 }
 
-/** Convert a premultiplied alpha pixel to a straigth alpha pixel. */
+/** Convert a premultiplied alpha pixel to a straight alpha pixel. */
 static av_always_inline void premult2straight(uint8_t *src)
 {
     int r = src[0];
diff --git a/libavcodec/texturedspenc.c b/libavcodec/texturedspenc.c
index 7160396..8b28630 100644
--- a/libavcodec/texturedspenc.c
+++ b/libavcodec/texturedspenc.c
@@ -181,7 +181,7 @@ static unsigned int match_colors(const uint8_t *block, ptrdiff_t stride,
     int x, y, k = 0;
     int c0_point, half_point, c3_point;
     uint8_t color[16];
-    const int indexMap[8] = {
+    static const int indexMap[8] = {
         0 << 30, 2 << 30, 0 << 30, 2 << 30,
         3 << 30, 3 << 30, 1 << 30, 1 << 30,
     };
@@ -213,7 +213,7 @@ static unsigned int match_colors(const uint8_t *block, ptrdiff_t stride,
      * the same inside that subinterval.
      *
      * Relying on this 1d approximation isn't always optimal in terms of
-     * euclidean distance, but it's very close and a lot faster.
+     * Euclidean distance, but it's very close and a lot faster.
      *
      * http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html */
     c0_point   = (stops[1] + stops[3]) >> 1;
@@ -309,7 +309,7 @@ static void optimize_colors(const uint8_t *block, ptrdiff_t stride,
     if (fabs(vfb) > magn)
         magn = fabs(vfb);
 
-    /* if magnitudo is too small, default to luminance */
+    /* if magnitude is too small, default to luminance */
     if (magn < 4.0f) {
         /* JPEG YCbCr luma coefs, scaled by 1000 */
         v_r = 299;
@@ -359,8 +359,8 @@ static int refine_colors(const uint8_t *block, ptrdiff_t stride,
     /* Additional magic to save a lot of multiplies in the accumulating loop.
      * The tables contain precomputed products of weights for least squares
      * system, accumulated inside one 32-bit register */
-    const int w1tab[4] = { 3, 0, 2, 1 };
-    const int prods[4] = { 0x090000, 0x000900, 0x040102, 0x010402 };
+    static const int w1tab[4] = { 3, 0, 2, 1 };
+    static const int prods[4] = { 0x090000, 0x000900, 0x040102, 0x010402 };
 
     /* Check if all pixels have the same index */
     if ((mask ^ (mask << 2)) < 4) {
diff --git a/libavcodec/truemotion2rt.c b/libavcodec/truemotion2rt.c
new file mode 100644
index 0000000..49f2114
--- /dev/null
+++ b/libavcodec/truemotion2rt.c
@@ -0,0 +1,221 @@
+/*
+ * Duck TrueMotion 2.0 Real Time Decoder
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avcodec.h"
+#define BITSTREAM_READER_LE
+#include "get_bits.h"
+#include "internal.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
+
+typedef struct TrueMotion2RTContext {
+    GetBitContext gb;
+    const uint8_t *buf;
+    int size;
+    int delta_size;
+    int hscale;
+} TrueMotion2RTContext;
+
+static av_cold int decode_init(AVCodecContext *avctx)
+{
+    avctx->pix_fmt = AV_PIX_FMT_YUV410P;
+    return 0;
+}
+
+/* Returns the number of bytes consumed from the bytestream. Returns -1 if
+ * there was an error while decoding the header */
+static int truemotion2rt_decode_header(AVCodecContext *avctx)
+{
+    TrueMotion2RTContext *s = avctx->priv_data;
+    uint8_t header_buffer[128] = { 0 };  /* logical maximum size of the header */
+    int i, header_size;
+
+    header_size = ((s->buf[0] >> 5) | (s->buf[0] << 3)) & 0x7f;
+    if (header_size < 10) {
+        av_log(avctx, AV_LOG_ERROR, "invalid header size (%d)\n", header_size);
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (header_size + 1 > s->size) {
+        av_log(avctx, AV_LOG_ERROR, "Input packet too small.\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    /* unscramble the header bytes with a XOR operation */
+    for (i = 1; i < header_size; i++)
+        header_buffer[i - 1] = s->buf[i] ^ s->buf[i + 1];
+
+    s->delta_size = header_buffer[1];
+    s->hscale = 1 + !!header_buffer[3];
+    if (s->delta_size < 2 || s->delta_size > 4)
+        return AVERROR_INVALIDDATA;
+
+    avctx->height = AV_RL16(header_buffer + 5);
+    avctx->width  = AV_RL16(header_buffer + 7);
+
+    return header_size;
+}
+
+static const int16_t delta_tab4[] = {
+    1, -1, 2, -3, 8, -8, 18, -18, 36, -36, 54, -54, 96, -96, 144, -144
+};
+
+static const int16_t delta_tab3[] = {
+    2, -3, 8, -8, 18, -18, 36, -36
+};
+
+static const int16_t delta_tab2[] = {
+    5, -7, 36, -36
+};
+
+static const int16_t *const delta_tabs[] = {
+    delta_tab2, delta_tab3, delta_tab4,
+};
+
+static int decode_frame(AVCodecContext *avctx,
+                        void *data, int *got_frame,
+                        AVPacket *avpkt)
+{
+    TrueMotion2RTContext *s = avctx->priv_data;
+    const uint8_t *buf = avpkt->data;
+    int ret, buf_size = avpkt->size;
+    AVFrame * const p = data;
+    GetBitContext *gb = &s->gb;
+    uint8_t *dst;
+    int x, y, delta_mode;
+
+    s->buf = buf;
+    s->size = buf_size;
+
+    if ((ret = truemotion2rt_decode_header(avctx)) < 0)
+        return ret;
+
+    if ((ret = init_get_bits8(gb, buf + ret, buf_size - ret)) < 0)
+        return ret;
+
+    if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
+        return ret;
+
+    skip_bits(gb, 32);
+    delta_mode = s->delta_size - 2;
+    dst = p->data[0];
+    for (y = 0; y < avctx->height; y++) {
+        int diff = 0;
+        for (x = 0; x < avctx->width; x += s->hscale) {
+            diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
+            dst[x] = av_clip_uint8((y ? dst[x - p->linesize[0]] : 0) + diff);
+        }
+        dst += p->linesize[0];
+    }
+
+    if (s->hscale > 1) {
+        dst = p->data[0];
+        for (y = 0; y < avctx->height; y++) {
+            for (x = 1; x < avctx->width; x += s->hscale) {
+                dst[x] = dst[x - 1];
+            }
+            dst += p->linesize[0];
+        }
+    }
+
+    dst = p->data[0];
+    for (y = 0; y < avctx->height; y++) {
+        for (x = 0; x < avctx->width; x++)
+            dst[x] = av_clip_uint8(dst[x] + (dst[x] - 128) / 3);
+        dst += p->linesize[0];
+    }
+
+    dst = p->data[1];
+    for (y = 0; y < avctx->height >> 2; y++) {
+        int diff = 0;
+        for (x = 0; x < avctx->width >> 2; x += s->hscale) {
+            diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
+            dst[x] = av_clip_uint8((y ? dst[x - p->linesize[1]] : 128) + diff);
+        }
+        dst += p->linesize[1];
+    }
+
+    if (s->hscale > 1) {
+        dst = p->data[1];
+        for (y = 0; y < avctx->height >> 2; y++) {
+            for (x = 1; x < avctx->width >> 2; x += s->hscale) {
+                dst[x] = dst[x - 1];
+            }
+            dst += p->linesize[1];
+        }
+    }
+
+    dst = p->data[1];
+    for (y = 0; y < avctx->height >> 2; y++) {
+        for (x = 0; x < avctx->width >> 2; x++)
+            dst[x] += (dst[x] - 128) / 8;
+        dst += p->linesize[1];
+    }
+
+    dst = p->data[2];
+    for (y = 0; y < avctx->height >> 2; y++) {
+        int diff = 0;
+        for (x = 0; x < avctx->width >> 2; x += s->hscale) {
+            diff  += delta_tabs[delta_mode][get_bits(gb, s->delta_size)];
+            dst[x] = av_clip_uint8((y ? dst[x - p->linesize[2]] : 128) + diff);
+        }
+        dst += p->linesize[2];
+    }
+
+    if (s->hscale > 1) {
+        dst = p->data[2];
+        for (y = 0; y < avctx->height >> 2; y++) {
+            for (x = 1; x < avctx->width >> 2; x += s->hscale) {
+                dst[x] = dst[x - 1];
+            }
+            dst += p->linesize[2];
+        }
+    }
+
+    dst = p->data[2];
+    for (y = 0; y < avctx->height >> 2; y++) {
+        for (x = 0; x < avctx->width >> 2; x++)
+            dst[x] += (dst[x] - 128) / 8;
+        dst += p->linesize[2];
+    }
+
+    p->pict_type = AV_PICTURE_TYPE_I;
+    p->key_frame = 1;
+    *got_frame   = 1;
+
+    return buf_size;
+}
+
+AVCodec ff_truemotion2rt_decoder = {
+    .name           = "truemotion2rt",
+    .long_name      = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_TRUEMOTION2RT,
+    .priv_data_size = sizeof(TrueMotion2RTContext),
+    .init           = decode_init,
+    .decode         = decode_frame,
+    .capabilities   = AV_CODEC_CAP_DR1,
+};
diff --git a/libavcodec/tscc.c b/libavcodec/tscc.c
index 8c5ec68..bd5fe03 100644
--- a/libavcodec/tscc.c
+++ b/libavcodec/tscc.c
@@ -32,7 +32,6 @@
  *  then this coded picture is packed with ZLib
  *
  * Supports: BGR8,BGR555,BGR24 - only BGR8 and BGR555 tested
- *
  */
 
 #include <stdio.h>
diff --git a/libavcodec/tscc2.c b/libavcodec/tscc2.c
index 9bb7ab3..69a6fac 100644
--- a/libavcodec/tscc2.c
+++ b/libavcodec/tscc2.c
@@ -31,6 +31,7 @@
 #include "get_bits.h"
 #include "bytestream.h"
 #include "internal.h"
+#include "mathops.h"
 #include "tscc2data.h"
 
 typedef struct TSCC2Context {
@@ -179,7 +180,7 @@ static int tscc2_decode_mb(TSCC2Context *c, int *q, int vlc_set,
                 if (bpos >= 16)
                     return AVERROR_INVALIDDATA;
                 val = sign_extend(ac >> 4, 8);
-                c->block[tscc2_zigzag[bpos++]] = val;
+                c->block[ff_zigzag_scan[bpos++]] = val;
             }
             tscc2_idct4_put(c->block, q, dst + k * 4, stride);
         }
diff --git a/libavcodec/tscc2data.h b/libavcodec/tscc2data.h
index 7806267..7cd6f52 100644
--- a/libavcodec/tscc2data.h
+++ b/libavcodec/tscc2data.h
@@ -24,13 +24,6 @@
 
 #include <stdint.h>
 
-static const uint8_t tscc2_zigzag[16] = {
-   0,  1,  4,  8,
-   5,  2,  3,  6,
-   9, 12, 13, 10,
-   7, 11, 14, 15
-};
-
 #define NUM_VLC_SETS 13
 
 static const uint16_t tscc2_quants[NUM_VLC_SETS][3] = {
diff --git a/libavcodec/twinvq.h b/libavcodec/twinvq.h
index 228a489..24e5ebc 100644
--- a/libavcodec/twinvq.h
+++ b/libavcodec/twinvq.h
@@ -109,7 +109,7 @@ typedef struct TwinVQFrameData {
  * bitrate/sample rate
  */
 typedef struct TwinVQModeTab {
-    struct TwinVQFrameMode fmode[3]; ///< frame type-dependant parameters
+    struct TwinVQFrameMode fmode[3]; ///< frame type-dependent parameters
 
     uint16_t     size;        ///< frame size in samples
     uint8_t      n_lsp;       ///< number of lsp coefficients
diff --git a/libavcodec/twinvqdec.c b/libavcodec/twinvqdec.c
index 5f4dd35..c2353f5 100644
--- a/libavcodec/twinvqdec.c
+++ b/libavcodec/twinvqdec.c
@@ -149,7 +149,7 @@ static int very_broken_op(int a, int b)
 /**
  * Sum to data a periodic peak of a given period, width and shape.
  *
- * @param period the period of the peak divised by 400.0
+ * @param period the period of the peak divided by 400.0
  */
 static void add_peak(int period, int width, const float *shape,
                      float ppc_gain, float *speech, int len)
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index f532824..f7adb52 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -34,6 +34,7 @@
 #include "libavutil/channel_layout.h"
 #include "libavutil/crc.h"
 #include "libavutil/frame.h"
+#include "libavutil/hwcontext.h"
 #include "libavutil/internal.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/mem_internal.h"
@@ -166,12 +167,12 @@ static av_cold void avcodec_init(void)
 
 int av_codec_is_encoder(const AVCodec *codec)
 {
-    return codec && (codec->encode_sub || codec->encode2);
+    return codec && (codec->encode_sub || codec->encode2 ||codec->send_frame);
 }
 
 int av_codec_is_decoder(const AVCodec *codec)
 {
-    return codec && codec->decode;
+    return codec && (codec->decode || codec->send_packet);
 }
 
 av_cold void avcodec_register(AVCodec *codec)
@@ -351,6 +352,8 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height,
     case AV_PIX_FMT_GBRP14BE:
     case AV_PIX_FMT_GBRP16LE:
     case AV_PIX_FMT_GBRP16BE:
+    case AV_PIX_FMT_GBRAP12LE:
+    case AV_PIX_FMT_GBRAP12BE:
     case AV_PIX_FMT_GBRAP16LE:
     case AV_PIX_FMT_GBRAP16BE:
         w_align = 16; //FIXME assume 16 pixel per macroblock
@@ -653,8 +656,8 @@ static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format);
     int i;
 
-    if (pic->data[0]) {
-        av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n");
+    if (pic->data[0] || pic->data[1] || pic->data[2] || pic->data[3]) {
+        av_log(s, AV_LOG_ERROR, "pic->data[*]!=NULL in avcodec_default_get_buffer\n");
         return -1;
     }
 
@@ -754,10 +757,11 @@ int ff_init_buffer_info(AVCodecContext *avctx, AVFrame *frame)
         enum AVPacketSideDataType packet;
         enum AVFrameSideDataType frame;
     } sd[] = {
-        { AV_PKT_DATA_REPLAYGAIN ,   AV_FRAME_DATA_REPLAYGAIN },
-        { AV_PKT_DATA_DISPLAYMATRIX, AV_FRAME_DATA_DISPLAYMATRIX },
-        { AV_PKT_DATA_STEREO3D,      AV_FRAME_DATA_STEREO3D },
-        { AV_PKT_DATA_AUDIO_SERVICE_TYPE, AV_FRAME_DATA_AUDIO_SERVICE_TYPE },
+        { AV_PKT_DATA_REPLAYGAIN ,                AV_FRAME_DATA_REPLAYGAIN },
+        { AV_PKT_DATA_DISPLAYMATRIX,              AV_FRAME_DATA_DISPLAYMATRIX },
+        { AV_PKT_DATA_STEREO3D,                   AV_FRAME_DATA_STEREO3D },
+        { AV_PKT_DATA_AUDIO_SERVICE_TYPE,         AV_FRAME_DATA_AUDIO_SERVICE_TYPE },
+        { AV_PKT_DATA_MASTERING_DISPLAY_METADATA, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA },
     };
 
     if (pkt) {
@@ -849,6 +853,30 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
     return ff_init_buffer_info(avctx, frame);
 }
 
+static void validate_avframe_allocation(AVCodecContext *avctx, AVFrame *frame)
+{
+    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
+        int i;
+        int num_planes = av_pix_fmt_count_planes(frame->format);
+        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
+        int flags = desc ? desc->flags : 0;
+        if (num_planes == 1 && (flags & AV_PIX_FMT_FLAG_PAL))
+            num_planes = 2;
+        for (i = 0; i < num_planes; i++) {
+            av_assert0(frame->data[i]);
+        }
+        // For now do not enforce anything for palette of pseudopal formats
+        if (num_planes == 1 && (flags & AV_PIX_FMT_FLAG_PSEUDOPAL))
+            num_planes = 2;
+        // For formats without data like hwaccel allow unused pointers to be non-NULL.
+        for (i = num_planes; num_planes > 0 && i < FF_ARRAY_ELEMS(frame->data); i++) {
+            if (frame->data[i])
+                av_log(avctx, AV_LOG_ERROR, "Buffer returned by get_buffer2() did not zero unused plane pointers\n");
+            frame->data[i] = NULL;
+        }
+    }
+}
+
 static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags)
 {
     const AVHWAccel *hwaccel = avctx->hwaccel;
@@ -860,13 +888,17 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags)
             av_log(avctx, AV_LOG_ERROR, "video_get_buffer: image parameters invalid\n");
             return AVERROR(EINVAL);
         }
-    }
-    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
+
         if (frame->width <= 0 || frame->height <= 0) {
             frame->width  = FFMAX(avctx->width,  AV_CEIL_RSHIFT(avctx->coded_width,  avctx->lowres));
             frame->height = FFMAX(avctx->height, AV_CEIL_RSHIFT(avctx->coded_height, avctx->lowres));
             override_dimensions = 0;
         }
+
+        if (frame->data[0] || frame->data[1] || frame->data[2] || frame->data[3]) {
+            av_log(avctx, AV_LOG_ERROR, "pic->data[*]!=NULL in get_buffer_internal\n");
+            return AVERROR(EINVAL);
+        }
     }
     ret = ff_decode_frame_props(avctx, frame);
     if (ret < 0)
@@ -881,6 +913,8 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags)
         avctx->sw_pix_fmt = avctx->pix_fmt;
 
     ret = avctx->get_buffer2(avctx, frame, flags);
+    if (ret >= 0)
+        validate_avframe_allocation(avctx, frame);
 
 end:
     if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions) {
@@ -1126,6 +1160,10 @@ int av_codec_get_max_lowres(const AVCodec *codec)
     return codec->max_lowres;
 }
 
+int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec){
+    return !!(codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM);
+}
+
 static void get_subtitle_defaults(AVSubtitle *sub)
 {
     memset(sub, 0, sizeof(*sub));
@@ -1216,6 +1254,18 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
         goto free_and_end;
     }
 
+    avctx->internal->buffer_frame = av_frame_alloc();
+    if (!avctx->internal->buffer_frame) {
+        ret = AVERROR(ENOMEM);
+        goto free_and_end;
+    }
+
+    avctx->internal->buffer_pkt = av_packet_alloc();
+    if (!avctx->internal->buffer_pkt) {
+        ret = AVERROR(ENOMEM);
+        goto free_and_end;
+    }
+
     if (codec->priv_data_size > 0) {
         if (!avctx->priv_data) {
             avctx->priv_data = av_mallocz(codec->priv_data_size);
@@ -1362,6 +1412,13 @@ FF_DISABLE_DEPRECATION_WARNINGS
         }
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
+
+        if (avctx->time_base.num <= 0 || avctx->time_base.den <= 0) {
+            av_log(avctx, AV_LOG_ERROR, "The encoder timebase is not set.\n");
+            ret = AVERROR(EINVAL);
+            goto free_and_end;
+        }
+
         if (avctx->codec->sample_fmts) {
             for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) {
                 if (avctx->sample_fmt == avctx->codec->sample_fmts[i])
@@ -1487,6 +1544,16 @@ FF_ENABLE_DEPRECATION_WARNINGS
                    avctx->time_base.den);
             goto free_and_end;
         }
+
+        if (avctx->hw_frames_ctx) {
+            AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
+            if (frames_ctx->format != avctx->pix_fmt) {
+                av_log(avctx, AV_LOG_ERROR,
+                       "Mismatching AVCodecContext.pix_fmt and AVHWFramesContext.format\n");
+                ret = AVERROR(EINVAL);
+                goto free_and_end;
+            }
+        }
     }
 
     avctx->pts_correction_num_faulty_pts =
@@ -1610,6 +1677,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
     av_dict_free(&tmp);
     av_freep(&avctx->priv_data);
     if (avctx->internal) {
+        av_packet_free(&avctx->internal->buffer_pkt);
+        av_frame_free(&avctx->internal->buffer_frame);
         av_frame_free(&avctx->internal->to_free);
         av_freep(&avctx->internal->pool);
     }
@@ -1717,6 +1786,11 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx,
 
     *got_packet_ptr = 0;
 
+    if (!avctx->codec->encode2) {
+        av_log(avctx, AV_LOG_ERROR, "This encoder requires using the avcodec_send_frame() API.\n");
+        return AVERROR(ENOSYS);
+    }
+
     if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) && !frame) {
         av_packet_unref(avpkt);
         av_init_packet(avpkt);
@@ -1856,6 +1930,11 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx,
 
     *got_packet_ptr = 0;
 
+    if (!avctx->codec->encode2) {
+        av_log(avctx, AV_LOG_ERROR, "This encoder requires using the avcodec_send_frame() API.\n");
+        return AVERROR(ENOSYS);
+    }
+
     if(CONFIG_FRAME_THREAD_ENCODER &&
        avctx->internal->frame_thread_encoder && (avctx->active_thread_type&FF_THREAD_FRAME))
         return ff_thread_video_encode_frame(avctx, avpkt, frame, got_packet_ptr);
@@ -1988,7 +2067,8 @@ static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
     if (!(avctx->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE)) {
         av_log(avctx, AV_LOG_ERROR, "This decoder does not support parameter "
                "changes, but PARAM_CHANGE side data was sent to it.\n");
-        return AVERROR(EINVAL);
+        ret = AVERROR(EINVAL);
+        goto fail2;
     }
 
     if (size < 4)
@@ -2003,7 +2083,8 @@ static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
         val = bytestream_get_le32(&data);
         if (val <= 0 || val > INT_MAX) {
             av_log(avctx, AV_LOG_ERROR, "Invalid channel count");
-            return AVERROR_INVALIDDATA;
+            ret = AVERROR_INVALIDDATA;
+            goto fail2;
         }
         avctx->channels = val;
         size -= 4;
@@ -2020,7 +2101,8 @@ static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
         val = bytestream_get_le32(&data);
         if (val <= 0 || val > INT_MAX) {
             av_log(avctx, AV_LOG_ERROR, "Invalid sample rate");
-            return AVERROR_INVALIDDATA;
+            ret = AVERROR_INVALIDDATA;
+            goto fail2;
         }
         avctx->sample_rate = val;
         size -= 4;
@@ -2033,13 +2115,20 @@ static int apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
         size -= 8;
         ret = ff_set_dimensions(avctx, avctx->width, avctx->height);
         if (ret < 0)
-            return ret;
+            goto fail2;
     }
 
     return 0;
 fail:
     av_log(avctx, AV_LOG_ERROR, "PARAM_CHANGE side data too small.\n");
-    return AVERROR_INVALIDDATA;
+    ret = AVERROR_INVALIDDATA;
+fail2:
+    if (ret < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
+        if (avctx->err_recognition & AV_EF_EXPLODE)
+            return ret;
+    }
+    return 0;
 }
 
 static int unrefcount_frame(AVCodecInternal *avci, AVFrame *frame)
@@ -2104,21 +2193,28 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
         return AVERROR(EINVAL);
     }
 
+    if (!avctx->codec->decode) {
+        av_log(avctx, AV_LOG_ERROR, "This decoder requires using the avcodec_send_packet() API.\n");
+        return AVERROR(ENOSYS);
+    }
+
     *got_picture_ptr = 0;
     if ((avctx->coded_width || avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))
         return AVERROR(EINVAL);
 
+    avctx->internal->pkt = avpkt;
+    ret = apply_param_change(avctx, avpkt);
+    if (ret < 0)
+        return ret;
+
     av_frame_unref(picture);
 
     if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size ||
         (avctx->active_thread_type & FF_THREAD_FRAME)) {
         int did_split = av_packet_split_side_data(&tmp);
         ret = apply_param_change(avctx, &tmp);
-        if (ret < 0) {
-            av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
-            if (avctx->err_recognition & AV_EF_EXPLODE)
-                goto fail;
-        }
+        if (ret < 0)
+            goto fail;
 
         avctx->internal->pkt = &tmp;
         if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
@@ -2192,12 +2288,18 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
 
     *got_frame_ptr = 0;
 
+    if (!avctx->codec)
+        return AVERROR(EINVAL);
+
+    if (!avctx->codec->decode) {
+        av_log(avctx, AV_LOG_ERROR, "This decoder requires using the avcodec_send_packet() API.\n");
+        return AVERROR(ENOSYS);
+    }
+
     if (!avpkt->data && avpkt->size) {
         av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n");
         return AVERROR(EINVAL);
     }
-    if (!avctx->codec)
-        return AVERROR(EINVAL);
     if (avctx->codec->type != AVMEDIA_TYPE_AUDIO) {
         av_log(avctx, AV_LOG_ERROR, "Invalid media type for audio\n");
         return AVERROR(EINVAL);
@@ -2215,11 +2317,8 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
         AVPacket tmp = *avpkt;
         int did_split = av_packet_split_side_data(&tmp);
         ret = apply_param_change(avctx, &tmp);
-        if (ret < 0) {
-            av_log(avctx, AV_LOG_ERROR, "Error applying parameter changes.\n");
-            if (avctx->err_recognition & AV_EF_EXPLODE)
-                goto fail;
-        }
+        if (ret < 0)
+            goto fail;
 
         avctx->internal->pkt = &tmp;
         if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
@@ -2254,7 +2353,7 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
             skip_reason = AV_RL8(side + 8);
             discard_reason = AV_RL8(side + 9);
         }
-        if (avctx->internal->skip_samples && *got_frame_ptr &&
+        if (avctx->internal->skip_samples > 0 && *got_frame_ptr &&
             !(avctx->flags2 & AV_CODEC_FLAG2_SKIP_MANUAL)) {
             if(frame->nb_samples <= avctx->internal->skip_samples){
                 *got_frame_ptr = 0;
@@ -2293,8 +2392,7 @@ int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
                     int64_t diff_ts = av_rescale_q(frame->nb_samples - discard_padding,
                                                    (AVRational){1, avctx->sample_rate},
                                                    avctx->pkt_timebase);
-                    if (av_frame_get_pkt_duration(frame) >= diff_ts)
-                        av_frame_set_pkt_duration(frame, av_frame_get_pkt_duration(frame) - diff_ts);
+                    av_frame_set_pkt_duration(frame, diff_ts);
                 } else {
                     av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for discarded samples.\n");
                 }
@@ -2332,6 +2430,8 @@ fail:
             av_frame_unref(frame);
     }
 
+    av_assert0(ret <= avpkt->size);
+
     return ret;
 }
 
@@ -2413,6 +2513,79 @@ static int utf8_check(const uint8_t *str)
     return 1;
 }
 
+#if FF_API_ASS_TIMING
+static void insert_ts(AVBPrint *buf, int ts)
+{
+    if (ts == -1) {
+        av_bprintf(buf, "9:59:59.99,");
+    } else {
+        int h, m, s;
+
+        h = ts/360000;  ts -= 360000*h;
+        m = ts/  6000;  ts -=   6000*m;
+        s = ts/   100;  ts -=    100*s;
+        av_bprintf(buf, "%d:%02d:%02d.%02d,", h, m, s, ts);
+    }
+}
+
+static int convert_sub_to_old_ass_form(AVSubtitle *sub, const AVPacket *pkt, AVRational tb)
+{
+    int i;
+    AVBPrint buf;
+
+    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+    for (i = 0; i < sub->num_rects; i++) {
+        char *final_dialog;
+        const char *dialog;
+        AVSubtitleRect *rect = sub->rects[i];
+        int ts_start, ts_duration = -1;
+        long int layer;
+
+        if (rect->type != SUBTITLE_ASS || !strncmp(rect->ass, "Dialogue: ", 10))
+            continue;
+
+        av_bprint_clear(&buf);
+
+        /* skip ReadOrder */
+        dialog = strchr(rect->ass, ',');
+        if (!dialog)
+            continue;
+        dialog++;
+
+        /* extract Layer or Marked */
+        layer = strtol(dialog, (char**)&dialog, 10);
+        if (*dialog != ',')
+            continue;
+        dialog++;
+
+        /* rescale timing to ASS time base (ms) */
+        ts_start = av_rescale_q(pkt->pts, tb, av_make_q(1, 100));
+        if (pkt->duration != -1)
+            ts_duration = av_rescale_q(pkt->duration, tb, av_make_q(1, 100));
+        sub->end_display_time = FFMAX(sub->end_display_time, 10 * ts_duration);
+
+        /* construct ASS (standalone file form with timestamps) string */
+        av_bprintf(&buf, "Dialogue: %ld,", layer);
+        insert_ts(&buf, ts_start);
+        insert_ts(&buf, ts_duration == -1 ? -1 : ts_start + ts_duration);
+        av_bprintf(&buf, "%s\r\n", dialog);
+
+        final_dialog = av_strdup(buf.str);
+        if (!av_bprint_is_complete(&buf) || !final_dialog) {
+            av_freep(&final_dialog);
+            av_bprint_finalize(&buf, NULL);
+            return AVERROR(ENOMEM);
+        }
+        av_freep(&rect->ass);
+        rect->ass = final_dialog;
+    }
+
+    av_bprint_finalize(&buf, NULL);
+    return 0;
+}
+#endif
+
 int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
                              int *got_sub_ptr,
                              AVPacket *avpkt)
@@ -2463,6 +2636,17 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
             av_assert1((ret >= 0) >= !!*got_sub_ptr &&
                        !!*got_sub_ptr >= !!sub->num_rects);
 
+#if FF_API_ASS_TIMING
+            if (avctx->sub_text_format == FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS
+                && *got_sub_ptr && sub->num_rects) {
+                const AVRational tb = avctx->pkt_timebase.num ? avctx->pkt_timebase
+                                                              : avctx->time_base;
+                int err = convert_sub_to_old_ass_form(sub, avpkt, tb);
+                if (err < 0)
+                    ret = err;
+            }
+#endif
+
             if (sub->num_rects && !sub->end_display_time && avpkt->duration &&
                 avctx->pkt_timebase.num) {
                 AVRational ms = { 1, 1000 };
@@ -2526,6 +2710,252 @@ void avsubtitle_free(AVSubtitle *sub)
     memset(sub, 0, sizeof(AVSubtitle));
 }
 
+static int do_decode(AVCodecContext *avctx, AVPacket *pkt)
+{
+    int got_frame;
+    int ret;
+
+    av_assert0(!avctx->internal->buffer_frame->buf[0]);
+
+    if (!pkt)
+        pkt = avctx->internal->buffer_pkt;
+
+    // This is the lesser evil. The field is for compatibility with legacy users
+    // of the legacy API, and users using the new API should not be forced to
+    // even know about this field.
+    avctx->refcounted_frames = 1;
+
+    // Some codecs (at least wma lossless) will crash when feeding drain packets
+    // after EOF was signaled.
+    if (avctx->internal->draining_done)
+        return AVERROR_EOF;
+
+    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
+        ret = avcodec_decode_video2(avctx, avctx->internal->buffer_frame,
+                                    &got_frame, pkt);
+        if (ret >= 0)
+            ret = pkt->size;
+    } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
+        ret = avcodec_decode_audio4(avctx, avctx->internal->buffer_frame,
+                                    &got_frame, pkt);
+    } else {
+        ret = AVERROR(EINVAL);
+    }
+
+    if (ret == AVERROR(EAGAIN))
+        ret = pkt->size;
+
+    if (ret < 0)
+        return ret;
+
+    if (avctx->internal->draining && !got_frame)
+        avctx->internal->draining_done = 1;
+
+    if (ret >= pkt->size) {
+        av_packet_unref(avctx->internal->buffer_pkt);
+    } else {
+        int consumed = ret;
+
+        if (pkt != avctx->internal->buffer_pkt) {
+            av_packet_unref(avctx->internal->buffer_pkt);
+            if ((ret = av_packet_ref(avctx->internal->buffer_pkt, pkt)) < 0)
+                return ret;
+        }
+
+        avctx->internal->buffer_pkt->data += consumed;
+        avctx->internal->buffer_pkt->size -= consumed;
+        avctx->internal->buffer_pkt->pts   = AV_NOPTS_VALUE;
+        avctx->internal->buffer_pkt->dts   = AV_NOPTS_VALUE;
+    }
+
+    if (got_frame)
+        av_assert0(avctx->internal->buffer_frame->buf[0]);
+
+    return 0;
+}
+
+int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
+{
+    int ret;
+
+    if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))
+        return AVERROR(EINVAL);
+
+    if (avctx->internal->draining)
+        return AVERROR_EOF;
+
+    if (!avpkt || !avpkt->size) {
+        avctx->internal->draining = 1;
+        avpkt = NULL;
+
+        if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
+            return 0;
+    }
+
+    if (avctx->codec->send_packet) {
+        if (avpkt) {
+            AVPacket tmp = *avpkt;
+            int did_split = av_packet_split_side_data(&tmp);
+            ret = apply_param_change(avctx, &tmp);
+            if (ret >= 0)
+                ret = avctx->codec->send_packet(avctx, &tmp);
+            if (did_split)
+                av_packet_free_side_data(&tmp);
+            return ret;
+        } else {
+            return avctx->codec->send_packet(avctx, NULL);
+        }
+    }
+
+    // Emulation via old API. Assume avpkt is likely not refcounted, while
+    // decoder output is always refcounted, and avoid copying.
+
+    if (avctx->internal->buffer_pkt->size || avctx->internal->buffer_frame->buf[0])
+        return AVERROR(EAGAIN);
+
+    // The goal is decoding the first frame of the packet without using memcpy,
+    // because the common case is having only 1 frame per packet (especially
+    // with video, but audio too). In other cases, it can't be avoided, unless
+    // the user is feeding refcounted packets.
+    return do_decode(avctx, (AVPacket *)avpkt);
+}
+
+int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+    int ret;
+
+    av_frame_unref(frame);
+
+    if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec))
+        return AVERROR(EINVAL);
+
+    if (avctx->codec->receive_frame) {
+        if (avctx->internal->draining && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
+            return AVERROR_EOF;
+        return avctx->codec->receive_frame(avctx, frame);
+    }
+
+    // Emulation via old API.
+
+    if (!avctx->internal->buffer_frame->buf[0]) {
+        if (!avctx->internal->buffer_pkt->size && !avctx->internal->draining)
+            return AVERROR(EAGAIN);
+
+        while (1) {
+            if ((ret = do_decode(avctx, avctx->internal->buffer_pkt)) < 0) {
+                av_packet_unref(avctx->internal->buffer_pkt);
+                return ret;
+            }
+            // Some audio decoders may consume partial data without returning
+            // a frame (fate-wmapro-2ch). There is no way to make the caller
+            // call avcodec_receive_frame() again without returning a frame,
+            // so try to decode more in these cases.
+            if (avctx->internal->buffer_frame->buf[0] ||
+                !avctx->internal->buffer_pkt->size)
+                break;
+        }
+    }
+
+    if (!avctx->internal->buffer_frame->buf[0])
+        return avctx->internal->draining ? AVERROR_EOF : AVERROR(EAGAIN);
+
+    av_frame_move_ref(frame, avctx->internal->buffer_frame);
+    return 0;
+}
+
+static int do_encode(AVCodecContext *avctx, const AVFrame *frame, int *got_packet)
+{
+    int ret;
+    *got_packet = 0;
+
+    av_packet_unref(avctx->internal->buffer_pkt);
+    avctx->internal->buffer_pkt_valid = 0;
+
+    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
+        ret = avcodec_encode_video2(avctx, avctx->internal->buffer_pkt,
+                                    frame, got_packet);
+    } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
+        ret = avcodec_encode_audio2(avctx, avctx->internal->buffer_pkt,
+                                    frame, got_packet);
+    } else {
+        ret = AVERROR(EINVAL);
+    }
+
+    if (ret >= 0 && *got_packet) {
+        // Encoders must always return ref-counted buffers.
+        // Side-data only packets have no data and can be not ref-counted.
+        av_assert0(!avctx->internal->buffer_pkt->data || avctx->internal->buffer_pkt->buf);
+        avctx->internal->buffer_pkt_valid = 1;
+        ret = 0;
+    } else {
+        av_packet_unref(avctx->internal->buffer_pkt);
+    }
+
+    return ret;
+}
+
+int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame)
+{
+    if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx->codec))
+        return AVERROR(EINVAL);
+
+    if (avctx->internal->draining)
+        return AVERROR_EOF;
+
+    if (!frame) {
+        avctx->internal->draining = 1;
+
+        if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
+            return 0;
+    }
+
+    if (avctx->codec->send_frame)
+        return avctx->codec->send_frame(avctx, frame);
+
+    // Emulation via old API. Do it here instead of avcodec_receive_packet, because:
+    // 1. if the AVFrame is not refcounted, the copying will be much more
+    //    expensive than copying the packet data
+    // 2. assume few users use non-refcounted AVPackets, so usually no copy is
+    //    needed
+
+    if (avctx->internal->buffer_pkt_valid)
+        return AVERROR(EAGAIN);
+
+    return do_encode(avctx, frame, &(int){0});
+}
+
+int attribute_align_arg avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
+{
+    av_packet_unref(avpkt);
+
+    if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx->codec))
+        return AVERROR(EINVAL);
+
+    if (avctx->codec->receive_packet) {
+        if (avctx->internal->draining && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
+            return AVERROR_EOF;
+        return avctx->codec->receive_packet(avctx, avpkt);
+    }
+
+    // Emulation via old API.
+
+    if (!avctx->internal->buffer_pkt_valid) {
+        int got_packet;
+        int ret;
+        if (!avctx->internal->draining)
+            return AVERROR(EAGAIN);
+        ret = do_encode(avctx, NULL, &got_packet);
+        if (ret < 0)
+            return ret;
+        if (ret >= 0 && !got_packet)
+            return AVERROR_EOF;
+    }
+
+    av_packet_move_ref(avpkt, avctx->internal->buffer_pkt);
+    avctx->internal->buffer_pkt_valid = 0;
+    return 0;
+}
+
 av_cold int avcodec_close(AVCodecContext *avctx)
 {
     int i;
@@ -2546,6 +2976,8 @@ av_cold int avcodec_close(AVCodecContext *avctx)
         avctx->internal->byte_buffer_size = 0;
         av_freep(&avctx->internal->byte_buffer);
         av_frame_free(&avctx->internal->to_free);
+        av_frame_free(&avctx->internal->buffer_frame);
+        av_packet_free(&avctx->internal->buffer_pkt);
         for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
             av_buffer_pool_uninit(&pool->pools[i]);
         av_freep(&avctx->internal->pool);
@@ -2562,6 +2994,8 @@ av_cold int avcodec_close(AVCodecContext *avctx)
     av_freep(&avctx->coded_side_data);
     avctx->nb_coded_side_data = 0;
 
+    av_buffer_unref(&avctx->hw_frames_ctx);
+
     if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
         av_opt_free(avctx->priv_data);
     av_opt_free(avctx);
@@ -2914,6 +3348,12 @@ const char *avcodec_license(void)
 
 void avcodec_flush_buffers(AVCodecContext *avctx)
 {
+    avctx->internal->draining      = 0;
+    avctx->internal->draining_done = 0;
+    av_frame_unref(avctx->internal->buffer_frame);
+    av_packet_unref(avctx->internal->buffer_pkt);
+    avctx->internal->buffer_pkt_valid = 0;
+
     if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
         ff_thread_flush(avctx);
     else if (avctx->codec->flush)
@@ -3021,21 +3461,17 @@ int av_get_bits_per_sample(enum AVCodecID codec_id)
     }
 }
 
-int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
+static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba,
+                                    uint32_t tag, int bits_per_coded_sample, int64_t bitrate,
+                                    uint8_t * extradata, int frame_size, int frame_bytes)
 {
-    int id, sr, ch, ba, tag, bps;
-
-    id  = avctx->codec_id;
-    sr  = avctx->sample_rate;
-    ch  = avctx->channels;
-    ba  = avctx->block_align;
-    tag = avctx->codec_tag;
-    bps = av_get_exact_bits_per_sample(avctx->codec_id);
+    int bps = av_get_exact_bits_per_sample(id);
+    int framecount = (ba > 0 && frame_bytes / ba > 0) ? frame_bytes / ba : 1;
 
     /* codecs with an exact constant bits per sample */
     if (bps > 0 && ch > 0 && frame_bytes > 0 && ch < 32768 && bps < 32768)
         return (frame_bytes * 8LL) / (bps * ch);
-    bps = avctx->bits_per_coded_sample;
+    bps = bits_per_coded_sample;
 
     /* codecs with a fixed packet duration */
     switch (id) {
@@ -3051,7 +3487,7 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
     case AV_CODEC_ID_GSM_MS:       return  320;
     case AV_CODEC_ID_MP1:          return  384;
     case AV_CODEC_ID_ATRAC1:       return  512;
-    case AV_CODEC_ID_ATRAC3:       return 1024;
+    case AV_CODEC_ID_ATRAC3:       return 1024 * framecount;
     case AV_CODEC_ID_ATRAC3P:      return 2048;
     case AV_CODEC_ID_MP2:
     case AV_CODEC_ID_MUSEPACK7:    return 1152;
@@ -3062,6 +3498,8 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
         /* calc from sample rate */
         if (id == AV_CODEC_ID_TTA)
             return 256 * sr / 245;
+        else if (id == AV_CODEC_ID_DST)
+            return 588 * sr / 44100;
 
         if (ch > 0) {
             /* calc from sample rate and channels */
@@ -3113,6 +3551,7 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
             case AV_CODEC_ID_ADPCM_DTK:
                 return frame_bytes / (16 * ch) * 28;
             case AV_CODEC_ID_ADPCM_4XM:
+            case AV_CODEC_ID_ADPCM_IMA_DAT4:
             case AV_CODEC_ID_ADPCM_IMA_ISS:
                 return (frame_bytes - 4 * ch) * 2 / ch;
             case AV_CODEC_ID_ADPCM_IMA_SMJPEG:
@@ -3121,7 +3560,7 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
                 return (frame_bytes - 8) * 2 / ch;
             case AV_CODEC_ID_ADPCM_THP:
             case AV_CODEC_ID_ADPCM_THP_LE:
-                if (avctx->extradata)
+                if (extradata)
                     return frame_bytes * 14 / (8 * ch);
                 break;
             case AV_CODEC_ID_ADPCM_XA:
@@ -3156,7 +3595,7 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
             if (ba > 0) {
                 /* calc from frame_bytes, channels, and block_align */
                 int blocks = frame_bytes / ba;
-                switch (avctx->codec_id) {
+                switch (id) {
                 case AV_CODEC_ID_ADPCM_IMA_WAV:
                     if (bps < 2 || bps > 5)
                         return 0;
@@ -3169,12 +3608,14 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
                     return blocks * ((ba - 4 * ch) * 2 / ch);
                 case AV_CODEC_ID_ADPCM_MS:
                     return blocks * (2 + (ba - 7 * ch) * 2 / ch);
+                case AV_CODEC_ID_ADPCM_MTAF:
+                    return blocks * (ba - 16) * 2 / ch;
                 }
             }
 
             if (bps > 0) {
                 /* calc from frame_bytes, channels, and bits_per_coded_sample */
-                switch (avctx->codec_id) {
+                switch (id) {
                 case AV_CODEC_ID_PCM_DVD:
                     if(bps<4)
                         return 0;
@@ -3191,19 +3632,37 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
     }
 
     /* Fall back on using frame_size */
-    if (avctx->frame_size > 1 && frame_bytes)
-        return avctx->frame_size;
+    if (frame_size > 1 && frame_bytes)
+        return frame_size;
 
     //For WMA we currently have no other means to calculate duration thus we
     //do it here by assuming CBR, which is true for all known cases.
-    if (avctx->bit_rate>0 && frame_bytes>0 && avctx->sample_rate>0 && avctx->block_align>1) {
-        if (avctx->codec_id == AV_CODEC_ID_WMAV1 || avctx->codec_id == AV_CODEC_ID_WMAV2)
-            return  (frame_bytes * 8LL * avctx->sample_rate) / avctx->bit_rate;
+    if (bitrate > 0 && frame_bytes > 0 && sr > 0 && ba > 1) {
+        if (id == AV_CODEC_ID_WMAV1 || id == AV_CODEC_ID_WMAV2)
+            return  (frame_bytes * 8LL * sr) / bitrate;
     }
 
     return 0;
 }
 
+int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes)
+{
+    return get_audio_frame_duration(avctx->codec_id, avctx->sample_rate,
+                                    avctx->channels, avctx->block_align,
+                                    avctx->codec_tag, avctx->bits_per_coded_sample,
+                                    avctx->bit_rate, avctx->extradata, avctx->frame_size,
+                                    frame_bytes);
+}
+
+int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes)
+{
+    return get_audio_frame_duration(par->codec_id, par->sample_rate,
+                                    par->channels, par->block_align,
+                                    par->codec_tag, par->bits_per_coded_sample,
+                                    par->bit_rate, par->extradata, par->frame_size,
+                                    frame_bytes);
+}
+
 #if !HAVE_THREADS
 int ff_thread_init(AVCodecContext *s)
 {
@@ -3555,3 +4014,217 @@ AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx)
 
     return props;
 }
+
+static void codec_parameters_reset(AVCodecParameters *par)
+{
+    av_freep(&par->extradata);
+
+    memset(par, 0, sizeof(*par));
+
+    par->codec_type          = AVMEDIA_TYPE_UNKNOWN;
+    par->codec_id            = AV_CODEC_ID_NONE;
+    par->format              = -1;
+    par->field_order         = AV_FIELD_UNKNOWN;
+    par->color_range         = AVCOL_RANGE_UNSPECIFIED;
+    par->color_primaries     = AVCOL_PRI_UNSPECIFIED;
+    par->color_trc           = AVCOL_TRC_UNSPECIFIED;
+    par->color_space         = AVCOL_SPC_UNSPECIFIED;
+    par->chroma_location     = AVCHROMA_LOC_UNSPECIFIED;
+    par->sample_aspect_ratio = (AVRational){ 0, 1 };
+    par->profile             = FF_PROFILE_UNKNOWN;
+    par->level               = FF_LEVEL_UNKNOWN;
+}
+
+AVCodecParameters *avcodec_parameters_alloc(void)
+{
+    AVCodecParameters *par = av_mallocz(sizeof(*par));
+
+    if (!par)
+        return NULL;
+    codec_parameters_reset(par);
+    return par;
+}
+
+void avcodec_parameters_free(AVCodecParameters **ppar)
+{
+    AVCodecParameters *par = *ppar;
+
+    if (!par)
+        return;
+    codec_parameters_reset(par);
+
+    av_freep(ppar);
+}
+
+int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
+{
+    codec_parameters_reset(dst);
+    memcpy(dst, src, sizeof(*dst));
+
+    dst->extradata      = NULL;
+    dst->extradata_size = 0;
+    if (src->extradata) {
+        dst->extradata = av_mallocz(src->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+        if (!dst->extradata)
+            return AVERROR(ENOMEM);
+        memcpy(dst->extradata, src->extradata, src->extradata_size);
+        dst->extradata_size = src->extradata_size;
+    }
+
+    return 0;
+}
+
+int avcodec_parameters_from_context(AVCodecParameters *par,
+                                    const AVCodecContext *codec)
+{
+    codec_parameters_reset(par);
+
+    par->codec_type = codec->codec_type;
+    par->codec_id   = codec->codec_id;
+    par->codec_tag  = codec->codec_tag;
+
+    par->bit_rate              = codec->bit_rate;
+    par->bits_per_coded_sample = codec->bits_per_coded_sample;
+    par->bits_per_raw_sample   = codec->bits_per_raw_sample;
+    par->profile               = codec->profile;
+    par->level                 = codec->level;
+
+    switch (par->codec_type) {
+    case AVMEDIA_TYPE_VIDEO:
+        par->format              = codec->pix_fmt;
+        par->width               = codec->width;
+        par->height              = codec->height;
+        par->field_order         = codec->field_order;
+        par->color_range         = codec->color_range;
+        par->color_primaries     = codec->color_primaries;
+        par->color_trc           = codec->color_trc;
+        par->color_space         = codec->colorspace;
+        par->chroma_location     = codec->chroma_sample_location;
+        par->sample_aspect_ratio = codec->sample_aspect_ratio;
+        par->video_delay         = codec->has_b_frames;
+        break;
+    case AVMEDIA_TYPE_AUDIO:
+        par->format          = codec->sample_fmt;
+        par->channel_layout  = codec->channel_layout;
+        par->channels        = codec->channels;
+        par->sample_rate     = codec->sample_rate;
+        par->block_align     = codec->block_align;
+        par->frame_size      = codec->frame_size;
+        par->initial_padding = codec->initial_padding;
+        par->seek_preroll    = codec->seek_preroll;
+        break;
+    case AVMEDIA_TYPE_SUBTITLE:
+        par->width  = codec->width;
+        par->height = codec->height;
+        break;
+    }
+
+    if (codec->extradata) {
+        par->extradata = av_mallocz(codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+        if (!par->extradata)
+            return AVERROR(ENOMEM);
+        memcpy(par->extradata, codec->extradata, codec->extradata_size);
+        par->extradata_size = codec->extradata_size;
+    }
+
+    return 0;
+}
+
+int avcodec_parameters_to_context(AVCodecContext *codec,
+                                  const AVCodecParameters *par)
+{
+    codec->codec_type = par->codec_type;
+    codec->codec_id   = par->codec_id;
+    codec->codec_tag  = par->codec_tag;
+
+    codec->bit_rate              = par->bit_rate;
+    codec->bits_per_coded_sample = par->bits_per_coded_sample;
+    codec->bits_per_raw_sample   = par->bits_per_raw_sample;
+    codec->profile               = par->profile;
+    codec->level                 = par->level;
+
+    switch (par->codec_type) {
+    case AVMEDIA_TYPE_VIDEO:
+        codec->pix_fmt                = par->format;
+        codec->width                  = par->width;
+        codec->height                 = par->height;
+        codec->field_order            = par->field_order;
+        codec->color_range            = par->color_range;
+        codec->color_primaries        = par->color_primaries;
+        codec->color_trc              = par->color_trc;
+        codec->colorspace             = par->color_space;
+        codec->chroma_sample_location = par->chroma_location;
+        codec->sample_aspect_ratio    = par->sample_aspect_ratio;
+        codec->has_b_frames           = par->video_delay;
+        break;
+    case AVMEDIA_TYPE_AUDIO:
+        codec->sample_fmt      = par->format;
+        codec->channel_layout  = par->channel_layout;
+        codec->channels        = par->channels;
+        codec->sample_rate     = par->sample_rate;
+        codec->block_align     = par->block_align;
+        codec->frame_size      = par->frame_size;
+        codec->delay           =
+        codec->initial_padding = par->initial_padding;
+        codec->seek_preroll    = par->seek_preroll;
+        break;
+    case AVMEDIA_TYPE_SUBTITLE:
+        codec->width  = par->width;
+        codec->height = par->height;
+        break;
+    }
+
+    if (par->extradata) {
+        av_freep(&codec->extradata);
+        codec->extradata = av_mallocz(par->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+        if (!codec->extradata)
+            return AVERROR(ENOMEM);
+        memcpy(codec->extradata, par->extradata, par->extradata_size);
+        codec->extradata_size = par->extradata_size;
+    }
+
+    return 0;
+}
+
+int ff_alloc_a53_sei(const AVFrame *frame, size_t prefix_len,
+                     void **data, size_t *sei_size)
+{
+    AVFrameSideData *side_data = NULL;
+    uint8_t *sei_data;
+
+    if (frame)
+        side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC);
+
+    if (!side_data) {
+        *data = NULL;
+        return 0;
+    }
+
+    *sei_size = side_data->size + 11;
+    *data = av_mallocz(*sei_size + prefix_len);
+    if (!*data)
+        return AVERROR(ENOMEM);
+    sei_data = (uint8_t*)*data + prefix_len;
+
+    // country code
+    sei_data[0] = 181;
+    sei_data[1] = 0;
+    sei_data[2] = 49;
+
+    /**
+     * 'GA94' is standard in North America for ATSC, but hard coding
+     * this style may not be the right thing to do -- other formats
+     * do exist. This information is not available in the side_data
+     * so we are going with this right now.
+     */
+    AV_WL32(sei_data + 3, MKTAG('G', 'A', '9', '4'));
+    sei_data[7] = 3;
+    sei_data[8] = ((side_data->size/3) & 0x1f) | 0x40;
+    sei_data[9] = 0;
+
+    memcpy(sei_data + 10, side_data->data, side_data->size);
+
+    sei_data[side_data->size+10] = 255;
+
+    return 0;
+}
diff --git a/libavcodec/utvideo.c b/libavcodec/utvideo.c
index b14e56e..5828d5e 100644
--- a/libavcodec/utvideo.c
+++ b/libavcodec/utvideo.c
@@ -39,3 +39,9 @@ int ff_ut_huff_cmp_len(const void *a, const void *b)
     const HuffEntry *aa = a, *bb = b;
     return (aa->len - bb->len)*256 + aa->sym - bb->sym;
 }
+
+int ff_ut10_huff_cmp_len(const void *a, const void *b)
+{
+    const HuffEntry *aa = a, *bb = b;
+    return (aa->len - bb->len)*1024 + aa->sym - bb->sym;
+}
diff --git a/libavcodec/utvideo.h b/libavcodec/utvideo.h
index 84eec66..b785bf0 100644
--- a/libavcodec/utvideo.h
+++ b/libavcodec/utvideo.h
@@ -76,6 +76,7 @@ typedef struct UtvideoContext {
     int      compression;
     int      interlaced;
     int      frame_pred;
+    int      pro;
 
     int      slice_stride;
     uint8_t *slice_bits, *slice_buffer[4];
@@ -83,12 +84,13 @@ typedef struct UtvideoContext {
 } UtvideoContext;
 
 typedef struct HuffEntry {
-    uint8_t  sym;
+    uint16_t sym;
     uint8_t  len;
     uint32_t code;
 } HuffEntry;
 
 /* Compare huffman tree nodes */
 int ff_ut_huff_cmp_len(const void *a, const void *b);
+int ff_ut10_huff_cmp_len(const void *a, const void *b);
 
 #endif /* AVCODEC_UTVIDEO_H */
diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c
index 760d9e5..8798714 100644
--- a/libavcodec/utvideodec.c
+++ b/libavcodec/utvideodec.c
@@ -35,6 +35,50 @@
 #include "thread.h"
 #include "utvideo.h"
 
+static int build_huff10(const uint8_t *src, VLC *vlc, int *fsym)
+{
+    int i;
+    HuffEntry he[1024];
+    int last;
+    uint32_t codes[1024];
+    uint8_t bits[1024];
+    uint16_t syms[1024];
+    uint32_t code;
+
+    *fsym = -1;
+    for (i = 0; i < 1024; i++) {
+        he[i].sym = i;
+        he[i].len = *src++;
+    }
+    qsort(he, 1024, sizeof(*he), ff_ut10_huff_cmp_len);
+
+    if (!he[0].len) {
+        *fsym = he[0].sym;
+        return 0;
+    }
+
+    last = 1023;
+    while (he[last].len == 255 && last)
+        last--;
+
+    if (he[last].len > 32) {
+        return -1;
+    }
+
+    code = 1;
+    for (i = last; i >= 0; i--) {
+        codes[i] = code >> (32 - he[i].len);
+        bits[i]  = he[i].len;
+        syms[i]  = he[i].sym;
+        code += 0x80000000u >> (he[i].len - 1);
+    }
+
+    return ff_init_vlc_sparse(vlc, FFMIN(he[last].len, 11), last + 1,
+                              bits,  sizeof(*bits),  sizeof(*bits),
+                              codes, sizeof(*codes), sizeof(*codes),
+                              syms,  sizeof(*syms),  sizeof(*syms), 0);
+}
+
 static int build_huff(const uint8_t *src, VLC *vlc, int *fsym)
 {
     int i;
@@ -78,6 +122,111 @@ static int build_huff(const uint8_t *src, VLC *vlc, int *fsym)
                               syms,  sizeof(*syms),  sizeof(*syms), 0);
 }
 
+static int decode_plane10(UtvideoContext *c, int plane_no,
+                          uint16_t *dst, int step, int stride,
+                          int width, int height,
+                          const uint8_t *src, const uint8_t *huff,
+                          int use_pred)
+{
+    int i, j, slice, pix, ret;
+    int sstart, send;
+    VLC vlc;
+    GetBitContext gb;
+    int prev, fsym;
+
+    if ((ret = build_huff10(huff, &vlc, &fsym)) < 0) {
+        av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
+        return ret;
+    }
+    if (fsym >= 0) { // build_huff reported a symbol to fill slices with
+        send = 0;
+        for (slice = 0; slice < c->slices; slice++) {
+            uint16_t *dest;
+
+            sstart = send;
+            send   = (height * (slice + 1) / c->slices);
+            dest   = dst + sstart * stride;
+
+            prev = 0x200;
+            for (j = sstart; j < send; j++) {
+                for (i = 0; i < width * step; i += step) {
+                    pix = fsym;
+                    if (use_pred) {
+                        prev += pix;
+                        prev &= 0x3FF;
+                        pix   = prev;
+                    }
+                    dest[i] = pix;
+                }
+                dest += stride;
+            }
+        }
+        return 0;
+    }
+
+    send = 0;
+    for (slice = 0; slice < c->slices; slice++) {
+        uint16_t *dest;
+        int slice_data_start, slice_data_end, slice_size;
+
+        sstart = send;
+        send   = (height * (slice + 1) / c->slices);
+        dest   = dst + sstart * stride;
+
+        // slice offset and size validation was done earlier
+        slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0;
+        slice_data_end   = AV_RL32(src + slice * 4);
+        slice_size       = slice_data_end - slice_data_start;
+
+        if (!slice_size) {
+            av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol "
+                   "yet a slice has a length of zero.\n");
+            goto fail;
+        }
+
+        memcpy(c->slice_bits, src + slice_data_start + c->slices * 4,
+               slice_size);
+        memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+        c->bdsp.bswap_buf((uint32_t *) c->slice_bits,
+                          (uint32_t *) c->slice_bits,
+                          (slice_data_end - slice_data_start + 3) >> 2);
+        init_get_bits(&gb, c->slice_bits, slice_size * 8);
+
+        prev = 0x200;
+        for (j = sstart; j < send; j++) {
+            for (i = 0; i < width * step; i += step) {
+                if (get_bits_left(&gb) <= 0) {
+                    av_log(c->avctx, AV_LOG_ERROR,
+                           "Slice decoding ran out of bits\n");
+                    goto fail;
+                }
+                pix = get_vlc2(&gb, vlc.table, vlc.bits, 3);
+                if (pix < 0) {
+                    av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
+                    goto fail;
+                }
+                if (use_pred) {
+                    prev += pix;
+                    prev &= 0x3FF;
+                    pix   = prev;
+                }
+                dest[i] = pix;
+            }
+            dest += stride;
+        }
+        if (get_bits_left(&gb) > 32)
+            av_log(c->avctx, AV_LOG_WARNING,
+                   "%d bits left after decoding slice\n", get_bits_left(&gb));
+    }
+
+    ff_free_vlc(&vlc);
+
+    return 0;
+fail:
+    ff_free_vlc(&vlc);
+    return AVERROR_INVALIDDATA;
+}
+
 static int decode_plane(UtvideoContext *c, int plane_no,
                         uint8_t *dst, int step, int stride,
                         int width, int height,
@@ -201,6 +350,28 @@ static void restore_rgb_planes(uint8_t *src, int step, int stride, int width,
     }
 }
 
+static void restore_rgb_planes10(AVFrame *frame, int width, int height)
+{
+    uint16_t *src_r = (uint16_t *)frame->data[2];
+    uint16_t *src_g = (uint16_t *)frame->data[0];
+    uint16_t *src_b = (uint16_t *)frame->data[1];
+    int r, g, b;
+    int i, j;
+
+    for (j = 0; j < height; j++) {
+        for (i = 0; i < width; i++) {
+            r = src_r[i];
+            g = src_g[i];
+            b = src_b[i];
+            src_r[i] = (r + g - 0x200) & 0x3FF;
+            src_b[i] = (b + g - 0x200) & 0x3FF;
+        }
+        src_r += frame->linesize[2] / 2;
+        src_g += frame->linesize[0] / 2;
+        src_b += frame->linesize[1] / 2;
+    }
+}
+
 static void restore_median(uint8_t *src, int step, int stride,
                            int width, int height, int slices, int rmode)
 {
@@ -345,35 +516,68 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 
     /* parse plane structure to get frame flags and validate slice offsets */
     bytestream2_init(&gb, buf, buf_size);
-    for (i = 0; i < c->planes; i++) {
-        plane_start[i] = gb.buffer;
-        if (bytestream2_get_bytes_left(&gb) < 256 + 4 * c->slices) {
-            av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n");
+    if (c->pro) {
+        if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) {
+            av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n");
             return AVERROR_INVALIDDATA;
         }
-        bytestream2_skipu(&gb, 256);
-        slice_start = 0;
-        slice_end   = 0;
-        for (j = 0; j < c->slices; j++) {
-            slice_end   = bytestream2_get_le32u(&gb);
-            slice_size  = slice_end - slice_start;
-            if (slice_end < 0 || slice_size < 0 ||
-                bytestream2_get_bytes_left(&gb) < slice_end) {
-                av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
+        c->frame_info = bytestream2_get_le32u(&gb);
+        c->slices = ((c->frame_info >> 16) & 0xff) + 1;
+        for (i = 0; i < c->planes; i++) {
+            plane_start[i] = gb.buffer;
+            if (bytestream2_get_bytes_left(&gb) < 1024 + 4 * c->slices) {
+                av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n");
                 return AVERROR_INVALIDDATA;
             }
-            slice_start = slice_end;
-            max_slice_size = FFMAX(max_slice_size, slice_size);
+            slice_start = 0;
+            slice_end   = 0;
+            for (j = 0; j < c->slices; j++) {
+                slice_end   = bytestream2_get_le32u(&gb);
+                if (slice_end < 0 || slice_end < slice_start ||
+                    bytestream2_get_bytes_left(&gb) < slice_end) {
+                    av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
+                    return AVERROR_INVALIDDATA;
+                }
+                slice_size  = slice_end - slice_start;
+                slice_start = slice_end;
+                max_slice_size = FFMAX(max_slice_size, slice_size);
+            }
+            plane_size = slice_end;
+            bytestream2_skipu(&gb, plane_size);
+            bytestream2_skipu(&gb, 1024);
         }
-        plane_size = slice_end;
-        bytestream2_skipu(&gb, plane_size);
-    }
-    plane_start[c->planes] = gb.buffer;
-    if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) {
-        av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n");
-        return AVERROR_INVALIDDATA;
+        plane_start[c->planes] = gb.buffer;
+    } else {
+        for (i = 0; i < c->planes; i++) {
+            plane_start[i] = gb.buffer;
+            if (bytestream2_get_bytes_left(&gb) < 256 + 4 * c->slices) {
+                av_log(avctx, AV_LOG_ERROR, "Insufficient data for a plane\n");
+                return AVERROR_INVALIDDATA;
+            }
+            bytestream2_skipu(&gb, 256);
+            slice_start = 0;
+            slice_end   = 0;
+            for (j = 0; j < c->slices; j++) {
+                slice_end   = bytestream2_get_le32u(&gb);
+                if (slice_end < 0 || slice_end < slice_start ||
+                    bytestream2_get_bytes_left(&gb) < slice_end) {
+                    av_log(avctx, AV_LOG_ERROR, "Incorrect slice size\n");
+                    return AVERROR_INVALIDDATA;
+                }
+                slice_size  = slice_end - slice_start;
+                slice_start = slice_end;
+                max_slice_size = FFMAX(max_slice_size, slice_size);
+            }
+            plane_size = slice_end;
+            bytestream2_skipu(&gb, plane_size);
+        }
+        plane_start[c->planes] = gb.buffer;
+        if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) {
+            av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n");
+            return AVERROR_INVALIDDATA;
+        }
+        c->frame_info = bytestream2_get_le32u(&gb);
     }
-    c->frame_info = bytestream2_get_le32u(&gb);
     av_log(avctx, AV_LOG_DEBUG, "frame information flags %"PRIX32"\n",
            c->frame_info);
 
@@ -418,6 +622,19 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         restore_rgb_planes(frame.f->data[0], c->planes, frame.f->linesize[0],
                            avctx->width, avctx->height);
         break;
+    case AV_PIX_FMT_GBRAP10:
+    case AV_PIX_FMT_GBRP10:
+        for (i = 0; i < c->planes; i++) {
+            ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], 1,
+                                 frame.f->linesize[i] / 2, avctx->width,
+                                 avctx->height, plane_start[i],
+                                 plane_start[i + 1] - 1024,
+                                 c->frame_pred == PRED_LEFT);
+            if (ret)
+                return ret;
+        }
+        restore_rgb_planes10(frame.f, avctx->width, avctx->height);
+        break;
     case AV_PIX_FMT_YUV420P:
         for (i = 0; i < 3; i++) {
             ret = decode_plane(c, i, frame.f->data[i], 1, frame.f->linesize[i],
@@ -459,6 +676,15 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
             }
         }
         break;
+    case AV_PIX_FMT_YUV422P10:
+        for (i = 0; i < 3; i++) {
+            ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], 1, frame.f->linesize[i] / 2,
+                                 avctx->width >> !!i, avctx->height,
+                                 plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT);
+            if (ret)
+                return ret;
+        }
+        break;
     }
 
     frame.f->key_frame = 1;
@@ -479,28 +705,37 @@ static av_cold int decode_init(AVCodecContext *avctx)
 
     ff_bswapdsp_init(&c->bdsp);
 
-    if (avctx->extradata_size < 16) {
+    if (avctx->extradata_size >= 16) {
+        av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
+               avctx->extradata[3], avctx->extradata[2],
+               avctx->extradata[1], avctx->extradata[0]);
+        av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n",
+               AV_RB32(avctx->extradata + 4));
+        c->frame_info_size = AV_RL32(avctx->extradata + 8);
+        c->flags           = AV_RL32(avctx->extradata + 12);
+
+        if (c->frame_info_size != 4)
+            avpriv_request_sample(avctx, "Frame info not 4 bytes");
+        av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags);
+        c->slices      = (c->flags >> 24) + 1;
+        c->compression = c->flags & 1;
+        c->interlaced  = c->flags & 0x800;
+    } else if (avctx->extradata_size == 8) {
+        av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
+               avctx->extradata[3], avctx->extradata[2],
+               avctx->extradata[1], avctx->extradata[0]);
+        av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n",
+               AV_RB32(avctx->extradata + 4));
+        c->interlaced  = 0;
+        c->pro         = 1;
+        c->frame_info_size = 4;
+    } else {
         av_log(avctx, AV_LOG_ERROR,
                "Insufficient extradata size %d, should be at least 16\n",
                avctx->extradata_size);
         return AVERROR_INVALIDDATA;
     }
 
-    av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n",
-           avctx->extradata[3], avctx->extradata[2],
-           avctx->extradata[1], avctx->extradata[0]);
-    av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n",
-           AV_RB32(avctx->extradata + 4));
-    c->frame_info_size = AV_RL32(avctx->extradata + 8);
-    c->flags           = AV_RL32(avctx->extradata + 12);
-
-    if (c->frame_info_size != 4)
-        avpriv_request_sample(avctx, "Frame info not 4 bytes");
-    av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags);
-    c->slices      = (c->flags >> 24) + 1;
-    c->compression = c->flags & 1;
-    c->interlaced  = c->flags & 0x800;
-
     c->slice_bits_size = 0;
 
     switch (avctx->codec_tag) {
@@ -522,6 +757,18 @@ static av_cold int decode_init(AVCodecContext *avctx)
         avctx->pix_fmt = AV_PIX_FMT_YUV422P;
         avctx->colorspace = AVCOL_SPC_BT470BG;
         break;
+    case MKTAG('U', 'Q', 'Y', '2'):
+        c->planes      = 3;
+        avctx->pix_fmt = AV_PIX_FMT_YUV422P10;
+        break;
+    case MKTAG('U', 'Q', 'R', 'G'):
+        c->planes      = 3;
+        avctx->pix_fmt = AV_PIX_FMT_GBRP10;
+        break;
+    case MKTAG('U', 'Q', 'R', 'A'):
+        c->planes      = 4;
+        avctx->pix_fmt = AV_PIX_FMT_GBRAP10;
+        break;
     case MKTAG('U', 'L', 'H', '0'):
         c->planes      = 3;
         avctx->pix_fmt = AV_PIX_FMT_YUV420P;
diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c
index 00185cf..6240413 100644
--- a/libavcodec/utvideoenc.c
+++ b/libavcodec/utvideoenc.c
@@ -160,7 +160,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
         return AVERROR(EINVAL);
     }
 
-    /* extradata size is 4 * 32bit */
+    /* extradata size is 4 * 32 bits */
     avctx->extradata_size = 16;
 
     avctx->extradata = av_mallocz(avctx->extradata_size +
@@ -371,7 +371,7 @@ static int write_huff_codes(uint8_t *src, uint8_t *dst, int dst_size,
         src += width;
     }
 
-    /* Pad output to a 32bit boundary */
+    /* Pad output to a 32-bit boundary */
     count = put_bits_count(&pb) & 0x1F;
 
     if (count)
@@ -609,7 +609,7 @@ static int utvideo_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     }
 
     /*
-     * Write frame information (LE 32bit unsigned)
+     * Write frame information (LE 32-bit unsigned)
      * into the output packet.
      * Contains the prediction method.
      */
diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c
index 00c89dc..d3a8e26 100644
--- a/libavcodec/v210enc.c
+++ b/libavcodec/v210enc.c
@@ -86,7 +86,8 @@ av_cold void ff_v210enc_init(V210EncContext *s)
 {
     s->pack_line_8  = v210_planar_pack_8_c;
     s->pack_line_10 = v210_planar_pack_10_c;
-    s->sample_factor = 1;
+    s->sample_factor_8  = 1;
+    s->sample_factor_10 = 1;
 
     if (ARCH_X86)
         ff_v210enc_init_x86(s);
@@ -133,15 +134,19 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         const uint16_t *y = (const uint16_t *)pic->data[0];
         const uint16_t *u = (const uint16_t *)pic->data[1];
         const uint16_t *v = (const uint16_t *)pic->data[2];
+
+        const int sample_size = 6 * s->sample_factor_10;
+        const int sample_w    = avctx->width / sample_size;
+
         for (h = 0; h < avctx->height; h++) {
             uint32_t val;
-            w = (avctx->width / (6 * s->sample_factor)) * 6 * s->sample_factor;
+            w = sample_w * sample_size;
             s->pack_line_10(y, u, v, dst, w);
 
             y += w;
             u += w >> 1;
             v += w >> 1;
-            dst += (w / (6 * s->sample_factor)) * 16 * s->sample_factor;
+            dst += sample_w * 16 * s->sample_factor_10;
 
             for (; w < avctx->width - 5; w += 6) {
                 WRITE_PIXELS(u, y, v);
@@ -178,15 +183,19 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         const uint8_t *y = pic->data[0];
         const uint8_t *u = pic->data[1];
         const uint8_t *v = pic->data[2];
+
+        const int sample_size = 12 * s->sample_factor_8;
+        const int sample_w    = avctx->width / sample_size;
+
         for (h = 0; h < avctx->height; h++) {
             uint32_t val;
-            w = (avctx->width / (12 * s->sample_factor)) * 12 * s->sample_factor;
+            w = sample_w * sample_size;
             s->pack_line_8(y, u, v, dst, w);
 
             y += w;
             u += w >> 1;
             v += w >> 1;
-            dst += (w / (12 * s->sample_factor)) * 32 * s->sample_factor;
+            dst += sample_w * 32 * s->sample_factor_8;
 
             for (; w < avctx->width - 5; w += 6) {
                 WRITE_PIXELS8(u, y, v);
diff --git a/libavcodec/v210enc.h b/libavcodec/v210enc.h
index 899a7d9..51305c1 100644
--- a/libavcodec/v210enc.h
+++ b/libavcodec/v210enc.h
@@ -28,8 +28,8 @@ typedef struct V210EncContext {
                         const uint8_t *v, uint8_t *dst, ptrdiff_t width);
     void (*pack_line_10)(const uint16_t *y, const uint16_t *u,
                          const uint16_t *v, uint8_t *dst, ptrdiff_t width);
-    int sample_factor; /* This value must be the same for both 8-and 10-bit
-                          functions otherwise the output will be incorrect. */
+    int sample_factor_8;
+    int sample_factor_10;
 } V210EncContext;
 
 void ff_v210enc_init(V210EncContext *s);
diff --git a/libavcodec/vaapi.c b/libavcodec/vaapi.c
index a1ea790..36db640 100644
--- a/libavcodec/vaapi.c
+++ b/libavcodec/vaapi.c
@@ -210,8 +210,6 @@ void ff_vaapi_common_end_frame(AVCodecContext *avctx)
 {
     FFVAContext * const vactx = ff_vaapi_get_context(avctx);
 
-    ff_dlog(avctx, "ff_vaapi_common_end_frame()\n");
-
     destroy_buffers(vactx->display, &vactx->pic_param_buf_id, 1);
     destroy_buffers(vactx->display, &vactx->iq_matrix_buf_id, 1);
     destroy_buffers(vactx->display, &vactx->bitplane_buf_id, 1);
diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
new file mode 100644
index 0000000..9490516
--- /dev/null
+++ b/libavcodec/vaapi_encode.c
@@ -0,0 +1,1238 @@
+/*
+ * 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 <inttypes.h>
+#include <string.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/common.h"
+#include "libavutil/log.h"
+#include "libavutil/pixdesc.h"
+
+#include "vaapi_encode.h"
+#include "avcodec.h"
+
+static const char *picture_type_name[] = { "IDR", "I", "P", "B" };
+
+static int vaapi_encode_make_packed_header(AVCodecContext *avctx,
+                                           VAAPIEncodePicture *pic,
+                                           int type, char *data, size_t bit_len)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAStatus vas;
+    VABufferID param_buffer, data_buffer;
+    VAEncPackedHeaderParameterBuffer params = {
+        .type = type,
+        .bit_length = bit_len,
+        .has_emulation_bytes = 1,
+    };
+
+    av_assert0(pic->nb_param_buffers + 2 <= MAX_PARAM_BUFFERS);
+
+    vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
+                         VAEncPackedHeaderParameterBufferType,
+                         sizeof(params), 1, &params, &param_buffer);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer "
+               "for packed header (type %d): %d (%s).\n",
+               type, vas, vaErrorStr(vas));
+        return AVERROR(EIO);
+    }
+    pic->param_buffers[pic->nb_param_buffers++] = param_buffer;
+
+    vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
+                         VAEncPackedHeaderDataBufferType,
+                         (bit_len + 7) / 8, 1, data, &data_buffer);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to create data buffer "
+               "for packed header (type %d): %d (%s).\n",
+               type, vas, vaErrorStr(vas));
+        return AVERROR(EIO);
+    }
+    pic->param_buffers[pic->nb_param_buffers++] = data_buffer;
+
+    av_log(avctx, AV_LOG_DEBUG, "Packed header buffer (%d) is %#x/%#x "
+           "(%zu bits).\n", type, param_buffer, data_buffer, bit_len);
+    return 0;
+}
+
+static int vaapi_encode_make_param_buffer(AVCodecContext *avctx,
+                                          VAAPIEncodePicture *pic,
+                                          int type, char *data, size_t len)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAStatus vas;
+    VABufferID buffer;
+
+    av_assert0(pic->nb_param_buffers + 1 <= MAX_PARAM_BUFFERS);
+
+    vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
+                         type, len, 1, data, &buffer);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer "
+               "(type %d): %d (%s).\n", type, vas, vaErrorStr(vas));
+        return AVERROR(EIO);
+    }
+    pic->param_buffers[pic->nb_param_buffers++] = buffer;
+
+    av_log(avctx, AV_LOG_DEBUG, "Param buffer (%d) is %#x.\n",
+           type, buffer);
+    return 0;
+}
+
+static int vaapi_encode_wait(AVCodecContext *avctx,
+                             VAAPIEncodePicture *pic)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAStatus vas;
+
+    av_assert0(pic->encode_issued);
+
+    if (pic->encode_complete) {
+        // Already waited for this picture.
+        return 0;
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "Sync to pic %"PRId64"/%"PRId64" "
+           "(recon surface %#x).\n", pic->display_order,
+           pic->encode_order, pic->recon_surface);
+
+    vas = vaSyncSurface(ctx->hwctx->display, pic->recon_surface);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        return AVERROR(EIO);
+    }
+
+    // Input is definitely finished with now.
+    av_frame_free(&pic->input_image);
+
+    pic->encode_complete = 1;
+    return 0;
+}
+
+static int vaapi_encode_issue(AVCodecContext *avctx,
+                              VAAPIEncodePicture *pic)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAAPIEncodeSlice *slice;
+    VAStatus vas;
+    int err, i;
+    char data[MAX_PARAM_BUFFER_SIZE];
+    size_t bit_len;
+
+    av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" "
+           "as type %s.\n", pic->display_order, pic->encode_order,
+           picture_type_name[pic->type]);
+    if (pic->nb_refs == 0) {
+        av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n");
+    } else {
+        av_log(avctx, AV_LOG_DEBUG, "Refers to:");
+        for (i = 0; i < pic->nb_refs; i++) {
+            av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,
+                   pic->refs[i]->display_order, pic->refs[i]->encode_order);
+        }
+        av_log(avctx, AV_LOG_DEBUG, ".\n");
+    }
+
+    av_assert0(pic->input_available && !pic->encode_issued);
+    for (i = 0; i < pic->nb_refs; i++) {
+        av_assert0(pic->refs[i]);
+        // If we are serialised then the references must have already
+        // completed.  If not, they must have been issued but need not
+        // have completed yet.
+        if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING)
+            av_assert0(pic->refs[i]->encode_complete);
+        else
+            av_assert0(pic->refs[i]->encode_issued);
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface);
+
+    pic->recon_image = av_frame_alloc();
+    if (!pic->recon_image) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    err = av_hwframe_get_buffer(ctx->recon_frames_ref, pic->recon_image, 0);
+    if (err < 0) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    pic->recon_surface = (VASurfaceID)(uintptr_t)pic->recon_image->data[3];
+    av_log(avctx, AV_LOG_DEBUG, "Recon surface is %#x.\n", pic->recon_surface);
+
+    vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
+                         VAEncCodedBufferType,
+                         MAX_OUTPUT_BUFFER_SIZE, 1, 0,
+                         &pic->output_buffer);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to create bitstream "
+               "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    av_log(avctx, AV_LOG_DEBUG, "Output buffer is %#x.\n",
+           pic->output_buffer);
+
+    if (ctx->codec->picture_params_size > 0) {
+        pic->codec_picture_params = av_malloc(ctx->codec->picture_params_size);
+        if (!pic->codec_picture_params)
+            goto fail;
+        memcpy(pic->codec_picture_params, ctx->codec_picture_params,
+               ctx->codec->picture_params_size);
+    } else {
+        av_assert0(!ctx->codec_picture_params);
+    }
+
+    pic->nb_param_buffers = 0;
+
+    if (pic->encode_order == 0) {
+        // Global parameter buffers are set on the first picture only.
+
+        for (i = 0; i < ctx->nb_global_params; i++) {
+            err = vaapi_encode_make_param_buffer(avctx, pic,
+                                                 VAEncMiscParameterBufferType,
+                                                 (char*)ctx->global_params[i],
+                                                 ctx->global_params_size[i]);
+            if (err < 0)
+                goto fail;
+        }
+    }
+
+    if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) {
+        err = vaapi_encode_make_param_buffer(avctx, pic,
+                                             VAEncSequenceParameterBufferType,
+                                             ctx->codec_sequence_params,
+                                             ctx->codec->sequence_params_size);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (ctx->codec->init_picture_params) {
+        err = ctx->codec->init_picture_params(avctx, pic);
+        if (err < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to initialise picture "
+                   "parameters: %d.\n", err);
+            goto fail;
+        }
+        err = vaapi_encode_make_param_buffer(avctx, pic,
+                                             VAEncPictureParameterBufferType,
+                                             pic->codec_picture_params,
+                                             ctx->codec->picture_params_size);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (pic->type == PICTURE_TYPE_IDR) {
+        if (ctx->codec->write_sequence_header) {
+            bit_len = 8 * sizeof(data);
+            err = ctx->codec->write_sequence_header(avctx, data, &bit_len);
+            if (err < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to write per-sequence "
+                       "header: %d.\n", err);
+                goto fail;
+            }
+            err = vaapi_encode_make_packed_header(avctx, pic,
+                                                  ctx->codec->sequence_header_type,
+                                                  data, bit_len);
+            if (err < 0)
+                goto fail;
+        }
+    }
+
+    if (ctx->codec->write_picture_header) {
+        bit_len = 8 * sizeof(data);
+        err = ctx->codec->write_picture_header(avctx, pic, data, &bit_len);
+        if (err < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Failed to write per-picture "
+                   "header: %d.\n", err);
+            goto fail;
+        }
+        err = vaapi_encode_make_packed_header(avctx, pic,
+                                              ctx->codec->picture_header_type,
+                                              data, bit_len);
+        if (err < 0)
+            goto fail;
+    }
+
+    if (ctx->codec->write_extra_buffer) {
+        for (i = 0;; i++) {
+            size_t len = sizeof(data);
+            int type;
+            err = ctx->codec->write_extra_buffer(avctx, pic, i, &type,
+                                                 data, &len);
+            if (err == AVERROR_EOF)
+                break;
+            if (err < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to write extra "
+                       "buffer %d: %d.\n", i, err);
+                goto fail;
+            }
+
+            err = vaapi_encode_make_param_buffer(avctx, pic, type,
+                                                 data, len);
+            if (err < 0)
+                goto fail;
+        }
+    }
+
+    av_assert0(pic->nb_slices <= MAX_PICTURE_SLICES);
+    for (i = 0; i < pic->nb_slices; i++) {
+        slice = av_mallocz(sizeof(*slice));
+        if (!slice) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+        pic->slices[i] = slice;
+
+        if (ctx->codec->slice_params_size > 0) {
+            slice->codec_slice_params = av_mallocz(ctx->codec->slice_params_size);
+            if (!slice->codec_slice_params) {
+                err = AVERROR(ENOMEM);
+                goto fail;
+            }
+        }
+
+        if (ctx->codec->init_slice_params) {
+            err = ctx->codec->init_slice_params(avctx, pic, slice);
+            if (err < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to initalise slice "
+                       "parameters: %d.\n", err);
+                goto fail;
+            }
+        }
+
+        if (ctx->codec->write_slice_header) {
+            bit_len = 8 * sizeof(data);
+            err = ctx->codec->write_slice_header(avctx, pic, slice,
+                                                 data, &bit_len);
+            if (err < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to write per-slice "
+                       "header: %d.\n", err);
+                goto fail;
+            }
+            err = vaapi_encode_make_packed_header(avctx, pic,
+                                                  ctx->codec->slice_header_type,
+                                                  data, bit_len);
+            if (err < 0)
+                goto fail;
+        }
+
+        if (ctx->codec->init_slice_params) {
+            err = vaapi_encode_make_param_buffer(avctx, pic,
+                                                 VAEncSliceParameterBufferType,
+                                                 slice->codec_slice_params,
+                                                 ctx->codec->slice_params_size);
+            if (err < 0)
+                goto fail;
+        }
+    }
+
+    vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,
+                         pic->input_surface);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to begin picture encode issue: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail_with_picture;
+    }
+
+    vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
+                          pic->param_buffers, pic->nb_param_buffers);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to upload encode parameters: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail_with_picture;
+    }
+
+    vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to end picture encode issue: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail_at_end;
+    }
+
+    pic->encode_issued = 1;
+
+    if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING)
+        return vaapi_encode_wait(avctx, pic);
+    else
+        return 0;
+
+fail_with_picture:
+    vaEndPicture(ctx->hwctx->display, ctx->va_context);
+fail:
+    for(i = 0; i < pic->nb_param_buffers; i++)
+        vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]);
+fail_at_end:
+    av_freep(&pic->codec_picture_params);
+    av_frame_free(&pic->recon_image);
+    return err;
+}
+
+static int vaapi_encode_output(AVCodecContext *avctx,
+                               VAAPIEncodePicture *pic, AVPacket *pkt)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VACodedBufferSegment *buf_list, *buf;
+    VAStatus vas;
+    int err;
+
+    err = vaapi_encode_wait(avctx, pic);
+    if (err < 0)
+        return err;
+
+    buf_list = NULL;
+    vas = vaMapBuffer(ctx->hwctx->display, pic->output_buffer,
+                      (void**)&buf_list);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to map output buffers: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    for (buf = buf_list; buf; buf = buf->next) {
+        av_log(avctx, AV_LOG_DEBUG, "Output buffer: %u bytes "
+               "(status %08x).\n", buf->size, buf->status);
+
+        err = av_new_packet(pkt, buf->size);
+        if (err < 0)
+            goto fail;
+
+        memcpy(pkt->data, buf->buf, buf->size);
+    }
+
+    if (pic->type == PICTURE_TYPE_IDR)
+        pkt->flags |= AV_PKT_FLAG_KEY;
+
+    pkt->pts = pic->pts;
+
+    vas = vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    vaDestroyBuffer(ctx->hwctx->display, pic->output_buffer);
+    pic->output_buffer = VA_INVALID_ID;
+
+    av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
+           pic->display_order, pic->encode_order);
+    return 0;
+
+fail:
+    if (pic->output_buffer != VA_INVALID_ID) {
+        vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
+        vaDestroyBuffer(ctx->hwctx->display, pic->output_buffer);
+        pic->output_buffer = VA_INVALID_ID;
+    }
+    return err;
+}
+
+static int vaapi_encode_discard(AVCodecContext *avctx,
+                                VAAPIEncodePicture *pic)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+
+    vaapi_encode_wait(avctx, pic);
+
+    if (pic->output_buffer != VA_INVALID_ID) {
+        av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
+               "%"PRId64"/%"PRId64".\n",
+               pic->display_order, pic->encode_order);
+
+        vaDestroyBuffer(ctx->hwctx->display, pic->output_buffer);
+        pic->output_buffer = VA_INVALID_ID;
+    }
+
+    return 0;
+}
+
+static VAAPIEncodePicture *vaapi_encode_alloc(void)
+{
+    VAAPIEncodePicture *pic;
+
+    pic = av_mallocz(sizeof(*pic));
+    if (!pic)
+        return NULL;
+
+    pic->input_surface = VA_INVALID_ID;
+    pic->recon_surface = VA_INVALID_ID;
+    pic->output_buffer = VA_INVALID_ID;
+
+    return pic;
+}
+
+static int vaapi_encode_free(AVCodecContext *avctx,
+                             VAAPIEncodePicture *pic)
+{
+    int i;
+
+    if (pic->encode_issued)
+        vaapi_encode_discard(avctx, pic);
+
+    for (i = 0; i < pic->nb_slices; i++) {
+        av_freep(&pic->slices[i]->priv_data);
+        av_freep(&pic->slices[i]->codec_slice_params);
+        av_freep(&pic->slices[i]);
+    }
+    av_freep(&pic->codec_picture_params);
+
+    av_frame_free(&pic->input_image);
+    av_frame_free(&pic->recon_image);
+
+    // Output buffer should already be destroyed.
+    av_assert0(pic->output_buffer == VA_INVALID_ID);
+
+    av_freep(&pic->priv_data);
+    av_freep(&pic->codec_picture_params);
+
+    av_free(pic);
+
+    return 0;
+}
+
+static int vaapi_encode_step(AVCodecContext *avctx,
+                             VAAPIEncodePicture *target)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAAPIEncodePicture *pic;
+    int i, err;
+
+    if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING ||
+        ctx->issue_mode == ISSUE_MODE_MINIMISE_LATENCY) {
+        // These two modes are equivalent, except that we wait for
+        // immediate completion on each operation if serialised.
+
+        if (!target) {
+            // No target, nothing to do yet.
+            return 0;
+        }
+
+        if (target->encode_complete) {
+            // Already done.
+            return 0;
+        }
+
+        pic = target;
+        for (i = 0; i < pic->nb_refs; i++) {
+            if (!pic->refs[i]->encode_complete) {
+                err = vaapi_encode_step(avctx, pic->refs[i]);
+                if (err < 0)
+                    return err;
+            }
+        }
+
+        err = vaapi_encode_issue(avctx, pic);
+        if (err < 0)
+            return err;
+
+    } else if (ctx->issue_mode == ISSUE_MODE_MAXIMISE_THROUGHPUT) {
+        int activity;
+
+        do {
+            activity = 0;
+            for (pic = ctx->pic_start; pic; pic = pic->next) {
+                if (!pic->input_available || pic->encode_issued)
+                    continue;
+                for (i = 0; i < pic->nb_refs; i++) {
+                    if (!pic->refs[i]->encode_issued)
+                        break;
+                }
+                if (i < pic->nb_refs)
+                    continue;
+                err = vaapi_encode_issue(avctx, pic);
+                if (err < 0)
+                    return err;
+                activity = 1;
+            }
+        } while(activity);
+
+        if (target) {
+            av_assert0(target->encode_issued && "broken dependencies?");
+        }
+
+    } else {
+        av_assert0(0);
+    }
+
+    return 0;
+}
+
+static int vaapi_encode_get_next(AVCodecContext *avctx,
+                                 VAAPIEncodePicture **pic_out)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAAPIEncodePicture *start, *end, *pic;
+    int i;
+
+    for (pic = ctx->pic_start; pic; pic = pic->next) {
+        if (pic->next)
+            av_assert0(pic->display_order + 1 == pic->next->display_order);
+        if (pic->display_order == ctx->input_order) {
+            *pic_out = pic;
+            return 0;
+        }
+    }
+
+    if (ctx->input_order == 0) {
+        // First frame is always an IDR frame.
+        av_assert0(!ctx->pic_start && !ctx->pic_end);
+
+        pic = vaapi_encode_alloc();
+        if (!pic)
+            return AVERROR(ENOMEM);
+
+        pic->type = PICTURE_TYPE_IDR;
+        pic->display_order = 0;
+        pic->encode_order  = 0;
+
+        ctx->pic_start = ctx->pic_end = pic;
+
+        *pic_out = pic;
+        return 0;
+    }
+
+    pic = vaapi_encode_alloc();
+    if (!pic)
+        return AVERROR(ENOMEM);
+
+    if (ctx->p_per_i == 0 || ctx->p_counter == ctx->p_per_i) {
+        if (ctx->i_per_idr == 0 || ctx->i_counter == ctx->i_per_idr) {
+            pic->type = PICTURE_TYPE_IDR;
+            ctx->i_counter = 0;
+        } else {
+            pic->type = PICTURE_TYPE_I;
+            ++ctx->i_counter;
+        }
+        ctx->p_counter = 0;
+    } else {
+        pic->type = PICTURE_TYPE_P;
+        pic->refs[0] = ctx->pic_end;
+        pic->nb_refs = 1;
+        ++ctx->p_counter;
+    }
+    start = end = pic;
+
+    if (pic->type != PICTURE_TYPE_IDR) {
+        // If that was not an IDR frame, add B-frames display-before and
+        // encode-after it.
+
+        for (i = 0; i < ctx->b_per_p; i++) {
+            pic = vaapi_encode_alloc();
+            if (!pic)
+                goto fail;
+
+            pic->type = PICTURE_TYPE_B;
+            pic->refs[0] = ctx->pic_end;
+            pic->refs[1] = end;
+            pic->nb_refs = 2;
+
+            pic->next = start;
+            pic->display_order = ctx->input_order + ctx->b_per_p - i - 1;
+            pic->encode_order  = pic->display_order + 1;
+            start = pic;
+        }
+    }
+
+    for (i = 0, pic = start; pic; i++, pic = pic->next) {
+        pic->display_order = ctx->input_order + i;
+        if (end->type == PICTURE_TYPE_IDR)
+            pic->encode_order = ctx->input_order + i;
+        else if (pic == end)
+            pic->encode_order = ctx->input_order;
+        else
+            pic->encode_order = ctx->input_order + i + 1;
+    }
+
+    av_assert0(ctx->pic_end);
+    ctx->pic_end->next = start;
+    ctx->pic_end = end;
+
+    *pic_out = start;
+
+    av_log(avctx, AV_LOG_DEBUG, "Pictures:");
+    for (pic = ctx->pic_start; pic; pic = pic->next) {
+        av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")",
+               picture_type_name[pic->type],
+               pic->display_order, pic->encode_order);
+    }
+    av_log(avctx, AV_LOG_DEBUG, "\n");
+
+    return 0;
+
+fail:
+    while (start) {
+        pic = start->next;
+        vaapi_encode_free(avctx, start);
+        start = pic;
+    }
+    return AVERROR(ENOMEM);
+}
+
+static int vaapi_encode_mangle_end(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAAPIEncodePicture *pic, *last_pic, *next;
+
+    // Find the last picture we actually have input for.
+    for (pic = ctx->pic_start; pic; pic = pic->next) {
+        if (!pic->input_available)
+            break;
+        last_pic = pic;
+    }
+
+    if (pic) {
+        av_assert0(last_pic);
+
+        if (last_pic->type == PICTURE_TYPE_B) {
+            // Some fixing up is required.  Change the type of this
+            // picture to P, then modify preceding B references which
+            // point beyond it to point at it instead.
+
+            last_pic->type = PICTURE_TYPE_P;
+            last_pic->encode_order = last_pic->refs[1]->encode_order;
+
+            for (pic = ctx->pic_start; pic != last_pic; pic = pic->next) {
+                if (pic->type == PICTURE_TYPE_B &&
+                    pic->refs[1] == last_pic->refs[1])
+                    pic->refs[1] = last_pic;
+            }
+
+            last_pic->nb_refs = 1;
+            last_pic->refs[1] = NULL;
+        } else {
+            // We can use the current structure (no references point
+            // beyond the end), but there are unused pics to discard.
+        }
+
+        // Discard all following pics, they will never be used.
+        for (pic = last_pic->next; pic; pic = next) {
+            next = pic->next;
+            vaapi_encode_free(avctx, pic);
+        }
+
+        last_pic->next = NULL;
+        ctx->pic_end = last_pic;
+
+    } else {
+        // Input is available for all pictures, so we don't need to
+        // mangle anything.
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "Pictures at end of stream:");
+    for (pic = ctx->pic_start; pic; pic = pic->next) {
+        av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")",
+               picture_type_name[pic->type],
+               pic->display_order, pic->encode_order);
+    }
+    av_log(avctx, AV_LOG_DEBUG, "\n");
+
+    return 0;
+}
+
+static int vaapi_encode_clear_old(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAAPIEncodePicture *pic, *old;
+    int i;
+
+    while (ctx->pic_start != ctx->pic_end) {
+        old = ctx->pic_start;
+        if (old->encode_order > ctx->output_order)
+            break;
+
+        for (pic = old->next; pic; pic = pic->next) {
+            if (pic->encode_complete)
+                continue;
+            for (i = 0; i < pic->nb_refs; i++) {
+                if (pic->refs[i] == old) {
+                    // We still need this picture because it's referred to
+                    // directly by a later one, so it and all following
+                    // pictures have to stay.
+                    return 0;
+                }
+            }
+        }
+
+        pic = ctx->pic_start;
+        ctx->pic_start = pic->next;
+        vaapi_encode_free(avctx, pic);
+    }
+
+    return 0;
+}
+
+int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt,
+                     const AVFrame *input_image, int *got_packet)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAAPIEncodePicture *pic;
+    int err;
+
+    if (input_image) {
+        av_log(avctx, AV_LOG_DEBUG, "Encode frame: %ux%u (%"PRId64").\n",
+               input_image->width, input_image->height, input_image->pts);
+
+        err = vaapi_encode_get_next(avctx, &pic);
+        if (err) {
+            av_log(avctx, AV_LOG_ERROR, "Input setup failed: %d.\n", err);
+            return err;
+        }
+
+        pic->input_image = av_frame_alloc();
+        if (!pic->input_image) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+        err = av_frame_ref(pic->input_image, input_image);
+        if (err < 0)
+            goto fail;
+        pic->input_surface = (VASurfaceID)(uintptr_t)input_image->data[3];
+        pic->pts = input_image->pts;
+
+        if (ctx->input_order == 0)
+            ctx->first_pts = pic->pts;
+        if (ctx->input_order == ctx->decode_delay)
+            ctx->dts_pts_diff = pic->pts - ctx->first_pts;
+        if (ctx->output_delay > 0)
+            ctx->ts_ring[ctx->input_order % (3 * ctx->output_delay)] = pic->pts;
+
+        pic->input_available = 1;
+
+    } else {
+        if (!ctx->end_of_stream) {
+            err = vaapi_encode_mangle_end(avctx);
+            if (err < 0)
+                goto fail;
+            ctx->end_of_stream = 1;
+        }
+    }
+
+    ++ctx->input_order;
+    ++ctx->output_order;
+    av_assert0(ctx->output_order + ctx->output_delay + 1 == ctx->input_order);
+
+    for (pic = ctx->pic_start; pic; pic = pic->next)
+        if (pic->encode_order == ctx->output_order)
+            break;
+
+    // pic can be null here if we don't have a specific target in this
+    // iteration.  We might still issue encodes if things can be overlapped,
+    // even though we don't intend to output anything.
+
+    err = vaapi_encode_step(avctx, pic);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
+        goto fail;
+    }
+
+    if (!pic) {
+        *got_packet = 0;
+    } else {
+        err = vaapi_encode_output(avctx, pic, pkt);
+        if (err < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err);
+            goto fail;
+        }
+
+        if (ctx->output_delay == 0) {
+            pkt->dts = pkt->pts;
+        } else if (ctx->output_order < ctx->decode_delay) {
+            if (ctx->ts_ring[ctx->output_order] < INT64_MIN + ctx->dts_pts_diff)
+                pkt->dts = INT64_MIN;
+            else
+                pkt->dts = ctx->ts_ring[ctx->output_order] - ctx->dts_pts_diff;
+        } else {
+            pkt->dts = ctx->ts_ring[(ctx->output_order - ctx->decode_delay) %
+                                    (3 * ctx->output_delay)];
+        }
+
+        *got_packet = 1;
+    }
+
+    err = vaapi_encode_clear_old(avctx);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "List clearing failed: %d.\n", err);
+        goto fail;
+    }
+
+    return 0;
+
+fail:
+    // Unclear what to clean up on failure.  There are probably some things we
+    // could do usefully clean up here, but for now just leave them for uninit()
+    // to do instead.
+    return err;
+}
+
+static av_cold int vaapi_encode_check_config(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAStatus vas;
+    int i, n, err;
+    VAProfile    *profiles    = NULL;
+    VAEntrypoint *entrypoints = NULL;
+    VAConfigAttrib attr[] = {
+        { VAConfigAttribRateControl     },
+        { VAConfigAttribEncMaxRefFrames },
+    };
+
+    n = vaMaxNumProfiles(ctx->hwctx->display);
+    profiles = av_malloc_array(n, sizeof(VAProfile));
+    if (!profiles) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    vas = vaQueryConfigProfiles(ctx->hwctx->display, profiles, &n);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n",
+               vas, vaErrorStr(vas));
+        err = AVERROR(ENOSYS);
+        goto fail;
+    }
+    for (i = 0; i < n; i++) {
+        if (profiles[i] == ctx->va_profile)
+            break;
+    }
+    if (i >= n) {
+        av_log(ctx, AV_LOG_ERROR, "Encoding profile not found (%d).\n",
+               ctx->va_profile);
+        err = AVERROR(ENOSYS);
+        goto fail;
+    }
+
+    n = vaMaxNumEntrypoints(ctx->hwctx->display);
+    entrypoints = av_malloc_array(n, sizeof(VAEntrypoint));
+    if (!entrypoints) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile,
+                                   entrypoints, &n);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to query entrypoints for "
+               "profile %u: %d (%s).\n", ctx->va_profile,
+               vas, vaErrorStr(vas));
+        err = AVERROR(ENOSYS);
+        goto fail;
+    }
+    for (i = 0; i < n; i++) {
+        if (entrypoints[i] == ctx->va_entrypoint)
+            break;
+    }
+    if (i >= n) {
+        av_log(ctx, AV_LOG_ERROR, "Encoding entrypoint not found "
+               "(%d / %d).\n", ctx->va_profile, ctx->va_entrypoint);
+        err = AVERROR(ENOSYS);
+        goto fail;
+    }
+
+    vas = vaGetConfigAttributes(ctx->hwctx->display,
+                                ctx->va_profile, ctx->va_entrypoint,
+                                attr, FF_ARRAY_ELEMS(attr));
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to fetch config "
+               "attributes: %d (%s).\n", vas, vaErrorStr(vas));
+        return AVERROR(EINVAL);
+    }
+
+    for (i = 0; i < FF_ARRAY_ELEMS(attr); i++) {
+        if (attr[i].value == VA_ATTRIB_NOT_SUPPORTED) {
+            // Unfortunately we have to treat this as "don't know" and hope
+            // for the best, because the Intel MJPEG encoder returns this
+            // for all the interesting attributes.
+            continue;
+        }
+        switch (attr[i].type) {
+        case VAConfigAttribRateControl:
+            if (!(ctx->va_rc_mode & attr[i].value)) {
+                av_log(avctx, AV_LOG_ERROR, "Rate control mode is not "
+                       "supported: %x\n", attr[i].value);
+                err = AVERROR(EINVAL);
+                goto fail;
+            }
+            break;
+        case VAConfigAttribEncMaxRefFrames:
+        {
+            unsigned int ref_l0 = attr[i].value & 0xffff;
+            unsigned int ref_l1 = (attr[i].value >> 16) & 0xffff;
+
+            if (avctx->gop_size > 1 && ref_l0 < 1) {
+                av_log(avctx, AV_LOG_ERROR, "P frames are not "
+                       "supported (%x).\n", attr[i].value);
+                err = AVERROR(EINVAL);
+                goto fail;
+            }
+            if (avctx->max_b_frames > 0 && ref_l1 < 1) {
+                av_log(avctx, AV_LOG_ERROR, "B frames are not "
+                       "supported (%x).\n", attr[i].value);
+                err = AVERROR(EINVAL);
+                goto fail;
+            }
+        }
+        break;
+        }
+    }
+
+    err = 0;
+fail:
+    av_freep(&profiles);
+    av_freep(&entrypoints);
+    return err;
+}
+
+av_cold int ff_vaapi_encode_init(AVCodecContext *avctx,
+                                 const VAAPIEncodeType *type)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    AVVAAPIFramesContext *recon_hwctx = NULL;
+    AVVAAPIHWConfig *hwconfig = NULL;
+    AVHWFramesConstraints *constraints = NULL;
+    enum AVPixelFormat recon_format;
+    VAStatus vas;
+    int err, i;
+
+    if (!avctx->hw_frames_ctx) {
+        av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
+               "required to associate the encoding device.\n");
+        return AVERROR(EINVAL);
+    }
+
+    ctx->codec = type;
+    ctx->codec_options = ctx->codec_options_data;
+
+    ctx->va_config  = VA_INVALID_ID;
+    ctx->va_context = VA_INVALID_ID;
+
+    ctx->priv_data = av_mallocz(type->priv_data_size);
+    if (!ctx->priv_data) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx);
+    if (!ctx->input_frames_ref) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
+
+    ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
+    if (!ctx->device_ref) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
+    ctx->hwctx = ctx->device->hwctx;
+
+    err = ctx->codec->init(avctx);
+    if (err < 0)
+        goto fail;
+
+    err = vaapi_encode_check_config(avctx);
+    if (err < 0)
+        goto fail;
+
+    vas = vaCreateConfig(ctx->hwctx->display,
+                         ctx->va_profile, ctx->va_entrypoint,
+                         ctx->config_attributes, ctx->nb_config_attributes,
+                         &ctx->va_config);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
+               "configuration: %d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref);
+    if (!hwconfig) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    hwconfig->config_id = ctx->va_config;
+
+    constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref,
+                                                      hwconfig);
+    if (!constraints) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    // Probably we can use the input surface format as the surface format
+    // of the reconstructed frames.  If not, we just pick the first (only?)
+    // format in the valid list and hope that it all works.
+    recon_format = AV_PIX_FMT_NONE;
+    if (constraints->valid_sw_formats) {
+        for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
+            if (ctx->input_frames->sw_format ==
+                constraints->valid_sw_formats[i]) {
+                recon_format = ctx->input_frames->sw_format;
+                break;
+            }
+        }
+        if (recon_format == AV_PIX_FMT_NONE)
+            recon_format = constraints->valid_sw_formats[i];
+    } else {
+        // No idea what to use; copy input format.
+        recon_format = ctx->input_frames->sw_format;
+    }
+    av_log(avctx, AV_LOG_DEBUG, "Using %s as format of "
+           "reconstructed frames.\n", av_get_pix_fmt_name(recon_format));
+
+    if (ctx->aligned_width  < constraints->min_width  ||
+        ctx->aligned_height < constraints->min_height ||
+        ctx->aligned_width  > constraints->max_width ||
+        ctx->aligned_height > constraints->max_height) {
+        av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at "
+               "size %dx%d (constraints: width %d-%d height %d-%d).\n",
+               ctx->aligned_width, ctx->aligned_height,
+               constraints->min_width,  constraints->max_width,
+               constraints->min_height, constraints->max_height);
+        err = AVERROR(EINVAL);
+        goto fail;
+    }
+
+    av_freep(&hwconfig);
+    av_hwframe_constraints_free(&constraints);
+
+    ctx->recon_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
+    if (!ctx->recon_frames_ref) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    ctx->recon_frames = (AVHWFramesContext*)ctx->recon_frames_ref->data;
+
+    ctx->recon_frames->format    = AV_PIX_FMT_VAAPI;
+    ctx->recon_frames->sw_format = recon_format;
+    ctx->recon_frames->width     = ctx->aligned_width;
+    ctx->recon_frames->height    = ctx->aligned_height;
+    ctx->recon_frames->initial_pool_size = ctx->nb_recon_frames;
+
+    err = av_hwframe_ctx_init(ctx->recon_frames_ref);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed "
+               "frame context: %d.\n", err);
+        goto fail;
+    }
+    recon_hwctx = ctx->recon_frames->hwctx;
+
+    vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
+                          ctx->aligned_width, ctx->aligned_height,
+                          VA_PROGRESSIVE,
+                          recon_hwctx->surface_ids,
+                          recon_hwctx->nb_surfaces,
+                          &ctx->va_context);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
+               "context: %d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    ctx->input_order  = 0;
+    ctx->output_delay = avctx->max_b_frames;
+    ctx->decode_delay = 1;
+    ctx->output_order = - ctx->output_delay - 1;
+
+    if (ctx->codec->sequence_params_size > 0) {
+        ctx->codec_sequence_params =
+            av_mallocz(ctx->codec->sequence_params_size);
+        if (!ctx->codec_sequence_params) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+    if (ctx->codec->picture_params_size > 0) {
+        ctx->codec_picture_params =
+            av_mallocz(ctx->codec->picture_params_size);
+        if (!ctx->codec_picture_params) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+
+    if (ctx->codec->init_sequence_params) {
+        err = ctx->codec->init_sequence_params(avctx);
+        if (err < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Codec sequence initialisation "
+                   "failed: %d.\n", err);
+            goto fail;
+        }
+    }
+
+    // All I are IDR for now.
+    ctx->i_per_idr = 0;
+    ctx->p_per_i = ((avctx->gop_size + avctx->max_b_frames) /
+                    (avctx->max_b_frames + 1));
+    ctx->b_per_p = avctx->max_b_frames;
+
+    // This should be configurable somehow.  (Needs testing on a machine
+    // where it actually overlaps properly, though.)
+    ctx->issue_mode = ISSUE_MODE_MAXIMISE_THROUGHPUT;
+
+    return 0;
+
+fail:
+    av_freep(&hwconfig);
+    av_hwframe_constraints_free(&constraints);
+    ff_vaapi_encode_close(avctx);
+    return err;
+}
+
+av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    VAAPIEncodePicture *pic, *next;
+
+    for (pic = ctx->pic_start; pic; pic = next) {
+        next = pic->next;
+        vaapi_encode_free(avctx, pic);
+    }
+
+    if (ctx->va_context != VA_INVALID_ID) {
+        vaDestroyContext(ctx->hwctx->display, ctx->va_context);
+        ctx->va_context = VA_INVALID_ID;
+    }
+
+    if (ctx->va_config != VA_INVALID_ID) {
+        vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
+        ctx->va_config = VA_INVALID_ID;
+    }
+
+    if (ctx->codec->close)
+        ctx->codec->close(avctx);
+
+    av_freep(&ctx->codec_sequence_params);
+    av_freep(&ctx->codec_picture_params);
+
+    av_buffer_unref(&ctx->recon_frames_ref);
+    av_buffer_unref(&ctx->input_frames_ref);
+    av_buffer_unref(&ctx->device_ref);
+
+    av_freep(&ctx->priv_data);
+
+    return 0;
+}
diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
new file mode 100644
index 0000000..b67168b
--- /dev/null
+++ b/libavcodec/vaapi_encode.h
@@ -0,0 +1,228 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VAAPI_ENCODE_H
+#define AVCODEC_VAAPI_ENCODE_H
+
+#include <stdint.h>
+
+#include <va/va.h>
+
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_vaapi.h"
+
+#include "avcodec.h"
+
+struct VAAPIEncodeType;
+struct VAAPIEncodePicture;
+
+enum {
+    MAX_CONFIG_ATTRIBUTES  = 4,
+    MAX_GLOBAL_PARAMS      = 4,
+    MAX_PICTURE_REFERENCES = 2,
+    MAX_PICTURE_SLICES     = 1,
+    MAX_PARAM_BUFFERS      = 16,
+    MAX_REORDER_DELAY      = 16,
+    MAX_PARAM_BUFFER_SIZE  = 1024,
+    MAX_OUTPUT_BUFFER_SIZE = 1024 * 1024,
+};
+
+enum {
+    PICTURE_TYPE_IDR = 0,
+    PICTURE_TYPE_I   = 1,
+    PICTURE_TYPE_P   = 2,
+    PICTURE_TYPE_B   = 3,
+};
+
+enum {
+    // All encode operations are done independently.
+    ISSUE_MODE_SERIALISE_EVERYTHING = 0,
+    // Overlap as many operations as possible.
+    ISSUE_MODE_MAXIMISE_THROUGHPUT,
+    // Overlap operations only when satisfying parallel dependencies.
+    ISSUE_MODE_MINIMISE_LATENCY,
+};
+
+typedef struct VAAPIEncodeSlice {
+    void           *priv_data;
+    void           *codec_slice_params;
+} VAAPIEncodeSlice;
+
+typedef struct VAAPIEncodePicture {
+    struct VAAPIEncodePicture *next;
+
+    int64_t         display_order;
+    int64_t         encode_order;
+    int64_t         pts;
+
+    int             type;
+    int             input_available;
+    int             encode_issued;
+    int             encode_complete;
+
+    AVFrame        *input_image;
+    VASurfaceID     input_surface;
+
+    AVFrame        *recon_image;
+    VASurfaceID     recon_surface;
+
+    int          nb_param_buffers;
+    VABufferID      param_buffers[MAX_PARAM_BUFFERS];
+
+    VABufferID      output_buffer;
+
+    void           *priv_data;
+    void           *codec_picture_params;
+
+    int          nb_refs;
+    struct VAAPIEncodePicture *refs[MAX_PICTURE_REFERENCES];
+
+    int          nb_slices;
+    VAAPIEncodeSlice *slices[MAX_PICTURE_SLICES];
+} VAAPIEncodePicture;
+
+typedef struct VAAPIEncodeContext {
+    const AVClass *class;
+
+    // Codec-specific hooks.
+    const struct VAAPIEncodeType *codec;
+
+    // Codec-specific state.
+    void *priv_data;
+
+    VAProfile       va_profile;
+    VAEntrypoint    va_entrypoint;
+    VAConfigID      va_config;
+    VAContextID     va_context;
+
+    int             va_rc_mode;
+
+    AVBufferRef    *device_ref;
+    AVHWDeviceContext *device;
+    AVVAAPIDeviceContext *hwctx;
+
+    AVBufferRef    *input_frames_ref;
+    AVHWFramesContext *input_frames;
+
+    // Input size, set from input frames.
+    int             input_width;
+    int             input_height;
+    // Aligned size, set by codec init, becomes hwframe size.
+    int             aligned_width;
+    int             aligned_height;
+
+    int          nb_recon_frames;
+    AVBufferRef    *recon_frames_ref;
+    AVHWFramesContext *recon_frames;
+
+    VAConfigAttrib  config_attributes[MAX_CONFIG_ATTRIBUTES];
+    int          nb_config_attributes;
+
+    VAEncMiscParameterBuffer *global_params[MAX_GLOBAL_PARAMS];
+    size_t          global_params_size[MAX_GLOBAL_PARAMS];
+    int          nb_global_params;
+
+    // Per-sequence parameter structure (VAEncSequenceParameterBuffer*).
+    void           *codec_sequence_params;
+
+    // Per-sequence parameters found in the per-picture parameter
+    // structure (VAEncPictureParameterBuffer*).
+    void           *codec_picture_params;
+
+    // Current encoding window, in display (input) order.
+    VAAPIEncodePicture *pic_start, *pic_end;
+
+    // Next input order index (display order).
+    int64_t         input_order;
+    // Number of frames that output is behind input.
+    int64_t         output_delay;
+    // Number of frames decode output will need to be delayed.
+    int64_t         decode_delay;
+    // Next output order index (encode order).
+    int64_t         output_order;
+
+    int             issue_mode;
+
+    // Timestamp handling.
+    int64_t         first_pts;
+    int64_t         dts_pts_diff;
+    int64_t         ts_ring[MAX_REORDER_DELAY * 3];
+
+    // Frame type decision.
+    int i_per_idr;
+    int p_per_i;
+    int b_per_p;
+    int idr_counter;
+    int i_counter;
+    int p_counter;
+    int end_of_stream;
+
+    // Codec-local options are allocated to follow this structure in
+    // memory (in the AVCodec definition, set priv_data_size to
+    // sizeof(VAAPIEncodeContext) + sizeof(VAAPIEncodeFooOptions)).
+    void *codec_options;
+    char codec_options_data[0];
+} VAAPIEncodeContext;
+
+
+typedef struct VAAPIEncodeType {
+    size_t    priv_data_size;
+
+    int  (*init)(AVCodecContext *avctx);
+    int (*close)(AVCodecContext *avctx);
+
+    size_t sequence_params_size;
+    size_t picture_params_size;
+    size_t slice_params_size;
+
+    int  (*init_sequence_params)(AVCodecContext *avctx);
+    int   (*init_picture_params)(AVCodecContext *avctx,
+                                 VAAPIEncodePicture *pic);
+    int     (*init_slice_params)(AVCodecContext *avctx,
+                                 VAAPIEncodePicture *pic,
+                                 VAAPIEncodeSlice *slice);
+
+    int sequence_header_type;
+    int picture_header_type;
+    int slice_header_type;
+
+    int (*write_sequence_header)(AVCodecContext *avctx,
+                                 char *data, size_t *data_len);
+    int  (*write_picture_header)(AVCodecContext *avctx,
+                                 VAAPIEncodePicture *pic,
+                                 char *data, size_t *data_len);
+    int    (*write_slice_header)(AVCodecContext *avctx,
+                                 VAAPIEncodePicture *pic,
+                                 VAAPIEncodeSlice *slice,
+                                 char *data, size_t *data_len);
+
+    int    (*write_extra_buffer)(AVCodecContext *avctx,
+                                 VAAPIEncodePicture *pic,
+                                 int index, int *type,
+                                 char *data, size_t *data_len);
+} VAAPIEncodeType;
+
+
+int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt,
+                     const AVFrame *input_image, int *got_packet);
+
+int ff_vaapi_encode_init(AVCodecContext *avctx,
+                         const VAAPIEncodeType *type);
+int ff_vaapi_encode_close(AVCodecContext *avctx);
+
+#endif /* AVCODEC_VAAPI_ENCODE_H */
diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
new file mode 100644
index 0000000..39e2ec0
--- /dev/null
+++ b/libavcodec/vaapi_encode_h264.c
@@ -0,0 +1,1001 @@
+/*
+ * 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 <va/va.h>
+#include <va/va_enc_h264.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixfmt.h"
+
+#include "avcodec.h"
+#include "h264.h"
+#include "internal.h"
+#include "vaapi_encode.h"
+#include "vaapi_encode_h26x.h"
+
+enum {
+    SLICE_TYPE_P  = 0,
+    SLICE_TYPE_B  = 1,
+    SLICE_TYPE_I  = 2,
+    SLICE_TYPE_SP = 3,
+    SLICE_TYPE_SI = 4,
+};
+
+// This structure contains all possibly-useful per-sequence syntax elements
+// which are not already contained in the various VAAPI structures.
+typedef struct VAAPIEncodeH264MiscSequenceParams {
+    unsigned int profile_idc;
+    char constraint_set0_flag;
+    char constraint_set1_flag;
+    char constraint_set2_flag;
+    char constraint_set3_flag;
+    char constraint_set4_flag;
+    char constraint_set5_flag;
+
+    char separate_colour_plane_flag;
+    char qpprime_y_zero_transform_bypass_flag;
+
+    char gaps_in_frame_num_allowed_flag;
+    char delta_pic_order_always_zero_flag;
+    char bottom_field_pic_order_in_frame_present_flag;
+
+    unsigned int num_slice_groups_minus1;
+    unsigned int slice_group_map_type;
+
+    int pic_init_qs_minus26;
+
+    char vui_parameters_present_flag;
+} VAAPIEncodeH264MiscSequenceParams;
+
+// This structure contains all possibly-useful per-slice syntax elements
+// which are not already contained in the various VAAPI structures.
+typedef struct VAAPIEncodeH264MiscSliceParams {
+    unsigned int nal_unit_type;
+    unsigned int nal_ref_idc;
+
+    unsigned int colour_plane_id;
+    char field_pic_flag;
+    char bottom_field_flag;
+
+    unsigned int redundant_pic_cnt;
+
+    char sp_for_switch_flag;
+    int slice_qs_delta;
+
+    char ref_pic_list_modification_flag_l0;
+    char ref_pic_list_modification_flag_l1;
+
+    char no_output_of_prior_pics_flag;
+    char long_term_reference_flag;
+    char adaptive_ref_pic_marking_mode_flag;
+} VAAPIEncodeH264MiscSliceParams;
+
+typedef struct VAAPIEncodeH264Slice {
+    VAAPIEncodeH264MiscSliceParams misc_slice_params;
+} VAAPIEncodeH264Slice;
+
+typedef struct VAAPIEncodeH264Context {
+    VAAPIEncodeH264MiscSequenceParams misc_sequence_params;
+
+    int mb_width;
+    int mb_height;
+
+    int fixed_qp_idr;
+    int fixed_qp_p;
+    int fixed_qp_b;
+
+    int next_frame_num;
+    int64_t idr_pic_count;
+
+    // Rate control configuration.
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterRateControl rc;
+    } rc_params;
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterHRD hrd;
+    } hrd_params;
+
+#if VA_CHECK_VERSION(0, 36, 0)
+    // Speed-quality tradeoff setting.
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterBufferQualityLevel quality;
+    } quality_params;
+#endif
+} VAAPIEncodeH264Context;
+
+typedef struct VAAPIEncodeH264Options {
+    int qp;
+    int quality;
+    int low_power;
+} VAAPIEncodeH264Options;
+
+
+#define vseq_var(name)     vseq->name, name
+#define vseq_field(name)   vseq->seq_fields.bits.name, name
+#define vpic_var(name)     vpic->name, name
+#define vpic_field(name)   vpic->pic_fields.bits.name, name
+#define vslice_var(name)   vslice->name, name
+#define vslice_field(name) vslice->slice_fields.bits.name, name
+#define mseq_var(name)     mseq->name, name
+#define mslice_var(name)   mslice->name, name
+
+static void vaapi_encode_h264_write_nal_header(PutBitContext *pbc,
+                                               int nal_unit_type, int nal_ref_idc)
+{
+    u(1, 0, forbidden_zero_bit);
+    u(2, nal_ref_idc, nal_ref_idc);
+    u(5, nal_unit_type, nal_unit_type);
+}
+
+static void vaapi_encode_h264_write_trailing_rbsp(PutBitContext *pbc)
+{
+    u(1, 1, rbsp_stop_one_bit);
+    while (put_bits_count(pbc) & 7)
+        u(1, 0, rbsp_alignment_zero_bit);
+}
+
+static void vaapi_encode_h264_write_sps(PutBitContext *pbc,
+                                        VAAPIEncodeContext *ctx)
+{
+    VAEncSequenceParameterBufferH264  *vseq = ctx->codec_sequence_params;
+    VAAPIEncodeH264Context            *priv = ctx->priv_data;
+    VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
+    int i;
+
+    vaapi_encode_h264_write_nal_header(pbc, NAL_SPS, 3);
+
+    u(8, mseq_var(profile_idc));
+    u(1, mseq_var(constraint_set0_flag));
+    u(1, mseq_var(constraint_set1_flag));
+    u(1, mseq_var(constraint_set2_flag));
+    u(1, mseq_var(constraint_set3_flag));
+    u(1, mseq_var(constraint_set4_flag));
+    u(1, mseq_var(constraint_set5_flag));
+    u(2, 0, reserved_zero_2bits);
+
+    u(8, vseq_var(level_idc));
+
+    ue(vseq_var(seq_parameter_set_id));
+
+    if (mseq->profile_idc == 100 || mseq->profile_idc == 110 ||
+        mseq->profile_idc == 122 || mseq->profile_idc == 244 ||
+        mseq->profile_idc ==  44 || mseq->profile_idc ==  83 ||
+        mseq->profile_idc ==  86 || mseq->profile_idc == 118 ||
+        mseq->profile_idc == 128 || mseq->profile_idc == 138) {
+        ue(vseq_field(chroma_format_idc));
+
+        if (vseq->seq_fields.bits.chroma_format_idc == 3)
+            u(1, mseq_var(separate_colour_plane_flag));
+
+        ue(vseq_var(bit_depth_luma_minus8));
+        ue(vseq_var(bit_depth_chroma_minus8));
+
+        u(1, mseq_var(qpprime_y_zero_transform_bypass_flag));
+
+        u(1, vseq_field(seq_scaling_matrix_present_flag));
+        if (vseq->seq_fields.bits.seq_scaling_matrix_present_flag) {
+            av_assert0(0 && "scaling matrices not supported");
+        }
+    }
+
+    ue(vseq_field(log2_max_frame_num_minus4));
+    ue(vseq_field(pic_order_cnt_type));
+
+    if (vseq->seq_fields.bits.pic_order_cnt_type == 0) {
+        ue(vseq_field(log2_max_pic_order_cnt_lsb_minus4));
+    } else if (vseq->seq_fields.bits.pic_order_cnt_type == 1) {
+        u(1, mseq_var(delta_pic_order_always_zero_flag));
+        se(vseq_var(offset_for_non_ref_pic));
+        se(vseq_var(offset_for_top_to_bottom_field));
+        ue(vseq_var(num_ref_frames_in_pic_order_cnt_cycle));
+
+        for (i = 0; i < vseq->num_ref_frames_in_pic_order_cnt_cycle; i++)
+            se(vseq_var(offset_for_ref_frame[i]));
+    }
+
+    ue(vseq_var(max_num_ref_frames));
+    u(1, mseq_var(gaps_in_frame_num_allowed_flag));
+
+    ue(vseq->picture_width_in_mbs  - 1, pic_width_in_mbs_minus1);
+    ue(vseq->picture_height_in_mbs - 1, pic_height_in_mbs_minus1);
+
+    u(1, vseq_field(frame_mbs_only_flag));
+    if (!vseq->seq_fields.bits.frame_mbs_only_flag)
+        u(1, vseq_field(mb_adaptive_frame_field_flag));
+
+    u(1, vseq_field(direct_8x8_inference_flag));
+
+    u(1, vseq_var(frame_cropping_flag));
+    if (vseq->frame_cropping_flag) {
+        ue(vseq_var(frame_crop_left_offset));
+        ue(vseq_var(frame_crop_right_offset));
+        ue(vseq_var(frame_crop_top_offset));
+        ue(vseq_var(frame_crop_bottom_offset));
+    }
+
+    u(1, mseq_var(vui_parameters_present_flag));
+
+    vaapi_encode_h264_write_trailing_rbsp(pbc);
+}
+
+static void vaapi_encode_h264_write_pps(PutBitContext *pbc,
+                                        VAAPIEncodeContext *ctx)
+{
+    VAEncPictureParameterBufferH264   *vpic = ctx->codec_picture_params;
+    VAAPIEncodeH264Context            *priv = ctx->priv_data;
+    VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
+
+    vaapi_encode_h264_write_nal_header(pbc, NAL_PPS, 3);
+
+    ue(vpic_var(pic_parameter_set_id));
+    ue(vpic_var(seq_parameter_set_id));
+
+    u(1, vpic_field(entropy_coding_mode_flag));
+    u(1, mseq_var(bottom_field_pic_order_in_frame_present_flag));
+
+    ue(mseq_var(num_slice_groups_minus1));
+    if (mseq->num_slice_groups_minus1 > 0) {
+        ue(mseq_var(slice_group_map_type));
+        av_assert0(0 && "slice groups not supported");
+    }
+
+    ue(vpic_var(num_ref_idx_l0_active_minus1));
+    ue(vpic_var(num_ref_idx_l1_active_minus1));
+
+    u(1, vpic_field(weighted_pred_flag));
+    u(2, vpic_field(weighted_bipred_idc));
+
+    se(vpic->pic_init_qp - 26, pic_init_qp_minus26);
+    se(mseq_var(pic_init_qs_minus26));
+    se(vpic_var(chroma_qp_index_offset));
+
+    u(1, vpic_field(deblocking_filter_control_present_flag));
+    u(1, vpic_field(constrained_intra_pred_flag));
+    u(1, vpic_field(redundant_pic_cnt_present_flag));
+    u(1, vpic_field(transform_8x8_mode_flag));
+
+    u(1, vpic_field(pic_scaling_matrix_present_flag));
+    if (vpic->pic_fields.bits.pic_scaling_matrix_present_flag) {
+        av_assert0(0 && "scaling matrices not supported");
+    }
+
+    se(vpic_var(second_chroma_qp_index_offset));
+
+    vaapi_encode_h264_write_trailing_rbsp(pbc);
+}
+
+static void vaapi_encode_h264_write_slice_header2(PutBitContext *pbc,
+                                                  VAAPIEncodeContext *ctx,
+                                                  VAAPIEncodePicture *pic,
+                                                  VAAPIEncodeSlice *slice)
+{
+    VAEncSequenceParameterBufferH264  *vseq = ctx->codec_sequence_params;
+    VAEncPictureParameterBufferH264   *vpic = pic->codec_picture_params;
+    VAEncSliceParameterBufferH264   *vslice = slice->codec_slice_params;
+    VAAPIEncodeH264Context            *priv = ctx->priv_data;
+    VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
+    VAAPIEncodeH264Slice            *pslice = slice->priv_data;
+    VAAPIEncodeH264MiscSliceParams  *mslice = &pslice->misc_slice_params;
+
+    vaapi_encode_h264_write_nal_header(pbc, mslice->nal_unit_type,
+                                       mslice->nal_ref_idc);
+
+    ue(vslice->macroblock_address, first_mb_in_slice);
+    ue(vslice_var(slice_type));
+    ue(vpic_var(pic_parameter_set_id));
+
+    if (mseq->separate_colour_plane_flag) {
+        u(2, mslice_var(colour_plane_id));
+    }
+
+    u(4 + vseq->seq_fields.bits.log2_max_frame_num_minus4,
+      (vpic->frame_num &
+       ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1)),
+      frame_num);
+
+    if (!vseq->seq_fields.bits.frame_mbs_only_flag) {
+        u(1, mslice_var(field_pic_flag));
+        if (mslice->field_pic_flag)
+            u(1, mslice_var(bottom_field_flag));
+    }
+
+    if (vpic->pic_fields.bits.idr_pic_flag) {
+        ue(vslice_var(idr_pic_id));
+    }
+
+    if (vseq->seq_fields.bits.pic_order_cnt_type == 0) {
+        u(4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4,
+          vslice_var(pic_order_cnt_lsb));
+        if (mseq->bottom_field_pic_order_in_frame_present_flag &&
+            !mslice->field_pic_flag) {
+            se(vslice_var(delta_pic_order_cnt_bottom));
+        }
+    }
+
+    if (vseq->seq_fields.bits.pic_order_cnt_type == 1 &&
+        !vseq->seq_fields.bits.delta_pic_order_always_zero_flag) {
+        se(vslice_var(delta_pic_order_cnt[0]));
+        if (mseq->bottom_field_pic_order_in_frame_present_flag &&
+            !mslice->field_pic_flag) {
+            se(vslice_var(delta_pic_order_cnt[1]));
+        }
+    }
+
+    if (vpic->pic_fields.bits.redundant_pic_cnt_present_flag) {
+        ue(mslice_var(redundant_pic_cnt));
+    }
+
+    if (vslice->slice_type == SLICE_TYPE_B) {
+        u(1, vslice_var(direct_spatial_mv_pred_flag));
+    }
+
+    if (vslice->slice_type == SLICE_TYPE_P ||
+        vslice->slice_type == SLICE_TYPE_SP ||
+        vslice->slice_type == SLICE_TYPE_B) {
+        u(1, vslice_var(num_ref_idx_active_override_flag));
+        if (vslice->num_ref_idx_active_override_flag) {
+            ue(vslice_var(num_ref_idx_l0_active_minus1));
+            if (vslice->slice_type == SLICE_TYPE_B)
+                ue(vslice_var(num_ref_idx_l1_active_minus1));
+        }
+    }
+
+    if (mslice->nal_unit_type == 20 || mslice->nal_unit_type == 21) {
+        av_assert0(0 && "no MVC support");
+    } else {
+        if (vslice->slice_type % 5 != 2 && vslice->slice_type % 5 != 4) {
+            u(1, mslice_var(ref_pic_list_modification_flag_l0));
+            if (mslice->ref_pic_list_modification_flag_l0) {
+                av_assert0(0 && "ref pic list modification");
+            }
+        }
+        if (vslice->slice_type % 5 == 1) {
+            u(1, mslice_var(ref_pic_list_modification_flag_l1));
+            if (mslice->ref_pic_list_modification_flag_l1) {
+                av_assert0(0 && "ref pic list modification");
+            }
+        }
+    }
+
+    if ((vpic->pic_fields.bits.weighted_pred_flag &&
+         (vslice->slice_type == SLICE_TYPE_P ||
+          vslice->slice_type == SLICE_TYPE_SP)) ||
+        (vpic->pic_fields.bits.weighted_bipred_idc == 1 &&
+         vslice->slice_type == SLICE_TYPE_B)) {
+        av_assert0(0 && "prediction weights not supported");
+    }
+
+    av_assert0(mslice->nal_ref_idc > 0 ==
+               vpic->pic_fields.bits.reference_pic_flag);
+    if (mslice->nal_ref_idc != 0) {
+        if (vpic->pic_fields.bits.idr_pic_flag) {
+            u(1, mslice_var(no_output_of_prior_pics_flag));
+            u(1, mslice_var(long_term_reference_flag));
+        } else {
+            u(1, mslice_var(adaptive_ref_pic_marking_mode_flag));
+            if (mslice->adaptive_ref_pic_marking_mode_flag) {
+                av_assert0(0 && "MMCOs not supported");
+            }
+        }
+    }
+
+    if (vpic->pic_fields.bits.entropy_coding_mode_flag &&
+        vslice->slice_type != SLICE_TYPE_I &&
+        vslice->slice_type != SLICE_TYPE_SI) {
+        ue(vslice_var(cabac_init_idc));
+    }
+
+    se(vslice_var(slice_qp_delta));
+    if (vslice->slice_type == SLICE_TYPE_SP ||
+        vslice->slice_type == SLICE_TYPE_SI) {
+        if (vslice->slice_type == SLICE_TYPE_SP)
+            u(1, mslice_var(sp_for_switch_flag));
+        se(mslice_var(slice_qs_delta));
+    }
+
+    if (vpic->pic_fields.bits.deblocking_filter_control_present_flag) {
+        ue(vslice_var(disable_deblocking_filter_idc));
+        if (vslice->disable_deblocking_filter_idc != 1) {
+            se(vslice_var(slice_alpha_c0_offset_div2));
+            se(vslice_var(slice_beta_offset_div2));
+        }
+    }
+
+    if (mseq->num_slice_groups_minus1 > 0 &&
+        mseq->slice_group_map_type >= 3 && mseq->slice_group_map_type <= 5) {
+        av_assert0(0 && "slice groups not supported");
+    }
+
+    // No alignment - this need not be a byte boundary.
+}
+
+static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx,
+                                                   char *data, size_t *data_len)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    PutBitContext pbc;
+    char tmp[256];
+    int err;
+    size_t nal_len, bit_len, bit_pos, next_len;
+
+    bit_len = *data_len;
+    bit_pos = 0;
+
+    init_put_bits(&pbc, tmp, sizeof(tmp));
+    vaapi_encode_h264_write_sps(&pbc, ctx);
+    nal_len = put_bits_count(&pbc);
+    flush_put_bits(&pbc);
+
+    next_len = bit_len - bit_pos;
+    err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8,
+                                                       &next_len,
+                                                       tmp, nal_len);
+    if (err < 0)
+        return err;
+    bit_pos += next_len;
+
+    init_put_bits(&pbc, tmp, sizeof(tmp));
+    vaapi_encode_h264_write_pps(&pbc, ctx);
+    nal_len = put_bits_count(&pbc);
+    flush_put_bits(&pbc);
+
+    next_len = bit_len - bit_pos;
+    err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8,
+                                                       &next_len,
+                                                       tmp, nal_len);
+    if (err < 0)
+        return err;
+    bit_pos += next_len;
+
+    *data_len = bit_pos;
+    return 0;
+}
+
+static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx,
+                                                VAAPIEncodePicture *pic,
+                                                VAAPIEncodeSlice *slice,
+                                                char *data, size_t *data_len)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    PutBitContext pbc;
+    char tmp[256];
+    size_t header_len;
+
+    init_put_bits(&pbc, tmp, sizeof(tmp));
+    vaapi_encode_h264_write_slice_header2(&pbc, ctx, pic, slice);
+    header_len = put_bits_count(&pbc);
+    flush_put_bits(&pbc);
+
+    return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len,
+                                                        tmp, header_len);
+}
+
+static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext                 *ctx = avctx->priv_data;
+    VAEncSequenceParameterBufferH264  *vseq = ctx->codec_sequence_params;
+    VAEncPictureParameterBufferH264   *vpic = ctx->codec_picture_params;
+    VAAPIEncodeH264Context            *priv = ctx->priv_data;
+    VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
+    int i;
+
+    {
+        vseq->seq_parameter_set_id = 0;
+
+        vseq->level_idc = avctx->level;
+
+        vseq->max_num_ref_frames = 2;
+
+        vseq->picture_width_in_mbs  = priv->mb_width;
+        vseq->picture_height_in_mbs = priv->mb_height;
+
+        vseq->seq_fields.bits.chroma_format_idc = 1;
+        vseq->seq_fields.bits.frame_mbs_only_flag = 1;
+        vseq->seq_fields.bits.direct_8x8_inference_flag = 1;
+        vseq->seq_fields.bits.log2_max_frame_num_minus4 = 4;
+        vseq->seq_fields.bits.pic_order_cnt_type = 0;
+
+        if (ctx->input_width  != ctx->aligned_width ||
+            ctx->input_height != ctx->aligned_height) {
+            vseq->frame_cropping_flag = 1;
+
+            vseq->frame_crop_left_offset   = 0;
+            vseq->frame_crop_right_offset  =
+                (ctx->aligned_width - ctx->input_width) / 2;
+            vseq->frame_crop_top_offset    = 0;
+            vseq->frame_crop_bottom_offset =
+                (ctx->aligned_height - ctx->input_height) / 2;
+        } else {
+            vseq->frame_cropping_flag = 0;
+        }
+
+        vseq->bits_per_second = avctx->bit_rate;
+        if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
+            vseq->num_units_in_tick = avctx->framerate.num;
+            vseq->time_scale        = 2 * avctx->framerate.den;
+        } else {
+            vseq->num_units_in_tick = avctx->time_base.num;
+            vseq->time_scale        = 2 * avctx->time_base.den;
+        }
+
+        vseq->intra_period     = ctx->p_per_i * (ctx->b_per_p + 1);
+        vseq->intra_idr_period = vseq->intra_period;
+        vseq->ip_period        = ctx->b_per_p + 1;
+    }
+
+    {
+        vpic->CurrPic.picture_id = VA_INVALID_ID;
+        vpic->CurrPic.flags      = VA_PICTURE_H264_INVALID;
+
+        for (i = 0; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) {
+            vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID;
+            vpic->ReferenceFrames[i].flags      = VA_PICTURE_H264_INVALID;
+        }
+
+        vpic->coded_buf = VA_INVALID_ID;
+
+        vpic->pic_parameter_set_id = 0;
+        vpic->seq_parameter_set_id = 0;
+
+        vpic->num_ref_idx_l0_active_minus1 = 0;
+        vpic->num_ref_idx_l1_active_minus1 = 0;
+
+        vpic->pic_fields.bits.entropy_coding_mode_flag =
+            ((avctx->profile & 0xff) != 66);
+        vpic->pic_fields.bits.weighted_pred_flag = 0;
+        vpic->pic_fields.bits.weighted_bipred_idc = 0;
+        vpic->pic_fields.bits.transform_8x8_mode_flag =
+            ((avctx->profile & 0xff) >= 100);
+
+        vpic->pic_init_qp = priv->fixed_qp_idr;
+    }
+
+    {
+        mseq->profile_idc = avctx->profile & 0xff;
+
+        if (avctx->profile & FF_PROFILE_H264_CONSTRAINED)
+            mseq->constraint_set1_flag = 1;
+        if (avctx->profile & FF_PROFILE_H264_INTRA)
+            mseq->constraint_set3_flag = 1;
+    }
+
+    return 0;
+}
+
+static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx,
+                                                 VAAPIEncodePicture *pic)
+{
+    VAAPIEncodeContext                *ctx = avctx->priv_data;
+    VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
+    VAEncPictureParameterBufferH264  *vpic = pic->codec_picture_params;
+    VAAPIEncodeH264Context           *priv = ctx->priv_data;
+    int i;
+
+    if (pic->type == PICTURE_TYPE_IDR) {
+        av_assert0(pic->display_order == pic->encode_order);
+        vpic->frame_num = 0;
+        priv->next_frame_num = 1;
+    } else {
+        vpic->frame_num = priv->next_frame_num;
+        if (pic->type != PICTURE_TYPE_B) {
+            // nal_ref_idc != 0
+            ++priv->next_frame_num;
+        }
+    }
+
+    vpic->frame_num = vpic->frame_num &
+        ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1);
+
+    vpic->CurrPic.picture_id          = pic->recon_surface;
+    vpic->CurrPic.frame_idx           = vpic->frame_num;
+    vpic->CurrPic.flags               = 0;
+    vpic->CurrPic.TopFieldOrderCnt    = pic->display_order;
+    vpic->CurrPic.BottomFieldOrderCnt = pic->display_order;
+
+    for (i = 0; i < pic->nb_refs; i++) {
+        VAAPIEncodePicture *ref = pic->refs[i];
+        av_assert0(ref && ref->encode_order < pic->encode_order);
+        vpic->ReferenceFrames[i].picture_id = ref->recon_surface;
+        vpic->ReferenceFrames[i].frame_idx  = ref->encode_order;
+        vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
+        vpic->ReferenceFrames[i].TopFieldOrderCnt    = ref->display_order;
+        vpic->ReferenceFrames[i].BottomFieldOrderCnt = ref->display_order;
+    }
+    for (; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) {
+        vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID;
+        vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
+    }
+
+    vpic->coded_buf = pic->output_buffer;
+
+    vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR);
+    vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B);
+
+    pic->nb_slices = 1;
+
+    return 0;
+}
+
+static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
+                                               VAAPIEncodePicture *pic,
+                                               VAAPIEncodeSlice *slice)
+{
+    VAAPIEncodeContext                 *ctx = avctx->priv_data;
+    VAEncSequenceParameterBufferH264  *vseq = ctx->codec_sequence_params;
+    VAEncPictureParameterBufferH264   *vpic = pic->codec_picture_params;
+    VAEncSliceParameterBufferH264   *vslice = slice->codec_slice_params;
+    VAAPIEncodeH264Context            *priv = ctx->priv_data;
+    VAAPIEncodeH264Slice            *pslice;
+    VAAPIEncodeH264MiscSliceParams  *mslice;
+    int i;
+
+    slice->priv_data = av_mallocz(sizeof(*pslice));
+    if (!slice->priv_data)
+        return AVERROR(ENOMEM);
+    pslice = slice->priv_data;
+    mslice = &pslice->misc_slice_params;
+
+    if (pic->type == PICTURE_TYPE_IDR)
+        mslice->nal_unit_type = NAL_IDR_SLICE;
+    else
+        mslice->nal_unit_type = NAL_SLICE;
+
+    switch (pic->type) {
+    case PICTURE_TYPE_IDR:
+        vslice->slice_type  = SLICE_TYPE_I;
+        mslice->nal_ref_idc = 3;
+        break;
+    case PICTURE_TYPE_I:
+        vslice->slice_type  = SLICE_TYPE_I;
+        mslice->nal_ref_idc = 2;
+        break;
+    case PICTURE_TYPE_P:
+        vslice->slice_type  = SLICE_TYPE_P;
+        mslice->nal_ref_idc = 1;
+        break;
+    case PICTURE_TYPE_B:
+        vslice->slice_type  = SLICE_TYPE_B;
+        mslice->nal_ref_idc = 0;
+        break;
+    default:
+        av_assert0(0 && "invalid picture type");
+    }
+
+    // Only one slice per frame.
+    vslice->macroblock_address = 0;
+    vslice->num_macroblocks = priv->mb_width * priv->mb_height;
+
+    vslice->macroblock_info = VA_INVALID_ID;
+
+    vslice->pic_parameter_set_id = vpic->pic_parameter_set_id;
+    vslice->idr_pic_id = priv->idr_pic_count++;
+
+    vslice->pic_order_cnt_lsb = pic->display_order &
+        ((1 << (4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4)) - 1);
+
+    for (i = 0; i < FF_ARRAY_ELEMS(vslice->RefPicList0); i++) {
+        vslice->RefPicList0[i].picture_id = VA_INVALID_ID;
+        vslice->RefPicList0[i].flags      = VA_PICTURE_H264_INVALID;
+        vslice->RefPicList1[i].picture_id = VA_INVALID_ID;
+        vslice->RefPicList1[i].flags      = VA_PICTURE_H264_INVALID;
+    }
+
+    av_assert0(pic->nb_refs <= 2);
+    if (pic->nb_refs >= 1) {
+        // Backward reference for P- or B-frame.
+        av_assert0(pic->type == PICTURE_TYPE_P ||
+                   pic->type == PICTURE_TYPE_B);
+
+        vslice->num_ref_idx_l0_active_minus1 = 0;
+        vslice->RefPicList0[0] = vpic->ReferenceFrames[0];
+    }
+    if (pic->nb_refs >= 2) {
+        // Forward reference for B-frame.
+        av_assert0(pic->type == PICTURE_TYPE_B);
+
+        vslice->num_ref_idx_l1_active_minus1 = 0;
+        vslice->RefPicList1[0] = vpic->ReferenceFrames[1];
+    }
+
+    if (pic->type == PICTURE_TYPE_B)
+        vslice->slice_qp_delta = priv->fixed_qp_b - vpic->pic_init_qp;
+    else if (pic->type == PICTURE_TYPE_P)
+        vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp;
+    else
+        vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp;
+
+    vslice->direct_spatial_mv_pred_flag = 1;
+
+    return 0;
+}
+
+static av_cold int vaapi_encode_h264_init_constant_bitrate(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH264Context *priv = ctx->priv_data;
+    int hrd_buffer_size;
+    int hrd_initial_buffer_fullness;
+
+    if (avctx->bit_rate > INT32_MAX) {
+        av_log(avctx, AV_LOG_ERROR, "Target bitrate of 2^31 bps or "
+               "higher is not supported.\n");
+        return AVERROR(EINVAL);
+    }
+
+    if (avctx->rc_buffer_size)
+        hrd_buffer_size = avctx->rc_buffer_size;
+    else
+        hrd_buffer_size = avctx->bit_rate;
+    if (avctx->rc_initial_buffer_occupancy)
+        hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
+    else
+        hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
+
+    priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl;
+    priv->rc_params.rc = (VAEncMiscParameterRateControl) {
+        .bits_per_second   = avctx->bit_rate,
+        .target_percentage = 66,
+        .window_size       = 1000,
+        .initial_qp        = (avctx->qmax >= 0 ? avctx->qmax : 40),
+        .min_qp            = (avctx->qmin >= 0 ? avctx->qmin : 18),
+        .basic_unit_size   = 0,
+    };
+    ctx->global_params[ctx->nb_global_params] =
+        &priv->rc_params.misc;
+    ctx->global_params_size[ctx->nb_global_params++] =
+        sizeof(priv->rc_params);
+
+    priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD;
+    priv->hrd_params.hrd = (VAEncMiscParameterHRD) {
+        .initial_buffer_fullness = hrd_initial_buffer_fullness,
+        .buffer_size             = hrd_buffer_size,
+    };
+    ctx->global_params[ctx->nb_global_params] =
+        &priv->hrd_params.misc;
+    ctx->global_params_size[ctx->nb_global_params++] =
+        sizeof(priv->hrd_params);
+
+    // These still need to be  set for pic_init_qp/slice_qp_delta.
+    priv->fixed_qp_idr = 26;
+    priv->fixed_qp_p   = 26;
+    priv->fixed_qp_b   = 26;
+
+    av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %"PRId64" bps.\n",
+           avctx->bit_rate);
+    return 0;
+}
+
+static av_cold int vaapi_encode_h264_init_fixed_qp(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH264Context *priv = ctx->priv_data;
+    VAAPIEncodeH264Options  *opt = ctx->codec_options;
+
+    priv->fixed_qp_p = opt->qp;
+    if (avctx->i_quant_factor > 0.0)
+        priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
+                                    avctx->i_quant_offset) + 0.5);
+    else
+        priv->fixed_qp_idr = priv->fixed_qp_p;
+    if (avctx->b_quant_factor > 0.0)
+        priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
+                                  avctx->b_quant_offset) + 0.5);
+    else
+        priv->fixed_qp_b = priv->fixed_qp_p;
+
+    av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
+           "%d / %d / %d for IDR- / P- / B-frames.\n",
+           priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
+    return 0;
+}
+
+static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
+{
+    static const VAConfigAttrib default_config_attributes[] = {
+        { .type  = VAConfigAttribRTFormat,
+          .value = VA_RT_FORMAT_YUV420 },
+        { .type  = VAConfigAttribEncPackedHeaders,
+          .value = (VA_ENC_PACKED_HEADER_SEQUENCE |
+                    VA_ENC_PACKED_HEADER_SLICE) },
+    };
+
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH264Context *priv = ctx->priv_data;
+    VAAPIEncodeH264Options  *opt = ctx->codec_options;
+    int i, err;
+
+    switch (avctx->profile) {
+    case FF_PROFILE_H264_CONSTRAINED_BASELINE:
+        ctx->va_profile = VAProfileH264ConstrainedBaseline;
+        break;
+    case FF_PROFILE_H264_BASELINE:
+        ctx->va_profile = VAProfileH264Baseline;
+        break;
+    case FF_PROFILE_H264_MAIN:
+        ctx->va_profile = VAProfileH264Main;
+        break;
+    case FF_PROFILE_H264_EXTENDED:
+        av_log(avctx, AV_LOG_ERROR, "H.264 extended profile "
+               "is not supported.\n");
+        return AVERROR_PATCHWELCOME;
+    case FF_PROFILE_UNKNOWN:
+    case FF_PROFILE_H264_HIGH:
+        ctx->va_profile = VAProfileH264High;
+        break;
+    case FF_PROFILE_H264_HIGH_10:
+    case FF_PROFILE_H264_HIGH_10_INTRA:
+        av_log(avctx, AV_LOG_ERROR, "H.264 10-bit profiles "
+               "are not supported.\n");
+        return AVERROR_PATCHWELCOME;
+    case FF_PROFILE_H264_HIGH_422:
+    case FF_PROFILE_H264_HIGH_422_INTRA:
+    case FF_PROFILE_H264_HIGH_444:
+    case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
+    case FF_PROFILE_H264_HIGH_444_INTRA:
+    case FF_PROFILE_H264_CAVLC_444:
+        av_log(avctx, AV_LOG_ERROR, "H.264 non-4:2:0 profiles "
+               "are not supported.\n");
+        return AVERROR_PATCHWELCOME;
+    default:
+        av_log(avctx, AV_LOG_ERROR, "Unknown H.264 profile %d.\n",
+               avctx->profile);
+        return AVERROR(EINVAL);
+    }
+    if (opt->low_power) {
+#if VA_CHECK_VERSION(0, 39, 1)
+        ctx->va_entrypoint = VAEntrypointEncSliceLP;
+#else
+        av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
+               "supported with this VAAPI version.\n");
+        return AVERROR(EINVAL);
+#endif
+    } else {
+        ctx->va_entrypoint = VAEntrypointEncSlice;
+    }
+
+    ctx->input_width    = avctx->width;
+    ctx->input_height   = avctx->height;
+    ctx->aligned_width  = FFALIGN(ctx->input_width,  16);
+    ctx->aligned_height = FFALIGN(ctx->input_height, 16);
+    priv->mb_width      = ctx->aligned_width  / 16;
+    priv->mb_height     = ctx->aligned_height / 16;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
+        ctx->config_attributes[ctx->nb_config_attributes++] =
+            default_config_attributes[i];
+    }
+
+    if (avctx->bit_rate > 0) {
+        ctx->va_rc_mode = VA_RC_CBR;
+        err = vaapi_encode_h264_init_constant_bitrate(avctx);
+    } else {
+        ctx->va_rc_mode = VA_RC_CQP;
+        err = vaapi_encode_h264_init_fixed_qp(avctx);
+    }
+    if (err < 0)
+        return err;
+
+    ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
+        .type  = VAConfigAttribRateControl,
+        .value = ctx->va_rc_mode,
+    };
+
+    if (opt->quality > 0) {
+#if VA_CHECK_VERSION(0, 36, 0)
+        priv->quality_params.misc.type =
+            VAEncMiscParameterTypeQualityLevel;
+        priv->quality_params.quality.quality_level = opt->quality;
+
+        ctx->global_params[ctx->nb_global_params] =
+            &priv->quality_params.misc;
+        ctx->global_params_size[ctx->nb_global_params++] =
+            sizeof(priv->quality_params);
+#else
+        av_log(avctx, AV_LOG_WARNING, "The encode quality option is not "
+               "supported with this VAAPI version.\n");
+#endif
+    }
+
+    ctx->nb_recon_frames = 20;
+
+    return 0;
+}
+
+static VAAPIEncodeType vaapi_encode_type_h264 = {
+    .priv_data_size        = sizeof(VAAPIEncodeH264Context),
+
+    .init                  = &vaapi_encode_h264_init_internal,
+
+    .sequence_params_size  = sizeof(VAEncSequenceParameterBufferH264),
+    .init_sequence_params  = &vaapi_encode_h264_init_sequence_params,
+
+    .picture_params_size   = sizeof(VAEncPictureParameterBufferH264),
+    .init_picture_params   = &vaapi_encode_h264_init_picture_params,
+
+    .slice_params_size     = sizeof(VAEncSliceParameterBufferH264),
+    .init_slice_params     = &vaapi_encode_h264_init_slice_params,
+
+    .sequence_header_type  = VAEncPackedHeaderSequence,
+    .write_sequence_header = &vaapi_encode_h264_write_sequence_header,
+
+    .slice_header_type     = VAEncPackedHeaderH264_Slice,
+    .write_slice_header    = &vaapi_encode_h264_write_slice_header,
+};
+
+static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
+{
+    return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h264);
+}
+
+#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
+                   offsetof(VAAPIEncodeH264Options, x))
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
+static const AVOption vaapi_encode_h264_options[] = {
+    { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
+      OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 20 }, 0, 52, FLAGS },
+    { "quality", "Set encode quality (trades off against speed, higher is faster)",
+      OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8, FLAGS },
+    { "low_power", "Use low-power encoding mode (experimental: only supported "
+      "on some platforms, does not support all features)",
+      OFFSET(low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS },
+    { NULL },
+};
+
+static const AVCodecDefault vaapi_encode_h264_defaults[] = {
+    { "profile",        "100" },
+    { "level",          "51"  },
+    { "b",              "0"   },
+    { "bf",             "2"   },
+    { "g",              "120" },
+    { "i_qfactor",      "1.0" },
+    { "i_qoffset",      "0.0" },
+    { "b_qfactor",      "1.2" },
+    { "b_qoffset",      "0.0" },
+    { NULL },
+};
+
+static const AVClass vaapi_encode_h264_class = {
+    .class_name = "h264_vaapi",
+    .item_name  = av_default_item_name,
+    .option     = vaapi_encode_h264_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_h264_vaapi_encoder = {
+    .name           = "h264_vaapi",
+    .long_name      = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_H264,
+    .priv_data_size = (sizeof(VAAPIEncodeContext) +
+                       sizeof(VAAPIEncodeH264Options)),
+    .init           = &vaapi_encode_h264_init,
+    .encode2        = &ff_vaapi_encode2,
+    .close          = &ff_vaapi_encode_close,
+    .priv_class     = &vaapi_encode_h264_class,
+    .capabilities   = AV_CODEC_CAP_DELAY,
+    .defaults       = vaapi_encode_h264_defaults,
+    .pix_fmts = (const enum AVPixelFormat[]) {
+        AV_PIX_FMT_VAAPI,
+        AV_PIX_FMT_NONE,
+    },
+};
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
new file mode 100644
index 0000000..c42c08e
--- /dev/null
+++ b/libavcodec/vaapi_encode_h265.c
@@ -0,0 +1,1372 @@
+/*
+ * 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 <va/va.h>
+#include <va/va_enc_hevc.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixfmt.h"
+
+#include "avcodec.h"
+#include "hevc.h"
+#include "internal.h"
+#include "put_bits.h"
+#include "vaapi_encode.h"
+#include "vaapi_encode_h26x.h"
+
+
+#define MAX_ST_REF_PIC_SETS  32
+#define MAX_DPB_PICS         16
+#define MAX_LAYERS            1
+
+
+typedef struct VAAPIEncodeH265STRPS {
+    char inter_ref_pic_set_prediction_flag;
+
+    unsigned int num_negative_pics;
+    unsigned int num_positive_pics;
+
+    unsigned int delta_poc_s0_minus1[MAX_DPB_PICS];
+    char used_by_curr_pic_s0_flag[MAX_DPB_PICS];
+
+    unsigned int delta_poc_s1_minus1[MAX_DPB_PICS];
+    char used_by_curr_pic_s1_flag[MAX_DPB_PICS];
+} VAAPIEncodeH265STRPS;
+
+// This structure contains all possibly-useful per-sequence syntax elements
+// which are not already contained in the various VAAPI structures.
+typedef struct VAAPIEncodeH265MiscSequenceParams {
+
+    // Parameter set IDs.
+    unsigned int video_parameter_set_id;
+    unsigned int seq_parameter_set_id;
+
+    // Layering.
+    unsigned int vps_max_layers_minus1;
+    unsigned int vps_max_sub_layers_minus1;
+    char vps_temporal_id_nesting_flag;
+    unsigned int vps_max_layer_id;
+    unsigned int vps_num_layer_sets_minus1;
+    unsigned int sps_max_sub_layers_minus1;
+    char sps_temporal_id_nesting_flag;
+    char layer_id_included_flag[MAX_LAYERS][64];
+
+    // Profile/tier/level parameters.
+    char general_profile_compatibility_flag[32];
+    char general_progressive_source_flag;
+    char general_interlaced_source_flag;
+    char general_non_packed_constraint_flag;
+    char general_frame_only_constraint_flag;
+    char general_inbld_flag;
+
+    // Decode/display ordering parameters.
+    unsigned int log2_max_pic_order_cnt_lsb_minus4;
+    char vps_sub_layer_ordering_info_present_flag;
+    unsigned int vps_max_dec_pic_buffering_minus1[MAX_LAYERS];
+    unsigned int vps_max_num_reorder_pics[MAX_LAYERS];
+    unsigned int vps_max_latency_increase_plus1[MAX_LAYERS];
+    char sps_sub_layer_ordering_info_present_flag;
+    unsigned int sps_max_dec_pic_buffering_minus1[MAX_LAYERS];
+    unsigned int sps_max_num_reorder_pics[MAX_LAYERS];
+    unsigned int sps_max_latency_increase_plus1[MAX_LAYERS];
+
+    // Timing information.
+    char vps_timing_info_present_flag;
+    unsigned int vps_num_units_in_tick;
+    unsigned int vps_time_scale;
+    char vps_poc_proportional_to_timing_flag;
+    unsigned int vps_num_ticks_poc_diff_minus1;
+
+    // Cropping information.
+    char conformance_window_flag;
+    unsigned int conf_win_left_offset;
+    unsigned int conf_win_right_offset;
+    unsigned int conf_win_top_offset;
+    unsigned int conf_win_bottom_offset;
+
+    // Short-term reference picture sets.
+    unsigned int num_short_term_ref_pic_sets;
+    VAAPIEncodeH265STRPS st_ref_pic_set[MAX_ST_REF_PIC_SETS];
+
+    // Long-term reference pictures.
+    char long_term_ref_pics_present_flag;
+    unsigned int num_long_term_ref_pics_sps;
+    struct {
+        unsigned int lt_ref_pic_poc_lsb_sps;
+        char used_by_curr_pic_lt_sps_flag;
+    } lt_ref_pic;
+
+    // Deblocking filter control.
+    char deblocking_filter_control_present_flag;
+    char deblocking_filter_override_enabled_flag;
+    char pps_deblocking_filter_disabled_flag;
+    int pps_beta_offset_div2;
+    int pps_tc_offset_div2;
+
+    // Video Usability Information.
+    char vui_parameters_present_flag;
+    char aspect_ratio_info_present_flag;
+    unsigned int aspect_ratio_idc;
+    unsigned int sar_width;
+    unsigned int sar_height;
+    char video_signal_type_present_flag;
+    unsigned int video_format;
+    char video_full_range_flag;
+    char colour_description_present_flag;
+    unsigned int colour_primaries;
+    unsigned int transfer_characteristics;
+    unsigned int matrix_coeffs;
+
+    // Oddments.
+    char uniform_spacing_flag;
+    char output_flag_present_flag;
+    char cabac_init_present_flag;
+    unsigned int num_extra_slice_header_bits;
+    char lists_modification_present_flag;
+    char pps_slice_chroma_qp_offsets_present_flag;
+    char pps_slice_chroma_offset_list_enabled_flag;
+} VAAPIEncodeH265MiscSequenceParams;
+
+// This structure contains all possibly-useful per-slice syntax elements
+// which are not already contained in the various VAAPI structures.
+typedef struct VAAPIEncodeH265MiscSliceParams {
+    // Slice segments.
+    char first_slice_segment_in_pic_flag;
+    unsigned int slice_segment_address;
+
+    // Short-term reference picture sets.
+    char short_term_ref_pic_set_sps_flag;
+    unsigned int short_term_ref_pic_idx;
+    VAAPIEncodeH265STRPS st_ref_pic_set;
+
+    // Deblocking filter.
+    char deblocking_filter_override_flag;
+
+    // Oddments.
+    char slice_reserved_flag[8];
+    char no_output_of_prior_pics_flag;
+    char pic_output_flag;
+} VAAPIEncodeH265MiscSliceParams;
+
+typedef struct VAAPIEncodeH265Slice {
+    VAAPIEncodeH265MiscSliceParams misc_slice_params;
+
+    int64_t pic_order_cnt;
+} VAAPIEncodeH265Slice;
+
+typedef struct VAAPIEncodeH265Context {
+    VAAPIEncodeH265MiscSequenceParams misc_sequence_params;
+
+    unsigned int ctu_width;
+    unsigned int ctu_height;
+
+    int fixed_qp_idr;
+    int fixed_qp_p;
+    int fixed_qp_b;
+
+    int64_t last_idr_frame;
+
+    // Rate control configuration.
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterRateControl rc;
+    } rc_params;
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterHRD hrd;
+    } hrd_params;
+} VAAPIEncodeH265Context;
+
+typedef struct VAAPIEncodeH265Options {
+    int qp;
+} VAAPIEncodeH265Options;
+
+
+#define vseq_var(name)     vseq->name, name
+#define vseq_field(name)   vseq->seq_fields.bits.name, name
+#define vpic_var(name)     vpic->name, name
+#define vpic_field(name)   vpic->pic_fields.bits.name, name
+#define vslice_var(name)   vslice->name, name
+#define vslice_field(name) vslice->slice_fields.bits.name, name
+#define mseq_var(name)     mseq->name, name
+#define mslice_var(name)   mslice->name, name
+#define mstrps_var(name)   mstrps->name, name
+
+static void vaapi_encode_h265_write_nal_unit_header(PutBitContext *pbc,
+                                                    int nal_unit_type)
+{
+    u(1, 0, forbidden_zero_bit);
+    u(6, nal_unit_type, nal_unit_type);
+    u(6, 0, nuh_layer_id);
+    u(3, 1, nuh_temporal_id_plus1);
+}
+
+static void vaapi_encode_h265_write_rbsp_trailing_bits(PutBitContext *pbc)
+{
+    u(1, 1, rbsp_stop_one_bit);
+    while (put_bits_count(pbc) & 7)
+        u(1, 0, rbsp_alignment_zero_bit);
+}
+
+static void vaapi_encode_h265_write_profile_tier_level(PutBitContext *pbc,
+                                                       VAAPIEncodeContext *ctx)
+{
+    VAEncSequenceParameterBufferHEVC  *vseq = ctx->codec_sequence_params;
+    VAAPIEncodeH265Context            *priv = ctx->priv_data;
+    VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params;
+    int j;
+
+    if (1) {
+        u(2, 0, general_profile_space);
+        u(1, vseq_var(general_tier_flag));
+        u(5, vseq_var(general_profile_idc));
+
+        for (j = 0; j < 32; j++) {
+            u(1, mseq_var(general_profile_compatibility_flag[j]));
+        }
+
+        u(1, mseq_var(general_progressive_source_flag));
+        u(1, mseq_var(general_interlaced_source_flag));
+        u(1, mseq_var(general_non_packed_constraint_flag));
+        u(1, mseq_var(general_frame_only_constraint_flag));
+
+        if (0) {
+            // Not main profile.
+            // Lots of extra constraint flags.
+        } else {
+            // put_bits only handles up to 31 bits.
+            u(23, 0, general_reserved_zero_43bits);
+            u(20, 0, general_reserved_zero_43bits);
+        }
+
+        if (vseq->general_profile_idc >= 1 && vseq->general_profile_idc <= 5) {
+            u(1, mseq_var(general_inbld_flag));
+        } else {
+            u(1, 0, general_reserved_zero_bit);
+        }
+    }
+
+    u(8, vseq_var(general_level_idc));
+
+    // No sublayers.
+}
+
+static void vaapi_encode_h265_write_vps(PutBitContext *pbc,
+                                        VAAPIEncodeContext *ctx)
+{
+    VAAPIEncodeH265Context            *priv = ctx->priv_data;
+    VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params;
+    int i, j;
+
+    vaapi_encode_h265_write_nal_unit_header(pbc, NAL_VPS);
+
+    u(4, mseq->video_parameter_set_id, vps_video_parameter_set_id);
+
+    u(1, 1, vps_base_layer_internal_flag);
+    u(1, 1, vps_base_layer_available_flag);
+    u(6, mseq_var(vps_max_layers_minus1));
+    u(3, mseq_var(vps_max_sub_layers_minus1));
+    u(1, mseq_var(vps_temporal_id_nesting_flag));
+
+    u(16, 0xffff, vps_reserved_0xffff_16bits);
+
+    vaapi_encode_h265_write_profile_tier_level(pbc, ctx);
+
+    u(1, mseq_var(vps_sub_layer_ordering_info_present_flag));
+    for (i = (mseq->vps_sub_layer_ordering_info_present_flag ?
+              0 : mseq->vps_max_sub_layers_minus1);
+         i <= mseq->vps_max_sub_layers_minus1; i++) {
+        ue(mseq_var(vps_max_dec_pic_buffering_minus1[i]));
+        ue(mseq_var(vps_max_num_reorder_pics[i]));
+        ue(mseq_var(vps_max_latency_increase_plus1[i]));
+    }
+
+    u(6, mseq_var(vps_max_layer_id));
+    ue(mseq_var(vps_num_layer_sets_minus1));
+    for (i = 1; i <= mseq->vps_num_layer_sets_minus1; i++) {
+        for (j = 0; j < mseq->vps_max_layer_id; j++)
+            u(1, mseq_var(layer_id_included_flag[i][j]));
+    }
+
+    u(1, mseq_var(vps_timing_info_present_flag));
+    if (mseq->vps_timing_info_present_flag) {
+        u(1, 0, put_bits_hack_zero_bit);
+        u(31, mseq_var(vps_num_units_in_tick));
+        u(1, 0, put_bits_hack_zero_bit);
+        u(31, mseq_var(vps_time_scale));
+        u(1, mseq_var(vps_poc_proportional_to_timing_flag));
+        if (mseq->vps_poc_proportional_to_timing_flag) {
+            ue(mseq_var(vps_num_ticks_poc_diff_minus1));
+        }
+        ue(0, vps_num_hrd_parameters);
+    }
+
+    u(1, 0, vps_extension_flag);
+
+    vaapi_encode_h265_write_rbsp_trailing_bits(pbc);
+}
+
+static void vaapi_encode_h265_write_st_ref_pic_set(PutBitContext *pbc,
+                                                   int st_rps_idx,
+                                                   VAAPIEncodeH265STRPS *mstrps)
+{
+    int i;
+
+    if (st_rps_idx != 0)
+       u(1, mstrps_var(inter_ref_pic_set_prediction_flag));
+
+    if (mstrps->inter_ref_pic_set_prediction_flag) {
+        av_assert0(0 && "inter ref pic set prediction not supported");
+    } else {
+        ue(mstrps_var(num_negative_pics));
+        ue(mstrps_var(num_positive_pics));
+
+        for (i = 0; i < mstrps->num_negative_pics; i++) {
+            ue(mstrps_var(delta_poc_s0_minus1[i]));
+            u(1, mstrps_var(used_by_curr_pic_s0_flag[i]));
+        }
+        for (i = 0; i < mstrps->num_positive_pics; i++) {
+            ue(mstrps_var(delta_poc_s1_minus1[i]));
+            u(1, mstrps_var(used_by_curr_pic_s1_flag[i]));
+        }
+    }
+}
+
+static void vaapi_encode_h265_write_vui_parameters(PutBitContext *pbc,
+                                                   VAAPIEncodeContext *ctx)
+{
+    VAAPIEncodeH265Context            *priv = ctx->priv_data;
+    VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params;
+
+    u(1, mseq_var(aspect_ratio_info_present_flag));
+    if (mseq->aspect_ratio_info_present_flag) {
+        u(8, mseq_var(aspect_ratio_idc));
+        if (mseq->aspect_ratio_idc == 255) {
+            u(16, mseq_var(sar_width));
+            u(16, mseq_var(sar_height));
+        }
+    }
+
+    u(1, 0, overscan_info_present_flag);
+
+    u(1, mseq_var(video_signal_type_present_flag));
+    if (mseq->video_signal_type_present_flag) {
+        u(3, mseq_var(video_format));
+        u(1, mseq_var(video_full_range_flag));
+        u(1, mseq_var(colour_description_present_flag));
+        if (mseq->colour_description_present_flag) {
+            u(8, mseq_var(colour_primaries));
+            u(8, mseq_var(transfer_characteristics));
+            u(8, mseq_var(matrix_coeffs));
+        }
+    }
+
+    u(1, 0, chroma_loc_info_present_flag);
+    u(1, 0, neutral_chroma_indication_flag);
+    u(1, 0, field_seq_flag);
+    u(1, 0, frame_field_info_present_flag);
+    u(1, 0, default_display_window_flag);
+    u(1, 0, vui_timing_info_present_flag);
+    u(1, 0, bitstream_restriction_flag_flag);
+}
+
+static void vaapi_encode_h265_write_sps(PutBitContext *pbc,
+                                        VAAPIEncodeContext *ctx)
+{
+    VAEncSequenceParameterBufferHEVC  *vseq = ctx->codec_sequence_params;
+    VAAPIEncodeH265Context            *priv = ctx->priv_data;
+    VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params;
+    int i;
+
+    vaapi_encode_h265_write_nal_unit_header(pbc, NAL_SPS);
+
+    u(4, mseq->video_parameter_set_id, sps_video_parameter_set_id);
+
+    u(3, mseq_var(sps_max_sub_layers_minus1));
+    u(1, mseq_var(sps_temporal_id_nesting_flag));
+
+    vaapi_encode_h265_write_profile_tier_level(pbc, ctx);
+
+    ue(mseq->seq_parameter_set_id, sps_seq_parameter_set_id);
+    ue(vseq_field(chroma_format_idc));
+    if (vseq->seq_fields.bits.chroma_format_idc == 3)
+        u(1, 0, separate_colour_plane_flag);
+
+    ue(vseq_var(pic_width_in_luma_samples));
+    ue(vseq_var(pic_height_in_luma_samples));
+
+    u(1, mseq_var(conformance_window_flag));
+    if (mseq->conformance_window_flag) {
+        ue(mseq_var(conf_win_left_offset));
+        ue(mseq_var(conf_win_right_offset));
+        ue(mseq_var(conf_win_top_offset));
+        ue(mseq_var(conf_win_bottom_offset));
+    }
+
+    ue(vseq_field(bit_depth_luma_minus8));
+    ue(vseq_field(bit_depth_chroma_minus8));
+
+    ue(mseq_var(log2_max_pic_order_cnt_lsb_minus4));
+
+    u(1, mseq_var(sps_sub_layer_ordering_info_present_flag));
+    for (i = (mseq->sps_sub_layer_ordering_info_present_flag ?
+              0 : mseq->sps_max_sub_layers_minus1);
+         i <= mseq->sps_max_sub_layers_minus1; i++) {
+        ue(mseq_var(sps_max_dec_pic_buffering_minus1[i]));
+        ue(mseq_var(sps_max_num_reorder_pics[i]));
+        ue(mseq_var(sps_max_latency_increase_plus1[i]));
+    }
+
+    ue(vseq_var(log2_min_luma_coding_block_size_minus3));
+    ue(vseq_var(log2_diff_max_min_luma_coding_block_size));
+    ue(vseq_var(log2_min_transform_block_size_minus2));
+    ue(vseq_var(log2_diff_max_min_transform_block_size));
+    ue(vseq_var(max_transform_hierarchy_depth_inter));
+    ue(vseq_var(max_transform_hierarchy_depth_intra));
+
+    u(1, vseq_field(scaling_list_enabled_flag));
+    if (vseq->seq_fields.bits.scaling_list_enabled_flag) {
+        u(1, 0, sps_scaling_list_data_present_flag);
+    }
+
+    u(1, vseq_field(amp_enabled_flag));
+    u(1, vseq_field(sample_adaptive_offset_enabled_flag));
+
+    u(1, vseq_field(pcm_enabled_flag));
+    if (vseq->seq_fields.bits.pcm_enabled_flag) {
+        u(4, vseq_var(pcm_sample_bit_depth_luma_minus1));
+        u(4, vseq_var(pcm_sample_bit_depth_chroma_minus1));
+        ue(vseq_var(log2_min_pcm_luma_coding_block_size_minus3));
+        ue(vseq->log2_max_pcm_luma_coding_block_size_minus3 -
+           vseq->log2_min_pcm_luma_coding_block_size_minus3,
+           log2_diff_max_min_pcm_luma_coding_block_size);
+        u(1, vseq_field(pcm_loop_filter_disabled_flag));
+    }
+
+    ue(mseq_var(num_short_term_ref_pic_sets));
+    for (i = 0; i < mseq->num_short_term_ref_pic_sets; i++)
+        vaapi_encode_h265_write_st_ref_pic_set(pbc, i,
+                                               &mseq->st_ref_pic_set[i]);
+
+    u(1, mseq_var(long_term_ref_pics_present_flag));
+    if (mseq->long_term_ref_pics_present_flag) {
+        ue(0, num_long_term_ref_pics_sps);
+    }
+
+    u(1, vseq_field(sps_temporal_mvp_enabled_flag));
+    u(1, vseq_field(strong_intra_smoothing_enabled_flag));
+
+    u(1, mseq_var(vui_parameters_present_flag));
+    if (mseq->vui_parameters_present_flag) {
+        vaapi_encode_h265_write_vui_parameters(pbc, ctx);
+    }
+
+    u(1, 0, sps_extension_present_flag);
+
+    vaapi_encode_h265_write_rbsp_trailing_bits(pbc);
+}
+
+static void vaapi_encode_h265_write_pps(PutBitContext *pbc,
+                                        VAAPIEncodeContext *ctx)
+{
+    VAEncPictureParameterBufferHEVC   *vpic = ctx->codec_picture_params;
+    VAAPIEncodeH265Context            *priv = ctx->priv_data;
+    VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params;
+    int i;
+
+    vaapi_encode_h265_write_nal_unit_header(pbc, NAL_PPS);
+
+    ue(vpic->slice_pic_parameter_set_id, pps_pic_parameter_set_id);
+    ue(mseq->seq_parameter_set_id, pps_seq_parameter_set_id);
+
+    u(1, vpic_field(dependent_slice_segments_enabled_flag));
+    u(1, mseq_var(output_flag_present_flag));
+    u(3, mseq_var(num_extra_slice_header_bits));
+    u(1, vpic_field(sign_data_hiding_enabled_flag));
+    u(1, mseq_var(cabac_init_present_flag));
+
+    ue(vpic_var(num_ref_idx_l0_default_active_minus1));
+    ue(vpic_var(num_ref_idx_l1_default_active_minus1));
+
+    se(vpic->pic_init_qp - 26, init_qp_minus26);
+
+    u(1, vpic_field(constrained_intra_pred_flag));
+    u(1, vpic_field(transform_skip_enabled_flag));
+
+    u(1, vpic_field(cu_qp_delta_enabled_flag));
+    if (vpic->pic_fields.bits.cu_qp_delta_enabled_flag)
+        ue(vpic_var(diff_cu_qp_delta_depth));
+
+    se(vpic_var(pps_cb_qp_offset));
+    se(vpic_var(pps_cr_qp_offset));
+
+    u(1, mseq_var(pps_slice_chroma_qp_offsets_present_flag));
+    u(1, vpic_field(weighted_pred_flag));
+    u(1, vpic_field(weighted_bipred_flag));
+    u(1, vpic_field(transquant_bypass_enabled_flag));
+    u(1, vpic_field(tiles_enabled_flag));
+    u(1, vpic_field(entropy_coding_sync_enabled_flag));
+
+    if (vpic->pic_fields.bits.tiles_enabled_flag) {
+        ue(vpic_var(num_tile_columns_minus1));
+        ue(vpic_var(num_tile_rows_minus1));
+        u(1, mseq_var(uniform_spacing_flag));
+        if (!mseq->uniform_spacing_flag) {
+            for (i = 0; i < vpic->num_tile_columns_minus1; i++)
+                ue(vpic_var(column_width_minus1[i]));
+            for (i = 0; i < vpic->num_tile_rows_minus1; i++)
+                ue(vpic_var(row_height_minus1[i]));
+        }
+        u(1, vpic_field(loop_filter_across_tiles_enabled_flag));
+    }
+
+    u(1, vpic_field(pps_loop_filter_across_slices_enabled_flag));
+    u(1, mseq_var(deblocking_filter_control_present_flag));
+    if (mseq->deblocking_filter_control_present_flag) {
+        u(1, mseq_var(deblocking_filter_override_enabled_flag));
+        u(1, mseq_var(pps_deblocking_filter_disabled_flag));
+        if (!mseq->pps_deblocking_filter_disabled_flag) {
+            se(mseq_var(pps_beta_offset_div2));
+            se(mseq_var(pps_tc_offset_div2));
+        }
+    }
+
+    u(1, 0, pps_scaling_list_data_present_flag);
+    // No scaling list data.
+
+    u(1, mseq_var(lists_modification_present_flag));
+    ue(vpic_var(log2_parallel_merge_level_minus2));
+    u(1, 0, slice_segment_header_extension_present_flag);
+    u(1, 0, pps_extension_present_flag);
+
+    vaapi_encode_h265_write_rbsp_trailing_bits(pbc);
+}
+
+static void vaapi_encode_h265_write_slice_header2(PutBitContext *pbc,
+                                                  VAAPIEncodeContext *ctx,
+                                                  VAAPIEncodePicture *pic,
+                                                  VAAPIEncodeSlice *slice)
+{
+    VAEncSequenceParameterBufferHEVC  *vseq = ctx->codec_sequence_params;
+    VAEncPictureParameterBufferHEVC   *vpic = pic->codec_picture_params;
+    VAEncSliceParameterBufferHEVC   *vslice = slice->codec_slice_params;
+    VAAPIEncodeH265Context            *priv = ctx->priv_data;
+    VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params;
+    VAAPIEncodeH265Slice            *pslice = slice->priv_data;
+    VAAPIEncodeH265MiscSliceParams  *mslice = &pslice->misc_slice_params;
+    int i;
+
+    vaapi_encode_h265_write_nal_unit_header(pbc, vpic->nal_unit_type);
+
+    u(1, mslice_var(first_slice_segment_in_pic_flag));
+    if (vpic->nal_unit_type >= NAL_BLA_W_LP &&
+       vpic->nal_unit_type <= 23)
+        u(1, mslice_var(no_output_of_prior_pics_flag));
+
+    ue(vslice_var(slice_pic_parameter_set_id));
+
+    if (!mslice->first_slice_segment_in_pic_flag) {
+        if (vpic->pic_fields.bits.dependent_slice_segments_enabled_flag)
+            u(1, vslice_field(dependent_slice_segment_flag));
+        u(av_log2((priv->ctu_width * priv->ctu_height) - 1) + 1,
+          mslice_var(slice_segment_address));
+    }
+    if (!vslice->slice_fields.bits.dependent_slice_segment_flag) {
+        for (i = 0; i < mseq->num_extra_slice_header_bits; i++)
+            u(1, mslice_var(slice_reserved_flag[i]));
+
+        ue(vslice_var(slice_type));
+        if (mseq->output_flag_present_flag)
+            u(1, 1, pic_output_flag);
+        if (vseq->seq_fields.bits.separate_colour_plane_flag)
+            u(2, vslice_field(colour_plane_id));
+        if (vpic->nal_unit_type != NAL_IDR_W_RADL &&
+           vpic->nal_unit_type != NAL_IDR_N_LP) {
+            u(4 + mseq->log2_max_pic_order_cnt_lsb_minus4,
+              (pslice->pic_order_cnt &
+               ((1 << (mseq->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1)),
+              slice_pic_order_cnt_lsb);
+
+            u(1, mslice_var(short_term_ref_pic_set_sps_flag));
+            if (!mslice->short_term_ref_pic_set_sps_flag) {
+                vaapi_encode_h265_write_st_ref_pic_set(pbc, mseq->num_short_term_ref_pic_sets,
+                                                       &mslice->st_ref_pic_set);
+            } else if (mseq->num_short_term_ref_pic_sets > 1) {
+                u(av_log2(mseq->num_short_term_ref_pic_sets - 1) + 1,
+                  mslice_var(short_term_ref_pic_idx));
+            }
+
+            if (mseq->long_term_ref_pics_present_flag) {
+                av_assert0(0);
+            }
+
+            if (vseq->seq_fields.bits.sps_temporal_mvp_enabled_flag) {
+                u(1, vslice_field(slice_temporal_mvp_enabled_flag));
+            }
+
+            if (vseq->seq_fields.bits.sample_adaptive_offset_enabled_flag) {
+                u(1, vslice_field(slice_sao_luma_flag));
+                if (!vseq->seq_fields.bits.separate_colour_plane_flag &&
+                   vseq->seq_fields.bits.chroma_format_idc != 0) {
+                    u(1, vslice_field(slice_sao_chroma_flag));
+                }
+            }
+
+            if (vslice->slice_type == P_SLICE || vslice->slice_type == B_SLICE) {
+                u(1, vslice_field(num_ref_idx_active_override_flag));
+                if (vslice->slice_fields.bits.num_ref_idx_active_override_flag) {
+                    ue(vslice_var(num_ref_idx_l0_active_minus1));
+                    if (vslice->slice_type == B_SLICE) {
+                        ue(vslice_var(num_ref_idx_l1_active_minus1));
+                    }
+                }
+
+                if (mseq->lists_modification_present_flag) {
+                    av_assert0(0);
+                    // ref_pic_lists_modification()
+                }
+                if (vslice->slice_type == B_SLICE) {
+                    u(1, vslice_field(mvd_l1_zero_flag));
+                }
+                if (mseq->cabac_init_present_flag) {
+                    u(1, vslice_field(cabac_init_flag));
+                }
+                if (vslice->slice_fields.bits.slice_temporal_mvp_enabled_flag) {
+                    if (vslice->slice_type == B_SLICE)
+                        u(1, vslice_field(collocated_from_l0_flag));
+                    ue(vpic->collocated_ref_pic_index, collocated_ref_idx);
+                }
+                if ((vpic->pic_fields.bits.weighted_pred_flag &&
+                     vslice->slice_type == P_SLICE) ||
+                    (vpic->pic_fields.bits.weighted_bipred_flag &&
+                     vslice->slice_type == B_SLICE)) {
+                    av_assert0(0);
+                    // pred_weight_table()
+                }
+                ue(5 - vslice->max_num_merge_cand, five_minus_max_num_merge_cand);
+            }
+
+            se(vslice_var(slice_qp_delta));
+            if (mseq->pps_slice_chroma_qp_offsets_present_flag) {
+                se(vslice_var(slice_cb_qp_offset));
+                se(vslice_var(slice_cr_qp_offset));
+            }
+            if (mseq->pps_slice_chroma_offset_list_enabled_flag) {
+                u(1, 0, cu_chroma_qp_offset_enabled_flag);
+            }
+            if (mseq->deblocking_filter_override_enabled_flag) {
+                u(1, mslice_var(deblocking_filter_override_flag));
+            }
+            if (mslice->deblocking_filter_override_flag) {
+                u(1, vslice_field(slice_deblocking_filter_disabled_flag));
+                if (!vslice->slice_fields.bits.slice_deblocking_filter_disabled_flag) {
+                    se(vslice_var(slice_beta_offset_div2));
+                    se(vslice_var(slice_tc_offset_div2));
+                }
+            }
+            if (vpic->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag &&
+                (vslice->slice_fields.bits.slice_sao_luma_flag ||
+                 vslice->slice_fields.bits.slice_sao_chroma_flag ||
+                 vslice->slice_fields.bits.slice_deblocking_filter_disabled_flag)) {
+                u(1, vslice_field(slice_loop_filter_across_slices_enabled_flag));
+            }
+        }
+
+        if (vpic->pic_fields.bits.tiles_enabled_flag ||
+            vpic->pic_fields.bits.entropy_coding_sync_enabled_flag) {
+            // num_entry_point_offsets
+        }
+
+        if (0) {
+            // slice_segment_header_extension_length
+        }
+    }
+
+    u(1, 1, alignment_bit_equal_to_one);
+    while (put_bits_count(pbc) & 7)
+        u(1, 0, alignment_bit_equal_to_zero);
+}
+
+static int vaapi_encode_h265_write_sequence_header(AVCodecContext *avctx,
+                                                   char *data, size_t *data_len)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    PutBitContext pbc;
+    char tmp[256];
+    int err;
+    size_t nal_len, bit_len, bit_pos, next_len;
+
+    bit_len = *data_len;
+    bit_pos = 0;
+
+    init_put_bits(&pbc, tmp, sizeof(tmp));
+    vaapi_encode_h265_write_vps(&pbc, ctx);
+    nal_len = put_bits_count(&pbc);
+    flush_put_bits(&pbc);
+
+    next_len = bit_len - bit_pos;
+    err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8,
+                                                       &next_len,
+                                                       tmp, nal_len);
+    if (err < 0)
+        return err;
+    bit_pos += next_len;
+
+    init_put_bits(&pbc, tmp, sizeof(tmp));
+    vaapi_encode_h265_write_sps(&pbc, ctx);
+    nal_len = put_bits_count(&pbc);
+    flush_put_bits(&pbc);
+
+    next_len = bit_len - bit_pos;
+    err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8,
+                                                       &next_len,
+                                                       tmp, nal_len);
+    if (err < 0)
+        return err;
+    bit_pos += next_len;
+
+    init_put_bits(&pbc, tmp, sizeof(tmp));
+    vaapi_encode_h265_write_pps(&pbc, ctx);
+    nal_len = put_bits_count(&pbc);
+    flush_put_bits(&pbc);
+
+    next_len = bit_len - bit_pos;
+    err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8,
+                                                       &next_len,
+                                                       tmp, nal_len);
+    if (err < 0)
+        return err;
+    bit_pos += next_len;
+
+    *data_len = bit_pos;
+    return 0;
+}
+
+static int vaapi_encode_h265_write_slice_header(AVCodecContext *avctx,
+                                                VAAPIEncodePicture *pic,
+                                                VAAPIEncodeSlice *slice,
+                                                char *data, size_t *data_len)
+{
+    VAAPIEncodeContext *ctx = avctx->priv_data;
+    PutBitContext pbc;
+    char tmp[256];
+    size_t header_len;
+
+    init_put_bits(&pbc, tmp, sizeof(tmp));
+    vaapi_encode_h265_write_slice_header2(&pbc, ctx, pic, slice);
+    header_len = put_bits_count(&pbc);
+    flush_put_bits(&pbc);
+
+    return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len,
+                                                        tmp, header_len);
+}
+
+static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext                 *ctx = avctx->priv_data;
+    VAEncSequenceParameterBufferHEVC  *vseq = ctx->codec_sequence_params;
+    VAEncPictureParameterBufferHEVC   *vpic = ctx->codec_picture_params;
+    VAAPIEncodeH265Context            *priv = ctx->priv_data;
+    VAAPIEncodeH265MiscSequenceParams *mseq = &priv->misc_sequence_params;
+    int i;
+
+    {
+        // general_profile_space == 0.
+        vseq->general_profile_idc = 1; // Main profile (ctx->codec_profile?)
+        vseq->general_tier_flag = 0;
+
+        vseq->general_level_idc = avctx->level * 3;
+
+        vseq->intra_period = 0;
+        vseq->intra_idr_period = 0;
+        vseq->ip_period = 0;
+
+        vseq->pic_width_in_luma_samples  = ctx->aligned_width;
+        vseq->pic_height_in_luma_samples = ctx->aligned_height;
+
+        vseq->seq_fields.bits.chroma_format_idc = 1; // 4:2:0.
+        vseq->seq_fields.bits.separate_colour_plane_flag = 0;
+        vseq->seq_fields.bits.bit_depth_luma_minus8 = 0; // 8-bit luma.
+        vseq->seq_fields.bits.bit_depth_chroma_minus8 = 0; // 8-bit chroma.
+        // Other misc flags all zero.
+
+        // These have to come from the capabilities of the encoder.  We have
+        // no way to query it, so just hardcode ones which worked for me...
+        // CTB size from 8x8 to 32x32.
+        vseq->log2_min_luma_coding_block_size_minus3 = 0;
+        vseq->log2_diff_max_min_luma_coding_block_size = 2;
+        // Transform size from 4x4 to 32x32.
+        vseq->log2_min_transform_block_size_minus2 = 0;
+        vseq->log2_diff_max_min_transform_block_size = 3;
+        // Full transform hierarchy allowed (2-5).
+        vseq->max_transform_hierarchy_depth_inter = 3;
+        vseq->max_transform_hierarchy_depth_intra = 3;
+
+        vseq->vui_parameters_present_flag = 0;
+
+        vseq->bits_per_second = avctx->bit_rate;
+        if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
+            vseq->vui_num_units_in_tick = avctx->framerate.num;
+            vseq->vui_time_scale        = avctx->framerate.den;
+        } else {
+            vseq->vui_num_units_in_tick = avctx->time_base.num;
+            vseq->vui_time_scale        = avctx->time_base.den;
+        }
+
+        vseq->intra_period     = ctx->p_per_i * (ctx->b_per_p + 1);
+        vseq->intra_idr_period = vseq->intra_period;
+        vseq->ip_period        = ctx->b_per_p + 1;
+    }
+
+    {
+        vpic->decoded_curr_pic.picture_id = VA_INVALID_ID;
+        vpic->decoded_curr_pic.flags      = VA_PICTURE_HEVC_INVALID;
+
+        for (i = 0; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) {
+            vpic->reference_frames[i].picture_id = VA_INVALID_ID;
+            vpic->reference_frames[i].flags      = VA_PICTURE_HEVC_INVALID;
+        }
+
+        vpic->collocated_ref_pic_index = 0xff;
+
+        vpic->last_picture = 0;
+
+        vpic->pic_init_qp = priv->fixed_qp_idr;
+
+        vpic->diff_cu_qp_delta_depth = 0;
+        vpic->pps_cb_qp_offset = 0;
+        vpic->pps_cr_qp_offset = 0;
+
+        // tiles_enabled_flag == 0, so ignore num_tile_(rows|columns)_minus1.
+
+        vpic->log2_parallel_merge_level_minus2 = 0;
+
+        // No limit on size.
+        vpic->ctu_max_bitsize_allowed = 0;
+
+        vpic->num_ref_idx_l0_default_active_minus1 = 0;
+        vpic->num_ref_idx_l1_default_active_minus1 = 0;
+
+        vpic->slice_pic_parameter_set_id = 0;
+
+        vpic->pic_fields.bits.screen_content_flag = 0;
+        vpic->pic_fields.bits.enable_gpu_weighted_prediction = 0;
+        vpic->pic_fields.bits.cu_qp_delta_enabled_flag = 1;
+    }
+
+    {
+        mseq->video_parameter_set_id = 5;
+        mseq->seq_parameter_set_id = 5;
+
+        mseq->vps_max_layers_minus1 = 0;
+        mseq->vps_max_sub_layers_minus1 = 0;
+        mseq->vps_temporal_id_nesting_flag = 1;
+        mseq->sps_max_sub_layers_minus1 = 0;
+        mseq->sps_temporal_id_nesting_flag = 1;
+
+        for (i = 0; i < 32; i++) {
+            mseq->general_profile_compatibility_flag[i] =
+                (i == vseq->general_profile_idc);
+        }
+
+        mseq->general_progressive_source_flag    = 1;
+        mseq->general_interlaced_source_flag     = 0;
+        mseq->general_non_packed_constraint_flag = 0;
+        mseq->general_frame_only_constraint_flag = 1;
+        mseq->general_inbld_flag = 0;
+
+        mseq->log2_max_pic_order_cnt_lsb_minus4 = 8;
+        mseq->vps_sub_layer_ordering_info_present_flag = 0;
+        mseq->vps_max_dec_pic_buffering_minus1[0] = 1;
+        mseq->vps_max_num_reorder_pics[0]         = ctx->b_per_p;
+        mseq->vps_max_latency_increase_plus1[0]   = 0;
+        mseq->sps_sub_layer_ordering_info_present_flag = 0;
+        mseq->sps_max_dec_pic_buffering_minus1[0] = 1;
+        mseq->sps_max_num_reorder_pics[0]         = ctx->b_per_p;
+        mseq->sps_max_latency_increase_plus1[0]   = 0;
+
+        mseq->vps_timing_info_present_flag = 1;
+        mseq->vps_num_units_in_tick = avctx->time_base.num;
+        mseq->vps_time_scale        = avctx->time_base.den;
+        mseq->vps_poc_proportional_to_timing_flag = 1;
+        mseq->vps_num_ticks_poc_diff_minus1 = 0;
+
+        if (ctx->input_width  != ctx->aligned_width ||
+            ctx->input_height != ctx->aligned_height) {
+            mseq->conformance_window_flag = 1;
+            mseq->conf_win_left_offset   = 0;
+            mseq->conf_win_right_offset  =
+                (ctx->aligned_width - ctx->input_width) / 2;
+            mseq->conf_win_top_offset    = 0;
+            mseq->conf_win_bottom_offset =
+                (ctx->aligned_height - ctx->input_height) / 2;
+        } else {
+            mseq->conformance_window_flag = 0;
+        }
+
+        mseq->num_short_term_ref_pic_sets = 0;
+        // STRPSs should ideally be here rather than repeated in each slice.
+
+        mseq->vui_parameters_present_flag = 1;
+        if (avctx->sample_aspect_ratio.num != 0) {
+            mseq->aspect_ratio_info_present_flag = 1;
+            if (avctx->sample_aspect_ratio.num ==
+                avctx->sample_aspect_ratio.den) {
+                mseq->aspect_ratio_idc = 1;
+            } else {
+                mseq->aspect_ratio_idc = 255; // Extended SAR.
+                mseq->sar_width  = avctx->sample_aspect_ratio.num;
+                mseq->sar_height = avctx->sample_aspect_ratio.den;
+            }
+        }
+        if (1) {
+            // Should this be conditional on some of these being set?
+            mseq->video_signal_type_present_flag = 1;
+            mseq->video_format = 5; // Unspecified.
+            mseq->video_full_range_flag = 0;
+            mseq->colour_description_present_flag = 1;
+            mseq->colour_primaries = avctx->color_primaries;
+            mseq->transfer_characteristics = avctx->color_trc;
+            mseq->matrix_coeffs = avctx->colorspace;
+        }
+    }
+
+    return 0;
+}
+
+static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
+                                                 VAAPIEncodePicture *pic)
+{
+    VAAPIEncodeContext               *ctx = avctx->priv_data;
+    VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params;
+    VAAPIEncodeH265Context          *priv = ctx->priv_data;
+    int i;
+
+    if (pic->type == PICTURE_TYPE_IDR) {
+        av_assert0(pic->display_order == pic->encode_order);
+        priv->last_idr_frame = pic->display_order;
+    } else {
+        av_assert0(pic->encode_order > priv->last_idr_frame);
+        // Display order need not be if we have RA[SD]L pictures, though.
+    }
+
+    vpic->decoded_curr_pic.picture_id    = pic->recon_surface;
+    vpic->decoded_curr_pic.pic_order_cnt =
+        pic->display_order - priv->last_idr_frame;
+    vpic->decoded_curr_pic.flags         = 0;
+
+    for (i = 0; i < pic->nb_refs; i++) {
+        VAAPIEncodePicture *ref = pic->refs[i];
+        av_assert0(ref);
+        vpic->reference_frames[i].picture_id    = ref->recon_surface;
+        vpic->reference_frames[i].pic_order_cnt =
+            ref->display_order - priv->last_idr_frame;
+        vpic->reference_frames[i].flags =
+            (ref->display_order < pic->display_order ?
+             VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE : 0) |
+            (ref->display_order > pic->display_order ?
+             VA_PICTURE_HEVC_RPS_ST_CURR_AFTER  : 0);
+    }
+    for (; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++) {
+        vpic->reference_frames[i].picture_id = VA_INVALID_ID;
+        vpic->reference_frames[i].flags      = VA_PICTURE_HEVC_INVALID;
+    }
+
+    vpic->coded_buf = pic->output_buffer;
+
+    switch (pic->type) {
+    case PICTURE_TYPE_IDR:
+        vpic->nal_unit_type = NAL_IDR_W_RADL;
+        vpic->pic_fields.bits.idr_pic_flag = 1;
+        vpic->pic_fields.bits.coding_type  = 1;
+        vpic->pic_fields.bits.reference_pic_flag = 1;
+        break;
+    case PICTURE_TYPE_I:
+        vpic->nal_unit_type = NAL_TRAIL_R;
+        vpic->pic_fields.bits.idr_pic_flag = 0;
+        vpic->pic_fields.bits.coding_type  = 1;
+        vpic->pic_fields.bits.reference_pic_flag = 1;
+        break;
+    case PICTURE_TYPE_P:
+        vpic->nal_unit_type = NAL_TRAIL_R;
+        vpic->pic_fields.bits.idr_pic_flag = 0;
+        vpic->pic_fields.bits.coding_type  = 2;
+        vpic->pic_fields.bits.reference_pic_flag = 1;
+        break;
+    case PICTURE_TYPE_B:
+        vpic->nal_unit_type = NAL_TRAIL_R;
+        vpic->pic_fields.bits.idr_pic_flag = 0;
+        vpic->pic_fields.bits.coding_type  = 3;
+        vpic->pic_fields.bits.reference_pic_flag = 0;
+        break;
+    default:
+        av_assert0(0 && "invalid picture type");
+    }
+
+    pic->nb_slices = 1;
+
+    return 0;
+}
+
+static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
+                                               VAAPIEncodePicture *pic,
+                                               VAAPIEncodeSlice *slice)
+{
+    VAAPIEncodeContext                *ctx = avctx->priv_data;
+    VAEncPictureParameterBufferHEVC  *vpic = pic->codec_picture_params;
+    VAEncSliceParameterBufferHEVC  *vslice = slice->codec_slice_params;
+    VAAPIEncodeH265Context           *priv = ctx->priv_data;
+    VAAPIEncodeH265Slice           *pslice;
+    VAAPIEncodeH265MiscSliceParams *mslice;
+    int i;
+
+    slice->priv_data = av_mallocz(sizeof(*pslice));
+    if (!slice->priv_data)
+        return AVERROR(ENOMEM);
+    pslice = slice->priv_data;
+    mslice = &pslice->misc_slice_params;
+
+    // Currently we only support one slice per frame.
+    vslice->slice_segment_address = 0;
+    vslice->num_ctu_in_slice = priv->ctu_width * priv->ctu_height;
+
+    switch (pic->type) {
+    case PICTURE_TYPE_IDR:
+    case PICTURE_TYPE_I:
+        vslice->slice_type = I_SLICE;
+        break;
+    case PICTURE_TYPE_P:
+        vslice->slice_type = P_SLICE;
+        break;
+    case PICTURE_TYPE_B:
+        vslice->slice_type = B_SLICE;
+        break;
+    default:
+        av_assert0(0 && "invalid picture type");
+    }
+
+    vslice->slice_pic_parameter_set_id = vpic->slice_pic_parameter_set_id;
+
+    pslice->pic_order_cnt = pic->display_order - priv->last_idr_frame;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) {
+        vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID;
+        vslice->ref_pic_list0[i].flags      = VA_PICTURE_HEVC_INVALID;
+        vslice->ref_pic_list1[i].picture_id = VA_INVALID_ID;
+        vslice->ref_pic_list1[i].flags      = VA_PICTURE_HEVC_INVALID;
+    }
+
+    av_assert0(pic->nb_refs <= 2);
+    if (pic->nb_refs >= 1) {
+        // Backward reference for P- or B-frame.
+        av_assert0(pic->type == PICTURE_TYPE_P ||
+                   pic->type == PICTURE_TYPE_B);
+
+        vslice->num_ref_idx_l0_active_minus1 = 0;
+        vslice->ref_pic_list0[0] = vpic->reference_frames[0];
+    }
+    if (pic->nb_refs >= 2) {
+        // Forward reference for B-frame.
+        av_assert0(pic->type == PICTURE_TYPE_B);
+
+        vslice->num_ref_idx_l1_active_minus1 = 0;
+        vslice->ref_pic_list1[0] = vpic->reference_frames[1];
+    }
+
+    vslice->max_num_merge_cand = 5;
+
+    if (pic->type == PICTURE_TYPE_B)
+        vslice->slice_qp_delta = priv->fixed_qp_b  - vpic->pic_init_qp;
+    else if (pic->type == PICTURE_TYPE_P)
+        vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp;
+    else
+        vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp;
+
+    vslice->slice_fields.bits.last_slice_of_pic_flag = 1;
+
+    mslice->first_slice_segment_in_pic_flag = 1;
+
+    if (pic->type == PICTURE_TYPE_IDR) {
+        // No reference pictures.
+    } else if (0) {
+        mslice->short_term_ref_pic_set_sps_flag = 1;
+        mslice->short_term_ref_pic_idx = 0;
+    } else {
+        VAAPIEncodePicture *st;
+        int used;
+
+        mslice->short_term_ref_pic_set_sps_flag = 0;
+        mslice->st_ref_pic_set.inter_ref_pic_set_prediction_flag = 0;
+
+        for (st = ctx->pic_start; st; st = st->next) {
+            if (st->encode_order >= pic->encode_order) {
+                // Not yet in DPB.
+                continue;
+            }
+            used = 0;
+            for (i = 0; i < pic->nb_refs; i++) {
+                if (pic->refs[i] == st)
+                    used = 1;
+            }
+            if (!used) {
+                // Currently true, but need not be.
+                continue;
+            }
+            // This only works for one instance of each (delta_poc_sN_minus1
+            // is relative to the previous frame in the list, not relative to
+            // the current frame directly).
+            if (st->display_order < pic->display_order) {
+                i = mslice->st_ref_pic_set.num_negative_pics;
+                mslice->st_ref_pic_set.delta_poc_s0_minus1[i] =
+                    pic->display_order - st->display_order - 1;
+                mslice->st_ref_pic_set.used_by_curr_pic_s0_flag[i] = used;
+                ++mslice->st_ref_pic_set.num_negative_pics;
+            } else {
+                i = mslice->st_ref_pic_set.num_positive_pics;
+                mslice->st_ref_pic_set.delta_poc_s1_minus1[i] =
+                    st->display_order - pic->display_order - 1;
+                mslice->st_ref_pic_set.used_by_curr_pic_s1_flag[i] = used;
+                ++mslice->st_ref_pic_set.num_positive_pics;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static av_cold int vaapi_encode_h265_init_constant_bitrate(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH265Context *priv = ctx->priv_data;
+    int hrd_buffer_size;
+    int hrd_initial_buffer_fullness;
+
+    if (avctx->bit_rate > INT32_MAX) {
+        av_log(avctx, AV_LOG_ERROR, "Target bitrate of 2^31 bps or "
+               "higher is not supported.\n");
+        return AVERROR(EINVAL);
+    }
+
+    if (avctx->rc_buffer_size)
+        hrd_buffer_size = avctx->rc_buffer_size;
+    else
+        hrd_buffer_size = avctx->bit_rate;
+    if (avctx->rc_initial_buffer_occupancy)
+        hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
+    else
+        hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
+
+    priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl;
+    priv->rc_params.rc = (VAEncMiscParameterRateControl) {
+        .bits_per_second   = avctx->bit_rate,
+        .target_percentage = 66,
+        .window_size       = 1000,
+        .initial_qp        = (avctx->qmax >= 0 ? avctx->qmax : 40),
+        .min_qp            = (avctx->qmin >= 0 ? avctx->qmin : 20),
+        .basic_unit_size   = 0,
+    };
+    ctx->global_params[ctx->nb_global_params] =
+        &priv->rc_params.misc;
+    ctx->global_params_size[ctx->nb_global_params++] =
+        sizeof(priv->rc_params);
+
+    priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD;
+    priv->hrd_params.hrd = (VAEncMiscParameterHRD) {
+        .initial_buffer_fullness = hrd_initial_buffer_fullness,
+        .buffer_size             = hrd_buffer_size,
+    };
+    ctx->global_params[ctx->nb_global_params] =
+        &priv->hrd_params.misc;
+    ctx->global_params_size[ctx->nb_global_params++] =
+        sizeof(priv->hrd_params);
+
+    // These still need to be  set for pic_init_qp/slice_qp_delta.
+    priv->fixed_qp_idr = 30;
+    priv->fixed_qp_p   = 30;
+    priv->fixed_qp_b   = 30;
+
+    av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %"PRId64" bps.\n",
+           avctx->bit_rate);
+    return 0;
+}
+
+static av_cold int vaapi_encode_h265_init_fixed_qp(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH265Context *priv = ctx->priv_data;
+    VAAPIEncodeH265Options  *opt = ctx->codec_options;
+
+    priv->fixed_qp_p = opt->qp;
+    if (avctx->i_quant_factor > 0.0)
+        priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
+                                    avctx->i_quant_offset) + 0.5);
+    else
+        priv->fixed_qp_idr = priv->fixed_qp_p;
+    if (avctx->b_quant_factor > 0.0)
+        priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
+                                  avctx->b_quant_offset) + 0.5);
+    else
+        priv->fixed_qp_b = priv->fixed_qp_p;
+
+    av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
+           "%d / %d / %d for IDR- / P- / B-frames.\n",
+           priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
+    return 0;
+}
+
+static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
+{
+    static const VAConfigAttrib default_config_attributes[] = {
+        { .type  = VAConfigAttribRTFormat,
+          .value = VA_RT_FORMAT_YUV420 },
+        { .type  = VAConfigAttribEncPackedHeaders,
+          .value = (VA_ENC_PACKED_HEADER_SEQUENCE |
+                    VA_ENC_PACKED_HEADER_SLICE) },
+    };
+
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH265Context *priv = ctx->priv_data;
+    int i, err;
+
+    switch (avctx->profile) {
+    case FF_PROFILE_HEVC_MAIN:
+    case FF_PROFILE_UNKNOWN:
+        ctx->va_profile = VAProfileHEVCMain;
+        break;
+    case FF_PROFILE_HEVC_MAIN_10:
+        av_log(avctx, AV_LOG_ERROR, "H.265 main 10-bit profile "
+               "is not supported.\n");
+        return AVERROR_PATCHWELCOME;
+    default:
+        av_log(avctx, AV_LOG_ERROR, "Unknown H.265 profile %d.\n",
+               avctx->profile);
+        return AVERROR(EINVAL);
+    }
+    ctx->va_entrypoint = VAEntrypointEncSlice;
+
+    ctx->input_width    = avctx->width;
+    ctx->input_height   = avctx->height;
+    ctx->aligned_width  = FFALIGN(ctx->input_width,  16);
+    ctx->aligned_height = FFALIGN(ctx->input_height, 16);
+    priv->ctu_width     = FFALIGN(ctx->aligned_width,  32) / 32;
+    priv->ctu_height    = FFALIGN(ctx->aligned_height, 32) / 32;
+
+    av_log(avctx, AV_LOG_VERBOSE, "Input %ux%u -> Aligned %ux%u -> CTU %ux%u.\n",
+           ctx->input_width, ctx->input_height, ctx->aligned_width,
+           ctx->aligned_height, priv->ctu_width, priv->ctu_height);
+
+    for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
+        ctx->config_attributes[ctx->nb_config_attributes++] =
+            default_config_attributes[i];
+    }
+
+    if (avctx->bit_rate > 0) {
+        ctx->va_rc_mode = VA_RC_CBR;
+        err = vaapi_encode_h265_init_constant_bitrate(avctx);
+    } else {
+        ctx->va_rc_mode = VA_RC_CQP;
+        err = vaapi_encode_h265_init_fixed_qp(avctx);
+    }
+    if (err < 0)
+        return err;
+
+    ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
+        .type  = VAConfigAttribRateControl,
+        .value = ctx->va_rc_mode,
+    };
+
+    ctx->nb_recon_frames = 20;
+
+    return 0;
+}
+
+static VAAPIEncodeType vaapi_encode_type_h265 = {
+    .priv_data_size        = sizeof(VAAPIEncodeH265Context),
+
+    .init                  = &vaapi_encode_h265_init_internal,
+
+    .sequence_params_size  = sizeof(VAEncSequenceParameterBufferHEVC),
+    .init_sequence_params  = &vaapi_encode_h265_init_sequence_params,
+
+    .picture_params_size   = sizeof(VAEncPictureParameterBufferHEVC),
+    .init_picture_params   = &vaapi_encode_h265_init_picture_params,
+
+    .slice_params_size     = sizeof(VAEncSliceParameterBufferHEVC),
+    .init_slice_params     = &vaapi_encode_h265_init_slice_params,
+
+    .sequence_header_type  = VAEncPackedHeaderSequence,
+    .write_sequence_header = &vaapi_encode_h265_write_sequence_header,
+
+    .slice_header_type     = VAEncPackedHeaderHEVC_Slice,
+    .write_slice_header    = &vaapi_encode_h265_write_slice_header,
+};
+
+static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx)
+{
+    return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h265);
+}
+
+#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
+                   offsetof(VAAPIEncodeH265Options, x))
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
+static const AVOption vaapi_encode_h265_options[] = {
+    { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
+      OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, 52, FLAGS },
+    { NULL },
+};
+
+static const AVCodecDefault vaapi_encode_h265_defaults[] = {
+    { "profile",        "1"   },
+    { "level",          "51"  },
+    { "b",              "0"   },
+    { "bf",             "2"   },
+    { "g",              "120" },
+    { "i_qfactor",      "1.0" },
+    { "i_qoffset",      "0.0" },
+    { "b_qfactor",      "1.2" },
+    { "b_qoffset",      "0.0" },
+    { NULL },
+};
+
+static const AVClass vaapi_encode_h265_class = {
+    .class_name = "h265_vaapi",
+    .item_name  = av_default_item_name,
+    .option     = vaapi_encode_h265_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_hevc_vaapi_encoder = {
+    .name           = "hevc_vaapi",
+    .long_name      = NULL_IF_CONFIG_SMALL("H.265/HEVC (VAAPI)"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_HEVC,
+    .priv_data_size = (sizeof(VAAPIEncodeContext) +
+                       sizeof(VAAPIEncodeH265Options)),
+    .init           = &vaapi_encode_h265_init,
+    .encode2        = &ff_vaapi_encode2,
+    .close          = &ff_vaapi_encode_close,
+    .priv_class     = &vaapi_encode_h265_class,
+    .capabilities   = AV_CODEC_CAP_DELAY,
+    .defaults       = vaapi_encode_h265_defaults,
+    .pix_fmts = (const enum AVPixelFormat[]) {
+        AV_PIX_FMT_VAAPI,
+        AV_PIX_FMT_NONE,
+    },
+};
diff --git a/libavcodec/vaapi_encode_h26x.c b/libavcodec/vaapi_encode_h26x.c
new file mode 100644
index 0000000..d806f9b
--- /dev/null
+++ b/libavcodec/vaapi_encode_h26x.c
@@ -0,0 +1,68 @@
+/*
+ * 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 <stdint.h>
+
+#include "vaapi_encode_h26x.h"
+
+int ff_vaapi_encode_h26x_nal_unit_to_byte_stream(uint8_t *dst, size_t *dst_bit_len,
+                                                 uint8_t *src, size_t src_bit_len)
+{
+    size_t dp, sp;
+    int zero_run = 0;
+    size_t dst_len = *dst_bit_len / 8;
+    size_t src_len = (src_bit_len + 7) / 8;
+    int trailing_zeroes = src_len * 8 - src_bit_len;
+
+    if (dst_len < src_len + 4) {
+        // Definitely doesn't fit.
+        goto fail;
+    }
+
+    // Start code.
+    dst[0] = dst[1] = dst[2] = 0;
+    dst[3] = 1;
+    dp = 4;
+
+    for (sp = 0; sp < src_len; sp++) {
+        if (dp >= dst_len)
+            goto fail;
+        if (zero_run < 2) {
+            if (src[sp] == 0)
+                ++zero_run;
+            else
+                zero_run = 0;
+        } else {
+            if ((src[sp] & ~3) == 0) {
+                // emulation_prevention_three_byte
+                dst[dp++] = 3;
+                if (dp >= dst_len)
+                    goto fail;
+            }
+            zero_run = src[sp] == 0;
+        }
+        dst[dp++] = src[sp];
+    }
+
+    *dst_bit_len = 8 * dp - trailing_zeroes;
+    return 0;
+
+fail:
+    *dst_bit_len = 0;
+    return AVERROR(ENOSPC);
+}
diff --git a/libavcodec/vaapi_encode_h26x.h b/libavcodec/vaapi_encode_h26x.h
new file mode 100644
index 0000000..f8c6e13
--- /dev/null
+++ b/libavcodec/vaapi_encode_h26x.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VAAPI_ENCODE_H26X_H
+#define AVCODEC_VAAPI_ENCODE_H26X_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "golomb.h"
+#include "put_bits.h"
+
+
+// Debug code may be interested in the name of the syntax element being
+// for tracing purposes.  Here, it is just discarded.
+
+#define write_u(pbc, width, value, name) put_bits(pbc, width, value)
+#define write_ue(pbc, value, name)       set_ue_golomb(pbc, value)
+#define write_se(pbc, value, name)       set_se_golomb(pbc, value)
+
+#define u(width, ...) write_u(pbc, width, __VA_ARGS__)
+#define ue(...)       write_ue(pbc, __VA_ARGS__)
+#define se(...)       write_se(pbc, __VA_ARGS__)
+
+
+// Copy from src to dst, applying emulation prevention.
+int ff_vaapi_encode_h26x_nal_unit_to_byte_stream(uint8_t *dst, size_t *dst_len,
+                                                 uint8_t *src, size_t src_len);
+
+#endif /* AVCODEC_VAAPI_ENCODE_H26X_H */
diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c
new file mode 100644
index 0000000..316b359
--- /dev/null
+++ b/libavcodec/vaapi_encode_mjpeg.c
@@ -0,0 +1,422 @@
+/*
+ * 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 <va/va.h>
+#include <va/va_enc_jpeg.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/common.h"
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixfmt.h"
+
+#include "avcodec.h"
+#include "internal.h"
+#include "jpegtables.h"
+#include "mjpeg.h"
+#include "put_bits.h"
+#include "vaapi_encode.h"
+
+
+// Standard JPEG quantisation tables, in zigzag order.
+static const unsigned char vaapi_encode_mjpeg_quant_luminance[64] = {
+    16,  11,  12,  14,  12,  10,  16,  14,
+    13,  14,  18,  17,  16,  19,  24,  40,
+    26,  24,  22,  22,  24,  49,  35,  37,
+    29,  40,  58,  51,  61,  60,  57,  51,
+    56,  55,  64,  72,  92,  78,  64,  68,
+    87,  69,  55,  56,  80, 109,  81,  87,
+    95,  98, 103, 104, 103,  62,  77, 113,
+   121, 112, 100, 120,  92, 101, 103,  99,
+};
+static const unsigned char vaapi_encode_mjpeg_quant_chrominance[64] = {
+    17,  18,  18,  24,  21,  24,  47,  26,
+    26,  47,  99,  66,  56,  66,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+};
+
+typedef struct VAAPIEncodeMJPEGContext {
+    int quality;
+    int component_subsample_h[3];
+    int component_subsample_v[3];
+
+    VAQMatrixBufferJPEG quant_tables;
+    VAHuffmanTableBufferJPEGBaseline huffman_tables;
+} VAAPIEncodeMJPEGContext;
+
+static av_cold void vaapi_encode_mjpeg_copy_huffman(unsigned char *dst_lengths,
+                                                    unsigned char *dst_values,
+                                                    const unsigned char *src_lengths,
+                                                    const unsigned char *src_values)
+{
+    int i, mt;
+
+    ++src_lengths;
+
+    mt = 0;
+    for (i = 0; i < 16; i++)
+        mt += (dst_lengths[i] = src_lengths[i]);
+
+    for (i = 0; i < mt; i++)
+        dst_values[i] = src_values[i];
+}
+
+static av_cold void vaapi_encode_mjpeg_init_tables(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext                *ctx = avctx->priv_data;
+    VAAPIEncodeMJPEGContext          *priv = ctx->priv_data;
+    VAQMatrixBufferJPEG             *quant = &priv->quant_tables;
+    VAHuffmanTableBufferJPEGBaseline *huff = &priv->huffman_tables;
+    int i;
+
+    quant->load_lum_quantiser_matrix = 1;
+    quant->load_chroma_quantiser_matrix = 1;
+
+    for (i = 0; i < 64; i++) {
+        quant->lum_quantiser_matrix[i] =
+            vaapi_encode_mjpeg_quant_luminance[i];
+        quant->chroma_quantiser_matrix[i] =
+            vaapi_encode_mjpeg_quant_chrominance[i];
+    }
+
+    huff->load_huffman_table[0] = 1;
+    vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[0].num_dc_codes,
+                                    huff->huffman_table[0].dc_values,
+                                    avpriv_mjpeg_bits_dc_luminance,
+                                    avpriv_mjpeg_val_dc);
+    vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[0].num_ac_codes,
+                                    huff->huffman_table[0].ac_values,
+                                    avpriv_mjpeg_bits_ac_luminance,
+                                    avpriv_mjpeg_val_ac_luminance);
+    memset(huff->huffman_table[0].pad, 0, sizeof(huff->huffman_table[0].pad));
+
+    huff->load_huffman_table[1] = 1;
+    vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[1].num_dc_codes,
+                                    huff->huffman_table[1].dc_values,
+                                    avpriv_mjpeg_bits_dc_chrominance,
+                                    avpriv_mjpeg_val_dc);
+    vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[1].num_ac_codes,
+                                    huff->huffman_table[1].ac_values,
+                                    avpriv_mjpeg_bits_ac_chrominance,
+                                    avpriv_mjpeg_val_ac_chrominance);
+    memset(huff->huffman_table[1].pad, 0, sizeof(huff->huffman_table[1].pad));
+}
+
+static void vaapi_encode_mjpeg_write_marker(PutBitContext *pbc, int marker)
+{
+    put_bits(pbc, 8, 0xff);
+    put_bits(pbc, 8, marker);
+}
+
+static int vaapi_encode_mjpeg_write_image_header(AVCodecContext *avctx,
+                                                 VAAPIEncodePicture *pic,
+                                                 VAAPIEncodeSlice *slice,
+                                                 char *data, size_t *data_len)
+{
+    VAAPIEncodeContext               *ctx = avctx->priv_data;
+    VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params;
+    VAEncSliceParameterBufferJPEG *vslice = slice->codec_slice_params;
+    VAAPIEncodeMJPEGContext         *priv = ctx->priv_data;
+    PutBitContext pbc;
+    int t, i, quant_scale;
+
+    init_put_bits(&pbc, data, *data_len);
+
+    vaapi_encode_mjpeg_write_marker(&pbc, SOI);
+
+    // Quantisation table coefficients are scaled for quality by the driver,
+    // so we also need to do it ourselves here so that headers match.
+    if (priv->quality < 50)
+        quant_scale = 5000 / priv->quality;
+    else
+        quant_scale = 200 - 2 * priv->quality;
+
+    for (t = 0; t < 2; t++) {
+        int q;
+
+        vaapi_encode_mjpeg_write_marker(&pbc, DQT);
+
+        put_bits(&pbc, 16, 3 + 64); // Lq
+        put_bits(&pbc, 4, 0); // Pq
+        put_bits(&pbc, 4, t); // Tq
+
+        for (i = 0; i < 64; i++) {
+            q = i[t ? priv->quant_tables.chroma_quantiser_matrix
+                    : priv->quant_tables.lum_quantiser_matrix];
+            q = (q * quant_scale) / 100;
+            if (q < 1)   q = 1;
+            if (q > 255) q = 255;
+            put_bits(&pbc, 8, q);
+        }
+    }
+
+    vaapi_encode_mjpeg_write_marker(&pbc, SOF0);
+
+    put_bits(&pbc, 16, 8 + 3 * vpic->num_components); // Lf
+    put_bits(&pbc, 8,  vpic->sample_bit_depth); // P
+    put_bits(&pbc, 16, vpic->picture_height);   // Y
+    put_bits(&pbc, 16, vpic->picture_width);    // X
+    put_bits(&pbc, 8,  vpic->num_components);   // Nf
+
+    for (i = 0; i < vpic->num_components; i++) {
+        put_bits(&pbc, 8, vpic->component_id[i]); // Ci
+        put_bits(&pbc, 4, priv->component_subsample_h[i]); // Hi
+        put_bits(&pbc, 4, priv->component_subsample_v[i]); // Vi
+        put_bits(&pbc, 8, vpic->quantiser_table_selector[i]); // Tqi
+    }
+
+    for (t = 0; t < 4; t++) {
+        int mt;
+        unsigned char *lengths, *values;
+
+        vaapi_encode_mjpeg_write_marker(&pbc, DHT);
+
+        if ((t & 1) == 0) {
+            lengths = priv->huffman_tables.huffman_table[t / 2].num_dc_codes;
+            values  = priv->huffman_tables.huffman_table[t / 2].dc_values;
+        } else {
+            lengths = priv->huffman_tables.huffman_table[t / 2].num_ac_codes;
+            values  = priv->huffman_tables.huffman_table[t / 2].ac_values;
+        }
+
+        mt = 0;
+        for (i = 0; i < 16; i++)
+            mt += lengths[i];
+
+        put_bits(&pbc, 16, 2 + 17 + mt); // Lh
+        put_bits(&pbc, 4, t & 1); // Tc
+        put_bits(&pbc, 4, t / 2); // Th
+
+        for (i = 0; i < 16; i++)
+            put_bits(&pbc, 8, lengths[i]);
+        for (i = 0; i < mt; i++)
+            put_bits(&pbc, 8, values[i]);
+    }
+
+    vaapi_encode_mjpeg_write_marker(&pbc, SOS);
+
+    av_assert0(vpic->num_components == vslice->num_components);
+
+    put_bits(&pbc, 16, 6 + 2 * vslice->num_components); // Ls
+    put_bits(&pbc, 8,  vslice->num_components); // Ns
+
+    for (i = 0; i < vslice->num_components; i++) {
+        put_bits(&pbc, 8, vslice->components[i].component_selector); // Csj
+        put_bits(&pbc, 4, vslice->components[i].dc_table_selector);  // Tdj
+        put_bits(&pbc, 4, vslice->components[i].ac_table_selector);  // Taj
+    }
+
+    put_bits(&pbc, 8, 0); // Ss
+    put_bits(&pbc, 8, 63); // Se
+    put_bits(&pbc, 4, 0); // Ah
+    put_bits(&pbc, 4, 0); // Al
+
+    *data_len = put_bits_count(&pbc);
+    flush_put_bits(&pbc);
+
+    return 0;
+}
+
+static int vaapi_encode_mjpeg_write_extra_buffer(AVCodecContext *avctx,
+                                                 VAAPIEncodePicture *pic,
+                                                 int index, int *type,
+                                                 char *data, size_t *data_len)
+{
+    VAAPIEncodeContext       *ctx = avctx->priv_data;
+    VAAPIEncodeMJPEGContext *priv = ctx->priv_data;
+
+    if (index == 0) {
+        // Write quantisation tables.
+        if (*data_len < sizeof(priv->quant_tables))
+            return AVERROR(EINVAL);
+        *type = VAQMatrixBufferType;
+        memcpy(data, &priv->quant_tables,
+               *data_len = sizeof(priv->quant_tables));
+
+    } else if (index == 1) {
+        // Write huffman tables.
+        if (*data_len < sizeof(priv->huffman_tables))
+            return AVERROR(EINVAL);
+        *type = VAHuffmanTableBufferType;
+        memcpy(data, &priv->huffman_tables,
+               *data_len = sizeof(priv->huffman_tables));
+
+    } else {
+        return AVERROR_EOF;
+    }
+    return 0;
+}
+
+static int vaapi_encode_mjpeg_init_picture_params(AVCodecContext *avctx,
+                                                  VAAPIEncodePicture *pic)
+{
+    VAAPIEncodeContext               *ctx = avctx->priv_data;
+    VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params;
+    VAAPIEncodeMJPEGContext         *priv = ctx->priv_data;
+
+    vpic->reconstructed_picture = pic->recon_surface;
+    vpic->coded_buf = pic->output_buffer;
+
+    vpic->picture_width  = ctx->input_width;
+    vpic->picture_height = ctx->input_height;
+
+    vpic->pic_flags.bits.profile      = 0;
+    vpic->pic_flags.bits.progressive  = 0;
+    vpic->pic_flags.bits.huffman      = 1;
+    vpic->pic_flags.bits.interleaved  = 0;
+    vpic->pic_flags.bits.differential = 0;
+
+    vpic->sample_bit_depth = 8;
+    vpic->num_scan = 1;
+
+    vpic->num_components = 3;
+
+    vpic->component_id[0] = 1;
+    vpic->component_id[1] = 2;
+    vpic->component_id[2] = 3;
+
+    priv->component_subsample_h[0] = 2;
+    priv->component_subsample_v[0] = 2;
+    priv->component_subsample_h[1] = 1;
+    priv->component_subsample_v[1] = 1;
+    priv->component_subsample_h[2] = 1;
+    priv->component_subsample_v[2] = 1;
+
+    vpic->quantiser_table_selector[0] = 0;
+    vpic->quantiser_table_selector[1] = 1;
+    vpic->quantiser_table_selector[2] = 1;
+
+    vpic->quality = priv->quality;
+
+    pic->nb_slices = 1;
+
+    return 0;
+}
+
+static int vaapi_encode_mjpeg_init_slice_params(AVCodecContext *avctx,
+                                                VAAPIEncodePicture *pic,
+                                                VAAPIEncodeSlice *slice)
+{
+    VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params;
+    VAEncSliceParameterBufferJPEG *vslice = slice->codec_slice_params;
+    int i;
+
+    vslice->restart_interval = 0;
+
+    vslice->num_components = vpic->num_components;
+    for (i = 0; i < vslice->num_components; i++) {
+        vslice->components[i].component_selector = i + 1;
+        vslice->components[i].dc_table_selector = (i > 0);
+        vslice->components[i].ac_table_selector = (i > 0);
+    }
+
+    return 0;
+}
+
+static av_cold int vaapi_encode_mjpeg_init_internal(AVCodecContext *avctx)
+{
+    static const VAConfigAttrib default_config_attributes[] = {
+        { .type  = VAConfigAttribRTFormat,
+          .value = VA_RT_FORMAT_YUV420 },
+        { .type  = VAConfigAttribEncPackedHeaders,
+          .value = VA_ENC_PACKED_HEADER_SEQUENCE },
+    };
+
+    VAAPIEncodeContext       *ctx = avctx->priv_data;
+    VAAPIEncodeMJPEGContext *priv = ctx->priv_data;
+    int i;
+
+    ctx->va_profile    = VAProfileJPEGBaseline;
+    ctx->va_entrypoint = VAEntrypointEncPicture;
+
+    ctx->input_width    = avctx->width;
+    ctx->input_height   = avctx->height;
+    ctx->aligned_width  = FFALIGN(ctx->input_width,  8);
+    ctx->aligned_height = FFALIGN(ctx->input_height, 8);
+
+    for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
+        ctx->config_attributes[ctx->nb_config_attributes++] =
+            default_config_attributes[i];
+    }
+
+    priv->quality = avctx->global_quality;
+    if (priv->quality < 1 || priv->quality > 100) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid quality value %d "
+               "(must be 1-100).\n", priv->quality);
+        return AVERROR(EINVAL);
+    }
+
+    vaapi_encode_mjpeg_init_tables(avctx);
+
+    return 0;
+}
+
+static VAAPIEncodeType vaapi_encode_type_mjpeg = {
+    .priv_data_size        = sizeof(VAAPIEncodeMJPEGContext),
+
+    .init                  = &vaapi_encode_mjpeg_init_internal,
+
+    .picture_params_size   = sizeof(VAEncPictureParameterBufferJPEG),
+    .init_picture_params   = &vaapi_encode_mjpeg_init_picture_params,
+
+    .slice_params_size     = sizeof(VAEncSliceParameterBufferJPEG),
+    .init_slice_params     = &vaapi_encode_mjpeg_init_slice_params,
+
+    .slice_header_type     = VAEncPackedHeaderRawData,
+    .write_slice_header    = &vaapi_encode_mjpeg_write_image_header,
+
+    .write_extra_buffer    = &vaapi_encode_mjpeg_write_extra_buffer,
+};
+
+static av_cold int vaapi_encode_mjpeg_init(AVCodecContext *avctx)
+{
+    return ff_vaapi_encode_init(avctx, &vaapi_encode_type_mjpeg);
+}
+
+static const AVCodecDefault vaapi_encode_mjpeg_defaults[] = {
+    { "global_quality", "80" },
+    { NULL },
+};
+
+static const AVClass vaapi_encode_mjpeg_class = {
+    .class_name = "mjpeg_vaapi",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_mjpeg_vaapi_encoder = {
+    .name           = "mjpeg_vaapi",
+    .long_name      = NULL_IF_CONFIG_SMALL("MJPEG (VAAPI)"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_MJPEG,
+    .priv_data_size = sizeof(VAAPIEncodeContext),
+    .init           = &vaapi_encode_mjpeg_init,
+    .encode2        = &ff_vaapi_encode2,
+    .close          = &ff_vaapi_encode_close,
+    .priv_class     = &vaapi_encode_mjpeg_class,
+    .defaults       = vaapi_encode_mjpeg_defaults,
+    .pix_fmts = (const enum AVPixelFormat[]) {
+        AV_PIX_FMT_VAAPI,
+        AV_PIX_FMT_NONE,
+    },
+};
diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c
index ded2cb3..92efb26 100644
--- a/libavcodec/vaapi_h264.c
+++ b/libavcodec/vaapi_h264.c
@@ -196,25 +196,25 @@ static void fill_vaapi_plain_pred_weight_table(H264Context   *h,
     H264SliceContext *sl = &h->slice_ctx[0];
     unsigned int i, j;
 
-    *luma_weight_flag    = sl->luma_weight_flag[list];
-    *chroma_weight_flag  = sl->chroma_weight_flag[list];
+    *luma_weight_flag    = sl->pwt.luma_weight_flag[list];
+    *chroma_weight_flag  = sl->pwt.chroma_weight_flag[list];
 
     for (i = 0; i < sl->ref_count[list]; i++) {
         /* VA API also wants the inferred (default) values, not
            only what is available in the bitstream (7.4.3.2). */
-        if (sl->luma_weight_flag[list]) {
-            luma_weight[i] = sl->luma_weight[i][list][0];
-            luma_offset[i] = sl->luma_weight[i][list][1];
+        if (sl->pwt.luma_weight_flag[list]) {
+            luma_weight[i] = sl->pwt.luma_weight[i][list][0];
+            luma_offset[i] = sl->pwt.luma_weight[i][list][1];
         } else {
-            luma_weight[i] = 1 << sl->luma_log2_weight_denom;
+            luma_weight[i] = 1 << sl->pwt.luma_log2_weight_denom;
             luma_offset[i] = 0;
         }
         for (j = 0; j < 2; j++) {
-            if (sl->chroma_weight_flag[list]) {
-                chroma_weight[i][j] = sl->chroma_weight[i][list][j][0];
-                chroma_offset[i][j] = sl->chroma_weight[i][list][j][1];
+            if (sl->pwt.chroma_weight_flag[list]) {
+                chroma_weight[i][j] = sl->pwt.chroma_weight[i][list][j][0];
+                chroma_offset[i][j] = sl->pwt.chroma_weight[i][list][j][1];
             } else {
-                chroma_weight[i][j] = 1 << sl->chroma_log2_weight_denom;
+                chroma_weight[i][j] = 1 << sl->pwt.chroma_log2_weight_denom;
                 chroma_offset[i][j] = 0;
             }
         }
@@ -228,11 +228,11 @@ static int vaapi_h264_start_frame(AVCodecContext          *avctx,
 {
     H264Context * const h = avctx->priv_data;
     FFVAContext * const vactx = ff_vaapi_get_context(avctx);
+    const PPS *pps = h->ps.pps;
+    const SPS *sps = h->ps.sps;
     VAPictureParameterBufferH264 *pic_param;
     VAIQMatrixBufferH264 *iq_matrix;
 
-    ff_dlog(avctx, "vaapi_h264_start_frame()\n");
-
     vactx->slice_param_size = sizeof(VASliceParameterBufferH264);
 
     /* Fill in VAPictureParameterBufferH264. */
@@ -244,48 +244,48 @@ static int vaapi_h264_start_frame(AVCodecContext          *avctx,
         return -1;
     pic_param->picture_width_in_mbs_minus1                      = h->mb_width - 1;
     pic_param->picture_height_in_mbs_minus1                     = h->mb_height - 1;
-    pic_param->bit_depth_luma_minus8                            = h->sps.bit_depth_luma - 8;
-    pic_param->bit_depth_chroma_minus8                          = h->sps.bit_depth_chroma - 8;
-    pic_param->num_ref_frames                                   = h->sps.ref_frame_count;
+    pic_param->bit_depth_luma_minus8                            = sps->bit_depth_luma - 8;
+    pic_param->bit_depth_chroma_minus8                          = sps->bit_depth_chroma - 8;
+    pic_param->num_ref_frames                                   = sps->ref_frame_count;
     pic_param->seq_fields.value                                 = 0; /* reset all bits */
-    pic_param->seq_fields.bits.chroma_format_idc                = h->sps.chroma_format_idc;
-    pic_param->seq_fields.bits.residual_colour_transform_flag   = h->sps.residual_color_transform_flag; /* XXX: only for 4:4:4 high profile? */
-    pic_param->seq_fields.bits.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag;
-    pic_param->seq_fields.bits.frame_mbs_only_flag              = h->sps.frame_mbs_only_flag;
-    pic_param->seq_fields.bits.mb_adaptive_frame_field_flag     = h->sps.mb_aff;
-    pic_param->seq_fields.bits.direct_8x8_inference_flag        = h->sps.direct_8x8_inference_flag;
-    pic_param->seq_fields.bits.MinLumaBiPredSize8x8             = h->sps.level_idc >= 31; /* A.3.3.2 */
-    pic_param->seq_fields.bits.log2_max_frame_num_minus4        = h->sps.log2_max_frame_num - 4;
-    pic_param->seq_fields.bits.pic_order_cnt_type               = h->sps.poc_type;
-    pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4;
-    pic_param->seq_fields.bits.delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag;
-    pic_param->num_slice_groups_minus1                          = h->pps.slice_group_count - 1;
-    pic_param->slice_group_map_type                             = h->pps.mb_slice_group_map_type;
+    pic_param->seq_fields.bits.chroma_format_idc                = sps->chroma_format_idc;
+    pic_param->seq_fields.bits.residual_colour_transform_flag   = sps->residual_color_transform_flag; /* XXX: only for 4:4:4 high profile? */
+    pic_param->seq_fields.bits.gaps_in_frame_num_value_allowed_flag = sps->gaps_in_frame_num_allowed_flag;
+    pic_param->seq_fields.bits.frame_mbs_only_flag              = sps->frame_mbs_only_flag;
+    pic_param->seq_fields.bits.mb_adaptive_frame_field_flag     = sps->mb_aff;
+    pic_param->seq_fields.bits.direct_8x8_inference_flag        = sps->direct_8x8_inference_flag;
+    pic_param->seq_fields.bits.MinLumaBiPredSize8x8             = sps->level_idc >= 31; /* A.3.3.2 */
+    pic_param->seq_fields.bits.log2_max_frame_num_minus4        = sps->log2_max_frame_num - 4;
+    pic_param->seq_fields.bits.pic_order_cnt_type               = sps->poc_type;
+    pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4;
+    pic_param->seq_fields.bits.delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag;
+    pic_param->num_slice_groups_minus1                          = pps->slice_group_count - 1;
+    pic_param->slice_group_map_type                             = pps->mb_slice_group_map_type;
     pic_param->slice_group_change_rate_minus1                   = 0; /* XXX: unimplemented in FFmpeg */
-    pic_param->pic_init_qp_minus26                              = h->pps.init_qp - 26;
-    pic_param->pic_init_qs_minus26                              = h->pps.init_qs - 26;
-    pic_param->chroma_qp_index_offset                           = h->pps.chroma_qp_index_offset[0];
-    pic_param->second_chroma_qp_index_offset                    = h->pps.chroma_qp_index_offset[1];
+    pic_param->pic_init_qp_minus26                              = pps->init_qp - 26;
+    pic_param->pic_init_qs_minus26                              = pps->init_qs - 26;
+    pic_param->chroma_qp_index_offset                           = pps->chroma_qp_index_offset[0];
+    pic_param->second_chroma_qp_index_offset                    = pps->chroma_qp_index_offset[1];
     pic_param->pic_fields.value                                 = 0; /* reset all bits */
-    pic_param->pic_fields.bits.entropy_coding_mode_flag         = h->pps.cabac;
-    pic_param->pic_fields.bits.weighted_pred_flag               = h->pps.weighted_pred;
-    pic_param->pic_fields.bits.weighted_bipred_idc              = h->pps.weighted_bipred_idc;
-    pic_param->pic_fields.bits.transform_8x8_mode_flag          = h->pps.transform_8x8_mode;
+    pic_param->pic_fields.bits.entropy_coding_mode_flag         = pps->cabac;
+    pic_param->pic_fields.bits.weighted_pred_flag               = pps->weighted_pred;
+    pic_param->pic_fields.bits.weighted_bipred_idc              = pps->weighted_bipred_idc;
+    pic_param->pic_fields.bits.transform_8x8_mode_flag          = pps->transform_8x8_mode;
     pic_param->pic_fields.bits.field_pic_flag                   = h->picture_structure != PICT_FRAME;
-    pic_param->pic_fields.bits.constrained_intra_pred_flag      = h->pps.constrained_intra_pred;
-    pic_param->pic_fields.bits.pic_order_present_flag           = h->pps.pic_order_present;
-    pic_param->pic_fields.bits.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
-    pic_param->pic_fields.bits.redundant_pic_cnt_present_flag   = h->pps.redundant_pic_cnt_present;
+    pic_param->pic_fields.bits.constrained_intra_pred_flag      = pps->constrained_intra_pred;
+    pic_param->pic_fields.bits.pic_order_present_flag           = pps->pic_order_present;
+    pic_param->pic_fields.bits.deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present;
+    pic_param->pic_fields.bits.redundant_pic_cnt_present_flag   = pps->redundant_pic_cnt_present;
     pic_param->pic_fields.bits.reference_pic_flag               = h->nal_ref_idc != 0;
-    pic_param->frame_num                                        = h->frame_num;
+    pic_param->frame_num                                        = h->poc.frame_num;
 
     /* Fill in VAIQMatrixBufferH264. */
     iq_matrix = ff_vaapi_alloc_iq_matrix(vactx, sizeof(VAIQMatrixBufferH264));
     if (!iq_matrix)
         return -1;
-    memcpy(iq_matrix->ScalingList4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->ScalingList4x4));
-    memcpy(iq_matrix->ScalingList8x8[0], h->pps.scaling_matrix8[0], sizeof(iq_matrix->ScalingList8x8[0]));
-    memcpy(iq_matrix->ScalingList8x8[1], h->pps.scaling_matrix8[3], sizeof(iq_matrix->ScalingList8x8[0]));
+    memcpy(iq_matrix->ScalingList4x4, pps->scaling_matrix4, sizeof(iq_matrix->ScalingList4x4));
+    memcpy(iq_matrix->ScalingList8x8[0], pps->scaling_matrix8[0], sizeof(iq_matrix->ScalingList8x8[0]));
+    memcpy(iq_matrix->ScalingList8x8[1], pps->scaling_matrix8[3], sizeof(iq_matrix->ScalingList8x8[0]));
     return 0;
 }
 
@@ -297,7 +297,6 @@ static int vaapi_h264_end_frame(AVCodecContext *avctx)
     H264SliceContext *sl = &h->slice_ctx[0];
     int ret;
 
-    ff_dlog(avctx, "vaapi_h264_end_frame()\n");
     ret = ff_vaapi_commit_slices(vactx);
     if (ret < 0)
         goto finish;
@@ -323,26 +322,23 @@ static int vaapi_h264_decode_slice(AVCodecContext *avctx,
     H264SliceContext *sl  = &h->slice_ctx[0];
     VASliceParameterBufferH264 *slice_param;
 
-    ff_dlog(avctx, "vaapi_h264_decode_slice(): buffer %p, size %d\n",
-            buffer, size);
-
     /* Fill in VASliceParameterBufferH264. */
     slice_param = (VASliceParameterBufferH264 *)ff_vaapi_alloc_slice(vactx, buffer, size);
     if (!slice_param)
         return -1;
-    slice_param->slice_data_bit_offset          = get_bits_count(&sl->gb) + 8; /* bit buffer started beyond nal_unit_type */
+    slice_param->slice_data_bit_offset          = get_bits_count(&sl->gb);
     slice_param->first_mb_in_slice              = (sl->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + sl->mb_x;
     slice_param->slice_type                     = ff_h264_get_slice_type(sl);
     slice_param->direct_spatial_mv_pred_flag    = sl->slice_type == AV_PICTURE_TYPE_B ? sl->direct_spatial_mv_pred : 0;
     slice_param->num_ref_idx_l0_active_minus1   = sl->list_count > 0 ? sl->ref_count[0] - 1 : 0;
     slice_param->num_ref_idx_l1_active_minus1   = sl->list_count > 1 ? sl->ref_count[1] - 1 : 0;
     slice_param->cabac_init_idc                 = sl->cabac_init_idc;
-    slice_param->slice_qp_delta                 = sl->qscale - h->pps.init_qp;
+    slice_param->slice_qp_delta                 = sl->qscale - h->ps.pps->init_qp;
     slice_param->disable_deblocking_filter_idc  = sl->deblocking_filter < 2 ? !sl->deblocking_filter : sl->deblocking_filter;
     slice_param->slice_alpha_c0_offset_div2     = sl->slice_alpha_c0_offset / 2;
     slice_param->slice_beta_offset_div2         = sl->slice_beta_offset     / 2;
-    slice_param->luma_log2_weight_denom         = sl->luma_log2_weight_denom;
-    slice_param->chroma_log2_weight_denom       = sl->chroma_log2_weight_denom;
+    slice_param->luma_log2_weight_denom         = sl->pwt.luma_log2_weight_denom;
+    slice_param->chroma_log2_weight_denom       = sl->pwt.chroma_log2_weight_denom;
 
     fill_vaapi_RefPicList(slice_param->RefPicList0, sl->ref_list[0], sl->list_count > 0 ? sl->ref_count[0] : 0);
     fill_vaapi_RefPicList(slice_param->RefPicList1, sl->ref_list[1], sl->list_count > 1 ? sl->ref_count[1] : 0);
diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c
index 518fec0..9329e54 100644
--- a/libavcodec/vaapi_mpeg2.c
+++ b/libavcodec/vaapi_mpeg2.c
@@ -46,8 +46,6 @@ static int vaapi_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint8_
     VAIQMatrixBufferMPEG2 *iq_matrix;
     int i;
 
-    ff_dlog(avctx, "vaapi_mpeg2_start_frame()\n");
-
     vactx->slice_param_size = sizeof(VASliceParameterBufferMPEG2);
 
     /* Fill in VAPictureParameterBufferMPEG2 */
@@ -109,8 +107,6 @@ static int vaapi_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer
     GetBitContext gb;
     uint32_t quantiser_scale_code, intra_slice_flag, macroblock_offset;
 
-    ff_dlog(avctx, "vaapi_mpeg2_decode_slice(): buffer %p, size %d\n", buffer, size);
-
     /* Determine macroblock_offset */
     init_get_bits(&gb, buffer, 8 * size);
     if (get_bits_long(&gb, 32) >> 8 != 1) /* start code */
diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c
index b5b946d..725f00b 100644
--- a/libavcodec/vaapi_mpeg4.c
+++ b/libavcodec/vaapi_mpeg4.c
@@ -51,8 +51,6 @@ static int vaapi_mpeg4_start_frame(AVCodecContext *avctx, av_unused const uint8_
     VAIQMatrixBufferMPEG4 *iq_matrix;
     int i;
 
-    ff_dlog(avctx, "vaapi_mpeg4_start_frame()\n");
-
     vactx->slice_param_size = sizeof(VASliceParameterBufferMPEG4);
 
     /* Fill in VAPictureParameterBufferMPEG4 */
@@ -125,8 +123,6 @@ static int vaapi_mpeg4_decode_slice(AVCodecContext *avctx, const uint8_t *buffer
     FFVAContext * const vactx = ff_vaapi_get_context(avctx);
     VASliceParameterBufferMPEG4 *slice_param;
 
-    ff_dlog(avctx, "vaapi_mpeg4_decode_slice(): buffer %p, size %d\n", buffer, size);
-
     /* Fill in VASliceParameterBufferMPEG4 */
     slice_param = (VASliceParameterBufferMPEG4 *)ff_vaapi_alloc_slice(vactx, buffer, size);
     if (!slice_param)
diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c
index 5ded5db..4e82be1 100644
--- a/libavcodec/vaapi_vc1.c
+++ b/libavcodec/vaapi_vc1.c
@@ -151,8 +151,6 @@ static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t
     FFVAContext * const vactx = ff_vaapi_get_context(avctx);
     VAPictureParameterBufferVC1 *pic_param;
 
-    ff_dlog(avctx, "vaapi_vc1_start_frame()\n");
-
     vactx->slice_param_size = sizeof(VASliceParameterBufferVC1);
 
     /* Fill in VAPictureParameterBufferVC1 */
@@ -318,8 +316,6 @@ static int vaapi_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer,
     FFVAContext * const vactx = ff_vaapi_get_context(avctx);
     VASliceParameterBufferVC1 *slice_param;
 
-    ff_dlog(avctx, "vaapi_vc1_decode_slice(): buffer %p, size %d\n", buffer, size);
-
     /* Current bit buffer is beyond any marker for VC-1, so skip it */
     if (avctx->codec_id == AV_CODEC_ID_VC1 && IS_MARKER(AV_RB32(buffer))) {
         buffer += 4;
diff --git a/libavcodec/vble.c b/libavcodec/vble.c
index bb9c81c..0340cad 100644
--- a/libavcodec/vble.c
+++ b/libavcodec/vble.c
@@ -33,6 +33,7 @@
 #include "huffyuvdsp.h"
 #include "internal.h"
 #include "mathops.h"
+#include "thread.h"
 
 typedef struct VBLEContext {
     AVCodecContext *avctx;
@@ -125,6 +126,7 @@ static int vble_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     int offset = 0;
     int width_uv = avctx->width / 2, height_uv = avctx->height / 2;
     int ret;
+    ThreadFrame frame = { .f = data };
 
     if (avpkt->size < 4 || avpkt->size - 4 > INT_MAX/8) {
         av_log(avctx, AV_LOG_ERROR, "Invalid packet size\n");
@@ -132,7 +134,7 @@ static int vble_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     }
 
     /* Allocate buffer */
-    if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
+    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0)
         return ret;
 
     /* Set flags */
@@ -212,5 +214,6 @@ AVCodec ff_vble_decoder = {
     .init           = vble_decode_init,
     .close          = vble_decode_close,
     .decode         = vble_decode_frame,
-    .capabilities   = AV_CODEC_CAP_DR1,
+    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .init_thread_copy = ONLY_IF_THREADS_ENABLED(vble_decode_init),
 };
diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c
index 08e1f2c..48a2cc1 100644
--- a/libavcodec/vc1.c
+++ b/libavcodec/vc1.c
@@ -24,7 +24,6 @@
 /**
  * @file
  * VC-1 and WMV3 decoder common code
- *
  */
 
 #include "libavutil/attributes.h"
@@ -33,7 +32,7 @@
 #include "mpegvideo.h"
 #include "vc1.h"
 #include "vc1data.h"
-#include "msmpeg4data.h"
+#include "wmv2data.h"
 #include "unary.h"
 #include "simple_idct.h"
 
@@ -392,7 +391,7 @@ int ff_vc1_decode_sequence_header(AVCodecContext *avctx, VC1Context *v, GetBitCo
            "Profile %i:\nfrmrtq_postproc=%i, bitrtq_postproc=%i\n"
            "LoopFilter=%i, MultiRes=%i, FastUVMC=%i, Extended MV=%i\n"
            "Rangered=%i, VSTransform=%i, Overlap=%i, SyncMarker=%i\n"
-           "DQuant=%i, Quantizer mode=%i, Max B frames=%i\n",
+           "DQuant=%i, Quantizer mode=%i, Max B-frames=%i\n",
            v->profile, v->frmrtq_postproc, v->bitrtq_postproc,
            v->s.loop_filter, v->multires, v->fastuvmc, v->extended_mv,
            v->rangered, v->vstransform, v->overlap, v->resync_marker,
@@ -765,7 +764,7 @@ int ff_vc1_parse_frame_header(VC1Context *v, GetBitContext* gb)
         av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: "
                "Imode: %i, Invert: %i\n", status>>1, status&1);
 
-        /* Hopefully this is correct for P frames */
+        /* Hopefully this is correct for P-frames */
         v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables
         v->cbpcy_vlc = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)];
 
@@ -1153,7 +1152,7 @@ int ff_vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb)
             av_log(v->s.avctx, AV_LOG_DEBUG, "MB Skip plane encoding: "
                    "Imode: %i, Invert: %i\n", status>>1, status&1);
 
-            /* Hopefully this is correct for P frames */
+            /* Hopefully this is correct for P-frames */
             v->s.mv_table_index = get_bits(gb, 2); //but using ff_vc1_ tables
             v->cbpcy_vlc        = &ff_vc1_cbpcy_p_vlc[get_bits(gb, 2)];
         } else if (v->fcm == ILACE_FRAME) { // frame interlaced
diff --git a/libavcodec/vc1.h b/libavcodec/vc1.h
index eefb613..556906d 100644
--- a/libavcodec/vc1.h
+++ b/libavcodec/vc1.h
@@ -73,7 +73,7 @@ enum DQDoubleEdge {
 };
 //@}
 
-/** MV modes for P frames */
+/** MV modes for P-frames */
 //@{
 enum MVModes {
     MV_PMODE_1MV_HPEL_BILIN,
@@ -96,7 +96,7 @@ enum MBModesIntfr {
 };
 //@}
 
-/** @name MV types for B frames */
+/** @name MV types for B-frames */
 //@{
 enum BMVTypes {
     BMV_TYPE_BACKWARD,
@@ -106,7 +106,7 @@ enum BMVTypes {
 };
 //@}
 
-/** @name Block types for P/B frames */
+/** @name Block types for P/B-frames */
 //@{
 enum TransformTypes {
     TT_8X8,
@@ -194,18 +194,18 @@ typedef struct VC1Context{
 
     /** Advanced Profile */
     //@{
-    int level;            ///< 3bits, for Advanced/Simple Profile, provided by TS layer
-    int chromaformat;     ///< 2bits, 2=4:2:0, only defined
+    int level;            ///< 3 bits, for Advanced/Simple Profile, provided by TS layer
+    int chromaformat;     ///< 2 bits, 2=4:2:0, only defined
     int postprocflag;     ///< Per-frame processing suggestion flag present
     int broadcast;        ///< TFF/RFF present
     int interlace;        ///< Progressive/interlaced (RPTFTM syntax element)
     int tfcntrflag;       ///< TFCNTR present
     int panscanflag;      ///< NUMPANSCANWIN, TOPLEFT{X,Y}, BOTRIGHT{X,Y} present
     int refdist_flag;     ///< REFDIST syntax element present in II, IP, PI or PP field picture headers
-    int extended_dmv;     ///< Additional extended dmv range at P/B frame-level
-    int color_prim;       ///< 8bits, chroma coordinates of the color primaries
-    int transfer_char;    ///< 8bits, Opto-electronic transfer characteristics
-    int matrix_coef;      ///< 8bits, Color primaries->YCbCr transform matrix
+    int extended_dmv;     ///< Additional extended dmv range at P/B-frame-level
+    int color_prim;       ///< 8 bits, chroma coordinates of the color primaries
+    int transfer_char;    ///< 8 bits, Opto-electronic transfer characteristics
+    int matrix_coef;      ///< 8 bits, Color primaries->YCbCr transform matrix
     int hrd_param_flag;   ///< Presence of Hypothetical Reference
                           ///< Decoder parameters
     int psf;              ///< Progressive Segmented Frame
@@ -215,23 +215,23 @@ typedef struct VC1Context{
      * TODO: choose between ints, uint8_ts and monobit flags
      */
     //@{
-    int profile;          ///< 2bits, Profile
-    int frmrtq_postproc;  ///< 3bits,
-    int bitrtq_postproc;  ///< 5bits, quantized framerate-based postprocessing strength
+    int profile;          ///< 2 bits, Profile
+    int frmrtq_postproc;  ///< 3 bits,
+    int bitrtq_postproc;  ///< 5 bits, quantized framerate-based postprocessing strength
     int max_coded_width, max_coded_height;
     int fastuvmc;         ///< Rounding of qpel vector to hpel ? (not in Simple)
     int extended_mv;      ///< Ext MV in P/B (not in Simple)
-    int dquant;           ///< How qscale varies with MBs, 2bits (not in Simple)
+    int dquant;           ///< How qscale varies with MBs, 2 bits (not in Simple)
     int vstransform;      ///< variable-size [48]x[48] transform type + info
     int overlap;          ///< overlapped transforms in use
-    int quantizer_mode;   ///< 2bits, quantizer mode used for sequence, see QUANT_*
+    int quantizer_mode;   ///< 2 bits, quantizer mode used for sequence, see QUANT_*
     int finterpflag;      ///< INTERPFRM present
     //@}
 
     /** Frame decoding info for all profiles */
     //@{
-    uint8_t mv_mode;             ///< MV coding monde
-    uint8_t mv_mode2;            ///< Secondary MV coding mode (B frames)
+    uint8_t mv_mode;             ///< MV coding mode
+    uint8_t mv_mode2;            ///< Secondary MV coding mode (B-frames)
     int k_x;                     ///< Number of bits for MVs (depends on MV range)
     int k_y;                     ///< Number of bits for MVs (depends on MV range)
     int range_x, range_y;        ///< MV range
diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c
index 255ba1d..f9f26f7 100644
--- a/libavcodec/vc1_block.c
+++ b/libavcodec/vc1_block.c
@@ -2492,7 +2492,7 @@ static void vc1_decode_i_blocks(VC1Context *v)
     uint8_t *coded_val;
     int mb_pos;
 
-    /* select codingmode used for VLC tables selection */
+    /* select coding mode used for VLC tables selection */
     switch (v->y_ac_table_index) {
     case 0:
         v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
@@ -2640,7 +2640,7 @@ static void vc1_decode_i_blocks_adv(VC1Context *v)
     int mqdiff;
     GetBitContext *gb = &s->gb;
 
-    /* select codingmode used for VLC tables selection */
+    /* select coding mode used for VLC tables selection */
     switch (v->y_ac_table_index) {
     case 0:
         v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
@@ -2768,7 +2768,7 @@ static void vc1_decode_p_blocks(VC1Context *v)
     MpegEncContext *s = &v->s;
     int apply_loop_filter;
 
-    /* select codingmode used for VLC tables selection */
+    /* select coding mode used for VLC tables selection */
     switch (v->c_ac_table_index) {
     case 0:
         v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
@@ -2844,7 +2844,7 @@ static void vc1_decode_b_blocks(VC1Context *v)
 {
     MpegEncContext *s = &v->s;
 
-    /* select codingmode used for VLC tables selection */
+    /* select coding mode used for VLC tables selection */
     switch (v->c_ac_table_index) {
     case 0:
         v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
@@ -2931,7 +2931,14 @@ void ff_vc1_decode_blocks(VC1Context *v)
 
     v->s.esc3_level_length = 0;
     if (v->x8_type) {
-        ff_intrax8_decode_picture(&v->x8, 2*v->pq + v->halfpq, v->pq * !v->pquantizer);
+        ff_intrax8_decode_picture(&v->x8, &v->s.current_picture,
+                                  &v->s.gb, &v->s.mb_x, &v->s.mb_y,
+                                  2 * v->pq + v->halfpq, v->pq * !v->pquantizer,
+                                  v->s.loop_filter, v->s.low_delay);
+
+        ff_er_add_slice(&v->s.er, 0, 0,
+                        (v->s.mb_x >> 1) - 1, (v->s.mb_y >> 1) - 1,
+                        ER_MB_END);
     } else {
         v->cur_blk_idx     =  0;
         v->left_blk_idx    = -1;
diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c
index 4467646..75c74ca 100644
--- a/libavcodec/vc1_mc.c
+++ b/libavcodec/vc1_mc.c
@@ -188,7 +188,7 @@ void ff_vc1_mc_1mv(VC1Context *v, int dir)
     mx = s->mv[dir][0][0];
     my = s->mv[dir][0][1];
 
-    // store motion vectors for further use in B frames
+    // store motion vectors for further use in B-frames
     if (s->pict_type == AV_PICTURE_TYPE_P) {
         for (i = 0; i < 4; i++) {
             s->current_picture.motion_val[1][s->block_index[i] + v->blocks_off][0] = mx;
@@ -867,7 +867,7 @@ void ff_vc1_interp_mc(VC1Context *v)
 
     if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
         return;
-    /* Chroma MC always uses qpel blilinear */
+    /* Chroma MC always uses qpel bilinear */
     uvmx = (uvmx & 3) << 1;
     uvmy = (uvmy & 3) << 1;
     if (!v->rnd) {
diff --git a/libavcodec/vc1_pred.c b/libavcodec/vc1_pred.c
index 13134e5..54712f6 100644
--- a/libavcodec/vc1_pred.c
+++ b/libavcodec/vc1_pred.c
@@ -468,7 +468,7 @@ void ff_vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y,
     int A[2], B[2], C[2];
     int px = 0, py = 0;
     int a_valid = 0, b_valid = 0, c_valid = 0;
-    int field_a, field_b, field_c; // 0: same, 1: opposit
+    int field_a, field_b, field_c; // 0: same, 1: opposite
     int total_valid, num_samefield, num_oppfield;
     int pos_c, pos_b, n_adj;
 
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index f66afb9..4f78aa8 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -324,7 +324,7 @@ static void vc1_sprite_flush(AVCodecContext *avctx)
 av_cold int ff_vc1_decode_init_alloc_tables(VC1Context *v)
 {
     MpegEncContext *s = &v->s;
-    int i;
+    int i, ret = AVERROR(ENOMEM);
     int mb_height = FFALIGN(s->mb_height, 2);
 
     /* Allocate mb bitplanes */
@@ -334,67 +334,70 @@ av_cold int ff_vc1_decode_init_alloc_tables(VC1Context *v)
     v->fieldtx_plane    = av_mallocz(s->mb_stride * mb_height);
     v->acpred_plane     = av_malloc (s->mb_stride * mb_height);
     v->over_flags_plane = av_malloc (s->mb_stride * mb_height);
+    if (!v->mv_type_mb_plane || !v->direct_mb_plane || !v->forward_mb_plane ||
+        !v->fieldtx_plane || !v->acpred_plane || !v->over_flags_plane)
+        goto error;
 
     v->n_allocated_blks = s->mb_width + 2;
     v->block            = av_malloc(sizeof(*v->block) * v->n_allocated_blks);
     v->cbp_base         = av_malloc(sizeof(v->cbp_base[0]) * 2 * s->mb_stride);
+    if (!v->block || !v->cbp_base)
+        goto error;
     v->cbp              = v->cbp_base + s->mb_stride;
     v->ttblk_base       = av_malloc(sizeof(v->ttblk_base[0]) * 2 * s->mb_stride);
+    if (!v->ttblk_base)
+        goto error;
     v->ttblk            = v->ttblk_base + s->mb_stride;
     v->is_intra_base    = av_mallocz(sizeof(v->is_intra_base[0]) * 2 * s->mb_stride);
+    if (!v->is_intra_base)
+        goto error;
     v->is_intra         = v->is_intra_base + s->mb_stride;
     v->luma_mv_base     = av_mallocz(sizeof(v->luma_mv_base[0]) * 2 * s->mb_stride);
+    if (!v->luma_mv_base)
+        goto error;
     v->luma_mv          = v->luma_mv_base + s->mb_stride;
 
     /* allocate block type info in that way so it could be used with s->block_index[] */
     v->mb_type_base = av_malloc(s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2);
+    if (!v->mb_type_base)
+        goto error;
     v->mb_type[0]   = v->mb_type_base + s->b8_stride + 1;
     v->mb_type[1]   = v->mb_type_base + s->b8_stride * (mb_height * 2 + 1) + s->mb_stride + 1;
     v->mb_type[2]   = v->mb_type[1] + s->mb_stride * (mb_height + 1);
 
     /* allocate memory to store block level MV info */
     v->blk_mv_type_base = av_mallocz(     s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2);
+    if (!v->blk_mv_type_base)
+        goto error;
     v->blk_mv_type      = v->blk_mv_type_base + s->b8_stride + 1;
     v->mv_f_base        = av_mallocz(2 * (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2));
+    if (!v->mv_f_base)
+        goto error;
     v->mv_f[0]          = v->mv_f_base + s->b8_stride + 1;
     v->mv_f[1]          = v->mv_f[0] + (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2);
     v->mv_f_next_base   = av_mallocz(2 * (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2));
+    if (!v->mv_f_next_base)
+        goto error;
     v->mv_f_next[0]     = v->mv_f_next_base + s->b8_stride + 1;
     v->mv_f_next[1]     = v->mv_f_next[0] + (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2);
 
-    /* Init coded blocks info */
-    if (v->profile == PROFILE_ADVANCED) {
-//        if (alloc_bitplane(&v->over_flags_plane, s->mb_width, s->mb_height) < 0)
-//            return -1;
-//        if (alloc_bitplane(&v->ac_pred_plane, s->mb_width, s->mb_height) < 0)
-//            return -1;
-    }
-
-    ff_intrax8_common_init(&v->x8,s);
-
     if (s->avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || s->avctx->codec_id == AV_CODEC_ID_VC1IMAGE) {
         for (i = 0; i < 4; i++)
             if (!(v->sr_rows[i >> 1][i & 1] = av_malloc(v->output_width)))
                 return AVERROR(ENOMEM);
     }
 
-    if (!v->mv_type_mb_plane || !v->direct_mb_plane || !v->acpred_plane || !v->over_flags_plane ||
-        !v->block || !v->cbp_base || !v->ttblk_base || !v->is_intra_base || !v->luma_mv_base ||
-        !v->mb_type_base) {
-        av_freep(&v->mv_type_mb_plane);
-        av_freep(&v->direct_mb_plane);
-        av_freep(&v->acpred_plane);
-        av_freep(&v->over_flags_plane);
-        av_freep(&v->block);
-        av_freep(&v->cbp_base);
-        av_freep(&v->ttblk_base);
-        av_freep(&v->is_intra_base);
-        av_freep(&v->luma_mv_base);
-        av_freep(&v->mb_type_base);
-        return AVERROR(ENOMEM);
-    }
+    ret = ff_intrax8_common_init(s->avctx, &v->x8, &s->idsp,
+                                 s->block, s->block_last_index,
+                                 s->mb_width, s->mb_height);
+    if (ret < 0)
+        goto error;
 
     return 0;
+
+error:
+    ff_vc1_decode_end(s->avctx);
+    return ret;
 }
 
 av_cold void ff_vc1_init_transposed_scantables(VC1Context *v)
@@ -414,7 +417,7 @@ av_cold void ff_vc1_init_transposed_scantables(VC1Context *v)
 
 /** Initialize a VC1/WMV3 decoder
  * @todo TODO: Handle VC-1 IDUs (Transport level?)
- * @todo TODO: Decypher remaining bits in extra_data
+ * @todo TODO: Decipher remaining bits in extra_data
  */
 static av_cold int vc1_decode_init(AVCodecContext *avctx)
 {
diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c
index a16c8d5..2d7e9b7 100644
--- a/libavcodec/vc1dsp.c
+++ b/libavcodec/vc1dsp.c
@@ -22,7 +22,6 @@
 /**
  * @file
  * VC-1 and WMV3 decoder
- *
  */
 
 #include "libavutil/avassert.h"
diff --git a/libavcodec/vc1dsp.h b/libavcodec/vc1dsp.h
index e2f75ac..3d48f09 100644
--- a/libavcodec/vc1dsp.h
+++ b/libavcodec/vc1dsp.h
@@ -22,7 +22,6 @@
 /**
  * @file
  * VC-1 and WMV3 decoder
- *
  */
 
 #ifndef AVCODEC_VC1DSP_H
diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c
index bf3f3a9..bbbeaa0 100644
--- a/libavcodec/vc2enc.c
+++ b/libavcodec/vc2enc.c
@@ -19,21 +19,69 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavutil/ffversion.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "dirac.h"
 #include "put_bits.h"
 #include "internal.h"
+#include "version.h"
 
 #include "vc2enc_dwt.h"
 #include "diractab.h"
 
 /* Quantizations above this usually zero coefficients and lower the quality */
-#define MAX_QUANT_INDEX 100
+#define MAX_QUANT_INDEX FF_ARRAY_ELEMS(ff_dirac_qscale_tab)
 
+/* Total range is -COEF_LUT_TAB to +COEFF_LUT_TAB, but total tab size is half
+ * (COEF_LUT_TAB*MAX_QUANT_INDEX) since the sign is appended during encoding */
 #define COEF_LUT_TAB 2048
 
+/* The limited size resolution of each slice forces us to do this */
+#define SSIZE_ROUND(b) (FFALIGN((b), s->size_scaler) + 4 + s->prefix_bytes)
+
+/* Decides the cutoff point in # of slices to distribute the leftover bytes */
+#define SLICE_REDIST_TOTAL 150
+
+typedef struct VC2BaseVideoFormat {
+    enum AVPixelFormat pix_fmt;
+    AVRational time_base;
+    int width, height, interlaced, level;
+    const char *name;
+} VC2BaseVideoFormat;
+
+static const VC2BaseVideoFormat base_video_fmts[] = {
+    { 0 }, /* Custom format, here just to make indexing equal to base_vf */
+    { AV_PIX_FMT_YUV420P,   { 1001, 15000 },  176,  120, 0, 1,     "QSIF525" },
+    { AV_PIX_FMT_YUV420P,   {    2,    25 },  176,  144, 0, 1,     "QCIF"    },
+    { AV_PIX_FMT_YUV420P,   { 1001, 15000 },  352,  240, 0, 1,     "SIF525"  },
+    { AV_PIX_FMT_YUV420P,   {    2,    25 },  352,  288, 0, 1,     "CIF"     },
+    { AV_PIX_FMT_YUV420P,   { 1001, 15000 },  704,  480, 0, 1,     "4SIF525" },
+    { AV_PIX_FMT_YUV420P,   {    2,    25 },  704,  576, 0, 1,     "4CIF"    },
+
+    { AV_PIX_FMT_YUV422P10, { 1001, 30000 },  720,  480, 1, 2,   "SD480I-60" },
+    { AV_PIX_FMT_YUV422P10, {    1,    25 },  720,  576, 1, 2,   "SD576I-50" },
+
+    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 1280,  720, 0, 3,  "HD720P-60"  },
+    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 1280,  720, 0, 3,  "HD720P-50"  },
+    { AV_PIX_FMT_YUV422P10, { 1001, 30000 }, 1920, 1080, 1, 3,  "HD1080I-60" },
+    { AV_PIX_FMT_YUV422P10, {    1,    25 }, 1920, 1080, 1, 3,  "HD1080I-50" },
+    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 1920, 1080, 0, 3,  "HD1080P-60" },
+    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 1920, 1080, 0, 3,  "HD1080P-50" },
+
+    { AV_PIX_FMT_YUV444P12, {    1,    24 }, 2048, 1080, 0, 4,        "DC2K" },
+    { AV_PIX_FMT_YUV444P12, {    1,    24 }, 4096, 2160, 0, 5,        "DC4K" },
+
+    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 3840, 2160, 0, 6, "UHDTV 4K-60" },
+    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 3840, 2160, 0, 6, "UHDTV 4K-50" },
+
+    { AV_PIX_FMT_YUV422P10, { 1001, 60000 }, 7680, 4320, 0, 7, "UHDTV 8K-60" },
+    { AV_PIX_FMT_YUV422P10, {    1,    50 }, 7680, 4320, 0, 7, "UHDTV 8K-50" },
+
+    { AV_PIX_FMT_YUV422P10, { 1001, 24000 }, 1920, 1080, 0, 3,  "HD1080P-24" },
+    { AV_PIX_FMT_YUV422P10, { 1001, 30000 },  720,  486, 1, 2,  "SD Pro486"  },
+};
+static const int base_video_fmts_len = FF_ARRAY_ELEMS(base_video_fmts);
+
 enum VC2_QM {
     VC2_QM_DEF = 0,
     VC2_QM_COL,
@@ -61,11 +109,13 @@ typedef struct Plane {
 
 typedef struct SliceArgs {
     PutBitContext pb;
+    int cache[MAX_QUANT_INDEX];
     void *ctx;
     int x;
     int y;
     int quant_idx;
     int bits_ceil;
+    int bits_floor;
     int bytes;
 } SliceArgs;
 
@@ -91,6 +141,7 @@ typedef struct VC2EncContext {
     /* For conversion from unsigned pixel values to signed */
     int diff_offset;
     int bpp;
+    int bpp_idx;
 
     /* Picture number */
     uint32_t picture_number;
@@ -102,6 +153,7 @@ typedef struct VC2EncContext {
 
     /* Quantization matrix */
     uint8_t quant[MAX_DWT_LEVELS][4];
+    int custom_quant_matrix;
 
     /* Coefficient LUT */
     uint32_t *coef_lut_val;
@@ -116,8 +168,9 @@ typedef struct VC2EncContext {
 
     /* Rate control stuff */
     int slice_max_bytes;
+    int slice_min_bytes;
     int q_ceil;
-    int q_start;
+    int q_avg;
 
     /* Options */
     double tolerance;
@@ -134,19 +187,6 @@ typedef struct VC2EncContext {
     enum DiracParseCodes last_parse_code;
 } VC2EncContext;
 
-static av_always_inline void put_padding(PutBitContext *pb, int bytes)
-{
-    int bits = bytes*8;
-    if (!bits)
-        return;
-    while (bits > 31) {
-        put_bits(pb, 31, 0);
-        bits -= 31;
-    }
-    if (bits)
-        put_bits(pb, bits, 0);
-}
-
 static av_always_inline void put_vc2_ue_uint(PutBitContext *pb, uint32_t val)
 {
     int i;
@@ -175,7 +215,7 @@ static av_always_inline void put_vc2_ue_uint(PutBitContext *pb, uint32_t val)
     put_bits(pb, bits*2 + 1, (pbits << 1) | 1);
 }
 
-static av_always_inline int count_vc2_ue_uint(uint16_t val)
+static av_always_inline int count_vc2_ue_uint(uint32_t val)
 {
     int topbit = 1, maxval = 1;
 
@@ -191,8 +231,8 @@ static av_always_inline int count_vc2_ue_uint(uint16_t val)
     return ff_log2(topbit)*2 + 1;
 }
 
-static av_always_inline void get_vc2_ue_uint(uint16_t val, uint8_t *nbits,
-                                               uint32_t *eval)
+static av_always_inline void get_vc2_ue_uint(int val, uint8_t *nbits,
+                                             uint32_t *eval)
 {
     int i;
     int pbits = 0, bits = 0, topbit = 1, maxval = 1;
@@ -331,31 +371,9 @@ static void encode_clean_area(VC2EncContext *s)
 /* VC-2 11.3.8 - signal_range() */
 static void encode_signal_range(VC2EncContext *s)
 {
-    int idx;
-    AVCodecContext *avctx = s->avctx;
-    const AVPixFmtDescriptor *fmt = av_pix_fmt_desc_get(avctx->pix_fmt);
-    const int depth = fmt->comp[0].depth;
-    if (depth == 8 && avctx->color_range == AVCOL_RANGE_JPEG) {
-        idx = 1;
-        s->bpp = 1;
-        s->diff_offset = 128;
-    } else if (depth == 8 && (avctx->color_range == AVCOL_RANGE_MPEG ||
-               avctx->color_range == AVCOL_RANGE_UNSPECIFIED)) {
-        idx = 2;
-        s->bpp = 1;
-        s->diff_offset = 128;
-    } else if (depth == 10) {
-        idx = 3;
-        s->bpp = 2;
-        s->diff_offset = 512;
-    } else {
-        idx = 4;
-        s->bpp = 2;
-        s->diff_offset = 2048;
-    }
     put_bits(&s->pb, 1, !s->strict_compliance);
     if (!s->strict_compliance)
-        put_vc2_ue_uint(&s->pb, idx);
+        put_vc2_ue_uint(&s->pb, s->bpp_idx);
 }
 
 /* VC-2 11.3.9 - color_spec() */
@@ -459,10 +477,23 @@ const uint8_t vc2_qm_flat_tab[][4] = {
     { 0,  0,  0,  0}
 };
 
-static void init_custom_qm(VC2EncContext *s)
+static void init_quant_matrix(VC2EncContext *s)
 {
     int level, orientation;
 
+    if (s->wavelet_depth <= 4 && s->quant_matrix == VC2_QM_DEF) {
+        s->custom_quant_matrix = 0;
+        for (level = 0; level < s->wavelet_depth; level++) {
+            s->quant[level][0] = ff_dirac_default_qmat[s->wavelet_idx][level][0];
+            s->quant[level][1] = ff_dirac_default_qmat[s->wavelet_idx][level][1];
+            s->quant[level][2] = ff_dirac_default_qmat[s->wavelet_idx][level][2];
+            s->quant[level][3] = ff_dirac_default_qmat[s->wavelet_idx][level][3];
+        }
+        return;
+    }
+
+    s->custom_quant_matrix = 1;
+
     if (s->quant_matrix == VC2_QM_DEF) {
         for (level = 0; level < s->wavelet_depth; level++) {
             for (orientation = 0; orientation < 4; orientation++) {
@@ -490,25 +521,15 @@ static void init_custom_qm(VC2EncContext *s)
 /* VC-2 12.3.4.2 - quant_matrix() */
 static void encode_quant_matrix(VC2EncContext *s)
 {
-    int level, custom_quant_matrix = 0;
-    if (s->wavelet_depth > 4 || s->quant_matrix != VC2_QM_DEF)
-        custom_quant_matrix = 1;
-    put_bits(&s->pb, 1, custom_quant_matrix);
-    if (custom_quant_matrix) {
-        init_custom_qm(s);
+    int level;
+    put_bits(&s->pb, 1, s->custom_quant_matrix);
+    if (s->custom_quant_matrix) {
         put_vc2_ue_uint(&s->pb, s->quant[0][0]);
         for (level = 0; level < s->wavelet_depth; level++) {
             put_vc2_ue_uint(&s->pb, s->quant[level][1]);
             put_vc2_ue_uint(&s->pb, s->quant[level][2]);
             put_vc2_ue_uint(&s->pb, s->quant[level][3]);
         }
-    } else {
-        for (level = 0; level < s->wavelet_depth; level++) {
-            s->quant[level][0] = ff_dirac_default_qmat[s->wavelet_idx][level][0];
-            s->quant[level][1] = ff_dirac_default_qmat[s->wavelet_idx][level][1];
-            s->quant[level][2] = ff_dirac_default_qmat[s->wavelet_idx][level][2];
-            s->quant[level][3] = ff_dirac_default_qmat[s->wavelet_idx][level][3];
-        }
     }
 }
 
@@ -527,7 +548,6 @@ static void encode_wavelet_transform(VC2EncContext *s)
 {
     encode_transform_params(s);
     avpriv_align_put_bits(&s->pb);
-    /* Continued after DWT in encode_transform_data() */
 }
 
 /* VC-2 12 - picture_parse() */
@@ -539,29 +559,7 @@ static void encode_picture_start(VC2EncContext *s)
     encode_wavelet_transform(s);
 }
 
-#define QUANT(c)  \
-    c <<= 2;      \
-    c /= qfactor; \
-
-static av_always_inline void coeff_quantize_get(qcoef coeff, int qfactor,
-                                                uint8_t *len, uint32_t *eval)
-{
-    QUANT(coeff)
-    get_vc2_ue_uint(abs(coeff), len, eval);
-    if (coeff) {
-        *eval = (*eval << 1) | (coeff < 0);
-        *len += 1;
-    }
-}
-
-static av_always_inline void coeff_quantize_encode(PutBitContext *pb, qcoef coeff,
-                                                   int qfactor)
-{
-    QUANT(coeff)
-    put_vc2_ue_uint(pb, abs(coeff));
-    if (coeff)
-        put_bits(pb, 1, coeff < 0);
-}
+#define QUANT(c, qf) (((c) << 2)/(qf))
 
 /* VC-2 13.5.5.2 - slice_band() */
 static void encode_subband(VC2EncContext *s, PutBitContext *pb, int sx, int sy,
@@ -569,34 +567,43 @@ static void encode_subband(VC2EncContext *s, PutBitContext *pb, int sx, int sy,
 {
     int x, y;
 
-    int left   = b->width  * (sx+0) / s->num_x;
-    int right  = b->width  * (sx+1) / s->num_x;
-    int top    = b->height * (sy+0) / s->num_y;
-    int bottom = b->height * (sy+1) / s->num_y;
+    const int left   = b->width  * (sx+0) / s->num_x;
+    const int right  = b->width  * (sx+1) / s->num_x;
+    const int top    = b->height * (sy+0) / s->num_y;
+    const int bottom = b->height * (sy+1) / s->num_y;
 
-    int qfactor = ff_dirac_qscale_tab[quant];
-    uint8_t  *len_lut = &s->coef_lut_len[2*quant*COEF_LUT_TAB + COEF_LUT_TAB];
-    uint32_t *val_lut = &s->coef_lut_val[2*quant*COEF_LUT_TAB + COEF_LUT_TAB];
+    const int qfactor = ff_dirac_qscale_tab[quant];
+    const uint8_t  *len_lut = &s->coef_lut_len[quant*COEF_LUT_TAB];
+    const uint32_t *val_lut = &s->coef_lut_val[quant*COEF_LUT_TAB];
 
     dwtcoef *coeff = b->buf + top * b->stride;
 
     for (y = top; y < bottom; y++) {
         for (x = left; x < right; x++) {
-            if (coeff[x] >= -COEF_LUT_TAB && coeff[x] < COEF_LUT_TAB)
-                put_bits(pb, len_lut[coeff[x]], val_lut[coeff[x]]);
-            else
-                coeff_quantize_encode(pb, coeff[x], qfactor);
+            const int neg = coeff[x] < 0;
+            uint32_t c_abs = FFABS(coeff[x]);
+            if (c_abs < COEF_LUT_TAB) {
+                put_bits(pb, len_lut[c_abs], val_lut[c_abs] | neg);
+            } else {
+                c_abs = QUANT(c_abs, qfactor);
+                put_vc2_ue_uint(pb, c_abs);
+                if (c_abs)
+                    put_bits(pb, 1, neg);
+            }
         }
         coeff += b->stride;
     }
 }
 
-static int count_hq_slice(VC2EncContext *s, int slice_x,
-                          int slice_y, int quant_idx)
+static int count_hq_slice(SliceArgs *slice, int quant_idx)
 {
-    int x, y, left, right, top, bottom, qfactor;
+    int x, y;
     uint8_t quants[MAX_DWT_LEVELS][4];
     int bits = 0, p, level, orientation;
+    VC2EncContext *s = slice->ctx;
+
+    if (slice->cache[quant_idx])
+        return slice->cache[quant_idx];
 
     bits += 8*s->prefix_bytes;
     bits += 8; /* quant_idx */
@@ -611,28 +618,28 @@ static int count_hq_slice(VC2EncContext *s, int slice_x,
         bits += 8;
         for (level = 0; level < s->wavelet_depth; level++) {
             for (orientation = !!level; orientation < 4; orientation++) {
-                dwtcoef *buf;
                 SubBand *b = &s->plane[p].band[level][orientation];
 
-                quant_idx = quants[level][orientation];
-                qfactor = ff_dirac_qscale_tab[quant_idx];
+                const int q_idx = quants[level][orientation];
+                const uint8_t *len_lut = &s->coef_lut_len[q_idx*COEF_LUT_TAB];
+                const int qfactor = ff_dirac_qscale_tab[q_idx];
 
-                left   = b->width  * slice_x    / s->num_x;
-                right  = b->width  *(slice_x+1) / s->num_x;
-                top    = b->height * slice_y    / s->num_y;
-                bottom = b->height *(slice_y+1) / s->num_y;
+                const int left   = b->width  * slice->x    / s->num_x;
+                const int right  = b->width  *(slice->x+1) / s->num_x;
+                const int top    = b->height * slice->y    / s->num_y;
+                const int bottom = b->height *(slice->y+1) / s->num_y;
 
-                buf = b->buf + top * b->stride;
+                dwtcoef *buf = b->buf + top * b->stride;
 
                 for (y = top; y < bottom; y++) {
                     for (x = left; x < right; x++) {
-                        qcoef coeff = (qcoef)buf[x];
-                        if (coeff >= -COEF_LUT_TAB && coeff < COEF_LUT_TAB) {
-                            bits += s->coef_lut_len[2*quant_idx*COEF_LUT_TAB + coeff + COEF_LUT_TAB];
+                        uint32_t c_abs = FFABS(buf[x]);
+                        if (c_abs < COEF_LUT_TAB) {
+                            bits += len_lut[c_abs];
                         } else {
-                            QUANT(coeff)
-                            bits += count_vc2_ue_uint(abs(coeff));
-                            bits += !!coeff;
+                            c_abs = QUANT(c_abs, qfactor);
+                            bits += count_vc2_ue_uint(c_abs);
+                            bits += !!c_abs;
                         }
                     }
                     buf += b->stride;
@@ -646,6 +653,8 @@ static int count_hq_slice(VC2EncContext *s, int slice_x,
         bits += pad_c*8;
     }
 
+    slice->cache[quant_idx] = bits;
+
     return bits;
 }
 
@@ -656,53 +665,103 @@ static int rate_control(AVCodecContext *avctx, void *arg)
 {
     SliceArgs *slice_dat = arg;
     VC2EncContext *s = slice_dat->ctx;
-    const int sx = slice_dat->x;
-    const int sy = slice_dat->y;
-    int bits_last = INT_MAX, quant_buf[2] = {-1, -1};
-    int quant = s->q_start, range = s->q_start/3;
-    const int64_t top = slice_dat->bits_ceil;
-    const double percent = s->tolerance;
-    const double bottom = top - top*(percent/100.0f);
-    int bits = count_hq_slice(s, sx, sy, quant);
-    range -= range & 1; /* Make it an even number */
+    const int top = slice_dat->bits_ceil;
+    const int bottom = slice_dat->bits_floor;
+    int quant_buf[2] = {-1, -1};
+    int quant = slice_dat->quant_idx, step = 1;
+    int bits_last, bits = count_hq_slice(slice_dat, quant);
     while ((bits > top) || (bits < bottom)) {
-        range *= bits > top ? +1 : -1;
-        quant = av_clip(quant + range, 0, s->q_ceil);
-        bits = count_hq_slice(s, sx, sy, quant);
-        range = av_clip(range/2, 1, s->q_ceil);
+        const int signed_step = bits > top ? +step : -step;
+        quant  = av_clip(quant + signed_step, 0, s->q_ceil-1);
+        bits   = count_hq_slice(slice_dat, quant);
         if (quant_buf[1] == quant) {
-            quant = bits_last < bits ? quant_buf[0] : quant;
-            bits  = bits_last < bits ? bits_last : bits;
+            quant = FFMAX(quant_buf[0], quant);
+            bits  = quant == quant_buf[0] ? bits_last : bits;
             break;
         }
+        step         = av_clip(step/2, 1, (s->q_ceil-1)/2);
         quant_buf[1] = quant_buf[0];
         quant_buf[0] = quant;
-        bits_last = bits;
+        bits_last    = bits;
     }
-    slice_dat->quant_idx = av_clip(quant, 0, s->q_ceil);
-    slice_dat->bytes = FFALIGN((bits >> 3), s->size_scaler) + 4 + s->prefix_bytes;
-
+    slice_dat->quant_idx = av_clip(quant, 0, s->q_ceil-1);
+    slice_dat->bytes = SSIZE_ROUND(bits >> 3);
     return 0;
 }
 
-static void calc_slice_sizes(VC2EncContext *s)
+static int calc_slice_sizes(VC2EncContext *s)
 {
-    int slice_x, slice_y;
+    int i, j, slice_x, slice_y, bytes_left = 0;
+    int bytes_top[SLICE_REDIST_TOTAL] = {0};
+    int64_t total_bytes_needed = 0;
+    int slice_redist_range = FFMIN(SLICE_REDIST_TOTAL, s->num_x*s->num_y);
     SliceArgs *enc_args = s->slice_args;
+    SliceArgs *top_loc[SLICE_REDIST_TOTAL] = {NULL};
+
+    init_quant_matrix(s);
 
     for (slice_y = 0; slice_y < s->num_y; slice_y++) {
         for (slice_x = 0; slice_x < s->num_x; slice_x++) {
             SliceArgs *args = &enc_args[s->num_x*slice_y + slice_x];
             args->ctx = s;
-            args->x = slice_x;
-            args->y = slice_y;
-            args->bits_ceil = s->slice_max_bytes << 3;
+            args->x   = slice_x;
+            args->y   = slice_y;
+            args->bits_ceil  = s->slice_max_bytes << 3;
+            args->bits_floor = s->slice_min_bytes << 3;
+            memset(args->cache, 0, s->q_ceil*sizeof(*args->cache));
         }
     }
 
-    /* Determine quantization indices and bytes per slice */
+    /* First pass - determine baseline slice sizes w.r.t. max_slice_size */
     s->avctx->execute(s->avctx, rate_control, enc_args, NULL, s->num_x*s->num_y,
                       sizeof(SliceArgs));
+
+    for (i = 0; i < s->num_x*s->num_y; i++) {
+        SliceArgs *args = &enc_args[i];
+        bytes_left += s->slice_max_bytes - args->bytes;
+        for (j = 0; j < slice_redist_range; j++) {
+            if (args->bytes > bytes_top[j]) {
+                bytes_top[j] = args->bytes;
+                top_loc[j]   = args;
+                break;
+            }
+        }
+    }
+
+    /* Second pass - distribute leftover bytes */
+    while (1) {
+        int distributed = 0;
+        for (i = 0; i < slice_redist_range; i++) {
+            SliceArgs *args;
+            int bits, bytes, diff, prev_bytes, new_idx;
+            if (bytes_left <= 0)
+                break;
+            if (!top_loc[i] || !top_loc[i]->quant_idx)
+                break;
+            args = top_loc[i];
+            prev_bytes = args->bytes;
+            new_idx = FFMAX(args->quant_idx - 1, 0);
+            bits  = count_hq_slice(args, new_idx);
+            bytes = SSIZE_ROUND(bits >> 3);
+            diff  = bytes - prev_bytes;
+            if ((bytes_left - diff) > 0) {
+                args->quant_idx = new_idx;
+                args->bytes = bytes;
+                bytes_left -= diff;
+                distributed++;
+            }
+        }
+        if (!distributed)
+            break;
+    }
+
+    for (i = 0; i < s->num_x*s->num_y; i++) {
+        SliceArgs *args = &enc_args[i];
+        total_bytes_needed += args->bytes;
+        s->q_avg = (s->q_avg + args->quant_idx)/2;
+    }
+
+    return total_bytes_needed;
 }
 
 /* VC-2 13.5.3 - hq_slice */
@@ -718,8 +777,10 @@ static int encode_hq_slice(AVCodecContext *avctx, void *arg)
     uint8_t quants[MAX_DWT_LEVELS][4];
     int p, level, orientation;
 
-    avpriv_align_put_bits(pb);
-    put_padding(pb, s->prefix_bytes);
+    /* The reference decoder ignores it, and its typical length is 0 */
+    memset(put_bits_ptr(pb), 0, s->prefix_bytes);
+    skip_put_bytes(pb, s->prefix_bytes);
+
     put_bits(pb, 8, quant_idx);
 
     /* Slice quantization (slice_quantizers() in the specs) */
@@ -750,7 +811,10 @@ static int encode_hq_slice(AVCodecContext *avctx, void *arg)
             pad_c = (pad_s*s->size_scaler) - bytes_len;
         }
         pb->buf[bytes_start] = pad_s;
-        put_padding(pb, pad_c);
+        flush_put_bits(pb);
+        /* vc2-reference uses that padding that decodes to '0' coeffs */
+        memset(put_bits_ptr(pb), 0xFF, pad_c);
+        skip_put_bytes(pb, pad_c);
     }
 
     return 0;
@@ -770,8 +834,7 @@ static int encode_slices(VC2EncContext *s)
     for (slice_y = 0; slice_y < s->num_y; slice_y++) {
         for (slice_x = 0; slice_x < s->num_x; slice_x++) {
             SliceArgs *args = &enc_args[s->num_x*slice_y + slice_x];
-            init_put_bits(&args->pb, buf + skip, args->bytes);
-            s->q_start = (s->q_start + args->quant_idx)/2;
+            init_put_bits(&args->pb, buf + skip, args->bytes+s->prefix_bytes);
             skip += args->bytes;
         }
     }
@@ -819,8 +882,6 @@ static int encode_slices(VC2EncContext *s)
  * of levels. The rest of the areas can be thought as the details needed
  * to restore the image perfectly to its original size.
  */
-
-
 static int dwt_plane(AVCodecContext *avctx, void *arg)
 {
     TransformArgs *transform_dat = arg;
@@ -878,10 +939,36 @@ static int dwt_plane(AVCodecContext *avctx, void *arg)
     return 0;
 }
 
-static void encode_frame(VC2EncContext *s, const AVFrame *frame,
-                         const char *aux_data, int field)
+static int encode_frame(VC2EncContext *s, AVPacket *avpkt, const AVFrame *frame,
+                        const char *aux_data, const int header_size, int field)
 {
-    int i;
+    int i, ret;
+    int64_t max_frame_bytes;
+
+     /* Threaded DWT transform */
+    for (i = 0; i < 3; i++) {
+        s->transform_args[i].ctx   = s;
+        s->transform_args[i].field = field;
+        s->transform_args[i].plane = &s->plane[i];
+        s->transform_args[i].idata = frame->data[i];
+        s->transform_args[i].istride = frame->linesize[i];
+    }
+    s->avctx->execute(s->avctx, dwt_plane, s->transform_args, NULL, 3,
+                      sizeof(TransformArgs));
+
+    /* Calculate per-slice quantizers and sizes */
+    max_frame_bytes = header_size + calc_slice_sizes(s);
+
+    if (field < 2) {
+        ret = ff_alloc_packet2(s->avctx, avpkt,
+                               max_frame_bytes << s->interlaced,
+                               max_frame_bytes << s->interlaced);
+        if (ret) {
+            av_log(s->avctx, AV_LOG_ERROR, "Error getting output packet.\n");
+            return ret;
+        }
+        init_put_bits(&s->pb, avpkt->data, avpkt->size);
+    }
 
     /* Sequence header */
     encode_parse_info(s, DIRAC_PCODE_SEQ_HEADER);
@@ -897,41 +984,29 @@ static void encode_frame(VC2EncContext *s, const AVFrame *frame,
     encode_parse_info(s, DIRAC_PCODE_PICTURE_HQ);
     encode_picture_start(s);
 
-    for (i = 0; i < 3; i++) {
-        s->transform_args[i].ctx   = s;
-        s->transform_args[i].field = field;
-        s->transform_args[i].plane = &s->plane[i];
-        s->transform_args[i].idata = frame->data[i];
-        s->transform_args[i].istride = frame->linesize[i];
-    }
-
-    /* Do a DWT transform */
-    s->avctx->execute(s->avctx, dwt_plane, s->transform_args, NULL, 3,
-                      sizeof(TransformArgs));
-
-    /* Calculate per-slice quantizers and sizes */
-    calc_slice_sizes(s);
-
-    /* Init planes and encode slices */
+    /* Encode slices */
     encode_slices(s);
 
     /* End sequence */
     encode_parse_info(s, DIRAC_PCODE_END_SEQ);
+
+    return 0;
 }
 
 static av_cold int vc2_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
-                                      const AVFrame *frame, int *got_packet_ptr)
+                                      const AVFrame *frame, int *got_packet)
 {
-    int ret;
-    int max_frame_bytes, sig_size = 256;
+    int ret = 0;
+    int sig_size = 256;
     VC2EncContext *s = avctx->priv_data;
-    const char aux_data[] = "FFmpeg version "FFMPEG_VERSION;
-    const int aux_data_size = sizeof(aux_data);
+    const int bitexact = avctx->flags & AV_CODEC_FLAG_BITEXACT;
+    const char *aux_data = bitexact ? "Lavc" : LIBAVCODEC_IDENT;
+    const int aux_data_size = bitexact ? sizeof("Lavc") : sizeof(LIBAVCODEC_IDENT);
     const int header_size = 100 + aux_data_size;
-    int64_t r_bitrate = avctx->bit_rate >> (s->interlaced);
+    int64_t max_frame_bytes, r_bitrate = avctx->bit_rate >> (s->interlaced);
 
     s->avctx = avctx;
-    s->size_scaler = 1;
+    s->size_scaler = 2;
     s->prefix_bytes = 0;
     s->last_parse_code = 0;
     s->next_parse_offset = 0;
@@ -939,32 +1014,31 @@ static av_cold int vc2_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     /* Rate control */
     max_frame_bytes = (av_rescale(r_bitrate, s->avctx->time_base.num,
                                   s->avctx->time_base.den) >> 3) - header_size;
+    s->slice_max_bytes = av_rescale(max_frame_bytes, 1, s->num_x*s->num_y);
 
     /* Find an appropriate size scaler */
     while (sig_size > 255) {
-        s->slice_max_bytes = FFALIGN(av_rescale(max_frame_bytes, 1,
-                                     s->num_x*s->num_y), s->size_scaler);
-        s->slice_max_bytes += 4 + s->prefix_bytes;
-        sig_size = s->slice_max_bytes/s->size_scaler; /* Signalled slize size */
+        int r_size = SSIZE_ROUND(s->slice_max_bytes);
+        sig_size = r_size/s->size_scaler; /* Signalled slize size */
         s->size_scaler <<= 1;
     }
 
-    ret = ff_alloc_packet2(avctx, avpkt, max_frame_bytes*2, 0);
-    if (ret < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
+    s->slice_max_bytes = SSIZE_ROUND(s->slice_max_bytes);
+    s->slice_min_bytes = s->slice_max_bytes - s->slice_max_bytes*(s->tolerance/100.0f);
+
+    ret = encode_frame(s, avpkt, frame, aux_data, header_size, s->interlaced);
+    if (ret)
         return ret;
-    } else {
-        init_put_bits(&s->pb, avpkt->data, avpkt->size);
+    if (s->interlaced) {
+        ret = encode_frame(s, avpkt, frame, aux_data, header_size, 2);
+        if (ret)
+            return ret;
     }
 
-    encode_frame(s, frame, aux_data, s->interlaced);
-    if (s->interlaced)
-        encode_frame(s, frame, NULL, 2);
-
     flush_put_bits(&s->pb);
     avpkt->size = put_bits_count(&s->pb) >> 3;
 
-    *got_packet_ptr = 1;
+    *got_packet = 1;
 
     return 0;
 }
@@ -974,6 +1048,8 @@ static av_cold int vc2_encode_end(AVCodecContext *avctx)
     int i;
     VC2EncContext *s = avctx->priv_data;
 
+    av_log(avctx, AV_LOG_INFO, "Qavg: %i\n", s->q_avg);
+
     for (i = 0; i < 3; i++) {
         ff_vc2enc_free_transforms(&s->transform_args[i].t);
         av_freep(&s->plane[i].coef_buf);
@@ -986,12 +1062,13 @@ static av_cold int vc2_encode_end(AVCodecContext *avctx)
     return 0;
 }
 
-
 static av_cold int vc2_encode_init(AVCodecContext *avctx)
 {
     Plane *p;
     SubBand *b;
     int i, j, level, o, shift;
+    const AVPixFmtDescriptor *fmt = av_pix_fmt_desc_get(avctx->pix_fmt);
+    const int depth = fmt->comp[0].depth;
     VC2EncContext *s = avctx->priv_data;
 
     s->picture_number = 0;
@@ -1007,44 +1084,31 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx)
     s->base_vf   = -1;
     s->strict_compliance = 1;
 
+    s->q_avg = 0;
+    s->slice_max_bytes = 0;
+    s->slice_min_bytes = 0;
+
     /* Mark unknown as progressive */
     s->interlaced = !((avctx->field_order == AV_FIELD_UNKNOWN) ||
                       (avctx->field_order == AV_FIELD_PROGRESSIVE));
 
-    if (avctx->pix_fmt == AV_PIX_FMT_YUV422P10) {
-        if (avctx->width == 1280 && avctx->height == 720) {
-            s->level = 3;
-            if (avctx->time_base.num == 1001 && avctx->time_base.den == 60000)
-                s->base_vf = 9;
-            if (avctx->time_base.num == 1 && avctx->time_base.den == 50)
-                s->base_vf = 10;
-        } else if (avctx->width == 1920 && avctx->height == 1080) {
-            s->level = 3;
-            if (s->interlaced) {
-                if (avctx->time_base.num == 1001 && avctx->time_base.den == 30000)
-                    s->base_vf = 11;
-                if (avctx->time_base.num == 1 && avctx->time_base.den == 50)
-                    s->base_vf = 12;
-            } else {
-                if (avctx->time_base.num == 1001 && avctx->time_base.den == 60000)
-                    s->base_vf = 13;
-                if (avctx->time_base.num == 1 && avctx->time_base.den == 50)
-                    s->base_vf = 14;
-                if (avctx->time_base.num == 1001 && avctx->time_base.den == 24000)
-                    s->base_vf = 21;
-            }
-        } else if (avctx->width == 3840 && avctx->height == 2160) {
-            s->level = 6;
-            if (avctx->time_base.num == 1001 && avctx->time_base.den == 60000)
-                s->base_vf = 17;
-            if (avctx->time_base.num == 1 && avctx->time_base.den == 50)
-                s->base_vf = 18;
-        }
-    }
-
-    if (s->interlaced && s->base_vf <= 0) {
-        av_log(avctx, AV_LOG_ERROR, "Interlacing not supported with non standard formats!\n");
-        return AVERROR_UNKNOWN;
+    for (i = 0; i < base_video_fmts_len; i++) {
+        const VC2BaseVideoFormat *fmt = &base_video_fmts[i];
+        if (avctx->pix_fmt != fmt->pix_fmt)
+            continue;
+        if (avctx->time_base.num != fmt->time_base.num)
+            continue;
+        if (avctx->time_base.den != fmt->time_base.den)
+            continue;
+        if (avctx->width != fmt->width)
+            continue;
+        if (avctx->height != fmt->height)
+            continue;
+        if (s->interlaced != fmt->interlaced)
+            continue;
+        s->base_vf = i;
+        s->level   = base_video_fmts[i].level;
+        break;
     }
 
     if (s->interlaced)
@@ -1072,11 +1136,33 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx)
             return AVERROR_UNKNOWN;
         }
     } else {
-        av_log(avctx, AV_LOG_INFO, "Selected base video format = %i\n", s->base_vf);
+        av_log(avctx, AV_LOG_INFO, "Selected base video format = %i (%s)\n",
+               s->base_vf, base_video_fmts[s->base_vf].name);
     }
 
+    /* Chroma subsampling */
     avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift);
 
+    /* Bit depth and color range index */
+    if (depth == 8 && avctx->color_range == AVCOL_RANGE_JPEG) {
+        s->bpp = 1;
+        s->bpp_idx = 1;
+        s->diff_offset = 128;
+    } else if (depth == 8 && (avctx->color_range == AVCOL_RANGE_MPEG ||
+               avctx->color_range == AVCOL_RANGE_UNSPECIFIED)) {
+        s->bpp = 1;
+        s->bpp_idx = 2;
+        s->diff_offset = 128;
+    } else if (depth == 10) {
+        s->bpp = 2;
+        s->bpp_idx = 3;
+        s->diff_offset = 512;
+    } else {
+        s->bpp = 2;
+        s->bpp_idx = 4;
+        s->diff_offset = 2048;
+    }
+
     /* Planes initialization */
     for (i = 0; i < 3; i++) {
         int w, h;
@@ -1106,8 +1192,8 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx)
 
         /* DWT init */
         if (ff_vc2enc_init_transforms(&s->transform_args[i].t,
-                                        s->plane[0].coef_stride,
-                                        s->plane[0].dwt_height))
+                                      s->plane[i].coef_stride,
+                                      s->plane[i].dwt_height))
             goto alloc_fail;
     }
 
@@ -1115,24 +1201,31 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx)
     s->num_x = s->plane[0].dwt_width/s->slice_width;
     s->num_y = s->plane[0].dwt_height/s->slice_height;
 
-    s->slice_args = av_malloc(s->num_x*s->num_y*sizeof(SliceArgs));
+    s->slice_args = av_calloc(s->num_x*s->num_y, sizeof(SliceArgs));
     if (!s->slice_args)
         goto alloc_fail;
 
     /* Lookup tables */
-    s->coef_lut_len = av_malloc(2*COEF_LUT_TAB*s->q_ceil*sizeof(*s->coef_lut_len));
+    s->coef_lut_len = av_malloc(COEF_LUT_TAB*(s->q_ceil+1)*sizeof(*s->coef_lut_len));
     if (!s->coef_lut_len)
         goto alloc_fail;
 
-    s->coef_lut_val = av_malloc(2*COEF_LUT_TAB*s->q_ceil*sizeof(*s->coef_lut_val));
+    s->coef_lut_val = av_malloc(COEF_LUT_TAB*(s->q_ceil+1)*sizeof(*s->coef_lut_val));
     if (!s->coef_lut_val)
         goto alloc_fail;
 
     for (i = 0; i < s->q_ceil; i++) {
-        for (j = -COEF_LUT_TAB; j < COEF_LUT_TAB; j++) {
-            uint8_t  *len_lut = &s->coef_lut_len[2*i*COEF_LUT_TAB + COEF_LUT_TAB];
-            uint32_t *val_lut = &s->coef_lut_val[2*i*COEF_LUT_TAB + COEF_LUT_TAB];
-            coeff_quantize_get(j, ff_dirac_qscale_tab[i], &len_lut[j], &val_lut[j]);
+        uint8_t  *len_lut = &s->coef_lut_len[i*COEF_LUT_TAB];
+        uint32_t *val_lut = &s->coef_lut_val[i*COEF_LUT_TAB];
+        for (j = 0; j < COEF_LUT_TAB; j++) {
+            get_vc2_ue_uint(QUANT(j, ff_dirac_qscale_tab[i]),
+                            &len_lut[j], &val_lut[j]);
+            if (len_lut[j] != 1) {
+                len_lut[j] += 1;
+                val_lut[j] <<= 1;
+            } else {
+                val_lut[j] = 1;
+            }
         }
     }
 
@@ -1146,13 +1239,15 @@ alloc_fail:
 
 #define VC2ENC_FLAGS (AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
 static const AVOption vc2enc_options[] = {
-    {"tolerance",     "Max undershoot in percent", offsetof(VC2EncContext, tolerance), AV_OPT_TYPE_DOUBLE, {.dbl = 10.0f}, 0.0f, 45.0f, VC2ENC_FLAGS, "tolerance"},
-    {"slice_width",   "Slice width",  offsetof(VC2EncContext, slice_width), AV_OPT_TYPE_INT, {.i64 = 128}, 32, 1024, VC2ENC_FLAGS, "slice_width"},
-    {"slice_height",  "Slice height", offsetof(VC2EncContext, slice_height), AV_OPT_TYPE_INT, {.i64 = 64}, 8, 1024, VC2ENC_FLAGS, "slice_height"},
-    {"wavelet_depth", "Transform depth", offsetof(VC2EncContext, wavelet_depth), AV_OPT_TYPE_INT, {.i64 = 5}, 1, 5, VC2ENC_FLAGS, "wavelet_depth"},
+    {"tolerance",     "Max undershoot in percent", offsetof(VC2EncContext, tolerance), AV_OPT_TYPE_DOUBLE, {.dbl = 5.0f}, 0.0f, 45.0f, VC2ENC_FLAGS, "tolerance"},
+    {"slice_width",   "Slice width",  offsetof(VC2EncContext, slice_width), AV_OPT_TYPE_INT, {.i64 = 32}, 32, 1024, VC2ENC_FLAGS, "slice_width"},
+    {"slice_height",  "Slice height", offsetof(VC2EncContext, slice_height), AV_OPT_TYPE_INT, {.i64 = 16}, 8, 1024, VC2ENC_FLAGS, "slice_height"},
+    {"wavelet_depth", "Transform depth", offsetof(VC2EncContext, wavelet_depth), AV_OPT_TYPE_INT, {.i64 = 4}, 1, 5, VC2ENC_FLAGS, "wavelet_depth"},
     {"wavelet_type",  "Transform type",  offsetof(VC2EncContext, wavelet_idx), AV_OPT_TYPE_INT, {.i64 = VC2_TRANSFORM_9_7}, 0, VC2_TRANSFORMS_NB, VC2ENC_FLAGS, "wavelet_idx"},
-        {"9_7",       "Deslauriers-Dubuc (9,7)", 0, AV_OPT_TYPE_CONST, {.i64 = VC2_TRANSFORM_9_7}, INT_MIN, INT_MAX, VC2ENC_FLAGS, "wavelet_idx"},
-        {"5_3",       "LeGall (5,3)",            0, AV_OPT_TYPE_CONST, {.i64 = VC2_TRANSFORM_5_3}, INT_MIN, INT_MAX, VC2ENC_FLAGS, "wavelet_idx"},
+        {"9_7",          "Deslauriers-Dubuc (9,7)", 0, AV_OPT_TYPE_CONST, {.i64 = VC2_TRANSFORM_9_7},    INT_MIN, INT_MAX, VC2ENC_FLAGS, "wavelet_idx"},
+        {"5_3",          "LeGall (5,3)",            0, AV_OPT_TYPE_CONST, {.i64 = VC2_TRANSFORM_5_3},    INT_MIN, INT_MAX, VC2ENC_FLAGS, "wavelet_idx"},
+        {"haar",         "Haar (with shift)",       0, AV_OPT_TYPE_CONST, {.i64 = VC2_TRANSFORM_HAAR_S}, INT_MIN, INT_MAX, VC2ENC_FLAGS, "wavelet_idx"},
+        {"haar_noshift", "Haar (without shift)",    0, AV_OPT_TYPE_CONST, {.i64 = VC2_TRANSFORM_HAAR},   INT_MIN, INT_MAX, VC2ENC_FLAGS, "wavelet_idx"},
     {"qm", "Custom quantization matrix", offsetof(VC2EncContext, quant_matrix), AV_OPT_TYPE_INT, {.i64 = VC2_QM_DEF}, 0, VC2_QM_NB, VC2ENC_FLAGS, "quant_matrix"},
         {"default",   "Default from the specifications", 0, AV_OPT_TYPE_CONST, {.i64 = VC2_QM_DEF}, INT_MIN, INT_MAX, VC2ENC_FLAGS, "quant_matrix"},
         {"color",     "Prevents low bitrate discoloration", 0, AV_OPT_TYPE_CONST, {.i64 = VC2_QM_COL}, INT_MIN, INT_MAX, VC2ENC_FLAGS, "quant_matrix"},
@@ -1181,16 +1276,17 @@ static const enum AVPixelFormat allowed_pix_fmts[] = {
 };
 
 AVCodec ff_vc2_encoder = {
-    .name = "vc2",
-    .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-2"),
-    .type = AVMEDIA_TYPE_VIDEO,
-    .id = AV_CODEC_ID_DIRAC,
+    .name           = "vc2",
+    .long_name      = NULL_IF_CONFIG_SMALL("SMPTE VC-2"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_DIRAC,
     .priv_data_size = sizeof(VC2EncContext),
-    .init = vc2_encode_init,
-    .close = vc2_encode_end,
-    .capabilities = AV_CODEC_CAP_SLICE_THREADS,
-    .encode2 = vc2_encode_frame,
-    .priv_class = &vc2enc_class,
-    .defaults = vc2enc_defaults,
-    .pix_fmts = allowed_pix_fmts
+    .init           = vc2_encode_init,
+    .close          = vc2_encode_end,
+    .capabilities   = AV_CODEC_CAP_SLICE_THREADS,
+    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
+    .encode2        = vc2_encode_frame,
+    .priv_class     = &vc2enc_class,
+    .defaults       = vc2enc_defaults,
+    .pix_fmts       = allowed_pix_fmts
 };
diff --git a/libavcodec/vc2enc_dwt.c b/libavcodec/vc2enc_dwt.c
index eb34168..c60b003 100644
--- a/libavcodec/vc2enc_dwt.c
+++ b/libavcodec/vc2enc_dwt.c
@@ -211,10 +211,56 @@ static void vc2_subband_dwt_53(VC2TransformContext *t, dwtcoef *data,
     deinterleave(data, stride, width, height, synth);
 }
 
+static av_always_inline void dwt_haar(VC2TransformContext *t, dwtcoef *data,
+                                      ptrdiff_t stride, int width, int height,
+                                      const int s)
+{
+    int x, y;
+    dwtcoef *synth = t->buffer, *synthl = synth, *datal = data;
+    const ptrdiff_t synth_width  = width  << 1;
+    const ptrdiff_t synth_height = height << 1;
+
+    /* Horizontal synthesis. */
+    for (y = 0; y < synth_height; y++) {
+        for (x = 0; x < synth_width; x += 2) {
+            synthl[y*synth_width + x + 1] = (datal[y*stride + x + 1] << s) -
+                                            (datal[y*stride + x] << s);
+            synthl[y*synth_width + x] = (datal[y*stride + x + 0] << s) +
+                                        ((synthl[y*synth_width + x + 1] + 1) >> 1);
+        }
+    }
+
+    /* Vertical synthesis. */
+    for (x = 0; x < synth_width; x++) {
+        for (y = 0; y < synth_height; y += 2) {
+            synthl[(y + 1)*synth_width + x] = synthl[(y + 1)*synth_width + x] -
+                                              synthl[y*synth_width + x];
+            synthl[y*synth_width + x] = synthl[y*synth_width + x] +
+                                        ((synthl[(y + 1)*synth_width + x] + 1) >> 1);
+        }
+    }
+
+    deinterleave(data, stride, width, height, synth);
+}
+
+static void vc2_subband_dwt_haar(VC2TransformContext *t, dwtcoef *data,
+                                 ptrdiff_t stride, int width, int height)
+{
+    dwt_haar(t, data, stride, width, height, 0);
+}
+
+static void vc2_subband_dwt_haar_shift(VC2TransformContext *t, dwtcoef *data,
+                                       ptrdiff_t stride, int width, int height)
+{
+    dwt_haar(t, data, stride, width, height, 1);
+}
+
 av_cold int ff_vc2enc_init_transforms(VC2TransformContext *s, int p_width, int p_height)
 {
     s->vc2_subband_dwt[VC2_TRANSFORM_9_7]    = vc2_subband_dwt_97;
     s->vc2_subband_dwt[VC2_TRANSFORM_5_3]    = vc2_subband_dwt_53;
+    s->vc2_subband_dwt[VC2_TRANSFORM_HAAR]   = vc2_subband_dwt_haar;
+    s->vc2_subband_dwt[VC2_TRANSFORM_HAAR_S] = vc2_subband_dwt_haar_shift;
 
     s->buffer = av_malloc(2*p_width*p_height*sizeof(dwtcoef));
     if (!s->buffer)
diff --git a/libavcodec/vc2enc_dwt.h b/libavcodec/vc2enc_dwt.h
index 8e1b614..7fbbfbe 100644
--- a/libavcodec/vc2enc_dwt.h
+++ b/libavcodec/vc2enc_dwt.h
@@ -25,10 +25,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-typedef int16_t dwtcoef;
-typedef int32_t qcoef;   /* Quantization needs more precision */
-
-/* Only Deslauriers-Dubuc (9,7) and LeGall (5,3) supported! */
+typedef int32_t dwtcoef;
 
 enum VC2TransformType {
     VC2_TRANSFORM_9_7    = 0,   /* Deslauriers-Dubuc (9,7)  */
diff --git a/libavcodec/vda_h264_dec.c b/libavcodec/vda_h264_dec.c
index a092693..a196eb7 100644
--- a/libavcodec/vda_h264_dec.c
+++ b/libavcodec/vda_h264_dec.c
@@ -226,7 +226,7 @@ static av_cold int vdadec_init(AVCodecContext *avctx)
     ctx->h264_initialized = 1;
 
     for (i = 0; i < MAX_SPS_COUNT; i++) {
-        SPS *sps = ctx->h264ctx.sps_buffers[i];
+        const SPS *sps = (const SPS*)ctx->h264ctx.ps.sps_list[i]->data;
         if (sps && (sps->bit_depth_luma != 8 ||
                 sps->chroma_format_idc == 2 ||
                 sps->chroma_format_idc == 3)) {
diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c
index a01c445..1d4c1ce 100644
--- a/libavcodec/vdpau.c
+++ b/libavcodec/vdpau.c
@@ -22,19 +22,26 @@
  */
 
 #include <limits.h>
-#include "libavutil/avassert.h"
+
 #include "avcodec.h"
 #include "internal.h"
 #include "h264.h"
 #include "vc1.h"
-
-#undef NDEBUG
-#include <assert.h>
-
 #include "vdpau.h"
 #include "vdpau_compat.h"
 #include "vdpau_internal.h"
 
+// XXX: at the time of adding this ifdefery, av_assert* wasn't use outside.
+// When dropping it, make sure other av_assert* were not added since then.
+#if FF_API_BUFS_VDPAU
+#include "libavutil/avassert.h"
+#endif
+
+#if FF_API_VDPAU
+#undef NDEBUG
+#include <assert.h>
+#endif
+
 /**
  * @addtogroup VDPAU_Decoding
  *
@@ -459,7 +466,7 @@ void ff_vdpau_h264_picture_start(H264Context *h)
         render->info.h264.field_order_cnt[i] = foc;
     }
 
-    render->info.h264.frame_num = h->frame_num;
+    render->info.h264.frame_num = h->poc.frame_num;
 }
 
 void ff_vdpau_h264_picture_complete(H264Context *h)
@@ -476,30 +483,30 @@ void ff_vdpau_h264_picture_complete(H264Context *h)
     render->info.h264.is_reference                           = (h->cur_pic_ptr->reference & 3) ? VDP_TRUE : VDP_FALSE;
     render->info.h264.field_pic_flag                         = h->picture_structure != PICT_FRAME;
     render->info.h264.bottom_field_flag                      = h->picture_structure == PICT_BOTTOM_FIELD;
-    render->info.h264.num_ref_frames                         = h->sps.ref_frame_count;
-    render->info.h264.mb_adaptive_frame_field_flag           = h->sps.mb_aff && !render->info.h264.field_pic_flag;
-    render->info.h264.constrained_intra_pred_flag            = h->pps.constrained_intra_pred;
-    render->info.h264.weighted_pred_flag                     = h->pps.weighted_pred;
-    render->info.h264.weighted_bipred_idc                    = h->pps.weighted_bipred_idc;
-    render->info.h264.frame_mbs_only_flag                    = h->sps.frame_mbs_only_flag;
-    render->info.h264.transform_8x8_mode_flag                = h->pps.transform_8x8_mode;
-    render->info.h264.chroma_qp_index_offset                 = h->pps.chroma_qp_index_offset[0];
-    render->info.h264.second_chroma_qp_index_offset          = h->pps.chroma_qp_index_offset[1];
-    render->info.h264.pic_init_qp_minus26                    = h->pps.init_qp - 26;
-    render->info.h264.num_ref_idx_l0_active_minus1           = h->pps.ref_count[0] - 1;
-    render->info.h264.num_ref_idx_l1_active_minus1           = h->pps.ref_count[1] - 1;
-    render->info.h264.log2_max_frame_num_minus4              = h->sps.log2_max_frame_num - 4;
-    render->info.h264.pic_order_cnt_type                     = h->sps.poc_type;
-    render->info.h264.log2_max_pic_order_cnt_lsb_minus4      = h->sps.poc_type ? 0 : h->sps.log2_max_poc_lsb - 4;
-    render->info.h264.delta_pic_order_always_zero_flag       = h->sps.delta_pic_order_always_zero_flag;
-    render->info.h264.direct_8x8_inference_flag              = h->sps.direct_8x8_inference_flag;
-    render->info.h264.entropy_coding_mode_flag               = h->pps.cabac;
-    render->info.h264.pic_order_present_flag                 = h->pps.pic_order_present;
-    render->info.h264.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
-    render->info.h264.redundant_pic_cnt_present_flag         = h->pps.redundant_pic_cnt_present;
-    memcpy(render->info.h264.scaling_lists_4x4, h->pps.scaling_matrix4, sizeof(render->info.h264.scaling_lists_4x4));
-    memcpy(render->info.h264.scaling_lists_8x8[0], h->pps.scaling_matrix8[0], sizeof(render->info.h264.scaling_lists_8x8[0]));
-    memcpy(render->info.h264.scaling_lists_8x8[1], h->pps.scaling_matrix8[3], sizeof(render->info.h264.scaling_lists_8x8[0]));
+    render->info.h264.num_ref_frames                         = h->ps.sps->ref_frame_count;
+    render->info.h264.mb_adaptive_frame_field_flag           = h->ps.sps->mb_aff && !render->info.h264.field_pic_flag;
+    render->info.h264.constrained_intra_pred_flag            = h->ps.pps->constrained_intra_pred;
+    render->info.h264.weighted_pred_flag                     = h->ps.pps->weighted_pred;
+    render->info.h264.weighted_bipred_idc                    = h->ps.pps->weighted_bipred_idc;
+    render->info.h264.frame_mbs_only_flag                    = h->ps.sps->frame_mbs_only_flag;
+    render->info.h264.transform_8x8_mode_flag                = h->ps.pps->transform_8x8_mode;
+    render->info.h264.chroma_qp_index_offset                 = h->ps.pps->chroma_qp_index_offset[0];
+    render->info.h264.second_chroma_qp_index_offset          = h->ps.pps->chroma_qp_index_offset[1];
+    render->info.h264.pic_init_qp_minus26                    = h->ps.pps->init_qp - 26;
+    render->info.h264.num_ref_idx_l0_active_minus1           = h->ps.pps->ref_count[0] - 1;
+    render->info.h264.num_ref_idx_l1_active_minus1           = h->ps.pps->ref_count[1] - 1;
+    render->info.h264.log2_max_frame_num_minus4              = h->ps.sps->log2_max_frame_num - 4;
+    render->info.h264.pic_order_cnt_type                     = h->ps.sps->poc_type;
+    render->info.h264.log2_max_pic_order_cnt_lsb_minus4      = h->ps.sps->poc_type ? 0 : h->ps.sps->log2_max_poc_lsb - 4;
+    render->info.h264.delta_pic_order_always_zero_flag       = h->ps.sps->delta_pic_order_always_zero_flag;
+    render->info.h264.direct_8x8_inference_flag              = h->ps.sps->direct_8x8_inference_flag;
+    render->info.h264.entropy_coding_mode_flag               = h->ps.pps->cabac;
+    render->info.h264.pic_order_present_flag                 = h->ps.pps->pic_order_present;
+    render->info.h264.deblocking_filter_control_present_flag = h->ps.pps->deblocking_filter_parameters_present;
+    render->info.h264.redundant_pic_cnt_present_flag         = h->ps.pps->redundant_pic_cnt_present;
+    memcpy(render->info.h264.scaling_lists_4x4, h->ps.pps->scaling_matrix4, sizeof(render->info.h264.scaling_lists_4x4));
+    memcpy(render->info.h264.scaling_lists_8x8[0], h->ps.pps->scaling_matrix8[0], sizeof(render->info.h264.scaling_lists_8x8[0]));
+    memcpy(render->info.h264.scaling_lists_8x8[1], h->ps.pps->scaling_matrix8[3], sizeof(render->info.h264.scaling_lists_8x8[0]));
 
     ff_h264_draw_horiz_band(h, &h->slice_ctx[0], 0, h->avctx->height);
     render->bitstream_buffers_used = 0;
@@ -694,6 +701,7 @@ void ff_vdpau_mpeg4_decode_picture(Mpeg4DecContext *ctx, const uint8_t *buf,
 #endif /* CONFIG_MPEG4_VDPAU_DECODER */
 #endif /* FF_API_VDPAU */
 
+#if FF_API_VDPAU_PROFILE
 int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile)
 {
 #define PROFILE(prof)                      \
@@ -740,6 +748,7 @@ do {                                       \
     return AVERROR(EINVAL);
 #undef PROFILE
 }
+#endif /* FF_API_VDPAU_PROFILE */
 
 AVVDPAUContext *av_vdpau_alloc_context(void)
 {
diff --git a/libavcodec/vdpau_h264.c b/libavcodec/vdpau_h264.c
index 10376ac..5ae3449 100644
--- a/libavcodec/vdpau_h264.c
+++ b/libavcodec/vdpau_h264.c
@@ -120,6 +120,8 @@ static int vdpau_h264_start_frame(AVCodecContext *avctx,
                                   const uint8_t *buffer, uint32_t size)
 {
     H264Context * const h = avctx->priv_data;
+    const PPS *pps = h->ps.pps;
+    const SPS *sps = h->ps.sps;
     H264Picture *pic = h->cur_pic_ptr;
     struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private;
     VdpPictureInfoH264 *info = &pic_ctx->info.h264;
@@ -132,40 +134,40 @@ static int vdpau_h264_start_frame(AVCodecContext *avctx,
     info->field_order_cnt[0]                     = h264_foc(pic->field_poc[0]);
     info->field_order_cnt[1]                     = h264_foc(pic->field_poc[1]);
     info->is_reference                           = h->nal_ref_idc != 0;
-    info->frame_num                              = h->frame_num;
+    info->frame_num                              = h->poc.frame_num;
     info->field_pic_flag                         = h->picture_structure != PICT_FRAME;
     info->bottom_field_flag                      = h->picture_structure == PICT_BOTTOM_FIELD;
-    info->num_ref_frames                         = h->sps.ref_frame_count;
-    info->mb_adaptive_frame_field_flag           = h->sps.mb_aff && !info->field_pic_flag;
-    info->constrained_intra_pred_flag            = h->pps.constrained_intra_pred;
-    info->weighted_pred_flag                     = h->pps.weighted_pred;
-    info->weighted_bipred_idc                    = h->pps.weighted_bipred_idc;
-    info->frame_mbs_only_flag                    = h->sps.frame_mbs_only_flag;
-    info->transform_8x8_mode_flag                = h->pps.transform_8x8_mode;
-    info->chroma_qp_index_offset                 = h->pps.chroma_qp_index_offset[0];
-    info->second_chroma_qp_index_offset          = h->pps.chroma_qp_index_offset[1];
-    info->pic_init_qp_minus26                    = h->pps.init_qp - 26;
-    info->num_ref_idx_l0_active_minus1           = h->pps.ref_count[0] - 1;
-    info->num_ref_idx_l1_active_minus1           = h->pps.ref_count[1] - 1;
-    info->log2_max_frame_num_minus4              = h->sps.log2_max_frame_num - 4;
-    info->pic_order_cnt_type                     = h->sps.poc_type;
-    info->log2_max_pic_order_cnt_lsb_minus4      = h->sps.poc_type ? 0 : h->sps.log2_max_poc_lsb - 4;
-    info->delta_pic_order_always_zero_flag       = h->sps.delta_pic_order_always_zero_flag;
-    info->direct_8x8_inference_flag              = h->sps.direct_8x8_inference_flag;
+    info->num_ref_frames                         = sps->ref_frame_count;
+    info->mb_adaptive_frame_field_flag           = sps->mb_aff && !info->field_pic_flag;
+    info->constrained_intra_pred_flag            = pps->constrained_intra_pred;
+    info->weighted_pred_flag                     = pps->weighted_pred;
+    info->weighted_bipred_idc                    = pps->weighted_bipred_idc;
+    info->frame_mbs_only_flag                    = sps->frame_mbs_only_flag;
+    info->transform_8x8_mode_flag                = pps->transform_8x8_mode;
+    info->chroma_qp_index_offset                 = pps->chroma_qp_index_offset[0];
+    info->second_chroma_qp_index_offset          = pps->chroma_qp_index_offset[1];
+    info->pic_init_qp_minus26                    = pps->init_qp - 26;
+    info->num_ref_idx_l0_active_minus1           = pps->ref_count[0] - 1;
+    info->num_ref_idx_l1_active_minus1           = pps->ref_count[1] - 1;
+    info->log2_max_frame_num_minus4              = sps->log2_max_frame_num - 4;
+    info->pic_order_cnt_type                     = sps->poc_type;
+    info->log2_max_pic_order_cnt_lsb_minus4      = sps->poc_type ? 0 : sps->log2_max_poc_lsb - 4;
+    info->delta_pic_order_always_zero_flag       = sps->delta_pic_order_always_zero_flag;
+    info->direct_8x8_inference_flag              = sps->direct_8x8_inference_flag;
 #ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE
-    info2->qpprime_y_zero_transform_bypass_flag  = h->sps.transform_bypass;
-    info2->separate_colour_plane_flag            = h->sps.residual_color_transform_flag;
+    info2->qpprime_y_zero_transform_bypass_flag  = sps->transform_bypass;
+    info2->separate_colour_plane_flag            = sps->residual_color_transform_flag;
 #endif
-    info->entropy_coding_mode_flag               = h->pps.cabac;
-    info->pic_order_present_flag                 = h->pps.pic_order_present;
-    info->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
-    info->redundant_pic_cnt_present_flag         = h->pps.redundant_pic_cnt_present;
+    info->entropy_coding_mode_flag               = pps->cabac;
+    info->pic_order_present_flag                 = pps->pic_order_present;
+    info->deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present;
+    info->redundant_pic_cnt_present_flag         = pps->redundant_pic_cnt_present;
 
-    memcpy(info->scaling_lists_4x4, h->pps.scaling_matrix4,
+    memcpy(info->scaling_lists_4x4, pps->scaling_matrix4,
            sizeof(info->scaling_lists_4x4));
-    memcpy(info->scaling_lists_8x8[0], h->pps.scaling_matrix8[0],
+    memcpy(info->scaling_lists_8x8[0], pps->scaling_matrix8[0],
            sizeof(info->scaling_lists_8x8[0]));
-    memcpy(info->scaling_lists_8x8[1], h->pps.scaling_matrix8[3],
+    memcpy(info->scaling_lists_8x8[1], pps->scaling_matrix8[3],
            sizeof(info->scaling_lists_8x8[1]));
 
     vdpau_h264_set_reference_frames(avctx);
@@ -237,8 +239,8 @@ static int vdpau_h264_init(AVCodecContext *avctx)
         break;
 #endif
     case FF_PROFILE_H264_HIGH_10:
-        /* XXX: High 10 can be treated as High so long as only 8-bits per
-         * formats are supported. */
+        /* XXX: High 10 can be treated as High so long as only 8 bits per
+         * format are supported. */
         profile = VDP_DECODER_PROFILE_H264_HIGH;
         break;
 #ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE
diff --git a/libavcodec/vdpau_hevc.c b/libavcodec/vdpau_hevc.c
index 3c1dc5f..03c61dc 100644
--- a/libavcodec/vdpau_hevc.c
+++ b/libavcodec/vdpau_hevc.c
@@ -53,8 +53,8 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
     info->bit_depth_luma_minus8 = sps->bit_depth - 8;
     info->bit_depth_chroma_minus8 = sps->bit_depth - 8;
     info->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4;
-    /** Provides the value corresponding to the nuh_temporal_id of the frame
-        to be decoded. */
+    /* Provide the value corresponding to the nuh_temporal_id of the frame
+       to be decoded. */
     info->sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1;
     info->log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3;
     info->log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size;
@@ -63,34 +63,34 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
     info->max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter;
     info->max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra;
     info->scaling_list_enabled_flag = sps->scaling_list_enable_flag;
-    /** Scaling lists, in diagonal order, to be used for this frame. */
+    /* Scaling lists, in diagonal order, to be used for this frame. */
     for (size_t i = 0; i < 6; i++) {
         for (size_t j = 0; j < 16; j++) {
-            /** Scaling List for 4x4 quantization matrix,
-                indexed as ScalingList4x4[matrixId][i]. */
+            /* Scaling List for 4x4 quantization matrix,
+               indexed as ScalingList4x4[matrixId][i]. */
             uint8_t pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j];
             info->ScalingList4x4[i][j] = sl->sl[0][i][pos];
         }
         for (size_t j = 0; j < 64; j++) {
             uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
-            /** Scaling List for 8x8 quantization matrix,
-                indexed as ScalingList8x8[matrixId][i]. */
+            /* Scaling List for 8x8 quantization matrix,
+               indexed as ScalingList8x8[matrixId][i]. */
             info->ScalingList8x8[i][j] = sl->sl[1][i][pos];
-            /** Scaling List for 16x16 quantization matrix,
-                indexed as ScalingList16x16[matrixId][i]. */
+            /* Scaling List for 16x16 quantization matrix,
+               indexed as ScalingList16x16[matrixId][i]. */
             info->ScalingList16x16[i][j] = sl->sl[2][i][pos];
             if (i < 2) {
-                /** Scaling List for 32x32 quantization matrix,
-                    indexed as ScalingList32x32[matrixId][i]. */
+                /* Scaling List for 32x32 quantization matrix,
+                   indexed as ScalingList32x32[matrixId][i]. */
                 info->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos];
             }
         }
-        /** Scaling List DC Coefficients for 16x16,
-            indexed as ScalingListDCCoeff16x16[matrixId]. */
+        /* Scaling List DC Coefficients for 16x16,
+           indexed as ScalingListDCCoeff16x16[matrixId]. */
         info->ScalingListDCCoeff16x16[i] = sl->sl_dc[0][i];
         if (i < 2) {
-            /** Scaling List DC Coefficients for 32x32,
-                indexed as ScalingListDCCoeff32x32[matrixId]. */
+            /* Scaling List DC Coefficients for 32x32,
+               indexed as ScalingListDCCoeff32x32[matrixId]. */
             info->ScalingListDCCoeff32x32[i] = sl->sl_dc[1][i * 3];
         }
     }
@@ -98,32 +98,28 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
     info->sample_adaptive_offset_enabled_flag = sps->sao_enabled;
     info->pcm_enabled_flag = sps->pcm_enabled_flag;
     if (info->pcm_enabled_flag) {
-        /** Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
+        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
         info->pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1;
-        /** Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
+        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
         info->pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1;
-        /** Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
+        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
         info->log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3;
-        /** Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
+        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
         info->log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size;
-        /** Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
+        /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */
         info->pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag;
     }
-    /** Per spec, when zero, assume short_term_ref_pic_set_sps_flag
-        is also zero. */
+    /* Per spec, when zero, assume short_term_ref_pic_set_sps_flag
+       is also zero. */
     info->num_short_term_ref_pic_sets = sps->nb_st_rps;
     info->long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag;
-    /** Only needed if long_term_ref_pics_present_flag is set. Ignored
-        otherwise. */
+    /* Only needed if long_term_ref_pics_present_flag is set. Ignored
+       otherwise. */
     info->num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps;
     info->sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag;
     info->strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag;
-    /** @} */
 
-    /** \name HEVC Picture Parameter Set
-     *
-     * Copies of the HEVC Picture Parameter Set bitstream fields.
-     * @{ */
+    /* Copy the HEVC Picture Parameter Set bitstream fields. */
     info->dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag;
     info->output_flag_present_flag = pps->output_flag_present_flag;
     info->num_extra_slice_header_bits = pps->num_extra_slice_header_bits;
@@ -135,7 +131,7 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
     info->constrained_intra_pred_flag = pps->constrained_intra_pred_flag;
     info->transform_skip_enabled_flag = pps->transform_skip_enabled_flag;
     info->cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag;
-    /** Only needed if cu_qp_delta_enabled_flag is set. Ignored otherwise. */
+    /* Only needed if cu_qp_delta_enabled_flag is set. Ignored otherwise. */
     info->diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth;
     info->pps_cb_qp_offset = pps->cb_qp_offset;
     info->pps_cr_qp_offset = pps->cr_qp_offset;
@@ -146,58 +142,53 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
     info->tiles_enabled_flag = pps->tiles_enabled_flag;
     info->entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag;
     if (info->tiles_enabled_flag) {
-        /** Only valid if tiles_enabled_flag is set. Ignored otherwise. */
+        /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */
         info->num_tile_columns_minus1 = pps->num_tile_columns - 1;
-        /** Only valid if tiles_enabled_flag is set. Ignored otherwise. */
+        /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */
         info->num_tile_rows_minus1 = pps->num_tile_rows - 1;
-        /** Only valid if tiles_enabled_flag is set. Ignored otherwise. */
+        /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */
         info->uniform_spacing_flag = pps->uniform_spacing_flag;
-        /** Only need to set 0..num_tile_columns_minus1. The struct
-            definition reserves up to the maximum of 20. Invalid values are
-            ignored. */
+        /* Only need to set 0..num_tile_columns_minus1. The struct
+           definition reserves up to the maximum of 20. Invalid values are
+           ignored. */
         for (ssize_t i = 0; i < pps->num_tile_columns; i++) {
             info->column_width_minus1[i] = pps->column_width[i] - 1;
         }
-        /** Only need to set 0..num_tile_rows_minus1. The struct
-          definition reserves up to the maximum of 22. Invalid values are
-          ignored.*/
+        /* Only need to set 0..num_tile_rows_minus1. The struct
+           definition reserves up to the maximum of 22. Invalid values are
+           ignored.*/
         for (ssize_t i = 0; i < pps->num_tile_rows; i++) {
             info->row_height_minus1[i] = pps->row_height[i] - 1;
         }
-        /** Only needed if tiles_enabled_flag is set. Invalid values are
-          ignored. */
+        /* Only needed if tiles_enabled_flag is set. Invalid values are
+           ignored. */
         info->loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag;
     }
     info->pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag;
     info->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag;
-    /** Only valid if deblocking_filter_control_present_flag is set. Ignored
-        otherwise. */
+    /* Only valid if deblocking_filter_control_present_flag is set. Ignored
+       otherwise. */
     info->deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag;
-    /** Only valid if deblocking_filter_control_present_flag is set. Ignored
-        otherwise. */
+    /* Only valid if deblocking_filter_control_present_flag is set. Ignored
+       otherwise. */
     info->pps_deblocking_filter_disabled_flag = pps->disable_dbf;
-    /** Only valid if deblocking_filter_control_present_flag is set and
-        pps_deblocking_filter_disabled_flag is not set. Ignored otherwise.*/
+    /* Only valid if deblocking_filter_control_present_flag is set and
+       pps_deblocking_filter_disabled_flag is not set. Ignored otherwise.*/
     info->pps_beta_offset_div2 = pps->beta_offset / 2;
-    /** Only valid if deblocking_filter_control_present_flag is set and
-        pps_deblocking_filter_disabled_flag is not set. Ignored otherwise. */
+    /* Only valid if deblocking_filter_control_present_flag is set and
+       pps_deblocking_filter_disabled_flag is not set. Ignored otherwise. */
     info->pps_tc_offset_div2 = pps->tc_offset / 2;
     info->lists_modification_present_flag = pps->lists_modification_present_flag;
     info->log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2;
     info->slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag;
 
-    /** \name HEVC Slice Segment Header
-     *
-     * Copies of the HEVC Slice Segment Header bitstream fields and calculated
-     * values detailed in the specification.
-     * @{ */
-    /** Set to 1 if nal_unit_type is equal to IDR_W_RADL or IDR_N_LP.
-        Set to zero otherwise. */
+    /* Set to 1 if nal_unit_type is equal to IDR_W_RADL or IDR_N_LP.
+       Set to zero otherwise. */
     info->IDRPicFlag = IS_IDR(h);
-    /** Set to 1 if nal_unit_type in the range of BLA_W_LP to
-        RSV_IRAP_VCL23, inclusive. Set to zero otherwise.*/
+    /* Set to 1 if nal_unit_type in the range of BLA_W_LP to
+       RSV_IRAP_VCL23, inclusive. Set to zero otherwise.*/
     info->RAPPicFlag = IS_IRAP(h);
-    /** See section 7.4.7.1 of the specification. */
+    /* See section 7.4.7.1 of the specification. */
     info->CurrRpsIdx = sps->nb_st_rps;
     if (sh->short_term_ref_pic_set_sps_flag == 1) {
         for (size_t i = 0; i < sps->nb_st_rps; i++) {
@@ -207,35 +198,33 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
             }
         }
     }
-    /** See section 7.4.7.2 of the specification. */
+    /* See section 7.4.7.2 of the specification. */
     info->NumPocTotalCurr = ff_hevc_frame_nb_refs(h);
     if (sh->short_term_ref_pic_set_sps_flag == 0 && sh->short_term_rps) {
-        /** Corresponds to specification field, NumDeltaPocs[RefRpsIdx].
-            Only applicable when short_term_ref_pic_set_sps_flag == 0.
-            Implementations will ignore this value in other cases. See 7.4.8. */
+        /* Corresponds to specification field, NumDeltaPocs[RefRpsIdx].
+           Only applicable when short_term_ref_pic_set_sps_flag == 0.
+           Implementations will ignore this value in other cases. See 7.4.8. */
         info->NumDeltaPocsOfRefRpsIdx = sh->short_term_rps->rps_idx_num_delta_pocs;
     }
-    /** Section 7.6.3.1 of the H.265/HEVC Specification defines the syntax of
-        the slice_segment_header. This header contains information that
-        some VDPAU implementations may choose to skip. The VDPAU API
-        requires client applications to track the number of bits used in the
-        slice header for structures associated with short term and long term
-        reference pictures. First, VDPAU requires the number of bits used by
-        the short_term_ref_pic_set array in the slice_segment_header. */
+    /* Section 7.6.3.1 of the H.265/HEVC Specification defines the syntax of
+       the slice_segment_header. This header contains information that
+       some VDPAU implementations may choose to skip. The VDPAU API
+       requires client applications to track the number of bits used in the
+       slice header for structures associated with short term and long term
+       reference pictures. First, VDPAU requires the number of bits used by
+       the short_term_ref_pic_set array in the slice_segment_header. */
     info->NumShortTermPictureSliceHeaderBits = sh->short_term_ref_pic_set_size;
-    /** Second, VDPAU requires the number of bits used for long term reference
-        pictures in the slice_segment_header. This is equal to the number
-        of bits used for the contents of the block beginning with
-        "if(long_term_ref_pics_present_flag)". */
+    /* Second, VDPAU requires the number of bits used for long term reference
+       pictures in the slice_segment_header. This is equal to the number
+       of bits used for the contents of the block beginning with
+       "if(long_term_ref_pics_present_flag)". */
     info->NumLongTermPictureSliceHeaderBits = sh->long_term_ref_pic_set_size;
-    /** @} */
 
-    /** Slice Decoding Process - Picture Order Count */
-    /** The value of PicOrderCntVal of the picture in the access unit
-        containing the SEI message. The picture being decoded. */
+    /* The value of PicOrderCntVal of the picture in the access unit
+       containing the SEI message. The picture being decoded. */
     info->CurrPicOrderCntVal = h->poc;
 
-    /** Slice Decoding Process - Reference Picture Sets */
+    /* Slice Decoding Process - Reference Picture Sets */
     for (size_t i = 0; i < 16; i++) {
         info->RefPics[i] = VDP_INVALID_HANDLE;
         info->PicOrderCntVal[i] = 0;
@@ -251,15 +240,15 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
                      "This frame may not be decoded correctly.\n");
                 break;
             }
-            /** Array of video reference surfaces.
-                Set any unused positions to VDP_INVALID_HANDLE. */
+            /* Array of video reference surfaces.
+               Set any unused positions to VDP_INVALID_HANDLE. */
             info->RefPics[j] = ff_vdpau_get_surface_id(frame->frame);
-            /** Array of picture order counts. These correspond to positions
-                in the RefPics array. */
+            /* Array of picture order counts. These correspond to positions
+               in the RefPics array. */
             info->PicOrderCntVal[j] = frame->poc;
-            /** Array used to specify whether a particular RefPic is
-                a long term reference. A value of "1" indicates a long-term
-                reference. */
+            /* Array used to specify whether a particular RefPic is
+               a long term reference. A value of "1" indicates a long-term
+               reference. */
             // XXX: Setting this caused glitches in the nvidia implementation
             // Always setting it to zero, produces correct results
             //info->IsLongTerm[j] = frame->flags & HEVC_FRAME_FLAG_LONG_REF;
@@ -267,8 +256,8 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
             j++;
         }
     }
-    /** Copy of specification field, see Section 8.3.2 of the
-        H.265/HEVC Specification. */
+    /* Copy of specification field, see Section 8.3.2 of the
+       H.265/HEVC Specification. */
     info->NumPocStCurrBefore = h->rps[ST_CURR_BEF].nb_refs;
     if (info->NumPocStCurrBefore > 8) {
         av_log(avctx, AV_LOG_WARNING,
@@ -276,8 +265,8 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
              "This frame may not be decoded correctly.\n");
         info->NumPocStCurrBefore = 8;
     }
-    /** Copy of specification field, see Section 8.3.2 of the
-        H.265/HEVC Specification. */
+    /* Copy of specification field, see Section 8.3.2 of the
+       H.265/HEVC Specification. */
     info->NumPocStCurrAfter = h->rps[ST_CURR_AFT].nb_refs;
     if (info->NumPocStCurrAfter > 8) {
         av_log(avctx, AV_LOG_WARNING,
@@ -285,8 +274,8 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
              "This frame may not be decoded correctly.\n");
         info->NumPocStCurrAfter = 8;
     }
-    /** Copy of specification field, see Section 8.3.2 of the
-        H.265/HEVC Specification. */
+    /* Copy of specification field, see Section 8.3.2 of the
+       H.265/HEVC Specification. */
     info->NumPocLtCurr = h->rps[LT_CURR].nb_refs;
     if (info->NumPocLtCurr > 8) {
         av_log(avctx, AV_LOG_WARNING,
@@ -294,8 +283,8 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
              "This frame may not be decoded correctly.\n");
         info->NumPocLtCurr = 8;
     }
-    /** Reference Picture Set list, one of the short-term RPS. These
-        correspond to positions in the RefPics array. */
+    /* Reference Picture Set list, one of the short-term RPS. These
+       correspond to positions in the RefPics array. */
     for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) {
         HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i];
         if (frame) {
@@ -317,8 +306,8 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
             av_log(avctx, AV_LOG_WARNING, "missing STR Before frame: %zd\n", i);
         }
     }
-    /** Reference Picture Set list, one of the short-term RPS. These
-        correspond to positions in the RefPics array. */
+    /* Reference Picture Set list, one of the short-term RPS. These
+       correspond to positions in the RefPics array. */
     for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) {
         HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i];
         if (frame) {
@@ -340,8 +329,8 @@ static int vdpau_hevc_start_frame(AVCodecContext *avctx,
             av_log(avctx, AV_LOG_WARNING, "missing STR After frame: %zd\n", i);
         }
     }
-    /** Reference Picture Set list, one of the long-term RPS. These
-        correspond to positions in the RefPics array. */
+    /* Reference Picture Set list, one of the long-term RPS. These
+       correspond to positions in the RefPics array. */
     for (ssize_t i = 0, j = 0; i < h->rps[LT_CURR].nb_refs; i++) {
         HEVCFrame *frame = h->rps[LT_CURR].ref[i];
         if (frame) {
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 37a35e0..4f6423b 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -29,8 +28,8 @@
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR  57
-#define LIBAVCODEC_VERSION_MINOR  24
-#define LIBAVCODEC_VERSION_MICRO 102
+#define LIBAVCODEC_VERSION_MINOR  48
+#define LIBAVCODEC_VERSION_MICRO 101
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
@@ -212,5 +211,20 @@
 #ifndef FF_API_PRIVATE_OPT
 #define FF_API_PRIVATE_OPT      (LIBAVCODEC_VERSION_MAJOR < 59)
 #endif
+#ifndef FF_API_ASS_TIMING
+#define FF_API_ASS_TIMING       (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_OLD_BSF
+#define FF_API_OLD_BSF          (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_COPY_CONTEXT
+#define FF_API_COPY_CONTEXT     (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_GET_CONTEXT_DEFAULTS
+#define FF_API_GET_CONTEXT_DEFAULTS (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
+#ifndef FF_API_NVENC_OLD_NAME
+#define FF_API_NVENC_OLD_NAME    (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
 
 #endif /* AVCODEC_VERSION_H */
diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c
index 2f4d531..c2c621d 100644
--- a/libavcodec/videotoolbox.c
+++ b/libavcodec/videotoolbox.c
@@ -84,7 +84,7 @@ CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
     H264Context *h     = avctx->priv_data;
     CFDataRef data = NULL;
     uint8_t *p;
-    int vt_extradata_size = 6 + 3 + h->sps.data_size + 4 + h->pps.data_size;
+    int vt_extradata_size = 6 + 2 + h->ps.sps->data_size + 3 + h->ps.pps->data_size;
     uint8_t *vt_extradata = av_malloc(vt_extradata_size);
     if (!vt_extradata)
         return NULL;
@@ -92,21 +92,19 @@ CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
     p = vt_extradata;
 
     AV_W8(p + 0, 1); /* version */
-    AV_W8(p + 1, h->sps.data[0]); /* profile */
-    AV_W8(p + 2, h->sps.data[1]); /* profile compat */
-    AV_W8(p + 3, h->sps.data[2]); /* level */
+    AV_W8(p + 1, h->ps.sps->data[1]); /* profile */
+    AV_W8(p + 2, h->ps.sps->data[2]); /* profile compat */
+    AV_W8(p + 3, h->ps.sps->data[3]); /* level */
     AV_W8(p + 4, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 3 (11) */
     AV_W8(p + 5, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
-    AV_WB16(p + 6, h->sps.data_size + 1);
-    AV_W8(p + 8, NAL_SPS | (3 << 5)); // NAL unit header
-    memcpy(p + 9, h->sps.data, h->sps.data_size);
-    p += 9 + h->sps.data_size;
+    AV_WB16(p + 6, h->ps.sps->data_size);
+    memcpy(p + 8, h->ps.sps->data, h->ps.sps->data_size);
+    p += 8 + h->ps.sps->data_size;
     AV_W8(p + 0, 1); /* number of pps */
-    AV_WB16(p + 1, h->pps.data_size + 1);
-    AV_W8(p + 3, NAL_PPS | (3 << 5)); // NAL unit header
-    memcpy(p + 4, h->pps.data, h->pps.data_size);
+    AV_WB16(p + 1, h->ps.pps->data_size);
+    memcpy(p + 3, h->ps.pps->data, h->ps.pps->data_size);
 
-    p += 4 + h->pps.data_size;
+    p += 3 + h->ps.pps->data_size;
     av_assert0(p - vt_extradata == vt_extradata_size);
 
     data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
@@ -407,7 +405,7 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec
                                                           AVCodecContext *avctx)
 {
     CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
-                                                                   1,
+                                                                   0,
                                                                    &kCFTypeDictionaryKeyCallBacks,
                                                                    &kCFTypeDictionaryValueCallBacks);
 
@@ -597,8 +595,10 @@ static void videotoolbox_default_free(AVCodecContext *avctx)
         if (videotoolbox->cm_fmt_desc)
             CFRelease(videotoolbox->cm_fmt_desc);
 
-        if (videotoolbox->session)
+        if (videotoolbox->session) {
             VTDecompressionSessionInvalidate(videotoolbox->session);
+            CFRelease(videotoolbox->session);
+        }
     }
 }
 
diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
new file mode 100644
index 0000000..4345ca3
--- /dev/null
+++ b/libavcodec/videotoolboxenc.c
@@ -0,0 +1,2003 @@
+/*
+ * copyright (c) 2015 Rick Kern <kernrj at gmail.com>
+ *
+ * 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 <VideoToolbox/VideoToolbox.h>
+#include <CoreVideo/CoreVideo.h>
+#include <CoreMedia/CoreMedia.h>
+#include <TargetConditionals.h>
+#include <Availability.h>
+#include "avcodec.h"
+#include "libavutil/opt.h"
+#include "libavutil/avassert.h"
+#include "libavutil/atomic.h"
+#include "libavutil/avstring.h"
+#include "libavcodec/avcodec.h"
+#include "libavutil/pixdesc.h"
+#include "internal.h"
+#include <pthread.h>
+
+#if !CONFIG_VT_BT2020
+# define kCVImageBufferColorPrimaries_ITU_R_2020   CFSTR("ITU_R_2020")
+# define kCVImageBufferTransferFunction_ITU_R_2020 CFSTR("ITU_R_2020")
+# define kCVImageBufferYCbCrMatrix_ITU_R_2020      CFSTR("ITU_R_2020")
+#endif
+
+typedef enum VT_H264Profile {
+    H264_PROF_AUTO,
+    H264_PROF_BASELINE,
+    H264_PROF_MAIN,
+    H264_PROF_HIGH,
+    H264_PROF_COUNT
+} VT_H264Profile;
+
+typedef enum VTH264Entropy{
+    VT_ENTROPY_NOT_SET,
+    VT_CAVLC,
+    VT_CABAC
+} VTH264Entropy;
+
+static const uint8_t start_code[] = { 0, 0, 0, 1 };
+
+typedef struct BufNode {
+    CMSampleBufferRef cm_buffer;
+    struct BufNode* next;
+    int error;
+} BufNode;
+
+typedef struct VTEncContext {
+    AVClass *class;
+    VTCompressionSessionRef session;
+    CFStringRef ycbcr_matrix;
+    CFStringRef color_primaries;
+    CFStringRef transfer_function;
+
+    pthread_mutex_t lock;
+    pthread_cond_t  cv_sample_sent;
+
+    int async_error;
+
+    BufNode *q_head;
+    BufNode *q_tail;
+
+    int64_t frame_ct_out;
+    int64_t frame_ct_in;
+
+    int64_t first_pts;
+    int64_t dts_delta;
+
+    int64_t profile;
+    int64_t level;
+    int64_t entropy;
+    int64_t realtime;
+    int64_t frames_before;
+    int64_t frames_after;
+
+    int64_t allow_sw;
+
+    bool flushing;
+    bool has_b_frames;
+    bool warned_color_range;
+} VTEncContext;
+
+static int vtenc_populate_extradata(AVCodecContext   *avctx,
+                                    CMVideoCodecType codec_type,
+                                    CFStringRef      profile_level,
+                                    CFNumberRef      gamma_level,
+                                    CFDictionaryRef  enc_info,
+                                    CFDictionaryRef  pixel_buffer_info);
+
+/**
+ * NULL-safe release of *refPtr, and sets value to NULL.
+ */
+static void vt_release_num(CFNumberRef* refPtr){
+    if (!*refPtr) {
+        return;
+    }
+
+    CFRelease(*refPtr);
+    *refPtr = NULL;
+}
+
+static void set_async_error(VTEncContext *vtctx, int err)
+{
+    BufNode *info;
+
+    pthread_mutex_lock(&vtctx->lock);
+
+    vtctx->async_error = err;
+
+    info = vtctx->q_head;
+    vtctx->q_head = vtctx->q_tail = NULL;
+
+    while (info) {
+        BufNode *next = info->next;
+        CFRelease(info->cm_buffer);
+        av_free(info);
+        info = next;
+    }
+
+    pthread_mutex_unlock(&vtctx->lock);
+}
+
+static int vtenc_q_pop(VTEncContext *vtctx, bool wait, CMSampleBufferRef *buf)
+{
+    BufNode *info;
+
+    pthread_mutex_lock(&vtctx->lock);
+
+    if (vtctx->async_error) {
+        pthread_mutex_unlock(&vtctx->lock);
+        return vtctx->async_error;
+    }
+
+    if (vtctx->flushing && vtctx->frame_ct_in == vtctx->frame_ct_out) {
+        *buf = NULL;
+
+        pthread_mutex_unlock(&vtctx->lock);
+        return 0;
+    }
+
+    while (!vtctx->q_head && !vtctx->async_error && wait) {
+        pthread_cond_wait(&vtctx->cv_sample_sent, &vtctx->lock);
+    }
+
+    if (!vtctx->q_head) {
+        pthread_mutex_unlock(&vtctx->lock);
+        *buf = NULL;
+        return 0;
+    }
+
+    info = vtctx->q_head;
+    vtctx->q_head = vtctx->q_head->next;
+    if (!vtctx->q_head) {
+        vtctx->q_tail = NULL;
+    }
+
+    pthread_mutex_unlock(&vtctx->lock);
+
+    *buf = info->cm_buffer;
+    av_free(info);
+
+    vtctx->frame_ct_out++;
+
+    return 0;
+}
+
+static void vtenc_q_push(VTEncContext *vtctx, CMSampleBufferRef buffer)
+{
+    BufNode *info = av_malloc(sizeof(BufNode));
+    if (!info) {
+        set_async_error(vtctx, AVERROR(ENOMEM));
+        return;
+    }
+
+    CFRetain(buffer);
+    info->cm_buffer = buffer;
+    info->next = NULL;
+
+    pthread_mutex_lock(&vtctx->lock);
+    pthread_cond_signal(&vtctx->cv_sample_sent);
+
+    if (!vtctx->q_head) {
+        vtctx->q_head = info;
+    } else {
+        vtctx->q_tail->next = info;
+    }
+
+    vtctx->q_tail = info;
+
+    pthread_mutex_unlock(&vtctx->lock);
+}
+
+static int count_nalus(size_t length_code_size,
+                       CMSampleBufferRef sample_buffer,
+                       int *count)
+{
+    size_t offset = 0;
+    int status;
+    int nalu_ct = 0;
+    uint8_t size_buf[4];
+    size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
+    CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sample_buffer);
+
+    if (length_code_size > 4)
+        return AVERROR_INVALIDDATA;
+
+    while (offset < src_size) {
+        size_t curr_src_len;
+        size_t box_len = 0;
+        size_t i;
+
+        status = CMBlockBufferCopyDataBytes(block,
+                                            offset,
+                                            length_code_size,
+                                            size_buf);
+
+        for (i = 0; i < length_code_size; i++) {
+            box_len <<= 8;
+            box_len |= size_buf[i];
+        }
+
+        curr_src_len = box_len + length_code_size;
+        offset += curr_src_len;
+
+        nalu_ct++;
+    }
+
+    *count = nalu_ct;
+    return 0;
+}
+
+static CMVideoCodecType get_cm_codec_type(enum AVCodecID id)
+{
+    switch (id) {
+    case AV_CODEC_ID_H264: return kCMVideoCodecType_H264;
+    default:               return 0;
+    }
+}
+
+/**
+ * Get the parameter sets from a CMSampleBufferRef.
+ * @param dst If *dst isn't NULL, the parameters are copied into existing
+ *            memory. *dst_size must be set accordingly when *dst != NULL.
+ *            If *dst is NULL, it will be allocated.
+ *            In all cases, *dst_size is set to the number of bytes used starting
+ *            at *dst.
+ */
+static int get_params_size(
+    AVCodecContext              *avctx,
+    CMVideoFormatDescriptionRef vid_fmt,
+    size_t                      *size)
+{
+    size_t total_size = 0;
+    size_t ps_count;
+    int is_count_bad = 0;
+    size_t i;
+    int status;
+    status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
+                                                                0,
+                                                                NULL,
+                                                                NULL,
+                                                                &ps_count,
+                                                                NULL);
+    if (status) {
+        is_count_bad = 1;
+        ps_count     = 0;
+        status       = 0;
+    }
+
+    for (i = 0; i < ps_count || is_count_bad; i++) {
+        const uint8_t *ps;
+        size_t ps_size;
+        status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
+                                                                    i,
+                                                                    &ps,
+                                                                    &ps_size,
+                                                                    NULL,
+                                                                    NULL);
+        if (status) {
+            /*
+             * When ps_count is invalid, status != 0 ends the loop normally
+             * unless we didn't get any parameter sets.
+             */
+            if (i > 0 && is_count_bad) status = 0;
+
+            break;
+        }
+
+        total_size += ps_size + sizeof(start_code);
+    }
+
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error getting parameter set sizes: %d\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
+    *size = total_size;
+    return 0;
+}
+
+static int copy_param_sets(
+    AVCodecContext              *avctx,
+    CMVideoFormatDescriptionRef vid_fmt,
+    uint8_t                     *dst,
+    size_t                      dst_size)
+{
+    size_t ps_count;
+    int is_count_bad = 0;
+    int status;
+    size_t offset = 0;
+    size_t i;
+
+    status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
+                                                                0,
+                                                                NULL,
+                                                                NULL,
+                                                                &ps_count,
+                                                                NULL);
+    if (status) {
+        is_count_bad = 1;
+        ps_count     = 0;
+        status       = 0;
+    }
+
+
+    for (i = 0; i < ps_count || is_count_bad; i++) {
+        const uint8_t *ps;
+        size_t ps_size;
+        size_t next_offset;
+
+        status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
+                                                                    i,
+                                                                    &ps,
+                                                                    &ps_size,
+                                                                    NULL,
+                                                                    NULL);
+        if (status) {
+            if (i > 0 && is_count_bad) status = 0;
+
+            break;
+        }
+
+        next_offset = offset + sizeof(start_code) + ps_size;
+        if (dst_size < next_offset) {
+            av_log(avctx, AV_LOG_ERROR, "Error: buffer too small for parameter sets.\n");
+            return AVERROR_BUFFER_TOO_SMALL;
+        }
+
+        memcpy(dst + offset, start_code, sizeof(start_code));
+        offset += sizeof(start_code);
+
+        memcpy(dst + offset, ps, ps_size);
+        offset = next_offset;
+    }
+
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error getting parameter set data: %d\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static int set_extradata(AVCodecContext *avctx, CMSampleBufferRef sample_buffer)
+{
+    CMVideoFormatDescriptionRef vid_fmt;
+    size_t total_size;
+    int status;
+
+    vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
+    if (!vid_fmt) {
+        av_log(avctx, AV_LOG_ERROR, "No video format.\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    status = get_params_size(avctx, vid_fmt, &total_size);
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Could not get parameter sets.\n");
+        return status;
+    }
+
+    avctx->extradata = av_mallocz(total_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!avctx->extradata) {
+        return AVERROR(ENOMEM);
+    }
+    avctx->extradata_size = total_size;
+
+    status = copy_param_sets(avctx, vid_fmt, avctx->extradata, total_size);
+
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Could not copy param sets.\n");
+        return status;
+    }
+
+    return 0;
+}
+
+static void vtenc_output_callback(
+    void *ctx,
+    void *sourceFrameCtx,
+    OSStatus status,
+    VTEncodeInfoFlags flags,
+    CMSampleBufferRef sample_buffer)
+{
+    AVCodecContext *avctx = ctx;
+    VTEncContext   *vtctx = avctx->priv_data;
+
+    if (vtctx->async_error) {
+        if(sample_buffer) CFRelease(sample_buffer);
+        return;
+    }
+
+    if (status || !sample_buffer) {
+        av_log(avctx, AV_LOG_ERROR, "Error encoding frame: %d\n", (int)status);
+        set_async_error(vtctx, AVERROR_EXTERNAL);
+        return;
+    }
+
+    if (!avctx->extradata && (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
+        int set_status = set_extradata(avctx, sample_buffer);
+        if (set_status) {
+            set_async_error(vtctx, set_status);
+            return;
+        }
+    }
+
+    vtenc_q_push(vtctx, sample_buffer);
+}
+
+static int get_length_code_size(
+    AVCodecContext    *avctx,
+    CMSampleBufferRef sample_buffer,
+    size_t            *size)
+{
+    CMVideoFormatDescriptionRef vid_fmt;
+    int isize;
+    int status;
+
+    vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
+    if (!vid_fmt) {
+        av_log(avctx, AV_LOG_ERROR, "Error getting buffer format description.\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    status = CMVideoFormatDescriptionGetH264ParameterSetAtIndex(vid_fmt,
+                                                                0,
+                                                                NULL,
+                                                                NULL,
+                                                                NULL,
+                                                                &isize);
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error getting length code size: %d\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
+    *size = isize;
+    return 0;
+}
+
+/*
+ * Returns true on success.
+ *
+ * If profile_level_val is NULL and this method returns true, don't specify the
+ * profile/level to the encoder.
+ */
+static bool get_vt_profile_level(AVCodecContext *avctx,
+                                 CFStringRef    *profile_level_val)
+{
+    VTEncContext *vtctx = avctx->priv_data;
+    int64_t profile = vtctx->profile;
+
+    if (profile == H264_PROF_AUTO && vtctx->level) {
+        //Need to pick a profile if level is not auto-selected.
+        profile = vtctx->has_b_frames ? H264_PROF_MAIN : H264_PROF_BASELINE;
+    }
+
+    *profile_level_val = NULL;
+
+    switch (profile) {
+        case H264_PROF_AUTO:
+            return true;
+
+        case H264_PROF_BASELINE:
+            switch (vtctx->level) {
+                case  0: *profile_level_val = kVTProfileLevel_H264_Baseline_AutoLevel; break;
+                case 13: *profile_level_val = kVTProfileLevel_H264_Baseline_1_3;       break;
+                case 30: *profile_level_val = kVTProfileLevel_H264_Baseline_3_0;       break;
+                case 31: *profile_level_val = kVTProfileLevel_H264_Baseline_3_1;       break;
+                case 32: *profile_level_val = kVTProfileLevel_H264_Baseline_3_2;       break;
+                case 40: *profile_level_val = kVTProfileLevel_H264_Baseline_4_0;       break;
+                case 41: *profile_level_val = kVTProfileLevel_H264_Baseline_4_1;       break;
+                case 42: *profile_level_val = kVTProfileLevel_H264_Baseline_4_2;       break;
+                case 50: *profile_level_val = kVTProfileLevel_H264_Baseline_5_0;       break;
+                case 51: *profile_level_val = kVTProfileLevel_H264_Baseline_5_1;       break;
+                case 52: *profile_level_val = kVTProfileLevel_H264_Baseline_5_2;       break;
+            }
+            break;
+
+        case H264_PROF_MAIN:
+            switch (vtctx->level) {
+                case  0: *profile_level_val = kVTProfileLevel_H264_Main_AutoLevel; break;
+                case 30: *profile_level_val = kVTProfileLevel_H264_Main_3_0;       break;
+                case 31: *profile_level_val = kVTProfileLevel_H264_Main_3_1;       break;
+                case 32: *profile_level_val = kVTProfileLevel_H264_Main_3_2;       break;
+                case 40: *profile_level_val = kVTProfileLevel_H264_Main_4_0;       break;
+                case 41: *profile_level_val = kVTProfileLevel_H264_Main_4_1;       break;
+                case 42: *profile_level_val = kVTProfileLevel_H264_Main_4_2;       break;
+                case 50: *profile_level_val = kVTProfileLevel_H264_Main_5_0;       break;
+                case 51: *profile_level_val = kVTProfileLevel_H264_Main_5_1;       break;
+                case 52: *profile_level_val = kVTProfileLevel_H264_Main_5_2;       break;
+            }
+            break;
+
+        case H264_PROF_HIGH:
+            switch (vtctx->level) {
+                case  0: *profile_level_val = kVTProfileLevel_H264_High_AutoLevel; break;
+                case 30: *profile_level_val = kVTProfileLevel_H264_High_3_0;       break;
+                case 31: *profile_level_val = kVTProfileLevel_H264_High_3_1;       break;
+                case 32: *profile_level_val = kVTProfileLevel_H264_High_3_2;       break;
+                case 40: *profile_level_val = kVTProfileLevel_H264_High_4_0;       break;
+                case 41: *profile_level_val = kVTProfileLevel_H264_High_4_1;       break;
+                case 42: *profile_level_val = kVTProfileLevel_H264_High_4_2;       break;
+                case 50: *profile_level_val = kVTProfileLevel_H264_High_5_0;       break;
+                case 51: *profile_level_val = kVTProfileLevel_H264_High_5_1;       break;
+                case 52: *profile_level_val = kVTProfileLevel_H264_High_5_2;       break;
+            }
+            break;
+    }
+
+    if (!*profile_level_val) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid Profile/Level.\n");
+        return false;
+    }
+
+    return true;
+}
+
+static int get_cv_pixel_format(AVCodecContext* avctx,
+                               enum AVPixelFormat fmt,
+                               enum AVColorRange range,
+                               int* av_pixel_format,
+                               int* range_guessed)
+{
+    if (range_guessed) *range_guessed = range != AVCOL_RANGE_MPEG &&
+                                        range != AVCOL_RANGE_JPEG;
+
+    //MPEG range is used when no range is set
+    if (fmt == AV_PIX_FMT_NV12) {
+        *av_pixel_format = range == AVCOL_RANGE_JPEG ?
+                                        kCVPixelFormatType_420YpCbCr8BiPlanarFullRange :
+                                        kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
+    } else if (fmt == AV_PIX_FMT_YUV420P) {
+        *av_pixel_format = range == AVCOL_RANGE_JPEG ?
+                                        kCVPixelFormatType_420YpCbCr8PlanarFullRange :
+                                        kCVPixelFormatType_420YpCbCr8Planar;
+    } else {
+        return AVERROR(EINVAL);
+    }
+
+    return 0;
+}
+
+static void add_color_attr(AVCodecContext *avctx, CFMutableDictionaryRef dict) {
+    VTEncContext *vtctx = avctx->priv_data;
+
+    if (vtctx->color_primaries) {
+        CFDictionarySetValue(dict,
+                             kCVImageBufferColorPrimariesKey,
+                             vtctx->color_primaries);
+    }
+
+    if (vtctx->transfer_function) {
+        CFDictionarySetValue(dict,
+                             kCVImageBufferTransferFunctionKey,
+                             vtctx->transfer_function);
+    }
+
+    if (vtctx->ycbcr_matrix) {
+        CFDictionarySetValue(dict,
+                             kCVImageBufferYCbCrMatrixKey,
+                             vtctx->ycbcr_matrix);
+    }
+}
+
+static int create_cv_pixel_buffer_info(AVCodecContext* avctx,
+                                       CFMutableDictionaryRef* dict)
+{
+    CFNumberRef cv_color_format_num = NULL;
+    CFNumberRef width_num = NULL;
+    CFNumberRef height_num = NULL;
+    CFMutableDictionaryRef pixel_buffer_info = NULL;
+    int cv_color_format;
+    int status = get_cv_pixel_format(avctx,
+                                     avctx->pix_fmt,
+                                     avctx->color_range,
+                                     &cv_color_format,
+                                     NULL);
+    if (status) return status;
+
+    pixel_buffer_info = CFDictionaryCreateMutable(
+                            kCFAllocatorDefault,
+                            20,
+                            &kCFCopyStringDictionaryKeyCallBacks,
+                            &kCFTypeDictionaryValueCallBacks);
+
+    if (!pixel_buffer_info) goto pbinfo_nomem;
+
+    cv_color_format_num = CFNumberCreate(kCFAllocatorDefault,
+                                         kCFNumberSInt32Type,
+                                         &cv_color_format);
+    if (!cv_color_format_num) goto pbinfo_nomem;
+
+    CFDictionarySetValue(pixel_buffer_info,
+                         kCVPixelBufferPixelFormatTypeKey,
+                         cv_color_format_num);
+    vt_release_num(&cv_color_format_num);
+
+    width_num = CFNumberCreate(kCFAllocatorDefault,
+                               kCFNumberSInt32Type,
+                               &avctx->width);
+    if (!width_num) return AVERROR(ENOMEM);
+
+    CFDictionarySetValue(pixel_buffer_info,
+                         kCVPixelBufferWidthKey,
+                         width_num);
+    vt_release_num(&width_num);
+
+    height_num = CFNumberCreate(kCFAllocatorDefault,
+                                kCFNumberSInt32Type,
+                                &avctx->height);
+    if (!height_num) goto pbinfo_nomem;
+
+    CFDictionarySetValue(pixel_buffer_info,
+                         kCVPixelBufferHeightKey,
+                         height_num);
+    vt_release_num(&height_num);
+
+    add_color_attr(avctx, pixel_buffer_info);
+
+    *dict = pixel_buffer_info;
+    return 0;
+
+pbinfo_nomem:
+    vt_release_num(&cv_color_format_num);
+    vt_release_num(&width_num);
+    vt_release_num(&height_num);
+    if (pixel_buffer_info) CFRelease(pixel_buffer_info);
+
+    return AVERROR(ENOMEM);
+}
+
+static int get_cv_color_primaries(AVCodecContext *avctx,
+                                  CFStringRef *primaries)
+{
+    enum AVColorPrimaries pri = avctx->color_primaries;
+    switch (pri) {
+        case AVCOL_PRI_UNSPECIFIED:
+            *primaries = NULL;
+            break;
+
+        case AVCOL_PRI_BT709:
+            *primaries = kCVImageBufferColorPrimaries_ITU_R_709_2;
+            break;
+
+        case AVCOL_PRI_BT2020:
+            *primaries = kCVImageBufferColorPrimaries_ITU_R_2020;
+            break;
+
+        default:
+            av_log(avctx, AV_LOG_ERROR, "Color primaries %s is not supported.\n", av_color_primaries_name(pri));
+            *primaries = NULL;
+            return -1;
+    }
+
+    return 0;
+}
+
+static int get_cv_transfer_function(AVCodecContext *avctx,
+                                    CFStringRef *transfer_fnc,
+                                    CFNumberRef *gamma_level)
+{
+    enum AVColorTransferCharacteristic trc = avctx->color_trc;
+    Float32 gamma;
+    *gamma_level = NULL;
+
+    switch (trc) {
+        case AVCOL_TRC_UNSPECIFIED:
+            *transfer_fnc = NULL;
+            break;
+
+        case AVCOL_TRC_BT709:
+            *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_709_2;
+            break;
+
+        case AVCOL_TRC_SMPTE240M:
+            *transfer_fnc = kCVImageBufferTransferFunction_SMPTE_240M_1995;
+            break;
+
+        case AVCOL_TRC_GAMMA22:
+            gamma = 2.2;
+            *transfer_fnc = kCVImageBufferTransferFunction_UseGamma;
+            *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma);
+            break;
+
+        case AVCOL_TRC_GAMMA28:
+            gamma = 2.8;
+            *transfer_fnc = kCVImageBufferTransferFunction_UseGamma;
+            *gamma_level = CFNumberCreate(NULL, kCFNumberFloat32Type, &gamma);
+            break;
+
+        case AVCOL_TRC_BT2020_10:
+        case AVCOL_TRC_BT2020_12:
+            *transfer_fnc = kCVImageBufferTransferFunction_ITU_R_2020;
+            break;
+
+        default:
+            av_log(avctx, AV_LOG_ERROR, "Transfer function %s is not supported.\n", av_color_transfer_name(trc));
+            return -1;
+    }
+
+    return 0;
+}
+
+static int get_cv_ycbcr_matrix(AVCodecContext *avctx, CFStringRef *matrix) {
+    switch(avctx->colorspace) {
+        case AVCOL_SPC_BT709:
+            *matrix = kCVImageBufferYCbCrMatrix_ITU_R_709_2;
+            break;
+
+        case AVCOL_SPC_UNSPECIFIED:
+            *matrix = NULL;
+            break;
+
+        case AVCOL_SPC_BT470BG:
+        case AVCOL_SPC_SMPTE170M:
+            *matrix = kCVImageBufferYCbCrMatrix_ITU_R_601_4;
+            break;
+
+        case AVCOL_SPC_SMPTE240M:
+            *matrix = kCVImageBufferYCbCrMatrix_SMPTE_240M_1995;
+            break;
+
+        case AVCOL_SPC_BT2020_NCL:
+            *matrix = kCVImageBufferYCbCrMatrix_ITU_R_2020;
+            break;
+
+        default:
+            av_log(avctx, AV_LOG_ERROR, "Color space %s is not supported.\n", av_color_space_name(avctx->colorspace));
+            return -1;
+    }
+
+    return 0;
+}
+
+static int vtenc_create_encoder(AVCodecContext   *avctx,
+                                CMVideoCodecType codec_type,
+                                CFStringRef      profile_level,
+                                CFNumberRef      gamma_level,
+                                CFDictionaryRef  enc_info,
+                                CFDictionaryRef  pixel_buffer_info,
+                                VTCompressionSessionRef *session)
+{
+    VTEncContext *vtctx = avctx->priv_data;
+    SInt32       bit_rate = avctx->bit_rate;
+    CFNumberRef  bit_rate_num;
+
+    int status = VTCompressionSessionCreate(kCFAllocatorDefault,
+                                            avctx->width,
+                                            avctx->height,
+                                            codec_type,
+                                            enc_info,
+                                            pixel_buffer_info,
+                                            kCFAllocatorDefault,
+                                            vtenc_output_callback,
+                                            avctx,
+                                            session);
+
+    if (status || !vtctx->session) {
+        av_log(avctx, AV_LOG_ERROR, "Error: cannot create compression session: %d\n", status);
+
+#if !TARGET_OS_IPHONE
+        if (!vtctx->allow_sw) {
+            av_log(avctx, AV_LOG_ERROR, "Try -allow_sw 1. The hardware encoder may be busy, or not supported.\n");
+        }
+#endif
+
+        return AVERROR_EXTERNAL;
+    }
+
+    bit_rate_num = CFNumberCreate(kCFAllocatorDefault,
+                                  kCFNumberSInt32Type,
+                                  &bit_rate);
+    if (!bit_rate_num) return AVERROR(ENOMEM);
+
+    status = VTSessionSetProperty(vtctx->session,
+                                  kVTCompressionPropertyKey_AverageBitRate,
+                                  bit_rate_num);
+    CFRelease(bit_rate_num);
+
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error setting bitrate property: %d\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
+    if (profile_level) {
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_ProfileLevel,
+                                      profile_level);
+        if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Error setting profile/level property: %d\n", status);
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    if (avctx->gop_size > 0) {
+        CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault,
+                                              kCFNumberIntType,
+                                              &avctx->gop_size);
+        if (!interval) {
+            return AVERROR(ENOMEM);
+        }
+
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_MaxKeyFrameInterval,
+                                      interval);
+        CFRelease(interval);
+
+        if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Error setting 'max key-frame interval' property: %d\n", status);
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    if (vtctx->frames_before) {
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_MoreFramesBeforeStart,
+                                      kCFBooleanTrue);
+
+        if (status == kVTPropertyNotSupportedErr) {
+            av_log(avctx, AV_LOG_WARNING, "frames_before property is not supported on this device. Ignoring.\n");
+        } else if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Error setting frames_before property: %d\n", status);
+        }
+    }
+
+    if (vtctx->frames_after) {
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_MoreFramesAfterEnd,
+                                      kCFBooleanTrue);
+
+        if (status == kVTPropertyNotSupportedErr) {
+            av_log(avctx, AV_LOG_WARNING, "frames_after property is not supported on this device. Ignoring.\n");
+        } else if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Error setting frames_after property: %d\n", status);
+        }
+    }
+
+    if (avctx->sample_aspect_ratio.num != 0) {
+        CFNumberRef num;
+        CFNumberRef den;
+        CFMutableDictionaryRef par;
+        AVRational *avpar = &avctx->sample_aspect_ratio;
+
+        av_reduce(&avpar->num, &avpar->den,
+                   avpar->num,  avpar->den,
+                  0xFFFFFFFF);
+
+        num = CFNumberCreate(kCFAllocatorDefault,
+                             kCFNumberIntType,
+                             &avpar->num);
+
+        den = CFNumberCreate(kCFAllocatorDefault,
+                             kCFNumberIntType,
+                             &avpar->den);
+
+
+
+        par = CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                        2,
+                                        &kCFCopyStringDictionaryKeyCallBacks,
+                                        &kCFTypeDictionaryValueCallBacks);
+
+        if (!par || !num || !den) {
+            if (par) CFRelease(par);
+            if (num) CFRelease(num);
+            if (den) CFRelease(den);
+
+            return AVERROR(ENOMEM);
+        }
+
+        CFDictionarySetValue(
+            par,
+            kCMFormatDescriptionKey_PixelAspectRatioHorizontalSpacing,
+            num);
+
+        CFDictionarySetValue(
+            par,
+            kCMFormatDescriptionKey_PixelAspectRatioVerticalSpacing,
+            den);
+
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_PixelAspectRatio,
+                                      par);
+
+        CFRelease(par);
+        CFRelease(num);
+        CFRelease(den);
+
+        if (status) {
+            av_log(avctx,
+                   AV_LOG_ERROR,
+                   "Error setting pixel aspect ratio to %d:%d: %d.\n",
+                   avctx->sample_aspect_ratio.num,
+                   avctx->sample_aspect_ratio.den,
+                   status);
+
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+
+    if (vtctx->transfer_function) {
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_TransferFunction,
+                                      vtctx->transfer_function);
+
+        if (status) {
+            av_log(avctx, AV_LOG_WARNING, "Could not set transfer function: %d\n", status);
+        }
+    }
+
+
+    if (vtctx->ycbcr_matrix) {
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_YCbCrMatrix,
+                                      vtctx->ycbcr_matrix);
+
+        if (status) {
+            av_log(avctx, AV_LOG_WARNING, "Could not set ycbcr matrix: %d\n", status);
+        }
+    }
+
+
+    if (vtctx->color_primaries) {
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_ColorPrimaries,
+                                      vtctx->color_primaries);
+
+        if (status) {
+            av_log(avctx, AV_LOG_WARNING, "Could not set color primaries: %d\n", status);
+        }
+    }
+
+    if (gamma_level) {
+        status = VTSessionSetProperty(vtctx->session,
+                                      kCVImageBufferGammaLevelKey,
+                                      gamma_level);
+
+        if (status) {
+            av_log(avctx, AV_LOG_WARNING, "Could not set gamma level: %d\n", status);
+        }
+    }
+
+    if (!vtctx->has_b_frames) {
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_AllowFrameReordering,
+                                      kCFBooleanFalse);
+
+        if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Error setting 'allow frame reordering' property: %d\n", status);
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    if (vtctx->entropy != VT_ENTROPY_NOT_SET) {
+        CFStringRef entropy = vtctx->entropy == VT_CABAC ?
+                                kVTH264EntropyMode_CABAC:
+                                kVTH264EntropyMode_CAVLC;
+
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_H264EntropyMode,
+                                      entropy);
+
+        if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Error setting entropy property: %d\n", status);
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    if (vtctx->realtime) {
+        status = VTSessionSetProperty(vtctx->session,
+                                      kVTCompressionPropertyKey_RealTime,
+                                      kCFBooleanTrue);
+
+        if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Error setting realtime property: %d\n", status);
+        }
+    }
+
+    status = VTCompressionSessionPrepareToEncodeFrames(vtctx->session);
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error: cannot prepare encoder: %d\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static av_cold int vtenc_init(AVCodecContext *avctx)
+{
+    CFMutableDictionaryRef enc_info;
+    CFMutableDictionaryRef pixel_buffer_info;
+    CMVideoCodecType       codec_type;
+    VTEncContext           *vtctx = avctx->priv_data;
+    CFStringRef            profile_level;
+    CFBooleanRef           has_b_frames_cfbool;
+    CFNumberRef            gamma_level = NULL;
+    int                    status;
+
+    codec_type = get_cm_codec_type(avctx->codec_id);
+    if (!codec_type) {
+        av_log(avctx, AV_LOG_ERROR, "Error: no mapping for AVCodecID %d\n", avctx->codec_id);
+        return AVERROR(EINVAL);
+    }
+
+    vtctx->has_b_frames = avctx->max_b_frames > 0;
+    if(vtctx->has_b_frames && vtctx->profile == H264_PROF_BASELINE){
+        av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n");
+        vtctx->has_b_frames = false;
+    }
+
+    if (vtctx->entropy == VT_CABAC && vtctx->profile == H264_PROF_BASELINE) {
+        av_log(avctx, AV_LOG_WARNING, "CABAC entropy requires 'main' or 'high' profile, but baseline was requested. Encode will not use CABAC entropy.\n");
+        vtctx->entropy = VT_ENTROPY_NOT_SET;
+    }
+
+    if (!get_vt_profile_level(avctx, &profile_level)) return AVERROR(EINVAL);
+
+    vtctx->session = NULL;
+
+    enc_info = CFDictionaryCreateMutable(
+        kCFAllocatorDefault,
+        20,
+        &kCFCopyStringDictionaryKeyCallBacks,
+        &kCFTypeDictionaryValueCallBacks
+    );
+
+    if (!enc_info) return AVERROR(ENOMEM);
+
+#if !TARGET_OS_IPHONE
+    if (!vtctx->allow_sw) {
+        CFDictionarySetValue(enc_info, kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder, kCFBooleanTrue);
+    } else {
+        CFDictionarySetValue(enc_info, kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder,  kCFBooleanTrue);
+    }
+#endif
+
+    if (avctx->pix_fmt != AV_PIX_FMT_VIDEOTOOLBOX) {
+        status = create_cv_pixel_buffer_info(avctx, &pixel_buffer_info);
+        if (status)
+            goto init_cleanup;
+    } else {
+        pixel_buffer_info = NULL;
+    }
+
+    pthread_mutex_init(&vtctx->lock, NULL);
+    pthread_cond_init(&vtctx->cv_sample_sent, NULL);
+    vtctx->dts_delta = vtctx->has_b_frames ? -1 : 0;
+
+    get_cv_transfer_function(avctx, &vtctx->transfer_function, &gamma_level);
+    get_cv_ycbcr_matrix(avctx, &vtctx->ycbcr_matrix);
+    get_cv_color_primaries(avctx, &vtctx->color_primaries);
+
+
+    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
+        status = vtenc_populate_extradata(avctx,
+                                          codec_type,
+                                          profile_level,
+                                          gamma_level,
+                                          enc_info,
+                                          pixel_buffer_info);
+        if (status)
+            goto init_cleanup;
+    }
+
+    status = vtenc_create_encoder(avctx,
+                                  codec_type,
+                                  profile_level,
+                                  gamma_level,
+                                  enc_info,
+                                  pixel_buffer_info,
+                                  &vtctx->session);
+
+    if (status < 0)
+        goto init_cleanup;
+
+    status = VTSessionCopyProperty(vtctx->session,
+                                   kVTCompressionPropertyKey_AllowFrameReordering,
+                                   kCFAllocatorDefault,
+                                   &has_b_frames_cfbool);
+
+    if (!status) {
+        //Some devices don't output B-frames for main profile, even if requested.
+        vtctx->has_b_frames = CFBooleanGetValue(has_b_frames_cfbool);
+        CFRelease(has_b_frames_cfbool);
+    }
+    avctx->has_b_frames = vtctx->has_b_frames;
+
+init_cleanup:
+    if (gamma_level)
+        CFRelease(gamma_level);
+
+    if (pixel_buffer_info)
+        CFRelease(pixel_buffer_info);
+
+    CFRelease(enc_info);
+
+    return status;
+}
+
+static void vtenc_get_frame_info(CMSampleBufferRef buffer, bool *is_key_frame)
+{
+    CFArrayRef      attachments;
+    CFDictionaryRef attachment;
+    CFBooleanRef    not_sync;
+    CFIndex         len;
+
+    attachments = CMSampleBufferGetSampleAttachmentsArray(buffer, false);
+    len = !attachments ? 0 : CFArrayGetCount(attachments);
+
+    if (!len) {
+        *is_key_frame = true;
+        return;
+    }
+
+    attachment = CFArrayGetValueAtIndex(attachments, 0);
+
+    if (CFDictionaryGetValueIfPresent(attachment,
+                                      kCMSampleAttachmentKey_NotSync,
+                                      (const void **)&not_sync))
+    {
+        *is_key_frame = !CFBooleanGetValue(not_sync);
+    } else {
+        *is_key_frame = true;
+    }
+}
+
+/**
+ * Copies NAL units and replaces length codes with
+ * H.264 Annex B start codes. On failure, the contents of
+ * dst_data may have been modified.
+ *
+ * @param length_code_size Byte length of each length code
+ * @param src_data NAL units prefixed with length codes.
+ * @param src_size Length of buffer, excluding any padding.
+ * @param dst_data Must be zeroed before calling this function.
+ *                 Contains the copied NAL units prefixed with
+ *                 start codes when the function returns
+ *                 successfully.
+ * @param dst_size Length of dst_data
+ * @return 0 on success
+ *         AVERROR_INVALIDDATA if length_code_size is invalid
+ *         AVERROR_BUFFER_TOO_SMALL if dst_data is too small
+ *         or if a length_code in src_data specifies data beyond
+ *         the end of its buffer.
+ */
+static int copy_replace_length_codes(
+    AVCodecContext *avctx,
+    size_t        length_code_size,
+    CMSampleBufferRef sample_buffer,
+    uint8_t       *dst_data,
+    size_t        dst_size)
+{
+    size_t src_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
+    size_t remaining_src_size = src_size;
+    size_t remaining_dst_size = dst_size;
+    size_t src_offset = 0;
+    int status;
+    uint8_t size_buf[4];
+    CMBlockBufferRef block = CMSampleBufferGetDataBuffer(sample_buffer);
+
+    if (length_code_size > 4) {
+        return AVERROR_INVALIDDATA;
+    }
+
+    while (remaining_src_size > 0) {
+        size_t curr_src_len;
+        size_t curr_dst_len;
+        size_t box_len = 0;
+        size_t i;
+
+        uint8_t       *dst_box;
+
+        status = CMBlockBufferCopyDataBytes(block,
+                                            src_offset,
+                                            length_code_size,
+                                            size_buf);
+        if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Cannot copy length: %d\n", status);
+            return AVERROR_EXTERNAL;
+        }
+
+        for (i = 0; i < length_code_size; i++) {
+            box_len <<= 8;
+            box_len |= size_buf[i];
+        }
+
+        curr_src_len = box_len + length_code_size;
+        curr_dst_len = box_len + sizeof(start_code);
+
+        if (remaining_src_size < curr_src_len) {
+            return AVERROR_BUFFER_TOO_SMALL;
+        }
+
+        if (remaining_dst_size < curr_dst_len) {
+            return AVERROR_BUFFER_TOO_SMALL;
+        }
+
+        dst_box = dst_data + sizeof(start_code);
+
+        memcpy(dst_data, start_code, sizeof(start_code));
+        status = CMBlockBufferCopyDataBytes(block,
+                                            src_offset + length_code_size,
+                                            box_len,
+                                            dst_box);
+
+        if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Cannot copy data: %d\n", status);
+            return AVERROR_EXTERNAL;
+        }
+
+        src_offset += curr_src_len;
+        dst_data += curr_dst_len;
+
+        remaining_src_size -= curr_src_len;
+        remaining_dst_size -= curr_dst_len;
+    }
+
+    return 0;
+}
+
+static int vtenc_cm_to_avpacket(
+    AVCodecContext    *avctx,
+    CMSampleBufferRef sample_buffer,
+    AVPacket          *pkt)
+{
+    VTEncContext *vtctx = avctx->priv_data;
+
+    int     status;
+    bool    is_key_frame;
+    bool    add_header;
+    size_t  length_code_size;
+    size_t  header_size = 0;
+    size_t  in_buf_size;
+    size_t  out_buf_size;
+    int64_t dts_delta;
+    int64_t time_base_num;
+    int nalu_count;
+    CMTime  pts;
+    CMTime  dts;
+    CMVideoFormatDescriptionRef vid_fmt;
+
+
+    vtenc_get_frame_info(sample_buffer, &is_key_frame);
+    status = get_length_code_size(avctx, sample_buffer, &length_code_size);
+    if (status) return status;
+
+    add_header = is_key_frame && !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER);
+
+    if (add_header) {
+        vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer);
+        if (!vid_fmt) {
+            av_log(avctx, AV_LOG_ERROR, "Cannot get format description.\n");
+            return AVERROR_EXTERNAL;
+        }
+
+        int status = get_params_size(avctx, vid_fmt, &header_size);
+        if (status) return status;
+    }
+
+    status = count_nalus(length_code_size, sample_buffer, &nalu_count);
+    if(status)
+        return status;
+
+    in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer);
+    out_buf_size = header_size +
+                   in_buf_size +
+                   nalu_count * ((int)sizeof(start_code) - (int)length_code_size);
+
+    status = ff_alloc_packet2(avctx, pkt, out_buf_size, out_buf_size);
+    if (status < 0)
+        return status;
+
+    if (add_header) {
+        status = copy_param_sets(avctx, vid_fmt, pkt->data, out_buf_size);
+        if(status) return status;
+    }
+
+    status = copy_replace_length_codes(
+        avctx,
+        length_code_size,
+        sample_buffer,
+        pkt->data + header_size,
+        pkt->size - header_size
+    );
+
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d", status);
+        return status;
+    }
+
+    if (is_key_frame) {
+        pkt->flags |= AV_PKT_FLAG_KEY;
+    }
+
+    pts = CMSampleBufferGetPresentationTimeStamp(sample_buffer);
+    dts = CMSampleBufferGetDecodeTimeStamp      (sample_buffer);
+
+    if (CMTIME_IS_INVALID(dts)) {
+        if (!vtctx->has_b_frames) {
+            dts = pts;
+        } else {
+            av_log(avctx, AV_LOG_ERROR, "DTS is invalid.\n");
+            return AVERROR_EXTERNAL;
+        }
+    }
+
+    dts_delta = vtctx->dts_delta >= 0 ? vtctx->dts_delta : 0;
+    time_base_num = avctx->time_base.num;
+    pkt->pts = pts.value / time_base_num;
+    pkt->dts = dts.value / time_base_num - dts_delta;
+    pkt->size = out_buf_size;
+
+    return 0;
+}
+
+/*
+ * contiguous_buf_size is 0 if not contiguous, and the size of the buffer
+ * containing all planes if so.
+ */
+static int get_cv_pixel_info(
+    AVCodecContext *avctx,
+    const AVFrame  *frame,
+    int            *color,
+    int            *plane_count,
+    size_t         *widths,
+    size_t         *heights,
+    size_t         *strides,
+    size_t         *contiguous_buf_size)
+{
+    VTEncContext *vtctx = avctx->priv_data;
+    int av_format       = frame->format;
+    int av_color_range  = av_frame_get_color_range(frame);
+    int i;
+    int range_guessed;
+    int status;
+
+    status = get_cv_pixel_format(avctx, av_format, av_color_range, color, &range_guessed);
+    if (status) {
+        av_log(avctx,
+            AV_LOG_ERROR,
+            "Could not get pixel format for color format '%s' range '%s'.\n",
+            av_get_pix_fmt_name(av_format),
+            av_color_range > AVCOL_RANGE_UNSPECIFIED &&
+            av_color_range < AVCOL_RANGE_NB ?
+               av_color_range_name(av_color_range) :
+               "Unknown");
+
+        return AVERROR(EINVAL);
+    }
+
+    if (range_guessed) {
+        if (!vtctx->warned_color_range) {
+            vtctx->warned_color_range = true;
+            av_log(avctx,
+                   AV_LOG_WARNING,
+                   "Color range not set for %s. Using MPEG range.\n",
+                   av_get_pix_fmt_name(av_format));
+        }
+
+        av_log(avctx, AV_LOG_WARNING, "");
+    }
+
+    switch (av_format) {
+    case AV_PIX_FMT_NV12:
+        *plane_count = 2;
+
+        widths [0] = avctx->width;
+        heights[0] = avctx->height;
+        strides[0] = frame ? frame->linesize[0] : avctx->width;
+
+        widths [1] = (avctx->width  + 1) / 2;
+        heights[1] = (avctx->height + 1) / 2;
+        strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) & -2;
+        break;
+
+    case AV_PIX_FMT_YUV420P:
+        *plane_count = 3;
+
+        widths [0] = avctx->width;
+        heights[0] = avctx->height;
+        strides[0] = frame ? frame->linesize[0] : avctx->width;
+
+        widths [1] = (avctx->width  + 1) / 2;
+        heights[1] = (avctx->height + 1) / 2;
+        strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) / 2;
+
+        widths [2] = (avctx->width  + 1) / 2;
+        heights[2] = (avctx->height + 1) / 2;
+        strides[2] = frame ? frame->linesize[2] : (avctx->width + 1) / 2;
+        break;
+
+    default:
+        av_log(
+               avctx,
+               AV_LOG_ERROR,
+               "Could not get frame format info for color %d range %d.\n",
+               av_format,
+               av_color_range);
+
+        return AVERROR(EINVAL);
+    }
+
+    *contiguous_buf_size = 0;
+    for (i = 0; i < *plane_count; i++) {
+        if (i < *plane_count - 1 &&
+            frame->data[i] + strides[i] * heights[i] != frame->data[i + 1]) {
+            *contiguous_buf_size = 0;
+            break;
+        }
+
+        *contiguous_buf_size += strides[i] * heights[i];
+    }
+
+    return 0;
+}
+
+#if !TARGET_OS_IPHONE
+//Not used on iOS - frame is always copied.
+static void free_avframe(
+    void       *release_ctx,
+    const void *data,
+    size_t      size,
+    size_t      plane_count,
+    const void *plane_addresses[])
+{
+    AVFrame *frame = release_ctx;
+    av_frame_free(&frame);
+}
+#else
+//Not used on OSX - frame is never copied.
+static int copy_avframe_to_pixel_buffer(AVCodecContext   *avctx,
+                                        const AVFrame    *frame,
+                                        CVPixelBufferRef cv_img,
+                                        const size_t     *plane_strides,
+                                        const size_t     *plane_rows)
+{
+    int i, j;
+    size_t plane_count;
+    int status;
+    int rows;
+    int src_stride;
+    int dst_stride;
+    uint8_t *src_addr;
+    uint8_t *dst_addr;
+    size_t copy_bytes;
+
+    status = CVPixelBufferLockBaseAddress(cv_img, 0);
+    if (status) {
+        av_log(
+            avctx,
+            AV_LOG_ERROR,
+            "Error: Could not lock base address of CVPixelBuffer: %d.\n",
+            status
+        );
+    }
+
+    if (CVPixelBufferIsPlanar(cv_img)) {
+        plane_count = CVPixelBufferGetPlaneCount(cv_img);
+        for (i = 0; frame->data[i]; i++) {
+            if (i == plane_count) {
+                CVPixelBufferUnlockBaseAddress(cv_img, 0);
+                av_log(avctx,
+                    AV_LOG_ERROR,
+                    "Error: different number of planes in AVFrame and CVPixelBuffer.\n"
+                );
+
+                return AVERROR_EXTERNAL;
+            }
+
+            dst_addr = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img, i);
+            src_addr = (uint8_t*)frame->data[i];
+            dst_stride = CVPixelBufferGetBytesPerRowOfPlane(cv_img, i);
+            src_stride = plane_strides[i];
+            rows = plane_rows[i];
+
+            if (dst_stride == src_stride) {
+                memcpy(dst_addr, src_addr, src_stride * rows);
+            } else {
+                copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
+
+                for (j = 0; j < rows; j++) {
+                    memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
+                }
+            }
+        }
+    } else {
+        if (frame->data[1]) {
+            CVPixelBufferUnlockBaseAddress(cv_img, 0);
+            av_log(avctx,
+                AV_LOG_ERROR,
+                "Error: different number of planes in AVFrame and non-planar CVPixelBuffer.\n"
+            );
+
+            return AVERROR_EXTERNAL;
+        }
+
+        dst_addr = (uint8_t*)CVPixelBufferGetBaseAddress(cv_img);
+        src_addr = (uint8_t*)frame->data[0];
+        dst_stride = CVPixelBufferGetBytesPerRow(cv_img);
+        src_stride = plane_strides[0];
+        rows = plane_rows[0];
+
+        if (dst_stride == src_stride) {
+            memcpy(dst_addr, src_addr, src_stride * rows);
+        } else {
+            copy_bytes = dst_stride < src_stride ? dst_stride : src_stride;
+
+            for (j = 0; j < rows; j++) {
+                memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes);
+            }
+        }
+    }
+
+    status = CVPixelBufferUnlockBaseAddress(cv_img, 0);
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error: Could not unlock CVPixelBuffer base address: %d.\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+#endif //!TARGET_OS_IPHONE
+
+static int create_cv_pixel_buffer(AVCodecContext   *avctx,
+                                  const AVFrame    *frame,
+                                  CVPixelBufferRef *cv_img)
+{
+    int plane_count;
+    int color;
+    size_t widths [AV_NUM_DATA_POINTERS];
+    size_t heights[AV_NUM_DATA_POINTERS];
+    size_t strides[AV_NUM_DATA_POINTERS];
+    int status;
+    size_t contiguous_buf_size;
+#if TARGET_OS_IPHONE
+    CVPixelBufferPoolRef pix_buf_pool;
+    VTEncContext* vtctx = avctx->priv_data;
+#else
+    CFMutableDictionaryRef pix_buf_attachments = CFDictionaryCreateMutable(
+                                                   kCFAllocatorDefault,
+                                                   10,
+                                                   &kCFCopyStringDictionaryKeyCallBacks,
+                                                   &kCFTypeDictionaryValueCallBacks);
+
+    if (!pix_buf_attachments) return AVERROR(ENOMEM);
+#endif
+
+    if (avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX) {
+        av_assert0(frame->format == AV_PIX_FMT_VIDEOTOOLBOX);
+
+        *cv_img = (CVPixelBufferRef)frame->data[3];
+        av_assert0(*cv_img);
+
+        CFRetain(*cv_img);
+        return 0;
+    }
+
+    memset(widths,  0, sizeof(widths));
+    memset(heights, 0, sizeof(heights));
+    memset(strides, 0, sizeof(strides));
+
+    status = get_cv_pixel_info(
+        avctx,
+        frame,
+        &color,
+        &plane_count,
+        widths,
+        heights,
+        strides,
+        &contiguous_buf_size
+    );
+
+    if (status) {
+        av_log(
+            avctx,
+            AV_LOG_ERROR,
+            "Error: Cannot convert format %d color_range %d: %d\n",
+            frame->format,
+            av_frame_get_color_range(frame),
+            status
+        );
+
+        return AVERROR_EXTERNAL;
+    }
+
+#if TARGET_OS_IPHONE
+    pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session);
+    if (!pix_buf_pool) {
+        av_log(avctx, AV_LOG_ERROR, "Could not get pixel buffer pool.\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    status = CVPixelBufferPoolCreatePixelBuffer(NULL,
+                                                pix_buf_pool,
+                                                cv_img);
+
+
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Could not create pixel buffer from pool: %d.\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
+    status = copy_avframe_to_pixel_buffer(avctx, frame, *cv_img, strides, heights);
+    if (status) {
+        CFRelease(*cv_img);
+        *cv_img = NULL;
+        return status;
+    }
+#else
+    AVFrame *enc_frame = av_frame_alloc();
+    if (!enc_frame) return AVERROR(ENOMEM);
+
+    status = av_frame_ref(enc_frame, frame);
+    if (status) {
+        av_frame_free(&enc_frame);
+        return status;
+    }
+
+    status = CVPixelBufferCreateWithPlanarBytes(
+        kCFAllocatorDefault,
+        enc_frame->width,
+        enc_frame->height,
+        color,
+        NULL,
+        contiguous_buf_size,
+        plane_count,
+        (void **)enc_frame->data,
+        widths,
+        heights,
+        strides,
+        free_avframe,
+        enc_frame,
+        NULL,
+        cv_img
+    );
+
+    add_color_attr(avctx, pix_buf_attachments);
+    CVBufferSetAttachments(*cv_img, pix_buf_attachments, kCVAttachmentMode_ShouldPropagate);
+    CFRelease(pix_buf_attachments);
+
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error: Could not create CVPixelBuffer: %d\n", status);
+        return AVERROR_EXTERNAL;
+    }
+#endif
+
+    return 0;
+}
+
+static int create_encoder_dict_h264(const AVFrame *frame,
+                                    CFDictionaryRef* dict_out)
+{
+    CFDictionaryRef dict = NULL;
+    if (frame->pict_type == AV_PICTURE_TYPE_I) {
+        const void *keys[] = { kVTEncodeFrameOptionKey_ForceKeyFrame };
+        const void *vals[] = { kCFBooleanTrue };
+
+        dict = CFDictionaryCreate(NULL, keys, vals, 1, NULL, NULL);
+        if(!dict) return AVERROR(ENOMEM);
+    }
+
+    *dict_out = dict;
+    return 0;
+}
+
+static int vtenc_send_frame(AVCodecContext *avctx,
+                            VTEncContext   *vtctx,
+                            const AVFrame  *frame)
+{
+    CMTime time;
+    CFDictionaryRef frame_dict;
+    CVPixelBufferRef cv_img = NULL;
+    int status = create_cv_pixel_buffer(avctx, frame, &cv_img);
+
+    if (status) return status;
+
+    status = create_encoder_dict_h264(frame, &frame_dict);
+    if (status) {
+        CFRelease(cv_img);
+        return status;
+    }
+
+    time = CMTimeMake(frame->pts * avctx->time_base.num, avctx->time_base.den);
+    status = VTCompressionSessionEncodeFrame(
+        vtctx->session,
+        cv_img,
+        time,
+        kCMTimeInvalid,
+        frame_dict,
+        NULL,
+        NULL
+    );
+
+    if (frame_dict) CFRelease(frame_dict);
+    CFRelease(cv_img);
+
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error: cannot encode frame: %d\n", status);
+        return AVERROR_EXTERNAL;
+    }
+
+    return 0;
+}
+
+static av_cold int vtenc_frame(
+    AVCodecContext *avctx,
+    AVPacket       *pkt,
+    const AVFrame  *frame,
+    int            *got_packet)
+{
+    VTEncContext *vtctx = avctx->priv_data;
+    bool get_frame;
+    int status;
+    CMSampleBufferRef buf = NULL;
+
+    if (frame) {
+        status = vtenc_send_frame(avctx, vtctx, frame);
+
+        if (status) {
+            status = AVERROR_EXTERNAL;
+            goto end_nopkt;
+        }
+
+        if (vtctx->frame_ct_in == 0) {
+            vtctx->first_pts = frame->pts;
+        } else if(vtctx->frame_ct_in == 1 && vtctx->has_b_frames) {
+            vtctx->dts_delta = frame->pts - vtctx->first_pts;
+        }
+
+        vtctx->frame_ct_in++;
+    } else if(!vtctx->flushing) {
+        vtctx->flushing = true;
+
+        status = VTCompressionSessionCompleteFrames(vtctx->session,
+                                                    kCMTimeIndefinite);
+
+        if (status) {
+            av_log(avctx, AV_LOG_ERROR, "Error flushing frames: %d\n", status);
+            status = AVERROR_EXTERNAL;
+            goto end_nopkt;
+        }
+    }
+
+    *got_packet = 0;
+    get_frame = vtctx->dts_delta >= 0 || !frame;
+    if (!get_frame) {
+        status = 0;
+        goto end_nopkt;
+    }
+
+    status = vtenc_q_pop(vtctx, !frame, &buf);
+    if (status) goto end_nopkt;
+    if (!buf)   goto end_nopkt;
+
+    status = vtenc_cm_to_avpacket(avctx, buf, pkt);
+    CFRelease(buf);
+    if (status) goto end_nopkt;
+
+    *got_packet = 1;
+    return 0;
+
+end_nopkt:
+    av_packet_unref(pkt);
+    return status;
+}
+
+static int vtenc_populate_extradata(AVCodecContext   *avctx,
+                                    CMVideoCodecType codec_type,
+                                    CFStringRef      profile_level,
+                                    CFNumberRef      gamma_level,
+                                    CFDictionaryRef  enc_info,
+                                    CFDictionaryRef  pixel_buffer_info)
+{
+    VTEncContext *vtctx = avctx->priv_data;
+    AVFrame *frame = av_frame_alloc();
+    int y_size = avctx->width * avctx->height;
+    int chroma_size = (avctx->width / 2) * (avctx->height / 2);
+    CMSampleBufferRef buf = NULL;
+    int status;
+
+    if (!frame)
+        return AVERROR(ENOMEM);
+
+    frame->buf[0] = av_buffer_alloc(y_size + 2 * chroma_size);
+
+    if(!frame->buf[0]){
+        status = AVERROR(ENOMEM);
+        goto pe_cleanup;
+    }
+
+    status = vtenc_create_encoder(avctx,
+                                  codec_type,
+                                  profile_level,
+                                  gamma_level,
+                                  enc_info,
+                                  pixel_buffer_info,
+                                  &vtctx->session);
+    if (status)
+        goto pe_cleanup;
+
+    frame->data[0] = frame->buf[0]->data;
+    memset(frame->data[0],   0,      y_size);
+
+    frame->data[1] = frame->buf[0]->data + y_size;
+    memset(frame->data[1], 128, chroma_size);
+
+
+    if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
+        frame->data[2] = frame->buf[0]->data + y_size + chroma_size;
+        memset(frame->data[2], 128, chroma_size);
+    }
+
+    frame->linesize[0] = avctx->width;
+
+    if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
+        frame->linesize[1] =
+        frame->linesize[2] = (avctx->width + 1) / 2;
+    } else {
+        frame->linesize[1] = (avctx->width + 1) / 2;
+    }
+
+    frame->format          = avctx->pix_fmt;
+    frame->width           = avctx->width;
+    frame->height          = avctx->height;
+    av_frame_set_colorspace(frame, avctx->colorspace);
+    av_frame_set_color_range(frame, avctx->color_range);
+    frame->color_trc       = avctx->color_trc;
+    frame->color_primaries = avctx->color_primaries;
+
+    frame->pts = 0;
+    status = vtenc_send_frame(avctx, vtctx, frame);
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "Error sending frame: %d\n", status);
+        goto pe_cleanup;
+    }
+
+    //Populates extradata - output frames are flushed and param sets are available.
+    status = VTCompressionSessionCompleteFrames(vtctx->session,
+                                                kCMTimeIndefinite);
+
+    if (status)
+        goto pe_cleanup;
+
+    status = vtenc_q_pop(vtctx, 0, &buf);
+    if (status) {
+        av_log(avctx, AV_LOG_ERROR, "popping: %d\n", status);
+        goto pe_cleanup;
+    }
+
+    CFRelease(buf);
+
+
+
+pe_cleanup:
+    if(vtctx->session)
+        CFRelease(vtctx->session);
+
+    vtctx->session = NULL;
+    vtctx->frame_ct_out = 0;
+
+    av_frame_unref(frame);
+    av_frame_free(&frame);
+
+    av_assert0(status != 0 || (avctx->extradata && avctx->extradata_size > 0));
+
+    return status;
+}
+
+static av_cold int vtenc_close(AVCodecContext *avctx)
+{
+    VTEncContext *vtctx = avctx->priv_data;
+
+    if(!vtctx->session) return 0;
+
+    pthread_cond_destroy(&vtctx->cv_sample_sent);
+    pthread_mutex_destroy(&vtctx->lock);
+    CFRelease(vtctx->session);
+    vtctx->session = NULL;
+
+    if (vtctx->color_primaries) {
+        CFRelease(vtctx->color_primaries);
+        vtctx->color_primaries = NULL;
+    }
+
+    if (vtctx->transfer_function) {
+        CFRelease(vtctx->transfer_function);
+        vtctx->transfer_function = NULL;
+    }
+
+    if (vtctx->ycbcr_matrix) {
+        CFRelease(vtctx->ycbcr_matrix);
+        vtctx->ycbcr_matrix = NULL;
+    }
+
+    return 0;
+}
+
+static const enum AVPixelFormat pix_fmts[] = {
+    AV_PIX_FMT_VIDEOTOOLBOX,
+    AV_PIX_FMT_NV12,
+    AV_PIX_FMT_YUV420P,
+    AV_PIX_FMT_NONE
+};
+
+#define OFFSET(x) offsetof(VTEncContext, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = H264_PROF_AUTO }, H264_PROF_AUTO, H264_PROF_COUNT, VE, "profile" },
+    { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_BASELINE }, INT_MIN, INT_MAX, VE, "profile" },
+    { "main",     "Main Profile",     0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_MAIN     }, INT_MIN, INT_MAX, VE, "profile" },
+    { "high",     "High Profile",     0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_HIGH     }, INT_MIN, INT_MAX, VE, "profile" },
+
+    { "level", "Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, VE, "level" },
+    { "1.3", "Level 1.3, only available with Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, INT_MIN, INT_MAX, VE, "level" },
+    { "3.0", "Level 3.0", 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, INT_MIN, INT_MAX, VE, "level" },
+    { "3.1", "Level 3.1", 0, AV_OPT_TYPE_CONST, { .i64 = 31 }, INT_MIN, INT_MAX, VE, "level" },
+    { "3.2", "Level 3.2", 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, INT_MIN, INT_MAX, VE, "level" },
+    { "4.0", "Level 4.0", 0, AV_OPT_TYPE_CONST, { .i64 = 40 }, INT_MIN, INT_MAX, VE, "level" },
+    { "4.1", "Level 4.1", 0, AV_OPT_TYPE_CONST, { .i64 = 41 }, INT_MIN, INT_MAX, VE, "level" },
+    { "4.2", "Level 4.2", 0, AV_OPT_TYPE_CONST, { .i64 = 42 }, INT_MIN, INT_MAX, VE, "level" },
+    { "5.0", "Level 5.0", 0, AV_OPT_TYPE_CONST, { .i64 = 50 }, INT_MIN, INT_MAX, VE, "level" },
+    { "5.1", "Level 5.1", 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, INT_MIN, INT_MAX, VE, "level" },
+    { "5.2", "Level 5.2", 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, INT_MIN, INT_MAX, VE, "level" },
+
+    { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL,
+        { .i64 = 0 }, 0, 1, VE },
+
+    { "coder", "Entropy coding", OFFSET(entropy), AV_OPT_TYPE_INT, { .i64 = VT_ENTROPY_NOT_SET }, VT_ENTROPY_NOT_SET, VT_CABAC, VE, "coder" },
+    { "cavlc", "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, "coder" },
+    { "vlc",   "CAVLC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CAVLC }, INT_MIN, INT_MAX, VE, "coder" },
+    { "cabac", "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, "coder" },
+    { "ac",    "CABAC entropy coding", 0, AV_OPT_TYPE_CONST, { .i64 = VT_CABAC }, INT_MIN, INT_MAX, VE, "coder" },
+
+    { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).",
+        OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+
+    { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.",
+        OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+    { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.",
+        OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
+
+    { NULL },
+};
+
+static const AVClass h264_videotoolbox_class = {
+    .class_name = "h264_videotoolbox",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_h264_videotoolbox_encoder = {
+    .name             = "h264_videotoolbox",
+    .long_name        = NULL_IF_CONFIG_SMALL("VideoToolbox H.264 Encoder"),
+    .type             = AVMEDIA_TYPE_VIDEO,
+    .id               = AV_CODEC_ID_H264,
+    .priv_data_size   = sizeof(VTEncContext),
+    .pix_fmts         = pix_fmts,
+    .init             = vtenc_init,
+    .encode2          = vtenc_frame,
+    .close            = vtenc_close,
+    .capabilities     = AV_CODEC_CAP_DELAY,
+    .priv_class       = &h264_videotoolbox_class,
+    .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
+                        FF_CODEC_CAP_INIT_CLEANUP,
+};
diff --git a/libavcodec/vlc.h b/libavcodec/vlc.h
new file mode 100644
index 0000000..9e38f8c
--- /dev/null
+++ b/libavcodec/vlc.h
@@ -0,0 +1,65 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_VLC_H
+#define AVCODEC_VLC_H
+
+#include <stdint.h>
+
+#define VLC_TYPE int16_t
+
+typedef struct VLC {
+    int bits;
+    VLC_TYPE (*table)[2]; ///< code, bits
+    int table_size, table_allocated;
+} VLC;
+
+typedef struct RL_VLC_ELEM {
+    int16_t level;
+    int8_t len;
+    uint8_t run;
+} RL_VLC_ELEM;
+
+#define init_vlc(vlc, nb_bits, nb_codes,                \
+                 bits, bits_wrap, bits_size,            \
+                 codes, codes_wrap, codes_size,         \
+                 flags)                                 \
+    ff_init_vlc_sparse(vlc, nb_bits, nb_codes,          \
+                       bits, bits_wrap, bits_size,      \
+                       codes, codes_wrap, codes_size,   \
+                       NULL, 0, 0, flags)
+
+int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
+                       const void *bits, int bits_wrap, int bits_size,
+                       const void *codes, int codes_wrap, int codes_size,
+                       const void *symbols, int symbols_wrap, int symbols_size,
+                       int flags);
+void ff_free_vlc(VLC *vlc);
+
+#define INIT_VLC_LE             2
+#define INIT_VLC_USE_NEW_STATIC 4
+
+#define INIT_VLC_STATIC(vlc, bits, a, b, c, d, e, f, g, static_size)       \
+    do {                                                                   \
+        static VLC_TYPE table[static_size][2];                             \
+        (vlc)->table           = table;                                    \
+        (vlc)->table_allocated = static_size;                              \
+        init_vlc(vlc, bits, a, b, c, d, e, f, g, INIT_VLC_USE_NEW_STATIC); \
+    } while (0)
+
+#endif /* AVCODEC_VLC_H */
diff --git a/libavcodec/vorbis_parser.h b/libavcodec/vorbis_parser.h
index 81fda3b..9205027 100644
--- a/libavcodec/vorbis_parser.h
+++ b/libavcodec/vorbis_parser.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
index 5bbf47b..fa749be 100644
--- a/libavcodec/vp3.c
+++ b/libavcodec/vp3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2004 The FFmpeg Project
+ * Copyright (C) 2003-2004 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -946,14 +946,14 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
     int num_coeffs      = s->num_coded_frags[plane][coeff_index];
     int16_t *dct_tokens = s->dct_tokens[plane][coeff_index];
 
-    /* local references to structure members to avoid repeated deferences */
+    /* local references to structure members to avoid repeated dereferences */
     int *coded_fragment_list   = s->coded_fragment_list[plane];
     Vp3Fragment *all_fragments = s->all_fragments;
     VLC_TYPE(*vlc_table)[2] = table->table;
 
     if (num_coeffs < 0)
         av_log(s->avctx, AV_LOG_ERROR,
-               "Invalid number of coefficents at level %d\n", coeff_index);
+               "Invalid number of coefficients at level %d\n", coeff_index);
 
     if (eob_run > num_coeffs) {
         coeff_i      =
@@ -1124,7 +1124,7 @@ static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb)
         c_tables[i] = &s->ac_vlc_4[ac_c_table];
     }
 
-    /* decode all AC coefficents */
+    /* decode all AC coefficients */
     for (i = 1; i <= 63; i++) {
         residual_eob_run = unpack_vlcs(s, gb, y_tables[i], i,
                                        0, residual_eob_run);
@@ -1322,7 +1322,7 @@ static void apply_loop_filter(Vp3DecodeContext *s, int plane,
         for (x = 0; x < width; x++) {
             /* This code basically just deblocks on the edges of coded blocks.
              * However, it has to be much more complicated because of the
-             * braindamaged deblock ordering used in VP3/Theora. Order matters
+             * brain damaged deblock ordering used in VP3/Theora. Order matters
              * because some pixels get filtered twice. */
             if (s->all_fragments[fragment].coding_method != MODE_COPY) {
                 /* do not perform left edge filter for left columns frags */
@@ -1595,7 +1595,7 @@ static void render_slice(Vp3DecodeContext *s, int slice)
                             /* Note, it is possible to implement all MC cases
                              * with put_no_rnd_pixels_l2 which would look more
                              * like the VP3 source but this would be slower as
-                             * put_no_rnd_pixels_tab is better optimzed */
+                             * put_no_rnd_pixels_tab is better optimized */
                             if (motion_halfpel_index != 3) {
                                 s->hdsp.put_no_rnd_pixels_tab[1][motion_halfpel_index](
                                     output_plane + first_pixel,
diff --git a/libavcodec/vp3data.h b/libavcodec/vp3data.h
index da31f6d..3884bca 100644
--- a/libavcodec/vp3data.h
+++ b/libavcodec/vp3data.h
@@ -1,5 +1,5 @@
 /*
- * copyright (C) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/vp3dsp.c b/libavcodec/vp3dsp.c
index d8a3e0a..814c78e 100644
--- a/libavcodec/vp3dsp.c
+++ b/libavcodec/vp3dsp.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 The FFmpeg Project
+ * Copyright (C) 2004 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index 64037fc..c1c3eb7 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -28,6 +28,7 @@
 
 #include "avcodec.h"
 #include "internal.h"
+#include "mathops.h"
 #include "rectangle.h"
 #include "thread.h"
 #include "vp8.h"
@@ -541,7 +542,7 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
                    sizeof(vp7_mv_default_prob[i]));
         memset(&s->segmentation, 0, sizeof(s->segmentation));
         memset(&s->lf_delta, 0, sizeof(s->lf_delta));
-        memcpy(s->prob[0].scan, zigzag_scan, sizeof(s->prob[0].scan));
+        memcpy(s->prob[0].scan, ff_zigzag_scan, sizeof(s->prob[0].scan));
     }
 
     if (s->keyframe || s->profile > 0)
@@ -613,7 +614,7 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
     /* G. DCT coefficient ordering specification */
     if (vp8_rac_get(c))
         for (i = 1; i < 16; i++)
-            s->prob[0].scan[i] = zigzag_scan[vp8_rac_get_uint(c, 4)];
+            s->prob[0].scan[i] = ff_zigzag_scan[vp8_rac_get_uint(c, 4)];
 
     /* H. Loop filter levels  */
     if (s->profile > 0)
@@ -1162,10 +1163,10 @@ void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y,
                     uint8_t *segment, uint8_t *ref, int layout, int is_vp7)
 {
     VP56RangeCoder *c = &s->c;
-    const char *vp7_feature_name[] = { "q-index",
-                                       "lf-delta",
-                                       "partial-golden-update",
-                                       "blit-pitch" };
+    static const char *vp7_feature_name[] = { "q-index",
+                                              "lf-delta",
+                                              "partial-golden-update",
+                                              "blit-pitch" };
     if (is_vp7) {
         int i;
         *segment = 0;
@@ -1350,7 +1351,7 @@ static int vp8_decode_block_coeffs_internal(VP56RangeCoder *r,
                                             int16_t qmul[2])
 {
     return decode_block_coeffs_internal(r, block, probs, i,
-                                        token_prob, qmul, zigzag_scan, IS_VP8);
+                                        token_prob, qmul, ff_zigzag_scan, IS_VP8);
 }
 #endif
 
@@ -1398,7 +1399,7 @@ void decode_mb_coeffs(VP8Context *s, VP8ThreadData *td, VP56RangeCoder *c,
         // decode DC values and do hadamard
         nnz = decode_block_coeffs(c, td->block_dc, s->prob->token[1], 0,
                                   nnz_pred, s->qmat[segment].luma_dc_qmul,
-                                  zigzag_scan, is_vp7);
+                                  ff_zigzag_scan, is_vp7);
         l_nnz[8] = t_nnz[8] = !!nnz;
 
         if (is_vp7 && mb->mode > MODE_I4x4) {
@@ -2746,7 +2747,7 @@ int vp78_decode_init(AVCodecContext *avctx, int is_vp7)
     }
 
     /* does not change for VP8 */
-    memcpy(s->prob[0].scan, zigzag_scan, sizeof(s->prob[0].scan));
+    memcpy(s->prob[0].scan, ff_zigzag_scan, sizeof(s->prob[0].scan));
 
     if ((ret = vp8_init_frames(s)) < 0) {
         ff_vp8_decode_free(avctx);
diff --git a/libavcodec/vp8.h b/libavcodec/vp8.h
index cfd82aa..374e138 100644
--- a/libavcodec/vp8.h
+++ b/libavcodec/vp8.h
@@ -223,7 +223,7 @@ typedef struct VP8Context {
 
     /**
      * These are all of the updatable probabilities for binary decisions.
-     * They are only implictly reset on keyframes, making it quite likely
+     * They are only implicitly reset on keyframes, making it quite likely
      * for an interframe to desync if a prior frame's header was corrupt
      * or missing outright!
      */
@@ -271,7 +271,7 @@ typedef struct VP8Context {
     /**
      * This describes the macroblock memory layout.
      * 0 -> Only width+height*2+1 macroblocks allocated (frame/single thread).
-     * 1 -> Macroblocks for entire frame alloced (sliced thread).
+     * 1 -> Macroblocks for entire frame allocated (sliced thread).
      */
     int mb_layout;
 
diff --git a/libavcodec/vp8data.h b/libavcodec/vp8data.h
index f9dbf56..5e6dea7 100644
--- a/libavcodec/vp8data.h
+++ b/libavcodec/vp8data.h
@@ -708,14 +708,6 @@ static const uint8_t vp8_token_update_probs[4][8][3][NUM_DCT_TOKENS - 1] = {
     },
 };
 
-// fixme: copied from h264data.h
-static const uint8_t zigzag_scan[16]={
-    0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
-    1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
-    1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,
-    3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4,
-};
-
 static const uint8_t vp8_dc_qlookup[VP8_MAX_QUANT + 1] = {
       4,   5,   6,   7,   8,   9,  10,  10,  11,  12,  13,  14,  15,  16,  17,  17,
      18,  19,  20,  20,  21,  21,  22,  22,  23,  23,  24,  25,  25,  26,  27,  28,
diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
index 5d8ad12..cb2a4a2 100644
--- a/libavcodec/vp9.c
+++ b/libavcodec/vp9.c
@@ -642,6 +642,8 @@ static int decode_frame_header(AVCodecContext *ctx,
     s->s.h.refreshctx   = s->s.h.errorres ? 0 : get_bits1(&s->gb);
     s->s.h.parallelmode = s->s.h.errorres ? 1 : get_bits1(&s->gb);
     s->s.h.framectxid   = c = get_bits(&s->gb, 2);
+    if (s->s.h.keyframe || s->s.h.intraonly)
+        s->s.h.framectxid = 0; // BUG: libvpx ignores this field in keyframes
 
     /* loopfilter header data */
     if (s->s.h.keyframe || s->s.h.errorres || s->s.h.intraonly) {
@@ -743,7 +745,7 @@ static int decode_frame_header(AVCodecContext *ctx,
         if (s->s.h.lf_delta.enabled) {
             s->s.h.segmentation.feat[i].lflvl[0][0] =
             s->s.h.segmentation.feat[i].lflvl[0][1] =
-                av_clip_uintp2(lflvl + (s->s.h.lf_delta.ref[0] << sh), 6);
+                av_clip_uintp2(lflvl + (s->s.h.lf_delta.ref[0] * (1 << sh)), 6);
             for (j = 1; j < 4; j++) {
                 s->s.h.segmentation.feat[i].lflvl[j][0] =
                     av_clip_uintp2(lflvl + ((s->s.h.lf_delta.ref[j] +
@@ -2769,7 +2771,7 @@ static av_always_inline void mc_chroma_unscaled(VP9Context *s, vp9_mc_func (*mc)
                                                 ptrdiff_t y, ptrdiff_t x, const VP56mv *mv,
                                                 int bw, int bh, int w, int h, int bytesperpixel)
 {
-    int mx = mv->x << !s->ss_h, my = mv->y << !s->ss_v, th;
+    int mx = mv->x * (1 << !s->ss_h), my = mv->y * (1 << !s->ss_v), th;
 
     y += my >> 4;
     x += mx >> 4;
@@ -2849,8 +2851,8 @@ static av_always_inline void mc_luma_scaled(VP9Context *s, vp9_scaled_mc_func sm
     int th;
     VP56mv mv;
 
-    mv.x = av_clip(in_mv->x, -(x + pw - px + 4) << 3, (s->cols * 8 - x + px + 3) << 3);
-    mv.y = av_clip(in_mv->y, -(y + ph - py + 4) << 3, (s->rows * 8 - y + py + 3) << 3);
+    mv.x = av_clip(in_mv->x, -(x + pw - px + 4) * 8, (s->cols * 8 - x + px + 3) * 8);
+    mv.y = av_clip(in_mv->y, -(y + ph - py + 4) * 8, (s->rows * 8 - y + py + 3) * 8);
     // BUG libvpx seems to scale the two components separately. This introduces
     // rounding errors but we have to reproduce them to be exactly compatible
     // with the output from libvpx...
@@ -2907,19 +2909,19 @@ static av_always_inline void mc_chroma_scaled(VP9Context *s, vp9_scaled_mc_func
 
     if (s->ss_h) {
         // BUG https://code.google.com/p/webm/issues/detail?id=820
-        mv.x = av_clip(in_mv->x, -(x + pw - px + 4) << 4, (s->cols * 4 - x + px + 3) << 4);
+        mv.x = av_clip(in_mv->x, -(x + pw - px + 4) * 16, (s->cols * 4 - x + px + 3) * 16);
         mx = scale_mv(mv.x, 0) + (scale_mv(x * 16, 0) & ~15) + (scale_mv(x * 32, 0) & 15);
     } else {
-        mv.x = av_clip(in_mv->x, -(x + pw - px + 4) << 3, (s->cols * 8 - x + px + 3) << 3);
-        mx = scale_mv(mv.x << 1, 0) + scale_mv(x * 16, 0);
+        mv.x = av_clip(in_mv->x, -(x + pw - px + 4) * 8, (s->cols * 8 - x + px + 3) * 8);
+        mx = scale_mv(mv.x * 2, 0) + scale_mv(x * 16, 0);
     }
     if (s->ss_v) {
         // BUG https://code.google.com/p/webm/issues/detail?id=820
-        mv.y = av_clip(in_mv->y, -(y + ph - py + 4) << 4, (s->rows * 4 - y + py + 3) << 4);
+        mv.y = av_clip(in_mv->y, -(y + ph - py + 4) * 16, (s->rows * 4 - y + py + 3) * 16);
         my = scale_mv(mv.y, 1) + (scale_mv(y * 16, 1) & ~15) + (scale_mv(y * 32, 1) & 15);
     } else {
-        mv.y = av_clip(in_mv->y, -(y + ph - py + 4) << 3, (s->rows * 8 - y + py + 3) << 3);
-        my = scale_mv(mv.y << 1, 1) + scale_mv(y * 16, 1);
+        mv.y = av_clip(in_mv->y, -(y + ph - py + 4) * 8, (s->rows * 8 - y + py + 3) * 8);
+        my = scale_mv(mv.y * 2, 1) + scale_mv(y * 16, 1);
     }
 #undef scale_mv
     y = my >> 4;
diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c
new file mode 100644
index 0000000..b686adb
--- /dev/null
+++ b/libavcodec/vp9_superframe_bsf.c
@@ -0,0 +1,205 @@
+/*
+ * Vp9 invisible (alt-ref) frame to superframe merge bitstream filter
+ * Copyright (c) 2016 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * 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/avassert.h"
+#include "avcodec.h"
+#include "bsf.h"
+#include "get_bits.h"
+
+#define MAX_CACHE 8
+typedef struct VP9BSFContext {
+    int n_cache;
+    struct CachedBuf {
+        uint8_t *data;
+        int size;
+    } cache[MAX_CACHE];
+} VP9BSFContext;
+
+static void stats(const struct CachedBuf *in, int n_in,
+                  unsigned *_max, unsigned *_sum)
+{
+    int n;
+    unsigned max = 0, sum = 0;
+
+    for (n = 0; n < n_in; n++) {
+        unsigned sz = in[n].size;
+
+        if (sz > max)
+            max = sz;
+        sum += sz;
+    }
+
+    *_max = max;
+    *_sum = sum;
+}
+
+static int merge_superframe(const struct CachedBuf *in, int n_in, AVPacket *out)
+{
+    unsigned max, sum, mag, marker, n, sz;
+    uint8_t *ptr;
+    int res;
+
+    stats(in, n_in, &max, &sum);
+    mag = av_log2(max) >> 3;
+    marker = 0xC0 + (mag << 3) + (n_in - 1);
+    sz = sum + 2 + (mag + 1) * n_in;
+    res = av_new_packet(out, sz);
+    if (res < 0)
+        return res;
+    ptr = out->data;
+    for (n = 0; n < n_in; n++) {
+        memcpy(ptr, in[n].data, in[n].size);
+        ptr += in[n].size;
+    }
+
+#define wloop(mag, wr) \
+    for (n = 0; n < n_in; n++) { \
+        wr; \
+        ptr += mag + 1; \
+    }
+
+    // write superframe with marker 110[mag:2][nframes:3]
+    *ptr++ = marker;
+    switch (mag) {
+    case 0:
+        wloop(mag, *ptr = in[n].size);
+        break;
+    case 1:
+        wloop(mag, AV_WL16(ptr, in[n].size));
+        break;
+    case 2:
+        wloop(mag, AV_WL24(ptr, in[n].size));
+        break;
+    case 3:
+        wloop(mag, AV_WL32(ptr, in[n].size));
+        break;
+    }
+    *ptr++ = marker;
+    av_assert0(ptr == &out->data[out->size]);
+
+    return 0;
+}
+
+static int vp9_superframe_filter(AVBSFContext *ctx, AVPacket *out)
+{
+    GetBitContext gb;
+    VP9BSFContext *s = ctx->priv_data;
+    AVPacket *in;
+    int res, invisible, profile, marker, uses_superframe_syntax = 0, n;
+
+    res = ff_bsf_get_packet(ctx, &in);
+    if (res < 0)
+        return res;
+
+    marker = in->data[in->size - 1];
+    if ((marker & 0xe0) == 0xc0) {
+        int nbytes = 1 + ((marker >> 3) & 0x3);
+        int n_frames = 1 + (marker & 0x7), idx_sz = 2 + n_frames * nbytes;
+
+        uses_superframe_syntax = in->size >= idx_sz && in->data[in->size - idx_sz] == marker;
+    }
+
+    if ((res = init_get_bits8(&gb, in->data, in->size)) < 0)
+        goto done;
+
+    get_bits(&gb, 2); // frame marker
+    profile  = get_bits1(&gb);
+    profile |= get_bits1(&gb) << 1;
+    if (profile == 3) profile += get_bits1(&gb);
+
+    if (get_bits1(&gb)) {
+        invisible = 0;
+    } else {
+        get_bits1(&gb); // keyframe
+        invisible = !get_bits1(&gb);
+    }
+
+    if (uses_superframe_syntax && s->n_cache > 0) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Mixing of superframe syntax and naked VP9 frames not supported");
+        res = AVERROR_INVALIDDATA;
+        goto done;
+    } else if ((!invisible || uses_superframe_syntax) && !s->n_cache) {
+        // passthrough
+        av_packet_move_ref(out, in);
+        goto done;
+    } else if (s->n_cache + 1 >= MAX_CACHE) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Too many invisible frames");
+        res = AVERROR_INVALIDDATA;
+        goto done;
+    }
+
+    s->cache[s->n_cache].size = in->size;
+    if (invisible && !uses_superframe_syntax) {
+        s->cache[s->n_cache].data = av_malloc(in->size);
+        if (!s->cache[s->n_cache].data) {
+            res = AVERROR(ENOMEM);
+            goto done;
+        }
+        memcpy(s->cache[s->n_cache++].data, in->data, in->size);
+        res = AVERROR(EAGAIN);
+        goto done;
+    }
+    av_assert0(s->n_cache > 0);
+
+    s->cache[s->n_cache].data = in->data;
+
+    // build superframe
+    if ((res = merge_superframe(s->cache, s->n_cache + 1, out)) < 0)
+        goto done;
+
+    for (n = 0; n < s->n_cache; n++)
+        av_freep(&s->cache[n].data);
+    s->n_cache = 0;
+
+    res = av_packet_copy_props(out, in);
+    if (res < 0)
+        goto done;
+
+done:
+    if (res < 0)
+        av_packet_unref(out);
+    av_packet_free(&in);
+    return res;
+}
+
+static void vp9_superframe_close(AVBSFContext *ctx)
+{
+    VP9BSFContext *s = ctx->priv_data;
+    int n;
+
+    // free cached data
+    for (n = 0; n < s->n_cache; n++)
+        av_freep(&s->cache[n].data);
+}
+
+static const enum AVCodecID codec_ids[] = {
+    AV_CODEC_ID_VP9, AV_CODEC_ID_NONE,
+};
+
+const AVBitStreamFilter ff_vp9_superframe_bsf = {
+    .name           = "vp9_superframe",
+    .priv_data_size = sizeof(VP9BSFContext),
+    .filter         = vp9_superframe_filter,
+    .close          = vp9_superframe_close,
+    .codec_ids      = codec_ids,
+};
diff --git a/libavcodec/vp9dsp.h b/libavcodec/vp9dsp.h
index 016a9bb..733f5bf 100644
--- a/libavcodec/vp9dsp.h
+++ b/libavcodec/vp9dsp.h
@@ -47,7 +47,7 @@ typedef struct VP9DSPContext {
      */
     // FIXME(rbultje) maybe replace left/top pointers with HAVE_TOP/
     // HAVE_LEFT/HAVE_TOPRIGHT flags instead, and then handle it in-place?
-    // also needs to fit in with what h264/vp8/etc do
+    // also needs to fit in with what H.264/VP8/etc do
     void (*intra_pred[N_TXFM_SIZES][N_INTRA_PRED_MODES])(uint8_t *dst,
                                                          ptrdiff_t stride,
                                                          const uint8_t *left,
diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c
index 3ed9652..81d50bb 100644
--- a/libavcodec/vqavideo.c
+++ b/libavcodec/vqavideo.c
@@ -1,6 +1,6 @@
 /*
  * Westwood Studios VQA Video Decoder
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index 5c2961f..e715c4b 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -196,7 +196,6 @@ typedef struct WebPContext {
     uint8_t *alpha_data;                /* alpha chunk data */
     int alpha_data_size;                /* alpha chunk data size */
     int has_exif;                       /* set after an EXIF chunk has been processed */
-    AVDictionary *exif_metadata;        /* EXIF chunk data */
     int width;                          /* image width */
     int height;                         /* image height */
     int lossless;                       /* indicates lossless or lossy */
@@ -1386,7 +1385,6 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         return AVERROR_INVALIDDATA;
     }
 
-    av_dict_free(&s->exif_metadata);
     while (bytestream2_get_bytes_left(&gb) > 8) {
         char chunk_str[5] = { 0 };
 
@@ -1463,6 +1461,7 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         }
         case MKTAG('E', 'X', 'I', 'F'): {
             int le, ifd_offset, exif_offset = bytestream2_tell(&gb);
+            AVDictionary *exif_metadata = NULL;
             GetByteContext exif_gb;
 
             if (s->has_exif) {
@@ -1484,15 +1483,15 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
             }
 
             bytestream2_seek(&exif_gb, ifd_offset, SEEK_SET);
-            if (avpriv_exif_decode_ifd(avctx, &exif_gb, le, 0, &s->exif_metadata) < 0) {
+            if (avpriv_exif_decode_ifd(avctx, &exif_gb, le, 0, &exif_metadata) < 0) {
                 av_log(avctx, AV_LOG_ERROR, "error decoding Exif data\n");
                 goto exif_end;
             }
 
-            av_dict_copy(avpriv_frame_get_metadatap(data), s->exif_metadata, 0);
+            av_dict_copy(avpriv_frame_get_metadatap(data), exif_metadata, 0);
 
 exif_end:
-            av_dict_free(&s->exif_metadata);
+            av_dict_free(&exif_metadata);
             bytestream2_skip(&gb, chunk_size);
             break;
         }
@@ -1501,7 +1500,7 @@ exif_end:
         case MKTAG('A', 'N', 'M', 'F'):
         case MKTAG('X', 'M', 'P', ' '):
             AV_WL32(chunk_str, chunk_type);
-            av_log(avctx, AV_LOG_VERBOSE, "skipping unsupported chunk: %s\n",
+            av_log(avctx, AV_LOG_WARNING, "skipping unsupported chunk: %s\n",
                    chunk_str);
             bytestream2_skip(&gb, chunk_size);
             break;
diff --git a/libavcodec/webvttdec.c b/libavcodec/webvttdec.c
index 7354588..7b2d175 100644
--- a/libavcodec/webvttdec.c
+++ b/libavcodec/webvttdec.c
@@ -85,15 +85,12 @@ static int webvtt_decode_frame(AVCodecContext *avctx,
     int ret = 0;
     AVSubtitle *sub = data;
     const char *ptr = avpkt->data;
+    FFASSDecoderContext *s = avctx->priv_data;
     AVBPrint buf;
 
     av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
-    if (ptr && avpkt->size > 0 && !webvtt_event_to_ass(&buf, ptr)) {
-        int ts_start     = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1,100});
-        int ts_duration  = avpkt->duration != -1 ?
-                           av_rescale_q(avpkt->duration, avctx->time_base, (AVRational){1,100}) : -1;
-        ret = ff_ass_add_rect_bprint(sub, &buf, ts_start, ts_duration);
-    }
+    if (ptr && avpkt->size > 0 && !webvtt_event_to_ass(&buf, ptr))
+        ret = ff_ass_add_rect(sub, buf.str, s->readorder++, 0, NULL, NULL);
     av_bprint_finalize(&buf, NULL);
     if (ret < 0)
         return ret;
@@ -108,4 +105,6 @@ AVCodec ff_webvtt_decoder = {
     .id             = AV_CODEC_ID_WEBVTT,
     .decode         = webvtt_decode_frame,
     .init           = ff_ass_subtitle_header_default,
+    .flush          = ff_ass_decoder_flush,
+    .priv_data_size = sizeof(FFASSDecoderContext),
 };
diff --git a/libavcodec/webvttenc.c b/libavcodec/webvttenc.c
index 9f67a2e..c84bbf4 100644
--- a/libavcodec/webvttenc.c
+++ b/libavcodec/webvttenc.c
@@ -159,21 +159,38 @@ static int webvtt_encode_frame(AVCodecContext *avctx,
 {
     WebVTTContext *s = avctx->priv_data;
     ASSDialog *dialog;
-    int i, num;
+    int i;
 
     av_bprint_clear(&s->buffer);
 
     for (i=0; i<sub->num_rects; i++) {
+        const char *ass = sub->rects[i]->ass;
+
         if (sub->rects[i]->type != SUBTITLE_ASS) {
             av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
             return AVERROR(ENOSYS);
         }
 
-        dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num);
+#if FF_API_ASS_TIMING
+        if (!strncmp(ass, "Dialogue: ", 10)) {
+            int num;
+            dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num);
+            // TODO reindent
         for (; dialog && num--; dialog++) {
             webvtt_style_apply(s, dialog->style);
             ff_ass_split_override_codes(&webvtt_callbacks, s, dialog->text);
         }
+        } else {
+#endif
+            dialog = ff_ass_split_dialog2(s->ass_ctx, ass);
+            if (!dialog)
+                return AVERROR(ENOMEM);
+            webvtt_style_apply(s, dialog->style);
+            ff_ass_split_override_codes(&webvtt_callbacks, s, dialog->text);
+            ff_ass_free_dialog(&dialog);
+#if FF_API_ASS_TIMING
+        }
+#endif
     }
 
     if (!av_bprint_is_complete(&s->buffer))
diff --git a/libavcodec/wma.c b/libavcodec/wma.c
index 6d1c7e5..bc8e2d1 100644
--- a/libavcodec/wma.c
+++ b/libavcodec/wma.c
@@ -429,7 +429,7 @@ unsigned int ff_wma_get_large_val(GetBitContext *gb)
  * @param version 0 for wma1,2 1 for wmapro
  * @param ptr output buffer
  * @param offset offset in the output buffer
- * @param num_coefs number of input coefficents
+ * @param num_coefs number of input coefficients
  * @param block_len input buffer length (2^n)
  * @param frame_len_bits number of bits for escaped run codes
  * @param coef_nb_bits number of bits for escaped level codes
diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c
index 1a84323..78b51e5 100644
--- a/libavcodec/wmadec.c
+++ b/libavcodec/wmadec.c
@@ -34,8 +34,7 @@
  */
 
 #include "libavutil/attributes.h"
-#include "libavutil/internal.h"
-#include "libavutil/libm.h"
+#include "libavutil/ffmath.h"
 
 #include "avcodec.h"
 #include "internal.h"
@@ -81,7 +80,7 @@ static av_cold int wma_decode_init(AVCodecContext *avctx)
 
     s->avctx = avctx;
 
-    /* extract flag infos */
+    /* extract flag info */
     flags2    = 0;
     extradata = avctx->extradata;
     if (avctx->codec->id == AV_CODEC_ID_WMAV1 && avctx->extradata_size >= 4)
@@ -350,7 +349,7 @@ static int decode_exp_vlc(WMACodecContext *s, int ch)
             av_log(s->avctx, AV_LOG_ERROR, "Exponent vlc invalid\n");
             return -1;
         }
-        /* NOTE: this offset is the same as MPEG4 AAC ! */
+        /* NOTE: this offset is the same as MPEG-4 AAC! */
         last_exp += code - 60;
         if ((unsigned) last_exp + 60 >= FF_ARRAY_ELEMS(pow_tab)) {
             av_log(s->avctx, AV_LOG_ERROR, "Exponent out of range: %d\n",
@@ -427,7 +426,7 @@ static void wma_window(WMACodecContext *s, float *out)
 
 /**
  * @return 0 if OK. 1 if last block of frame. return -1 if
- * unrecorrable error.
+ * unrecoverable error.
  */
 static int wma_decode_block(WMACodecContext *s)
 {
diff --git a/libavcodec/wmaenc.c b/libavcodec/wmaenc.c
index d0727e6..c68babd 100644
--- a/libavcodec/wmaenc.c
+++ b/libavcodec/wmaenc.c
@@ -20,7 +20,7 @@
  */
 
 #include "libavutil/attributes.h"
-#include "libavutil/internal.h"
+#include "libavutil/ffmath.h"
 
 #include "avcodec.h"
 #include "internal.h"
@@ -57,7 +57,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
         return AVERROR(EINVAL);
     }
 
-    /* extract flag infos */
+    /* extract flag info */
     flags1 = 0;
     flags2 = 1;
     if (avctx->codec->id == AV_CODEC_ID_WMAV1) {
diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c
index 8a5ffb8..6b4edfc 100644
--- a/libavcodec/wmalosslessdec.c
+++ b/libavcodec/wmalosslessdec.c
@@ -72,7 +72,8 @@ typedef struct WmallDecodeCtx {
     AVCodecContext  *avctx;
     AVFrame         *frame;
     LLAudDSPContext dsp;                           ///< accelerated DSP functions
-    uint8_t         frame_data[MAX_FRAMESIZE + AV_INPUT_BUFFER_PADDING_SIZE];  ///< compressed frame data
+    uint8_t         *frame_data;                    ///< compressed frame data
+    int             max_frame_size;                 ///< max bitstream size
     PutBitContext   pb;                             ///< context for filling the frame_data buffer
 
     /* frame size dependent frame information (set during initialization) */
@@ -104,8 +105,8 @@ typedef struct WmallDecodeCtx {
     uint32_t        frame_num;                      ///< current frame number (not used for decoding)
     GetBitContext   gb;                             ///< bitstream reader context
     int             buf_bit_size;                   ///< buffer size in bits
-    int16_t         *samples_16[WMALL_MAX_CHANNELS]; ///< current samplebuffer pointer (16-bit)
-    int32_t         *samples_32[WMALL_MAX_CHANNELS]; ///< current samplebuffer pointer (24-bit)
+    int16_t         *samples_16[WMALL_MAX_CHANNELS]; ///< current sample buffer pointer (16-bit)
+    int32_t         *samples_32[WMALL_MAX_CHANNELS]; ///< current sample buffer pointer (24-bit)
     uint8_t         drc_gain;                       ///< gain for the DRC tool
     int8_t          skip_frame;                     ///< skip output step
     int8_t          parsed_all_subframes;           ///< all subframes decoded?
@@ -134,8 +135,8 @@ typedef struct WmallDecodeCtx {
     int8_t  mclms_scaling;
     int16_t mclms_coeffs[WMALL_MAX_CHANNELS * WMALL_MAX_CHANNELS * 32];
     int16_t mclms_coeffs_cur[WMALL_MAX_CHANNELS * WMALL_MAX_CHANNELS];
-    int16_t mclms_prevvalues[WMALL_MAX_CHANNELS * 2 * 32];
-    int16_t mclms_updates[WMALL_MAX_CHANNELS * 2 * 32];
+    int32_t mclms_prevvalues[WMALL_MAX_CHANNELS * 2 * 32];
+    int32_t mclms_updates[WMALL_MAX_CHANNELS * 2 * 32];
     int     mclms_recent;
 
     int     movave_scaling;
@@ -147,7 +148,7 @@ typedef struct WmallDecodeCtx {
         int coefsend;
         int bitsend;
         DECLARE_ALIGNED(16, int16_t, coefs)[MAX_ORDER + WMALL_COEFF_PAD_SIZE/sizeof(int16_t)];
-        DECLARE_ALIGNED(16, int16_t, lms_prevvalues)[MAX_ORDER * 2 + WMALL_COEFF_PAD_SIZE/sizeof(int16_t)];
+        DECLARE_ALIGNED(16, int32_t, lms_prevvalues)[MAX_ORDER * 2 + WMALL_COEFF_PAD_SIZE/sizeof(int16_t)];
         DECLARE_ALIGNED(16, int16_t, lms_updates)[MAX_ORDER * 2 + WMALL_COEFF_PAD_SIZE/sizeof(int16_t)];
         int recent;
     } cdlms[WMALL_MAX_CHANNELS][9];
@@ -171,8 +172,6 @@ typedef struct WmallDecodeCtx {
     int lpc_order;
     int lpc_scaling;
     int lpc_intbits;
-
-    int channel_coeffs[WMALL_MAX_CHANNELS][WMALL_BLOCK_MAX_SIZE];
 } WmallDecodeCtx;
 
 /** Get sign of integer (1 for positive, -1 for negative and 0 for zero) */
@@ -190,9 +189,14 @@ static av_cold int decode_init(AVCodecContext *avctx)
         return AVERROR(EINVAL);
     }
 
+    s->max_frame_size = MAX_FRAMESIZE * avctx->channels;
+    s->frame_data = av_mallocz(s->max_frame_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!s->frame_data)
+        return AVERROR(ENOMEM);
+
     s->avctx = avctx;
     ff_llauddsp_init(&s->dsp);
-    init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
+    init_put_bits(&s->pb, s->frame_data, s->max_frame_size);
 
     if (avctx->extradata_size >= 18) {
         s->decode_flags    = AV_RL16(edata_ptr + 14);
@@ -464,7 +468,7 @@ static int decode_cdlms(WmallDecodeCtx *s)
                 s->cdlms[0][0].order = 0;
                 return AVERROR_INVALIDDATA;
             }
-            if(s->cdlms[c][i].order & 8) {
+            if(s->cdlms[c][i].order & 8 && s->bits_per_sample == 16) {
                 static int warned;
                 if(!warned)
                     avpriv_request_sample(s->avctx, "CDLMS of order %d",
@@ -651,10 +655,10 @@ static void mclms_update(WmallDecodeCtx *s, int icoef, int *pred)
     if (s->mclms_recent == 0) {
         memcpy(&s->mclms_prevvalues[order * num_channels],
                s->mclms_prevvalues,
-               sizeof(int16_t) * order * num_channels);
+               sizeof(int32_t) * order * num_channels);
         memcpy(&s->mclms_updates[order * num_channels],
                s->mclms_updates,
-               sizeof(int16_t) * order * num_channels);
+               sizeof(int32_t) * order * num_channels);
         s->mclms_recent = num_channels * order;
     }
 }
@@ -670,10 +674,10 @@ static void mclms_predict(WmallDecodeCtx *s, int icoef, int *pred)
         if (!s->is_channel_coded[ich])
             continue;
         for (i = 0; i < order * num_channels; i++)
-            pred[ich] += s->mclms_prevvalues[i + s->mclms_recent] *
+            pred[ich] += (uint32_t)s->mclms_prevvalues[i + s->mclms_recent] *
                          s->mclms_coeffs[i + order * num_channels * ich];
         for (i = 0; i < ich; i++)
-            pred[ich] += s->channel_residues[i][icoef] *
+            pred[ich] += (uint32_t)s->channel_residues[i][icoef] *
                          s->mclms_coeffs_cur[i + num_channels * ich];
         pred[ich] += 1 << s->mclms_scaling - 1;
         pred[ich] >>= s->mclms_scaling;
@@ -690,32 +694,6 @@ static void revert_mclms(WmallDecodeCtx *s, int tile_size)
     }
 }
 
-static void lms_update(WmallDecodeCtx *s, int ich, int ilms, int input)
-{
-    int recent = s->cdlms[ich][ilms].recent;
-    int range  = 1 << s->bits_per_sample - 1;
-    int order  = s->cdlms[ich][ilms].order;
-
-    if (recent)
-        recent--;
-    else {
-        memcpy(s->cdlms[ich][ilms].lms_prevvalues + order,
-               s->cdlms[ich][ilms].lms_prevvalues, sizeof(*s->cdlms[ich][ilms].lms_prevvalues) * order);
-        memcpy(s->cdlms[ich][ilms].lms_updates + order,
-               s->cdlms[ich][ilms].lms_updates, sizeof(*s->cdlms[ich][ilms].lms_updates) * order);
-        recent = order - 1;
-    }
-
-    s->cdlms[ich][ilms].lms_prevvalues[recent] = av_clip(input, -range, range - 1);
-    s->cdlms[ich][ilms].lms_updates[recent] = WMASIGN(input) * s->update_speed[ich];
-
-    s->cdlms[ich][ilms].lms_updates[recent + (order >> 4)] >>= 2;
-    s->cdlms[ich][ilms].lms_updates[recent + (order >> 3)] >>= 1;
-    s->cdlms[ich][ilms].recent = recent;
-    memset(s->cdlms[ich][ilms].lms_updates + recent + order, 0,
-           sizeof(s->cdlms[ich][ilms].lms_updates) - 2*(recent+order));
-}
-
 static void use_high_update_speed(WmallDecodeCtx *s, int ich)
 {
     int ilms, recent, icoef;
@@ -751,32 +729,63 @@ static void use_normal_update_speed(WmallDecodeCtx *s, int ich)
     s->update_speed[ich] = 8;
 }
 
-static void revert_cdlms(WmallDecodeCtx *s, int ch,
-                         int coef_begin, int coef_end)
-{
-    int icoef, pred, ilms, num_lms, residue, input;
-
-    num_lms = s->cdlms_ttl[ch];
-    for (ilms = num_lms - 1; ilms >= 0; ilms--) {
-        for (icoef = coef_begin; icoef < coef_end; icoef++) {
-            pred = 1 << (s->cdlms[ch][ilms].scaling - 1);
-            residue = s->channel_residues[ch][icoef];
-            pred += s->dsp.scalarproduct_and_madd_int16(s->cdlms[ch][ilms].coefs,
-                                                        s->cdlms[ch][ilms].lms_prevvalues
-                                                            + s->cdlms[ch][ilms].recent,
-                                                        s->cdlms[ch][ilms].lms_updates
-                                                            + s->cdlms[ch][ilms].recent,
-                                                        FFALIGN(s->cdlms[ch][ilms].order,
-                                                                WMALL_COEFF_PAD_SIZE),
-                                                        WMASIGN(residue));
-            input = residue + (pred >> s->cdlms[ch][ilms].scaling);
-            lms_update(s, ch, ilms, input);
-            s->channel_residues[ch][icoef] = input;
-        }
-    }
-    emms_c();
+#define CD_LMS(bits, ROUND) \
+static void lms_update ## bits (WmallDecodeCtx *s, int ich, int ilms, int input) \
+{ \
+    int recent = s->cdlms[ich][ilms].recent; \
+    int range  = 1 << s->bits_per_sample - 1; \
+    int order  = s->cdlms[ich][ilms].order; \
+    int ##bits##_t *prev = (int##bits##_t *)s->cdlms[ich][ilms].lms_prevvalues; \
+ \
+    if (recent) \
+        recent--; \
+    else { \
+        memcpy(prev + order, prev, (bits/8) * order); \
+        memcpy(s->cdlms[ich][ilms].lms_updates + order, \
+               s->cdlms[ich][ilms].lms_updates, \
+               sizeof(*s->cdlms[ich][ilms].lms_updates) * order); \
+        recent = order - 1; \
+    } \
+ \
+    prev[recent] = av_clip(input, -range, range - 1); \
+    s->cdlms[ich][ilms].lms_updates[recent] = WMASIGN(input) * s->update_speed[ich]; \
+ \
+    s->cdlms[ich][ilms].lms_updates[recent + (order >> 4)] >>= 2; \
+    s->cdlms[ich][ilms].lms_updates[recent + (order >> 3)] >>= 1; \
+    s->cdlms[ich][ilms].recent = recent; \
+    memset(s->cdlms[ich][ilms].lms_updates + recent + order, 0, \
+           sizeof(s->cdlms[ich][ilms].lms_updates) - \
+           sizeof(*s->cdlms[ich][ilms].lms_updates)*(recent+order)); \
+} \
+ \
+static void revert_cdlms ## bits (WmallDecodeCtx *s, int ch, \
+                                  int coef_begin, int coef_end) \
+{ \
+    int icoef, pred, ilms, num_lms, residue, input; \
+ \
+    num_lms = s->cdlms_ttl[ch]; \
+    for (ilms = num_lms - 1; ilms >= 0; ilms--) { \
+        for (icoef = coef_begin; icoef < coef_end; icoef++) { \
+            int##bits##_t *prevvalues = (int##bits##_t *)s->cdlms[ch][ilms].lms_prevvalues; \
+            pred = 1 << (s->cdlms[ch][ilms].scaling - 1); \
+            residue = s->channel_residues[ch][icoef]; \
+            pred += s->dsp.scalarproduct_and_madd_int## bits (s->cdlms[ch][ilms].coefs, \
+                                                        prevvalues + s->cdlms[ch][ilms].recent, \
+                                                        s->cdlms[ch][ilms].lms_updates + \
+                                                        s->cdlms[ch][ilms].recent, \
+                                                        FFALIGN(s->cdlms[ch][ilms].order, ROUND), \
+                                                        WMASIGN(residue)); \
+            input = residue + (pred >> s->cdlms[ch][ilms].scaling); \
+            lms_update ## bits(s, ch, ilms, input); \
+            s->channel_residues[ch][icoef] = input; \
+        } \
+    } \
+    if (bits <= 16) emms_c(); \
 }
 
+CD_LMS(16, WMALL_COEFF_PAD_SIZE)
+CD_LMS(32, 8)
+
 static void revert_inter_ch_decorr(WmallDecodeCtx *s, int tile_size)
 {
     if (s->num_channels != 2)
@@ -813,7 +822,7 @@ static void revert_acfilter(WmallDecodeCtx *s, int tile_size)
         for (i = order; i < tile_size; i++) {
             pred = 0;
             for (j = 0; j < order; j++)
-                pred += s->channel_residues[ich][i - j - 1] * filter_coeffs[j];
+                pred += (uint32_t)s->channel_residues[ich][i - j - 1] * filter_coeffs[j];
             pred >>= scaling;
             s->channel_residues[ich][i] += pred;
         }
@@ -891,14 +900,17 @@ static int decode_subframe(WmallDecodeCtx *s)
         s->quant_stepsize = get_bits(&s->gb, 8) + 1;
 
         reset_codec(s);
-    } else if (!s->cdlms[0][0].order) {
+    }
+
+    rawpcm_tile = get_bits1(&s->gb);
+
+    if (!rawpcm_tile && !s->cdlms[0][0].order) {
         av_log(s->avctx, AV_LOG_DEBUG,
                "Waiting for seekable tile\n");
         av_frame_unref(s->frame);
         return -1;
     }
 
-    rawpcm_tile = get_bits1(&s->gb);
 
     for (i = 0; i < s->num_channels; i++)
         s->is_channel_coded[i] = 1;
@@ -937,32 +949,37 @@ static int decode_subframe(WmallDecodeCtx *s)
                 bits * s->num_channels * subframe_len, get_bits_count(&s->gb));
         for (i = 0; i < s->num_channels; i++)
             for (j = 0; j < subframe_len; j++)
-                s->channel_coeffs[i][j] = get_sbits_long(&s->gb, bits);
+                s->channel_residues[i][j] = get_sbits_long(&s->gb, bits);
     } else {
-        for (i = 0; i < s->num_channels; i++)
+        for (i = 0; i < s->num_channels; i++) {
             if (s->is_channel_coded[i]) {
                 decode_channel_residues(s, i, subframe_len);
                 if (s->seekable_tile)
                     use_high_update_speed(s, i);
                 else
                     use_normal_update_speed(s, i);
-                revert_cdlms(s, i, 0, subframe_len);
+                if (s->bits_per_sample > 16)
+                    revert_cdlms32(s, i, 0, subframe_len);
+                else
+                    revert_cdlms16(s, i, 0, subframe_len);
             } else {
                 memset(s->channel_residues[i], 0, sizeof(**s->channel_residues) * subframe_len);
             }
+        }
+
+        if (s->do_mclms)
+            revert_mclms(s, subframe_len);
+        if (s->do_inter_ch_decorr)
+            revert_inter_ch_decorr(s, subframe_len);
+        if (s->do_ac_filter)
+            revert_acfilter(s, subframe_len);
+
+        /* Dequantize */
+        if (s->quant_stepsize != 1)
+            for (i = 0; i < s->num_channels; i++)
+                for (j = 0; j < subframe_len; j++)
+                    s->channel_residues[i][j] *= s->quant_stepsize;
     }
-    if (s->do_mclms)
-        revert_mclms(s, subframe_len);
-    if (s->do_inter_ch_decorr)
-        revert_inter_ch_decorr(s, subframe_len);
-    if (s->do_ac_filter)
-        revert_acfilter(s, subframe_len);
-
-    /* Dequantize */
-    if (s->quant_stepsize != 1)
-        for (i = 0; i < s->num_channels; i++)
-            for (j = 0; j < subframe_len; j++)
-                s->channel_residues[i][j] *= s->quant_stepsize;
 
     /* Write to proper output buffer depending on bit-depth */
     for (i = 0; i < s->channels_for_cur_subframe; i++) {
@@ -1043,6 +1060,9 @@ static int decode_frame(WmallDecodeCtx *s)
         if (get_bits1(gb)) {
             skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
             ff_dlog(s->avctx, "end skip: %i\n", skip);
+            s->frame->nb_samples -= skip;
+            if (s->frame->nb_samples <= 0)
+                return AVERROR_INVALIDDATA;
         }
 
     }
@@ -1121,12 +1141,12 @@ static void save_bits(WmallDecodeCtx *s, GetBitContext* gb, int len,
     if (!append) {
         s->frame_offset   = get_bits_count(gb) & 7;
         s->num_saved_bits = s->frame_offset;
-        init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
+        init_put_bits(&s->pb, s->frame_data, s->max_frame_size);
     }
 
     buflen = (s->num_saved_bits + len + 8) >> 3;
 
-    if (len <= 0 || buflen > MAX_FRAMESIZE) {
+    if (len <= 0 || buflen > s->max_frame_size) {
         avpriv_request_sample(s->avctx, "Too small input buffer");
         s->packet_loss = 1;
         return;
@@ -1163,25 +1183,24 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr,
 
     s->frame->nb_samples = 0;
 
-    if (s->packet_done || s->packet_loss) {
+    if (!buf_size && s->num_saved_bits > get_bits_count(&s->gb)) {
+        s->packet_done = 0;
+        if (!decode_frame(s))
+            s->num_saved_bits = 0;
+    } else if (s->packet_done || s->packet_loss) {
         s->packet_done = 0;
 
         if (!buf_size)
             return 0;
-        /* sanity check for the buffer length */
-        if (buf_size < avctx->block_align) {
-            av_log(avctx, AV_LOG_ERROR, "buf size %d invalid\n", buf_size);
-            return AVERROR_INVALIDDATA;
-        }
 
-        s->next_packet_start = buf_size - avctx->block_align;
-        buf_size             = avctx->block_align;
+        s->next_packet_start = buf_size - FFMIN(avctx->block_align, buf_size);
+        buf_size             = FFMIN(avctx->block_align, buf_size);
         s->buf_bit_size      = buf_size << 3;
 
         /* parse packet header */
         init_get_bits(gb, buf, s->buf_bit_size);
         packet_sequence_number = get_bits(gb, 4);
-        skip_bits(gb, 1);   // Skip seekable_frame_in_packet, currently ununused
+        skip_bits(gb, 1);   // Skip seekable_frame_in_packet, currently unused
         spliced_packet = get_bits1(gb);
         if (spliced_packet)
             avpriv_request_sample(avctx, "Bitstream splicing");
@@ -1223,7 +1242,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr,
              * to decode incomplete frames in the s->len_prefix == 0 case. */
             s->num_saved_bits = 0;
             s->packet_loss    = 0;
-            init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
+            init_put_bits(&s->pb, s->frame_data, s->max_frame_size);
         }
 
     } else {
@@ -1264,7 +1283,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr,
 
     s->packet_offset = get_bits_count(gb) & 7;
 
-    return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3;
+    return (s->packet_loss) ? AVERROR_INVALIDDATA : buf_size ? get_bits_count(gb) >> 3 : 0;
 }
 
 static void flush(AVCodecContext *avctx)
@@ -1277,7 +1296,7 @@ static void flush(AVCodecContext *avctx)
     s->next_packet_start = 0;
     s->cdlms[0][0].order = 0;
     s->frame->nb_samples = 0;
-    init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
+    init_put_bits(&s->pb, s->frame_data, s->max_frame_size);
 }
 
 static av_cold int decode_close(AVCodecContext *avctx)
@@ -1285,6 +1304,7 @@ static av_cold int decode_close(AVCodecContext *avctx)
     WmallDecodeCtx *s = avctx->priv_data;
 
     av_frame_free(&s->frame);
+    av_freep(&s->frame_data);
 
     return 0;
 }
diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c
index 2ea59e9..2cc1b09 100644
--- a/libavcodec/wmaprodec.c
+++ b/libavcodec/wmaprodec.c
@@ -88,8 +88,8 @@
 
 #include <inttypes.h>
 
+#include "libavutil/ffmath.h"
 #include "libavutil/float_dsp.h"
-#include "libavutil/internal.h"
 #include "libavutil/intfloat.h"
 #include "libavutil/intreadwrite.h"
 #include "avcodec.h"
diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c
index 029dfdd..ceac61f 100644
--- a/libavcodec/wmavoice.c
+++ b/libavcodec/wmavoice.c
@@ -1193,7 +1193,7 @@ static void aw_pulse_set1(WMAVoiceContext *s, GetBitContext *gb,
 /**
  * @}
  *
- * Generate a random number from frame_cntr and block_idx, which will lief
+ * Generate a random number from frame_cntr and block_idx, which will live
  * in the range [0, 1000 - block_size] (so it can be used as an index in a
  * table of size 1000 of which you want to read block_size entries).
  *
@@ -1516,7 +1516,7 @@ static int synth_frame(AVCodecContext *ctx, GetBitContext *gb, int frame_idx,
             /* Pitch is given per block. Per-block pitches are encoded as an
              * absolute value for the first block, and then delta values
              * relative to this value) for all subsequent blocks. The scale of
-             * this pitch value is semi-logaritmic compared to its use in the
+             * this pitch value is semi-logarithmic compared to its use in the
              * decoder, so we convert it to normal scale also. */
             int block_pitch,
                 t1 = (s->block_conv_table[1] - s->block_conv_table[0]) << 2,
diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c
index 9c3acbc..327c5bd 100644
--- a/libavcodec/wmv2.c
+++ b/libavcodec/wmv2.c
@@ -25,6 +25,7 @@
 #include "msmpeg4data.h"
 #include "simple_idct.h"
 #include "wmv2.h"
+#include "wmv2data.h"
 
 
 av_cold void ff_wmv2_common_init(Wmv2Context *w)
diff --git a/libavcodec/wmv2data.c b/libavcodec/wmv2data.c
new file mode 100644
index 0000000..e858572
--- /dev/null
+++ b/libavcodec/wmv2data.c
@@ -0,0 +1,35 @@
+/*
+ * 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 <stdint.h>
+
+#include "wmv2data.h"
+
+const uint8_t ff_wmv2_scantableA[64] = {
+    0x00, 0x01, 0x02, 0x08, 0x03, 0x09, 0x0A, 0x10,
+    0x04, 0x0B, 0x11, 0x18, 0x12, 0x0C, 0x05, 0x13,
+    0x19, 0x0D, 0x14, 0x1A, 0x1B, 0x06, 0x15, 0x1C,
+    0x0E, 0x16, 0x1D, 0x07, 0x1E, 0x0F, 0x17, 0x1F,
+};
+
+const uint8_t ff_wmv2_scantableB[64] = {
+    0x00, 0x08, 0x01, 0x10, 0x09, 0x18, 0x11, 0x02,
+    0x20, 0x0A, 0x19, 0x28, 0x12, 0x30, 0x21, 0x1A,
+    0x38, 0x29, 0x22, 0x03, 0x31, 0x39, 0x0B, 0x2A,
+    0x13, 0x32, 0x1B, 0x3A, 0x23, 0x2B, 0x33, 0x3B,
+};
diff --git a/libavcodec/wmv2data.h b/libavcodec/wmv2data.h
new file mode 100644
index 0000000..178346a
--- /dev/null
+++ b/libavcodec/wmv2data.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_WMV2DATA_H
+#define AVCODEC_WMV2DATA_H
+
+#include <stdint.h>
+
+extern const uint8_t ff_wmv2_scantableA[64];
+extern const uint8_t ff_wmv2_scantableB[64];
+
+#endif /* AVCODEC_WMV2DATA_H */
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 99c95d3..20dbee5 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -219,7 +219,14 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s)
     s->picture_number++; // FIXME ?
 
     if (w->j_type) {
-        ff_intrax8_decode_picture(&w->x8, 2 * s->qscale, (s->qscale - 1) | 1);
+        ff_intrax8_decode_picture(&w->x8, &s->current_picture,
+                                  &s->gb, &s->mb_x, &s->mb_y,
+                                  2 * s->qscale, (s->qscale - 1) | 1,
+                                  s->loop_filter, s->low_delay);
+
+        ff_er_add_slice(&w->s.er, 0, 0,
+                        (w->s.mb_x >> 1) - 1, (w->s.mb_y >> 1) - 1,
+                        ER_MB_END);
         return 1;
     }
 
@@ -462,9 +469,9 @@ static av_cold int wmv2_decode_init(AVCodecContext *avctx)
 
     ff_wmv2_common_init(w);
 
-    ff_intrax8_common_init(&w->x8, &w->s);
-
-    return 0;
+    return ff_intrax8_common_init(avctx, &w->x8, &w->s.idsp,
+                                  w->s.block, w->s.block_last_index,
+                                  w->s.mb_width, w->s.mb_height);
 }
 
 static av_cold int wmv2_decode_end(AVCodecContext *avctx)
diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c
index 3ed8b5f..74ae12b 100644
--- a/libavcodec/wmv2enc.c
+++ b/libavcodec/wmv2enc.c
@@ -81,7 +81,7 @@ int ff_wmv2_encode_picture_header(MpegEncContext *s, int picture_number)
     put_bits(&s->pb, 5, s->qscale);
 
     s->dc_table_index  = 1;
-    s->mv_table_index  = 1; /* only if P frame */
+    s->mv_table_index  = 1; /* only if P-frame */
     s->per_mb_rl_table = 0;
     s->mspel           = 0;
     w->per_mb_abt      = 0;
diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile
index 668a9be..839b5bc 100644
--- a/libavcodec/x86/Makefile
+++ b/libavcodec/x86/Makefile
@@ -33,6 +33,7 @@ OBJS-$(CONFIG_MPEGVIDEOENC)            += x86/mpegvideoenc.o           \
 OBJS-$(CONFIG_PIXBLOCKDSP)             += x86/pixblockdsp_init.o
 OBJS-$(CONFIG_QPELDSP)                 += x86/qpeldsp_init.o
 OBJS-$(CONFIG_RV34DSP)                 += x86/rv34dsp_init.o
+OBJS-$(CONFIG_VC1DSP)                  += x86/vc1dsp_init.o
 OBJS-$(CONFIG_VIDEODSP)                += x86/videodsp_init.o
 OBJS-$(CONFIG_VP3DSP)                  += x86/vp3dsp_init.o
 OBJS-$(CONFIG_VP8DSP)                  += x86/vp8dsp_init.o
@@ -62,7 +63,6 @@ OBJS-$(CONFIG_TRUEHD_DECODER)          += x86/mlpdsp_init.o
 OBJS-$(CONFIG_TTA_DECODER)             += x86/ttadsp_init.o
 OBJS-$(CONFIG_V210_DECODER)            += x86/v210-init.o
 OBJS-$(CONFIG_V210_ENCODER)            += x86/v210enc_init.o
-OBJS-$(CONFIG_VC1_DECODER)             += x86/vc1dsp_init.o
 OBJS-$(CONFIG_VORBIS_DECODER)          += x86/vorbisdsp_init.o
 OBJS-$(CONFIG_VP6_DECODER)             += x86/vp6dsp_init.o
 OBJS-$(CONFIG_VP9_DECODER)             += x86/vp9dsp_init.o            \
@@ -76,11 +76,11 @@ OBJS-$(CONFIG_WEBP_DECODER)            += x86/vp8dsp_init.o
 # subsystems
 MMX-OBJS-$(CONFIG_FDCTDSP)             += x86/fdct.o
 MMX-OBJS-$(CONFIG_IDCTDSP)             += x86/simple_idct.o
+MMX-OBJS-$(CONFIG_VC1DSP)              += x86/vc1dsp_mmx.o
 
 # decoders/encoders
 MMX-OBJS-$(CONFIG_SNOW_DECODER)        += x86/snowdsp.o
 MMX-OBJS-$(CONFIG_SNOW_ENCODER)        += x86/snowdsp.o
-MMX-OBJS-$(CONFIG_VC1_DECODER)         += x86/vc1dsp_mmx.o
 
 # subsystems
 YASM-OBJS-$(CONFIG_AC3DSP)             += x86/ac3dsp.o
@@ -120,6 +120,8 @@ YASM-OBJS-$(CONFIG_QPELDSP)            += x86/qpeldsp.o                 \
                                           x86/fpel.o                    \
                                           x86/qpel.o
 YASM-OBJS-$(CONFIG_RV34DSP)            += x86/rv34dsp.o
+YASM-OBJS-$(CONFIG_VC1DSP)             += x86/vc1dsp_loopfilter.o       \
+                                          x86/vc1dsp_mc.o
 YASM-OBJS-$(CONFIG_IDCTDSP)            += x86/simple_idct10.o
 YASM-OBJS-$(CONFIG_VIDEODSP)           += x86/videodsp.o
 YASM-OBJS-$(CONFIG_VP3DSP)             += x86/vp3dsp.o
@@ -160,7 +162,6 @@ YASM-OBJS-$(CONFIG_TRUEHD_DECODER)     += x86/mlpdsp.o
 YASM-OBJS-$(CONFIG_TTA_DECODER)        += x86/ttadsp.o
 YASM-OBJS-$(CONFIG_V210_ENCODER)       += x86/v210enc.o
 YASM-OBJS-$(CONFIG_V210_DECODER)       += x86/v210.o
-YASM-OBJS-$(CONFIG_VC1_DECODER)        += x86/vc1dsp.o
 YASM-OBJS-$(CONFIG_VORBIS_DECODER)     += x86/vorbisdsp.o
 YASM-OBJS-$(CONFIG_VP6_DECODER)        += x86/vp6dsp.o
 YASM-OBJS-$(CONFIG_VP9_DECODER)        += x86/vp9intrapred.o            \
diff --git a/libavcodec/x86/aacpsdsp.asm b/libavcodec/x86/aacpsdsp.asm
index d1187df..e92cbbc 100644
--- a/libavcodec/x86/aacpsdsp.asm
+++ b/libavcodec/x86/aacpsdsp.asm
@@ -33,35 +33,29 @@ SECTION .text
 ;*************************************************************************
 %macro PS_ADD_SQUARES 1
 cglobal ps_add_squares, 3, 3, %1, dst, src, n
+    shl    nd, 3
+    add  srcq, nq
+    neg    nq
+
+align 16
 .loop:
-    movaps m0, [srcq]
-    movaps m1, [srcq+mmsize]
+    movaps m0, [srcq+nq]
+    movaps m1, [srcq+nq+mmsize]
     mulps  m0, m0
     mulps  m1, m1
-%if cpuflag(sse3)
-    haddps m0, m1
-%else
-    movaps m3, m0
-    movaps m4, m1
-    shufps m3, m3, q0301
-    shufps m4, m4, q0301
-    addps  m0, m3
-    addps  m1, m4
-    shufps m0, m1, q2020
-%endif
+    HADDPS m0, m1, m2
     addps  m0, [dstq]
     movaps [dstq], m0
     add  dstq, mmsize
-    add  srcq, mmsize*2
-    sub    nd, mmsize/4
-    jg .loop
+    add    nq, mmsize*2
+    jl .loop
     REP_RET
 %endmacro
 
 INIT_XMM sse
-PS_ADD_SQUARES 3
+PS_ADD_SQUARES 2
 INIT_XMM sse3
-PS_ADD_SQUARES 5
+PS_ADD_SQUARES 3
 
 ;*******************************************************************
 ;void ff_ps_mul_pair_single_sse(float (*dst)[2], float (*src0)[2],
diff --git a/libavcodec/x86/audiodsp_init.c b/libavcodec/x86/audiodsp_init.c
index a2ce231..8f9e604 100644
--- a/libavcodec/x86/audiodsp_init.c
+++ b/libavcodec/x86/audiodsp_init.c
@@ -21,7 +21,6 @@
 #include "config.h"
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/audiodsp.h"
 
diff --git a/libavcodec/x86/cabac.h b/libavcodec/x86/cabac.h
index 3510336..4795f5b 100644
--- a/libavcodec/x86/cabac.h
+++ b/libavcodec/x86/cabac.h
@@ -62,7 +62,7 @@
         "sub    "tmp"       , "low"                        \n\t"
 #else /* HAVE_FAST_CMOV */
 #define BRANCHLESS_GET_CABAC_UPDATE(ret, retq, low, range, tmp) \
-/* P4 Prescott has crappy cmov,sbb,64bit shift so avoid them */ \
+/* P4 Prescott has crappy cmov,sbb,64-bit shift so avoid them */ \
         "sub    "low"       , "tmp"                        \n\t"\
         "sar    $31         , "tmp"                        \n\t"\
         "sub    %%ecx       , "range"                      \n\t"\
diff --git a/libavcodec/x86/dcadsp.asm b/libavcodec/x86/dcadsp.asm
index fb13957..c5bf21a 100644
--- a/libavcodec/x86/dcadsp.asm
+++ b/libavcodec/x86/dcadsp.asm
@@ -201,3 +201,82 @@ LFE_FIR0_FLOAT
 INIT_XMM fma3
 LFE_FIR0_FLOAT
 %endif
+
+%macro LFE_FIR1_FLOAT 0
+cglobal lfe_fir1_float, 4, 6, 10, samples, lfe, coeff, nblocks, cnt1, cnt2
+    shr nblocksd, 2
+    sub     lfeq, 3*sizeof_float
+    mov    cnt1d, 64*sizeof_float
+    mov    cnt2d, 64*sizeof_float-16
+    lea   coeffq, [coeffq+cnt1q*4]
+    add samplesq, cnt1q
+    neg    cnt1q
+
+.loop:
+%if cpuflag(avx)
+    cvtdq2ps  m4, [lfeq]
+    shufps    m5, m4, m4, q0123
+%elif cpuflag(sse2)
+    movu      m4, [lfeq]
+    cvtdq2ps  m4, m4
+    pshufd    m5, m4, q0123
+%endif
+
+.inner_loop:
+    movaps    m6, [coeffq+cnt1q*4   ]
+    movaps    m7, [coeffq+cnt1q*4+16]
+    mulps     m0, m5, m6
+    mulps     m1, m5, m7
+%if ARCH_X86_64
+    movaps    m8, [coeffq+cnt1q*4+32]
+    movaps    m9, [coeffq+cnt1q*4+48]
+    mulps     m2, m5, m8
+    mulps     m3, m5, m9
+%else
+    mulps     m2, m5, [coeffq+cnt1q*4+32]
+    mulps     m3, m5, [coeffq+cnt1q*4+48]
+%endif
+
+    haddps    m0, m1
+    haddps    m2, m3
+    haddps    m0, m2
+    movaps [samplesq+cnt1q], m0
+
+    mulps     m6, m4
+    mulps     m7, m4
+%if ARCH_X86_64
+    mulps     m8, m4
+    mulps     m9, m4
+
+    haddps    m6, m7
+    haddps    m8, m9
+    haddps    m6, m8
+%else
+    mulps     m2, m4, [coeffq+cnt1q*4+32]
+    mulps     m3, m4, [coeffq+cnt1q*4+48]
+
+    haddps    m6, m7
+    haddps    m2, m3
+    haddps    m6, m2
+%endif
+    movaps [samplesq+cnt2q], m6
+
+    sub    cnt2d, 16
+    add    cnt1q, 16
+    jl .inner_loop
+
+    add     lfeq, sizeof_float
+    add samplesq, 128*sizeof_float
+    mov    cnt1q, -64*sizeof_float
+    mov    cnt2d,  64*sizeof_float-16
+    sub nblocksd, 1
+    jg .loop
+    RET
+%endmacro
+
+INIT_XMM sse3
+LFE_FIR1_FLOAT
+%if HAVE_AVX_EXTERNAL
+INIT_XMM avx
+LFE_FIR1_FLOAT
+%endif
diff --git a/libavcodec/x86/dcadsp_init.c b/libavcodec/x86/dcadsp_init.c
index bfe13e5..fc10fb8 100644
--- a/libavcodec/x86/dcadsp_init.c
+++ b/libavcodec/x86/dcadsp_init.c
@@ -23,10 +23,13 @@
 
 #define LFE_FIR_FLOAT_FUNC(opt)                                               \
 void ff_lfe_fir0_float_##opt(float *pcm_samples, int32_t *lfe_samples,         \
+                             const float *filter_coeff, ptrdiff_t npcmblocks); \
+void ff_lfe_fir1_float_##opt(float *pcm_samples, int32_t *lfe_samples,         \
                              const float *filter_coeff, ptrdiff_t npcmblocks);
 
 LFE_FIR_FLOAT_FUNC(sse)
 LFE_FIR_FLOAT_FUNC(sse2)
+LFE_FIR_FLOAT_FUNC(sse3)
 LFE_FIR_FLOAT_FUNC(avx)
 LFE_FIR_FLOAT_FUNC(fma3)
 
@@ -38,8 +41,12 @@ av_cold void ff_dcadsp_init_x86(DCADSPContext *s)
         s->lfe_fir_float[0] = ff_lfe_fir0_float_sse;
     if (EXTERNAL_SSE2(cpu_flags))
         s->lfe_fir_float[0] = ff_lfe_fir0_float_sse2;
-    if (EXTERNAL_AVX(cpu_flags))
+    if (EXTERNAL_SSE3(cpu_flags))
+        s->lfe_fir_float[1] = ff_lfe_fir1_float_sse3;
+    if (EXTERNAL_AVX(cpu_flags)) {
         s->lfe_fir_float[0] = ff_lfe_fir0_float_avx;
+        s->lfe_fir_float[1] = ff_lfe_fir1_float_avx;
+    }
     if (EXTERNAL_FMA3(cpu_flags))
         s->lfe_fir_float[0] = ff_lfe_fir0_float_fma3;
 }
diff --git a/libavcodec/x86/dct-test.c b/libavcodec/x86/dct-test.c
deleted file mode 100644
index 28ede16..0000000
--- a/libavcodec/x86/dct-test.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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 "config.h"
-
-#include "fdct.h"
-#include "xvididct.h"
-#include "simple_idct.h"
-
-#if (CONFIG_PRORES_DECODER || CONFIG_PRORES_LGPL_DECODER) && ARCH_X86_64 && HAVE_YASM
-void ff_prores_idct_put_10_sse2(uint16_t *dst, int linesize,
-                                int16_t *block, int16_t *qmat);
-
-#define PR_WRAP(INSN) \
-static void ff_prores_idct_put_10_##INSN##_wrap(int16_t *dst){ \
-    LOCAL_ALIGNED(16, int16_t, qmat, [64]); \
-    LOCAL_ALIGNED(16, int16_t, tmp, [64]); \
-    int i; \
- \
-    for(i=0; i<64; i++){ \
-        qmat[i]=4; \
-        tmp[i]= dst[i]; \
-    } \
-    ff_prores_idct_put_10_##INSN (dst, 16, tmp, qmat); \
- \
-    for(i=0; i<64; i++) { \
-         dst[i] -= 512; \
-    } \
-}
-
-PR_WRAP(sse2)
-
-# if HAVE_AVX_EXTERNAL
-void ff_prores_idct_put_10_avx(uint16_t *dst, int linesize,
-                               int16_t *block, int16_t *qmat);
-PR_WRAP(avx)
-# endif
-
-#endif
-
-static const struct algo fdct_tab_arch[] = {
-#if HAVE_MMX_INLINE
-    { "MMX",    ff_fdct_mmx,    FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMX },
-#endif
-#if HAVE_MMXEXT_INLINE
-    { "MMXEXT", ff_fdct_mmxext, FF_IDCT_PERM_NONE, AV_CPU_FLAG_MMXEXT },
-#endif
-#if HAVE_SSE2_INLINE
-    { "SSE2",   ff_fdct_sse2,   FF_IDCT_PERM_NONE, AV_CPU_FLAG_SSE2 },
-#endif
-    { 0 }
-};
-
-static const struct algo idct_tab_arch[] = {
-#if HAVE_MMX_INLINE
-    { "SIMPLE-MMX",  ff_simple_idct_mmx,  FF_IDCT_PERM_SIMPLE, AV_CPU_FLAG_MMX },
-#endif
-#if CONFIG_MPEG4_DECODER && HAVE_YASM
-#if ARCH_X86_32
-    { "XVID-MMX",    ff_xvid_idct_mmx,    FF_IDCT_PERM_NONE,   AV_CPU_FLAG_MMX,    1 },
-    { "XVID-MMXEXT", ff_xvid_idct_mmxext, FF_IDCT_PERM_NONE,   AV_CPU_FLAG_MMXEXT, 1 },
-#endif
-#if HAVE_SSE2_EXTERNAL
-    { "XVID-SSE2",   ff_xvid_idct_sse2,   FF_IDCT_PERM_SSE2,   AV_CPU_FLAG_SSE2,   1 },
-#endif
-#endif /* CONFIG_MPEG4_DECODER && HAVE_YASM */
-#if (CONFIG_PRORES_DECODER || CONFIG_PRORES_LGPL_DECODER) && ARCH_X86_64 && HAVE_YASM
-    { "PR-SSE2",     ff_prores_idct_put_10_sse2_wrap, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2, 1 },
-# if HAVE_AVX_EXTERNAL
-    { "PR-AVX",      ff_prores_idct_put_10_avx_wrap, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_AVX, 1 },
-# endif
-#endif
-#if HAVE_YASM
-#if ARCH_X86_64
-#if HAVE_SSE2_EXTERNAL
-    { "SIMPLE10-SSE2",  ff_simple_idct10_sse2, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2},
-    { "SIMPLE12-SSE2",  ff_simple_idct12_sse2, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2, 1 },
-#endif
-#if HAVE_AVX_EXTERNAL
-    { "SIMPLE10-AVX",   ff_simple_idct10_avx,  FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_AVX},
-    { "SIMPLE12-AVX",   ff_simple_idct12_avx,  FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_AVX,  1 },
-#endif
-#endif
-#endif
-    { 0 }
-};
-
-static const uint8_t idct_simple_mmx_perm[64] = {
-    0x00, 0x08, 0x04, 0x09, 0x01, 0x0C, 0x05, 0x0D,
-    0x10, 0x18, 0x14, 0x19, 0x11, 0x1C, 0x15, 0x1D,
-    0x20, 0x28, 0x24, 0x29, 0x21, 0x2C, 0x25, 0x2D,
-    0x12, 0x1A, 0x16, 0x1B, 0x13, 0x1E, 0x17, 0x1F,
-    0x02, 0x0A, 0x06, 0x0B, 0x03, 0x0E, 0x07, 0x0F,
-    0x30, 0x38, 0x34, 0x39, 0x31, 0x3C, 0x35, 0x3D,
-    0x22, 0x2A, 0x26, 0x2B, 0x23, 0x2E, 0x27, 0x2F,
-    0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F,
-};
-
-static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 };
-
-static int permute_x86(int16_t dst[64], const int16_t src[64],
-                       enum idct_permutation_type perm_type)
-{
-    int i;
-
-    switch (perm_type) {
-    case FF_IDCT_PERM_SIMPLE:
-        for (i = 0; i < 64; i++)
-            dst[idct_simple_mmx_perm[i]] = src[i];
-        return 1;
-    case FF_IDCT_PERM_SSE2:
-        for (i = 0; i < 64; i++)
-            dst[(i & 0x38) | idct_sse2_row_perm[i & 7]] = src[i];
-        return 1;
-    }
-
-    return 0;
-}
diff --git a/libavcodec/x86/fft.asm b/libavcodec/x86/fft.asm
index 22d9866..cdbfd66 100644
--- a/libavcodec/x86/fft.asm
+++ b/libavcodec/x86/fft.asm
@@ -73,7 +73,7 @@ ps_m1p1: dd 1<<31, 0
 cextern ps_neg
 
 %assign i 16
-%rep 13
+%rep 14
 cextern cos_ %+ i
 %assign i i<<1
 %endrep
@@ -756,7 +756,7 @@ DECL_PASS pass_interleave_3dnow, PASS_BIG 0
 %endif
 
 %assign n 1<<%1
-%rep 17-%1
+%rep 18-%1
 %assign n2 n/2
 %assign n4 n/4
 %xdefine list_of_fft list_of_fft, fft %+ n %+ fullsuffix SECTION_REL
diff --git a/libavcodec/x86/fft_init.c b/libavcodec/x86/fft_init.c
index 5085f11..928f1dc 100644
--- a/libavcodec/x86/fft_init.c
+++ b/libavcodec/x86/fft_init.c
@@ -17,39 +17,43 @@
  */
 
 #include "config.h"
+
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
 #include "libavutil/x86/cpu.h"
+
 #include "fft.h"
 
 av_cold void ff_fft_init_x86(FFTContext *s)
 {
     int cpu_flags = av_get_cpu_flags();
 
+    if (s->nbits > 16)
+        return;
+
 #if ARCH_X86_32
     if (EXTERNAL_AMD3DNOW(cpu_flags)) {
-        /* 3DNow! for K6-2/3 */
         s->imdct_calc = ff_imdct_calc_3dnow;
         s->imdct_half = ff_imdct_half_3dnow;
         s->fft_calc   = ff_fft_calc_3dnow;
     }
+
     if (EXTERNAL_AMD3DNOWEXT(cpu_flags)) {
-        /* 3DNowEx for K7 */
         s->imdct_calc = ff_imdct_calc_3dnowext;
         s->imdct_half = ff_imdct_half_3dnowext;
         s->fft_calc   = ff_fft_calc_3dnowext;
     }
-#endif
+#endif /* ARCH_X86_32 */
+
     if (EXTERNAL_SSE(cpu_flags)) {
-        /* SSE for P3/P4/K8 */
         s->imdct_calc  = ff_imdct_calc_sse;
         s->imdct_half  = ff_imdct_half_sse;
         s->fft_permute = ff_fft_permute_sse;
         s->fft_calc    = ff_fft_calc_sse;
         s->fft_permutation = FF_FFT_PERM_SWAP_LSBS;
     }
+
     if (EXTERNAL_AVX_FAST(cpu_flags) && s->nbits >= 5) {
-        /* AVX for SB */
         s->imdct_half      = ff_imdct_half_avx;
         s->fft_calc        = ff_fft_calc_avx;
         s->fft_permutation = FF_FFT_PERM_AVX;
diff --git a/libavcodec/x86/fmtconvert_init.c b/libavcodec/x86/fmtconvert_init.c
index e4cbadc..6d35377 100644
--- a/libavcodec/x86/fmtconvert_init.c
+++ b/libavcodec/x86/fmtconvert_init.c
@@ -24,7 +24,6 @@
 
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/fmtconvert.h"
 
diff --git a/libavcodec/x86/h264_chromamc.asm b/libavcodec/x86/h264_chromamc.asm
index 107ae51..fa698e5 100644
--- a/libavcodec/x86/h264_chromamc.asm
+++ b/libavcodec/x86/h264_chromamc.asm
@@ -1,5 +1,5 @@
 ;******************************************************************************
-;* MMX/SSSE3-optimized functions for H264 chroma MC
+;* MMX/SSSE3-optimized functions for H.264 chroma MC
 ;* Copyright (c) 2005 Zoltan Hidvegi <hzoli -a- hzoli -d- com>,
 ;*               2005-2008 Loren Merritt
 ;*
diff --git a/libavcodec/x86/h264_i386.h b/libavcodec/x86/h264_i386.h
index 49ad0e0..4dfbc30 100644
--- a/libavcodec/x86/h264_i386.h
+++ b/libavcodec/x86/h264_i386.h
@@ -21,7 +21,7 @@
 
 /**
  * @file
- * H.264 / AVC / MPEG4 part10 codec.
+ * H.264 / AVC / MPEG-4 part10 codec.
  * non-MMX i386-specific optimizations for H.264
  * @author Michael Niedermayer <michaelni at gmx.at>
  */
diff --git a/libavcodec/x86/hpeldsp_init.c b/libavcodec/x86/hpeldsp_init.c
index 5c5da28..f1ba4be 100644
--- a/libavcodec/x86/hpeldsp_init.c
+++ b/libavcodec/x86/hpeldsp_init.c
@@ -24,7 +24,6 @@
 
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/avcodec.h"
 #include "libavcodec/hpeldsp.h"
diff --git a/libavcodec/x86/inline_asm.h b/libavcodec/x86/inline_asm.h
index 3e65a76..0198746 100644
--- a/libavcodec/x86/inline_asm.h
+++ b/libavcodec/x86/inline_asm.h
@@ -50,7 +50,7 @@
 #endif
 
 // using regr as temporary and for the output result
-// first argument is unmodifed and second is trashed
+// first argument is unmodified and second is trashed
 // regfe is supposed to contain 0xfefefefefefefefe
 #define PAVGB_MMX_NO_RND(rega, regb, regr, regfe)                \
     "movq   "#rega", "#regr"            \n\t"                    \
diff --git a/libavcodec/x86/lossless_audiodsp.asm b/libavcodec/x86/lossless_audiodsp.asm
index 5597dad..063d7b4 100644
--- a/libavcodec/x86/lossless_audiodsp.asm
+++ b/libavcodec/x86/lossless_audiodsp.asm
@@ -68,6 +68,39 @@ SCALARPRODUCT
 INIT_XMM sse2
 SCALARPRODUCT
 
+INIT_XMM sse4
+; int ff_scalarproduct_and_madd_int32(int16_t *v1, int32_t *v2, int16_t *v3,
+;                                     int order, int mul)
+cglobal scalarproduct_and_madd_int32, 4,4,8, v1, v2, v3, order, mul
+    shl orderq, 1
+    movd    m7, mulm
+    SPLATW  m7, m7
+    pxor    m6, m6
+    add v1q, orderq
+    lea v2q, [v2q + 2*orderq]
+    add v3q, orderq
+    neg orderq
+.loop:
+    mova    m3, [v1q + orderq]
+    movu    m0, [v2q + 2*orderq]
+    pmovsxwd m4, m3
+    movu    m1, [v2q + 2*orderq + mmsize]
+    movhlps m5, m3
+    movu    m2, [v3q + orderq]
+    pmovsxwd m5, m5
+    pmullw  m2, m7
+    pmulld  m0, m4
+    pmulld  m1, m5
+    paddw   m2, m3
+    paddd   m6, m0
+    paddd   m6, m1
+    mova    [v1q + orderq], m2
+    add     orderq, 16
+    jl .loop
+    HADDD   m6, m0
+    movd   eax, m6
+    RET
+
 %macro SCALARPRODUCT_LOOP 1
 align 16
 .loop%1:
diff --git a/libavcodec/x86/lossless_audiodsp_init.c b/libavcodec/x86/lossless_audiodsp_init.c
index 197173c..10b6a65 100644
--- a/libavcodec/x86/lossless_audiodsp_init.c
+++ b/libavcodec/x86/lossless_audiodsp_init.c
@@ -31,6 +31,10 @@ int32_t ff_scalarproduct_and_madd_int16_ssse3(int16_t *v1, const int16_t *v2,
                                               const int16_t *v3,
                                               int order, int mul);
 
+int32_t ff_scalarproduct_and_madd_int32_sse4(int16_t *v1, const int32_t *v2,
+                                             const int16_t *v3,
+                                             int order, int mul);
+
 av_cold void ff_llauddsp_init_x86(LLAudDSPContext *c)
 {
 #if HAVE_YASM
@@ -45,5 +49,8 @@ av_cold void ff_llauddsp_init_x86(LLAudDSPContext *c)
     if (EXTERNAL_SSSE3(cpu_flags) &&
         !(cpu_flags & (AV_CPU_FLAG_SSE42 | AV_CPU_FLAG_3DNOW))) // cachesplit
         c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_ssse3;
+
+    if (EXTERNAL_SSE4(cpu_flags))
+        c->scalarproduct_and_madd_int32 = ff_scalarproduct_and_madd_int32_sse4;
 #endif
 }
diff --git a/libavcodec/x86/mpegvideo.c b/libavcodec/x86/mpegvideo.c
index af47422..1811326 100644
--- a/libavcodec/x86/mpegvideo.c
+++ b/libavcodec/x86/mpegvideo.c
@@ -1,6 +1,6 @@
 /*
  * Optimized for ia32 CPUs by Nick Kurshev <nickols_k at mail.ru>
- * h263, mpeg1, mpeg2 dequantizer & draw_edges by Michael Niedermayer <michaelni at gmx.at>
+ * H.263, MPEG-1, MPEG-2 dequantizer & draw_edges by Michael Niedermayer <michaelni at gmx.at>
  *
  * This file is part of FFmpeg.
  *
@@ -180,7 +180,7 @@ static void dct_unquantize_mpeg1_intra_mmx(MpegEncContext *s,
         block0 = block[0] * s->y_dc_scale;
     else
         block0 = block[0] * s->c_dc_scale;
-    /* XXX: only mpeg1 */
+    /* XXX: only MPEG-1 */
     quant_matrix = s->intra_matrix;
 __asm__ volatile(
                 "pcmpeqw %%mm7, %%mm7           \n\t"
diff --git a/libavcodec/x86/mpegvideodsp.c b/libavcodec/x86/mpegvideodsp.c
index 941a8e2..e0498f3 100644
--- a/libavcodec/x86/mpegvideodsp.c
+++ b/libavcodec/x86/mpegvideodsp.c
@@ -19,7 +19,6 @@
 #include "config.h"
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/mpegvideodsp.h"
 #include "libavcodec/videodsp.h"
diff --git a/libavcodec/x86/rv34dsp_init.c b/libavcodec/x86/rv34dsp_init.c
index 99c56f9..d417dac 100644
--- a/libavcodec/x86/rv34dsp_init.c
+++ b/libavcodec/x86/rv34dsp_init.c
@@ -21,7 +21,6 @@
 
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/rv34dsp.h"
 
diff --git a/libavcodec/x86/rv40dsp.asm b/libavcodec/x86/rv40dsp.asm
index fdd81a0..d0c3af0 100644
--- a/libavcodec/x86/rv40dsp.asm
+++ b/libavcodec/x86/rv40dsp.asm
@@ -335,14 +335,14 @@ INIT_XMM ssse3
 FILTER_SSSE3  put
 FILTER_SSSE3  avg
 
-; %1=5bits weights?, %2=dst %3=src1 %4=src3 %5=stride if sse2
+; %1=5-bit weights?, %2=dst %3=src1 %4=src3 %5=stride if SSE2
 %macro RV40_WCORE  4-5
     movh       m4, [%3 + r6 + 0]
     movh       m5, [%4 + r6 + 0]
 %if %0 == 4
 %define OFFSET r6 + mmsize / 2
 %else
-    ; 8x8 block and sse2, stride was provided
+    ; 8x8 block and SSE2, stride was provided
 %define OFFSET r6
     add        r6, r5
 %endif
@@ -350,7 +350,7 @@ FILTER_SSSE3  avg
     movh       m7, [%4 + OFFSET]
 
 %if %1 == 0
-    ; 14bits weights
+    ; 14-bit weights
     punpcklbw  m4, m0
     punpcklbw  m5, m0
     punpcklbw  m6, m0
@@ -368,7 +368,7 @@ FILTER_SSSE3  avg
     paddw      m4, m5
     paddw      m6, m7
 %else
-    ; 5bits weights
+    ; 5-bit weights
 %if cpuflag(ssse3)
     punpcklbw  m4, m5
     punpcklbw  m6, m7
@@ -404,7 +404,7 @@ FILTER_SSSE3  avg
 
     packuswb   m4, m6
 %if %0 == 5
-    ; Only called for 8x8 blocks and sse2
+    ; Only called for 8x8 blocks and SSE2
     sub        r6, r5
     movh       [%2 + r6], m4
     add        r6, r5
diff --git a/libavcodec/x86/sbrdsp.asm b/libavcodec/x86/sbrdsp.asm
index b6fa535..07a412b 100644
--- a/libavcodec/x86/sbrdsp.asm
+++ b/libavcodec/x86/sbrdsp.asm
@@ -526,31 +526,15 @@ align 16
     xorps   m2, [ps_mask3]
     xorps   m5, [ps_mask3]
     xorps   m6, [ps_mask3]
+    HADDPS  m2, m5, m3
+    HADDPS  m7, m6, m4
 %if cpuflag(sse3)
     movshdup m0, m1
-    haddps  m2, m5
-    haddps  m7, m6
-    addss   m1, m0
 %else
-    movaps  m3, m2
-    movaps  m0, m5
-    movaps  m4, m6
-    shufps  m3, m3, q0301
-    shufps  m0, m0, q0301
-    shufps  m4, m4, q0301
-    addps   m2, m3
-    addps   m5, m0
-    addps   m6, m4
-
-    movss   m0, m7
-    movss   m3, m1
-    shufps  m7, m7, q0001
+    movss   m0, m1
     shufps  m1, m1, q0001
-    addss   m7, m0
-    addss   m1, m3
-    shufps  m2, m5, q2020
-    shufps  m7, m6, q2020
 %endif
+    addss   m1, m0
     movaps  [phiq     ], m2
     movhps  [phiq+0x18], m7
     movss   [phiq+0x28], m7
diff --git a/libavcodec/x86/v210enc.asm b/libavcodec/x86/v210enc.asm
index 0545454..965f2be 100644
--- a/libavcodec/x86/v210enc.asm
+++ b/libavcodec/x86/v210enc.asm
@@ -93,8 +93,10 @@ cglobal v210_planar_pack_10, 5, 5, 4+cpuflag(avx2), y, u, v, dst, width
     RET
 %endmacro
 
+%if HAVE_SSSE3_EXTERNAL
 INIT_XMM ssse3
 v210_planar_pack_10
+%endif
 
 %if HAVE_AVX2_EXTERNAL
 INIT_YMM avx2
@@ -167,10 +169,14 @@ cglobal v210_planar_pack_8, 5, 5, 7, y, u, v, dst, width
     RET
 %endmacro
 
+%if HAVE_SSSE3_EXTERNAL
 INIT_XMM ssse3
 v210_planar_pack_8
+%endif
+%if HAVE_AVX_EXTERNAL
 INIT_XMM avx
 v210_planar_pack_8
+%endif
 
 %if HAVE_AVX2_EXTERNAL
 INIT_YMM avx2
diff --git a/libavcodec/x86/v210enc_init.c b/libavcodec/x86/v210enc_init.c
index 8abb152..e997b4b 100644
--- a/libavcodec/x86/v210enc_init.c
+++ b/libavcodec/x86/v210enc_init.c
@@ -45,9 +45,10 @@ av_cold void ff_v210enc_init_x86(V210EncContext *s)
     if (EXTERNAL_AVX(cpu_flags))
         s->pack_line_8 = ff_v210_planar_pack_8_avx;
 
-    if (EXTERNAL_AVX2_FAST(cpu_flags)) {
-        s->pack_line_8 = ff_v210_planar_pack_8_avx2;
-        s->pack_line_10 = ff_v210_planar_pack_10_avx2;
-        s->sample_factor = 2;
+    if (EXTERNAL_AVX2(cpu_flags)) {
+        s->sample_factor_8  = 2;
+        s->pack_line_8      = ff_v210_planar_pack_8_avx2;
+        s->sample_factor_10 = 2;
+        s->pack_line_10     = ff_v210_planar_pack_10_avx2;
     }
 }
diff --git a/libavcodec/x86/vc1dsp.asm b/libavcodec/x86/vc1dsp.asm
deleted file mode 100644
index eee42c2..0000000
--- a/libavcodec/x86/vc1dsp.asm
+++ /dev/null
@@ -1,585 +0,0 @@
-;******************************************************************************
-;* VC1 DSP optimizations
-;* Copyright (c) 2007 Christophe GISQUET <christophe.gisquet at free.fr>
-;* Copyright (c) 2009 David Conrad
-;*
-;* This file is part of FFmpeg.
-;*
-;* FFmpeg is free software; you can redistribute it and/or
-;* modify it under the terms of the GNU Lesser General Public
-;* License as published by the Free Software Foundation; either
-;* version 2.1 of the License, or (at your option) any later version.
-;*
-;* FFmpeg is distributed in the hope that it will be useful,
-;* but WITHOUT ANY WARRANTY; without even the implied warranty of
-;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-;* Lesser General Public License for more details.
-;*
-;* You should have received a copy of the GNU Lesser General Public
-;* License along with FFmpeg; if not, write to the Free Software
-;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-;******************************************************************************
-
-%include "libavutil/x86/x86util.asm"
-
-cextern pw_4
-cextern pw_5
-cextern pw_9
-cextern pw_128
-
-section .text
-
-; dst_low, dst_high (src), zero
-; zero-extends one vector from 8 to 16 bits
-%macro UNPACK_8TO16 4
-    mova      m%2, m%3
-    punpckh%1 m%3, m%4
-    punpckl%1 m%2, m%4
-%endmacro
-
-%macro STORE_4_WORDS 6
-%if cpuflag(sse4)
-    pextrw %1, %5, %6+0
-    pextrw %2, %5, %6+1
-    pextrw %3, %5, %6+2
-    pextrw %4, %5, %6+3
-%else
-    movd  %6d, %5
-%if mmsize==16
-    psrldq %5, 4
-%else
-    psrlq  %5, 32
-%endif
-    mov    %1, %6w
-    shr    %6, 16
-    mov    %2, %6w
-    movd  %6d, %5
-    mov    %3, %6w
-    shr    %6, 16
-    mov    %4, %6w
-%endif
-%endmacro
-
-; in:  p1 p0 q0 q1, clobbers p0
-; out: p1 = (2*(p1 - q1) - 5*(p0 - q0) + 4) >> 3
-%macro VC1_LOOP_FILTER_A0 4
-    psubw  %1, %4
-    psubw  %2, %3
-    paddw  %1, %1
-    pmullw %2, [pw_5]
-    psubw  %1, %2
-    paddw  %1, [pw_4]
-    psraw  %1, 3
-%endmacro
-
-; in: p0 q0 a0 a1 a2
-;     m0 m1 m7 m6 m5
-; %1: size
-; out: m0=p0' m1=q0'
-%macro VC1_FILTER 1
-    PABSW   m4, m7
-    PABSW   m3, m6
-    PABSW   m2, m5
-    mova    m6, m4
-    pminsw  m3, m2
-    pcmpgtw m6, m3  ; if (a2 < a0 || a1 < a0)
-    psubw   m3, m4
-    pmullw  m3, [pw_5]   ; 5*(a3 - a0)
-    PABSW   m2, m3
-    psraw   m2, 3   ; abs(d/8)
-    pxor    m7, m3  ; d_sign ^= a0_sign
-
-    pxor    m5, m5
-    movd    m3, r2d
-%if %1 > 4
-    punpcklbw m3, m3
-%endif
-    punpcklbw m3, m5
-    pcmpgtw m3, m4  ; if (a0 < pq)
-    pand    m6, m3
-
-    mova    m3, m0
-    psubw   m3, m1
-    PABSW   m4, m3
-    psraw   m4, 1
-    pxor    m3, m7  ; d_sign ^ clip_sign
-    psraw   m3, 15
-    pminsw  m2, m4  ; min(d, clip)
-    pcmpgtw m4, m5
-    pand    m6, m4  ; filt3 (C return value)
-
-; each set of 4 pixels is not filtered if the 3rd is not
-%if mmsize==16
-    pshuflw m4, m6, 0xaa
-%if %1 > 4
-    pshufhw m4, m4, 0xaa
-%endif
-%else
-    pshufw  m4, m6, 0xaa
-%endif
-    pandn   m3, m4
-    pand    m2, m6
-    pand    m3, m2  ; d final
-
-    psraw   m7, 15
-    pxor    m3, m7
-    psubw   m3, m7
-    psubw   m0, m3
-    paddw   m1, m3
-    packuswb m0, m0
-    packuswb m1, m1
-%endmacro
-
-; 1st param: size of filter
-; 2nd param: mov suffix equivalent to the filter size
-%macro VC1_V_LOOP_FILTER 2
-    pxor      m5, m5
-    mov%2     m6, [r4]
-    mov%2     m4, [r4+r1]
-    mov%2     m7, [r4+2*r1]
-    mov%2     m0, [r4+r3]
-    punpcklbw m6, m5
-    punpcklbw m4, m5
-    punpcklbw m7, m5
-    punpcklbw m0, m5
-
-    VC1_LOOP_FILTER_A0 m6, m4, m7, m0
-    mov%2     m1, [r0]
-    mov%2     m2, [r0+r1]
-    punpcklbw m1, m5
-    punpcklbw m2, m5
-    mova      m4, m0
-    VC1_LOOP_FILTER_A0 m7, m4, m1, m2
-    mov%2     m3, [r0+2*r1]
-    mov%2     m4, [r0+r3]
-    punpcklbw m3, m5
-    punpcklbw m4, m5
-    mova      m5, m1
-    VC1_LOOP_FILTER_A0 m5, m2, m3, m4
-
-    VC1_FILTER %1
-    mov%2 [r4+r3], m0
-    mov%2 [r0],    m1
-%endmacro
-
-; 1st param: size of filter
-;     NOTE: UNPACK_8TO16 this number of 8 bit numbers are in half a register
-; 2nd (optional) param: temp register to use for storing words
-%macro VC1_H_LOOP_FILTER 1-2
-%if %1 == 4
-    movq      m0, [r0     -4]
-    movq      m1, [r0+  r1-4]
-    movq      m2, [r0+2*r1-4]
-    movq      m3, [r0+  r3-4]
-    TRANSPOSE4x4B 0, 1, 2, 3, 4
-%else
-    movq      m0, [r0     -4]
-    movq      m4, [r0+  r1-4]
-    movq      m1, [r0+2*r1-4]
-    movq      m5, [r0+  r3-4]
-    movq      m2, [r4     -4]
-    movq      m6, [r4+  r1-4]
-    movq      m3, [r4+2*r1-4]
-    movq      m7, [r4+  r3-4]
-    punpcklbw m0, m4
-    punpcklbw m1, m5
-    punpcklbw m2, m6
-    punpcklbw m3, m7
-    TRANSPOSE4x4W 0, 1, 2, 3, 4
-%endif
-    pxor      m5, m5
-
-    UNPACK_8TO16 bw, 6, 0, 5
-    UNPACK_8TO16 bw, 7, 1, 5
-    VC1_LOOP_FILTER_A0 m6, m0, m7, m1
-    UNPACK_8TO16 bw, 4, 2, 5
-    mova    m0, m1                      ; m0 = p0
-    VC1_LOOP_FILTER_A0 m7, m1, m4, m2
-    UNPACK_8TO16 bw, 1, 3, 5
-    mova    m5, m4
-    VC1_LOOP_FILTER_A0 m5, m2, m1, m3
-    SWAP 1, 4                           ; m1 = q0
-
-    VC1_FILTER %1
-    punpcklbw m0, m1
-%if %0 > 1
-    STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, %2
-%if %1 > 4
-    psrldq m0, 4
-    STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, %2
-%endif
-%else
-    STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, 0
-    STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, 4
-%endif
-%endmacro
-
-
-%macro START_V_FILTER 0
-    mov  r4, r0
-    lea  r3, [4*r1]
-    sub  r4, r3
-    lea  r3, [r1+2*r1]
-    imul r2, 0x01010101
-%endmacro
-
-%macro START_H_FILTER 1
-    lea  r3, [r1+2*r1]
-%if %1 > 4
-    lea  r4, [r0+4*r1]
-%endif
-    imul r2, 0x01010101
-%endmacro
-
-%macro VC1_LF 0
-cglobal vc1_v_loop_filter_internal
-    VC1_V_LOOP_FILTER 4, d
-    ret
-
-cglobal vc1_h_loop_filter_internal
-    VC1_H_LOOP_FILTER 4, r4
-    ret
-
-; void ff_vc1_v_loop_filter4_mmxext(uint8_t *src, int stride, int pq)
-cglobal vc1_v_loop_filter4, 3,5,0
-    START_V_FILTER
-    call vc1_v_loop_filter_internal
-    RET
-
-; void ff_vc1_h_loop_filter4_mmxext(uint8_t *src, int stride, int pq)
-cglobal vc1_h_loop_filter4, 3,5,0
-    START_H_FILTER 4
-    call vc1_h_loop_filter_internal
-    RET
-
-; void ff_vc1_v_loop_filter8_mmxext(uint8_t *src, int stride, int pq)
-cglobal vc1_v_loop_filter8, 3,5,0
-    START_V_FILTER
-    call vc1_v_loop_filter_internal
-    add  r4, 4
-    add  r0, 4
-    call vc1_v_loop_filter_internal
-    RET
-
-; void ff_vc1_h_loop_filter8_mmxext(uint8_t *src, int stride, int pq)
-cglobal vc1_h_loop_filter8, 3,5,0
-    START_H_FILTER 4
-    call vc1_h_loop_filter_internal
-    lea  r0, [r0+4*r1]
-    call vc1_h_loop_filter_internal
-    RET
-%endmacro
-
-INIT_MMX mmxext
-VC1_LF
-
-INIT_XMM sse2
-; void ff_vc1_v_loop_filter8_sse2(uint8_t *src, int stride, int pq)
-cglobal vc1_v_loop_filter8, 3,5,8
-    START_V_FILTER
-    VC1_V_LOOP_FILTER 8, q
-    RET
-
-; void ff_vc1_h_loop_filter8_sse2(uint8_t *src, int stride, int pq)
-cglobal vc1_h_loop_filter8, 3,6,8
-    START_H_FILTER 8
-    VC1_H_LOOP_FILTER 8, r5
-    RET
-
-INIT_MMX ssse3
-; void ff_vc1_v_loop_filter4_ssse3(uint8_t *src, int stride, int pq)
-cglobal vc1_v_loop_filter4, 3,5,0
-    START_V_FILTER
-    VC1_V_LOOP_FILTER 4, d
-    RET
-
-; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, int stride, int pq)
-cglobal vc1_h_loop_filter4, 3,5,0
-    START_H_FILTER 4
-    VC1_H_LOOP_FILTER 4, r4
-    RET
-
-INIT_XMM ssse3
-; void ff_vc1_v_loop_filter8_ssse3(uint8_t *src, int stride, int pq)
-cglobal vc1_v_loop_filter8, 3,5,8
-    START_V_FILTER
-    VC1_V_LOOP_FILTER 8, q
-    RET
-
-; void ff_vc1_h_loop_filter8_ssse3(uint8_t *src, int stride, int pq)
-cglobal vc1_h_loop_filter8, 3,6,8
-    START_H_FILTER 8
-    VC1_H_LOOP_FILTER 8, r5
-    RET
-
-INIT_XMM sse4
-; void ff_vc1_h_loop_filter8_sse4(uint8_t *src, int stride, int pq)
-cglobal vc1_h_loop_filter8, 3,5,8
-    START_H_FILTER 8
-    VC1_H_LOOP_FILTER 8
-    RET
-
-%if HAVE_MMX_INLINE
-
-; XXX some of these macros are not used right now, but they will in the future
-;     when more functions are ported.
-
-%macro OP_PUT 2 ; dst, src
-%endmacro
-
-%macro OP_AVG 2 ; dst, src
-    pavgb           %1, %2
-%endmacro
-
-%macro NORMALIZE_MMX 1 ; shift
-    paddw           m3, m7 ; +bias-r
-    paddw           m4, m7 ; +bias-r
-    psraw           m3, %1
-    psraw           m4, %1
-%endmacro
-
-%macro TRANSFER_DO_PACK 2 ; op, dst
-    packuswb        m3, m4
-    %1              m3, [%2]
-    mova          [%2], m3
-%endmacro
-
-%macro TRANSFER_DONT_PACK 2 ; op, dst
-    %1              m3, [%2]
-    %1              m3, [%2 + mmsize]
-    mova          [%2], m3
-    mova [mmsize + %2], m4
-%endmacro
-
-; see MSPEL_FILTER13_CORE for use as UNPACK macro
-%macro DO_UNPACK 1 ; reg
-    punpcklbw       %1, m0
-%endmacro
-%macro DONT_UNPACK 1 ; reg
-%endmacro
-
-; Compute the rounder 32-r or 8-r and unpacks it to m7
-%macro LOAD_ROUNDER_MMX 1 ; round
-    movd      m7, %1
-    punpcklwd m7, m7
-    punpckldq m7, m7
-%endmacro
-
-%macro SHIFT2_LINE 5 ; off, r0, r1, r2, r3
-    paddw          m%3, m%4
-    movh           m%2, [srcq + stride_neg2]
-    pmullw         m%3, m6
-    punpcklbw      m%2, m0
-    movh           m%5, [srcq + strideq]
-    psubw          m%3, m%2
-    punpcklbw      m%5, m0
-    paddw          m%3, m7
-    psubw          m%3, m%5
-    psraw          m%3, shift
-    movu   [dstq + %1], m%3
-    add           srcq, strideq
-%endmacro
-
-INIT_MMX mmx
-; void ff_vc1_put_ver_16b_shift2_mmx(int16_t *dst, const uint8_t *src,
-;                                    x86_reg stride, int rnd, int64_t shift)
-; Sacrificing m6 makes it possible to pipeline loads from src
-%if ARCH_X86_32
-cglobal vc1_put_ver_16b_shift2, 3,6,0, dst, src, stride
-    DECLARE_REG_TMP     3, 4, 5
-    %define rnd r3mp
-    %define shift qword r4m
-%else ; X86_64
-cglobal vc1_put_ver_16b_shift2, 4,7,0, dst, src, stride
-    DECLARE_REG_TMP     4, 5, 6
-    %define   rnd r3d
-    ; We need shift either in memory or in a mm reg as it's used in psraw
-    ; On WIN64, the arg is already on the stack
-    ; On UNIX64, m5 doesn't seem to be used
-%if WIN64
-    %define shift r4mp
-%else ; UNIX64
-    %define shift m5
-    mova shift, r4q
-%endif ; WIN64
-%endif ; X86_32
-%define stride_neg2 t0q
-%define stride_9minus4 t1q
-%define i t2q
-    mov       stride_neg2, strideq
-    neg       stride_neg2
-    add       stride_neg2, stride_neg2
-    lea    stride_9minus4, [strideq * 9 - 4]
-    mov                 i, 3
-    LOAD_ROUNDER_MMX  rnd
-    mova               m6, [pw_9]
-    pxor               m0, m0
-.loop:
-    movh               m2, [srcq]
-    add              srcq, strideq
-    movh               m3, [srcq]
-    punpcklbw          m2, m0
-    punpcklbw          m3, m0
-    SHIFT2_LINE         0, 1, 2, 3, 4
-    SHIFT2_LINE        24, 2, 3, 4, 1
-    SHIFT2_LINE        48, 3, 4, 1, 2
-    SHIFT2_LINE        72, 4, 1, 2, 3
-    SHIFT2_LINE        96, 1, 2, 3, 4
-    SHIFT2_LINE       120, 2, 3, 4, 1
-    SHIFT2_LINE       144, 3, 4, 1, 2
-    SHIFT2_LINE       168, 4, 1, 2, 3
-    sub              srcq, stride_9minus4
-    add              dstq, 8
-    dec                 i
-        jnz         .loop
-    REP_RET
-%undef rnd
-%undef shift
-%undef stride_neg2
-%undef stride_9minus4
-%undef i
-
-; void ff_vc1_*_hor_16b_shift2_mmx(uint8_t *dst, x86_reg stride,
-;                                  const int16_t *src, int rnd);
-; Data is already unpacked, so some operations can directly be made from
-; memory.
-%macro HOR_16B_SHIFT2 2 ; op, opname
-cglobal vc1_%2_hor_16b_shift2, 4, 5, 0, dst, stride, src, rnd, h
-    mov                hq, 8
-    sub              srcq, 2
-    sub              rndd, (-1+9+9-1) * 1024 ; add -1024 bias
-    LOAD_ROUNDER_MMX rndq
-    mova               m5, [pw_9]
-    mova               m6, [pw_128]
-    pxor               m0, m0
-
-.loop:
-    mova               m1, [srcq + 2 * 0]
-    mova               m2, [srcq + 2 * 0 + mmsize]
-    mova               m3, [srcq + 2 * 1]
-    mova               m4, [srcq + 2 * 1 + mmsize]
-    paddw              m3, [srcq + 2 * 2]
-    paddw              m4, [srcq + 2 * 2 + mmsize]
-    paddw              m1, [srcq + 2 * 3]
-    paddw              m2, [srcq + 2 * 3 + mmsize]
-    pmullw             m3, m5
-    pmullw             m4, m5
-    psubw              m3, m1
-    psubw              m4, m2
-    NORMALIZE_MMX      7
-    ; remove bias
-    paddw              m3, m6
-    paddw              m4, m6
-    TRANSFER_DO_PACK   %1, dstq
-    add              srcq, 24
-    add              dstq, strideq
-    dec                hq
-        jnz         .loop
-
-    RET
-%endmacro
-
-INIT_MMX mmx
-HOR_16B_SHIFT2 OP_PUT, put
-
-INIT_MMX mmxext
-HOR_16B_SHIFT2 OP_AVG, avg
-%endif ; HAVE_MMX_INLINE
-
-%macro INV_TRANS_INIT 0
-    movsxdifnidn linesizeq, linesized
-    movd       m0, blockd
-    SPLATW     m0, m0
-    pxor       m1, m1
-    psubw      m1, m0
-    packuswb   m0, m0
-    packuswb   m1, m1
-
-    DEFINE_ARGS dest, linesize, linesize3
-    lea    linesize3q, [linesizeq*3]
-%endmacro
-
-%macro INV_TRANS_PROCESS 1
-    mov%1                  m2, [destq+linesizeq*0]
-    mov%1                  m3, [destq+linesizeq*1]
-    mov%1                  m4, [destq+linesizeq*2]
-    mov%1                  m5, [destq+linesize3q]
-    paddusb                m2, m0
-    paddusb                m3, m0
-    paddusb                m4, m0
-    paddusb                m5, m0
-    psubusb                m2, m1
-    psubusb                m3, m1
-    psubusb                m4, m1
-    psubusb                m5, m1
-    mov%1 [linesizeq*0+destq], m2
-    mov%1 [linesizeq*1+destq], m3
-    mov%1 [linesizeq*2+destq], m4
-    mov%1 [linesize3q +destq], m5
-%endmacro
-
-; ff_vc1_inv_trans_?x?_dc_mmxext(uint8_t *dest, int linesize, int16_t *block)
-INIT_MMX mmxext
-cglobal vc1_inv_trans_4x4_dc, 3,4,0, dest, linesize, block
-    movsx         r3d, WORD [blockq]
-    mov        blockd, r3d             ; dc
-    shl        blockd, 4               ; 16 * dc
-    lea        blockd, [blockq+r3+4]   ; 17 * dc + 4
-    sar        blockd, 3               ; >> 3
-    mov           r3d, blockd          ; dc
-    shl        blockd, 4               ; 16 * dc
-    lea        blockd, [blockq+r3+64]  ; 17 * dc + 64
-    sar        blockd, 7               ; >> 7
-
-    INV_TRANS_INIT
-
-    INV_TRANS_PROCESS h
-    RET
-
-INIT_MMX mmxext
-cglobal vc1_inv_trans_4x8_dc, 3,4,0, dest, linesize, block
-    movsx         r3d, WORD [blockq]
-    mov        blockd, r3d             ; dc
-    shl        blockd, 4               ; 16 * dc
-    lea        blockd, [blockq+r3+4]   ; 17 * dc + 4
-    sar        blockd, 3               ; >> 3
-    shl        blockd, 2               ;  4 * dc
-    lea        blockd, [blockq*3+64]   ; 12 * dc + 64
-    sar        blockd, 7               ; >> 7
-
-    INV_TRANS_INIT
-
-    INV_TRANS_PROCESS h
-    lea         destq, [destq+linesizeq*4]
-    INV_TRANS_PROCESS h
-    RET
-
-INIT_MMX mmxext
-cglobal vc1_inv_trans_8x4_dc, 3,4,0, dest, linesize, block
-    movsx      blockd, WORD [blockq]   ; dc
-    lea        blockd, [blockq*3+1]    ;  3 * dc + 1
-    sar        blockd, 1               ; >> 1
-    mov           r3d, blockd          ; dc
-    shl        blockd, 4               ; 16 * dc
-    lea        blockd, [blockq+r3+64]  ; 17 * dc + 64
-    sar        blockd, 7               ; >> 7
-
-    INV_TRANS_INIT
-
-    INV_TRANS_PROCESS a
-    RET
-
-INIT_MMX mmxext
-cglobal vc1_inv_trans_8x8_dc, 3,3,0, dest, linesize, block
-    movsx      blockd, WORD [blockq]   ; dc
-    lea        blockd, [blockq*3+1]    ;  3 * dc + 1
-    sar        blockd, 1               ; >> 1
-    lea        blockd, [blockq*3+16]   ;  3 * dc + 16
-    sar        blockd, 5               ; >> 5
-
-    INV_TRANS_INIT
-
-    INV_TRANS_PROCESS a
-    lea         destq, [destq+linesizeq*4]
-    INV_TRANS_PROCESS a
-    RET
diff --git a/libavcodec/x86/vc1dsp_loopfilter.asm b/libavcodec/x86/vc1dsp_loopfilter.asm
new file mode 100644
index 0000000..1838f6f
--- /dev/null
+++ b/libavcodec/x86/vc1dsp_loopfilter.asm
@@ -0,0 +1,317 @@
+;******************************************************************************
+;* VC1 loopfilter optimizations
+;* Copyright (c) 2009 David Conrad
+;*
+;* This file is part of FFmpeg.
+;*
+;* FFmpeg is free software; you can redistribute it and/or
+;* modify it under the terms of the GNU Lesser General Public
+;* License as published by the Free Software Foundation; either
+;* version 2.1 of the License, or (at your option) any later version.
+;*
+;* FFmpeg is distributed in the hope that it will be useful,
+;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;* Lesser General Public License for more details.
+;*
+;* You should have received a copy of the GNU Lesser General Public
+;* License along with FFmpeg; if not, write to the Free Software
+;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;******************************************************************************
+
+%include "libavutil/x86/x86util.asm"
+
+cextern pw_4
+cextern pw_5
+
+section .text
+
+; dst_low, dst_high (src), zero
+; zero-extends one vector from 8 to 16 bits
+%macro UNPACK_8TO16 4
+    mova      m%2, m%3
+    punpckh%1 m%3, m%4
+    punpckl%1 m%2, m%4
+%endmacro
+
+%macro STORE_4_WORDS 6
+%if cpuflag(sse4)
+    pextrw %1, %5, %6+0
+    pextrw %2, %5, %6+1
+    pextrw %3, %5, %6+2
+    pextrw %4, %5, %6+3
+%else
+    movd  %6d, %5
+%if mmsize==16
+    psrldq %5, 4
+%else
+    psrlq  %5, 32
+%endif
+    mov    %1, %6w
+    shr    %6, 16
+    mov    %2, %6w
+    movd  %6d, %5
+    mov    %3, %6w
+    shr    %6, 16
+    mov    %4, %6w
+%endif
+%endmacro
+
+; in:  p1 p0 q0 q1, clobbers p0
+; out: p1 = (2*(p1 - q1) - 5*(p0 - q0) + 4) >> 3
+%macro VC1_LOOP_FILTER_A0 4
+    psubw  %1, %4
+    psubw  %2, %3
+    paddw  %1, %1
+    pmullw %2, [pw_5]
+    psubw  %1, %2
+    paddw  %1, [pw_4]
+    psraw  %1, 3
+%endmacro
+
+; in: p0 q0 a0 a1 a2
+;     m0 m1 m7 m6 m5
+; %1: size
+; out: m0=p0' m1=q0'
+%macro VC1_FILTER 1
+    PABSW   m4, m7
+    PABSW   m3, m6
+    PABSW   m2, m5
+    mova    m6, m4
+    pminsw  m3, m2
+    pcmpgtw m6, m3  ; if (a2 < a0 || a1 < a0)
+    psubw   m3, m4
+    pmullw  m3, [pw_5]   ; 5*(a3 - a0)
+    PABSW   m2, m3
+    psraw   m2, 3   ; abs(d/8)
+    pxor    m7, m3  ; d_sign ^= a0_sign
+
+    pxor    m5, m5
+    movd    m3, r2d
+%if %1 > 4
+    punpcklbw m3, m3
+%endif
+    punpcklbw m3, m5
+    pcmpgtw m3, m4  ; if (a0 < pq)
+    pand    m6, m3
+
+    mova    m3, m0
+    psubw   m3, m1
+    PABSW   m4, m3
+    psraw   m4, 1
+    pxor    m3, m7  ; d_sign ^ clip_sign
+    psraw   m3, 15
+    pminsw  m2, m4  ; min(d, clip)
+    pcmpgtw m4, m5
+    pand    m6, m4  ; filt3 (C return value)
+
+; each set of 4 pixels is not filtered if the 3rd is not
+%if mmsize==16
+    pshuflw m4, m6, 0xaa
+%if %1 > 4
+    pshufhw m4, m4, 0xaa
+%endif
+%else
+    pshufw  m4, m6, 0xaa
+%endif
+    pandn   m3, m4
+    pand    m2, m6
+    pand    m3, m2  ; d final
+
+    psraw   m7, 15
+    pxor    m3, m7
+    psubw   m3, m7
+    psubw   m0, m3
+    paddw   m1, m3
+    packuswb m0, m0
+    packuswb m1, m1
+%endmacro
+
+; 1st param: size of filter
+; 2nd param: mov suffix equivalent to the filter size
+%macro VC1_V_LOOP_FILTER 2
+    pxor      m5, m5
+    mov%2     m6, [r4]
+    mov%2     m4, [r4+r1]
+    mov%2     m7, [r4+2*r1]
+    mov%2     m0, [r4+r3]
+    punpcklbw m6, m5
+    punpcklbw m4, m5
+    punpcklbw m7, m5
+    punpcklbw m0, m5
+
+    VC1_LOOP_FILTER_A0 m6, m4, m7, m0
+    mov%2     m1, [r0]
+    mov%2     m2, [r0+r1]
+    punpcklbw m1, m5
+    punpcklbw m2, m5
+    mova      m4, m0
+    VC1_LOOP_FILTER_A0 m7, m4, m1, m2
+    mov%2     m3, [r0+2*r1]
+    mov%2     m4, [r0+r3]
+    punpcklbw m3, m5
+    punpcklbw m4, m5
+    mova      m5, m1
+    VC1_LOOP_FILTER_A0 m5, m2, m3, m4
+
+    VC1_FILTER %1
+    mov%2 [r4+r3], m0
+    mov%2 [r0],    m1
+%endmacro
+
+; 1st param: size of filter
+;     NOTE: UNPACK_8TO16 this number of 8 bit numbers are in half a register
+; 2nd (optional) param: temp register to use for storing words
+%macro VC1_H_LOOP_FILTER 1-2
+%if %1 == 4
+    movq      m0, [r0     -4]
+    movq      m1, [r0+  r1-4]
+    movq      m2, [r0+2*r1-4]
+    movq      m3, [r0+  r3-4]
+    TRANSPOSE4x4B 0, 1, 2, 3, 4
+%else
+    movq      m0, [r0     -4]
+    movq      m4, [r0+  r1-4]
+    movq      m1, [r0+2*r1-4]
+    movq      m5, [r0+  r3-4]
+    movq      m2, [r4     -4]
+    movq      m6, [r4+  r1-4]
+    movq      m3, [r4+2*r1-4]
+    movq      m7, [r4+  r3-4]
+    punpcklbw m0, m4
+    punpcklbw m1, m5
+    punpcklbw m2, m6
+    punpcklbw m3, m7
+    TRANSPOSE4x4W 0, 1, 2, 3, 4
+%endif
+    pxor      m5, m5
+
+    UNPACK_8TO16 bw, 6, 0, 5
+    UNPACK_8TO16 bw, 7, 1, 5
+    VC1_LOOP_FILTER_A0 m6, m0, m7, m1
+    UNPACK_8TO16 bw, 4, 2, 5
+    mova    m0, m1                      ; m0 = p0
+    VC1_LOOP_FILTER_A0 m7, m1, m4, m2
+    UNPACK_8TO16 bw, 1, 3, 5
+    mova    m5, m4
+    VC1_LOOP_FILTER_A0 m5, m2, m1, m3
+    SWAP 1, 4                           ; m1 = q0
+
+    VC1_FILTER %1
+    punpcklbw m0, m1
+%if %0 > 1
+    STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, %2
+%if %1 > 4
+    psrldq m0, 4
+    STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, %2
+%endif
+%else
+    STORE_4_WORDS [r0-1], [r0+r1-1], [r0+2*r1-1], [r0+r3-1], m0, 0
+    STORE_4_WORDS [r4-1], [r4+r1-1], [r4+2*r1-1], [r4+r3-1], m0, 4
+%endif
+%endmacro
+
+
+%macro START_V_FILTER 0
+    mov  r4, r0
+    lea  r3, [4*r1]
+    sub  r4, r3
+    lea  r3, [r1+2*r1]
+    imul r2, 0x01010101
+%endmacro
+
+%macro START_H_FILTER 1
+    lea  r3, [r1+2*r1]
+%if %1 > 4
+    lea  r4, [r0+4*r1]
+%endif
+    imul r2, 0x01010101
+%endmacro
+
+%macro VC1_LF 0
+cglobal vc1_v_loop_filter_internal
+    VC1_V_LOOP_FILTER 4, d
+    ret
+
+cglobal vc1_h_loop_filter_internal
+    VC1_H_LOOP_FILTER 4, r4
+    ret
+
+; void ff_vc1_v_loop_filter4_mmxext(uint8_t *src, int stride, int pq)
+cglobal vc1_v_loop_filter4, 3,5,0
+    START_V_FILTER
+    call vc1_v_loop_filter_internal
+    RET
+
+; void ff_vc1_h_loop_filter4_mmxext(uint8_t *src, int stride, int pq)
+cglobal vc1_h_loop_filter4, 3,5,0
+    START_H_FILTER 4
+    call vc1_h_loop_filter_internal
+    RET
+
+; void ff_vc1_v_loop_filter8_mmxext(uint8_t *src, int stride, int pq)
+cglobal vc1_v_loop_filter8, 3,5,0
+    START_V_FILTER
+    call vc1_v_loop_filter_internal
+    add  r4, 4
+    add  r0, 4
+    call vc1_v_loop_filter_internal
+    RET
+
+; void ff_vc1_h_loop_filter8_mmxext(uint8_t *src, int stride, int pq)
+cglobal vc1_h_loop_filter8, 3,5,0
+    START_H_FILTER 4
+    call vc1_h_loop_filter_internal
+    lea  r0, [r0+4*r1]
+    call vc1_h_loop_filter_internal
+    RET
+%endmacro
+
+INIT_MMX mmxext
+VC1_LF
+
+INIT_XMM sse2
+; void ff_vc1_v_loop_filter8_sse2(uint8_t *src, int stride, int pq)
+cglobal vc1_v_loop_filter8, 3,5,8
+    START_V_FILTER
+    VC1_V_LOOP_FILTER 8, q
+    RET
+
+; void ff_vc1_h_loop_filter8_sse2(uint8_t *src, int stride, int pq)
+cglobal vc1_h_loop_filter8, 3,6,8
+    START_H_FILTER 8
+    VC1_H_LOOP_FILTER 8, r5
+    RET
+
+INIT_MMX ssse3
+; void ff_vc1_v_loop_filter4_ssse3(uint8_t *src, int stride, int pq)
+cglobal vc1_v_loop_filter4, 3,5,0
+    START_V_FILTER
+    VC1_V_LOOP_FILTER 4, d
+    RET
+
+; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, int stride, int pq)
+cglobal vc1_h_loop_filter4, 3,5,0
+    START_H_FILTER 4
+    VC1_H_LOOP_FILTER 4, r4
+    RET
+
+INIT_XMM ssse3
+; void ff_vc1_v_loop_filter8_ssse3(uint8_t *src, int stride, int pq)
+cglobal vc1_v_loop_filter8, 3,5,8
+    START_V_FILTER
+    VC1_V_LOOP_FILTER 8, q
+    RET
+
+; void ff_vc1_h_loop_filter8_ssse3(uint8_t *src, int stride, int pq)
+cglobal vc1_h_loop_filter8, 3,6,8
+    START_H_FILTER 8
+    VC1_H_LOOP_FILTER 8, r5
+    RET
+
+INIT_XMM sse4
+; void ff_vc1_h_loop_filter8_sse4(uint8_t *src, int stride, int pq)
+cglobal vc1_h_loop_filter8, 3,5,8
+    START_H_FILTER 8
+    VC1_H_LOOP_FILTER 8
+    RET
diff --git a/libavcodec/x86/vc1dsp_mc.asm b/libavcodec/x86/vc1dsp_mc.asm
new file mode 100644
index 0000000..7eaf043
--- /dev/null
+++ b/libavcodec/x86/vc1dsp_mc.asm
@@ -0,0 +1,292 @@
+;******************************************************************************
+;* VC1 motion compensation optimizations
+;* Copyright (c) 2007 Christophe GISQUET <christophe.gisquet at free.fr>
+;*
+;* 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/x86/x86util.asm"
+
+cextern pw_9
+cextern pw_128
+
+section .text
+
+%if HAVE_MMX_INLINE
+
+; XXX some of these macros are not used right now, but they will in the future
+;     when more functions are ported.
+
+%macro OP_PUT 2 ; dst, src
+%endmacro
+
+%macro OP_AVG 2 ; dst, src
+    pavgb           %1, %2
+%endmacro
+
+%macro NORMALIZE_MMX 1 ; shift
+    paddw           m3, m7 ; +bias-r
+    paddw           m4, m7 ; +bias-r
+    psraw           m3, %1
+    psraw           m4, %1
+%endmacro
+
+%macro TRANSFER_DO_PACK 2 ; op, dst
+    packuswb        m3, m4
+    %1              m3, [%2]
+    mova          [%2], m3
+%endmacro
+
+%macro TRANSFER_DONT_PACK 2 ; op, dst
+    %1              m3, [%2]
+    %1              m3, [%2 + mmsize]
+    mova          [%2], m3
+    mova [mmsize + %2], m4
+%endmacro
+
+; see MSPEL_FILTER13_CORE for use as UNPACK macro
+%macro DO_UNPACK 1 ; reg
+    punpcklbw       %1, m0
+%endmacro
+%macro DONT_UNPACK 1 ; reg
+%endmacro
+
+; Compute the rounder 32-r or 8-r and unpacks it to m7
+%macro LOAD_ROUNDER_MMX 1 ; round
+    movd      m7, %1
+    punpcklwd m7, m7
+    punpckldq m7, m7
+%endmacro
+
+%macro SHIFT2_LINE 5 ; off, r0, r1, r2, r3
+    paddw          m%3, m%4
+    movh           m%2, [srcq + stride_neg2]
+    pmullw         m%3, m6
+    punpcklbw      m%2, m0
+    movh           m%5, [srcq + strideq]
+    psubw          m%3, m%2
+    punpcklbw      m%5, m0
+    paddw          m%3, m7
+    psubw          m%3, m%5
+    psraw          m%3, shift
+    movu   [dstq + %1], m%3
+    add           srcq, strideq
+%endmacro
+
+INIT_MMX mmx
+; void ff_vc1_put_ver_16b_shift2_mmx(int16_t *dst, const uint8_t *src,
+;                                    x86_reg stride, int rnd, int64_t shift)
+; Sacrificing m6 makes it possible to pipeline loads from src
+%if ARCH_X86_32
+cglobal vc1_put_ver_16b_shift2, 3,6,0, dst, src, stride
+    DECLARE_REG_TMP     3, 4, 5
+    %define rnd r3mp
+    %define shift qword r4m
+%else ; X86_64
+cglobal vc1_put_ver_16b_shift2, 4,7,0, dst, src, stride
+    DECLARE_REG_TMP     4, 5, 6
+    %define   rnd r3d
+    ; We need shift either in memory or in a mm reg as it's used in psraw
+    ; On WIN64, the arg is already on the stack
+    ; On UNIX64, m5 doesn't seem to be used
+%if WIN64
+    %define shift r4mp
+%else ; UNIX64
+    %define shift m5
+    mova shift, r4q
+%endif ; WIN64
+%endif ; X86_32
+%define stride_neg2 t0q
+%define stride_9minus4 t1q
+%define i t2q
+    mov       stride_neg2, strideq
+    neg       stride_neg2
+    add       stride_neg2, stride_neg2
+    lea    stride_9minus4, [strideq * 9 - 4]
+    mov                 i, 3
+    LOAD_ROUNDER_MMX  rnd
+    mova               m6, [pw_9]
+    pxor               m0, m0
+.loop:
+    movh               m2, [srcq]
+    add              srcq, strideq
+    movh               m3, [srcq]
+    punpcklbw          m2, m0
+    punpcklbw          m3, m0
+    SHIFT2_LINE         0, 1, 2, 3, 4
+    SHIFT2_LINE        24, 2, 3, 4, 1
+    SHIFT2_LINE        48, 3, 4, 1, 2
+    SHIFT2_LINE        72, 4, 1, 2, 3
+    SHIFT2_LINE        96, 1, 2, 3, 4
+    SHIFT2_LINE       120, 2, 3, 4, 1
+    SHIFT2_LINE       144, 3, 4, 1, 2
+    SHIFT2_LINE       168, 4, 1, 2, 3
+    sub              srcq, stride_9minus4
+    add              dstq, 8
+    dec                 i
+        jnz         .loop
+    REP_RET
+%undef rnd
+%undef shift
+%undef stride_neg2
+%undef stride_9minus4
+%undef i
+
+; void ff_vc1_*_hor_16b_shift2_mmx(uint8_t *dst, x86_reg stride,
+;                                  const int16_t *src, int rnd);
+; Data is already unpacked, so some operations can directly be made from
+; memory.
+%macro HOR_16B_SHIFT2 2 ; op, opname
+cglobal vc1_%2_hor_16b_shift2, 4, 5, 0, dst, stride, src, rnd, h
+    mov                hq, 8
+    sub              srcq, 2
+    sub              rndd, (-1+9+9-1) * 1024 ; add -1024 bias
+    LOAD_ROUNDER_MMX rndq
+    mova               m5, [pw_9]
+    mova               m6, [pw_128]
+    pxor               m0, m0
+
+.loop:
+    mova               m1, [srcq + 2 * 0]
+    mova               m2, [srcq + 2 * 0 + mmsize]
+    mova               m3, [srcq + 2 * 1]
+    mova               m4, [srcq + 2 * 1 + mmsize]
+    paddw              m3, [srcq + 2 * 2]
+    paddw              m4, [srcq + 2 * 2 + mmsize]
+    paddw              m1, [srcq + 2 * 3]
+    paddw              m2, [srcq + 2 * 3 + mmsize]
+    pmullw             m3, m5
+    pmullw             m4, m5
+    psubw              m3, m1
+    psubw              m4, m2
+    NORMALIZE_MMX      7
+    ; remove bias
+    paddw              m3, m6
+    paddw              m4, m6
+    TRANSFER_DO_PACK   %1, dstq
+    add              srcq, 24
+    add              dstq, strideq
+    dec                hq
+        jnz         .loop
+
+    RET
+%endmacro
+
+INIT_MMX mmx
+HOR_16B_SHIFT2 OP_PUT, put
+
+INIT_MMX mmxext
+HOR_16B_SHIFT2 OP_AVG, avg
+%endif ; HAVE_MMX_INLINE
+
+%macro INV_TRANS_INIT 0
+    movsxdifnidn linesizeq, linesized
+    movd       m0, blockd
+    SPLATW     m0, m0
+    pxor       m1, m1
+    psubw      m1, m0
+    packuswb   m0, m0
+    packuswb   m1, m1
+
+    DEFINE_ARGS dest, linesize, linesize3
+    lea    linesize3q, [linesizeq*3]
+%endmacro
+
+%macro INV_TRANS_PROCESS 1
+    mov%1                  m2, [destq+linesizeq*0]
+    mov%1                  m3, [destq+linesizeq*1]
+    mov%1                  m4, [destq+linesizeq*2]
+    mov%1                  m5, [destq+linesize3q]
+    paddusb                m2, m0
+    paddusb                m3, m0
+    paddusb                m4, m0
+    paddusb                m5, m0
+    psubusb                m2, m1
+    psubusb                m3, m1
+    psubusb                m4, m1
+    psubusb                m5, m1
+    mov%1 [linesizeq*0+destq], m2
+    mov%1 [linesizeq*1+destq], m3
+    mov%1 [linesizeq*2+destq], m4
+    mov%1 [linesize3q +destq], m5
+%endmacro
+
+; ff_vc1_inv_trans_?x?_dc_mmxext(uint8_t *dest, int linesize, int16_t *block)
+INIT_MMX mmxext
+cglobal vc1_inv_trans_4x4_dc, 3,4,0, dest, linesize, block
+    movsx         r3d, WORD [blockq]
+    mov        blockd, r3d             ; dc
+    shl        blockd, 4               ; 16 * dc
+    lea        blockd, [blockq+r3+4]   ; 17 * dc + 4
+    sar        blockd, 3               ; >> 3
+    mov           r3d, blockd          ; dc
+    shl        blockd, 4               ; 16 * dc
+    lea        blockd, [blockq+r3+64]  ; 17 * dc + 64
+    sar        blockd, 7               ; >> 7
+
+    INV_TRANS_INIT
+
+    INV_TRANS_PROCESS h
+    RET
+
+INIT_MMX mmxext
+cglobal vc1_inv_trans_4x8_dc, 3,4,0, dest, linesize, block
+    movsx         r3d, WORD [blockq]
+    mov        blockd, r3d             ; dc
+    shl        blockd, 4               ; 16 * dc
+    lea        blockd, [blockq+r3+4]   ; 17 * dc + 4
+    sar        blockd, 3               ; >> 3
+    shl        blockd, 2               ;  4 * dc
+    lea        blockd, [blockq*3+64]   ; 12 * dc + 64
+    sar        blockd, 7               ; >> 7
+
+    INV_TRANS_INIT
+
+    INV_TRANS_PROCESS h
+    lea         destq, [destq+linesizeq*4]
+    INV_TRANS_PROCESS h
+    RET
+
+INIT_MMX mmxext
+cglobal vc1_inv_trans_8x4_dc, 3,4,0, dest, linesize, block
+    movsx      blockd, WORD [blockq]   ; dc
+    lea        blockd, [blockq*3+1]    ;  3 * dc + 1
+    sar        blockd, 1               ; >> 1
+    mov           r3d, blockd          ; dc
+    shl        blockd, 4               ; 16 * dc
+    lea        blockd, [blockq+r3+64]  ; 17 * dc + 64
+    sar        blockd, 7               ; >> 7
+
+    INV_TRANS_INIT
+
+    INV_TRANS_PROCESS a
+    RET
+
+INIT_MMX mmxext
+cglobal vc1_inv_trans_8x8_dc, 3,3,0, dest, linesize, block
+    movsx      blockd, WORD [blockq]   ; dc
+    lea        blockd, [blockq*3+1]    ;  3 * dc + 1
+    sar        blockd, 1               ; >> 1
+    lea        blockd, [blockq*3+16]   ;  3 * dc + 16
+    sar        blockd, 5               ; >> 5
+
+    INV_TRANS_INIT
+
+    INV_TRANS_PROCESS a
+    lea         destq, [destq+linesizeq*4]
+    INV_TRANS_PROCESS a
+    RET
diff --git a/libavcodec/x86/vc1dsp_mmx.c b/libavcodec/x86/vc1dsp_mmx.c
index 8325648..da32a3e 100644
--- a/libavcodec/x86/vc1dsp_mmx.c
+++ b/libavcodec/x86/vc1dsp_mmx.c
@@ -76,7 +76,7 @@ void ff_vc1_avg_hor_16b_shift2_mmxext(uint8_t *dst, x86_reg stride,
 
 /**
  * Purely vertical or horizontal 1/2 shift interpolation.
- * Sacrify mm6 for *9 factor.
+ * Sacrifice mm6 for *9 factor.
  */
 #define VC1_SHIFT2(OP, OPNAME)\
 static void OPNAME ## vc1_shift2_mmx(uint8_t *dst, const uint8_t *src,\
@@ -135,7 +135,7 @@ VC1_SHIFT2(OP_AVG, avg_)
 /**
  * Core of the 1/4 and 3/4 shift bicubic interpolation.
  *
- * @param UNPACK  Macro unpacking arguments from 8 to 16bits (can be empty).
+ * @param UNPACK  Macro unpacking arguments from 8 to 16 bits (can be empty).
  * @param MOVQ    "movd 1" or "movq 2", if data read is already unpacked.
  * @param A1      Address of 1st tap (beware of unpacked/packed).
  * @param A2      Address of 2nd tap
@@ -175,7 +175,7 @@ VC1_SHIFT2(OP_AVG, avg_)
      "paddw     %%mm2, %%mm4    \n\t" /* 4,53,18,-3 */
 
 /**
- * Macro to build the vertical 16bits version of vc1_put_shift[13].
+ * Macro to build the vertical 16 bits version of vc1_put_shift[13].
  * Here, offset=src_stride. Parameters passed A1 to A4 must use
  * %3 (src_stride) and %4 (3*src_stride).
  *
@@ -233,8 +233,8 @@ vc1_put_ver_16b_ ## NAME ## _mmx(int16_t *dst, const uint8_t *src,      \
 }
 
 /**
- * Macro to build the horizontal 16bits version of vc1_put_shift[13].
- * Here, offset=16bits, so parameters passed A1 to A4 should be simple.
+ * Macro to build the horizontal 16 bits version of vc1_put_shift[13].
+ * Here, offset=16 bits, so parameters passed A1 to A4 should be simple.
  *
  * @param  NAME   Either 1 or 3
  * @see MSPEL_FILTER13_CORE for information on A1->A4
@@ -271,7 +271,7 @@ OPNAME ## vc1_hor_16b_ ## NAME ## _mmx(uint8_t *dst, x86_reg stride,    \
 }
 
 /**
- * Macro to build the 8bits, any direction, version of vc1_put_shift[13].
+ * Macro to build the 8 bits, any direction, version of vc1_put_shift[13].
  * Here, offset=src_stride. Parameters passed A1 to A4 must use
  * %3 (offset) and %4 (3*offset).
  *
diff --git a/libavcodec/x86/vp6dsp_init.c b/libavcodec/x86/vp6dsp_init.c
index 82baee7..81d371d 100644
--- a/libavcodec/x86/vp6dsp_init.c
+++ b/libavcodec/x86/vp6dsp_init.c
@@ -22,7 +22,6 @@
 
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/vp56dsp.h"
 
diff --git a/libavcodec/x86/vp8dsp_init.c b/libavcodec/x86/vp8dsp_init.c
index 8d5d033..897d5a0 100644
--- a/libavcodec/x86/vp8dsp_init.c
+++ b/libavcodec/x86/vp8dsp_init.c
@@ -23,7 +23,6 @@
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
 #include "libavutil/mem.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/vp8dsp.h"
 
diff --git a/libavcodec/xan.c b/libavcodec/xan.c
index 662386a..9609f83 100644
--- a/libavcodec/xan.c
+++ b/libavcodec/xan.c
@@ -1,6 +1,6 @@
 /*
  * Wing Commander/Xan Video Decoder
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (C) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavcodec/xsubdec.c b/libavcodec/xsubdec.c
index 540607a..b024535 100644
--- a/libavcodec/xsubdec.c
+++ b/libavcodec/xsubdec.c
@@ -57,8 +57,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
     int64_t packet_time = 0;
     GetBitContext gb;
     int has_alpha = avctx->codec_tag == MKTAG('D','X','S','A');
-    AVSubtitleRect *rect;
-    int j;
 
     // check that at least header fits
     if (buf_size < 27 + 7 * 2 + 4 * (3 + has_alpha)) {
@@ -134,11 +132,15 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
 
 #if FF_API_AVPICTURE
 FF_DISABLE_DEPRECATION_WARNINGS
+{
+    AVSubtitleRect *rect;
+    int j;
     rect = sub->rects[0];
     for (j = 0; j < 4; j++) {
         rect->pict.data[j] = rect->data[j];
         rect->pict.linesize[j] = rect->linesize[j];
     }
+}
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
diff --git a/libavcodec/ylc.c b/libavcodec/ylc.c
new file mode 100644
index 0000000..95a5e05
--- /dev/null
+++ b/libavcodec/ylc.c
@@ -0,0 +1,472 @@
+/*
+ * YUY2 Lossless Codec
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libavutil/imgutils.h"
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
+#include "avcodec.h"
+#include "bswapdsp.h"
+#include "get_bits.h"
+#include "huffyuvdsp.h"
+#include "internal.h"
+#include "unary.h"
+
+typedef struct YLCContext {
+    VLC vlc[4];
+    uint32_t table[1024];
+    uint8_t *table_bits;
+    uint8_t *bitstream_bits;
+    int table_bits_size;
+    int bitstream_bits_size;
+    BswapDSPContext bdsp;
+} YLCContext;
+
+static av_cold int decode_init(AVCodecContext *avctx)
+{
+    YLCContext *s = avctx->priv_data;
+
+    avctx->pix_fmt = AV_PIX_FMT_YUYV422;
+    ff_bswapdsp_init(&s->bdsp);
+
+    return 0;
+}
+
+typedef struct Node {
+    int16_t  sym;
+    int16_t  n0;
+    uint32_t count;
+    int16_t  l, r;
+} Node;
+
+static void get_tree_codes(uint32_t *bits, int16_t *lens, uint8_t *xlat,
+                           Node *nodes, int node,
+                           uint32_t pfx, int pl, int *pos)
+{
+    int s;
+
+    s = nodes[node].sym;
+    if (s != -1) {
+        bits[*pos] = (~pfx) & ((1 << FFMAX(pl, 1)) - 1);
+        lens[*pos] = FFMAX(pl, 1);
+        xlat[*pos] = s + (pl == 0);
+        (*pos)++;
+    } else {
+        pfx <<= 1;
+        pl++;
+        get_tree_codes(bits, lens, xlat, nodes, nodes[node].l, pfx, pl,
+                       pos);
+        pfx |= 1;
+        get_tree_codes(bits, lens, xlat, nodes, nodes[node].r, pfx, pl,
+                       pos);
+    }
+}
+
+static int build_vlc(AVCodecContext *avctx, VLC *vlc, const uint32_t *table)
+{
+    Node nodes[512];
+    uint32_t bits[256];
+    int16_t lens[256];
+    uint8_t xlat[256];
+    int cur_node, i, j, pos = 0;
+
+    ff_free_vlc(vlc);
+
+    for (i = 0; i < 256; i++) {
+        nodes[i].count = table[i];
+        nodes[i].sym   = i;
+        nodes[i].n0    = -2;
+        nodes[i].l     = i;
+        nodes[i].r     = i;
+    }
+
+    cur_node = 256;
+    j = 0;
+    do {
+        for (i = 0; ; i++) {
+            int new_node = j;
+            int first_node = cur_node;
+            int second_node = cur_node;
+            int nd, st;
+
+            nodes[cur_node].count = -1;
+
+            do {
+                int val = nodes[new_node].count;
+                if (val && (val < nodes[first_node].count)) {
+                    if (val >= nodes[second_node].count) {
+                        first_node = new_node;
+                    } else {
+                        first_node = second_node;
+                        second_node = new_node;
+                    }
+                }
+                new_node += 1;
+            } while (new_node != cur_node);
+
+            if (first_node == cur_node)
+                break;
+
+            nd = nodes[second_node].count;
+            st = nodes[first_node].count;
+            nodes[second_node].count = 0;
+            nodes[first_node].count  = 0;
+            nodes[cur_node].count = nd + st;
+            nodes[cur_node].sym = -1;
+            nodes[cur_node].n0 = cur_node;
+            nodes[cur_node].l = first_node;
+            nodes[cur_node].r = second_node;
+            cur_node++;
+        }
+        j++;
+    } while (cur_node - 256 == j);
+
+    get_tree_codes(bits, lens, xlat, nodes, cur_node - 1, 0, 0, &pos);
+
+    return ff_init_vlc_sparse(vlc, 10, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0);
+}
+
+static const uint8_t table_y1[] = {
+    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
+    0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
+    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+    0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+    0x02, 0x00,
+};
+
+static const uint8_t table_u[] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x00,
+};
+
+static const uint8_t table_y2[] = {
+    0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
+    0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC,
+    0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE,
+    0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFC, 0xFC,
+    0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF,
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFD, 0xFD, 0xFD,
+    0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+    0x00, 0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE,
+    0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
+    0x01, 0x01, 0x01, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE,
+    0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
+    0x01, 0x01, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
+    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
+    0x02, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00,
+    0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
+    0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+    0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0xFF,
+    0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+    0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF,
+    0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
+    0x02, 0x02, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0xFF,
+    0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
+    0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x01,
+    0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
+    0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01,
+    0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04,
+    0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+    0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04,
+    0x04, 0x00,
+};
+
+static const uint8_t table_v[] = {
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
+    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
+    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
+    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
+    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
+    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
+    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
+    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
+    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF,
+    0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01,
+    0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00,
+    0x01, 0x00,
+};
+
+static int decode_frame(AVCodecContext *avctx,
+                        void *data, int *got_frame,
+                        AVPacket *avpkt)
+{
+    int TL[4] = { 128, 128, 128, 128 };
+    int L[4]  = { 128, 128, 128, 128 };
+    YLCContext *s = avctx->priv_data;
+    const uint8_t *buf = avpkt->data;
+    int ret, x, y, toffset, boffset;
+    AVFrame * const p = data;
+    GetBitContext gb;
+    uint8_t *dst;
+
+    if (avpkt->size <= 16)
+        return AVERROR_INVALIDDATA;
+
+    if (AV_RL32(buf) != MKTAG('Y', 'L', 'C', '0') ||
+        AV_RL32(buf + 4) != 0)
+        return AVERROR_INVALIDDATA;
+
+    toffset = AV_RL32(buf + 8);
+    if (toffset < 16 || toffset >= avpkt->size)
+        return AVERROR_INVALIDDATA;
+
+    boffset = AV_RL32(buf + 12);
+    if (toffset >= boffset || boffset >= avpkt->size)
+        return AVERROR_INVALIDDATA;
+
+    if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
+        return ret;
+
+    av_fast_malloc(&s->table_bits, &s->table_bits_size,
+                   boffset - toffset + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!s->table_bits)
+        return AVERROR(ENOMEM);
+
+    memcpy(s->table_bits, avpkt->data + toffset, boffset - toffset);
+    memset(s->table_bits + boffset - toffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+    s->bdsp.bswap_buf((uint32_t *) s->table_bits,
+                      (uint32_t *) s->table_bits,
+                      (boffset - toffset + 3) >> 2);
+    if ((ret = init_get_bits8(&gb, s->table_bits, boffset - toffset)) < 0)
+        return ret;
+
+    for (x = 0; x < 1024; x++) {
+        unsigned len = get_unary(&gb, 1, 31);
+        uint32_t val = ((1U << len) - 1) + get_bits_long(&gb, len);
+
+        s->table[x] = val;
+    }
+
+    ret = build_vlc(avctx, &s->vlc[0], &s->table[0  ]);
+    if (ret < 0)
+        return ret;
+    ret = build_vlc(avctx, &s->vlc[1], &s->table[256]);
+    if (ret < 0)
+        return ret;
+    ret = build_vlc(avctx, &s->vlc[2], &s->table[512]);
+    if (ret < 0)
+        return ret;
+    ret = build_vlc(avctx, &s->vlc[3], &s->table[768]);
+    if (ret < 0)
+        return ret;
+
+    av_fast_malloc(&s->bitstream_bits, &s->bitstream_bits_size,
+                   avpkt->size - boffset + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!s->bitstream_bits)
+        return AVERROR(ENOMEM);
+
+    memcpy(s->bitstream_bits, avpkt->data + boffset, avpkt->size - boffset);
+    memset(s->bitstream_bits + avpkt->size - boffset, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+    s->bdsp.bswap_buf((uint32_t *) s->bitstream_bits,
+                      (uint32_t *) s->bitstream_bits,
+                      (avpkt->size - boffset) >> 2);
+    if ((ret = init_get_bits8(&gb, s->bitstream_bits, avpkt->size - boffset)) < 0)
+        return ret;
+
+    dst = p->data[0];
+    for (y = 0; y < avctx->height; y++) {
+        memset(dst, 0, avctx->width * 2);
+        dst += p->linesize[0];
+    }
+
+    dst = p->data[0];
+    for (y = 0; y < avctx->height; y++) {
+        for (x = 0; x < avctx->width * 2 && y < avctx->height;) {
+            if (get_bits_left(&gb) <= 0)
+                return AVERROR_INVALIDDATA;
+
+            if (get_bits1(&gb)) {
+                int val = get_vlc2(&gb, s->vlc[0].table, s->vlc[0].bits, 3);
+                if (val < 0) {
+                    return AVERROR_INVALIDDATA;
+                } else if (val < 0xE1) {
+                    dst[x    ] = table_y1[val];
+                    dst[x + 1] = table_u[val];
+                    dst[x + 2] = table_y2[val];
+                    dst[x + 3] = table_v[val];
+                    x += 4;
+                } else {
+                    int incr = (val - 0xDF) * 4;
+                    if (x + incr >= avctx->width * 2) {
+                        int iy = ((x + incr) / (avctx->width * 2));
+                        x  = (x + incr) % (avctx->width * 2);
+                        y += iy;
+                        dst += iy * p->linesize[0];
+                    } else {
+                        x += incr;
+                    }
+                }
+            } else {
+                int y1, y2, u, v;
+
+                y1 = get_vlc2(&gb, s->vlc[1].table, s->vlc[1].bits, 3);
+                u  = get_vlc2(&gb, s->vlc[2].table, s->vlc[2].bits, 3);
+                y2 = get_vlc2(&gb, s->vlc[1].table, s->vlc[1].bits, 3);
+                v  = get_vlc2(&gb, s->vlc[3].table, s->vlc[3].bits, 3);
+                if (y1 < 0 || y2 < 0 || u < 0 || v < 0)
+                    return AVERROR_INVALIDDATA;
+                dst[x    ] = y1;
+                dst[x + 1] = u;
+                dst[x + 2] = y1 + y2;
+                dst[x + 3] = v;
+                x += 4;
+            }
+        }
+        dst += p->linesize[0];
+    }
+
+    dst = p->data[0];
+    for (x = 0; x < avctx->width * 2; x += 4) {
+        dst[x    ] =        dst[x    ] + L[0];
+        dst[x + 2] = L[0] = dst[x + 2] + L[0];
+        L[1] = dst[x + 1] + L[1];
+        dst[x + 1] = L[1];
+        L[2] = dst[x + 3] + L[2];
+        dst[x + 3] = L[2];
+    }
+    dst += p->linesize[0];
+
+    for (y = 1; y < avctx->height; y++) {
+        x = 0;
+        dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
+        dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
+        TL[0] = dst[x + 2 - p->linesize[0]];
+        L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
+        dst[x + 1] = L[1];
+        TL[1] = dst[x + 1 - p->linesize[0]];
+        L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
+        dst[x + 3] = L[2];
+        TL[2] = dst[x + 3 - p->linesize[0]];
+        for (x = 4; x < avctx->width * 2; x += 4) {
+            dst[x    ] =        dst[x    ] + L[0] + dst[x + 0 - p->linesize[0]] - TL[0];
+            dst[x + 2] = L[0] = dst[x + 2] + L[0] + dst[x + 2 - p->linesize[0]] - TL[0];
+            TL[0] = dst[x + 2 - p->linesize[0]];
+            L[1] = dst[x + 1] + L[1] + dst[x + 1 - p->linesize[0]] - TL[1];
+            dst[x + 1] = L[1];
+            TL[1] = dst[x + 1 - p->linesize[0]];
+            L[2] = dst[x + 3] + L[2] + dst[x + 3 - p->linesize[0]] - TL[2];
+            dst[x + 3] = L[2];
+            TL[2] = dst[x + 3 - p->linesize[0]];
+        }
+        dst += p->linesize[0];
+    }
+
+    p->pict_type = AV_PICTURE_TYPE_I;
+    p->key_frame = 1;
+    *got_frame   = 1;
+
+    return avpkt->size;
+}
+
+static av_cold int decode_end(AVCodecContext *avctx)
+{
+    YLCContext *s = avctx->priv_data;
+
+    ff_free_vlc(&s->vlc[0]);
+    ff_free_vlc(&s->vlc[1]);
+    ff_free_vlc(&s->vlc[2]);
+    ff_free_vlc(&s->vlc[3]);
+
+    return 0;
+}
+
+AVCodec ff_ylc_decoder = {
+    .name           = "ylc",
+    .long_name      = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_YLC,
+    .priv_data_size = sizeof(YLCContext),
+    .init           = decode_init,
+    .close          = decode_end,
+    .decode         = decode_frame,
+    .capabilities   = AV_CODEC_CAP_DR1,
+};
diff --git a/libavcodec/yop.c b/libavcodec/yop.c
index c6b19ec..32cfea2 100644
--- a/libavcodec/yop.c
+++ b/libavcodec/yop.c
@@ -22,11 +22,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavutil/intreadwrite.h"
+#include <string.h>
+
 #include "libavutil/imgutils.h"
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
 
 #include "avcodec.h"
-#include "get_bits.h"
 #include "internal.h"
 
 typedef struct YopDecContext {
diff --git a/libavcodec/zmbv.c b/libavcodec/zmbv.c
index 25a1cd2..f126515 100644
--- a/libavcodec/zmbv.c
+++ b/libavcodec/zmbv.c
@@ -513,7 +513,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
 
-    if (c->comp == 0) { //Uncompressed data
+    if (c->comp == 0) { // uncompressed data
         if (c->decomp_size < len) {
             av_log(avctx, AV_LOG_ERROR, "Buffer too small\n");
             return AVERROR_INVALIDDATA;
diff --git a/libavdevice/Makefile b/libavdevice/Makefile
index 8394e87..585827b 100644
--- a/libavdevice/Makefile
+++ b/libavdevice/Makefile
@@ -9,6 +9,8 @@ OBJS    = alldevices.o                                                  \
           avdevice.o                                                    \
           utils.o                                                       \
 
+OBJS-$(HAVE_LIBC_MSVCRT)                 += file_open.o
+
 # input/output devices
 OBJS-$(CONFIG_ALSA_INDEV)                += alsa_dec.o alsa.o timefilter.o
 OBJS-$(CONFIG_ALSA_OUTDEV)               += alsa_enc.o alsa.o
@@ -53,8 +55,6 @@ OBJS-$(CONFIG_XV_OUTDEV)                 += xv.o
 OBJS-$(CONFIG_LIBCDIO_INDEV)             += libcdio.o
 OBJS-$(CONFIG_LIBDC1394_INDEV)           += libdc1394.o
 
-OBJS-$(HAVE_LIBC_MSVCRT)                 += file_open.o
-
 # Windows resource file
 SLIBOBJS-$(HAVE_GNU_WINDRES)             += avdeviceres.o
 
@@ -70,4 +70,4 @@ SKIPHEADERS-$(CONFIG_V4L2_OUTDEV)        += v4l2-common.h
 SKIPHEADERS-$(HAVE_ALSA_ASOUNDLIB_H)     += alsa.h
 SKIPHEADERS-$(HAVE_SNDIO_H)              += sndio.h
 
-TESTPROGS = timefilter
+TESTPROGS-$(CONFIG_JACK_INDEV)           += timefilter
diff --git a/libavdevice/alsa.c b/libavdevice/alsa.c
index 75ac444..8d27913 100644
--- a/libavdevice/alsa.c
+++ b/libavdevice/alsa.c
@@ -175,7 +175,7 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,
     snd_pcm_t *h;
     snd_pcm_hw_params_t *hw_params;
     snd_pcm_uframes_t buffer_size, period_size;
-    uint64_t layout = ctx->streams[0]->codec->channel_layout;
+    uint64_t layout = ctx->streams[0]->codecpar->channel_layout;
 
     if (ctx->filename[0] == 0) audio_device = "default";
     else                       audio_device = ctx->filename;
diff --git a/libavdevice/alsa_dec.c b/libavdevice/alsa_dec.c
index 71a6ef4..c50ce71 100644
--- a/libavdevice/alsa_dec.c
+++ b/libavdevice/alsa_dec.c
@@ -79,11 +79,11 @@ static av_cold int audio_read_header(AVFormatContext *s1)
     }
 
     /* take real parameters */
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = codec_id;
-    st->codec->sample_rate = s->sample_rate;
-    st->codec->channels    = s->channels;
-    st->codec->frame_size = s->frame_size;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = codec_id;
+    st->codecpar->sample_rate = s->sample_rate;
+    st->codecpar->channels    = s->channels;
+    st->codecpar->frame_size = s->frame_size;
     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
     /* microseconds instead of seconds, MHz instead of Hz */
     s->timefilter = ff_timefilter_new(1000000.0 / s->sample_rate,
diff --git a/libavdevice/alsa_enc.c b/libavdevice/alsa_enc.c
index 10289a9..bddc61f 100644
--- a/libavdevice/alsa_enc.c
+++ b/libavdevice/alsa_enc.c
@@ -55,20 +55,20 @@ static av_cold int audio_write_header(AVFormatContext *s1)
     enum AVCodecID codec_id;
     int res;
 
-    if (s1->nb_streams != 1 || s1->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
+    if (s1->nb_streams != 1 || s1->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
         av_log(s1, AV_LOG_ERROR, "Only a single audio stream is supported.\n");
         return AVERROR(EINVAL);
     }
     st = s1->streams[0];
 
-    sample_rate = st->codec->sample_rate;
-    codec_id    = st->codec->codec_id;
+    sample_rate = st->codecpar->sample_rate;
+    codec_id    = st->codecpar->codec_id;
     res = ff_alsa_open(s1, SND_PCM_STREAM_PLAYBACK, &sample_rate,
-        st->codec->channels, &codec_id);
-    if (sample_rate != st->codec->sample_rate) {
+        st->codecpar->channels, &codec_id);
+    if (sample_rate != st->codecpar->sample_rate) {
         av_log(s1, AV_LOG_ERROR,
                "sample rate %d not available, nearest is %d\n",
-               st->codec->sample_rate, sample_rate);
+               st->codecpar->sample_rate, sample_rate);
         goto fail;
     }
     avpriv_set_pts_info(st, 64, 1, sample_rate);
@@ -124,7 +124,7 @@ static int audio_write_frame(AVFormatContext *s1, int stream_index,
 
     /* ff_alsa_open() should have accepted only supported formats */
     if ((flags & AV_WRITE_UNCODED_FRAME_QUERY))
-        return av_sample_fmt_is_planar(s1->streams[stream_index]->codec->sample_fmt) ?
+        return av_sample_fmt_is_planar(s1->streams[stream_index]->codecpar->format) ?
                AVERROR(EINVAL) : 0;
     /* set only used fields */
     pkt.data     = (*frame)->data[0];
diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index 763e675..e2ddf47 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -560,11 +560,11 @@ static int get_video_config(AVFormatContext *s)
     image_buffer      = CMSampleBufferGetImageBuffer(ctx->current_frame);
     image_buffer_size = CVImageBufferGetEncodedSize(image_buffer);
 
-    stream->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
-    stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    stream->codec->width      = (int)image_buffer_size.width;
-    stream->codec->height     = (int)image_buffer_size.height;
-    stream->codec->pix_fmt    = ctx->pixel_format;
+    stream->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
+    stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    stream->codecpar->width      = (int)image_buffer_size.width;
+    stream->codecpar->height     = (int)image_buffer_size.height;
+    stream->codecpar->format     = ctx->pixel_format;
 
     CFRelease(ctx->current_frame);
     ctx->current_frame = nil;
@@ -603,10 +603,10 @@ static int get_audio_config(AVFormatContext *s)
         return 1;
     }
 
-    stream->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
-    stream->codec->sample_rate    = basic_desc->mSampleRate;
-    stream->codec->channels       = basic_desc->mChannelsPerFrame;
-    stream->codec->channel_layout = av_get_default_channel_layout(stream->codec->channels);
+    stream->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    stream->codecpar->sample_rate    = basic_desc->mSampleRate;
+    stream->codecpar->channels       = basic_desc->mChannelsPerFrame;
+    stream->codecpar->channel_layout = av_get_default_channel_layout(stream->codecpar->channels);
 
     ctx->audio_channels        = basic_desc->mChannelsPerFrame;
     ctx->audio_bits_per_sample = basic_desc->mBitsPerChannel;
@@ -620,22 +620,22 @@ static int get_audio_config(AVFormatContext *s)
         ctx->audio_float &&
         ctx->audio_bits_per_sample == 32 &&
         ctx->audio_packed) {
-        stream->codec->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
+        stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_F32BE : AV_CODEC_ID_PCM_F32LE;
     } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
         ctx->audio_signed_integer &&
         ctx->audio_bits_per_sample == 16 &&
         ctx->audio_packed) {
-        stream->codec->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
+        stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S16BE : AV_CODEC_ID_PCM_S16LE;
     } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
         ctx->audio_signed_integer &&
         ctx->audio_bits_per_sample == 24 &&
         ctx->audio_packed) {
-        stream->codec->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
+        stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
     } else if (basic_desc->mFormatID == kAudioFormatLinearPCM &&
         ctx->audio_signed_integer &&
         ctx->audio_bits_per_sample == 32 &&
         ctx->audio_packed) {
-        stream->codec->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
+        stream->codecpar->codec_id = ctx->audio_be ? AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
     } else {
         av_log(s, AV_LOG_ERROR, "audio format is not supported\n");
         return 1;
@@ -1021,7 +1021,7 @@ static const AVOption options[] = {
     { "video_device_index", "select video device by index for devices with same name (starts at 0)", offsetof(AVFContext, video_device_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     { "audio_device_index", "select audio device by index for devices with same name (starts at 0)", offsetof(AVFContext, audio_device_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     { "pixel_format", "set pixel format", offsetof(AVFContext, pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_YUV420P}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM},
-    { "framerate", "set frame rate", offsetof(AVFContext, framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
+    { "framerate", "set frame rate", offsetof(AVFContext, framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     { "video_size", "set video size", offsetof(AVFContext, width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
     { "capture_cursor", "capture the screen cursor", offsetof(AVFContext, capture_cursor), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
     { "capture_mouse_clicks", "capture the screen mouse clicks", offsetof(AVFContext, capture_mouse_clicks), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
diff --git a/libavdevice/bktr.c b/libavdevice/bktr.c
index c8a8953..2902425 100644
--- a/libavdevice/bktr.c
+++ b/libavdevice/bktr.c
@@ -286,14 +286,12 @@ static int grab_read_header(AVFormatContext *s1)
 
     s->per_frame = ((uint64_t)1000000 * framerate.den) / framerate.num;
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->pix_fmt = AV_PIX_FMT_YUV420P;
-    st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
-    st->codec->width = s->width;
-    st->codec->height = s->height;
-    st->codec->time_base.den = framerate.num;
-    st->codec->time_base.num = framerate.den;
-
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->format = AV_PIX_FMT_YUV420P;
+    st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->width = s->width;
+    st->codecpar->height = s->height;
+    st->avg_frame_rate = framerate;
 
     if (bktr_init(s1->filename, s->width, s->height, s->standard,
                   &s->video_fd, &s->tuner_fd, -1, 0.0) < 0) {
diff --git a/libavdevice/caca.c b/libavdevice/caca.c
index 75adc35..93cc0ff 100644
--- a/libavdevice/caca.c
+++ b/libavdevice/caca.c
@@ -92,7 +92,7 @@ static int caca_write_header(AVFormatContext *s)
 {
     CACAContext *c = s->priv_data;
     AVStream *st = s->streams[0];
-    AVCodecContext *encctx = st->codec;
+    AVCodecParameters *encctx = st->codecpar;
     int ret, bpp;
 
     c->ctx = s;
@@ -126,10 +126,10 @@ static int caca_write_header(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    if (encctx->pix_fmt != AV_PIX_FMT_RGB24) {
+    if (encctx->format != AV_PIX_FMT_RGB24) {
         av_log(s, AV_LOG_ERROR,
                "Unsupported pixel format '%s', choose rgb24\n",
-               av_get_pix_fmt_name(encctx->pix_fmt));
+               av_get_pix_fmt_name(encctx->format));
         return AVERROR(EINVAL);
     }
 
@@ -140,7 +140,7 @@ static int caca_write_header(AVFormatContext *s)
         goto fail;
     }
 
-    bpp = av_get_bits_per_pixel(av_pix_fmt_desc_get(encctx->pix_fmt));
+    bpp = av_get_bits_per_pixel(av_pix_fmt_desc_get(encctx->format));
     c->dither = caca_create_dither(bpp, encctx->width, encctx->height,
                                    bpp / 8 * encctx->width,
                                    0x0000ff, 0x00ff00, 0xff0000, 0);
diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp
index 9d7dc97..1c305f3 100644
--- a/libavdevice/decklink_dec.cpp
+++ b/libavdevice/decklink_dec.cpp
@@ -249,9 +249,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
     // Handle Video Frame
     if (videoFrame) {
         AVPacket pkt;
-        AVCodecContext *c;
         av_init_packet(&pkt);
-        c = ctx->video_st->codec;
         if (ctx->frameCount % 25 == 0) {
             unsigned long long qsize = avpacket_queue_size(&ctx->queue);
             av_log(avctx, AV_LOG_DEBUG,
@@ -354,7 +352,6 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
         }
 #endif
 
-        c->frame_number++;
         if (avpacket_queue_put(&ctx->queue, &pkt) < 0) {
             ++ctx->dropped;
         }
@@ -362,14 +359,12 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
 
     // Handle Audio Frame
     if (audioFrame) {
-        AVCodecContext *c;
         AVPacket pkt;
         BMDTimeValue audio_pts;
         av_init_packet(&pkt);
 
-        c = ctx->audio_st->codec;
         //hack among hacks
-        pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codec->channels * (16 / 8);
+        pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (16 / 8);
         audioFrame->GetBytes(&audioFrameBytes);
         audioFrame->GetPacketTime(&audio_pts, ctx->audio_st->time_base.den);
         pkt.pts = audio_pts / ctx->audio_st->time_base.num;
@@ -386,7 +381,6 @@ HRESULT decklink_input_callback::VideoInputFrameArrived(
         pkt.stream_index = ctx->audio_st->index;
         pkt.data         = (uint8_t *)audioFrameBytes;
 
-        c->frame_number++;
         if (avpacket_queue_put(&ctx->queue, &pkt) < 0) {
             ++ctx->dropped;
         }
@@ -551,10 +545,10 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
         av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n");
         goto error;
     }
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = AV_CODEC_ID_PCM_S16LE;
-    st->codec->sample_rate = bmdAudioSampleRate48kHz;
-    st->codec->channels    = cctx->audio_channels;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_CODEC_ID_PCM_S16LE;
+    st->codecpar->sample_rate = bmdAudioSampleRate48kHz;
+    st->codecpar->channels    = cctx->audio_channels;
     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
     ctx->audio_st=st;
 
@@ -563,21 +557,21 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
         av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n");
         goto error;
     }
-    st->codec->codec_type  = AVMEDIA_TYPE_VIDEO;
-    st->codec->width       = ctx->bmd_width;
-    st->codec->height      = ctx->bmd_height;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->width       = ctx->bmd_width;
+    st->codecpar->height      = ctx->bmd_height;
 
-    st->codec->time_base.den      = ctx->bmd_tb_den;
-    st->codec->time_base.num      = ctx->bmd_tb_num;
-    st->codec->bit_rate    = av_image_get_buffer_size(st->codec->pix_fmt, ctx->bmd_width, ctx->bmd_height, 1) * 1/av_q2d(st->codec->time_base) * 8;
+    st->time_base.den      = ctx->bmd_tb_den;
+    st->time_base.num      = ctx->bmd_tb_num;
+    st->codecpar->bit_rate    = av_image_get_buffer_size((AVPixelFormat)st->codecpar->format, ctx->bmd_width, ctx->bmd_height, 1) * 1/av_q2d(st->time_base) * 8;
 
     if (cctx->v210) {
-        st->codec->codec_id    = AV_CODEC_ID_V210;
-        st->codec->codec_tag   = MKTAG('V', '2', '1', '0');
+        st->codecpar->codec_id    = AV_CODEC_ID_V210;
+        st->codecpar->codec_tag   = MKTAG('V', '2', '1', '0');
     } else {
-        st->codec->codec_id    = AV_CODEC_ID_RAWVIDEO;
-        st->codec->pix_fmt     = AV_PIX_FMT_UYVY422;
-        st->codec->codec_tag   = MKTAG('U', 'Y', 'V', 'Y');
+        st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
+        st->codecpar->format      = AV_PIX_FMT_UYVY422;
+        st->codecpar->codec_tag   = MKTAG('U', 'Y', 'V', 'Y');
     }
 
     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
@@ -590,16 +584,16 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx)
             av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n");
             goto error;
         }
-        st->codec->codec_type  = AVMEDIA_TYPE_SUBTITLE;
-        st->codec->time_base.den      = ctx->bmd_tb_den;
-        st->codec->time_base.num      = ctx->bmd_tb_num;
-        st->codec->codec_id    = AV_CODEC_ID_DVB_TELETEXT;
+        st->codecpar->codec_type  = AVMEDIA_TYPE_SUBTITLE;
+        st->time_base.den         = ctx->bmd_tb_den;
+        st->time_base.num         = ctx->bmd_tb_num;
+        st->codecpar->codec_id    = AV_CODEC_ID_DVB_TELETEXT;
         avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
         ctx->teletext_st = st;
     }
 
-    av_log(avctx, AV_LOG_VERBOSE, "Using %d input audio channels\n", ctx->audio_st->codec->channels);
-    result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, ctx->audio_st->codec->channels);
+    av_log(avctx, AV_LOG_VERBOSE, "Using %d input audio channels\n", ctx->audio_st->codecpar->channels);
+    result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, ctx->audio_st->codecpar->channels);
 
     if (result != S_OK) {
         av_log(avctx, AV_LOG_ERROR, "Cannot enable audio input\n");
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index f56c165..f2453e6 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -104,10 +104,10 @@ dshow_read_close(AVFormatContext *s)
     if (ctx->device_filter[AudioDevice])
         IBaseFilter_Release(ctx->device_filter[AudioDevice]);
 
-    if (ctx->device_name[0])
-        av_freep(&ctx->device_name[0]);
-    if (ctx->device_name[1])
-        av_freep(&ctx->device_name[1]);
+    av_freep(&ctx->device_name[0]);
+    av_freep(&ctx->device_name[1]);
+    av_freep(&ctx->device_unique_name[0]);
+    av_freep(&ctx->device_unique_name[1]);
 
     if(ctx->mutex)
         CloseHandle(ctx->mutex);
@@ -205,7 +205,8 @@ fail:
  */
 static int
 dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
-                    enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype, IBaseFilter **pfilter)
+                    enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype,
+                    IBaseFilter **pfilter, char **device_unique_name)
 {
     struct dshow_ctx *ctx = avctx->priv_data;
     IBaseFilter *device_filter = NULL;
@@ -276,10 +277,13 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
                     av_log(avctx, AV_LOG_ERROR, "Unable to BindToObject for %s\n", device_name);
                     goto fail1;
                 }
+                *device_unique_name = unique_name;
+                // success, loop will end now
             }
         } else {
             av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name);
             av_log(avctx, AV_LOG_INFO, "    Alternative name \"%s\"\n", unique_name);
+            av_free(unique_name);
         }
 
 fail1:
@@ -288,7 +292,6 @@ fail1:
         if (bind_ctx)
             IBindCtx_Release(bind_ctx);
         av_free(friendly_name);
-        av_free(unique_name);
         if (bag)
             IPropertyBag_Release(bag);
         IMoniker_Release(m);
@@ -706,14 +709,15 @@ dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
 {
     struct dshow_ctx *ctx = avctx->priv_data;
     IBaseFilter *device_filter = NULL;
+    char *device_unique_name = NULL;
     int r;
 
-    if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter)) < 0)
+    if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name)) < 0)
         return r;
     ctx->device_filter[devtype] = device_filter;
     if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, NULL)) < 0)
         return r;
-
+    av_freep(&device_unique_name);
     return 0;
 }
 
@@ -723,6 +727,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
 {
     struct dshow_ctx *ctx = avctx->priv_data;
     IBaseFilter *device_filter = NULL;
+    char *device_filter_unique_name = NULL;
     IGraphBuilder *graph = ctx->graph;
     IPin *device_pin = NULL;
     libAVPin *capture_pin = NULL;
@@ -733,6 +738,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
     IStream *ifile_stream = NULL;
     IStream *ofile_stream = NULL;
     IPersistStream *pers_stream = NULL;
+    enum dshowDeviceType otherDevType = (devtype == VideoDevice) ? AudioDevice : VideoDevice;
 
     const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
 
@@ -766,13 +772,26 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
         av_log(avctx, AV_LOG_INFO, "Capture filter loaded successfully from file \"%s\".\n", filename);
     } else {
 
-        if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter)) < 0) {
+        if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_filter_unique_name)) < 0) {
             ret = r;
             goto error;
         }
     }
+        if (ctx->device_filter[otherDevType]) {
+        // avoid adding add two instances of the same device to the graph, one for video, one for audio
+        // a few devices don't support this (could also do this check earlier to avoid double crossbars, etc. but they seem OK)
+        if (strcmp(device_filter_unique_name, ctx->device_unique_name[otherDevType]) == 0) {
+          av_log(avctx, AV_LOG_DEBUG, "reusing previous graph capture filter... %s\n", device_filter_unique_name);
+          IBaseFilter_Release(device_filter);
+          device_filter = ctx->device_filter[otherDevType];
+          IBaseFilter_AddRef(ctx->device_filter[otherDevType]);
+        } else {
+            av_log(avctx, AV_LOG_DEBUG, "not reusing previous graph capture filter %s != %s\n", device_filter_unique_name, ctx->device_unique_name[otherDevType]);
+        }
+    }
 
     ctx->device_filter [devtype] = device_filter;
+    ctx->device_unique_name [devtype] = device_filter_unique_name;
 
     r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
     if (r != S_OK) {
@@ -918,7 +937,7 @@ dshow_add_device(AVFormatContext *avctx,
 {
     struct dshow_ctx *ctx = avctx->priv_data;
     AM_MEDIA_TYPE type;
-    AVCodecContext *codec;
+    AVCodecParameters *par;
     AVStream *st;
     int ret = AVERROR(EIO);
 
@@ -933,7 +952,7 @@ dshow_add_device(AVFormatContext *avctx,
 
     libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type);
 
-    codec = st->codec;
+    par = st->codecpar;
     if (devtype == VideoDevice) {
         BITMAPINFOHEADER *bih = NULL;
         AVRational time_base;
@@ -952,33 +971,35 @@ dshow_add_device(AVFormatContext *avctx,
             goto error;
         }
 
-        codec->time_base  = time_base;
-        codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        codec->width      = bih->biWidth;
-        codec->height     = bih->biHeight;
-        codec->codec_tag  = bih->biCompression;
-        codec->pix_fmt    = dshow_pixfmt(bih->biCompression, bih->biBitCount);
+        st->avg_frame_rate = av_inv_q(time_base);
+        st->r_frame_rate = av_inv_q(time_base);
+
+        par->codec_type = AVMEDIA_TYPE_VIDEO;
+        par->width      = bih->biWidth;
+        par->height     = bih->biHeight;
+        par->codec_tag  = bih->biCompression;
+        par->format     = dshow_pixfmt(bih->biCompression, bih->biBitCount);
         if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) {
             av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n");
-            codec->color_range = AVCOL_RANGE_MPEG; // just in case it needs this...
+            par->color_range = AVCOL_RANGE_MPEG; // just in case it needs this...
         }
-        if (codec->pix_fmt == AV_PIX_FMT_NONE) {
+        if (par->format == AV_PIX_FMT_NONE) {
             const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL };
-            codec->codec_id = av_codec_get_id(tags, bih->biCompression);
-            if (codec->codec_id == AV_CODEC_ID_NONE) {
+            par->codec_id = av_codec_get_id(tags, bih->biCompression);
+            if (par->codec_id == AV_CODEC_ID_NONE) {
                 av_log(avctx, AV_LOG_ERROR, "Unknown compression type. "
                                  "Please report type 0x%X.\n", (int) bih->biCompression);
                 return AVERROR_PATCHWELCOME;
             }
-            codec->bits_per_coded_sample = bih->biBitCount;
+            par->bits_per_coded_sample = bih->biBitCount;
         } else {
-            codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+            par->codec_id = AV_CODEC_ID_RAWVIDEO;
             if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) {
-                codec->bits_per_coded_sample = bih->biBitCount;
-                codec->extradata = av_malloc(9 + AV_INPUT_BUFFER_PADDING_SIZE);
-                if (codec->extradata) {
-                    codec->extradata_size = 9;
-                    memcpy(codec->extradata, "BottomUp", 9);
+                par->bits_per_coded_sample = bih->biBitCount;
+                par->extradata = av_malloc(9 + AV_INPUT_BUFFER_PADDING_SIZE);
+                if (par->extradata) {
+                    par->extradata_size = 9;
+                    memcpy(par->extradata, "BottomUp", 9);
                 }
             }
         }
@@ -993,11 +1014,11 @@ dshow_add_device(AVFormatContext *avctx,
             goto error;
         }
 
-        codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-        codec->sample_fmt  = sample_fmt_bits_per_sample(fx->wBitsPerSample);
-        codec->codec_id    = waveform_codec_id(codec->sample_fmt);
-        codec->sample_rate = fx->nSamplesPerSec;
-        codec->channels    = fx->nChannels;
+        par->codec_type  = AVMEDIA_TYPE_AUDIO;
+        par->format      = sample_fmt_bits_per_sample(fx->wBitsPerSample);
+        par->codec_id    = waveform_codec_id(par->format);
+        par->sample_rate = fx->nSamplesPerSec;
+        par->channels    = fx->nChannels;
     }
 
     avpriv_set_pts_info(st, 64, 1, 10000000);
@@ -1099,9 +1120,9 @@ static int dshow_read_header(AVFormatContext *avctx)
 
     if (ctx->list_devices) {
         av_log(avctx, AV_LOG_INFO, "DirectShow video devices (some may be both video and audio devices)\n");
-        dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL);
+        dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL);
         av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n");
-        dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL);
+        dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL);
         ret = AVERROR_EXIT;
         goto error;
     }
diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h
index f26eaf9..475d62b 100644
--- a/libavdevice/dshow_capture.h
+++ b/libavdevice/dshow_capture.h
@@ -289,6 +289,8 @@ struct dshow_ctx {
     IGraphBuilder *graph;
 
     char *device_name[2];
+    char *device_unique_name[2];
+
     int video_device_number;
     int audio_device_number;
 
diff --git a/libavdevice/dshow_crossbar.c b/libavdevice/dshow_crossbar.c
index c0739da..95fb466 100644
--- a/libavdevice/dshow_crossbar.c
+++ b/libavdevice/dshow_crossbar.c
@@ -167,7 +167,7 @@ dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2,
     }
 
     if (devtype == VideoDevice && ctx->show_analog_tv_tuner_dialog) {
-        hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL, 
+        hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL,
              device_filter, &IID_IAMTVTuner, (void**) &tv_tuner_filter);
         if (hr == S_OK) {
             hr = IAMCrossbar_QueryInterface(tv_tuner_filter, &IID_IBaseFilter, (void **) &tv_tuner_base_filter);
@@ -179,7 +179,7 @@ dshow_try_setup_crossbar_options(ICaptureGraphBuilder2 *graph_builder2,
         }
     }
     if (devtype == AudioDevice && ctx->show_analog_tv_tuner_audio_dialog) {
-        hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL, 
+        hr = ICaptureGraphBuilder2_FindInterface(graph_builder2, &LOOK_UPSTREAM_ONLY, NULL,
              device_filter, &IID_IAMTVAudio, (void**) &tv_audio_filter);
         if (hr == S_OK) {
             hr = IAMCrossbar_QueryInterface(tv_audio_filter, &IID_IBaseFilter, (void **) &tv_audio_base_filter);
diff --git a/libavdevice/fbdev_dec.c b/libavdevice/fbdev_dec.c
index e9a3639..3b31373 100644
--- a/libavdevice/fbdev_dec.c
+++ b/libavdevice/fbdev_dec.c
@@ -126,13 +126,13 @@ static av_cold int fbdev_read_header(AVFormatContext *avctx)
         goto fail;
     }
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
-    st->codec->width      = fbdev->width;
-    st->codec->height     = fbdev->height;
-    st->codec->pix_fmt    = pix_fmt;
-    st->codec->time_base  = av_inv_q(fbdev->framerate_q);
-    st->codec->bit_rate   =
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->width      = fbdev->width;
+    st->codecpar->height     = fbdev->height;
+    st->codecpar->format     = pix_fmt;
+    st->avg_frame_rate       = fbdev->framerate_q;
+    st->codecpar->bit_rate   =
         fbdev->width * fbdev->height * fbdev->bytes_per_pixel * av_q2d(fbdev->framerate_q) * 8;
 
     av_log(avctx, AV_LOG_INFO,
@@ -140,7 +140,7 @@ static av_cold int fbdev_read_header(AVFormatContext *avctx)
            fbdev->width, fbdev->height, fbdev->varinfo.bits_per_pixel,
            av_get_pix_fmt_name(pix_fmt),
            fbdev->framerate_q.num, fbdev->framerate_q.den,
-           (int64_t)st->codec->bit_rate);
+           (int64_t)st->codecpar->bit_rate);
     return 0;
 
 fail:
@@ -220,7 +220,7 @@ static int fbdev_get_device_list(AVFormatContext *s, AVDeviceInfoList *device_li
 #define OFFSET(x) offsetof(FBDevContext, x)
 #define DEC AV_OPT_FLAG_DECODING_PARAM
 static const AVOption options[] = {
-    { "framerate","", OFFSET(framerate_q), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, DEC },
+    { "framerate","", OFFSET(framerate_q), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC },
     { NULL },
 };
 
diff --git a/libavdevice/fbdev_enc.c b/libavdevice/fbdev_enc.c
index 28efc71..b4e5f84 100644
--- a/libavdevice/fbdev_enc.c
+++ b/libavdevice/fbdev_enc.c
@@ -48,7 +48,7 @@ static av_cold int fbdev_write_header(AVFormatContext *h)
     int ret, flags = O_RDWR;
     const char* device;
 
-    if (h->nb_streams != 1 || h->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO) {
+    if (h->nb_streams != 1 || h->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
         av_log(fbdev, AV_LOG_ERROR, "Only a single video stream is supported.\n");
         return AVERROR(EINVAL);
     }
@@ -105,11 +105,11 @@ static int fbdev_write_packet(AVFormatContext *h, AVPacket *pkt)
     enum AVPixelFormat fb_pix_fmt;
     int disp_height;
     int bytes_to_copy;
-    AVCodecContext *codec_ctx = h->streams[0]->codec;
-    enum AVPixelFormat video_pix_fmt = codec_ctx->pix_fmt;
-    int video_width = codec_ctx->width;
-    int video_height = codec_ctx->height;
-    int bytes_per_pixel = ((codec_ctx->bits_per_coded_sample + 7) >> 3);
+    AVCodecParameters *par = h->streams[0]->codecpar;
+    enum AVPixelFormat video_pix_fmt = par->format;
+    int video_width = par->width;
+    int video_height = par->height;
+    int bytes_per_pixel = ((par->bits_per_coded_sample + 7) >> 3);
     int src_line_size = video_width * bytes_per_pixel;
     int i;
 
diff --git a/libavdevice/gdigrab.c b/libavdevice/gdigrab.c
index 4428a34..87f5012 100644
--- a/libavdevice/gdigrab.c
+++ b/libavdevice/gdigrab.c
@@ -403,10 +403,11 @@ gdigrab_read_header(AVFormatContext *s1)
         }
     }
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_BMP;
-    st->codec->time_base  = gdigrab->time_base;
-    st->codec->bit_rate   = (gdigrab->header_size + gdigrab->frame_size) * 1/av_q2d(gdigrab->time_base) * 8;
+    st->avg_frame_rate = av_inv_q(gdigrab->time_base);
+
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_BMP;
+    st->codecpar->bit_rate   = (gdigrab->header_size + gdigrab->frame_size) * 1/av_q2d(gdigrab->time_base) * 8;
 
     return 0;
 
@@ -446,6 +447,8 @@ static void paint_mouse_pointer(AVFormatContext *s1, struct gdigrab *gdigrab)
         POINT pos;
         RECT clip_rect = gdigrab->clip_rect;
         HWND hwnd = gdigrab->hwnd;
+        int vertres = GetDeviceCaps(gdigrab->source_hdc, VERTRES);
+        int desktopvertres = GetDeviceCaps(gdigrab->source_hdc, DESKTOPVERTRES);
         info.hbmMask = NULL;
         info.hbmColor = NULL;
 
@@ -479,6 +482,10 @@ static void paint_mouse_pointer(AVFormatContext *s1, struct gdigrab *gdigrab)
             }
         }
 
+        //that would keep the correct location of mouse with hidpi screens
+        pos.x = pos.x * desktopvertres / vertres;
+        pos.y = pos.y * desktopvertres / vertres;
+
         av_log(s1, AV_LOG_DEBUG, "Cursor pos (%li,%li) -> (%li,%li)\n",
                 ci.ptScreenPos.x, ci.ptScreenPos.y, pos.x, pos.y);
 
@@ -615,7 +622,7 @@ static int gdigrab_read_close(AVFormatContext *s1)
 static const AVOption options[] = {
     { "draw_mouse", "draw the mouse pointer", OFFSET(draw_mouse), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, DEC },
     { "show_region", "draw border around capture area", OFFSET(show_region), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC },
-    { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, 0, DEC },
+    { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, INT_MAX, DEC },
     { "video_size", "set video frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
     { "offset_x", "capture area x offset", OFFSET(offset_x), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
     { "offset_y", "capture area y offset", OFFSET(offset_y), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
diff --git a/libavdevice/jack.c b/libavdevice/jack.c
index 9ecbf9e..34e2152 100644
--- a/libavdevice/jack.c
+++ b/libavdevice/jack.c
@@ -35,6 +35,16 @@
 #include "timefilter.h"
 #include "avdevice.h"
 
+#if HAVE_DISPATCH_DISPATCH_H
+#include <dispatch/dispatch.h>
+#define sem_t dispatch_semaphore_t
+#define sem_init(psem,x,val)  *psem = dispatch_semaphore_create(val)
+#define sem_post(psem)                dispatch_semaphore_signal(*psem)
+#define sem_wait(psem)                dispatch_semaphore_wait(*psem, DISPATCH_TIME_FOREVER)
+#define sem_timedwait(psem, val)      dispatch_semaphore_wait(*psem, dispatch_walltime(val, 0))
+#define sem_destroy(psem)             dispatch_release(*psem)
+#endif
+
 /**
  * Size of the internal FIFO buffers as a number of audio packets
  */
@@ -252,14 +262,14 @@ static int audio_read_header(AVFormatContext *context)
         return AVERROR(ENOMEM);
     }
 
-    stream->codec->codec_type   = AVMEDIA_TYPE_AUDIO;
+    stream->codecpar->codec_type   = AVMEDIA_TYPE_AUDIO;
 #if HAVE_BIGENDIAN
-    stream->codec->codec_id     = AV_CODEC_ID_PCM_F32BE;
+    stream->codecpar->codec_id     = AV_CODEC_ID_PCM_F32BE;
 #else
-    stream->codec->codec_id     = AV_CODEC_ID_PCM_F32LE;
+    stream->codecpar->codec_id     = AV_CODEC_ID_PCM_F32LE;
 #endif
-    stream->codec->sample_rate  = self->sample_rate;
-    stream->codec->channels     = self->nports;
+    stream->codecpar->sample_rate  = self->sample_rate;
+    stream->codecpar->channels     = self->nports;
 
     avpriv_set_pts_info(stream, 64, 1, 1000000);  /* 64 bits pts in us */
     return 0;
diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c
index 8e9e67d..f9b2694 100644
--- a/libavdevice/lavfi.c
+++ b/libavdevice/lavfi.c
@@ -108,8 +108,8 @@ static int create_subcc_streams(AVFormatContext *avctx)
             lavfi->sink_stream_subcc_map[sink_idx] = avctx->nb_streams;
             if (!(st = avformat_new_stream(avctx, NULL)))
                 return AVERROR(ENOMEM);
-            st->codec->codec_id = AV_CODEC_ID_EIA_608;
-            st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
+            st->codecpar->codec_id = AV_CODEC_ID_EIA_608;
+            st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
         } else {
             lavfi->sink_stream_subcc_map[sink_idx] = -1;
         }
@@ -314,28 +314,26 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
     for (i = 0; i < lavfi->nb_sinks; i++) {
         AVFilterLink *link = lavfi->sinks[lavfi->stream_sink_map[i]]->inputs[0];
         AVStream *st = avctx->streams[i];
-        st->codec->codec_type = link->type;
+        st->codecpar->codec_type = link->type;
         avpriv_set_pts_info(st, 64, link->time_base.num, link->time_base.den);
         if (link->type == AVMEDIA_TYPE_VIDEO) {
-            st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
-            st->codec->pix_fmt    = link->format;
-            st->codec->time_base  = link->time_base;
-            st->codec->width      = link->w;
-            st->codec->height     = link->h;
+            st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
+            st->codecpar->format     = link->format;
+            st->codecpar->width      = link->w;
+            st->codecpar->height     = link->h;
             st       ->sample_aspect_ratio =
-            st->codec->sample_aspect_ratio = link->sample_aspect_ratio;
+            st->codecpar->sample_aspect_ratio = link->sample_aspect_ratio;
             avctx->probesize = FFMAX(avctx->probesize,
                                      link->w * link->h *
                                      av_get_padded_bits_per_pixel(av_pix_fmt_desc_get(link->format)) *
                                      30);
         } else if (link->type == AVMEDIA_TYPE_AUDIO) {
-            st->codec->codec_id    = av_get_pcm_codec(link->format, -1);
-            st->codec->channels    = avfilter_link_get_channels(link);
-            st->codec->sample_fmt  = link->format;
-            st->codec->sample_rate = link->sample_rate;
-            st->codec->time_base   = link->time_base;
-            st->codec->channel_layout = link->channel_layout;
-            if (st->codec->codec_id == AV_CODEC_ID_NONE)
+            st->codecpar->codec_id    = av_get_pcm_codec(link->format, -1);
+            st->codecpar->channels    = avfilter_link_get_channels(link);
+            st->codecpar->format      = link->format;
+            st->codecpar->sample_rate = link->sample_rate;
+            st->codecpar->channel_layout = link->channel_layout;
+            if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
                 av_log(avctx, AV_LOG_ERROR,
                        "Could not find PCM codec for sample format %s.\n",
                        av_get_sample_fmt_name(link->format));
diff --git a/libavdevice/libcdio.c b/libavdevice/libcdio.c
index 9e9b0d8..f6d4fce 100644
--- a/libavdevice/libcdio.c
+++ b/libavdevice/libcdio.c
@@ -85,19 +85,19 @@ static av_cold int read_header(AVFormatContext *ctx)
     }
     cdio_paranoia_modeset(s->paranoia, s->paranoia_mode);
 
-    st->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_type      = AVMEDIA_TYPE_AUDIO;
     if (s->drive->bigendianp)
-        st->codec->codec_id    = AV_CODEC_ID_PCM_S16BE;
+        st->codecpar->codec_id    = AV_CODEC_ID_PCM_S16BE;
     else
-        st->codec->codec_id    = AV_CODEC_ID_PCM_S16LE;
-    st->codec->sample_rate     = 44100;
-    st->codec->channels        = 2;
+        st->codecpar->codec_id    = AV_CODEC_ID_PCM_S16LE;
+    st->codecpar->sample_rate     = 44100;
+    st->codecpar->channels        = 2;
     if (s->drive->audio_last_sector != CDIO_INVALID_LSN &&
         s->drive->audio_first_sector != CDIO_INVALID_LSN)
         st->duration           = s->drive->audio_last_sector - s->drive->audio_first_sector;
     else if (s->drive->tracks)
         st->duration = s->drive->disc_toc[s->drive->tracks].dwStartSector;
-    avpriv_set_pts_info(st, 64, CDIO_CD_FRAMESIZE_RAW, 2*st->codec->channels*st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, CDIO_CD_FRAMESIZE_RAW, 2 * st->codecpar->channels * st->codecpar->sample_rate);
 
     for (i = 0; i < s->drive->tracks; i++) {
         char title[16];
diff --git a/libavdevice/libdc1394.c b/libavdevice/libdc1394.c
index dcdca60..43fa232 100644
--- a/libavdevice/libdc1394.c
+++ b/libavdevice/libdc1394.c
@@ -171,13 +171,12 @@ static inline int dc1394_read_common(AVFormatContext *c,
         goto out;
     }
     avpriv_set_pts_info(vst, 64, 1, 1000);
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
-    vst->codec->time_base.den = framerate.num;
-    vst->codec->time_base.num = framerate.den;
-    vst->codec->width = fmt->width;
-    vst->codec->height = fmt->height;
-    vst->codec->pix_fmt = fmt->pix_fmt;
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
+    vst->codecpar->width = fmt->width;
+    vst->codecpar->height = fmt->height;
+    vst->codecpar->format = fmt->pix_fmt;
+    vst->avg_frame_rate = framerate;
 
     /* packet init */
     av_init_packet(&dc1394->packet);
@@ -188,7 +187,7 @@ static inline int dc1394_read_common(AVFormatContext *c,
 
     dc1394->current_frame = 0;
 
-    vst->codec->bit_rate = av_rescale(dc1394->packet.size * 8, fps->frame_rate, 1000);
+    vst->codecpar->bit_rate = av_rescale(dc1394->packet.size * 8, fps->frame_rate, 1000);
     *select_fps = fps;
     *select_fmt = fmt;
 out:
diff --git a/libavdevice/openal-dec.c b/libavdevice/openal-dec.c
index e4daf53..0647952 100644
--- a/libavdevice/openal-dec.c
+++ b/libavdevice/openal-dec.c
@@ -128,7 +128,7 @@ static int read_header(AVFormatContext *ctx)
     int error = 0;
     const char *error_msg;
     AVStream *st = NULL;
-    AVCodecContext *codec = NULL;
+    AVCodecParameters *par = NULL;
 
     if (ad->list_devices) {
         print_al_capture_devices(ctx);
@@ -156,11 +156,11 @@ static int read_header(AVFormatContext *ctx)
     avpriv_set_pts_info(st, 64, 1, 1000000);
 
     /* Set codec parameters */
-    codec = st->codec;
-    codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    codec->sample_rate = ad->sample_rate;
-    codec->channels = get_al_format_info(ad->sample_format)->channels;
-    codec->codec_id = get_al_format_info(ad->sample_format)->codec_id;
+    par = st->codecpar;
+    par->codec_type = AVMEDIA_TYPE_AUDIO;
+    par->sample_rate = ad->sample_rate;
+    par->channels = get_al_format_info(ad->sample_format)->channels;
+    par->codec_id = get_al_format_info(ad->sample_format)->codec_id;
 
     /* This is needed to read the audio data */
     ad->sample_step = (av_get_bits_per_sample(get_al_format_info(ad->sample_format)->codec_id) *
diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c
index ba8d36a..1dbbb80 100644
--- a/libavdevice/opengl_enc.c
+++ b/libavdevice/opengl_enc.c
@@ -678,11 +678,11 @@ static void opengl_compute_display_area(AVFormatContext *s)
     AVRational sar, dar; /* sample and display aspect ratios */
     OpenGLContext *opengl = s->priv_data;
     AVStream *st = s->streams[0];
-    AVCodecContext *encctx = st->codec;
+    AVCodecParameters *par = st->codecpar;
 
     /* compute overlay width and height from the codec context information */
     sar = st->sample_aspect_ratio.num ? st->sample_aspect_ratio : (AVRational){ 1, 1 };
-    dar = av_mul_q(sar, (AVRational){ encctx->width, encctx->height });
+    dar = av_mul_q(sar, (AVRational){ par->width, par->height });
 
     /* we suppose the screen has a 1/1 sample aspect ratio */
     /* fit in the window */
@@ -1065,15 +1065,15 @@ static av_cold int opengl_write_header(AVFormatContext *h)
     int ret;
 
     if (h->nb_streams != 1 ||
-        h->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
-        h->streams[0]->codec->codec_id != AV_CODEC_ID_RAWVIDEO) {
+        h->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
+        h->streams[0]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) {
         av_log(opengl, AV_LOG_ERROR, "Only a single video stream is supported.\n");
         return AVERROR(EINVAL);
     }
     st = h->streams[0];
-    opengl->width = st->codec->width;
-    opengl->height = st->codec->height;
-    opengl->pix_fmt = st->codec->pix_fmt;
+    opengl->width = st->codecpar->width;
+    opengl->height = st->codecpar->height;
+    opengl->pix_fmt = st->codecpar->format;
     if (!opengl->window_width)
         opengl->window_width = opengl->width;
     if (!opengl->window_height)
@@ -1200,7 +1200,7 @@ static uint8_t* opengl_get_plane_pointer(OpenGLContext *opengl, AVPacket *pkt, i
 static int opengl_draw(AVFormatContext *h, void *input, int repaint, int is_pkt)
 {
     OpenGLContext *opengl = h->priv_data;
-    enum AVPixelFormat pix_fmt = h->streams[0]->codec->pix_fmt;
+    enum AVPixelFormat pix_fmt = h->streams[0]->codecpar->format;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
     int ret;
 
diff --git a/libavdevice/oss_dec.c b/libavdevice/oss_dec.c
index 3a9a20a..9f748f2 100644
--- a/libavdevice/oss_dec.c
+++ b/libavdevice/oss_dec.c
@@ -63,10 +63,10 @@ static int audio_read_header(AVFormatContext *s1)
     }
 
     /* take real parameters */
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = s->codec_id;
-    st->codec->sample_rate = s->sample_rate;
-    st->codec->channels = s->channels;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = s->codec_id;
+    st->codecpar->sample_rate = s->sample_rate;
+    st->codecpar->channels = s->channels;
 
     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
     return 0;
diff --git a/libavdevice/oss_enc.c b/libavdevice/oss_enc.c
index 3781eb5..2268b4c 100644
--- a/libavdevice/oss_enc.c
+++ b/libavdevice/oss_enc.c
@@ -49,8 +49,8 @@ static int audio_write_header(AVFormatContext *s1)
     int ret;
 
     st = s1->streams[0];
-    s->sample_rate = st->codec->sample_rate;
-    s->channels = st->codec->channels;
+    s->sample_rate = st->codecpar->sample_rate;
+    s->channels = st->codecpar->channels;
     ret = ff_oss_audio_open(s1, 1, s1->filename);
     if (ret < 0) {
         return AVERROR(EIO);
diff --git a/libavdevice/pulse_audio_dec.c b/libavdevice/pulse_audio_dec.c
index aa0800b..95a1d6e 100644
--- a/libavdevice/pulse_audio_dec.c
+++ b/libavdevice/pulse_audio_dec.c
@@ -242,10 +242,10 @@ static av_cold int pulse_read_header(AVFormatContext *s)
     pa_threaded_mainloop_unlock(pd->mainloop);
 
     /* take real parameters */
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = codec_id;
-    st->codec->sample_rate = pd->sample_rate;
-    st->codec->channels    = pd->channels;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = codec_id;
+    st->codecpar->sample_rate = pd->sample_rate;
+    st->codecpar->channels    = pd->channels;
     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
 
     pd->timefilter = ff_timefilter_new(1000000.0 / pd->sample_rate,
diff --git a/libavdevice/pulse_audio_enc.c b/libavdevice/pulse_audio_enc.c
index b419a38..6fb634e 100644
--- a/libavdevice/pulse_audio_enc.c
+++ b/libavdevice/pulse_audio_enc.c
@@ -452,7 +452,7 @@ static av_cold int pulse_write_header(AVFormatContext *h)
                                                   PA_STREAM_AUTO_TIMING_UPDATE |
                                                   PA_STREAM_NOT_MONOTONIC;
 
-    if (h->nb_streams != 1 || h->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
+    if (h->nb_streams != 1 || h->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
         av_log(s, AV_LOG_ERROR, "Only a single audio stream is supported.\n");
         return AVERROR(EINVAL);
     }
@@ -468,8 +468,8 @@ static av_cold int pulse_write_header(AVFormatContext *h)
 
     if (s->buffer_duration) {
         int64_t bytes = s->buffer_duration;
-        bytes *= st->codec->channels * st->codec->sample_rate *
-                 av_get_bytes_per_sample(st->codec->sample_fmt);
+        bytes *= st->codecpar->channels * st->codecpar->sample_rate *
+                 av_get_bytes_per_sample(st->codecpar->format);
         bytes /= 1000;
         buffer_attributes.tlength = FFMAX(s->buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1));
         av_log(s, AV_LOG_DEBUG,
@@ -483,9 +483,9 @@ static av_cold int pulse_write_header(AVFormatContext *h)
     if (s->minreq)
         buffer_attributes.minreq = s->minreq;
 
-    sample_spec.format = ff_codec_id_to_pulse_format(st->codec->codec_id);
-    sample_spec.rate = st->codec->sample_rate;
-    sample_spec.channels = st->codec->channels;
+    sample_spec.format = ff_codec_id_to_pulse_format(st->codecpar->codec_id);
+    sample_spec.rate = st->codecpar->sample_rate;
+    sample_spec.channels = st->codecpar->channels;
     if (!pa_sample_spec_valid(&sample_spec)) {
         av_log(s, AV_LOG_ERROR, "Invalid sample spec.\n");
         return AVERROR(EINVAL);
@@ -494,10 +494,10 @@ static av_cold int pulse_write_header(AVFormatContext *h)
     if (sample_spec.channels == 1) {
         channel_map.channels = 1;
         channel_map.map[0] = PA_CHANNEL_POSITION_MONO;
-    } else if (st->codec->channel_layout) {
-        if (av_get_channel_layout_nb_channels(st->codec->channel_layout) != st->codec->channels)
+    } else if (st->codecpar->channel_layout) {
+        if (av_get_channel_layout_nb_channels(st->codecpar->channel_layout) != st->codecpar->channels)
             return AVERROR(EINVAL);
-        pulse_map_channels_to_pulse(st->codec->channel_layout, &channel_map);
+        pulse_map_channels_to_pulse(st->codecpar->channel_layout, &channel_map);
         /* Unknown channel is present in channel_layout, let PulseAudio use its default. */
         if (channel_map.channels != sample_spec.channels) {
             av_log(s, AV_LOG_WARNING, "Unknown channel. Using defaul channel map.\n");
@@ -637,9 +637,8 @@ static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt)
         s->timestamp += pkt->duration;
     } else {
         AVStream *st = h->streams[0];
-        AVCodecContext *codec_ctx = st->codec;
-        AVRational r = { 1, codec_ctx->sample_rate };
-        int64_t samples = pkt->size / (av_get_bytes_per_sample(codec_ctx->sample_fmt) * codec_ctx->channels);
+        AVRational r = { 1, st->codecpar->sample_rate };
+        int64_t samples = pkt->size / (av_get_bytes_per_sample(st->codecpar->format) * st->codecpar->channels);
         s->timestamp += av_rescale_q(samples, r, st->time_base);
     }
 
@@ -678,7 +677,7 @@ static int pulse_write_frame(AVFormatContext *h, int stream_index,
 
     /* Planar formats are not supported yet. */
     if (flags & AV_WRITE_UNCODED_FRAME_QUERY)
-        return av_sample_fmt_is_planar(h->streams[stream_index]->codec->sample_fmt) ?
+        return av_sample_fmt_is_planar(h->streams[stream_index]->codecpar->format) ?
                AVERROR(EINVAL) : 0;
 
     pkt.data     = (*frame)->data[0];
diff --git a/libavdevice/sdl.c b/libavdevice/sdl.c
index 4cccfe5..4322750 100644
--- a/libavdevice/sdl.c
+++ b/libavdevice/sdl.c
@@ -94,12 +94,12 @@ static void compute_overlay_rect(AVFormatContext *s)
     AVRational sar, dar; /* sample and display aspect ratios */
     SDLContext *sdl = s->priv_data;
     AVStream *st = s->streams[0];
-    AVCodecContext *encctx = st->codec;
+    AVCodecParameters *par = st->codecpar;
     SDL_Rect *overlay_rect = &sdl->overlay_rect;
 
     /* compute overlay width and height from the codec context information */
     sar = st->sample_aspect_ratio.num ? st->sample_aspect_ratio : (AVRational){ 1, 1 };
-    dar = av_mul_q(sar, (AVRational){ encctx->width, encctx->height });
+    dar = av_mul_q(sar, (AVRational){ par->width, par->height });
 
     /* we suppose the screen has a 1/1 sample aspect ratio */
     if (sdl->window_width && sdl->window_height) {
@@ -115,10 +115,10 @@ static void compute_overlay_rect(AVFormatContext *s)
         }
     } else {
         if (sar.num > sar.den) {
-            overlay_rect->w = encctx->width;
+            overlay_rect->w = par->width;
             overlay_rect->h = av_rescale(overlay_rect->w, dar.den, dar.num);
         } else {
-            overlay_rect->h = encctx->height;
+            overlay_rect->h = par->height;
             overlay_rect->w = av_rescale(overlay_rect->h, dar.num, dar.den);
         }
         sdl->window_width  = overlay_rect->w;
@@ -137,7 +137,7 @@ static int event_thread(void *arg)
     SDLContext *sdl = s->priv_data;
     int flags = SDL_BASE_FLAGS | (sdl->window_fullscreen ? SDL_FULLSCREEN : 0);
     AVStream *st = s->streams[0];
-    AVCodecContext *encctx = st->codec;
+    AVCodecParameters *par = st->codecpar;
 
     /* initialization */
     if (SDL_Init(SDL_INIT_VIDEO) != 0) {
@@ -155,19 +155,19 @@ static int event_thread(void *arg)
         goto init_end;
     }
 
-    sdl->overlay = SDL_CreateYUVOverlay(encctx->width, encctx->height,
+    sdl->overlay = SDL_CreateYUVOverlay(par->width, par->height,
                                         sdl->overlay_fmt, sdl->surface);
-    if (!sdl->overlay || sdl->overlay->pitches[0] < encctx->width) {
+    if (!sdl->overlay || sdl->overlay->pitches[0] < par->width) {
         av_log(s, AV_LOG_ERROR,
                "SDL does not support an overlay with size of %dx%d pixels\n",
-               encctx->width, encctx->height);
+               par->width, par->height);
         sdl->init_ret = AVERROR(EINVAL);
         goto init_end;
     }
 
     sdl->init_ret = 0;
     av_log(s, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s -> w:%d h:%d\n",
-           encctx->width, encctx->height, av_get_pix_fmt_name(encctx->pix_fmt),
+           par->width, par->height, av_get_pix_fmt_name(par->format),
            sdl->overlay_rect.w, sdl->overlay_rect.h);
 
 init_end:
@@ -234,7 +234,7 @@ static int sdl_write_header(AVFormatContext *s)
 {
     SDLContext *sdl = s->priv_data;
     AVStream *st = s->streams[0];
-    AVCodecContext *encctx = st->codec;
+    AVCodecParameters *par = st->codecpar;
     int i, ret;
 
     if (!sdl->window_title)
@@ -251,15 +251,15 @@ static int sdl_write_header(AVFormatContext *s)
     }
 
     if (   s->nb_streams > 1
-        || encctx->codec_type != AVMEDIA_TYPE_VIDEO
-        || encctx->codec_id   != AV_CODEC_ID_RAWVIDEO) {
+        || par->codec_type != AVMEDIA_TYPE_VIDEO
+        || par->codec_id   != AV_CODEC_ID_RAWVIDEO) {
         av_log(s, AV_LOG_ERROR, "Only supports one rawvideo stream\n");
         ret = AVERROR(EINVAL);
         goto fail;
     }
 
     for (i = 0; sdl_overlay_pix_fmt_map[i].pix_fmt != AV_PIX_FMT_NONE; i++) {
-        if (sdl_overlay_pix_fmt_map[i].pix_fmt == encctx->pix_fmt) {
+        if (sdl_overlay_pix_fmt_map[i].pix_fmt == par->format) {
             sdl->overlay_fmt = sdl_overlay_pix_fmt_map[i].overlay_fmt;
             break;
         }
@@ -268,7 +268,7 @@ static int sdl_write_header(AVFormatContext *s)
     if (!sdl->overlay_fmt) {
         av_log(s, AV_LOG_ERROR,
                "Unsupported pixel format '%s', choose one of yuv420p, yuyv422, or uyvy422\n",
-               av_get_pix_fmt_name(encctx->pix_fmt));
+               av_get_pix_fmt_name(par->format));
         ret = AVERROR(EINVAL);
         goto fail;
     }
@@ -315,7 +315,7 @@ fail:
 static int sdl_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     SDLContext *sdl = s->priv_data;
-    AVCodecContext *encctx = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     uint8_t *data[4];
     int linesize[4];
     int i;
@@ -324,7 +324,7 @@ static int sdl_write_packet(AVFormatContext *s, AVPacket *pkt)
         sdl_write_trailer(s);
         return AVERROR(EIO);
     }
-    av_image_fill_arrays(data, linesize, pkt->data, encctx->pix_fmt, encctx->width, encctx->height, 1);
+    av_image_fill_arrays(data, linesize, pkt->data, par->format, par->width, par->height, 1);
 
     SDL_LockMutex(sdl->mutex);
     SDL_FillRect(sdl->surface, &sdl->surface->clip_rect,
diff --git a/libavdevice/sndio_dec.c b/libavdevice/sndio_dec.c
index 6f1160e..2d13232 100644
--- a/libavdevice/sndio_dec.c
+++ b/libavdevice/sndio_dec.c
@@ -46,10 +46,10 @@ static av_cold int audio_read_header(AVFormatContext *s1)
         return ret;
 
     /* take real parameters */
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = s->codec_id;
-    st->codec->sample_rate = s->sample_rate;
-    st->codec->channels    = s->channels;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = s->codec_id;
+    st->codecpar->sample_rate = s->sample_rate;
+    st->codecpar->channels    = s->channels;
 
     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
 
diff --git a/libavdevice/sndio_enc.c b/libavdevice/sndio_enc.c
index 52b9060..47f500d 100644
--- a/libavdevice/sndio_enc.c
+++ b/libavdevice/sndio_enc.c
@@ -35,8 +35,8 @@ static av_cold int audio_write_header(AVFormatContext *s1)
     int ret;
 
     st             = s1->streams[0];
-    s->sample_rate = st->codec->sample_rate;
-    s->channels    = st->codec->channels;
+    s->sample_rate = st->codecpar->sample_rate;
+    s->channels    = st->codecpar->channels;
 
     ret = ff_sndio_open(s1, 1, s1->filename);
 
diff --git a/libavdevice/tests/timefilter.c b/libavdevice/tests/timefilter.c
new file mode 100644
index 0000000..7c1ed0a
--- /dev/null
+++ b/libavdevice/tests/timefilter.c
@@ -0,0 +1,98 @@
+/*
+ * 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 <stdio.h>
+
+#include "libavutil/common.h"
+#include "libavutil/lfg.h"
+
+#include "libavdevice/timefilter.h"
+
+#define LFG_MAX ((1LL << 32) - 1)
+
+int main(void)
+{
+    AVLFG prng;
+    double n0, n1;
+#define SAMPLES 1000
+    double ideal[SAMPLES];
+    double samples[SAMPLES];
+    double samplet[SAMPLES];
+    for (n0 = 0; n0 < 40; n0 = 2 * n0 + 1) {
+        for (n1 = 0; n1 < 10; n1 = 2 * n1 + 1) {
+            double best_error = 1000000000;
+            double bestpar0   = n0 ? 1 : 100000;
+            double bestpar1   = 1;
+            int better, i;
+
+            av_lfg_init(&prng, 123);
+            for (i = 0; i < SAMPLES; i++) {
+                samplet[i] = 10 + i + (av_lfg_get(&prng) < LFG_MAX/2 ? 0 : 0.999);
+                ideal[i]   = samplet[i] + n1 * i / (1000);
+                samples[i] = ideal[i] + n0 * (av_lfg_get(&prng) - LFG_MAX / 2) / (LFG_MAX * 10LL);
+                if(i && samples[i]<samples[i-1])
+                    samples[i]=samples[i-1]+0.001;
+            }
+
+            do {
+                double par0, par1;
+                better = 0;
+                for (par0 = bestpar0 * 0.8; par0 <= bestpar0 * 1.21; par0 += bestpar0 * 0.05) {
+                    for (par1 = bestpar1 * 0.8; par1 <= bestpar1 * 1.21; par1 += bestpar1 * 0.05) {
+                        double error   = 0;
+                        TimeFilter *tf = ff_timefilter_new(1, par0, par1);
+                        if (!tf) {
+                            printf("Could not allocate memory for timefilter.\n");
+                            exit(1);
+                        }
+                        for (i = 0; i < SAMPLES; i++) {
+                            double filtered;
+                            filtered = ff_timefilter_update(tf, samples[i], i ? (samplet[i] - samplet[i-1]) : 1);
+                            if(filtered < 0 || filtered > 1000000000)
+                                printf("filter is unstable\n");
+                            error   += (filtered - ideal[i]) * (filtered - ideal[i]);
+                        }
+                        ff_timefilter_destroy(tf);
+                        if (error < best_error) {
+                            best_error = error;
+                            bestpar0   = par0;
+                            bestpar1   = par1;
+                            better     = 1;
+                        }
+                    }
+                }
+            } while (better);
+#if 0
+            double lastfil = 9;
+            TimeFilter *tf = ff_timefilter_new(1, bestpar0, bestpar1);
+            for (i = 0; i < SAMPLES; i++) {
+                double filtered;
+                filtered = ff_timefilter_update(tf, samples[i], 1);
+                printf("%f %f %f %f\n", i - samples[i] + 10, filtered - samples[i],
+                       samples[FFMAX(i, 1)] - samples[FFMAX(i - 1, 0)], filtered - lastfil);
+                lastfil = filtered;
+            }
+            ff_timefilter_destroy(tf);
+#else
+            printf(" [%12f %11f %9f]", bestpar0, bestpar1, best_error);
+#endif
+        }
+        printf("\n");
+    }
+    return 0;
+}
diff --git a/libavdevice/timefilter.c b/libavdevice/timefilter.c
index 9d38f93..ad6485d 100644
--- a/libavdevice/timefilter.c
+++ b/libavdevice/timefilter.c
@@ -24,7 +24,7 @@
 
 #include "libavutil/common.h"
 #include "libavutil/mem.h"
-#include "config.h"
+
 #include "timefilter.h"
 
 struct TimeFilter {
@@ -89,80 +89,3 @@ double ff_timefilter_eval(TimeFilter *self, double delta)
 {
     return self->cycle_time + self->clock_period * delta;
 }
-
-#ifdef TEST
-#include "libavutil/lfg.h"
-#define LFG_MAX ((1LL << 32) - 1)
-
-int main(void)
-{
-    AVLFG prng;
-    double n0, n1;
-#define SAMPLES 1000
-    double ideal[SAMPLES];
-    double samples[SAMPLES];
-    double samplet[SAMPLES];
-    for (n0 = 0; n0 < 40; n0 = 2 * n0 + 1) {
-        for (n1 = 0; n1 < 10; n1 = 2 * n1 + 1) {
-            double best_error = 1000000000;
-            double bestpar0   = n0 ? 1 : 100000;
-            double bestpar1   = 1;
-            int better, i;
-
-            av_lfg_init(&prng, 123);
-            for (i = 0; i < SAMPLES; i++) {
-                samplet[i] = 10 + i + (av_lfg_get(&prng) < LFG_MAX/2 ? 0 : 0.999);
-                ideal[i]   = samplet[i] + n1 * i / (1000);
-                samples[i] = ideal[i] + n0 * (av_lfg_get(&prng) - LFG_MAX / 2) / (LFG_MAX * 10LL);
-                if(i && samples[i]<samples[i-1])
-                    samples[i]=samples[i-1]+0.001;
-            }
-
-            do {
-                double par0, par1;
-                better = 0;
-                for (par0 = bestpar0 * 0.8; par0 <= bestpar0 * 1.21; par0 += bestpar0 * 0.05) {
-                    for (par1 = bestpar1 * 0.8; par1 <= bestpar1 * 1.21; par1 += bestpar1 * 0.05) {
-                        double error   = 0;
-                        TimeFilter *tf = ff_timefilter_new(1, par0, par1);
-                        if (!tf) {
-                            printf("Could not allocate memory for timefilter.\n");
-                            exit(1);
-                        }
-                        for (i = 0; i < SAMPLES; i++) {
-                            double filtered;
-                            filtered = ff_timefilter_update(tf, samples[i], i ? (samplet[i] - samplet[i-1]) : 1);
-                            if(filtered < 0 || filtered > 1000000000)
-                                printf("filter is unstable\n");
-                            error   += (filtered - ideal[i]) * (filtered - ideal[i]);
-                        }
-                        ff_timefilter_destroy(tf);
-                        if (error < best_error) {
-                            best_error = error;
-                            bestpar0   = par0;
-                            bestpar1   = par1;
-                            better     = 1;
-                        }
-                    }
-                }
-            } while (better);
-#if 0
-            double lastfil = 9;
-            TimeFilter *tf = ff_timefilter_new(1, bestpar0, bestpar1);
-            for (i = 0; i < SAMPLES; i++) {
-                double filtered;
-                filtered = ff_timefilter_update(tf, samples[i], 1);
-                printf("%f %f %f %f\n", i - samples[i] + 10, filtered - samples[i],
-                       samples[FFMAX(i, 1)] - samples[FFMAX(i - 1, 0)], filtered - lastfil);
-                lastfil = filtered;
-            }
-            ff_timefilter_destroy(tf);
-#else
-            printf(" [%12f %11f %9f]", bestpar0, bestpar1, best_error);
-#endif
-        }
-        printf("\n");
-    }
-    return 0;
-}
-#endif
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index 383033e..ddf331d 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -715,11 +715,8 @@ static int v4l2_set_parameters(AVFormatContext *ctx)
     streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) < 0) {
         ret = AVERROR(errno);
-        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", av_err2str(ret));
-        return ret;
-    }
-
-    if (framerate_q.num && framerate_q.den) {
+        av_log(ctx, AV_LOG_WARNING, "ioctl(VIDIOC_G_PARM): %s\n", av_err2str(ret));
+    } else if (framerate_q.num && framerate_q.den) {
         if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
             tpf = &streamparm.parm.capture.timeperframe;
 
@@ -938,8 +935,8 @@ static int v4l2_read_header(AVFormatContext *ctx)
     if ((res = v4l2_set_parameters(ctx)) < 0)
         goto fail;
 
-    st->codec->pix_fmt = ff_fmt_v4l2ff(desired_format, codec_id);
-    s->frame_size = av_image_get_buffer_size(st->codec->pix_fmt,
+    st->codecpar->format = ff_fmt_v4l2ff(desired_format, codec_id);
+    s->frame_size = av_image_get_buffer_size(st->codecpar->format,
                                              s->width, s->height, 1);
 
     if ((res = mmap_init(ctx)) ||
@@ -948,22 +945,22 @@ static int v4l2_read_header(AVFormatContext *ctx)
 
     s->top_field_first = first_field(s);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = codec_id;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = codec_id;
     if (codec_id == AV_CODEC_ID_RAWVIDEO)
-        st->codec->codec_tag =
-            avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
+        st->codecpar->codec_tag =
+            avcodec_pix_fmt_to_codec_tag(st->codecpar->format);
     else if (codec_id == AV_CODEC_ID_H264) {
         st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;
     }
     if (desired_format == V4L2_PIX_FMT_YVU420)
-        st->codec->codec_tag = MKTAG('Y', 'V', '1', '2');
+        st->codecpar->codec_tag = MKTAG('Y', 'V', '1', '2');
     else if (desired_format == V4L2_PIX_FMT_YVU410)
-        st->codec->codec_tag = MKTAG('Y', 'V', 'U', '9');
-    st->codec->width = s->width;
-    st->codec->height = s->height;
+        st->codecpar->codec_tag = MKTAG('Y', 'V', 'U', '9');
+    st->codecpar->width = s->width;
+    st->codecpar->height = s->height;
     if (st->avg_frame_rate.den)
-        st->codec->bit_rate = s->frame_size * av_q2d(st->avg_frame_rate) * 8;
+        st->codecpar->bit_rate = s->frame_size * av_q2d(st->avg_frame_rate) * 8;
 
     return 0;
 
@@ -974,9 +971,9 @@ fail:
 
 static int v4l2_read_packet(AVFormatContext *ctx, AVPacket *pkt)
 {
-    struct video_data *s = ctx->priv_data;
-#if FF_API_CODED_FRAME
+#if FF_API_CODED_FRAME && FF_API_LAVF_AVCTX
 FF_DISABLE_DEPRECATION_WARNINGS
+    struct video_data *s = ctx->priv_data;
     AVFrame *frame = ctx->streams[0]->codec->coded_frame;
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
@@ -987,7 +984,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
         return res;
     }
 
-#if FF_API_CODED_FRAME
+#if FF_API_CODED_FRAME && FF_API_LAVF_AVCTX
 FF_DISABLE_DEPRECATION_WARNINGS
     if (frame && s->interlaced) {
         frame->interlaced_frame = 1;
diff --git a/libavdevice/v4l2enc.c b/libavdevice/v4l2enc.c
index ac4068c..faf6e07 100644
--- a/libavdevice/v4l2enc.c
+++ b/libavdevice/v4l2enc.c
@@ -33,7 +33,7 @@ static av_cold int write_header(AVFormatContext *s1)
         .type = V4L2_BUF_TYPE_VIDEO_OUTPUT
     };
     V4L2Context *s = s1->priv_data;
-    AVCodecContext *enc_ctx;
+    AVCodecParameters *par;
     uint32_t v4l2_pixfmt;
 
     if (s1->flags & AVFMT_FLAG_NONBLOCK)
@@ -47,19 +47,19 @@ static av_cold int write_header(AVFormatContext *s1)
     }
 
     if (s1->nb_streams != 1 ||
-        s1->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
-        s1->streams[0]->codec->codec_id   != AV_CODEC_ID_RAWVIDEO) {
+        s1->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
+        s1->streams[0]->codecpar->codec_id   != AV_CODEC_ID_RAWVIDEO) {
         av_log(s1, AV_LOG_ERROR,
                "V4L2 output device supports only a single raw video stream\n");
         return AVERROR(EINVAL);
     }
 
-    enc_ctx = s1->streams[0]->codec;
+    par = s1->streams[0]->codecpar;
 
-    v4l2_pixfmt = ff_fmt_ff2v4l(enc_ctx->pix_fmt, AV_CODEC_ID_RAWVIDEO);
+    v4l2_pixfmt = ff_fmt_ff2v4l(par->format, AV_CODEC_ID_RAWVIDEO);
     if (!v4l2_pixfmt) { // XXX: try to force them one by one?
         av_log(s1, AV_LOG_ERROR, "Unknown V4L2 pixel format equivalent for %s\n",
-               av_get_pix_fmt_name(enc_ctx->pix_fmt));
+               av_get_pix_fmt_name(par->format));
         return AVERROR(EINVAL);
     }
 
@@ -69,10 +69,10 @@ static av_cold int write_header(AVFormatContext *s1)
         return res;
     }
 
-    fmt.fmt.pix.width       = enc_ctx->width;
-    fmt.fmt.pix.height      = enc_ctx->height;
+    fmt.fmt.pix.width       = par->width;
+    fmt.fmt.pix.height      = par->height;
     fmt.fmt.pix.pixelformat = v4l2_pixfmt;
-    fmt.fmt.pix.sizeimage   = av_image_get_buffer_size(enc_ctx->pix_fmt, enc_ctx->width, enc_ctx->height, 1);
+    fmt.fmt.pix.sizeimage   = av_image_get_buffer_size(par->format, par->width, par->height, 1);
 
     if (ioctl(s->fd, VIDIOC_S_FMT, &fmt) < 0) {
         res = AVERROR(errno);
diff --git a/libavdevice/vfwcap.c b/libavdevice/vfwcap.c
index e1f8b86..1ed7313 100644
--- a/libavdevice/vfwcap.c
+++ b/libavdevice/vfwcap.c
@@ -161,7 +161,7 @@ static void dump_bih(AVFormatContext *s, BITMAPINFOHEADER *bih)
 static int shall_we_drop(AVFormatContext *s)
 {
     struct vfw_ctx *ctx = s->priv_data;
-    static const uint8_t dropscore[] = {62, 75, 87, 100};
+    static const uint8_t dropscore[4] = { 62, 75, 87, 100 };
     const int ndropscores = FF_ARRAY_ELEMS(dropscore);
     unsigned int buffer_fullness = (ctx->curbufsize*100)/s->max_picture_buffer;
 
@@ -245,7 +245,7 @@ static int vfw_read_close(AVFormatContext *s)
 static int vfw_read_header(AVFormatContext *s)
 {
     struct vfw_ctx *ctx = s->priv_data;
-    AVCodecContext *codec;
+    AVCodecParameters *par;
     AVStream *st;
     int devnum;
     int bisize;
@@ -377,29 +377,30 @@ static int vfw_read_header(AVFormatContext *s)
     if(!ret)
         goto fail;
 
-    codec = st->codec;
-    codec->time_base = av_inv_q(framerate_q);
-    codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    codec->width  = bi->bmiHeader.biWidth;
-    codec->height = bi->bmiHeader.biHeight;
-    codec->pix_fmt = vfw_pixfmt(biCompression, biBitCount);
-    if(codec->pix_fmt == AV_PIX_FMT_NONE) {
-        codec->codec_id = vfw_codecid(biCompression);
-        if(codec->codec_id == AV_CODEC_ID_NONE) {
+    st->avg_frame_rate = framerate_q;
+
+    par = st->codecpar;
+    par->codec_type = AVMEDIA_TYPE_VIDEO;
+    par->width  = bi->bmiHeader.biWidth;
+    par->height = bi->bmiHeader.biHeight;
+    par->format = vfw_pixfmt(biCompression, biBitCount);
+    if (par->format == AV_PIX_FMT_NONE) {
+        par->codec_id = vfw_codecid(biCompression);
+        if (par->codec_id == AV_CODEC_ID_NONE) {
             av_log(s, AV_LOG_ERROR, "Unknown compression type. "
                              "Please report verbose (-v 9) debug information.\n");
             vfw_read_close(s);
             return AVERROR_PATCHWELCOME;
         }
-        codec->bits_per_coded_sample = biBitCount;
+        par->bits_per_coded_sample = biBitCount;
     } else {
-        codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+        par->codec_id = AV_CODEC_ID_RAWVIDEO;
         if(biCompression == BI_RGB) {
-            codec->bits_per_coded_sample = biBitCount;
-            codec->extradata = av_malloc(9 + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (codec->extradata) {
-                codec->extradata_size = 9;
-                memcpy(codec->extradata, "BottomUp", 9);
+            par->bits_per_coded_sample = biBitCount;
+            par->extradata = av_malloc(9 + AV_INPUT_BUFFER_PADDING_SIZE);
+            if (par->extradata) {
+                par->extradata_size = 9;
+                memcpy(par->extradata, "BottomUp", 9);
             }
         }
     }
diff --git a/libavdevice/x11grab.c b/libavdevice/x11grab.c
index 9dc3472..5c8cfc1 100644
--- a/libavdevice/x11grab.c
+++ b/libavdevice/x11grab.c
@@ -77,7 +77,7 @@ typedef struct X11GrabContext {
     Display *dpy;            /**< X11 display from which x11grab grabs frames */
     XImage *image;           /**< X11 image holding the grab */
     int use_shm;             /**< !0 when using XShm extension */
-    XShmSegmentInfo shminfo; /**< When using XShm, keeps track of XShm infos */
+    XShmSegmentInfo shminfo; /**< When using XShm, keeps track of XShm info */
     int draw_mouse;          /**< Set by a private option. */
     int follow_mouse;        /**< Set by a private option. */
     int show_region;         /**< set by a private option. */
@@ -355,11 +355,11 @@ static int x11grab_read_header(AVFormatContext *s1)
     x11grab->image      = image;
     x11grab->use_shm    = use_shm;
 
-    ret = pixfmt_from_image(s1, image, &st->codec->pix_fmt);
+    ret = pixfmt_from_image(s1, image, &st->codecpar->format);
     if (ret < 0)
         goto out;
 
-    if (st->codec->pix_fmt == AV_PIX_FMT_PAL8) {
+    if (st->codecpar->format == AV_PIX_FMT_PAL8) {
         color_map = DefaultColormap(dpy, screen);
         for (i = 0; i < 256; ++i)
             color[i].pixel = i;
@@ -372,12 +372,13 @@ static int x11grab_read_header(AVFormatContext *s1)
     }
 
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
-    st->codec->width      = x11grab->width;
-    st->codec->height     = x11grab->height;
-    st->codec->time_base  = x11grab->time_base;
-    st->codec->bit_rate   = x11grab->frame_size * 1 / av_q2d(x11grab->time_base) * 8;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->width      = x11grab->width;
+    st->codecpar->height     = x11grab->height;
+    st->codecpar->bit_rate   = x11grab->frame_size * 1 / av_q2d(x11grab->time_base) * 8;
+
+    st->avg_frame_rate       = av_inv_q(x11grab->time_base);
 
 out:
     av_free(dpyname);
@@ -667,7 +668,7 @@ static const AVOption options[] = {
     { "centered",     "keep the mouse pointer at the center of grabbing region when following",
       0, AV_OPT_TYPE_CONST, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "follow_mouse" },
 
-    { "framerate",  "set video frame rate",      OFFSET(framerate),   AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, 0, DEC },
+    { "framerate",  "set video frame rate",      OFFSET(framerate),   AV_OPT_TYPE_VIDEO_RATE, {.str = "ntsc"}, 0, INT_MAX, DEC },
     { "show_region", "show the grabbing region", OFFSET(show_region), AV_OPT_TYPE_INT,        {.i64 = 0}, 0, 1, DEC },
     { "video_size",  "set video frame size",     OFFSET(width),       AV_OPT_TYPE_IMAGE_SIZE, {.str = "vga"}, 0, 0, DEC },
     { "use_shm",     "use MIT-SHM extension",    OFFSET(use_shm),     AV_OPT_TYPE_INT,        {.i64 = 1}, 0, 1, DEC },
diff --git a/libavdevice/xcbgrab.c b/libavdevice/xcbgrab.c
index 2da7ec7..9da46c8 100644
--- a/libavdevice/xcbgrab.c
+++ b/libavdevice/xcbgrab.c
@@ -548,13 +548,12 @@ static int create_stream(AVFormatContext *s)
                                   st->avg_frame_rate.num };
     c->time_frame = av_gettime();
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
-    st->codec->width      = c->width;
-    st->codec->height     = c->height;
-    st->codec->time_base  = c->time_base;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->width      = c->width;
+    st->codecpar->height     = c->height;
 
-    ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codec->pix_fmt);
+    ret = pixfmt_from_pixmap_format(s, geo->depth, &st->codecpar->format);
 
     free(geo);
 
diff --git a/libavdevice/xv.c b/libavdevice/xv.c
index 64cddeb..185de75 100644
--- a/libavdevice/xv.c
+++ b/libavdevice/xv.c
@@ -109,22 +109,22 @@ static int xv_write_header(AVFormatContext *s)
     XColor fgcolor;
     XWindowAttributes window_attrs;
     int num_formats = 0, j, tag, ret;
-    AVCodecContext *encctx = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
     if (   s->nb_streams > 1
-        || encctx->codec_type != AVMEDIA_TYPE_VIDEO
-        || encctx->codec_id   != AV_CODEC_ID_RAWVIDEO) {
+        || par->codec_type != AVMEDIA_TYPE_VIDEO
+        || par->codec_id   != AV_CODEC_ID_RAWVIDEO) {
         av_log(s, AV_LOG_ERROR, "Only supports one rawvideo stream\n");
         return AVERROR(EINVAL);
     }
 
-    if (!(tag = xv_get_tag_from_format(encctx->pix_fmt))) {
+    if (!(tag = xv_get_tag_from_format(par->format))) {
         av_log(s, AV_LOG_ERROR,
                "Unsupported pixel format '%s', only yuv420p, uyvy422, yuyv422 are currently supported\n",
-               av_get_pix_fmt_name(encctx->pix_fmt));
+               av_get_pix_fmt_name(par->format));
         return AVERROR_PATCHWELCOME;
     }
-    xv->image_format = encctx->pix_fmt;
+    xv->image_format = par->format;
 
     xv->display = XOpenDisplay(xv->display_name);
     if (!xv->display) {
@@ -132,12 +132,12 @@ static int xv_write_header(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    xv->image_width  = encctx->width;
-    xv->image_height = encctx->height;
+    xv->image_width  = par->width;
+    xv->image_height = par->height;
     if (!xv->window_width && !xv->window_height) {
-        AVRational sar = encctx->sample_aspect_ratio;
-        xv->window_width  = encctx->width;
-        xv->window_height = encctx->height;
+        AVRational sar = par->sample_aspect_ratio;
+        xv->window_width  = par->width;
+        xv->window_height = par->height;
         if (sar.num) {
             if (sar.num > sar.den)
                 xv->window_width = av_rescale(xv->window_width, sar.num, sar.den);
@@ -189,14 +189,14 @@ static int xv_write_header(AVFormatContext *s)
     if (j >= num_formats) {
         av_log(s, AV_LOG_ERROR,
                "Device does not support pixel format %s, aborting\n",
-               av_get_pix_fmt_name(encctx->pix_fmt));
+               av_get_pix_fmt_name(par->format));
         ret = AVERROR(EINVAL);
         goto fail;
     }
 
     xv->gc = XCreateGC(xv->display, xv->window, 0, 0);
-    xv->image_width  = encctx->width;
-    xv->image_height = encctx->height;
+    xv->image_width  = par->width;
+    xv->image_height = par->height;
     xv->yuv_image = XvShmCreateImage(xv->display, xv->xv_port, tag, 0,
                                      xv->image_width, xv->image_height, &xv->yuv_shminfo);
     xv->yuv_shminfo.shmid = shmget(IPC_PRIVATE, xv->yuv_image->data_size,
@@ -228,11 +228,11 @@ static void compute_display_area(AVFormatContext *s)
     XVContext *xv = s->priv_data;
     AVRational sar, dar; /* sample and display aspect ratios */
     AVStream *st = s->streams[0];
-    AVCodecContext *encctx = st->codec;
+    AVCodecParameters *par = st->codecpar;
 
     /* compute overlay width and height from the codec context information */
     sar = st->sample_aspect_ratio.num ? st->sample_aspect_ratio : (AVRational){ 1, 1 };
-    dar = av_mul_q(sar, (AVRational){ encctx->width, encctx->height });
+    dar = av_mul_q(sar, (AVRational){ par->width, par->height });
 
     /* we suppose the screen has a 1/1 sample aspect ratio */
     /* fit in the window */
@@ -321,12 +321,12 @@ static int write_picture(AVFormatContext *s, uint8_t *input_data[4],
 
 static int xv_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *ctx = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     uint8_t *data[4];
     int linesize[4];
 
-    av_image_fill_arrays(data, linesize, pkt->data, ctx->pix_fmt,
-                         ctx->width, ctx->height, 1);
+    av_image_fill_arrays(data, linesize, pkt->data, par->format,
+                         par->width, par->height, 1);
     return write_picture(s, data, linesize);
 }
 
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 8916588..65a831e 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -24,6 +24,10 @@ OBJS = allfilters.o                                                     \
        transform.o                                                      \
        video.o                                                          \
 
+OBJS-$(HAVE_THREADS)                         += pthread.o
+
+# audio filters
+OBJS-$(CONFIG_ABENCH_FILTER)                 += f_bench.o
 OBJS-$(CONFIG_ACOMPRESSOR_FILTER)            += af_sidechaincompress.o
 OBJS-$(CONFIG_ACROSSFADE_FILTER)             += af_afade.o
 OBJS-$(CONFIG_ADELAY_FILTER)                 += af_adelay.o
@@ -38,6 +42,7 @@ OBJS-$(CONFIG_AGATE_FILTER)                  += af_agate.o
 OBJS-$(CONFIG_AINTERLEAVE_FILTER)            += f_interleave.o
 OBJS-$(CONFIG_ALIMITER_FILTER)               += af_alimiter.o
 OBJS-$(CONFIG_ALLPASS_FILTER)                += af_biquads.o
+OBJS-$(CONFIG_ALOOP_FILTER)                  += f_loop.o
 OBJS-$(CONFIG_AMERGE_FILTER)                 += af_amerge.o
 OBJS-$(CONFIG_AMETADATA_FILTER)              += f_metadata.o
 OBJS-$(CONFIG_AMIX_FILTER)                   += af_amix.o
@@ -79,10 +84,12 @@ OBJS-$(CONFIG_EARWAX_FILTER)                 += af_earwax.o
 OBJS-$(CONFIG_EBUR128_FILTER)                += f_ebur128.o
 OBJS-$(CONFIG_EQUALIZER_FILTER)              += af_biquads.o
 OBJS-$(CONFIG_EXTRASTEREO_FILTER)            += af_extrastereo.o
+OBJS-$(CONFIG_FIREQUALIZER_FILTER)           += af_firequalizer.o
 OBJS-$(CONFIG_FLANGER_FILTER)                += af_flanger.o generate_wave_table.o
 OBJS-$(CONFIG_HIGHPASS_FILTER)               += af_biquads.o
 OBJS-$(CONFIG_JOIN_FILTER)                   += af_join.o
 OBJS-$(CONFIG_LADSPA_FILTER)                 += af_ladspa.o
+OBJS-$(CONFIG_LOUDNORM_FILTER)               += af_loudnorm.o
 OBJS-$(CONFIG_LOWPASS_FILTER)                += af_biquads.o
 OBJS-$(CONFIG_PAN_FILTER)                    += af_pan.o
 OBJS-$(CONFIG_REPLAYGAIN_FILTER)             += af_replaygain.o
@@ -100,37 +107,46 @@ OBJS-$(CONFIG_TREMOLO_FILTER)                += af_tremolo.o
 OBJS-$(CONFIG_VIBRATO_FILTER)                += af_vibrato.o generate_wave_table.o
 OBJS-$(CONFIG_VOLUME_FILTER)                 += af_volume.o
 OBJS-$(CONFIG_VOLUMEDETECT_FILTER)           += af_volumedetect.o
+OBJS-$(CONFIG_HDCD_FILTER)                   += af_hdcd.o
 
 OBJS-$(CONFIG_AEVALSRC_FILTER)               += aeval.o
 OBJS-$(CONFIG_ANOISESRC_FILTER)              += asrc_anoisesrc.o
-OBJS-$(CONFIG_ANULLSRC_FILTER)               += asrc_anullsrc.o
 OBJS-$(CONFIG_FLITE_FILTER)                  += asrc_flite.o
 OBJS-$(CONFIG_SINE_FILTER)                   += asrc_sine.o
 
 OBJS-$(CONFIG_ANULLSINK_FILTER)              += asink_anullsink.o
+OBJS-$(CONFIG_ANULLSRC_FILTER)               += asrc_anullsrc.o
 
 OBJS-$(CONFIG_ASS_FILTER)                    += vf_subtitles.o
 OBJS-$(CONFIG_ALPHAEXTRACT_FILTER)           += vf_extractplanes.o
 OBJS-$(CONFIG_ALPHAMERGE_FILTER)             += vf_alphamerge.o
 OBJS-$(CONFIG_ATADENOISE_FILTER)             += vf_atadenoise.o
 OBJS-$(CONFIG_BBOX_FILTER)                   += bbox.o vf_bbox.o
+OBJS-$(CONFIG_BENCH_FILTER)                  += f_bench.o
 OBJS-$(CONFIG_BLACKDETECT_FILTER)            += vf_blackdetect.o
+
+# video filters
 OBJS-$(CONFIG_BLACKFRAME_FILTER)             += vf_blackframe.o
 OBJS-$(CONFIG_BLEND_FILTER)                  += vf_blend.o dualinput.o framesync.o
 OBJS-$(CONFIG_BOXBLUR_FILTER)                += vf_boxblur.o
+OBJS-$(CONFIG_BWDIF_FILTER)                  += vf_bwdif.o
 OBJS-$(CONFIG_CHROMAKEY_FILTER)              += vf_chromakey.o
+OBJS-$(CONFIG_CIESCOPE_FILTER)               += vf_ciescope.o
 OBJS-$(CONFIG_CODECVIEW_FILTER)              += vf_codecview.o
 OBJS-$(CONFIG_COLORBALANCE_FILTER)           += vf_colorbalance.o
 OBJS-$(CONFIG_COLORCHANNELMIXER_FILTER)      += vf_colorchannelmixer.o
 OBJS-$(CONFIG_COLORKEY_FILTER)               += vf_colorkey.o
 OBJS-$(CONFIG_COLORLEVELS_FILTER)            += vf_colorlevels.o
 OBJS-$(CONFIG_COLORMATRIX_FILTER)            += vf_colormatrix.o
+OBJS-$(CONFIG_COLORSPACE_FILTER)             += vf_colorspace.o colorspacedsp.o
 OBJS-$(CONFIG_CONVOLUTION_FILTER)            += vf_convolution.o
 OBJS-$(CONFIG_COPY_FILTER)                   += vf_copy.o
+OBJS-$(CONFIG_COREIMAGE_FILTER)              += vf_coreimage.o
 OBJS-$(CONFIG_COVER_RECT_FILTER)             += vf_cover_rect.o lavfutils.o
 OBJS-$(CONFIG_CROP_FILTER)                   += vf_crop.o
 OBJS-$(CONFIG_CROPDETECT_FILTER)             += vf_cropdetect.o
 OBJS-$(CONFIG_CURVES_FILTER)                 += vf_curves.o
+OBJS-$(CONFIG_DATASCOPE_FILTER)              += vf_datascope.o
 OBJS-$(CONFIG_DCTDNOIZ_FILTER)               += vf_dctdnoiz.o
 OBJS-$(CONFIG_DEBAND_FILTER)                 += vf_deband.o
 OBJS-$(CONFIG_DECIMATE_FILTER)               += vf_decimate.o
@@ -153,6 +169,7 @@ OBJS-$(CONFIG_EXTRACTPLANES_FILTER)          += vf_extractplanes.o
 OBJS-$(CONFIG_FADE_FILTER)                   += vf_fade.o
 OBJS-$(CONFIG_FFTFILT_FILTER)                += vf_fftfilt.o
 OBJS-$(CONFIG_FIELD_FILTER)                  += vf_field.o
+OBJS-$(CONFIG_FIELDHINT_FILTER)              += vf_fieldhint.o
 OBJS-$(CONFIG_FIELDMATCH_FILTER)             += vf_fieldmatch.o
 OBJS-$(CONFIG_FIELDORDER_FILTER)             += vf_fieldorder.o
 OBJS-$(CONFIG_FIND_RECT_FILTER)              += vf_find_rect.o lavfutils.o
@@ -171,6 +188,9 @@ OBJS-$(CONFIG_HISTEQ_FILTER)                 += vf_histeq.o
 OBJS-$(CONFIG_HISTOGRAM_FILTER)              += vf_histogram.o
 OBJS-$(CONFIG_HQDN3D_FILTER)                 += vf_hqdn3d.o
 OBJS-$(CONFIG_HQX_FILTER)                    += vf_hqx.o
+OBJS-$(CONFIG_HWDOWNLOAD_FILTER)             += vf_hwdownload.o
+OBJS-$(CONFIG_HWUPLOAD_CUDA_FILTER)          += vf_hwupload_cuda.o
+OBJS-$(CONFIG_HWUPLOAD_FILTER)               += vf_hwupload.o
 OBJS-$(CONFIG_HSTACK_FILTER)                 += vf_stack.o framesync.o
 OBJS-$(CONFIG_HUE_FILTER)                    += vf_hue.o
 OBJS-$(CONFIG_IDET_FILTER)                   += vf_idet.o
@@ -180,6 +200,7 @@ OBJS-$(CONFIG_INTERLACE_FILTER)              += vf_interlace.o
 OBJS-$(CONFIG_INTERLEAVE_FILTER)             += f_interleave.o
 OBJS-$(CONFIG_KERNDEINT_FILTER)              += vf_kerndeint.o
 OBJS-$(CONFIG_LENSCORRECTION_FILTER)         += vf_lenscorrection.o
+OBJS-$(CONFIG_LOOP_FILTER)                   += f_loop.o
 OBJS-$(CONFIG_LUT3D_FILTER)                  += vf_lut3d.o
 OBJS-$(CONFIG_LUT_FILTER)                    += vf_lut.o
 OBJS-$(CONFIG_LUTRGB_FILTER)                 += vf_lut.o
@@ -212,7 +233,9 @@ OBJS-$(CONFIG_PSNR_FILTER)                   += vf_psnr.o dualinput.o framesync.
 OBJS-$(CONFIG_PULLUP_FILTER)                 += vf_pullup.o
 OBJS-$(CONFIG_QP_FILTER)                     += vf_qp.o
 OBJS-$(CONFIG_RANDOM_FILTER)                 += vf_random.o
+OBJS-$(CONFIG_READVITC_FILTER)               += vf_readvitc.o
 OBJS-$(CONFIG_REALTIME_FILTER)               += f_realtime.o
+OBJS-$(CONFIG_REMAP_FILTER)                  += vf_remap.o framesync.o
 OBJS-$(CONFIG_REMOVEGRAIN_FILTER)            += vf_removegrain.o
 OBJS-$(CONFIG_REMOVELOGO_FILTER)             += bbox.o lswsutils.o lavfutils.o vf_removelogo.o
 OBJS-$(CONFIG_REPEATFIELDS_FILTER)           += vf_repeatfields.o
@@ -225,6 +248,8 @@ OBJS-$(CONFIG_SCALE2REF_FILTER)              += vf_scale.o
 OBJS-$(CONFIG_SELECT_FILTER)                 += f_select.o
 OBJS-$(CONFIG_SELECTIVECOLOR_FILTER)         += vf_selectivecolor.o
 OBJS-$(CONFIG_SENDCMD_FILTER)                += f_sendcmd.o
+OBJS-$(CONFIG_SCALE_NPP_FILTER)              += vf_scale_npp.o
+OBJS-$(CONFIG_SCALE_VAAPI_FILTER)            += vf_scale_vaapi.o
 OBJS-$(CONFIG_SETDAR_FILTER)                 += vf_aspect.o
 OBJS-$(CONFIG_SETFIELD_FILTER)               += vf_setfield.o
 OBJS-$(CONFIG_SETPTS_FILTER)                 += setpts.o
@@ -271,7 +296,9 @@ OBJS-$(CONFIG_ZSCALE_FILTER)                 += vf_zscale.o
 OBJS-$(CONFIG_ALLRGB_FILTER)                 += vsrc_testsrc.o
 OBJS-$(CONFIG_ALLYUV_FILTER)                 += vsrc_testsrc.o
 OBJS-$(CONFIG_CELLAUTO_FILTER)               += vsrc_cellauto.o
+OBJS-$(CONFIG_NULLSINK_FILTER)               += vsink_nullsink.o
 OBJS-$(CONFIG_COLOR_FILTER)                  += vsrc_testsrc.o
+OBJS-$(CONFIG_COREIMAGESRC_FILTER)           += vf_coreimage.o
 OBJS-$(CONFIG_FREI0R_SRC_FILTER)             += vf_frei0r.o
 OBJS-$(CONFIG_HALDCLUTSRC_FILTER)            += vsrc_testsrc.o
 OBJS-$(CONFIG_LIFE_FILTER)                   += vsrc_life.o
@@ -284,8 +311,6 @@ OBJS-$(CONFIG_SMPTEHDBARS_FILTER)            += vsrc_testsrc.o
 OBJS-$(CONFIG_TESTSRC_FILTER)                += vsrc_testsrc.o
 OBJS-$(CONFIG_TESTSRC2_FILTER)               += vsrc_testsrc.o
 
-OBJS-$(CONFIG_NULLSINK_FILTER)               += vsink_nullsink.o
-
 # multimedia filters
 OBJS-$(CONFIG_ADRAWGRAPH_FILTER)             += f_drawgraph.o
 OBJS-$(CONFIG_AHISTOGRAM_FILTER)             += avf_ahistogram.o
@@ -311,7 +336,6 @@ SLIBOBJS-$(HAVE_GNU_WINDRES)                 += avfilterres.o
 SKIPHEADERS-$(CONFIG_LIBVIDSTAB)             += vidstabutils.h
 SKIPHEADERS-$(CONFIG_OPENCL)                 += opencl_internal.h deshake_opencl_kernel.h unsharp_opencl_kernel.h
 
-OBJS-$(HAVE_THREADS)                         += pthread.o
 OBJS-$(CONFIG_SHARED)                        += log2_tab.o
 
 TOOLS     = graph2dot
diff --git a/libavfilter/af_afftfilt.c b/libavfilter/af_afftfilt.c
index 8e41f52..3fc1a1b 100644
--- a/libavfilter/af_afftfilt.c
+++ b/libavfilter/af_afftfilt.c
@@ -60,7 +60,7 @@ enum                                   { VAR_SAMPLE_RATE, VAR_BIN, VAR_NBBINS, V
 static const AVOption afftfilt_options[] = {
     { "real", "set channels real expressions",       OFFSET(real_str), AV_OPT_TYPE_STRING, {.str = "1" }, 0, 0, A },
     { "imag",  "set channels imaginary expressions", OFFSET(img_str),  AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, A },
-    { "win_size", "set window size", OFFSET(fft_bits), AV_OPT_TYPE_INT, {.i64=12}, 4, 16, A, "fft" },
+    { "win_size", "set window size", OFFSET(fft_bits), AV_OPT_TYPE_INT, {.i64=12}, 4, 17, A, "fft" },
         { "w16",    0, 0, AV_OPT_TYPE_CONST, {.i64=4},  0, 0, A, "fft" },
         { "w32",    0, 0, AV_OPT_TYPE_CONST, {.i64=5},  0, 0, A, "fft" },
         { "w64",    0, 0, AV_OPT_TYPE_CONST, {.i64=6},  0, 0, A, "fft" },
@@ -74,6 +74,7 @@ static const AVOption afftfilt_options[] = {
         { "w16384", 0, 0, AV_OPT_TYPE_CONST, {.i64=14}, 0, 0, A, "fft" },
         { "w32768", 0, 0, AV_OPT_TYPE_CONST, {.i64=15}, 0, 0, A, "fft" },
         { "w65536", 0, 0, AV_OPT_TYPE_CONST, {.i64=16}, 0, 0, A, "fft" },
+        { "w131072",0, 0, AV_OPT_TYPE_CONST, {.i64=17}, 0, 0, A, "fft" },
     { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64 = WFUNC_HANNING}, 0, NB_WFUNC-1, A, "win_func" },
         { "rect",     "Rectangular",      0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT},     0, 0, A, "win_func" },
         { "bartlett", "Bartlett",         0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, A, "win_func" },
diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c
index e64e289..3e5e7ee 100644
--- a/libavfilter/af_amix.c
+++ b/libavfilter/af_amix.c
@@ -312,6 +312,9 @@ static int output_frame(AVFilterLink *outlink)
 
     calculate_scales(s, nb_samples);
 
+    if (nb_samples == 0)
+        return 0;
+
     out_buf = ff_get_audio_buffer(outlink, nb_samples);
     if (!out_buf)
         return AVERROR(ENOMEM);
diff --git a/libavfilter/af_anequalizer.c b/libavfilter/af_anequalizer.c
index a344c77..2403460 100644
--- a/libavfilter/af_anequalizer.c
+++ b/libavfilter/af_anequalizer.c
@@ -21,6 +21,7 @@
 
 #include "libavutil/intreadwrite.h"
 #include "libavutil/avstring.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "avfilter.h"
diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c
index b3b8f28..17b8ad0 100644
--- a/libavfilter/af_astats.c
+++ b/libavfilter/af_astats.c
@@ -98,14 +98,27 @@ static void reset_stats(AudioStatsContext *s)
 {
     int c;
 
-    memset(s->chstats, 0, sizeof(*s->chstats));
-
     for (c = 0; c < s->nb_channels; c++) {
         ChannelStats *p = &s->chstats[c];
 
         p->min = p->min_sigma_x2 = DBL_MAX;
         p->max = p->max_sigma_x2 = DBL_MIN;
-        p->min_diff = p->max_diff = -1;
+        p->min_diff = DBL_MAX;
+        p->max_diff = DBL_MIN;
+        p->sigma_x = 0;
+        p->sigma_x2 = 0;
+        p->avg_sigma_x2 = 0;
+        p->min_sigma_x2 = 0;
+        p->max_sigma_x2 = 0;
+        p->min_run = 0;
+        p->max_run = 0;
+        p->min_runs = 0;
+        p->max_runs = 0;
+        p->diff1_sum = 0;
+        p->mask = 0;
+        p->min_count = 0;
+        p->max_count = 0;
+        p->nb_samples = 0;
     }
 }
 
@@ -119,6 +132,7 @@ static int config_output(AVFilterLink *outlink)
     s->nb_channels = outlink->channels;
     s->mult = exp((-1 / s->time_constant / outlink->sample_rate));
     s->tc_samples = 5 * s->time_constant * outlink->sample_rate + .5;
+    s->nb_frames = 0;
 
     reset_stats(s);
 
@@ -163,8 +177,8 @@ static inline void update_stat(AudioStatsContext *s, ChannelStats *p, double d)
     p->sigma_x += d;
     p->sigma_x2 += d * d;
     p->avg_sigma_x2 = p->avg_sigma_x2 * s->mult + (1.0 - s->mult) * d * d;
-    p->min_diff = FFMIN(p->min_diff == -1 ? DBL_MAX : p->min_diff, fabs(d - (p->min_diff == -1 ? DBL_MAX : p->last)));
-    p->max_diff = FFMAX(p->max_diff, fabs(d - (p->max_diff == -1 ? d : p->last)));
+    p->min_diff = FFMIN(p->min_diff, fabs(d - p->last));
+    p->max_diff = FFMAX(p->max_diff, fabs(d - p->last));
     p->diff1_sum += fabs(d - p->last);
     p->last = d;
     p->mask |= llrint(d * (UINT64_C(1) << 63));
@@ -269,6 +283,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
     const double *src;
     int i, c;
 
+    if (s->reset_count > 0) {
+        if (s->nb_frames >= s->reset_count) {
+            reset_stats(s);
+            s->nb_frames = 0;
+        }
+        s->nb_frames++;
+    }
+
     switch (inlink->format) {
     case AV_SAMPLE_FMT_DBLP:
         for (c = 0; c < channels; c++) {
@@ -292,14 +314,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
     if (s->metadata)
         set_metadata(s, metadata);
 
-    if (s->reset_count > 0) {
-        s->nb_frames++;
-        if (s->nb_frames >= s->reset_count) {
-            reset_stats(s);
-            s->nb_frames = 0;
-        }
-    }
-
     return ff_filter_frame(inlink->dst->outputs[0], buf);
 }
 
diff --git a/libavfilter/af_compand.c b/libavfilter/af_compand.c
index b746364..0bb719f 100644
--- a/libavfilter/af_compand.c
+++ b/libavfilter/af_compand.c
@@ -29,6 +29,7 @@
 
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/opt.h"
 #include "libavutil/samplefmt.h"
 #include "audio.h"
diff --git a/libavfilter/af_firequalizer.c b/libavfilter/af_firequalizer.c
new file mode 100644
index 0000000..6a9c641
--- /dev/null
+++ b/libavfilter/af_firequalizer.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright (c) 2016 Muhammad Faiz <mfcc64 at gmail.com>
+ *
+ * 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/eval.h"
+#include "libavutil/avassert.h"
+#include "libavcodec/avfft.h"
+#include "avfilter.h"
+#include "internal.h"
+#include "audio.h"
+
+#define RDFT_BITS_MIN 4
+#define RDFT_BITS_MAX 16
+
+enum WindowFunc {
+    WFUNC_MIN,
+    WFUNC_RECTANGULAR = WFUNC_MIN,
+    WFUNC_HANN,
+    WFUNC_HAMMING,
+    WFUNC_BLACKMAN,
+    WFUNC_NUTTALL3,
+    WFUNC_MNUTTALL3,
+    WFUNC_NUTTALL,
+    WFUNC_BNUTTALL,
+    WFUNC_BHARRIS,
+    WFUNC_MAX = WFUNC_BHARRIS
+};
+
+#define NB_GAIN_ENTRY_MAX 4096
+typedef struct {
+    double  freq;
+    double  gain;
+} GainEntry;
+
+typedef struct {
+    int buf_idx;
+    int overlap_idx;
+} OverlapIndex;
+
+typedef struct {
+    const AVClass *class;
+
+    RDFTContext   *analysis_irdft;
+    RDFTContext   *rdft;
+    RDFTContext   *irdft;
+    int           analysis_rdft_len;
+    int           rdft_len;
+
+    float         *analysis_buf;
+    float         *kernel_tmp_buf;
+    float         *kernel_buf;
+    float         *conv_buf;
+    OverlapIndex  *conv_idx;
+    int           fir_len;
+    int           nsamples_max;
+    int64_t       next_pts;
+    int           frame_nsamples_max;
+    int           remaining;
+
+    char          *gain_cmd;
+    char          *gain_entry_cmd;
+    const char    *gain;
+    const char    *gain_entry;
+    double        delay;
+    double        accuracy;
+    int           wfunc;
+    int           fixed;
+    int           multi;
+    int           zero_phase;
+
+    int           nb_gain_entry;
+    int           gain_entry_err;
+    GainEntry     gain_entry_tbl[NB_GAIN_ENTRY_MAX];
+} FIREqualizerContext;
+
+#define OFFSET(x) offsetof(FIREqualizerContext, x)
+#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+static const AVOption firequalizer_options[] = {
+    { "gain", "set gain curve", OFFSET(gain), AV_OPT_TYPE_STRING, { .str = "gain_interpolate(f)" }, 0, 0, FLAGS },
+    { "gain_entry", "set gain entry", OFFSET(gain_entry), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
+    { "delay", "set delay", OFFSET(delay), AV_OPT_TYPE_DOUBLE, { .dbl = 0.01 }, 0.0, 1e10, FLAGS },
+    { "accuracy", "set accuracy", OFFSET(accuracy), AV_OPT_TYPE_DOUBLE, { .dbl = 5.0 }, 0.0, 1e10, FLAGS },
+    { "wfunc", "set window function", OFFSET(wfunc), AV_OPT_TYPE_INT, { .i64 = WFUNC_HANN }, WFUNC_MIN, WFUNC_MAX, FLAGS, "wfunc" },
+        { "rectangular", "rectangular window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_RECTANGULAR }, 0, 0, FLAGS, "wfunc" },
+        { "hann", "hann window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_HANN }, 0, 0, FLAGS, "wfunc" },
+        { "hamming", "hamming window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_HAMMING }, 0, 0, FLAGS, "wfunc" },
+        { "blackman", "blackman window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_BLACKMAN }, 0, 0, FLAGS, "wfunc" },
+        { "nuttall3", "3-term nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_NUTTALL3 }, 0, 0, FLAGS, "wfunc" },
+        { "mnuttall3", "minimum 3-term nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_MNUTTALL3 }, 0, 0, FLAGS, "wfunc" },
+        { "nuttall", "nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_NUTTALL }, 0, 0, FLAGS, "wfunc" },
+        { "bnuttall", "blackman-nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_BNUTTALL }, 0, 0, FLAGS, "wfunc" },
+        { "bharris", "blackman-harris window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_BHARRIS }, 0, 0, FLAGS, "wfunc" },
+    { "fixed", "set fixed frame samples", OFFSET(fixed), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
+    { "multi", "set multi channels mode", OFFSET(multi), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
+    { "zero_phase", "set zero phase mode", OFFSET(zero_phase), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(firequalizer);
+
+static void common_uninit(FIREqualizerContext *s)
+{
+    av_rdft_end(s->analysis_irdft);
+    av_rdft_end(s->rdft);
+    av_rdft_end(s->irdft);
+    s->analysis_irdft = s->rdft = s->irdft = NULL;
+
+    av_freep(&s->analysis_buf);
+    av_freep(&s->kernel_tmp_buf);
+    av_freep(&s->kernel_buf);
+    av_freep(&s->conv_buf);
+    av_freep(&s->conv_idx);
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    FIREqualizerContext *s = ctx->priv;
+
+    common_uninit(s);
+    av_freep(&s->gain_cmd);
+    av_freep(&s->gain_entry_cmd);
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+    AVFilterChannelLayouts *layouts;
+    AVFilterFormats *formats;
+    static const enum AVSampleFormat sample_fmts[] = {
+        AV_SAMPLE_FMT_FLTP,
+        AV_SAMPLE_FMT_NONE
+    };
+    int ret;
+
+    layouts = ff_all_channel_counts();
+    if (!layouts)
+        return AVERROR(ENOMEM);
+    ret = ff_set_common_channel_layouts(ctx, layouts);
+    if (ret < 0)
+        return ret;
+
+    formats = ff_make_format_list(sample_fmts);
+    if (!formats)
+        return AVERROR(ENOMEM);
+    ret = ff_set_common_formats(ctx, formats);
+    if (ret < 0)
+        return ret;
+
+    formats = ff_all_samplerates();
+    if (!formats)
+        return AVERROR(ENOMEM);
+    return ff_set_common_samplerates(ctx, formats);
+}
+
+static void fast_convolute(FIREqualizerContext *s, const float *kernel_buf, float *conv_buf,
+                           OverlapIndex *idx, float *data, int nsamples)
+{
+    if (nsamples <= s->nsamples_max) {
+        float *buf = conv_buf + idx->buf_idx * s->rdft_len;
+        float *obuf = conv_buf + !idx->buf_idx * s->rdft_len + idx->overlap_idx;
+        int k;
+
+        memcpy(buf, data, nsamples * sizeof(*data));
+        memset(buf + nsamples, 0, (s->rdft_len - nsamples) * sizeof(*data));
+        av_rdft_calc(s->rdft, buf);
+
+        buf[0] *= kernel_buf[0];
+        buf[1] *= kernel_buf[1];
+        for (k = 2; k < s->rdft_len; k += 2) {
+            float re, im;
+            re = buf[k] * kernel_buf[k] - buf[k+1] * kernel_buf[k+1];
+            im = buf[k] * kernel_buf[k+1] + buf[k+1] * kernel_buf[k];
+            buf[k] = re;
+            buf[k+1] = im;
+        }
+
+        av_rdft_calc(s->irdft, buf);
+        for (k = 0; k < s->rdft_len - idx->overlap_idx; k++)
+            buf[k] += obuf[k];
+        memcpy(data, buf, nsamples * sizeof(*data));
+        idx->buf_idx = !idx->buf_idx;
+        idx->overlap_idx = nsamples;
+    } else {
+        while (nsamples > s->nsamples_max * 2) {
+            fast_convolute(s, kernel_buf, conv_buf, idx, data, s->nsamples_max);
+            data += s->nsamples_max;
+            nsamples -= s->nsamples_max;
+        }
+        fast_convolute(s, kernel_buf, conv_buf, idx, data, nsamples/2);
+        fast_convolute(s, kernel_buf, conv_buf, idx, data + nsamples/2, nsamples - nsamples/2);
+    }
+}
+
+static double entry_func(void *p, double freq, double gain)
+{
+    AVFilterContext *ctx = p;
+    FIREqualizerContext *s = ctx->priv;
+
+    if (s->nb_gain_entry >= NB_GAIN_ENTRY_MAX) {
+        av_log(ctx, AV_LOG_ERROR, "entry table overflow.\n");
+        s->gain_entry_err = AVERROR(EINVAL);
+        return 0;
+    }
+
+    if (isnan(freq)) {
+        av_log(ctx, AV_LOG_ERROR, "nan frequency (%g, %g).\n", freq, gain);
+        s->gain_entry_err = AVERROR(EINVAL);
+        return 0;
+    }
+
+    if (s->nb_gain_entry > 0 && freq <= s->gain_entry_tbl[s->nb_gain_entry - 1].freq) {
+        av_log(ctx, AV_LOG_ERROR, "unsorted frequency (%g, %g).\n", freq, gain);
+        s->gain_entry_err = AVERROR(EINVAL);
+        return 0;
+    }
+
+    s->gain_entry_tbl[s->nb_gain_entry].freq = freq;
+    s->gain_entry_tbl[s->nb_gain_entry].gain = gain;
+    s->nb_gain_entry++;
+    return 0;
+}
+
+static int gain_entry_compare(const void *key, const void *memb)
+{
+    const double *freq = key;
+    const GainEntry *entry = memb;
+
+    if (*freq < entry[0].freq)
+        return -1;
+    if (*freq > entry[1].freq)
+        return 1;
+    return 0;
+}
+
+static double gain_interpolate_func(void *p, double freq)
+{
+    AVFilterContext *ctx = p;
+    FIREqualizerContext *s = ctx->priv;
+    GainEntry *res;
+    double d0, d1, d;
+
+    if (isnan(freq))
+        return freq;
+
+    if (!s->nb_gain_entry)
+        return 0;
+
+    if (freq <= s->gain_entry_tbl[0].freq)
+        return s->gain_entry_tbl[0].gain;
+
+    if (freq >= s->gain_entry_tbl[s->nb_gain_entry-1].freq)
+        return s->gain_entry_tbl[s->nb_gain_entry-1].gain;
+
+    res = bsearch(&freq, &s->gain_entry_tbl, s->nb_gain_entry - 1, sizeof(*res), gain_entry_compare);
+    av_assert0(res);
+
+    d  = res[1].freq - res[0].freq;
+    d0 = freq - res[0].freq;
+    d1 = res[1].freq - freq;
+
+    if (d0 && d1)
+        return (d0 * res[1].gain + d1 * res[0].gain) / d;
+
+    if (d0)
+        return res[1].gain;
+
+    return res[0].gain;
+}
+
+static const char *const var_names[] = {
+    "f",
+    "sr",
+    "ch",
+    "chid",
+    "chs",
+    "chlayout",
+    NULL
+};
+
+enum VarOffset {
+    VAR_F,
+    VAR_SR,
+    VAR_CH,
+    VAR_CHID,
+    VAR_CHS,
+    VAR_CHLAYOUT,
+    VAR_NB
+};
+
+static int generate_kernel(AVFilterContext *ctx, const char *gain, const char *gain_entry)
+{
+    FIREqualizerContext *s = ctx->priv;
+    AVFilterLink *inlink = ctx->inputs[0];
+    const char *gain_entry_func_names[] = { "entry", NULL };
+    const char *gain_func_names[] = { "gain_interpolate", NULL };
+    double (*gain_entry_funcs[])(void *, double, double) = { entry_func, NULL };
+    double (*gain_funcs[])(void *, double) = { gain_interpolate_func, NULL };
+    double vars[VAR_NB];
+    AVExpr *gain_expr;
+    int ret, k, center, ch;
+
+    s->nb_gain_entry = 0;
+    s->gain_entry_err = 0;
+    if (gain_entry) {
+        double result = 0.0;
+        ret = av_expr_parse_and_eval(&result, gain_entry, NULL, NULL, NULL, NULL,
+                                     gain_entry_func_names, gain_entry_funcs, ctx, 0, ctx);
+        if (ret < 0)
+            return ret;
+        if (s->gain_entry_err < 0)
+            return s->gain_entry_err;
+    }
+
+    av_log(ctx, AV_LOG_DEBUG, "nb_gain_entry = %d.\n", s->nb_gain_entry);
+
+    ret = av_expr_parse(&gain_expr, gain, var_names,
+                        gain_func_names, gain_funcs, NULL, NULL, 0, ctx);
+    if (ret < 0)
+        return ret;
+
+    vars[VAR_CHS] = inlink->channels;
+    vars[VAR_CHLAYOUT] = inlink->channel_layout;
+    vars[VAR_SR] = inlink->sample_rate;
+    for (ch = 0; ch < inlink->channels; ch++) {
+        vars[VAR_CH] = ch;
+        vars[VAR_CHID] = av_channel_layout_extract_channel(inlink->channel_layout, ch);
+        vars[VAR_F] = 0.0;
+        s->analysis_buf[0] = pow(10.0, 0.05 * av_expr_eval(gain_expr, vars, ctx));
+        vars[VAR_F] = 0.5 * inlink->sample_rate;
+        s->analysis_buf[1] = pow(10.0, 0.05 * av_expr_eval(gain_expr, vars, ctx));
+
+        for (k = 1; k < s->analysis_rdft_len/2; k++) {
+            vars[VAR_F] = k * ((double)inlink->sample_rate /(double)s->analysis_rdft_len);
+            s->analysis_buf[2*k] = pow(10.0, 0.05 * av_expr_eval(gain_expr, vars, ctx));
+            s->analysis_buf[2*k+1] = 0.0;
+        }
+
+        av_rdft_calc(s->analysis_irdft, s->analysis_buf);
+        center = s->fir_len / 2;
+
+        for (k = 0; k <= center; k++) {
+            double u = k * (M_PI/center);
+            double win;
+            switch (s->wfunc) {
+            case WFUNC_RECTANGULAR:
+                win = 1.0;
+                break;
+            case WFUNC_HANN:
+                win = 0.5 + 0.5 * cos(u);
+                break;
+            case WFUNC_HAMMING:
+                win = 0.53836 + 0.46164 * cos(u);
+                break;
+            case WFUNC_BLACKMAN:
+                win = 0.48 + 0.5 * cos(u) + 0.02 * cos(2*u);
+                break;
+            case WFUNC_NUTTALL3:
+                win = 0.40897 + 0.5 * cos(u) + 0.09103 * cos(2*u);
+                break;
+            case WFUNC_MNUTTALL3:
+                win = 0.4243801 + 0.4973406 * cos(u) + 0.0782793 * cos(2*u);
+                break;
+            case WFUNC_NUTTALL:
+                win = 0.355768 + 0.487396 * cos(u) + 0.144232 * cos(2*u) + 0.012604 * cos(3*u);
+                break;
+            case WFUNC_BNUTTALL:
+                win = 0.3635819 + 0.4891775 * cos(u) + 0.1365995 * cos(2*u) + 0.0106411 * cos(3*u);
+                break;
+            case WFUNC_BHARRIS:
+                win = 0.35875 + 0.48829 * cos(u) + 0.14128 * cos(2*u) + 0.01168 * cos(3*u);
+                break;
+            default:
+                av_assert0(0);
+            }
+            s->analysis_buf[k] *= (2.0/s->analysis_rdft_len) * (2.0/s->rdft_len) * win;
+        }
+
+        for (k = 0; k < center - k; k++) {
+            float tmp = s->analysis_buf[k];
+            s->analysis_buf[k] = s->analysis_buf[center - k];
+            s->analysis_buf[center - k] = tmp;
+        }
+
+        for (k = 1; k <= center; k++)
+            s->analysis_buf[center + k] = s->analysis_buf[center - k];
+
+        memset(s->analysis_buf + s->fir_len, 0, (s->rdft_len - s->fir_len) * sizeof(*s->analysis_buf));
+        av_rdft_calc(s->rdft, s->analysis_buf);
+
+        for (k = 0; k < s->rdft_len; k++) {
+            if (isnan(s->analysis_buf[k]) || isinf(s->analysis_buf[k])) {
+                av_log(ctx, AV_LOG_ERROR, "filter kernel contains nan or infinity.\n");
+                av_expr_free(gain_expr);
+                return AVERROR(EINVAL);
+            }
+        }
+
+        memcpy(s->kernel_tmp_buf + ch * s->rdft_len, s->analysis_buf, s->rdft_len * sizeof(*s->analysis_buf));
+        if (!s->multi)
+            break;
+    }
+
+    memcpy(s->kernel_buf, s->kernel_tmp_buf, (s->multi ? inlink->channels : 1) * s->rdft_len * sizeof(*s->kernel_buf));
+    av_expr_free(gain_expr);
+    return 0;
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+    AVFilterContext *ctx = inlink->dst;
+    FIREqualizerContext *s = ctx->priv;
+    int rdft_bits;
+
+    common_uninit(s);
+
+    s->next_pts = 0;
+    s->frame_nsamples_max = 0;
+
+    s->fir_len = FFMAX(2 * (int)(inlink->sample_rate * s->delay) + 1, 3);
+    s->remaining = s->fir_len - 1;
+
+    for (rdft_bits = RDFT_BITS_MIN; rdft_bits <= RDFT_BITS_MAX; rdft_bits++) {
+        s->rdft_len = 1 << rdft_bits;
+        s->nsamples_max = s->rdft_len - s->fir_len + 1;
+        if (s->nsamples_max * 2 >= s->fir_len)
+            break;
+    }
+
+    if (rdft_bits > RDFT_BITS_MAX) {
+        av_log(ctx, AV_LOG_ERROR, "too large delay, please decrease it.\n");
+        return AVERROR(EINVAL);
+    }
+
+    if (!(s->rdft = av_rdft_init(rdft_bits, DFT_R2C)) || !(s->irdft = av_rdft_init(rdft_bits, IDFT_C2R)))
+        return AVERROR(ENOMEM);
+
+    for ( ; rdft_bits <= RDFT_BITS_MAX; rdft_bits++) {
+        s->analysis_rdft_len = 1 << rdft_bits;
+        if (inlink->sample_rate <= s->accuracy * s->analysis_rdft_len)
+            break;
+    }
+
+    if (rdft_bits > RDFT_BITS_MAX) {
+        av_log(ctx, AV_LOG_ERROR, "too small accuracy, please increase it.\n");
+        return AVERROR(EINVAL);
+    }
+
+    if (!(s->analysis_irdft = av_rdft_init(rdft_bits, IDFT_C2R)))
+        return AVERROR(ENOMEM);
+
+    s->analysis_buf = av_malloc_array(s->analysis_rdft_len, sizeof(*s->analysis_buf));
+    s->kernel_tmp_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->channels : 1), sizeof(*s->kernel_tmp_buf));
+    s->kernel_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->channels : 1), sizeof(*s->kernel_buf));
+    s->conv_buf   = av_calloc(2 * s->rdft_len * inlink->channels, sizeof(*s->conv_buf));
+    s->conv_idx   = av_calloc(inlink->channels, sizeof(*s->conv_idx));
+    if (!s->analysis_buf || !s->kernel_tmp_buf || !s->kernel_buf || !s->conv_buf || !s->conv_idx)
+        return AVERROR(ENOMEM);
+
+    av_log(ctx, AV_LOG_DEBUG, "sample_rate = %d, channels = %d, analysis_rdft_len = %d, rdft_len = %d, fir_len = %d, nsamples_max = %d.\n",
+           inlink->sample_rate, inlink->channels, s->analysis_rdft_len, s->rdft_len, s->fir_len, s->nsamples_max);
+
+    if (s->fixed)
+        inlink->min_samples = inlink->max_samples = inlink->partial_buf_size = s->nsamples_max;
+
+    return generate_kernel(ctx, s->gain_cmd ? s->gain_cmd : s->gain,
+                           s->gain_entry_cmd ? s->gain_entry_cmd : s->gain_entry);
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
+{
+    AVFilterContext *ctx = inlink->dst;
+    FIREqualizerContext *s = ctx->priv;
+    int ch;
+
+    for (ch = 0; ch < inlink->channels; ch++) {
+        fast_convolute(s, s->kernel_buf + (s->multi ? ch * s->rdft_len : 0),
+                       s->conv_buf + 2 * ch * s->rdft_len, s->conv_idx + ch,
+                       (float *) frame->extended_data[ch], frame->nb_samples);
+    }
+
+    s->next_pts = AV_NOPTS_VALUE;
+    if (frame->pts != AV_NOPTS_VALUE) {
+        s->next_pts = frame->pts + av_rescale_q(frame->nb_samples, av_make_q(1, inlink->sample_rate), inlink->time_base);
+        if (s->zero_phase)
+            frame->pts -= av_rescale_q(s->fir_len/2, av_make_q(1, inlink->sample_rate), inlink->time_base);
+    }
+    s->frame_nsamples_max = FFMAX(s->frame_nsamples_max, frame->nb_samples);
+    return ff_filter_frame(ctx->outputs[0], frame);
+}
+
+static int request_frame(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    FIREqualizerContext *s= ctx->priv;
+    int ret;
+
+    ret = ff_request_frame(ctx->inputs[0]);
+    if (ret == AVERROR_EOF && s->remaining > 0 && s->frame_nsamples_max > 0) {
+        AVFrame *frame = ff_get_audio_buffer(outlink, FFMIN(s->remaining, s->frame_nsamples_max));
+
+        if (!frame)
+            return AVERROR(ENOMEM);
+
+        av_samples_set_silence(frame->extended_data, 0, frame->nb_samples, outlink->channels, frame->format);
+        frame->pts = s->next_pts;
+        s->remaining -= frame->nb_samples;
+        ret = filter_frame(ctx->inputs[0], frame);
+    }
+
+    return ret;
+}
+
+static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
+                           char *res, int res_len, int flags)
+{
+    FIREqualizerContext *s = ctx->priv;
+    int ret = AVERROR(ENOSYS);
+
+    if (!strcmp(cmd, "gain")) {
+        char *gain_cmd;
+
+        gain_cmd = av_strdup(args);
+        if (!gain_cmd)
+            return AVERROR(ENOMEM);
+
+        ret = generate_kernel(ctx, gain_cmd, s->gain_entry_cmd ? s->gain_entry_cmd : s->gain_entry);
+        if (ret >= 0) {
+            av_freep(&s->gain_cmd);
+            s->gain_cmd = gain_cmd;
+        } else {
+            av_freep(&gain_cmd);
+        }
+    } else if (!strcmp(cmd, "gain_entry")) {
+        char *gain_entry_cmd;
+
+        gain_entry_cmd = av_strdup(args);
+        if (!gain_entry_cmd)
+            return AVERROR(ENOMEM);
+
+        ret = generate_kernel(ctx, s->gain_cmd ? s->gain_cmd : s->gain, gain_entry_cmd);
+        if (ret >= 0) {
+            av_freep(&s->gain_entry_cmd);
+            s->gain_entry_cmd = gain_entry_cmd;
+        } else {
+            av_freep(&gain_entry_cmd);
+        }
+    }
+
+    return ret;
+}
+
+static const AVFilterPad firequalizer_inputs[] = {
+    {
+        .name           = "default",
+        .config_props   = config_input,
+        .filter_frame   = filter_frame,
+        .type           = AVMEDIA_TYPE_AUDIO,
+        .needs_writable = 1,
+    },
+    { NULL }
+};
+
+static const AVFilterPad firequalizer_outputs[] = {
+    {
+        .name           = "default",
+        .request_frame  = request_frame,
+        .type           = AVMEDIA_TYPE_AUDIO,
+    },
+    { NULL }
+};
+
+AVFilter ff_af_firequalizer = {
+    .name               = "firequalizer",
+    .description        = NULL_IF_CONFIG_SMALL("Finite Impulse Response Equalizer."),
+    .uninit             = uninit,
+    .query_formats      = query_formats,
+    .process_command    = process_command,
+    .priv_size          = sizeof(FIREqualizerContext),
+    .inputs             = firequalizer_inputs,
+    .outputs            = firequalizer_outputs,
+    .priv_class         = &firequalizer_class,
+};
diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c
new file mode 100644
index 0000000..16bdcb0
--- /dev/null
+++ b/libavfilter/af_hdcd.c
@@ -0,0 +1,1149 @@
+/*
+   Copyright (C) 2010, Chris Moeller,
+   All rights reserved.
+   Optimizations by Gumboot
+   Redistribution and use in source and binary forms, with or without modification,
+   are permitted provided that the following conditions are met:
+     1. Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+     2. Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+     3. The names of its contributors may not be used to endorse or promote
+        products derived from this software without specific prior written
+        permission.
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+  Original code reverse engineered from HDCD decoder library by Christopher Key,
+  which was likely reverse engineered from Windows Media Player.
+*/
+
+/*
+  More information about high definition audio cds:
+  http://www.audiomisc.co.uk/HFN/HDCD/Enigma.html
+  http://www.audiomisc.co.uk/HFN/HDCD/Examined.html
+ */
+
+#include "libavutil/opt.h"
+#include "libavutil/avassert.h"
+#include "avfilter.h"
+#include "internal.h"
+#include "audio.h"
+
+static const uint32_t peaktab[] = {
+    0x2cc08300, 0x2cc10600, 0x2cc18900, 0x2cc20c00, 0x2cc28f00, 0x2cc31200, 0x2cc39500, 0x2cc41800, 0x2cc49b00, 0x2cc51e00, 0x2cc5a100, 0x2cc62400, 0x2cc6a700, 0x2cc72a00, 0x2cc7ad00, 0x2cc83000,
+    0x2cc8b300, 0x2cc93600, 0x2cc9b900, 0x2cca3c00, 0x2ccabf00, 0x2ccb4200, 0x2ccbc500, 0x2ccc4800, 0x2ccccb00, 0x2ccd4e00, 0x2ccdd100, 0x2cce5400, 0x2cced700, 0x2ccf5a00, 0x2ccfdd00, 0x2cd06000,
+    0x2cd0e300, 0x2cd16600, 0x2cd1e900, 0x2cd26c00, 0x2cd2ef00, 0x2cd37200, 0x2cd3f500, 0x2cd47800, 0x2cd4fb00, 0x2cd57e00, 0x2cd60100, 0x2cd68400, 0x2cd70700, 0x2cd78a00, 0x2cd80d00, 0x2cd89000,
+    0x2cd91300, 0x2cd99600, 0x2cda1900, 0x2cda9c00, 0x2cdb1f00, 0x2cdba200, 0x2cdc2500, 0x2cdca800, 0x2cdd2b00, 0x2cddae00, 0x2cde3100, 0x2cdeb400, 0x2cdf3700, 0x2cdfba00, 0x2ce03d00, 0x2ce0c000,
+    0x2ce14300, 0x2ce1c600, 0x2ce24900, 0x2ce2cc00, 0x2ce34f00, 0x2ce3d200, 0x2ce45500, 0x2ce4d800, 0x2ce55b00, 0x2ce5de00, 0x2ce66100, 0x2ce6e400, 0x2ce76700, 0x2ce7ea00, 0x2ce86d00, 0x2ce8f000,
+    0x2ce97300, 0x2ce9f600, 0x2cea7900, 0x2ceafc00, 0x2ceb7f00, 0x2cec0200, 0x2cec8500, 0x2ced0800, 0x2ced8b00, 0x2cee0e00, 0x2cee9100, 0x2cef1400, 0x2cef9700, 0x2cf01a00, 0x2cf09d00, 0x2cf12000,
+    0x2cf1a300, 0x2cf22600, 0x2cf2a900, 0x2cf32c00, 0x2cf3af00, 0x2cf43200, 0x2cf4b500, 0x2cf53800, 0x2cf5bb00, 0x2cf63e00, 0x2cf6c100, 0x2cf74400, 0x2cf7c700, 0x2cf84a00, 0x2cf8cd00, 0x2cf95000,
+    0x2cf9d300, 0x2cfa5600, 0x2cfad900, 0x2cfb5c00, 0x2cfbdf00, 0x2cfc6200, 0x2cfce500, 0x2cfd6800, 0x2cfdeb00, 0x2cfe6e00, 0x2cfef100, 0x2cff7400, 0x2cfff700, 0x2d007a00, 0x2d00fd00, 0x2d018000,
+    0x2d020300, 0x2d028600, 0x2d030900, 0x2d038c00, 0x2d040f00, 0x2d049200, 0x2d051500, 0x2d059800, 0x2d061b00, 0x2d069e00, 0x2d072100, 0x2d07a400, 0x2d082700, 0x2d08aa00, 0x2d092d00, 0x2d09b000,
+    0x2d0a3300, 0x2d0ab600, 0x2d0b3900, 0x2d0bbc00, 0x2d0c3f00, 0x2d0cc200, 0x2d0d4500, 0x2d0dc800, 0x2d0e4b00, 0x2d0ece00, 0x2d0f5100, 0x2d0fd400, 0x2d105700, 0x2d10da00, 0x2d115d00, 0x2d11e000,
+    0x2d126300, 0x2d12e600, 0x2d136900, 0x2d13ec00, 0x2d146f00, 0x2d14f200, 0x2d157500, 0x2d15f800, 0x2d167b00, 0x2d16fe00, 0x2d178100, 0x2d180400, 0x2d188700, 0x2d190a00, 0x2d198d00, 0x2d1a1000,
+    0x2d1a9300, 0x2d1b1600, 0x2d1b9900, 0x2d1c1c00, 0x2d1c9f00, 0x2d1d2200, 0x2d1da500, 0x2d1e2800, 0x2d1eab00, 0x2d1f2e00, 0x2d1fb100, 0x2d203400, 0x2d20b700, 0x2d213a00, 0x2d21bd00, 0x2d224000,
+    0x2d22c300, 0x2d234600, 0x2d23c900, 0x2d244c00, 0x2d24cf00, 0x2d255200, 0x2d25d500, 0x2d265800, 0x2d26db00, 0x2d275e00, 0x2d27e100, 0x2d286400, 0x2d28e700, 0x2d296a00, 0x2d29ed00, 0x2d2a7000,
+    0x2d2af300, 0x2d2b7600, 0x2d2bf900, 0x2d2c7c00, 0x2d2cff00, 0x2d2d8200, 0x2d2e0500, 0x2d2e8800, 0x2d2f0b00, 0x2d2f8e00, 0x2d301100, 0x2d309400, 0x2d311700, 0x2d319a00, 0x2d321d00, 0x2d32a000,
+    0x2d332300, 0x2d33a600, 0x2d342900, 0x2d34ac00, 0x2d352f00, 0x2d35b200, 0x2d363500, 0x2d36b800, 0x2d373b00, 0x2d37be00, 0x2d384100, 0x2d38c400, 0x2d394700, 0x2d39ca00, 0x2d3a4d00, 0x2d3ad000,
+    0x2d3b5300, 0x2d3bd600, 0x2d3c5900, 0x2d3cdc00, 0x2d3d5f00, 0x2d3de200, 0x2d3e6500, 0x2d3ee800, 0x2d3f6b00, 0x2d3fee00, 0x2d407100, 0x2d40f400, 0x2d417700, 0x2d41fa00, 0x2d427d00, 0x2d430000,
+    0x2d438300, 0x2d440600, 0x2d448900, 0x2d450c00, 0x2d458f00, 0x2d461200, 0x2d469500, 0x2d471800, 0x2d479b00, 0x2d481e00, 0x2d48a100, 0x2d492400, 0x2d49a700, 0x2d4a2a00, 0x2d4aad00, 0x2d4b3000,
+    0x2d4bb300, 0x2d4c3600, 0x2d4cb900, 0x2d4d3c00, 0x2d4dbf00, 0x2d4e4200, 0x2d4ec500, 0x2d4f4800, 0x2d4fcb00, 0x2d504e00, 0x2d50d100, 0x2d515400, 0x2d51d700, 0x2d525a00, 0x2d52dd00, 0x2d536000,
+    0x2d53e300, 0x2d546600, 0x2d54e900, 0x2d556c00, 0x2d55ef00, 0x2d567200, 0x2d56f500, 0x2d577800, 0x2d57fb00, 0x2d587e00, 0x2d590100, 0x2d598400, 0x2d5a0700, 0x2d5a8a00, 0x2d5b0d00, 0x2d5b9000,
+    0x2d5c1300, 0x2d5c9600, 0x2d5d1900, 0x2d5d9c00, 0x2d5e1f00, 0x2d5ea200, 0x2d5f2500, 0x2d5fa800, 0x2d602b00, 0x2d60ae00, 0x2d613100, 0x2d61b400, 0x2d623700, 0x2d62ba00, 0x2d633d00, 0x2d63c000,
+    0x2d644300, 0x2d64c600, 0x2d654900, 0x2d65cc00, 0x2d664f00, 0x2d66d200, 0x2d675500, 0x2d67d800, 0x2d685b00, 0x2d68de00, 0x2d696100, 0x2d69e400, 0x2d6a6700, 0x2d6aea00, 0x2d6b6d00, 0x2d6bf000,
+    0x2d6c7300, 0x2d6cf600, 0x2d6d7900, 0x2d6dfc00, 0x2d6e7f00, 0x2d6f0200, 0x2d6f8500, 0x2d700800, 0x2d708b00, 0x2d710e00, 0x2d719100, 0x2d721400, 0x2d729700, 0x2d731a00, 0x2d739d00, 0x2d742000,
+    0x2d74a300, 0x2d752600, 0x2d75a900, 0x2d762c00, 0x2d76af00, 0x2d773200, 0x2d77b500, 0x2d783800, 0x2d78bb00, 0x2d793e00, 0x2d79c100, 0x2d7a4400, 0x2d7ac700, 0x2d7b4a00, 0x2d7bcd00, 0x2d7c5000,
+    0x2d7cd300, 0x2d7d5600, 0x2d7dd900, 0x2d7e5c00, 0x2d7edf00, 0x2d7f6200, 0x2d7fe500, 0x2d806800, 0x2d80eb00, 0x2d816e00, 0x2d81f100, 0x2d827400, 0x2d82f700, 0x2d837a00, 0x2d83fd00, 0x2d848000,
+    0x2d850300, 0x2d858600, 0x2d860900, 0x2d868c00, 0x2d870f00, 0x2d879200, 0x2d881500, 0x2d889800, 0x2d891b00, 0x2d899e00, 0x2d8a2100, 0x2d8aa400, 0x2d8b2700, 0x2d8baa00, 0x2d8c2d00, 0x2d8cb000,
+    0x2d8d3300, 0x2d8db600, 0x2d8e3900, 0x2d8ebc00, 0x2d8f3f00, 0x2d8fc200, 0x2d904500, 0x2d90c800, 0x2d914b00, 0x2d91ce00, 0x2d925100, 0x2d92d400, 0x2d935700, 0x2d93da00, 0x2d945d00, 0x2d94e000,
+    0x2d956300, 0x2d95e600, 0x2d966900, 0x2d96ec00, 0x2d976f00, 0x2d97f200, 0x2d987500, 0x2d98f800, 0x2d997b00, 0x2d99fe00, 0x2d9a8100, 0x2d9b0400, 0x2d9b8700, 0x2d9c0a00, 0x2d9c8d00, 0x2d9d1000,
+    0x2d9d9300, 0x2d9e1600, 0x2d9e9900, 0x2d9f1c00, 0x2d9f9f00, 0x2da02200, 0x2da0a500, 0x2da12800, 0x2da1ab00, 0x2da22e00, 0x2da2b100, 0x2da33400, 0x2da3b700, 0x2da43a00, 0x2da4bd00, 0x2da54000,
+    0x2da5c300, 0x2da64600, 0x2da6c900, 0x2da74c00, 0x2da7cf00, 0x2da85200, 0x2da8d500, 0x2da95800, 0x2da9db00, 0x2daa5e00, 0x2daae100, 0x2dab6400, 0x2dabe700, 0x2dac6a00, 0x2daced00, 0x2dad7000,
+    0x2dadf300, 0x2dae7600, 0x2daef900, 0x2daf7c00, 0x2dafff00, 0x2db08200, 0x2db10500, 0x2db18800, 0x2db20b00, 0x2db28e00, 0x2db31100, 0x2db39400, 0x2db41700, 0x2db49a00, 0x2db51d00, 0x2db5a000,
+    0x2db62300, 0x2db6a600, 0x2db72900, 0x2db7ac00, 0x2db82f00, 0x2db8b200, 0x2db93500, 0x2db9b800, 0x2dba3b00, 0x2dbabe00, 0x2dbb4100, 0x2dbbc400, 0x2dbc4700, 0x2dbcca00, 0x2dbd4d00, 0x2dbdd000,
+    0x2dbe5300, 0x2dbed600, 0x2dbf5900, 0x2dbfdc00, 0x2dc05f00, 0x2dc0e200, 0x2dc16500, 0x2dc1e800, 0x2dc26b00, 0x2dc2ee00, 0x2dc37100, 0x2dc3f400, 0x2dc47700, 0x2dc4fa00, 0x2dc57d00, 0x2dc60000,
+    0x2dc68700, 0x2dc70e00, 0x2dc79500, 0x2dc81c00, 0x2dc8a300, 0x2dc92a00, 0x2dc9b100, 0x2dca3800, 0x2dcabf00, 0x2dcb4600, 0x2dcbcd00, 0x2dcc5400, 0x2dccdb00, 0x2dcd6200, 0x2dcde900, 0x2dce7000,
+    0x2dcef700, 0x2dcf7e00, 0x2dd00500, 0x2dd08c00, 0x2dd11300, 0x2dd19a00, 0x2dd22100, 0x2dd2a800, 0x2dd32f00, 0x2dd3b600, 0x2dd43d00, 0x2dd4c400, 0x2dd54b00, 0x2dd5d200, 0x2dd65900, 0x2dd6e000,
+    0x2dd76700, 0x2dd7ee00, 0x2dd87500, 0x2dd8fc00, 0x2dd98300, 0x2dda0a00, 0x2dda9100, 0x2ddb1800, 0x2ddb9f00, 0x2ddc2600, 0x2ddcad00, 0x2ddd3400, 0x2dddbb00, 0x2dde4200, 0x2ddec900, 0x2ddf5000,
+    0x2ddfd700, 0x2de05e00, 0x2de0e500, 0x2de16c00, 0x2de1f300, 0x2de27a00, 0x2de30100, 0x2de38800, 0x2de40f00, 0x2de49600, 0x2de51d00, 0x2de5a400, 0x2de62b00, 0x2de6b200, 0x2de73900, 0x2de7c000,
+    0x2de84700, 0x2de8ce00, 0x2de95500, 0x2de9dc00, 0x2dea6300, 0x2deaea00, 0x2deb7100, 0x2debf800, 0x2dec7f00, 0x2ded0600, 0x2ded8d00, 0x2dee1400, 0x2dee9b00, 0x2def2200, 0x2defa900, 0x2df03000,
+    0x2df0b700, 0x2df13e00, 0x2df1c500, 0x2df24c00, 0x2df2d300, 0x2df35a00, 0x2df3e100, 0x2df46800, 0x2df4ef00, 0x2df57600, 0x2df5fd00, 0x2df68400, 0x2df70b00, 0x2df79200, 0x2df81900, 0x2df8a000,
+    0x2df92700, 0x2df9ae00, 0x2dfa3500, 0x2dfabc00, 0x2dfb4300, 0x2dfbca00, 0x2dfc5100, 0x2dfcd800, 0x2dfd5f00, 0x2dfde600, 0x2dfe6d00, 0x2dfef400, 0x2dff7b00, 0x2e000200, 0x2e008900, 0x2e011000,
+    0x2e019700, 0x2e021e00, 0x2e02a500, 0x2e032c00, 0x2e03b300, 0x2e043a00, 0x2e04c100, 0x2e054800, 0x2e05cf00, 0x2e065600, 0x2e06dd00, 0x2e076400, 0x2e07eb00, 0x2e087200, 0x2e08f900, 0x2e098000,
+    0x2e0a0700, 0x2e0a8e00, 0x2e0b1500, 0x2e0b9c00, 0x2e0c2300, 0x2e0caa00, 0x2e0d3100, 0x2e0db800, 0x2e0e3f00, 0x2e0ec600, 0x2e0f4d00, 0x2e0fd400, 0x2e105b00, 0x2e10e200, 0x2e116900, 0x2e11f000,
+    0x2e127700, 0x2e12fe00, 0x2e138500, 0x2e140c00, 0x2e149300, 0x2e151a00, 0x2e15a100, 0x2e162800, 0x2e16af00, 0x2e173600, 0x2e17bd00, 0x2e184400, 0x2e18cb00, 0x2e195200, 0x2e19d900, 0x2e1a6000,
+    0x2e1ae700, 0x2e1b6e00, 0x2e1bf500, 0x2e1c7c00, 0x2e1d0300, 0x2e1d8a00, 0x2e1e1100, 0x2e1e9800, 0x2e1f1f00, 0x2e1fa600, 0x2e202d00, 0x2e20b400, 0x2e213b00, 0x2e21c200, 0x2e224900, 0x2e22d000,
+    0x2e235700, 0x2e23de00, 0x2e246500, 0x2e24ec00, 0x2e257300, 0x2e25fa00, 0x2e268100, 0x2e270800, 0x2e278f00, 0x2e281600, 0x2e289d00, 0x2e292400, 0x2e29ab00, 0x2e2a3200, 0x2e2ab900, 0x2e2b4000,
+    0x2e2bc700, 0x2e2c4e00, 0x2e2cd500, 0x2e2d5c00, 0x2e2de300, 0x2e2e6a00, 0x2e2ef100, 0x2e2f7800, 0x2e2fff00, 0x2e308600, 0x2e310d00, 0x2e319400, 0x2e321b00, 0x2e32a200, 0x2e332900, 0x2e33b000,
+    0x2e343700, 0x2e34be00, 0x2e354500, 0x2e35cc00, 0x2e365300, 0x2e36da00, 0x2e376100, 0x2e37e800, 0x2e386f00, 0x2e38f600, 0x2e397d00, 0x2e3a0400, 0x2e3a8b00, 0x2e3b1200, 0x2e3b9900, 0x2e3c2000,
+    0x2e3ca700, 0x2e3d2e00, 0x2e3db500, 0x2e3e3c00, 0x2e3ec300, 0x2e3f4a00, 0x2e3fd100, 0x2e405800, 0x2e40df00, 0x2e416600, 0x2e41ed00, 0x2e427400, 0x2e42fb00, 0x2e438200, 0x2e440900, 0x2e449000,
+    0x2e451700, 0x2e459e00, 0x2e462500, 0x2e46ac00, 0x2e473300, 0x2e47ba00, 0x2e484100, 0x2e48c800, 0x2e494f00, 0x2e49d600, 0x2e4a5d00, 0x2e4ae400, 0x2e4b6b00, 0x2e4bf200, 0x2e4c7900, 0x2e4d0000,
+    0x2e4d8700, 0x2e4e0e00, 0x2e4e9500, 0x2e4f1c00, 0x2e4fa300, 0x2e502a00, 0x2e50b100, 0x2e513800, 0x2e51bf00, 0x2e524600, 0x2e52cd00, 0x2e535400, 0x2e53db00, 0x2e546200, 0x2e54e900, 0x2e557000,
+    0x2e55f700, 0x2e567e00, 0x2e570500, 0x2e578c00, 0x2e581300, 0x2e589a00, 0x2e592100, 0x2e59a800, 0x2e5a2f00, 0x2e5ab600, 0x2e5b3d00, 0x2e5bc400, 0x2e5c4b00, 0x2e5cd200, 0x2e5d5900, 0x2e5de000,
+    0x2e5e6700, 0x2e5eee00, 0x2e5f7500, 0x2e5ffc00, 0x2e608300, 0x2e610a00, 0x2e619100, 0x2e621800, 0x2e629f00, 0x2e632600, 0x2e63ad00, 0x2e643400, 0x2e64bb00, 0x2e654200, 0x2e65c900, 0x2e665000,
+    0x2e66d700, 0x2e675e00, 0x2e67e500, 0x2e686c00, 0x2e68f300, 0x2e697a00, 0x2e6a0100, 0x2e6a8800, 0x2e6b0f00, 0x2e6b9600, 0x2e6c1d00, 0x2e6ca400, 0x2e6d2b00, 0x2e6db200, 0x2e6e3900, 0x2e6ec000,
+    0x2e6f4700, 0x2e6fce00, 0x2e705500, 0x2e70dc00, 0x2e716300, 0x2e71ea00, 0x2e727100, 0x2e72f800, 0x2e737f00, 0x2e740600, 0x2e748d00, 0x2e751400, 0x2e759b00, 0x2e762200, 0x2e76a900, 0x2e773000,
+    0x2e77b700, 0x2e783e00, 0x2e78c500, 0x2e794c00, 0x2e79d300, 0x2e7a5a00, 0x2e7ae100, 0x2e7b6800, 0x2e7bef00, 0x2e7c7600, 0x2e7cfd00, 0x2e7d8400, 0x2e7e0b00, 0x2e7e9200, 0x2e7f1900, 0x2e7fa000,
+    0x2e802700, 0x2e80ae00, 0x2e813500, 0x2e81bc00, 0x2e824300, 0x2e82ca00, 0x2e835100, 0x2e83d800, 0x2e845f00, 0x2e84e600, 0x2e856d00, 0x2e85f400, 0x2e867b00, 0x2e870200, 0x2e878900, 0x2e881000,
+    0x2e889700, 0x2e891e00, 0x2e89a500, 0x2e8a2c00, 0x2e8ab300, 0x2e8b3a00, 0x2e8bc100, 0x2e8c4800, 0x2e8ccf00, 0x2e8d5600, 0x2e8ddd00, 0x2e8e6400, 0x2e8eeb00, 0x2e8f7200, 0x2e8ff900, 0x2e908000,
+    0x2e910700, 0x2e918e00, 0x2e921500, 0x2e929c00, 0x2e932300, 0x2e93aa00, 0x2e943100, 0x2e94b800, 0x2e953f00, 0x2e95c600, 0x2e964d00, 0x2e96d400, 0x2e975b00, 0x2e97e200, 0x2e986900, 0x2e98f000,
+    0x2e997700, 0x2e99fe00, 0x2e9a8500, 0x2e9b0c00, 0x2e9b9300, 0x2e9c1a00, 0x2e9ca100, 0x2e9d2800, 0x2e9daf00, 0x2e9e3600, 0x2e9ebd00, 0x2e9f4400, 0x2e9fcb00, 0x2ea05200, 0x2ea0d900, 0x2ea16000,
+    0x2ea1e700, 0x2ea26e00, 0x2ea2f500, 0x2ea37c00, 0x2ea40300, 0x2ea48a00, 0x2ea51100, 0x2ea59800, 0x2ea61f00, 0x2ea6a600, 0x2ea72d00, 0x2ea7b400, 0x2ea83b00, 0x2ea8c200, 0x2ea94900, 0x2ea9d000,
+    0x2eaa5700, 0x2eaade00, 0x2eab6500, 0x2eabec00, 0x2eac7300, 0x2eacfa00, 0x2ead8100, 0x2eae0800, 0x2eae8f00, 0x2eaf1600, 0x2eaf9d00, 0x2eb02400, 0x2eb0ab00, 0x2eb13200, 0x2eb1b900, 0x2eb24000,
+    0x2eb2c700, 0x2eb34e00, 0x2eb3d500, 0x2eb45c00, 0x2eb4e300, 0x2eb56a00, 0x2eb5f100, 0x2eb67800, 0x2eb6ff00, 0x2eb78600, 0x2eb80d00, 0x2eb89400, 0x2eb91b00, 0x2eb9a200, 0x2eba2900, 0x2ebab000,
+    0x2ebb3700, 0x2ebbbe00, 0x2ebc4500, 0x2ebccc00, 0x2ebd5300, 0x2ebdda00, 0x2ebe6100, 0x2ebee800, 0x2ebf6f00, 0x2ebff600, 0x2ec07d00, 0x2ec10400, 0x2ec18b00, 0x2ec21200, 0x2ec29900, 0x2ec32000,
+    0x2ec3a700, 0x2ec42e00, 0x2ec4b500, 0x2ec53c00, 0x2ec5c300, 0x2ec64a00, 0x2ec6d100, 0x2ec75800, 0x2ec7df00, 0x2ec86600, 0x2ec8ed00, 0x2ec97400, 0x2ec9fb00, 0x2eca8200, 0x2ecb0900, 0x2ecb9000,
+    0x2ecc1700, 0x2ecc9e00, 0x2ecd2500, 0x2ecdac00, 0x2ece3300, 0x2eceba00, 0x2ecf4100, 0x2ecfc800, 0x2ed04f00, 0x2ed0d600, 0x2ed15d00, 0x2ed1e400, 0x2ed26b00, 0x2ed2f200, 0x2ed37900, 0x2ed40000,
+    0x2ed48700, 0x2ed50e00, 0x2ed59500, 0x2ed61c00, 0x2ed6a300, 0x2ed72a00, 0x2ed7b100, 0x2ed83800, 0x2ed8bf00, 0x2ed94600, 0x2ed9cd00, 0x2eda5400, 0x2edadb00, 0x2edb6200, 0x2edbe900, 0x2edc7000,
+    0x2edcf700, 0x2edd7e00, 0x2ede0500, 0x2ede8c00, 0x2edf1300, 0x2edf9a00, 0x2ee02100, 0x2ee0a800, 0x2ee12f00, 0x2ee1b600, 0x2ee23d00, 0x2ee2c400, 0x2ee34b00, 0x2ee3d200, 0x2ee45900, 0x2ee4e000,
+    0x2ee56700, 0x2ee5ee00, 0x2ee67500, 0x2ee6fc00, 0x2ee78300, 0x2ee80a00, 0x2ee89100, 0x2ee91800, 0x2ee99f00, 0x2eea2600, 0x2eeaad00, 0x2eeb3400, 0x2eebbb00, 0x2eec4200, 0x2eecc900, 0x2eed5000,
+    0x2eedd700, 0x2eee5e00, 0x2eeee500, 0x2eef6c00, 0x2eeff300, 0x2ef07a00, 0x2ef10100, 0x2ef18800, 0x2ef20f00, 0x2ef29600, 0x2ef31d00, 0x2ef3a400, 0x2ef42b00, 0x2ef4b200, 0x2ef53900, 0x2ef5c000,
+    0x2ef64700, 0x2ef6ce00, 0x2ef75500, 0x2ef7dc00, 0x2ef86300, 0x2ef8ea00, 0x2ef97100, 0x2ef9f800, 0x2efa7f00, 0x2efb0600, 0x2efb8d00, 0x2efc1400, 0x2efc9b00, 0x2efd2200, 0x2efda900, 0x2efe3000,
+    0x2efeb700, 0x2eff3e00, 0x2effc500, 0x2f004c00, 0x2f00d300, 0x2f015a00, 0x2f01e100, 0x2f026800, 0x2f02ef00, 0x2f037600, 0x2f03fd00, 0x2f048400, 0x2f050b00, 0x2f059200, 0x2f061900, 0x2f06a000,
+    0x2f072700, 0x2f07ae00, 0x2f083500, 0x2f08bc00, 0x2f094300, 0x2f09ca00, 0x2f0a5100, 0x2f0ad800, 0x2f0b5f00, 0x2f0be600, 0x2f0c6d00, 0x2f0cf400, 0x2f0d7b00, 0x2f0e0200, 0x2f0e8900, 0x2f0f1000,
+    0x2f0f9700, 0x2f101e00, 0x2f10a500, 0x2f112c00, 0x2f11b300, 0x2f123a00, 0x2f12c100, 0x2f134800, 0x2f13cf00, 0x2f145600, 0x2f14dd00, 0x2f156400, 0x2f15eb00, 0x2f167200, 0x2f16f900, 0x2f178000,
+    0x2f180700, 0x2f188e00, 0x2f191500, 0x2f199c00, 0x2f1a2300, 0x2f1aaa00, 0x2f1b3100, 0x2f1bb800, 0x2f1c3f00, 0x2f1cc600, 0x2f1d4d00, 0x2f1dd400, 0x2f1e5b00, 0x2f1ee200, 0x2f1f6900, 0x2f1ff000,
+    0x2f207700, 0x2f20fe00, 0x2f218500, 0x2f220c00, 0x2f229300, 0x2f231a00, 0x2f23a100, 0x2f242800, 0x2f24af00, 0x2f253600, 0x2f25bd00, 0x2f264400, 0x2f26cb00, 0x2f275200, 0x2f27d900, 0x2f286000,
+    0x2f28e700, 0x2f296e00, 0x2f29f500, 0x2f2a7c00, 0x2f2b0300, 0x2f2b8a00, 0x2f2c1100, 0x2f2c9800, 0x2f2d1f00, 0x2f2da600, 0x2f2e2d00, 0x2f2eb400, 0x2f2f3b00, 0x2f2fc200, 0x2f304900, 0x2f30d000,
+    0x2f315700, 0x2f31de00, 0x2f326500, 0x2f32ec00, 0x2f337300, 0x2f33fa00, 0x2f348100, 0x2f350800, 0x2f358f00, 0x2f361600, 0x2f369d00, 0x2f372400, 0x2f37ab00, 0x2f383200, 0x2f38b900, 0x2f394000,
+    0x2f39c700, 0x2f3a4e00, 0x2f3ad500, 0x2f3b5c00, 0x2f3be300, 0x2f3c6a00, 0x2f3cf100, 0x2f3d7800, 0x2f3dff00, 0x2f3e8600, 0x2f3f0d00, 0x2f3f9400, 0x2f401b00, 0x2f40a200, 0x2f412900, 0x2f41b000,
+    0x2f423700, 0x2f42be00, 0x2f434500, 0x2f43cc00, 0x2f445300, 0x2f44da00, 0x2f456100, 0x2f45e800, 0x2f466f00, 0x2f46f600, 0x2f477d00, 0x2f480400, 0x2f488b00, 0x2f491200, 0x2f499900, 0x2f4a2000,
+    0x2f4aa700, 0x2f4b2e00, 0x2f4bb500, 0x2f4c3c00, 0x2f4cc300, 0x2f4d4a00, 0x2f4dd100, 0x2f4e5800, 0x2f4edf00, 0x2f4f6600, 0x2f4fed00, 0x2f507400, 0x2f50fb00, 0x2f518200, 0x2f520900, 0x2f529000,
+    0x2f531700, 0x2f539e00, 0x2f542500, 0x2f54ac00, 0x2f553300, 0x2f55ba00, 0x2f564100, 0x2f56c800, 0x2f574f00, 0x2f57d600, 0x2f585d00, 0x2f58e400, 0x2f596b00, 0x2f59f200, 0x2f5a7900, 0x2f5b0000,
+    0x2f5b8700, 0x2f5c0e00, 0x2f5c9500, 0x2f5d1c00, 0x2f5da300, 0x2f5e2a00, 0x2f5eb100, 0x2f5f3800, 0x2f5fbf00, 0x2f604600, 0x2f60cd00, 0x2f615400, 0x2f61db00, 0x2f626200, 0x2f62e900, 0x2f637000,
+    0x2f63f700, 0x2f647e00, 0x2f650500, 0x2f658c00, 0x2f661300, 0x2f669a00, 0x2f672100, 0x2f67a800, 0x2f682f00, 0x2f68b600, 0x2f693d00, 0x2f69c400, 0x2f6a4b00, 0x2f6ad200, 0x2f6b5900, 0x2f6be000,
+    0x2f6c6700, 0x2f6cee00, 0x2f6d7500, 0x2f6dfc00, 0x2f6e8300, 0x2f6f0a00, 0x2f6f9100, 0x2f701800, 0x2f709f00, 0x2f712600, 0x2f71ad00, 0x2f723400, 0x2f72bb00, 0x2f734200, 0x2f73c900, 0x2f745000,
+    0x2f74d700, 0x2f755e00, 0x2f75e500, 0x2f766c00, 0x2f76f300, 0x2f777a00, 0x2f780100, 0x2f788800, 0x2f790f00, 0x2f799600, 0x2f7a1d00, 0x2f7aa400, 0x2f7b2b00, 0x2f7bb200, 0x2f7c3900, 0x2f7cc000,
+    0x2f7d4700, 0x2f7dce00, 0x2f7e5500, 0x2f7edc00, 0x2f7f6300, 0x2f7fea00, 0x2f807100, 0x2f80f800, 0x2f817f00, 0x2f820600, 0x2f828d00, 0x2f831400, 0x2f839b00, 0x2f842200, 0x2f84a900, 0x2f853000,
+    0x2f85b700, 0x2f863e00, 0x2f86c500, 0x2f874c00, 0x2f87d300, 0x2f885a00, 0x2f88e100, 0x2f896800, 0x2f89ef00, 0x2f8a7600, 0x2f8afd00, 0x2f8b8400, 0x2f8c0b00, 0x2f8c9200, 0x2f8d1900, 0x2f8da000,
+    0x2f8e2700, 0x2f8eae00, 0x2f8f3500, 0x2f8fbc00, 0x2f904300, 0x2f90ca00, 0x2f915100, 0x2f91d800, 0x2f925f00, 0x2f92e600, 0x2f936d00, 0x2f93f400, 0x2f947b00, 0x2f950200, 0x2f958900, 0x2f961000,
+    0x2f969700, 0x2f971e00, 0x2f97a500, 0x2f982c00, 0x2f98b300, 0x2f993a00, 0x2f99c100, 0x2f9a4800, 0x2f9acf00, 0x2f9b5600, 0x2f9bdd00, 0x2f9c6400, 0x2f9ceb00, 0x2f9d7200, 0x2f9df900, 0x2f9e8000,
+    0x2f9f0700, 0x2f9f8e00, 0x2fa01500, 0x2fa09c00, 0x2fa12300, 0x2fa1aa00, 0x2fa23100, 0x2fa2b800, 0x2fa33f00, 0x2fa3c600, 0x2fa44d00, 0x2fa4d400, 0x2fa55b00, 0x2fa5e200, 0x2fa66900, 0x2fa6f000,
+    0x2fa77700, 0x2fa7fe00, 0x2fa88500, 0x2fa90c00, 0x2fa99300, 0x2faa1a00, 0x2faaa100, 0x2fab2800, 0x2fabaf00, 0x2fac3600, 0x2facbd00, 0x2fad4400, 0x2fadcb00, 0x2fae5200, 0x2faed900, 0x2faf6000,
+    0x2fafe700, 0x2fb06e00, 0x2fb0f500, 0x2fb17c00, 0x2fb20300, 0x2fb28a00, 0x2fb31100, 0x2fb39800, 0x2fb41f00, 0x2fb4a600, 0x2fb52d00, 0x2fb5b400, 0x2fb63b00, 0x2fb6c200, 0x2fb74900, 0x2fb7d000,
+    0x2fb85700, 0x2fb8de00, 0x2fb96500, 0x2fb9ec00, 0x2fba7300, 0x2fbafa00, 0x2fbb8100, 0x2fbc0800, 0x2fbc8f00, 0x2fbd1600, 0x2fbd9d00, 0x2fbe2400, 0x2fbeab00, 0x2fbf3200, 0x2fbfb900, 0x2fc04000,
+    0x2fc0c700, 0x2fc14e00, 0x2fc1d500, 0x2fc25c00, 0x2fc2e300, 0x2fc36a00, 0x2fc3f100, 0x2fc47800, 0x2fc4ff00, 0x2fc58600, 0x2fc60d00, 0x2fc69400, 0x2fc71b00, 0x2fc7a200, 0x2fc82900, 0x2fc8b000,
+    0x2fc93700, 0x2fc9be00, 0x2fca4500, 0x2fcacc00, 0x2fcb5300, 0x2fcbda00, 0x2fcc6100, 0x2fcce800, 0x2fcd6f00, 0x2fcdf600, 0x2fce7d00, 0x2fcf0400, 0x2fcf8b00, 0x2fd01200, 0x2fd09900, 0x2fd12000,
+    0x2fd1a700, 0x2fd22e00, 0x2fd2b500, 0x2fd33c00, 0x2fd3c300, 0x2fd44a00, 0x2fd4d100, 0x2fd55800, 0x2fd5df00, 0x2fd66600, 0x2fd6ed00, 0x2fd77400, 0x2fd7fb00, 0x2fd88200, 0x2fd90900, 0x2fd99000,
+    0x2fda1700, 0x2fda9e00, 0x2fdb2500, 0x2fdbac00, 0x2fdc3300, 0x2fdcba00, 0x2fdd4100, 0x2fddc800, 0x2fde4f00, 0x2fded600, 0x2fdf5d00, 0x2fdfe400, 0x2fe06b00, 0x2fe0f200, 0x2fe17900, 0x2fe20000,
+    0x2fe29600, 0x2fe32c00, 0x2fe3c200, 0x2fe45800, 0x2fe4ee00, 0x2fe58400, 0x2fe61a00, 0x2fe6b000, 0x2fe74600, 0x2fe7dc00, 0x2fe87200, 0x2fe90800, 0x2fe99e00, 0x2fea3400, 0x2feaca00, 0x2feb6000,
+    0x2febf600, 0x2fec8c00, 0x2fed2200, 0x2fedb800, 0x2fee4e00, 0x2feee400, 0x2fef7a00, 0x2ff01000, 0x2ff0a600, 0x2ff13c00, 0x2ff1d200, 0x2ff26800, 0x2ff2fe00, 0x2ff39400, 0x2ff42a00, 0x2ff4c000,
+    0x2ff55600, 0x2ff5ec00, 0x2ff68200, 0x2ff71800, 0x2ff7ae00, 0x2ff84400, 0x2ff8da00, 0x2ff97000, 0x2ffa0600, 0x2ffa9c00, 0x2ffb3200, 0x2ffbc800, 0x2ffc5e00, 0x2ffcf400, 0x2ffd8a00, 0x2ffe2000,
+    0x2ffeb600, 0x2fff4c00, 0x2fffe200, 0x30007800, 0x30010e00, 0x3001a400, 0x30023a00, 0x3002d000, 0x30036600, 0x3003fc00, 0x30049200, 0x30052800, 0x3005be00, 0x30065400, 0x3006ea00, 0x30078000,
+    0x30081600, 0x3008ac00, 0x30094200, 0x3009d800, 0x300a6e00, 0x300b0400, 0x300b9a00, 0x300c3000, 0x300cc600, 0x300d5c00, 0x300df200, 0x300e8800, 0x300f1e00, 0x300fb400, 0x30104a00, 0x3010e000,
+    0x30117600, 0x30120c00, 0x3012a200, 0x30133800, 0x3013ce00, 0x30146400, 0x3014fa00, 0x30159000, 0x30162600, 0x3016bc00, 0x30175200, 0x3017e800, 0x30187e00, 0x30191400, 0x3019aa00, 0x301a4000,
+    0x301ad600, 0x301b6c00, 0x301c0200, 0x301c9800, 0x301d2e00, 0x301dc400, 0x301e5a00, 0x301ef000, 0x301f8600, 0x30201c00, 0x3020b200, 0x30214800, 0x3021de00, 0x30227400, 0x30230a00, 0x3023a000,
+    0x30243600, 0x3024cc00, 0x30256200, 0x3025f800, 0x30268e00, 0x30272400, 0x3027ba00, 0x30285000, 0x3028e600, 0x30297c00, 0x302a1200, 0x302aa800, 0x302b3e00, 0x302bd400, 0x302c6a00, 0x302d0000,
+    0x302d9600, 0x302e2c00, 0x302ec200, 0x302f5800, 0x302fee00, 0x30308400, 0x30311a00, 0x3031b000, 0x30324600, 0x3032dc00, 0x30337200, 0x30340800, 0x30349e00, 0x30353400, 0x3035ca00, 0x30366000,
+    0x3036f600, 0x30378c00, 0x30382200, 0x3038b800, 0x30394e00, 0x3039e400, 0x303a7a00, 0x303b1000, 0x303ba600, 0x303c3c00, 0x303cd200, 0x303d6800, 0x303dfe00, 0x303e9400, 0x303f2a00, 0x303fc000,
+    0x30405600, 0x3040ec00, 0x30418200, 0x30421800, 0x3042ae00, 0x30434400, 0x3043da00, 0x30447000, 0x30450600, 0x30459c00, 0x30463200, 0x3046c800, 0x30475e00, 0x3047f400, 0x30488a00, 0x30492000,
+    0x3049b600, 0x304a4c00, 0x304ae200, 0x304b7800, 0x304c0e00, 0x304ca400, 0x304d3a00, 0x304dd000, 0x304e6600, 0x304efc00, 0x304f9200, 0x30502800, 0x3050be00, 0x30515400, 0x3051ea00, 0x30528000,
+    0x30531600, 0x3053ac00, 0x30544200, 0x3054d800, 0x30556e00, 0x30560400, 0x30569a00, 0x30573000, 0x3057c600, 0x30585c00, 0x3058f200, 0x30598800, 0x305a1e00, 0x305ab400, 0x305b4a00, 0x305be000,
+    0x305c7600, 0x305d0c00, 0x305da200, 0x305e3800, 0x305ece00, 0x305f6400, 0x305ffa00, 0x30609000, 0x30612600, 0x3061bc00, 0x30625200, 0x3062e800, 0x30637e00, 0x30641400, 0x3064aa00, 0x30654000,
+    0x3065d600, 0x30666c00, 0x30670200, 0x30679800, 0x30682e00, 0x3068c400, 0x30695a00, 0x3069f000, 0x306a8600, 0x306b1c00, 0x306bb200, 0x306c4800, 0x306cde00, 0x306d7400, 0x306e0a00, 0x306ea000,
+    0x306f3600, 0x306fcc00, 0x30706200, 0x3070f800, 0x30718e00, 0x30722400, 0x3072ba00, 0x30735000, 0x3073e600, 0x30747c00, 0x30751200, 0x3075a800, 0x30763e00, 0x3076d400, 0x30776a00, 0x30780000,
+    0x30789600, 0x30792c00, 0x3079c200, 0x307a5800, 0x307aee00, 0x307b8400, 0x307c1a00, 0x307cb000, 0x307d4600, 0x307ddc00, 0x307e7200, 0x307f0800, 0x307f9e00, 0x30803400, 0x3080ca00, 0x30816000,
+    0x3081f600, 0x30828c00, 0x30832200, 0x3083b800, 0x30844e00, 0x3084e400, 0x30857a00, 0x30861000, 0x3086a600, 0x30873c00, 0x3087d200, 0x30886800, 0x3088fe00, 0x30899400, 0x308a2a00, 0x308ac000,
+    0x308b5600, 0x308bec00, 0x308c8200, 0x308d1800, 0x308dae00, 0x308e4400, 0x308eda00, 0x308f7000, 0x30900600, 0x30909c00, 0x30913200, 0x3091c800, 0x30925e00, 0x3092f400, 0x30938a00, 0x30942000,
+    0x3094b600, 0x30954c00, 0x3095e200, 0x30967800, 0x30970e00, 0x3097a400, 0x30983a00, 0x3098d000, 0x30996600, 0x3099fc00, 0x309a9200, 0x309b2800, 0x309bbe00, 0x309c5400, 0x309cea00, 0x309d8000,
+    0x309e1600, 0x309eac00, 0x309f4200, 0x309fd800, 0x30a06e00, 0x30a10400, 0x30a19a00, 0x30a23000, 0x30a2c600, 0x30a35c00, 0x30a3f200, 0x30a48800, 0x30a51e00, 0x30a5b400, 0x30a64a00, 0x30a6e000,
+    0x30a77600, 0x30a80c00, 0x30a8a200, 0x30a93800, 0x30a9ce00, 0x30aa6400, 0x30aafa00, 0x30ab9000, 0x30ac2600, 0x30acbc00, 0x30ad5200, 0x30ade800, 0x30ae7e00, 0x30af1400, 0x30afaa00, 0x30b04000,
+    0x30b0d600, 0x30b16c00, 0x30b20200, 0x30b29800, 0x30b32e00, 0x30b3c400, 0x30b45a00, 0x30b4f000, 0x30b58600, 0x30b61c00, 0x30b6b200, 0x30b74800, 0x30b7de00, 0x30b87400, 0x30b90a00, 0x30b9a000,
+    0x30ba3600, 0x30bacc00, 0x30bb6200, 0x30bbf800, 0x30bc8e00, 0x30bd2400, 0x30bdba00, 0x30be5000, 0x30bee600, 0x30bf7c00, 0x30c01200, 0x30c0a800, 0x30c13e00, 0x30c1d400, 0x30c26a00, 0x30c30000,
+    0x30c39600, 0x30c42c00, 0x30c4c200, 0x30c55800, 0x30c5ee00, 0x30c68400, 0x30c71a00, 0x30c7b000, 0x30c84600, 0x30c8dc00, 0x30c97200, 0x30ca0800, 0x30ca9e00, 0x30cb3400, 0x30cbca00, 0x30cc6000,
+    0x30ccf600, 0x30cd8c00, 0x30ce2200, 0x30ceb800, 0x30cf4e00, 0x30cfe400, 0x30d07a00, 0x30d11000, 0x30d1a600, 0x30d23c00, 0x30d2d200, 0x30d36800, 0x30d3fe00, 0x30d49400, 0x30d52a00, 0x30d5c000,
+    0x30d65600, 0x30d6ec00, 0x30d78200, 0x30d81800, 0x30d8ae00, 0x30d94400, 0x30d9da00, 0x30da7000, 0x30db0600, 0x30db9c00, 0x30dc3200, 0x30dcc800, 0x30dd5e00, 0x30ddf400, 0x30de8a00, 0x30df2000,
+    0x30dfb600, 0x30e04c00, 0x30e0e200, 0x30e17800, 0x30e20e00, 0x30e2a400, 0x30e33a00, 0x30e3d000, 0x30e46600, 0x30e4fc00, 0x30e59200, 0x30e62800, 0x30e6be00, 0x30e75400, 0x30e7ea00, 0x30e88000,
+    0x30e91600, 0x30e9ac00, 0x30ea4200, 0x30ead800, 0x30eb6e00, 0x30ec0400, 0x30ec9a00, 0x30ed3000, 0x30edc600, 0x30ee5c00, 0x30eef200, 0x30ef8800, 0x30f01e00, 0x30f0b400, 0x30f14a00, 0x30f1e000,
+    0x30f27600, 0x30f30c00, 0x30f3a200, 0x30f43800, 0x30f4ce00, 0x30f56400, 0x30f5fa00, 0x30f69000, 0x30f72600, 0x30f7bc00, 0x30f85200, 0x30f8e800, 0x30f97e00, 0x30fa1400, 0x30faaa00, 0x30fb4000,
+    0x30fbd600, 0x30fc6c00, 0x30fd0200, 0x30fd9800, 0x30fe2e00, 0x30fec400, 0x30ff5a00, 0x30fff000, 0x31008600, 0x31011c00, 0x3101b200, 0x31024800, 0x3102de00, 0x31037400, 0x31040a00, 0x3104a000,
+    0x31053600, 0x3105cc00, 0x31066200, 0x3106f800, 0x31078e00, 0x31082400, 0x3108ba00, 0x31095000, 0x3109e600, 0x310a7c00, 0x310b1200, 0x310ba800, 0x310c3e00, 0x310cd400, 0x310d6a00, 0x310e0000,
+    0x310e9600, 0x310f2c00, 0x310fc200, 0x31105800, 0x3110ee00, 0x31118400, 0x31121a00, 0x3112b000, 0x31134600, 0x3113dc00, 0x31147200, 0x31150800, 0x31159e00, 0x31163400, 0x3116ca00, 0x31176000,
+    0x3117f600, 0x31188c00, 0x31192200, 0x3119b800, 0x311a4e00, 0x311ae400, 0x311b7a00, 0x311c1000, 0x311ca600, 0x311d3c00, 0x311dd200, 0x311e6800, 0x311efe00, 0x311f9400, 0x31202a00, 0x3120c000,
+    0x31215600, 0x3121ec00, 0x31228200, 0x31231800, 0x3123ae00, 0x31244400, 0x3124da00, 0x31257000, 0x31260600, 0x31269c00, 0x31273200, 0x3127c800, 0x31285e00, 0x3128f400, 0x31298a00, 0x312a2000,
+    0x312ab600, 0x312b4c00, 0x312be200, 0x312c7800, 0x312d0e00, 0x312da400, 0x312e3a00, 0x312ed000, 0x312f6600, 0x312ffc00, 0x31309200, 0x31312800, 0x3131be00, 0x31325400, 0x3132ea00, 0x31338000,
+    0x31341600, 0x3134ac00, 0x31354200, 0x3135d800, 0x31366e00, 0x31370400, 0x31379a00, 0x31383000, 0x3138c600, 0x31395c00, 0x3139f200, 0x313a8800, 0x313b1e00, 0x313bb400, 0x313c4a00, 0x313ce000,
+    0x313d7600, 0x313e0c00, 0x313ea200, 0x313f3800, 0x313fce00, 0x31406300, 0x3140f900, 0x31418f00, 0x31422500, 0x3142bb00, 0x31435100, 0x3143e700, 0x31447d00, 0x31451300, 0x3145a900, 0x31463f00,
+    0x3146d500, 0x31476b00, 0x31480100, 0x31489700, 0x31492d00, 0x3149c300, 0x314a5900, 0x314aef00, 0x314b8500, 0x314c1b00, 0x314cb100, 0x314d4700, 0x314ddd00, 0x314e7300, 0x314f0900, 0x314f9f00,
+    0x31503500, 0x3150cb00, 0x31516100, 0x3151f700, 0x31528d00, 0x31532300, 0x3153b900, 0x31544f00, 0x3154e500, 0x31557b00, 0x31561100, 0x3156a700, 0x31573d00, 0x3157d300, 0x31586900, 0x3158ff00,
+    0x31599500, 0x315a2b00, 0x315ac100, 0x315b5700, 0x315bed00, 0x315c8300, 0x315d1900, 0x315daf00, 0x315e4500, 0x315edb00, 0x315f7100, 0x31600700, 0x31609d00, 0x31613300, 0x3161c900, 0x31625f00,
+    0x3162f500, 0x31638b00, 0x31642100, 0x3164b700, 0x31654d00, 0x3165e300, 0x31667900, 0x31670f00, 0x3167a500, 0x31683b00, 0x3168d100, 0x31696700, 0x3169fd00, 0x316a9300, 0x316b2900, 0x316bbf00,
+    0x316c5500, 0x316ceb00, 0x316d8100, 0x316e1700, 0x316ead00, 0x316f4300, 0x316fd900, 0x31706f00, 0x31710500, 0x31719b00, 0x31723100, 0x3172c700, 0x31735d00, 0x3173f300, 0x31748900, 0x31751f00,
+    0x3175b500, 0x31764b00, 0x3176e100, 0x31777700, 0x31780d00, 0x3178a300, 0x31793900, 0x3179cf00, 0x317a6500, 0x317afb00, 0x317b9100, 0x317c2700, 0x317cbd00, 0x317d5300, 0x317de900, 0x317e7f00,
+    0x317f1500, 0x317fab00, 0x31804100, 0x3180d700, 0x31816d00, 0x31820300, 0x31829900, 0x31832f00, 0x3183c500, 0x31845b00, 0x3184f100, 0x31858700, 0x31861d00, 0x3186b300, 0x31874900, 0x3187df00,
+    0x31887500, 0x31890b00, 0x3189a100, 0x318a3700, 0x318acd00, 0x318b6300, 0x318bf900, 0x318c8f00, 0x318d2500, 0x318dbb00, 0x318e5100, 0x318ee700, 0x318f7d00, 0x31901300, 0x3190a900, 0x31913f00,
+    0x3191d500, 0x31926b00, 0x31930100, 0x31939700, 0x31942d00, 0x3194c300, 0x31955900, 0x3195ef00, 0x31968500, 0x31971b00, 0x3197b100, 0x31984700, 0x3198dd00, 0x31997300, 0x319a0900, 0x319a9f00,
+    0x319b3500, 0x319bcb00, 0x319c6100, 0x319cf700, 0x319d8d00, 0x319e2300, 0x319eb900, 0x319f4f00, 0x319fe500, 0x31a07b00, 0x31a11100, 0x31a1a700, 0x31a23d00, 0x31a2d300, 0x31a36900, 0x31a3ff00,
+    0x31a49500, 0x31a52b00, 0x31a5c100, 0x31a65700, 0x31a6ed00, 0x31a78300, 0x31a81900, 0x31a8af00, 0x31a94500, 0x31a9db00, 0x31aa7100, 0x31ab0700, 0x31ab9d00, 0x31ac3300, 0x31acc900, 0x31ad5f00,
+    0x31adf500, 0x31ae8b00, 0x31af2100, 0x31afb700, 0x31b04d00, 0x31b0e300, 0x31b17900, 0x31b20f00, 0x31b2a500, 0x31b33b00, 0x31b3d100, 0x31b46700, 0x31b4fd00, 0x31b59300, 0x31b62900, 0x31b6bf00,
+    0x31b75500, 0x31b7eb00, 0x31b88100, 0x31b91700, 0x31b9ad00, 0x31ba4300, 0x31bad900, 0x31bb6f00, 0x31bc0500, 0x31bc9b00, 0x31bd3100, 0x31bdc700, 0x31be5d00, 0x31bef300, 0x31bf8900, 0x31c01f00,
+    0x31c0b500, 0x31c14b00, 0x31c1e100, 0x31c27700, 0x31c30d00, 0x31c3a300, 0x31c43900, 0x31c4cf00, 0x31c56500, 0x31c5fb00, 0x31c69100, 0x31c72700, 0x31c7bd00, 0x31c85300, 0x31c8e900, 0x31c97f00,
+    0x31ca1500, 0x31caab00, 0x31cb4100, 0x31cbd700, 0x31cc6d00, 0x31cd0300, 0x31cd9900, 0x31ce2f00, 0x31cec500, 0x31cf5b00, 0x31cff100, 0x31d08700, 0x31d11d00, 0x31d1b300, 0x31d24900, 0x31d2df00,
+    0x31d37500, 0x31d40b00, 0x31d4a100, 0x31d53700, 0x31d5cd00, 0x31d66300, 0x31d6f900, 0x31d78f00, 0x31d82500, 0x31d8bb00, 0x31d95100, 0x31d9e700, 0x31da7d00, 0x31db1300, 0x31dba900, 0x31dc3f00,
+    0x31dcd500, 0x31dd6b00, 0x31de0100, 0x31de9700, 0x31df2d00, 0x31dfc300, 0x31e05900, 0x31e0ef00, 0x31e18500, 0x31e21b00, 0x31e2b100, 0x31e34700, 0x31e3dd00, 0x31e47300, 0x31e50900, 0x31e59f00,
+    0x31e63500, 0x31e6cb00, 0x31e76100, 0x31e7f700, 0x31e88d00, 0x31e92300, 0x31e9b900, 0x31ea4f00, 0x31eae500, 0x31eb7b00, 0x31ec1100, 0x31eca700, 0x31ed3d00, 0x31edd300, 0x31ee6900, 0x31eeff00,
+    0x31ef9500, 0x31f02b00, 0x31f0c100, 0x31f15700, 0x31f1ed00, 0x31f28300, 0x31f31900, 0x31f3af00, 0x31f44500, 0x31f4db00, 0x31f57100, 0x31f60700, 0x31f69d00, 0x31f73300, 0x31f7c900, 0x31f85f00,
+    0x31f8f500, 0x31f98b00, 0x31fa2100, 0x31fab700, 0x31fb4d00, 0x31fbe300, 0x31fc7900, 0x31fd0f00, 0x31fda500, 0x31fe3b00, 0x31fed100, 0x31ff6700, 0x31fffd00, 0x32009300, 0x32012900, 0x3201bf00,
+    0x32025500, 0x3202eb00, 0x32038100, 0x32041700, 0x3204ad00, 0x32054300, 0x3205d900, 0x32066f00, 0x32070500, 0x32079b00, 0x32083100, 0x3208c700, 0x32095d00, 0x3209f300, 0x320a8900, 0x320b1f00,
+    0x320bb500, 0x320c4b00, 0x320ce100, 0x320d7700, 0x320e0d00, 0x320ea300, 0x320f3900, 0x320fcf00, 0x32106500, 0x3210fb00, 0x32119100, 0x32122700, 0x3212bd00, 0x32135300, 0x3213e900, 0x32147f00,
+    0x32151500, 0x3215ab00, 0x32164100, 0x3216d700, 0x32176d00, 0x32180300, 0x32189900, 0x32192f00, 0x3219c500, 0x321a5b00, 0x321af100, 0x321b8700, 0x321c1d00, 0x321cb300, 0x321d4900, 0x321ddf00,
+    0x321e7500, 0x321f0b00, 0x321fa100, 0x32203700, 0x3220cd00, 0x32216300, 0x3221f900, 0x32228f00, 0x32232500, 0x3223bb00, 0x32245100, 0x3224e700, 0x32257d00, 0x32261300, 0x3226a900, 0x32273f00,
+    0x3227d500, 0x32286b00, 0x32290100, 0x32299700, 0x322a2d00, 0x322ac300, 0x322b5900, 0x322bef00, 0x322c8500, 0x322d1b00, 0x322db100, 0x322e4700, 0x322edd00, 0x322f7300, 0x32300900, 0x32309f00,
+    0x32313500, 0x3231cb00, 0x32326100, 0x3232f700, 0x32338d00, 0x32342300, 0x3234b900, 0x32354f00, 0x3235e500, 0x32367b00, 0x32371100, 0x3237a700, 0x32383d00, 0x3238d300, 0x32396900, 0x3239ff00,
+    0x323aa400, 0x323b4900, 0x323bee00, 0x323c9300, 0x323d3800, 0x323ddd00, 0x323e8200, 0x323f2700, 0x323fcc00, 0x32407100, 0x32411600, 0x3241bb00, 0x32426000, 0x32430500, 0x3243aa00, 0x32444f00,
+    0x3244f400, 0x32459900, 0x32463e00, 0x3246e300, 0x32478800, 0x32482d00, 0x3248d200, 0x32497700, 0x324a1c00, 0x324ac100, 0x324b6600, 0x324c0b00, 0x324cb000, 0x324d5500, 0x324dfa00, 0x324e9f00,
+    0x324f4400, 0x324fe900, 0x32508e00, 0x32513300, 0x3251d800, 0x32527d00, 0x32532200, 0x3253c700, 0x32546c00, 0x32551100, 0x3255b600, 0x32565b00, 0x32570000, 0x3257a500, 0x32584a00, 0x3258ef00,
+    0x32599400, 0x325a3900, 0x325ade00, 0x325b8300, 0x325c2800, 0x325ccd00, 0x325d7200, 0x325e1700, 0x325ebc00, 0x325f6100, 0x32600600, 0x3260ab00, 0x32615000, 0x3261f500, 0x32629a00, 0x32633f00,
+    0x3263e400, 0x32648900, 0x32652e00, 0x3265d300, 0x32667800, 0x32671d00, 0x3267c200, 0x32686700, 0x32690c00, 0x3269b100, 0x326a5600, 0x326afb00, 0x326ba000, 0x326c4500, 0x326cea00, 0x326d8f00,
+    0x326e3400, 0x326ed900, 0x326f7e00, 0x32702300, 0x3270c800, 0x32716d00, 0x32721200, 0x3272b700, 0x32735c00, 0x32740100, 0x3274a600, 0x32754b00, 0x3275f000, 0x32769500, 0x32773a00, 0x3277df00,
+    0x32788400, 0x32792900, 0x3279ce00, 0x327a7300, 0x327b1800, 0x327bbd00, 0x327c6200, 0x327d0700, 0x327dac00, 0x327e5100, 0x327ef600, 0x327f9b00, 0x32804000, 0x3280e500, 0x32818a00, 0x32822f00,
+    0x3282d400, 0x32837900, 0x32841e00, 0x3284c300, 0x32856800, 0x32860d00, 0x3286b200, 0x32875700, 0x3287fc00, 0x3288a100, 0x32894600, 0x3289eb00, 0x328a9000, 0x328b3500, 0x328bda00, 0x328c7f00,
+    0x328d2400, 0x328dc900, 0x328e6e00, 0x328f1300, 0x328fb800, 0x32905d00, 0x32910200, 0x3291a700, 0x32924c00, 0x3292f100, 0x32939600, 0x32943b00, 0x3294e000, 0x32958500, 0x32962a00, 0x3296cf00,
+    0x32977400, 0x32981900, 0x3298be00, 0x32996300, 0x329a0800, 0x329aad00, 0x329b5200, 0x329bf700, 0x329c9c00, 0x329d4100, 0x329de600, 0x329e8b00, 0x329f3000, 0x329fd500, 0x32a07a00, 0x32a11f00,
+    0x32a1c400, 0x32a26900, 0x32a30e00, 0x32a3b300, 0x32a45800, 0x32a4fd00, 0x32a5a200, 0x32a64700, 0x32a6ec00, 0x32a79100, 0x32a83600, 0x32a8db00, 0x32a98000, 0x32aa2500, 0x32aaca00, 0x32ab6f00,
+    0x32ac1400, 0x32acb900, 0x32ad5e00, 0x32ae0300, 0x32aea800, 0x32af4d00, 0x32aff200, 0x32b09700, 0x32b13c00, 0x32b1e100, 0x32b28600, 0x32b32b00, 0x32b3d000, 0x32b47500, 0x32b51a00, 0x32b5bf00,
+    0x32b66400, 0x32b70900, 0x32b7ae00, 0x32b85300, 0x32b8f800, 0x32b99d00, 0x32ba4200, 0x32bae700, 0x32bb8c00, 0x32bc3100, 0x32bcd600, 0x32bd7b00, 0x32be2000, 0x32bec500, 0x32bf6a00, 0x32c00f00,
+    0x32c0b400, 0x32c15900, 0x32c1fe00, 0x32c2a300, 0x32c34800, 0x32c3ed00, 0x32c49200, 0x32c53700, 0x32c5dc00, 0x32c68100, 0x32c72600, 0x32c7cb00, 0x32c87000, 0x32c91500, 0x32c9ba00, 0x32ca5f00,
+    0x32cb0400, 0x32cba900, 0x32cc4e00, 0x32ccf300, 0x32cd9800, 0x32ce3d00, 0x32cee200, 0x32cf8700, 0x32d02c00, 0x32d0d100, 0x32d17600, 0x32d21b00, 0x32d2c000, 0x32d36500, 0x32d40a00, 0x32d4af00,
+    0x32d55400, 0x32d5f900, 0x32d69e00, 0x32d74300, 0x32d7e800, 0x32d88d00, 0x32d93200, 0x32d9d700, 0x32da7c00, 0x32db2100, 0x32dbc600, 0x32dc6b00, 0x32dd1000, 0x32ddb500, 0x32de5a00, 0x32deff00,
+    0x32dfa400, 0x32e04900, 0x32e0ee00, 0x32e19300, 0x32e23800, 0x32e2dd00, 0x32e38200, 0x32e42700, 0x32e4cc00, 0x32e57100, 0x32e61600, 0x32e6bb00, 0x32e76000, 0x32e80500, 0x32e8aa00, 0x32e94f00,
+    0x32e9f400, 0x32ea9900, 0x32eb3e00, 0x32ebe300, 0x32ec8800, 0x32ed2d00, 0x32edd200, 0x32ee7700, 0x32ef1c00, 0x32efc100, 0x32f06600, 0x32f10b00, 0x32f1b000, 0x32f25500, 0x32f2fa00, 0x32f39f00,
+    0x32f44400, 0x32f4e900, 0x32f58e00, 0x32f63300, 0x32f6d800, 0x32f77d00, 0x32f82200, 0x32f8c700, 0x32f96c00, 0x32fa1100, 0x32fab600, 0x32fb5b00, 0x32fc0000, 0x32fca500, 0x32fd4a00, 0x32fdef00,
+    0x32fe9400, 0x32ff3900, 0x32ffde00, 0x33008300, 0x33012800, 0x3301cd00, 0x33027200, 0x33031700, 0x3303bc00, 0x33046100, 0x33050600, 0x3305ab00, 0x33065000, 0x3306f500, 0x33079a00, 0x33083f00,
+    0x3308e400, 0x33098900, 0x330a2e00, 0x330ad300, 0x330b7800, 0x330c1d00, 0x330cc200, 0x330d6700, 0x330e0c00, 0x330eb100, 0x330f5600, 0x330ffb00, 0x3310a000, 0x33114500, 0x3311ea00, 0x33128f00,
+    0x33133400, 0x3313d900, 0x33147e00, 0x33152300, 0x3315c800, 0x33166d00, 0x33171200, 0x3317b700, 0x33185c00, 0x33190100, 0x3319a600, 0x331a4b00, 0x331af000, 0x331b9500, 0x331c3a00, 0x331cdf00,
+    0x331d8400, 0x331e2900, 0x331ece00, 0x331f7300, 0x33201800, 0x3320bd00, 0x33216200, 0x33220700, 0x3322ac00, 0x33235100, 0x3323f600, 0x33249b00, 0x33254000, 0x3325e500, 0x33268a00, 0x33272f00,
+    0x3327d400, 0x33287900, 0x33291e00, 0x3329c300, 0x332a6800, 0x332b0d00, 0x332bb200, 0x332c5700, 0x332cfc00, 0x332da100, 0x332e4600, 0x332eeb00, 0x332f9000, 0x33303500, 0x3330da00, 0x33317f00,
+    0x33322400, 0x3332c900, 0x33336e00, 0x33341300, 0x3334b800, 0x33355d00, 0x33360200, 0x3336a700, 0x33374c00, 0x3337f100, 0x33389600, 0x33393b00, 0x3339e000, 0x333a8500, 0x333b2a00, 0x333bcf00,
+    0x333c7400, 0x333d1900, 0x333dbe00, 0x333e6300, 0x333f0800, 0x333fad00, 0x33405200, 0x3340f700, 0x33419c00, 0x33424100, 0x3342e600, 0x33438b00, 0x33443000, 0x3344d500, 0x33457a00, 0x33461f00,
+    0x3346c400, 0x33476900, 0x33480e00, 0x3348b300, 0x33495800, 0x3349fd00, 0x334aa200, 0x334b4700, 0x334bec00, 0x334c9100, 0x334d3600, 0x334ddb00, 0x334e8000, 0x334f2500, 0x334fca00, 0x33506f00,
+    0x33511400, 0x3351b900, 0x33525e00, 0x33530300, 0x3353a800, 0x33544d00, 0x3354f200, 0x33559700, 0x33563c00, 0x3356e100, 0x33578600, 0x33582b00, 0x3358d000, 0x33597500, 0x335a1a00, 0x335abf00,
+    0x335b6400, 0x335c0900, 0x335cae00, 0x335d5300, 0x335df800, 0x335e9d00, 0x335f4200, 0x335fe700, 0x33608c00, 0x33613100, 0x3361d600, 0x33627b00, 0x33632000, 0x3363c500, 0x33646a00, 0x33650f00,
+    0x3365b400, 0x33665900, 0x3366fe00, 0x3367a300, 0x33684800, 0x3368ed00, 0x33699200, 0x336a3700, 0x336adc00, 0x336b8100, 0x336c2600, 0x336ccb00, 0x336d7000, 0x336e1500, 0x336eba00, 0x336f5f00,
+    0x33700400, 0x3370a900, 0x33714e00, 0x3371f300, 0x33729800, 0x33733d00, 0x3373e200, 0x33748700, 0x33752c00, 0x3375d100, 0x33767600, 0x33771b00, 0x3377c000, 0x33786500, 0x33790a00, 0x3379af00,
+    0x337a5400, 0x337af900, 0x337b9e00, 0x337c4300, 0x337ce800, 0x337d8d00, 0x337e3200, 0x337ed700, 0x337f7c00, 0x33802100, 0x3380c600, 0x33816b00, 0x33821000, 0x3382b500, 0x33835a00, 0x3383ff00,
+    0x3384a700, 0x33854f00, 0x3385f700, 0x33869f00, 0x33874700, 0x3387ef00, 0x33889700, 0x33893f00, 0x3389e700, 0x338a8f00, 0x338b3700, 0x338bdf00, 0x338c8700, 0x338d2f00, 0x338dd700, 0x338e7f00,
+    0x338f2700, 0x338fcf00, 0x33907700, 0x33911f00, 0x3391c700, 0x33926f00, 0x33931700, 0x3393bf00, 0x33946700, 0x33950f00, 0x3395b700, 0x33965f00, 0x33970700, 0x3397af00, 0x33985700, 0x3398ff00,
+    0x3399a700, 0x339a4f00, 0x339af700, 0x339b9f00, 0x339c4700, 0x339cef00, 0x339d9700, 0x339e3f00, 0x339ee700, 0x339f8f00, 0x33a03700, 0x33a0df00, 0x33a18700, 0x33a22f00, 0x33a2d700, 0x33a37f00,
+    0x33a42700, 0x33a4cf00, 0x33a57700, 0x33a61f00, 0x33a6c700, 0x33a76f00, 0x33a81700, 0x33a8bf00, 0x33a96700, 0x33aa0f00, 0x33aab700, 0x33ab5f00, 0x33ac0700, 0x33acaf00, 0x33ad5700, 0x33adff00,
+    0x33aea700, 0x33af4f00, 0x33aff700, 0x33b09f00, 0x33b14700, 0x33b1ef00, 0x33b29700, 0x33b33f00, 0x33b3e700, 0x33b48f00, 0x33b53700, 0x33b5df00, 0x33b68700, 0x33b72f00, 0x33b7d700, 0x33b87f00,
+    0x33b92700, 0x33b9cf00, 0x33ba7700, 0x33bb1f00, 0x33bbc700, 0x33bc6f00, 0x33bd1700, 0x33bdbf00, 0x33be6700, 0x33bf0f00, 0x33bfb700, 0x33c05f00, 0x33c10700, 0x33c1af00, 0x33c25700, 0x33c2ff00,
+    0x33c3a700, 0x33c44f00, 0x33c4f700, 0x33c59f00, 0x33c64700, 0x33c6ef00, 0x33c79700, 0x33c83f00, 0x33c8e700, 0x33c98f00, 0x33ca3700, 0x33cadf00, 0x33cb8700, 0x33cc2f00, 0x33ccd700, 0x33cd7f00,
+    0x33ce2700, 0x33cecf00, 0x33cf7700, 0x33d01f00, 0x33d0c700, 0x33d16f00, 0x33d21700, 0x33d2bf00, 0x33d36700, 0x33d40f00, 0x33d4b700, 0x33d55f00, 0x33d60700, 0x33d6af00, 0x33d75700, 0x33d80000,
+    0x33d8a800, 0x33d95000, 0x33d9f800, 0x33daa000, 0x33db4800, 0x33dbf000, 0x33dc9800, 0x33dd4000, 0x33dde800, 0x33de9000, 0x33df3800, 0x33dfe000, 0x33e08800, 0x33e13000, 0x33e1d800, 0x33e28000,
+    0x33e32800, 0x33e3d000, 0x33e47800, 0x33e52000, 0x33e5c800, 0x33e67000, 0x33e71800, 0x33e7c000, 0x33e86800, 0x33e91000, 0x33e9b800, 0x33ea6000, 0x33eb0800, 0x33ebb000, 0x33ec5800, 0x33ed0000,
+    0x33eda800, 0x33ee5000, 0x33eef800, 0x33efa000, 0x33f04800, 0x33f0f000, 0x33f19800, 0x33f24000, 0x33f2e800, 0x33f39000, 0x33f43800, 0x33f4e000, 0x33f58800, 0x33f63000, 0x33f6d800, 0x33f78000,
+    0x33f82800, 0x33f8d000, 0x33f97800, 0x33fa2000, 0x33fac800, 0x33fb7000, 0x33fc1800, 0x33fcc000, 0x33fd6800, 0x33fe1000, 0x33feb800, 0x33ff6000, 0x34000800, 0x3400b000, 0x34015800, 0x34020000,
+    0x3402a800, 0x34035000, 0x3403f800, 0x3404a000, 0x34054800, 0x3405f000, 0x34069800, 0x34074000, 0x3407e800, 0x34089000, 0x34093800, 0x3409e000, 0x340a8800, 0x340b3000, 0x340bd800, 0x340c8000,
+    0x340d2800, 0x340dd000, 0x340e7800, 0x340f2000, 0x340fc800, 0x34107000, 0x34111800, 0x3411c000, 0x34126800, 0x34131000, 0x3413b800, 0x34146000, 0x34150800, 0x3415b000, 0x34165800, 0x34170000,
+    0x3417a800, 0x34185000, 0x3418f800, 0x3419a000, 0x341a4800, 0x341af000, 0x341b9800, 0x341c4000, 0x341ce800, 0x341d9000, 0x341e3800, 0x341ee000, 0x341f8800, 0x34203000, 0x3420d800, 0x34218000,
+    0x34222800, 0x3422d000, 0x34237800, 0x34242000, 0x3424c800, 0x34257000, 0x34261800, 0x3426c000, 0x34276800, 0x34281000, 0x3428b800, 0x34296000, 0x342a0800, 0x342ab000, 0x342b5800, 0x342c0000,
+    0x342ca800, 0x342d5000, 0x342df800, 0x342ea000, 0x342f4800, 0x342ff000, 0x34309800, 0x34314000, 0x3431e800, 0x34329000, 0x34333800, 0x3433e000, 0x34348800, 0x34353000, 0x3435d800, 0x34368000,
+    0x34372800, 0x3437d000, 0x34387800, 0x34392000, 0x3439c800, 0x343a7000, 0x343b1800, 0x343bc000, 0x343c6800, 0x343d1000, 0x343db800, 0x343e6000, 0x343f0800, 0x343fb000, 0x34405800, 0x34410000,
+    0x3441a800, 0x34425000, 0x3442f800, 0x3443a000, 0x34444800, 0x3444f000, 0x34459800, 0x34464000, 0x3446e800, 0x34479000, 0x34483800, 0x3448e000, 0x34498800, 0x344a3000, 0x344ad800, 0x344b8000,
+    0x344c2800, 0x344cd000, 0x344d7800, 0x344e2000, 0x344ec800, 0x344f7000, 0x34501800, 0x3450c000, 0x34516800, 0x34521000, 0x3452b800, 0x34536000, 0x34540800, 0x3454b000, 0x34555800, 0x34560000,
+    0x3456a800, 0x34575000, 0x3457f800, 0x3458a000, 0x34594800, 0x3459f000, 0x345a9800, 0x345b4000, 0x345be800, 0x345c9000, 0x345d3800, 0x345de000, 0x345e8800, 0x345f3000, 0x345fd800, 0x34608000,
+    0x34612800, 0x3461d000, 0x34627800, 0x34632000, 0x3463c800, 0x34647000, 0x34651800, 0x3465c000, 0x34666800, 0x34671000, 0x3467b800, 0x34686000, 0x34690800, 0x3469b000, 0x346a5800, 0x346b0000,
+    0x346ba800, 0x346c5000, 0x346cf800, 0x346da000, 0x346e4800, 0x346ef000, 0x346f9800, 0x34704000, 0x3470e800, 0x34719000, 0x34723800, 0x3472e000, 0x34738800, 0x34743000, 0x3474d800, 0x34758000,
+    0x34762800, 0x3476d000, 0x34777800, 0x34782000, 0x3478c800, 0x34797000, 0x347a1800, 0x347ac000, 0x347b6800, 0x347c1000, 0x347cb800, 0x347d6000, 0x347e0800, 0x347eb000, 0x347f5800, 0x34800000,
+    0x3480a800, 0x34815000, 0x3481f800, 0x3482a000, 0x34834800, 0x3483f000, 0x34849800, 0x34854000, 0x3485e800, 0x34869000, 0x34873800, 0x3487e000, 0x34888800, 0x34893000, 0x3489d800, 0x348a8000,
+    0x348b2800, 0x348bd000, 0x348c7800, 0x348d2000, 0x348dc800, 0x348e7000, 0x348f1800, 0x348fc000, 0x34906800, 0x34911000, 0x3491b800, 0x34926000, 0x34930800, 0x3493b000, 0x34945800, 0x34950000,
+    0x3495a800, 0x34965000, 0x3496f800, 0x3497a000, 0x34984800, 0x3498f000, 0x34999800, 0x349a4000, 0x349ae800, 0x349b9000, 0x349c3800, 0x349ce000, 0x349d8800, 0x349e3000, 0x349ed800, 0x349f8000,
+    0x34a02800, 0x34a0d000, 0x34a17800, 0x34a22000, 0x34a2c800, 0x34a37000, 0x34a41800, 0x34a4c000, 0x34a56800, 0x34a61000, 0x34a6b800, 0x34a76000, 0x34a80800, 0x34a8b000, 0x34a95800, 0x34aa0000,
+    0x34aaa800, 0x34ab5000, 0x34abf800, 0x34aca000, 0x34ad4800, 0x34adf000, 0x34ae9800, 0x34af4000, 0x34afe800, 0x34b09000, 0x34b13800, 0x34b1e000, 0x34b28800, 0x34b33000, 0x34b3d800, 0x34b48000,
+    0x34b52800, 0x34b5d000, 0x34b67800, 0x34b72000, 0x34b7c800, 0x34b87000, 0x34b91800, 0x34b9c000, 0x34ba6800, 0x34bb1000, 0x34bbb800, 0x34bc6000, 0x34bd0800, 0x34bdb000, 0x34be5800, 0x34bf0000,
+    0x34bfa800, 0x34c05000, 0x34c0f800, 0x34c1a000, 0x34c24800, 0x34c2f000, 0x34c39800, 0x34c44000, 0x34c4e800, 0x34c59000, 0x34c63800, 0x34c6e000, 0x34c78800, 0x34c83000, 0x34c8d800, 0x34c98000,
+    0x34ca2800, 0x34cad000, 0x34cb7800, 0x34cc2000, 0x34ccc800, 0x34cd7000, 0x34ce1800, 0x34cec000, 0x34cf6800, 0x34d01000, 0x34d0b800, 0x34d16000, 0x34d20800, 0x34d2b000, 0x34d35800, 0x34d40000,
+    0x34d4bb00, 0x34d57600, 0x34d63100, 0x34d6ec00, 0x34d7a700, 0x34d86200, 0x34d91d00, 0x34d9d800, 0x34da9300, 0x34db4e00, 0x34dc0900, 0x34dcc400, 0x34dd7f00, 0x34de3a00, 0x34def500, 0x34dfb000,
+    0x34e06b00, 0x34e12600, 0x34e1e100, 0x34e29c00, 0x34e35700, 0x34e41200, 0x34e4cd00, 0x34e58800, 0x34e64300, 0x34e6fe00, 0x34e7b900, 0x34e87400, 0x34e92f00, 0x34e9ea00, 0x34eaa500, 0x34eb6000,
+    0x34ec1b00, 0x34ecd600, 0x34ed9100, 0x34ee4c00, 0x34ef0700, 0x34efc200, 0x34f07d00, 0x34f13800, 0x34f1f300, 0x34f2ae00, 0x34f36900, 0x34f42400, 0x34f4df00, 0x34f59a00, 0x34f65500, 0x34f71000,
+    0x34f7cb00, 0x34f88600, 0x34f94100, 0x34f9fc00, 0x34fab700, 0x34fb7200, 0x34fc2d00, 0x34fce800, 0x34fda300, 0x34fe5e00, 0x34ff1900, 0x34ffd400, 0x35008f00, 0x35014a00, 0x35020500, 0x3502c000,
+    0x35037b00, 0x35043600, 0x3504f100, 0x3505ac00, 0x35066700, 0x35072200, 0x3507dd00, 0x35089800, 0x35095300, 0x350a0e00, 0x350ac900, 0x350b8400, 0x350c3f00, 0x350cfa00, 0x350db500, 0x350e7000,
+    0x350f2b00, 0x350fe600, 0x3510a100, 0x35115c00, 0x35121700, 0x3512d200, 0x35138d00, 0x35144800, 0x35150300, 0x3515be00, 0x35167900, 0x35173400, 0x3517ef00, 0x3518aa00, 0x35196500, 0x351a2000,
+    0x351adb00, 0x351b9600, 0x351c5100, 0x351d0c00, 0x351dc700, 0x351e8200, 0x351f3d00, 0x351ff800, 0x3520b300, 0x35216e00, 0x35222900, 0x3522e400, 0x35239f00, 0x35245a00, 0x35251500, 0x3525d000,
+    0x35268b00, 0x35274600, 0x35280100, 0x3528bc00, 0x35297700, 0x352a3200, 0x352aed00, 0x352ba800, 0x352c6300, 0x352d1e00, 0x352dd900, 0x352e9400, 0x352f4f00, 0x35300a00, 0x3530c500, 0x35318000,
+    0x35323b00, 0x3532f600, 0x3533b100, 0x35346c00, 0x35352700, 0x3535e200, 0x35369d00, 0x35375800, 0x35381300, 0x3538ce00, 0x35398900, 0x353a4400, 0x353aff00, 0x353bba00, 0x353c7500, 0x353d3000,
+    0x353deb00, 0x353ea600, 0x353f6100, 0x35401c00, 0x3540d700, 0x35419200, 0x35424d00, 0x35430800, 0x3543c300, 0x35447e00, 0x35453900, 0x3545f400, 0x3546af00, 0x35476a00, 0x35482500, 0x3548e000,
+    0x35499b00, 0x354a5600, 0x354b1100, 0x354bcc00, 0x354c8700, 0x354d4200, 0x354dfd00, 0x354eb800, 0x354f7300, 0x35502e00, 0x3550e900, 0x3551a400, 0x35525f00, 0x35531a00, 0x3553d500, 0x35549000,
+    0x35554b00, 0x35560600, 0x3556c100, 0x35577c00, 0x35583700, 0x3558f200, 0x3559ad00, 0x355a6800, 0x355b2300, 0x355bde00, 0x355c9900, 0x355d5400, 0x355e0f00, 0x355eca00, 0x355f8500, 0x35604000,
+    0x3560fb00, 0x3561b600, 0x35627100, 0x35632c00, 0x3563e700, 0x3564a200, 0x35655d00, 0x35661800, 0x3566d300, 0x35678e00, 0x35684900, 0x35690400, 0x3569bf00, 0x356a7a00, 0x356b3500, 0x356bf000,
+    0x356cab00, 0x356d6600, 0x356e2100, 0x356edc00, 0x356f9700, 0x35705200, 0x35710d00, 0x3571c800, 0x35728300, 0x35733e00, 0x3573f900, 0x3574b400, 0x35756f00, 0x35762a00, 0x3576e500, 0x3577a000,
+    0x35785b00, 0x35791600, 0x3579d100, 0x357a8c00, 0x357b4700, 0x357c0200, 0x357cbd00, 0x357d7800, 0x357e3300, 0x357eee00, 0x357fa900, 0x35806400, 0x35811f00, 0x3581da00, 0x35829500, 0x35835000,
+    0x35840b00, 0x3584c600, 0x35858100, 0x35863c00, 0x3586f700, 0x3587b200, 0x35886d00, 0x35892800, 0x3589e300, 0x358a9e00, 0x358b5900, 0x358c1400, 0x358ccf00, 0x358d8a00, 0x358e4500, 0x358f0000,
+    0x358fbb00, 0x35907600, 0x35913100, 0x3591ec00, 0x3592a700, 0x35936200, 0x35941d00, 0x3594d800, 0x35959300, 0x35964e00, 0x35970900, 0x3597c400, 0x35987f00, 0x35993a00, 0x3599f500, 0x359ab000,
+    0x359b6b00, 0x359c2600, 0x359ce100, 0x359d9c00, 0x359e5700, 0x359f1200, 0x359fcd00, 0x35a08800, 0x35a14300, 0x35a1fe00, 0x35a2b900, 0x35a37400, 0x35a42f00, 0x35a4ea00, 0x35a5a500, 0x35a66000,
+    0x35a71b00, 0x35a7d600, 0x35a89100, 0x35a94c00, 0x35aa0700, 0x35aac200, 0x35ab7d00, 0x35ac3800, 0x35acf300, 0x35adae00, 0x35ae6900, 0x35af2400, 0x35afdf00, 0x35b09a00, 0x35b15500, 0x35b21000,
+    0x35b2cb00, 0x35b38600, 0x35b44100, 0x35b4fc00, 0x35b5b700, 0x35b67200, 0x35b72d00, 0x35b7e800, 0x35b8a300, 0x35b95e00, 0x35ba1900, 0x35bad400, 0x35bb8f00, 0x35bc4a00, 0x35bd0500, 0x35bdc000,
+    0x35be7b00, 0x35bf3600, 0x35bff100, 0x35c0ac00, 0x35c16700, 0x35c22200, 0x35c2dd00, 0x35c39800, 0x35c45300, 0x35c50e00, 0x35c5c900, 0x35c68400, 0x35c73f00, 0x35c7fa00, 0x35c8b500, 0x35c97000,
+    0x35ca2b00, 0x35cae600, 0x35cba100, 0x35cc5c00, 0x35cd1700, 0x35cdd200, 0x35ce8d00, 0x35cf4800, 0x35d00300, 0x35d0be00, 0x35d17900, 0x35d23400, 0x35d2ef00, 0x35d3aa00, 0x35d46500, 0x35d52000,
+    0x35d5db00, 0x35d69600, 0x35d75100, 0x35d80c00, 0x35d8c700, 0x35d98200, 0x35da3d00, 0x35daf800, 0x35dbb300, 0x35dc6e00, 0x35dd2900, 0x35dde400, 0x35de9f00, 0x35df5a00, 0x35e01500, 0x35e0d000,
+    0x35e18b00, 0x35e24600, 0x35e30100, 0x35e3bc00, 0x35e47700, 0x35e53200, 0x35e5ed00, 0x35e6a800, 0x35e76300, 0x35e81e00, 0x35e8d900, 0x35e99400, 0x35ea4f00, 0x35eb0a00, 0x35ebc500, 0x35ec8000,
+    0x35ed3b00, 0x35edf600, 0x35eeb100, 0x35ef6c00, 0x35f02700, 0x35f0e200, 0x35f19d00, 0x35f25800, 0x35f31300, 0x35f3ce00, 0x35f48900, 0x35f54400, 0x35f5ff00, 0x35f6ba00, 0x35f77500, 0x35f83000,
+    0x35f8eb00, 0x35f9a600, 0x35fa6100, 0x35fb1c00, 0x35fbd700, 0x35fc9200, 0x35fd4d00, 0x35fe0800, 0x35fec300, 0x35ff7e00, 0x36003900, 0x3600f400, 0x3601af00, 0x36026a00, 0x36032500, 0x3603e000,
+    0x36049b00, 0x36055600, 0x36061100, 0x3606cc00, 0x36078700, 0x36084200, 0x3608fd00, 0x3609b800, 0x360a7300, 0x360b2e00, 0x360be900, 0x360ca400, 0x360d5f00, 0x360e1a00, 0x360ed500, 0x360f9000,
+    0x36104b00, 0x36110600, 0x3611c100, 0x36127c00, 0x36133700, 0x3613f200, 0x3614ad00, 0x36156800, 0x36162300, 0x3616de00, 0x36179900, 0x36185400, 0x36190f00, 0x3619ca00, 0x361a8500, 0x361b4000,
+    0x361bfb00, 0x361cb600, 0x361d7100, 0x361e2c00, 0x361ee700, 0x361fa200, 0x36205d00, 0x36211800, 0x3621d300, 0x36228e00, 0x36234900, 0x36240400, 0x3624bf00, 0x36257a00, 0x36263500, 0x3626f000,
+    0x3627ab00, 0x36286600, 0x36292100, 0x3629dc00, 0x362a9700, 0x362b5200, 0x362c0d00, 0x362cc800, 0x362d8300, 0x362e3e00, 0x362ef900, 0x362fb400, 0x36306f00, 0x36312a00, 0x3631e500, 0x3632a000,
+    0x36335b00, 0x36341600, 0x3634d100, 0x36358c00, 0x36364700, 0x36370200, 0x3637bd00, 0x36387800, 0x36393300, 0x3639ee00, 0x363aa900, 0x363b6400, 0x363c1f00, 0x363cda00, 0x363d9500, 0x363e5000,
+    0x363f0b00, 0x363fc600, 0x36408100, 0x36413c00, 0x3641f700, 0x3642b200, 0x36436d00, 0x36442800, 0x3644e300, 0x36459e00, 0x36465900, 0x36471400, 0x3647cf00, 0x36488a00, 0x36494500, 0x364a0000,
+    0x364ac000, 0x364b8000, 0x364c4000, 0x364d0000, 0x364dc000, 0x364e8000, 0x364f4000, 0x36500000, 0x3650c000, 0x36518000, 0x36524000, 0x36530000, 0x3653c000, 0x36548000, 0x36554000, 0x36560000,
+    0x3656c000, 0x36578000, 0x36584000, 0x36590000, 0x3659c000, 0x365a8000, 0x365b4000, 0x365c0000, 0x365cc000, 0x365d8000, 0x365e4000, 0x365f0000, 0x365fc000, 0x36608000, 0x36614000, 0x36620000,
+    0x3662c000, 0x36638000, 0x36644000, 0x36650000, 0x3665c000, 0x36668000, 0x36674000, 0x36680000, 0x3668c000, 0x36698000, 0x366a4000, 0x366b0000, 0x366bc000, 0x366c8000, 0x366d4000, 0x366e0000,
+    0x366ec000, 0x366f8000, 0x36704000, 0x36710000, 0x3671c000, 0x36728000, 0x36734000, 0x36740000, 0x3674c000, 0x36758000, 0x36764000, 0x36770000, 0x3677c000, 0x36788000, 0x36794000, 0x367a0000,
+    0x367ac000, 0x367b8000, 0x367c4000, 0x367d0000, 0x367dc000, 0x367e8000, 0x367f4000, 0x36800000, 0x3680c000, 0x36818000, 0x36824000, 0x36830000, 0x3683c000, 0x36848000, 0x36854000, 0x36860000,
+    0x3686c000, 0x36878000, 0x36884000, 0x36890000, 0x3689c000, 0x368a8000, 0x368b4000, 0x368c0000, 0x368cc000, 0x368d8000, 0x368e4000, 0x368f0000, 0x368fc000, 0x36908000, 0x36914000, 0x36920000,
+    0x3692c000, 0x36938000, 0x36944000, 0x36950000, 0x3695c000, 0x36968000, 0x36974000, 0x36980000, 0x3698c000, 0x36998000, 0x369a4000, 0x369b0000, 0x369bc000, 0x369c8000, 0x369d4000, 0x369e0000,
+    0x369ec000, 0x369f8000, 0x36a04000, 0x36a10000, 0x36a1c000, 0x36a28000, 0x36a34000, 0x36a40000, 0x36a4c000, 0x36a58000, 0x36a64000, 0x36a70000, 0x36a7c000, 0x36a88000, 0x36a94000, 0x36aa0000,
+    0x36aac000, 0x36ab8000, 0x36ac4000, 0x36ad0000, 0x36adc000, 0x36ae8000, 0x36af4000, 0x36b00000, 0x36b0c000, 0x36b18000, 0x36b24000, 0x36b30000, 0x36b3c000, 0x36b48000, 0x36b54000, 0x36b60000,
+    0x36b6c000, 0x36b78000, 0x36b84000, 0x36b90000, 0x36b9c000, 0x36ba8000, 0x36bb4000, 0x36bc0000, 0x36bcc000, 0x36bd8000, 0x36be4000, 0x36bf0000, 0x36bfc000, 0x36c08000, 0x36c14000, 0x36c20000,
+    0x36c2c000, 0x36c38000, 0x36c44000, 0x36c50000, 0x36c5c000, 0x36c68000, 0x36c74000, 0x36c80000, 0x36c8c000, 0x36c98000, 0x36ca4000, 0x36cb0000, 0x36cbc000, 0x36cc8000, 0x36cd4000, 0x36ce0000,
+    0x36cec000, 0x36cf8000, 0x36d04000, 0x36d10000, 0x36d1c000, 0x36d28000, 0x36d34000, 0x36d40000, 0x36d4c000, 0x36d58000, 0x36d64000, 0x36d70000, 0x36d7c000, 0x36d88000, 0x36d94000, 0x36da0000,
+    0x36dac000, 0x36db8000, 0x36dc4000, 0x36dd0000, 0x36ddc000, 0x36de8000, 0x36df4000, 0x36e00000, 0x36e0c000, 0x36e18000, 0x36e24000, 0x36e30000, 0x36e3c000, 0x36e48000, 0x36e54000, 0x36e60000,
+    0x36e6c000, 0x36e78000, 0x36e84000, 0x36e90000, 0x36e9c000, 0x36ea8000, 0x36eb4000, 0x36ec0000, 0x36ecc000, 0x36ed8000, 0x36ee4000, 0x36ef0000, 0x36efc000, 0x36f08000, 0x36f14000, 0x36f20000,
+    0x36f2c000, 0x36f38000, 0x36f44000, 0x36f50000, 0x36f5c000, 0x36f68000, 0x36f74000, 0x36f80000, 0x36f8c000, 0x36f98000, 0x36fa4000, 0x36fb0000, 0x36fbc000, 0x36fc8000, 0x36fd4000, 0x36fe0000,
+    0x36fec000, 0x36ff8000, 0x37004000, 0x37010000, 0x3701c000, 0x37028000, 0x37034000, 0x37040000, 0x3704c000, 0x37058000, 0x37064000, 0x37070000, 0x3707c000, 0x37088000, 0x37094000, 0x370a0000,
+    0x370ac000, 0x370b8000, 0x370c4000, 0x370d0000, 0x370dc000, 0x370e8000, 0x370f4000, 0x37100000, 0x3710c000, 0x37118000, 0x37124000, 0x37130000, 0x3713c000, 0x37148000, 0x37154000, 0x37160000,
+    0x3716c000, 0x37178000, 0x37184000, 0x37190000, 0x3719c000, 0x371a8000, 0x371b4000, 0x371c0000, 0x371cc000, 0x371d8000, 0x371e4000, 0x371f0000, 0x371fc000, 0x37208000, 0x37214000, 0x37220000,
+    0x3722c000, 0x37238000, 0x37244000, 0x37250000, 0x3725c000, 0x37268000, 0x37274000, 0x37280000, 0x3728c000, 0x37298000, 0x372a4000, 0x372b0000, 0x372bc000, 0x372c8000, 0x372d4000, 0x372e0000,
+    0x372ec000, 0x372f8000, 0x37304000, 0x37310000, 0x3731c000, 0x37328000, 0x37334000, 0x37340000, 0x3734c000, 0x37358000, 0x37364000, 0x37370000, 0x3737c000, 0x37388000, 0x37394000, 0x373a0000,
+    0x373ac000, 0x373b8000, 0x373c4000, 0x373d0000, 0x373dc000, 0x373e8000, 0x373f4000, 0x37400000, 0x3740c000, 0x37418000, 0x37424000, 0x37430000, 0x3743c000, 0x37448000, 0x37454000, 0x37460000,
+    0x3746c000, 0x37478000, 0x37484000, 0x37490000, 0x3749c000, 0x374a8000, 0x374b4000, 0x374c0000, 0x374cc000, 0x374d8000, 0x374e4000, 0x374f0000, 0x374fc000, 0x37508000, 0x37514000, 0x37520000,
+    0x3752c000, 0x37538000, 0x37544000, 0x37550000, 0x3755c000, 0x37568000, 0x37574000, 0x37580000, 0x3758c000, 0x37598000, 0x375a4000, 0x375b0000, 0x375bc000, 0x375c8000, 0x375d4000, 0x375e0000,
+    0x375ec000, 0x375f8000, 0x37604000, 0x37610000, 0x3761c000, 0x37628000, 0x37634000, 0x37640000, 0x3764c000, 0x37658000, 0x37664000, 0x37670000, 0x3767c000, 0x37688000, 0x37694000, 0x376a0000,
+    0x376ac000, 0x376b8000, 0x376c4000, 0x376d0000, 0x376dc000, 0x376e8000, 0x376f4000, 0x37700000, 0x3770c000, 0x37718000, 0x37724000, 0x37730000, 0x3773c000, 0x37748000, 0x37754000, 0x37760000,
+    0x3776c000, 0x37778000, 0x37784000, 0x37790000, 0x3779c000, 0x377a8000, 0x377b4000, 0x377c0000, 0x377cc000, 0x377d8000, 0x377e4000, 0x377f0000, 0x377fc000, 0x37808000, 0x37814000, 0x37820000,
+    0x3782c000, 0x37838000, 0x37844000, 0x37850000, 0x3785c000, 0x37868000, 0x37874000, 0x37880000, 0x3788c000, 0x37898000, 0x378a4000, 0x378b0000, 0x378bc000, 0x378c8000, 0x378d4000, 0x378e0000,
+    0x378ec000, 0x378f8000, 0x37904000, 0x37910000, 0x3791c000, 0x37928000, 0x37934000, 0x37940000, 0x3794c000, 0x37958000, 0x37964000, 0x37970000, 0x3797c000, 0x37988000, 0x37994000, 0x379a0000,
+    0x379ac000, 0x379b8000, 0x379c4000, 0x379d0000, 0x379dc000, 0x379e8000, 0x379f4000, 0x37a00000, 0x37a0c000, 0x37a18000, 0x37a24000, 0x37a30000, 0x37a3c000, 0x37a48000, 0x37a54000, 0x37a60000,
+    0x37a6c000, 0x37a78000, 0x37a84000, 0x37a90000, 0x37a9c000, 0x37aa8000, 0x37ab4000, 0x37ac0000, 0x37acc000, 0x37ad8000, 0x37ae4000, 0x37af0000, 0x37afc000, 0x37b08000, 0x37b14000, 0x37b20000,
+    0x37b2c000, 0x37b38000, 0x37b44000, 0x37b50000, 0x37b5c000, 0x37b68000, 0x37b74000, 0x37b80000, 0x37b8c000, 0x37b98000, 0x37ba4000, 0x37bb0000, 0x37bbc000, 0x37bc8000, 0x37bd4000, 0x37be0000,
+    0x37bec000, 0x37bf8000, 0x37c04000, 0x37c10000, 0x37c1c000, 0x37c28000, 0x37c34000, 0x37c40000, 0x37c4c000, 0x37c58000, 0x37c64000, 0x37c70000, 0x37c7c000, 0x37c88000, 0x37c94000, 0x37ca0000,
+    0x37cad800, 0x37cbb000, 0x37cc8800, 0x37cd6000, 0x37ce3800, 0x37cf1000, 0x37cfe800, 0x37d0c000, 0x37d19800, 0x37d27000, 0x37d34800, 0x37d42000, 0x37d4f800, 0x37d5d000, 0x37d6a800, 0x37d78000,
+    0x37d85800, 0x37d93000, 0x37da0800, 0x37dae000, 0x37dbb800, 0x37dc9000, 0x37dd6800, 0x37de4000, 0x37df1800, 0x37dff000, 0x37e0c800, 0x37e1a000, 0x37e27800, 0x37e35000, 0x37e42800, 0x37e50000,
+    0x37e5d800, 0x37e6b000, 0x37e78800, 0x37e86000, 0x37e93800, 0x37ea1000, 0x37eae800, 0x37ebc000, 0x37ec9800, 0x37ed7000, 0x37ee4800, 0x37ef2000, 0x37eff800, 0x37f0d000, 0x37f1a800, 0x37f28000,
+    0x37f35800, 0x37f43000, 0x37f50800, 0x37f5e000, 0x37f6b800, 0x37f79000, 0x37f86800, 0x37f94000, 0x37fa1800, 0x37faf000, 0x37fbc800, 0x37fca000, 0x37fd7800, 0x37fe5000, 0x37ff2800, 0x38000000,
+    0x3800d800, 0x3801b000, 0x38028800, 0x38036000, 0x38043800, 0x38051000, 0x3805e800, 0x3806c000, 0x38079800, 0x38087000, 0x38094800, 0x380a2000, 0x380af800, 0x380bd000, 0x380ca800, 0x380d8000,
+    0x380e5800, 0x380f3000, 0x38100800, 0x3810e000, 0x3811b800, 0x38129000, 0x38136800, 0x38144000, 0x38151800, 0x3815f000, 0x3816c800, 0x3817a000, 0x38187800, 0x38195000, 0x381a2800, 0x381b0000,
+    0x381bd800, 0x381cb000, 0x381d8800, 0x381e6000, 0x381f3800, 0x38201000, 0x3820e800, 0x3821c000, 0x38229800, 0x38237000, 0x38244800, 0x38252000, 0x3825f800, 0x3826d000, 0x3827a800, 0x38288000,
+    0x38295800, 0x382a3000, 0x382b0800, 0x382be000, 0x382cb800, 0x382d9000, 0x382e6800, 0x382f4000, 0x38301800, 0x3830f000, 0x3831c800, 0x3832a000, 0x38337800, 0x38345000, 0x38352800, 0x38360000,
+    0x3836d800, 0x3837b000, 0x38388800, 0x38396000, 0x383a3800, 0x383b1000, 0x383be800, 0x383cc000, 0x383d9800, 0x383e7000, 0x383f4800, 0x38402000, 0x3840f800, 0x3841d000, 0x3842a800, 0x38438000,
+    0x38445800, 0x38453000, 0x38460800, 0x3846e000, 0x3847b800, 0x38489000, 0x38496800, 0x384a4000, 0x384b1800, 0x384bf000, 0x384cc800, 0x384da000, 0x384e7800, 0x384f5000, 0x38502800, 0x38510000,
+    0x3851d800, 0x3852b000, 0x38538800, 0x38546000, 0x38553800, 0x38561000, 0x3856e800, 0x3857c000, 0x38589800, 0x38597000, 0x385a4800, 0x385b2000, 0x385bf800, 0x385cd000, 0x385da800, 0x385e8000,
+    0x385f5800, 0x38603000, 0x38610800, 0x3861e000, 0x3862b800, 0x38639000, 0x38646800, 0x38654000, 0x38661800, 0x3866f000, 0x3867c800, 0x3868a000, 0x38697800, 0x386a5000, 0x386b2800, 0x386c0000,
+    0x386cd700, 0x386daf00, 0x386e8700, 0x386f5f00, 0x38703700, 0x38710f00, 0x3871e700, 0x3872bf00, 0x38739700, 0x38746f00, 0x38754700, 0x38761f00, 0x3876f700, 0x3877cf00, 0x3878a700, 0x38797f00,
+    0x387a5700, 0x387b2f00, 0x387c0700, 0x387cdf00, 0x387db700, 0x387e8f00, 0x387f6700, 0x38803f00, 0x38811700, 0x3881ef00, 0x3882c700, 0x38839f00, 0x38847700, 0x38854f00, 0x38862700, 0x3886ff00,
+    0x3887d700, 0x3888af00, 0x38898700, 0x388a5f00, 0x388b3700, 0x388c0f00, 0x388ce700, 0x388dbf00, 0x388e9700, 0x388f6f00, 0x38904700, 0x38911f00, 0x3891f700, 0x3892cf00, 0x3893a700, 0x38947f00,
+    0x38955700, 0x38962f00, 0x38970700, 0x3897df00, 0x3898b700, 0x38998f00, 0x389a6700, 0x389b3f00, 0x389c1700, 0x389cef00, 0x389dc700, 0x389e9f00, 0x389f7700, 0x38a04f00, 0x38a12700, 0x38a1ff00,
+    0x38a2d700, 0x38a3af00, 0x38a48700, 0x38a55f00, 0x38a63700, 0x38a70f00, 0x38a7e700, 0x38a8bf00, 0x38a99700, 0x38aa6f00, 0x38ab4700, 0x38ac1f00, 0x38acf700, 0x38adcf00, 0x38aea700, 0x38af7f00,
+    0x38b05700, 0x38b12f00, 0x38b20700, 0x38b2df00, 0x38b3b700, 0x38b48f00, 0x38b56700, 0x38b63f00, 0x38b71700, 0x38b7ef00, 0x38b8c700, 0x38b99f00, 0x38ba7700, 0x38bb4f00, 0x38bc2700, 0x38bcff00,
+    0x38bdd700, 0x38beaf00, 0x38bf8700, 0x38c05f00, 0x38c13700, 0x38c20f00, 0x38c2e700, 0x38c3bf00, 0x38c49700, 0x38c56f00, 0x38c64700, 0x38c71f00, 0x38c7f700, 0x38c8cf00, 0x38c9a700, 0x38ca7f00,
+    0x38cb5700, 0x38cc2f00, 0x38cd0700, 0x38cddf00, 0x38ceb700, 0x38cf8f00, 0x38d06700, 0x38d13f00, 0x38d21700, 0x38d2ef00, 0x38d3c700, 0x38d49f00, 0x38d57700, 0x38d64f00, 0x38d72700, 0x38d7ff00,
+    0x38d8d700, 0x38d9af00, 0x38da8700, 0x38db5f00, 0x38dc3700, 0x38dd0f00, 0x38dde700, 0x38debf00, 0x38df9700, 0x38e06f00, 0x38e14700, 0x38e21f00, 0x38e2f700, 0x38e3cf00, 0x38e4a700, 0x38e57f00,
+    0x38e65700, 0x38e72f00, 0x38e80700, 0x38e8df00, 0x38e9b700, 0x38ea8f00, 0x38eb6700, 0x38ec3f00, 0x38ed1700, 0x38edef00, 0x38eec700, 0x38ef9f00, 0x38f07700, 0x38f14f00, 0x38f22700, 0x38f2ff00,
+    0x38f3d700, 0x38f4af00, 0x38f58700, 0x38f65f00, 0x38f73700, 0x38f80f00, 0x38f8e700, 0x38f9bf00, 0x38fa9700, 0x38fb6f00, 0x38fc4700, 0x38fd1f00, 0x38fdf700, 0x38fecf00, 0x38ffa700, 0x39007f00,
+    0x39015700, 0x39022f00, 0x39030700, 0x3903df00, 0x3904b700, 0x39058f00, 0x39066700, 0x39073f00, 0x39081700, 0x3908ef00, 0x3909c700, 0x390a9f00, 0x390b7700, 0x390c4f00, 0x390d2700, 0x390dff00,
+    0x390ed700, 0x390faf00, 0x39108700, 0x39115f00, 0x39123700, 0x39130f00, 0x3913e700, 0x3914bf00, 0x39159700, 0x39166f00, 0x39174700, 0x39181f00, 0x3918f700, 0x3919cf00, 0x391aa700, 0x391b7f00,
+    0x391c5700, 0x391d2f00, 0x391e0700, 0x391edf00, 0x391fb700, 0x39208f00, 0x39216700, 0x39223f00, 0x39231700, 0x3923ef00, 0x3924c700, 0x39259f00, 0x39267700, 0x39274f00, 0x39282700, 0x3928ff00,
+    0x3929d700, 0x392aaf00, 0x392b8700, 0x392c5f00, 0x392d3700, 0x392e0f00, 0x392ee700, 0x392fbf00, 0x39309700, 0x39316f00, 0x39324700, 0x39331f00, 0x3933f700, 0x3934cf00, 0x3935a700, 0x39367f00,
+    0x39375700, 0x39382f00, 0x39390700, 0x3939df00, 0x393ab700, 0x393b8f00, 0x393c6700, 0x393d3f00, 0x393e1700, 0x393eef00, 0x393fc700, 0x39409f00, 0x39417700, 0x39424f00, 0x39432700, 0x3943ff00,
+    0x3944d700, 0x3945af00, 0x39468700, 0x39475f00, 0x39483700, 0x39490f00, 0x3949e700, 0x394abf00, 0x394b9700, 0x394c6f00, 0x394d4700, 0x394e1f00, 0x394ef700, 0x394fcf00, 0x3950a700, 0x39517f00,
+    0x39525700, 0x39532f00, 0x39540700, 0x3954df00, 0x3955b700, 0x39568f00, 0x39576700, 0x39583f00, 0x39591700, 0x3959ef00, 0x395ac700, 0x395b9f00, 0x395c7700, 0x395d4f00, 0x395e2700, 0x395eff00,
+    0x395fd700, 0x3960af00, 0x39618700, 0x39625f00, 0x39633700, 0x39640f00, 0x3964e700, 0x3965bf00, 0x39669700, 0x39676f00, 0x39684700, 0x39691f00, 0x3969f700, 0x396acf00, 0x396ba700, 0x396c7f00,
+    0x396d5700, 0x396e2f00, 0x396f0700, 0x396fdf00, 0x3970b700, 0x39718f00, 0x39726700, 0x39733f00, 0x39741700, 0x3974ef00, 0x3975c700, 0x39769f00, 0x39777700, 0x39784f00, 0x39792700, 0x3979ff00,
+    0x397ae900, 0x397bd300, 0x397cbd00, 0x397da700, 0x397e9100, 0x397f7b00, 0x39806500, 0x39814f00, 0x39823900, 0x39832300, 0x39840d00, 0x3984f700, 0x3985e100, 0x3986cb00, 0x3987b500, 0x39889f00,
+    0x39898900, 0x398a7300, 0x398b5d00, 0x398c4700, 0x398d3100, 0x398e1b00, 0x398f0500, 0x398fef00, 0x3990d900, 0x3991c300, 0x3992ad00, 0x39939700, 0x39948100, 0x39956b00, 0x39965500, 0x39973f00,
+    0x39982900, 0x39991300, 0x3999fd00, 0x399ae700, 0x399bd100, 0x399cbb00, 0x399da500, 0x399e8f00, 0x399f7900, 0x39a06300, 0x39a14d00, 0x39a23700, 0x39a32100, 0x39a40b00, 0x39a4f500, 0x39a5df00,
+    0x39a6c900, 0x39a7b300, 0x39a89d00, 0x39a98700, 0x39aa7100, 0x39ab5b00, 0x39ac4500, 0x39ad2f00, 0x39ae1900, 0x39af0300, 0x39afed00, 0x39b0d700, 0x39b1c100, 0x39b2ab00, 0x39b39500, 0x39b47f00,
+    0x39b56900, 0x39b65300, 0x39b73d00, 0x39b82700, 0x39b91100, 0x39b9fb00, 0x39bae500, 0x39bbcf00, 0x39bcb900, 0x39bda300, 0x39be8d00, 0x39bf7700, 0x39c06100, 0x39c14b00, 0x39c23500, 0x39c31f00,
+    0x39c40900, 0x39c4f300, 0x39c5dd00, 0x39c6c700, 0x39c7b100, 0x39c89b00, 0x39c98500, 0x39ca6f00, 0x39cb5900, 0x39cc4300, 0x39cd2d00, 0x39ce1700, 0x39cf0100, 0x39cfeb00, 0x39d0d500, 0x39d1bf00,
+    0x39d2a900, 0x39d39300, 0x39d47d00, 0x39d56700, 0x39d65100, 0x39d73b00, 0x39d82500, 0x39d90f00, 0x39d9f900, 0x39dae300, 0x39dbcd00, 0x39dcb700, 0x39dda100, 0x39de8b00, 0x39df7500, 0x39e05f00,
+    0x39e14900, 0x39e23300, 0x39e31d00, 0x39e40700, 0x39e4f100, 0x39e5db00, 0x39e6c500, 0x39e7af00, 0x39e89900, 0x39e98300, 0x39ea6d00, 0x39eb5700, 0x39ec4100, 0x39ed2b00, 0x39ee1500, 0x39eeff00,
+    0x39efe900, 0x39f0d300, 0x39f1bd00, 0x39f2a700, 0x39f39100, 0x39f47b00, 0x39f56500, 0x39f64f00, 0x39f73900, 0x39f82300, 0x39f90d00, 0x39f9f700, 0x39fae100, 0x39fbcb00, 0x39fcb500, 0x39fd9f00,
+    0x39fe8900, 0x39ff7300, 0x3a005d00, 0x3a014700, 0x3a023100, 0x3a031b00, 0x3a040500, 0x3a04ef00, 0x3a05d900, 0x3a06c300, 0x3a07ad00, 0x3a089700, 0x3a098100, 0x3a0a6b00, 0x3a0b5500, 0x3a0c3f00,
+    0x3a0d2900, 0x3a0e1300, 0x3a0efd00, 0x3a0fe700, 0x3a10d100, 0x3a11bb00, 0x3a12a500, 0x3a138f00, 0x3a147900, 0x3a156300, 0x3a164d00, 0x3a173700, 0x3a182100, 0x3a190b00, 0x3a19f500, 0x3a1adf00,
+    0x3a1bc900, 0x3a1cb300, 0x3a1d9d00, 0x3a1e8700, 0x3a1f7100, 0x3a205b00, 0x3a214500, 0x3a222f00, 0x3a231900, 0x3a240300, 0x3a24ed00, 0x3a25d700, 0x3a26c100, 0x3a27ab00, 0x3a289500, 0x3a297f00,
+    0x3a2a6900, 0x3a2b5300, 0x3a2c3d00, 0x3a2d2700, 0x3a2e1100, 0x3a2efb00, 0x3a2fe500, 0x3a30cf00, 0x3a31b900, 0x3a32a300, 0x3a338d00, 0x3a347700, 0x3a356100, 0x3a364b00, 0x3a373500, 0x3a381f00,
+    0x3a390900, 0x3a39f300, 0x3a3add00, 0x3a3bc700, 0x3a3cb100, 0x3a3d9b00, 0x3a3e8500, 0x3a3f6f00, 0x3a405900, 0x3a414300, 0x3a422d00, 0x3a431700, 0x3a440100, 0x3a44eb00, 0x3a45d500, 0x3a46bf00,
+    0x3a47a900, 0x3a489300, 0x3a497d00, 0x3a4a6700, 0x3a4b5100, 0x3a4c3b00, 0x3a4d2500, 0x3a4e0f00, 0x3a4ef900, 0x3a4fe300, 0x3a50cd00, 0x3a51b700, 0x3a52a100, 0x3a538b00, 0x3a547500, 0x3a555f00,
+    0x3a564900, 0x3a573300, 0x3a581d00, 0x3a590700, 0x3a59f100, 0x3a5adb00, 0x3a5bc500, 0x3a5caf00, 0x3a5d9900, 0x3a5e8300, 0x3a5f6d00, 0x3a605700, 0x3a614100, 0x3a622b00, 0x3a631500, 0x3a63ff00,
+    0x3a64e900, 0x3a65d300, 0x3a66bd00, 0x3a67a700, 0x3a689100, 0x3a697b00, 0x3a6a6500, 0x3a6b4f00, 0x3a6c3900, 0x3a6d2300, 0x3a6e0d00, 0x3a6ef700, 0x3a6fe100, 0x3a70cb00, 0x3a71b500, 0x3a729f00,
+    0x3a738900, 0x3a747300, 0x3a755d00, 0x3a764700, 0x3a773100, 0x3a781b00, 0x3a790500, 0x3a79ef00, 0x3a7ad900, 0x3a7bc300, 0x3a7cad00, 0x3a7d9700, 0x3a7e8100, 0x3a7f6b00, 0x3a805500, 0x3a813f00,
+    0x3a822900, 0x3a831300, 0x3a83fd00, 0x3a84e700, 0x3a85d100, 0x3a86bb00, 0x3a87a500, 0x3a888f00, 0x3a897900, 0x3a8a6300, 0x3a8b4d00, 0x3a8c3700, 0x3a8d2100, 0x3a8e0b00, 0x3a8ef500, 0x3a8fdf00,
+    0x3a90c900, 0x3a91b300, 0x3a929d00, 0x3a938700, 0x3a947100, 0x3a955b00, 0x3a964500, 0x3a972f00, 0x3a981900, 0x3a990300, 0x3a99ed00, 0x3a9ad700, 0x3a9bc100, 0x3a9cab00, 0x3a9d9500, 0x3a9e7f00,
+    0x3a9f6900, 0x3aa05300, 0x3aa13d00, 0x3aa22700, 0x3aa31100, 0x3aa3fb00, 0x3aa4e500, 0x3aa5cf00, 0x3aa6b900, 0x3aa7a300, 0x3aa88d00, 0x3aa97700, 0x3aaa6100, 0x3aab4b00, 0x3aac3500, 0x3aad1f00,
+    0x3aae0900, 0x3aaef300, 0x3aafdd00, 0x3ab0c700, 0x3ab1b100, 0x3ab29b00, 0x3ab38500, 0x3ab46f00, 0x3ab55900, 0x3ab64300, 0x3ab72d00, 0x3ab81700, 0x3ab90100, 0x3ab9eb00, 0x3abad500, 0x3abbbf00,
+    0x3abca900, 0x3abd9300, 0x3abe7d00, 0x3abf6700, 0x3ac05100, 0x3ac13b00, 0x3ac22500, 0x3ac30f00, 0x3ac3f900, 0x3ac4e300, 0x3ac5cd00, 0x3ac6b700, 0x3ac7a100, 0x3ac88b00, 0x3ac97500, 0x3aca5f00,
+    0x3acb4900, 0x3acc3300, 0x3acd1d00, 0x3ace0700, 0x3acef100, 0x3acfdb00, 0x3ad0c500, 0x3ad1af00, 0x3ad29900, 0x3ad38300, 0x3ad46d00, 0x3ad55700, 0x3ad64100, 0x3ad72b00, 0x3ad81500, 0x3ad8ff00,
+    0x3ad9e900, 0x3adad300, 0x3adbbd00, 0x3adca700, 0x3add9100, 0x3ade7b00, 0x3adf6500, 0x3ae04f00, 0x3ae13900, 0x3ae22300, 0x3ae30d00, 0x3ae3f700, 0x3ae4e100, 0x3ae5cb00, 0x3ae6b500, 0x3ae79f00,
+    0x3ae88900, 0x3ae97300, 0x3aea5d00, 0x3aeb4700, 0x3aec3100, 0x3aed1b00, 0x3aee0500, 0x3aeeef00, 0x3aefd900, 0x3af0c300, 0x3af1ad00, 0x3af29700, 0x3af38100, 0x3af46b00, 0x3af55500, 0x3af63f00,
+    0x3af72900, 0x3af81300, 0x3af8fd00, 0x3af9e700, 0x3afad100, 0x3afbbb00, 0x3afca500, 0x3afd8f00, 0x3afe7900, 0x3aff6300, 0x3b004e00, 0x3b013800, 0x3b022200, 0x3b030c00, 0x3b03f600, 0x3b04e000,
+    0x3b05ca00, 0x3b06b400, 0x3b079e00, 0x3b088800, 0x3b097200, 0x3b0a5c00, 0x3b0b4600, 0x3b0c3000, 0x3b0d1a00, 0x3b0e0400, 0x3b0eee00, 0x3b0fd800, 0x3b10c200, 0x3b11ac00, 0x3b129600, 0x3b138000,
+    0x3b146a00, 0x3b155400, 0x3b163e00, 0x3b172800, 0x3b181200, 0x3b18fc00, 0x3b19e600, 0x3b1ad000, 0x3b1bba00, 0x3b1ca400, 0x3b1d8e00, 0x3b1e7800, 0x3b1f6200, 0x3b204c00, 0x3b213600, 0x3b222000,
+    0x3b230a00, 0x3b23f400, 0x3b24de00, 0x3b25c800, 0x3b26b200, 0x3b279c00, 0x3b288600, 0x3b297000, 0x3b2a5a00, 0x3b2b4400, 0x3b2c2e00, 0x3b2d1800, 0x3b2e0200, 0x3b2eec00, 0x3b2fd600, 0x3b30c000,
+    0x3b31aa00, 0x3b329400, 0x3b337e00, 0x3b346800, 0x3b355200, 0x3b363c00, 0x3b372600, 0x3b381000, 0x3b38fa00, 0x3b39e400, 0x3b3ace00, 0x3b3bb800, 0x3b3ca200, 0x3b3d8c00, 0x3b3e7600, 0x3b3f6000,
+    0x3b404a00, 0x3b413400, 0x3b421e00, 0x3b430800, 0x3b43f200, 0x3b44dc00, 0x3b45c600, 0x3b46b000, 0x3b479a00, 0x3b488400, 0x3b496e00, 0x3b4a5800, 0x3b4b4200, 0x3b4c2c00, 0x3b4d1600, 0x3b4e0000,
+    0x3b4f0000, 0x3b500000, 0x3b510000, 0x3b520000, 0x3b530000, 0x3b540000, 0x3b550000, 0x3b560000, 0x3b570000, 0x3b580000, 0x3b590000, 0x3b5a0000, 0x3b5b0000, 0x3b5c0000, 0x3b5d0000, 0x3b5e0000,
+    0x3b5f0000, 0x3b600000, 0x3b610000, 0x3b620000, 0x3b630000, 0x3b640000, 0x3b650000, 0x3b660000, 0x3b670000, 0x3b680000, 0x3b690000, 0x3b6a0000, 0x3b6b0000, 0x3b6c0000, 0x3b6d0000, 0x3b6e0000,
+    0x3b6f0000, 0x3b700000, 0x3b710000, 0x3b720000, 0x3b730000, 0x3b740000, 0x3b750000, 0x3b760000, 0x3b770000, 0x3b780000, 0x3b790000, 0x3b7a0000, 0x3b7b0000, 0x3b7c0000, 0x3b7d0000, 0x3b7e0000,
+    0x3b7f0000, 0x3b800000, 0x3b810000, 0x3b820000, 0x3b830000, 0x3b840000, 0x3b850000, 0x3b860000, 0x3b870000, 0x3b880000, 0x3b890000, 0x3b8a0000, 0x3b8b0000, 0x3b8c0000, 0x3b8d0000, 0x3b8e0000,
+    0x3b8f0000, 0x3b900000, 0x3b910000, 0x3b920000, 0x3b930000, 0x3b940000, 0x3b950000, 0x3b960000, 0x3b970000, 0x3b980000, 0x3b990000, 0x3b9a0000, 0x3b9b0000, 0x3b9c0000, 0x3b9d0000, 0x3b9e0000,
+    0x3b9f0000, 0x3ba00000, 0x3ba10000, 0x3ba20000, 0x3ba30000, 0x3ba40000, 0x3ba50000, 0x3ba60000, 0x3ba70000, 0x3ba80000, 0x3ba90000, 0x3baa0000, 0x3bab0000, 0x3bac0000, 0x3bad0000, 0x3bae0000,
+    0x3baf0000, 0x3bb00000, 0x3bb10000, 0x3bb20000, 0x3bb30000, 0x3bb40000, 0x3bb50000, 0x3bb60000, 0x3bb70000, 0x3bb80000, 0x3bb90000, 0x3bba0000, 0x3bbb0000, 0x3bbc0000, 0x3bbd0000, 0x3bbe0000,
+    0x3bbf0000, 0x3bc00000, 0x3bc10000, 0x3bc20000, 0x3bc30000, 0x3bc40000, 0x3bc50000, 0x3bc60000, 0x3bc70000, 0x3bc80000, 0x3bc90000, 0x3bca0000, 0x3bcb0000, 0x3bcc0000, 0x3bcd0000, 0x3bce0000,
+    0x3bcf0000, 0x3bd00000, 0x3bd10000, 0x3bd20000, 0x3bd30000, 0x3bd40000, 0x3bd50000, 0x3bd60000, 0x3bd70000, 0x3bd80000, 0x3bd90000, 0x3bda0000, 0x3bdb0000, 0x3bdc0000, 0x3bdd0000, 0x3bde0000,
+    0x3bdf0000, 0x3be00000, 0x3be10000, 0x3be20000, 0x3be30000, 0x3be40000, 0x3be50000, 0x3be60000, 0x3be70000, 0x3be80000, 0x3be90000, 0x3bea0000, 0x3beb0000, 0x3bec0000, 0x3bed0000, 0x3bee0000,
+    0x3bef0000, 0x3bf00000, 0x3bf10000, 0x3bf20000, 0x3bf30000, 0x3bf40000, 0x3bf50000, 0x3bf60000, 0x3bf70000, 0x3bf80000, 0x3bf90000, 0x3bfa0000, 0x3bfb0000, 0x3bfc0000, 0x3bfd0000, 0x3bfe0000,
+    0x3bff0000, 0x3c000000, 0x3c010000, 0x3c020000, 0x3c030000, 0x3c040000, 0x3c050000, 0x3c060000, 0x3c070000, 0x3c080000, 0x3c090000, 0x3c0a0000, 0x3c0b0000, 0x3c0c0000, 0x3c0d0000, 0x3c0e0000,
+    0x3c0f0000, 0x3c100000, 0x3c110000, 0x3c120000, 0x3c130000, 0x3c140000, 0x3c150000, 0x3c160000, 0x3c170000, 0x3c180000, 0x3c190000, 0x3c1a0000, 0x3c1b0000, 0x3c1c0000, 0x3c1d0000, 0x3c1e0000,
+    0x3c1f0000, 0x3c200000, 0x3c210000, 0x3c220000, 0x3c230000, 0x3c240000, 0x3c250000, 0x3c260000, 0x3c270000, 0x3c280000, 0x3c290000, 0x3c2a0000, 0x3c2b0000, 0x3c2c0000, 0x3c2d0000, 0x3c2e0000,
+    0x3c2f0000, 0x3c300000, 0x3c310000, 0x3c320000, 0x3c330000, 0x3c340000, 0x3c350000, 0x3c360000, 0x3c370000, 0x3c380000, 0x3c390000, 0x3c3a0000, 0x3c3b0000, 0x3c3c0000, 0x3c3d0000, 0x3c3e0000,
+    0x3c3f0000, 0x3c400000, 0x3c410000, 0x3c420000, 0x3c430000, 0x3c440000, 0x3c450000, 0x3c460000, 0x3c470000, 0x3c480000, 0x3c490000, 0x3c4a0000, 0x3c4b0000, 0x3c4c0000, 0x3c4d0000, 0x3c4e0000,
+    0x3c4f0000, 0x3c500000, 0x3c510000, 0x3c520000, 0x3c530000, 0x3c540000, 0x3c550000, 0x3c560000, 0x3c570000, 0x3c580000, 0x3c590000, 0x3c5a0000, 0x3c5b0000, 0x3c5c0000, 0x3c5d0000, 0x3c5e0000,
+    0x3c5f0000, 0x3c600000, 0x3c610000, 0x3c620000, 0x3c630000, 0x3c640000, 0x3c650000, 0x3c660000, 0x3c670000, 0x3c680000, 0x3c690000, 0x3c6a0000, 0x3c6b0000, 0x3c6c0000, 0x3c6d0000, 0x3c6e0000,
+    0x3c6f0000, 0x3c700000, 0x3c710000, 0x3c720000, 0x3c730000, 0x3c740000, 0x3c750000, 0x3c760000, 0x3c770000, 0x3c780000, 0x3c790000, 0x3c7a0000, 0x3c7b0000, 0x3c7c0000, 0x3c7d0000, 0x3c7e0000,
+    0x3c7f0000, 0x3c800000, 0x3c810000, 0x3c820000, 0x3c830000, 0x3c840000, 0x3c850000, 0x3c860000, 0x3c870000, 0x3c880000, 0x3c890000, 0x3c8a0000, 0x3c8b0000, 0x3c8c0000, 0x3c8d0000, 0x3c8e0000,
+    0x3c8f0000, 0x3c900000, 0x3c910000, 0x3c920000, 0x3c930000, 0x3c940000, 0x3c950000, 0x3c960000, 0x3c970000, 0x3c980000, 0x3c990000, 0x3c9a0000, 0x3c9b0000, 0x3c9c0000, 0x3c9d0000, 0x3c9e0000,
+    0x3c9f0000, 0x3ca00000, 0x3ca10000, 0x3ca20000, 0x3ca30000, 0x3ca40000, 0x3ca50000, 0x3ca60000, 0x3ca70000, 0x3ca80000, 0x3ca90000, 0x3caa0000, 0x3cab0000, 0x3cac0000, 0x3cad0000, 0x3cae0000,
+    0x3caf0000, 0x3cb00000, 0x3cb10000, 0x3cb20000, 0x3cb30000, 0x3cb40000, 0x3cb50000, 0x3cb60000, 0x3cb70000, 0x3cb80000, 0x3cb90000, 0x3cba0000, 0x3cbb0000, 0x3cbc0000, 0x3cbd0000, 0x3cbe0000,
+    0x3cbf0000, 0x3cc00000, 0x3cc10000, 0x3cc20000, 0x3cc30000, 0x3cc40000, 0x3cc50000, 0x3cc60000, 0x3cc70000, 0x3cc80000, 0x3cc90000, 0x3cca0000, 0x3ccb0000, 0x3ccc0000, 0x3ccd0000, 0x3cce0000,
+    0x3ccf0000, 0x3cd00000, 0x3cd10000, 0x3cd20000, 0x3cd30000, 0x3cd40000, 0x3cd50000, 0x3cd60000, 0x3cd70000, 0x3cd80000, 0x3cd90000, 0x3cda0000, 0x3cdb0000, 0x3cdc0000, 0x3cdd0000, 0x3cde0000,
+    0x3cdf0000, 0x3ce00000, 0x3ce10000, 0x3ce20000, 0x3ce30000, 0x3ce40000, 0x3ce50000, 0x3ce60000, 0x3ce70000, 0x3ce80000, 0x3ce90000, 0x3cea0000, 0x3ceb0000, 0x3cec0000, 0x3ced0000, 0x3cee0000,
+    0x3cef0000, 0x3cf00000, 0x3cf10000, 0x3cf20000, 0x3cf30000, 0x3cf40000, 0x3cf50000, 0x3cf60000, 0x3cf70000, 0x3cf80000, 0x3cf90000, 0x3cfa0000, 0x3cfb0000, 0x3cfc0000, 0x3cfd0000, 0x3cfe0000,
+    0x3cff0000, 0x3d000000, 0x3d010000, 0x3d020000, 0x3d030000, 0x3d040000, 0x3d050000, 0x3d060000, 0x3d070000, 0x3d080000, 0x3d090000, 0x3d0a0000, 0x3d0b0000, 0x3d0c0000, 0x3d0d0000, 0x3d0e0000,
+    0x3d0f0000, 0x3d100000, 0x3d110000, 0x3d120000, 0x3d130000, 0x3d140000, 0x3d150000, 0x3d160000, 0x3d170000, 0x3d180000, 0x3d190000, 0x3d1a0000, 0x3d1b0000, 0x3d1c0000, 0x3d1d0000, 0x3d1e0000,
+    0x3d1f0000, 0x3d200000, 0x3d210000, 0x3d220000, 0x3d230000, 0x3d240000, 0x3d250000, 0x3d260000, 0x3d270000, 0x3d280000, 0x3d290000, 0x3d2a0000, 0x3d2b0000, 0x3d2c0000, 0x3d2d0000, 0x3d2e0000,
+    0x3d2f0000, 0x3d300000, 0x3d310000, 0x3d320000, 0x3d330000, 0x3d340000, 0x3d350000, 0x3d360000, 0x3d370000, 0x3d380000, 0x3d390000, 0x3d3a0000, 0x3d3b0000, 0x3d3c0000, 0x3d3d0000, 0x3d3e0000,
+    0x3d3f0000, 0x3d400000, 0x3d410000, 0x3d420000, 0x3d430000, 0x3d440000, 0x3d450000, 0x3d460000, 0x3d470000, 0x3d480000, 0x3d490000, 0x3d4a0000, 0x3d4b0000, 0x3d4c0000, 0x3d4d0000, 0x3d4e0000,
+    0x3d4f2200, 0x3d504400, 0x3d516600, 0x3d528800, 0x3d53aa00, 0x3d54cc00, 0x3d55ee00, 0x3d571000, 0x3d583200, 0x3d595400, 0x3d5a7600, 0x3d5b9800, 0x3d5cba00, 0x3d5ddc00, 0x3d5efe00, 0x3d602000,
+    0x3d614200, 0x3d626400, 0x3d638600, 0x3d64a800, 0x3d65ca00, 0x3d66ec00, 0x3d680e00, 0x3d693000, 0x3d6a5200, 0x3d6b7400, 0x3d6c9600, 0x3d6db800, 0x3d6eda00, 0x3d6ffc00, 0x3d711e00, 0x3d724000,
+    0x3d736200, 0x3d748400, 0x3d75a600, 0x3d76c800, 0x3d77ea00, 0x3d790c00, 0x3d7a2e00, 0x3d7b5000, 0x3d7c7200, 0x3d7d9400, 0x3d7eb600, 0x3d7fd800, 0x3d80fa00, 0x3d821c00, 0x3d833e00, 0x3d846000,
+    0x3d858200, 0x3d86a400, 0x3d87c600, 0x3d88e800, 0x3d8a0a00, 0x3d8b2c00, 0x3d8c4e00, 0x3d8d7000, 0x3d8e9200, 0x3d8fb400, 0x3d90d600, 0x3d91f800, 0x3d931a00, 0x3d943c00, 0x3d955e00, 0x3d968000,
+    0x3d97a200, 0x3d98c400, 0x3d99e600, 0x3d9b0800, 0x3d9c2a00, 0x3d9d4c00, 0x3d9e6e00, 0x3d9f9000, 0x3da0b200, 0x3da1d400, 0x3da2f600, 0x3da41800, 0x3da53a00, 0x3da65c00, 0x3da77e00, 0x3da8a000,
+    0x3da9c200, 0x3daae400, 0x3dac0600, 0x3dad2800, 0x3dae4a00, 0x3daf6c00, 0x3db08e00, 0x3db1b000, 0x3db2d200, 0x3db3f400, 0x3db51600, 0x3db63800, 0x3db75a00, 0x3db87c00, 0x3db99e00, 0x3dbac000,
+    0x3dbbe200, 0x3dbd0400, 0x3dbe2600, 0x3dbf4800, 0x3dc06a00, 0x3dc18c00, 0x3dc2ae00, 0x3dc3d000, 0x3dc4f200, 0x3dc61400, 0x3dc73600, 0x3dc85800, 0x3dc97a00, 0x3dca9c00, 0x3dcbbe00, 0x3dcce000,
+    0x3dce0200, 0x3dcf2400, 0x3dd04600, 0x3dd16800, 0x3dd28a00, 0x3dd3ac00, 0x3dd4ce00, 0x3dd5f000, 0x3dd71200, 0x3dd83400, 0x3dd95600, 0x3dda7800, 0x3ddb9a00, 0x3ddcbc00, 0x3dddde00, 0x3ddf0000,
+    0x3de02200, 0x3de14400, 0x3de26600, 0x3de38800, 0x3de4aa00, 0x3de5cc00, 0x3de6ee00, 0x3de81000, 0x3de93200, 0x3dea5400, 0x3deb7600, 0x3dec9800, 0x3dedba00, 0x3deedc00, 0x3deffe00, 0x3df12000,
+    0x3df24200, 0x3df36400, 0x3df48600, 0x3df5a800, 0x3df6ca00, 0x3df7ec00, 0x3df90e00, 0x3dfa3000, 0x3dfb5200, 0x3dfc7400, 0x3dfd9600, 0x3dfeb800, 0x3dffda00, 0x3e00fc00, 0x3e021e00, 0x3e034000,
+    0x3e046200, 0x3e058400, 0x3e06a600, 0x3e07c800, 0x3e08ea00, 0x3e0a0c00, 0x3e0b2e00, 0x3e0c5000, 0x3e0d7200, 0x3e0e9400, 0x3e0fb600, 0x3e10d800, 0x3e11fa00, 0x3e131c00, 0x3e143e00, 0x3e156000,
+    0x3e168200, 0x3e17a400, 0x3e18c600, 0x3e19e800, 0x3e1b0a00, 0x3e1c2c00, 0x3e1d4e00, 0x3e1e7000, 0x3e1f9200, 0x3e20b400, 0x3e21d600, 0x3e22f800, 0x3e241a00, 0x3e253c00, 0x3e265e00, 0x3e278000,
+    0x3e28a200, 0x3e29c400, 0x3e2ae600, 0x3e2c0800, 0x3e2d2a00, 0x3e2e4c00, 0x3e2f6e00, 0x3e309000, 0x3e31b200, 0x3e32d400, 0x3e33f600, 0x3e351800, 0x3e363a00, 0x3e375c00, 0x3e387e00, 0x3e39a000,
+    0x3e3ac200, 0x3e3be400, 0x3e3d0600, 0x3e3e2800, 0x3e3f4a00, 0x3e406c00, 0x3e418e00, 0x3e42b000, 0x3e43d200, 0x3e44f400, 0x3e461600, 0x3e473800, 0x3e485a00, 0x3e497c00, 0x3e4a9e00, 0x3e4bc000,
+    0x3e4ce200, 0x3e4e0400, 0x3e4f2600, 0x3e504800, 0x3e516a00, 0x3e528c00, 0x3e53ae00, 0x3e54d000, 0x3e55f200, 0x3e571400, 0x3e583600, 0x3e595800, 0x3e5a7a00, 0x3e5b9c00, 0x3e5cbe00, 0x3e5de000,
+    0x3e5f0200, 0x3e602400, 0x3e614600, 0x3e626800, 0x3e638a00, 0x3e64ac00, 0x3e65ce00, 0x3e66f000, 0x3e681200, 0x3e693400, 0x3e6a5600, 0x3e6b7800, 0x3e6c9a00, 0x3e6dbc00, 0x3e6ede00, 0x3e700000,
+    0x3e712100, 0x3e724300, 0x3e736500, 0x3e748700, 0x3e75a900, 0x3e76cb00, 0x3e77ed00, 0x3e790f00, 0x3e7a3100, 0x3e7b5300, 0x3e7c7500, 0x3e7d9700, 0x3e7eb900, 0x3e7fdb00, 0x3e80fd00, 0x3e821f00,
+    0x3e834100, 0x3e846300, 0x3e858500, 0x3e86a700, 0x3e87c900, 0x3e88eb00, 0x3e8a0d00, 0x3e8b2f00, 0x3e8c5100, 0x3e8d7300, 0x3e8e9500, 0x3e8fb700, 0x3e90d900, 0x3e91fb00, 0x3e931d00, 0x3e943f00,
+    0x3e956100, 0x3e968300, 0x3e97a500, 0x3e98c700, 0x3e99e900, 0x3e9b0b00, 0x3e9c2d00, 0x3e9d4f00, 0x3e9e7100, 0x3e9f9300, 0x3ea0b500, 0x3ea1d700, 0x3ea2f900, 0x3ea41b00, 0x3ea53d00, 0x3ea65f00,
+    0x3ea78100, 0x3ea8a300, 0x3ea9c500, 0x3eaae700, 0x3eac0900, 0x3ead2b00, 0x3eae4d00, 0x3eaf6f00, 0x3eb09100, 0x3eb1b300, 0x3eb2d500, 0x3eb3f700, 0x3eb51900, 0x3eb63b00, 0x3eb75d00, 0x3eb87f00,
+    0x3eb9a100, 0x3ebac300, 0x3ebbe500, 0x3ebd0700, 0x3ebe2900, 0x3ebf4b00, 0x3ec06d00, 0x3ec18f00, 0x3ec2b100, 0x3ec3d300, 0x3ec4f500, 0x3ec61700, 0x3ec73900, 0x3ec85b00, 0x3ec97d00, 0x3eca9f00,
+    0x3ecbc100, 0x3ecce300, 0x3ece0500, 0x3ecf2700, 0x3ed04900, 0x3ed16b00, 0x3ed28d00, 0x3ed3af00, 0x3ed4d100, 0x3ed5f300, 0x3ed71500, 0x3ed83700, 0x3ed95900, 0x3eda7b00, 0x3edb9d00, 0x3edcbf00,
+    0x3edde100, 0x3edf0300, 0x3ee02500, 0x3ee14700, 0x3ee26900, 0x3ee38b00, 0x3ee4ad00, 0x3ee5cf00, 0x3ee6f100, 0x3ee81300, 0x3ee93500, 0x3eea5700, 0x3eeb7900, 0x3eec9b00, 0x3eedbd00, 0x3eeedf00,
+    0x3ef00100, 0x3ef12300, 0x3ef24500, 0x3ef36700, 0x3ef48900, 0x3ef5ab00, 0x3ef6cd00, 0x3ef7ef00, 0x3ef91100, 0x3efa3300, 0x3efb5500, 0x3efc7700, 0x3efd9900, 0x3efebb00, 0x3effdd00, 0x3f00ff00,
+    0x3f022100, 0x3f034300, 0x3f046500, 0x3f058700, 0x3f06a900, 0x3f07cb00, 0x3f08ed00, 0x3f0a0f00, 0x3f0b3100, 0x3f0c5300, 0x3f0d7500, 0x3f0e9700, 0x3f0fb900, 0x3f10db00, 0x3f11fd00, 0x3f131f00,
+    0x3f144100, 0x3f156300, 0x3f168500, 0x3f17a700, 0x3f18c900, 0x3f19eb00, 0x3f1b0d00, 0x3f1c2f00, 0x3f1d5100, 0x3f1e7300, 0x3f1f9500, 0x3f20b700, 0x3f21d900, 0x3f22fb00, 0x3f241d00, 0x3f253f00,
+    0x3f266100, 0x3f278300, 0x3f28a500, 0x3f29c700, 0x3f2ae900, 0x3f2c0b00, 0x3f2d2d00, 0x3f2e4f00, 0x3f2f7100, 0x3f309300, 0x3f31b500, 0x3f32d700, 0x3f33f900, 0x3f351b00, 0x3f363d00, 0x3f375f00,
+    0x3f388100, 0x3f39a300, 0x3f3ac500, 0x3f3be700, 0x3f3d0900, 0x3f3e2b00, 0x3f3f4d00, 0x3f406f00, 0x3f419100, 0x3f42b300, 0x3f43d500, 0x3f44f700, 0x3f461900, 0x3f473b00, 0x3f485d00, 0x3f497f00,
+    0x3f4aa100, 0x3f4bc300, 0x3f4ce500, 0x3f4e0700, 0x3f4f2900, 0x3f504b00, 0x3f516d00, 0x3f528f00, 0x3f53b100, 0x3f54d300, 0x3f55f500, 0x3f571700, 0x3f583900, 0x3f595b00, 0x3f5a7d00, 0x3f5b9f00,
+    0x3f5cc100, 0x3f5de300, 0x3f5f0500, 0x3f602700, 0x3f614900, 0x3f626b00, 0x3f638d00, 0x3f64af00, 0x3f65d100, 0x3f66f300, 0x3f681500, 0x3f693700, 0x3f6a5900, 0x3f6b7b00, 0x3f6c9d00, 0x3f6dbf00,
+    0x3f6ee100, 0x3f700300, 0x3f712500, 0x3f724700, 0x3f736900, 0x3f748b00, 0x3f75ad00, 0x3f76cf00, 0x3f77f100, 0x3f791300, 0x3f7a3500, 0x3f7b5700, 0x3f7c7900, 0x3f7d9b00, 0x3f7ebd00, 0x3f7fdf00,
+    0x3f810100, 0x3f822300, 0x3f834500, 0x3f846700, 0x3f858900, 0x3f86ab00, 0x3f87cd00, 0x3f88ef00, 0x3f8a1100, 0x3f8b3300, 0x3f8c5500, 0x3f8d7700, 0x3f8e9900, 0x3f8fbb00, 0x3f90dd00, 0x3f91ff00,
+    0x3f935300, 0x3f94a700, 0x3f95fb00, 0x3f974f00, 0x3f98a300, 0x3f99f700, 0x3f9b4b00, 0x3f9c9f00, 0x3f9df300, 0x3f9f4700, 0x3fa09b00, 0x3fa1ef00, 0x3fa34300, 0x3fa49700, 0x3fa5eb00, 0x3fa73f00,
+    0x3fa89300, 0x3fa9e700, 0x3fab3b00, 0x3fac8f00, 0x3fade300, 0x3faf3700, 0x3fb08b00, 0x3fb1df00, 0x3fb33300, 0x3fb48700, 0x3fb5db00, 0x3fb72f00, 0x3fb88300, 0x3fb9d700, 0x3fbb2b00, 0x3fbc7f00,
+    0x3fbdd300, 0x3fbf2700, 0x3fc07b00, 0x3fc1cf00, 0x3fc32300, 0x3fc47700, 0x3fc5cb00, 0x3fc71f00, 0x3fc87300, 0x3fc9c700, 0x3fcb1b00, 0x3fcc6f00, 0x3fcdc300, 0x3fcf1700, 0x3fd06b00, 0x3fd1bf00,
+    0x3fd31300, 0x3fd46700, 0x3fd5bb00, 0x3fd70f00, 0x3fd86300, 0x3fd9b700, 0x3fdb0b00, 0x3fdc5f00, 0x3fddb300, 0x3fdf0700, 0x3fe05b00, 0x3fe1af00, 0x3fe30300, 0x3fe45700, 0x3fe5ab00, 0x3fe6ff00,
+    0x3fe85300, 0x3fe9a700, 0x3feafb00, 0x3fec4f00, 0x3feda300, 0x3feef700, 0x3ff04b00, 0x3ff19f00, 0x3ff2f300, 0x3ff44700, 0x3ff59b00, 0x3ff6ef00, 0x3ff84300, 0x3ff99700, 0x3ffaeb00, 0x3ffc3f00,
+    0x3ffd9300, 0x3ffee700, 0x40003b00, 0x40018f00, 0x4002e300, 0x40043700, 0x40058b00, 0x4006df00, 0x40083300, 0x40098700, 0x400adb00, 0x400c2f00, 0x400d8300, 0x400ed700, 0x40102b00, 0x40117f00,
+    0x4012d300, 0x40142700, 0x40157b00, 0x4016cf00, 0x40182300, 0x40197700, 0x401acb00, 0x401c1f00, 0x401d7300, 0x401ec700, 0x40201b00, 0x40216f00, 0x4022c300, 0x40241700, 0x40256b00, 0x4026bf00,
+    0x40281300, 0x40296700, 0x402abb00, 0x402c0f00, 0x402d6300, 0x402eb700, 0x40300b00, 0x40315f00, 0x4032b300, 0x40340700, 0x40355b00, 0x4036af00, 0x40380300, 0x40395700, 0x403aab00, 0x403bff00,
+    0x403d5300, 0x403ea700, 0x403ffb00, 0x40414f00, 0x4042a300, 0x4043f700, 0x40454b00, 0x40469f00, 0x4047f300, 0x40494700, 0x404a9b00, 0x404bef00, 0x404d4300, 0x404e9700, 0x404feb00, 0x40513f00,
+    0x40529300, 0x4053e700, 0x40553b00, 0x40568f00, 0x4057e300, 0x40593700, 0x405a8b00, 0x405bdf00, 0x405d3300, 0x405e8700, 0x405fdb00, 0x40612f00, 0x40628300, 0x4063d700, 0x40652b00, 0x40667f00,
+    0x4067d300, 0x40692700, 0x406a7b00, 0x406bcf00, 0x406d2300, 0x406e7700, 0x406fcb00, 0x40711f00, 0x40727300, 0x4073c700, 0x40751b00, 0x40766f00, 0x4077c300, 0x40791700, 0x407a6b00, 0x407bbf00,
+    0x407d1300, 0x407e6700, 0x407fbb00, 0x40810f00, 0x40826300, 0x4083b700, 0x40850b00, 0x40865f00, 0x4087b300, 0x40890700, 0x408a5b00, 0x408baf00, 0x408d0300, 0x408e5700, 0x408fab00, 0x4090ff00,
+    0x40925300, 0x4093a700, 0x4094fb00, 0x40964f00, 0x4097a300, 0x4098f700, 0x409a4b00, 0x409b9f00, 0x409cf300, 0x409e4700, 0x409f9b00, 0x40a0ef00, 0x40a24300, 0x40a39700, 0x40a4eb00, 0x40a63f00,
+    0x40a79300, 0x40a8e700, 0x40aa3b00, 0x40ab8f00, 0x40ace300, 0x40ae3700, 0x40af8b00, 0x40b0df00, 0x40b23300, 0x40b38700, 0x40b4db00, 0x40b62f00, 0x40b78300, 0x40b8d700, 0x40ba2b00, 0x40bb7f00,
+    0x40bcd300, 0x40be2700, 0x40bf7b00, 0x40c0cf00, 0x40c22300, 0x40c37700, 0x40c4cb00, 0x40c61f00, 0x40c77300, 0x40c8c700, 0x40ca1b00, 0x40cb6f00, 0x40ccc300, 0x40ce1700, 0x40cf6b00, 0x40d0bf00,
+    0x40d21300, 0x40d36700, 0x40d4bb00, 0x40d60f00, 0x40d76300, 0x40d8b700, 0x40da0b00, 0x40db5f00, 0x40dcb300, 0x40de0700, 0x40df5b00, 0x40e0af00, 0x40e20300, 0x40e35700, 0x40e4ab00, 0x40e5ff00,
+    0x40e75300, 0x40e8a700, 0x40e9fb00, 0x40eb4f00, 0x40eca300, 0x40edf700, 0x40ef4b00, 0x40f09f00, 0x40f1f300, 0x40f34700, 0x40f49b00, 0x40f5ef00, 0x40f74300, 0x40f89700, 0x40f9eb00, 0x40fb3f00,
+    0x40fc9300, 0x40fde700, 0x40ff3b00, 0x41008f00, 0x4101e300, 0x41033700, 0x41048b00, 0x4105df00, 0x41073300, 0x41088700, 0x4109db00, 0x410b2f00, 0x410c8300, 0x410dd700, 0x410f2b00, 0x41107f00,
+    0x4111d300, 0x41132700, 0x41147b00, 0x4115cf00, 0x41172300, 0x41187700, 0x4119cb00, 0x411b1f00, 0x411c7300, 0x411dc700, 0x411f1b00, 0x41206f00, 0x4121c300, 0x41231700, 0x41246b00, 0x4125bf00,
+    0x41271300, 0x41286700, 0x4129bb00, 0x412b0f00, 0x412c6300, 0x412db700, 0x412f0b00, 0x41305f00, 0x4131b300, 0x41330700, 0x41345b00, 0x4135af00, 0x41370300, 0x41385700, 0x4139ab00, 0x413aff00,
+    0x413c5300, 0x413da700, 0x413efb00, 0x41404f00, 0x4141a300, 0x4142f700, 0x41444b00, 0x41459f00, 0x4146f300, 0x41484700, 0x41499b00, 0x414aef00, 0x414c4300, 0x414d9700, 0x414eeb00, 0x41503f00,
+    0x41519300, 0x4152e700, 0x41543b00, 0x41558f00, 0x4156e300, 0x41583700, 0x41598b00, 0x415adf00, 0x415c3300, 0x415d8700, 0x415edb00, 0x41602f00, 0x41618300, 0x4162d700, 0x41642b00, 0x41657f00,
+    0x4166d300, 0x41682700, 0x41697b00, 0x416acf00, 0x416c2300, 0x416d7700, 0x416ecb00, 0x41701f00, 0x41717300, 0x4172c700, 0x41741b00, 0x41756f00, 0x4176c300, 0x41781700, 0x41796b00, 0x417abf00,
+    0x417c1300, 0x417d6700, 0x417ebb00, 0x41800f00, 0x41816300, 0x4182b700, 0x41840b00, 0x41855f00, 0x4186b300, 0x41880700, 0x41895b00, 0x418aaf00, 0x418c0300, 0x418d5700, 0x418eab00, 0x418fff00,
+    0x41915300, 0x4192a700, 0x4193fb00, 0x41954f00, 0x4196a300, 0x4197f700, 0x41994b00, 0x419a9f00, 0x419bf300, 0x419d4700, 0x419e9b00, 0x419fef00, 0x41a14300, 0x41a29700, 0x41a3eb00, 0x41a53f00,
+    0x41a69300, 0x41a7e700, 0x41a93b00, 0x41aa8f00, 0x41abe300, 0x41ad3700, 0x41ae8b00, 0x41afdf00, 0x41b13300, 0x41b28700, 0x41b3db00, 0x41b52f00, 0x41b68300, 0x41b7d700, 0x41b92b00, 0x41ba7f00,
+    0x41bbd300, 0x41bd2700, 0x41be7b00, 0x41bfcf00, 0x41c12300, 0x41c27700, 0x41c3cb00, 0x41c51f00, 0x41c67300, 0x41c7c700, 0x41c91b00, 0x41ca6f00, 0x41cbc300, 0x41cd1700, 0x41ce6b00, 0x41cfbf00,
+    0x41d11300, 0x41d26700, 0x41d3bb00, 0x41d50f00, 0x41d66300, 0x41d7b700, 0x41d90b00, 0x41da5f00, 0x41dbb300, 0x41dd0700, 0x41de5b00, 0x41dfaf00, 0x41e10300, 0x41e25700, 0x41e3ab00, 0x41e4ff00,
+    0x41e65300, 0x41e7a700, 0x41e8fb00, 0x41ea4f00, 0x41eba300, 0x41ecf700, 0x41ee4b00, 0x41ef9f00, 0x41f0f300, 0x41f24700, 0x41f39b00, 0x41f4ef00, 0x41f64300, 0x41f79700, 0x41f8eb00, 0x41fa3f00,
+    0x41fb9300, 0x41fce700, 0x41fe3b00, 0x41ff8f00, 0x4200e300, 0x42023700, 0x42038b00, 0x4204df00, 0x42063300, 0x42078700, 0x4208db00, 0x420a2f00, 0x420b8300, 0x420cd700, 0x420e2b00, 0x420f7f00,
+    0x4210d300, 0x42122700, 0x42137b00, 0x4214cf00, 0x42162300, 0x42177700, 0x4218cb00, 0x421a1f00, 0x421b7300, 0x421cc700, 0x421e1b00, 0x421f6f00, 0x4220c300, 0x42221700, 0x42236b00, 0x4224bf00,
+    0x42261300, 0x42276700, 0x4228bb00, 0x422a0f00, 0x422b6300, 0x422cb700, 0x422e0b00, 0x422f5f00, 0x4230b300, 0x42320700, 0x42335b00, 0x4234af00, 0x42360300, 0x42375700, 0x4238ab00, 0x4239ff00,
+    0x423b9d00, 0x423d3b00, 0x423ed900, 0x42407700, 0x42421500, 0x4243b300, 0x42455100, 0x4246ef00, 0x42488d00, 0x424a2b00, 0x424bc900, 0x424d6700, 0x424f0500, 0x4250a300, 0x42524100, 0x4253df00,
+    0x42557d00, 0x42571b00, 0x4258b900, 0x425a5700, 0x425bf500, 0x425d9300, 0x425f3100, 0x4260cf00, 0x42626d00, 0x42640b00, 0x4265a900, 0x42674700, 0x4268e500, 0x426a8300, 0x426c2100, 0x426dbf00,
+    0x426f5d00, 0x4270fb00, 0x42729900, 0x42743700, 0x4275d500, 0x42777300, 0x42791100, 0x427aaf00, 0x427c4d00, 0x427deb00, 0x427f8900, 0x42812700, 0x4282c500, 0x42846300, 0x42860100, 0x42879f00,
+    0x42893d00, 0x428adb00, 0x428c7900, 0x428e1700, 0x428fb500, 0x42915300, 0x4292f100, 0x42948f00, 0x42962d00, 0x4297cb00, 0x42996900, 0x429b0700, 0x429ca500, 0x429e4300, 0x429fe100, 0x42a17f00,
+    0x42a31d00, 0x42a4bb00, 0x42a65900, 0x42a7f700, 0x42a99500, 0x42ab3300, 0x42acd100, 0x42ae6f00, 0x42b00d00, 0x42b1ab00, 0x42b34900, 0x42b4e700, 0x42b68500, 0x42b82300, 0x42b9c100, 0x42bb5f00,
+    0x42bcfd00, 0x42be9b00, 0x42c03900, 0x42c1d700, 0x42c37500, 0x42c51300, 0x42c6b100, 0x42c84f00, 0x42c9ed00, 0x42cb8b00, 0x42cd2900, 0x42cec700, 0x42d06500, 0x42d20300, 0x42d3a100, 0x42d53f00,
+    0x42d6dd00, 0x42d87b00, 0x42da1900, 0x42dbb700, 0x42dd5500, 0x42def300, 0x42e09100, 0x42e22f00, 0x42e3cd00, 0x42e56b00, 0x42e70900, 0x42e8a700, 0x42ea4500, 0x42ebe300, 0x42ed8100, 0x42ef1f00,
+    0x42f0bd00, 0x42f25b00, 0x42f3f900, 0x42f59700, 0x42f73500, 0x42f8d300, 0x42fa7100, 0x42fc0f00, 0x42fdad00, 0x42ff4b00, 0x4300e900, 0x43028700, 0x43042500, 0x4305c300, 0x43076100, 0x4308ff00,
+    0x430a9d00, 0x430c3b00, 0x430dd900, 0x430f7700, 0x43111500, 0x4312b300, 0x43145100, 0x4315ef00, 0x43178d00, 0x43192b00, 0x431ac900, 0x431c6700, 0x431e0500, 0x431fa300, 0x43214100, 0x4322df00,
+    0x43247d00, 0x43261b00, 0x4327b900, 0x43295700, 0x432af500, 0x432c9300, 0x432e3100, 0x432fcf00, 0x43316d00, 0x43330b00, 0x4334a900, 0x43364700, 0x4337e500, 0x43398300, 0x433b2100, 0x433cbf00,
+    0x433e5d00, 0x433ffb00, 0x43419900, 0x43433700, 0x4344d500, 0x43467300, 0x43481100, 0x4349af00, 0x434b4d00, 0x434ceb00, 0x434e8900, 0x43502700, 0x4351c500, 0x43536300, 0x43550100, 0x43569f00,
+    0x43583d00, 0x4359db00, 0x435b7900, 0x435d1700, 0x435eb500, 0x43605300, 0x4361f100, 0x43638f00, 0x43652d00, 0x4366cb00, 0x43686900, 0x436a0700, 0x436ba500, 0x436d4300, 0x436ee100, 0x43707f00,
+    0x43721d00, 0x4373bb00, 0x43755900, 0x4376f700, 0x43789500, 0x437a3300, 0x437bd100, 0x437d6f00, 0x437f0d00, 0x4380ab00, 0x43824900, 0x4383e700, 0x43858500, 0x43872300, 0x4388c100, 0x438a5f00,
+    0x438bfd00, 0x438d9b00, 0x438f3900, 0x4390d700, 0x43927500, 0x43941300, 0x4395b100, 0x43974f00, 0x4398ed00, 0x439a8b00, 0x439c2900, 0x439dc700, 0x439f6500, 0x43a10300, 0x43a2a100, 0x43a43f00,
+    0x43a5dd00, 0x43a77b00, 0x43a91900, 0x43aab700, 0x43ac5500, 0x43adf300, 0x43af9100, 0x43b12f00, 0x43b2cd00, 0x43b46b00, 0x43b60900, 0x43b7a700, 0x43b94500, 0x43bae300, 0x43bc8100, 0x43be1f00,
+    0x43bfbd00, 0x43c15b00, 0x43c2f900, 0x43c49700, 0x43c63500, 0x43c7d300, 0x43c97100, 0x43cb0f00, 0x43ccad00, 0x43ce4b00, 0x43cfe900, 0x43d18700, 0x43d32500, 0x43d4c300, 0x43d66100, 0x43d7ff00,
+    0x43d99d00, 0x43db3b00, 0x43dcd900, 0x43de7700, 0x43e01500, 0x43e1b300, 0x43e35100, 0x43e4ef00, 0x43e68d00, 0x43e82b00, 0x43e9c900, 0x43eb6700, 0x43ed0500, 0x43eea300, 0x43f04100, 0x43f1df00,
+    0x43f37d00, 0x43f51b00, 0x43f6b900, 0x43f85700, 0x43f9f500, 0x43fb9300, 0x43fd3100, 0x43fecf00, 0x44006d00, 0x44020b00, 0x4403a900, 0x44054700, 0x4406e500, 0x44088300, 0x440a2100, 0x440bbf00,
+    0x440d5d00, 0x440efb00, 0x44109900, 0x44123700, 0x4413d500, 0x44157300, 0x44171100, 0x4418af00, 0x441a4d00, 0x441beb00, 0x441d8900, 0x441f2700, 0x4420c500, 0x44226300, 0x44240100, 0x44259f00,
+    0x44273d00, 0x4428db00, 0x442a7900, 0x442c1700, 0x442db500, 0x442f5300, 0x4430f100, 0x44328f00, 0x44342d00, 0x4435cb00, 0x44376900, 0x44390700, 0x443aa500, 0x443c4300, 0x443de100, 0x443f7f00,
+    0x44411d00, 0x4442bb00, 0x44445900, 0x4445f700, 0x44479500, 0x44493300, 0x444ad100, 0x444c6f00, 0x444e0d00, 0x444fab00, 0x44514900, 0x4452e700, 0x44548500, 0x44562300, 0x4457c100, 0x44595f00,
+    0x445afd00, 0x445c9b00, 0x445e3900, 0x445fd700, 0x44617500, 0x44631300, 0x4464b100, 0x44664f00, 0x4467ed00, 0x44698b00, 0x446b2900, 0x446cc700, 0x446e6500, 0x44700300, 0x4471a100, 0x44733f00,
+    0x4474dd00, 0x44767b00, 0x44781900, 0x4479b700, 0x447b5500, 0x447cf300, 0x447e9100, 0x44802f00, 0x4481cd00, 0x44836b00, 0x44850900, 0x4486a700, 0x44884500, 0x4489e300, 0x448b8100, 0x448d1f00,
+    0x448ebd00, 0x44905b00, 0x4491f900, 0x44939700, 0x44953500, 0x4496d300, 0x44987100, 0x449a0f00, 0x449bad00, 0x449d4b00, 0x449ee900, 0x44a08700, 0x44a22500, 0x44a3c300, 0x44a56100, 0x44a6ff00,
+    0x44a89d00, 0x44aa3b00, 0x44abd900, 0x44ad7700, 0x44af1500, 0x44b0b300, 0x44b25100, 0x44b3ef00, 0x44b58d00, 0x44b72b00, 0x44b8c900, 0x44ba6700, 0x44bc0500, 0x44bda300, 0x44bf4100, 0x44c0df00,
+    0x44c27d00, 0x44c41b00, 0x44c5b900, 0x44c75700, 0x44c8f500, 0x44ca9300, 0x44cc3100, 0x44cdcf00, 0x44cf6d00, 0x44d10b00, 0x44d2a900, 0x44d44700, 0x44d5e500, 0x44d78300, 0x44d92100, 0x44dabf00,
+    0x44dc5d00, 0x44ddfb00, 0x44df9900, 0x44e13700, 0x44e2d500, 0x44e47300, 0x44e61100, 0x44e7af00, 0x44e94d00, 0x44eaeb00, 0x44ec8900, 0x44ee2700, 0x44efc500, 0x44f16300, 0x44f30100, 0x44f49f00,
+    0x44f63d00, 0x44f7db00, 0x44f97900, 0x44fb1700, 0x44fcb500, 0x44fe5300, 0x44fff100, 0x45018f00, 0x45032d00, 0x4504cb00, 0x45066900, 0x45080700, 0x4509a500, 0x450b4300, 0x450ce100, 0x450e7f00,
+    0x45101d00, 0x4511bb00, 0x45135900, 0x4514f700, 0x45169500, 0x45183300, 0x4519d100, 0x451b6f00, 0x451d0d00, 0x451eab00, 0x45204900, 0x4521e700, 0x45238500, 0x45252300, 0x4526c100, 0x45285f00,
+    0x4529fd00, 0x452b9b00, 0x452d3900, 0x452ed700, 0x45307500, 0x45321300, 0x4533b100, 0x45354f00, 0x4536ed00, 0x45388b00, 0x453a2900, 0x453bc700, 0x453d6500, 0x453f0300, 0x4540a100, 0x45423f00,
+    0x4543dd00, 0x45457b00, 0x45471900, 0x4548b700, 0x454a5500, 0x454bf300, 0x454d9100, 0x454f2f00, 0x4550cd00, 0x45526b00, 0x45540900, 0x4555a700, 0x45574500, 0x4558e300, 0x455a8100, 0x455c1f00,
+    0x455dbd00, 0x455f5b00, 0x4560f900, 0x45629700, 0x45643500, 0x4565d300, 0x45677100, 0x45690f00, 0x456aad00, 0x456c4b00, 0x456de900, 0x456f8700, 0x45712500, 0x4572c300, 0x45746100, 0x4575ff00,
+    0x4577e300, 0x4579c700, 0x457bab00, 0x457d8f00, 0x457f7300, 0x45815700, 0x45833b00, 0x45851f00, 0x45870300, 0x4588e700, 0x458acb00, 0x458caf00, 0x458e9300, 0x45907700, 0x45925b00, 0x45943f00,
+    0x45962300, 0x45980700, 0x4599eb00, 0x459bcf00, 0x459db300, 0x459f9700, 0x45a17b00, 0x45a35f00, 0x45a54300, 0x45a72700, 0x45a90b00, 0x45aaef00, 0x45acd300, 0x45aeb700, 0x45b09b00, 0x45b27f00,
+    0x45b46300, 0x45b64700, 0x45b82b00, 0x45ba0f00, 0x45bbf300, 0x45bdd700, 0x45bfbb00, 0x45c19f00, 0x45c38300, 0x45c56700, 0x45c74b00, 0x45c92f00, 0x45cb1300, 0x45ccf700, 0x45cedb00, 0x45d0bf00,
+    0x45d2a300, 0x45d48700, 0x45d66b00, 0x45d84f00, 0x45da3300, 0x45dc1700, 0x45ddfb00, 0x45dfdf00, 0x45e1c300, 0x45e3a700, 0x45e58b00, 0x45e76f00, 0x45e95300, 0x45eb3700, 0x45ed1b00, 0x45eeff00,
+    0x45f0e300, 0x45f2c700, 0x45f4ab00, 0x45f68f00, 0x45f87300, 0x45fa5700, 0x45fc3b00, 0x45fe1f00, 0x46000300, 0x4601e700, 0x4603cb00, 0x4605af00, 0x46079300, 0x46097700, 0x460b5b00, 0x460d3f00,
+    0x460f2300, 0x46110700, 0x4612eb00, 0x4614cf00, 0x4616b300, 0x46189700, 0x461a7b00, 0x461c5f00, 0x461e4300, 0x46202700, 0x46220b00, 0x4623ef00, 0x4625d300, 0x4627b700, 0x46299b00, 0x462b7f00,
+    0x462d6300, 0x462f4700, 0x46312b00, 0x46330f00, 0x4634f300, 0x4636d700, 0x4638bb00, 0x463a9f00, 0x463c8300, 0x463e6700, 0x46404b00, 0x46422f00, 0x46441300, 0x4645f700, 0x4647db00, 0x4649bf00,
+    0x464ba300, 0x464d8700, 0x464f6b00, 0x46514f00, 0x46533300, 0x46551700, 0x4656fb00, 0x4658df00, 0x465ac300, 0x465ca700, 0x465e8b00, 0x46606f00, 0x46625300, 0x46643700, 0x46661b00, 0x4667ff00,
+    0x4669e300, 0x466bc700, 0x466dab00, 0x466f8f00, 0x46717300, 0x46735700, 0x46753b00, 0x46771f00, 0x46790300, 0x467ae700, 0x467ccb00, 0x467eaf00, 0x46809300, 0x46827700, 0x46845b00, 0x46863f00,
+    0x46882300, 0x468a0700, 0x468beb00, 0x468dcf00, 0x468fb300, 0x46919700, 0x46937b00, 0x46955f00, 0x46974300, 0x46992700, 0x469b0b00, 0x469cef00, 0x469ed300, 0x46a0b700, 0x46a29b00, 0x46a47f00,
+    0x46a66300, 0x46a84700, 0x46aa2b00, 0x46ac0f00, 0x46adf300, 0x46afd700, 0x46b1bb00, 0x46b39f00, 0x46b58300, 0x46b76700, 0x46b94b00, 0x46bb2f00, 0x46bd1300, 0x46bef700, 0x46c0db00, 0x46c2bf00,
+    0x46c4a300, 0x46c68700, 0x46c86b00, 0x46ca4f00, 0x46cc3300, 0x46ce1700, 0x46cffb00, 0x46d1df00, 0x46d3c300, 0x46d5a700, 0x46d78b00, 0x46d96f00, 0x46db5300, 0x46dd3700, 0x46df1b00, 0x46e0ff00,
+    0x46e2e300, 0x46e4c700, 0x46e6ab00, 0x46e88f00, 0x46ea7300, 0x46ec5700, 0x46ee3b00, 0x46f01f00, 0x46f20300, 0x46f3e700, 0x46f5cb00, 0x46f7af00, 0x46f99300, 0x46fb7700, 0x46fd5b00, 0x46ff3f00,
+    0x47012300, 0x47030700, 0x4704eb00, 0x4706cf00, 0x4708b300, 0x470a9700, 0x470c7b00, 0x470e5f00, 0x47104300, 0x47122700, 0x47140b00, 0x4715ef00, 0x4717d300, 0x4719b700, 0x471b9b00, 0x471d7f00,
+    0x471f6300, 0x47214700, 0x47232b00, 0x47250f00, 0x4726f300, 0x4728d700, 0x472abb00, 0x472c9f00, 0x472e8300, 0x47306700, 0x47324b00, 0x47342f00, 0x47361300, 0x4737f700, 0x4739db00, 0x473bbf00,
+    0x473da300, 0x473f8700, 0x47416b00, 0x47434f00, 0x47453300, 0x47471700, 0x4748fb00, 0x474adf00, 0x474cc300, 0x474ea700, 0x47508b00, 0x47526f00, 0x47545300, 0x47563700, 0x47581b00, 0x4759ff00,
+    0x475c3f00, 0x475e7f00, 0x4760bf00, 0x4762ff00, 0x47653f00, 0x47677f00, 0x4769bf00, 0x476bff00, 0x476e3f00, 0x47707f00, 0x4772bf00, 0x4774ff00, 0x47773f00, 0x47797f00, 0x477bbf00, 0x477dff00,
+    0x47803f00, 0x47827f00, 0x4784bf00, 0x4786ff00, 0x47893f00, 0x478b7f00, 0x478dbf00, 0x478fff00, 0x47923f00, 0x47947f00, 0x4796bf00, 0x4798ff00, 0x479b3f00, 0x479d7f00, 0x479fbf00, 0x47a1ff00,
+    0x47a43f00, 0x47a67f00, 0x47a8bf00, 0x47aaff00, 0x47ad3f00, 0x47af7f00, 0x47b1bf00, 0x47b3ff00, 0x47b63f00, 0x47b87f00, 0x47babf00, 0x47bcff00, 0x47bf3f00, 0x47c17f00, 0x47c3bf00, 0x47c5ff00,
+    0x47c83f00, 0x47ca7f00, 0x47ccbf00, 0x47ceff00, 0x47d13f00, 0x47d37f00, 0x47d5bf00, 0x47d7ff00, 0x47da3f00, 0x47dc7f00, 0x47debf00, 0x47e0ff00, 0x47e33f00, 0x47e57f00, 0x47e7bf00, 0x47e9ff00,
+    0x47ec3f00, 0x47ee7f00, 0x47f0bf00, 0x47f2ff00, 0x47f53f00, 0x47f77f00, 0x47f9bf00, 0x47fbff00, 0x47fe3f00, 0x48007f00, 0x4802bf00, 0x4804ff00, 0x48073f00, 0x48097f00, 0x480bbf00, 0x480dff00,
+    0x48103f00, 0x48127f00, 0x4814bf00, 0x4816ff00, 0x48193f00, 0x481b7f00, 0x481dbf00, 0x481fff00, 0x48223f00, 0x48247f00, 0x4826bf00, 0x4828ff00, 0x482b3f00, 0x482d7f00, 0x482fbf00, 0x4831ff00,
+    0x48343f00, 0x48367f00, 0x4838bf00, 0x483aff00, 0x483d3f00, 0x483f7f00, 0x4841bf00, 0x4843ff00, 0x48463f00, 0x48487f00, 0x484abf00, 0x484cff00, 0x484f3f00, 0x48517f00, 0x4853bf00, 0x4855ff00,
+    0x48583f00, 0x485a7f00, 0x485cbf00, 0x485eff00, 0x48613f00, 0x48637f00, 0x4865bf00, 0x4867ff00, 0x486a3f00, 0x486c7f00, 0x486ebf00, 0x4870ff00, 0x48733f00, 0x48757f00, 0x4877bf00, 0x4879ff00,
+    0x487c3f00, 0x487e7f00, 0x4880bf00, 0x4882ff00, 0x48853f00, 0x48877f00, 0x4889bf00, 0x488bff00, 0x488e3f00, 0x48907f00, 0x4892bf00, 0x4894ff00, 0x48973f00, 0x48997f00, 0x489bbf00, 0x489dff00,
+    0x48a03f00, 0x48a27f00, 0x48a4bf00, 0x48a6ff00, 0x48a93f00, 0x48ab7f00, 0x48adbf00, 0x48afff00, 0x48b23f00, 0x48b47f00, 0x48b6bf00, 0x48b8ff00, 0x48bb3f00, 0x48bd7f00, 0x48bfbf00, 0x48c1ff00,
+    0x48c43f00, 0x48c67f00, 0x48c8bf00, 0x48caff00, 0x48cd3f00, 0x48cf7f00, 0x48d1bf00, 0x48d3ff00, 0x48d63f00, 0x48d87f00, 0x48dabf00, 0x48dcff00, 0x48df3f00, 0x48e17f00, 0x48e3bf00, 0x48e5ff00,
+    0x48e83f00, 0x48ea7f00, 0x48ecbf00, 0x48eeff00, 0x48f13f00, 0x48f37f00, 0x48f5bf00, 0x48f7ff00, 0x48fa3f00, 0x48fc7f00, 0x48febf00, 0x4900ff00, 0x49033f00, 0x49057f00, 0x4907bf00, 0x4909ff00,
+    0x490c3f00, 0x490e7f00, 0x4910bf00, 0x4912ff00, 0x49153f00, 0x49177f00, 0x4919bf00, 0x491bff00, 0x491e3f00, 0x49207f00, 0x4922bf00, 0x4924ff00, 0x49273f00, 0x49297f00, 0x492bbf00, 0x492dff00,
+    0x49303f00, 0x49327f00, 0x4934bf00, 0x4936ff00, 0x49393f00, 0x493b7f00, 0x493dbf00, 0x493fff00, 0x49423f00, 0x49447f00, 0x4946bf00, 0x4948ff00, 0x494b3f00, 0x494d7f00, 0x494fbf00, 0x4951ff00,
+    0x49543f00, 0x49567f00, 0x4958bf00, 0x495aff00, 0x495d3f00, 0x495f7f00, 0x4961bf00, 0x4963ff00, 0x49663f00, 0x49687f00, 0x496abf00, 0x496cff00, 0x496f3f00, 0x49717f00, 0x4973bf00, 0x4975ff00,
+    0x49783f00, 0x497a7f00, 0x497cbf00, 0x497eff00, 0x49813f00, 0x49837f00, 0x4985bf00, 0x4987ff00, 0x498a3f00, 0x498c7f00, 0x498ebf00, 0x4990ff00, 0x49933f00, 0x49957f00, 0x4997bf00, 0x4999ff00,
+    0x499cb300, 0x499f6700, 0x49a21b00, 0x49a4cf00, 0x49a78300, 0x49aa3700, 0x49aceb00, 0x49af9f00, 0x49b25300, 0x49b50700, 0x49b7bb00, 0x49ba6f00, 0x49bd2300, 0x49bfd700, 0x49c28b00, 0x49c53f00,
+    0x49c7f300, 0x49caa700, 0x49cd5b00, 0x49d00f00, 0x49d2c300, 0x49d57700, 0x49d82b00, 0x49dadf00, 0x49dd9300, 0x49e04700, 0x49e2fb00, 0x49e5af00, 0x49e86300, 0x49eb1700, 0x49edcb00, 0x49f07f00,
+    0x49f33300, 0x49f5e700, 0x49f89b00, 0x49fb4f00, 0x49fe0300, 0x4a00b700, 0x4a036b00, 0x4a061f00, 0x4a08d300, 0x4a0b8700, 0x4a0e3b00, 0x4a10ef00, 0x4a13a300, 0x4a165700, 0x4a190b00, 0x4a1bbf00,
+    0x4a1e7300, 0x4a212700, 0x4a23db00, 0x4a268f00, 0x4a294300, 0x4a2bf700, 0x4a2eab00, 0x4a315f00, 0x4a341300, 0x4a36c700, 0x4a397c00, 0x4a3c3000, 0x4a3ee400, 0x4a419800, 0x4a444c00, 0x4a470000,
+    0x4a49b400, 0x4a4c6800, 0x4a4f1c00, 0x4a51d000, 0x4a548400, 0x4a573800, 0x4a59ec00, 0x4a5ca000, 0x4a5f5400, 0x4a620800, 0x4a64bc00, 0x4a677000, 0x4a6a2400, 0x4a6cd800, 0x4a6f8c00, 0x4a724000,
+    0x4a74f400, 0x4a77a800, 0x4a7a5c00, 0x4a7d1000, 0x4a7fc400, 0x4a827800, 0x4a852c00, 0x4a87e000, 0x4a8a9400, 0x4a8d4800, 0x4a8ffc00, 0x4a92b000, 0x4a956400, 0x4a981800, 0x4a9acc00, 0x4a9d8000,
+    0x4aa03400, 0x4aa2e800, 0x4aa59c00, 0x4aa85000, 0x4aab0400, 0x4aadb800, 0x4ab06c00, 0x4ab32000, 0x4ab5d400, 0x4ab88800, 0x4abb3c00, 0x4abdf000, 0x4ac0a400, 0x4ac35800, 0x4ac60c00, 0x4ac8c000,
+    0x4acb7400, 0x4ace2800, 0x4ad0dc00, 0x4ad39000, 0x4ad64400, 0x4ad8f800, 0x4adbac00, 0x4ade6000, 0x4ae11400, 0x4ae3c800, 0x4ae67c00, 0x4ae93000, 0x4aebe400, 0x4aee9800, 0x4af14c00, 0x4af40000,
+    0x4af6cc00, 0x4af99800, 0x4afc6400, 0x4aff3000, 0x4b01fc00, 0x4b04c800, 0x4b079400, 0x4b0a6000, 0x4b0d2c00, 0x4b0ff800, 0x4b12c400, 0x4b159000, 0x4b185c00, 0x4b1b2800, 0x4b1df400, 0x4b20c000,
+    0x4b238c00, 0x4b265800, 0x4b292400, 0x4b2bf000, 0x4b2ebc00, 0x4b318800, 0x4b345400, 0x4b372000, 0x4b39ec00, 0x4b3cb800, 0x4b3f8400, 0x4b425000, 0x4b451c00, 0x4b47e800, 0x4b4ab400, 0x4b4d8000,
+    0x4b504c00, 0x4b531800, 0x4b55e400, 0x4b58b000, 0x4b5b7c00, 0x4b5e4800, 0x4b611400, 0x4b63e000, 0x4b66ac00, 0x4b697800, 0x4b6c4400, 0x4b6f1000, 0x4b71dc00, 0x4b74a800, 0x4b777400, 0x4b7a4000,
+    0x4b7d0c00, 0x4b7fd800, 0x4b82a400, 0x4b857000, 0x4b883c00, 0x4b8b0800, 0x4b8dd400, 0x4b90a000, 0x4b936c00, 0x4b963800, 0x4b990400, 0x4b9bd000, 0x4b9e9c00, 0x4ba16800, 0x4ba43400, 0x4ba70000,
+    0x4ba9cc00, 0x4bac9800, 0x4baf6400, 0x4bb23000, 0x4bb4fc00, 0x4bb7c700, 0x4bba9300, 0x4bbd5f00, 0x4bc02b00, 0x4bc2f700, 0x4bc5c300, 0x4bc88f00, 0x4bcb5b00, 0x4bce2700, 0x4bd0f300, 0x4bd3bf00,
+    0x4bd68b00, 0x4bd95700, 0x4bdc2300, 0x4bdeef00, 0x4be1bb00, 0x4be48700, 0x4be75300, 0x4bea1f00, 0x4beceb00, 0x4befb700, 0x4bf28300, 0x4bf54f00, 0x4bf81b00, 0x4bfae700, 0x4bfdb300, 0x4c007f00,
+    0x4c034b00, 0x4c061700, 0x4c08e300, 0x4c0baf00, 0x4c0e7b00, 0x4c114700, 0x4c141300, 0x4c16df00, 0x4c19ab00, 0x4c1c7700, 0x4c1f4300, 0x4c220f00, 0x4c24db00, 0x4c27a700, 0x4c2a7300, 0x4c2d3f00,
+    0x4c300b00, 0x4c32d700, 0x4c35a300, 0x4c386f00, 0x4c3b3b00, 0x4c3e0700, 0x4c40d300, 0x4c439f00, 0x4c466b00, 0x4c493700, 0x4c4c0300, 0x4c4ecf00, 0x4c519b00, 0x4c546700, 0x4c573300, 0x4c59ff00,
+    0x4c5d7700, 0x4c60ef00, 0x4c646700, 0x4c67df00, 0x4c6b5700, 0x4c6ecf00, 0x4c724700, 0x4c75bf00, 0x4c793700, 0x4c7caf00, 0x4c802700, 0x4c839f00, 0x4c871700, 0x4c8a8f00, 0x4c8e0700, 0x4c917f00,
+    0x4c94f700, 0x4c986f00, 0x4c9be700, 0x4c9f5f00, 0x4ca2d700, 0x4ca64f00, 0x4ca9c700, 0x4cad3f00, 0x4cb0b700, 0x4cb42f00, 0x4cb7a700, 0x4cbb1f00, 0x4cbe9700, 0x4cc20f00, 0x4cc58700, 0x4cc8ff00,
+    0x4ccc7700, 0x4ccfef00, 0x4cd36700, 0x4cd6df00, 0x4cda5700, 0x4cddcf00, 0x4ce14700, 0x4ce4bf00, 0x4ce83700, 0x4cebaf00, 0x4cef2700, 0x4cf29f00, 0x4cf61700, 0x4cf98f00, 0x4cfd0700, 0x4d007f00,
+    0x4d03f700, 0x4d076f00, 0x4d0ae700, 0x4d0e5f00, 0x4d11d700, 0x4d154f00, 0x4d18c700, 0x4d1c3f00, 0x4d1fb700, 0x4d232f00, 0x4d26a700, 0x4d2a1f00, 0x4d2d9700, 0x4d310f00, 0x4d348700, 0x4d37ff00,
+    0x4d3b7700, 0x4d3eef00, 0x4d426700, 0x4d45df00, 0x4d495700, 0x4d4ccf00, 0x4d504700, 0x4d53bf00, 0x4d573700, 0x4d5aaf00, 0x4d5e2700, 0x4d619f00, 0x4d651700, 0x4d688f00, 0x4d6c0700, 0x4d6f7f00,
+    0x4d72f700, 0x4d766f00, 0x4d79e700, 0x4d7d5f00, 0x4d80d700, 0x4d844f00, 0x4d87c700, 0x4d8b3f00, 0x4d8eb700, 0x4d922f00, 0x4d95a700, 0x4d991f00, 0x4d9c9700, 0x4da00f00, 0x4da38700, 0x4da6ff00,
+    0x4daa7700, 0x4dadef00, 0x4db16700, 0x4db4df00, 0x4db85700, 0x4dbbcf00, 0x4dbf4700, 0x4dc2bf00, 0x4dc63700, 0x4dc9af00, 0x4dcd2700, 0x4dd09f00, 0x4dd41700, 0x4dd78f00, 0x4ddb0700, 0x4dde7f00,
+    0x4de1f700, 0x4de56f00, 0x4de8e700, 0x4dec5f00, 0x4defd700, 0x4df34f00, 0x4df6c700, 0x4dfa3f00, 0x4dfdb700, 0x4e012f00, 0x4e04a700, 0x4e081f00, 0x4e0b9700, 0x4e0f0f00, 0x4e128700, 0x4e15ff00,
+    0x4e19ff00, 0x4e1dff00, 0x4e21ff00, 0x4e25ff00, 0x4e29ff00, 0x4e2dff00, 0x4e31ff00, 0x4e35ff00, 0x4e39ff00, 0x4e3dff00, 0x4e41ff00, 0x4e45ff00, 0x4e49ff00, 0x4e4dff00, 0x4e51ff00, 0x4e55ff00,
+    0x4e59ff00, 0x4e5dff00, 0x4e61ff00, 0x4e65ff00, 0x4e69ff00, 0x4e6dff00, 0x4e71ff00, 0x4e75ff00, 0x4e79ff00, 0x4e7dff00, 0x4e81ff00, 0x4e85ff00, 0x4e89ff00, 0x4e8dff00, 0x4e91ff00, 0x4e95ff00,
+    0x4e99ff00, 0x4e9dff00, 0x4ea1ff00, 0x4ea5ff00, 0x4ea9ff00, 0x4eadff00, 0x4eb1ff00, 0x4eb5ff00, 0x4eb9ff00, 0x4ebdff00, 0x4ec1ff00, 0x4ec5ff00, 0x4ec9ff00, 0x4ecdff00, 0x4ed1ff00, 0x4ed5ff00,
+    0x4ed9ff00, 0x4eddff00, 0x4ee1ff00, 0x4ee5ff00, 0x4ee9ff00, 0x4eedff00, 0x4ef1ff00, 0x4ef5ff00, 0x4ef9ff00, 0x4efdff00, 0x4f01ff00, 0x4f05ff00, 0x4f09ff00, 0x4f0dff00, 0x4f11ff00, 0x4f15ff00,
+    0x4f19ff00, 0x4f1dff00, 0x4f21ff00, 0x4f25ff00, 0x4f29ff00, 0x4f2dff00, 0x4f31ff00, 0x4f35ff00, 0x4f39ff00, 0x4f3dff00, 0x4f41ff00, 0x4f45ff00, 0x4f49ff00, 0x4f4dff00, 0x4f51ff00, 0x4f55ff00,
+    0x4f59ff00, 0x4f5dff00, 0x4f61ff00, 0x4f65ff00, 0x4f69ff00, 0x4f6dff00, 0x4f71ff00, 0x4f75ff00, 0x4f79ff00, 0x4f7dff00, 0x4f81ff00, 0x4f85ff00, 0x4f89ff00, 0x4f8dff00, 0x4f91ff00, 0x4f95ff00,
+    0x4f99ff00, 0x4f9dff00, 0x4fa1ff00, 0x4fa5ff00, 0x4fa9ff00, 0x4fadff00, 0x4fb1ff00, 0x4fb5ff00, 0x4fb9ff00, 0x4fbdff00, 0x4fc1ff00, 0x4fc5ff00, 0x4fc9ff00, 0x4fcdff00, 0x4fd1ff00, 0x4fd5ff00,
+    0x4fd9ff00, 0x4fddff00, 0x4fe1ff00, 0x4fe5ff00, 0x4fe9ff00, 0x4fedff00, 0x4ff1ff00, 0x4ff5ff00, 0x4ff9ff00, 0x4ffdff00, 0x5001ff00, 0x5005ff00, 0x5009ff00, 0x500dff00, 0x5011ff00, 0x5015ff00,
+    0x501a7700, 0x501eef00, 0x50236700, 0x5027df00, 0x502c5700, 0x5030cf00, 0x50354700, 0x5039bf00, 0x503e3700, 0x5042af00, 0x50472700, 0x504b9f00, 0x50501700, 0x50548f00, 0x50590700, 0x505d7f00,
+    0x5061f700, 0x50666f00, 0x506ae700, 0x506f5f00, 0x5073d700, 0x50785000, 0x507cc800, 0x50814000, 0x5085b800, 0x508a3000, 0x508ea800, 0x50932000, 0x50979800, 0x509c1000, 0x50a08800, 0x50a50000,
+    0x50a97800, 0x50adf000, 0x50b26800, 0x50b6e000, 0x50bb5800, 0x50bfd000, 0x50c44800, 0x50c8c000, 0x50cd3800, 0x50d1b000, 0x50d62800, 0x50daa000, 0x50df1800, 0x50e39000, 0x50e80800, 0x50ec8000,
+    0x50f0f800, 0x50f57000, 0x50f9e800, 0x50fe6000, 0x5102d800, 0x51075000, 0x510bc800, 0x51104000, 0x5114b800, 0x51193000, 0x511da800, 0x51222000, 0x51269800, 0x512b1000, 0x512f8800, 0x51340000,
+    0x51396800, 0x513ed000, 0x51443800, 0x5149a000, 0x514f0800, 0x51547000, 0x5159d800, 0x515f4000, 0x5164a800, 0x516a1000, 0x516f7800, 0x5174e000, 0x517a4800, 0x517fb000, 0x51851800, 0x518a8000,
+    0x518fe800, 0x51955000, 0x519ab800, 0x51a02000, 0x51a58800, 0x51aaf000, 0x51b05800, 0x51b5c000, 0x51bb2800, 0x51c09000, 0x51c5f800, 0x51cb6000, 0x51d0c800, 0x51d63000, 0x51db9800, 0x51e10000,
+    0x51e66800, 0x51ebd000, 0x51f13800, 0x51f6a000, 0x51fc0800, 0x52017000, 0x5206d800, 0x520c4000, 0x5211a800, 0x52171000, 0x521c7800, 0x5221e000, 0x52274800, 0x522cb000, 0x52321800, 0x52378000,
+    0x523ce800, 0x52425000, 0x5247b800, 0x524d2000, 0x52528800, 0x5257f000, 0x525d5800, 0x5262c000, 0x52682800, 0x526d9000, 0x5272f800, 0x52786000, 0x527dc800, 0x52833000, 0x52889800, 0x528e0000,
+    0x5293c000, 0x52998000, 0x529f4000, 0x52a50000, 0x52aac000, 0x52b08000, 0x52b64000, 0x52bc0000, 0x52c1bf00, 0x52c77f00, 0x52cd3f00, 0x52d2ff00, 0x52d8bf00, 0x52de7f00, 0x52e43f00, 0x52e9ff00,
+    0x52efbf00, 0x52f57f00, 0x52fb3f00, 0x5300ff00, 0x5306bf00, 0x530c7f00, 0x53123f00, 0x5317ff00, 0x531dbf00, 0x53237f00, 0x53293f00, 0x532eff00, 0x5334bf00, 0x533a7f00, 0x53403f00, 0x5345ff00,
+    0x534bbf00, 0x53517f00, 0x53573f00, 0x535cff00, 0x5362bf00, 0x53687f00, 0x536e3f00, 0x5373ff00, 0x5379bf00, 0x537f7f00, 0x53853f00, 0x538aff00, 0x5390bf00, 0x53967f00, 0x539c3f00, 0x53a1ff00,
+    0x53a7bf00, 0x53ad7f00, 0x53b33f00, 0x53b8ff00, 0x53bebf00, 0x53c47f00, 0x53ca3f00, 0x53cfff00, 0x53d5bf00, 0x53db7f00, 0x53e13f00, 0x53e6ff00, 0x53ecbf00, 0x53f27f00, 0x53f83f00, 0x53fdff00,
+    0x54055f00, 0x540cbf00, 0x54141f00, 0x541b7f00, 0x5422df00, 0x542a3f00, 0x54319f00, 0x5438ff00, 0x54405f00, 0x5447bf00, 0x544f1f00, 0x54567f00, 0x545ddf00, 0x54653f00, 0x546c9f00, 0x5473ff00,
+    0x547b5f00, 0x5482bf00, 0x548a1f00, 0x54917f00, 0x5498df00, 0x54a03f00, 0x54a79f00, 0x54aeff00, 0x54b65f00, 0x54bdbf00, 0x54c51f00, 0x54cc7f00, 0x54d3df00, 0x54db3f00, 0x54e29f00, 0x54e9ff00,
+    0x54f15f00, 0x54f8bf00, 0x55001f00, 0x55077f00, 0x550edf00, 0x55163f00, 0x551d9f00, 0x5524ff00, 0x552c5f00, 0x5533bf00, 0x553b1f00, 0x55427f00, 0x5549df00, 0x55513f00, 0x55589f00, 0x555fff00,
+    0x55675f00, 0x556ebf00, 0x55761f00, 0x557d7f00, 0x5584df00, 0x558c3f00, 0x55939f00, 0x559aff00, 0x55a25f00, 0x55a9bf00, 0x55b11f00, 0x55b87f00, 0x55bfdf00, 0x55c73f00, 0x55ce9f00, 0x55d5ff00,
+    0x55de9f00, 0x55e73f00, 0x55efdf00, 0x55f87f00, 0x56011f00, 0x5609bf00, 0x56125f00, 0x561aff00, 0x56239f00, 0x562c3f00, 0x5634df00, 0x563d7f00, 0x56461f00, 0x564ebf00, 0x56575f00, 0x565fff00,
+    0x56689f00, 0x56713f00, 0x5679df00, 0x56827f00, 0x568b1f00, 0x5693bf00, 0x569c5f00, 0x56a4ff00, 0x56ad9f00, 0x56b63f00, 0x56bedf00, 0x56c77f00, 0x56d01f00, 0x56d8bf00, 0x56e15f00, 0x56e9ff00,
+    0x56f29f00, 0x56fb3f00, 0x5703df00, 0x570c7f00, 0x57151f00, 0x571dbf00, 0x57265f00, 0x572eff00, 0x57379f00, 0x57403f00, 0x5748df00, 0x57517f00, 0x575a1f00, 0x5762bf00, 0x576b5f00, 0x5773ff00,
+    0x577c9f00, 0x57853f00, 0x578ddf00, 0x57967f00, 0x579f1f00, 0x57a7bf00, 0x57b05f00, 0x57b8ff00, 0x57c19f00, 0x57ca3f00, 0x57d2df00, 0x57db7f00, 0x57e41f00, 0x57ecbf00, 0x57f55f00, 0x57fdff00,
+    0x58087f00, 0x5812ff00, 0x581d7f00, 0x5827ff00, 0x58327f00, 0x583cff00, 0x58477f00, 0x5851ff00, 0x585c7f00, 0x5866ff00, 0x58717f00, 0x587bff00, 0x58867f00, 0x5890ff00, 0x589b7f00, 0x58a5ff00,
+    0x58b07f00, 0x58baff00, 0x58c57f00, 0x58cfff00, 0x58da7f00, 0x58e4ff00, 0x58ef7f00, 0x58f9ff00, 0x59047f00, 0x590eff00, 0x59197f00, 0x5923ff00, 0x592e7f00, 0x5938ff00, 0x59437f00, 0x594dff00,
+    0x59587f00, 0x5962ff00, 0x596d7f00, 0x5977ff00, 0x59827f00, 0x598cff00, 0x59977f00, 0x59a1ff00, 0x59ac7f00, 0x59b6ff00, 0x59c17f00, 0x59cbff00, 0x59d67f00, 0x59e0ff00, 0x59eb7f00, 0x59f5ff00,
+    0x5a007f00, 0x5a0aff00, 0x5a157f00, 0x5a1fff00, 0x5a2a7f00, 0x5a34ff00, 0x5a3f7f00, 0x5a49ff00, 0x5a547f00, 0x5a5eff00, 0x5a697f00, 0x5a73ff00, 0x5a7e7f00, 0x5a88ff00, 0x5a937f00, 0x5a9dff00,
+    0x5aaa0700, 0x5ab60f00, 0x5ac21700, 0x5ace1f00, 0x5ada2700, 0x5ae62f00, 0x5af23700, 0x5afe3f00, 0x5b0a4700, 0x5b164f00, 0x5b225700, 0x5b2e5f00, 0x5b3a6700, 0x5b466f00, 0x5b527700, 0x5b5e7f00,
+    0x5b6a8700, 0x5b768f00, 0x5b829700, 0x5b8e9f00, 0x5b9aa700, 0x5ba6af00, 0x5bb2b700, 0x5bbebf00, 0x5bcac700, 0x5bd6cf00, 0x5be2d700, 0x5beedf00, 0x5bfae700, 0x5c06ef00, 0x5c12f700, 0x5c1eff00,
+    0x5c2b0700, 0x5c370f00, 0x5c431700, 0x5c4f1f00, 0x5c5b2700, 0x5c672f00, 0x5c733700, 0x5c7f3f00, 0x5c8b4700, 0x5c974f00, 0x5ca35700, 0x5caf5f00, 0x5cbb6700, 0x5cc76f00, 0x5cd37700, 0x5cdf7f00,
+    0x5ceb8700, 0x5cf78f00, 0x5d039700, 0x5d0f9f00, 0x5d1ba700, 0x5d27af00, 0x5d33b700, 0x5d3fbf00, 0x5d4bc700, 0x5d57cf00, 0x5d63d700, 0x5d6fdf00, 0x5d7be700, 0x5d87ef00, 0x5d93f700, 0x5da00000,
+    0x5dac8000, 0x5db90000, 0x5dc58000, 0x5dd20000, 0x5dde8000, 0x5deb0000, 0x5df78000, 0x5e040000, 0x5e108000, 0x5e1d0000, 0x5e298000, 0x5e360000, 0x5e428000, 0x5e4f0000, 0x5e5b8000, 0x5e680000,
+    0x5e748000, 0x5e810000, 0x5e8d8000, 0x5e9a0000, 0x5ea68000, 0x5eb30000, 0x5ebf8000, 0x5ecc0000, 0x5ed88000, 0x5ee50000, 0x5ef18000, 0x5efe0000, 0x5f0a8000, 0x5f170000, 0x5f238000, 0x5f300000,
+    0x5f3c8000, 0x5f490000, 0x5f558000, 0x5f620000, 0x5f6e8000, 0x5f7b0000, 0x5f878000, 0x5f940000, 0x5fa08000, 0x5fad0000, 0x5fb98000, 0x5fc60000, 0x5fd28000, 0x5fdf0000, 0x5feb8000, 0x5ff80000,
+    0x60048000, 0x60110000, 0x601d8000, 0x602a0000, 0x60368000, 0x60430000, 0x604f8000, 0x605c0000, 0x60688000, 0x60750000, 0x60818000, 0x608e0000, 0x609a8000, 0x60a70000, 0x60b38000, 0x60c00000,
+    0x60cc8000, 0x60d90000, 0x60e58000, 0x60f20000, 0x60fe8000, 0x610b0000, 0x61178000, 0x61240000, 0x61308000, 0x613d0000, 0x61498000, 0x61560000, 0x61628000, 0x616f0000, 0x617b8000, 0x61880000,
+    0x61948000, 0x61a10000, 0x61ad8000, 0x61ba0000, 0x61c68000, 0x61d30000, 0x61df8000, 0x61ec0000, 0x61f88000, 0x62050000, 0x62118000, 0x621e0000, 0x622a8000, 0x62370000, 0x62438000, 0x62500000,
+    0x625c8000, 0x62690000, 0x62758000, 0x62820000, 0x628e8000, 0x629b0000, 0x62a78000, 0x62b40000, 0x62c08000, 0x62cd0000, 0x62d98000, 0x62e60000, 0x62f28000, 0x62ff0000, 0x630b8000, 0x63180000,
+    0x63248000, 0x63310000, 0x633d8000, 0x634a0000, 0x63568000, 0x63630000, 0x636f8000, 0x637c0000, 0x63888000, 0x63950000, 0x63a18000, 0x63ae0000, 0x63ba8000, 0x63c70000, 0x63d38000, 0x63e00000,
+    0x63ec8000, 0x63f90000, 0x64058000, 0x64120000, 0x641e8000, 0x642b0000, 0x64378000, 0x64440000, 0x64508000, 0x645d0000, 0x64698000, 0x64760000, 0x64828000, 0x648f0000, 0x649b8000, 0x64a80000,
+    0x64b48000, 0x64c10000, 0x64cd8000, 0x64da0000, 0x64e68000, 0x64f30000, 0x64ff8000, 0x650c0000, 0x65188000, 0x65250000, 0x65318000, 0x653e0000, 0x654a8000, 0x65570000, 0x65638000, 0x65700000,
+    0x657c8000, 0x65890000, 0x65958000, 0x65a20000, 0x65ae8000, 0x65bb0000, 0x65c78000, 0x65d40000, 0x65e08000, 0x65ed0000, 0x65f98000, 0x66060000, 0x66128000, 0x661f0000, 0x662b8000, 0x66380000,
+    0x66448000, 0x66510000, 0x665d8000, 0x666a0000, 0x66768000, 0x66830000, 0x668f8000, 0x669c0000, 0x66a88000, 0x66b50000, 0x66c18000, 0x66ce0000, 0x66da8000, 0x66e70000, 0x66f38000, 0x67000000,
+    0x670c8000, 0x67190000, 0x67258000, 0x67320000, 0x673e8000, 0x674b0000, 0x67578000, 0x67640000, 0x67708000, 0x677d0000, 0x67898000, 0x67960000, 0x67a28000, 0x67af0000, 0x67bb8000, 0x67c80000,
+    0x67d48000, 0x67e10000, 0x67ed8000, 0x67fa0000, 0x68068000, 0x68130000, 0x681f8000, 0x682c0000, 0x68388000, 0x68450000, 0x68518000, 0x685e0000, 0x686a8000, 0x68770000, 0x68838000, 0x68900000,
+    0x689c8000, 0x68a90000, 0x68b58000, 0x68c20000, 0x68ce8000, 0x68db0000, 0x68e78000, 0x68f40000, 0x69008000, 0x690d0000, 0x69198000, 0x69260000, 0x69328000, 0x693f0000, 0x694b8000, 0x69580000,
+    0x69648000, 0x69710000, 0x697d8000, 0x698a0000, 0x69968000, 0x69a30000, 0x69af8000, 0x69bc0000, 0x69c88000, 0x69d50000, 0x69e18000, 0x69ee0000, 0x69fa8000, 0x6a070000, 0x6a138000, 0x6a200000,
+    0x6a2c8000, 0x6a390000, 0x6a458000, 0x6a520000, 0x6a5e8000, 0x6a6b0000, 0x6a778000, 0x6a840000, 0x6a908000, 0x6a9d0000, 0x6aa98000, 0x6ab60000, 0x6ac28000, 0x6acf0000, 0x6adb8000, 0x6ae80000,
+    0x6af48000, 0x6b010000, 0x6b0d8000, 0x6b1a0000, 0x6b268000, 0x6b330000, 0x6b3f8000, 0x6b4c0000, 0x6b588000, 0x6b650000, 0x6b718000, 0x6b7e0000, 0x6b8a8000, 0x6b970000, 0x6ba38000, 0x6bb00000,
+    0x6bbc8000, 0x6bc90000, 0x6bd58000, 0x6be20000, 0x6bee8000, 0x6bfb0000, 0x6c078000, 0x6c140000, 0x6c208000, 0x6c2d0000, 0x6c398000, 0x6c460000, 0x6c528000, 0x6c5f0000, 0x6c6b8000, 0x6c780000,
+    0x6c848000, 0x6c910000, 0x6c9d8000, 0x6caa0000, 0x6cb68000, 0x6cc30000, 0x6ccf8000, 0x6cdc0000, 0x6ce88000, 0x6cf50000, 0x6d018000, 0x6d0e0000, 0x6d1a8000, 0x6d270000, 0x6d338000, 0x6d400000,
+    0x6d4c8000, 0x6d590000, 0x6d658000, 0x6d720000, 0x6d7e8000, 0x6d8b0000, 0x6d978000, 0x6da40000, 0x6db08000, 0x6dbd0000, 0x6dc98000, 0x6dd60000, 0x6de28000, 0x6def0000, 0x6dfb8000, 0x6e080000,
+    0x6e148000, 0x6e210000, 0x6e2d8000, 0x6e3a0000, 0x6e468000, 0x6e530000, 0x6e5f8000, 0x6e6c0000, 0x6e788000, 0x6e850000, 0x6e918000, 0x6e9e0000, 0x6eaa8000, 0x6eb70000, 0x6ec38000, 0x6ed00000,
+    0x6edc8000, 0x6ee90000, 0x6ef58000, 0x6f020000, 0x6f0e8000, 0x6f1b0000, 0x6f278000, 0x6f340000, 0x6f408000, 0x6f4d0000, 0x6f598000, 0x6f660000, 0x6f728000, 0x6f7f0000, 0x6f8b8000, 0x6f980000,
+    0x6fa48000, 0x6fb10000, 0x6fbd8000, 0x6fca0000, 0x6fd68000, 0x6fe30000, 0x6fef8000, 0x6ffc0000, 0x70088000, 0x70150000, 0x70218000, 0x702e0000, 0x703a8000, 0x70470000, 0x70538000, 0x70600000,
+    0x706c8000, 0x70790000, 0x70858000, 0x70920000, 0x709e8000, 0x70ab0000, 0x70b78000, 0x70c40000, 0x70d08000, 0x70dd0000, 0x70e98000, 0x70f60000, 0x71028000, 0x710f0000, 0x711b8000, 0x71280000,
+    0x71348000, 0x71410000, 0x714d8000, 0x715a0000, 0x71668000, 0x71730000, 0x717f8000, 0x718c0000, 0x71988000, 0x71a50000, 0x71b18000, 0x71be0000, 0x71ca8000, 0x71d70000, 0x71e38000, 0x71f00000,
+    0x71fc8000, 0x72090000, 0x72158000, 0x72220000, 0x722e8000, 0x723b0000, 0x72478000, 0x72540000, 0x72608000, 0x726d0000, 0x72798000, 0x72860000, 0x72928000, 0x729f0000, 0x72ab8000, 0x72b80000,
+    0x72c48000, 0x72d10000, 0x72dd8000, 0x72ea0000, 0x72f68000, 0x73030000, 0x730f8000, 0x731c0000, 0x73288000, 0x73350000, 0x73418000, 0x734e0000, 0x735a8000, 0x73670000, 0x73738000, 0x73800000,
+    0x738c8000, 0x73990000, 0x73a58000, 0x73b20000, 0x73be8000, 0x73cb0000, 0x73d78000, 0x73e40000, 0x73f08000, 0x73fd0000, 0x74098000, 0x74160000, 0x74228000, 0x742f0000, 0x743b8000, 0x74480000,
+    0x74548000, 0x74610000, 0x746d8000, 0x747a0000, 0x74868000, 0x74930000, 0x749f8000, 0x74ac0000, 0x74b88000, 0x74c50000, 0x74d18000, 0x74de0000, 0x74ea8000, 0x74f70000, 0x75038000, 0x75100000,
+    0x751c8000, 0x75290000, 0x75358000, 0x75420000, 0x754e8000, 0x755b0000, 0x75678000, 0x75740000, 0x75808000, 0x758d0000, 0x75998000, 0x75a60000, 0x75b28000, 0x75bf0000, 0x75cb8000, 0x75d80000,
+    0x75e48000, 0x75f10000, 0x75fd8000, 0x760a0000, 0x76168000, 0x76230000, 0x762f8000, 0x763c0000, 0x76488000, 0x76550000, 0x76618000, 0x766e0000, 0x767a8000, 0x76870000, 0x76938000, 0x76a00000,
+    0x76ac8000, 0x76b90000, 0x76c58000, 0x76d20000, 0x76de8000, 0x76eb0000, 0x76f78000, 0x77040000, 0x77108000, 0x771d0000, 0x77298000, 0x77360000, 0x77428000, 0x774f0000, 0x775b8000, 0x77680000,
+    0x77748000, 0x77810000, 0x778d8000, 0x779a0000, 0x77a68000, 0x77b30000, 0x77bf8000, 0x77cc0000, 0x77d88000, 0x77e50000, 0x77f18000, 0x77fe0000, 0x780a8000, 0x78170000, 0x78238000, 0x78300000,
+    0x783c8000, 0x78490000, 0x78558000, 0x78620000, 0x786e8000, 0x787b0000, 0x78878000, 0x78940000, 0x78a08000, 0x78ad0000, 0x78b98000, 0x78c60000, 0x78d28000, 0x78df0000, 0x78eb8000, 0x78f80000,
+    0x79048000, 0x79110000, 0x791d8000, 0x792a0000, 0x79368000, 0x79430000, 0x794f8000, 0x795c0000, 0x79688000, 0x79750000, 0x79818000, 0x798e0000, 0x799a8000, 0x79a70000, 0x79b38000, 0x79c00000,
+    0x79cc8000, 0x79d90000, 0x79e58000, 0x79f20000, 0x79fe8000, 0x7a0b0000, 0x7a178000, 0x7a240000, 0x7a308000, 0x7a3d0000, 0x7a498000, 0x7a560000, 0x7a628000, 0x7a6f0000, 0x7a7b8000, 0x7a880000,
+    0x7a948000, 0x7aa10000, 0x7aad8000, 0x7aba0000, 0x7ac68000, 0x7ad30000, 0x7adf8000, 0x7aec0000, 0x7af88000, 0x7b050000, 0x7b118000, 0x7b1e0000, 0x7b2a8000, 0x7b370000, 0x7b438000, 0x7b500000,
+    0x7b5c8000, 0x7b690000, 0x7b758000, 0x7b820000, 0x7b8e8000, 0x7b9b0000, 0x7ba78000, 0x7bb40000, 0x7bc08000, 0x7bcd0000, 0x7bd98000, 0x7be60000, 0x7bf28000, 0x7bff0000, 0x7c0b8000, 0x7c180000,
+    0x7c248000, 0x7c310000, 0x7c3d8000, 0x7c4a0000, 0x7c568000, 0x7c630000, 0x7c6f8000, 0x7c7c0000, 0x7c888000, 0x7c950000, 0x7ca18000, 0x7cae0000, 0x7cba8000, 0x7cc70000, 0x7cd38000, 0x7ce00000,
+    0x7cec8000, 0x7cf90000, 0x7d058000, 0x7d120000, 0x7d1e8000, 0x7d2b0000, 0x7d378000, 0x7d440000, 0x7d508000, 0x7d5d0000, 0x7d698000, 0x7d760000, 0x7d828000, 0x7d8f0000, 0x7d9b8000, 0x7da80000,
+    0x7db48000, 0x7dc10000, 0x7dcd8000, 0x7dda0000, 0x7de68000, 0x7df30000, 0x7dff8000, 0x7e0c0000, 0x7e188000, 0x7e250000, 0x7e318000, 0x7e3e0000, 0x7e4a8000, 0x7e570000, 0x7e638000, 0x7e700000,
+    0x7e7c8000, 0x7e890000, 0x7e958000, 0x7ea20000, 0x7eae8000, 0x7ebb0000, 0x7ec78000, 0x7ed40000, 0x7ee08000, 0x7eed0000, 0x7ef98000, 0x7f060000, 0x7f128000, 0x7f1f0000, 0x7f2b8000, 0x7f380000,
+    0x7f448000, 0x7f510000, 0x7f5d8000, 0x7f6a0000, 0x7f768000, 0x7f830000, 0x7f8f8000, 0x7f9c0000, 0x7fa88000, 0x7fb50000, 0x7fc18000, 0x7fce0000, 0x7fda8000, 0x7fe70000, 0x7ff38000, 0x80000000
+};
+
+static const uint8_t readaheadtab[] = {
+    0x03, 0x02, 0x01, 0x01, 0x1f, 0x1e, 0x1f, 0x11, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f,
+    0x10, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1c, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e,
+    0x1f, 0x0f, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1c, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f,
+    0x1e, 0x1f, 0x1b, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1c, 0x1f, 0x1e, 0x1f, 0x1d,
+    0x1f, 0x1e, 0x0e, 0x19, 0x07, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1c, 0x1f, 0x1e, 0x1f,
+    0x1d, 0x1f, 0x1e, 0x1f, 0x1b, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1c, 0x1f, 0x1e,
+    0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1a, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1c, 0x1f,
+    0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1b, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1c,
+    0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x0d, 0x18, 0x20, 0x06, 0x1e, 0x1f, 0x12, 0x1f, 0x1e, 0x1f,
+    0x1c, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1b, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e,
+    0x1f, 0x1c, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1a, 0x08, 0x1e, 0x1f, 0x1d, 0x1f,
+    0x1e, 0x1f, 0x1c, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1b, 0x1f, 0x1e, 0x1f, 0x1d,
+    0x1f, 0x1e, 0x1f, 0x1c, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x19, 0x1f, 0x13, 0x1f,
+    0x1d, 0x1f, 0x1e, 0x1f, 0x1c, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1b, 0x09, 0x1e,
+    0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1c, 0x1f, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1a, 0x14,
+    0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1c, 0x0a, 0x1e, 0x1f, 0x1d, 0x1f, 0x1e, 0x1f, 0x1b,
+    0x15, 0x1e, 0x1f, 0x1d, 0x0b, 0x1e, 0x1f, 0x1c, 0x16, 0x1e, 0x0c, 0x1d, 0x17, 0x1e, 0x1f,
+    0x20
+};
+
+//values between 0 and 1 multiplied by 2^23 to avoid floating point numbers.
+static const int32_t gaintab[] = {
+    0x800000, 0x7ff144, 0x7fe28a, 0x7fd3d2, 0x7fc51b, 0x7fb666, 0x7fa7b3, 0x7f9901, 0x7f8a52, 0x7f7ba3, 0x7f6cf7, 0x7f5e4c, 0x7f4fa3, 0x7f40fc, 0x7f3256,
+    0x7f23b2, 0x7f1510, 0x7f066f, 0x7ef7d0, 0x7ee933, 0x7eda97, 0x7ecbfd, 0x7ebd65, 0x7eaece, 0x7ea039, 0x7e91a6, 0x7e8315, 0x7e7485, 0x7e65f6, 0x7e576a,
+    0x7e48df, 0x7e3a56, 0x7e2bce, 0x7e1d49, 0x7e0ec5, 0x7e0042, 0x7df1c1, 0x7de342, 0x7dd4c5, 0x7dc649, 0x7db7cf, 0x7da956, 0x7d9adf, 0x7d8c6a, 0x7d7df7,
+    0x7d6f85, 0x7d6115, 0x7d52a6, 0x7d443a, 0x7d35ce, 0x7d2765, 0x7d18fd, 0x7d0a97, 0x7cfc32, 0x7cedd0, 0x7cdf6e, 0x7cd10f, 0x7cc2b1, 0x7cb455, 0x7ca5fa,
+    0x7c97a1, 0x7c894a, 0x7c7af4, 0x7c6ca0, 0x7c5e4e, 0x7c4ffd, 0x7c41ae, 0x7c3361, 0x7c2515, 0x7c16cb, 0x7c0882, 0x7bfa3b, 0x7bebf6, 0x7bddb3, 0x7bcf71,
+    0x7bc131, 0x7bb2f2, 0x7ba4b5, 0x7b967a, 0x7b8840, 0x7b7a08, 0x7b6bd2, 0x7b5d9d, 0x7b4f6a, 0x7b4138, 0x7b3308, 0x7b24da, 0x7b16ad, 0x7b0882, 0x7afa59,
+    0x7aec31, 0x7ade0b, 0x7acfe7, 0x7ac1c4, 0x7ab3a3, 0x7aa583, 0x7a9765, 0x7a8949, 0x7a7b2e, 0x7a6d15, 0x7a5efd, 0x7a50e8, 0x7a42d3, 0x7a34c1, 0x7a26b0,
+    0x7a18a0, 0x7a0a93, 0x79fc87, 0x79ee7c, 0x79e073, 0x79d26c, 0x79c466, 0x79b662, 0x79a860, 0x799a5f, 0x798c60, 0x797e62, 0x797066, 0x79626c, 0x795473,
+    0x79467c, 0x793886, 0x792a92, 0x791ca0, 0x790eaf, 0x7900c0, 0x78f2d3, 0x78e4e7, 0x78d6fc, 0x78c914, 0x78bb2d, 0x78ad47, 0x789f63, 0x789181, 0x7883a0,
+    0x7875c1, 0x7867e3, 0x785a07, 0x784c2d, 0x783e54, 0x78307d, 0x7822a8, 0x7814d4, 0x780701, 0x77f931, 0x77eb61, 0x77dd94, 0x77cfc8, 0x77c1fd, 0x77b434,
+    0x77a66d, 0x7798a8, 0x778ae3, 0x777d21, 0x776f60, 0x7761a1, 0x7753e3, 0x774627, 0x77386c, 0x772ab3, 0x771cfc, 0x770f46, 0x770192, 0x76f3df, 0x76e62e,
+    0x76d87e, 0x76cad0, 0x76bd24, 0x76af79, 0x76a1d0, 0x769428, 0x768682, 0x7678de, 0x766b3b, 0x765d99, 0x764ffa, 0x76425b, 0x7634bf, 0x762723, 0x76198a,
+    0x760bf2, 0x75fe5c, 0x75f0c7, 0x75e333, 0x75d5a2, 0x75c811, 0x75ba83, 0x75acf6, 0x759f6a, 0x7591e0, 0x758458, 0x7576d1, 0x75694c, 0x755bc8, 0x754e46,
+    0x7540c6, 0x753347, 0x7525c9, 0x75184d, 0x750ad3, 0x74fd5a, 0x74efe3, 0x74e26d, 0x74d4f9, 0x74c786, 0x74ba15, 0x74aca6, 0x749f38, 0x7491cb, 0x748460,
+    0x7476f7, 0x74698f, 0x745c29, 0x744ec4, 0x744161, 0x7433ff, 0x74269f, 0x741941, 0x740be4, 0x73fe88, 0x73f12e, 0x73e3d6, 0x73d67f, 0x73c92a, 0x73bbd6,
+    0x73ae84, 0x73a133, 0x7393e4, 0x738696, 0x73794a, 0x736bff, 0x735eb6, 0x73516f, 0x734429, 0x7336e4, 0x7329a1, 0x731c60, 0x730f20, 0x7301e1, 0x72f4a5,
+    0x72e769, 0x72da2f, 0x72ccf7, 0x72bfc0, 0x72b28b, 0x72a557, 0x729825, 0x728af4, 0x727dc5, 0x727098, 0x72636c, 0x725641, 0x724918, 0x723bf0, 0x722eca,
+    0x7221a6, 0x721482, 0x720761, 0x71fa41, 0x71ed22, 0x71e005, 0x71d2ea, 0x71c5d0, 0x71b8b7, 0x71aba0, 0x719e8b, 0x719177, 0x718465, 0x717754, 0x716a44,
+    0x715d36, 0x71502a, 0x71431f, 0x713615, 0x71290e, 0x711c07, 0x710f02, 0x7101ff, 0x70f4fd, 0x70e7fc, 0x70dafd, 0x70ce00, 0x70c104, 0x70b40a, 0x70a711,
+    0x709a19, 0x708d23, 0x70802f, 0x70733c, 0x70664a, 0x70595a, 0x704c6c, 0x703f7f, 0x703293, 0x7025a9, 0x7018c0, 0x700bd9, 0x6ffef4, 0x6ff20f, 0x6fe52d,
+    0x6fd84c, 0x6fcb6c, 0x6fbe8e, 0x6fb1b1, 0x6fa4d6, 0x6f97fc, 0x6f8b24, 0x6f7e4d, 0x6f7178, 0x6f64a4, 0x6f57d2, 0x6f4b01, 0x6f3e31, 0x6f3163, 0x6f2497,
+    0x6f17cc, 0x6f0b02, 0x6efe3a, 0x6ef174, 0x6ee4af, 0x6ed7eb, 0x6ecb29, 0x6ebe68, 0x6eb1a9, 0x6ea4eb, 0x6e982f, 0x6e8b74, 0x6e7ebb, 0x6e7203, 0x6e654c,
+    0x6e5897, 0x6e4be4, 0x6e3f32, 0x6e3281, 0x6e25d2, 0x6e1924, 0x6e0c78, 0x6dffcd, 0x6df324, 0x6de67c, 0x6dd9d6, 0x6dcd31, 0x6dc08e, 0x6db3ec, 0x6da74b,
+    0x6d9aac, 0x6d8e0e, 0x6d8172, 0x6d74d7, 0x6d683e, 0x6d5ba6, 0x6d4f10, 0x6d427b, 0x6d35e7, 0x6d2955, 0x6d1cc5, 0x6d1036, 0x6d03a8, 0x6cf71c, 0x6cea91,
+    0x6cde07, 0x6cd17f, 0x6cc4f9, 0x6cb874, 0x6cabf0, 0x6c9f6e, 0x6c92ed, 0x6c866e, 0x6c79f0, 0x6c6d74, 0x6c60f9, 0x6c547f, 0x6c4807, 0x6c3b91, 0x6c2f1b,
+    0x6c22a8, 0x6c1635, 0x6c09c4, 0x6bfd55, 0x6bf0e7, 0x6be47a, 0x6bd80f, 0x6bcba5, 0x6bbf3d, 0x6bb2d6, 0x6ba670, 0x6b9a0c, 0x6b8daa, 0x6b8148, 0x6b74e9,
+    0x6b688a, 0x6b5c2d, 0x6b4fd2, 0x6b4378, 0x6b371f, 0x6b2ac8, 0x6b1e72, 0x6b121d, 0x6b05ca, 0x6af979, 0x6aed29, 0x6ae0da, 0x6ad48d, 0x6ac841, 0x6abbf6,
+    0x6aafad, 0x6aa365, 0x6a971f, 0x6a8ada, 0x6a7e97, 0x6a7255, 0x6a6614, 0x6a59d5, 0x6a4d97, 0x6a415b, 0x6a3520, 0x6a28e6, 0x6a1cae, 0x6a1078, 0x6a0442,
+    0x69f80e, 0x69ebdc, 0x69dfab, 0x69d37b, 0x69c74d, 0x69bb20, 0x69aef4, 0x69a2ca, 0x6996a1, 0x698a7a, 0x697e54, 0x697230, 0x69660c, 0x6959eb, 0x694dca,
+    0x6941ab, 0x69358e, 0x692972, 0x691d57, 0x69113e, 0x690526, 0x68f90f, 0x68ecfa, 0x68e0e6, 0x68d4d4, 0x68c8c3, 0x68bcb3, 0x68b0a5, 0x68a498, 0x68988d,
+    0x688c83, 0x68807a, 0x687473, 0x68686d, 0x685c68, 0x685065, 0x684463, 0x683863, 0x682c64, 0x682066, 0x68146a, 0x68086f, 0x67fc76, 0x67f07d, 0x67e487,
+    0x67d891, 0x67cc9d, 0x67c0ab, 0x67b4ba, 0x67a8ca, 0x679cdb, 0x6790ee, 0x678502, 0x677918, 0x676d2f, 0x676147, 0x675561, 0x67497c, 0x673d99, 0x6731b7,
+    0x6725d6, 0x6719f7, 0x670e19, 0x67023c, 0x66f661, 0x66ea87, 0x66deae, 0x66d2d7, 0x66c701, 0x66bb2d, 0x66af59, 0x66a388, 0x6697b7, 0x668be8, 0x66801a,
+    0x66744e, 0x666883, 0x665cba, 0x6650f1, 0x66452a, 0x663965, 0x662da1, 0x6621de, 0x66161c, 0x660a5c, 0x65fe9e, 0x65f2e0, 0x65e724, 0x65db69, 0x65cfb0,
+    0x65c3f8, 0x65b841, 0x65ac8c, 0x65a0d8, 0x659525, 0x658974, 0x657dc4, 0x657216, 0x656668, 0x655abc, 0x654f12, 0x654369, 0x6537c1, 0x652c1a, 0x652075,
+    0x6514d1, 0x65092f, 0x64fd8d, 0x64f1ee, 0x64e64f, 0x64dab2, 0x64cf16, 0x64c37c, 0x64b7e3, 0x64ac4b, 0x64a0b4, 0x64951f, 0x64898b, 0x647df9, 0x647268,
+    0x6466d8, 0x645b49, 0x644fbc, 0x644430, 0x6438a6, 0x642d1d, 0x642195, 0x64160e, 0x640a89, 0x63ff05, 0x63f383, 0x63e802, 0x63dc82, 0x63d103, 0x63c586,
+    0x63ba0a, 0x63ae8f, 0x63a316, 0x63979e, 0x638c28, 0x6380b2, 0x63753e, 0x6369cc, 0x635e5a, 0x6352ea, 0x63477b, 0x633c0e, 0x6330a2, 0x632537, 0x6319ce,
+    0x630e66, 0x6302ff, 0x62f799, 0x62ec35, 0x62e0d2, 0x62d571, 0x62ca10, 0x62beb1, 0x62b354, 0x62a7f7, 0x629c9c, 0x629142, 0x6285ea, 0x627a93, 0x626f3d,
+    0x6263e9, 0x625895, 0x624d43, 0x6241f3, 0x6236a4, 0x622b56, 0x622009, 0x6214bd, 0x620973, 0x61fe2b, 0x61f2e3, 0x61e79d, 0x61dc58, 0x61d114, 0x61c5d2,
+    0x61ba91, 0x61af51, 0x61a413, 0x6198d6, 0x618d9a, 0x61825f, 0x617726, 0x616bee, 0x6160b7, 0x615582, 0x614a4e, 0x613f1b, 0x6133ea, 0x6128b9, 0x611d8a,
+    0x61125d, 0x610730, 0x60fc05, 0x60f0dc, 0x60e5b3, 0x60da8c, 0x60cf66, 0x60c441, 0x60b91e, 0x60adfc, 0x60a2db, 0x6097bc, 0x608c9d, 0x608180, 0x607665,
+    0x606b4a, 0x606031, 0x605519, 0x604a03, 0x603eed, 0x6033d9, 0x6028c7, 0x601db5, 0x6012a5, 0x600796, 0x5ffc88, 0x5ff17c, 0x5fe671, 0x5fdb67, 0x5fd05e,
+    0x5fc557, 0x5fba51, 0x5faf4c, 0x5fa449, 0x5f9947, 0x5f8e46, 0x5f8346, 0x5f7848, 0x5f6d4a, 0x5f624e, 0x5f5754, 0x5f4c5a, 0x5f4162, 0x5f366c, 0x5f2b76,
+    0x5f2082, 0x5f158f, 0x5f0a9d, 0x5effac, 0x5ef4bd, 0x5ee9cf, 0x5edee2, 0x5ed3f7, 0x5ec90c, 0x5ebe23, 0x5eb33c, 0x5ea855, 0x5e9d70, 0x5e928c, 0x5e87a9,
+    0x5e7cc8, 0x5e71e8, 0x5e6709, 0x5e5c2b, 0x5e514f, 0x5e4673, 0x5e3b99, 0x5e30c1, 0x5e25e9, 0x5e1b13, 0x5e103e, 0x5e056a, 0x5dfa98, 0x5defc7, 0x5de4f7,
+    0x5dda28, 0x5dcf5a, 0x5dc48e, 0x5db9c3, 0x5daef9, 0x5da431, 0x5d996a, 0x5d8ea4, 0x5d83df, 0x5d791b, 0x5d6e59, 0x5d6398, 0x5d58d8, 0x5d4e19, 0x5d435c,
+    0x5d38a0, 0x5d2de5, 0x5d232b, 0x5d1873, 0x5d0dbc, 0x5d0306, 0x5cf851, 0x5ced9d, 0x5ce2eb, 0x5cd83a, 0x5ccd8a, 0x5cc2dc, 0x5cb82e, 0x5cad82, 0x5ca2d7,
+    0x5c982e, 0x5c8d85, 0x5c82de, 0x5c7838, 0x5c6d93, 0x5c62f0, 0x5c584e, 0x5c4dad, 0x5c430d, 0x5c386e, 0x5c2dd1, 0x5c2334, 0x5c1899, 0x5c0e00, 0x5c0367,
+    0x5bf8d0, 0x5bee3a, 0x5be3a5, 0x5bd911, 0x5bce7f, 0x5bc3ee, 0x5bb95e, 0x5baecf, 0x5ba441, 0x5b99b5, 0x5b8f2a, 0x5b84a0, 0x5b7a17, 0x5b6f90, 0x5b6509,
+    0x5b5a84, 0x5b5000, 0x5b457e, 0x5b3afc, 0x5b307c, 0x5b25fd, 0x5b1b7f, 0x5b1103, 0x5b0687, 0x5afc0d, 0x5af194, 0x5ae71c, 0x5adca6, 0x5ad230, 0x5ac7bc,
+    0x5abd49, 0x5ab2d7, 0x5aa867, 0x5a9df7, 0x5a9389, 0x5a891c, 0x5a7eb1, 0x5a7446, 0x5a69dd, 0x5a5f74, 0x5a550d, 0x5a4aa8, 0x5a4043, 0x5a35e0, 0x5a2b7e,
+    0x5a211d, 0x5a16bd, 0x5a0c5e, 0x5a0201, 0x59f7a5, 0x59ed4a, 0x59e2f0, 0x59d897, 0x59ce40, 0x59c3e9, 0x59b994, 0x59af40, 0x59a4ee, 0x599a9c, 0x59904c,
+    0x5985fd, 0x597baf, 0x597162, 0x596717, 0x595ccc, 0x595283, 0x59483b, 0x593df4, 0x5933ae, 0x59296a, 0x591f27, 0x5914e5, 0x590aa4, 0x590064, 0x58f625,
+    0x58ebe8, 0x58e1ac, 0x58d771, 0x58cd37, 0x58c2fe, 0x58b8c7, 0x58ae90, 0x58a45b, 0x589a27, 0x588ff5, 0x5885c3, 0x587b93, 0x587163, 0x586735, 0x585d08,
+    0x5852dc, 0x5848b2, 0x583e88, 0x583460, 0x582a39, 0x582013, 0x5815ee, 0x580bcb, 0x5801a9, 0x57f787, 0x57ed67, 0x57e348, 0x57d92b, 0x57cf0e, 0x57c4f3,
+    0x57bad8, 0x57b0bf, 0x57a6a7, 0x579c91, 0x57927b, 0x578866, 0x577e53, 0x577441, 0x576a30, 0x576020, 0x575612, 0x574c04, 0x5741f8, 0x5737ed, 0x572de3,
+    0x5723da, 0x5719d2, 0x570fcc, 0x5705c6, 0x56fbc2, 0x56f1bf, 0x56e7bd, 0x56ddbc, 0x56d3bc, 0x56c9be, 0x56bfc1, 0x56b5c4, 0x56abc9, 0x56a1cf, 0x5697d7,
+    0x568ddf, 0x5683e9, 0x5679f3, 0x566fff, 0x56660c, 0x565c1a, 0x56522a, 0x56483a, 0x563e4c, 0x56345e, 0x562a72, 0x562087, 0x56169d, 0x560cb5, 0x5602cd,
+    0x55f8e7, 0x55ef01, 0x55e51d, 0x55db3a, 0x55d158, 0x55c777, 0x55bd98, 0x55b3b9, 0x55a9dc, 0x55a000, 0x559625, 0x558c4b, 0x558272, 0x55789a, 0x556ec4,
+    0x5564ee, 0x555b1a, 0x555147, 0x554775, 0x553da4, 0x5533d4, 0x552a06, 0x552038, 0x55166c, 0x550ca1, 0x5502d7, 0x54f90e, 0x54ef46, 0x54e57f, 0x54dbba,
+    0x54d1f5, 0x54c832, 0x54be6f, 0x54b4ae, 0x54aaee, 0x54a130, 0x549772, 0x548db5, 0x5483fa, 0x547a3f, 0x547086, 0x5466ce, 0x545d17, 0x545361, 0x5449ac,
+    0x543ff9, 0x543646, 0x542c95, 0x5422e4, 0x541935, 0x540f87, 0x5405da, 0x53fc2e, 0x53f283, 0x53e8da, 0x53df31, 0x53d58a, 0x53cbe4, 0x53c23e, 0x53b89a,
+    0x53aef7, 0x53a555, 0x539bb5, 0x539215, 0x538877, 0x537ed9, 0x53753d, 0x536ba2, 0x536208, 0x53586f, 0x534ed7, 0x534540, 0x533baa, 0x533216, 0x532882,
+    0x531ef0, 0x53155e, 0x530bce, 0x53023f, 0x52f8b1, 0x52ef24, 0x52e599, 0x52dc0e, 0x52d284, 0x52c8fc, 0x52bf74, 0x52b5ee, 0x52ac69, 0x52a2e5, 0x529962,
+    0x528fe0, 0x52865f, 0x527cdf, 0x527361, 0x5269e3, 0x526067, 0x5256eb, 0x524d71, 0x5243f8, 0x523a80, 0x523109, 0x522793, 0x521e1e, 0x5214ab, 0x520b38,
+    0x5201c6, 0x51f856, 0x51eee7, 0x51e578, 0x51dc0b, 0x51d29f, 0x51c934, 0x51bfca, 0x51b661, 0x51acf9, 0x51a393, 0x519a2d, 0x5190c9, 0x518765, 0x517e03,
+    0x5174a1, 0x516b41, 0x5161e2, 0x515884, 0x514f27, 0x5145cb, 0x513c70, 0x513317, 0x5129be, 0x512066, 0x511710, 0x510dba, 0x510466, 0x50fb13, 0x50f1c1,
+    0x50e86f, 0x50df1f, 0x50d5d0, 0x50cc82, 0x50c336, 0x50b9ea, 0x50b09f, 0x50a755, 0x509e0d, 0x5094c5, 0x508b7f, 0x50823a, 0x5078f5, 0x506fb2, 0x506670,
+    0x505d2f, 0x5053ef, 0x504ab0, 0x504172, 0x503835, 0x502ef9, 0x5025be, 0x501c85, 0x50134c, 0x500a15, 0x5000de, 0x4ff7a9, 0x4fee74, 0x4fe541, 0x4fdc0f,
+    0x4fd2de, 0x4fc9ae, 0x4fc07e, 0x4fb750, 0x4fae23, 0x4fa4f8, 0x4f9bcd, 0x4f92a3, 0x4f897a, 0x4f8053, 0x4f772c, 0x4f6e06, 0x4f64e2, 0x4f5bbe, 0x4f529c,
+    0x4f497b, 0x4f405a, 0x4f373b, 0x4f2e1d, 0x4f2500, 0x4f1be4, 0x4f12c9, 0x4f09af, 0x4f0096, 0x4ef77e, 0x4eee67, 0x4ee551, 0x4edc3c, 0x4ed328, 0x4eca16,
+    0x4ec104, 0x4eb7f3, 0x4eaee4, 0x4ea5d5, 0x4e9cc8, 0x4e93bc, 0x4e8ab0, 0x4e81a6, 0x4e789c, 0x4e6f94, 0x4e668d, 0x4e5d87, 0x4e5482, 0x4e4b7e, 0x4e427a,
+    0x4e3978, 0x4e3077, 0x4e2777, 0x4e1e79, 0x4e157b, 0x4e0c7e, 0x4e0382, 0x4dfa87, 0x4df18d, 0x4de895, 0x4ddf9d, 0x4dd6a6, 0x4dcdb1, 0x4dc4bc, 0x4dbbc9,
+    0x4db2d6, 0x4da9e5, 0x4da0f4, 0x4d9805, 0x4d8f16, 0x4d8629, 0x4d7d3c, 0x4d7451, 0x4d6b67, 0x4d627e, 0x4d5995, 0x4d50ae, 0x4d47c8, 0x4d3ee3, 0x4d35ff,
+    0x4d2d1b, 0x4d2439, 0x4d1b58, 0x4d1278, 0x4d0999, 0x4d00bb, 0x4cf7de, 0x4cef02, 0x4ce627, 0x4cdd4d, 0x4cd474, 0x4ccb9c, 0x4cc2c5, 0x4cb9f0, 0x4cb11b,
+    0x4ca847, 0x4c9f74, 0x4c96a2, 0x4c8dd1, 0x4c8502, 0x4c7c33, 0x4c7365, 0x4c6a98, 0x4c61cd, 0x4c5902, 0x4c5038, 0x4c4770, 0x4c3ea8, 0x4c35e1, 0x4c2d1c,
+    0x4c2457, 0x4c1b93, 0x4c12d1, 0x4c0a0f, 0x4c014f, 0x4bf88f, 0x4befd0, 0x4be713, 0x4bde56, 0x4bd59b, 0x4bcce0, 0x4bc426, 0x4bbb6e, 0x4bb2b6, 0x4baa00,
+    0x4ba14a, 0x4b9896, 0x4b8fe2, 0x4b8730, 0x4b7e7e, 0x4b75cd, 0x4b6d1e, 0x4b646f, 0x4b5bc2, 0x4b5315, 0x4b4a6a, 0x4b41bf, 0x4b3916, 0x4b306d, 0x4b27c6,
+    0x4b1f1f, 0x4b1679, 0x4b0dd5, 0x4b0531, 0x4afc8f, 0x4af3ed, 0x4aeb4c, 0x4ae2ad, 0x4ada0e, 0x4ad171, 0x4ac8d4, 0x4ac038, 0x4ab79e, 0x4aaf04, 0x4aa66b,
+    0x4a9dd4, 0x4a953d, 0x4a8ca7, 0x4a8413, 0x4a7b7f, 0x4a72ec, 0x4a6a5a, 0x4a61ca, 0x4a593a, 0x4a50ab, 0x4a481d, 0x4a3f91, 0x4a3705, 0x4a2e7a, 0x4a25f0,
+    0x4a1d67, 0x4a14df, 0x4a0c58, 0x4a03d2, 0x49fb4d, 0x49f2c9, 0x49ea46, 0x49e1c4, 0x49d943, 0x49d0c3, 0x49c844, 0x49bfc6, 0x49b749, 0x49aecd, 0x49a652,
+    0x499dd7, 0x49955e, 0x498ce6, 0x49846f, 0x497bf8, 0x497383, 0x496b0f, 0x49629b, 0x495a29, 0x4951b8, 0x494947, 0x4940d8, 0x493869, 0x492ffc, 0x49278f,
+    0x491f23, 0x4916b9, 0x490e4f, 0x4905e6, 0x48fd7f, 0x48f518, 0x48ecb2, 0x48e44d, 0x48dbe9, 0x48d386, 0x48cb25, 0x48c2c4, 0x48ba64, 0x48b205, 0x48a9a6,
+    0x48a149, 0x4898ed, 0x489092, 0x488838, 0x487fdf, 0x487786, 0x486f2f, 0x4866d8, 0x485e83, 0x48562f, 0x484ddb, 0x484589, 0x483d37, 0x4834e6, 0x482c97,
+    0x482448, 0x481bfa, 0x4813ad, 0x480b62, 0x480317, 0x47facd, 0x47f284, 0x47ea3c, 0x47e1f5, 0x47d9ae, 0x47d169, 0x47c925, 0x47c0e2, 0x47b89f, 0x47b05e,
+    0x47a81e, 0x479fde, 0x4797a0, 0x478f62, 0x478725, 0x477eea, 0x4776af, 0x476e75, 0x47663c, 0x475e05, 0x4755ce, 0x474d98, 0x474563, 0x473d2f, 0x4734fb,
+    0x472cc9, 0x472498, 0x471c68, 0x471438, 0x470c0a, 0x4703dc, 0x46fbb0, 0x46f384, 0x46eb59, 0x46e330, 0x46db07, 0x46d2df, 0x46cab8, 0x46c292, 0x46ba6d,
+    0x46b249, 0x46aa26, 0x46a203, 0x4699e2, 0x4691c2, 0x4689a2, 0x468184, 0x467966, 0x46714a, 0x46692e, 0x466113, 0x4658f9, 0x4650e0, 0x4648c9, 0x4640b1,
+    0x46389b, 0x463086, 0x462872, 0x46205f, 0x46184c, 0x46103b, 0x46082a, 0x46001b, 0x45f80c, 0x45effe, 0x45e7f2, 0x45dfe6, 0x45d7db, 0x45cfd1, 0x45c7c8,
+    0x45bfbf, 0x45b7b8, 0x45afb2, 0x45a7ac, 0x459fa8, 0x4597a4, 0x458fa2, 0x4587a0, 0x457f9f, 0x45779f, 0x456fa0, 0x4567a2, 0x455fa5, 0x4557a9, 0x454fae,
+    0x4547b3, 0x453fba, 0x4537c1, 0x452fca, 0x4527d3, 0x451fdd, 0x4517e8, 0x450ff5, 0x450802, 0x45000f, 0x44f81e, 0x44f02e, 0x44e83f, 0x44e050, 0x44d863,
+    0x44d076, 0x44c88a, 0x44c09f, 0x44b8b6, 0x44b0cd, 0x44a8e4, 0x44a0fd, 0x449917, 0x449132, 0x44894d, 0x44816a, 0x447987, 0x4471a5, 0x4469c5, 0x4461e5,
+    0x445a06, 0x445228, 0x444a4b, 0x44426e, 0x443a93, 0x4432b8, 0x442adf, 0x442306, 0x441b2e, 0x441358, 0x440b82, 0x4403ad, 0x43fbd8, 0x43f405, 0x43ec33,
+    0x43e461, 0x43dc91, 0x43d4c1, 0x43ccf3, 0x43c525, 0x43bd58, 0x43b58c, 0x43adc1, 0x43a5f6, 0x439e2d, 0x439664, 0x438e9d, 0x4386d6, 0x437f10, 0x43774c,
+    0x436f88, 0x4367c5, 0x436002, 0x435841, 0x435081, 0x4348c1, 0x434102, 0x433945, 0x433188, 0x4329cc, 0x432211, 0x431a57, 0x43129d, 0x430ae5, 0x43032e,
+    0x42fb77, 0x42f3c1, 0x42ec0c, 0x42e458, 0x42dca5, 0x42d4f3, 0x42cd42, 0x42c591, 0x42bde2, 0x42b633, 0x42ae85, 0x42a6d9, 0x429f2d, 0x429781, 0x428fd7,
+    0x42882e, 0x428085, 0x4278de, 0x427137, 0x426991, 0x4261ec, 0x425a48, 0x4252a5, 0x424b03, 0x424361, 0x423bc1, 0x423421, 0x422c82, 0x4224e5, 0x421d48,
+    0x4215ab, 0x420e10, 0x420676, 0x41fedc, 0x41f744, 0x41efac, 0x41e815, 0x41e07f, 0x41d8ea, 0x41d155, 0x41c9c2, 0x41c22f, 0x41ba9e, 0x41b30d, 0x41ab7d,
+    0x41a3ee, 0x419c60, 0x4194d2, 0x418d46, 0x4185ba, 0x417e30, 0x4176a6, 0x416f1d, 0x416795, 0x41600d, 0x415887, 0x415102, 0x41497d, 0x4141f9, 0x413a76,
+    0x4132f4, 0x412b73, 0x4123f3, 0x411c73, 0x4114f5, 0x410d77, 0x4105fa, 0x40fe7e, 0x40f703, 0x40ef89, 0x40e80f, 0x40e097, 0x40d91f, 0x40d1a8, 0x40ca32,
+    0x40c2bd, 0x40bb49, 0x40b3d5, 0x40ac63, 0x40a4f1, 0x409d80, 0x409610, 0x408ea1, 0x408733, 0x407fc5, 0x407859, 0x4070ed, 0x406982, 0x406218, 0x405aaf,
+    0x405347, 0x404bdf, 0x404479, 0x403d13, 0x4035ae, 0x402e4a, 0x4026e7, 0x401f85, 0x401823, 0x4010c3, 0x400963, 0x400204, 0x3ffaa6, 0x3ff348, 0x3febec,
+    0x3fe490, 0x3fdd36, 0x3fd5dc, 0x3fce83, 0x3fc72b, 0x3fbfd3, 0x3fb87d, 0x3fb127, 0x3fa9d3, 0x3fa27f, 0x3f9b2c, 0x3f93d9, 0x3f8c88, 0x3f8537, 0x3f7de8,
+    0x3f7699, 0x3f6f4b, 0x3f67fd, 0x3f60b1, 0x3f5966, 0x3f521b, 0x3f4ad1, 0x3f4388, 0x3f3c40, 0x3f34f9, 0x3f2db2, 0x3f266c, 0x3f1f28, 0x3f17e4, 0x3f10a1,
+    0x3f095e, 0x3f021d, 0x3efadc, 0x3ef39c, 0x3eec5d, 0x3ee51f, 0x3edde2, 0x3ed6a6, 0x3ecf6a, 0x3ec82f, 0x3ec0f5, 0x3eb9bc, 0x3eb284, 0x3eab4c, 0x3ea416,
+    0x3e9ce0, 0x3e95ab, 0x3e8e77, 0x3e8743, 0x3e8011, 0x3e78df, 0x3e71ae, 0x3e6a7e, 0x3e634f, 0x3e5c21, 0x3e54f3, 0x3e4dc7, 0x3e469b, 0x3e3f70, 0x3e3845,
+    0x3e311c, 0x3e29f3, 0x3e22cc, 0x3e1ba5, 0x3e147f, 0x3e0d59, 0x3e0635, 0x3dff11, 0x3df7ef, 0x3df0cd, 0x3de9ab, 0x3de28b, 0x3ddb6b, 0x3dd44d, 0x3dcd2f,
+    0x3dc612, 0x3dbef6, 0x3db7da, 0x3db0c0, 0x3da9a6, 0x3da28d, 0x3d9b75, 0x3d945d, 0x3d8d47, 0x3d8631, 0x3d7f1c, 0x3d7808, 0x3d70f5, 0x3d69e2, 0x3d62d1,
+    0x3d5bc0, 0x3d54b0, 0x3d4da1, 0x3d4692, 0x3d3f85, 0x3d3878, 0x3d316c, 0x3d2a61, 0x3d2356, 0x3d1c4d, 0x3d1544, 0x3d0e3c, 0x3d0735, 0x3d002f, 0x3cf929,
+    0x3cf225, 0x3ceb21, 0x3ce41e, 0x3cdd1c, 0x3cd61a, 0x3ccf1a, 0x3cc81a, 0x3cc11b, 0x3cba1c, 0x3cb31f, 0x3cac22, 0x3ca527, 0x3c9e2c, 0x3c9731, 0x3c9038,
+    0x3c893f, 0x3c8248, 0x3c7b51, 0x3c745b, 0x3c6d65, 0x3c6671, 0x3c5f7d, 0x3c588a, 0x3c5198, 0x3c4aa6, 0x3c43b6, 0x3c3cc6, 0x3c35d7, 0x3c2ee9, 0x3c27fb,
+    0x3c210f, 0x3c1a23, 0x3c1338, 0x3c0c4e, 0x3c0564, 0x3bfe7c, 0x3bf794, 0x3bf0ad, 0x3be9c7, 0x3be2e1, 0x3bdbfd, 0x3bd519, 0x3bce36, 0x3bc753, 0x3bc072,
+    0x3bb991, 0x3bb2b1, 0x3babd2, 0x3ba4f4, 0x3b9e17, 0x3b973a, 0x3b905e, 0x3b8983, 0x3b82a8, 0x3b7bcf, 0x3b74f6, 0x3b6e1e, 0x3b6747, 0x3b6070, 0x3b599b,
+    0x3b52c6, 0x3b4bf2, 0x3b451f, 0x3b3e4c, 0x3b377b, 0x3b30aa, 0x3b29da, 0x3b230a, 0x3b1c3c, 0x3b156e, 0x3b0ea1, 0x3b07d5, 0x3b0109, 0x3afa3f, 0x3af375,
+    0x3aecac, 0x3ae5e3, 0x3adf1c, 0x3ad855, 0x3ad18f, 0x3acaca, 0x3ac406, 0x3abd42, 0x3ab67f, 0x3aafbd, 0x3aa8fc, 0x3aa23b, 0x3a9b7c, 0x3a94bd, 0x3a8dfe,
+    0x3a8741, 0x3a8084, 0x3a79c9, 0x3a730d, 0x3a6c53, 0x3a659a, 0x3a5ee1, 0x3a5829, 0x3a5172, 0x3a4abb, 0x3a4406, 0x3a3d51, 0x3a369d, 0x3a2fe9, 0x3a2937,
+    0x3a2285, 0x3a1bd4, 0x3a1524, 0x3a0e74, 0x3a07c5, 0x3a0118, 0x39fa6a, 0x39f3be, 0x39ed12, 0x39e667, 0x39dfbd, 0x39d914, 0x39d26b, 0x39cbc4, 0x39c51d,
+    0x39be76, 0x39b7d1, 0x39b12c, 0x39aa88, 0x39a3e5, 0x399d42, 0x3996a1, 0x399000, 0x398960, 0x3982c0, 0x397c22, 0x397584, 0x396ee7, 0x39684a, 0x3961af,
+    0x395b14, 0x39547a, 0x394de0, 0x394748, 0x3940b0, 0x393a19, 0x393383, 0x392ced, 0x392658, 0x391fc4, 0x391931, 0x39129f, 0x390c0d, 0x39057c, 0x38feec,
+    0x38f85c, 0x38f1ce, 0x38eb40, 0x38e4b2, 0x38de26, 0x38d79a, 0x38d10f, 0x38ca85, 0x38c3fc, 0x38bd73, 0x38b6eb, 0x38b064, 0x38a9de, 0x38a358, 0x389cd3,
+    0x38964f, 0x388fcb, 0x388949, 0x3882c7, 0x387c46, 0x3875c5, 0x386f45, 0x3868c7, 0x386248, 0x385bcb, 0x38554e, 0x384ed2, 0x384857, 0x3841dd, 0x383b63,
+    0x3834ea, 0x382e72, 0x3827fa, 0x382184, 0x381b0e, 0x381498, 0x380e24, 0x3807b0, 0x38013d, 0x37facb, 0x37f459, 0x37ede9, 0x37e778, 0x37e109, 0x37da9b,
+    0x37d42d, 0x37cdc0, 0x37c753, 0x37c0e8, 0x37ba7d, 0x37b413, 0x37ada9, 0x37a741, 0x37a0d9, 0x379a72, 0x37940b, 0x378da6, 0x378741, 0x3780dc, 0x377a79,
+    0x377416, 0x376db4, 0x376753, 0x3760f2, 0x375a93, 0x375433, 0x374dd5, 0x374777, 0x37411b, 0x373abe, 0x373463, 0x372e08, 0x3727ae, 0x372155, 0x371afd,
+    0x3714a5, 0x370e4e, 0x3707f8, 0x3701a2, 0x36fb4d, 0x36f4f9, 0x36eea6, 0x36e853, 0x36e201, 0x36dbb0, 0x36d55f, 0x36cf10, 0x36c8c1, 0x36c272, 0x36bc25,
+    0x36b5d8, 0x36af8c, 0x36a940, 0x36a2f6, 0x369cac, 0x369663, 0x36901a, 0x3689d2, 0x36838b, 0x367d45, 0x3676ff, 0x3670ba, 0x366a76, 0x366433, 0x365df0,
+    0x3657ae, 0x36516d, 0x364b2c, 0x3644ec, 0x363ead, 0x36386f, 0x363231, 0x362bf4, 0x3625b8, 0x361f7c, 0x361942, 0x361308, 0x360cce, 0x360695, 0x36005e,
+    0x35fa26
+};
+
+typedef struct {
+    uint64_t window;
+    unsigned char readahead, arg, control;
+    int running_gain;
+    unsigned sustain, sustain_reset;
+    int code_counterA;
+    int code_counterB;
+    int code_counterC;
+} hdcd_state_t;
+
+typedef struct HDCDContext {
+    const AVClass *class;
+    hdcd_state_t state[2];
+} HDCDContext;
+
+static const AVOption hdcd_options[] = {
+     {NULL}
+};
+
+AVFILTER_DEFINE_CLASS(hdcd);
+
+#define APPLY_GAIN(s,g) do{int64_t s64 = s; s64 *= gaintab[g]; s = (int32_t)(s64 >> 23); }while(0);
+
+static void hdcd_reset(hdcd_state_t *state, unsigned rate)
+{
+    state->window = 0;
+    state->readahead = 32;
+    state->arg = 0;
+    state->control = 0;
+
+    state->running_gain = 0;
+
+    state->sustain = 0;
+    state->sustain_reset = rate * 10;
+
+    state->code_counterA = 0;
+    state->code_counterB = 0;
+    state->code_counterC = 0;
+}
+
+static int integrate(hdcd_state_t *state, int *flag, const int32_t *samples, int count, int stride)
+{
+    uint32_t bits = 0;
+    int result = FFMIN(state->readahead, count);
+    int i;
+    *flag = 0;
+
+    for (i = result - 1; i >= 0; i--) {
+        bits |= (*samples & 1) << i; /* might be better as a conditional? */
+        samples += stride;
+    }
+
+    state->window = (state->window << result) | bits;
+    state->readahead -= result;
+    if (state->readahead > 0)
+        return result;
+
+    bits = (state->window ^ state->window >> 5 ^ state->window >> 23);
+
+    if (state->arg) {
+        if ((bits & 0xffffffc8) == 0x0fa00500) {
+            state->control = (bits & 255) + (bits & 7);
+            *flag = 1;
+            state->code_counterA++;
+        }
+        if (((bits ^ (~bits >> 8 & 255)) & 0xffff00ff) == 0xa0060000) {
+            state->control = bits >> 8 & 255;
+            *flag = 1;
+            state->code_counterB++;
+        }
+        state->arg = 0;
+    }
+    if (bits == 0x7e0fa005 || bits == 0x7e0fa006) {
+        state->readahead = (bits & 3) * 8;
+        state->arg = 1;
+        state->code_counterC++;
+    } else {
+        if (bits)
+            state->readahead = readaheadtab[bits & 0xff];
+        else
+            state->readahead = 31; /* ffwd over digisilence */
+    }
+    return result;
+}
+
+static int hdcd_scan(hdcd_state_t *state, const int32_t *samples, int max, int stride)
+{
+    int result;
+    if (state->sustain > 0) {
+        if (state->sustain <= max) {
+            state->control = 0;
+            max = state->sustain;
+        }
+        state->sustain -= max;
+    }
+    result = 0;
+    while (result < max) {
+        int flag;
+        int consumed = integrate(state, &flag, samples, max - result, stride);
+        result += consumed;
+        if (flag > 0) {
+            state->sustain = state->sustain_reset;
+            break;
+        }
+        samples += consumed * stride;
+    }
+    return result;
+}
+
+static int hdcd_envelope(int32_t *samples, int count, int stride, int gain, int target_gain, int extend)
+{
+    int i;
+    int32_t *samples_end = samples + stride * count;
+
+    if (extend) {
+        for (i = 0; i < count; i++) {
+            int32_t sample = samples[i * stride];
+            int32_t asample = abs(sample) - 0x5981;
+            if (asample >= 0)
+                sample = sample >= 0 ? peaktab[asample] : -peaktab[asample];
+            else
+                sample <<= 15;
+
+            samples[i * stride] = sample;
+        }
+    } else {
+        for (i = 0; i < count; i++)
+            samples[i * stride] <<= 15;
+    }
+
+    if (gain <= target_gain) {
+        int len = FFMIN(count, target_gain - gain);
+        /* attenuate slowly */
+        for (i = 0; i < len; i++) {
+            APPLY_GAIN(*samples, gain);
+            samples += stride;
+        }
+        count -= len;
+    } else {
+        int len = FFMIN(count, (gain - target_gain) >> 3);
+        /* amplify quickly */
+        for (i = 0; i < len; i++) {
+            gain -= 8;
+            APPLY_GAIN(*samples, gain);
+            samples += stride;
+        }
+        if (gain - 8 < target_gain)
+            gain = target_gain;
+        count -= len;
+    }
+
+    /* hold a steady level */
+    if (gain == 0) {
+        if (count > 0)
+            samples += count * stride;
+    } else {
+        while (--count >= 0) {
+            APPLY_GAIN(*samples, gain);
+            samples += stride;
+        }
+    }
+
+    av_assert0(samples == samples_end);
+
+    return gain;
+}
+
+static void hdcd_process(hdcd_state_t *state, int32_t *samples, int count, int stride)
+{
+    int32_t *samples_end = samples + count * stride;
+    int gain = state->running_gain;
+    int peak_extend = (state->control & 16);
+    int target_gain = (state->control & 15) << 7;
+    int lead = 0;
+
+    while (count > lead) {
+        int envelope_run;
+        int run;
+
+        av_assert0(samples + lead * stride + stride * (count - lead) <= samples_end);
+        run = hdcd_scan(state, samples + lead * stride, count - lead, stride) + lead;
+        envelope_run = run - 1;
+
+        av_assert0(samples + envelope_run * stride <= samples_end);
+        gain = hdcd_envelope(samples, envelope_run, stride, gain, target_gain, peak_extend);
+
+        samples += envelope_run * stride;
+        count -= envelope_run;
+        lead = run - envelope_run;
+        peak_extend = (state->control & 16);
+        target_gain = (state->control & 15) << 7;
+    }
+    if (lead > 0) {
+        av_assert0(samples + lead * stride <= samples_end);
+        gain = hdcd_envelope(samples, lead, stride, gain, target_gain, peak_extend);
+    }
+
+    state->running_gain = gain;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx = inlink->dst;
+    HDCDContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFrame *out;
+    const int16_t *in_data;
+    int32_t *out_data;
+    int n, c;
+
+    out = ff_get_audio_buffer(outlink, in->nb_samples);
+    if (!out) {
+        av_frame_free(&in);
+        return AVERROR(ENOMEM);
+    }
+    av_frame_copy_props(out, in);
+    out->format = outlink->format;
+
+    in_data  = (int16_t*)in->data[0];
+    out_data = (int32_t*)out->data[0];
+    for (n = 0; n < in->nb_samples * in->channels; n++) {
+        out_data[n] = in_data[n];
+    }
+
+    for (c = 0; c < inlink->channels; c++) {
+        hdcd_state_t *state = &s->state[c];
+        hdcd_process(state, out_data + c, in->nb_samples, out->channels);
+    }
+
+    av_frame_free(&in);
+    return ff_filter_frame(outlink, out);
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+    AVFilterFormats *in_formats;
+    AVFilterFormats *out_formats;
+    AVFilterFormats *sample_rates = NULL;
+    AVFilterChannelLayouts *layouts = NULL;
+    AVFilterLink *inlink  = ctx->inputs[0];
+    AVFilterLink *outlink = ctx->outputs[0];
+
+    static const enum AVSampleFormat sample_fmts_in[] = {
+        AV_SAMPLE_FMT_S16,
+        AV_SAMPLE_FMT_NONE
+    };
+    static const enum AVSampleFormat sample_fmts_out[] = {
+        AV_SAMPLE_FMT_S32,
+        AV_SAMPLE_FMT_NONE
+    };
+    int ret;
+
+    ret = ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO);
+    if (ret < 0)
+        return ret;
+
+    ret = ff_set_common_channel_layouts(ctx, layouts);
+    if (ret < 0)
+        return ret;
+
+    in_formats = ff_make_format_list(sample_fmts_in);
+    out_formats = ff_make_format_list(sample_fmts_out);
+    if (!in_formats || !out_formats)
+        return AVERROR(ENOMEM);
+
+    ret = ff_formats_ref(in_formats, &inlink->out_formats);
+    if (ret < 0)
+        return ret;
+    ret = ff_formats_ref(out_formats, &outlink->in_formats);
+    if (ret < 0)
+        return ret;
+
+    ret = ff_add_format(&sample_rates, 44100);
+    if (ret < 0)
+        return AVERROR(ENOMEM);
+
+    return ff_set_common_samplerates(ctx, sample_rates);
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    HDCDContext *s = ctx->priv;
+    int i;
+
+    for (i = 0; i < 2; i++) {
+        hdcd_state_t *state = &s->state[i];
+        av_log(ctx, AV_LOG_VERBOSE, "Channel %d: counter A: %d, B: %d, C: %d\n", i, state->code_counterA,
+                state->code_counterB, state->code_counterC);
+    }
+}
+
+static av_cold int init(AVFilterContext *ctx)
+{
+
+    HDCDContext *s = ctx->priv;
+    int c;
+
+    for (c = 0; c < 2; c++) {
+        hdcd_reset(&s->state[c], 44100);
+    }
+
+    return 0;
+}
+
+static const AVFilterPad avfilter_af_hdcd_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_AUDIO,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad avfilter_af_hdcd_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_AUDIO,
+    },
+    { NULL }
+};
+
+AVFilter ff_af_hdcd = {
+    .name          = "hdcd",
+    .description   = NULL_IF_CONFIG_SMALL("Apply high definition audio cd decoding."),
+    .priv_size     = sizeof(HDCDContext),
+    .priv_class    = &hdcd_class,
+    .init          = init,
+    .uninit        = uninit,
+    .query_formats = query_formats,
+    .inputs        = avfilter_af_hdcd_inputs,
+    .outputs       = avfilter_af_hdcd_outputs,
+};
diff --git a/libavfilter/af_loudnorm.c b/libavfilter/af_loudnorm.c
new file mode 100644
index 0000000..604697e
--- /dev/null
+++ b/libavfilter/af_loudnorm.c
@@ -0,0 +1,920 @@
+/*
+ * Copyright (c) 2016 Kyle Swanson <k at ylo.ph>.
+ *
+ * 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
+ */
+
+/* http://k.ylo.ph/2016/04/04/loudnorm.html */
+
+#include "libavutil/opt.h"
+#include "avfilter.h"
+#include "internal.h"
+#include "audio.h"
+#include <ebur128.h>
+
+enum FrameType {
+    FIRST_FRAME,
+    INNER_FRAME,
+    FINAL_FRAME,
+    LINEAR_MODE,
+    FRAME_NB
+};
+
+enum LimiterState {
+    OUT,
+    ATTACK,
+    SUSTAIN,
+    RELEASE,
+    STATE_NB
+};
+
+enum PrintFormat {
+    NONE,
+    JSON,
+    SUMMARY,
+    PF_NB
+};
+
+typedef struct LoudNormContext {
+    const AVClass *class;
+    double target_i;
+    double target_lra;
+    double target_tp;
+    double measured_i;
+    double measured_lra;
+    double measured_tp;
+    double measured_thresh;
+    double offset;
+    int linear;
+    int dual_mono;
+    enum PrintFormat print_format;
+
+    double *buf;
+    int buf_size;
+    int buf_index;
+    int prev_buf_index;
+
+    double delta[30];
+    double weights[21];
+    double prev_delta;
+    int index;
+
+    double gain_reduction[2];
+    double *limiter_buf;
+    double *prev_smp;
+    int limiter_buf_index;
+    int limiter_buf_size;
+    enum LimiterState limiter_state;
+    int peak_index;
+    int env_index;
+    int env_cnt;
+    int attack_length;
+    int release_length;
+
+    int64_t pts;
+    enum FrameType frame_type;
+    int above_threshold;
+    int prev_nb_samples;
+    int channels;
+
+    ebur128_state *r128_in;
+    ebur128_state *r128_out;
+} LoudNormContext;
+
+#define OFFSET(x) offsetof(LoudNormContext, x)
+#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+static const AVOption loudnorm_options[] = {
+    { "I",                "set integrated loudness target",    OFFSET(target_i),         AV_OPT_TYPE_DOUBLE,  {.dbl = -24.},   -70.,       -5.,  FLAGS },
+    { "i",                "set integrated loudness target",    OFFSET(target_i),         AV_OPT_TYPE_DOUBLE,  {.dbl = -24.},   -70.,       -5.,  FLAGS },
+    { "LRA",              "set loudness range target",         OFFSET(target_lra),       AV_OPT_TYPE_DOUBLE,  {.dbl =  7.},     1.,        20.,  FLAGS },
+    { "lra",              "set loudness range target",         OFFSET(target_lra),       AV_OPT_TYPE_DOUBLE,  {.dbl =  7.},     1.,        20.,  FLAGS },
+    { "TP",               "set maximum true peak",             OFFSET(target_tp),        AV_OPT_TYPE_DOUBLE,  {.dbl = -2.},    -9.,         0.,  FLAGS },
+    { "tp",               "set maximum true peak",             OFFSET(target_tp),        AV_OPT_TYPE_DOUBLE,  {.dbl = -2.},    -9.,         0.,  FLAGS },
+    { "measured_I",       "measured IL of input file",         OFFSET(measured_i),       AV_OPT_TYPE_DOUBLE,  {.dbl =  0.},    -99.,        0.,  FLAGS },
+    { "measured_i",       "measured IL of input file",         OFFSET(measured_i),       AV_OPT_TYPE_DOUBLE,  {.dbl =  0.},    -99.,        0.,  FLAGS },
+    { "measured_LRA",     "measured LRA of input file",        OFFSET(measured_lra),     AV_OPT_TYPE_DOUBLE,  {.dbl =  0.},     0.,        99.,  FLAGS },
+    { "measured_lra",     "measured LRA of input file",        OFFSET(measured_lra),     AV_OPT_TYPE_DOUBLE,  {.dbl =  0.},     0.,        99.,  FLAGS },
+    { "measured_TP",      "measured true peak of input file",  OFFSET(measured_tp),      AV_OPT_TYPE_DOUBLE,  {.dbl =  99.},   -99.,       99.,  FLAGS },
+    { "measured_tp",      "measured true peak of input file",  OFFSET(measured_tp),      AV_OPT_TYPE_DOUBLE,  {.dbl =  99.},   -99.,       99.,  FLAGS },
+    { "measured_thresh",  "measured threshold of input file",  OFFSET(measured_thresh),  AV_OPT_TYPE_DOUBLE,  {.dbl = -70.},   -99.,        0.,  FLAGS },
+    { "offset",           "set offset gain",                   OFFSET(offset),           AV_OPT_TYPE_DOUBLE,  {.dbl =  0.},    -99.,       99.,  FLAGS },
+    { "linear",           "normalize linearly if possible",    OFFSET(linear),           AV_OPT_TYPE_BOOL,    {.i64 =  1},        0,         1,  FLAGS },
+    { "dual_mono",        "treat mono input as dual-mono",     OFFSET(dual_mono),        AV_OPT_TYPE_BOOL,    {.i64 =  0},        0,         1,  FLAGS },
+    { "print_format",     "set print format for stats",        OFFSET(print_format),     AV_OPT_TYPE_INT,     {.i64 =  NONE},  NONE,  PF_NB -1,  FLAGS, "print_format" },
+    {     "none",         0,                                   0,                        AV_OPT_TYPE_CONST,   {.i64 =  NONE},     0,         0,  FLAGS, "print_format" },
+    {     "json",         0,                                   0,                        AV_OPT_TYPE_CONST,   {.i64 =  JSON},     0,         0,  FLAGS, "print_format" },
+    {     "summary",      0,                                   0,                        AV_OPT_TYPE_CONST,   {.i64 =  SUMMARY},  0,         0,  FLAGS, "print_format" },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(loudnorm);
+
+static inline int frame_size(int sample_rate, int frame_len_msec)
+{
+    const int frame_size = round((double)sample_rate * (frame_len_msec / 1000.0));
+    return frame_size + (frame_size % 2);
+}
+
+static void init_gaussian_filter(LoudNormContext *s)
+{
+    double total_weight = 0.0;
+    const double sigma = 3.5;
+    double adjust;
+    int i;
+
+    const int offset = 21 / 2;
+    const double c1 = 1.0 / (sigma * sqrt(2.0 * M_PI));
+    const double c2 = 2.0 * pow(sigma, 2.0);
+
+    for (i = 0; i < 21; i++) {
+        const int x = i - offset;
+        s->weights[i] = c1 * exp(-(pow(x, 2.0) / c2));
+        total_weight += s->weights[i];
+    }
+
+    adjust = 1.0 / total_weight;
+    for (i = 0; i < 21; i++)
+        s->weights[i] *= adjust;
+}
+
+static double gaussian_filter(LoudNormContext *s, int index)
+{
+    double result = 0.;
+    int i;
+
+    index = index - 10 > 0 ? index - 10 : index + 20;
+    for (i = 0; i < 21; i++)
+        result += s->delta[((index + i) < 30) ? (index + i) : (index + i - 30)] * s->weights[i];
+
+    return result;
+}
+
+static void detect_peak(LoudNormContext *s, int offset, int nb_samples, int channels, int *peak_delta, double *peak_value)
+{
+    int n, c, i, index;
+    double ceiling;
+    double *buf;
+
+    *peak_delta = -1;
+    buf = s->limiter_buf;
+    ceiling = s->target_tp;
+
+    index = s->limiter_buf_index + (offset * channels) + (1920 * channels);
+    if (index >= s->limiter_buf_size)
+        index -= s->limiter_buf_size;
+
+    if (s->frame_type == FIRST_FRAME) {
+        for (c = 0; c < channels; c++)
+            s->prev_smp[c] = fabs(buf[index + c - channels]);
+    }
+
+    for (n = 0; n < nb_samples; n++) {
+        for (c = 0; c < channels; c++) {
+            double this, next, max_peak;
+
+            this = fabs(buf[(index + c) < s->limiter_buf_size ? (index + c) : (index + c - s->limiter_buf_size)]);
+            next = fabs(buf[(index + c + channels) < s->limiter_buf_size ? (index + c + channels) : (index + c + channels - s->limiter_buf_size)]);
+
+            if ((s->prev_smp[c] <= this) && (next <= this) && (this > ceiling) && (n > 0)) {
+                int detected;
+
+                detected = 1;
+                for (i = 2; i < 12; i++) {
+                    next = fabs(buf[(index + c + (i * channels)) < s->limiter_buf_size ? (index + c + (i * channels)) : (index + c + (i * channels) - s->limiter_buf_size)]);
+                    if (next > this) {
+                        detected = 0;
+                        break;
+                    }
+                }
+
+                if (!detected)
+                    continue;
+
+                for (c = 0; c < channels; c++) {
+                    if (c == 0 || fabs(buf[index + c]) > max_peak)
+                        max_peak = fabs(buf[index + c]);
+
+                    s->prev_smp[c] = fabs(buf[(index + c) < s->limiter_buf_size ? (index + c) : (index + c - s->limiter_buf_size)]);
+                }
+
+                *peak_delta = n;
+                s->peak_index = index;
+                *peak_value = max_peak;
+                return;
+            }
+
+            s->prev_smp[c] = this;
+        }
+
+        index += channels;
+        if (index >= s->limiter_buf_size)
+            index -= s->limiter_buf_size;
+    }
+}
+
+static void true_peak_limiter(LoudNormContext *s, double *out, int nb_samples, int channels)
+{
+    int n, c, index, peak_delta, smp_cnt;
+    double ceiling, peak_value;
+    double *buf;
+
+    buf = s->limiter_buf;
+    ceiling = s->target_tp;
+    index = s->limiter_buf_index;
+    smp_cnt = 0;
+
+    if (s->frame_type == FIRST_FRAME) {
+        double max;
+
+        max = 0.;
+        for (n = 0; n < 1920; n++) {
+            for (c = 0; c < channels; c++) {
+              max = fabs(buf[c]) > max ? fabs(buf[c]) : max;
+            }
+            buf += channels;
+        }
+
+        if (max > ceiling) {
+            s->gain_reduction[1] = ceiling / max;
+            s->limiter_state = SUSTAIN;
+            buf = s->limiter_buf;
+
+            for (n = 0; n < 1920; n++) {
+                for (c = 0; c < channels; c++) {
+                    double env;
+                    env = s->gain_reduction[1];
+                    buf[c] *= env;
+                }
+                buf += channels;
+            }
+        }
+
+        buf = s->limiter_buf;
+    }
+
+    do {
+
+        switch(s->limiter_state) {
+        case OUT:
+            detect_peak(s, smp_cnt, nb_samples - smp_cnt, channels, &peak_delta, &peak_value);
+            if (peak_delta != -1) {
+                s->env_cnt = 0;
+                smp_cnt += (peak_delta - s->attack_length);
+                s->gain_reduction[0] = 1.;
+                s->gain_reduction[1] = ceiling / peak_value;
+                s->limiter_state = ATTACK;
+
+                s->env_index = s->peak_index - (s->attack_length * channels);
+                if (s->env_index < 0)
+                    s->env_index += s->limiter_buf_size;
+
+                s->env_index += (s->env_cnt * channels);
+                if (s->env_index > s->limiter_buf_size)
+                    s->env_index -= s->limiter_buf_size;
+
+            } else {
+                smp_cnt = nb_samples;
+            }
+            break;
+
+        case ATTACK:
+            for (; s->env_cnt < s->attack_length; s->env_cnt++) {
+                for (c = 0; c < channels; c++) {
+                    double env;
+                    env = s->gain_reduction[0] - ((double) s->env_cnt / (s->attack_length - 1) * (s->gain_reduction[0] - s->gain_reduction[1]));
+                    buf[s->env_index + c] *= env;
+                }
+
+                s->env_index += channels;
+                if (s->env_index >= s->limiter_buf_size)
+                    s->env_index -= s->limiter_buf_size;
+
+                smp_cnt++;
+                if (smp_cnt >= nb_samples) {
+                    s->env_cnt++;
+                    break;
+                }
+            }
+
+            if (smp_cnt < nb_samples) {
+                s->env_cnt = 0;
+                s->attack_length = 1920;
+                s->limiter_state = SUSTAIN;
+            }
+            break;
+
+        case SUSTAIN:
+            detect_peak(s, smp_cnt, nb_samples, channels, &peak_delta, &peak_value);
+            if (peak_delta == -1) {
+                s->limiter_state = RELEASE;
+                s->gain_reduction[0] = s->gain_reduction[1];
+                s->gain_reduction[1] = 1.;
+                s->env_cnt = 0;
+                break;
+            } else {
+                double gain_reduction;
+                gain_reduction = ceiling / peak_value;
+
+                if (gain_reduction < s->gain_reduction[1]) {
+                    s->limiter_state = ATTACK;
+
+                    s->attack_length = peak_delta;
+                    if (s->attack_length <= 1)
+                        s->attack_length =  2;
+
+                    s->gain_reduction[0] = s->gain_reduction[1];
+                    s->gain_reduction[1] = gain_reduction;
+                    s->env_cnt = 0;
+                    break;
+                }
+
+                for (s->env_cnt = 0; s->env_cnt < peak_delta; s->env_cnt++) {
+                    for (c = 0; c < channels; c++) {
+                        double env;
+                        env = s->gain_reduction[1];
+                        buf[s->env_index + c] *= env;
+                    }
+
+                    s->env_index += channels;
+                    if (s->env_index >= s->limiter_buf_size)
+                        s->env_index -= s->limiter_buf_size;
+
+                    smp_cnt++;
+                    if (smp_cnt >= nb_samples) {
+                        s->env_cnt++;
+                        break;
+                    }
+                }
+            }
+            break;
+
+        case RELEASE:
+            for (; s->env_cnt < s->release_length; s->env_cnt++) {
+                for (c = 0; c < channels; c++) {
+                    double env;
+                    env = s->gain_reduction[0] + (((double) s->env_cnt / (s->release_length - 1)) * (s->gain_reduction[1] - s->gain_reduction[0]));
+                    buf[s->env_index + c] *= env;
+                }
+
+                s->env_index += channels;
+                if (s->env_index >= s->limiter_buf_size)
+                    s->env_index -= s->limiter_buf_size;
+
+                smp_cnt++;
+                if (smp_cnt >= nb_samples) {
+                    s->env_cnt++;
+                    break;
+                }
+            }
+
+            if (smp_cnt < nb_samples) {
+                s->env_cnt = 0;
+                s->limiter_state = OUT;
+            }
+
+            break;
+        }
+
+    } while (smp_cnt < nb_samples);
+
+    for (n = 0; n < nb_samples; n++) {
+        for (c = 0; c < channels; c++) {
+            out[c] = buf[index + c];
+            if (fabs(out[c]) > ceiling) {
+                out[c] = ceiling * (out[c] < 0 ? -1 : 1);
+            }
+        }
+        out += channels;
+        index += channels;
+        if (index >= s->limiter_buf_size)
+            index -= s->limiter_buf_size;
+    }
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx = inlink->dst;
+    LoudNormContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFrame *out;
+    const double *src;
+    double *dst;
+    double *buf;
+    double *limiter_buf;
+    int i, n, c, subframe_length, src_index;
+    double gain, gain_next, env_global, env_shortterm,
+    global, shortterm, lra, relative_threshold;
+
+    if (av_frame_is_writable(in)) {
+        out = in;
+    } else {
+        out = ff_get_audio_buffer(inlink, in->nb_samples);
+        if (!out) {
+            av_frame_free(&in);
+            return AVERROR(ENOMEM);
+        }
+        av_frame_copy_props(out, in);
+    }
+
+    out->pts = s->pts;
+    src = (const double *)in->data[0];
+    dst = (double *)out->data[0];
+    buf = s->buf;
+    limiter_buf = s->limiter_buf;
+
+    ebur128_add_frames_double(s->r128_in, src, in->nb_samples);
+
+    if (s->frame_type == FIRST_FRAME && in->nb_samples < frame_size(inlink->sample_rate, 3000)) {
+        double offset, offset_tp, true_peak;
+
+        ebur128_loudness_global(s->r128_in, &global);
+        for (c = 0; c < inlink->channels; c++) {
+            double tmp;
+            ebur128_sample_peak(s->r128_in, c, &tmp);
+            if (c == 0 || tmp > true_peak)
+                true_peak = tmp;
+        }
+
+        offset    = s->target_i - global;
+        offset_tp = true_peak + offset;
+        s->offset = offset_tp < s->target_tp ? offset : s->target_tp - true_peak;
+        s->offset = pow(10., s->offset / 20.);
+        s->frame_type = LINEAR_MODE;
+    }
+
+    switch (s->frame_type) {
+    case FIRST_FRAME:
+        for (n = 0; n < in->nb_samples; n++) {
+            for (c = 0; c < inlink->channels; c++) {
+                buf[s->buf_index + c] = src[c];
+            }
+            src += inlink->channels;
+            s->buf_index += inlink->channels;
+        }
+
+        ebur128_loudness_shortterm(s->r128_in, &shortterm);
+
+        if (shortterm < s->measured_thresh) {
+            s->above_threshold = 0;
+            env_shortterm = shortterm <= -70. ? 0. : s->target_i - s->measured_i;
+        } else {
+            s->above_threshold = 1;
+            env_shortterm = shortterm <= -70. ? 0. : s->target_i - shortterm;
+        }
+
+        for (n = 0; n < 30; n++)
+            s->delta[n] = pow(10., env_shortterm / 20.);
+        s->prev_delta = s->delta[s->index];
+
+        s->buf_index =
+        s->limiter_buf_index = 0;
+
+        for (n = 0; n < (s->limiter_buf_size / inlink->channels); n++) {
+            for (c = 0; c < inlink->channels; c++) {
+                limiter_buf[s->limiter_buf_index + c] = buf[s->buf_index + c] * s->delta[s->index] * s->offset;
+            }
+            s->limiter_buf_index += inlink->channels;
+            if (s->limiter_buf_index >= s->limiter_buf_size)
+                s->limiter_buf_index -= s->limiter_buf_size;
+
+            s->buf_index += inlink->channels;
+        }
+
+        subframe_length = frame_size(inlink->sample_rate, 100);
+        true_peak_limiter(s, dst, subframe_length, inlink->channels);
+        ebur128_add_frames_double(s->r128_out, dst, subframe_length);
+
+        s->pts +=
+        out->nb_samples =
+        inlink->min_samples =
+        inlink->max_samples =
+        inlink->partial_buf_size = subframe_length;
+
+        s->frame_type = INNER_FRAME;
+        break;
+
+    case INNER_FRAME:
+        gain      = gaussian_filter(s, s->index + 10 < 30 ? s->index + 10 : s->index + 10 - 30);
+        gain_next = gaussian_filter(s, s->index + 11 < 30 ? s->index + 11 : s->index + 11 - 30);
+
+        for (n = 0; n < in->nb_samples; n++) {
+            for (c = 0; c < inlink->channels; c++) {
+                buf[s->prev_buf_index + c] = src[c];
+                limiter_buf[s->limiter_buf_index + c] = buf[s->buf_index + c] * (gain + (((double) n / in->nb_samples) * (gain_next - gain))) * s->offset;
+            }
+            src += inlink->channels;
+
+            s->limiter_buf_index += inlink->channels;
+            if (s->limiter_buf_index >= s->limiter_buf_size)
+                s->limiter_buf_index -= s->limiter_buf_size;
+
+            s->prev_buf_index += inlink->channels;
+            if (s->prev_buf_index >= s->buf_size)
+                s->prev_buf_index -= s->buf_size;
+
+            s->buf_index += inlink->channels;
+            if (s->buf_index >= s->buf_size)
+                s->buf_index -= s->buf_size;
+        }
+
+        subframe_length = (frame_size(inlink->sample_rate, 100) - in->nb_samples) * inlink->channels;
+        s->limiter_buf_index = s->limiter_buf_index + subframe_length < s->limiter_buf_size ? s->limiter_buf_index + subframe_length : s->limiter_buf_index + subframe_length - s->limiter_buf_size;
+
+        true_peak_limiter(s, dst, in->nb_samples, inlink->channels);
+        ebur128_add_frames_double(s->r128_out, dst, in->nb_samples);
+
+        ebur128_loudness_range(s->r128_in, &lra);
+        ebur128_loudness_global(s->r128_in, &global);
+        ebur128_loudness_shortterm(s->r128_in, &shortterm);
+        ebur128_relative_threshold(s->r128_in, &relative_threshold);
+
+        if (s->above_threshold == 0) {
+            double shortterm_out;
+
+            if (shortterm > s->measured_thresh)
+                s->prev_delta *= 1.0058;
+
+            ebur128_loudness_shortterm(s->r128_out, &shortterm_out);
+            if (shortterm_out >= s->target_i)
+                s->above_threshold = 1;
+        }
+
+        if (shortterm < relative_threshold || shortterm <= -70. || s->above_threshold == 0) {
+            s->delta[s->index] = s->prev_delta;
+        } else {
+            env_global = fabs(shortterm - global) < (s->target_lra / 2.) ? shortterm - global : (s->target_lra / 2.) * ((shortterm - global) < 0 ? -1 : 1);
+            env_shortterm = s->target_i - shortterm;
+            s->delta[s->index] = pow(10., (env_global + env_shortterm) / 20.);
+        }
+
+        s->prev_delta = s->delta[s->index];
+        s->index++;
+        if (s->index >= 30)
+            s->index -= 30;
+        s->prev_nb_samples = in->nb_samples;
+        s->pts += in->nb_samples;
+        break;
+
+    case FINAL_FRAME:
+        gain = gaussian_filter(s, s->index + 10 < 30 ? s->index + 10 : s->index + 10 - 30);
+        s->limiter_buf_index = 0;
+        src_index = 0;
+
+        for (n = 0; n < s->limiter_buf_size / inlink->channels; n++) {
+            for (c = 0; c < inlink->channels; c++) {
+                s->limiter_buf[s->limiter_buf_index + c] = src[src_index + c] * gain * s->offset;
+            }
+            src_index += inlink->channels;
+
+            s->limiter_buf_index += inlink->channels;
+            if (s->limiter_buf_index >= s->limiter_buf_size)
+                s->limiter_buf_index -= s->limiter_buf_size;
+        }
+
+        subframe_length = frame_size(inlink->sample_rate, 100);
+        for (i = 0; i < in->nb_samples / subframe_length; i++) {
+            true_peak_limiter(s, dst, subframe_length, inlink->channels);
+
+            for (n = 0; n < subframe_length; n++) {
+                for (c = 0; c < inlink->channels; c++) {
+                    if (src_index < (in->nb_samples * inlink->channels)) {
+                        limiter_buf[s->limiter_buf_index + c] = src[src_index + c] * gain * s->offset;
+                    } else {
+                        limiter_buf[s->limiter_buf_index + c] = 0.;
+                    }
+                }
+
+                if (src_index < (in->nb_samples * inlink->channels))
+                    src_index += inlink->channels;
+
+                s->limiter_buf_index += inlink->channels;
+                if (s->limiter_buf_index >= s->limiter_buf_size)
+                    s->limiter_buf_index -= s->limiter_buf_size;
+            }
+
+            dst += (subframe_length * inlink->channels);
+        }
+
+        dst = (double *)out->data[0];
+        ebur128_add_frames_double(s->r128_out, dst, in->nb_samples);
+        break;
+
+    case LINEAR_MODE:
+        for (n = 0; n < in->nb_samples; n++) {
+            for (c = 0; c < inlink->channels; c++) {
+                dst[c] = src[c] * s->offset;
+            }
+            src += inlink->channels;
+            dst += inlink->channels;
+        }
+
+        dst = (double *)out->data[0];
+        ebur128_add_frames_double(s->r128_out, dst, in->nb_samples);
+        s->pts += in->nb_samples;
+        break;
+    }
+
+    if (in != out)
+        av_frame_free(&in);
+
+    return ff_filter_frame(outlink, out);
+}
+
+static int request_frame(AVFilterLink *outlink)
+{
+    int ret;
+    AVFilterContext *ctx = outlink->src;
+    AVFilterLink *inlink = ctx->inputs[0];
+    LoudNormContext *s = ctx->priv;
+
+    ret = ff_request_frame(inlink);
+    if (ret == AVERROR_EOF && s->frame_type == INNER_FRAME) {
+        double *src;
+        double *buf;
+        int nb_samples, n, c, offset;
+        AVFrame *frame;
+
+        nb_samples  = (s->buf_size / inlink->channels) - s->prev_nb_samples;
+        nb_samples -= (frame_size(inlink->sample_rate, 100) - s->prev_nb_samples);
+
+        frame = ff_get_audio_buffer(outlink, nb_samples);
+        if (!frame)
+            return AVERROR(ENOMEM);
+        frame->nb_samples = nb_samples;
+
+        buf = s->buf;
+        src = (double *)frame->data[0];
+
+        offset  = ((s->limiter_buf_size / inlink->channels) - s->prev_nb_samples) * inlink->channels;
+        offset -= (frame_size(inlink->sample_rate, 100) - s->prev_nb_samples) * inlink->channels;
+        s->buf_index = s->buf_index - offset < 0 ? s->buf_index - offset + s->buf_size : s->buf_index - offset;
+
+        for (n = 0; n < nb_samples; n++) {
+            for (c = 0; c < inlink->channels; c++) {
+                src[c] = buf[s->buf_index + c];
+            }
+            src += inlink->channels;
+            s->buf_index += inlink->channels;
+            if (s->buf_index >= s->buf_size)
+                s->buf_index -= s->buf_size;
+        }
+
+        s->frame_type = FINAL_FRAME;
+        ret = filter_frame(inlink, frame);
+    }
+    return ret;
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+    AVFilterFormats *formats;
+    AVFilterChannelLayouts *layouts;
+    AVFilterLink *inlink = ctx->inputs[0];
+    AVFilterLink *outlink = ctx->outputs[0];
+    static const int input_srate[] = {192000, -1};
+    static const enum AVSampleFormat sample_fmts[] = {
+        AV_SAMPLE_FMT_DBL,
+        AV_SAMPLE_FMT_NONE
+    };
+    int ret;
+
+    layouts = ff_all_channel_counts();
+    if (!layouts)
+        return AVERROR(ENOMEM);
+    ret = ff_set_common_channel_layouts(ctx, layouts);
+    if (ret < 0)
+        return ret;
+
+    formats = ff_make_format_list(sample_fmts);
+    if (!formats)
+        return AVERROR(ENOMEM);
+    ret = ff_set_common_formats(ctx, formats);
+    if (ret < 0)
+        return ret;
+
+    formats = ff_make_format_list(input_srate);
+    if (!formats)
+        return AVERROR(ENOMEM);
+    ret = ff_formats_ref(formats, &inlink->out_samplerates);
+    if (ret < 0)
+        return ret;
+    ret = ff_formats_ref(formats, &outlink->in_samplerates);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+    AVFilterContext *ctx = inlink->dst;
+    LoudNormContext *s = ctx->priv;
+
+    s->r128_in = ebur128_init(inlink->channels, inlink->sample_rate, EBUR128_MODE_I | EBUR128_MODE_S | EBUR128_MODE_LRA | EBUR128_MODE_SAMPLE_PEAK);
+    if (!s->r128_in)
+        return AVERROR(ENOMEM);
+
+    s->r128_out = ebur128_init(inlink->channels, inlink->sample_rate, EBUR128_MODE_I | EBUR128_MODE_S | EBUR128_MODE_LRA | EBUR128_MODE_SAMPLE_PEAK);
+    if (!s->r128_out)
+        return AVERROR(ENOMEM);
+
+    if (inlink->channels == 1 && s->dual_mono) {
+        ebur128_set_channel(s->r128_in,  0, EBUR128_DUAL_MONO);
+        ebur128_set_channel(s->r128_out, 0, EBUR128_DUAL_MONO);
+    }
+
+    s->buf_size = frame_size(inlink->sample_rate, 3000) * inlink->channels;
+    s->buf = av_malloc_array(s->buf_size, sizeof(*s->buf));
+    if (!s->buf)
+        return AVERROR(ENOMEM);
+
+    s->limiter_buf_size = frame_size(inlink->sample_rate, 210) * inlink->channels;
+    s->limiter_buf = av_malloc_array(s->buf_size, sizeof(*s->limiter_buf));
+    if (!s->limiter_buf)
+        return AVERROR(ENOMEM);
+
+    s->prev_smp = av_malloc_array(inlink->channels, sizeof(*s->prev_smp));
+    if (!s->prev_smp)
+        return AVERROR(ENOMEM);
+
+    init_gaussian_filter(s);
+
+    s->frame_type = FIRST_FRAME;
+
+    if (s->linear) {
+        double offset, offset_tp;
+        offset    = s->target_i - s->measured_i;
+        offset_tp = s->measured_tp + offset;
+
+        if (s->measured_tp != 99 && s->measured_thresh != -70 && s->measured_lra != 0 && s->measured_i != 0) {
+            if ((offset_tp <= s->target_tp) && (s->measured_lra <= s->target_lra)) {
+                s->frame_type = LINEAR_MODE;
+                s->offset = offset;
+            }
+        }
+    }
+
+    if (s->frame_type != LINEAR_MODE) {
+        inlink->min_samples =
+        inlink->max_samples =
+        inlink->partial_buf_size = frame_size(inlink->sample_rate, 3000);
+    }
+
+    s->pts =
+    s->buf_index =
+    s->prev_buf_index =
+    s->limiter_buf_index = 0;
+    s->channels = inlink->channels;
+    s->index = 1;
+    s->limiter_state = OUT;
+    s->offset = pow(10., s->offset / 20.);
+    s->target_tp = pow(10., s->target_tp / 20.);
+    s->attack_length = frame_size(inlink->sample_rate, 10);
+    s->release_length = frame_size(inlink->sample_rate, 100);
+
+    return 0;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    LoudNormContext *s = ctx->priv;
+    double i_in, i_out, lra_in, lra_out, thresh_in, thresh_out, tp_in, tp_out;
+    int c;
+
+    if (!s->r128_in || !s->r128_out)
+        goto end;
+
+    ebur128_loudness_range(s->r128_in, &lra_in);
+    ebur128_loudness_global(s->r128_in, &i_in);
+    ebur128_relative_threshold(s->r128_in, &thresh_in);
+    for (c = 0; c < s->channels; c++) {
+        double tmp;
+        ebur128_sample_peak(s->r128_in, c, &tmp);
+        if ((c == 0) || (tmp > tp_in))
+            tp_in = tmp;
+    }
+
+    ebur128_loudness_range(s->r128_out, &lra_out);
+    ebur128_loudness_global(s->r128_out, &i_out);
+    ebur128_relative_threshold(s->r128_out, &thresh_out);
+    for (c = 0; c < s->channels; c++) {
+        double tmp;
+        ebur128_sample_peak(s->r128_out, c, &tmp);
+        if ((c == 0) || (tmp > tp_out))
+            tp_out = tmp;
+    }
+
+    switch(s->print_format) {
+    case NONE:
+        break;
+
+    case JSON:
+        av_log(ctx, AV_LOG_INFO,
+            "\n{\n"
+            "\t\"input_i\" : \"%.2f\",\n"
+            "\t\"input_tp\" : \"%.2f\",\n"
+            "\t\"input_lra\" : \"%.2f\",\n"
+            "\t\"input_thresh\" : \"%.2f\",\n"
+            "\t\"output_i\" : \"%.2f\",\n"
+            "\t\"output_tp\" : \"%+.2f\",\n"
+            "\t\"output_lra\" : \"%.2f\",\n"
+            "\t\"output_thresh\" : \"%.2f\",\n"
+            "\t\"normalization_type\" : \"%s\",\n"
+            "\t\"target_offset\" : \"%.2f\"\n"
+            "}\n",
+            i_in,
+            20. * log10(tp_in),
+            lra_in,
+            thresh_in,
+            i_out,
+            20. * log10(tp_out),
+            lra_out,
+            thresh_out,
+            s->frame_type == LINEAR_MODE ? "linear" : "dynamic",
+            s->target_i - i_out
+        );
+        break;
+
+    case SUMMARY:
+        av_log(ctx, AV_LOG_INFO,
+            "\n"
+            "Input Integrated:   %+6.1f LUFS\n"
+            "Input True Peak:    %+6.1f dBTP\n"
+            "Input LRA:          %6.1f LU\n"
+            "Input Threshold:    %+6.1f LUFS\n"
+            "\n"
+            "Output Integrated:  %+6.1f LUFS\n"
+            "Output True Peak:   %+6.1f dBTP\n"
+            "Output LRA:         %6.1f LU\n"
+            "Output Threshold:   %+6.1f LUFS\n"
+            "\n"
+            "Normalization Type:   %s\n"
+            "Target Offset:      %+6.1f LU\n",
+            i_in,
+            20. * log10(tp_in),
+            lra_in,
+            thresh_in,
+            i_out,
+            20. * log10(tp_out),
+            lra_out,
+            thresh_out,
+            s->frame_type == LINEAR_MODE ? "Linear" : "Dynamic",
+            s->target_i - i_out
+        );
+        break;
+    }
+
+end:
+    if (s->r128_in)
+        ebur128_destroy(&s->r128_in);
+    if (s->r128_out)
+        ebur128_destroy(&s->r128_out);
+    av_freep(&s->limiter_buf);
+    av_freep(&s->prev_smp);
+    av_freep(&s->buf);
+}
+
+static const AVFilterPad avfilter_af_loudnorm_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_AUDIO,
+        .config_props = config_input,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad avfilter_af_loudnorm_outputs[] = {
+    {
+        .name          = "default",
+        .request_frame = request_frame,
+        .type          = AVMEDIA_TYPE_AUDIO,
+    },
+    { NULL }
+};
+
+AVFilter ff_af_loudnorm = {
+    .name          = "loudnorm",
+    .description   = NULL_IF_CONFIG_SMALL("EBU R128 loudness normalization"),
+    .priv_size     = sizeof(LoudNormContext),
+    .priv_class    = &loudnorm_class,
+    .query_formats = query_formats,
+    .uninit        = uninit,
+    .inputs        = avfilter_af_loudnorm_inputs,
+    .outputs       = avfilter_af_loudnorm_outputs,
+};
diff --git a/libavfilter/af_sofalizer.c b/libavfilter/af_sofalizer.c
index 0f1231f..7558f57 100644
--- a/libavfilter/af_sofalizer.c
+++ b/libavfilter/af_sofalizer.c
@@ -29,6 +29,8 @@
 #include <netcdf.h>
 
 #include "libavcodec/avfft.h"
+#include "libavutil/avstring.h"
+#include "libavutil/channel_layout.h"
 #include "libavutil/float_dsp.h"
 #include "libavutil/intmath.h"
 #include "libavutil/opt.h"
@@ -52,6 +54,12 @@ typedef struct NCSofa {  /* contains data of one SOFA file */
     float *data_ir;      /* IRs (time-domain) */
 } NCSofa;
 
+typedef struct VirtualSpeaker {
+    uint8_t set;
+    float azim;
+    float elev;
+} VirtualSpeaker;
+
 typedef struct SOFAlizerContext {
     const AVClass *class;
 
@@ -61,6 +69,7 @@ typedef struct SOFAlizerContext {
     int sample_rate;            /* sample rate from SOFA file */
     float *speaker_azim;        /* azimuth of the virtual loudspeakers */
     float *speaker_elev;        /* elevation of the virtual loudspeakers */
+    char *speakers_pos;         /* custom positions of the virtual loudspeakers */
     float gain_lfe;             /* gain applied to LFE channel */
     int lfe_channel;            /* LFE channel position in channel layout */
 
@@ -89,6 +98,8 @@ typedef struct SOFAlizerContext {
     float radius;        /* distance virtual loudspeakers to listener (in metres) */
     int type;            /* processing type */
 
+    VirtualSpeaker vspkrpos[64];
+
     FFTContext *fft[2], *ifft[2];
     FFTComplex *data_hrtf[2];
 
@@ -269,7 +280,7 @@ static int load_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
     sp_r = s->sofa.sp_r = av_malloc_array(m_dim, sizeof(float));
     /* delay and IR values required for each ear and measurement position: */
     data_delay = s->sofa.data_delay = av_calloc(m_dim, 2 * sizeof(int));
-    data_ir = s->sofa.data_ir = av_malloc_array(m_dim * n_samples, sizeof(float) * 2);
+    data_ir = s->sofa.data_ir = av_calloc(m_dim * FFALIGN(n_samples, 16), sizeof(float) * 2);
 
     if (!data_delay || !sp_a || !sp_e || !sp_r || !data_ir) {
         /* if memory could not be allocated */
@@ -316,6 +327,7 @@ static int load_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
     if (!strncmp(data_delay_dim_name, "I", 2)) {
         /* check 2 characters to assure string is 0-terminated after "I" */
         int delay[2]; /* delays get from SOFA file: */
+        int *data_delay_r;
 
         av_log(ctx, AV_LOG_DEBUG, "Data.Delay has dimension [I R]\n");
         status = nc_get_var_int(ncid, data_delay_id, &delay[0]);
@@ -324,7 +336,7 @@ static int load_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
             ret = AVERROR(EINVAL);
             goto error;
         }
-        int *data_delay_r = data_delay + m_dim;
+        data_delay_r = data_delay + m_dim;
         for (i = 0; i < m_dim; i++) { /* extend given dimension [I R] to [M R] */
             /* assign constant delay value for all measurements to data_delay fields */
             data_delay[i]   = delay[0];
@@ -352,6 +364,8 @@ static int load_sofa(AVFilterContext *ctx, char *filename, int *samplingrate)
     s->sofa.ncid = ncid; /* netCDF ID of SOFA file */
     nc_close(ncid); /* close SOFA file */
 
+    av_log(ctx, AV_LOG_DEBUG, "m_dim: %d n_samples %d\n", m_dim, n_samples);
+
     return 0;
 
 error:
@@ -359,6 +373,62 @@ error:
     return ret;
 }
 
+static int parse_channel_name(char **arg, int *rchannel)
+{
+    char buf[8];
+    int len, i, channel_id = 0;
+    int64_t layout, layout0;
+
+    /* try to parse a channel name, e.g. "FL" */
+    if (sscanf(*arg, "%7[A-Z]%n", buf, &len)) {
+        layout0 = layout = av_get_channel_layout(buf);
+        /* channel_id <- first set bit in layout */
+        for (i = 32; i > 0; i >>= 1) {
+            if (layout >= (int64_t)1 << i) {
+                channel_id += i;
+                layout >>= i;
+            }
+        }
+        /* reject layouts that are not a single channel */
+        if (channel_id >= 64 || layout0 != (int64_t)1 << channel_id)
+            return AVERROR(EINVAL);
+        *rchannel = channel_id;
+        *arg += len;
+        return 0;
+    }
+    return AVERROR(EINVAL);
+}
+
+static void parse_speaker_pos(AVFilterContext *ctx, int64_t in_channel_layout)
+{
+    SOFAlizerContext *s = ctx->priv;
+    char *arg, *tokenizer, *p, *args = av_strdup(s->speakers_pos);
+
+    if (!args)
+        return;
+    p = args;
+
+    while ((arg = av_strtok(p, "|", &tokenizer))) {
+        float azim, elev;
+        int out_ch_id;
+
+        p = NULL;
+        if (parse_channel_name(&arg, &out_ch_id))
+            continue;
+        if (sscanf(arg, "%f %f", &azim, &elev) == 2) {
+            s->vspkrpos[out_ch_id].set = 1;
+            s->vspkrpos[out_ch_id].azim = azim;
+            s->vspkrpos[out_ch_id].elev = elev;
+        } else if (sscanf(arg, "%f", &azim) == 1) {
+            s->vspkrpos[out_ch_id].set = 1;
+            s->vspkrpos[out_ch_id].azim = azim;
+            s->vspkrpos[out_ch_id].elev = 0;
+        }
+    }
+
+    av_free(args);
+}
+
 static int get_speaker_pos(AVFilterContext *ctx,
                            float *speaker_azim, float *speaker_elev)
 {
@@ -373,6 +443,9 @@ static int get_speaker_pos(AVFilterContext *ctx,
 
     s->lfe_channel = -1;
 
+    if (s->speakers_pos)
+        parse_speaker_pos(ctx, channels_layout);
+
     /* set speaker positions according to input channel configuration: */
     for (m = 0, ch = 0; ch < n_conv && m < 64; m++) {
         uint64_t mask = channels_layout & (1 << m);
@@ -414,6 +487,12 @@ static int get_speaker_pos(AVFilterContext *ctx,
         default:
             return AVERROR(EINVAL);
         }
+
+        if (s->vspkrpos[m].set) {
+            azim[ch] = s->vspkrpos[m].azim;
+            elev[ch] = s->vspkrpos[m].elev;
+        }
+
         if (mask)
             ch++;
     }
@@ -488,8 +567,15 @@ static int compensate_volume(AVFilterContext *ctx)
         av_log(ctx, AV_LOG_DEBUG, "Compensate-factor: %f\n", compensate);
         ir = sofa->data_ir;
         /* apply volume compensation to IRs */
-        s->fdsp->vector_fmul_scalar(ir, ir, compensate, sofa->n_samples * sofa->m_dim * 2);
-        emms_c();
+        if (sofa->n_samples & 31) {
+            int i;
+            for (i = 0; i < sofa->n_samples * sofa->m_dim * 2; i++) {
+                ir[i] = ir[i] * compensate;
+            }
+        } else {
+            s->fdsp->vector_fmul_scalar(ir, ir, compensate, sofa->n_samples * sofa->m_dim * 2);
+            emms_c();
+        }
     }
 
     return 0;
@@ -554,7 +640,7 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n
                 /* LFE is an input channel but requires no convolution */
                 /* apply gain to LFE signal and add to output buffer */
                 *dst += *(buffer[s->lfe_channel] + wr) * s->gain_lfe;
-                temp_ir += n_samples;
+                temp_ir += FFALIGN(n_samples, 16);
                 continue;
             }
 
@@ -574,7 +660,7 @@ static int sofalizer_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n
 
             /* multiply signal and IR, and add up the results */
             dst[0] += s->fdsp->scalarproduct_float(temp_ir, temp_src, n_samples);
-            temp_ir += n_samples;
+            temp_ir += FFALIGN(n_samples, 16);
         }
 
         /* clippings counter */
@@ -812,8 +898,8 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius)
         s->temp_src[1] = av_calloc(FFALIGN(n_samples, 16), sizeof(float));
 
         /* get temporary IR for L and R channel */
-        data_ir_l = av_malloc_array(n_conv * n_samples, sizeof(*data_ir_l));
-        data_ir_r = av_malloc_array(n_conv * n_samples, sizeof(*data_ir_r));
+        data_ir_l = av_calloc(n_conv * FFALIGN(n_samples, 16), sizeof(*data_ir_l));
+        data_ir_r = av_calloc(n_conv * FFALIGN(n_samples, 16), sizeof(*data_ir_r));
         if (!data_ir_r || !data_ir_l || !s->temp_src[0] || !s->temp_src[1]) {
             av_free(data_ir_l);
             av_free(data_ir_r);
@@ -842,7 +928,7 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius)
         delay_r[i] = *(s->sofa.data_delay + 2 * m[i] + 1);
 
         if (s->type == TIME_DOMAIN) {
-            offset = i * n_samples; /* no. samples already written */
+            offset = i * FFALIGN(n_samples, 16); /* no. samples already written */
             for (j = 0; j < n_samples; j++) {
                 /* load reversed IRs of the specified source position
                  * sample-by-sample for left and right ear; and apply gain */
@@ -889,8 +975,8 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius)
 
     if (s->type == TIME_DOMAIN) {
         /* copy IRs and delays to allocated memory in the SOFAlizerContext struct: */
-        memcpy(s->data_ir[0], data_ir_l, sizeof(float) * n_conv * n_samples);
-        memcpy(s->data_ir[1], data_ir_r, sizeof(float) * n_conv * n_samples);
+        memcpy(s->data_ir[0], data_ir_l, sizeof(float) * n_conv * FFALIGN(n_samples, 16));
+        memcpy(s->data_ir[1], data_ir_r, sizeof(float) * n_conv * FFALIGN(n_samples, 16));
 
         av_freep(&data_ir_l); /* free temporary IR memory */
         av_freep(&data_ir_r);
@@ -928,6 +1014,11 @@ static av_cold int init(AVFilterContext *ctx)
     SOFAlizerContext *s = ctx->priv;
     int ret;
 
+    if (!s->filename) {
+        av_log(ctx, AV_LOG_ERROR, "Valid SOFA filename must be set.\n");
+        return AVERROR(EINVAL);
+    }
+
     /* load SOFA file, */
     /* initialize file IDs to 0 before attempting to load SOFA files,
      * this assures that in case of error, only the memory of already
@@ -999,15 +1090,15 @@ static int config_input(AVFilterLink *inlink)
         s->ifft[1] = av_fft_init(log2(s->n_fft), 1);
 
         if (!s->fft[0] || !s->fft[1] || !s->ifft[0] || !s->ifft[1]) {
-            av_log(ctx, AV_LOG_ERROR, "Unable to create FFT contexts.\n");
+            av_log(ctx, AV_LOG_ERROR, "Unable to create FFT contexts of size %d.\n", s->n_fft);
             return AVERROR(ENOMEM);
         }
     }
 
     /* Allocate memory for the impulse responses, delays and the ringbuffers */
     /* size: (longest IR) * (number of channels to convolute) */
-    s->data_ir[0] = av_malloc_array(n_max_ir, sizeof(float) * s->n_conv);
-    s->data_ir[1] = av_malloc_array(n_max_ir, sizeof(float) * s->n_conv);
+    s->data_ir[0] = av_calloc(FFALIGN(n_max_ir, 16), sizeof(float) * s->n_conv);
+    s->data_ir[1] = av_calloc(FFALIGN(n_max_ir, 16), sizeof(float) * s->n_conv);
     /* length:  number of channels to convolute */
     s->delay[0] = av_malloc_array(s->n_conv, sizeof(float));
     s->delay[1] = av_malloc_array(s->n_conv, sizeof(float));
@@ -1099,6 +1190,7 @@ static const AVOption sofalizer_options[] = {
     { "type",      "set processing", OFFSET(type),      AV_OPT_TYPE_INT,    {.i64=1},       0,   1, .flags = FLAGS, "type" },
     { "time",      "time domain",      0,               AV_OPT_TYPE_CONST,  {.i64=0},       0,   0, .flags = FLAGS, "type" },
     { "freq",      "frequency domain", 0,               AV_OPT_TYPE_CONST,  {.i64=1},       0,   0, .flags = FLAGS, "type" },
+    { "speakers",  "set speaker custom positions", OFFSET(speakers_pos), AV_OPT_TYPE_STRING,  {.str=0},    0, 0, .flags = FLAGS },
     { NULL }
 };
 
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 3913e7b..4d6b916 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -27,6 +27,7 @@
 #include "libavutil/channel_layout.h"
 #include "libavutil/common.h"
 #include "libavutil/eval.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/float_dsp.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/opt.h"
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index fa7d304..d0d491e 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -45,6 +45,7 @@ void avfilter_register_all(void)
         return;
     initialized = 1;
 
+    REGISTER_FILTER(ABENCH,         abench,         af);
     REGISTER_FILTER(ACOMPRESSOR,    acompressor,    af);
     REGISTER_FILTER(ACROSSFADE,     acrossfade,     af);
     REGISTER_FILTER(ADELAY,         adelay,         af);
@@ -58,6 +59,7 @@ void avfilter_register_all(void)
     REGISTER_FILTER(AINTERLEAVE,    ainterleave,    af);
     REGISTER_FILTER(ALIMITER,       alimiter,       af);
     REGISTER_FILTER(ALLPASS,        allpass,        af);
+    REGISTER_FILTER(ALOOP,          aloop,          af);
     REGISTER_FILTER(AMERGE,         amerge,         af);
     REGISTER_FILTER(AMETADATA,      ametadata,      af);
     REGISTER_FILTER(AMIX,           amix,           af);
@@ -100,10 +102,13 @@ void avfilter_register_all(void)
     REGISTER_FILTER(EBUR128,        ebur128,        af);
     REGISTER_FILTER(EQUALIZER,      equalizer,      af);
     REGISTER_FILTER(EXTRASTEREO,    extrastereo,    af);
+    REGISTER_FILTER(FIREQUALIZER,   firequalizer,   af);
     REGISTER_FILTER(FLANGER,        flanger,        af);
+    REGISTER_FILTER(HDCD,           hdcd,           af);
     REGISTER_FILTER(HIGHPASS,       highpass,       af);
     REGISTER_FILTER(JOIN,           join,           af);
     REGISTER_FILTER(LADSPA,         ladspa,         af);
+    REGISTER_FILTER(LOUDNORM,       loudnorm,       af);
     REGISTER_FILTER(LOWPASS,        lowpass,        af);
     REGISTER_FILTER(PAN,            pan,            af);
     REGISTER_FILTER(REPLAYGAIN,     replaygain,     af);
@@ -134,24 +139,30 @@ void avfilter_register_all(void)
     REGISTER_FILTER(ALPHAMERGE,     alphamerge,     vf);
     REGISTER_FILTER(ATADENOISE,     atadenoise,     vf);
     REGISTER_FILTER(ASS,            ass,            vf);
+    REGISTER_FILTER(BENCH,          bench,          vf);
     REGISTER_FILTER(BBOX,           bbox,           vf);
     REGISTER_FILTER(BLACKDETECT,    blackdetect,    vf);
     REGISTER_FILTER(BLACKFRAME,     blackframe,     vf);
     REGISTER_FILTER(BLEND,          blend,          vf);
     REGISTER_FILTER(BOXBLUR,        boxblur,        vf);
+    REGISTER_FILTER(BWDIF,          bwdif,          vf);
     REGISTER_FILTER(CHROMAKEY,      chromakey,      vf);
+    REGISTER_FILTER(CIESCOPE,       ciescope,       vf);
     REGISTER_FILTER(CODECVIEW,      codecview,      vf);
     REGISTER_FILTER(COLORBALANCE,   colorbalance,   vf);
     REGISTER_FILTER(COLORCHANNELMIXER, colorchannelmixer, vf);
     REGISTER_FILTER(COLORKEY,       colorkey,       vf);
     REGISTER_FILTER(COLORLEVELS,    colorlevels,    vf);
     REGISTER_FILTER(COLORMATRIX,    colormatrix,    vf);
+    REGISTER_FILTER(COLORSPACE,     colorspace,     vf);
     REGISTER_FILTER(CONVOLUTION,    convolution,    vf);
     REGISTER_FILTER(COPY,           copy,           vf);
+    REGISTER_FILTER(COREIMAGE,      coreimage,      vf);
     REGISTER_FILTER(COVER_RECT,     cover_rect,     vf);
     REGISTER_FILTER(CROP,           crop,           vf);
     REGISTER_FILTER(CROPDETECT,     cropdetect,     vf);
     REGISTER_FILTER(CURVES,         curves,         vf);
+    REGISTER_FILTER(DATASCOPE,      datascope,      vf);
     REGISTER_FILTER(DCTDNOIZ,       dctdnoiz,       vf);
     REGISTER_FILTER(DEBAND,         deband,         vf);
     REGISTER_FILTER(DECIMATE,       decimate,       vf);
@@ -174,6 +185,7 @@ void avfilter_register_all(void)
     REGISTER_FILTER(FADE,           fade,           vf);
     REGISTER_FILTER(FFTFILT,        fftfilt,        vf);
     REGISTER_FILTER(FIELD,          field,          vf);
+    REGISTER_FILTER(FIELDHINT,      fieldhint,      vf);
     REGISTER_FILTER(FIELDMATCH,     fieldmatch,     vf);
     REGISTER_FILTER(FIELDORDER,     fieldorder,     vf);
     REGISTER_FILTER(FIND_RECT,      find_rect,      vf);
@@ -192,6 +204,9 @@ void avfilter_register_all(void)
     REGISTER_FILTER(HISTOGRAM,      histogram,      vf);
     REGISTER_FILTER(HQDN3D,         hqdn3d,         vf);
     REGISTER_FILTER(HQX,            hqx,            vf);
+    REGISTER_FILTER(HWDOWNLOAD,     hwdownload,     vf);
+    REGISTER_FILTER(HWUPLOAD,       hwupload,       vf);
+    REGISTER_FILTER(HWUPLOAD_CUDA,  hwupload_cuda,  vf);
     REGISTER_FILTER(HSTACK,         hstack,         vf);
     REGISTER_FILTER(HUE,            hue,            vf);
     REGISTER_FILTER(IDET,           idet,           vf);
@@ -201,6 +216,7 @@ void avfilter_register_all(void)
     REGISTER_FILTER(INTERLEAVE,     interleave,     vf);
     REGISTER_FILTER(KERNDEINT,      kerndeint,      vf);
     REGISTER_FILTER(LENSCORRECTION, lenscorrection, vf);
+    REGISTER_FILTER(LOOP,           loop,           vf);
     REGISTER_FILTER(LUT3D,          lut3d,          vf);
     REGISTER_FILTER(LUT,            lut,            vf);
     REGISTER_FILTER(LUTRGB,         lutrgb,         vf);
@@ -232,7 +248,9 @@ void avfilter_register_all(void)
     REGISTER_FILTER(PULLUP,         pullup,         vf);
     REGISTER_FILTER(QP,             qp,             vf);
     REGISTER_FILTER(RANDOM,         random,         vf);
+    REGISTER_FILTER(READVITC,       readvitc,       vf);
     REGISTER_FILTER(REALTIME,       realtime,       vf);
+    REGISTER_FILTER(REMAP,          remap,          vf);
     REGISTER_FILTER(REMOVEGRAIN,    removegrain,    vf);
     REGISTER_FILTER(REMOVELOGO,     removelogo,     vf);
     REGISTER_FILTER(REPEATFIELDS,   repeatfields,   vf);
@@ -241,6 +259,8 @@ void avfilter_register_all(void)
     REGISTER_FILTER(SAB,            sab,            vf);
     REGISTER_FILTER(SCALE,          scale,          vf);
     REGISTER_FILTER(SCALE2REF,      scale2ref,      vf);
+    REGISTER_FILTER(SCALE_NPP,      scale_npp,      vf);
+    REGISTER_FILTER(SCALE_VAAPI,    scale_vaapi,    vf);
     REGISTER_FILTER(SELECT,         select,         vf);
     REGISTER_FILTER(SELECTIVECOLOR, selectivecolor, vf);
     REGISTER_FILTER(SENDCMD,        sendcmd,        vf);
@@ -292,6 +312,7 @@ void avfilter_register_all(void)
     REGISTER_FILTER(ALLYUV,         allyuv,         vsrc);
     REGISTER_FILTER(CELLAUTO,       cellauto,       vsrc);
     REGISTER_FILTER(COLOR,          color,          vsrc);
+    REGISTER_FILTER(COREIMAGESRC,   coreimagesrc,   vsrc);
     REGISTER_FILTER(FREI0R,         frei0r_src,     vsrc);
     REGISTER_FILTER(HALDCLUTSRC,    haldclutsrc,    vsrc);
     REGISTER_FILTER(LIFE,           life,           vsrc);
diff --git a/libavfilter/avf_ahistogram.c b/libavfilter/avf_ahistogram.c
index a716a96..5874151 100644
--- a/libavfilter/avf_ahistogram.c
+++ b/libavfilter/avf_ahistogram.c
@@ -63,8 +63,8 @@ static const AVOption ahistogram_options[] = {
     { "dmode", "set method to display channels", OFFSET(dmode), AV_OPT_TYPE_INT, {.i64=SINGLE}, 0, NB_DMODES-1, FLAGS, "dmode" },
         { "single", "all channels use single histogram", 0, AV_OPT_TYPE_CONST, {.i64=SINGLE},   0, 0, FLAGS, "dmode" },
         { "separate", "each channel have own histogram", 0, AV_OPT_TYPE_CONST, {.i64=SEPARATE}, 0, 0, FLAGS, "dmode" },
-    { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
-    { "r",    "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
+    { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
+    { "r",    "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
     { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, FLAGS },
     { "s",    "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, FLAGS },
     { "scale", "set display scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=LOG}, LINEAR, NB_SCALES-1, FLAGS, "scale" },
@@ -165,7 +165,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     const int H = s->histogram_h;
     const int w = s->w;
     int c, y, n, p, bin;
-    uint64_t acmax = 0;
+    uint64_t acmax = 1;
 
     if (!s->out || s->out->width  != outlink->w ||
                    s->out->height != outlink->h) {
diff --git a/libavfilter/avf_aphasemeter.c b/libavfilter/avf_aphasemeter.c
index 7c1e993..8e8b292 100644
--- a/libavfilter/avf_aphasemeter.c
+++ b/libavfilter/avf_aphasemeter.c
@@ -49,8 +49,8 @@ typedef struct AudioPhaseMeterContext {
 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
 
 static const AVOption aphasemeter_options[] = {
-    { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
-    { "r",    "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
+    { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
+    { "r",    "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
     { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="800x400"}, 0, 0, FLAGS },
     { "s",    "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="800x400"}, 0, 0, FLAGS },
     { "rc", "set red contrast",   OFFSET(contrast[0]), AV_OPT_TYPE_INT, {.i64=2}, 0, 255, FLAGS },
diff --git a/libavfilter/avf_avectorscope.c b/libavfilter/avf_avectorscope.c
index 29d0287..3ba044f 100644
--- a/libavfilter/avf_avectorscope.c
+++ b/libavfilter/avf_avectorscope.c
@@ -69,8 +69,8 @@ static const AVOption avectorscope_options[] = {
     { "lissajous",    "", 0, AV_OPT_TYPE_CONST, {.i64=LISSAJOUS},    0, 0, FLAGS, "mode" },
     { "lissajous_xy", "", 0, AV_OPT_TYPE_CONST, {.i64=LISSAJOUS_XY}, 0, 0, FLAGS, "mode" },
     { "polar",        "", 0, AV_OPT_TYPE_CONST, {.i64=POLAR},        0, 0, FLAGS, "mode" },
-    { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
-    { "r",    "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
+    { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
+    { "r",    "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
     { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="400x400"}, 0, 0, FLAGS },
     { "s",    "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="400x400"}, 0, 0, FLAGS },
     { "rc", "set red contrast",   OFFSET(contrast[0]), AV_OPT_TYPE_INT, {.i64=40},  0, 255, FLAGS },
diff --git a/libavfilter/avf_showcqt.c b/libavfilter/avf_showcqt.c
index 712a999..16bb2be 100644
--- a/libavfilter/avf_showcqt.c
+++ b/libavfilter/avf_showcqt.c
@@ -18,9 +18,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <math.h>
-#include <stdlib.h>
-
 #include "config.h"
 #include "libavcodec/avfft.h"
 #include "libavutil/avassert.h"
@@ -28,6 +25,7 @@
 #include "libavutil/xga_font_data.h"
 #include "libavutil/eval.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/time.h"
 #include "avfilter.h"
 #include "internal.h"
 #include "lavfutils.h"
@@ -48,6 +46,8 @@
 #define FONTCOLOR       "st(0, (midi(f)-59.5)/12);" \
     "st(1, if(between(ld(0),0,1), 0.5-0.5*cos(2*PI*ld(0)), 0));" \
     "r(1-ld(1)) + b(ld(1))"
+#define PTS_STEP 10
+#define PTS_TOLERANCE 1
 
 #define OFFSET(x) offsetof(ShowCQTContext, x)
 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
@@ -55,9 +55,9 @@
 static const AVOption showcqt_options[] = {
     { "size",         "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" },      0, 0,        FLAGS },
     { "s",            "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, { .str = "1920x1080" },      0, 0,        FLAGS },
-    { "fps",          "set video rate", OFFSET(rate),  AV_OPT_TYPE_VIDEO_RATE, { .str = "25" },             0, 0,        FLAGS },
-    { "rate",         "set video rate", OFFSET(rate),  AV_OPT_TYPE_VIDEO_RATE, { .str = "25" },             0, 0,        FLAGS },
-    { "r",            "set video rate", OFFSET(rate),  AV_OPT_TYPE_VIDEO_RATE, { .str = "25" },             0, 0,        FLAGS },
+    { "fps",          "set video rate", OFFSET(rate),  AV_OPT_TYPE_VIDEO_RATE, { .str = "25" },             1, 1000,     FLAGS },
+    { "rate",         "set video rate", OFFSET(rate),  AV_OPT_TYPE_VIDEO_RATE, { .str = "25" },             1, 1000,     FLAGS },
+    { "r",            "set video rate", OFFSET(rate),  AV_OPT_TYPE_VIDEO_RATE, { .str = "25" },             1, 1000,     FLAGS },
     { "bar_h",   "set bargraph height", OFFSET(bar_h),        AV_OPT_TYPE_INT, { .i64 = -1 },              -1, INT_MAX,  FLAGS },
     { "axis_h",      "set axis height", OFFSET(axis_h),       AV_OPT_TYPE_INT, { .i64 = -1 },              -1, INT_MAX,  FLAGS },
     { "sono_h",  "set sonogram height", OFFSET(sono_h),       AV_OPT_TYPE_INT, { .i64 = -1 },              -1, INT_MAX,  FLAGS },
@@ -91,7 +91,33 @@ AVFILTER_DEFINE_CLASS(showcqt);
 static void common_uninit(ShowCQTContext *s)
 {
     int k;
-
+    int level = AV_LOG_DEBUG;
+    int64_t plot_time;
+
+    if (s->fft_time)
+        av_log(s->ctx, level, "fft_time         = %16.3f s.\n", s->fft_time * 1e-6);
+    if (s->cqt_time)
+        av_log(s->ctx, level, "cqt_time         = %16.3f s.\n", s->cqt_time * 1e-6);
+    if (s->process_cqt_time)
+        av_log(s->ctx, level, "process_cqt_time = %16.3f s.\n", s->process_cqt_time * 1e-6);
+    if (s->update_sono_time)
+        av_log(s->ctx, level, "update_sono_time = %16.3f s.\n", s->update_sono_time * 1e-6);
+    if (s->alloc_time)
+        av_log(s->ctx, level, "alloc_time       = %16.3f s.\n", s->alloc_time * 1e-6);
+    if (s->bar_time)
+        av_log(s->ctx, level, "bar_time         = %16.3f s.\n", s->bar_time * 1e-6);
+    if (s->axis_time)
+        av_log(s->ctx, level, "axis_time        = %16.3f s.\n", s->axis_time * 1e-6);
+    if (s->sono_time)
+        av_log(s->ctx, level, "sono_time        = %16.3f s.\n", s->sono_time * 1e-6);
+
+    plot_time = s->fft_time + s->cqt_time + s->process_cqt_time + s->update_sono_time
+              + s->alloc_time + s->bar_time + s->axis_time + s->sono_time;
+    if (plot_time)
+        av_log(s->ctx, level, "plot_time        = %16.3f s.\n", plot_time * 1e-6);
+
+    s->fft_time = s->cqt_time = s->process_cqt_time = s->update_sono_time
+                = s->alloc_time = s->bar_time = s->axis_time = s->sono_time = 0;
     /* axis_frame may be non reference counted frame */
     if (s->axis_frame && !s->axis_frame->buf[0]) {
         av_freep(s->axis_frame->data);
@@ -104,7 +130,7 @@ static void common_uninit(ShowCQTContext *s)
     av_fft_end(s->fft_ctx);
     s->fft_ctx = NULL;
     if (s->coeffs)
-        for (k = 0; k < s->cqt_len * 2; k++)
+        for (k = 0; k < s->cqt_len; k++)
             av_freep(&s->coeffs[k].val);
     av_freep(&s->coeffs);
     av_freep(&s->fft_data);
@@ -250,61 +276,25 @@ static void cqt_calc(FFTComplex *dst, const FFTComplex *src, const Coeffs *coeff
     }
 }
 
-#if 0
-static void cqt_calc_interleave(FFTComplex *dst, const FFTComplex *src, const Coeffs *coeffs,
-                                int len, int fft_len)
-{
-    int k, x, i, m;
-
-    for (k = 0; k < len; k++) {
-        FFTComplex l, r, a = {0,0}, b = {0,0};
-
-        m = 2 * k;
-        for (x = 0; x < coeffs[m].len; x++) {
-            FFTSample u = coeffs[m].val[x];
-            i = coeffs[m].start + x;
-            a.re += u * src[i].re;
-            a.im += u * src[i].im;
-        }
-
-        m++;
-        for (x = 0; x < coeffs[m].len; x++) {
-            FFTSample u = coeffs[m].val[x];
-            i = coeffs[m].start + x;
-            b.re += u * src[i].re;
-            b.im += u * src[i].im;
-        }
-
-        /* separate left and right, (and multiply by 2.0) */
-        l.re = a.re + b.re;
-        l.im = a.im - b.im;
-        r.re = b.im + a.im;
-        r.im = b.re - a.re;
-        dst[k].re = l.re * l.re + l.im * l.im;
-        dst[k].im = r.re * r.re + r.im * r.im;
-    }
-}
-#endif
-
 static int init_cqt(ShowCQTContext *s)
 {
     const char *var_names[] = { "timeclamp", "tc", "frequency", "freq", "f", NULL };
     AVExpr *expr = NULL;
     int rate = s->ctx->inputs[0]->sample_rate;
-    int nb_cqt_coeffs = 0, nb_cqt_coeffs_r = 0;
+    int nb_cqt_coeffs = 0;
     int k, x, ret;
 
     if ((ret = av_expr_parse(&expr, s->tlength, var_names, NULL, NULL, NULL, NULL, 0, s->ctx)) < 0)
         goto error;
 
     ret = AVERROR(ENOMEM);
-    if (!(s->coeffs = av_calloc(s->cqt_len * 2, sizeof(*s->coeffs))))
+    if (!(s->coeffs = av_calloc(s->cqt_len, sizeof(*s->coeffs))))
         goto error;
 
     for (k = 0; k < s->cqt_len; k++) {
         double vars[] = { s->timeclamp, s->timeclamp, s->freq[k], s->freq[k], s->freq[k] };
         double flen, center, tlength;
-        int start, end, m = (s->cqt_coeffs_type == COEFFS_TYPE_INTERLEAVE) ? (2 * k) : k;
+        int start, end, m = k;
 
         if (s->freq[k] > 0.5 * rate)
             continue;
@@ -322,14 +312,6 @@ static int init_cqt(ShowCQTContext *s)
         if (!(s->coeffs[m].val = av_calloc(s->coeffs[m].len, sizeof(*s->coeffs[m].val))))
             goto error;
 
-        if (s->cqt_coeffs_type == COEFFS_TYPE_INTERLEAVE) {
-            s->coeffs[m+1].start = (s->fft_len - end) & ~(s->cqt_align - 1);
-            s->coeffs[m+1].len = ((s->fft_len - start) | (s->cqt_align - 1)) + 1 - s->coeffs[m+1].start;
-            nb_cqt_coeffs_r += s->coeffs[m+1].len;
-            if (!(s->coeffs[m+1].val = av_calloc(s->coeffs[m+1].len, sizeof(*s->coeffs[m+1].val))))
-                goto error;
-        }
-
         for (x = start; x <= end; x++) {
             int sign = (x & 1) ? (-1) : 1;
             double y = 2.0 * M_PI * (x - center) * (1.0 / flen);
@@ -337,22 +319,20 @@ static int init_cqt(ShowCQTContext *s)
             double w = 0.355768 + 0.487396 * cos(y) + 0.144232 * cos(2*y) + 0.012604 * cos(3*y);
             w *= sign * (1.0 / s->fft_len);
             s->coeffs[m].val[x - s->coeffs[m].start] = w;
-            if (s->cqt_coeffs_type == COEFFS_TYPE_INTERLEAVE)
-                s->coeffs[m+1].val[(s->fft_len - x) - s->coeffs[m+1].start] = w;
         }
+
+        if (s->permute_coeffs)
+            s->permute_coeffs(s->coeffs[m].val, s->coeffs[m].len);
     }
 
     av_expr_free(expr);
-    if (s->cqt_coeffs_type == COEFFS_TYPE_DEFAULT)
-        av_log(s->ctx, AV_LOG_INFO, "nb_cqt_coeffs = %d.\n", nb_cqt_coeffs);
-    else
-        av_log(s->ctx, AV_LOG_INFO, "nb_cqt_coeffs = {%d,%d}.\n", nb_cqt_coeffs, nb_cqt_coeffs_r);
+    av_log(s->ctx, AV_LOG_INFO, "nb_cqt_coeffs = %d.\n", nb_cqt_coeffs);
     return 0;
 
 error:
     av_expr_free(expr);
     if (s->coeffs)
-        for (k = 0; k < s->cqt_len * 2; k++)
+        for (k = 0; k < s->cqt_len; k++)
             av_freep(&s->coeffs[k].val);
     av_freep(&s->coeffs);
     return ret;
@@ -388,9 +368,9 @@ static enum AVPixelFormat convert_axis_pixel_format(enum AVPixelFormat format)
 {
     switch (format) {
         case AV_PIX_FMT_RGB24:   format = AV_PIX_FMT_RGBA; break;
-        case AV_PIX_FMT_YUV444P: format = AV_PIX_FMT_YUVA444P; break;
-        case AV_PIX_FMT_YUV422P: format = AV_PIX_FMT_YUVA422P; break;
-        case AV_PIX_FMT_YUV420P: format = AV_PIX_FMT_YUVA420P; break;
+        case AV_PIX_FMT_YUV444P:
+        case AV_PIX_FMT_YUV422P:
+        case AV_PIX_FMT_YUV420P: format = AV_PIX_FMT_YUVA444P; break;
     }
     return format;
 }
@@ -442,29 +422,31 @@ static double midi(void *p, double f)
 static double r_func(void *p, double x)
 {
     x = av_clipd(x, 0.0, 1.0);
-    return (int)(x*255.0+0.5) << 16;
+    return lrint(x*255.0) << 16;
 }
 
 static double g_func(void *p, double x)
 {
     x = av_clipd(x, 0.0, 1.0);
-    return (int)(x*255.0+0.5) << 8;
+    return lrint(x*255.0) << 8;
 }
 
 static double b_func(void *p, double x)
 {
     x = av_clipd(x, 0.0, 1.0);
-    return (int)(x*255.0+0.5);
+    return lrint(x*255.0);
 }
 
-static int init_axis_color(ShowCQTContext *s, AVFrame *tmp)
+static int init_axis_color(ShowCQTContext *s, AVFrame *tmp, int half)
 {
     const char *var_names[] = { "timeclamp", "tc", "frequency", "freq", "f", NULL };
     const char *func_names[] = { "midi", "r", "g", "b", NULL };
     double (*funcs[])(void *, double) = { midi, r_func, g_func, b_func };
     AVExpr *expr = NULL;
     double *freq = NULL;
-    int x, y, ret;
+    int x, xs, y, ret;
+    int width = half ? 1920/2 : 1920, height = half ? 16 : 32;
+    int step = half ? 2 : 1;
 
     if (s->basefreq != (double) BASEFREQ || s->endfreq != (double) ENDFREQ) {
         av_log(s->ctx, AV_LOG_WARNING, "font axis rendering is not implemented in non-default frequency range,"
@@ -483,17 +465,16 @@ static int init_axis_color(ShowCQTContext *s, AVFrame *tmp)
         return ret;
     }
 
-    for (x = 0; x < 1920; x++) {
-        double vars[] = { s->timeclamp, s->timeclamp, freq[x], freq[x], freq[x] };
+    for (x = 0, xs = 0; x < width; x++, xs += step) {
+        double vars[] = { s->timeclamp, s->timeclamp, freq[xs], freq[xs], freq[xs] };
         int color = (int) av_expr_eval(expr, vars, NULL);
         uint8_t r = (color >> 16) & 0xFF, g = (color >> 8) & 0xFF, b = color & 0xFF;
         uint8_t *data = tmp->data[0];
         int linesize = tmp->linesize[0];
-        for (y = 0; y < 32; y++) {
+        for (y = 0; y < height; y++) {
             data[linesize * y + 4 * x] = r;
             data[linesize * y + 4 * x + 1] = g;
             data[linesize * y + 4 * x + 2] = b;
-            data[linesize * y + 4 * x + 3] = 0;
         }
     }
 
@@ -593,19 +574,18 @@ static int render_default_font(AVFrame *tmp)
     int x, u, v, mask;
     uint8_t *data = tmp->data[0];
     int linesize = tmp->linesize[0];
+    int width = 1920/2, height = 16;
 
-    for (x = 0; x < 1920; x += 192) {
+    for (x = 0; x < width; x += width/10) {
         uint8_t *startptr = data + 4 * x;
         for (u = 0; u < 12; u++) {
-            for (v = 0; v < 16; v++) {
-                uint8_t *p = startptr + 2 * v * linesize + 16 * 4 * u;
-                for (mask = 0x80; mask; mask >>= 1, p += 8) {
-                    if (mask & avpriv_vga16_font[str[u] * 16 + v]) {
+            for (v = 0; v < height; v++) {
+                uint8_t *p = startptr + v * linesize + height/2 * 4 * u;
+                for (mask = 0x80; mask; mask >>= 1, p += 4) {
+                    if (mask & avpriv_vga16_font[str[u] * 16 + v])
                         p[3] = 255;
-                        p[7] = 255;
-                        p[linesize+3] = 255;
-                        p[linesize+7] = 255;
-                    }
+                    else
+                        p[3] = 0;
                 }
             }
         }
@@ -618,22 +598,27 @@ static int init_axis_from_font(ShowCQTContext *s)
 {
     AVFrame *tmp = NULL;
     int ret = AVERROR(ENOMEM);
+    int width = 1920, height = 32;
+    int default_font = 0;
 
-    if (!(tmp = alloc_frame_empty(AV_PIX_FMT_RGBA, 1920, 32)))
+    if (!(tmp = alloc_frame_empty(AV_PIX_FMT_RGBA, width, height)))
         goto fail;
 
     if (!(s->axis_frame = av_frame_alloc()))
         goto fail;
 
-    if ((ret = init_axis_color(s, tmp)) < 0)
+    if (render_freetype(s, tmp) < 0 && (default_font = 1, ret = render_default_font(tmp)) < 0)
         goto fail;
 
-    if (render_freetype(s, tmp) < 0 && (ret = render_default_font(tmp)) < 0)
+    if (default_font)
+        width /= 2, height /= 2;
+
+    if ((ret = init_axis_color(s, tmp, default_font)) < 0)
         goto fail;
 
     if ((ret = ff_scale_image(s->axis_frame->data, s->axis_frame->linesize, s->width, s->axis_h,
                               convert_axis_pixel_format(s->format), tmp->data, tmp->linesize,
-                              1920, 32, AV_PIX_FMT_RGBA, s->ctx)) < 0)
+                              width, height, AV_PIX_FMT_RGBA, s->ctx)) < 0)
         goto fail;
 
     av_frame_free(&tmp);
@@ -703,14 +688,38 @@ static void draw_bar_rgb(AVFrame *out, const float *h, const float *rcp_h,
                 *lp++ = 0;
             } else {
                 mul = (h[x] - ht) * rcp_h[x];
-                *lp++ = mul * c[x].rgb.r + 0.5f;
-                *lp++ = mul * c[x].rgb.g + 0.5f;
-                *lp++ = mul * c[x].rgb.b + 0.5f;
+                *lp++ = lrintf(mul * c[x].rgb.r);
+                *lp++ = lrintf(mul * c[x].rgb.g);
+                *lp++ = lrintf(mul * c[x].rgb.b);
             }
         }
     }
 }
 
+#define DRAW_BAR_WITH_CHROMA(x) \
+do { \
+    if (h[x] <= ht) { \
+        *lpy++ = 16; \
+        *lpu++ = 128; \
+        *lpv++ = 128; \
+    } else { \
+        mul = (h[x] - ht) * rcp_h[x]; \
+        *lpy++ = lrintf(mul * c[x].yuv.y + 16.0f); \
+        *lpu++ = lrintf(mul * c[x].yuv.u + 128.0f); \
+        *lpv++ = lrintf(mul * c[x].yuv.v + 128.0f); \
+    } \
+} while (0)
+
+#define DRAW_BAR_WITHOUT_CHROMA(x) \
+do { \
+    if (h[x] <= ht) { \
+        *lpy++ = 16; \
+    } else { \
+        mul = (h[x] - ht) * rcp_h[x]; \
+        *lpy++ = lrintf(mul * c[x].yuv.y + 16.0f); \
+    } \
+} while (0)
+
 static void draw_bar_yuv(AVFrame *out, const float *h, const float *rcp_h,
                          const ColorFloat *c, int bar_h)
 {
@@ -727,36 +736,15 @@ static void draw_bar_yuv(AVFrame *out, const float *h, const float *rcp_h,
         lpy = vy + y * lsy;
         lpu = vu + yh * lsu;
         lpv = vv + yh * lsv;
-        for (x = 0; x < w; x += 2) {
-            if (h[x] <= ht) {
-                *lpy++ = 16;
-                *lpu++ = 128;
-                *lpv++ = 128;
-            } else {
-                mul = (h[x] - ht) * rcp_h[x];
-                *lpy++ = mul * c[x].yuv.y + 16.5f;
-                *lpu++ = mul * c[x].yuv.u + 128.5f;
-                *lpv++ = mul * c[x].yuv.v + 128.5f;
+        if (fmt == AV_PIX_FMT_YUV444P) {
+            for (x = 0; x < w; x += 2) {
+                DRAW_BAR_WITH_CHROMA(x);
+                DRAW_BAR_WITH_CHROMA(x+1);
             }
-            /* u and v are skipped on yuv422p and yuv420p */
-            if (fmt == AV_PIX_FMT_YUV444P) {
-                if (h[x+1] <= ht) {
-                    *lpy++ = 16;
-                    *lpu++ = 128;
-                    *lpv++ = 128;
-                } else {
-                    mul = (h[x+1] - ht) * rcp_h[x+1];
-                    *lpy++ = mul * c[x+1].yuv.y + 16.5f;
-                    *lpu++ = mul * c[x+1].yuv.u + 128.5f;
-                    *lpv++ = mul * c[x+1].yuv.v + 128.5f;
-                }
-            } else {
-                if (h[x+1] <= ht) {
-                    *lpy++ = 16;
-                } else {
-                    mul = (h[x+1] - ht) * rcp_h[x+1];
-                    *lpy++ = mul * c[x+1].yuv.y + 16.5f;
-                }
+        } else {
+            for (x = 0; x < w; x += 2) {
+                DRAW_BAR_WITH_CHROMA(x);
+                DRAW_BAR_WITHOUT_CHROMA(x+1);
             }
         }
 
@@ -764,46 +752,20 @@ static void draw_bar_yuv(AVFrame *out, const float *h, const float *rcp_h,
         lpy = vy + (y+1) * lsy;
         lpu = vu + (y+1) * lsu;
         lpv = vv + (y+1) * lsv;
-        for (x = 0; x < w; x += 2) {
-            /* u and v are skipped on yuv420p */
-            if (fmt != AV_PIX_FMT_YUV420P) {
-                if (h[x] <= ht) {
-                    *lpy++ = 16;
-                    *lpu++ = 128;
-                    *lpv++ = 128;
-                } else {
-                    mul = (h[x] - ht) * rcp_h[x];
-                    *lpy++ = mul * c[x].yuv.y + 16.5f;
-                    *lpu++ = mul * c[x].yuv.u + 128.5f;
-                    *lpv++ = mul * c[x].yuv.v + 128.5f;
-                }
-            } else {
-                if (h[x] <= ht) {
-                    *lpy++ = 16;
-                } else {
-                    mul = (h[x] - ht) * rcp_h[x];
-                    *lpy++ = mul * c[x].yuv.y + 16.5f;
-                }
+        if (fmt == AV_PIX_FMT_YUV444P) {
+            for (x = 0; x < w; x += 2) {
+                DRAW_BAR_WITH_CHROMA(x);
+                DRAW_BAR_WITH_CHROMA(x+1);
             }
-            /* u and v are skipped on yuv422p and yuv420p */
-            if (out->format == AV_PIX_FMT_YUV444P) {
-                if (h[x+1] <= ht) {
-                    *lpy++ = 16;
-                    *lpu++ = 128;
-                    *lpv++ = 128;
-                } else {
-                    mul = (h[x+1] - ht) * rcp_h[x+1];
-                    *lpy++ = mul * c[x+1].yuv.y + 16.5f;
-                    *lpu++ = mul * c[x+1].yuv.u + 128.5f;
-                    *lpv++ = mul * c[x+1].yuv.v + 128.5f;
-                }
-            } else {
-                if (h[x+1] <= ht) {
-                    *lpy++ = 16;
-                } else {
-                    mul = (h[x+1] - ht) * rcp_h[x+1];
-                    *lpy++ = mul * c[x+1].yuv.y + 16.5f;
-                }
+        } else if (fmt == AV_PIX_FMT_YUV422P) {
+            for (x = 0; x < w; x += 2) {
+                DRAW_BAR_WITH_CHROMA(x);
+                DRAW_BAR_WITHOUT_CHROMA(x+1);
+            }
+        } else {
+            for (x = 0; x < w; x += 2) {
+                DRAW_BAR_WITHOUT_CHROMA(x);
+                DRAW_BAR_WITHOUT_CHROMA(x+1);
             }
         }
     }
@@ -819,20 +781,102 @@ static void draw_axis_rgb(AVFrame *out, AVFrame *axis, const ColorFloat *c, int
         lp = out->data[0] + (off + y) * out->linesize[0];
         lpa = axis->data[0] + y * axis->linesize[0];
         for (x = 0; x < w; x++) {
-            a = rcp_255 * lpa[3];
-            *lp++ = a * lpa[0] + (1.0f - a) * c[x].rgb.r + 0.5f;
-            *lp++ = a * lpa[1] + (1.0f - a) * c[x].rgb.g + 0.5f;
-            *lp++ = a * lpa[2] + (1.0f - a) * c[x].rgb.b + 0.5f;
+            if (!lpa[3]) {
+                *lp++ = lrintf(c[x].rgb.r);
+                *lp++ = lrintf(c[x].rgb.g);
+                *lp++ = lrintf(c[x].rgb.b);
+            } else if (lpa[3] == 255) {
+                *lp++ = lpa[0];
+                *lp++ = lpa[1];
+                *lp++ = lpa[2];
+            } else {
+                a = rcp_255 * lpa[3];
+                *lp++ = lrintf(a * lpa[0] + (1.0f - a) * c[x].rgb.r);
+                *lp++ = lrintf(a * lpa[1] + (1.0f - a) * c[x].rgb.g);
+                *lp++ = lrintf(a * lpa[2] + (1.0f - a) * c[x].rgb.b);
+            }
             lpa += 4;
         }
     }
 }
 
+#define BLEND_WITH_CHROMA(c) \
+do { \
+    if (!*lpaa) { \
+        *lpy = lrintf(c.yuv.y + 16.0f); \
+        *lpu = lrintf(c.yuv.u + 128.0f); \
+        *lpv = lrintf(c.yuv.v + 128.0f); \
+    } else if (255 == *lpaa) { \
+        *lpy = *lpay; \
+        *lpu = *lpau; \
+        *lpv = *lpav; \
+    } else { \
+        float a = (1.0f/255.0f) * (*lpaa); \
+        *lpy = lrintf(a * (*lpay) + (1.0f - a) * (c.yuv.y + 16.0f)); \
+        *lpu = lrintf(a * (*lpau) + (1.0f - a) * (c.yuv.u + 128.0f)); \
+        *lpv = lrintf(a * (*lpav) + (1.0f - a) * (c.yuv.v + 128.0f)); \
+    } \
+    lpy++; lpu++; lpv++; \
+    lpay++; lpau++; lpav++; lpaa++; \
+} while (0)
+
+#define BLEND_WITHOUT_CHROMA(c, alpha_inc) \
+do { \
+    if (!*lpaa) { \
+        *lpy = lrintf(c.yuv.y + 16.0f); \
+    } else if (255 == *lpaa) { \
+        *lpy = *lpay; \
+    } else { \
+        float a = (1.0f/255.0f) * (*lpaa); \
+        *lpy = lrintf(a * (*lpay) + (1.0f - a) * (c.yuv.y + 16.0f)); \
+    } \
+    lpy++; \
+    lpay++; lpaa += alpha_inc; \
+} while (0)
+
+#define BLEND_CHROMA2(c) \
+do { \
+    if (!lpaa[0] && !lpaa[1]) { \
+        *lpu = lrintf(c.yuv.u + 128.0f); \
+        *lpv = lrintf(c.yuv.v + 128.0f); \
+    } else if (255 == lpaa[0] && 255 == lpaa[1]) { \
+        *lpu = *lpau; *lpv = *lpav; \
+    } else { \
+        float a0 = (0.5f/255.0f) * lpaa[0]; \
+        float a1 = (0.5f/255.0f) * lpaa[1]; \
+        float b = 1.0f - a0 - a1; \
+        *lpu = lrintf(a0 * lpau[0] + a1 * lpau[1] + b * (c.yuv.u + 128.0f)); \
+        *lpv = lrintf(a0 * lpav[0] + a1 * lpav[1] + b * (c.yuv.v + 128.0f)); \
+    } \
+    lpau += 2; lpav += 2; lpaa++; lpu++; lpv++; \
+} while (0)
+
+#define BLEND_CHROMA2x2(c) \
+do { \
+    if (!lpaa[0] && !lpaa[1] && !lpaa[lsaa] && !lpaa[lsaa+1]) { \
+        *lpu = lrintf(c.yuv.u + 128.0f); \
+        *lpv = lrintf(c.yuv.v + 128.0f); \
+    } else if (255 == lpaa[0] && 255 == lpaa[1] && \
+               255 == lpaa[lsaa] && 255 == lpaa[lsaa+1]) { \
+        *lpu = *lpau; *lpv = *lpav; \
+    } else { \
+        float a0 = (0.25f/255.0f) * lpaa[0]; \
+        float a1 = (0.25f/255.0f) * lpaa[1]; \
+        float a2 = (0.25f/255.0f) * lpaa[lsaa]; \
+        float a3 = (0.25f/255.0f) * lpaa[lsaa+1]; \
+        float b = 1.0f - a0 - a1 - a2 - a3; \
+        *lpu = lrintf(a0 * lpau[0] + a1 * lpau[1] + a2 * lpau[lsau] + a3 * lpau[lsau+1] \
+                    + b * (c.yuv.u + 128.0f)); \
+        *lpv = lrintf(a0 * lpav[0] + a1 * lpav[1] + a2 * lpav[lsav] + a3 * lpav[lsav+1] \
+                    + b * (c.yuv.v + 128.0f)); \
+    } \
+    lpau += 2; lpav += 2; lpaa++; lpu++; lpv++; \
+} while (0)
+
 static void draw_axis_yuv(AVFrame *out, AVFrame *axis, const ColorFloat *c, int off)
 {
     int fmt = out->format, x, y, yh, w = axis->width, h = axis->height;
     int offh = (fmt == AV_PIX_FMT_YUV420P) ? off / 2 : off;
-    float a, rcp_255 = 1.0f / 255.0f;
     uint8_t *vy = out->data[0], *vu = out->data[1], *vv = out->data[2];
     uint8_t *vay = axis->data[0], *vau = axis->data[1], *vav = axis->data[2], *vaa = axis->data[3];
     int lsy = out->linesize[0], lsu = out->linesize[1], lsv = out->linesize[2];
@@ -845,20 +889,25 @@ static void draw_axis_yuv(AVFrame *out, AVFrame *axis, const ColorFloat *c, int
         lpu = vu + (offh + yh) * lsu;
         lpv = vv + (offh + yh) * lsv;
         lpay = vay + y * lsay;
-        lpau = vau + yh * lsau;
-        lpav = vav + yh * lsav;
+        lpau = vau + y * lsau;
+        lpav = vav + y * lsav;
         lpaa = vaa + y * lsaa;
-        for (x = 0; x < w; x += 2) {
-            a = rcp_255 * (*lpaa++);
-            *lpy++ = a * (*lpay++) + (1.0f - a) * (c[x].yuv.y + 16.0f) + 0.5f;
-            *lpu++ = a * (*lpau++) + (1.0f - a) * (c[x].yuv.u + 128.0f) + 0.5f;
-            *lpv++ = a * (*lpav++) + (1.0f - a) * (c[x].yuv.v + 128.0f) + 0.5f;
-            /* u and v are skipped on yuv422p and yuv420p */
-            a = rcp_255 * (*lpaa++);
-            *lpy++ = a * (*lpay++) + (1.0f - a) * (c[x+1].yuv.y + 16.0f) + 0.5f;
-            if (fmt == AV_PIX_FMT_YUV444P) {
-                *lpu++ = a * (*lpau++) + (1.0f - a) * (c[x+1].yuv.u + 128.0f) + 0.5f;
-                *lpv++ = a * (*lpav++) + (1.0f - a) * (c[x+1].yuv.v + 128.0f) + 0.5f;
+        if (fmt == AV_PIX_FMT_YUV444P) {
+            for (x = 0; x < w; x += 2) {
+                BLEND_WITH_CHROMA(c[x]);
+                BLEND_WITH_CHROMA(c[x+1]);
+            }
+        } else if (fmt == AV_PIX_FMT_YUV422P) {
+            for (x = 0; x < w; x += 2) {
+                BLEND_WITHOUT_CHROMA(c[x], 0);
+                BLEND_CHROMA2(c[x]);
+                BLEND_WITHOUT_CHROMA(c[x+1], 1);
+            }
+        } else {
+            for (x = 0; x < w; x += 2) {
+                BLEND_WITHOUT_CHROMA(c[x], 0);
+                BLEND_CHROMA2x2(c[x]);
+                BLEND_WITHOUT_CHROMA(c[x+1], 1);
             }
         }
 
@@ -869,20 +918,21 @@ static void draw_axis_yuv(AVFrame *out, AVFrame *axis, const ColorFloat *c, int
         lpau = vau + (y + 1) * lsau;
         lpav = vav + (y + 1) * lsav;
         lpaa = vaa + (y + 1) * lsaa;
-        for (x = 0; x < out->width; x += 2) {
-            /* u and v are skipped on yuv420p */
-            a = rcp_255 * (*lpaa++);
-            *lpy++ = a * (*lpay++) + (1.0f - a) * (c[x].yuv.y + 16.0f) + 0.5f;
-            if (fmt != AV_PIX_FMT_YUV420P) {
-                *lpu++ = a * (*lpau++) + (1.0f - a) * (c[x].yuv.u + 128.0f) + 0.5f;
-                *lpv++ = a * (*lpav++) + (1.0f - a) * (c[x].yuv.v + 128.0f) + 0.5f;
+        if (fmt == AV_PIX_FMT_YUV444P) {
+            for (x = 0; x < w; x += 2) {
+                BLEND_WITH_CHROMA(c[x]);
+                BLEND_WITH_CHROMA(c[x+1]);
+            }
+        } else if (fmt == AV_PIX_FMT_YUV422P) {
+            for (x = 0; x < w; x += 2) {
+                BLEND_WITHOUT_CHROMA(c[x], 0);
+                BLEND_CHROMA2(c[x]);
+                BLEND_WITHOUT_CHROMA(c[x+1], 1);
             }
-            /* u and v are skipped on yuv422p and yuv420p */
-            a = rcp_255 * (*lpaa++);
-            *lpy++ = a * (*lpay++) + (1.0f - a) * (c[x+1].yuv.y + 16.0f) + 0.5f;
-            if (fmt == AV_PIX_FMT_YUV444P) {
-                *lpu++ = a * (*lpau++) + (1.0f - a) * (c[x+1].yuv.u + 128.0f) + 0.5f;
-                *lpv++ = a * (*lpav++) + (1.0f - a) * (c[x+1].yuv.v + 128.0f) + 0.5f;
+        } else {
+            for (x = 0; x < w; x += 2) {
+                BLEND_WITHOUT_CHROMA(c[x], 1);
+                BLEND_WITHOUT_CHROMA(c[x+1], 1);
             }
         }
     }
@@ -918,9 +968,9 @@ static void update_sono_rgb(AVFrame *sono, const ColorFloat *c, int idx)
     uint8_t *lp = sono->data[0] + idx * sono->linesize[0];
 
     for (x = 0; x < w; x++) {
-        *lp++ = c[x].rgb.r + 0.5f;
-        *lp++ = c[x].rgb.g + 0.5f;
-        *lp++ = c[x].rgb.b + 0.5f;
+        *lp++ = lrintf(c[x].rgb.r);
+        *lp++ = lrintf(c[x].rgb.g);
+        *lp++ = lrintf(c[x].rgb.b);
     }
 }
 
@@ -932,13 +982,13 @@ static void update_sono_yuv(AVFrame *sono, const ColorFloat *c, int idx)
     uint8_t *lpv = sono->data[2] + idx * sono->linesize[2];
 
     for (x = 0; x < w; x += 2) {
-        *lpy++ = c[x].yuv.y + 16.5f;
-        *lpu++ = c[x].yuv.u + 128.5f;
-        *lpv++ = c[x].yuv.v + 128.5f;
-        *lpy++ = c[x+1].yuv.y + 16.5f;
+        *lpy++ = lrintf(c[x].yuv.y + 16.0f);
+        *lpu++ = lrintf(c[x].yuv.u + 128.0f);
+        *lpv++ = lrintf(c[x].yuv.v + 128.0f);
+        *lpy++ = lrintf(c[x+1].yuv.y + 16.0f);
         if (fmt == AV_PIX_FMT_YUV444P) {
-            *lpu++ = c[x+1].yuv.u + 128.5f;
-            *lpv++ = c[x+1].yuv.v + 128.5f;
+            *lpu++ = lrintf(c[x+1].yuv.u + 128.0f);
+            *lpv++ = lrintf(c[x+1].yuv.v + 128.0f);
         }
     }
 }
@@ -989,38 +1039,65 @@ static void process_cqt(ShowCQTContext *s)
         yuv_from_cqt(s->c_buf, s->cqt_result, s->sono_g, s->width);
 }
 
-static int plot_cqt(AVFilterContext *ctx)
+static int plot_cqt(AVFilterContext *ctx, AVFrame **frameout)
 {
     AVFilterLink *outlink = ctx->outputs[0];
     ShowCQTContext *s = ctx->priv;
-    int ret = 0;
+    int64_t last_time, cur_time;
+
+#define UPDATE_TIME(t) \
+    cur_time = av_gettime(); \
+    t += cur_time - last_time; \
+    last_time = cur_time
+
+    last_time = av_gettime();
 
     memcpy(s->fft_result, s->fft_data, s->fft_len * sizeof(*s->fft_data));
     av_fft_permute(s->fft_ctx, s->fft_result);
     av_fft_calc(s->fft_ctx, s->fft_result);
     s->fft_result[s->fft_len] = s->fft_result[0];
+    UPDATE_TIME(s->fft_time);
+
     s->cqt_calc(s->cqt_result, s->fft_result, s->coeffs, s->cqt_len, s->fft_len);
+    UPDATE_TIME(s->cqt_time);
+
     process_cqt(s);
-    if (s->sono_h)
+    UPDATE_TIME(s->process_cqt_time);
+
+    if (s->sono_h) {
         s->update_sono(s->sono_frame, s->c_buf, s->sono_idx);
+        UPDATE_TIME(s->update_sono_time);
+    }
+
     if (!s->sono_count) {
-        AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+        AVFrame *out = *frameout = ff_get_video_buffer(outlink, outlink->w, outlink->h);
         if (!out)
             return AVERROR(ENOMEM);
-        if (s->bar_h)
+        out->sample_aspect_ratio = av_make_q(1, 1);
+        av_frame_set_color_range(out, AVCOL_RANGE_MPEG);
+        UPDATE_TIME(s->alloc_time);
+
+        if (s->bar_h) {
             s->draw_bar(out, s->h_buf, s->rcp_h_buf, s->c_buf, s->bar_h);
-        if (s->axis_h)
+            UPDATE_TIME(s->bar_time);
+        }
+
+        if (s->axis_h) {
             s->draw_axis(out, s->axis_frame, s->c_buf, s->bar_h);
-        if (s->sono_h)
+            UPDATE_TIME(s->axis_time);
+        }
+
+        if (s->sono_h) {
             s->draw_sono(out, s->sono_frame, s->bar_h + s->axis_h, s->sono_idx);
-        out->pts = s->frame_count;
-        ret = ff_filter_frame(outlink, out);
-        s->frame_count++;
+            UPDATE_TIME(s->sono_time);
+        }
+        out->pts = s->next_pts;
+        s->next_pts += PTS_STEP;
     }
     s->sono_count = (s->sono_count + 1) % s->count;
     if (s->sono_h)
         s->sono_idx = (s->sono_idx + s->sono_h - 1) % s->sono_h;
-    return ret;
+    return 0;
 }
 
 /* main filter control */
@@ -1133,7 +1210,7 @@ static int config_output(AVFilterLink *outlink)
     s->format = outlink->format;
     outlink->sample_aspect_ratio = av_make_q(1, 1);
     outlink->frame_rate = s->rate;
-    outlink->time_base = av_inv_q(s->rate);
+    outlink->time_base = av_mul_q(av_inv_q(s->rate), av_make_q(1, PTS_STEP));
     av_log(ctx, AV_LOG_INFO, "video: %dx%d %s %d/%d fps, bar_h = %d, axis_h = %d, sono_h = %d.\n",
            s->width, s->height, av_get_pix_fmt_name(s->format), s->rate.num, s->rate.den,
            s->bar_h, s->axis_h, s->sono_h);
@@ -1157,8 +1234,8 @@ static int config_output(AVFilterLink *outlink)
         return AVERROR(ENOMEM);
 
     s->cqt_align = 1;
-    s->cqt_coeffs_type = COEFFS_TYPE_DEFAULT;
     s->cqt_calc = cqt_calc;
+    s->permute_coeffs = NULL;
     s->draw_sono = draw_sono;
     if (s->format == AV_PIX_FMT_RGB24) {
         s->draw_bar = draw_bar_rgb;
@@ -1170,6 +1247,9 @@ static int config_output(AVFilterLink *outlink)
         s->update_sono = update_sono_yuv;
     }
 
+    if (ARCH_X86)
+        ff_showcqt_init_x86(s);
+
     if ((ret = init_cqt(s)) < 0)
         return ret;
 
@@ -1209,7 +1289,7 @@ static int config_output(AVFilterLink *outlink)
         return AVERROR(ENOMEM);
 
     s->sono_count = 0;
-    s->frame_count = 0;
+    s->next_pts = 0;
     s->sono_idx = 0;
     s->remaining_fill = s->fft_len / 2;
     s->remaining_frac = 0;
@@ -1232,14 +1312,16 @@ static int config_output(AVFilterLink *outlink)
 static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
 {
     AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
     ShowCQTContext *s = ctx->priv;
     int remaining, step, ret, x, i, j, m;
     float *audio_data;
+    AVFrame *out = NULL;
 
     if (!insamples) {
         while (s->remaining_fill < s->fft_len / 2) {
             memset(&s->fft_data[s->fft_len - s->remaining_fill], 0, sizeof(*s->fft_data) * s->remaining_fill);
-            ret = plot_cqt(ctx);
+            ret = plot_cqt(ctx, &out);
             if (ret < 0)
                 return ret;
 
@@ -1248,6 +1330,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
             for (x = 0; x < (s->fft_len-step); x++)
                 s->fft_data[x] = s->fft_data[x+step];
             s->remaining_fill += step;
+
+            if (out)
+                return ff_filter_frame(outlink, out);
         }
         return AVERROR_EOF;
     }
@@ -1263,12 +1348,30 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
                 s->fft_data[j+m].re = audio_data[2*(i+m)];
                 s->fft_data[j+m].im = audio_data[2*(i+m)+1];
             }
-            ret = plot_cqt(ctx);
+            ret = plot_cqt(ctx, &out);
             if (ret < 0) {
                 av_frame_free(&insamples);
                 return ret;
             }
             remaining -= s->remaining_fill;
+            if (out) {
+                int64_t pts = av_rescale_q(insamples->pts, inlink->time_base, av_make_q(1, inlink->sample_rate));
+                pts += insamples->nb_samples - remaining - s->fft_len/2;
+                pts = av_rescale_q(pts, av_make_q(1, inlink->sample_rate), outlink->time_base);
+                if (FFABS(pts - out->pts) > PTS_TOLERANCE) {
+                    av_log(ctx, AV_LOG_DEBUG, "changing pts from %"PRId64" (%.3f) to %"PRId64" (%.3f).\n",
+                           out->pts, out->pts * av_q2d(outlink->time_base),
+                           pts, pts * av_q2d(outlink->time_base));
+                    out->pts = pts;
+                    s->next_pts = pts + PTS_STEP;
+                }
+                ret = ff_filter_frame(outlink, out);
+                if (ret < 0) {
+                    av_frame_free(&insamples);
+                    return ret;
+                }
+                out = NULL;
+            }
             step = s->step + (s->step_frac.num + s->remaining_frac) / s->step_frac.den;
             s->remaining_frac = (s->step_frac.num + s->remaining_frac) % s->step_frac.den;
             for (m = 0; m < s->fft_len-step; m++)
@@ -1294,7 +1397,7 @@ static int request_frame(AVFilterLink *outlink)
 
     ret = ff_request_frame(inlink);
     if (ret == AVERROR_EOF)
-        filter_frame(inlink, NULL);
+        ret = filter_frame(inlink, NULL);
     return ret;
 }
 
diff --git a/libavfilter/avf_showcqt.h b/libavfilter/avf_showcqt.h
index a48b2b0..588830f 100644
--- a/libavfilter/avf_showcqt.h
+++ b/libavfilter/avf_showcqt.h
@@ -30,11 +30,6 @@ typedef struct {
     int start, len;
 } Coeffs;
 
-enum CoeffsType {
-    COEFFS_TYPE_DEFAULT,
-    COEFFS_TYPE_INTERLEAVE
-};
-
 typedef struct {
     float r, g, b;
 } RGBFloat;
@@ -60,7 +55,7 @@ typedef struct {
     AVRational          step_frac;
     int                 remaining_frac;
     int                 remaining_fill;
-    int64_t             frame_count;
+    int64_t             next_pts;
     double              *freq;
     FFTContext          *fft_ctx;
     Coeffs              *coeffs;
@@ -71,7 +66,6 @@ typedef struct {
     int                 fft_len;
     int                 cqt_len;
     int                 cqt_align;
-    enum CoeffsType     cqt_coeffs_type;
     ColorFloat          *c_buf;
     float               *h_buf;
     float               *rcp_h_buf;
@@ -80,11 +74,21 @@ typedef struct {
     /* callback */
     void                (*cqt_calc)(FFTComplex *dst, const FFTComplex *src, const Coeffs *coeffs,
                                     int len, int fft_len);
+    void                (*permute_coeffs)(float *v, int len);
     void                (*draw_bar)(AVFrame *out, const float *h, const float *rcp_h,
                                     const ColorFloat *c, int bar_h);
     void                (*draw_axis)(AVFrame *out, AVFrame *axis, const ColorFloat *c, int off);
     void                (*draw_sono)(AVFrame *out, AVFrame *sono, int off, int idx);
     void                (*update_sono)(AVFrame *sono, const ColorFloat *c, int idx);
+    /* performance debugging */
+    int64_t             fft_time;
+    int64_t             cqt_time;
+    int64_t             process_cqt_time;
+    int64_t             update_sono_time;
+    int64_t             alloc_time;
+    int64_t             bar_time;
+    int64_t             axis_time;
+    int64_t             sono_time;
     /* option */
     int                 width, height;
     AVRational          rate;
@@ -109,4 +113,6 @@ typedef struct {
     int                 axis;
 } ShowCQTContext;
 
+void ff_showcqt_init_x86(ShowCQTContext *s);
+
 #endif
diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c
index f7ccdf7..3454370 100644
--- a/libavfilter/avf_showvolume.c
+++ b/libavfilter/avf_showvolume.c
@@ -41,6 +41,8 @@ typedef struct ShowVolumeContext {
     double f;
     AVRational frame_rate;
     char *color;
+    int orientation;
+    int step;
 
     AVFrame *out;
     AVExpr *c_expr;
@@ -53,15 +55,19 @@ typedef struct ShowVolumeContext {
 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
 
 static const AVOption showvolume_options[] = {
-    { "rate", "set video rate",  OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
-    { "r",    "set video rate",  OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, 0, FLAGS },
+    { "rate", "set video rate",  OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
+    { "r",    "set video rate",  OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
     { "b", "set border width",   OFFSET(b), AV_OPT_TYPE_INT, {.i64=1}, 0, 5, FLAGS },
-    { "w", "set channel width",  OFFSET(w), AV_OPT_TYPE_INT, {.i64=400}, 80, 1080, FLAGS },
-    { "h", "set channel height", OFFSET(h), AV_OPT_TYPE_INT, {.i64=20}, 1, 100, FLAGS },
+    { "w", "set channel width",  OFFSET(w), AV_OPT_TYPE_INT, {.i64=400}, 80, 8192, FLAGS },
+    { "h", "set channel height", OFFSET(h), AV_OPT_TYPE_INT, {.i64=20}, 1, 900, FLAGS },
     { "f", "set fade",           OFFSET(f), AV_OPT_TYPE_DOUBLE, {.dbl=0.95}, 0.001, 1, FLAGS },
     { "c", "set volume color expression", OFFSET(color), AV_OPT_TYPE_STRING, {.str="if(gte(VOLUME,-6), if(gte(VOLUME,-2), if(gte(VOLUME,-1), if(gt(VOLUME,0), 0xff0000ff, 0xff0066ff), 0xff00ffff),0xff00ff00),0xffff0000)"}, 0, 0, FLAGS },
     { "t", "display channel names", OFFSET(draw_text), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
     { "v", "display volume value", OFFSET(draw_volume), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
+    { "o", "set orientation", OFFSET(orientation), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "orientation" },
+    {   "h", "horizontal", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "orientation" },
+    {   "v", "vertical",   0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "orientation" },
+    { "s", "set step size", OFFSET(step), AV_OPT_TYPE_INT, {.i64=0}, 0, 5, FLAGS },
     { NULL }
 };
 
@@ -96,7 +102,7 @@ static int query_formats(AVFilterContext *ctx)
     if ((ret = ff_formats_ref(formats, &inlink->out_formats)) < 0)
         return ret;
 
-    layouts = ff_all_channel_layouts();
+    layouts = ff_all_channel_counts();
     if ((ret = ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts)) < 0)
         return ret;
 
@@ -132,15 +138,21 @@ static int config_output(AVFilterLink *outlink)
     ShowVolumeContext *s = outlink->src->priv;
     AVFilterLink *inlink = outlink->src->inputs[0];
 
-    outlink->w = s->w;
-    outlink->h = s->h * inlink->channels + (inlink->channels - 1) * s->b;
+    if (s->orientation) {
+        outlink->h = s->w;
+        outlink->w = s->h * inlink->channels + (inlink->channels - 1) * s->b;
+    } else {
+        outlink->w = s->w;
+        outlink->h = s->h * inlink->channels + (inlink->channels - 1) * s->b;
+    }
+
     outlink->sample_aspect_ratio = (AVRational){1,1};
     outlink->frame_rate = s->frame_rate;
 
     return 0;
 }
 
-static void drawtext(AVFrame *pic, int x, int y, const char *txt)
+static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o)
 {
     const uint8_t *font;
     int font_height;
@@ -150,15 +162,26 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt)
 
     for (i = 0; txt[i]; i++) {
         int char_y, mask;
-        uint8_t *p = pic->data[0] + y*pic->linesize[0] + (x + i*8)*4;
 
-        for (char_y = 0; char_y < font_height; char_y++) {
-            for (mask = 0x80; mask; mask >>= 1) {
-                if (font[txt[i] * font_height + char_y] & mask)
-                    AV_WN32(p, ~AV_RN32(p));
-                p += 4;
+        if (o) {
+            for (char_y = font_height - 1; char_y >= 0; char_y--) {
+                uint8_t *p = pic->data[0] + (y + i * 10) * pic->linesize[0] + x * 4;
+                for (mask = 0x80; mask; mask >>= 1) {
+                    if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
+                        AV_WN32(&p[char_y * 4], ~AV_RN32(&p[char_y * 4]));
+                    p += pic->linesize[0];
+                }
+            }
+        } else {
+            uint8_t *p = pic->data[0] + y * pic->linesize[0] + (x + i * 8) * 4;
+            for (char_y = 0; char_y < font_height; char_y++) {
+                for (mask = 0x80; mask; mask >>= 1) {
+                    if (font[txt[i] * font_height + char_y] & mask)
+                        AV_WN32(p, ~AV_RN32(p));
+                    p += 4;
+                }
+                p += pic->linesize[0] - 8 * 4;
             }
-            p += pic->linesize[0] - 8*4;
         }
     }
 }
@@ -168,6 +191,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
     AVFilterContext *ctx = inlink->dst;
     AVFilterLink *outlink = ctx->outputs[0];
     ShowVolumeContext *s = ctx->priv;
+    const int step = s->step;
     int c, i, j, k;
     AVFrame *out;
 
@@ -187,7 +211,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
 
     for (j = 0; j < outlink->h; j++) {
         uint8_t *dst = s->out->data[0] + j * s->out->linesize[0];
-        for (k = 0; k < s->w; k++) {
+        for (k = 0; k < outlink->w; k++) {
             dst[k * 4 + 0] = FFMAX(dst[k * 4 + 0] * s->f, 0);
             dst[k * 4 + 1] = FFMAX(dst[k * 4 + 1] * s->f, 0);
             dst[k * 4 + 2] = FFMAX(dst[k * 4 + 2] * s->f, 0);
@@ -195,29 +219,67 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
         }
     }
 
-    for (c = 0; c < inlink->channels; c++) {
-        float *src = (float *)insamples->extended_data[c];
-        float max = 0;
-        uint32_t color;
-
-        for (i = 0; i < insamples->nb_samples; i++)
-            max = FFMAX(max, src[i]);
-
-        s->values[c * VAR_VARS_NB + VAR_VOLUME] = 20.0 * log10(max);
-        max = av_clipf(max, 0, 1);
-        s->values[c * VAR_VARS_NB + VAR_CHANNEL] = c;
-        color = av_expr_eval(s->c_expr, &s->values[c * VAR_VARS_NB], NULL);
-
-        for (j = 0; j < s->h; j++) {
-            uint8_t *dst = s->out->data[0] + (c * s->h + c * s->b + j) * s->out->linesize[0];
+    if (s->orientation) {
+        for (c = 0; c < inlink->channels; c++) {
+            float *src = (float *)insamples->extended_data[c];
+            float max = 0;
+            uint32_t color;
+
+            for (i = 0; i < insamples->nb_samples; i++)
+                max = FFMAX(max, src[i]);
+
+            s->values[c * VAR_VARS_NB + VAR_VOLUME] = 20.0 * log10(max);
+            max = av_clipf(max, 0, 1);
+            s->values[c * VAR_VARS_NB + VAR_CHANNEL] = c;
+            color = av_expr_eval(s->c_expr, &s->values[c * VAR_VARS_NB], NULL);
+
+            for (j = outlink->h - outlink->h * max; j < outlink->h; j++) {
+                uint8_t *dst = s->out->data[0] + j * s->out->linesize[0] + c * (s->b + s->h) * 4;
+                for (k = 0; k < s->h; k++) {
+                    AV_WN32A(&dst[k * 4], color);
+                    if (j & step)
+                        j += step;
+                }
+            }
 
-            for (k = 0; k < s->w * max; k++)
-                AV_WN32A(dst + k * 4, color);
+            if (outlink->h > 40 && s->draw_text) {
+                const char *channel_name = av_get_channel_name(av_channel_layout_extract_channel(insamples->channel_layout, c));
+                if (!channel_name)
+                    continue;
+                drawtext(s->out, c * (s->h + s->b) + (s->h - 10) / 2, outlink->h - 35, channel_name, 1);
+            }
         }
+    } else {
+        for (c = 0; c < inlink->channels; c++) {
+            float *src = (float *)insamples->extended_data[c];
+            float max = 0;
+            uint32_t color;
+
+            for (i = 0; i < insamples->nb_samples; i++)
+                max = FFMAX(max, src[i]);
+
+            s->values[c * VAR_VARS_NB + VAR_VOLUME] = 20.0 * log10(max);
+            max = av_clipf(max, 0, 1);
+            s->values[c * VAR_VARS_NB + VAR_CHANNEL] = c;
+            color = av_expr_eval(s->c_expr, &s->values[c * VAR_VARS_NB], NULL);
+
+            for (j = 0; j < s->h; j++) {
+                uint8_t *dst = s->out->data[0] + (c * s->h + c * s->b + j) * s->out->linesize[0];
+
+                for (k = 0; k < s->w * max; k++) {
+                    AV_WN32A(dst + k * 4, color);
+                    if (k & step)
+                        k += step;
+                }
+            }
 
-        if (s->h >= 8 && s->draw_text)
-            drawtext(s->out, 2, c * (s->h + s->b) + (s->h - 8) / 2,
-                     av_get_channel_name(av_channel_layout_extract_channel(insamples->channel_layout, c)));
+            if (s->h >= 8 && s->draw_text) {
+                const char *channel_name = av_get_channel_name(av_channel_layout_extract_channel(insamples->channel_layout, c));
+                if (!channel_name)
+                    continue;
+                drawtext(s->out, 2, c * (s->h + s->b) + (s->h - 8) / 2, channel_name, 0);
+            }
+        }
     }
 
     av_frame_free(&insamples);
@@ -227,11 +289,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
     av_frame_make_writable(out);
 
     for (c = 0; c < inlink->channels && s->draw_volume; c++) {
-        if (s->h >= 8) {
-            char buf[16];
-
-            snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]);
-            drawtext(out, FFMAX(0, s->w - 8 * (int)strlen(buf)), c * (s->h + s->b) + (s->h - 8) / 2, buf);
+        char buf[16];
+        if (s->orientation) {
+            if (s->h >= 8) {
+                snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]);
+                drawtext(out, c * (s->h + s->b) + (s->h - 8) / 2, 2, buf, 1);
+            }
+        } else {
+            if (s->h >= 8) {
+                snprintf(buf, sizeof(buf), "%.2f", s->values[c * VAR_VARS_NB + VAR_VOLUME]);
+                drawtext(out, FFMAX(0, s->w - 8 * (int)strlen(buf)), c * (s->h + s->b) + (s->h - 8) / 2, buf, 0);
+            }
         }
     }
 
diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c
index 269dc11..9008964 100644
--- a/libavfilter/avf_showwaves.c
+++ b/libavfilter/avf_showwaves.c
@@ -93,8 +93,8 @@ static const AVOption showwaves_options[] = {
         { "p2p",   "draw a line between samples",          0, AV_OPT_TYPE_CONST, {.i64=MODE_P2P},           .flags=FLAGS, .unit="mode"},
         { "cline", "draw a centered line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_CENTERED_LINE}, .flags=FLAGS, .unit="mode"},
     { "n",    "set how many samples to show in the same point", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS },
-    { "rate", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
-    { "r",    "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
+    { "rate", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
+    { "r",    "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
     { "split_channels", "draw channels separately", OFFSET(split_channels), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
     { "colors", "set channels colors", OFFSET(colors), AV_OPT_TYPE_STRING, {.str = "red|green|blue|yellow|orange|lime|pink|magenta|brown" }, 0, 0, FLAGS },
     { "scale", "set amplitude scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, SCALE_NB-1, FLAGS, .unit="scale" },
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 2f4d59f..21f8d9e 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -22,9 +22,11 @@
 #include "libavutil/atomic.h"
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
+#include "libavutil/buffer.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/common.h"
 #include "libavutil/eval.h"
+#include "libavutil/hwcontext.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/internal.h"
 #include "libavutil/opt.h"
@@ -322,6 +324,17 @@ int avfilter_config_links(AVFilterContext *filter)
                     return ret;
                 }
 
+            if (link->src->nb_inputs && link->src->inputs[0]->hw_frames_ctx &&
+                !link->hw_frames_ctx) {
+                AVHWFramesContext *input_ctx = (AVHWFramesContext*)link->src->inputs[0]->hw_frames_ctx->data;
+
+                if (input_ctx->format == link->format) {
+                    link->hw_frames_ctx = av_buffer_ref(link->src->inputs[0]->hw_frames_ctx);
+                    if (!link->hw_frames_ctx)
+                        return AVERROR(ENOMEM);
+                }
+            }
+
             link->init_state = AVLINK_INIT;
         }
     }
@@ -715,6 +728,8 @@ static void free_link(AVFilterLink *link)
     if (link->dst)
         link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL;
 
+    av_buffer_unref(&link->hw_frames_ctx);
+
     ff_formats_unref(&link->in_formats);
     ff_formats_unref(&link->out_formats);
     ff_formats_unref(&link->in_samplerates);
@@ -747,6 +762,8 @@ void avfilter_free(AVFilterContext *filter)
     if (filter->filter->priv_class)
         av_opt_free(filter->priv);
 
+    av_buffer_unref(&filter->hw_device_ctx);
+
     av_freep(&filter->name);
     av_freep(&filter->input_pads);
     av_freep(&filter->output_pads);
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 04bf585..757b81a 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -37,6 +37,7 @@
 
 #include "libavutil/attributes.h"
 #include "libavutil/avutil.h"
+#include "libavutil/buffer.h"
 #include "libavutil/dict.h"
 #include "libavutil/frame.h"
 #include "libavutil/log.h"
@@ -349,6 +350,15 @@ struct AVFilterContext {
     void *enable;                   ///< parsed expression (AVExpr*)
     double *var_values;             ///< variable values for the enable expression
     int is_disabled;                ///< the enabled state from the last expression evaluation
+
+    /**
+     * For filters which will create hardware frames, sets the device the
+     * filter should create them in.  All other filters will ignore this field:
+     * in particular, a filter which consumes or processes hardware frames will
+     * instead use the hw_frames_ctx field in AVFilterLink to carry the
+     * hardware context information.
+     */
+    AVBufferRef *hw_device_ctx;
 };
 
 /**
@@ -534,6 +544,12 @@ struct AVFilterLink {
      * cleared when a frame is filtered.
      */
     int frame_wanted_out;
+
+    /**
+     * For hwaccel pixel formats, this should be a reference to the
+     * AVHWFramesContext describing the frames.
+     */
+    AVBufferRef *hw_frames_ctx;
 };
 
 /**
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 9f50b41..4275113 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -93,12 +93,17 @@ AVFilterGraph *avfilter_graph_alloc(void)
 
 void ff_filter_graph_remove_filter(AVFilterGraph *graph, AVFilterContext *filter)
 {
-    int i;
+    int i, j;
     for (i = 0; i < graph->nb_filters; i++) {
         if (graph->filters[i] == filter) {
             FFSWAP(AVFilterContext*, graph->filters[i],
                    graph->filters[graph->nb_filters - 1]);
             graph->nb_filters--;
+            filter->graph = NULL;
+            for (j = 0; j<filter->nb_outputs; j++)
+                if (filter->outputs[j])
+                    filter->outputs[j]->graph = NULL;
+
             return;
         }
     }
diff --git a/libavfilter/blend.h b/libavfilter/blend.h
index ccef136..54c4fdb 100644
--- a/libavfilter/blend.h
+++ b/libavfilter/blend.h
@@ -56,6 +56,8 @@ enum BlendMode {
     BLEND_GLOW,
     BLEND_ADDITION128,
     BLEND_MULTIPLY128,
+    BLEND_HEAT,
+    BLEND_FREEZE,
     BLEND_NB
 };
 
@@ -68,7 +70,7 @@ typedef struct FilterParams {
                   const uint8_t *bottom, ptrdiff_t bottom_linesize,
                   uint8_t *dst, ptrdiff_t dst_linesize,
                   ptrdiff_t width, ptrdiff_t height,
-                  struct FilterParams *param, double *values);
+                  struct FilterParams *param, double *values, int starty);
 } FilterParams;
 
 void ff_blend_init(FilterParams *param, int is_16bit);
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index 3920b04..9294811 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -54,6 +54,8 @@ typedef struct BufferSourceContext {
     AVRational        pixel_aspect;
     char              *sws_param;
 
+    AVBufferRef *hw_frames_ctx;
+
     /* audio only */
     int sample_rate;
     enum AVSampleFormat sample_fmt;
@@ -61,6 +63,7 @@ typedef struct BufferSourceContext {
     uint64_t channel_layout;
     char    *channel_layout_str;
 
+    int got_format_from_params;
     int eof;
 } BufferSourceContext;
 
@@ -76,6 +79,62 @@ typedef struct BufferSourceContext {
         return AVERROR(EINVAL);\
     }
 
+AVBufferSrcParameters *av_buffersrc_parameters_alloc(void)
+{
+    AVBufferSrcParameters *par = av_mallocz(sizeof(*par));
+    if (!par)
+        return NULL;
+
+    par->format = -1;
+
+    return par;
+}
+
+int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param)
+{
+    BufferSourceContext *s = ctx->priv;
+
+    if (param->time_base.num > 0 && param->time_base.den > 0)
+        s->time_base = param->time_base;
+
+    switch (ctx->filter->outputs[0].type) {
+    case AVMEDIA_TYPE_VIDEO:
+        if (param->format != AV_PIX_FMT_NONE) {
+            s->got_format_from_params = 1;
+            s->pix_fmt = param->format;
+        }
+        if (param->width > 0)
+            s->w = param->width;
+        if (param->height > 0)
+            s->h = param->height;
+        if (param->sample_aspect_ratio.num > 0 && param->sample_aspect_ratio.den > 0)
+            s->pixel_aspect = param->sample_aspect_ratio;
+        if (param->frame_rate.num > 0 && param->frame_rate.den > 0)
+            s->frame_rate = param->frame_rate;
+        if (param->hw_frames_ctx) {
+            av_buffer_unref(&s->hw_frames_ctx);
+            s->hw_frames_ctx = av_buffer_ref(param->hw_frames_ctx);
+            if (!s->hw_frames_ctx)
+                return AVERROR(ENOMEM);
+        }
+        break;
+    case AVMEDIA_TYPE_AUDIO:
+        if (param->format != AV_SAMPLE_FMT_NONE) {
+            s->got_format_from_params = 1;
+            s->sample_fmt = param->format;
+        }
+        if (param->sample_rate > 0)
+            s->sample_rate = param->sample_rate;
+        if (param->channel_layout)
+            s->channel_layout = param->channel_layout;
+        break;
+    default:
+        return AVERROR_BUG;
+    }
+
+    return 0;
+}
+
 int attribute_align_arg av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame)
 {
     return av_buffersrc_add_frame_flags(ctx, (AVFrame *)frame,
@@ -187,7 +246,8 @@ static av_cold int init_video(AVFilterContext *ctx)
 {
     BufferSourceContext *c = ctx->priv;
 
-    if (c->pix_fmt == AV_PIX_FMT_NONE || !c->w || !c->h || av_q2d(c->time_base) <= 0) {
+    if (!(c->pix_fmt != AV_PIX_FMT_NONE || c->got_format_from_params) || !c->w || !c->h ||
+        av_q2d(c->time_base) <= 0) {
         av_log(ctx, AV_LOG_ERROR, "Invalid parameters provided.\n");
         return AVERROR(EINVAL);
     }
@@ -225,8 +285,8 @@ static const AVOption buffer_options[] = {
     { "sar_num",       "deprecated, do not use", OFFSET(pixel_aspect.num), AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, V },
     { "sar_den",       "deprecated, do not use", OFFSET(pixel_aspect.den), AV_OPT_TYPE_INT,      { .i64 = 0 }, 0, INT_MAX, V },
 #endif
-    { "sar",           "sample aspect ratio",    OFFSET(pixel_aspect),     AV_OPT_TYPE_RATIONAL, { .dbl = 1 }, 0, DBL_MAX, V },
-    { "pixel_aspect",  "sample aspect ratio",    OFFSET(pixel_aspect),     AV_OPT_TYPE_RATIONAL, { .dbl = 1 }, 0, DBL_MAX, V },
+    { "sar",           "sample aspect ratio",    OFFSET(pixel_aspect),     AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
+    { "pixel_aspect",  "sample aspect ratio",    OFFSET(pixel_aspect),     AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
     { "time_base",     NULL,                     OFFSET(time_base),        AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
     { "frame_rate",    NULL,                     OFFSET(frame_rate),       AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, DBL_MAX, V },
     { "sws_param",     NULL,                     OFFSET(sws_param),        AV_OPT_TYPE_STRING,                    .flags = V },
@@ -251,7 +311,7 @@ static av_cold int init_audio(AVFilterContext *ctx)
     BufferSourceContext *s = ctx->priv;
     int ret = 0;
 
-    if (s->sample_fmt == AV_SAMPLE_FMT_NONE) {
+    if (!(s->sample_fmt != AV_SAMPLE_FMT_NONE || s->got_format_from_params)) {
         av_log(ctx, AV_LOG_ERROR, "Sample format was not set or was invalid\n");
         return AVERROR(EINVAL);
     }
@@ -305,6 +365,7 @@ static av_cold void uninit(AVFilterContext *ctx)
         av_fifo_generic_read(s->fifo, &frame, sizeof(frame), NULL);
         av_frame_free(&frame);
     }
+    av_buffer_unref(&s->hw_frames_ctx);
     av_fifo_freep(&s->fifo);
 }
 
@@ -352,6 +413,12 @@ static int config_props(AVFilterLink *link)
         link->w = c->w;
         link->h = c->h;
         link->sample_aspect_ratio = c->pixel_aspect;
+
+        if (c->hw_frames_ctx) {
+            link->hw_frames_ctx = av_buffer_ref(c->hw_frames_ctx);
+            if (!link->hw_frames_ctx)
+                return AVERROR(ENOMEM);
+        }
         break;
     case AVMEDIA_TYPE_AUDIO:
         if (!c->channel_layout)
@@ -370,6 +437,7 @@ static int request_frame(AVFilterLink *link)
 {
     BufferSourceContext *c = link->src->priv;
     AVFrame *frame;
+    int ret;
 
     if (!av_fifo_size(c->fifo)) {
         if (c->eof)
@@ -379,7 +447,9 @@ static int request_frame(AVFilterLink *link)
     }
     av_fifo_generic_read(c->fifo, &frame, sizeof(frame), NULL);
 
-    return ff_filter_frame(link, frame);
+    ret = ff_filter_frame(link, frame);
+
+    return ret;
 }
 
 static int poll_frame(AVFilterLink *link)
diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h
index 847c093..31417c4 100644
--- a/libavfilter/buffersrc.h
+++ b/libavfilter/buffersrc.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -66,6 +65,80 @@ enum {
 unsigned av_buffersrc_get_nb_failed_requests(AVFilterContext *buffer_src);
 
 /**
+ * This structure contains the parameters describing the frames that will be
+ * passed to this filter.
+ *
+ * It should be allocated with av_buffersrc_parameters_alloc() and freed with
+ * av_free(). All the allocated fields in it remain owned by the caller.
+ */
+typedef struct AVBufferSrcParameters {
+    /**
+     * video: the pixel format, value corresponds to enum AVPixelFormat
+     * audio: the sample format, value corresponds to enum AVSampleFormat
+     */
+    int format;
+    /**
+     * The timebase to be used for the timestamps on the input frames.
+     */
+    AVRational time_base;
+
+    /**
+     * Video only, the display dimensions of the input frames.
+     */
+    int width, height;
+
+    /**
+     * Video only, the sample (pixel) aspect ratio.
+     */
+    AVRational sample_aspect_ratio;
+
+    /**
+     * Video only, the frame rate of the input video. This field must only be
+     * set to a non-zero value if input stream has a known constant framerate
+     * and should be left at its initial value if the framerate is variable or
+     * unknown.
+     */
+    AVRational frame_rate;
+
+    /**
+     * Video with a hwaccel pixel format only. This should be a reference to an
+     * AVHWFramesContext instance describing the input frames.
+     */
+    AVBufferRef *hw_frames_ctx;
+
+    /**
+     * Audio only, the audio sampling rate in samples per secon.
+     */
+    int sample_rate;
+
+    /**
+     * Audio only, the audio channel layout
+     */
+    uint64_t channel_layout;
+} AVBufferSrcParameters;
+
+/**
+ * Allocate a new AVBufferSrcParameters instance. It should be freed by the
+ * caller with av_free().
+ */
+AVBufferSrcParameters *av_buffersrc_parameters_alloc(void);
+
+/**
+ * Initialize the buffersrc or abuffersrc filter with the provided parameters.
+ * This function may be called multiple times, the later calls override the
+ * previous ones. Some of the parameters may also be set through AVOptions, then
+ * whatever method is used last takes precedence.
+ *
+ * @param ctx an instance of the buffersrc or abuffersrc filter
+ * @param param the stream parameters. The frames later passed to this filter
+ *              must conform to those parameters. All the allocated fields in
+ *              param remain owned by the caller, libavfilter will make internal
+ *              copies or references when necessary.
+ * @return 0 on success, a negative AVERROR code on failure.
+ */
+int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *param);
+
+/**
  * Add a frame to the buffer source.
  *
  * @param ctx   an instance of the buffersrc filter
diff --git a/libavfilter/bwdif.h b/libavfilter/bwdif.h
new file mode 100644
index 0000000..8b42c76
--- /dev/null
+++ b/libavfilter/bwdif.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFILTER_BWDIF_H
+#define AVFILTER_BWDIF_H
+
+#include "libavutil/pixdesc.h"
+#include "avfilter.h"
+
+enum BWDIFMode {
+    BWDIF_MODE_SEND_FRAME = 0, ///< send 1 frame for each frame
+    BWDIF_MODE_SEND_FIELD = 1, ///< send 1 frame for each field
+};
+
+enum BWDIFParity {
+    BWDIF_PARITY_TFF  =  0, ///< top field first
+    BWDIF_PARITY_BFF  =  1, ///< bottom field first
+    BWDIF_PARITY_AUTO = -1, ///< auto detection
+};
+
+enum BWDIFDeint {
+    BWDIF_DEINT_ALL        = 0, ///< deinterlace all frames
+    BWDIF_DEINT_INTERLACED = 1, ///< only deinterlace frames marked as interlaced
+};
+
+typedef struct BWDIFContext {
+    const AVClass *class;
+
+    int mode;           ///< BWDIFMode
+    int parity;         ///< BWDIFParity
+    int deint;          ///< BWDIFDeint
+
+    int frame_pending;
+
+    AVFrame *cur;
+    AVFrame *next;
+    AVFrame *prev;
+    AVFrame *out;
+
+    void (*filter_intra)(void *dst1, void *cur1, int w, int prefs, int mrefs,
+                         int prefs3, int mrefs3, int parity, int clip_max);
+    void (*filter_line)(void *dst, void *prev, void *cur, void *next,
+                        int w, int prefs, int mrefs, int prefs2, int mrefs2,
+                        int prefs3, int mrefs3, int prefs4, int mrefs4,
+                        int parity, int clip_max);
+    void (*filter_edge)(void *dst, void *prev, void *cur, void *next,
+                        int w, int prefs, int mrefs, int prefs2, int mrefs2,
+                        int parity, int clip_max, int spat);
+
+    const AVPixFmtDescriptor *csp;
+    int inter_field;
+    int eof;
+} BWDIFContext;
+
+void ff_bwdif_init_x86(BWDIFContext *bwdif);
+
+#endif /* AVFILTER_BWDIF_H */
diff --git a/libavfilter/colorspacedsp.c b/libavfilter/colorspacedsp.c
new file mode 100644
index 0000000..b8ba5c0
--- /dev/null
+++ b/libavfilter/colorspacedsp.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2016 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * 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 "colorspacedsp.h"
+
+/*
+ * SS_W/H stands for "subsampling_w/h"
+ * it's analogous to AVPixFmtDescriptor->log2_chroma_w/h.
+ */
+#define SS_W 0
+#define SS_H 0
+
+#define BIT_DEPTH 8
+#include "colorspacedsp_template.c"
+
+#undef BIT_DEPTH
+#define BIT_DEPTH 10
+#include "colorspacedsp_template.c"
+
+#undef BIT_DEPTH
+#define BIT_DEPTH 12
+#include "colorspacedsp_template.c"
+
+#undef SS_W
+#undef SS_H
+
+#define SS_W 1
+#define SS_H 0
+
+#undef BIT_DEPTH
+#define BIT_DEPTH 8
+#include "colorspacedsp_template.c"
+
+#undef BIT_DEPTH
+#define BIT_DEPTH 10
+#include "colorspacedsp_template.c"
+
+#undef BIT_DEPTH
+#define BIT_DEPTH 12
+#include "colorspacedsp_template.c"
+
+#undef SS_W
+#undef SS_H
+
+#define SS_W 1
+#define SS_H 1
+
+#undef BIT_DEPTH
+#define BIT_DEPTH 8
+#include "colorspacedsp_template.c"
+
+#undef BIT_DEPTH
+#define BIT_DEPTH 10
+#include "colorspacedsp_template.c"
+
+#undef BIT_DEPTH
+#define BIT_DEPTH 12
+#include "colorspacedsp_template.c"
+
+static void multiply3x3_c(int16_t *buf[3], ptrdiff_t stride,
+                          int w, int h, const int16_t m[3][3][8])
+{
+    int y, x;
+    int16_t *buf0 = buf[0], *buf1 = buf[1], *buf2 = buf[2];
+
+    for (y = 0; y < h; y++) {
+        for (x = 0; x < w; x++) {
+            int v0 = buf0[x], v1 = buf1[x], v2 = buf2[x];
+
+            buf0[x] = av_clip_int16((m[0][0][0] * v0 + m[0][1][0] * v1 +
+                                     m[0][2][0] * v2 + 8192) >> 14);
+            buf1[x] = av_clip_int16((m[1][0][0] * v0 + m[1][1][0] * v1 +
+                                     m[1][2][0] * v2 + 8192) >> 14);
+            buf2[x] = av_clip_int16((m[2][0][0] * v0 + m[2][1][0] * v1 +
+                                     m[2][2][0] * v2 + 8192) >> 14);
+        }
+
+        buf0 += stride;
+        buf1 += stride;
+        buf2 += stride;
+    }
+}
+
+void ff_colorspacedsp_init(ColorSpaceDSPContext *dsp)
+{
+#define init_yuv2rgb_fn(bit) \
+    dsp->yuv2rgb[BPP_##bit][SS_444] = yuv2rgb_444p##bit##_c; \
+    dsp->yuv2rgb[BPP_##bit][SS_422] = yuv2rgb_422p##bit##_c; \
+    dsp->yuv2rgb[BPP_##bit][SS_420] = yuv2rgb_420p##bit##_c
+
+    init_yuv2rgb_fn( 8);
+    init_yuv2rgb_fn(10);
+    init_yuv2rgb_fn(12);
+
+#define init_rgb2yuv_fn(bit) \
+    dsp->rgb2yuv[BPP_##bit][SS_444] = rgb2yuv_444p##bit##_c; \
+    dsp->rgb2yuv[BPP_##bit][SS_422] = rgb2yuv_422p##bit##_c; \
+    dsp->rgb2yuv[BPP_##bit][SS_420] = rgb2yuv_420p##bit##_c
+
+    init_rgb2yuv_fn( 8);
+    init_rgb2yuv_fn(10);
+    init_rgb2yuv_fn(12);
+
+#define init_rgb2yuv_fsb_fn(bit) \
+    dsp->rgb2yuv_fsb[BPP_##bit][SS_444] = rgb2yuv_fsb_444p##bit##_c; \
+    dsp->rgb2yuv_fsb[BPP_##bit][SS_422] = rgb2yuv_fsb_422p##bit##_c; \
+    dsp->rgb2yuv_fsb[BPP_##bit][SS_420] = rgb2yuv_fsb_420p##bit##_c
+
+    init_rgb2yuv_fsb_fn( 8);
+    init_rgb2yuv_fsb_fn(10);
+    init_rgb2yuv_fsb_fn(12);
+
+#define init_yuv2yuv_fn(idx1, bit1, bit2) \
+    dsp->yuv2yuv[idx1][BPP_##bit2][SS_444] = yuv2yuv_444p##bit1##to##bit2##_c; \
+    dsp->yuv2yuv[idx1][BPP_##bit2][SS_422] = yuv2yuv_422p##bit1##to##bit2##_c; \
+    dsp->yuv2yuv[idx1][BPP_##bit2][SS_420] = yuv2yuv_420p##bit1##to##bit2##_c
+#define init_yuv2yuv_fns(bit1) \
+    init_yuv2yuv_fn(BPP_##bit1, bit1,  8); \
+    init_yuv2yuv_fn(BPP_##bit1, bit1, 10); \
+    init_yuv2yuv_fn(BPP_##bit1, bit1, 12)
+
+    init_yuv2yuv_fns( 8);
+    init_yuv2yuv_fns(10);
+    init_yuv2yuv_fns(12);
+
+    dsp->multiply3x3 = multiply3x3_c;
+
+    if (ARCH_X86)
+        ff_colorspacedsp_x86_init(dsp);
+}
diff --git a/libavfilter/colorspacedsp.h b/libavfilter/colorspacedsp.h
new file mode 100644
index 0000000..a81e4f0
--- /dev/null
+++ b/libavfilter/colorspacedsp.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFILTER_COLORSPACEDSP_H
+#define AVFILTER_COLORSPACEDSP_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef void (*yuv2rgb_fn)(int16_t *rgb[3], ptrdiff_t rgb_stride,
+                           uint8_t *yuv[3], const ptrdiff_t yuv_stride[3],
+                           int w, int h, const int16_t yuv2rgb_coeffs[3][3][8],
+                           const int16_t yuv_offset[8]);
+typedef void (*rgb2yuv_fn)(uint8_t *yuv[3], const ptrdiff_t yuv_stride[3],
+                           int16_t *rgb[3], ptrdiff_t rgb_stride,
+                           int w, int h, const int16_t rgb2yuv_coeffs[3][3][8],
+                           const int16_t yuv_offset[8]);
+typedef void (*rgb2yuv_fsb_fn)(uint8_t *yuv[3], const ptrdiff_t yuv_stride[3],
+                               int16_t *rgb[3], ptrdiff_t rgb_stride,
+                               int w, int h, const int16_t rgb2yuv_coeffs[3][3][8],
+                               const int16_t yuv_offset[8],
+                               int *rnd[3][2]);
+typedef void (*yuv2yuv_fn)(uint8_t *yuv_out[3], const ptrdiff_t yuv_out_stride[3],
+                           uint8_t *yuv_in[3], const ptrdiff_t yuv_in_stride[3],
+                           int w, int h, const int16_t yuv2yuv_coeffs[3][3][8],
+                           const int16_t yuv_offset[2][8]);
+
+enum BitDepthIndex {
+    BPP_8,
+    BPP_10,
+    BPP_12,
+    NB_BPP,
+};
+
+enum ChromaSubsamplingIndex {
+    SS_444,
+    SS_422,
+    SS_420,
+    NB_SS,
+};
+
+typedef struct ColorSpaceDSPContext {
+    /* Convert input YUV pixel buffer from a user into an internal, 15bpp array
+     * of intermediate RGB data. */
+    yuv2rgb_fn yuv2rgb[NB_BPP][NB_SS];
+    /* Convert intermediate RGB data (15bpp, internal format) into YUV data and
+     * store into user-provided output buffer */
+    rgb2yuv_fn rgb2yuv[NB_BPP][NB_SS];
+    /* Same as rgb2yuv(), but use floyd-steinberg dithering */
+    rgb2yuv_fsb_fn rgb2yuv_fsb[NB_BPP][NB_SS];
+    /* Direct yuv-to-yuv conversion (input and output are both user-provided
+     * buffers) */
+    yuv2yuv_fn yuv2yuv[NB_BPP /* in */][NB_BPP /* out */][NB_SS];
+
+    /* In-place 3x3 matrix multiplication. Input and output are both 15bpp
+     * (our internal data format) */
+    void (*multiply3x3)(int16_t *data[3], ptrdiff_t stride,
+                        int w, int h, const int16_t m[3][3][8]);
+} ColorSpaceDSPContext;
+
+void ff_colorspacedsp_init(ColorSpaceDSPContext *dsp);
+
+/* internal */
+void ff_colorspacedsp_x86_init(ColorSpaceDSPContext *dsp);
+
+#endif /* AVFILTER_COLORSPACEDSP_H */
diff --git a/libavfilter/colorspacedsp_template.c b/libavfilter/colorspacedsp_template.c
new file mode 100644
index 0000000..53ac0d7
--- /dev/null
+++ b/libavfilter/colorspacedsp_template.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2016 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * 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/avassert.h"
+
+#undef avg
+#undef ss
+
+#if SS_W == 0
+#define ss 444
+#define avg(a,b,c,d) (a)
+#elif SS_H == 0
+#define ss 422
+#define avg(a,b,c,d) (((a) + (b) + 1) >> 1)
+#else
+#define ss 420
+#define avg(a,b,c,d) (((a) + (b) + (c) + (d) + 2) >> 2)
+#endif
+
+#undef fn
+#undef fn2
+#undef fn3
+#define fn3(a,b,c) a##_##c##p##b##_c
+#define fn2(a,b,c) fn3(a,b,c)
+#define fn(a) fn2(a, BIT_DEPTH, ss)
+
+#undef pixel
+#undef av_clip_pixel
+#if BIT_DEPTH == 8
+#define pixel uint8_t
+#define av_clip_pixel(x) av_clip_uint8(x)
+#else
+#define pixel uint16_t
+#define av_clip_pixel(x) av_clip_uintp2(x, BIT_DEPTH)
+#endif
+
+static void fn(yuv2rgb)(int16_t *rgb[3], ptrdiff_t rgb_stride,
+                        uint8_t *_yuv[3], const ptrdiff_t yuv_stride[3],
+                        int w, int h, const int16_t yuv2rgb_coeffs[3][3][8],
+                        const int16_t yuv_offset[8])
+{
+    pixel **yuv = (pixel **) _yuv;
+    const pixel *yuv0 = yuv[0], *yuv1 = yuv[1], *yuv2 = yuv[2];
+    int16_t *rgb0 = rgb[0], *rgb1 = rgb[1], *rgb2 = rgb[2];
+    int y, x;
+    int cy = yuv2rgb_coeffs[0][0][0];
+    int crv = yuv2rgb_coeffs[0][2][0];
+    int cgu = yuv2rgb_coeffs[1][1][0];
+    int cgv = yuv2rgb_coeffs[1][2][0];
+    int cbu = yuv2rgb_coeffs[2][1][0];
+    const int sh = BIT_DEPTH - 1, rnd = 1 << (sh - 1);
+    const int uv_offset = 128 << (BIT_DEPTH - 8);
+
+    av_assert2(yuv2rgb_coeffs[0][1][0] == 0);
+    av_assert2(yuv2rgb_coeffs[2][2][0] == 0);
+    av_assert2(yuv2rgb_coeffs[1][0][0] == cy && yuv2rgb_coeffs[2][0][0] == cy);
+
+    w = AV_CEIL_RSHIFT(w, SS_W);
+    h = AV_CEIL_RSHIFT(h, SS_H);
+    for (y = 0; y < h; y++) {
+        for (x = 0; x < w; x++) {
+            int y00 = yuv0[x << SS_W] - yuv_offset[0];
+#if SS_W == 1
+            int y01 = yuv0[2 * x + 1] - yuv_offset[0];
+#if SS_H == 1
+            int y10 = yuv0[yuv_stride[0] / sizeof(pixel) + 2 * x] - yuv_offset[0];
+            int y11 = yuv0[yuv_stride[0] / sizeof(pixel) + 2 * x + 1] - yuv_offset[0];
+#endif
+#endif
+            int u = yuv1[x] - uv_offset, v = yuv2[x] - uv_offset;
+
+            rgb0[x << SS_W]              = av_clip_int16((y00 * cy + crv * v + rnd) >> sh);
+#if SS_W == 1
+            rgb0[2 * x + 1]              = av_clip_int16((y01 * cy + crv * v + rnd) >> sh);
+#if SS_H == 1
+            rgb0[2 * x + rgb_stride]     = av_clip_int16((y10 * cy + crv * v + rnd) >> sh);
+            rgb0[2 * x + rgb_stride + 1] = av_clip_int16((y11 * cy + crv * v + rnd) >> sh);
+#endif
+#endif
+
+            rgb1[x << SS_W]              = av_clip_int16((y00 * cy + cgu * u +
+                                                          cgv * v + rnd) >> sh);
+#if SS_W == 1
+            rgb1[2 * x + 1]              = av_clip_int16((y01 * cy + cgu * u +
+                                                          cgv * v + rnd) >> sh);
+#if SS_H == 1
+            rgb1[2 * x + rgb_stride]     = av_clip_int16((y10 * cy + cgu * u +
+                                                          cgv * v + rnd) >> sh);
+            rgb1[2 * x + rgb_stride + 1] = av_clip_int16((y11 * cy + cgu * u +
+                                                          cgv * v + rnd) >> sh);
+#endif
+#endif
+
+            rgb2[x << SS_W]              = av_clip_int16((y00 * cy + cbu * u + rnd) >> sh);
+#if SS_W == 1
+            rgb2[2 * x + 1]              = av_clip_int16((y01 * cy + cbu * u + rnd) >> sh);
+#if SS_H == 1
+            rgb2[2 * x + rgb_stride]     = av_clip_int16((y10 * cy + cbu * u + rnd) >> sh);
+            rgb2[2 * x + rgb_stride + 1] = av_clip_int16((y11 * cy + cbu * u + rnd) >> sh);
+#endif
+#endif
+        }
+
+        yuv0 += (yuv_stride[0] * (1 << SS_H)) / sizeof(pixel);
+        yuv1 += yuv_stride[1] / sizeof(pixel);
+        yuv2 += yuv_stride[2] / sizeof(pixel);
+        rgb0 += rgb_stride * (1 << SS_H);
+        rgb1 += rgb_stride * (1 << SS_H);
+        rgb2 += rgb_stride * (1 << SS_H);
+    }
+}
+
+static void fn(rgb2yuv)(uint8_t *_yuv[3], const ptrdiff_t yuv_stride[3],
+                        int16_t *rgb[3], ptrdiff_t s,
+                        int w, int h, const int16_t rgb2yuv_coeffs[3][3][8],
+                        const int16_t yuv_offset[8])
+{
+    pixel **yuv = (pixel **) _yuv;
+    pixel *yuv0 = yuv[0], *yuv1 = yuv[1], *yuv2 = yuv[2];
+    const int16_t *rgb0 = rgb[0], *rgb1 = rgb[1], *rgb2 = rgb[2];
+    int y, x;
+    const int sh = 29 - BIT_DEPTH;
+    const int rnd = 1 << (sh - 1);
+    int cry = rgb2yuv_coeffs[0][0][0];
+    int cgy = rgb2yuv_coeffs[0][1][0];
+    int cby = rgb2yuv_coeffs[0][2][0];
+    int cru = rgb2yuv_coeffs[1][0][0];
+    int cgu = rgb2yuv_coeffs[1][1][0];
+    int cburv = rgb2yuv_coeffs[1][2][0];
+    int cgv = rgb2yuv_coeffs[2][1][0];
+    int cbv = rgb2yuv_coeffs[2][2][0];
+    ptrdiff_t s0 = yuv_stride[0] / sizeof(pixel);
+    const int uv_offset = 128 << (BIT_DEPTH - 8);
+
+    av_assert2(rgb2yuv_coeffs[1][2][0] == rgb2yuv_coeffs[2][0][0]);
+    w = AV_CEIL_RSHIFT(w, SS_W);
+    h = AV_CEIL_RSHIFT(h, SS_H);
+    for (y = 0; y < h; y++) {
+        for (x = 0; x < w; x++) {
+            int r00 = rgb0[x << SS_W], g00 = rgb1[x << SS_W], b00 = rgb2[x << SS_W];
+#if SS_W == 1
+            int r01 = rgb0[x * 2 + 1], g01 = rgb1[x * 2 + 1], b01 = rgb2[x * 2 + 1];
+#if SS_H == 1
+            int r10 = rgb0[x * 2 + 0 + s], g10 = rgb1[x * 2 + 0 + s], b10 = rgb2[x * 2 + 0 + s];
+            int r11 = rgb0[x * 2 + 1 + s], g11 = rgb1[x * 2 + 1 + s], b11 = rgb2[x * 2 + 1 + s];
+#endif
+#endif
+
+            yuv0[x << SS_W]      = av_clip_pixel(yuv_offset[0] +
+                                                 ((r00 * cry + g00 * cgy +
+                                                   b00 * cby + rnd) >> sh));
+#if SS_W == 1
+            yuv0[x * 2 + 1]      = av_clip_pixel(yuv_offset[0] +
+                                                 ((r01 * cry + g01 * cgy +
+                                                   b01 * cby + rnd) >> sh));
+#if SS_H == 1
+            yuv0[x * 2 + 0 + s0] = av_clip_pixel(yuv_offset[0] +
+                                                 ((r10 * cry + g10 * cgy +
+                                                   b10 * cby + rnd) >> sh));
+            yuv0[x * 2 + 1 + s0] = av_clip_pixel(yuv_offset[0] +
+                                                 ((r11 * cry + g11 * cgy +
+                                                   b11 * cby + rnd) >> sh));
+#endif
+#endif
+
+            yuv1[x]      = av_clip_pixel(uv_offset +
+                                         ((avg(r00, r01, r10, r11) * cru +
+                                           avg(g00, g01, g10, g11) * cgu +
+                                           avg(b00, b01, b10, b11) * cburv + rnd) >> sh));
+            yuv2[x]      = av_clip_pixel(uv_offset +
+                                         ((avg(r00, r01, r10, r11) * cburv +
+                                           avg(g00, g01, g10, g11) * cgv +
+                                           avg(b00, b01, b10, b11) * cbv + rnd) >> sh));
+        }
+
+        yuv0 += s0 * (1 << SS_H);
+        yuv1 += yuv_stride[1] / sizeof(pixel);
+        yuv2 += yuv_stride[2] / sizeof(pixel);
+        rgb0 += s * (1 << SS_H);
+        rgb1 += s * (1 << SS_H);
+        rgb2 += s * (1 << SS_H);
+    }
+}
+
+/* floyd-steinberg dithering - for any mid-top pixel A in a 3x2 block of pixels:
+ *    1 A 2
+ *    3 4 5
+ * the rounding error is distributed over the neighbouring pixels:
+ *    2: 7/16th, 3: 3/16th, 4: 5/16th and 5: 1/16th
+ */
+static void fn(rgb2yuv_fsb)(uint8_t *_yuv[3], const ptrdiff_t yuv_stride[3],
+                            int16_t *rgb[3], ptrdiff_t s,
+                            int w, int h, const int16_t rgb2yuv_coeffs[3][3][8],
+                            const int16_t yuv_offset[8],
+                            int *rnd_scratch[3][2])
+{
+    pixel **yuv = (pixel **) _yuv;
+    pixel *yuv0 = yuv[0], *yuv1 = yuv[1], *yuv2 = yuv[2];
+    const int16_t *rgb0 = rgb[0], *rgb1 = rgb[1], *rgb2 = rgb[2];
+    int y, x;
+    const int sh = 29 - BIT_DEPTH;
+    const int rnd = 1 << (sh - 1);
+    int cry = rgb2yuv_coeffs[0][0][0];
+    int cgy = rgb2yuv_coeffs[0][1][0];
+    int cby = rgb2yuv_coeffs[0][2][0];
+    int cru = rgb2yuv_coeffs[1][0][0];
+    int cgu = rgb2yuv_coeffs[1][1][0];
+    int cburv = rgb2yuv_coeffs[1][2][0];
+    int cgv = rgb2yuv_coeffs[2][1][0];
+    int cbv = rgb2yuv_coeffs[2][2][0];
+    ptrdiff_t s0 = yuv_stride[0] / sizeof(pixel);
+    const int uv_offset = 128 << (BIT_DEPTH - 8);
+    unsigned mask = (1 << sh) - 1;
+
+    for (x = 0; x < w; x++) {
+        rnd_scratch[0][0][x] =
+        rnd_scratch[0][1][x] = rnd;
+    }
+    av_assert2(rgb2yuv_coeffs[1][2][0] == rgb2yuv_coeffs[2][0][0]);
+    w = AV_CEIL_RSHIFT(w, SS_W);
+    h = AV_CEIL_RSHIFT(h, SS_H);
+    for (x = 0; x < w; x++) {
+        rnd_scratch[1][0][x] =
+        rnd_scratch[1][1][x] =
+        rnd_scratch[2][0][x] =
+        rnd_scratch[2][1][x] = rnd;
+    }
+    for (y = 0; y < h; y++) {
+        for (x = 0; x < w; x++) {
+            int r00 = rgb0[x << SS_W], g00 = rgb1[x << SS_W], b00 = rgb2[x << SS_W];
+            int y00;
+#if SS_W == 1
+            int r01 = rgb0[x * 2 + 1], g01 = rgb1[x * 2 + 1], b01 = rgb2[x * 2 + 1];
+            int y01;
+#if SS_H == 1
+            int r10 = rgb0[x * 2 + 0 + s], g10 = rgb1[x * 2 + 0 + s], b10 = rgb2[x * 2 + 0 + s];
+            int r11 = rgb0[x * 2 + 1 + s], g11 = rgb1[x * 2 + 1 + s], b11 = rgb2[x * 2 + 1 + s];
+            int y10, y11;
+#endif
+#endif
+            int u, v, diff;
+
+            y00 = r00 * cry + g00 * cgy + b00 * cby + rnd_scratch[0][y & !SS_H][x << SS_W];
+            diff = (y00 & mask) - rnd;
+            yuv0[x << SS_W]      = av_clip_pixel(yuv_offset[0] + (y00 >> sh));
+            rnd_scratch[0][ (y & !SS_H)][(x << SS_W) + 1] += (diff * 7 + 8) >> 4;
+            rnd_scratch[0][!(y & !SS_H)][(x << SS_W) - 1] += (diff * 3 + 8) >> 4;
+            rnd_scratch[0][!(y & !SS_H)][(x << SS_W) + 0] += (diff * 5 + 8) >> 4;
+            rnd_scratch[0][!(y & !SS_H)][(x << SS_W) + 1] += (diff * 1 + 8) >> 4;
+            rnd_scratch[0][ (y & !SS_H)][(x << SS_W) + 0]  = rnd;
+#if SS_W == 1
+            y01 = r01 * cry + g01 * cgy + b01 * cby + rnd_scratch[0][y & !SS_H][x * 2 + 1];
+            diff = (y01 & mask) - rnd;
+            yuv0[x * 2 + 1]      = av_clip_pixel(yuv_offset[0] + (y01 >> sh));
+            rnd_scratch[0][ (y & !SS_H)][x * 2 + 2] += (diff * 7 + 8) >> 4;
+            rnd_scratch[0][!(y & !SS_H)][x * 2 + 0] += (diff * 3 + 8) >> 4;
+            rnd_scratch[0][!(y & !SS_H)][x * 2 + 1] += (diff * 5 + 8) >> 4;
+            rnd_scratch[0][!(y & !SS_H)][x * 2 + 2] += (diff * 1 + 8) >> 4;
+            rnd_scratch[0][ (y & !SS_H)][x * 2 + 1]  = rnd;
+#if SS_H == 1
+            y10 = r10 * cry + g10 * cgy + b10 * cby + rnd_scratch[0][1][x * 2 + 0];
+            diff = (y10 & mask) - rnd;
+            yuv0[x * 2 + 0 + s0] = av_clip_pixel(yuv_offset[0] + (y10 >> sh));
+            rnd_scratch[0][1][x * 2 + 1] += (diff * 7 + 8) >> 4;
+            rnd_scratch[0][0][x * 2 - 1] += (diff * 3 + 8) >> 4;
+            rnd_scratch[0][0][x * 2 + 0] += (diff * 5 + 8) >> 4;
+            rnd_scratch[0][0][x * 2 + 1] += (diff * 1 + 8) >> 4;
+            rnd_scratch[0][1][x * 2 + 0]  = rnd;
+
+            y11 = r11 * cry + g11 * cgy + b11 * cby + rnd_scratch[0][1][x * 2 + 1];
+            diff = (y11 & mask) - rnd;
+            yuv0[x * 2 + 1 + s0] = av_clip_pixel(yuv_offset[0] + (y11 >> sh));
+            rnd_scratch[0][1][x * 2 + 2] += (diff * 7 + 8) >> 4;
+            rnd_scratch[0][0][x * 2 + 0] += (diff * 3 + 8) >> 4;
+            rnd_scratch[0][0][x * 2 + 1] += (diff * 5 + 8) >> 4;
+            rnd_scratch[0][0][x * 2 + 2] += (diff * 1 + 8) >> 4;
+            rnd_scratch[0][1][x * 2 + 1]  = rnd;
+#endif
+#endif
+
+            u = avg(r00, r01, r10, r11) * cru +
+                avg(g00, g01, g10, g11) * cgu +
+                avg(b00, b01, b10, b11) * cburv + rnd_scratch[1][y & 1][x];
+            diff = (u & mask) - rnd;
+            yuv1[x] = av_clip_pixel(uv_offset + (u >> sh));
+            rnd_scratch[1][ (y & 1)][x + 1] += (diff * 7 + 8) >> 4;
+            rnd_scratch[1][!(y & 1)][x - 1] += (diff * 3 + 8) >> 4;
+            rnd_scratch[1][!(y & 1)][x + 0] += (diff * 5 + 8) >> 4;
+            rnd_scratch[1][!(y & 1)][x + 1] += (diff * 1 + 8) >> 4;
+            rnd_scratch[1][ (y & 1)][x + 0]  = rnd;
+
+            v = avg(r00, r01, r10, r11) * cburv +
+                avg(g00, g01, g10, g11) * cgv +
+                avg(b00, b01, b10, b11) * cbv + rnd_scratch[2][y & 1][x];
+            diff = (v & mask) - rnd;
+            yuv2[x] = av_clip_pixel(uv_offset + (v >> sh));
+            rnd_scratch[2][ (y & 1)][x + 1] += (diff * 7 + 8) >> 4;
+            rnd_scratch[2][!(y & 1)][x - 1] += (diff * 3 + 8) >> 4;
+            rnd_scratch[2][!(y & 1)][x + 0] += (diff * 5 + 8) >> 4;
+            rnd_scratch[2][!(y & 1)][x + 1] += (diff * 1 + 8) >> 4;
+            rnd_scratch[2][ (y & 1)][x + 0]  = rnd;
+        }
+
+        yuv0 += s0 * (1 << SS_H);
+        yuv1 += yuv_stride[1] / sizeof(pixel);
+        yuv2 += yuv_stride[2] / sizeof(pixel);
+        rgb0 += s * (1 << SS_H);
+        rgb1 += s * (1 << SS_H);
+        rgb2 += s * (1 << SS_H);
+    }
+}
+
+#undef IN_BIT_DEPTH
+#undef OUT_BIT_DEPTH
+#define OUT_BIT_DEPTH BIT_DEPTH
+#define IN_BIT_DEPTH 8
+#include "colorspacedsp_yuv2yuv_template.c"
+
+#undef IN_BIT_DEPTH
+#define IN_BIT_DEPTH 10
+#include "colorspacedsp_yuv2yuv_template.c"
+
+#undef IN_BIT_DEPTH
+#define IN_BIT_DEPTH 12
+#include "colorspacedsp_yuv2yuv_template.c"
diff --git a/libavfilter/colorspacedsp_yuv2yuv_template.c b/libavfilter/colorspacedsp_yuv2yuv_template.c
new file mode 100644
index 0000000..3fae38c
--- /dev/null
+++ b/libavfilter/colorspacedsp_yuv2yuv_template.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * 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/avassert.h"
+
+#undef opixel
+#define opixel pixel
+
+#undef ipixel
+#if IN_BIT_DEPTH == 8
+#define ipixel uint8_t
+#else
+#define ipixel uint16_t
+#endif
+
+#undef fn
+#undef fn2
+#undef fn3
+#define fn3(a,b,c,d) a##_##d##p##b##to##c##_c
+#define fn2(a,b,c,d) fn3(a,b,c,d)
+#define fn(a) fn2(a, IN_BIT_DEPTH, OUT_BIT_DEPTH, ss)
+
+static void fn(yuv2yuv)(uint8_t *_dst[3], const ptrdiff_t dst_stride[3],
+                        uint8_t *_src[3], const ptrdiff_t src_stride[3],
+                        int w, int h, const int16_t c[3][3][8],
+                        const int16_t yuv_offset[2][8])
+{
+    opixel **dst = (opixel **) _dst;
+    ipixel **src = (ipixel **) _src;
+    const ipixel *src0 = src[0], *src1 = src[1], *src2 = src[2];
+    opixel *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2];
+    int y, x;
+    const int sh = 14 + IN_BIT_DEPTH - OUT_BIT_DEPTH;
+    const int rnd = 1 << (sh - 1);
+    int y_off_in = yuv_offset[0][0];
+    int y_off_out = yuv_offset[1][0] << sh;
+    const int uv_off_in = 128 << (IN_BIT_DEPTH - 8);
+    const int uv_off_out = rnd + (128 << (OUT_BIT_DEPTH - 8 + sh));
+    int cyy = c[0][0][0], cyu = c[0][1][0], cyv = c[0][2][0];
+    int cuu = c[1][1][0], cuv = c[1][2][0], cvu = c[2][1][0], cvv = c[2][2][0];
+
+    av_assert2(c[1][0][0] == 0);
+    av_assert2(c[2][0][0] == 0);
+    w = AV_CEIL_RSHIFT(w, SS_W);
+    h = AV_CEIL_RSHIFT(h, SS_H);
+    for (y = 0; y < h; y++) {
+        for (x = 0; x < w; x++) {
+            int y00 = src0[x << SS_W] - y_off_in;
+#if SS_W == 1
+            int y01 = src0[2 * x + 1] - y_off_in;
+#if SS_H == 1
+            int y10 = src0[src_stride[0] / sizeof(ipixel) + 2 * x] - y_off_in;
+            int y11 = src0[src_stride[0] / sizeof(ipixel) + 2 * x + 1] - y_off_in;
+#endif
+#endif
+            int u = src1[x] - uv_off_in, v = src2[x] - uv_off_in;
+            int uv_val = cyu * u + cyv * v + rnd + y_off_out;
+
+            dst0[x << SS_W] = av_clip_pixel((cyy * y00 + uv_val) >> sh);
+#if SS_W == 1
+            dst0[x * 2 + 1] = av_clip_pixel((cyy * y01 + uv_val) >> sh);
+#if SS_H == 1
+            dst0[x * 2 + 0 + dst_stride[0] / sizeof(opixel)] =
+                              av_clip_pixel((cyy * y10 + uv_val) >> sh);
+            dst0[x * 2 + 1 + dst_stride[0] / sizeof(opixel)] =
+                              av_clip_pixel((cyy * y11 + uv_val) >> sh);
+#endif
+#endif
+
+            dst1[x] = av_clip_pixel((u * cuu + v * cuv + uv_off_out) >> sh);
+            dst2[x] = av_clip_pixel((u * cvu + v * cvv + uv_off_out) >> sh);
+        }
+
+        dst0 += (dst_stride[0] * (1 << SS_H)) / sizeof(opixel);
+        dst1 += dst_stride[1] / sizeof(opixel);
+        dst2 += dst_stride[2] / sizeof(opixel);
+        src0 += (src_stride[0] * (1 << SS_H)) / sizeof(ipixel);
+        src1 += src_stride[1] / sizeof(ipixel);
+        src2 += src_stride[2] / sizeof(ipixel);
+    }
+}
diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c
index 23a0eb5..e533040 100644
--- a/libavfilter/drawutils.c
+++ b/libavfilter/drawutils.c
@@ -24,6 +24,7 @@
 #include "libavutil/avassert.h"
 #include "libavutil/avutil.h"
 #include "libavutil/colorspace.h"
+#include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
 #include "libavutil/pixdesc.h"
 #include "drawutils.h"
@@ -52,11 +53,21 @@ int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
     case AV_PIX_FMT_BGRA:
     case AV_PIX_FMT_BGR0:
     case AV_PIX_FMT_BGR24: rgba_map[BLUE ] = 0; rgba_map[GREEN] = 1; rgba_map[RED  ] = 2; rgba_map[ALPHA] = 3; break;
-    case AV_PIX_FMT_GBRP9:
-    case AV_PIX_FMT_GBRP10:
-    case AV_PIX_FMT_GBRP12:
-    case AV_PIX_FMT_GBRP14:
+    case AV_PIX_FMT_GBRP9LE:
+    case AV_PIX_FMT_GBRP9BE:
+    case AV_PIX_FMT_GBRP10LE:
+    case AV_PIX_FMT_GBRP10BE:
+    case AV_PIX_FMT_GBRP12LE:
+    case AV_PIX_FMT_GBRP12BE:
+    case AV_PIX_FMT_GBRP14LE:
+    case AV_PIX_FMT_GBRP14BE:
+    case AV_PIX_FMT_GBRP16LE:
+    case AV_PIX_FMT_GBRP16BE:
     case AV_PIX_FMT_GBRAP:
+    case AV_PIX_FMT_GBRAP12LE:
+    case AV_PIX_FMT_GBRAP12BE:
+    case AV_PIX_FMT_GBRAP16LE:
+    case AV_PIX_FMT_GBRAP16BE:
     case AV_PIX_FMT_GBRP:  rgba_map[GREEN] = 0; rgba_map[BLUE ] = 1; rgba_map[RED  ] = 2; rgba_map[ALPHA] = 3; break;
     default:                    /* unsupported */
         return AVERROR(EINVAL);
@@ -175,8 +186,10 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
         return AVERROR(ENOSYS);
     for (i = 0; i < desc->nb_components; i++) {
         c = &desc->comp[i];
-        /* for now, only 8-bits formats */
-        if (c->depth != 8)
+        /* for now, only 8-16 bits formats */
+        if (c->depth < 8 || c->depth > 16)
+            return AVERROR(ENOSYS);
+        if (desc->flags & AV_PIX_FMT_FLAG_BE)
             return AVERROR(ENOSYS);
         if (c->plane >= MAX_PLANES)
             return AVERROR(ENOSYS);
@@ -184,13 +197,14 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
         if (pixelstep[c->plane] != 0 &&
             pixelstep[c->plane] != c->step)
             return AVERROR(ENOSYS);
+        if (pixelstep[c->plane] == 6 &&
+            c->depth == 16)
+            return AVERROR(ENOSYS);
         pixelstep[c->plane] = c->step;
         if (pixelstep[c->plane] >= 8)
             return AVERROR(ENOSYS);
         nb_planes = FFMAX(nb_planes, c->plane + 1);
     }
-    if ((desc->log2_chroma_w || desc->log2_chroma_h) && nb_planes < 3)
-        return AVERROR(ENOSYS); /* exclude NV12 and NV21 */
     memset(draw, 0, sizeof(*draw));
     draw->desc      = desc;
     draw->format    = format;
@@ -198,7 +212,7 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
     memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep));
     draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w;
     draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h;
-    for (i = 0; i < ((desc->nb_components - 1) | 1); i++)
+    for (i = 0; i < (desc->nb_components - !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)); i++)
         draw->comp_mask[desc->comp[i].plane] |=
             1 << desc->comp[i].offset;
     return 0;
@@ -214,21 +228,42 @@ void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4
     if ((draw->desc->flags & AV_PIX_FMT_FLAG_RGB) &&
         ff_fill_rgba_map(rgba_map, draw->format) >= 0) {
         if (draw->nb_planes == 1) {
-            for (i = 0; i < 4; i++)
+            for (i = 0; i < 4; i++) {
                 color->comp[0].u8[rgba_map[i]] = rgba[i];
+                if (draw->desc->comp[rgba_map[i]].depth > 8) {
+                    color->comp[0].u16[rgba_map[i]] = color->comp[0].u8[rgba_map[i]] << 8;
+                }
+            }
         } else {
-            for (i = 0; i < 4; i++)
+            for (i = 0; i < 4; i++) {
                 color->comp[rgba_map[i]].u8[0] = rgba[i];
+                if (draw->desc->comp[rgba_map[i]].depth > 8)
+                    color->comp[rgba_map[i]].u16[0] = color->comp[rgba_map[i]].u8[0] << (draw->desc->comp[rgba_map[i]].depth - 8);
+            }
         }
-    } else if (draw->nb_planes == 3 || draw->nb_planes == 4) {
+    } else if (draw->nb_planes >= 2) {
         /* assume YUV */
-        color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
-        color->comp[1].u8[0] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
-        color->comp[2].u8[0] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
+        const AVPixFmtDescriptor *desc = draw->desc;
+        color->comp[desc->comp[0].plane].u8[desc->comp[0].offset] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
+        color->comp[desc->comp[1].plane].u8[desc->comp[1].offset] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
+        color->comp[desc->comp[2].plane].u8[desc->comp[2].offset] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
         color->comp[3].u8[0] = rgba[3];
+#define EXPAND(compn) \
+        if (desc->comp[compn].depth > 8) \
+            color->comp[desc->comp[compn].plane].u16[desc->comp[compn].offset] = \
+            color->comp[desc->comp[compn].plane].u8[desc->comp[compn].offset] << (draw->desc->comp[compn].depth - 8)
+        EXPAND(3);
+        EXPAND(2);
+        EXPAND(1);
+        EXPAND(0);
     } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A) {
         color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
         color->comp[1].u8[0] = rgba[3];
+    } else if (draw->format == AV_PIX_FMT_GRAY16LE || draw->format == AV_PIX_FMT_YA16LE) {
+        color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
+        color->comp[0].u16[0] = color->comp[0].u8[0] << 8;
+        color->comp[1].u8[0] = rgba[3];
+        color->comp[1].u16[0] = color->comp[1].u8[0] << 8;
     } else {
         av_log(NULL, AV_LOG_WARNING,
                "Color conversion not implemented for %s\n", draw->desc->name);
@@ -272,6 +307,7 @@ void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color,
 {
     int plane, x, y, wp, hp;
     uint8_t *p0, *p;
+    FFDrawColor color_tmp = *color;
 
     for (plane = 0; plane < draw->nb_planes; plane++) {
         p0 = pointer_at(draw, dst, dst_linesize, plane, dst_x, dst_y);
@@ -280,9 +316,15 @@ void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color,
         if (!hp)
             return;
         p = p0;
+
+        if (HAVE_BIGENDIAN && draw->desc->comp[0].depth > 8) {
+            for (x = 0; 2*x < draw->pixelstep[plane]; x++)
+                color_tmp.comp[plane].u16[x] = av_bswap16(color_tmp.comp[plane].u16[x]);
+        }
+
         /* copy first line from color */
         for (x = 0; x < wp; x++) {
-            memcpy(p, color->comp[plane].u8, draw->pixelstep[plane]);
+            memcpy(p, color_tmp.comp[plane].u8, draw->pixelstep[plane]);
             p += draw->pixelstep[plane];
         }
         wp *= draw->pixelstep[plane];
@@ -361,6 +403,31 @@ static void blend_line(uint8_t *dst, unsigned src, unsigned alpha,
     }
 }
 
+static void blend_line16(uint8_t *dst, unsigned src, unsigned alpha,
+                         int dx, int w, unsigned hsub, int left, int right)
+{
+    unsigned asrc = alpha * src;
+    unsigned tau = 0x10001 - alpha;
+    int x;
+
+    if (left) {
+        unsigned suba = (left * alpha) >> hsub;
+        uint16_t value = AV_RL16(dst);
+        AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
+        dst += dx;
+    }
+    for (x = 0; x < w; x++) {
+        uint16_t value = AV_RL16(dst);
+        AV_WL16(dst, (value * tau + asrc) >> 16);
+        dst += dx;
+    }
+    if (right) {
+        unsigned suba = (right * alpha) >> hsub;
+        uint16_t value = AV_RL16(dst);
+        AV_WL16(dst, (value * (0x10001 - suba) + src * suba) >> 16);
+    }
+}
+
 void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color,
                         uint8_t *dst[], int dst_linesize[],
                         int dst_w, int dst_h,
@@ -375,9 +442,14 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color,
     clip_interval(dst_h, &y0, &h, NULL);
     if (w <= 0 || h <= 0 || !color->rgba[3])
         return;
-    /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
-    alpha = 0x10203 * color->rgba[3] + 0x2;
-    nb_planes = (draw->nb_planes - 1) | 1; /* eliminate alpha */
+    if (draw->desc->comp[0].depth <= 8) {
+        /* 0x10203 * alpha + 2 is in the [ 2 ; 0x1010101 - 2 ] range */
+        alpha = 0x10203 * color->rgba[3] + 0x2;
+    } else {
+        /* 0x101 * alpha is in the [ 2 ; 0x1001] range */
+        alpha = 0x101 * color->rgba[3] + 0x2;
+    }
+    nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA);
     for (plane = 0; plane < nb_planes; plane++) {
         nb_comp = draw->pixelstep[plane];
         p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
@@ -388,27 +460,75 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color,
         subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
         subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
         for (comp = 0; comp < nb_comp; comp++) {
+            const int depth = draw->desc->comp[comp].depth;
+
             if (!component_used(draw, plane, comp))
                 continue;
             p = p0 + comp;
             if (top) {
-                blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
-                           draw->pixelstep[plane], w_sub,
-                           draw->hsub[plane], left, right);
+                if (depth <= 8) {
+                    blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
+                               draw->pixelstep[plane], w_sub,
+                               draw->hsub[plane], left, right);
+                } else {
+                    blend_line16(p, color->comp[plane].u16[comp], alpha >> 1,
+                                 draw->pixelstep[plane], w_sub,
+                                 draw->hsub[plane], left, right);
+                }
                 p += dst_linesize[plane];
             }
-            for (y = 0; y < h_sub; y++) {
-                blend_line(p, color->comp[plane].u8[comp], alpha,
-                           draw->pixelstep[plane], w_sub,
-                           draw->hsub[plane], left, right);
-                p += dst_linesize[plane];
+            if (depth <= 8) {
+                for (y = 0; y < h_sub; y++) {
+                    blend_line(p, color->comp[plane].u8[comp], alpha,
+                               draw->pixelstep[plane], w_sub,
+                               draw->hsub[plane], left, right);
+                    p += dst_linesize[plane];
+                }
+            } else {
+                for (y = 0; y < h_sub; y++) {
+                    blend_line16(p, color->comp[plane].u16[comp], alpha,
+                                 draw->pixelstep[plane], w_sub,
+                                 draw->hsub[plane], left, right);
+                    p += dst_linesize[plane];
+                }
             }
-            if (bottom)
-                blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
-                           draw->pixelstep[plane], w_sub,
-                           draw->hsub[plane], left, right);
+            if (bottom) {
+                if (depth <= 8) {
+                    blend_line(p, color->comp[plane].u8[comp], alpha >> 1,
+                               draw->pixelstep[plane], w_sub,
+                               draw->hsub[plane], left, right);
+                } else {
+                    blend_line16(p, color->comp[plane].u16[comp], alpha >> 1,
+                                 draw->pixelstep[plane], w_sub,
+                                 draw->hsub[plane], left, right);
+                }
+            }
+        }
+    }
+}
+
+static void blend_pixel16(uint8_t *dst, unsigned src, unsigned alpha,
+                          const uint8_t *mask, int mask_linesize, int l2depth,
+                          unsigned w, unsigned h, unsigned shift, unsigned xm0)
+{
+    unsigned xm, x, y, t = 0;
+    unsigned xmshf = 3 - l2depth;
+    unsigned xmmod = 7 >> l2depth;
+    unsigned mbits = (1 << (1 << l2depth)) - 1;
+    unsigned mmult = 255 / mbits;
+    uint16_t value = AV_RL16(dst);
+
+    for (y = 0; y < h; y++) {
+        xm = xm0;
+        for (x = 0; x < w; x++) {
+            t += ((mask[xm >> xmshf] >> ((~xm & xmmod) << l2depth)) & mbits)
+                 * mmult;
+            xm++;
         }
+        mask += mask_linesize;
     }
+    alpha = (t >> shift) * alpha;
+    AV_WL16(dst, ((0x10001 - alpha) * value + alpha * src) >> 16);
 }
 
 static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,
@@ -434,6 +554,31 @@ static void blend_pixel(uint8_t *dst, unsigned src, unsigned alpha,
     *dst = ((0x1010101 - alpha) * *dst + alpha * src) >> 24;
 }
 
+static void blend_line_hv16(uint8_t *dst, int dst_delta,
+                            unsigned src, unsigned alpha,
+                            const uint8_t *mask, int mask_linesize, int l2depth, int w,
+                            unsigned hsub, unsigned vsub,
+                            int xm, int left, int right, int hband)
+{
+    int x;
+
+    if (left) {
+        blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
+                      left, hband, hsub + vsub, xm);
+        dst += dst_delta;
+        xm += left;
+    }
+    for (x = 0; x < w; x++) {
+        blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
+                      1 << hsub, hband, hsub + vsub, xm);
+        dst += dst_delta;
+        xm += 1 << hsub;
+    }
+    if (right)
+        blend_pixel16(dst, src, alpha, mask, mask_linesize, l2depth,
+                      right, hband, hsub + vsub, xm);
+}
+
 static void blend_line_hv(uint8_t *dst, int dst_delta,
                           unsigned src, unsigned alpha,
                           const uint8_t *mask, int mask_linesize, int l2depth, int w,
@@ -474,10 +619,14 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color,
     mask += ym0 * mask_linesize;
     if (mask_w <= 0 || mask_h <= 0 || !color->rgba[3])
         return;
-    /* alpha is in the [ 0 ; 0x10203 ] range,
-       alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
-    alpha = (0x10307 * color->rgba[3] + 0x3) >> 8;
-    nb_planes = (draw->nb_planes - 1) | 1; /* eliminate alpha */
+    if (draw->desc->comp[0].depth <= 8) {
+        /* alpha is in the [ 0 ; 0x10203 ] range,
+           alpha * mask is in the [ 0 ; 0x1010101 - 4 ] range */
+        alpha = (0x10307 * color->rgba[3] + 0x3) >> 8;
+    } else {
+        alpha = (0x101 * color->rgba[3] + 0x2) >> 8;
+    }
+    nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA);
     for (plane = 0; plane < nb_planes; plane++) {
         nb_comp = draw->pixelstep[plane];
         p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0);
@@ -488,34 +637,65 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color,
         subsampling_bounds(draw->hsub[plane], &x_sub, &w_sub, &left, &right);
         subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom);
         for (comp = 0; comp < nb_comp; comp++) {
+            const int depth = draw->desc->comp[comp].depth;
+
             if (!component_used(draw, plane, comp))
                 continue;
             p = p0 + comp;
             m = mask;
             if (top) {
-                blend_line_hv(p, draw->pixelstep[plane],
-                              color->comp[plane].u8[comp], alpha,
-                              m, mask_linesize, l2depth, w_sub,
-                              draw->hsub[plane], draw->vsub[plane],
-                              xm0, left, right, top);
+                if (depth <= 8) {
+                    blend_line_hv(p, draw->pixelstep[plane],
+                                  color->comp[plane].u8[comp], alpha,
+                                  m, mask_linesize, l2depth, w_sub,
+                                  draw->hsub[plane], draw->vsub[plane],
+                                  xm0, left, right, top);
+                } else {
+                    blend_line_hv16(p, draw->pixelstep[plane],
+                                    color->comp[plane].u16[comp], alpha,
+                                    m, mask_linesize, l2depth, w_sub,
+                                    draw->hsub[plane], draw->vsub[plane],
+                                    xm0, left, right, top);
+                }
                 p += dst_linesize[plane];
                 m += top * mask_linesize;
             }
-            for (y = 0; y < h_sub; y++) {
-                blend_line_hv(p, draw->pixelstep[plane],
-                              color->comp[plane].u8[comp], alpha,
-                              m, mask_linesize, l2depth, w_sub,
-                              draw->hsub[plane], draw->vsub[plane],
-                              xm0, left, right, 1 << draw->vsub[plane]);
-                p += dst_linesize[plane];
-                m += mask_linesize << draw->vsub[plane];
+            if (depth <= 8) {
+                for (y = 0; y < h_sub; y++) {
+                    blend_line_hv(p, draw->pixelstep[plane],
+                                  color->comp[plane].u8[comp], alpha,
+                                  m, mask_linesize, l2depth, w_sub,
+                                  draw->hsub[plane], draw->vsub[plane],
+                                  xm0, left, right, 1 << draw->vsub[plane]);
+                    p += dst_linesize[plane];
+                    m += mask_linesize << draw->vsub[plane];
+                }
+            } else {
+                for (y = 0; y < h_sub; y++) {
+                    blend_line_hv16(p, draw->pixelstep[plane],
+                                    color->comp[plane].u16[comp], alpha,
+                                    m, mask_linesize, l2depth, w_sub,
+                                    draw->hsub[plane], draw->vsub[plane],
+                                    xm0, left, right, 1 << draw->vsub[plane]);
+                    p += dst_linesize[plane];
+                    m += mask_linesize << draw->vsub[plane];
+                }
+            }
+            if (bottom) {
+                if (depth <= 8) {
+                    blend_line_hv(p, draw->pixelstep[plane],
+                                  color->comp[plane].u8[comp], alpha,
+                                  m, mask_linesize, l2depth, w_sub,
+                                  draw->hsub[plane], draw->vsub[plane],
+                                  xm0, left, right, bottom);
+                } else {
+                    blend_line_hv16(p, draw->pixelstep[plane],
+                                    color->comp[plane].u16[comp], alpha,
+                                    m, mask_linesize, l2depth, w_sub,
+                                    draw->hsub[plane], draw->vsub[plane],
+                                    xm0, left, right, bottom);
+                }
             }
-            if (bottom)
-                blend_line_hv(p, draw->pixelstep[plane],
-                              color->comp[plane].u8[comp], alpha,
-                              m, mask_linesize, l2depth, w_sub,
-                              draw->hsub[plane], draw->vsub[plane],
-                              xm0, left, right, bottom);
         }
     }
 }
@@ -545,43 +725,3 @@ AVFilterFormats *ff_draw_supported_pixel_formats(unsigned flags)
             return NULL;
     return fmts;
 }
-
-#ifdef TEST
-
-#undef printf
-
-int main(void)
-{
-    enum AVPixelFormat f;
-    const AVPixFmtDescriptor *desc;
-    FFDrawContext draw;
-    FFDrawColor color;
-    int r, i;
-
-    for (f = 0; av_pix_fmt_desc_get(f); f++) {
-        desc = av_pix_fmt_desc_get(f);
-        if (!desc->name)
-            continue;
-        printf("Testing %s...%*s", desc->name,
-               (int)(16 - strlen(desc->name)), "");
-        r = ff_draw_init(&draw, f, 0);
-        if (r < 0) {
-            char buf[128];
-            av_strerror(r, buf, sizeof(buf));
-            printf("no: %s\n", buf);
-            continue;
-        }
-        ff_draw_color(&draw, &color, (uint8_t[]) { 1, 0, 0, 1 });
-        for (i = 0; i < sizeof(color); i++)
-            if (((uint8_t *)&color)[i] != 128)
-                break;
-        if (i == sizeof(color)) {
-            printf("fallback color\n");
-            continue;
-        }
-        printf("ok\n");
-    }
-    return 0;
-}
-
-#endif
diff --git a/libavfilter/drawutils.h b/libavfilter/drawutils.h
index e247dd6..1fb3e4f 100644
--- a/libavfilter/drawutils.h
+++ b/libavfilter/drawutils.h
@@ -60,9 +60,9 @@ typedef struct FFDrawContext {
 typedef struct FFDrawColor {
     uint8_t rgba[4];
     union {
-        uint32_t u32;
-        uint16_t u16;
-        uint8_t  u8[4];
+        uint32_t u32[4];
+        uint16_t u16[8];
+        uint8_t  u8[16];
     } comp[MAX_PLANES];
 } FFDrawColor;
 
diff --git a/libavfilter/dualinput.c b/libavfilter/dualinput.c
index 1a078a2..4475097 100644
--- a/libavfilter/dualinput.c
+++ b/libavfilter/dualinput.c
@@ -66,6 +66,9 @@ int ff_dualinput_init(AVFilterContext *ctx, FFDualInputContext *s)
         in[1].after = EXT_NULL;
         in[1].sync  = 0;
     }
+    if (s->skip_initial_unpaired) {
+        in[1].before = EXT_STOP;
+    }
 
     return ff_framesync_configure(&s->fs);
 }
diff --git a/libavfilter/dualinput.h b/libavfilter/dualinput.h
index 5ff23e6..707b10c 100644
--- a/libavfilter/dualinput.h
+++ b/libavfilter/dualinput.h
@@ -35,6 +35,7 @@ typedef struct {
     AVFrame *(*process)(AVFilterContext *ctx, AVFrame *main, const AVFrame *second);
     int shortest;               ///< terminate stream when the second input terminates
     int repeatlast;             ///< repeat last second frame
+    int skip_initial_unpaired;  ///< Skip initial frames that do not have a 2nd input
 } FFDualInputContext;
 
 int ff_dualinput_init(AVFilterContext *ctx, FFDualInputContext *s);
diff --git a/libavfilter/f_bench.c b/libavfilter/f_bench.c
new file mode 100644
index 0000000..b7b1792
--- /dev/null
+++ b/libavfilter/f_bench.c
@@ -0,0 +1,151 @@
+/*
+ * 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/time.h"
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+
+enum BenchAction {
+    ACTION_START,
+    ACTION_STOP,
+    NB_ACTION
+};
+
+typedef struct {
+    const AVClass *class;
+    int action;
+    int64_t max, min;
+    int64_t sum;
+    int n;
+} BenchContext;
+
+#define OFFSET(x) offsetof(BenchContext, x)
+#define DEFINE_OPTIONS(filt_name, FLAGS)                                                                                \
+static const AVOption filt_name##_options[] = {                                                                         \
+    { "action", "set action", OFFSET(action), AV_OPT_TYPE_INT, {.i64=ACTION_START}, 0, NB_ACTION-1, FLAGS, "action" },  \
+        { "start", "start timer",  0, AV_OPT_TYPE_CONST, {.i64=ACTION_START}, INT_MIN, INT_MAX, FLAGS, "action" },      \
+        { "stop",  "stop timer",   0, AV_OPT_TYPE_CONST, {.i64=ACTION_STOP},  INT_MIN, INT_MAX, FLAGS, "action" },      \
+    { NULL }                                                                                                            \
+}
+
+#define START_TIME_KEY "lavfi.bench.start_time"
+#define T2F(v) ((v) / 1000000.)
+
+static av_cold int init(AVFilterContext *ctx)
+{
+    BenchContext *s = ctx->priv;
+    s->min = INT64_MAX;
+    s->max = INT64_MIN;
+    return 0;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx = inlink->dst;
+    BenchContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    const int64_t t = av_gettime();
+
+    if (t < 0)
+        return ff_filter_frame(outlink, in);
+
+    if (s->action == ACTION_START) {
+        av_dict_set_int(&in->metadata, START_TIME_KEY, t, 0);
+    } else if (s->action == ACTION_STOP) {
+        AVDictionaryEntry *e = av_dict_get(in->metadata, START_TIME_KEY, NULL, 0);
+        if (e) {
+            const int64_t start = strtoll(e->value, NULL, 0);
+            const int64_t diff = t - start;
+            s->sum += diff;
+            s->n++;
+            s->min = FFMIN(s->min, diff);
+            s->max = FFMAX(s->max, diff);
+            av_log(s, AV_LOG_INFO, "t:%f avg:%f max:%f min:%f\n",
+                   T2F(diff), T2F(s->sum / s->n), T2F(s->max), T2F(s->min));
+        }
+        av_dict_set(&in->metadata, START_TIME_KEY, NULL, 0);
+    }
+
+    return ff_filter_frame(outlink, in);
+}
+
+#if CONFIG_BENCH_FILTER
+DEFINE_OPTIONS(bench, AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM);
+AVFILTER_DEFINE_CLASS(bench);
+
+static const AVFilterPad bench_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad bench_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_bench = {
+    .name          = "bench",
+    .description   = NULL_IF_CONFIG_SMALL("Benchmark part of a filtergraph."),
+    .priv_size     = sizeof(BenchContext),
+    .init          = init,
+    .inputs        = bench_inputs,
+    .outputs       = bench_outputs,
+    .priv_class    = &bench_class,
+};
+#endif /* CONFIG_BENCH_FILTER */
+
+#if CONFIG_ABENCH_FILTER
+DEFINE_OPTIONS(abench, AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM);
+AVFILTER_DEFINE_CLASS(abench);
+
+static const AVFilterPad abench_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_AUDIO,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad abench_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_AUDIO,
+    },
+    { NULL }
+};
+
+AVFilter ff_af_abench = {
+    .name          = "abench",
+    .description   = NULL_IF_CONFIG_SMALL("Benchmark part of a filtergraph."),
+    .priv_size     = sizeof(BenchContext),
+    .init          = init,
+    .inputs        = abench_inputs,
+    .outputs       = abench_outputs,
+    .priv_class    = &abench_class,
+};
+#endif /* CONFIG_ABENCH_FILTER */
diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c
index c4b30b4..59eaedd 100644
--- a/libavfilter/f_ebur128.c
+++ b/libavfilter/f_ebur128.c
@@ -33,6 +33,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/dict.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/xga_font_data.h"
 #include "libavutil/opt.h"
 #include "libavutil/timestamp.h"
diff --git a/libavfilter/f_loop.c b/libavfilter/f_loop.c
new file mode 100644
index 0000000..00e0215
--- /dev/null
+++ b/libavfilter/f_loop.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * 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/audio_fifo.h"
+#include "libavutil/avassert.h"
+#include "libavutil/fifo.h"
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "avfilter.h"
+#include "audio.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+typedef struct LoopContext {
+    const AVClass *class;
+
+    AVAudioFifo *fifo;
+    AVAudioFifo *left;
+    AVFrame **frames;
+    int nb_frames;
+    int current_frame;
+    int64_t start_pts;
+    int64_t duration;
+    int64_t current_sample;
+    int64_t nb_samples;
+    int64_t ignored_samples;
+
+    int loop;
+    int64_t size;
+    int64_t start;
+    int64_t pts;
+} LoopContext;
+
+#define AFLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+#define VFLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+#define OFFSET(x) offsetof(LoopContext, x)
+
+#if CONFIG_ALOOP_FILTER
+
+static int aconfig_input(AVFilterLink *inlink)
+{
+    AVFilterContext *ctx = inlink->dst;
+    LoopContext *s  = ctx->priv;
+
+    s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, 8192);
+    s->left = av_audio_fifo_alloc(inlink->format, inlink->channels, 8192);
+    if (!s->fifo || !s->left)
+        return AVERROR(ENOMEM);
+
+    return 0;
+}
+
+static av_cold void auninit(AVFilterContext *ctx)
+{
+    LoopContext *s = ctx->priv;
+
+    av_audio_fifo_free(s->fifo);
+    av_audio_fifo_free(s->left);
+}
+
+static int push_samples(AVFilterContext *ctx, int nb_samples)
+{
+    AVFilterLink *outlink = ctx->outputs[0];
+    LoopContext *s = ctx->priv;
+    AVFrame *out;
+    int ret, i = 0;
+
+    while (s->loop != 0 && i < nb_samples) {
+        out = ff_get_audio_buffer(outlink, FFMIN(nb_samples, s->nb_samples - s->current_sample));
+        if (!out)
+            return AVERROR(ENOMEM);
+        ret = av_audio_fifo_peek_at(s->fifo, (void **)out->extended_data, out->nb_samples, s->current_sample);
+        if (ret < 0) {
+            av_frame_free(&out);
+            return ret;
+        }
+        out->pts = s->pts;
+        out->nb_samples = ret;
+        s->pts += out->nb_samples;
+        i += out->nb_samples;
+        s->current_sample += out->nb_samples;
+
+        ret = ff_filter_frame(outlink, out);
+        if (ret < 0)
+            return ret;
+
+        if (s->current_sample >= s->nb_samples) {
+            s->current_sample = 0;
+
+            if (s->loop > 0)
+                s->loop--;
+        }
+    }
+
+    return ret;
+}
+
+static int afilter_frame(AVFilterLink *inlink, AVFrame *frame)
+{
+    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    LoopContext *s = ctx->priv;
+    int ret = 0;
+
+    if (s->ignored_samples + frame->nb_samples > s->start && s->size > 0 && s->loop != 0) {
+        if (s->nb_samples < s->size) {
+            int written = FFMIN(frame->nb_samples, s->size - s->nb_samples);
+            int drain = 0;
+
+            ret = av_audio_fifo_write(s->fifo, (void **)frame->extended_data, written);
+            if (ret < 0)
+                return ret;
+            if (!s->nb_samples) {
+                drain = FFMAX(0, s->start - s->ignored_samples);
+                s->pts = frame->pts;
+                av_audio_fifo_drain(s->fifo, drain);
+                s->pts += s->start - s->ignored_samples;
+            }
+            s->nb_samples += ret - drain;
+            drain = frame->nb_samples - written;
+            if (s->nb_samples == s->size && drain > 0) {
+                int ret2;
+
+                ret2 = av_audio_fifo_write(s->left, (void **)frame->extended_data, frame->nb_samples);
+                if (ret2 < 0)
+                   return ret2;
+                av_audio_fifo_drain(s->left, drain);
+            }
+            frame->nb_samples = ret;
+            s->pts += ret;
+            ret = ff_filter_frame(outlink, frame);
+        } else {
+            int nb_samples = frame->nb_samples;
+
+            av_frame_free(&frame);
+            ret = push_samples(ctx, nb_samples);
+        }
+    } else {
+        s->ignored_samples += frame->nb_samples;
+        frame->pts = s->pts;
+        s->pts += frame->nb_samples;
+        ret = ff_filter_frame(outlink, frame);
+    }
+
+    return ret;
+}
+
+static int arequest_frame(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    LoopContext *s = ctx->priv;
+    int ret = 0;
+
+    if ((!s->size) ||
+        (s->nb_samples < s->size) ||
+        (s->nb_samples >= s->size && s->loop == 0)) {
+        int nb_samples = av_audio_fifo_size(s->left);
+
+        if (s->loop == 0 && nb_samples > 0) {
+            AVFrame *out;
+
+            out = ff_get_audio_buffer(outlink, nb_samples);
+            if (!out)
+                return AVERROR(ENOMEM);
+            av_audio_fifo_read(s->left, (void **)out->extended_data, nb_samples);
+            out->pts = s->pts;
+            s->pts += nb_samples;
+            ret = ff_filter_frame(outlink, out);
+            if (ret < 0)
+                return ret;
+        }
+        ret = ff_request_frame(ctx->inputs[0]);
+    } else {
+        ret = push_samples(ctx, 1024);
+    }
+
+    if (ret == AVERROR_EOF && s->nb_samples > 0 && s->loop != 0) {
+        ret = push_samples(ctx, outlink->sample_rate);
+    }
+
+    return ret;
+}
+
+static const AVOption aloop_options[] = {
+    { "loop",  "number of loops",               OFFSET(loop),  AV_OPT_TYPE_INT,   {.i64 = 0 }, -1, INT_MAX,   AFLAGS },
+    { "size",  "max number of samples to loop", OFFSET(size),  AV_OPT_TYPE_INT64, {.i64 = 0 },  0, INT32_MAX, AFLAGS },
+    { "start", "set the loop start sample",     OFFSET(start), AV_OPT_TYPE_INT64, {.i64 = 0 },  0, INT64_MAX, AFLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(aloop);
+
+static const AVFilterPad ainputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_AUDIO,
+        .filter_frame = afilter_frame,
+        .config_props = aconfig_input,
+    },
+    { NULL }
+};
+
+static const AVFilterPad aoutputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_AUDIO,
+        .request_frame = arequest_frame,
+    },
+    { NULL }
+};
+
+AVFilter ff_af_aloop = {
+    .name          = "aloop",
+    .description   = NULL_IF_CONFIG_SMALL("Loop audio samples."),
+    .priv_size     = sizeof(LoopContext),
+    .priv_class    = &aloop_class,
+    .uninit        = auninit,
+    .query_formats = ff_query_formats_all,
+    .inputs        = ainputs,
+    .outputs       = aoutputs,
+};
+#endif /* CONFIG_ALOOP_FILTER */
+
+#if CONFIG_LOOP_FILTER
+
+static av_cold int init(AVFilterContext *ctx)
+{
+    LoopContext *s = ctx->priv;
+
+    s->frames = av_calloc(s->size, sizeof(*s->frames));
+    if (!s->frames)
+        return AVERROR(ENOMEM);
+
+    return 0;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    LoopContext *s = ctx->priv;
+    int i;
+
+    for (i = 0; i < s->nb_frames; i++)
+        av_frame_free(&s->frames[i]);
+
+    av_freep(&s->frames);
+    s->nb_frames = 0;
+}
+
+static int push_frame(AVFilterContext *ctx)
+{
+    AVFilterLink *outlink = ctx->outputs[0];
+    LoopContext *s = ctx->priv;
+    int64_t pts;
+    int ret;
+
+    AVFrame *out = av_frame_clone(s->frames[s->current_frame]);
+
+    if (!out)
+        return AVERROR(ENOMEM);
+    out->pts += s->duration - s->start_pts;
+    pts = out->pts + av_frame_get_pkt_duration(out);
+    ret = ff_filter_frame(outlink, out);
+    s->current_frame++;
+
+    if (s->current_frame >= s->nb_frames) {
+        s->duration = pts;
+        s->current_frame = 0;
+
+        if (s->loop > 0)
+            s->loop--;
+    }
+
+    return ret;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
+{
+    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    LoopContext *s = ctx->priv;
+    int ret = 0;
+
+    if (inlink->frame_count >= s->start && s->size > 0 && s->loop != 0) {
+        if (s->nb_frames < s->size) {
+            if (!s->nb_frames)
+                s->start_pts = frame->pts;
+            s->frames[s->nb_frames] = av_frame_clone(frame);
+            if (!s->frames[s->nb_frames]) {
+                av_frame_free(&frame);
+                return AVERROR(ENOMEM);
+            }
+            s->nb_frames++;
+            s->duration = frame->pts + av_frame_get_pkt_duration(frame);
+            ret = ff_filter_frame(outlink, frame);
+        } else {
+            av_frame_free(&frame);
+            ret = push_frame(ctx);
+        }
+    } else {
+        frame->pts += s->duration;
+        ret = ff_filter_frame(outlink, frame);
+    }
+
+    return ret;
+}
+
+static int request_frame(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    LoopContext *s = ctx->priv;
+    int ret = 0;
+
+    if ((!s->size) ||
+        (s->nb_frames < s->size) ||
+        (s->nb_frames >= s->size && s->loop == 0)) {
+        ret = ff_request_frame(ctx->inputs[0]);
+    } else {
+        ret = push_frame(ctx);
+    }
+
+    if (ret == AVERROR_EOF && s->nb_frames > 0 && s->loop != 0) {
+        ret = push_frame(ctx);
+    }
+
+    return ret;
+}
+
+static const AVOption loop_options[] = {
+    { "loop",  "number of loops",              OFFSET(loop),  AV_OPT_TYPE_INT,   {.i64 = 0 }, -1, INT_MAX,   VFLAGS },
+    { "size",  "max number of frames to loop", OFFSET(size),  AV_OPT_TYPE_INT64, {.i64 = 0 },  0, INT16_MAX, VFLAGS },
+    { "start", "set the loop start frame",     OFFSET(start), AV_OPT_TYPE_INT64, {.i64 = 0 },  0, INT64_MAX, VFLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(loop);
+
+static const AVFilterPad inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad outputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_VIDEO,
+        .request_frame = request_frame,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_loop = {
+    .name        = "loop",
+    .description = NULL_IF_CONFIG_SMALL("Loop video frames."),
+    .priv_size   = sizeof(LoopContext),
+    .priv_class  = &loop_class,
+    .init        = init,
+    .uninit      = uninit,
+    .inputs      = inputs,
+    .outputs     = outputs,
+};
+#endif /* CONFIG_LOOP_FILTER */
diff --git a/libavfilter/f_metadata.c b/libavfilter/f_metadata.c
index fa6b9d3..ab07ccf 100644
--- a/libavfilter/f_metadata.c
+++ b/libavfilter/f_metadata.c
@@ -30,6 +30,7 @@
 #include "libavutil/eval.h"
 #include "libavutil/internal.h"
 #include "libavutil/opt.h"
+#include "libavutil/timestamp.h"
 #include "avfilter.h"
 #include "audio.h"
 #include "formats.h"
@@ -305,13 +306,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
         break;
     case METADATA_PRINT:
         if (!s->key && e) {
-            s->print(ctx, "frame %"PRId64" pts %"PRId64"\n", inlink->frame_count, frame->pts);
+            s->print(ctx, "frame:%-4"PRId64" pts:%-7s pts_time:%-7s\n",
+                     inlink->frame_count, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base));
             s->print(ctx, "%s=%s\n", e->key, e->value);
             while ((e = av_dict_get(metadata, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL) {
                 s->print(ctx, "%s=%s\n", e->key, e->value);
             }
         } else if (e && e->value && (!s->value || (e->value && s->compare(s, e->value, s->value)))) {
-            s->print(ctx, "frame %"PRId64" pts %"PRId64"\n", inlink->frame_count, frame->pts);
+            s->print(ctx, "frame:%-4"PRId64" pts:%-7s pts_time:%-7s\n",
+                     inlink->frame_count, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base));
             s->print(ctx, "%s=%s\n", s->key, e->value);
         }
         return ff_filter_frame(outlink, frame);
diff --git a/libavfilter/f_streamselect.c b/libavfilter/f_streamselect.c
index db46c99..03cedba 100644
--- a/libavfilter/f_streamselect.c
+++ b/libavfilter/f_streamselect.c
@@ -267,7 +267,7 @@ static av_cold int init(AVFilterContext *ctx)
     if (!strcmp(ctx->filter->name, "astreamselect"))
         s->is_audio = 1;
 
-    for (;;) {
+    for (; map;) {
         char *p;
 
         strtol(map, &p, 0);
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index f12dcf4..20f45e3 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -683,52 +683,3 @@ int ff_parse_channel_layout(int64_t *ret, int *nret, const char *arg,
         *nret = av_get_channel_layout_nb_channels(chlayout);
     return 0;
 }
-
-#ifdef TEST
-
-#undef printf
-
-int main(void)
-{
-    const int64_t *cl;
-    char buf[512];
-    int i;
-    const char *teststrings[] ={
-        "blah",
-        "1",
-        "2",
-        "-1",
-        "60",
-        "65",
-        "1c",
-        "2c",
-        "-1c",
-        "60c",
-        "65c",
-        "5.1",
-        "stereo",
-        "1+1+1+1",
-        "1c+1c+1c+1c",
-        "2c+1c",
-        "0x3",
-    };
-
-    for (cl = avfilter_all_channel_layouts; *cl != -1; cl++) {
-        av_get_channel_layout_string(buf, sizeof(buf), -1, *cl);
-        printf("%s\n", buf);
-    }
-
-    for ( i = 0; i<FF_ARRAY_ELEMS(teststrings); i++) {
-        int64_t layout = -1;
-        int count = -1;
-        int ret;
-        ret = ff_parse_channel_layout(&layout, &count, teststrings[i], NULL);
-
-        printf ("%d = ff_parse_channel_layout(%016"PRIX64", %2d, %s);\n", ret ? -1 : 0, layout, count, teststrings[i]);
-    }
-
-    return 0;
-}
-
-#endif
-
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index ce09d3c..77981f5 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -273,7 +273,6 @@ int ff_formats_ref(AVFilterFormats *formats, AVFilterFormats **ref);
 void ff_formats_unref(AVFilterFormats **ref);
 
 /**
- *
  *         Before                                 After
  *   ________                         ________
  *  |formats |<---------.            |formats |<---------.
diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c
index d9f40d6..04b4272 100644
--- a/libavfilter/graphparser.c
+++ b/libavfilter/graphparser.c
@@ -27,7 +27,7 @@
 #include "libavutil/mem.h"
 #include "avfilter.h"
 
-#define WHITESPACES " \n\t"
+#define WHITESPACES " \n\t\r"
 
 /**
  * Link two filters together.
@@ -165,12 +165,12 @@ static int parse_filter(AVFilterContext **filt_ctx, const char **buf, AVFilterGr
                         int index, void *log_ctx)
 {
     char *opts = NULL;
-    char *name = av_get_token(buf, "=,;[\n");
+    char *name = av_get_token(buf, "=,;[");
     int ret;
 
     if (**buf == '=') {
         (*buf)++;
-        opts = av_get_token(buf, "[],;\n");
+        opts = av_get_token(buf, "[],;");
     }
 
     ret = create_filter(filt_ctx, graph, index, name, opts, log_ctx);
@@ -354,7 +354,7 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs,
             av_freep(&match);
             av_freep(&input);
         } else {
-            /* Not in the list, so add the first input as a open_output */
+            /* Not in the list, so add the first input as an open_output */
             input->name = name;
             insert_inout(open_outputs, input);
         }
diff --git a/libavfilter/interlace.h b/libavfilter/interlace.h
index 44f1e06..da073ae 100644
--- a/libavfilter/interlace.h
+++ b/libavfilter/interlace.h
@@ -47,7 +47,7 @@ enum FieldType {
 typedef struct InterlaceContext {
     const AVClass *class;
     enum ScanMode scan;    // top or bottom field first scanning
-    int lowpass;           // enable or disable low pass filterning
+    int lowpass;           // enable or disable low pass filtering
     AVFrame *cur, *next;   // the two frames from which the new one is obtained
     void (*lowpass_line)(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp,
                          const uint8_t *srcp_above, const uint8_t *srcp_below);
diff --git a/libavfilter/pthread.c b/libavfilter/pthread.c
index 37ca73f..ccb915e 100644
--- a/libavfilter/pthread.c
+++ b/libavfilter/pthread.c
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
diff --git a/libavfilter/split.c b/libavfilter/split.c
index c545fd6..6cf4ab1 100644
--- a/libavfilter/split.c
+++ b/libavfilter/split.c
@@ -95,7 +95,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
 }
 
 #define OFFSET(x) offsetof(SplitContext, x)
-#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM
+#define FLAGS (AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
 static const AVOption options[] = {
     { "outputs", "set number of outputs", OFFSET(nb_outputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT_MAX, FLAGS },
     { NULL }
diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c
index eab2458..23dcb7b 100644
--- a/libavfilter/src_movie.c
+++ b/libavfilter/src_movie.c
@@ -46,7 +46,10 @@
 
 typedef struct MovieStream {
     AVStream *st;
+    AVCodecContext *codec_ctx;
     int done;
+    int64_t discontinuity_threshold;
+    int64_t last_pts;
 } MovieStream;
 
 typedef struct MovieContext {
@@ -59,6 +62,8 @@ typedef struct MovieContext {
     char *stream_specs; /**< user-provided list of streams, separated by + */
     int stream_index; /**< for compatibility */
     int loop_count;
+    int64_t discontinuity_threshold;
+    int64_t ts_offset;
 
     AVFormatContext *format_ctx;
     int eof;
@@ -83,6 +88,7 @@ static const AVOption movie_options[]= {
     { "streams",      "set streams",             OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str =  0},  CHAR_MAX, CHAR_MAX, FLAGS },
     { "s",            "set streams",             OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str =  0},  CHAR_MAX, CHAR_MAX, FLAGS },
     { "loop",         "set loop count",          OFFSET(loop_count),   AV_OPT_TYPE_INT,    {.i64 =  1},  0,        INT_MAX, FLAGS },
+    { "discontinuity", "set discontinuity threshold", OFFSET(discontinuity_threshold), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, FLAGS },
     { NULL },
 };
 
@@ -133,11 +139,11 @@ static AVStream *find_stream(void *log, AVFormatContext *avf, const char *spec)
                          "did not match any stream");
         return NULL;
     }
-    if (found->codec->codec_type != AVMEDIA_TYPE_VIDEO &&
-        found->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
+    if (found->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
+        found->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
         av_log(log, AV_LOG_ERROR, "Stream specifier \"%s\" matched a %s stream,"
                "currently unsupported by libavfilter\n", spec,
-               av_get_media_type_string(found->codec->codec_type));
+               av_get_media_type_string(found->codecpar->codec_type));
         return NULL;
     }
     return found;
@@ -148,15 +154,23 @@ static int open_stream(void *log, MovieStream *st)
     AVCodec *codec;
     int ret;
 
-    codec = avcodec_find_decoder(st->st->codec->codec_id);
+    codec = avcodec_find_decoder(st->st->codecpar->codec_id);
     if (!codec) {
         av_log(log, AV_LOG_ERROR, "Failed to find any codec\n");
         return AVERROR(EINVAL);
     }
 
-    st->st->codec->refcounted_frames = 1;
+    st->codec_ctx = avcodec_alloc_context3(codec);
+    if (!st->codec_ctx)
+        return AVERROR(ENOMEM);
+
+    ret = avcodec_parameters_to_context(st->codec_ctx, st->st->codecpar);
+    if (ret < 0)
+        return ret;
+
+    st->codec_ctx->refcounted_frames = 1;
 
-    if ((ret = avcodec_open2(st->st->codec, codec, NULL)) < 0) {
+    if ((ret = avcodec_open2(st->codec_ctx, codec, NULL)) < 0) {
         av_log(log, AV_LOG_ERROR, "Failed to open codec\n");
         return ret;
     }
@@ -166,24 +180,24 @@ static int open_stream(void *log, MovieStream *st)
 
 static int guess_channel_layout(MovieStream *st, int st_index, void *log_ctx)
 {
-    AVCodecContext *dec_ctx = st->st->codec;
+    AVCodecParameters *dec_par = st->st->codecpar;
     char buf[256];
-    int64_t chl = av_get_default_channel_layout(dec_ctx->channels);
+    int64_t chl = av_get_default_channel_layout(dec_par->channels);
 
     if (!chl) {
         av_log(log_ctx, AV_LOG_ERROR,
                "Channel layout is not set in stream %d, and could not "
                "be guessed from the number of channels (%d)\n",
-               st_index, dec_ctx->channels);
+               st_index, dec_par->channels);
         return AVERROR(EINVAL);
     }
 
-    av_get_channel_layout_string(buf, sizeof(buf), dec_ctx->channels, chl);
+    av_get_channel_layout_string(buf, sizeof(buf), dec_par->channels, chl);
     av_log(log_ctx, AV_LOG_WARNING,
            "Channel layout is not set in output stream %d, "
            "guessed channel layout is '%s'\n",
            st_index, buf);
-    dec_ctx->channel_layout = chl;
+    dec_par->channel_layout = chl;
     return 0;
 }
 
@@ -273,6 +287,8 @@ static av_cold int movie_common_init(AVFilterContext *ctx)
         st->discard = AVDISCARD_DEFAULT;
         movie->st[i].st = st;
         movie->max_stream_index = FFMAX(movie->max_stream_index, st->index);
+        movie->st[i].discontinuity_threshold =
+            av_rescale_q(movie->discontinuity_threshold, AV_TIME_BASE_Q, st->time_base);
     }
     if (av_strtok(NULL, "+", &cursor))
         return AVERROR_BUG;
@@ -287,22 +303,22 @@ static av_cold int movie_common_init(AVFilterContext *ctx)
         AVFilterPad pad = { 0 };
         movie->out_index[movie->st[i].st->index] = i;
         snprintf(name, sizeof(name), "out%d", i);
-        pad.type          = movie->st[i].st->codec->codec_type;
+        pad.type          = movie->st[i].st->codecpar->codec_type;
         pad.name          = av_strdup(name);
         if (!pad.name)
             return AVERROR(ENOMEM);
         pad.config_props  = movie_config_output_props;
         pad.request_frame = movie_request_frame;
         ff_insert_outpad(ctx, i, &pad);
-        ret = open_stream(ctx, &movie->st[i]);
-        if (ret < 0)
-            return ret;
-        if ( movie->st[i].st->codec->codec->type == AVMEDIA_TYPE_AUDIO &&
-            !movie->st[i].st->codec->channel_layout) {
+        if ( movie->st[i].st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
+            !movie->st[i].st->codecpar->channel_layout) {
             ret = guess_channel_layout(&movie->st[i], i, ctx);
             if (ret < 0)
                 return ret;
         }
+        ret = open_stream(ctx, &movie->st[i]);
+        if (ret < 0)
+            return ret;
     }
 
     av_log(ctx, AV_LOG_VERBOSE, "seek_point:%"PRIi64" format_name:%s file_name:%s stream_index:%d\n",
@@ -320,7 +336,7 @@ static av_cold void movie_uninit(AVFilterContext *ctx)
     for (i = 0; i < ctx->nb_outputs; i++) {
         av_freep(&ctx->output_pads[i].name);
         if (movie->st[i].st)
-            avcodec_close(movie->st[i].st->codec);
+            avcodec_free_context(&movie->st[i].codec_ctx);
     }
     av_freep(&movie->st);
     av_freep(&movie->out_index);
@@ -337,17 +353,17 @@ static int movie_query_formats(AVFilterContext *ctx)
 
     for (i = 0; i < ctx->nb_outputs; i++) {
         MovieStream *st = &movie->st[i];
-        AVCodecContext *c = st->st->codec;
+        AVCodecParameters *c = st->st->codecpar;
         AVFilterLink *outlink = ctx->outputs[i];
 
         switch (c->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
-            list[0] = c->pix_fmt;
+            list[0] = c->format;
             if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->in_formats)) < 0)
                 return ret;
             break;
         case AVMEDIA_TYPE_AUDIO:
-            list[0] = c->sample_fmt;
+            list[0] = c->format;
             if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->in_formats)) < 0)
                 return ret;
             list[0] = c->sample_rate;
@@ -370,7 +386,7 @@ static int movie_config_output_props(AVFilterLink *outlink)
     MovieContext *movie  = ctx->priv;
     unsigned out_id = FF_OUTLINK_IDX(outlink);
     MovieStream *st = &movie->st[out_id];
-    AVCodecContext *c = st->st->codec;
+    AVCodecParameters *c = st->st->codecpar;
 
     outlink->time_base = st->st->time_base;
 
@@ -429,7 +445,7 @@ static int rewind_file(AVFilterContext *ctx)
     }
 
     for (i = 0; i < ctx->nb_outputs; i++) {
-        avcodec_flush_buffers(movie->st[i].st->codec);
+        avcodec_flush_buffers(movie->st[i].codec_ctx);
         movie->st[i].done = 0;
     }
     movie->eof = 0;
@@ -502,13 +518,13 @@ static int movie_push_frame(AVFilterContext *ctx, unsigned out_id)
     if (!frame)
         return AVERROR(ENOMEM);
 
-    frame_type = st->st->codec->codec_type;
+    frame_type = st->st->codecpar->codec_type;
     switch (frame_type) {
     case AVMEDIA_TYPE_VIDEO:
-        ret = avcodec_decode_video2(st->st->codec, frame, &got_frame, pkt);
+        ret = avcodec_decode_video2(st->codec_ctx, frame, &got_frame, pkt);
         break;
     case AVMEDIA_TYPE_AUDIO:
-        ret = avcodec_decode_audio4(st->st->codec, frame, &got_frame, pkt);
+        ret = avcodec_decode_audio4(st->codec_ctx, frame, &got_frame, pkt);
         break;
     default:
         ret = AVERROR(ENOSYS);
@@ -522,7 +538,7 @@ static int movie_push_frame(AVFilterContext *ctx, unsigned out_id)
         movie->pkt.data = NULL;
         return 0;
     }
-    if (!ret || st->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+    if (!ret || st->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
         ret = pkt->size;
 
     pkt->data += ret;
@@ -540,10 +556,25 @@ static int movie_push_frame(AVFilterContext *ctx, unsigned out_id)
     }
 
     frame->pts = av_frame_get_best_effort_timestamp(frame);
+    if (frame->pts != AV_NOPTS_VALUE) {
+        if (movie->ts_offset)
+            frame->pts += av_rescale_q_rnd(movie->ts_offset, AV_TIME_BASE_Q, outlink->time_base, AV_ROUND_UP);
+        if (st->discontinuity_threshold) {
+            if (st->last_pts != AV_NOPTS_VALUE) {
+                int64_t diff = frame->pts - st->last_pts;
+                if (diff < 0 || diff > st->discontinuity_threshold) {
+                    av_log(ctx, AV_LOG_VERBOSE, "Discontinuity in stream:%d diff:%"PRId64"\n", pkt_out_id, diff);
+                    movie->ts_offset += av_rescale_q_rnd(-diff, outlink->time_base, AV_TIME_BASE_Q, AV_ROUND_UP);
+                    frame->pts -= diff;
+                }
+            }
+        }
+        st->last_pts = frame->pts;
+    }
     ff_dlog(ctx, "movie_push_frame(): file:'%s' %s\n", movie->file_name,
             describe_frame_to_str((char[1024]){0}, 1024, frame, frame_type, outlink));
 
-    if (st->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         if (frame->format != outlink->format) {
             av_log(ctx, AV_LOG_ERROR, "Format changed %s -> %s, discarding frame\n",
                 av_get_pix_fmt_name(outlink->format),
@@ -573,6 +604,49 @@ static int movie_request_frame(AVFilterLink *outlink)
     }
 }
 
+static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
+                           char *res, int res_len, int flags)
+{
+    MovieContext *movie = ctx->priv;
+    int ret = AVERROR(ENOSYS);
+
+    if (!strcmp(cmd, "seek")) {
+        int idx, flags, i;
+        int64_t ts;
+        char tail[2];
+
+        if (sscanf(args, "%i|%"SCNi64"|%i %1s", &idx, &ts, &flags, tail) != 3)
+            return AVERROR(EINVAL);
+
+        ret = av_seek_frame(movie->format_ctx, idx, ts, flags);
+        if (ret < 0)
+            return ret;
+
+        for (i = 0; i < ctx->nb_outputs; i++) {
+            avcodec_flush_buffers(movie->st[i].codec_ctx);
+            movie->st[i].done = 0;
+        }
+        return ret;
+    } else if (!strcmp(cmd, "get_duration")) {
+        int print_len;
+        char tail[2];
+
+        if (!res || res_len <= 0)
+            return AVERROR(EINVAL);
+
+        if (args && sscanf(args, "%1s", tail) == 1)
+            return AVERROR(EINVAL);
+
+        print_len = snprintf(res, res_len, "%"PRId64, movie->format_ctx->duration);
+        if (print_len < 0 || print_len >= res_len)
+            return AVERROR(EINVAL);
+
+        return 0;
+    }
+
+    return ret;
+}
+
 #if CONFIG_MOVIE_FILTER
 
 AVFILTER_DEFINE_CLASS(movie);
@@ -589,6 +663,7 @@ AVFilter ff_avsrc_movie = {
     .inputs    = NULL,
     .outputs   = NULL,
     .flags     = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
+    .process_command = process_command
 };
 
 #endif  /* CONFIG_MOVIE_FILTER */
@@ -610,6 +685,7 @@ AVFilter ff_avsrc_amovie = {
     .outputs    = NULL,
     .priv_class = &amovie_class,
     .flags      = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
+    .process_command = process_command,
 };
 
 #endif /* CONFIG_AMOVIE_FILTER */
diff --git a/libavfilter/tests/drawutils.c b/libavfilter/tests/drawutils.c
new file mode 100644
index 0000000..7fe53dd
--- /dev/null
+++ b/libavfilter/tests/drawutils.c
@@ -0,0 +1,56 @@
+/*
+ * 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 <stdio.h>
+
+#include "libavutil/pixdesc.h"
+#include "libavfilter/drawutils.h"
+
+int main(void)
+{
+    enum AVPixelFormat f;
+    const AVPixFmtDescriptor *desc;
+    FFDrawContext draw;
+    FFDrawColor color;
+    int r, i;
+
+    for (f = 0; av_pix_fmt_desc_get(f); f++) {
+        desc = av_pix_fmt_desc_get(f);
+        if (!desc->name)
+            continue;
+        printf("Testing %s...%*s", desc->name,
+               (int)(16 - strlen(desc->name)), "");
+        r = ff_draw_init(&draw, f, 0);
+        if (r < 0) {
+            char buf[128];
+            av_strerror(r, buf, sizeof(buf));
+            printf("no: %s\n", buf);
+            continue;
+        }
+        ff_draw_color(&draw, &color, (uint8_t[]) { 1, 0, 0, 1 });
+        for (i = 0; i < sizeof(color); i++)
+            if (((uint8_t *)&color)[i] != 128)
+                break;
+        if (i == sizeof(color)) {
+            printf("fallback color\n");
+            continue;
+        }
+        printf("ok\n");
+    }
+    return 0;
+}
diff --git a/libavfilter/filtfmts.c b/libavfilter/tests/filtfmts.c
similarity index 100%
rename from libavfilter/filtfmts.c
rename to libavfilter/tests/filtfmts.c
diff --git a/libavfilter/tests/formats.c b/libavfilter/tests/formats.c
new file mode 100644
index 0000000..0e8ba4a
--- /dev/null
+++ b/libavfilter/tests/formats.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007 Bobby Bingham
+ *
+ * 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 "libavfilter/formats.c"
+
+#undef printf
+
+int main(void)
+{
+    const int64_t *cl;
+    char buf[512];
+    int i;
+    const char *teststrings[] ={
+        "blah",
+        "1",
+        "2",
+        "-1",
+        "60",
+        "65",
+        "1c",
+        "2c",
+        "-1c",
+        "60c",
+        "65c",
+        "5.1",
+        "stereo",
+        "1+1+1+1",
+        "1c+1c+1c+1c",
+        "2c+1c",
+        "0x3",
+    };
+
+    for (cl = avfilter_all_channel_layouts; *cl != -1; cl++) {
+        av_get_channel_layout_string(buf, sizeof(buf), -1, *cl);
+        printf("%s\n", buf);
+    }
+
+    for ( i = 0; i<FF_ARRAY_ELEMS(teststrings); i++) {
+        int64_t layout = -1;
+        int count = -1;
+        int ret;
+        ret = ff_parse_channel_layout(&layout, &count, teststrings[i], NULL);
+
+        printf ("%d = ff_parse_channel_layout(%016"PRIX64", %2d, %s);\n", ret ? -1 : 0, layout, count, teststrings[i]);
+    }
+
+    return 0;
+}
diff --git a/libavfilter/thread.h b/libavfilter/thread.h
index 5f347e8..c709f17 100644
--- a/libavfilter/thread.h
+++ b/libavfilter/thread.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
diff --git a/libavfilter/trim.c b/libavfilter/trim.c
index 9141ac5..9daaeaf 100644
--- a/libavfilter/trim.c
+++ b/libavfilter/trim.c
@@ -16,8 +16,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <float.h>
-#include <math.h>
 #include <stdint.h>
 
 #include "config.h"
@@ -43,9 +41,6 @@ typedef struct TrimContext {
     int64_t duration;
     int64_t start_time, end_time;
     int64_t start_frame, end_frame;
-
-    double duration_dbl;
-    double start_time_dbl, end_time_dbl;
     /*
      * in the link timebase for video,
      * in 1/samplerate for audio
@@ -91,13 +86,6 @@ static int config_input(AVFilterLink *inlink)
     AVRational tb = (inlink->type == AVMEDIA_TYPE_VIDEO) ?
                      inlink->time_base : (AVRational){ 1, inlink->sample_rate };
 
-    if (s->start_time_dbl != DBL_MAX)
-        s->start_time = s->start_time_dbl * 1e6;
-    if (s->end_time_dbl != DBL_MAX)
-        s->end_time = s->end_time_dbl * 1e6;
-    if (s->duration_dbl != 0)
-        s->duration = s->duration_dbl * 1e6;
-
     if (s->start_time != INT64_MAX) {
         int64_t start_pts = av_rescale_q(s->start_time, AV_TIME_BASE_Q, tb);
         if (s->start_pts == AV_NOPTS_VALUE || start_pts < s->start_pts)
@@ -116,23 +104,21 @@ static int config_input(AVFilterLink *inlink)
 
 #define OFFSET(x) offsetof(TrimContext, x)
 #define COMMON_OPTS                                                                                                                                                         \
+    { "start",       "Timestamp of the first frame that "                                                                                                        \
+        "should be passed",                                              OFFSET(start_time),  AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX },    INT64_MIN, INT64_MAX, FLAGS }, \
     { "starti",      "Timestamp of the first frame that "                                                                                                        \
         "should be passed",                                              OFFSET(start_time),  AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX },    INT64_MIN, INT64_MAX, FLAGS }, \
+    { "end",         "Timestamp of the first frame that "                                                                                                        \
+        "should be dropped again",                                       OFFSET(end_time),    AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX },    INT64_MIN, INT64_MAX, FLAGS }, \
     { "endi",        "Timestamp of the first frame that "                                                                                                        \
         "should be dropped again",                                       OFFSET(end_time),    AV_OPT_TYPE_DURATION, { .i64 = INT64_MAX },    INT64_MIN, INT64_MAX, FLAGS }, \
     { "start_pts",   "Timestamp of the first frame that should be "                                                                                                         \
        " passed",                                                        OFFSET(start_pts),   AV_OPT_TYPE_INT64,  { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
     { "end_pts",     "Timestamp of the first frame that should be "                                                                                                         \
         "dropped again",                                                 OFFSET(end_pts),     AV_OPT_TYPE_INT64,  { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, FLAGS }, \
+    { "duration",    "Maximum duration of the output",                   OFFSET(duration),    AV_OPT_TYPE_DURATION, { .i64 = 0 },                    0, INT64_MAX, FLAGS }, \
     { "durationi",   "Maximum duration of the output",                   OFFSET(duration),    AV_OPT_TYPE_DURATION, { .i64 = 0 },                    0, INT64_MAX, FLAGS },
 
-#define COMPAT_OPTS \
-    { "start",       "Timestamp in seconds of the first frame that "                                                                                                        \
-        "should be passed",                                              OFFSET(start_time_dbl),AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX },       -DBL_MAX, DBL_MAX,     FLAGS }, \
-    { "end",         "Timestamp in seconds of the first frame that "                                                                                                        \
-        "should be dropped again",                                       OFFSET(end_time_dbl),  AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX },       -DBL_MAX, DBL_MAX,     FLAGS }, \
-    { "duration",    "Maximum duration of the output in seconds",        OFFSET(duration_dbl),  AV_OPT_TYPE_DOUBLE, { .dbl = 0 },                      0,   DBL_MAX, FLAGS },
-
 
 #if CONFIG_TRIM_FILTER
 static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
@@ -197,7 +183,6 @@ static const AVOption trim_options[] = {
         "to the output",                                                 OFFSET(start_frame), AV_OPT_TYPE_INT64,  { .i64 = -1 },       -1, INT64_MAX, FLAGS },
     { "end_frame",   "Number of the first frame that should be dropped "
         "again",                                                         OFFSET(end_frame),   AV_OPT_TYPE_INT64,  { .i64 = INT64_MAX }, 0, INT64_MAX, FLAGS },
-    COMPAT_OPTS
     { NULL }
 };
 #undef FLAGS
@@ -352,7 +337,6 @@ static const AVOption atrim_options[] = {
         "passed to the output",                                          OFFSET(start_sample), AV_OPT_TYPE_INT64,  { .i64 = -1 },       -1, INT64_MAX, FLAGS },
     { "end_sample",   "Number of the first audio sample that should be "
         "dropped again",                                                 OFFSET(end_sample),   AV_OPT_TYPE_INT64,  { .i64 = INT64_MAX }, 0, INT64_MAX, FLAGS },
-    COMPAT_OPTS
     { NULL }
 };
 #undef FLAGS
diff --git a/libavfilter/vaf_spectrumsynth.c b/libavfilter/vaf_spectrumsynth.c
index 8d4014e..ee394b4 100644
--- a/libavfilter/vaf_spectrumsynth.c
+++ b/libavfilter/vaf_spectrumsynth.c
@@ -27,6 +27,7 @@
 #include "libavcodec/avfft.h"
 #include "libavutil/avassert.h"
 #include "libavutil/channel_layout.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "avfilter.h"
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 1fe7757..6d56dad 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -30,7 +30,7 @@
 #include "libavutil/version.h"
 
 #define LIBAVFILTER_VERSION_MAJOR   6
-#define LIBAVFILTER_VERSION_MINOR  31
+#define LIBAVFILTER_VERSION_MINOR  47
 #define LIBAVFILTER_VERSION_MICRO 100
 
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c
index ea63a20..a121267 100644
--- a/libavfilter/vf_blend.c
+++ b/libavfilter/vf_blend.c
@@ -76,9 +76,11 @@ typedef struct ThreadData {
     { "divide",     "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DIVIDE},     0, 0, FLAGS, "mode" },\
     { "dodge",      "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_DODGE},      0, 0, FLAGS, "mode" },\
     { "exclusion",  "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_EXCLUSION},  0, 0, FLAGS, "mode" },\
+    { "freeze",     "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_FREEZE},     0, 0, FLAGS, "mode" },\
     { "glow",       "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_GLOW},       0, 0, FLAGS, "mode" },\
     { "hardlight",  "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_HARDLIGHT},  0, 0, FLAGS, "mode" },\
     { "hardmix",    "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_HARDMIX},    0, 0, FLAGS, "mode" },\
+    { "heat",       "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_HEAT},       0, 0, FLAGS, "mode" },\
     { "lighten",    "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_LIGHTEN},    0, 0, FLAGS, "mode" },\
     { "linearlight","", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_LINEARLIGHT},0, 0, FLAGS, "mode" },\
     { "multiply",   "", 0, AV_OPT_TYPE_CONST, {.i64=BLEND_MULTIPLY},   0, 0, FLAGS, "mode" },\
@@ -123,7 +125,7 @@ static void blend_copy ## src(const uint8_t *top, ptrdiff_t top_linesize,    \
                             const uint8_t *bottom, ptrdiff_t bottom_linesize,\
                             uint8_t *dst, ptrdiff_t dst_linesize,            \
                             ptrdiff_t width, ptrdiff_t height,               \
-                            FilterParams *param, double *values)             \
+                            FilterParams *param, double *values, int starty) \
 {                                                                            \
     av_image_copy_plane(dst, dst_linesize, src, src ## _linesize,            \
                         width, height);                                 \
@@ -138,7 +140,7 @@ static void blend_normal_8bit(const uint8_t *top, ptrdiff_t top_linesize,
                               const uint8_t *bottom, ptrdiff_t bottom_linesize,
                               uint8_t *dst, ptrdiff_t dst_linesize,
                               ptrdiff_t width, ptrdiff_t height,
-                              FilterParams *param, double *values)
+                              FilterParams *param, double *values, int starty)
 {
     const double opacity = param->opacity;
     int i, j;
@@ -157,7 +159,7 @@ static void blend_normal_16bit(const uint8_t *_top, ptrdiff_t top_linesize,
                                   const uint8_t *_bottom, ptrdiff_t bottom_linesize,
                                   uint8_t *_dst, ptrdiff_t dst_linesize,
                                   ptrdiff_t width, ptrdiff_t height,
-                                  FilterParams *param, double *values)
+                                  FilterParams *param, double *values, int starty)
 {
     const uint16_t *top = (uint16_t*)_top;
     const uint16_t *bottom = (uint16_t*)_bottom;
@@ -183,7 +185,7 @@ static void blend_## name##_8bit(const uint8_t *top, ptrdiff_t top_linesize,
                                  const uint8_t *bottom, ptrdiff_t bottom_linesize,   \
                                  uint8_t *dst, ptrdiff_t dst_linesize,               \
                                  ptrdiff_t width, ptrdiff_t height,                \
-                                 FilterParams *param, double *values)          \
+                                 FilterParams *param, double *values, int starty) \
 {                                                                              \
     double opacity = param->opacity;                                           \
     int i, j;                                                                  \
@@ -203,7 +205,7 @@ static void blend_## name##_16bit(const uint8_t *_top, ptrdiff_t top_linesize,
                                   const uint8_t *_bottom, ptrdiff_t bottom_linesize, \
                                   uint8_t *_dst, ptrdiff_t dst_linesize,             \
                                   ptrdiff_t width, ptrdiff_t height,           \
-                                  FilterParams *param, double *values)         \
+                                  FilterParams *param, double *values, int starty)         \
 {                                                                              \
     const uint16_t *top = (uint16_t*)_top;                                     \
     const uint16_t *bottom = (uint16_t*)_bottom;                               \
@@ -245,6 +247,8 @@ DEFINE_BLEND8(screen,     SCREEN(1, A, B))
 DEFINE_BLEND8(overlay,    (A < 128) ? MULTIPLY(2, A, B) : SCREEN(2, A, B))
 DEFINE_BLEND8(hardlight,  (B < 128) ? MULTIPLY(2, B, A) : SCREEN(2, B, A))
 DEFINE_BLEND8(hardmix,    (A < (255 - B)) ? 0: 255)
+DEFINE_BLEND8(heat,       (A == 0) ? 0 : 255 - FFMIN(((255 - B) * (255 - B)) / A, 255))
+DEFINE_BLEND8(freeze,     (B == 0) ? 0 : 255 - FFMIN(((255 - A) * (255 - A)) / B, 255))
 DEFINE_BLEND8(darken,     FFMIN(A, B))
 DEFINE_BLEND8(lighten,    FFMAX(A, B))
 DEFINE_BLEND8(divide,     av_clip_uint8(B == 0 ? 255 : 255 * A / B))
@@ -285,6 +289,8 @@ DEFINE_BLEND16(screen,     SCREEN(1, A, B))
 DEFINE_BLEND16(overlay,    (A < 32768) ? MULTIPLY(2, A, B) : SCREEN(2, A, B))
 DEFINE_BLEND16(hardlight,  (B < 32768) ? MULTIPLY(2, B, A) : SCREEN(2, B, A))
 DEFINE_BLEND16(hardmix,    (A < (65535 - B)) ? 0: 65535)
+DEFINE_BLEND16(heat,       (A == 0) ? 0 : 65535 - FFMIN(((65535 - B) * (65535 - B)) / A, 65535))
+DEFINE_BLEND16(freeze,     (B == 0) ? 0 : 65535 - FFMIN(((65535 - A) * (65535 - A)) / B, 65535))
 DEFINE_BLEND16(darken,     FFMIN(A, B))
 DEFINE_BLEND16(lighten,    FFMAX(A, B))
 DEFINE_BLEND16(divide,     av_clip_uint16(B == 0 ? 65535 : 65535 * A / B))
@@ -307,7 +313,7 @@ static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize,
                                const uint8_t *_bottom, ptrdiff_t bottom_linesize,    \
                                uint8_t *_dst, ptrdiff_t dst_linesize,                \
                                ptrdiff_t width, ptrdiff_t height,              \
-                               FilterParams *param, double *values)            \
+                               FilterParams *param, double *values, int starty) \
 {                                                                              \
     const type *top = (type*)_top;                                             \
     const type *bottom = (type*)_bottom;                                       \
@@ -319,7 +325,7 @@ static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize,
     bottom_linesize /= div;                                                    \
                                                                                \
     for (y = 0; y < height; y++) {                                             \
-        values[VAR_Y] = y;                                                     \
+        values[VAR_Y] = y + starty;                                            \
         for (x = 0; x < width; x++) {                                          \
             values[VAR_X]      = x;                                            \
             values[VAR_TOP]    = values[VAR_A] = top[x];                       \
@@ -359,7 +365,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
                      td->bottom->linesize[td->plane],
                      dst + slice_start * td->dst->linesize[td->plane],
                      td->dst->linesize[td->plane],
-                     td->w, height, td->param, &values[0]);
+                     td->w, height, td->param, &values[0], slice_start);
     return 0;
 }
 
@@ -451,9 +457,11 @@ void ff_blend_init(FilterParams *param, int is_16bit)
     case BLEND_DIVIDE:     param->blend = is_16bit ? blend_divide_16bit     : blend_divide_8bit;     break;
     case BLEND_DODGE:      param->blend = is_16bit ? blend_dodge_16bit      : blend_dodge_8bit;      break;
     case BLEND_EXCLUSION:  param->blend = is_16bit ? blend_exclusion_16bit  : blend_exclusion_8bit;  break;
+    case BLEND_FREEZE:     param->blend = is_16bit ? blend_freeze_16bit     : blend_freeze_8bit;     break;
     case BLEND_GLOW:       param->blend = is_16bit ? blend_glow_16bit       : blend_glow_8bit;       break;
     case BLEND_HARDLIGHT:  param->blend = is_16bit ? blend_hardlight_16bit  : blend_hardlight_8bit;  break;
     case BLEND_HARDMIX:    param->blend = is_16bit ? blend_hardmix_16bit    : blend_hardmix_8bit;    break;
+    case BLEND_HEAT:       param->blend = is_16bit ? blend_heat_16bit       : blend_heat_8bit;       break;
     case BLEND_LIGHTEN:    param->blend = is_16bit ? blend_lighten_16bit    : blend_lighten_8bit;    break;
     case BLEND_LINEARLIGHT:param->blend = is_16bit ? blend_linearlight_16bit: blend_linearlight_8bit;break;
     case BLEND_MULTIPLY:   param->blend = is_16bit ? blend_multiply_16bit   : blend_multiply_8bit;   break;
diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c
new file mode 100644
index 0000000..595b825
--- /dev/null
+++ b/libavfilter/vf_bwdif.c
@@ -0,0 +1,584 @@
+/*
+ * BobWeaver Deinterlacing Filter
+ * Copyright (C) 2016 Thomas Mundt <loudmax at yahoo.de>
+ *
+ * Based on YADIF (Yet Another Deinterlacing Filter)
+ * Copyright (C) 2006-2011 Michael Niedermayer <michaelni at gmx.at>
+ *               2010      James Darnley <james.darnley at gmail.com>
+ *
+ * With use of Weston 3 Field Deinterlacing Filter algorithm
+ * Copyright (C) 2012 British Broadcasting Corporation, All Rights Reserved
+ * Author of de-interlace algorithm: Jim Easterbrook for BBC R&D
+ * Based on the process described by Martin Weston for BBC R&D
+ *
+ * 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/avassert.h"
+#include "libavutil/common.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/imgutils.h"
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+#include "bwdif.h"
+
+/*
+ * Filter coefficients coef_lf and coef_hf taken from BBC PH-2071 (Weston 3 Field Deinterlacer).
+ * Used when there is spatial and temporal interpolation.
+ * Filter coefficients coef_sp are used when there is spatial interpolation only.
+ * Adjusted for matching visual sharpness impression of spatial and temporal interpolation.
+ */
+static const uint16_t coef_lf[2] = { 4309, 213 };
+static const uint16_t coef_hf[3] = { 5570, 3801, 1016 };
+static const uint16_t coef_sp[2] = { 5077, 981 };
+
+typedef struct ThreadData {
+    AVFrame *frame;
+    int plane;
+    int w, h;
+    int parity;
+    int tff;
+} ThreadData;
+
+#define FILTER_INTRA() \
+    for (x = 0; x < w; x++) { \
+        interpol = (coef_sp[0] * (cur[mrefs] + cur[prefs]) - coef_sp[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
+        dst[0] = av_clip(interpol, 0, clip_max); \
+ \
+        dst++; \
+        cur++; \
+    }
+
+#define FILTER1() \
+    for (x = 0; x < w; x++) { \
+        int c = cur[mrefs]; \
+        int d = (prev2[0] + next2[0]) >> 1; \
+        int e = cur[prefs]; \
+        int temporal_diff0 = FFABS(prev2[0] - next2[0]); \
+        int temporal_diff1 =(FFABS(prev[mrefs] - c) + FFABS(prev[prefs] - e)) >> 1; \
+        int temporal_diff2 =(FFABS(next[mrefs] - c) + FFABS(next[prefs] - e)) >> 1; \
+        int diff = FFMAX3(temporal_diff0 >> 1, temporal_diff1, temporal_diff2); \
+ \
+        if (!diff) { \
+            dst[0] = d; \
+        } else {
+
+#define SPAT_CHECK() \
+            int b = ((prev2[mrefs2] + next2[mrefs2]) >> 1) - c; \
+            int f = ((prev2[prefs2] + next2[prefs2]) >> 1) - e; \
+            int dc = d - c; \
+            int de = d - e; \
+            int max = FFMAX3(de, dc, FFMIN(b, f)); \
+            int min = FFMIN3(de, dc, FFMAX(b, f)); \
+            diff = FFMAX3(diff, min, -max);
+
+#define FILTER_LINE() \
+            SPAT_CHECK() \
+            if (FFABS(c - e) > temporal_diff0) { \
+                interpol = (((coef_hf[0] * (prev2[0] + next2[0]) \
+                    - coef_hf[1] * (prev2[mrefs2] + next2[mrefs2] + prev2[prefs2] + next2[prefs2]) \
+                    + coef_hf[2] * (prev2[mrefs4] + next2[mrefs4] + prev2[prefs4] + next2[prefs4])) >> 2) \
+                    + coef_lf[0] * (c + e) - coef_lf[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
+            } else { \
+                interpol = (coef_sp[0] * (c + e) - coef_sp[1] * (cur[mrefs3] + cur[prefs3])) >> 13; \
+            }
+
+#define FILTER_EDGE() \
+            if (spat) { \
+                SPAT_CHECK() \
+            } \
+            interpol = (c + e) >> 1;
+
+#define FILTER2() \
+            if (interpol > d + diff) \
+                interpol = d + diff; \
+            else if (interpol < d - diff) \
+                interpol = d - diff; \
+ \
+            dst[0] = av_clip(interpol, 0, clip_max); \
+        } \
+ \
+        dst++; \
+        cur++; \
+        prev++; \
+        next++; \
+        prev2++; \
+        next2++; \
+    }
+
+static void filter_intra(void *dst1, void *cur1, int w, int prefs, int mrefs,
+                         int prefs3, int mrefs3, int parity, int clip_max)
+{
+    uint8_t *dst = dst1;
+    uint8_t *cur = cur1;
+    int interpol, x;
+
+    FILTER_INTRA()
+}
+
+static void filter_line_c(void *dst1, void *prev1, void *cur1, void *next1,
+                          int w, int prefs, int mrefs, int prefs2, int mrefs2,
+                          int prefs3, int mrefs3, int prefs4, int mrefs4,
+                          int parity, int clip_max)
+{
+    uint8_t *dst   = dst1;
+    uint8_t *prev  = prev1;
+    uint8_t *cur   = cur1;
+    uint8_t *next  = next1;
+    uint8_t *prev2 = parity ? prev : cur ;
+    uint8_t *next2 = parity ? cur  : next;
+    int interpol, x;
+
+    FILTER1()
+    FILTER_LINE()
+    FILTER2()
+}
+
+static void filter_edge(void *dst1, void *prev1, void *cur1, void *next1,
+                        int w, int prefs, int mrefs, int prefs2, int mrefs2,
+                        int parity, int clip_max, int spat)
+{
+    uint8_t *dst   = dst1;
+    uint8_t *prev  = prev1;
+    uint8_t *cur   = cur1;
+    uint8_t *next  = next1;
+    uint8_t *prev2 = parity ? prev : cur ;
+    uint8_t *next2 = parity ? cur  : next;
+    int interpol, x;
+
+    FILTER1()
+    FILTER_EDGE()
+    FILTER2()
+}
+
+static void filter_intra_16bit(void *dst1, void *cur1, int w, int prefs, int mrefs,
+                               int prefs3, int mrefs3, int parity, int clip_max)
+{
+    uint16_t *dst = dst1;
+    uint16_t *cur = cur1;
+    int interpol, x;
+
+    FILTER_INTRA()
+}
+
+static void filter_line_c_16bit(void *dst1, void *prev1, void *cur1, void *next1,
+                                int w, int prefs, int mrefs, int prefs2, int mrefs2,
+                                int prefs3, int mrefs3, int prefs4, int mrefs4,
+                                int parity, int clip_max)
+{
+    uint16_t *dst   = dst1;
+    uint16_t *prev  = prev1;
+    uint16_t *cur   = cur1;
+    uint16_t *next  = next1;
+    uint16_t *prev2 = parity ? prev : cur ;
+    uint16_t *next2 = parity ? cur  : next;
+    int interpol, x;
+
+    FILTER1()
+    FILTER_LINE()
+    FILTER2()
+}
+
+static void filter_edge_16bit(void *dst1, void *prev1, void *cur1, void *next1,
+                              int w, int prefs, int mrefs, int prefs2, int mrefs2,
+                              int parity, int clip_max, int spat)
+{
+    uint16_t *dst   = dst1;
+    uint16_t *prev  = prev1;
+    uint16_t *cur   = cur1;
+    uint16_t *next  = next1;
+    uint16_t *prev2 = parity ? prev : cur ;
+    uint16_t *next2 = parity ? cur  : next;
+    int interpol, x;
+
+    FILTER1()
+    FILTER_EDGE()
+    FILTER2()
+}
+
+static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    BWDIFContext *s = ctx->priv;
+    ThreadData *td  = arg;
+    int linesize = s->cur->linesize[td->plane];
+    int clip_max = (1 << (s->csp->comp[td->plane].depth)) - 1;
+    int df = (s->csp->comp[td->plane].depth + 7) / 8;
+    int refs = linesize / df;
+    int slice_start = (td->h *  jobnr   ) / nb_jobs;
+    int slice_end   = (td->h * (jobnr+1)) / nb_jobs;
+    int y;
+
+    for (y = slice_start; y < slice_end; y++) {
+        if ((y ^ td->parity) & 1) {
+            uint8_t *prev = &s->prev->data[td->plane][y * linesize];
+            uint8_t *cur  = &s->cur ->data[td->plane][y * linesize];
+            uint8_t *next = &s->next->data[td->plane][y * linesize];
+            uint8_t *dst  = &td->frame->data[td->plane][y * td->frame->linesize[td->plane]];
+            if (!s->inter_field) {
+                s->filter_intra(dst, cur, td->w, (y + df) < td->h ? refs : -refs,
+                                y > (df - 1) ? -refs : refs,
+                                (y + 3*df) < td->h ? 3 * refs : -refs,
+                                y > (3*df - 1) ? -3 * refs : refs,
+                                td->parity ^ td->tff, clip_max);
+            } else if ((y < 4) || ((y + 5) > td->h)) {
+                s->filter_edge(dst, prev, cur, next, td->w,
+                               (y + df) < td->h ? refs : -refs,
+                               y > (df - 1) ? -refs : refs,
+                               refs << 1, -(refs << 1),
+                               td->parity ^ td->tff, clip_max,
+                               (y < 2) || ((y + 3) > td->h) ? 0 : 1);
+            } else {
+                s->filter_line(dst, prev, cur, next, td->w,
+                               refs, -refs, refs << 1, -(refs << 1),
+                               3 * refs, -3 * refs, refs << 2, -(refs << 2),
+                               td->parity ^ td->tff, clip_max);
+            }
+        } else {
+            memcpy(&td->frame->data[td->plane][y * td->frame->linesize[td->plane]],
+                   &s->cur->data[td->plane][y * linesize], td->w * df);
+        }
+    }
+    return 0;
+}
+
+static void filter(AVFilterContext *ctx, AVFrame *dstpic,
+                   int parity, int tff)
+{
+    BWDIFContext *bwdif = ctx->priv;
+    ThreadData td = { .frame = dstpic, .parity = parity, .tff = tff };
+    int i;
+
+    for (i = 0; i < bwdif->csp->nb_components; i++) {
+        int w = dstpic->width;
+        int h = dstpic->height;
+
+        if (i == 1 || i == 2) {
+            w = AV_CEIL_RSHIFT(w, bwdif->csp->log2_chroma_w);
+            h = AV_CEIL_RSHIFT(h, bwdif->csp->log2_chroma_h);
+        }
+
+        td.w     = w;
+        td.h     = h;
+        td.plane = i;
+
+        ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(h, ctx->graph->nb_threads));
+    }
+    if (!bwdif->inter_field) {
+        bwdif->inter_field = 1;
+    }
+
+    emms_c();
+}
+
+static int return_frame(AVFilterContext *ctx, int is_second)
+{
+    BWDIFContext *bwdif = ctx->priv;
+    AVFilterLink *link  = ctx->outputs[0];
+    int tff, ret;
+
+    if (bwdif->parity == -1) {
+        tff = bwdif->cur->interlaced_frame ?
+              bwdif->cur->top_field_first : 1;
+    } else {
+        tff = bwdif->parity ^ 1;
+    }
+
+    if (is_second) {
+        bwdif->out = ff_get_video_buffer(link, link->w, link->h);
+        if (!bwdif->out)
+            return AVERROR(ENOMEM);
+
+        av_frame_copy_props(bwdif->out, bwdif->cur);
+        bwdif->out->interlaced_frame = 0;
+        if (bwdif->inter_field < 0)
+            bwdif->inter_field = 0;
+    }
+
+    filter(ctx, bwdif->out, tff ^ !is_second, tff);
+
+    if (is_second) {
+        int64_t cur_pts  = bwdif->cur->pts;
+        int64_t next_pts = bwdif->next->pts;
+
+        if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) {
+            bwdif->out->pts = cur_pts + next_pts;
+        } else {
+            bwdif->out->pts = AV_NOPTS_VALUE;
+        }
+    }
+    ret = ff_filter_frame(ctx->outputs[0], bwdif->out);
+
+    bwdif->frame_pending = (bwdif->mode&1) && !is_second;
+    return ret;
+}
+
+static int checkstride(BWDIFContext *bwdif, const AVFrame *a, const AVFrame *b)
+{
+    int i;
+    for (i = 0; i < bwdif->csp->nb_components; i++)
+        if (a->linesize[i] != b->linesize[i])
+            return 1;
+    return 0;
+}
+
+static void fixstride(AVFilterLink *link, AVFrame *f)
+{
+    AVFrame *dst = ff_default_get_video_buffer(link, f->width, f->height);
+    if(!dst)
+        return;
+    av_frame_copy_props(dst, f);
+    av_image_copy(dst->data, dst->linesize,
+                  (const uint8_t **)f->data, f->linesize,
+                  dst->format, dst->width, dst->height);
+    av_frame_unref(f);
+    av_frame_move_ref(f, dst);
+    av_frame_free(&dst);
+}
+
+static int filter_frame(AVFilterLink *link, AVFrame *frame)
+{
+    AVFilterContext *ctx = link->dst;
+    BWDIFContext *bwdif = ctx->priv;
+
+    av_assert0(frame);
+
+    if (bwdif->frame_pending)
+        return_frame(ctx, 1);
+
+    if (bwdif->prev)
+        av_frame_free(&bwdif->prev);
+    bwdif->prev = bwdif->cur;
+    bwdif->cur  = bwdif->next;
+    bwdif->next = frame;
+
+    if (!bwdif->cur) {
+        bwdif->cur = av_frame_clone(bwdif->next);
+        if (!bwdif->cur)
+            return AVERROR(ENOMEM);
+        bwdif->inter_field = 0;
+    }
+
+    if (checkstride(bwdif, bwdif->next, bwdif->cur)) {
+        av_log(ctx, AV_LOG_VERBOSE, "Reallocating frame due to differing stride\n");
+        fixstride(link, bwdif->next);
+    }
+    if (checkstride(bwdif, bwdif->next, bwdif->cur))
+        fixstride(link, bwdif->cur);
+    if (bwdif->prev && checkstride(bwdif, bwdif->next, bwdif->prev))
+        fixstride(link, bwdif->prev);
+    if (checkstride(bwdif, bwdif->next, bwdif->cur) || (bwdif->prev && checkstride(bwdif, bwdif->next, bwdif->prev))) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to reallocate frame\n");
+        return -1;
+    }
+
+    if (!bwdif->prev)
+        return 0;
+
+    if ((bwdif->deint && !bwdif->cur->interlaced_frame) ||
+        ctx->is_disabled ||
+        (bwdif->deint && !bwdif->prev->interlaced_frame && bwdif->prev->repeat_pict) ||
+        (bwdif->deint && !bwdif->next->interlaced_frame && bwdif->next->repeat_pict)
+    ) {
+        bwdif->out  = av_frame_clone(bwdif->cur);
+        if (!bwdif->out)
+            return AVERROR(ENOMEM);
+
+        av_frame_free(&bwdif->prev);
+        if (bwdif->out->pts != AV_NOPTS_VALUE)
+            bwdif->out->pts *= 2;
+        return ff_filter_frame(ctx->outputs[0], bwdif->out);
+    }
+
+    bwdif->out = ff_get_video_buffer(ctx->outputs[0], link->w, link->h);
+    if (!bwdif->out)
+        return AVERROR(ENOMEM);
+
+    av_frame_copy_props(bwdif->out, bwdif->cur);
+    bwdif->out->interlaced_frame = 0;
+
+    if (bwdif->out->pts != AV_NOPTS_VALUE)
+        bwdif->out->pts *= 2;
+
+    return return_frame(ctx, 0);
+}
+
+static int request_frame(AVFilterLink *link)
+{
+    AVFilterContext *ctx = link->src;
+    BWDIFContext *bwdif = ctx->priv;
+    int ret;
+
+    if (bwdif->frame_pending) {
+        return_frame(ctx, 1);
+        return 0;
+    }
+
+    if (bwdif->eof)
+        return AVERROR_EOF;
+
+    ret  = ff_request_frame(link->src->inputs[0]);
+
+    if (ret == AVERROR_EOF && bwdif->cur) {
+        AVFrame *next = av_frame_clone(bwdif->next);
+
+        if (!next)
+            return AVERROR(ENOMEM);
+
+        bwdif->inter_field = -1;
+        next->pts = bwdif->next->pts * 2 - bwdif->cur->pts;
+
+        filter_frame(link->src->inputs[0], next);
+        bwdif->eof = 1;
+    } else if (ret < 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    BWDIFContext *bwdif = ctx->priv;
+
+    av_frame_free(&bwdif->prev);
+    av_frame_free(&bwdif->cur );
+    av_frame_free(&bwdif->next);
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+    static const enum AVPixelFormat pix_fmts[] = {
+        AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV420P,
+        AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P,
+        AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P,
+        AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P,
+        AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9,
+        AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
+        AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12,
+        AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14,
+        AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16,
+        AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
+        AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9,
+        AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10,
+        AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16,
+        AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
+        AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16,
+        AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP16,
+        AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16,
+        AV_PIX_FMT_NONE
+    };
+
+    AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
+    if (!fmts_list)
+        return AVERROR(ENOMEM);
+
+    return ff_set_common_formats(ctx, fmts_list);
+}
+
+static int config_props(AVFilterLink *link)
+{
+    AVFilterContext *ctx = link->src;
+    BWDIFContext *s = link->src->priv;
+
+    link->time_base.num = link->src->inputs[0]->time_base.num;
+    link->time_base.den = link->src->inputs[0]->time_base.den * 2;
+    link->w             = link->src->inputs[0]->w;
+    link->h             = link->src->inputs[0]->h;
+
+    if(s->mode&1)
+        link->frame_rate = av_mul_q(link->src->inputs[0]->frame_rate, (AVRational){2,1});
+
+    if (link->w < 3 || link->h < 3) {
+        av_log(ctx, AV_LOG_ERROR, "Video of less than 3 columns or lines is not supported\n");
+        return AVERROR(EINVAL);
+    }
+
+    s->csp = av_pix_fmt_desc_get(link->format);
+    if (s->csp->comp[0].depth > 8) {
+        s->filter_intra = filter_intra_16bit;
+        s->filter_line  = filter_line_c_16bit;
+        s->filter_edge  = filter_edge_16bit;
+    } else {
+        s->filter_intra = filter_intra;
+        s->filter_line  = filter_line_c;
+        s->filter_edge  = filter_edge;
+    }
+
+    if (ARCH_X86)
+        ff_bwdif_init_x86(s);
+
+    return 0;
+}
+
+
+#define OFFSET(x) offsetof(BWDIFContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+#define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, INT_MIN, INT_MAX, FLAGS, unit }
+
+static const AVOption bwdif_options[] = {
+    { "mode",   "specify the interlacing mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=BWDIF_MODE_SEND_FIELD}, 0, 1, FLAGS, "mode"},
+    CONST("send_frame", "send one frame for each frame", BWDIF_MODE_SEND_FRAME, "mode"),
+    CONST("send_field", "send one frame for each field", BWDIF_MODE_SEND_FIELD, "mode"),
+
+    { "parity", "specify the assumed picture field parity", OFFSET(parity), AV_OPT_TYPE_INT, {.i64=BWDIF_PARITY_AUTO}, -1, 1, FLAGS, "parity" },
+    CONST("tff",  "assume top field first",    BWDIF_PARITY_TFF,  "parity"),
+    CONST("bff",  "assume bottom field first", BWDIF_PARITY_BFF,  "parity"),
+    CONST("auto", "auto detect parity",        BWDIF_PARITY_AUTO, "parity"),
+
+    { "deint", "specify which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=BWDIF_DEINT_ALL}, 0, 1, FLAGS, "deint" },
+    CONST("all",        "deinterlace all frames",                       BWDIF_DEINT_ALL,        "deint"),
+    CONST("interlaced", "only deinterlace frames marked as interlaced", BWDIF_DEINT_INTERLACED, "deint"),
+
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(bwdif);
+
+static const AVFilterPad avfilter_vf_bwdif_inputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_VIDEO,
+        .filter_frame  = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad avfilter_vf_bwdif_outputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_VIDEO,
+        .request_frame = request_frame,
+        .config_props  = config_props,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_bwdif = {
+    .name          = "bwdif",
+    .description   = NULL_IF_CONFIG_SMALL("Deinterlace the input image."),
+    .priv_size     = sizeof(BWDIFContext),
+    .priv_class    = &bwdif_class,
+    .uninit        = uninit,
+    .query_formats = query_formats,
+    .inputs        = avfilter_vf_bwdif_inputs,
+    .outputs       = avfilter_vf_bwdif_outputs,
+    .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
+};
diff --git a/libavfilter/vf_ciescope.c b/libavfilter/vf_ciescope.c
new file mode 100644
index 0000000..450c17b
--- /dev/null
+++ b/libavfilter/vf_ciescope.c
@@ -0,0 +1,1510 @@
+/*
+ * Copyright (c) 2000 John Walker
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * 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/avassert.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
+#include "libavutil/parseutils.h"
+#include "libavutil/pixdesc.h"
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+enum CieSystem {
+    XYY,
+    UCS,
+    LUV,
+    NB_CIE
+};
+
+enum ColorsSystems {
+    NTSCsystem,
+    EBUsystem,
+    SMPTEsystem,
+    SMPTE240Msystem,
+    APPLEsystem,
+    wRGBsystem,
+    CIE1931system,
+    Rec709system,
+    Rec2020system,
+    NB_CS
+};
+
+typedef struct CiescopeContext {
+    const AVClass *class;
+    int color_system;
+    unsigned gamuts;
+    int size;
+    int show_white;
+    int correct_gamma;
+    int cie;
+    float intensity;
+    float contrast;
+    int background;
+
+    double log2lin[65536];
+    double igamma;
+    double i[3][3];
+    double m[3][3];
+    AVFrame *f;
+    void (*filter)(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y);
+} CiescopeContext;
+
+#define OFFSET(x) offsetof(CiescopeContext, x)
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+
+static const AVOption ciescope_options[] = {
+    { "system",     "set color system", OFFSET(color_system), AV_OPT_TYPE_INT, {.i64=Rec709system}, 0, NB_CS-1, FLAGS, "system" },
+    {   "ntsc",       "NTSC 1953 Y'I'O' (ITU-R BT.470 System M)", 0, AV_OPT_TYPE_CONST, {.i64=NTSCsystem},     0, 0, FLAGS, "system" },
+    {   "470m",       "NTSC 1953 Y'I'O' (ITU-R BT.470 System M)", 0, AV_OPT_TYPE_CONST, {.i64=NTSCsystem},     0, 0, FLAGS, "system" },
+    {   "ebu",        "EBU Y'U'V' (PAL/SECAM) (ITU-R BT.470 System B, G)", 0, AV_OPT_TYPE_CONST, {.i64=EBUsystem},      0, 0, FLAGS, "system" },
+    {   "470bg",      "EBU Y'U'V' (PAL/SECAM) (ITU-R BT.470 System B, G)", 0, AV_OPT_TYPE_CONST, {.i64=EBUsystem},      0, 0, FLAGS, "system" },
+    {   "smpte",      "SMPTE-C RGB",            0, AV_OPT_TYPE_CONST, {.i64=SMPTEsystem},    0, 0, FLAGS, "system" },
+    {   "240m",       "SMPTE-240M Y'PbPr",      0, AV_OPT_TYPE_CONST, {.i64=SMPTE240Msystem},0, 0, FLAGS, "system" },
+    {   "apple",      "Apple RGB",              0, AV_OPT_TYPE_CONST, {.i64=APPLEsystem},    0, 0, FLAGS, "system" },
+    {   "widergb",    "Adobe Wide Gamut RGB",   0, AV_OPT_TYPE_CONST, {.i64=wRGBsystem},     0, 0, FLAGS, "system" },
+    {   "cie1931",    "CIE 1931 RGB",           0, AV_OPT_TYPE_CONST, {.i64=CIE1931system},  0, 0, FLAGS, "system" },
+    {   "hdtv",       "ITU.BT-709 Y'CbCr",      0, AV_OPT_TYPE_CONST, {.i64=Rec709system},   0, 0, FLAGS, "system" },
+    {   "rec709",     "ITU.BT-709 Y'CbCr",      0, AV_OPT_TYPE_CONST, {.i64=Rec709system},   0, 0, FLAGS, "system" },
+    {   "uhdtv",      "ITU-R.BT-2020",          0, AV_OPT_TYPE_CONST, {.i64=Rec2020system},  0, 0, FLAGS, "system" },
+    {   "rec2020",    "ITU-R.BT-2020",          0, AV_OPT_TYPE_CONST, {.i64=Rec2020system},  0, 0, FLAGS, "system" },
+    { "cie",        "set cie system", OFFSET(cie), AV_OPT_TYPE_INT,   {.i64=XYY}, 0, NB_CIE-1, FLAGS, "cie" },
+    {   "xyy",      "CIE 1931 xyY", 0, AV_OPT_TYPE_CONST, {.i64=XYY}, 0, 0, FLAGS, "cie" },
+    {   "ucs",      "CIE 1960 UCS", 0, AV_OPT_TYPE_CONST, {.i64=UCS}, 0, 0, FLAGS, "cie" },
+    {   "luv",      "CIE 1976 Luv", 0, AV_OPT_TYPE_CONST, {.i64=LUV}, 0, 0, FLAGS, "cie" },
+    { "gamuts",     "set what gamuts to draw", OFFSET(gamuts), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, 0xFFF, FLAGS, "gamuts" },
+    {   "ntsc",     NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<NTSCsystem},      0, 0, FLAGS, "gamuts" },
+    {   "470m",     NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<NTSCsystem},      0, 0, FLAGS, "gamuts" },
+    {   "ebu",      NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<EBUsystem},       0, 0, FLAGS, "gamuts" },
+    {   "470bg",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<EBUsystem},       0, 0, FLAGS, "gamuts" },
+    {   "smpte",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<SMPTEsystem},     0, 0, FLAGS, "gamuts" },
+    {   "240m",     NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<SMPTE240Msystem}, 0, 0, FLAGS, "gamuts" },
+    {   "apple",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<APPLEsystem},     0, 0, FLAGS, "gamuts" },
+    {   "widergb",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<wRGBsystem},      0, 0, FLAGS, "gamuts" },
+    {   "cie1931",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<CIE1931system},   0, 0, FLAGS, "gamuts" },
+    {   "hdtv",     NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<Rec709system},    0, 0, FLAGS, "gamuts" },
+    {   "rec709",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<Rec709system},    0, 0, FLAGS, "gamuts" },
+    {   "uhdtv",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<Rec2020system},   0, 0, FLAGS, "gamuts" },
+    {   "rec2020",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=1<<Rec2020system},   0, 0, FLAGS, "gamuts" },
+    { "size",       "set ciescope size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=512}, 256, 8192, FLAGS },
+    { "s",          "set ciescope size", OFFSET(size), AV_OPT_TYPE_INT, {.i64=512}, 256, 8192, FLAGS },
+    { "intensity",  "set ciescope intensity", OFFSET(intensity), AV_OPT_TYPE_FLOAT, {.dbl=0.001}, 0, 1, FLAGS },
+    { "i",          "set ciescope intensity", OFFSET(intensity), AV_OPT_TYPE_FLOAT, {.dbl=0.001}, 0, 1, FLAGS },
+    { "contrast",   NULL, OFFSET(contrast), AV_OPT_TYPE_FLOAT, {.dbl=0.75},  0, 1, FLAGS },
+    { "corrgamma",  NULL, OFFSET(correct_gamma), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
+    { "showwhite",  NULL, OFFSET(show_white), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
+    { "gamma",      NULL, OFFSET(igamma), AV_OPT_TYPE_DOUBLE, {.dbl=2.6}, 0.1, 6, FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(ciescope);
+
+static const enum AVPixelFormat in_pix_fmts[] = {
+    AV_PIX_FMT_RGB24,
+    AV_PIX_FMT_RGBA,
+    AV_PIX_FMT_RGB48,
+    AV_PIX_FMT_RGBA64,
+    AV_PIX_FMT_XYZ12,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_pix_fmts[] = {
+    AV_PIX_FMT_RGBA64,
+    AV_PIX_FMT_NONE
+};
+
+static int query_formats(AVFilterContext *ctx)
+{
+    int ret;
+
+    if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->out_formats)) < 0)
+        return ret;
+
+    if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0)
+        return ret;
+
+    return 0;
+}
+
+static int config_output(AVFilterLink *outlink)
+{
+    CiescopeContext *s = outlink->src->priv;
+
+    outlink->h = outlink->w = s->size;
+    outlink->sample_aspect_ratio = (AVRational){1,1};
+
+    return 0;
+}
+
+/* A  color  system is defined by the CIE x and y  coordinates of its
+   three primary illuminants and the x and y coordinates of the  white
+   point. */
+
+struct ColorSystem {
+    double xRed, yRed,                /* Red primary illuminant */
+           xGreen, yGreen,            /* Green primary illuminant */
+           xBlue, yBlue,              /* Blue primary illuminant */
+           xWhite, yWhite,            /* White point */
+           gamma;             /* gamma of nonlinear correction */
+};
+
+static float const spectral_chromaticity[][3] = {
+    { 0.175560, 0.005294, 0.819146 },
+    { 0.175483, 0.005286, 0.819231 },
+    { 0.175400, 0.005279, 0.819321 },
+    { 0.175317, 0.005271, 0.819412 },
+    { 0.175237, 0.005263, 0.819500 },
+    { 0.175161, 0.005256, 0.819582 },
+    { 0.175088, 0.005247, 0.819665 },
+    { 0.175015, 0.005236, 0.819749 },
+    { 0.174945, 0.005226, 0.819829 },
+    { 0.174880, 0.005221, 0.819899 },
+    { 0.174821, 0.005221, 0.819959 },
+    { 0.174770, 0.005229, 0.820001 },
+    { 0.174722, 0.005238, 0.820040 },
+    { 0.174665, 0.005236, 0.820098 },
+    { 0.174595, 0.005218, 0.820187 },
+    { 0.174510, 0.005182, 0.820309 },
+    { 0.174409, 0.005127, 0.820464 },
+    { 0.174308, 0.005068, 0.820624 },
+    { 0.174222, 0.005017, 0.820761 },
+    { 0.174156, 0.004981, 0.820863 },
+    { 0.174112, 0.004964, 0.820924 },
+    { 0.174088, 0.004964, 0.820948 },
+    { 0.174073, 0.004973, 0.820955 },
+    { 0.174057, 0.004982, 0.820961 },
+    { 0.174036, 0.004986, 0.820978 },
+    { 0.174008, 0.004981, 0.821012 },
+    { 0.173972, 0.004964, 0.821064 },
+    { 0.173932, 0.004943, 0.821125 },
+    { 0.173889, 0.004926, 0.821185 },
+    { 0.173845, 0.004916, 0.821239 },
+    { 0.173801, 0.004915, 0.821284 },
+    { 0.173754, 0.004925, 0.821321 },
+    { 0.173705, 0.004937, 0.821358 },
+    { 0.173655, 0.004944, 0.821401 },
+    { 0.173606, 0.004940, 0.821454 },
+    { 0.173560, 0.004923, 0.821517 },
+    { 0.173514, 0.004895, 0.821590 },
+    { 0.173468, 0.004865, 0.821667 },
+    { 0.173424, 0.004836, 0.821740 },
+    { 0.173380, 0.004813, 0.821807 },
+    { 0.173337, 0.004797, 0.821866 },
+    { 0.173291, 0.004786, 0.821923 },
+    { 0.173238, 0.004779, 0.821983 },
+    { 0.173174, 0.004775, 0.822051 },
+    { 0.173101, 0.004774, 0.822125 },
+    { 0.173021, 0.004775, 0.822204 },
+    { 0.172934, 0.004781, 0.822285 },
+    { 0.172843, 0.004791, 0.822366 },
+    { 0.172751, 0.004799, 0.822450 },
+    { 0.172662, 0.004802, 0.822536 },
+    { 0.172577, 0.004799, 0.822624 },
+    { 0.172489, 0.004795, 0.822715 },
+    { 0.172396, 0.004796, 0.822808 },
+    { 0.172296, 0.004803, 0.822901 },
+    { 0.172192, 0.004815, 0.822993 },
+    { 0.172087, 0.004833, 0.823081 },
+    { 0.171982, 0.004855, 0.823163 },
+    { 0.171871, 0.004889, 0.823240 },
+    { 0.171741, 0.004939, 0.823319 },
+    { 0.171587, 0.005010, 0.823402 },
+    { 0.171407, 0.005102, 0.823490 },
+    { 0.171206, 0.005211, 0.823583 },
+    { 0.170993, 0.005334, 0.823674 },
+    { 0.170771, 0.005470, 0.823759 },
+    { 0.170541, 0.005621, 0.823838 },
+    { 0.170301, 0.005789, 0.823911 },
+    { 0.170050, 0.005974, 0.823976 },
+    { 0.169786, 0.006177, 0.824037 },
+    { 0.169505, 0.006398, 0.824097 },
+    { 0.169203, 0.006639, 0.824158 },
+    { 0.168878, 0.006900, 0.824222 },
+    { 0.168525, 0.007184, 0.824291 },
+    { 0.168146, 0.007491, 0.824363 },
+    { 0.167746, 0.007821, 0.824433 },
+    { 0.167328, 0.008175, 0.824496 },
+    { 0.166895, 0.008556, 0.824549 },
+    { 0.166446, 0.008964, 0.824589 },
+    { 0.165977, 0.009402, 0.824622 },
+    { 0.165483, 0.009865, 0.824652 },
+    { 0.164963, 0.010351, 0.824687 },
+    { 0.164412, 0.010858, 0.824731 },
+    { 0.163828, 0.011385, 0.824787 },
+    { 0.163210, 0.011937, 0.824853 },
+    { 0.162552, 0.012520, 0.824928 },
+    { 0.161851, 0.013137, 0.825011 },
+    { 0.161105, 0.013793, 0.825102 },
+    { 0.160310, 0.014491, 0.825199 },
+    { 0.159466, 0.015232, 0.825302 },
+    { 0.158573, 0.016015, 0.825412 },
+    { 0.157631, 0.016840, 0.825529 },
+    { 0.156641, 0.017705, 0.825654 },
+    { 0.155605, 0.018609, 0.825786 },
+    { 0.154525, 0.019556, 0.825920 },
+    { 0.153397, 0.020554, 0.826049 },
+    { 0.152219, 0.021612, 0.826169 },
+    { 0.150985, 0.022740, 0.826274 },
+    { 0.149691, 0.023950, 0.826359 },
+    { 0.148337, 0.025247, 0.826416 },
+    { 0.146928, 0.026635, 0.826437 },
+    { 0.145468, 0.028118, 0.826413 },
+    { 0.143960, 0.029703, 0.826337 },
+    { 0.142405, 0.031394, 0.826201 },
+    { 0.140796, 0.033213, 0.825991 },
+    { 0.139121, 0.035201, 0.825679 },
+    { 0.137364, 0.037403, 0.825233 },
+    { 0.135503, 0.039879, 0.824618 },
+    { 0.133509, 0.042692, 0.823798 },
+    { 0.131371, 0.045876, 0.822753 },
+    { 0.129086, 0.049450, 0.821464 },
+    { 0.126662, 0.053426, 0.819912 },
+    { 0.124118, 0.057803, 0.818079 },
+    { 0.121469, 0.062588, 0.815944 },
+    { 0.118701, 0.067830, 0.813468 },
+    { 0.115807, 0.073581, 0.810612 },
+    { 0.112776, 0.079896, 0.807328 },
+    { 0.109594, 0.086843, 0.803563 },
+    { 0.106261, 0.094486, 0.799253 },
+    { 0.102776, 0.102864, 0.794360 },
+    { 0.099128, 0.112007, 0.788865 },
+    { 0.095304, 0.121945, 0.782751 },
+    { 0.091294, 0.132702, 0.776004 },
+    { 0.087082, 0.144317, 0.768601 },
+    { 0.082680, 0.156866, 0.760455 },
+    { 0.078116, 0.170420, 0.751464 },
+    { 0.073437, 0.185032, 0.741531 },
+    { 0.068706, 0.200723, 0.730571 },
+    { 0.063993, 0.217468, 0.718539 },
+    { 0.059316, 0.235254, 0.705430 },
+    { 0.054667, 0.254096, 0.691238 },
+    { 0.050031, 0.274002, 0.675967 },
+    { 0.045391, 0.294976, 0.659633 },
+    { 0.040757, 0.316981, 0.642262 },
+    { 0.036195, 0.339900, 0.623905 },
+    { 0.031756, 0.363598, 0.604646 },
+    { 0.027494, 0.387921, 0.584584 },
+    { 0.023460, 0.412703, 0.563837 },
+    { 0.019705, 0.437756, 0.542539 },
+    { 0.016268, 0.462955, 0.520777 },
+    { 0.013183, 0.488207, 0.498610 },
+    { 0.010476, 0.513404, 0.476120 },
+    { 0.008168, 0.538423, 0.453409 },
+    { 0.006285, 0.563068, 0.430647 },
+    { 0.004875, 0.587116, 0.408008 },
+    { 0.003982, 0.610447, 0.385570 },
+    { 0.003636, 0.633011, 0.363352 },
+    { 0.003859, 0.654823, 0.341318 },
+    { 0.004646, 0.675898, 0.319456 },
+    { 0.006011, 0.696120, 0.297869 },
+    { 0.007988, 0.715342, 0.276670 },
+    { 0.010603, 0.733413, 0.255984 },
+    { 0.013870, 0.750186, 0.235943 },
+    { 0.017766, 0.765612, 0.216622 },
+    { 0.022244, 0.779630, 0.198126 },
+    { 0.027273, 0.792104, 0.180623 },
+    { 0.032820, 0.802926, 0.164254 },
+    { 0.038852, 0.812016, 0.149132 },
+    { 0.045328, 0.819391, 0.135281 },
+    { 0.052177, 0.825164, 0.122660 },
+    { 0.059326, 0.829426, 0.111249 },
+    { 0.066716, 0.832274, 0.101010 },
+    { 0.074302, 0.833803, 0.091894 },
+    { 0.082053, 0.834090, 0.083856 },
+    { 0.089942, 0.833289, 0.076769 },
+    { 0.097940, 0.831593, 0.070468 },
+    { 0.106021, 0.829178, 0.064801 },
+    { 0.114161, 0.826207, 0.059632 },
+    { 0.122347, 0.822770, 0.054882 },
+    { 0.130546, 0.818928, 0.050526 },
+    { 0.138702, 0.814774, 0.046523 },
+    { 0.146773, 0.810395, 0.042832 },
+    { 0.154722, 0.805864, 0.039414 },
+    { 0.162535, 0.801238, 0.036226 },
+    { 0.170237, 0.796519, 0.033244 },
+    { 0.177850, 0.791687, 0.030464 },
+    { 0.185391, 0.786728, 0.027881 },
+    { 0.192876, 0.781629, 0.025495 },
+    { 0.200309, 0.776399, 0.023292 },
+    { 0.207690, 0.771055, 0.021255 },
+    { 0.215030, 0.765595, 0.019375 },
+    { 0.222337, 0.760020, 0.017643 },
+    { 0.229620, 0.754329, 0.016051 },
+    { 0.236885, 0.748524, 0.014591 },
+    { 0.244133, 0.742614, 0.013253 },
+    { 0.251363, 0.736606, 0.012031 },
+    { 0.258578, 0.730507, 0.010916 },
+    { 0.265775, 0.724324, 0.009901 },
+    { 0.272958, 0.718062, 0.008980 },
+    { 0.280129, 0.711725, 0.008146 },
+    { 0.287292, 0.705316, 0.007391 },
+    { 0.294450, 0.698842, 0.006708 },
+    { 0.301604, 0.692308, 0.006088 },
+    { 0.308760, 0.685712, 0.005528 },
+    { 0.315914, 0.679063, 0.005022 },
+    { 0.323066, 0.672367, 0.004566 },
+    { 0.330216, 0.665628, 0.004156 },
+    { 0.337363, 0.658848, 0.003788 },
+    { 0.344513, 0.652028, 0.003459 },
+    { 0.351664, 0.645172, 0.003163 },
+    { 0.358814, 0.638287, 0.002899 },
+    { 0.365959, 0.631379, 0.002662 },
+    { 0.373102, 0.624451, 0.002448 },
+    { 0.380244, 0.617502, 0.002254 },
+    { 0.387379, 0.610542, 0.002079 },
+    { 0.394507, 0.603571, 0.001922 },
+    { 0.401626, 0.596592, 0.001782 },
+    { 0.408736, 0.589607, 0.001657 },
+    { 0.415836, 0.582618, 0.001546 },
+    { 0.422921, 0.575631, 0.001448 },
+    { 0.429989, 0.568649, 0.001362 },
+    { 0.437036, 0.561676, 0.001288 },
+    { 0.444062, 0.554714, 0.001224 },
+    { 0.451065, 0.547766, 0.001169 },
+    { 0.458041, 0.540837, 0.001123 },
+    { 0.464986, 0.533930, 0.001084 },
+    { 0.471899, 0.527051, 0.001051 },
+    { 0.478775, 0.520202, 0.001023 },
+    { 0.485612, 0.513389, 0.001000 },
+    { 0.492405, 0.506615, 0.000980 },
+    { 0.499151, 0.499887, 0.000962 },
+    { 0.505845, 0.493211, 0.000944 },
+    { 0.512486, 0.486591, 0.000923 },
+    { 0.519073, 0.480029, 0.000899 },
+    { 0.525600, 0.473527, 0.000872 },
+    { 0.532066, 0.467091, 0.000843 },
+    { 0.538463, 0.460725, 0.000812 },
+    { 0.544787, 0.454434, 0.000779 },
+    { 0.551031, 0.448225, 0.000744 },
+    { 0.557193, 0.442099, 0.000708 },
+    { 0.563269, 0.436058, 0.000673 },
+    { 0.569257, 0.430102, 0.000641 },
+    { 0.575151, 0.424232, 0.000616 },
+    { 0.580953, 0.418447, 0.000601 },
+    { 0.586650, 0.412758, 0.000591 },
+    { 0.592225, 0.407190, 0.000586 },
+    { 0.597658, 0.401762, 0.000580 },
+    { 0.602933, 0.396497, 0.000571 },
+    { 0.608035, 0.391409, 0.000556 },
+    { 0.612977, 0.386486, 0.000537 },
+    { 0.617779, 0.381706, 0.000516 },
+    { 0.622459, 0.377047, 0.000493 },
+    { 0.627037, 0.372491, 0.000472 },
+    { 0.631521, 0.368026, 0.000453 },
+    { 0.635900, 0.363665, 0.000435 },
+    { 0.640156, 0.359428, 0.000416 },
+    { 0.644273, 0.355331, 0.000396 },
+    { 0.648233, 0.351395, 0.000372 },
+    { 0.652028, 0.347628, 0.000344 },
+    { 0.655669, 0.344018, 0.000313 },
+    { 0.659166, 0.340553, 0.000281 },
+    { 0.662528, 0.337221, 0.000251 },
+    { 0.665764, 0.334011, 0.000226 },
+    { 0.668874, 0.330919, 0.000207 },
+    { 0.671859, 0.327947, 0.000194 },
+    { 0.674720, 0.325095, 0.000185 },
+    { 0.677459, 0.322362, 0.000179 },
+    { 0.680079, 0.319747, 0.000174 },
+    { 0.682582, 0.317249, 0.000170 },
+    { 0.684971, 0.314863, 0.000167 },
+    { 0.687250, 0.312586, 0.000164 },
+    { 0.689426, 0.310414, 0.000160 },
+    { 0.691504, 0.308342, 0.000154 },
+    { 0.693490, 0.306366, 0.000145 },
+    { 0.695389, 0.304479, 0.000133 },
+    { 0.697206, 0.302675, 0.000119 },
+    { 0.698944, 0.300950, 0.000106 },
+    { 0.700606, 0.299301, 0.000093 },
+    { 0.702193, 0.297725, 0.000083 },
+    { 0.703709, 0.296217, 0.000074 },
+    { 0.705163, 0.294770, 0.000067 },
+    { 0.706563, 0.293376, 0.000061 },
+    { 0.707918, 0.292027, 0.000055 },
+    { 0.709231, 0.290719, 0.000050 },
+    { 0.710500, 0.289453, 0.000047 },
+    { 0.711724, 0.288232, 0.000044 },
+    { 0.712901, 0.287057, 0.000041 },
+    { 0.714032, 0.285929, 0.000040 },
+    { 0.715117, 0.284845, 0.000038 },
+    { 0.716159, 0.283804, 0.000036 },
+    { 0.717159, 0.282806, 0.000035 },
+    { 0.718116, 0.281850, 0.000034 },
+    { 0.719033, 0.280935, 0.000032 },
+    { 0.719912, 0.280058, 0.000030 },
+    { 0.720753, 0.279219, 0.000028 },
+    { 0.721555, 0.278420, 0.000026 },
+    { 0.722315, 0.277662, 0.000023 },
+    { 0.723032, 0.276948, 0.000020 },
+    { 0.723702, 0.276282, 0.000016 },
+    { 0.724328, 0.275660, 0.000012 },
+    { 0.724914, 0.275078, 0.000007 },
+    { 0.725467, 0.274530, 0.000003 },
+    { 0.725992, 0.274008, 0.000000 },
+    { 0.726495, 0.273505, 0.000000 },
+    { 0.726975, 0.273025, 0.000000 },
+    { 0.727432, 0.272568, 0.000000 },
+    { 0.727864, 0.272136, 0.000000 },
+    { 0.728272, 0.271728, 0.000000 },
+    { 0.728656, 0.271344, 0.000000 },
+    { 0.729020, 0.270980, 0.000000 },
+    { 0.729361, 0.270639, 0.000000 },
+    { 0.729678, 0.270322, 0.000000 },
+    { 0.729969, 0.270031, 0.000000 },
+    { 0.730234, 0.269766, 0.000000 },
+    { 0.730474, 0.269526, 0.000000 },
+    { 0.730693, 0.269307, 0.000000 },
+    { 0.730896, 0.269104, 0.000000 },
+    { 0.731089, 0.268911, 0.000000 },
+    { 0.731280, 0.268720, 0.000000 },
+    { 0.731467, 0.268533, 0.000000 },
+    { 0.731650, 0.268350, 0.000000 },
+    { 0.731826, 0.268174, 0.000000 },
+    { 0.731993, 0.268007, 0.000000 },
+    { 0.732150, 0.267850, 0.000000 },
+    { 0.732300, 0.267700, 0.000000 },
+    { 0.732443, 0.267557, 0.000000 },
+    { 0.732581, 0.267419, 0.000000 },
+    { 0.732719, 0.267281, 0.000000 },
+    { 0.732859, 0.267141, 0.000000 },
+    { 0.733000, 0.267000, 0.000000 },
+    { 0.733142, 0.266858, 0.000000 },
+    { 0.733281, 0.266719, 0.000000 },
+    { 0.733417, 0.266583, 0.000000 },
+    { 0.733551, 0.266449, 0.000000 },
+    { 0.733683, 0.266317, 0.000000 },
+    { 0.733813, 0.266187, 0.000000 },
+    { 0.733936, 0.266064, 0.000000 },
+    { 0.734047, 0.265953, 0.000000 },
+    { 0.734143, 0.265857, 0.000000 },
+    { 0.734221, 0.265779, 0.000000 },
+    { 0.734286, 0.265714, 0.000000 },
+    { 0.734341, 0.265659, 0.000000 },
+    { 0.734390, 0.265610, 0.000000 },
+    { 0.734438, 0.265562, 0.000000 },
+    { 0.734482, 0.265518, 0.000000 },
+    { 0.734523, 0.265477, 0.000000 },
+    { 0.734560, 0.265440, 0.000000 },
+    { 0.734592, 0.265408, 0.000000 },
+    { 0.734621, 0.265379, 0.000000 },
+    { 0.734649, 0.265351, 0.000000 },
+    { 0.734673, 0.265327, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+    { 0.734690, 0.265310, 0.000000 },
+};
+
+
+/* Standard white point chromaticities. */
+
+#define C     0.310063, 0.316158
+#define E     1.0/3.0, 1.0/3.0
+#define D50   0.34570, 0.3585
+#define D65   0.312713, 0.329016
+
+/* Gamma of nonlinear correction.
+   See Charles Poynton's ColorFAQ Item 45 and GammaFAQ Item 6 at
+   http://www.inforamp.net/~poynton/ColorFAQ.html
+   http://www.inforamp.net/~poynton/GammaFAQ.html
+*/
+
+#define GAMMA_REC709    0.      /* Rec. 709 */
+
+static const struct ColorSystem color_systems[] = {
+    [NTSCsystem] = {
+        0.67,  0.33,  0.21,  0.71,  0.14,  0.08,
+        C, GAMMA_REC709
+    },
+    [EBUsystem] = {
+        0.64,  0.33,  0.29,  0.60,  0.15,  0.06,
+        D65, GAMMA_REC709
+    },
+    [SMPTEsystem] = {
+        0.630, 0.340, 0.310, 0.595, 0.155, 0.070,
+        D65, GAMMA_REC709
+    },
+    [SMPTE240Msystem] = {
+        0.670, 0.330, 0.210, 0.710, 0.150, 0.060,
+        D65, GAMMA_REC709
+    },
+    [APPLEsystem] = {
+        0.625, 0.340, 0.280, 0.595, 0.115, 0.070,
+        D65, GAMMA_REC709
+    },
+    [wRGBsystem] = {
+        0.7347, 0.2653, 0.1152, 0.8264, 0.1566, 0.0177,
+        D50, GAMMA_REC709
+    },
+    [CIE1931system] = {
+        0.7347, 0.2653, 0.2738, 0.7174, 0.1666, 0.0089,
+        E, GAMMA_REC709
+    },
+    [Rec709system] = {
+        0.64,  0.33,  0.30,  0.60,  0.15,  0.06,
+        D65, GAMMA_REC709
+    },
+    [Rec2020system] = {
+        0.708,  0.292,  0.170,  0.797,  0.131,  0.046,
+        D65, GAMMA_REC709
+    },
+};
+
+/*
+static struct ColorSystem CustomSystem = {
+    "Custom",
+    0.64,  0.33,  0.30,  0.60,  0.15,  0.06,
+    D65, GAMMA_REC709
+};
+*/
+
+static void
+uv_to_xy(double   const u,
+         double   const v,
+         double * const xc,
+         double * const yc)
+{
+/*
+    Given 1970 coordinates u, v, determine 1931 chromaticities x, y
+*/
+    *xc = 3*u / (2*u - 8*v + 4);
+    *yc = 2*v / (2*u - 8*v + 4);
+}
+
+static void
+upvp_to_xy(double   const up,
+           double   const vp,
+           double * const xc,
+           double * const yc)
+{
+/*
+    Given 1976 coordinates u', v', determine 1931 chromaticities x, y
+*/
+    *xc = 9*up / (6*up - 16*vp + 12);
+    *yc = 4*vp / (6*up - 16*vp + 12);
+}
+
+static void
+xy_to_upvp(double xc,
+           double yc,
+           double * const up,
+           double * const vp)
+{
+/*
+    Given 1931 chromaticities x, y, determine 1976 coordinates u', v'
+*/
+    *up = 4*xc / (- 2*xc + 12*yc + 3);
+    *vp = 9*yc / (- 2*xc + 12*yc + 3);
+}
+
+static void
+xy_to_uv(double xc,
+         double yc,
+         double * const u,
+         double * const v)
+{
+/*
+    Given 1931 chromaticities x, y, determine 1960 coordinates u, v
+*/
+    *u = 4*xc / (- 2*xc + 12*yc + 3);
+    *v = 6*yc / (- 2*xc + 12*yc + 3);
+}
+
+static void
+xyz_to_rgb(const double m[3][3],
+           double xc, double yc, double zc,
+           double * const r, double * const g, double * const b)
+{
+    *r = m[0][0]*xc + m[0][1]*yc + m[0][2]*zc;
+    *g = m[1][0]*xc + m[1][1]*yc + m[1][2]*zc;
+    *b = m[2][0]*xc + m[2][1]*yc + m[2][2]*zc;
+}
+
+static void invert_matrix3x3(double in[3][3], double out[3][3])
+{
+    double m00 = in[0][0], m01 = in[0][1], m02 = in[0][2],
+           m10 = in[1][0], m11 = in[1][1], m12 = in[1][2],
+           m20 = in[2][0], m21 = in[2][1], m22 = in[2][2];
+    int i, j;
+    double det;
+
+    out[0][0] =  (m11 * m22 - m21 * m12);
+    out[0][1] = -(m01 * m22 - m21 * m02);
+    out[0][2] =  (m01 * m12 - m11 * m02);
+    out[1][0] = -(m10 * m22 - m20 * m12);
+    out[1][1] =  (m00 * m22 - m20 * m02);
+    out[1][2] = -(m00 * m12 - m10 * m02);
+    out[2][0] =  (m10 * m21 - m20 * m11);
+    out[2][1] = -(m00 * m21 - m20 * m01);
+    out[2][2] =  (m00 * m11 - m10 * m01);
+
+    det = m00 * out[0][0] + m10 * out[0][1] + m20 * out[0][2];
+    det = 1.0 / det;
+
+    for (i = 0; i < 3; i++) {
+        for (j = 0; j < 3; j++)
+            out[i][j] *= det;
+    }
+}
+
+static void get_rgb2xyz_matrix(struct ColorSystem system, double m[3][3])
+{
+    double S[3], X[4], Z[4];
+    int i;
+
+    X[0] = system.xRed   / system.yRed;
+    X[1] = system.xGreen / system.yGreen;
+    X[2] = system.xBlue  / system.yBlue;
+    X[3] = system.xWhite / system.yWhite;
+
+    Z[0] = (1 - system.xRed   - system.yRed)   / system.yRed;
+    Z[1] = (1 - system.xGreen - system.yGreen) / system.yGreen;
+    Z[2] = (1 - system.xBlue  - system.yBlue)  / system.yBlue;
+    Z[3] = (1 - system.xWhite - system.yWhite) / system.yWhite;
+
+    for (i = 0; i < 3; i++) {
+        m[0][i] = X[i];
+        m[1][i] = 1;
+        m[2][i] = Z[i];
+    }
+
+    invert_matrix3x3(m, m);
+
+    for (i = 0; i < 3; i++)
+        S[i] = m[i][0] * X[3] + m[i][1] * 1 + m[i][2] * Z[3];
+
+    for (i = 0; i < 3; i++) {
+        m[0][i] = S[i] * X[i];
+        m[1][i] = S[i] * 1;
+        m[2][i] = S[i] * Z[i];
+    }
+}
+
+static void
+rgb_to_xy(double rc,
+          double gc,
+          double bc,
+          double * const x,
+          double * const y,
+          double * const z,
+          const double m[3][3])
+{
+    double sum;
+
+    *x = m[0][0] * rc + m[0][1] * gc + m[0][2] * bc;
+    *y = m[1][0] * rc + m[1][1] * gc + m[1][2] * bc;
+    *z = m[2][0] * rc + m[2][1] * gc + m[2][2] * bc;
+
+    sum = *x + *y + *z;
+
+    *x = *x / sum;
+    *y = *y / sum;
+}
+
+static int
+constrain_rgb(double * const r,
+              double * const g,
+              double * const b)
+{
+/*----------------------------------------------------------------------------
+    If  the  requested RGB shade contains a negative weight for one of
+    the primaries, it lies outside the color  gamut  accessible  from
+    the  given  triple  of  primaries.  Desaturate it by adding white,
+    equal quantities of R, G, and B, enough to make RGB all positive.
+-----------------------------------------------------------------------------*/
+    double w;
+
+    /* Amount of white needed is w = - min(0, *r, *g, *b) */
+    w = (0 < *r) ? 0 : *r;
+    w = (w < *g) ? w : *g;
+    w = (w < *b) ? w : *b;
+    w = - w;
+
+    /* Add just enough white to make r, g, b all positive. */
+    if (w > 0) {
+        *r += w;  *g += w; *b += w;
+
+        return 1;                     /* Color modified to fit RGB gamut */
+    }
+
+    return 0;                         /* Color within RGB gamut */
+}
+
+static void
+gamma_correct(const struct ColorSystem * const cs,
+              double *                   const c)
+{
+/*----------------------------------------------------------------------------
+    Transform linear RGB values to nonlinear RGB values.
+
+    Rec. 709 is ITU-R Recommendation BT. 709 (1990)
+    ``Basic Parameter Values for the HDTV Standard for the Studio and for
+    International Programme Exchange'', formerly CCIR Rec. 709.
+
+    For details see
+       http://www.inforamp.net/~poynton/ColorFAQ.html
+       http://www.inforamp.net/~poynton/GammaFAQ.html
+-----------------------------------------------------------------------------*/
+    double gamma;
+    double cc;
+
+    gamma = cs->gamma;
+
+    if (gamma == 0.) {
+        /* Rec. 709 gamma correction. */
+        cc = 0.018;
+        if (*c < cc) {
+            *c *= (1.099 * pow(cc, 0.45) - 0.099) / cc;
+        } else {
+            *c = 1.099 * pow(*c, 0.45) - 0.099;
+        }
+    } else {
+    /* Nonlinear color = (Linear color)^(1/gamma) */
+        *c = pow(*c, 1./gamma);
+    }
+}
+
+
+
+static void
+gamma_correct_rgb(const struct ColorSystem * const cs,
+                  double * const r,
+                  double * const g,
+                  double * const b)
+{
+    gamma_correct(cs, r);
+    gamma_correct(cs, g);
+    gamma_correct(cs, b);
+}
+
+/* Sz(X) is the displacement in pixels of a displacement of X normalized
+   distance units.  (A normalized distance unit is 1/512 of the smaller
+   dimension of the canvas)
+*/
+#define Sz(x) (((x) * (int)FFMIN(w, h)) / 512)
+
+static void
+monochrome_color_location(double waveLength, int w, int h,
+                          int cie, int *xP, int *yP)
+{
+    const int ix = waveLength - 360;
+    const double pX = spectral_chromaticity[ix][0];
+    const double pY = spectral_chromaticity[ix][1];
+    const double pZ = spectral_chromaticity[ix][2];
+    const double px = pX / (pX + pY + pZ);
+    const double py = pY / (pX + pY + pZ);
+
+    if (cie == LUV) {
+        double up, vp;
+
+        xy_to_upvp(px, py, &up, &vp);
+        *xP = up * (w - 1);
+        *yP = (h - 1) - vp * (h - 1);
+    } else if (cie == UCS) {
+        double u, v;
+
+        xy_to_uv(px, py, &u, &v);
+        *xP = u * (w - 1);
+        *yP = (h - 1) - v * (h - 1);
+    } else if (cie == XYY) {
+        *xP = px * (w - 1);
+        *yP = (h - 1) - py * (h - 1);
+    } else {
+        av_assert0(0);
+    }
+}
+
+static void
+find_tongue(uint16_t* const pixels,
+            int       const w,
+            int       const linesize,
+            int       const row,
+            int *     const presentP,
+            int *     const leftEdgeP,
+            int *     const rightEdgeP)
+{
+    int i;
+
+    for (i = 0; i < w && pixels[row * linesize + i * 4 + 0] == 0; i++)
+        ;
+
+    if (i >= w) {
+        *presentP = 0;
+    } else {
+        int j;
+        int const leftEdge = i;
+
+        *presentP = 1;
+
+        for (j = w - 1; j >= leftEdge && pixels[row * linesize + j * 4 + 0] == 0; j--)
+            ;
+
+        *rightEdgeP = j;
+        *leftEdgeP = leftEdge;
+    }
+}
+
+static void draw_line(uint16_t *const pixels, int linesize,
+                      int x0, int y0, int x1, int y1,
+                      int w, int h,
+                      const uint16_t *const rgbcolor)
+{
+    int dx  = FFABS(x1 - x0), sx = x0 < x1 ? 1 : -1;
+    int dy  = FFABS(y1 - y0), sy = y0 < y1 ? 1 : -1;
+    int err = (dx > dy ? dx : -dy) / 2, e2;
+
+    for (;;) {
+        pixels[y0 * linesize + x0 * 4 + 0] = rgbcolor[0];
+        pixels[y0 * linesize + x0 * 4 + 1] = rgbcolor[1];
+        pixels[y0 * linesize + x0 * 4 + 2] = rgbcolor[2];
+        pixels[y0 * linesize + x0 * 4 + 3] = rgbcolor[3];
+
+        if (x0 == x1 && y0 == y1)
+            break;
+
+        e2 = err;
+
+        if (e2 >-dx) {
+            err -= dy;
+            x0 += sx;
+        }
+
+        if (e2 < dy) {
+            err += dx;
+            y0 += sy;
+        }
+    }
+}
+
+static void draw_rline(uint16_t *const pixels, int linesize,
+                       int x0, int y0, int x1, int y1,
+                       int w, int h)
+{
+    int dx  = FFABS(x1 - x0), sx = x0 < x1 ? 1 : -1;
+    int dy  = FFABS(y1 - y0), sy = y0 < y1 ? 1 : -1;
+    int err = (dx > dy ? dx : -dy) / 2, e2;
+
+    for (;;) {
+        pixels[y0 * linesize + x0 * 4 + 0] = 65535 - pixels[y0 * linesize + x0 * 4 + 0];
+        pixels[y0 * linesize + x0 * 4 + 1] = 65535 - pixels[y0 * linesize + x0 * 4 + 1];
+        pixels[y0 * linesize + x0 * 4 + 2] = 65535 - pixels[y0 * linesize + x0 * 4 + 2];
+        pixels[y0 * linesize + x0 * 4 + 3] = 65535;
+
+        if (x0 == x1 && y0 == y1)
+            break;
+
+        e2 = err;
+
+        if (e2 >-dx) {
+            err -= dy;
+            x0 += sx;
+        }
+
+        if (e2 < dy) {
+            err += dx;
+            y0 += sy;
+        }
+    }
+}
+
+static void
+tongue_outline(uint16_t* const pixels,
+               int       const linesize,
+               int       const w,
+               int       const h,
+               uint16_t  const maxval,
+               int       const cie)
+{
+    const uint16_t rgbcolor[4] = { maxval, maxval, maxval, maxval };
+    int wavelength;
+    int lx, ly;
+    int fx, fy;
+
+    for (wavelength = 360; wavelength <= 830; wavelength++) {
+        int icx, icy;
+
+        monochrome_color_location(wavelength, w, h, cie,
+                                  &icx, &icy);
+
+        if (wavelength > 360)
+            draw_line(pixels, linesize, lx, ly, icx, icy, w, h, rgbcolor);
+        else {
+            fx = icx;
+            fy = icy;
+        }
+        lx = icx;
+        ly = icy;
+    }
+    draw_line(pixels, linesize, lx, ly, fx, fy, w, h, rgbcolor);
+}
+
+static void
+fill_in_tongue(uint16_t*                  const pixels,
+               int                        const linesize,
+               int                        const w,
+               int                        const h,
+               uint16_t                   const maxval,
+               const struct ColorSystem * const cs,
+               double                     const m[3][3],
+               int                        const cie,
+               int                        const correct_gamma,
+               float                      const contrast)
+{
+    int y;
+
+    /* Scan the image line by line and  fill  the  tongue  outline
+       with the RGB values determined by the color system for the x-y
+       co-ordinates within the tongue.
+    */
+
+    for (y = 0; y < h; ++y) {
+        int  present;  /* There is some tongue on this line */
+        int leftEdge; /* x position of leftmost pixel in tongue on this line */
+        int rightEdge; /* same, but rightmost */
+
+        find_tongue(pixels, w, linesize, y, &present, &leftEdge, &rightEdge);
+
+        if (present) {
+            int x;
+
+            for (x = leftEdge; x <= rightEdge; ++x) {
+                double cx, cy, cz, jr, jg, jb, jmax;
+                int r, g, b, mx = maxval;
+
+                if (cie == LUV) {
+                    double up, vp;
+                    up = ((double) x) / (w - 1);
+                    vp = 1.0 - ((double) y) / (h - 1);
+                    upvp_to_xy(up, vp, &cx, &cy);
+                    cz = 1.0 - (cx + cy);
+                } else if (cie == UCS) {
+                    double u, v;
+                    u = ((double) x) / (w - 1);
+                    v = 1.0 - ((double) y) / (h - 1);
+                    uv_to_xy(u, v, &cx, &cy);
+                    cz = 1.0 - (cx + cy);
+                } else if (cie == XYY) {
+                    cx = ((double) x) / (w - 1);
+                    cy = 1.0 - ((double) y) / (h - 1);
+                    cz = 1.0 - (cx + cy);
+                } else {
+                    av_assert0(0);
+                }
+
+                xyz_to_rgb(m, cx, cy, cz, &jr, &jg, &jb);
+
+                /* Check whether the requested color  is  within  the
+                   gamut  achievable with the given color system.  If
+                   not, draw it in a reduced  intensity,  interpolated
+                   by desaturation to the closest within-gamut color. */
+
+                if (constrain_rgb(&jr, &jg, &jb))
+                    mx *= contrast;
+
+                jmax = FFMAX3(jr, jg, jb);
+                if (jmax > 0) {
+                    jr = jr / jmax;
+                    jg = jg / jmax;
+                    jb = jb / jmax;
+                }
+                /* gamma correct from linear rgb to nonlinear rgb. */
+                if (correct_gamma)
+                    gamma_correct_rgb(cs, &jr, &jg, &jb);
+                r = mx * jr;
+                g = mx * jg;
+                b = mx * jb;
+                pixels[y * linesize + x * 4 + 0] = r;
+                pixels[y * linesize + x * 4 + 1] = g;
+                pixels[y * linesize + x * 4 + 2] = b;
+                pixels[y * linesize + x * 4 + 3] = 65535;
+            }
+        }
+    }
+}
+
+static void
+plot_white_point(uint16_t*      pixels,
+                 int      const linesize,
+                 int      const w,
+                 int      const h,
+                 int      const maxval,
+                 int      const color_system,
+                 int      const cie)
+{
+    const struct ColorSystem *cs = &color_systems[color_system];
+    int wx, wy;
+
+    if (cie == LUV) {
+        double wup, wvp;
+        xy_to_upvp(cs->xWhite, cs->yWhite, &wup, &wvp);
+        wx = wup;
+        wy = wvp;
+        wx = (w - 1) * wup;
+        wy = (h - 1) - ((int) ((h - 1) * wvp));
+    } else if (cie == UCS) {
+        double wu, wv;
+        xy_to_uv(cs->xWhite, cs->yWhite, &wu, &wv);
+        wx = wu;
+        wy = wv;
+        wx = (w - 1) * wu;
+        wy = (h - 1) - ((int) ((h - 1) * wv));
+    } else if (cie == XYY) {
+        wx = (w - 1) * cs->xWhite;
+        wy = (h - 1) - ((int) ((h - 1) * cs->yWhite));
+    } else {
+        av_assert0(0);
+    }
+
+    draw_rline(pixels, linesize,
+               wx + Sz(3), wy, wx + Sz(10), wy,
+               w, h);
+    draw_rline(pixels, linesize,
+               wx - Sz(3), wy, wx - Sz(10), wy,
+               w, h);
+    draw_rline(pixels, linesize,
+               wx, wy + Sz(3), wx, wy + Sz(10),
+               w, h);
+    draw_rline(pixels, linesize,
+               wx, wy - Sz(3), wx, wy - Sz(10),
+               w, h);
+}
+
+static int draw_background(AVFilterContext *ctx)
+{
+    CiescopeContext *s = ctx->priv;
+    const struct ColorSystem *cs = &color_systems[s->color_system];
+    AVFilterLink *outlink = ctx->outputs[0];
+    int w = s->size;
+    int h = s->size;
+    uint16_t *pixels;
+
+    if ((s->f = ff_get_video_buffer(outlink, outlink->w, outlink->h)) == NULL)
+        return AVERROR(ENOMEM);
+    pixels = (uint16_t *)s->f->data[0];
+
+    tongue_outline(pixels, s->f->linesize[0] / 2, w, h, 65535, s->cie);
+
+    fill_in_tongue(pixels, s->f->linesize[0] / 2, w, h, 65535, cs, (const double (*)[3])s->i, s->cie,
+                   s->correct_gamma, s->contrast);
+
+    return 0;
+}
+
+static void filter_rgb48(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y)
+{
+    CiescopeContext *s = ctx->priv;
+    const uint16_t* src = (const uint16_t*)(in->data[0] + in->linesize[0] * y + x * 6);
+    double r = src[0] / 65535.;
+    double g = src[1] / 65535.;
+    double b = src[2] / 65535.;
+    double cz;
+
+    rgb_to_xy(r, g, b, cx, cy, &cz, (const double (*)[3])s->m);
+}
+
+static void filter_rgba64(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y)
+{
+    CiescopeContext *s = ctx->priv;
+    const uint16_t* src = (const uint16_t*)(in->data[0] + in->linesize[0] * y + x * 8);
+    double r = src[0] / 65535.;
+    double g = src[1] / 65535.;
+    double b = src[2] / 65535.;
+    double cz;
+
+    rgb_to_xy(r, g, b, cx, cy, &cz, (const double (*)[3])s->m);
+}
+
+static void filter_rgb24(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y)
+{
+    CiescopeContext *s = ctx->priv;
+    const uint8_t* src = in->data[0] + in->linesize[0] * y + x * 3;
+    double r = src[0] / 255.;
+    double g = src[1] / 255.;
+    double b = src[2] / 255.;
+    double cz;
+
+    rgb_to_xy(r, g, b, cx, cy, &cz, (const double (*)[3])s->m);
+}
+
+static void filter_rgba(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y)
+{
+    CiescopeContext *s = ctx->priv;
+    const uint8_t* src = in->data[0] + in->linesize[0] * y + x * 4;
+    double r = src[0] / 255.;
+    double g = src[1] / 255.;
+    double b = src[2] / 255.;
+    double cz;
+
+    rgb_to_xy(r, g, b, cx, cy, &cz, (const double (*)[3])s->m);
+}
+
+static void filter_xyz(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y)
+{
+    CiescopeContext *s = ctx->priv;
+    const uint16_t* src = (uint16_t *)(in->data[0] + in->linesize[0] * y + x * 6);
+    double lx = s->log2lin[src[0]];
+    double ly = s->log2lin[src[1]];
+    double lz = s->log2lin[src[2]];
+    double sum = lx + ly + lz;
+
+    if (sum == 0)
+        sum = 1;
+    *cx = lx / sum;
+    *cy = ly / sum;
+}
+
+static void plot_gamuts(uint16_t *pixels, int linesize, int w, int h,
+                        int cie, int gamuts)
+{
+    int i;
+
+    for (i = 0; i < NB_CS; i++) {
+        const struct ColorSystem *cs = &color_systems[i];
+        int rx, ry, gx, gy, bx, by;
+
+        if (!((1 << i) & gamuts))
+            continue;
+        if (cie == LUV) {
+            double wup, wvp;
+            xy_to_upvp(cs->xRed, cs->yRed, &wup, &wvp);
+            rx = (w - 1) * wup;
+            ry = (h - 1) - ((int) ((h - 1) * wvp));
+            xy_to_upvp(cs->xGreen, cs->yGreen, &wup, &wvp);
+            gx = (w - 1) * wup;
+            gy = (h - 1) - ((int) ((h - 1) * wvp));
+            xy_to_upvp(cs->xBlue, cs->yBlue, &wup, &wvp);
+            bx = (w - 1) * wup;
+            by = (h - 1) - ((int) ((h - 1) * wvp));
+        } else if (cie == UCS) {
+            double wu, wv;
+            xy_to_uv(cs->xRed, cs->yRed, &wu, &wv);
+            rx = (w - 1) * wu;
+            ry = (h - 1) - ((int) ((h - 1) * wv));
+            xy_to_uv(cs->xGreen, cs->yGreen, &wu, &wv);
+            gx = (w - 1) * wu;
+            gy = (h - 1) - ((int) ((h - 1) * wv));
+            xy_to_uv(cs->xBlue, cs->yBlue, &wu, &wv);
+            bx = (w - 1) * wu;
+            by = (h - 1) - ((int) ((h - 1) * wv));
+        } else if (cie == XYY) {
+            rx = (w - 1) * cs->xRed;
+            ry = (h - 1) - ((int) ((h - 1) * cs->yRed));
+            gx = (w - 1) * cs->xGreen;
+            gy = (h - 1) - ((int) ((h - 1) * cs->yGreen));
+            bx = (w - 1) * cs->xBlue;
+            by = (h - 1) - ((int) ((h - 1) * cs->yBlue));
+        } else {
+            av_assert0(0);
+        }
+
+        draw_rline(pixels, linesize, rx, ry, gx, gy, w, h);
+        draw_rline(pixels, linesize, gx, gy, bx, by, w, h);
+        draw_rline(pixels, linesize, bx, by, rx, ry, w, h);
+    }
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx  = inlink->dst;
+    CiescopeContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    int i = s->intensity * 65535;
+    int w = outlink->w;
+    int h = outlink->h;
+    AVFrame *out;
+    int ret, x, y;
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        av_frame_free(&in);
+        return AVERROR(ENOMEM);
+    }
+    out->pts = in->pts;
+
+    if (!s->background) {
+        ret = draw_background(ctx);
+        if (ret < 0)
+            return ret;
+        s->background = 1;
+    }
+    for (y = 0; y < outlink->h; y++) {
+        memset(out->data[0] + y * out->linesize[0], 0, outlink->w * 8);
+    }
+
+    for (y = 0; y < in->height; y++) {
+        for (x = 0; x < in->width; x++) {
+            double cx, cy;
+            uint16_t *dst;
+            int wx, wy;
+
+            s->filter(ctx, in, &cx, &cy, x, y);
+
+            if (s->cie == LUV) {
+                double up, vp;
+                xy_to_upvp(cx, cy, &up, &vp);
+                cx = up;
+                cy = vp;
+            } else if (s->cie == UCS) {
+                double u, v;
+                xy_to_uv(cx, cy, &u, &v);
+                cx = u;
+                cy = v;
+            }
+
+            wx = (w - 1) * cx;
+            wy = (h - 1) - ((h - 1) * cy);
+
+            if (wx < 0 || wx >= w ||
+                wy < 0 || wy >= h)
+                continue;
+
+            dst = (uint16_t *)(out->data[0] + wy * out->linesize[0] + wx * 8 + 0);
+            dst[0] = FFMIN(dst[0] + i, 65535);
+            dst[1] = FFMIN(dst[1] + i, 65535);
+            dst[2] = FFMIN(dst[2] + i, 65535);
+            dst[3] = 65535;
+        }
+    }
+
+    for (y = 0; y < outlink->h; y++) {
+        uint16_t *dst = (uint16_t *)(out->data[0] + y * out->linesize[0]);
+        const uint16_t *src = (const uint16_t *)(s->f->data[0] + y * s->f->linesize[0]);
+        for (x = 0; x < outlink->w; x++) {
+            const int xx = x * 4;
+            if (dst[xx + 3] == 0) {
+                dst[xx + 0] = src[xx + 0];
+                dst[xx + 1] = src[xx + 1];
+                dst[xx + 2] = src[xx + 2];
+                dst[xx + 3] = src[xx + 3];
+            }
+        }
+    }
+
+    if (s->show_white)
+        plot_white_point((uint16_t *)out->data[0], out->linesize[0] / 2,
+                         outlink->w, outlink->h, 65535,
+                         s->color_system, s->cie);
+
+    plot_gamuts((uint16_t *)out->data[0], out->linesize[0] / 2,
+                outlink->w, outlink->h,
+                s->cie, s->gamuts);
+
+    av_frame_free(&in);
+    return ff_filter_frame(outlink, out);
+}
+
+static void av_cold uninit(AVFilterContext *ctx)
+{
+    CiescopeContext *s = ctx->priv;
+
+    av_frame_free(&s->f);
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+    CiescopeContext *s = inlink->dst->priv;
+    int i;
+
+    get_rgb2xyz_matrix(color_systems[s->color_system], s->m);
+    invert_matrix3x3(s->m, s->i);
+
+    switch (inlink->format) {
+    case AV_PIX_FMT_RGB24:
+        s->filter = filter_rgb24;
+        break;
+    case AV_PIX_FMT_RGBA:
+        s->filter = filter_rgba;
+        break;
+    case AV_PIX_FMT_RGB48:
+        s->filter = filter_rgb48;
+        break;
+    case AV_PIX_FMT_RGBA64:
+        s->filter = filter_rgba64;
+        break;
+    case AV_PIX_FMT_XYZ12:
+        s->filter = filter_xyz;
+        for (i = 0; i < 65536; i++)
+            s->log2lin[i] = pow(i / 65535., s->igamma) * 65535.;
+        break;
+    default:
+        av_assert0(0);
+    }
+
+    return 0;
+}
+
+static const AVFilterPad inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+        .config_props = config_input,
+    },
+    { NULL }
+};
+
+static const AVFilterPad outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = config_output,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_ciescope = {
+    .name          = "ciescope",
+    .description   = NULL_IF_CONFIG_SMALL("Video CIE scope."),
+    .priv_size     = sizeof(CiescopeContext),
+    .priv_class    = &ciescope_class,
+    .query_formats = query_formats,
+    .uninit        = uninit,
+    .inputs        = inputs,
+    .outputs       = outputs,
+};
diff --git a/libavfilter/vf_codecview.c b/libavfilter/vf_codecview.c
index e70b397..dc33973 100644
--- a/libavfilter/vf_codecview.c
+++ b/libavfilter/vf_codecview.c
@@ -38,22 +38,40 @@
 #define MV_P_FOR  (1<<0)
 #define MV_B_FOR  (1<<1)
 #define MV_B_BACK (1<<2)
+#define MV_TYPE_FOR  (1<<0)
+#define MV_TYPE_BACK (1<<1)
+#define FRAME_TYPE_I (1<<0)
+#define FRAME_TYPE_P (1<<1)
+#define FRAME_TYPE_B (1<<2)
 
 typedef struct {
     const AVClass *class;
     unsigned mv;
+    unsigned frame_type;
+    unsigned mv_type;
     int hsub, vsub;
     int qp;
 } CodecViewContext;
 
 #define OFFSET(x) offsetof(CodecViewContext, x)
 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+#define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, 0, 0, FLAGS, unit }
+
 static const AVOption codecview_options[] = {
     { "mv", "set motion vectors to visualize", OFFSET(mv), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "mv" },
-        {"pf", "forward predicted MVs of P-frames",  0, AV_OPT_TYPE_CONST, {.i64 = MV_P_FOR },  INT_MIN, INT_MAX, FLAGS, "mv"},
-        {"bf", "forward predicted MVs of B-frames",  0, AV_OPT_TYPE_CONST, {.i64 = MV_B_FOR },  INT_MIN, INT_MAX, FLAGS, "mv"},
-        {"bb", "backward predicted MVs of B-frames", 0, AV_OPT_TYPE_CONST, {.i64 = MV_B_BACK }, INT_MIN, INT_MAX, FLAGS, "mv"},
+        CONST("pf", "forward predicted MVs of P-frames",  MV_P_FOR,  "mv"),
+        CONST("bf", "forward predicted MVs of B-frames",  MV_B_FOR,  "mv"),
+        CONST("bb", "backward predicted MVs of B-frames", MV_B_BACK, "mv"),
     { "qp", NULL, OFFSET(qp), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
+    { "mv_type", "set motion vectors type", OFFSET(mv_type), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "mv_type" },
+    { "mvt",     "set motion vectors type", OFFSET(mv_type), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "mv_type" },
+        CONST("fp", "forward predicted MVs",  MV_TYPE_FOR,  "mv_type"),
+        CONST("bp", "backward predicted MVs", MV_TYPE_BACK, "mv_type"),
+    { "frame_type", "set frame types to visualize motion vectors of", OFFSET(frame_type), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "frame_type" },
+    { "ft",         "set frame types to visualize motion vectors of", OFFSET(frame_type), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "frame_type" },
+        CONST("if", "I-frames", FRAME_TYPE_I, "frame_type"),
+        CONST("pf", "P-frames", FRAME_TYPE_P, "frame_type"),
+        CONST("bf", "B-frames", FRAME_TYPE_B, "frame_type"),
     { NULL }
 };
 
@@ -224,20 +242,37 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
         }
     }
 
-    if (s->mv) {
+    if (s->mv || s->mv_type) {
         AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MOTION_VECTORS);
         if (sd) {
             int i;
             const AVMotionVector *mvs = (const AVMotionVector *)sd->data;
+            const int is_iframe = (s->frame_type & FRAME_TYPE_I) && frame->pict_type == AV_PICTURE_TYPE_I;
+            const int is_pframe = (s->frame_type & FRAME_TYPE_P) && frame->pict_type == AV_PICTURE_TYPE_P;
+            const int is_bframe = (s->frame_type & FRAME_TYPE_B) && frame->pict_type == AV_PICTURE_TYPE_B;
+
             for (i = 0; i < sd->size / sizeof(*mvs); i++) {
                 const AVMotionVector *mv = &mvs[i];
                 const int direction = mv->source > 0;
-                if ((direction == 0 && (s->mv & MV_P_FOR)  && frame->pict_type == AV_PICTURE_TYPE_P) ||
-                    (direction == 0 && (s->mv & MV_B_FOR)  && frame->pict_type == AV_PICTURE_TYPE_B) ||
-                    (direction == 1 && (s->mv & MV_B_BACK) && frame->pict_type == AV_PICTURE_TYPE_B))
-                    draw_arrow(frame->data[0], mv->dst_x, mv->dst_y, mv->src_x, mv->src_y,
-                               frame->width, frame->height, frame->linesize[0],
-                               100, 0, mv->source > 0);
+
+                if (s->mv_type) {
+                    const int is_fp = direction == 0 && (s->mv_type & MV_TYPE_FOR);
+                    const int is_bp = direction == 1 && (s->mv_type & MV_TYPE_BACK);
+
+                    if ((!s->frame_type && (is_fp || is_bp)) ||
+                        is_iframe && is_fp || is_iframe && is_bp ||
+                        is_pframe && is_fp ||
+                        is_bframe && is_fp || is_bframe && is_bp)
+                        draw_arrow(frame->data[0], mv->dst_x, mv->dst_y, mv->src_x, mv->src_y,
+                                   frame->width, frame->height, frame->linesize[0],
+                                   100, 0, direction);
+                } else if (s->mv)
+                    if ((direction == 0 && (s->mv & MV_P_FOR)  && frame->pict_type == AV_PICTURE_TYPE_P) ||
+                        (direction == 0 && (s->mv & MV_B_FOR)  && frame->pict_type == AV_PICTURE_TYPE_B) ||
+                        (direction == 1 && (s->mv & MV_B_BACK) && frame->pict_type == AV_PICTURE_TYPE_B))
+                        draw_arrow(frame->data[0], mv->dst_x, mv->dst_y, mv->src_x, mv->src_y,
+                                   frame->width, frame->height, frame->linesize[0],
+                                   100, 0, direction);
             }
         }
     }
diff --git a/libavfilter/vf_colormatrix.c b/libavfilter/vf_colormatrix.c
index 4a57fe0..15fb680 100644
--- a/libavfilter/vf_colormatrix.c
+++ b/libavfilter/vf_colormatrix.c
@@ -40,19 +40,12 @@
 #define NS(n) ((n) < 0 ? (int)((n)*65536.0-0.5+DBL_EPSILON) : (int)((n)*65536.0+0.5))
 #define CB(n) av_clip_uint8(n)
 
-static const double yuv_coeff[4][3][3] = {
-    { { +0.7152, +0.0722, +0.2126 }, // Rec.709 (0)
-      { -0.3850, +0.5000, -0.1150 },
-      { -0.4540, -0.0460, +0.5000 } },
-    { { +0.5900, +0.1100, +0.3000 }, // FCC (1)
-      { -0.3310, +0.5000, -0.1690 },
-      { -0.4210, -0.0790, +0.5000 } },
-    { { +0.5870, +0.1140, +0.2990 }, // Rec.601 (ITU-R BT.470-2/SMPTE 170M) (2)
-      { -0.3313, +0.5000, -0.1687 },
-      { -0.4187, -0.0813, +0.5000 } },
-    { { +0.7010, +0.0870, +0.2120 }, // SMPTE 240M (3)
-      { -0.3840, +0.5000, -0.1160 },
-      { -0.4450, -0.0550, +0.5000 } },
+static const double yuv_coeff_luma[5][3] = {
+    { +0.7152, +0.0722, +0.2126 }, // Rec.709 (0)
+    { +0.5900, +0.1100, +0.3000 }, // FCC (1)
+    { +0.5870, +0.1140, +0.2990 }, // Rec.601 (ITU-R BT.470-2/SMPTE 170M) (2)
+    { +0.7010, +0.0870, +0.2120 }, // SMPTE 240M (3)
+    { +0.6780, +0.0593, +0.2627 }, // Rec.2020 (4)
 };
 
 enum ColorMode {
@@ -61,12 +54,13 @@ enum ColorMode {
     COLOR_MODE_FCC,
     COLOR_MODE_BT601,
     COLOR_MODE_SMPTE240M,
+    COLOR_MODE_BT2020,
     COLOR_MODE_COUNT
 };
 
 typedef struct {
     const AVClass *class;
-    int yuv_convert[16][3][3];
+    int yuv_convert[25][3][3];
     int interlaced;
     int source, dest;        ///< ColorMode
     int mode;
@@ -97,6 +91,7 @@ static const AVOption colormatrix_options[] = {
     { "bt470bg",   "set BT.470 colorspace",      0, AV_OPT_TYPE_CONST, {.i64=COLOR_MODE_BT601},       .flags=FLAGS, .unit="color_mode" },
     { "smpte170m", "set SMTPE-170M colorspace",  0, AV_OPT_TYPE_CONST, {.i64=COLOR_MODE_BT601},       .flags=FLAGS, .unit="color_mode" },
     { "smpte240m", "set SMPTE-240M colorspace",  0, AV_OPT_TYPE_CONST, {.i64=COLOR_MODE_SMPTE240M},   .flags=FLAGS, .unit="color_mode" },
+    { "bt2020",    "set BT.2020 colorspace",     0, AV_OPT_TYPE_CONST, {.i64=COLOR_MODE_BT2020},      .flags=FLAGS, .unit="color_mode" },
     { NULL }
 };
 
@@ -122,7 +117,7 @@ AVFILTER_DEFINE_CLASS(colormatrix);
 #define imh im[2][1]
 #define imi im[2][2]
 
-static void inverse3x3(double im[3][3], const double m[3][3])
+static void inverse3x3(double im[3][3], double m[3][3])
 {
     double det = ma * (me * mi - mf * mh) - mb * (md * mi - mf * mg) + mc * (md * mh - me * mg);
     det = 1.0 / det;
@@ -137,7 +132,7 @@ static void inverse3x3(double im[3][3], const double m[3][3])
     imi = det * (ma * me - mb * md);
 }
 
-static void solve_coefficients(double cm[3][3], double rgb[3][3], const double yuv[3][3])
+static void solve_coefficients(double cm[3][3], double rgb[3][3], double yuv[3][3])
 {
     int i, j;
     for (i = 0; i < 3; i++)
@@ -148,15 +143,29 @@ static void solve_coefficients(double cm[3][3], double rgb[3][3], const double y
 static void calc_coefficients(AVFilterContext *ctx)
 {
     ColorMatrixContext *color = ctx->priv;
-    double rgb_coeffd[4][3][3];
-    double yuv_convertd[16][3][3];
+    double yuv_coeff[5][3][3];
+    double rgb_coeffd[5][3][3];
+    double yuv_convertd[25][3][3];
+    double bscale, rscale;
     int v = 0;
     int i, j, k;
-
-    for (i = 0; i < 4; i++)
+    for (i = 0; i < 5; i++) {
+        yuv_coeff[i][0][0] = yuv_coeff_luma[i][0];
+        yuv_coeff[i][0][1] = yuv_coeff_luma[i][1];
+        yuv_coeff[i][0][2] = yuv_coeff_luma[i][2];
+        bscale = 0.5 / (yuv_coeff[i][0][1] - 1.0);
+        rscale = 0.5 / (yuv_coeff[i][0][2] - 1.0);
+        yuv_coeff[i][1][0] = bscale * yuv_coeff[i][0][0];
+        yuv_coeff[i][1][1] = 0.5;
+        yuv_coeff[i][1][2] = bscale * yuv_coeff[i][0][2];
+        yuv_coeff[i][2][0] = rscale * yuv_coeff[i][0][0];
+        yuv_coeff[i][2][1] = rscale * yuv_coeff[i][0][1];
+        yuv_coeff[i][2][2] = 0.5;
+    }
+    for (i = 0; i < 5; i++)
         inverse3x3(rgb_coeffd[i], yuv_coeff[i]);
-    for (i = 0; i < 4; i++) {
-        for (j = 0; j < 4; j++) {
+    for (i = 0; i < 5; i++) {
+        for (j = 0; j < 5; j++) {
             solve_coefficients(yuv_convertd[v], rgb_coeffd[i], yuv_coeff[j]);
             for (k = 0; k < 3; k++) {
                 color->yuv_convert[v][k][0] = NS(yuv_convertd[v][k][0]);
@@ -172,7 +181,7 @@ static void calc_coefficients(AVFilterContext *ctx)
     }
 }
 
-static const char * const color_modes[] = {"bt709", "fcc", "bt601", "smpte240m"};
+static const char * const color_modes[] = {"bt709", "fcc", "bt601", "smpte240m", "bt2020"};
 
 static av_cold int init(AVFilterContext *ctx)
 {
@@ -435,20 +444,23 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
         case AVCOL_SPC_SMPTE240M : source = COLOR_MODE_SMPTE240M ; break;
         case AVCOL_SPC_BT470BG   : source = COLOR_MODE_BT601     ; break;
         case AVCOL_SPC_SMPTE170M : source = COLOR_MODE_BT601     ; break;
+        case AVCOL_SPC_BT2020_NCL: source = COLOR_MODE_BT2020    ; break;
+        case AVCOL_SPC_BT2020_CL : source = COLOR_MODE_BT2020    ; break;
         default :
             av_log(ctx, AV_LOG_ERROR, "Input frame does not specify a supported colorspace, and none has been specified as source either\n");
             av_frame_free(&out);
             return AVERROR(EINVAL);
         }
-        color->mode = source * 4 + color->dest;
+        color->mode = source * 5 + color->dest;
     } else
-        color->mode = color->source * 4 + color->dest;
+        color->mode = color->source * 5 + color->dest;
 
     switch(color->dest) {
-    case COLOR_MODE_BT709    : av_frame_set_colorspace(out, AVCOL_SPC_BT709)    ; break;
-    case COLOR_MODE_FCC      : av_frame_set_colorspace(out, AVCOL_SPC_FCC)      ; break;
-    case COLOR_MODE_SMPTE240M: av_frame_set_colorspace(out, AVCOL_SPC_SMPTE240M); break;
-    case COLOR_MODE_BT601    : av_frame_set_colorspace(out, AVCOL_SPC_BT470BG)  ; break;
+    case COLOR_MODE_BT709    : av_frame_set_colorspace(out, AVCOL_SPC_BT709)     ; break;
+    case COLOR_MODE_FCC      : av_frame_set_colorspace(out, AVCOL_SPC_FCC)       ; break;
+    case COLOR_MODE_SMPTE240M: av_frame_set_colorspace(out, AVCOL_SPC_SMPTE240M) ; break;
+    case COLOR_MODE_BT601    : av_frame_set_colorspace(out, AVCOL_SPC_BT470BG)   ; break;
+    case COLOR_MODE_BT2020   : av_frame_set_colorspace(out, AVCOL_SPC_BT2020_NCL); break;
     }
 
     td.src = in;
diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c
new file mode 100644
index 0000000..3d39f13
--- /dev/null
+++ b/libavfilter/vf_colorspace.c
@@ -0,0 +1,1110 @@
+/*
+ * Copyright (c) 2016 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * 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
+ * Convert between colorspaces.
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/pixfmt.h"
+
+#include "avfilter.h"
+#include "colorspacedsp.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+enum DitherMode {
+    DITHER_NONE,
+    DITHER_FSB,
+    DITHER_NB,
+};
+
+enum Colorspace {
+    CS_UNSPECIFIED,
+    CS_BT470M,
+    CS_BT470BG,
+    CS_BT601_6_525,
+    CS_BT601_6_625,
+    CS_BT709,
+    CS_SMPTE170M,
+    CS_SMPTE240M,
+    CS_BT2020,
+    CS_NB,
+};
+
+enum Whitepoint {
+    WP_D65,
+    WP_C,
+    WP_NB,
+};
+
+enum WhitepointAdaptation {
+    WP_ADAPT_BRADFORD,
+    WP_ADAPT_VON_KRIES,
+    NB_WP_ADAPT_NON_IDENTITY,
+    WP_ADAPT_IDENTITY = NB_WP_ADAPT_NON_IDENTITY,
+    NB_WP_ADAPT,
+};
+
+static const enum AVColorTransferCharacteristic default_trc[CS_NB + 1] = {
+    [CS_UNSPECIFIED] = AVCOL_TRC_UNSPECIFIED,
+    [CS_BT470M]      = AVCOL_TRC_GAMMA22,
+    [CS_BT470BG]     = AVCOL_TRC_GAMMA28,
+    [CS_BT601_6_525] = AVCOL_TRC_SMPTE170M,
+    [CS_BT601_6_625] = AVCOL_TRC_SMPTE170M,
+    [CS_BT709]       = AVCOL_TRC_BT709,
+    [CS_SMPTE170M]   = AVCOL_TRC_SMPTE170M,
+    [CS_SMPTE240M]   = AVCOL_TRC_SMPTE240M,
+    [CS_BT2020]      = AVCOL_TRC_BT2020_10,
+    [CS_NB]          = AVCOL_TRC_UNSPECIFIED,
+};
+
+static const enum AVColorPrimaries default_prm[CS_NB + 1] = {
+    [CS_UNSPECIFIED] = AVCOL_PRI_UNSPECIFIED,
+    [CS_BT470M]      = AVCOL_PRI_BT470M,
+    [CS_BT470BG]     = AVCOL_PRI_BT470BG,
+    [CS_BT601_6_525] = AVCOL_PRI_SMPTE170M,
+    [CS_BT601_6_625] = AVCOL_PRI_BT470BG,
+    [CS_BT709]       = AVCOL_PRI_BT709,
+    [CS_SMPTE170M]   = AVCOL_PRI_SMPTE170M,
+    [CS_SMPTE240M]   = AVCOL_PRI_SMPTE240M,
+    [CS_BT2020]      = AVCOL_PRI_BT2020,
+    [CS_NB]          = AVCOL_PRI_UNSPECIFIED,
+};
+
+static const enum AVColorSpace default_csp[CS_NB + 1] = {
+    [CS_UNSPECIFIED] = AVCOL_SPC_UNSPECIFIED,
+    [CS_BT470M]      = AVCOL_SPC_SMPTE170M,
+    [CS_BT470BG]     = AVCOL_SPC_BT470BG,
+    [CS_BT601_6_525] = AVCOL_SPC_SMPTE170M,
+    [CS_BT601_6_625] = AVCOL_SPC_BT470BG,
+    [CS_BT709]       = AVCOL_SPC_BT709,
+    [CS_SMPTE170M]   = AVCOL_SPC_SMPTE170M,
+    [CS_SMPTE240M]   = AVCOL_SPC_SMPTE240M,
+    [CS_BT2020]      = AVCOL_SPC_BT2020_NCL,
+    [CS_NB]          = AVCOL_SPC_UNSPECIFIED,
+};
+
+struct ColorPrimaries {
+    enum Whitepoint wp;
+    double xr, yr, xg, yg, xb, yb;
+};
+
+struct TransferCharacteristics {
+    double alpha, beta, gamma, delta;
+};
+
+struct LumaCoefficients {
+    double cr, cg, cb;
+};
+
+struct WhitepointCoefficients {
+    double xw, yw;
+};
+
+typedef struct ColorSpaceContext {
+    const AVClass *class;
+
+    ColorSpaceDSPContext dsp;
+
+    enum Colorspace user_all;
+    enum AVColorSpace in_csp, out_csp, user_csp;
+    enum AVColorRange in_rng, out_rng, user_rng;
+    enum AVColorTransferCharacteristic in_trc, out_trc, user_trc;
+    enum AVColorPrimaries in_prm, out_prm, user_prm;
+    enum AVPixelFormat in_format, user_format;
+    int fast_mode;
+    enum DitherMode dither;
+    enum WhitepointAdaptation wp_adapt;
+
+    int16_t *rgb[3];
+    ptrdiff_t rgb_stride;
+    unsigned rgb_sz;
+    int *dither_scratch[3][2], *dither_scratch_base[3][2];
+
+    const struct ColorPrimaries *in_primaries, *out_primaries;
+    int lrgb2lrgb_passthrough;
+    DECLARE_ALIGNED(16, int16_t, lrgb2lrgb_coeffs)[3][3][8];
+
+    const struct TransferCharacteristics *in_txchr, *out_txchr;
+    int rgb2rgb_passthrough;
+    int16_t *lin_lut, *delin_lut;
+
+    const struct LumaCoefficients *in_lumacoef, *out_lumacoef;
+    int yuv2yuv_passthrough, yuv2yuv_fastmode;
+    DECLARE_ALIGNED(16, int16_t, yuv2rgb_coeffs)[3][3][8];
+    DECLARE_ALIGNED(16, int16_t, rgb2yuv_coeffs)[3][3][8];
+    DECLARE_ALIGNED(16, int16_t, yuv2yuv_coeffs)[3][3][8];
+    DECLARE_ALIGNED(16, int16_t, yuv_offset)[2 /* in, out */][8];
+    yuv2rgb_fn yuv2rgb;
+    rgb2yuv_fn rgb2yuv;
+    rgb2yuv_fsb_fn rgb2yuv_fsb;
+    yuv2yuv_fn yuv2yuv;
+    double yuv2rgb_dbl_coeffs[3][3], rgb2yuv_dbl_coeffs[3][3];
+    int in_y_rng, in_uv_rng, out_y_rng, out_uv_rng;
+} ColorSpaceContext;
+
+// FIXME deal with odd width/heights (or just forbid it)
+// FIXME faster linearize/delinearize implementation (integer pow)
+// FIXME bt2020cl support (linearization between yuv/rgb step instead of between rgb/xyz)
+// FIXME test that the values in (de)lin_lut don't exceed their container storage
+// type size (only useful if we keep the LUT and don't move to fast integer pow)
+// FIXME dithering if bitdepth goes down?
+// FIXME bitexact for fate integration?
+
+/*
+ * All constants explained in e.g. https://linuxtv.org/downloads/v4l-dvb-apis/ch02s06.html
+ * The older ones (bt470bg/m) are also explained in their respective ITU docs
+ * (e.g. https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.470-5-199802-S!!PDF-E.pdf)
+ * whereas the newer ones can typically be copied directly from wikipedia :)
+ */
+static const struct LumaCoefficients luma_coefficients[AVCOL_SPC_NB] = {
+    [AVCOL_SPC_FCC]        = { 0.30,   0.59,   0.11   },
+    [AVCOL_SPC_BT470BG]    = { 0.299,  0.587,  0.114  },
+    [AVCOL_SPC_SMPTE170M]  = { 0.299,  0.587,  0.114  },
+    [AVCOL_SPC_BT709]      = { 0.2126, 0.7152, 0.0722 },
+    [AVCOL_SPC_SMPTE240M]  = { 0.212,  0.701,  0.087  },
+    [AVCOL_SPC_BT2020_NCL] = { 0.2627, 0.6780, 0.0593 },
+    [AVCOL_SPC_BT2020_CL]  = { 0.2627, 0.6780, 0.0593 },
+};
+
+static const struct LumaCoefficients *get_luma_coefficients(enum AVColorSpace csp)
+{
+    const struct LumaCoefficients *coeffs;
+
+    if (csp >= AVCOL_SPC_NB)
+        return NULL;
+    coeffs = &luma_coefficients[csp];
+    if (!coeffs->cr)
+        return NULL;
+
+    return coeffs;
+}
+
+static void fill_rgb2yuv_table(const struct LumaCoefficients *coeffs,
+                               double rgb2yuv[3][3])
+{
+    double bscale, rscale;
+
+    rgb2yuv[0][0] = coeffs->cr;
+    rgb2yuv[0][1] = coeffs->cg;
+    rgb2yuv[0][2] = coeffs->cb;
+    bscale = 0.5 / (coeffs->cb - 1.0);
+    rscale = 0.5 / (coeffs->cr - 1.0);
+    rgb2yuv[1][0] = bscale * coeffs->cr;
+    rgb2yuv[1][1] = bscale * coeffs->cg;
+    rgb2yuv[1][2] = 0.5;
+    rgb2yuv[2][0] = 0.5;
+    rgb2yuv[2][1] = rscale * coeffs->cg;
+    rgb2yuv[2][2] = rscale * coeffs->cb;
+}
+
+// FIXME I'm pretty sure gamma22/28 also have a linear toe slope, but I can't
+// find any actual tables that document their real values...
+// See http://www.13thmonkey.org/~boris/gammacorrection/ first graph why it matters
+static const struct TransferCharacteristics transfer_characteristics[AVCOL_TRC_NB] = {
+    [AVCOL_TRC_BT709]     = { 1.099,  0.018,  0.45, 4.5 },
+    [AVCOL_TRC_GAMMA22]   = { 1.0,    0.0,    1.0 / 2.2, 0.0 },
+    [AVCOL_TRC_GAMMA28]   = { 1.0,    0.0,    1.0 / 2.8, 0.0 },
+    [AVCOL_TRC_SMPTE170M] = { 1.099,  0.018,  0.45, 4.5 },
+    [AVCOL_TRC_SMPTE240M] = { 1.1115, 0.0228, 0.45, 4.0 },
+    [AVCOL_TRC_BT2020_10] = { 1.099,  0.018,  0.45, 4.5 },
+    [AVCOL_TRC_BT2020_12] = { 1.0993, 0.0181, 0.45, 4.5 },
+};
+
+static const struct TransferCharacteristics *
+    get_transfer_characteristics(enum AVColorTransferCharacteristic trc)
+{
+    const struct TransferCharacteristics *coeffs;
+
+    if (trc >= AVCOL_TRC_NB)
+        return NULL;
+    coeffs = &transfer_characteristics[trc];
+    if (!coeffs->alpha)
+        return NULL;
+
+    return coeffs;
+}
+
+static const struct WhitepointCoefficients whitepoint_coefficients[WP_NB] = {
+    [WP_D65] = { 0.3127, 0.3290 },
+    [WP_C]   = { 0.3100, 0.3160 },
+};
+
+static const struct ColorPrimaries color_primaries[AVCOL_PRI_NB] = {
+    [AVCOL_PRI_BT709]     = { WP_D65, 0.640, 0.330, 0.300, 0.600, 0.150, 0.060 },
+    [AVCOL_PRI_BT470M]    = { WP_C,   0.670, 0.330, 0.210, 0.710, 0.140, 0.080 },
+    [AVCOL_PRI_BT470BG]   = { WP_D65, 0.640, 0.330, 0.290, 0.600, 0.150, 0.060,},
+    [AVCOL_PRI_SMPTE170M] = { WP_D65, 0.630, 0.340, 0.310, 0.595, 0.155, 0.070 },
+    [AVCOL_PRI_SMPTE240M] = { WP_D65, 0.630, 0.340, 0.310, 0.595, 0.155, 0.070 },
+    [AVCOL_PRI_BT2020]    = { WP_D65, 0.708, 0.292, 0.170, 0.797, 0.131, 0.046 },
+};
+
+static const struct ColorPrimaries *get_color_primaries(enum AVColorPrimaries prm)
+{
+    const struct ColorPrimaries *coeffs;
+
+    if (prm >= AVCOL_PRI_NB)
+        return NULL;
+    coeffs = &color_primaries[prm];
+    if (!coeffs->xr)
+        return NULL;
+
+    return coeffs;
+}
+
+static void invert_matrix3x3(const double in[3][3], double out[3][3])
+{
+    double m00 = in[0][0], m01 = in[0][1], m02 = in[0][2],
+           m10 = in[1][0], m11 = in[1][1], m12 = in[1][2],
+           m20 = in[2][0], m21 = in[2][1], m22 = in[2][2];
+    int i, j;
+    double det;
+
+    out[0][0] =  (m11 * m22 - m21 * m12);
+    out[0][1] = -(m01 * m22 - m21 * m02);
+    out[0][2] =  (m01 * m12 - m11 * m02);
+    out[1][0] = -(m10 * m22 - m20 * m12);
+    out[1][1] =  (m00 * m22 - m20 * m02);
+    out[1][2] = -(m00 * m12 - m10 * m02);
+    out[2][0] =  (m10 * m21 - m20 * m11);
+    out[2][1] = -(m00 * m21 - m20 * m01);
+    out[2][2] =  (m00 * m11 - m10 * m01);
+
+    det = m00 * out[0][0] + m10 * out[0][1] + m20 * out[0][2];
+    det = 1.0 / det;
+
+    for (i = 0; i < 3; i++) {
+        for (j = 0; j < 3; j++)
+            out[i][j] *= det;
+    }
+}
+
+static int fill_gamma_table(ColorSpaceContext *s)
+{
+    int n;
+    double in_alpha = s->in_txchr->alpha, in_beta = s->in_txchr->beta;
+    double in_gamma = s->in_txchr->gamma, in_delta = s->in_txchr->delta;
+    double in_ialpha = 1.0 / in_alpha, in_igamma = 1.0 / in_gamma, in_idelta = 1.0 / in_delta;
+    double out_alpha = s->out_txchr->alpha, out_beta = s->out_txchr->beta;
+    double out_gamma = s->out_txchr->gamma, out_delta = s->out_txchr->delta;
+
+    s->lin_lut = av_malloc(sizeof(*s->lin_lut) * 32768 * 2);
+    if (!s->lin_lut)
+        return AVERROR(ENOMEM);
+    s->delin_lut = &s->lin_lut[32768];
+    for (n = 0; n < 32768; n++) {
+        double v = (n - 2048.0) / 28672.0, d, l;
+
+        // delinearize
+        if (v <= -out_beta) {
+            d = -out_alpha * pow(-v, out_gamma) + (out_alpha - 1.0);
+        } else if (v < out_beta) {
+            d = out_delta * v;
+        } else {
+            d = out_alpha * pow(v, out_gamma) - (out_alpha - 1.0);
+        }
+        s->delin_lut[n] = av_clip_int16(lrint(d * 28672.0));
+
+        // linearize
+        if (v <= -in_beta) {
+            l = -pow((1.0 - in_alpha - v) * in_ialpha, in_igamma);
+        } else if (v < in_beta) {
+            l = v * in_idelta;
+        } else {
+            l = pow((v + in_alpha - 1.0) * in_ialpha, in_igamma);
+        }
+        s->lin_lut[n] = av_clip_int16(lrint(l * 28672.0));
+    }
+
+    return 0;
+}
+
+/*
+ * see e.g. http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
+ */
+static void fill_rgb2xyz_table(const struct ColorPrimaries *coeffs,
+                               double rgb2xyz[3][3])
+{
+    const struct WhitepointCoefficients *wp = &whitepoint_coefficients[coeffs->wp];
+    double i[3][3], sr, sg, sb, zw;
+
+    rgb2xyz[0][0] = coeffs->xr / coeffs->yr;
+    rgb2xyz[0][1] = coeffs->xg / coeffs->yg;
+    rgb2xyz[0][2] = coeffs->xb / coeffs->yb;
+    rgb2xyz[1][0] = rgb2xyz[1][1] = rgb2xyz[1][2] = 1.0;
+    rgb2xyz[2][0] = (1.0 - coeffs->xr - coeffs->yr) / coeffs->yr;
+    rgb2xyz[2][1] = (1.0 - coeffs->xg - coeffs->yg) / coeffs->yg;
+    rgb2xyz[2][2] = (1.0 - coeffs->xb - coeffs->yb) / coeffs->yb;
+    invert_matrix3x3(rgb2xyz, i);
+    zw = 1.0 - wp->xw - wp->yw;
+    sr = i[0][0] * wp->xw + i[0][1] * wp->yw + i[0][2] * zw;
+    sg = i[1][0] * wp->xw + i[1][1] * wp->yw + i[1][2] * zw;
+    sb = i[2][0] * wp->xw + i[2][1] * wp->yw + i[2][2] * zw;
+    rgb2xyz[0][0] *= sr;
+    rgb2xyz[0][1] *= sg;
+    rgb2xyz[0][2] *= sb;
+    rgb2xyz[1][0] *= sr;
+    rgb2xyz[1][1] *= sg;
+    rgb2xyz[1][2] *= sb;
+    rgb2xyz[2][0] *= sr;
+    rgb2xyz[2][1] *= sg;
+    rgb2xyz[2][2] *= sb;
+}
+
+static void mul3x3(double dst[3][3], const double src1[3][3], const double src2[3][3])
+{
+    int m, n;
+
+    for (m = 0; m < 3; m++)
+        for (n = 0; n < 3; n++)
+            dst[m][n] = src2[m][0] * src1[0][n] +
+                        src2[m][1] * src1[1][n] +
+                        src2[m][2] * src1[2][n];
+}
+
+/*
+ * See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
+ * This function uses the Bradford mechanism.
+ */
+static void fill_whitepoint_conv_table(double out[3][3], enum WhitepointAdaptation wp_adapt,
+                                       enum Whitepoint src, enum Whitepoint dst)
+{
+    static const double ma_tbl[NB_WP_ADAPT_NON_IDENTITY][3][3] = {
+        [WP_ADAPT_BRADFORD] = {
+            {  0.8951,  0.2664, -0.1614 },
+            { -0.7502,  1.7135,  0.0367 },
+            {  0.0389, -0.0685,  1.0296 },
+        }, [WP_ADAPT_VON_KRIES] = {
+            {  0.40024,  0.70760, -0.08081 },
+            { -0.22630,  1.16532,  0.04570 },
+            {  0.00000,  0.00000,  0.91822 },
+        },
+    };
+    const double (*ma)[3] = ma_tbl[wp_adapt];
+    const struct WhitepointCoefficients *wp_src = &whitepoint_coefficients[src];
+    double zw_src = 1.0 - wp_src->xw - wp_src->yw;
+    const struct WhitepointCoefficients *wp_dst = &whitepoint_coefficients[dst];
+    double zw_dst = 1.0 - wp_dst->xw - wp_dst->yw;
+    double mai[3][3], fac[3][3], tmp[3][3];
+    double rs, gs, bs, rd, gd, bd;
+
+    invert_matrix3x3(ma, mai);
+    rs = ma[0][0] * wp_src->xw + ma[0][1] * wp_src->yw + ma[0][2] * zw_src;
+    gs = ma[1][0] * wp_src->xw + ma[1][1] * wp_src->yw + ma[1][2] * zw_src;
+    bs = ma[2][0] * wp_src->xw + ma[2][1] * wp_src->yw + ma[2][2] * zw_src;
+    rd = ma[0][0] * wp_dst->xw + ma[0][1] * wp_dst->yw + ma[0][2] * zw_dst;
+    gd = ma[1][0] * wp_dst->xw + ma[1][1] * wp_dst->yw + ma[1][2] * zw_dst;
+    bd = ma[2][0] * wp_dst->xw + ma[2][1] * wp_dst->yw + ma[2][2] * zw_dst;
+    fac[0][0] = rd / rs;
+    fac[1][1] = gd / gs;
+    fac[2][2] = bd / bs;
+    fac[0][1] = fac[0][2] = fac[1][0] = fac[1][2] = fac[2][0] = fac[2][1] = 0.0;
+    mul3x3(tmp, ma, fac);
+    mul3x3(out, tmp, mai);
+}
+
+static void apply_lut(int16_t *buf[3], ptrdiff_t stride,
+                      int w, int h, const int16_t *lut)
+{
+    int y, x, n;
+
+    for (n = 0; n < 3; n++) {
+        int16_t *data = buf[n];
+
+        for (y = 0; y < h; y++) {
+            for (x = 0; x < w; x++)
+                data[x] = lut[av_clip_uintp2(2048 + data[x], 15)];
+
+            data += stride;
+        }
+    }
+}
+
+struct ThreadData {
+    AVFrame *in, *out;
+    ptrdiff_t in_linesize[3], out_linesize[3];
+    int in_ss_h, out_ss_h;
+};
+
+static int convert(AVFilterContext *ctx, void *data, int job_nr, int n_jobs)
+{
+    struct ThreadData *td = data;
+    ColorSpaceContext *s = ctx->priv;
+    uint8_t *in_data[3], *out_data[3];
+    int16_t *rgb[3];
+    int h_in = (td->in->height + 1) >> 1;
+    int h1 = 2 * (job_nr * h_in / n_jobs), h2 = 2 * ((job_nr + 1) * h_in / n_jobs);
+    int w = td->in->width, h = h2 - h1;
+
+    in_data[0]  = td->in->data[0]  + td->in_linesize[0]  *  h1;
+    in_data[1]  = td->in->data[1]  + td->in_linesize[1]  * (h1 >> td->in_ss_h);
+    in_data[2]  = td->in->data[2]  + td->in_linesize[2]  * (h1 >> td->in_ss_h);
+    out_data[0] = td->out->data[0] + td->out_linesize[0] *  h1;
+    out_data[1] = td->out->data[1] + td->out_linesize[1] * (h1 >> td->out_ss_h);
+    out_data[2] = td->out->data[2] + td->out_linesize[2] * (h1 >> td->out_ss_h);
+    rgb[0]      = s->rgb[0]        + s->rgb_stride       *  h1;
+    rgb[1]      = s->rgb[1]        + s->rgb_stride       *  h1;
+    rgb[2]      = s->rgb[2]        + s->rgb_stride       *  h1;
+
+    // FIXME for simd, also make sure we do pictures with negative stride
+    // top-down so we don't overwrite lines with padding of data before it
+    // in the same buffer (same as swscale)
+
+    if (s->yuv2yuv_fastmode) {
+        // FIXME possibly use a fast mode in case only the y range changes?
+        // since in that case, only the diagonal entries in yuv2yuv_coeffs[]
+        // are non-zero
+        s->yuv2yuv(out_data, td->out_linesize, in_data, td->in_linesize, w, h,
+                   s->yuv2yuv_coeffs, s->yuv_offset);
+    } else {
+        // FIXME maybe (for caching effciency) do pipeline per-line instead of
+        // full buffer per function? (Or, since yuv2rgb requires 2 lines: per
+        // 2 lines, for yuv420.)
+        /*
+         * General design:
+         * - yuv2rgb converts from whatever range the input was ([16-235/240] or
+         *   [0,255] or the 10/12bpp equivalents thereof) to an integer version
+         *   of RGB in psuedo-restricted 15+sign bits. That means that the float
+         *   range [0.0,1.0] is in [0,28762], and the remainder of the int16_t
+         *   range is used for overflow/underflow outside the representable
+         *   range of this RGB type. rgb2yuv is the exact opposite.
+         * - gamma correction is done using a LUT since that appears to work
+         *   fairly fast.
+         * - If the input is chroma-subsampled (420/422), the yuv2rgb conversion
+         *   (or rgb2yuv conversion) uses nearest-neighbour sampling to read
+         *   read chroma pixels at luma resolution. If you want some more fancy
+         *   filter, you can use swscale to convert to yuv444p.
+         * - all coefficients are 14bit (so in the [-2.0,2.0] range).
+         */
+        s->yuv2rgb(rgb, s->rgb_stride, in_data, td->in_linesize, w, h,
+                   s->yuv2rgb_coeffs, s->yuv_offset[0]);
+        if (!s->rgb2rgb_passthrough) {
+            apply_lut(rgb, s->rgb_stride, w, h, s->lin_lut);
+            if (!s->lrgb2lrgb_passthrough)
+                s->dsp.multiply3x3(rgb, s->rgb_stride, w, h, s->lrgb2lrgb_coeffs);
+            apply_lut(rgb, s->rgb_stride, w, h, s->delin_lut);
+        }
+        if (s->dither == DITHER_FSB) {
+            s->rgb2yuv_fsb(out_data, td->out_linesize, rgb, s->rgb_stride, w, h,
+                           s->rgb2yuv_coeffs, s->yuv_offset[1], s->dither_scratch);
+        } else {
+            s->rgb2yuv(out_data, td->out_linesize, rgb, s->rgb_stride, w, h,
+                       s->rgb2yuv_coeffs, s->yuv_offset[1]);
+        }
+    }
+
+    return 0;
+}
+
+static int get_range_off(int *off, int *y_rng, int *uv_rng,
+                         enum AVColorRange rng, int depth)
+{
+    switch (rng) {
+    case AVCOL_RANGE_MPEG:
+        *off = 16 << (depth - 8);
+        *y_rng = 219 << (depth - 8);
+        *uv_rng = 224 << (depth - 8);
+        break;
+    case AVCOL_RANGE_JPEG:
+        *off = 0;
+        *y_rng = *uv_rng = (256 << (depth - 8)) - 1;
+        break;
+    default:
+        return AVERROR(EINVAL);
+    }
+
+    return 0;
+}
+
+static int create_filtergraph(AVFilterContext *ctx,
+                              const AVFrame *in, const AVFrame *out)
+{
+    ColorSpaceContext *s = ctx->priv;
+    const AVPixFmtDescriptor *in_desc  = av_pix_fmt_desc_get(in->format);
+    const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(out->format);
+    int emms = 0, m, n, o, res, fmt_identical, redo_yuv2rgb = 0, redo_rgb2yuv = 0;
+
+#define supported_depth(d) ((d) == 8 || (d) == 10 || (d) == 12)
+#define supported_subsampling(lcw, lch) \
+    (((lcw) == 0 && (lch) == 0) || ((lcw) == 1 && (lch) == 0) || ((lcw) == 1 && (lch) == 1))
+#define supported_format(d) \
+    ((d) != NULL && (d)->nb_components == 3 && \
+     !((d)->flags & AV_PIX_FMT_FLAG_RGB) && \
+     supported_depth((d)->comp[0].depth) && \
+     supported_subsampling((d)->log2_chroma_w, (d)->log2_chroma_h))
+
+    if (!supported_format(in_desc)) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Unsupported input format %d (%s) or bitdepth (%d)\n",
+               in->format, av_get_pix_fmt_name(in->format),
+               in_desc ? in_desc->comp[0].depth : -1);
+        return AVERROR(EINVAL);
+    }
+    if (!supported_format(out_desc)) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Unsupported output format %d (%s) or bitdepth (%d)\n",
+               out->format, av_get_pix_fmt_name(out->format),
+               out_desc ? out_desc->comp[0].depth : -1);
+        return AVERROR(EINVAL);
+    }
+
+    if (in->color_primaries  != s->in_prm)  s->in_primaries  = NULL;
+    if (out->color_primaries != s->out_prm) s->out_primaries = NULL;
+    if (in->color_trc        != s->in_trc)  s->in_txchr      = NULL;
+    if (out->color_trc       != s->out_trc) s->out_txchr     = NULL;
+    if (in->colorspace       != s->in_csp ||
+        in->color_range      != s->in_rng)  s->in_lumacoef   = NULL;
+    if (out->colorspace      != s->out_csp ||
+        out->color_range     != s->out_rng) s->out_lumacoef  = NULL;
+
+    if (!s->out_primaries || !s->in_primaries) {
+        s->in_prm = in->color_primaries;
+        s->in_primaries = get_color_primaries(s->in_prm);
+        if (!s->in_primaries) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "Unsupported input primaries %d (%s)\n",
+                   s->in_prm, av_color_primaries_name(s->in_prm));
+            return AVERROR(EINVAL);
+        }
+        s->out_prm = out->color_primaries;
+        s->out_primaries = get_color_primaries(s->out_prm);
+        if (!s->out_primaries) {
+            if (s->out_prm == AVCOL_PRI_UNSPECIFIED) {
+                if (s->user_all == CS_UNSPECIFIED) {
+                    av_log(ctx, AV_LOG_ERROR, "Please specify output primaries\n");
+                } else {
+                    av_log(ctx, AV_LOG_ERROR,
+                           "Unsupported output color property %d\n", s->user_all);
+                }
+            } else {
+                av_log(ctx, AV_LOG_ERROR,
+                       "Unsupported output primaries %d (%s)\n",
+                       s->out_prm, av_color_primaries_name(s->out_prm));
+            }
+            return AVERROR(EINVAL);
+        }
+        s->lrgb2lrgb_passthrough = !memcmp(s->in_primaries, s->out_primaries,
+                                           sizeof(*s->in_primaries));
+        if (!s->lrgb2lrgb_passthrough) {
+            double rgb2xyz[3][3], xyz2rgb[3][3], rgb2rgb[3][3];
+
+            fill_rgb2xyz_table(s->out_primaries, rgb2xyz);
+            invert_matrix3x3(rgb2xyz, xyz2rgb);
+            fill_rgb2xyz_table(s->in_primaries, rgb2xyz);
+            if (s->out_primaries->wp != s->in_primaries->wp &&
+                s->wp_adapt != WP_ADAPT_IDENTITY) {
+                double wpconv[3][3], tmp[3][3];
+
+                fill_whitepoint_conv_table(wpconv, s->wp_adapt, s->in_primaries->wp,
+                                           s->out_primaries->wp);
+                mul3x3(tmp, rgb2xyz, wpconv);
+                mul3x3(rgb2rgb, tmp, xyz2rgb);
+            } else {
+                mul3x3(rgb2rgb, rgb2xyz, xyz2rgb);
+            }
+            for (m = 0; m < 3; m++)
+                for (n = 0; n < 3; n++) {
+                    s->lrgb2lrgb_coeffs[m][n][0] = lrint(16384.0 * rgb2rgb[m][n]);
+                    for (o = 1; o < 8; o++)
+                        s->lrgb2lrgb_coeffs[m][n][o] = s->lrgb2lrgb_coeffs[m][n][0];
+                }
+
+            emms = 1;
+        }
+    }
+
+    if (!s->in_txchr) {
+        av_freep(&s->lin_lut);
+        s->in_trc = in->color_trc;
+        s->in_txchr = get_transfer_characteristics(s->in_trc);
+        if (!s->in_txchr) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "Unsupported input transfer characteristics %d (%s)\n",
+                   s->in_trc, av_color_transfer_name(s->in_trc));
+            return AVERROR(EINVAL);
+        }
+    }
+
+    if (!s->out_txchr) {
+        av_freep(&s->lin_lut);
+        s->out_trc = out->color_trc;
+        s->out_txchr = get_transfer_characteristics(s->out_trc);
+        if (!s->out_txchr) {
+            if (s->out_trc == AVCOL_TRC_UNSPECIFIED) {
+                if (s->user_all == CS_UNSPECIFIED) {
+                    av_log(ctx, AV_LOG_ERROR,
+                           "Please specify output transfer characteristics\n");
+                } else {
+                    av_log(ctx, AV_LOG_ERROR,
+                           "Unsupported output color property %d\n", s->user_all);
+                }
+            } else {
+                av_log(ctx, AV_LOG_ERROR,
+                       "Unsupported output transfer characteristics %d (%s)\n",
+                       s->out_trc, av_color_transfer_name(s->out_trc));
+            }
+            return AVERROR(EINVAL);
+        }
+    }
+
+    s->rgb2rgb_passthrough = s->fast_mode || (s->lrgb2lrgb_passthrough &&
+                             !memcmp(s->in_txchr, s->out_txchr, sizeof(*s->in_txchr)));
+    if (!s->rgb2rgb_passthrough && !s->lin_lut) {
+        res = fill_gamma_table(s);
+        if (res < 0)
+            return res;
+        emms = 1;
+    }
+
+    if (!s->in_lumacoef) {
+        s->in_csp = in->colorspace;
+        s->in_rng = in->color_range;
+        s->in_lumacoef = get_luma_coefficients(s->in_csp);
+        if (!s->in_lumacoef) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "Unsupported input colorspace %d (%s)\n",
+                   s->in_csp, av_color_space_name(s->in_csp));
+            return AVERROR(EINVAL);
+        }
+        redo_yuv2rgb = 1;
+    }
+
+    if (!s->out_lumacoef) {
+        s->out_csp = out->colorspace;
+        s->out_rng = out->color_range;
+        s->out_lumacoef = get_luma_coefficients(s->out_csp);
+        if (!s->out_lumacoef) {
+            if (s->out_csp == AVCOL_SPC_UNSPECIFIED) {
+                if (s->user_all == CS_UNSPECIFIED) {
+                    av_log(ctx, AV_LOG_ERROR,
+                           "Please specify output transfer characteristics\n");
+                } else {
+                    av_log(ctx, AV_LOG_ERROR,
+                           "Unsupported output color property %d\n", s->user_all);
+                }
+            } else {
+                av_log(ctx, AV_LOG_ERROR,
+                       "Unsupported output transfer characteristics %d (%s)\n",
+                       s->out_csp, av_color_space_name(s->out_csp));
+            }
+            return AVERROR(EINVAL);
+        }
+        redo_rgb2yuv = 1;
+    }
+
+    fmt_identical = in_desc->log2_chroma_h == out_desc->log2_chroma_h &&
+                    in_desc->log2_chroma_w == out_desc->log2_chroma_w;
+    s->yuv2yuv_fastmode = s->rgb2rgb_passthrough && fmt_identical;
+    s->yuv2yuv_passthrough = s->yuv2yuv_fastmode && s->in_rng == s->out_rng &&
+                             !memcmp(s->in_lumacoef, s->out_lumacoef,
+                                     sizeof(*s->in_lumacoef)) &&
+                             in_desc->comp[0].depth == out_desc->comp[0].depth;
+    if (!s->yuv2yuv_passthrough) {
+        if (redo_yuv2rgb) {
+            double rgb2yuv[3][3], (*yuv2rgb)[3] = s->yuv2rgb_dbl_coeffs;
+            int off, bits, in_rng;
+
+            res = get_range_off(&off, &s->in_y_rng, &s->in_uv_rng,
+                                s->in_rng, in_desc->comp[0].depth);
+            if (res < 0) {
+                av_log(ctx, AV_LOG_ERROR,
+                       "Unsupported input color range %d (%s)\n",
+                       s->in_rng, av_color_range_name(s->in_rng));
+                return res;
+            }
+            for (n = 0; n < 8; n++)
+                s->yuv_offset[0][n] = off;
+            fill_rgb2yuv_table(s->in_lumacoef, rgb2yuv);
+            invert_matrix3x3(rgb2yuv, yuv2rgb);
+            bits = 1 << (in_desc->comp[0].depth - 1);
+            for (n = 0; n < 3; n++) {
+                for (in_rng = s->in_y_rng, m = 0; m < 3; m++, in_rng = s->in_uv_rng) {
+                    s->yuv2rgb_coeffs[n][m][0] = lrint(28672 * bits * yuv2rgb[n][m] / in_rng);
+                    for (o = 1; o < 8; o++)
+                        s->yuv2rgb_coeffs[n][m][o] = s->yuv2rgb_coeffs[n][m][0];
+                }
+            }
+            av_assert2(s->yuv2rgb_coeffs[0][1][0] == 0);
+            av_assert2(s->yuv2rgb_coeffs[2][2][0] == 0);
+            av_assert2(s->yuv2rgb_coeffs[0][0][0] == s->yuv2rgb_coeffs[1][0][0]);
+            av_assert2(s->yuv2rgb_coeffs[0][0][0] == s->yuv2rgb_coeffs[2][0][0]);
+            s->yuv2rgb = s->dsp.yuv2rgb[(in_desc->comp[0].depth - 8) >> 1]
+                                       [in_desc->log2_chroma_h + in_desc->log2_chroma_w];
+            emms = 1;
+        }
+
+        if (redo_rgb2yuv) {
+            double (*rgb2yuv)[3] = s->rgb2yuv_dbl_coeffs;
+            int off, out_rng, bits;
+
+            res = get_range_off(&off, &s->out_y_rng, &s->out_uv_rng,
+                                s->out_rng, out_desc->comp[0].depth);
+            if (res < 0) {
+                av_log(ctx, AV_LOG_ERROR,
+                       "Unsupported output color range %d (%s)\n",
+                       s->out_rng, av_color_range_name(s->out_rng));
+                return res;
+            }
+            for (n = 0; n < 8; n++)
+                s->yuv_offset[1][n] = off;
+            fill_rgb2yuv_table(s->out_lumacoef, rgb2yuv);
+            bits = 1 << (29 - out_desc->comp[0].depth);
+            for (out_rng = s->out_y_rng, n = 0; n < 3; n++, out_rng = s->out_uv_rng) {
+                for (m = 0; m < 3; m++) {
+                    s->rgb2yuv_coeffs[n][m][0] = lrint(bits * out_rng * rgb2yuv[n][m] / 28672);
+                    for (o = 1; o < 8; o++)
+                        s->rgb2yuv_coeffs[n][m][o] = s->rgb2yuv_coeffs[n][m][0];
+                }
+            }
+            av_assert2(s->rgb2yuv_coeffs[1][2][0] == s->rgb2yuv_coeffs[2][0][0]);
+            s->rgb2yuv = s->dsp.rgb2yuv[(out_desc->comp[0].depth - 8) >> 1]
+                                       [out_desc->log2_chroma_h + out_desc->log2_chroma_w];
+            s->rgb2yuv_fsb = s->dsp.rgb2yuv_fsb[(out_desc->comp[0].depth - 8) >> 1]
+                                       [out_desc->log2_chroma_h + out_desc->log2_chroma_w];
+            emms = 1;
+        }
+
+        if (s->yuv2yuv_fastmode && (redo_yuv2rgb || redo_rgb2yuv)) {
+            int idepth = in_desc->comp[0].depth, odepth = out_desc->comp[0].depth;
+            double (*rgb2yuv)[3] = s->rgb2yuv_dbl_coeffs;
+            double (*yuv2rgb)[3] = s->yuv2rgb_dbl_coeffs;
+            double yuv2yuv[3][3];
+            int in_rng, out_rng;
+
+            mul3x3(yuv2yuv, yuv2rgb, rgb2yuv);
+            for (out_rng = s->out_y_rng, m = 0; m < 3; m++, out_rng = s->out_uv_rng) {
+                for (in_rng = s->in_y_rng, n = 0; n < 3; n++, in_rng = s->in_uv_rng) {
+                    s->yuv2yuv_coeffs[m][n][0] =
+                        lrint(16384 * yuv2yuv[m][n] * out_rng * (1 << idepth) /
+                              (in_rng * (1 << odepth)));
+                    for (o = 1; o < 8; o++)
+                        s->yuv2yuv_coeffs[m][n][o] = s->yuv2yuv_coeffs[m][n][0];
+                }
+            }
+            av_assert2(s->yuv2yuv_coeffs[1][0][0] == 0);
+            av_assert2(s->yuv2yuv_coeffs[2][0][0] == 0);
+            s->yuv2yuv = s->dsp.yuv2yuv[(idepth - 8) >> 1][(odepth - 8) >> 1]
+                                       [in_desc->log2_chroma_h + in_desc->log2_chroma_w];
+        }
+    }
+
+    if (emms)
+        emms_c();
+
+    return 0;
+}
+
+static int init(AVFilterContext *ctx)
+{
+    ColorSpaceContext *s = ctx->priv;
+
+    ff_colorspacedsp_init(&s->dsp);
+
+    return 0;
+}
+
+static void uninit(AVFilterContext *ctx)
+{
+    ColorSpaceContext *s = ctx->priv;
+
+    av_freep(&s->rgb[0]);
+    av_freep(&s->rgb[1]);
+    av_freep(&s->rgb[2]);
+    s->rgb_sz = 0;
+    av_freep(&s->dither_scratch_base[0][0]);
+    av_freep(&s->dither_scratch_base[0][1]);
+    av_freep(&s->dither_scratch_base[1][0]);
+    av_freep(&s->dither_scratch_base[1][1]);
+    av_freep(&s->dither_scratch_base[2][0]);
+    av_freep(&s->dither_scratch_base[2][1]);
+
+    av_freep(&s->lin_lut);
+}
+
+static int filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    AVFilterContext *ctx = link->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    ColorSpaceContext *s = ctx->priv;
+    // FIXME if yuv2yuv_passthrough, don't get a new buffer but use the
+    // input one if it is writable *OR* the actual literal values of in_*
+    // and out_* are identical (not just their respective properties)
+    AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    int res;
+    ptrdiff_t rgb_stride = FFALIGN(in->width * sizeof(int16_t), 32);
+    unsigned rgb_sz = rgb_stride * in->height;
+    struct ThreadData td;
+
+    if (!out) {
+        av_frame_free(&in);
+        return AVERROR(ENOMEM);
+    }
+    av_frame_copy_props(out, in);
+
+    out->color_primaries = s->user_prm == AVCOL_PRI_UNSPECIFIED ?
+                           default_prm[FFMIN(s->user_all, CS_NB)] : s->user_prm;
+    if (s->user_trc == AVCOL_TRC_UNSPECIFIED) {
+        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(out->format);
+
+        out->color_trc   = default_trc[FFMIN(s->user_all, CS_NB)];
+        if (out->color_trc == AVCOL_TRC_BT2020_10 && desc && desc->comp[0].depth >= 12)
+            out->color_trc = AVCOL_TRC_BT2020_12;
+    } else {
+        out->color_trc   = s->user_trc;
+    }
+    out->colorspace      = s->user_csp == AVCOL_SPC_UNSPECIFIED ?
+                           default_csp[FFMIN(s->user_all, CS_NB)] : s->user_csp;
+    out->color_range     = s->user_rng == AVCOL_RANGE_UNSPECIFIED ?
+                           in->color_range : s->user_rng;
+    if (rgb_sz != s->rgb_sz) {
+        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(out->format);
+        int uvw = in->width >> desc->log2_chroma_w;
+
+        av_freep(&s->rgb[0]);
+        av_freep(&s->rgb[1]);
+        av_freep(&s->rgb[2]);
+        s->rgb_sz = 0;
+        av_freep(&s->dither_scratch_base[0][0]);
+        av_freep(&s->dither_scratch_base[0][1]);
+        av_freep(&s->dither_scratch_base[1][0]);
+        av_freep(&s->dither_scratch_base[1][1]);
+        av_freep(&s->dither_scratch_base[2][0]);
+        av_freep(&s->dither_scratch_base[2][1]);
+
+        s->rgb[0] = av_malloc(rgb_sz);
+        s->rgb[1] = av_malloc(rgb_sz);
+        s->rgb[2] = av_malloc(rgb_sz);
+        s->dither_scratch_base[0][0] =
+            av_malloc(sizeof(*s->dither_scratch_base[0][0]) * (in->width + 4));
+        s->dither_scratch_base[0][1] =
+            av_malloc(sizeof(*s->dither_scratch_base[0][1]) * (in->width + 4));
+        s->dither_scratch_base[1][0] =
+            av_malloc(sizeof(*s->dither_scratch_base[1][0]) * (uvw + 4));
+        s->dither_scratch_base[1][1] =
+            av_malloc(sizeof(*s->dither_scratch_base[1][1]) * (uvw + 4));
+        s->dither_scratch_base[2][0] =
+            av_malloc(sizeof(*s->dither_scratch_base[2][0]) * (uvw + 4));
+        s->dither_scratch_base[2][1] =
+            av_malloc(sizeof(*s->dither_scratch_base[2][1]) * (uvw + 4));
+        s->dither_scratch[0][0] = &s->dither_scratch_base[0][0][1];
+        s->dither_scratch[0][1] = &s->dither_scratch_base[0][1][1];
+        s->dither_scratch[1][0] = &s->dither_scratch_base[1][0][1];
+        s->dither_scratch[1][1] = &s->dither_scratch_base[1][1][1];
+        s->dither_scratch[2][0] = &s->dither_scratch_base[2][0][1];
+        s->dither_scratch[2][1] = &s->dither_scratch_base[2][1][1];
+        if (!s->rgb[0] || !s->rgb[1] || !s->rgb[2] ||
+            !s->dither_scratch_base[0][0] || !s->dither_scratch_base[0][1] ||
+            !s->dither_scratch_base[1][0] || !s->dither_scratch_base[1][1] ||
+            !s->dither_scratch_base[2][0] || !s->dither_scratch_base[2][1]) {
+            uninit(ctx);
+            return AVERROR(ENOMEM);
+        }
+        s->rgb_sz = rgb_sz;
+    }
+    res = create_filtergraph(ctx, in, out);
+    if (res < 0)
+        return res;
+    s->rgb_stride = rgb_stride / sizeof(int16_t);
+    td.in = in;
+    td.out = out;
+    td.in_linesize[0] = in->linesize[0];
+    td.in_linesize[1] = in->linesize[1];
+    td.in_linesize[2] = in->linesize[2];
+    td.out_linesize[0] = out->linesize[0];
+    td.out_linesize[1] = out->linesize[1];
+    td.out_linesize[2] = out->linesize[2];
+    td.in_ss_h = av_pix_fmt_desc_get(in->format)->log2_chroma_h;
+    td.out_ss_h = av_pix_fmt_desc_get(out->format)->log2_chroma_h;
+    if (s->yuv2yuv_passthrough) {
+        res = av_frame_copy(out, in);
+        if (res < 0)
+            return res;
+    } else {
+        ctx->internal->execute(ctx, convert, &td, NULL,
+                               FFMIN((in->height + 1) >> 1, ctx->graph->nb_threads));
+    }
+    av_frame_free(&in);
+
+    return ff_filter_frame(outlink, out);
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+    static const enum AVPixelFormat pix_fmts[] = {
+        AV_PIX_FMT_YUV420P,   AV_PIX_FMT_YUV422P,   AV_PIX_FMT_YUV444P,
+        AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
+        AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12,
+        AV_PIX_FMT_NONE
+    };
+    int res;
+    ColorSpaceContext *s = ctx->priv;
+    AVFilterFormats *formats = ff_make_format_list(pix_fmts);
+
+    if (!formats)
+        return AVERROR(ENOMEM);
+    if (s->user_format == AV_PIX_FMT_NONE)
+        return ff_set_common_formats(ctx, formats);
+    res = ff_formats_ref(formats, &ctx->inputs[0]->out_formats);
+    if (res < 0)
+        return res;
+    formats = NULL;
+    res = ff_add_format(&formats, s->user_format);
+    if (res < 0)
+        return res;
+
+    return ff_formats_ref(formats, &ctx->outputs[0]->in_formats);
+}
+
+static int config_props(AVFilterLink *outlink)
+{
+    AVFilterLink *inlink = outlink->src->inputs[0];
+
+    outlink->w = inlink->w;
+    outlink->h = inlink->h;
+    outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
+    outlink->time_base = inlink->time_base;
+
+    return 0;
+}
+
+#define OFFSET(x) offsetof(ColorSpaceContext, x)
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
+#define ENUM(x, y, z) { x, "", 0, AV_OPT_TYPE_CONST, { .i64 = y }, INT_MIN, INT_MAX, FLAGS, z }
+
+static const AVOption colorspace_options[] = {
+    { "all",        "Set all color properties together",
+      OFFSET(user_all),   AV_OPT_TYPE_INT, { .i64 = CS_UNSPECIFIED },
+      CS_UNSPECIFIED, CS_NB - 1, FLAGS, "all" },
+    ENUM("bt470m",      CS_BT470M,             "all"),
+    ENUM("bt470bg",     CS_BT470BG,            "all"),
+    ENUM("bt601-6-525", CS_BT601_6_525,        "all"),
+    ENUM("bt601-6-625", CS_BT601_6_625,        "all"),
+    ENUM("bt709",       CS_BT709,              "all"),
+    ENUM("smpte170m",   CS_SMPTE170M,          "all"),
+    ENUM("smpte240m",   CS_SMPTE240M,          "all"),
+    ENUM("bt2020",      CS_BT2020,             "all"),
+
+    { "space",      "Output colorspace",
+      OFFSET(user_csp),   AV_OPT_TYPE_INT, { .i64 = AVCOL_SPC_UNSPECIFIED },
+      AVCOL_PRI_RESERVED0, AVCOL_PRI_NB - 1, FLAGS, "csp" },
+    ENUM("bt709",       AVCOL_SPC_BT709,       "csp"),
+    ENUM("fcc",         AVCOL_SPC_FCC,         "csp"),
+    ENUM("bt470bg",     AVCOL_SPC_BT470BG,     "csp"),
+    ENUM("smpte170m",   AVCOL_SPC_SMPTE170M,   "csp"),
+    ENUM("smpte240m",   AVCOL_SPC_SMPTE240M,   "csp"),
+    ENUM("bt2020ncl",   AVCOL_SPC_BT2020_NCL,  "csp"),
+
+    { "range",      "Output color range",
+      OFFSET(user_rng),   AV_OPT_TYPE_INT, { .i64 = AVCOL_RANGE_UNSPECIFIED },
+      AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_NB - 1, FLAGS, "rng" },
+    ENUM("mpeg",        AVCOL_RANGE_MPEG,      "rng"),
+    ENUM("jpeg",        AVCOL_RANGE_JPEG,      "rng"),
+
+    { "primaries",  "Output color primaries",
+      OFFSET(user_prm),   AV_OPT_TYPE_INT, { .i64 = AVCOL_PRI_UNSPECIFIED },
+      AVCOL_PRI_RESERVED0, AVCOL_PRI_NB - 1, FLAGS, "prm" },
+    ENUM("bt709",        AVCOL_PRI_BT709,      "prm"),
+    ENUM("bt470m",       AVCOL_PRI_BT470M,     "prm"),
+    ENUM("bt470bg",      AVCOL_PRI_BT470BG,    "prm"),
+    ENUM("smpte170m",    AVCOL_PRI_SMPTE170M,  "prm"),
+    ENUM("smpte240m",    AVCOL_PRI_SMPTE240M,  "prm"),
+    ENUM("bt2020",       AVCOL_PRI_BT2020,     "prm"),
+
+    { "trc",        "Output transfer characteristics",
+      OFFSET(user_trc),   AV_OPT_TYPE_INT, { .i64 = AVCOL_TRC_UNSPECIFIED },
+      AVCOL_TRC_RESERVED0, AVCOL_TRC_NB - 1, FLAGS, "trc" },
+    ENUM("bt709",        AVCOL_TRC_BT709,        "trc"),
+    ENUM("gamma22",      AVCOL_TRC_GAMMA22,      "trc"),
+    ENUM("gamma28",      AVCOL_TRC_GAMMA28,      "trc"),
+    ENUM("smpte170m",    AVCOL_TRC_SMPTE170M,    "trc"),
+    ENUM("smpte240m",    AVCOL_TRC_SMPTE240M,    "trc"),
+    ENUM("bt2020-10",    AVCOL_TRC_BT2020_10,    "trc"),
+    ENUM("bt2020-12",    AVCOL_TRC_BT2020_12,    "trc"),
+
+    { "format",   "Output pixel format",
+      OFFSET(user_format), AV_OPT_TYPE_INT,  { .i64 = AV_PIX_FMT_NONE },
+      AV_PIX_FMT_NONE, AV_PIX_FMT_GBRAP12LE, FLAGS, "fmt" },
+    ENUM("yuv420p",   AV_PIX_FMT_YUV420P,   "fmt"),
+    ENUM("yuv420p10", AV_PIX_FMT_YUV420P10, "fmt"),
+    ENUM("yuv420p12", AV_PIX_FMT_YUV420P12, "fmt"),
+    ENUM("yuv422p",   AV_PIX_FMT_YUV422P,   "fmt"),
+    ENUM("yuv422p10", AV_PIX_FMT_YUV422P10, "fmt"),
+    ENUM("yuv422p12", AV_PIX_FMT_YUV422P12, "fmt"),
+    ENUM("yuv444p",   AV_PIX_FMT_YUV444P,   "fmt"),
+    ENUM("yuv444p10", AV_PIX_FMT_YUV444P10, "fmt"),
+    ENUM("yuv444p12", AV_PIX_FMT_YUV444P12, "fmt"),
+
+    { "fast",     "Ignore primary chromaticity and gamma correction",
+      OFFSET(fast_mode), AV_OPT_TYPE_BOOL,  { .i64 = 0    },
+      0, 1, FLAGS },
+
+    { "dither",   "Dithering mode",
+      OFFSET(dither), AV_OPT_TYPE_INT, { .i64 = DITHER_NONE },
+      DITHER_NONE, DITHER_NB - 1, FLAGS, "dither" },
+    ENUM("none", DITHER_NONE, "dither"),
+    ENUM("fsb",  DITHER_FSB,  "dither"),
+
+    { "wpadapt", "Whitepoint adaptation method",
+      OFFSET(wp_adapt), AV_OPT_TYPE_INT, { .i64 = WP_ADAPT_BRADFORD },
+      WP_ADAPT_BRADFORD, NB_WP_ADAPT - 1, FLAGS, "wpadapt" },
+    ENUM("bradford", WP_ADAPT_BRADFORD, "wpadapt"),
+    ENUM("vonkries", WP_ADAPT_VON_KRIES, "wpadapt"),
+    ENUM("identity", WP_ADAPT_IDENTITY, "wpadapt"),
+
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(colorspace);
+
+static const AVFilterPad inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = config_props,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_colorspace = {
+    .name            = "colorspace",
+    .description     = NULL_IF_CONFIG_SMALL("Convert between colorspaces."),
+    .init            = init,
+    .uninit          = uninit,
+    .query_formats   = query_formats,
+    .priv_size       = sizeof(ColorSpaceContext),
+    .priv_class      = &colorspace_class,
+    .inputs          = inputs,
+    .outputs         = outputs,
+    .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
+};
diff --git a/libavfilter/vf_copy.c b/libavfilter/vf_copy.c
index fb9a906..b0159cf 100644
--- a/libavfilter/vf_copy.c
+++ b/libavfilter/vf_copy.c
@@ -27,6 +27,23 @@
 #include "internal.h"
 #include "video.h"
 
+static int query_formats(AVFilterContext *ctx)
+{
+    AVFilterFormats *formats = NULL;
+    int fmt;
+
+    for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) {
+        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
+        int ret;
+        if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
+            continue;
+        if ((ret = ff_add_format(&formats, fmt)) < 0)
+            return ret;
+    }
+
+    return ff_set_common_formats(ctx, formats);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
     AVFilterLink *outlink = inlink->dst->outputs[0];
@@ -64,4 +81,5 @@ AVFilter ff_vf_copy = {
     .description = NULL_IF_CONFIG_SMALL("Copy the input video unchanged to the output."),
     .inputs      = avfilter_vf_copy_inputs,
     .outputs     = avfilter_vf_copy_outputs,
+    .query_formats = query_formats,
 };
diff --git a/libavfilter/vf_coreimage.m b/libavfilter/vf_coreimage.m
new file mode 100644
index 0000000..9c8db02
--- /dev/null
+++ b/libavfilter/vf_coreimage.m
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2016 Thilo Borgmann
+ *
+ * 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
+ * Video processing based on Apple's CoreImage API
+ */
+
+#import <QuartzCore/CoreImage.h>
+#import <AppKit/AppKit.h>
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+
+typedef struct CoreImageContext {
+    const AVClass   *class;
+
+    int             is_video_source;    ///< filter is used as video source
+
+    int             w, h;               ///< video size
+    AVRational      sar;                ///< sample aspect ratio
+    AVRational      frame_rate;         ///< video frame rate
+    AVRational      time_base;          ///< stream time base
+    int64_t         duration;           ///< duration expressed in microseconds
+    int64_t         pts;                ///< increasing presentation time stamp
+    AVFrame         *picref;            ///< cached reference containing the painted picture
+
+    CFTypeRef       glctx;              ///< OpenGL context
+    CGContextRef    cgctx;              ///< Bitmap context for image copy
+    CFTypeRef       input_image;        ///< Input image container for passing into Core Image API
+    CGColorSpaceRef color_space;        ///< Common color space for input image and cgcontext
+    int             bits_per_component; ///< Shared bpc for input-output operation
+
+    char            *filter_string;     ///< The complete user provided filter definition
+    CFTypeRef       *filters;           ///< CIFilter object for all requested filters
+    int             num_filters;        ///< Amount of filters in *filters
+
+    char            *output_rect;       ///< Rectangle to be filled with filter intput
+    int             list_filters;       ///< Option used to list all available filters including generators
+    int             list_generators;    ///< Option used to list all available generators
+} CoreImageContext;
+
+static int config_output(AVFilterLink *link)
+{
+    CoreImageContext *ctx = link->src->priv;
+
+    link->w                   = ctx->w;
+    link->h                   = ctx->h;
+    link->sample_aspect_ratio = ctx->sar;
+    link->frame_rate          = ctx->frame_rate;
+    link->time_base           = ctx->time_base;
+
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
+    ctx->bits_per_component        = av_get_bits_per_pixel(desc) / desc->nb_components;
+
+    return 0;
+}
+
+/** Determine image properties from input link of filter chain.
+ */
+static int config_input(AVFilterLink *link)
+{
+    CoreImageContext *ctx          = link->dst->priv;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
+    ctx->bits_per_component        = av_get_bits_per_pixel(desc) / desc->nb_components;
+
+    return 0;
+}
+
+/** Print a list of all available filters including options and respective value ranges and defaults.
+ */
+static void list_filters(CoreImageContext *ctx)
+{
+    // querying filters and attributes
+    NSArray *filter_categories = nil;
+
+    if (ctx->list_generators && !ctx->list_filters) {
+        filter_categories = [NSArray arrayWithObjects:kCICategoryGenerator, nil];
+    }
+
+    NSArray *filter_names = [CIFilter filterNamesInCategories:filter_categories];
+    NSEnumerator *filters = [filter_names objectEnumerator];
+
+    NSString *filter_name;
+    while (filter_name = [filters nextObject]) {
+        av_log(ctx, AV_LOG_INFO, "Filter: %s\n", [filter_name UTF8String]);
+        NSString *input;
+
+        CIFilter *filter             = [CIFilter filterWithName:filter_name];
+        NSDictionary *filter_attribs = [filter attributes]; // <nsstring, id>
+        NSArray      *filter_inputs  = [filter inputKeys];  // <nsstring>
+
+        for (input in filter_inputs) {
+            NSDictionary *input_attribs = [filter_attribs valueForKey:input];
+            NSString *input_class       = [input_attribs valueForKey:kCIAttributeClass];
+            if ([input_class isEqualToString:@"NSNumber"]) {
+                NSNumber *value_default = [input_attribs valueForKey:kCIAttributeDefault];
+                NSNumber *value_min     = [input_attribs valueForKey:kCIAttributeSliderMin];
+                NSNumber *value_max     = [input_attribs valueForKey:kCIAttributeSliderMax];
+
+                av_log(ctx, AV_LOG_INFO, "\tOption: %s\t[%s]\t[%s %s][%s]\n",
+                    [input UTF8String],
+                    [input_class UTF8String],
+                    [[value_min stringValue] UTF8String],
+                    [[value_max stringValue] UTF8String],
+                    [[value_default stringValue] UTF8String]);
+            } else {
+                av_log(ctx, AV_LOG_INFO, "\tOption: %s\t[%s]\n",
+                    [input UTF8String],
+                    [input_class UTF8String]);
+            }
+        }
+    }
+}
+
+static int query_formats(AVFilterContext *fctx)
+{
+    static const enum AVPixelFormat inout_fmts_rgb[] = {
+        AV_PIX_FMT_ARGB,
+        AV_PIX_FMT_NONE
+    };
+
+    AVFilterFormats *inout_formats;
+    int ret;
+
+    if (!(inout_formats = ff_make_format_list(inout_fmts_rgb))) {
+        return AVERROR(ENOMEM);
+    }
+
+    if ((ret = ff_formats_ref(inout_formats, &fctx->inputs[0]->out_formats)) < 0 ||
+        (ret = ff_formats_ref(inout_formats, &fctx->outputs[0]->in_formats)) < 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+static int query_formats_src(AVFilterContext *fctx)
+{
+    static const enum AVPixelFormat inout_fmts_rgb[] = {
+        AV_PIX_FMT_ARGB,
+        AV_PIX_FMT_NONE
+    };
+
+    AVFilterFormats *inout_formats;
+    int ret;
+
+    if (!(inout_formats = ff_make_format_list(inout_fmts_rgb))) {
+        return AVERROR(ENOMEM);
+    }
+
+    if ((ret = ff_formats_ref(inout_formats, &fctx->outputs[0]->in_formats)) < 0) {
+        return ret;
+    }
+
+    return 0;
+}
+
+static int apply_filter(CoreImageContext *ctx, AVFilterLink *link, AVFrame *frame)
+{
+    int i;
+
+    // (re-)initialize input image
+    const CGSize frame_size = {
+        frame->width,
+        frame->height
+    };
+
+    NSData *data = [NSData dataWithBytesNoCopy:frame->data[0]
+                           length:frame->height*frame->linesize[0]
+                           freeWhenDone:NO];
+
+    CIImage *ret = [(__bridge CIImage*)ctx->input_image initWithBitmapData:data
+                                                        bytesPerRow:frame->linesize[0]
+                                                        size:frame_size
+                                                        format:kCIFormatARGB8
+                                                        colorSpace:ctx->color_space]; //kCGColorSpaceGenericRGB
+    if (!ret) {
+        av_log(ctx, AV_LOG_ERROR, "Input image could not be initialized.\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    CIFilter *filter       = NULL;
+    CIImage *filter_input  = (__bridge CIImage*)ctx->input_image;
+    CIImage *filter_output = NULL;
+
+    // successively apply all filters
+    for (i = 0; i < ctx->num_filters; i++) {
+        if (i) {
+            // set filter input to previous filter output
+            filter_input    = [(__bridge CIImage*)ctx->filters[i-1] valueForKey:kCIOutputImageKey];
+            CGRect out_rect = [filter_input extent];
+            if (out_rect.size.width > frame->width || out_rect.size.height > frame->height) {
+                // do not keep padded image regions after filtering
+                out_rect.origin.x    = 0.0f;
+                out_rect.origin.y    = 0.0f;
+                out_rect.size.width  = frame->width;
+                out_rect.size.height = frame->height;
+            }
+            filter_input = [filter_input imageByCroppingToRect:out_rect];
+        }
+
+        filter = (__bridge CIFilter*)ctx->filters[i];
+
+        // do not set input image for the first filter if used as video source
+        if (!ctx->is_video_source || i) {
+            @try {
+                [filter setValue:filter_input forKey:kCIInputImageKey];
+            } @catch (NSException *exception) {
+                if (![[exception name] isEqualToString:NSUndefinedKeyException]) {
+                    av_log(ctx, AV_LOG_ERROR, "An error occurred: %s.", [exception.reason UTF8String]);
+                    return AVERROR_EXTERNAL;
+                } else {
+                    av_log(ctx, AV_LOG_WARNING, "Selected filter does not accept an input image.\n");
+                }
+            }
+        }
+    }
+
+    // get output of last filter
+    filter_output = [filter valueForKey:kCIOutputImageKey];
+
+    if (!filter_output) {
+        av_log(ctx, AV_LOG_ERROR, "Filter output not available.\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    // do not keep padded image regions after filtering
+    CGRect out_rect = [filter_output extent];
+    if (out_rect.size.width > frame->width || out_rect.size.height > frame->height) {
+        av_log(ctx, AV_LOG_DEBUG, "Cropping output image.\n");
+        out_rect.origin.x    = 0.0f;
+        out_rect.origin.y    = 0.0f;
+        out_rect.size.width  = frame->width;
+        out_rect.size.height = frame->height;
+    }
+
+    CGImageRef out = [(__bridge CIContext*)ctx->glctx createCGImage:filter_output
+                                                      fromRect:out_rect];
+
+    if (!out) {
+        av_log(ctx, AV_LOG_ERROR, "Cannot create valid output image.\n");
+    }
+
+    // create bitmap context on the fly for rendering into current frame->data[]
+    if (ctx->cgctx) {
+        CGContextRelease(ctx->cgctx);
+        ctx->cgctx = NULL;
+    }
+    size_t out_width  = CGImageGetWidth(out);
+    size_t out_height = CGImageGetHeight(out);
+
+    if (out_width > frame->width || out_height > frame->height) { // this might result in segfault
+        av_log(ctx, AV_LOG_WARNING, "Output image has unexpected size: %lux%lu (expected: %ix%i). This may crash...\n",
+               out_width, out_height, frame->width, frame->height);
+    }
+    ctx->cgctx = CGBitmapContextCreate(frame->data[0],
+                                       frame->width,
+                                       frame->height,
+                                       ctx->bits_per_component,
+                                       frame->linesize[0],
+                                       ctx->color_space,
+                                       (uint32_t)kCGImageAlphaPremultipliedFirst); // ARGB
+    if (!ctx->cgctx) {
+        av_log(ctx, AV_LOG_ERROR, "CGBitmap context cannot be created.\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    // copy ("draw") the output image into the frame data
+    CGRect rect = {{0,0},{frame->width, frame->height}};
+    if (ctx->output_rect) {
+        @try {
+            NSString *tmp_string = [NSString stringWithUTF8String:ctx->output_rect];
+            NSRect tmp           = NSRectFromString(tmp_string);
+            rect                 = NSRectToCGRect(tmp);
+        } @catch (NSException *exception) {
+            av_log(ctx, AV_LOG_ERROR, "An error occurred: %s.", [exception.reason UTF8String]);
+            return AVERROR_EXTERNAL;
+        }
+        if (rect.size.width == 0.0f) {
+            av_log(ctx, AV_LOG_WARNING, "Width of output rect is zero.\n");
+        }
+        if (rect.size.height == 0.0f) {
+            av_log(ctx, AV_LOG_WARNING, "Height of output rect is zero.\n");
+        }
+    }
+
+    CGContextDrawImage(ctx->cgctx, rect, out);
+
+    return ff_filter_frame(link, frame);
+}
+
+/** Apply all valid filters successively to the input image.
+ *  The final output image is copied from the GPU by "drawing" using a bitmap context.
+ */
+static int filter_frame(AVFilterLink *link, AVFrame *frame)
+{
+    return apply_filter(link->dst->priv, link->dst->outputs[0], frame);
+}
+
+static int request_frame(AVFilterLink *link)
+{
+    CoreImageContext *ctx = link->src->priv;
+    AVFrame *frame;
+
+    if (ctx->duration >= 0 &&
+        av_rescale_q(ctx->pts, ctx->time_base, AV_TIME_BASE_Q) >= ctx->duration) {
+        return AVERROR_EOF;
+    }
+
+    if (!ctx->picref) {
+        ctx->picref = ff_get_video_buffer(link, ctx->w, ctx->h);
+        if (!ctx->picref) {
+            return AVERROR(ENOMEM);
+        }
+    }
+
+    frame = av_frame_clone(ctx->picref);
+    if (!frame) {
+        return AVERROR(ENOMEM);
+    }
+
+    frame->pts                 = ctx->pts;
+    frame->key_frame           = 1;
+    frame->interlaced_frame    = 0;
+    frame->pict_type           = AV_PICTURE_TYPE_I;
+    frame->sample_aspect_ratio = ctx->sar;
+
+    ctx->pts++;
+
+    return apply_filter(ctx, link, frame);
+}
+
+/** Set an option of the given filter to the provided key-value pair.
+ */
+static void set_option(CoreImageContext *ctx, CIFilter *filter, const char *key, const char *value)
+{
+        NSString *input_key = [NSString stringWithUTF8String:key];
+        NSString *input_val = [NSString stringWithUTF8String:value];
+
+        NSDictionary *filter_attribs = [filter attributes]; // <nsstring, id>
+        NSDictionary *input_attribs  = [filter_attribs valueForKey:input_key];
+
+        NSString *input_class = [input_attribs valueForKey:kCIAttributeClass];
+        NSString *input_type  = [input_attribs valueForKey:kCIAttributeType];
+
+        if (!input_attribs) {
+            av_log(ctx, AV_LOG_WARNING, "Skipping unknown option: \"%s\".\n",
+                   [input_key UTF8String]); // [[filter name] UTF8String]) not currently defined...
+            return;
+        }
+
+        av_log(ctx, AV_LOG_DEBUG, "key: %s, val: %s, #attribs: %lu, class: %s, type: %s\n",
+               [input_key UTF8String],
+               [input_val UTF8String],
+               input_attribs ? (unsigned long)[input_attribs count] : -1,
+               [input_class UTF8String],
+               [input_type UTF8String]);
+
+        if ([input_class isEqualToString:@"NSNumber"]) {
+            float input          = input_val.floatValue;
+            NSNumber *max_value  = [input_attribs valueForKey:kCIAttributeSliderMax];
+            NSNumber *min_value  = [input_attribs valueForKey:kCIAttributeSliderMin];
+            NSNumber *used_value = nil;
+
+#define CLAMP_WARNING do {     \
+av_log(ctx, AV_LOG_WARNING, "Value of \"%f\" for option \"%s\" is out of range [%f %f], clamping to \"%f\".\n", \
+       input,                  \
+       [input_key UTF8String], \
+       min_value.floatValue,   \
+       max_value.floatValue,   \
+       used_value.floatValue); \
+} while(0)
+            if (input > max_value.floatValue) {
+                used_value = max_value;
+                CLAMP_WARNING;
+            } else if (input < min_value.floatValue) {
+                used_value = min_value;
+                CLAMP_WARNING;
+            } else {
+                used_value = [NSNumber numberWithFloat:input];
+            }
+
+            [filter setValue:used_value forKey:input_key];
+        } else if ([input_class isEqualToString:@"CIVector"]) {
+            CIVector *input = [CIVector vectorWithString:input_val];
+
+            if (!input) {
+                av_log(ctx, AV_LOG_WARNING, "Skipping invalid CIVctor description: \"%s\".\n",
+                       [input_val UTF8String]);
+                return;
+            }
+
+            [filter setValue:input forKey:input_key];
+        } else if ([input_class isEqualToString:@"CIColor"]) {
+            CIColor *input = [CIColor colorWithString:input_val];
+
+            if (!input) {
+                av_log(ctx, AV_LOG_WARNING, "Skipping invalid CIColor description: \"%s\".\n",
+                       [input_val UTF8String]);
+                return;
+            }
+
+            [filter setValue:input forKey:input_key];
+        } else if ([input_class isEqualToString:@"NSString"]) { // set display name as string with latin1 encoding
+            [filter setValue:input_val forKey:input_key];
+        } else if ([input_class isEqualToString:@"NSData"]) { // set display name as string with latin1 encoding
+            NSData *input = [NSData dataWithBytes:(const void*)[input_val cStringUsingEncoding:NSISOLatin1StringEncoding]
+                                    length:[input_val lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]];
+
+            if (!input) {
+                av_log(ctx, AV_LOG_WARNING, "Skipping invalid NSData description: \"%s\".\n",
+                       [input_val UTF8String]);
+                return;
+            }
+
+            [filter setValue:input forKey:input_key];
+        } else {
+            av_log(ctx, AV_LOG_WARNING, "Skipping unsupported option class: \"%s\".\n",
+                   [input_class UTF8String]);
+            avpriv_report_missing_feature(ctx, "Handling of some option classes");
+            return;
+        }
+}
+
+/** Create a filter object by a given name and set all options to defaults.
+ *  Overwrite any option given by the user to the provided value in filter_options.
+ */
+static CIFilter* create_filter(CoreImageContext *ctx, const char *filter_name, AVDictionary *filter_options)
+{
+    // create filter object
+    CIFilter *filter = [CIFilter filterWithName:[NSString stringWithUTF8String:filter_name]];
+
+    // set default options
+    [filter setDefaults];
+
+    // set user options
+    if (filter_options) {
+        AVDictionaryEntry *o = NULL;
+        while ((o = av_dict_get(filter_options, "", o, AV_DICT_IGNORE_SUFFIX))) {
+            set_option(ctx, filter, o->key, o->value);
+        }
+    }
+
+    return filter;
+}
+
+static av_cold int init(AVFilterContext *fctx)
+{
+    CoreImageContext *ctx     = fctx->priv;
+    AVDictionary *filter_dict = NULL;
+    AVDictionaryEntry *f      = NULL;
+    AVDictionaryEntry *o      = NULL;
+    int ret;
+    int i;
+
+    if (ctx->list_filters || ctx->list_generators) {
+        list_filters(ctx);
+        return AVERROR_EXIT;
+    }
+
+    if (ctx->filter_string) {
+        // parse filter string (filter=name at opt=val at opt2=val2#name2 at opt3=val3) for filters separated by #
+        av_log(ctx, AV_LOG_DEBUG, "Filter_string: %s\n", ctx->filter_string);
+        ret = av_dict_parse_string(&filter_dict, ctx->filter_string, "@", "#", AV_DICT_MULTIKEY); // parse filter_name:all_filter_options
+        if (ret) {
+            av_log(ctx, AV_LOG_ERROR, "Parsing of filters failed.\n");
+            return AVERROR(EIO);
+        }
+        ctx->num_filters = av_dict_count(filter_dict);
+        av_log(ctx, AV_LOG_DEBUG, "Filter count: %i\n", ctx->num_filters);
+
+        // allocate CIFilter array
+        ctx->filters = av_mallocz_array(ctx->num_filters, sizeof(CIFilter*));
+        if (!ctx->filters) {
+            av_log(ctx, AV_LOG_ERROR, "Could not allocate filter array.\n");
+            return AVERROR(ENOMEM);
+        }
+
+        // parse filters for option key-value pairs (opt=val at opt2=val2) separated by @
+        i = 0;
+        while ((f = av_dict_get(filter_dict, "", f, AV_DICT_IGNORE_SUFFIX))) {
+            AVDictionary *filter_options = NULL;
+
+            if (strncmp(f->value, "default", 7)) { // not default
+                ret = av_dict_parse_string(&filter_options, f->value, "=", "@", 0); // parse option_name:option_value
+                if (ret) {
+                    av_log(ctx, AV_LOG_ERROR, "Parsing of filter options for \"%s\" failed.\n", f->key);
+                    return AVERROR(EIO);
+                }
+            }
+
+            if (av_log_get_level() >= AV_LOG_DEBUG) {
+                av_log(ctx, AV_LOG_DEBUG, "Creating filter %i: \"%s\":\n", i, f->key);
+                if (!filter_options) {
+                    av_log(ctx, AV_LOG_DEBUG, "\tusing default options\n");
+                } else {
+                    while ((o = av_dict_get(filter_options, "", o, AV_DICT_IGNORE_SUFFIX))) {
+                        av_log(ctx, AV_LOG_DEBUG, "\t%s: %s\n", o->key, o->value);
+                    }
+                }
+            }
+
+            ctx->filters[i] = CFBridgingRetain(create_filter(ctx, f->key, filter_options));
+            if (!ctx->filters[i]) {
+                av_log(ctx, AV_LOG_ERROR, "Could not create filter \"%s\".\n", f->key);
+                return AVERROR(EINVAL);
+            }
+
+            i++;
+        }
+    } else {
+        av_log(ctx, AV_LOG_ERROR, "No filters specified.\n");
+        return AVERROR(EINVAL);
+    }
+
+    // create GPU context on OSX
+    const NSOpenGLPixelFormatAttribute attr[] = {
+        NSOpenGLPFAAccelerated,
+        NSOpenGLPFANoRecovery,
+        NSOpenGLPFAColorSize, 32,
+        0
+    };
+
+    NSOpenGLPixelFormat *pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:(void *)&attr];
+    ctx->color_space                  = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+    ctx->glctx                        = CFBridgingRetain([CIContext contextWithCGLContext:CGLGetCurrentContext()
+                                                         pixelFormat:[pixel_format CGLPixelFormatObj]
+                                                         colorSpace:ctx->color_space
+                                                         options:nil]);
+
+    if (!ctx->glctx) {
+        av_log(ctx, AV_LOG_ERROR, "CIContext not created.\n");
+        return AVERROR_EXTERNAL;
+    }
+
+    // Creating an empty input image as input container for the context
+    ctx->input_image = CFBridgingRetain([CIImage emptyImage]);
+
+    return 0;
+}
+
+static av_cold int init_src(AVFilterContext *fctx)
+{
+    CoreImageContext *ctx = fctx->priv;
+
+    ctx->is_video_source = 1;
+    ctx->time_base       = av_inv_q(ctx->frame_rate);
+    ctx->pts             = 0;
+
+    return init(fctx);
+}
+
+static av_cold void uninit(AVFilterContext *fctx)
+{
+#define SafeCFRelease(ptr) do { \
+    if (ptr) {                  \
+        CFRelease(ptr);         \
+        ptr = NULL;             \
+    }                           \
+} while (0)
+
+    CoreImageContext *ctx = fctx->priv;
+
+    SafeCFRelease(ctx->glctx);
+    SafeCFRelease(ctx->cgctx);
+    SafeCFRelease(ctx->color_space);
+    SafeCFRelease(ctx->input_image);
+
+    if (ctx->filters) {
+        for (int i = 0; i < ctx->num_filters; i++) {
+            SafeCFRelease(ctx->filters[i]);
+        }
+        av_freep(&ctx->filters);
+    }
+
+    av_frame_free(&ctx->picref);
+}
+
+static const AVFilterPad vf_coreimage_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+        .config_props = config_input,
+    },
+    { NULL }
+};
+
+static const AVFilterPad vf_coreimage_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+    },
+    { NULL }
+};
+
+static const AVFilterPad vsrc_coreimagesrc_outputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_VIDEO,
+        .request_frame = request_frame,
+        .config_props  = config_output,
+    },
+    { NULL }
+};
+
+#define OFFSET(x) offsetof(CoreImageContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+#define GENERATOR_OPTIONS                                                                                                               \
+    {"size",     "set video size",                OFFSET(w),          AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0,         FLAGS}, \
+    {"s",        "set video size",                OFFSET(w),          AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0,         FLAGS}, \
+    {"rate",     "set video rate",                OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"},      0, INT_MAX,         FLAGS}, \
+    {"r",        "set video rate",                OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"},      0, INT_MAX,         FLAGS}, \
+    {"duration", "set video duration",            OFFSET(duration),   AV_OPT_TYPE_DURATION,   {.i64 = -1},       -1, INT64_MAX, FLAGS}, \
+    {"d",        "set video duration",            OFFSET(duration),   AV_OPT_TYPE_DURATION,   {.i64 = -1},       -1, INT64_MAX, FLAGS}, \
+    {"sar",      "set video sample aspect ratio", OFFSET(sar),        AV_OPT_TYPE_RATIONAL,   {.dbl = 1},         0, INT_MAX,   FLAGS},
+
+#define FILTER_OPTIONS                                                                                                                           \
+    {"list_filters",    "list available filters",                OFFSET(list_filters),    AV_OPT_TYPE_BOOL,   {.i64 = 0}, 0, 1, .flags = FLAGS}, \
+    {"list_generators", "list available generators",             OFFSET(list_generators), AV_OPT_TYPE_BOOL,   {.i64 = 0}, 0, 1, .flags = FLAGS}, \
+    {"filter",          "names and options of filters to apply", OFFSET(filter_string),   AV_OPT_TYPE_STRING, {.str = NULL},    .flags = FLAGS}, \
+    {"output_rect",     "output rectangle within output image",  OFFSET(output_rect),     AV_OPT_TYPE_STRING, {.str = NULL},    .flags = FLAGS},
+
+
+// definitions for coreimage video filter
+static const AVOption coreimage_options[] = {
+    FILTER_OPTIONS
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(coreimage);
+
+AVFilter ff_vf_coreimage = {
+    .name          = "coreimage",
+    .description   = NULL_IF_CONFIG_SMALL("Video filtering using CoreImage API."),
+    .init          = init,
+    .uninit        = uninit,
+    .priv_size     = sizeof(CoreImageContext),
+    .priv_class    = &coreimage_class,
+    .inputs        = vf_coreimage_inputs,
+    .outputs       = vf_coreimage_outputs,
+    .query_formats = query_formats,
+};
+
+// definitions for coreimagesrc video source
+static const AVOption coreimagesrc_options[] = {
+    GENERATOR_OPTIONS
+    FILTER_OPTIONS
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(coreimagesrc);
+
+AVFilter ff_vsrc_coreimagesrc = {
+    .name          = "coreimagesrc",
+    .description   = NULL_IF_CONFIG_SMALL("Video source using image generators of CoreImage API."),
+    .init          = init_src,
+    .uninit        = uninit,
+    .priv_size     = sizeof(CoreImageContext),
+    .priv_class    = &coreimagesrc_class,
+    .inputs        = NULL,
+    .outputs       = vsrc_coreimagesrc_outputs,
+    .query_formats = query_formats_src,
+};
diff --git a/libavfilter/vf_datascope.c b/libavfilter/vf_datascope.c
new file mode 100644
index 0000000..3c82a0e
--- /dev/null
+++ b/libavfilter/vf_datascope.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * 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/avassert.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
+#include "libavutil/parseutils.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/xga_font_data.h"
+#include "avfilter.h"
+#include "drawutils.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+typedef struct DatascopeContext {
+    const AVClass *class;
+    int ow, oh;
+    int x, y;
+    int mode;
+    int axis;
+
+    int nb_planes;
+    int nb_comps;
+    int chars;
+    FFDrawContext draw;
+    FFDrawColor yellow;
+    FFDrawColor white;
+    FFDrawColor black;
+    FFDrawColor gray;
+
+    int (*filter)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
+} DatascopeContext;
+
+#define OFFSET(x) offsetof(DatascopeContext, x)
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+
+static const AVOption datascope_options[] = {
+    { "size", "set output size", OFFSET(ow),   AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, FLAGS },
+    { "s",    "set output size", OFFSET(ow),   AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, FLAGS },
+    { "x",    "set x offset", OFFSET(x),    AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
+    { "y",    "set y offset", OFFSET(y),    AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
+    { "mode", "set scope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "mode" },
+    {   "mono",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" },
+    {   "color",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" },
+    {   "color2", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "mode" },
+    { "axis",    "draw column/row numbers", OFFSET(axis), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(datascope);
+
+static int query_formats(AVFilterContext *ctx)
+{
+    return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0));
+}
+
+static void draw_text(DatascopeContext *s, AVFrame *frame, FFDrawColor *color,
+                      int x0, int y0, const uint8_t *text, int vertical)
+{
+    int x = x0;
+
+    for (; *text; text++) {
+        if (*text == '\n') {
+            x = x0;
+            y0 += 8;
+            continue;
+        }
+        ff_blend_mask(&s->draw, color, frame->data, frame->linesize,
+                      frame->width, frame->height,
+                      avpriv_cga_font + *text * 8, 1, 8, 8, 0, 0, x, y0);
+        if (vertical) {
+            x = x0;
+            y0 += 8;
+        } else {
+            x += 8;
+        }
+    }
+}
+
+static void pick_color(FFDrawContext *draw, FFDrawColor *color, AVFrame *in, int x, int y, int *value)
+{
+    int p, i;
+
+    color->rgba[3] = 255;
+    for (p = 0; p < draw->nb_planes; p++) {
+        if (draw->desc->comp[p].depth == 8) {
+            if (draw->nb_planes == 1) {
+                for (i = 0; i < 4; i++) {
+                    value[i] = in->data[0][y * in->linesize[0] + x * draw->pixelstep[0] + i];
+                    color->comp[0].u8[i] = value[i];
+                }
+            } else {
+                value[p] = in->data[p][(y >> draw->vsub[p]) * in->linesize[p] + (x >> draw->hsub[p])];
+                color->comp[p].u8[0] = value[p];
+            }
+        } else {
+            if (draw->nb_planes == 1) {
+                for (i = 0; i < 4; i++) {
+                    value[i] = AV_RL16(in->data[0] + y * in->linesize[0] + x * draw->pixelstep[0] + i * 2);
+                    color->comp[0].u16[i] = value[i];
+                }
+            } else {
+                value[p] = AV_RL16(in->data[p] + (y >> draw->vsub[p]) * in->linesize[p] + (x >> draw->hsub[p]) * 2);
+                color->comp[p].u16[0] = value[p];
+            }
+        }
+    }
+}
+
+static void reverse_color(FFDrawContext *draw, FFDrawColor *color, FFDrawColor *reverse)
+{
+    int p;
+
+    reverse->rgba[3] = 255;
+    for (p = 0; p < draw->nb_planes; p++) {
+        if (draw->desc->comp[p].depth == 8) {
+            reverse->comp[p].u8[0] = color->comp[p].u8[0] > 127 ? 0 : 255;
+            reverse->comp[p].u8[1] = color->comp[p].u8[1] > 127 ? 0 : 255;
+            reverse->comp[p].u8[2] = color->comp[p].u8[2] > 127 ? 0 : 255;
+            reverse->comp[p].u8[3] = color->comp[p].u8[3] > 127 ? 0 : 255;
+        } else {
+            const unsigned max = (1 << draw->desc->comp[p].depth) - 1;
+            const unsigned mid = (max + 1) / 2;
+
+            reverse->comp[p].u16[0] = color->comp[p].u16[0] > mid ? 0 : max;
+            reverse->comp[p].u16[1] = color->comp[p].u16[1] > mid ? 0 : max;
+            reverse->comp[p].u16[2] = color->comp[p].u16[2] > mid ? 0 : max;
+            reverse->comp[p].u16[3] = color->comp[p].u16[3] > mid ? 0 : max;
+        }
+    }
+}
+
+typedef struct ThreadData {
+    AVFrame *in, *out;
+    int xoff, yoff;
+} ThreadData;
+
+static int filter_color2(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    DatascopeContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFilterLink *inlink = ctx->inputs[0];
+    ThreadData *td = arg;
+    AVFrame *in = td->in;
+    AVFrame *out = td->out;
+    const int xoff = td->xoff;
+    const int yoff = td->yoff;
+    const int P = FFMAX(s->nb_planes, s->nb_comps);
+    const int C = s->chars;
+    const int W = (outlink->w - xoff) / (C * 10);
+    const int H = (outlink->h - yoff) / (P * 12);
+    const char *format[2] = {"%02X\n", "%04X\n"};
+    const int slice_start = (W * jobnr) / nb_jobs;
+    const int slice_end = (W * (jobnr+1)) / nb_jobs;
+    int x, y, p;
+
+    for (y = 0; y < H && (y + s->y < inlink->h); y++) {
+        for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
+            FFDrawColor color = { { 0 } };
+            FFDrawColor reverse = { { 0 } };
+            int value[4] = { 0 };
+
+            pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
+            reverse_color(&s->draw, &color, &reverse);
+            ff_fill_rectangle(&s->draw, &color, out->data, out->linesize,
+                              xoff + x * C * 10, yoff + y * P * 12, C * 10, P * 12);
+
+            for (p = 0; p < P; p++) {
+                char text[256];
+
+                snprintf(text, sizeof(text), format[C>>2], value[p]);
+                draw_text(s, out, &reverse, xoff + x * C * 10 + 2, yoff + y * P * 12 + p * 10 + 2, text, 0);
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int filter_color(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    DatascopeContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFilterLink *inlink = ctx->inputs[0];
+    ThreadData *td = arg;
+    AVFrame *in = td->in;
+    AVFrame *out = td->out;
+    const int xoff = td->xoff;
+    const int yoff = td->yoff;
+    const int P = FFMAX(s->nb_planes, s->nb_comps);
+    const int C = s->chars;
+    const int W = (outlink->w - xoff) / (C * 10);
+    const int H = (outlink->h - yoff) / (P * 12);
+    const char *format[2] = {"%02X\n", "%04X\n"};
+    const int slice_start = (W * jobnr) / nb_jobs;
+    const int slice_end = (W * (jobnr+1)) / nb_jobs;
+    int x, y, p;
+
+    for (y = 0; y < H && (y + s->y < inlink->h); y++) {
+        for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
+            FFDrawColor color = { { 0 } };
+            int value[4] = { 0 };
+
+            pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
+
+            for (p = 0; p < P; p++) {
+                char text[256];
+
+                snprintf(text, sizeof(text), format[C>>2], value[p]);
+                draw_text(s, out, &color, xoff + x * C * 10 + 2, yoff + y * P * 12 + p * 10 + 2, text, 0);
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int filter_mono(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    DatascopeContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFilterLink *inlink = ctx->inputs[0];
+    ThreadData *td = arg;
+    AVFrame *in = td->in;
+    AVFrame *out = td->out;
+    const int xoff = td->xoff;
+    const int yoff = td->yoff;
+    const int P = FFMAX(s->nb_planes, s->nb_comps);
+    const int C = s->chars;
+    const int W = (outlink->w - xoff) / (C * 10);
+    const int H = (outlink->h - yoff) / (P * 12);
+    const char *format[2] = {"%02X\n", "%04X\n"};
+    const int slice_start = (W * jobnr) / nb_jobs;
+    const int slice_end = (W * (jobnr+1)) / nb_jobs;
+    int x, y, p;
+
+    for (y = 0; y < H && (y + s->y < inlink->h); y++) {
+        for (x = slice_start; x < slice_end && (x + s->x < inlink->w); x++) {
+            FFDrawColor color = { { 0 } };
+            int value[4] = { 0 };
+
+            pick_color(&s->draw, &color, in, x + s->x, y + s->y, value);
+            for (p = 0; p < P; p++) {
+                char text[256];
+
+                snprintf(text, sizeof(text), format[C>>2], value[p]);
+                draw_text(s, out, &s->white, xoff + x * C * 10 + 2, yoff + y * P * 12 + p * 10 + 2, text, 0);
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx  = inlink->dst;
+    DatascopeContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    ThreadData td = { 0 };
+    int ymaxlen = 0;
+    int xmaxlen = 0;
+    AVFrame *out;
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        av_frame_free(&in);
+        return AVERROR(ENOMEM);
+    }
+    out->pts = in->pts;
+
+    ff_fill_rectangle(&s->draw, &s->black, out->data, out->linesize,
+                      0, 0, outlink->w, outlink->h);
+
+    if (s->axis) {
+        const int P = FFMAX(s->nb_planes, s->nb_comps);
+        const int C = s->chars;
+        int Y = outlink->h / (P * 12);
+        int X = outlink->w / (C * 10);
+        char text[256] = { 0 };
+        int x, y;
+
+        snprintf(text, sizeof(text), "%d", s->y + Y);
+        ymaxlen = strlen(text);
+        ymaxlen *= 10;
+        snprintf(text, sizeof(text), "%d", s->x + X);
+        xmaxlen = strlen(text);
+        xmaxlen *= 10;
+
+        Y = (outlink->h - xmaxlen) / (P * 12);
+        X = (outlink->w - ymaxlen) / (C * 10);
+
+        for (y = 0; y < Y; y++) {
+            snprintf(text, sizeof(text), "%d", s->y + y);
+
+            ff_fill_rectangle(&s->draw, &s->gray, out->data, out->linesize,
+                              0, xmaxlen + y * P * 12 + (P + 1) * P - 2, ymaxlen, 10);
+
+            draw_text(s, out, &s->yellow, 2, xmaxlen + y * P * 12 + (P + 1) * P, text, 0);
+        }
+
+        for (x = 0; x < X; x++) {
+            snprintf(text, sizeof(text), "%d", s->x + x);
+
+            ff_fill_rectangle(&s->draw, &s->gray, out->data, out->linesize,
+                              ymaxlen + x * C * 10 + 2 * C - 2, 0, 10, xmaxlen);
+
+            draw_text(s, out, &s->yellow, ymaxlen + x * C * 10 + 2 * C, 2, text, 1);
+        }
+    }
+
+    td.in = in; td.out = out, td.yoff = xmaxlen, td.xoff = ymaxlen;
+    ctx->internal->execute(ctx, s->filter, &td, NULL, FFMIN(ctx->graph->nb_threads, FFMAX(outlink->w / 20, 1)));
+
+    av_frame_free(&in);
+    return ff_filter_frame(outlink, out);
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+    DatascopeContext *s = inlink->dst->priv;
+
+    s->nb_planes = av_pix_fmt_count_planes(inlink->format);
+    ff_draw_init(&s->draw, inlink->format, 0);
+    ff_draw_color(&s->draw, &s->white,  (uint8_t[]){ 255, 255, 255, 255} );
+    ff_draw_color(&s->draw, &s->black,  (uint8_t[]){ 0, 0, 0, 0} );
+    ff_draw_color(&s->draw, &s->yellow, (uint8_t[]){ 255, 255, 0, 255} );
+    ff_draw_color(&s->draw, &s->gray,   (uint8_t[]){ 77, 77, 77, 255} );
+    s->chars = (s->draw.desc->comp[0].depth + 7) / 8 * 2;
+    s->nb_comps = s->draw.desc->nb_components;
+
+    switch (s->mode) {
+    case 0: s->filter = filter_mono;   break;
+    case 1: s->filter = filter_color;  break;
+    case 2: s->filter = filter_color2; break;
+    }
+
+    return 0;
+}
+
+static int config_output(AVFilterLink *outlink)
+{
+    DatascopeContext *s = outlink->src->priv;
+
+    outlink->h = s->oh;
+    outlink->w = s->ow;
+    outlink->sample_aspect_ratio = (AVRational){1,1};
+
+    return 0;
+}
+
+static const AVFilterPad inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+        .config_props = config_input,
+    },
+    { NULL }
+};
+
+static const AVFilterPad outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = config_output,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_datascope = {
+    .name          = "datascope",
+    .description   = NULL_IF_CONFIG_SMALL("Video data analysis."),
+    .priv_size     = sizeof(DatascopeContext),
+    .priv_class    = &datascope_class,
+    .query_formats = query_formats,
+    .inputs        = inputs,
+    .outputs       = outputs,
+    .flags         = AVFILTER_FLAG_SLICE_THREADS,
+};
diff --git a/libavfilter/vf_decimate.c b/libavfilter/vf_decimate.c
index e2c0a32..39c3331 100644
--- a/libavfilter/vf_decimate.c
+++ b/libavfilter/vf_decimate.c
@@ -164,9 +164,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         return 0;
     dm->got_frame[INPUT_MAIN] = dm->got_frame[INPUT_CLEANSRC] = 0;
 
+    if (dm->ppsrc)
+        in = dm->clean_src[dm->fid];
+
     if (in) {
         /* update frame metrics */
-        prv = dm->fid ? dm->queue[dm->fid - 1].frame : dm->last;
+        prv = dm->fid ? (dm->ppsrc ? dm->clean_src[dm->fid - 1] : dm->queue[dm->fid - 1].frame) : dm->last;
         if (!prv) {
             dm->queue[dm->fid].maxbdiff = INT64_MAX;
             dm->queue[dm->fid].totdiff  = INT64_MAX;
@@ -365,8 +368,6 @@ static int config_output(AVFilterLink *outlink)
     DecimateContext *dm = ctx->priv;
     const AVFilterLink *inlink =
         ctx->inputs[dm->ppsrc ? INPUT_CLEANSRC : INPUT_MAIN];
-    const AVFilterLink *inlink_main =
-        ctx->inputs[INPUT_MAIN];
     AVRational fps = inlink->frame_rate;
 
     if (!fps.num || !fps.den) {
@@ -374,13 +375,6 @@ static int config_output(AVFilterLink *outlink)
                "current rate of %d/%d is invalid\n", fps.num, fps.den);
         return AVERROR(EINVAL);
     }
-
-    if (inlink->w != inlink_main->w ||
-        inlink->h != inlink_main->h ||
-        inlink->format != inlink_main->format) {
-        av_log(ctx, AV_LOG_ERROR, "frame parameters differ between inputs\n");
-        return AVERROR_PATCHWELCOME;
-    }
     fps = av_mul_q(fps, (AVRational){dm->cycle - 1, dm->cycle});
     av_log(ctx, AV_LOG_VERBOSE, "FPS: %d/%d -> %d/%d\n",
            inlink->frame_rate.num, inlink->frame_rate.den, fps.num, fps.den);
diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c
index 63c3539..065d093 100644
--- a/libavfilter/vf_delogo.c
+++ b/libavfilter/vf_delogo.c
@@ -226,6 +226,20 @@ static av_cold int init(AVFilterContext *ctx)
     return 0;
 }
 
+static int config_input(AVFilterLink *inlink)
+{
+    DelogoContext *s = inlink->dst->priv;
+
+    /* Check whether the logo area fits in the frame */
+    if (s->x + (s->band - 1) < 0 || s->x + s->w - (s->band*2 - 2) > inlink->w ||
+        s->y + (s->band - 1) < 0 || s->y + s->h - (s->band*2 - 2) > inlink->h) {
+        av_log(s, AV_LOG_ERROR, "Logo area is outside of the frame.\n");
+        return AVERROR(EINVAL);
+    }
+
+    return 0;
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
     DelogoContext *s = inlink->dst->priv;
@@ -284,6 +298,7 @@ static const AVFilterPad avfilter_vf_delogo_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
+        .config_props = config_input,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_detelecine.c b/libavfilter/vf_detelecine.c
index 6fd9aad..9a7b462 100644
--- a/libavfilter/vf_detelecine.c
+++ b/libavfilter/vf_detelecine.c
@@ -37,6 +37,7 @@ typedef struct {
     int first_field;
     char *pattern;
     int start_frame;
+    int init_len;
     unsigned int pattern_pos;
     unsigned int nskip_fields;
     int64_t start_time;
@@ -49,7 +50,7 @@ typedef struct {
     int planeheight[4];
     int stride[4];
 
-    AVFrame *frame;
+    AVFrame *frame[2];
     AVFrame *temp;
 } DetelecineContext;
 
@@ -74,6 +75,7 @@ static av_cold int init(AVFilterContext *ctx)
     DetelecineContext *s = ctx->priv;
     const char *p;
     int max = 0;
+    int sum = 0;
 
     if (!strlen(s->pattern)) {
         av_log(ctx, AV_LOG_ERROR, "No pattern provided.\n");
@@ -86,14 +88,21 @@ static av_cold int init(AVFilterContext *ctx)
             return AVERROR_INVALIDDATA;
         }
 
+        sum += *p - '0';
         max = FFMAX(*p - '0', max);
         s->pts.num += *p - '0';
         s->pts.den += 2;
     }
 
+    if (s->start_frame >= sum) {
+        av_log(ctx, AV_LOG_ERROR, "Provided start_frame is too big.\n");
+        return AVERROR_INVALIDDATA;
+    }
+
     s->nskip_fields = 0;
     s->pattern_pos = 0;
     s->start_time = AV_NOPTS_VALUE;
+    s->init_len = 0;
 
     if (s->start_frame != 0) {
         int nfields = 0;
@@ -101,7 +110,7 @@ static av_cold int init(AVFilterContext *ctx)
             nfields += *p - '0';
             s->pattern_pos++;
             if (nfields >= 2*s->start_frame) {
-                s->nskip_fields = nfields - 2*s->start_frame;
+                s->init_len = nfields - 2*s->start_frame;
                 break;
             }
         }
@@ -140,8 +149,12 @@ static int config_input(AVFilterLink *inlink)
     if (!s->temp)
         return AVERROR(ENOMEM);
 
-    s->frame = ff_get_video_buffer(inlink, inlink->w, inlink->h);
-    if (!s->frame)
+    s->frame[0] = ff_get_video_buffer(inlink, inlink->w, inlink->h);
+    if (!s->frame[0])
+        return AVERROR(ENOMEM);
+
+    s->frame[1] = ff_get_video_buffer(inlink, inlink->w, inlink->h);
+    if (!s->frame[1])
         return AVERROR(ENOMEM);
 
     if ((ret = av_image_fill_linesizes(s->stride, inlink->format, inlink->w)) < 0)
@@ -195,24 +208,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
         s->nskip_fields -= 2;
         return 0;
     } else if (s->nskip_fields >= 1) {
-        if (s->occupied) {
-            s->occupied = 0;
-            s->nskip_fields--;
-        }
-        else {
-            for (i = 0; i < s->nb_planes; i++) {
-                av_image_copy_plane(s->temp->data[i], s->temp->linesize[i],
-                                    inpicref->data[i], inpicref->linesize[i],
-                                    s->stride[i],
-                                    s->planeheight[i]);
-            }
-            s->occupied = 1;
-            s->nskip_fields--;
-            return 0;
+        for (i = 0; i < s->nb_planes; i++) {
+            av_image_copy_plane(s->temp->data[i], s->temp->linesize[i],
+                                inpicref->data[i], inpicref->linesize[i],
+                                s->stride[i],
+                                s->planeheight[i]);
         }
+        s->occupied = 1;
+        s->nskip_fields--;
+        return 0;
     }
 
     if (s->nskip_fields == 0) {
+        len = s->init_len;
+        s->init_len = 0;
         while(!len && s->pattern[s->pattern_pos]) {
             len = s->pattern[s->pattern_pos] - '0';
             s->pattern_pos++;
@@ -226,58 +235,85 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
             return 0;
         }
 
+        if (len == 1 && s->occupied) {
+            s->occupied = 0;
+            // output THIS image as-is
+            for (i = 0; i < s->nb_planes; i++)
+                av_image_copy_plane(s->frame[out]->data[i], s->frame[out]->linesize[i],
+                                    s->temp->data[i], s->temp->linesize[i],
+                                    s->stride[i],
+                                    s->planeheight[i]);
+            len = 0;
+            while(!len && s->pattern[s->pattern_pos]) {
+                len = s->pattern[s->pattern_pos] - '0';
+                s->pattern_pos++;
+            }
+
+            if (!s->pattern[s->pattern_pos])
+                s->pattern_pos = 0;
+
+            s->occupied = 0;
+            ++out;
+        }
+
         if (s->occupied) {
             for (i = 0; i < s->nb_planes; i++) {
                 // fill in the EARLIER field from the new pic
-                av_image_copy_plane(s->frame->data[i] + s->frame->linesize[i] * s->first_field,
-                                    s->frame->linesize[i] * 2,
+                av_image_copy_plane(s->frame[out]->data[i] + s->frame[out]->linesize[i] * s->first_field,
+                                    s->frame[out]->linesize[i] * 2,
                                     inpicref->data[i] + inpicref->linesize[i] * s->first_field,
                                     inpicref->linesize[i] * 2,
                                     s->stride[i],
                                     (s->planeheight[i] - s->first_field + 1) / 2);
                 // fill in the LATER field from the buffered pic
-                av_image_copy_plane(s->frame->data[i] + s->frame->linesize[i] * !s->first_field,
-                                    s->frame->linesize[i] * 2,
+                av_image_copy_plane(s->frame[out]->data[i] + s->frame[out]->linesize[i] * !s->first_field,
+                                    s->frame[out]->linesize[i] * 2,
                                     s->temp->data[i] + s->temp->linesize[i] * !s->first_field,
                                     s->temp->linesize[i] * 2,
                                     s->stride[i],
                                     (s->planeheight[i] - !s->first_field + 1) / 2);
             }
-            len -= 2;
-            for (i = 0; i < s->nb_planes; i++) {
-                av_image_copy_plane(s->temp->data[i], s->temp->linesize[i],
-                                    inpicref->data[i], inpicref->linesize[i],
-                                    s->stride[i],
-                                    s->planeheight[i]);
+
+            s->occupied = 0;
+            if (len <= 2) {
+                for (i = 0; i < s->nb_planes; i++) {
+                    av_image_copy_plane(s->temp->data[i], s->temp->linesize[i],
+                                        inpicref->data[i], inpicref->linesize[i],
+                                        s->stride[i],
+                                        s->planeheight[i]);
+                }
+                s->occupied = 1;
             }
-            s->occupied = 1;
-            out = 1;
+            ++out;
+            len = (len >= 3) ? len - 3 : 0;
         } else {
             if (len >= 2) {
                 // output THIS image as-is
                 for (i = 0; i < s->nb_planes; i++)
-                    av_image_copy_plane(s->frame->data[i], s->frame->linesize[i],
+                    av_image_copy_plane(s->frame[out]->data[i], s->frame[out]->linesize[i],
                                         inpicref->data[i], inpicref->linesize[i],
                                         s->stride[i],
                                         s->planeheight[i]);
                 len -= 2;
-                out = 1;
+                ++out;
             } else if (len == 1) {
-                // fill in the EARLIER field from the new pic
-                for (i = 0; i < s->nb_planes; i++) {
-                    av_image_copy_plane(s->frame->data[i] +
-                                        s->frame->linesize[i] * s->first_field,
-                                        s->frame->linesize[i] * 2,
-                                        inpicref->data[i] +
-                                        inpicref->linesize[i] * s->first_field,
-                                        inpicref->linesize[i] * 2, s->stride[i],
-                                        (s->planeheight[i] - s->first_field + 1) / 2);
-                 }
+                // output THIS image as-is
+                for (i = 0; i < s->nb_planes; i++)
+                    av_image_copy_plane(s->frame[out]->data[i], s->frame[out]->linesize[i],
+                                        inpicref->data[i], inpicref->linesize[i],
+                                        s->stride[i],
+                                        s->planeheight[i]);
 
-                // TODO: not sure about the other field
+                for (i = 0; i < s->nb_planes; i++) {
+                    av_image_copy_plane(s->temp->data[i], s->temp->linesize[i],
+                                        inpicref->data[i], inpicref->linesize[i],
+                                        s->stride[i],
+                                        s->planeheight[i]);
+                }
+                s->occupied = 1;
 
                 len--;
-                out = 1;
+                ++out;
             }
         }
 
@@ -289,8 +325,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
     }
     s->nskip_fields = len;
 
-    if (out) {
-        AVFrame *frame = av_frame_clone(s->frame);
+    for (i = 0; i < out; ++i) {
+        AVFrame *frame = av_frame_clone(s->frame[i]);
 
         if (!frame) {
             av_frame_free(&inpicref);
@@ -314,7 +350,8 @@ static av_cold void uninit(AVFilterContext *ctx)
     DetelecineContext *s = ctx->priv;
 
     av_frame_free(&s->temp);
-    av_frame_free(&s->frame);
+    av_frame_free(&s->frame[0]);
+    av_frame_free(&s->frame[1]);
 }
 
 static const AVFilterPad detelecine_inputs[] = {
diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c
index 35a08e8..88bb9ae 100644
--- a/libavfilter/vf_drawbox.c
+++ b/libavfilter/vf_drawbox.c
@@ -79,6 +79,7 @@ typedef struct DrawBoxContext {
     char *x_expr, *y_expr; ///< expression for x and y
     char *w_expr, *h_expr; ///< expression for width and height
     char *t_expr;          ///< expression for thickness
+    int have_alpha;
 } DrawBoxContext;
 
 static const int NUM_EXPR_EVALS = 5;
@@ -110,6 +111,7 @@ static int query_formats(AVFilterContext *ctx)
         AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUV410P,
         AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P,
         AV_PIX_FMT_YUV440P,  AV_PIX_FMT_YUVJ440P,
+        AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
         AV_PIX_FMT_NONE
     };
     AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
@@ -130,6 +132,7 @@ static int config_input(AVFilterLink *inlink)
 
     s->hsub = desc->log2_chroma_w;
     s->vsub = desc->log2_chroma_h;
+    s->have_alpha = desc->flags & AV_PIX_FMT_FLAG_ALPHA;
 
     var_values[VAR_IN_H] = var_values[VAR_IH] = inlink->h;
     var_values[VAR_IN_W] = var_values[VAR_IW] = inlink->w;
@@ -210,27 +213,55 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
     int plane, x, y, xb = s->x, yb = s->y;
     unsigned char *row[4];
 
-    for (y = FFMAX(yb, 0); y < frame->height && y < (yb + s->h); y++) {
-        row[0] = frame->data[0] + y * frame->linesize[0];
-
-        for (plane = 1; plane < 3; plane++)
-            row[plane] = frame->data[plane] +
-                 frame->linesize[plane] * (y >> s->vsub);
-
-        if (s->invert_color) {
-            for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++)
-                if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
-                    (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness))
-                    row[0][x] = 0xff - row[0][x];
-        } else {
-            for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++) {
-                double alpha = (double)s->yuv_color[A] / 255;
-
-                if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
-                    (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness)) {
-                    row[0][x                 ] = (1 - alpha) * row[0][x                 ] + alpha * s->yuv_color[Y];
-                    row[1][x >> s->hsub] = (1 - alpha) * row[1][x >> s->hsub] + alpha * s->yuv_color[U];
-                    row[2][x >> s->hsub] = (1 - alpha) * row[2][x >> s->hsub] + alpha * s->yuv_color[V];
+    if (s->have_alpha) {
+        for (y = FFMAX(yb, 0); y < frame->height && y < (yb + s->h); y++) {
+            row[0] = frame->data[0] + y * frame->linesize[0];
+            row[3] = frame->data[3] + y * frame->linesize[3];
+
+            for (plane = 1; plane < 3; plane++)
+                row[plane] = frame->data[plane] +
+                     frame->linesize[plane] * (y >> s->vsub);
+
+            if (s->invert_color) {
+                for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++)
+                    if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
+                        (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness))
+                        row[0][x] = 0xff - row[0][x];
+            } else {
+                for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++) {
+                    if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
+                        (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness)) {
+                        row[0][x           ] = s->yuv_color[Y];
+                        row[1][x >> s->hsub] = s->yuv_color[U];
+                        row[2][x >> s->hsub] = s->yuv_color[V];
+                        row[3][x           ] = s->yuv_color[A];
+                    }
+                }
+            }
+        }
+    } else {
+        for (y = FFMAX(yb, 0); y < frame->height && y < (yb + s->h); y++) {
+            row[0] = frame->data[0] + y * frame->linesize[0];
+
+            for (plane = 1; plane < 3; plane++)
+                row[plane] = frame->data[plane] +
+                     frame->linesize[plane] * (y >> s->vsub);
+
+            if (s->invert_color) {
+                for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++)
+                    if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
+                        (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness))
+                        row[0][x] = 0xff - row[0][x];
+            } else {
+                for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++) {
+                    double alpha = (double)s->yuv_color[A] / 255;
+
+                    if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
+                        (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness)) {
+                        row[0][x                 ] = (1 - alpha) * row[0][x                 ] + alpha * s->yuv_color[Y];
+                        row[1][x >> s->hsub] = (1 - alpha) * row[1][x >> s->hsub] + alpha * s->yuv_color[U];
+                        row[2][x >> s->hsub] = (1 - alpha) * row[2][x >> s->hsub] + alpha * s->yuv_color[V];
+                    }
                 }
             }
         }
@@ -323,25 +354,51 @@ static int drawgrid_filter_frame(AVFilterLink *inlink, AVFrame *frame)
     int plane, x, y;
     uint8_t *row[4];
 
-    for (y = 0; y < frame->height; y++) {
-        row[0] = frame->data[0] + y * frame->linesize[0];
-
-        for (plane = 1; plane < 3; plane++)
-            row[plane] = frame->data[plane] +
-                 frame->linesize[plane] * (y >> drawgrid->vsub);
-
-        if (drawgrid->invert_color) {
-            for (x = 0; x < frame->width; x++)
-                if (pixel_belongs_to_grid(drawgrid, x, y))
-                    row[0][x] = 0xff - row[0][x];
-        } else {
-            for (x = 0; x < frame->width; x++) {
-                double alpha = (double)drawgrid->yuv_color[A] / 255;
-
-                if (pixel_belongs_to_grid(drawgrid, x, y)) {
-                    row[0][x                  ] = (1 - alpha) * row[0][x                  ] + alpha * drawgrid->yuv_color[Y];
-                    row[1][x >> drawgrid->hsub] = (1 - alpha) * row[1][x >> drawgrid->hsub] + alpha * drawgrid->yuv_color[U];
-                    row[2][x >> drawgrid->hsub] = (1 - alpha) * row[2][x >> drawgrid->hsub] + alpha * drawgrid->yuv_color[V];
+    if (drawgrid->have_alpha) {
+        for (y = 0; y < frame->height; y++) {
+            row[0] = frame->data[0] + y * frame->linesize[0];
+            row[3] = frame->data[3] + y * frame->linesize[3];
+
+            for (plane = 1; plane < 3; plane++)
+                row[plane] = frame->data[plane] +
+                     frame->linesize[plane] * (y >> drawgrid->vsub);
+
+            if (drawgrid->invert_color) {
+                for (x = 0; x < frame->width; x++)
+                    if (pixel_belongs_to_grid(drawgrid, x, y))
+                        row[0][x] = 0xff - row[0][x];
+            } else {
+                for (x = 0; x < frame->width; x++) {
+                    if (pixel_belongs_to_grid(drawgrid, x, y)) {
+                        row[0][x                  ] = drawgrid->yuv_color[Y];
+                        row[1][x >> drawgrid->hsub] = drawgrid->yuv_color[U];
+                        row[2][x >> drawgrid->hsub] = drawgrid->yuv_color[V];
+                        row[3][x                  ] = drawgrid->yuv_color[A];
+                    }
+                }
+            }
+        }
+    } else {
+        for (y = 0; y < frame->height; y++) {
+            row[0] = frame->data[0] + y * frame->linesize[0];
+
+            for (plane = 1; plane < 3; plane++)
+                row[plane] = frame->data[plane] +
+                     frame->linesize[plane] * (y >> drawgrid->vsub);
+
+            if (drawgrid->invert_color) {
+                for (x = 0; x < frame->width; x++)
+                    if (pixel_belongs_to_grid(drawgrid, x, y))
+                        row[0][x] = 0xff - row[0][x];
+            } else {
+                for (x = 0; x < frame->width; x++) {
+                    double alpha = (double)drawgrid->yuv_color[A] / 255;
+
+                    if (pixel_belongs_to_grid(drawgrid, x, y)) {
+                        row[0][x                  ] = (1 - alpha) * row[0][x                  ] + alpha * drawgrid->yuv_color[Y];
+                        row[1][x >> drawgrid->hsub] = (1 - alpha) * row[1][x >> drawgrid->hsub] + alpha * drawgrid->yuv_color[U];
+                        row[2][x >> drawgrid->hsub] = (1 - alpha) * row[2][x >> drawgrid->hsub] + alpha * drawgrid->yuv_color[V];
+                    }
                 }
             }
         }
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index 65c2c58..214aef0 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -860,6 +860,8 @@ static int func_metadata(AVFilterContext *ctx, AVBPrint *bp,
 
     if (e && e->value)
         av_bprintf(bp, "%s", e->value);
+    else if (argc >= 2)
+        av_bprintf(bp, "%s", argv[1]);
     return 0;
 }
 
@@ -975,7 +977,7 @@ static const struct drawtext_function {
     { "localtime", 0, 1, 'L', func_strftime },
     { "frame_num", 0, 0, 0,   func_frame_num },
     { "n",         0, 0, 0,   func_frame_num },
-    { "metadata",  1, 1, 0,   func_metadata },
+    { "metadata",  1, 2, 0,   func_metadata },
 };
 
 static int eval_function(AVFilterContext *ctx, AVBPrint *bp, char *fct,
diff --git a/libavfilter/vf_elbg.c b/libavfilter/vf_elbg.c
index b34136b..396af82 100644
--- a/libavfilter/vf_elbg.c
+++ b/libavfilter/vf_elbg.c
@@ -186,7 +186,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
         p0 = (uint8_t *)out->data[0];
 
         for (i = 0; i < elbg->codebook_length; i++) {
-            pal[i] = (elbg->codebook[i*3  ] << 16) |
+            pal[i] =  0xFFU                 << 24  |
+                     (elbg->codebook[i*3  ] << 16) |
                      (elbg->codebook[i*3+1] <<  8) |
                       elbg->codebook[i*3+2];
         }
diff --git a/libavfilter/vf_eq.c b/libavfilter/vf_eq.c
index 0b929f3..5ecdb31 100644
--- a/libavfilter/vf_eq.c
+++ b/libavfilter/vf_eq.c
@@ -385,4 +385,5 @@ AVFilter ff_vf_eq = {
     .query_formats   = query_formats,
     .init            = initialize,
     .uninit          = uninit,
+    .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_extractplanes.c b/libavfilter/vf_extractplanes.c
index 099c00f..a23f838 100644
--- a/libavfilter/vf_extractplanes.c
+++ b/libavfilter/vf_extractplanes.c
@@ -62,7 +62,7 @@ AVFILTER_DEFINE_CLASS(extractplanes);
 
 static int query_formats(AVFilterContext *ctx)
 {
-    static const enum AVPixelFormat in_pixfmts[] = {
+    static const enum AVPixelFormat in_pixfmts_le[] = {
         AV_PIX_FMT_YUV410P,
         AV_PIX_FMT_YUV411P,
         AV_PIX_FMT_YUV440P,
@@ -73,30 +73,51 @@ static int query_formats(AVFilterContext *ctx)
         AV_PIX_FMT_YUVJ411P,
         AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P,
         AV_PIX_FMT_YUV420P16LE, AV_PIX_FMT_YUVA420P16LE,
-        AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_YUVA420P16BE,
         AV_PIX_FMT_YUV422P16LE, AV_PIX_FMT_YUVA422P16LE,
-        AV_PIX_FMT_YUV422P16BE, AV_PIX_FMT_YUVA422P16BE,
         AV_PIX_FMT_YUV444P16LE, AV_PIX_FMT_YUVA444P16LE,
-        AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUVA444P16BE,
         AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A,
-        AV_PIX_FMT_YA16LE, AV_PIX_FMT_YA16BE,
-        AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE,
+        AV_PIX_FMT_YA16LE, AV_PIX_FMT_GRAY16LE,
         AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
         AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA,
         AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR,
+        AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0,
+        AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR,
         AV_PIX_FMT_RGB48LE, AV_PIX_FMT_BGR48LE,
-        AV_PIX_FMT_RGB48BE, AV_PIX_FMT_BGR48BE,
         AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_BGRA64LE,
+        AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
+        AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRAP16LE,
+        AV_PIX_FMT_NONE,
+    };
+    static const enum AVPixelFormat in_pixfmts_be[] = {
+        AV_PIX_FMT_YUV410P,
+        AV_PIX_FMT_YUV411P,
+        AV_PIX_FMT_YUV440P,
+        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P,
+        AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA422P,
+        AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P,
+        AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P,
+        AV_PIX_FMT_YUVJ411P,
+        AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P,
+        AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_YUVA420P16BE,
+        AV_PIX_FMT_YUV422P16BE, AV_PIX_FMT_YUVA422P16BE,
+        AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUVA444P16BE,
+        AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A,
+        AV_PIX_FMT_YA16BE, AV_PIX_FMT_GRAY16BE,
+        AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
+        AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA,
+        AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR,
+        AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0,
+        AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR,
+        AV_PIX_FMT_RGB48BE, AV_PIX_FMT_BGR48BE,
         AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_BGRA64BE,
         AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
-        AV_PIX_FMT_GBRP16LE, AV_PIX_FMT_GBRP16BE,
-        AV_PIX_FMT_GBRAP16LE, AV_PIX_FMT_GBRAP16BE,
+        AV_PIX_FMT_GBRP16BE, AV_PIX_FMT_GBRAP16BE,
         AV_PIX_FMT_NONE,
     };
     static const enum AVPixelFormat out8_pixfmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
     static const enum AVPixelFormat out16le_pixfmts[] = { AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_NONE };
     static const enum AVPixelFormat out16be_pixfmts[] = { AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE };
-    const enum AVPixelFormat *out_pixfmts;
+    const enum AVPixelFormat *out_pixfmts, *in_pixfmts;
     const AVPixFmtDescriptor *desc;
     AVFilterFormats *avff;
     int i, ret, depth = 0, be = 0;
@@ -106,14 +127,19 @@ static int query_formats(AVFilterContext *ctx)
         return AVERROR(EAGAIN);
     }
 
-    if (!ctx->inputs[0]->out_formats)
-        if ((ret = ff_formats_ref(ff_make_format_list(in_pixfmts), &ctx->inputs[0]->out_formats)) < 0)
-            return ret;
-
     avff = ctx->inputs[0]->in_formats;
     desc = av_pix_fmt_desc_get(avff->formats[0]);
     depth = desc->comp[0].depth;
     be = desc->flags & AV_PIX_FMT_FLAG_BE;
+    if (be) {
+        in_pixfmts = in_pixfmts_be;
+    } else {
+        in_pixfmts = in_pixfmts_le;
+    }
+    if (!ctx->inputs[0]->out_formats)
+        if ((ret = ff_formats_ref(ff_make_format_list(in_pixfmts), &ctx->inputs[0]->out_formats)) < 0)
+            return ret;
+
     for (i = 1; i < avff->nb_formats; i++) {
         desc = av_pix_fmt_desc_get(avff->formats[i]);
         if (depth != desc->comp[0].depth ||
diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c
index f7b2b6a..cf77d87 100644
--- a/libavfilter/vf_fade.c
+++ b/libavfilter/vf_fade.c
@@ -247,7 +247,7 @@ static int filter_slice_chroma(AVFilterContext *ctx, void *arg, int jobnr,
     const int width = AV_CEIL_RSHIFT(frame->width, s->hsub);
     const int height= AV_CEIL_RSHIFT(frame->height, s->vsub);
     int slice_start = (height *  jobnr   ) / nb_jobs;
-    int slice_end   = (height * (jobnr+1)) / nb_jobs;
+    int slice_end   = FFMIN(((height * (jobnr+1)) / nb_jobs), frame->height);
 
     for (plane = 1; plane < 3; plane++) {
         for (i = slice_start; i < slice_end; i++) {
diff --git a/libavfilter/vf_fieldhint.c b/libavfilter/vf_fieldhint.c
new file mode 100644
index 0000000..2b845e7
--- /dev/null
+++ b/libavfilter/vf_fieldhint.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * 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/avassert.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+#include "avfilter.h"
+#include "internal.h"
+#include "video.h"
+
+typedef struct FieldHintContext {
+    const AVClass *class;
+
+    char *hint_file_str;
+    FILE *hint;
+    int mode;
+
+    AVFrame *frame[3];
+
+    int64_t line;
+    int nb_planes;
+    int eof;
+    int planewidth[4];
+    int planeheight[4];
+} FieldHintContext;
+
+#define OFFSET(x) offsetof(FieldHintContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+static const AVOption fieldhint_options[] = {
+    { "hint", "set hint file", OFFSET(hint_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS },
+    { "mode", "set hint mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "mode" },
+    {   "absolute", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" },
+    {   "relative", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(fieldhint);
+
+static av_cold int init(AVFilterContext *ctx)
+{
+    FieldHintContext *s = ctx->priv;
+    int ret;
+
+    if (!s->hint_file_str) {
+        av_log(ctx, AV_LOG_ERROR, "Hint file must be set.\n");
+        return AVERROR(EINVAL);
+    }
+    s->hint = fopen(s->hint_file_str, "r");
+    if (!s->hint) {
+        ret = AVERROR(errno);
+        av_log(ctx, AV_LOG_ERROR, "%s: %s\n", s->hint_file_str, av_err2str(ret));
+        return ret;
+    }
+
+    return 0;
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+    AVFilterFormats *pix_fmts = NULL;
+    int fmt, ret;
+
+    for (fmt = 0; av_pix_fmt_desc_get(fmt); fmt++) {
+        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
+        if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL ||
+              desc->flags & AV_PIX_FMT_FLAG_PAL     ||
+              desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) &&
+            (ret = ff_add_format(&pix_fmts, fmt)) < 0)
+            return ret;
+    }
+
+    return ff_set_common_formats(ctx, pix_fmts);
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+    FieldHintContext *s = inlink->dst->priv;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+    int ret;
+
+    if ((ret = av_image_fill_linesizes(s->planewidth, inlink->format, inlink->w)) < 0)
+        return ret;
+
+    s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
+    s->planeheight[0] = s->planeheight[3] = inlink->h;
+
+    s->nb_planes = av_pix_fmt_count_planes(inlink->format);
+
+    return 0;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    FieldHintContext *s = ctx->priv;
+    AVFrame *out, *top, *bottom;
+    char buf[1024] = { 0 };
+    int64_t tf, bf;
+    char hint = '=';
+    int p;
+
+    av_frame_free(&s->frame[0]);
+    s->frame[0] = s->frame[1];
+    s->frame[1] = s->frame[2];
+    s->frame[2] = in;
+    if (!s->frame[1])
+        return 0;
+    else if (!s->frame[0]) {
+        s->frame[0] = av_frame_clone(s->frame[1]);
+        if (!s->frame[0])
+            return AVERROR(ENOMEM);
+    }
+
+    while (1) {
+        if (fgets(buf, sizeof(buf)-1, s->hint)) {
+            s->line++;
+            if (buf[0] == '#' || buf[0] == ';') {
+                continue;
+            } else if (sscanf(buf, "%"PRId64",%"PRId64" %c", &tf, &bf, &hint) == 3) {
+                ;
+            } else if (sscanf(buf, "%"PRId64",%"PRId64"", &tf, &bf) == 2) {
+                ;
+            } else {
+                av_log(ctx, AV_LOG_ERROR, "Invalid entry at line %"PRId64".\n", s->line);
+                return AVERROR_INVALIDDATA;
+            }
+            switch (s->mode) {
+            case 0:
+                if (tf > outlink->frame_count + 1 || tf < FFMAX(0, outlink->frame_count - 1) ||
+                    bf > outlink->frame_count + 1 || bf < FFMAX(0, outlink->frame_count - 1)) {
+                    av_log(ctx, AV_LOG_ERROR, "Out of range frames %"PRId64" and/or %"PRId64" on line %"PRId64" for %"PRId64". input frame.\n", tf, bf, s->line, inlink->frame_count);
+                    return AVERROR_INVALIDDATA;
+                }
+                break;
+            case 1:
+                if (tf > 1 || tf < -1 ||
+                    bf > 1 || bf < -1) {
+                    av_log(ctx, AV_LOG_ERROR, "Out of range %"PRId64" and/or %"PRId64" on line %"PRId64" for %"PRId64". input frame.\n", tf, bf, s->line, inlink->frame_count);
+                    return AVERROR_INVALIDDATA;
+                }
+            };
+            break;
+        } else {
+            av_log(ctx, AV_LOG_ERROR, "Missing entry for %"PRId64". input frame.\n", inlink->frame_count);
+            return AVERROR_INVALIDDATA;
+        }
+    }
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out)
+        return AVERROR(ENOMEM);
+    av_frame_copy_props(out, s->frame[1]);
+
+    switch (s->mode) {
+    case 0:
+        top    = s->frame[tf - outlink->frame_count + 1];
+        bottom = s->frame[bf - outlink->frame_count + 1];
+        break;
+    case 1:
+        top    = s->frame[1 + tf];
+        bottom = s->frame[1 + bf];
+        break;
+    default:
+        av_assert0(0);
+    }
+
+    switch (hint) {
+    case '+':
+        out->interlaced_frame = 1;
+        break;
+    case '-':
+        out->interlaced_frame = 0;
+        break;
+    case '=':
+        break;
+    default:
+        av_log(ctx, AV_LOG_ERROR, "Invalid hint: %c.\n", hint);
+        return AVERROR(EINVAL);
+    }
+
+    for (p = 0; p < s->nb_planes; p++) {
+        av_image_copy_plane(out->data[p],
+                            out->linesize[p] * 2,
+                            top->data[p],
+                            top->linesize[p] * 2,
+                            s->planewidth[p],
+                            (s->planeheight[p] + 1) / 2);
+        av_image_copy_plane(out->data[p] + out->linesize[p],
+                            out->linesize[p] * 2,
+                            bottom->data[p] + bottom->linesize[p],
+                            bottom->linesize[p] * 2,
+                            s->planewidth[p],
+                            (s->planeheight[p] + 1) / 2);
+    }
+
+    return ff_filter_frame(outlink, out);
+}
+
+static int request_frame(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    FieldHintContext *s = ctx->priv;
+    int ret;
+
+    if (s->eof)
+        return AVERROR_EOF;
+
+    ret = ff_request_frame(ctx->inputs[0]);
+    if (ret == AVERROR_EOF && s->frame[2]) {
+        AVFrame *next = av_frame_clone(s->frame[2]);
+        if (!next)
+            return AVERROR(ENOMEM);
+        ret = filter_frame(ctx->inputs[0], next);
+        s->eof = 1;
+    }
+
+    return ret;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    FieldHintContext *s = ctx->priv;
+
+    if (s->hint)
+        fclose(s->hint);
+    s->hint = NULL;
+
+    av_frame_free(&s->frame[0]);
+    av_frame_free(&s->frame[1]);
+    av_frame_free(&s->frame[2]);
+}
+
+static const AVFilterPad inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = config_input,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad outputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_VIDEO,
+        .request_frame = request_frame,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_fieldhint = {
+    .name          = "fieldhint",
+    .description   = NULL_IF_CONFIG_SMALL("Field matching using hints."),
+    .priv_size     = sizeof(FieldHintContext),
+    .priv_class    = &fieldhint_class,
+    .init          = init,
+    .uninit        = uninit,
+    .query_formats = query_formats,
+    .inputs        = inputs,
+    .outputs       = outputs,
+};
diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c
index 1fb3442..a57c99d 100644
--- a/libavfilter/vf_format.c
+++ b/libavfilter/vf_format.c
@@ -140,7 +140,7 @@ static int query_formats(AVFilterContext *ctx)
 
 #define OFFSET(x) offsetof(FormatContext, x)
 static const AVOption options[] = {
-    { "pix_fmts", "A '|'-separated list of pixel formats", OFFSET(pix_fmts), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_VIDEO_PARAM },
+    { "pix_fmts", "A '|'-separated list of pixel formats", OFFSET(pix_fmts), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM },
     { NULL }
 };
 
diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index 0500e97..20ccd79 100644
--- a/libavfilter/vf_fps.c
+++ b/libavfilter/vf_fps.c
@@ -62,7 +62,7 @@ typedef struct FPSContext {
 #define V AV_OPT_FLAG_VIDEO_PARAM
 #define F AV_OPT_FLAG_FILTERING_PARAM
 static const AVOption fps_options[] = {
-    { "fps", "A string describing desired output framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, .flags = V|F },
+    { "fps", "A string describing desired output framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, INT_MAX, V|F },
     { "start_time", "Assume the first PTS should be this value.", OFFSET(start_time), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX}, -DBL_MAX, DBL_MAX, V },
     { "round", "set rounding method for timestamps", OFFSET(rounding), AV_OPT_TYPE_INT, { .i64 = AV_ROUND_NEAR_INF }, 0, 5, V|F, "round" },
     { "zero", "round towards 0",      OFFSET(rounding), AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_ZERO     }, 0, 5, V|F, "round" },
diff --git a/libavfilter/vf_frei0r.c b/libavfilter/vf_frei0r.c
index 9aa3edc..8aeac08 100644
--- a/libavfilter/vf_frei0r.c
+++ b/libavfilter/vf_frei0r.c
@@ -160,54 +160,6 @@ static int set_params(AVFilterContext *ctx, const char *params)
             if (ret < 0)
                 return ret;
         }
-
-        av_log(ctx, AV_LOG_VERBOSE,
-               "idx:%d name:'%s' type:%s explanation:'%s' ",
-               i, info.name,
-               info.type == F0R_PARAM_BOOL     ? "bool"     :
-               info.type == F0R_PARAM_DOUBLE   ? "double"   :
-               info.type == F0R_PARAM_COLOR    ? "color"    :
-               info.type == F0R_PARAM_POSITION ? "position" :
-               info.type == F0R_PARAM_STRING   ? "string"   : "unknown",
-               info.explanation);
-
-#ifdef DEBUG
-        av_log(ctx, AV_LOG_DEBUG, "value:");
-        switch (info.type) {
-            void *v;
-            double d;
-            char str[128];
-            f0r_param_color_t col;
-            f0r_param_position_t pos;
-
-        case F0R_PARAM_BOOL:
-            v = &d;
-            s->get_param_value(s->instance, v, i);
-            av_log(ctx, AV_LOG_DEBUG, "%s", d >= 0.5 && d <= 1.0 ? "y" : "n");
-            break;
-        case F0R_PARAM_DOUBLE:
-            v = &d;
-            s->get_param_value(s->instance, v, i);
-            av_log(ctx, AV_LOG_DEBUG, "%f", d);
-            break;
-        case F0R_PARAM_COLOR:
-            v = &col;
-            s->get_param_value(s->instance, v, i);
-            av_log(ctx, AV_LOG_DEBUG, "%f/%f/%f", col.r, col.g, col.b);
-            break;
-        case F0R_PARAM_POSITION:
-            v = &pos;
-            s->get_param_value(s->instance, v, i);
-            av_log(ctx, AV_LOG_DEBUG, "%f/%f", pos.x, pos.y);
-            break;
-        default: /* F0R_PARAM_STRING */
-            v = str;
-            s->get_param_value(s->instance, v, i);
-            av_log(ctx, AV_LOG_DEBUG, "'%s'", str);
-            break;
-        }
-#endif
-        av_log(ctx, AV_LOG_VERBOSE, ".\n");
     }
 
     return 0;
@@ -510,7 +462,7 @@ static int source_request_frame(AVFilterLink *outlink)
 
 static const AVOption frei0r_src_options[] = {
     { "size",          "Dimensions of the generated video.", OFFSET(w),         AV_OPT_TYPE_IMAGE_SIZE, { .str = "320x240" }, .flags = FLAGS },
-    { "framerate",     NULL,                                 OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, .flags = FLAGS },
+    { "framerate",     NULL,                                 OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, INT_MAX, .flags = FLAGS },
     { "filter_name",   NULL,                                 OFFSET(dl_name),   AV_OPT_TYPE_STRING,                  .flags = FLAGS },
     { "filter_params", NULL,                                 OFFSET(params),    AV_OPT_TYPE_STRING,                  .flags = FLAGS },
     { NULL },
diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c
index e9af24f..f63128d 100644
--- a/libavfilter/vf_gradfun.c
+++ b/libavfilter/vf_gradfun.c
@@ -26,9 +26,9 @@
  *
  * Apply a boxblur debanding algorithm (based on the gradfun2db
  * AviSynth filter by prunedtree).
- * Foreach pixel, if it's within threshold of the blurred value, make it closer.
- * So now we have a smoothed and higher bitdepth version of all the shallow
- * gradients, while leaving detailed areas untouched.
+ * For each pixel, if it is within the threshold of the blurred value, make it
+ * closer. So now we have a smoothed and higher bitdepth version of all the
+ * shallow gradients, while leaving detailed areas untouched.
  * Dither it back to 8bit.
  */
 
diff --git a/libavfilter/vf_histogram.c b/libavfilter/vf_histogram.c
index 3a4725b..5b4060c 100644
--- a/libavfilter/vf_histogram.c
+++ b/libavfilter/vf_histogram.c
@@ -54,12 +54,15 @@ static const AVOption histogram_options[] = {
     { "level_height", "set level height", OFFSET(level_height), AV_OPT_TYPE_INT, {.i64=200}, 50, 2048, FLAGS},
     { "scale_height", "set scale height", OFFSET(scale_height), AV_OPT_TYPE_INT, {.i64=12}, 0, 40, FLAGS},
     { "display_mode", "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display_mode"},
-    { "parade",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display_mode" },
-    { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display_mode" },
+    { "d",            "set display mode", OFFSET(display_mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display_mode"},
+        { "parade",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display_mode" },
+        { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display_mode" },
     { "levels_mode", "set levels mode", OFFSET(levels_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "levels_mode"},
-    { "linear",      NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "levels_mode" },
-    { "logarithmic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "levels_mode" },
+    { "m",           "set levels mode", OFFSET(levels_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "levels_mode"},
+        { "linear",      NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "levels_mode" },
+        { "logarithmic", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "levels_mode" },
     { "components", "set color components to display", OFFSET(components), AV_OPT_TYPE_INT, {.i64=7}, 1, 15, FLAGS},
+    { "c",          "set color components to display", OFFSET(components), AV_OPT_TYPE_INT, {.i64=7}, 1, 15, FLAGS},
     { NULL }
 };
 
@@ -75,8 +78,10 @@ static const enum AVPixelFormat levels_in_pix_fmts[] = {
     AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9,
     AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
     AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10,
+    AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12,
     AV_PIX_FMT_GBRAP,    AV_PIX_FMT_GBRP,
     AV_PIX_FMT_GBRP9,    AV_PIX_FMT_GBRP10,
+    AV_PIX_FMT_GBRP12,   AV_PIX_FMT_GBRAP12,
     AV_PIX_FMT_GRAY8,
     AV_PIX_FMT_NONE
 };
@@ -96,6 +101,11 @@ static const enum AVPixelFormat levels_out_yuv10_pix_fmts[] = {
     AV_PIX_FMT_NONE
 };
 
+static const enum AVPixelFormat levels_out_yuv12_pix_fmts[] = {
+    AV_PIX_FMT_YUV444P12,
+    AV_PIX_FMT_NONE
+};
+
 static const enum AVPixelFormat levels_out_rgb8_pix_fmts[] = {
     AV_PIX_FMT_GBRAP,    AV_PIX_FMT_GBRP,
     AV_PIX_FMT_NONE
@@ -111,6 +121,11 @@ static const enum AVPixelFormat levels_out_rgb10_pix_fmts[] = {
     AV_PIX_FMT_NONE
 };
 
+static const enum AVPixelFormat levels_out_rgb12_pix_fmts[] = {
+    AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
+    AV_PIX_FMT_NONE
+};
+
 static int query_formats(AVFilterContext *ctx)
 {
     AVFilterFormats *avff;
@@ -144,12 +159,18 @@ static int query_formats(AVFilterContext *ctx)
         out_pix_fmts = levels_out_rgb9_pix_fmts;
     else if (rgb && bits == 10)
         out_pix_fmts = levels_out_rgb10_pix_fmts;
+    else if (rgb && bits == 12)
+        out_pix_fmts = levels_out_rgb12_pix_fmts;
     else if (bits == 8)
         out_pix_fmts = levels_out_yuv8_pix_fmts;
     else if (bits == 9)
         out_pix_fmts = levels_out_yuv9_pix_fmts;
-    else // if (bits == 10)
+    else if (bits == 10)
         out_pix_fmts = levels_out_yuv10_pix_fmts;
+    else if (bits == 12)
+        out_pix_fmts = levels_out_yuv12_pix_fmts;
+    else
+        return AVERROR(EAGAIN);
     if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0)
         return ret;
 
@@ -171,6 +192,7 @@ static int config_input(AVFilterLink *inlink)
     h->mult = h->histogram_size / 256;
 
     switch (inlink->format) {
+    case AV_PIX_FMT_GBRP12:
     case AV_PIX_FMT_GBRP10:
     case AV_PIX_FMT_GBRP9:
     case AV_PIX_FMT_GBRAP:
diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c
index 3fb69fc..d6c14bb 100644
--- a/libavfilter/vf_hqdn3d.c
+++ b/libavfilter/vf_hqdn3d.c
@@ -127,7 +127,7 @@ static int denoise_depth(HQDN3DContext *s,
                          int w, int h, int sstride, int dstride,
                          int16_t *spatial, int16_t *temporal, int depth)
 {
-    // FIXME: For 16bit depth, frame_ant could be a pointer to the previous
+    // FIXME: For 16-bit depth, frame_ant could be a pointer to the previous
     // filtered frame rather than a separate buffer.
     long x, y;
     uint16_t *frame_ant = *frame_ant_ptr;
diff --git a/libavfilter/vf_hwdownload.c b/libavfilter/vf_hwdownload.c
new file mode 100644
index 0000000..1e8d819
--- /dev/null
+++ b/libavfilter/vf_hwdownload.c
@@ -0,0 +1,213 @@
+/*
+ * 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/buffer.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+typedef struct HWDownloadContext {
+    const AVClass *class;
+
+    AVBufferRef       *hwframes_ref;
+    AVHWFramesContext *hwframes;
+} HWDownloadContext;
+
+static int hwdownload_query_formats(AVFilterContext *avctx)
+{
+    AVFilterFormats  *infmts = NULL;
+    AVFilterFormats *outfmts = NULL;
+    const AVPixFmtDescriptor *desc;
+    int err;
+
+    for (desc = av_pix_fmt_desc_next(NULL); desc;
+         desc = av_pix_fmt_desc_next(desc)) {
+        if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)
+            err = ff_add_format(&infmts,  av_pix_fmt_desc_get_id(desc));
+        else
+            err = ff_add_format(&outfmts, av_pix_fmt_desc_get_id(desc));
+        if (err) {
+            ff_formats_unref(&infmts);
+            ff_formats_unref(&outfmts);
+            return err;
+        }
+    }
+
+    if ((err = ff_formats_ref(infmts,  &avctx->inputs[0]->out_formats)) < 0 ||
+        (err = ff_formats_ref(outfmts, &avctx->outputs[0]->in_formats)) < 0)
+        return err;
+
+    return 0;
+}
+
+static int hwdownload_config_input(AVFilterLink *inlink)
+{
+    AVFilterContext *avctx = inlink->dst;
+    HWDownloadContext *ctx = avctx->priv;
+
+    av_buffer_unref(&ctx->hwframes_ref);
+
+    if (!inlink->hw_frames_ctx) {
+        av_log(ctx, AV_LOG_ERROR, "The input must have a hardware frame "
+               "reference.\n");
+        return AVERROR(EINVAL);
+    }
+
+    ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx);
+    if (!ctx->hwframes_ref)
+        return AVERROR(ENOMEM);
+
+    ctx->hwframes = (AVHWFramesContext*)ctx->hwframes_ref->data;
+
+    return 0;
+}
+
+static int hwdownload_config_output(AVFilterLink *outlink)
+{
+    AVFilterContext *avctx = outlink->src;
+    AVFilterLink *inlink   = avctx->inputs[0];
+    HWDownloadContext *ctx = avctx->priv;
+    enum AVPixelFormat *formats;
+    int err, i, found;
+
+    if (!ctx->hwframes_ref)
+        return AVERROR(EINVAL);
+
+    err = av_hwframe_transfer_get_formats(ctx->hwframes_ref,
+                                          AV_HWFRAME_TRANSFER_DIRECTION_FROM,
+                                          &formats, 0);
+    if (err < 0)
+        return err;
+
+    found = 0;
+    for (i = 0; formats[i] != AV_PIX_FMT_NONE; i++) {
+        if (formats[i] == outlink->format) {
+            found = 1;
+            break;
+        }
+    }
+    av_freep(&formats);
+
+    if (!found) {
+        av_log(ctx, AV_LOG_ERROR, "Invalid output format %s for hwframe "
+               "download.\n", av_get_pix_fmt_name(outlink->format));
+        return AVERROR(EINVAL);
+    }
+
+    outlink->w = inlink->w;
+    outlink->h = inlink->h;
+
+    return 0;
+}
+
+static int hwdownload_filter_frame(AVFilterLink *link, AVFrame *input)
+{
+    AVFilterContext *avctx = link->dst;
+    AVFilterLink  *outlink = avctx->outputs[0];
+    HWDownloadContext *ctx = avctx->priv;
+    AVFrame *output = NULL;
+    int err;
+
+    if (!ctx->hwframes_ref || !input->hw_frames_ctx) {
+        av_log(ctx, AV_LOG_ERROR, "Input frames must have hardware context.\n");
+        err = AVERROR(EINVAL);
+        goto fail;
+    }
+    if ((void*)ctx->hwframes != input->hw_frames_ctx->data) {
+        av_log(ctx, AV_LOG_ERROR, "Input frame is not the in the configured "
+               "hwframe context.\n");
+        err = AVERROR(EINVAL);
+        goto fail;
+    }
+
+    output = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!output) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    err = av_hwframe_transfer_data(output, input, 0);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to download frame: %d.\n", err);
+        goto fail;
+    }
+
+    err = av_frame_copy_props(output, input);
+    if (err < 0)
+        goto fail;
+
+    av_frame_free(&input);
+
+    return ff_filter_frame(avctx->outputs[0], output);
+
+fail:
+    av_frame_free(&input);
+    av_frame_free(&output);
+    return err;
+}
+
+static av_cold void hwdownload_uninit(AVFilterContext *avctx)
+{
+    HWDownloadContext *ctx = avctx->priv;
+
+    av_buffer_unref(&ctx->hwframes_ref);
+}
+
+static const AVClass hwdownload_class = {
+    .class_name = "hwdownload",
+    .item_name  = av_default_item_name,
+    .option     = NULL,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static const AVFilterPad hwdownload_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = hwdownload_config_input,
+        .filter_frame = hwdownload_filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad hwdownload_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = hwdownload_config_output,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_hwdownload = {
+    .name          = "hwdownload",
+    .description   = NULL_IF_CONFIG_SMALL("Download a hardware frame to a normal frame"),
+    .uninit        = hwdownload_uninit,
+    .query_formats = hwdownload_query_formats,
+    .priv_size     = sizeof(HWDownloadContext),
+    .priv_class    = &hwdownload_class,
+    .inputs        = hwdownload_inputs,
+    .outputs       = hwdownload_outputs,
+};
diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c
new file mode 100644
index 0000000..08af2dd
--- /dev/null
+++ b/libavfilter/vf_hwupload.c
@@ -0,0 +1,241 @@
+/*
+ * 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/buffer.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_internal.h"
+#include "libavutil/log.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/opt.h"
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+typedef struct HWUploadContext {
+    const AVClass *class;
+
+    AVBufferRef       *hwdevice_ref;
+    AVHWDeviceContext *hwdevice;
+
+    AVBufferRef       *hwframes_ref;
+    AVHWFramesContext *hwframes;
+} HWUploadContext;
+
+static int hwupload_query_formats(AVFilterContext *avctx)
+{
+    HWUploadContext *ctx = avctx->priv;
+    AVHWFramesConstraints *constraints = NULL;
+    const enum AVPixelFormat *input_pix_fmts, *output_pix_fmts;
+    AVFilterFormats *input_formats = NULL;
+    int err, i;
+
+    if (!avctx->hw_device_ctx) {
+        av_log(ctx, AV_LOG_ERROR, "A hardware device reference is required "
+               "to upload frames to.\n");
+        return AVERROR(EINVAL);
+    }
+
+    ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx);
+    if (!ctx->hwdevice_ref)
+        return AVERROR(ENOMEM);
+    ctx->hwdevice = (AVHWDeviceContext*)ctx->hwdevice_ref->data;
+
+    constraints = av_hwdevice_get_hwframe_constraints(ctx->hwdevice_ref, NULL);
+    if (!constraints) {
+        err = AVERROR(EINVAL);
+        goto fail;
+    }
+
+    input_pix_fmts  = constraints->valid_sw_formats;
+    output_pix_fmts = constraints->valid_hw_formats;
+
+    input_formats = ff_make_format_list(output_pix_fmts);
+    if (!input_formats) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    if (input_pix_fmts) {
+        for (i = 0; input_pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
+            err = ff_add_format(&input_formats, input_pix_fmts[i]);
+            if (err < 0) {
+                ff_formats_unref(&input_formats);
+                goto fail;
+            }
+        }
+    }
+
+    ff_formats_ref(input_formats, &avctx->inputs[0]->out_formats);
+
+    ff_formats_ref(ff_make_format_list(output_pix_fmts),
+                   &avctx->outputs[0]->in_formats);
+
+    av_hwframe_constraints_free(&constraints);
+    return 0;
+
+fail:
+    av_buffer_unref(&ctx->hwdevice_ref);
+    av_hwframe_constraints_free(&constraints);
+    return err;
+}
+
+static int hwupload_config_output(AVFilterLink *outlink)
+{
+    AVFilterContext *avctx = outlink->src;
+    AVFilterLink   *inlink = avctx->inputs[0];
+    HWUploadContext   *ctx = avctx->priv;
+    int err;
+
+    av_buffer_unref(&ctx->hwframes_ref);
+
+    if (inlink->format == outlink->format) {
+        // The input is already a hardware format, so we just want to
+        // pass through the input frames in their own hardware context.
+        if (!inlink->hw_frames_ctx) {
+            av_log(ctx, AV_LOG_ERROR, "No input hwframe context.\n");
+            return AVERROR(EINVAL);
+        }
+
+        outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
+        if (!outlink->hw_frames_ctx)
+            return AVERROR(ENOMEM);
+
+        return 0;
+    }
+
+    ctx->hwframes_ref = av_hwframe_ctx_alloc(ctx->hwdevice_ref);
+    if (!ctx->hwframes_ref)
+        return AVERROR(ENOMEM);
+
+    ctx->hwframes = (AVHWFramesContext*)ctx->hwframes_ref->data;
+
+    av_log(ctx, AV_LOG_DEBUG, "Surface format is %s.\n",
+           av_get_pix_fmt_name(inlink->format));
+
+    ctx->hwframes->format    = outlink->format;
+    ctx->hwframes->sw_format = inlink->format;
+    ctx->hwframes->width     = inlink->w;
+    ctx->hwframes->height    = inlink->h;
+
+    err = av_hwframe_ctx_init(ctx->hwframes_ref);
+    if (err < 0)
+        goto fail;
+
+    outlink->hw_frames_ctx = av_buffer_ref(ctx->hwframes_ref);
+    if (!outlink->hw_frames_ctx) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    return 0;
+
+fail:
+    av_buffer_unref(&ctx->hwframes_ref);
+    return err;
+}
+
+static int hwupload_filter_frame(AVFilterLink *link, AVFrame *input)
+{
+    AVFilterContext *avctx = link->dst;
+    AVFilterLink  *outlink = avctx->outputs[0];
+    HWUploadContext   *ctx = avctx->priv;
+    AVFrame *output = NULL;
+    int err;
+
+    if (input->format == outlink->format)
+        return ff_filter_frame(outlink, input);
+
+    output = av_frame_alloc();
+    if (!output) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    err = av_hwframe_get_buffer(ctx->hwframes_ref, output, 0);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to allocate frame to upload to.\n");
+        goto fail;
+    }
+
+    output->width  = input->width;
+    output->height = input->height;
+
+    err = av_hwframe_transfer_data(output, input, 0);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to upload frame: %d.\n", err);
+        goto fail;
+    }
+
+    err = av_frame_copy_props(output, input);
+    if (err < 0)
+        goto fail;
+
+    av_frame_free(&input);
+
+    return ff_filter_frame(outlink, output);
+
+fail:
+    av_frame_free(&input);
+    av_frame_free(&output);
+    return err;
+}
+
+static av_cold void hwupload_uninit(AVFilterContext *avctx)
+{
+    HWUploadContext *ctx = avctx->priv;
+
+    av_buffer_unref(&ctx->hwframes_ref);
+    av_buffer_unref(&ctx->hwdevice_ref);
+}
+
+static const AVClass hwupload_class = {
+    .class_name = "hwupload",
+    .item_name  = av_default_item_name,
+    .option     = NULL,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static const AVFilterPad hwupload_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = hwupload_filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad hwupload_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = hwupload_config_output,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_hwupload = {
+    .name          = "hwupload",
+    .description   = NULL_IF_CONFIG_SMALL("Upload a normal frame to a hardware frame"),
+    .uninit        = hwupload_uninit,
+    .query_formats = hwupload_query_formats,
+    .priv_size     = sizeof(HWUploadContext),
+    .priv_class    = &hwupload_class,
+    .inputs        = hwupload_inputs,
+    .outputs       = hwupload_outputs,
+};
diff --git a/libavfilter/vf_hwupload_cuda.c b/libavfilter/vf_hwupload_cuda.c
new file mode 100644
index 0000000..c22221c
--- /dev/null
+++ b/libavfilter/vf_hwupload_cuda.c
@@ -0,0 +1,232 @@
+/*
+ * 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/buffer.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_cuda.h"
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+typedef struct CudaUploadContext {
+    const AVClass *class;
+    int device_idx;
+
+    AVBufferRef *hwdevice;
+    AVBufferRef *hwframe;
+} CudaUploadContext;
+
+static void cudaupload_ctx_free(AVHWDeviceContext *ctx)
+{
+    AVCUDADeviceContext *hwctx = ctx->hwctx;
+    cuCtxDestroy(hwctx->cuda_ctx);
+}
+
+static av_cold int cudaupload_init(AVFilterContext *ctx)
+{
+    CudaUploadContext *s = ctx->priv;
+
+    AVHWDeviceContext   *device_ctx;
+    AVCUDADeviceContext *device_hwctx;
+    CUdevice device;
+    CUcontext cuda_ctx = NULL, dummy;
+    CUresult err;
+    int ret;
+
+    err = cuInit(0);
+    if (err != CUDA_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Could not initialize the CUDA driver API\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    err = cuDeviceGet(&device, s->device_idx);
+    if (err != CUDA_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Could not get the device number %d\n", s->device_idx);
+        return AVERROR_UNKNOWN;
+    }
+
+    err = cuCtxCreate(&cuda_ctx, 0, device);
+    if (err != CUDA_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Error creating a CUDA context\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    cuCtxPopCurrent(&dummy);
+
+    s->hwdevice = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA);
+    if (!s->hwdevice) {
+        cuCtxDestroy(cuda_ctx);
+        return AVERROR(ENOMEM);
+    }
+
+    device_ctx       = (AVHWDeviceContext*)s->hwdevice->data;
+    device_ctx->free = cudaupload_ctx_free;
+
+    device_hwctx = device_ctx->hwctx;
+    device_hwctx->cuda_ctx = cuda_ctx;
+
+    ret = av_hwdevice_ctx_init(s->hwdevice);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
+static av_cold void cudaupload_uninit(AVFilterContext *ctx)
+{
+    CudaUploadContext *s = ctx->priv;
+
+    av_buffer_unref(&s->hwframe);
+    av_buffer_unref(&s->hwdevice);
+}
+
+static int cudaupload_query_formats(AVFilterContext *ctx)
+{
+    static const enum AVPixelFormat input_pix_fmts[] = {
+        AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P,
+        AV_PIX_FMT_NONE,
+    };
+    static const enum AVPixelFormat output_pix_fmts[] = {
+        AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE,
+    };
+    AVFilterFormats *in_fmts  = ff_make_format_list(input_pix_fmts);
+    AVFilterFormats *out_fmts = ff_make_format_list(output_pix_fmts);
+
+    ff_formats_ref(in_fmts,  &ctx->inputs[0]->out_formats);
+    ff_formats_ref(out_fmts, &ctx->outputs[0]->in_formats);
+
+    return 0;
+}
+
+static int cudaupload_config_output(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    AVFilterLink *inlink = ctx->inputs[0];
+    CudaUploadContext *s = ctx->priv;
+
+    AVHWFramesContext *hwframe_ctx;
+    int ret;
+
+    av_buffer_unref(&s->hwframe);
+    s->hwframe = av_hwframe_ctx_alloc(s->hwdevice);
+    if (!s->hwframe)
+        return AVERROR(ENOMEM);
+
+    hwframe_ctx            = (AVHWFramesContext*)s->hwframe->data;
+    hwframe_ctx->format    = AV_PIX_FMT_CUDA;
+    hwframe_ctx->sw_format = inlink->format;
+    hwframe_ctx->width     = FFALIGN(inlink->w, 16);
+    hwframe_ctx->height    = FFALIGN(inlink->h, 16);
+
+    ret = av_hwframe_ctx_init(s->hwframe);
+    if (ret < 0)
+        return ret;
+
+    outlink->hw_frames_ctx = av_buffer_ref(s->hwframe);
+    if (!outlink->hw_frames_ctx)
+        return AVERROR(ENOMEM);
+
+    return 0;
+}
+
+static int cudaupload_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    AVFilterContext   *ctx = link->dst;
+    CudaUploadContext   *s = ctx->priv;
+
+    AVFrame *out = NULL;
+    int ret;
+
+    out = av_frame_alloc();
+    if (!out) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ret = av_hwframe_get_buffer(s->hwframe, out, 0);
+    if (ret < 0)
+        goto fail;
+
+    out->width  = in->width;
+    out->height = in->height;
+
+    ret = av_hwframe_transfer_data(out, in, 0);
+    if (ret < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Error transferring data to the GPU\n");
+        goto fail;
+    }
+
+    ret = av_frame_copy_props(out, in);
+    if (ret < 0)
+        goto fail;
+
+    av_frame_free(&in);
+
+    return ff_filter_frame(ctx->outputs[0], out);
+fail:
+    av_frame_free(&in);
+    av_frame_free(&out);
+    return ret;
+}
+
+#define OFFSET(x) offsetof(CudaUploadContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption cudaupload_options[] = {
+    { "device", "Number of the device to use", OFFSET(device_idx), AV_OPT_TYPE_INT, { .i64 = 0 }, .flags = FLAGS },
+    { NULL },
+};
+
+AVFILTER_DEFINE_CLASS(cudaupload);
+
+static const AVFilterPad cudaupload_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = cudaupload_filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad cudaupload_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = cudaupload_config_output,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_hwupload_cuda = {
+    .name        = "hwupload_cuda",
+    .description = NULL_IF_CONFIG_SMALL("Upload a system memory frame to a CUDA device."),
+
+    .init      = cudaupload_init,
+    .uninit    = cudaupload_uninit,
+
+    .query_formats = cudaupload_query_formats,
+
+    .priv_size  = sizeof(CudaUploadContext),
+    .priv_class = &cudaupload_class,
+
+    .inputs    = cudaupload_inputs,
+    .outputs   = cudaupload_outputs,
+};
diff --git a/libavfilter/vf_mcdeint.c b/libavfilter/vf_mcdeint.c
index ea32a24..050a834 100644
--- a/libavfilter/vf_mcdeint.c
+++ b/libavfilter/vf_mcdeint.c
@@ -38,7 +38,7 @@
  *
  * Only past frames are used, we should ideally use future frames too,
  * something like filtering the whole movie in forward and then
- * backward direction seems like a interesting idea but the current
+ * backward direction seems like an interesting idea but the current
  * filter framework is FAR from supporting such things.
  *
  * Combining the motion compensated image with the input image also is
diff --git a/libavfilter/vf_nnedi.c b/libavfilter/vf_nnedi.c
index 330d3d6..b14aa64 100644
--- a/libavfilter/vf_nnedi.c
+++ b/libavfilter/vf_nnedi.c
@@ -601,7 +601,7 @@ static void evalfunc_1(NNEDIContext *s, FrameData *frame_data)
 
         const int ystart = frame_data->field[plane];
         const int ystop = height - 12;
-        uint8_t *srcpp;
+        const uint8_t *srcpp;
 
         if (!(s->process_plane & (1 << plane)))
             continue;
@@ -1173,6 +1173,7 @@ static av_cold void uninit(AVFilterContext *ctx)
 
     av_freep(&s->frame_data.input);
     av_freep(&s->frame_data.temp);
+    av_freep(&s->fdsp);
     av_frame_free(&s->second);
 }
 
diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index 37f19ea..c33b35d 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -108,7 +108,7 @@ enum OverlayFormat {
 
 typedef struct OverlayContext {
     const AVClass *class;
-    int x, y;                   ///< position of overlayed picture
+    int x, y;                   ///< position of overlaid picture
 
     int allow_packed_rgb;
     uint8_t main_is_packed_rgb;
diff --git a/libavfilter/vf_owdenoise.c b/libavfilter/vf_owdenoise.c
index 3a77f89..6becccc 100644
--- a/libavfilter/vf_owdenoise.c
+++ b/libavfilter/vf_owdenoise.c
@@ -222,7 +222,6 @@ static void filter(OWDenoiseContext *s,
 
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
-    int direct = 0;
     AVFilterContext *ctx = inlink->dst;
     OWDenoiseContext *s = ctx->priv;
     AVFilterLink *outlink = ctx->outputs[0];
@@ -231,8 +230,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     const int ch = AV_CEIL_RSHIFT(inlink->h, s->vsub);
 
     if (av_frame_is_writable(in)) {
-        direct = 1;
         out = in;
+
+        if (s->luma_strength > 0)
+            filter(s, out->data[0], out->linesize[0], in->data[0], in->linesize[0], inlink->w, inlink->h, s->luma_strength);
+        if (s->chroma_strength > 0) {
+            filter(s, out->data[1], out->linesize[1], in->data[1], in->linesize[1], cw,        ch,        s->chroma_strength);
+            filter(s, out->data[2], out->linesize[2], in->data[2], in->linesize[2], cw,        ch,        s->chroma_strength);
+        }
     } else {
         out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
         if (!out) {
@@ -240,13 +245,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             return AVERROR(ENOMEM);
         }
         av_frame_copy_props(out, in);
-    }
 
-    filter(s, out->data[0], out->linesize[0], in->data[0], in->linesize[0], inlink->w, inlink->h, s->luma_strength);
-    filter(s, out->data[1], out->linesize[1], in->data[1], in->linesize[1], cw,        ch,        s->chroma_strength);
-    filter(s, out->data[2], out->linesize[2], in->data[2], in->linesize[2], cw,        ch,        s->chroma_strength);
+        if (s->luma_strength > 0) {
+            filter(s, out->data[0], out->linesize[0], in->data[0], in->linesize[0], inlink->w, inlink->h, s->luma_strength);
+        } else {
+            av_image_copy_plane(out->data[0], out->linesize[0], in ->data[0], in ->linesize[0], inlink->w, inlink->h);
+        }
+        if (s->chroma_strength > 0) {
+            filter(s, out->data[1], out->linesize[1], in->data[1], in->linesize[1], cw, ch, s->chroma_strength);
+            filter(s, out->data[2], out->linesize[2], in->data[2], in->linesize[2], cw, ch, s->chroma_strength);
+        } else {
+            av_image_copy_plane(out->data[1], out->linesize[1], in ->data[1], in ->linesize[1], inlink->w, inlink->h);
+            av_image_copy_plane(out->data[2], out->linesize[2], in ->data[2], in ->linesize[2], inlink->w, inlink->h);
+        }
 
-    if (!direct) {
         if (in->data[3])
             av_image_copy_plane(out->data[3], out->linesize[3],
                                 in ->data[3], in ->linesize[3],
diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c
index 35f955d..dfc873c 100644
--- a/libavfilter/vf_pad.c
+++ b/libavfilter/vf_pad.c
@@ -33,7 +33,6 @@
 #include "libavutil/eval.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/colorspace.h"
-#include "libavutil/avassert.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/mathematics.h"
diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c
index 1225a66..dece05a 100644
--- a/libavfilter/vf_paletteuse.c
+++ b/libavfilter/vf_paletteuse.c
@@ -1003,6 +1003,7 @@ static av_cold int init(AVFilterContext *ctx)
 {
     PaletteUseContext *s = ctx->priv;
     s->dinput.repeatlast = 1; // only 1 frame in the palette
+    s->dinput.skip_initial_unpaired = 1;
     s->dinput.process    = load_apply_palette;
 
     s->set_frame = set_frame_lut[s->color_search_method][s->dither];
diff --git a/libavfilter/vf_perspective.c b/libavfilter/vf_perspective.c
index 4949ee8..2b5afce 100644
--- a/libavfilter/vf_perspective.c
+++ b/libavfilter/vf_perspective.c
@@ -48,6 +48,7 @@ typedef struct PerspectiveContext {
     int hsub, vsub;
     int nb_planes;
     int sense;
+    int eval_mode;
 
     int (*perspective)(AVFilterContext *ctx,
                        void *arg, int job, int nb_jobs);
@@ -61,6 +62,12 @@ enum PERSPECTIVESense {
     PERSPECTIVE_SENSE_DESTINATION = 1, ///< coordinates give locations in destination of corners of source.
 };
 
+enum EvalMode {
+    EVAL_MODE_INIT,
+    EVAL_MODE_FRAME,
+    EVAL_MODE_NB
+};
+
 static const AVOption perspective_options[] = {
     { "x0", "set top left x coordinate",     OFFSET(expr_str[0][0]), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS },
     { "y0", "set top left y coordinate",     OFFSET(expr_str[0][1]), AV_OPT_TYPE_STRING, {.str="0"}, 0, 0, FLAGS },
@@ -78,6 +85,9 @@ static const AVOption perspective_options[] = {
                 0, AV_OPT_TYPE_CONST, {.i64=PERSPECTIVE_SENSE_SOURCE}, 0, 0, FLAGS, "sense"},
     {       "destination", "specify locations in destination to send corners of source",
                 0, AV_OPT_TYPE_CONST, {.i64=PERSPECTIVE_SENSE_DESTINATION}, 0, 0, FLAGS, "sense"},
+    { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" },
+         { "init",  "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT},  .flags = FLAGS, .unit = "eval" },
+         { "frame", "eval expressions per-frame",                  0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" },
 
     { NULL }
 };
@@ -115,20 +125,22 @@ static inline double get_coeff(double d)
     return coeff;
 }
 
-static const char *const var_names[] = {   "W",   "H",        NULL };
-enum                                   { VAR_W, VAR_H, VAR_VARS_NB };
+static const char *const var_names[] = {   "W",   "H",   "in",   "on",        NULL };
+enum                                   { VAR_W, VAR_H, VAR_IN, VAR_ON, VAR_VARS_NB };
 
-static int config_input(AVFilterLink *inlink)
+static int calc_persp_luts(AVFilterContext *ctx, AVFilterLink *inlink)
 {
+    PerspectiveContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
+    double (*ref)[2]      = s->ref;
+
+    double values[VAR_VARS_NB] = { [VAR_W] = inlink->w, [VAR_H] = inlink->h,
+                                   [VAR_IN] = inlink->frame_count  + 1,
+                                   [VAR_ON] = outlink->frame_count + 1 };
+    const int h = values[VAR_H];
+    const int w = values[VAR_W];
     double x0, x1, x2, x3, x4, x5, x6, x7, x8, q;
     double t0, t1, t2, t3;
-    AVFilterContext *ctx = inlink->dst;
-    PerspectiveContext *s = ctx->priv;
-    double (*ref)[2] = s->ref;
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
-    double values[VAR_VARS_NB] = { [VAR_W] = inlink->w, [VAR_H] = inlink->h };
-    int h = inlink->h;
-    int w = inlink->w;
     int x, y, i, j, ret;
 
     for (i = 0; i < 4; i++) {
@@ -144,19 +156,6 @@ static int config_input(AVFilterLink *inlink)
         }
     }
 
-    s->hsub = desc->log2_chroma_w;
-    s->vsub = desc->log2_chroma_h;
-    s->nb_planes = av_pix_fmt_count_planes(inlink->format);
-    if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
-        return ret;
-
-    s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
-    s->height[0] = s->height[3] = inlink->h;
-
-    s->pv = av_realloc_f(s->pv, w * h, 2 * sizeof(*s->pv));
-    if (!s->pv)
-        return AVERROR(ENOMEM);
-
     switch (s->sense) {
     case PERSPECTIVE_SENSE_SOURCE:
         x6 = ((ref[0][0] - ref[1][0] - ref[2][0] + ref[3][0]) *
@@ -223,6 +222,36 @@ static int config_input(AVFilterLink *inlink)
         }
     }
 
+    return 0;
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+    AVFilterContext *ctx = inlink->dst;
+    PerspectiveContext *s = ctx->priv;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+    int h = inlink->h;
+    int w = inlink->w;
+    int i, j, ret;
+    s->hsub = desc->log2_chroma_w;
+    s->vsub = desc->log2_chroma_h;
+    s->nb_planes = av_pix_fmt_count_planes(inlink->format);
+    if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0)
+        return ret;
+
+    s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
+    s->height[0] = s->height[3] = inlink->h;
+
+    s->pv = av_realloc_f(s->pv, w * h, 2 * sizeof(*s->pv));
+    if (!s->pv)
+        return AVERROR(ENOMEM);
+
+    if (s->eval_mode == EVAL_MODE_INIT) {
+        if ((ret = calc_persp_luts(ctx, inlink)) < 0) {
+            return ret;
+        }
+    }
+
     for (i = 0; i < SUB_PIXELS; i++){
         double d = i / (double)SUB_PIXELS;
         double temp[4];
@@ -423,6 +452,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
     PerspectiveContext *s = ctx->priv;
     AVFrame *out;
     int plane;
+    int ret;
 
     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     if (!out) {
@@ -431,6 +461,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
     }
     av_frame_copy_props(out, frame);
 
+    if (s->eval_mode == EVAL_MODE_FRAME) {
+        if ((ret = calc_persp_luts(ctx, inlink)) < 0) {
+            return ret;
+        }
+    }
+
     for (plane = 0; plane < s->nb_planes; plane++) {
         int hsub = plane == 1 || plane == 2 ? s->hsub : 0;
         int vsub = plane == 1 || plane == 2 ? s->vsub : 0;
diff --git a/libavfilter/vf_readvitc.c b/libavfilter/vf_readvitc.c
new file mode 100644
index 0000000..d70af6a
--- /dev/null
+++ b/libavfilter/vf_readvitc.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2016 Tobias Rapp
+ *
+ * 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
+ * Filter for reading the vertical interval timecode (VITC).
+ * See also https://en.wikipedia.org/wiki/Vertical_interval_timecode
+ */
+
+#include "libavutil/common.h"
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/timecode.h"
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+
+#define LINE_DATA_SIZE 9
+
+typedef struct ReadVitcContext {
+    const AVClass *class;
+
+    int scan_max;
+    double thr_b;
+    double thr_w;
+
+    int threshold_black;
+    int threshold_white;
+    int threshold_gray;
+    int grp_width;
+    uint8_t line_data[LINE_DATA_SIZE];
+    char tcbuf[AV_TIMECODE_STR_SIZE];
+} ReadVitcContext;
+
+#define OFFSET(x) offsetof(ReadVitcContext, x)
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+static const AVOption readvitc_options[] = {
+    { "scan_max", "maximum line numbers to scan for VITC data", OFFSET(scan_max), AV_OPT_TYPE_INT, {.i64 = 45 }, -1, INT_MAX, FLAGS },
+    { "thr_b",    "black color threshold", OFFSET(thr_b), AV_OPT_TYPE_DOUBLE, {.dbl = 0.2 }, 0, 1.0, FLAGS },
+    { "thr_w",    "white color threshold", OFFSET(thr_w), AV_OPT_TYPE_DOUBLE, {.dbl = 0.6 }, 0, 1.0, FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(readvitc);
+
+static uint8_t get_vitc_crc( uint8_t *line ) {
+    uint8_t crc;
+
+    crc = 0x01 | (line[0] << 2);
+    crc ^= (line[0] >> 6) | 0x04 | (line[1] << 4);
+    crc ^= (line[1] >> 4) | 0x10 | (line[2] << 6);
+    crc ^= (line[2] >> 2) | 0x40;
+    crc ^= line[3];
+    crc ^= 0x01 | (line[4] << 2);
+    crc ^= (line[4] >> 6) | 0x04 | (line[5] << 4);
+    crc ^= (line[5] >> 4) | 0x10 | (line[6] << 6);
+    crc ^= (line[6] >> 2) | 0x40;
+    crc ^= line[7];
+    crc ^= 0x01;
+    crc = (crc >> 2) | (crc << 6);  // rotate byte right by two bits
+    return crc;
+}
+
+static inline uint8_t get_pit_avg3( uint8_t *line, int i ) {
+    return ((line[i-1] + line[i] + line[i+1]) / 3);
+}
+
+static int read_vitc_line( ReadVitcContext *ctx, uint8_t *src, int line_size, int width, int height )
+{
+    uint8_t *scan_line;
+    int grp_index, pit_index;
+    int grp_start_pos;
+    uint8_t pit_value;
+    int x, y, res = 0;
+
+    if (ctx->scan_max >= 0)
+        height = FFMIN(height, ctx->scan_max);
+
+    // scan lines for VITC data, starting from the top
+    for (y = 0; y < height; y++) {
+        scan_line = src;
+        memset(ctx->line_data, 0, LINE_DATA_SIZE);
+        grp_index = 0;
+        x = 0;
+        while ((x < width) && (grp_index < 9)) {
+            // search next sync pattern
+            while ((x < width) && (scan_line[x] < ctx->threshold_white))
+                x++;
+            while ((x < width) && (scan_line[x] > ctx->threshold_black))
+                x++;
+            x = FFMAX(x - ((ctx->grp_width+10) / 20), 1);  // step back a half pit
+            grp_start_pos = x;
+            if ((grp_start_pos + ctx->grp_width) > width)
+                break;  // not enough pixels for reading a whole pit group
+            pit_value = get_pit_avg3(scan_line, x);
+            if (pit_value < ctx->threshold_white)
+               break;  // first sync bit mismatch
+            x = grp_start_pos + ((ctx->grp_width) / 10);
+            pit_value = get_pit_avg3(scan_line, x);
+            if (pit_value > ctx->threshold_black )
+                break;  // second sync bit mismatch
+            for (pit_index = 0; pit_index <= 7; pit_index++) {
+                x = grp_start_pos + (((pit_index+2)*ctx->grp_width) / 10);
+                pit_value = get_pit_avg3(scan_line, x);
+                if (pit_value > ctx->threshold_gray)
+                    ctx->line_data[grp_index] |= (1 << pit_index);
+            }
+            grp_index++;
+        }
+        if ((grp_index == 9) && (get_vitc_crc(ctx->line_data) == ctx->line_data[8])) {
+            res = 1;
+            break;
+        }
+        src += line_size;
+    }
+
+    return res;
+}
+
+static unsigned bcd2uint(uint8_t high, uint8_t low)
+{
+   if (high > 9 || low > 9)
+       return 0;
+   return 10*high + low;
+}
+
+static char *make_vitc_tc_string(char *buf, uint8_t *line)
+{
+    unsigned hh   = bcd2uint(line[7] & 0x03, line[6] & 0x0f);  // 6-bit hours
+    unsigned mm   = bcd2uint(line[5] & 0x07, line[4] & 0x0f);  // 7-bit minutes
+    unsigned ss   = bcd2uint(line[3] & 0x07, line[2] & 0x0f);  // 7-bit seconds
+    unsigned ff   = bcd2uint(line[1] & 0x03, line[0] & 0x0f);  // 6-bit frames
+    unsigned drop = (line[1] & 0x04);                          // 1-bit drop flag
+    snprintf(buf, AV_TIMECODE_STR_SIZE, "%02u:%02u:%02u%c%02u",
+             hh, mm, ss, drop ? ';' : ':', ff);
+    return buf;
+}
+
+static av_cold int init(AVFilterContext *ctx)
+{
+    ReadVitcContext *s = ctx->priv;
+
+    s->threshold_black = s->thr_b * UINT8_MAX;
+    s->threshold_white = s->thr_w * UINT8_MAX;
+    if (s->threshold_black > s->threshold_white) {
+        av_log(ctx, AV_LOG_WARNING, "Black color threshold is higher than white color threshold (%g > %g)\n",
+                s->thr_b, s->thr_w);
+        return AVERROR(EINVAL);
+    }
+    s->threshold_gray = s->threshold_white - ((s->threshold_white - s->threshold_black) / 2);
+    av_log(ctx, AV_LOG_DEBUG, "threshold_black:%d threshold_white:%d threshold_gray:%d\n",
+            s->threshold_black, s->threshold_white, s->threshold_gray);
+
+    return 0;
+}
+
+static int config_props(AVFilterLink *inlink)
+{
+    AVFilterContext *ctx = inlink->dst;
+    ReadVitcContext *s = ctx->priv;
+
+    s->grp_width = inlink->w * 5 / 48;
+    av_log(ctx, AV_LOG_DEBUG, "w:%d h:%d grp_width:%d scan_max:%d\n",
+            inlink->w, inlink->h, s->grp_width, s->scan_max);
+    return 0;
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+    static const enum AVPixelFormat pixel_fmts[] = {
+        AV_PIX_FMT_GRAY8,
+        AV_PIX_FMT_NV12,
+        AV_PIX_FMT_NV16,
+        AV_PIX_FMT_NV21,
+        AV_PIX_FMT_YUV410P,
+        AV_PIX_FMT_YUV411P,
+        AV_PIX_FMT_YUV420P,
+        AV_PIX_FMT_YUV422P,
+        AV_PIX_FMT_YUV440P,
+        AV_PIX_FMT_YUV444P,
+        AV_PIX_FMT_YUVA420P,
+        AV_PIX_FMT_YUVA422P,
+        AV_PIX_FMT_YUVA444P,
+        AV_PIX_FMT_YUVJ411P,
+        AV_PIX_FMT_YUVJ420P,
+        AV_PIX_FMT_YUVJ422P,
+        AV_PIX_FMT_YUVJ440P,
+        AV_PIX_FMT_YUVJ444P,
+        AV_PIX_FMT_NONE
+    };
+    AVFilterFormats *fmts_list = ff_make_format_list(pixel_fmts);
+    if (!fmts_list)
+        return AVERROR(ENOMEM);
+    return ff_set_common_formats(ctx, fmts_list);
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
+{
+    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    ReadVitcContext *s = ctx->priv;
+    int found;
+
+    found = read_vitc_line(s, frame->data[0], frame->linesize[0], inlink->w, inlink->h);
+    av_dict_set(avpriv_frame_get_metadatap(frame), "lavfi.readvitc.found", (found ? "1" : "0"), 0);
+    if (found)
+        av_dict_set(avpriv_frame_get_metadatap(frame), "lavfi.readvitc.tc_str", make_vitc_tc_string(s->tcbuf, s->line_data), 0);
+
+    return ff_filter_frame(outlink, frame);
+}
+
+static const AVFilterPad inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+        .config_props = config_props,
+    },
+    { NULL }
+};
+
+static const AVFilterPad outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_readvitc = {
+    .name          = "readvitc",
+    .description   = NULL_IF_CONFIG_SMALL("Read vertical interval timecode and write it to frame metadata."),
+    .priv_size     = sizeof(ReadVitcContext),
+    .priv_class    = &readvitc_class,
+    .inputs        = inputs,
+    .outputs       = outputs,
+    .init          = init,
+    .query_formats = query_formats,
+};
diff --git a/libavfilter/vf_remap.c b/libavfilter/vf_remap.c
new file mode 100644
index 0000000..c6639fe
--- /dev/null
+++ b/libavfilter/vf_remap.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2016 Floris Sluiter
+ *
+ * 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
+ * Pixel remap filter
+ * This filter copies pixel by pixel a source frame to a target frame.
+ * It remaps the pixels to a new x,y destination based on two files ymap/xmap.
+ * Map files are passed as a parameter and are in PGM format (P2 or P5),
+ * where the values are y(rows)/x(cols) coordinates of the source_frame.
+ * The *target* frame dimension is based on mapfile dimensions: specified in the
+ * header of the mapfile and reflected in the number of datavalues.
+ * Dimensions of ymap and xmap must be equal. Datavalues must be positive or zero.
+ * Any datavalue in the ymap or xmap which value is higher
+ * then the *source* frame height or width is silently ignored, leaving a
+ * blank/chromakey pixel. This can safely be used as a feature to create overlays.
+ *
+ * Algorithm digest:
+ * Target_frame[y][x] = Source_frame[ ymap[y][x] ][ [xmap[y][x] ];
+ */
+
+#include "libavutil/imgutils.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/opt.h"
+#include "avfilter.h"
+#include "formats.h"
+#include "framesync.h"
+#include "internal.h"
+#include "video.h"
+
+typedef struct RemapContext {
+    const AVClass *class;
+    int nb_planes;
+    int nb_components;
+    int step;
+    FFFrameSync fs;
+
+    void (*remap)(struct RemapContext *s, const AVFrame *in,
+                  const AVFrame *xin, const AVFrame *yin,
+                  AVFrame *out);
+} RemapContext;
+
+#define OFFSET(x) offsetof(RemapContext, x)
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+
+static const AVOption remap_options[] = {
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(remap);
+
+static int query_formats(AVFilterContext *ctx)
+{
+    static const enum AVPixelFormat pix_fmts[] = {
+        AV_PIX_FMT_YUVA444P,
+        AV_PIX_FMT_YUV444P,
+        AV_PIX_FMT_YUVJ444P,
+        AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
+        AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA,
+        AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
+        AV_PIX_FMT_NONE
+    };
+    static const enum AVPixelFormat map_fmts[] = {
+        AV_PIX_FMT_GRAY16,
+        AV_PIX_FMT_NONE
+    };
+    AVFilterFormats *pix_formats = NULL, *map_formats = NULL;
+    int ret;
+
+    if (!(pix_formats = ff_make_format_list(pix_fmts)) ||
+        !(map_formats = ff_make_format_list(map_fmts))) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+    if ((ret = ff_formats_ref(pix_formats, &ctx->inputs[0]->out_formats)) < 0 ||
+        (ret = ff_formats_ref(map_formats, &ctx->inputs[1]->out_formats)) < 0 ||
+        (ret = ff_formats_ref(map_formats, &ctx->inputs[2]->out_formats)) < 0 ||
+        (ret = ff_formats_ref(pix_formats, &ctx->outputs[0]->in_formats)) < 0)
+        goto fail;
+    return 0;
+fail:
+    if (pix_formats)
+        av_freep(&pix_formats->formats);
+    av_freep(&pix_formats);
+    if (map_formats)
+        av_freep(&map_formats->formats);
+    av_freep(&map_formats);
+    return ret;
+}
+
+/**
+ * remap_planar algorithm expects planes of same size
+ * pixels are copied from source to target using :
+ * Target_frame[y][x] = Source_frame[ ymap[y][x] ][ [xmap[y][x] ];
+ */
+static void remap_planar(RemapContext *s, const AVFrame *in,
+                         const AVFrame *xin, const AVFrame *yin,
+                         AVFrame *out)
+{
+    const int xlinesize = xin->linesize[0] / 2;
+    const int ylinesize = yin->linesize[0] / 2;
+    int x , y, plane;
+
+    for (plane = 0; plane < s->nb_planes ; plane++) {
+        uint8_t *dst         = out->data[plane];
+        const int dlinesize  = out->linesize[plane];
+        const uint8_t *src   = in->data[plane];
+        const int slinesize  = in->linesize[plane];
+        const uint16_t *xmap = (const uint16_t *)xin->data[0];
+        const uint16_t *ymap = (const uint16_t *)yin->data[0];
+
+        for (y = 0; y < out->height; y++) {
+            for (x = 0; x < out->width; x++) {
+                if (ymap[x] < in->height && xmap[x] < in->width) {
+                    dst[x] = src[ymap[x] * slinesize + xmap[x]];
+                } else {
+                    dst[x] = 0;
+                }
+            }
+            dst  += dlinesize;
+            xmap += xlinesize;
+            ymap += ylinesize;
+        }
+    }
+}
+
+/**
+ * remap_packed algorithm expects pixels with both padded bits (step) and
+ * number of components correctly set.
+ * pixels are copied from source to target using :
+ * Target_frame[y][x] = Source_frame[ ymap[y][x] ][ [xmap[y][x] ];
+ */
+static void remap_packed(RemapContext *s, const AVFrame *in,
+                         const AVFrame *xin, const AVFrame *yin,
+                         AVFrame *out)
+{
+    uint8_t *dst = out->data[0];
+    const uint8_t *src  = in->data[0];
+    const int dlinesize = out->linesize[0];
+    const int slinesize = in->linesize[0];
+    const int xlinesize = xin->linesize[0] / 2;
+    const int ylinesize = yin->linesize[0] / 2;
+    const uint16_t *xmap = (const uint16_t *)xin->data[0];
+    const uint16_t *ymap = (const uint16_t *)yin->data[0];
+    const int step = s->step;
+    int c, x, y;
+
+    for (y = 0; y < out->height; y++) {
+        for (x = 0; x < out->width; x++) {
+            for (c = 0; c < s->nb_components; c++) {
+                if (ymap[x] < in->height && xmap[x] < in->width) {
+                    dst[x * step + c] = src[ymap[x] * slinesize + xmap[x] * step + c];
+                } else {
+                    dst[x * step + c] = 0;
+                }
+            }
+        }
+        dst  += dlinesize;
+        xmap += xlinesize;
+        ymap += ylinesize;
+    }
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+    AVFilterContext *ctx = inlink->dst;
+    RemapContext *s = ctx->priv;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
+
+    s->nb_planes = av_pix_fmt_count_planes(inlink->format);
+    s->nb_components = desc->nb_components;
+
+    if (s->nb_planes > 1 || s->nb_components == 1) {
+        s->remap = remap_planar;
+    } else {
+        s->remap = remap_packed;
+    }
+
+    s->step = av_get_padded_bits_per_pixel(desc) >> 3;
+    return 0;
+}
+
+static int process_frame(FFFrameSync *fs)
+{
+    AVFilterContext *ctx = fs->parent;
+    RemapContext *s = fs->opaque;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AVFrame *out, *in, *xpic, *ypic;
+    int ret;
+
+    if ((ret = ff_framesync_get_frame(&s->fs, 0, &in,   0)) < 0 ||
+        (ret = ff_framesync_get_frame(&s->fs, 1, &xpic, 0)) < 0 ||
+        (ret = ff_framesync_get_frame(&s->fs, 2, &ypic, 0)) < 0)
+        return ret;
+
+    if (ctx->is_disabled) {
+        out = av_frame_clone(in);
+        if (!out)
+            return AVERROR(ENOMEM);
+    } else {
+        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+        if (!out)
+            return AVERROR(ENOMEM);
+        av_frame_copy_props(out, in);
+
+        s->remap(s, in, xpic, ypic, out);
+    }
+    out->pts = av_rescale_q(in->pts, s->fs.time_base, outlink->time_base);
+
+    return ff_filter_frame(outlink, out);
+}
+
+static int config_output(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    RemapContext *s = ctx->priv;
+    AVFilterLink *srclink = ctx->inputs[0];
+    AVFilterLink *xlink = ctx->inputs[1];
+    AVFilterLink *ylink = ctx->inputs[2];
+    FFFrameSyncIn *in;
+    int ret;
+
+    if (xlink->w != ylink->w || xlink->h != ylink->h) {
+        av_log(ctx, AV_LOG_ERROR, "Second input link %s parameters "
+               "(size %dx%d) do not match the corresponding "
+               "third input link %s parameters (%dx%d)\n",
+               ctx->input_pads[1].name, xlink->w, xlink->h,
+               ctx->input_pads[2].name, ylink->w, ylink->h);
+        return AVERROR(EINVAL);
+    }
+
+    outlink->w = xlink->w;
+    outlink->h = xlink->h;
+    outlink->time_base = srclink->time_base;
+    outlink->sample_aspect_ratio = srclink->sample_aspect_ratio;
+    outlink->frame_rate = srclink->frame_rate;
+
+    ret = ff_framesync_init(&s->fs, ctx, 3);
+    if (ret < 0)
+        return ret;
+
+    in = s->fs.in;
+    in[0].time_base = srclink->time_base;
+    in[1].time_base = xlink->time_base;
+    in[2].time_base = ylink->time_base;
+    in[0].sync   = 2;
+    in[0].before = EXT_STOP;
+    in[0].after  = EXT_STOP;
+    in[1].sync   = 1;
+    in[1].before = EXT_NULL;
+    in[1].after  = EXT_INFINITY;
+    in[2].sync   = 1;
+    in[2].before = EXT_NULL;
+    in[2].after  = EXT_INFINITY;
+    s->fs.opaque   = s;
+    s->fs.on_event = process_frame;
+
+    return ff_framesync_configure(&s->fs);
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
+{
+    RemapContext *s = inlink->dst->priv;
+    return ff_framesync_filter_frame(&s->fs, inlink, buf);
+}
+
+static int request_frame(AVFilterLink *outlink)
+{
+    RemapContext *s = outlink->src->priv;
+    return ff_framesync_request_frame(&s->fs, outlink);
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    RemapContext *s = ctx->priv;
+
+    ff_framesync_uninit(&s->fs);
+}
+
+static const AVFilterPad remap_inputs[] = {
+    {
+        .name         = "source",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+        .config_props = config_input,
+    },
+    {
+        .name         = "xmap",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+    },
+    {
+        .name         = "ymap",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad remap_outputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_VIDEO,
+        .config_props  = config_output,
+        .request_frame = request_frame,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_remap = {
+    .name          = "remap",
+    .description   = NULL_IF_CONFIG_SMALL("Remap pixels"),
+    .priv_size     = sizeof(RemapContext),
+    .uninit        = uninit,
+    .query_formats = query_formats,
+    .inputs        = remap_inputs,
+    .outputs       = remap_outputs,
+    .priv_class    = &remap_class,
+    .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
+};
diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index ac9d4c3..22bee96 100644
--- a/libavfilter/vf_scale.c
+++ b/libavfilter/vf_scale.c
@@ -237,9 +237,11 @@ static const int *parse_yuv_type(const char *s, enum AVColorSpace colorspace)
         colorspace = AVCOL_SPC_SMPTE240M;
     } else if (s && (strstr(s, "bt601") || strstr(s, "bt470") || strstr(s, "smpte170m"))) {
         colorspace = AVCOL_SPC_BT470BG;
+    } else if (s && strstr(s, "bt2020")) {
+        colorspace = AVCOL_SPC_BT2020_NCL;
     }
 
-    if (colorspace < 1 || colorspace > 7) {
+    if (colorspace < 1 || colorspace > 10 || colorspace == 8) {
         colorspace = AVCOL_SPC_BT470BG;
     }
 
diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c
new file mode 100644
index 0000000..68cee39
--- /dev/null
+++ b/libavfilter/vf_scale_npp.c
@@ -0,0 +1,660 @@
+/*
+ * 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
+ * scale video filter
+ */
+
+#include <nppi.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/avstring.h"
+#include "libavutil/common.h"
+#include "libavutil/eval.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_cuda.h"
+#include "libavutil/internal.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+static const enum AVPixelFormat supported_formats[] = {
+    AV_PIX_FMT_YUV420P,
+    AV_PIX_FMT_NV12,
+    AV_PIX_FMT_YUV444P,
+};
+
+static const enum AVPixelFormat deinterleaved_formats[][2] = {
+    { AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P },
+};
+
+static const char *const var_names[] = {
+    "PI",
+    "PHI",
+    "E",
+    "in_w",   "iw",
+    "in_h",   "ih",
+    "out_w",  "ow",
+    "out_h",  "oh",
+    "a", "dar",
+    "sar",
+    NULL
+};
+
+enum var_name {
+    VAR_PI,
+    VAR_PHI,
+    VAR_E,
+    VAR_IN_W,   VAR_IW,
+    VAR_IN_H,   VAR_IH,
+    VAR_OUT_W,  VAR_OW,
+    VAR_OUT_H,  VAR_OH,
+    VAR_A, VAR_DAR,
+    VAR_SAR,
+    VARS_NB
+};
+
+enum ScaleStage {
+    STAGE_DEINTERLEAVE,
+    STAGE_RESIZE,
+    STAGE_INTERLEAVE,
+    STAGE_NB,
+};
+
+typedef struct NPPScaleStageContext {
+    int stage_needed;
+    enum AVPixelFormat in_fmt;
+    enum AVPixelFormat out_fmt;
+
+    struct {
+        int width;
+        int height;
+    } planes_in[3], planes_out[3];
+
+    AVBufferRef *frames_ctx;
+    AVFrame     *frame;
+} NPPScaleStageContext;
+
+typedef struct NPPScaleContext {
+    const AVClass *class;
+
+    NPPScaleStageContext stages[STAGE_NB];
+    AVFrame *tmp_frame;
+    int passthrough;
+
+    int shift_width, shift_height;
+
+    /**
+     * New dimensions. Special values are:
+     *   0 = original width/height
+     *  -1 = keep original aspect
+     */
+    int w, h;
+
+    /**
+     * Output sw format. AV_PIX_FMT_NONE for no conversion.
+     */
+    enum AVPixelFormat format;
+
+    char *w_expr;               ///< width  expression string
+    char *h_expr;               ///< height expression string
+    char *format_str;
+
+    int interp_algo;
+} NPPScaleContext;
+
+static int nppscale_init(AVFilterContext *ctx)
+{
+    NPPScaleContext *s = ctx->priv;
+    int i;
+
+    if (!strcmp(s->format_str, "same")) {
+        s->format = AV_PIX_FMT_NONE;
+    } else {
+        s->format = av_get_pix_fmt(s->format_str);
+        if (s->format == AV_PIX_FMT_NONE) {
+            av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", s->format_str);
+            return AVERROR(EINVAL);
+        }
+    }
+
+    for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) {
+        s->stages[i].frame = av_frame_alloc();
+        if (!s->stages[i].frame)
+            return AVERROR(ENOMEM);
+    }
+    s->tmp_frame = av_frame_alloc();
+    if (!s->tmp_frame)
+        return AVERROR(ENOMEM);
+
+    return 0;
+}
+
+static void nppscale_uninit(AVFilterContext *ctx)
+{
+    NPPScaleContext *s = ctx->priv;
+    int i;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) {
+        av_frame_free(&s->stages[i].frame);
+        av_buffer_unref(&s->stages[i].frames_ctx);
+    }
+    av_frame_free(&s->tmp_frame);
+}
+
+static int nppscale_query_formats(AVFilterContext *ctx)
+{
+    static const enum AVPixelFormat pixel_formats[] = {
+        AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE,
+    };
+    AVFilterFormats *pix_fmts  = ff_make_format_list(pixel_formats);
+
+    ff_set_common_formats(ctx, pix_fmts);
+
+    return 0;
+}
+
+static int init_stage(NPPScaleStageContext *stage, AVBufferRef *device_ctx)
+{
+    AVBufferRef *out_ref = NULL;
+    AVHWFramesContext *out_ctx;
+    int in_sw, in_sh, out_sw, out_sh;
+    int ret, i;
+
+    av_pix_fmt_get_chroma_sub_sample(stage->in_fmt,  &in_sw,  &in_sh);
+    av_pix_fmt_get_chroma_sub_sample(stage->out_fmt, &out_sw, &out_sh);
+    if (!stage->planes_out[0].width) {
+        stage->planes_out[0].width  = stage->planes_in[0].width;
+        stage->planes_out[0].height = stage->planes_in[0].height;
+    }
+
+    for (i = 1; i < FF_ARRAY_ELEMS(stage->planes_in); i++) {
+        stage->planes_in[i].width   = stage->planes_in[0].width   >> in_sw;
+        stage->planes_in[i].height  = stage->planes_in[0].height  >> in_sh;
+        stage->planes_out[i].width  = stage->planes_out[0].width  >> out_sw;
+        stage->planes_out[i].height = stage->planes_out[0].height >> out_sh;
+    }
+
+    out_ref = av_hwframe_ctx_alloc(device_ctx);
+    if (!out_ref)
+        return AVERROR(ENOMEM);
+    out_ctx = (AVHWFramesContext*)out_ref->data;
+
+    out_ctx->format    = AV_PIX_FMT_CUDA;
+    out_ctx->sw_format = stage->out_fmt;
+    out_ctx->width     = FFALIGN(stage->planes_out[0].width,  32);
+    out_ctx->height    = FFALIGN(stage->planes_out[0].height, 32);
+
+    ret = av_hwframe_ctx_init(out_ref);
+    if (ret < 0)
+        goto fail;
+
+    av_frame_unref(stage->frame);
+    ret = av_hwframe_get_buffer(out_ref, stage->frame, 0);
+    if (ret < 0)
+        goto fail;
+
+    stage->frame->width  = stage->planes_out[0].width;
+    stage->frame->height = stage->planes_out[0].height;
+
+    av_buffer_unref(&stage->frames_ctx);
+    stage->frames_ctx = out_ref;
+
+    return 0;
+fail:
+    av_buffer_unref(&out_ref);
+    return ret;
+}
+
+static int format_is_supported(enum AVPixelFormat fmt)
+{
+    int i;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++)
+        if (supported_formats[i] == fmt)
+            return 1;
+    return 0;
+}
+
+static enum AVPixelFormat get_deinterleaved_format(enum AVPixelFormat fmt)
+{
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt);
+    int i, planes;
+
+    planes = av_pix_fmt_count_planes(fmt);
+    if (planes == desc->nb_components)
+        return fmt;
+    for (i = 0; i < FF_ARRAY_ELEMS(deinterleaved_formats); i++)
+        if (deinterleaved_formats[i][0] == fmt)
+            return deinterleaved_formats[i][1];
+    return AV_PIX_FMT_NONE;
+}
+
+static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_height,
+                                 int out_width, int out_height)
+{
+    NPPScaleContext *s = ctx->priv;
+
+    AVHWFramesContext *in_frames_ctx;
+
+    enum AVPixelFormat in_format;
+    enum AVPixelFormat out_format;
+    enum AVPixelFormat in_deinterleaved_format;
+    enum AVPixelFormat out_deinterleaved_format;
+
+    int i, ret, last_stage = -1;
+
+    /* check that we have a hw context */
+    if (!ctx->inputs[0]->hw_frames_ctx) {
+        av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
+        return AVERROR(EINVAL);
+    }
+    in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
+    in_format     = in_frames_ctx->sw_format;
+    out_format    = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format;
+
+    if (!format_is_supported(in_format)) {
+        av_log(ctx, AV_LOG_ERROR, "Unsupported input format: %s\n",
+               av_get_pix_fmt_name(in_format));
+        return AVERROR(ENOSYS);
+    }
+    if (!format_is_supported(out_format)) {
+        av_log(ctx, AV_LOG_ERROR, "Unsupported output format: %s\n",
+               av_get_pix_fmt_name(out_format));
+        return AVERROR(ENOSYS);
+    }
+
+    in_deinterleaved_format  = get_deinterleaved_format(in_format);
+    out_deinterleaved_format = get_deinterleaved_format(out_format);
+    if (in_deinterleaved_format  == AV_PIX_FMT_NONE ||
+        out_deinterleaved_format == AV_PIX_FMT_NONE)
+        return AVERROR_BUG;
+
+    /* figure out which stages need to be done */
+    if (in_width != out_width || in_height != out_height ||
+        in_deinterleaved_format != out_deinterleaved_format)
+        s->stages[STAGE_RESIZE].stage_needed = 1;
+
+    if (!s->stages[STAGE_RESIZE].stage_needed && in_format == out_format)
+        s->passthrough = 1;
+
+    if (!s->passthrough) {
+        if (in_format != in_deinterleaved_format)
+            s->stages[STAGE_DEINTERLEAVE].stage_needed = 1;
+        if (out_format != out_deinterleaved_format)
+            s->stages[STAGE_INTERLEAVE].stage_needed = 1;
+    }
+
+    s->stages[STAGE_DEINTERLEAVE].in_fmt              = in_format;
+    s->stages[STAGE_DEINTERLEAVE].out_fmt             = in_deinterleaved_format;
+    s->stages[STAGE_DEINTERLEAVE].planes_in[0].width  = in_width;
+    s->stages[STAGE_DEINTERLEAVE].planes_in[0].height = in_height;
+
+    s->stages[STAGE_RESIZE].in_fmt               = in_deinterleaved_format;
+    s->stages[STAGE_RESIZE].out_fmt              = out_deinterleaved_format;
+    s->stages[STAGE_RESIZE].planes_in[0].width   = in_width;
+    s->stages[STAGE_RESIZE].planes_in[0].height  = in_height;
+    s->stages[STAGE_RESIZE].planes_out[0].width  = out_width;
+    s->stages[STAGE_RESIZE].planes_out[0].height = out_height;
+
+    s->stages[STAGE_INTERLEAVE].in_fmt              = out_deinterleaved_format;
+    s->stages[STAGE_INTERLEAVE].out_fmt             = out_format;
+    s->stages[STAGE_INTERLEAVE].planes_in[0].width  = out_width;
+    s->stages[STAGE_INTERLEAVE].planes_in[0].height = out_height;
+
+    /* init the hardware contexts */
+    for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) {
+        if (!s->stages[i].stage_needed)
+            continue;
+
+        ret = init_stage(&s->stages[i], in_frames_ctx->device_ref);
+        if (ret < 0)
+            return ret;
+
+        last_stage = i;
+    }
+
+    if (last_stage < 0)
+        return AVERROR_BUG;
+    ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->stages[last_stage].frames_ctx);
+    if (!ctx->outputs[0]->hw_frames_ctx)
+        return AVERROR(ENOMEM);
+
+    return 0;
+}
+
+static int nppscale_config_props(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    AVFilterLink *inlink = outlink->src->inputs[0];
+    NPPScaleContext  *s = ctx->priv;
+    int64_t w, h;
+    double var_values[VARS_NB], res;
+    char *expr;
+    int ret;
+
+    var_values[VAR_PI]    = M_PI;
+    var_values[VAR_PHI]   = M_PHI;
+    var_values[VAR_E]     = M_E;
+    var_values[VAR_IN_W]  = var_values[VAR_IW] = inlink->w;
+    var_values[VAR_IN_H]  = var_values[VAR_IH] = inlink->h;
+    var_values[VAR_OUT_W] = var_values[VAR_OW] = NAN;
+    var_values[VAR_OUT_H] = var_values[VAR_OH] = NAN;
+    var_values[VAR_A]     = (double) inlink->w / inlink->h;
+    var_values[VAR_SAR]   = inlink->sample_aspect_ratio.num ?
+        (double) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1;
+    var_values[VAR_DAR]   = var_values[VAR_A] * var_values[VAR_SAR];
+
+    /* evaluate width and height */
+    av_expr_parse_and_eval(&res, (expr = s->w_expr),
+                           var_names, var_values,
+                           NULL, NULL, NULL, NULL, NULL, 0, ctx);
+    s->w = var_values[VAR_OUT_W] = var_values[VAR_OW] = res;
+    if ((ret = av_expr_parse_and_eval(&res, (expr = s->h_expr),
+                                      var_names, var_values,
+                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
+        goto fail;
+    s->h = var_values[VAR_OUT_H] = var_values[VAR_OH] = res;
+    /* evaluate again the width, as it may depend on the output height */
+    if ((ret = av_expr_parse_and_eval(&res, (expr = s->w_expr),
+                                      var_names, var_values,
+                                      NULL, NULL, NULL, NULL, NULL, 0, ctx)) < 0)
+        goto fail;
+    s->w = res;
+
+    w = s->w;
+    h = s->h;
+
+    /* sanity check params */
+    if (w <  -1 || h <  -1) {
+        av_log(ctx, AV_LOG_ERROR, "Size values less than -1 are not acceptable.\n");
+        return AVERROR(EINVAL);
+    }
+    if (w == -1 && h == -1)
+        s->w = s->h = 0;
+
+    if (!(w = s->w))
+        w = inlink->w;
+    if (!(h = s->h))
+        h = inlink->h;
+    if (w == -1)
+        w = av_rescale(h, inlink->w, inlink->h);
+    if (h == -1)
+        h = av_rescale(w, inlink->h, inlink->w);
+
+    if (w > INT_MAX || h > INT_MAX ||
+        (h * inlink->w) > INT_MAX  ||
+        (w * inlink->h) > INT_MAX)
+        av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n");
+
+    outlink->w = w;
+    outlink->h = h;
+
+    ret = init_processing_chain(ctx, inlink->w, inlink->h, w, h);
+    if (ret < 0)
+        return ret;
+
+    av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d\n",
+           inlink->w, inlink->h, outlink->w, outlink->h);
+
+    if (inlink->sample_aspect_ratio.num)
+        outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w,
+                                                             outlink->w*inlink->h},
+                                                inlink->sample_aspect_ratio);
+    else
+        outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
+
+    return 0;
+
+fail:
+    av_log(NULL, AV_LOG_ERROR,
+           "Error when evaluating the expression '%s'\n", expr);
+    return ret;
+}
+
+static int nppscale_deinterleave(AVFilterContext *ctx, NPPScaleStageContext *stage,
+                                 AVFrame *out, AVFrame *in)
+{
+    AVHWFramesContext *in_frames_ctx = (AVHWFramesContext*)in->hw_frames_ctx->data;
+    NppStatus err;
+
+    switch (in_frames_ctx->sw_format) {
+    case AV_PIX_FMT_NV12:
+        err = nppiYCbCr420_8u_P2P3R(in->data[0], in->linesize[0],
+                                    in->data[1], in->linesize[1],
+                                    out->data, out->linesize,
+                                    (NppiSize){ in->width, in->height });
+        break;
+    default:
+        return AVERROR_BUG;
+    }
+    if (err != NPP_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "NPP deinterleave error: %d\n", err);
+        return AVERROR_UNKNOWN;
+    }
+
+    return 0;
+}
+
+static int nppscale_resize(AVFilterContext *ctx, NPPScaleStageContext *stage,
+                           AVFrame *out, AVFrame *in)
+{
+    NPPScaleContext *s = ctx->priv;
+    NppStatus err;
+    int i;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(in->data) && in->data[i]; i++) {
+        int iw = stage->planes_in[i].width;
+        int ih = stage->planes_in[i].height;
+        int ow = stage->planes_out[i].width;
+        int oh = stage->planes_out[i].height;
+
+        err = nppiResizeSqrPixel_8u_C1R(in->data[i], (NppiSize){ iw, ih },
+                                        in->linesize[i], (NppiRect){ 0, 0, iw, ih },
+                                        out->data[i], out->linesize[i],
+                                        (NppiRect){ 0, 0, ow, oh },
+                                        (double)ow / iw, (double)oh / ih,
+                                        0.0, 0.0, s->interp_algo);
+        if (err != NPP_SUCCESS) {
+            av_log(ctx, AV_LOG_ERROR, "NPP resize error: %d\n", err);
+            return AVERROR_UNKNOWN;
+        }
+    }
+
+    return 0;
+}
+
+static int nppscale_interleave(AVFilterContext *ctx, NPPScaleStageContext *stage,
+                               AVFrame *out, AVFrame *in)
+{
+    AVHWFramesContext *out_frames_ctx = (AVHWFramesContext*)out->hw_frames_ctx->data;
+    NppStatus err;
+
+    switch (out_frames_ctx->sw_format) {
+    case AV_PIX_FMT_NV12:
+        err = nppiYCbCr420_8u_P3P2R((const uint8_t**)in->data,
+                                    in->linesize,
+                                    out->data[0], out->linesize[0],
+                                    out->data[1], out->linesize[1],
+                                    (NppiSize){ in->width, in->height });
+        break;
+    default:
+        return AVERROR_BUG;
+    }
+    if (err != NPP_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "NPP deinterleave error: %d\n", err);
+        return AVERROR_UNKNOWN;
+    }
+
+    return 0;
+}
+
+static int (*const nppscale_process[])(AVFilterContext *ctx, NPPScaleStageContext *stage,
+                                       AVFrame *out, AVFrame *in) = {
+    [STAGE_DEINTERLEAVE] = nppscale_deinterleave,
+    [STAGE_RESIZE]       = nppscale_resize,
+    [STAGE_INTERLEAVE]   = nppscale_interleave,
+};
+
+static int nppscale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in)
+{
+    NPPScaleContext *s = ctx->priv;
+    AVFrame *src = in;
+    int i, ret, last_stage = -1;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) {
+        if (!s->stages[i].stage_needed)
+            continue;
+
+        ret = nppscale_process[i](ctx, &s->stages[i], s->stages[i].frame, src);
+        if (ret < 0)
+            return ret;
+
+        src        = s->stages[i].frame;
+        last_stage = i;
+    }
+
+    if (last_stage < 0)
+        return AVERROR_BUG;
+    ret = av_hwframe_get_buffer(src->hw_frames_ctx, s->tmp_frame, 0);
+    if (ret < 0)
+        return ret;
+
+    av_frame_move_ref(out, src);
+    av_frame_move_ref(src, s->tmp_frame);
+
+    ret = av_frame_copy_props(out, in);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
+static int nppscale_filter_frame(AVFilterLink *link, AVFrame *in)
+{
+    AVFilterContext              *ctx = link->dst;
+    NPPScaleContext                *s = ctx->priv;
+    AVFilterLink             *outlink = ctx->outputs[0];
+    AVHWFramesContext     *frames_ctx = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
+    AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
+
+    AVFrame *out = NULL;
+    CUresult err;
+    CUcontext dummy;
+    int ret = 0;
+
+    if (s->passthrough)
+        return ff_filter_frame(outlink, in);
+
+    out = av_frame_alloc();
+    if (!out) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den,
+              (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w,
+              (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h,
+              INT_MAX);
+
+    err = cuCtxPushCurrent(device_hwctx->cuda_ctx);
+    if (err != CUDA_SUCCESS) {
+        ret = AVERROR_UNKNOWN;
+        goto fail;
+    }
+
+    ret = nppscale_scale(ctx, out, in);
+
+    cuCtxPopCurrent(&dummy);
+    if (ret < 0)
+        goto fail;
+
+    av_frame_free(&in);
+    return ff_filter_frame(outlink, out);
+fail:
+    av_frame_free(&in);
+    av_frame_free(&out);
+    return ret;
+}
+
+#define OFFSET(x) offsetof(NPPScaleContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption options[] = {
+    { "w",      "Output video width",  OFFSET(w_expr),     AV_OPT_TYPE_STRING, { .str = "iw"   }, .flags = FLAGS },
+    { "h",      "Output video height", OFFSET(h_expr),     AV_OPT_TYPE_STRING, { .str = "ih"   }, .flags = FLAGS },
+    { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS },
+
+    { "interp_algo", "Interpolation algorithm used for resizing", OFFSET(interp_algo), AV_OPT_TYPE_INT, { .i64 = NPPI_INTER_CUBIC }, 0, INT_MAX, FLAGS, "interp_algo" },
+        { "nn",                 "nearest neighbour",                 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_NN                 }, 0, 0, FLAGS, "interp_algo" },
+        { "linear",             "linear",                            0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_LINEAR             }, 0, 0, FLAGS, "interp_algo" },
+        { "cubic",              "cubic",                             0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC              }, 0, 0, FLAGS, "interp_algo" },
+        { "cubic2p_bspline",    "2-parameter cubic (B=1, C=0)",      0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_BSPLINE    }, 0, 0, FLAGS, "interp_algo" },
+        { "cubic2p_catmullrom", "2-parameter cubic (B=0, C=1/2)",    0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_CATMULLROM }, 0, 0, FLAGS, "interp_algo" },
+        { "cubic2p_b05c03",     "2-parameter cubic (B=1/2, C=3/10)", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_B05C03     }, 0, 0, FLAGS, "interp_algo" },
+        { "super",              "supersampling",                     0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_SUPER              }, 0, 0, FLAGS, "interp_algo" },
+        { "lanczos",            "Lanczos",                           0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_LANCZOS            }, 0, 0, FLAGS, "interp_algo" },
+    { NULL },
+};
+
+static const AVClass nppscale_class = {
+    .class_name = "nppscale",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static const AVFilterPad nppscale_inputs[] = {
+    {
+        .name        = "default",
+        .type        = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = nppscale_filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad nppscale_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = nppscale_config_props,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_scale_npp = {
+    .name      = "scale_npp",
+    .description = NULL_IF_CONFIG_SMALL("NVIDIA Performance Primitives video "
+                                        "scaling and format conversion"),
+
+    .init          = nppscale_init,
+    .uninit        = nppscale_uninit,
+    .query_formats = nppscale_query_formats,
+
+    .priv_size = sizeof(NPPScaleContext),
+    .priv_class = &nppscale_class,
+
+    .inputs    = nppscale_inputs,
+    .outputs   = nppscale_outputs,
+};
diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
new file mode 100644
index 0000000..8dd5acf
--- /dev/null
+++ b/libavfilter/vf_scale_vaapi.c
@@ -0,0 +1,460 @@
+/*
+ * 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 <string.h>
+
+#include <va/va.h>
+#include <va/va_vpp.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/hwcontext.h"
+#include "libavutil/hwcontext_vaapi.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+
+typedef struct ScaleVAAPIContext {
+    const AVClass *class;
+
+    AVVAAPIDeviceContext *hwctx;
+    AVBufferRef *device_ref;
+
+    int valid_ids;
+    VAConfigID  va_config;
+    VAContextID va_context;
+
+    AVBufferRef       *input_frames_ref;
+    AVHWFramesContext *input_frames;
+
+    AVBufferRef       *output_frames_ref;
+    AVHWFramesContext *output_frames;
+
+    char *output_format_string;
+    enum AVPixelFormat output_format;
+    int output_width;
+    int output_height;
+
+} ScaleVAAPIContext;
+
+
+static int scale_vaapi_query_formats(AVFilterContext *avctx)
+{
+    enum AVPixelFormat pix_fmts[] = {
+        AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE,
+    };
+
+    ff_formats_ref(ff_make_format_list(pix_fmts),
+                   &avctx->inputs[0]->out_formats);
+    ff_formats_ref(ff_make_format_list(pix_fmts),
+                   &avctx->outputs[0]->in_formats);
+
+    return 0;
+}
+
+static int scale_vaapi_pipeline_uninit(ScaleVAAPIContext *ctx)
+{
+    if (ctx->va_context != VA_INVALID_ID) {
+        vaDestroyContext(ctx->hwctx->display, ctx->va_context);
+        ctx->va_context = VA_INVALID_ID;
+    }
+
+    if (ctx->va_config != VA_INVALID_ID) {
+        vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
+        ctx->va_config = VA_INVALID_ID;
+    }
+
+    av_buffer_unref(&ctx->output_frames_ref);
+    av_buffer_unref(&ctx->device_ref);
+    ctx->hwctx = 0;
+
+    return 0;
+}
+
+static int scale_vaapi_config_input(AVFilterLink *inlink)
+{
+    AVFilterContext *avctx = inlink->dst;
+    ScaleVAAPIContext *ctx = avctx->priv;
+
+    scale_vaapi_pipeline_uninit(ctx);
+
+    if (!inlink->hw_frames_ctx) {
+        av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
+               "required to associate the processing device.\n");
+        return AVERROR(EINVAL);
+    }
+
+    ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
+    ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
+
+    return 0;
+}
+
+static int scale_vaapi_config_output(AVFilterLink *outlink)
+{
+    AVFilterContext *avctx = outlink->src;
+    ScaleVAAPIContext *ctx = avctx->priv;
+    AVVAAPIHWConfig *hwconfig = NULL;
+    AVHWFramesConstraints *constraints = NULL;
+    AVVAAPIFramesContext *va_frames;
+    VAStatus vas;
+    int err, i;
+
+    scale_vaapi_pipeline_uninit(ctx);
+
+    ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
+    ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx;
+
+    av_assert0(ctx->va_config == VA_INVALID_ID);
+    vas = vaCreateConfig(ctx->hwctx->display, VAProfileNone,
+                         VAEntrypointVideoProc, 0, 0, &ctx->va_config);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create processing pipeline "
+               "config: %d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref);
+    if (!hwconfig) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    hwconfig->config_id = ctx->va_config;
+
+    constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref,
+                                                      hwconfig);
+    if (!constraints) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (ctx->output_format == AV_PIX_FMT_NONE)
+        ctx->output_format = ctx->input_frames->sw_format;
+    if (constraints->valid_sw_formats) {
+        for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
+            if (ctx->output_format == constraints->valid_sw_formats[i])
+                break;
+        }
+        if (constraints->valid_sw_formats[i] == AV_PIX_FMT_NONE) {
+            av_log(ctx, AV_LOG_ERROR, "Hardware does not support output "
+                   "format %s.\n", av_get_pix_fmt_name(ctx->output_format));
+            err = AVERROR(EINVAL);
+            goto fail;
+        }
+    }
+
+    if (ctx->output_width  < constraints->min_width  ||
+        ctx->output_height < constraints->min_height ||
+        ctx->output_width  > constraints->max_width  ||
+        ctx->output_height > constraints->max_height) {
+        av_log(ctx, AV_LOG_ERROR, "Hardware does not support scaling to "
+               "size %dx%d (constraints: width %d-%d height %d-%d).\n",
+               ctx->output_width, ctx->output_height,
+               constraints->min_width,  constraints->max_width,
+               constraints->min_height, constraints->max_height);
+        err = AVERROR(EINVAL);
+        goto fail;
+    }
+
+    ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
+    if (!ctx->output_frames_ref) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context "
+               "for output.\n");
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data;
+
+    ctx->output_frames->format    = AV_PIX_FMT_VAAPI;
+    ctx->output_frames->sw_format = ctx->output_format;
+    ctx->output_frames->width     = ctx->output_width;
+    ctx->output_frames->height    = ctx->output_height;
+
+    // The number of output frames we need is determined by what follows
+    // the filter.  If it's an encoder with complex frame reference
+    // structures then this could be very high.
+    ctx->output_frames->initial_pool_size = 10;
+
+    err = av_hwframe_ctx_init(ctx->output_frames_ref);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame "
+               "context for output: %d\n", err);
+        goto fail;
+    }
+
+    va_frames = ctx->output_frames->hwctx;
+
+    av_assert0(ctx->va_context == VA_INVALID_ID);
+    vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
+                          ctx->output_width, ctx->output_height,
+                          VA_PROGRESSIVE,
+                          va_frames->surface_ids, va_frames->nb_surfaces,
+                          &ctx->va_context);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create processing pipeline "
+               "context: %d (%s).\n", vas, vaErrorStr(vas));
+        return AVERROR(EIO);
+    }
+
+    outlink->w = ctx->output_width;
+    outlink->h = ctx->output_height;
+
+    outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref);
+    if (!outlink->hw_frames_ctx) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    av_freep(&hwconfig);
+    av_hwframe_constraints_free(&constraints);
+    return 0;
+
+fail:
+    av_buffer_unref(&ctx->output_frames_ref);
+    av_freep(&hwconfig);
+    av_hwframe_constraints_free(&constraints);
+    return err;
+}
+
+static int vaapi_proc_colour_standard(enum AVColorSpace av_cs)
+{
+    switch(av_cs) {
+#define CS(av, va) case AVCOL_SPC_ ## av: return VAProcColorStandard ## va;
+        CS(BT709,     BT709);
+        CS(BT470BG,   BT601);
+        CS(SMPTE170M, SMPTE170M);
+        CS(SMPTE240M, SMPTE240M);
+#undef CS
+    default:
+        return VAProcColorStandardNone;
+    }
+}
+
+static int scale_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
+{
+    AVFilterContext *avctx = inlink->dst;
+    AVFilterLink *outlink = avctx->outputs[0];
+    ScaleVAAPIContext *ctx = avctx->priv;
+    AVFrame *output_frame = NULL;
+    VASurfaceID input_surface, output_surface;
+    VAProcPipelineParameterBuffer params;
+    VABufferID params_id;
+    VAStatus vas;
+    int err;
+
+    av_log(ctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
+           av_get_pix_fmt_name(input_frame->format),
+           input_frame->width, input_frame->height, input_frame->pts);
+
+    if (ctx->va_context == VA_INVALID_ID)
+        return AVERROR(EINVAL);
+
+    input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];
+    av_log(ctx, AV_LOG_DEBUG, "Using surface %#x for scale input.\n",
+           input_surface);
+
+    output_frame = av_frame_alloc();
+    if (!output_frame) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to allocate output frame.");
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    err = av_hwframe_get_buffer(ctx->output_frames_ref, output_frame, 0);
+    if (err < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to get surface for "
+               "output: %d\n.", err);
+    }
+
+    output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3];
+    av_log(ctx, AV_LOG_DEBUG, "Using surface %#x for scale output.\n",
+           output_surface);
+
+    memset(&params, 0, sizeof(params));
+
+    params.surface = input_surface;
+    params.surface_region = 0;
+    params.surface_color_standard =
+        vaapi_proc_colour_standard(input_frame->colorspace);
+
+    params.output_region = 0;
+    params.output_background_color = 0xff000000;
+    params.output_color_standard = params.surface_color_standard;
+
+    params.pipeline_flags = 0;
+    params.filter_flags = VA_FILTER_SCALING_HQ;
+
+    vas = vaBeginPicture(ctx->hwctx->display,
+                         ctx->va_context, output_surface);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to attach new picture: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
+                         VAProcPipelineParameterBufferType,
+                         sizeof(params), 1, &params, &params_id);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create parameter buffer: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail_after_begin;
+    }
+    av_log(ctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n",
+           params_id);
+
+    vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
+                          &params_id, 1);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to render parameter buffer: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail_after_begin;
+    }
+
+    vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to start picture processing: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail_after_render;
+    }
+
+    // This doesn't get freed automatically for some reason.
+    vas = vaDestroyBuffer(ctx->hwctx->display, params_id);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to free parameter buffer: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    av_frame_copy_props(output_frame, input_frame);
+    av_frame_free(&input_frame);
+
+    av_log(ctx, AV_LOG_DEBUG, "Filter output: %s, %ux%u (%"PRId64").\n",
+           av_get_pix_fmt_name(output_frame->format),
+           output_frame->width, output_frame->height, output_frame->pts);
+
+    return ff_filter_frame(outlink, output_frame);
+
+    // We want to make sure that if vaBeginPicture has been called, we also
+    // call vaRenderPicture and vaEndPicture.  These calls may well fail or
+    // do something else nasty, but once we're in this failure case there
+    // isn't much else we can do.
+fail_after_begin:
+    vaRenderPicture(ctx->hwctx->display, ctx->va_context, &params_id, 1);
+fail_after_render:
+    vaEndPicture(ctx->hwctx->display, ctx->va_context);
+fail:
+    av_frame_free(&input_frame);
+    av_frame_free(&output_frame);
+    return err;
+}
+
+static av_cold int scale_vaapi_init(AVFilterContext *avctx)
+{
+    ScaleVAAPIContext *ctx = avctx->priv;
+
+    ctx->va_config  = VA_INVALID_ID;
+    ctx->va_context = VA_INVALID_ID;
+    ctx->valid_ids  = 1;
+
+    if (ctx->output_format_string) {
+        ctx->output_format = av_get_pix_fmt(ctx->output_format_string);
+        if (ctx->output_format == AV_PIX_FMT_NONE) {
+            av_log(ctx, AV_LOG_ERROR, "Invalid output format.\n");
+            return AVERROR(EINVAL);
+        }
+    } else {
+        // Use the input format once that is configured.
+        ctx->output_format = AV_PIX_FMT_NONE;
+    }
+
+    return 0;
+}
+
+static av_cold void scale_vaapi_uninit(AVFilterContext *avctx)
+{
+    ScaleVAAPIContext *ctx = avctx->priv;
+
+    if (ctx->valid_ids)
+        scale_vaapi_pipeline_uninit(ctx);
+
+    av_buffer_unref(&ctx->input_frames_ref);
+    av_buffer_unref(&ctx->output_frames_ref);
+    av_buffer_unref(&ctx->device_ref);
+}
+
+
+#define OFFSET(x) offsetof(ScaleVAAPIContext, x)
+#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
+static const AVOption scale_vaapi_options[] = {
+    { "w", "Output video width",
+      OFFSET(output_width),  AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS },
+    { "h", "Output video height",
+      OFFSET(output_height), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS },
+    { "format", "Output video format (software format of hardware frames)",
+      OFFSET(output_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS },
+    { NULL },
+};
+
+static const AVClass scale_vaapi_class = {
+    .class_name = "scale_vaapi",
+    .item_name  = av_default_item_name,
+    .option     = scale_vaapi_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static const AVFilterPad scale_vaapi_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = &scale_vaapi_filter_frame,
+        .config_props = &scale_vaapi_config_input,
+    },
+    { NULL }
+};
+
+static const AVFilterPad scale_vaapi_outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_VIDEO,
+        .config_props = &scale_vaapi_config_output,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_scale_vaapi = {
+    .name          = "scale_vaapi",
+    .description   = NULL_IF_CONFIG_SMALL("Scale to/from VAAPI surfaces."),
+    .priv_size     = sizeof(ScaleVAAPIContext),
+    .init          = &scale_vaapi_init,
+    .uninit        = &scale_vaapi_uninit,
+    .query_formats = &scale_vaapi_query_formats,
+    .inputs        = scale_vaapi_inputs,
+    .outputs       = scale_vaapi_outputs,
+    .priv_class    = &scale_vaapi_class,
+};
diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
index 63b22c3..0f22644 100644
--- a/libavfilter/vf_subtitles.c
+++ b/libavfilter/vf_subtitles.c
@@ -333,7 +333,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
         ret = -1;
         if (ass->stream_index < fmt->nb_streams) {
             for (j = 0; j < fmt->nb_streams; j++) {
-                if (fmt->streams[j]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+                if (fmt->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
                     if (ass->stream_index == k) {
                         ret = j;
                         break;
@@ -355,7 +355,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
     /* Load attached fonts */
     for (j = 0; j < fmt->nb_streams; j++) {
         AVStream *st = fmt->streams[j];
-        if (st->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT &&
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT &&
             attachment_is_font(st)) {
             const AVDictionaryEntry *tag = NULL;
             tag = av_dict_get(st->metadata, "filename", NULL,
@@ -365,8 +365,8 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
                 av_log(ctx, AV_LOG_DEBUG, "Loading attached font: %s\n",
                        tag->value);
                 ass_add_font(ass->library, tag->value,
-                             st->codec->extradata,
-                             st->codec->extradata_size);
+                             st->codecpar->extradata,
+                             st->codecpar->extradata_size);
             } else {
                 av_log(ctx, AV_LOG_WARNING,
                        "Font attachment has no filename, ignored.\n");
@@ -378,14 +378,13 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
     ass_set_fonts(ass->renderer, NULL, NULL, 1, NULL, 1);
 
     /* Open decoder */
-    dec_ctx = st->codec;
-    dec = avcodec_find_decoder(dec_ctx->codec_id);
+    dec = avcodec_find_decoder(st->codecpar->codec_id);
     if (!dec) {
         av_log(ctx, AV_LOG_ERROR, "Failed to find subtitle codec %s\n",
-               avcodec_get_name(dec_ctx->codec_id));
+               avcodec_get_name(st->codecpar->codec_id));
         return AVERROR(EINVAL);
     }
-    dec_desc = avcodec_descriptor_get(dec_ctx->codec_id);
+    dec_desc = avcodec_descriptor_get(st->codecpar->codec_id);
     if (dec_desc && !(dec_desc->props & AV_CODEC_PROP_TEXT_SUB)) {
         av_log(ctx, AV_LOG_ERROR,
                "Only text based subtitles are currently supported\n");
@@ -393,7 +392,28 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
     }
     if (ass->charenc)
         av_dict_set(&codec_opts, "sub_charenc", ass->charenc, 0);
-    ret = avcodec_open2(dec_ctx, dec, &codec_opts);
+    if (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57,26,100))
+        av_dict_set(&codec_opts, "sub_text_format", "ass", 0);
+
+    dec_ctx = avcodec_alloc_context3(dec);
+    if (!dec_ctx)
+        return AVERROR(ENOMEM);
+
+    ret = avcodec_parameters_to_context(dec_ctx, st->codecpar);
+    if (ret < 0)
+        goto end;
+
+    /*
+     * This is required by the decoding process in order to rescale the
+     * timestamps: in the current API the decoded subtitles have their pts
+     * expressed in AV_TIME_BASE, and thus the lavc internals need to know the
+     * stream time base in order to achieve the rescaling.
+     *
+     * That API is old and needs to be reworked to match behaviour with A/V.
+     */
+    av_codec_set_pkt_timebase(dec_ctx, st->time_base);
+
+    ret = avcodec_open2(dec_ctx, NULL, &codec_opts);
     if (ret < 0)
         goto end;
 
@@ -436,11 +456,17 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
                 av_log(ctx, AV_LOG_WARNING, "Error decoding: %s (ignored)\n",
                        av_err2str(ret));
             } else if (got_subtitle) {
+                const int64_t start_time = av_rescale_q(sub.pts, AV_TIME_BASE_Q, av_make_q(1, 1000));
+                const int64_t duration   = sub.end_display_time;
                 for (i = 0; i < sub.num_rects; i++) {
                     char *ass_line = sub.rects[i]->ass;
                     if (!ass_line)
                         break;
-                    ass_process_data(ass->track, ass_line, strlen(ass_line));
+                    if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,25,100))
+                        ass_process_data(ass->track, ass_line, strlen(ass_line));
+                    else
+                        ass_process_chunk(ass->track, ass_line, strlen(ass_line),
+                                          start_time, duration);
                 }
             }
         }
@@ -450,10 +476,9 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
 
 end:
     av_dict_free(&codec_opts);
-    if (dec_ctx)
-        avcodec_close(dec_ctx);
-    if (fmt)
-        avformat_close_input(&fmt);
+    avcodec_close(dec_ctx);
+    avcodec_free_context(&dec_ctx);
+    avformat_close_input(&fmt);
     return ret;
 }
 
diff --git a/libavfilter/vf_telecine.c b/libavfilter/vf_telecine.c
index 182c670..58babca 100644
--- a/libavfilter/vf_telecine.c
+++ b/libavfilter/vf_telecine.c
@@ -190,6 +190,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
     }
 
     if (s->occupied) {
+        av_frame_make_writable(s->frame[nout]);
         for (i = 0; i < s->nb_planes; i++) {
             // fill in the EARLIER field from the buffered pic
             av_image_copy_plane(s->frame[nout]->data[i] + s->frame[nout]->linesize[i] * s->first_field,
@@ -213,6 +214,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
 
     while (len >= 2) {
         // output THIS image as-is
+        av_frame_make_writable(s->frame[nout]);
         for (i = 0; i < s->nb_planes; i++)
             av_image_copy_plane(s->frame[nout]->data[i], s->frame[nout]->linesize[i],
                                 inpicref->data[i], inpicref->linesize[i],
diff --git a/libavfilter/vf_vectorscope.c b/libavfilter/vf_vectorscope.c
index 2112b80..987bc66 100644
--- a/libavfilter/vf_vectorscope.c
+++ b/libavfilter/vf_vectorscope.c
@@ -23,6 +23,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/xga_font_data.h"
 #include "avfilter.h"
 #include "formats.h"
 #include "internal.h"
@@ -34,6 +35,7 @@ enum VectorscopeMode {
     COLOR2,
     COLOR3,
     COLOR4,
+    COLOR5,
     MODE_NB
 };
 
@@ -42,19 +44,33 @@ typedef struct VectorscopeContext {
     int mode;
     int intensity;
     float fintensity;
-    const uint8_t *bg_color;
+    uint16_t bg_color[4];
     int planewidth[4];
     int planeheight[4];
     int hsub, vsub;
     int x, y, pd;
     int is_yuv;
     int size;
+    int depth;
     int mult;
     int envelope;
-    uint8_t peak[1024][1024];
+    int graticule;
+    float opacity;
+    float bgopacity;
+    float lthreshold;
+    float hthreshold;
+    int tmin;
+    int tmax;
+    int flags;
+    int colorspace;
+    int cs;
+    uint8_t *peak_memory;
+    uint8_t **peak;
 
     void (*vectorscope)(struct VectorscopeContext *s,
                         AVFrame *in, AVFrame *out, int pd);
+    void (*graticulef)(struct VectorscopeContext *s, AVFrame *out,
+                       int X, int Y, int D, int P);
 } VectorscopeContext;
 
 #define OFFSET(x) offsetof(VectorscopeContext, x)
@@ -68,6 +84,7 @@ static const AVOption vectorscope_options[] = {
     {   "color2", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR2}, 0, 0, FLAGS, "mode" },
     {   "color3", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR3}, 0, 0, FLAGS, "mode" },
     {   "color4", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR4}, 0, 0, FLAGS, "mode" },
+    {   "color5", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR5}, 0, 0, FLAGS, "mode" },
     { "x", "set color component on X axis", OFFSET(x), AV_OPT_TYPE_INT, {.i64=1}, 0, 2, FLAGS},
     { "y", "set color component on Y axis", OFFSET(y), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, FLAGS},
     { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.004}, 0, 1, FLAGS},
@@ -78,6 +95,29 @@ static const AVOption vectorscope_options[] = {
     {   "instant",      0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" },
     {   "peak",         0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" },
     {   "peak+instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" },
+    { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule"},
+    { "g",         "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule"},
+    {   "none",         0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" },
+    {   "green",        0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" },
+    {   "color",        0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "graticule" },
+    { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS},
+    { "o",       "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS},
+    { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=4}, 0, 7, FLAGS, "flags"},
+    { "f",     "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=4}, 0, 7, FLAGS, "flags"},
+    {   "white", "draw white point", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" },
+    {   "black", "draw black point", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" },
+    {   "name",  "draw point name",  0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "flags" },
+    { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, FLAGS},
+    { "b",         "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, FLAGS},
+    { "lthreshold", "set low threshold",  OFFSET(lthreshold), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS},
+    { "l",          "set low threshold",  OFFSET(lthreshold), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS},
+    { "hthreshold", "set high threshold", OFFSET(hthreshold), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, FLAGS},
+    { "h",          "set high threshold", OFFSET(hthreshold), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, FLAGS},
+    { "colorspace", "set colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "colorspace"},
+    { "c",          "set colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "colorspace"},
+    {   "auto",       0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "colorspace" },
+    {   "601",        0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "colorspace" },
+    {   "709",        0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "colorspace" },
     { NULL }
 };
 
@@ -89,12 +129,17 @@ static const enum AVPixelFormat out_yuv8_pix_fmts[] = {
 };
 
 static const enum AVPixelFormat out_yuv9_pix_fmts[] = {
-    AV_PIX_FMT_YUV444P9,
+    AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUV444P9,
     AV_PIX_FMT_NONE
 };
 
 static const enum AVPixelFormat out_yuv10_pix_fmts[] = {
-    AV_PIX_FMT_YUV444P10,
+    AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUV444P10,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_yuv12_pix_fmts[] = {
+    AV_PIX_FMT_YUV444P12,
     AV_PIX_FMT_NONE
 };
 
@@ -113,11 +158,19 @@ static const enum AVPixelFormat out_rgb10_pix_fmts[] = {
     AV_PIX_FMT_NONE
 };
 
+static const enum AVPixelFormat out_rgb12_pix_fmts[] = {
+    AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
+    AV_PIX_FMT_NONE
+};
+
 static const enum AVPixelFormat in1_pix_fmts[] = {
     AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
     AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10,
+    AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10,
+    AV_PIX_FMT_YUV444P12,
     AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRP,
     AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
+    AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
     AV_PIX_FMT_NONE
 };
 
@@ -129,8 +182,12 @@ static const enum AVPixelFormat in2_pix_fmts[] = {
     AV_PIX_FMT_YUV440P,  AV_PIX_FMT_YUV410P,
     AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRP,
     AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
+    AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
     AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9,
     AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
+    AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9,
+    AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10,
+    AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV440P12,
     AV_PIX_FMT_NONE
 };
 
@@ -175,28 +232,44 @@ static int query_formats(AVFilterContext *ctx)
         out_pix_fmts = out_rgb9_pix_fmts;
     else if (rgb && depth == 10)
         out_pix_fmts = out_rgb10_pix_fmts;
+    else if (rgb && depth == 12)
+        out_pix_fmts = out_rgb12_pix_fmts;
+    else if (depth == 8)
+        out_pix_fmts = out_yuv8_pix_fmts;
     else if (depth == 9)
         out_pix_fmts = out_yuv9_pix_fmts;
     else if (depth == 10)
         out_pix_fmts = out_yuv10_pix_fmts;
+    else if (depth == 12)
+        out_pix_fmts = out_yuv12_pix_fmts;
     else
-        out_pix_fmts = out_yuv8_pix_fmts;
+        return AVERROR(EAGAIN);
     if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0)
         return ret;
 
     return 0;
 }
 
-static const uint8_t black_yuva_color[4] = { 0, 127, 127, 0 };
-static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 0 };
-
 static int config_output(AVFilterLink *outlink)
 {
     VectorscopeContext *s = outlink->src->priv;
+    int i;
 
     s->intensity = s->fintensity * (s->size - 1);
     outlink->h = outlink->w = s->size;
     outlink->sample_aspect_ratio = (AVRational){1,1};
+
+    s->peak_memory = av_calloc(s->size, s->size);
+    if (!s->peak_memory)
+        return AVERROR(ENOMEM);
+
+    s->peak = av_calloc(s->size, sizeof(*s->peak));
+    if (!s->peak)
+        return AVERROR(ENOMEM);
+
+    for (i = 0; i < s->size; i++)
+        s->peak[i] = s->peak_memory + s->size * i;
+
     return 0;
 }
 
@@ -346,48 +419,55 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
     uint16_t *dpd = dst[pd];
     const int max = s->size - 1;
     const int mid = s->size / 2;
+    const int tmin = s->tmin;
+    const int tmax = s->tmax;
     int i, j, k;
 
     for (k = 0; k < 4 && dst[k]; k++) {
-        const int mult = s->mult;
-
         for (i = 0; i < out->height ; i++)
             for (j = 0; j < out->width; j++)
                 AV_WN16(out->data[k] + i * out->linesize[k] + j * 2,
-                        s->mode == COLOR && k == s->pd ? 0 : s->bg_color[k] * mult);
+                        (s->mode == COLOR || s->mode == COLOR5) && k == s->pd ? 0 : s->bg_color[k]);
     }
 
     switch (s->mode) {
     case COLOR:
+    case COLOR5:
     case GRAY:
         if (s->is_yuv) {
             for (i = 0; i < h; i++) {
                 const int iwx = i * slinesizex;
                 const int iwy = i * slinesizey;
+                const int iwd = i * slinesized;
                 for (j = 0; j < w; j++) {
                     const int x = FFMIN(spx[iwx + j], max);
                     const int y = FFMIN(spy[iwy + j], max);
+                    const int z = spd[iwd + j];
                     const int pos = y * dlinesize + x;
 
+                    if (z < tmin || z > tmax)
+                        continue;
+
                     dpd[pos] = FFMIN(dpd[pos] + intensity, max);
-                    if (dst[3])
-                        dst[3][pos] = max;
                 }
             }
         } else {
             for (i = 0; i < h; i++) {
                 const int iwx = i * slinesizex;
                 const int iwy = i * slinesizey;
+                const int iwd = i * slinesized;
                 for (j = 0; j < w; j++) {
                     const int x = FFMIN(spx[iwx + j], max);
                     const int y = FFMIN(spy[iwy + j], max);
+                    const int z = spd[iwd + j];
                     const int pos = y * dlinesize + x;
 
+                    if (z < tmin || z > tmax)
+                        continue;
+
                     dst[0][pos] = FFMIN(dst[0][pos] + intensity, max);
                     dst[1][pos] = FFMIN(dst[1][pos] + intensity, max);
                     dst[2][pos] = FFMIN(dst[2][pos] + intensity, max);
-                    if (dst[3])
-                        dst[3][pos] = max;
                 }
             }
         }
@@ -397,34 +477,40 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
             for (i = 0; i < h; i++) {
                 const int iw1 = i * slinesizex;
                 const int iw2 = i * slinesizey;
+                const int iwd = i * slinesized;
                 for (j = 0; j < w; j++) {
                     const int x = FFMIN(spx[iw1 + j], max);
                     const int y = FFMIN(spy[iw2 + j], max);
+                    const int z = spd[iwd + j];
                     const int pos = y * dlinesize + x;
 
+                    if (z < tmin || z > tmax)
+                        continue;
+
                     if (!dpd[pos])
                         dpd[pos] = FFABS(mid - x) + FFABS(mid - y);
                     dpx[pos] = x;
                     dpy[pos] = y;
-                    if (dst[3])
-                        dst[3][pos] = max;
                 }
             }
         } else {
             for (i = 0; i < h; i++) {
                 const int iw1 = i * slinesizex;
                 const int iw2 = i * slinesizey;
+                const int iwd = i * slinesized;
                 for (j = 0; j < w; j++) {
                     const int x = FFMIN(spx[iw1 + j], max);
                     const int y = FFMIN(spy[iw2 + j], max);
+                    const int z = spd[iwd + j];
                     const int pos = y * dlinesize + x;
 
+                    if (z < tmin || z > tmax)
+                        continue;
+
                     if (!dpd[pos])
                         dpd[pos] = FFMIN(x + y, max);
                     dpx[pos] = x;
                     dpy[pos] = y;
-                    if (dst[3])
-                        dst[3][pos] = max;
                 }
             }
         }
@@ -433,16 +519,19 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
         for (i = 0; i < h; i++) {
             const int iw1 = i * slinesizex;
             const int iw2 = i * slinesizey;
+            const int iwd = i * slinesized;
             for (j = 0; j < w; j++) {
                 const int x = FFMIN(spx[iw1 + j], max);
                 const int y = FFMIN(spy[iw2 + j], max);
+                const int z = spd[iwd + j];
                 const int pos = y * dlinesize + x;
 
+                if (z < tmin || z > tmax)
+                    continue;
+
                 dpd[pos] = FFMIN(max, dpd[pos] + intensity);
                 dpx[pos] = x;
                 dpy[pos] = y;
-                if (dst[3])
-                    dst[3][pos] = max;
             }
         }
         break;
@@ -454,13 +543,15 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
             for (j = 0; j < in->width; j++) {
                 const int x = FFMIN(spx[iwx + (j >> hsub)], max);
                 const int y = FFMIN(spy[iwy + (j >> hsub)], max);
+                const int z = spd[iwd + j];
                 const int pos = y * dlinesize + x;
 
-                dpd[pos] = FFMAX(spd[iwd + j], dpd[pos]);
+                if (z < tmin || z > tmax)
+                    continue;
+
+                dpd[pos] = FFMAX(z, dpd[pos]);
                 dpx[pos] = x;
                 dpy[pos] = y;
-                if (dst[3])
-                    dst[3][pos] = max;
             }
         }
         break;
@@ -470,6 +561,17 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
 
     envelope16(s, out);
 
+    if (dst[3]) {
+        for (i = 0; i < out->height; i++) {
+            for (j = 0; j < out->width; j++) {
+                int pos = i * dlinesize + j;
+
+                if (dpd[pos])
+                    dst[3][pos] = max;
+            }
+        }
+    }
+
     if (s->mode == COLOR) {
         for (i = 0; i < out->height; i++) {
             for (j = 0; j < out->width; j++) {
@@ -480,6 +582,16 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
                 }
             }
         }
+    } else if (s->mode == COLOR5) {
+        for (i = 0; i < out->height; i++) {
+            for (j = 0; j < out->width; j++) {
+                if (!dpd[i * dlinesize + j]) {
+                    dpx[i * dlinesize + j] = j;
+                    dpy[i * dlinesize + j] = i;
+                    dpd[i * dlinesize + j] = mid * M_SQRT2 - hypot(i - mid, j - mid);
+                }
+            }
+        }
     }
 }
 
@@ -503,44 +615,53 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
     uint8_t *dpx = dst[px];
     uint8_t *dpy = dst[py];
     uint8_t *dpd = dst[pd];
+    const int tmin = s->tmin;
+    const int tmax = s->tmax;
     int i, j, k;
 
     for (k = 0; k < 4 && dst[k]; k++)
         for (i = 0; i < out->height ; i++)
             memset(dst[k] + i * out->linesize[k],
-                   s->mode == COLOR && k == s->pd ? 0 : s->bg_color[k], out->width);
+                   (s->mode == COLOR || s->mode == COLOR5) && k == s->pd ? 0 : s->bg_color[k], out->width);
 
     switch (s->mode) {
+    case COLOR5:
     case COLOR:
     case GRAY:
         if (s->is_yuv) {
             for (i = 0; i < h; i++) {
                 const int iwx = i * slinesizex;
                 const int iwy = i * slinesizey;
+                const int iwd = i * slinesized;
                 for (j = 0; j < w; j++) {
                     const int x = spx[iwx + j];
                     const int y = spy[iwy + j];
+                    const int z = spd[iwd + j];
                     const int pos = y * dlinesize + x;
 
+                    if (z < tmin || z > tmax)
+                        continue;
+
                     dpd[pos] = FFMIN(dpd[pos] + intensity, 255);
-                    if (dst[3])
-                        dst[3][pos] = 255;
                 }
             }
         } else {
             for (i = 0; i < h; i++) {
                 const int iwx = i * slinesizex;
                 const int iwy = i * slinesizey;
+                const int iwd = i * slinesized;
                 for (j = 0; j < w; j++) {
                     const int x = spx[iwx + j];
                     const int y = spy[iwy + j];
+                    const int z = spd[iwd + j];
                     const int pos = y * dlinesize + x;
 
+                    if (z < tmin || z > tmax)
+                        continue;
+
                     dst[0][pos] = FFMIN(dst[0][pos] + intensity, 255);
                     dst[1][pos] = FFMIN(dst[1][pos] + intensity, 255);
                     dst[2][pos] = FFMIN(dst[2][pos] + intensity, 255);
-                    if (dst[3])
-                        dst[3][pos] = 255;
                 }
             }
         }
@@ -550,34 +671,40 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
             for (i = 0; i < h; i++) {
                 const int iw1 = i * slinesizex;
                 const int iw2 = i * slinesizey;
+                const int iwd = i * slinesized;
                 for (j = 0; j < w; j++) {
                     const int x = spx[iw1 + j];
                     const int y = spy[iw2 + j];
+                    const int z = spd[iwd + j];
                     const int pos = y * dlinesize + x;
 
+                    if (z < tmin || z > tmax)
+                        continue;
+
                     if (!dpd[pos])
                         dpd[pos] = FFABS(128 - x) + FFABS(128 - y);
                     dpx[pos] = x;
                     dpy[pos] = y;
-                    if (dst[3])
-                        dst[3][pos] = 255;
                 }
             }
         } else {
             for (i = 0; i < h; i++) {
                 const int iw1 = i * slinesizex;
                 const int iw2 = i * slinesizey;
+                const int iwd = i * slinesized;
                 for (j = 0; j < w; j++) {
                     const int x = spx[iw1 + j];
                     const int y = spy[iw2 + j];
+                    const int z = spd[iwd + j];
                     const int pos = y * dlinesize + x;
 
+                    if (z < tmin || z > tmax)
+                        continue;
+
                     if (!dpd[pos])
                         dpd[pos] = FFMIN(x + y, 255);
                     dpx[pos] = x;
                     dpy[pos] = y;
-                    if (dst[3])
-                        dst[3][pos] = 255;
                 }
             }
         }
@@ -586,16 +713,19 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
         for (i = 0; i < h; i++) {
             const int iw1 = i * slinesizex;
             const int iw2 = i * slinesizey;
+            const int iwd = i * slinesized;
             for (j = 0; j < w; j++) {
                 const int x = spx[iw1 + j];
                 const int y = spy[iw2 + j];
+                const int z = spd[iwd + j];
                 const int pos = y * dlinesize + x;
 
+                if (z < tmin || z > tmax)
+                    continue;
+
                 dpd[pos] = FFMIN(255, dpd[pos] + intensity);
                 dpx[pos] = x;
                 dpy[pos] = y;
-                if (dst[3])
-                    dst[3][pos] = 255;
             }
         }
         break;
@@ -607,13 +737,15 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
             for (j = 0; j < in->width; j++) {
                 const int x = spx[iwx + (j >> hsub)];
                 const int y = spy[iwy + (j >> hsub)];
+                const int z = spd[iwd + j];
                 const int pos = y * dlinesize + x;
 
-                dpd[pos] = FFMAX(spd[iwd + j], dpd[pos]);
+                if (z < tmin || z > tmax)
+                    continue;
+
+                dpd[pos] = FFMAX(z, dpd[pos]);
                 dpx[pos] = x;
                 dpy[pos] = y;
-                if (dst[3])
-                    dst[3][pos] = 255;
             }
         }
         break;
@@ -623,6 +755,17 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
 
     envelope(s, out);
 
+    if (dst[3]) {
+        for (i = 0; i < out->height; i++) {
+            for (j = 0; j < out->width; j++) {
+                int pos = i * dlinesize + j;
+
+                if (dpd[pos])
+                    dst[3][pos] = 255;
+            }
+        }
+    }
+
     if (s->mode == COLOR) {
         for (i = 0; i < out->height; i++) {
             for (j = 0; j < out->width; j++) {
@@ -633,6 +776,428 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
                 }
             }
         }
+    } else if (s->mode == COLOR5) {
+        for (i = 0; i < out->height; i++) {
+            for (j = 0; j < out->width; j++) {
+                if (!dpd[i * out->linesize[pd] + j]) {
+                    dpx[i * out->linesize[px] + j] = j;
+                    dpy[i * out->linesize[py] + j] = i;
+                    dpd[i * out->linesize[pd] + j] = 128 * M_SQRT2 - hypot(i - 128, j - 128);
+                }
+            }
+        }
+    }
+}
+
+const static char *positions_name[] = {
+    "R", "B", "Cy", "Yl", "G", "Mg",
+};
+
+const static uint16_t positions[][14][3] = {
+  {
+    {  81,  90, 240 }, {  41, 240, 110 }, { 170, 166,  16 },
+    { 210,  16, 146 }, { 145,  54,  34 }, { 106, 202, 222 },
+    { 162,  44, 142 }, { 131, 156,  44 }, { 112,  72,  58 },
+    {  84, 184, 198 }, {  65, 100, 212 }, {  35, 212, 114 },
+    { 235, 128, 128 }, { 16, 128, 128 } },
+  { {  63, 102, 240 }, {  32, 240, 118 }, { 188, 154,  16 },
+    { 219,  16, 138 }, { 173,  42,  26 }, {  78, 214, 230 },
+    {  28, 212, 120 }, {  51, 109, 212 }, {  63, 193, 204 },
+    { 133,  63,  52 }, { 145, 147,  44 }, { 168,  44, 136 },
+    { 235, 128, 128 }, { 16, 128, 128 } },
+  { {  81*2,  90*2, 240*2 }, {  41*2, 240*2, 110*2 }, { 170*2, 166*2,  16*2 },
+    { 210*2,  16*2, 146*2 }, { 145*2,  54*2,  34*2 }, { 106*2, 202*2, 222*2 },
+    { 162*2,  44*2, 142*2 }, { 131*2, 156*2,  44*2 }, { 112*2,  72*2,  58*2 },
+    {  84*2, 184*2, 198*2 }, {  65*2, 100*2, 212*2 }, {  35*2, 212*2, 114*2 },
+    { 470, 256, 256 }, { 32, 256, 256 } },
+  { {  63*2, 102*2, 240*2 }, {  32*2, 240*2, 118*2 }, { 188*2, 154*2,  16*2 },
+    { 219*2,  16*2, 138*2 }, { 173*2,  42*2,  26*2 }, {  78*2, 214*2, 230*2 },
+    {  28*2, 212*2, 120*2 }, {  51*2, 109*2, 212*2 }, {  63*2, 193*2, 204*2 },
+    { 133*2,  63*2,  52*2 }, { 145*2, 147*2,  44*2 }, { 168*2,  44*2, 136*2 },
+    { 470, 256, 256 }, { 32, 256, 256 } },
+  { {  81*4,  90*4, 240*4 }, {  41*4, 240*4, 110*4 }, { 170*4, 166*4,  16*4 },
+    { 210*4,  16*4, 146*4 }, { 145*4,  54*4,  34*4 }, { 106*4, 202*4, 222*4 },
+    { 162*4,  44*4, 142*4 }, { 131*4, 156*4,  44*4 }, { 112*4,  72*4,  58*4 },
+    {  84*4, 184*4, 198*4 }, {  65*4, 100*4, 212*4 }, {  35*4, 212*4, 114*4 },
+    { 940, 512, 512 }, { 64, 512, 512 } },
+  { {  63*4, 102*4, 240*4 }, {  32*4, 240*4, 118*4 }, { 188*4, 154*4,  16*4 },
+    { 219*4,  16*4, 138*4 }, { 173*4,  42*4,  26*4 }, {  78*4, 214*4, 230*4 },
+    {  28*4, 212*4, 120*4 }, {  51*4, 109*4, 212*4 }, {  63*4, 193*4, 204*4 },
+    { 133*4,  63*4,  52*4 }, { 145*4, 147*4,  44*4 }, { 168*4,  44*4, 136*4 },
+    { 940, 512, 512 }, { 64, 512, 512 } },
+  { {  81*8,  90*4, 240*8 }, {  41*8, 240*8, 110*8 }, { 170*8, 166*8,  16*8 },
+    { 210*8,  16*4, 146*8 }, { 145*8,  54*8,  34*8 }, { 106*8, 202*8, 222*8 },
+    { 162*8,  44*4, 142*8 }, { 131*8, 156*8,  44*8 }, { 112*8,  72*8,  58*8 },
+    {  84*8, 184*4, 198*8 }, {  65*8, 100*8, 212*8 }, {  35*8, 212*8, 114*8 },
+    { 1880, 1024, 1024 }, { 128, 1024, 1024 } },
+  { {  63*8, 102*8, 240*8 }, {  32*8, 240*8, 118*8 }, { 188*8, 154*8,  16*8 },
+    { 219*8,  16*8, 138*8 }, { 173*8,  42*8,  26*8 }, {  78*8, 214*8, 230*8 },
+    {  28*8, 212*8, 120*8 }, {  51*8, 109*8, 212*8 }, {  63*8, 193*8, 204*8 },
+    { 133*8,  63*8,  52*8 }, { 145*8, 147*8,  44*8 }, { 168*8,  44*8, 136*8 },
+    { 1880, 1024, 1024 }, { 128, 1024, 1024 } },
+  { {  81*16,  90*16, 240*16 }, {  41*16, 240*16, 110*16 }, { 170*16, 166*16,  16*16 },
+    { 210*16,  16*16, 146*16 }, { 145*16,  54*16,  34*16 }, { 106*16, 202*16, 222*16 },
+    { 162*16,  44*16, 142*16 }, { 131*16, 156*16,  44*16 }, { 112*16,  72*16,  58*16 },
+    {  84*16, 184*16, 198*16 }, {  65*16, 100*16, 212*16 }, {  35*16, 212*16, 114*16 },
+    { 3760, 2048, 2048 }, { 256, 2048, 2048 } },
+  { {  63*16, 102*16, 240*16 }, {  32*16, 240*16, 118*16 }, { 188*16, 154*16,  16*16 },
+    { 219*16,  16*16, 138*16 }, { 173*16,  42*16,  26*16 }, {  78*16, 214*16, 230*16 },
+    {  28*16, 212*16, 120*16 }, {  51*16, 109*16, 212*16 }, {  63*16, 193*16, 204*16 },
+    { 133*16,  63*16,  52*16 }, { 145*16, 147*16,  44*16 }, { 168*16,  44*16, 136*16 },
+    { 3760, 2048, 2048 }, { 256, 2048, 2048 } },
+};
+
+static void draw_dots(uint8_t *dst, int L, int v, float o)
+{
+    const float f = 1. - o;
+    const float V = o * v;
+    int l = L * 2;
+
+    dst[ l - 3] = dst[ l - 3] * f + V;
+    dst[ l + 3] = dst[ l + 3] * f + V;
+    dst[-l - 3] = dst[-l - 3] * f + V;
+    dst[-l + 3] = dst[-l + 3] * f + V;
+
+    l += L;
+
+    dst[ l - 3] = dst[ l - 3] * f + V;
+    dst[ l + 3] = dst[ l + 3] * f + V;
+    dst[ l - 2] = dst[ l - 2] * f + V;
+    dst[ l + 2] = dst[ l + 2] * f + V;
+    dst[-l - 3] = dst[-l - 3] * f + V;
+    dst[-l + 3] = dst[-l + 3] * f + V;
+    dst[-l - 2] = dst[-l - 2] * f + V;
+    dst[-l + 2] = dst[-l + 2] * f + V;
+}
+
+static void draw_dots16(uint16_t *dst, int L, int v, float o)
+{
+    const float f = 1. - o;
+    const float V = o * v;
+    int l = L * 2;
+
+    dst[ l - 3] = dst[ l - 3] * f + V;
+    dst[ l + 3] = dst[ l + 3] * f + V;
+    dst[-l - 3] = dst[-l - 3] * f + V;
+    dst[-l + 3] = dst[-l + 3] * f + V;
+
+    l += L;
+
+    dst[ l - 3] = dst[ l - 3] * f + V;
+    dst[ l + 3] = dst[ l + 3] * f + V;
+    dst[ l - 2] = dst[ l - 2] * f + V;
+    dst[ l + 2] = dst[ l + 2] * f + V;
+    dst[-l - 3] = dst[-l - 3] * f + V;
+    dst[-l + 3] = dst[-l + 3] * f + V;
+    dst[-l - 2] = dst[-l - 2] * f + V;
+    dst[-l + 2] = dst[-l + 2] * f + V;
+}
+
+static void none_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
+{
+}
+
+static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
+{
+    const uint8_t *font;
+    int font_height;
+    int i, plane;
+
+    font = avpriv_cga_font,   font_height =  8;
+
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
+        for (i = 0; txt[i]; i++) {
+            int char_y, mask;
+            int v = color[plane];
+
+            uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8);
+            for (char_y = font_height - 1; char_y >= 0; char_y--) {
+                for (mask = 0x80; mask; mask >>= 1) {
+                    if (font[txt[i] * font_height + char_y] & mask)
+                        p[0] = p[0] * o2 + v * o1;
+                    p++;
+                }
+                p += out->linesize[plane] - 8;
+            }
+        }
+    }
+}
+
+static void draw_htext16(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint16_t color[4])
+{
+    const uint8_t *font;
+    int font_height;
+    int i, plane;
+
+    font = avpriv_cga_font,   font_height =  8;
+
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
+        for (i = 0; txt[i]; i++) {
+            int char_y, mask;
+            int v = color[plane];
+
+            uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8);
+            for (char_y = font_height - 1; char_y >= 0; char_y--) {
+                for (mask = 0x80; mask; mask >>= 1) {
+                    if (font[txt[i] * font_height + char_y] & mask)
+                        p[0] = p[0] * o2 + v * o1;
+                    p++;
+                }
+                p += out->linesize[plane] / 2 - 8;
+            }
+        }
+    }
+}
+
+static void color_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
+{
+    const int max = s->size - 1;
+    const float o = s->opacity;
+    int i;
+
+    for (i = 0; i < 12; i++) {
+        int x = positions[P][i][X];
+        int y = positions[P][i][Y];
+        int d = positions[P][i][D];
+
+        draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, d, o);
+        draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, x, o);
+        draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, y, o);
+        if (out->data[3])
+            draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
+    }
+
+    if (s->flags & 1) {
+        int x = positions[P][12][X];
+        int y = positions[P][12][Y];
+        int d = positions[P][12][D];
+
+        draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, d, o);
+        draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, x, o);
+        draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, y, o);
+        if (out->data[3])
+            draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
+    }
+
+    if (s->flags & 2) {
+        int x = positions[P][13][X];
+        int y = positions[P][13][Y];
+        int d = positions[P][13][D];
+
+        draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, d, o);
+        draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, x, o);
+        draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, y, o);
+        if (out->data[3])
+            draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
+    }
+
+    for (i = 0; i < 6 && s->flags & 4; i++) {
+        uint16_t color[4] = { 0, 0, 0, 0 };
+        int x = positions[P][i][X];
+        int y = positions[P][i][Y];
+        int d = positions[P][i][D];
+
+        color[D] = d;
+        color[X] = x;
+        color[Y] = y;
+        color[3] = max;
+
+        if (x > max / 2)
+            x += 8;
+        else
+            x -= 14;
+        if (y > max / 2)
+            y += 8;
+        else
+            y -= 14;
+
+        x = av_clip(x, 0, out->width - 9);
+        y = av_clip(y, 0, out->height - 9);
+        draw_htext16(out, x, y, o, 1. - o, positions_name[i], color);
+    }
+}
+
+static void color_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
+{
+    const float o = s->opacity;
+    int i;
+
+    for (i = 0; i < 12; i++) {
+        int x = positions[P][i][X];
+        int y = positions[P][i][Y];
+        int d = positions[P][i][D];
+
+        draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], d, o);
+        draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], x, o);
+        draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], y, o);
+        if (out->data[3])
+            draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
+    }
+
+    if (s->flags & 1) {
+        int x = positions[P][12][X];
+        int y = positions[P][12][Y];
+        int d = positions[P][12][D];
+
+        draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], d, o);
+        draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], x, o);
+        draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], y, o);
+        if (out->data[3])
+            draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
+    }
+
+    if (s->flags & 2) {
+        int x = positions[P][13][X];
+        int y = positions[P][13][Y];
+        int d = positions[P][12][D];
+
+        draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], d, o);
+        draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], x, o);
+        draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], y, o);
+        if (out->data[3])
+            draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
+    }
+
+    for (i = 0; i < 6 && s->flags & 4; i++) {
+        uint8_t color[4] = { 0, 0, 0, 255 };
+        int x = positions[P][i][X];
+        int y = positions[P][i][Y];
+        int d = positions[P][i][D];
+
+        color[D] = d;
+        color[X] = x;
+        color[Y] = y;
+
+        if (x > 128)
+            x += 8;
+        else
+            x -= 14;
+        if (y > 128)
+            y += 8;
+        else
+            y -= 14;
+
+        x = av_clip(x, 0, out->width - 9);
+        y = av_clip(y, 0, out->height - 9);
+        draw_htext(out, x, y, o, 1. - o, positions_name[i], color);
+    }
+}
+
+static void green_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
+{
+    const int max = s->size - 1;
+    const float o = s->opacity;
+    const int m = s->mult;
+    int i;
+
+    for (i = 0; i < 12; i++) {
+        int x = positions[P][i][X];
+        int y = positions[P][i][Y];
+
+        draw_dots16((uint16_t *)(out->data[0] + y * out->linesize[0] + x * 2), out->linesize[0] / 2, 128 * m, o);
+        draw_dots16((uint16_t *)(out->data[1] + y * out->linesize[1] + x * 2), out->linesize[1] / 2, 0, o);
+        draw_dots16((uint16_t *)(out->data[2] + y * out->linesize[2] + x * 2), out->linesize[2] / 2, 0, o);
+        if (out->data[3])
+            draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
+    }
+
+    if (s->flags & 1) {
+        int x = positions[P][12][X];
+        int y = positions[P][12][Y];
+
+        draw_dots16((uint16_t *)(out->data[0] + y * out->linesize[0] + x * 2), out->linesize[0] / 2, 128 * m, o);
+        draw_dots16((uint16_t *)(out->data[1] + y * out->linesize[1] + x * 2), out->linesize[1] / 2, 0, o);
+        draw_dots16((uint16_t *)(out->data[2] + y * out->linesize[2] + x * 2), out->linesize[2] / 2, 0, o);
+        if (out->data[3])
+            draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
+    }
+
+    if (s->flags & 2) {
+        int x = positions[P][13][X];
+        int y = positions[P][13][Y];
+
+        draw_dots16((uint16_t *)(out->data[0] + y * out->linesize[0] + x * 2), out->linesize[0] / 2, 128 * m, o);
+        draw_dots16((uint16_t *)(out->data[1] + y * out->linesize[1] + x * 2), out->linesize[1] / 2, 0, o);
+        draw_dots16((uint16_t *)(out->data[2] + y * out->linesize[2] + x * 2), out->linesize[2] / 2, 0, o);
+        if (out->data[3])
+            draw_dots16((uint16_t *)(out->data[3] + y * out->linesize[3] + x * 2), out->linesize[3] / 2, max, o);
+    }
+
+    for (i = 0; i < 6 && s->flags & 4; i++) {
+        const uint16_t color[4] = { 128 * m, 0, 0, max };
+        int x = positions[P][i][X];
+        int y = positions[P][i][Y];
+
+        if (x > max / 2)
+            x += 8;
+        else
+            x -= 14;
+        if (y > max / 2)
+            y += 8;
+        else
+            y -= 14;
+
+        x = av_clip(x, 0, out->width - 9);
+        y = av_clip(y, 0, out->height - 9);
+        draw_htext16(out, x, y, o, 1. - o, positions_name[i], color);
+    }
+}
+
+static void green_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P)
+{
+    const float o = s->opacity;
+    int i;
+
+    for (i = 0; i < 12; i++) {
+        int x = positions[P][i][X];
+        int y = positions[P][i][Y];
+
+        draw_dots(out->data[0] + y * out->linesize[0] + x, out->linesize[0], 128, o);
+        draw_dots(out->data[1] + y * out->linesize[1] + x, out->linesize[1], 0, o);
+        draw_dots(out->data[2] + y * out->linesize[2] + x, out->linesize[2], 0, o);
+        if (out->data[3])
+            draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
+    }
+
+    if (s->flags & 1) {
+        int x = positions[P][12][X];
+        int y = positions[P][12][Y];
+
+        draw_dots(out->data[0] + y * out->linesize[0] + x, out->linesize[0], 128, o);
+        draw_dots(out->data[1] + y * out->linesize[1] + x, out->linesize[1], 0, o);
+        draw_dots(out->data[2] + y * out->linesize[2] + x, out->linesize[2], 0, o);
+        if (out->data[3])
+            draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
+    }
+
+    if (s->flags & 2) {
+        int x = positions[P][13][X];
+        int y = positions[P][13][Y];
+
+        draw_dots(out->data[0] + y * out->linesize[0] + x, out->linesize[0], 128, o);
+        draw_dots(out->data[1] + y * out->linesize[1] + x, out->linesize[1], 0, o);
+        draw_dots(out->data[2] + y * out->linesize[2] + x, out->linesize[2], 0, o);
+        if (out->data[3])
+            draw_dots(out->data[3] + y * out->linesize[3] + x, out->linesize[3], 255, o);
+    }
+
+    for (i = 0; i < 6 && s->flags & 4; i++) {
+        const uint8_t color[4] = { 128, 0, 0, 255 };
+        int x = positions[P][i][X];
+        int y = positions[P][i][Y];
+
+        if (x > 128)
+            x += 8;
+        else
+            x -= 14;
+        if (y > 128)
+            y += 8;
+        else
+            y -= 14;
+
+        x = av_clip(x, 0, out->width - 9);
+        y = av_clip(y, 0, out->height - 9);
+        draw_htext(out, x, y, o, 1. - o, positions_name[i], color);
     }
 }
 
@@ -642,15 +1207,38 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     VectorscopeContext *s = ctx->priv;
     AVFilterLink *outlink = ctx->outputs[0];
     AVFrame *out;
+    int plane;
+
+    if (s->colorspace) {
+        s->cs = (s->depth - 8) * 2 + s->colorspace - 1;
+    } else {
+        switch (av_frame_get_colorspace(in)) {
+        case AVCOL_SPC_SMPTE170M:
+        case AVCOL_SPC_BT470BG:
+            s->cs = (s->depth - 8) * 2 + 0;
+            break;
+        case AVCOL_SPC_BT709:
+        default:
+            s->cs = (s->depth - 8) * 2 + 1;
+        }
+    }
 
     out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
     if (!out) {
         av_frame_free(&in);
         return AVERROR(ENOMEM);
     }
-    out->pts = in->pts;
+    av_frame_copy_props(out, in);
 
     s->vectorscope(s, in, out, s->pd);
+    s->graticulef(s, out, s->x, s->y, s->pd, s->cs);
+
+    for (plane = 0; plane < 4; plane++) {
+        if (out->data[plane]) {
+            out->data[plane]    += (s->size - 1) * out->linesize[plane];
+            out->linesize[plane] = -out->linesize[plane];
+        }
+    }
 
     av_frame_free(&in);
     return ff_filter_frame(outlink, out);
@@ -659,11 +1247,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 static int config_input(AVFilterLink *inlink)
 {
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
-    VectorscopeContext *s = inlink->dst->priv;
+    AVFilterContext *ctx = inlink->dst;
+    VectorscopeContext *s = ctx->priv;
 
     s->is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB);
     s->size = 1 << desc->comp[0].depth;
     s->mult = s->size / 256;
+    s->depth = desc->comp[0].depth;
+    s->tmin = s->lthreshold * (s->size - 1);
+    s->tmax = s->hthreshold * (s->size - 1);
+
+    if (s->tmin > s->tmax) {
+        av_log(ctx, AV_LOG_ERROR, "low threshold should be less than high threshold\n");
+        return AVERROR(EINVAL);
+    }
 
     if (s->mode == GRAY && s->is_yuv)
         s->pd = 0;
@@ -681,15 +1278,36 @@ static int config_input(AVFilterLink *inlink)
     else
         s->vectorscope = vectorscope16;
 
+    s->graticulef = none_graticule;
+
+    if (s->is_yuv && s->size == 256) {
+        if (s->graticule == 1)
+            s->graticulef = green_graticule;
+        else if (s->graticule == 2)
+            s->graticulef = color_graticule;
+    } else if (s->is_yuv) {
+        if (s->graticule == 1)
+            s->graticulef = green_graticule16;
+        else if (s->graticule == 2)
+            s->graticulef = color_graticule16;
+    }
+
+    s->bg_color[3] = s->bgopacity * (s->size - 1);
+
     switch (inlink->format) {
+    case AV_PIX_FMT_GBRP12:
     case AV_PIX_FMT_GBRP10:
     case AV_PIX_FMT_GBRP9:
     case AV_PIX_FMT_GBRAP:
     case AV_PIX_FMT_GBRP:
-        s->bg_color = black_gbrp_color;
+        s->bg_color[0] = 0;
+        s->bg_color[1] = 0;
+        s->bg_color[2] = 0;
         break;
     default:
-        s->bg_color = black_yuva_color;
+        s->bg_color[0] = 0;
+        s->bg_color[1] = s->size / 2 - 1;
+        s->bg_color[2] = s->size / 2 - 1;
     }
 
     s->hsub = desc->log2_chroma_w;
@@ -702,6 +1320,14 @@ static int config_input(AVFilterLink *inlink)
     return 0;
 }
 
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    VectorscopeContext *s = ctx->priv;
+
+    av_freep(&s->peak);
+    av_freep(&s->peak_memory);
+}
+
 static const AVFilterPad inputs[] = {
     {
         .name         = "default",
@@ -727,6 +1353,7 @@ AVFilter ff_vf_vectorscope = {
     .priv_size     = sizeof(VectorscopeContext),
     .priv_class    = &vectorscope_class,
     .query_formats = query_formats,
+    .uninit        = uninit,
     .inputs        = inputs,
     .outputs       = outputs,
 };
diff --git a/libavfilter/vf_waveform.c b/libavfilter/vf_waveform.c
index 4fb78bd..c2b84fb 100644
--- a/libavfilter/vf_waveform.c
+++ b/libavfilter/vf_waveform.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2015 Paul B Mahol
+ * Copyright (c) 2012-2016 Paul B Mahol
  * Copyright (c) 2013 Marton Balint
  *
  * This file is part of FFmpeg.
@@ -23,6 +23,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/xga_font_data.h"
 #include "avfilter.h"
 #include "formats.h"
 #include "internal.h"
@@ -33,14 +34,38 @@ enum FilterType {
     FLAT,
     AFLAT,
     CHROMA,
-    ACHROMA,
     COLOR,
+    ACOLOR,
     NB_FILTERS
 };
 
+enum DisplayType {
+    OVERLAY,
+    STACK,
+    PARADE,
+    NB_DISPLAYS
+};
+
+enum ScaleType {
+    DIGITAL,
+    MILLIVOLTS,
+    IRE,
+    NB_SCALES
+};
+
+typedef struct GraticuleLine {
+    const char *name;
+    uint16_t pos;
+} GraticuleLine;
+
+typedef struct GraticuleLines {
+    struct GraticuleLine line[4];
+} GraticuleLines;
+
 typedef struct WaveformContext {
     const AVClass *class;
     int            mode;
+    int            acomp;
     int            ncomp;
     int            pcomp;
     const uint8_t  *bg_color;
@@ -49,17 +74,28 @@ typedef struct WaveformContext {
     int            mirror;
     int            display;
     int            envelope;
+    int            graticule;
+    float          opacity;
     int            estart[4];
     int            eend[4];
     int            *emax[4][4];
     int            *emin[4][4];
     int            *peak;
     int            filter;
+    int            flags;
     int            bits;
     int            max;
     int            size;
-    void (*waveform)(struct WaveformContext *s, AVFrame *in, AVFrame *out,
-                     int component, int intensity, int offset, int column);
+    int            scale;
+    int            shift_w[4], shift_h[4];
+    GraticuleLines *glines;
+    int            nb_glines;
+    void (*waveform)(struct WaveformContext *s,
+                     AVFrame *in, AVFrame *out,
+                     int component, int intensity,
+                     int offset_y, int offset_x,
+                     int column, int mirror);
+    void (*graticulef)(struct WaveformContext *s, AVFrame *out);
     const AVPixFmtDescriptor *desc;
 } WaveformContext;
 
@@ -75,10 +111,11 @@ static const AVOption waveform_options[] = {
     { "i",         "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS },
     { "mirror", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
     { "r",      "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
-    { "display", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display" },
-    { "d",       "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "display" },
-        { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "display" },
-        { "parade",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "display" },
+    { "display", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=STACK}, 0, NB_DISPLAYS-1, FLAGS, "display" },
+    { "d",       "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=STACK}, 0, NB_DISPLAYS-1, FLAGS, "display" },
+        { "overlay", NULL, 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY}, 0, 0, FLAGS, "display" },
+        { "stack",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=STACK},   0, 0, FLAGS, "display" },
+        { "parade",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=PARADE},  0, 0, FLAGS, "display" },
     { "components", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS },
     { "c",          "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS },
     { "envelope", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" },
@@ -93,16 +130,31 @@ static const AVOption waveform_options[] = {
         { "flat"   , NULL, 0, AV_OPT_TYPE_CONST, {.i64=FLAT},    0, 0, FLAGS, "filter" },
         { "aflat"  , NULL, 0, AV_OPT_TYPE_CONST, {.i64=AFLAT},   0, 0, FLAGS, "filter" },
         { "chroma",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=CHROMA},  0, 0, FLAGS, "filter" },
-        { "achroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64=ACHROMA}, 0, 0, FLAGS, "filter" },
         { "color",   NULL, 0, AV_OPT_TYPE_CONST, {.i64=COLOR},   0, 0, FLAGS, "filter" },
+        { "acolor",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=ACOLOR},  0, 0, FLAGS, "filter" },
+    { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "graticule" },
+    { "g",         "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "graticule" },
+        { "none",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" },
+        { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" },
+    { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
+    { "o",       "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS },
+    { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" },
+    { "fl",    "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" },
+        { "numbers",  "draw numbers", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" },
+        { "dots",     "draw dots instead of lines", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" },
+    { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" },
+    { "s",     "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" },
+        { "digital",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=DIGITAL},    0, 0, FLAGS, "scale" },
+        { "millivolts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MILLIVOLTS}, 0, 0, FLAGS, "scale" },
+        { "ire",        NULL, 0, AV_OPT_TYPE_CONST, {.i64=IRE},        0, 0, FLAGS, "scale" },
     { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(waveform);
 
-static const enum AVPixelFormat lowpass_pix_fmts[] = {
+static const enum AVPixelFormat in_lowpass_pix_fmts[] = {
     AV_PIX_FMT_GBRP,     AV_PIX_FMT_GBRAP,
-    AV_PIX_FMT_GBRP9,    AV_PIX_FMT_GBRP10,
+    AV_PIX_FMT_GBRP9,    AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
     AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
     AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV440P,
     AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUV410P,
@@ -114,59 +166,174 @@ static const enum AVPixelFormat lowpass_pix_fmts[] = {
     AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9,
     AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10,
     AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10,
+    AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12,
     AV_PIX_FMT_NONE
 };
 
-static const enum AVPixelFormat flat_pix_fmts[] = {
-    AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE
+static const enum AVPixelFormat in_color_pix_fmts[] = {
+    AV_PIX_FMT_GBRP,     AV_PIX_FMT_GBRAP,
+    AV_PIX_FMT_GBRP9,    AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
+    AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
+    AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV440P,
+    AV_PIX_FMT_YUV411P,
+    AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P,
+    AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
+    AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
+    AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9,
+    AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9,
+    AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10,
+    AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10,
+    AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat in_flat_pix_fmts[] = {
+    AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
+    AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV440P,
+    AV_PIX_FMT_YUV411P,
+    AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P,
+    AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
+    AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P,
+    AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9,
+    AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA420P9,
+    AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10,
+    AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA420P10,
+    AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12,
+    AV_PIX_FMT_NONE
 };
 
-static const enum AVPixelFormat color_pix_fmts[] = {
+static const enum AVPixelFormat out_rgb8_lowpass_pix_fmts[] = {
     AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
-    AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_rgb9_lowpass_pix_fmts[] = {
+    AV_PIX_FMT_GBRP9,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_rgb10_lowpass_pix_fmts[] = {
+    AV_PIX_FMT_GBRP10,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_rgb12_lowpass_pix_fmts[] = {
+    AV_PIX_FMT_GBRP12,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_yuv8_lowpass_pix_fmts[] = {
+    AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVA444P,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_yuv9_lowpass_pix_fmts[] = {
+    AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUVA444P9,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_yuv10_lowpass_pix_fmts[] = {
+    AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_yuv12_lowpass_pix_fmts[] = {
+    AV_PIX_FMT_YUV444P12,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat out_gray8_lowpass_pix_fmts[] = {
+    AV_PIX_FMT_GRAY8,
+    AV_PIX_FMT_NONE
+};
+
+static const enum AVPixelFormat flat_pix_fmts[] = {
     AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
     AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10,
+    AV_PIX_FMT_YUV444P12,
     AV_PIX_FMT_NONE
 };
 
 static int query_formats(AVFilterContext *ctx)
 {
     WaveformContext *s = ctx->priv;
-    AVFilterFormats *fmts_list;
-    const enum AVPixelFormat *pix_fmts;
+    const enum AVPixelFormat *out_pix_fmts;
+    const enum AVPixelFormat *in_pix_fmts;
+    const AVPixFmtDescriptor *desc;
+    AVFilterFormats *avff;
+    int depth, rgb, i, ret, ncomp;
+
+    if (!ctx->inputs[0]->in_formats ||
+        !ctx->inputs[0]->in_formats->nb_formats) {
+        return AVERROR(EAGAIN);
+    }
 
     switch (s->filter) {
-    case LOWPASS: pix_fmts = lowpass_pix_fmts; break;
-    case FLAT:
-    case AFLAT:
+    case LOWPASS: in_pix_fmts = in_lowpass_pix_fmts; break;
     case CHROMA:
-    case ACHROMA: pix_fmts = flat_pix_fmts;    break;
-    case COLOR:   pix_fmts = color_pix_fmts;   break;
+    case AFLAT:
+    case FLAT:    in_pix_fmts = in_flat_pix_fmts;    break;
+    case ACOLOR:
+    case COLOR:   in_pix_fmts = in_color_pix_fmts;   break;
     }
 
-    fmts_list = ff_make_format_list(pix_fmts);
-    if (!fmts_list)
-        return AVERROR(ENOMEM);
-    return ff_set_common_formats(ctx, fmts_list);
+    if (!ctx->inputs[0]->out_formats) {
+        if ((ret = ff_formats_ref(ff_make_format_list(in_pix_fmts), &ctx->inputs[0]->out_formats)) < 0)
+            return ret;
+    }
+
+    avff = ctx->inputs[0]->in_formats;
+    desc = av_pix_fmt_desc_get(avff->formats[0]);
+    ncomp = desc->nb_components;
+    rgb = desc->flags & AV_PIX_FMT_FLAG_RGB;
+    depth = desc->comp[0].depth;
+    for (i = 1; i < avff->nb_formats; i++) {
+        desc = av_pix_fmt_desc_get(avff->formats[i]);
+        if (rgb != (desc->flags & AV_PIX_FMT_FLAG_RGB) ||
+            depth != desc->comp[0].depth)
+            return AVERROR(EAGAIN);
+    }
+
+    if (s->filter == LOWPASS && ncomp == 1 && depth == 8)
+        out_pix_fmts = out_gray8_lowpass_pix_fmts;
+    else if (rgb && depth == 8 && ncomp > 2)
+        out_pix_fmts = out_rgb8_lowpass_pix_fmts;
+    else if (rgb && depth == 9 && ncomp > 2)
+        out_pix_fmts = out_rgb9_lowpass_pix_fmts;
+    else if (rgb && depth == 10 && ncomp > 2)
+        out_pix_fmts = out_rgb10_lowpass_pix_fmts;
+    else if (rgb && depth == 12 && ncomp > 2)
+        out_pix_fmts = out_rgb12_lowpass_pix_fmts;
+    else if (depth == 8 && ncomp > 2)
+        out_pix_fmts = out_yuv8_lowpass_pix_fmts;
+    else if (depth == 9 && ncomp > 2)
+        out_pix_fmts = out_yuv9_lowpass_pix_fmts;
+    else if (depth == 10 && ncomp > 2)
+        out_pix_fmts = out_yuv10_lowpass_pix_fmts;
+    else if (depth == 12 && ncomp > 2)
+        out_pix_fmts = out_yuv12_lowpass_pix_fmts;
+    else
+        return AVERROR(EAGAIN);
+    if ((ret = ff_formats_ref(ff_make_format_list(out_pix_fmts), &ctx->outputs[0]->in_formats)) < 0)
+        return ret;
+
+    return 0;
 }
 
-static void envelope_instant16(WaveformContext *s, AVFrame *out, int plane, int component)
+static void envelope_instant16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
 {
     const int dst_linesize = out->linesize[component] / 2;
     const int bg = s->bg_color[component] * (s->max / 256);
     const int limit = s->max - 1;
-    const int is_chroma = (component == 1 || component == 2);
-    const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
-    const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
-    const int dst_h = AV_CEIL_RSHIFT(out->height, shift_h);
-    const int dst_w = AV_CEIL_RSHIFT(out->width, shift_w);
+    const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
+    const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
     const int start = s->estart[plane];
     const int end = s->eend[plane];
     uint16_t *dst;
     int x, y;
 
     if (s->mode) {
-        for (x = 0; x < dst_w; x++) {
+        for (x = offset; x < offset + dst_w; x++) {
             for (y = start; y < end; y++) {
                 dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
                 if (dst[0] != bg) {
@@ -183,7 +350,7 @@ static void envelope_instant16(WaveformContext *s, AVFrame *out, int plane, int
             }
         }
     } else {
-        for (y = 0; y < dst_h; y++) {
+        for (y = offset; y < offset + dst_h; y++) {
             dst = (uint16_t *)out->data[component] + y * dst_linesize;
             for (x = start; x < end; x++) {
                 if (dst[x] != bg) {
@@ -201,22 +368,19 @@ static void envelope_instant16(WaveformContext *s, AVFrame *out, int plane, int
     }
 }
 
-static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int component)
+static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
 {
     const int dst_linesize = out->linesize[component];
     const uint8_t bg = s->bg_color[component];
-    const int is_chroma = (component == 1 || component == 2);
-    const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
-    const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
-    const int dst_h = AV_CEIL_RSHIFT(out->height, shift_h);
-    const int dst_w = AV_CEIL_RSHIFT(out->width, shift_w);
+    const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
+    const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
     const int start = s->estart[plane];
     const int end = s->eend[plane];
     uint8_t *dst;
     int x, y;
 
     if (s->mode) {
-        for (x = 0; x < dst_w; x++) {
+        for (x = offset; x < offset + dst_w; x++) {
             for (y = start; y < end; y++) {
                 dst = out->data[component] + y * dst_linesize + x;
                 if (dst[0] != bg) {
@@ -233,7 +397,7 @@ static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int co
             }
         }
     } else {
-        for (y = 0; y < dst_h; y++) {
+        for (y = offset; y < offset + dst_h; y++) {
             dst = out->data[component] + y * dst_linesize;
             for (x = start; x < end; x++) {
                 if (dst[x] != bg) {
@@ -251,16 +415,13 @@ static void envelope_instant(WaveformContext *s, AVFrame *out, int plane, int co
     }
 }
 
-static void envelope_peak16(WaveformContext *s, AVFrame *out, int plane, int component)
+static void envelope_peak16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
 {
     const int dst_linesize = out->linesize[component] / 2;
     const int bg = s->bg_color[component] * (s->max / 256);
     const int limit = s->max - 1;
-    const int is_chroma = (component == 1 || component == 2);
-    const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
-    const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
-    const int dst_h = AV_CEIL_RSHIFT(out->height, shift_h);
-    const int dst_w = AV_CEIL_RSHIFT(out->width, shift_w);
+    const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
+    const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
     const int start = s->estart[plane];
     const int end = s->eend[plane];
     int *emax = s->emax[plane][component];
@@ -269,70 +430,67 @@ static void envelope_peak16(WaveformContext *s, AVFrame *out, int plane, int com
     int x, y;
 
     if (s->mode) {
-        for (x = 0; x < dst_w; x++) {
-            for (y = start; y < end && y < emin[x]; y++) {
+        for (x = offset; x < offset + dst_w; x++) {
+            for (y = start; y < end && y < emin[x - offset]; y++) {
                 dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
                 if (dst[0] != bg) {
-                    emin[x] = y;
+                    emin[x - offset] = y;
                     break;
                 }
             }
-            for (y = end - 1; y >= start && y >= emax[x]; y--) {
+            for (y = end - 1; y >= start && y >= emax[x - offset]; y--) {
                 dst = (uint16_t *)out->data[component] + y * dst_linesize + x;
                 if (dst[0] != bg) {
-                    emax[x] = y;
+                    emax[x - offset] = y;
                     break;
                 }
             }
         }
 
         if (s->envelope == 3)
-            envelope_instant16(s, out, plane, component);
+            envelope_instant16(s, out, plane, component, offset);
 
-        for (x = 0; x < dst_w; x++) {
-            dst = (uint16_t *)out->data[component] + emin[x] * dst_linesize + x;
+        for (x = offset; x < offset + dst_w; x++) {
+            dst = (uint16_t *)out->data[component] + emin[x - offset] * dst_linesize + x;
             dst[0] = limit;
-            dst = (uint16_t *)out->data[component] + emax[x] * dst_linesize + x;
+            dst = (uint16_t *)out->data[component] + emax[x - offset] * dst_linesize + x;
             dst[0] = limit;
         }
     } else {
-        for (y = 0; y < dst_h; y++) {
+        for (y = offset; y < offset + dst_h; y++) {
             dst = (uint16_t *)out->data[component] + y * dst_linesize;
-            for (x = start; x < end && x < emin[y]; x++) {
+            for (x = start; x < end && x < emin[y - offset]; x++) {
                 if (dst[x] != bg) {
-                    emin[y] = x;
+                    emin[y - offset] = x;
                     break;
                 }
             }
-            for (x = end - 1; x >= start && x >= emax[y]; x--) {
+            for (x = end - 1; x >= start && x >= emax[y - offset]; x--) {
                 if (dst[x] != bg) {
-                    emax[y] = x;
+                    emax[y - offset] = x;
                     break;
                 }
             }
         }
 
         if (s->envelope == 3)
-            envelope_instant16(s, out, plane, component);
+            envelope_instant16(s, out, plane, component, offset);
 
-        for (y = 0; y < dst_h; y++) {
-            dst = (uint16_t *)out->data[component] + y * dst_linesize + emin[y];
+        for (y = offset; y < offset + dst_h; y++) {
+            dst = (uint16_t *)out->data[component] + y * dst_linesize + emin[y - offset];
             dst[0] = limit;
-            dst = (uint16_t *)out->data[component] + y * dst_linesize + emax[y];
+            dst = (uint16_t *)out->data[component] + y * dst_linesize + emax[y - offset];
             dst[0] = limit;
         }
     }
 }
 
-static void envelope_peak(WaveformContext *s, AVFrame *out, int plane, int component)
+static void envelope_peak(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
 {
     const int dst_linesize = out->linesize[component];
     const int bg = s->bg_color[component];
-    const int is_chroma = (component == 1 || component == 2);
-    const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
-    const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
-    const int dst_h = AV_CEIL_RSHIFT(out->height, shift_h);
-    const int dst_w = AV_CEIL_RSHIFT(out->width, shift_w);
+    const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
+    const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
     const int start = s->estart[plane];
     const int end = s->eend[plane];
     int *emax = s->emax[plane][component];
@@ -341,80 +499,80 @@ static void envelope_peak(WaveformContext *s, AVFrame *out, int plane, int compo
     int x, y;
 
     if (s->mode) {
-        for (x = 0; x < dst_w; x++) {
-            for (y = start; y < end && y < emin[x]; y++) {
+        for (x = offset; x < offset + dst_w; x++) {
+            for (y = start; y < end && y < emin[x - offset]; y++) {
                 dst = out->data[component] + y * dst_linesize + x;
                 if (dst[0] != bg) {
-                    emin[x] = y;
+                    emin[x - offset] = y;
                     break;
                 }
             }
-            for (y = end - 1; y >= start && y >= emax[x]; y--) {
+            for (y = end - 1; y >= start && y >= emax[x - offset]; y--) {
                 dst = out->data[component] + y * dst_linesize + x;
                 if (dst[0] != bg) {
-                    emax[x] = y;
+                    emax[x - offset] = y;
                     break;
                 }
             }
         }
 
         if (s->envelope == 3)
-            envelope_instant(s, out, plane, component);
+            envelope_instant(s, out, plane, component, offset);
 
-        for (x = 0; x < dst_w; x++) {
-            dst = out->data[component] + emin[x] * dst_linesize + x;
+        for (x = offset; x < offset + dst_w; x++) {
+            dst = out->data[component] + emin[x - offset] * dst_linesize + x;
             dst[0] = 255;
-            dst = out->data[component] + emax[x] * dst_linesize + x;
+            dst = out->data[component] + emax[x - offset] * dst_linesize + x;
             dst[0] = 255;
         }
     } else {
-        for (y = 0; y < dst_h; y++) {
+        for (y = offset; y < offset + dst_h; y++) {
             dst = out->data[component] + y * dst_linesize;
-            for (x = start; x < end && x < emin[y]; x++) {
+            for (x = start; x < end && x < emin[y - offset]; x++) {
                 if (dst[x] != bg) {
-                    emin[y] = x;
+                    emin[y - offset] = x;
                     break;
                 }
             }
-            for (x = end - 1; x >= start && x >= emax[y]; x--) {
+            for (x = end - 1; x >= start && x >= emax[y - offset]; x--) {
                 if (dst[x] != bg) {
-                    emax[y] = x;
+                    emax[y - offset] = x;
                     break;
                 }
             }
         }
 
         if (s->envelope == 3)
-            envelope_instant(s, out, plane, component);
+            envelope_instant(s, out, plane, component, offset);
 
-        for (y = 0; y < dst_h; y++) {
-            dst = out->data[component] + y * dst_linesize + emin[y];
+        for (y = offset; y < offset + dst_h; y++) {
+            dst = out->data[component] + y * dst_linesize + emin[y - offset];
             dst[0] = 255;
-            dst = out->data[component] + y * dst_linesize + emax[y];
+            dst = out->data[component] + y * dst_linesize + emax[y - offset];
             dst[0] = 255;
         }
     }
 }
 
-static void envelope16(WaveformContext *s, AVFrame *out, int plane, int component)
+static void envelope16(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
 {
     if (s->envelope == 0) {
         return;
     } else if (s->envelope == 1) {
-        envelope_instant16(s, out, plane, component);
+        envelope_instant16(s, out, plane, component, offset);
     } else {
-        envelope_peak16(s, out, plane, component);
+        envelope_peak16(s, out, plane, component, offset);
     }
 }
 
-static void envelope(WaveformContext *s, AVFrame *out, int plane, int component)
+static void envelope(WaveformContext *s, AVFrame *out, int plane, int component, int offset)
 {
     if (s->envelope == 0) {
         return;
     } else if (s->envelope == 1) {
-        envelope_instant(s, out, plane, component);
+        envelope_instant(s, out, plane, component, offset);
     } else {
-        envelope_peak(s, out, plane, component);
+        envelope_peak(s, out, plane, component, offset);
     }
 }
 
@@ -434,14 +592,15 @@ static void update(uint8_t *target, int max, int intensity)
         *target = 255;
 }
 
-static void lowpass16(WaveformContext *s, AVFrame *in, AVFrame *out,
-                      int component, int intensity, int offset, int column)
+static av_always_inline void lowpass16(WaveformContext *s,
+                                       AVFrame *in, AVFrame *out,
+                                       int component, int intensity,
+                                       int offset_y, int offset_x,
+                                       int column, int mirror)
 {
     const int plane = s->desc->comp[component].plane;
-    const int mirror = s->mirror;
-    const int is_chroma = (component == 1 || component == 2);
-    const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
-    const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
+    const int shift_w = s->shift_w[component];
+    const int shift_h = s->shift_h[component];
     const int src_linesize = in->linesize[plane] / 2;
     const int dst_linesize = out->linesize[plane] / 2;
     const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
@@ -450,14 +609,15 @@ static void lowpass16(WaveformContext *s, AVFrame *in, AVFrame *out,
     const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
     const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
     const uint16_t *src_data = (const uint16_t *)in->data[plane];
-    uint16_t *dst_data = (uint16_t *)out->data[plane] + (column ? (offset >> shift_h) * dst_linesize : offset >> shift_w);
-    uint16_t * const dst_bottom_line = dst_data + dst_linesize * ((s->size >> shift_h) - 1);
+    uint16_t *dst_data = (uint16_t *)out->data[plane] + offset_y * dst_linesize + offset_x;
+    uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
     uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
+    const int step = column ? 1 << shift_w : 1 << shift_h;
     const uint16_t *p;
     int y;
 
     if (!column && mirror)
-        dst_data += s->size >> shift_w;
+        dst_data += s->size;
 
     for (y = 0; y < src_h; y++) {
         const uint16_t *src_data_end = src_data + src_w;
@@ -465,33 +625,57 @@ static void lowpass16(WaveformContext *s, AVFrame *in, AVFrame *out,
 
         for (p = src_data; p < src_data_end; p++) {
             uint16_t *target;
-            int v = FFMIN(*p, limit);
+            int i = 0, v = FFMIN(*p, limit);
 
             if (column) {
-                target = dst++ + dst_signed_linesize * (v >> shift_h);
+                do {
+                    target = dst++ + dst_signed_linesize * v;
+                    update16(target, max, intensity, limit);
+                } while (++i < step);
             } else {
-                if (mirror)
-                    target = dst_data - (v >> shift_w) - 1;
-                else
-                    target = dst_data + (v >> shift_w);
+                uint16_t *row = dst_data;
+                do {
+                    if (mirror)
+                        target = row - v - 1;
+                    else
+                        target = row + v;
+                    update16(target, max, intensity, limit);
+                    row += dst_linesize;
+                } while (++i < step);
             }
-            update16(target, max, intensity, limit);
         }
         src_data += src_linesize;
-        dst_data += dst_linesize;
+        dst_data += dst_linesize * step;
     }
 
-    envelope16(s, out, plane, plane);
+    envelope16(s, out, plane, plane, column ? offset_x : offset_y);
+}
+
+#define LOWPASS16_FUNC(name, column, mirror)               \
+static void lowpass16_##name(WaveformContext *s,           \
+                             AVFrame *in, AVFrame *out,    \
+                             int component, int intensity, \
+                             int offset_y, int offset_x,   \
+                             int unused1, int unused2)     \
+{                                                          \
+    lowpass16(s, in, out, component, intensity,            \
+              offset_y, offset_x, column, mirror);         \
 }
 
-static void lowpass(WaveformContext *s, AVFrame *in, AVFrame *out,
-                    int component, int intensity, int offset, int column)
+LOWPASS16_FUNC(column_mirror, 1, 1)
+LOWPASS16_FUNC(column,        1, 0)
+LOWPASS16_FUNC(row_mirror,    0, 1)
+LOWPASS16_FUNC(row,           0, 0)
+
+static av_always_inline void lowpass(WaveformContext *s,
+                                     AVFrame *in, AVFrame *out,
+                                     int component, int intensity,
+                                     int offset_y, int offset_x,
+                                     int column, int mirror)
 {
     const int plane = s->desc->comp[component].plane;
-    const int mirror = s->mirror;
-    const int is_chroma = (component == 1 || component == 2);
-    const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
-    const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
+    const int shift_w = s->shift_w[component];
+    const int shift_h = s->shift_h[component];
     const int src_linesize = in->linesize[plane];
     const int dst_linesize = out->linesize[plane];
     const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
@@ -499,14 +683,15 @@ static void lowpass(WaveformContext *s, AVFrame *in, AVFrame *out,
     const int src_h = AV_CEIL_RSHIFT(in->height, shift_h);
     const int src_w = AV_CEIL_RSHIFT(in->width, shift_w);
     const uint8_t *src_data = in->data[plane];
-    uint8_t *dst_data = out->data[plane] + (column ? (offset >> shift_h) * dst_linesize : offset >> shift_w);
-    uint8_t * const dst_bottom_line = dst_data + dst_linesize * ((s->size >> shift_h) - 1);
+    uint8_t *dst_data = out->data[plane] + offset_y * dst_linesize + offset_x;
+    uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
     uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
+    const int step = column ? 1 << shift_w : 1 << shift_h;
     const uint8_t *p;
     int y;
 
     if (!column && mirror)
-        dst_data += s->size >> shift_w;
+        dst_data += s->size;
 
     for (y = 0; y < src_h; y++) {
         const uint8_t *src_data_end = src_data + src_w;
@@ -515,33 +700,92 @@ static void lowpass(WaveformContext *s, AVFrame *in, AVFrame *out,
         for (p = src_data; p < src_data_end; p++) {
             uint8_t *target;
             if (column) {
-                target = dst++ + dst_signed_linesize * (*p >> shift_h);
+                target = dst + dst_signed_linesize * *p;
+                dst += step;
+                update(target, max, intensity);
             } else {
+                uint8_t *row = dst_data;
                 if (mirror)
-                    target = dst_data - (*p >> shift_w) - 1;
+                    target = row - *p - 1;
                 else
-                    target = dst_data + (*p >> shift_w);
+                    target = row + *p;
+                update(target, max, intensity);
+                row += dst_linesize;
             }
-            update(target, max, intensity);
         }
         src_data += src_linesize;
-        dst_data += dst_linesize;
+        dst_data += dst_linesize * step;
+    }
+
+    if (column && step > 1) {
+        const int dst_w = s->display == PARADE ? out->width / s->acomp : out->width;
+        const int dst_h = 256;
+        uint8_t *dst;
+        int x, z;
+
+        dst = out->data[plane] + offset_y * dst_linesize + offset_x;
+        for (y = 0; y < dst_h; y++) {
+            for (x = 0; x < dst_w; x+=step) {
+                for (z = 1; z < step; z++) {
+                    dst[x + z] = dst[x];
+                }
+            }
+            dst += dst_linesize;
+        }
+    } else if (step > 1) {
+        const int dst_h = s->display == PARADE ? out->height / s->acomp : out->height;
+        const int dst_w = 256;
+        uint8_t *dst;
+        int z;
+
+        dst = out->data[plane] + offset_y * dst_linesize + offset_x;
+        for (y = 0; y < dst_h; y+=step) {
+            for (z = 1; z < step; z++)
+                memcpy(dst + dst_linesize * z, dst, dst_w);
+            dst += dst_linesize * step;
+        }
     }
 
-    envelope(s, out, plane, plane);
+    envelope(s, out, plane, plane, column ? offset_x : offset_y);
+}
+
+#define LOWPASS_FUNC(name, column, mirror)               \
+static void lowpass_##name(WaveformContext *s,           \
+                           AVFrame *in, AVFrame *out,    \
+                           int component, int intensity, \
+                           int offset_y, int offset_x,   \
+                           int unused1, int unused2)     \
+{                                                        \
+    lowpass(s, in, out, component, intensity,            \
+            offset_y, offset_x, column, mirror);         \
 }
 
-static void flat(WaveformContext *s, AVFrame *in, AVFrame *out,
-                 int component, int intensity, int offset, int column)
+LOWPASS_FUNC(column_mirror, 1, 1)
+LOWPASS_FUNC(column,        1, 0)
+LOWPASS_FUNC(row_mirror,    0, 1)
+LOWPASS_FUNC(row,           0, 0)
+
+static av_always_inline void flat16(WaveformContext *s,
+                                    AVFrame *in, AVFrame *out,
+                                    int component, int intensity,
+                                    int offset_y, int offset_x,
+                                    int column, int mirror)
 {
     const int plane = s->desc->comp[component].plane;
-    const int mirror = s->mirror;
-    const int c0_linesize = in->linesize[ plane + 0 ];
-    const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
-    const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
-    const int d0_linesize = out->linesize[ plane + 0 ];
-    const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
-    const int max = 255 - intensity;
+    const int c0_linesize = in->linesize[ plane + 0 ] / 2;
+    const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
+    const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
+    const int c0_shift_w = s->shift_w[ component + 0 ];
+    const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[ component + 0 ];
+    const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
+    const int d0_linesize = out->linesize[ plane + 0 ] / 2;
+    const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
+    const int limit = s->max - 1;
+    const int max = limit - intensity;
+    const int mid = s->max / 2;
     const int src_h = in->height;
     const int src_w = in->width;
     int x, y;
@@ -551,41 +795,44 @@ static void flat(WaveformContext *s, AVFrame *in, AVFrame *out,
         const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
 
         for (x = 0; x < src_w; x++) {
-            const uint8_t *c0_data = in->data[plane + 0];
-            const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
-            const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
-            uint8_t *d0_data = out->data[plane] + offset * d0_linesize;
-            uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
-            uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
-            uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
-            uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
-            uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
+            const uint16_t *c0_data = (uint16_t *)in->data[plane + 0];
+            const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
+            const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
+            uint16_t *d0_data = (uint16_t *)(out->data[plane]) + offset_y * d0_linesize + offset_x;
+            uint16_t *d1_data = (uint16_t *)(out->data[(plane + 1) % s->ncomp]) + offset_y * d1_linesize + offset_x;
+            uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
+            uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
+            uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
+            uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
 
             for (y = 0; y < src_h; y++) {
-                const int c0 = c0_data[x] + 256;
-                const int c1 = FFABS(c1_data[x] - 128) + FFABS(c2_data[x] - 128);
-                uint8_t *target;
+                const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + s->max;
+                const int c1 = FFMIN(FFABS(c1_data[x >> c1_shift_w] - mid) + FFABS(c2_data[x >> c2_shift_w] - mid), limit);
+                uint16_t *target;
 
                 target = d0 + x + d0_signed_linesize * c0;
-                update(target, max, intensity);
+                update16(target, max, intensity, limit);
                 target = d1 + x + d1_signed_linesize * (c0 - c1);
-                update(target, max, 1);
+                update16(target, max, intensity, limit);
                 target = d1 + x + d1_signed_linesize * (c0 + c1);
-                update(target, max, 1);
-
-                c0_data += c0_linesize;
-                c1_data += c1_linesize;
-                c2_data += c2_linesize;
+                update16(target, max, intensity, limit);
+
+                if (!c0_shift_h || (y & c0_shift_h))
+                    c0_data += c0_linesize;
+                if (!c1_shift_h || (y & c1_shift_h))
+                    c1_data += c1_linesize;
+                if (!c2_shift_h || (y & c2_shift_h))
+                    c2_data += c2_linesize;
                 d0_data += d0_linesize;
                 d1_data += d1_linesize;
             }
         }
     } else {
-        const uint8_t *c0_data = in->data[plane];
-        const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
-        const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
-        uint8_t *d0_data = out->data[plane] + offset;
-        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset;
+        const uint16_t *c0_data = (uint16_t *)in->data[plane];
+        const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
+        const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
+        uint16_t *d0_data = (uint16_t *)(out->data[plane]) + offset_y * d0_linesize + offset_x;
+        uint16_t *d1_data = (uint16_t *)(out->data[(plane + 1) % s->ncomp]) + offset_y * d1_linesize + offset_x;
 
         if (mirror) {
             d0_data += s->size - 1;
@@ -594,50 +841,60 @@ static void flat(WaveformContext *s, AVFrame *in, AVFrame *out,
 
         for (y = 0; y < src_h; y++) {
             for (x = 0; x < src_w; x++) {
-                int c0 = c0_data[x] + 256;
-                const int c1 = FFABS(c1_data[x] - 128) + FFABS(c2_data[x] - 128);
-                uint8_t *target;
+                const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + s->max;
+                const int c1 = FFMIN(FFABS(c1_data[x >> c1_shift_w] - mid) + FFABS(c2_data[x >> c2_shift_w] - mid), limit);
+                uint16_t *target;
 
                 if (mirror) {
                     target = d0_data - c0;
-                    update(target, max, intensity);
+                    update16(target, max, intensity, limit);
                     target = d1_data - (c0 - c1);
-                    update(target, max, 1);
+                    update16(target, max, intensity, limit);
                     target = d1_data - (c0 + c1);
-                    update(target, max, 1);
+                    update16(target, max, intensity, limit);
                 } else {
                     target = d0_data + c0;
-                    update(target, max, intensity);
+                    update16(target, max, intensity, limit);
                     target = d1_data + (c0 - c1);
-                    update(target, max, 1);
+                    update16(target, max, intensity, limit);
                     target = d1_data + (c0 + c1);
-                    update(target, max, 1);
+                    update16(target, max, intensity, limit);
                 }
             }
 
-            c0_data += c0_linesize;
-            c1_data += c1_linesize;
-            c2_data += c2_linesize;
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
             d0_data += d0_linesize;
             d1_data += d1_linesize;
         }
     }
 
-    envelope(s, out, plane, plane);
-    envelope(s, out, plane, (plane + 1) % s->ncomp);
+    envelope16(s, out, plane, plane, column ? offset_x : offset_y);
+    envelope16(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y);
 }
 
-static void aflat(WaveformContext *s, AVFrame *in, AVFrame *out,
-                  int component, int intensity, int offset, int column)
+static av_always_inline void flat(WaveformContext *s,
+                                  AVFrame *in, AVFrame *out,
+                                  int component, int intensity,
+                                  int offset_y, int offset_x,
+                                  int column, int mirror)
 {
     const int plane = s->desc->comp[component].plane;
-    const int mirror = s->mirror;
     const int c0_linesize = in->linesize[ plane + 0 ];
     const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
     const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
+    const int c0_shift_w = s->shift_w[ component + 0 ];
+    const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[ component + 0 ];
+    const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
     const int d0_linesize = out->linesize[ plane + 0 ];
     const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
-    const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
     const int max = 255 - intensity;
     const int src_h = in->height;
     const int src_w = in->width;
@@ -646,176 +903,233 @@ static void aflat(WaveformContext *s, AVFrame *in, AVFrame *out,
     if (column) {
         const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
         const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
-        const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
 
         for (x = 0; x < src_w; x++) {
             const uint8_t *c0_data = in->data[plane + 0];
             const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
             const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
-            uint8_t *d0_data = out->data[plane] + offset * d0_linesize;
-            uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
-            uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset * d2_linesize;
+            uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
+            uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
             uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
             uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
             uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
             uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
-            uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
-            uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
 
             for (y = 0; y < src_h; y++) {
-                const int c0 = c0_data[x] + 128;
-                const int c1 = c1_data[x] - 128;
-                const int c2 = c2_data[x] - 128;
+                const int c0 = c0_data[x >> c0_shift_w] + 256;
+                const int c1 = FFABS(c1_data[x >> c1_shift_w] - 128) + FFABS(c2_data[x >> c2_shift_w] - 128);
                 uint8_t *target;
 
                 target = d0 + x + d0_signed_linesize * c0;
                 update(target, max, intensity);
-
+                target = d1 + x + d1_signed_linesize * (c0 - c1);
+                update(target, max, intensity);
                 target = d1 + x + d1_signed_linesize * (c0 + c1);
-                update(target, max, 1);
-
-                target = d2 + x + d2_signed_linesize * (c0 + c2);
-                update(target, max, 1);
+                update(target, max, intensity);
 
-                c0_data += c0_linesize;
-                c1_data += c1_linesize;
-                c2_data += c2_linesize;
+                if (!c0_shift_h || (y & c0_shift_h))
+                    c0_data += c0_linesize;
+                if (!c1_shift_h || (y & c1_shift_h))
+                    c1_data += c1_linesize;
+                if (!c2_shift_h || (y & c2_shift_h))
+                    c2_data += c2_linesize;
                 d0_data += d0_linesize;
                 d1_data += d1_linesize;
-                d2_data += d2_linesize;
             }
         }
     } else {
         const uint8_t *c0_data = in->data[plane];
         const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
         const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
-        uint8_t *d0_data = out->data[plane] + offset;
-        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset;
-        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset;
+        uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
 
         if (mirror) {
             d0_data += s->size - 1;
             d1_data += s->size - 1;
-            d2_data += s->size - 1;
         }
 
         for (y = 0; y < src_h; y++) {
             for (x = 0; x < src_w; x++) {
-                const int c0 = c0_data[x] + 128;
-                const int c1 = c1_data[x] - 128;
-                const int c2 = c2_data[x] - 128;
+                int c0 = c0_data[x >> c0_shift_w] + 256;
+                const int c1 = FFABS(c1_data[x >> c1_shift_w] - 128) + FFABS(c2_data[x >> c2_shift_w] - 128);
                 uint8_t *target;
 
                 if (mirror) {
                     target = d0_data - c0;
                     update(target, max, intensity);
+                    target = d1_data - (c0 - c1);
+                    update(target, max, intensity);
                     target = d1_data - (c0 + c1);
-                    update(target, max, 1);
-                    target = d2_data - (c0 + c2);
-                    update(target, max, 1);
+                    update(target, max, intensity);
                 } else {
                     target = d0_data + c0;
                     update(target, max, intensity);
+                    target = d1_data + (c0 - c1);
+                    update(target, max, intensity);
                     target = d1_data + (c0 + c1);
-                    update(target, max, 1);
-                    target = d2_data + (c0 + c2);
-                    update(target, max, 1);
+                    update(target, max, intensity);
                 }
             }
 
-            c0_data += c0_linesize;
-            c1_data += c1_linesize;
-            c2_data += c2_linesize;
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
             d0_data += d0_linesize;
             d1_data += d1_linesize;
-            d2_data += d2_linesize;
         }
     }
 
-    envelope(s, out, plane, (plane + 0) % s->ncomp);
-    envelope(s, out, plane, (plane + 1) % s->ncomp);
-    envelope(s, out, plane, (plane + 2) % s->ncomp);
+    envelope(s, out, plane, plane, column ? offset_x : offset_y);
+    envelope(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y);
 }
 
-static void chroma(WaveformContext *s, AVFrame *in, AVFrame *out,
-                   int component, int intensity, int offset, int column)
+static av_always_inline void aflat16(WaveformContext *s,
+                                     AVFrame *in, AVFrame *out,
+                                     int component, int intensity,
+                                     int offset_y, int offset_x,
+                                     int column, int mirror)
 {
     const int plane = s->desc->comp[component].plane;
-    const int mirror = s->mirror;
-    const int c0_linesize = in->linesize[(plane + 1) % s->ncomp];
-    const int c1_linesize = in->linesize[(plane + 2) % s->ncomp];
-    const int dst_linesize = out->linesize[plane];
-    const int max = 255 - intensity;
+    const int c0_linesize = in->linesize[ plane + 0 ] / 2;
+    const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
+    const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
+    const int c0_shift_w = s->shift_w[ component + 0 ];
+    const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[ component + 0 ];
+    const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
+    const int d0_linesize = out->linesize[ plane + 0 ] / 2;
+    const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
+    const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2;
+    const int limit = s->max - 1;
+    const int max = limit - intensity;
+    const int mid = s->max / 2;
     const int src_h = in->height;
     const int src_w = in->width;
     int x, y;
 
     if (column) {
-        const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
+        const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
+        const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
+        const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
 
         for (x = 0; x < src_w; x++) {
-            const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp];
-            const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp];
-            uint8_t *dst_data = out->data[plane] + offset * dst_linesize;
-            uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
-            uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
-            uint8_t *dst = dst_line;
+            const uint16_t *c0_data = (uint16_t *)in->data[plane + 0];
+            const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
+            const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
+            uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
+            uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+            uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
+            uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
+            uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
+            uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
+            uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
+            uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
+            uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data);
 
             for (y = 0; y < src_h; y++) {
-                const int sum = FFABS(c0_data[x] - 128) + FFABS(c1_data[x] - 128);
-                uint8_t *target;
+                const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid;
+                const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid;
+                const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid;
+                uint16_t *target;
 
-                target = dst + x + dst_signed_linesize * (256 - sum);
-                update(target, max, intensity);
-                target = dst + x + dst_signed_linesize * (255 + sum);
-                update(target, max, intensity);
+                target = d0 + x + d0_signed_linesize * c0;
+                update16(target, max, intensity, limit);
 
-                c0_data += c0_linesize;
-                c1_data += c1_linesize;
-                dst_data += dst_linesize;
+                target = d1 + x + d1_signed_linesize * (c0 + c1);
+                update16(target, max, intensity, limit);
+
+                target = d2 + x + d2_signed_linesize * (c0 + c2);
+                update16(target, max, intensity, limit);
+
+                if (!c0_shift_h || (y & c0_shift_h))
+                    c0_data += c0_linesize;
+                if (!c1_shift_h || (y & c1_shift_h))
+                    c1_data += c1_linesize;
+                if (!c2_shift_h || (y & c2_shift_h))
+                    c2_data += c2_linesize;
+                d0_data += d0_linesize;
+                d1_data += d1_linesize;
+                d2_data += d2_linesize;
             }
         }
     } else {
-        const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp];
-        const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp];
-        uint8_t *dst_data = out->data[plane] + offset;
+        const uint16_t *c0_data = (uint16_t *)in->data[plane];
+        const uint16_t *c1_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
+        const uint16_t *c2_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
+        uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
+
+        if (mirror) {
+            d0_data += s->size - 1;
+            d1_data += s->size - 1;
+            d2_data += s->size - 1;
+        }
 
-        if (mirror)
-            dst_data += s->size - 1;
         for (y = 0; y < src_h; y++) {
             for (x = 0; x < src_w; x++) {
-                const int sum = FFABS(c0_data[x] - 128) + FFABS(c1_data[x] - 128);
-                uint8_t *target;
+                const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit) + mid;
+                const int c1 = FFMIN(c1_data[x >> c1_shift_w], limit) - mid;
+                const int c2 = FFMIN(c2_data[x >> c2_shift_w], limit) - mid;
+                uint16_t *target;
 
                 if (mirror) {
-                    target = dst_data - (256 - sum);
-                    update(target, max, intensity);
-                    target = dst_data - (255 + sum);
-                    update(target, max, intensity);
+                    target = d0_data - c0;
+                    update16(target, max, intensity, limit);
+                    target = d1_data - (c0 + c1);
+                    update16(target, max, intensity, limit);
+                    target = d2_data - (c0 + c2);
+                    update16(target, max, intensity, limit);
                 } else {
-                    target = dst_data + (256 - sum);
-                    update(target, max, intensity);
-                    target = dst_data + (255 + sum);
-                    update(target, max, intensity);
+                    target = d0_data + c0;
+                    update16(target, max, intensity, limit);
+                    target = d1_data + (c0 + c1);
+                    update16(target, max, intensity, limit);
+                    target = d2_data + (c0 + c2);
+                    update16(target, max, intensity, limit);
                 }
             }
 
-            c0_data += c0_linesize;
-            c1_data += c1_linesize;
-            dst_data += dst_linesize;
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
+            d0_data += d0_linesize;
+            d1_data += d1_linesize;
+            d2_data += d2_linesize;
         }
     }
 
-    envelope(s, out, plane, (plane + 0) % s->ncomp);
+    envelope16(s, out, plane, (plane + 0) % s->ncomp, column ? offset_x : offset_y);
+    envelope16(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y);
+    envelope16(s, out, plane, (plane + 2) % s->ncomp, column ? offset_x : offset_y);
 }
 
-static void achroma(WaveformContext *s, AVFrame *in, AVFrame *out,
-                    int component, int intensity, int offset, int column)
+static av_always_inline void aflat(WaveformContext *s,
+                                   AVFrame *in, AVFrame *out,
+                                   int component, int intensity,
+                                   int offset_y, int offset_x,
+                                   int column, int mirror)
 {
     const int plane = s->desc->comp[component].plane;
-    const int mirror = s->mirror;
+    const int c0_linesize = in->linesize[ plane + 0 ];
     const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
     const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
+    const int c0_shift_w = s->shift_w[ component + 0 ];
+    const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[ component + 0 ];
+    const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
+    const int d0_linesize = out->linesize[ plane + 0 ];
     const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
     const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
     const int max = 255 - intensity;
@@ -824,42 +1138,57 @@ static void achroma(WaveformContext *s, AVFrame *in, AVFrame *out,
     int x, y;
 
     if (column) {
+        const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
         const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
         const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
 
         for (x = 0; x < src_w; x++) {
+            const uint8_t *c0_data = in->data[plane + 0];
             const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
             const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
-            uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
-            uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset * d2_linesize;
+            uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
+            uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+            uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
+            uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
+            uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
             uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
             uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
             uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
             uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
 
             for (y = 0; y < src_h; y++) {
-                const int c1 = c1_data[x] - 128;
-                const int c2 = c2_data[x] - 128;
+                const int c0 = c0_data[x >> c0_shift_w] + 128;
+                const int c1 = c1_data[x >> c1_shift_w] - 128;
+                const int c2 = c2_data[x >> c2_shift_w] - 128;
                 uint8_t *target;
 
-                target = d1 + x + d1_signed_linesize * (128 + c1);
+                target = d0 + x + d0_signed_linesize * c0;
                 update(target, max, intensity);
 
-                target = d2 + x + d2_signed_linesize * (128 + c2);
+                target = d1 + x + d1_signed_linesize * (c0 + c1);
                 update(target, max, intensity);
 
-                c1_data += c1_linesize;
-                c2_data += c2_linesize;
+                target = d2 + x + d2_signed_linesize * (c0 + c2);
+                update(target, max, intensity);
+
+                if (!c0_shift_h || (y & c0_shift_h))
+                    c0_data += c0_linesize;
+                if (!c1_shift_h || (y & c1_shift_h))
+                    c1_data += c1_linesize;
+                if (!c1_shift_h || (y & c1_shift_h))
+                    c2_data += c1_linesize;
+                d0_data += d0_linesize;
                 d1_data += d1_linesize;
                 d2_data += d2_linesize;
             }
         }
     } else {
+        const uint8_t *c0_data = in->data[plane];
         const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
         const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
-        uint8_t *d0_data = out->data[plane] + offset;
-        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset;
-        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset;
+        uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
 
         if (mirror) {
             d0_data += s->size - 1;
@@ -869,60 +1198,233 @@ static void achroma(WaveformContext *s, AVFrame *in, AVFrame *out,
 
         for (y = 0; y < src_h; y++) {
             for (x = 0; x < src_w; x++) {
-                const int c1 = c1_data[x] - 128;
-                const int c2 = c2_data[x] - 128;
+                const int c0 = c0_data[x >> c0_shift_w] + 128;
+                const int c1 = c1_data[x >> c1_shift_w] - 128;
+                const int c2 = c2_data[x >> c2_shift_w] - 128;
                 uint8_t *target;
 
                 if (mirror) {
-                    target = d1_data - (128 + c1);
+                    target = d0_data - c0;
+                    update(target, max, intensity);
+                    target = d1_data - (c0 + c1);
                     update(target, max, intensity);
-                    target = d2_data - (128 + c2);
+                    target = d2_data - (c0 + c2);
                     update(target, max, intensity);
                 } else {
-                    target = d1_data + (128 + c1);
+                    target = d0_data + c0;
+                    update(target, max, intensity);
+                    target = d1_data + (c0 + c1);
                     update(target, max, intensity);
-                    target = d2_data + (128 + c2);
+                    target = d2_data + (c0 + c2);
                     update(target, max, intensity);
                 }
             }
 
-            c1_data += c1_linesize;
-            c2_data += c2_linesize;
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
+            d0_data += d0_linesize;
             d1_data += d1_linesize;
             d2_data += d2_linesize;
         }
     }
 
-    envelope(s, out, plane, (plane + 1) % s->ncomp);
-    envelope(s, out, plane, (plane + 2) % s->ncomp);
+    envelope(s, out, plane, (plane + 0) % s->ncomp, column ? offset_x : offset_y);
+    envelope(s, out, plane, (plane + 1) % s->ncomp, column ? offset_x : offset_y);
+    envelope(s, out, plane, (plane + 2) % s->ncomp, column ? offset_x : offset_y);
 }
 
-static void color16(WaveformContext *s, AVFrame *in, AVFrame *out,
-                    int component, int intensity, int offset, int column)
+static av_always_inline void chroma16(WaveformContext *s,
+                                      AVFrame *in, AVFrame *out,
+                                      int component, int intensity,
+                                      int offset_y, int offset_x,
+                                      int column, int mirror)
 {
     const int plane = s->desc->comp[component].plane;
-    const int mirror = s->mirror;
+    const int c0_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
+    const int c1_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
+    const int dst_linesize = out->linesize[plane] / 2;
     const int limit = s->max - 1;
-    const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0];
-    const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp];
-    const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp];
-    const int c0_linesize = in->linesize[ plane + 0 ] / 2;
-    const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
-    const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
-    const int d0_linesize = out->linesize[ plane + 0 ] / 2;
+    const int max = limit - intensity;
+    const int mid = s->max / 2;
+    const int c0_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c1_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c1_shift_h = s->shift_h[(component + 2) % s->ncomp];
+    const int src_h = in->height;
+    const int src_w = in->width;
+    int x, y;
+
+    if (column) {
+        const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
+
+        for (x = 0; x < src_w; x++) {
+            const uint16_t *c0_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
+            const uint16_t *c1_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
+            uint16_t *dst_data = (uint16_t *)out->data[plane] + offset_y * dst_linesize + offset_x;
+            uint16_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
+            uint16_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
+            uint16_t *dst = dst_line;
+
+            for (y = 0; y < src_h; y++) {
+                const int sum = FFMIN(FFABS(c0_data[x >> c0_shift_w] - mid) + FFABS(c1_data[x >> c1_shift_w] - mid - 1), limit);
+                uint16_t *target;
+
+                target = dst + x + dst_signed_linesize * sum;
+                update16(target, max, intensity, limit);
+
+                if (!c0_shift_h || (y & c0_shift_h))
+                    c0_data += c0_linesize;
+                if (!c1_shift_h || (y & c1_shift_h))
+                    c1_data += c1_linesize;
+                dst_data += dst_linesize;
+            }
+        }
+    } else {
+        const uint16_t *c0_data = (uint16_t *)in->data[(plane + 1) % s->ncomp];
+        const uint16_t *c1_data = (uint16_t *)in->data[(plane + 2) % s->ncomp];
+        uint16_t *dst_data = (uint16_t *)out->data[plane] + offset_y * dst_linesize + offset_x;
+
+        if (mirror)
+            dst_data += s->size - 1;
+        for (y = 0; y < src_h; y++) {
+            for (x = 0; x < src_w; x++) {
+                const int sum = FFMIN(FFABS(c0_data[x >> c0_shift_w] - mid) + FFABS(c1_data[x >> c1_shift_w] - mid - 1), limit);
+                uint16_t *target;
+
+                if (mirror) {
+                    target = dst_data - sum;
+                    update16(target, max, intensity, limit);
+                } else {
+                    target = dst_data + sum;
+                    update16(target, max, intensity, limit);
+                }
+            }
+
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            dst_data += dst_linesize;
+        }
+    }
+
+    envelope16(s, out, plane, plane, column ? offset_x : offset_y);
+}
+
+static av_always_inline void chroma(WaveformContext *s,
+                                    AVFrame *in, AVFrame *out,
+                                    int component, int intensity,
+                                    int offset_y, int offset_x,
+                                    int column, int mirror)
+{
+    const int plane = s->desc->comp[component].plane;
+    const int c0_linesize = in->linesize[(plane + 1) % s->ncomp];
+    const int c1_linesize = in->linesize[(plane + 2) % s->ncomp];
+    const int dst_linesize = out->linesize[plane];
+    const int max = 255 - intensity;
+    const int c0_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c1_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c1_shift_h = s->shift_h[(component + 2) % s->ncomp];
+    const int src_h = in->height;
+    const int src_w = in->width;
+    int x, y;
+
+    if (column) {
+        const int dst_signed_linesize = dst_linesize * (mirror == 1 ? -1 : 1);
+
+        for (x = 0; x < src_w; x++) {
+            const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp];
+            const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp];
+            uint8_t *dst_data = out->data[plane] + offset_y * dst_linesize + offset_x;
+            uint8_t * const dst_bottom_line = dst_data + dst_linesize * (s->size - 1);
+            uint8_t * const dst_line = (mirror ? dst_bottom_line : dst_data);
+            uint8_t *dst = dst_line;
+
+            for (y = 0; y < src_h; y++) {
+                const int sum = FFABS(c0_data[x >> c0_shift_w] - 128) + FFABS(c1_data[x >> c1_shift_w] - 127);
+                uint8_t *target;
+
+                target = dst + x + dst_signed_linesize * sum;
+                update(target, max, intensity);
+
+                if (!c0_shift_h || (y & c0_shift_h))
+                    c0_data += c0_linesize;
+                if (!c1_shift_h || (y & c1_shift_h))
+                    c1_data += c1_linesize;
+                dst_data += dst_linesize;
+            }
+        }
+    } else {
+        const uint8_t *c0_data = in->data[(plane + 1) % s->ncomp];
+        const uint8_t *c1_data = in->data[(plane + 2) % s->ncomp];
+        uint8_t *dst_data = out->data[plane] + offset_y * dst_linesize + offset_x;
+
+        if (mirror)
+            dst_data += s->size - 1;
+        for (y = 0; y < src_h; y++) {
+            for (x = 0; x < src_w; x++) {
+                const int sum = FFABS(c0_data[x >> c0_shift_w] - 128) + FFABS(c1_data[x >> c1_shift_w] - 127);
+                uint8_t *target;
+
+                if (mirror) {
+                    target = dst_data - sum;
+                    update(target, max, intensity);
+                } else {
+                    target = dst_data + sum;
+                    update(target, max, intensity);
+                }
+            }
+
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            dst_data += dst_linesize;
+        }
+    }
+
+    envelope(s, out, plane, plane, column ? offset_x : offset_y);
+}
+
+static av_always_inline void color16(WaveformContext *s,
+                                     AVFrame *in, AVFrame *out,
+                                     int component, int intensity,
+                                     int offset_y, int offset_x,
+                                     int column, int mirror)
+{
+    const int plane = s->desc->comp[component].plane;
+    const int limit = s->max - 1;
+    const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0];
+    const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp];
+    const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp];
+    const int c0_linesize = in->linesize[ plane + 0 ] / 2;
+    const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
+    const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
+    const int d0_linesize = out->linesize[ plane + 0 ] / 2;
     const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
     const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2;
+    const int c0_shift_w = s->shift_w[ component + 0 ];
+    const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[ component + 0 ];
+    const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
     const int src_h = in->height;
     const int src_w = in->width;
     int x, y;
 
-    if (s->mode) {
+    if (column) {
         const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
         const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
         const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
-        uint16_t *d0_data = (uint16_t *)out->data[plane] + offset * d0_linesize;
-        uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
-        uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset * d2_linesize;
+        uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
         uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
         uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
         uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
@@ -932,26 +1434,29 @@ static void color16(WaveformContext *s, AVFrame *in, AVFrame *out,
 
         for (y = 0; y < src_h; y++) {
             for (x = 0; x < src_w; x++) {
-                const int c0 = FFMIN(c0_data[x], limit);
-                const int c1 = c1_data[x];
-                const int c2 = c2_data[x];
+                const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
+                const int c1 = c1_data[x >> c1_shift_w];
+                const int c2 = c2_data[x >> c2_shift_w];
 
                 *(d0 + d0_signed_linesize * c0 + x) = c0;
                 *(d1 + d1_signed_linesize * c0 + x) = c1;
                 *(d2 + d2_signed_linesize * c0 + x) = c2;
             }
 
-            c0_data += c0_linesize;
-            c1_data += c1_linesize;
-            c2_data += c2_linesize;
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
             d0_data += d0_linesize;
             d1_data += d1_linesize;
             d2_data += d2_linesize;
         }
     } else {
-        uint16_t *d0_data = (uint16_t *)out->data[plane] + offset;
-        uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset;
-        uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset;
+        uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
 
         if (mirror) {
             d0_data += s->size - 1;
@@ -961,9 +1466,9 @@ static void color16(WaveformContext *s, AVFrame *in, AVFrame *out,
 
         for (y = 0; y < src_h; y++) {
             for (x = 0; x < src_w; x++) {
-                const int c0 = FFMIN(c0_data[x], limit);
-                const int c1 = c1_data[x];
-                const int c2 = c2_data[x];
+                const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
+                const int c1 = c1_data[x >> c1_shift_w];
+                const int c2 = c2_data[x >> c2_shift_w];
 
                 if (mirror) {
                     *(d0_data - c0) = c0;
@@ -976,23 +1481,28 @@ static void color16(WaveformContext *s, AVFrame *in, AVFrame *out,
                 }
             }
 
-            c0_data += c0_linesize;
-            c1_data += c1_linesize;
-            c2_data += c2_linesize;
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
             d0_data += d0_linesize;
             d1_data += d1_linesize;
             d2_data += d2_linesize;
         }
     }
 
-    envelope16(s, out, plane, plane);
+    envelope16(s, out, plane, plane, column ? offset_x : offset_y);
 }
 
-static void color(WaveformContext *s, AVFrame *in, AVFrame *out,
-                  int component, int intensity, int offset, int column)
+static av_always_inline void color(WaveformContext *s,
+                                   AVFrame *in, AVFrame *out,
+                                   int component, int intensity,
+                                   int offset_y, int offset_x,
+                                   int column, int mirror)
 {
     const int plane = s->desc->comp[component].plane;
-    const int mirror = s->mirror;
     const uint8_t *c0_data = in->data[plane + 0];
     const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
     const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
@@ -1002,6 +1512,12 @@ static void color(WaveformContext *s, AVFrame *in, AVFrame *out,
     const int d0_linesize = out->linesize[ plane + 0 ];
     const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
     const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
+    const int c0_shift_w = s->shift_w[ component + 0 ];
+    const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[ component + 0 ];
+    const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
     const int src_h = in->height;
     const int src_w = in->width;
     int x, y;
@@ -1010,9 +1526,9 @@ static void color(WaveformContext *s, AVFrame *in, AVFrame *out,
         const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
         const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
         const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
-        uint8_t *d0_data = out->data[plane] + offset * d0_linesize;
-        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset * d1_linesize;
-        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset * d2_linesize;
+        uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
         uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
         uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
         uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
@@ -1022,26 +1538,29 @@ static void color(WaveformContext *s, AVFrame *in, AVFrame *out,
 
         for (y = 0; y < src_h; y++) {
             for (x = 0; x < src_w; x++) {
-                const int c0 = c0_data[x];
-                const int c1 = c1_data[x];
-                const int c2 = c2_data[x];
+                const int c0 = c0_data[x >> c0_shift_w];
+                const int c1 = c1_data[x >> c1_shift_w];
+                const int c2 = c2_data[x >> c2_shift_w];
 
                 *(d0 + d0_signed_linesize * c0 + x) = c0;
                 *(d1 + d1_signed_linesize * c0 + x) = c1;
                 *(d2 + d2_signed_linesize * c0 + x) = c2;
             }
 
-            c0_data += c0_linesize;
-            c1_data += c1_linesize;
-            c2_data += c2_linesize;
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
             d0_data += d0_linesize;
             d1_data += d1_linesize;
             d2_data += d2_linesize;
         }
     } else {
-        uint8_t *d0_data = out->data[plane] + offset;
-        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset;
-        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset;
+        uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
 
         if (mirror) {
             d0_data += s->size - 1;
@@ -1051,9 +1570,9 @@ static void color(WaveformContext *s, AVFrame *in, AVFrame *out,
 
         for (y = 0; y < src_h; y++) {
             for (x = 0; x < src_w; x++) {
-                const int c0 = c0_data[x];
-                const int c1 = c1_data[x];
-                const int c2 = c2_data[x];
+                const int c0 = c0_data[x >> c0_shift_w];
+                const int c1 = c1_data[x >> c1_shift_w];
+                const int c2 = c2_data[x >> c2_shift_w];
 
                 if (mirror) {
                     *(d0_data - c0) = c0;
@@ -1066,21 +1585,856 @@ static void color(WaveformContext *s, AVFrame *in, AVFrame *out,
                 }
             }
 
-            c0_data += c0_linesize;
-            c1_data += c1_linesize;
-            c2_data += c2_linesize;
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
             d0_data += d0_linesize;
             d1_data += d1_linesize;
             d2_data += d2_linesize;
         }
     }
 
-    envelope(s, out, plane, plane);
+    envelope(s, out, plane, plane, column ? offset_x : offset_y);
+}
+
+static av_always_inline void acolor16(WaveformContext *s,
+                                      AVFrame *in, AVFrame *out,
+                                      int component, int intensity,
+                                      int offset_y, int offset_x,
+                                      int column, int mirror)
+{
+    const int plane = s->desc->comp[component].plane;
+    const int limit = s->max - 1;
+    const int max = limit - intensity;
+    const uint16_t *c0_data = (const uint16_t *)in->data[plane + 0];
+    const uint16_t *c1_data = (const uint16_t *)in->data[(plane + 1) % s->ncomp];
+    const uint16_t *c2_data = (const uint16_t *)in->data[(plane + 2) % s->ncomp];
+    const int c0_linesize = in->linesize[ plane + 0 ] / 2;
+    const int c1_linesize = in->linesize[(plane + 1) % s->ncomp] / 2;
+    const int c2_linesize = in->linesize[(plane + 2) % s->ncomp] / 2;
+    const int d0_linesize = out->linesize[ plane + 0 ] / 2;
+    const int d1_linesize = out->linesize[(plane + 1) % s->ncomp] / 2;
+    const int d2_linesize = out->linesize[(plane + 2) % s->ncomp] / 2;
+    const int c0_shift_w = s->shift_w[ component + 0 ];
+    const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[ component + 0 ];
+    const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
+    const int src_h = in->height;
+    const int src_w = in->width;
+    int x, y;
+
+    if (s->mode) {
+        const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
+        const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
+        const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
+        uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
+        uint16_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
+        uint16_t * const d0 = (mirror ? d0_bottom_line : d0_data);
+        uint16_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
+        uint16_t * const d1 = (mirror ? d1_bottom_line : d1_data);
+        uint16_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
+        uint16_t * const d2 = (mirror ? d2_bottom_line : d2_data);
+
+        for (y = 0; y < src_h; y++) {
+            for (x = 0; x < src_w; x++) {
+                const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
+                const int c1 = c1_data[x >> c1_shift_w];
+                const int c2 = c2_data[x >> c2_shift_w];
+
+                update16(d0 + d0_signed_linesize * c0 + x, max, intensity, limit);
+                *(d1 + d1_signed_linesize * c0 + x) = c1;
+                *(d2 + d2_signed_linesize * c0 + x) = c2;
+            }
+
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
+            d0_data += d0_linesize;
+            d1_data += d1_linesize;
+            d2_data += d2_linesize;
+        }
+    } else {
+        uint16_t *d0_data = (uint16_t *)out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint16_t *d1_data = (uint16_t *)out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint16_t *d2_data = (uint16_t *)out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
+
+        if (mirror) {
+            d0_data += s->size - 1;
+            d1_data += s->size - 1;
+            d2_data += s->size - 1;
+        }
+
+        for (y = 0; y < src_h; y++) {
+            for (x = 0; x < src_w; x++) {
+                const int c0 = FFMIN(c0_data[x >> c0_shift_w], limit);
+                const int c1 = c1_data[x >> c1_shift_w];
+                const int c2 = c2_data[x >> c2_shift_w];
+
+                if (mirror) {
+                    update16(d0_data - c0, max, intensity, limit);
+                    *(d1_data - c0) = c1;
+                    *(d2_data - c0) = c2;
+                } else {
+                    update16(d0_data + c0, max, intensity, limit);
+                    *(d1_data + c0) = c1;
+                    *(d2_data + c0) = c2;
+                }
+            }
+
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
+            d0_data += d0_linesize;
+            d1_data += d1_linesize;
+            d2_data += d2_linesize;
+        }
+    }
+
+    envelope16(s, out, plane, plane, column ? offset_x : offset_y);
+}
+
+static av_always_inline void acolor(WaveformContext *s,
+                                    AVFrame *in, AVFrame *out,
+                                    int component, int intensity,
+                                    int offset_y, int offset_x,
+                                    int column, int mirror)
+{
+    const int plane = s->desc->comp[component].plane;
+    const uint8_t *c0_data = in->data[plane + 0];
+    const uint8_t *c1_data = in->data[(plane + 1) % s->ncomp];
+    const uint8_t *c2_data = in->data[(plane + 2) % s->ncomp];
+    const int c0_linesize = in->linesize[ plane + 0 ];
+    const int c1_linesize = in->linesize[(plane + 1) % s->ncomp];
+    const int c2_linesize = in->linesize[(plane + 2) % s->ncomp];
+    const int d0_linesize = out->linesize[ plane + 0 ];
+    const int d1_linesize = out->linesize[(plane + 1) % s->ncomp];
+    const int d2_linesize = out->linesize[(plane + 2) % s->ncomp];
+    const int c0_shift_w = s->shift_w[ component + 0 ];
+    const int c1_shift_w = s->shift_w[(component + 1) % s->ncomp];
+    const int c2_shift_w = s->shift_w[(component + 2) % s->ncomp];
+    const int c0_shift_h = s->shift_h[ component + 0 ];
+    const int c1_shift_h = s->shift_h[(component + 1) % s->ncomp];
+    const int c2_shift_h = s->shift_h[(component + 2) % s->ncomp];
+    const int max = 255 - intensity;
+    const int src_h = in->height;
+    const int src_w = in->width;
+    int x, y;
+
+    if (s->mode) {
+        const int d0_signed_linesize = d0_linesize * (mirror == 1 ? -1 : 1);
+        const int d1_signed_linesize = d1_linesize * (mirror == 1 ? -1 : 1);
+        const int d2_signed_linesize = d2_linesize * (mirror == 1 ? -1 : 1);
+        uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
+        uint8_t * const d0_bottom_line = d0_data + d0_linesize * (s->size - 1);
+        uint8_t * const d0 = (mirror ? d0_bottom_line : d0_data);
+        uint8_t * const d1_bottom_line = d1_data + d1_linesize * (s->size - 1);
+        uint8_t * const d1 = (mirror ? d1_bottom_line : d1_data);
+        uint8_t * const d2_bottom_line = d2_data + d2_linesize * (s->size - 1);
+        uint8_t * const d2 = (mirror ? d2_bottom_line : d2_data);
+
+        for (y = 0; y < src_h; y++) {
+            for (x = 0; x < src_w; x++) {
+                const int c0 = c0_data[x >> c0_shift_w];
+                const int c1 = c1_data[x >> c1_shift_w];
+                const int c2 = c2_data[x >> c2_shift_w];
+
+                update(d0 + d0_signed_linesize * c0 + x, max, intensity);
+                *(d1 + d1_signed_linesize * c0 + x) = c1;
+                *(d2 + d2_signed_linesize * c0 + x) = c2;
+            }
+
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
+            d0_data += d0_linesize;
+            d1_data += d1_linesize;
+            d2_data += d2_linesize;
+        }
+    } else {
+        uint8_t *d0_data = out->data[plane] + offset_y * d0_linesize + offset_x;
+        uint8_t *d1_data = out->data[(plane + 1) % s->ncomp] + offset_y * d1_linesize + offset_x;
+        uint8_t *d2_data = out->data[(plane + 2) % s->ncomp] + offset_y * d2_linesize + offset_x;
+
+        if (mirror) {
+            d0_data += s->size - 1;
+            d1_data += s->size - 1;
+            d2_data += s->size - 1;
+        }
+
+        for (y = 0; y < src_h; y++) {
+            for (x = 0; x < src_w; x++) {
+                const int c0 = c0_data[x >> c0_shift_w];
+                const int c1 = c1_data[x >> c1_shift_w];
+                const int c2 = c2_data[x >> c2_shift_w];
+
+                if (mirror) {
+                    update(d0_data - c0, max, intensity);
+                    *(d1_data - c0) = c1;
+                    *(d2_data - c0) = c2;
+                } else {
+                    update(d0_data + c0, max, intensity);
+                    *(d1_data + c0) = c1;
+                    *(d2_data + c0) = c2;
+                }
+            }
+
+            if (!c0_shift_h || (y & c0_shift_h))
+                c0_data += c0_linesize;
+            if (!c1_shift_h || (y & c1_shift_h))
+                c1_data += c1_linesize;
+            if (!c2_shift_h || (y & c2_shift_h))
+                c2_data += c2_linesize;
+            d0_data += d0_linesize;
+            d1_data += d1_linesize;
+            d2_data += d2_linesize;
+        }
+    }
+
+    envelope(s, out, plane, plane, column ? offset_x : offset_y);
 }
 
 static const uint8_t black_yuva_color[4] = { 0, 127, 127, 255 };
+static const uint8_t green_yuva_color[4] = { 255, 0, 0, 255 };
 static const uint8_t black_gbrp_color[4] = { 0, 0, 0, 255 };
 
+static const GraticuleLines aflat_digital8[] = {
+    { { {  "16",  16+128 }, {  "16",  16+128 }, {  "16",  16+128 }, {   "0",   0+128 } } },
+    { { { "128", 128+128 }, { "128", 128+128 }, { "128", 128+128 }, { "128", 128+128 } } },
+    { { { "235", 235+128 }, { "240", 240+128 }, { "240", 240+128 }, { "255", 255+128 } } },
+};
+
+static const GraticuleLines aflat_digital9[] = {
+    { { {  "32",  32+256 }, {  "32",  32+256 }, {  "32",  32+256 }, {   "0",   0+256 } } },
+    { { { "256", 256+256 }, { "256", 256+256 }, { "256", 256+256 }, { "256", 256+256 } } },
+    { { { "470", 470+256 }, { "480", 480+256 }, { "480", 480+256 }, { "511", 511+256 } } },
+};
+
+static const GraticuleLines aflat_digital10[] = {
+    { { {  "64",  64+512 }, {  "64",  64+512 }, {  "64",  64+512 }, {    "0",    0+512 } } },
+    { { { "512", 512+512 }, { "512", 512+512 }, { "512", 512+512 }, {  "512",  512+512 } } },
+    { { { "940", 940+512 }, { "960", 960+512 }, { "960", 960+512 }, { "1023", 1023+512 } } },
+};
+
+static const GraticuleLines aflat_digital12[] = {
+    { { {  "256",  256+2048 }, {  "256",  256+2048 }, {  "256",  256+2048 }, {    "0",    0+2048 } } },
+    { { { "2048", 2048+2048 }, { "2048", 2048+2048 }, { "2048", 2048+2048 }, { "2048", 2048+2048 } } },
+    { { { "3760", 3760+2048 }, { "3840", 3840+2048 }, { "3840", 3840+2048 }, { "4095", 4095+2048 } } },
+};
+
+static const GraticuleLines aflat_millivolts8[] = {
+    { { {   "0",  16+128 }, {   "0",  16+128 }, {   "0",  16+128 }, {   "0",   0+128 } } },
+    { { { "175",  71+128 }, { "175",  72+128 }, { "175",  72+128 }, { "175",  64+128 } } },
+    { { { "350", 126+128 }, { "350", 128+128 }, { "350", 128+128 }, { "350", 128+128 } } },
+    { { { "525", 180+128 }, { "525", 184+128 }, { "525", 184+128 }, { "525", 192+128 } } },
+    { { { "700", 235+128 }, { "700", 240+128 }, { "700", 240+128 }, { "700", 255+128 } } },
+};
+
+static const GraticuleLines aflat_millivolts9[] = {
+    { { {   "0",  32+256 }, {   "0",  32+256 }, {   "0",  32+256 }, {   "0",   0+256 } } },
+    { { { "175", 142+256 }, { "175", 144+256 }, { "175", 144+256 }, { "175", 128+256 } } },
+    { { { "350", 251+256 }, { "350", 256+256 }, { "350", 256+256 }, { "350", 256+256 } } },
+    { { { "525", 361+256 }, { "525", 368+256 }, { "525", 368+256 }, { "525", 384+256 } } },
+    { { { "700", 470+256 }, { "700", 480+256 }, { "700", 480+256 }, { "700", 511+256 } } },
+};
+
+static const GraticuleLines aflat_millivolts10[] = {
+    { { {   "0",  64+512 }, {   "0",  64+512 }, {   "0",  64+512 }, {   "0",    0+512 } } },
+    { { { "175", 283+512 }, { "175", 288+512 }, { "175", 288+512 }, { "175",  256+512 } } },
+    { { { "350", 502+512 }, { "350", 512+512 }, { "350", 512+512 }, { "350",  512+512 } } },
+    { { { "525", 721+512 }, { "525", 736+512 }, { "525", 736+512 }, { "525",  768+512 } } },
+    { { { "700", 940+512 }, { "700", 960+512 }, { "700", 960+512 }, { "700", 1023+512 } } },
+};
+
+static const GraticuleLines aflat_millivolts12[] = {
+    { { {   "0",  256+2048 }, {   "0",  256+2048 }, {   "0",  256+2048 }, {   "0",    0+2048 } } },
+    { { { "175", 1132+2048 }, { "175", 1152+2048 }, { "175", 1152+2048 }, { "175", 1024+2048 } } },
+    { { { "350", 2008+2048 }, { "350", 2048+2048 }, { "350", 2048+2048 }, { "350", 2048+2048 } } },
+    { { { "525", 2884+2048 }, { "525", 2944+2048 }, { "525", 2944+2048 }, { "525", 3072+2048 } } },
+    { { { "700", 3760+2048 }, { "700", 3840+2048 }, { "700", 3840+2048 }, { "700", 4095+2048 } } },
+};
+
+static const GraticuleLines aflat_ire8[] = {
+    { { { "-25", -39+128 }, { "-25", -40+128 }, { "-25", -40+128 }, { "-25", -64+128 } } },
+    { { {   "0",  16+128 }, {   "0",  16+128 }, {   "0",  16+128 }, {   "0",   0+128 } } },
+    { { {  "25",  71+128 }, {  "25",  72+128 }, {  "25",  72+128 }, {  "25",  64+128 } } },
+    { { {  "50", 126+128 }, {  "50", 128+128 }, {  "50", 128+128 }, {  "50", 128+128 } } },
+    { { {  "75", 180+128 }, {  "75", 184+128 }, {  "75", 184+128 }, {  "75", 192+128 } } },
+    { { { "100", 235+128 }, { "100", 240+128 }, { "100", 240+128 }, { "100", 256+128 } } },
+    { { { "125", 290+128 }, { "125", 296+128 }, { "125", 296+128 }, { "125", 320+128 } } },
+};
+
+static const GraticuleLines aflat_ire9[] = {
+    { { { "-25", -78+256 }, { "-25", -80+256 }, { "-25", -80+256 }, { "-25",-128+256 } } },
+    { { {   "0",  32+256 }, {   "0",  32+256 }, {   "0",  32+256 }, {   "0",   0+256 } } },
+    { { {  "25", 142+256 }, {  "25", 144+256 }, {  "25", 144+256 }, {  "25", 128+256 } } },
+    { { {  "50", 251+256 }, {  "50", 256+256 }, {  "50", 256+256 }, {  "50", 256+256 } } },
+    { { {  "75", 361+256 }, {  "75", 368+256 }, {  "75", 368+256 }, {  "75", 384+256 } } },
+    { { { "100", 470+256 }, { "100", 480+256 }, { "100", 480+256 }, { "100", 512+256 } } },
+    { { { "125", 580+256 }, { "125", 592+256 }, { "125", 592+256 }, { "125", 640+256 } } },
+};
+
+static const GraticuleLines aflat_ire10[] = {
+    { { { "-25",-156+512 }, { "-25",-160+512 }, { "-25",-160+512 }, { "-25", -256+512 } } },
+    { { {   "0",  64+512 }, {   "0",  64+512 }, {  "0",   64+512 }, {   "0",    0+512 } } },
+    { { {  "25", 283+512 }, {  "25", 288+512 }, {  "25", 288+512 }, {  "25",  256+512 } } },
+    { { {  "50", 502+512 }, {  "50", 512+512 }, {  "50", 512+512 }, {  "50",  512+512 } } },
+    { { {  "75", 721+512 }, {  "75", 736+512 }, {  "75", 736+512 }, {  "75",  768+512 } } },
+    { { { "100", 940+512 }, { "100", 960+512 }, { "100", 960+512 }, { "100", 1024+512 } } },
+    { { { "125",1160+512 }, { "125",1184+512 }, { "125",1184+512 }, { "125", 1280+512 } } },
+};
+
+static const GraticuleLines aflat_ire12[] = {
+    { { { "-25", -624+2048 }, { "-25", -640+2048 }, { "-25", -640+2048 }, { "-25",-1024+2048 } } },
+    { { {   "0",  256+2048 }, {   "0",  256+2048 }, {   "0",  256+2048 }, {   "0",    0+2048 } } },
+    { { {  "25", 1132+2048 }, {  "25", 1152+2048 }, {  "25", 1152+2048 }, {  "25", 1024+2048 } } },
+    { { {  "50", 2008+2048 }, {  "50", 2048+2048 }, {  "50", 2048+2048 }, {  "50", 2048+2048 } } },
+    { { {  "75", 2884+2048 }, {  "75", 2944+2048 }, {  "75", 2944+2048 }, {  "75", 3072+2048 } } },
+    { { { "100", 3760+2048 }, { "100", 3840+2048 }, { "100", 3840+2048 }, { "100", 4096+2048 } } },
+    { { { "125", 4640+2048 }, { "125", 4736+2048 }, { "125", 4736+2048 }, { "125", 5120+2048 } } },
+};
+
+static const GraticuleLines flat_digital8[] = {
+    { { {  "16",  16+256 }, {  "16",  16+256 }, {  "16",  16+256 }, {   "0",   0+256 } } },
+    { { { "128", 128+256 }, { "128", 128+256 }, { "128", 128+256 }, { "128", 128+256 } } },
+    { { { "235", 235+256 }, { "240", 240+256 }, { "240", 240+256 }, { "255", 255+256 } } },
+};
+
+static const GraticuleLines flat_digital9[] = {
+    { { {  "32",  32+512 }, {  "32",  32+512 }, {  "32",  32+512 }, {   "0",   0+512 } } },
+    { { { "256", 256+512 }, { "256", 256+512 }, { "256", 256+512 }, { "256", 256+512 } } },
+    { { { "470", 470+512 }, { "480", 480+512 }, { "480", 480+512 }, { "511", 511+512 } } },
+};
+
+static const GraticuleLines flat_digital10[] = {
+    { { {  "64",  64+1024 }, {  "64",  64+1024 }, {  "64",  64+1024 }, {    "0",    0+1024 } } },
+    { { { "512", 512+1024 }, { "512", 512+1024 }, { "512", 512+1024 }, {  "512",  512+1024 } } },
+    { { { "940", 940+1024 }, { "960", 960+1024 }, { "960", 960+1024 }, { "1023", 1023+1024 } } },
+};
+
+static const GraticuleLines flat_digital12[] = {
+    { { {  "256",  256+4096 }, {  "256",  256+4096 }, {  "256",  256+4096 }, {    "0",    0+4096 } } },
+    { { { "2048", 2048+4096 }, { "2048", 2048+4096 }, { "2048", 2048+4096 }, { "2048", 2048+4096 } } },
+    { { { "3760", 3760+4096 }, { "3840", 3840+4096 }, { "3840", 3840+4096 }, { "4095", 4095+4096 } } },
+};
+
+static const GraticuleLines flat_millivolts8[] = {
+    { { {   "0",  16+256 }, {   "0",  16+256 }, {   "0",  16+256 }, {   "0",   0+256 } } },
+    { { { "175",  71+256 }, { "175",  72+256 }, { "175",  72+256 }, { "175",  64+256 } } },
+    { { { "350", 126+256 }, { "350", 128+256 }, { "350", 128+256 }, { "350", 128+256 } } },
+    { { { "525", 180+256 }, { "525", 184+256 }, { "525", 184+256 }, { "525", 192+256 } } },
+    { { { "700", 235+256 }, { "700", 240+256 }, { "700", 240+256 }, { "700", 255+256 } } },
+};
+
+static const GraticuleLines flat_millivolts9[] = {
+    { { {   "0",  32+512 }, {   "0",  32+512 }, {   "0",  32+512 }, {   "0",   0+512 } } },
+    { { { "175", 142+512 }, { "175", 144+512 }, { "175", 144+512 }, { "175", 128+512 } } },
+    { { { "350", 251+512 }, { "350", 256+512 }, { "350", 256+512 }, { "350", 256+512 } } },
+    { { { "525", 361+512 }, { "525", 368+512 }, { "525", 368+512 }, { "525", 384+512 } } },
+    { { { "700", 470+512 }, { "700", 480+512 }, { "700", 480+512 }, { "700", 511+512 } } },
+};
+
+static const GraticuleLines flat_millivolts10[] = {
+    { { {   "0",  64+1024 }, {   "0",  64+1024 }, {   "0",  64+1024 }, {   "0",    0+1024 } } },
+    { { { "175", 283+1024 }, { "175", 288+1024 }, { "175", 288+1024 }, { "175",  256+1024 } } },
+    { { { "350", 502+1024 }, { "350", 512+1024 }, { "350", 512+1024 }, { "350",  512+1024 } } },
+    { { { "525", 721+1024 }, { "525", 736+1024 }, { "525", 736+1024 }, { "525",  768+1024 } } },
+    { { { "700", 940+1024 }, { "700", 960+1024 }, { "700", 960+1024 }, { "700", 1023+1024 } } },
+};
+
+static const GraticuleLines flat_millivolts12[] = {
+    { { {   "0",  256+4096 }, {   "0",  256+4096 }, {   "0",  256+4096 }, {   "0",    0+4096 } } },
+    { { { "175", 1132+4096 }, { "175", 1152+4096 }, { "175", 1152+4096 }, { "175", 1024+4096 } } },
+    { { { "350", 2008+4096 }, { "350", 2048+4096 }, { "350", 2048+4096 }, { "350", 2048+4096 } } },
+    { { { "525", 2884+4096 }, { "525", 2944+4096 }, { "525", 2944+4096 }, { "525", 3072+4096 } } },
+    { { { "700", 3760+4096 }, { "700", 3840+4096 }, { "700", 3840+4096 }, { "700", 4095+4096 } } },
+};
+
+static const GraticuleLines flat_ire8[] = {
+    { { { "-25", -39+256 }, { "-25", -40+256 }, { "-25", -40+256 }, { "-25", -64+256 } } },
+    { { {   "0",  16+256 }, {   "0",  16+256 }, {   "0",  16+256 }, {   "0",   0+256 } } },
+    { { {  "25",  71+256 }, {  "25",  72+256 }, {  "25",  72+256 }, {  "25",  64+256 } } },
+    { { {  "50", 126+256 }, {  "50", 128+256 }, {  "50", 128+256 }, {  "50", 128+256 } } },
+    { { {  "75", 180+256 }, {  "75", 184+256 }, {  "75", 184+256 }, {  "75", 192+256 } } },
+    { { { "100", 235+256 }, { "100", 240+256 }, { "100", 240+256 }, { "100", 256+256 } } },
+    { { { "125", 290+256 }, { "125", 296+256 }, { "125", 296+256 }, { "125", 320+256 } } },
+};
+
+static const GraticuleLines flat_ire9[] = {
+    { { { "-25", -78+512 }, { "-25", -80+512 }, { "-25", -80+512 }, { "-25",-128+512 } } },
+    { { {   "0",  32+512 }, {   "0",  32+512 }, {   "0",  32+512 }, {   "0",   0+512 } } },
+    { { {  "25", 142+512 }, {  "25", 144+512 }, {  "25", 144+512 }, {  "25", 128+512 } } },
+    { { {  "50", 251+512 }, {  "50", 256+512 }, {  "50", 256+512 }, {  "50", 256+512 } } },
+    { { {  "75", 361+512 }, {  "75", 368+512 }, {  "75", 368+512 }, {  "75", 384+512 } } },
+    { { { "100", 470+512 }, { "100", 480+512 }, { "100", 480+512 }, { "100", 512+512 } } },
+    { { { "125", 580+512 }, { "125", 592+512 }, { "125", 592+512 }, { "125", 640+512 } } },
+};
+
+static const GraticuleLines flat_ire10[] = {
+    { { { "-25",-156+1024 }, { "-25",-160+1024 }, { "-25",-160+1024 }, { "-25", -256+1024 } } },
+    { { {   "0",  64+1024 }, {   "0",  64+1024 }, {  "0",   64+1024 }, {   "0",    0+1024 } } },
+    { { {  "25", 283+1024 }, {  "25", 288+1024 }, {  "25", 288+1024 }, {  "25",  256+1024 } } },
+    { { {  "50", 502+1024 }, {  "50", 512+1024 }, {  "50", 512+1024 }, {  "50",  512+1024 } } },
+    { { {  "75", 721+1024 }, {  "75", 736+1024 }, {  "75", 736+1024 }, {  "75",  768+1024 } } },
+    { { { "100", 940+1024 }, { "100", 960+1024 }, { "100", 960+1024 }, { "100", 1024+1024 } } },
+    { { { "125",1160+1024 }, { "125",1184+1024 }, { "125",1184+1024 }, { "125", 1280+1024 } } },
+};
+
+static const GraticuleLines flat_ire12[] = {
+    { { { "-25", -624+4096 }, { "-25", -640+4096 }, { "-25", -640+4096 }, { "-25",-1024+4096 } } },
+    { { {   "0",  256+4096 }, {   "0",  256+4096 }, {   "0",  256+4096 }, {   "0",    0+4096 } } },
+    { { {  "25", 1132+4096 }, {  "25", 1152+4096 }, {  "25", 1152+4096 }, {  "25", 1024+4096 } } },
+    { { {  "50", 2008+4096 }, {  "50", 2048+4096 }, {  "50", 2048+4096 }, {  "50", 2048+4096 } } },
+    { { {  "75", 2884+4096 }, {  "75", 2944+4096 }, {  "75", 2944+4096 }, {  "75", 3072+4096 } } },
+    { { { "100", 3760+4096 }, { "100", 3840+4096 }, { "100", 3840+4096 }, { "100", 4096+4096 } } },
+    { { { "125", 4640+4096 }, { "125", 4736+4096 }, { "125", 4736+4096 }, { "125", 5120+4096 } } },
+};
+
+static const GraticuleLines digital8[] = {
+    { { {  "16",  16 }, {  "16",  16 }, {  "16",  16 }, {   "0",   0 } } },
+    { { { "128", 128 }, { "128", 128 }, { "128", 128 }, { "128", 128 } } },
+    { { { "235", 235 }, { "240", 240 }, { "240", 240 }, { "255", 255 } } },
+};
+
+static const GraticuleLines digital9[] = {
+    { { {  "32",  32 }, {  "32",  32 }, {  "32",  32 }, {   "0",   0 } } },
+    { { { "256", 256 }, { "256", 256 }, { "256", 256 }, { "256", 256 } } },
+    { { { "470", 470 }, { "480", 480 }, { "480", 480 }, { "511", 511 } } },
+};
+
+static const GraticuleLines digital10[] = {
+    { { {  "64",  64 }, {  "64",  64 }, {  "64",  64 }, {    "0",    0 } } },
+    { { { "512", 512 }, { "512", 512 }, { "512", 512 }, {  "512",  512 } } },
+    { { { "940", 940 }, { "960", 960 }, { "960", 960 }, { "1023", 1023 } } },
+};
+
+static const GraticuleLines digital12[] = {
+    { { {  "256",  256 }, {  "256",  256 }, {  "256",  256 }, {    "0",    0 } } },
+    { { { "2048", 2048 }, { "2048", 2048 }, { "2048", 2048 }, { "2048", 2048 } } },
+    { { { "3760", 3760 }, { "3840", 3840 }, { "3840", 3840 }, { "4095", 4095 } } },
+};
+
+static const GraticuleLines millivolts8[] = {
+    { { {   "0",  16 }, {   "0",  16 }, {   "0",  16 }, {   "0",   0 } } },
+    { { { "175",  71 }, { "175",  72 }, { "175",  72 }, { "175",  64 } } },
+    { { { "350", 126 }, { "350", 128 }, { "350", 128 }, { "350", 128 } } },
+    { { { "525", 180 }, { "525", 184 }, { "525", 184 }, { "525", 192 } } },
+    { { { "700", 235 }, { "700", 240 }, { "700", 240 }, { "700", 255 } } },
+};
+
+static const GraticuleLines millivolts9[] = {
+    { { {   "0",  32 }, {   "0",  32 }, {   "0",  32 }, {   "0",   0 } } },
+    { { { "175", 142 }, { "175", 144 }, { "175", 144 }, { "175", 128 } } },
+    { { { "350", 251 }, { "350", 256 }, { "350", 256 }, { "350", 256 } } },
+    { { { "525", 361 }, { "525", 368 }, { "525", 368 }, { "525", 384 } } },
+    { { { "700", 470 }, { "700", 480 }, { "700", 480 }, { "700", 511 } } },
+};
+
+static const GraticuleLines millivolts10[] = {
+    { { {   "0",  64 }, {   "0",  64 }, {   "0",  64 }, {   "0",    0 } } },
+    { { { "175", 283 }, { "175", 288 }, { "175", 288 }, { "175",  256 } } },
+    { { { "350", 502 }, { "350", 512 }, { "350", 512 }, { "350",  512 } } },
+    { { { "525", 721 }, { "525", 736 }, { "525", 736 }, { "525",  768 } } },
+    { { { "700", 940 }, { "700", 960 }, { "700", 960 }, { "700", 1023 } } },
+};
+
+static const GraticuleLines millivolts12[] = {
+    { { {   "0",  256 }, {   "0",  256 }, {   "0",  256 }, {   "0",    0 } } },
+    { { { "175", 1132 }, { "175", 1152 }, { "175", 1152 }, { "175", 1024 } } },
+    { { { "350", 2008 }, { "350", 2048 }, { "350", 2048 }, { "350", 2048 } } },
+    { { { "525", 2884 }, { "525", 2944 }, { "525", 2944 }, { "525", 3072 } } },
+    { { { "700", 3760 }, { "700", 3840 }, { "700", 3840 }, { "700", 4095 } } },
+};
+
+static const GraticuleLines ire8[] = {
+    { { {   "0",  16 }, {   "0",  16 }, {   "0",  16 }, {   "0",   0 } } },
+    { { {  "25",  71 }, {  "25",  72 }, {  "25",  72 }, {  "25",  64 } } },
+    { { {  "50", 126 }, {  "50", 128 }, {  "50", 128 }, {  "50", 128 } } },
+    { { {  "75", 180 }, {  "75", 184 }, {  "75", 184 }, {  "75", 192 } } },
+    { { { "100", 235 }, { "100", 240 }, { "100", 240 }, { "100", 255 } } },
+};
+
+static const GraticuleLines ire9[] = {
+    { { {   "0",  32 }, {   "0",  32 }, {   "0",  32 }, {   "0",   0 } } },
+    { { {  "25", 142 }, {  "25", 144 }, {  "25", 144 }, {  "25", 128 } } },
+    { { {  "50", 251 }, {  "50", 256 }, {  "50", 256 }, {  "50", 256 } } },
+    { { {  "75", 361 }, {  "75", 368 }, {  "75", 368 }, {  "75", 384 } } },
+    { { { "100", 470 }, { "100", 480 }, { "100", 480 }, { "100", 511 } } },
+};
+
+static const GraticuleLines ire10[] = {
+    { { {   "0",  64 }, {   "0",  64 }, {  "0",   64 }, {   "0",    0 } } },
+    { { {  "25", 283 }, {  "25", 288 }, {  "25", 288 }, {  "25",  256 } } },
+    { { {  "50", 502 }, {  "50", 512 }, {  "50", 512 }, {  "50",  512 } } },
+    { { {  "75", 721 }, {  "75", 736 }, {  "75", 736 }, {  "75",  768 } } },
+    { { { "100", 940 }, { "100", 960 }, { "100", 960 }, { "100", 1023 } } },
+};
+
+static const GraticuleLines ire12[] = {
+    { { {   "0",  256 }, {   "0",  256 }, {   "0",  256 }, {   "0",    0 } } },
+    { { {  "25", 1132 }, {  "25", 1152 }, {  "25", 1152 }, {  "25", 1024 } } },
+    { { {  "50", 2008 }, {  "50", 2048 }, {  "50", 2048 }, {  "50", 2048 } } },
+    { { {  "75", 2884 }, {  "75", 2944 }, {  "75", 2944 }, {  "75", 3072 } } },
+    { { { "100", 3760 }, { "100", 3840 }, { "100", 3840 }, { "100", 4095 } } },
+};
+
+static const GraticuleLines chroma_digital8[] = {
+    { { {  "50",  50 }, {  "50",  50 }, {  "50",  50 }, {  "50",  50 } } },
+    { { { "100", 100 }, { "100", 100 }, { "100", 100 }, { "100", 100 } } },
+    { { { "150", 150 }, { "150", 150 }, { "150", 150 }, { "150", 150 } } },
+    { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } },
+    { { { "255", 255 }, { "255", 255 }, { "255", 255 }, { "255", 255 } } },
+};
+
+static const GraticuleLines chroma_digital9[] = {
+    { { { "100", 100 }, { "100", 100 }, { "100", 100 }, { "100", 100 } } },
+    { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } },
+    { { { "300", 300 }, { "300", 300 }, { "300", 300 }, { "300", 300 } } },
+    { { { "400", 400 }, { "400", 400 }, { "400", 400 }, { "400", 400 } } },
+    { { { "500", 500 }, { "500", 500 }, { "500", 500 }, { "500", 500 } } },
+};
+
+static const GraticuleLines chroma_digital10[] = {
+    { { { "200", 200 }, { "200", 200 }, { "200", 200 }, { "200", 200 } } },
+    { { { "400", 400 }, { "400", 400 }, { "400", 400 }, { "400", 400 } } },
+    { { { "600", 600 }, { "600", 600 }, { "600", 600 }, { "600", 600 } } },
+    { { { "800", 800 }, { "800", 800 }, { "800", 800 }, { "800", 800 } } },
+    { { {"1000",1000 }, {"1000",1000 }, {"1000",1000 }, {"1000",1000 } } },
+};
+
+static const GraticuleLines chroma_digital12[] = {
+    { { {  "800",  800 }, {  "800",  800 }, {  "800",  800 }, {  "800",  800 } } },
+    { { { "1600", 1600 }, { "1600", 1600 }, { "1600", 1600 }, { "1600", 1600 } } },
+    { { { "2400", 2400 }, { "2400", 2400 }, { "2400", 2400 }, { "2400", 2400 } } },
+    { { { "3200", 3200 }, { "3200", 3200 }, { "3200", 3200 }, { "3200", 3200 } } },
+    { { { "4000", 4000 }, { "4000", 4000 }, { "4000", 4000 }, { "4000", 4000 } } },
+};
+
+static void blend_vline(uint8_t *dst, int height, int linesize, float o1, float o2, int v, int step)
+{
+    int y;
+
+    for (y = 0; y < height; y += step) {
+        dst[0] = v * o1 + dst[0] * o2;
+
+        dst += linesize * step;
+    }
+}
+
+static void blend_vline16(uint16_t *dst, int height, int linesize, float o1, float o2, int v, int step)
+{
+    int y;
+
+    for (y = 0; y < height; y += step) {
+        dst[0] = v * o1 + dst[0] * o2;
+
+        dst += (linesize / 2) * step;
+    }
+}
+
+static void blend_hline(uint8_t *dst, int width, float o1, float o2, int v, int step)
+{
+    int x;
+
+    for (x = 0; x < width; x += step) {
+        dst[x] = v * o1 + dst[x] * o2;
+    }
+}
+
+static void blend_hline16(uint16_t *dst, int width, float o1, float o2, int v, int step)
+{
+    int x;
+
+    for (x = 0; x < width; x += step) {
+        dst[x] = v * o1 + dst[x] * o2;
+    }
+}
+
+static void draw_htext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
+{
+    const uint8_t *font;
+    int font_height;
+    int i, plane;
+
+    font = avpriv_cga_font,   font_height =  8;
+
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
+        for (i = 0; txt[i]; i++) {
+            int char_y, mask;
+            int v = color[plane];
+
+            uint8_t *p = out->data[plane] + y * out->linesize[plane] + (x + i * 8);
+            for (char_y = 0; char_y < font_height; char_y++) {
+                for (mask = 0x80; mask; mask >>= 1) {
+                    if (font[txt[i] * font_height + char_y] & mask)
+                        p[0] = p[0] * o2 + v * o1;
+                    p++;
+                }
+                p += out->linesize[plane] - 8;
+            }
+        }
+    }
+}
+
+static void draw_htext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
+{
+    const uint8_t *font;
+    int font_height;
+    int i, plane;
+
+    font = avpriv_cga_font,   font_height =  8;
+
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
+        for (i = 0; txt[i]; i++) {
+            int char_y, mask;
+            int v = color[plane] * mult;
+
+            uint16_t *p = (uint16_t *)(out->data[plane] + y * out->linesize[plane]) + (x + i * 8);
+            for (char_y = 0; char_y < font_height; char_y++) {
+                for (mask = 0x80; mask; mask >>= 1) {
+                    if (font[txt[i] * font_height + char_y] & mask)
+                        p[0] = p[0] * o2 + v * o1;
+                    p++;
+                }
+                p += out->linesize[plane] / 2 - 8;
+            }
+        }
+    }
+}
+
+static void draw_vtext(AVFrame *out, int x, int y, float o1, float o2, const char *txt, const uint8_t color[4])
+{
+    const uint8_t *font;
+    int font_height;
+    int i, plane;
+
+    font = avpriv_cga_font,   font_height =  8;
+
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
+        for (i = 0; txt[i]; i++) {
+            int char_y, mask;
+            int v = color[plane];
+
+            for (char_y = font_height - 1; char_y >= 0; char_y--) {
+                uint8_t *p = out->data[plane] + (y + i * 10) * out->linesize[plane] + x;
+                for (mask = 0x80; mask; mask >>= 1) {
+                    if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
+                        p[char_y] = p[char_y] * o2 + v * o1;
+                    p += out->linesize[plane];
+                }
+            }
+        }
+    }
+}
+
+static void draw_vtext16(AVFrame *out, int x, int y, int mult, float o1, float o2, const char *txt, const uint8_t color[4])
+{
+    const uint8_t *font;
+    int font_height;
+    int i, plane;
+
+    font = avpriv_cga_font,   font_height =  8;
+
+    for (plane = 0; plane < 4 && out->data[plane]; plane++) {
+        for (i = 0; txt[i]; i++) {
+            int char_y, mask;
+            int v = color[plane] * mult;
+
+            for (char_y = 0; char_y < font_height; char_y++) {
+                uint16_t *p = (uint16_t *)(out->data[plane] + (y + i * 10) * out->linesize[plane]) + x;
+                for (mask = 0x80; mask; mask >>= 1) {
+                    if (font[txt[i] * font_height + font_height - 1 - char_y] & mask)
+                        p[char_y] = p[char_y] * o2 + v * o1;
+                    p += out->linesize[plane] / 2;
+                }
+            }
+        }
+    }
+}
+
+static void graticule_none(WaveformContext *s, AVFrame *out)
+{
+}
+
+static void graticule_green_row(WaveformContext *s, AVFrame *out)
+{
+    const int step = (s->flags & 2) + 1;
+    const float o1 = s->opacity;
+    const float o2 = 1. - o1;
+    const int height = s->display == PARADE ? out->height / s->acomp : out->height;
+    int k = 0, c, p, l, offset_x = 0, offset_y = 0;
+
+    for (c = 0; c < s->ncomp; c++) {
+        if (!((1 << c) & s->pcomp) || (!s->display && k > 0))
+            continue;
+
+        k++;
+        for (p = 0; p < s->ncomp; p++) {
+            const int v = green_yuva_color[p];
+            for (l = 0; l < s->nb_glines; l++) {
+                const uint16_t pos = s->glines[l].line[c].pos;
+                int x = offset_x + (s->mirror ? s->size - 1 - pos : pos);
+                uint8_t *dst = out->data[p] + offset_y * out->linesize[p] + x;
+
+                blend_vline(dst, height, out->linesize[p], o1, o2, v, step);
+            }
+        }
+
+        for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
+            const char *name = s->glines[l].line[c].name;
+            const uint16_t pos = s->glines[l].line[c].pos;
+            int x = offset_x + (s->mirror ? s->size - 1 - pos : pos) - 10;
+
+            if (x < 0)
+                x = 4;
+
+            draw_vtext(out, x, offset_y + 2, o1, o2, name, green_yuva_color);
+        }
+
+        offset_x += s->size * (s->display == STACK);
+        offset_y += height * (s->display == PARADE);
+    }
+}
+
+static void graticule16_green_row(WaveformContext *s, AVFrame *out)
+{
+    const int step = (s->flags & 2) + 1;
+    const float o1 = s->opacity;
+    const float o2 = 1. - o1;
+    const int mult = s->size / 256;
+    const int height = s->display == PARADE ? out->height / s->acomp : out->height;
+    int k = 0, c, p, l, offset_x = 0, offset_y = 0;
+
+    for (c = 0; c < s->ncomp; c++) {
+        if (!((1 << c) & s->pcomp) || (!s->display && k > 0))
+            continue;
+
+        k++;
+        for (p = 0; p < s->ncomp; p++) {
+            const int v = green_yuva_color[p] * mult;
+            for (l = 0; l < s->nb_glines ; l++) {
+                const uint16_t pos = s->glines[l].line[c].pos;
+                int x = offset_x + (s->mirror ? s->size - 1 - pos : pos);
+                uint16_t *dst = (uint16_t *)(out->data[p] + offset_y * out->linesize[p]) + x;
+
+                blend_vline16(dst, height, out->linesize[p], o1, o2, v, step);
+            }
+        }
+
+        for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
+            const char *name = s->glines[l].line[c].name;
+            const uint16_t pos = s->glines[l].line[c].pos;
+            int x = offset_x + (s->mirror ? s->size - 1 - pos : pos) - 10;
+
+            if (x < 0)
+                x = 4;
+
+            draw_vtext16(out, x, offset_y + 2, mult, o1, o2, name, green_yuva_color);
+        }
+
+        offset_x += s->size * (s->display == STACK);
+        offset_y += height * (s->display == PARADE);
+    }
+}
+
+static void graticule_green_column(WaveformContext *s, AVFrame *out)
+{
+    const int step = (s->flags & 2) + 1;
+    const float o1 = s->opacity;
+    const float o2 = 1. - o1;
+    const int width = s->display == PARADE ? out->width / s->acomp : out->width;
+    int k = 0, c, p, l, offset_y = 0, offset_x = 0;
+
+    for (c = 0; c < s->ncomp; c++) {
+        if ((!((1 << c) & s->pcomp) || (!s->display && k > 0)))
+            continue;
+
+        k++;
+        for (p = 0; p < s->ncomp; p++) {
+            const int v = green_yuva_color[p];
+            for (l = 0; l < s->nb_glines ; l++) {
+                const uint16_t pos = s->glines[l].line[c].pos;
+                int y = offset_y + (s->mirror ? s->size - 1 - pos : pos);
+                uint8_t *dst = out->data[p] + y * out->linesize[p] + offset_x;
+
+                blend_hline(dst, width, o1, o2, v, step);
+            }
+        }
+
+        for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
+            const char *name = s->glines[l].line[c].name;
+            const uint16_t pos = s->glines[l].line[c].pos;
+            int y = offset_y + (s->mirror ? s->size - 1 - pos : pos) - 10;
+
+            if (y < 0)
+                y = 4;
+
+            draw_htext(out, 2 + offset_x, y, o1, o2, name, green_yuva_color);
+        }
+
+        offset_y += s->size * (s->display == STACK);
+        offset_x += width * (s->display == PARADE);
+    }
+}
+
+static void graticule16_green_column(WaveformContext *s, AVFrame *out)
+{
+    const int step = (s->flags & 2) + 1;
+    const float o1 = s->opacity;
+    const float o2 = 1. - o1;
+    const int mult = s->size / 256;
+    const int width = s->display == PARADE ? out->width / s->acomp : out->width;
+    int k = 0, c, p, l, offset_x = 0, offset_y = 0;
+
+    for (c = 0; c < s->ncomp; c++) {
+        if ((!((1 << c) & s->pcomp) || (!s->display && k > 0)))
+            continue;
+
+        k++;
+        for (p = 0; p < s->ncomp; p++) {
+            const int v = green_yuva_color[p] * mult;
+            for (l = 0; l < s->nb_glines ; l++) {
+                const uint16_t pos = s->glines[l].line[c].pos;
+                int y = offset_y + (s->mirror ? s->size - 1 - pos : pos);
+                uint16_t *dst = (uint16_t *)(out->data[p] + y * out->linesize[p]) + offset_x;
+
+                blend_hline16(dst, width, o1, o2, v, step);
+            }
+        }
+
+        for (l = 0; l < s->nb_glines && (s->flags & 1); l++) {
+            const char *name = s->glines[l].line[c].name;
+            const uint16_t pos = s->glines[l].line[c].pos;
+            int y = offset_y + (s->mirror ? s->size - 1 - pos: pos) - 10;
+
+            if (y < 0)
+                y = 4;
+
+            draw_htext16(out, 2 + offset_x, y, mult, o1, o2, name, green_yuva_color);
+        }
+
+        offset_y += s->size * (s->display == STACK);
+        offset_x += width * (s->display == PARADE);
+    }
+}
+
 static int config_input(AVFilterLink *inlink)
 {
     AVFilterContext *ctx = inlink->dst;
@@ -1092,25 +2446,200 @@ static int config_input(AVFilterLink *inlink)
     s->max = 1 << s->bits;
     s->intensity = s->fintensity * (s->max - 1);
 
+    s->shift_w[0] = s->shift_w[3] = 0;
+    s->shift_h[0] = s->shift_h[3] = 0;
+    s->shift_w[1] = s->shift_w[2] = s->desc->log2_chroma_w;
+    s->shift_h[1] = s->shift_h[2] = s->desc->log2_chroma_h;
+
+    s->graticulef = graticule_none;
+
+    switch (s->filter) {
+    case AFLAT: s->size = 256 * 2; break;
+    case FLAT:  s->size = 256 * 3; break;
+    default:    s->size = 256;     break;
+    }
+
+    switch (s->filter | ((s->bits > 8) << 4) |
+            (s->mode << 8) | (s->mirror << 12)) {
+    case 0x1100: s->waveform = lowpass_column_mirror; break;
+    case 0x1000: s->waveform = lowpass_row_mirror;    break;
+    case 0x0100: s->waveform = lowpass_column;        break;
+    case 0x0000: s->waveform = lowpass_row;           break;
+    case 0x1110: s->waveform = lowpass16_column_mirror; break;
+    case 0x1010: s->waveform = lowpass16_row_mirror;    break;
+    case 0x0110: s->waveform = lowpass16_column;        break;
+    case 0x0010: s->waveform = lowpass16_row;           break;
+    case 0x1101:
+    case 0x1001:
+    case 0x0101:
+    case 0x0001: s->waveform = flat;      break;
+    case 0x1111:
+    case 0x1011:
+    case 0x0111:
+    case 0x0011: s->waveform = flat16;    break;
+    case 0x1102:
+    case 0x1002:
+    case 0x0102:
+    case 0x0002: s->waveform = aflat;     break;
+    case 0x1112:
+    case 0x1012:
+    case 0x0112:
+    case 0x0012: s->waveform = aflat16;   break;
+    case 0x1103:
+    case 0x1003:
+    case 0x0103:
+    case 0x0003: s->waveform = chroma;    break;
+    case 0x1113:
+    case 0x1013:
+    case 0x0113:
+    case 0x0013: s->waveform = chroma16;  break;
+    case 0x1104:
+    case 0x1004:
+    case 0x0104:
+    case 0x0004: s->waveform = color;     break;
+    case 0x1114:
+    case 0x1014:
+    case 0x0114:
+    case 0x0014: s->waveform = color16;   break;
+    case 0x1105:
+    case 0x1005:
+    case 0x0105:
+    case 0x0005: s->waveform = acolor;    break;
+    case 0x1115:
+    case 0x1015:
+    case 0x0115:
+    case 0x0015: s->waveform = acolor16;  break;
+    }
+
     switch (s->filter) {
     case LOWPASS:
-            s->size = 256;
-            s->waveform = s->bits > 8 ? lowpass16 : lowpass; break;
-    case FLAT:
-            s->size = 256 * 3;
-            s->waveform = flat;    break;
-    case AFLAT:
-            s->size = 256 * 2;
-            s->waveform = aflat;   break;
+    case COLOR:
+    case ACOLOR:
     case CHROMA:
-            s->size = 256 * 2;
-            s->waveform = chroma;  break;
-    case ACHROMA:
-            s->size = 256;
-            s->waveform = achroma; break;
+    case AFLAT:
+    case FLAT:
+        if (s->graticule && s->mode == 1)
+            s->graticulef = s->bits > 8 ? graticule16_green_column : graticule_green_column;
+        else if (s->graticule && s->mode == 0)
+            s->graticulef = s->bits > 8 ? graticule16_green_row : graticule_green_row;
+        break;
+    }
+
+    switch (s->filter) {
     case COLOR:
-            s->size = 256;
-            s->waveform = s->bits > 8 ?   color16 :   color; break;
+    case ACOLOR:
+    case LOWPASS:
+        switch (s->scale) {
+        case DIGITAL:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)digital8;  s->nb_glines = FF_ARRAY_ELEMS(digital8);  break;
+            case  9: s->glines = (GraticuleLines *)digital9;  s->nb_glines = FF_ARRAY_ELEMS(digital9);  break;
+            case 10: s->glines = (GraticuleLines *)digital10; s->nb_glines = FF_ARRAY_ELEMS(digital10); break;
+            case 12: s->glines = (GraticuleLines *)digital12; s->nb_glines = FF_ARRAY_ELEMS(digital12); break;
+            }
+            break;
+        case MILLIVOLTS:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)millivolts8;  s->nb_glines = FF_ARRAY_ELEMS(millivolts8);  break;
+            case  9: s->glines = (GraticuleLines *)millivolts9;  s->nb_glines = FF_ARRAY_ELEMS(millivolts9);  break;
+            case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break;
+            case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break;
+            }
+            break;
+        case IRE:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)ire8;  s->nb_glines = FF_ARRAY_ELEMS(ire8);  break;
+            case  9: s->glines = (GraticuleLines *)ire9;  s->nb_glines = FF_ARRAY_ELEMS(ire9);  break;
+            case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break;
+            case 12: s->glines = (GraticuleLines *)ire12; s->nb_glines = FF_ARRAY_ELEMS(ire12); break;
+            }
+            break;
+        }
+        break;
+    case CHROMA:
+        switch (s->scale) {
+        case DIGITAL:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)chroma_digital8;  s->nb_glines = FF_ARRAY_ELEMS(chroma_digital8);  break;
+            case  9: s->glines = (GraticuleLines *)chroma_digital9;  s->nb_glines = FF_ARRAY_ELEMS(chroma_digital9);  break;
+            case 10: s->glines = (GraticuleLines *)chroma_digital10; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital10); break;
+            case 12: s->glines = (GraticuleLines *)chroma_digital12; s->nb_glines = FF_ARRAY_ELEMS(chroma_digital12); break;
+            }
+            break;
+        case MILLIVOLTS:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)millivolts8;  s->nb_glines = FF_ARRAY_ELEMS(millivolts8);  break;
+            case  9: s->glines = (GraticuleLines *)millivolts9;  s->nb_glines = FF_ARRAY_ELEMS(millivolts9);  break;
+            case 10: s->glines = (GraticuleLines *)millivolts10; s->nb_glines = FF_ARRAY_ELEMS(millivolts10); break;
+            case 12: s->glines = (GraticuleLines *)millivolts12; s->nb_glines = FF_ARRAY_ELEMS(millivolts12); break;
+            }
+            break;
+        case IRE:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)ire8;  s->nb_glines = FF_ARRAY_ELEMS(ire8);  break;
+            case  9: s->glines = (GraticuleLines *)ire9;  s->nb_glines = FF_ARRAY_ELEMS(ire9);  break;
+            case 10: s->glines = (GraticuleLines *)ire10; s->nb_glines = FF_ARRAY_ELEMS(ire10); break;
+            case 12: s->glines = (GraticuleLines *)ire12; s->nb_glines = FF_ARRAY_ELEMS(ire12); break;
+            }
+            break;
+        }
+        break;
+    case AFLAT:
+        switch (s->scale) {
+        case DIGITAL:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)aflat_digital8;  s->nb_glines = FF_ARRAY_ELEMS(aflat_digital8);  break;
+            case  9: s->glines = (GraticuleLines *)aflat_digital9;  s->nb_glines = FF_ARRAY_ELEMS(aflat_digital9);  break;
+            case 10: s->glines = (GraticuleLines *)aflat_digital10; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital10); break;
+            case 12: s->glines = (GraticuleLines *)aflat_digital12; s->nb_glines = FF_ARRAY_ELEMS(aflat_digital12); break;
+            }
+            break;
+        case MILLIVOLTS:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)aflat_millivolts8;  s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts8);  break;
+            case  9: s->glines = (GraticuleLines *)aflat_millivolts9;  s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts9);  break;
+            case 10: s->glines = (GraticuleLines *)aflat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts10); break;
+            case 12: s->glines = (GraticuleLines *)aflat_millivolts12; s->nb_glines = FF_ARRAY_ELEMS(aflat_millivolts12); break;
+            }
+            break;
+        case IRE:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)aflat_ire8;  s->nb_glines = FF_ARRAY_ELEMS(aflat_ire8);  break;
+            case  9: s->glines = (GraticuleLines *)aflat_ire9;  s->nb_glines = FF_ARRAY_ELEMS(aflat_ire9);  break;
+            case 10: s->glines = (GraticuleLines *)aflat_ire10; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire10); break;
+            case 12: s->glines = (GraticuleLines *)aflat_ire12; s->nb_glines = FF_ARRAY_ELEMS(aflat_ire12); break;
+            }
+            break;
+        }
+        break;
+    case FLAT:
+        switch (s->scale) {
+        case DIGITAL:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)flat_digital8;  s->nb_glines = FF_ARRAY_ELEMS(flat_digital8);  break;
+            case  9: s->glines = (GraticuleLines *)flat_digital9;  s->nb_glines = FF_ARRAY_ELEMS(flat_digital9);  break;
+            case 10: s->glines = (GraticuleLines *)flat_digital10; s->nb_glines = FF_ARRAY_ELEMS(flat_digital10); break;
+            case 12: s->glines = (GraticuleLines *)flat_digital12; s->nb_glines = FF_ARRAY_ELEMS(flat_digital12); break;
+            }
+            break;
+        case MILLIVOLTS:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)flat_millivolts8;  s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts8);  break;
+            case  9: s->glines = (GraticuleLines *)flat_millivolts9;  s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts9);  break;
+            case 10: s->glines = (GraticuleLines *)flat_millivolts10; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts10); break;
+            case 12: s->glines = (GraticuleLines *)flat_millivolts12; s->nb_glines = FF_ARRAY_ELEMS(flat_millivolts12); break;
+            }
+            break;
+        case IRE:
+            switch (s->bits) {
+            case  8: s->glines = (GraticuleLines *)flat_ire8;  s->nb_glines = FF_ARRAY_ELEMS(flat_ire8);  break;
+            case  9: s->glines = (GraticuleLines *)flat_ire9;  s->nb_glines = FF_ARRAY_ELEMS(flat_ire9);  break;
+            case 10: s->glines = (GraticuleLines *)flat_ire10; s->nb_glines = FF_ARRAY_ELEMS(flat_ire10); break;
+            case 12: s->glines = (GraticuleLines *)flat_ire12; s->nb_glines = FF_ARRAY_ELEMS(flat_ire12); break;
+            }
+            break;
+        }
+        break;
     }
 
     s->size = s->size << (s->bits - 8);
@@ -1120,7 +2649,9 @@ static int config_input(AVFilterLink *inlink)
     case AV_PIX_FMT_GBRP:
     case AV_PIX_FMT_GBRP9:
     case AV_PIX_FMT_GBRP10:
+    case AV_PIX_FMT_GBRP12:
         s->bg_color = black_gbrp_color;
+        s->graticulef = graticule_none;
         break;
     default:
         s->bg_color = black_yuva_color;
@@ -1134,20 +2665,23 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     WaveformContext *s = ctx->priv;
-    int comp = 0, i, j = 0, k, p, size, shift;
+    int comp = 0, i, j = 0, k, p, size;
 
     for (i = 0; i < s->ncomp; i++) {
         if ((1 << i) & s->pcomp)
             comp++;
     }
+    s->acomp = comp;
 
     av_freep(&s->peak);
 
     if (s->mode) {
-        outlink->h = s->size * FFMAX(comp * s->display, 1);
+        outlink->h = s->size * FFMAX(comp * (s->display == STACK), 1);
+        outlink->w = inlink->w * FFMAX(comp * (s->display == PARADE), 1);
         size = inlink->w;
     } else {
-        outlink->w = s->size * FFMAX(comp * s->display, 1);
+        outlink->w = s->size * FFMAX(comp * (s->display == STACK), 1);
+        outlink->h = inlink->h * FFMAX(comp * (s->display == PARADE), 1);
         size = inlink->h;
     }
 
@@ -1155,26 +2689,21 @@ static int config_output(AVFilterLink *outlink)
     if (!s->peak)
         return AVERROR(ENOMEM);
 
-    for (p = 0; p < 4; p++) {
-        const int is_chroma = (p == 1 || p == 2);
-        const int shift_w = (is_chroma ? s->desc->log2_chroma_w : 0);
-        const int shift_h = (is_chroma ? s->desc->log2_chroma_h : 0);
+    for (p = 0; p < s->ncomp; p++) {
         const int plane = s->desc->comp[p].plane;
         int offset;
 
         if (!((1 << p) & s->pcomp))
             continue;
 
-        shift = s->mode ? shift_h : shift_w;
-
         for (k = 0; k < 4; k++) {
             s->emax[plane][k] = s->peak + size * (plane * 4 + k + 0);
             s->emin[plane][k] = s->peak + size * (plane * 4 + k + 16);
         }
 
-        offset = j++ * s->size * s->display;
-        s->estart[plane] = offset >> shift;
-        s->eend[plane]   = (offset + s->size - 1) >> shift;
+        offset = j++ * s->size * (s->display == STACK);
+        s->estart[plane] = offset;
+        s->eend[plane]   = (offset + s->size - 1);
         for (i = 0; i < size; i++) {
             for (k = 0; k < 4; k++) {
                 s->emax[plane][k][i] = s->estart[plane];
@@ -1202,22 +2731,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         return AVERROR(ENOMEM);
     }
     out->pts = in->pts;
+    av_frame_set_color_range(out, AVCOL_RANGE_JPEG);
 
     for (k = 0; k < s->ncomp; k++) {
-        const int is_chroma = (k == 1 || k == 2);
-        const int dst_h = AV_CEIL_RSHIFT(outlink->h, (is_chroma ? s->desc->log2_chroma_h : 0));
-        const int dst_w = AV_CEIL_RSHIFT(outlink->w, (is_chroma ? s->desc->log2_chroma_w : 0));
         if (s->bits <= 8) {
-            for (i = 0; i < dst_h ; i++)
+            for (i = 0; i < outlink->h ; i++)
                 memset(out->data[s->desc->comp[k].plane] +
                        i * out->linesize[s->desc->comp[k].plane],
-                       s->bg_color[k], dst_w);
+                       s->bg_color[k], outlink->w);
         } else {
-            const int mult = s->size / 256;
+            const int mult = s->max / 256;
             uint16_t *dst = (uint16_t *)out->data[s->desc->comp[k].plane];
 
-            for (i = 0; i < dst_h ; i++) {
-                for (j = 0; j < dst_w; j++)
+            for (i = 0; i < outlink->h ; i++) {
+                for (j = 0; j < outlink->w; j++)
                     dst[j] = s->bg_color[k] * mult;
                 dst += out->linesize[s->desc->comp[k].plane] / 2;
             }
@@ -1226,10 +2753,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 
     for (k = 0, i = 0; k < s->ncomp; k++) {
         if ((1 << k) & s->pcomp) {
-            const int offset = i++ * s->size * s->display;
-            s->waveform(s, in, out, k, s->intensity, offset, s->mode);
+            int offset_y;
+            int offset_x;
+
+            if (s->display == PARADE) {
+                offset_x = s->mode ? i++ * inlink->w : 0;
+                offset_y = s->mode ? 0 : i++ * inlink->h;
+            } else {
+                offset_y = s->mode ? i++ * s->size * !!s->display : 0;
+                offset_x = s->mode ? 0 : i++ * s->size * !!s->display;
+            }
+            s->waveform(s, in, out, k, s->intensity, offset_y, offset_x, s->mode, s->mirror);
         }
     }
+    s->graticulef(s, out);
 
     av_frame_free(&in);
     return ff_filter_frame(outlink, out);
diff --git a/libavfilter/vf_zoompan.c b/libavfilter/vf_zoompan.c
index 99a1a34..471e143 100644
--- a/libavfilter/vf_zoompan.c
+++ b/libavfilter/vf_zoompan.c
@@ -104,7 +104,7 @@ static const AVOption zoompan_options[] = {
     { "y", "set the y expression", OFFSET(y_expr_str), AV_OPT_TYPE_STRING, {.str="0"}, .flags = FLAGS },
     { "d", "set the duration expression", OFFSET(duration_expr_str), AV_OPT_TYPE_STRING, {.str="90"}, .flags = FLAGS },
     { "s", "set the output image size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, .flags = FLAGS },
-    { "fps", "set the output framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, .flags = FLAGS },
+    { "fps", "set the output framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, INT_MAX, .flags = FLAGS },
     { NULL }
 };
 
diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c
index 939775a..5a7ffc3 100644
--- a/libavfilter/vf_zscale.c
+++ b/libavfilter/vf_zscale.c
@@ -453,8 +453,8 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
         s->src_format.pixel_type = desc->comp[0].depth > 8 ? ZIMG_PIXEL_WORD : ZIMG_PIXEL_BYTE;
         s->src_format.color_family = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_COLOR_RGB : ZIMG_COLOR_YUV;
         s->src_format.matrix_coefficients = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_MATRIX_RGB : s->colorspace_in == -1 ? convert_matrix(in->colorspace) : s->colorspace_in;
-        s->src_format.transfer_characteristics = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_TRANSFER_UNSPECIFIED : s->trc_in == - 1 ? convert_trc(in->color_trc) : s->trc_in;
-        s->src_format.color_primaries = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_PRIMARIES_UNSPECIFIED : s->primaries_in == -1 ? convert_primaries(in->color_primaries) : s->primaries_in;
+        s->src_format.transfer_characteristics = s->trc_in == - 1 ? convert_trc(in->color_trc) : s->trc_in;
+        s->src_format.color_primaries = s->primaries_in == -1 ? convert_primaries(in->color_primaries) : s->primaries_in;
         s->src_format.pixel_range = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_RANGE_FULL : s->range_in == -1 ? convert_range(in->color_range) : s->range_in;
 
         s->dst_format.width = out->width;
@@ -465,8 +465,8 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
         s->dst_format.pixel_type = odesc->comp[0].depth > 8 ? ZIMG_PIXEL_WORD : ZIMG_PIXEL_BYTE;
         s->dst_format.color_family = (odesc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_COLOR_RGB : ZIMG_COLOR_YUV;
         s->dst_format.matrix_coefficients = (odesc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_MATRIX_RGB : s->colorspace == -1 ? convert_matrix(out->colorspace) : s->colorspace;
-        s->dst_format.transfer_characteristics = (odesc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_TRANSFER_UNSPECIFIED : s->trc == -1 ? convert_trc(out->color_trc) : s->trc;
-        s->dst_format.color_primaries = (odesc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_PRIMARIES_UNSPECIFIED : s->primaries == -1 ? convert_primaries(out->color_primaries) : s->primaries;
+        s->dst_format.transfer_characteristics = s->trc == -1 ? convert_trc(out->color_trc) : s->trc;
+        s->dst_format.color_primaries = s->primaries == -1 ? convert_primaries(out->color_primaries) : s->primaries;
         s->dst_format.pixel_range = (odesc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_RANGE_FULL : s->range == -1 ? convert_range(out->color_range) : s->range;
 
         if (s->colorspace != -1)
diff --git a/libavfilter/vsrc_cellauto.c b/libavfilter/vsrc_cellauto.c
index 67bd167..4961f76 100644
--- a/libavfilter/vsrc_cellauto.c
+++ b/libavfilter/vsrc_cellauto.c
@@ -65,8 +65,8 @@ static const AVOption cellauto_options[] = {
     { "f",        "read initial pattern from file", OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
     { "pattern",  "set initial pattern", OFFSET(pattern), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
     { "p",        "set initial pattern", OFFSET(pattern), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
-    { "rate",     "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
-    { "r",        "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
+    { "rate",     "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
+    { "r",        "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
     { "size",     "set video size", OFFSET(w),    AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, FLAGS },
     { "s",        "set video size", OFFSET(w),    AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, FLAGS },
     { "rule",     "set rule",       OFFSET(rule), AV_OPT_TYPE_INT,    {.i64 = 110},  0, 255, FLAGS },
diff --git a/libavfilter/vsrc_life.c b/libavfilter/vsrc_life.c
index 3d1d36f..8d51051 100644
--- a/libavfilter/vsrc_life.c
+++ b/libavfilter/vsrc_life.c
@@ -82,8 +82,8 @@ static const AVOption life_options[] = {
     { "f",        "set source file",  OFFSET(filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
     { "size",     "set video size",   OFFSET(w),        AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, FLAGS },
     { "s",        "set video size",   OFFSET(w),        AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, FLAGS },
-    { "rate",     "set video rate",   OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
-    { "r",        "set video rate",   OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
+    { "rate",     "set video rate",   OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
+    { "r",        "set video rate",   OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
     { "rule",     "set rule",         OFFSET(rule_str), AV_OPT_TYPE_STRING, {.str = "B3/S23"}, CHAR_MIN, CHAR_MAX, FLAGS },
     { "random_fill_ratio", "set fill ratio for filling initial grid randomly", OFFSET(random_fill_ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1/M_PHI}, 0, 1, FLAGS },
     { "ratio",             "set fill ratio for filling initial grid randomly", OFFSET(random_fill_ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1/M_PHI}, 0, 1, FLAGS },
diff --git a/libavfilter/vsrc_mptestsrc.c b/libavfilter/vsrc_mptestsrc.c
index 25ad2ad..3c75821 100644
--- a/libavfilter/vsrc_mptestsrc.c
+++ b/libavfilter/vsrc_mptestsrc.c
@@ -61,8 +61,8 @@ typedef struct MPTestContext {
 #define OFFSET(x) offsetof(MPTestContext, x)
 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
 static const AVOption mptestsrc_options[]= {
-    { "rate",     "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
-    { "r",        "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },
+    { "rate",     "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
+    { "r",        "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
     { "duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },
     { "d",        "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },
 
diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c
index 54d8b26..30c70bc 100644
--- a/libavfilter/vsrc_testsrc.c
+++ b/libavfilter/vsrc_testsrc.c
@@ -37,6 +37,7 @@
 
 #include "libavutil/avassert.h"
 #include "libavutil/common.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/opt.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/intreadwrite.h"
@@ -85,8 +86,8 @@ typedef struct TestSourceContext {
     { "s",        "set video size",     OFFSET(w),        AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS },\
 
 #define COMMON_OPTIONS_NOSIZE \
-    { "rate",     "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },\
-    { "r",        "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, FLAGS },\
+    { "rate",     "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },\
+    { "r",        "set video rate",     OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },\
     { "duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },\
     { "d",        "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },\
     { "sar",      "set video sample aspect ratio", OFFSET(sar), AV_OPT_TYPE_RATIONAL, {.dbl= 1},  0, INT_MAX, FLAGS },
@@ -1073,12 +1074,12 @@ AVFilter ff_vsrc_rgbtestsrc = {
 
 static const uint8_t rainbow[7][4] = {
     { 180, 128, 128, 255 },     /* 75% white */
-    { 161,  44, 141, 255 },     /* 75% yellow */
+    { 162,  44, 142, 255 },     /* 75% yellow */
     { 131, 156,  44, 255 },     /* 75% cyan */
-    { 112,  72,  57, 255 },     /* 75% green */
-    {  83, 183, 198, 255 },     /* 75% magenta */
-    {  65,  99, 212, 255 },     /* 75% red */
-    {  34, 212, 114, 255 },     /* 75% blue */
+    { 112,  72,  58, 255 },     /* 75% green */
+    {  84, 184, 198, 255 },     /* 75% magenta */
+    {  65, 100, 212, 255 },     /* 75% red */
+    {  35, 212, 114, 255 },     /* 75% blue */
 };
 
 static const uint8_t rainbowhd[7][4] = {
@@ -1092,9 +1093,9 @@ static const uint8_t rainbowhd[7][4] = {
 };
 
 static const uint8_t wobnair[7][4] = {
-    {  34, 212, 114, 255 },     /* 75% blue */
+    {  35, 212, 114, 255 },     /* 75% blue */
     {  19, 128, 128, 255 },     /* 7.5% intensity black */
-    {  83, 183, 198, 255 },     /* 75% magenta */
+    {  84, 184, 198, 255 },     /* 75% magenta */
     {  19, 128, 128, 255 },     /* 7.5% intensity black */
     { 131, 156,  44, 255 },     /* 75% cyan */
     {  19, 128, 128, 255 },     /* 7.5% intensity black */
diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile
index 33de380..b6195f8 100644
--- a/libavfilter/x86/Makefile
+++ b/libavfilter/x86/Makefile
@@ -1,4 +1,6 @@
 OBJS-$(CONFIG_BLEND_FILTER)                  += x86/vf_blend_init.o
+OBJS-$(CONFIG_BWDIF_FILTER)                  += x86/vf_bwdif_init.o
+OBJS-$(CONFIG_COLORSPACE_FILTER)             += x86/colorspacedsp_init.o
 OBJS-$(CONFIG_EQ_FILTER)                     += x86/vf_eq.o
 OBJS-$(CONFIG_FSPP_FILTER)                   += x86/vf_fspp_init.o
 OBJS-$(CONFIG_GRADFUN_FILTER)                += x86/vf_gradfun_init.o
@@ -11,6 +13,7 @@ OBJS-$(CONFIG_PP7_FILTER)                    += x86/vf_pp7_init.o
 OBJS-$(CONFIG_PSNR_FILTER)                   += x86/vf_psnr_init.o
 OBJS-$(CONFIG_PULLUP_FILTER)                 += x86/vf_pullup_init.o
 OBJS-$(CONFIG_REMOVEGRAIN_FILTER)            += x86/vf_removegrain_init.o
+OBJS-$(CONFIG_SHOWCQT_FILTER)                += x86/avf_showcqt_init.o
 OBJS-$(CONFIG_SPP_FILTER)                    += x86/vf_spp.o
 OBJS-$(CONFIG_SSIM_FILTER)                   += x86/vf_ssim_init.o
 OBJS-$(CONFIG_STEREO3D_FILTER)               += x86/vf_stereo3d_init.o
@@ -21,6 +24,8 @@ OBJS-$(CONFIG_W3FDIF_FILTER)                 += x86/vf_w3fdif_init.o
 OBJS-$(CONFIG_YADIF_FILTER)                  += x86/vf_yadif_init.o
 
 YASM-OBJS-$(CONFIG_BLEND_FILTER)             += x86/vf_blend.o
+YASM-OBJS-$(CONFIG_BWDIF_FILTER)             += x86/vf_bwdif.o
+YASM-OBJS-$(CONFIG_COLORSPACE_FILTER)        += x86/colorspacedsp.o
 YASM-OBJS-$(CONFIG_FSPP_FILTER)              += x86/vf_fspp.o
 YASM-OBJS-$(CONFIG_GRADFUN_FILTER)           += x86/vf_gradfun.o
 YASM-OBJS-$(CONFIG_HQDN3D_FILTER)            += x86/vf_hqdn3d.o
@@ -33,6 +38,7 @@ YASM-OBJS-$(CONFIG_PULLUP_FILTER)            += x86/vf_pullup.o
 ifdef CONFIG_GPL
 YASM-OBJS-$(CONFIG_REMOVEGRAIN_FILTER)       += x86/vf_removegrain.o
 endif
+YASM-OBJS-$(CONFIG_SHOWCQT_FILTER)           += x86/avf_showcqt.o
 YASM-OBJS-$(CONFIG_SSIM_FILTER)              += x86/vf_ssim.o
 YASM-OBJS-$(CONFIG_STEREO3D_FILTER)          += x86/vf_stereo3d.o
 YASM-OBJS-$(CONFIG_TBLEND_FILTER)            += x86/vf_blend.o
diff --git a/libavfilter/x86/avf_showcqt.asm b/libavfilter/x86/avf_showcqt.asm
new file mode 100644
index 0000000..659afeb
--- /dev/null
+++ b/libavfilter/x86/avf_showcqt.asm
@@ -0,0 +1,201 @@
+;*****************************************************************************
+;* x86-optimized functions for showcqt filter
+;*
+;* Copyright (C) 2016 Muhammad Faiz <mfcc64 at gmail.com>
+;*
+;* 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/x86/x86util.asm"
+
+%if ARCH_X86_64
+%define pointer resq
+%else
+%define pointer resd
+%endif
+
+struc Coeffs
+    .val:   pointer 1
+    .start: resd 1
+    .len:   resd 1
+    .sizeof:
+endstruc
+
+%macro EMULATE_FMADDPS 5 ; dst, src1, src2, src3, tmp
+%if cpuflag(fma3) || cpuflag(fma4)
+    fmaddps %1, %2, %3, %4
+%else
+    mulps   %5, %2, %3
+    addps   %1, %4, %5
+%endif
+%endmacro ; EMULATE_FMADDPS
+
+%macro CQT_CALC 9
+; %1 = a_re, %2 = a_im, %3 = b_re, %4 = b_im
+; %5 = m_re, %6 = m_im, %7 = tmp, %8 = coeffval, %9 = coeffsq_offset
+    mov     id, xd
+    add     id, [coeffsq + Coeffs.start + %9]
+    movaps  m%5, [srcq + 8 * iq]
+    movaps  m%7, [srcq + 8 * iq + mmsize]
+    shufps  m%6, m%5, m%7, q3131
+    shufps  m%5, m%5, m%7, q2020
+    sub     id, fft_lend
+    EMULATE_FMADDPS m%2, m%6, m%8, m%2, m%6
+    neg     id
+    EMULATE_FMADDPS m%1, m%5, m%8, m%1, m%5
+    movups  m%5, [srcq + 8 * iq - mmsize + 8]
+    movups  m%7, [srcq + 8 * iq - 2*mmsize + 8]
+    %if mmsize == 32
+    vperm2f128 m%5, m%5, m%5, 1
+    vperm2f128 m%7, m%7, m%7, 1
+    %endif
+    shufps  m%6, m%5, m%7, q1313
+    shufps  m%5, m%5, m%7, q0202
+    EMULATE_FMADDPS m%4, m%6, m%8, m%4, m%6
+    EMULATE_FMADDPS m%3, m%5, m%8, m%3, m%5
+%endmacro ; CQT_CALC
+
+%macro CQT_SEPARATE 6 ; a_re, a_im, b_re, b_im, tmp, tmp2
+    addps   m%5, m%4, m%2
+    subps   m%6, m%3, m%1
+    addps   m%1, m%1, m%3
+    subps   m%2, m%2, m%4
+    HADDPS  m%5, m%6, m%3
+    HADDPS  m%1, m%2, m%3
+    HADDPS  m%1, m%5, m%2
+    %if mmsize == 32
+    vextractf128 xmm%2, m%1, 1
+    addps   xmm%1, xmm%2
+    %endif
+%endmacro ; CQT_SEPARATE
+
+%macro DECLARE_CQT_CALC 0
+; ff_showcqt_cqt_calc_*(dst, src, coeffs, len, fft_len)
+%if ARCH_X86_64
+cglobal showcqt_cqt_calc, 5, 10, 12, dst, src, coeffs, len, fft_len, x, coeffs_val, coeffs_val2, i, coeffs_len
+    align   16
+    .loop_k:
+        mov     xd, [coeffsq + Coeffs.len]
+        xorps   m0, m0, m0
+        movaps  m1, m0
+        movaps  m2, m0
+        mov     coeffs_lend, [coeffsq + Coeffs.len + Coeffs.sizeof]
+        movaps  m3, m0
+        movaps  m8, m0
+        cmp     coeffs_lend, xd
+        movaps  m9, m0
+        movaps  m10, m0
+        movaps  m11, m0
+        cmova   coeffs_lend, xd
+        xor     xd, xd
+        test    coeffs_lend, coeffs_lend
+        jz      .check_loop_b
+        mov     coeffs_valq, [coeffsq + Coeffs.val]
+        mov     coeffs_val2q, [coeffsq + Coeffs.val + Coeffs.sizeof]
+        align   16
+        .loop_ab:
+            movaps  m7, [coeffs_valq + 4 * xq]
+            CQT_CALC 0, 1, 2, 3, 4, 5, 6, 7, 0
+            movaps  m7, [coeffs_val2q + 4 * xq]
+            CQT_CALC 8, 9, 10, 11, 4, 5, 6, 7, Coeffs.sizeof
+            add     xd, mmsize/4
+            cmp     xd, coeffs_lend
+            jb      .loop_ab
+        .check_loop_b:
+        cmp     xd, [coeffsq + Coeffs.len + Coeffs.sizeof]
+        jae     .check_loop_a
+        align   16
+        .loop_b:
+            movaps  m7, [coeffs_val2q + 4 * xq]
+            CQT_CALC 8, 9, 10, 11, 4, 5, 6, 7, Coeffs.sizeof
+            add     xd, mmsize/4
+            cmp     xd, [coeffsq + Coeffs.len + Coeffs.sizeof]
+            jb      .loop_b
+        .loop_end:
+        CQT_SEPARATE 0, 1, 2, 3, 4, 5
+        CQT_SEPARATE 8, 9, 10, 11, 4, 5
+        mulps   xmm0, xmm0
+        mulps   xmm8, xmm8
+        HADDPS  xmm0, xmm8, xmm1
+        movaps  [dstq], xmm0
+        sub     lend, 2
+        lea     dstq, [dstq + 16]
+        lea     coeffsq, [coeffsq + 2*Coeffs.sizeof]
+        jnz     .loop_k
+        REP_RET
+        align   16
+        .check_loop_a:
+        cmp     xd, [coeffsq + Coeffs.len]
+        jae     .loop_end
+        align   16
+        .loop_a:
+            movaps  m7, [coeffs_valq + 4 * xq]
+            CQT_CALC 0, 1, 2, 3, 4, 5, 6, 7, 0
+            add     xd, mmsize/4
+            cmp     xd, [coeffsq + Coeffs.len]
+            jb      .loop_a
+        jmp     .loop_end
+%else
+cglobal showcqt_cqt_calc, 4, 7, 8, dst, src, coeffs, len, x, coeffs_val, i
+%define fft_lend r4m
+    align   16
+    .loop_k:
+        mov     xd, [coeffsq + Coeffs.len]
+        xorps   m0, m0, m0
+        movaps  m1, m0
+        movaps  m2, m0
+        movaps  m3, m0
+        test    xd, xd
+        jz      .store
+        mov     coeffs_valq, [coeffsq + Coeffs.val]
+        xor     xd, xd
+        align   16
+        .loop_x:
+            movaps  m7, [coeffs_valq + 4 * xq]
+            CQT_CALC 0, 1, 2, 3, 4, 5, 6, 7, 0
+            add     xd, mmsize/4
+            cmp     xd, [coeffsq + Coeffs.len]
+            jb      .loop_x
+        CQT_SEPARATE 0, 1, 2, 3, 4, 5
+        mulps   xmm0, xmm0
+        HADDPS  xmm0, xmm0, xmm1
+        .store:
+        movlps  [dstq], xmm0
+        sub     lend, 1
+        lea     dstq, [dstq + 8]
+        lea     coeffsq, [coeffsq + Coeffs.sizeof]
+        jnz     .loop_k
+        REP_RET
+%endif ; ARCH_X86_64
+%endmacro ; DECLARE_CQT_CALC
+
+INIT_XMM sse
+DECLARE_CQT_CALC
+INIT_XMM sse3
+DECLARE_CQT_CALC
+%if HAVE_AVX_EXTERNAL
+INIT_YMM avx
+DECLARE_CQT_CALC
+%endif
+%if HAVE_FMA3_EXTERNAL
+INIT_YMM fma3
+DECLARE_CQT_CALC
+%endif
+%if HAVE_FMA4_EXTERNAL
+INIT_XMM fma4
+DECLARE_CQT_CALC
+%endif
diff --git a/libavfilter/x86/avf_showcqt_init.c b/libavfilter/x86/avf_showcqt_init.c
new file mode 100644
index 0000000..0cc164c
--- /dev/null
+++ b/libavfilter/x86/avf_showcqt_init.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016 Muhammad Faiz <mfcc64 at gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/x86/cpu.h"
+#include "libavfilter/avf_showcqt.h"
+
+#define DECLARE_CQT_CALC(type) \
+void ff_showcqt_cqt_calc_##type(FFTComplex *dst, const FFTComplex *src, \
+                                const Coeffs *coeffs, int len, int fft_len)
+
+DECLARE_CQT_CALC(sse);
+DECLARE_CQT_CALC(sse3);
+DECLARE_CQT_CALC(avx);
+DECLARE_CQT_CALC(fma3);
+DECLARE_CQT_CALC(fma4);
+
+#define permute_coeffs_0 NULL
+
+static void permute_coeffs_01452367(float *v, int len)
+{
+    int k;
+    for (k = 0; k < len; k += 8) {
+        FFSWAP(float, v[k+2], v[k+4]);
+        FFSWAP(float, v[k+3], v[k+5]);
+    }
+}
+
+av_cold void ff_showcqt_init_x86(ShowCQTContext *s)
+{
+    int cpuflags = av_get_cpu_flags();
+
+#define SELECT_CQT_CALC(type, TYPE, align, perm) \
+if (EXTERNAL_##TYPE(cpuflags)) { \
+    s->cqt_calc = ff_showcqt_cqt_calc_##type; \
+    s->cqt_align = align; \
+    s->permute_coeffs = permute_coeffs_##perm; \
+}
+
+    SELECT_CQT_CALC(sse,  SSE,  4, 0);
+    SELECT_CQT_CALC(sse3, SSE3_FAST, 4, 0);
+    SELECT_CQT_CALC(fma4, FMA4, 4, 0); // using xmm
+    SELECT_CQT_CALC(avx,  AVX_FAST,  8, 01452367);
+    SELECT_CQT_CALC(fma3, FMA3_FAST, 8, 01452367);
+}
diff --git a/libavfilter/x86/colorspacedsp.asm b/libavfilter/x86/colorspacedsp.asm
new file mode 100644
index 0000000..67d851a
--- /dev/null
+++ b/libavfilter/x86/colorspacedsp.asm
@@ -0,0 +1,1097 @@
+;*****************************************************************************
+;* x86-optimized functions for colorspace filter
+;*
+;* Copyright (C) 2016 Ronald S. Bultje <rsbultje at gmail.com>
+;*
+;* 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/x86/x86util.asm"
+
+SECTION_RODATA
+
+pw_1: times 8 dw 1
+pw_2: times 8 dw 2
+pw_4: times 8 dw 4
+pw_8: times 8 dw 8
+pw_16: times 8 dw 16
+pw_64: times 8 dw 64
+pw_128: times 8 dw 128
+pw_256: times 8 dw 256
+pw_512: times 8 dw 512
+pw_1023: times 8 dw 1023
+pw_1024: times 8 dw 1024
+pw_2048: times 8 dw 2048
+pw_4095: times 8 dw 4095
+pw_8192: times 8 dw 8192
+pw_16384: times 8 dw 16384
+
+pd_1: times 4 dd 1
+pd_2: times 4 dd 2
+pd_128: times 4 dd 128
+pd_512: times 4 dd 512
+pd_2048: times 4 dd 2048
+pd_8192: times 4 dd 8192
+pd_32768: times 4 dd 32768
+pd_131072: times 4 dd 131072
+
+SECTION .text
+
+; void ff_yuv2yuv_420p8to8_sse2(uint8_t *yuv_out[3], ptrdiff_t yuv_out_stride[3],
+;                               uint8_t *yuv_in[3], ptrdiff_t yuv_in_stride[3],
+;                               int w, int h, const int16_t yuv2yuv_coeffs[3][3][8],
+;                               const int16_t yuv_offset[2][8])
+
+%if ARCH_X86_64
+%macro YUV2YUV_FN 4 ; in_bitdepth, out_bitdepth, log2_chroma_w (horiz), log2_chroma_h (vert)
+
+%assign %%sh (14 + %1 - %2)
+%assign %%rnd (1 << (%%sh - 1))
+%assign %%uvinoff (128 << (%1 - 8))
+%assign %%uvoutoff (128 << (%2 - 8))
+%if %3 == 0
+%assign %%ss 444
+%elif %4 == 0
+%assign %%ss 422
+%else ; %4 == 1
+%assign %%ss 420
+%endif ; %3/%4
+%if %2 != 8
+%assign %%maxval (1 << %2) - 1
+%endif ; %2 != 8
+
+%assign %%ypsh %%sh - 1
+%if %%ypsh > 14
+%assign %%yoffsh %%ypsh - 13
+%assign %%ypsh 14
+%else
+%assign %%yoffsh 1
+%endif
+%assign %%yprnd (1 << (%%yoffsh - 1))
+%assign %%ypmul (1 << %%ypsh)
+
+cglobal yuv2yuv_ %+ %%ss %+ p%1to%2, 8, 14, 16, 0 - (4 * mmsize), \
+                                     yo, yos, yi, yis, w, h, c, yoff, ui, vi, uo, vo
+%if %3 == 1
+    inc             wd
+    sar             wd, 1
+%if %4 == 1
+    inc             hd
+    sar             hd, 1
+%endif ; %4 == 1
+%endif ; %3 == 1
+    mov [rsp+3*mmsize+0], wd
+    mov [rsp+3*mmsize+4], hd
+
+    mova           m10, [cq]
+    pxor           m11, m11
+    mova           m12, [pd_ %+ %%uvoutoff]
+    pslld          m12, %%sh
+    paddd          m12, [pd_ %+ %%rnd]
+    mova           m13, [pw_ %+ %%uvinoff]
+    mova           m14, [yoffq+ 0]      ; y_off_in
+    mova           m15, [yoffq+16]      ; y_off_out
+%if %%yoffsh != 0
+    psllw          m15, %%yoffsh
+%endif
+    paddw          m15, [pw_ %+ %%yprnd]
+    punpcklwd      m10, m15
+    mova           m15, [pw_ %+ %%ypmul]
+    movh            m0, [cq+1*16]       ; cyu
+    movh            m1, [cq+2*16]       ; cyv
+    movh            m2, [cq+4*16]       ; cuu
+    movh            m3, [cq+5*16]       ; cuv
+    movh            m4, [cq+7*16]       ; cvu
+    movh            m5, [cq+8*16]       ; cvv
+    punpcklwd       m0, m1
+    punpcklwd       m2, m3
+    punpcklwd       m4, m5
+    mova [rsp+0*mmsize], m0
+    mova [rsp+1*mmsize], m2
+    mova [rsp+2*mmsize], m4
+
+    DEFINE_ARGS yo, yos, yi, yis, ui, vi, uo, vo, uis, vis, uos, vos, x, tmp
+
+    mov            uiq, [yiq+gprsize*1]
+    mov            viq, [yiq+gprsize*2]
+    mov            yiq, [yiq+gprsize*0]
+    mov            uoq, [yoq+gprsize*1]
+    mov            voq, [yoq+gprsize*2]
+    mov            yoq, [yoq+gprsize*0]
+    mov           uisq, [yisq+gprsize*1]
+    mov           visq, [yisq+gprsize*2]
+    mov           yisq, [yisq+gprsize*0]
+    mov           uosq, [yosq+gprsize*1]
+    mov           vosq, [yosq+gprsize*2]
+    mov           yosq, [yosq+gprsize*0]
+
+.loop_v:
+    xor             xq, xq
+
+.loop_h:
+%if %4 == 1
+    lea           tmpq, [yiq+yisq]
+%endif ; %4 == 1
+%if %1 == 8
+    movu            m0, [yiq+xq*(1<<%3)]        ; y00/01
+%if %4 == 1
+    movu            m2, [tmpq+xq*2]             ; y10/11
+%endif ; %4 == 1
+%if %3 == 1
+    movh            m4, [uiq+xq]                ; u
+    movh            m5, [viq+xq]                ; v
+%else ; %3 != 1
+    movu            m4, [uiq+xq]                ; u
+    movu            m5, [viq+xq]                ; v
+%endif ; %3 ==/!= 1
+    punpckhbw       m1, m0, m11
+    punpcklbw       m0, m11
+%if %4 == 1
+    punpckhbw       m3, m2, m11
+    punpcklbw       m2, m11
+%endif ; %4 == 1
+%if %3 == 0
+    punpckhbw       m2, m4, m11
+    punpckhbw       m3, m5, m11
+%endif ; %3 == 0
+    punpcklbw       m4, m11
+    punpcklbw       m5, m11
+%else ; %1 != 8
+    movu            m0, [yiq+xq*(2<<%3)]        ; y00/01
+    movu            m1, [yiq+xq*(2<<%3)+mmsize] ; y00/01
+%if %4 == 1
+    movu            m2, [tmpq+xq*4]             ; y10/11
+    movu            m3, [tmpq+xq*4+mmsize]      ; y10/11
+%endif ; %4 == 1
+    movu            m4, [uiq+xq*2]              ; u
+    movu            m5, [viq+xq*2]              ; v
+%if %3 == 0
+    movu            m2, [uiq+xq*2+mmsize]
+    movu            m3, [viq+xq*2+mmsize]
+%endif ; %3 == 0
+%endif ; %1 ==/!= 8
+    psubw           m0, m14
+    psubw           m1, m14
+%if %4 == 1
+    psubw           m2, m14
+    psubw           m3, m14
+%endif ; %4 == 1
+    psubw           m4, m13
+    psubw           m5, m13
+%if %3 == 0
+    psubw           m2, m13
+    psubw           m3, m13
+%endif ; %3 == 0
+
+    SBUTTERFLY   wd, 4, 5, 6
+    pmaddwd         m6, m4, [rsp+1*mmsize]
+    pmaddwd         m7, m5, [rsp+1*mmsize]
+%if %3 == 0
+    SBUTTERFLY   wd, 2, 3, 8
+    pmaddwd         m8, m2, [rsp+1*mmsize]
+    pmaddwd         m9, m3, [rsp+1*mmsize]
+%else ; %3 != 0
+    pmaddwd         m8, m4, [rsp+2*mmsize]
+    pmaddwd         m9, m5, [rsp+2*mmsize]
+%endif
+    paddd           m6, m12
+    paddd           m7, m12
+    paddd           m8, m12
+    paddd           m9, m12
+    psrad           m6, %%sh
+    psrad           m7, %%sh
+    psrad           m8, %%sh
+    psrad           m9, %%sh
+    packssdw        m6, m7
+    packssdw        m8, m9
+%if %2 == 8
+    packuswb        m6, m8
+%if %3 == 0
+    movu      [uoq+xq], m6
+%else ; %3 != 0
+    movh      [uoq+xq], m6
+    movhps    [voq+xq], m6
+%endif ; %3 ==/!= 0
+%else ; %2 != 8
+    CLIPW           m6, m11, [pw_ %+ %%maxval]
+    CLIPW           m8, m11, [pw_ %+ %%maxval]
+    movu    [uoq+xq*2], m6
+%if %3 == 0
+    movu    [uoq+xq*2+mmsize], m8
+%else ; %3 != 0
+    movu    [voq+xq*2], m8
+%endif ; %3 ==/!= 0
+%endif ; %2 ==/!= 8
+
+%if %3 == 0
+    pmaddwd         m6, m4, [rsp+2*mmsize]
+    pmaddwd         m7, m5, [rsp+2*mmsize]
+    pmaddwd         m8, m2, [rsp+2*mmsize]
+    pmaddwd         m9, m3, [rsp+2*mmsize]
+    paddd           m6, m12
+    paddd           m7, m12
+    paddd           m8, m12
+    paddd           m9, m12
+    psrad           m6, %%sh
+    psrad           m7, %%sh
+    psrad           m8, %%sh
+    psrad           m9, %%sh
+    packssdw        m6, m7
+    packssdw        m8, m9
+%if %2 == 8
+    packuswb        m6, m8
+    movu      [voq+xq], m6
+%else ; %2 != 8
+    CLIPW           m6, m11, [pw_ %+ %%maxval]
+    CLIPW           m8, m11, [pw_ %+ %%maxval]
+    movu    [voq+xq*2], m6
+    movu    [voq+xq*2+mmsize], m8
+%endif ; %2 ==/!= 8
+%endif ; %3 == 0
+
+    pmaddwd         m4, [rsp+0*mmsize]
+    pmaddwd         m5, [rsp+0*mmsize]          ; uv_val
+%if %3 == 0
+    pmaddwd         m2, [rsp+0*mmsize]
+    pmaddwd         m3, [rsp+0*mmsize]
+%endif ; %3 == 0
+
+    ; unpack y pixels with m15 (shifted round + offset), then multiply
+    ; by m10, add uv pixels, and we're done!
+%if %3 == 1
+    punpckhdq       m8, m4, m4
+    punpckldq       m4, m4
+    punpckhdq       m9, m5, m5
+    punpckldq       m5, m5
+%else ; %3 != 1
+    SWAP             8, 5, 2
+    SWAP             3, 9
+%endif ; %3 ==/!= 1
+%if %4 == 1
+    punpckhwd       m6, m2, m15
+    punpcklwd       m2, m15
+    punpckhwd       m7, m3, m15
+    punpcklwd       m3, m15
+    pmaddwd         m2, m10
+    pmaddwd         m6, m10
+    pmaddwd         m3, m10
+    pmaddwd         m7, m10
+    paddd           m2, m4
+    paddd           m6, m8
+    paddd           m3, m5
+    paddd           m7, m9
+    psrad           m2, %%sh
+    psrad           m6, %%sh
+    psrad           m3, %%sh
+    psrad           m7, %%sh
+    packssdw        m2, m6
+    packssdw        m3, m7
+
+    lea           tmpq, [yoq+yosq]
+%if %2 == 8
+    packuswb        m2, m3
+    movu   [tmpq+xq*2], m2
+%else ; %2 != 8
+    CLIPW           m2, m11, [pw_ %+ %%maxval]
+    CLIPW           m3, m11, [pw_ %+ %%maxval]
+    movu   [tmpq+xq*4], m2
+    movu [tmpq+xq*4+mmsize], m3
+%endif ; %2 ==/!= 8
+%endif ; %4 == 1
+
+    punpckhwd       m6, m0, m15
+    punpcklwd       m0, m15
+    punpckhwd       m7, m1, m15
+    punpcklwd       m1, m15
+    pmaddwd         m0, m10
+    pmaddwd         m6, m10
+    pmaddwd         m1, m10
+    pmaddwd         m7, m10
+    paddd           m0, m4
+    paddd           m6, m8
+    paddd           m1, m5
+    paddd           m7, m9
+    psrad           m0, %%sh
+    psrad           m6, %%sh
+    psrad           m1, %%sh
+    psrad           m7, %%sh
+    packssdw        m0, m6
+    packssdw        m1, m7
+
+%if %2 == 8
+    packuswb        m0, m1
+    movu    [yoq+xq*(1<<%3)], m0
+%else ; %2 != 8
+    CLIPW           m0, m11, [pw_ %+ %%maxval]
+    CLIPW           m1, m11, [pw_ %+ %%maxval]
+    movu  [yoq+xq*(2<<%3)], m0
+    movu [yoq+xq*(2<<%3)+mmsize], m1
+%endif ; %2 ==/!= 8
+
+    add             xq, mmsize >> %3
+    cmp             xd, dword [rsp+3*mmsize+0]
+    jl .loop_h
+
+%if %4 == 1
+    lea            yiq, [yiq+yisq*2]
+    lea            yoq, [yoq+yosq*2]
+%else ; %4 != 1
+    add            yiq, yisq
+    add            yoq, yosq
+%endif ; %4 ==/!= 1
+    add            uiq, uisq
+    add            viq, visq
+    add            uoq, uosq
+    add            voq, vosq
+    dec dword [rsp+3*mmsize+4]
+    jg .loop_v
+
+    RET
+%endmacro
+
+%macro YUV2YUV_FNS 2 ; ss_w, ss_h
+YUV2YUV_FN  8,  8, %1, %2
+YUV2YUV_FN 10,  8, %1, %2
+YUV2YUV_FN 12,  8, %1, %2
+YUV2YUV_FN  8, 10, %1, %2
+YUV2YUV_FN 10, 10, %1, %2
+YUV2YUV_FN 12, 10, %1, %2
+YUV2YUV_FN  8, 12, %1, %2
+YUV2YUV_FN 10, 12, %1, %2
+YUV2YUV_FN 12, 12, %1, %2
+%endmacro
+
+INIT_XMM sse2
+YUV2YUV_FNS 0, 0
+YUV2YUV_FNS 1, 0
+YUV2YUV_FNS 1, 1
+
+; void ff_yuv2rgb_420p8_sse2(int16_t *rgb[3], ptrdiff_t rgb_stride,
+;                            uint8_t *yuv[3], ptrdiff_t yuv_stride[3],
+;                            int w, int h, const int16_t yuv2rgb_coeffs[3][3][8],
+;                            const int16_t yuv_offset[8])
+%macro YUV2RGB_FN 3 ; depth, log2_chroma_w (horiz), log2_chroma_h (vert)
+%assign %%sh (%1 - 1)
+%assign %%rnd (1 << (%%sh - 1))
+%assign %%uvoff (1 << (%1 - 1))
+%if %2 == 0
+%assign %%ss 444
+%elif %3 == 0
+%assign %%ss 422
+%else ; %3 == 1
+%assign %%ss 420
+%endif ; %2/%3
+
+cglobal yuv2rgb_ %+ %%ss %+ p%1, 8, 14, 16, 0 - 8 * mmsize, \
+                                rgb, rgbs, yuv, yuvs, ww, h, c, yoff
+%if %2 == 1
+    inc            wwd
+    sar            wwd, 1
+%endif ; %2 == 1
+%if %3 == 1
+    inc             hd
+    sar             hd, 1
+%endif ; %3 == 1
+    pxor           m11, m11
+    mova           m15, [yoffq]                 ; yoff
+    movh           m14, [cq+  0]                ; cy
+    movh           m10, [cq+ 32]                ; crv
+    movh           m13, [cq+112]                ; cbu
+    movh           m12, [cq+ 64]                ; cgu
+    movh            m9, [cq+ 80]                ; cgv
+    punpcklwd      m14, [pw_ %+ %%rnd]          ; cy, rnd
+    punpcklwd      m13, m11                     ; cbu, 0
+    punpcklwd      m11, m10                     ; 0, crv
+    punpcklwd      m12, m9                      ; cgu, cgv
+    mova [rsp+0*mmsize], m11
+    mova [rsp+1*mmsize], m12
+    mova [rsp+2*mmsize], m13
+    mova [rsp+3*mmsize], m14
+    pxor           m14, m14
+
+    DEFINE_ARGS r, rgbs, y, ys, ww, h, g, b, u, v, us, vs, x, tmp
+
+    mov             gq, [rq+1*gprsize]
+    mov             bq, [rq+2*gprsize]
+    mov             rq, [rq+0*gprsize]
+    mov             uq, [yq+1*gprsize]
+    mov             vq, [yq+2*gprsize]
+    mov             yq, [yq+0*gprsize]
+    mov            usq, [ysq+1*gprsize]
+    mov            vsq, [ysq+2*gprsize]
+    mov            ysq, [ysq+0*gprsize]
+
+.loop_v:
+    xor             xq, xq
+
+.loop_h:
+%if %3 == 1
+    lea           tmpq, [yq+ysq]
+%endif ; %3 == 1
+%if %1 == 8
+    movu            m0, [yq+xq*(1<<%2)]
+%if %3 == 1
+    movu            m2, [tmpq+xq*2]
+%endif ; %3 == 1
+%if %2 == 1
+    movh            m4, [uq+xq]
+    movh            m5, [vq+xq]
+%else ; %2 != 1
+    movu            m4, [uq+xq]
+    movu            m5, [vq+xq]
+%endif ; %2 ==/!= 1
+    punpckhbw       m1, m0, m14
+    punpcklbw       m0, m14
+%if %3 == 1
+    punpckhbw       m3, m2, m14
+    punpcklbw       m2, m14
+%endif ; %3 == 1
+%if %2 == 0
+    punpckhbw       m2, m4, m14
+    punpckhbw       m3, m5, m14
+%endif ; %2 == 0
+    punpcklbw       m4, m14
+    punpcklbw       m5, m14
+%else ; %1 != 8
+    movu            m0, [yq+xq*(2<<%2)]
+    movu            m1, [yq+xq*(2<<%2)+mmsize]
+%if %3 == 1
+    movu            m2, [tmpq+xq*4]
+    movu            m3, [tmpq+xq*4+mmsize]
+%endif ; %3 == 1
+    movu            m4, [uq+xq*2]
+    movu            m5, [vq+xq*2]
+%if %2 == 0
+    movu            m2, [uq+xq*2+mmsize]
+    movu            m3, [vq+xq*2+mmsize]
+%endif ; %2 == 0
+%endif ; %1 ==/!= 8
+    psubw           m0, m15
+    psubw           m1, m15
+%if %3 == 1
+    psubw           m2, m15
+    psubw           m3, m15
+%endif ; %3 == 1
+    psubw           m4, [pw_ %+ %%uvoff]
+    psubw           m5, [pw_ %+ %%uvoff]
+    SBUTTERFLY   wd, 4, 5, 6
+%if %2 == 0
+    psubw           m2, [pw_ %+ %%uvoff]
+    psubw           m3, [pw_ %+ %%uvoff]
+    SBUTTERFLY   wd, 2, 3, 6
+%endif ; %2 == 0
+
+    ; calculate y+rnd full-resolution [0-3,6-9]
+    punpckhwd       m6, m0, [pw_1]              ; y, 1
+    punpcklwd       m0, [pw_1]                  ; y, 1
+    punpckhwd       m7, m1, [pw_1]              ; y, 1
+    punpcklwd       m1, [pw_1]                  ; y, 1
+    pmaddwd         m0, [rsp+3*mmsize]
+    pmaddwd         m6, [rsp+3*mmsize]
+    pmaddwd         m1, [rsp+3*mmsize]
+    pmaddwd         m7, [rsp+3*mmsize]
+%if %3 == 1
+    punpckhwd       m8, m2, [pw_1]              ; y, 1
+    punpcklwd       m2, [pw_1]                  ; y, 1
+    punpckhwd       m9, m3, [pw_1]              ; y, 1
+    punpcklwd       m3, [pw_1]                  ; y, 1
+    pmaddwd         m2, [rsp+3*mmsize]
+    pmaddwd         m8, [rsp+3*mmsize]
+    pmaddwd         m3, [rsp+3*mmsize]
+    pmaddwd         m9, [rsp+3*mmsize]
+    mova [rsp+4*mmsize], m2
+    mova [rsp+5*mmsize], m8
+    mova [rsp+6*mmsize], m3
+    mova [rsp+7*mmsize], m9
+%endif ; %3 == 1
+
+    ; calculate r offsets (un-subsampled, then duplicate)
+    pmaddwd        m10, m4, [rsp+0*mmsize]
+%if %2 == 1
+    pmaddwd        m12, m5, [rsp+0*mmsize]
+    punpckhdq      m11, m10, m10
+    punpckldq      m10, m10
+    punpckhdq      m13, m12, m12
+    punpckldq      m12, m12
+%else ; %2 != 1
+    pmaddwd        m11, m5, [rsp+0*mmsize]
+    pmaddwd        m12, m2, [rsp+0*mmsize]
+    pmaddwd        m13, m3, [rsp+0*mmsize]
+%endif ; %2 ==/!= 1
+%if %3 == 1
+    paddd           m2, m10, [rsp+4*mmsize]
+    paddd           m3, m11, [rsp+5*mmsize]
+    paddd           m8, m12, [rsp+6*mmsize]
+    paddd           m9, m13, [rsp+7*mmsize]
+%endif
+    paddd          m10, m0
+    paddd          m11, m6
+    paddd          m12, m1
+    paddd          m13, m7
+%if %3 == 1
+    psrad           m2, %%sh
+    psrad           m3, %%sh
+    psrad           m8, %%sh
+    psrad           m9, %%sh
+%endif ; %3 == 1
+    psrad          m10, %%sh
+    psrad          m11, %%sh
+    psrad          m12, %%sh
+    psrad          m13, %%sh
+%if %3 == 1
+    lea           tmpq, [rq+rgbsq*2]
+    packssdw        m2, m3
+    packssdw        m8, m9
+    mova [tmpq+xq*4], m2
+    mova [tmpq+xq*4+mmsize], m8
+%endif ; %3 == 1
+    packssdw       m10, m11
+    packssdw       m12, m13
+    mova   [rq+xq*(2 << %2)], m10
+    mova   [rq+xq*(2 << %2)+mmsize], m12
+
+    ; calculate g offsets (un-subsampled, then duplicate)
+    pmaddwd        m10, m4, [rsp+1*mmsize]
+%if %2 == 1
+    pmaddwd        m12, m5, [rsp+1*mmsize]
+    punpckhdq      m11, m10, m10
+    punpckldq      m10, m10
+    punpckhdq      m13, m12, m12
+    punpckldq      m12, m12
+%else ; %2 != 1
+    pmaddwd        m11, m5, [rsp+1*mmsize]
+    pmaddwd        m12, m2, [rsp+1*mmsize]
+    pmaddwd        m13, m3, [rsp+1*mmsize]
+%endif ; %2 ==/!= 1
+%if %3 == 1
+    paddd           m2, m10, [rsp+4*mmsize]
+    paddd           m3, m11, [rsp+5*mmsize]
+    paddd           m8, m12, [rsp+6*mmsize]
+    paddd           m9, m13, [rsp+7*mmsize]
+%endif ; %3 == 1
+    paddd          m10, m0
+    paddd          m11, m6
+    paddd          m12, m1
+    paddd          m13, m7
+%if %3 == 1
+    psrad           m2, %%sh
+    psrad           m3, %%sh
+    psrad           m8, %%sh
+    psrad           m9, %%sh
+%endif ; %3 == 1
+    psrad          m10, %%sh
+    psrad          m11, %%sh
+    psrad          m12, %%sh
+    psrad          m13, %%sh
+%if %3 == 1
+    lea           tmpq, [gq+rgbsq*2]
+    packssdw        m2, m3
+    packssdw        m8, m9
+    mova [tmpq+xq*4], m2
+    mova [tmpq+xq*4+mmsize], m8
+%endif ; %3 == 1
+    packssdw       m10, m11
+    packssdw       m12, m13
+    mova   [gq+xq*(2 << %2)], m10
+    mova   [gq+xq*(2 << %2)+mmsize], m12
+
+    ; calculate b offsets (un-subsampled, then duplicate)
+    pmaddwd         m4, [rsp+2*mmsize]
+    pmaddwd         m5, [rsp+2*mmsize]
+%if %2 == 1
+    punpckhdq       m2, m4, m4
+    punpckldq       m4, m4
+    punpckhdq       m3, m5, m5
+    punpckldq       m5, m5
+%else ; %2 != 1
+    pmaddwd         m2, [rsp+2*mmsize]
+    pmaddwd         m3, [rsp+2*mmsize]
+    SWAP             2, 5
+%endif ; %2 ==/!= 1
+    paddd           m0, m4
+    paddd           m6, m2
+    paddd           m1, m5
+    paddd           m7, m3
+%if %3 == 1
+    paddd           m4, [rsp+4*mmsize]
+    paddd           m2, [rsp+5*mmsize]
+    paddd           m5, [rsp+6*mmsize]
+    paddd           m3, [rsp+7*mmsize]
+%endif ; %3 == 1
+    psrad           m0, %%sh
+    psrad           m6, %%sh
+    psrad           m1, %%sh
+    psrad           m7, %%sh
+%if %3 == 1
+    psrad           m4, %%sh
+    psrad           m2, %%sh
+    psrad           m5, %%sh
+    psrad           m3, %%sh
+%endif ; %3 == 1
+    packssdw        m0, m6
+    packssdw        m1, m7
+    movu   [bq+xq*(2 << %2)], m0
+    movu   [bq+xq*(2 << %2)+mmsize], m1
+%if %3 == 1
+    lea           tmpq, [bq+rgbsq*2]
+    packssdw        m4, m2
+    packssdw        m5, m3
+    movu [tmpq+xq*4], m4
+    movu [tmpq+xq*4+mmsize], m5
+%endif ; %3 == 1
+
+    add             xd, mmsize >> %2
+    cmp             xd, wwd
+    jl .loop_h
+
+    lea             rq, [rq+rgbsq*(2 << %3)]
+    lea             gq, [gq+rgbsq*(2 << %3)]
+    lea             bq, [bq+rgbsq*(2 << %3)]
+%if %3 == 1
+    lea             yq, [yq+ysq*2]
+%else ; %3 != 0
+    add             yq, ysq
+%endif ; %3 ==/!= 1
+    add             uq, usq
+    add             vq, vsq
+    dec             hd
+    jg .loop_v
+
+    RET
+%endmacro
+
+%macro YUV2RGB_FNS 2
+YUV2RGB_FN  8, %1, %2
+YUV2RGB_FN 10, %1, %2
+YUV2RGB_FN 12, %1, %2
+%endmacro
+
+INIT_XMM sse2
+YUV2RGB_FNS 0, 0
+YUV2RGB_FNS 1, 0
+YUV2RGB_FNS 1, 1
+
+%macro RGB2YUV_FN 3 ; depth, log2_chroma_w (horiz), log2_chroma_h (vert)
+%assign %%sh 29 - %1
+%assign %%rnd (1 << (%%sh - 15))
+%assign %%uvrnd ((128 << (%1 - 8)) << (%%sh - 14))
+%if %1 != 8
+%assign %%maxval ((1 << %1) - 1)
+%endif ; %1 != 8
+%if %2 == 0
+%assign %%ss 444
+%elif %3 == 0
+%assign %%ss 422
+%else ; %3 == 1
+%assign %%ss 420
+%endif ; %2/%3
+
+cglobal rgb2yuv_ %+ %%ss %+ p%1, 8, 14, 16, 0 - 6 * mmsize, \
+                                 yuv, yuvs, rgb, rgbs, ww, h, c, off
+%if %2 == 1
+    inc            wwd
+    sar            wwd, 1
+%endif ; %2 == 1
+%if %3 == 1
+    inc             hd
+    sar             hd, 1
+%endif ; %3 == 1
+
+    ; prepare coeffs
+    movh            m8, [offq]
+    movh            m9, [pw_ %+ %%uvrnd]
+    psllw           m8, %%sh - 14
+    paddw           m9, [pw_ %+ %%rnd]
+    paddw           m8, [pw_ %+ %%rnd]
+    movh            m0, [cq+  0]
+    movh            m1, [cq+ 16]
+    movh            m2, [cq+ 32]
+    movh            m3, [cq+ 48]
+    movh            m4, [cq+ 64]
+    movh            m5, [cq+ 80]
+    movh            m6, [cq+112]
+    movh            m7, [cq+128]
+    punpcklwd       m0, m1
+    punpcklwd       m2, m8
+    punpcklwd       m3, m4
+    punpcklwd       m4, m5, m9
+    punpcklwd       m5, m6
+    punpcklwd       m7, m9
+
+    mova [rsp+0*mmsize], m0                 ; cry, cgy
+    mova [rsp+1*mmsize], m2                 ; cby, off + rnd
+    mova [rsp+2*mmsize], m3                 ; cru, cgu
+    mova [rsp+3*mmsize], m4                 ; cburv, uvoff + rnd
+    mova [rsp+4*mmsize], m5                 ; cburv, cgv
+    mova [rsp+5*mmsize], m7                 ; cbv, uvoff + rnd
+
+
+    DEFINE_ARGS y, ys, r, rgbs, ww, h, u, v, us, vs, g, b, tmp, x
+    mov             gq, [rq+gprsize*1]
+    mov             bq, [rq+gprsize*2]
+    mov             rq, [rq+gprsize*0]
+    mov             uq, [yq+gprsize*1]
+    mov             vq, [yq+gprsize*2]
+    mov             yq, [yq+gprsize*0]
+    mov            usq, [ysq+gprsize*1]
+    mov            vsq, [ysq+gprsize*2]
+    mov            ysq, [ysq+gprsize*0]
+
+    pxor           m15, m15
+.loop_v:
+    xor             xd, xd
+
+.loop_h:
+    ; top line y
+    mova            m0, [rq+xq*(2<<%2)]
+    mova            m3, [rq+xq*(2<<%2)+mmsize]
+    mova            m1, [gq+xq*(2<<%2)]
+    mova            m4, [gq+xq*(2<<%2)+mmsize]
+    mova            m2, [bq+xq*(2<<%2)]
+    mova            m5, [bq+xq*(2<<%2)+mmsize]
+
+    punpcklwd       m6, m0, m1
+    punpckhwd       m7, m0, m1
+    punpcklwd       m8, m3, m4
+    punpckhwd       m9, m3, m4
+    punpcklwd      m10, m2, [pw_16384]
+    punpckhwd      m11, m2, [pw_16384]
+    punpcklwd      m12, m5, [pw_16384]
+    punpckhwd      m13, m5, [pw_16384]
+
+    pmaddwd         m6, [rsp+0*mmsize]
+    pmaddwd         m7, [rsp+0*mmsize]
+    pmaddwd         m8, [rsp+0*mmsize]
+    pmaddwd         m9, [rsp+0*mmsize]
+    pmaddwd        m10, [rsp+1*mmsize]
+    pmaddwd        m11, [rsp+1*mmsize]
+    pmaddwd        m12, [rsp+1*mmsize]
+    pmaddwd        m13, [rsp+1*mmsize]
+    paddd           m6, m10
+    paddd           m7, m11
+    paddd           m8, m12
+    paddd           m9, m13
+    psrad           m6, %%sh
+    psrad           m7, %%sh
+    psrad           m8, %%sh
+    psrad           m9, %%sh
+    packssdw        m6, m7
+    packssdw        m8, m9
+%if %1 == 8
+    packuswb        m6, m8
+    movu [yq+xq*(1<<%2)], m6
+%else
+    CLIPW           m6, m15, [pw_ %+ %%maxval]
+    CLIPW           m8, m15, [pw_ %+ %%maxval]
+    movu [yq+xq*(2<<%2)], m6
+    movu [yq+xq*(2<<%2)+mmsize], m8
+%endif
+
+%if %2 == 1
+    ; subsampling cached data
+    pmaddwd         m0, [pw_1]
+    pmaddwd         m1, [pw_1]
+    pmaddwd         m2, [pw_1]
+    pmaddwd         m3, [pw_1]
+    pmaddwd         m4, [pw_1]
+    pmaddwd         m5, [pw_1]
+
+%if %3 == 1
+    ; bottom line y, r/g portion only
+    lea           tmpq, [rgbsq+xq*2]
+    mova            m6, [rq+tmpq*2]
+    mova            m9, [rq+tmpq*2+mmsize]
+    mova            m7, [gq+tmpq*2]
+    mova           m10, [gq+tmpq*2+mmsize]
+    mova            m8, [bq+tmpq*2]
+    mova           m11, [bq+tmpq*2+mmsize]
+
+    punpcklwd      m12, m6, m7
+    punpckhwd      m13, m6, m7
+    punpcklwd      m14, m9, m10
+    punpckhwd      m15, m9, m10
+
+    ; release two more registers
+    pmaddwd         m6, [pw_1]
+    pmaddwd         m7, [pw_1]
+    pmaddwd         m9, [pw_1]
+    pmaddwd        m10, [pw_1]
+    paddd           m0, m6
+    paddd           m3, m9
+    paddd           m1, m7
+    paddd           m4, m10
+
+    ; bottom line y, b/rnd portion only
+    punpcklwd       m6, m8,  [pw_16384]
+    punpckhwd       m7, m8,  [pw_16384]
+    punpcklwd       m9, m11, [pw_16384]
+    punpckhwd      m10, m11, [pw_16384]
+
+    pmaddwd        m12, [rsp+0*mmsize]
+    pmaddwd        m13, [rsp+0*mmsize]
+    pmaddwd        m14, [rsp+0*mmsize]
+    pmaddwd        m15, [rsp+0*mmsize]
+    pmaddwd         m6, [rsp+1*mmsize]
+    pmaddwd         m7, [rsp+1*mmsize]
+    pmaddwd         m9, [rsp+1*mmsize]
+    pmaddwd        m10, [rsp+1*mmsize]
+    paddd          m12, m6
+    paddd          m13, m7
+    paddd          m14, m9
+    paddd          m15, m10
+    psrad          m12, %%sh
+    psrad          m13, %%sh
+    psrad          m14, %%sh
+    psrad          m15, %%sh
+    packssdw       m12, m13
+    packssdw       m14, m15
+    lea           tmpq, [yq+ysq]
+%if %1 == 8
+    packuswb       m12, m14
+    movu   [tmpq+xq*2], m12
+%else
+    pxor           m15, m15
+    CLIPW          m12, m15, [pw_ %+ %%maxval]
+    CLIPW          m14, m15, [pw_ %+ %%maxval]
+    movu   [tmpq+xq*4], m12
+    movu [tmpq+xq*4+mmsize], m14
+%endif
+
+    ; complete subsampling of r/g/b pixels for u/v
+    pmaddwd         m8, [pw_1]
+    pmaddwd        m11, [pw_1]
+    paddd           m2, m8
+    paddd           m5, m11
+    paddd           m0, [pd_2]
+    paddd           m1, [pd_2]
+    paddd           m2, [pd_2]
+    paddd           m3, [pd_2]
+    paddd           m4, [pd_2]
+    paddd           m5, [pd_2]
+    psrad           m0, 2
+    psrad           m1, 2
+    psrad           m2, 2
+    psrad           m3, 2
+    psrad           m4, 2
+    psrad           m5, 2
+%else ; %3 != 1
+    paddd           m0, [pd_1]
+    paddd           m1, [pd_1]
+    paddd           m2, [pd_1]
+    paddd           m3, [pd_1]
+    paddd           m4, [pd_1]
+    paddd           m5, [pd_1]
+    psrad           m0, 1
+    psrad           m1, 1
+    psrad           m2, 1
+    psrad           m3, 1
+    psrad           m4, 1
+    psrad           m5, 1
+%endif ; %3 ==/!= 1
+    packssdw        m0, m3
+    packssdw        m1, m4
+    packssdw        m2, m5
+%endif ; %2 == 1
+
+    ; convert u/v pixels
+    SBUTTERFLY   wd, 0, 1, 6
+    punpckhwd       m6, m2, [pw_16384]
+    punpcklwd       m2, [pw_16384]
+
+    pmaddwd         m7, m0, [rsp+2*mmsize]
+    pmaddwd         m8, m1, [rsp+2*mmsize]
+    pmaddwd         m9, m2, [rsp+3*mmsize]
+    pmaddwd        m10, m6, [rsp+3*mmsize]
+    pmaddwd         m0, [rsp+4*mmsize]
+    pmaddwd         m1, [rsp+4*mmsize]
+    pmaddwd         m2, [rsp+5*mmsize]
+    pmaddwd         m6, [rsp+5*mmsize]
+    paddd           m7, m9
+    paddd           m8, m10
+    paddd           m0, m2
+    paddd           m1, m6
+    psrad           m7, %%sh
+    psrad           m8, %%sh
+    psrad           m0, %%sh
+    psrad           m1, %%sh
+    packssdw        m7, m8
+    packssdw        m0, m1
+%if %2 == 1
+%if %1 == 8
+    packuswb        m7, m0
+    movh       [uq+xq], m7
+    movhps     [vq+xq], m7
+%else
+    CLIPW           m7, m15, [pw_ %+ %%maxval]
+    CLIPW           m0, m15, [pw_ %+ %%maxval]
+    movu     [uq+xq*2], m7
+    movu     [vq+xq*2], m0
+%endif
+%else ; %2 != 1
+    ; second set of u/v pixels
+    SBUTTERFLY   wd, 3, 4, 6
+    punpckhwd       m6, m5, [pw_16384]
+    punpcklwd       m5, [pw_16384]
+
+    pmaddwd         m8, m3, [rsp+2*mmsize]
+    pmaddwd         m9, m4, [rsp+2*mmsize]
+    pmaddwd        m10, m5, [rsp+3*mmsize]
+    pmaddwd        m11, m6, [rsp+3*mmsize]
+    pmaddwd         m3, [rsp+4*mmsize]
+    pmaddwd         m4, [rsp+4*mmsize]
+    pmaddwd         m5, [rsp+5*mmsize]
+    pmaddwd         m6, [rsp+5*mmsize]
+    paddd           m8, m10
+    paddd           m9, m11
+    paddd           m3, m5
+    paddd           m4, m6
+    psrad           m8, %%sh
+    psrad           m9, %%sh
+    psrad           m3, %%sh
+    psrad           m4, %%sh
+    packssdw        m8, m9
+    packssdw        m3, m4
+
+%if %1 == 8
+    packuswb        m7, m8
+    packuswb        m0, m3
+    movu       [uq+xq], m7
+    movu       [vq+xq], m0
+%else
+    CLIPW           m7, m15, [pw_ %+ %%maxval]
+    CLIPW           m0, m15, [pw_ %+ %%maxval]
+    CLIPW           m8, m15, [pw_ %+ %%maxval]
+    CLIPW           m3, m15, [pw_ %+ %%maxval]
+    movu     [uq+xq*2], m7
+    movu [uq+xq*2+mmsize], m8
+    movu     [vq+xq*2], m0
+    movu [vq+xq*2+mmsize], m3
+%endif
+%endif ; %2 ==/!= 1
+
+    add             xq, mmsize >> %2
+    cmp             xd, wwd
+    jl .loop_h
+
+%if %3 == 0
+    add             yq, ysq
+%else ; %3 != 0
+    lea             yq, [yq+ysq*2]
+%endif ; %3 ==/!= 0
+    add             uq, usq
+    add             vq, vsq
+    lea             rq, [rq+rgbsq*(2<<%3)]
+    lea             gq, [gq+rgbsq*(2<<%3)]
+    lea             bq, [bq+rgbsq*(2<<%3)]
+    dec             hd
+    jg .loop_v
+
+    RET
+%endmacro
+
+%macro RGB2YUV_FNS 2
+RGB2YUV_FN  8, %1, %2
+RGB2YUV_FN 10, %1, %2
+RGB2YUV_FN 12, %1, %2
+%endmacro
+
+INIT_XMM sse2
+RGB2YUV_FNS 0, 0
+RGB2YUV_FNS 1, 0
+RGB2YUV_FNS 1, 1
+
+; void ff_multiply3x3_sse2(int16_t *data[3], ptrdiff_t stride,
+;                          int w, int h, const int16_t coeff[3][3][8])
+INIT_XMM sse2
+cglobal multiply3x3, 5, 7, 16, data, stride, ww, h, c
+    movh            m0, [cq+  0]
+    movh            m1, [cq+ 32]
+    movh            m2, [cq+ 48]
+    movh            m3, [cq+ 80]
+    movh            m4, [cq+ 96]
+    movh            m5, [cq+128]
+    punpcklwd       m0, [cq+ 16]
+    punpcklwd       m1, [pw_8192]
+    punpcklwd       m2, [cq+ 64]
+    punpcklwd       m3, [pw_8192]
+    punpcklwd       m4, [cq+112]
+    punpcklwd       m5, [pw_8192]
+
+    DEFINE_ARGS data0, stride, ww, h, data1, data2, x
+    shl        strideq, 1
+    mov         data1q, [data0q+gprsize*1]
+    mov         data2q, [data0q+gprsize*2]
+    mov         data0q, [data0q+gprsize*0]
+
+.loop_v:
+    xor             xd, xd
+
+.loop_h:
+    mova            m6, [data0q+xq*2]
+    mova            m7, [data1q+xq*2]
+    mova            m8, [data2q+xq*2]
+    SBUTTERFLY   wd, 6, 7, 9
+    punpckhwd       m9, m8, [pw_1]
+    punpcklwd       m8, [pw_1]
+
+    pmaddwd        m10, m6, m0
+    pmaddwd        m11, m7, m0
+    pmaddwd        m12, m8, m1
+    pmaddwd        m13, m9, m1
+    paddd          m10, m12
+    paddd          m11, m13
+    psrad          m10, 14
+    psrad          m11, 14
+
+    pmaddwd        m12, m6, m2
+    pmaddwd        m13, m7, m2
+    pmaddwd        m14, m8, m3
+    pmaddwd        m15, m9, m3
+    paddd          m12, m14
+    paddd          m13, m15
+    psrad          m12, 14
+    psrad          m13, 14
+
+    pmaddwd         m6, m4
+    pmaddwd         m7, m4
+    pmaddwd         m8, m5
+    pmaddwd         m9, m5
+    paddd           m6, m8
+    paddd           m7, m9
+    psrad           m6, 14
+    psrad           m7, 14
+
+    packssdw       m10, m11
+    packssdw       m12, m13
+    packssdw        m6, m7
+
+    mova [data0q+xq*2], m10
+    mova [data1q+xq*2], m12
+    mova [data2q+xq*2], m6
+
+    add             xd, mmsize / 2
+    cmp             xd, wwd
+    jl .loop_h
+
+    add         data0q, strideq
+    add         data1q, strideq
+    add         data2q, strideq
+    dec             hd
+    jg .loop_v
+
+    RET
+%endif
diff --git a/libavfilter/x86/colorspacedsp_init.c b/libavfilter/x86/colorspacedsp_init.c
new file mode 100644
index 0000000..b5006ac
--- /dev/null
+++ b/libavfilter/x86/colorspacedsp_init.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * 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/x86/cpu.h"
+
+#include "libavfilter/colorspacedsp.h"
+
+#define decl_yuv2yuv_fn(t) \
+void ff_yuv2yuv_##t##_sse2(uint8_t *yuv_out[3], const ptrdiff_t yuv_out_stride[3], \
+                           uint8_t *yuv_in[3], const ptrdiff_t yuv_in_stride[3], \
+                           int w, int h, const int16_t yuv2yuv_coeffs[3][3][8], \
+                           const int16_t yuv_offset[2][8])
+
+#define decl_yuv2yuv_fns(ss) \
+decl_yuv2yuv_fn(ss##p8to8); \
+decl_yuv2yuv_fn(ss##p10to8); \
+decl_yuv2yuv_fn(ss##p12to8); \
+decl_yuv2yuv_fn(ss##p8to10); \
+decl_yuv2yuv_fn(ss##p10to10); \
+decl_yuv2yuv_fn(ss##p12to10); \
+decl_yuv2yuv_fn(ss##p8to12); \
+decl_yuv2yuv_fn(ss##p10to12); \
+decl_yuv2yuv_fn(ss##p12to12)
+
+decl_yuv2yuv_fns(420);
+decl_yuv2yuv_fns(422);
+decl_yuv2yuv_fns(444);
+
+#define decl_yuv2rgb_fn(t) \
+void ff_yuv2rgb_##t##_sse2(int16_t *rgb_out[3], ptrdiff_t rgb_stride, \
+                           uint8_t *yuv_in[3], const ptrdiff_t yuv_stride[3], \
+                           int w, int h, const int16_t coeff[3][3][8], \
+                           const int16_t yuv_offset[8])
+
+#define decl_yuv2rgb_fns(ss) \
+decl_yuv2rgb_fn(ss##p8); \
+decl_yuv2rgb_fn(ss##p10); \
+decl_yuv2rgb_fn(ss##p12)
+
+decl_yuv2rgb_fns(420);
+decl_yuv2rgb_fns(422);
+decl_yuv2rgb_fns(444);
+
+#define decl_rgb2yuv_fn(t) \
+void ff_rgb2yuv_##t##_sse2(uint8_t *yuv_out[3], const ptrdiff_t yuv_stride[3], \
+                           int16_t *rgb_in[3], ptrdiff_t rgb_stride, \
+                           int w, int h, const int16_t coeff[3][3][8], \
+                           const int16_t yuv_offset[8])
+
+#define decl_rgb2yuv_fns(ss) \
+decl_rgb2yuv_fn(ss##p8); \
+decl_rgb2yuv_fn(ss##p10); \
+decl_rgb2yuv_fn(ss##p12)
+
+decl_rgb2yuv_fns(420);
+decl_rgb2yuv_fns(422);
+decl_rgb2yuv_fns(444);
+
+void ff_multiply3x3_sse2(int16_t *data[3], ptrdiff_t stride, int w, int h,
+                         const int16_t coeff[3][3][8]);
+
+void ff_colorspacedsp_x86_init(ColorSpaceDSPContext *dsp)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (ARCH_X86_64 && EXTERNAL_SSE2(cpu_flags)) {
+#define assign_yuv2yuv_fns(ss) \
+        dsp->yuv2yuv[BPP_8 ][BPP_8 ][SS_##ss] = ff_yuv2yuv_##ss##p8to8_sse2; \
+        dsp->yuv2yuv[BPP_8 ][BPP_10][SS_##ss] = ff_yuv2yuv_##ss##p8to10_sse2; \
+        dsp->yuv2yuv[BPP_8 ][BPP_12][SS_##ss] = ff_yuv2yuv_##ss##p8to12_sse2; \
+        dsp->yuv2yuv[BPP_10][BPP_8 ][SS_##ss] = ff_yuv2yuv_##ss##p10to8_sse2; \
+        dsp->yuv2yuv[BPP_10][BPP_10][SS_##ss] = ff_yuv2yuv_##ss##p10to10_sse2; \
+        dsp->yuv2yuv[BPP_10][BPP_12][SS_##ss] = ff_yuv2yuv_##ss##p10to12_sse2; \
+        dsp->yuv2yuv[BPP_12][BPP_8 ][SS_##ss] = ff_yuv2yuv_##ss##p12to8_sse2; \
+        dsp->yuv2yuv[BPP_12][BPP_10][SS_##ss] = ff_yuv2yuv_##ss##p12to10_sse2; \
+        dsp->yuv2yuv[BPP_12][BPP_12][SS_##ss] = ff_yuv2yuv_##ss##p12to12_sse2
+
+        assign_yuv2yuv_fns(420);
+        assign_yuv2yuv_fns(422);
+        assign_yuv2yuv_fns(444);
+
+#define assign_yuv2rgb_fns(ss) \
+        dsp->yuv2rgb[BPP_8 ][SS_##ss] = ff_yuv2rgb_##ss##p8_sse2; \
+        dsp->yuv2rgb[BPP_10][SS_##ss] = ff_yuv2rgb_##ss##p10_sse2; \
+        dsp->yuv2rgb[BPP_12][SS_##ss] = ff_yuv2rgb_##ss##p12_sse2
+
+        assign_yuv2rgb_fns(420);
+        assign_yuv2rgb_fns(422);
+        assign_yuv2rgb_fns(444);
+
+#define assign_rgb2yuv_fns(ss) \
+        dsp->rgb2yuv[BPP_8 ][SS_##ss] = ff_rgb2yuv_##ss##p8_sse2; \
+        dsp->rgb2yuv[BPP_10][SS_##ss] = ff_rgb2yuv_##ss##p10_sse2; \
+        dsp->rgb2yuv[BPP_12][SS_##ss] = ff_rgb2yuv_##ss##p12_sse2
+
+        assign_rgb2yuv_fns(420);
+        assign_rgb2yuv_fns(422);
+        assign_rgb2yuv_fns(444);
+
+        dsp->multiply3x3 = ff_multiply3x3_sse2;
+    }
+}
diff --git a/libavfilter/x86/vf_blend.asm b/libavfilter/x86/vf_blend.asm
index 47471aa..33b1ad1 100644
--- a/libavfilter/x86/vf_blend.asm
+++ b/libavfilter/x86/vf_blend.asm
@@ -24,6 +24,7 @@
 
 SECTION_RODATA
 
+ps_255: times 4 dd 255.0
 pw_1:   times 8 dw 1
 pw_128: times 8 dw 128
 pw_255: times 8 dw 255
@@ -218,6 +219,35 @@ BLEND_INIT hardmix, 5
     jl .loop
 BLEND_END
 
+BLEND_INIT divide, 4
+    pxor       m2, m2
+    mova       m3, [ps_255]
+.nextrow:
+    mov        xq, widthq
+
+    .loop:
+        movd            m0, [topq + xq]      ; 000000xx
+        movd            m1, [bottomq + xq]
+        punpcklbw       m0, m2               ; 00000x0x
+        punpcklbw       m1, m2
+        punpcklwd       m0, m2               ; 000x000x
+        punpcklwd       m1, m2
+
+        cvtdq2ps        m0, m0
+        cvtdq2ps        m1, m1
+        divps           m0, m1               ; a / b
+        mulps           m0, m3               ; a / b * 255
+        minps           m0, m3
+        cvttps2dq       m0, m0
+
+        packssdw        m0, m0               ; 00000x0x
+        packuswb        m0, m0               ; 000000xx
+        movd   [dstq + xq], m0
+        add             xq, mmsize / 4
+
+    jl .loop
+BLEND_END
+
 BLEND_INIT phoenix, 4
     mova       m3, [pb_255]
 .nextrow:
diff --git a/libavfilter/x86/vf_blend_init.c b/libavfilter/x86/vf_blend_init.c
index 555e1e5..96fe3d8 100644
--- a/libavfilter/x86/vf_blend_init.c
+++ b/libavfilter/x86/vf_blend_init.c
@@ -28,7 +28,7 @@ void ff_blend_##name##_##opt(const uint8_t *top, ptrdiff_t top_linesize,       \
                              const uint8_t *bottom, ptrdiff_t bottom_linesize, \
                              uint8_t *dst, ptrdiff_t dst_linesize,             \
                              ptrdiff_t width, ptrdiff_t height,                \
-                             struct FilterParams *param, double *values);
+                             struct FilterParams *param, double *values, int starty);
 
 BLEND_FUNC(addition, sse2)
 BLEND_FUNC(addition128, sse2)
@@ -39,6 +39,7 @@ BLEND_FUNC(difference128, sse2)
 BLEND_FUNC(multiply, sse2)
 BLEND_FUNC(screen, sse2)
 BLEND_FUNC(hardmix, sse2)
+BLEND_FUNC(divide, sse2)
 BLEND_FUNC(lighten, sse2)
 BLEND_FUNC(or, sse2)
 BLEND_FUNC(phoenix, sse2)
@@ -61,6 +62,7 @@ av_cold void ff_blend_init_x86(FilterParams *param, int is_16bit)
         case BLEND_AVERAGE:  param->blend = ff_blend_average_sse2;  break;
         case BLEND_DARKEN:   param->blend = ff_blend_darken_sse2;   break;
         case BLEND_DIFFERENCE128: param->blend = ff_blend_difference128_sse2; break;
+        case BLEND_DIVIDE:   param->blend = ff_blend_divide_sse2;   break;
         case BLEND_HARDMIX:  param->blend = ff_blend_hardmix_sse2;  break;
         case BLEND_LIGHTEN:  param->blend = ff_blend_lighten_sse2;  break;
         case BLEND_MULTIPLY: param->blend = ff_blend_multiply_sse2; break;
diff --git a/libavfilter/x86/vf_bwdif.asm b/libavfilter/x86/vf_bwdif.asm
new file mode 100644
index 0000000..147b7c6
--- /dev/null
+++ b/libavfilter/x86/vf_bwdif.asm
@@ -0,0 +1,270 @@
+;*****************************************************************************
+;* x86-optimized functions for bwdif filter
+;*
+;* Copyright (C) 2016 Thomas Mundt <loudmax at yahoo.de>
+;*
+;* Based on yadif simd code
+;* Copyright (C) 2006 Michael Niedermayer <michaelni at gmx.at>
+;*               2013 Daniel Kang <daniel.d.kang at gmail.com>
+;*
+;* 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/x86/x86util.asm"
+
+SECTION_RODATA
+
+pw_coefhf:  times 4 dw  1016, 5570
+pw_coefhf1: times 8 dw -3801
+pw_coefsp:  times 4 dw  5077, -981
+pw_splfdif: times 4 dw  -768,  768
+
+SECTION .text
+
+%macro LOAD8 2
+    movh         %1, %2
+    punpcklbw    %1, m7
+%endmacro
+
+%macro LOAD12 2
+    movu         %1, %2
+%endmacro
+
+%macro DISP8 0
+    packuswb     m2, m2
+    movh     [dstq], m2
+%endmacro
+
+%macro DISP12 0
+    CLIPW        m2, m7, m12
+    movu     [dstq], m2
+%endmacro
+
+%macro FILTER 5
+    pxor         m7, m7
+.loop%1:
+    LOAD%4       m0, [curq+t0*%5]
+    LOAD%4       m1, [curq+t1*%5]
+    LOAD%4       m2, [%2]
+    LOAD%4       m3, [%3]
+    mova         m4, m3
+    paddw        m3, m2
+    psubw        m2, m4
+    ABS1         m2, m4
+    mova         m8, m3
+    mova         m9, m2
+    LOAD%4       m3, [prevq+t0*%5]
+    LOAD%4       m4, [prevq+t1*%5]
+    psubw        m3, m0
+    psubw        m4, m1
+    ABS2         m3, m4, m5, m6
+    paddw        m3, m4
+    psrlw        m2, 1
+    psrlw        m3, 1
+    pmaxsw       m2, m3
+    LOAD%4       m3, [nextq+t0*%5]
+    LOAD%4       m4, [nextq+t1*%5]
+    psubw        m3, m0
+    psubw        m4, m1
+    ABS2         m3, m4, m5, m6
+    paddw        m3, m4
+    psrlw        m3, 1
+    pmaxsw       m2, m3
+
+    LOAD%4       m3, [%2+t0*2*%5]
+    LOAD%4       m4, [%3+t0*2*%5]
+    LOAD%4       m5, [%2+t1*2*%5]
+    LOAD%4       m6, [%3+t1*2*%5]
+    paddw        m3, m4
+    paddw        m5, m6
+    mova         m6, m3
+    paddw        m6, m5
+    mova        m10, m6
+    psrlw        m3, 1
+    psrlw        m5, 1
+    psubw        m3, m0
+    psubw        m5, m1
+    mova         m6, m3
+    pminsw       m3, m5
+    pmaxsw       m5, m6
+    mova         m4, m8
+    psraw        m4, 1
+    mova         m6, m4
+    psubw        m6, m0
+    psubw        m4, m1
+    pmaxsw       m3, m6
+    pminsw       m5, m6
+    pmaxsw       m3, m4
+    pminsw       m5, m4
+    mova         m6, m7
+    psubw        m6, m3
+    pmaxsw       m6, m5
+    mova         m3, m2
+    pcmpgtw      m3, m7
+    pand         m6, m3
+    pmaxsw       m2, m6
+    mova        m11, m2
+
+    LOAD%4       m2, [%2+t0*4*%5]
+    LOAD%4       m3, [%3+t0*4*%5]
+    LOAD%4       m4, [%2+t1*4*%5]
+    LOAD%4       m5, [%3+t1*4*%5]
+    paddw        m2, m3
+    paddw        m4, m5
+    paddw        m2, m4
+    mova         m3, m2
+    punpcklwd    m2, m8
+    punpckhwd    m3, m8
+    pmaddwd      m2, [pw_coefhf]
+    pmaddwd      m3, [pw_coefhf]
+    mova         m4, m10
+    mova         m6, m4
+    pmullw       m4, [pw_coefhf1]
+    pmulhw       m6, [pw_coefhf1]
+    mova         m5, m4
+    punpcklwd    m4, m6
+    punpckhwd    m5, m6
+    paddd        m2, m4
+    paddd        m3, m5
+    psrad        m2, 2
+    psrad        m3, 2
+
+    mova         m4, m0
+    paddw        m0, m1
+%if ARCH_X86_64
+    LOAD%4       m5, [curq+t2*%5]
+    LOAD%4       m6, [curq+t3*%5]
+%else
+    mov          r4, prefs3mp
+    mov          r5, mrefs3mp
+    LOAD%4       m5, [curq+t0*%5]
+    LOAD%4       m6, [curq+t1*%5]
+    mov          r4, prefsmp
+    mov          r5, mrefsmp
+%endif
+    paddw        m6, m5
+    psubw        m1, m4
+    ABS1         m1, m4
+    pcmpgtw      m1, m9
+    mova         m4, m1
+    punpcklwd    m1, m4
+    punpckhwd    m4, m4
+    pand         m2, m1
+    pand         m3, m4
+    mova         m5, [pw_splfdif]
+    mova         m7, m5
+    pand         m5, m1
+    pand         m7, m4
+    paddw        m5, [pw_coefsp]
+    paddw        m7, [pw_coefsp]
+    mova         m4, m0
+    punpcklwd    m0, m6
+    punpckhwd    m4, m6
+    pmaddwd      m0, m5
+    pmaddwd      m4, m7
+    paddd        m2, m0
+    paddd        m3, m4
+    psrad        m2, 13
+    psrad        m3, 13
+    packssdw     m2, m3
+
+    mova         m4, m8
+    psraw        m4, 1
+    mova         m0, m11
+    mova         m3, m4
+    psubw        m4, m0
+    paddw        m3, m0
+    CLIPW        m2, m4, m3
+    pxor         m7, m7
+    DISP%4
+
+    add        dstq, STEP
+    add       prevq, STEP
+    add        curq, STEP
+    add       nextq, STEP
+    sub    DWORD wm, mmsize/2
+    jg .loop%1
+%endmacro
+
+%macro PROC 2
+%if ARCH_X86_64
+    movsxd       r5, DWORD prefsm
+    movsxd       r6, DWORD mrefsm
+    movsxd       r7, DWORD prefs3m
+    movsxd       r8, DWORD mrefs3m
+    DECLARE_REG_TMP 5, 6, 7, 8
+%else
+    %define m8  [rsp+ 0]
+    %define m9  [rsp+16]
+    %define m10 [rsp+32]
+    %define m11 [rsp+48]
+    mov          r4, prefsmp
+    mov          r5, mrefsmp
+    DECLARE_REG_TMP 4, 5
+%endif
+    cmp DWORD paritym, 0
+    je .parity0
+    FILTER 1, prevq, curq, %1, %2
+    jmp .ret
+.parity0:
+    FILTER 0, curq, nextq, %1, %2
+.ret:
+    RET
+%endmacro
+
+%macro BWDIF 0
+%if ARCH_X86_64
+cglobal bwdif_filter_line, 4, 9, 12, 0, dst, prev, cur, next, w, prefs, \
+                                        mrefs, prefs2, mrefs2, prefs3, mrefs3, \
+                                        prefs4, mrefs4, parity, clip_max
+%else
+cglobal bwdif_filter_line, 4, 6, 8, 64, dst, prev, cur, next, w, prefs, \
+                                        mrefs, prefs2, mrefs2, prefs3, mrefs3, \
+                                        prefs4, mrefs4, parity, clip_max
+%endif
+    %define STEP mmsize/2
+    PROC 8, 1
+
+%if ARCH_X86_64
+cglobal bwdif_filter_line_12bit, 4, 9, 13, 0, dst, prev, cur, next, w, \
+                                              prefs, mrefs, prefs2, mrefs2, \
+                                              prefs3, mrefs3, prefs4, \
+                                              mrefs4, parity, clip_max
+    movd        m12, DWORD clip_maxm
+    SPLATW      m12, m12, 0
+%else
+cglobal bwdif_filter_line_12bit, 4, 6, 8, 80, dst, prev, cur, next, w, \
+                                              prefs, mrefs, prefs2, mrefs2, \
+                                              prefs3, mrefs3, prefs4, \
+                                              mrefs4, parity, clip_max
+    %define m12 [rsp+64]
+    movd         m0, DWORD clip_maxm
+    SPLATW       m0, m0, 0
+    mova        m12, m0
+%endif
+    %define STEP mmsize
+    PROC 12, 2
+%endmacro
+
+INIT_XMM ssse3
+BWDIF
+INIT_XMM sse2
+BWDIF
+%if ARCH_X86_32
+INIT_MMX mmxext
+BWDIF
+%endif
diff --git a/libavfilter/x86/vf_bwdif_init.c b/libavfilter/x86/vf_bwdif_init.c
new file mode 100644
index 0000000..1cb8438
--- /dev/null
+++ b/libavfilter/x86/vf_bwdif_init.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 Thomas Mundt <loudmax at yahoo.de>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/mem.h"
+#include "libavutil/x86/asm.h"
+#include "libavutil/x86/cpu.h"
+#include "libavfilter/bwdif.h"
+
+void ff_bwdif_filter_line_mmxext(void *dst, void *prev, void *cur, void *next,
+                                 int w, int prefs, int mrefs, int prefs2,
+                                 int mrefs2, int prefs3, int mrefs3, int prefs4,
+                                 int mrefs4, int parity, int clip_max);
+void ff_bwdif_filter_line_sse2(void *dst, void *prev, void *cur, void *next,
+                               int w, int prefs, int mrefs, int prefs2,
+                               int mrefs2, int prefs3, int mrefs3, int prefs4,
+                               int mrefs4, int parity, int clip_max);
+void ff_bwdif_filter_line_ssse3(void *dst, void *prev, void *cur, void *next,
+                                int w, int prefs, int mrefs, int prefs2,
+                                int mrefs2, int prefs3, int mrefs3, int prefs4,
+                                int mrefs4, int parity, int clip_max);
+
+void ff_bwdif_filter_line_12bit_mmxext(void *dst, void *prev, void *cur, void *next,
+                                       int w, int prefs, int mrefs, int prefs2,
+                                       int mrefs2, int prefs3, int mrefs3, int prefs4,
+                                       int mrefs4, int parity, int clip_max);
+void ff_bwdif_filter_line_12bit_sse2(void *dst, void *prev, void *cur, void *next,
+                                     int w, int prefs, int mrefs, int prefs2,
+                                     int mrefs2, int prefs3, int mrefs3, int prefs4,
+                                     int mrefs4, int parity, int clip_max);
+void ff_bwdif_filter_line_12bit_ssse3(void *dst, void *prev, void *cur, void *next,
+                                      int w, int prefs, int mrefs, int prefs2,
+                                      int mrefs2, int prefs3, int mrefs3, int prefs4,
+                                      int mrefs4, int parity, int clip_max);
+
+av_cold void ff_bwdif_init_x86(BWDIFContext *bwdif)
+{
+    int cpu_flags = av_get_cpu_flags();
+    int bit_depth = (!bwdif->csp) ? 8 : bwdif->csp->comp[0].depth;
+
+    if (bit_depth <= 8) {
+#if ARCH_X86_32
+        if (EXTERNAL_MMXEXT(cpu_flags))
+            bwdif->filter_line = ff_bwdif_filter_line_mmxext;
+#endif /* ARCH_X86_32 */
+        if (EXTERNAL_SSE2(cpu_flags))
+            bwdif->filter_line = ff_bwdif_filter_line_sse2;
+        if (EXTERNAL_SSSE3(cpu_flags))
+            bwdif->filter_line = ff_bwdif_filter_line_ssse3;
+    } else if (bit_depth <= 12) {
+#if ARCH_X86_32
+        if (EXTERNAL_MMXEXT(cpu_flags))
+            bwdif->filter_line = ff_bwdif_filter_line_12bit_mmxext;
+#endif /* ARCH_X86_32 */
+        if (EXTERNAL_SSE2(cpu_flags))
+            bwdif->filter_line = ff_bwdif_filter_line_12bit_sse2;
+        if (EXTERNAL_SSSE3(cpu_flags))
+            bwdif->filter_line = ff_bwdif_filter_line_12bit_ssse3;
+    }
+}
diff --git a/libavfilter/x86/vf_gradfun_init.c b/libavfilter/x86/vf_gradfun_init.c
index c638a05..3f51562 100644
--- a/libavfilter/x86/vf_gradfun_init.c
+++ b/libavfilter/x86/vf_gradfun_init.c
@@ -22,7 +22,6 @@
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
 #include "libavutil/mem.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavfilter/gradfun.h"
 
diff --git a/libavfilter/x86/vf_interlace_init.c b/libavfilter/x86/vf_interlace_init.c
index 68ee47d..52a22f8 100644
--- a/libavfilter/x86/vf_interlace_init.c
+++ b/libavfilter/x86/vf_interlace_init.c
@@ -22,7 +22,6 @@
 #include "libavutil/cpu.h"
 #include "libavutil/internal.h"
 #include "libavutil/mem.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 
 #include "libavfilter/interlace.h"
diff --git a/libavfilter/x86/vf_yadif_init.c b/libavfilter/x86/vf_yadif_init.c
index c36a2d0..c39bc44 100644
--- a/libavfilter/x86/vf_yadif_init.c
+++ b/libavfilter/x86/vf_yadif_init.c
@@ -21,7 +21,6 @@
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
 #include "libavutil/mem.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavfilter/yadif.h"
 
diff --git a/libavformat/3dostr.c b/libavformat/3dostr.c
index 5325a03..3668e5f 100644
--- a/libavformat/3dostr.c
+++ b/libavformat/3dostr.c
@@ -61,17 +61,17 @@ static int threedostr_read_header(AVFormatContext *s)
             if (!st)
                 return AVERROR(ENOMEM);
 
-            st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-            st->codec->sample_rate = avio_rb32(s->pb);
-            st->codec->channels    = avio_rb32(s->pb);
-            if (st->codec->channels <= 0)
+            st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->sample_rate = avio_rb32(s->pb);
+            st->codecpar->channels    = avio_rb32(s->pb);
+            if (st->codecpar->channels <= 0)
                 return AVERROR_INVALIDDATA;
             codec                  = avio_rl32(s->pb);
             avio_skip(s->pb, 4);
             if (ctrl_size == 20 || ctrl_size == 3 || ctrl_size == -1)
-                st->duration       = (avio_rb32(s->pb) - 1) / st->codec->channels;
+                st->duration       = (avio_rb32(s->pb) - 1) / st->codecpar->channels;
             else
-                st->duration       = avio_rb32(s->pb) * 16 / st->codec->channels;
+                st->duration       = avio_rb32(s->pb) * 16 / st->codecpar->channels;
             size -= 56;
             found_shdr = 1;
             break;
@@ -95,15 +95,15 @@ static int threedostr_read_header(AVFormatContext *s)
 
     switch (codec) {
     case MKTAG('S','D','X','2'):
-        st->codec->codec_id    = AV_CODEC_ID_SDX2_DPCM;
-        st->codec->block_align = 1 * st->codec->channels;
+        st->codecpar->codec_id    = AV_CODEC_ID_SDX2_DPCM;
+        st->codecpar->block_align = 1 * st->codecpar->channels;
         break;
     default:
         avpriv_request_sample(s, "codec %X", codec);
         return AVERROR_PATCHWELCOME;
     }
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
@@ -142,7 +142,7 @@ static int threedostr_read_packet(AVFormatContext *s, AVPacket *pkt)
             ret = av_get_packet(s->pb, pkt, size);
             pkt->pos = pos;
             pkt->stream_index = 0;
-            pkt->duration = size / st->codec->channels;
+            pkt->duration = size / st->codecpar->channels;
             size = 0;
             found_ssmp = 1;
             break;
diff --git a/libavformat/4xm.c b/libavformat/4xm.c
index 70f0def..8a50778 100644
--- a/libavformat/4xm.c
+++ b/libavformat/4xm.c
@@ -1,6 +1,6 @@
 /*
  * 4X Technologies .4xm File Demuxer (no muxer)
- * Copyright (c) 2003  The FFmpeg Project
+ * Copyright (c) 2003  The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -108,16 +108,16 @@ static int parse_vtrk(AVFormatContext *s,
 
     fourxm->video_stream_index = st->index;
 
-    st->codec->codec_type     = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id       = AV_CODEC_ID_4XM;
+    st->codecpar->codec_type     = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id       = AV_CODEC_ID_4XM;
 
-    st->codec->extradata      = av_mallocz(4 + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!st->codec->extradata)
+    st->codecpar->extradata      = av_mallocz(4 + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!st->codecpar->extradata)
         return AVERROR(ENOMEM);
-    st->codec->extradata_size = 4;
-    AV_WL32(st->codec->extradata, AV_RL32(buf + 16));
-    st->codec->width  = AV_RL32(buf + 36);
-    st->codec->height = AV_RL32(buf + 40);
+    st->codecpar->extradata_size = 4;
+    AV_WL32(st->codecpar->extradata, AV_RL32(buf + 16));
+    st->codecpar->width  = AV_RL32(buf + 36);
+    st->codecpar->height = AV_RL32(buf + 40);
 
     return 0;
 }
@@ -173,23 +173,23 @@ static int parse_strk(AVFormatContext *s,
 
     fourxm->tracks[track].stream_index = st->index;
 
-    st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_tag             = 0;
-    st->codec->channels              = fourxm->tracks[track].channels;
-    st->codec->sample_rate           = fourxm->tracks[track].sample_rate;
-    st->codec->bits_per_coded_sample = fourxm->tracks[track].bits;
-    st->codec->bit_rate              = st->codec->channels *
-                                       st->codec->sample_rate *
-                                       st->codec->bits_per_coded_sample;
-    st->codec->block_align           = st->codec->channels *
-                                       st->codec->bits_per_coded_sample;
+    st->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_tag             = 0;
+    st->codecpar->channels              = fourxm->tracks[track].channels;
+    st->codecpar->sample_rate           = fourxm->tracks[track].sample_rate;
+    st->codecpar->bits_per_coded_sample = fourxm->tracks[track].bits;
+    st->codecpar->bit_rate              = st->codecpar->channels *
+                                          st->codecpar->sample_rate *
+                                          st->codecpar->bits_per_coded_sample;
+    st->codecpar->block_align           = st->codecpar->channels *
+                                          st->codecpar->bits_per_coded_sample;
 
     if (fourxm->tracks[track].adpcm){
-        st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM;
-    } else if (st->codec->bits_per_coded_sample == 8) {
-        st->codec->codec_id = AV_CODEC_ID_PCM_U8;
+        st->codecpar->codec_id = AV_CODEC_ID_ADPCM_4XM;
+    } else if (st->codecpar->bits_per_coded_sample == 8) {
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
     } else
-        st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
 
     return 0;
 }
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 35a383d..c49f9de 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -19,11 +19,16 @@ OBJS = allformats.o         \
        options.o            \
        os_support.o         \
        qtpalette.o          \
+       protocols.o          \
        riff.o               \
        sdp.o                \
        url.o                \
        utils.o              \
 
+OBJS-$(HAVE_LIBC_MSVCRT)                 += file_open.o
+
+# subsystems
+OBJS-$(CONFIG_ISO_MEDIA)                 += isom.o
 OBJS-$(CONFIG_NETWORK)                   += network.o
 OBJS-$(CONFIG_RIFFDEC)                   += riffdec.o
 OBJS-$(CONFIG_RIFFENC)                   += riffenc.o
@@ -51,12 +56,13 @@ OBJS-$(CONFIG_RTPDEC)                    += rdt.o                       \
                                             rtpdec_qdm2.o               \
                                             rtpdec_qt.o                 \
                                             rtpdec_svq3.o               \
+                                            rtpdec_vc2hq.o              \
                                             rtpdec_vp8.o                \
                                             rtpdec_vp9.o                \
-                                            rtpdec_xiph.o               \
-                                            srtp.o
+                                            rtpdec_xiph.o
 OBJS-$(CONFIG_RTPENC_CHAIN)              += rtpenc_chain.o rtp.o
 OBJS-$(CONFIG_SHARED)                    += log2_tab.o golomb_tab.o
+OBJS-$(CONFIG_SRTP)                      += srtp.o
 
 # muxers/demuxers
 OBJS-$(CONFIG_A64_MUXER)                 += a64.o rawenc.o
@@ -69,15 +75,16 @@ OBJS-$(CONFIG_ACT_DEMUXER)               += act.o
 OBJS-$(CONFIG_ADF_DEMUXER)               += bintext.o sauce.o
 OBJS-$(CONFIG_ADP_DEMUXER)               += adp.o
 OBJS-$(CONFIG_ADS_DEMUXER)               += ads.o
-OBJS-$(CONFIG_ADX_DEMUXER)               += adxdec.o
-OBJS-$(CONFIG_ADX_MUXER)                 += rawenc.o
 OBJS-$(CONFIG_ADTS_MUXER)                += adtsenc.o apetag.o img2.o \
                                             id3v2enc.o
+OBJS-$(CONFIG_ADX_DEMUXER)               += adxdec.o
+OBJS-$(CONFIG_ADX_MUXER)                 += rawenc.o
 OBJS-$(CONFIG_AEA_DEMUXER)               += aea.o pcm.o
 OBJS-$(CONFIG_AFC_DEMUXER)               += afc.o
 OBJS-$(CONFIG_AIFF_DEMUXER)              += aiffdec.o pcm.o isom.o \
                                             mov_chan.o
 OBJS-$(CONFIG_AIFF_MUXER)                += aiffenc.o isom.o id3v2enc.o
+OBJS-$(CONFIG_AIX_DEMUXER)               += aixdec.o
 OBJS-$(CONFIG_AMR_DEMUXER)               += amr.o
 OBJS-$(CONFIG_AMR_MUXER)                 += amr.o
 OBJS-$(CONFIG_ANM_DEMUXER)               += anm.o
@@ -90,19 +97,19 @@ OBJS-$(CONFIG_ASF_DEMUXER)               += asfdec_f.o asf.o asfcrypt.o \
                                             avlanguage.o
 OBJS-$(CONFIG_ASF_O_DEMUXER)             += asfdec_o.o asf.o asfcrypt.o \
                                             avlanguage.o
-OBJS-$(CONFIG_ASF_MUXER)                 += asfenc.o asf.o
+OBJS-$(CONFIG_ASF_MUXER)                 += asfenc.o asf.o avlanguage.o
 OBJS-$(CONFIG_ASS_DEMUXER)               += assdec.o subtitles.o
 OBJS-$(CONFIG_ASS_MUXER)                 += assenc.o
 OBJS-$(CONFIG_AST_DEMUXER)               += ast.o astdec.o
 OBJS-$(CONFIG_AST_MUXER)                 += ast.o astenc.o
 OBJS-$(CONFIG_AU_DEMUXER)                += au.o pcm.o
 OBJS-$(CONFIG_AU_MUXER)                  += au.o rawenc.o
-OBJS-$(CONFIG_AVI_DEMUXER)               += avidec.o isom.o
-OBJS-$(CONFIG_AVI_MUXER)                 += avienc.o mpegtsenc.o avlanguage.o
+OBJS-$(CONFIG_AVI_DEMUXER)               += avidec.o
+OBJS-$(CONFIG_AVI_MUXER)                 += avienc.o mpegtsenc.o avlanguage.o rawutils.o
 OBJS-$(CONFIG_AVISYNTH)                  += avisynth.o
 OBJS-$(CONFIG_AVM2_MUXER)                += swfenc.o swf.o
 OBJS-$(CONFIG_AVR_DEMUXER)               += avr.o pcm.o
-OBJS-$(CONFIG_AVS_DEMUXER)               += avs.o vocdec.o voc.o
+OBJS-$(CONFIG_AVS_DEMUXER)               += avs.o voc_packet.o vocdec.o voc.o
 OBJS-$(CONFIG_BETHSOFTVID_DEMUXER)       += bethsoftvid.o
 OBJS-$(CONFIG_BFI_DEMUXER)               += bfi.o
 OBJS-$(CONFIG_BINK_DEMUXER)              += bink.o
@@ -113,9 +120,9 @@ OBJS-$(CONFIG_BMV_DEMUXER)               += bmv.o
 OBJS-$(CONFIG_BOA_DEMUXER)               += boadec.o
 OBJS-$(CONFIG_BFSTM_DEMUXER)             += brstm.o
 OBJS-$(CONFIG_BRSTM_DEMUXER)             += brstm.o
-OBJS-$(CONFIG_C93_DEMUXER)               += c93.o vocdec.o voc.o
+OBJS-$(CONFIG_C93_DEMUXER)               += c93.o voc_packet.o vocdec.o voc.o
 OBJS-$(CONFIG_CAF_DEMUXER)               += cafdec.o caf.o mov.o mov_chan.o \
-                                            isom.o replaygain.o
+                                            replaygain.o
 OBJS-$(CONFIG_CAF_MUXER)                 += cafenc.o caf.o riff.o isom.o
 OBJS-$(CONFIG_CAVSVIDEO_DEMUXER)         += cavsvideodec.o rawdec.o
 OBJS-$(CONFIG_CAVSVIDEO_MUXER)           += rawenc.o
@@ -126,7 +133,7 @@ OBJS-$(CONFIG_CONCAT_DEMUXER)            += concatdec.o
 OBJS-$(CONFIG_CRC_MUXER)                 += crcenc.o
 OBJS-$(CONFIG_DATA_DEMUXER)              += rawdec.o
 OBJS-$(CONFIG_DATA_MUXER)                += rawdec.o
-OBJS-$(CONFIG_DASH_MUXER)                += dashenc.o isom.o
+OBJS-$(CONFIG_DASH_MUXER)                += dashenc.o
 OBJS-$(CONFIG_DAUD_DEMUXER)              += dauddec.o
 OBJS-$(CONFIG_DAUD_MUXER)                += daudenc.o
 OBJS-$(CONFIG_DCSTR_DEMUXER)             += dcstr.o
@@ -144,6 +151,7 @@ OBJS-$(CONFIG_DTS_MUXER)                 += rawenc.o
 OBJS-$(CONFIG_DV_DEMUXER)                += dv.o
 OBJS-$(CONFIG_DV_MUXER)                  += dvenc.o
 OBJS-$(CONFIG_DVBSUB_DEMUXER)            += dvbsub.o
+OBJS-$(CONFIG_DVBTXT_DEMUXER)            += dvbtxt.o
 OBJS-$(CONFIG_DXA_DEMUXER)               += dxa.o
 OBJS-$(CONFIG_EA_CDATA_DEMUXER)          += eacdata.o
 OBJS-$(CONFIG_EA_DEMUXER)                += electronicarts.o
@@ -169,12 +177,14 @@ OBJS-$(CONFIG_LIVE_FLV_DEMUXER)          += flvdec.o
 OBJS-$(CONFIG_FLV_MUXER)                 += flvenc.o avc.o
 OBJS-$(CONFIG_FOURXM_DEMUXER)            += 4xm.o
 OBJS-$(CONFIG_FRAMECRC_MUXER)            += framecrcenc.o framehash.o
-OBJS-$(CONFIG_FRAMEMD5_MUXER)            += md5enc.o framehash.o
+OBJS-$(CONFIG_FRAMEHASH_MUXER)           += hashenc.o framehash.o
+OBJS-$(CONFIG_FRAMEMD5_MUXER)            += hashenc.o framehash.o
 OBJS-$(CONFIG_FRM_DEMUXER)               += frmdec.o
 OBJS-$(CONFIG_FSB_DEMUXER)               += fsb.o
 OBJS-$(CONFIG_GIF_MUXER)                 += gif.o
 OBJS-$(CONFIG_GIF_DEMUXER)               += gifdec.o
 OBJS-$(CONFIG_GSM_DEMUXER)               += gsmdec.o
+OBJS-$(CONFIG_GSM_MUXER)                 += rawenc.o
 OBJS-$(CONFIG_GXF_DEMUXER)               += gxf.o
 OBJS-$(CONFIG_GXF_MUXER)                 += gxfenc.o audiointerleave.o
 OBJS-$(CONFIG_G722_DEMUXER)              += g722.o rawdec.o
@@ -189,6 +199,7 @@ OBJS-$(CONFIG_H263_DEMUXER)              += h263dec.o rawdec.o
 OBJS-$(CONFIG_H263_MUXER)                += rawenc.o
 OBJS-$(CONFIG_H264_DEMUXER)              += h264dec.o rawdec.o
 OBJS-$(CONFIG_H264_MUXER)                += rawenc.o
+OBJS-$(CONFIG_HASH_MUXER)                += hashenc.o
 OBJS-$(CONFIG_HDS_MUXER)                 += hdsenc.o
 OBJS-$(CONFIG_HEVC_DEMUXER)              += hevcdec.o rawdec.o
 OBJS-$(CONFIG_HEVC_MUXER)                += rawenc.o
@@ -215,8 +226,14 @@ OBJS-$(CONFIG_IMAGE_EXR_PIPE_DEMUXER)     += img2dec.o img2.o
 OBJS-$(CONFIG_IMAGE_J2K_PIPE_DEMUXER)     += img2dec.o img2.o
 OBJS-$(CONFIG_IMAGE_JPEG_PIPE_DEMUXER)    += img2dec.o img2.o
 OBJS-$(CONFIG_IMAGE_JPEGLS_PIPE_DEMUXER)  += img2dec.o img2.o
+OBJS-$(CONFIG_IMAGE_PAM_PIPE_DEMUXER)     += img2dec.o img2.o
+OBJS-$(CONFIG_IMAGE_PBM_PIPE_DEMUXER)     += img2dec.o img2.o
+OBJS-$(CONFIG_IMAGE_PCX_PIPE_DEMUXER)     += img2dec.o img2.o
+OBJS-$(CONFIG_IMAGE_PGMYUV_PIPE_DEMUXER)  += img2dec.o img2.o
+OBJS-$(CONFIG_IMAGE_PGM_PIPE_DEMUXER)     += img2dec.o img2.o
 OBJS-$(CONFIG_IMAGE_PICTOR_PIPE_DEMUXER)  += img2dec.o img2.o
 OBJS-$(CONFIG_IMAGE_PNG_PIPE_DEMUXER)     += img2dec.o img2.o
+OBJS-$(CONFIG_IMAGE_PPM_PIPE_DEMUXER)     += img2dec.o img2.o
 OBJS-$(CONFIG_IMAGE_QDRAW_PIPE_DEMUXER)   += img2dec.o img2.o
 OBJS-$(CONFIG_IMAGE_SGI_PIPE_DEMUXER)     += img2dec.o img2.o
 OBJS-$(CONFIG_IMAGE_SUNRAST_PIPE_DEMUXER) += img2dec.o img2.o
@@ -244,14 +261,14 @@ OBJS-$(CONFIG_LXF_DEMUXER)               += lxfdec.o
 OBJS-$(CONFIG_M4V_DEMUXER)               += m4vdec.o rawdec.o
 OBJS-$(CONFIG_M4V_MUXER)                 += rawenc.o
 OBJS-$(CONFIG_MATROSKA_DEMUXER)          += matroskadec.o matroska.o  \
-                                            isom.o rmsipr.o flac_picture.o \
+                                            rmsipr.o flac_picture.o \
                                             oggparsevorbis.o vorbiscomment.o \
                                             flac_picture.o replaygain.o
 OBJS-$(CONFIG_MATROSKA_MUXER)            += matroskaenc.o matroska.o \
-                                            isom.o avc.o hevc.o \
+                                            avc.o hevc.o \
                                             flacenc_header.o avlanguage.o vorbiscomment.o wv.o \
                                             webmdashenc.o webm_chunk.o
-OBJS-$(CONFIG_MD5_MUXER)                 += md5enc.o
+OBJS-$(CONFIG_MD5_MUXER)                 += hashenc.o
 OBJS-$(CONFIG_MGSTS_DEMUXER)             += mgsts.o
 OBJS-$(CONFIG_MICRODVD_DEMUXER)          += microdvddec.o subtitles.o
 OBJS-$(CONFIG_MICRODVD_MUXER)            += microdvdenc.o
@@ -263,9 +280,10 @@ OBJS-$(CONFIG_MLV_DEMUXER)               += mlvdec.o riffdec.o
 OBJS-$(CONFIG_MM_DEMUXER)                += mm.o
 OBJS-$(CONFIG_MMF_DEMUXER)               += mmf.o
 OBJS-$(CONFIG_MMF_MUXER)                 += mmf.o rawenc.o
-OBJS-$(CONFIG_MOV_DEMUXER)               += mov.o isom.o mov_chan.o replaygain.o
-OBJS-$(CONFIG_MOV_MUXER)                 += movenc.o isom.o avc.o hevc.o \
-                                            movenchint.o mov_chan.o rtp.o movenccenc.o
+OBJS-$(CONFIG_MOV_DEMUXER)               += mov.o mov_chan.o replaygain.o
+OBJS-$(CONFIG_MOV_MUXER)                 += movenc.o avc.o hevc.o vpcc.o \
+                                            movenchint.o mov_chan.o rtp.o \
+                                            movenccenc.o rawutils.o
 OBJS-$(CONFIG_MP2_MUXER)                 += mp3enc.o rawenc.o id3v2enc.o
 OBJS-$(CONFIG_MP3_DEMUXER)               += mp3dec.o replaygain.o
 OBJS-$(CONFIG_MP3_MUXER)                 += mp3enc.o rawenc.o id3v2enc.o
@@ -273,13 +291,13 @@ OBJS-$(CONFIG_MPC_DEMUXER)               += mpc.o apetag.o img2.o
 OBJS-$(CONFIG_MPC8_DEMUXER)              += mpc8.o apetag.o img2.o
 OBJS-$(CONFIG_MPEG1SYSTEM_MUXER)         += mpegenc.o
 OBJS-$(CONFIG_MPEG1VCD_MUXER)            += mpegenc.o
+OBJS-$(CONFIG_MPEG1VIDEO_MUXER)          += rawenc.o
 OBJS-$(CONFIG_MPEG2DVD_MUXER)            += mpegenc.o
-OBJS-$(CONFIG_MPEG2VOB_MUXER)            += mpegenc.o
 OBJS-$(CONFIG_MPEG2SVCD_MUXER)           += mpegenc.o
-OBJS-$(CONFIG_MPEG1VIDEO_MUXER)          += rawenc.o
 OBJS-$(CONFIG_MPEG2VIDEO_MUXER)          += rawenc.o
+OBJS-$(CONFIG_MPEG2VOB_MUXER)            += mpegenc.o
 OBJS-$(CONFIG_MPEGPS_DEMUXER)            += mpeg.o
-OBJS-$(CONFIG_MPEGTS_DEMUXER)            += mpegts.o isom.o
+OBJS-$(CONFIG_MPEGTS_DEMUXER)            += mpegts.o
 OBJS-$(CONFIG_MPEGTS_MUXER)              += mpegtsenc.o
 OBJS-$(CONFIG_MPEGVIDEO_DEMUXER)         += mpegvideodec.o rawdec.o
 OBJS-$(CONFIG_MPJPEG_DEMUXER)            += mpjpegdec.o
@@ -288,7 +306,9 @@ OBJS-$(CONFIG_MPL2_DEMUXER)              += mpl2dec.o subtitles.o
 OBJS-$(CONFIG_MSF_DEMUXER)               += msf.o
 OBJS-$(CONFIG_MPSUB_DEMUXER)             += mpsubdec.o subtitles.o
 OBJS-$(CONFIG_MSNWC_TCP_DEMUXER)         += msnwc_tcp.o
+OBJS-$(CONFIG_MTAF_DEMUXER)              += mtaf.o
 OBJS-$(CONFIG_MTV_DEMUXER)               += mtv.o
+OBJS-$(CONFIG_MUSX_DEMUXER)              += musx.o
 OBJS-$(CONFIG_MV_DEMUXER)                += mvdec.o
 OBJS-$(CONFIG_MVI_DEMUXER)               += mvi.o
 OBJS-$(CONFIG_MXF_DEMUXER)               += mxfdec.o mxf.o
@@ -381,9 +401,9 @@ OBJS-$(CONFIG_RM_MUXER)                  += rmenc.o rm.o
 OBJS-$(CONFIG_ROQ_DEMUXER)               += idroqdec.o
 OBJS-$(CONFIG_ROQ_MUXER)                 += idroqenc.o rawenc.o
 OBJS-$(CONFIG_RSD_DEMUXER)               += rsd.o
+OBJS-$(CONFIG_RPL_DEMUXER)               += rpl.o
 OBJS-$(CONFIG_RSO_DEMUXER)               += rsodec.o rso.o pcm.o
 OBJS-$(CONFIG_RSO_MUXER)                 += rsoenc.o rso.o
-OBJS-$(CONFIG_RPL_DEMUXER)               += rpl.o
 OBJS-$(CONFIG_RTP_MPEGTS_MUXER)          += rtpenc_mpegts.o
 OBJS-$(CONFIG_RTP_MUXER)                 += rtp.o         \
                                             rtpenc_aac.o     \
@@ -396,7 +416,9 @@ OBJS-$(CONFIG_RTP_MUXER)                 += rtp.o         \
                                             rtpenc_jpeg.o \
                                             rtpenc_mpv.o     \
                                             rtpenc.o      \
+                                            rtpenc_vc2hq.o              \
                                             rtpenc_vp8.o  \
+                                            rtpenc_vp9.o                \
                                             rtpenc_xiph.o \
                                             avc.o hevc.o
 OBJS-$(CONFIG_RTSP_DEMUXER)              += rtsp.o rtspdec.o httpauth.o \
@@ -417,7 +439,7 @@ OBJS-$(CONFIG_SINGLEJPEG_MUXER)          += rawenc.o
 OBJS-$(CONFIG_SMACKER_DEMUXER)           += smacker.o
 OBJS-$(CONFIG_SMJPEG_DEMUXER)            += smjpegdec.o smjpeg.o
 OBJS-$(CONFIG_SMJPEG_MUXER)              += smjpegenc.o smjpeg.o
-OBJS-$(CONFIG_SMOOTHSTREAMING_MUXER)     += smoothstreamingenc.o isom.o
+OBJS-$(CONFIG_SMOOTHSTREAMING_MUXER)     += smoothstreamingenc.o
 OBJS-$(CONFIG_SMUSH_DEMUXER)             += smush.o
 OBJS-$(CONFIG_SOL_DEMUXER)               += sol.o pcm.o
 OBJS-$(CONFIG_SOX_DEMUXER)               += soxdec.o pcm.o
@@ -460,7 +482,7 @@ OBJS-$(CONFIG_VC1T_MUXER)                += vc1testenc.o
 OBJS-$(CONFIG_VIVO_DEMUXER)              += vivo.o
 OBJS-$(CONFIG_VMD_DEMUXER)               += sierravmd.o
 OBJS-$(CONFIG_VOBSUB_DEMUXER)            += subtitles.o # mpeg demuxer is in the dependencies
-OBJS-$(CONFIG_VOC_DEMUXER)               += vocdec.o voc.o
+OBJS-$(CONFIG_VOC_DEMUXER)               += vocdec.o voc_packet.o voc.o
 OBJS-$(CONFIG_VOC_MUXER)                 += vocenc.o voc.o
 OBJS-$(CONFIG_VPK_DEMUXER)               += vpk.o
 OBJS-$(CONFIG_VPLAYER_DEMUXER)           += vplayerdec.o subtitles.o
@@ -471,25 +493,22 @@ OBJS-$(CONFIG_WAV_DEMUXER)               += wavdec.o pcm.o
 OBJS-$(CONFIG_WAV_MUXER)                 += wavenc.o
 OBJS-$(CONFIG_WC3_DEMUXER)               += wc3movie.o
 OBJS-$(CONFIG_WEBM_MUXER)                += matroskaenc.o matroska.o \
-                                            isom.o avc.o hevc.o \
+                                            avc.o hevc.o \
                                             flacenc_header.o avlanguage.o \
                                             wv.o vorbiscomment.o \
                                             webmdashenc.o webm_chunk.o
-OBJS-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER)+= matroskadec.o matroska.o  \
-                                            isom.o rmsipr.o flac_picture.o \
-                                            oggparsevorbis.o vorbiscomment.o \
-                                            flac_picture.o replaygain.o
 OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER)  += webmdashenc.o matroska.o
 OBJS-$(CONFIG_WEBM_CHUNK_MUXER)          += webm_chunk.o matroska.o
 OBJS-$(CONFIG_WEBP_MUXER)                += webpenc.o
 OBJS-$(CONFIG_WEBVTT_DEMUXER)            += webvttdec.o subtitles.o
 OBJS-$(CONFIG_WEBVTT_MUXER)              += webvttenc.o
 OBJS-$(CONFIG_WSAUD_DEMUXER)             += westwood_aud.o
+OBJS-$(CONFIG_WSD_DEMUXER)               += wsddec.o rawdec.o
 OBJS-$(CONFIG_WSVQA_DEMUXER)             += westwood_vqa.o
-OBJS-$(CONFIG_WTV_DEMUXER)               += wtvdec.o wtv_common.o asf.o \
-                                            avlanguage.o mpegts.o isom.o
+OBJS-$(CONFIG_WTV_DEMUXER)               += wtvdec.o wtv_common.o \
+                                            asf.o
 OBJS-$(CONFIG_WTV_MUXER)                 += wtvenc.o wtv_common.o \
-                                            mpegtsenc.o asf.o
+                                            asf.o
 OBJS-$(CONFIG_WV_DEMUXER)                += wvdec.o wv.o apetag.o img2.o
 OBJS-$(CONFIG_WVE_DEMUXER)               += wvedec.o pcm.o
 OBJS-$(CONFIG_WV_MUXER)                  += wvenc.o wv.o apetag.o img2.o
@@ -499,8 +518,8 @@ OBJS-$(CONFIG_XMV_DEMUXER)               += xmv.o
 OBJS-$(CONFIG_XVAG_DEMUXER)              += xvag.o
 OBJS-$(CONFIG_XWMA_DEMUXER)              += xwma.o
 OBJS-$(CONFIG_YOP_DEMUXER)               += yop.o
-OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER)        += yuv4mpegenc.o
 OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER)      += yuv4mpegdec.o
+OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER)        += yuv4mpegenc.o
 
 # external libraries
 OBJS-$(CONFIG_CHROMAPRINT_MUXER)         += chromaprint.o
@@ -530,9 +549,9 @@ OBJS-$(CONFIG_HTTP_PROTOCOL)             += http.o httpauth.o urldecode.o
 OBJS-$(CONFIG_HTTPPROXY_PROTOCOL)        += http.o httpauth.o urldecode.o
 OBJS-$(CONFIG_HTTPS_PROTOCOL)            += http.o httpauth.o urldecode.o
 OBJS-$(CONFIG_ICECAST_PROTOCOL)          += icecast.o
+OBJS-$(CONFIG_MD5_PROTOCOL)              += md5proto.o
 OBJS-$(CONFIG_MMSH_PROTOCOL)             += mmsh.o mms.o asf.o
 OBJS-$(CONFIG_MMST_PROTOCOL)             += mmst.o mms.o asf.o
-OBJS-$(CONFIG_MD5_PROTOCOL)              += md5proto.o
 OBJS-$(CONFIG_PIPE_PROTOCOL)             += file.o
 OBJS-$(CONFIG_RTMP_PROTOCOL)             += rtmpproto.o rtmppkt.o
 OBJS-$(CONFIG_RTMPE_PROTOCOL)            += rtmpproto.o rtmppkt.o
@@ -553,8 +572,6 @@ OBJS-$(CONFIG_UDP_PROTOCOL)              += udp.o
 OBJS-$(CONFIG_UDPLITE_PROTOCOL)          += udp.o
 OBJS-$(CONFIG_UNIX_PROTOCOL)             += unix.o
 
-OBJS-$(HAVE_LIBC_MSVCRT)                 += file_open.o
-
 # libavdevice dependencies
 OBJS-$(CONFIG_IEC61883_INDEV)            += dv.o
 
@@ -564,14 +581,14 @@ SLIBOBJS-$(HAVE_GNU_WINDRES)             += avformatres.o
 SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h
 SKIPHEADERS-$(CONFIG_NETWORK)            += network.h rtsp.h
 
-TESTPROGS = async                                                       \
-            seek                                                        \
-            srtp                                                        \
+TESTPROGS = seek                                                        \
             url                                                         \
+#           async                                                       \
 
+TESTPROGS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh
 TESTPROGS-$(CONFIG_MOV_MUXER)            += movenc
 TESTPROGS-$(CONFIG_NETWORK)              += noproxy
-TESTPROGS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh
+TESTPROGS-$(CONFIG_SRTP)                 += srtp
 
 TOOLS     = aviocat                                                     \
             ismindex                                                    \
diff --git a/libavformat/a64.c b/libavformat/a64.c
index a7f93a2..2a0489d 100644
--- a/libavformat/a64.c
+++ b/libavformat/a64.c
@@ -26,7 +26,7 @@
 
 static int a64_write_header(AVFormatContext *s)
 {
-    AVCodecContext *avctx = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     uint8_t header[5] = {
         0x00, //load
         0x40, //address
@@ -35,20 +35,20 @@ static int a64_write_header(AVFormatContext *s)
         0x00  //fps in 50/fps;
     };
 
-    if (avctx->extradata_size < 4) {
+    if (par->extradata_size < 4) {
         av_log(s, AV_LOG_ERROR, "Missing extradata\n");
         return AVERROR_INVALIDDATA;
     }
 
-    switch (avctx->codec_id) {
+    switch (par->codec_id) {
     case AV_CODEC_ID_A64_MULTI:
         header[2] = 0x00;
-        header[3] = AV_RB32(avctx->extradata+0);
+        header[3] = AV_RB32(par->extradata+0);
         header[4] = 2;
         break;
     case AV_CODEC_ID_A64_MULTI5:
         header[2] = 0x01;
-        header[3] = AV_RB32(avctx->extradata+0);
+        header[3] = AV_RB32(par->extradata+0);
         header[4] = 3;
         break;
     default:
diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c
index 1b98e1d..aa23756 100644
--- a/libavformat/aacdec.c
+++ b/libavformat/aacdec.c
@@ -84,9 +84,9 @@ static int adts_aac_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id   = s->iformat->raw_codec_id;
-    st->need_parsing      = AVSTREAM_PARSE_FULL_RAW;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id   = s->iformat->raw_codec_id;
+    st->need_parsing         = AVSTREAM_PARSE_FULL_RAW;
 
     ff_id3v1_read(s);
     if (s->pb->seekable &&
diff --git a/libavformat/aadec.c b/libavformat/aadec.c
index 266a8e8..cf5f3d1 100644
--- a/libavformat/aadec.c
+++ b/libavformat/aadec.c
@@ -173,22 +173,22 @@ static int aa_read_header(AVFormatContext *s)
         av_freep(&c->tea_ctx);
         return AVERROR(ENOMEM);
     }
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     if (!strcmp(codec_name, "mp332")) {
-        st->codec->codec_id = AV_CODEC_ID_MP3;
-        st->codec->sample_rate = 22050;
+        st->codecpar->codec_id = AV_CODEC_ID_MP3;
+        st->codecpar->sample_rate = 22050;
         st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
         st->start_time = 0;
     } else if (!strcmp(codec_name, "acelp85")) {
-        st->codec->codec_id = AV_CODEC_ID_SIPR;
-        st->codec->block_align = 19;
-        st->codec->channels = 1;
-        st->codec->sample_rate = 8500;
+        st->codecpar->codec_id = AV_CODEC_ID_SIPR;
+        st->codecpar->block_align = 19;
+        st->codecpar->channels = 1;
+        st->codecpar->sample_rate = 8500;
     } else if (!strcmp(codec_name, "acelp16")) {
-        st->codec->codec_id = AV_CODEC_ID_SIPR;
-        st->codec->block_align = 20;
-        st->codec->channels = 1;
-        st->codec->sample_rate = 16000;
+        st->codecpar->codec_id = AV_CODEC_ID_SIPR;
+        st->codecpar->block_align = 20;
+        st->codecpar->channels = 1;
+        st->codecpar->sample_rate = 16000;
     }
 
     /* determine, and jump to audio start offset */
diff --git a/libavformat/acm.c b/libavformat/acm.c
index afcafa8..08dd928 100644
--- a/libavformat/acm.c
+++ b/libavformat/acm.c
@@ -41,24 +41,24 @@ static int acm_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id   = AV_CODEC_ID_INTERPLAY_ACM;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id   = AV_CODEC_ID_INTERPLAY_ACM;
 
-    ff_alloc_extradata(st->codec, 14);
-    if (!st->codec->extradata)
+    ff_alloc_extradata(st->codecpar, 14);
+    if (!st->codecpar->extradata)
         return AVERROR(ENOMEM);
-    ret = avio_read(s->pb, st->codec->extradata, 14);
+    ret = avio_read(s->pb, st->codecpar->extradata, 14);
     if (ret < 10)
         return ret < 0 ? ret : AVERROR_EOF;
 
-    st->codec->channels    = AV_RL16(st->codec->extradata +  8);
-    st->codec->sample_rate = AV_RL16(st->codec->extradata + 10);
-    if (st->codec->channels <= 0 || st->codec->sample_rate <= 0)
+    st->codecpar->channels    = AV_RL16(st->codecpar->extradata +  8);
+    st->codecpar->sample_rate = AV_RL16(st->codecpar->extradata + 10);
+    if (st->codecpar->channels <= 0 || st->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
     st->start_time         = 0;
-    st->duration           = AV_RL32(st->codec->extradata +  4) / st->codec->channels;
+    st->duration           = AV_RL32(st->codecpar->extradata +  4) / st->codecpar->channels;
     st->need_parsing       = AVSTREAM_PARSE_FULL_RAW;
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
diff --git a/libavformat/act.c b/libavformat/act.c
index 35aacbc..fe67411 100644
--- a/libavformat/act.c
+++ b/libavformat/act.c
@@ -75,29 +75,29 @@ static int read_header(AVFormatContext *s)
 
     avio_skip(pb, 16);
     size=avio_rl32(pb);
-    ff_get_wav_header(s, pb, st->codec, size, 0);
+    ff_get_wav_header(s, pb, st->codecpar, size, 0);
 
     /*
       8000Hz (Fine-rec) file format has 10 bytes long
       packets with 10ms of sound data in them
     */
-    if (st->codec->sample_rate != 8000) {
-        av_log(s, AV_LOG_ERROR, "Sample rate %d is not supported.\n", st->codec->sample_rate);
+    if (st->codecpar->sample_rate != 8000) {
+        av_log(s, AV_LOG_ERROR, "Sample rate %d is not supported.\n", st->codecpar->sample_rate);
         return AVERROR_INVALIDDATA;
     }
 
-    st->codec->frame_size=80;
-    st->codec->channels=1;
+    st->codecpar->frame_size=80;
+    st->codecpar->channels=1;
     avpriv_set_pts_info(st, 64, 1, 100);
 
-    st->codec->codec_id=AV_CODEC_ID_G729;
+    st->codecpar->codec_id=AV_CODEC_ID_G729;
 
     avio_seek(pb, 257, SEEK_SET);
     msec=avio_rl16(pb);
     sec=avio_r8(pb);
     min=avio_rl32(pb);
 
-    st->duration = av_rescale(1000*(min*60+sec)+msec, st->codec->sample_rate, 1000 * st->codec->frame_size);
+    st->duration = av_rescale(1000*(min*60+sec)+msec, st->codecpar->sample_rate, 1000 * st->codecpar->frame_size);
 
     ctx->bytes_left_in_chunk=CHUNK_SIZE;
 
@@ -113,10 +113,10 @@ static int read_packet(AVFormatContext *s,
     ACTContext *ctx = s->priv_data;
     AVIOContext *pb = s->pb;
     int ret;
-    int frame_size=s->streams[0]->codec->sample_rate==8000?10:22;
+    int frame_size=s->streams[0]->codecpar->sample_rate==8000?10:22;
 
 
-    if(s->streams[0]->codec->sample_rate==8000)
+    if(s->streams[0]->codecpar->sample_rate==8000)
         ret=av_new_packet(pkt, 10);
     else
         ret=av_new_packet(pkt, 11);
@@ -124,7 +124,7 @@ static int read_packet(AVFormatContext *s,
     if(ret)
         return ret;
 
-    if(s->streams[0]->codec->sample_rate==4400 && !ctx->second_packet)
+    if(s->streams[0]->codecpar->sample_rate==4400 && !ctx->second_packet)
     {
         ret = avio_read(pb, ctx->audio_buffer, frame_size);
 
@@ -147,7 +147,7 @@ static int read_packet(AVFormatContext *s,
 
         ctx->second_packet=1;
     }
-    else if(s->streams[0]->codec->sample_rate==4400 && ctx->second_packet)
+    else if(s->streams[0]->codecpar->sample_rate==4400 && ctx->second_packet)
     {
         pkt->data[0]=ctx->audio_buffer[5];
         pkt->data[1]=ctx->audio_buffer[17];
diff --git a/libavformat/adp.c b/libavformat/adp.c
index f53375a..9ab2ec4 100644
--- a/libavformat/adp.c
+++ b/libavformat/adp.c
@@ -53,16 +53,16 @@ static int adp_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id       = AV_CODEC_ID_ADPCM_DTK;
-    st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
-    st->codec->channels       = 2;
-    st->codec->sample_rate    = 48000;
+    st->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id       = AV_CODEC_ID_ADPCM_DTK;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+    st->codecpar->channels       = 2;
+    st->codecpar->sample_rate    = 48000;
     st->start_time            = 0;
     if (s->pb->seekable)
-        st->duration          = av_get_audio_frame_duration(st->codec, avio_size(s->pb));
+        st->duration          = av_get_audio_frame_duration2(st->codecpar, avio_size(s->pb));
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
diff --git a/libavformat/ads.c b/libavformat/ads.c
index bda2673..73ea7c7 100644
--- a/libavformat/ads.c
+++ b/libavformat/ads.c
@@ -42,39 +42,39 @@ static int ads_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     avio_skip(s->pb, 8);
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
     codec                  = avio_rl32(s->pb);
-    st->codec->sample_rate = avio_rl32(s->pb);
-    if (st->codec->sample_rate <= 0)
+    st->codecpar->sample_rate = avio_rl32(s->pb);
+    if (st->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
-    st->codec->channels    = avio_rl32(s->pb);
-    if (st->codec->channels <= 0)
+    st->codecpar->channels    = avio_rl32(s->pb);
+    if (st->codecpar->channels <= 0)
         return AVERROR_INVALIDDATA;
     align                  = avio_rl32(s->pb);
-    if (align <= 0 || align > INT_MAX / st->codec->channels)
+    if (align <= 0 || align > INT_MAX / st->codecpar->channels)
         return AVERROR_INVALIDDATA;
 
     if (codec == 1)
-        st->codec->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR;
     else
-        st->codec->codec_id = AV_CODEC_ID_ADPCM_PSX;
+        st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX;
 
-    st->codec->block_align = st->codec->channels * align;
+    st->codecpar->block_align = st->codecpar->channels * align;
     avio_skip(s->pb, 12);
     size = avio_rl32(s->pb);
-    if (st->codec->codec_id == AV_CODEC_ID_ADPCM_PSX)
-        st->duration = (size - 0x40) / 16 / st->codec->channels * 28;
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_PSX)
+        st->duration = (size - 0x40) / 16 / st->codecpar->channels * 28;
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
 
 static int ads_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int ret;
 
-    ret = av_get_packet(s->pb, pkt, codec->block_align);
+    ret = av_get_packet(s->pb, pkt, par->block_align);
     pkt->stream_index = 0;
     return ret;
 }
diff --git a/libavformat/adtsenc.c b/libavformat/adtsenc.c
index 242d738..5e006dd 100644
--- a/libavformat/adtsenc.c
+++ b/libavformat/adtsenc.c
@@ -97,13 +97,13 @@ static int adts_decode_extradata(AVFormatContext *s, ADTSContext *adts, const ui
 static int adts_write_header(AVFormatContext *s)
 {
     ADTSContext *adts = s->priv_data;
-    AVCodecContext *avc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
     if (adts->id3v2tag)
         ff_id3v2_write_simple(s, 4, ID3v2_DEFAULT_MAGIC);
-    if (avc->extradata_size > 0)
-        return adts_decode_extradata(s, adts, avc->extradata,
-                                     avc->extradata_size);
+    if (par->extradata_size > 0)
+        return adts_decode_extradata(s, adts, par->extradata,
+                                     par->extradata_size);
 
     return 0;
 }
diff --git a/libavformat/adxdec.c b/libavformat/adxdec.c
index 05cef0b..cf44531 100644
--- a/libavformat/adxdec.c
+++ b/libavformat/adxdec.c
@@ -50,15 +50,15 @@ static int adx_probe(AVProbeData *p)
 static int adx_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     ADXDemuxerContext *c = s->priv_data;
-    AVCodecContext *avctx = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int ret, size;
 
-    if (avctx->channels <= 0) {
-        av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", avctx->channels);
+    if (par->channels <= 0) {
+        av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->channels);
         return AVERROR_INVALIDDATA;
     }
 
-    size = BLOCK_SIZE * avctx->channels;
+    size = BLOCK_SIZE * par->channels;
 
     pkt->pos = avio_tell(s->pb);
     pkt->stream_index = 0;
@@ -82,37 +82,38 @@ static int adx_read_packet(AVFormatContext *s, AVPacket *pkt)
 static int adx_read_header(AVFormatContext *s)
 {
     ADXDemuxerContext *c = s->priv_data;
-    AVCodecContext *avctx;
+    AVCodecParameters *par;
 
     AVStream *st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    avctx = s->streams[0]->codec;
+    par = s->streams[0]->codecpar;
 
     if (avio_rb16(s->pb) != 0x8000)
         return AVERROR_INVALIDDATA;
     c->header_size = avio_rb16(s->pb) + 4;
     avio_seek(s->pb, -4, SEEK_CUR);
 
-    if (ff_get_extradata(avctx, s->pb, c->header_size) < 0)
+    if (ff_get_extradata(s, par, s->pb, c->header_size) < 0)
         return AVERROR(ENOMEM);
 
-    if (avctx->extradata_size < 12) {
+    if (par->extradata_size < 12) {
         av_log(s, AV_LOG_ERROR, "Invalid extradata size.\n");
         return AVERROR_INVALIDDATA;
     }
-    avctx->channels    = AV_RB8(avctx->extradata + 7);
-    avctx->sample_rate = AV_RB32(avctx->extradata + 8);
+    par->channels    = AV_RB8 (par->extradata + 7);
+    par->sample_rate = AV_RB32(par->extradata + 8);
 
-    if (avctx->channels <= 0) {
-        av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", avctx->channels);
+    if (par->channels <= 0) {
+        av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->channels);
         return AVERROR_INVALIDDATA;
     }
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = s->iformat->raw_codec_id;
+    par->codec_type  = AVMEDIA_TYPE_AUDIO;
+    par->codec_id    = s->iformat->raw_codec_id;
+    par->bit_rate    = par->sample_rate * par->channels * BLOCK_SIZE * 8LL / BLOCK_SAMPLES;
 
-    avpriv_set_pts_info(st, 64, BLOCK_SAMPLES, avctx->sample_rate);
+    avpriv_set_pts_info(st, 64, BLOCK_SAMPLES, par->sample_rate);
 
     return 0;
 }
diff --git a/libavformat/aea.c b/libavformat/aea.c
index db415c9..f795495 100644
--- a/libavformat/aea.c
+++ b/libavformat/aea.c
@@ -32,7 +32,7 @@ static int aea_read_probe(AVProbeData *p)
     if (p->buf_size <= 2048+212)
         return 0;
 
-    /* Magic is '00 08 00 00' in Little Endian*/
+    /* Magic is '00 08 00 00' in little-endian*/
     if (AV_RL32(p->buf)==0x800) {
         int ch, i;
         ch = p->buf[264];
@@ -67,29 +67,29 @@ static int aea_read_header(AVFormatContext *s)
 
     /* Parse the amount of channels and skip to pos 2048(0x800) */
     avio_skip(s->pb, 264);
-    st->codec->channels = avio_r8(s->pb);
+    st->codecpar->channels = avio_r8(s->pb);
     avio_skip(s->pb, 1783);
 
 
-    st->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id       = AV_CODEC_ID_ATRAC1;
-    st->codec->sample_rate    = 44100;
-    st->codec->bit_rate       = 292000;
+    st->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id       = AV_CODEC_ID_ATRAC1;
+    st->codecpar->sample_rate    = 44100;
+    st->codecpar->bit_rate       = 292000;
 
-    if (st->codec->channels != 1 && st->codec->channels != 2) {
-        av_log(s,AV_LOG_ERROR,"Channels %d not supported!\n",st->codec->channels);
+    if (st->codecpar->channels != 1 && st->codecpar->channels != 2) {
+        av_log(s, AV_LOG_ERROR, "Channels %d not supported!\n", st->codecpar->channels);
         return AVERROR_INVALIDDATA;
     }
 
-    st->codec->channel_layout = (st->codec->channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
+    st->codecpar->channel_layout = (st->codecpar->channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
 
-    st->codec->block_align = AT1_SU_SIZE * st->codec->channels;
+    st->codecpar->block_align = AT1_SU_SIZE * st->codecpar->channels;
     return 0;
 }
 
 static int aea_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    int ret = av_get_packet(s->pb, pkt, s->streams[0]->codec->block_align);
+    int ret = av_get_packet(s->pb, pkt, s->streams[0]->codecpar->block_align);
 
     pkt->stream_index = 0;
     if (ret <= 0)
diff --git a/libavformat/afc.c b/libavformat/afc.c
index 8dbd232..542cb16 100644
--- a/libavformat/afc.c
+++ b/libavformat/afc.c
@@ -35,20 +35,20 @@ static int afc_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id   = AV_CODEC_ID_ADPCM_AFC;
-    st->codec->channels   = 2;
-    st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id   = AV_CODEC_ID_ADPCM_AFC;
+    st->codecpar->channels   = 2;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
 
-    if (ff_alloc_extradata(st->codec, 1))
+    if (ff_alloc_extradata(st->codecpar, 1))
         return AVERROR(ENOMEM);
-    st->codec->extradata[0] = 8 * st->codec->channels;
+    st->codecpar->extradata[0] = 8 * st->codecpar->channels;
 
     c->data_end = avio_rb32(s->pb) + 32LL;
     st->duration = avio_rb32(s->pb);
-    st->codec->sample_rate = avio_rb16(s->pb);
+    st->codecpar->sample_rate = avio_rb16(s->pb);
     avio_skip(s->pb, 22);
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c
index 34b266d..d191bc4 100644
--- a/libavformat/aiffdec.c
+++ b/libavformat/aiffdec.c
@@ -95,7 +95,7 @@ static int get_aiff_header(AVFormatContext *s, int size,
                                     unsigned version)
 {
     AVIOContext *pb        = s->pb;
-    AVCodecContext *codec  = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     AIFFInputContext *aiff = s->priv_data;
     int exp;
     uint64_t val;
@@ -104,10 +104,10 @@ static int get_aiff_header(AVFormatContext *s, int size,
 
     if (size & 1)
         size++;
-    codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    codec->channels = avio_rb16(pb);
+    par->codec_type = AVMEDIA_TYPE_AUDIO;
+    par->channels = avio_rb16(pb);
     num_frames = avio_rb32(pb);
-    codec->bits_per_coded_sample = avio_rb16(pb);
+    par->bits_per_coded_sample = avio_rb16(pb);
 
     exp = avio_rb16(pb) - 16383 - 63;
     val = avio_rb64(pb);
@@ -119,29 +119,29 @@ static int get_aiff_header(AVFormatContext *s, int size,
         sample_rate = val << exp;
     else
         sample_rate = (val + (1ULL<<(-exp-1))) >> -exp;
-    codec->sample_rate = sample_rate;
+    par->sample_rate = sample_rate;
     size -= 18;
 
     /* get codec id for AIFF-C */
     if (size < 4) {
         version = AIFF;
     } else if (version == AIFF_C_VERSION1) {
-        codec->codec_tag = avio_rl32(pb);
-        codec->codec_id  = ff_codec_get_id(ff_codec_aiff_tags, codec->codec_tag);
-        if (codec->codec_id == AV_CODEC_ID_NONE) {
+        par->codec_tag = avio_rl32(pb);
+        par->codec_id  = ff_codec_get_id(ff_codec_aiff_tags, par->codec_tag);
+        if (par->codec_id == AV_CODEC_ID_NONE) {
             char tag[32];
-            av_get_codec_tag_string(tag, sizeof(tag), codec->codec_tag);
+            av_get_codec_tag_string(tag, sizeof(tag), par->codec_tag);
             avpriv_request_sample(s, "unknown or unsupported codec tag: %s", tag);
         }
         size -= 4;
     }
 
-    if (version != AIFF_C_VERSION1 || codec->codec_id == AV_CODEC_ID_PCM_S16BE) {
-        codec->codec_id = aiff_codec_get_id(codec->bits_per_coded_sample);
-        codec->bits_per_coded_sample = av_get_bits_per_sample(codec->codec_id);
+    if (version != AIFF_C_VERSION1 || par->codec_id == AV_CODEC_ID_PCM_S16BE) {
+        par->codec_id = aiff_codec_get_id(par->bits_per_coded_sample);
+        par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
         aiff->block_duration = 1;
     } else {
-        switch (codec->codec_id) {
+        switch (par->codec_id) {
         case AV_CODEC_ID_PCM_F32BE:
         case AV_CODEC_ID_PCM_F64BE:
         case AV_CODEC_ID_PCM_S16LE:
@@ -150,39 +150,39 @@ static int get_aiff_header(AVFormatContext *s, int size,
             aiff->block_duration = 1;
             break;
         case AV_CODEC_ID_ADPCM_IMA_QT:
-            codec->block_align = 34*codec->channels;
+            par->block_align = 34 * par->channels;
             break;
         case AV_CODEC_ID_MACE3:
-            codec->block_align = 2*codec->channels;
+            par->block_align = 2 * par->channels;
             break;
         case AV_CODEC_ID_ADPCM_G726LE:
-            codec->bits_per_coded_sample = 5;
+            par->bits_per_coded_sample = 5;
         case AV_CODEC_ID_ADPCM_IMA_WS:
         case AV_CODEC_ID_ADPCM_G722:
         case AV_CODEC_ID_MACE6:
         case AV_CODEC_ID_SDX2_DPCM:
-            codec->block_align = 1*codec->channels;
+            par->block_align = 1 * par->channels;
             break;
         case AV_CODEC_ID_GSM:
-            codec->block_align = 33;
+            par->block_align = 33;
             break;
         default:
             aiff->block_duration = 1;
             break;
         }
-        if (codec->block_align > 0)
-            aiff->block_duration = av_get_audio_frame_duration(codec,
-                                                               codec->block_align);
+        if (par->block_align > 0)
+            aiff->block_duration = av_get_audio_frame_duration2(par,
+                                                                par->block_align);
     }
 
     /* Block align needs to be computed in all cases, as the definition
      * is specific to applications -> here we use the WAVE format definition */
-    if (!codec->block_align)
-        codec->block_align = (av_get_bits_per_sample(codec->codec_id) * codec->channels) >> 3;
+    if (!par->block_align)
+        par->block_align = (av_get_bits_per_sample(par->codec_id) * par->channels) >> 3;
 
     if (aiff->block_duration) {
-        codec->bit_rate = codec->sample_rate * (codec->block_align << 3) /
-                          aiff->block_duration;
+        par->bit_rate = par->sample_rate * (par->block_align << 3) /
+                        aiff->block_duration;
     }
 
     /* Chunk is over */
@@ -238,7 +238,7 @@ static int aiff_read_header(AVFormatContext *s)
         /* parse different chunks */
         size = get_tag(pb, &tag);
 
-        if (size == AVERROR_EOF && offset > 0 && st->codec->block_align) {
+        if (size == AVERROR_EOF && offset > 0 && st->codecpar->block_align) {
             av_log(s, AV_LOG_WARNING, "header parser hit EOF\n");
             goto got_sound;
         }
@@ -288,7 +288,7 @@ static int aiff_read_header(AVFormatContext *s)
             offset = avio_rb32(pb);      /* Offset of sound data */
             avio_rb32(pb);               /* BlockSize... don't care */
             offset += avio_tell(pb);    /* Compute absolute data offset */
-            if (st->codec->block_align && !pb->seekable)    /* Assume COMM already parsed */
+            if (st->codecpar->block_align && !pb->seekable)    /* Assume COMM already parsed */
                 goto got_sound;
             if (!pb->seekable) {
                 av_log(s, AV_LOG_ERROR, "file is not seekable\n");
@@ -299,26 +299,26 @@ static int aiff_read_header(AVFormatContext *s)
         case MKTAG('w', 'a', 'v', 'e'):
             if ((uint64_t)size > (1<<30))
                 return -1;
-            if (ff_get_extradata(st->codec, pb, size) < 0)
+            if (ff_get_extradata(s, st->codecpar, pb, size) < 0)
                 return AVERROR(ENOMEM);
-            if (st->codec->codec_id == AV_CODEC_ID_QDM2 && size>=12*4 && !st->codec->block_align) {
-                st->codec->block_align = AV_RB32(st->codec->extradata+11*4);
-                aiff->block_duration = AV_RB32(st->codec->extradata+9*4);
-            } else if (st->codec->codec_id == AV_CODEC_ID_QCELP) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 && size>=12*4 && !st->codecpar->block_align) {
+                st->codecpar->block_align = AV_RB32(st->codecpar->extradata+11*4);
+                aiff->block_duration = AV_RB32(st->codecpar->extradata+9*4);
+            } else if (st->codecpar->codec_id == AV_CODEC_ID_QCELP) {
                 char rate = 0;
                 if (size >= 25)
-                    rate = st->codec->extradata[24];
+                    rate = st->codecpar->extradata[24];
                 switch (rate) {
                 case 'H': // RATE_HALF
-                    st->codec->block_align = 17;
+                    st->codecpar->block_align = 17;
                     break;
                 case 'F': // RATE_FULL
                 default:
-                    st->codec->block_align = 35;
+                    st->codecpar->block_align = 35;
                 }
                 aiff->block_duration = 160;
-                st->codec->bit_rate = st->codec->sample_rate * (st->codec->block_align << 3) /
-                                      aiff->block_duration;
+                st->codecpar->bit_rate = st->codecpar->sample_rate * (st->codecpar->block_align << 3) /
+                                         aiff->block_duration;
             }
             break;
         case MKTAG('C','H','A','N'):
@@ -326,7 +326,7 @@ static int aiff_read_header(AVFormatContext *s)
                 return AVERROR_INVALIDDATA;
             break;
         case 0:
-            if (offset > 0 && st->codec->block_align) // COMM && SSND
+            if (offset > 0 && st->codecpar->block_align) // COMM && SSND
                 goto got_sound;
         default: /* Jump */
             if (size & 1)   /* Always even aligned */
@@ -336,13 +336,13 @@ static int aiff_read_header(AVFormatContext *s)
     }
 
 got_sound:
-    if (!st->codec->block_align) {
+    if (!st->codecpar->block_align) {
         av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n");
         return -1;
     }
 
     /* Now positioned, get the sound data start and end */
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     st->start_time = 0;
     st->duration = st->nb_frames * aiff->block_duration;
 
@@ -368,26 +368,26 @@ static int aiff_read_packet(AVFormatContext *s,
         return AVERROR_EOF;
 
     /* Now for that packet */
-    switch (st->codec->codec_id) {
+    switch (st->codecpar->codec_id) {
     case AV_CODEC_ID_ADPCM_IMA_QT:
     case AV_CODEC_ID_GSM:
     case AV_CODEC_ID_QDM2:
     case AV_CODEC_ID_QCELP:
-        size = st->codec->block_align;
+        size = st->codecpar->block_align;
         break;
     default:
-        size = (MAX_SIZE / st->codec->block_align) * st->codec->block_align;
+        size = (MAX_SIZE / st->codecpar->block_align) * st->codecpar->block_align;
     }
     size = FFMIN(max_size, size);
     res = av_get_packet(s->pb, pkt, size);
     if (res < 0)
         return res;
 
-    if (size >= st->codec->block_align)
+    if (size >= st->codecpar->block_align)
         pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
     /* Only one stream in an AIFF file */
     pkt->stream_index = 0;
-    pkt->duration     = (res / st->codec->block_align) * aiff->block_duration;
+    pkt->duration     = (res / st->codecpar->block_align) * aiff->block_duration;
     return 0;
 }
 
diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c
index 25dc5e6..d876997 100644
--- a/libavformat/aiffenc.c
+++ b/libavformat/aiffenc.c
@@ -102,16 +102,16 @@ static int aiff_write_header(AVFormatContext *s)
 {
     AIFFOutputContext *aiff = s->priv_data;
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc;
+    AVCodecParameters *par;
     uint64_t sample_rate;
     int i, aifc = 0;
 
     aiff->audio_stream_idx = -1;
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
-        if (aiff->audio_stream_idx < 0 && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (aiff->audio_stream_idx < 0 && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             aiff->audio_stream_idx = i;
-        } else if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO) {
+        } else if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
             av_log(s, AV_LOG_ERROR, "AIFF allows only one audio stream and a picture.\n");
             return AVERROR(EINVAL);
         }
@@ -121,12 +121,12 @@ static int aiff_write_header(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    enc = s->streams[aiff->audio_stream_idx]->codec;
+    par = s->streams[aiff->audio_stream_idx]->codecpar;
 
     /* First verify if format is ok */
-    if (!enc->codec_tag)
+    if (!par->codec_tag)
         return -1;
-    if (enc->codec_tag != MKTAG('N','O','N','E'))
+    if (par->codec_tag != MKTAG('N','O','N','E'))
         aifc = 1;
 
     /* FORM AIFF header */
@@ -136,7 +136,7 @@ static int aiff_write_header(AVFormatContext *s)
     ffio_wfourcc(pb, aifc ? "AIFC" : "AIFF");
 
     if (aifc) { // compressed audio
-        if (!enc->block_align) {
+        if (!par->block_align) {
             av_log(s, AV_LOG_ERROR, "block align not set\n");
             return -1;
         }
@@ -146,10 +146,10 @@ static int aiff_write_header(AVFormatContext *s)
         avio_wb32(pb, 0xA2805140);
     }
 
-    if (enc->channels > 2 && enc->channel_layout) {
+    if (par->channels > 2 && par->channel_layout) {
         ffio_wfourcc(pb, "CHAN");
         avio_wb32(pb, 12);
-        ff_mov_write_chan(pb, enc->channel_layout);
+        ff_mov_write_chan(pb, par->channel_layout);
     }
 
     put_meta(s, "title",     MKTAG('N', 'A', 'M', 'E'));
@@ -160,35 +160,35 @@ static int aiff_write_header(AVFormatContext *s)
     /* Common chunk */
     ffio_wfourcc(pb, "COMM");
     avio_wb32(pb, aifc ? 24 : 18); /* size */
-    avio_wb16(pb, enc->channels);  /* Number of channels */
+    avio_wb16(pb, par->channels);  /* Number of channels */
 
     aiff->frames = avio_tell(pb);
     avio_wb32(pb, 0);              /* Number of frames */
 
-    if (!enc->bits_per_coded_sample)
-        enc->bits_per_coded_sample = av_get_bits_per_sample(enc->codec_id);
-    if (!enc->bits_per_coded_sample) {
+    if (!par->bits_per_coded_sample)
+        par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
+    if (!par->bits_per_coded_sample) {
         av_log(s, AV_LOG_ERROR, "could not compute bits per sample\n");
         return -1;
     }
-    if (!enc->block_align)
-        enc->block_align = (enc->bits_per_coded_sample * enc->channels) >> 3;
+    if (!par->block_align)
+        par->block_align = (par->bits_per_coded_sample * par->channels) >> 3;
 
-    avio_wb16(pb, enc->bits_per_coded_sample); /* Sample size */
+    avio_wb16(pb, par->bits_per_coded_sample); /* Sample size */
 
-    sample_rate = av_double2int(enc->sample_rate);
+    sample_rate = av_double2int(par->sample_rate);
     avio_wb16(pb, (sample_rate >> 52) + (16383 - 1023));
     avio_wb64(pb, UINT64_C(1) << 63 | sample_rate << 11);
 
     if (aifc) {
-        avio_wl32(pb, enc->codec_tag);
+        avio_wl32(pb, par->codec_tag);
         avio_wb16(pb, 0);
     }
 
-    if (enc->codec_tag == MKTAG('Q','D','M','2') && enc->extradata_size) {
+    if (par->codec_tag == MKTAG('Q','D','M','2') && par->extradata_size) {
         ffio_wfourcc(pb, "wave");
-        avio_wb32(pb, enc->extradata_size);
-        avio_write(pb, enc->extradata, enc->extradata_size);
+        avio_wb32(pb, par->extradata_size);
+        avio_write(pb, par->extradata, par->extradata_size);
     }
 
     /* Sound data chunk */
@@ -199,7 +199,7 @@ static int aiff_write_header(AVFormatContext *s)
     avio_wb32(pb, 0);                    /* Block-size (block align) */
 
     avpriv_set_pts_info(s->streams[aiff->audio_stream_idx], 64, 1,
-                        s->streams[aiff->audio_stream_idx]->codec->sample_rate);
+                        s->streams[aiff->audio_stream_idx]->codecpar->sample_rate);
 
     /* Data is starting here */
     avio_flush(pb);
@@ -217,7 +217,7 @@ static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt)
         int ret;
         AVPacketList *pict_list, *last;
 
-        if (s->streams[pkt->stream_index]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
+        if (s->streams[pkt->stream_index]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
             return 0;
 
         /* warn only once for each stream */
@@ -256,7 +256,7 @@ static int aiff_write_trailer(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     AIFFOutputContext *aiff = s->priv_data;
     AVPacketList *pict_list = aiff->pict_list;
-    AVCodecContext *enc = s->streams[aiff->audio_stream_idx]->codec;
+    AVCodecParameters *par = s->streams[aiff->audio_stream_idx]->codecpar;
 
     /* Chunks sizes must be even */
     int64_t file_size, end_size;
@@ -269,7 +269,7 @@ static int aiff_write_trailer(AVFormatContext *s)
     if (s->pb->seekable) {
         /* Number of sample frames */
         avio_seek(pb, aiff->frames, SEEK_SET);
-        avio_wb32(pb, (file_size-aiff->ssnd-12)/enc->block_align);
+        avio_wb32(pb, (file_size - aiff->ssnd - 12) / par->block_align);
 
         /* Sound Data chunk size */
         avio_seek(pb, aiff->ssnd, SEEK_SET);
diff --git a/libavformat/aixdec.c b/libavformat/aixdec.c
new file mode 100644
index 0000000..cad8a1e
--- /dev/null
+++ b/libavformat/aixdec.c
@@ -0,0 +1,140 @@
+/*
+ * AIX demuxer
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * 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/intreadwrite.h"
+#include "avformat.h"
+#include "internal.h"
+
+static int aix_probe(AVProbeData *p)
+{
+    if (AV_RL32(p->buf) != MKTAG('A','I','X','F') ||
+        AV_RB32(p->buf +  8) != 0x01000014 ||
+        AV_RB32(p->buf + 12) != 0x00000800)
+        return 0;
+
+    return AVPROBE_SCORE_MAX;
+}
+
+static int aix_read_header(AVFormatContext *s)
+{
+    unsigned nb_streams, first_offset, nb_segments;
+    unsigned stream_list_offset;
+    unsigned segment_list_offset = 0x20;
+    unsigned segment_list_entry_size = 0x10;
+    unsigned size;
+    int i;
+
+    avio_skip(s->pb, 4);
+    first_offset = avio_rb32(s->pb) + 8;
+    avio_skip(s->pb, 16);
+    nb_segments = avio_rb16(s->pb);
+    if (nb_segments == 0)
+        return AVERROR_INVALIDDATA;
+    stream_list_offset = segment_list_offset + segment_list_entry_size * nb_segments + 0x10;
+    if (stream_list_offset >= first_offset)
+        return AVERROR_INVALIDDATA;
+    avio_seek(s->pb, stream_list_offset, SEEK_SET);
+    nb_streams = avio_r8(s->pb);
+    if (nb_streams == 0)
+        return AVERROR_INVALIDDATA;
+    avio_skip(s->pb, 7);
+    for (i = 0; i < nb_streams; i++) {
+        AVStream *st = avformat_new_stream(s, NULL);
+
+        if (!st)
+            return AVERROR(ENOMEM);
+        st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_ADX;
+        st->codecpar->sample_rate = avio_rb32(s->pb);
+        st->codecpar->channels    = avio_r8(s->pb);
+        avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
+        avio_skip(s->pb, 3);
+    }
+
+    avio_seek(s->pb, first_offset, SEEK_SET);
+    for (i = 0; i < nb_streams; i++) {
+        if (avio_rl32(s->pb) != MKTAG('A','I','X','P'))
+            return AVERROR_INVALIDDATA;
+        size = avio_rb32(s->pb);
+        if (size <= 8)
+            return AVERROR_INVALIDDATA;
+        avio_skip(s->pb, 8);
+        ff_get_extradata(s, s->streams[i]->codecpar, s->pb, size - 8);
+    }
+
+    return 0;
+}
+
+static int aix_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    unsigned size, index, duration, chunk;
+    int64_t pos;
+    int sequence, ret, i;
+
+    pos = avio_tell(s->pb);
+    if (avio_feof(s->pb))
+        return AVERROR_EOF;
+    chunk = avio_rl32(s->pb);
+    size = avio_rb32(s->pb);
+    if (chunk == MKTAG('A','I','X','E')) {
+        avio_skip(s->pb, size);
+        for (i = 0; i < s->nb_streams; i++) {
+            if (avio_feof(s->pb))
+                return AVERROR_EOF;
+            chunk = avio_rl32(s->pb);
+            size = avio_rb32(s->pb);
+            avio_skip(s->pb, size);
+        }
+        pos = avio_tell(s->pb);
+        chunk = avio_rl32(s->pb);
+        size = avio_rb32(s->pb);
+    }
+
+    if (chunk != MKTAG('A','I','X','P'))
+        return AVERROR_INVALIDDATA;
+    if (size <= 8)
+        return AVERROR_INVALIDDATA;
+    index = avio_r8(s->pb);
+    if (avio_r8(s->pb) != s->nb_streams || index >= s->nb_streams)
+        return AVERROR_INVALIDDATA;
+    duration = avio_rb16(s->pb);
+    sequence = avio_rb32(s->pb);
+    if (sequence < 0) {
+        avio_skip(s->pb, size - 8);
+        return 0;
+    }
+
+    ret = av_get_packet(s->pb, pkt, size - 8);
+    pkt->stream_index = index;
+    pkt->duration = duration;
+    pkt->pos = pos;
+    return ret;
+}
+
+AVInputFormat ff_aix_demuxer = {
+    .name        = "aix",
+    .long_name   = NULL_IF_CONFIG_SMALL("CRI AIX"),
+    .read_probe  = aix_probe,
+    .read_header = aix_read_header,
+    .read_packet = aix_read_packet,
+    .extensions  = "aix",
+    .flags       = AVFMT_GENERIC_INDEX,
+};
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index 02bb16a..d490cc4 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -41,20 +41,12 @@
 
 #define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)
 
-#define REGISTER_PROTOCOL(X, x)                                         \
-    {                                                                   \
-        extern URLProtocol ff_##x##_protocol;                           \
-        if (CONFIG_##X##_PROTOCOL)                                      \
-            ffurl_register_protocol(&ff_##x##_protocol);                \
-    }
-
 void av_register_all(void)
 {
     static int initialized;
 
     if (initialized)
         return;
-    initialized = 1;
 
     avcodec_register_all();
 
@@ -73,6 +65,7 @@ void av_register_all(void)
     REGISTER_DEMUXER (AEA,              aea);
     REGISTER_DEMUXER (AFC,              afc);
     REGISTER_MUXDEMUX(AIFF,             aiff);
+    REGISTER_DEMUXER (AIX,              aix);
     REGISTER_MUXDEMUX(AMR,              amr);
     REGISTER_DEMUXER (ANM,              anm);
     REGISTER_DEMUXER (APC,              apc);
@@ -121,6 +114,7 @@ void av_register_all(void)
     REGISTER_DEMUXER (DTSHD,            dtshd);
     REGISTER_MUXDEMUX(DV,               dv);
     REGISTER_DEMUXER (DVBSUB,           dvbsub);
+    REGISTER_DEMUXER (DVBTXT,           dvbtxt);
     REGISTER_DEMUXER (DXA,              dxa);
     REGISTER_DEMUXER (EA,               ea);
     REGISTER_DEMUXER (EA_CDATA,         ea_cdata);
@@ -136,6 +130,7 @@ void av_register_all(void)
     REGISTER_DEMUXER (LIVE_FLV,         live_flv);
     REGISTER_DEMUXER (FOURXM,           fourxm);
     REGISTER_MUXER   (FRAMECRC,         framecrc);
+    REGISTER_MUXER   (FRAMEHASH,        framehash);
     REGISTER_MUXER   (FRAMEMD5,         framemd5);
     REGISTER_DEMUXER (FRM,              frm);
     REGISTER_DEMUXER (FSB,              fsb);
@@ -144,11 +139,12 @@ void av_register_all(void)
     REGISTER_DEMUXER (G729,             g729);
     REGISTER_DEMUXER (GENH,             genh);
     REGISTER_MUXDEMUX(GIF,              gif);
-    REGISTER_DEMUXER (GSM,              gsm);
+    REGISTER_MUXDEMUX(GSM,              gsm);
     REGISTER_MUXDEMUX(GXF,              gxf);
     REGISTER_MUXDEMUX(H261,             h261);
     REGISTER_MUXDEMUX(H263,             h263);
     REGISTER_MUXDEMUX(H264,             h264);
+    REGISTER_MUXER   (HASH,             hash);
     REGISTER_MUXER   (HDS,              hds);
     REGISTER_MUXDEMUX(HEVC,             hevc);
     REGISTER_MUXDEMUX(HLS,              hls);
@@ -212,7 +208,9 @@ void av_register_all(void)
     REGISTER_DEMUXER (MPSUB,            mpsub);
     REGISTER_DEMUXER (MSF,              msf);
     REGISTER_DEMUXER (MSNWC_TCP,        msnwc_tcp);
+    REGISTER_DEMUXER (MTAF,             mtaf);
     REGISTER_DEMUXER (MTV,              mtv);
+    REGISTER_DEMUXER (MUSX,             musx);
     REGISTER_DEMUXER (MV,               mv);
     REGISTER_DEMUXER (MVI,              mvi);
     REGISTER_MUXDEMUX(MXF,              mxf);
@@ -337,6 +335,7 @@ void av_register_all(void)
     REGISTER_MUXER   (WEBP,             webp);
     REGISTER_MUXDEMUX(WEBVTT,           webvtt);
     REGISTER_DEMUXER (WSAUD,            wsaud);
+    REGISTER_DEMUXER (WSD,              wsd);
     REGISTER_DEMUXER (WSVQA,            wsvqa);
     REGISTER_MUXDEMUX(WTV,              wtv);
     REGISTER_DEMUXER (WVE,              wve);
@@ -357,65 +356,25 @@ void av_register_all(void)
     REGISTER_DEMUXER (IMAGE_J2K_PIPE,        image_j2k_pipe);
     REGISTER_DEMUXER (IMAGE_JPEG_PIPE,       image_jpeg_pipe);
     REGISTER_DEMUXER (IMAGE_JPEGLS_PIPE,     image_jpegls_pipe);
+    REGISTER_DEMUXER (IMAGE_PAM_PIPE,        image_pam_pipe);
+    REGISTER_DEMUXER (IMAGE_PBM_PIPE,        image_pbm_pipe);
+    REGISTER_DEMUXER (IMAGE_PCX_PIPE,        image_pcx_pipe);
+    REGISTER_DEMUXER (IMAGE_PGMYUV_PIPE,     image_pgmyuv_pipe);
+    REGISTER_DEMUXER (IMAGE_PGM_PIPE,        image_pgm_pipe);
     REGISTER_DEMUXER (IMAGE_PICTOR_PIPE,     image_pictor_pipe);
     REGISTER_DEMUXER (IMAGE_PNG_PIPE,        image_png_pipe);
+    REGISTER_DEMUXER (IMAGE_PPM_PIPE,        image_ppm_pipe);
     REGISTER_DEMUXER (IMAGE_QDRAW_PIPE,      image_qdraw_pipe);
     REGISTER_DEMUXER (IMAGE_SGI_PIPE,        image_sgi_pipe);
     REGISTER_DEMUXER (IMAGE_SUNRAST_PIPE,    image_sunrast_pipe);
     REGISTER_DEMUXER (IMAGE_TIFF_PIPE,       image_tiff_pipe);
     REGISTER_DEMUXER (IMAGE_WEBP_PIPE,       image_webp_pipe);
 
-
-    /* protocols */
-    REGISTER_PROTOCOL(ASYNC,            async);
-    REGISTER_PROTOCOL(BLURAY,           bluray);
-    REGISTER_PROTOCOL(CACHE,            cache);
-    REGISTER_PROTOCOL(CONCAT,           concat);
-    REGISTER_PROTOCOL(CRYPTO,           crypto);
-    REGISTER_PROTOCOL(DATA,             data);
-    REGISTER_PROTOCOL(FFRTMPCRYPT,      ffrtmpcrypt);
-    REGISTER_PROTOCOL(FFRTMPHTTP,       ffrtmphttp);
-    REGISTER_PROTOCOL(FILE,             file);
-    REGISTER_PROTOCOL(FTP,              ftp);
-    REGISTER_PROTOCOL(GOPHER,           gopher);
-    REGISTER_PROTOCOL(HLS,              hls);
-    REGISTER_PROTOCOL(HTTP,             http);
-    REGISTER_PROTOCOL(HTTPPROXY,        httpproxy);
-    REGISTER_PROTOCOL(HTTPS,            https);
-    REGISTER_PROTOCOL(ICECAST,          icecast);
-    REGISTER_PROTOCOL(MMSH,             mmsh);
-    REGISTER_PROTOCOL(MMST,             mmst);
-    REGISTER_PROTOCOL(MD5,              md5);
-    REGISTER_PROTOCOL(PIPE,             pipe);
-    REGISTER_PROTOCOL(RTMP,             rtmp);
-    REGISTER_PROTOCOL(RTMPE,            rtmpe);
-    REGISTER_PROTOCOL(RTMPS,            rtmps);
-    REGISTER_PROTOCOL(RTMPT,            rtmpt);
-    REGISTER_PROTOCOL(RTMPTE,           rtmpte);
-    REGISTER_PROTOCOL(RTMPTS,           rtmpts);
-    REGISTER_PROTOCOL(RTP,              rtp);
-    REGISTER_PROTOCOL(SCTP,             sctp);
-    REGISTER_PROTOCOL(SRTP,             srtp);
-    REGISTER_PROTOCOL(SUBFILE,          subfile);
-    REGISTER_PROTOCOL(TCP,              tcp);
-    REGISTER_PROTOCOL(TLS_SCHANNEL,     tls_schannel);
-    REGISTER_PROTOCOL(TLS_SECURETRANSPORT, tls_securetransport);
-    REGISTER_PROTOCOL(TLS_GNUTLS,       tls_gnutls);
-    REGISTER_PROTOCOL(TLS_OPENSSL,      tls_openssl);
-    REGISTER_PROTOCOL(UDP,              udp);
-    REGISTER_PROTOCOL(UDPLITE,          udplite);
-    REGISTER_PROTOCOL(UNIX,             unix);
-
     /* external libraries */
     REGISTER_MUXER   (CHROMAPRINT,      chromaprint);
     REGISTER_DEMUXER (LIBGME,           libgme);
     REGISTER_DEMUXER (LIBMODPLUG,       libmodplug);
     REGISTER_MUXDEMUX(LIBNUT,           libnut);
-    REGISTER_PROTOCOL(LIBRTMP,          librtmp);
-    REGISTER_PROTOCOL(LIBRTMPE,         librtmpe);
-    REGISTER_PROTOCOL(LIBRTMPS,         librtmps);
-    REGISTER_PROTOCOL(LIBRTMPT,         librtmpt);
-    REGISTER_PROTOCOL(LIBRTMPTE,        librtmpte);
-    REGISTER_PROTOCOL(LIBSSH,           libssh);
-    REGISTER_PROTOCOL(LIBSMBCLIENT,     libsmbclient);
+
+    initialized = 1;
 }
diff --git a/libavformat/amr.c b/libavformat/amr.c
index 137df11..59963e1 100644
--- a/libavformat/amr.c
+++ b/libavformat/amr.c
@@ -1,6 +1,6 @@
 /*
  * amr file format
- * Copyright (c) 2001 ffmpeg project
+ * Copyright (c) 2001 FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -42,13 +42,13 @@ static const char AMRWB_header[] = "#!AMR-WB\n";
 static int amr_write_header(AVFormatContext *s)
 {
     AVIOContext    *pb  = s->pb;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
     s->priv_data = NULL;
 
-    if (enc->codec_id == AV_CODEC_ID_AMR_NB) {
+    if (par->codec_id == AV_CODEC_ID_AMR_NB) {
         avio_write(pb, AMR_header,   sizeof(AMR_header)   - 1); /* magic number */
-    } else if (enc->codec_id == AV_CODEC_ID_AMR_WB) {
+    } else if (par->codec_id == AV_CODEC_ID_AMR_WB) {
         avio_write(pb, AMRWB_header, sizeof(AMRWB_header) - 1); /* magic number */
     } else {
         return -1;
@@ -94,25 +94,25 @@ static int amr_read_header(AVFormatContext *s)
             return -1;
         }
 
-        st->codec->codec_tag   = MKTAG('s', 'a', 'w', 'b');
-        st->codec->codec_id    = AV_CODEC_ID_AMR_WB;
-        st->codec->sample_rate = 16000;
+        st->codecpar->codec_tag   = MKTAG('s', 'a', 'w', 'b');
+        st->codecpar->codec_id    = AV_CODEC_ID_AMR_WB;
+        st->codecpar->sample_rate = 16000;
     } else {
-        st->codec->codec_tag   = MKTAG('s', 'a', 'm', 'r');
-        st->codec->codec_id    = AV_CODEC_ID_AMR_NB;
-        st->codec->sample_rate = 8000;
+        st->codecpar->codec_tag   = MKTAG('s', 'a', 'm', 'r');
+        st->codecpar->codec_id    = AV_CODEC_ID_AMR_NB;
+        st->codecpar->sample_rate = 8000;
     }
-    st->codec->channels   = 1;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    st->codecpar->channels   = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
 
 static int amr_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int read, size = 0, toc, mode;
     int64_t pos = avio_tell(s->pb);
     AMRContext *amr = s->priv_data;
@@ -121,17 +121,17 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt)
         return AVERROR(EIO);
     }
 
-    // FIXME this is wrong, this should rather be in a AVParser
+    // FIXME this is wrong, this should rather be in an AVParser
     toc  = avio_r8(s->pb);
     mode = (toc >> 3) & 0x0F;
 
-    if (enc->codec_id == AV_CODEC_ID_AMR_NB) {
+    if (par->codec_id == AV_CODEC_ID_AMR_NB) {
         static const uint8_t packed_size[16] = {
             12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0
         };
 
         size = packed_size[mode] + 1;
-    } else if (enc->codec_id == AV_CODEC_ID_AMR_WB) {
+    } else if (par->codec_id == AV_CODEC_ID_AMR_WB) {
         static const uint8_t packed_size[16] = {
             18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 6, 0, 0, 0, 1, 1
         };
@@ -145,13 +145,13 @@ static int amr_read_packet(AVFormatContext *s, AVPacket *pkt)
     if (amr->cumulated_size < UINT64_MAX - size) {
         amr->cumulated_size += size;
         /* Both AMR formats have 50 frames per second */
-        s->streams[0]->codec->bit_rate = amr->cumulated_size / ++amr->block_count * 8 * 50;
+        s->streams[0]->codecpar->bit_rate = amr->cumulated_size / ++amr->block_count * 8 * 50;
     }
 
     pkt->stream_index = 0;
     pkt->pos          = pos;
     pkt->data[0]      = toc;
-    pkt->duration     = enc->codec_id == AV_CODEC_ID_AMR_NB ? 160 : 320;
+    pkt->duration     = par->codec_id == AV_CODEC_ID_AMR_NB ? 160 : 320;
     read              = avio_read(s->pb, pkt->data + 1, size - 1);
 
     if (read != size - 1) {
diff --git a/libavformat/anm.c b/libavformat/anm.c
index 2320047..b31757a 100644
--- a/libavformat/anm.c
+++ b/libavformat/anm.c
@@ -100,11 +100,11 @@ static int read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_ANM;
-    st->codec->codec_tag  = 0; /* no fourcc */
-    st->codec->width      = avio_rl16(pb);
-    st->codec->height     = avio_rl16(pb);
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_ANM;
+    st->codecpar->codec_tag  = 0; /* no fourcc */
+    st->codecpar->width      = avio_rl16(pb);
+    st->codecpar->height     = avio_rl16(pb);
     if (avio_r8(pb) != 0)
         goto invalid;
     avio_skip(pb, 1); /* frame rate multiplier info */
@@ -132,12 +132,12 @@ static int read_header(AVFormatContext *s)
     avio_skip(pb, 58);
 
     /* color cycling and palette data */
-    st->codec->extradata_size = 16*8 + 4*256;
-    st->codec->extradata      = av_mallocz(st->codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!st->codec->extradata) {
+    st->codecpar->extradata_size = 16*8 + 4*256;
+    st->codecpar->extradata      = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!st->codecpar->extradata) {
         return AVERROR(ENOMEM);
     }
-    ret = avio_read(pb, st->codec->extradata, st->codec->extradata_size);
+    ret = avio_read(pb, st->codecpar->extradata, st->codecpar->extradata_size);
     if (ret < 0)
         return ret;
 
diff --git a/libavformat/apc.c b/libavformat/apc.c
index 21bb514..a4dcf66 100644
--- a/libavformat/apc.c
+++ b/libavformat/apc.c
@@ -46,28 +46,28 @@ static int apc_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_APC;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_APC;
 
     avio_rl32(pb); /* number of samples */
-    st->codec->sample_rate = avio_rl32(pb);
+    st->codecpar->sample_rate = avio_rl32(pb);
 
     /* initial predictor values for adpcm decoder */
-    if (ff_get_extradata(st->codec, pb, 2 * 4) < 0)
+    if (ff_get_extradata(s, st->codecpar, pb, 2 * 4) < 0)
         return AVERROR(ENOMEM);
 
     if (avio_rl32(pb)) {
-        st->codec->channels       = 2;
-        st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+        st->codecpar->channels       = 2;
+        st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
     } else {
-        st->codec->channels       = 1;
-        st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+        st->codecpar->channels       = 1;
+        st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
     }
 
-    st->codec->bits_per_coded_sample = 4;
-    st->codec->bit_rate = st->codec->bits_per_coded_sample * st->codec->channels
-                          * st->codec->sample_rate;
-    st->codec->block_align = 1;
+    st->codecpar->bits_per_coded_sample = 4;
+    st->codecpar->bit_rate = st->codecpar->bits_per_coded_sample * st->codecpar->channels
+                          * st->codecpar->sample_rate;
+    st->codecpar->block_align = 1;
 
     return 0;
 }
diff --git a/libavformat/ape.c b/libavformat/ape.c
index 3e81972..061f328 100644
--- a/libavformat/ape.c
+++ b/libavformat/ape.c
@@ -348,23 +348,23 @@ static int ape_read_header(AVFormatContext * s)
 
     total_blocks = (ape->totalframes == 0) ? 0 : ((ape->totalframes - 1) * ape->blocksperframe) + ape->finalframeblocks;
 
-    st->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id        = AV_CODEC_ID_APE;
-    st->codec->codec_tag       = MKTAG('A', 'P', 'E', ' ');
-    st->codec->channels        = ape->channels;
-    st->codec->sample_rate     = ape->samplerate;
-    st->codec->bits_per_coded_sample = ape->bps;
+    st->codecpar->codec_type      = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id        = AV_CODEC_ID_APE;
+    st->codecpar->codec_tag       = MKTAG('A', 'P', 'E', ' ');
+    st->codecpar->channels        = ape->channels;
+    st->codecpar->sample_rate     = ape->samplerate;
+    st->codecpar->bits_per_coded_sample = ape->bps;
 
     st->nb_frames = ape->totalframes;
     st->start_time = 0;
     st->duration  = total_blocks;
     avpriv_set_pts_info(st, 64, 1, ape->samplerate);
 
-    if (ff_alloc_extradata(st->codec, APE_EXTRADATA_SIZE))
+    if (ff_alloc_extradata(st->codecpar, APE_EXTRADATA_SIZE))
         return AVERROR(ENOMEM);
-    AV_WL16(st->codec->extradata + 0, ape->fileversion);
-    AV_WL16(st->codec->extradata + 2, ape->compressiontype);
-    AV_WL16(st->codec->extradata + 4, ape->formatflags);
+    AV_WL16(st->codecpar->extradata + 0, ape->fileversion);
+    AV_WL16(st->codecpar->extradata + 2, ape->compressiontype);
+    AV_WL16(st->codecpar->extradata + 4, ape->formatflags);
 
     pts = 0;
     for (i = 0; i < ape->totalframes; i++) {
diff --git a/libavformat/apetag.c b/libavformat/apetag.c
index 2ee277f..08e80f4 100644
--- a/libavformat/apetag.c
+++ b/libavformat/apetag.c
@@ -89,16 +89,16 @@ static int ape_tag_read_field(AVFormatContext *s)
             }
 
             st->disposition      |= AV_DISPOSITION_ATTACHED_PIC;
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_id   = id;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_id   = id;
 
             st->attached_pic              = pkt;
             st->attached_pic.stream_index = st->index;
             st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
         } else {
-            if (ff_get_extradata(st->codec, s->pb, size) < 0)
+            if (ff_get_extradata(s, st->codecpar, s->pb, size) < 0)
                 return AVERROR(ENOMEM);
-            st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
+            st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT;
         }
     } else {
         value = av_malloc(size+1);
@@ -193,6 +193,7 @@ int ff_ape_write_tag(AVFormatContext *s)
                      APE_TAG_FLAG_IS_HEADER);
     ffio_fill(dyn_bc, 0, 8);             // reserved
 
+    ff_standardize_creation_time(s);
     while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) {
         int val_len;
 
diff --git a/libavformat/apngdec.c b/libavformat/apngdec.c
index c6403a1..bb17896 100644
--- a/libavformat/apngdec.c
+++ b/libavformat/apngdec.c
@@ -122,9 +122,9 @@ end:
     return AVPROBE_SCORE_MAX;
 }
 
-static int append_extradata(AVCodecContext *s, AVIOContext *pb, int len)
+static int append_extradata(AVCodecParameters *par, AVIOContext *pb, int len)
 {
-    int previous_size = s->extradata_size;
+    int previous_size = par->extradata_size;
     int new_size, ret;
     uint8_t *new_extradata;
 
@@ -132,13 +132,13 @@ static int append_extradata(AVCodecContext *s, AVIOContext *pb, int len)
         return AVERROR_INVALIDDATA;
 
     new_size = previous_size + len;
-    new_extradata = av_realloc(s->extradata, new_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    new_extradata = av_realloc(par->extradata, new_size + AV_INPUT_BUFFER_PADDING_SIZE);
     if (!new_extradata)
         return AVERROR(ENOMEM);
-    s->extradata = new_extradata;
-    s->extradata_size = new_size;
+    par->extradata = new_extradata;
+    par->extradata_size = new_size;
 
-    if ((ret = avio_read(pb, s->extradata + previous_size, len)) < 0)
+    if ((ret = avio_read(pb, par->extradata + previous_size, len)) < 0)
         return ret;
 
     return previous_size;
@@ -170,23 +170,23 @@ static int apng_read_header(AVFormatContext *s)
     /* set the timebase to something large enough (1/100,000 of second)
      * to hopefully cope with all sane frame durations */
     avpriv_set_pts_info(st, 64, 1, 100000);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_APNG;
-    st->codec->width      = avio_rb32(pb);
-    st->codec->height     = avio_rb32(pb);
-    if ((ret = av_image_check_size(st->codec->width, st->codec->height, 0, s)) < 0)
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_APNG;
+    st->codecpar->width      = avio_rb32(pb);
+    st->codecpar->height     = avio_rb32(pb);
+    if ((ret = av_image_check_size(st->codecpar->width, st->codecpar->height, 0, s)) < 0)
         return ret;
 
     /* extradata will contain every chunk up to the first fcTL (excluded) */
-    st->codec->extradata = av_malloc(len + 12 + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!st->codec->extradata)
+    st->codecpar->extradata = av_malloc(len + 12 + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!st->codecpar->extradata)
         return AVERROR(ENOMEM);
-    st->codec->extradata_size = len + 12;
-    AV_WB32(st->codec->extradata,    len);
-    AV_WL32(st->codec->extradata+4,  tag);
-    AV_WB32(st->codec->extradata+8,  st->codec->width);
-    AV_WB32(st->codec->extradata+12, st->codec->height);
-    if ((ret = avio_read(pb, st->codec->extradata+16, 9)) < 0)
+    st->codecpar->extradata_size = len + 12;
+    AV_WB32(st->codecpar->extradata,    len);
+    AV_WL32(st->codecpar->extradata+4,  tag);
+    AV_WB32(st->codecpar->extradata+8,  st->codecpar->width);
+    AV_WB32(st->codecpar->extradata+12, st->codecpar->height);
+    if ((ret = avio_read(pb, st->codecpar->extradata+16, 9)) < 0)
         goto fail;
 
     while (!avio_feof(pb)) {
@@ -218,11 +218,11 @@ static int apng_read_header(AVFormatContext *s)
         switch (tag) {
         case MKTAG('a', 'c', 'T', 'L'):
             if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
-                (ret = append_extradata(st->codec, pb, len + 12)) < 0)
+                (ret = append_extradata(st->codecpar, pb, len + 12)) < 0)
                 goto fail;
             acTL_found = 1;
-            ctx->num_frames = AV_RB32(st->codec->extradata + ret + 8);
-            ctx->num_play   = AV_RB32(st->codec->extradata + ret + 12);
+            ctx->num_frames = AV_RB32(st->codecpar->extradata + ret + 8);
+            ctx->num_play   = AV_RB32(st->codecpar->extradata + ret + 12);
             av_log(s, AV_LOG_DEBUG, "num_frames: %"PRIu32", num_play: %"PRIu32"\n",
                                     ctx->num_frames, ctx->num_play);
             break;
@@ -236,15 +236,15 @@ static int apng_read_header(AVFormatContext *s)
             return 0;
         default:
             if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
-                (ret = append_extradata(st->codec, pb, len + 12)) < 0)
+                (ret = append_extradata(st->codecpar, pb, len + 12)) < 0)
                 goto fail;
         }
     }
 
 fail:
-    if (st->codec->extradata_size) {
-        av_freep(&st->codec->extradata);
-        st->codec->extradata_size = 0;
+    if (st->codecpar->extradata_size) {
+        av_freep(&st->codecpar->extradata);
+        st->codecpar->extradata_size = 0;
     }
     return ret;
 }
@@ -298,15 +298,15 @@ static int decode_fctl_chunk(AVFormatContext *s, APNGDemuxContext *ctx, AVPacket
             dispose_op,
             blend_op);
 
-    if (width != s->streams[0]->codec->width ||
-        height != s->streams[0]->codec->height ||
+    if (width != s->streams[0]->codecpar->width ||
+        height != s->streams[0]->codecpar->height ||
         x_offset != 0 ||
         y_offset != 0) {
         if (sequence_number == 0 ||
-            x_offset >= s->streams[0]->codec->width ||
-            width > s->streams[0]->codec->width - x_offset ||
-            y_offset >= s->streams[0]->codec->height ||
-            height > s->streams[0]->codec->height - y_offset)
+            x_offset >= s->streams[0]->codecpar->width ||
+            width > s->streams[0]->codecpar->width - x_offset ||
+            y_offset >= s->streams[0]->codecpar->height ||
+            height > s->streams[0]->codecpar->height - y_offset)
             return AVERROR_INVALIDDATA;
         ctx->is_key_frame = 0;
     } else {
@@ -400,7 +400,7 @@ static int apng_read_packet(AVFormatContext *s, AVPacket *pkt)
             avio_seek(pb, -8, SEEK_CUR);
             return AVERROR_EOF;
         }
-        if ((ret = avio_seek(pb, s->streams[0]->codec->extradata_size + 8, SEEK_SET)) < 0)
+        if ((ret = avio_seek(pb, s->streams[0]->codecpar->extradata_size + 8, SEEK_SET)) < 0)
             return ret;
         return 0;
     default:
diff --git a/libavformat/apngenc.c b/libavformat/apngenc.c
index 4326a7c..e25df2e 100644
--- a/libavformat/apngenc.c
+++ b/libavformat/apngenc.c
@@ -80,8 +80,8 @@ static int apng_write_header(AVFormatContext *format_context)
     APNGMuxContext *apng = format_context->priv_data;
 
     if (format_context->nb_streams != 1 ||
-        format_context->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
-        format_context->streams[0]->codec->codec_id   != AV_CODEC_ID_APNG) {
+        format_context->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
+        format_context->streams[0]->codecpar->codec_id   != AV_CODEC_ID_APNG) {
         av_log(format_context, AV_LOG_ERROR,
                "APNG muxer supports only a single video APNG stream.\n");
         return AVERROR(EINVAL);
@@ -106,7 +106,7 @@ static void flush_packet(AVFormatContext *format_context, AVPacket *packet)
     APNGMuxContext *apng = format_context->priv_data;
     AVIOContext *io_context = format_context->pb;
     AVStream *codec_stream = format_context->streams[0];
-    AVCodecContext *codec_context = codec_stream->codec;
+    AVCodecParameters *codec_par = codec_stream->codecpar;
 
     av_assert0(apng->prev_packet);
 
@@ -117,13 +117,13 @@ static void flush_packet(AVFormatContext *format_context, AVPacket *packet)
         av_log(format_context, AV_LOG_INFO, "Only a single frame so saving as a normal PNG.\n");
 
         // Write normal PNG headers without acTL chunk
-        existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), codec_context->extradata, codec_context->extradata_size);
+        existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), codec_par->extradata, codec_par->extradata_size);
         if (existing_acTL_chunk) {
             uint8_t *chunk_after_acTL = existing_acTL_chunk + AV_RB32(existing_acTL_chunk) + 12;
-            avio_write(io_context, codec_context->extradata, existing_acTL_chunk - codec_context->extradata);
-            avio_write(io_context, chunk_after_acTL, codec_context->extradata + codec_context->extradata_size - chunk_after_acTL);
+            avio_write(io_context, codec_par->extradata, existing_acTL_chunk - codec_par->extradata);
+            avio_write(io_context, chunk_after_acTL, codec_par->extradata + codec_par->extradata_size - chunk_after_acTL);
         } else {
-            avio_write(io_context, codec_context->extradata, codec_context->extradata_size);
+            avio_write(io_context, codec_par->extradata, codec_par->extradata_size);
         }
 
         // Write frame data without fcTL chunk
@@ -142,9 +142,9 @@ static void flush_packet(AVFormatContext *format_context, AVPacket *packet)
             uint8_t *existing_acTL_chunk;
 
             // Write normal PNG headers
-            avio_write(io_context, codec_context->extradata, codec_context->extradata_size);
+            avio_write(io_context, codec_par->extradata, codec_par->extradata_size);
 
-            existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), codec_context->extradata, codec_context->extradata_size);
+            existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), codec_par->extradata, codec_par->extradata_size);
             if (!existing_acTL_chunk) {
                 uint8_t buf[8];
                 // Write animation control header
diff --git a/libavformat/aqtitledec.c b/libavformat/aqtitledec.c
index 7c864c8..f0e840b 100644
--- a/libavformat/aqtitledec.c
+++ b/libavformat/aqtitledec.c
@@ -58,8 +58,8 @@ static int aqt_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, aqt->frame_rate.den, aqt->frame_rate.num);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_TEXT;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_TEXT;
 
     while (!avio_feof(s->pb)) {
         char line[4096];
diff --git a/libavformat/asf.c b/libavformat/asf.c
index 455ca4d..719cae9 100644
--- a/libavformat/asf.c
+++ b/libavformat/asf.c
@@ -147,6 +147,14 @@ const ff_asf_guid ff_asf_extended_stream_properties_object = {
     0xcb, 0xa5, 0xe6, 0x14, 0x72, 0xc6, 0x32, 0x43, 0x83, 0x99, 0xa9, 0x69, 0x52, 0x06, 0x5b, 0x5a
 };
 
+const ff_asf_guid ff_asf_group_mutual_exclusion_object = {
+    0x40, 0x5a, 0x46, 0xd1, 0x79, 0x5a, 0x38, 0x43, 0xb7, 0x1b, 0xe3, 0x6b, 0x8f, 0xd6, 0xc2, 0x49
+};
+
+const ff_asf_guid ff_asf_mutex_language = {
+    0x00, 0x2a, 0xe2, 0xd6, 0xda, 0x35, 0xd1, 0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe
+};
+
 /* List of official tags at http://msdn.microsoft.com/en-us/library/dd743066(VS.85).aspx */
 const AVMetadataConv ff_asf_metadata_conv[] = {
     { "WM/AlbumArtist",          "album_artist"     },
diff --git a/libavformat/asf.h b/libavformat/asf.h
index 914ddef..1a5b338 100644
--- a/libavformat/asf.h
+++ b/libavformat/asf.h
@@ -48,7 +48,7 @@ typedef struct ASFMainHeader {
                                  *   invalid if broadcasting (could be ignored) */
     uint32_t preroll;           /**< timestamp of the first packet, in milliseconds
                                  *   if nonzero - subtract from time */
-    uint32_t ignore;            ///< preroll is 64bit - but let's just ignore it
+    uint32_t ignore;            ///< preroll is 64 bits - but let's just ignore it
     uint32_t flags;             /**< 0x01 - broadcast
                                  *   0x02 - seekable
                                  *   rest is reserved should be 0 */
@@ -100,6 +100,8 @@ extern const ff_asf_guid ff_asf_content_encryption;
 extern const ff_asf_guid ff_asf_ext_content_encryption;
 extern const ff_asf_guid ff_asf_digital_signature;
 extern const ff_asf_guid ff_asf_extended_stream_properties_object;
+extern const ff_asf_guid ff_asf_group_mutual_exclusion_object;
+extern const ff_asf_guid ff_asf_mutex_language;
 
 extern const AVMetadataConv ff_asf_metadata_conv[];
 
diff --git a/libavformat/asfdec_f.c b/libavformat/asfdec_f.c
index 3ee0fcd..2c81b13 100644
--- a/libavformat/asfdec_f.c
+++ b/libavformat/asfdec_f.c
@@ -281,8 +281,8 @@ static int asf_read_picture(AVFormatContext *s, int len)
         goto fail;
     }
     st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
-    st->codec->codec_type         = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id           = id;
+    st->codecpar->codec_type      = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id        = id;
     st->attached_pic              = pkt;
     st->attached_pic.stream_index = st->index;
     st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
@@ -436,7 +436,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size)
         type = AVMEDIA_TYPE_VIDEO;
     } else if (!ff_guidcmp(&g, &ff_asf_jfif_media)) {
         type                = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id = AV_CODEC_ID_MJPEG;
+        st->codecpar->codec_id = AV_CODEC_ID_MJPEG;
     } else if (!ff_guidcmp(&g, &ff_asf_command_stream)) {
         type = AVMEDIA_TYPE_DATA;
     } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) {
@@ -470,18 +470,18 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size)
         }
     }
 
-    st->codec->codec_type = type;
+    st->codecpar->codec_type = type;
     if (type == AVMEDIA_TYPE_AUDIO) {
-        int ret = ff_get_wav_header(s, pb, st->codec, type_specific_size, 0);
+        int ret = ff_get_wav_header(s, pb, st->codecpar, type_specific_size, 0);
         if (ret < 0)
             return ret;
         if (is_dvr_ms_audio) {
             // codec_id and codec_tag are unreliable in dvr_ms
             // files. Set them later by probing stream.
             st->request_probe    = 1;
-            st->codec->codec_tag = 0;
+            st->codecpar->codec_tag = 0;
         }
-        if (st->codec->codec_id == AV_CODEC_ID_AAC)
+        if (st->codecpar->codec_id == AV_CODEC_ID_AAC)
             st->need_parsing = AVSTREAM_PARSE_NONE;
         else
             st->need_parsing = AVSTREAM_PARSE_FULL;
@@ -507,52 +507,52 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size)
         avio_r8(pb);
         avio_rl16(pb);        /* size */
         sizeX             = avio_rl32(pb); /* size */
-        st->codec->width  = avio_rl32(pb);
-        st->codec->height = avio_rl32(pb);
+        st->codecpar->width  = avio_rl32(pb);
+        st->codecpar->height = avio_rl32(pb);
         /* not available for asf */
         avio_rl16(pb); /* panes */
-        st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */
+        st->codecpar->bits_per_coded_sample = avio_rl16(pb); /* depth */
         tag1                             = avio_rl32(pb);
         avio_skip(pb, 20);
         if (sizeX > 40) {
-            st->codec->extradata_size = ffio_limit(pb, sizeX - 40);
-            st->codec->extradata      = av_mallocz(st->codec->extradata_size +
+            st->codecpar->extradata_size = ffio_limit(pb, sizeX - 40);
+            st->codecpar->extradata      = av_mallocz(st->codecpar->extradata_size +
                                                    AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!st->codec->extradata)
+            if (!st->codecpar->extradata)
                 return AVERROR(ENOMEM);
-            avio_read(pb, st->codec->extradata, st->codec->extradata_size);
+            avio_read(pb, st->codecpar->extradata, st->codecpar->extradata_size);
         }
 
         /* Extract palette from extradata if bpp <= 8 */
         /* This code assumes that extradata contains only palette */
         /* This is true for all paletted codecs implemented in libavcodec */
-        if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) {
+        if (st->codecpar->extradata_size && (st->codecpar->bits_per_coded_sample <= 8)) {
 #if HAVE_BIGENDIAN
             int i;
-            for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE) / 4; i++)
-                asf_st->palette[i] = av_bswap32(((uint32_t *)st->codec->extradata)[i]);
+            for (i = 0; i < FFMIN(st->codecpar->extradata_size, AVPALETTE_SIZE) / 4; i++)
+                asf_st->palette[i] = av_bswap32(((uint32_t *)st->codecpar->extradata)[i]);
 #else
-            memcpy(asf_st->palette, st->codec->extradata,
-                   FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
+            memcpy(asf_st->palette, st->codecpar->extradata,
+                   FFMIN(st->codecpar->extradata_size, AVPALETTE_SIZE));
 #endif
             asf_st->palette_changed = 1;
         }
 
-        st->codec->codec_tag = tag1;
-        st->codec->codec_id  = ff_codec_get_id(ff_codec_bmp_tags, tag1);
+        st->codecpar->codec_tag = tag1;
+        st->codecpar->codec_id  = ff_codec_get_id(ff_codec_bmp_tags, tag1);
         if (tag1 == MKTAG('D', 'V', 'R', ' ')) {
             st->need_parsing = AVSTREAM_PARSE_FULL;
             /* issue658 contains wrong w/h and MS even puts a fake seq header
              * with wrong w/h in extradata while a correct one is in the stream.
              * maximum lameness */
-            st->codec->width      =
-                st->codec->height = 0;
-            av_freep(&st->codec->extradata);
-            st->codec->extradata_size = 0;
+            st->codecpar->width      =
+                st->codecpar->height = 0;
+            av_freep(&st->codecpar->extradata);
+            st->codecpar->extradata_size = 0;
         }
-        if (st->codec->codec_id == AV_CODEC_ID_H264)
+        if (st->codecpar->codec_id == AV_CODEC_ID_H264)
             st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;
-        if (st->codec->codec_id == AV_CODEC_ID_MPEG4)
+        if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4)
             st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;
     }
     pos2 = avio_tell(pb);
@@ -828,7 +828,7 @@ static int asf_read_header(AVFormatContext *s)
         } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_header)) {
             asf_read_ext_stream_properties(s, gsize);
 
-            // there could be a optional stream properties object to follow
+            // there could be an optional stream properties object to follow
             // if so the next iteration will pick it up
             continue;
         } else if (!ff_guidcmp(&g, &ff_asf_head1_guid)) {
@@ -890,21 +890,21 @@ static int asf_read_header(AVFormatContext *s)
         int stream_num = asf->asfid2avid[i];
         if (stream_num >= 0) {
             AVStream *st = s->streams[stream_num];
-            if (!st->codec->bit_rate)
-                st->codec->bit_rate = asf->stream_bitrates[i];
+            if (!st->codecpar->bit_rate)
+                st->codecpar->bit_rate = asf->stream_bitrates[i];
             if (asf->dar[i].num > 0 && asf->dar[i].den > 0) {
                 av_reduce(&st->sample_aspect_ratio.num,
                           &st->sample_aspect_ratio.den,
                           asf->dar[i].num, asf->dar[i].den, INT_MAX);
             } else if ((asf->dar[0].num > 0) && (asf->dar[0].den > 0) &&
                        // Use ASF container value if the stream doesn't set AR.
-                       (st->codec->codec_type == AVMEDIA_TYPE_VIDEO))
+                       (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO))
                 av_reduce(&st->sample_aspect_ratio.num,
                           &st->sample_aspect_ratio.den,
                           asf->dar[0].num, asf->dar[0].den, INT_MAX);
 
-            av_log(s, AV_LOG_TRACE, "i=%d, st->codec->codec_type:%d, asf->dar %d:%d sar=%d:%d\n",
-                    i, st->codec->codec_type, asf->dar[i].num, asf->dar[i].den,
+            av_log(s, AV_LOG_TRACE, "i=%d, st->codecpar->codec_type:%d, asf->dar %d:%d sar=%d:%d\n",
+                    i, st->codecpar->codec_type, asf->dar[i].num, asf->dar[i].den,
                     st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
 
             // copy and convert language codes to the frontend
@@ -1316,9 +1316,9 @@ static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
             av_log(asf, AV_LOG_TRACE, "new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n",
                     asf->stream_index, asf->packet_key_frame,
                     asf_st->pkt.flags & AV_PKT_FLAG_KEY,
-                    s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO,
+                    s->streams[asf->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO,
                     asf_st->packet_obj_size);
-            if (s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+            if (s->streams[asf->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
                 asf->packet_key_frame = 1;
             if (asf->packet_key_frame)
                 asf_st->pkt.flags |= AV_PKT_FLAG_KEY;
@@ -1371,7 +1371,7 @@ static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
         /* test if whole packet is read */
         if (asf_st->frag_offset == asf_st->pkt.size) {
             // workaround for macroshit radio DVR-MS files
-            if (s->streams[asf->stream_index]->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
+            if (s->streams[asf->stream_index]->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
                 asf_st->pkt.size > 100) {
                 int i;
                 for (i = 0; i < asf_st->pkt.size && !asf_st->pkt.data[i]; i++)
@@ -1492,7 +1492,7 @@ static void skip_to_key(AVFormatContext *s)
     for (i = 0; i < 128; i++) {
         int j = asf->asfid2avid[i];
         ASFStream *asf_st = &asf->streams[i];
-        if (j < 0 || s->streams[j]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
+        if (j < 0 || s->streams[j]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
             continue;
 
         asf_st->skip_to_key = 1;
diff --git a/libavformat/asfdec_o.c b/libavformat/asfdec_o.c
index 2320c66..9eefa5a 100644
--- a/libavformat/asfdec_o.c
+++ b/libavformat/asfdec_o.c
@@ -20,7 +20,6 @@
  */
 
 #include "libavutil/attributes.h"
-#include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/bswap.h"
 #include "libavutil/common.h"
@@ -122,8 +121,8 @@ typedef struct ASFContext {
 
     int stream_index; // from packet header, for the subpayload case
 
-    // packet parameteres
-    uint64_t sub_header_offset; // offset of subplayload header
+    // packet parameters
+    uint64_t sub_header_offset; // offset of subpayload header
     int64_t sub_dts;
     uint8_t dts_delta; // for subpayloads
     uint32_t packet_size_internal; // packet size stored inside ASFPacket, can be 0
@@ -431,8 +430,8 @@ static int asf_read_picture(AVFormatContext *s, int len)
     }
 
     st->disposition              |= AV_DISPOSITION_ATTACHED_PIC;
-    st->codec->codec_type         = asf_st->type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id           = id;
+    st->codecpar->codec_type      = asf_st->type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id        = id;
     st->attached_pic              = pkt;
     st->attached_pic.stream_index = asf_st->index = st->index;
     st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
@@ -695,26 +694,26 @@ static int parse_video_info(AVIOContext *pb, AVStream *st)
     uint16_t size;
     unsigned int tag;
 
-    st->codec->width  = avio_rl32(pb);
-    st->codec->height = avio_rl32(pb);
+    st->codecpar->width  = avio_rl32(pb);
+    st->codecpar->height = avio_rl32(pb);
     avio_skip(pb, 1); // skip reserved flags
     size = avio_rl16(pb); // size of the Format Data
     tag  = ff_get_bmp_header(pb, st, NULL);
-    st->codec->codec_tag = tag;
-    st->codec->codec_id  = ff_codec_get_id(ff_codec_bmp_tags, tag);
+    st->codecpar->codec_tag = tag;
+    st->codecpar->codec_id  = ff_codec_get_id(ff_codec_bmp_tags, tag);
 
     if (size > BMP_HEADER_SIZE) {
         int ret;
-        st->codec->extradata_size  = size - BMP_HEADER_SIZE;
-        if (!(st->codec->extradata = av_malloc(st->codec->extradata_size +
+        st->codecpar->extradata_size  = size - BMP_HEADER_SIZE;
+        if (!(st->codecpar->extradata = av_malloc(st->codecpar->extradata_size +
                                                AV_INPUT_BUFFER_PADDING_SIZE))) {
-            st->codec->extradata_size = 0;
+            st->codecpar->extradata_size = 0;
             return AVERROR(ENOMEM);
         }
-        memset(st->codec->extradata + st->codec->extradata_size , 0,
+        memset(st->codecpar->extradata + st->codecpar->extradata_size , 0,
                AV_INPUT_BUFFER_PADDING_SIZE);
-        if ((ret = avio_read(pb, st->codec->extradata,
-                             st->codec->extradata_size)) < 0)
+        if ((ret = avio_read(pb, st->codecpar->extradata,
+                             st->codecpar->extradata_size)) < 0)
             return ret;
     }
     return 0;
@@ -773,7 +772,7 @@ static int asf_read_stream_properties(AVFormatContext *s, const GUIDParseTable *
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 32, 1, 1000); // pts should be dword, in milliseconds
-    st->codec->codec_type = type;
+    st->codecpar->codec_type = type;
     asf->asf_st[asf->nb_streams] = av_mallocz(sizeof(*asf_st));
     if (!asf->asf_st[asf->nb_streams])
         return AVERROR(ENOMEM);
@@ -790,7 +789,7 @@ static int asf_read_stream_properties(AVFormatContext *s, const GUIDParseTable *
     switch (type) {
     case AVMEDIA_TYPE_AUDIO:
         asf_st->type = AVMEDIA_TYPE_AUDIO;
-        if ((ret = ff_get_wav_header(s, pb, st->codec, ts_data_len, 0)) < 0)
+        if ((ret = ff_get_wav_header(s, pb, st->codecpar, ts_data_len, 0)) < 0)
             return ret;
         break;
     case AVMEDIA_TYPE_VIDEO:
@@ -867,7 +866,7 @@ static int asf_read_ext_stream_properties(AVFormatContext *s, const GUIDParseTab
     if (st) {
         st->start_time           = start_time;
         st->duration             = end_time - start_time;
-        st->codec->bit_rate      = bitrate;
+        st->codecpar->bit_rate   = bitrate;
         st->avg_frame_rate.num   = 10000000;
         st->avg_frame_rate.den   = time_per_frame;
     }
diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c
index 14f92e2..88f01e0 100644
--- a/libavformat/asfenc.c
+++ b/libavformat/asfenc.c
@@ -227,7 +227,7 @@ typedef struct ASFContext {
     const char *languages[128];
     int nb_languages;
     int64_t creation_time;
-    /* non streamed additonnal info */
+    /* non-streamed additional info */
     uint64_t nb_packets;                 ///< how many packets are there in the file, invalid if broadcasting
     int64_t duration;                    ///< in 100ns units
     /* packet filling */
@@ -392,10 +392,11 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
     int header_size, n, extra_size, extra_size2, wav_extra_size;
     int has_title, has_aspect_ratio = 0;
     int metadata_count;
-    AVCodecContext *enc;
+    AVCodecParameters *par;
     int64_t header_offset, cur_pos, hpos;
     int bit_rate;
     int64_t duration;
+    int audio_language_counts[128] = { 0 };
 
     ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);
 
@@ -418,14 +419,14 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
     bit_rate = 0;
     for (n = 0; n < s->nb_streams; n++) {
         AVDictionaryEntry *entry;
-        enc = s->streams[n]->codec;
+        par = s->streams[n]->codecpar;
 
         avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */
 
-        bit_rate += enc->bit_rate;
-        if (   enc->codec_type == AVMEDIA_TYPE_VIDEO
-            && enc->sample_aspect_ratio.num > 0
-            && enc->sample_aspect_ratio.den > 0)
+        bit_rate += par->bit_rate;
+        if (   par->codec_type == AVMEDIA_TYPE_VIDEO
+            && par->sample_aspect_ratio.num > 0
+            && par->sample_aspect_ratio.den > 0)
             has_aspect_ratio++;
 
         entry = av_dict_get(s->streams[n]->metadata, "language", NULL, 0);
@@ -444,6 +445,8 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
                     asf->streams[n].stream_language_index = asf->nb_languages;
                     asf->nb_languages++;
                 }
+                if (par->codec_type == AVMEDIA_TYPE_AUDIO)
+                    audio_language_counts[asf->streams[n].stream_language_index]++;
             }
         } else {
             asf->streams[n].stream_language_index = 128;
@@ -484,6 +487,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
     if (asf->nb_languages) {
         int64_t hpos2;
         int i;
+        int nb_audio_languages = 0;
 
         hpos2 = put_header(pb, &ff_asf_language_guid);
         avio_wl16(pb, asf->nb_languages);
@@ -493,6 +497,25 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
         }
         end_header(pb, hpos2);
 
+        for (i = 0; i < asf->nb_languages; i++)
+            if (audio_language_counts[i])
+                nb_audio_languages++;
+
+        if (nb_audio_languages > 1) {
+            hpos2 = put_header(pb, &ff_asf_group_mutual_exclusion_object);
+            ff_put_guid(pb, &ff_asf_mutex_language);
+            avio_wl16(pb, nb_audio_languages);
+            for (i = 0; i < asf->nb_languages; i++) {
+                if (audio_language_counts[i]) {
+                    avio_wl16(pb, audio_language_counts[i]);
+                    for (n = 0; n < s->nb_streams; n++)
+                        if (asf->streams[n].stream_language_index == i && s->streams[n]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
+                            avio_wl16(pb, n + 1);
+                }
+            }
+            end_header(pb, hpos2);
+        }
+
         for (n = 0; n < s->nb_streams; n++) {
             int64_t es_pos;
             if (asf->streams[n].stream_language_index > 127)
@@ -500,10 +523,10 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
             es_pos = put_header(pb, &ff_asf_extended_stream_properties_object);
             avio_wl64(pb, 0); /* start time */
             avio_wl64(pb, 0); /* end time */
-            avio_wl32(pb, s->streams[n]->codec->bit_rate); /* data bitrate bps */
+            avio_wl32(pb, s->streams[n]->codecpar->bit_rate); /* data bitrate bps */
             avio_wl32(pb, 5000); /* buffer size ms */
             avio_wl32(pb, 0); /* initial buffer fullness */
-            avio_wl32(pb, s->streams[n]->codec->bit_rate); /* peak data bitrate */
+            avio_wl32(pb, s->streams[n]->codecpar->bit_rate); /* peak data bitrate */
             avio_wl32(pb, 5000); /* maximum buffer size ms */
             avio_wl32(pb, 0); /* max initial buffer fullness */
             avio_wl32(pb, 0); /* max object size */
@@ -521,11 +544,11 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
         hpos2 = put_header(pb, &ff_asf_metadata_header);
         avio_wl16(pb, 2 * has_aspect_ratio);
         for (n = 0; n < s->nb_streams; n++) {
-            enc = s->streams[n]->codec;
-            if (   enc->codec_type == AVMEDIA_TYPE_VIDEO
-                && enc->sample_aspect_ratio.num > 0
-                && enc->sample_aspect_ratio.den > 0) {
-                AVRational sar = enc->sample_aspect_ratio;
+            par = s->streams[n]->codecpar;
+            if (   par->codec_type == AVMEDIA_TYPE_VIDEO
+                && par->sample_aspect_ratio.num > 0
+                && par->sample_aspect_ratio.den > 0) {
+                AVRational sar = par->sample_aspect_ratio;
                 avio_wl16(pb, 0);
                 // the stream number is set like this below
                 avio_wl16(pb, n + 1);
@@ -555,7 +578,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
     }
     end_header(pb, hpos);
 
-    /* title and other infos */
+    /* title and other info */
     if (has_title) {
         int len;
         uint8_t *buf;
@@ -597,11 +620,11 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
         int64_t es_pos;
         //        ASFStream *stream = &asf->streams[n];
 
-        enc                 = s->streams[n]->codec;
+        par                 = s->streams[n]->codecpar;
         asf->streams[n].num = n + 1;
         asf->streams[n].seq = 1;
 
-        switch (enc->codec_type) {
+        switch (par->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
             wav_extra_size = 0;
             extra_size     = 18 + wav_extra_size;
@@ -609,14 +632,14 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
             break;
         default:
         case AVMEDIA_TYPE_VIDEO:
-            wav_extra_size = enc->extradata_size;
+            wav_extra_size = par->extradata_size;
             extra_size     = 0x33 + wav_extra_size;
             extra_size2    = 0;
             break;
         }
 
         hpos = put_header(pb, &ff_asf_stream_header);
-        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
             ff_put_guid(pb, &ff_asf_audio_stream);
             ff_put_guid(pb, &ff_asf_audio_conceal_spread);
         } else {
@@ -630,9 +653,9 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
         avio_wl16(pb, n + 1); /* stream number */
         avio_wl32(pb, 0); /* ??? */
 
-        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
             /* WAVEFORMATEX header */
-            int wavsize = ff_put_wav_header(pb, enc, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
+            int wavsize = ff_put_wav_header(s, pb, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
 
             if (wavsize < 0)
                 return -1;
@@ -644,23 +667,23 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
             }
             /* ERROR Correction */
             avio_w8(pb, 0x01);
-            if (enc->codec_id == AV_CODEC_ID_ADPCM_G726 || !enc->block_align) {
+            if (par->codec_id == AV_CODEC_ID_ADPCM_G726 || !par->block_align) {
                 avio_wl16(pb, 0x0190);
                 avio_wl16(pb, 0x0190);
             } else {
-                avio_wl16(pb, enc->block_align);
-                avio_wl16(pb, enc->block_align);
+                avio_wl16(pb, par->block_align);
+                avio_wl16(pb, par->block_align);
             }
             avio_wl16(pb, 0x01);
             avio_w8(pb, 0x00);
         } else {
-            avio_wl32(pb, enc->width);
-            avio_wl32(pb, enc->height);
+            avio_wl32(pb, par->width);
+            avio_wl32(pb, par->height);
             avio_w8(pb, 2); /* ??? */
-            avio_wl16(pb, 40 + enc->extradata_size); /* size */
+            avio_wl16(pb, 40 + par->extradata_size); /* size */
 
             /* BITMAPINFOHEADER header */
-            ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1, 0);
+            ff_put_bmp_header(pb, par, ff_codec_bmp_tags, 1, 0);
         }
         end_header(pb, hpos);
     }
@@ -674,17 +697,17 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
         const AVCodecDescriptor *codec_desc;
         const char *desc;
 
-        enc  = s->streams[n]->codec;
-        codec_desc = avcodec_descriptor_get(enc->codec_id);
+        par  = s->streams[n]->codecpar;
+        codec_desc = avcodec_descriptor_get(par->codec_id);
 
-        if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
+        if (par->codec_type == AVMEDIA_TYPE_AUDIO)
             avio_wl16(pb, 2);
-        else if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
+        else if (par->codec_type == AVMEDIA_TYPE_VIDEO)
             avio_wl16(pb, 1);
         else
             avio_wl16(pb, -1);
 
-        if (enc->codec_id == AV_CODEC_ID_WMAV2)
+        if (par->codec_id == AV_CODEC_ID_WMAV2)
             desc = "Windows Media Audio V8";
         else
             desc = codec_desc ? codec_desc->name : NULL;
@@ -709,14 +732,14 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
         avio_wl16(pb, 0); /* no parameters */
 
         /* id */
-        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
             avio_wl16(pb, 2);
-            avio_wl16(pb, enc->codec_tag);
+            avio_wl16(pb, par->codec_tag);
         } else {
             avio_wl16(pb, 4);
-            avio_wl32(pb, enc->codec_tag);
+            avio_wl32(pb, par->codec_tag);
         }
-        if (!enc->codec_tag)
+        if (!par->codec_tag)
             return -1;
     }
     end_header(pb, hpos);
@@ -940,7 +963,7 @@ static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst,
                         PACKET_HEADER_MIN_SIZE - 1;
 
             if (frag_len1 < payload_len &&
-                avst->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+                avst->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                 flush_packet(s);
                 continue;
             }
@@ -1030,7 +1053,7 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
     ASFContext *asf = s->priv_data;
     AVIOContext *pb = s->pb;
     ASFStream *stream;
-    AVCodecContext *codec;
+    AVCodecParameters *par;
     uint32_t packet_number;
     int64_t pts;
     int start_sec;
@@ -1038,10 +1061,10 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
     int ret;
     uint64_t offset = avio_tell(pb);
 
-    codec  = s->streams[pkt->stream_index]->codec;
+    par  = s->streams[pkt->stream_index]->codecpar;
     stream = &asf->streams[pkt->stream_index];
 
-    if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
+    if (par->codec_type == AVMEDIA_TYPE_AUDIO)
         flags &= ~AV_PKT_FLAG_KEY;
 
     pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts;
diff --git a/libavformat/assdec.c b/libavformat/assdec.c
index 21148b6..d89c14e 100644
--- a/libavformat/assdec.c
+++ b/libavformat/assdec.c
@@ -121,8 +121,8 @@ static int ass_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 100);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_ASS;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_ASS;
 
     av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED);
     av_bprint_init(&line,   0, AV_BPRINT_SIZE_UNLIMITED);
@@ -153,7 +153,7 @@ static int ass_read_header(AVFormatContext *s)
         sub->duration = duration;
     }
 
-    res = avpriv_bprint_to_extradata(st->codec, &header);
+    res = ff_bprint_to_codecpar_extradata(st->codecpar, &header);
     if (res < 0)
         goto end;
 
diff --git a/libavformat/assenc.c b/libavformat/assenc.c
index e59c266..d50f18f 100644
--- a/libavformat/assenc.c
+++ b/libavformat/assenc.c
@@ -33,7 +33,6 @@ typedef struct DialogueLine {
 
 typedef struct ASSContext {
     const AVClass *class;
-    int write_ts; // 0: ssa (timing in payload), 1: ass (matroska like)
     int expected_readorder;
     DialogueLine *dialogue_cache;
     DialogueLine *last_added_dialogue;
@@ -47,18 +46,16 @@ typedef struct ASSContext {
 static int write_header(AVFormatContext *s)
 {
     ASSContext *ass = s->priv_data;
-    AVCodecContext *avctx = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (s->nb_streams != 1 || (avctx->codec_id != AV_CODEC_ID_SSA &&
-                               avctx->codec_id != AV_CODEC_ID_ASS)) {
+    if (s->nb_streams != 1 || par->codec_id != AV_CODEC_ID_ASS) {
         av_log(s, AV_LOG_ERROR, "Exactly one ASS/SSA stream is needed.\n");
         return AVERROR(EINVAL);
     }
-    ass->write_ts = avctx->codec_id == AV_CODEC_ID_ASS;
     avpriv_set_pts_info(s->streams[0], 64, 1, 100);
-    if (avctx->extradata_size > 0) {
-        size_t header_size = avctx->extradata_size;
-        uint8_t *trailer = strstr(avctx->extradata, "\n[Events]");
+    if (par->extradata_size > 0) {
+        size_t header_size = par->extradata_size;
+        uint8_t *trailer = strstr(par->extradata, "\n[Events]");
 
         if (trailer)
             trailer = strstr(trailer, "Format:");
@@ -66,17 +63,17 @@ static int write_header(AVFormatContext *s)
             trailer = strstr(trailer, "\n");
 
         if (trailer++) {
-            header_size = (trailer - avctx->extradata);
-            ass->trailer_size = avctx->extradata_size - header_size;
+            header_size = (trailer - par->extradata);
+            ass->trailer_size = par->extradata_size - header_size;
             if (ass->trailer_size)
                 ass->trailer = trailer;
         }
 
-        avio_write(s->pb, avctx->extradata, header_size);
-        if (avctx->extradata[header_size - 1] != '\n')
+        avio_write(s->pb, par->extradata, header_size);
+        if (par->extradata[header_size - 1] != '\n')
             avio_write(s->pb, "\r\n", 2);
-        ass->ssa_mode = !strstr(avctx->extradata, "\n[V4+ Styles]");
-        if (!strstr(avctx->extradata, "\n[Events]"))
+        ass->ssa_mode = !strstr(par->extradata, "\n[V4+ Styles]");
+        if (!strstr(par->extradata, "\n[Events]"))
             avio_printf(s->pb, "[Events]\r\nFormat: %s, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n",
                         ass->ssa_mode ? "Marked" : "Layer");
     }
@@ -159,50 +156,46 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     ASSContext *ass = s->priv_data;
 
-    if (ass->write_ts) {
-        long int layer;
-        char *p = pkt->data;
-        int64_t start = pkt->pts;
-        int64_t end   = start + pkt->duration;
-        int hh1, mm1, ss1, ms1;
-        int hh2, mm2, ss2, ms2;
-        DialogueLine *dialogue = av_mallocz(sizeof(*dialogue));
-
-        if (!dialogue)
-            return AVERROR(ENOMEM);
-
-        dialogue->readorder = strtol(p, &p, 10);
-        if (dialogue->readorder < ass->expected_readorder)
-            av_log(s, AV_LOG_WARNING, "Unexpected ReadOrder %d\n",
-                   dialogue->readorder);
-        if (*p == ',')
-            p++;
-
-        if (ass->ssa_mode && !strncmp(p, "Marked=", 7))
-            p += 7;
-
-        layer = strtol(p, &p, 10);
-        if (*p == ',')
-            p++;
-        hh1 = (int)(start / 360000);    mm1 = (int)(start / 6000) % 60;
-        hh2 = (int)(end   / 360000);    mm2 = (int)(end   / 6000) % 60;
-        ss1 = (int)(start / 100) % 60;  ms1 = (int)(start % 100);
-        ss2 = (int)(end   / 100) % 60;  ms2 = (int)(end   % 100);
-        if (hh1 > 9) hh1 = 9, mm1 = 59, ss1 = 59, ms1 = 99;
-        if (hh2 > 9) hh2 = 9, mm2 = 59, ss2 = 59, ms2 = 99;
-
-        dialogue->line = av_asprintf("%s%ld,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s",
-                                     ass->ssa_mode ? "Marked=" : "",
-                                     layer, hh1, mm1, ss1, ms1, hh2, mm2, ss2, ms2, p);
-        if (!dialogue->line) {
-            av_free(dialogue);
-            return AVERROR(ENOMEM);
-        }
-        insert_dialogue(ass, dialogue);
-        purge_dialogues(s, ass->ignore_readorder);
-    } else {
-        avio_write(s->pb, pkt->data, pkt->size);
+    long int layer;
+    char *p = pkt->data;
+    int64_t start = pkt->pts;
+    int64_t end   = start + pkt->duration;
+    int hh1, mm1, ss1, ms1;
+    int hh2, mm2, ss2, ms2;
+    DialogueLine *dialogue = av_mallocz(sizeof(*dialogue));
+
+    if (!dialogue)
+        return AVERROR(ENOMEM);
+
+    dialogue->readorder = strtol(p, &p, 10);
+    if (dialogue->readorder < ass->expected_readorder)
+        av_log(s, AV_LOG_WARNING, "Unexpected ReadOrder %d\n",
+               dialogue->readorder);
+    if (*p == ',')
+        p++;
+
+    if (ass->ssa_mode && !strncmp(p, "Marked=", 7))
+        p += 7;
+
+    layer = strtol(p, &p, 10);
+    if (*p == ',')
+        p++;
+    hh1 = (int)(start / 360000);    mm1 = (int)(start / 6000) % 60;
+    hh2 = (int)(end   / 360000);    mm2 = (int)(end   / 6000) % 60;
+    ss1 = (int)(start / 100) % 60;  ms1 = (int)(start % 100);
+    ss2 = (int)(end   / 100) % 60;  ms2 = (int)(end   % 100);
+    if (hh1 > 9) hh1 = 9, mm1 = 59, ss1 = 59, ms1 = 99;
+    if (hh2 > 9) hh2 = 9, mm2 = 59, ss2 = 59, ms2 = 99;
+
+    dialogue->line = av_asprintf("%s%ld,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,%s",
+                                 ass->ssa_mode ? "Marked=" : "",
+                                 layer, hh1, mm1, ss1, ms1, hh2, mm2, ss2, ms2, p);
+    if (!dialogue->line) {
+        av_free(dialogue);
+        return AVERROR(ENOMEM);
     }
+    insert_dialogue(ass, dialogue);
+    purge_dialogues(s, ass->ignore_readorder);
 
     return 0;
 }
@@ -237,10 +230,10 @@ static const AVClass ass_class = {
 AVOutputFormat ff_ass_muxer = {
     .name           = "ass",
     .long_name      = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"),
-    .mime_type      = "text/x-ssa",
+    .mime_type      = "text/x-ass",
     .extensions     = "ass,ssa",
     .priv_data_size = sizeof(ASSContext),
-    .subtitle_codec = AV_CODEC_ID_SSA,
+    .subtitle_codec = AV_CODEC_ID_ASS,
     .write_header   = write_header,
     .write_packet   = write_packet,
     .write_trailer  = write_trailer,
diff --git a/libavformat/astdec.c b/libavformat/astdec.c
index 92c208d..f3ca721 100644
--- a/libavformat/astdec.c
+++ b/libavformat/astdec.c
@@ -48,8 +48,8 @@ static int ast_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     avio_skip(s->pb, 8);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id   = ff_codec_get_id(ff_codec_ast_tags, avio_rb16(s->pb));
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id   = ff_codec_get_id(ff_codec_ast_tags, avio_rb16(s->pb));
 
     depth = avio_rb16(s->pb);
     if (depth != 16) {
@@ -57,23 +57,23 @@ static int ast_read_header(AVFormatContext *s)
         return AVERROR_INVALIDDATA;
     }
 
-    st->codec->channels = avio_rb16(s->pb);
-    if (!st->codec->channels)
+    st->codecpar->channels = avio_rb16(s->pb);
+    if (!st->codecpar->channels)
         return AVERROR_INVALIDDATA;
 
-    if (st->codec->channels == 2)
-        st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
-    else if (st->codec->channels == 4)
-        st->codec->channel_layout = AV_CH_LAYOUT_4POINT0;
+    if (st->codecpar->channels == 2)
+        st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+    else if (st->codecpar->channels == 4)
+        st->codecpar->channel_layout = AV_CH_LAYOUT_4POINT0;
 
     avio_skip(s->pb, 2);
-    st->codec->sample_rate = avio_rb32(s->pb);
-    if (st->codec->sample_rate <= 0)
+    st->codecpar->sample_rate = avio_rb32(s->pb);
+    if (st->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
     st->start_time         = 0;
     st->duration           = avio_rb32(s->pb);
     avio_skip(s->pb, 40);
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
@@ -90,10 +90,10 @@ static int ast_read_packet(AVFormatContext *s, AVPacket *pkt)
     pos  = avio_tell(s->pb);
     type = avio_rl32(s->pb);
     size = avio_rb32(s->pb);
-    if (size > INT_MAX / s->streams[0]->codec->channels)
+    if (size > INT_MAX / s->streams[0]->codecpar->channels)
         return AVERROR_INVALIDDATA;
 
-    size *= s->streams[0]->codec->channels;
+    size *= s->streams[0]->codecpar->channels;
     if ((ret = avio_skip(s->pb, 24)) < 0) // padding
         return ret;
 
diff --git a/libavformat/astenc.c b/libavformat/astenc.c
index cf7a12c..11f8717 100644
--- a/libavformat/astenc.c
+++ b/libavformat/astenc.c
@@ -37,7 +37,7 @@ typedef struct ASTMuxContext {
 
 #define CHECK_LOOP(type) \
     if (ast->loop ## type > 0) { \
-        ast->loop ## type = av_rescale_rnd(ast->loop ## type, enc->sample_rate, 1000, AV_ROUND_DOWN); \
+        ast->loop ## type = av_rescale_rnd(ast->loop ## type, par->sample_rate, 1000, AV_ROUND_DOWN); \
         if (ast->loop ## type < 0 || ast->loop ## type > UINT_MAX) { \
             av_log(s, AV_LOG_ERROR, "Invalid loop" #type " value\n"); \
             return AVERROR(EINVAL);  \
@@ -48,22 +48,22 @@ static int ast_write_header(AVFormatContext *s)
 {
     ASTMuxContext *ast = s->priv_data;
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc;
+    AVCodecParameters *par;
     unsigned int codec_tag;
 
     if (s->nb_streams == 1) {
-        enc = s->streams[0]->codec;
+        par = s->streams[0]->codecpar;
     } else {
         av_log(s, AV_LOG_ERROR, "only one stream is supported\n");
         return AVERROR(EINVAL);
     }
 
-    if (enc->codec_id == AV_CODEC_ID_ADPCM_AFC) {
+    if (par->codec_id == AV_CODEC_ID_ADPCM_AFC) {
         av_log(s, AV_LOG_ERROR, "muxing ADPCM AFC is not implemented\n");
         return AVERROR_PATCHWELCOME;
     }
 
-    codec_tag = ff_codec_get_tag(ff_codec_ast_tags, enc->codec_id);
+    codec_tag = ff_codec_get_tag(ff_codec_ast_tags, par->codec_id);
     if (!codec_tag) {
         av_log(s, AV_LOG_ERROR, "unsupported codec\n");
         return AVERROR(EINVAL);
@@ -84,9 +84,9 @@ static int ast_write_header(AVFormatContext *s)
     avio_wb32(pb, 0); /* File size minus header */
     avio_wb16(pb, codec_tag);
     avio_wb16(pb, 16); /* Bit depth */
-    avio_wb16(pb, enc->channels);
+    avio_wb16(pb, par->channels);
     avio_wb16(pb, 0); /* Loop flag */
-    avio_wb32(pb, enc->sample_rate);
+    avio_wb32(pb, par->sample_rate);
 
     ast->samples = avio_tell(pb);
     avio_wb32(pb, 0); /* Number of samples */
@@ -110,8 +110,8 @@ static int ast_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     AVIOContext *pb = s->pb;
     ASTMuxContext *ast = s->priv_data;
-    AVCodecContext *enc = s->streams[0]->codec;
-    int size = pkt->size / enc->channels;
+    AVCodecParameters *par = s->streams[0]->codecpar;
+    int size = pkt->size / par->channels;
 
     if (s->streams[0]->nb_frames == 0)
         ast->fbs = size;
@@ -133,9 +133,9 @@ static int ast_write_trailer(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
     ASTMuxContext *ast = s->priv_data;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int64_t file_size = avio_tell(pb);
-    int64_t samples = (file_size - 64 - (32 * s->streams[0]->nb_frames)) / enc->block_align; /* PCM_S16BE_PLANAR */
+    int64_t samples = (file_size - 64 - (32 * s->streams[0]->nb_frames)) / par->block_align; /* PCM_S16BE_PLANAR */
 
     av_log(s, AV_LOG_DEBUG, "total samples: %"PRId64"\n", samples);
 
diff --git a/libavformat/async.c b/libavformat/async.c
index 138ef13..54dbd23 100644
--- a/libavformat/async.c
+++ b/libavformat/async.c
@@ -251,7 +251,7 @@ static int async_open(URLContext *h, const char *arg, int flags, AVDictionary **
 
     /* wrap interrupt callback */
     c->interrupt_callback = h->interrupt_callback;
-    ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist);
+    ret = ffurl_open_whitelist(&c->inner, arg, flags, &interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist, h);
     if (ret != 0) {
         av_log(h, AV_LOG_ERROR, "ffurl_open failed : %s, %s\n", av_err2str(ret), arg);
         goto url_fail;
@@ -479,7 +479,7 @@ static const AVClass async_context_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_async_protocol = {
+const URLProtocol ff_async_protocol = {
     .name                = "async",
     .url_open2           = async_open,
     .url_read            = async_read,
@@ -489,7 +489,7 @@ URLProtocol ff_async_protocol = {
     .priv_data_class     = &async_context_class,
 };
 
-#ifdef TEST
+#if 0
 
 #define TEST_SEEK_POS    (1536)
 #define TEST_STREAM_SIZE (2048)
@@ -581,7 +581,7 @@ static const AVClass async_test_context_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_async_test_protocol = {
+const URLProtocol ff_async_test_protocol = {
     .name                = "async-test",
     .url_open2           = async_test_open,
     .url_read            = async_test_read,
diff --git a/libavformat/au.c b/libavformat/au.c
index 53702bc..f70f827 100644
--- a/libavformat/au.c
+++ b/libavformat/au.c
@@ -36,7 +36,7 @@
 /* if we don't know the size in advance */
 #define AU_UNKNOWN_SIZE ((uint32_t)(~0))
 /* the specification requires an annotation field of at least eight bytes */
-#define AU_HEADER_SIZE (24+8)
+#define AU_DEFAULT_HEADER_SIZE (24+8)
 
 static const AVCodecTag codec_au_tags[] = {
     { AV_CODEC_ID_PCM_MULAW,  1 },
@@ -66,6 +66,72 @@ static int au_probe(AVProbeData *p)
         return 0;
 }
 
+static int au_read_annotation(AVFormatContext *s, int size)
+{
+    static const char * keys[] = {
+        "title",
+        "artist",
+        "album",
+        "track",
+        "genre",
+        NULL };
+    AVIOContext *pb = s->pb;
+    enum { PARSE_KEY, PARSE_VALUE, PARSE_FINISHED } state = PARSE_KEY;
+    char c;
+    AVBPrint bprint;
+    char * key = NULL;
+    char * value = NULL;
+    int i;
+
+    av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
+
+    while (size-- > 0) {
+        c = avio_r8(pb);
+        switch(state) {
+        case PARSE_KEY:
+            if (c == '\0') {
+                state = PARSE_FINISHED;
+            } else if (c == '=') {
+                av_bprint_finalize(&bprint, &key);
+                av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
+                state = PARSE_VALUE;
+            } else {
+                av_bprint_chars(&bprint, c, 1);
+            }
+            break;
+        case PARSE_VALUE:
+            if (c == '\0' || c == '\n') {
+                if (av_bprint_finalize(&bprint, &value) != 0) {
+                    av_log(s, AV_LOG_ERROR, "Memory error while parsing AU metadata.\n");
+                } else {
+                    av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
+                    for (i = 0; keys[i] != NULL && key != NULL; i++) {
+                        if (av_strcasecmp(keys[i], key) == 0) {
+                            av_dict_set(&(s->metadata), keys[i], value, AV_DICT_DONT_STRDUP_VAL);
+                            av_freep(&key);
+                            value = NULL;
+                        }
+                    }
+                }
+                av_freep(&key);
+                av_freep(&value);
+                state = (c == '\0') ? PARSE_FINISHED : PARSE_KEY;
+            } else {
+                av_bprint_chars(&bprint, c, 1);
+            }
+            break;
+        case PARSE_FINISHED:
+            break;
+        default:
+            /* should never happen */
+            av_assert0(0);
+        }
+    }
+    av_bprint_finalize(&bprint, NULL);
+    av_freep(&key);
+    return 0;
+}
+
 #define BLOCK_SIZE 1024
 
 static int au_read_header(AVFormatContext *s)
@@ -94,8 +160,8 @@ static int au_read_header(AVFormatContext *s)
     channels = avio_rb32(pb);
 
     if (size > 24) {
-        /* skip unused data */
-        avio_skip(pb, size - 24);
+        /* parse annotation field to get metadata */
+        au_read_annotation(s, size - 24);
     }
 
     codec = ff_codec_get_id(codec_au_tags, id);
@@ -132,16 +198,16 @@ static int au_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_tag   = id;
-    st->codec->codec_id    = codec;
-    st->codec->channels    = channels;
-    st->codec->sample_rate = rate;
-    st->codec->bits_per_coded_sample = bps;
-    st->codec->bit_rate    = channels * rate * bps;
-    st->codec->block_align = FFMAX(bps * st->codec->channels / 8, 1);
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_tag   = id;
+    st->codecpar->codec_id    = codec;
+    st->codecpar->channels    = channels;
+    st->codecpar->sample_rate = rate;
+    st->codecpar->bits_per_coded_sample = bps;
+    st->codecpar->bit_rate    = channels * rate * bps;
+    st->codecpar->block_align = FFMAX(bps * st->codecpar->channels / 8, 1);
     if (data_size != AU_UNKNOWN_SIZE)
-    st->duration = (((int64_t)data_size)<<3) / (st->codec->channels * (int64_t)bps);
+        st->duration = (((int64_t)data_size)<<3) / (st->codecpar->channels * (int64_t)bps);
 
     st->start_time = 0;
     avpriv_set_pts_info(st, 64, 1, rate);
@@ -163,31 +229,87 @@ AVInputFormat ff_au_demuxer = {
 
 #if CONFIG_AU_MUXER
 
+typedef struct AUContext {
+    uint32_t header_size;
+} AUContext;
+
 #include "rawenc.h"
 
+static int au_get_annotations(AVFormatContext *s, char **buffer)
+{
+    static const char * keys[] = {
+        "Title",
+        "Artist",
+        "Album",
+        "Track",
+        "Genre",
+        NULL };
+    int i;
+    int cnt = 0;
+    AVDictionary *m = s->metadata;
+    AVDictionaryEntry *t = NULL;
+    AVBPrint bprint;
+
+    av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
+
+    for (i = 0; keys[i] != NULL; i++) {
+        t = av_dict_get(m, keys[i], NULL, 0);
+        if (t != NULL) {
+            if (cnt++)
+                av_bprint_chars(&bprint, '\n', 1);
+            av_bprint_append_data(&bprint, keys[i], strlen(keys[i]));
+            av_bprint_chars(&bprint, '=', 1);
+            av_bprint_append_data(&bprint, t->value, strlen(t->value));
+        }
+    }
+    /* pad with 0's */
+    av_bprint_append_data(&bprint, "\0\0\0\0\0\0\0\0", 8);
+    return av_bprint_finalize(&bprint, buffer);
+}
+
 static int au_write_header(AVFormatContext *s)
 {
+    int ret;
+    AUContext *au = s->priv_data;
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
+    char *annotations = NULL;
+
+    au->header_size = AU_DEFAULT_HEADER_SIZE;
 
     if (s->nb_streams != 1) {
         av_log(s, AV_LOG_ERROR, "only one stream is supported\n");
         return AVERROR(EINVAL);
     }
 
-    enc->codec_tag = ff_codec_get_tag(codec_au_tags, enc->codec_id);
-    if (!enc->codec_tag) {
+    par->codec_tag = ff_codec_get_tag(codec_au_tags, par->codec_id);
+    if (!par->codec_tag) {
         av_log(s, AV_LOG_ERROR, "unsupported codec\n");
         return AVERROR(EINVAL);
     }
 
+    if (av_dict_count(s->metadata) > 0) {
+        ret = au_get_annotations(s, &annotations);
+        if (ret < 0)
+            return ret;
+        if (annotations != NULL) {
+            au->header_size = (24 + strlen(annotations) + 8) & ~7;
+            if (au->header_size < AU_DEFAULT_HEADER_SIZE)
+                au->header_size = AU_DEFAULT_HEADER_SIZE;
+        }
+    }
     ffio_wfourcc(pb, ".snd");                   /* magic number */
-    avio_wb32(pb, AU_HEADER_SIZE);              /* header size */
+    avio_wb32(pb, au->header_size);             /* header size */
     avio_wb32(pb, AU_UNKNOWN_SIZE);             /* data size */
-    avio_wb32(pb, enc->codec_tag);              /* codec ID */
-    avio_wb32(pb, enc->sample_rate);
-    avio_wb32(pb, enc->channels);
-    avio_wb64(pb, 0); /* annotation field */
+    avio_wb32(pb, par->codec_tag);              /* codec ID */
+    avio_wb32(pb, par->sample_rate);
+    avio_wb32(pb, par->channels);
+    if (annotations != NULL) {
+        avio_write(pb, annotations, au->header_size - 24);
+        av_freep(&annotations);
+    } else {
+        avio_wb64(pb, 0); /* annotation field */
+    }
     avio_flush(pb);
 
     return 0;
@@ -196,12 +318,13 @@ static int au_write_header(AVFormatContext *s)
 static int au_write_trailer(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
+    AUContext *au = s->priv_data;
     int64_t file_size = avio_tell(pb);
 
     if (s->pb->seekable && file_size < INT32_MAX) {
         /* update file size */
         avio_seek(pb, 8, SEEK_SET);
-        avio_wb32(pb, (uint32_t)(file_size - AU_HEADER_SIZE));
+        avio_wb32(pb, (uint32_t)(file_size - au->header_size));
         avio_seek(pb, file_size, SEEK_SET);
         avio_flush(pb);
     }
@@ -214,6 +337,7 @@ AVOutputFormat ff_au_muxer = {
     .long_name     = NULL_IF_CONFIG_SMALL("Sun AU"),
     .mime_type     = "audio/basic",
     .extensions    = "au",
+    .priv_data_size = sizeof(AUContext),
     .audio_codec   = AV_CODEC_ID_PCM_S16BE,
     .video_codec   = AV_CODEC_ID_NONE,
     .write_header  = au_write_header,
diff --git a/libavformat/audiointerleave.c b/libavformat/audiointerleave.c
index 6d1401d..6d4954b 100644
--- a/libavformat/audiointerleave.c
+++ b/libavformat/audiointerleave.c
@@ -33,7 +33,7 @@ void ff_audio_interleave_close(AVFormatContext *s)
         AVStream *st = s->streams[i];
         AudioInterleaveContext *aic = st->priv_data;
 
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
             av_fifo_freep(&aic->fifo);
     }
 }
@@ -55,9 +55,9 @@ int ff_audio_interleave_init(AVFormatContext *s,
         AVStream *st = s->streams[i];
         AudioInterleaveContext *aic = st->priv_data;
 
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            aic->sample_size = (st->codec->channels *
-                                av_get_bits_per_sample(st->codec->codec_id)) / 8;
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            aic->sample_size = (st->codecpar->channels *
+                                av_get_bits_per_sample(st->codecpar->codec_id)) / 8;
             if (!aic->sample_size) {
                 av_log(s, AV_LOG_ERROR, "could not compute sample size\n");
                 return AVERROR(EINVAL);
@@ -111,7 +111,7 @@ int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt
     if (pkt) {
         AVStream *st = s->streams[pkt->stream_index];
         AudioInterleaveContext *aic = st->priv_data;
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             unsigned new_size = av_fifo_size(aic->fifo) + pkt->size;
             if (new_size > aic->fifo_size) {
                 if (av_fifo_realloc2(aic->fifo, new_size) < 0)
@@ -131,7 +131,7 @@ int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt
 
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             AVPacket new_pkt = { 0 };
             while ((ret = interleave_new_audio_packet(s, &new_pkt, i, flush)) > 0) {
                 if ((ret = ff_interleave_add_packet(s, &new_pkt, compare_ts)) < 0)
diff --git a/libavformat/avc.c b/libavformat/avc.c
index f7b8f38..094a958 100644
--- a/libavformat/avc.c
+++ b/libavformat/avc.c
@@ -106,7 +106,7 @@ int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
 int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
 {
     if (len > 6) {
-        /* check for h264 start code */
+        /* check for H.264 start code */
         if (AV_RB32(data) == 0x00000001 ||
             AV_RB24(data) == 0x000001) {
             uint8_t *buf=NULL, *end, *start;
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 34bad43..818184e 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -161,8 +161,8 @@
  * av_read_frame() on it. Each call, if successful, will return an AVPacket
  * containing encoded data for one AVStream, identified by
  * AVPacket.stream_index. This packet may be passed straight into the libavcodec
- * decoding functions avcodec_decode_video2(), avcodec_decode_audio4() or
- * avcodec_decode_subtitle2() if the caller wishes to decode the data.
+ * decoding functions avcodec_send_packet() or avcodec_decode_subtitle2() if the
+ * caller wishes to decode the data.
  *
  * AVPacket.pts, AVPacket.dts and AVPacket.duration timing information will be
  * set if known. They may also be unset (i.e. AV_NOPTS_VALUE for
@@ -203,15 +203,15 @@
  *   avio_open2() or a custom one.
  * - Unless the format is of the AVFMT_NOSTREAMS type, at least one stream must
  *   be created with the avformat_new_stream() function. The caller should fill
- *   the @ref AVStream.codec "stream codec context" information, such as the
- *   codec @ref AVCodecContext.codec_type "type", @ref AVCodecContext.codec_id
+ *   the @ref AVStream.codecpar "stream codec parameters" information, such as the
+ *   codec @ref AVCodecParameters.codec_type "type", @ref AVCodecParameters.codec_id
  *   "id" and other parameters (e.g. width / height, the pixel or sample format,
  *   etc.) as known. The @ref AVStream.time_base "stream timebase" should
  *   be set to the timebase that the caller desires to use for this stream (note
  *   that the timebase actually used by the muxer can be different, as will be
  *   described later).
  * - It is advised to manually initialize only the relevant fields in
- *   AVCodecContext, rather than using @ref avcodec_copy_context() during
+ *   AVCodecParameters, rather than using @ref avcodec_parameters_copy() during
  *   remuxing: there is no guarantee that the codec context values remain valid
  *   for both input and output format contexts.
  * - The caller may fill in additional information, such as @ref
@@ -310,7 +310,6 @@
  * @{
  * @}
  * @}
- *
  */
 
 #include <time.h>
@@ -528,7 +527,7 @@ typedef struct AVOutputFormat {
      * can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER,
      * AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS, AVFMT_VARIABLE_FPS,
      * AVFMT_NODIMENSIONS, AVFMT_NOSTREAMS, AVFMT_ALLOW_FLUSH,
-     * AVFMT_TS_NONSTRICT
+     * AVFMT_TS_NONSTRICT, AVFMT_TS_NEGATIVE
      */
     int flags;
 
@@ -873,18 +872,13 @@ typedef struct AVStream {
      * encoding: set by the user, replaced by libavformat if left unset
      */
     int id;
+#if FF_API_LAVF_AVCTX
     /**
-     * Codec context associated with this stream. Allocated and freed by
-     * libavformat.
-     *
-     * - decoding: The demuxer exports codec information stored in the headers
-     *             here.
-     * - encoding: The user sets codec information, the muxer writes it to the
-     *             output. Mandatory fields as specified in AVCodecContext
-     *             documentation must be set even if this AVCodecContext is
-     *             not actually used for encoding.
+     * @deprecated use the codecpar struct instead
      */
+    attribute_deprecated
     AVCodecContext *codec;
+#endif
     void *priv_data;
 
 #if FF_API_LAVF_FRAC
@@ -1212,6 +1206,17 @@ typedef struct AVStream {
      * Must not be accessed in any way by callers.
      */
     AVStreamInternal *internal;
+
+    /*
+     * Codec parameters associated with this stream. Allocated and freed by
+     * libavformat in avformat_new_stream() and avformat_free_context()
+     * respectively.
+     *
+     * - demuxing: filled by libavformat on stream creation or in
+     *             avformat_find_stream_info()
+     * - muxing: filled by the caller before avformat_write_header()
+     */
+    AVCodecParameters *codecpar;
 } AVStream;
 
 AVRational av_stream_get_r_frame_rate(const AVStream *s);
@@ -1300,6 +1305,12 @@ typedef struct AVFormatInternal AVFormatInternal;
  * version bump.
  * sizeof(AVFormatContext) must not be used outside libav*, use
  * avformat_alloc_context() to create an AVFormatContext.
+ *
+ * Fields can be accessed through AVOptions (av_opt*),
+ * the name string used matches the associated command line parameter name and
+ * can be found in libavformat/options_table.h.
+ * The AVOption/command line parameter names differ in some cases from the C
+ * structure field names for historic reasons or brevity.
  */
 typedef struct AVFormatContext {
     /**
@@ -1842,9 +1853,9 @@ typedef struct AVFormatContext {
     /*
      * A callback for opening new IO streams.
      *
-     * Certain muxers or demuxers (e.g. for various playlist-based formats) need
-     * to open additional files during muxing or demuxing. This callback allows
-     * the caller to provide custom IO in such cases.
+     * Whenever a muxer or a demuxer needs to open an IO stream (typically from
+     * avformat_open_input() for demuxers, but for certain formats can happen at
+     * other times as well), it will call this callback to obtain an IO context.
      *
      * @param s the format context
      * @param pb on success, the newly opened IO context should be returned here
@@ -1866,6 +1877,13 @@ typedef struct AVFormatContext {
      * A callback for closing the streams opened with AVFormatContext.io_open().
      */
     void (*io_close)(struct AVFormatContext *s, AVIOContext *pb);
+
+    /**
+     * ',' separated list of disallowed protocols.
+     * - encoding: unused
+     * - decoding: set by user through AVOptions (NO direct access)
+     */
+    char *protocol_blacklist;
 } AVFormatContext;
 
 int av_format_get_probe_score(const AVFormatContext *s);
@@ -2409,6 +2427,10 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt);
  * increasing dts. Callers doing their own interleaving should call
  * av_write_frame() instead of this function.
  *
+ * Using this function instead of av_write_frame() can give muxers advance
+ * knowledge of future packets, improving e.g. the behaviour of the mp4
+ * muxer for VFR content in fragmenting mode.
+ *
  * @param s media file handle
  * @param pkt The packet containing the data to be written.
  *            <br>
@@ -2443,7 +2465,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt);
 int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);
 
 /**
- * Write a uncoded frame to an output media file.
+ * Write an uncoded frame to an output media file.
  *
  * The frame must be correctly interleaved according to the container
  * specification; if not, then av_interleaved_write_frame() must be used.
@@ -2454,7 +2476,7 @@ int av_write_uncoded_frame(AVFormatContext *s, int stream_index,
                            AVFrame *frame);
 
 /**
- * Write a uncoded frame to an output media file.
+ * Write an uncoded frame to an output media file.
  *
  * If the muxer supports it, this function makes it possible to write an AVFrame
  * structure directly, without encoding it into a packet.
@@ -2844,13 +2866,18 @@ int avformat_queue_attached_pictures(AVFormatContext *s);
  * Apply a list of bitstream filters to a packet.
  *
  * @param codec AVCodecContext, usually from an AVStream
- * @param pkt the packet to apply filters to
+ * @param pkt the packet to apply filters to. If, on success, the returned
+ *        packet has size == 0 and side_data_elems == 0, it indicates that
+ *        the packet should be dropped
  * @param bsfc a NULL-terminated list of filters to apply
  * @return  >=0 on success;
  *          AVERROR code on failure
  */
+#if FF_API_OLD_BSF
+attribute_deprecated
 int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt,
                                AVBitStreamFilterContext *bsfc);
+#endif
 
 /**
  * @}
diff --git a/libavformat/avi.h b/libavformat/avi.h
index 34da76f..af21f2c 100644
--- a/libavformat/avi.h
+++ b/libavformat/avi.h
@@ -32,7 +32,11 @@
 #define AVI_MASTER_INDEX_SIZE   256
 #define AVI_MAX_STREAM_COUNT    100
 
+/* stream header flags */
+#define AVISF_VIDEO_PALCHANGES  0x00010000
+
 /* index flags */
-#define AVIIF_INDEX             0x10
+#define AVIIF_INDEX             0x00000010
+#define AVIIF_NO_TIME           0x00000100
 
 #endif /* AVFORMAT_AVI_H */
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 3859810..38ea86d 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -385,11 +385,11 @@ static void avi_read_nikon(AVFormatContext *s, uint64_t end)
     }
 }
 
-static int avi_extract_stream_metadata(AVStream *st)
+static int avi_extract_stream_metadata(AVFormatContext *s, AVStream *st)
 {
     GetByteContext gb;
-    uint8_t *data = st->codec->extradata;
-    int data_size = st->codec->extradata_size;
+    uint8_t *data = st->codecpar->extradata;
+    int data_size = st->codecpar->extradata_size;
     int tag, offset;
 
     if (!data || data_size < 8) {
@@ -408,13 +408,13 @@ static int avi_extract_stream_metadata(AVStream *st)
         bytestream2_init(&gb, data + offset, data_size - offset);
 
         // decode EXIF tags from IFD, AVI is always little-endian
-        return avpriv_exif_decode_ifd(st->codec, &gb, 1, 0, &st->metadata);
+        return avpriv_exif_decode_ifd(s, &gb, 1, 0, &st->metadata);
         break;
     case MKTAG('C', 'A', 'S', 'I'):
-        avpriv_request_sample(st->codec, "RIFF stream data tag type CASI (%u)", tag);
+        avpriv_request_sample(s, "RIFF stream data tag type CASI (%u)", tag);
         break;
     case MKTAG('Z', 'o', 'r', 'a'):
-        avpriv_request_sample(st->codec, "RIFF stream data tag type Zora (%u)", tag);
+        avpriv_request_sample(s, "RIFF stream data tag type Zora (%u)", tag);
         break;
     default:
         break;
@@ -456,12 +456,12 @@ static int calculate_bitrate(AVFormatContext *s)
         for (j = 0; j < st->nb_index_entries; j++)
             len += st->index_entries[j].size;
 
-        if (st->nb_index_entries < 2 || st->codec->bit_rate > 0)
+        if (st->nb_index_entries < 2 || st->codecpar->bit_rate > 0)
             continue;
         duration = st->index_entries[j-1].timestamp - st->index_entries[0].timestamp;
         bitrate = av_rescale(8*len, st->time_base.den, duration * st->time_base.num);
         if (bitrate <= INT_MAX && bitrate > 0) {
-            st->codec->bit_rate = bitrate;
+            st->codecpar->bit_rate = bitrate;
         }
     }
     return 1;
@@ -603,8 +603,8 @@ static int avi_read_header(AVFormatContext *s)
                     goto fail;
 
                 ast = s->streams[0]->priv_data;
-                av_freep(&s->streams[0]->codec->extradata);
-                av_freep(&s->streams[0]->codec);
+                av_freep(&s->streams[0]->codecpar->extradata);
+                av_freep(&s->streams[0]->codecpar);
                 if (s->streams[0]->info)
                     av_freep(&s->streams[0]->info->duration_error);
                 av_freep(&s->streams[0]->info);
@@ -670,7 +670,7 @@ static int avi_read_header(AVFormatContext *s)
                 av_log(s, AV_LOG_ERROR, "crazy start time, iam scared, giving up\n");
                 ast->cum_len = 0;
             }
-            ast->sample_size = avio_rl32(pb); /* sample ssize */
+            ast->sample_size = avio_rl32(pb);
             ast->cum_len    *= FFMAX(1, ast->sample_size);
             av_log(s, AV_LOG_TRACE, "%"PRIu32" %"PRIu32" %d\n",
                     ast->rate, ast->scale, ast->sample_size);
@@ -733,17 +733,17 @@ static int avi_read_header(AVFormatContext *s)
                 if (cur_pos < list_end)
                     size = FFMIN(size, list_end - cur_pos);
                 st = s->streams[stream_index];
-                if (st->codec->codec_type != AVMEDIA_TYPE_UNKNOWN) {
+                if (st->codecpar->codec_type != AVMEDIA_TYPE_UNKNOWN) {
                     avio_skip(pb, size);
                     break;
                 }
                 switch (codec_type) {
                 case AVMEDIA_TYPE_VIDEO:
                     if (amv_file_format) {
-                        st->codec->width      = avih_width;
-                        st->codec->height     = avih_height;
-                        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-                        st->codec->codec_id   = AV_CODEC_ID_AMV;
+                        st->codecpar->width      = avih_width;
+                        st->codecpar->height     = avih_height;
+                        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+                        st->codecpar->codec_id   = AV_CODEC_ID_AMV;
                         avio_skip(pb, size);
                         break;
                     }
@@ -751,40 +751,40 @@ static int avi_read_header(AVFormatContext *s)
 
                     if (tag1 == MKTAG('D', 'X', 'S', 'B') ||
                         tag1 == MKTAG('D', 'X', 'S', 'A')) {
-                        st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-                        st->codec->codec_tag  = tag1;
-                        st->codec->codec_id   = AV_CODEC_ID_XSUB;
+                        st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+                        st->codecpar->codec_tag  = tag1;
+                        st->codecpar->codec_id   = AV_CODEC_ID_XSUB;
                         break;
                     }
 
                     if (size > 10 * 4 && size < (1 << 30) && size < avi->fsize) {
                         if (esize == size-1 && (esize&1)) {
-                            st->codec->extradata_size = esize - 10 * 4;
+                            st->codecpar->extradata_size = esize - 10 * 4;
                         } else
-                            st->codec->extradata_size =  size - 10 * 4;
-                        if (ff_get_extradata(st->codec, pb, st->codec->extradata_size) < 0)
+                            st->codecpar->extradata_size =  size - 10 * 4;
+                        if (ff_get_extradata(s, st->codecpar, pb, st->codecpar->extradata_size) < 0)
                             return AVERROR(ENOMEM);
                     }
 
                     // FIXME: check if the encoder really did this correctly
-                    if (st->codec->extradata_size & 1)
+                    if (st->codecpar->extradata_size & 1)
                         avio_r8(pb);
 
                     /* Extract palette from extradata if bpp <= 8.
                      * This code assumes that extradata contains only palette.
                      * This is true for all paletted codecs implemented in
                      * FFmpeg. */
-                    if (st->codec->extradata_size &&
-                        (st->codec->bits_per_coded_sample <= 8)) {
-                        int pal_size = (1 << st->codec->bits_per_coded_sample) << 2;
+                    if (st->codecpar->extradata_size &&
+                        (st->codecpar->bits_per_coded_sample <= 8)) {
+                        int pal_size = (1 << st->codecpar->bits_per_coded_sample) << 2;
                         const uint8_t *pal_src;
 
-                        pal_size = FFMIN(pal_size, st->codec->extradata_size);
-                        pal_src  = st->codec->extradata +
-                                   st->codec->extradata_size - pal_size;
+                        pal_size = FFMIN(pal_size, st->codecpar->extradata_size);
+                        pal_src  = st->codecpar->extradata +
+                                   st->codecpar->extradata_size - pal_size;
                         /* Exclude the "BottomUp" field from the palette */
-                        if (pal_src - st->codec->extradata >= 9 &&
-                            !memcmp(st->codec->extradata + st->codec->extradata_size - 9, "BottomUp", 9))
+                        if (pal_src - st->codecpar->extradata >= 9 &&
+                            !memcmp(st->codecpar->extradata + st->codecpar->extradata_size - 9, "BottomUp", 9))
                             pal_src -= 9;
                         for (i = 0; i < pal_size / 4; i++)
                             ast->pal[i] = 0xFFU<<24 | AV_RL32(pal_src+4*i);
@@ -793,17 +793,17 @@ static int avi_read_header(AVFormatContext *s)
 
                     print_tag("video", tag1, 0);
 
-                    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-                    st->codec->codec_tag  = tag1;
-                    st->codec->codec_id   = ff_codec_get_id(ff_codec_bmp_tags,
+                    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+                    st->codecpar->codec_tag  = tag1;
+                    st->codecpar->codec_id   = ff_codec_get_id(ff_codec_bmp_tags,
                                                             tag1);
                     /* If codec is not found yet, try with the mov tags. */
-                    if (!st->codec->codec_id) {
+                    if (!st->codecpar->codec_id) {
                         char tag_buf[32];
                         av_get_codec_tag_string(tag_buf, sizeof(tag_buf), tag1);
-                        st->codec->codec_id =
+                        st->codecpar->codec_id =
                             ff_codec_get_id(ff_codec_movvideo_tags, tag1);
-                        if (st->codec->codec_id)
+                        if (st->codecpar->codec_id)
                            av_log(s, AV_LOG_WARNING,
                                   "mov tag found in avi (fourcc %s)\n",
                                   tag_buf);
@@ -812,44 +812,44 @@ static int avi_read_header(AVFormatContext *s)
                      * for generating correct pts. */
                     st->need_parsing = AVSTREAM_PARSE_HEADERS;
 
-                    if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
+                    if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4 &&
                         ast->handler == MKTAG('X', 'V', 'I', 'D'))
-                        st->codec->codec_tag = MKTAG('X', 'V', 'I', 'D');
+                        st->codecpar->codec_tag = MKTAG('X', 'V', 'I', 'D');
 
-                    if (st->codec->codec_tag == MKTAG('V', 'S', 'S', 'H'))
+                    if (st->codecpar->codec_tag == MKTAG('V', 'S', 'S', 'H'))
                         st->need_parsing = AVSTREAM_PARSE_FULL;
-                    if (st->codec->codec_id == AV_CODEC_ID_RV40)
+                    if (st->codecpar->codec_id == AV_CODEC_ID_RV40)
                         st->need_parsing = AVSTREAM_PARSE_NONE;
 
-                    if (st->codec->codec_tag == 0 && st->codec->height > 0 &&
-                        st->codec->extradata_size < 1U << 30) {
-                        st->codec->extradata_size += 9;
-                        if ((ret = av_reallocp(&st->codec->extradata,
-                                               st->codec->extradata_size +
+                    if (st->codecpar->codec_tag == 0 && st->codecpar->height > 0 &&
+                        st->codecpar->extradata_size < 1U << 30) {
+                        st->codecpar->extradata_size += 9;
+                        if ((ret = av_reallocp(&st->codecpar->extradata,
+                                               st->codecpar->extradata_size +
                                                AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
-                            st->codec->extradata_size = 0;
+                            st->codecpar->extradata_size = 0;
                             return ret;
                         } else
-                            memcpy(st->codec->extradata + st->codec->extradata_size - 9,
+                            memcpy(st->codecpar->extradata + st->codecpar->extradata_size - 9,
                                    "BottomUp", 9);
                     }
-                    st->codec->height = FFABS(st->codec->height);
+                    st->codecpar->height = FFABS(st->codecpar->height);
 
 //                    avio_skip(pb, size - 5 * 4);
                     break;
                 case AVMEDIA_TYPE_AUDIO:
-                    ret = ff_get_wav_header(s, pb, st->codec, size, 0);
+                    ret = ff_get_wav_header(s, pb, st->codecpar, size, 0);
                     if (ret < 0)
                         return ret;
-                    ast->dshow_block_align = st->codec->block_align;
-                    if (ast->sample_size && st->codec->block_align &&
-                        ast->sample_size != st->codec->block_align) {
+                    ast->dshow_block_align = st->codecpar->block_align;
+                    if (ast->sample_size && st->codecpar->block_align &&
+                        ast->sample_size != st->codecpar->block_align) {
                         av_log(s,
                                AV_LOG_WARNING,
                                "sample size (%d) != block align (%d)\n",
                                ast->sample_size,
-                               st->codec->block_align);
-                        ast->sample_size = st->codec->block_align;
+                               st->codecpar->block_align);
+                        ast->sample_size = st->codecpar->block_align;
                     }
                     /* 2-aligned
                      * (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */
@@ -861,45 +861,45 @@ static int avi_read_header(AVFormatContext *s)
                     /* ADTS header is in extradata, AAC without header must be
                      * stored as exact frames. Parser not needed and it will
                      * fail. */
-                    if (st->codec->codec_id == AV_CODEC_ID_AAC &&
-                        st->codec->extradata_size)
+                    if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
+                        st->codecpar->extradata_size)
                         st->need_parsing = AVSTREAM_PARSE_NONE;
                     // The flac parser does not work with AVSTREAM_PARSE_TIMESTAMPS
-                    if (st->codec->codec_id == AV_CODEC_ID_FLAC)
+                    if (st->codecpar->codec_id == AV_CODEC_ID_FLAC)
                         st->need_parsing = AVSTREAM_PARSE_NONE;
                     /* AVI files with Xan DPCM audio (wrongly) declare PCM
                      * audio in the header but have Axan as stream_code_tag. */
                     if (ast->handler == AV_RL32("Axan")) {
-                        st->codec->codec_id  = AV_CODEC_ID_XAN_DPCM;
-                        st->codec->codec_tag = 0;
+                        st->codecpar->codec_id  = AV_CODEC_ID_XAN_DPCM;
+                        st->codecpar->codec_tag = 0;
                         ast->dshow_block_align = 0;
                     }
                     if (amv_file_format) {
-                        st->codec->codec_id    = AV_CODEC_ID_ADPCM_IMA_AMV;
+                        st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_IMA_AMV;
                         ast->dshow_block_align = 0;
                     }
-                    if ((st->codec->codec_id == AV_CODEC_ID_AAC  ||
-                         st->codec->codec_id == AV_CODEC_ID_FLAC ||
-                         st->codec->codec_id == AV_CODEC_ID_MP2 ) && ast->dshow_block_align <= 4 && ast->dshow_block_align) {
+                    if ((st->codecpar->codec_id == AV_CODEC_ID_AAC  ||
+                         st->codecpar->codec_id == AV_CODEC_ID_FLAC ||
+                         st->codecpar->codec_id == AV_CODEC_ID_MP2 ) && ast->dshow_block_align <= 4 && ast->dshow_block_align) {
                         av_log(s, AV_LOG_DEBUG, "overriding invalid dshow_block_align of %d\n", ast->dshow_block_align);
                         ast->dshow_block_align = 0;
                     }
-                    if (st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 1024 && ast->sample_size == 1024 ||
-                       st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 4096 && ast->sample_size == 4096 ||
-                       st->codec->codec_id == AV_CODEC_ID_MP3 && ast->dshow_block_align == 1152 && ast->sample_size == 1152) {
+                    if (st->codecpar->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 1024 && ast->sample_size == 1024 ||
+                       st->codecpar->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 4096 && ast->sample_size == 4096 ||
+                       st->codecpar->codec_id == AV_CODEC_ID_MP3 && ast->dshow_block_align == 1152 && ast->sample_size == 1152) {
                         av_log(s, AV_LOG_DEBUG, "overriding sample_size\n");
                         ast->sample_size = 0;
                     }
                     break;
                 case AVMEDIA_TYPE_SUBTITLE:
-                    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
+                    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
                     st->request_probe= 1;
                     avio_skip(pb, size);
                     break;
                 default:
-                    st->codec->codec_type = AVMEDIA_TYPE_DATA;
-                    st->codec->codec_id   = AV_CODEC_ID_NONE;
-                    st->codec->codec_tag  = 0;
+                    st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+                    st->codecpar->codec_id   = AV_CODEC_ID_NONE;
+                    st->codecpar->codec_tag  = 0;
                     avio_skip(pb, size);
                     break;
                 }
@@ -907,8 +907,8 @@ static int avi_read_header(AVFormatContext *s)
             break;
         case MKTAG('s', 't', 'r', 'd'):
             if (stream_index >= (unsigned)s->nb_streams
-                || s->streams[stream_index]->codec->extradata_size
-                || s->streams[stream_index]->codec->codec_tag == MKTAG('H','2','6','4')) {
+                || s->streams[stream_index]->codecpar->extradata_size
+                || s->streams[stream_index]->codecpar->codec_tag == MKTAG('H','2','6','4')) {
                 avio_skip(pb, size);
             } else {
                 uint64_t cur_pos = avio_tell(pb);
@@ -917,14 +917,14 @@ static int avi_read_header(AVFormatContext *s)
                 st = s->streams[stream_index];
 
                 if (size<(1<<30)) {
-                    if (ff_get_extradata(st->codec, pb, size) < 0)
+                    if (ff_get_extradata(s, st->codecpar, pb, size) < 0)
                         return AVERROR(ENOMEM);
                 }
 
-                if (st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly
+                if (st->codecpar->extradata_size & 1) //FIXME check if the encoder really did this correctly
                     avio_r8(pb);
 
-                ret = avi_extract_stream_metadata(st);
+                ret = avi_extract_stream_metadata(s, st);
                 if (ret < 0) {
                     av_log(s, AV_LOG_WARNING, "could not decoding EXIF data in stream header.\n");
                 }
@@ -1014,8 +1014,8 @@ fail:
     if (dict_entry && !strcmp(dict_entry->value, "PotEncoder"))
         for (i = 0; i < s->nb_streams; i++) {
             AVStream *st = s->streams[i];
-            if (   st->codec->codec_id == AV_CODEC_ID_MPEG1VIDEO
-                || st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO)
+            if (   st->codecpar->codec_id == AV_CODEC_ID_MPEG1VIDEO
+                || st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO)
                 st->need_parsing = AVSTREAM_PARSE_FULL;
         }
 
@@ -1089,13 +1089,12 @@ static int read_gab2_sub(AVFormatContext *s, AVStream *st, AVPacket *pkt)
 
         ast->sub_ctx->pb = pb;
 
-        if (ff_copy_whitelists(ast->sub_ctx, s) < 0)
+        if (ff_copy_whiteblacklists(ast->sub_ctx, s) < 0)
             goto error;
 
         if (!avformat_open_input(&ast->sub_ctx, "", sub_demuxer, NULL)) {
             ff_read_packet(ast->sub_ctx, &ast->sub_pkt);
-            *st->codec = *ast->sub_ctx->streams[0]->codec;
-            ast->sub_ctx->streams[0]->codec->extradata = NULL;
+            avcodec_parameters_copy(st->codecpar, ast->sub_ctx->streams[0]->codecpar);
             time_base = ast->sub_ctx->streams[0]->time_base;
             avpriv_set_pts_info(st, 64, time_base.num, time_base.den);
         }
@@ -1232,8 +1231,8 @@ start_sync:
                 // workaround for broken small-file-bug402.avi
                 if (   d[2] == 'w' && d[3] == 'b'
                    && n == 0
-                   && st ->codec->codec_type == AVMEDIA_TYPE_VIDEO
-                   && st1->codec->codec_type == AVMEDIA_TYPE_AUDIO
+                   && st ->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
+                   && st1->codecpar->codec_type == AVMEDIA_TYPE_AUDIO
                    && ast->prefix == 'd'*256+'c'
                    && (d[2]*256+d[3] == ast1->prefix || !ast1->prefix_count)
                   ) {
@@ -1443,8 +1442,8 @@ resync:
             pkt->flags |= AV_PKT_FLAG_KEY;
             if (size < 0)
                 av_packet_unref(pkt);
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE &&
-                   !st->codec->codec_tag && read_gab2_sub(s, st, pkt)) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
+                   !st->codecpar->codec_tag && read_gab2_sub(s, st, pkt)) {
             ast->frame_offset++;
             avi->stream_index = -1;
             ast->remaining    = 0;
@@ -1468,7 +1467,7 @@ resync:
                     size);
             pkt->stream_index = avi->stream_index;
 
-            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->index_entries) {
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->index_entries) {
                 AVIndexEntry *e;
                 int index;
 
@@ -1479,7 +1478,7 @@ resync:
                     if (index == st->nb_index_entries-1) {
                         int key=1;
                         uint32_t state=-1;
-                        if (st->codec->codec_id == AV_CODEC_ID_MPEG4) {
+                        if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
                             const uint8_t *ptr = pkt->data, *end = ptr + FFMIN(size, 256);
                             while (ptr < end) {
                                 ptr = avpriv_find_start_code(ptr, end, &state);
@@ -1557,7 +1556,7 @@ static int avi_read_idx1(AVFormatContext *s, int size)
     avi->stream_index = -1;
     avio_seek(pb, idx1_pos, SEEK_SET);
 
-    if (s->nb_streams == 1 && s->streams[0]->codec->codec_tag == AV_RL32("MMES")) {
+    if (s->nb_streams == 1 && s->streams[0]->codecpar->codec_tag == AV_RL32("MMES")) {
         first_packet_pos = 0;
         data_offset = avi->movi_list;
     }
@@ -1581,6 +1580,11 @@ static int avi_read_idx1(AVFormatContext *s, int size)
         st  = s->streams[index];
         ast = st->priv_data;
 
+        /* Skip 'xxpc' palette change entries in the index until a logic
+         * to process these is properly implemented. */
+        if ((tag >> 16 & 0xff) == 'p' && (tag >> 24 & 0xff) == 'c')
+            continue;
+
         if (first_packet && first_packet_pos) {
             if (avi->movi_list + 4 != pos || pos + 500 > first_packet_pos)
                 data_offset  = first_packet_pos - pos;
@@ -1656,7 +1660,7 @@ static int check_stream_max_drift(AVFormatContext *s)
                 max_dts = FFMAX(max_dts, dts);
                 max_buffer = FFMAX(max_buffer,
                                    av_rescale(dts - min_dts,
-                                              st->codec->bit_rate,
+                                              st->codecpar->bit_rate,
                                               AV_TIME_BASE));
             }
         }
@@ -1695,6 +1699,8 @@ static int guess_ni_flag(AVFormatContext *s)
             size = avio_rl32(s->pb);
             if (get_stream_idx(tag) == i && pos + size > st->index_entries[1].pos)
                 last_start = INT64_MAX;
+            if (get_stream_idx(tag) == i && size == st->index_entries[0].size + 8)
+                last_start = INT64_MAX;
         }
 
         if (st->index_entries[0].pos > last_start)
@@ -1842,7 +1848,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
         if (st2->nb_index_entries <= 0)
             continue;
 
-//        av_assert1(st2->codec->block_align);
+//        av_assert1(st2->codecpar->block_align);
         av_assert0(fabs(av_q2d(st2->time_base) - ast2->scale / (double)ast2->rate) < av_q2d(st2->time_base) * 0.00000001);
         index = av_index_search_timestamp(st2,
                                           av_rescale_q(timestamp,
@@ -1851,7 +1857,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
                                           FFMAX(ast2->sample_size, 1),
                                           flags |
                                           AVSEEK_FLAG_BACKWARD |
-                                          (st2->codec->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
+                                          (st2->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
         if (index < 0)
             index = 0;
         ast2->seek_pos = st2->index_entries[index].pos;
@@ -1867,7 +1873,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
         index = av_index_search_timestamp(
                 st2,
                 av_rescale_q(timestamp, st->time_base, st2->time_base) * FFMAX(ast2->sample_size, 1),
-                flags | AVSEEK_FLAG_BACKWARD | (st2->codec->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
+                flags | AVSEEK_FLAG_BACKWARD | (st2->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
         if (index < 0)
             index = 0;
         while (!avi->non_interleaved && index>0 && st2->index_entries[index-1].pos >= pos_min)
diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index 649961d..9504a02 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -44,7 +44,10 @@
  */
 
 typedef struct AVIIentry {
-    unsigned int flags, pos, len;
+    char tag[4];
+    unsigned int flags;
+    unsigned int pos;
+    unsigned int len;
 } AVIIentry;
 
 #define AVI_INDEX_CLUSTER_SIZE 16384
@@ -77,9 +80,15 @@ typedef struct AVIStream {
     int64_t last_dts;
 
     AVIIndex indexes;
+
+    int64_t strh_flags_offset;
+
+    uint32_t palette[AVPALETTE_COUNT];
+    uint32_t old_palette[AVPALETTE_COUNT];
+    int64_t pal_offset;
 } AVIStream;
 
-static int avi_write_packet(AVFormatContext *s, AVPacket *pkt);
+static int avi_write_packet_internal(AVFormatContext *s, AVPacket *pkt);
 
 static inline AVIIentry *avi_get_ientry(const AVIIndex *idx, int ent_id)
 {
@@ -88,6 +97,43 @@ static inline AVIIentry *avi_get_ientry(const AVIIndex *idx, int ent_id)
     return &idx->cluster[cl][id];
 }
 
+static int avi_add_ientry(AVFormatContext *s, int stream_index, char *tag,
+                          unsigned int flags, unsigned int size)
+{
+    AVIContext *avi  = s->priv_data;
+    AVIOContext *pb  = s->pb;
+    AVIStream *avist = s->streams[stream_index]->priv_data;
+    AVIIndex *idx    = &avist->indexes;
+    int cl           = idx->entry / AVI_INDEX_CLUSTER_SIZE;
+    int id           = idx->entry % AVI_INDEX_CLUSTER_SIZE;
+
+    if (idx->ents_allocated <= idx->entry) {
+        idx->cluster = av_realloc_f(idx->cluster, sizeof(void*), cl+1);
+        if (!idx->cluster) {
+            idx->ents_allocated = 0;
+            idx->entry          = 0;
+            return AVERROR(ENOMEM);
+        }
+        idx->cluster[cl] =
+            av_malloc(AVI_INDEX_CLUSTER_SIZE * sizeof(AVIIentry));
+        if (!idx->cluster[cl])
+            return AVERROR(ENOMEM);
+        idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
+    }
+
+    if (tag)
+        memcpy(idx->cluster[cl][id].tag, tag, 4);
+    else
+        memset(idx->cluster[cl][id].tag, 0, 4);
+    idx->cluster[cl][id].flags = flags;
+    idx->cluster[cl][id].pos   = avio_tell(pb) - avi->movi_list;
+    idx->cluster[cl][id].len   = size;
+    avist->max_size = FFMAX(avist->max_size, size);
+    idx->entry++;
+
+    return 0;
+}
+
 static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb,
                                   const char *riff_tag, const char *list_tag)
 {
@@ -134,21 +180,21 @@ static int avi_write_counters(AVFormatContext *s, int riff_id)
     AVIContext *avi = s->priv_data;
     int n, au_byterate, au_ssize, au_scale, nb_frames = 0;
     int64_t file_size;
-    AVCodecContext *stream;
+    AVCodecParameters *par;
 
     file_size = avio_tell(pb);
     for (n = 0; n < s->nb_streams; n++) {
         AVIStream *avist = s->streams[n]->priv_data;
 
         av_assert0(avist->frames_hdr_strm);
-        stream = s->streams[n]->codec;
+        par = s->streams[n]->codecpar;
         avio_seek(pb, avist->frames_hdr_strm, SEEK_SET);
         ff_parse_specific_params(s->streams[n], &au_byterate, &au_ssize, &au_scale);
         if (au_ssize == 0)
             avio_wl32(pb, avist->packet_count);
         else
             avio_wl32(pb, avist->audio_strm_length / au_ssize);
-        if (stream->codec_type == AVMEDIA_TYPE_VIDEO)
+        if (par->codec_type == AVMEDIA_TYPE_VIDEO)
             nb_frames = FFMAX(nb_frames, avist->packet_count);
     }
     if (riff_id == 1) {
@@ -165,7 +211,7 @@ static void write_odml_master(AVFormatContext *s, int stream_index)
 {
     AVIOContext *pb = s->pb;
     AVStream *st = s->streams[stream_index];
-    AVCodecContext *enc = st->codec;
+    AVCodecParameters *par = st->codecpar;
     AVIStream *avist = st->priv_data;
     unsigned char tag[5];
     int j;
@@ -179,7 +225,7 @@ static void write_odml_master(AVFormatContext *s, int stream_index)
     avio_w8(pb, 0);     /* bIndexSubType (0 == frame index) */
     avio_w8(pb, 0);     /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */
     avio_wl32(pb, 0);   /* nEntriesInUse (will fill out later on) */
-    ffio_wfourcc(pb, avi_stream2fourcc(tag, stream_index, enc->codec_type));
+    ffio_wfourcc(pb, avi_stream2fourcc(tag, stream_index, par->codec_type));
                         /* dwChunkId */
     avio_wl64(pb, 0);   /* dwReserved[3] */
     avio_wl32(pb, 0);   /* Must be 0.    */
@@ -193,7 +239,7 @@ static int avi_write_header(AVFormatContext *s)
     AVIContext *avi = s->priv_data;
     AVIOContext *pb = s->pb;
     int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale;
-    AVCodecContext *video_enc;
+    AVCodecParameters *video_par;
     AVStream *video_st = NULL;
     int64_t list1, list2, strh, strf;
     AVDictionaryEntry *t = NULL;
@@ -220,12 +266,12 @@ static int avi_write_header(AVFormatContext *s)
     avio_wl32(pb, 14 * 4);
     bitrate = 0;
 
-    video_enc = NULL;
+    video_par = NULL;
     for (n = 0; n < s->nb_streams; n++) {
-        AVCodecContext *codec = s->streams[n]->codec;
-        bitrate += codec->bit_rate;
-        if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-            video_enc = codec;
+        AVCodecParameters *par = s->streams[n]->codecpar;
+        bitrate += par->bit_rate;
+        if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
+            video_par = par;
             video_st = s->streams[n];
         }
     }
@@ -249,9 +295,9 @@ static int avi_write_header(AVFormatContext *s)
     avio_wl32(pb, 0); /* initial frame */
     avio_wl32(pb, s->nb_streams); /* nb streams */
     avio_wl32(pb, 1024 * 1024); /* suggested buffer size */
-    if (video_enc) {
-        avio_wl32(pb, video_enc->width);
-        avio_wl32(pb, video_enc->height);
+    if (video_par) {
+        avio_wl32(pb, video_par->width);
+        avio_wl32(pb, video_par->height);
     } else {
         avio_wl32(pb, 0);
         avio_wl32(pb, 0);
@@ -264,18 +310,18 @@ static int avi_write_header(AVFormatContext *s)
     /* stream list */
     for (i = 0; i < n; i++) {
         AVStream *st = s->streams[i];
-        AVCodecContext *enc = st->codec;
+        AVCodecParameters *par = st->codecpar;
         AVIStream *avist = st->priv_data;
         list2 = ff_start_tag(pb, "LIST");
         ffio_wfourcc(pb, "strl");
 
         /* stream generic header */
         strh = ff_start_tag(pb, "strh");
-        switch (enc->codec_type) {
+        switch (par->codec_type) {
         case AVMEDIA_TYPE_SUBTITLE:
             // XSUB subtitles behave like video tracks, other subtitles
             // are not (yet) supported.
-            if (enc->codec_id != AV_CODEC_ID_XSUB) {
+            if (par->codec_id != AV_CODEC_ID_XSUB) {
                 av_log(s, AV_LOG_ERROR,
                        "Subtitle streams other than DivX XSUB are not supported by the AVI muxer.\n");
                 return AVERROR_PATCHWELCOME;
@@ -293,11 +339,12 @@ static int avi_write_header(AVFormatContext *s)
             ffio_wfourcc(pb, "dats");
             break;
         }
-        if (enc->codec_type == AVMEDIA_TYPE_VIDEO ||
-            enc->codec_id == AV_CODEC_ID_XSUB)
-            avio_wl32(pb, enc->codec_tag);
+        if (par->codec_type == AVMEDIA_TYPE_VIDEO ||
+            par->codec_id == AV_CODEC_ID_XSUB)
+            avio_wl32(pb, par->codec_tag);
         else
             avio_wl32(pb, 1);
+        avist->strh_flags_offset = avio_tell(pb);
         avio_wl32(pb, 0); /* flags */
         avio_wl16(pb, 0); /* priority */
         avio_wl16(pb, 0); /* language */
@@ -305,14 +352,14 @@ static int avi_write_header(AVFormatContext *s)
 
         ff_parse_specific_params(st, &au_byterate, &au_ssize, &au_scale);
 
-        if (   enc->codec_type == AVMEDIA_TYPE_VIDEO
-            && enc->codec_id != AV_CODEC_ID_XSUB
+        if (   par->codec_type == AVMEDIA_TYPE_VIDEO
+            && par->codec_id != AV_CODEC_ID_XSUB
             && au_byterate > 1000LL*au_scale) {
             au_byterate = 600;
             au_scale    = 1;
         }
         avpriv_set_pts_info(st, 64, au_scale, au_byterate);
-        if (enc->codec_id == AV_CODEC_ID_XSUB)
+        if (par->codec_id == AV_CODEC_ID_XSUB)
             au_scale = au_byterate = 0;
 
         avio_wl32(pb, au_scale); /* scale */
@@ -328,56 +375,57 @@ static int avi_write_header(AVFormatContext *s)
             avio_wl32(pb, 0);  /* length, XXX: filled later */
 
         /* suggested buffer size, is set to largest chunk size in avi_write_trailer */
-        if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
+        if (par->codec_type == AVMEDIA_TYPE_VIDEO)
             avio_wl32(pb, 1024 * 1024);
-        else if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
+        else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
             avio_wl32(pb, 12 * 1024);
         else
             avio_wl32(pb, 0);
         avio_wl32(pb, -1); /* quality */
         avio_wl32(pb, au_ssize); /* sample size */
         avio_wl32(pb, 0);
-        avio_wl16(pb, enc->width);
-        avio_wl16(pb, enc->height);
+        avio_wl16(pb, par->width);
+        avio_wl16(pb, par->height);
         ff_end_tag(pb, strh);
 
-        if (enc->codec_type != AVMEDIA_TYPE_DATA) {
+        if (par->codec_type != AVMEDIA_TYPE_DATA) {
             int ret, flags;
             enum AVPixelFormat pix_fmt;
 
             strf = ff_start_tag(pb, "strf");
-            switch (enc->codec_type) {
+            switch (par->codec_type) {
             case AVMEDIA_TYPE_SUBTITLE:
                 /* XSUB subtitles behave like video tracks, other subtitles
                  * are not (yet) supported. */
-                if (enc->codec_id != AV_CODEC_ID_XSUB)
+                if (par->codec_id != AV_CODEC_ID_XSUB)
                     break;
             case AVMEDIA_TYPE_VIDEO:
                 /* WMP expects RGB 5:5:5 rawvideo in avi to have bpp set to 16. */
-                if (  !enc->codec_tag
-                    && enc->codec_id == AV_CODEC_ID_RAWVIDEO
-                    && enc->pix_fmt == AV_PIX_FMT_RGB555LE
-                    && enc->bits_per_coded_sample == 15)
-                    enc->bits_per_coded_sample = 16;
-                ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 0, 0);
+                if (  !par->codec_tag
+                    && par->codec_id == AV_CODEC_ID_RAWVIDEO
+                    && par->format == AV_PIX_FMT_RGB555LE
+                    && par->bits_per_coded_sample == 15)
+                    par->bits_per_coded_sample = 16;
+                avist->pal_offset = avio_tell(pb) + 40;
+                ff_put_bmp_header(pb, par, ff_codec_bmp_tags, 0, 0);
                 pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi,
-                                              enc->bits_per_coded_sample);
-                if (   !enc->codec_tag
-                    && enc->codec_id == AV_CODEC_ID_RAWVIDEO
-                    && enc->pix_fmt != pix_fmt
-                    && enc->pix_fmt != AV_PIX_FMT_NONE)
+                                              par->bits_per_coded_sample);
+                if (   !par->codec_tag
+                    && par->codec_id == AV_CODEC_ID_RAWVIDEO
+                    && par->format != pix_fmt
+                    && par->format != AV_PIX_FMT_NONE)
                     av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to avi, output file will be unreadable\n",
-                          av_get_pix_fmt_name(enc->pix_fmt));
+                          av_get_pix_fmt_name(par->format));
                 break;
             case AVMEDIA_TYPE_AUDIO:
                 flags = (avi->write_channel_mask == 0) ? FF_PUT_WAV_HEADER_SKIP_CHANNELMASK : 0;
-                if ((ret = ff_put_wav_header(pb, enc, flags)) < 0)
+                if ((ret = ff_put_wav_header(s, pb, par, flags)) < 0)
                     return ret;
                 break;
             default:
                 av_log(s, AV_LOG_ERROR,
                     "Invalid or not supported codec type '%s' found in the input\n",
-                    (char *)av_x_if_null(av_get_media_type_string(enc->codec_type), "?"));
+                    (char *)av_x_if_null(av_get_media_type_string(par->codec_type), "?"));
                 return AVERROR(EINVAL);
             }
             ff_end_tag(pb, strf);
@@ -385,7 +433,7 @@ static int avi_write_header(AVFormatContext *s)
                 ff_riff_write_info_tag(s->pb, "strn", t->value);
                 t = NULL;
             }
-            if (enc->codec_id == AV_CODEC_ID_XSUB
+            if (par->codec_id == AV_CODEC_ID_XSUB
             && (t = av_dict_get(s->streams[i]->metadata, "language", NULL, 0))) {
                 const char* langstr = av_convert_lang_to(t->value, AV_LANG_ISO639_1);
                 t = NULL;
@@ -403,13 +451,13 @@ static int avi_write_header(AVFormatContext *s)
             write_odml_master(s, i);
         }
 
-        if (enc->codec_type == AVMEDIA_TYPE_VIDEO   &&
+        if (par->codec_type == AVMEDIA_TYPE_VIDEO   &&
             st->sample_aspect_ratio.num > 0 &&
             st->sample_aspect_ratio.den > 0) {
             int vprp       = ff_start_tag(pb, "vprp");
             AVRational dar = av_mul_q(st->sample_aspect_ratio,
-                                      (AVRational) { enc->width,
-                                                     enc->height });
+                                      (AVRational) { par->width,
+                                                     par->height });
             int num, den;
             av_reduce(&num, &den, dar.num, dar.den, 0xFFFF);
 
@@ -417,18 +465,18 @@ static int avi_write_header(AVFormatContext *s)
             avio_wl32(pb, 0); // video standard = unknown
             // TODO: should be avg_frame_rate
             avio_wl32(pb, (2LL*st->time_base.den + st->time_base.num - 1) / (2LL * st->time_base.num));
-            avio_wl32(pb, enc->width);
-            avio_wl32(pb, enc->height);
+            avio_wl32(pb, par->width);
+            avio_wl32(pb, par->height);
             avio_wl16(pb, den);
             avio_wl16(pb, num);
-            avio_wl32(pb, enc->width);
-            avio_wl32(pb, enc->height);
+            avio_wl32(pb, par->width);
+            avio_wl32(pb, par->height);
             avio_wl32(pb, 1); // progressive FIXME
 
-            avio_wl32(pb, enc->height);
-            avio_wl32(pb, enc->width);
-            avio_wl32(pb, enc->height);
-            avio_wl32(pb, enc->width);
+            avio_wl32(pb, par->height);
+            avio_wl32(pb, par->width);
+            avio_wl32(pb, par->height);
+            avio_wl32(pb, par->width);
             avio_wl32(pb, 0);
             avio_wl32(pb, 0);
 
@@ -496,7 +544,7 @@ static void update_odml_entry(AVFormatContext *s, int stream_index, int64_t ix,
     avio_wl64(pb, ix);                    /* qwOffset */
     avio_wl32(pb, size);                  /* dwSize */
     ff_parse_specific_params(s->streams[stream_index], &au_byterate, &au_ssize, &au_scale);
-    if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO && au_ssize > 0) {
+    if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && au_ssize > 0) {
         uint32_t audio_segm_size = (avist->audio_strm_length - avist->indexes.audio_strm_offset);
         if ((audio_segm_size % au_ssize > 0) && !avist->sample_requested) {
             avpriv_request_sample(s, "OpenDML index duration for audio packets with partial frames");
@@ -538,7 +586,7 @@ static int avi_write_ix(AVFormatContext *s)
         AVIStream *avist = s->streams[i]->priv_data;
         int64_t ix;
 
-        avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type);
+        avi_stream2fourcc(tag, i, s->streams[i]->codecpar->codec_type);
         ix_tag[3] = '0' + i;
 
         /* Writing AVI OpenDML leaf index chunk */
@@ -602,9 +650,13 @@ static int avi_write_idx1(AVFormatContext *s)
             }
             if (!empty) {
                 avist = s->streams[stream_id]->priv_data;
-                avi_stream2fourcc(tag, stream_id,
-                                  s->streams[stream_id]->codec->codec_type);
-                ffio_wfourcc(pb, tag);
+                if (*ie->tag)
+                    ffio_wfourcc(pb, ie->tag);
+                else {
+                    avi_stream2fourcc(tag, stream_id,
+                                  s->streams[stream_id]->codecpar->codec_type);
+                    ffio_wfourcc(pb, tag);
+                }
                 avio_wl32(pb, ie->flags);
                 avio_wl32(pb, ie->pos);
                 avio_wl32(pb, ie->len);
@@ -621,11 +673,11 @@ static int avi_write_idx1(AVFormatContext *s)
 static int write_skip_frames(AVFormatContext *s, int stream_index, int64_t dts)
 {
     AVIStream *avist    = s->streams[stream_index]->priv_data;
-    AVCodecContext *enc = s->streams[stream_index]->codec;
+    AVCodecParameters *par = s->streams[stream_index]->codecpar;
 
     ff_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(dts), avist->packet_count, stream_index);
-    while (enc->block_align == 0 && dts != AV_NOPTS_VALUE &&
-           dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) {
+    while (par->block_align == 0 && dts != AV_NOPTS_VALUE &&
+           dts > avist->packet_count && par->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) {
         AVPacket empty_packet;
 
         if (dts - avist->packet_count > 60000) {
@@ -637,7 +689,7 @@ static int write_skip_frames(AVFormatContext *s, int stream_index, int64_t dts)
         empty_packet.size         = 0;
         empty_packet.data         = NULL;
         empty_packet.stream_index = stream_index;
-        avi_write_packet(s, &empty_packet);
+        avi_write_packet_internal(s, &empty_packet);
         ff_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(dts), avist->packet_count);
     }
 
@@ -646,17 +698,11 @@ static int write_skip_frames(AVFormatContext *s, int stream_index, int64_t dts)
 
 static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    unsigned char tag[5];
-    unsigned int flags = 0;
     const int stream_index = pkt->stream_index;
-    int size               = pkt->size;
-    AVIContext *avi     = s->priv_data;
-    AVIOContext *pb     = s->pb;
-    AVIStream *avist    = s->streams[stream_index]->priv_data;
-    AVCodecContext *enc = s->streams[stream_index]->codec;
+    AVCodecParameters *par = s->streams[stream_index]->codecpar;
     int ret;
 
-    if (enc->codec_id == AV_CODEC_ID_H264 && enc->codec_tag == MKTAG('H','2','6','4') && pkt->size) {
+    if (par->codec_id == AV_CODEC_ID_H264 && par->codec_tag == MKTAG('H','2','6','4') && pkt->size) {
         ret = ff_check_h264_startcode(s, s->streams[stream_index], pkt);
         if (ret < 0)
             return ret;
@@ -665,6 +711,97 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
     if ((ret = write_skip_frames(s, stream_index, pkt->dts)) < 0)
         return ret;
 
+    if (!pkt->size)
+        return avi_write_packet_internal(s, pkt); /* Passthrough */
+
+    if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
+        AVIStream *avist = s->streams[stream_index]->priv_data;
+        AVIOContext *pb  = s->pb;
+        AVPacket *opkt   = pkt;
+        int reshuffle_ret;
+        if (par->codec_id == AV_CODEC_ID_RAWVIDEO && par->codec_tag == 0) {
+            int64_t bpc = par->bits_per_coded_sample != 15 ? par->bits_per_coded_sample : 16;
+            int expected_stride = ((par->width * bpc + 31) >> 5)*4;
+            reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, par, expected_stride);
+            if (reshuffle_ret < 0)
+                return reshuffle_ret;
+        } else
+            reshuffle_ret = 0;
+        if (par->format == AV_PIX_FMT_PAL8) {
+            ret = ff_get_packet_palette(s, opkt, reshuffle_ret, avist->palette);
+            if (ret < 0)
+                goto fail;
+            if (ret) {
+                int pal_size = 1 << par->bits_per_coded_sample;
+                int pc_tag, i;
+
+                av_assert0(par->bits_per_coded_sample >= 0 && par->bits_per_coded_sample <= 8);
+
+                if (pb->seekable && avist->pal_offset) {
+                    int64_t cur_offset = avio_tell(pb);
+                    avio_seek(pb, avist->pal_offset, SEEK_SET);
+                    for (i = 0; i < pal_size; i++) {
+                        uint32_t v = avist->palette[i];
+                        avio_wl32(pb, v & 0xffffff);
+                    }
+                    avio_seek(pb, cur_offset, SEEK_SET);
+                    memcpy(avist->old_palette, avist->palette, pal_size * 4);
+                    avist->pal_offset = 0;
+                }
+                if (memcmp(avist->palette, avist->old_palette, pal_size * 4)) {
+                    unsigned char tag[5];
+                    avi_stream2fourcc(tag, stream_index, par->codec_type);
+                    tag[2] = 'p'; tag[3] = 'c';
+                    if (s->pb->seekable) {
+                        if (avist->strh_flags_offset) {
+                            int64_t cur_offset = avio_tell(pb);
+                            avio_seek(pb, avist->strh_flags_offset, SEEK_SET);
+                            avio_wl32(pb, AVISF_VIDEO_PALCHANGES);
+                            avio_seek(pb, cur_offset, SEEK_SET);
+                            avist->strh_flags_offset = 0;
+                        }
+                        ret = avi_add_ientry(s, stream_index, tag, AVIIF_NO_TIME,
+                                       pal_size * 4 + 4);
+                        if (ret < 0)
+                            goto fail;
+                    }
+                    pc_tag = ff_start_tag(pb, tag);
+                    avio_w8(pb, 0);
+                    avio_w8(pb, pal_size & 0xFF);
+                    avio_wl16(pb, 0); // reserved
+                    for (i = 0; i < pal_size; i++) {
+                        uint32_t v = avist->palette[i];
+                        avio_wb32(pb, v<<8);
+                    }
+                    ff_end_tag(pb, pc_tag);
+                    memcpy(avist->old_palette, avist->palette, pal_size * 4);
+                }
+            }
+        }
+        if (reshuffle_ret) {
+            ret = avi_write_packet_internal(s, pkt);
+
+fail:
+            if (reshuffle_ret)
+                av_packet_free(&pkt);
+            return ret;
+        }
+    }
+
+    return avi_write_packet_internal(s, pkt);
+}
+
+static int avi_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
+{
+    unsigned char tag[5];
+    unsigned int flags = 0;
+    const int stream_index = pkt->stream_index;
+    int size               = pkt->size;
+    AVIContext *avi     = s->priv_data;
+    AVIOContext *pb     = s->pb;
+    AVIStream *avist    = s->streams[stream_index]->priv_data;
+    AVCodecParameters *par = s->streams[stream_index]->codecpar;
+
     if (pkt->dts != AV_NOPTS_VALUE)
         avist->last_dts = pkt->dts + pkt->duration;
 
@@ -683,35 +820,17 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
         avi->movi_list = avi_start_new_riff(s, pb, "AVIX", "movi");
     }
 
-    avi_stream2fourcc(tag, stream_index, enc->codec_type);
+    avi_stream2fourcc(tag, stream_index, par->codec_type);
     if (pkt->flags & AV_PKT_FLAG_KEY)
         flags = 0x10;
-    if (enc->codec_type == AVMEDIA_TYPE_AUDIO)
+    if (par->codec_type == AVMEDIA_TYPE_AUDIO)
         avist->audio_strm_length += size;
 
     if (s->pb->seekable) {
-        AVIIndex *idx = &avist->indexes;
-        int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
-        int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
-        if (idx->ents_allocated <= idx->entry) {
-            idx->cluster = av_realloc_f(idx->cluster, sizeof(void*), cl+1);
-            if (!idx->cluster) {
-                idx->ents_allocated = 0;
-                idx->entry          = 0;
-                return AVERROR(ENOMEM);
-            }
-            idx->cluster[cl] =
-                av_malloc(AVI_INDEX_CLUSTER_SIZE * sizeof(AVIIentry));
-            if (!idx->cluster[cl])
-                return AVERROR(ENOMEM);
-            idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE;
-        }
-
-        idx->cluster[cl][id].flags = flags;
-        idx->cluster[cl][id].pos   = avio_tell(pb) - avi->movi_list;
-        idx->cluster[cl][id].len   = size;
-        avist->max_size = FFMAX(avist->max_size, size);
-        idx->entry++;
+        int ret;
+        ret = avi_add_ientry(s, stream_index, NULL, flags, size);
+        if (ret < 0)
+            return ret;
     }
 
     avio_write(pb, tag, 4);
@@ -752,15 +871,15 @@ static int avi_write_trailer(AVFormatContext *s)
             avio_skip(pb, 16);
 
             for (n = nb_frames = 0; n < s->nb_streams; n++) {
-                AVCodecContext *stream = s->streams[n]->codec;
+                AVCodecParameters *par = s->streams[n]->codecpar;
                 AVIStream *avist       = s->streams[n]->priv_data;
 
-                if (stream->codec_type == AVMEDIA_TYPE_VIDEO) {
+                if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
                     if (nb_frames < avist->packet_count)
                         nb_frames = avist->packet_count;
                 } else {
-                    if (stream->codec_id == AV_CODEC_ID_MP2 ||
-                        stream->codec_id == AV_CODEC_ID_MP3)
+                    if (par->codec_id == AV_CODEC_ID_MP2 ||
+                        par->codec_id == AV_CODEC_ID_MP3)
                         nb_frames += avist->packet_count;
                 }
             }
diff --git a/libavformat/avio.c b/libavformat/avio.c
index 362099d..3606eb0 100644
--- a/libavformat/avio.c
+++ b/libavformat/avio.c
@@ -31,13 +31,6 @@
 #endif
 #include "url.h"
 
-static URLProtocol *first_protocol = NULL;
-
-URLProtocol *ffurl_protocol_next(const URLProtocol *prev)
-{
-    return prev ? prev->next : first_protocol;
-}
-
 /** @name Logging context. */
 /*@{*/
 static const char *urlcontext_to_name(void *ptr)
@@ -57,62 +50,27 @@ static void *urlcontext_child_next(void *obj, void *prev)
     return NULL;
 }
 
-static const AVClass *urlcontext_child_class_next(const AVClass *prev)
-{
-    URLProtocol *p = NULL;
-
-    /* find the protocol that corresponds to prev */
-    while (prev && (p = ffurl_protocol_next(p)))
-        if (p->priv_data_class == prev)
-            break;
-
-    /* find next protocol with priv options */
-    while (p = ffurl_protocol_next(p))
-        if (p->priv_data_class)
-            return p->priv_data_class;
-    return NULL;
-}
-
 #define OFFSET(x) offsetof(URLContext,x)
 #define E AV_OPT_FLAG_ENCODING_PARAM
 #define D AV_OPT_FLAG_DECODING_PARAM
 static const AVOption options[] = {
     {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
+    {"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
+    {"rw_timeout", "Timeout for IO operations (in microseconds)", offsetof(URLContext, rw_timeout), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_DECODING_PARAM },
     { NULL }
 };
+
 const AVClass ffurl_context_class = {
     .class_name       = "URLContext",
     .item_name        = urlcontext_to_name,
     .option           = options,
     .version          = LIBAVUTIL_VERSION_INT,
     .child_next       = urlcontext_child_next,
-    .child_class_next = urlcontext_child_class_next,
+    .child_class_next = ff_urlcontext_child_class_next,
 };
 /*@}*/
 
-const char *avio_enum_protocols(void **opaque, int output)
-{
-    URLProtocol *p;
-    *opaque = ffurl_protocol_next(*opaque);
-    if (!(p = *opaque))
-        return NULL;
-    if ((output && p->url_write) || (!output && p->url_read))
-        return p->name;
-    return avio_enum_protocols(opaque, output);
-}
-
-int ffurl_register_protocol(URLProtocol *protocol)
-{
-    URLProtocol **p;
-    p = &first_protocol;
-    while (*p)
-        p = &(*p)->next;
-    *p             = protocol;
-    protocol->next = NULL;
-    return 0;
-}
-
-static int url_alloc_for_protocol(URLContext **puc, struct URLProtocol *up,
+static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up,
                                   const char *filename, int flags,
                                   const AVIOInterruptCB *int_cb)
 {
@@ -217,12 +175,19 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
     // Check that URLContext was initialized correctly and lists are matching if set
     av_assert0(!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
                (uc->protocol_whitelist && !strcmp(uc->protocol_whitelist, e->value)));
+    av_assert0(!(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
+               (uc->protocol_blacklist && !strcmp(uc->protocol_blacklist, e->value)));
 
     if (uc->protocol_whitelist && av_match_list(uc->prot->name, uc->protocol_whitelist, ',') <= 0) {
         av_log(uc, AV_LOG_ERROR, "Protocol not on whitelist \'%s\'!\n", uc->protocol_whitelist);
         return AVERROR(EINVAL);
     }
 
+    if (uc->protocol_blacklist && av_match_list(uc->prot->name, uc->protocol_blacklist, ',') > 0) {
+        av_log(uc, AV_LOG_ERROR, "Protocol blacklisted \'%s\'!\n", uc->protocol_blacklist);
+        return AVERROR(EINVAL);
+    }
+
     if (!uc->protocol_whitelist && uc->prot->default_whitelist) {
         av_log(uc, AV_LOG_DEBUG, "Setting default whitelist '%s'\n", uc->prot->default_whitelist);
         uc->protocol_whitelist = av_strdup(uc->prot->default_whitelist);
@@ -234,6 +199,8 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
 
     if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0)
         return err;
+    if ((err = av_dict_set(options, "protocol_blacklist", uc->protocol_blacklist, 0)) < 0)
+        return err;
 
     err =
         uc->prot->url_open2 ? uc->prot->url_open2(uc,
@@ -243,6 +210,7 @@ int ffurl_connect(URLContext *uc, AVDictionary **options)
         uc->prot->url_open(uc, uc->filename, uc->flags);
 
     av_dict_set(options, "protocol_whitelist", NULL, 0);
+    av_dict_set(options, "protocol_blacklist", NULL, 0);
 
     if (err)
         return err;
@@ -280,11 +248,12 @@ int ffurl_handshake(URLContext *c)
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"                \
     "0123456789+-."
 
-static struct URLProtocol *url_find_protocol(const char *filename)
+static const struct URLProtocol *url_find_protocol(const char *filename)
 {
-    URLProtocol *up = NULL;
+    const URLProtocol **protocols;
     char proto_str[128], proto_nested[128], *ptr;
     size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
+    int i;
 
     if (filename[proto_len] != ':' &&
         (strncmp(filename, "subfile,", 8) || !strchr(filename + proto_len + 1, ':')) ||
@@ -300,26 +269,30 @@ static struct URLProtocol *url_find_protocol(const char *filename)
     if ((ptr = strchr(proto_nested, '+')))
         *ptr = '\0';
 
-    while (up = ffurl_protocol_next(up)) {
-        if (!strcmp(proto_str, up->name))
-            break;
+    protocols = ffurl_get_protocols(NULL, NULL);
+    if (!protocols)
+        return NULL;
+    for (i = 0; protocols[i]; i++) {
+            const URLProtocol *up = protocols[i];
+        if (!strcmp(proto_str, up->name)) {
+            av_freep(&protocols);
+            return up;
+        }
         if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME &&
-            !strcmp(proto_nested, up->name))
-            break;
+            !strcmp(proto_nested, up->name)) {
+            av_freep(&protocols);
+            return up;
+        }
     }
+    av_freep(&protocols);
 
-    return up;
+    return NULL;
 }
 
 int ffurl_alloc(URLContext **puc, const char *filename, int flags,
                 const AVIOInterruptCB *int_cb)
 {
-    URLProtocol *p = NULL;
-
-    if (!first_protocol) {
-        av_log(NULL, AV_LOG_WARNING, "No URL Protocols are registered. "
-                                     "Missing call to av_register_all()?\n");
-    }
+    const URLProtocol *p = NULL;
 
     p = url_find_protocol(filename);
     if (p)
@@ -328,19 +301,26 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
     *puc = NULL;
     if (av_strstart(filename, "https:", NULL))
         av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with "
-                                     "openssl, gnutls,\n"
+                                     "openssl, gnutls "
                                      "or securetransport enabled.\n");
     return AVERROR_PROTOCOL_NOT_FOUND;
 }
 
 int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
-                         const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist)
+                         const AVIOInterruptCB *int_cb, AVDictionary **options,
+                         const char *whitelist, const char* blacklist,
+                         URLContext *parent)
 {
     AVDictionary *tmp_opts = NULL;
     AVDictionaryEntry *e;
     int ret = ffurl_alloc(puc, filename, flags, int_cb);
     if (ret < 0)
         return ret;
+    if (parent)
+        av_opt_copy(*puc, parent);
+    if (options &&
+        (ret = av_opt_set_dict(*puc, options)) < 0)
+        goto fail;
     if (options && (*puc)->prot->priv_data_class &&
         (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
         goto fail;
@@ -351,10 +331,16 @@ int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
     av_assert0(!whitelist ||
                !(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
                !strcmp(whitelist, e->value));
+    av_assert0(!blacklist ||
+               !(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
+               !strcmp(blacklist, e->value));
 
     if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
         goto fail;
 
+    if ((ret = av_dict_set(options, "protocol_blacklist", blacklist, 0)) < 0)
+        goto fail;
+
     if ((ret = av_opt_set_dict(*puc, options)) < 0)
         goto fail;
 
@@ -372,7 +358,7 @@ int ffurl_open(URLContext **puc, const char *filename, int flags,
                const AVIOInterruptCB *int_cb, AVDictionary **options)
 {
     return ffurl_open_whitelist(puc, filename, flags,
-                                int_cb, options, NULL);
+                                int_cb, options, NULL, NULL, NULL);
 }
 
 static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
@@ -409,8 +395,10 @@ static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
             }
         } else if (ret < 1)
             return (ret < 0 && ret != AVERROR_EOF) ? ret : len;
-        if (ret)
+        if (ret) {
             fast_retries = FFMAX(fast_retries, 2);
+            wait_since = 0;
+        }
         len += ret;
     }
     return len;
@@ -484,7 +472,7 @@ int ffurl_close(URLContext *h)
 
 const char *avio_find_protocol_name(const char *url)
 {
-    URLProtocol *p = url_find_protocol(url);
+    const URLProtocol *p = url_find_protocol(url);
 
     return p ? p->name : NULL;
 }
diff --git a/libavformat/avio.h b/libavformat/avio.h
index 7fbce32..b1ce1d1 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -97,6 +97,42 @@ typedef struct AVIODirContext {
 } AVIODirContext;
 
 /**
+ * Different data types that can be returned via the AVIO
+ * write_data_type callback.
+ */
+enum AVIODataMarkerType {
+    /**
+     * Header data; this needs to be present for the stream to be decodeable.
+     */
+    AVIO_DATA_MARKER_HEADER,
+    /**
+     * A point in the output bytestream where a decoder can start decoding
+     * (i.e. a keyframe). A demuxer/decoder given the data flagged with
+     * AVIO_DATA_MARKER_HEADER, followed by any AVIO_DATA_MARKER_SYNC_POINT,
+     * should give decodeable results.
+     */
+    AVIO_DATA_MARKER_SYNC_POINT,
+    /**
+     * A point in the output bytestream where a demuxer can start parsing
+     * (for non self synchronizing bytestream formats). That is, any
+     * non-keyframe packet start point.
+     */
+    AVIO_DATA_MARKER_BOUNDARY_POINT,
+    /**
+     * This is any, unlabelled data. It can either be a muxer not marking
+     * any positions at all, it can be an actual boundary/sync point
+     * that the muxer chooses not to mark, or a later part of a packet/fragment
+     * that is cut into multiple write callbacks due to limited IO buffer size.
+     */
+    AVIO_DATA_MARKER_UNKNOWN,
+    /**
+     * Trailer data, which doesn't contain actual content, but only for
+     * finalizing the output file.
+     */
+    AVIO_DATA_MARKER_TRAILER
+};
+
+/**
  * Bytestream IO Context.
  * New fields can be added to the end with minor version bumps.
  * Removal, reordering and changes to existing fields require a major
@@ -254,9 +290,30 @@ typedef struct AVIOContext {
      * ',' separated list of allowed protocols.
      */
     const char *protocol_whitelist;
-} AVIOContext;
 
-/* unbuffered I/O */
+    /**
+     * ',' separated list of disallowed protocols.
+     */
+    const char *protocol_blacklist;
+
+    /**
+     * A callback that is used instead of write_packet.
+     */
+    int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,
+                           enum AVIODataMarkerType type, int64_t time);
+    /**
+     * If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT,
+     * but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly
+     * small chunks of data returned from the callback).
+     */
+    int ignore_boundary_point;
+
+    /**
+     * Internal, not meant to be used from outside of AVIOContext.
+     */
+    enum AVIODataMarkerType current_type;
+    int64_t last_time;
+} AVIOContext;
 
 /**
  * Return the name of the protocol that will handle the passed URL.
@@ -409,14 +466,26 @@ int avio_put_str16le(AVIOContext *s, const char *str);
 int avio_put_str16be(AVIOContext *s, const char *str);
 
 /**
- * Passing this as the "whence" parameter to a seek function causes it to
+ * Mark the written bytestream as a specific type.
+ *
+ * Zero-length ranges are omitted from the output.
+ *
+ * @param time the stream time the current bytestream pos corresponds to
+ *             (in AV_TIME_BASE units), or AV_NOPTS_VALUE if unknown or not
+ *             applicable
+ * @param type the kind of data written starting at the current pos
+ */
+void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type);
+
+/**
+ * ORing this as the "whence" parameter to a seek function causes it to
  * return the filesize without seeking anywhere. Supporting this is optional.
  * If it is not supported then the seek function will return <0.
  */
 #define AVSEEK_SIZE 0x10000
 
 /**
- * Oring this flag as into the "whence" parameter to a seek function causes it to
+ * Passing this flag as the "whence" parameter to a seek function causes it to
  * seek by any means (like reopening and linear reading) or other normally unreasonable
  * means that can be extremely slow.
  * This may be ignored by the seek code.
diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h
index f7c8588..3867be6 100644
--- a/libavformat/avio_internal.h
+++ b/libavformat/avio_internal.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -151,7 +150,7 @@ int ffio_open_null_buf(AVIOContext **s);
 
 int ffio_open_whitelist(AVIOContext **s, const char *url, int flags,
                          const AVIOInterruptCB *int_cb, AVDictionary **options,
-                         const char *whitelist);
+                         const char *whitelist, const char *blacklist);
 
 /**
  * Close a null buffer.
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 213ee96..95793c9 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -42,10 +42,15 @@
  */
 #define SHORT_SEEK_THRESHOLD 4096
 
+typedef struct AVIOInternal {
+    URLContext *h;
+} AVIOInternal;
+
 static void *ff_avio_child_next(void *obj, void *prev)
 {
     AVIOContext *s = obj;
-    return prev ? NULL : s->opaque;
+    AVIOInternal *internal = s->opaque;
+    return prev ? NULL : internal->h;
 }
 
 static const AVClass *ff_avio_child_class_next(const AVClass *prev)
@@ -110,6 +115,11 @@ int ffio_init_context(AVIOContext *s,
     s->read_pause = NULL;
     s->read_seek  = NULL;
 
+    s->write_data_type       = NULL;
+    s->ignore_boundary_point = 0;
+    s->current_type          = AVIO_DATA_MARKER_UNKNOWN;
+    s->last_time             = AV_NOPTS_VALUE;
+
     return 0;
 }
 
@@ -132,12 +142,24 @@ AVIOContext *avio_alloc_context(
 
 static void writeout(AVIOContext *s, const uint8_t *data, int len)
 {
-    if (s->write_packet && !s->error) {
-        int ret = s->write_packet(s->opaque, (uint8_t *)data, len);
+    if (!s->error) {
+        int ret = 0;
+        if (s->write_data_type)
+            ret = s->write_data_type(s->opaque, (uint8_t *)data,
+                                     len,
+                                     s->current_type,
+                                     s->last_time);
+        else if (s->write_packet)
+            ret = s->write_packet(s->opaque, (uint8_t *)data, len);
         if (ret < 0) {
             s->error = ret;
         }
     }
+    if (s->current_type == AVIO_DATA_MARKER_SYNC_POINT ||
+        s->current_type == AVIO_DATA_MARKER_BOUNDARY_POINT) {
+        s->current_type = AVIO_DATA_MARKER_UNKNOWN;
+    }
+    s->last_time = AV_NOPTS_VALUE;
     s->writeout_count ++;
     s->pos += len;
 }
@@ -445,6 +467,37 @@ void avio_wb24(AVIOContext *s, unsigned int val)
     avio_w8(s, (uint8_t)val);
 }
 
+void avio_write_marker(AVIOContext *s, int64_t time, enum AVIODataMarkerType type)
+{
+    if (!s->write_data_type)
+        return;
+    // If ignoring boundary points, just treat it as unknown
+    if (type == AVIO_DATA_MARKER_BOUNDARY_POINT && s->ignore_boundary_point)
+        type = AVIO_DATA_MARKER_UNKNOWN;
+    // Avoid unnecessary flushes if we are already in non-header/trailer
+    // data and setting the type to unknown
+    if (type == AVIO_DATA_MARKER_UNKNOWN &&
+        (s->current_type != AVIO_DATA_MARKER_HEADER &&
+         s->current_type != AVIO_DATA_MARKER_TRAILER))
+        return;
+
+    switch (type) {
+    case AVIO_DATA_MARKER_HEADER:
+    case AVIO_DATA_MARKER_TRAILER:
+        // For header/trailer, ignore a new marker of the same type;
+        // consecutive header/trailer markers can be merged.
+        if (type == s->current_type)
+            return;
+        break;
+    }
+
+    // If we've reached here, we have a new, noteworthy marker.
+    // Flush the previous data and mark the start of the new data.
+    avio_flush(s);
+    s->current_type = type;
+    s->last_time = time;
+}
+
 /* Input stream */
 
 static void fill_buffer(AVIOContext *s)
@@ -781,9 +834,44 @@ uint64_t ffio_read_varlen(AVIOContext *bc){
     return val;
 }
 
+static int io_read_packet(void *opaque, uint8_t *buf, int buf_size)
+{
+    AVIOInternal *internal = opaque;
+    return ffurl_read(internal->h, buf, buf_size);
+}
+
+static int io_write_packet(void *opaque, uint8_t *buf, int buf_size)
+{
+    AVIOInternal *internal = opaque;
+    return ffurl_write(internal->h, buf, buf_size);
+}
+
+static int64_t io_seek(void *opaque, int64_t offset, int whence)
+{
+    AVIOInternal *internal = opaque;
+    return ffurl_seek(internal->h, offset, whence);
+}
+
+static int io_read_pause(void *opaque, int pause)
+{
+    AVIOInternal *internal = opaque;
+    if (!internal->h->prot->url_read_pause)
+        return AVERROR(ENOSYS);
+    return internal->h->prot->url_read_pause(internal->h, pause);
+}
+
+static int64_t io_read_seek(void *opaque, int stream_index, int64_t timestamp, int flags)
+{
+    AVIOInternal *internal = opaque;
+    if (!internal->h->prot->url_read_seek)
+        return AVERROR(ENOSYS);
+    return internal->h->prot->url_read_seek(internal->h, stream_index, timestamp, flags);
+}
+
 int ffio_fdopen(AVIOContext **s, URLContext *h)
 {
-    uint8_t *buffer;
+    AVIOInternal *internal = NULL;
+    uint8_t *buffer = NULL;
     int buffer_size, max_packet_size;
 
     max_packet_size = h->max_packet_size;
@@ -796,28 +884,41 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
     if (!buffer)
         return AVERROR(ENOMEM);
 
-    *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h,
-                            (int (*)(void *, uint8_t *, int)) ffurl_read,
-                            (int (*)(void *, uint8_t *, int)) ffurl_write,
-                            (int64_t (*)(void *, int64_t, int)) ffurl_seek);
-    if (!*s) {
-        av_free(buffer);
-        return AVERROR(ENOMEM);
-    }
+    internal = av_mallocz(sizeof(*internal));
+    if (!internal)
+        goto fail;
+
+    internal->h = h;
+
+    *s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE,
+                            internal, io_read_packet, io_write_packet, io_seek);
+    if (!*s)
+        goto fail;
+
     (*s)->protocol_whitelist = av_strdup(h->protocol_whitelist);
     if (!(*s)->protocol_whitelist && h->protocol_whitelist) {
         avio_closep(s);
-        return AVERROR(ENOMEM);
+        goto fail;
+    }
+    (*s)->protocol_blacklist = av_strdup(h->protocol_blacklist);
+    if (!(*s)->protocol_blacklist && h->protocol_blacklist) {
+        avio_closep(s);
+        goto fail;
     }
     (*s)->direct = h->flags & AVIO_FLAG_DIRECT;
+
     (*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
     (*s)->max_packet_size = max_packet_size;
     if(h->prot) {
-        (*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
-        (*s)->read_seek  = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek;
+        (*s)->read_pause = io_read_pause;
+        (*s)->read_seek  = io_read_seek;
     }
     (*s)->av_class = &ff_avio_class;
     return 0;
+fail:
+    av_freep(&internal);
+    av_freep(&buffer);
+    return AVERROR(ENOMEM);
 }
 
 int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
@@ -930,13 +1031,13 @@ int avio_open(AVIOContext **s, const char *filename, int flags)
 
 int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
                          const AVIOInterruptCB *int_cb, AVDictionary **options,
-                         const char *whitelist
+                         const char *whitelist, const char *blacklist
                         )
 {
     URLContext *h;
     int err;
 
-    err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist);
+    err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist, NULL);
     if (err < 0)
         return err;
     err = ffio_fdopen(s, h);
@@ -950,24 +1051,28 @@ int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
 int avio_open2(AVIOContext **s, const char *filename, int flags,
                const AVIOInterruptCB *int_cb, AVDictionary **options)
 {
-    return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL);
+    return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL, NULL);
 }
 
 int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
                        const AVIOInterruptCB *int_cb, AVDictionary **options)
 {
-    return ffio_open_whitelist(pb, url, flags, int_cb, options, s->protocol_whitelist);
+    return ffio_open_whitelist(pb, url, flags, int_cb, options, s->protocol_whitelist, s->protocol_blacklist);
 }
 
 int avio_close(AVIOContext *s)
 {
+    AVIOInternal *internal;
     URLContext *h;
 
     if (!s)
         return 0;
 
     avio_flush(s);
-    h = s->opaque;
+    internal = s->opaque;
+    h        = internal->h;
+
+    av_freep(&s->opaque);
     av_freep(&s->buffer);
     if (s->write_flag)
         av_log(s, AV_LOG_DEBUG, "Statistics: %d seeks, %d writeouts\n", s->seek_count, s->writeout_count);
@@ -1008,15 +1113,14 @@ int avio_pause(AVIOContext *s, int pause)
 int64_t avio_seek_time(AVIOContext *s, int stream_index,
                        int64_t timestamp, int flags)
 {
-    URLContext *h = s->opaque;
     int64_t ret;
     if (!s->read_seek)
         return AVERROR(ENOSYS);
-    ret = s->read_seek(h, stream_index, timestamp, flags);
+    ret = s->read_seek(s->opaque, stream_index, timestamp, flags);
     if (ret >= 0) {
         int64_t pos;
         s->buf_ptr = s->buf_end; // Flush buffer
-        pos = s->seek(h, 0, SEEK_CUR);
+        pos = s->seek(s->opaque, 0, SEEK_CUR);
         if (pos >= 0)
             s->pos = pos;
         else if (pos != AVERROR(ENOSYS))
diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c
index 45641c0..d6167fa 100644
--- a/libavformat/avisynth.c
+++ b/libavformat/avisynth.c
@@ -1,6 +1,6 @@
 /*
  * AviSynth/AvxSynth support
- * Copyright (c) 2012 AvxSynth Team.
+ * Copyright (c) 2012 AvxSynth Team
  *
  * This file is part of FFmpeg
  * FFmpeg is free software; you can redistribute it and/or
@@ -232,10 +232,10 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st)
     AviSynthContext *avs = s->priv_data;
     int planar = 0; // 0: packed, 1: YUV, 2: Y8
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
-    st->codec->width      = avs->vi->width;
-    st->codec->height     = avs->vi->height;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->width      = avs->vi->width;
+    st->codecpar->height     = avs->vi->height;
 
     st->avg_frame_rate    = (AVRational) { avs->vi->fps_numerator,
                                            avs->vi->fps_denominator };
@@ -247,38 +247,38 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st)
     switch (avs->vi->pixel_type) {
 #ifdef USING_AVISYNTH
     case AVS_CS_YV24:
-        st->codec->pix_fmt = AV_PIX_FMT_YUV444P;
-        planar             = 1;
+        st->codecpar->format = AV_PIX_FMT_YUV444P;
+        planar               = 1;
         break;
     case AVS_CS_YV16:
-        st->codec->pix_fmt = AV_PIX_FMT_YUV422P;
-        planar             = 1;
+        st->codecpar->format = AV_PIX_FMT_YUV422P;
+        planar               = 1;
         break;
     case AVS_CS_YV411:
-        st->codec->pix_fmt = AV_PIX_FMT_YUV411P;
-        planar             = 1;
+        st->codecpar->format = AV_PIX_FMT_YUV411P;
+        planar               = 1;
         break;
     case AVS_CS_Y8:
-        st->codec->pix_fmt = AV_PIX_FMT_GRAY8;
-        planar             = 2;
+        st->codecpar->format = AV_PIX_FMT_GRAY8;
+        planar               = 2;
         break;
 #endif
     case AVS_CS_BGR24:
-        st->codec->pix_fmt = AV_PIX_FMT_BGR24;
+        st->codecpar->format = AV_PIX_FMT_BGR24;
         break;
     case AVS_CS_BGR32:
-        st->codec->pix_fmt = AV_PIX_FMT_RGB32;
+        st->codecpar->format = AV_PIX_FMT_RGB32;
         break;
     case AVS_CS_YUY2:
-        st->codec->pix_fmt = AV_PIX_FMT_YUYV422;
+        st->codecpar->format = AV_PIX_FMT_YUYV422;
         break;
     case AVS_CS_YV12:
-        st->codec->pix_fmt = AV_PIX_FMT_YUV420P;
-        planar             = 1;
+        st->codecpar->format = AV_PIX_FMT_YUV420P;
+        planar               = 1;
         break;
     case AVS_CS_I420: // Is this even used anywhere?
-        st->codec->pix_fmt = AV_PIX_FMT_YUV420P;
-        planar             = 1;
+        st->codecpar->format = AV_PIX_FMT_YUV420P;
+        planar               = 1;
         break;
     default:
         av_log(s, AV_LOG_ERROR,
@@ -307,27 +307,27 @@ static int avisynth_create_stream_audio(AVFormatContext *s, AVStream *st)
 {
     AviSynthContext *avs = s->priv_data;
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->sample_rate = avs->vi->audio_samples_per_second;
-    st->codec->channels    = avs->vi->nchannels;
-    st->duration           = avs->vi->num_audio_samples;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->sample_rate = avs->vi->audio_samples_per_second;
+    st->codecpar->channels    = avs->vi->nchannels;
+    st->duration              = avs->vi->num_audio_samples;
     avpriv_set_pts_info(st, 64, 1, avs->vi->audio_samples_per_second);
 
     switch (avs->vi->sample_type) {
     case AVS_SAMPLE_INT8:
-        st->codec->codec_id = AV_CODEC_ID_PCM_U8;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
         break;
     case AVS_SAMPLE_INT16:
-        st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
         break;
     case AVS_SAMPLE_INT24:
-        st->codec->codec_id = AV_CODEC_ID_PCM_S24LE;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
         break;
     case AVS_SAMPLE_INT32:
-        st->codec->codec_id = AV_CODEC_ID_PCM_S32LE;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
         break;
     case AVS_SAMPLE_FLOAT:
-        st->codec->codec_id = AV_CODEC_ID_PCM_F32LE;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
         break;
     default:
         av_log(s, AV_LOG_ERROR,
@@ -636,7 +636,7 @@ static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt)
     /* If either stream reaches EOF, try to read the other one before
      * giving up. */
     avisynth_next_stream(s, &st, pkt, &discard);
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         ret = avisynth_read_packet_video(s, pkt, discard);
         if (ret == AVERROR_EOF && avs_has_audio(avs->vi)) {
             avisynth_next_stream(s, &st, pkt, &discard);
@@ -678,7 +678,7 @@ static int avisynth_read_seek(AVFormatContext *s, int stream_index,
     samplerate = (AVRational) { avs->vi->audio_samples_per_second, 1 };
 
     st = s->streams[stream_index];
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         /* AviSynth frame counts are signed int. */
         if ((timestamp >= avs->vi->num_frames) ||
             (timestamp > INT_MAX)              ||
diff --git a/libavformat/avlanguage.h b/libavformat/avlanguage.h
index 7fb8968..84bef58 100644
--- a/libavformat/avlanguage.h
+++ b/libavformat/avlanguage.h
@@ -26,7 +26,7 @@
  */
 enum AVLangCodespace {
     AV_LANG_ISO639_2_BIBL, /** 3-char bibliographic language codes as per ISO-IEC 639-2 */
-    AV_LANG_ISO639_2_TERM, /** 3-char terminologic language codes as per ISO-IEC 639-2 */
+    AV_LANG_ISO639_2_TERM, /** 3-char terminological language codes as per ISO-IEC 639-2 */
     AV_LANG_ISO639_1       /** 2-char code of language as per ISO/IEC 639-1 */
 };
 
diff --git a/libavformat/avr.c b/libavformat/avr.c
index a33134e..294160e 100644
--- a/libavformat/avr.c
+++ b/libavformat/avr.c
@@ -46,22 +46,22 @@ static int avr_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
 
     avio_skip(s->pb, 4); // magic
     avio_skip(s->pb, 8); // sample_name
 
     chan = avio_rb16(s->pb);
     if (!chan) {
-        st->codec->channels = 1;
+        st->codecpar->channels = 1;
     } else if (chan == 0xFFFFu) {
-        st->codec->channels = 2;
+        st->codecpar->channels = 2;
     } else {
         avpriv_request_sample(s, "chan %d", chan);
         return AVERROR_PATCHWELCOME;
     }
 
-    st->codec->bits_per_coded_sample = bps = avio_rb16(s->pb);
+    st->codecpar->bits_per_coded_sample = bps = avio_rb16(s->pb);
 
     sign = avio_rb16(s->pb);
 
@@ -69,21 +69,21 @@ static int avr_read_header(AVFormatContext *s)
     avio_skip(s->pb, 2); // midi
     avio_skip(s->pb, 1); // replay speed
 
-    st->codec->sample_rate = avio_rb24(s->pb);
+    st->codecpar->sample_rate = avio_rb24(s->pb);
     avio_skip(s->pb, 4 * 3);
     avio_skip(s->pb, 2 * 3);
     avio_skip(s->pb, 20);
     avio_skip(s->pb, 64);
 
-    st->codec->codec_id = ff_get_pcm_codec_id(bps, 0, 1, sign);
-    if (st->codec->codec_id == AV_CODEC_ID_NONE) {
+    st->codecpar->codec_id = ff_get_pcm_codec_id(bps, 0, 1, sign);
+    if (st->codecpar->codec_id == AV_CODEC_ID_NONE) {
         avpriv_request_sample(s, "Bps %d and sign %d", bps, sign);
         return AVERROR_PATCHWELCOME;
     }
 
-    st->codec->block_align = bps * st->codec->channels / 8;
+    st->codecpar->block_align = bps * st->codecpar->channels / 8;
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     return 0;
 }
 
diff --git a/libavformat/avs.c b/libavformat/avs.c
index b264b55..763ba63 100644
--- a/libavformat/avs.c
+++ b/libavformat/avs.c
@@ -184,11 +184,11 @@ static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
                     avs->st_video = avformat_new_stream(s, NULL);
                     if (!avs->st_video)
                         return AVERROR(ENOMEM);
-                    avs->st_video->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-                    avs->st_video->codec->codec_id = AV_CODEC_ID_AVS;
-                    avs->st_video->codec->width = avs->width;
-                    avs->st_video->codec->height = avs->height;
-                    avs->st_video->codec->bits_per_coded_sample=avs->bits_per_sample;
+                    avs->st_video->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+                    avs->st_video->codecpar->codec_id = AV_CODEC_ID_AVS;
+                    avs->st_video->codecpar->width = avs->width;
+                    avs->st_video->codecpar->height = avs->height;
+                    avs->st_video->codecpar->bits_per_coded_sample=avs->bits_per_sample;
                     avs->st_video->nb_frames = avs->nb_frames;
 #if FF_API_R_FRAME_RATE
                     avs->st_video->r_frame_rate =
@@ -203,7 +203,7 @@ static int avs_read_packet(AVFormatContext * s, AVPacket * pkt)
                     avs->st_audio = avformat_new_stream(s, NULL);
                     if (!avs->st_audio)
                         return AVERROR(ENOMEM);
-                    avs->st_audio->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+                    avs->st_audio->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
                 }
                 avs->remaining_audio_size = size - 4;
                 size = avs_read_audio_packet(s, pkt);
diff --git a/libavformat/bethsoftvid.c b/libavformat/bethsoftvid.c
index 40a4252..f516806 100644
--- a/libavformat/bethsoftvid.c
+++ b/libavformat/bethsoftvid.c
@@ -116,13 +116,13 @@ static int read_frame(BVID_DemuxContext *vid, AVIOContext *pb, AVPacket *pkt,
                                   "video packet");
         }
         avpriv_set_pts_info(st, 64, 185, vid->sample_rate);
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id   = AV_CODEC_ID_BETHSOFTVID;
-        st->codec->width      = vid->width;
-        st->codec->height     = vid->height;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_id   = AV_CODEC_ID_BETHSOFTVID;
+        st->codecpar->width      = vid->width;
+        st->codecpar->height     = vid->height;
     }
     st      = s->streams[vid->video_index];
-    npixels = st->codec->width * st->codec->height;
+    npixels = st->codecpar->width * st->codecpar->height;
 
     vidbuf_start = av_malloc(vidbuf_capacity = BUFFER_PADDING_SIZE);
     if(!vidbuf_start)
@@ -245,13 +245,13 @@ static int vid_read_packet(AVFormatContext *s,
                 if (!st)
                     return AVERROR(ENOMEM);
                 vid->audio_index                 = st->index;
-                st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
-                st->codec->codec_id              = AV_CODEC_ID_PCM_U8;
-                st->codec->channels              = 1;
-                st->codec->channel_layout        = AV_CH_LAYOUT_MONO;
-                st->codec->bits_per_coded_sample = 8;
-                st->codec->sample_rate           = vid->sample_rate;
-                st->codec->bit_rate              = 8 * st->codec->sample_rate;
+                st->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
+                st->codecpar->codec_id              = AV_CODEC_ID_PCM_U8;
+                st->codecpar->channels              = 1;
+                st->codecpar->channel_layout        = AV_CH_LAYOUT_MONO;
+                st->codecpar->bits_per_coded_sample = 8;
+                st->codecpar->sample_rate           = vid->sample_rate;
+                st->codecpar->bit_rate              = 8 * st->codecpar->sample_rate;
                 st->start_time                   = 0;
                 avpriv_set_pts_info(st, 64, 1, vid->sample_rate);
             }
diff --git a/libavformat/bfi.c b/libavformat/bfi.c
index cc7f494..568363d 100644
--- a/libavformat/bfi.c
+++ b/libavformat/bfi.c
@@ -75,38 +75,38 @@ static int bfi_read_header(AVFormatContext * s)
     avio_rl32(pb);
     fps                    = avio_rl32(pb);
     avio_skip(pb, 12);
-    vstream->codec->width  = avio_rl32(pb);
-    vstream->codec->height = avio_rl32(pb);
+    vstream->codecpar->width  = avio_rl32(pb);
+    vstream->codecpar->height = avio_rl32(pb);
 
     /*Load the palette to extradata */
     avio_skip(pb, 8);
-    vstream->codec->extradata      = av_malloc(768);
-    if (!vstream->codec->extradata)
+    vstream->codecpar->extradata      = av_malloc(768);
+    if (!vstream->codecpar->extradata)
         return AVERROR(ENOMEM);
-    vstream->codec->extradata_size = 768;
-    avio_read(pb, vstream->codec->extradata,
-               vstream->codec->extradata_size);
+    vstream->codecpar->extradata_size = 768;
+    avio_read(pb, vstream->codecpar->extradata,
+               vstream->codecpar->extradata_size);
 
-    astream->codec->sample_rate = avio_rl32(pb);
+    astream->codecpar->sample_rate = avio_rl32(pb);
 
     /* Set up the video codec... */
     avpriv_set_pts_info(vstream, 32, 1, fps);
-    vstream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vstream->codec->codec_id   = AV_CODEC_ID_BFI;
-    vstream->codec->pix_fmt    = AV_PIX_FMT_PAL8;
-    vstream->nb_frames         =
-    vstream->duration          = bfi->nframes;
+    vstream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    vstream->codecpar->codec_id   = AV_CODEC_ID_BFI;
+    vstream->codecpar->format     = AV_PIX_FMT_PAL8;
+    vstream->nb_frames            =
+    vstream->duration             = bfi->nframes;
 
     /* Set up the audio codec now... */
-    astream->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
-    astream->codec->codec_id        = AV_CODEC_ID_PCM_U8;
-    astream->codec->channels        = 1;
-    astream->codec->channel_layout  = AV_CH_LAYOUT_MONO;
-    astream->codec->bits_per_coded_sample = 8;
-    astream->codec->bit_rate        =
-        astream->codec->sample_rate * astream->codec->bits_per_coded_sample;
+    astream->codecpar->codec_type      = AVMEDIA_TYPE_AUDIO;
+    astream->codecpar->codec_id        = AV_CODEC_ID_PCM_U8;
+    astream->codecpar->channels        = 1;
+    astream->codecpar->channel_layout  = AV_CH_LAYOUT_MONO;
+    astream->codecpar->bits_per_coded_sample = 8;
+    astream->codecpar->bit_rate        =
+        astream->codecpar->sample_rate * astream->codecpar->bits_per_coded_sample;
     avio_seek(pb, chunk_header - 3, SEEK_SET);
-    avpriv_set_pts_info(astream, 64, 1, astream->codec->sample_rate);
+    avpriv_set_pts_info(astream, 64, 1, astream->codecpar->sample_rate);
     return 0;
 }
 
diff --git a/libavformat/bink.c b/libavformat/bink.c
index 332edbb..c214eb3 100644
--- a/libavformat/bink.c
+++ b/libavformat/bink.c
@@ -45,6 +45,7 @@ enum BinkAudFlags {
 #define BINK_MAX_AUDIO_TRACKS   256
 #define BINK_MAX_WIDTH          7680
 #define BINK_MAX_HEIGHT         4800
+#define SMUSH_BLOCK_SIZE        512
 
 typedef struct BinkDemuxContext {
     uint32_t file_size;
@@ -55,21 +56,26 @@ typedef struct BinkDemuxContext {
     int64_t audio_pts[BINK_MAX_AUDIO_TRACKS];
 
     uint32_t remain_packet_size;
+    int smush_size;
 } BinkDemuxContext;
 
 static int probe(AVProbeData *p)
 {
     const uint8_t *b = p->buf;
-
-    if (((b[0] == 'B' && b[1] == 'I' && b[2] == 'K' &&
-         (b[3] == 'b' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' || b[3] == 'i')) ||
-         (b[0] == 'K' && b[1] == 'B' && b[2] == '2' && /* Bink 2 */
-         (b[3] == 'a' || b[3] == 'd' || b[3] == 'f' || b[3] == 'g'))) &&
-        AV_RL32(b+8) > 0 &&  // num_frames
-        AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH &&
-        AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT &&
-        AV_RL32(b+28) > 0 && AV_RL32(b+32) > 0)  // fps num,den
-        return AVPROBE_SCORE_MAX;
+    int smush = AV_RN32(p->buf) == AV_RN32("SMUS");
+
+    do {
+        if (((b[0] == 'B' && b[1] == 'I' && b[2] == 'K' &&
+             (b[3] == 'b' || b[3] == 'f' || b[3] == 'g' || b[3] == 'h' || b[3] == 'i')) ||
+             (b[0] == 'K' && b[1] == 'B' && b[2] == '2' && /* Bink 2 */
+             (b[3] == 'a' || b[3] == 'd' || b[3] == 'f' || b[3] == 'g'))) &&
+            AV_RL32(b+8) > 0 &&  // num_frames
+            AV_RL32(b+20) > 0 && AV_RL32(b+20) <= BINK_MAX_WIDTH &&
+            AV_RL32(b+24) > 0 && AV_RL32(b+24) <= BINK_MAX_HEIGHT &&
+            AV_RL32(b+28) > 0 && AV_RL32(b+32) > 0)  // fps num,den
+            return AVPROBE_SCORE_MAX;
+            b += SMUSH_BLOCK_SIZE;
+    } while (smush && b < p->buf + p->buf_size - 32);
     return 0;
 }
 
@@ -89,7 +95,18 @@ static int read_header(AVFormatContext *s)
     if (!vst)
         return AVERROR(ENOMEM);
 
-    vst->codec->codec_tag = avio_rl32(pb);
+    vst->codecpar->codec_tag = avio_rl32(pb);
+    if (vst->codecpar->codec_tag == AV_RL32("SMUS")) {
+        do {
+            bink->smush_size += SMUSH_BLOCK_SIZE;
+            avio_skip(pb, SMUSH_BLOCK_SIZE - 4);
+            vst->codecpar->codec_tag = avio_rl32(pb);
+        } while (!avio_feof(pb) && (vst->codecpar->codec_tag & 0xFFFFFF) != AV_RL32("BIK"));
+        if (avio_feof(pb)) {
+            av_log(s, AV_LOG_ERROR, "invalid SMUSH header: BIK not found\n");
+            return AVERROR_INVALIDDATA;
+        }
+    }
 
     bink->file_size = avio_rl32(pb) + 8;
     vst->duration   = avio_rl32(pb);
@@ -107,8 +124,8 @@ static int read_header(AVFormatContext *s)
 
     avio_skip(pb, 4);
 
-    vst->codec->width  = avio_rl32(pb);
-    vst->codec->height = avio_rl32(pb);
+    vst->codecpar->width  = avio_rl32(pb);
+    vst->codecpar->height = avio_rl32(pb);
 
     fps_num = avio_rl32(pb);
     fps_den = avio_rl32(pb);
@@ -121,15 +138,15 @@ static int read_header(AVFormatContext *s)
     avpriv_set_pts_info(vst, 64, fps_den, fps_num);
     vst->avg_frame_rate = av_inv_q(vst->time_base);
 
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_id   = AV_CODEC_ID_BINKVIDEO;
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_id   = AV_CODEC_ID_BINKVIDEO;
 
-    if ((vst->codec->codec_tag & 0xFFFFFF) == MKTAG('K', 'B', '2', 0)) {
+    if ((vst->codecpar->codec_tag & 0xFFFFFF) == MKTAG('K', 'B', '2', 0)) {
         av_log(s, AV_LOG_WARNING, "Bink 2 video is not implemented\n");
-        vst->codec->codec_id = AV_CODEC_ID_NONE;
+        vst->codecpar->codec_id = AV_CODEC_ID_NONE;
     }
 
-    if (ff_get_extradata(vst->codec, pb, 4) < 0)
+    if (ff_get_extradata(s, vst->codecpar, pb, 4) < 0)
         return AVERROR(ENOMEM);
 
     bink->num_audio_tracks = avio_rl32(pb);
@@ -148,23 +165,23 @@ static int read_header(AVFormatContext *s)
             ast = avformat_new_stream(s, NULL);
             if (!ast)
                 return AVERROR(ENOMEM);
-            ast->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-            ast->codec->codec_tag   = 0;
-            ast->codec->sample_rate = avio_rl16(pb);
-            avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
+            ast->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+            ast->codecpar->codec_tag   = 0;
+            ast->codecpar->sample_rate = avio_rl16(pb);
+            avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
             flags = avio_rl16(pb);
-            ast->codec->codec_id = flags & BINK_AUD_USEDCT ?
+            ast->codecpar->codec_id = flags & BINK_AUD_USEDCT ?
                                    AV_CODEC_ID_BINKAUDIO_DCT : AV_CODEC_ID_BINKAUDIO_RDFT;
             if (flags & BINK_AUD_STEREO) {
-                ast->codec->channels       = 2;
-                ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+                ast->codecpar->channels       = 2;
+                ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
             } else {
-                ast->codec->channels       = 1;
-                ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
+                ast->codecpar->channels       = 1;
+                ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
             }
-            if (ff_alloc_extradata(ast->codec, 4))
+            if (ff_alloc_extradata(ast->codecpar, 4))
                 return AVERROR(ENOMEM);
-            AV_WL32(ast->codec->extradata, vst->codec->codec_tag);
+            AV_WL32(ast->codecpar->extradata, vst->codecpar->codec_tag);
         }
 
         for (i = 0; i < bink->num_audio_tracks; i++)
@@ -195,7 +212,7 @@ static int read_header(AVFormatContext *s)
     }
 
     if (vst->index_entries)
-        avio_seek(pb, vst->index_entries[0].pos, SEEK_SET);
+        avio_seek(pb, vst->index_entries[0].pos + bink->smush_size, SEEK_SET);
     else
         avio_skip(pb, 4);
 
@@ -247,10 +264,10 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
             pkt->pts = bink->audio_pts[bink->current_track - 1];
 
             /* Each audio packet reports the number of decompressed samples
-               (in bytes). We use this value to calcuate the audio PTS */
+               (in bytes). We use this value to calculate the audio PTS */
             if (pkt->size >= 4)
                 bink->audio_pts[bink->current_track -1] +=
-                    AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codec->channels);
+                    AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codecpar->channels);
             return 0;
         } else {
             avio_skip(pb, audio_size);
@@ -279,7 +296,7 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, in
         return -1;
 
     /* seek to the first frame */
-    if (avio_seek(s->pb, vst->index_entries[0].pos, SEEK_SET) < 0)
+    if (avio_seek(s->pb, vst->index_entries[0].pos + bink->smush_size, SEEK_SET) < 0)
         return -1;
 
     bink->video_pts = 0;
diff --git a/libavformat/bintext.c b/libavformat/bintext.c
index 217ea49..a264fd1 100644
--- a/libavformat/bintext.c
+++ b/libavformat/bintext.c
@@ -54,12 +54,12 @@ static AVStream * init_stream(AVFormatContext *s)
     AVStream *st = avformat_new_stream(s, NULL);
     if (!st)
         return NULL;
-    st->codec->codec_tag   = 0;
-    st->codec->codec_type  = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_tag   = 0;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_VIDEO;
 
     if (!bin->width) {
-        st->codec->width  = (80<<3);
-        st->codec->height = (25<<4);
+        st->codecpar->width  = (80<<3);
+        st->codecpar->height = (25<<4);
     }
 
     avpriv_set_pts_info(st, 60, bin->framerate.den, bin->framerate.num);
@@ -74,9 +74,9 @@ static AVStream * init_stream(AVFormatContext *s)
 /**
  * Given filesize and width, calculate height (assume font_height of 16)
  */
-static void calculate_height(AVCodecContext *avctx, uint64_t fsize)
+static void calculate_height(AVCodecParameters *par, uint64_t fsize)
 {
-    avctx->height = (fsize / ((avctx->width>>3)*2)) << 4;
+    par->height = (fsize / ((par->width>>3)*2)) << 4;
 }
 #endif
 
@@ -119,11 +119,11 @@ static int next_tag_read(AVFormatContext *avctx, uint64_t *fsize)
     return 0;
 }
 
-static void predict_width(AVCodecContext *avctx, uint64_t fsize, int got_width)
+static void predict_width(AVCodecParameters *par, uint64_t fsize, int got_width)
 {
     /** attempt to guess width */
     if (!got_width)
-        avctx->width = fsize > 4000 ? (160<<3) : (80<<3);
+        par->width = fsize > 4000 ? (160<<3) : (80<<3);
 }
 
 static int bintext_read_header(AVFormatContext *s)
@@ -134,12 +134,12 @@ static int bintext_read_header(AVFormatContext *s)
     AVStream *st = init_stream(s);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_id    = AV_CODEC_ID_BINTEXT;
+    st->codecpar->codec_id    = AV_CODEC_ID_BINTEXT;
 
-    if (ff_alloc_extradata(st->codec, 2))
+    if (ff_alloc_extradata(st->codecpar, 2))
         return AVERROR(ENOMEM);
-    st->codec->extradata[0] = 16;
-    st->codec->extradata[1] = 0;
+    st->codecpar->extradata[0] = 16;
+    st->codecpar->extradata[1] = 0;
 
     if (pb->seekable) {
         int got_width = 0;
@@ -147,8 +147,8 @@ static int bintext_read_header(AVFormatContext *s)
         if (ff_sauce_read(s, &bin->fsize, &got_width, 0) < 0)
             next_tag_read(s, &bin->fsize);
         if (!bin->width) {
-            predict_width(st->codec, bin->fsize, got_width);
-            calculate_height(st->codec, bin->fsize);
+            predict_width(st->codecpar, bin->fsize, got_width);
+            calculate_height(st->codecpar, bin->fsize);
         }
         avio_seek(pb, 0, SEEK_SET);
     }
@@ -179,30 +179,30 @@ static int xbin_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     avio_skip(pb, 5);
-    st->codec->width   = avio_rl16(pb)<<3;
-    st->codec->height  = avio_rl16(pb);
+    st->codecpar->width   = avio_rl16(pb)<<3;
+    st->codecpar->height  = avio_rl16(pb);
     fontheight         = avio_r8(pb);
-    st->codec->height *= fontheight;
+    st->codecpar->height *= fontheight;
     flags              = avio_r8(pb);
 
-    st->codec->extradata_size = 2;
+    st->codecpar->extradata_size = 2;
     if ((flags & BINTEXT_PALETTE))
-        st->codec->extradata_size += 48;
+        st->codecpar->extradata_size += 48;
     if ((flags & BINTEXT_FONT))
-        st->codec->extradata_size += fontheight * (flags & 0x10 ? 512 : 256);
-    st->codec->codec_id    = flags & 4 ? AV_CODEC_ID_XBIN : AV_CODEC_ID_BINTEXT;
+        st->codecpar->extradata_size += fontheight * (flags & 0x10 ? 512 : 256);
+    st->codecpar->codec_id    = flags & 4 ? AV_CODEC_ID_XBIN : AV_CODEC_ID_BINTEXT;
 
-    if (ff_alloc_extradata(st->codec, st->codec->extradata_size))
+    if (ff_alloc_extradata(st->codecpar, st->codecpar->extradata_size))
         return AVERROR(ENOMEM);
-    st->codec->extradata[0] = fontheight;
-    st->codec->extradata[1] = flags;
-    if (avio_read(pb, st->codec->extradata + 2, st->codec->extradata_size - 2) < 0)
+    st->codecpar->extradata[0] = fontheight;
+    st->codecpar->extradata[1] = flags;
+    if (avio_read(pb, st->codecpar->extradata + 2, st->codecpar->extradata_size - 2) < 0)
         return AVERROR(EIO);
 
     if (pb->seekable) {
-        bin->fsize = avio_size(pb) - 9 - st->codec->extradata_size;
+        bin->fsize = avio_size(pb) - 9 - st->codecpar->extradata_size;
         ff_sauce_read(s, &bin->fsize, NULL, 0);
-        avio_seek(pb, 9 + st->codec->extradata_size, SEEK_SET);
+        avio_seek(pb, 9 + st->codecpar->extradata_size, SEEK_SET);
     }
 
     return 0;
@@ -222,28 +222,28 @@ static int adf_read_header(AVFormatContext *s)
     st = init_stream(s);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_id    = AV_CODEC_ID_BINTEXT;
+    st->codecpar->codec_id    = AV_CODEC_ID_BINTEXT;
 
-    if (ff_alloc_extradata(st->codec, 2 + 48 + 4096))
+    if (ff_alloc_extradata(st->codecpar, 2 + 48 + 4096))
         return AVERROR(ENOMEM);
-    st->codec->extradata[0] = 16;
-    st->codec->extradata[1] = BINTEXT_PALETTE|BINTEXT_FONT;
+    st->codecpar->extradata[0] = 16;
+    st->codecpar->extradata[1] = BINTEXT_PALETTE|BINTEXT_FONT;
 
-    if (avio_read(pb, st->codec->extradata + 2, 24) < 0)
+    if (avio_read(pb, st->codecpar->extradata + 2, 24) < 0)
         return AVERROR(EIO);
     avio_skip(pb, 144);
-    if (avio_read(pb, st->codec->extradata + 2 + 24, 24) < 0)
+    if (avio_read(pb, st->codecpar->extradata + 2 + 24, 24) < 0)
         return AVERROR(EIO);
-    if (avio_read(pb, st->codec->extradata + 2 + 48, 4096) < 0)
+    if (avio_read(pb, st->codecpar->extradata + 2 + 48, 4096) < 0)
         return AVERROR(EIO);
 
     if (pb->seekable) {
         int got_width = 0;
         bin->fsize = avio_size(pb) - 1 - 192 - 4096;
-        st->codec->width = 80<<3;
+        st->codecpar->width = 80<<3;
         ff_sauce_read(s, &bin->fsize, &got_width, 0);
         if (!bin->width)
-            calculate_height(st->codec, bin->fsize);
+            calculate_height(st->codecpar, bin->fsize);
         avio_seek(pb, 1 + 192 + 4096, SEEK_SET);
     }
     return 0;
@@ -277,24 +277,24 @@ static int idf_read_header(AVFormatContext *s)
     st = init_stream(s);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_id    = AV_CODEC_ID_IDF;
+    st->codecpar->codec_id    = AV_CODEC_ID_IDF;
 
-    if (ff_alloc_extradata(st->codec, 2 + 48 + 4096))
+    if (ff_alloc_extradata(st->codecpar, 2 + 48 + 4096))
         return AVERROR(ENOMEM);
-    st->codec->extradata[0] = 16;
-    st->codec->extradata[1] = BINTEXT_PALETTE|BINTEXT_FONT;
+    st->codecpar->extradata[0] = 16;
+    st->codecpar->extradata[1] = BINTEXT_PALETTE|BINTEXT_FONT;
 
     avio_seek(pb, avio_size(pb) - 4096 - 48, SEEK_SET);
 
-    if (avio_read(pb, st->codec->extradata + 2 + 48, 4096) < 0)
+    if (avio_read(pb, st->codecpar->extradata + 2 + 48, 4096) < 0)
         return AVERROR(EIO);
-    if (avio_read(pb, st->codec->extradata + 2, 48) < 0)
+    if (avio_read(pb, st->codecpar->extradata + 2, 48) < 0)
         return AVERROR(EIO);
 
     bin->fsize = avio_size(pb) - 12 - 4096 - 48;
     ff_sauce_read(s, &bin->fsize, &got_width, 0);
     if (!bin->width)
-        calculate_height(st->codec, bin->fsize);
+        calculate_height(st->codecpar, bin->fsize);
     avio_seek(pb, 12, SEEK_SET);
     return 0;
 }
@@ -326,7 +326,7 @@ static int read_packet(AVFormatContext *s,
 static const AVOption options[] = {
     { "linespeed", "set simulated line speed (bytes per second)", OFFSET(chars_per_frame), AV_OPT_TYPE_INT, {.i64 = 6000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM},
     { "video_size", "set video size, such as 640x480 or hd720.", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
-    { "framerate", "set framerate (frames per second)", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
+    { "framerate", "set framerate (frames per second)", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     { NULL },
 };
 
diff --git a/libavformat/bit.c b/libavformat/bit.c
index 138d2fe..c3f2fdf 100644
--- a/libavformat/bit.c
+++ b/libavformat/bit.c
@@ -55,11 +55,11 @@ static int read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id=AV_CODEC_ID_G729;
-    st->codec->sample_rate=8000;
-    st->codec->block_align = 16;
-    st->codec->channels=1;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id=AV_CODEC_ID_G729;
+    st->codecpar->sample_rate=8000;
+    st->codecpar->block_align = 16;
+    st->codecpar->channels=1;
 
     avpriv_set_pts_info(st, 64, 1, 100);
     return 0;
@@ -117,16 +117,16 @@ AVInputFormat ff_bit_demuxer = {
 #if CONFIG_MUXERS
 static int write_header(AVFormatContext *s)
 {
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if ((enc->codec_id != AV_CODEC_ID_G729) || enc->channels != 1) {
+    if ((par->codec_id != AV_CODEC_ID_G729) || par->channels != 1) {
         av_log(s, AV_LOG_ERROR,
                "only codec g729 with 1 channel is supported by this format\n");
         return AVERROR(EINVAL);
     }
 
-    enc->bits_per_coded_sample = 16;
-    enc->block_align = (enc->bits_per_coded_sample * enc->channels) >> 3;
+    par->bits_per_coded_sample = 16;
+    par->block_align = (par->bits_per_coded_sample * par->channels) >> 3;
 
     return 0;
 }
diff --git a/libavformat/bluray.c b/libavformat/bluray.c
index d2c57aa..9282bf9 100644
--- a/libavformat/bluray.c
+++ b/libavformat/bluray.c
@@ -224,7 +224,7 @@ static int64_t bluray_seek(URLContext *h, int64_t pos, int whence)
 }
 
 
-URLProtocol ff_bluray_protocol = {
+const URLProtocol ff_bluray_protocol = {
     .name            = "bluray",
     .url_close       = bluray_close,
     .url_open        = bluray_open,
diff --git a/libavformat/bmv.c b/libavformat/bmv.c
index f7a6068..ac567c2 100644
--- a/libavformat/bmv.c
+++ b/libavformat/bmv.c
@@ -1,6 +1,6 @@
 /*
  * Discworld II BMV demuxer
- * Copyright (c) 2011 Konstantin Shishkov.
+ * Copyright (c) 2011 Konstantin Shishkov
  *
  * This file is part of FFmpeg.
  *
@@ -47,20 +47,20 @@ static int bmv_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, 0);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_BMV_VIDEO;
-    st->codec->width      = 640;
-    st->codec->height     = 429;
-    st->codec->pix_fmt    = AV_PIX_FMT_PAL8;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_BMV_VIDEO;
+    st->codecpar->width      = 640;
+    st->codecpar->height     = 429;
+    st->codecpar->format     = AV_PIX_FMT_PAL8;
     avpriv_set_pts_info(st, 16, 1, 12);
     ast = avformat_new_stream(s, 0);
     if (!ast)
         return AVERROR(ENOMEM);
-    ast->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
-    ast->codec->codec_id        = AV_CODEC_ID_BMV_AUDIO;
-    ast->codec->channels        = 2;
-    ast->codec->channel_layout  = AV_CH_LAYOUT_STEREO;
-    ast->codec->sample_rate     = 22050;
+    ast->codecpar->codec_type      = AVMEDIA_TYPE_AUDIO;
+    ast->codecpar->codec_id        = AV_CODEC_ID_BMV_AUDIO;
+    ast->codecpar->channels        = 2;
+    ast->codecpar->channel_layout  = AV_CH_LAYOUT_STEREO;
+    ast->codecpar->sample_rate     = 22050;
     avpriv_set_pts_info(ast, 16, 1, 22050);
 
     c->get_next  = 1;
diff --git a/libavformat/boadec.c b/libavformat/boadec.c
index be003e5..ac2a33b 100644
--- a/libavformat/boadec.c
+++ b/libavformat/boadec.c
@@ -46,16 +46,16 @@ static int read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_ADPCM_MS;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_ADPCM_MS;
 
     avio_rl32(s->pb);
     avio_rl32(s->pb);
-    st->codec->sample_rate = avio_rl32(s->pb);
-    st->codec->channels    = avio_rl32(s->pb);
+    st->codecpar->sample_rate = avio_rl32(s->pb);
+    st->codecpar->channels    = avio_rl32(s->pb);
     s->internal->data_offset = avio_rl32(s->pb);
     avio_r8(s->pb);
-    st->codec->block_align = st->codec->channels * avio_rl32(s->pb);
+    st->codecpar->block_align = st->codecpar->channels * avio_rl32(s->pb);
 
     avio_seek(s->pb, s->internal->data_offset, SEEK_SET);
 
@@ -66,7 +66,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     AVStream *st = s->streams[0];
 
-    return av_get_packet(s->pb, pkt, st->codec->block_align);
+    return av_get_packet(s->pb, pkt, st->codecpar->block_align);
 }
 
 AVInputFormat ff_boa_demuxer = {
diff --git a/libavformat/brstm.c b/libavformat/brstm.c
index aae2575..2e1cada 100644
--- a/libavformat/brstm.c
+++ b/libavformat/brstm.c
@@ -99,7 +99,7 @@ static int read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
 
     avio_skip(s->pb, 4);
 
@@ -169,7 +169,7 @@ static int read_header(AVFormatContext *s)
     }
 
     size = read32(s);
-    if (size < 192)
+    if (size < 40)
         return AVERROR_INVALIDDATA;
     avio_skip(s->pb, 4); // unknown
     h1offset = read32(s);
@@ -197,15 +197,15 @@ static int read_header(AVFormatContext *s)
     }
 
     loop = avio_r8(s->pb); // loop flag
-    st->codec->codec_id = codec;
-    st->codec->channels = avio_r8(s->pb);
-    if (!st->codec->channels)
+    st->codecpar->codec_id = codec;
+    st->codecpar->channels = avio_r8(s->pb);
+    if (!st->codecpar->channels)
         return AVERROR_INVALIDDATA;
 
     avio_skip(s->pb, 1); // padding
 
-    st->codec->sample_rate = bfstm ? read32(s) : read16(s);
-    if (st->codec->sample_rate <= 0)
+    st->codecpar->sample_rate = bfstm ? read32(s) : read16(s);
+    if (st->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
 
     if (!bfstm)
@@ -214,7 +214,7 @@ static int read_header(AVFormatContext *s)
     if (loop) {
         if (av_dict_set_int(&s->metadata, "loop_start",
                             av_rescale(read32(s), AV_TIME_BASE,
-                                       st->codec->sample_rate),
+                                       st->codecpar->sample_rate),
                             0) < 0)
             return AVERROR(ENOMEM);
     } else {
@@ -223,7 +223,7 @@ static int read_header(AVFormatContext *s)
 
     st->start_time = 0;
     st->duration = read32(s);
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     if (!bfstm)
         start = read32(s);
@@ -235,14 +235,14 @@ static int read_header(AVFormatContext *s)
     }
 
     b->block_size = read32(s);
-    if (b->block_size > UINT32_MAX / st->codec->channels)
+    if (b->block_size > UINT32_MAX / st->codecpar->channels)
         return AVERROR_INVALIDDATA;
 
     b->samples_per_block = read32(s);
     b->last_block_used_bytes = read32(s);
     b->last_block_samples = read32(s);
     b->last_block_size = read32(s);
-    if (b->last_block_size > UINT32_MAX / st->codec->channels)
+    if (b->last_block_size > UINT32_MAX / st->codecpar->channels)
         return AVERROR_INVALIDDATA;
     if (b->last_block_used_bytes > b->last_block_size)
         return AVERROR_INVALIDDATA;
@@ -255,16 +255,16 @@ static int read_header(AVFormatContext *s)
         if (!bfstm)
             toffset = read32(s) + 16LL;
         else
-            toffset = toffset + read32(s) + st->codec->channels * 8 - 8;
+            toffset = toffset + read32(s) + st->codecpar->channels * 8 - 8;
         if (toffset > size)
             return AVERROR_INVALIDDATA;
 
         avio_skip(s->pb, pos + toffset - avio_tell(s->pb));
-        b->table = av_mallocz(32 * st->codec->channels);
+        b->table = av_mallocz(32 * st->codecpar->channels);
         if (!b->table)
             return AVERROR(ENOMEM);
 
-        for (ch = 0; ch < st->codec->channels; ch++) {
+        for (ch = 0; ch < st->codecpar->channels; ch++) {
             if (avio_read(s->pb, b->table + ch * 32, 32) != 32) {
                 ret = AVERROR_INVALIDDATA;
                 goto fail;
@@ -295,7 +295,7 @@ static int read_header(AVFormatContext *s)
                 codec != AV_CODEC_ID_ADPCM_THP_LE)
                 goto skip;
 
-            asize = b->block_count * st->codec->channels * 4;
+            asize = b->block_count * st->codecpar->channels * 4;
             if (size < asize) {
                 ret = AVERROR_INVALIDDATA;
                 goto fail;
@@ -357,7 +357,7 @@ fail:
 
 static int read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     BRSTMDemuxContext *b = s->priv_data;
     uint32_t samples, size, skip = 0;
     int ret, i;
@@ -385,8 +385,8 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
         return AVERROR_EOF;
     }
 
-    if (codec->codec_id == AV_CODEC_ID_ADPCM_THP ||
-        codec->codec_id == AV_CODEC_ID_ADPCM_THP_LE) {
+    if (par->codec_id == AV_CODEC_ID_ADPCM_THP ||
+        par->codec_id == AV_CODEC_ID_ADPCM_THP_LE) {
         uint8_t *dst;
 
         if (!b->adpc) {
@@ -394,30 +394,30 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
             return AVERROR_INVALIDDATA;
         }
         if (!b->table) {
-            b->table = av_mallocz(32 * codec->channels);
+            b->table = av_mallocz(32 * par->channels);
             if (!b->table)
                 return AVERROR(ENOMEM);
         }
 
         if (size > (INT_MAX - 32 - 4) ||
-            (32 + 4 + size) > (INT_MAX / codec->channels) ||
-            (32 + 4 + size) * codec->channels > INT_MAX - 8)
+            (32 + 4 + size) > (INT_MAX / par->channels) ||
+            (32 + 4 + size) * par->channels > INT_MAX - 8)
             return AVERROR_INVALIDDATA;
-        if (av_new_packet(pkt, 8 + (32 + 4 + size) * codec->channels) < 0)
+        if (av_new_packet(pkt, 8 + (32 + 4 + size) * par->channels) < 0)
             return AVERROR(ENOMEM);
         dst = pkt->data;
-        if (codec->codec_id == AV_CODEC_ID_ADPCM_THP_LE) {
-            bytestream_put_le32(&dst, size * codec->channels);
+        if (par->codec_id == AV_CODEC_ID_ADPCM_THP_LE) {
+            bytestream_put_le32(&dst, size * par->channels);
             bytestream_put_le32(&dst, samples);
         } else {
-            bytestream_put_be32(&dst, size * codec->channels);
+            bytestream_put_be32(&dst, size * par->channels);
             bytestream_put_be32(&dst, samples);
         }
-        bytestream_put_buffer(&dst, b->table, 32 * codec->channels);
-        bytestream_put_buffer(&dst, b->adpc + 4 * codec->channels *
-                                    (b->current_block - 1), 4 * codec->channels);
+        bytestream_put_buffer(&dst, b->table, 32 * par->channels);
+        bytestream_put_buffer(&dst, b->adpc + 4 * par->channels *
+                                    (b->current_block - 1), 4 * par->channels);
 
-        for (i = 0; i < codec->channels; i++) {
+        for (i = 0; i < par->channels; i++) {
             ret = avio_read(s->pb, dst, size);
             dst += size;
             avio_skip(s->pb, skip);
@@ -428,7 +428,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
         }
         pkt->duration = samples;
     } else {
-        size *= codec->channels;
+        size *= par->channels;
         ret = av_get_packet(s->pb, pkt, size);
     }
 
@@ -449,7 +449,7 @@ static int read_seek(AVFormatContext *s, int stream_index,
 
     timestamp /= b->samples_per_block;
     ret = avio_seek(s->pb, b->data_start + timestamp * b->block_size *
-                           st->codec->channels, SEEK_SET);
+                           st->codecpar->channels, SEEK_SET);
     if (ret < 0)
         return ret;
 
diff --git a/libavformat/c93.c b/libavformat/c93.c
index 20ae9c4..b1a245a 100644
--- a/libavformat/c93.c
+++ b/libavformat/c93.c
@@ -83,10 +83,10 @@ static int read_header(AVFormatContext *s)
     if (!video)
         return AVERROR(ENOMEM);
 
-    video->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    video->codec->codec_id = AV_CODEC_ID_C93;
-    video->codec->width = 320;
-    video->codec->height = 192;
+    video->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    video->codecpar->codec_id = AV_CODEC_ID_C93;
+    video->codecpar->width = 320;
+    video->codecpar->height = 192;
     /* 4:3 320x200 with 8 empty lines */
     video->sample_aspect_ratio = (AVRational) { 5, 6 };
     avpriv_set_pts_info(video, 64, 2, 25);
@@ -120,7 +120,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
                 c93->audio = avformat_new_stream(s, NULL);
                 if (!c93->audio)
                     return AVERROR(ENOMEM);
-                c93->audio->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+                c93->audio->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
             }
             avio_skip(pb, 26); /* VOC header */
             ret = ff_voc_get_packet(s, pkt, c93->audio, datasize - 26);
diff --git a/libavformat/cache.c b/libavformat/cache.c
index 8aed37e..6aabca2 100644
--- a/libavformat/cache.c
+++ b/libavformat/cache.c
@@ -29,7 +29,7 @@
 
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
-#include "libavutil/file.h"
+#include "libavutil/internal.h"
 #include "libavutil/opt.h"
 #include "libavutil/tree.h"
 #include "avformat.h"
@@ -77,7 +77,7 @@ static int cache_open(URLContext *h, const char *arg, int flags, AVDictionary **
 
     av_strstart(arg, "cache:", &arg);
 
-    c->fd = av_tempfile("ffcache", &buffername, 0, h);
+    c->fd = avpriv_tempfile("ffcache", &buffername, 0, h);
     if (c->fd < 0){
         av_log(h, AV_LOG_ERROR, "Failed to create tempfile\n");
         return c->fd;
@@ -87,7 +87,7 @@ static int cache_open(URLContext *h, const char *arg, int flags, AVDictionary **
     av_freep(&buffername);
 
     return ffurl_open_whitelist(&c->inner, arg, flags, &h->interrupt_callback,
-                                options, h->protocol_whitelist);
+                                options, h->protocol_whitelist, h->protocol_blacklist, h);
 }
 
 static int add_entry(URLContext *h, const unsigned char *buf, int size)
@@ -319,7 +319,7 @@ static const AVClass cache_context_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_cache_protocol = {
+const URLProtocol ff_cache_protocol = {
     .name                = "cache",
     .url_open2           = cache_open,
     .url_read            = cache_read,
diff --git a/libavformat/caf.c b/libavformat/caf.c
index 0085461..c05fb80 100644
--- a/libavformat/caf.c
+++ b/libavformat/caf.c
@@ -55,7 +55,7 @@ const AVCodecTag ff_codec_caf_tags[] = {
     { AV_CODEC_ID_PCM_MULAW,       MKTAG('u','l','a','w') },
     { AV_CODEC_ID_QCELP,           MKTAG('Q','c','l','p') },
     { AV_CODEC_ID_QDM2,            MKTAG('Q','D','M','2') },
-    { AV_CODEC_ID_QDM2,            MKTAG('Q','D','M','C') },
+    { AV_CODEC_ID_QDMC,            MKTAG('Q','D','M','C') },
   /* currently unsupported codecs */
   /*{ AC-3 over S/PDIF          MKTAG('c','a','c','3') },*/
   /*{ MPEG4CELP                 MKTAG('c','e','l','p') },*/
diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c
index bfbbb02..1c4ca40 100644
--- a/libavformat/cafdec.c
+++ b/libavformat/cafdec.c
@@ -69,29 +69,29 @@ static int read_desc_chunk(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     /* parse format description */
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->sample_rate = av_int2double(avio_rb64(pb));
-    st->codec->codec_tag   = avio_rl32(pb);
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
+    st->codecpar->codec_tag   = avio_rl32(pb);
     flags = avio_rb32(pb);
     caf->bytes_per_packet  = avio_rb32(pb);
-    st->codec->block_align = caf->bytes_per_packet;
+    st->codecpar->block_align = caf->bytes_per_packet;
     caf->frames_per_packet = avio_rb32(pb);
-    st->codec->channels    = avio_rb32(pb);
-    st->codec->bits_per_coded_sample = avio_rb32(pb);
+    st->codecpar->channels    = avio_rb32(pb);
+    st->codecpar->bits_per_coded_sample = avio_rb32(pb);
 
     /* calculate bit rate for constant size packets */
     if (caf->frames_per_packet > 0 && caf->bytes_per_packet > 0) {
-        st->codec->bit_rate = (uint64_t)st->codec->sample_rate * (uint64_t)caf->bytes_per_packet * 8
-                              / (uint64_t)caf->frames_per_packet;
+        st->codecpar->bit_rate = (uint64_t)st->codecpar->sample_rate * (uint64_t)caf->bytes_per_packet * 8
+                                 / (uint64_t)caf->frames_per_packet;
     } else {
-        st->codec->bit_rate = 0;
+        st->codecpar->bit_rate = 0;
     }
 
     /* determine codec */
-    if (st->codec->codec_tag == MKTAG('l','p','c','m'))
-        st->codec->codec_id = ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, (flags ^ 0x2) | 0x4);
+    if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
+        st->codecpar->codec_id = ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample, (flags ^ 0x2) | 0x4);
     else
-        st->codec->codec_id = ff_codec_get_id(ff_codec_caf_tags, st->codec->codec_tag);
+        st->codecpar->codec_id = ff_codec_get_id(ff_codec_caf_tags, st->codecpar->codec_tag);
     return 0;
 }
 
@@ -104,7 +104,7 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size)
     if (size < 0 || size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
         return -1;
 
-    if (st->codec->codec_id == AV_CODEC_ID_AAC) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
         /* The magic cookie format for AAC is an mp4 esds atom.
            The lavc AAC decoder requires the data from the codec specific
            description as extradata input. */
@@ -113,13 +113,13 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size)
         strt = avio_tell(pb);
         ff_mov_read_esds(s, pb);
         skip = size - (avio_tell(pb) - strt);
-        if (skip < 0 || !st->codec->extradata ||
-            st->codec->codec_id != AV_CODEC_ID_AAC) {
+        if (skip < 0 || !st->codecpar->extradata ||
+            st->codecpar->codec_id != AV_CODEC_ID_AAC) {
             av_log(s, AV_LOG_ERROR, "invalid AAC magic cookie\n");
             return AVERROR_INVALIDDATA;
         }
         avio_skip(pb, skip);
-    } else if (st->codec->codec_id == AV_CODEC_ID_ALAC) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_ALAC) {
 #define ALAC_PREAMBLE 12
 #define ALAC_HEADER   36
 #define ALAC_NEW_KUKI 24
@@ -134,8 +134,8 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size)
             return AVERROR_INVALIDDATA;
         }
 
-        av_freep(&st->codec->extradata);
-        if (ff_alloc_extradata(st->codec, ALAC_HEADER))
+        av_freep(&st->codecpar->extradata);
+        if (ff_alloc_extradata(st->codecpar, ALAC_HEADER))
             return AVERROR(ENOMEM);
 
         /* For the old style cookie, we skip 12 bytes, then read 36 bytes.
@@ -145,30 +145,30 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size)
         if (!memcmp(&preamble[4], "frmaalac", 8)) {
             if (size < ALAC_PREAMBLE + ALAC_HEADER) {
                 av_log(s, AV_LOG_ERROR, "invalid ALAC magic cookie\n");
-                av_freep(&st->codec->extradata);
+                av_freep(&st->codecpar->extradata);
                 return AVERROR_INVALIDDATA;
             }
-            if (avio_read(pb, st->codec->extradata, ALAC_HEADER) != ALAC_HEADER) {
+            if (avio_read(pb, st->codecpar->extradata, ALAC_HEADER) != ALAC_HEADER) {
                 av_log(s, AV_LOG_ERROR, "failed to read kuki header\n");
-                av_freep(&st->codec->extradata);
+                av_freep(&st->codecpar->extradata);
                 return AVERROR_INVALIDDATA;
             }
             avio_skip(pb, size - ALAC_PREAMBLE - ALAC_HEADER);
         } else {
-            AV_WB32(st->codec->extradata, 36);
-            memcpy(&st->codec->extradata[4], "alac", 4);
-            AV_WB32(&st->codec->extradata[8], 0);
-            memcpy(&st->codec->extradata[12], preamble, 12);
-            if (avio_read(pb, &st->codec->extradata[24], ALAC_NEW_KUKI - 12) != ALAC_NEW_KUKI - 12) {
+            AV_WB32(st->codecpar->extradata, 36);
+            memcpy(&st->codecpar->extradata[4], "alac", 4);
+            AV_WB32(&st->codecpar->extradata[8], 0);
+            memcpy(&st->codecpar->extradata[12], preamble, 12);
+            if (avio_read(pb, &st->codecpar->extradata[24], ALAC_NEW_KUKI - 12) != ALAC_NEW_KUKI - 12) {
                 av_log(s, AV_LOG_ERROR, "failed to read new kuki header\n");
-                av_freep(&st->codec->extradata);
+                av_freep(&st->codecpar->extradata);
                 return AVERROR_INVALIDDATA;
             }
             avio_skip(pb, size - ALAC_NEW_KUKI);
         }
     } else {
-        av_freep(&st->codec->extradata);
-        if (ff_get_extradata(st->codec, pb, size) < 0)
+        av_freep(&st->codecpar->extradata);
+        if (ff_get_extradata(s, st->codecpar, pb, size) < 0)
             return AVERROR(ENOMEM);
     }
 
@@ -323,15 +323,15 @@ static int read_header(AVFormatContext *s)
         if (caf->data_size > 0)
             st->nb_frames = (caf->data_size / caf->bytes_per_packet) * caf->frames_per_packet;
     } else if (st->nb_index_entries && st->duration > 0) {
-        st->codec->bit_rate = st->codec->sample_rate * caf->data_size * 8 /
-                              st->duration;
+        st->codecpar->bit_rate = st->codecpar->sample_rate * caf->data_size * 8 /
+                                 st->duration;
     } else {
         av_log(s, AV_LOG_ERROR, "Missing packet table. It is required when "
                                 "block size or frame size are variable.\n");
         return AVERROR_INVALIDDATA;
     }
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     st->start_time = 0;
 
     /* position the stream at the start of data */
diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c
index 544bc4a..5ea8e69 100644
--- a/libavformat/cafenc.c
+++ b/libavformat/cafenc.c
@@ -87,6 +87,7 @@ static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int bl
     case AV_CODEC_ID_AC3:
         return 1536;
     case AV_CODEC_ID_QDM2:
+    case AV_CODEC_ID_QDMC:
         return 2048 * channels;
     case AV_CODEC_ID_ALAC:
         return 4096;
@@ -102,19 +103,19 @@ static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels, int bl
 static int caf_write_header(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     CAFContext *caf = s->priv_data;
     AVDictionaryEntry *t = NULL;
-    unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, enc->codec_id);
+    unsigned int codec_tag = ff_codec_get_tag(ff_codec_caf_tags, par->codec_id);
     int64_t chunk_size = 0;
-    int frame_size = enc->frame_size;
+    int frame_size = par->frame_size;
 
     if (s->nb_streams != 1) {
         av_log(s, AV_LOG_ERROR, "CAF files have exactly one stream\n");
         return AVERROR(EINVAL);
     }
 
-    switch (enc->codec_id) {
+    switch (par->codec_id) {
     case AV_CODEC_ID_AAC:
         av_log(s, AV_LOG_ERROR, "muxing codec currently unsupported\n");
         return AVERROR_PATCHWELCOME;
@@ -125,13 +126,13 @@ static int caf_write_header(AVFormatContext *s)
         return AVERROR_INVALIDDATA;
     }
 
-    if (!enc->block_align && !pb->seekable) {
+    if (!par->block_align && !pb->seekable) {
         av_log(s, AV_LOG_ERROR, "Muxing variable packet size not supported on non seekable output\n");
         return AVERROR_INVALIDDATA;
     }
 
-    if (enc->codec_id != AV_CODEC_ID_MP3 || frame_size != 576)
-        frame_size = samples_per_packet(enc->codec_id, enc->channels, enc->block_align);
+    if (par->codec_id != AV_CODEC_ID_MP3 || frame_size != 576)
+        frame_size = samples_per_packet(par->codec_id, par->channels, par->block_align);
 
     ffio_wfourcc(pb, "caff"); //< mFileType
     avio_wb16(pb, 1);         //< mFileVersion
@@ -139,26 +140,26 @@ static int caf_write_header(AVFormatContext *s)
 
     ffio_wfourcc(pb, "desc");                         //< Audio Description chunk
     avio_wb64(pb, 32);                                //< mChunkSize
-    avio_wb64(pb, av_double2int(enc->sample_rate));   //< mSampleRate
+    avio_wb64(pb, av_double2int(par->sample_rate));   //< mSampleRate
     avio_wl32(pb, codec_tag);                         //< mFormatID
-    avio_wb32(pb, codec_flags(enc->codec_id));        //< mFormatFlags
-    avio_wb32(pb, enc->block_align);                  //< mBytesPerPacket
+    avio_wb32(pb, codec_flags(par->codec_id));        //< mFormatFlags
+    avio_wb32(pb, par->block_align);                  //< mBytesPerPacket
     avio_wb32(pb, frame_size);                        //< mFramesPerPacket
-    avio_wb32(pb, enc->channels);                     //< mChannelsPerFrame
-    avio_wb32(pb, av_get_bits_per_sample(enc->codec_id)); //< mBitsPerChannel
+    avio_wb32(pb, par->channels);                     //< mChannelsPerFrame
+    avio_wb32(pb, av_get_bits_per_sample(par->codec_id)); //< mBitsPerChannel
 
-    if (enc->channel_layout) {
+    if (par->channel_layout) {
         ffio_wfourcc(pb, "chan");
         avio_wb64(pb, 12);
-        ff_mov_write_chan(pb, enc->channel_layout);
+        ff_mov_write_chan(pb, par->channel_layout);
     }
 
-    if (enc->codec_id == AV_CODEC_ID_ALAC) {
+    if (par->codec_id == AV_CODEC_ID_ALAC) {
         ffio_wfourcc(pb, "kuki");
-        avio_wb64(pb, 12 + enc->extradata_size);
+        avio_wb64(pb, 12 + par->extradata_size);
         avio_write(pb, "\0\0\0\14frmaalac", 12);
-        avio_write(pb, enc->extradata, enc->extradata_size);
-    } else if (enc->codec_id == AV_CODEC_ID_AMR_NB) {
+        avio_write(pb, par->extradata, par->extradata_size);
+    } else if (par->codec_id == AV_CODEC_ID_AMR_NB) {
         ffio_wfourcc(pb, "kuki");
         avio_wb64(pb, 29);
         avio_write(pb, "\0\0\0\14frmasamr", 12);
@@ -169,12 +170,13 @@ static int caf_write_header(AVFormatContext *s)
         avio_wb16(pb, 0x81FF); /* Mode set (all modes for AMR_NB) */
         avio_w8(pb, 0x00); /* Mode change period (no restriction) */
         avio_w8(pb, 0x01); /* Frames per sample */
-    } else if (enc->codec_id == AV_CODEC_ID_QDM2) {
+    } else if (par->codec_id == AV_CODEC_ID_QDM2 || par->codec_id == AV_CODEC_ID_QDMC) {
         ffio_wfourcc(pb, "kuki");
-        avio_wb64(pb, enc->extradata_size);
-        avio_write(pb, enc->extradata, enc->extradata_size);
+        avio_wb64(pb, par->extradata_size);
+        avio_write(pb, par->extradata, par->extradata_size);
     }
 
+    ff_standardize_creation_time(s);
     if (av_dict_count(s->metadata)) {
         ffio_wfourcc(pb, "info"); //< Information chunk
         while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
@@ -203,7 +205,7 @@ static int caf_write_packet(AVFormatContext *s, AVPacket *pkt)
     CAFContext *caf = s->priv_data;
 
     avio_write(s->pb, pkt->data, pkt->size);
-    if (!s->streams[0]->codec->block_align) {
+    if (!s->streams[0]->codecpar->block_align) {
         void *pkt_sizes = caf->pkt_sizes;
         int i, alloc_size = caf->size_entries_used + 5;
         if (alloc_size < 0) {
@@ -232,7 +234,7 @@ static int caf_write_trailer(AVFormatContext *s)
 {
     CAFContext *caf = s->priv_data;
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
     if (pb->seekable) {
         int64_t file_size = avio_tell(pb);
@@ -240,11 +242,11 @@ static int caf_write_trailer(AVFormatContext *s)
         avio_seek(pb, caf->data, SEEK_SET);
         avio_wb64(pb, file_size - caf->data - 8);
         avio_seek(pb, file_size, SEEK_SET);
-        if (!enc->block_align) {
+        if (!par->block_align) {
             ffio_wfourcc(pb, "pakt");
             avio_wb64(pb, caf->size_entries_used + 24);
             avio_wb64(pb, caf->packets); ///< mNumberPackets
-            avio_wb64(pb, caf->packets * samples_per_packet(enc->codec_id, enc->channels, enc->block_align)); ///< mNumberValidFrames
+            avio_wb64(pb, caf->packets * samples_per_packet(par->codec_id, par->channels, par->block_align)); ///< mNumberValidFrames
             avio_wb32(pb, 0); ///< mPrimingFrames
             avio_wb32(pb, 0); ///< mRemainderFrames
             avio_write(pb, caf->pkt_sizes, caf->size_entries_used);
diff --git a/libavformat/cdg.c b/libavformat/cdg.c
index b1f137f..05cac6e 100644
--- a/libavformat/cdg.c
+++ b/libavformat/cdg.c
@@ -39,8 +39,8 @@ static int read_header(AVFormatContext *s)
     if (!vst)
         return AVERROR(ENOMEM);
 
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_id   = AV_CODEC_ID_CDGRAPHICS;
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_id   = AV_CODEC_ID_CDGRAPHICS;
 
     /// 75 sectors/sec * 4 packets/sector = 300 packets/sec
     avpriv_set_pts_info(vst, 32, 1, 300);
diff --git a/libavformat/cdxl.c b/libavformat/cdxl.c
index 3d80b47..94a063c 100644
--- a/libavformat/cdxl.c
+++ b/libavformat/cdxl.c
@@ -111,7 +111,7 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
     uint32_t current_size, video_size, image_size;
     uint16_t audio_size, palette_size, width, height;
     int64_t  pos;
-    int      frames, ret;
+    int      format, frames, ret;
 
     if (avio_feof(pb))
         return AVERROR_EOF;
@@ -125,6 +125,7 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
         return AVERROR_INVALIDDATA;
     }
 
+    format       = cdxl->header[1] & 0xE0;
     current_size = AV_RB32(&cdxl->header[2]);
     width        = AV_RB16(&cdxl->header[14]);
     height       = AV_RB16(&cdxl->header[16]);
@@ -132,7 +133,10 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
     audio_size   = AV_RB16(&cdxl->header[22]);
     if (FFALIGN(width, 16) * (uint64_t)height * cdxl->header[19] > INT_MAX)
         return AVERROR_INVALIDDATA;
-    image_size   = FFALIGN(width, 16) * height * cdxl->header[19] / 8;
+    if (format == 0x20)
+        image_size = width * height * cdxl->header[19] / 8;
+    else
+        image_size = FFALIGN(width, 16) * height * cdxl->header[19] / 8;
     video_size   = palette_size + image_size;
 
     if (palette_size > 512)
@@ -146,17 +150,17 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
             if (!st)
                 return AVERROR(ENOMEM);
 
-            st->codec->codec_type    = AVMEDIA_TYPE_AUDIO;
-            st->codec->codec_tag     = 0;
-            st->codec->codec_id      = AV_CODEC_ID_PCM_S8;
+            st->codecpar->codec_type    = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_tag     = 0;
+            st->codecpar->codec_id      = AV_CODEC_ID_PCM_S8;
             if (cdxl->header[1] & 0x10) {
-                st->codec->channels       = 2;
-                st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+                st->codecpar->channels       = 2;
+                st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
             } else {
-                st->codec->channels       = 1;
-                st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+                st->codecpar->channels       = 1;
+                st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
             }
-            st->codec->sample_rate   = cdxl->sample_rate;
+            st->codecpar->sample_rate   = cdxl->sample_rate;
             st->start_time           = 0;
             cdxl->audio_stream_index = st->index;
             avpriv_set_pts_info(st, 64, 1, cdxl->sample_rate);
@@ -175,11 +179,11 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt)
             if (!st)
                 return AVERROR(ENOMEM);
 
-            st->codec->codec_type    = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_tag     = 0;
-            st->codec->codec_id      = AV_CODEC_ID_CDXL;
-            st->codec->width         = width;
-            st->codec->height        = height;
+            st->codecpar->codec_type    = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_tag     = 0;
+            st->codecpar->codec_id      = AV_CODEC_ID_CDXL;
+            st->codecpar->width         = width;
+            st->codecpar->height        = height;
 
             if (audio_size + video_size && cdxl->filesize > 0) {
                 frames = cdxl->filesize / (audio_size + video_size);
diff --git a/libavformat/chromaprint.c b/libavformat/chromaprint.c
index 4d67f43..8c9a6c0 100644
--- a/libavformat/chromaprint.c
+++ b/libavformat/chromaprint.c
@@ -85,17 +85,17 @@ static int write_header(AVFormatContext *s)
 
     st = s->streams[0];
 
-    if (st->codec->channels > 2) {
+    if (st->codecpar->channels > 2) {
         av_log(s, AV_LOG_ERROR, "Only up to 2 channels are supported\n");
         goto fail;
     }
 
-    if (st->codec->sample_rate < 1000) {
+    if (st->codecpar->sample_rate < 1000) {
         av_log(s, AV_LOG_ERROR, "Sampling rate must be at least 1000\n");
         goto fail;
     }
 
-    if (!chromaprint_start(cpr->ctx, st->codec->sample_rate, st->codec->channels)) {
+    if (!chromaprint_start(cpr->ctx, st->codecpar->sample_rate, st->codecpar->channels)) {
         av_log(s, AV_LOG_ERROR, "Failed to start chromaprint\n");
         goto fail;
     }
diff --git a/libavformat/cinedec.c b/libavformat/cinedec.c
index 3184084..0efedda 100644
--- a/libavformat/cinedec.c
+++ b/libavformat/cinedec.c
@@ -101,9 +101,9 @@ static int cine_read_header(AVFormatContext *avctx)
     st = avformat_new_stream(avctx, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
-    st->codec->codec_tag  = 0;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->codec_tag  = 0;
 
     /* CINEFILEHEADER structure */
     avio_skip(pb, 4); // Type, Headersize
@@ -127,8 +127,8 @@ static int cine_read_header(AVFormatContext *avctx)
     /* BITMAPINFOHEADER structure */
     avio_seek(pb, offImageHeader, SEEK_SET);
     avio_skip(pb, 4); //biSize
-    st->codec->width      = avio_rl32(pb);
-    st->codec->height     = avio_rl32(pb);
+    st->codecpar->width      = avio_rl32(pb);
+    st->codecpar->height     = avio_rl32(pb);
 
     if (avio_rl16(pb) != 1) // biPlanes
         return AVERROR_INVALIDDATA;
@@ -144,7 +144,7 @@ static int cine_read_header(AVFormatContext *avctx)
         vflip = 0;
         break;
     case 0x100: /* BI_PACKED */
-        st->codec->codec_tag = MKTAG('B', 'I', 'T', 0);
+        st->codecpar->codec_tag = MKTAG('B', 'I', 'T', 0);
         vflip = 1;
         break;
     default:
@@ -167,8 +167,8 @@ static int cine_read_header(AVFormatContext *avctx)
 
     avio_skip(pb, 616); // Binning .. bFlipH
     if (!avio_rl32(pb) ^ vflip) {
-        st->codec->extradata  = av_strdup("BottomUp");
-        st->codec->extradata_size  = 9;
+        st->codecpar->extradata  = av_strdup("BottomUp");
+        st->codecpar->extradata_size  = 9;
     }
 
     avio_skip(pb, 4); // Grid
@@ -193,17 +193,17 @@ static int cine_read_header(AVFormatContext *avctx)
     set_metadata_float(&st->metadata, "wbgain[0].b", av_int2float(avio_rl32(pb)), 1);
     avio_skip(pb, 36); // WBGain[1].. WBView
 
-    st->codec->bits_per_coded_sample = avio_rl32(pb);
+    st->codecpar->bits_per_coded_sample = avio_rl32(pb);
 
     if (compression == CC_RGB) {
         if (biBitCount == 8) {
-            st->codec->pix_fmt = AV_PIX_FMT_GRAY8;
+            st->codecpar->format = AV_PIX_FMT_GRAY8;
         } else if (biBitCount == 16) {
-            st->codec->pix_fmt = AV_PIX_FMT_GRAY16LE;
+            st->codecpar->format = AV_PIX_FMT_GRAY16LE;
         } else if (biBitCount == 24) {
-            st->codec->pix_fmt = AV_PIX_FMT_BGR24;
+            st->codecpar->format = AV_PIX_FMT_BGR24;
         } else if (biBitCount == 48) {
-            st->codec->pix_fmt = AV_PIX_FMT_BGR48LE;
+            st->codecpar->format = AV_PIX_FMT_BGR48LE;
         } else {
             avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
             return AVERROR_INVALIDDATA;
@@ -212,9 +212,9 @@ static int cine_read_header(AVFormatContext *avctx)
         switch (CFA & 0xFFFFFF) {
         case CFA_BAYER:
             if (biBitCount == 8) {
-                st->codec->pix_fmt = AV_PIX_FMT_BAYER_GBRG8;
+                st->codecpar->format = AV_PIX_FMT_BAYER_GBRG8;
             } else if (biBitCount == 16) {
-                st->codec->pix_fmt = AV_PIX_FMT_BAYER_GBRG16LE;
+                st->codecpar->format = AV_PIX_FMT_BAYER_GBRG16LE;
             } else {
                 avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
                 return AVERROR_INVALIDDATA;
@@ -222,9 +222,9 @@ static int cine_read_header(AVFormatContext *avctx)
             break;
         case CFA_BAYERFLIP:
             if (biBitCount == 8) {
-                st->codec->pix_fmt = AV_PIX_FMT_BAYER_RGGB8;
+                st->codecpar->format = AV_PIX_FMT_BAYER_RGGB8;
             } else if (biBitCount == 16) {
-                st->codec->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE;
+                st->codecpar->format = AV_PIX_FMT_BAYER_RGGB16LE;
             } else {
                 avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
                 return AVERROR_INVALIDDATA;
diff --git a/libavformat/concat.c b/libavformat/concat.c
index 7a8eb1b..46b520f 100644
--- a/libavformat/concat.c
+++ b/libavformat/concat.c
@@ -98,7 +98,7 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags)
 
         /* creating URLContext */
         err = ffurl_open_whitelist(&uc, node_uri, flags,
-                                   &h->interrupt_callback, NULL, h->protocol_whitelist);
+                                   &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h);
         if (err < 0)
             break;
 
@@ -186,7 +186,7 @@ static int64_t concat_seek(URLContext *h, int64_t pos, int whence)
     return result;
 }
 
-URLProtocol ff_concat_protocol = {
+const URLProtocol ff_concat_protocol = {
     .name           = "concat",
     .url_open       = concat_open,
     .url_read       = concat_read,
diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
index de7b89a..b3a430e 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -35,6 +35,7 @@ typedef enum ConcatMatchMode {
 
 typedef struct ConcatStream {
     AVBitStreamFilterContext *bsf;
+    AVCodecContext *avctx;
     int out_stream_index;
 } ConcatStream;
 
@@ -164,18 +165,22 @@ static int copy_stream_props(AVStream *st, AVStream *source_st)
 {
     int ret;
 
-    if (st->codec->codec_id || !source_st->codec->codec_id) {
-        if (st->codec->extradata_size < source_st->codec->extradata_size) {
-            ret = ff_alloc_extradata(st->codec,
-                                     source_st->codec->extradata_size);
+    if (st->codecpar->codec_id || !source_st->codecpar->codec_id) {
+        if (st->codecpar->extradata_size < source_st->codecpar->extradata_size) {
+            if (st->codecpar->extradata) {
+                av_freep(&st->codecpar->extradata);
+                st->codecpar->extradata_size = 0;
+            }
+            ret = ff_alloc_extradata(st->codecpar,
+                                     source_st->codecpar->extradata_size);
             if (ret < 0)
                 return ret;
         }
-        memcpy(st->codec->extradata, source_st->codec->extradata,
-               source_st->codec->extradata_size);
+        memcpy(st->codecpar->extradata, source_st->codecpar->extradata,
+               source_st->codecpar->extradata_size);
         return 0;
     }
-    if ((ret = avcodec_copy_context(st->codec, source_st->codec)) < 0)
+    if ((ret = avcodec_parameters_copy(st->codecpar, source_st->codecpar)) < 0)
         return ret;
     st->r_frame_rate        = source_st->r_frame_rate;
     st->avg_frame_rate      = source_st->avg_frame_rate;
@@ -192,9 +197,10 @@ static int detect_stream_specific(AVFormatContext *avf, int idx)
     AVStream *st = cat->avf->streams[idx];
     ConcatStream *cs = &cat->cur_file->streams[idx];
     AVBitStreamFilterContext *bsf;
+    int ret;
 
-    if (cat->auto_convert && st->codec->codec_id == AV_CODEC_ID_H264 &&
-        (st->codec->extradata_size < 4 || AV_RB32(st->codec->extradata) != 1)) {
+    if (cat->auto_convert && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
+        (st->codecpar->extradata_size < 4 || AV_RB32(st->codecpar->extradata) != 1)) {
         av_log(cat->avf, AV_LOG_INFO,
                "Auto-inserting h264_mp4toannexb bitstream filter\n");
         if (!(bsf = av_bitstream_filter_init("h264_mp4toannexb"))) {
@@ -203,6 +209,23 @@ static int detect_stream_specific(AVFormatContext *avf, int idx)
             return AVERROR_BSF_NOT_FOUND;
         }
         cs->bsf = bsf;
+
+        cs->avctx = avcodec_alloc_context3(NULL);
+        if (!cs->avctx)
+            return AVERROR(ENOMEM);
+
+        /* This really should be part of the bsf work.
+           Note: input bitstream filtering will not work with bsf that
+           create extradata from the first packet. */
+        av_freep(&st->codecpar->extradata);
+        st->codecpar->extradata_size = 0;
+
+        ret = avcodec_parameters_to_context(cs->avctx, st->codecpar);
+        if (ret < 0) {
+            avcodec_free_context(&cs->avctx);
+            return ret;
+        }
+
     }
     return 0;
 }
@@ -301,7 +324,7 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
 
     cat->avf->interrupt_callback = avf->interrupt_callback;
 
-    if ((ret = ff_copy_whitelists(cat->avf, avf)) < 0)
+    if ((ret = ff_copy_whiteblacklists(cat->avf, avf)) < 0)
         return ret;
 
     if ((ret = avformat_open_input(&cat->avf, file->url, NULL, NULL)) < 0 ||
@@ -338,15 +361,21 @@ static int open_file(AVFormatContext *avf, unsigned fileno)
 static int concat_read_close(AVFormatContext *avf)
 {
     ConcatContext *cat = avf->priv_data;
-    unsigned i;
+    unsigned i, j;
 
-    if (cat->avf)
-        avformat_close_input(&cat->avf);
     for (i = 0; i < cat->nb_files; i++) {
         av_freep(&cat->files[i].url);
+        for (j = 0; j < cat->files[i].nb_streams; j++) {
+            if (cat->files[i].streams[j].avctx)
+                avcodec_free_context(&cat->files[i].streams[j].avctx);
+            if (cat->files[i].streams[j].bsf)
+                av_bitstream_filter_close(cat->files[i].streams[j].bsf);
+        }
         av_freep(&cat->files[i].streams);
         av_dict_free(&cat->files[i].metadata);
     }
+    if (cat->avf)
+        avformat_close_input(&cat->avf);
     av_freep(&cat->files);
     return 0;
 }
@@ -499,7 +528,8 @@ static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
     av_assert0(cs->out_stream_index >= 0);
     for (bsf = cs->bsf; bsf; bsf = bsf->next) {
         pkt2 = *pkt;
-        ret = av_bitstream_filter_filter(bsf, st->codec, NULL,
+
+        ret = av_bitstream_filter_filter(bsf, cs->avctx, NULL,
                                          &pkt2.data, &pkt2.size,
                                          pkt->data, pkt->size,
                                          !!(pkt->flags & AV_PKT_FLAG_KEY));
@@ -507,6 +537,21 @@ static int filter_packet(AVFormatContext *avf, ConcatStream *cs, AVPacket *pkt)
             av_packet_unref(pkt);
             return ret;
         }
+
+        if (cs->avctx->extradata_size > st->codecpar->extradata_size) {
+            int eret;
+            if (st->codecpar->extradata)
+                av_freep(&st->codecpar->extradata);
+
+            eret = ff_alloc_extradata(st->codecpar, cs->avctx->extradata_size);
+            if (eret < 0) {
+                av_packet_unref(pkt);
+                return AVERROR(ENOMEM);
+            }
+            st->codecpar->extradata_size = cs->avctx->extradata_size;
+            memcpy(st->codecpar->extradata, cs->avctx->extradata, cs->avctx->extradata_size);
+        }
+
         av_assert0(pkt2.buf);
         if (ret == 0 && pkt2.data != pkt->data) {
             if ((ret = av_copy_packet(&pkt2, pkt)) < 0) {
diff --git a/libavformat/crypto.c b/libavformat/crypto.c
index b1871fe..2999f50 100644
--- a/libavformat/crypto.c
+++ b/libavformat/crypto.c
@@ -138,7 +138,7 @@ static int crypto_open2(URLContext *h, const char *uri, int flags, AVDictionary
 
     if ((ret = ffurl_open_whitelist(&c->hd, nested_url, flags,
                                     &h->interrupt_callback, options,
-                                    h->protocol_whitelist)) < 0) {
+                                    h->protocol_whitelist, h->protocol_blacklist, h)) < 0) {
         av_log(h, AV_LOG_ERROR, "Unable to open resource: %s\n", nested_url);
         goto err;
     }
@@ -284,7 +284,7 @@ static int crypto_close(URLContext *h)
     return 0;
 }
 
-URLProtocol ff_crypto_protocol = {
+const URLProtocol ff_crypto_protocol = {
     .name            = "crypto",
     .url_open2       = crypto_open2,
     .url_read        = crypto_read,
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 1dd1a9d..519f9c4 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -63,7 +63,7 @@ typedef struct OutputStream {
     AVFormatContext *ctx;
     int ctx_inited;
     uint8_t iobuf[32768];
-    URLContext *out;
+    AVIOContext *out;
     int packets_written;
     char initfile[1024];
     int64_t init_start_pos;
@@ -104,24 +104,24 @@ static int dash_write(void *opaque, uint8_t *buf, int buf_size)
 {
     OutputStream *os = opaque;
     if (os->out)
-        ffurl_write(os->out, buf, buf_size);
+        avio_write(os->out, buf, buf_size);
     return buf_size;
 }
 
 // RFC 6381
-static void set_codec_str(AVFormatContext *s, AVCodecContext *codec,
+static void set_codec_str(AVFormatContext *s, AVCodecParameters *par,
                           char *str, int size)
 {
     const AVCodecTag *tags[2] = { NULL, NULL };
     uint32_t tag;
-    if (codec->codec_type == AVMEDIA_TYPE_VIDEO)
+    if (par->codec_type == AVMEDIA_TYPE_VIDEO)
         tags[0] = ff_codec_movvideo_tags;
-    else if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
+    else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
         tags[0] = ff_codec_movaudio_tags;
     else
         return;
 
-    tag = av_codec_get_tag(tags, codec->codec_id);
+    tag = av_codec_get_tag(tags, par->codec_id);
     if (!tag)
         return;
     if (size < 5)
@@ -132,17 +132,17 @@ static void set_codec_str(AVFormatContext *s, AVCodecContext *codec,
     if (!strcmp(str, "mp4a") || !strcmp(str, "mp4v")) {
         uint32_t oti;
         tags[0] = ff_mp4_obj_type;
-        oti = av_codec_get_tag(tags, codec->codec_id);
+        oti = av_codec_get_tag(tags, par->codec_id);
         if (oti)
             av_strlcatf(str, size, ".%02x", oti);
         else
             return;
 
         if (tag == MKTAG('m', 'p', '4', 'a')) {
-            if (codec->extradata_size >= 2) {
-                int aot = codec->extradata[0] >> 3;
+            if (par->extradata_size >= 2) {
+                int aot = par->extradata[0] >> 3;
                 if (aot == 31)
-                    aot = ((AV_RB16(codec->extradata) >> 5) & 0x3f) + 32;
+                    aot = ((AV_RB16(par->extradata) >> 5) & 0x3f) + 32;
                 av_strlcatf(str, size, ".%d", aot);
             }
         } else if (tag == MKTAG('m', 'p', '4', 'v')) {
@@ -151,8 +151,8 @@ static void set_codec_str(AVFormatContext *s, AVCodecContext *codec,
         }
     } else if (!strcmp(str, "avc1")) {
         uint8_t *tmpbuf = NULL;
-        uint8_t *extradata = codec->extradata;
-        int extradata_size = codec->extradata_size;
+        uint8_t *extradata = par->extradata;
+        int extradata_size = par->extradata_size;
         if (!extradata_size)
             return;
         if (extradata[0] != 1) {
@@ -186,8 +186,7 @@ static void dash_free(AVFormatContext *s)
             av_write_trailer(os->ctx);
         if (os->ctx && os->ctx->pb)
             av_free(os->ctx->pb);
-        ffurl_close(os->out);
-        os->out =  NULL;
+        ff_format_io_close(s, &os->out);
         if (os->ctx)
             avformat_free_context(os->ctx);
         for (j = 0; j < os->nb_segments; j++)
@@ -516,10 +515,10 @@ static int write_manifest(AVFormatContext *s, int final)
             AVStream *st = s->streams[i];
             OutputStream *os = &c->streams[i];
 
-            if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO)
+            if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
                 continue;
 
-            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/mp4\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"", i, os->codec_str, os->bandwidth_str, st->codec->width, st->codec->height);
+            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/mp4\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"", i, os->codec_str, os->bandwidth_str, st->codecpar->width, st->codecpar->height);
             if (st->avg_frame_rate.num)
                 avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
             avio_printf(out, ">\n");
@@ -535,11 +534,11 @@ static int write_manifest(AVFormatContext *s, int final)
             AVStream *st = s->streams[i];
             OutputStream *os = &c->streams[i];
 
-            if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+            if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
                 continue;
 
-            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/mp4\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n", i, os->codec_str, os->bandwidth_str, st->codec->sample_rate);
-            avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n", st->codec->channels);
+            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/mp4\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n", i, os->codec_str, os->bandwidth_str, st->codecpar->sample_rate);
+            avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n", st->codecpar->channels);
             output_segment_list(&c->streams[i], out, c);
             avio_printf(out, "\t\t\t</Representation>\n");
         }
@@ -549,7 +548,7 @@ static int write_manifest(AVFormatContext *s, int final)
     avio_printf(out, "</MPD>\n");
     avio_flush(out);
     ff_format_io_close(s, &out);
-    return ff_rename(temp_filename, s->filename, s);
+    return avpriv_io_move(temp_filename, s->filename);
 }
 
 static int dash_write_header(AVFormatContext *s)
@@ -599,9 +598,7 @@ static int dash_write_header(AVFormatContext *s)
         AVDictionary *opts = NULL;
         char filename[1024];
 
-        os->bit_rate = s->streams[i]->codec->bit_rate ?
-                       s->streams[i]->codec->bit_rate :
-                       s->streams[i]->codec->rc_max_rate;
+        os->bit_rate = s->streams[i]->codecpar->bit_rate;
         if (os->bit_rate) {
             snprintf(os->bandwidth_str, sizeof(os->bandwidth_str),
                      " bandwidth=\"%d\"", os->bit_rate);
@@ -631,10 +628,11 @@ static int dash_write_header(AVFormatContext *s)
             ret = AVERROR(ENOMEM);
             goto fail;
         }
-        avcodec_copy_context(st->codec, s->streams[i]->codec);
+        avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
         st->time_base = s->streams[i]->time_base;
         ctx->avoid_negative_ts = s->avoid_negative_ts;
+        ctx->flags = s->flags;
 
         ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, dash_write, NULL);
         if (!ctx->pb) {
@@ -651,7 +649,7 @@ static int dash_write_header(AVFormatContext *s)
             dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0);
         }
         snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
-        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
+        ret = s->io_open(s, &os->out, filename, AVIO_FLAG_WRITE, NULL);
         if (ret < 0)
             goto fail;
         os->init_start_pos = 0;
@@ -671,7 +669,7 @@ static int dash_write_header(AVFormatContext *s)
         // already before being handed to this muxer, so we don't have mismatches
         // between the MPD and the actual segments.
         s->avoid_negative_ts = ctx->avoid_negative_ts;
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
             if (avg_frame_rate.num > 0) {
                 if (av_cmp_q(avg_frame_rate, c->min_frame_rate) < 0)
@@ -682,11 +680,11 @@ static int dash_write_header(AVFormatContext *s)
                 c->ambiguous_frame_rate = 1;
             }
             c->has_video = 1;
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             c->has_audio = 1;
         }
 
-        set_codec_str(s, st->codec, os->codec_str, sizeof(os->codec_str));
+        set_codec_str(s, st->codecpar, os->codec_str, sizeof(os->codec_str));
         os->first_pts = AV_NOPTS_VALUE;
         os->max_pts = AV_NOPTS_VALUE;
         os->last_dts = AV_NOPTS_VALUE;
@@ -755,18 +753,18 @@ static void find_index_range(AVFormatContext *s, const char *full_path,
                              int64_t pos, int *index_length)
 {
     uint8_t buf[8];
-    URLContext *fd;
+    AVIOContext *pb;
     int ret;
 
-    ret = ffurl_open_whitelist(&fd, full_path, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist);
+    ret = s->io_open(s, &pb, full_path, AVIO_FLAG_READ, NULL);
     if (ret < 0)
         return;
-    if (ffurl_seek(fd, pos, SEEK_SET) != pos) {
-        ffurl_close(fd);
+    if (avio_seek(pb, pos, SEEK_SET) != pos) {
+        ff_format_io_close(s, &pb);
         return;
     }
-    ret = ffurl_read(fd, buf, 8);
-    ffurl_close(fd);
+    ret = avio_read(pb, buf, 8);
+    ff_format_io_close(s, &pb);
     if (ret < 8)
         return;
     if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
@@ -775,24 +773,24 @@ static void find_index_range(AVFormatContext *s, const char *full_path,
 }
 
 static int update_stream_extradata(AVFormatContext *s, OutputStream *os,
-                                   AVCodecContext *codec)
+                                   AVCodecParameters *par)
 {
     uint8_t *extradata;
 
-    if (os->ctx->streams[0]->codec->extradata_size || !codec->extradata_size)
+    if (os->ctx->streams[0]->codecpar->extradata_size || !par->extradata_size)
         return 0;
 
-    extradata = av_malloc(codec->extradata_size);
+    extradata = av_malloc(par->extradata_size);
 
     if (!extradata)
         return AVERROR(ENOMEM);
 
-    memcpy(extradata, codec->extradata, codec->extradata_size);
+    memcpy(extradata, par->extradata, par->extradata_size);
 
-    os->ctx->streams[0]->codec->extradata = extradata;
-    os->ctx->streams[0]->codec->extradata_size = codec->extradata_size;
+    os->ctx->streams[0]->codecpar->extradata = extradata;
+    os->ctx->streams[0]->codecpar->extradata_size = par->extradata_size;
 
-    set_codec_str(s, codec, os->codec_str, sizeof(os->codec_str));
+    set_codec_str(s, par, os->codec_str, sizeof(os->codec_str));
 
     return 0;
 }
@@ -818,7 +816,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
         // Flush all audio streams as well, in sync with video keyframes,
         // but not the other video streams.
         if (stream >= 0 && i != stream) {
-            if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+            if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
                 continue;
             // Make sure we don't flush audio streams multiple times, when
             // all video streams are flushed one at a time.
@@ -829,10 +827,8 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
         if (!os->init_range_length) {
             av_write_frame(os->ctx, NULL);
             os->init_range_length = avio_tell(os->ctx->pb);
-            if (!c->single_file) {
-                ffurl_close(os->out);
-                os->out = NULL;
-            }
+            if (!c->single_file)
+                ff_format_io_close(s, &os->out);
         }
 
         start_pos = avio_tell(os->ctx->pb);
@@ -841,7 +837,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
             dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_pts);
             snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);
             snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path);
-            ret = ffurl_open_whitelist(&os->out, temp_path, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
+            ret = s->io_open(s, &os->out, temp_path, AVIO_FLAG_WRITE, NULL);
             if (ret < 0)
                 break;
             write_styp(os->ctx->pb);
@@ -857,9 +853,8 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
         if (c->single_file) {
             find_index_range(s, full_path, start_pos, &index_length);
         } else {
-            ffurl_close(os->out);
-            os->out = NULL;
-            ret = ff_rename(temp_path, full_path, s);
+            ff_format_io_close(s, &os->out);
+            ret = avpriv_io_move(temp_path, full_path);
             if (ret < 0)
                 break;
         }
@@ -900,7 +895,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
     int64_t seg_end_duration = (os->segment_index) * (int64_t) c->min_seg_duration;
     int ret;
 
-    ret = update_stream_extradata(s, os, st->codec);
+    ret = update_stream_extradata(s, os, st->codecpar);
     if (ret < 0)
         return ret;
 
@@ -925,7 +920,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
     if (os->first_pts == AV_NOPTS_VALUE)
         os->first_pts = pkt->pts;
 
-    if ((!c->has_video || st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
+    if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
         pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
         av_compare_ts(pkt->pts - os->first_pts, st->time_base,
                       seg_end_duration, AV_TIME_BASE_Q) >= 0) {
diff --git a/libavformat/data_uri.c b/libavformat/data_uri.c
index 1598b99..1863830 100644
--- a/libavformat/data_uri.c
+++ b/libavformat/data_uri.c
@@ -109,7 +109,7 @@ static int data_read(URLContext *h, unsigned char *buf, int size)
     return size;
 }
 
-URLProtocol ff_data_protocol = {
+const URLProtocol ff_data_protocol = {
     .name           = "data",
     .url_open       = data_open,
     .url_close      = data_close,
diff --git a/libavformat/dauddec.c b/libavformat/dauddec.c
index f6e7491..69196b0 100644
--- a/libavformat/dauddec.c
+++ b/libavformat/dauddec.c
@@ -26,15 +26,15 @@ static int daud_header(AVFormatContext *s) {
     AVStream *st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_PCM_S24DAUD;
-    st->codec->codec_tag = MKTAG('d', 'a', 'u', 'd');
-    st->codec->channels = 6;
-    st->codec->channel_layout = AV_CH_LAYOUT_5POINT1;
-    st->codec->sample_rate = 96000;
-    st->codec->bit_rate = 3 * 6 * 96000 * 8;
-    st->codec->block_align = 3 * 6;
-    st->codec->bits_per_coded_sample = 24;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_PCM_S24DAUD;
+    st->codecpar->codec_tag = MKTAG('d', 'a', 'u', 'd');
+    st->codecpar->channels = 6;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_5POINT1;
+    st->codecpar->sample_rate = 96000;
+    st->codecpar->bit_rate = 3 * 6 * 96000 * 8;
+    st->codecpar->block_align = 3 * 6;
+    st->codecpar->bits_per_coded_sample = 24;
     return 0;
 }
 
diff --git a/libavformat/daudenc.c b/libavformat/daudenc.c
index 99b18d3..15a5afd 100644
--- a/libavformat/daudenc.c
+++ b/libavformat/daudenc.c
@@ -23,8 +23,8 @@
 
 static int daud_write_header(struct AVFormatContext *s)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
-    if (codec->channels!=6 || codec->sample_rate!=96000)
+    AVCodecParameters *par = s->streams[0]->codecpar;
+    if (par->channels!=6 || par->sample_rate!=96000)
         return -1;
     return 0;
 }
diff --git a/libavformat/dcstr.c b/libavformat/dcstr.c
index 2ae61de..69fae41 100644
--- a/libavformat/dcstr.c
+++ b/libavformat/dcstr.c
@@ -39,35 +39,35 @@ static int dcstr_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->channels    = avio_rl32(s->pb);
-    st->codec->sample_rate = avio_rl32(s->pb);
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channels    = avio_rl32(s->pb);
+    st->codecpar->sample_rate = avio_rl32(s->pb);
     codec                  = avio_rl32(s->pb);
     align                  = avio_rl32(s->pb);
     avio_skip(s->pb, 4);
     st->duration           = avio_rl32(s->pb);
-    st->codec->channels   *= avio_rl32(s->pb);
-    if (!align || align > INT_MAX / st->codec->channels)
+    st->codecpar->channels   *= avio_rl32(s->pb);
+    if (!align || align > INT_MAX / st->codecpar->channels)
         return AVERROR_INVALIDDATA;
-    st->codec->block_align = align * st->codec->channels;
+    st->codecpar->block_align = align * st->codecpar->channels;
 
     switch (codec) {
-    case  4: st->codec->codec_id = AV_CODEC_ID_ADPCM_AICA;       break;
-    case 16: st->codec->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR; break;
+    case  4: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_AICA;       break;
+    case 16: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR; break;
     default: avpriv_request_sample(s, "codec %X", codec);
              return AVERROR_PATCHWELCOME;
     }
 
     avio_skip(s->pb, 0x800 - avio_tell(s->pb));
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
 
 static int dcstr_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
-    return av_get_packet(s->pb, pkt, codec->block_align);
+    AVCodecParameters *par    = s->streams[0]->codecpar;
+    return av_get_packet(s->pb, pkt, par->block_align);
 }
 
 AVInputFormat ff_dcstr_demuxer = {
diff --git a/libavformat/dfa.c b/libavformat/dfa.c
index b16672c..9858ee7 100644
--- a/libavformat/dfa.c
+++ b/libavformat/dfa.c
@@ -56,10 +56,10 @@ static int dfa_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_DFA;
-    st->codec->width      = avio_rl16(pb);
-    st->codec->height     = avio_rl16(pb);
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_DFA;
+    st->codecpar->width      = avio_rl16(pb);
+    st->codecpar->height     = avio_rl16(pb);
     mspf = avio_rl32(pb);
     if (!mspf) {
         av_log(s, AV_LOG_WARNING, "Zero FPS reported, defaulting to 10\n");
@@ -69,9 +69,9 @@ static int dfa_read_header(AVFormatContext *s)
     avio_skip(pb, 128 - 16); // padding
     st->duration = frames;
 
-    if (ff_alloc_extradata(st->codec, 2))
+    if (ff_alloc_extradata(st->codecpar, 2))
         return AVERROR(ENOMEM);
-    AV_WL16(st->codec->extradata, version);
+    AV_WL16(st->codecpar->extradata, version);
     if (version == 0x100)
         st->sample_aspect_ratio = (AVRational){2, 1};
 
diff --git a/libavformat/dsfdec.c b/libavformat/dsfdec.c
index ae198b2..f16b397 100644
--- a/libavformat/dsfdec.c
+++ b/libavformat/dsfdec.c
@@ -99,29 +99,33 @@ static int dsf_read_header(AVFormatContext *s)
 
     channel_type = avio_rl32(pb);
     if (channel_type < FF_ARRAY_ELEMS(dsf_channel_layout))
-        st->codec->channel_layout = dsf_channel_layout[channel_type];
-    if (!st->codec->channel_layout)
+        st->codecpar->channel_layout = dsf_channel_layout[channel_type];
+    if (!st->codecpar->channel_layout)
         avpriv_request_sample(s, "channel type %i", channel_type);
 
-    st->codec->codec_type   = AVMEDIA_TYPE_AUDIO;
-    st->codec->channels     = avio_rl32(pb);
-    st->codec->sample_rate  = avio_rl32(pb) / 8;
+    st->codecpar->codec_type   = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channels     = avio_rl32(pb);
+    st->codecpar->sample_rate  = avio_rl32(pb) / 8;
+
+    if (st->codecpar->channels <= 0)
+        return AVERROR_INVALIDDATA;
 
     switch(avio_rl32(pb)) {
-    case 1: st->codec->codec_id = AV_CODEC_ID_DSD_LSBF_PLANAR; break;
-    case 8: st->codec->codec_id = AV_CODEC_ID_DSD_MSBF_PLANAR; break;
+    case 1: st->codecpar->codec_id = AV_CODEC_ID_DSD_LSBF_PLANAR; break;
+    case 8: st->codecpar->codec_id = AV_CODEC_ID_DSD_MSBF_PLANAR; break;
     default:
         avpriv_request_sample(s, "unknown most significant bit");
         return AVERROR_INVALIDDATA;
     }
 
     avio_skip(pb, 8);
-    st->codec->block_align = avio_rl32(pb);
-    if (st->codec->block_align > INT_MAX / st->codec->channels) {
+    st->codecpar->block_align = avio_rl32(pb);
+    if (st->codecpar->block_align > INT_MAX / st->codecpar->channels) {
         avpriv_request_sample(s, "block_align overflow");
         return AVERROR_INVALIDDATA;
     }
-    st->codec->block_align *= st->codec->channels;
+    st->codecpar->block_align *= st->codecpar->channels;
+    st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * 8LL;
     avio_skip(pb, 4);
 
     /* data chunk */
@@ -145,7 +149,7 @@ static int dsf_read_packet(AVFormatContext *s, AVPacket *pkt)
         return AVERROR_EOF;
 
     pkt->stream_index = 0;
-    return av_get_packet(pb, pkt, FFMIN(dsf->data_end - pos, st->codec->block_align));
+    return av_get_packet(pb, pkt, FFMIN(dsf->data_end - pos, st->codecpar->block_align));
 }
 
 AVInputFormat ff_dsf_demuxer = {
diff --git a/libavformat/dsicin.c b/libavformat/dsicin.c
index 6ba8c28..bd4f3ad 100644
--- a/libavformat/dsicin.c
+++ b/libavformat/dsicin.c
@@ -116,11 +116,11 @@ static int cin_read_header(AVFormatContext *s)
 
     avpriv_set_pts_info(st, 32, 1, 12);
     cin->video_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_DSICINVIDEO;
-    st->codec->codec_tag = 0;  /* no fourcc */
-    st->codec->width = hdr->video_frame_width;
-    st->codec->height = hdr->video_frame_height;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_DSICINVIDEO;
+    st->codecpar->codec_tag = 0;  /* no fourcc */
+    st->codecpar->width = hdr->video_frame_width;
+    st->codecpar->height = hdr->video_frame_height;
 
     /* initialize the audio decoder stream */
     st = avformat_new_stream(s, NULL);
@@ -129,14 +129,14 @@ static int cin_read_header(AVFormatContext *s)
 
     avpriv_set_pts_info(st, 32, 1, 22050);
     cin->audio_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_DSICINAUDIO;
-    st->codec->codec_tag = 0;  /* no tag */
-    st->codec->channels = 1;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    st->codec->sample_rate = 22050;
-    st->codec->bits_per_coded_sample = 8;
-    st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample * st->codec->channels;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_DSICINAUDIO;
+    st->codecpar->codec_tag = 0;  /* no tag */
+    st->codecpar->channels = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->sample_rate = 22050;
+    st->codecpar->bits_per_coded_sample = 8;
+    st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->channels;
 
     return 0;
 }
diff --git a/libavformat/dss.c b/libavformat/dss.c
index bf7a1a4..2f7f20d 100644
--- a/libavformat/dss.c
+++ b/libavformat/dss.c
@@ -144,22 +144,22 @@ static int dss_read_header(AVFormatContext *s)
     ctx->audio_codec = avio_r8(pb);
 
     if (ctx->audio_codec == DSS_ACODEC_DSS_SP) {
-        st->codec->codec_id    = AV_CODEC_ID_DSS_SP;
-        st->codec->sample_rate = 11025;
+        st->codecpar->codec_id    = AV_CODEC_ID_DSS_SP;
+        st->codecpar->sample_rate = 11025;
     } else if (ctx->audio_codec == DSS_ACODEC_G723_1) {
-        st->codec->codec_id    = AV_CODEC_ID_G723_1;
-        st->codec->sample_rate = 8000;
+        st->codecpar->codec_id    = AV_CODEC_ID_G723_1;
+        st->codecpar->sample_rate = 8000;
     } else {
         avpriv_request_sample(s, "Support for codec %x in DSS",
                               ctx->audio_codec);
         return AVERROR_PATCHWELCOME;
     }
 
-    st->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    st->codec->channels       = 1;
+    st->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->channels       = 1;
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     st->start_time = 0;
 
     /* Jump over header */
@@ -235,7 +235,7 @@ static int dss_sp_read_packet(AVFormatContext *s, AVPacket *pkt)
     pkt->duration     = 264;
     pkt->pos = pos;
     pkt->stream_index = 0;
-    s->bit_rate = 8LL * ctx->packet_size * st->codec->sample_rate * 512 / (506 * pkt->duration);
+    s->bit_rate = 8LL * ctx->packet_size * st->codecpar->sample_rate * 512 / (506 * pkt->duration);
 
     if (ctx->counter < 0) {
         int size2 = ctx->counter + read_size;
@@ -299,7 +299,7 @@ static int dss_723_1_read_packet(AVFormatContext *s, AVPacket *pkt)
     pkt->data[0]  = byte;
     offset        = 1;
     pkt->duration = 240;
-    s->bit_rate = 8LL * size * st->codec->sample_rate * 512 / (506 * pkt->duration);
+    s->bit_rate = 8LL * size * st->codecpar->sample_rate * 512 / (506 * pkt->duration);
 
     pkt->stream_index = 0;
 
diff --git a/libavformat/dtsdec.c b/libavformat/dtsdec.c
index ef28391..8c985b8 100644
--- a/libavformat/dtsdec.c
+++ b/libavformat/dtsdec.c
@@ -19,6 +19,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/crc.h"
+
 #include "libavcodec/bytestream.h"
 #include "libavcodec/dca.h"
 #include "libavcodec/dca_syncwords.h"
@@ -32,23 +34,50 @@ static int dts_probe(AVProbeData *p)
     const uint8_t *buf, *bufp;
     uint32_t state = -1;
     int markers[4*16] = {0};
-    int sum, max, i;
+    int exss_markers = 0, exss_nextpos = 0;
+    int sum, max, pos, i;
     int64_t diff = 0;
     uint8_t hdr[12 + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 };
 
-    buf = p->buf + FFMIN(4096, p->buf_size);
-
-    for(; buf < (p->buf+p->buf_size)-2; buf+=2) {
+    for (pos = FFMIN(4096, p->buf_size); pos < p->buf_size - 2; pos += 2) {
         int marker, sample_blocks, sample_rate, sr_code, framesize;
-        int lfe;
+        int lfe, wide_hdr, hdr_size;
         GetBitContext gb;
 
-        bufp = buf;
+        bufp = buf = p->buf + pos;
         state = (state << 16) | bytestream_get_be16(&bufp);
 
-        if (buf - p->buf >= 4)
+        if (pos >= 4)
             diff += FFABS(((int16_t)AV_RL16(buf)) - (int16_t)AV_RL16(buf-4));
 
+        /* extension substream (EXSS) */
+        if (state == DCA_SYNCWORD_SUBSTREAM) {
+            if (pos < exss_nextpos)
+                continue;
+
+            init_get_bits(&gb, buf - 2, 96);
+            skip_bits_long(&gb, 42);
+
+            wide_hdr  = get_bits1(&gb);
+            hdr_size  = get_bits(&gb,  8 + 4 * wide_hdr) + 1;
+            framesize = get_bits(&gb, 16 + 4 * wide_hdr) + 1;
+            if (hdr_size & 3 || framesize & 3)
+                continue;
+            if (hdr_size < 16 || framesize < hdr_size)
+                continue;
+            if (pos - 2 + hdr_size > p->buf_size)
+                continue;
+            if (av_crc(av_crc_get_table(AV_CRC_16_CCITT), 0xffff, buf + 3, hdr_size - 5))
+                continue;
+
+            if (pos == exss_nextpos)
+                exss_markers++;
+            else
+                exss_markers = FFMAX(1, exss_markers - 1);
+            exss_nextpos = pos + framesize;
+            continue;
+        }
+
         /* regular bitstream */
         if (state == DCA_SYNCWORD_CORE_BE &&
             (bytestream_get_be16(&bufp) & 0xFC00) == 0xFC00)
@@ -103,6 +132,9 @@ static int dts_probe(AVProbeData *p)
         markers[marker] ++;
     }
 
+    if (exss_markers > 3)
+        return AVPROBE_SCORE_EXTENSION + 1;
+
     sum = max = 0;
     for (i=0; i<FF_ARRAY_ELEMS(markers); i++) {
         sum += markers[i];
diff --git a/libavformat/dtshddec.c b/libavformat/dtshddec.c
index 0fd0304..f5f0407 100644
--- a/libavformat/dtshddec.c
+++ b/libavformat/dtshddec.c
@@ -21,7 +21,9 @@
 
 #include "libavutil/intreadwrite.h"
 #include "libavutil/dict.h"
+#include "libavcodec/dca.h"
 #include "avformat.h"
+#include "internal.h"
 
 #define AUPR_HDR 0x415550522D484452
 #define AUPRINFO 0x41555052494E464F
@@ -53,6 +55,7 @@ static int dtshd_read_header(AVFormatContext *s)
     DTSHDDemuxContext *dtshd = s->priv_data;
     AVIOContext *pb = s->pb;
     uint64_t chunk_type, chunk_size;
+    int64_t duration, data_start;
     AVStream *st;
     int ret;
     char *value;
@@ -60,14 +63,17 @@ static int dtshd_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id   = AV_CODEC_ID_DTS;
-    st->need_parsing      = AVSTREAM_PARSE_FULL_RAW;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id   = AV_CODEC_ID_DTS;
+    st->need_parsing         = AVSTREAM_PARSE_FULL_RAW;
 
-    while (!avio_feof(pb)) {
+    for (;;) {
         chunk_type = avio_rb64(pb);
         chunk_size = avio_rb64(pb);
 
+        if (avio_feof(pb))
+            break;
+
         if (chunk_size < 4) {
             av_log(s, AV_LOG_ERROR, "chunk size too small\n");
             return AVERROR_INVALIDDATA;
@@ -79,10 +85,28 @@ static int dtshd_read_header(AVFormatContext *s)
 
         switch (chunk_type) {
         case STRMDATA:
-            dtshd->data_end = chunk_size + avio_tell(pb);
+            data_start = avio_tell(pb);
+            dtshd->data_end = data_start + chunk_size;
             if (dtshd->data_end <= chunk_size)
                 return AVERROR_INVALIDDATA;
-            return 0;
+            if (!pb->seekable)
+                goto break_loop;
+            goto skip;
+            break;
+        case AUPR_HDR:
+            if (chunk_size < 21)
+                return AVERROR_INVALIDDATA;
+            avio_skip(pb, 3);
+            st->codecpar->sample_rate = avio_rb24(pb);
+            if (!st->codecpar->sample_rate)
+                return AVERROR_INVALIDDATA;
+            duration  = avio_rb32(pb); // num_frames
+            duration *= avio_rb16(pb); // samples_per_frames
+            st->duration = duration;
+            avio_skip(pb, 5);
+            st->codecpar->channels = ff_dca_count_chs_for_mask(avio_rb16(pb));
+            st->codecpar->initial_padding = avio_rb16(pb);
+            avio_skip(pb, chunk_size - 21);
             break;
         case FILEINFO:
             if (chunk_size > INT_MAX)
@@ -103,7 +127,16 @@ skip:
         };
     }
 
-    return AVERROR_EOF;
+    if (!dtshd->data_end)
+        return AVERROR_EOF;
+
+    avio_seek(pb, data_start, SEEK_SET);
+
+break_loop:
+    if (st->codecpar->sample_rate)
+        avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
+
+    return 0;
 }
 
 static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)
diff --git a/libavformat/dump.c b/libavformat/dump.c
index eaf87fe..cd14625 100644
--- a/libavformat/dump.c
+++ b/libavformat/dump.c
@@ -26,6 +26,7 @@
 #include "libavutil/display.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/log.h"
+#include "libavutil/mastering_display_metadata.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/avstring.h"
@@ -100,7 +101,7 @@ static void pkt_dump_internal(void *avcl, FILE *f, int level, const AVPacket *pk
     HEXDUMP_PRINT("\n");
     HEXDUMP_PRINT("  size=%d\n", pkt->size);
     if (dump_payload)
-        av_hex_dump(f, pkt->data, pkt->size);
+        hex_dump_internal(avcl, f, level, pkt->data, pkt->size);
 }
 
 void av_pkt_dump2(FILE *f, const AVPacket *pkt, int dump_payload, const AVStream *st)
@@ -259,35 +260,7 @@ static void dump_stereo3d(void *ctx, AVPacketSideData *sd)
 
     stereo = (AVStereo3D *)sd->data;
 
-    switch (stereo->type) {
-    case AV_STEREO3D_2D:
-        av_log(ctx, AV_LOG_INFO, "2D");
-        break;
-    case AV_STEREO3D_SIDEBYSIDE:
-        av_log(ctx, AV_LOG_INFO, "side by side");
-        break;
-    case AV_STEREO3D_TOPBOTTOM:
-        av_log(ctx, AV_LOG_INFO, "top and bottom");
-        break;
-    case AV_STEREO3D_FRAMESEQUENCE:
-        av_log(ctx, AV_LOG_INFO, "frame alternate");
-        break;
-    case AV_STEREO3D_CHECKERBOARD:
-        av_log(ctx, AV_LOG_INFO, "checkerboard");
-        break;
-    case AV_STEREO3D_LINES:
-        av_log(ctx, AV_LOG_INFO, "interleaved lines");
-        break;
-    case AV_STEREO3D_COLUMNS:
-        av_log(ctx, AV_LOG_INFO, "interleaved columns");
-        break;
-    case AV_STEREO3D_SIDEBYSIDE_QUINCUNX:
-        av_log(ctx, AV_LOG_INFO, "side by side (quincunx subsampling)");
-        break;
-    default:
-        av_log(ctx, AV_LOG_WARNING, "unknown");
-        break;
-    }
+    av_log(ctx, AV_LOG_INFO, "%s", av_stereo3d_type_name(stereo->type));
 
     if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
         av_log(ctx, AV_LOG_INFO, " (inverted)");
@@ -336,6 +309,39 @@ static void dump_audioservicetype(void *ctx, AVPacketSideData *sd)
     }
 }
 
+static void dump_cpb(void *ctx, AVPacketSideData *sd)
+{
+    AVCPBProperties *cpb = (AVCPBProperties *)sd->data;
+
+    if (sd->size < sizeof(*cpb)) {
+        av_log(ctx, AV_LOG_INFO, "invalid data");
+        return;
+    }
+
+    av_log(ctx, AV_LOG_INFO,
+           "bitrate max/min/avg: %d/%d/%d buffer size: %d vbv_delay: %"PRId64,
+           cpb->max_bitrate, cpb->min_bitrate, cpb->avg_bitrate,
+           cpb->buffer_size,
+           cpb->vbv_delay);
+}
+
+static void dump_mastering_display_metadata(void *ctx, AVPacketSideData* sd) {
+    AVMasteringDisplayMetadata* metadata = (AVMasteringDisplayMetadata*)sd->data;
+    av_log(ctx, AV_LOG_INFO, "Mastering Display Metadata, "
+           "has_primaries:%d has_luminance:%d "
+           "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f) "
+           "min_luminance=%f, max_luminance=%f\n",
+           metadata->has_primaries, metadata->has_luminance,
+           av_q2d(metadata->display_primaries[0][0]),
+           av_q2d(metadata->display_primaries[0][1]),
+           av_q2d(metadata->display_primaries[1][0]),
+           av_q2d(metadata->display_primaries[1][1]),
+           av_q2d(metadata->display_primaries[2][0]),
+           av_q2d(metadata->display_primaries[2][1]),
+           av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1]),
+           av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance));
+}
+
 static void dump_sidedata(void *ctx, AVStream *st, const char *indent)
 {
     int i;
@@ -359,7 +365,7 @@ static void dump_sidedata(void *ctx, AVStream *st, const char *indent)
             dump_paramchange(ctx, &sd);
             break;
         case AV_PKT_DATA_H263_MB_INFO:
-            av_log(ctx, AV_LOG_INFO, "h263 macroblock info");
+            av_log(ctx, AV_LOG_INFO, "H.263 macroblock info");
             break;
         case AV_PKT_DATA_REPLAYGAIN:
             av_log(ctx, AV_LOG_INFO, "replaygain: ");
@@ -380,8 +386,15 @@ static void dump_sidedata(void *ctx, AVStream *st, const char *indent)
         case AV_PKT_DATA_QUALITY_STATS:
             av_log(ctx, AV_LOG_INFO, "quality factor: %d, pict_type: %c", AV_RL32(sd.data), av_get_picture_type_char(sd.data[4]));
             break;
+        case AV_PKT_DATA_CPB_PROPERTIES:
+            av_log(ctx, AV_LOG_INFO, "cpb: ");
+            dump_cpb(ctx, &sd);
+            break;
+        case AV_PKT_DATA_MASTERING_DISPLAY_METADATA:
+            dump_mastering_display_metadata(ctx, &sd);
+            break;
         default:
-            av_log(ctx, AV_LOG_WARNING,
+            av_log(ctx, AV_LOG_INFO,
                    "unknown side data type %d (%d bytes)", sd.type, sd.size);
             break;
         }
@@ -399,14 +412,32 @@ static void dump_stream_format(AVFormatContext *ic, int i,
     AVStream *st = ic->streams[i];
     AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
     char *separator = ic->dump_separator;
-    char **codec_separator = av_opt_ptr(st->codec->av_class, st->codec, "dump_separator");
-    int use_format_separator = !*codec_separator;
-
-    if (use_format_separator)
-        *codec_separator = av_strdup(separator);
-    avcodec_string(buf, sizeof(buf), st->codec, is_output);
-    if (use_format_separator)
-        av_freep(codec_separator);
+    AVCodecContext *avctx;
+    int ret;
+
+    avctx = avcodec_alloc_context3(NULL);
+    if (!avctx)
+        return;
+
+    ret = avcodec_parameters_to_context(avctx, st->codecpar);
+    if (ret < 0) {
+        avcodec_free_context(&avctx);
+        return;
+    }
+
+    // Fields which are missing from AVCodecParameters need to be taken from the AVCodecContext
+    avctx->properties = st->codec->properties;
+    avctx->codec      = st->codec->codec;
+    avctx->qmin       = st->codec->qmin;
+    avctx->qmax       = st->codec->qmax;
+    avctx->coded_width  = st->codec->coded_width;
+    avctx->coded_height = st->codec->coded_height;
+
+    if (separator)
+        av_opt_set(avctx, "dump_separator", separator, 0);
+    avcodec_string(buf, sizeof(buf), avctx, is_output);
+    avcodec_free_context(&avctx);
+
     av_log(NULL, AV_LOG_INFO, "    Stream #%d:%d", index, i);
 
     /* the pid is an important information, so we display it */
@@ -419,19 +450,19 @@ static void dump_stream_format(AVFormatContext *ic, int i,
            st->time_base.num, st->time_base.den);
     av_log(NULL, AV_LOG_INFO, ": %s", buf);
 
-    if (st->sample_aspect_ratio.num && // default
-        av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) {
+    if (st->sample_aspect_ratio.num &&
+        av_cmp_q(st->sample_aspect_ratio, st->codecpar->sample_aspect_ratio)) {
         AVRational display_aspect_ratio;
         av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
-                  st->codec->width  * (int64_t)st->sample_aspect_ratio.num,
-                  st->codec->height * (int64_t)st->sample_aspect_ratio.den,
+                  st->codecpar->width  * (int64_t)st->sample_aspect_ratio.num,
+                  st->codecpar->height * (int64_t)st->sample_aspect_ratio.den,
                   1024 * 1024);
         av_log(NULL, AV_LOG_INFO, ", SAR %d:%d DAR %d:%d",
                st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
                display_aspect_ratio.num, display_aspect_ratio.den);
     }
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         int fps = st->avg_frame_rate.den && st->avg_frame_rate.num;
         int tbr = st->r_frame_rate.den && st->r_frame_rate.num;
         int tbn = st->time_base.den && st->time_base.num;
@@ -511,10 +542,12 @@ void av_dump_format(AVFormatContext *ic, int index,
         if (ic->start_time != AV_NOPTS_VALUE) {
             int secs, us;
             av_log(NULL, AV_LOG_INFO, ", start: ");
-            secs = ic->start_time / AV_TIME_BASE;
+            secs = llabs(ic->start_time / AV_TIME_BASE);
             us   = llabs(ic->start_time % AV_TIME_BASE);
-            av_log(NULL, AV_LOG_INFO, "%d.%06d",
-                   secs, (int) av_rescale(us, 1000000, AV_TIME_BASE));
+            av_log(NULL, AV_LOG_INFO, "%s%d.%06d",
+                   ic->start_time >= 0 ? "" : "-",
+                   secs,
+                   (int) av_rescale(us, 1000000, AV_TIME_BASE));
         }
         av_log(NULL, AV_LOG_INFO, ", bitrate: ");
         if (ic->bit_rate)
diff --git a/libavformat/dv.c b/libavformat/dv.c
index 84c3061..89a9e10 100644
--- a/libavformat/dv.c
+++ b/libavformat/dv.c
@@ -110,11 +110,11 @@ static const int dv_audio_frequency[3] = {
 
 /*
  * There's a couple of assumptions being made here:
- * 1. By default we silence erroneous (0x8000/16bit 0x800/12bit) audio samples.
+ * 1. By default we silence erroneous (0x8000/16-bit 0x800/12-bit) audio samples.
  *    We can pass them upwards when libavcodec will be ready to deal with them.
  * 2. We don't do software emphasis.
- * 3. Audio is always returned as 16bit linear samples: 12bit nonlinear samples
- *    are converted into 16bit linear ones.
+ * 3. Audio is always returned as 16-bit linear samples: 12-bit nonlinear samples
+ *    are converted into 16-bit linear ones.
  */
 static int dv_extract_audio(const uint8_t *frame, uint8_t **ppcm,
                             const AVDVProfile *sys)
@@ -130,7 +130,7 @@ static int dv_extract_audio(const uint8_t *frame, uint8_t **ppcm,
 
     smpls = as_pack[1]      & 0x3f; /* samples in this frame - min. samples */
     freq  = as_pack[4] >> 3 & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */
-    quant = as_pack[4]      & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */
+    quant = as_pack[4]      & 0x07; /* 0 - 16-bit linear, 1 - 12-bit nonlinear */
 
     if (quant > 1)
         return -1;  /* unsupported quantization */
@@ -161,7 +161,7 @@ static int dv_extract_audio(const uint8_t *frame, uint8_t **ppcm,
         for (i = 0; i < sys->difseg_size; i++) {
             frame += 6 * 80; /* skip DIF segment header */
             if (quant == 1 && i == half_ch) {
-                /* next stereo channel (12bit mode only) */
+                /* next stereo channel (12-bit mode only) */
                 av_assert0(ipcm<4);
                 pcm = ppcm[ipcm++];
                 if (!pcm)
@@ -171,7 +171,7 @@ static int dv_extract_audio(const uint8_t *frame, uint8_t **ppcm,
             /* for each AV sequence */
             for (j = 0; j < 9; j++) {
                 for (d = 8; d < 80; d += 2) {
-                    if (quant == 0) {  /* 16bit quantization */
+                    if (quant == 0) {  /* 16-bit quantization */
                         of = sys->audio_shuffle[i][j] +
                              (d - 8) / 2 * sys->audio_stride;
                         if (of * 2 >= size)
@@ -184,7 +184,7 @@ static int dv_extract_audio(const uint8_t *frame, uint8_t **ppcm,
 
                         if (pcm[of * 2 + 1] == 0x80 && pcm[of * 2] == 0x00)
                             pcm[of * 2 + 1] = 0;
-                    } else {           /* 12bit quantization */
+                    } else {           /* 12-bit quantization */
                         lc = ((uint16_t)frame[d]     << 4) |
                              ((uint16_t)frame[d + 2] >> 4);
                         rc = ((uint16_t)frame[d + 1] << 4) |
@@ -233,7 +233,7 @@ static int dv_extract_audio_info(DVDemuxContext *c, const uint8_t *frame)
     smpls = as_pack[1]      & 0x3f; /* samples in this frame - min. samples */
     freq  = as_pack[4] >> 3 & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */
     stype = as_pack[3]      & 0x1f; /* 0 - 2CH, 2 - 4CH, 3 - 8CH */
-    quant = as_pack[4]      & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */
+    quant = as_pack[4]      & 0x07; /* 0 - 16-bit linear, 1 - 12-bit nonlinear */
 
     if (freq >= FF_ARRAY_ELEMS(dv_audio_frequency)) {
         av_log(c->fctx, AV_LOG_ERROR,
@@ -259,8 +259,8 @@ static int dv_extract_audio_info(DVDemuxContext *c, const uint8_t *frame)
             if (!c->ast[i])
                 break;
             avpriv_set_pts_info(c->ast[i], 64, 1, 30000);
-            c->ast[i]->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-            c->ast[i]->codec->codec_id   = AV_CODEC_ID_PCM_S16LE;
+            c->ast[i]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+            c->ast[i]->codecpar->codec_id   = AV_CODEC_ID_PCM_S16LE;
 
             av_init_packet(&c->audio_pkt[i]);
             c->audio_pkt[i].size         = 0;
@@ -268,10 +268,10 @@ static int dv_extract_audio_info(DVDemuxContext *c, const uint8_t *frame)
             c->audio_pkt[i].stream_index = c->ast[i]->index;
             c->audio_pkt[i].flags       |= AV_PKT_FLAG_KEY;
         }
-        c->ast[i]->codec->sample_rate    = dv_audio_frequency[freq];
-        c->ast[i]->codec->channels       = 2;
-        c->ast[i]->codec->channel_layout = AV_CH_LAYOUT_STEREO;
-        c->ast[i]->codec->bit_rate       = 2 * dv_audio_frequency[freq] * 16;
+        c->ast[i]->codecpar->sample_rate    = dv_audio_frequency[freq];
+        c->ast[i]->codecpar->channels       = 2;
+        c->ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+        c->ast[i]->codecpar->bit_rate       = 2 * dv_audio_frequency[freq] * 16;
         c->ast[i]->start_time            = 0;
     }
     c->ach = i;
@@ -282,29 +282,25 @@ static int dv_extract_audio_info(DVDemuxContext *c, const uint8_t *frame)
 static int dv_extract_video_info(DVDemuxContext *c, const uint8_t *frame)
 {
     const uint8_t *vsc_pack;
-    AVCodecContext *avctx;
+    AVCodecParameters *par;
     int apt, is16_9;
-    int size = 0;
-
-    if (c->sys) {
-        avctx = c->vst->codec;
-
-        avpriv_set_pts_info(c->vst, 64, c->sys->time_base.num,
-                            c->sys->time_base.den);
-        c->vst->avg_frame_rate = av_inv_q(c->vst->time_base);
-
-        /* finding out SAR is a little bit messy */
-        vsc_pack = dv_extract_pack(frame, dv_video_control);
-        apt      = frame[4] & 0x07;
-        is16_9   = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 ||
-                                 (!apt && (vsc_pack[2] & 0x07) == 0x07)));
-        c->vst->sample_aspect_ratio = c->sys->sar[is16_9];
-        avctx->bit_rate = av_rescale_q(c->sys->frame_size,
-                                       (AVRational) { 8, 1 },
-                                       c->sys->time_base);
-        size = c->sys->frame_size;
-    }
-    return size;
+
+    par = c->vst->codecpar;
+
+    avpriv_set_pts_info(c->vst, 64, c->sys->time_base.num,
+                        c->sys->time_base.den);
+    c->vst->avg_frame_rate = av_inv_q(c->vst->time_base);
+
+    /* finding out SAR is a little bit messy */
+    vsc_pack = dv_extract_pack(frame, dv_video_control);
+    apt      = frame[4] & 0x07;
+    is16_9   = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 ||
+                             (!apt && (vsc_pack[2] & 0x07) == 0x07)));
+    c->vst->sample_aspect_ratio = c->sys->sar[is16_9];
+    par->bit_rate = av_rescale_q(c->sys->frame_size,
+                                   (AVRational) { 8, 1 },
+                                   c->sys->time_base);
+    return c->sys->frame_size;
 }
 
 static int dv_extract_timecode(DVDemuxContext* c, const uint8_t* frame, char *tc)
@@ -340,9 +336,9 @@ DVDemuxContext *avpriv_dv_init_demux(AVFormatContext *s)
     }
 
     c->fctx                   = s;
-    c->vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    c->vst->codec->codec_id   = AV_CODEC_ID_DVVIDEO;
-    c->vst->codec->bit_rate   = 25000000;
+    c->vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    c->vst->codecpar->codec_id   = AV_CODEC_ID_DVVIDEO;
+    c->vst->codecpar->bit_rate   = 25000000;
     c->vst->start_time        = 0;
 
     return c;
@@ -384,7 +380,7 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
         c->audio_pkt[i].pos  = pos;
         c->audio_pkt[i].size = size;
         c->audio_pkt[i].pts  = c->abytes * 30000 * 8 /
-                               c->ast[i]->codec->bit_rate;
+                               c->ast[i]->codecpar->bit_rate;
         ppcm[i] = c->audio_buf[i];
     }
     if (c->ach)
@@ -422,13 +418,12 @@ static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c,
                                int64_t timestamp, int flags)
 {
     // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk)
-    const AVDVProfile *sys = av_dv_codec_profile2(c->vst->codec->coded_width, c->vst->codec->coded_height,
-                                                  c->vst->codec->pix_fmt, c->vst->codec->time_base);
+    const int frame_size = c->sys->frame_size;
     int64_t offset;
     int64_t size       = avio_size(s->pb) - s->internal->data_offset;
-    int64_t max_offset = ((size - 1) / sys->frame_size) * sys->frame_size;
+    int64_t max_offset = ((size - 1) / frame_size) * frame_size;
 
-    offset = sys->frame_size * timestamp;
+    offset = frame_size * timestamp;
 
     if (size >= 0 && offset > max_offset)
         offset = max_offset;
@@ -444,7 +439,7 @@ void ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset)
     if (c->ach) {
         if (c->sys) {
         c->abytes = av_rescale_q(c->frames, c->sys->time_base,
-                                 (AVRational) { 8, c->ast[0]->codec->bit_rate });
+                                 (AVRational) { 8, c->ast[0]->codecpar->bit_rate });
         } else
             av_log(c->fctx, AV_LOG_ERROR, "cannot adjust audio bytes\n");
     }
diff --git a/libavformat/dvbtxt.c b/libavformat/dvbtxt.c
new file mode 100644
index 0000000..6828738
--- /dev/null
+++ b/libavformat/dvbtxt.c
@@ -0,0 +1,50 @@
+/*
+ * RAW dvb teletext demuxer
+ * Copyright (c) 2016 Marton Balnt <cus at passwd.hu>
+ *
+ * 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 "libavcodec/dvbtxt.h"
+
+#include "avformat.h"
+#include "rawdec.h"
+
+static int dvbtxt_probe(AVProbeData *p)
+{
+    const uint8_t *end = p->buf + p->buf_size;
+    const uint8_t *buf;
+
+    /* The purpose of this is demuxer is to detect DVB teletext streams in
+     * mpegts, so we reject invalid buffer sizes */
+    if ((p->buf_size + 45) % 184 != 0)
+        return 0;
+
+    if (!ff_data_identifier_is_teletext(p->buf[0]))
+        return 0;
+
+    for (buf = p->buf + 1; buf < end; buf += 46) {
+        if (!ff_data_unit_id_is_teletext(buf[0]) && buf[0] != 0xff)
+            return 0;
+        if (buf[1] != 0x2c)     // data_unit_length
+            return 0;
+    }
+
+    return AVPROBE_SCORE_MAX / 2;
+}
+
+FF_DEF_RAWSUB_DEMUXER(dvbtxt, "dvbtxt", dvbtxt_probe, NULL, AV_CODEC_ID_DVB_TELETEXT, 0)
diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c
index 6cefe8b..422823c 100644
--- a/libavformat/dvenc.c
+++ b/libavformat/dvenc.c
@@ -41,7 +41,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/timecode.h"
 
-#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
+#define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32-bit audio
 
 struct DVMuxContext {
     AVClass          *av_class;
@@ -105,13 +105,13 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu
     case dv_audio_source:  /* AAUX source pack */
         va_start(ap, buf);
         channel = va_arg(ap, int);
-        if (c->ast[channel]->codec->sample_rate == 44100) {
+        if (c->ast[channel]->codecpar->sample_rate == 44100) {
             audio_type = 1;
-        } else if (c->ast[channel]->codec->sample_rate == 32000)
+        } else if (c->ast[channel]->codecpar->sample_rate == 32000)
             audio_type = 2;
         buf[1] = (1 << 7) | /* locked mode -- SMPTE only supports locked mode */
                  (1 << 6) | /* reserved -- always 1 */
-                 (dv_audio_frame_size(c->sys, c->frames, c->ast[channel]->codec->sample_rate) -
+                 (dv_audio_frame_size(c->sys, c->frames, c->ast[channel]->codecpar->sample_rate) -
                   c->sys->audio_min_samples[audio_type]);
                             /* # of samples      */
         buf[2] = (0 << 7) | /* multi-stereo      */
@@ -125,7 +125,7 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu
         buf[4] = (1 << 7) | /* emphasis: 1 -- off */
                  (0 << 6) | /* emphasis time constant: 0 -- reserved */
                  (audio_type << 3) | /* frequency: 0 -- 48kHz, 1 -- 44,1kHz, 2 -- 32kHz */
-                  0;        /* quantization: 0 -- 16bit linear, 1 -- 12bit nonlinear */
+                  0;        /* quantization: 0 -- 16-bit linear, 1 -- 12-bit nonlinear */
 
         va_end(ap);
         break;
@@ -186,7 +186,7 @@ static int dv_write_pack(enum dv_pack_type pack_id, DVMuxContext *c, uint8_t* bu
 static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr)
 {
     int i, j, d, of, size;
-    size = 4 * dv_audio_frame_size(c->sys, c->frames, c->ast[channel]->codec->sample_rate);
+    size = 4 * dv_audio_frame_size(c->sys, c->frames, c->ast[channel]->codecpar->sample_rate);
     frame_ptr += channel * c->sys->difseg_size * 150 * 80;
     for (i = 0; i < c->sys->difseg_size; i++) {
         frame_ptr += 6 * 80; /* skip DIF segment header */
@@ -238,20 +238,21 @@ static void dv_inject_metadata(DVMuxContext *c, uint8_t* frame)
  * The following 3 functions constitute our interface to the world
  */
 
-static int dv_assemble_frame(DVMuxContext *c, AVStream* st,
+static int dv_assemble_frame(AVFormatContext *s,
+                             DVMuxContext *c, AVStream* st,
                              uint8_t* data, int data_size, uint8_t** frame)
 {
     int i, reqasize;
 
     *frame = &c->frame_buf[0];
 
-    switch (st->codec->codec_type) {
+    switch (st->codecpar->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
         /* FIXME: we have to have more sensible approach than this one */
         if (c->has_video)
-            av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames);
+            av_log(s, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames);
         if (data_size != c->sys->frame_size) {
-            av_log(st->codec, AV_LOG_ERROR, "Unexpected frame size, %d != %d\n",
+            av_log(s, AV_LOG_ERROR, "Unexpected frame size, %d != %d\n",
                    data_size, c->sys->frame_size);
             return AVERROR(ENOSYS);
         }
@@ -264,10 +265,10 @@ static int dv_assemble_frame(DVMuxContext *c, AVStream* st,
 
           /* FIXME: we have to have more sensible approach than this one */
         if (av_fifo_size(c->audio_data[i]) + data_size >= 100*MAX_AUDIO_FRAME_SIZE)
-            av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames);
+            av_log(s, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames);
         av_fifo_generic_write(c->audio_data[i], data, data_size, NULL);
 
-        reqasize = 4 * dv_audio_frame_size(c->sys, c->frames, st->codec->sample_rate);
+        reqasize = 4 * dv_audio_frame_size(c->sys, c->frames, st->codecpar->sample_rate);
 
         /* Let us see if we've got enough audio for one DV frame. */
         c->has_audio |= ((reqasize <= av_fifo_size(c->audio_data[i])) << i);
@@ -283,7 +284,7 @@ static int dv_assemble_frame(DVMuxContext *c, AVStream* st,
         c->has_audio = 0;
         for (i=0; i < c->n_ast; i++) {
             dv_inject_audio(c, i, *frame);
-            reqasize = 4 * dv_audio_frame_size(c->sys, c->frames, c->ast[i]->codec->sample_rate);
+            reqasize = 4 * dv_audio_frame_size(c->sys, c->frames, c->ast[i]->codecpar->sample_rate);
             av_fifo_drain(c->audio_data[i], reqasize);
             c->has_audio |= ((reqasize <= av_fifo_size(c->audio_data[i])) << i);
         }
@@ -313,7 +314,7 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s)
 
     /* We have to sort out where audio and where video stream is */
     for (i=0; i<s->nb_streams; i++) {
-        switch (s->streams[i]->codec->codec_type) {
+        switch (s->streams[i]->codecpar->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
             if (vst) return NULL;
             vst = s->streams[i];
@@ -328,28 +329,28 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s)
     }
 
     /* Some checks -- DV format is very picky about its incoming streams */
-    if (!vst || vst->codec->codec_id != AV_CODEC_ID_DVVIDEO)
+    if (!vst || vst->codecpar->codec_id != AV_CODEC_ID_DVVIDEO)
         goto bail_out;
     for (i=0; i<c->n_ast; i++) {
         if (c->ast[i]) {
-            if(c->ast[i]->codec->codec_id    != AV_CODEC_ID_PCM_S16LE ||
-               c->ast[i]->codec->channels    != 2)
+            if(c->ast[i]->codecpar->codec_id    != AV_CODEC_ID_PCM_S16LE ||
+               c->ast[i]->codecpar->channels    != 2)
                 goto bail_out;
-            if (c->ast[i]->codec->sample_rate != 48000 &&
-                c->ast[i]->codec->sample_rate != 44100 &&
-                c->ast[i]->codec->sample_rate != 32000    )
+            if (c->ast[i]->codecpar->sample_rate != 48000 &&
+                c->ast[i]->codecpar->sample_rate != 44100 &&
+                c->ast[i]->codecpar->sample_rate != 32000    )
                 goto bail_out;
         }
     }
-    c->sys = av_dv_codec_profile2(vst->codec->width, vst->codec->height,
-                                  vst->codec->pix_fmt, vst->codec->time_base);
+    c->sys = av_dv_codec_profile2(vst->codecpar->width, vst->codecpar->height,
+                                  vst->codecpar->format, vst->time_base);
     if (!c->sys)
         goto bail_out;
 
     if ((c->sys->time_base.den != 25 && c->sys->time_base.den != 50) || c->sys->time_base.num != 1) {
-        if (c->ast[0] && c->ast[0]->codec->sample_rate != 48000)
+        if (c->ast[0] && c->ast[0]->codecpar->sample_rate != 48000)
             goto bail_out;
-        if (c->ast[1] && c->ast[1]->codec->sample_rate != 48000)
+        if (c->ast[1] && c->ast[1]->codecpar->sample_rate != 48000)
             goto bail_out;
     }
 
@@ -420,7 +421,7 @@ static int dv_write_packet(struct AVFormatContext *s, AVPacket *pkt)
     uint8_t* frame;
     int fsize;
 
-    fsize = dv_assemble_frame(s->priv_data, s->streams[pkt->stream_index],
+    fsize = dv_assemble_frame(s, s->priv_data, s->streams[pkt->stream_index],
                               pkt->data, pkt->size, &frame);
     if (fsize > 0) {
         avio_write(s->pb, frame, fsize);
diff --git a/libavformat/dxa.c b/libavformat/dxa.c
index 1a5822a..162838c 100644
--- a/libavformat/dxa.c
+++ b/libavformat/dxa.c
@@ -106,11 +106,11 @@ static int dxa_read_header(AVFormatContext *s)
         ast = avformat_new_stream(s, NULL);
         if (!ast)
             return AVERROR(ENOMEM);
-        ret = ff_get_wav_header(s, pb, ast->codec, fsize, 0);
+        ret = ff_get_wav_header(s, pb, ast->codecpar, fsize, 0);
         if (ret < 0)
             return ret;
-        if (ast->codec->sample_rate > 0)
-            avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
+        if (ast->codecpar->sample_rate > 0)
+            avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
         // find 'data' chunk
         while(avio_tell(pb) < c->vidpos && !avio_feof(pb)){
             tag = avio_rl32(pb);
@@ -119,18 +119,18 @@ static int dxa_read_header(AVFormatContext *s)
             avio_skip(pb, fsize);
         }
         c->bpc = (fsize + c->frames - 1) / c->frames;
-        if(ast->codec->block_align)
-            c->bpc = ((c->bpc + ast->codec->block_align - 1) / ast->codec->block_align) * ast->codec->block_align;
+        if(ast->codecpar->block_align)
+            c->bpc = ((c->bpc + ast->codecpar->block_align - 1) / ast->codecpar->block_align) * ast->codecpar->block_align;
         c->bytes_left = fsize;
         c->wavpos = avio_tell(pb);
         avio_seek(pb, c->vidpos, SEEK_SET);
     }
 
     /* now we are ready: build format streams */
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_DXA;
-    st->codec->width      = w;
-    st->codec->height     = h;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_DXA;
+    st->codecpar->width      = w;
+    st->codecpar->height     = h;
     av_reduce(&den, &num, den, num, (1UL<<31)-1);
     avpriv_set_pts_info(st, 33, num, den);
     /* flags & 0x80 means that image is interlaced,
@@ -138,7 +138,7 @@ static int dxa_read_header(AVFormatContext *s)
      * either way set true height
      */
     if(flags & 0xC0){
-        st->codec->height >>= 1;
+        st->codecpar->height >>= 1;
     }
     c->readvid = !c->has_sound;
     c->vidpos  = avio_tell(pb);
diff --git a/libavformat/eacdata.c b/libavformat/eacdata.c
index 165ff1a..97eb66e 100644
--- a/libavformat/eacdata.c
+++ b/libavformat/eacdata.c
@@ -70,12 +70,12 @@ static int cdata_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_tag = 0; /* no fourcc */
-    st->codec->codec_id = AV_CODEC_ID_ADPCM_EA_XAS;
-    st->codec->channels = cdata->channels;
-    st->codec->channel_layout = channel_layout;
-    st->codec->sample_rate = sample_rate;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_tag = 0; /* no fourcc */
+    st->codecpar->codec_id = AV_CODEC_ID_ADPCM_EA_XAS;
+    st->codecpar->channels = cdata->channels;
+    st->codecpar->channel_layout = channel_layout;
+    st->codecpar->sample_rate = sample_rate;
     avpriv_set_pts_info(st, 64, 1, sample_rate);
 
     cdata->audio_pts = 0;
diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c
index 8601782..80ce4c6 100644
--- a/libavformat/electronicarts.c
+++ b/libavformat/electronicarts.c
@@ -1,5 +1,5 @@
 /* Electronic Arts Multimedia File Demuxer
- * Copyright (c) 2004 The FFmpeg Project
+ * Copyright (c) 2004  The FFmpeg project
  * Copyright (c) 2006-2008 Peter Ross
  *
  * This file is part of FFmpeg.
@@ -499,14 +499,14 @@ static int init_video_stream(AVFormatContext *s, VideoProperties *video)
     if (!st)
         return AVERROR(ENOMEM);
     video->stream_index = st->index;
-    st->codec->codec_type  = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id    = video->codec;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id    = video->codec;
     // parsing is necessary to make FFmpeg generate correct timestamps
-    if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO)
+    if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO)
         st->need_parsing = AVSTREAM_PARSE_HEADERS;
-    st->codec->codec_tag   = 0; /* no fourcc */
-    st->codec->width       = video->width;
-    st->codec->height      = video->height;
+    st->codecpar->codec_tag   = 0; /* no fourcc */
+    st->codecpar->width       = video->width;
+    st->codecpar->height      = video->height;
     st->duration           = st->nb_frames = video->nb_frames;
     if (video->time_base.num)
         avpriv_set_pts_info(st, 64, video->time_base.num, video->time_base.den);
@@ -551,17 +551,17 @@ static int ea_read_header(AVFormatContext *s)
         if (!st)
             return AVERROR(ENOMEM);
         avpriv_set_pts_info(st, 33, 1, ea->sample_rate);
-        st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id              = ea->audio_codec;
-        st->codec->codec_tag             = 0;   /* no tag */
-        st->codec->channels              = ea->num_channels;
-        st->codec->sample_rate           = ea->sample_rate;
-        st->codec->bits_per_coded_sample = ea->bytes * 8;
-        st->codec->bit_rate              = st->codec->channels *
-                                           st->codec->sample_rate *
-                                           st->codec->bits_per_coded_sample / 4;
-        st->codec->block_align           = st->codec->channels *
-                                           st->codec->bits_per_coded_sample;
+        st->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id              = ea->audio_codec;
+        st->codecpar->codec_tag             = 0;   /* no tag */
+        st->codecpar->channels              = ea->num_channels;
+        st->codecpar->sample_rate           = ea->sample_rate;
+        st->codecpar->bits_per_coded_sample = ea->bytes * 8;
+        st->codecpar->bit_rate              = st->codecpar->channels *
+                                              st->codecpar->sample_rate *
+                                              st->codecpar->bits_per_coded_sample / 4;
+        st->codecpar->block_align           = st->codecpar->channels *
+                                              st->codecpar->bits_per_coded_sample;
         ea->audio_stream_index           = st->index;
         st->start_time                   = 0;
     }
diff --git a/libavformat/epafdec.c b/libavformat/epafdec.c
index c737892..29190ff 100644
--- a/libavformat/epafdec.c
+++ b/libavformat/epafdec.c
@@ -66,15 +66,15 @@ static int epaf_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->channels    = channels;
-    st->codec->sample_rate = sample_rate;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channels    = channels;
+    st->codecpar->sample_rate = sample_rate;
     switch (codec) {
     case 0:
-        st->codec->codec_id = le ? AV_CODEC_ID_PCM_S16LE : AV_CODEC_ID_PCM_S16BE;
+        st->codecpar->codec_id = le ? AV_CODEC_ID_PCM_S16LE : AV_CODEC_ID_PCM_S16BE;
         break;
     case 2:
-        st->codec->codec_id = AV_CODEC_ID_PCM_S8;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
         break;
     case 1:
         avpriv_request_sample(s, "24-bit Paris PCM format");
@@ -82,10 +82,10 @@ static int epaf_read_header(AVFormatContext *s)
         return AVERROR_INVALIDDATA;
     }
 
-    st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id);
-    st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8;
+    st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
+    st->codecpar->block_align = st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8;
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     if (avio_skip(s->pb, 2024) < 0)
         return AVERROR_INVALIDDATA;
diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
index 257319b..16ba8ec 100644
--- a/libavformat/ffmdec.c
+++ b/libavformat/ffmdec.c
@@ -27,6 +27,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
+#include "libavutil/pixdesc.h"
 #include "avformat.h"
 #include "internal.h"
 #include "ffm.h"
@@ -283,7 +284,7 @@ static int ffm2_read_header(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     AVCodecContext *codec;
     const AVCodecDescriptor *codec_desc;
-    int ret;
+    int ret, i;
     int f_main = 0, f_cprv = -1, f_stvi = -1, f_stau = -1;
     AVCodec *enc;
     char *buffer;
@@ -356,8 +357,12 @@ static int ffm2_read_header(AVFormatContext *s)
             codec->flags2 = avio_rb32(pb);
             codec->debug = avio_rb32(pb);
             if (codec->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
-                if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0)
+                int size = avio_rb32(pb);
+                codec->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
+                if (!codec->extradata)
                     return AVERROR(ENOMEM);
+                codec->extradata_size = size;
+                avio_read(pb, codec->extradata, size);
             }
             break;
         case MKBETAG('S', 'T', 'V', 'I'):
@@ -377,6 +382,11 @@ static int ffm2_read_header(AVFormatContext *s)
             codec->height = avio_rb16(pb);
             codec->gop_size = avio_rb16(pb);
             codec->pix_fmt = avio_rb32(pb);
+            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
+                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
+                codec->pix_fmt = AV_PIX_FMT_NONE;
+                goto fail;
+            }
             codec->qmin = avio_r8(pb);
             codec->qmax = avio_r8(pb);
             codec->max_qdiff = avio_r8(pb);
@@ -476,6 +486,9 @@ static int ffm2_read_header(AVFormatContext *s)
         avio_seek(pb, next, SEEK_SET);
     }
 
+    for (i = 0; i < s->nb_streams; i++)
+        avcodec_parameters_from_context(s->streams[i]->codecpar, s->streams[i]->codec);
+
     /* get until end of block reached */
     while ((avio_tell(pb) % ffm->packet_size) != 0 && !pb->eof_reached)
         avio_r8(pb);
@@ -569,6 +582,11 @@ static int ffm_read_header(AVFormatContext *s)
             codec->height = avio_rb16(pb);
             codec->gop_size = avio_rb16(pb);
             codec->pix_fmt = avio_rb32(pb);
+            if (!av_pix_fmt_desc_get(codec->pix_fmt)) {
+                av_log(s, AV_LOG_ERROR, "Invalid pix fmt id: %d\n", codec->pix_fmt);
+                codec->pix_fmt = AV_PIX_FMT_NONE;
+                goto fail;
+            }
             codec->qmin = avio_r8(pb);
             codec->qmax = avio_r8(pb);
             codec->max_qdiff = avio_r8(pb);
@@ -617,9 +635,15 @@ static int ffm_read_header(AVFormatContext *s)
             goto fail;
         }
         if (codec->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
-            if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0)
+            int size = avio_rb32(pb);
+            codec->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!codec->extradata)
                 return AVERROR(ENOMEM);
+            codec->extradata_size = size;
+            avio_read(pb, codec->extradata, size);
         }
+
+        avcodec_parameters_from_context(st->codecpar, codec);
     }
 
     /* get until end of block reached */
diff --git a/libavformat/ffmetadec.c b/libavformat/ffmetadec.c
index e226406..3290b3b 100644
--- a/libavformat/ffmetadec.c
+++ b/libavformat/ffmetadec.c
@@ -139,8 +139,8 @@ static int read_header(AVFormatContext *s)
             if (!st)
                 return AVERROR(ENOMEM);
 
-            st->codec->codec_type = AVMEDIA_TYPE_DATA;
-            st->codec->codec_id   = AV_CODEC_ID_FFMETADATA;
+            st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+            st->codecpar->codec_id   = AV_CODEC_ID_FFMETADATA;
 
             m = &st->metadata;
         } else if (!memcmp(line, ID_CHAPTER, strlen(ID_CHAPTER))) {
diff --git a/libavformat/file.c b/libavformat/file.c
index 544647f..264542a 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -72,6 +72,7 @@ typedef struct FileContext {
     int fd;
     int trunc;
     int blocksize;
+    int follow;
 #if HAVE_DIRENT_H
     DIR *dir;
 #endif
@@ -80,6 +81,7 @@ typedef struct FileContext {
 static const AVOption file_options[] = {
     { "truncate", "truncate existing files on write", offsetof(FileContext, trunc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
     { "blocksize", "set I/O operation maximum block size", offsetof(FileContext, blocksize), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
+    { "follow", "Follow a file as it is being written", offsetof(FileContext, follow), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
     { NULL }
 };
 
@@ -108,6 +110,8 @@ static int file_read(URLContext *h, unsigned char *buf, int size)
     int ret;
     size = FFMIN(size, c->blocksize);
     ret = read(c->fd, buf, size);
+    if (ret == 0 && c->follow)
+        return AVERROR(EAGAIN);
     return (ret == -1) ? AVERROR(errno) : ret;
 }
 
@@ -144,7 +148,11 @@ static int file_check(URLContext *h, int mask)
             ret |= AVIO_FLAG_WRITE;
 #else
     struct stat st;
+#   ifndef _WIN32
     ret = stat(filename, &st);
+#   else
+    ret = win32_stat(filename, &st);
+#   endif
     if (ret < 0)
         return AVERROR(errno);
 
@@ -176,7 +184,6 @@ static int file_delete(URLContext *h)
 
 static int file_move(URLContext *h_src, URLContext *h_dst)
 {
-#if HAVE_UNISTD_H
     const char *filename_src = h_src->filename;
     const char *filename_dst = h_dst->filename;
     av_strstart(filename_src, "file:", &filename_src);
@@ -186,9 +193,6 @@ static int file_move(URLContext *h_src, URLContext *h_dst)
         return AVERROR(errno);
 
     return 0;
-#else
-    return AVERROR(ENOSYS);
-#endif /* HAVE_UNISTD_H */
 }
 
 #if CONFIG_FILE_PROTOCOL
@@ -333,7 +337,7 @@ static int file_close_dir(URLContext *h)
 #endif /* HAVE_LSTAT */
 }
 
-URLProtocol ff_file_protocol = {
+const URLProtocol ff_file_protocol = {
     .name                = "file",
     .url_open            = file_open,
     .url_read            = file_read,
@@ -379,7 +383,7 @@ static int pipe_open(URLContext *h, const char *filename, int flags)
     return 0;
 }
 
-URLProtocol ff_pipe_protocol = {
+const URLProtocol ff_pipe_protocol = {
     .name                = "pipe",
     .url_open            = pipe_open,
     .url_read            = file_read,
diff --git a/libavformat/filmstripdec.c b/libavformat/filmstripdec.c
index cdbb93b..414e276 100644
--- a/libavformat/filmstripdec.c
+++ b/libavformat/filmstripdec.c
@@ -60,15 +60,15 @@ static int read_header(AVFormatContext *s)
     }
 
     avio_skip(pb, 2);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
-    st->codec->pix_fmt    = AV_PIX_FMT_RGBA;
-    st->codec->codec_tag  = 0; /* no fourcc */
-    st->codec->width      = avio_rb16(pb);
-    st->codec->height     = avio_rb16(pb);
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->format     = AV_PIX_FMT_RGBA;
+    st->codecpar->codec_tag  = 0; /* no fourcc */
+    st->codecpar->width      = avio_rb16(pb);
+    st->codecpar->height     = avio_rb16(pb);
     film->leading         = avio_rb16(pb);
 
-    if (st->codec->width * 4LL * st->codec->height >= INT_MAX) {
+    if (st->codecpar->width * 4LL * st->codecpar->height >= INT_MAX) {
         av_log(s, AV_LOG_ERROR, "dimensions too large\n");
         return AVERROR_PATCHWELCOME;
     }
@@ -88,9 +88,9 @@ static int read_packet(AVFormatContext *s,
 
     if (avio_feof(s->pb))
         return AVERROR(EIO);
-    pkt->dts = avio_tell(s->pb) / (st->codec->width * (int64_t)(st->codec->height + film->leading) * 4);
-    pkt->size = av_get_packet(s->pb, pkt, st->codec->width * st->codec->height * 4);
-    avio_skip(s->pb, st->codec->width * (int64_t) film->leading * 4);
+    pkt->dts = avio_tell(s->pb) / (st->codecpar->width * (int64_t)(st->codecpar->height + film->leading) * 4);
+    pkt->size = av_get_packet(s->pb, pkt, st->codecpar->width * st->codecpar->height * 4);
+    avio_skip(s->pb, st->codecpar->width * (int64_t) film->leading * 4);
     if (pkt->size < 0)
         return pkt->size;
     pkt->flags |= AV_PKT_FLAG_KEY;
@@ -100,7 +100,7 @@ static int read_packet(AVFormatContext *s,
 static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
 {
     AVStream *st = s->streams[stream_index];
-    if (avio_seek(s->pb, FFMAX(timestamp, 0) * st->codec->width * st->codec->height * 4, SEEK_SET) < 0)
+    if (avio_seek(s->pb, FFMAX(timestamp, 0) * st->codecpar->width * st->codecpar->height * 4, SEEK_SET) < 0)
         return -1;
     return 0;
 }
diff --git a/libavformat/filmstripenc.c b/libavformat/filmstripenc.c
index 9e2c710..8ead696 100644
--- a/libavformat/filmstripenc.c
+++ b/libavformat/filmstripenc.c
@@ -35,7 +35,7 @@ typedef struct FilmstripMuxContext {
 
 static int write_header(AVFormatContext *s)
 {
-    if (s->streams[0]->codec->pix_fmt != AV_PIX_FMT_RGBA) {
+    if (s->streams[0]->codecpar->format != AV_PIX_FMT_RGBA) {
         av_log(s, AV_LOG_ERROR, "only AV_PIX_FMT_RGBA is supported\n");
         return AVERROR_INVALIDDATA;
     }
@@ -61,8 +61,8 @@ static int write_trailer(AVFormatContext *s)
     avio_wb32(pb, film->nb_frames);
     avio_wb16(pb, 0);  // packing method
     avio_wb16(pb, 0);  // reserved
-    avio_wb16(pb, st->codec->width);
-    avio_wb16(pb, st->codec->height);
+    avio_wb16(pb, st->codecpar->width);
+    avio_wb16(pb, st->codecpar->height);
     avio_wb16(pb, 0);  // leading
     // TODO: should be avg_frame_rate
     avio_wb16(pb, st->time_base.den / st->time_base.num);
diff --git a/libavformat/flac_picture.c b/libavformat/flac_picture.c
index 7bd9825..a3217f0 100644
--- a/libavformat/flac_picture.c
+++ b/libavformat/flac_picture.c
@@ -132,10 +132,10 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size)
     st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
 
     st->disposition      |= AV_DISPOSITION_ATTACHED_PIC;
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = id;
-    st->codec->width      = width;
-    st->codec->height     = height;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = id;
+    st->codecpar->width      = width;
+    st->codecpar->height     = height;
     av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0);
     if (desc)
         av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL);
diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c
index eb92216..3060dc4 100644
--- a/libavformat/flacdec.c
+++ b/libavformat/flacdec.c
@@ -52,8 +52,8 @@ static int flac_read_header(AVFormatContext *s)
     AVStream *st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_FLAC;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_FLAC;
     st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
     /* the parameters will be extracted from the compressed bitstream */
 
@@ -102,14 +102,14 @@ static int flac_read_header(AVFormatContext *s)
                 RETURN_ERROR(AVERROR_INVALIDDATA);
             }
             found_streaminfo = 1;
-            st->codec->extradata      = buffer;
-            st->codec->extradata_size = metadata_size;
+            st->codecpar->extradata      = buffer;
+            st->codecpar->extradata_size = metadata_size;
             buffer = NULL;
 
             /* get sample rate and sample count from STREAMINFO header;
              * other parameters will be extracted by the parser */
-            samplerate = AV_RB24(st->codec->extradata + 10) >> 4;
-            samples    = (AV_RB64(st->codec->extradata + 13) >> 24) & ((1ULL << 36) - 1);
+            samplerate = AV_RB24(st->codecpar->extradata + 10) >> 4;
+            samples    = (AV_RB64(st->codecpar->extradata + 13) >> 24) & ((1ULL << 36) - 1);
 
             /* set time base and duration */
             if (samplerate > 0) {
@@ -189,7 +189,7 @@ static int flac_read_header(AVFormatContext *s)
                         av_log(s, AV_LOG_WARNING,
                                "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n");
                     } else {
-                        st->codec->channel_layout = mask;
+                        st->codecpar->channel_layout = mask;
                         av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0);
                     }
                 }
@@ -248,7 +248,7 @@ static av_unused int64_t flac_read_timestamp(AVFormatContext *s, int stream_inde
         return AV_NOPTS_VALUE;
 
     av_init_packet(&pkt);
-    parser = av_parser_init(st->codec->codec_id);
+    parser = av_parser_init(st->codecpar->codec_id);
     if (!parser){
         return AV_NOPTS_VALUE;
     }
@@ -259,11 +259,13 @@ static av_unused int64_t flac_read_timestamp(AVFormatContext *s, int stream_inde
         if (ret < 0){
             if (ret == AVERROR(EAGAIN))
                 continue;
-            else
-                break;
+            else {
+                av_packet_unref(&pkt);
+                av_assert1(!pkt.size);
+            }
         }
         av_init_packet(&out_pkt);
-        av_parser_parse2(parser, st->codec,
+        av_parser_parse2(parser, st->internal->avctx,
                          &out_pkt.data, &out_pkt.size, pkt.data, pkt.size,
                          pkt.pts, pkt.dts, *ppos);
 
@@ -277,7 +279,8 @@ static av_unused int64_t flac_read_timestamp(AVFormatContext *s, int stream_inde
                 pts = parser->pts;
                 break;
             }
-        }
+        } else if (ret < 0)
+            break;
     }
     av_parser_close(parser);
     return pts;
diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c
index 321af50..89b21e9 100644
--- a/libavformat/flacenc.c
+++ b/libavformat/flacenc.c
@@ -78,7 +78,7 @@ static int flac_write_header(struct AVFormatContext *s)
 {
     int ret;
     int padding = s->metadata_header_padding;
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     FlacMuxerContext *c   = s->priv_data;
 
     if (!c->write_header)
@@ -88,7 +88,7 @@ static int flac_write_header(struct AVFormatContext *s)
         av_log(s, AV_LOG_ERROR, "only one stream is supported\n");
         return AVERROR(EINVAL);
     }
-    if (codec->codec_id != AV_CODEC_ID_FLAC) {
+    if (par->codec_id != AV_CODEC_ID_FLAC) {
         av_log(s, AV_LOG_ERROR, "unsupported codec\n");
         return AVERROR(EINVAL);
     }
@@ -99,15 +99,15 @@ static int flac_write_header(struct AVFormatContext *s)
      * size of a metadata block so we must clip this value to 2^24-1. */
     padding = av_clip_uintp2(padding, 24);
 
-    ret = ff_flac_write_header(s->pb, codec->extradata,
-                               codec->extradata_size, 0);
+    ret = ff_flac_write_header(s->pb, par->extradata,
+                               par->extradata_size, 0);
     if (ret)
         return ret;
 
     /* add the channel layout tag */
-    if (codec->channel_layout &&
-        !(codec->channel_layout & ~0x3ffffULL) &&
-        !ff_flac_is_native_layout(codec->channel_layout)) {
+    if (par->channel_layout &&
+        !(par->channel_layout & ~0x3ffffULL) &&
+        !ff_flac_is_native_layout(par->channel_layout)) {
         AVDictionaryEntry *chmask = av_dict_get(s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK",
                                                 NULL, 0);
 
@@ -116,7 +116,7 @@ static int flac_write_header(struct AVFormatContext *s)
                    "already present, this muxer will not overwrite it.\n");
         } else {
             uint8_t buf[32];
-            snprintf(buf, sizeof(buf), "0x%"PRIx64, codec->channel_layout);
+            snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout);
             av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0);
         }
     }
@@ -142,7 +142,7 @@ static int flac_write_trailer(struct AVFormatContext *s)
     int64_t file_size;
     FlacMuxerContext *c = s->priv_data;
     uint8_t *streaminfo = c->streaminfo ? c->streaminfo :
-                                          s->streams[0]->codec->extradata;
+                                          s->streams[0]->codecpar->extradata;
 
     if (!c->write_header || !streaminfo)
         return 0;
diff --git a/libavformat/flic.c b/libavformat/flic.c
index 30de351..49f5d21 100644
--- a/libavformat/flic.c
+++ b/libavformat/flic.c
@@ -1,6 +1,6 @@
 /*
  * FLI/FLC Animation File Demuxer
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -109,25 +109,25 @@ static int flic_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     flic->video_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_FLIC;
-    st->codec->codec_tag = 0;  /* no fourcc */
-    st->codec->width = AV_RL16(&header[0x08]);
-    st->codec->height = AV_RL16(&header[0x0A]);
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_FLIC;
+    st->codecpar->codec_tag = 0;  /* no fourcc */
+    st->codecpar->width = AV_RL16(&header[0x08]);
+    st->codecpar->height = AV_RL16(&header[0x0A]);
 
-    if (!st->codec->width || !st->codec->height) {
+    if (!st->codecpar->width || !st->codecpar->height) {
         /* Ugly hack needed for the following sample: */
         /* http://samples.mplayerhq.hu/fli-flc/fli-bugs/specular.flc */
         av_log(s, AV_LOG_WARNING,
                "File with no specified width/height. Trying 640x480.\n");
-        st->codec->width  = 640;
-        st->codec->height = 480;
+        st->codecpar->width  = 640;
+        st->codecpar->height = 480;
     }
 
     /* send over the whole 128-byte FLIC header */
-    if (ff_alloc_extradata(st->codec, FLIC_HEADER_SIZE))
+    if (ff_alloc_extradata(st->codecpar, FLIC_HEADER_SIZE))
         return AVERROR(ENOMEM);
-    memcpy(st->codec->extradata, header, FLIC_HEADER_SIZE);
+    memcpy(st->codecpar->extradata, header, FLIC_HEADER_SIZE);
 
     /* peek at the preamble to detect TFTD videos - they seem to always start with an audio chunk */
     if (avio_read(pb, preamble, FLIC_PREAMBLE_SIZE) != FLIC_PREAMBLE_SIZE) {
@@ -152,21 +152,21 @@ static int flic_read_header(AVFormatContext *s)
         flic->audio_stream_index = ast->index;
 
         /* all audio frames are the same size, so use the size of the first chunk for block_align */
-        ast->codec->block_align = AV_RL32(&preamble[0]);
-        ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        ast->codec->codec_id = AV_CODEC_ID_PCM_U8;
-        ast->codec->codec_tag = 0;
-        ast->codec->sample_rate = FLIC_TFTD_SAMPLE_RATE;
-        ast->codec->channels = 1;
-        ast->codec->bit_rate = st->codec->sample_rate * 8;
-        ast->codec->bits_per_coded_sample = 8;
-        ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
-        ast->codec->extradata_size = 0;
+        ast->codecpar->block_align = AV_RL32(&preamble[0]);
+        ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
+        ast->codecpar->codec_tag = 0;
+        ast->codecpar->sample_rate = FLIC_TFTD_SAMPLE_RATE;
+        ast->codecpar->channels = 1;
+        ast->codecpar->bit_rate = st->codecpar->sample_rate * 8;
+        ast->codecpar->bits_per_coded_sample = 8;
+        ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+        ast->codecpar->extradata_size = 0;
 
         /* Since the header information is incorrect we have to figure out the
          * framerate using block_align and the fact that the audio is 22050 Hz.
          * We usually have two cases: 2205 -> 10 fps and 1470 -> 15 fps */
-        avpriv_set_pts_info(st, 64, ast->codec->block_align, FLIC_TFTD_SAMPLE_RATE);
+        avpriv_set_pts_info(st, 64, ast->codecpar->block_align, FLIC_TFTD_SAMPLE_RATE);
         avpriv_set_pts_info(ast, 64, 1, FLIC_TFTD_SAMPLE_RATE);
     } else if (AV_RL16(&header[0x10]) == FLIC_CHUNK_MAGIC_1) {
         avpriv_set_pts_info(st, 64, FLIC_MC_SPEED, 70);
@@ -175,10 +175,10 @@ static int flic_read_header(AVFormatContext *s)
         avio_seek(pb, 12, SEEK_SET);
 
         /* send over abbreviated FLIC header chunk */
-        av_freep(&st->codec->extradata);
-        if (ff_alloc_extradata(st->codec, 12))
+        av_freep(&st->codecpar->extradata);
+        if (ff_alloc_extradata(st->codecpar, 12))
             return AVERROR(ENOMEM);
-        memcpy(st->codec->extradata, header, 12);
+        memcpy(st->codecpar->extradata, header, 12);
 
     } else if (magic_number == FLIC_FILE_MAGIC_1) {
         avpriv_set_pts_info(st, 64, speed, 70);
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index 5090ac2..2bf1e05 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -4,8 +4,8 @@
  *
  * This demuxer will generate a 1 byte extradata for VP6F content.
  * It is composed of:
- *  - upper 4bits: difference between encoded width and visible width
- *  - lower 4bits: difference between encoded height and visible height
+ *  - upper 4 bits: difference between encoded width and visible width
+ *  - lower 4 bits: difference between encoded height and visible height
  *
  * This file is part of FFmpeg.
  *
@@ -97,26 +97,26 @@ static AVStream *create_stream(AVFormatContext *s, int codec_type)
     AVStream *st = avformat_new_stream(s, NULL);
     if (!st)
         return NULL;
-    st->codec->codec_type = codec_type;
+    st->codecpar->codec_type = codec_type;
     if (s->nb_streams>=3 ||(   s->nb_streams==2
-                           && s->streams[0]->codec->codec_type != AVMEDIA_TYPE_SUBTITLE
-                           && s->streams[1]->codec->codec_type != AVMEDIA_TYPE_SUBTITLE))
+                           && s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE
+                           && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE))
         s->ctx_flags &= ~AVFMTCTX_NOHEADER;
 
     avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
     return st;
 }
 
-static int flv_same_audio_codec(AVCodecContext *acodec, int flags)
+static int flv_same_audio_codec(AVCodecParameters *apar, int flags)
 {
     int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
     int flv_codecid           = flags & FLV_AUDIO_CODECID_MASK;
     int codec_id;
 
-    if (!acodec->codec_id && !acodec->codec_tag)
+    if (!apar->codec_id && !apar->codec_tag)
         return 1;
 
-    if (acodec->bits_per_coded_sample != bits_per_coded_sample)
+    if (apar->bits_per_coded_sample != bits_per_coded_sample)
         return 0;
 
     switch (flv_codecid) {
@@ -129,42 +129,42 @@ static int flv_same_audio_codec(AVCodecContext *acodec, int flags)
 #else
                    : AV_CODEC_ID_PCM_S16LE;
 #endif
-        return codec_id == acodec->codec_id;
+        return codec_id == apar->codec_id;
     case FLV_CODECID_PCM_LE:
         codec_id = bits_per_coded_sample == 8
                    ? AV_CODEC_ID_PCM_U8
                    : AV_CODEC_ID_PCM_S16LE;
-        return codec_id == acodec->codec_id;
+        return codec_id == apar->codec_id;
     case FLV_CODECID_AAC:
-        return acodec->codec_id == AV_CODEC_ID_AAC;
+        return apar->codec_id == AV_CODEC_ID_AAC;
     case FLV_CODECID_ADPCM:
-        return acodec->codec_id == AV_CODEC_ID_ADPCM_SWF;
+        return apar->codec_id == AV_CODEC_ID_ADPCM_SWF;
     case FLV_CODECID_SPEEX:
-        return acodec->codec_id == AV_CODEC_ID_SPEEX;
+        return apar->codec_id == AV_CODEC_ID_SPEEX;
     case FLV_CODECID_MP3:
-        return acodec->codec_id == AV_CODEC_ID_MP3;
+        return apar->codec_id == AV_CODEC_ID_MP3;
     case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
     case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
     case FLV_CODECID_NELLYMOSER:
-        return acodec->codec_id == AV_CODEC_ID_NELLYMOSER;
+        return apar->codec_id == AV_CODEC_ID_NELLYMOSER;
     case FLV_CODECID_PCM_MULAW:
-        return acodec->sample_rate == 8000 &&
-               acodec->codec_id    == AV_CODEC_ID_PCM_MULAW;
+        return apar->sample_rate == 8000 &&
+               apar->codec_id    == AV_CODEC_ID_PCM_MULAW;
     case FLV_CODECID_PCM_ALAW:
-        return acodec->sample_rate == 8000 &&
-               acodec->codec_id    == AV_CODEC_ID_PCM_ALAW;
+        return apar->sample_rate == 8000 &&
+               apar->codec_id    == AV_CODEC_ID_PCM_ALAW;
     default:
-        return acodec->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
+        return apar->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
     }
 }
 
 static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream,
-                                AVCodecContext *acodec, int flv_codecid)
+                                AVCodecParameters *apar, int flv_codecid)
 {
     switch (flv_codecid) {
     // no distinction between S16 and S8 PCM codec flags
     case FLV_CODECID_PCM:
-        acodec->codec_id = acodec->bits_per_coded_sample == 8
+        apar->codec_id = apar->bits_per_coded_sample == 8
                            ? AV_CODEC_ID_PCM_U8
 #if HAVE_BIGENDIAN
                            : AV_CODEC_ID_PCM_S16BE;
@@ -173,118 +173,118 @@ static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream,
 #endif
         break;
     case FLV_CODECID_PCM_LE:
-        acodec->codec_id = acodec->bits_per_coded_sample == 8
+        apar->codec_id = apar->bits_per_coded_sample == 8
                            ? AV_CODEC_ID_PCM_U8
                            : AV_CODEC_ID_PCM_S16LE;
         break;
     case FLV_CODECID_AAC:
-        acodec->codec_id = AV_CODEC_ID_AAC;
+        apar->codec_id = AV_CODEC_ID_AAC;
         break;
     case FLV_CODECID_ADPCM:
-        acodec->codec_id = AV_CODEC_ID_ADPCM_SWF;
+        apar->codec_id = AV_CODEC_ID_ADPCM_SWF;
         break;
     case FLV_CODECID_SPEEX:
-        acodec->codec_id    = AV_CODEC_ID_SPEEX;
-        acodec->sample_rate = 16000;
+        apar->codec_id    = AV_CODEC_ID_SPEEX;
+        apar->sample_rate = 16000;
         break;
     case FLV_CODECID_MP3:
-        acodec->codec_id      = AV_CODEC_ID_MP3;
+        apar->codec_id      = AV_CODEC_ID_MP3;
         astream->need_parsing = AVSTREAM_PARSE_FULL;
         break;
     case FLV_CODECID_NELLYMOSER_8KHZ_MONO:
         // in case metadata does not otherwise declare samplerate
-        acodec->sample_rate = 8000;
-        acodec->codec_id    = AV_CODEC_ID_NELLYMOSER;
+        apar->sample_rate = 8000;
+        apar->codec_id    = AV_CODEC_ID_NELLYMOSER;
         break;
     case FLV_CODECID_NELLYMOSER_16KHZ_MONO:
-        acodec->sample_rate = 16000;
-        acodec->codec_id    = AV_CODEC_ID_NELLYMOSER;
+        apar->sample_rate = 16000;
+        apar->codec_id    = AV_CODEC_ID_NELLYMOSER;
         break;
     case FLV_CODECID_NELLYMOSER:
-        acodec->codec_id = AV_CODEC_ID_NELLYMOSER;
+        apar->codec_id = AV_CODEC_ID_NELLYMOSER;
         break;
     case FLV_CODECID_PCM_MULAW:
-        acodec->sample_rate = 8000;
-        acodec->codec_id    = AV_CODEC_ID_PCM_MULAW;
+        apar->sample_rate = 8000;
+        apar->codec_id    = AV_CODEC_ID_PCM_MULAW;
         break;
     case FLV_CODECID_PCM_ALAW:
-        acodec->sample_rate = 8000;
-        acodec->codec_id    = AV_CODEC_ID_PCM_ALAW;
+        apar->sample_rate = 8000;
+        apar->codec_id    = AV_CODEC_ID_PCM_ALAW;
         break;
     default:
         avpriv_request_sample(s, "Audio codec (%x)",
                flv_codecid >> FLV_AUDIO_CODECID_OFFSET);
-        acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;
+        apar->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET;
     }
 }
 
-static int flv_same_video_codec(AVCodecContext *vcodec, int flags)
+static int flv_same_video_codec(AVCodecParameters *vpar, int flags)
 {
     int flv_codecid = flags & FLV_VIDEO_CODECID_MASK;
 
-    if (!vcodec->codec_id && !vcodec->codec_tag)
+    if (!vpar->codec_id && !vpar->codec_tag)
         return 1;
 
     switch (flv_codecid) {
     case FLV_CODECID_H263:
-        return vcodec->codec_id == AV_CODEC_ID_FLV1;
+        return vpar->codec_id == AV_CODEC_ID_FLV1;
     case FLV_CODECID_SCREEN:
-        return vcodec->codec_id == AV_CODEC_ID_FLASHSV;
+        return vpar->codec_id == AV_CODEC_ID_FLASHSV;
     case FLV_CODECID_SCREEN2:
-        return vcodec->codec_id == AV_CODEC_ID_FLASHSV2;
+        return vpar->codec_id == AV_CODEC_ID_FLASHSV2;
     case FLV_CODECID_VP6:
-        return vcodec->codec_id == AV_CODEC_ID_VP6F;
+        return vpar->codec_id == AV_CODEC_ID_VP6F;
     case FLV_CODECID_VP6A:
-        return vcodec->codec_id == AV_CODEC_ID_VP6A;
+        return vpar->codec_id == AV_CODEC_ID_VP6A;
     case FLV_CODECID_H264:
-        return vcodec->codec_id == AV_CODEC_ID_H264;
+        return vpar->codec_id == AV_CODEC_ID_H264;
     default:
-        return vcodec->codec_tag == flv_codecid;
+        return vpar->codec_tag == flv_codecid;
     }
 }
 
 static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream,
                                int flv_codecid, int read)
 {
-    AVCodecContext *vcodec = vstream->codec;
+    AVCodecParameters *par = vstream->codecpar;
     switch (flv_codecid) {
     case FLV_CODECID_H263:
-        vcodec->codec_id = AV_CODEC_ID_FLV1;
+        par->codec_id = AV_CODEC_ID_FLV1;
         break;
     case FLV_CODECID_REALH263:
-        vcodec->codec_id = AV_CODEC_ID_H263;
+        par->codec_id = AV_CODEC_ID_H263;
         break; // Really mean it this time
     case FLV_CODECID_SCREEN:
-        vcodec->codec_id = AV_CODEC_ID_FLASHSV;
+        par->codec_id = AV_CODEC_ID_FLASHSV;
         break;
     case FLV_CODECID_SCREEN2:
-        vcodec->codec_id = AV_CODEC_ID_FLASHSV2;
+        par->codec_id = AV_CODEC_ID_FLASHSV2;
         break;
     case FLV_CODECID_VP6:
-        vcodec->codec_id = AV_CODEC_ID_VP6F;
+        par->codec_id = AV_CODEC_ID_VP6F;
     case FLV_CODECID_VP6A:
         if (flv_codecid == FLV_CODECID_VP6A)
-            vcodec->codec_id = AV_CODEC_ID_VP6A;
+            par->codec_id = AV_CODEC_ID_VP6A;
         if (read) {
-            if (vcodec->extradata_size != 1) {
-                ff_alloc_extradata(vcodec, 1);
+            if (par->extradata_size != 1) {
+                ff_alloc_extradata(par, 1);
             }
-            if (vcodec->extradata)
-                vcodec->extradata[0] = avio_r8(s->pb);
+            if (par->extradata)
+                par->extradata[0] = avio_r8(s->pb);
             else
                 avio_skip(s->pb, 1);
         }
         return 1;     // 1 byte body size adjustment for flv_read_packet()
     case FLV_CODECID_H264:
-        vcodec->codec_id = AV_CODEC_ID_H264;
+        par->codec_id = AV_CODEC_ID_H264;
         vstream->need_parsing = AVSTREAM_PARSE_HEADERS;
         return 3;     // not 4, reading packet type will consume one byte
     case FLV_CODECID_MPEG4:
-        vcodec->codec_id = AV_CODEC_ID_MPEG4;
+        par->codec_id = AV_CODEC_ID_MPEG4;
         return 3;
     default:
         avpriv_request_sample(s, "Video codec (%x)", flv_codecid);
-        vcodec->codec_tag = flv_codecid;
+        par->codec_tag = flv_codecid;
     }
 
     return 0;
@@ -393,7 +393,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
                             AVStream *vstream, const char *key,
                             int64_t max_pos, int depth)
 {
-    AVCodecContext *acodec, *vcodec;
+    AVCodecParameters *apar, *vpar;
     FLVContext *flv = s->priv_data;
     AVIOContext *ioc;
     AMFDataType amf_type;
@@ -477,8 +477,8 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
     }
 
     if (key) {
-        acodec = astream ? astream->codec : NULL;
-        vcodec = vstream ? vstream->codec : NULL;
+        apar = astream ? astream->codecpar : NULL;
+        vpar = vstream ? vstream->codecpar : NULL;
 
         // stream info doesn't live any deeper than the first object
         if (depth == 1) {
@@ -486,36 +486,36 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
                 amf_type == AMF_DATA_TYPE_BOOL) {
                 if (!strcmp(key, "duration"))
                     s->duration = num_val * AV_TIME_BASE;
-                else if (!strcmp(key, "videodatarate") && vcodec &&
+                else if (!strcmp(key, "videodatarate") && vpar &&
                          0 <= (int)(num_val * 1024.0))
-                    vcodec->bit_rate = num_val * 1024.0;
-                else if (!strcmp(key, "audiodatarate") && acodec &&
+                    vpar->bit_rate = num_val * 1024.0;
+                else if (!strcmp(key, "audiodatarate") && apar &&
                          0 <= (int)(num_val * 1024.0))
-                    acodec->bit_rate = num_val * 1024.0;
+                    apar->bit_rate = num_val * 1024.0;
                 else if (!strcmp(key, "datastream")) {
                     AVStream *st = create_stream(s, AVMEDIA_TYPE_SUBTITLE);
                     if (!st)
                         return AVERROR(ENOMEM);
-                    st->codec->codec_id = AV_CODEC_ID_TEXT;
+                    st->codecpar->codec_id = AV_CODEC_ID_TEXT;
                 } else if (flv->trust_metadata) {
-                    if (!strcmp(key, "videocodecid") && vcodec) {
+                    if (!strcmp(key, "videocodecid") && vpar) {
                         flv_set_video_codec(s, vstream, num_val, 0);
-                    } else if (!strcmp(key, "audiocodecid") && acodec) {
+                    } else if (!strcmp(key, "audiocodecid") && apar) {
                         int id = ((int)num_val) << FLV_AUDIO_CODECID_OFFSET;
-                        flv_set_audio_codec(s, astream, acodec, id);
-                    } else if (!strcmp(key, "audiosamplerate") && acodec) {
-                        acodec->sample_rate = num_val;
-                    } else if (!strcmp(key, "audiosamplesize") && acodec) {
-                        acodec->bits_per_coded_sample = num_val;
-                    } else if (!strcmp(key, "stereo") && acodec) {
-                        acodec->channels       = num_val + 1;
-                        acodec->channel_layout = acodec->channels == 2 ?
-                                                 AV_CH_LAYOUT_STEREO :
-                                                 AV_CH_LAYOUT_MONO;
-                    } else if (!strcmp(key, "width") && vcodec) {
-                        vcodec->width = num_val;
-                    } else if (!strcmp(key, "height") && vcodec) {
-                        vcodec->height = num_val;
+                        flv_set_audio_codec(s, astream, apar, id);
+                    } else if (!strcmp(key, "audiosamplerate") && apar) {
+                        apar->sample_rate = num_val;
+                    } else if (!strcmp(key, "audiosamplesize") && apar) {
+                        apar->bits_per_coded_sample = num_val;
+                    } else if (!strcmp(key, "stereo") && apar) {
+                        apar->channels       = num_val + 1;
+                        apar->channel_layout = apar->channels == 2 ?
+                                               AV_CH_LAYOUT_STEREO :
+                                               AV_CH_LAYOUT_MONO;
+                    } else if (!strcmp(key, "width") && vpar) {
+                        vpar->width = num_val;
+                    } else if (!strcmp(key, "height") && vpar) {
+                        vpar->height = num_val;
                     }
                 }
             }
@@ -533,8 +533,8 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
         }
 
         if (amf_type == AMF_DATA_TYPE_OBJECT && s->nb_streams == 1 &&
-           ((!acodec && !strcmp(key, "audiocodecid")) ||
-            (!vcodec && !strcmp(key, "videocodecid"))))
+           ((!apar && !strcmp(key, "audiocodecid")) ||
+            (!vpar && !strcmp(key, "videocodecid"))))
                 s->ctx_flags &= ~AVFMTCTX_NOHEADER; //If there is either audio/video missing, codecid will be an empty object
 
         if (!strcmp(key, "duration")        ||
@@ -612,11 +612,11 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos)
     // the lookup every time it is called.
     for (i = 0; i < s->nb_streams; i++) {
         stream = s->streams[i];
-        if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+        if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
             vstream = stream;
-        else if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+        else if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
             astream = stream;
-        else if (stream->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
+        else if (stream->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
             dstream = stream;
     }
 
@@ -629,23 +629,14 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos)
 
 static int flv_read_header(AVFormatContext *s)
 {
-    int offset, flags;
     FLVContext *flv = s->priv_data;
+    int offset;
 
     avio_skip(s->pb, 4);
-    flags = avio_r8(s->pb);
+    avio_r8(s->pb); // flags
 
     s->ctx_flags |= AVFMTCTX_NOHEADER;
 
-    if (flags & FLV_HEADER_FLAG_HASVIDEO)
-        if (!create_stream(s, AVMEDIA_TYPE_VIDEO))
-            return AVERROR(ENOMEM);
-    if (flags & FLV_HEADER_FLAG_HASAUDIO)
-        if (!create_stream(s, AVMEDIA_TYPE_AUDIO))
-            return AVERROR(ENOMEM);
-    // Flag doesn't indicate whether or not there is script-data present. Must
-    // create that stream if it's encountered.
-
     offset = avio_rb32(s->pb);
     avio_seek(s->pb, offset, SEEK_SET);
     avio_skip(s->pb, 4);
@@ -667,8 +658,8 @@ static int flv_read_close(AVFormatContext *s)
 
 static int flv_get_extradata(AVFormatContext *s, AVStream *st, int size)
 {
-    av_freep(&st->codec->extradata);
-    if (ff_get_extradata(st->codec, s->pb, size) < 0)
+    av_freep(&st->codecpar->extradata);
+    if (ff_get_extradata(s, st->codecpar, s->pb, size) < 0)
         return AVERROR(ENOMEM);
     return 0;
 }
@@ -786,7 +777,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
 
     for (i = 0; i < s->nb_streams; i++) {
         st = s->streams[i];
-        if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
             break;
     }
 
@@ -794,7 +785,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt,
         st = create_stream(s, AVMEDIA_TYPE_SUBTITLE);
         if (!st)
             return AVERROR(ENOMEM);
-        st->codec->codec_id = AV_CODEC_ID_TEXT;
+        st->codecpar->codec_id = AV_CODEC_ID_TEXT;
     }
 
     pkt->dts  = dts;
@@ -945,15 +936,15 @@ skip:
         for (i = 0; i < s->nb_streams; i++) {
             st = s->streams[i];
             if (stream_type == FLV_STREAM_TYPE_AUDIO) {
-                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
-                    (s->audio_codec_id || flv_same_audio_codec(st->codec, flags)))
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
+                    (s->audio_codec_id || flv_same_audio_codec(st->codecpar, flags)))
                     break;
             } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
-                if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
-                    (s->video_codec_id || flv_same_video_codec(st->codec, flags)))
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+                    (s->video_codec_id || flv_same_video_codec(st->codecpar, flags)))
                     break;
             } else if (stream_type == FLV_STREAM_TYPE_DATA) {
-                if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
                     break;
             }
         }
@@ -1019,41 +1010,46 @@ retry_duration:
         sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >>
                                 FLV_AUDIO_SAMPLERATE_OFFSET) >> 3;
         bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8;
-        if (!st->codec->channels || !st->codec->sample_rate ||
-            !st->codec->bits_per_coded_sample) {
-            st->codec->channels              = channels;
-            st->codec->channel_layout        = channels == 1
+        if (!st->codecpar->channels || !st->codecpar->sample_rate ||
+            !st->codecpar->bits_per_coded_sample) {
+            st->codecpar->channels              = channels;
+            st->codecpar->channel_layout        = channels == 1
                                                ? AV_CH_LAYOUT_MONO
                                                : AV_CH_LAYOUT_STEREO;
-            st->codec->sample_rate           = sample_rate;
-            st->codec->bits_per_coded_sample = bits_per_coded_sample;
+            st->codecpar->sample_rate           = sample_rate;
+            st->codecpar->bits_per_coded_sample = bits_per_coded_sample;
         }
-        if (!st->codec->codec_id) {
-            flv_set_audio_codec(s, st, st->codec,
+        if (!st->codecpar->codec_id) {
+            flv_set_audio_codec(s, st, st->codecpar,
                                 flags & FLV_AUDIO_CODECID_MASK);
             flv->last_sample_rate =
-            sample_rate           = st->codec->sample_rate;
+            sample_rate           = st->codecpar->sample_rate;
             flv->last_channels    =
-            channels              = st->codec->channels;
+            channels              = st->codecpar->channels;
         } else {
-            AVCodecContext ctx = {0};
-            ctx.sample_rate = sample_rate;
-            ctx.bits_per_coded_sample = bits_per_coded_sample;
-            flv_set_audio_codec(s, st, &ctx, flags & FLV_AUDIO_CODECID_MASK);
-            sample_rate = ctx.sample_rate;
+            AVCodecParameters *par = avcodec_parameters_alloc();
+            if (!par) {
+                ret = AVERROR(ENOMEM);
+                goto leave;
+            }
+            par->sample_rate = sample_rate;
+            par->bits_per_coded_sample = bits_per_coded_sample;
+            flv_set_audio_codec(s, st, par, flags & FLV_AUDIO_CODECID_MASK);
+            sample_rate = par->sample_rate;
+            avcodec_parameters_free(&par);
         }
     } else if (stream_type == FLV_STREAM_TYPE_VIDEO) {
         size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK, 1);
     } else if (stream_type == FLV_STREAM_TYPE_DATA) {
-        st->codec->codec_id = AV_CODEC_ID_TEXT;
+        st->codecpar->codec_id = AV_CODEC_ID_TEXT;
     }
 
-    if (st->codec->codec_id == AV_CODEC_ID_AAC ||
-        st->codec->codec_id == AV_CODEC_ID_H264 ||
-        st->codec->codec_id == AV_CODEC_ID_MPEG4) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_AAC ||
+        st->codecpar->codec_id == AV_CODEC_ID_H264 ||
+        st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
         int type = avio_r8(s->pb);
         size--;
-        if (st->codec->codec_id == AV_CODEC_ID_H264 || st->codec->codec_id == AV_CODEC_ID_MPEG4) {
+        if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
             // sign extension
             int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
             pts = dts + cts;
@@ -1068,11 +1064,11 @@ retry_duration:
                 dts = pts = AV_NOPTS_VALUE;
             }
         }
-        if (type == 0 && (!st->codec->extradata || st->codec->codec_id == AV_CODEC_ID_AAC ||
-            st->codec->codec_id == AV_CODEC_ID_H264)) {
+        if (type == 0 && (!st->codecpar->extradata || st->codecpar->codec_id == AV_CODEC_ID_AAC ||
+            st->codecpar->codec_id == AV_CODEC_ID_H264)) {
             AVDictionaryEntry *t;
 
-            if (st->codec->extradata) {
+            if (st->codecpar->extradata) {
                 if ((ret = flv_queue_extradata(flv, s->pb, stream_type, size)) < 0)
                     return ret;
                 ret = FFERROR_REDO;
@@ -1083,22 +1079,22 @@ retry_duration:
 
             /* Workaround for buggy Omnia A/XE encoder */
             t = av_dict_get(s->metadata, "Encoder", NULL, 0);
-            if (st->codec->codec_id == AV_CODEC_ID_AAC && t && !strcmp(t->value, "Omnia A/XE"))
-                st->codec->extradata_size = 2;
+            if (st->codecpar->codec_id == AV_CODEC_ID_AAC && t && !strcmp(t->value, "Omnia A/XE"))
+                st->codecpar->extradata_size = 2;
 
-            if (st->codec->codec_id == AV_CODEC_ID_AAC && 0) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_AAC && 0) {
                 MPEG4AudioConfig cfg;
 
-                if (avpriv_mpeg4audio_get_config(&cfg, st->codec->extradata,
-                                             st->codec->extradata_size * 8, 1) >= 0) {
-                st->codec->channels       = cfg.channels;
-                st->codec->channel_layout = 0;
+                if (avpriv_mpeg4audio_get_config(&cfg, st->codecpar->extradata,
+                                                 st->codecpar->extradata_size * 8, 1) >= 0) {
+                st->codecpar->channels       = cfg.channels;
+                st->codecpar->channel_layout = 0;
                 if (cfg.ext_sample_rate)
-                    st->codec->sample_rate = cfg.ext_sample_rate;
+                    st->codecpar->sample_rate = cfg.ext_sample_rate;
                 else
-                    st->codec->sample_rate = cfg.sample_rate;
+                    st->codecpar->sample_rate = cfg.sample_rate;
                 av_log(s, AV_LOG_TRACE, "mp4a config channels %d sample rate %d\n",
-                        st->codec->channels, st->codec->sample_rate);
+                        st->codecpar->channels, st->codecpar->sample_rate);
                 }
             }
 
@@ -1144,10 +1140,11 @@ retry_duration:
 
 leave:
     last = avio_rb32(s->pb);
-    if (last != orig_size + 11 &&
+    if (last != orig_size + 11 && last != orig_size + 10 &&
+        !avio_feof(s->pb) &&
         (last != orig_size || !last) && last != flv->sum_flv_tag_size &&
         !flv->broken_sizes) {
-        av_log(s, AV_LOG_ERROR, "Packet mismatch %d %d\n", last, orig_size + 11);
+        av_log(s, AV_LOG_ERROR, "Packet mismatch %d %d %d\n", last, orig_size + 11, flv->sum_flv_tag_size);
         avio_seek(s->pb, pos + 1, SEEK_SET);
         ret = resync(s);
         av_packet_unref(pkt);
diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
index 8fd5d29..ccbcf64 100644
--- a/libavformat/flvenc.c
+++ b/libavformat/flvenc.c
@@ -23,6 +23,7 @@
 #include "libavutil/dict.h"
 #include "libavutil/intfloat.h"
 #include "libavutil/avassert.h"
+#include "libavutil/mathematics.h"
 #include "avc.h"
 #include "avformat.h"
 #include "flv.h"
@@ -68,10 +69,10 @@ typedef struct FLVContext {
     int64_t duration;
     int64_t delay;      ///< first dts delay (needed for AVC & Speex)
 
-    AVCodecContext *audio_enc;
-    AVCodecContext *video_enc;
+    AVCodecParameters *audio_par;
+    AVCodecParameters *video_par;
     double framerate;
-    AVCodecContext *data_enc;
+    AVCodecParameters *data_par;
 
     int flags;
 } FLVContext;
@@ -80,27 +81,27 @@ typedef struct FLVStreamContext {
     int64_t last_ts;    ///< last timestamp for each stream
 } FLVStreamContext;
 
-static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc)
+static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par)
 {
-    int flags = (enc->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT
+    int flags = (par->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT
                                                    : FLV_SAMPLESSIZE_8BIT;
 
-    if (enc->codec_id == AV_CODEC_ID_AAC) // specs force these parameters
+    if (par->codec_id == AV_CODEC_ID_AAC) // specs force these parameters
         return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ |
                FLV_SAMPLESSIZE_16BIT | FLV_STEREO;
-    else if (enc->codec_id == AV_CODEC_ID_SPEEX) {
-        if (enc->sample_rate != 16000) {
+    else if (par->codec_id == AV_CODEC_ID_SPEEX) {
+        if (par->sample_rate != 16000) {
             av_log(s, AV_LOG_ERROR,
                    "FLV only supports wideband (16kHz) Speex audio\n");
             return AVERROR(EINVAL);
         }
-        if (enc->channels != 1) {
+        if (par->channels != 1) {
             av_log(s, AV_LOG_ERROR, "FLV only supports mono Speex audio\n");
             return AVERROR(EINVAL);
         }
         return FLV_CODECID_SPEEX | FLV_SAMPLERATE_11025HZ | FLV_SAMPLESSIZE_16BIT;
     } else {
-        switch (enc->sample_rate) {
+        switch (par->sample_rate) {
         case 44100:
             flags |= FLV_SAMPLERATE_44100HZ;
             break;
@@ -113,22 +114,22 @@ static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc)
         case 16000: // nellymoser only
         case  8000: // nellymoser only
         case  5512: // not MP3
-            if (enc->codec_id != AV_CODEC_ID_MP3) {
+            if (par->codec_id != AV_CODEC_ID_MP3) {
                 flags |= FLV_SAMPLERATE_SPECIAL;
                 break;
             }
         default:
             av_log(s, AV_LOG_ERROR,
                    "FLV does not support sample rate %d, "
-                   "choose from (44100, 22050, 11025)\n", enc->sample_rate);
+                   "choose from (44100, 22050, 11025)\n", par->sample_rate);
             return AVERROR(EINVAL);
         }
     }
 
-    if (enc->channels > 1)
+    if (par->channels > 1)
         flags |= FLV_STEREO;
 
-    switch (enc->codec_id) {
+    switch (par->codec_id) {
     case AV_CODEC_ID_MP3:
         flags |= FLV_CODECID_MP3    | FLV_SAMPLESSIZE_16BIT;
         break;
@@ -145,9 +146,9 @@ static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc)
         flags |= FLV_CODECID_ADPCM  | FLV_SAMPLESSIZE_16BIT;
         break;
     case AV_CODEC_ID_NELLYMOSER:
-        if (enc->sample_rate == 8000)
+        if (par->sample_rate == 8000)
             flags |= FLV_CODECID_NELLYMOSER_8KHZ_MONO  | FLV_SAMPLESSIZE_16BIT;
-        else if (enc->sample_rate == 16000)
+        else if (par->sample_rate == 16000)
             flags |= FLV_CODECID_NELLYMOSER_16KHZ_MONO | FLV_SAMPLESSIZE_16BIT;
         else
             flags |= FLV_CODECID_NELLYMOSER            | FLV_SAMPLESSIZE_16BIT;
@@ -159,11 +160,11 @@ static int get_audio_flags(AVFormatContext *s, AVCodecContext *enc)
         flags = FLV_CODECID_PCM_ALAW  | FLV_SAMPLERATE_SPECIAL | FLV_SAMPLESSIZE_16BIT;
         break;
     case 0:
-        flags |= enc->codec_tag << 4;
+        flags |= par->codec_tag << 4;
         break;
     default:
         av_log(s, AV_LOG_ERROR, "Audio codec '%s' not compatible with FLV\n",
-               avcodec_get_name(enc->codec_id));
+               avcodec_get_name(par->codec_id));
         return AVERROR(EINVAL);
     }
 
@@ -226,9 +227,9 @@ static void write_metadata(AVFormatContext *s, unsigned int ts)
     /* mixed array (hash) with size and string/type/data tuples */
     avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY);
     metadata_count_pos = avio_tell(pb);
-    metadata_count = 4 * !!flv->video_enc +
-                     5 * !!flv->audio_enc +
-                     1 * !!flv->data_enc  +
+    metadata_count = 4 * !!flv->video_par +
+                     5 * !!flv->audio_par +
+                     1 * !!flv->data_par  +
                      2; // +2 for duration and file size
 
     avio_wb32(pb, metadata_count);
@@ -239,15 +240,15 @@ static void write_metadata(AVFormatContext *s, unsigned int ts)
     // fill in the guessed duration, it'll be corrected later if incorrect
     put_amf_double(pb, s->duration / AV_TIME_BASE);
 
-    if (flv->video_enc) {
+    if (flv->video_par) {
         put_amf_string(pb, "width");
-        put_amf_double(pb, flv->video_enc->width);
+        put_amf_double(pb, flv->video_par->width);
 
         put_amf_string(pb, "height");
-        put_amf_double(pb, flv->video_enc->height);
+        put_amf_double(pb, flv->video_par->height);
 
         put_amf_string(pb, "videodatarate");
-        put_amf_double(pb, flv->video_enc->bit_rate / 1024.0);
+        put_amf_double(pb, flv->video_par->bit_rate / 1024.0);
 
         if (flv->framerate != 0.0) {
             put_amf_string(pb, "framerate");
@@ -256,31 +257,32 @@ static void write_metadata(AVFormatContext *s, unsigned int ts)
         }
 
         put_amf_string(pb, "videocodecid");
-        put_amf_double(pb, flv->video_enc->codec_tag);
+        put_amf_double(pb, flv->video_par->codec_tag);
     }
 
-    if (flv->audio_enc) {
+    if (flv->audio_par) {
         put_amf_string(pb, "audiodatarate");
-        put_amf_double(pb, flv->audio_enc->bit_rate / 1024.0);
+        put_amf_double(pb, flv->audio_par->bit_rate / 1024.0);
 
         put_amf_string(pb, "audiosamplerate");
-        put_amf_double(pb, flv->audio_enc->sample_rate);
+        put_amf_double(pb, flv->audio_par->sample_rate);
 
         put_amf_string(pb, "audiosamplesize");
-        put_amf_double(pb, flv->audio_enc->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16);
+        put_amf_double(pb, flv->audio_par->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16);
 
         put_amf_string(pb, "stereo");
-        put_amf_bool(pb, flv->audio_enc->channels == 2);
+        put_amf_bool(pb, flv->audio_par->channels == 2);
 
         put_amf_string(pb, "audiocodecid");
-        put_amf_double(pb, flv->audio_enc->codec_tag);
+        put_amf_double(pb, flv->audio_par->codec_tag);
     }
 
-    if (flv->data_enc) {
+    if (flv->data_par) {
         put_amf_string(pb, "datastream");
         put_amf_double(pb, 0.0);
     }
 
+    ff_standardize_creation_time(s);
     while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
         if(   !strcmp(tag->key, "width")
             ||!strcmp(tag->key, "height")
@@ -342,76 +344,138 @@ static int unsupported_codec(AVFormatContext *s,
     return AVERROR(ENOSYS);
 }
 
+static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par) {
+    int64_t data_size;
+    AVIOContext *pb = s->pb;
+    FLVContext *flv = s->priv_data;
+
+    if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
+            || par->codec_id == AV_CODEC_ID_MPEG4) {
+        int64_t pos;
+        avio_w8(pb,
+                par->codec_type == AVMEDIA_TYPE_VIDEO ?
+                        FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO);
+        avio_wb24(pb, 0); // size patched later
+        avio_wb24(pb, 0); // ts
+        avio_w8(pb, 0);   // ts ext
+        avio_wb24(pb, 0); // streamid
+        pos = avio_tell(pb);
+        if (par->codec_id == AV_CODEC_ID_AAC) {
+            avio_w8(pb, get_audio_flags(s, par));
+            avio_w8(pb, 0); // AAC sequence header
+
+            if (!par->extradata_size && flv->flags & 1) {
+                PutBitContext pbc;
+                int samplerate_index;
+                int channels = flv->audio_par->channels
+                        - (flv->audio_par->channels == 8 ? 1 : 0);
+                uint8_t data[2];
+
+                for (samplerate_index = 0; samplerate_index < 16;
+                        samplerate_index++)
+                    if (flv->audio_par->sample_rate
+                            == mpeg4audio_sample_rates[samplerate_index])
+                        break;
+
+                init_put_bits(&pbc, data, sizeof(data));
+                put_bits(&pbc, 5, flv->audio_par->profile + 1); //profile
+                put_bits(&pbc, 4, samplerate_index); //sample rate index
+                put_bits(&pbc, 4, channels);
+                put_bits(&pbc, 1, 0); //frame length - 1024 samples
+                put_bits(&pbc, 1, 0); //does not depend on core coder
+                put_bits(&pbc, 1, 0); //is not extension
+                flush_put_bits(&pbc);
+
+                avio_w8(pb, data[0]);
+                avio_w8(pb, data[1]);
+
+                av_log(s, AV_LOG_WARNING, "AAC sequence header: %02x %02x.\n",
+                        data[0], data[1]);
+            }
+            avio_write(pb, par->extradata, par->extradata_size);
+        } else {
+            avio_w8(pb, par->codec_tag | FLV_FRAME_KEY); // flags
+            avio_w8(pb, 0); // AVC sequence header
+            avio_wb24(pb, 0); // composition time
+            ff_isom_write_avcc(pb, par->extradata, par->extradata_size);
+        }
+        data_size = avio_tell(pb) - pos;
+        avio_seek(pb, -data_size - 10, SEEK_CUR);
+        avio_wb24(pb, data_size);
+        avio_skip(pb, data_size + 10 - 3);
+        avio_wb32(pb, data_size + 11); // previous tag size
+    }
+}
+
 static int flv_write_header(AVFormatContext *s)
 {
     int i;
     AVIOContext *pb = s->pb;
     FLVContext *flv = s->priv_data;
-    int64_t data_size;
 
     for (i = 0; i < s->nb_streams; i++) {
-        AVCodecContext *enc = s->streams[i]->codec;
+        AVCodecParameters *par = s->streams[i]->codecpar;
         FLVStreamContext *sc;
-        switch (enc->codec_type) {
+        switch (par->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
             if (s->streams[i]->avg_frame_rate.den &&
                 s->streams[i]->avg_frame_rate.num) {
                 flv->framerate = av_q2d(s->streams[i]->avg_frame_rate);
             }
-            if (flv->video_enc) {
+            if (flv->video_par) {
                 av_log(s, AV_LOG_ERROR,
                        "at most one video stream is supported in flv\n");
                 return AVERROR(EINVAL);
             }
-            flv->video_enc = enc;
-            if (!ff_codec_get_tag(flv_video_codec_ids, enc->codec_id))
-                return unsupported_codec(s, "Video", enc->codec_id);
+            flv->video_par = par;
+            if (!ff_codec_get_tag(flv_video_codec_ids, par->codec_id))
+                return unsupported_codec(s, "Video", par->codec_id);
 
-            if (enc->codec_id == AV_CODEC_ID_MPEG4 ||
-                enc->codec_id == AV_CODEC_ID_H263) {
+            if (par->codec_id == AV_CODEC_ID_MPEG4 ||
+                par->codec_id == AV_CODEC_ID_H263) {
                 int error = s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL;
                 av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING,
-                       "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(enc->codec_id));
+                       "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(par->codec_id));
 
                 if (error) {
                     av_log(s, AV_LOG_ERROR,
                            "use vstrict=-1 / -strict -1 to use it anyway.\n");
                     return AVERROR(EINVAL);
                 }
-            } else if (enc->codec_id == AV_CODEC_ID_VP6) {
+            } else if (par->codec_id == AV_CODEC_ID_VP6) {
                 av_log(s, AV_LOG_WARNING,
                        "Muxing VP6 in flv will produce flipped video on playback.\n");
             }
             break;
         case AVMEDIA_TYPE_AUDIO:
-            if (flv->audio_enc) {
+            if (flv->audio_par) {
                 av_log(s, AV_LOG_ERROR,
                        "at most one audio stream is supported in flv\n");
                 return AVERROR(EINVAL);
             }
-            flv->audio_enc = enc;
-            if (get_audio_flags(s, enc) < 0)
-                return unsupported_codec(s, "Audio", enc->codec_id);
-            if (enc->codec_id == AV_CODEC_ID_PCM_S16BE)
+            flv->audio_par = par;
+            if (get_audio_flags(s, par) < 0)
+                return unsupported_codec(s, "Audio", par->codec_id);
+            if (par->codec_id == AV_CODEC_ID_PCM_S16BE)
                 av_log(s, AV_LOG_WARNING,
                        "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n");
             break;
         case AVMEDIA_TYPE_DATA:
-            if (enc->codec_id != AV_CODEC_ID_TEXT && enc->codec_id != AV_CODEC_ID_NONE)
-                return unsupported_codec(s, "Data", enc->codec_id);
-            flv->data_enc = enc;
+            if (par->codec_id != AV_CODEC_ID_TEXT && par->codec_id != AV_CODEC_ID_NONE)
+                return unsupported_codec(s, "Data", par->codec_id);
+            flv->data_par = par;
             break;
         case AVMEDIA_TYPE_SUBTITLE:
-            if (enc->codec_id != AV_CODEC_ID_TEXT) {
+            if (par->codec_id != AV_CODEC_ID_TEXT) {
                 av_log(s, AV_LOG_ERROR, "Subtitle codec '%s' for stream %d is not compatible with FLV\n",
-                       avcodec_get_name(enc->codec_id), i);
+                       avcodec_get_name(par->codec_id), i);
                 return AVERROR_INVALIDDATA;
             }
-            flv->data_enc = enc;
+            flv->data_par = par;
             break;
         default:
             av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n",
-                   av_get_media_type_string(enc->codec_type), i);
+                   av_get_media_type_string(par->codec_type), i);
             return AVERROR(EINVAL);
         }
         avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */
@@ -427,13 +491,13 @@ static int flv_write_header(AVFormatContext *s)
 
     avio_write(pb, "FLV", 3);
     avio_w8(pb, 1);
-    avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!flv->audio_enc +
-                FLV_HEADER_FLAG_HASVIDEO * !!flv->video_enc);
+    avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!flv->audio_par +
+                FLV_HEADER_FLAG_HASVIDEO * !!flv->video_par);
     avio_wb32(pb, 9);
     avio_wb32(pb, 0);
 
     for (i = 0; i < s->nb_streams; i++)
-        if (s->streams[i]->codec->codec_tag == 5) {
+        if (s->streams[i]->codecpar->codec_tag == 5) {
             avio_w8(pb, 8);     // message type
             avio_wb24(pb, 0);   // include flags
             avio_wb24(pb, 0);   // time stamp
@@ -445,57 +509,7 @@ static int flv_write_header(AVFormatContext *s)
     write_metadata(s, 0);
 
     for (i = 0; i < s->nb_streams; i++) {
-        AVCodecContext *enc = s->streams[i]->codec;
-        if (enc->codec_id == AV_CODEC_ID_AAC || enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) {
-            int64_t pos;
-            avio_w8(pb, enc->codec_type == AVMEDIA_TYPE_VIDEO ?
-                    FLV_TAG_TYPE_VIDEO : FLV_TAG_TYPE_AUDIO);
-            avio_wb24(pb, 0); // size patched later
-            avio_wb24(pb, 0); // ts
-            avio_w8(pb, 0);   // ts ext
-            avio_wb24(pb, 0); // streamid
-            pos = avio_tell(pb);
-            if (enc->codec_id == AV_CODEC_ID_AAC) {
-                avio_w8(pb, get_audio_flags(s, enc));
-                avio_w8(pb, 0); // AAC sequence header
-
-                if (!enc->extradata_size && flv->flags & 1) {
-                    PutBitContext pbc;
-                    int samplerate_index;
-                    int channels = flv->audio_enc->channels - (flv->audio_enc->channels == 8 ? 1 : 0);
-                    uint8_t data[2];
-
-                    for (samplerate_index = 0; samplerate_index < 16; samplerate_index++)
-                        if (flv->audio_enc->sample_rate == mpeg4audio_sample_rates[samplerate_index])
-                            break;
-
-                    init_put_bits(&pbc, data, sizeof(data));
-                    put_bits(&pbc, 5, flv->audio_enc->profile + 1); //profile
-                    put_bits(&pbc, 4, samplerate_index); //sample rate index
-                    put_bits(&pbc, 4, channels);
-                    put_bits(&pbc, 1, 0); //frame length - 1024 samples
-                    put_bits(&pbc, 1, 0); //does not depend on core coder
-                    put_bits(&pbc, 1, 0); //is not extension
-                    flush_put_bits(&pbc);
-
-                    avio_w8(pb, data[0]);
-                    avio_w8(pb, data[1]);
-
-                    av_log(s, AV_LOG_WARNING, "AAC sequence header: %02x %02x.\n", data[0], data[1]);
-                }
-                avio_write(pb, enc->extradata, enc->extradata_size);
-            } else {
-                avio_w8(pb, enc->codec_tag | FLV_FRAME_KEY); // flags
-                avio_w8(pb, 0); // AVC sequence header
-                avio_wb24(pb, 0); // composition time
-                ff_isom_write_avcc(pb, enc->extradata, enc->extradata_size);
-            }
-            data_size = avio_tell(pb) - pos;
-            avio_seek(pb, -data_size - 10, SEEK_CUR);
-            avio_wb24(pb, data_size);
-            avio_skip(pb, data_size + 10 - 3);
-            avio_wb32(pb, data_size + 11); // previous tag size
-        }
+        flv_write_codec_header(s, s->streams[i]->codecpar);
     }
 
     return 0;
@@ -511,10 +525,10 @@ static int flv_write_trailer(AVFormatContext *s)
 
     /* Add EOS tag */
     for (i = 0; i < s->nb_streams; i++) {
-        AVCodecContext *enc = s->streams[i]->codec;
+        AVCodecParameters *par = s->streams[i]->codecpar;
         FLVStreamContext *sc = s->streams[i]->priv_data;
-        if (enc->codec_type == AVMEDIA_TYPE_VIDEO &&
-                (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4))
+        if (par->codec_type == AVMEDIA_TYPE_VIDEO &&
+                (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4))
             put_avc_eos_tag(pb, sc->last_ts);
     }
 
@@ -537,7 +551,7 @@ static int flv_write_trailer(AVFormatContext *s)
 static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     AVIOContext *pb      = s->pb;
-    AVCodecContext *enc  = s->streams[pkt->stream_index]->codec;
+    AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
     FLVContext *flv      = s->priv_data;
     FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data;
     unsigned ts;
@@ -545,14 +559,27 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
     uint8_t *data = NULL;
     int flags = -1, flags_size, ret;
 
-    if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_VP6A ||
-        enc->codec_id == AV_CODEC_ID_VP6  || enc->codec_id == AV_CODEC_ID_AAC)
+    if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A ||
+        par->codec_id == AV_CODEC_ID_VP6  || par->codec_id == AV_CODEC_ID_AAC)
         flags_size = 2;
-    else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4)
+    else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4)
         flags_size = 5;
     else
         flags_size = 1;
 
+    if (par->codec_id == AV_CODEC_ID_AAC || par->codec_id == AV_CODEC_ID_H264
+            || par->codec_id == AV_CODEC_ID_MPEG4) {
+        int side_size = 0;
+        uint8_t *side = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, &side_size);
+        if (side && side_size > 0 && (side_size != par->extradata_size || memcmp(side, par->extradata, side_size))) {
+            av_free(par->extradata);
+            par->extradata = av_mallocz(side_size + AV_INPUT_BUFFER_PADDING_SIZE);
+            memcpy(par->extradata, side, side_size);
+            par->extradata_size = side_size;
+            flv_write_codec_header(s, par);
+        }
+    }
+
     if (flv->delay == AV_NOPTS_VALUE)
         flv->delay = -pkt->dts;
 
@@ -569,16 +596,19 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
         s->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
     }
 
-    switch (enc->codec_type) {
+    avio_write_marker(pb, av_rescale(ts, AV_TIME_BASE, 1000),
+                      pkt->flags & AV_PKT_FLAG_KEY && (flv->video_par ? par->codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
+
+    switch (par->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
         avio_w8(pb, FLV_TAG_TYPE_VIDEO);
 
-        flags = ff_codec_get_tag(flv_video_codec_ids, enc->codec_id);
+        flags = ff_codec_get_tag(flv_video_codec_ids, par->codec_id);
 
         flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER;
         break;
     case AVMEDIA_TYPE_AUDIO:
-        flags = get_audio_flags(s, enc);
+        flags = get_audio_flags(s, par);
 
         av_assert0(size);
 
@@ -592,12 +622,12 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
         return AVERROR(EINVAL);
     }
 
-    if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) {
+    if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
         /* check if extradata looks like mp4 formatted */
-        if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1)
+        if (par->extradata_size > 0 && *(uint8_t*)par->extradata != 1)
             if ((ret = ff_avc_parse_nal_units_buf(pkt->data, &data, &size)) < 0)
                 return ret;
-    } else if (enc->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
+    } else if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
                (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
         if (!s->streams[pkt->stream_index]->nb_frames) {
         av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
@@ -609,7 +639,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
     }
 
     /* check Speex packet duration */
-    if (enc->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160)
+    if (par->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160)
         av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than "
                                   "8 frames per packet. Adobe Flash "
                                   "Player cannot handle this!\n");
@@ -628,11 +658,11 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
     avio_w8(pb, (ts >> 24) & 0x7F); // timestamps are 32 bits _signed_
     avio_wb24(pb, flv->reserved);
 
-    if (enc->codec_type == AVMEDIA_TYPE_DATA ||
-        enc->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
+    if (par->codec_type == AVMEDIA_TYPE_DATA ||
+        par->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
         int data_size;
         int64_t metadata_size_pos = avio_tell(pb);
-        if (enc->codec_id == AV_CODEC_ID_TEXT) {
+        if (par->codec_id == AV_CODEC_ID_TEXT) {
             // legacy FFmpeg magic?
             avio_w8(pb, AMF_DATA_TYPE_STRING);
             put_amf_string(pb, "onTextData");
@@ -659,17 +689,17 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
     } else {
         av_assert1(flags>=0);
         avio_w8(pb,flags);
-        if (enc->codec_id == AV_CODEC_ID_VP6)
+        if (par->codec_id == AV_CODEC_ID_VP6)
             avio_w8(pb,0);
-        if (enc->codec_id == AV_CODEC_ID_VP6F || enc->codec_id == AV_CODEC_ID_VP6A) {
-            if (enc->extradata_size)
-                avio_w8(pb, enc->extradata[0]);
+        if (par->codec_id == AV_CODEC_ID_VP6F || par->codec_id == AV_CODEC_ID_VP6A) {
+            if (par->extradata_size)
+                avio_w8(pb, par->extradata[0]);
             else
-                avio_w8(pb, ((FFALIGN(enc->width,  16) - enc->width) << 4) |
-                             (FFALIGN(enc->height, 16) - enc->height));
-        } else if (enc->codec_id == AV_CODEC_ID_AAC)
+                avio_w8(pb, ((FFALIGN(par->width,  16) - par->width) << 4) |
+                             (FFALIGN(par->height, 16) - par->height));
+        } else if (par->codec_id == AV_CODEC_ID_AAC)
             avio_w8(pb, 1); // AAC raw
-        else if (enc->codec_id == AV_CODEC_ID_H264 || enc->codec_id == AV_CODEC_ID_MPEG4) {
+        else if (par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_MPEG4) {
             avio_w8(pb, 1); // AVC NALU
             avio_wb24(pb, pkt->pts - pkt->dts);
         }
diff --git a/libavformat/format.c b/libavformat/format.c
index 15fe167..38ca2a3 100644
--- a/libavformat/format.c
+++ b/libavformat/format.c
@@ -62,20 +62,24 @@ void av_register_input_format(AVInputFormat *format)
 {
     AVInputFormat **p = last_iformat;
 
-    format->next = NULL;
-    while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
+    // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL
+    while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
         p = &(*p)->next;
-    last_iformat = &format->next;
+
+    if (!format->next)
+        last_iformat = &format->next;
 }
 
 void av_register_output_format(AVOutputFormat *format)
 {
     AVOutputFormat **p = last_oformat;
 
-    format->next = NULL;
-    while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
+    // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL
+    while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
         p = &(*p)->next;
-    last_oformat = &format->next;
+
+    if (!format->next)
+        last_oformat = &format->next;
 }
 
 int av_match_ext(const char *filename, const char *extensions)
@@ -223,8 +227,12 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened,
             if (av_match_ext(lpd.filename, fmt1->extensions))
                 score = AVPROBE_SCORE_EXTENSION;
         }
-        if (av_match_name(lpd.mime_type, fmt1->mime_type))
-            score = FFMAX(score, AVPROBE_SCORE_MIME);
+        if (av_match_name(lpd.mime_type, fmt1->mime_type)) {
+            if (AVPROBE_SCORE_MIME > score) {
+                av_log(NULL, AV_LOG_DEBUG, "Probing %s score:%d increased to %d due to MIME type\n", fmt1->name, score, AVPROBE_SCORE_MIME);
+                score = AVPROBE_SCORE_MIME;
+            }
+        }
         if (score > score_max) {
             score_max = score;
             fmt       = fmt1;
diff --git a/libavformat/framecrcenc.c b/libavformat/framecrcenc.c
index eacbc45..91bcdcd 100644
--- a/libavformat/framecrcenc.c
+++ b/libavformat/framecrcenc.c
@@ -31,11 +31,11 @@ static int framecrc_write_header(struct AVFormatContext *s)
     int i;
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
-        AVCodecContext *avctx = st->codec;
-        if (avctx->extradata) {
-            uint32_t crc = av_adler32_update(0, avctx->extradata, avctx->extradata_size);
+        AVCodecParameters *par = st->codecpar;
+        if (par->extradata) {
+            uint32_t crc = av_adler32_update(0, par->extradata, par->extradata_size);
             avio_printf(s->pb, "#extradata %d: %8d, 0x%08"PRIx32"\n",
-                        i, avctx->extradata_size, crc);
+                        i, par->extradata_size, crc);
         }
     }
 
diff --git a/libavformat/framehash.c b/libavformat/framehash.c
index a8357b0..4c5499e 100644
--- a/libavformat/framehash.c
+++ b/libavformat/framehash.c
@@ -28,7 +28,20 @@ int ff_framehash_write_header(AVFormatContext *s)
         avio_printf(s->pb, "#software: %s\n", LIBAVFORMAT_IDENT);
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
+        AVCodecParameters *avctx = st->codecpar;
         avio_printf(s->pb, "#tb %d: %d/%d\n", i, st->time_base.num, st->time_base.den);
+        avio_printf(s->pb, "#media_type %d: %s\n", i, av_get_media_type_string(avctx->codec_type));
+        avio_printf(s->pb, "#codec_id %d: %s\n", i, avcodec_get_name(avctx->codec_id));
+        switch (avctx->codec_type) {
+        case AVMEDIA_TYPE_AUDIO:
+            avio_printf(s->pb, "#sample_rate %d: %d\n", i,avctx->sample_rate);
+            avio_printf(s->pb, "#channel_layout %d: %"PRIx64"\n", i,avctx->channel_layout);
+            break;
+        case AVMEDIA_TYPE_VIDEO:
+            avio_printf(s->pb, "#dimensions %d: %dx%d\n", i, avctx->width, avctx->height);
+            avio_printf(s->pb, "#sar %d: %d/%d\n", i, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
+            break;
+        }
         avio_flush(s->pb);
     }
     return 0;
diff --git a/libavformat/frmdec.c b/libavformat/frmdec.c
index 260afbc..2f6b726 100644
--- a/libavformat/frmdec.c
+++ b/libavformat/frmdec.c
@@ -58,30 +58,30 @@ static int frm_read_header(AVFormatContext *avctx)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
     avio_skip(pb, 3);
 
-    st->codec->pix_fmt    = avpriv_find_pix_fmt(frm_pix_fmt_tags, avio_r8(pb));
-    if (!st->codec->pix_fmt)
+    st->codecpar->format    = avpriv_find_pix_fmt(frm_pix_fmt_tags, avio_r8(pb));
+    if (!st->codecpar->format)
         return AVERROR_INVALIDDATA;
 
-    st->codec->codec_tag  = 0;
-    st->codec->width      = avio_rl16(pb);
-    st->codec->height     = avio_rl16(pb);
+    st->codecpar->codec_tag  = 0;
+    st->codecpar->width      = avio_rl16(pb);
+    st->codecpar->height     = avio_rl16(pb);
     return 0;
 }
 
 static int frm_read_packet(AVFormatContext *avctx, AVPacket *pkt)
 {
     FrmContext *s = avctx->priv_data;
-    AVCodecContext *stc = avctx->streams[0]->codec;
+    AVCodecParameters *par = avctx->streams[0]->codecpar;
     int packet_size, ret;
 
     if (s->count)
         return AVERROR_EOF;
 
-    packet_size = av_image_get_buffer_size(stc->pix_fmt, stc->width, stc->height, 1);
+    packet_size = av_image_get_buffer_size(par->format, par->width, par->height, 1);
     if (packet_size < 0)
         return AVERROR_INVALIDDATA;
 
@@ -89,7 +89,7 @@ static int frm_read_packet(AVFormatContext *avctx, AVPacket *pkt)
     if (ret < 0)
         return ret;
 
-    if (stc->pix_fmt == AV_PIX_FMT_BGRA) {
+    if (par->format == AV_PIX_FMT_BGRA) {
         int i;
         for (i = 3; i + 1 <= pkt->size; i += 4)
             pkt->data[i] = 0xFF - pkt->data[i];
diff --git a/libavformat/fsb.c b/libavformat/fsb.c
index 2837c19..4f59576 100644
--- a/libavformat/fsb.c
+++ b/libavformat/fsb.c
@@ -39,7 +39,7 @@ static int fsb_read_header(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     unsigned format, version, c;
     int64_t offset;
-    AVCodecContext *codec;
+    AVCodecParameters *par;
     AVStream *st = avformat_new_stream(s, NULL);
 
     avio_skip(pb, 3); // "FSB"
@@ -53,9 +53,9 @@ static int fsb_read_header(AVFormatContext *s)
 
     if (!st)
         return AVERROR(ENOMEM);
-    codec = st->codec;
-    codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    codec->codec_tag   = 0;
+    par = st->codecpar;
+    par->codec_type  = AVMEDIA_TYPE_AUDIO;
+    par->codec_tag   = 0;
 
     if (version == 3) {
         offset = avio_rl32(pb) + 0x18;
@@ -63,35 +63,35 @@ static int fsb_read_header(AVFormatContext *s)
         st->duration = avio_rl32(pb);
         avio_skip(pb, 12);
         format = avio_rl32(pb);
-        codec->sample_rate = avio_rl32(pb);
-        if (codec->sample_rate <= 0)
+        par->sample_rate = avio_rl32(pb);
+        if (par->sample_rate <= 0)
             return AVERROR_INVALIDDATA;
         avio_skip(pb, 6);
-        codec->channels    = avio_rl16(pb);
-        if (!codec->channels)
+        par->channels    = avio_rl16(pb);
+        if (!par->channels)
             return AVERROR_INVALIDDATA;
 
         if (format & 0x00000100) {
-            codec->codec_id    = AV_CODEC_ID_PCM_S16LE;
-            codec->block_align = 4096 * codec->channels;
+            par->codec_id    = AV_CODEC_ID_PCM_S16LE;
+            par->block_align = 4096 * par->channels;
         } else if (format & 0x00400000) {
-            codec->bits_per_coded_sample = 4;
-            codec->codec_id    = AV_CODEC_ID_ADPCM_IMA_WAV;
-            codec->block_align = 36 * codec->channels;
+            par->bits_per_coded_sample = 4;
+            par->codec_id    = AV_CODEC_ID_ADPCM_IMA_WAV;
+            par->block_align = 36 * par->channels;
         } else if (format & 0x00800000) {
-            codec->codec_id    = AV_CODEC_ID_ADPCM_PSX;
-            codec->block_align = 16 * codec->channels;
+            par->codec_id    = AV_CODEC_ID_ADPCM_PSX;
+            par->block_align = 16 * par->channels;
         } else if (format & 0x02000000) {
-            codec->codec_id    = AV_CODEC_ID_ADPCM_THP;
-            codec->block_align = 8 * codec->channels;
-            if (codec->channels > INT_MAX / 32)
+            par->codec_id    = AV_CODEC_ID_ADPCM_THP;
+            par->block_align = 8 * par->channels;
+            if (par->channels > INT_MAX / 32)
                 return AVERROR_INVALIDDATA;
-            ff_alloc_extradata(codec, 32 * codec->channels);
-            if (!codec->extradata)
+            ff_alloc_extradata(par, 32 * par->channels);
+            if (!par->extradata)
                 return AVERROR(ENOMEM);
             avio_seek(pb, 0x68, SEEK_SET);
-            for (c = 0; c < codec->channels; c++) {
-                avio_read(pb, codec->extradata + 32 * c, 32);
+            for (c = 0; c < par->channels; c++) {
+                avio_read(pb, par->extradata + 32 * c, 32);
                 avio_skip(pb, 14);
             }
         } else {
@@ -109,45 +109,45 @@ static int fsb_read_header(AVFormatContext *s)
         case 0x00001005:
         case 0x40001081:
         case 0x40200001:
-            codec->codec_id = AV_CODEC_ID_XMA2;
+            par->codec_id = AV_CODEC_ID_XMA2;
             break;
         case 0x40000802:
-            codec->codec_id = AV_CODEC_ID_ADPCM_THP;
+            par->codec_id = AV_CODEC_ID_ADPCM_THP;
             break;
         default:
             avpriv_request_sample(s, "format 0x%X", format);
             return AVERROR_PATCHWELCOME;
         }
 
-        codec->sample_rate = avio_rl32(pb);
-        if (codec->sample_rate <= 0)
+        par->sample_rate = avio_rl32(pb);
+        if (par->sample_rate <= 0)
             return AVERROR_INVALIDDATA;
         avio_skip(pb, 6);
 
-        codec->channels    = avio_rl16(pb);
-        if (!codec->channels)
+        par->channels    = avio_rl16(pb);
+        if (!par->channels)
             return AVERROR_INVALIDDATA;
 
-        switch (codec->codec_id) {
+        switch (par->codec_id) {
         case AV_CODEC_ID_XMA2:
-            ff_alloc_extradata(codec, 34);
-            if (!codec->extradata)
+            ff_alloc_extradata(par, 34);
+            if (!par->extradata)
                 return AVERROR(ENOMEM);
-            memset(codec->extradata, 0, 34);
-            codec->block_align = 2048;
+            memset(par->extradata, 0, 34);
+            par->block_align = 2048;
             break;
         case AV_CODEC_ID_ADPCM_THP:
-            if (codec->channels > INT_MAX / 32)
+            if (par->channels > INT_MAX / 32)
                 return AVERROR_INVALIDDATA;
-            ff_alloc_extradata(codec, 32 * codec->channels);
-            if (!codec->extradata)
+            ff_alloc_extradata(par, 32 * par->channels);
+            if (!par->extradata)
                 return AVERROR(ENOMEM);
             avio_seek(pb, 0x80, SEEK_SET);
-            for (c = 0; c < codec->channels; c++) {
-                avio_read(pb, codec->extradata + 32 * c, 32);
+            for (c = 0; c < par->channels; c++) {
+                avio_read(pb, par->extradata + 32 * c, 32);
                 avio_skip(pb, 14);
             }
-            codec->block_align = 8 * codec->channels;
+            par->block_align = 8 * par->channels;
             break;
         }
     } else {
@@ -157,14 +157,14 @@ static int fsb_read_header(AVFormatContext *s)
     avio_skip(pb, offset - avio_tell(pb));
     s->internal->data_offset = avio_tell(pb);
 
-    avpriv_set_pts_info(st, 64, 1, codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, par->sample_rate);
 
     return 0;
 }
 
 static int fsb_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int64_t pos;
     int ret;
 
@@ -172,25 +172,25 @@ static int fsb_read_packet(AVFormatContext *s, AVPacket *pkt)
         return AVERROR_EOF;
 
     pos = avio_tell(s->pb);
-    if (codec->codec_id == AV_CODEC_ID_ADPCM_THP &&
-               codec->channels > 1) {
+    if (par->codec_id == AV_CODEC_ID_ADPCM_THP &&
+               par->channels > 1) {
         int i, ch;
 
-        ret = av_new_packet(pkt, codec->block_align);
+        ret = av_new_packet(pkt, par->block_align);
         if (ret < 0)
             return ret;
         for (i = 0; i < 4; i++) {
-            for (ch = 0; ch < codec->channels; ch++) {
+            for (ch = 0; ch < par->channels; ch++) {
                 pkt->data[ch * 8 + i * 2 + 0] = avio_r8(s->pb);
                 pkt->data[ch * 8 + i * 2 + 1] = avio_r8(s->pb);
             }
         }
         ret = 0;
     } else {
-        ret = av_get_packet(s->pb, pkt, codec->block_align);
+        ret = av_get_packet(s->pb, pkt, par->block_align);
     }
 
-    if (codec->codec_id == AV_CODEC_ID_XMA2 && pkt->size >= 1)
+    if (par->codec_id == AV_CODEC_ID_XMA2 && pkt->size >= 1)
         pkt->duration = (pkt->data[0] >> 2) * 512;
 
     pkt->pos = pos;
diff --git a/libavformat/ftp.c b/libavformat/ftp.c
index c2a60f6..0663b47 100644
--- a/libavformat/ftp.c
+++ b/libavformat/ftp.c
@@ -401,10 +401,12 @@ static int ftp_file_size(FTPContext *s)
 static int ftp_retrieve(FTPContext *s)
 {
     char command[CONTROL_BUFFER_SIZE];
-    static const int retr_codes[] = {150, 0};
+    static const int retr_codes[] = {150, 125, 0};
+    int resp_code;
 
     snprintf(command, sizeof(command), "RETR %s\r\n", s->path);
-    if (ftp_send_command(s, command, retr_codes, NULL) != 150)
+    resp_code = ftp_send_command(s, command, retr_codes, NULL);
+    if (resp_code != 125 && resp_code != 150)
         return AVERROR(EIO);
 
     s->state = DOWNLOADING;
@@ -415,10 +417,12 @@ static int ftp_retrieve(FTPContext *s)
 static int ftp_store(FTPContext *s)
 {
     char command[CONTROL_BUFFER_SIZE];
-    static const int stor_codes[] = {150, 0};
+    static const int stor_codes[] = {150, 125, 0};
+    int resp_code;
 
     snprintf(command, sizeof(command), "STOR %s\r\n", s->path);
-    if (ftp_send_command(s, command, stor_codes, NULL) != 150)
+    resp_code = ftp_send_command(s, command, stor_codes, NULL);
+    if (resp_code != 125 && resp_code != 150)
         return AVERROR(EIO);
 
     s->state = UPLOADING;
@@ -539,7 +543,7 @@ static int ftp_connect_control_connection(URLContext *h)
         } /* if option is not given, don't pass it and let tcp use its own default */
         err = ffurl_open_whitelist(&s->conn_control, buf, AVIO_FLAG_READ_WRITE,
                                    &h->interrupt_callback, &opts,
-                                   h->protocol_whitelist);
+                                   h->protocol_whitelist, h->protocol_blacklist, h);
         av_dict_free(&opts);
         if (err < 0) {
             av_log(h, AV_LOG_ERROR, "Cannot open control connection\n");
@@ -593,7 +597,7 @@ static int ftp_connect_data_connection(URLContext *h)
         } /* if option is not given, don't pass it and let tcp use its own default */
         err = ffurl_open_whitelist(&s->conn_data, buf, h->flags,
                                    &h->interrupt_callback, &opts,
-                                   h->protocol_whitelist);
+                                   h->protocol_whitelist, h->protocol_blacklist, h);
         av_dict_free(&opts);
         if (err < 0)
             return err;
@@ -1099,7 +1103,7 @@ cleanup:
     return ret;
 }
 
-URLProtocol ff_ftp_protocol = {
+const URLProtocol ff_ftp_protocol = {
     .name                = "ftp",
     .url_open            = ftp_open,
     .url_read            = ftp_read,
diff --git a/libavformat/g722.c b/libavformat/g722.c
index 1a87c7d..2feec01 100644
--- a/libavformat/g722.c
+++ b/libavformat/g722.c
@@ -32,17 +32,17 @@ static int g722_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = AV_CODEC_ID_ADPCM_G722;
-    st->codec->sample_rate = 16000;
-    st->codec->channels    = 1;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_G722;
+    st->codecpar->sample_rate = 16000;
+    st->codecpar->channels    = 1;
 
-    st->codec->bits_per_coded_sample =
-        av_get_bits_per_sample(st->codec->codec_id);
+    st->codecpar->bits_per_coded_sample =
+        av_get_bits_per_sample(st->codecpar->codec_id);
 
-    av_assert0(st->codec->bits_per_coded_sample > 0);
+    av_assert0(st->codecpar->bits_per_coded_sample > 0);
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     return 0;
 }
 
diff --git a/libavformat/g723_1.c b/libavformat/g723_1.c
index 661e7bd..27c8c39 100644
--- a/libavformat/g723_1.c
+++ b/libavformat/g723_1.c
@@ -39,13 +39,13 @@ static av_cold int g723_1_init(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id       = AV_CODEC_ID_G723_1;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    st->codec->channels       = 1;
-    st->codec->sample_rate    = 8000;
+    st->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id       = AV_CODEC_ID_G723_1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->channels       = 1;
+    st->codecpar->sample_rate    = 8000;
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     st->start_time = 0;
 
     return 0;
diff --git a/libavformat/g729dec.c b/libavformat/g729dec.c
index 349a014..7b67fc4 100644
--- a/libavformat/g729dec.c
+++ b/libavformat/g729dec.c
@@ -19,13 +19,15 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "avformat.h"
-#include "internal.h"
 #include "libavutil/log.h"
 #include "libavutil/opt.h"
 
+#include "avformat.h"
+#include "internal.h"
+
 typedef struct G729DemuxerContext {
     AVClass *class;
+
     int bit_rate;
 } G729DemuxerContext;
 
@@ -38,49 +40,49 @@ static int g729_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_G729;
-    st->codec->sample_rate = 8000;
-    st->codec->channels = 1;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_CODEC_ID_G729;
+    st->codecpar->sample_rate = 8000;
+    st->codecpar->channels    = 1;
 
-    if (s1 && s1->bit_rate) {
+    if (s1 && s1->bit_rate)
         s->bit_rate = s1->bit_rate;
-    }
 
-    if (s->bit_rate == 0) {
-        av_log(s, AV_LOG_DEBUG, "No bitrate specified. Assuming 8000 b/s\n");
-        s->bit_rate = 8000;
+    switch(s->bit_rate) {
+    case 6400:
+        st->codecpar->block_align = 8;
+        break;
+    case 8000:
+        st->codecpar->block_align = 10;
+        break;
+    default:
+        av_log(s, AV_LOG_ERROR, "Invalid bit_rate value %"PRId64". "
+               "Only 6400 and 8000 b/s are supported.", s->bit_rate);
+        return AVERROR(EINVAL);
     }
 
-    if (s->bit_rate == 6400) {
-        st->codec->block_align = 8;
-    } else if (s->bit_rate == 8000) {
-        st->codec->block_align = 10;
-    } else {
-        av_log(s, AV_LOG_ERROR, "Only 8000 b/s and 6400 b/s bitrates are supported. Provided: %"PRId64" b/s\n", (int64_t)s->bit_rate);
-        return AVERROR_INVALIDDATA;
-    }
+    avpriv_set_pts_info(st, st->codecpar->block_align << 3, 1,
+                        st->codecpar->sample_rate);
 
-    avpriv_set_pts_info(st, st->codec->block_align << 3, 1, st->codec->sample_rate);
     return 0;
 }
+
 static int g729_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    int ret;
-
-    ret = av_get_packet(s->pb, pkt, s->streams[0]->codec->block_align);
-
-    pkt->stream_index = 0;
+    AVStream *st = s->streams[0];
+    int ret = av_get_packet(s->pb, pkt, st->codecpar->block_align);
     if (ret < 0)
         return ret;
 
-    pkt->dts = pkt->pts = pkt->pos / s->streams[0]->codec->block_align;
+    pkt->stream_index = 0;
+    pkt->dts = pkt->pts = pkt->pos / st->codecpar->block_align;
 
-    return ret;
+    return 0;
 }
 
+#define OFFSET(x) offsetof(G729DemuxerContext, x)
 static const AVOption g729_options[] = {
-    { "bit_rate", "", offsetof(G729DemuxerContext, bit_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+    { "bit_rate", "", OFFSET(bit_rate), AV_OPT_TYPE_INT, { .i64 = 8000 }, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     { NULL },
 };
 
diff --git a/libavformat/genh.c b/libavformat/genh.c
index cb1a02f..b683e02 100644
--- a/libavformat/genh.c
+++ b/libavformat/genh.c
@@ -52,50 +52,50 @@ static int genh_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->channels    = avio_rl32(s->pb);
-    if (st->codec->channels <= 0)
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channels    = avio_rl32(s->pb);
+    if (st->codecpar->channels <= 0)
         return AVERROR_INVALIDDATA;
-    if (st->codec->channels == 1)
-        st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    else if (st->codec->channels == 2)
-        st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+    if (st->codecpar->channels == 1)
+        st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    else if (st->codecpar->channels == 2)
+        st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
     align                  =
     c->interleave_size     = avio_rl32(s->pb);
-    if (align < 0 || align > INT_MAX / st->codec->channels)
+    if (align < 0 || align > INT_MAX / st->codecpar->channels)
         return AVERROR_INVALIDDATA;
-    st->codec->block_align = align * st->codec->channels;
-    st->codec->sample_rate = avio_rl32(s->pb);
+    st->codecpar->block_align = align * st->codecpar->channels;
+    st->codecpar->sample_rate = avio_rl32(s->pb);
     avio_skip(s->pb, 4);
     st->duration = avio_rl32(s->pb);
 
     codec = avio_rl32(s->pb);
     switch (codec) {
-    case  0: st->codec->codec_id = AV_CODEC_ID_ADPCM_PSX;        break;
+    case  0: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX;        break;
     case  1:
-    case 11: st->codec->bits_per_coded_sample = 4;
-             st->codec->block_align = 36 * st->codec->channels;
-             st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WAV;    break;
-    case  2: st->codec->codec_id = AV_CODEC_ID_ADPCM_DTK;        break;
-    case  3: st->codec->codec_id = st->codec->block_align > 0 ?
+    case 11: st->codecpar->bits_per_coded_sample = 4;
+             st->codecpar->block_align = 36 * st->codecpar->channels;
+             st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WAV;    break;
+    case  2: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_DTK;        break;
+    case  3: st->codecpar->codec_id = st->codecpar->block_align > 0 ?
                                    AV_CODEC_ID_PCM_S16BE_PLANAR :
                                    AV_CODEC_ID_PCM_S16BE;        break;
-    case  4: st->codec->codec_id = st->codec->block_align > 0 ?
+    case  4: st->codecpar->codec_id = st->codecpar->block_align > 0 ?
                                    AV_CODEC_ID_PCM_S16LE_PLANAR :
                                    AV_CODEC_ID_PCM_S16LE;        break;
-    case  5: st->codec->codec_id = st->codec->block_align > 0 ?
+    case  5: st->codecpar->codec_id = st->codecpar->block_align > 0 ?
                                    AV_CODEC_ID_PCM_S8_PLANAR :
                                    AV_CODEC_ID_PCM_S8;           break;
-    case  6: st->codec->codec_id = AV_CODEC_ID_SDX2_DPCM;        break;
-    case  7: ret = ff_alloc_extradata(st->codec, 2);
+    case  6: st->codecpar->codec_id = AV_CODEC_ID_SDX2_DPCM;        break;
+    case  7: ret = ff_alloc_extradata(st->codecpar, 2);
              if (ret < 0)
                  return ret;
-             AV_WL16(st->codec->extradata, 3);
-             st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;     break;
-    case 10: st->codec->codec_id = AV_CODEC_ID_ADPCM_AICA;       break;
-    case 12: st->codec->codec_id = AV_CODEC_ID_ADPCM_THP;        break;
-    case 13: st->codec->codec_id = AV_CODEC_ID_PCM_U8;           break;
-    case 17: st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_QT;     break;
+             AV_WL16(st->codecpar->extradata, 3);
+             st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;     break;
+    case 10: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_AICA;       break;
+    case 12: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_THP;        break;
+    case 13: st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;           break;
+    case 17: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_QT;     break;
     default:
              avpriv_request_sample(s, "codec %d", codec);
              return AVERROR_PATCHWELCOME;
@@ -117,25 +117,25 @@ static int genh_read_header(AVFormatContext *s)
     coef_splitted[0] = avio_rl32(s->pb);
     coef_splitted[1] = avio_rl32(s->pb);
 
-    if (st->codec->codec_id == AV_CODEC_ID_ADPCM_THP) {
-        if (st->codec->channels > 2) {
-            avpriv_request_sample(s, "channels %d>2", st->codec->channels);
+    if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_THP) {
+        if (st->codecpar->channels > 2) {
+            avpriv_request_sample(s, "channels %d>2", st->codecpar->channels);
             return AVERROR_PATCHWELCOME;
         }
 
-        ff_alloc_extradata(st->codec, 32 * st->codec->channels);
-        for (ch = 0; ch < st->codec->channels; ch++) {
+        ff_alloc_extradata(st->codecpar, 32 * st->codecpar->channels);
+        for (ch = 0; ch < st->codecpar->channels; ch++) {
             if (coef_type & 1) {
                 avpriv_request_sample(s, "coef_type & 1");
                 return AVERROR_PATCHWELCOME;
             } else {
                 avio_seek(s->pb, coef[ch], SEEK_SET);
-                avio_read(s->pb, st->codec->extradata + 32 * ch, 32);
+                avio_read(s->pb, st->codecpar->extradata + 32 * ch, 32);
             }
         }
 
         if (c->dsp_int_type == 1) {
-            st->codec->block_align = 8 * st->codec->channels;
+            st->codecpar->block_align = 8 * st->codecpar->channels;
             if (c->interleave_size != 1 &&
                 c->interleave_size != 2 &&
                 c->interleave_size != 4)
@@ -145,38 +145,38 @@ static int genh_read_header(AVFormatContext *s)
 
     avio_skip(s->pb, start_offset - avio_tell(s->pb));
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
 
 static int genh_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     GENHDemuxContext *c = s->priv_data;
     int ret;
 
-    if (c->dsp_int_type == 1 && codec->codec_id == AV_CODEC_ID_ADPCM_THP &&
-        codec->channels > 1) {
+    if (c->dsp_int_type == 1 && par->codec_id == AV_CODEC_ID_ADPCM_THP &&
+        par->channels > 1) {
         int i, ch;
 
         if (avio_feof(s->pb))
             return AVERROR_EOF;
-        ret = av_new_packet(pkt, 8 * codec->channels);
+        ret = av_new_packet(pkt, 8 * par->channels);
         if (ret < 0)
             return ret;
         for (i = 0; i < 8 / c->interleave_size; i++) {
-            for (ch = 0; ch < codec->channels; ch++) {
+            for (ch = 0; ch < par->channels; ch++) {
                 pkt->data[ch * 8 + i*c->interleave_size+0] = avio_r8(s->pb);
                 pkt->data[ch * 8 + i*c->interleave_size+1] = avio_r8(s->pb);
             }
         }
         ret = 0;
-    } else if (codec->codec_id == AV_CODEC_ID_SDX2_DPCM) {
-        ret = av_get_packet(s->pb, pkt, codec->block_align * 1024);
+    } else if (par->codec_id == AV_CODEC_ID_SDX2_DPCM) {
+        ret = av_get_packet(s->pb, pkt, par->block_align * 1024);
 
     } else {
-        ret = av_get_packet(s->pb, pkt, codec->block_align ? codec->block_align : 1024 * codec->channels);
+        ret = av_get_packet(s->pb, pkt, par->block_align ? par->block_align : 1024 * par->channels);
     }
 
     pkt->stream_index = 0;
diff --git a/libavformat/gif.c b/libavformat/gif.c
index 6537e55..91cd40d 100644
--- a/libavformat/gif.c
+++ b/libavformat/gif.c
@@ -50,12 +50,12 @@ static int get_palette_transparency_index(const uint32_t *palette)
     return smallest_alpha < 128 ? transparent_color_index : -1;
 }
 
-static int gif_image_write_header(AVIOContext *pb, const AVCodecContext *avctx,
+static int gif_image_write_header(AVIOContext *pb, AVStream *st,
                                   int loop_count, uint32_t *palette)
 {
     int i;
     int64_t aspect = 0;
-    const AVRational sar = avctx->sample_aspect_ratio;
+    const AVRational sar = st->sample_aspect_ratio;
 
     if (sar.num > 0 && sar.den > 0) {
         aspect = sar.num * 64LL / sar.den - 15;
@@ -65,8 +65,8 @@ static int gif_image_write_header(AVIOContext *pb, const AVCodecContext *avctx,
 
     avio_write(pb, "GIF", 3);
     avio_write(pb, "89a", 3);
-    avio_wl16(pb, avctx->width);
-    avio_wl16(pb, avctx->height);
+    avio_wl16(pb, st->codecpar->width);
+    avio_wl16(pb, st->codecpar->height);
 
     if (palette) {
         const int bcid = get_palette_transparency_index(palette);
@@ -112,26 +112,26 @@ typedef struct GIFContext {
 static int gif_write_header(AVFormatContext *s)
 {
     GIFContext *gif = s->priv_data;
-    AVCodecContext *video_enc;
+    AVCodecParameters *video_par;
     uint32_t palette[AVPALETTE_COUNT];
 
     if (s->nb_streams != 1 ||
-        s->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
-        s->streams[0]->codec->codec_id   != AV_CODEC_ID_GIF) {
+        s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ||
+        s->streams[0]->codecpar->codec_id   != AV_CODEC_ID_GIF) {
         av_log(s, AV_LOG_ERROR,
                "GIF muxer supports only a single video GIF stream.\n");
         return AVERROR(EINVAL);
     }
 
-    video_enc = s->streams[0]->codec;
+    video_par = s->streams[0]->codecpar;
 
     avpriv_set_pts_info(s->streams[0], 64, 1, 100);
-    if (avpriv_set_systematic_pal2(palette, video_enc->pix_fmt) < 0) {
-        av_assert0(video_enc->pix_fmt == AV_PIX_FMT_PAL8);
+    if (avpriv_set_systematic_pal2(palette, video_par->format) < 0) {
+        av_assert0(video_par->format == AV_PIX_FMT_PAL8);
         /* delay header writing: we wait for the first palette to put it
          * globally */
     } else {
-        gif_image_write_header(s->pb, video_enc, gif->loop, palette);
+        gif_image_write_header(s->pb, s->streams[0], gif->loop, palette);
     }
 
     return 0;
@@ -183,7 +183,7 @@ static int flush_packet(AVFormatContext *s, AVPacket *new)
 static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     GIFContext *gif = s->priv_data;
-    const AVCodecContext *video_enc = s->streams[0]->codec;
+    AVStream *video_st = s->streams[0];
 
     if (!gif->prev_pkt) {
         gif->prev_pkt = av_malloc(sizeof(*gif->prev_pkt));
@@ -191,7 +191,7 @@ static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
             return AVERROR(ENOMEM);
 
         /* Write the first palette as global palette */
-        if (video_enc->pix_fmt == AV_PIX_FMT_PAL8) {
+        if (video_st->codecpar->format == AV_PIX_FMT_PAL8) {
             int size;
             void *palette = av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size);
 
@@ -203,7 +203,7 @@ static int gif_write_packet(AVFormatContext *s, AVPacket *pkt)
                 av_log(s, AV_LOG_ERROR, "Invalid palette extradata\n");
                 return AVERROR_INVALIDDATA;
             }
-            gif_image_write_header(s->pb, video_enc, gif->loop, palette);
+            gif_image_write_header(s->pb, video_st, gif->loop, palette);
         }
 
         return av_copy_packet(gif->prev_pkt, pkt);
diff --git a/libavformat/gifdec.c b/libavformat/gifdec.c
index 48bd603..8993ca6 100644
--- a/libavformat/gifdec.c
+++ b/libavformat/gifdec.c
@@ -118,10 +118,10 @@ static int gif_read_header(AVFormatContext *s)
     /* GIF format operates with time in "hundredths of second",
      * therefore timebase is 1/100 */
     avpriv_set_pts_info(st, 64, 1, 100);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_GIF;
-    st->codec->width      = width;
-    st->codec->height     = height;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_GIF;
+    st->codecpar->width      = width;
+    st->codecpar->height     = height;
 
     /* jump to start because gif decoder needs header data too */
     if (avio_seek(pb, 0, SEEK_SET) != 0)
diff --git a/libavformat/gopher.c b/libavformat/gopher.c
index 835ad7f..3070b24 100644
--- a/libavformat/gopher.c
+++ b/libavformat/gopher.c
@@ -94,7 +94,7 @@ static int gopher_open(URLContext *h, const char *uri, int flags)
 
     s->hd = NULL;
     err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
-                               &h->interrupt_callback, NULL, h->protocol_whitelist);
+                               &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h);
     if (err < 0)
         goto fail;
 
@@ -114,7 +114,7 @@ static int gopher_read(URLContext *h, uint8_t *buf, int size)
 }
 
 
-URLProtocol ff_gopher_protocol = {
+const URLProtocol ff_gopher_protocol = {
     .name           = "gopher",
     .url_open       = gopher_open,
     .url_read       = gopher_read,
diff --git a/libavformat/gsmdec.c b/libavformat/gsmdec.c
index 97dd8c5..1627106 100644
--- a/libavformat/gsmdec.c
+++ b/libavformat/gsmdec.c
@@ -34,6 +34,23 @@ typedef struct GSMDemuxerContext {
     int sample_rate;
 } GSMDemuxerContext;
 
+static int gsm_probe(AVProbeData *p)
+{
+    int valid = 0, invalid = 0;
+    uint8_t *b = p->buf;
+    while (b < p->buf + p->buf_size - 32) {
+        if ((*b & 0xf0) == 0xd0) {
+            valid++;
+        } else {
+            invalid++;
+        }
+        b += 33;
+    }
+    if (valid >> 5 > invalid)
+        return AVPROBE_SCORE_EXTENSION + 1;
+    return 0;
+}
+
 static int gsm_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     int ret, size;
@@ -61,12 +78,12 @@ static int gsm_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = s->iformat->raw_codec_id;
-    st->codec->channels    = 1;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    st->codec->sample_rate = c->sample_rate;
-    st->codec->bit_rate    = GSM_BLOCK_SIZE * 8 * c->sample_rate / GSM_BLOCK_SAMPLES;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = s->iformat->raw_codec_id;
+    st->codecpar->channels    = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->sample_rate = c->sample_rate;
+    st->codecpar->bit_rate    = GSM_BLOCK_SIZE * 8 * c->sample_rate / GSM_BLOCK_SAMPLES;
 
     avpriv_set_pts_info(st, 64, GSM_BLOCK_SAMPLES, GSM_SAMPLE_RATE);
 
@@ -91,6 +108,7 @@ AVInputFormat ff_gsm_demuxer = {
     .name           = "gsm",
     .long_name      = NULL_IF_CONFIG_SMALL("raw GSM"),
     .priv_data_size = sizeof(GSMDemuxerContext),
+    .read_probe     = gsm_probe,
     .read_header    = gsm_read_header,
     .read_packet    = gsm_read_packet,
     .flags          = AVFMT_GENERIC_INDEX,
diff --git a/libavformat/gxf.c b/libavformat/gxf.c
index d9b629d..399f745 100644
--- a/libavformat/gxf.c
+++ b/libavformat/gxf.c
@@ -114,77 +114,77 @@ static int get_sindex(AVFormatContext *s, int id, int format) {
     switch (format) {
         case 3:
         case 4:
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_id = AV_CODEC_ID_MJPEG;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_id = AV_CODEC_ID_MJPEG;
             break;
         case 13:
         case 14:
         case 15:
         case 16:
         case 25:
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_id = AV_CODEC_ID_DVVIDEO;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_id = AV_CODEC_ID_DVVIDEO;
             break;
         case 11:
         case 12:
         case 20:
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_id = AV_CODEC_ID_MPEG2VIDEO;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_id = AV_CODEC_ID_MPEG2VIDEO;
             st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
             break;
         case 22:
         case 23:
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_id = AV_CODEC_ID_MPEG1VIDEO;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_id = AV_CODEC_ID_MPEG1VIDEO;
             st->need_parsing = AVSTREAM_PARSE_HEADERS; //get keyframe flag etc.
             break;
         case 9:
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-            st->codec->codec_id = AV_CODEC_ID_PCM_S24LE;
-            st->codec->channels = 1;
-            st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-            st->codec->sample_rate = 48000;
-            st->codec->bit_rate = 3 * 1 * 48000 * 8;
-            st->codec->block_align = 3 * 1;
-            st->codec->bits_per_coded_sample = 24;
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
+            st->codecpar->channels = 1;
+            st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+            st->codecpar->sample_rate = 48000;
+            st->codecpar->bit_rate = 3 * 1 * 48000 * 8;
+            st->codecpar->block_align = 3 * 1;
+            st->codecpar->bits_per_coded_sample = 24;
             break;
         case 10:
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-            st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
-            st->codec->channels = 1;
-            st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-            st->codec->sample_rate = 48000;
-            st->codec->bit_rate = 2 * 1 * 48000 * 8;
-            st->codec->block_align = 2 * 1;
-            st->codec->bits_per_coded_sample = 16;
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
+            st->codecpar->channels = 1;
+            st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+            st->codecpar->sample_rate = 48000;
+            st->codecpar->bit_rate = 2 * 1 * 48000 * 8;
+            st->codecpar->block_align = 2 * 1;
+            st->codecpar->bits_per_coded_sample = 16;
             break;
         case 17:
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-            st->codec->codec_id = AV_CODEC_ID_AC3;
-            st->codec->channels = 2;
-            st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
-            st->codec->sample_rate = 48000;
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_id = AV_CODEC_ID_AC3;
+            st->codecpar->channels = 2;
+            st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+            st->codecpar->sample_rate = 48000;
             break;
         case 26: /* AVCi50 / AVCi100 (AVC Intra) */
         case 29: /* AVCHD */
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_id = AV_CODEC_ID_H264;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_id = AV_CODEC_ID_H264;
             st->need_parsing = AVSTREAM_PARSE_HEADERS;
             break;
         // timecode tracks:
         case 7:
         case 8:
         case 24:
-            st->codec->codec_type = AVMEDIA_TYPE_DATA;
-            st->codec->codec_id = AV_CODEC_ID_NONE;
+            st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+            st->codecpar->codec_id = AV_CODEC_ID_NONE;
             break;
         case 30:
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_id = AV_CODEC_ID_DNXHD;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_id = AV_CODEC_ID_DNXHD;
             break;
         default:
-            st->codec->codec_type = AVMEDIA_TYPE_UNKNOWN;
-            st->codec->codec_id = AV_CODEC_ID_NONE;
+            st->codecpar->codec_type = AVMEDIA_TYPE_UNKNOWN;
+            st->codecpar->codec_id = AV_CODEC_ID_NONE;
             break;
     }
     return s->nb_streams - 1;
@@ -532,11 +532,11 @@ static int gxf_packet(AVFormatContext *s, AVPacket *pkt) {
         avio_rb32(pb); // "timeline" field number
         avio_r8(pb); // flags
         avio_r8(pb); // reserved
-        if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE ||
-            st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) {
+        if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE ||
+            st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) {
             int first = field_info >> 16;
             int last  = field_info & 0xffff; // last is exclusive
-            int bps = av_get_bits_per_sample(st->codec->codec_id)>>3;
+            int bps = av_get_bits_per_sample(st->codecpar->codec_id)>>3;
             if (first <= last && last*bps <= pkt_len) {
                 avio_skip(pb, first*bps);
                 skip = pkt_len - last*bps;
@@ -551,7 +551,7 @@ static int gxf_packet(AVFormatContext *s, AVPacket *pkt) {
         pkt->dts = field_nr;
 
         //set duration manually for DV or else lavf misdetects the frame rate
-        if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO)
+        if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO)
             pkt->duration = si->fields_per_frame;
 
         return ret;
diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c
index 8229fe9..79951b5 100644
--- a/libavformat/gxfenc.c
+++ b/libavformat/gxfenc.c
@@ -57,7 +57,7 @@ typedef struct GXFStreamContext {
     int pframes;
     int bframes;
     int p_per_gop;
-    int b_per_i_or_p; ///< number of B frames per I frame or P frame
+    int b_per_i_or_p; ///< number of B-frames per I-frame or P-frame
     int first_gop_closed;
     unsigned order;   ///< interleaving order
 } GXFStreamContext;
@@ -124,7 +124,7 @@ static int gxf_find_lines_index(AVStream *st)
     int i;
 
     for (i = 0; i < 6; ++i) {
-        if (st->codec->height == gxf_lines_tab[i].height) {
+        if (st->codecpar->height == gxf_lines_tab[i].height) {
             sc->lines_index = gxf_lines_tab[i].index;
             return 0;
         }
@@ -198,18 +198,18 @@ static int gxf_write_mpeg_auxiliary(AVIOContext *pb, AVStream *st)
         if (sc->b_per_i_or_p > 9)
             sc->b_per_i_or_p = 9; /* ensure value won't take more than one char */
     }
-    if (st->codec->height == 512 || st->codec->height == 608)
+    if (st->codecpar->height == 512 || st->codecpar->height == 608)
         starting_line = 7; // VBI
-    else if (st->codec->height == 480)
+    else if (st->codecpar->height == 480)
         starting_line = 20;
     else
         starting_line = 23; // default PAL
 
     size = snprintf(buffer, sizeof(buffer), "Ver 1\nBr %.6f\nIpg 1\nPpi %d\nBpiop %d\n"
                     "Pix 0\nCf %d\nCg %d\nSl %d\nnl16 %d\nVi 1\nf1 1\n",
-                    (float)st->codec->bit_rate, sc->p_per_gop, sc->b_per_i_or_p,
-                    st->codec->pix_fmt == AV_PIX_FMT_YUV422P ? 2 : 1, sc->first_gop_closed == 1,
-                    starting_line, (st->codec->height + 15) / 16);
+                    (float)st->codecpar->bit_rate, sc->p_per_gop, sc->b_per_i_or_p,
+                    st->codecpar->format == AV_PIX_FMT_YUV422P ? 2 : 1, sc->first_gop_closed == 1,
+                    starting_line, (st->codecpar->height + 15) / 16);
     av_assert0(size < sizeof(buffer));
     avio_w8(pb, TRACK_MPG_AUX);
     avio_w8(pb, size + 1);
@@ -223,7 +223,7 @@ static int gxf_write_dv_auxiliary(AVIOContext *pb, AVStream *st)
 
     avio_w8(pb, TRACK_AUX);
     avio_w8(pb, 8);
-    if (st->codec->pix_fmt == AV_PIX_FMT_YUV420P)
+    if (st->codecpar->format == AV_PIX_FMT_YUV420P)
         track_aux_data |= 0x01;     /* marks stream as DVCAM instead of DVPRO */
     track_aux_data |= 0x40000000;   /* aux data is valid */
     avio_wl64(pb, track_aux_data);
@@ -520,7 +520,7 @@ static int gxf_write_umf_media_mpeg(AVIOContext *pb, AVStream *st)
 {
     GXFStreamContext *sc = st->priv_data;
 
-    if (st->codec->pix_fmt == AV_PIX_FMT_YUV422P)
+    if (st->codecpar->format == AV_PIX_FMT_YUV422P)
         avio_wl32(pb, 2);
     else
         avio_wl32(pb, 1); /* default to 420 */
@@ -529,9 +529,9 @@ static int gxf_write_umf_media_mpeg(AVIOContext *pb, AVStream *st)
     avio_wl32(pb, 1); /* I picture per GOP */
     avio_wl32(pb, sc->p_per_gop);
     avio_wl32(pb, sc->b_per_i_or_p);
-    if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO)
+    if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO)
         avio_wl32(pb, 2);
-    else if (st->codec->codec_id == AV_CODEC_ID_MPEG1VIDEO)
+    else if (st->codecpar->codec_id == AV_CODEC_ID_MPEG1VIDEO)
         avio_wl32(pb, 1);
     else
         avio_wl32(pb, 0);
@@ -556,7 +556,7 @@ static int gxf_write_umf_media_dv(AVIOContext *pb, GXFStreamContext *sc, AVStrea
 {
     int dv_umf_data = 0;
 
-    if (st->codec->pix_fmt == AV_PIX_FMT_YUV420P)
+    if (st->codecpar->format == AV_PIX_FMT_YUV420P)
         dv_umf_data |= 0x20; /* marks as DVCAM instead of DVPRO */
     avio_wl32(pb, dv_umf_data);
     avio_wl32(pb, 0);
@@ -620,7 +620,7 @@ static int gxf_write_umf_media_description(AVFormatContext *s)
             gxf_write_umf_media_timecode(pb, gxf->tc.drop);
         else {
             AVStream *st = s->streams[i];
-            switch (st->codec->codec_id) {
+            switch (st->codecpar->codec_id) {
             case AV_CODEC_ID_MPEG1VIDEO:
             case AV_CODEC_ID_MPEG2VIDEO:
                 gxf_write_umf_media_mpeg(pb, st);
@@ -722,22 +722,22 @@ static int gxf_write_header(AVFormatContext *s)
             return AVERROR(ENOMEM);
         st->priv_data = sc;
 
-        sc->media_type = ff_codec_get_tag(gxf_media_types, st->codec->codec_id);
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            if (st->codec->codec_id != AV_CODEC_ID_PCM_S16LE) {
+        sc->media_type = ff_codec_get_tag(gxf_media_types, st->codecpar->codec_id);
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE) {
                 av_log(s, AV_LOG_ERROR, "only 16 BIT PCM LE allowed for now\n");
                 return -1;
             }
-            if (st->codec->sample_rate != 48000) {
+            if (st->codecpar->sample_rate != 48000) {
                 av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n");
                 return -1;
             }
-            if (st->codec->channels != 1) {
+            if (st->codecpar->channels != 1) {
                 av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n");
                 return -1;
             }
             sc->track_type = 2;
-            sc->sample_rate = st->codec->sample_rate;
+            sc->sample_rate = st->codecpar->sample_rate;
             avpriv_set_pts_info(st, 64, 1, sc->sample_rate);
             sc->sample_size = 16;
             sc->frame_rate_index = -2;
@@ -746,18 +746,18 @@ static int gxf_write_header(AVFormatContext *s)
             gxf->audio_tracks++;
             gxf->flags |= 0x04000000; /* audio is 16 bit pcm */
             media_info = 'A';
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             if (i != 0) {
                 av_log(s, AV_LOG_ERROR, "video stream must be the first track\n");
                 return -1;
             }
             /* FIXME check from time_base ? */
-            if (st->codec->height == 480 || st->codec->height == 512) { /* NTSC or NTSC+VBI */
+            if (st->codecpar->height == 480 || st->codecpar->height == 512) { /* NTSC or NTSC+VBI */
                 sc->frame_rate_index = 5;
                 sc->sample_rate = 60;
                 gxf->flags |= 0x00000080;
                 gxf->time_base = (AVRational){ 1001, 60000 };
-            } else if (st->codec->height == 576 || st->codec->height == 608) { /* PAL or PAL+VBI */
+            } else if (st->codecpar->height == 576 || st->codecpar->height == 608) { /* PAL or PAL+VBI */
                 sc->frame_rate_index = 6;
                 sc->media_type++;
                 sc->sample_rate = 50;
@@ -773,12 +773,12 @@ static int gxf_write_header(AVFormatContext *s)
             avpriv_set_pts_info(st, 64, gxf->time_base.num, gxf->time_base.den);
             if (gxf_find_lines_index(st) < 0)
                 sc->lines_index = -1;
-            sc->sample_size = st->codec->bit_rate;
+            sc->sample_size = st->codecpar->bit_rate;
             sc->fields = 2; /* interlaced */
 
             vsc = sc;
 
-            switch (st->codec->codec_id) {
+            switch (st->codecpar->codec_id) {
             case AV_CODEC_ID_MJPEG:
                 sc->track_type = 1;
                 gxf->flags |= 0x00004000;
@@ -797,7 +797,7 @@ static int gxf_write_header(AVFormatContext *s)
                 media_info = 'M';
                 break;
             case AV_CODEC_ID_DVVIDEO:
-                if (st->codec->pix_fmt == AV_PIX_FMT_YUV422P) {
+                if (st->codecpar->format == AV_PIX_FMT_YUV422P) {
                     sc->media_type += 2;
                     sc->track_type = 6;
                     gxf->flags |= 0x00002000;
@@ -903,7 +903,7 @@ static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size)
     /* If the video is frame-encoded, the frame numbers shall be represented by
      * even field numbers.
      * see SMPTE360M-2004  6.4.2.1.3 Media field number */
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         field_nb = gxf->nb_fields;
     } else {
         field_nb = av_rescale_rnd(pkt->dts, gxf->time_base.den,
@@ -913,10 +913,10 @@ static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size)
     avio_w8(pb, sc->media_type);
     avio_w8(pb, st->index);
     avio_wb32(pb, field_nb);
-    if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
         avio_wb16(pb, 0);
         avio_wb16(pb, size / 2);
-    } else if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
         int frame_type = gxf_parse_mpeg_frame(sc, pkt->data, pkt->size);
         if (frame_type == AV_PICTURE_TYPE_I) {
             avio_w8(pb, 0x0d);
@@ -929,7 +929,7 @@ static int gxf_write_media_preamble(AVFormatContext *s, AVPacket *pkt, int size)
             sc->pframes++;
         }
         avio_wb24(pb, size);
-    } else if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) {
         avio_w8(pb, size / 4096);
         avio_wb24(pb, 0);
     } else
@@ -951,15 +951,15 @@ static int gxf_write_packet(AVFormatContext *s, AVPacket *pkt)
     int ret;
 
     gxf_write_packet_header(pb, PKT_MEDIA);
-    if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */
+    if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO && pkt->size % 4) /* MPEG-2 frames must be padded */
         padding = 4 - pkt->size % 4;
-    else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+    else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
         padding = GXF_AUDIO_PACKET_SIZE - pkt->size;
     gxf_write_media_preamble(s, pkt, pkt->size + padding);
     avio_write(pb, pkt->data, pkt->size);
     gxf_write_padding(pb, padding);
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         if (!(gxf->flt_entries_nb % 500)) {
             int err;
             if ((err = av_reallocp_array(&gxf->flt_entries,
@@ -997,7 +997,7 @@ static int gxf_compare_field_nb(AVFormatContext *s, AVPacket *next, AVPacket *cu
     for (i = 0; i < 2; i++) {
         AVStream *st = s->streams[pkt[i]->stream_index];
         sc[i] = st->priv_data;
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             field_nb[i] = av_rescale_rnd(pkt[i]->dts, gxf->time_base.den,
                                          (int64_t)48000*gxf->time_base.num, AV_ROUND_UP);
             field_nb[i] &= ~1; // compare against even field number because audio must be before video
@@ -1011,7 +1011,7 @@ static int gxf_compare_field_nb(AVFormatContext *s, AVPacket *next, AVPacket *cu
 
 static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
 {
-    if (pkt && s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+    if (pkt && s->streams[pkt->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
         pkt->duration = 2; // enforce 2 fields
     return ff_audio_rechunk_interleave(s, out, pkt, flush,
                                ff_interleave_packet_per_dts, gxf_compare_field_nb);
diff --git a/libavformat/h264dec.c b/libavformat/h264dec.c
index d1d37ca..85d7163 100644
--- a/libavformat/h264dec.c
+++ b/libavformat/h264dec.c
@@ -19,17 +19,26 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavcodec/get_bits.h"
+#include "libavcodec/golomb.h"
 #include "avformat.h"
 #include "rawdec.h"
 #include "libavcodec/internal.h"
 
+#define MAX_SPS_COUNT          32
+#define MAX_PPS_COUNT         256
+
 static int h264_probe(AVProbeData *p)
 {
     uint32_t code = -1;
     int sps = 0, pps = 0, idr = 0, res = 0, sli = 0;
-    int i;
+    int i, ret;
+    int pps_ids[MAX_PPS_COUNT+1] = {0};
+    int sps_ids[MAX_SPS_COUNT+1] = {0};
+    unsigned pps_id, sps_id;
+    GetBitContext gb;
 
-    for (i = 0; i < p->buf_size; i++) {
+    for (i = 0; i + 2 < p->buf_size; i++) {
         code = (code << 8) + p->buf[i];
         if ((code & 0xffffff00) == 0x100) {
             int ref_idc = (code >> 5) & 3;
@@ -53,19 +62,48 @@ static int h264_probe(AVProbeData *p)
                     res++;
             }
 
+            ret = init_get_bits8(&gb, p->buf + i + 1, p->buf_size - i - 1);
+            if (ret < 0)
+                return 0;
+
             switch (type) {
             case 1:
-                sli++;
-                break;
             case 5:
-                idr++;
+                get_ue_golomb_long(&gb);
+                if (get_ue_golomb_long(&gb) > 9U)
+                    return 0;
+                pps_id = get_ue_golomb_long(&gb);
+                if (pps_id > MAX_PPS_COUNT)
+                    return 0;
+                if (!pps_ids[pps_id])
+                    break;
+
+                if (type == 1)
+                    sli++;
+                else
+                    idr++;
                 break;
             case 7:
-                if (p->buf[i + 2] & 0x03)
+                skip_bits(&gb, 14);
+                if (get_bits(&gb, 2))
+                    return 0;
+                skip_bits(&gb, 8);
+                sps_id = get_ue_golomb_long(&gb);
+                if (sps_id > MAX_SPS_COUNT)
                     return 0;
+                sps_ids[sps_id] = 1;
                 sps++;
                 break;
             case 8:
+                pps_id = get_ue_golomb_long(&gb);
+                if (pps_id > MAX_PPS_COUNT)
+                    return 0;
+                sps_id = get_ue_golomb_long(&gb);
+                if (sps_id > MAX_SPS_COUNT)
+                    return 0;
+                if (!sps_ids[sps_id])
+                    break;
+                pps_ids[pps_id] = 1;
                 pps++;
                 break;
             }
diff --git a/libavformat/hashenc.c b/libavformat/hashenc.c
new file mode 100644
index 0000000..a66db4a
--- /dev/null
+++ b/libavformat/hashenc.c
@@ -0,0 +1,262 @@
+/*
+ * Hash/MD5 encoder (for codec/format testing)
+ * Copyright (c) 2009 Reimar Döffinger, based on crcenc (c) 2002 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
+#include "libavutil/hash.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
+#include "avformat.h"
+#include "internal.h"
+
+struct HashContext {
+    const AVClass *avclass;
+    struct AVHashContext *hash;
+    char *hash_name;
+    int format_version;
+};
+
+#define OFFSET(x) offsetof(struct HashContext, x)
+#define ENC AV_OPT_FLAG_ENCODING_PARAM
+#if CONFIG_HASH_MUXER || CONFIG_FRAMEHASH_MUXER
+static const AVOption hash_options[] = {
+    { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "sha256"}, 0, 0, ENC },
+    { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC },
+    { NULL },
+};
+#endif
+
+#if CONFIG_MD5_MUXER || CONFIG_FRAMEMD5_MUXER
+static const AVOption md5_options[] = {
+    { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "md5"}, 0, 0, ENC },
+    { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 2}, 1, 2, ENC },
+    { NULL },
+};
+#endif
+
+#if CONFIG_HASH_MUXER || CONFIG_MD5_MUXER
+static int hash_write_header(struct AVFormatContext *s)
+{
+    struct HashContext *c = s->priv_data;
+    int res = av_hash_alloc(&c->hash, c->hash_name);
+    if (res < 0)
+        return res;
+    av_hash_init(c->hash);
+    return 0;
+}
+
+static int hash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+    struct HashContext *c = s->priv_data;
+    av_hash_update(c->hash, pkt->data, pkt->size);
+    return 0;
+}
+
+static int hash_write_trailer(struct AVFormatContext *s)
+{
+    struct HashContext *c = s->priv_data;
+    char buf[AV_HASH_MAX_SIZE*2+128];
+    snprintf(buf, sizeof(buf) - 200, "%s=", av_hash_get_name(c->hash));
+
+    av_hash_final_hex(c->hash, buf + strlen(buf), sizeof(buf) - strlen(buf));
+    av_strlcatf(buf, sizeof(buf), "\n");
+    avio_write(s->pb, buf, strlen(buf));
+    avio_flush(s->pb);
+
+    av_hash_freep(&c->hash);
+    return 0;
+}
+#endif
+
+#if CONFIG_HASH_MUXER
+static const AVClass hashenc_class = {
+    .class_name = "hash encoder class",
+    .item_name  = av_default_item_name,
+    .option     = hash_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVOutputFormat ff_hash_muxer = {
+    .name              = "hash",
+    .long_name         = NULL_IF_CONFIG_SMALL("Hash testing"),
+    .priv_data_size    = sizeof(struct HashContext),
+    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
+    .video_codec       = AV_CODEC_ID_RAWVIDEO,
+    .write_header      = hash_write_header,
+    .write_packet      = hash_write_packet,
+    .write_trailer     = hash_write_trailer,
+    .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
+                         AVFMT_TS_NEGATIVE,
+    .priv_class        = &hashenc_class,
+};
+#endif
+
+#if CONFIG_MD5_MUXER
+static const AVClass md5enc_class = {
+    .class_name = "MD5 encoder class",
+    .item_name  = av_default_item_name,
+    .option     = md5_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVOutputFormat ff_md5_muxer = {
+    .name              = "md5",
+    .long_name         = NULL_IF_CONFIG_SMALL("MD5 testing"),
+    .priv_data_size    = sizeof(struct HashContext),
+    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
+    .video_codec       = AV_CODEC_ID_RAWVIDEO,
+    .write_header      = hash_write_header,
+    .write_packet      = hash_write_packet,
+    .write_trailer     = hash_write_trailer,
+    .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
+                         AVFMT_TS_NEGATIVE,
+    .priv_class        = &md5enc_class,
+};
+#endif
+
+#if CONFIG_FRAMEHASH_MUXER || CONFIG_FRAMEMD5_MUXER
+static void framehash_print_extradata(struct AVFormatContext *s)
+{
+    int i;
+
+    for (i = 0; i < s->nb_streams; i++) {
+        AVStream *st = s->streams[i];
+        AVCodecParameters *par = st->codecpar;
+        if (par->extradata) {
+            struct HashContext *c = s->priv_data;
+            char buf[AV_HASH_MAX_SIZE*2+1];
+
+            avio_printf(s->pb, "#extradata %d, %31d, ", i, par->extradata_size);
+            av_hash_init(c->hash);
+            av_hash_update(c->hash, par->extradata, par->extradata_size);
+            av_hash_final_hex(c->hash, buf, sizeof(buf));
+            avio_write(s->pb, buf, strlen(buf));
+            avio_printf(s->pb, "\n");
+        }
+    }
+}
+
+static int framehash_write_header(struct AVFormatContext *s)
+{
+    struct HashContext *c = s->priv_data;
+    int res = av_hash_alloc(&c->hash, c->hash_name);
+    if (res < 0)
+        return res;
+    avio_printf(s->pb, "#format: frame checksums\n");
+    avio_printf(s->pb, "#version: %d\n", c->format_version);
+    avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hash));
+    framehash_print_extradata(s);
+    ff_framehash_write_header(s);
+    avio_printf(s->pb, "#stream#, dts,        pts, duration,     size, hash\n");
+    return 0;
+}
+
+static int framehash_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+{
+    struct HashContext *c = s->priv_data;
+    char buf[AV_HASH_MAX_SIZE*2+128];
+    int len;
+    av_hash_init(c->hash);
+    av_hash_update(c->hash, pkt->data, pkt->size);
+
+    snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ",
+             pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size);
+    len = strlen(buf);
+    av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len);
+    avio_write(s->pb, buf, strlen(buf));
+
+    if (c->format_version > 1 && pkt->side_data_elems) {
+        int i, j;
+        avio_printf(s->pb, ", S=%d", pkt->side_data_elems);
+        for (i = 0; i < pkt->side_data_elems; i++) {
+            av_hash_init(c->hash);
+            if (HAVE_BIGENDIAN && pkt->side_data[i].type == AV_PKT_DATA_PALETTE) {
+                for (j = 0; j < pkt->side_data[i].size; j += sizeof(uint32_t)) {
+                    uint32_t data = AV_RL32(pkt->side_data[i].data + j);
+                    av_hash_update(c->hash, (uint8_t *)&data, sizeof(uint32_t));
+                }
+            } else
+                av_hash_update(c->hash, pkt->side_data[i].data, pkt->side_data[i].size);
+            snprintf(buf, sizeof(buf) - (AV_HASH_MAX_SIZE * 2 + 1), ", %8d, ", pkt->side_data[i].size);
+            len = strlen(buf);
+            av_hash_final_hex(c->hash, buf + len, sizeof(buf) - len);
+            avio_write(s->pb, buf, strlen(buf));
+        }
+    }
+
+    avio_printf(s->pb, "\n");
+    avio_flush(s->pb);
+    return 0;
+}
+
+static int framehash_write_trailer(struct AVFormatContext *s)
+{
+    struct HashContext *c = s->priv_data;
+    av_hash_freep(&c->hash);
+    return 0;
+}
+#endif
+
+#if CONFIG_FRAMEHASH_MUXER
+static const AVClass framehash_class = {
+    .class_name = "frame hash encoder class",
+    .item_name  = av_default_item_name,
+    .option     = hash_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVOutputFormat ff_framehash_muxer = {
+    .name              = "framehash",
+    .long_name         = NULL_IF_CONFIG_SMALL("Per-frame hash testing"),
+    .priv_data_size    = sizeof(struct HashContext),
+    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
+    .video_codec       = AV_CODEC_ID_RAWVIDEO,
+    .write_header      = framehash_write_header,
+    .write_packet      = framehash_write_packet,
+    .write_trailer     = framehash_write_trailer,
+    .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
+                         AVFMT_TS_NEGATIVE,
+    .priv_class        = &framehash_class,
+};
+#endif
+
+#if CONFIG_FRAMEMD5_MUXER
+static const AVClass framemd5_class = {
+    .class_name = "frame hash encoder class",
+    .item_name  = av_default_item_name,
+    .option     = md5_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVOutputFormat ff_framemd5_muxer = {
+    .name              = "framemd5",
+    .long_name         = NULL_IF_CONFIG_SMALL("Per-frame MD5 testing"),
+    .priv_data_size    = sizeof(struct HashContext),
+    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
+    .video_codec       = AV_CODEC_ID_RAWVIDEO,
+    .write_header      = framehash_write_header,
+    .write_packet      = framehash_write_packet,
+    .write_trailer     = framehash_write_trailer,
+    .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
+                         AVFMT_TS_NEGATIVE,
+    .priv_class        = &framemd5_class,
+};
+#endif
diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c
index 3e6e821..347df83 100644
--- a/libavformat/hdsenc.c
+++ b/libavformat/hdsenc.c
@@ -340,18 +340,18 @@ static int hds_write_header(AVFormatContext *s)
         AVFormatContext *ctx;
         AVStream *st = s->streams[i];
 
-        if (!st->codec->bit_rate) {
+        if (!st->codecpar->bit_rate) {
             av_log(s, AV_LOG_ERROR, "No bit rate set for stream %d\n", i);
             ret = AVERROR(EINVAL);
             goto fail;
         }
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             if (os->has_video) {
                 c->nb_streams++;
                 os++;
             }
             os->has_video = 1;
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             if (os->has_audio) {
                 c->nb_streams++;
                 os++;
@@ -362,7 +362,7 @@ static int hds_write_header(AVFormatContext *s)
             ret = AVERROR(EINVAL);
             goto fail;
         }
-        os->bitrate += s->streams[i]->codec->bit_rate;
+        os->bitrate += s->streams[i]->codecpar->bit_rate;
 
         if (!os->ctx) {
             os->first_stream = i;
@@ -374,6 +374,7 @@ static int hds_write_header(AVFormatContext *s)
             os->ctx = ctx;
             ctx->oformat = oformat;
             ctx->interrupt_callback = s->interrupt_callback;
+            ctx->flags = s->flags;
 
             ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf),
                                          AVIO_FLAG_WRITE, os,
@@ -391,8 +392,8 @@ static int hds_write_header(AVFormatContext *s)
             ret = AVERROR(ENOMEM);
             goto fail;
         }
-        avcodec_copy_context(st->codec, s->streams[i]->codec);
-        st->codec->codec_tag = 0;
+        avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
+        st->codecpar->codec_tag = 0;
         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
         st->time_base = s->streams[i]->time_base;
     }
@@ -519,7 +520,7 @@ static int hds_write_packet(AVFormatContext *s, AVPacket *pkt)
     if (st->first_dts == AV_NOPTS_VALUE)
         st->first_dts = pkt->dts;
 
-    if ((!os->has_video || st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
+    if ((!os->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
         av_compare_ts(pkt->dts - st->first_dts, st->time_base,
                       end_dts, AV_TIME_BASE_Q) >= 0 &&
         pkt->flags & AV_PKT_FLAG_KEY && os->packets_written) {
diff --git a/libavformat/hls.c b/libavformat/hls.c
index fc1ff38..b962d67 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -36,7 +36,6 @@
 #include "avformat.h"
 #include "internal.h"
 #include "avio_internal.h"
-#include "url.h"
 #include "id3v2.h"
 
 #define INITIAL_BUFFER_SIZE 32768
@@ -94,7 +93,7 @@ struct playlist {
     char url[MAX_URL_SIZE];
     AVIOContext pb;
     uint8_t* read_buffer;
-    URLContext *input;
+    AVIOContext *input;
     AVFormatContext *parent;
     int index;
     AVFormatContext *ctx;
@@ -248,7 +247,7 @@ static void free_playlist_list(HLSContext *c)
         av_packet_unref(&pls->pkt);
         av_freep(&pls->pb.buffer);
         if (pls->input)
-            ffurl_close(pls->input);
+            ff_format_io_close(c->ctx, &pls->input);
         if (pls->ctx) {
             pls->ctx->pb = NULL;
             avformat_close_input(&pls->ctx);
@@ -582,44 +581,32 @@ static int ensure_playlist(HLSContext *c, struct playlist **pls, const char *url
     return 0;
 }
 
-static int url_connect(struct playlist *pls, AVDictionary *opts, AVDictionary *opts2)
-{
-    AVDictionary *tmp = NULL;
-    int ret;
-
-    av_dict_copy(&tmp, opts, 0);
-    av_dict_copy(&tmp, opts2, 0);
-
-    if (pls->parent->protocol_whitelist) {
-        pls->input->protocol_whitelist =  av_strdup(pls->parent->protocol_whitelist);
-        if (!pls->input->protocol_whitelist) {
-            av_dict_free(&tmp);
-            return AVERROR(ENOMEM);
-        }
-    }
-
-    if ((ret = ffurl_connect(pls->input, &tmp)) < 0) {
-        ffurl_close(pls->input);
-        pls->input = NULL;
-    }
-
-    av_dict_free(&tmp);
-    return ret;
-}
-
 static void update_options(char **dest, const char *name, void *src)
 {
     av_freep(dest);
-    av_opt_get(src, name, 0, (uint8_t**)dest);
+    av_opt_get(src, name, AV_OPT_SEARCH_CHILDREN, (uint8_t**)dest);
     if (*dest && !strlen(*dest))
         av_freep(dest);
 }
 
-static int open_url(HLSContext *c, URLContext **uc, const char *url, AVDictionary *opts)
+static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url,
+                    AVDictionary *opts, AVDictionary *opts2)
 {
+    HLSContext *c = s->priv_data;
     AVDictionary *tmp = NULL;
+    const char *proto_name = NULL;
     int ret;
-    const char *proto_name = avio_find_protocol_name(url);
+
+    av_dict_copy(&tmp, opts, 0);
+    av_dict_copy(&tmp, opts2, 0);
+
+    if (av_strstart(url, "crypto", NULL)) {
+        if (url[6] == '+' || url[6] == ':')
+            proto_name = avio_find_protocol_name(url + 7);
+    }
+
+    if (!proto_name)
+        proto_name = avio_find_protocol_name(url);
 
     if (!proto_name)
         return AVERROR_INVALIDDATA;
@@ -629,17 +616,16 @@ static int open_url(HLSContext *c, URLContext **uc, const char *url, AVDictionar
         return AVERROR_INVALIDDATA;
     if (!strncmp(proto_name, url, strlen(proto_name)) && url[strlen(proto_name)] == ':')
         ;
+    else if (av_strstart(url, "crypto", NULL) && !strncmp(proto_name, url + 7, strlen(proto_name)) && url[7 + strlen(proto_name)] == ':')
+        ;
     else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5))
         return AVERROR_INVALIDDATA;
 
-    av_dict_copy(&tmp, c->avio_opts, 0);
-    av_dict_copy(&tmp, opts, 0);
-
-    ret = ffurl_open_whitelist(uc, url, AVIO_FLAG_READ, c->interrupt_callback, &tmp, c->ctx->protocol_whitelist);
-    if( ret >= 0) {
+    ret = s->io_open(s, pb, url, AVIO_FLAG_READ, &tmp);
+    if (ret >= 0) {
         // update cookies on http response with setcookies.
-        URLContext *u = *uc;
-        update_options(&c->cookies, "cookies", u->priv_data);
+        void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
+        update_options(&c->cookies, "cookies", u);
         av_dict_set(&opts, "cookies", c->cookies, 0);
     }
 
@@ -862,7 +848,6 @@ enum ReadFromURLMode {
     READ_COMPLETE,
 };
 
-/* read from URLContext, limiting read to current segment */
 static int read_from_url(struct playlist *pls, struct segment *seg,
                          uint8_t *buf, int buf_size,
                          enum ReadFromURLMode mode)
@@ -873,10 +858,12 @@ static int read_from_url(struct playlist *pls, struct segment *seg,
     if (seg->size >= 0)
         buf_size = FFMIN(buf_size, seg->size - pls->cur_seg_offset);
 
-    if (mode == READ_COMPLETE)
-        ret = ffurl_read_complete(pls->input, buf, buf_size);
-    else
-        ret = ffurl_read(pls->input, buf, buf_size);
+    if (mode == READ_COMPLETE) {
+        ret = avio_read(pls->input, buf, buf_size);
+        if (ret != buf_size)
+            av_log(NULL, AV_LOG_ERROR, "Could not read complete segment.\n");
+    } else
+        ret = avio_read(pls->input, buf, buf_size);
 
     if (ret > 0)
         pls->cur_seg_offset += ret;
@@ -981,7 +968,6 @@ static void handle_id3(AVIOContext *pb, struct playlist *pls)
         ff_id3v2_free_extra_meta(&extra_meta);
 }
 
-/* Intercept and handle ID3 tags between URLContext and AVIOContext */
 static void intercept_id3(struct playlist *pls, uint8_t *buf,
                          int buf_size, int *len)
 {
@@ -1105,19 +1091,19 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg)
            seg->url, seg->url_offset, pls->index);
 
     if (seg->key_type == KEY_NONE) {
-        ret = open_url(pls->parent->priv_data, &pls->input, seg->url, opts);
+        ret = open_url(pls->parent, &pls->input, seg->url, c->avio_opts, opts);
     } else if (seg->key_type == KEY_AES_128) {
-//         HLSContext *c = var->parent->priv_data;
+        AVDictionary *opts2 = NULL;
         char iv[33], key[33], url[MAX_URL_SIZE];
         if (strcmp(seg->key, pls->key_url)) {
-            URLContext *uc;
-            if (open_url(pls->parent->priv_data, &uc, seg->key, opts) == 0) {
-                if (ffurl_read_complete(uc, pls->key, sizeof(pls->key))
-                    != sizeof(pls->key)) {
+            AVIOContext *pb;
+            if (open_url(pls->parent, &pb, seg->key, c->avio_opts, opts) == 0) {
+                ret = avio_read(pb, pls->key, sizeof(pls->key));
+                if (ret != sizeof(pls->key)) {
                     av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n",
                            seg->key);
                 }
-                ffurl_close(uc);
+                ff_format_io_close(pls->parent, &pb);
             } else {
                 av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n",
                        seg->key);
@@ -1132,13 +1118,15 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg)
         else
             snprintf(url, sizeof(url), "crypto:%s", seg->url);
 
-        if ((ret = ffurl_alloc(&pls->input, url, AVIO_FLAG_READ,
-                               &pls->parent->interrupt_callback)) < 0)
-            goto cleanup;
-        av_opt_set(pls->input->priv_data, "key", key, 0);
-        av_opt_set(pls->input->priv_data, "iv", iv, 0);
+        av_dict_copy(&opts2, c->avio_opts, 0);
+        av_dict_set(&opts2, "key", key, 0);
+        av_dict_set(&opts2, "iv", iv, 0);
+
+        ret = open_url(pls->parent, &pls->input, url, opts2, opts);
+
+        av_dict_free(&opts2);
 
-        if ((ret = url_connect(pls, c->avio_opts, opts)) < 0) {
+        if (ret < 0) {
             goto cleanup;
         }
         ret = 0;
@@ -1154,12 +1142,11 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg)
      * should already be where want it to, but this allows e.g. local testing
      * without a HTTP server. */
     if (ret == 0 && seg->key_type == KEY_NONE && seg->url_offset) {
-        int seekret = ffurl_seek(pls->input, seg->url_offset, SEEK_SET);
+        int64_t seekret = avio_seek(pls->input, seg->url_offset, SEEK_SET);
         if (seekret < 0) {
             av_log(pls->parent, AV_LOG_ERROR, "Unable to seek to offset %"PRId64" of HLS segment '%s'\n", seg->url_offset, seg->url);
             ret = seekret;
-            ffurl_close(pls->input);
-            pls->input = NULL;
+            ff_format_io_close(pls->parent, &pls->input);
         }
     }
 
@@ -1185,8 +1172,6 @@ static int update_init_section(struct playlist *pls, struct segment *seg)
     if (!seg->init_section)
         return 0;
 
-    /* this will clobber playlist URLContext stuff, so this should be
-     * called between segments only */
     ret = open_input(c, pls, seg->init_section);
     if (ret < 0) {
         av_log(pls->parent, AV_LOG_WARNING,
@@ -1197,7 +1182,7 @@ static int update_init_section(struct playlist *pls, struct segment *seg)
 
     if (seg->init_section->size >= 0)
         sec_size = seg->init_section->size;
-    else if ((urlsize = ffurl_size(pls->input)) >= 0)
+    else if ((urlsize = avio_size(pls->input)) >= 0)
         sec_size = urlsize;
     else
         sec_size = max_init_section_size;
@@ -1212,8 +1197,7 @@ static int update_init_section(struct playlist *pls, struct segment *seg)
 
     ret = read_from_url(pls, seg->init_section, pls->init_sec_buf,
                         pls->init_sec_buf_size, READ_COMPLETE);
-    ffurl_close(pls->input);
-    pls->input = NULL;
+    ff_format_io_close(pls->parent, &pls->input);
 
     if (ret < 0)
         return ret;
@@ -1340,8 +1324,7 @@ reload:
 
         return ret;
     }
-    ffurl_close(v->input);
-    v->input = NULL;
+    ff_format_io_close(v->parent, &v->input);
     v->cur_seq_no++;
 
     c->cur_seq_no = v->cur_seq_no;
@@ -1401,7 +1384,7 @@ static void add_metadata_from_renditions(AVFormatContext *s, struct playlist *pl
     for (i = 0; i < pls->ctx->nb_streams; i++) {
         AVStream *st = s->streams[pls->stream_offset + i];
 
-        if (st->codec->codec_type != type)
+        if (st->codecpar->codec_type != type)
             continue;
 
         for (; rend_idx < pls->n_renditions; rend_idx++) {
@@ -1492,7 +1475,7 @@ static int select_cur_seq_no(HLSContext *c, struct playlist *pls)
 static int save_avio_options(AVFormatContext *s)
 {
     HLSContext *c = s->priv_data;
-    const char *opts[] = {
+    static const char *opts[] = {
         "headers", "http_proxy", "user_agent", "user-agent", "cookies", NULL };
     const char **opt = opts;
     uint8_t *buf;
@@ -1511,9 +1494,19 @@ static int save_avio_options(AVFormatContext *s)
     return ret;
 }
 
+static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url,
+                          int flags, AVDictionary **opts)
+{
+    av_log(s, AV_LOG_ERROR,
+           "A HLS playlist item '%s' referred to an external file '%s'. "
+           "Opening this file was forbidden for security reasons\n",
+           s->filename, url);
+    return AVERROR(EPERM);
+}
+
 static int hls_read_header(AVFormatContext *s)
 {
-    URLContext *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb->opaque;
+    void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
     HLSContext *c = s->priv_data;
     int ret = 0, i, j, stream_offset = 0;
 
@@ -1525,19 +1518,18 @@ static int hls_read_header(AVFormatContext *s)
     c->first_timestamp = AV_NOPTS_VALUE;
     c->cur_timestamp = AV_NOPTS_VALUE;
 
-    // if the URL context is good, read important options we must broker later
-    if (u && u->prot->priv_data_class) {
+    if (u) {
         // get the previous user agent & set back to null if string size is zero
-        update_options(&c->user_agent, "user-agent", u->priv_data);
+        update_options(&c->user_agent, "user-agent", u);
 
         // get the previous cookies & set back to null if string size is zero
-        update_options(&c->cookies, "cookies", u->priv_data);
+        update_options(&c->cookies, "cookies", u);
 
         // get the previous headers & set back to null if string size is zero
-        update_options(&c->headers, "headers", u->priv_data);
+        update_options(&c->headers, "headers", u);
 
         // get the previous http proxt & set back to null if string size is zero
-        update_options(&c->http_proxy, "http_proxy", u->priv_data);
+        update_options(&c->http_proxy, "http_proxy", u);
     }
 
     if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0)
@@ -1632,9 +1624,10 @@ static int hls_read_header(AVFormatContext *s)
             goto fail;
         }
         pls->ctx->pb       = &pls->pb;
+        pls->ctx->io_open  = nested_io_open;
         pls->stream_offset = stream_offset;
 
-        if ((ret = ff_copy_whitelists(pls->ctx, s)) < 0)
+        if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
             goto fail;
 
         ret = avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL);
@@ -1666,7 +1659,7 @@ static int hls_read_header(AVFormatContext *s)
             }
             st->id = i;
 
-            avcodec_copy_context(st->codec, pls->ctx->streams[j]->codec);
+            avcodec_parameters_copy(st->codecpar, pls->ctx->streams[j]->codecpar);
 
             if (pls->is_id3_timestamped) /* custom timestamps via id3 */
                 avpriv_set_pts_info(st, 33, 1, MPEG_TIME_BASE);
@@ -1747,8 +1740,7 @@ static int recheck_discard_flags(AVFormatContext *s, int first)
             av_log(s, AV_LOG_INFO, "Now receiving playlist %d, segment %d\n", i, pls->cur_seq_no);
         } else if (first && !pls->cur_needed && pls->needed) {
             if (pls->input)
-                ffurl_close(pls->input);
-            pls->input = NULL;
+                ff_format_io_close(pls->parent, &pls->input);
             pls->needed = 0;
             changed = 1;
             av_log(s, AV_LOG_INFO, "No longer receiving playlist %d\n", i);
@@ -1953,10 +1945,8 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
     for (i = 0; i < c->n_playlists; i++) {
         /* Reset reading */
         struct playlist *pls = c->playlists[i];
-        if (pls->input) {
-            ffurl_close(pls->input);
-            pls->input = NULL;
-        }
+        if (pls->input)
+            ff_format_io_close(pls->parent, &pls->input);
         av_packet_unref(&pls->pkt);
         reset_packet(&pls->pkt);
         pls->pb.eof_reached = 0;
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 85a0907..a9fa5d8 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -64,6 +64,13 @@ typedef enum HLSFlags {
     HLS_OMIT_ENDLIST = (1 << 4),
 } HLSFlags;
 
+typedef enum {
+    PLAYLIST_TYPE_NONE,
+    PLAYLIST_TYPE_EVENT,
+    PLAYLIST_TYPE_VOD,
+    PLAYLIST_TYPE_NB,
+} PlaylistType;
+
 typedef struct HLSContext {
     const AVClass *class;  // Class for private options.
     unsigned number;
@@ -79,9 +86,11 @@ typedef struct HLSContext {
     int max_nb_segments;   // Set by a private option.
     int  wrap;             // Set by a private option.
     uint32_t flags;        // enum HLSFlags
+    uint32_t pl_type;      // enum PlaylistType
     char *segment_filename;
 
     int use_localtime;      ///< flag to expand filename with localtime
+    int use_localtime_mkdir;///< flag to mkdir dirname in timebased filename
     int allowcache;
     int64_t recording_time;
     int has_video;
@@ -287,14 +296,14 @@ static int hls_mux_init(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st;
         AVFormatContext *loc;
-        if (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
+        if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE)
             loc = vtt_oc;
         else
             loc = oc;
 
         if (!(st = avformat_new_stream(loc, NULL)))
             return AVERROR(ENOMEM);
-        avcodec_copy_context(st->codec, s->streams[i]->codec);
+        avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
         st->time_base = s->streams[i]->time_base;
     }
@@ -304,16 +313,35 @@ static int hls_mux_init(AVFormatContext *s)
 }
 
 /* Create a new segment and append it to the segment list */
-static int hls_append_segment(HLSContext *hls, double duration, int64_t pos,
-                              int64_t size)
+static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double duration,
+                              int64_t pos, int64_t size)
 {
     HLSSegment *en = av_malloc(sizeof(*en));
+    char *tmp, *p;
+    const char *pl_dir, *filename;
     int ret;
 
     if (!en)
         return AVERROR(ENOMEM);
 
-    av_strlcpy(en->filename, av_basename(hls->avf->filename), sizeof(en->filename));
+    filename = av_basename(hls->avf->filename);
+
+    if (hls->use_localtime_mkdir) {
+        /* Possibly prefix with mkdir'ed subdir, if playlist share same
+         * base path. */
+        tmp = av_strdup(s->filename);
+        if (!tmp) {
+            av_free(en);
+            return AVERROR(ENOMEM);
+        }
+
+        pl_dir = av_dirname(tmp);
+        p = hls->avf->filename;
+        if (strstr(p, pl_dir) == p)
+            filename = hls->avf->filename + strlen(pl_dir) + 1;
+        av_free(tmp);
+    }
+    av_strlcpy(en->filename, filename, sizeof(en->filename));
 
     if(hls->has_subtitle)
         av_strlcpy(en->sub_filename, av_basename(hls->vtt_avf->filename), sizeof(en->sub_filename));
@@ -337,6 +365,10 @@ static int hls_append_segment(HLSContext *hls, double duration, int64_t pos,
 
     hls->last_segment = en;
 
+    // EVENT or VOD playlists imply sliding window cannot be used
+    if (hls->pl_type != PLAYLIST_TYPE_NONE)
+        hls->max_nb_segments = 0;
+
     if (hls->max_nb_segments && hls->nb_entries >= hls->max_nb_segments) {
         en = hls->segments;
         hls->segments = en->next;
@@ -412,6 +444,11 @@ static int hls_window(AVFormatContext *s, int last)
     }
     avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
     avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
+    if (hls->pl_type == PLAYLIST_TYPE_EVENT) {
+        avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
+    } else if (hls->pl_type == PLAYLIST_TYPE_VOD) {
+        avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
+    }
 
     av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n",
            sequence);
@@ -508,7 +545,22 @@ static int hls_start(AVFormatContext *s)
                 av_log(oc, AV_LOG_ERROR, "Could not get segment filename with use_localtime\n");
                 return AVERROR(EINVAL);
             }
-       } else if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
+
+            if (c->use_localtime_mkdir) {
+                const char *dir;
+                char *fn_copy = av_strdup(oc->filename);
+                if (!fn_copy) {
+                    return AVERROR(ENOMEM);
+                }
+                dir = av_dirname(fn_copy);
+                if (mkdir(dir, 0777) == -1 && errno != EEXIST) {
+                    av_log(oc, AV_LOG_ERROR, "Could not create directory %s with use_localtime_mkdir\n", dir);
+                    av_free(fn_copy);
+                    return AVERROR(errno);
+                }
+                av_free(fn_copy);
+            }
+        } else if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
                                   c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0) {
             av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try use -use_localtime 1 with it\n", c->basename);
             return AVERROR(EINVAL);
@@ -607,9 +659,9 @@ static int hls_write_header(AVFormatContext *s)
 
     for (i = 0; i < s->nb_streams; i++) {
         hls->has_video +=
-            s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO;
+            s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
         hls->has_subtitle +=
-            s->streams[i]->codec->codec_type == AVMEDIA_TYPE_SUBTITLE;
+            s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE;
     }
 
     if (hls->has_video > 1)
@@ -711,7 +763,7 @@ static int hls_write_header(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *inner_st;
         AVStream *outer_st = s->streams[i];
-        if (outer_st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)
+        if (outer_st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
             inner_st = hls->avf->streams[i];
         else if (hls->vtt_avf)
             inner_st = hls->vtt_avf->streams[0];
@@ -747,7 +799,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
     int ret, can_split = 1;
     int stream_index = 0;
 
-    if( st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
+    if( st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE ) {
         oc = hls->vtt_avf;
         stream_index = 0;
     } else {
@@ -760,9 +812,9 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
     }
 
     if (hls->has_video) {
-        can_split = st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+        can_split = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
                     pkt->flags & AV_PKT_FLAG_KEY;
-        is_ref_pkt = st->codec->codec_type == AVMEDIA_TYPE_VIDEO;
+        is_ref_pkt = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
     }
     if (pkt->pts == AV_NOPTS_VALUE)
         is_ref_pkt = can_split = 0;
@@ -778,7 +830,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
 
         new_start_pos = avio_tell(hls->avf->pb);
         hls->size = new_start_pos - hls->start_pos;
-        ret = hls_append_segment(hls, hls->duration, hls->start_pos, hls->size);
+        ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);
         hls->start_pos = new_start_pos;
         if (ret < 0)
             return ret;
@@ -801,7 +853,7 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
         if (ret < 0)
             return ret;
 
-        if( st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE )
+        if( st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE )
             oc = hls->vtt_avf;
         else
         oc = hls->avf;
@@ -825,7 +877,7 @@ static int hls_write_trailer(struct AVFormatContext *s)
     if (oc->pb) {
         hls->size = avio_tell(hls->avf->pb) - hls->start_pos;
         ff_format_io_close(s, &oc->pb);
-        hls_append_segment(hls, hls->duration, hls->start_pos, hls->size);
+        hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);
     }
 
     if (vtt_oc) {
@@ -871,7 +923,11 @@ static const AVOption options[] = {
     {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX,   E, "flags"},
     {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX,   E, "flags"},
     {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"},
-    { "use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
+    {"use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
+    {"use_localtime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
+    {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, "pl_type" },
+    {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, "pl_type" },
+    {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, "pl_type" },
     {"method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
 
     { NULL },
diff --git a/libavformat/hlsproto.c b/libavformat/hlsproto.c
index b8f2f37..2b19ed0 100644
--- a/libavformat/hlsproto.c
+++ b/libavformat/hlsproto.c
@@ -119,7 +119,7 @@ static int parse_playlist(URLContext *h, const char *url)
 
     if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
                                    &h->interrupt_callback, NULL,
-                                   h->protocol_whitelist)) < 0)
+                                   h->protocol_whitelist, h->protocol_blacklist)) < 0)
         return ret;
 
     read_chomp_line(in, line, sizeof(line));
@@ -307,7 +307,7 @@ retry:
     av_log(h, AV_LOG_DEBUG, "opening %s\n", url);
     ret = ffurl_open_whitelist(&s->seg_hd, url, AVIO_FLAG_READ,
                                &h->interrupt_callback, NULL,
-                               h->protocol_whitelist);
+                               h->protocol_whitelist, h->protocol_blacklist, h);
     if (ret < 0) {
         if (ff_check_interrupt(&h->interrupt_callback))
             return AVERROR_EXIT;
@@ -318,7 +318,7 @@ retry:
     goto start;
 }
 
-URLProtocol ff_hls_protocol = {
+const URLProtocol ff_hls_protocol = {
     .name           = "hls",
     .url_open       = hls_open,
     .url_read       = hls_read,
diff --git a/libavformat/hnm.c b/libavformat/hnm.c
index 8bd8097..24d4e80 100644
--- a/libavformat/hnm.c
+++ b/libavformat/hnm.c
@@ -108,15 +108,15 @@ static int hnm_read_header(AVFormatContext *s)
     if (!(vst = avformat_new_stream(s, NULL)))
         return AVERROR(ENOMEM);
 
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_id   = AV_CODEC_ID_HNM4_VIDEO;
-    vst->codec->codec_tag  = 0;
-    vst->codec->width      = hnm->width;
-    vst->codec->height     = hnm->height;
-    vst->codec->extradata  = av_mallocz(1);
-
-    vst->codec->extradata_size = 1;
-    memcpy(vst->codec->extradata, &hnm->version, 1);
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_id   = AV_CODEC_ID_HNM4_VIDEO;
+    vst->codecpar->codec_tag  = 0;
+    vst->codecpar->width      = hnm->width;
+    vst->codecpar->height     = hnm->height;
+    vst->codecpar->extradata  = av_mallocz(1);
+
+    vst->codecpar->extradata_size = 1;
+    memcpy(vst->codecpar->extradata, &hnm->version, 1);
 
     vst->start_time = 0;
 
diff --git a/libavformat/http.c b/libavformat/http.c
index 3dad2ef..51275d9 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -221,7 +221,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
     if (!s->hd) {
         err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE,
                                    &h->interrupt_callback, options,
-                                   h->protocol_whitelist);
+                                   h->protocol_whitelist, h->protocol_blacklist, h);
         if (err < 0)
             return err;
     }
@@ -370,7 +370,7 @@ static int http_write_reply(URLContext* h, int status_code)
         message_len = snprintf(message, sizeof(message),
                  "HTTP/1.1 %03d %s\r\n"
                  "Content-Type: %s\r\n"
-                 "Content-Length: %zu\r\n"
+                 "Content-Length: %"SIZE_SPECIFIER"\r\n"
                  "\r\n"
                  "%03d %s\r\n",
                  reply_code,
@@ -456,7 +456,7 @@ static int http_listen(URLContext *h, const char *uri, int flags,
         goto fail;
     if ((ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
                                     &h->interrupt_callback, options,
-                                    h->protocol_whitelist
+                                    h->protocol_whitelist, h->protocol_blacklist, h
                                    )) < 0)
         goto fail;
     s->handshake_step = LOWER_PROTO;
@@ -1220,7 +1220,8 @@ static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int fo
 static int http_read_stream(URLContext *h, uint8_t *buf, int size)
 {
     HTTPContext *s = h->priv_data;
-    int err, new_location, read_ret, seek_ret;
+    int err, new_location, read_ret;
+    int64_t seek_ret;
 
     if (!s->hd)
         return AVERROR_EOF;
@@ -1508,7 +1509,7 @@ static const AVClass flavor ## _context_class = {   \
 #if CONFIG_HTTP_PROTOCOL
 HTTP_CLASS(http);
 
-URLProtocol ff_http_protocol = {
+const URLProtocol ff_http_protocol = {
     .name                = "http",
     .url_open2           = http_open,
     .url_accept          = http_accept,
@@ -1529,7 +1530,7 @@ URLProtocol ff_http_protocol = {
 #if CONFIG_HTTPS_PROTOCOL
 HTTP_CLASS(https);
 
-URLProtocol ff_https_protocol = {
+const URLProtocol ff_https_protocol = {
     .name                = "https",
     .url_open2           = http_open,
     .url_read            = http_read,
@@ -1582,7 +1583,7 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags)
 redo:
     ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
                                &h->interrupt_callback, NULL,
-                               h->protocol_whitelist);
+                               h->protocol_whitelist, h->protocol_blacklist, h);
     if (ret < 0)
         return ret;
 
@@ -1644,7 +1645,7 @@ static int http_proxy_write(URLContext *h, const uint8_t *buf, int size)
     return ffurl_write(s->hd, buf, size);
 }
 
-URLProtocol ff_httpproxy_protocol = {
+const URLProtocol ff_httpproxy_protocol = {
     .name                = "httpproxy",
     .url_open            = http_proxy_open,
     .url_read            = http_buf_read,
diff --git a/libavformat/httpauth.h b/libavformat/httpauth.h
index 9c15a38..0e70859 100644
--- a/libavformat/httpauth.h
+++ b/libavformat/httpauth.h
@@ -62,7 +62,7 @@ typedef struct HTTPAuthState {
      */
     char realm[200];
     /**
-     * The parameters specifiec to digest authentication.
+     * The parameters specific to digest authentication.
      */
     DigestParams digest_params;
     /**
diff --git a/libavformat/icecast.c b/libavformat/icecast.c
index a3b9a36..02e3e38 100644
--- a/libavformat/icecast.c
+++ b/libavformat/icecast.c
@@ -165,7 +165,7 @@ static int icecast_open(URLContext *h, const char *uri, int flags)
     ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path);
     // Finally open http proto handler
     ret = ffurl_open_whitelist(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL,
-                               &opt_dict, h->protocol_whitelist);
+                               &opt_dict, h->protocol_whitelist, h->protocol_blacklist, h);
 
 cleanup:
     av_freep(&user);
@@ -209,7 +209,7 @@ static const AVClass icecast_context_class = {
     .version        = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_icecast_protocol = {
+const URLProtocol ff_icecast_protocol = {
     .name            = "icecast",
     .url_open        = icecast_open,
     .url_write       = icecast_write,
diff --git a/libavformat/icodec.c b/libavformat/icodec.c
index 6ddb901..8019a35 100644
--- a/libavformat/icodec.c
+++ b/libavformat/icodec.c
@@ -45,11 +45,14 @@ typedef struct {
 
 static int probe(AVProbeData *p)
 {
-    unsigned i, frames = AV_RL16(p->buf + 4);
+    unsigned i, frames, checked = 0;
 
-    if (AV_RL16(p->buf) || AV_RL16(p->buf + 2) != 1 || !frames)
+    if (p->buf_size < 22 || AV_RL16(p->buf) || AV_RL16(p->buf + 2) != 1)
         return 0;
-    for (i = 0; i < frames; i++) {
+    frames = AV_RL16(p->buf + 4);
+    if (!frames)
+        return 0;
+    for (i = 0; i < frames && i * 16 + 22 <= p->buf_size; i++) {
         unsigned offset;
         if (AV_RL16(p->buf + 10 + i * 16) & ~1)
             return FFMIN(i, AVPROBE_SCORE_MAX / 4);
@@ -60,14 +63,15 @@ static int probe(AVProbeData *p)
         offset = AV_RL32(p->buf + 18 + i * 16);
         if (offset < 22)
             return FFMIN(i, AVPROBE_SCORE_MAX / 4);
-        if (offset + 8 > p->buf_size)
-            return AVPROBE_SCORE_MAX / 4 + FFMIN(i, 1);
+        if (offset > p->buf_size - 8)
+            continue;
         if (p->buf[offset] != 40 && AV_RB64(p->buf + offset) != PNGSIG)
             return FFMIN(i, AVPROBE_SCORE_MAX / 4);
-        if (i * 16 + 6 > p->buf_size)
-            return AVPROBE_SCORE_MAX / 4 + FFMIN(i, 1);
+        checked++;
     }
 
+    if (checked < frames)
+        return AVPROBE_SCORE_MAX / 4 + FFMIN(checked, 1);
     return AVPROBE_SCORE_MAX / 2 + 1;
 }
 
@@ -95,9 +99,9 @@ static int read_header(AVFormatContext *s)
         if (!st)
             return AVERROR(ENOMEM);
 
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->width      = avio_r8(pb);
-        st->codec->height     = avio_r8(pb);
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->width      = avio_r8(pb);
+        st->codecpar->height     = avio_r8(pb);
         ico->images[i].nb_pal = avio_r8(pb);
         if (ico->images[i].nb_pal == 255)
             ico->images[i].nb_pal = 0;
@@ -113,20 +117,20 @@ static int read_header(AVFormatContext *s)
         codec = avio_rl32(pb);
         switch (codec) {
         case MKTAG(0x89, 'P', 'N', 'G'):
-            st->codec->codec_id = AV_CODEC_ID_PNG;
-            st->codec->width    = 0;
-            st->codec->height   = 0;
+            st->codecpar->codec_id = AV_CODEC_ID_PNG;
+            st->codecpar->width    = 0;
+            st->codecpar->height   = 0;
             break;
         case 40:
             if (ico->images[i].size < 40)
                 return AVERROR_INVALIDDATA;
-            st->codec->codec_id = AV_CODEC_ID_BMP;
+            st->codecpar->codec_id = AV_CODEC_ID_BMP;
             tmp = avio_rl32(pb);
             if (tmp)
-                st->codec->width = tmp;
+                st->codecpar->width = tmp;
             tmp = avio_rl32(pb);
             if (tmp)
-                st->codec->height = tmp / 2;
+                st->codecpar->height = tmp / 2;
             break;
         default:
             avpriv_request_sample(s, "codec %d", codec);
@@ -153,7 +157,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
     if ((ret = avio_seek(pb, image->offset, SEEK_SET)) < 0)
         return ret;
 
-    if (s->streams[ico->current_image]->codec->codec_id == AV_CODEC_ID_PNG) {
+    if (s->streams[ico->current_image]->codecpar->codec_id == AV_CODEC_ID_PNG) {
         if ((ret = av_get_packet(pb, pkt, image->size)) < 0)
             return ret;
     } else {
@@ -173,13 +177,13 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
         if ((ret = avio_read(pb, buf, image->size)) < 0)
             return ret;
 
-        st->codec->bits_per_coded_sample = AV_RL16(buf + 14);
+        st->codecpar->bits_per_coded_sample = AV_RL16(buf + 14);
 
         if (AV_RL32(buf + 32))
             image->nb_pal = AV_RL32(buf + 32);
 
-        if (st->codec->bits_per_coded_sample <= 8 && !image->nb_pal) {
-            image->nb_pal = 1 << st->codec->bits_per_coded_sample;
+        if (st->codecpar->bits_per_coded_sample <= 8 && !image->nb_pal) {
+            image->nb_pal = 1 << st->codecpar->bits_per_coded_sample;
             AV_WL32(buf + 32, image->nb_pal);
         }
 
diff --git a/libavformat/icoenc.c b/libavformat/icoenc.c
index 53d4420..a7ada19 100644
--- a/libavformat/icoenc.c
+++ b/libavformat/icoenc.c
@@ -42,33 +42,33 @@ typedef struct {
     IcoImage *images;
 } IcoMuxContext;
 
-static int ico_check_attributes(AVFormatContext *s, const AVCodecContext *c)
+static int ico_check_attributes(AVFormatContext *s, const AVCodecParameters *p)
 {
-    if (c->codec_id == AV_CODEC_ID_BMP) {
-        if (c->pix_fmt == AV_PIX_FMT_PAL8 && AV_PIX_FMT_RGB32 != AV_PIX_FMT_BGRA) {
+    if (p->codec_id == AV_CODEC_ID_BMP) {
+        if (p->format == AV_PIX_FMT_PAL8 && AV_PIX_FMT_RGB32 != AV_PIX_FMT_BGRA) {
             av_log(s, AV_LOG_ERROR, "Wrong endianness for bmp pixel format\n");
             return AVERROR(EINVAL);
-        } else if (c->pix_fmt != AV_PIX_FMT_PAL8 &&
-                   c->pix_fmt != AV_PIX_FMT_RGB555LE &&
-                   c->pix_fmt != AV_PIX_FMT_BGR24 &&
-                   c->pix_fmt != AV_PIX_FMT_BGRA) {
+        } else if (p->format != AV_PIX_FMT_PAL8 &&
+                   p->format != AV_PIX_FMT_RGB555LE &&
+                   p->format != AV_PIX_FMT_BGR24 &&
+                   p->format != AV_PIX_FMT_BGRA) {
             av_log(s, AV_LOG_ERROR, "BMP must be 1bit, 4bit, 8bit, 16bit, 24bit, or 32bit\n");
             return AVERROR(EINVAL);
         }
-    } else if (c->codec_id == AV_CODEC_ID_PNG) {
-        if (c->pix_fmt != AV_PIX_FMT_RGBA) {
+    } else if (p->codec_id == AV_CODEC_ID_PNG) {
+        if (p->format != AV_PIX_FMT_RGBA) {
             av_log(s, AV_LOG_ERROR, "PNG in ico requires pixel format to be rgba\n");
             return AVERROR(EINVAL);
         }
     } else {
-        const AVCodecDescriptor *codesc = avcodec_descriptor_get(c->codec_id);
+        const AVCodecDescriptor *codesc = avcodec_descriptor_get(p->codec_id);
         av_log(s, AV_LOG_ERROR, "Unsupported codec %s\n", codesc ? codesc->name : "");
         return AVERROR(EINVAL);
     }
 
-    if (c->width > 256 ||
-        c->height > 256) {
-        av_log(s, AV_LOG_ERROR, "Unsupported dimensions %dx%d (dimensions cannot exceed 256x256)\n", c->width, c->height);
+    if (p->width > 256 ||
+        p->height > 256) {
+        av_log(s, AV_LOG_ERROR, "Unsupported dimensions %dx%d (dimensions cannot exceed 256x256)\n", p->width, p->height);
         return AVERROR(EINVAL);
     }
 
@@ -95,7 +95,7 @@ static int ico_write_header(AVFormatContext *s)
     avio_skip(pb, 2); // skip the number of images
 
     for (i = 0; i < s->nb_streams; i++) {
-        if (ret = ico_check_attributes(s, s->streams[i]->codec))
+        if (ret = ico_check_attributes(s, s->streams[i]->codecpar))
             return ret;
 
         // Fill in later when writing trailer...
@@ -116,7 +116,7 @@ static int ico_write_packet(AVFormatContext *s, AVPacket *pkt)
     IcoMuxContext *ico = s->priv_data;
     IcoImage *image;
     AVIOContext *pb = s->pb;
-    AVCodecContext *c = s->streams[pkt->stream_index]->codec;
+    AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
     int i;
 
     if (ico->current_image >= ico->nb_images) {
@@ -127,11 +127,11 @@ static int ico_write_packet(AVFormatContext *s, AVPacket *pkt)
     image = &ico->images[ico->current_image++];
 
     image->offset = avio_tell(pb);
-    image->width = (c->width == 256) ? 0 : c->width;
-    image->height = (c->height == 256) ? 0 : c->height;
+    image->width = (par->width == 256) ? 0 : par->width;
+    image->height = (par->height == 256) ? 0 : par->height;
 
-    if (c->codec_id == AV_CODEC_ID_PNG) {
-        image->bits = c->bits_per_coded_sample;
+    if (par->codec_id == AV_CODEC_ID_PNG) {
+        image->bits = par->bits_per_coded_sample;
         image->size = pkt->size;
 
         avio_write(pb, pkt->data, pkt->size);
@@ -142,13 +142,13 @@ static int ico_write_packet(AVFormatContext *s, AVPacket *pkt)
         }
 
         image->bits = AV_RL16(pkt->data + 28); // allows things like 1bit and 4bit images to be preserved
-        image->size = pkt->size - 14 + c->height * (c->width + 7) / 8;
+        image->size = pkt->size - 14 + par->height * (par->width + 7) / 8;
 
         avio_write(pb, pkt->data + 14, 8); // Skip the BITMAPFILEHEADER header
         avio_wl32(pb, AV_RL32(pkt->data + 22) * 2); // rewrite height as 2 * height
         avio_write(pb, pkt->data + 26, pkt->size - 26);
 
-        for (i = 0; i < c->height * (c->width + 7) / 8; ++i)
+        for (i = 0; i < par->height * (par->width + 7) / 8; ++i)
             avio_w8(pb, 0x00); // Write bitmask (opaque)
     }
 
@@ -169,8 +169,8 @@ static int ico_write_trailer(AVFormatContext *s)
         avio_w8(pb, ico->images[i].width);
         avio_w8(pb, ico->images[i].height);
 
-        if (s->streams[i]->codec->codec_id == AV_CODEC_ID_BMP &&
-            s->streams[i]->codec->pix_fmt == AV_PIX_FMT_PAL8) {
+        if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_BMP &&
+            s->streams[i]->codecpar->format == AV_PIX_FMT_PAL8) {
             avio_w8(pb, (ico->images[i].bits >= 8) ? 0 : 1 << ico->images[i].bits);
         } else {
             avio_w8(pb, 0);
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index addf937..46b9394 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -1091,11 +1091,11 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
             return AVERROR(ENOMEM);
 
         st->disposition      |= AV_DISPOSITION_ATTACHED_PIC;
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id   = apic->id;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_id   = apic->id;
 
         if (AV_RB64(apic->buf->data) == 0x89504e470d0a1a0a)
-            st->codec->codec_id = AV_CODEC_ID_PNG;
+            st->codecpar->codec_id = AV_CODEC_ID_PNG;
 
         if (apic->description[0])
             av_dict_set(&st->metadata, "title", apic->description, 0);
diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c
index 8b804c4..14de76a 100644
--- a/libavformat/id3v2enc.c
+++ b/libavformat/id3v2enc.c
@@ -84,7 +84,7 @@ static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char *
     len = avio_close_dyn_buf(dyn_buf, &pb);
 
     avio_wb32(avioc, tag);
-    /* ID3v2.3 frame size is not synchsafe */
+    /* ID3v2.3 frame size is not sync-safe */
     if (id3->version == 3)
         avio_wb32(avioc, len);
     else
@@ -242,6 +242,7 @@ int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
                                   ID3v2_ENCODING_UTF8;
     int i, ret;
 
+    ff_standardize_creation_time(s);
     if ((ret = write_metadata(s->pb, &s->metadata, id3, enc)) < 0)
         return ret;
 
@@ -268,7 +269,7 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt)
 
     /* get the mimetype*/
     while (mime->id != AV_CODEC_ID_NONE) {
-        if (mime->id == st->codec->codec_id) {
+        if (mime->id == st->codecpar->codec_id) {
             mimetype = mime->str;
             break;
         }
diff --git a/libavformat/idcin.c b/libavformat/idcin.c
index 10afed6..cf69102 100644
--- a/libavformat/idcin.c
+++ b/libavformat/idcin.c
@@ -1,6 +1,6 @@
 /*
  * id Quake II CIN File Demuxer
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -33,7 +33,7 @@
  * types. However, a CIN file does start with 5 32-bit numbers that
  * specify audio and video parameters. This demuxer gets around the lack
  * of file signature by performing sanity checks on those parameters.
- * Probabalistically, this is a reasonable solution since the number of
+ * Probabilistically, this is a reasonable solution since the number of
  * valid combinations of the 5 parameters is a very small subset of the
  * total 160-bit number space.
  *
@@ -198,14 +198,14 @@ static int idcin_read_header(AVFormatContext *s)
     avpriv_set_pts_info(st, 33, 1, IDCIN_FPS);
     st->start_time = 0;
     idcin->video_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_IDCIN;
-    st->codec->codec_tag = 0;  /* no fourcc */
-    st->codec->width = width;
-    st->codec->height = height;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_IDCIN;
+    st->codecpar->codec_tag = 0;  /* no fourcc */
+    st->codecpar->width = width;
+    st->codecpar->height = height;
 
     /* load up the Huffman tables into extradata */
-    if ((ret = ff_get_extradata(st->codec, pb, HUFFMAN_TABLE_SIZE)) < 0)
+    if ((ret = ff_get_extradata(s, st->codecpar, pb, HUFFMAN_TABLE_SIZE)) < 0)
         return ret;
 
     if (idcin->audio_present) {
@@ -216,19 +216,19 @@ static int idcin_read_header(AVFormatContext *s)
         avpriv_set_pts_info(st, 63, 1, sample_rate);
         st->start_time = 0;
         idcin->audio_stream_index = st->index;
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_tag = 1;
-        st->codec->channels = channels;
-        st->codec->channel_layout = channels > 1 ? AV_CH_LAYOUT_STEREO :
-                                                   AV_CH_LAYOUT_MONO;
-        st->codec->sample_rate = sample_rate;
-        st->codec->bits_per_coded_sample = bytes_per_sample * 8;
-        st->codec->bit_rate = sample_rate * bytes_per_sample * 8 * channels;
-        st->codec->block_align = idcin->block_align = bytes_per_sample * channels;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_tag = 1;
+        st->codecpar->channels = channels;
+        st->codecpar->channel_layout = channels > 1 ? AV_CH_LAYOUT_STEREO :
+                                                      AV_CH_LAYOUT_MONO;
+        st->codecpar->sample_rate = sample_rate;
+        st->codecpar->bits_per_coded_sample = bytes_per_sample * 8;
+        st->codecpar->bit_rate = sample_rate * bytes_per_sample * 8 * channels;
+        st->codecpar->block_align = idcin->block_align = bytes_per_sample * channels;
         if (bytes_per_sample == 1)
-            st->codec->codec_id = AV_CODEC_ID_PCM_U8;
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
         else
-            st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
 
         if (sample_rate % 14 != 0) {
             idcin->audio_chunk_size1 = (sample_rate / 14) *
diff --git a/libavformat/idroqdec.c b/libavformat/idroqdec.c
index 76bb392..b664279 100644
--- a/libavformat/idroqdec.c
+++ b/libavformat/idroqdec.c
@@ -1,6 +1,6 @@
 /*
  * id RoQ (.roq) File Demuxer
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -130,14 +130,14 @@ static int roq_read_packet(AVFormatContext *s,
                     return AVERROR(ENOMEM);
                 avpriv_set_pts_info(st, 63, 1, roq->frame_rate);
                 roq->video_stream_index = st->index;
-                st->codec->codec_type   = AVMEDIA_TYPE_VIDEO;
-                st->codec->codec_id     = AV_CODEC_ID_ROQ;
-                st->codec->codec_tag    = 0;  /* no fourcc */
+                st->codecpar->codec_type   = AVMEDIA_TYPE_VIDEO;
+                st->codecpar->codec_id     = AV_CODEC_ID_ROQ;
+                st->codecpar->codec_tag    = 0;  /* no fourcc */
 
                 if (avio_read(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE)
                     return AVERROR(EIO);
-                st->codec->width  = roq->width  = AV_RL16(preamble);
-                st->codec->height = roq->height = AV_RL16(preamble + 2);
+                st->codecpar->width  = roq->width  = AV_RL16(preamble);
+                st->codecpar->height = roq->height = AV_RL16(preamble + 2);
                 break;
             }
             /* don't care about this chunk anymore */
@@ -178,22 +178,22 @@ static int roq_read_packet(AVFormatContext *s,
                     return AVERROR(ENOMEM);
                 avpriv_set_pts_info(st, 32, 1, RoQ_AUDIO_SAMPLE_RATE);
                 roq->audio_stream_index = st->index;
-                st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-                st->codec->codec_id = AV_CODEC_ID_ROQ_DPCM;
-                st->codec->codec_tag = 0;  /* no tag */
+                st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+                st->codecpar->codec_id = AV_CODEC_ID_ROQ_DPCM;
+                st->codecpar->codec_tag = 0;  /* no tag */
                 if (chunk_type == RoQ_SOUND_STEREO) {
-                    st->codec->channels       = 2;
-                    st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+                    st->codecpar->channels       = 2;
+                    st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
                 } else {
-                    st->codec->channels       = 1;
-                    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+                    st->codecpar->channels       = 1;
+                    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
                 }
-                roq->audio_channels    = st->codec->channels;
-                st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
-                st->codec->bits_per_coded_sample = 16;
-                st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
-                    st->codec->bits_per_coded_sample;
-                st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
+                roq->audio_channels    = st->codecpar->channels;
+                st->codecpar->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
+                st->codecpar->bits_per_coded_sample = 16;
+                st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+                    st->codecpar->bits_per_coded_sample;
+                st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample;
             }
         case RoQ_QUAD_VQ:
             if (chunk_type == RoQ_QUAD_VQ) {
diff --git a/libavformat/idroqenc.c b/libavformat/idroqenc.c
index 28a3aba..8122efe 100644
--- a/libavformat/idroqenc.c
+++ b/libavformat/idroqenc.c
@@ -29,25 +29,24 @@ static int roq_write_header(struct AVFormatContext *s)
         0x84, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, /* fps: */ 0x1E, 0x00
     };
     int n;
-    AVCodecContext *avctx;
 
 // set the actual fps
     for(n=0;n<s->nb_streams;n++) {
-        if ((avctx=s->streams[n]->codec)->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (s->streams[n]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             unsigned int fps;
 
-            if (avctx->time_base.num != 1) {
-                av_log(avctx, AV_LOG_ERROR, "Frame rate must be integer\n");
+            if (s->streams[n]->avg_frame_rate.den != 1) {
+                av_log(s, AV_LOG_ERROR, "Frame rate must be integer\n");
                 return AVERROR(EINVAL);
             }
 
-            if ((fps=avctx->time_base.den) > 255) {
-                av_log(avctx, AV_LOG_ERROR, "Frame rate may not exceed 255fps\n");
+            if ((fps=s->streams[n]->avg_frame_rate.num) > 255) {
+                av_log(s, AV_LOG_ERROR, "Frame rate may not exceed 255fps\n");
                 return AVERROR(EINVAL);
             }
 
             if (fps != 30) {
-                av_log(avctx, AV_LOG_WARNING, "For vintage compatibility fps must be 30\n");
+                av_log(s, AV_LOG_WARNING, "For vintage compatibility fps must be 30\n");
             }
 
             header[6] = fps;
diff --git a/libavformat/iff.c b/libavformat/iff.c
index 2889083..bf44170 100644
--- a/libavformat/iff.c
+++ b/libavformat/iff.c
@@ -59,7 +59,14 @@
 #define ID_RGB8       MKTAG('R','G','B','8')
 #define ID_RGBN       MKTAG('R','G','B','N')
 #define ID_DSD        MKTAG('D','S','D',' ')
+#define ID_DST        MKTAG('D','S','T',' ')
+#define ID_DSTC       MKTAG('D','S','T','C')
+#define ID_DSTF       MKTAG('D','S','T','F')
+#define ID_FRTE       MKTAG('F','R','T','E')
 #define ID_ANIM       MKTAG('A','N','I','M')
+#define ID_ANHD       MKTAG('A','N','H','D')
+#define ID_DLTA       MKTAG('D','L','T','A')
+#define ID_DPAN       MKTAG('D','P','A','N')
 
 #define ID_FORM       MKTAG('F','O','R','M')
 #define ID_FRM8       MKTAG('F','R','M','8')
@@ -113,6 +120,7 @@ typedef struct IffDemuxContext {
     unsigned  transparency; ///< transparency color index in palette
     unsigned  masking;      ///< masking method used
     uint8_t   tvdc[32];     ///< TVDC lookup table
+    int64_t   pts;
 } IffDemuxContext;
 
 /* Metadata string read */
@@ -147,7 +155,6 @@ static int iff_probe(AVProbeData *p)
           AV_RL32(d+8) == ID_DEEP ||
           AV_RL32(d+8) == ID_ILBM ||
           AV_RL32(d+8) == ID_RGB8 ||
-          AV_RL32(d+8) == ID_RGB8 ||
           AV_RL32(d+8) == ID_ANIM ||
           AV_RL32(d+8) == ID_RGBN)) ||
          (AV_RL32(d) == ID_FRM8 && AV_RL32(d+12) == ID_DSD))
@@ -157,6 +164,7 @@ static int iff_probe(AVProbeData *p)
 
 static const AVCodecTag dsd_codec_tags[] = {
     { AV_CODEC_ID_DSD_MSBF, ID_DSD },
+    { AV_CODEC_ID_DST,      ID_DST },
     { AV_CODEC_ID_NONE, 0 },
 };
 
@@ -209,7 +217,7 @@ static int parse_dsd_diin(AVFormatContext *s, AVStream *st, uint64_t eof)
 {
     AVIOContext *pb = s->pb;
 
-    while (avio_tell(pb) + 12 <= eof) {
+    while (avio_tell(pb) + 12 <= eof && !avio_feof(pb)) {
         uint32_t tag      = avio_rl32(pb);
         uint64_t size     = avio_rb64(pb);
         uint64_t orig_pos = avio_tell(pb);
@@ -243,7 +251,7 @@ static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof)
     int dsd_layout[6];
     ID3v2ExtraMeta *id3v2_extra_meta;
 
-    while (avio_tell(pb) + 12 <= eof) {
+    while (avio_tell(pb) + 12 <= eof && !avio_feof(pb)) {
         uint32_t tag      = avio_rl32(pb);
         uint64_t size     = avio_rb64(pb);
         uint64_t orig_pos = avio_tell(pb);
@@ -262,21 +270,21 @@ static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof)
         case MKTAG('C','H','N','L'):
             if (size < 2)
                 return AVERROR_INVALIDDATA;
-            st->codec->channels       = avio_rb16(pb);
-            if (size < 2 + st->codec->channels * 4)
+            st->codecpar->channels       = avio_rb16(pb);
+            if (size < 2 + st->codecpar->channels * 4)
                 return AVERROR_INVALIDDATA;
-            st->codec->channel_layout = 0;
-            if (st->codec->channels > FF_ARRAY_ELEMS(dsd_layout)) {
+            st->codecpar->channel_layout = 0;
+            if (st->codecpar->channels > FF_ARRAY_ELEMS(dsd_layout)) {
                 avpriv_request_sample(s, "channel layout");
                 break;
             }
-            for (i = 0; i < st->codec->channels; i++)
+            for (i = 0; i < st->codecpar->channels; i++)
                 dsd_layout[i] = avio_rl32(pb);
             for (i = 0; i < FF_ARRAY_ELEMS(dsd_channel_layout); i++) {
                 const DSDLayoutDesc * d = &dsd_channel_layout[i];
-                if (av_get_channel_layout_nb_channels(d->layout) == st->codec->channels &&
-                    !memcmp(d->dsd_layout, dsd_layout, st->codec->channels * sizeof(uint32_t))) {
-                    st->codec->channel_layout = d->layout;
+                if (av_get_channel_layout_nb_channels(d->layout) == st->codecpar->channels &&
+                    !memcmp(d->dsd_layout, dsd_layout, st->codecpar->channels * sizeof(uint32_t))) {
+                    st->codecpar->channel_layout = d->layout;
                     break;
                 }
             }
@@ -285,9 +293,9 @@ static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof)
         case MKTAG('C','M','P','R'):
             if (size < 4)
                 return AVERROR_INVALIDDATA;
-            tag = avio_rl32(pb);
-            st->codec->codec_id = ff_codec_get_id(dsd_codec_tags, tag);
-            if (!st->codec->codec_id) {
+            st->codecpar->codec_tag = tag = avio_rl32(pb);
+            st->codecpar->codec_id = ff_codec_get_id(dsd_codec_tags, tag);
+            if (!st->codecpar->codec_id) {
                 av_log(s, AV_LOG_ERROR, "'%c%c%c%c' compression is not supported\n",
                     tag&0xFF, (tag>>8)&0xFF, (tag>>16)&0xFF, (tag>>24)&0xFF);
                 return AVERROR_PATCHWELCOME;
@@ -297,7 +305,7 @@ static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof)
         case MKTAG('F','S',' ',' '):
             if (size < 4)
                 return AVERROR_INVALIDDATA;
-            st->codec->sample_rate = avio_rb32(pb) / 8;
+            st->codecpar->sample_rate = avio_rb32(pb) / 8;
             break;
 
         case MKTAG('I','D','3',' '):
@@ -323,8 +331,8 @@ static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof)
             config = avio_rb16(pb);
             if (config != 0xFFFF) {
                 if (config < FF_ARRAY_ELEMS(dsd_loudspeaker_config))
-                    st->codec->channel_layout = dsd_loudspeaker_config[config];
-                if (!st->codec->channel_layout)
+                    st->codecpar->channel_layout = dsd_loudspeaker_config[config];
+                if (!st->codecpar->channel_layout)
                     avpriv_request_sample(s, "loudspeaker configuration %d", config);
             }
             break;
@@ -336,6 +344,63 @@ static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof)
     return 0;
 }
 
+static int read_dst_frame(AVFormatContext *s, AVPacket *pkt)
+{
+    IffDemuxContext *iff = s->priv_data;
+    AVIOContext *pb = s->pb;
+    uint32_t chunk_id;
+    uint64_t chunk_pos, data_pos, data_size;
+    int ret = AVERROR_EOF;
+
+    while (!avio_feof(pb)) {
+        chunk_pos = avio_tell(pb);
+        if (chunk_pos >= iff->body_end)
+            return AVERROR_EOF;
+
+        chunk_id = avio_rl32(pb);
+        data_size = iff->is_64bit ? avio_rb64(pb) : avio_rb32(pb);
+        data_pos = avio_tell(pb);
+
+        if (data_size < 1)
+            return AVERROR_INVALIDDATA;
+
+        switch (chunk_id) {
+        case ID_DSTF:
+            if (!pkt) {
+                iff->body_pos  = avio_tell(pb) - (iff->is_64bit ? 12 : 8);
+                iff->body_size = iff->body_end - iff->body_pos;
+                return 0;
+            }
+            ret = av_get_packet(pb, pkt, data_size);
+            if (ret < 0)
+                return ret;
+            if (data_size & 1)
+                avio_skip(pb, 1);
+            pkt->flags |= AV_PKT_FLAG_KEY;
+            pkt->stream_index = 0;
+            pkt->duration = 588 * s->streams[0]->codecpar->sample_rate / 44100;
+            pkt->pos = chunk_pos;
+
+            chunk_pos = avio_tell(pb);
+            if (chunk_pos >= iff->body_end)
+                return 0;
+
+            avio_seek(pb, chunk_pos, SEEK_SET);
+            return 0;
+
+        case ID_FRTE:
+            if (data_size < 4)
+                return AVERROR_INVALIDDATA;
+            s->streams[0]->duration = avio_rb32(pb) * 588LL * s->streams[0]->codecpar->sample_rate / 44100;
+            break;
+        }
+
+        avio_skip(pb, data_size - (avio_tell(pb) - data_pos) + (data_size & 1));
+    }
+
+    return ret;
+}
+
 static const uint8_t deep_rgb24[] = {0, 0, 0, 3, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8};
 static const uint8_t deep_rgba[]  = {0, 0, 0, 4, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8};
 static const uint8_t deep_bgra[]  = {0, 0, 0, 4, 0, 3, 0, 8, 0, 2, 0, 8, 0, 1, 0, 8};
@@ -360,15 +425,14 @@ static int iff_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->channels = 1;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->channels = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
     iff->is_64bit = avio_rl32(pb) == ID_FRM8;
     avio_skip(pb, iff->is_64bit ? 8 : 4);
     // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content
-    st->codec->codec_tag = avio_rl32(pb);
-    if (st->codec->codec_tag == ID_ANIM) {
-        avio_skip(pb, 8);
-        st->codec->codec_tag = avio_rl32(pb);
+    st->codecpar->codec_tag = avio_rl32(pb);
+    if (st->codecpar->codec_tag == ID_ANIM) {
+        avio_skip(pb, 12);
     }
     iff->bitmap_compression = -1;
     iff->svx8_compression = -1;
@@ -386,12 +450,12 @@ static int iff_read_header(AVFormatContext *s)
 
         switch(chunk_id) {
         case ID_VHDR:
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
 
             if (data_size < 14)
                 return AVERROR_INVALIDDATA;
             avio_skip(pb, 12);
-            st->codec->sample_rate = avio_rb16(pb);
+            st->codecpar->sample_rate = avio_rb16(pb);
             if (data_size >= 16) {
                 avio_skip(pb, 1);
                 iff->svx8_compression = avio_r8(pb);
@@ -399,7 +463,7 @@ static int iff_read_header(AVFormatContext *s)
             break;
 
         case ID_MHDR:
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
 
             if (data_size < 32)
                 return AVERROR_INVALIDDATA;
@@ -411,34 +475,40 @@ static int iff_read_header(AVFormatContext *s)
             if (!den)
                 return AVERROR_INVALIDDATA;
             avio_skip(pb, 2);
-            st->codec->sample_rate = num / den;
-            st->codec->channels = avio_rb16(pb);
+            st->codecpar->sample_rate = num / den;
+            st->codecpar->channels = avio_rb16(pb);
             iff->maud_compression = avio_rb16(pb);
-            if (st->codec->channels == 1)
-                st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-            else if (st->codec->channels == 2)
-                st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+            if (st->codecpar->channels == 1)
+                st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+            else if (st->codecpar->channels == 2)
+                st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
             break;
 
         case ID_ABIT:
         case ID_BODY:
         case ID_DBOD:
         case ID_DSD:
+        case ID_DST:
         case ID_MDAT:
             iff->body_pos = avio_tell(pb);
             iff->body_end = iff->body_pos + data_size;
             iff->body_size = data_size;
+            if (chunk_id == ID_DST) {
+                int ret = read_dst_frame(s, NULL);
+                if (ret < 0)
+                    return ret;
+            }
             break;
 
         case ID_CHAN:
             if (data_size < 4)
                 return AVERROR_INVALIDDATA;
             if (avio_rb32(pb) < 6) {
-                st->codec->channels       = 1;
-                st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+                st->codecpar->channels       = 1;
+                st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
             } else {
-                st->codec->channels       = 2;
-                st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+                st->codecpar->channels       = 2;
+                st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
             }
             break;
 
@@ -454,22 +524,22 @@ static int iff_read_header(AVFormatContext *s)
                         data_size);
                  return AVERROR_INVALIDDATA;
             }
-            st->codec->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE;
-            st->codec->extradata      = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!st->codec->extradata)
+            st->codecpar->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE;
+            st->codecpar->extradata      = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!st->codecpar->extradata)
                 return AVERROR(ENOMEM);
-            if (avio_read(pb, st->codec->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0)
+            if (avio_read(pb, st->codecpar->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0)
                 return AVERROR(EIO);
             break;
 
         case ID_BMHD:
-            st->codec->codec_type            = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_type            = AVMEDIA_TYPE_VIDEO;
             if (data_size <= 8)
                 return AVERROR_INVALIDDATA;
-            st->codec->width                 = avio_rb16(pb);
-            st->codec->height                = avio_rb16(pb);
+            st->codecpar->width                 = avio_rb16(pb);
+            st->codecpar->height                = avio_rb16(pb);
             avio_skip(pb, 4); // x, y offset
-            st->codec->bits_per_coded_sample = avio_r8(pb);
+            st->codecpar->bits_per_coded_sample = avio_r8(pb);
             if (data_size >= 10)
                 masking                      = avio_r8(pb);
             if (data_size >= 11)
@@ -484,21 +554,29 @@ static int iff_read_header(AVFormatContext *s)
             }
             break;
 
+        case ID_ANHD:
+            break;
+
+        case ID_DPAN:
+            avio_skip(pb, 2);
+            st->duration = avio_rb16(pb);
+            break;
+
         case ID_DPEL:
             if (data_size < 4 || (data_size & 3))
                 return AVERROR_INVALIDDATA;
             if ((fmt_size = avio_read(pb, fmt, sizeof(fmt))) < 0)
                 return fmt_size;
             if (fmt_size == sizeof(deep_rgb24) && !memcmp(fmt, deep_rgb24, sizeof(deep_rgb24)))
-                st->codec->pix_fmt = AV_PIX_FMT_RGB24;
+                st->codecpar->format = AV_PIX_FMT_RGB24;
             else if (fmt_size == sizeof(deep_rgba) && !memcmp(fmt, deep_rgba, sizeof(deep_rgba)))
-                st->codec->pix_fmt = AV_PIX_FMT_RGBA;
+                st->codecpar->format = AV_PIX_FMT_RGBA;
             else if (fmt_size == sizeof(deep_bgra) && !memcmp(fmt, deep_bgra, sizeof(deep_bgra)))
-                st->codec->pix_fmt = AV_PIX_FMT_BGRA;
+                st->codecpar->format = AV_PIX_FMT_BGRA;
             else if (fmt_size == sizeof(deep_argb) && !memcmp(fmt, deep_argb, sizeof(deep_argb)))
-                st->codec->pix_fmt = AV_PIX_FMT_ARGB;
+                st->codecpar->format = AV_PIX_FMT_ARGB;
             else if (fmt_size == sizeof(deep_abgr) && !memcmp(fmt, deep_abgr, sizeof(deep_abgr)))
-                st->codec->pix_fmt = AV_PIX_FMT_ABGR;
+                st->codecpar->format = AV_PIX_FMT_ABGR;
             else {
                 avpriv_request_sample(s, "color format %.16s", fmt);
                 return AVERROR_PATCHWELCOME;
@@ -506,22 +584,22 @@ static int iff_read_header(AVFormatContext *s)
             break;
 
         case ID_DGBL:
-            st->codec->codec_type            = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_type         = AVMEDIA_TYPE_VIDEO;
             if (data_size < 8)
                 return AVERROR_INVALIDDATA;
-            st->codec->width                 = avio_rb16(pb);
-            st->codec->height                = avio_rb16(pb);
+            st->codecpar->width              = avio_rb16(pb);
+            st->codecpar->height             = avio_rb16(pb);
             iff->bitmap_compression          = avio_rb16(pb);
             st->sample_aspect_ratio.num      = avio_r8(pb);
             st->sample_aspect_ratio.den      = avio_r8(pb);
-            st->codec->bits_per_coded_sample = 24;
+            st->codecpar->bits_per_coded_sample = 24;
             break;
 
         case ID_DLOC:
             if (data_size < 4)
                 return AVERROR_INVALIDDATA;
-            st->codec->width  = avio_rb16(pb);
-            st->codec->height = avio_rb16(pb);
+            st->codecpar->width  = avio_rb16(pb);
+            st->codecpar->height = avio_rb16(pb);
             break;
 
         case ID_TVDC:
@@ -545,7 +623,7 @@ static int iff_read_header(AVFormatContext *s)
                 return AVERROR_INVALIDDATA;
             version = avio_rb32(pb);
             av_log(s, AV_LOG_DEBUG, "DSIFF v%d.%d.%d.%d\n",version >> 24, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF);
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
             break;
 
         case MKTAG('D','I','I','N'):
@@ -626,37 +704,41 @@ static int iff_read_header(AVFormatContext *s)
         avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1));
     }
 
-    avio_seek(pb, iff->body_pos, SEEK_SET);
+    if (st->codecpar->codec_tag == ID_ANIM)
+        avio_seek(pb, 12, SEEK_SET);
+    else
+        avio_seek(pb, iff->body_pos, SEEK_SET);
 
-    switch(st->codec->codec_type) {
+    switch(st->codecpar->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
-        avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
+        avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate);
 
-        if (st->codec->codec_tag == ID_16SV)
-            st->codec->codec_id = AV_CODEC_ID_PCM_S16BE_PLANAR;
-        else if (st->codec->codec_tag == ID_MAUD) {
+        if (st->codecpar->codec_tag == ID_16SV)
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE_PLANAR;
+        else if (st->codecpar->codec_tag == ID_MAUD) {
             if (iff->maud_bits == 8 && !iff->maud_compression) {
-                st->codec->codec_id = AV_CODEC_ID_PCM_U8;
+                st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
             } else if (iff->maud_bits == 16 && !iff->maud_compression) {
-                st->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
+                st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
             } else if (iff->maud_bits ==  8 && iff->maud_compression == 2) {
-                st->codec->codec_id = AV_CODEC_ID_PCM_ALAW;
+                st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW;
             } else if (iff->maud_bits ==  8 && iff->maud_compression == 3) {
-                st->codec->codec_id = AV_CODEC_ID_PCM_MULAW;
+                st->codecpar->codec_id = AV_CODEC_ID_PCM_MULAW;
             } else {
                 avpriv_request_sample(s, "compression %d and bit depth %d", iff->maud_compression, iff->maud_bits);
                 return AVERROR_PATCHWELCOME;
             }
-        } else if (st->codec->codec_tag != ID_DSD) {
+        } else if (st->codecpar->codec_tag != ID_DSD &&
+                   st->codecpar->codec_tag != ID_DST) {
             switch (iff->svx8_compression) {
             case COMP_NONE:
-                st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR;
+                st->codecpar->codec_id = AV_CODEC_ID_PCM_S8_PLANAR;
                 break;
             case COMP_FIB:
-                st->codec->codec_id = AV_CODEC_ID_8SVX_FIB;
+                st->codecpar->codec_id = AV_CODEC_ID_8SVX_FIB;
                 break;
             case COMP_EXP:
-                st->codec->codec_id = AV_CODEC_ID_8SVX_EXP;
+                st->codecpar->codec_id = AV_CODEC_ID_8SVX_EXP;
                 break;
             default:
                 av_log(s, AV_LOG_ERROR,
@@ -665,29 +747,33 @@ static int iff_read_header(AVFormatContext *s)
             }
         }
 
-        st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id);
-        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample;
-        st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
+        st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
+        st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample;
+        st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample;
+        if (st->codecpar->codec_tag == ID_DSD && st->codecpar->block_align <= 0)
+            return AVERROR_INVALIDDATA;
         break;
 
     case AVMEDIA_TYPE_VIDEO:
-        iff->bpp          = st->codec->bits_per_coded_sample;
+        iff->bpp          = st->codecpar->bits_per_coded_sample;
+        if (st->codecpar->codec_tag == ID_ANIM)
+            avpriv_set_pts_info(st, 32, 1, 60);
         if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) {
             iff->ham      = iff->bpp > 6 ? 6 : 4;
-            st->codec->bits_per_coded_sample = 24;
+            st->codecpar->bits_per_coded_sample = 24;
         }
         iff->flags        = (screenmode & 0x80 /* Extra HalfBrite */) && iff->bpp <= 8;
         iff->masking      = masking;
         iff->transparency = transparency;
 
-        if (!st->codec->extradata) {
-            st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE;
-            st->codec->extradata      = av_malloc(IFF_EXTRA_VIDEO_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!st->codec->extradata)
+        if (!st->codecpar->extradata) {
+            st->codecpar->extradata_size = IFF_EXTRA_VIDEO_SIZE;
+            st->codecpar->extradata      = av_malloc(IFF_EXTRA_VIDEO_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!st->codecpar->extradata)
                 return AVERROR(ENOMEM);
         }
-        av_assert0(st->codec->extradata_size >= IFF_EXTRA_VIDEO_SIZE);
-        buf = st->codec->extradata;
+        av_assert0(st->codecpar->extradata_size >= IFF_EXTRA_VIDEO_SIZE);
+        buf = st->codecpar->extradata;
         bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE);
         bytestream_put_byte(&buf, iff->bitmap_compression);
         bytestream_put_byte(&buf, iff->bpp);
@@ -696,7 +782,7 @@ static int iff_read_header(AVFormatContext *s)
         bytestream_put_be16(&buf, iff->transparency);
         bytestream_put_byte(&buf, iff->masking);
         bytestream_put_buffer(&buf, iff->tvdc, sizeof(iff->tvdc));
-        st->codec->codec_id = AV_CODEC_ID_IFF_ILBM;
+        st->codecpar->codec_id = AV_CODEC_ID_IFF_ILBM;
         break;
     default:
         return -1;
@@ -705,6 +791,28 @@ static int iff_read_header(AVFormatContext *s)
     return 0;
 }
 
+static unsigned get_anim_duration(uint8_t *buf, int size)
+{
+    GetByteContext gb;
+
+    bytestream2_init(&gb, buf, size);
+    bytestream2_skip(&gb, 4);
+    while (bytestream2_get_bytes_left(&gb) > 8) {
+        unsigned chunk = bytestream2_get_le32(&gb);
+        unsigned size = bytestream2_get_be32(&gb);
+
+        if (chunk == ID_ANHD) {
+            if (size < 40)
+                break;
+            bytestream2_skip(&gb, 14);
+            return bytestream2_get_be32(&gb);
+        } else {
+            bytestream2_skip(&gb, size + size & 1);
+        }
+    }
+    return 10;
+}
+
 static int iff_read_packet(AVFormatContext *s,
                            AVPacket *pkt)
 {
@@ -714,39 +822,61 @@ static int iff_read_packet(AVFormatContext *s,
     int ret;
     int64_t pos = avio_tell(pb);
 
-    if (pos >= iff->body_end)
+    if (avio_feof(pb))
+        return AVERROR_EOF;
+    if (st->codecpar->codec_tag != ID_ANIM && pos >= iff->body_end)
         return AVERROR_EOF;
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-        if (st->codec->codec_tag == ID_DSD || st->codec->codec_tag == ID_MAUD) {
-            ret = av_get_packet(pb, pkt, FFMIN(iff->body_end - pos, 1024 * st->codec->block_align));
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (st->codecpar->codec_tag == ID_DSD || st->codecpar->codec_tag == ID_MAUD) {
+            ret = av_get_packet(pb, pkt, FFMIN(iff->body_end - pos, 1024 * st->codecpar->block_align));
+        } else if (st->codecpar->codec_tag == ID_DST) {
+            return read_dst_frame(s, pkt);
         } else {
             if (iff->body_size > INT_MAX)
                 return AVERROR_INVALIDDATA;
             ret = av_get_packet(pb, pkt, iff->body_size);
         }
-    } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-        uint8_t *buf;
-
-        if (iff->body_size > INT_MAX - 2)
-            return AVERROR_INVALIDDATA;
-        if (av_new_packet(pkt, iff->body_size + 2) < 0) {
-            return AVERROR(ENOMEM);
+    } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+               st->codecpar->codec_tag  == ID_ANIM) {
+        uint64_t data_size, orig_pos;
+        uint32_t chunk_id, chunk_id2;
+
+        while (!avio_feof(pb)) {
+            if (avio_feof(pb))
+                return AVERROR_EOF;
+
+            orig_pos  = avio_tell(pb);
+            chunk_id  = avio_rl32(pb);
+            data_size = avio_rb32(pb);
+            chunk_id2 = avio_rl32(pb);
+
+            if (chunk_id  == ID_FORM &&
+                chunk_id2 == ID_ILBM) {
+                avio_skip(pb, -4);
+                break;
+            } else if (chunk_id == ID_FORM &&
+                       chunk_id2 == ID_ANIM) {
+                continue;
+            } else {
+                avio_skip(pb, data_size);
+            }
         }
-
-        buf = pkt->data;
-        bytestream_put_be16(&buf, 2);
-        ret = avio_read(pb, buf, iff->body_size);
-        if (ret<0) {
-            av_packet_unref(pkt);
-        } else if (ret < iff->body_size)
-            av_shrink_packet(pkt, ret + 2);
+        ret = av_get_packet(pb, pkt, data_size);
+        pkt->pos = orig_pos;
+        pkt->duration = get_anim_duration(pkt->data, pkt->size);
+        if (pos == 12)
+            pkt->flags |= AV_PKT_FLAG_KEY;
+    } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+               st->codecpar->codec_tag  != ID_ANIM) {
+        ret = av_get_packet(pb, pkt, iff->body_size);
+        pkt->pos = pos;
+        if (pos == iff->body_pos)
+            pkt->flags |= AV_PKT_FLAG_KEY;
     } else {
         av_assert0(0);
     }
 
-    if (pos == iff->body_pos)
-        pkt->flags |= AV_PKT_FLAG_KEY;
     if (ret < 0)
         return ret;
     pkt->stream_index = 0;
diff --git a/libavformat/ilbc.c b/libavformat/ilbc.c
index ebee2fb..50e3c3c 100644
--- a/libavformat/ilbc.c
+++ b/libavformat/ilbc.c
@@ -28,22 +28,22 @@ static const char mode30_header[] = "#!iLBC30\n";
 static int ilbc_write_header(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc;
+    AVCodecParameters *par;
 
     if (s->nb_streams != 1) {
         av_log(s, AV_LOG_ERROR, "Unsupported number of streams\n");
         return AVERROR(EINVAL);
     }
-    enc = s->streams[0]->codec;
+    par = s->streams[0]->codecpar;
 
-    if (enc->codec_id != AV_CODEC_ID_ILBC) {
+    if (par->codec_id != AV_CODEC_ID_ILBC) {
         av_log(s, AV_LOG_ERROR, "Unsupported codec\n");
         return AVERROR(EINVAL);
     }
 
-    if (enc->block_align == 50) {
+    if (par->block_align == 50) {
         avio_write(pb, mode30_header, sizeof(mode30_header) - 1);
-    } else if (enc->block_align == 38) {
+    } else if (par->block_align == 38) {
         avio_write(pb, mode20_header, sizeof(mode20_header) - 1);
     } else {
         av_log(s, AV_LOG_ERROR, "Unsupported mode\n");
@@ -79,18 +79,18 @@ static int ilbc_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_id = AV_CODEC_ID_ILBC;
-    st->codec->sample_rate = 8000;
-    st->codec->channels = 1;
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_ILBC;
+    st->codecpar->sample_rate = 8000;
+    st->codecpar->channels = 1;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     st->start_time = 0;
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     if (!memcmp(header, mode20_header, sizeof(mode20_header) - 1)) {
-        st->codec->block_align = 38;
-        st->codec->bit_rate = 15200;
+        st->codecpar->block_align = 38;
+        st->codecpar->bit_rate = 15200;
     } else if (!memcmp(header, mode30_header, sizeof(mode30_header) - 1)) {
-        st->codec->block_align = 50;
-        st->codec->bit_rate = 13333;
+        st->codecpar->block_align = 50;
+        st->codecpar->bit_rate = 13333;
     } else {
         av_log(s, AV_LOG_ERROR, "Unrecognized iLBC file header\n");
         return AVERROR_INVALIDDATA;
@@ -102,16 +102,16 @@ static int ilbc_read_header(AVFormatContext *s)
 static int ilbc_read_packet(AVFormatContext *s,
                           AVPacket *pkt)
 {
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int ret;
 
-    if ((ret = av_new_packet(pkt, enc->block_align)) < 0)
+    if ((ret = av_new_packet(pkt, par->block_align)) < 0)
         return ret;
 
     pkt->stream_index = 0;
     pkt->pos = avio_tell(s->pb);
-    pkt->duration = enc->block_align == 38 ? 160 : 240;
-    if ((ret = avio_read(s->pb, pkt->data, enc->block_align)) != enc->block_align) {
+    pkt->duration = par->block_align == 38 ? 160 : 240;
+    if ((ret = avio_read(s->pb, pkt->data, par->block_align)) != par->block_align) {
         av_packet_unref(pkt);
         return ret < 0 ? ret : AVERROR(EIO);
     }
diff --git a/libavformat/img2.c b/libavformat/img2.c
index 50352b5..0f6f75c 100644
--- a/libavformat/img2.c
+++ b/libavformat/img2.c
@@ -81,7 +81,7 @@ const IdStrMap ff_img_tags[] = {
     { AV_CODEC_ID_NONE,       NULL       }
 };
 
-static enum AVCodecID av_str2id(const IdStrMap *tags, const char *str)
+static enum AVCodecID str2id(const IdStrMap *tags, const char *str)
 {
     str = strrchr(str, '.');
     if (!str)
@@ -99,5 +99,5 @@ static enum AVCodecID av_str2id(const IdStrMap *tags, const char *str)
 
 enum AVCodecID ff_guess_image2_codec(const char *filename)
 {
-    return av_str2id(ff_img_tags, filename);
+    return str2id(ff_img_tags, filename);
 }
diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c
index c353563..9d6796f 100644
--- a/libavformat/img2dec.c
+++ b/libavformat/img2dec.c
@@ -33,6 +33,7 @@
 #include "avio_internal.h"
 #include "internal.h"
 #include "img2.h"
+#include "libavcodec/mjpeg.h"
 
 #if HAVE_GLOB
 /* Locally define as 0 (bitwise-OR no-op) any missing glob options that
@@ -220,8 +221,8 @@ int ff_img_read_header(AVFormatContext *s1)
         avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num);
 
     if (s->width && s->height) {
-        st->codec->width  = s->width;
-        st->codec->height = s->height;
+        st->codecpar->width  = s->width;
+        st->codecpar->height = s->height;
     }
 
     if (!s->is_pipe) {
@@ -306,18 +307,18 @@ int ff_img_read_header(AVFormatContext *s1)
     }
 
     if (s1->video_codec_id) {
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id   = s1->video_codec_id;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_id   = s1->video_codec_id;
     } else if (s1->audio_codec_id) {
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id   = s1->audio_codec_id;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id   = s1->audio_codec_id;
     } else if (s1->iformat->raw_codec_id) {
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id   = s1->iformat->raw_codec_id;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_id   = s1->iformat->raw_codec_id;
     } else {
         const char *str = strrchr(s->path, '.');
         s->split_planes       = str && !av_strcasecmp(str + 1, "y");
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
         if (s1->pb) {
             int probe_buffer_size = 2048;
             uint8_t *probe_buffer = av_realloc(NULL, probe_buffer_size + AVPROBE_PADDING_SIZE);
@@ -345,7 +346,7 @@ int ff_img_read_header(AVFormatContext *s1)
                     !fmt->raw_codec_id)
                     continue;
                 if (fmt->read_probe(&pd) > 0) {
-                    st->codec->codec_id = fmt->raw_codec_id;
+                    st->codecpar->codec_id = fmt->raw_codec_id;
                     break;
                 }
             }
@@ -354,16 +355,16 @@ int ff_img_read_header(AVFormatContext *s1)
             } else
                 ffio_rewind_with_probe_data(s1->pb, &probe_buffer, probe_buffer_size);
         }
-        if (st->codec->codec_id == AV_CODEC_ID_NONE)
-            st->codec->codec_id = ff_guess_image2_codec(s->path);
-        if (st->codec->codec_id == AV_CODEC_ID_LJPEG)
-            st->codec->codec_id = AV_CODEC_ID_MJPEG;
-        if (st->codec->codec_id == AV_CODEC_ID_ALIAS_PIX) // we cannot distingiush this from BRENDER_PIX
-            st->codec->codec_id = AV_CODEC_ID_NONE;
+        if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
+            st->codecpar->codec_id = ff_guess_image2_codec(s->path);
+        if (st->codecpar->codec_id == AV_CODEC_ID_LJPEG)
+            st->codecpar->codec_id = AV_CODEC_ID_MJPEG;
+        if (st->codecpar->codec_id == AV_CODEC_ID_ALIAS_PIX) // we cannot distingiush this from BRENDER_PIX
+            st->codecpar->codec_id = AV_CODEC_ID_NONE;
     }
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
         pix_fmt != AV_PIX_FMT_NONE)
-        st->codec->pix_fmt = pix_fmt;
+        st->codecpar->format = pix_fmt;
 
     return 0;
 }
@@ -376,7 +377,7 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
     int i, res;
     int size[3]           = { 0 }, ret[3] = { 0 };
     AVIOContext *f[3]     = { NULL };
-    AVCodecContext *codec = s1->streams[0]->codec;
+    AVCodecParameters *par = s1->streams[0]->codecpar;
 
     if (!s->is_pipe) {
         /* loop over input */
@@ -417,7 +418,7 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
             filename[strlen(filename) - 1] = 'U' + i;
         }
 
-        if (codec->codec_id == AV_CODEC_ID_NONE) {
+        if (par->codec_id == AV_CODEC_ID_NONE) {
             AVProbeData pd = { 0 };
             AVInputFormat *ifmt;
             uint8_t header[PROBE_BUF_MIN + AVPROBE_PADDING_SIZE];
@@ -435,11 +436,11 @@ int ff_img_read_packet(AVFormatContext *s1, AVPacket *pkt)
 
             ifmt = av_probe_input_format3(&pd, 1, &score);
             if (ifmt && ifmt->read_packet == ff_img_read_packet && ifmt->raw_codec_id)
-                codec->codec_id = ifmt->raw_codec_id;
+                par->codec_id = ifmt->raw_codec_id;
         }
 
-        if (codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->width)
-            infer_size(&codec->width, &codec->height, size[0]);
+        if (par->codec_id == AV_CODEC_ID_RAWVIDEO && !par->width)
+            infer_size(&par->width, &par->height, size[0]);
     } else {
         f[0] = s1->pb;
         if (avio_feof(f[0]) && s->loop && s->is_pipe)
@@ -560,7 +561,7 @@ static int img_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
 #define OFFSET(x) offsetof(VideoDemuxData, x)
 #define DEC AV_OPT_FLAG_DECODING_PARAM
 const AVOption ff_img_options[] = {
-    { "framerate",    "set the video framerate",             OFFSET(framerate),    AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0,   DEC },
+    { "framerate",    "set the video framerate",             OFFSET(framerate),    AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX,   DEC },
     { "loop",         "force loop over input file sequence", OFFSET(loop),         AV_OPT_TYPE_BOOL,   {.i64 = 0   }, 0, 1,       DEC },
 
     { "pattern_type", "set pattern type",                    OFFSET(pattern_type), AV_OPT_TYPE_INT,    {.i64=PT_DEFAULT}, 0,       INT_MAX, DEC, "pattern_type"},
@@ -687,7 +688,7 @@ static int j2k_probe(AVProbeData *p)
 static int jpeg_probe(AVProbeData *p)
 {
     const uint8_t *b = p->buf;
-    int i, state = 0xD8;
+    int i, state = SOI;
 
     if (AV_RB16(b) != 0xFFD8 ||
         AV_RB32(b) == 0xFFD8FFF7)
@@ -700,55 +701,58 @@ static int jpeg_probe(AVProbeData *p)
             continue;
         c = b[i + 1];
         switch (c) {
-        case 0xD8:
+        case SOI:
             return 0;
-        case 0xC0:
-        case 0xC1:
-        case 0xC2:
-        case 0xC3:
-        case 0xC5:
-        case 0xC6:
-        case 0xC7:
-            if (state != 0xD8)
+        case SOF0:
+        case SOF1:
+        case SOF2:
+        case SOF3:
+        case SOF5:
+        case SOF6:
+        case SOF7:
+            i += AV_RB16(&b[i + 2]) + 1;
+            if (state != SOI)
                 return 0;
-            state = 0xC0;
+            state = SOF0;
             break;
-        case 0xDA:
-            if (state != 0xC0)
+        case SOS:
+            i += AV_RB16(&b[i + 2]) + 1;
+            if (state != SOF0 && state != SOS)
                 return 0;
-            state = 0xDA;
+            state = SOS;
             break;
-        case 0xD9:
-            if (state != 0xDA)
+        case EOI:
+            if (state != SOS)
                 return 0;
-            state = 0xD9;
+            state = EOI;
             break;
-        case 0xE0:
-        case 0xE1:
-        case 0xE2:
-        case 0xE3:
-        case 0xE4:
-        case 0xE5:
-        case 0xE6:
-        case 0xE7:
-        case 0xE8:
-        case 0xE9:
-        case 0xEA:
-        case 0xEB:
-        case 0xEC:
-        case 0xED:
-        case 0xEE:
-        case 0xEF:
+        case APP0:
+        case APP1:
+        case APP2:
+        case APP3:
+        case APP4:
+        case APP5:
+        case APP6:
+        case APP7:
+        case APP8:
+        case APP9:
+        case APP10:
+        case APP11:
+        case APP12:
+        case APP13:
+        case APP14:
+        case APP15:
+        case COM:
             i += AV_RB16(&b[i + 2]) + 1;
             break;
         default:
-            if (  (c >= 0x02 && c <= 0xBF)
-                || c == 0xC8)
+            if (  (c > TEM && c < SOF0)
+                || c == JPG)
                 return 0;
         }
     }
 
-    if (state == 0xD9)
+    if (state == EOI)
         return AVPROBE_SCORE_EXTENSION + 1;
     return AVPROBE_SCORE_EXTENSION / 8;
 }
@@ -762,6 +766,27 @@ static int jpegls_probe(AVProbeData *p)
     return 0;
 }
 
+static int pcx_probe(AVProbeData *p)
+{
+    const uint8_t *b = p->buf;
+
+    if (   p->buf_size < 128
+        || b[0] != 10
+        || b[1] > 5
+        || b[2] != 1
+        || av_popcount(b[3]) != 1 || b[3] > 8
+        || AV_RL16(&b[4]) > AV_RL16(&b[8])
+        || AV_RL16(&b[6]) > AV_RL16(&b[10])
+        || b[64])
+        return 0;
+    b += 73;
+    while (++b < p->buf + 128)
+        if (*b)
+            return AVPROBE_SCORE_EXTENSION / 4;
+
+    return AVPROBE_SCORE_EXTENSION + 1;
+}
+
 static int qdraw_probe(AVProbeData *p)
 {
     const uint8_t *b = p->buf;
@@ -837,6 +862,56 @@ static int webp_probe(AVProbeData *p)
     return 0;
 }
 
+static int pnm_magic_check(const AVProbeData *p, int magic)
+{
+    const uint8_t *b = p->buf;
+
+    return b[0] == 'P' && b[1] == magic + '0';
+}
+
+static inline int pnm_probe(const AVProbeData *p)
+{
+    const uint8_t *b = p->buf;
+
+    while (b[2] == '\r')
+        b++;
+    if (b[2] == '\n' && (b[3] == '#' || (b[3] >= '0' && b[3] <= '9')))
+        return AVPROBE_SCORE_EXTENSION + 2;
+    return 0;
+}
+
+static int pbm_probe(AVProbeData *p)
+{
+    return pnm_magic_check(p, 1) || pnm_magic_check(p, 4) ? pnm_probe(p) : 0;
+}
+
+static inline int pgmx_probe(AVProbeData *p)
+{
+    return pnm_magic_check(p, 2) || pnm_magic_check(p, 5) ? pnm_probe(p) : 0;
+}
+
+static int pgm_probe(AVProbeData *p)
+{
+    int ret = pgmx_probe(p);
+    return ret && !av_match_ext(p->filename, "pgmyuv") ? ret : 0;
+}
+
+static int pgmyuv_probe(AVProbeData *p) // custom FFmpeg format recognized by file extension
+{
+    int ret = pgmx_probe(p);
+    return ret && av_match_ext(p->filename, "pgmyuv") ? ret : 0;
+}
+
+static int ppm_probe(AVProbeData *p)
+{
+    return pnm_magic_check(p, 3) || pnm_magic_check(p, 6) ? pnm_probe(p) : 0;
+}
+
+static int pam_probe(AVProbeData *p)
+{
+    return pnm_magic_check(p, 7) ? pnm_probe(p) : 0;
+}
+
 #define IMAGEAUTO_DEMUXER(imgname, codecid)\
 static const AVClass imgname ## _class = {\
     .class_name = AV_STRINGIFY(imgname) " demuxer",\
@@ -863,8 +938,14 @@ IMAGEAUTO_DEMUXER(exr,     AV_CODEC_ID_EXR)
 IMAGEAUTO_DEMUXER(j2k,     AV_CODEC_ID_JPEG2000)
 IMAGEAUTO_DEMUXER(jpeg,    AV_CODEC_ID_MJPEG)
 IMAGEAUTO_DEMUXER(jpegls,  AV_CODEC_ID_JPEGLS)
+IMAGEAUTO_DEMUXER(pam,     AV_CODEC_ID_PAM)
+IMAGEAUTO_DEMUXER(pbm,     AV_CODEC_ID_PBM)
+IMAGEAUTO_DEMUXER(pcx,     AV_CODEC_ID_PCX)
+IMAGEAUTO_DEMUXER(pgm,     AV_CODEC_ID_PGM)
+IMAGEAUTO_DEMUXER(pgmyuv,  AV_CODEC_ID_PGMYUV)
 IMAGEAUTO_DEMUXER(pictor,  AV_CODEC_ID_PICTOR)
 IMAGEAUTO_DEMUXER(png,     AV_CODEC_ID_PNG)
+IMAGEAUTO_DEMUXER(ppm,     AV_CODEC_ID_PPM)
 IMAGEAUTO_DEMUXER(qdraw,   AV_CODEC_ID_QDRAW)
 IMAGEAUTO_DEMUXER(sgi,     AV_CODEC_ID_SGI)
 IMAGEAUTO_DEMUXER(sunrast, AV_CODEC_ID_SUNRAST)
diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c
index ebbac2b..32c68e4 100644
--- a/libavformat/img2enc.c
+++ b/libavformat/img2enc.c
@@ -50,7 +50,7 @@ static int write_header(AVFormatContext *s)
 {
     VideoMuxData *img = s->priv_data;
     AVStream *st = s->streams[0];
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(st->codec->pix_fmt);
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(st->codecpar->format);
 
     av_strlcpy(img->path, s->filename, sizeof(img->path));
 
@@ -60,9 +60,9 @@ static int write_header(AVFormatContext *s)
     else
         img->is_pipe = 1;
 
-    if (st->codec->codec_id == AV_CODEC_ID_GIF) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_GIF) {
         img->muxer = "gif";
-    } else if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) {
         const char *str = strrchr(img->path, '.');
         img->split_planes =     str
                              && !av_strcasecmp(str + 1, "y")
@@ -80,8 +80,8 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
     VideoMuxData *img = s->priv_data;
     AVIOContext *pb[4];
     char filename[1024];
-    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
-    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(codec->pix_fmt);
+    AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(par->format);
     int i;
     int nb_renames = 0;
 
@@ -123,8 +123,8 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
     }
 
     if (img->split_planes) {
-        int ysize = codec->width * codec->height;
-        int usize = AV_CEIL_RSHIFT(codec->width, desc->log2_chroma_w) * AV_CEIL_RSHIFT(codec->height, desc->log2_chroma_h);
+        int ysize = par->width * par->height;
+        int usize = AV_CEIL_RSHIFT(par->width, desc->log2_chroma_w) * AV_CEIL_RSHIFT(par->height, desc->log2_chroma_h);
         if (desc->comp[0].depth >= 9) {
             ysize *= 2;
             usize *= 2;
@@ -159,7 +159,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
         fmt->pb = pb[0];
         if ((ret = av_copy_packet(&pkt2, pkt))                            < 0 ||
             (ret = av_dup_packet(&pkt2))                                  < 0 ||
-            (ret = avcodec_copy_context(st->codec, s->streams[0]->codec)) < 0 ||
+            (ret = avcodec_parameters_copy(st->codecpar, s->streams[0]->codecpar)) < 0 ||
             (ret = avformat_write_header(fmt, NULL))                      < 0 ||
             (ret = av_interleaved_write_frame(fmt, &pkt2))                < 0 ||
             (ret = av_write_trailer(fmt))                                 < 0) {
diff --git a/libavformat/internal.h b/libavformat/internal.h
index fee823d..647ad65 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -22,6 +22,8 @@
 #define AVFORMAT_INTERNAL_H
 
 #include <stdint.h>
+
+#include "libavutil/bprint.h"
 #include "avformat.h"
 #include "os_support.h"
 
@@ -122,6 +124,7 @@ struct AVFormatInternal {
      * Whether or not a header has already been written
      */
     int header_written;
+    int write_header_ret;
 };
 
 struct AVStreamInternal {
@@ -132,16 +135,33 @@ struct AVStreamInternal {
     int reorder;
 
     /**
-     * bitstream filter to run on stream
+     * bitstream filters to run on stream
      * - encoding: Set by muxer using ff_stream_add_bitstream_filter
      * - decoding: unused
      */
-    AVBitStreamFilterContext *bsfc;
+    AVBSFContext **bsfcs;
+    int nb_bsfcs;
 
     /**
      * Whether or not check_bitstream should still be run on each packet
      */
     int bitstream_checked;
+
+    /**
+     * The codec context used by avformat_find_stream_info, the parser, etc.
+     */
+    AVCodecContext *avctx;
+    /**
+     * 1 if avctx has been initialized with the values from the codec parameters
+     */
+    int avctx_inited;
+
+    enum AVCodecID orig_codec_id;
+
+    /**
+     * Whether the internal avctx needs to be updated from codecpar (after a late change to codecpar)
+     */
+    int need_context_update;
 };
 
 #ifdef __GNUC__
@@ -495,7 +515,7 @@ static inline int ff_rename(const char *oldpath, const char *newpath, void *logc
  * @param size size of extradata
  * @return 0 if OK, AVERROR_xxx on error
  */
-int ff_alloc_extradata(AVCodecContext *avctx, int size);
+int ff_alloc_extradata(AVCodecParameters *par, int size);
 
 /**
  * Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end
@@ -504,7 +524,7 @@ int ff_alloc_extradata(AVCodecContext *avctx, int size);
  * @param size size of extradata
  * @return >= 0 if OK, AVERROR_xxx on error
  */
-int ff_get_extradata(AVCodecContext *avctx, AVIOContext *pb, int size);
+int ff_get_extradata(AVFormatContext *s, AVCodecParameters *par, AVIOContext *pb, int size);
 
 /**
  * add frame for rfps calculation.
@@ -532,7 +552,7 @@ enum AVWriteUncodedFrameFlags {
 /**
  * Copies the whilelists from one context to the other
  */
-int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src);
+int ff_copy_whiteblacklists(AVFormatContext *dst, AVFormatContext *src);
 
 int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
                        const AVIOInterruptCB *int_cb, AVDictionary **options);
@@ -545,7 +565,7 @@ int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *
 
 /*
  * A wrapper around AVFormatContext.io_close that should be used
- * intead of calling the pointer directly.
+ * instead of calling the pointer directly.
  */
 void ff_format_io_close(AVFormatContext *s, AVIOContext **pb);
 
@@ -560,4 +580,57 @@ void ff_format_io_close(AVFormatContext *s, AVIOContext **pb);
  */
 int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int return_seconds);
 
+/**
+ * Standardize creation_time metadata in AVFormatContext to an ISO-8601
+ * timestamp string.
+ *
+ * @param s AVFormatContext
+ * @return <0 on error
+ */
+int ff_standardize_creation_time(AVFormatContext *s);
+
+#define CONTAINS_PAL 2
+/**
+ * Reshuffles the lines to use the user specified stride.
+ *
+ * @param ppkt input and output packet
+ * @return negative error code or
+ *         0 if no new packet was allocated
+ *         non-zero if a new packet was allocated and ppkt has to be freed
+ *         CONTAINS_PAL if in addition to a new packet the old contained a palette
+ */
+int ff_reshuffle_raw_rgb(AVFormatContext *s, AVPacket **ppkt, AVCodecParameters *par, int expected_stride);
+
+/**
+ * Retrieves the palette from a packet, either from side data, or
+ * appended to the video data in the packet itself (raw video only).
+ * It is commonly used after a call to ff_reshuffle_raw_rgb().
+ *
+ * Use 0 for the ret parameter to check for side data only.
+ *
+ * @param pkt pointer to packet before calling ff_reshuffle_raw_rgb()
+ * @param ret return value from ff_reshuffle_raw_rgb(), or 0
+ * @param palette pointer to palette buffer
+ * @return negative error code or
+ *         1 if the packet has a palette, else 0
+ */
+int ff_get_packet_palette(AVFormatContext *s, AVPacket *pkt, int ret, uint32_t *palette);
+
+/**
+ * Finalize buf into extradata and set its size appropriately.
+ */
+int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf);
+
+/**
+ * Find the next packet in the interleaving queue for the given stream.
+ * The packet is not removed from the interleaving queue, but only
+ * a pointer to it is returned.
+ *
+ * @param ts_offset the ts difference between packet in the que and the muxer.
+ *
+ * @return a pointer to the next packet, or NULL if no packet is queued
+ *         for this stream.
+ */
+const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream, int64_t *ts_offset);
+
 #endif /* AVFORMAT_INTERNAL_H */
diff --git a/libavformat/ipmovie.c b/libavformat/ipmovie.c
index bc5d8cc..f9ab3e0 100644
--- a/libavformat/ipmovie.c
+++ b/libavformat/ipmovie.c
@@ -1,6 +1,6 @@
 /*
  * Interplay MVE File Demuxer
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -221,19 +221,19 @@ static int init_audio(AVFormatContext *s)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate);
     ipmovie->audio_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = ipmovie->audio_type;
-    st->codec->codec_tag = 0;  /* no tag */
-    st->codec->channels = ipmovie->audio_channels;
-    st->codec->channel_layout = st->codec->channels == 1 ? AV_CH_LAYOUT_MONO :
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = ipmovie->audio_type;
+    st->codecpar->codec_tag = 0;  /* no tag */
+    st->codecpar->channels = ipmovie->audio_channels;
+    st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO :
                                                             AV_CH_LAYOUT_STEREO;
-    st->codec->sample_rate = ipmovie->audio_sample_rate;
-    st->codec->bits_per_coded_sample = ipmovie->audio_bits;
-    st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
-        st->codec->bits_per_coded_sample;
-    if (st->codec->codec_id == AV_CODEC_ID_INTERPLAY_DPCM)
-        st->codec->bit_rate /= 2;
-    st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
+    st->codecpar->sample_rate = ipmovie->audio_sample_rate;
+    st->codecpar->bits_per_coded_sample = ipmovie->audio_bits;
+    st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+        st->codecpar->bits_per_coded_sample;
+    if (st->codecpar->codec_id == AV_CODEC_ID_INTERPLAY_DPCM)
+        st->codecpar->bit_rate /= 2;
+    st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample;
 
     return 0;
 }
@@ -623,12 +623,12 @@ static int ipmovie_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 63, 1, 1000000);
     ipmovie->video_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_INTERPLAY_VIDEO;
-    st->codec->codec_tag = 0;  /* no fourcc */
-    st->codec->width = ipmovie->video_width;
-    st->codec->height = ipmovie->video_height;
-    st->codec->bits_per_coded_sample = ipmovie->video_bpp;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_INTERPLAY_VIDEO;
+    st->codecpar->codec_tag = 0;  /* no fourcc */
+    st->codecpar->width = ipmovie->video_width;
+    st->codecpar->height = ipmovie->video_height;
+    st->codecpar->bits_per_coded_sample = ipmovie->video_bpp;
 
     if (ipmovie->audio_type) {
         return init_audio(s);
diff --git a/libavformat/ircamdec.c b/libavformat/ircamdec.c
index f9533ec..59f3a49 100644
--- a/libavformat/ircamdec.c
+++ b/libavformat/ircamdec.c
@@ -85,19 +85,19 @@ static int ircam_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->channels    = channels;
-    st->codec->sample_rate = sample_rate;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channels    = channels;
+    st->codecpar->sample_rate = sample_rate;
 
-    st->codec->codec_id = ff_codec_get_id(tags, tag);
-    if (st->codec->codec_id == AV_CODEC_ID_NONE) {
+    st->codecpar->codec_id = ff_codec_get_id(tags, tag);
+    if (st->codecpar->codec_id == AV_CODEC_ID_NONE) {
         av_log(s, AV_LOG_ERROR, "unknown tag %X\n", tag);
         return AVERROR_INVALIDDATA;
     }
 
-    st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id);
-    st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8;
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
+    st->codecpar->block_align = st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8;
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     avio_skip(s->pb, 1008);
 
     return 0;
diff --git a/libavformat/ircamenc.c b/libavformat/ircamenc.c
index 1a829d4..323ecb3 100644
--- a/libavformat/ircamenc.c
+++ b/libavformat/ircamenc.c
@@ -28,7 +28,7 @@
 
 static int ircam_write_header(AVFormatContext *s)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     uint32_t tag;
 
     if (s->nb_streams != 1) {
@@ -36,15 +36,15 @@ static int ircam_write_header(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    tag = ff_codec_get_tag(ff_codec_ircam_le_tags, codec->codec_id);
+    tag = ff_codec_get_tag(ff_codec_ircam_le_tags, par->codec_id);
     if (!tag) {
         av_log(s, AV_LOG_ERROR, "unsupported codec\n");
         return AVERROR(EINVAL);
     }
 
     avio_wl32(s->pb, 0x0001A364);
-    avio_wl32(s->pb, av_q2intfloat((AVRational){codec->sample_rate, 1}));
-    avio_wl32(s->pb, codec->channels);
+    avio_wl32(s->pb, av_q2intfloat((AVRational){par->sample_rate, 1}));
+    avio_wl32(s->pb, par->channels);
     avio_wl32(s->pb, tag);
     ffio_fill(s->pb, 0, 1008);
     return 0;
diff --git a/libavformat/isom.c b/libavformat/isom.c
index 2ca1265..d412f06 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -38,15 +38,15 @@ const AVCodecTag ff_mp4_obj_type[] = {
     { AV_CODEC_ID_HEVC        , 0x23 },
     { AV_CODEC_ID_AAC         , 0x40 },
     { AV_CODEC_ID_MP4ALS      , 0x40 }, /* 14496-3 ALS */
-    { AV_CODEC_ID_MPEG2VIDEO  , 0x61 }, /* MPEG2 Main */
-    { AV_CODEC_ID_MPEG2VIDEO  , 0x60 }, /* MPEG2 Simple */
-    { AV_CODEC_ID_MPEG2VIDEO  , 0x62 }, /* MPEG2 SNR */
-    { AV_CODEC_ID_MPEG2VIDEO  , 0x63 }, /* MPEG2 Spatial */
-    { AV_CODEC_ID_MPEG2VIDEO  , 0x64 }, /* MPEG2 High */
-    { AV_CODEC_ID_MPEG2VIDEO  , 0x65 }, /* MPEG2 422 */
-    { AV_CODEC_ID_AAC         , 0x66 }, /* MPEG2 AAC Main */
-    { AV_CODEC_ID_AAC         , 0x67 }, /* MPEG2 AAC Low */
-    { AV_CODEC_ID_AAC         , 0x68 }, /* MPEG2 AAC SSR */
+    { AV_CODEC_ID_MPEG2VIDEO  , 0x61 }, /* MPEG-2 Main */
+    { AV_CODEC_ID_MPEG2VIDEO  , 0x60 }, /* MPEG-2 Simple */
+    { AV_CODEC_ID_MPEG2VIDEO  , 0x62 }, /* MPEG-2 SNR */
+    { AV_CODEC_ID_MPEG2VIDEO  , 0x63 }, /* MPEG-2 Spatial */
+    { AV_CODEC_ID_MPEG2VIDEO  , 0x64 }, /* MPEG-2 High */
+    { AV_CODEC_ID_MPEG2VIDEO  , 0x65 }, /* MPEG-2 422 */
+    { AV_CODEC_ID_AAC         , 0x66 }, /* MPEG-2 AAC Main */
+    { AV_CODEC_ID_AAC         , 0x67 }, /* MPEG-2 AAC Low */
+    { AV_CODEC_ID_AAC         , 0x68 }, /* MPEG-2 AAC SSR */
     { AV_CODEC_ID_MP3         , 0x69 }, /* 13818-3 */
     { AV_CODEC_ID_MP2         , 0x69 }, /* 11172-3 */
     { AV_CODEC_ID_MPEG1VIDEO  , 0x6A }, /* 11172-2 */
@@ -59,9 +59,10 @@ const AVCodecTag ff_mp4_obj_type[] = {
     { AV_CODEC_ID_AC3         , 0xA5 },
     { AV_CODEC_ID_EAC3        , 0xA6 },
     { AV_CODEC_ID_DTS         , 0xA9 }, /* mp4ra.org */
-    { AV_CODEC_ID_TSCC2       , 0xD0 }, /* non standard, camtasia uses it */
-    { AV_CODEC_ID_VORBIS      , 0xDD }, /* non standard, gpac uses it */
-    { AV_CODEC_ID_DVD_SUBTITLE, 0xE0 }, /* non standard, see unsupported-embedded-subs-2.mp4 */
+    { AV_CODEC_ID_VP9         , 0xC0 }, /* nonstandard, update when there is a standard value */
+    { AV_CODEC_ID_TSCC2       , 0xD0 }, /* nonstandard, camtasia uses it */
+    { AV_CODEC_ID_VORBIS      , 0xDD }, /* nonstandard, gpac uses it */
+    { AV_CODEC_ID_DVD_SUBTITLE, 0xE0 }, /* nonstandard, see unsupported-embedded-subs-2.mp4 */
     { AV_CODEC_ID_QCELP       , 0xE1 },
     { AV_CODEC_ID_MPEG4SYSTEMS, 0x01 },
     { AV_CODEC_ID_MPEG4SYSTEMS, 0x02 },
@@ -71,10 +72,10 @@ const AVCodecTag ff_mp4_obj_type[] = {
 const AVCodecTag ff_codec_movvideo_tags[] = {
 /*  { AV_CODEC_ID_, MKTAG('I', 'V', '5', '0') }, *//* Indeo 5.0 */
 
-    { AV_CODEC_ID_RAWVIDEO, MKTAG('r', 'a', 'w', ' ') }, /* Uncompressed RGB */
-    { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', '2') }, /* Uncompressed YUV422 */
-    { AV_CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* UNCOMPRESSED 8BIT 4:2:2 */
-    { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', 's') }, /* same as 2vuy but byte swapped */
+    { AV_CODEC_ID_RAWVIDEO, MKTAG('r', 'a', 'w', ' ') }, /* uncompressed RGB */
+    { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', '2') }, /* uncompressed YUV422 */
+    { AV_CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* uncompressed 8-bit 4:2:2 */
+    { AV_CODEC_ID_RAWVIDEO, MKTAG('y', 'u', 'v', 's') }, /* same as 2VUY but byte-swapped */
 
     { AV_CODEC_ID_RAWVIDEO, MKTAG('L', '5', '5', '5') },
     { AV_CODEC_ID_RAWVIDEO, MKTAG('L', '5', '6', '5') },
@@ -93,18 +94,18 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
     { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', '2', '0') }, /* Radius DV YUV PAL */
     { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', '1', '1') }, /* Radius DV YUV NTSC */
 
-    { AV_CODEC_ID_R10K,   MKTAG('R', '1', '0', 'k') }, /* UNCOMPRESSED 10BIT RGB */
-    { AV_CODEC_ID_R10K,   MKTAG('R', '1', '0', 'g') }, /* UNCOMPRESSED 10BIT RGB */
-    { AV_CODEC_ID_R210,   MKTAG('r', '2', '1', '0') }, /* UNCOMPRESSED 10BIT RGB */
+    { AV_CODEC_ID_R10K,   MKTAG('R', '1', '0', 'k') }, /* uncompressed 10-bit RGB */
+    { AV_CODEC_ID_R10K,   MKTAG('R', '1', '0', 'g') }, /* uncompressed 10-bit RGB */
+    { AV_CODEC_ID_R210,   MKTAG('r', '2', '1', '0') }, /* uncompressed 10-bit RGB */
     { AV_CODEC_ID_AVUI,   MKTAG('A', 'V', 'U', 'I') }, /* AVID Uncompressed deinterleaved UYVY422 */
     { AV_CODEC_ID_AVRP,   MKTAG('A', 'V', 'r', 'p') }, /* Avid 1:1 10-bit RGB Packer */
     { AV_CODEC_ID_AVRP,   MKTAG('S', 'U', 'D', 'S') }, /* Avid DS Uncompressed */
-    { AV_CODEC_ID_V210,   MKTAG('v', '2', '1', '0') }, /* UNCOMPRESSED 10BIT 4:2:2 */
-    { AV_CODEC_ID_V210,   MKTAG('b', 'x', 'y', '2') }, /* BOXX 10BIT 4:2:2 */
-    { AV_CODEC_ID_V308,   MKTAG('v', '3', '0', '8') }, /* UNCOMPRESSED  8BIT 4:4:4 */
-    { AV_CODEC_ID_V408,   MKTAG('v', '4', '0', '8') }, /* UNCOMPRESSED  8BIT 4:4:4:4 */
-    { AV_CODEC_ID_V410,   MKTAG('v', '4', '1', '0') }, /* UNCOMPRESSED 10BIT 4:4:4 */
-    { AV_CODEC_ID_Y41P,   MKTAG('Y', '4', '1', 'P') }, /* UNCOMPRESSED 12BIT 4:1:1 */
+    { AV_CODEC_ID_V210,   MKTAG('v', '2', '1', '0') }, /* uncompressed 10-bit 4:2:2 */
+    { AV_CODEC_ID_V210,   MKTAG('b', 'x', 'y', '2') }, /* BOXX 10-bit 4:2:2 */
+    { AV_CODEC_ID_V308,   MKTAG('v', '3', '0', '8') }, /* uncompressed  8-bit 4:4:4 */
+    { AV_CODEC_ID_V408,   MKTAG('v', '4', '0', '8') }, /* uncompressed  8-bit 4:4:4:4 */
+    { AV_CODEC_ID_V410,   MKTAG('v', '4', '1', '0') }, /* uncompressed 10-bit 4:4:4 */
+    { AV_CODEC_ID_Y41P,   MKTAG('Y', '4', '1', 'P') }, /* uncompressed 12-bit 4:1:1 */
     { AV_CODEC_ID_YUV4,   MKTAG('y', 'u', 'v', '4') }, /* libquicktime packed yuv420p */
     { AV_CODEC_ID_TARGA_Y216, MKTAG('Y', '2', '1', '6') },
 
@@ -125,8 +126,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
     { AV_CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
     { AV_CODEC_ID_MPEG4, MKTAG('3', 'I', 'V', '2') }, /* experimental: 3IVX files before ivx D4 4.5.1 */
 
-    { AV_CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H263 */
-    { AV_CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H263 ?? works */
+    { AV_CODEC_ID_H263, MKTAG('h', '2', '6', '3') }, /* H.263 */
+    { AV_CODEC_ID_H263, MKTAG('s', '2', '6', '3') }, /* H.263 ?? works */
 
     { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */
     { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */
@@ -176,30 +177,32 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
     { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '5') }, /* AVC-Intra 100M 1080i50 */
     { AV_CODEC_ID_H264, MKTAG('a', 'i', '1', '6') }, /* AVC-Intra 100M 1080i60 */
     { AV_CODEC_ID_H264, MKTAG('A', 'V', 'i', 'n') }, /* AVC-Intra with implicit SPS/PPS */
-    { AV_CODEC_ID_H264, MKTAG('a', 'i', 'v', 'x') }, /* XAVC 4:2:2 10bit */
+    { AV_CODEC_ID_H264, MKTAG('a', 'i', 'v', 'x') }, /* XAVC 10-bit 4:2:2 */
     { AV_CODEC_ID_H264, MKTAG('r', 'v', '6', '4') }, /* X-Com Radvision */
 
+    { AV_CODEC_ID_VP9,  MKTAG('v', 'p', '0', '9') }, /* VP9 */
+
     { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', ' ') },
     { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', '1', 'v', '1') }, /* Apple MPEG-1 Camcorder */
     { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'e', 'g') }, /* MPEG */
     { AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '1', 'v') }, /* CoreMedia CMVideoCodecType */
     { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', '2', 'v', '1') }, /* Apple MPEG-2 Camcorder */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '1') }, /* MPEG2 HDV 720p30 */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG2 HDV 1080i60 */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* MPEG2 HDV 1080i50 */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '4') }, /* MPEG2 HDV 720p24 */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '5') }, /* MPEG2 HDV 720p25 */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '6') }, /* MPEG2 HDV 1080p24 */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '7') }, /* MPEG2 HDV 1080p25 */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '8') }, /* MPEG2 HDV 1080p30 */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '9') }, /* MPEG2 HDV 720p60 JVC */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', 'a') }, /* MPEG2 HDV 720p50 */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG2 IMX NTSC 525/60 50mb/s produced by FCP */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG2 IMX PAL 625/50 50mb/s produced by FCP */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'n') }, /* MPEG2 IMX NTSC 525/60 40mb/s produced by FCP */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'p') }, /* MPEG2 IMX PAL 625/50 40mb/s produced by FCP */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */
-    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '1') }, /* MPEG-2 HDV 720p30 */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '2') }, /* MPEG-2 HDV 1080i60 */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '3') }, /* MPEG-2 HDV 1080i50 */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '4') }, /* MPEG-2 HDV 720p24 */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '5') }, /* MPEG-2 HDV 720p25 */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '6') }, /* MPEG-2 HDV 1080p24 */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '7') }, /* MPEG-2 HDV 1080p25 */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '8') }, /* MPEG-2 HDV 1080p30 */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', '9') }, /* MPEG-2 HDV 720p60 JVC */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('h', 'd', 'v', 'a') }, /* MPEG-2 HDV 720p50 */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'n') }, /* MPEG-2 IMX NTSC 525/60 50mb/s produced by FCP */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '5', 'p') }, /* MPEG-2 IMX PAL 625/50 50mb/s produced by FCP */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'n') }, /* MPEG-2 IMX NTSC 525/60 40mb/s produced by FCP */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'p') }, /* MPEG-2 IMX PAL 625/50 40mb/s produced by FCP */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG-2 IMX NTSC 525/60 30mb/s produced by FCP */
+    { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG-2 IMX PAL 625/50 30mb/s produced by FCP */
     { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '1') }, /* XDCAM HD422 720p30 CBR */
     { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '4') }, /* XDCAM HD422 720p24 CBR */
     { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '5') }, /* XDCAM HD422 720p25 CBR */
@@ -269,6 +272,23 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
     { AV_CODEC_ID_DXV, MKTAG('D', 'X', 'D', '3') },
     { AV_CODEC_ID_DXV, MKTAG('D', 'X', 'D', 'I') },
 
+    { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'R', 'G') },
+    { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'R', 'A') },
+    { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'G', '0') },
+    { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '0') },
+    { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '2') },
+    { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', '4') },
+    { AV_CODEC_ID_MAGICYUV, MKTAG('M', '8', 'Y', 'A') },
+
+    { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '0') },
+    { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '1') },
+    { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '2') },
+    { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '3') },
+    { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '4') },
+    { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '5') },
+    { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '6') },
+    { AV_CODEC_ID_SHEERVIDEO, MKTAG('S', 'h', 'r', '7') },
+
     { AV_CODEC_ID_NONE, 0 },
 };
 
@@ -296,6 +316,7 @@ const AVCodecTag ff_codec_movaudio_tags[] = {
     { AV_CODEC_ID_MP3,             MKTAG('.', 'm', 'p', '3') },
     { AV_CODEC_ID_MP3,             0x6D730055                },
     { AV_CODEC_ID_NELLYMOSER,      MKTAG('n', 'm', 'o', 's') }, /* Flash Media Server */
+    { AV_CODEC_ID_NELLYMOSER,      MKTAG('N', 'E', 'L', 'L') }, /* Perian */
     { AV_CODEC_ID_PCM_ALAW,        MKTAG('a', 'l', 'a', 'w') },
     { AV_CODEC_ID_PCM_F32BE,       MKTAG('f', 'l', '3', '2') },
     { AV_CODEC_ID_PCM_F32LE,       MKTAG('f', 'l', '3', '2') },
@@ -336,7 +357,7 @@ const AVCodecTag ff_codec_movsubtitle_tags[] = {
 /* map numeric codes from mdhd atom to ISO 639 */
 /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
 /* http://developer.apple.com/documentation/mac/Text/Text-368.html */
-/* deprecated by putting the code as 3*5bit ascii */
+/* deprecated by putting the code as 3*5 bits ASCII */
 static const char mov_mdhd_language_map[][4] = {
     /* 0-9 */
     "eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor",
@@ -374,7 +395,7 @@ int ff_mov_iso639_to_lang(const char lang[4], int mp4)
     /* handle undefined as such */
     if (lang[0] == '\0')
         lang = "und";
-    /* 5bit ascii */
+    /* 5 bits ASCII */
     for (i = 0; i < 3; i++) {
         uint8_t c = lang[i];
         c -= 0x60;
@@ -426,7 +447,7 @@ int ff_mp4_read_descr(AVFormatContext *fc, AVIOContext *pb, int *tag)
     int len;
     *tag = avio_r8(pb);
     len = ff_mp4_read_descr_len(pb);
-    av_log(fc, AV_LOG_TRACE, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
+    av_log(fc, AV_LOG_TRACE, "MPEG-4 description: tag=0x%02x len=%d\n", *tag, len);
     return len;
 }
 
@@ -465,47 +486,43 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext
     avio_r8(pb); /* stream type */
     avio_rb24(pb); /* buffer size db */
 
-    if(avcodec_is_open(st->codec)) {
-        av_log(fc, AV_LOG_DEBUG, "codec open in read_dec_config_descr\n");
-        return -1;
-    }
-
     v = avio_rb32(pb);
-    if (v < INT32_MAX)
-        st->codec->rc_max_rate = v;
+    // TODO: fix this
+    //if (v < INT32_MAX)
+    //    st->codecpar->rc_max_rate = v;
 
-    st->codec->bit_rate = avio_rb32(pb); /* avg bitrate */
+    st->codecpar->bit_rate = avio_rb32(pb); /* avg bitrate */
 
     codec_id= ff_codec_get_id(ff_mp4_obj_type, object_type_id);
     if (codec_id)
-        st->codec->codec_id= codec_id;
+        st->codecpar->codec_id = codec_id;
     av_log(fc, AV_LOG_TRACE, "esds object type id 0x%02x\n", object_type_id);
     len = ff_mp4_read_descr(fc, pb, &tag);
     if (tag == MP4DecSpecificDescrTag) {
-        av_log(fc, AV_LOG_TRACE, "Specific MPEG4 header len=%d\n", len);
+        av_log(fc, AV_LOG_TRACE, "Specific MPEG-4 header len=%d\n", len);
         if (!len || (uint64_t)len > (1<<30))
             return -1;
-        av_free(st->codec->extradata);
-        if ((ret = ff_get_extradata(st->codec, pb, len)) < 0)
+        av_free(st->codecpar->extradata);
+        if ((ret = ff_get_extradata(fc, st->codecpar, pb, len)) < 0)
             return ret;
-        if (st->codec->codec_id == AV_CODEC_ID_AAC) {
+        if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
             MPEG4AudioConfig cfg = {0};
-            avpriv_mpeg4audio_get_config(&cfg, st->codec->extradata,
-                                         st->codec->extradata_size * 8, 1);
-            st->codec->channels = cfg.channels;
+            avpriv_mpeg4audio_get_config(&cfg, st->codecpar->extradata,
+                                         st->codecpar->extradata_size * 8, 1);
+            st->codecpar->channels = cfg.channels;
             if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4
-                st->codec->sample_rate = avpriv_mpa_freq_tab[cfg.sampling_index];
+                st->codecpar->sample_rate = avpriv_mpa_freq_tab[cfg.sampling_index];
             else if (cfg.ext_sample_rate)
-                st->codec->sample_rate = cfg.ext_sample_rate;
+                st->codecpar->sample_rate = cfg.ext_sample_rate;
             else
-                st->codec->sample_rate = cfg.sample_rate;
+                st->codecpar->sample_rate = cfg.sample_rate;
             av_log(fc, AV_LOG_TRACE, "mp4a config channels %d obj %d ext obj %d "
-                    "sample rate %d ext sample rate %d\n", st->codec->channels,
+                    "sample rate %d ext sample rate %d\n", st->codecpar->channels,
                     cfg.object_type, cfg.ext_object_type,
                     cfg.sample_rate, cfg.ext_sample_rate);
-            if (!(st->codec->codec_id = ff_codec_get_id(mp4_audio_types,
+            if (!(st->codecpar->codec_id = ff_codec_get_id(mp4_audio_types,
                                                         cfg.object_type)))
-                st->codec->codec_id = AV_CODEC_ID_AAC;
+                st->codecpar->codec_id = AV_CODEC_ID_AAC;
         }
     }
     return 0;
diff --git a/libavformat/isom.h b/libavformat/isom.h
index 99bc7be..726f350 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -177,6 +177,9 @@ typedef struct MOVStreamContext {
         uint8_t* auxiliary_info;
         uint8_t* auxiliary_info_end;
         uint8_t* auxiliary_info_pos;
+        uint8_t auxiliary_info_default_size;
+        uint8_t* auxiliary_info_sizes;
+        size_t auxiliary_info_sizes_count;
         struct AVAESCTR* aes_ctr;
     } cenc;
 } MOVStreamContext;
diff --git a/libavformat/iss.c b/libavformat/iss.c
index fbde505..95b35dc 100644
--- a/libavformat/iss.c
+++ b/libavformat/iss.c
@@ -107,23 +107,23 @@ static av_cold int iss_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_ISS;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_ISS;
     if (stereo) {
-        st->codec->channels       = 2;
-        st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+        st->codecpar->channels       = 2;
+        st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
     } else {
-        st->codec->channels       = 1;
-        st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+        st->codecpar->channels       = 1;
+        st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
     }
-    st->codec->sample_rate = 44100;
+    st->codecpar->sample_rate = 44100;
     if(rate_divisor > 0)
-         st->codec->sample_rate /= rate_divisor;
-    st->codec->bits_per_coded_sample = 4;
-    st->codec->bit_rate = st->codec->channels * st->codec->sample_rate
-                                      * st->codec->bits_per_coded_sample;
-    st->codec->block_align = iss->packet_size;
-    avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
+         st->codecpar->sample_rate /= rate_divisor;
+    st->codecpar->bits_per_coded_sample = 4;
+    st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate
+                                      * st->codecpar->bits_per_coded_sample;
+    st->codecpar->block_align = iss->packet_size;
+    avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate);
 
     return 0;
 }
@@ -138,8 +138,8 @@ static int iss_read_packet(AVFormatContext *s, AVPacket *pkt)
 
     pkt->stream_index = 0;
     pkt->pts = avio_tell(s->pb) - iss->sample_start_pos;
-    if(s->streams[0]->codec->channels > 0)
-        pkt->pts /= s->streams[0]->codec->channels*2;
+    if(s->streams[0]->codecpar->channels > 0)
+        pkt->pts /= s->streams[0]->codecpar->channels*2;
     return 0;
 }
 
diff --git a/libavformat/iv8.c b/libavformat/iv8.c
index f1e351c..077d905 100644
--- a/libavformat/iv8.c
+++ b/libavformat/iv8.c
@@ -45,8 +45,8 @@ static int read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_MPEG4;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_MPEG4;
     st->need_parsing = AVSTREAM_PARSE_FULL;
     avpriv_set_pts_info(st, 64, 1, 90000);
 
diff --git a/libavformat/ivfdec.c b/libavformat/ivfdec.c
index c0fdafb..197c099 100644
--- a/libavformat/ivfdec.c
+++ b/libavformat/ivfdec.c
@@ -46,11 +46,11 @@ static int read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_tag  = avio_rl32(s->pb);
-    st->codec->codec_id   = ff_codec_get_id(ff_codec_bmp_tags, st->codec->codec_tag);
-    st->codec->width      = avio_rl16(s->pb);
-    st->codec->height     = avio_rl16(s->pb);
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_tag  = avio_rl32(s->pb);
+    st->codecpar->codec_id   = ff_codec_get_id(ff_codec_bmp_tags, st->codecpar->codec_tag);
+    st->codecpar->width      = avio_rl16(s->pb);
+    st->codecpar->height     = avio_rl16(s->pb);
     time_base.den         = avio_rl32(s->pb);
     time_base.num         = avio_rl32(s->pb);
     st->duration          = avio_rl64(s->pb);
diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c
index 484d87d..5dbcd97 100644
--- a/libavformat/ivfenc.c
+++ b/libavformat/ivfenc.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "avformat.h"
+#include "internal.h"
 #include "libavutil/intreadwrite.h"
 
 typedef struct IVFEncContext {
@@ -27,25 +28,25 @@ typedef struct IVFEncContext {
 
 static int ivf_write_header(AVFormatContext *s)
 {
-    AVCodecContext *ctx;
+    AVCodecParameters *par;
     AVIOContext *pb = s->pb;
 
     if (s->nb_streams != 1) {
         av_log(s, AV_LOG_ERROR, "Format supports only exactly one video stream\n");
         return AVERROR(EINVAL);
     }
-    ctx = s->streams[0]->codec;
-    if (ctx->codec_type != AVMEDIA_TYPE_VIDEO ||
-        !(ctx->codec_id == AV_CODEC_ID_VP8 || ctx->codec_id == AV_CODEC_ID_VP9)) {
+    par = s->streams[0]->codecpar;
+    if (par->codec_type != AVMEDIA_TYPE_VIDEO ||
+        !(par->codec_id == AV_CODEC_ID_VP8 || par->codec_id == AV_CODEC_ID_VP9)) {
         av_log(s, AV_LOG_ERROR, "Currently only VP8 and VP9 are supported!\n");
         return AVERROR(EINVAL);
     }
     avio_write(pb, "DKIF", 4);
     avio_wl16(pb, 0); // version
     avio_wl16(pb, 32); // header length
-    avio_wl32(pb, ctx->codec_tag ? ctx->codec_tag : ctx->codec_id == AV_CODEC_ID_VP9 ? AV_RL32("VP90") : AV_RL32("VP80"));
-    avio_wl16(pb, ctx->width);
-    avio_wl16(pb, ctx->height);
+    avio_wl32(pb, par->codec_tag ? par->codec_tag : par->codec_id == AV_CODEC_ID_VP9 ? AV_RL32("VP90") : AV_RL32("VP80"));
+    avio_wl16(pb, par->width);
+    avio_wl16(pb, par->height);
     avio_wl32(pb, s->streams[0]->time_base.den);
     avio_wl32(pb, s->streams[0]->time_base.num);
     avio_wl64(pb, 0xFFFFFFFFFFFFFFFFULL);
@@ -85,6 +86,17 @@ static int ivf_write_trailer(AVFormatContext *s)
     return 0;
 }
 
+static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
+{
+    int ret = 1;
+    AVStream *st = s->streams[pkt->stream_index];
+
+    if (st->codecpar->codec_id == AV_CODEC_ID_VP9)
+        ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
+
+    return ret;
+}
+
 AVOutputFormat ff_ivf_muxer = {
     .priv_data_size = sizeof(IVFEncContext),
     .name         = "ivf",
@@ -95,4 +107,5 @@ AVOutputFormat ff_ivf_muxer = {
     .write_header = ivf_write_header,
     .write_packet = ivf_write_packet,
     .write_trailer = ivf_write_trailer,
+    .check_bitstream = ivf_check_bitstream,
 };
diff --git a/libavformat/jacosubdec.c b/libavformat/jacosubdec.c
index 0436a93..520c435 100644
--- a/libavformat/jacosubdec.c
+++ b/libavformat/jacosubdec.c
@@ -167,8 +167,8 @@ static int jacosub_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 100);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_JACOSUB;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_JACOSUB;
 
     jacosub->timeres = 30;
 
@@ -230,7 +230,7 @@ static int jacosub_read_header(AVFormatContext *s)
     }
 
     /* general/essential directives in the extradata */
-    ret = avpriv_bprint_to_extradata(st->codec, &header);
+    ret = ff_bprint_to_codecpar_extradata(st->codecpar, &header);
     if (ret < 0)
         goto fail;
 
diff --git a/libavformat/jacosubenc.c b/libavformat/jacosubenc.c
index a11e45a..0954f5f 100644
--- a/libavformat/jacosubenc.c
+++ b/libavformat/jacosubenc.c
@@ -21,10 +21,10 @@
 
 static int jacosub_write_header(AVFormatContext *s)
 {
-    const AVCodecContext *avctx = s->streams[0]->codec;
+    const AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (avctx->extradata_size) {
-        avio_write(s->pb, avctx->extradata, avctx->extradata_size - 1);
+    if (par->extradata_size) {
+        avio_write(s->pb, par->extradata, par->extradata_size - 1);
         avio_flush(s->pb);
     }
     return 0;
diff --git a/libavformat/jvdec.c b/libavformat/jvdec.c
index a31c723..b2c067f 100644
--- a/libavformat/jvdec.c
+++ b/libavformat/jvdec.c
@@ -85,11 +85,11 @@ static int read_header(AVFormatContext *s)
     if (!ast || !vst)
         return AVERROR(ENOMEM);
 
-    vst->codec->codec_type  = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_id    = AV_CODEC_ID_JV;
-    vst->codec->codec_tag   = 0; /* no fourcc */
-    vst->codec->width       = avio_rl16(pb);
-    vst->codec->height      = avio_rl16(pb);
+    vst->codecpar->codec_type  = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_id    = AV_CODEC_ID_JV;
+    vst->codecpar->codec_tag   = 0; /* no fourcc */
+    vst->codecpar->width       = avio_rl16(pb);
+    vst->codecpar->height      = avio_rl16(pb);
     vst->duration           =
     vst->nb_frames          =
     ast->nb_index_entries   = avio_rl16(pb);
@@ -97,13 +97,13 @@ static int read_header(AVFormatContext *s)
 
     avio_skip(pb, 4);
 
-    ast->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
-    ast->codec->codec_id       = AV_CODEC_ID_PCM_U8;
-    ast->codec->codec_tag      = 0; /* no fourcc */
-    ast->codec->sample_rate    = avio_rl16(pb);
-    ast->codec->channels       = 1;
-    ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
+    ast->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    ast->codecpar->codec_id       = AV_CODEC_ID_PCM_U8;
+    ast->codecpar->codec_tag      = 0; /* no fourcc */
+    ast->codecpar->sample_rate    = avio_rl16(pb);
+    ast->codecpar->channels       = 1;
+    ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
 
     avio_skip(pb, 10);
 
diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c
index db6977e..43ca482 100644
--- a/libavformat/latmenc.c
+++ b/libavformat/latmenc.c
@@ -25,6 +25,7 @@
 #include "libavcodec/mpeg4audio.h"
 #include "libavutil/opt.h"
 #include "avformat.h"
+#include "internal.h"
 #include "rawenc.h"
 
 #define MAX_EXTRADATA_SIZE 1024
@@ -84,13 +85,13 @@ static int latm_decode_extradata(LATMContext *ctx, uint8_t *buf, int size)
 static int latm_write_header(AVFormatContext *s)
 {
     LATMContext *ctx = s->priv_data;
-    AVCodecContext *avctx = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (avctx->codec_id == AV_CODEC_ID_AAC_LATM)
+    if (par->codec_id == AV_CODEC_ID_AAC_LATM)
         return 0;
 
-    if (avctx->extradata_size > 0 &&
-        latm_decode_extradata(ctx, avctx->extradata, avctx->extradata_size) < 0)
+    if (par->extradata_size > 0 &&
+        latm_decode_extradata(ctx, par->extradata, par->extradata_size) < 0)
         return AVERROR_INVALIDDATA;
 
     return 0;
@@ -99,7 +100,7 @@ static int latm_write_header(AVFormatContext *s)
 static void latm_write_frame_header(AVFormatContext *s, PutBitContext *bs)
 {
     LATMContext *ctx = s->priv_data;
-    AVCodecContext *avctx = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int header_size;
 
     /* AudioMuxElement */
@@ -115,16 +116,16 @@ static void latm_write_frame_header(AVFormatContext *s, PutBitContext *bs)
 
         /* AudioSpecificConfig */
         if (ctx->object_type == AOT_ALS) {
-            header_size = avctx->extradata_size-(ctx->off >> 3);
-            avpriv_copy_bits(bs, &avctx->extradata[ctx->off >> 3], header_size);
+            header_size = par->extradata_size-(ctx->off >> 3);
+            avpriv_copy_bits(bs, &par->extradata[ctx->off >> 3], header_size);
         } else {
             // + 3 assumes not scalable and dependsOnCoreCoder == 0,
             // see decode_ga_specific_config in libavcodec/aacdec.c
-            avpriv_copy_bits(bs, avctx->extradata, ctx->off + 3);
+            avpriv_copy_bits(bs, par->extradata, ctx->off + 3);
 
             if (!ctx->channel_conf) {
                 GetBitContext gb;
-                int ret = init_get_bits8(&gb, avctx->extradata, avctx->extradata_size);
+                int ret = init_get_bits8(&gb, par->extradata, par->extradata_size);
                 av_assert0(ret >= 0); // extradata size has been checked already, so this should not fail
                 skip_bits_long(&gb, ctx->off + 3);
                 avpriv_copy_pce_data(bs, &gb);
@@ -150,15 +151,10 @@ static int latm_write_packet(AVFormatContext *s, AVPacket *pkt)
     int i, len;
     uint8_t loas_header[] = "\x56\xe0\x00";
 
-    if (s->streams[0]->codec->codec_id == AV_CODEC_ID_AAC_LATM)
+    if (s->streams[0]->codecpar->codec_id == AV_CODEC_ID_AAC_LATM)
         return ff_raw_write_packet(s, pkt);
 
-    if (pkt->size > 2 && pkt->data[0] == 0xff && (pkt->data[1] >> 4) == 0xf) {
-        av_log(s, AV_LOG_ERROR, "ADTS header detected - ADTS will not be incorrectly muxed into LATM\n");
-        return AVERROR_INVALIDDATA;
-    }
-
-    if (!s->streams[0]->codec->extradata) {
+    if (!s->streams[0]->codecpar->extradata) {
         if(pkt->size > 2 && pkt->data[0] == 0x56 && (pkt->data[1] >> 4) == 0xe &&
             (AV_RB16(pkt->data + 1) & 0x1FFF) + 3 == pkt->size)
             return ff_raw_write_packet(s, pkt);
@@ -217,6 +213,19 @@ too_large:
     return AVERROR_INVALIDDATA;
 }
 
+static int latm_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
+{
+    int ret = 1;
+    AVStream *st = s->streams[pkt->stream_index];
+
+    if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
+        if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
+            ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
+    }
+
+    return ret;
+}
+
 AVOutputFormat ff_latm_muxer = {
     .name           = "latm",
     .long_name      = NULL_IF_CONFIG_SMALL("LOAS/LATM"),
@@ -228,5 +237,6 @@ AVOutputFormat ff_latm_muxer = {
     .write_header   = latm_write_header,
     .write_packet   = latm_write_packet,
     .priv_class     = &latm_muxer_class,
+    .check_bitstream= latm_check_bitstream,
     .flags          = AVFMT_NOTIMESTAMPS,
 };
diff --git a/libavformat/libgme.c b/libavformat/libgme.c
index 276477b..228273d 100644
--- a/libavformat/libgme.c
+++ b/libavformat/libgme.c
@@ -126,10 +126,10 @@ static int read_header_gme(AVFormatContext *s)
     avpriv_set_pts_info(st, 64, 1, 1000);
     if (st->duration > 0)
         st->duration = gme->info->length;
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE);
-    st->codec->channels    = 2;
-    st->codec->sample_rate = gme->sample_rate;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE);
+    st->codecpar->channels    = 2;
+    st->codecpar->sample_rate = gme->sample_rate;
 
     return 0;
 }
diff --git a/libavformat/libmodplug.c b/libavformat/libmodplug.c
index 75699e8..f18c610 100644
--- a/libavformat/libmodplug.c
+++ b/libavformat/libmodplug.c
@@ -224,10 +224,10 @@ static int modplug_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 1000);
     st->duration = ModPlug_GetLength(modplug->f);
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = AV_CODEC_ID_PCM_S16LE;
-    st->codec->channels    = settings.mChannels;
-    st->codec->sample_rate = settings.mFrequency;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_CODEC_ID_PCM_S16LE;
+    st->codecpar->channels    = settings.mChannels;
+    st->codecpar->sample_rate = settings.mFrequency;
 
     // timebase = 1/1000, 2ch 16bits 44.1kHz-> 2*2*44100
     modplug->ts_per_packet = 1000*AUDIO_PKT_SIZE / (4*44100.);
@@ -238,10 +238,10 @@ static int modplug_read_header(AVFormatContext *s)
             return AVERROR(ENOMEM);
         avpriv_set_pts_info(vst, 64, 1, 1000);
         vst->duration = st->duration;
-        vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        vst->codec->codec_id   = AV_CODEC_ID_XBIN;
-        vst->codec->width      = modplug->w << 3;
-        vst->codec->height     = modplug->h << 3;
+        vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        vst->codecpar->codec_id   = AV_CODEC_ID_XBIN;
+        vst->codecpar->width      = modplug->w << 3;
+        vst->codecpar->height     = modplug->h << 3;
         modplug->linesize = modplug->w * 3;
         modplug->fsize    = modplug->linesize * modplug->h;
     }
diff --git a/libavformat/libnut.c b/libavformat/libnut.c
index 92623ed..26bb354 100644
--- a/libavformat/libnut.c
+++ b/libavformat/libnut.c
@@ -75,46 +75,46 @@ static int nut_write_header(AVFormatContext * avf) {
         return AVERROR(ENOMEM);
 
     for (i = 0; i < avf->nb_streams; i++) {
-        AVCodecContext * codec = avf->streams[i]->codec;
+        AVCodecParameters *par = avf->streams[i]->codecpar;
         int j;
         int fourcc = 0;
         int num, denom, ssize;
 
-        s[i].type = codec->codec_type == AVMEDIA_TYPE_VIDEO ? NUT_VIDEO_CLASS : NUT_AUDIO_CLASS;
+        s[i].type = par->codec_type == AVMEDIA_TYPE_VIDEO ? NUT_VIDEO_CLASS : NUT_AUDIO_CLASS;
 
-        if (codec->codec_tag) fourcc = codec->codec_tag;
-        else fourcc = ff_codec_get_tag(nut_tags, codec->codec_id);
+        if (par->codec_tag) fourcc = par->codec_tag;
+        else fourcc = ff_codec_get_tag(nut_tags, par->codec_id);
 
         if (!fourcc) {
-            if (codec->codec_type == AVMEDIA_TYPE_VIDEO) fourcc = ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id);
-            if (codec->codec_type == AVMEDIA_TYPE_AUDIO) fourcc = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_id);
+            if (par->codec_type == AVMEDIA_TYPE_VIDEO) fourcc = ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id);
+            if (par->codec_type == AVMEDIA_TYPE_AUDIO) fourcc = ff_codec_get_tag(ff_codec_wav_tags, par->codec_id);
         }
 
         s[i].fourcc_len = 4;
         s[i].fourcc = av_malloc(s[i].fourcc_len);
         for (j = 0; j < s[i].fourcc_len; j++) s[i].fourcc[j] = (fourcc >> (j*8)) & 0xFF;
 
-        ff_parse_specific_params(codec, &num, &ssize, &denom);
+        ff_parse_specific_params(avf->streams[i], &num, &ssize, &denom);
         avpriv_set_pts_info(avf->streams[i], 60, denom, num);
 
         s[i].time_base.num = denom;
         s[i].time_base.den = num;
 
         s[i].fixed_fps = 0;
-        s[i].decode_delay = codec->has_b_frames;
-        s[i].codec_specific_len = codec->extradata_size;
-        s[i].codec_specific = codec->extradata;
+        s[i].decode_delay = par->video_delay;
+        s[i].codec_specific_len = par->extradata_size;
+        s[i].codec_specific = par->extradata;
 
-        if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-            s[i].width = codec->width;
-            s[i].height = codec->height;
+        if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
+            s[i].width = par->width;
+            s[i].height = par->height;
             s[i].sample_width = 0;
             s[i].sample_height = 0;
             s[i].colorspace_type = 0;
         } else {
-            s[i].samplerate_num = codec->sample_rate;
+            s[i].samplerate_num = par->sample_rate;
             s[i].samplerate_denom = 1;
-            s[i].channel_count = codec->channels;
+            s[i].channel_count = par->channels;
         }
     }
 
@@ -226,45 +226,45 @@ static int nut_read_header(AVFormatContext * avf) {
         if (!st)
             return AVERROR(ENOMEM);
 
-        for (j = 0; j < s[i].fourcc_len && j < 8; j++) st->codec->codec_tag |= s[i].fourcc[j]<<(j*8);
+        for (j = 0; j < s[i].fourcc_len && j < 8; j++) st->codecpar->codec_tag |= s[i].fourcc[j]<<(j*8);
 
-        st->codec->has_b_frames = s[i].decode_delay;
+        st->codecpar->video_delay = s[i].decode_delay;
 
-        st->codec->extradata_size = s[i].codec_specific_len;
-        if (st->codec->extradata_size) {
-            if(ff_alloc_extradata(st->codec, st->codec->extradata_size)){
+        st->codecpar->extradata_size = s[i].codec_specific_len;
+        if (st->codecpar->extradata_size) {
+            if(ff_alloc_extradata(st->codecpar, st->codecpar->extradata_size)){
                 nut_demuxer_uninit(nut);
                 priv->nut = NULL;
                 return AVERROR(ENOMEM);
             }
-            memcpy(st->codec->extradata, s[i].codec_specific, st->codec->extradata_size);
+            memcpy(st->codecpar->extradata, s[i].codec_specific, st->codecpar->extradata_size);
         }
 
         avpriv_set_pts_info(avf->streams[i], 60, s[i].time_base.num, s[i].time_base.den);
         st->start_time = 0;
         st->duration = s[i].max_pts;
 
-        st->codec->codec_id = ff_codec_get_id(nut_tags, st->codec->codec_tag);
+        st->codecpar->codec_id = ff_codec_get_id(nut_tags, st->codecpar->codec_tag);
 
         switch(s[i].type) {
         case NUT_AUDIO_CLASS:
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-            if (st->codec->codec_id == AV_CODEC_ID_NONE) st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, st->codec->codec_tag);
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+            if (st->codecpar->codec_id == AV_CODEC_ID_NONE) st->codecpar->codec_id = ff_codec_get_id(ff_codec_wav_tags, st->codecpar->codec_tag);
 
-            st->codec->channels = s[i].channel_count;
-            st->codec->sample_rate = s[i].samplerate_num / s[i].samplerate_denom;
+            st->codecpar->channels = s[i].channel_count;
+            st->codecpar->sample_rate = s[i].samplerate_num / s[i].samplerate_denom;
             break;
         case NUT_VIDEO_CLASS:
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            if (st->codec->codec_id == AV_CODEC_ID_NONE) st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, st->codec->codec_tag);
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            if (st->codecpar->codec_id == AV_CODEC_ID_NONE) st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, st->codecpar->codec_tag);
 
-            st->codec->width = s[i].width;
-            st->codec->height = s[i].height;
+            st->codecpar->width = s[i].width;
+            st->codecpar->height = s[i].height;
             st->sample_aspect_ratio.num = s[i].sample_width;
             st->sample_aspect_ratio.den = s[i].sample_height;
             break;
         }
-        if (st->codec->codec_id == AV_CODEC_ID_NONE) av_log(avf, AV_LOG_ERROR, "Unknown codec?!\n");
+        if (st->codecpar->codec_id == AV_CODEC_ID_NONE) av_log(avf, AV_LOG_ERROR, "Unknown codec?!\n");
     }
 
     return 0;
diff --git a/libavformat/librtmp.c b/libavformat/librtmp.c
index bfa9a71..0fea675 100644
--- a/libavformat/librtmp.c
+++ b/libavformat/librtmp.c
@@ -337,7 +337,7 @@ static const AVClass lib ## flavor ## _class = {\
 };
 
 RTMP_CLASS(rtmp)
-URLProtocol ff_librtmp_protocol = {
+const URLProtocol ff_librtmp_protocol = {
     .name                = "rtmp",
     .url_open            = rtmp_open,
     .url_read            = rtmp_read,
@@ -352,7 +352,7 @@ URLProtocol ff_librtmp_protocol = {
 };
 
 RTMP_CLASS(rtmpt)
-URLProtocol ff_librtmpt_protocol = {
+const URLProtocol ff_librtmpt_protocol = {
     .name                = "rtmpt",
     .url_open            = rtmp_open,
     .url_read            = rtmp_read,
@@ -367,7 +367,7 @@ URLProtocol ff_librtmpt_protocol = {
 };
 
 RTMP_CLASS(rtmpe)
-URLProtocol ff_librtmpe_protocol = {
+const URLProtocol ff_librtmpe_protocol = {
     .name                = "rtmpe",
     .url_open            = rtmp_open,
     .url_read            = rtmp_read,
@@ -382,7 +382,7 @@ URLProtocol ff_librtmpe_protocol = {
 };
 
 RTMP_CLASS(rtmpte)
-URLProtocol ff_librtmpte_protocol = {
+const URLProtocol ff_librtmpte_protocol = {
     .name                = "rtmpte",
     .url_open            = rtmp_open,
     .url_read            = rtmp_read,
@@ -397,7 +397,7 @@ URLProtocol ff_librtmpte_protocol = {
 };
 
 RTMP_CLASS(rtmps)
-URLProtocol ff_librtmps_protocol = {
+const URLProtocol ff_librtmps_protocol = {
     .name                = "rtmps",
     .url_open            = rtmp_open,
     .url_read            = rtmp_read,
diff --git a/libavformat/libsmbclient.c b/libavformat/libsmbclient.c
index 84fef7f..b68cd8b 100644
--- a/libavformat/libsmbclient.c
+++ b/libavformat/libsmbclient.c
@@ -365,7 +365,7 @@ static const AVClass libsmbclient_context_class = {
     .version        = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_libsmbclient_protocol = {
+const URLProtocol ff_libsmbclient_protocol = {
     .name                = "smb",
     .url_open            = libsmbc_open,
     .url_read            = libsmbc_read,
diff --git a/libavformat/libssh.c b/libavformat/libssh.c
index 3c056f8..49e92e7 100644
--- a/libavformat/libssh.c
+++ b/libavformat/libssh.c
@@ -489,7 +489,7 @@ static const AVClass libssh_context_class = {
     .version        = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_libssh_protocol = {
+const URLProtocol ff_libssh_protocol = {
     .name                = "sftp",
     .url_open            = libssh_open,
     .url_read            = libssh_read,
diff --git a/libavformat/lmlm4.c b/libavformat/lmlm4.c
index 899f449..d0cf8fe 100644
--- a/libavformat/lmlm4.c
+++ b/libavformat/lmlm4.c
@@ -65,15 +65,15 @@ static int lmlm4_read_header(AVFormatContext *s)
 
     if (!(st = avformat_new_stream(s, NULL)))
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_MPEG4;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_MPEG4;
     st->need_parsing      = AVSTREAM_PARSE_HEADERS;
     avpriv_set_pts_info(st, 64, 1001, 30000);
 
     if (!(st = avformat_new_stream(s, NULL)))
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id   = AV_CODEC_ID_MP2;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id   = AV_CODEC_ID_MP2;
     st->need_parsing      = AVSTREAM_PARSE_HEADERS;
 
     /* the parameters will be extracted from the compressed bitstream */
diff --git a/libavformat/loasdec.c b/libavformat/loasdec.c
index c41809b..7044055 100644
--- a/libavformat/loasdec.c
+++ b/libavformat/loasdec.c
@@ -73,8 +73,8 @@ static int loas_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = s->iformat->raw_codec_id;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = s->iformat->raw_codec_id;
     st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
 
     //LCM of all possible AAC sample rates
diff --git a/libavformat/lrcdec.c b/libavformat/lrcdec.c
index d3655fc..12f74b2 100644
--- a/libavformat/lrcdec.c
+++ b/libavformat/lrcdec.c
@@ -165,8 +165,8 @@ static int lrc_read_header(AVFormatContext *s)
     }
     avpriv_set_pts_info(st, 64, 1, 1000);
     lrc->ts_offset = 0;
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_TEXT;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_TEXT;
     av_bprint_init(&line, 0, AV_BPRINT_SIZE_UNLIMITED);
 
     while(!avio_feof(s->pb)) {
diff --git a/libavformat/lrcenc.c b/libavformat/lrcenc.c
index b316ccd..c5fda64 100644
--- a/libavformat/lrcenc.c
+++ b/libavformat/lrcenc.c
@@ -39,19 +39,20 @@ static int lrc_write_header(AVFormatContext *s)
     const AVDictionaryEntry *metadata_item;
 
     if(s->nb_streams != 1 ||
-       s->streams[0]->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) {
+       s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
         av_log(s, AV_LOG_ERROR,
                "LRC supports only a single subtitle stream.\n");
         return AVERROR(EINVAL);
     }
-    if(s->streams[0]->codec->codec_id != AV_CODEC_ID_SUBRIP &&
-       s->streams[0]->codec->codec_id != AV_CODEC_ID_TEXT) {
+    if(s->streams[0]->codecpar->codec_id != AV_CODEC_ID_SUBRIP &&
+       s->streams[0]->codecpar->codec_id != AV_CODEC_ID_TEXT) {
         av_log(s, AV_LOG_ERROR, "Unsupported subtitle codec: %s\n",
-               avcodec_get_name(s->streams[0]->codec->codec_id));
+               avcodec_get_name(s->streams[0]->codecpar->codec_id));
         return AVERROR(EINVAL);
     }
     avpriv_set_pts_info(s->streams[0], 64, 1, 100);
 
+    ff_standardize_creation_time(s);
     ff_metadata_conv_ctx(s, ff_lrc_metadata_conv, NULL);
     if(!(s->flags & AVFMT_FLAG_BITEXACT)) { // avoid breaking regression tests
         /* LRC provides a metadata slot for specifying encoder version
diff --git a/libavformat/lvfdec.c b/libavformat/lvfdec.c
index 81aec59..b8af256 100644
--- a/libavformat/lvfdec.c
+++ b/libavformat/lvfdec.c
@@ -62,14 +62,14 @@ static int lvf_read_header(AVFormatContext *s)
             if (!st)
                 return AVERROR(ENOMEM);
 
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
             avio_skip(s->pb, 4);
-            st->codec->width      = avio_rl32(s->pb);
-            st->codec->height     = avio_rl32(s->pb);
+            st->codecpar->width      = avio_rl32(s->pb);
+            st->codecpar->height     = avio_rl32(s->pb);
             avio_skip(s->pb, 4);
-            st->codec->codec_tag  = avio_rl32(s->pb);
-            st->codec->codec_id   = ff_codec_get_id(ff_codec_bmp_tags,
-                                                    st->codec->codec_tag);
+            st->codecpar->codec_tag  = avio_rl32(s->pb);
+            st->codecpar->codec_id   = ff_codec_get_id(ff_codec_bmp_tags,
+                                                       st->codecpar->codec_tag);
             avpriv_set_pts_info(st, 32, 1, 1000);
             break;
         case MKTAG('0', '1', 'f', 'm'):
@@ -77,14 +77,14 @@ static int lvf_read_header(AVFormatContext *s)
             if (!st)
                 return AVERROR(ENOMEM);
 
-            st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-            st->codec->codec_tag   = avio_rl16(s->pb);
-            st->codec->channels    = avio_rl16(s->pb);
-            st->codec->sample_rate = avio_rl16(s->pb);
+            st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_tag   = avio_rl16(s->pb);
+            st->codecpar->channels    = avio_rl16(s->pb);
+            st->codecpar->sample_rate = avio_rl16(s->pb);
             avio_skip(s->pb, 8);
-            st->codec->bits_per_coded_sample = avio_r8(s->pb);
-            st->codec->codec_id    = ff_codec_get_id(ff_codec_wav_tags,
-                                                     st->codec->codec_tag);
+            st->codecpar->bits_per_coded_sample = avio_r8(s->pb);
+            st->codecpar->codec_id    = ff_codec_get_id(ff_codec_wav_tags,
+                                                        st->codecpar->codec_tag);
             avpriv_set_pts_info(st, 32, 1, 1000);
             break;
         case 0:
diff --git a/libavformat/lxfdec.c b/libavformat/lxfdec.c
index c00b4bd..99e56f2 100644
--- a/libavformat/lxfdec.c
+++ b/libavformat/lxfdec.c
@@ -178,25 +178,25 @@ static int get_packet_header(AVFormatContext *s)
 
         //set codec based on specified audio bitdepth
         //we only support tightly packed 16-, 20-, 24- and 32-bit PCM at the moment
-        st->codec->bits_per_coded_sample = (audio_format >> 6) & 0x3F;
+        st->codecpar->bits_per_coded_sample = (audio_format >> 6) & 0x3F;
 
-        if (st->codec->bits_per_coded_sample != (audio_format & 0x3F)) {
+        if (st->codecpar->bits_per_coded_sample != (audio_format & 0x3F)) {
             av_log(s, AV_LOG_WARNING, "only tightly packed PCM currently supported\n");
             return AVERROR_PATCHWELCOME;
         }
 
-        switch (st->codec->bits_per_coded_sample) {
-        case 16: st->codec->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR; break;
-        case 20: st->codec->codec_id = AV_CODEC_ID_PCM_LXF;   break;
-        case 24: st->codec->codec_id = AV_CODEC_ID_PCM_S24LE_PLANAR; break;
-        case 32: st->codec->codec_id = AV_CODEC_ID_PCM_S32LE_PLANAR; break;
+        switch (st->codecpar->bits_per_coded_sample) {
+        case 16: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR; break;
+        case 20: st->codecpar->codec_id = AV_CODEC_ID_PCM_LXF;   break;
+        case 24: st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE_PLANAR; break;
+        case 32: st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE_PLANAR; break;
         default:
             av_log(s, AV_LOG_WARNING,
                    "only 16-, 20-, 24- and 32-bit PCM currently supported\n");
             return AVERROR_PATCHWELCOME;
         }
 
-        samples = track_size * 8 / st->codec->bits_per_coded_sample;
+        samples = track_size * 8 / st->codecpar->bits_per_coded_sample;
 
         //use audio packet size to determine video standard
         //for NTSC we have one 8008-sample audio frame per five video frames
@@ -257,11 +257,11 @@ static int lxf_read_header(AVFormatContext *s)
     expiration_date       = AV_RL16(&header_data[58]);
     disk_params           = AV_RL32(&header_data[116]);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->bit_rate   = 1000000 * ((video_params >> 14) & 0xFF);
-    st->codec->codec_tag  = video_params & 0xF;
-    st->codec->codec_id   = ff_codec_get_id(lxf_tags, st->codec->codec_tag);
-    st->need_parsing      = AVSTREAM_PARSE_HEADERS;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->bit_rate   = 1000000 * ((video_params >> 14) & 0xFF);
+    st->codecpar->codec_tag  = video_params & 0xF;
+    st->codecpar->codec_id   = ff_codec_get_id(lxf_tags, st->codecpar->codec_tag);
+    st->need_parsing         = AVSTREAM_PARSE_HEADERS;
 
     av_log(s, AV_LOG_DEBUG, "record: %x = %i-%02i-%02i\n",
            record_date, 1900 + (record_date & 0x7F), (record_date >> 7) & 0xF,
@@ -278,11 +278,11 @@ static int lxf_read_header(AVFormatContext *s)
         if (!(st = avformat_new_stream(s, NULL)))
             return AVERROR(ENOMEM);
 
-        st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-        st->codec->sample_rate = LXF_SAMPLERATE;
-        st->codec->channels    = lxf->channels;
+        st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->sample_rate = LXF_SAMPLERATE;
+        st->codecpar->channels    = lxf->channels;
 
-        avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+        avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     }
 
     avio_skip(s->pb, lxf->extended_size);
diff --git a/libavformat/matroska.c b/libavformat/matroska.c
index faa662d..c592fb0 100644
--- a/libavformat/matroska.c
+++ b/libavformat/matroska.c
@@ -1,6 +1,6 @@
 /*
  * Matroska common data
- * Copyright (c) 2003-2004 The FFmpeg Project
+ * Copyright (c) 2003-2004 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index a654e0c..1ff76e6 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -1,6 +1,6 @@
 /*
  * Matroska constants
- * Copyright (c) 2003-2004 The FFmpeg Project
+ * Copyright (c) 2003-2004 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -119,10 +119,39 @@
 #define MATROSKA_ID_VIDEOPIXELCROPR 0x54DD
 #define MATROSKA_ID_VIDEODISPLAYUNIT 0x54B2
 #define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A
+#define MATROSKA_ID_VIDEOFIELDORDER 0x9D
 #define MATROSKA_ID_VIDEOSTEREOMODE 0x53B8
 #define MATROSKA_ID_VIDEOALPHAMODE 0x53C0
 #define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3
 #define MATROSKA_ID_VIDEOCOLORSPACE 0x2EB524
+#define MATROSKA_ID_VIDEOCOLOR 0x55B0
+
+#define MATROSKA_ID_VIDEOCOLORMATRIXCOEFF 0x55B1
+#define MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL 0x55B2
+#define MATROSKA_ID_VIDEOCOLORCHROMASUBHORZ 0x55B3
+#define MATROSKA_ID_VIDEOCOLORCHROMASUBVERT 0x55B4
+#define MATROSKA_ID_VIDEOCOLORCBSUBHORZ 0x55B5
+#define MATROSKA_ID_VIDEOCOLORCBSUBVERT 0x55B6
+#define MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ 0x55B7
+#define MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT 0x55B8
+#define MATROSKA_ID_VIDEOCOLORRANGE 0x55B9
+#define MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS 0x55BA
+
+#define MATROSKA_ID_VIDEOCOLORPRIMARIES 0x55BB
+#define MATROSKA_ID_VIDEOCOLORMAXCLL 0x55BC
+#define MATROSKA_ID_VIDEOCOLORMAXFALL 0x55BD
+
+#define MATROSKA_ID_VIDEOCOLORMASTERINGMETA 0x55D0
+#define MATROSKA_ID_VIDEOCOLOR_RX 0x55D1
+#define MATROSKA_ID_VIDEOCOLOR_RY 0x55D2
+#define MATROSKA_ID_VIDEOCOLOR_GX 0x55D3
+#define MATROSKA_ID_VIDEOCOLOR_GY 0x55D4
+#define MATROSKA_ID_VIDEOCOLOR_BX 0x55D5
+#define MATROSKA_ID_VIDEOCOLOR_BY 0x55D6
+#define MATROSKA_ID_VIDEOCOLOR_WHITEX 0x55D7
+#define MATROSKA_ID_VIDEOCOLOR_WHITEY 0x55D8
+#define MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX 0x55D9
+#define MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN 0x55DA
 
 /* IDs in the trackaudio master */
 #define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5
@@ -247,6 +276,21 @@ typedef enum {
 } MatroskaTrackEncodingCompAlgo;
 
 typedef enum {
+    MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED = 0,
+    MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED   = 1,
+    MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE  = 2
+} MatroskaVideoInterlaceFlag;
+
+typedef enum {
+    MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE  = 0,
+    MATROSKA_VIDEO_FIELDORDER_UNDETERMINED = 2,
+    MATROSKA_VIDEO_FIELDORDER_TT           = 1,
+    MATROSKA_VIDEO_FIELDORDER_BB           = 6,
+    MATROSKA_VIDEO_FIELDORDER_BT           = 9,
+    MATROSKA_VIDEO_FIELDORDER_TB           = 14,
+} MatroskaVideoFieldOrder;
+
+typedef enum {
   MATROSKA_VIDEO_STEREOMODE_TYPE_MONO               = 0,
   MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT         = 1,
   MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP         = 2,
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index d788232..f3d701f 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -39,6 +39,7 @@
 #include "libavutil/intfloat.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/lzo.h"
+#include "libavutil/mastering_display_metadata.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/time_internal.h"
@@ -130,6 +131,36 @@ typedef struct MatroskaTrackEncoding {
     MatroskaTrackEncryption encryption;
 } MatroskaTrackEncoding;
 
+typedef struct MatroskaMasteringMeta {
+    double r_x;
+    double r_y;
+    double g_x;
+    double g_y;
+    double b_x;
+    double b_y;
+    double white_x;
+    double white_y;
+    double max_luminance;
+    double min_luminance;
+} MatroskaMasteringMeta;
+
+typedef struct MatroskaTrackVideoColor {
+    uint64_t matrix_coefficients;
+    uint64_t bits_per_channel;
+    uint64_t chroma_sub_horz;
+    uint64_t chroma_sub_vert;
+    uint64_t cb_sub_horz;
+    uint64_t cb_sub_vert;
+    uint64_t chroma_siting_horz;
+    uint64_t chroma_siting_vert;
+    uint64_t range;
+    uint64_t transfer_characteristics;
+    uint64_t primaries;
+    uint64_t max_cll;
+    uint64_t max_fall;
+    MatroskaMasteringMeta mastering_meta;
+} MatroskaTrackVideoColor;
+
 typedef struct MatroskaTrackVideo {
     double   frame_rate;
     uint64_t display_width;
@@ -137,8 +168,11 @@ typedef struct MatroskaTrackVideo {
     uint64_t pixel_width;
     uint64_t pixel_height;
     EbmlBin color_space;
+    uint64_t interlaced;
+    uint64_t field_order;
     uint64_t stereo_mode;
     uint64_t alpha_mode;
+    MatroskaTrackVideoColor color;
 } MatroskaTrackVideo;
 
 typedef struct MatroskaTrackAudio {
@@ -185,11 +219,15 @@ typedef struct MatroskaTrack {
     MatroskaTrackOperation operation;
     EbmlList encodings;
     uint64_t codec_delay;
+    uint64_t codec_delay_in_track_tb;
 
     AVStream *stream;
     int64_t end_timecode;
     int ms_compat;
     uint64_t max_block_additional_id;
+
+    uint32_t palette[AVPALETTE_COUNT];
+    int has_palette;
 } MatroskaTrack;
 
 typedef struct MatroskaAttachment {
@@ -314,9 +352,6 @@ typedef struct MatroskaDemuxContext {
 
     /* WebM DASH Manifest live flag/ */
     int is_live;
-
-    uint32_t palette[AVPALETTE_COUNT];
-    int has_palette;
 } MatroskaDemuxContext;
 
 typedef struct MatroskaBlock {
@@ -356,6 +391,38 @@ static const EbmlSyntax matroska_info[] = {
     { 0 }
 };
 
+static const EbmlSyntax matroska_mastering_meta[] = {
+    { MATROSKA_ID_VIDEOCOLOR_RX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, r_x), { .f=-1 } },
+    { MATROSKA_ID_VIDEOCOLOR_RY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, r_y), { .f=-1 } },
+    { MATROSKA_ID_VIDEOCOLOR_GX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, g_x), { .f=-1 } },
+    { MATROSKA_ID_VIDEOCOLOR_GY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, g_y), { .f=-1 } },
+    { MATROSKA_ID_VIDEOCOLOR_BX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, b_x), { .f=-1 } },
+    { MATROSKA_ID_VIDEOCOLOR_BY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, b_y), { .f=-1 } },
+    { MATROSKA_ID_VIDEOCOLOR_WHITEX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, white_x), { .f=-1 } },
+    { MATROSKA_ID_VIDEOCOLOR_WHITEY, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, white_y), { .f=-1 } },
+    { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, min_luminance), { .f=-1 } },
+    { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX, EBML_FLOAT, 0, offsetof(MatroskaMasteringMeta, max_luminance), { .f=-1 } },
+    { 0 }
+};
+
+static const EbmlSyntax matroska_track_video_color[] = {
+    { MATROSKA_ID_VIDEOCOLORMATRIXCOEFF,      EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, matrix_coefficients), { .u=2 } },
+    { MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL,   EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, bits_per_channel), { .u=8 } },
+    { MATROSKA_ID_VIDEOCOLORCHROMASUBHORZ,    EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_horz), { .u=0 } },
+    { MATROSKA_ID_VIDEOCOLORCHROMASUBVERT,    EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_vert), { .u=0 } },
+    { MATROSKA_ID_VIDEOCOLORCBSUBHORZ,        EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, cb_sub_horz), { .u=0 } },
+    { MATROSKA_ID_VIDEOCOLORCBSUBVERT,        EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, cb_sub_vert), { .u=0 } },
+    { MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_horz), { .u=0 } },
+    { MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_vert), { .u=0 } },
+    { MATROSKA_ID_VIDEOCOLORRANGE,            EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, range), { .u=0 } },
+    { MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, transfer_characteristics), { .u=2 } },
+    { MATROSKA_ID_VIDEOCOLORPRIMARIES,        EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, primaries), { .u=2 } },
+    { MATROSKA_ID_VIDEOCOLORMAXCLL,           EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, max_cll), { .u=0 } },
+    { MATROSKA_ID_VIDEOCOLORMAXFALL,          EBML_UINT, 0, offsetof(MatroskaTrackVideoColor, max_fall), { .u=0 } },
+    { MATROSKA_ID_VIDEOCOLORMASTERINGMETA,    EBML_NEST, 0, offsetof(MatroskaTrackVideoColor, mastering_meta), { .n = matroska_mastering_meta } },
+    { 0 }
+};
+
 static const EbmlSyntax matroska_track_video[] = {
     { MATROSKA_ID_VIDEOFRAMERATE,      EBML_FLOAT, 0, offsetof(MatroskaTrackVideo, frame_rate) },
     { MATROSKA_ID_VIDEODISPLAYWIDTH,   EBML_UINT,  0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } },
@@ -364,12 +431,14 @@ static const EbmlSyntax matroska_track_video[] = {
     { MATROSKA_ID_VIDEOPIXELHEIGHT,    EBML_UINT,  0, offsetof(MatroskaTrackVideo, pixel_height) },
     { MATROSKA_ID_VIDEOCOLORSPACE,     EBML_BIN,   0, offsetof(MatroskaTrackVideo, color_space) },
     { MATROSKA_ID_VIDEOALPHAMODE,      EBML_UINT,  0, offsetof(MatroskaTrackVideo, alpha_mode) },
+    { MATROSKA_ID_VIDEOCOLOR,          EBML_NEST,  0, offsetof(MatroskaTrackVideo, color), { .n = matroska_track_video_color } },
     { MATROSKA_ID_VIDEOPIXELCROPB,     EBML_NONE },
     { MATROSKA_ID_VIDEOPIXELCROPT,     EBML_NONE },
     { MATROSKA_ID_VIDEOPIXELCROPL,     EBML_NONE },
     { MATROSKA_ID_VIDEOPIXELCROPR,     EBML_NONE },
     { MATROSKA_ID_VIDEODISPLAYUNIT,    EBML_NONE },
-    { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_NONE },
+    { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_UINT,  0, offsetof(MatroskaTrackVideo, interlaced),  { .u = MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED } },
+    { MATROSKA_ID_VIDEOFIELDORDER,     EBML_UINT,  0, offsetof(MatroskaTrackVideo, field_order), { .u = MATROSKA_VIDEO_FIELDORDER_UNDETERMINED } },
     { MATROSKA_ID_VIDEOSTEREOMODE,     EBML_UINT,  0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } },
     { MATROSKA_ID_VIDEOASPECTRATIO,    EBML_NONE },
     { 0 }
@@ -664,6 +733,8 @@ static const EbmlSyntax matroska_clusters_incremental[] = {
 
 static const char *const matroska_doctypes[] = { "matroska", "webm" };
 
+static int matroska_read_close(AVFormatContext *s);
+
 static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos)
 {
     AVIOContext *pb = matroska->ctx->pb;
@@ -1672,7 +1743,7 @@ static int matroska_parse_flac(AVFormatContext *s,
                     av_log(s, AV_LOG_WARNING,
                            "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n");
                 } else
-                    st->codec->channel_layout = mask;
+                    st->codecpar->channel_layout = mask;
             }
             av_dict_free(&dict);
         }
@@ -1684,7 +1755,28 @@ static int matroska_parse_flac(AVFormatContext *s,
     return 0;
 }
 
-static void mkv_stereo_mode_display_mul(int stereo_mode, int *h_width, int *h_height)
+static int mkv_field_order(int64_t field_order)
+{
+    switch (field_order) {
+    case MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE:
+        return AV_FIELD_PROGRESSIVE;
+    case MATROSKA_VIDEO_FIELDORDER_UNDETERMINED:
+        return AV_FIELD_UNKNOWN;
+    case MATROSKA_VIDEO_FIELDORDER_TT:
+        return AV_FIELD_TT;
+    case MATROSKA_VIDEO_FIELDORDER_BB:
+        return AV_FIELD_BB;
+    case MATROSKA_VIDEO_FIELDORDER_BT:
+        return AV_FIELD_BT;
+    case MATROSKA_VIDEO_FIELDORDER_TB:
+        return AV_FIELD_TB;
+    default:
+        return AV_FIELD_UNKNOWN;
+    }
+}
+
+static void mkv_stereo_mode_display_mul(int stereo_mode,
+                                        int *h_width, int *h_height)
 {
     switch (stereo_mode) {
         case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO:
@@ -1708,6 +1800,69 @@ static void mkv_stereo_mode_display_mul(int stereo_mode, int *h_width, int *h_he
     }
 }
 
+static int mkv_parse_video_color(AVStream *st, const MatroskaTrack *track) {
+    const MatroskaMasteringMeta* mastering_meta =
+        &track->video.color.mastering_meta;
+    // Mastering primaries are CIE 1931 coords, and must be > 0.
+    const int has_mastering_primaries =
+        mastering_meta->r_x > 0 && mastering_meta->r_y > 0 &&
+        mastering_meta->g_x > 0 && mastering_meta->g_y > 0 &&
+        mastering_meta->b_x > 0 && mastering_meta->b_y > 0 &&
+        mastering_meta->white_x > 0 && mastering_meta->white_y > 0;
+    const int has_mastering_luminance = mastering_meta->max_luminance > 0;
+
+    if (track->video.color.matrix_coefficients != AVCOL_SPC_RESERVED)
+        st->codecpar->color_space = track->video.color.matrix_coefficients;
+    if (track->video.color.primaries != AVCOL_PRI_RESERVED)
+        st->codecpar->color_primaries = track->video.color.primaries;
+    if (track->video.color.transfer_characteristics != AVCOL_TRC_RESERVED)
+        st->codecpar->color_trc = track->video.color.transfer_characteristics;
+    if (track->video.color.range != AVCOL_RANGE_UNSPECIFIED &&
+        track->video.color.range <= AVCOL_RANGE_JPEG)
+        st->codecpar->color_range = track->video.color.range;
+
+    if (has_mastering_primaries || has_mastering_luminance) {
+        // Use similar rationals as other standards.
+        const int chroma_den = 50000;
+        const int luma_den = 10000;
+        AVMasteringDisplayMetadata *metadata =
+            (AVMasteringDisplayMetadata*) av_stream_new_side_data(
+                st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
+                sizeof(AVMasteringDisplayMetadata));
+        if (!metadata) {
+            return AVERROR(ENOMEM);
+        }
+        memset(metadata, 0, sizeof(AVMasteringDisplayMetadata));
+        if (has_mastering_primaries) {
+            metadata->display_primaries[0][0] = av_make_q(
+                round(mastering_meta->r_x * chroma_den), chroma_den);
+            metadata->display_primaries[0][1] = av_make_q(
+                round(mastering_meta->r_y * chroma_den), chroma_den);
+            metadata->display_primaries[1][0] = av_make_q(
+                round(mastering_meta->g_x * chroma_den), chroma_den);
+            metadata->display_primaries[1][1] = av_make_q(
+                round(mastering_meta->g_y * chroma_den), chroma_den);
+            metadata->display_primaries[2][0] = av_make_q(
+                round(mastering_meta->b_x * chroma_den), chroma_den);
+            metadata->display_primaries[2][1] = av_make_q(
+                round(mastering_meta->b_y * chroma_den), chroma_den);
+            metadata->white_point[0] = av_make_q(
+                round(mastering_meta->white_x * chroma_den), chroma_den);
+            metadata->white_point[1] = av_make_q(
+                round(mastering_meta->white_y * chroma_den), chroma_den);
+            metadata->has_primaries = 1;
+        }
+        if (has_mastering_luminance) {
+            metadata->max_luminance = av_make_q(
+                round(mastering_meta->max_luminance * luma_den), luma_den);
+            metadata->min_luminance = av_make_q(
+                round(mastering_meta->min_luminance * luma_den), luma_den);
+            metadata->has_luminance = 1;
+        }
+    }
+    return 0;
+}
+
 static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *codec_id)
 {
     const AVCodecTag *codec_tags;
@@ -1881,11 +2036,11 @@ static int matroska_parse_tracks(AVFormatContext *s)
             ffio_init_context(&b, track->codec_priv.data,
                               track->codec_priv.size,
                               0, NULL, NULL, NULL, NULL);
-            ret = ff_get_wav_header(s, &b, st->codec, track->codec_priv.size, 0);
+            ret = ff_get_wav_header(s, &b, st->codecpar, track->codec_priv.size, 0);
             if (ret < 0)
                 return ret;
-            codec_id         = st->codec->codec_id;
-            fourcc           = st->codec->codec_tag;
+            codec_id         = st->codecpar->codec_id;
+            fourcc           = st->codecpar->codec_tag;
             extradata_offset = FFMIN(track->codec_priv.size, 18);
         } else if (!strcmp(track->codec_id, "A_QUICKTIME")
                    /* Normally 36, but allow noncompliant private data */
@@ -1930,9 +2085,9 @@ static int matroska_parse_tracks(AVFormatContext *s)
                 ffio_init_context(&b, track->codec_priv.data,
                                   track->codec_priv.size,
                                   0, NULL, NULL, NULL, NULL);
-                if (ff_get_qtpalette(codec_id, &b, matroska->palette)) {
+                if (ff_get_qtpalette(codec_id, &b, track->palette)) {
                     bit_depth &= 0x1F;
-                    matroska->has_palette = 1;
+                    track->has_palette = 1;
                 }
             }
         } else if (codec_id == AV_CODEC_ID_PCM_S16BE) {
@@ -2057,15 +2212,15 @@ static int matroska_parse_tracks(AVFormatContext *s)
             if (!track->audio.buf)
                 return AVERROR(ENOMEM);
             if (codec_id == AV_CODEC_ID_RA_288) {
-                st->codec->block_align = track->audio.coded_framesize;
+                st->codecpar->block_align = track->audio.coded_framesize;
                 track->codec_priv.size = 0;
             } else {
                 if (codec_id == AV_CODEC_ID_SIPR && flavor < 4) {
                     static const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 };
                     track->audio.sub_packet_size = ff_sipr_subpk_size[flavor];
-                    st->codec->bit_rate          = sipr_bit_rate[flavor];
+                    st->codecpar->bit_rate          = sipr_bit_rate[flavor];
                 }
-                st->codec->block_align = track->audio.sub_packet_size;
+                st->codecpar->block_align = track->audio.sub_packet_size;
                 extradata_offset       = 78;
             }
         } else if (codec_id == AV_CODEC_ID_FLAC && track->codec_priv.size) {
@@ -2087,11 +2242,11 @@ static int matroska_parse_tracks(AVFormatContext *s)
                             1000 * 1000 * 1000);    /* 64 bit pts in ns */
 
         /* convert the delay from ns to the track timebase */
-        track->codec_delay = av_rescale_q(track->codec_delay,
+        track->codec_delay_in_track_tb = av_rescale_q(track->codec_delay,
                                           (AVRational){ 1, 1000000000 },
                                           st->time_base);
 
-        st->codec->codec_id = codec_id;
+        st->codecpar->codec_id = codec_id;
 
         if (strcmp(track->language, "und"))
             av_dict_set(&st->metadata, "language", track->language, 0);
@@ -2102,14 +2257,14 @@ static int matroska_parse_tracks(AVFormatContext *s)
         if (track->flag_forced)
             st->disposition |= AV_DISPOSITION_FORCED;
 
-        if (!st->codec->extradata) {
+        if (!st->codecpar->extradata) {
             if (extradata) {
-                st->codec->extradata      = extradata;
-                st->codec->extradata_size = extradata_size;
+                st->codecpar->extradata      = extradata;
+                st->codecpar->extradata_size = extradata_size;
             } else if (track->codec_priv.data && track->codec_priv.size > 0) {
-                if (ff_alloc_extradata(st->codec, track->codec_priv.size))
+                if (ff_alloc_extradata(st->codecpar, track->codec_priv.size))
                     return AVERROR(ENOMEM);
-                memcpy(st->codec->extradata,
+                memcpy(st->codecpar->extradata,
                        track->codec_priv.data + extradata_offset,
                        track->codec_priv.size);
             }
@@ -2120,22 +2275,25 @@ static int matroska_parse_tracks(AVFormatContext *s)
             int display_width_mul  = 1;
             int display_height_mul = 1;
 
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_tag  = fourcc;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_tag  = fourcc;
             if (bit_depth >= 0)
-                st->codec->bits_per_coded_sample = bit_depth;
-            st->codec->width      = track->video.pixel_width;
-            st->codec->height     = track->video.pixel_height;
+                st->codecpar->bits_per_coded_sample = bit_depth;
+            st->codecpar->width      = track->video.pixel_width;
+            st->codecpar->height     = track->video.pixel_height;
+
+            if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED)
+                st->codecpar->field_order = mkv_field_order(track->video.field_order);
 
             if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB)
                 mkv_stereo_mode_display_mul(track->video.stereo_mode, &display_width_mul, &display_height_mul);
 
             av_reduce(&st->sample_aspect_ratio.num,
                       &st->sample_aspect_ratio.den,
-                      st->codec->height * track->video.display_width  * display_width_mul,
-                      st->codec->width  * track->video.display_height * display_height_mul,
+                      st->codecpar->height * track->video.display_width  * display_width_mul,
+                      st->codecpar->width  * track->video.display_height * display_height_mul,
                       255);
-            if (st->codec->codec_id != AV_CODEC_ID_HEVC)
+            if (st->codecpar->codec_id != AV_CODEC_ID_HEVC)
                 st->need_parsing = AVSTREAM_PARSE_HEADERS;
 
             if (track->default_duration) {
@@ -2177,30 +2335,36 @@ static int matroska_parse_tracks(AVFormatContext *s)
                 if (ret < 0)
                     return ret;
             }
+
+            if (s->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
+                int ret = mkv_parse_video_color(st, track);
+                if (ret < 0)
+                    return ret;
+            }
         } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
-            st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-            st->codec->codec_tag   = fourcc;
-            st->codec->sample_rate = track->audio.out_samplerate;
-            st->codec->channels    = track->audio.channels;
-            if (!st->codec->bits_per_coded_sample)
-                st->codec->bits_per_coded_sample = track->audio.bitdepth;
-            if (st->codec->codec_id == AV_CODEC_ID_MP3)
+            st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_tag   = fourcc;
+            st->codecpar->sample_rate = track->audio.out_samplerate;
+            st->codecpar->channels    = track->audio.channels;
+            if (!st->codecpar->bits_per_coded_sample)
+                st->codecpar->bits_per_coded_sample = track->audio.bitdepth;
+            if (st->codecpar->codec_id == AV_CODEC_ID_MP3)
                 st->need_parsing = AVSTREAM_PARSE_FULL;
-            else if (st->codec->codec_id != AV_CODEC_ID_AAC)
+            else if (st->codecpar->codec_id != AV_CODEC_ID_AAC)
                 st->need_parsing = AVSTREAM_PARSE_HEADERS;
             if (track->codec_delay > 0) {
-                st->codec->delay = av_rescale_q(track->codec_delay,
-                                                st->time_base,
-                                                (AVRational){1, st->codec->sample_rate});
+                st->codecpar->initial_padding = av_rescale_q(track->codec_delay,
+                                                             (AVRational){1, 1000000000},
+                                                             (AVRational){1, st->codecpar->codec_id == AV_CODEC_ID_OPUS ?
+                                                                             48000 : st->codecpar->sample_rate});
             }
             if (track->seek_preroll > 0) {
-                av_codec_set_seek_preroll(st->codec,
-                                          av_rescale_q(track->seek_preroll,
-                                                       (AVRational){1, 1000000000},
-                                                       (AVRational){1, st->codec->sample_rate}));
+                st->codecpar->seek_preroll = av_rescale_q(track->seek_preroll,
+                                                          (AVRational){1, 1000000000},
+                                                          (AVRational){1, st->codecpar->sample_rate});
             }
         } else if (codec_id == AV_CODEC_ID_WEBVTT) {
-            st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
+            st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
 
             if (!strcmp(track->codec_id, "D_WEBVTT/CAPTIONS")) {
                 st->disposition |= AV_DISPOSITION_CAPTIONS;
@@ -2210,8 +2374,8 @@ static int matroska_parse_tracks(AVFormatContext *s)
                 st->disposition |= AV_DISPOSITION_METADATA;
             }
         } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) {
-            st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-            if (st->codec->codec_id == AV_CODEC_ID_ASS)
+            st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+            if (st->codecpar->codec_id == AV_CODEC_ID_ASS)
                 matroska->contains_ssa = 1;
         }
     }
@@ -2275,7 +2439,7 @@ static int matroska_read_header(AVFormatContext *s)
     while (res != 1) {
         res = matroska_resync(matroska, pos);
         if (res < 0)
-            return res;
+            goto fail;
         pos = avio_tell(matroska->ctx->pb);
         res = ebml_parse(matroska, matroska_segment, matroska);
     }
@@ -2294,7 +2458,7 @@ static int matroska_read_header(AVFormatContext *s)
 
     res = matroska_parse_tracks(s);
     if (res < 0)
-        return res;
+        goto fail;
 
     attachments = attachments_list->elem;
     for (j = 0; j < attachments_list->nb_elem; j++) {
@@ -2307,21 +2471,21 @@ static int matroska_read_header(AVFormatContext *s)
                 break;
             av_dict_set(&st->metadata, "filename", attachments[j].filename, 0);
             av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0);
-            st->codec->codec_id   = AV_CODEC_ID_NONE;
+            st->codecpar->codec_id   = AV_CODEC_ID_NONE;
 
             for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) {
                 if (!strncmp(ff_mkv_image_mime_tags[i].str, attachments[j].mime,
                              strlen(ff_mkv_image_mime_tags[i].str))) {
-                    st->codec->codec_id = ff_mkv_image_mime_tags[i].id;
+                    st->codecpar->codec_id = ff_mkv_image_mime_tags[i].id;
                     break;
                 }
             }
 
             attachments[j].stream = st;
 
-            if (st->codec->codec_id != AV_CODEC_ID_NONE) {
-                st->disposition      |= AV_DISPOSITION_ATTACHED_PIC;
-                st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+            if (st->codecpar->codec_id != AV_CODEC_ID_NONE) {
+                st->disposition         |= AV_DISPOSITION_ATTACHED_PIC;
+                st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
 
                 av_init_packet(&st->attached_pic);
                 if ((res = av_new_packet(&st->attached_pic, attachments[j].bin.size)) < 0)
@@ -2330,16 +2494,16 @@ static int matroska_read_header(AVFormatContext *s)
                 st->attached_pic.stream_index = st->index;
                 st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
             } else {
-                st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
-                if (ff_alloc_extradata(st->codec, attachments[j].bin.size))
+                st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT;
+                if (ff_alloc_extradata(st->codecpar, attachments[j].bin.size))
                     break;
-                memcpy(st->codec->extradata, attachments[j].bin.data,
+                memcpy(st->codecpar->extradata, attachments[j].bin.data,
                        attachments[j].bin.size);
 
                 for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) {
                     if (!strncmp(ff_mkv_mime_tags[i].str, attachments[j].mime,
                                 strlen(ff_mkv_mime_tags[i].str))) {
-                        st->codec->codec_id = ff_mkv_mime_tags[i].id;
+                        st->codecpar->codec_id = ff_mkv_mime_tags[i].id;
                         break;
                     }
                 }
@@ -2368,6 +2532,9 @@ static int matroska_read_header(AVFormatContext *s)
     matroska_convert_tags(s);
 
     return 0;
+fail:
+    matroska_read_close(s);
+    return res;
 }
 
 /*
@@ -2378,16 +2545,19 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska,
                                    AVPacket *pkt)
 {
     if (matroska->num_packets > 0) {
+        MatroskaTrack *tracks = matroska->tracks.elem;
+        MatroskaTrack *track;
         memcpy(pkt, matroska->packets[0], sizeof(AVPacket));
         av_freep(&matroska->packets[0]);
-        if (matroska->has_palette) {
+        track = &tracks[pkt->stream_index];
+        if (track->has_palette) {
             uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
             if (!pal) {
                 av_log(matroska->ctx, AV_LOG_ERROR, "Cannot append palette to packet\n");
             } else {
-                memcpy(pal, matroska->palette, AVPALETTE_SIZE);
+                memcpy(pal, track->palette, AVPALETTE_SIZE);
             }
-            matroska->has_palette = 0;
+            track->has_palette = 0;
         }
         if (matroska->num_packets > 1) {
             void *newpackets;
@@ -2540,7 +2710,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
                                    uint8_t *data, int size, uint64_t timecode,
                                    int64_t pos)
 {
-    int a = st->codec->block_align;
+    int a = st->codecpar->block_align;
     int sps = track->audio.sub_packet_size;
     int cfs = track->audio.coded_framesize;
     int h   = track->audio.sub_packet_h;
@@ -2551,7 +2721,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
     if (!track->audio.pkt_cnt) {
         if (track->audio.sub_packet_cnt == 0)
             track->audio.buf_timecode = timecode;
-        if (st->codec->codec_id == AV_CODEC_ID_RA_288) {
+        if (st->codecpar->codec_id == AV_CODEC_ID_RA_288) {
             if (size < cfs * h / 2) {
                 av_log(matroska->ctx, AV_LOG_ERROR,
                        "Corrupt int4 RM-style audio packet size\n");
@@ -2560,7 +2730,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
             for (x = 0; x < h / 2; x++)
                 memcpy(track->audio.buf + x * 2 * w + y * cfs,
                        data + x * cfs, cfs);
-        } else if (st->codec->codec_id == AV_CODEC_ID_SIPR) {
+        } else if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) {
             if (size < w) {
                 av_log(matroska->ctx, AV_LOG_ERROR,
                        "Corrupt sipr RM-style audio packet size\n");
@@ -2580,7 +2750,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
         }
 
         if (++track->audio.sub_packet_cnt >= h) {
-            if (st->codec->codec_id == AV_CODEC_ID_SIPR)
+            if (st->codecpar->codec_id == AV_CODEC_ID_SIPR)
                 ff_rm_reorder_sipr_data(track->audio.buf, h, w);
             track->audio.sub_packet_cnt = 0;
             track->audio.pkt_cnt        = h * w / a;
@@ -2622,10 +2792,10 @@ static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src,
     uint16_t ver;
     int ret, offset = 0;
 
-    if (srclen < 12 || track->stream->codec->extradata_size < 2)
+    if (srclen < 12 || track->stream->codecpar->extradata_size < 2)
         return AVERROR_INVALIDDATA;
 
-    ver = AV_RL16(track->stream->codec->extradata);
+    ver = AV_RL16(track->stream->codecpar->extradata);
 
     samples = AV_RL32(src);
     src    += 4;
@@ -2827,7 +2997,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
             return res;
     }
 
-    if (st->codec->codec_id == AV_CODEC_ID_WAVPACK) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_WAVPACK) {
         uint8_t *wv_data;
         res = matroska_parse_wavpack(track, pkt_data, &wv_data, &pkt_size);
         if (res < 0) {
@@ -2840,7 +3010,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
         pkt_data = wv_data;
     }
 
-    if (st->codec->codec_id == AV_CODEC_ID_PRORES &&
+    if (st->codecpar->codec_id == AV_CODEC_ID_PRORES &&
         AV_RB32(&data[4]) != MKBETAG('i', 'c', 'p', 'f'))
         offset = 8;
 
@@ -2857,7 +3027,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
         goto fail;
     }
 
-    if (st->codec->codec_id == AV_CODEC_ID_PRORES && offset == 8) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_PRORES && offset == 8) {
         uint8_t *buf = pkt->data;
         bytestream_put_be32(&buf, pkt_size);
         bytestream_put_be32(&buf, MKBETAG('i', 'c', 'p', 'f'));
@@ -2896,7 +3066,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
         AV_WL32(side_data, 0);
         AV_WL32(side_data + 4, av_rescale_q(discard_padding,
                                             (AVRational){1, 1000000000},
-                                            (AVRational){1, st->codec->sample_rate}));
+                                            (AVRational){1, st->codecpar->sample_rate}));
     }
 
     if (track->ms_compat)
@@ -2908,7 +3078,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
 
 #if FF_API_CONVERGENCE_DURATION
 FF_DISABLE_DEPRECATION_WARNINGS
-    if (st->codec->codec_id == AV_CODEC_ID_SUBRIP) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_SUBRIP) {
         pkt->convergence_duration = lace_duration;
     }
 FF_ENABLE_DEPRECATION_WARNINGS
@@ -2969,7 +3139,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
 
     if (cluster_time != (uint64_t) -1 &&
         (block_time >= 0 || cluster_time >= -block_time)) {
-        timecode = cluster_time + block_time - track->codec_delay;
+        timecode = cluster_time + block_time - track->codec_delay_in_track_tb;
         if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE &&
             timecode < track->end_timecode)
             is_keyframe = 0;  /* overlapping subtitles are not key frame */
@@ -2998,8 +3168,8 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
 
     if (track->audio.samplerate == 8000) {
         // If this is needed for more codecs, then add them here
-        if (st->codec->codec_id == AV_CODEC_ID_AC3) {
-            if (track->audio.samplerate != st->codec->sample_rate || !st->codec->frame_size)
+        if (st->codecpar->codec_id == AV_CODEC_ID_AC3) {
+            if (track->audio.samplerate != st->codecpar->sample_rate || !st->codecpar->frame_size)
                 trust_default_duration = 0;
         }
     }
@@ -3019,18 +3189,18 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
             break;
         }
 
-        if ((st->codec->codec_id == AV_CODEC_ID_RA_288 ||
-             st->codec->codec_id == AV_CODEC_ID_COOK   ||
-             st->codec->codec_id == AV_CODEC_ID_SIPR   ||
-             st->codec->codec_id == AV_CODEC_ID_ATRAC3) &&
-            st->codec->block_align && track->audio.sub_packet_size) {
+        if ((st->codecpar->codec_id == AV_CODEC_ID_RA_288 ||
+             st->codecpar->codec_id == AV_CODEC_ID_COOK   ||
+             st->codecpar->codec_id == AV_CODEC_ID_SIPR   ||
+             st->codecpar->codec_id == AV_CODEC_ID_ATRAC3) &&
+            st->codecpar->block_align && track->audio.sub_packet_size) {
             res = matroska_parse_rm_audio(matroska, track, st, data,
                                           lace_size[n],
                                           timecode, pos);
             if (res)
                 goto end;
 
-        } else if (st->codec->codec_id == AV_CODEC_ID_WEBVTT) {
+        } else if (st->codecpar->codec_id == AV_CODEC_ID_WEBVTT) {
             res = matroska_parse_webvtt(matroska, track, st,
                                         data, lace_size[n],
                                         timecode, lace_duration,
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index f42434b..53353bd 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -41,6 +41,7 @@
 #include "libavutil/intfloat.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/lfg.h"
+#include "libavutil/mastering_display_metadata.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/random_seed.h"
@@ -118,6 +119,7 @@ typedef struct MatroskaMuxContext {
     AVPacket        cur_audio_pkt;
 
     int have_attachments;
+    int have_video;
 
     int reserve_cues_space;
     int cluster_size_limit;
@@ -485,7 +487,7 @@ static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tra
         for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) {
             int tracknum = entry[j].stream_idx;
             av_assert0(tracknum>=0 && tracknum<num_tracks);
-            if (tracks[tracknum].has_cue && s->streams[tracknum]->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)
+            if (tracks[tracknum].has_cue && s->streams[tracknum]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
                 continue;
             tracks[tracknum].has_cue = 1;
             ctp_nb ++;
@@ -501,7 +503,7 @@ static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tra
         for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) {
             int tracknum = entry[j].stream_idx;
             av_assert0(tracknum>=0 && tracknum<num_tracks);
-            if (tracks[tracknum].has_cue && s->streams[tracknum]->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)
+            if (tracks[tracknum].has_cue && s->streams[tracknum]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
                 continue;
             tracks[tracknum].has_cue = 1;
             track_positions = start_ebml_master(pb, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE);
@@ -520,19 +522,19 @@ static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tra
     return currentpos;
 }
 
-static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, AVCodecContext *codec)
+static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par)
 {
     const uint8_t *header_start[3];
     int header_len[3];
     int first_header_size;
     int j;
 
-    if (codec->codec_id == AV_CODEC_ID_VORBIS)
+    if (par->codec_id == AV_CODEC_ID_VORBIS)
         first_header_size = 30;
     else
         first_header_size = 42;
 
-    if (avpriv_split_xiph_headers(codec->extradata, codec->extradata_size,
+    if (avpriv_split_xiph_headers(par->extradata, par->extradata_size,
                               first_header_size, header_start, header_len) < 0) {
         av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
         return -1;
@@ -548,22 +550,22 @@ static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, AVCodecContex
     return 0;
 }
 
-static int put_wv_codecpriv(AVIOContext *pb, AVCodecContext *codec)
+static int put_wv_codecpriv(AVIOContext *pb, AVCodecParameters *par)
 {
-    if (codec->extradata && codec->extradata_size == 2)
-        avio_write(pb, codec->extradata, 2);
+    if (par->extradata && par->extradata_size == 2)
+        avio_write(pb, par->extradata, 2);
     else
         avio_wl16(pb, 0x403); // fallback to the version mentioned in matroska specs
     return 0;
 }
 
 static int put_flac_codecpriv(AVFormatContext *s,
-                              AVIOContext *pb, AVCodecContext *codec)
+                              AVIOContext *pb, AVCodecParameters *par)
 {
-    int write_comment = (codec->channel_layout &&
-                         !(codec->channel_layout & ~0x3ffffULL) &&
-                         !ff_flac_is_native_layout(codec->channel_layout));
-    int ret = ff_flac_write_header(pb, codec->extradata, codec->extradata_size,
+    int write_comment = (par->channel_layout &&
+                         !(par->channel_layout & ~0x3ffffULL) &&
+                         !ff_flac_is_native_layout(par->channel_layout));
+    int ret = ff_flac_write_header(pb, par->extradata, par->extradata_size,
                                    !write_comment);
 
     if (ret < 0)
@@ -576,7 +578,7 @@ static int put_flac_codecpriv(AVFormatContext *s,
         uint8_t buf[32], *data, *p;
         int64_t len;
 
-        snprintf(buf, sizeof(buf), "0x%"PRIx64, codec->channel_layout);
+        snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout);
         av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0);
 
         len = ff_vorbiscomment_length(dict, vendor);
@@ -604,13 +606,13 @@ static int put_flac_codecpriv(AVFormatContext *s,
     return 0;
 }
 
-static int get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec,
+static int get_aac_sample_rates(AVFormatContext *s, AVCodecParameters *par,
                                 int *sample_rate, int *output_sample_rate)
 {
     MPEG4AudioConfig mp4ac;
 
-    if (avpriv_mpeg4audio_get_config(&mp4ac, codec->extradata,
-                                     codec->extradata_size * 8, 1) < 0) {
+    if (avpriv_mpeg4audio_get_config(&mp4ac, par->extradata,
+                                     par->extradata_size * 8, 1) < 0) {
         av_log(s, AV_LOG_ERROR,
                "Error parsing AAC extradata, unable to determine samplerate.\n");
         return AVERROR(EINVAL);
@@ -622,48 +624,48 @@ static int get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec,
 }
 
 static int mkv_write_native_codecprivate(AVFormatContext *s,
-                                         AVCodecContext *codec,
+                                         AVCodecParameters *par,
                                          AVIOContext *dyn_cp)
 {
-    switch (codec->codec_id) {
+    switch (par->codec_id) {
     case AV_CODEC_ID_VORBIS:
     case AV_CODEC_ID_THEORA:
-        return put_xiph_codecpriv(s, dyn_cp, codec);
+        return put_xiph_codecpriv(s, dyn_cp, par);
     case AV_CODEC_ID_FLAC:
-        return put_flac_codecpriv(s, dyn_cp, codec);
+        return put_flac_codecpriv(s, dyn_cp, par);
     case AV_CODEC_ID_WAVPACK:
-        return put_wv_codecpriv(dyn_cp, codec);
+        return put_wv_codecpriv(dyn_cp, par);
     case AV_CODEC_ID_H264:
-        return ff_isom_write_avcc(dyn_cp, codec->extradata,
-                                  codec->extradata_size);
+        return ff_isom_write_avcc(dyn_cp, par->extradata,
+                                  par->extradata_size);
     case AV_CODEC_ID_HEVC:
-        ff_isom_write_hvcc(dyn_cp, codec->extradata,
-                           codec->extradata_size, 0);
+        ff_isom_write_hvcc(dyn_cp, par->extradata,
+                           par->extradata_size, 0);
         return 0;
     case AV_CODEC_ID_ALAC:
-        if (codec->extradata_size < 36) {
+        if (par->extradata_size < 36) {
             av_log(s, AV_LOG_ERROR,
                    "Invalid extradata found, ALAC expects a 36-byte "
                    "QuickTime atom.");
             return AVERROR_INVALIDDATA;
         } else
-            avio_write(dyn_cp, codec->extradata + 12,
-                       codec->extradata_size - 12);
+            avio_write(dyn_cp, par->extradata + 12,
+                       par->extradata_size - 12);
         break;
     default:
-        if (codec->codec_id == AV_CODEC_ID_PRORES &&
-            ff_codec_get_id(ff_codec_movvideo_tags, codec->codec_tag) == AV_CODEC_ID_PRORES) {
-            avio_wl32(dyn_cp, codec->codec_tag);
-        } else if (codec->extradata_size && codec->codec_id != AV_CODEC_ID_TTA)
-            avio_write(dyn_cp, codec->extradata, codec->extradata_size);
+        if (par->codec_id == AV_CODEC_ID_PRORES &&
+            ff_codec_get_id(ff_codec_movvideo_tags, par->codec_tag) == AV_CODEC_ID_PRORES) {
+            avio_wl32(dyn_cp, par->codec_tag);
+        } else if (par->extradata_size && par->codec_id != AV_CODEC_ID_TTA)
+            avio_write(dyn_cp, par->extradata, par->extradata_size);
     }
 
     return 0;
 }
 
 static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb,
-                                  AVCodecContext *codec, int native_id,
-                                  int qt_id)
+                                  AVCodecParameters *par,
+                                  int native_id, int qt_id)
 {
     AVIOContext *dyn_cp;
     uint8_t *codecpriv;
@@ -674,52 +676,52 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb,
         return ret;
 
     if (native_id) {
-        ret = mkv_write_native_codecprivate(s, codec, dyn_cp);
-    } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        ret = mkv_write_native_codecprivate(s, par, dyn_cp);
+    } else if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
         if (qt_id) {
-            if (!codec->codec_tag)
-                codec->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags,
-                                                    codec->codec_id);
-            if (codec->extradata_size) {
-                if (   ff_codec_get_id(ff_codec_movvideo_tags, codec->codec_tag) == codec->codec_id
-                    && ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(codec->extradata + 4)) != codec->codec_id
+            if (!par->codec_tag)
+                par->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags,
+                                                    par->codec_id);
+            if (par->extradata_size) {
+                if (   ff_codec_get_id(ff_codec_movvideo_tags, par->codec_tag) == par->codec_id
+                    && ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(par->extradata + 4)) != par->codec_id
                 ) {
                     int i;
-                    avio_wb32(dyn_cp, 0x5a + codec->extradata_size);
-                    avio_wl32(dyn_cp, codec->codec_tag);
+                    avio_wb32(dyn_cp, 0x5a + par->extradata_size);
+                    avio_wl32(dyn_cp, par->codec_tag);
                     for(i = 0; i < 0x5a - 8; i++)
                         avio_w8(dyn_cp, 0);
                 }
-                avio_write(dyn_cp, codec->extradata, codec->extradata_size);
+                avio_write(dyn_cp, par->extradata, par->extradata_size);
             }
         } else {
-            if (!ff_codec_get_tag(ff_codec_bmp_tags, codec->codec_id))
+            if (!ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id))
                 av_log(s, AV_LOG_WARNING, "codec %s is not supported by this format\n",
-                       avcodec_get_name(codec->codec_id));
+                       avcodec_get_name(par->codec_id));
 
-            if (!codec->codec_tag)
-                codec->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags,
-                                                    codec->codec_id);
-            if (!codec->codec_tag && codec->codec_id != AV_CODEC_ID_RAWVIDEO) {
+            if (!par->codec_tag)
+                par->codec_tag = ff_codec_get_tag(ff_codec_bmp_tags,
+                                                  par->codec_id);
+            if (!par->codec_tag && par->codec_id != AV_CODEC_ID_RAWVIDEO) {
                 av_log(s, AV_LOG_ERROR, "No bmp codec tag found for codec %s\n",
-                       avcodec_get_name(codec->codec_id));
+                       avcodec_get_name(par->codec_id));
                 ret = AVERROR(EINVAL);
             }
 
-            ff_put_bmp_header(dyn_cp, codec, ff_codec_bmp_tags, 0, 0);
+            ff_put_bmp_header(dyn_cp, par, ff_codec_bmp_tags, 0, 0);
         }
-    } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+    } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
         unsigned int tag;
-        tag = ff_codec_get_tag(ff_codec_wav_tags, codec->codec_id);
+        tag = ff_codec_get_tag(ff_codec_wav_tags, par->codec_id);
         if (!tag) {
             av_log(s, AV_LOG_ERROR, "No wav codec tag found for codec %s\n",
-                   avcodec_get_name(codec->codec_id));
+                   avcodec_get_name(par->codec_id));
             ret = AVERROR(EINVAL);
         }
-        if (!codec->codec_tag)
-            codec->codec_tag = tag;
+        if (!par->codec_tag)
+            par->codec_tag = tag;
 
-        ff_put_wav_header(dyn_cp, codec, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
+        ff_put_wav_header(s, dyn_cp, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX);
     }
 
     codecpriv_size = avio_close_dyn_buf(dyn_cp, &codecpriv);
@@ -730,6 +732,102 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb,
     return ret;
 }
 
+static int mkv_write_video_color(AVIOContext *pb, AVCodecParameters *par, AVStream *st) {
+    int side_data_size = 0;
+    const uint8_t *side_data = av_stream_get_side_data(
+        st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, &side_data_size);
+    ebml_master colorinfo = start_ebml_master(pb, MATROSKA_ID_VIDEOCOLOR, 0);
+
+    if (par->color_trc != AVCOL_TRC_UNSPECIFIED &&
+        par->color_trc < AVCOL_TRC_NB) {
+        put_ebml_uint(pb, MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS,
+                      par->color_trc);
+    }
+    if (par->color_space != AVCOL_SPC_UNSPECIFIED &&
+        par->color_space < AVCOL_SPC_NB) {
+        put_ebml_uint(pb, MATROSKA_ID_VIDEOCOLORMATRIXCOEFF, par->color_space);
+    }
+    if (par->color_primaries != AVCOL_PRI_UNSPECIFIED &&
+        par->color_primaries < AVCOL_PRI_NB) {
+        put_ebml_uint(pb, MATROSKA_ID_VIDEOCOLORPRIMARIES, par->color_primaries);
+    }
+    if (par->color_range != AVCOL_RANGE_UNSPECIFIED &&
+        par->color_range < AVCOL_RANGE_NB) {
+        put_ebml_uint(pb, MATROSKA_ID_VIDEOCOLORRANGE, par->color_range);
+    }
+    if (side_data_size == sizeof(AVMasteringDisplayMetadata)) {
+        ebml_master meta_element = start_ebml_master(
+            pb, MATROSKA_ID_VIDEOCOLORMASTERINGMETA, 0);
+        const AVMasteringDisplayMetadata *metadata =
+            (const AVMasteringDisplayMetadata*)side_data;
+        if (metadata->has_primaries) {
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_RX,
+                           av_q2d(metadata->display_primaries[0][0]));
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_RY,
+                           av_q2d(metadata->display_primaries[0][1]));
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_GX,
+                           av_q2d(metadata->display_primaries[1][0]));
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_GY,
+                           av_q2d(metadata->display_primaries[1][1]));
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_BX,
+                           av_q2d(metadata->display_primaries[2][0]));
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_BY,
+                           av_q2d(metadata->display_primaries[2][1]));
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_WHITEX,
+                           av_q2d(metadata->white_point[0]));
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_WHITEY,
+                           av_q2d(metadata->white_point[1]));
+        }
+        if (metadata->has_luminance) {
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX,
+                           av_q2d(metadata->max_luminance));
+            put_ebml_float(pb, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN,
+                           av_q2d(metadata->min_luminance));
+        }
+        end_ebml_master(pb, meta_element);
+    }
+    end_ebml_master(pb, colorinfo);
+    return 0;
+}
+
+static void mkv_write_field_order(AVIOContext *pb,
+                                  enum AVFieldOrder field_order)
+{
+    switch (field_order) {
+    case AV_FIELD_UNKNOWN:
+        put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED,
+                      MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED);
+        break;
+    case AV_FIELD_PROGRESSIVE:
+        put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED,
+                      MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE);
+        break;
+    case AV_FIELD_TT:
+    case AV_FIELD_BB:
+    case AV_FIELD_TB:
+    case AV_FIELD_BT:
+        put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED,
+                      MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED);
+        switch (field_order) {
+        case AV_FIELD_TT:
+            put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER,
+                          MATROSKA_VIDEO_FIELDORDER_TT);
+            break;
+        case AV_FIELD_BB:
+             put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER,
+                          MATROSKA_VIDEO_FIELDORDER_BB);
+            break;
+        case AV_FIELD_TB:
+            put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER,
+                          MATROSKA_VIDEO_FIELDORDER_TB);
+            break;
+        case AV_FIELD_BT:
+            put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER,
+                          MATROSKA_VIDEO_FIELDORDER_BT);
+            break;
+        }
+    }
+}
 
 static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb,
                                  AVStream *st, int mode, int *h_width, int *h_height)
@@ -833,30 +931,36 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
                            int i, AVIOContext *pb, int default_stream_exists)
 {
     AVStream *st = s->streams[i];
-    AVCodecContext *codec = st->codec;
+    AVCodecParameters *par = st->codecpar;
     ebml_master subinfo, track;
     int native_id = 0;
     int qt_id = 0;
-    int bit_depth = av_get_bits_per_sample(codec->codec_id);
-    int sample_rate = codec->sample_rate;
+    int bit_depth = av_get_bits_per_sample(par->codec_id);
+    int sample_rate = par->sample_rate;
     int output_sample_rate = 0;
     int display_width_div = 1;
     int display_height_div = 1;
     int j, ret;
     AVDictionaryEntry *tag;
 
-    if (codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
+    if (par->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
         mkv->have_attachments = 1;
         return 0;
     }
 
-    if (!bit_depth && codec->codec_id != AV_CODEC_ID_ADPCM_G726)
-        bit_depth = av_get_bytes_per_sample(codec->sample_fmt) << 3;
-    if (!bit_depth)
-        bit_depth = codec->bits_per_coded_sample;
+    if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (!bit_depth && par->codec_id != AV_CODEC_ID_ADPCM_G726) {
+            if (par->bits_per_raw_sample)
+                bit_depth = par->bits_per_raw_sample;
+            else
+                bit_depth = av_get_bytes_per_sample(par->format) << 3;
+        }
+        if (!bit_depth)
+            bit_depth = par->bits_per_coded_sample;
+    }
 
-    if (codec->codec_id == AV_CODEC_ID_AAC) {
-        ret = get_aac_sample_rates(s, codec, &sample_rate, &output_sample_rate);
+    if (par->codec_id == AV_CODEC_ID_AAC) {
+        ret = get_aac_sample_rates(s, par, &sample_rate, &output_sample_rate);
         if (ret < 0)
             return ret;
     }
@@ -871,7 +975,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
     if ((tag = av_dict_get(st->metadata, "title", NULL, 0)))
         put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value);
     tag = av_dict_get(st->metadata, "language", NULL, 0);
-    if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) {
+    if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT) {
         put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag && tag->value ? tag->value:"und");
     } else if (tag && tag->value) {
         put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag->value);
@@ -885,7 +989,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
     if (st->disposition & AV_DISPOSITION_FORCED)
         put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, 1);
 
-    if (mkv->mode == MODE_WEBM && codec->codec_id == AV_CODEC_ID_WEBVTT) {
+    if (mkv->mode == MODE_WEBM && par->codec_id == AV_CODEC_ID_WEBVTT) {
         const char *codec_id;
         if (st->disposition & AV_DISPOSITION_CAPTIONS) {
             codec_id = "D_WEBVTT/CAPTIONS";
@@ -905,13 +1009,13 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
         // look for a codec ID string specific to mkv to use,
         // if none are found, use AVI codes
         for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) {
-            if (ff_mkv_codec_tags[j].id == codec->codec_id) {
+            if (ff_mkv_codec_tags[j].id == par->codec_id) {
                 put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str);
                 native_id = 1;
                 break;
             }
         }
-        if (codec->codec_id == AV_CODEC_ID_RAWVIDEO && !codec->codec_tag) {
+        if (par->codec_id == AV_CODEC_ID_RAWVIDEO && !par->codec_tag) {
             if (mkv->allow_raw_vfw) {
                 native_id = 0;
             } else {
@@ -922,50 +1026,51 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
         }
     }
 
-    if (codec->codec_type == AVMEDIA_TYPE_AUDIO && codec->initial_padding && codec->codec_id == AV_CODEC_ID_OPUS) {
-        int64_t codecdelay = av_rescale_q(codec->initial_padding,
+    if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->initial_padding && par->codec_id == AV_CODEC_ID_OPUS) {
+        int64_t codecdelay = av_rescale_q(par->initial_padding,
                                           (AVRational){ 1, 48000 },
                                           (AVRational){ 1, 1000000000 });
         if (codecdelay < 0) {
             av_log(s, AV_LOG_ERROR, "Initial padding is invalid\n");
             return AVERROR(EINVAL);
         }
-//         mkv->tracks[i].ts_offset = av_rescale_q(codec->initial_padding,
-//                                                 (AVRational){ 1, codec->sample_rate },
+//         mkv->tracks[i].ts_offset = av_rescale_q(par->initial_padding,
+//                                                 (AVRational){ 1, par->sample_rate },
 //                                                 st->time_base);
 
         put_ebml_uint(pb, MATROSKA_ID_CODECDELAY, codecdelay);
     }
-    if (codec->codec_id == AV_CODEC_ID_OPUS) {
+    if (par->codec_id == AV_CODEC_ID_OPUS) {
         put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL);
     }
 
-    if (mkv->mode == MODE_WEBM && !(codec->codec_id == AV_CODEC_ID_VP8 ||
-                                    codec->codec_id == AV_CODEC_ID_VP9 ||
-                                    codec->codec_id == AV_CODEC_ID_OPUS ||
-                                    codec->codec_id == AV_CODEC_ID_VORBIS ||
-                                    codec->codec_id == AV_CODEC_ID_WEBVTT)) {
+    if (mkv->mode == MODE_WEBM && !(par->codec_id == AV_CODEC_ID_VP8 ||
+                                    par->codec_id == AV_CODEC_ID_VP9 ||
+                                    par->codec_id == AV_CODEC_ID_OPUS ||
+                                    par->codec_id == AV_CODEC_ID_VORBIS ||
+                                    par->codec_id == AV_CODEC_ID_WEBVTT)) {
         av_log(s, AV_LOG_ERROR,
                "Only VP8 or VP9 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM.\n");
         return AVERROR(EINVAL);
     }
 
-    switch (codec->codec_type) {
+    switch (par->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
+        mkv->have_video = 1;
         put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_VIDEO);
 
         if(   st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0
-           && av_cmp_q(av_inv_q(st->avg_frame_rate), codec->time_base) > 0)
+           && av_cmp_q(av_inv_q(st->avg_frame_rate), st->time_base) > 0)
             put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1000000000LL * st->avg_frame_rate.den / st->avg_frame_rate.num);
         else
-            put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1000000000LL * codec->time_base.num / codec->time_base.den);
+            put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1000000000LL * st->time_base.num / st->time_base.den);
 
         if (!native_id &&
-            ff_codec_get_tag(ff_codec_movvideo_tags, codec->codec_id) &&
-            ((!ff_codec_get_tag(ff_codec_bmp_tags,   codec->codec_id) && codec->codec_id != AV_CODEC_ID_RAWVIDEO) ||
-             codec->codec_id == AV_CODEC_ID_SVQ1 ||
-             codec->codec_id == AV_CODEC_ID_SVQ3 ||
-             codec->codec_id == AV_CODEC_ID_CINEPAK))
+            ff_codec_get_tag(ff_codec_movvideo_tags, par->codec_id) &&
+            ((!ff_codec_get_tag(ff_codec_bmp_tags,   par->codec_id) && par->codec_id != AV_CODEC_ID_RAWVIDEO) ||
+             par->codec_id == AV_CODEC_ID_SVQ1 ||
+             par->codec_id == AV_CODEC_ID_SVQ3 ||
+             par->codec_id == AV_CODEC_ID_CINEPAK))
             qt_id = 1;
 
         if (qt_id)
@@ -978,9 +1083,12 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
         }
 
         subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0);
-        // XXX: interlace flag?
-        put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
-        put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
+
+        put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , par->width);
+        put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, par->height);
+
+        if (mkv->mode != MODE_WEBM)
+            mkv_write_field_order(pb, par->field_order);
 
         // check both side data and metadata for stereo information,
         // write the result to the bitstream if any is found
@@ -992,30 +1100,32 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
 
         if (((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) ||
             ((tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) ||
-            (codec->pix_fmt == AV_PIX_FMT_YUVA420P)) {
+            (par->format == AV_PIX_FMT_YUVA420P)) {
             put_ebml_uint(pb, MATROSKA_ID_VIDEOALPHAMODE, 1);
         }
 
         // write DisplayWidth and DisplayHeight, they contain the size of
         // a single source view and/or the display aspect ratio
         if (st->sample_aspect_ratio.num) {
-            int64_t d_width = av_rescale(codec->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
+            int64_t d_width = av_rescale(par->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
             if (d_width > INT_MAX) {
                 av_log(s, AV_LOG_ERROR, "Overflow in display width\n");
                 return AVERROR(EINVAL);
             }
             put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width / display_width_div);
-            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);
+            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, par->height / display_height_div);
         } else if (display_width_div != 1 || display_height_div != 1) {
-            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , codec->width / display_width_div);
-            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, codec->height / display_height_div);
+            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , par->width / display_width_div);
+            put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, par->height / display_height_div);
         }
 
-        if (codec->codec_id == AV_CODEC_ID_RAWVIDEO) {
-            uint32_t color_space = av_le2ne32(codec->codec_tag);
+        if (par->codec_id == AV_CODEC_ID_RAWVIDEO) {
+            uint32_t color_space = av_le2ne32(par->codec_tag);
             put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space));
         }
-
+        if (s->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
+            mkv_write_video_color(pb, par, st);
+        }
         end_ebml_master(pb, subinfo);
         break;
 
@@ -1027,7 +1137,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
             put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM");
 
         subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 0);
-        put_ebml_uint  (pb, MATROSKA_ID_AUDIOCHANNELS    , codec->channels);
+        put_ebml_uint  (pb, MATROSKA_ID_AUDIOCHANNELS    , par->channels);
         put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate);
         if (output_sample_rate)
             put_ebml_float(pb, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate);
@@ -1038,11 +1148,11 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
 
     case AVMEDIA_TYPE_SUBTITLE:
         if (!native_id) {
-            av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", codec->codec_id);
+            av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", par->codec_id);
             return AVERROR(ENOSYS);
         }
 
-        if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT)
+        if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT)
             native_id = MATROSKA_TRACK_TYPE_SUBTITLE;
 
         put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id);
@@ -1052,8 +1162,8 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
         return AVERROR(EINVAL);
     }
 
-    if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) {
-        ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id);
+    if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT) {
+        ret = mkv_write_codecprivate(s, pb, par, native_id, qt_id);
         if (ret < 0)
             return ret;
     }
@@ -1318,7 +1428,7 @@ static int mkv_write_attachments(AVFormatContext *s)
         const char *mimetype = NULL;
         uint64_t fileuid;
 
-        if (st->codec->codec_type != AVMEDIA_TYPE_ATTACHMENT)
+        if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT)
             continue;
 
         attached_file = start_ebml_master(pb, MATROSKA_ID_ATTACHEDFILE, 0);
@@ -1332,15 +1442,15 @@ static int mkv_write_attachments(AVFormatContext *s)
         put_ebml_string(pb, MATROSKA_ID_FILENAME, t->value);
         if (t = av_dict_get(st->metadata, "mimetype", NULL, 0))
             mimetype = t->value;
-        else if (st->codec->codec_id != AV_CODEC_ID_NONE ) {
+        else if (st->codecpar->codec_id != AV_CODEC_ID_NONE ) {
             int i;
             for (i = 0; ff_mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++)
-                if (ff_mkv_mime_tags[i].id == st->codec->codec_id) {
+                if (ff_mkv_mime_tags[i].id == st->codecpar->codec_id) {
                     mimetype = ff_mkv_mime_tags[i].str;
                     break;
                 }
             for (i = 0; ff_mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++)
-                if (ff_mkv_image_mime_tags[i].id == st->codec->codec_id) {
+                if (ff_mkv_image_mime_tags[i].id == st->codecpar->codec_id) {
                     mimetype = ff_mkv_image_mime_tags[i].str;
                     break;
                 }
@@ -1357,7 +1467,7 @@ static int mkv_write_attachments(AVFormatContext *s)
             if (!sha)
                 return AVERROR(ENOMEM);
             av_sha_init(sha, 160);
-            av_sha_update(sha, st->codec->extradata, st->codec->extradata_size);
+            av_sha_update(sha, st->codecpar->extradata, st->codecpar->extradata_size);
             av_sha_final(sha, digest);
             av_free(sha);
             fileuid = AV_RL64(digest);
@@ -1368,7 +1478,7 @@ static int mkv_write_attachments(AVFormatContext *s)
                fileuid, i);
 
         put_ebml_string(pb, MATROSKA_ID_FILEMIMETYPE, mimetype);
-        put_ebml_binary(pb, MATROSKA_ID_FILEDATA, st->codec->extradata, st->codec->extradata_size);
+        put_ebml_binary(pb, MATROSKA_ID_FILEDATA, st->codecpar->extradata, st->codecpar->extradata_size);
         put_ebml_uint(pb, MATROSKA_ID_FILEUID, fileuid);
         end_ebml_master(pb, attached_file);
     }
@@ -1397,18 +1507,18 @@ static int mkv_write_header(AVFormatContext *s)
         version = 4;
 
     for (i = 0; i < s->nb_streams; i++) {
-        if (s->streams[i]->codec->codec_id == AV_CODEC_ID_ATRAC3 ||
-            s->streams[i]->codec->codec_id == AV_CODEC_ID_COOK ||
-            s->streams[i]->codec->codec_id == AV_CODEC_ID_RA_288 ||
-            s->streams[i]->codec->codec_id == AV_CODEC_ID_SIPR ||
-            s->streams[i]->codec->codec_id == AV_CODEC_ID_RV10 ||
-            s->streams[i]->codec->codec_id == AV_CODEC_ID_RV20) {
+        if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_ATRAC3 ||
+            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_COOK ||
+            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RA_288 ||
+            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_SIPR ||
+            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV10 ||
+            s->streams[i]->codecpar->codec_id == AV_CODEC_ID_RV20) {
             av_log(s, AV_LOG_ERROR,
                    "The Matroska muxer does not yet support muxing %s\n",
-                   avcodec_get_name(s->streams[i]->codec->codec_id));
+                   avcodec_get_name(s->streams[i]->codecpar->codec_id));
             return AVERROR_PATCHWELCOME;
         }
-        if (s->streams[i]->codec->codec_id == AV_CODEC_ID_OPUS ||
+        if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_OPUS ||
             av_dict_get(s->streams[i]->metadata, "stereo_mode", NULL, 0) ||
             av_dict_get(s->streams[i]->metadata, "alpha_mode", NULL, 0))
             version = 4;
@@ -1619,7 +1729,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
                             unsigned int blockid, AVPacket *pkt, int keyframe)
 {
     MatroskaMuxContext *mkv = s->priv_data;
-    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
+    AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
     uint8_t *data = NULL, *side_data = NULL;
     int offset = 0, size = pkt->size, side_data_size = 0;
     int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
@@ -1632,14 +1742,14 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
            "pts %" PRId64 ", dts %" PRId64 ", duration %" PRId64 ", keyframe %d\n",
            avio_tell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration,
            keyframe != 0);
-    if (codec->codec_id == AV_CODEC_ID_H264 && codec->extradata_size > 0 &&
-        (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1))
+    if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 &&
+        (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1))
         ff_avc_parse_nal_units_buf(pkt->data, &data, &size);
-    else if (codec->codec_id == AV_CODEC_ID_HEVC && codec->extradata_size > 6 &&
-             (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1))
+    else if (par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6 &&
+             (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1))
         /* extradata is Annex B, assume the bitstream is too and convert it */
         ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL);
-    else if (codec->codec_id == AV_CODEC_ID_WAVPACK) {
+    else if (par->codec_id == AV_CODEC_ID_WAVPACK) {
         int ret = mkv_strip_wavpack(pkt->data, &data, &size);
         if (ret < 0) {
             av_log(s, AV_LOG_ERROR, "Error stripping a WavPack packet.\n");
@@ -1648,7 +1758,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
     } else
         data = pkt->data;
 
-    if (codec->codec_id == AV_CODEC_ID_PRORES && size >= 8) {
+    if (par->codec_id == AV_CODEC_ID_PRORES && size >= 8) {
         /* Matroska specification requires to remove the first QuickTime atom
          */
         size  -= 8;
@@ -1661,7 +1771,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
 
     if (side_data && side_data_size >= 10) {
         discard_padding = av_rescale_q(AV_RL32(side_data + 4),
-                                       (AVRational){1, codec->sample_rate},
+                                       (AVRational){1, par->sample_rate},
                                        (AVRational){1, 1000000000});
     }
 
@@ -1793,7 +1903,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_
 {
     MatroskaMuxContext *mkv = s->priv_data;
     AVIOContext *pb         = s->pb;
-    AVCodecContext *codec   = s->streams[pkt->stream_index]->codec;
+    AVCodecParameters *par  = s->streams[pkt->stream_index]->codecpar;
     int keyframe            = !!(pkt->flags & AV_PKT_FLAG_KEY);
     int duration            = pkt->duration;
     int ret;
@@ -1835,14 +1945,14 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt, int add_
 
     relative_packet_pos = avio_tell(s->pb) - mkv->cluster.pos;
 
-    if (codec->codec_type != AVMEDIA_TYPE_SUBTITLE) {
+    if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) {
         mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe);
-        if (s->pb->seekable && (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe || add_cue)) {
+        if (s->pb->seekable && (par->codec_type == AVMEDIA_TYPE_VIDEO && keyframe || add_cue)) {
             ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, dash_tracknum, ts, mkv->cluster_pos, relative_packet_pos, -1);
             if (ret < 0) return ret;
         }
     } else {
-        if (codec->codec_id == AV_CODEC_ID_WEBVTT) {
+        if (par->codec_id == AV_CODEC_ID_WEBVTT) {
             duration = mkv_write_vtt_blocks(s, pb, pkt);
         } else {
             ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP,
@@ -1882,7 +1992,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
 static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     MatroskaMuxContext *mkv = s->priv_data;
-    int codec_type          = s->streams[pkt->stream_index]->codec->codec_type;
+    int codec_type          = s->streams[pkt->stream_index]->codecpar->codec_type;
     int keyframe            = !!(pkt->flags & AV_PKT_FLAG_KEY);
     int cluster_size;
     int64_t cluster_time;
@@ -1927,6 +2037,11 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
         mkv_start_new_cluster(s, pkt);
     }
 
+    if (!mkv->cluster_pos)
+        avio_write_marker(s->pb,
+                          av_rescale_q(pkt->dts, s->streams[pkt->stream_index]->time_base, AV_TIME_BASE_Q),
+                          keyframe && (mkv->have_video ? codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
+
     // check if we have an audio packet cached
     if (mkv->cur_audio_pkt.size > 0) {
         // for DASH audio, a CuePoint has to be added when there is a new cluster.
@@ -2118,9 +2233,12 @@ static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
     int ret = 1;
     AVStream *st = s->streams[pkt->stream_index];
 
-    if (st->codec->codec_id == AV_CODEC_ID_AAC)
+    if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
         if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
             ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
+        ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
+    }
 
     return ret;
 }
diff --git a/libavformat/md5enc.c b/libavformat/md5enc.c
deleted file mode 100644
index 8433be4..0000000
--- a/libavformat/md5enc.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * MD5 encoder (for codec/format testing)
- * Copyright (c) 2009 Reimar Döffinger, based on crcenc (c) 2002 Fabrice Bellard
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/avassert.h"
-#include "libavutil/avstring.h"
-#include "libavutil/hash.h"
-#include "libavutil/opt.h"
-#include "avformat.h"
-#include "internal.h"
-
-struct MD5Context {
-    const AVClass *avclass;
-    struct AVHashContext *hash;
-    char *hash_name;
-    int format_version;
-};
-
-static void md5_finish(struct AVFormatContext *s, char *buf)
-{
-    struct MD5Context *c = s->priv_data;
-    uint8_t md5[AV_HASH_MAX_SIZE];
-    int i, offset = strlen(buf);
-    int len = av_hash_get_size(c->hash);
-    av_assert0(len > 0 && len <= sizeof(md5));
-    av_hash_final(c->hash, md5);
-    for (i = 0; i < len; i++) {
-        snprintf(buf + offset, 3, "%02"PRIx8, md5[i]);
-        offset += 2;
-    }
-    buf[offset] = '\n';
-    buf[offset+1] = 0;
-
-    avio_write(s->pb, buf, strlen(buf));
-    avio_flush(s->pb);
-}
-
-#define OFFSET(x) offsetof(struct MD5Context, x)
-#define ENC AV_OPT_FLAG_ENCODING_PARAM
-static const AVOption hash_options[] = {
-    { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "md5"}, 0, 0, ENC },
-    { "format_version", "file format version", OFFSET(format_version), AV_OPT_TYPE_INT, {.i64 = 1}, 1, 1, ENC },
-    { NULL },
-};
-
-static const AVClass md5enc_class = {
-    .class_name = "hash encoder class",
-    .item_name  = av_default_item_name,
-    .option     = hash_options,
-    .version    = LIBAVUTIL_VERSION_INT,
-};
-
-#if CONFIG_MD5_MUXER
-static int write_header(struct AVFormatContext *s)
-{
-    struct MD5Context *c = s->priv_data;
-    int res = av_hash_alloc(&c->hash, c->hash_name);
-    if (res < 0)
-        return res;
-    av_hash_init(c->hash);
-    return 0;
-}
-
-static int write_packet(struct AVFormatContext *s, AVPacket *pkt)
-{
-    struct MD5Context *c = s->priv_data;
-    av_hash_update(c->hash, pkt->data, pkt->size);
-    return 0;
-}
-
-static int write_trailer(struct AVFormatContext *s)
-{
-    struct MD5Context *c = s->priv_data;
-    char buf[256];
-    av_strlcpy(buf, av_hash_get_name(c->hash), sizeof(buf) - 200);
-    av_strlcat(buf, "=", sizeof(buf) - 200);
-
-    md5_finish(s, buf);
-
-    av_hash_freep(&c->hash);
-    return 0;
-}
-
-AVOutputFormat ff_md5_muxer = {
-    .name              = "md5",
-    .long_name         = NULL_IF_CONFIG_SMALL("MD5 testing"),
-    .priv_data_size    = sizeof(struct MD5Context),
-    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
-    .video_codec       = AV_CODEC_ID_RAWVIDEO,
-    .write_header      = write_header,
-    .write_packet      = write_packet,
-    .write_trailer     = write_trailer,
-    .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
-                         AVFMT_TS_NEGATIVE,
-    .priv_class        = &md5enc_class,
-};
-#endif
-
-#if CONFIG_FRAMEMD5_MUXER
-static int framemd5_write_header(struct AVFormatContext *s)
-{
-    struct MD5Context *c = s->priv_data;
-    int res = av_hash_alloc(&c->hash, c->hash_name);
-    if (res < 0)
-        return res;
-    avio_printf(s->pb, "#format: frame checksums\n");
-    avio_printf(s->pb, "#version: %d\n", c->format_version);
-    avio_printf(s->pb, "#hash: %s\n", av_hash_get_name(c->hash));
-    ff_framehash_write_header(s);
-    avio_printf(s->pb, "#stream#, dts,        pts, duration,     size, hash\n");
-    return 0;
-}
-
-static int framemd5_write_packet(struct AVFormatContext *s, AVPacket *pkt)
-{
-    struct MD5Context *c = s->priv_data;
-    char buf[256];
-    av_hash_init(c->hash);
-    av_hash_update(c->hash, pkt->data, pkt->size);
-
-    snprintf(buf, sizeof(buf) - 64, "%d, %10"PRId64", %10"PRId64", %8"PRId64", %8d, ",
-             pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size);
-    md5_finish(s, buf);
-    return 0;
-}
-
-static int framemd5_write_trailer(struct AVFormatContext *s)
-{
-    struct MD5Context *c = s->priv_data;
-    av_hash_freep(&c->hash);
-    return 0;
-}
-
-static const AVClass framemd5_class = {
-    .class_name = "frame hash encoder class",
-    .item_name  = av_default_item_name,
-    .option     = hash_options,
-    .version    = LIBAVUTIL_VERSION_INT,
-};
-
-AVOutputFormat ff_framemd5_muxer = {
-    .name              = "framemd5",
-    .long_name         = NULL_IF_CONFIG_SMALL("Per-frame MD5 testing"),
-    .priv_data_size    = sizeof(struct MD5Context),
-    .audio_codec       = AV_CODEC_ID_PCM_S16LE,
-    .video_codec       = AV_CODEC_ID_RAWVIDEO,
-    .write_header      = framemd5_write_header,
-    .write_packet      = framemd5_write_packet,
-    .write_trailer     = framemd5_write_trailer,
-    .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
-                         AVFMT_TS_NEGATIVE,
-    .priv_class        = &framemd5_class,
-};
-#endif
diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c
index 9a092e4..0e04b90 100644
--- a/libavformat/md5proto.c
+++ b/libavformat/md5proto.c
@@ -71,7 +71,7 @@ static int md5_close(URLContext *h)
     if (*filename) {
         err = ffurl_open_whitelist(&out, filename, AVIO_FLAG_WRITE,
                                    &h->interrupt_callback, NULL,
-                                   h->protocol_whitelist);
+                                   h->protocol_whitelist, h->protocol_blacklist, h);
         if (err)
             return err;
         err = ffurl_write(out, buf, i*2+1);
@@ -87,7 +87,7 @@ static int md5_close(URLContext *h)
 }
 
 
-URLProtocol ff_md5_protocol = {
+const URLProtocol ff_md5_protocol = {
     .name                = "md5",
     .url_open            = md5_open,
     .url_write           = md5_write,
diff --git a/libavformat/mgsts.c b/libavformat/mgsts.c
index 8cbc952..0720de8 100644
--- a/libavformat/mgsts.c
+++ b/libavformat/mgsts.c
@@ -55,13 +55,13 @@ static int read_header(AVFormatContext *s)
     st->nb_frames  =
     st->duration   = avio_rb32(pb);
     fps = av_d2q(av_int2float(avio_rb32(pb)), INT_MAX);
-    st->codec->width  = avio_rb32(pb);
-    st->codec->height = avio_rb32(pb);
+    st->codecpar->width  = avio_rb32(pb);
+    st->codecpar->height = avio_rb32(pb);
     avio_skip(pb, 12);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_tag  = avio_rb32(pb);
-    st->codec->codec_id   = ff_codec_get_id(ff_codec_bmp_tags,
-                                            st->codec->codec_tag);
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_tag  = avio_rb32(pb);
+    st->codecpar->codec_id   = ff_codec_get_id(ff_codec_bmp_tags,
+                                               st->codecpar->codec_tag);
     avpriv_set_pts_info(st, 64, fps.den, fps.num);
     avio_skip(pb, 20);
 
diff --git a/libavformat/microdvddec.c b/libavformat/microdvddec.c
index 727ff94..c2f1ac4 100644
--- a/libavformat/microdvddec.c
+++ b/libavformat/microdvddec.c
@@ -114,11 +114,11 @@ static int microdvd_read_header(AVFormatContext *s)
                 has_real_fps = 1;
                 continue;
             }
-            if (!st->codec->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) {
-                st->codec->extradata = av_strdup(line + 11);
-                if (!st->codec->extradata)
+            if (!st->codecpar->extradata && sscanf(line, "{DEFAULT}{}%c", &c) == 1) {
+                st->codecpar->extradata = av_strdup(line + 11);
+                if (!st->codecpar->extradata)
                     return AVERROR(ENOMEM);
-                st->codec->extradata_size = strlen(st->codec->extradata) + 1;
+                st->codecpar->extradata_size = strlen(st->codecpar->extradata) + 1;
                 continue;
             }
         }
@@ -150,8 +150,8 @@ static int microdvd_read_header(AVFormatContext *s)
         pts_info = microdvd->frame_rate;
     }
     avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_MICRODVD;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_MICRODVD;
     return 0;
 }
 
diff --git a/libavformat/microdvdenc.c b/libavformat/microdvdenc.c
index 4d84384..04f475b 100644
--- a/libavformat/microdvdenc.c
+++ b/libavformat/microdvdenc.c
@@ -25,21 +25,21 @@
 
 static int microdvd_write_header(struct AVFormatContext *s)
 {
-    AVCodecContext *avctx = s->streams[0]->codec;
-    AVRational tb = avctx->time_base;
+    AVCodecParameters *par = s->streams[0]->codecpar;
+    AVRational framerate = s->streams[0]->avg_frame_rate;
 
-    if (s->nb_streams != 1 || avctx->codec_id != AV_CODEC_ID_MICRODVD) {
+    if (s->nb_streams != 1 || par->codec_id != AV_CODEC_ID_MICRODVD) {
         av_log(s, AV_LOG_ERROR, "Exactly one MicroDVD stream is needed.\n");
         return -1;
     }
 
-    if (avctx->extradata && avctx->extradata_size > 0) {
+    if (par->extradata && par->extradata_size > 0) {
         avio_write(s->pb, "{DEFAULT}{}", 11);
-        avio_write(s->pb, avctx->extradata, avctx->extradata_size);
+        avio_write(s->pb, par->extradata, par->extradata_size);
         avio_flush(s->pb);
     }
 
-    avpriv_set_pts_info(s->streams[0], 64, tb.num, tb.den);
+    avpriv_set_pts_info(s->streams[0], 64, framerate.num, framerate.den);
     return 0;
 }
 
diff --git a/libavformat/mlvdec.c b/libavformat/mlvdec.c
index 288b2a1..665b28d 100644
--- a/libavformat/mlvdec.c
+++ b/libavformat/mlvdec.c
@@ -130,32 +130,32 @@ static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int f
             break;
         size -= 16;
         if (vst && type == MKTAG('R','A','W','I') && size >= 164) {
-            vst->codec->width  = avio_rl16(pb);
-            vst->codec->height = avio_rl16(pb);
-            ret = av_image_check_size(vst->codec->width, vst->codec->height, 0, avctx);
+            vst->codecpar->width  = avio_rl16(pb);
+            vst->codecpar->height = avio_rl16(pb);
+            ret = av_image_check_size(vst->codecpar->width, vst->codecpar->height, 0, avctx);
             if (ret < 0)
                 return ret;
             if (avio_rl32(pb) != 1)
                 avpriv_request_sample(avctx, "raw api version");
             avio_skip(pb, 20); // pointer, width, height, pitch, frame_size
-            vst->codec->bits_per_coded_sample = avio_rl32(pb);
-            if (vst->codec->bits_per_coded_sample < 0 ||
-                vst->codec->bits_per_coded_sample > (INT_MAX - 7) / (vst->codec->width * vst->codec->height)) {
+            vst->codecpar->bits_per_coded_sample = avio_rl32(pb);
+            if (vst->codecpar->bits_per_coded_sample < 0 ||
+                vst->codecpar->bits_per_coded_sample > (INT_MAX - 7) / (vst->codecpar->width * vst->codecpar->height)) {
                 av_log(avctx, AV_LOG_ERROR,
                        "invalid bits_per_coded_sample %d (size: %dx%d)\n",
-                       vst->codec->bits_per_coded_sample,
-                       vst->codec->width, vst->codec->height);
+                       vst->codecpar->bits_per_coded_sample,
+                       vst->codecpar->width, vst->codecpar->height);
                 return AVERROR_INVALIDDATA;
             }
             avio_skip(pb, 8 + 16 + 24); // black_level, white_level, xywh, active_area, exposure_bias
             if (avio_rl32(pb) != 0x2010100) /* RGGB */
                 avpriv_request_sample(avctx, "cfa_pattern");
             avio_skip(pb, 80); // calibration_illuminant1, color_matrix1, dynamic_range
-            vst->codec->pix_fmt  = AV_PIX_FMT_BAYER_RGGB16LE;
-            vst->codec->codec_tag = MKTAG('B', 'I', 'T', 16);
+            vst->codecpar->format    = AV_PIX_FMT_BAYER_RGGB16LE;
+            vst->codecpar->codec_tag = MKTAG('B', 'I', 'T', 16);
             size -= 164;
         } else if (ast && type == MKTAG('W', 'A', 'V', 'I') && size >= 16) {
-            ret = ff_get_wav_header(avctx, pb, ast->codec, 16, 0);
+            ret = ff_get_wav_header(avctx, pb, ast->codecpar, 16, 0);
             if (ret < 0)
                 return ret;
             size -= 16;
@@ -286,23 +286,23 @@ static int read_header(AVFormatContext *avctx)
         vst->nb_frames = nb_video_frames;
         if ((mlv->class[0] & (MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA)))
             avpriv_request_sample(avctx, "compression");
-        vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+        vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
         switch (mlv->class[0] & ~(MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA)) {
         case MLV_VIDEO_CLASS_RAW:
-            vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+            vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
             break;
         case MLV_VIDEO_CLASS_YUV:
-            vst->codec->pix_fmt  = AV_PIX_FMT_YUV420P;
-            vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
-            vst->codec->codec_tag = 0;
+            vst->codecpar->format   = AV_PIX_FMT_YUV420P;
+            vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
+            vst->codecpar->codec_tag = 0;
             break;
         case MLV_VIDEO_CLASS_JPEG:
-            vst->codec->codec_id = AV_CODEC_ID_MJPEG;
-            vst->codec->codec_tag = 0;
+            vst->codecpar->codec_id = AV_CODEC_ID_MJPEG;
+            vst->codecpar->codec_tag = 0;
             break;
         case MLV_VIDEO_CLASS_H264:
-            vst->codec->codec_id = AV_CODEC_ID_H264;
-            vst->codec->codec_tag = 0;
+            vst->codecpar->codec_id = AV_CODEC_ID_H264;
+            vst->codecpar->codec_tag = 0;
             break;
         default:
             avpriv_request_sample(avctx, "unknown video class");
@@ -320,8 +320,8 @@ static int read_header(AVFormatContext *avctx)
         if ((mlv->class[1] & ~MLV_CLASS_FLAG_LZMA) != MLV_AUDIO_CLASS_WAV)
             avpriv_request_sample(avctx, "unknown audio class");
 
-        ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        avpriv_set_pts_info(ast, 33, 1, ast->codec->sample_rate);
+        ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate);
     }
 
     if (vst) {
@@ -413,15 +413,15 @@ static int read_packet(AVFormatContext *avctx, AVPacket *pkt)
     if (size < 16)
         return AVERROR_INVALIDDATA;
     avio_skip(pb, 12); //timestamp, frameNumber
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
         avio_skip(pb, 8); // cropPosX, cropPosY, panPosX, panPosY
     space = avio_rl32(pb);
     avio_skip(pb, space);
 
     if ((mlv->class[st->id] & (MLV_CLASS_FLAG_DELTA|MLV_CLASS_FLAG_LZMA))) {
         ret = AVERROR_PATCHWELCOME;
-    } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-        ret = av_get_packet(pb, pkt, (st->codec->width * st->codec->height * st->codec->bits_per_coded_sample + 7) >> 3);
+    } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+        ret = av_get_packet(pb, pkt, (st->codecpar->width * st->codecpar->height * st->codecpar->bits_per_coded_sample + 7) >> 3);
     } else { // AVMEDIA_TYPE_AUDIO
         if (space > UINT_MAX - 24 || size < (24 + space))
             return AVERROR_INVALIDDATA;
diff --git a/libavformat/mm.c b/libavformat/mm.c
index 81ae1a5..8a1382e 100644
--- a/libavformat/mm.c
+++ b/libavformat/mm.c
@@ -109,11 +109,11 @@ static int read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_MMVIDEO;
-    st->codec->codec_tag = 0;  /* no fourcc */
-    st->codec->width = width;
-    st->codec->height = height;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_MMVIDEO;
+    st->codecpar->codec_tag = 0;  /* no fourcc */
+    st->codecpar->width = width;
+    st->codecpar->height = height;
     avpriv_set_pts_info(st, 64, 1, frame_rate);
 
     /* audio stream */
@@ -121,12 +121,12 @@ static int read_header(AVFormatContext *s)
         st = avformat_new_stream(s, NULL);
         if (!st)
             return AVERROR(ENOMEM);
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_tag = 0; /* no fourcc */
-        st->codec->codec_id = AV_CODEC_ID_PCM_U8;
-        st->codec->channels = 1;
-        st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-        st->codec->sample_rate = 8000;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_tag = 0; /* no fourcc */
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
+        st->codecpar->channels = 1;
+        st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+        st->codecpar->sample_rate = 8000;
         avpriv_set_pts_info(st, 64, 1, 8000); /* 8000 hz */
     }
 
diff --git a/libavformat/mmf.c b/libavformat/mmf.c
index c2acec9..b8a9cad 100644
--- a/libavformat/mmf.c
+++ b/libavformat/mmf.c
@@ -73,14 +73,14 @@ static int mmf_write_header(AVFormatContext *s)
                           "VN:Lavf," :
                           "VN:"LIBAVFORMAT_IDENT",";
 
-    rate = mmf_rate_code(s->streams[0]->codec->sample_rate);
+    rate = mmf_rate_code(s->streams[0]->codecpar->sample_rate);
     if (rate < 0) {
         av_log(s, AV_LOG_ERROR, "Unsupported sample rate %d, supported are 4000, 8000, 11025, 22050 and 44100\n",
-               s->streams[0]->codec->sample_rate);
+               s->streams[0]->codecpar->sample_rate);
         return AVERROR(EINVAL);
     }
 
-    mmf->stereo = s->streams[0]->codec->channels > 1;
+    mmf->stereo = s->streams[0]->codecpar->channels > 1;
     if (mmf->stereo &&
         s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
         av_log(s, AV_LOG_ERROR, "Yamaha SMAF stereo is experimental, "
@@ -121,7 +121,7 @@ static int mmf_write_header(AVFormatContext *s)
 
     mmf->awapos = ff_start_tag(pb, "Awa\x01");
 
-    avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
+    avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codecpar->sample_rate);
 
     avio_flush(pb);
 
@@ -162,7 +162,7 @@ static int mmf_write_trailer(AVFormatContext *s)
         /* "play wav" */
         avio_w8(pb, 0); /* start time */
         avio_w8(pb, (mmf->stereo << 6) | 1); /* (channel << 6) | wavenum */
-        gatetime = size * 500 / s->streams[0]->codec->sample_rate;
+        gatetime = size * 500 / s->streams[0]->codecpar->sample_rate;
         put_varlength(pb, gatetime); /* duration */
 
         /* "nop" */
@@ -262,16 +262,16 @@ static int mmf_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id              = AV_CODEC_ID_ADPCM_YAMAHA;
-    st->codec->sample_rate           = rate;
-    st->codec->channels              = (params >> 7) + 1;
-    st->codec->channel_layout        = params >> 7 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
-    st->codec->bits_per_coded_sample = 4;
-    st->codec->bit_rate              = st->codec->sample_rate *
-                                       st->codec->bits_per_coded_sample;
+    st->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id              = AV_CODEC_ID_ADPCM_YAMAHA;
+    st->codecpar->sample_rate           = rate;
+    st->codecpar->channels              = (params >> 7) + 1;
+    st->codecpar->channel_layout        = params >> 7 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
+    st->codecpar->bits_per_coded_sample = 4;
+    st->codecpar->bit_rate              = st->codecpar->sample_rate *
+                                          st->codecpar->bits_per_coded_sample;
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
diff --git a/libavformat/mms.c b/libavformat/mms.c
index 807aade..17fa76a 100644
--- a/libavformat/mms.c
+++ b/libavformat/mms.c
@@ -97,7 +97,7 @@ int ff_mms_asf_header_parser(MMSContext *mms)
             flags     = AV_RL16(p + sizeof(ff_asf_guid)*3 + 24);
             stream_id = flags & 0x7F;
             //The second condition is for checking CS_PKT_STREAM_ID_REQUEST packet size,
-            //we can calcuate the packet size by stream_num.
+            //we can calculate the packet size by stream_num.
             //Please see function send_stream_selection_request().
             if (mms->stream_num < MMS_MAX_STREAMS &&
                     46 + mms->stream_num * 6 < sizeof(mms->out_buffer)) {
diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c
index 16f07fe..d18e2d8 100644
--- a/libavformat/mmsh.c
+++ b/libavformat/mmsh.c
@@ -41,7 +41,7 @@
 // see Ref 2.2.1.8
 #define USERAGENT  "User-Agent: NSPlayer/4.1.0.3856\r\n"
 // see Ref 2.2.1.4.33
-// the guid value can be changed to any valid value.
+// the GUID value can be changed to any valid value.
 #define CLIENTGUID "Pragma: xClientGUID={c77e7400-738a-11d2-9add-0020af0a3278}\r\n"
 
 // see Ref 2.2.3 for packet type define:
@@ -401,7 +401,7 @@ static int64_t mmsh_seek(URLContext *h, int64_t pos, int whence)
     return AVERROR(ENOSYS);
 }
 
-URLProtocol ff_mmsh_protocol = {
+const URLProtocol ff_mmsh_protocol = {
     .name           = "mmsh",
     .url_open       = mmsh_open,
     .url_read       = mmsh_read,
diff --git a/libavformat/mmst.c b/libavformat/mmst.c
index 21cf2a6..a97c2e0 100644
--- a/libavformat/mmst.c
+++ b/libavformat/mmst.c
@@ -427,7 +427,7 @@ static int send_startup_packet(MMSTContext *mmst)
     int ret;
     MMSContext *mms = &mmst->mms;
     // SubscriberName is defined in MS specification linked below.
-    // The guid value can be any valid value.
+    // The GUID value can be any valid value.
     // http://download.microsoft.com/
     // download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-WMSP%5D.pdf
     snprintf(data_string, sizeof(data_string),
@@ -524,13 +524,13 @@ static int mms_open(URLContext *h, const char *uri, int flags)
             sizeof(mmst->path), uri);
 
     if(port<0)
-        port = 1755; // defaut mms protocol port
+        port = 1755; // default MMS protocol port
 
     // establish tcp connection.
     ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL);
     err = ffurl_open_whitelist(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE,
                                &h->interrupt_callback, NULL,
-                               h->protocol_whitelist);
+                               h->protocol_whitelist, h->protocol_blacklist, h);
     if (err)
         goto fail;
 
@@ -629,7 +629,7 @@ static int mms_read(URLContext *h, uint8_t *buf, int size)
     return result;
 }
 
-URLProtocol ff_mmst_protocol = {
+const URLProtocol ff_mmst_protocol = {
     .name           = "mmst",
     .url_open       = mms_open,
     .url_read       = mms_read,
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 0408ad1..33ee799 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -209,12 +209,13 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
     st->attached_pic.stream_index = st->index;
     st->attached_pic.flags       |= AV_PKT_FLAG_KEY;
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = id;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = id;
 
     return 0;
 }
 
+// 3GPP TS 26.244
 static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
 {
     char language[4] = { 0 };
@@ -242,7 +243,8 @@ static int mov_metadata_loci(MOVContext *c, AVIOContext *pb, unsigned len)
     len -= 1;
 
     if (len < 12) {
-        av_log(c->fc, AV_LOG_ERROR, "no space for coordinates left (%d)\n", len);
+        av_log(c->fc, AV_LOG_ERROR,
+               "loci too short (%u bytes left, need at least %d)\n", len, 12);
         return AVERROR_INVALIDDATA;
     }
     longitude = ((int32_t) avio_rb32(pb)) / (float) (1 << 16);
@@ -413,9 +415,9 @@ retry:
     if (atom.size < 0 || str_size >= INT_MAX/2)
         return AVERROR_INVALIDDATA;
 
-    // Allocates enough space if data_type is a float32 number, otherwise
+    // Allocates enough space if data_type is a int32 or float32 number, otherwise
     // worst-case requirement for output string in case of utf8 coded input
-    num = (data_type == 23);
+    num = (data_type >= 21 && data_type <= 23);
     str_size_alloc = (num ? 512 : (raw ? str_size : str_size * 2)) + 1;
     str = av_mallocz(str_size_alloc);
     if (!str)
@@ -426,6 +428,38 @@ retry:
     else {
         if (!raw && (data_type == 3 || (data_type == 0 && (langcode < 0x400 || langcode == 0x7fff)))) { // MAC Encoded
             mov_read_mac_string(c, pb, str_size, str, str_size_alloc);
+        } else if (data_type == 21) { // BE signed integer, variable size
+            int val = 0;
+            if (str_size == 1)
+                val = (int8_t)avio_r8(pb);
+            else if (str_size == 2)
+                val = (int16_t)avio_rb16(pb);
+            else if (str_size == 3)
+                val = ((int32_t)(avio_rb24(pb)<<8))>>8;
+            else if (str_size == 4)
+                val = (int32_t)avio_rb32(pb);
+            if (snprintf(str, str_size_alloc, "%d", val) >= str_size_alloc) {
+                av_log(c->fc, AV_LOG_ERROR,
+                       "Failed to store the number (%d) in string.\n", val);
+                av_free(str);
+                return AVERROR_INVALIDDATA;
+            }
+        } else if (data_type == 22) { // BE unsigned integer, variable size
+            unsigned int val = 0;
+            if (str_size == 1)
+                val = avio_r8(pb);
+            else if (str_size == 2)
+                val = avio_rb16(pb);
+            else if (str_size == 3)
+                val = avio_rb24(pb);
+            else if (str_size == 4)
+                val = avio_rb32(pb);
+            if (snprintf(str, str_size_alloc, "%u", val) >= str_size_alloc) {
+                av_log(c->fc, AV_LOG_ERROR,
+                       "Failed to store the number (%u) in string.\n", val);
+                av_free(str);
+                return AVERROR_INVALIDDATA;
+            }
         } else if (data_type == 23 && str_size >= 4) {  // BE float32
             float val = av_int2float(avio_rb32(pb));
             if (snprintf(str, str_size_alloc, "%f", val) >= str_size_alloc) {
@@ -515,9 +549,11 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 
     avio_rb32(pb); // version + flags
     entries = avio_rb32(pb);
-    if (entries >  (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
+    if (!entries ||
+        entries >  (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||
         entries >= UINT_MAX / sizeof(*sc->drefs))
         return AVERROR_INVALIDDATA;
+    sc->drefs_count = 0;
     av_free(sc->drefs);
     sc->drefs_count = 0;
     sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
@@ -597,6 +633,13 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)
                         memmove(dref->path, dref->path+volume_len, len);
                         dref->path[len] = 0;
                     }
+                    // trim string of any ending zeros
+                    for (j = len - 1; j >= 0; j--) {
+                        if (dref->path[j] == 0)
+                            len--;
+                        else
+                            break;
+                    }
                     for (j = 0; j < len; j++)
                         if (dref->path[j] == ':' || dref->path[j] == 0)
                             dref->path[j] = '/';
@@ -660,13 +703,13 @@ static int mov_read_hdlr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     st = c->fc->streams[c->fc->nb_streams-1];
 
     if     (type == MKTAG('v','i','d','e'))
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     else if (type == MKTAG('s','o','u','n'))
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
     else if (type == MKTAG('m','1','a',' '))
-        st->codec->codec_id = AV_CODEC_ID_MP2;
+        st->codecpar->codec_id = AV_CODEC_ID_MP2;
     else if ((type == MKTAG('s','u','b','p')) || (type == MKTAG('c','l','c','p')))
-        st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
+        st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
 
     avio_rb32(pb); /* component  manufacture */
     avio_rb32(pb); /* component flags */
@@ -740,15 +783,19 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     bsmod = (ac3info >> 14) & 0x7;
     acmod = (ac3info >> 11) & 0x7;
     lfeon = (ac3info >> 10) & 0x1;
-    st->codec->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon;
-    st->codec->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
+    st->codecpar->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon;
+    st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
     if (lfeon)
-        st->codec->channel_layout |= AV_CH_LOW_FREQUENCY;
+        st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
     *ast = bsmod;
-    if (st->codec->channels > 1 && bsmod == 0x7)
+    if (st->codecpar->channels > 1 && bsmod == 0x7)
         *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
 
+#if FF_API_LAVF_AVCTX
+    FF_DISABLE_DEPRECATION_WARNINGS
     st->codec->audio_service_type = *ast;
+    FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     return 0;
 }
@@ -776,15 +823,19 @@ static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     bsmod = (eac3info >> 12) & 0x1f;
     acmod = (eac3info >>  9) & 0x7;
     lfeon = (eac3info >>  8) & 0x1;
-    st->codec->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
+    st->codecpar->channel_layout = avpriv_ac3_channel_layout_tab[acmod];
     if (lfeon)
-        st->codec->channel_layout |= AV_CH_LOW_FREQUENCY;
-    st->codec->channels = av_get_channel_layout_nb_channels(st->codec->channel_layout);
+        st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY;
+    st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
     *ast = bsmod;
-    if (st->codec->channels > 1 && bsmod == 0x7)
+    if (st->codecpar->channels > 1 && bsmod == 0x7)
         *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE;
 
+#if FF_API_LAVF_AVCTX
+    FF_DISABLE_DEPRECATION_WARNINGS
     st->codec->audio_service_type = *ast;
+    FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     return 0;
 }
@@ -814,15 +865,15 @@ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     }
     st = c->fc->streams[c->fc->nb_streams-1];
 
-    st->codec->sample_rate = get_bits_long(&gb, 32);
+    st->codecpar->sample_rate = get_bits_long(&gb, 32);
     skip_bits_long(&gb, 32); /* max bitrate */
-    st->codec->bit_rate = get_bits_long(&gb, 32);
-    st->codec->bits_per_coded_sample = get_bits(&gb, 8);
+    st->codecpar->bit_rate = get_bits_long(&gb, 32);
+    st->codecpar->bits_per_coded_sample = get_bits(&gb, 8);
     frame_duration_code = get_bits(&gb, 2);
     skip_bits(&gb, 30); /* various fields */
     channel_layout_code = get_bits(&gb, 16);
 
-    st->codec->frame_size =
+    st->codecpar->frame_size =
             (frame_duration_code == 0) ? 512 :
             (frame_duration_code == 1) ? 1024 :
             (frame_duration_code == 2) ? 2048 :
@@ -831,7 +882,7 @@ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     if (channel_layout_code > 0xff) {
         av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout");
     }
-    st->codec->channel_layout =
+    st->codecpar->channel_layout =
             ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) |
             ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) |
             ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) |
@@ -839,7 +890,7 @@ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
             ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) |
             ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0);
 
-    st->codec->channels = av_get_channel_layout_nb_channels(st->codec->channel_layout);
+    st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout);
 
     return 0;
 }
@@ -872,7 +923,7 @@ static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         return 0;
     st = c->fc->streams[c->fc->nb_streams-1];
 
-    if ((ret = ff_get_wav_header(c->fc, pb, st->codec, atom.size, 0)) < 0)
+    if ((ret = ff_get_wav_header(c->fc, pb, st->codecpar, atom.size, 0)) < 0)
         av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
 
     return ret;
@@ -1217,18 +1268,18 @@ static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     little_endian = avio_rb16(pb) & 0xFF;
     av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian);
     if (little_endian == 1) {
-        switch (st->codec->codec_id) {
+        switch (st->codecpar->codec_id) {
         case AV_CODEC_ID_PCM_S24BE:
-            st->codec->codec_id = AV_CODEC_ID_PCM_S24LE;
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
             break;
         case AV_CODEC_ID_PCM_S32BE:
-            st->codec->codec_id = AV_CODEC_ID_PCM_S32LE;
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
             break;
         case AV_CODEC_ID_PCM_F32BE:
-            st->codec->codec_id = AV_CODEC_ID_PCM_F32LE;
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
             break;
         case AV_CODEC_ID_PCM_F64BE:
-            st->codec->codec_id = AV_CODEC_ID_PCM_F64LE;
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE;
             break;
         default:
             break;
@@ -1270,9 +1321,9 @@ static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         uint8_t color_range = avio_r8(pb) >> 7;
         av_log(c->fc, AV_LOG_TRACE, " full %"PRIu8"", color_range);
         if (color_range)
-            st->codec->color_range = AVCOL_RANGE_JPEG;
+            st->codecpar->color_range = AVCOL_RANGE_JPEG;
         else
-            st->codec->color_range = AVCOL_RANGE_MPEG;
+            st->codecpar->color_range = AVCOL_RANGE_MPEG;
         /* 14496-12 references JPEG XR specs (rather than the more complete
          * 23001-8) so some adjusting is required */
         if (color_primaries >= AVCOL_PRI_FILM)
@@ -1283,26 +1334,26 @@ static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
             color_trc = AVCOL_TRC_UNSPECIFIED;
         if (color_matrix >= AVCOL_SPC_BT2020_NCL)
             color_matrix = AVCOL_SPC_UNSPECIFIED;
-        st->codec->color_primaries = color_primaries;
-        st->codec->color_trc = color_trc;
-        st->codec->colorspace = color_matrix;
+        st->codecpar->color_primaries = color_primaries;
+        st->codecpar->color_trc       = color_trc;
+        st->codecpar->color_space     = color_matrix;
     } else if (!strncmp(color_parameter_type, "nclc", 4)) {
         /* color primaries, Table 4-4 */
         switch (color_primaries) {
-        case 1: st->codec->color_primaries = AVCOL_PRI_BT709; break;
-        case 5: st->codec->color_primaries = AVCOL_PRI_SMPTE170M; break;
-        case 6: st->codec->color_primaries = AVCOL_PRI_SMPTE240M; break;
+        case 1: st->codecpar->color_primaries = AVCOL_PRI_BT709; break;
+        case 5: st->codecpar->color_primaries = AVCOL_PRI_SMPTE170M; break;
+        case 6: st->codecpar->color_primaries = AVCOL_PRI_SMPTE240M; break;
         }
         /* color transfer, Table 4-5 */
         switch (color_trc) {
-        case 1: st->codec->color_trc = AVCOL_TRC_BT709; break;
-        case 7: st->codec->color_trc = AVCOL_TRC_SMPTE240M; break;
+        case 1: st->codecpar->color_trc = AVCOL_TRC_BT709; break;
+        case 7: st->codecpar->color_trc = AVCOL_TRC_SMPTE240M; break;
         }
         /* color matrix, Table 4-6 */
         switch (color_matrix) {
-        case 1: st->codec->colorspace = AVCOL_SPC_BT709; break;
-        case 6: st->codec->colorspace = AVCOL_SPC_BT470BG; break;
-        case 7: st->codec->colorspace = AVCOL_SPC_SMPTE240M; break;
+        case 1: st->codecpar->color_space = AVCOL_SPC_BT709; break;
+        case 6: st->codecpar->color_space = AVCOL_SPC_BT470BG; break;
+        case 7: st->codecpar->color_space = AVCOL_SPC_SMPTE240M; break;
         }
     }
     av_log(c->fc, AV_LOG_TRACE, "\n");
@@ -1339,28 +1390,28 @@ static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) {
         av_log(NULL, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order);
     }
-    st->codec->field_order = decoded_field_order;
+    st->codecpar->field_order = decoded_field_order;
 
     return 0;
 }
 
-static int mov_realloc_extradata(AVCodecContext *codec, MOVAtom atom)
+static int mov_realloc_extradata(AVCodecParameters *par, MOVAtom atom)
 {
     int err = 0;
-    uint64_t size = (uint64_t)codec->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
+    uint64_t size = (uint64_t)par->extradata_size + atom.size + 8 + AV_INPUT_BUFFER_PADDING_SIZE;
     if (size > INT_MAX || (uint64_t)atom.size > INT_MAX)
         return AVERROR_INVALIDDATA;
-    if ((err = av_reallocp(&codec->extradata, size)) < 0) {
-        codec->extradata_size = 0;
+    if ((err = av_reallocp(&par->extradata, size)) < 0) {
+        par->extradata_size = 0;
         return err;
     }
-    codec->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
+    par->extradata_size = size - AV_INPUT_BUFFER_PADDING_SIZE;
     return 0;
 }
 
 /* Read a whole atom into the extradata return the size of the atom read, possibly truncated if != atom.size */
 static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
-                                        AVCodecContext *codec, uint8_t *buf)
+                                        AVCodecParameters *par, uint8_t *buf)
 {
     int64_t result = atom.size;
     int err;
@@ -1369,18 +1420,18 @@ static int64_t mov_read_atom_into_extradata(MOVContext *c, AVIOContext *pb, MOVA
     AV_WL32(buf + 4, atom.type);
     err = ffio_read_size(pb, buf + 8, atom.size);
     if (err < 0) {
-        codec->extradata_size -= atom.size;
+        par->extradata_size -= atom.size;
         return err;
     } else if (err < atom.size) {
         av_log(c->fc, AV_LOG_WARNING, "truncated extradata\n");
-        codec->extradata_size -= atom.size - err;
+        par->extradata_size -= atom.size - err;
         result = err;
     }
     memset(buf + 8 + err, 0, AV_INPUT_BUFFER_PADDING_SIZE);
     return result;
 }
 
-/* FIXME modify qdm2/svq3/h264 decoders to take full atom as extradata */
+/* FIXME modify QDM2/SVQ3/H.264 decoders to take full atom as extradata */
 static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
                               enum AVCodecID codec_id)
 {
@@ -1392,15 +1443,15 @@ static int mov_read_extradata(MOVContext *c, AVIOContext *pb, MOVAtom atom,
         return 0;
     st = c->fc->streams[c->fc->nb_streams-1];
 
-    if (st->codec->codec_id != codec_id)
+    if (st->codecpar->codec_id != codec_id)
         return 0; /* unexpected codec_id - don't mess with extradata */
 
-    original_size = st->codec->extradata_size;
-    err = mov_realloc_extradata(st->codec, atom);
+    original_size = st->codecpar->extradata_size;
+    err = mov_realloc_extradata(st->codecpar, atom);
     if (err)
         return err;
 
-    err =  mov_read_atom_into_extradata(c, pb, atom, st->codec,  st->codec->extradata + original_size);
+    err =  mov_read_atom_into_extradata(c, pb, atom, st->codecpar,  st->codecpar->extradata + original_size);
     if (err < 0)
         return err;
     return 0; // Note: this is the original behavior to ignore truncation.
@@ -1440,10 +1491,10 @@ static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216);
 
     if (!ret && c->fc->nb_streams >= 1) {
-        AVCodecContext *avctx = c->fc->streams[c->fc->nb_streams-1]->codec;
-        if (avctx->extradata_size >= 40) {
-            avctx->height = AV_RB16(&avctx->extradata[36]);
-            avctx->width  = AV_RB16(&avctx->extradata[38]);
+        AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
+        if (par->extradata_size >= 40) {
+            par->height = AV_RB16(&par->extradata[36]);
+            par->width  = AV_RB16(&par->extradata[38]);
         }
     }
     return ret;
@@ -1452,15 +1503,36 @@ static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
     if (c->fc->nb_streams >= 1) {
-        AVCodecContext *codec = c->fc->streams[c->fc->nb_streams-1]->codec;
-        if (codec->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
-            codec->codec_id == AV_CODEC_ID_H264 &&
+        AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
+        if (par->codec_tag == MKTAG('A', 'V', 'i', 'n') &&
+            par->codec_id == AV_CODEC_ID_H264 &&
             atom.size > 11) {
+            int cid;
             avio_skip(pb, 10);
+            cid = avio_rb16(pb);
             /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */
-            if (avio_rb16(pb) == 0xd4d)
-                codec->width = 1440;
+            if (cid == 0xd4d || cid == 0xd4e)
+                par->width = 1440;
             return 0;
+        } else if (par->codec_tag == MKTAG('A', 'V', 'd', '1') &&
+                   atom.size >= 24) {
+            int num, den;
+            avio_skip(pb, 12);
+            num = avio_rb32(pb);
+            den = avio_rb32(pb);
+            if (num <= 0 || den <= 0)
+                return 0;
+            switch (avio_rb32(pb)) {
+            case 2:
+                if (den >= INT_MAX / 2)
+                    return 0;
+                den *= 2;
+            case 1:
+                c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.num = num;
+                c->fc->streams[c->fc->nb_streams-1]->display_aspect_ratio.den = den;
+            default:
+                return 0;
+            }
         }
     }
 
@@ -1473,28 +1545,28 @@ static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     int length = 0;
     uint64_t original_size;
     if (c->fc->nb_streams >= 1) {
-        AVCodecContext *codec = c->fc->streams[c->fc->nb_streams-1]->codec;
-        if (codec->codec_id == AV_CODEC_ID_H264)
+        AVCodecParameters *par = c->fc->streams[c->fc->nb_streams-1]->codecpar;
+        if (par->codec_id == AV_CODEC_ID_H264)
             return 0;
         if (atom.size == 16) {
-            original_size = codec->extradata_size;
-            ret = mov_realloc_extradata(codec, atom);
+            original_size = par->extradata_size;
+            ret = mov_realloc_extradata(par, atom);
             if (!ret) {
-                length =  mov_read_atom_into_extradata(c, pb, atom, codec, codec->extradata + original_size);
+                length =  mov_read_atom_into_extradata(c, pb, atom, par, par->extradata + original_size);
                 if (length == atom.size) {
-                    const uint8_t range_value = codec->extradata[original_size + 19];
+                    const uint8_t range_value = par->extradata[original_size + 19];
                     switch (range_value) {
                     case 1:
-                        codec->color_range = AVCOL_RANGE_MPEG;
+                        par->color_range = AVCOL_RANGE_MPEG;
                         break;
                     case 2:
-                        codec->color_range = AVCOL_RANGE_JPEG;
+                        par->color_range = AVCOL_RANGE_JPEG;
                         break;
                     default:
                         av_log(c, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value);
                         break;
                     }
-                    ff_dlog(c, "color_range: %d\n", codec->color_range);
+                    ff_dlog(c, "color_range: %d\n", par->color_range);
                 } else {
                   /* For some reason the whole atom was not added to the extradata */
                   av_log(c, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n");
@@ -1527,16 +1599,16 @@ static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     if ((uint64_t)atom.size > (1<<30))
         return AVERROR_INVALIDDATA;
 
-    if (st->codec->codec_id == AV_CODEC_ID_QDM2 ||
-        st->codec->codec_id == AV_CODEC_ID_QDMC ||
-        st->codec->codec_id == AV_CODEC_ID_SPEEX) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_QDM2 ||
+        st->codecpar->codec_id == AV_CODEC_ID_QDMC ||
+        st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
         // pass all frma atom to codec, needed at least for QDMC and QDM2
-        av_freep(&st->codec->extradata);
-        ret = ff_get_extradata(st->codec, pb, atom.size);
+        av_freep(&st->codecpar->extradata);
+        ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
         if (ret < 0)
             return ret;
     } else if (atom.size > 8) { /* to read frma, esds atoms */
-        if (st->codec->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
+        if (st->codecpar->codec_id == AV_CODEC_ID_ALAC && atom.size >= 24) {
             uint64_t buffer;
             ret = ffio_ensure_seekback(pb, 8);
             if (ret < 0)
@@ -1548,16 +1620,16 @@ static int mov_read_wave(MOVContext *c, AVIOContext *pb, MOVAtom atom)
                 && buffer >> 32 >= 8) {
                 avio_skip(pb, -8);
                 atom.size += 8;
-            } else if (!st->codec->extradata_size) {
+            } else if (!st->codecpar->extradata_size) {
 #define ALAC_EXTRADATA_SIZE 36
-                st->codec->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
-                if (!st->codec->extradata)
+                st->codecpar->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
+                if (!st->codecpar->extradata)
                     return AVERROR(ENOMEM);
-                st->codec->extradata_size = ALAC_EXTRADATA_SIZE;
-                AV_WB32(st->codec->extradata    , ALAC_EXTRADATA_SIZE);
-                AV_WB32(st->codec->extradata + 4, MKTAG('a','l','a','c'));
-                AV_WB64(st->codec->extradata + 12, buffer);
-                avio_read(pb, st->codec->extradata + 20, 16);
+                st->codecpar->extradata_size = ALAC_EXTRADATA_SIZE;
+                AV_WB32(st->codecpar->extradata    , ALAC_EXTRADATA_SIZE);
+                AV_WB32(st->codecpar->extradata + 4, MKTAG('a','l','a','c'));
+                AV_WB64(st->codecpar->extradata + 12, buffer);
+                avio_read(pb, st->codecpar->extradata + 20, 16);
                 avio_skip(pb, atom.size - 24);
                 return 0;
             }
@@ -1594,12 +1666,12 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         if (type == MKTAG('f','i','e','l') && size == atom.size)
             return mov_read_default(c, pb, atom);
     }
-    if (st->codec->extradata_size > 1 && st->codec->extradata) {
+    if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) {
         av_log(c, AV_LOG_WARNING, "ignoring multiple glbl\n");
         return 0;
     }
-    av_freep(&st->codec->extradata);
-    ret = ff_get_extradata(st->codec, pb, atom.size);
+    av_freep(&st->codecpar->extradata);
+    ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size);
     if (ret < 0)
         return ret;
 
@@ -1624,8 +1696,8 @@ static int mov_read_dvc1(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         return 0;
 
     avio_seek(pb, 6, SEEK_CUR);
-    av_freep(&st->codec->extradata);
-    ret = ff_get_extradata(st->codec, pb, atom.size - 7);
+    av_freep(&st->codecpar->extradata);
+    ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 7);
     if (ret < 0)
         return ret;
 
@@ -1652,8 +1724,8 @@ static int mov_read_strf(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         return AVERROR_INVALIDDATA;
 
     avio_skip(pb, 40);
-    av_freep(&st->codec->extradata);
-    ret = ff_get_extradata(st->codec, pb, atom.size - 40);
+    av_freep(&st->codecpar->extradata);
+    ret = ff_get_extradata(c->fc, st->codecpar, pb, atom.size - 40);
     if (ret < 0)
         return ret;
 
@@ -1728,26 +1800,26 @@ static int mov_codec_id(AVStream *st, uint32_t format)
          (format & 0xFFFF) == 'T' + ('S' << 8)))
         id = ff_codec_get_id(ff_codec_wav_tags, av_bswap32(format) & 0xFFFF);
 
-    if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    } else if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO &&
-               /* skip old asf mpeg4 tag */
+    if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && id > 0) {
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    } else if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
+               /* skip old ASF MPEG-4 tag */
                format && format != MKTAG('m','p','4','s')) {
         id = ff_codec_get_id(ff_codec_movvideo_tags, format);
         if (id <= 0)
             id = ff_codec_get_id(ff_codec_bmp_tags, format);
         if (id > 0)
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        else if (st->codec->codec_type == AVMEDIA_TYPE_DATA ||
-                    (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE &&
-                    st->codec->codec_id == AV_CODEC_ID_NONE)) {
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
+                    (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE &&
+                    st->codecpar->codec_id == AV_CODEC_ID_NONE)) {
             id = ff_codec_get_id(ff_codec_movsubtitle_tags, format);
             if (id > 0)
-                st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
+                st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
         }
     }
 
-    st->codec->codec_tag = format;
+    st->codecpar->codec_tag = format;
 
     return id;
 }
@@ -1769,8 +1841,8 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
     avio_rb32(pb); /* temporal quality */
     avio_rb32(pb); /* spatial quality */
 
-    st->codec->width  = avio_rb16(pb); /* width */
-    st->codec->height = avio_rb16(pb); /* height */
+    st->codecpar->width  = avio_rb16(pb); /* width */
+    st->codecpar->height = avio_rb16(pb); /* height */
 
     avio_rb32(pb); /* horiz resolution */
     avio_rb32(pb); /* vert resolution */
@@ -1789,21 +1861,21 @@ static void mov_parse_stsd_video(MOVContext *c, AVIOContext *pb,
 
     /* codec_tag YV12 triggers an UV swap in rawdec.c */
     if (!memcmp(codec_name, "Planar Y'CbCr 8-bit 4:2:0", 25)) {
-        st->codec->codec_tag = MKTAG('I', '4', '2', '0');
-        st->codec->width &= ~1;
-        st->codec->height &= ~1;
+        st->codecpar->codec_tag = MKTAG('I', '4', '2', '0');
+        st->codecpar->width &= ~1;
+        st->codecpar->height &= ~1;
     }
-    /* Flash Media Server uses tag H263 with Sorenson Spark */
-    if (st->codec->codec_tag == MKTAG('H','2','6','3') &&
+    /* Flash Media Server uses tag H.263 with Sorenson Spark */
+    if (st->codecpar->codec_tag == MKTAG('H','2','6','3') &&
         !memcmp(codec_name, "Sorenson H263", 13))
-        st->codec->codec_id = AV_CODEC_ID_FLV1;
+        st->codecpar->codec_id = AV_CODEC_ID_FLV1;
 
-    st->codec->bits_per_coded_sample = avio_rb16(pb); /* depth */
+    st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* depth */
 
     avio_seek(pb, stsd_start, SEEK_SET);
 
-    if (ff_get_qtpalette(st->codec->codec_id, pb, sc->palette)) {
-        st->codec->bits_per_coded_sample &= 0x1F;
+    if (ff_get_qtpalette(st->codecpar->codec_id, pb, sc->palette)) {
+        st->codecpar->bits_per_coded_sample &= 0x1F;
         sc->has_palette = 1;
     }
 }
@@ -1818,14 +1890,14 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
     avio_rb16(pb); /* revision level */
     avio_rb32(pb); /* vendor */
 
-    st->codec->channels              = avio_rb16(pb); /* channel count */
-    st->codec->bits_per_coded_sample = avio_rb16(pb); /* sample size */
-    av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", st->codec->channels);
+    st->codecpar->channels              = avio_rb16(pb); /* channel count */
+    st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */
+    av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", st->codecpar->channels);
 
     sc->audio_cid = avio_rb16(pb);
     avio_rb16(pb); /* packet size = 0 */
 
-    st->codec->sample_rate = ((avio_rb32(pb) >> 16));
+    st->codecpar->sample_rate = ((avio_rb32(pb) >> 16));
 
     // Read QT version 1 fields. In version 0 these do not exist.
     av_log(c->fc, AV_LOG_TRACE, "version =%d, isom =%d\n", version, c->isom);
@@ -1839,22 +1911,22 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
             avio_rb32(pb); /* bytes per sample */
         } else if (version == 2) {
             avio_rb32(pb); /* sizeof struct only */
-            st->codec->sample_rate = av_int2double(avio_rb64(pb));
-            st->codec->channels    = avio_rb32(pb);
+            st->codecpar->sample_rate = av_int2double(avio_rb64(pb));
+            st->codecpar->channels    = avio_rb32(pb);
             avio_rb32(pb); /* always 0x7F000000 */
-            st->codec->bits_per_coded_sample = avio_rb32(pb);
+            st->codecpar->bits_per_coded_sample = avio_rb32(pb);
 
             flags = avio_rb32(pb); /* lpcm format specific flag */
             sc->bytes_per_frame   = avio_rb32(pb);
             sc->samples_per_frame = avio_rb32(pb);
-            if (st->codec->codec_tag == MKTAG('l','p','c','m'))
-                st->codec->codec_id =
-                    ff_mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample,
+            if (st->codecpar->codec_tag == MKTAG('l','p','c','m'))
+                st->codecpar->codec_id =
+                    ff_mov_get_lpcm_codec_id(st->codecpar->bits_per_coded_sample,
                                              flags);
         }
         if (version == 0 || (version == 1 && sc->audio_cid != -2)) {
             /* can't correctly handle variable sized packet as audio unit */
-            switch (st->codec->codec_id) {
+            switch (st->codecpar->codec_id) {
             case AV_CODEC_ID_MP2:
             case AV_CODEC_ID_MP3:
                 st->need_parsing = AVSTREAM_PARSE_FULL;
@@ -1864,43 +1936,43 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
     }
 
     if (sc->format == 0) {
-        if (st->codec->bits_per_coded_sample == 8)
-            st->codec->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
-        else if (st->codec->bits_per_coded_sample == 16)
-            st->codec->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
+        if (st->codecpar->bits_per_coded_sample == 8)
+            st->codecpar->codec_id = mov_codec_id(st, MKTAG('r','a','w',' '));
+        else if (st->codecpar->bits_per_coded_sample == 16)
+            st->codecpar->codec_id = mov_codec_id(st, MKTAG('t','w','o','s'));
     }
 
-    switch (st->codec->codec_id) {
+    switch (st->codecpar->codec_id) {
     case AV_CODEC_ID_PCM_S8:
     case AV_CODEC_ID_PCM_U8:
-        if (st->codec->bits_per_coded_sample == 16)
-            st->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
+        if (st->codecpar->bits_per_coded_sample == 16)
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
         break;
     case AV_CODEC_ID_PCM_S16LE:
     case AV_CODEC_ID_PCM_S16BE:
-        if (st->codec->bits_per_coded_sample == 8)
-            st->codec->codec_id = AV_CODEC_ID_PCM_S8;
-        else if (st->codec->bits_per_coded_sample == 24)
-            st->codec->codec_id =
-                st->codec->codec_id == AV_CODEC_ID_PCM_S16BE ?
+        if (st->codecpar->bits_per_coded_sample == 8)
+            st->codecpar->codec_id = AV_CODEC_ID_PCM_S8;
+        else if (st->codecpar->bits_per_coded_sample == 24)
+            st->codecpar->codec_id =
+                st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
                 AV_CODEC_ID_PCM_S24BE : AV_CODEC_ID_PCM_S24LE;
-        else if (st->codec->bits_per_coded_sample == 32)
-             st->codec->codec_id =
-                st->codec->codec_id == AV_CODEC_ID_PCM_S16BE ?
+        else if (st->codecpar->bits_per_coded_sample == 32)
+             st->codecpar->codec_id =
+                st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE ?
                 AV_CODEC_ID_PCM_S32BE : AV_CODEC_ID_PCM_S32LE;
         break;
     /* set values for old format before stsd version 1 appeared */
     case AV_CODEC_ID_MACE3:
         sc->samples_per_frame = 6;
-        sc->bytes_per_frame   = 2 * st->codec->channels;
+        sc->bytes_per_frame   = 2 * st->codecpar->channels;
         break;
     case AV_CODEC_ID_MACE6:
         sc->samples_per_frame = 6;
-        sc->bytes_per_frame   = 1 * st->codec->channels;
+        sc->bytes_per_frame   = 1 * st->codecpar->channels;
         break;
     case AV_CODEC_ID_ADPCM_IMA_QT:
         sc->samples_per_frame = 64;
-        sc->bytes_per_frame   = 34 * st->codec->channels;
+        sc->bytes_per_frame   = 34 * st->codecpar->channels;
         break;
     case AV_CODEC_ID_GSM:
         sc->samples_per_frame = 160;
@@ -1910,10 +1982,10 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
         break;
     }
 
-    bits_per_sample = av_get_bits_per_sample(st->codec->codec_id);
+    bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
     if (bits_per_sample) {
-        st->codec->bits_per_coded_sample = bits_per_sample;
-        sc->sample_size = (bits_per_sample >> 3) * st->codec->channels;
+        st->codecpar->bits_per_coded_sample = bits_per_sample;
+        sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels;
     }
 }
 
@@ -1925,10 +1997,10 @@ static void mov_parse_stsd_subtitle(MOVContext *c, AVIOContext *pb,
     // color, fonts, and default styles, so fake an atom to read it
     MOVAtom fake_atom = { .size = size };
     // mp4s contains a regular esds atom
-    if (st->codec->codec_tag != AV_RL32("mp4s"))
+    if (st->codecpar->codec_tag != AV_RL32("mp4s"))
         mov_read_glbl(c, pb, fake_atom);
-    st->codec->width  = sc->width;
-    st->codec->height = sc->height;
+    st->codecpar->width  = sc->width;
+    st->codecpar->height = sc->height;
 }
 
 static uint32_t yuv_to_rgba(uint32_t ycbcr)
@@ -1950,15 +2022,15 @@ static uint32_t yuv_to_rgba(uint32_t ycbcr)
 static int mov_rewrite_dvd_sub_extradata(AVStream *st)
 {
     char buf[256] = {0};
-    uint8_t *src = st->codec->extradata;
+    uint8_t *src = st->codecpar->extradata;
     int i;
 
-    if (st->codec->extradata_size != 64)
+    if (st->codecpar->extradata_size != 64)
         return 0;
 
-    if (st->codec->width > 0 &&  st->codec->height > 0)
+    if (st->codecpar->width > 0 &&  st->codecpar->height > 0)
         snprintf(buf, sizeof(buf), "size: %dx%d\n",
-                 st->codec->width, st->codec->height);
+                 st->codecpar->width, st->codecpar->height);
     av_strlcat(buf, "palette: ", sizeof(buf));
 
     for (i = 0; i < 16; i++) {
@@ -1971,13 +2043,13 @@ static int mov_rewrite_dvd_sub_extradata(AVStream *st)
     if (av_strlcat(buf, "\n", sizeof(buf)) >= sizeof(buf))
         return 0;
 
-    av_freep(&st->codec->extradata);
-    st->codec->extradata_size = 0;
-    st->codec->extradata = av_mallocz(strlen(buf) + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!st->codec->extradata)
+    av_freep(&st->codecpar->extradata);
+    st->codecpar->extradata_size = 0;
+    st->codecpar->extradata = av_mallocz(strlen(buf) + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!st->codecpar->extradata)
         return AVERROR(ENOMEM);
-    st->codec->extradata_size = strlen(buf);
-    memcpy(st->codec->extradata, buf, st->codec->extradata_size);
+    st->codecpar->extradata_size = strlen(buf);
+    memcpy(st->codecpar->extradata, buf, st->codecpar->extradata_size);
 
     return 0;
 }
@@ -1988,39 +2060,48 @@ static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
 {
     int ret;
 
-    if (st->codec->codec_tag == MKTAG('t','m','c','d')) {
+    if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
         if ((int)size != size)
             return AVERROR(ENOMEM);
 
-        ret = ff_get_extradata(st->codec, pb, size);
+        ret = ff_get_extradata(c->fc, st->codecpar, pb, size);
         if (ret < 0)
             return ret;
         if (size > 16) {
             MOVStreamContext *tmcd_ctx = st->priv_data;
             int val;
-            val = AV_RB32(st->codec->extradata + 4);
+            val = AV_RB32(st->codecpar->extradata + 4);
             tmcd_ctx->tmcd_flags = val;
-            if (val & 1)
-                st->codec->flags2 |= AV_CODEC_FLAG2_DROP_FRAME_TIMECODE;
-            st->codec->time_base.den = st->codec->extradata[16]; /* number of frame */
-            st->codec->time_base.num = 1;
+            st->avg_frame_rate.num = st->codecpar->extradata[16]; /* number of frame */
+            st->avg_frame_rate.den = 1;
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+            st->codec->time_base = av_inv_q(st->avg_frame_rate);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
             /* adjust for per frame dur in counter mode */
             if (tmcd_ctx->tmcd_flags & 0x0008) {
-                int timescale = AV_RB32(st->codec->extradata + 8);
-                int framedur = AV_RB32(st->codec->extradata + 12);
+                int timescale = AV_RB32(st->codecpar->extradata + 8);
+                int framedur = AV_RB32(st->codecpar->extradata + 12);
+                st->avg_frame_rate.num *= timescale;
+                st->avg_frame_rate.den *= framedur;
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
                 st->codec->time_base.den *= timescale;
                 st->codec->time_base.num *= framedur;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
             }
             if (size > 30) {
-                uint32_t len = AV_RB32(st->codec->extradata + 18); /* name atom length */
-                uint32_t format = AV_RB32(st->codec->extradata + 22);
+                uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */
+                uint32_t format = AV_RB32(st->codecpar->extradata + 22);
                 if (format == AV_RB32("name") && (int64_t)size >= (int64_t)len + 18) {
-                    uint16_t str_size = AV_RB16(st->codec->extradata + 26); /* string length */
+                    uint16_t str_size = AV_RB16(st->codecpar->extradata + 26); /* string length */
                     if (str_size > 0 && size >= (int)str_size + 26) {
                         char *reel_name = av_malloc(str_size + 1);
                         if (!reel_name)
                             return AVERROR(ENOMEM);
-                        memcpy(reel_name, st->codec->extradata + 30, str_size);
+                        memcpy(reel_name, st->codecpar->extradata + 30, str_size);
                         reel_name[str_size] = 0; /* Add null terminator */
                         /* don't add reel_name if emtpy string */
                         if (*reel_name == 0) {
@@ -2042,12 +2123,12 @@ static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb,
 static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
                                    AVStream *st, MOVStreamContext *sc)
 {
-    if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
-        !st->codec->sample_rate && sc->time_scale > 1)
-        st->codec->sample_rate = sc->time_scale;
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
+        !st->codecpar->sample_rate && sc->time_scale > 1)
+        st->codecpar->sample_rate = sc->time_scale;
 
     /* special codec parameters handling */
-    switch (st->codec->codec_id) {
+    switch (st->codecpar->codec_id) {
 #if CONFIG_DV_DEMUXER
     case AV_CODEC_ID_DVAUDIO:
         c->dv_fctx = avformat_alloc_context();
@@ -2061,33 +2142,33 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
             return AVERROR(ENOMEM);
         }
         sc->dv_audio_container = 1;
-        st->codec->codec_id    = AV_CODEC_ID_PCM_S16LE;
+        st->codecpar->codec_id    = AV_CODEC_ID_PCM_S16LE;
         break;
 #endif
     /* no ifdef since parameters are always those */
     case AV_CODEC_ID_QCELP:
-        st->codec->channels = 1;
+        st->codecpar->channels = 1;
         // force sample rate for qcelp when not stored in mov
-        if (st->codec->codec_tag != MKTAG('Q','c','l','p'))
-            st->codec->sample_rate = 8000;
+        if (st->codecpar->codec_tag != MKTAG('Q','c','l','p'))
+            st->codecpar->sample_rate = 8000;
         // FIXME: Why is the following needed for some files?
         sc->samples_per_frame = 160;
         if (!sc->bytes_per_frame)
             sc->bytes_per_frame = 35;
         break;
     case AV_CODEC_ID_AMR_NB:
-        st->codec->channels    = 1;
+        st->codecpar->channels    = 1;
         /* force sample rate for amr, stsd in 3gp does not store sample rate */
-        st->codec->sample_rate = 8000;
+        st->codecpar->sample_rate = 8000;
         break;
     case AV_CODEC_ID_AMR_WB:
-        st->codec->channels    = 1;
-        st->codec->sample_rate = 16000;
+        st->codecpar->channels    = 1;
+        st->codecpar->sample_rate = 16000;
         break;
     case AV_CODEC_ID_MP2:
     case AV_CODEC_ID_MP3:
         /* force type after stsd for m1a hdlr */
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
         break;
     case AV_CODEC_ID_GSM:
     case AV_CODEC_ID_ADPCM_MS:
@@ -2096,12 +2177,12 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb,
     case AV_CODEC_ID_MACE3:
     case AV_CODEC_ID_MACE6:
     case AV_CODEC_ID_QDM2:
-        st->codec->block_align = sc->bytes_per_frame;
+        st->codecpar->block_align = sc->bytes_per_frame;
         break;
     case AV_CODEC_ID_ALAC:
-        if (st->codec->extradata_size == 36) {
-            st->codec->channels    = AV_RB8 (st->codec->extradata + 21);
-            st->codec->sample_rate = AV_RB32(st->codec->extradata + 32);
+        if (st->codecpar->extradata_size == 36) {
+            st->codecpar->channels    = AV_RB8 (st->codecpar->extradata + 21);
+            st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32);
         }
         break;
     case AV_CODEC_ID_AC3:
@@ -2162,23 +2243,24 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
         int ret, dref_id = 1;
         MOVAtom a = { AV_RL32("stsd") };
         int64_t start_pos = avio_tell(pb);
-        int64_t size = avio_rb32(pb); /* size */
+        int64_t size    = avio_rb32(pb); /* size */
         uint32_t format = avio_rl32(pb); /* data format */
 
         if (size >= 16) {
             avio_rb32(pb); /* reserved */
             avio_rb16(pb); /* reserved */
             dref_id = avio_rb16(pb);
-        }else if (size <= 7){
-            av_log(c->fc, AV_LOG_ERROR, "invalid size %"PRId64" in stsd\n", size);
+        } else if (size <= 7) {
+            av_log(c->fc, AV_LOG_ERROR,
+                   "invalid size %"PRId64" in stsd\n", size);
             return AVERROR_INVALIDDATA;
         }
 
-        if (mov_skip_multiple_stsd(c, pb, st->codec->codec_tag, format,
+        if (mov_skip_multiple_stsd(c, pb, st->codecpar->codec_tag, format,
                                    size - (avio_tell(pb) - start_pos)))
             continue;
 
-        sc->pseudo_stream_id = st->codec->codec_tag ? -1 : pseudo_stream_id;
+        sc->pseudo_stream_id = st->codecpar->codec_tag ? -1 : pseudo_stream_id;
         sc->dref_id= dref_id;
         sc->format = format;
 
@@ -2187,16 +2269,16 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries)
         av_log(c->fc, AV_LOG_TRACE,
                "size=%"PRId64" 4CC= %c%c%c%c/0x%08x codec_type=%d\n", size,
                 (format >> 0) & 0xff, (format >> 8) & 0xff, (format >> 16) & 0xff,
-                (format >> 24) & 0xff, format, st->codec->codec_type);
+                (format >> 24) & 0xff, format, st->codecpar->codec_type);
 
-        if (st->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
-            st->codec->codec_id = id;
+        if (st->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) {
+            st->codecpar->codec_id = id;
             mov_parse_stsd_video(c, pb, st, sc);
-        } else if (st->codec->codec_type==AVMEDIA_TYPE_AUDIO) {
-            st->codec->codec_id = id;
+        } else if (st->codecpar->codec_type==AVMEDIA_TYPE_AUDIO) {
+            st->codecpar->codec_id = id;
             mov_parse_stsd_audio(c, pb, st, sc);
-        } else if (st->codec->codec_type==AVMEDIA_TYPE_SUBTITLE){
-            st->codec->codec_id = id;
+        } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){
+            st->codecpar->codec_id = id;
             mov_parse_stsd_subtitle(c, pb, st, sc,
                                     size - (avio_tell(pb) - start_pos));
         } else {
@@ -2329,7 +2411,7 @@ static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     if (!entries)
     {
         sc->keyframe_absent = 1;
-        if (!st->need_parsing && st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+        if (!st->need_parsing && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
             st->need_parsing = AVSTREAM_PARSE_HEADERS;
         return 0;
     }
@@ -2526,7 +2608,7 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
     AVStream *st;
     MOVStreamContext *sc;
-    unsigned int i, entries;
+    unsigned int i, entries, ctts_count = 0;
 
     if (c->fc->nb_streams < 1)
         return 0;
@@ -2552,8 +2634,16 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         int count    =avio_rb32(pb);
         int duration =avio_rb32(pb);
 
-        sc->ctts_data[i].count   = count;
-        sc->ctts_data[i].duration= duration;
+        if (count <= 0) {
+            av_log(c->fc, AV_LOG_TRACE,
+                   "ignoring CTTS entry with count=%d duration=%d\n",
+                   count, duration);
+            continue;
+        }
+
+        sc->ctts_data[ctts_count].count    = count;
+        sc->ctts_data[ctts_count].duration = duration;
+        ctts_count++;
 
         av_log(c->fc, AV_LOG_TRACE, "count=%d, duration=%d\n",
                 count, duration);
@@ -2569,7 +2659,7 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
             mov_update_dts_shift(sc, duration);
     }
 
-    sc->ctts_count = i;
+    sc->ctts_count = ctts_count;
 
     if (pb->eof_reached)
         return AVERROR_EOF;
@@ -2665,13 +2755,16 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
                 /* more than 16 frames delay, dts are likely wrong
                    this happens with files created by iMovie */
                 sc->wrong_dts = 1;
-                st->codec->has_b_frames = 1;
+                st->codecpar->video_delay = 1;
             }
         }
+
+        if (!unsupported && st->codecpar->codec_id == AV_CODEC_ID_AAC && start_time > 0)
+            sc->start_pad = start_time;
     }
 
     /* only use old uncompressed audio chunk demuxing when stts specifies it */
-    if (!(st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
+    if (!(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
           sc->stts_count == 1 && sc->stts_data[0].duration == 1)) {
         unsigned int current_sample = 0;
         unsigned int stts_sample = 0;
@@ -2743,14 +2836,19 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
                 if (sc->keyframe_absent
                     && !sc->stps_count
                     && !rap_group_present
-                    && (st->codec->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
+                    && (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || (i==0 && j==0)))
                      keyframe = 1;
                 if (keyframe)
                     distance = 0;
                 sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample];
                 if (sc->pseudo_stream_id == -1 ||
                    sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
-                    AVIndexEntry *e = &st->index_entries[st->nb_index_entries++];
+                    AVIndexEntry *e;
+                    if (sample_size > 0x3FFFFFFF) {
+                        av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
+                        return;
+                    }
+                    e = &st->index_entries[st->nb_index_entries++];
                     e->pos = current_offset;
                     e->timestamp = current_dts;
                     e->size = sample_size;
@@ -2759,7 +2857,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
                     av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
                             "size %d, distance %d, keyframe %d\n", st->index, current_sample,
                             current_offset, current_dts, sample_size, distance, keyframe);
-                    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries < 100)
+                    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries < 100)
                         ff_rfps_add_frame(mov->fc, st, current_dts);
                 }
 
@@ -2796,7 +2894,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
             }
         }
         if (st->duration > 0)
-            st->codec->bit_rate = stream_size*8*sc->time_scale/st->duration;
+            st->codecpar->bit_rate = stream_size*8*sc->time_scale/st->duration;
     } else {
         unsigned chunk_samples, total = 0;
 
@@ -2875,6 +2973,10 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
                     av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %d\n", total);
                     return;
                 }
+                if (size > 0x3FFFFFFF) {
+                    av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
+                    return;
+                }
                 e = &st->index_entries[st->nb_index_entries++];
                 e->pos = current_offset;
                 e->timestamp = current_dts;
@@ -3017,7 +3119,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     if (!sc) return AVERROR(ENOMEM);
 
     st->priv_data = sc;
-    st->codec->codec_type = AVMEDIA_TYPE_DATA;
+    st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
     sc->ffindex = st->index;
     c->trak_index = st->index;
 
@@ -3063,12 +3165,12 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         sc->pb_is_copied = 1;
     }
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-        if (!st->sample_aspect_ratio.num && st->codec->width && st->codec->height &&
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (!st->sample_aspect_ratio.num && st->codecpar->width && st->codecpar->height &&
             sc->height && sc->width &&
-            (st->codec->width != sc->width || st->codec->height != sc->height)) {
-            st->sample_aspect_ratio = av_d2q(((double)st->codec->height * sc->width) /
-                                             ((double)st->codec->width * sc->height), INT_MAX);
+            (st->codecpar->width != sc->width || st->codecpar->height != sc->height)) {
+            st->sample_aspect_ratio = av_d2q(((double)st->codecpar->height * sc->width) /
+                                             ((double)st->codecpar->width * sc->height), INT_MAX);
         }
 
 #if FF_API_R_FRAME_RATE
@@ -3079,14 +3181,14 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     }
 
     // done for ai5q, ai52, ai55, ai1q, ai12 and ai15.
-    if (!st->codec->extradata_size && st->codec->codec_id == AV_CODEC_ID_H264 &&
-        TAG_IS_AVCI(st->codec->codec_tag)) {
+    if (!st->codecpar->extradata_size && st->codecpar->codec_id == AV_CODEC_ID_H264 &&
+        TAG_IS_AVCI(st->codecpar->codec_tag)) {
         ret = ff_generate_avci_extradata(st);
         if (ret < 0)
             return ret;
     }
 
-    switch (st->codec->codec_id) {
+    switch (st->codecpar->codec_id) {
 #if CONFIG_H261_DECODER
     case AV_CODEC_ID_H261:
 #endif
@@ -3096,16 +3198,16 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 #if CONFIG_MPEG4_DECODER
     case AV_CODEC_ID_MPEG4:
 #endif
-        st->codec->width = 0; /* let decoder init width/height */
-        st->codec->height= 0;
+        st->codecpar->width = 0; /* let decoder init width/height */
+        st->codecpar->height= 0;
         break;
     }
 
     // If the duration of the mp3 packets is not constant, then they could need a parser
-    if (st->codec->codec_id == AV_CODEC_ID_MP3
+    if (st->codecpar->codec_id == AV_CODEC_ID_MP3
         && sc->stts_count > 3
         && sc->stts_count*10 > st->nb_frames
-        && sc->time_scale == st->codec->sample_rate) {
+        && sc->time_scale == st->codecpar->sample_rate) {
             st->need_parsing = AVSTREAM_PARSE_FULL;
     }
     /* Do not need those anymore. */
@@ -3172,11 +3274,12 @@ static int mov_read_keys(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     return 0;
 }
 
-static int mov_read_custom_2plus(MOVContext *c, AVIOContext *pb, int size)
+static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
-    int64_t end = avio_tell(pb) + size;
-    uint8_t *key = NULL, *val = NULL;
+    int64_t end = avio_tell(pb) + atom.size;
+    uint8_t *key = NULL, *val = NULL, *mean = NULL;
     int i;
+    int ret = 0;
     AVStream *st;
     MOVStreamContext *sc;
 
@@ -3185,10 +3288,9 @@ static int mov_read_custom_2plus(MOVContext *c, AVIOContext *pb, int size)
     st = c->fc->streams[c->fc->nb_streams-1];
     sc = st->priv_data;
 
-    for (i = 0; i < 2; i++) {
+    for (i = 0; i < 3; i++) {
         uint8_t **p;
         uint32_t len, tag;
-        int ret;
 
         if (end - avio_tell(pb) <= 12)
             break;
@@ -3201,7 +3303,9 @@ static int mov_read_custom_2plus(MOVContext *c, AVIOContext *pb, int size)
             break;
         len -= 12;
 
-        if (tag == MKTAG('n', 'a', 'm', 'e'))
+        if (tag == MKTAG('m', 'e', 'a', 'n'))
+            p = &mean;
+        else if (tag == MKTAG('n', 'a', 'm', 'e'))
             p = &key;
         else if (tag == MKTAG('d', 'a', 't', 'a') && len > 4) {
             avio_skip(pb, 4);
@@ -3216,12 +3320,12 @@ static int mov_read_custom_2plus(MOVContext *c, AVIOContext *pb, int size)
         ret = ffio_read_size(pb, *p, len);
         if (ret < 0) {
             av_freep(p);
-            return ret;
+            break;
         }
         (*p)[len] = 0;
     }
 
-    if (key && val) {
+    if (mean && key && val) {
         if (strcmp(key, "iTunSMPB") == 0) {
             int priming, remainder, samples;
             if(sscanf(val, "%*X %X %X %X", &priming, &remainder, &samples) == 3){
@@ -3234,44 +3338,16 @@ static int mov_read_custom_2plus(MOVContext *c, AVIOContext *pb, int size)
                         AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
             key = val = NULL;
         }
+    } else {
+        av_log(c->fc, AV_LOG_VERBOSE,
+               "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
     }
 
     avio_seek(pb, end, SEEK_SET);
     av_freep(&key);
     av_freep(&val);
-    return 0;
-}
-
-static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom)
-{
-    int64_t end = avio_tell(pb) + atom.size;
-    uint32_t tag, len;
-
-    if (atom.size < 8)
-        goto fail;
-
-    len = avio_rb32(pb);
-    tag = avio_rl32(pb);
-
-    if (len > atom.size)
-        goto fail;
-
-    if (tag == MKTAG('m', 'e', 'a', 'n') && len > 12) {
-        uint8_t domain[128];
-        int domain_len;
-
-        avio_skip(pb, 4); // flags
-        len -= 12;
-
-        domain_len = avio_get_str(pb, len, domain, sizeof(domain));
-        avio_skip(pb, len - domain_len);
-        return mov_read_custom_2plus(c, pb, end - avio_tell(pb));
-    }
-
-fail:
-    av_log(c->fc, AV_LOG_VERBOSE,
-           "Unhandled or malformed custom metadata of size %"PRId64"\n", atom.size);
-    return 0;
+    av_freep(&mean);
+    return ret;
 }
 
 static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom)
@@ -3616,7 +3692,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
             frag->time = AV_NOPTS_VALUE;
         }
         sc->ctts_count++;
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
             keyframe = 1;
         else
             keyframe =
@@ -4007,15 +4083,15 @@ static int mov_read_frma(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     case MKTAG('e','n','c','v'):        // encrypted video
     case MKTAG('e','n','c','a'):        // encrypted audio
         id = mov_codec_id(st, format);
-        if (st->codec->codec_id != AV_CODEC_ID_NONE &&
-            st->codec->codec_id != id) {
+        if (st->codecpar->codec_id != AV_CODEC_ID_NONE &&
+            st->codecpar->codec_id != id) {
             av_log(c->fc, AV_LOG_WARNING,
                    "ignoring 'frma' atom of '%.4s', stream has codec id %d\n",
-                   (char*)&format, st->codec->codec_id);
+                   (char*)&format, st->codecpar->codec_id);
             break;
         }
 
-        st->codec->codec_id = id;
+        st->codecpar->codec_id = id;
         sc->format = format;
         break;
 
@@ -4084,6 +4160,62 @@ static int mov_read_senc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     return av_aes_ctr_init(sc->cenc.aes_ctr, c->decryption_key);
 }
 
+static int mov_read_saiz(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+    AVStream *st;
+    MOVStreamContext *sc;
+    size_t data_size;
+    int atom_header_size;
+    int flags;
+
+    if (c->decryption_key_len == 0 || c->fc->nb_streams < 1)
+        return 0;
+
+    st = c->fc->streams[c->fc->nb_streams - 1];
+    sc = st->priv_data;
+
+    if (sc->cenc.auxiliary_info_sizes || sc->cenc.auxiliary_info_default_size) {
+        av_log(c->fc, AV_LOG_ERROR, "duplicate saiz atom\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    atom_header_size = 9;
+
+    avio_r8(pb); /* version */
+    flags = avio_rb24(pb);
+
+    if ((flags & 0x01) != 0) {
+        atom_header_size += 8;
+
+        avio_rb32(pb);    /* info type */
+        avio_rb32(pb);    /* info type param */
+    }
+
+    sc->cenc.auxiliary_info_default_size = avio_r8(pb);
+    avio_rb32(pb);    /* entries */
+
+    if (atom.size <= atom_header_size) {
+        return 0;
+    }
+
+    /* save the auxiliary info sizes as is */
+    data_size = atom.size - atom_header_size;
+
+    sc->cenc.auxiliary_info_sizes = av_malloc(data_size);
+    if (!sc->cenc.auxiliary_info_sizes) {
+        return AVERROR(ENOMEM);
+    }
+
+    sc->cenc.auxiliary_info_sizes_count = data_size;
+
+    if (avio_read(pb, sc->cenc.auxiliary_info_sizes, data_size) != data_size) {
+        av_log(c->fc, AV_LOG_ERROR, "failed to read the auxiliary info sizes");
+        return AVERROR_INVALIDDATA;
+    }
+
+    return 0;
+}
+
 static int cenc_filter(MOVContext *c, MOVStreamContext *sc, uint8_t *input, int size)
 {
     uint32_t encrypted_bytes;
@@ -4150,6 +4282,36 @@ static int cenc_filter(MOVContext *c, MOVStreamContext *sc, uint8_t *input, int
     return 0;
 }
 
+static int mov_seek_auxiliary_info(AVFormatContext *s, MOVStreamContext *sc)
+{
+    size_t auxiliary_info_seek_offset = 0;
+    int i;
+
+    if (sc->cenc.auxiliary_info_default_size) {
+        auxiliary_info_seek_offset = (size_t)sc->cenc.auxiliary_info_default_size * sc->current_sample;
+    } else if (sc->cenc.auxiliary_info_sizes) {
+        if (sc->current_sample > sc->cenc.auxiliary_info_sizes_count) {
+            av_log(s, AV_LOG_ERROR, "current sample %d greater than the number of auxiliary info sample sizes %"SIZE_SPECIFIER"\n",
+                sc->current_sample, sc->cenc.auxiliary_info_sizes_count);
+            return AVERROR_INVALIDDATA;
+        }
+
+        for (i = 0; i < sc->current_sample; i++) {
+            auxiliary_info_seek_offset += sc->cenc.auxiliary_info_sizes[i];
+        }
+    }
+
+    if (auxiliary_info_seek_offset > sc->cenc.auxiliary_info_end - sc->cenc.auxiliary_info) {
+        av_log(s, AV_LOG_ERROR, "auxiliary info offset %"SIZE_SPECIFIER" greater than auxiliary info size %"SIZE_SPECIFIER"\n",
+            auxiliary_info_seek_offset, (size_t)(sc->cenc.auxiliary_info_end - sc->cenc.auxiliary_info));
+        return AVERROR_INVALIDDATA;
+    }
+
+    sc->cenc.auxiliary_info_pos = sc->cenc.auxiliary_info + auxiliary_info_seek_offset;
+
+    return 0;
+}
+
 static const MOVParseTableEntry mov_default_parse_table[] = {
 { MKTAG('A','C','L','R'), mov_read_aclr },
 { MKTAG('A','P','R','G'), mov_read_avid },
@@ -4227,6 +4389,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = {
 { MKTAG('s','i','n','f'), mov_read_default },
 { MKTAG('f','r','m','a'), mov_read_frma },
 { MKTAG('s','e','n','c'), mov_read_senc },
+{ MKTAG('s','a','i','z'), mov_read_saiz },
 { 0, NULL }
 };
 
@@ -4513,8 +4676,7 @@ static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st,
 {
     AVTimecode tc;
     char buf[AV_TIMECODE_STR_SIZE];
-    AVRational rate = {st->codec->time_base.den,
-                       st->codec->time_base.num};
+    AVRational rate = st->avg_frame_rate;
     int ret = av_timecode_init(&tc, rate, flags, 0, s);
     if (ret < 0)
         return ret;
@@ -4587,6 +4749,7 @@ static int mov_read_close(AVFormatContext *s)
         av_freep(&sc->display_matrix);
 
         av_freep(&sc->cenc.auxiliary_info);
+        av_freep(&sc->cenc.auxiliary_info_sizes);
         av_aes_ctr_free(sc->cenc.aes_ctr);
     }
 
@@ -4625,7 +4788,7 @@ static int tmcd_is_referenced(AVFormatContext *s, int tmcd_id)
         AVStream *st = s->streams[i];
         MOVStreamContext *sc = st->priv_data;
 
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
             sc->timecode_track == tmcd_id)
             return 1;
     }
@@ -4640,7 +4803,7 @@ static void export_orphan_timecode(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
 
-        if (st->codec->codec_tag  == MKTAG('t','m','c','d') &&
+        if (st->codecpar->codec_tag  == MKTAG('t','m','c','d') &&
             !tmcd_is_referenced(s, i + 1)) {
             AVDictionaryEntry *tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
             if (tcr) {
@@ -4800,7 +4963,7 @@ static int mov_read_header(AVFormatContext *s)
         if (mov->chapter_track > 0 && !mov->ignore_chapters)
             mov_read_chapters(s);
         for (i = 0; i < s->nb_streams; i++)
-            if (s->streams[i]->codec->codec_tag == AV_RL32("tmcd"))
+            if (s->streams[i]->codecpar->codec_tag == AV_RL32("tmcd"))
                 mov_read_timecode_track(s, s->streams[i]);
     }
 
@@ -4829,25 +4992,25 @@ static int mov_read_header(AVFormatContext *s)
         AVStream *st = s->streams[i];
         MOVStreamContext *sc = st->priv_data;
         fix_timescale(mov, sc);
-        if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->codec->codec_id == AV_CODEC_ID_AAC) {
+        if(st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->codec_id == AV_CODEC_ID_AAC) {
             st->skip_samples = sc->start_pad;
         }
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && sc->nb_frames_for_fps > 0 && sc->duration_for_fps > 0)
             av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
                       sc->time_scale*(int64_t)sc->nb_frames_for_fps, sc->duration_for_fps, INT_MAX);
-        if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
-            if (st->codec->width <= 0 || st->codec->height <= 0) {
-                st->codec->width  = sc->width;
-                st->codec->height = sc->height;
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+            if (st->codecpar->width <= 0 || st->codecpar->height <= 0) {
+                st->codecpar->width  = sc->width;
+                st->codecpar->height = sc->height;
             }
-            if (st->codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) {
                 if ((err = mov_rewrite_dvd_sub_extradata(st)) < 0)
                     return err;
             }
         }
         if (mov->handbrake_version &&
             mov->handbrake_version <= 1000000*0 + 1000*10 + 2 &&  // 0.10.2
-            st->codec->codec_id == AV_CODEC_ID_MP3
+            st->codecpar->codec_id == AV_CODEC_ID_MP3
         ) {
             av_log(s, AV_LOG_VERBOSE, "Forcing full parsing for mp3 stream\n");
             st->need_parsing = AVSTREAM_PARSE_FULL;
@@ -4859,7 +5022,7 @@ static int mov_read_header(AVFormatContext *s)
             AVStream *st = s->streams[i];
             MOVStreamContext *sc = st->priv_data;
             if (st->duration > 0)
-                st->codec->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration;
+                st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration;
         }
     }
 
@@ -4868,7 +5031,7 @@ static int mov_read_header(AVFormatContext *s)
             AVStream *st = s->streams[i];
             MOVStreamContext *sc = st->priv_data;
             if (sc->duration_for_fps > 0) {
-                st->codec->bit_rate = sc->data_size * 8 * sc->time_scale /
+                st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale /
                     sc->duration_for_fps;
             }
         }
@@ -4876,7 +5039,7 @@ static int mov_read_header(AVFormatContext *s)
 
     for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) {
         if (mov->bitrates[i]) {
-            s->streams[i]->codec->bit_rate = mov->bitrates[i];
+            s->streams[i]->codecpar->bit_rate = mov->bitrates[i];
         }
     }
 
@@ -4886,7 +5049,7 @@ static int mov_read_header(AVFormatContext *s)
         AVStream *st = s->streams[i];
         MOVStreamContext *sc = st->priv_data;
 
-        switch (st->codec->codec_type) {
+        switch (st->codecpar->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
             err = ff_replaygain_export(st, s->metadata);
             if (err < 0) {
@@ -5154,6 +5317,12 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp,
             time_sample = next;
         }
     }
+
+    ret = mov_seek_auxiliary_info(s, sc);
+    if (ret < 0) {
+        return ret;
+    }
+
     return sample;
 }
 
diff --git a/libavformat/mov_chan.c b/libavformat/mov_chan.c
index cba07c5..dc8bf8d 100644
--- a/libavformat/mov_chan.c
+++ b/libavformat/mov_chan.c
@@ -588,9 +588,9 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st,
     }
     if (layout_tag == 0) {
         if (label_mask)
-            st->codec->channel_layout = label_mask;
+            st->codecpar->channel_layout = label_mask;
     } else
-        st->codec->channel_layout = ff_mov_get_channel_layout(layout_tag, bitmap);
+        st->codecpar->channel_layout = ff_mov_get_channel_layout(layout_tag, bitmap);
     avio_skip(pb, size - 12);
 
     return 0;
diff --git a/libavformat/movenc-test.c b/libavformat/movenc-test.c
deleted file mode 100644
index 8c69c76..0000000
--- a/libavformat/movenc-test.c
+++ /dev/null
@@ -1,676 +0,0 @@
-/*
- * Copyright (c) 2015 Martin Storsjo
- *
- * 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 "config.h"
-
-#include "libavutil/intreadwrite.h"
-#include "libavutil/mathematics.h"
-#include "libavutil/md5.h"
-
-#include "avformat.h"
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#if !HAVE_GETOPT
-#include "compat/getopt.c"
-#endif
-
-#define HASH_SIZE 16
-
-static const uint8_t h264_extradata[] = {
-    0x01, 0x4d, 0x40, 0x1e, 0xff, 0xe1, 0x00, 0x02, 0x67, 0x4d, 0x01, 0x00, 0x02, 0x68, 0xef
-};
-static const uint8_t aac_extradata[] = {
-    0x12, 0x10
-};
-
-
-static const char *format = "mp4";
-AVFormatContext *ctx;
-uint8_t iobuf[32768];
-AVDictionary *opts;
-
-int write_file;
-const char *cur_name;
-FILE* out;
-int out_size;
-struct AVMD5* md5;
-uint8_t hash[HASH_SIZE];
-
-AVStream *video_st, *audio_st;
-int64_t audio_dts, video_dts;
-
-int bframes;
-int64_t duration;
-int64_t audio_duration;
-int frames;
-int gop_size;
-int64_t next_p_pts;
-enum AVPictureType last_picture;
-int skip_write;
-int skip_write_audio;
-int clear_duration;
-
-int num_warnings;
-
-int check_faults;
-
-
-static void count_warnings(void *avcl, int level, const char *fmt, va_list vl)
-{
-    if (level == AV_LOG_WARNING)
-        num_warnings++;
-}
-
-static void init_count_warnings(void)
-{
-    av_log_set_callback(count_warnings);
-    num_warnings = 0;
-}
-
-static void reset_count_warnings(void)
-{
-    av_log_set_callback(av_log_default_callback);
-}
-
-static int io_write(void *opaque, uint8_t *buf, int size)
-{
-    out_size += size;
-    av_md5_update(md5, buf, size);
-    if (out)
-        fwrite(buf, 1, size, out);
-    return size;
-}
-
-static void init_out(const char *name)
-{
-    char buf[100];
-    cur_name = name;
-    snprintf(buf, sizeof(buf), "%s.%s", cur_name, format);
-
-    av_md5_init(md5);
-    if (write_file) {
-        out = fopen(buf, "wb");
-        if (!out)
-            perror(buf);
-    }
-    out_size = 0;
-}
-
-static void close_out(void)
-{
-    int i;
-    av_md5_final(md5, hash);
-    for (i = 0; i < HASH_SIZE; i++)
-        printf("%02x", hash[i]);
-    printf(" %d %s\n", out_size, cur_name);
-    if (out)
-        fclose(out);
-    out = NULL;
-}
-
-static void check_func(int value, int line, const char *msg, ...)
-{
-    if (!value) {
-        va_list ap;
-        va_start(ap, msg);
-        printf("%d: ", line);
-        vprintf(msg, ap);
-        printf("\n");
-        check_faults++;
-        va_end(ap);
-    }
-}
-#define check(value, ...) check_func(value, __LINE__, __VA_ARGS__)
-
-static void init_fps(int bf, int audio_preroll, int fps)
-{
-    AVStream *st;
-    ctx = avformat_alloc_context();
-    if (!ctx)
-        exit(1);
-    ctx->oformat = av_guess_format(format, NULL, NULL);
-    if (!ctx->oformat)
-        exit(1);
-    ctx->pb = avio_alloc_context(iobuf, sizeof(iobuf), AVIO_FLAG_WRITE, NULL, NULL, io_write, NULL);
-    if (!ctx->pb)
-        exit(1);
-    ctx->flags |= AVFMT_FLAG_BITEXACT;
-
-    st = avformat_new_stream(ctx, NULL);
-    if (!st)
-        exit(1);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_H264;
-    st->codec->width = 640;
-    st->codec->height = 480;
-    st->time_base.num = 1;
-    st->time_base.den = 30;
-    st->codec->extradata_size = sizeof(h264_extradata);
-    st->codec->extradata = av_mallocz(st->codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!st->codec->extradata)
-        exit(1);
-    memcpy(st->codec->extradata, h264_extradata, sizeof(h264_extradata));
-    video_st = st;
-
-    st = avformat_new_stream(ctx, NULL);
-    if (!st)
-        exit(1);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_AAC;
-    st->codec->sample_rate = 44100;
-    st->codec->channels = 2;
-    st->time_base.num = 1;
-    st->time_base.den = 44100;
-    st->codec->extradata_size = sizeof(aac_extradata);
-    st->codec->extradata = av_mallocz(st->codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!st->codec->extradata)
-        exit(1);
-    memcpy(st->codec->extradata, aac_extradata, sizeof(aac_extradata));
-    audio_st = st;
-
-    if (avformat_write_header(ctx, &opts) < 0)
-        exit(1);
-    av_dict_free(&opts);
-
-    frames = 0;
-    gop_size = 30;
-    duration = video_st->time_base.den / fps;
-    audio_duration = 1024LL * audio_st->time_base.den / audio_st->codec->sample_rate;
-    if (audio_preroll)
-        audio_preroll = 2048LL * audio_st->time_base.den / audio_st->codec->sample_rate;
-
-    bframes = bf;
-    video_dts = bframes ? -duration : 0;
-    audio_dts = -audio_preroll;
-}
-
-static void init(int bf, int audio_preroll)
-{
-    init_fps(bf, audio_preroll, 30);
-}
-
-static void mux_frames(int n)
-{
-    int end_frames = frames + n;
-    while (1) {
-        AVPacket pkt;
-        uint8_t pktdata[8] = { 0 };
-        av_init_packet(&pkt);
-
-        if (av_compare_ts(audio_dts, audio_st->time_base, video_dts, video_st->time_base) < 0) {
-            pkt.dts = pkt.pts = audio_dts;
-            pkt.stream_index = 1;
-            pkt.duration = audio_duration;
-            audio_dts += audio_duration;
-        } else {
-            if (frames == end_frames)
-                break;
-            pkt.dts = video_dts;
-            pkt.stream_index = 0;
-            pkt.duration = duration;
-            if ((frames % gop_size) == 0) {
-                pkt.flags |= AV_PKT_FLAG_KEY;
-                last_picture = AV_PICTURE_TYPE_I;
-                pkt.pts = pkt.dts + duration;
-                video_dts = pkt.pts;
-            } else {
-                if (last_picture == AV_PICTURE_TYPE_P) {
-                    last_picture = AV_PICTURE_TYPE_B;
-                    pkt.pts = pkt.dts;
-                    video_dts = next_p_pts;
-                } else {
-                    last_picture = AV_PICTURE_TYPE_P;
-                    if (((frames + 1) % gop_size) == 0) {
-                        pkt.pts = pkt.dts + duration;
-                        video_dts = pkt.pts;
-                    } else {
-                        next_p_pts = pkt.pts = pkt.dts + 2 * duration;
-                        video_dts += duration;
-                    }
-                }
-            }
-            if (!bframes)
-                pkt.pts = pkt.dts;
-            frames++;
-        }
-
-        if (clear_duration)
-            pkt.duration = 0;
-        AV_WB32(pktdata + 4, pkt.pts);
-        pkt.data = pktdata;
-        pkt.size = 8;
-        if (skip_write)
-            continue;
-        if (skip_write_audio && pkt.stream_index == 1)
-            continue;
-        av_write_frame(ctx, &pkt);
-    }
-}
-
-static void mux_gops(int n)
-{
-    mux_frames(gop_size * n);
-}
-
-static void skip_gops(int n)
-{
-    skip_write = 1;
-    mux_gops(n);
-    skip_write = 0;
-}
-
-static void signal_init_ts(void)
-{
-    AVPacket pkt;
-    av_init_packet(&pkt);
-    pkt.size = 0;
-    pkt.data = NULL;
-
-    pkt.stream_index = 0;
-    pkt.dts = video_dts;
-    pkt.pts = 0;
-    av_write_frame(ctx, &pkt);
-
-    pkt.stream_index = 1;
-    pkt.dts = pkt.pts = audio_dts;
-    av_write_frame(ctx, &pkt);
-}
-
-static void finish(void)
-{
-    av_write_trailer(ctx);
-    av_free(ctx->pb);
-    avformat_free_context(ctx);
-    ctx = NULL;
-}
-
-static void help(void)
-{
-    printf("movenc-test [-w]\n"
-           "-w          write output into files\n");
-}
-
-int main(int argc, char **argv)
-{
-    int c;
-    uint8_t header[HASH_SIZE];
-    uint8_t content[HASH_SIZE];
-    int empty_moov_pos;
-    int prev_pos;
-
-    for (;;) {
-        c = getopt(argc, argv, "wh");
-        if (c == -1)
-            break;
-        switch (c) {
-        case 'w':
-            write_file = 1;
-            break;
-        default:
-        case 'h':
-            help();
-            return 0;
-        }
-    }
-
-    av_register_all();
-
-    md5 = av_md5_alloc();
-    if (!md5)
-        return 1;
-
-    // Write a fragmented file with an initial moov that actually contains some
-    // samples. One moov+mdat with 1 second of data and one moof+mdat with 1
-    // second of data.
-    init_out("non-empty-moov");
-    av_dict_set(&opts, "movflags", "frag_keyframe", 0);
-    init(0, 0);
-    mux_gops(2);
-    finish();
-    close_out();
-
-    // Write a similar file, but with b-frames and audio preroll, handled
-    // via an edit list.
-    init_out("non-empty-moov-elst");
-    av_dict_set(&opts, "movflags", "frag_keyframe", 0);
-    av_dict_set(&opts, "use_editlist", "1", 0);
-    init(1, 1);
-    mux_gops(2);
-    finish();
-    close_out();
-
-    // Use b-frames but no audio-preroll, but without an edit list.
-    // Due to avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO, the dts
-    // of the first audio packet is > 0, but it is set to zero since edit
-    // lists aren't used, increasing the duration of the first packet instead.
-    init_out("non-empty-moov-no-elst");
-    av_dict_set(&opts, "movflags", "frag_keyframe", 0);
-    av_dict_set(&opts, "use_editlist", "0", 0);
-    init(1, 0);
-    mux_gops(2);
-    finish();
-    close_out();
-
-    format = "ismv";
-    // Write an ISMV, with b-frames and audio preroll.
-    init_out("ismv");
-    av_dict_set(&opts, "movflags", "frag_keyframe", 0);
-    init(1, 1);
-    mux_gops(2);
-    finish();
-    close_out();
-    format = "mp4";
-
-    // An initial moov that doesn't contain any samples, followed by two
-    // moof+mdat pairs.
-    init_out("empty-moov");
-    av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
-    av_dict_set(&opts, "use_editlist", "0", 0);
-    init(0, 0);
-    mux_gops(2);
-    finish();
-    close_out();
-    memcpy(content, hash, HASH_SIZE);
-
-    // Similar to the previous one, but with input that doesn't start at
-    // pts/dts 0. avoid_negative_ts behaves in the same way as
-    // in non-empty-moov-no-elst above.
-    init_out("empty-moov-no-elst");
-    av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
-    init(1, 0);
-    mux_gops(2);
-    finish();
-    close_out();
-
-    // Same as the previous one, but disable avoid_negative_ts (which
-    // would require using an edit list, but with empty_moov, one can't
-    // write a sensible edit list, when the start timestamps aren't known).
-    // This should trigger a warning - we check that the warning is produced.
-    init_count_warnings();
-    init_out("empty-moov-no-elst-no-adjust");
-    av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
-    av_dict_set(&opts, "avoid_negative_ts", "0", 0);
-    init(1, 0);
-    mux_gops(2);
-    finish();
-    close_out();
-
-    reset_count_warnings();
-    check(num_warnings > 0, "No warnings printed for unhandled start offset");
-
-    // Verify that delay_moov produces the same as empty_moov for
-    // simple input
-    init_out("delay-moov");
-    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
-    av_dict_set(&opts, "use_editlist", "0", 0);
-    init(0, 0);
-    mux_gops(2);
-    finish();
-    close_out();
-    check(!memcmp(hash, content, HASH_SIZE), "delay_moov differs from empty_moov");
-
-    // Test writing content that requires an edit list using delay_moov
-    init_out("delay-moov-elst");
-    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
-    init(1, 1);
-    mux_gops(2);
-    finish();
-    close_out();
-
-    // Test writing a file with one track lacking packets, with delay_moov.
-    skip_write_audio = 1;
-    init_out("delay-moov-empty-track");
-    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
-    init(0, 0);
-    mux_gops(2);
-    // The automatic flushing shouldn't output anything, since we're still
-    // waiting for data for some tracks
-    check(out_size == 0, "delay_moov flushed prematurely");
-    // When closed (or manually flushed), all the written data should still
-    // be output.
-    finish();
-    close_out();
-    check(out_size > 0, "delay_moov didn't output anything");
-
-    // Check that manually flushing still outputs things as expected. This
-    // produces two fragments, while the one above produces only one.
-    init_out("delay-moov-empty-track-flush");
-    av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0);
-    init(0, 0);
-    mux_gops(1);
-    av_write_frame(ctx, NULL); // Force writing the moov
-    check(out_size > 0, "No moov written");
-    av_write_frame(ctx, NULL);
-    mux_gops(1);
-    av_write_frame(ctx, NULL);
-    finish();
-    close_out();
-
-    skip_write_audio = 0;
-
-
-
-    // Verify that the header written by delay_moov when manually flushed
-    // is identical to the one by empty_moov.
-    init_out("empty-moov-header");
-    av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
-    av_dict_set(&opts, "use_editlist", "0", 0);
-    init(0, 0);
-    close_out();
-    memcpy(header, hash, HASH_SIZE);
-    init_out("empty-moov-content");
-    mux_gops(2);
-    // Written 2 seconds of content, with an automatic flush after 1 second.
-    check(out_size > 0, "No automatic flush?");
-    empty_moov_pos = prev_pos = out_size;
-    // Manually flush the second fragment
-    av_write_frame(ctx, NULL);
-    check(out_size > prev_pos, "No second fragment flushed?");
-    prev_pos = out_size;
-    // Check that an extra flush doesn't output any more data
-    av_write_frame(ctx, NULL);
-    check(out_size == prev_pos, "More data written?");
-    close_out();
-    memcpy(content, hash, HASH_SIZE);
-    // Ignore the trailer written here
-    finish();
-
-    init_out("delay-moov-header");
-    av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0);
-    av_dict_set(&opts, "use_editlist", "0", 0);
-    init(0, 0);
-    check(out_size == 0, "Output written during init with delay_moov");
-    mux_gops(1); // Write 1 second of content
-    av_write_frame(ctx, NULL); // Force writing the moov
-    close_out();
-    check(!memcmp(hash, header, HASH_SIZE), "delay_moov header differs from empty_moov");
-    init_out("delay-moov-content");
-    av_write_frame(ctx, NULL); // Flush the first fragment
-    check(out_size == empty_moov_pos, "Manually flushed content differs from automatically flushed, %d vs %d", out_size, empty_moov_pos);
-    mux_gops(1); // Write the rest of the content
-    av_write_frame(ctx, NULL); // Flush the second fragment
-    close_out();
-    check(!memcmp(hash, content, HASH_SIZE), "delay_moov content differs from empty_moov");
-    finish();
-
-
-    // Verify that we can produce an identical second fragment without
-    // writing the first one. First write the reference fragments that
-    // we want to reproduce.
-    av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash", 0);
-    init(0, 0);
-    mux_gops(1);
-    av_write_frame(ctx, NULL); // Output the first fragment
-    init_out("empty-moov-second-frag");
-    mux_gops(1);
-    av_write_frame(ctx, NULL); // Output the second fragment
-    close_out();
-    memcpy(content, hash, HASH_SIZE);
-    finish();
-
-    // Produce the same second fragment without actually writing the first
-    // one before.
-    av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash+frag_discont", 0);
-    av_dict_set(&opts, "fragment_index", "2", 0);
-    av_dict_set(&opts, "avoid_negative_ts", "0", 0);
-    av_dict_set(&opts, "use_editlist", "0", 0);
-    init(0, 0);
-    skip_gops(1);
-    init_out("empty-moov-second-frag-discont");
-    mux_gops(1);
-    av_write_frame(ctx, NULL); // Output the second fragment
-    close_out();
-    check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
-    finish();
-
-    // Produce the same thing by using delay_moov, which requires a slightly
-    // different call sequence.
-    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
-    av_dict_set(&opts, "fragment_index", "2", 0);
-    init(0, 0);
-    skip_gops(1);
-    mux_gops(1);
-    av_write_frame(ctx, NULL); // Output the moov
-    init_out("delay-moov-second-frag-discont");
-    av_write_frame(ctx, NULL); // Output the second fragment
-    close_out();
-    check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
-    finish();
-
-
-    // Test discontinously written fragments with b-frames (where the
-    // assumption of starting at pts=0 works) but not with audio preroll
-    // (which can't be guessed).
-    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0);
-    init(1, 0);
-    mux_gops(1);
-    init_out("delay-moov-elst-init");
-    av_write_frame(ctx, NULL); // Output the moov
-    close_out();
-    memcpy(header, hash, HASH_SIZE);
-    av_write_frame(ctx, NULL); // Output the first fragment
-    init_out("delay-moov-elst-second-frag");
-    mux_gops(1);
-    av_write_frame(ctx, NULL); // Output the second fragment
-    close_out();
-    memcpy(content, hash, HASH_SIZE);
-    finish();
-
-    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
-    av_dict_set(&opts, "fragment_index", "2", 0);
-    init(1, 0);
-    skip_gops(1);
-    mux_gops(1); // Write the second fragment
-    init_out("delay-moov-elst-init-discont");
-    av_write_frame(ctx, NULL); // Output the moov
-    close_out();
-    check(!memcmp(hash, header, HASH_SIZE), "discontinuously written header differs");
-    init_out("delay-moov-elst-second-frag-discont");
-    av_write_frame(ctx, NULL); // Output the second fragment
-    close_out();
-    check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
-    finish();
-
-
-    // Test discontinously written fragments with b-frames and audio preroll,
-    // properly signaled.
-    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0);
-    init(1, 1);
-    mux_gops(1);
-    init_out("delay-moov-elst-signal-init");
-    av_write_frame(ctx, NULL); // Output the moov
-    close_out();
-    memcpy(header, hash, HASH_SIZE);
-    av_write_frame(ctx, NULL); // Output the first fragment
-    init_out("delay-moov-elst-signal-second-frag");
-    mux_gops(1);
-    av_write_frame(ctx, NULL); // Output the second fragment
-    close_out();
-    memcpy(content, hash, HASH_SIZE);
-    finish();
-
-    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
-    av_dict_set(&opts, "fragment_index", "2", 0);
-    init(1, 1);
-    signal_init_ts();
-    skip_gops(1);
-    mux_gops(1); // Write the second fragment
-    init_out("delay-moov-elst-signal-init-discont");
-    av_write_frame(ctx, NULL); // Output the moov
-    close_out();
-    check(!memcmp(hash, header, HASH_SIZE), "discontinuously written header differs");
-    init_out("delay-moov-elst-signal-second-frag-discont");
-    av_write_frame(ctx, NULL); // Output the second fragment
-    close_out();
-    check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
-    finish();
-
-
-    // Test VFR content, with sidx atoms (which declare the pts duration
-    // of a fragment, forcing overriding the start pts of the next one).
-    // Here, the fragment duration in pts is significantly different from
-    // the duration in dts. The video stream starts at dts=-10,pts=0, and
-    // the second fragment starts at dts=155,pts=156. The trun duration sum
-    // of the first fragment is 165, which also is written as
-    // baseMediaDecodeTime in the tfdt in the second fragment. The sidx for
-    // the first fragment says earliest_presentation_time = 0 and
-    // subsegment_duration = 156, which also matches the sidx in the second
-    // fragment. For the audio stream, the pts and dts durations also don't
-    // match - the input stream starts at pts=-2048, but that part is excluded
-    // by the edit list.
-    init_out("vfr");
-    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0);
-    init_fps(1, 1, 3);
-    mux_frames(gop_size/2);
-    duration /= 10;
-    mux_frames(gop_size/2);
-    mux_gops(1);
-    finish();
-    close_out();
-
-    // Test VFR content, with cleared duration fields. In these cases,
-    // the muxer must guess the duration of the last packet of each
-    // fragment. As long as the framerate doesn't vary (too much) at the
-    // fragment edge, it works just fine. Additionally, when automatically
-    // cutting fragments, the muxer already know the timestamps of the next
-    // packet for one stream (in most cases the video stream), avoiding
-    // having to use guesses for that one.
-    init_count_warnings();
-    clear_duration = 1;
-    init_out("vfr-noduration");
-    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0);
-    init_fps(1, 1, 3);
-    mux_frames(gop_size/2);
-    duration /= 10;
-    mux_frames(gop_size/2);
-    mux_gops(1);
-    finish();
-    close_out();
-    clear_duration = 0;
-    reset_count_warnings();
-    check(num_warnings > 0, "No warnings printed for filled in durations");
-
-    av_free(md5);
-
-    return check_faults > 0 ? 1 : 0;
-}
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index b9c0f7a..d614933 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -49,6 +49,7 @@
 #include "hevc.h"
 #include "rtpenc.h"
 #include "mov_chan.h"
+#include "vpcc.h"
 
 static const AVOption options[] = {
     { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
@@ -69,6 +70,7 @@ static const AVOption options[] = {
     { "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     { "write_colr", "Write colr atom (Experimental, may be renamed or changed, do not use from scripts)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_COLR}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+    { "use_metadata_tags", "Use mdta atom for metadata.", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
     { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
     { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
@@ -83,9 +85,9 @@ static const AVOption options[] = {
     { "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext, fragments), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
     { "mov_gamma", "gamma value for gama atom", offsetof(MOVMuxContext, gamma), AV_OPT_TYPE_FLOAT, {.dbl = 0.0 }, 0.0, 10, AV_OPT_FLAG_ENCODING_PARAM},
     { "frag_interleave", "Interleave samples within fragments (max number of consecutive samples, lower is tighter interleaving, but with more overhead)", offsetof(MOVMuxContext, frag_interleave), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
-    { "encryption_scheme",    "Configures the encryption scheme, allowed values are none, cenc-aes-ctr", offsetof(MOVMuxContext, encryption_scheme_str),   AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
-    { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
-    { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM, .unit = "movflags" },
+    { "encryption_scheme",    "Configures the encryption scheme, allowed values are none, cenc-aes-ctr", offsetof(MOVMuxContext, encryption_scheme_str),   AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
+    { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
+    { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM },
     { NULL },
 };
 
@@ -370,7 +372,7 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track)
 
             if (hdr->substreamid == info->num_ind_sub + 1) {
                 //info->num_ind_sub++;
-                avpriv_request_sample(track->enc, "Multiple independent substreams");
+                avpriv_request_sample(track->par, "Multiple independent substreams");
                 return AVERROR_PATCHWELCOME;
             } else if (hdr->substreamid < info->num_ind_sub ||
                        hdr->substreamid == 0 && info->substream[0].bsid) {
@@ -513,8 +515,8 @@ end:
  */
 static int mov_write_extradata_tag(AVIOContext *pb, MOVTrack *track)
 {
-    avio_write(pb, track->enc->extradata, track->enc->extradata_size);
-    return track->enc->extradata_size;
+    avio_write(pb, track->par->extradata, track->par->extradata_size);
+    return track->par->extradata_size;
 }
 
 static int mov_write_enda_tag(AVIOContext *pb)
@@ -573,18 +575,18 @@ static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
     put_descr(pb, 0x04, 13 + decoder_specific_info_len);
 
     // Object type indication
-    if ((track->enc->codec_id == AV_CODEC_ID_MP2 ||
-         track->enc->codec_id == AV_CODEC_ID_MP3) &&
-        track->enc->sample_rate > 24000)
+    if ((track->par->codec_id == AV_CODEC_ID_MP2 ||
+         track->par->codec_id == AV_CODEC_ID_MP3) &&
+        track->par->sample_rate > 24000)
         avio_w8(pb, 0x6B); // 11172-3
     else
-        avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id));
+        avio_w8(pb, ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id));
 
     // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio)
     // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved)
-    if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
+    if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
         avio_w8(pb, (0x38 << 2) | 1); // flags (= NeroSubpicStream)
-    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
+    else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
         avio_w8(pb, 0x15); // flags (= Audiostream)
     else
         avio_w8(pb, 0x11); // flags (= Visualstream)
@@ -595,7 +597,7 @@ static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
     avio_wb24(pb, props ? props->buffer_size / 8 : 0); // Buffersize DB
 
     avg_bitrate = compute_avg_bitrate(track);
-    avio_wb32(pb, props ? FFMAX3(props->max_bitrate, props->avg_bitrate, avg_bitrate) : FFMAX(track->enc->bit_rate, avg_bitrate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
+    avio_wb32(pb, props ? FFMAX3(props->max_bitrate, props->avg_bitrate, avg_bitrate) : FFMAX(track->par->bit_rate, avg_bitrate)); // maxbitrate (FIXME should be max rate in any 1 sec window)
     avio_wb32(pb, avg_bitrate);
 
     if (track->vos_len) {
@@ -626,39 +628,39 @@ static int mov_pcm_be_gt16(enum AVCodecID codec_id)
            codec_id == AV_CODEC_ID_PCM_F64BE;
 }
 
-static int mov_write_ms_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_ms_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
 {
     int ret;
     int64_t pos = avio_tell(pb);
     avio_wb32(pb, 0);
     avio_wl32(pb, track->tag); // store it byteswapped
-    track->enc->codec_tag = av_bswap16(track->tag >> 16);
-    if ((ret = ff_put_wav_header(pb, track->enc, 0)) < 0)
+    track->par->codec_tag = av_bswap16(track->tag >> 16);
+    if ((ret = ff_put_wav_header(s, pb, track->par, 0)) < 0)
         return ret;
     return update_size(pb, pos);
 }
 
-static int mov_write_wfex_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_wfex_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
 {
     int ret;
     int64_t pos = avio_tell(pb);
     avio_wb32(pb, 0);
     ffio_wfourcc(pb, "wfex");
-    if ((ret = ff_put_wav_header(pb, track->enc, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0)
+    if ((ret = ff_put_wav_header(s, pb, track->st->codecpar, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX)) < 0)
         return ret;
     return update_size(pb, pos);
 }
 
-static int mov_write_chan_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
 {
     uint32_t layout_tag, bitmap;
     int64_t pos = avio_tell(pb);
 
-    layout_tag = ff_mov_get_channel_layout_tag(track->enc->codec_id,
-                                               track->enc->channel_layout,
+    layout_tag = ff_mov_get_channel_layout_tag(track->par->codec_id,
+                                               track->par->channel_layout,
                                                &bitmap);
     if (!layout_tag) {
-        av_log(track->enc, AV_LOG_WARNING, "not writing 'chan' tag due to "
+        av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to "
                "lack of channel information\n");
         return 0;
     }
@@ -677,41 +679,41 @@ static int mov_write_chan_tag(AVIOContext *pb, MOVTrack *track)
     return update_size(pb, pos);
 }
 
-static int mov_write_wave_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_wave_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
 
     avio_wb32(pb, 0);     /* size */
     ffio_wfourcc(pb, "wave");
 
-    if (track->enc->codec_id != AV_CODEC_ID_QDM2) {
+    if (track->par->codec_id != AV_CODEC_ID_QDM2) {
     avio_wb32(pb, 12);    /* size */
     ffio_wfourcc(pb, "frma");
     avio_wl32(pb, track->tag);
     }
 
-    if (track->enc->codec_id == AV_CODEC_ID_AAC) {
+    if (track->par->codec_id == AV_CODEC_ID_AAC) {
         /* useless atom needed by mplayer, ipod, not needed by quicktime */
         avio_wb32(pb, 12); /* size */
         ffio_wfourcc(pb, "mp4a");
         avio_wb32(pb, 0);
         mov_write_esds_tag(pb, track);
-    } else if (mov_pcm_le_gt16(track->enc->codec_id))  {
+    } else if (mov_pcm_le_gt16(track->par->codec_id))  {
       mov_write_enda_tag(pb);
-    } else if (mov_pcm_be_gt16(track->enc->codec_id))  {
+    } else if (mov_pcm_be_gt16(track->par->codec_id))  {
       mov_write_enda_tag_be(pb);
-    } else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB) {
+    } else if (track->par->codec_id == AV_CODEC_ID_AMR_NB) {
         mov_write_amr_tag(pb, track);
-    } else if (track->enc->codec_id == AV_CODEC_ID_AC3) {
+    } else if (track->par->codec_id == AV_CODEC_ID_AC3) {
         mov_write_ac3_tag(pb, track);
-    } else if (track->enc->codec_id == AV_CODEC_ID_EAC3) {
+    } else if (track->par->codec_id == AV_CODEC_ID_EAC3) {
         mov_write_eac3_tag(pb, track);
-    } else if (track->enc->codec_id == AV_CODEC_ID_ALAC ||
-               track->enc->codec_id == AV_CODEC_ID_QDM2) {
+    } else if (track->par->codec_id == AV_CODEC_ID_ALAC ||
+               track->par->codec_id == AV_CODEC_ID_QDM2) {
         mov_write_extradata_tag(pb, track);
-    } else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
-               track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
-        mov_write_ms_tag(pb, track);
+    } else if (track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
+               track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
+        mov_write_ms_tag(s, pb, track);
     }
 
     avio_wb32(pb, 8);     /* size */
@@ -880,7 +882,7 @@ static int get_samples_per_packet(MOVTrack *track)
 {
     int i, first_duration;
 
-// return track->enc->frame_size;
+// return track->par->frame_size;
 
     /* use 1 for raw PCM */
     if (!track->audio_vbr)
@@ -897,7 +899,7 @@ static int get_samples_per_packet(MOVTrack *track)
     return first_duration;
 }
 
-static int mov_write_audio_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
+static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
     int version = 0;
@@ -905,14 +907,14 @@ static int mov_write_audio_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr
 
     if (track->mode == MODE_MOV) {
         if (track->timescale > UINT16_MAX) {
-            if (mov_get_lpcm_flags(track->enc->codec_id))
+            if (mov_get_lpcm_flags(track->par->codec_id))
                 tag = AV_RL32("lpcm");
             version = 2;
-        } else if (track->audio_vbr || mov_pcm_le_gt16(track->enc->codec_id) ||
-                   mov_pcm_be_gt16(track->enc->codec_id) ||
-                   track->enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
-                   track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
-                   track->enc->codec_id == AV_CODEC_ID_QDM2) {
+        } else if (track->audio_vbr || mov_pcm_le_gt16(track->par->codec_id) ||
+                   mov_pcm_be_gt16(track->par->codec_id) ||
+                   track->par->codec_id == AV_CODEC_ID_ADPCM_MS ||
+                   track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
+                   track->par->codec_id == AV_CODEC_ID_QDM2) {
             version = 1;
         }
     }
@@ -939,21 +941,21 @@ static int mov_write_audio_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr
         avio_wb16(pb, 0);
         avio_wb32(pb, 0x00010000);
         avio_wb32(pb, 72);
-        avio_wb64(pb, av_double2int(track->enc->sample_rate));
-        avio_wb32(pb, track->enc->channels);
+        avio_wb64(pb, av_double2int(track->par->sample_rate));
+        avio_wb32(pb, track->par->channels);
         avio_wb32(pb, 0x7F000000);
-        avio_wb32(pb, av_get_bits_per_sample(track->enc->codec_id));
-        avio_wb32(pb, mov_get_lpcm_flags(track->enc->codec_id));
+        avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id));
+        avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id));
         avio_wb32(pb, track->sample_size);
         avio_wb32(pb, get_samples_per_packet(track));
     } else {
         if (track->mode == MODE_MOV) {
-            avio_wb16(pb, track->enc->channels);
-            if (track->enc->codec_id == AV_CODEC_ID_PCM_U8 ||
-                track->enc->codec_id == AV_CODEC_ID_PCM_S8)
+            avio_wb16(pb, track->par->channels);
+            if (track->par->codec_id == AV_CODEC_ID_PCM_U8 ||
+                track->par->codec_id == AV_CODEC_ID_PCM_S8)
                 avio_wb16(pb, 8); /* bits per sample */
-            else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_G726)
-                avio_wb16(pb, track->enc->bits_per_coded_sample);
+            else if (track->par->codec_id == AV_CODEC_ID_ADPCM_G726)
+                avio_wb16(pb, track->par->bits_per_coded_sample);
             else
                 avio_wb16(pb, 16);
             avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
@@ -964,51 +966,51 @@ static int mov_write_audio_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr
         }
 
         avio_wb16(pb, 0); /* packet size (= 0) */
-        avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ?
-                      track->enc->sample_rate : 0);
+        avio_wb16(pb, track->par->sample_rate <= UINT16_MAX ?
+                      track->par->sample_rate : 0);
         avio_wb16(pb, 0); /* Reserved */
     }
 
     if (version == 1) { /* SoundDescription V1 extended info */
-        if (mov_pcm_le_gt16(track->enc->codec_id) ||
-            mov_pcm_be_gt16(track->enc->codec_id))
+        if (mov_pcm_le_gt16(track->par->codec_id) ||
+            mov_pcm_be_gt16(track->par->codec_id))
             avio_wb32(pb, 1); /*  must be 1 for  uncompressed formats */
         else
-            avio_wb32(pb, track->enc->frame_size); /* Samples per packet */
-        avio_wb32(pb, track->sample_size / track->enc->channels); /* Bytes per packet */
+            avio_wb32(pb, track->par->frame_size); /* Samples per packet */
+        avio_wb32(pb, track->sample_size / track->par->channels); /* Bytes per packet */
         avio_wb32(pb, track->sample_size); /* Bytes per frame */
         avio_wb32(pb, 2); /* Bytes per sample */
     }
 
     if (track->mode == MODE_MOV &&
-        (track->enc->codec_id == AV_CODEC_ID_AAC           ||
-         track->enc->codec_id == AV_CODEC_ID_AC3           ||
-         track->enc->codec_id == AV_CODEC_ID_EAC3          ||
-         track->enc->codec_id == AV_CODEC_ID_AMR_NB        ||
-         track->enc->codec_id == AV_CODEC_ID_ALAC          ||
-         track->enc->codec_id == AV_CODEC_ID_ADPCM_MS      ||
-         track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
-         track->enc->codec_id == AV_CODEC_ID_QDM2          ||
-         (mov_pcm_le_gt16(track->enc->codec_id) && version==1) ||
-         (mov_pcm_be_gt16(track->enc->codec_id) && version==1)))
-        mov_write_wave_tag(pb, track);
+        (track->par->codec_id == AV_CODEC_ID_AAC           ||
+         track->par->codec_id == AV_CODEC_ID_AC3           ||
+         track->par->codec_id == AV_CODEC_ID_EAC3          ||
+         track->par->codec_id == AV_CODEC_ID_AMR_NB        ||
+         track->par->codec_id == AV_CODEC_ID_ALAC          ||
+         track->par->codec_id == AV_CODEC_ID_ADPCM_MS      ||
+         track->par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
+         track->par->codec_id == AV_CODEC_ID_QDM2          ||
+         (mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
+         (mov_pcm_be_gt16(track->par->codec_id) && version==1)))
+        mov_write_wave_tag(s, pb, track);
     else if (track->tag == MKTAG('m','p','4','a'))
         mov_write_esds_tag(pb, track);
-    else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB)
+    else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
         mov_write_amr_tag(pb, track);
-    else if (track->enc->codec_id == AV_CODEC_ID_AC3)
+    else if (track->par->codec_id == AV_CODEC_ID_AC3)
         mov_write_ac3_tag(pb, track);
-    else if (track->enc->codec_id == AV_CODEC_ID_EAC3)
+    else if (track->par->codec_id == AV_CODEC_ID_EAC3)
         mov_write_eac3_tag(pb, track);
-    else if (track->enc->codec_id == AV_CODEC_ID_ALAC)
+    else if (track->par->codec_id == AV_CODEC_ID_ALAC)
         mov_write_extradata_tag(pb, track);
-    else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO)
-        mov_write_wfex_tag(pb, track);
+    else if (track->par->codec_id == AV_CODEC_ID_WMAPRO)
+        mov_write_wfex_tag(s, pb, track);
     else if (track->vos_len > 0)
         mov_write_glbl_tag(pb, track);
 
-    if (track->mode == MODE_MOV && track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
-        mov_write_chan_tag(pb, track);
+    if (track->mode == MODE_MOV && track->par->codec_type == AVMEDIA_TYPE_AUDIO)
+        mov_write_chan_tag(s, pb, track);
 
     if (mov->encryption_scheme != MOV_ENC_NONE) {
         ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid);
@@ -1039,6 +1041,17 @@ static int mov_write_avcc_tag(AVIOContext *pb, MOVTrack *track)
     return update_size(pb, pos);
 }
 
+static int mov_write_vpcc_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
+{
+    int64_t pos = avio_tell(pb);
+
+    avio_wb32(pb, 0);
+    ffio_wfourcc(pb, "vpcC");
+    avio_wb32(pb, 0); /* version & flags */
+    ff_isom_write_vpcc(s, pb, track->par);
+    return update_size(pb, pos);
+}
+
 static int mov_write_hvcc_tag(AVIOContext *pb, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
@@ -1078,8 +1091,8 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
     ffio_wfourcc(pb, "ACLR");
     ffio_wfourcc(pb, "ACLR");
     ffio_wfourcc(pb, "0001");
-    if (track->enc->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
-        track->enc->color_range == AVCOL_RANGE_UNSPECIFIED) {
+    if (track->par->color_range == AVCOL_RANGE_MPEG || /* Legal range (16-235) */
+        track->par->color_range == AVCOL_RANGE_UNSPECIFIED) {
         avio_wb32(pb, 1); /* Corresponds to 709 in official encoder */
     } else { /* Full range (0-255) */
         avio_wb32(pb, 2); /* Corresponds to RGB in official encoder */
@@ -1098,18 +1111,18 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track)
     ffio_wfourcc(pb, "ARES");
     ffio_wfourcc(pb, "0001");
     avio_wb32(pb, cid); /* dnxhd cid, some id ? */
-    avio_wb32(pb, track->enc->width);
+    avio_wb32(pb, track->par->width);
     /* values below are based on samples created with quicktime and avid codecs */
     if (interlaced) {
-        avio_wb32(pb, track->enc->height / 2);
+        avio_wb32(pb, track->par->height / 2);
         avio_wb32(pb, 2); /* unknown */
         avio_wb32(pb, 0); /* unknown */
         avio_wb32(pb, 4); /* unknown */
     } else {
-        avio_wb32(pb, track->enc->height);
+        avio_wb32(pb, track->par->height);
         avio_wb32(pb, 1); /* unknown */
         avio_wb32(pb, 0); /* unknown */
-        if (track->enc->height == 1080)
+        if (track->par->height == 1080)
             avio_wb32(pb, 5); /* unknown */
         else
             avio_wb32(pb, 6); /* unknown */
@@ -1125,9 +1138,9 @@ static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
 {
     avio_wb32(pb, 12);
     ffio_wfourcc(pb, "DpxE");
-    if (track->enc->extradata_size >= 12 &&
-        !memcmp(&track->enc->extradata[4], "DpxE", 4)) {
-        avio_wb32(pb, track->enc->extradata[11]);
+    if (track->par->extradata_size >= 12 &&
+        !memcmp(&track->par->extradata[4], "DpxE", 4)) {
+        avio_wb32(pb, track->par->extradata[11]);
     } else {
         avio_wb32(pb, 1);
     }
@@ -1136,21 +1149,22 @@ static int mov_write_dpxe_tag(AVIOContext *pb, MOVTrack *track)
 
 static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
 {
-    int tag = track->enc->codec_tag;
+    int tag = track->par->codec_tag;
 
-    if (!ff_codec_get_tag(ff_mp4_obj_type, track->enc->codec_id))
+    if (!ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id))
         return 0;
 
-    if      (track->enc->codec_id == AV_CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
-    else if (track->enc->codec_id == AV_CODEC_ID_HEVC)      tag = MKTAG('h','e','v','1');
-    else if (track->enc->codec_id == AV_CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
-    else if (track->enc->codec_id == AV_CODEC_ID_EAC3)      tag = MKTAG('e','c','-','3');
-    else if (track->enc->codec_id == AV_CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
-    else if (track->enc->codec_id == AV_CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
-    else if (track->enc->codec_id == AV_CODEC_ID_VC1)       tag = MKTAG('v','c','-','1');
-    else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)  tag = MKTAG('m','p','4','v');
-    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)  tag = MKTAG('m','p','4','a');
-    else if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE)  tag = MKTAG('m','p','4','s');
+    if      (track->par->codec_id == AV_CODEC_ID_H264)      tag = MKTAG('a','v','c','1');
+    else if (track->par->codec_id == AV_CODEC_ID_HEVC)      tag = MKTAG('h','e','v','1');
+    else if (track->par->codec_id == AV_CODEC_ID_VP9)       tag = MKTAG('v','p','0','9');
+    else if (track->par->codec_id == AV_CODEC_ID_AC3)       tag = MKTAG('a','c','-','3');
+    else if (track->par->codec_id == AV_CODEC_ID_EAC3)      tag = MKTAG('e','c','-','3');
+    else if (track->par->codec_id == AV_CODEC_ID_DIRAC)     tag = MKTAG('d','r','a','c');
+    else if (track->par->codec_id == AV_CODEC_ID_MOV_TEXT)  tag = MKTAG('t','x','3','g');
+    else if (track->par->codec_id == AV_CODEC_ID_VC1)       tag = MKTAG('v','c','-','1');
+    else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)  tag = MKTAG('m','p','4','v');
+    else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)  tag = MKTAG('m','p','4','a');
+    else if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)  tag = MKTAG('m','p','4','s');
 
     return tag;
 }
@@ -1168,13 +1182,13 @@ static const AVCodecTag codec_ipod_tags[] = {
 
 static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track)
 {
-    int tag = track->enc->codec_tag;
+    int tag = track->par->codec_tag;
 
     // keep original tag for subs, ipod supports both formats
-    if (!(track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE &&
+    if (!(track->par->codec_type == AVMEDIA_TYPE_SUBTITLE &&
           (tag == MKTAG('t', 'x', '3', 'g') ||
            tag == MKTAG('t', 'e', 'x', 't'))))
-        tag = ff_codec_get_tag(codec_ipod_tags, track->enc->codec_id);
+        tag = ff_codec_get_tag(codec_ipod_tags, track->par->codec_id);
 
     if (!av_match_ext(s->filename, "m4a") &&
         !av_match_ext(s->filename, "m4b") &&
@@ -1189,17 +1203,17 @@ static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
 {
     int tag;
 
-    if (track->enc->width == 720) { /* SD */
-        if (track->enc->height == 480) { /* NTSC */
-            if  (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
+    if (track->par->width == 720) { /* SD */
+        if (track->par->height == 480) { /* NTSC */
+            if  (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n');
             else                                            tag = MKTAG('d','v','c',' ');
-       }else if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
-        else if (track->enc->pix_fmt == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
+       }else if (track->par->format == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p');
+        else if (track->par->format == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p');
         else                                                tag = MKTAG('d','v','p','p');
-    } else if (track->enc->height == 720) { /* HD 720 line */
+    } else if (track->par->height == 720) { /* HD 720 line */
         if  (track->st->time_base.den == 50)                tag = MKTAG('d','v','h','q');
         else                                                tag = MKTAG('d','v','h','p');
-    } else if (track->enc->height == 1080) { /* HD 1080 line */
+    } else if (track->par->height == 1080) { /* HD 1080 line */
         if  (track->st->time_base.den == 25)                tag = MKTAG('d','v','h','5');
         else                                                tag = MKTAG('d','v','h','6');
     } else {
@@ -1212,29 +1226,34 @@ static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
 
 static AVRational find_fps(AVFormatContext *s, AVStream *st)
 {
-    AVRational rate = {st->codec->time_base.den, st->codec->time_base.num};
-    /* if the codec time base makes no sense, try to fallback on stream frame rate */
+    AVRational rate = st->avg_frame_rate;
+
+#if FF_API_LAVF_AVCTX
+    FF_DISABLE_DEPRECATION_WARNINGS
+    rate = av_inv_q(st->codec->time_base);
     if (av_timecode_check_frame_rate(rate) < 0) {
         av_log(s, AV_LOG_DEBUG, "timecode: tbc=%d/%d invalid, fallback on %d/%d\n",
                rate.num, rate.den, st->avg_frame_rate.num, st->avg_frame_rate.den);
         rate = st->avg_frame_rate;
     }
+    FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     return rate;
 }
 
 static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
 {
-    int tag = track->enc->codec_tag;
-    int interlaced = track->enc->field_order > AV_FIELD_PROGRESSIVE;
+    int tag = track->par->codec_tag;
+    int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
     AVStream *st = track->st;
     int rate = av_q2d(find_fps(s, st));
 
     if (!tag)
         tag = MKTAG('m', '2', 'v', '1'); //fallback tag
 
-    if (track->enc->pix_fmt == AV_PIX_FMT_YUV420P) {
-        if (track->enc->width == 1280 && track->enc->height == 720) {
+    if (track->par->format == AV_PIX_FMT_YUV420P) {
+        if (track->par->width == 1280 && track->par->height == 720) {
             if (!interlaced) {
                 if      (rate == 24) tag = MKTAG('x','d','v','4');
                 else if (rate == 25) tag = MKTAG('x','d','v','5');
@@ -1242,7 +1261,7 @@ static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
                 else if (rate == 50) tag = MKTAG('x','d','v','a');
                 else if (rate == 60) tag = MKTAG('x','d','v','9');
             }
-        } else if (track->enc->width == 1440 && track->enc->height == 1080) {
+        } else if (track->par->width == 1440 && track->par->height == 1080) {
             if (!interlaced) {
                 if      (rate == 24) tag = MKTAG('x','d','v','6');
                 else if (rate == 25) tag = MKTAG('x','d','v','7');
@@ -1251,7 +1270,7 @@ static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
                 if      (rate == 25) tag = MKTAG('x','d','v','3');
                 else if (rate == 30) tag = MKTAG('x','d','v','2');
             }
-        } else if (track->enc->width == 1920 && track->enc->height == 1080) {
+        } else if (track->par->width == 1920 && track->par->height == 1080) {
             if (!interlaced) {
                 if      (rate == 24) tag = MKTAG('x','d','v','d');
                 else if (rate == 25) tag = MKTAG('x','d','v','e');
@@ -1261,8 +1280,8 @@ static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
                 else if (rate == 30) tag = MKTAG('x','d','v','b');
             }
         }
-    } else if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) {
-        if (track->enc->width == 1280 && track->enc->height == 720) {
+    } else if (track->par->format == AV_PIX_FMT_YUV422P) {
+        if (track->par->width == 1280 && track->par->height == 720) {
             if (!interlaced) {
                 if      (rate == 24) tag = MKTAG('x','d','5','4');
                 else if (rate == 25) tag = MKTAG('x','d','5','5');
@@ -1270,7 +1289,7 @@ static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
                 else if (rate == 50) tag = MKTAG('x','d','5','a');
                 else if (rate == 60) tag = MKTAG('x','d','5','9');
             }
-        } else if (track->enc->width == 1920 && track->enc->height == 1080) {
+        } else if (track->par->width == 1920 && track->par->height == 1080) {
             if (!interlaced) {
                 if      (rate == 24) tag = MKTAG('x','d','5','d');
                 else if (rate == 25) tag = MKTAG('x','d','5','e');
@@ -1287,16 +1306,16 @@ static int mov_get_mpeg2_xdcam_codec_tag(AVFormatContext *s, MOVTrack *track)
 
 static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
 {
-    int tag = track->enc->codec_tag;
-    int interlaced = track->enc->field_order > AV_FIELD_PROGRESSIVE;
+    int tag = track->par->codec_tag;
+    int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
     AVStream *st = track->st;
     int rate = av_q2d(find_fps(s, st));
 
     if (!tag)
         tag = MKTAG('a', 'v', 'c', 'i'); //fallback tag
 
-    if (track->enc->pix_fmt == AV_PIX_FMT_YUV420P10) {
-        if (track->enc->width == 960 && track->enc->height == 720) {
+    if (track->par->format == AV_PIX_FMT_YUV420P10) {
+        if (track->par->width == 960 && track->par->height == 720) {
             if (!interlaced) {
                 if      (rate == 24) tag = MKTAG('a','i','5','p');
                 else if (rate == 25) tag = MKTAG('a','i','5','q');
@@ -1304,7 +1323,7 @@ static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
                 else if (rate == 50) tag = MKTAG('a','i','5','q');
                 else if (rate == 60) tag = MKTAG('a','i','5','p');
             }
-        } else if (track->enc->width == 1440 && track->enc->height == 1080) {
+        } else if (track->par->width == 1440 && track->par->height == 1080) {
             if (!interlaced) {
                 if      (rate == 24) tag = MKTAG('a','i','5','3');
                 else if (rate == 25) tag = MKTAG('a','i','5','2');
@@ -1314,8 +1333,8 @@ static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
                 else if (rate == 60) tag = MKTAG('a','i','5','6');
             }
         }
-    } else if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P10) {
-        if (track->enc->width == 1280 && track->enc->height == 720) {
+    } else if (track->par->format == AV_PIX_FMT_YUV422P10) {
+        if (track->par->width == 1280 && track->par->height == 720) {
             if (!interlaced) {
                 if      (rate == 24) tag = MKTAG('a','i','1','p');
                 else if (rate == 25) tag = MKTAG('a','i','1','q');
@@ -1323,7 +1342,7 @@ static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
                 else if (rate == 50) tag = MKTAG('a','i','1','q');
                 else if (rate == 60) tag = MKTAG('a','i','1','p');
             }
-        } else if (track->enc->width == 1920 && track->enc->height == 1080) {
+        } else if (track->par->width == 1920 && track->par->height == 1080) {
             if (!interlaced) {
                 if      (rate == 24) tag = MKTAG('a','i','1','3');
                 else if (rate == 25) tag = MKTAG('a','i','1','2');
@@ -1333,9 +1352,9 @@ static int mov_get_h264_codec_tag(AVFormatContext *s, MOVTrack *track)
                 else if (rate == 50) tag = MKTAG('a','i','1','5');
                 else if (rate == 60) tag = MKTAG('a','i','1','6');
             }
-        } else if (   track->enc->width == 4096 && track->enc->height == 2160
-                   || track->enc->width == 3840 && track->enc->height == 2160
-                   || track->enc->width == 2048 && track->enc->height == 1080) {
+        } else if (   track->par->width == 4096 && track->par->height == 2160
+                   || track->par->width == 3840 && track->par->height == 2160
+                   || track->par->width == 2048 && track->par->height == 1080) {
             tag = MKTAG('a','i','v','x');
         }
     }
@@ -1367,68 +1386,68 @@ static const struct {
 
 static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track)
 {
-    int tag = track->enc->codec_tag;
+    int tag = track->par->codec_tag;
     int i;
     enum AVPixelFormat pix_fmt;
 
     for (i = 0; i < FF_ARRAY_ELEMS(mov_pix_fmt_tags); i++) {
-        if (track->enc->pix_fmt == mov_pix_fmt_tags[i].pix_fmt) {
+        if (track->par->format == mov_pix_fmt_tags[i].pix_fmt) {
             tag = mov_pix_fmt_tags[i].tag;
-            track->enc->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
-            if (track->enc->codec_tag == mov_pix_fmt_tags[i].tag)
+            track->par->bits_per_coded_sample = mov_pix_fmt_tags[i].bps;
+            if (track->par->codec_tag == mov_pix_fmt_tags[i].tag)
                 break;
         }
     }
 
     pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov,
-                                  track->enc->bits_per_coded_sample);
+                                  track->par->bits_per_coded_sample);
     if (tag == MKTAG('r','a','w',' ') &&
-        track->enc->pix_fmt != pix_fmt &&
-        track->enc->pix_fmt != AV_PIX_FMT_NONE)
+        track->par->format != pix_fmt &&
+        track->par->format != AV_PIX_FMT_NONE)
         av_log(s, AV_LOG_ERROR, "%s rawvideo cannot be written to mov, output file will be unreadable\n",
-               av_get_pix_fmt_name(track->enc->pix_fmt));
+               av_get_pix_fmt_name(track->par->format));
     return tag;
 }
 
 static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track)
 {
-    int tag = track->enc->codec_tag;
+    int tag = track->par->codec_tag;
 
     if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
-                 (track->enc->codec_id == AV_CODEC_ID_DVVIDEO ||
-                  track->enc->codec_id == AV_CODEC_ID_RAWVIDEO ||
-                  track->enc->codec_id == AV_CODEC_ID_H263 ||
-                  track->enc->codec_id == AV_CODEC_ID_H264 ||
-                  track->enc->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
-                  av_get_bits_per_sample(track->enc->codec_id)))) { // pcm audio
-        if (track->enc->codec_id == AV_CODEC_ID_DVVIDEO)
+                 (track->par->codec_id == AV_CODEC_ID_DVVIDEO ||
+                  track->par->codec_id == AV_CODEC_ID_RAWVIDEO ||
+                  track->par->codec_id == AV_CODEC_ID_H263 ||
+                  track->par->codec_id == AV_CODEC_ID_H264 ||
+                  track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
+                  av_get_bits_per_sample(track->par->codec_id)))) { // pcm audio
+        if (track->par->codec_id == AV_CODEC_ID_DVVIDEO)
             tag = mov_get_dv_codec_tag(s, track);
-        else if (track->enc->codec_id == AV_CODEC_ID_RAWVIDEO)
+        else if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO)
             tag = mov_get_rawvideo_codec_tag(s, track);
-        else if (track->enc->codec_id == AV_CODEC_ID_MPEG2VIDEO)
+        else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO)
             tag = mov_get_mpeg2_xdcam_codec_tag(s, track);
-        else if (track->enc->codec_id == AV_CODEC_ID_H264)
+        else if (track->par->codec_id == AV_CODEC_ID_H264)
             tag = mov_get_h264_codec_tag(s, track);
-        else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
-            tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->enc->codec_id);
+        else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
+            tag = ff_codec_get_tag(ff_codec_movvideo_tags, track->par->codec_id);
             if (!tag) { // if no mac fcc found, try with Microsoft tags
-                tag = ff_codec_get_tag(ff_codec_bmp_tags, track->enc->codec_id);
+                tag = ff_codec_get_tag(ff_codec_bmp_tags, track->par->codec_id);
                 if (tag)
                     av_log(s, AV_LOG_WARNING, "Using MS style video codec tag, "
                            "the file may be unplayable!\n");
             }
-        } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
-            tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->enc->codec_id);
+        } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
+            tag = ff_codec_get_tag(ff_codec_movaudio_tags, track->par->codec_id);
             if (!tag) { // if no mac fcc found, try with Microsoft tags
-                int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->enc->codec_id);
+                int ms_tag = ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id);
                 if (ms_tag) {
                     tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff));
                     av_log(s, AV_LOG_WARNING, "Using MS style audio codec tag, "
                            "the file may be unplayable!\n");
                 }
             }
-        } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
-            tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->enc->codec_id);
+        } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
+            tag = ff_codec_get_tag(ff_codec_movsubtitle_tags, track->par->codec_id);
     }
 
     return tag;
@@ -1462,14 +1481,14 @@ static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
         tag = mp4_get_codec_tag(s, track);
     else if (track->mode == MODE_ISM) {
         tag = mp4_get_codec_tag(s, track);
-        if (!tag && track->enc->codec_id == AV_CODEC_ID_WMAPRO)
+        if (!tag && track->par->codec_id == AV_CODEC_ID_WMAPRO)
             tag = MKTAG('w', 'm', 'a', ' ');
     } else if (track->mode == MODE_IPOD)
         tag = ipod_get_codec_tag(s, track);
     else if (track->mode & MODE_3GP)
-        tag = ff_codec_get_tag(codec_3gp_tags, track->enc->codec_id);
+        tag = ff_codec_get_tag(codec_3gp_tags, track->par->codec_id);
     else if (track->mode == MODE_F4V)
-        tag = ff_codec_get_tag(codec_f4v_tags, track->enc->codec_id);
+        tag = ff_codec_get_tag(codec_f4v_tags, track->par->codec_id);
     else
         tag = mov_get_codec_tag(s, track);
 
@@ -1496,11 +1515,11 @@ static const uint16_t fiel_data[] = {
     0x0000, 0x0100, 0x0201, 0x0206, 0x0209, 0x020e
 };
 
-static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order)
 {
     unsigned mov_field_order = 0;
-    if (track->enc->field_order < FF_ARRAY_ELEMS(fiel_data))
-        mov_field_order = fiel_data[track->enc->field_order];
+    if (field_order < FF_ARRAY_ELEMS(fiel_data))
+        mov_field_order = fiel_data[field_order];
     else
         return 0;
     avio_wb32(pb, 10);
@@ -1518,10 +1537,10 @@ static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
     avio_wb16(pb, 0);    /* Reserved */
     avio_wb16(pb, 1);    /* Data-reference index */
 
-    if (track->enc->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
+    if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
         mov_write_esds_tag(pb, track);
-    else if (track->enc->extradata_size)
-        avio_write(pb, track->enc->extradata, track->enc->extradata_size);
+    else if (track->par->extradata_size)
+        avio_write(pb, track->par->extradata, track->par->extradata_size);
 
     return update_size(pb, pos);
 }
@@ -1529,8 +1548,8 @@ static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track)
 static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track)
 {
     AVRational sar;
-    av_reduce(&sar.num, &sar.den, track->enc->sample_aspect_ratio.num,
-              track->enc->sample_aspect_ratio.den, INT_MAX);
+    av_reduce(&sar.num, &sar.den, track->par->sample_aspect_ratio.num,
+              track->par->sample_aspect_ratio.den, INT_MAX);
 
     avio_wb32(pb, 16);
     ffio_wfourcc(pb, "pasp");
@@ -1544,7 +1563,7 @@ static int mov_write_gama_tag(AVIOContext *pb, MOVTrack *track, double gamma)
     uint32_t gama = 0;
     if (gamma <= 0.0)
     {
-        gamma = avpriv_get_gamma_from_trc(track->enc->color_trc);
+        gamma = avpriv_get_gamma_from_trc(track->par->color_trc);
     }
     av_log(pb, AV_LOG_DEBUG, "gamma value %g\n", gamma);
 
@@ -1569,32 +1588,32 @@ static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track)
     // Ref (MOV): https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG9
     // Ref (MP4): ISO/IEC 14496-12:2012
 
-    if (track->enc->color_primaries == AVCOL_PRI_UNSPECIFIED &&
-        track->enc->color_trc == AVCOL_TRC_UNSPECIFIED &&
-        track->enc->colorspace == AVCOL_SPC_UNSPECIFIED) {
-        if ((track->enc->width >= 1920 && track->enc->height >= 1080)
-          || (track->enc->width == 1280 && track->enc->height == 720)) {
+    if (track->par->color_primaries == AVCOL_PRI_UNSPECIFIED &&
+        track->par->color_trc == AVCOL_TRC_UNSPECIFIED &&
+        track->par->color_space == AVCOL_SPC_UNSPECIFIED) {
+        if ((track->par->width >= 1920 && track->par->height >= 1080)
+          || (track->par->width == 1280 && track->par->height == 720)) {
             av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt709\n");
-            track->enc->color_primaries = AVCOL_PRI_BT709;
-        } else if (track->enc->width == 720 && track->height == 576) {
+            track->par->color_primaries = AVCOL_PRI_BT709;
+        } else if (track->par->width == 720 && track->height == 576) {
             av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming bt470bg\n");
-            track->enc->color_primaries = AVCOL_PRI_BT470BG;
-        } else if (track->enc->width == 720 &&
+            track->par->color_primaries = AVCOL_PRI_BT470BG;
+        } else if (track->par->width == 720 &&
                    (track->height == 486 || track->height == 480)) {
             av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, assuming smpte170\n");
-            track->enc->color_primaries = AVCOL_PRI_SMPTE170M;
+            track->par->color_primaries = AVCOL_PRI_SMPTE170M;
         } else {
             av_log(NULL, AV_LOG_WARNING, "color primaries unspecified, unable to assume anything\n");
         }
-        switch (track->enc->color_primaries) {
+        switch (track->par->color_primaries) {
         case AVCOL_PRI_BT709:
-            track->enc->color_trc = AVCOL_TRC_BT709;
-            track->enc->colorspace = AVCOL_SPC_BT709;
+            track->par->color_trc = AVCOL_TRC_BT709;
+            track->par->color_space = AVCOL_SPC_BT709;
             break;
         case AVCOL_PRI_SMPTE170M:
         case AVCOL_PRI_BT470BG:
-            track->enc->color_trc = AVCOL_TRC_BT709;
-            track->enc->colorspace = AVCOL_SPC_SMPTE170M;
+            track->par->color_trc = AVCOL_TRC_BT709;
+            track->par->color_space = AVCOL_SPC_SMPTE170M;
             break;
         }
     }
@@ -1608,20 +1627,20 @@ static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track)
         ffio_wfourcc(pb, "nclx");
     else
         ffio_wfourcc(pb, "nclc");
-    switch (track->enc->color_primaries) {
+    switch (track->par->color_primaries) {
     case AVCOL_PRI_BT709:     avio_wb16(pb, 1); break;
     case AVCOL_PRI_SMPTE170M:
     case AVCOL_PRI_SMPTE240M: avio_wb16(pb, 6); break;
     case AVCOL_PRI_BT470BG:   avio_wb16(pb, 5); break;
     default:                  avio_wb16(pb, 2);
     }
-    switch (track->enc->color_trc) {
+    switch (track->par->color_trc) {
     case AVCOL_TRC_BT709:     avio_wb16(pb, 1); break;
     case AVCOL_TRC_SMPTE170M: avio_wb16(pb, 1); break; // remapped
     case AVCOL_TRC_SMPTE240M: avio_wb16(pb, 7); break;
     default:                  avio_wb16(pb, 2);
     }
-    switch (track->enc->colorspace) {
+    switch (track->par->color_space) {
     case AVCOL_SPC_BT709:     avio_wb16(pb, 1); break;
     case AVCOL_SPC_BT470BG:
     case AVCOL_SPC_SMPTE170M: avio_wb16(pb, 6); break;
@@ -1630,7 +1649,7 @@ static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track)
     }
 
     if (track->mode == MODE_MP4) {
-        int full_range = track->enc->color_range == AVCOL_RANGE_JPEG;
+        int full_range = track->par->color_range == AVCOL_RANGE_JPEG;
         avio_w8(pb, full_range << 7);
         return 19;
     } else {
@@ -1641,26 +1660,26 @@ static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track)
 static void find_compressor(char * compressor_name, int len, MOVTrack *track)
 {
     AVDictionaryEntry *encoder;
-    int xdcam_res =  (track->enc->width == 1280 && track->enc->height == 720)
-                  || (track->enc->width == 1440 && track->enc->height == 1080)
-                  || (track->enc->width == 1920 && track->enc->height == 1080);
+    int xdcam_res =  (track->par->width == 1280 && track->par->height == 720)
+                  || (track->par->width == 1440 && track->par->height == 1080)
+                  || (track->par->width == 1920 && track->par->height == 1080);
 
     if (track->mode == MODE_MOV &&
         (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) {
         av_strlcpy(compressor_name, encoder->value, 32);
-    } else if (track->enc->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) {
-        int interlaced = track->enc->field_order > AV_FIELD_PROGRESSIVE;
+    } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) {
+        int interlaced = track->par->field_order > AV_FIELD_PROGRESSIVE;
         AVStream *st = track->st;
         int rate = av_q2d(find_fps(NULL, st));
         av_strlcatf(compressor_name, len, "XDCAM");
-        if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) {
+        if (track->par->format == AV_PIX_FMT_YUV422P) {
             av_strlcatf(compressor_name, len, " HD422");
-        } else if(track->enc->width == 1440) {
+        } else if(track->par->width == 1440) {
             av_strlcatf(compressor_name, len, " HD");
         } else
             av_strlcatf(compressor_name, len, " EX");
 
-        av_strlcatf(compressor_name, len, " %d%c", track->enc->height, interlaced ? 'i' : 'p');
+        av_strlcatf(compressor_name, len, " %d%c", track->par->height, interlaced ? 'i' : 'p');
 
         av_strlcatf(compressor_name, len, "%d", rate * (interlaced + 1));
     }
@@ -1686,7 +1705,7 @@ static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr
     avio_wb16(pb, 0); /* Codec stream revision (=0) */
     if (track->mode == MODE_MOV) {
         ffio_wfourcc(pb, "FFMP"); /* Vendor */
-        if (track->enc->codec_id == AV_CODEC_ID_RAWVIDEO) {
+        if (track->par->codec_id == AV_CODEC_ID_RAWVIDEO) {
             avio_wb32(pb, 0); /* Temporal Quality */
             avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/
         } else {
@@ -1698,7 +1717,7 @@ static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr
         avio_wb32(pb, 0); /* Reserved */
         avio_wb32(pb, 0); /* Reserved */
     }
-    avio_wb16(pb, track->enc->width); /* Video width */
+    avio_wb16(pb, track->par->width); /* Video width */
     avio_wb16(pb, track->height); /* Video height */
     avio_wb32(pb, 0x00480000); /* Horizontal resolution 72dpi */
     avio_wb32(pb, 0x00480000); /* Vertical resolution 72dpi */
@@ -1710,45 +1729,78 @@ static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr
     avio_w8(pb, strlen(compressor_name));
     avio_write(pb, compressor_name, 31);
 
-    if (track->mode == MODE_MOV && track->enc->bits_per_coded_sample)
-        avio_wb16(pb, track->enc->bits_per_coded_sample);
+    if (track->mode == MODE_MOV && track->par->bits_per_coded_sample)
+        avio_wb16(pb, track->par->bits_per_coded_sample |
+                  (track->par->format == AV_PIX_FMT_GRAY8 ? 0x20 : 0));
     else
         avio_wb16(pb, 0x18); /* Reserved */
-    avio_wb16(pb, 0xffff); /* Reserved */
+
+    if (track->mode == MODE_MOV && track->par->format == AV_PIX_FMT_PAL8) {
+        int pal_size = 1 << track->par->bits_per_coded_sample;
+        int i;
+        avio_wb16(pb, 0);             /* Color table ID */
+        avio_wb32(pb, 0);             /* Color table seed */
+        avio_wb16(pb, 0x8000);        /* Color table flags */
+        avio_wb16(pb, pal_size - 1);  /* Color table size (zero-relative) */
+        for (i = 0; i < pal_size; i++) {
+            uint32_t rgb = track->palette[i];
+            uint16_t r = (rgb >> 16) & 0xff;
+            uint16_t g = (rgb >> 8)  & 0xff;
+            uint16_t b = rgb         & 0xff;
+            avio_wb16(pb, 0);
+            avio_wb16(pb, (r << 8) | r);
+            avio_wb16(pb, (g << 8) | g);
+            avio_wb16(pb, (b << 8) | b);
+        }
+    } else
+        avio_wb16(pb, 0xffff); /* Reserved */
+
     if (track->tag == MKTAG('m','p','4','v'))
         mov_write_esds_tag(pb, track);
-    else if (track->enc->codec_id == AV_CODEC_ID_H263)
+    else if (track->par->codec_id == AV_CODEC_ID_H263)
         mov_write_d263_tag(pb);
-    else if (track->enc->codec_id == AV_CODEC_ID_AVUI ||
-            track->enc->codec_id == AV_CODEC_ID_SVQ3) {
+    else if (track->par->codec_id == AV_CODEC_ID_AVUI ||
+            track->par->codec_id == AV_CODEC_ID_SVQ3) {
         mov_write_extradata_tag(pb, track);
         avio_wb32(pb, 0);
-    } else if (track->enc->codec_id == AV_CODEC_ID_DNXHD) {
+    } else if (track->par->codec_id == AV_CODEC_ID_DNXHD) {
         mov_write_avid_tag(pb, track);
         avid = 1;
-    } else if (track->enc->codec_id == AV_CODEC_ID_HEVC)
+    } else if (track->par->codec_id == AV_CODEC_ID_HEVC)
         mov_write_hvcc_tag(pb, track);
-    else if (track->enc->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
+    else if (track->par->codec_id == AV_CODEC_ID_H264 && !TAG_IS_AVCI(track->tag)) {
         mov_write_avcc_tag(pb, track);
         if (track->mode == MODE_IPOD)
             mov_write_uuid_tag_ipod(pb);
-    } else if (track->enc->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0)
+    } else if (track->par->codec_id == AV_CODEC_ID_VP9) {
+        mov_write_vpcc_tag(mov->fc, pb, track);
+    } else if (track->par->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0)
         mov_write_dvc1_tag(pb, track);
-    else if (track->enc->codec_id == AV_CODEC_ID_VP6F ||
-             track->enc->codec_id == AV_CODEC_ID_VP6A) {
+    else if (track->par->codec_id == AV_CODEC_ID_VP6F ||
+             track->par->codec_id == AV_CODEC_ID_VP6A) {
         /* Don't write any potential extradata here - the cropping
          * is signalled via the normal width/height fields. */
-    } else if (track->enc->codec_id == AV_CODEC_ID_R10K) {
-        if (track->enc->codec_tag == MKTAG('R','1','0','k'))
+    } else if (track->par->codec_id == AV_CODEC_ID_R10K) {
+        if (track->par->codec_tag == MKTAG('R','1','0','k'))
             mov_write_dpxe_tag(pb, track);
     } else if (track->vos_len > 0)
         mov_write_glbl_tag(pb, track);
 
-    if (track->enc->codec_id != AV_CODEC_ID_H264 &&
-        track->enc->codec_id != AV_CODEC_ID_MPEG4 &&
-        track->enc->codec_id != AV_CODEC_ID_DNXHD)
-        if (track->enc->field_order != AV_FIELD_UNKNOWN)
-            mov_write_fiel_tag(pb, track);
+    if (track->par->codec_id != AV_CODEC_ID_H264 &&
+        track->par->codec_id != AV_CODEC_ID_MPEG4 &&
+        track->par->codec_id != AV_CODEC_ID_DNXHD) {
+        int field_order = track->par->field_order;
+
+#if FF_API_LAVF_AVCTX
+    FF_DISABLE_DEPRECATION_WARNINGS
+    if (field_order != track->st->codec->field_order && track->st->codec->field_order != AV_FIELD_UNKNOWN)
+        field_order = track->st->codec->field_order;
+    FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+        if (field_order != AV_FIELD_UNKNOWN)
+            mov_write_fiel_tag(pb, track, field_order);
+    }
 
     if (mov->flags & FF_MOV_FLAG_WRITE_GAMA) {
         if (track->mode == MODE_MOV)
@@ -1763,8 +1815,8 @@ static int mov_write_video_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tr
             av_log(mov->fc, AV_LOG_WARNING, "Not writing 'colr' atom. Format is not MOV or MP4.\n");
     }
 
-    if (track->enc->sample_aspect_ratio.den && track->enc->sample_aspect_ratio.num &&
-        track->enc->sample_aspect_ratio.den != track->enc->sample_aspect_ratio.num) {
+    if (track->par->sample_aspect_ratio.den && track->par->sample_aspect_ratio.num &&
+        track->par->sample_aspect_ratio.den != track->par->sample_aspect_ratio.num) {
         mov_write_pasp_tag(pb, track);
     }
 
@@ -1823,10 +1875,25 @@ static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
 #if 1
-    int frame_duration = av_rescale(track->timescale, track->enc->time_base.num, track->enc->time_base.den);
-    int nb_frames = ROUNDED_DIV(track->enc->time_base.den, track->enc->time_base.num);
+    int frame_duration;
+    int nb_frames;
     AVDictionaryEntry *t = NULL;
 
+    if (!track->st->avg_frame_rate.num || !track->st->avg_frame_rate.den) {
+#if FF_API_LAVF_AVCTX
+    FF_DISABLE_DEPRECATION_WARNINGS
+        frame_duration = av_rescale(track->timescale, track->st->codec->time_base.num, track->st->codec->time_base.den);
+        nb_frames      = ROUNDED_DIV(track->st->codec->time_base.den, track->st->codec->time_base.num);
+    FF_ENABLE_DEPRECATION_WARNINGS
+#else
+        av_log(NULL, AV_LOG_ERROR, "avg_frame_rate not set for tmcd track.\n");
+        return AVERROR(EINVAL);
+#endif
+    } else {
+        frame_duration = av_rescale(track->timescale, track->st->avg_frame_rate.num, track->st->avg_frame_rate.den);
+        nb_frames      = ROUNDED_DIV(track->st->avg_frame_rate.den, track->st->avg_frame_rate.num);
+    }
+
     if (nb_frames > 255) {
         av_log(NULL, AV_LOG_ERROR, "fps %d is too large\n", nb_frames);
         return AVERROR(EINVAL);
@@ -1843,10 +1910,8 @@ static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
     avio_w8(pb, nb_frames);                 /* Number of frames */
     avio_w8(pb, 0);                         /* Reserved */
 
-    if (track->st)
-        t = av_dict_get(track->st->metadata, "reel_name", NULL, 0);
-
-    if (t && utf8len(t->value))
+    t = av_dict_get(track->st->metadata, "reel_name", NULL, 0);
+    if (t && utf8len(t->value) && track->mode != MODE_MP4)
         mov_write_source_reference_tag(pb, track, t->value);
     else
         avio_wb16(pb, 0); /* zero size */
@@ -1856,28 +1921,28 @@ static int mov_write_tmcd_tag(AVIOContext *pb, MOVTrack *track)
     ffio_wfourcc(pb, "tmcd");               /* Data format */
     avio_wb32(pb, 0);                       /* Reserved */
     avio_wb32(pb, 1);                       /* Data reference index */
-    if (track->enc->extradata_size)
-        avio_write(pb, track->enc->extradata, track->enc->extradata_size);
+    if (track->par->extradata_size)
+        avio_write(pb, track->par->extradata, track->par->extradata_size);
 #endif
     return update_size(pb, pos);
 }
 
-static int mov_write_stsd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
+static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
     avio_wb32(pb, 0); /* size */
     ffio_wfourcc(pb, "stsd");
     avio_wb32(pb, 0); /* version & flags */
     avio_wb32(pb, 1); /* entry count */
-    if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
+    if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
         mov_write_video_tag(pb, mov, track);
-    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
-        mov_write_audio_tag(pb, mov, track);
-    else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)
+    else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
+        mov_write_audio_tag(s, pb, mov, track);
+    else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)
         mov_write_subtitle_tag(pb, track);
-    else if (track->enc->codec_tag == MKTAG('r','t','p',' '))
+    else if (track->par->codec_tag == MKTAG('r','t','p',' '))
         mov_write_rtp_tag(pb, track);
-    else if (track->enc->codec_tag == MKTAG('t','m','c','d'))
+    else if (track->par->codec_tag == MKTAG('t','m','c','d'))
         mov_write_tmcd_tag(pb, track);
     return update_size(pb, pos);
 }
@@ -1925,7 +1990,7 @@ static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track)
     uint32_t atom_size;
     int i;
 
-    if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
+    if (track->par->codec_type == AVMEDIA_TYPE_AUDIO && !track->audio_vbr) {
         stts_entries = av_malloc(sizeof(*stts_entries)); /* one entry */
         if (!stts_entries)
             return AVERROR(ENOMEM);
@@ -1978,22 +2043,22 @@ static int mov_write_dref_tag(AVIOContext *pb)
     return 28;
 }
 
-static int mov_write_stbl_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
+static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
     int ret;
 
     avio_wb32(pb, 0); /* size */
     ffio_wfourcc(pb, "stbl");
-    mov_write_stsd_tag(pb, mov, track);
+    mov_write_stsd_tag(s, pb, mov, track);
     mov_write_stts_tag(pb, track);
-    if ((track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
-         track->enc->codec_tag == MKTAG('r','t','p',' ')) &&
+    if ((track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
+         track->par->codec_tag == MKTAG('r','t','p',' ')) &&
         track->has_keyframes && track->has_keyframes < track->entry)
         mov_write_stss_tag(pb, track, MOV_SYNC_SAMPLE);
     if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
         mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
-    if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO &&
+    if (track->par->codec_type == AVMEDIA_TYPE_VIDEO &&
         track->flags & MOV_TRACK_CTTS && track->entry) {
 
         if ((ret = mov_write_ctts_tag(pb, track)) < 0)
@@ -2083,7 +2148,7 @@ static int mov_write_gmhd_tag(AVIOContext *pb, MOVTrack *track)
     avio_wb16(pb, 0x0000);
     }
 
-    if (track->enc->codec_tag == MKTAG('t','m','c','d')) {
+    if (track->par->codec_tag == MKTAG('t','m','c','d')) {
         int64_t tmcd_pos = avio_tell(pb);
         avio_wb32(pb, 0); /* size */
         ffio_wfourcc(pb, "tmcd");
@@ -2118,7 +2183,7 @@ static int is_clcp_track(MOVTrack *track)
            track->tag == MKTAG('c','6','0','8');
 }
 
-static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track)
 {
     const char *hdlr, *descr = NULL, *hdlr_type = NULL;
     int64_t pos = avio_tell(pb);
@@ -2129,13 +2194,13 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
 
     if (track) {
         hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0";
-        if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
             hdlr_type = "vide";
             descr     = "VideoHandler";
-        } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+        } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
             hdlr_type = "soun";
             descr     = "SoundHandler";
-        } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+        } else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
             if (is_clcp_track(track)) {
                 hdlr_type = "clcp";
                 descr = "ClosedCaptionHandler";
@@ -2149,20 +2214,20 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track)
                 }
             descr = "SubtitleHandler";
             }
-        } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) {
+        } else if (track->par->codec_tag == MKTAG('r','t','p',' ')) {
             hdlr_type = "hint";
             descr     = "HintHandler";
-        } else if (track->enc->codec_tag == MKTAG('t','m','c','d')) {
+        } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
             hdlr_type = "tmcd";
             descr = "TimeCodeHandler";
         } else {
             char tag_buf[32];
             av_get_codec_tag_string(tag_buf, sizeof(tag_buf),
-                                    track->enc->codec_tag);
+                                    track->par->codec_tag);
 
-            av_log(track->enc, AV_LOG_WARNING,
+            av_log(s, AV_LOG_WARNING,
                    "Unknown hldr_type for %s / 0x%04X, writing dummy values\n",
-                   tag_buf, track->enc->codec_tag);
+                   tag_buf, track->par->codec_tag);
         }
         if (track->st) {
             // hdlr.name is used by some players to identify the content title
@@ -2206,18 +2271,18 @@ static int mov_write_hmhd_tag(AVIOContext *pb)
     return 28;
 }
 
-static int mov_write_minf_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
+static int mov_write_minf_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
     int ret;
 
     avio_wb32(pb, 0); /* size */
     ffio_wfourcc(pb, "minf");
-    if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO)
+    if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)
         mov_write_vmhd_tag(pb);
-    else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
+    else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
         mov_write_smhd_tag(pb);
-    else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+    else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
         if (track->tag == MKTAG('t','e','x','t') || is_clcp_track(track)) {
             mov_write_gmhd_tag(pb, track);
         } else {
@@ -2226,12 +2291,15 @@ static int mov_write_minf_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *tra
     } else if (track->tag == MKTAG('r','t','p',' ')) {
         mov_write_hmhd_tag(pb);
     } else if (track->tag == MKTAG('t','m','c','d')) {
-        mov_write_gmhd_tag(pb, track);
+        if (track->mode == MODE_MP4)
+            mov_write_nmhd_tag(pb);
+        else
+            mov_write_gmhd_tag(pb, track);
     }
     if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
-        mov_write_hdlr_tag(pb, NULL);
+        mov_write_hdlr_tag(s, pb, NULL);
     mov_write_dinf_tag(pb);
-    if ((ret = mov_write_stbl_tag(pb, mov, track)) < 0)
+    if ((ret = mov_write_stbl_tag(s, pb, mov, track)) < 0)
         return ret;
     return update_size(pb, pos);
 }
@@ -2275,8 +2343,8 @@ static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov,
     return 32;
 }
 
-static int mov_write_mdia_tag(AVIOContext *pb, MOVMuxContext *mov,
-                              MOVTrack *track)
+static int mov_write_mdia_tag(AVFormatContext *s, AVIOContext *pb,
+                              MOVMuxContext *mov, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
     int ret;
@@ -2284,8 +2352,8 @@ static int mov_write_mdia_tag(AVIOContext *pb, MOVMuxContext *mov,
     avio_wb32(pb, 0); /* size */
     ffio_wfourcc(pb, "mdia");
     mov_write_mdhd_tag(pb, mov, track);
-    mov_write_hdlr_tag(pb, track);
-    if ((ret = mov_write_minf_tag(pb, mov, track)) < 0)
+    mov_write_hdlr_tag(s, pb, track);
+    if ((ret = mov_write_minf_tag(s, pb, mov, track)) < 0)
         return ret;
     return update_size(pb, pos);
 }
@@ -2325,7 +2393,7 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,
         if (mov->per_stream_grouping)
             group = st->index;
         else
-            group = st->codec->codec_type;
+            group = st->codecpar->codec_type;
 
         display_matrix = (uint32_t*)av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX,
                                                             &display_matrix_size);
@@ -2364,7 +2432,7 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,
     avio_wb16(pb, 0); /* layer */
     avio_wb16(pb, group); /* alternate group) */
     /* Volume, only for audio */
-    if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO)
+    if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)
         avio_wb16(pb, 0x0100);
     else
         avio_wb16(pb, 0);
@@ -2379,31 +2447,39 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,
         for (i = 0; i < 9; i++)
             avio_wb32(pb, display_matrix[i]);
     } else if (rotation == 90) {
-        write_matrix(pb,  0,  1, -1,  0, track->enc->height, 0);
+        write_matrix(pb,  0,  1, -1,  0, track->par->height, 0);
     } else if (rotation == 180) {
-        write_matrix(pb, -1,  0,  0, -1, track->enc->width, track->enc->height);
+        write_matrix(pb, -1,  0,  0, -1, track->par->width, track->par->height);
     } else if (rotation == 270) {
-        write_matrix(pb,  0, -1,  1,  0, 0, track->enc->width);
+        write_matrix(pb,  0, -1,  1,  0, 0, track->par->width);
     } else {
         write_matrix(pb,  1,  0,  0,  1, 0, 0);
     }
     /* Track width and height, for visual only */
-    if (st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
-               track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
+    if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO ||
+               track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
+        int64_t track_width_1616;
         if (track->mode == MODE_MOV) {
-            avio_wb32(pb, track->enc->width << 16);
-            avio_wb32(pb, track->height << 16);
+            track_width_1616 = track->par->width * 0x10000ULL;
         } else {
-            int64_t track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
-                                                  track->enc->width * 0x10000LL,
+            track_width_1616 = av_rescale(st->sample_aspect_ratio.num,
+                                                  track->par->width * 0x10000LL,
                                                   st->sample_aspect_ratio.den);
             if (!track_width_1616 ||
-                track->height != track->enc->height ||
+                track->height != track->par->height ||
                 track_width_1616 > UINT32_MAX)
-                track_width_1616 = track->enc->width * 0x10000U;
-            avio_wb32(pb, track_width_1616);
-            avio_wb32(pb, track->height * 0x10000U);
+                track_width_1616 = track->par->width * 0x10000ULL;
         }
+        if (track_width_1616 > UINT32_MAX) {
+            av_log(mov->fc, AV_LOG_WARNING, "track width is too large\n");
+            track_width_1616 = 0;
+        }
+        avio_wb32(pb, track_width_1616);
+        if (track->height > 0xFFFF) {
+            av_log(mov->fc, AV_LOG_WARNING, "track height is too large\n");
+            avio_wb32(pb, 0);
+        } else
+            avio_wb32(pb, track->height * 0x10000U);
     } else {
         avio_wb32(pb, 0);
         avio_wb32(pb, 0);
@@ -2413,8 +2489,8 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov,
 
 static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
 {
-    int32_t width = av_rescale(track->enc->sample_aspect_ratio.num, track->enc->width,
-                               track->enc->sample_aspect_ratio.den);
+    int32_t width = av_rescale(track->par->sample_aspect_ratio.num, track->par->width,
+                               track->par->sample_aspect_ratio.den);
 
     int64_t pos = avio_tell(pb);
 
@@ -2425,19 +2501,19 @@ static int mov_write_tapt_tag(AVIOContext *pb, MOVTrack *track)
     ffio_wfourcc(pb, "clef");
     avio_wb32(pb, 0);
     avio_wb32(pb, width << 16);
-    avio_wb32(pb, track->enc->height << 16);
+    avio_wb32(pb, track->par->height << 16);
 
     avio_wb32(pb, 20);
     ffio_wfourcc(pb, "prof");
     avio_wb32(pb, 0);
     avio_wb32(pb, width << 16);
-    avio_wb32(pb, track->enc->height << 16);
+    avio_wb32(pb, track->par->height << 16);
 
     avio_wb32(pb, 20);
     ffio_wfourcc(pb, "enof");
     avio_wb32(pb, 0);
-    avio_wb32(pb, track->enc->width << 16);
-    avio_wb32(pb, track->enc->height << 16);
+    avio_wb32(pb, track->par->width << 16);
+    avio_wb32(pb, track->par->height << 16);
 
     return update_size(pb, pos);
 }
@@ -2486,7 +2562,7 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
         /* In the positive delay case, the delay includes the cts
          * offset, and the second edit list entry below trims out
          * the same amount from the actual content. This makes sure
-         * that the offsetted last sample is included in the edit
+         * that the offset last sample is included in the edit
          * list duration as well. */
         if (version == 1) {
             avio_wb64(pb, delay);
@@ -2499,7 +2575,7 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov,
     } else {
         /* Avoid accidentally ending up with start_ct = -1 which has got a
          * special meaning. Normally start_ct should end up positive or zero
-         * here, but use FFMIN in case dts is a a small positive integer
+         * here, but use FFMIN in case dts is a small positive integer
          * rounded to 0 when represented in MOV_TIMESCALE units. */
         av_assert0(av_rescale_rnd(start_dts, MOV_TIMESCALE, track->timescale, AV_ROUND_DOWN) <= 0);
         start_ct  = -FFMIN(start_dts, 0);
@@ -2619,7 +2695,7 @@ static int mov_write_track_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
     return 0;
 }
 
-static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov,
+static int mov_write_trak_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov,
                               MOVTrack *track, AVStream *st)
 {
     int64_t pos = avio_tell(pb);
@@ -2649,14 +2725,14 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov,
     if (track->tref_tag)
         mov_write_tref_tag(pb, track);
 
-    if ((ret = mov_write_mdia_tag(pb, mov, track)) < 0)
+    if ((ret = mov_write_mdia_tag(s, pb, mov, track)) < 0)
         return ret;
     if (track->mode == MODE_PSP)
         mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
     if (track->tag == MKTAG('r','t','p',' '))
         mov_write_udta_sdp(pb, track);
     if (track->mode == MODE_MOV) {
-        if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
             double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
             if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) {
                 mov_write_tapt_tag(pb, track);
@@ -2680,8 +2756,8 @@ static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov)
     int video_profile = mov->iods_video_profile;
     for (i = 0; i < mov->nb_streams; i++) {
         if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
-            has_audio |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_AUDIO;
-            has_video |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_VIDEO;
+            has_audio |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_AUDIO;
+            has_video |= mov->tracks[i].par->codec_type == AVMEDIA_TYPE_VIDEO;
         }
     }
     if (audio_profile < 0)
@@ -2835,16 +2911,17 @@ static int mov_write_string_tag(AVIOContext *pb, const char *name,
     return size;
 }
 
-static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
-                                     const char *name, const char *tag,
-                                     int long_style)
+static AVDictionaryEntry *get_metadata_lang(AVFormatContext *s,
+                                            const char *tag, int *lang)
 {
-    int l, lang = 0, len, len2;
+    int l, len, len2;
     AVDictionaryEntry *t, *t2 = NULL;
     char tag2[16];
 
+    *lang = 0;
+
     if (!(t = av_dict_get(s->metadata, tag, NULL, 0)))
-        return 0;
+        return NULL;
 
     len = strlen(t->key);
     snprintf(tag2, sizeof(tag2), "%s-", tag);
@@ -2852,10 +2929,21 @@ static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
         len2 = strlen(t2->key);
         if (len2 == len + 4 && !strcmp(t->value, t2->value)
             && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) {
-            lang = l;
-            break;
+            *lang = l;
+            return t;
         }
     }
+    return t;
+}
+
+static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb,
+                                     const char *name, const char *tag,
+                                     int long_style)
+{
+    int lang;
+    AVDictionaryEntry *t = get_metadata_lang(s, tag, &lang);
+    if (!t)
+        return 0;
     return mov_write_string_tag(pb, name, t->value, lang, long_style);
 }
 
@@ -2877,6 +2965,57 @@ static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
     return size;
 }
 
+/* 3GPP TS 26.244 */
+static int mov_write_loci_tag(AVFormatContext *s, AVIOContext *pb)
+{
+    int lang;
+    int64_t pos = avio_tell(pb);
+    double latitude, longitude, altitude;
+    int32_t latitude_fix, longitude_fix, altitude_fix;
+    AVDictionaryEntry *t = get_metadata_lang(s, "location", &lang);
+    const char *ptr, *place = "";
+    char *end;
+    static const char *astronomical_body = "earth";
+    if (!t)
+        return 0;
+
+    ptr = t->value;
+    longitude = strtod(ptr, &end);
+    if (end == ptr) {
+        av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
+        return 0;
+    }
+    ptr = end;
+    latitude = strtod(ptr, &end);
+    if (end == ptr) {
+        av_log(s, AV_LOG_WARNING, "malformed location metadata\n");
+        return 0;
+    }
+    ptr = end;
+    altitude = strtod(ptr, &end);
+    /* If no altitude was present, the default 0 should be fine */
+    if (*end == '/')
+        place = end + 1;
+
+    latitude_fix  = (int32_t) ((1 << 16) * latitude);
+    longitude_fix = (int32_t) ((1 << 16) * longitude);
+    altitude_fix  = (int32_t) ((1 << 16) * altitude);
+
+    avio_wb32(pb, 0);         /* size */
+    ffio_wfourcc(pb, "loci"); /* type */
+    avio_wb32(pb, 0);         /* version + flags */
+    avio_wb16(pb, lang);
+    avio_write(pb, place, strlen(place) + 1);
+    avio_w8(pb, 0);           /* role of place (0 == shooting location, 1 == real location, 2 == fictional location) */
+    avio_wb32(pb, latitude_fix);
+    avio_wb32(pb, longitude_fix);
+    avio_wb32(pb, altitude_fix);
+    avio_write(pb, astronomical_body, strlen(astronomical_body) + 1);
+    avio_w8(pb, 0);           /* additional notes, null terminated string */
+
+    return update_size(pb, pos);
+}
+
 /* iTunes track or disc number */
 static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov,
                               AVFormatContext *s, int disc)
@@ -2971,7 +3110,71 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
     return update_size(pb, pos);
 }
 
-/* iTunes meta data tag */
+static int mov_write_mdta_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov,
+                                   AVFormatContext *s)
+{
+    avio_wb32(pb, 33); /* size */
+    ffio_wfourcc(pb, "hdlr");
+    avio_wb32(pb, 0);
+    avio_wb32(pb, 0);
+    ffio_wfourcc(pb, "mdta");
+    avio_wb32(pb, 0);
+    avio_wb32(pb, 0);
+    avio_wb32(pb, 0);
+    avio_w8(pb, 0);
+    return 33;
+}
+
+static int mov_write_mdta_keys_tag(AVIOContext *pb, MOVMuxContext *mov,
+                                   AVFormatContext *s)
+{
+    AVDictionaryEntry *t = NULL;
+    int64_t pos = avio_tell(pb);
+    int64_t curpos, entry_pos;
+    int count = 0;
+
+    avio_wb32(pb, 0); /* size */
+    ffio_wfourcc(pb, "keys");
+    avio_wb32(pb, 0);
+    entry_pos = avio_tell(pb);
+    avio_wb32(pb, 0); /* entry count */
+
+    while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
+        avio_wb32(pb, strlen(t->key) + 8);
+        ffio_wfourcc(pb, "mdta");
+        avio_write(pb, t->key, strlen(t->key));
+        count += 1;
+    }
+    curpos = avio_tell(pb);
+    avio_seek(pb, entry_pos, SEEK_SET);
+    avio_wb32(pb, count); // rewrite entry count
+    avio_seek(pb, curpos, SEEK_SET);
+
+    return update_size(pb, pos);
+}
+
+static int mov_write_mdta_ilst_tag(AVIOContext *pb, MOVMuxContext *mov,
+                                   AVFormatContext *s)
+{
+    AVDictionaryEntry *t = NULL;
+    int64_t pos = avio_tell(pb);
+    int count = 1; /* keys are 1-index based */
+
+    avio_wb32(pb, 0); /* size */
+    ffio_wfourcc(pb, "ilst");
+
+    while (t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)) {
+        int64_t entry_pos = avio_tell(pb);
+        avio_wb32(pb, 0); /* size */
+        avio_wb32(pb, count); /* key */
+        mov_write_string_data_tag(pb, t->value, 0, 1);
+        update_size(pb, entry_pos);
+        count += 1;
+    }
+    return update_size(pb, pos);
+}
+
+/* meta data tags */
 static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
                               AVFormatContext *s)
 {
@@ -2980,8 +3183,16 @@ static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov,
     avio_wb32(pb, 0); /* size */
     ffio_wfourcc(pb, "meta");
     avio_wb32(pb, 0);
-    mov_write_itunes_hdlr_tag(pb, mov, s);
-    mov_write_ilst_tag(pb, mov, s);
+    if (mov->flags & FF_MOV_FLAG_USE_MDTA) {
+        mov_write_mdta_hdlr_tag(pb, mov, s);
+        mov_write_mdta_keys_tag(pb, mov, s);
+        mov_write_mdta_ilst_tag(pb, mov, s);
+    }
+    else {
+        /* iTunes metadata tag */
+        mov_write_itunes_hdlr_tag(pb, mov, s);
+        mov_write_ilst_tag(pb, mov, s);
+    }
     size = update_size(pb, pos);
     return size;
 }
@@ -3092,7 +3303,8 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
         mov_write_3gp_udta_tag(pb_buf, s, "albm", "album");
         mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright");
         mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date");
-    } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
+        mov_write_loci_tag(s, pb_buf);
+    } else if (mov->mode == MODE_MOV && !(mov->flags & FF_MOV_FLAG_USE_MDTA)) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4
         mov_write_string_metadata(s, pb_buf, "\251ART", "artist",      0);
         mov_write_string_metadata(s, pb_buf, "\251nam", "title",       0);
         mov_write_string_metadata(s, pb_buf, "\251aut", "author",      0);
@@ -3112,6 +3324,7 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov,
     } else {
         /* iTunes meta data */
         mov_write_meta_tag(pb_buf, mov, s);
+        mov_write_loci_tag(s, pb_buf);
     }
 
     if (s->nb_chapters && !(mov->flags & FF_MOV_FLAG_DISABLE_CHPL))
@@ -3230,7 +3443,7 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
         if (track->tag == MKTAG('r','t','p',' ')) {
             track->tref_tag = MKTAG('h','i','n','t');
             track->tref_id = mov->tracks[track->src_track].track_id;
-        } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+        } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
             int * fallback, size;
             fallback = (int*)av_stream_get_side_data(track->st,
                                                      AV_PKT_DATA_FALLBACK_TRACK,
@@ -3260,7 +3473,7 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
         mov_write_iods_tag(pb, mov);
     for (i = 0; i < mov->nb_streams; i++) {
         if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT) {
-            int ret = mov_write_trak_tag(pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
+            int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL);
             if (ret < 0)
                 return ret;
         }
@@ -3325,41 +3538,41 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov)
          * here yet */
         int track_id = i + 1;
 
-        if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
             type = "video";
-        } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+        } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
             type = "audio";
         } else {
             continue;
         }
         avio_printf(pb, "<%s systemBitrate=\"%"PRId64"\">\n", type,
-                    (int64_t)track->enc->bit_rate);
-        param_write_int(pb, "systemBitrate", track->enc->bit_rate);
+                    (int64_t)track->par->bit_rate);
+        param_write_int(pb, "systemBitrate", track->par->bit_rate);
         param_write_int(pb, "trackID", track_id);
-        if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) {
-            if (track->enc->codec_id == AV_CODEC_ID_H264) {
+        if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
+            if (track->par->codec_id == AV_CODEC_ID_H264) {
                 uint8_t *ptr;
-                int size = track->enc->extradata_size;
-                if (!ff_avc_write_annexb_extradata(track->enc->extradata, &ptr,
+                int size = track->par->extradata_size;
+                if (!ff_avc_write_annexb_extradata(track->par->extradata, &ptr,
                                                    &size)) {
                     param_write_hex(pb, "CodecPrivateData",
-                                    ptr ? ptr : track->enc->extradata,
+                                    ptr ? ptr : track->par->extradata,
                                     size);
                     av_free(ptr);
                 }
                 param_write_string(pb, "FourCC", "H264");
-            } else if (track->enc->codec_id == AV_CODEC_ID_VC1) {
+            } else if (track->par->codec_id == AV_CODEC_ID_VC1) {
                 param_write_string(pb, "FourCC", "WVC1");
-                param_write_hex(pb, "CodecPrivateData", track->enc->extradata,
-                                track->enc->extradata_size);
+                param_write_hex(pb, "CodecPrivateData", track->par->extradata,
+                                track->par->extradata_size);
             }
-            param_write_int(pb, "MaxWidth", track->enc->width);
-            param_write_int(pb, "MaxHeight", track->enc->height);
-            param_write_int(pb, "DisplayWidth", track->enc->width);
-            param_write_int(pb, "DisplayHeight", track->enc->height);
+            param_write_int(pb, "MaxWidth", track->par->width);
+            param_write_int(pb, "MaxHeight", track->par->height);
+            param_write_int(pb, "DisplayWidth", track->par->width);
+            param_write_int(pb, "DisplayHeight", track->par->height);
         } else {
-            if (track->enc->codec_id == AV_CODEC_ID_AAC) {
-                switch (track->enc->profile)
+            if (track->par->codec_id == AV_CODEC_ID_AAC) {
+                switch (track->par->profile)
                 {
                     case FF_PROFILE_AAC_HE_V2:
                         param_write_string(pb, "FourCC", "AACP");
@@ -3370,18 +3583,18 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov)
                     default:
                         param_write_string(pb, "FourCC", "AACL");
                 }
-            } else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO) {
+            } else if (track->par->codec_id == AV_CODEC_ID_WMAPRO) {
                 param_write_string(pb, "FourCC", "WMAP");
             }
-            param_write_hex(pb, "CodecPrivateData", track->enc->extradata,
-                            track->enc->extradata_size);
+            param_write_hex(pb, "CodecPrivateData", track->par->extradata,
+                            track->par->extradata_size);
             param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags,
-                                                             track->enc->codec_id));
-            param_write_int(pb, "Channels", track->enc->channels);
-            param_write_int(pb, "SamplingRate", track->enc->sample_rate);
+                                                             track->par->codec_id));
+            param_write_int(pb, "Channels", track->par->channels);
+            param_write_int(pb, "SamplingRate", track->par->sample_rate);
             param_write_int(pb, "BitsPerSample", 16);
-            param_write_int(pb, "PacketSize", track->enc->block_align ?
-                                              track->enc->block_align : 4);
+            param_write_int(pb, "PacketSize", track->par->block_align ?
+                                              track->par->block_align : 4);
         }
         avio_printf(pb, "</%s>\n", type);
     }
@@ -3458,7 +3671,7 @@ static int mov_write_tfhd_tag(AVIOContext *pb, MOVMuxContext *mov,
             track->default_sample_flags = get_sample_flags(track, &track->cluster[1]);
         else
             track->default_sample_flags =
-                track->enc->codec_type == AVMEDIA_TYPE_VIDEO ?
+                track->par->codec_type == AVMEDIA_TYPE_VIDEO ?
                 (MOV_FRAG_SAMPLE_FLAG_DEPENDS_YES | MOV_FRAG_SAMPLE_FLAG_IS_NON_SYNC) :
                 MOV_FRAG_SAMPLE_FLAG_DEPENDS_NO;
         avio_wb32(pb, track->default_sample_flags);
@@ -3893,9 +4106,9 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
 
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
             has_video = 1;
-        if (st->codec->codec_id == AV_CODEC_ID_H264)
+        if (st->codecpar->codec_id == AV_CODEC_ID_H264)
             has_h264 = 1;
     }
 
@@ -3961,13 +4174,13 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s)
 static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
 {
     AVStream       *video_st    = s->streams[0];
-    AVCodecContext *video_codec = s->streams[0]->codec;
-    AVCodecContext *audio_codec = s->streams[1]->codec;
-    int audio_rate = audio_codec->sample_rate;
+    AVCodecParameters *video_par = s->streams[0]->codecpar;
+    AVCodecParameters *audio_par = s->streams[1]->codecpar;
+    int audio_rate = audio_par->sample_rate;
     // TODO: should be avg_frame_rate
     int frame_rate = ((video_st->time_base.den) * (0x10000)) / (video_st->time_base.num);
-    int audio_kbitrate = audio_codec->bit_rate / 1000;
-    int video_kbitrate = FFMIN(video_codec->bit_rate / 1000, 800 - audio_kbitrate);
+    int audio_kbitrate = audio_par->bit_rate / 1000;
+    int video_kbitrate = FFMIN(video_par->bit_rate / 1000, 800 - audio_kbitrate);
 
     avio_wb32(pb, 0x94); /* size */
     ffio_wfourcc(pb, "uuid");
@@ -3996,13 +4209,13 @@ static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
     avio_wb32(pb, audio_kbitrate);
     avio_wb32(pb, audio_kbitrate);
     avio_wb32(pb, audio_rate);
-    avio_wb32(pb, audio_codec->channels);
+    avio_wb32(pb, audio_par->channels);
 
     avio_wb32(pb, 0x34);  /* size */
     ffio_wfourcc(pb, "VPRF");   /* video */
     avio_wb32(pb, 0x0);
     avio_wb32(pb, 0x1);    /* TrackID */
-    if (video_codec->codec_id == AV_CODEC_ID_H264) {
+    if (video_par->codec_id == AV_CODEC_ID_H264) {
         ffio_wfourcc(pb, "avc1");
         avio_wb16(pb, 0x014D);
         avio_wb16(pb, 0x0015);
@@ -4016,8 +4229,8 @@ static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s)
     avio_wb32(pb, video_kbitrate);
     avio_wb32(pb, frame_rate);
     avio_wb32(pb, frame_rate);
-    avio_wb16(pb, video_codec->width);
-    avio_wb16(pb, video_codec->height);
+    avio_wb16(pb, video_par->width);
+    avio_wb16(pb, video_par->height);
     avio_wb32(pb, 0x010001); /* ? */
 }
 
@@ -4031,9 +4244,9 @@ static int mov_write_identification(AVIOContext *pb, AVFormatContext *s)
         int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0;
         for (i = 0; i < s->nb_streams; i++) {
             AVStream *st = s->streams[i];
-            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
                 video_streams_nb++;
-            else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+            else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
                 audio_streams_nb++;
             else
                 other_streams_nb++;
@@ -4161,10 +4374,32 @@ static int mov_flush_fragment(AVFormatContext *s, int force)
     int i, first_track = -1;
     int64_t mdat_size = 0;
     int ret;
+    int has_video = 0, starts_with_key = 0, first_video_track = 1;
 
     if (!(mov->flags & FF_MOV_FLAG_FRAGMENT))
         return 0;
 
+    // Try to fill in the duration of the last packet in each stream
+    // from queued packets in the interleave queues. If the flushing
+    // of fragments was triggered automatically by an AVPacket, we
+    // already have reliable info for the end of that track, but other
+    // tracks may need to be filled in.
+    for (i = 0; i < s->nb_streams; i++) {
+        MOVTrack *track = &mov->tracks[i];
+        if (!track->end_reliable) {
+            int64_t ts_offset;
+            const AVPacket *next = ff_interleaved_peek(s, i, &ts_offset);
+            if (next) {
+                track->track_duration = next->dts - track->start_dts + ts_offset;
+                if (next->pts != AV_NOPTS_VALUE)
+                    track->end_pts = next->pts;
+                else
+                    track->end_pts = next->dts;
+                track->end_pts += ts_offset;
+            }
+        }
+    }
+
     for (i = 0; i < mov->nb_streams; i++) {
         MOVTrack *track = &mov->tracks[i];
         if (track->entry <= 1)
@@ -4208,6 +4443,7 @@ static int mov_flush_fragment(AVFormatContext *s, int force)
         for (i = 0; i < mov->nb_streams; i++)
             mov->tracks[i].data_offset = pos + moov_size + 8;
 
+        avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
         if (mov->flags & FF_MOV_FLAG_DELAY_MOOV)
             mov_write_identification(s->pb, s);
         if ((ret = mov_write_moov_tag(s->pb, mov, s)) < 0)
@@ -4239,6 +4475,7 @@ static int mov_flush_fragment(AVFormatContext *s, int force)
                                              mov->tracks[i].track_duration -
                                              mov->tracks[i].cluster[0].dts;
             mov->tracks[i].entry = 0;
+            mov->tracks[i].end_reliable = 0;
         }
         avio_flush(s->pb);
         return 0;
@@ -4263,6 +4500,14 @@ static int mov_flush_fragment(AVFormatContext *s, int force)
             track->data_offset = 0;
         else
             track->data_offset = mdat_size;
+        if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) {
+            has_video = 1;
+            if (first_video_track) {
+                if (track->entry)
+                    starts_with_key = track->cluster[0].flags & MOV_SYNC_SAMPLE;
+                first_video_track = 0;
+            }
+        }
         if (!track->entry)
             continue;
         if (track->mdat_buf)
@@ -4274,6 +4519,10 @@ static int mov_flush_fragment(AVFormatContext *s, int force)
     if (!mdat_size)
         return 0;
 
+    avio_write_marker(s->pb,
+                      av_rescale(mov->tracks[first_track].cluster[0].dts, AV_TIME_BASE, mov->tracks[first_track].timescale),
+                      (has_video ? starts_with_key : mov->tracks[first_track].cluster[0].flags & MOV_SYNC_SAMPLE) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
+
     for (i = 0; i < mov->nb_streams; i++) {
         MOVTrack *track = &mov->tracks[i];
         int buf_size, write_moof = 1, moof_tracks = -1;
@@ -4306,6 +4555,7 @@ static int mov_flush_fragment(AVFormatContext *s, int force)
             track->frag_start += duration;
         track->entry = 0;
         track->entries_flushed = 0;
+        track->end_reliable = 0;
         if (!mov->frag_interleave) {
             if (!track->mdat_buf)
                 continue;
@@ -4347,7 +4597,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
     MOVMuxContext *mov = s->priv_data;
     AVIOContext *pb = s->pb;
     MOVTrack *trk = &mov->tracks[pkt->stream_index];
-    AVCodecContext *enc = trk->enc;
+    AVCodecParameters *par = trk->par;
     unsigned int samples_in_chunk = 0;
     int size = pkt->size, ret = 0;
     uint8_t *reformatted_data = NULL;
@@ -4391,7 +4641,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
         }
     }
 
-    if (enc->codec_id == AV_CODEC_ID_AMR_NB) {
+    if (par->codec_id == AV_CODEC_ID_AMR_NB) {
         /* We must find out how many AMR blocks there are in one packet */
         static const uint16_t packed_size[16] =
             {13, 14, 16, 18, 20, 21, 27, 32, 6, 0, 0, 0, 0, 0, 0, 1};
@@ -4405,28 +4655,28 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
             av_log(s, AV_LOG_ERROR, "fatal error, input is not a single packet, implement a AVParser for it\n");
             return -1;
         }
-    } else if (enc->codec_id == AV_CODEC_ID_ADPCM_MS ||
-               enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
-        samples_in_chunk = enc->frame_size;
+    } else if (par->codec_id == AV_CODEC_ID_ADPCM_MS ||
+               par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
+        samples_in_chunk = trk->par->frame_size;
     } else if (trk->sample_size)
         samples_in_chunk = size / trk->sample_size;
     else
         samples_in_chunk = 1;
 
     /* copy extradata if it exists */
-    if (trk->vos_len == 0 && enc->extradata_size > 0 &&
+    if (trk->vos_len == 0 && par->extradata_size > 0 &&
         !TAG_IS_AVCI(trk->tag) &&
-        (enc->codec_id != AV_CODEC_ID_DNXHD)) {
-        trk->vos_len  = enc->extradata_size;
+        (par->codec_id != AV_CODEC_ID_DNXHD)) {
+        trk->vos_len  = par->extradata_size;
         trk->vos_data = av_malloc(trk->vos_len);
         if (!trk->vos_data) {
             ret = AVERROR(ENOMEM);
             goto err;
         }
-        memcpy(trk->vos_data, enc->extradata, trk->vos_len);
+        memcpy(trk->vos_data, par->extradata, trk->vos_len);
     }
 
-    if (enc->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
+    if (par->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 &&
         (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {
         if (!s->streams[pkt->stream_index]->nb_frames) {
             av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: "
@@ -4436,9 +4686,9 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
         }
         av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
     }
-    if (enc->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1 && !TAG_IS_AVCI(trk->tag)) {
-        /* from x264 or from bytestream h264 */
-        /* nal reformating needed */
+    if (par->codec_id == AV_CODEC_ID_H264 && trk->vos_len > 0 && *(uint8_t *)trk->vos_data != 1 && !TAG_IS_AVCI(trk->tag)) {
+        /* from x264 or from bytestream H.264 */
+        /* NAL reformatting needed */
         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
             ff_avc_parse_nal_units_buf(pkt->data, &reformatted_data,
                                        &size);
@@ -4454,7 +4704,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
                 size = ff_avc_parse_nal_units(pb, pkt->data, pkt->size);
             }
         }
-    } else if (enc->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
+    } else if (par->codec_id == AV_CODEC_ID_HEVC && trk->vos_len > 6 &&
                (AV_RB24(trk->vos_data) == 1 || AV_RB32(trk->vos_data) == 1)) {
         /* extradata is Annex B, assume the bitstream is too and convert it */
         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams) {
@@ -4464,7 +4714,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
             size = ff_hevc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
         }
 #if CONFIG_AC3_PARSER
-    } else if (enc->codec_id == AV_CODEC_ID_EAC3) {
+    } else if (par->codec_id == AV_CODEC_ID_EAC3) {
         size = handle_eac3(mov, pkt, trk);
         if (size < 0)
             return size;
@@ -4474,8 +4724,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
 #endif
     } else {
         if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
-            if (enc->codec_id == AV_CODEC_ID_H264 && enc->extradata_size > 4) {
-                int nal_size_length = (enc->extradata[4] & 0x3) + 1;
+            if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 4) {
+                int nal_size_length = (par->extradata[4] & 0x3) + 1;
                 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
             } else {
                 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
@@ -4489,8 +4739,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
         }
     }
 
-    if ((enc->codec_id == AV_CODEC_ID_DNXHD ||
-         enc->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) {
+    if ((par->codec_id == AV_CODEC_ID_DNXHD ||
+         par->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) {
         /* copy frame to create needed atoms */
         trk->vos_len  = size;
         trk->vos_data = av_malloc(size);
@@ -4527,7 +4777,8 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
             /* We also may have written the pts and the corresponding duration
              * in sidx/tfrf/tfxd tags; make sure the sidx pts and duration match up with
              * the next fragment. This means the cts of the first sample must
-             * be the same in all fragments. */
+             * be the same in all fragments, unless end_pts was updated by
+             * the packet causing the fragment to be written. */
             if ((mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)) ||
                 mov->mode == MODE_ISM)
                 pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
@@ -4594,10 +4845,10 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
                                            trk->cluster[trk->entry].cts +
                                            pkt->duration);
 
-    if (enc->codec_id == AV_CODEC_ID_VC1) {
+    if (par->codec_id == AV_CODEC_ID_VC1) {
         mov_parse_vc1_frame(pkt, trk);
     } else if (pkt->flags & AV_PKT_FLAG_KEY) {
-        if (mov->mode == MODE_MOV && enc->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
+        if (mov->mode == MODE_MOV && par->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
             trk->entry > 0) { // force sync sample for the first key frame
             mov_parse_mpeg2_frame(pkt, &trk->cluster[trk->entry].flags);
             if (trk->cluster[trk->entry].flags & MOV_PARTIAL_SYNC_SAMPLE)
@@ -4627,7 +4878,7 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
 {
         MOVMuxContext *mov = s->priv_data;
         MOVTrack *trk = &mov->tracks[pkt->stream_index];
-        AVCodecContext *enc = trk->enc;
+        AVCodecParameters *par = trk->par;
         int64_t frag_duration = 0;
         int size = pkt->size;
 
@@ -4658,7 +4909,7 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
              frag_duration >= mov->max_fragment_duration) ||
              (mov->max_fragment_size && mov->mdat_size + size >= mov->max_fragment_size) ||
              (mov->flags & FF_MOV_FLAG_FRAG_KEYFRAME &&
-              enc->codec_type == AVMEDIA_TYPE_VIDEO &&
+              par->codec_type == AVMEDIA_TYPE_VIDEO &&
               trk->entry && pkt->flags & AV_PKT_FLAG_KEY)) {
             if (frag_duration >= mov->min_fragment_duration) {
                 // Set the duration of this track to line up with the next
@@ -4666,7 +4917,11 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
                 // duration, but only helps for this particular track, not
                 // for the other ones that are flushed at the same time.
                 trk->track_duration = pkt->dts - trk->start_dts;
-                trk->end_pts = pkt->pts;
+                if (pkt->pts != AV_NOPTS_VALUE)
+                    trk->end_pts = pkt->pts;
+                else
+                    trk->end_pts = pkt->dts;
+                trk->end_reliable = 1;
                 mov_auto_flush_fragment(s, 0);
             }
         }
@@ -4703,6 +4958,7 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
     } else {
         int i;
         MOVMuxContext *mov = s->priv_data;
+        MOVTrack *trk = &mov->tracks[pkt->stream_index];
 
         if (!pkt->size)
             return mov_write_single_packet(s, pkt); /* Passthrough. */
@@ -4730,7 +4986,7 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
             MOVTrack *trk = &mov->tracks[i];
             int ret;
 
-            if (trk->enc->codec_id == AV_CODEC_ID_MOV_TEXT &&
+            if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
                 trk->track_duration < pkt->dts &&
                 (trk->entry == 0 || !trk->last_sample_is_subtitle_end)) {
                 ret = mov_write_subtitle_end_packet(s, i, trk->track_duration);
@@ -4739,6 +4995,38 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt)
             }
         }
 
+        if (trk->mode == MODE_MOV && trk->par->codec_type == AVMEDIA_TYPE_VIDEO) {
+            AVPacket *opkt = pkt;
+            int reshuffle_ret, ret;
+            if (trk->is_unaligned_qt_rgb) {
+                int64_t bpc = trk->par->bits_per_coded_sample != 15 ? trk->par->bits_per_coded_sample : 16;
+                int expected_stride = ((trk->par->width * bpc + 15) >> 4)*2;
+                reshuffle_ret = ff_reshuffle_raw_rgb(s, &pkt, trk->par, expected_stride);
+                if (reshuffle_ret < 0)
+                    return reshuffle_ret;
+            } else
+                reshuffle_ret = 0;
+            if (trk->par->format == AV_PIX_FMT_PAL8 && !trk->pal_done) {
+                ret = ff_get_packet_palette(s, opkt, reshuffle_ret, trk->palette);
+                if (ret < 0)
+                    goto fail;
+                if (ret)
+                    trk->pal_done++;
+            } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
+                       (trk->par->format == AV_PIX_FMT_GRAY8 ||
+                       trk->par->format == AV_PIX_FMT_MONOBLACK)) {
+                for (i = 0; i < pkt->size; i++)
+                    pkt->data[i] = ~pkt->data[i];
+            }
+            if (reshuffle_ret) {
+                ret = mov_write_single_packet(s, pkt);
+fail:
+                if (reshuffle_ret)
+                    av_packet_free(&pkt);
+                return ret;
+            }
+        }
+
         return mov_write_single_packet(s, pkt);
     }
 }
@@ -4757,16 +5045,16 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
     track->mode = mov->mode;
     track->tag = MKTAG('t','e','x','t');
     track->timescale = MOV_TIMESCALE;
-    track->enc = avcodec_alloc_context3(NULL);
-    if (!track->enc)
+    track->par = avcodec_parameters_alloc();
+    if (!track->par)
         return AVERROR(ENOMEM);
-    track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    track->par->codec_type = AVMEDIA_TYPE_SUBTITLE;
 #if 0
     // These properties are required to make QT recognize the chapter track
     uint8_t chapter_properties[43] = { 0, 0, 0, 0, 0, 0, 0, 1, };
-    if (ff_alloc_extradata(track->enc, sizeof(chapter_properties)))
+    if (ff_alloc_extradata(track->par, sizeof(chapter_properties)))
         return AVERROR(ENOMEM);
-    memcpy(track->enc->extradata, chapter_properties, sizeof(chapter_properties));
+    memcpy(track->par->extradata, chapter_properties, sizeof(chapter_properties));
 #else
     if (avio_open_dyn_buf(&pb) >= 0) {
         int size;
@@ -4805,8 +5093,8 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
         avio_w8(pb, 0x00);   // font name length
 
         if ((size = avio_close_dyn_buf(pb, &buf)) > 0) {
-            track->enc->extradata = buf;
-            track->enc->extradata_size = size;
+            track->par->extradata = buf;
+            track->par->extradata_size = size;
         } else {
             av_freep(&buf);
         }
@@ -4822,7 +5110,7 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
         pkt.duration = end - pkt.dts;
 
         if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
-            const char encd[12] = {
+            static const char encd[12] = {
                 0x00, 0x00, 0x00, 0x0C,
                 'e',  'n',  'c',  'd',
                 0x00, 0x00, 0x01, 0x00 };
@@ -4842,21 +5130,25 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum)
     return 0;
 }
 
-static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, const char *tcstr)
+
+static int mov_check_timecode_track(AVFormatContext *s, AVTimecode *tc, int src_index, const char *tcstr)
+{
+    int ret;
+
+    /* compute the frame number */
+    ret = av_timecode_init_from_string(tc, find_fps(s,  s->streams[src_index]), tcstr, s);
+    return ret;
+}
+
+static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, AVTimecode tc)
 {
     int ret;
     MOVMuxContext *mov  = s->priv_data;
     MOVTrack *track     = &mov->tracks[index];
     AVStream *src_st    = s->streams[src_index];
-    AVTimecode tc;
     AVPacket pkt    = {.stream_index = index, .flags = AV_PKT_FLAG_KEY, .size = 4};
     AVRational rate = find_fps(s, src_st);
 
-    /* compute the frame number */
-    ret = av_timecode_init_from_string(&tc, rate, tcstr, s);
-    if (ret < 0)
-        return ret;
-
     /* tmcd track based on video stream */
     track->mode      = mov->mode;
     track->tag       = MKTAG('t','m','c','d');
@@ -4869,12 +5161,12 @@ static int mov_create_timecode_track(AVFormatContext *s, int index, int src_inde
     track->st = src_st;
 
     /* encode context: tmcd data stream */
-    track->enc = avcodec_alloc_context3(NULL);
-    if (!track->enc)
+    track->par = avcodec_parameters_alloc();
+    if (!track->par)
         return AVERROR(ENOMEM);
-    track->enc->codec_type = AVMEDIA_TYPE_DATA;
-    track->enc->codec_tag  = track->tag;
-    track->enc->time_base  = av_inv_q(rate);
+    track->par->codec_type = AVMEDIA_TYPE_DATA;
+    track->par->codec_tag  = track->tag;
+    track->st->avg_frame_rate = av_inv_q(rate);
 
     /* the tmcd track just contains one packet with the frame number */
     pkt.data = av_malloc(pkt.size);
@@ -4912,15 +5204,15 @@ static void enable_tracks(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
 
-        if (st->codec->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
-            st->codec->codec_type >= AVMEDIA_TYPE_NB)
+        if (st->codecpar->codec_type <= AVMEDIA_TYPE_UNKNOWN ||
+            st->codecpar->codec_type >= AVMEDIA_TYPE_NB)
             continue;
 
-        if (first[st->codec->codec_type] < 0)
-            first[st->codec->codec_type] = i;
+        if (first[st->codecpar->codec_type] < 0)
+            first[st->codecpar->codec_type] = i;
         if (st->disposition & AV_DISPOSITION_DEFAULT) {
             mov->tracks[i].flags |= MOV_TRACK_ENABLED;
-            enabled[st->codec->codec_type]++;
+            enabled[st->codecpar->codec_type]++;
         }
     }
 
@@ -4944,16 +5236,16 @@ static void mov_free(AVFormatContext *s)
     int i;
 
     if (mov->chapter_track) {
-        if (mov->tracks[mov->chapter_track].enc)
-            av_freep(&mov->tracks[mov->chapter_track].enc->extradata);
-        av_freep(&mov->tracks[mov->chapter_track].enc);
+        if (mov->tracks[mov->chapter_track].par)
+            av_freep(&mov->tracks[mov->chapter_track].par->extradata);
+        av_freep(&mov->tracks[mov->chapter_track].par);
     }
 
     for (i = 0; i < mov->nb_streams; i++) {
         if (mov->tracks[i].tag == MKTAG('r','t','p',' '))
             ff_mov_close_hinting(&mov->tracks[i]);
         else if (mov->tracks[i].tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd)
-            av_freep(&mov->tracks[i].enc);
+            av_freep(&mov->tracks[i].par);
         av_freep(&mov->tracks[i].cluster);
         av_freep(&mov->tracks[i].frag_info);
 
@@ -4988,7 +5280,7 @@ static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
     int i, width = 720, height = 480;
     int have_palette = 0, have_size = 0;
     uint32_t palette[16];
-    char *cur = st->codec->extradata;
+    char *cur = st->codecpar->extradata;
 
     while (cur && *cur) {
         if (strncmp("palette:", cur, 8) == 0) {
@@ -5025,8 +5317,8 @@ static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track,
         }
         track->vos_len = 16 * 4;
     }
-    st->codec->width = width;
-    st->codec->height = track->height = height;
+    st->codecpar->width = width;
+    st->codecpar->height = track->height = height;
 
     return 0;
 }
@@ -5132,29 +5424,34 @@ static int mov_write_header(AVFormatContext *s)
         hint_track = mov->nb_streams;
         for (i = 0; i < s->nb_streams; i++) {
             AVStream *st = s->streams[i];
-            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
-                st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
+                st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                 mov->nb_streams++;
             }
         }
     }
 
-    if (mov->mode == MODE_MOV) {
+    if (mov->mode == MODE_MOV || mov->mode == MODE_MP4) {
         tmcd_track = mov->nb_streams;
 
         /* +1 tmcd track for each video stream with a timecode */
         for (i = 0; i < s->nb_streams; i++) {
             AVStream *st = s->streams[i];
-            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
-                (global_tcr || av_dict_get(st->metadata, "timecode", NULL, 0)))
-                mov->nb_meta_tmcd++;
+            t = global_tcr;
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+                (t || (t=av_dict_get(st->metadata, "timecode", NULL, 0)))) {
+                AVTimecode tc;
+                ret = mov_check_timecode_track(s, &tc, i, t->value);
+                if (ret >= 0)
+                    mov->nb_meta_tmcd++;
+            }
         }
 
         /* check if there is already a tmcd track to remux */
         if (mov->nb_meta_tmcd) {
             for (i = 0; i < s->nb_streams; i++) {
                 AVStream *st = s->streams[i];
-                if (st->codec->codec_tag == MKTAG('t','m','c','d')) {
+                if (st->codecpar->codec_tag == MKTAG('t','m','c','d')) {
                     av_log(s, AV_LOG_WARNING, "You requested a copy of the original timecode track "
                            "so timecode metadata are now ignored\n");
                     mov->nb_meta_tmcd = 0;
@@ -5202,7 +5499,7 @@ static int mov_write_header(AVFormatContext *s)
         AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0);
 
         track->st  = st;
-        track->enc = st->codec;
+        track->par = st->codecpar;
         track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
         if (track->language < 0)
             track->language = 0;
@@ -5211,7 +5508,7 @@ static int mov_write_header(AVFormatContext *s)
         if (!track->tag) {
             av_log(s, AV_LOG_ERROR, "Could not find tag for codec %s in stream #%d, "
                    "codec not currently supported in container\n",
-                   avcodec_get_name(st->codec->codec_id), i);
+                   avcodec_get_name(st->codecpar->codec_id), i);
             ret = AVERROR(EINVAL);
             goto error;
         }
@@ -5221,11 +5518,11 @@ static int mov_write_header(AVFormatContext *s)
         track->start_dts  = AV_NOPTS_VALUE;
         track->start_cts  = AV_NOPTS_VALUE;
         track->end_pts    = AV_NOPTS_VALUE;
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
                 track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||
                 track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) {
-                if (st->codec->width != 720 || (st->codec->height != 608 && st->codec->height != 512)) {
+                if (st->codecpar->width != 720 || (st->codecpar->height != 608 && st->codecpar->height != 512)) {
                     av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n");
                     ret = AVERROR(EINVAL);
                     goto error;
@@ -5239,8 +5536,8 @@ static int mov_write_header(AVFormatContext *s)
                 while(track->timescale < 10000)
                     track->timescale *= 2;
             }
-            if (st->codec->width > 65535 || st->codec->height > 65535) {
-                av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codec->width, st->codec->height);
+            if (st->codecpar->width > 65535 || st->codecpar->height > 65535) {
+                av_log(s, AV_LOG_ERROR, "Resolution %dx%d too large for mov/mp4\n", st->codecpar->width, st->codecpar->height);
                 ret = AVERROR(EINVAL);
                 goto error;
             }
@@ -5249,50 +5546,75 @@ static int mov_write_header(AVFormatContext *s)
                        "WARNING codec timebase is very high. If duration is too long,\n"
                        "file may not be playable by quicktime. Specify a shorter timebase\n"
                        "or choose different container.\n");
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            track->timescale = st->codec->sample_rate;
-            if (!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) {
+            if (track->mode == MODE_MOV &&
+                track->par->codec_id == AV_CODEC_ID_RAWVIDEO &&
+                track->tag == MKTAG('r','a','w',' ')) {
+                enum AVPixelFormat pix_fmt = track->par->format;
+                if (pix_fmt == AV_PIX_FMT_NONE && track->par->bits_per_coded_sample == 1)
+                    pix_fmt = AV_PIX_FMT_MONOWHITE;
+                track->is_unaligned_qt_rgb =
+                        pix_fmt == AV_PIX_FMT_RGB24 ||
+                        pix_fmt == AV_PIX_FMT_BGR24 ||
+                        pix_fmt == AV_PIX_FMT_PAL8 ||
+                        pix_fmt == AV_PIX_FMT_GRAY8 ||
+                        pix_fmt == AV_PIX_FMT_MONOWHITE ||
+                        pix_fmt == AV_PIX_FMT_MONOBLACK;
+            }
+            if (track->mode == MODE_MP4 &&
+                track->par->codec_id == AV_CODEC_ID_VP9) {
+                if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
+                    av_log(s, AV_LOG_ERROR,
+                           "VP9 in MP4 support is experimental, add "
+                           "'-strict %d' if you want to use it.\n",
+                           FF_COMPLIANCE_EXPERIMENTAL);
+                    ret = AVERROR_EXPERIMENTAL;
+                    goto error;
+                }
+            }
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            track->timescale = st->codecpar->sample_rate;
+            if (!st->codecpar->frame_size && !av_get_bits_per_sample(st->codecpar->codec_id)) {
                 av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i);
                 track->audio_vbr = 1;
-            }else if (st->codec->codec_id == AV_CODEC_ID_ADPCM_MS ||
-                     st->codec->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
-                     st->codec->codec_id == AV_CODEC_ID_ILBC){
-                if (!st->codec->block_align) {
+            }else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS ||
+                     st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
+                     st->codecpar->codec_id == AV_CODEC_ID_ILBC){
+                if (!st->codecpar->block_align) {
                     av_log(s, AV_LOG_ERROR, "track %d: codec block align is not set for adpcm\n", i);
                     ret = AVERROR(EINVAL);
                     goto error;
                 }
-                track->sample_size = st->codec->block_align;
-            }else if (st->codec->frame_size > 1){ /* assume compressed audio */
+                track->sample_size = st->codecpar->block_align;
+            }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */
                 track->audio_vbr = 1;
             }else{
-                track->sample_size = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels;
+                track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) * st->codecpar->channels;
             }
-            if (st->codec->codec_id == AV_CODEC_ID_ILBC ||
-                st->codec->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_ILBC ||
+                st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) {
                 track->audio_vbr = 1;
             }
             if (track->mode != MODE_MOV &&
-                track->enc->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
+                track->par->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) {
                 if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
                     av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not standard, to mux anyway set strict to -1\n",
-                        i, track->enc->sample_rate);
+                        i, track->par->sample_rate);
                     ret = AVERROR(EINVAL);
                     goto error;
                 } else {
                     av_log(s, AV_LOG_WARNING, "track %d: muxing mp3 at %dhz is not standard in MP4\n",
-                           i, track->enc->sample_rate);
+                           i, track->par->sample_rate);
                 }
             }
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
             track->timescale = st->time_base.den;
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
             track->timescale = st->time_base.den;
         } else {
             track->timescale = MOV_TIMESCALE;
         }
         if (!track->height)
-            track->height = st->codec->height;
+            track->height = st->codecpar->height;
         /* The ism specific timescale isn't mandatory, but is assumed by
          * some tools, such as mp4split. */
         if (mov->mode == MODE_ISM)
@@ -5301,23 +5623,23 @@ static int mov_write_header(AVFormatContext *s)
         avpriv_set_pts_info(st, 64, 1, track->timescale);
 
         /* copy extradata if it exists */
-        if (st->codec->extradata_size) {
-            if (st->codec->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
+        if (st->codecpar->extradata_size) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE)
                 mov_create_dvd_sub_decoder_specific_info(track, st);
-            else if (!TAG_IS_AVCI(track->tag) && st->codec->codec_id != AV_CODEC_ID_DNXHD) {
-                track->vos_len  = st->codec->extradata_size;
+            else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) {
+                track->vos_len  = st->codecpar->extradata_size;
                 track->vos_data = av_malloc(track->vos_len);
                 if (!track->vos_data) {
                     ret = AVERROR(ENOMEM);
                     goto error;
                 }
-                memcpy(track->vos_data, st->codec->extradata, track->vos_len);
+                memcpy(track->vos_data, st->codecpar->extradata, track->vos_len);
             }
         }
 
         if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
             ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
-                track->enc->codec_id == AV_CODEC_ID_H264, s->flags & AVFMT_FLAG_BITEXACT);
+                track->par->codec_id == AV_CODEC_ID_H264, s->flags & AVFMT_FLAG_BITEXACT);
             if (ret) {
                 goto error;
             }
@@ -5329,8 +5651,8 @@ static int mov_write_header(AVFormatContext *s)
         AVStream *st= s->streams[i];
         MOVTrack *track= &mov->tracks[i];
 
-        if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO ||
-            track->enc->channel_layout != AV_CH_LAYOUT_MONO)
+        if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
+            track->par->channel_layout != AV_CH_LAYOUT_MONO)
             continue;
 
         for (j = 0; j < s->nb_streams; j++) {
@@ -5339,8 +5661,8 @@ static int mov_write_header(AVFormatContext *s)
             if (j == i)
                 continue;
 
-            if (stj->codec->codec_type != AVMEDIA_TYPE_AUDIO ||
-                trackj->enc->channel_layout != AV_CH_LAYOUT_MONO ||
+            if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
+                trackj->par->channel_layout != AV_CH_LAYOUT_MONO ||
                 trackj->language != track->language ||
                 trackj->tag != track->tag
             )
@@ -5382,8 +5704,8 @@ static int mov_write_header(AVFormatContext *s)
         /* Initialize the hint tracks for each audio and video stream */
         for (i = 0; i < s->nb_streams; i++) {
             AVStream *st = s->streams[i];
-            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
-                st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
+                st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
                 if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0)
                     goto error;
                 hint_track++;
@@ -5397,12 +5719,15 @@ static int mov_write_header(AVFormatContext *s)
             AVStream *st = s->streams[i];
             t = global_tcr;
 
-            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+                AVTimecode tc;
                 if (!t)
                     t = av_dict_get(st->metadata, "timecode", NULL, 0);
                 if (!t)
                     continue;
-                if ((ret = mov_create_timecode_track(s, tmcd_track, i, t->value)) < 0)
+                if (mov_check_timecode_track(s, &tc, i, t->value) < 0)
+                    continue;
+                if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0)
                     goto error;
                 tmcd_track++;
             }
@@ -5581,7 +5906,7 @@ static int mov_write_trailer(AVFormatContext *s)
      */
     for (i = 0; i < mov->nb_streams; i++) {
         MOVTrack *trk = &mov->tracks[i];
-        if (trk->enc->codec_id == AV_CODEC_ID_MOV_TEXT &&
+        if (trk->par->codec_id == AV_CODEC_ID_MOV_TEXT &&
             !trk->last_sample_is_subtitle_end) {
             mov_write_subtitle_end_packet(s, i, trk->track_duration);
             trk->last_sample_is_subtitle_end = 1;
@@ -5620,11 +5945,11 @@ static int mov_write_trailer(AVFormatContext *s)
         if (mov->flags & FF_MOV_FLAG_FASTSTART) {
             av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
             res = shift_data(s);
-            if (res == 0) {
-                avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
-                if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
-                    goto error;
-            }
+            if (res < 0)
+                goto error;
+            avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
+            if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
+                goto error;
         } else if (mov->reserved_moov_size > 0) {
             int64_t size;
             if ((res = mov_write_moov_tag(pb, mov, s)) < 0)
@@ -5649,16 +5974,19 @@ static int mov_write_trailer(AVFormatContext *s)
         for (i = 0; i < mov->nb_streams; i++)
            mov->tracks[i].data_offset = 0;
         if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) {
+            int64_t end;
             av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
             res = shift_data(s);
-            if (res == 0) {
-                int64_t end = avio_tell(pb);
-                avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
-                mov_write_sidx_tags(pb, mov, -1, 0);
-                avio_seek(pb, end, SEEK_SET);
-                mov_write_mfra_tag(pb, mov);
-            }
+            if (res < 0)
+                goto error;
+            end = avio_tell(pb);
+            avio_seek(pb, mov->reserved_header_pos, SEEK_SET);
+            mov_write_sidx_tags(pb, mov, -1, 0);
+            avio_seek(pb, end, SEEK_SET);
+            avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
+            mov_write_mfra_tag(pb, mov);
         } else {
+            avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
             mov_write_mfra_tag(pb, mov);
         }
     }
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index deb90fe..6e9f5ac 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -101,7 +101,7 @@ typedef struct MOVTrack {
     int         track_id;
     int         tag; ///< stsd fourcc
     AVStream        *st;
-    AVCodecContext *enc;
+    AVCodecParameters *par;
     int multichannel_as_mono;
 
     int         vos_len;
@@ -115,6 +115,7 @@ typedef struct MOVTrack {
     int64_t     start_dts;
     int64_t     start_cts;
     int64_t     end_pts;
+    int         end_reliable;
 
     int         hint_track;   ///< the track that hints this track, -1 if no hint track is set
     int         src_track;    ///< the track that this hint (or tmcd) track describes
@@ -152,6 +153,11 @@ typedef struct MOVTrack {
     void       *eac3_priv;
 
     MOVMuxCencContext cenc;
+
+    uint32_t palette[AVPALETTE_COUNT];
+    int pal_done;
+
+    int is_unaligned_qt_rgb;
 } MOVTrack;
 
 typedef enum {
@@ -228,6 +234,7 @@ typedef struct MOVMuxContext {
 #define FF_MOV_FLAG_GLOBAL_SIDX           (1 << 14)
 #define FF_MOV_FLAG_WRITE_COLR            (1 << 15)
 #define FF_MOV_FLAG_WRITE_GAMA            (1 << 16)
+#define FF_MOV_FLAG_USE_MDTA              (1 << 17)
 
 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);
 
diff --git a/libavformat/movenchint.c b/libavformat/movenchint.c
index 9e667ed..964026e 100644
--- a/libavformat/movenchint.c
+++ b/libavformat/movenchint.c
@@ -37,11 +37,11 @@ int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index)
     track->tag = MKTAG('r','t','p',' ');
     track->src_track = src_index;
 
-    track->enc = avcodec_alloc_context3(NULL);
-    if (!track->enc)
+    track->par = avcodec_parameters_alloc();
+    if (!track->par)
         goto fail;
-    track->enc->codec_type = AVMEDIA_TYPE_DATA;
-    track->enc->codec_tag  = track->tag;
+    track->par->codec_type = AVMEDIA_TYPE_DATA;
+    track->par->codec_tag  = track->tag;
 
     ret = ff_rtp_chain_mux_open(&track->rtp_ctx, s, src_st, NULL,
                                 RTP_MAX_PACKET_SIZE, src_index);
@@ -58,7 +58,7 @@ int ff_mov_init_hinting(AVFormatContext *s, int index, int src_index)
 fail:
     av_log(s, AV_LOG_WARNING,
            "Unable to initialize hinting of stream %d\n", src_index);
-    av_freep(&track->enc);
+    avcodec_parameters_free(&track->par);
     /* Set a default timescale, to avoid crashes in av_dump_format */
     track->timescale = 90000;
     return ret;
@@ -460,7 +460,7 @@ void ff_mov_close_hinting(MOVTrack *track)
 {
     AVFormatContext *rtp_ctx = track->rtp_ctx;
 
-    av_freep(&track->enc);
+    avcodec_parameters_free(&track->par);
     sample_queue_free(&track->sample_queue);
     if (!rtp_ctx)
         return;
diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c
index c76b21e..56c7f8c 100644
--- a/libavformat/mp3dec.c
+++ b/libavformat/mp3dec.c
@@ -57,6 +57,11 @@ typedef struct {
     int is_cbr;
 } MP3DecContext;
 
+enum CheckRet {
+    CHECK_WRONG_HEADER = -1,
+    CHECK_SEEK_FAILED  = -2,
+};
+
 static int check(AVIOContext *pb, int64_t pos, uint32_t *header);
 
 /* mp3 read */
@@ -64,6 +69,7 @@ static int check(AVIOContext *pb, int64_t pos, uint32_t *header);
 static int mp3_read_probe(AVProbeData *p)
 {
     int max_frames, first_frames = 0;
+    int whole_used = 0;
     int frames, ret;
     uint32_t header;
     const uint8_t *buf, *buf0, *buf2, *end;
@@ -88,8 +94,11 @@ static int mp3_read_probe(AVProbeData *p)
             buf2 += h.frame_size;
         }
         max_frames = FFMAX(max_frames, frames);
-        if(buf == buf0)
+        if(buf == buf0) {
             first_frames= frames;
+            if (buf2 == end + sizeof(uint32_t))
+                whole_used = 1;
+        }
     }
     // keep this in sync with ac3 probe, both need to avoid
     // issues with MPEG-files!
@@ -98,6 +107,7 @@ static int mp3_read_probe(AVProbeData *p)
     else if(max_frames>=4 && max_frames >= p->buf_size/10000) return AVPROBE_SCORE_EXTENSION / 2;
     else if(ff_id3v2_match(buf0, ID3v2_DEFAULT_MAGIC) && 2*ff_id3v2_tag_len(buf0) >= p->buf_size)
                            return p->buf_size < PROBE_BUF_MAX ? AVPROBE_SCORE_EXTENSION / 4 : AVPROBE_SCORE_EXTENSION - 2;
+    else if(first_frames > 1 && whole_used) return 5;
     else if(max_frames>=1 && max_frames >= p->buf_size/10000) return 1;
     else                   return 0;
 //mpegps_mp3_unrecognized_format.mpg has max_frames=3
@@ -326,7 +336,7 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base)
         st->duration = av_rescale_q(mp3->frames, (AVRational){spf, c.sample_rate},
                                     st->time_base);
     if (mp3->header_filesize && mp3->frames && !mp3->is_cbr)
-        st->codec->bit_rate = av_rescale(mp3->header_filesize, 8 * c.sample_rate, mp3->frames * (int64_t)spf);
+        st->codecpar->bit_rate = av_rescale(mp3->header_filesize, 8 * c.sample_rate, mp3->frames * (int64_t)spf);
 
     return 0;
 }
@@ -343,8 +353,8 @@ static int mp3_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_MP3;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_MP3;
     st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
     st->start_time = 0;
 
@@ -375,17 +385,30 @@ static int mp3_read_header(AVFormatContext *s)
             ffio_ensure_seekback(s->pb, i + 1024 + 4);
         frame_size = check(s->pb, off + i, &header);
         if (frame_size > 0) {
-            avio_seek(s->pb, off, SEEK_SET);
+            ret = avio_seek(s->pb, off, SEEK_SET);
+            if (ret < 0)
+                return ret;
             ffio_ensure_seekback(s->pb, i + 1024 + frame_size + 4);
-            if (check(s->pb, off + i + frame_size, &header2) >= 0 &&
+            ret = check(s->pb, off + i + frame_size, &header2);
+            if (ret >= 0 &&
                 (header & SAME_HEADER_MASK) == (header2 & SAME_HEADER_MASK))
             {
-                av_log(s, AV_LOG_INFO, "Skipping %d bytes of junk at %"PRId64".\n", i, off);
-                avio_seek(s->pb, off + i, SEEK_SET);
+                av_log(s, i > 0 ? AV_LOG_INFO : AV_LOG_VERBOSE, "Skipping %d bytes of junk at %"PRId64".\n", i, off);
+                ret = avio_seek(s->pb, off + i, SEEK_SET);
+                if (ret < 0)
+                    return ret;
                 break;
+            } else if (ret == CHECK_SEEK_FAILED) {
+                av_log(s, AV_LOG_ERROR, "Invalid frame size (%d): Could not seek to %"PRId64".\n", frame_size, off + i + frame_size);
+                return AVERROR(EINVAL);
             }
+        } else if (frame_size == CHECK_SEEK_FAILED) {
+            av_log(s, AV_LOG_ERROR, "Failed to read frame size: Could not seek to %"PRId64".\n", (int64_t) (i + 1024 + frame_size + 4));
+            return AVERROR(EINVAL);
         }
-        avio_seek(s->pb, off, SEEK_SET);
+        ret = avio_seek(s->pb, off, SEEK_SET);
+        if (ret < 0)
+            return ret;
     }
 
     // the seek index is relative to the end of the xing vbr headers
@@ -427,16 +450,21 @@ static int mp3_read_packet(AVFormatContext *s, AVPacket *pkt)
 static int check(AVIOContext *pb, int64_t pos, uint32_t *ret_header)
 {
     int64_t ret = avio_seek(pb, pos, SEEK_SET);
+    uint8_t header_buf[4];
     unsigned header;
     MPADecodeHeader sd;
     if (ret < 0)
-        return ret;
+        return CHECK_SEEK_FAILED;
 
-    header = avio_rb32(pb);
+    ret = avio_read(pb, &header_buf[0], 4);
+    if (ret < 0)
+        return CHECK_SEEK_FAILED;
+
+    header = AV_RB32(&header_buf[0]);
     if (ff_mpa_check_header(header) < 0)
-        return -1;
+        return CHECK_WRONG_HEADER;
     if (avpriv_mpegaudio_decode_header(&sd, header) == 1)
-        return -1;
+        return CHECK_WRONG_HEADER;
 
     if (ret_header)
         *ret_header = header;
@@ -468,8 +496,14 @@ static int64_t mp3_sync(AVFormatContext *s, int64_t target_pos, int flags)
 
         for(j=0; j<MIN_VALID; j++) {
             ret = check(s->pb, pos, NULL);
-            if(ret < 0)
-                break;
+            if(ret < 0) {
+                if (ret == CHECK_WRONG_HEADER) {
+                    break;
+                } else if (ret == CHECK_SEEK_FAILED) {
+                    av_log(s, AV_LOG_ERROR, "Could not seek to %"PRId64".\n", pos);
+                    return AVERROR(EINVAL);
+                }
+            }
             if ((target_pos - pos)*dir <= 0 && abs(MIN_VALID/2-j) < score) {
                 candidate = pos;
                 score = abs(MIN_VALID/2-j);
diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c
index 71f5178..de63401 100644
--- a/libavformat/mp3enc.c
+++ b/libavformat/mp3enc.c
@@ -129,7 +129,7 @@ static const uint8_t xing_offtbl[2][2] = {{32, 17}, {17, 9}};
 static int mp3_write_xing(AVFormatContext *s)
 {
     MP3Context       *mp3 = s->priv_data;
-    AVCodecContext *codec = s->streams[mp3->audio_stream_idx]->codec;
+    AVCodecParameters *par = s->streams[mp3->audio_stream_idx]->codecpar;
     AVDictionaryEntry *enc = av_dict_get(s->streams[mp3->audio_stream_idx]->metadata, "encoder", NULL, 0);
     AVIOContext *dyn_ctx;
     int32_t        header;
@@ -148,9 +148,9 @@ static int mp3_write_xing(AVFormatContext *s)
     for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) {
         const uint16_t base_freq = avpriv_mpa_freq_tab[i];
 
-        if      (codec->sample_rate == base_freq)     ver = 0x3; // MPEG 1
-        else if (codec->sample_rate == base_freq / 2) ver = 0x2; // MPEG 2
-        else if (codec->sample_rate == base_freq / 4) ver = 0x0; // MPEG 2.5
+        if      (par->sample_rate == base_freq)     ver = 0x3; // MPEG 1
+        else if (par->sample_rate == base_freq / 2) ver = 0x2; // MPEG 2
+        else if (par->sample_rate == base_freq / 4) ver = 0x0; // MPEG 2.5
         else continue;
 
         srate_idx = i;
@@ -161,7 +161,7 @@ static int mp3_write_xing(AVFormatContext *s)
         return -1;
     }
 
-    switch (codec->channels) {
+    switch (par->channels) {
     case 1:  channels = MPA_MONO;                                          break;
     case 2:  channels = MPA_STEREO;                                        break;
     default: av_log(s, AV_LOG_WARNING, "Unsupported number of channels, "
@@ -177,7 +177,7 @@ static int mp3_write_xing(AVFormatContext *s)
 
     for (bitrate_idx = 1; bitrate_idx < 15; bitrate_idx++) {
         int bit_rate = 1000 * avpriv_mpa_bitrate_tab[ver != 3][3 - 1][bitrate_idx];
-        int error    = FFABS(bit_rate - codec->bit_rate);
+        int error    = FFABS(bit_rate - par->bit_rate);
 
         if (error < best_bitrate_error) {
             best_bitrate_error = error;
@@ -249,10 +249,10 @@ static int mp3_write_xing(AVFormatContext *s)
     avio_w8(dyn_ctx, 0);      // unknown abr/minimal bitrate
 
     // encoder delay
-    if (codec->initial_padding - 528 - 1 >= 1 << 12) {
+    if (par->initial_padding - 528 - 1 >= 1 << 12) {
         av_log(s, AV_LOG_WARNING, "Too many samples of initial padding.\n");
     }
-    avio_wb24(dyn_ctx, FFMAX(codec->initial_padding - 528 - 1, 0)<<12);
+    avio_wb24(dyn_ctx, FFMAX(par->initial_padding - 528 - 1, 0)<<12);
 
     avio_w8(dyn_ctx,   0); // misc
     avio_w8(dyn_ctx,   0); // mp3gain
@@ -575,14 +575,14 @@ static int mp3_write_header(struct AVFormatContext *s)
     mp3->audio_stream_idx = -1;
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            if (mp3->audio_stream_idx >= 0 || st->codec->codec_id != AV_CODEC_ID_MP3) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (mp3->audio_stream_idx >= 0 || st->codecpar->codec_id != AV_CODEC_ID_MP3) {
                 av_log(s, AV_LOG_ERROR, "Invalid audio stream. Exactly one MP3 "
                        "audio stream is required.\n");
                 return AVERROR(EINVAL);
             }
             mp3->audio_stream_idx = i;
-        } else if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO) {
+        } else if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO) {
             av_log(s, AV_LOG_ERROR, "Only audio streams and pictures are allowed in MP3.\n");
             return AVERROR(EINVAL);
         }
diff --git a/libavformat/mpc.c b/libavformat/mpc.c
index d0c1b85..4bd1f50 100644
--- a/libavformat/mpc.c
+++ b/libavformat/mpc.c
@@ -20,7 +20,7 @@
  */
 
 #include "libavutil/channel_layout.h"
-#include "libavcodec/get_bits.h"
+
 #include "avformat.h"
 #include "internal.h"
 #include "apetag.h"
@@ -89,16 +89,16 @@ static int mpc_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_MUSEPACK7;
-    st->codec->channels = 2;
-    st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
-    st->codec->bits_per_coded_sample = 16;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK7;
+    st->codecpar->channels = 2;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+    st->codecpar->bits_per_coded_sample = 16;
 
-    if (ff_get_extradata(st->codec, s->pb, 16) < 0)
+    if (ff_get_extradata(s, st->codecpar, s->pb, 16) < 0)
         return AVERROR(ENOMEM);
-    st->codec->sample_rate = mpc_rate[st->codec->extradata[2] & 3];
-    avpriv_set_pts_info(st, 32, MPC_FRAMESIZE, st->codec->sample_rate);
+    st->codecpar->sample_rate = mpc_rate[st->codecpar->extradata[2] & 3];
+    avpriv_set_pts_info(st, 32, MPC_FRAMESIZE, st->codecpar->sample_rate);
     /* scan for seekpoints */
     st->start_time = 0;
     st->duration = c->fcount;
diff --git a/libavformat/mpc8.c b/libavformat/mpc8.c
index bf597b8..05d0c1a 100644
--- a/libavformat/mpc8.c
+++ b/libavformat/mpc8.c
@@ -248,18 +248,18 @@ static int mpc8_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_MUSEPACK8;
-    st->codec->bits_per_coded_sample = 16;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK8;
+    st->codecpar->bits_per_coded_sample = 16;
 
-    if (ff_get_extradata(st->codec, pb, 2) < 0)
+    if (ff_get_extradata(s, st->codecpar, pb, 2) < 0)
         return AVERROR(ENOMEM);
 
-    st->codec->channels = (st->codec->extradata[1] >> 4) + 1;
-    st->codec->sample_rate = mpc8_rate[st->codec->extradata[0] >> 5];
-    avpriv_set_pts_info(st, 32, 1152  << (st->codec->extradata[1]&3)*2, st->codec->sample_rate);
+    st->codecpar->channels = (st->codecpar->extradata[1] >> 4) + 1;
+    st->codecpar->sample_rate = mpc8_rate[st->codecpar->extradata[0] >> 5];
+    avpriv_set_pts_info(st, 32, 1152  << (st->codecpar->extradata[1]&3)*2, st->codecpar->sample_rate);
     st->start_time = 0;
-    st->duration = c->samples / (1152 << (st->codec->extradata[1]&3)*2);
+    st->duration = c->samples / (1152 << (st->codecpar->extradata[1]&3)*2);
     size -= avio_tell(pb) - pos;
     if (size > 0)
         avio_skip(pb, size);
diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index 69685cf..1c441c5 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -1,5 +1,5 @@
 /*
- * MPEG1/2 demuxer
+ * MPEG-1/2 demuxer
  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
  *
  * This file is part of FFmpeg.
@@ -371,7 +371,7 @@ redo:
             goto error_redo;
         c = avio_r8(s->pb);
         len--;
-        /* XXX: for mpeg1, should test only bit 7 */
+        /* XXX: for MPEG-1, should test only bit 7 */
         if (c != 0xff)
             break;
     }
@@ -568,7 +568,7 @@ redo:
         codec_id = AV_CODEC_ID_DTS;
     } else if (startcode >= 0xa0 && startcode <= 0xaf) {
         type     = AVMEDIA_TYPE_AUDIO;
-        if (lpcm_header_len == 6) {
+        if (lpcm_header_len == 6 || startcode == 0xa1) {
             codec_id = AV_CODEC_ID_MLP;
         } else {
             codec_id = AV_CODEC_ID_PCM_DVD;
@@ -597,13 +597,13 @@ skip:
     if (!st)
         goto skip;
     st->id                = startcode;
-    st->codec->codec_type = type;
-    st->codec->codec_id   = codec_id;
-    if (   st->codec->codec_id == AV_CODEC_ID_PCM_MULAW
-        || st->codec->codec_id == AV_CODEC_ID_PCM_ALAW) {
-        st->codec->channels = 1;
-        st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-        st->codec->sample_rate = 8000;
+    st->codecpar->codec_type = type;
+    st->codecpar->codec_id   = codec_id;
+    if (   st->codecpar->codec_id == AV_CODEC_ID_PCM_MULAW
+        || st->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW) {
+        st->codecpar->channels = 1;
+        st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+        st->codecpar->sample_rate = 8000;
     }
     st->request_probe     = request_probe;
     st->need_parsing      = AVSTREAM_PARSE_FULL;
@@ -612,7 +612,7 @@ found:
     if (st->discard >= AVDISCARD_ALL)
         goto skip;
     if (startcode >= 0xa0 && startcode <= 0xaf) {
-      if (st->codec->codec_id == AV_CODEC_ID_MLP) {
+      if (st->codecpar->codec_id == AV_CODEC_ID_MLP) {
             if (len < 6)
                 goto skip;
             avio_skip(s->pb, 6);
@@ -732,7 +732,7 @@ static int vobsub_read_header(AVFormatContext *s)
         goto end;
     }
 
-    if ((ret = ff_copy_whitelists(vobsub->sub_ctx, s)) < 0)
+    if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0)
         goto end;
 
     ret = avformat_open_input(&vobsub->sub_ctx, vobsub->sub_name, iformat, NULL);
@@ -791,8 +791,8 @@ static int vobsub_read_header(AVFormatContext *s)
                     goto end;
                 }
                 st->id = stream_id;
-                st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-                st->codec->codec_id   = AV_CODEC_ID_DVD_SUBTITLE;
+                st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+                st->codecpar->codec_id   = AV_CODEC_ID_DVD_SUBTITLE;
                 avpriv_set_pts_info(st, 64, 1, 1000);
                 av_dict_set(&st->metadata, "language", id, 0);
                 if (alt[0])
@@ -869,8 +869,8 @@ static int vobsub_read_header(AVFormatContext *s)
     av_bprint_finalize(&header, &header_str);
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *sub_st = s->streams[i];
-        sub_st->codec->extradata      = av_strdup(header_str);
-        sub_st->codec->extradata_size = header.len;
+        sub_st->codecpar->extradata      = av_strdup(header_str);
+        sub_st->codecpar->extradata_size = header.len;
     }
     av_free(header_str);
 
diff --git a/libavformat/mpeg.h b/libavformat/mpeg.h
index b43517c..617e36c 100644
--- a/libavformat/mpeg.h
+++ b/libavformat/mpeg.h
@@ -1,5 +1,5 @@
 /*
- * MPEG1/2 muxer and demuxer common defines
+ * MPEG-1/2 muxer and demuxer common defines
  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
  *
  * This file is part of FFmpeg.
diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c
index 2e09549..878fa63 100644
--- a/libavformat/mpegenc.c
+++ b/libavformat/mpegenc.c
@@ -1,5 +1,5 @@
 /*
- * MPEG1/2 muxer
+ * MPEG-1/2 muxer
  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
  *
  * This file is part of FFmpeg.
@@ -151,7 +151,7 @@ static int put_system_header(AVFormatContext *ctx, uint8_t *buf,
         put_bits(&pb, 1, 1);
     } else {
         put_bits(&pb, 1, 0); /* variable bitrate */
-        put_bits(&pb, 1, 0); /* non constrainted bit stream */
+        put_bits(&pb, 1, 0); /* nonconstrained bitstream */
     }
 
     if (s->is_vcd || s->is_dvd) {
@@ -348,35 +348,35 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
 
         avpriv_set_pts_info(st, 64, 1, 90000);
 
-        switch (st->codec->codec_type) {
+        switch (st->codecpar->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
             if (!s->is_mpeg2 &&
-                (st->codec->codec_id == AV_CODEC_ID_AC3 ||
-                 st->codec->codec_id == AV_CODEC_ID_DTS ||
-                 st->codec->codec_id == AV_CODEC_ID_PCM_S16BE))
+                (st->codecpar->codec_id == AV_CODEC_ID_AC3 ||
+                 st->codecpar->codec_id == AV_CODEC_ID_DTS ||
+                 st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE))
                  av_log(ctx, AV_LOG_WARNING,
                         "%s in MPEG-1 system streams is not widely supported, "
                         "consider using the vob or the dvd muxer "
                         "to force a MPEG-2 program stream.\n",
-                        avcodec_get_name(st->codec->codec_id));
-            if (st->codec->codec_id == AV_CODEC_ID_AC3) {
+                        avcodec_get_name(st->codecpar->codec_id));
+            if (st->codecpar->codec_id == AV_CODEC_ID_AC3) {
                 stream->id = ac3_id++;
-            } else if (st->codec->codec_id == AV_CODEC_ID_DTS) {
+            } else if (st->codecpar->codec_id == AV_CODEC_ID_DTS) {
                 stream->id = dts_id++;
-            } else if (st->codec->codec_id == AV_CODEC_ID_PCM_S16BE) {
+            } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE) {
                 stream->id = lpcm_id++;
                 for (j = 0; j < 4; j++) {
-                    if (lpcm_freq_tab[j] == st->codec->sample_rate)
+                    if (lpcm_freq_tab[j] == st->codecpar->sample_rate)
                         break;
                 }
                 if (j == 4)
                     goto fail;
-                if (st->codec->channels > 8)
+                if (st->codecpar->channels > 8)
                     return -1;
                 stream->lpcm_header[0] = 0x0c;
-                stream->lpcm_header[1] = (st->codec->channels - 1) | (j << 4);
+                stream->lpcm_header[1] = (st->codecpar->channels - 1) | (j << 4);
                 stream->lpcm_header[2] = 0x80;
-                stream->lpcm_align     = st->codec->channels * 2;
+                stream->lpcm_align     = st->codecpar->channels * 2;
             } else {
                 stream->id = mpa_id++;
             }
@@ -387,7 +387,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
             s->audio_bound++;
             break;
         case AVMEDIA_TYPE_VIDEO:
-            if (st->codec->codec_id == AV_CODEC_ID_H264)
+            if (st->codecpar->codec_id == AV_CODEC_ID_H264)
                 stream->id = h264_id++;
             else
                 stream->id = mpv_id++;
@@ -415,7 +415,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
             break;
         default:
             av_log(ctx, AV_LOG_ERROR, "Invalid media type %s for output stream #%d\n",
-                   av_get_media_type_string(st->codec->codec_type), i);
+                   av_get_media_type_string(st->codecpar->codec_type), i);
             return AVERROR(EINVAL);
         }
         stream->fifo = av_fifo_alloc(16);
@@ -435,7 +435,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
         if (props)
             codec_rate = props->max_bitrate;
         else
-            codec_rate = st->codec->bit_rate;
+            codec_rate = st->codecpar->bit_rate;
 
         if (!codec_rate)
             codec_rate = (1 << 21) * 8 * 50 / ctx->nb_streams;
@@ -444,7 +444,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx)
 
         if ((stream->id & 0xe0) == AUDIO_ID)
             audio_bitrate += codec_rate;
-        else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+        else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
             video_bitrate += codec_rate;
     }
 
@@ -984,7 +984,7 @@ retry:
         /* for subtitle, a single PES packet must be generated,
          * so we flush after every single subtitle packet */
         if (s->packet_size > avail_data && !flush
-            && st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)
+            && st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
             return 0;
         if (avail_data == 0)
             continue;
@@ -1115,7 +1115,7 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt)
     int64_t pts, dts;
     PacketDesc *pkt_desc;
     int preload;
-    const int is_iframe = st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+    const int is_iframe = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
                           (pkt->flags & AV_PKT_FLAG_KEY);
 
     preload = av_rescale(s->preload, 90000, AV_TIME_BASE);
@@ -1190,7 +1190,7 @@ static int mpeg_mux_end(AVFormatContext *ctx)
             break;
     }
 
-    /* End header according to MPEG1 systems standard. We do not write
+    /* End header according to MPEG-1 systems standard. We do not write
      * it as it is usually not needed by decoders and because it
      * complicates MPEG stream concatenation. */
     // avio_wb32(ctx->pb, ISO_11172_END_CODE);
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index 22874e6..b31d233 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -1,5 +1,5 @@
 /*
- * MPEG2 transport stream (aka DVB) demuxer
+ * MPEG-2 transport stream (aka DVB) demuxer
  * Copyright (c) 2002-2003 Fabrice Bellard
  *
  * This file is part of FFmpeg.
@@ -38,8 +38,8 @@
 #include "mpeg.h"
 #include "isom.h"
 
-/* maximum size in which we look for synchronisation if
- * synchronisation is lost */
+/* maximum size in which we look for synchronization if
+ * synchronization is lost */
 #define MAX_RESYNC_SIZE 65536
 
 #define MAX_PES_PAYLOAD 200 * 1024
@@ -235,6 +235,7 @@ typedef struct PESContext {
     int total_size;
     int pes_header_size;
     int extended_stream_id;
+    uint8_t stream_id;
     int64_t pts, dts;
     int64_t ts_packet_pos; /**< position of first TS packet of this PES packet */
     uint8_t header[MAX_PES_HEADER_SIZE];
@@ -445,7 +446,7 @@ static MpegTSFilter *mpegts_open_filter(MpegTSContext *ts, unsigned int pid,
 {
     MpegTSFilter *filter;
 
-    av_log(ts->stream, AV_LOG_TRACE, "Filter: pid=0x%x\n", pid);
+    av_log(ts->stream, AV_LOG_TRACE, "Filter: pid=0x%x type=%d\n", pid, type);
 
     if (pid >= NB_PID_MAX || ts->pids[pid])
         return NULL;
@@ -530,7 +531,7 @@ static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter)
     ts->pids[pid] = NULL;
 }
 
-static int analyze(const uint8_t *buf, int size, int packet_size, int *index,
+static int analyze(const uint8_t *buf, int size, int packet_size,
                    int probe)
 {
     int stat[TS_MAX_PACKET_SIZE];
@@ -541,15 +542,16 @@ static int analyze(const uint8_t *buf, int size, int packet_size, int *index,
     memset(stat, 0, packet_size * sizeof(*stat));
 
     for (i = 0; i < size - 3; i++) {
-        if (buf[i] == 0x47 &&
-            (!probe || (!(buf[i + 1] & 0x80) && buf[i + 3] != 0x47))) {
-            int x = i % packet_size;
-            stat[x]++;
-            stat_all++;
-            if (stat[x] > best_score) {
-                best_score = stat[x];
-                if (index)
-                    *index = x;
+        if (buf[i] == 0x47) {
+            int pid = AV_RB16(buf+1) & 0x1FFF;
+            int asc = buf[i + 3] & 0x30;
+            if (!probe || pid == 0x1FFF || asc) {
+                int x = i % packet_size;
+                stat[x]++;
+                stat_all++;
+                if (stat[x] > best_score) {
+                    best_score = stat[x];
+                }
             }
         }
     }
@@ -565,9 +567,9 @@ static int get_packet_size(const uint8_t *buf, int size)
     if (size < (TS_FEC_PACKET_SIZE * 5 + 1))
         return AVERROR_INVALIDDATA;
 
-    score      = analyze(buf, size, TS_PACKET_SIZE,      NULL, 0);
-    dvhs_score = analyze(buf, size, TS_DVHS_PACKET_SIZE, NULL, 0);
-    fec_score  = analyze(buf, size, TS_FEC_PACKET_SIZE,  NULL, 0);
+    score      = analyze(buf, size, TS_PACKET_SIZE,      0);
+    dvhs_score = analyze(buf, size, TS_DVHS_PACKET_SIZE, 0);
+    fec_score  = analyze(buf, size, TS_FEC_PACKET_SIZE,  0);
     av_log(NULL, AV_LOG_TRACE, "score: %d, dvhs_score: %d, fec_score: %d \n",
             score, dvhs_score, fec_score);
 
@@ -698,6 +700,7 @@ static const StreamType ISO_types[] = {
     { 0x11, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC_LATM   }, /* LATM syntax */
 #endif
     { 0x1b, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264       },
+    { 0x1c, AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC        },
     { 0x20, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264       },
     { 0x21, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_JPEG2000   },
     { 0x24, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC       },
@@ -736,8 +739,10 @@ static const StreamType REGD_types[] = {
     { MKTAG('D', 'T', 'S', '1'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS   },
     { MKTAG('D', 'T', 'S', '2'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS   },
     { MKTAG('D', 'T', 'S', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_DTS   },
+    { MKTAG('E', 'A', 'C', '3'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_EAC3  },
     { MKTAG('H', 'E', 'V', 'C'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_HEVC  },
     { MKTAG('K', 'L', 'V', 'A'), AVMEDIA_TYPE_DATA,  AV_CODEC_ID_SMPTE_KLV },
+    { MKTAG('I', 'D', '3', ' '), AVMEDIA_TYPE_DATA,  AV_CODEC_ID_TIMED_ID3 },
     { MKTAG('V', 'C', '-', '1'), AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1   },
     { MKTAG('O', 'p', 'u', 's'), AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_OPUS  },
     { 0 },
@@ -763,16 +768,15 @@ static void mpegts_find_stream_type(AVStream *st,
                                     uint32_t stream_type,
                                     const StreamType *types)
 {
-    if (avcodec_is_open(st->codec)) {
-        av_log(NULL, AV_LOG_DEBUG, "cannot set stream info, codec is open\n");
-        return;
-    }
-
     for (; types->stream_type; types++)
         if (stream_type == types->stream_type) {
-            st->codec->codec_type = types->codec_type;
-            st->codec->codec_id   = types->codec_id;
-            st->request_probe     = 0;
+            if (st->codecpar->codec_type != types->codec_type ||
+                st->codecpar->codec_id   != types->codec_id) {
+                st->codecpar->codec_type = types->codec_type;
+                st->codecpar->codec_id   = types->codec_id;
+                st->internal->need_context_update = 1;
+            }
+            st->request_probe        = 0;
             return;
         }
 }
@@ -780,18 +784,19 @@ static void mpegts_find_stream_type(AVStream *st,
 static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
                                   uint32_t stream_type, uint32_t prog_reg_desc)
 {
-    int old_codec_type = st->codec->codec_type;
-    int old_codec_id  = st->codec->codec_id;
+    int old_codec_type = st->codecpar->codec_type;
+    int old_codec_id   = st->codecpar->codec_id;
+    int old_codec_tag  = st->codecpar->codec_tag;
 
-    if (avcodec_is_open(st->codec)) {
-        av_log(pes->stream, AV_LOG_DEBUG, "cannot set stream info, codec is open\n");
+    if (avcodec_is_open(st->internal->avctx)) {
+        av_log(pes->stream, AV_LOG_DEBUG, "cannot set stream info, internal codec is open\n");
         return 0;
     }
 
     avpriv_set_pts_info(st, 33, 1, 90000);
     st->priv_data         = pes;
-    st->codec->codec_type = AVMEDIA_TYPE_DATA;
-    st->codec->codec_id   = AV_CODEC_ID_NONE;
+    st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+    st->codecpar->codec_id   = AV_CODEC_ID_NONE;
     st->need_parsing      = AVSTREAM_PARSE_FULL;
     pes->st          = st;
     pes->stream_type = stream_type;
@@ -800,14 +805,14 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
            "stream=%d stream_type=%x pid=%x prog_reg_desc=%.4s\n",
            st->index, pes->stream_type, pes->pid, (char *)&prog_reg_desc);
 
-    st->codec->codec_tag = pes->stream_type;
+    st->codecpar->codec_tag = pes->stream_type;
 
     mpegts_find_stream_type(st, pes->stream_type, ISO_types);
     if (pes->stream_type == 4)
         st->request_probe = 50;
     if ((prog_reg_desc == AV_RL32("HDMV") ||
          prog_reg_desc == AV_RL32("HDPR")) &&
-        st->codec->codec_id == AV_CODEC_ID_NONE) {
+        st->codecpar->codec_id == AV_CODEC_ID_NONE) {
         mpegts_find_stream_type(st, pes->stream_type, HDMV_types);
         if (pes->stream_type == 0x83) {
             // HDMV TrueHD streams also contain an AC3 coded version of the
@@ -828,28 +833,33 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
             sub_st->id = pes->pid;
             avpriv_set_pts_info(sub_st, 33, 1, 90000);
             sub_st->priv_data         = sub_pes;
-            sub_st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-            sub_st->codec->codec_id   = AV_CODEC_ID_AC3;
+            sub_st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+            sub_st->codecpar->codec_id   = AV_CODEC_ID_AC3;
             sub_st->need_parsing      = AVSTREAM_PARSE_FULL;
             sub_pes->sub_st           = pes->sub_st = sub_st;
         }
     }
-    if (st->codec->codec_id == AV_CODEC_ID_NONE)
+    if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
         mpegts_find_stream_type(st, pes->stream_type, MISC_types);
-    if (st->codec->codec_id == AV_CODEC_ID_NONE) {
-        st->codec->codec_id  = old_codec_id;
-        st->codec->codec_type = old_codec_type;
+    if (st->codecpar->codec_id == AV_CODEC_ID_NONE) {
+        st->codecpar->codec_id  = old_codec_id;
+        st->codecpar->codec_type = old_codec_type;
     }
-    if ((st->codec->codec_id == AV_CODEC_ID_NONE ||
+    if ((st->codecpar->codec_id == AV_CODEC_ID_NONE ||
             (st->request_probe > 0 && st->request_probe < AVPROBE_SCORE_STREAM_RETRY / 5)) &&
-        !avcodec_is_open(st->codec) &&
         st->probe_packets > 0 &&
         stream_type == STREAM_TYPE_PRIVATE_DATA) {
-        st->codec->codec_type = AVMEDIA_TYPE_DATA;
-        st->codec->codec_id   = AV_CODEC_ID_BIN_DATA;
+        st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+        st->codecpar->codec_id   = AV_CODEC_ID_BIN_DATA;
         st->request_probe = AVPROBE_SCORE_STREAM_RETRY / 5;
     }
 
+    /* queue a context update if properties changed */
+    if (old_codec_type != st->codecpar->codec_type ||
+        old_codec_id   != st->codecpar->codec_id   ||
+        old_codec_tag  != st->codecpar->codec_tag)
+        st->internal->need_context_update = 1;
+
     return 0;
 }
 
@@ -862,8 +872,10 @@ static void reset_pes_packet_state(PESContext *pes)
     av_buffer_unref(&pes->buffer);
 }
 
-static void new_pes_packet(PESContext *pes, AVPacket *pkt)
+static int new_pes_packet(PESContext *pes, AVPacket *pkt)
 {
+    char *sd;
+
     av_init_packet(pkt);
 
     pkt->buf  = pes->buffer;
@@ -891,6 +903,13 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
 
     pes->buffer = NULL;
     reset_pes_packet_state(pes);
+
+    sd = av_packet_new_side_data(pkt, AV_PKT_DATA_MPEGTS_STREAM_ID, 1);
+    if (!sd)
+        return AVERROR(ENOMEM);
+    *sd = pes->stream_id;
+
+    return 0;
 }
 
 static uint64_t get_ts64(GetBitContext *gb, int bits)
@@ -979,14 +998,16 @@ static int mpegts_push_data(MpegTSFilter *filter,
     PESContext *pes   = filter->u.pes_filter.opaque;
     MpegTSContext *ts = pes->ts;
     const uint8_t *p;
-    int len, code;
+    int ret, len, code;
 
     if (!ts->pkt)
         return 0;
 
     if (is_start) {
         if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) {
-            new_pes_packet(pes, ts->pkt);
+            ret = new_pes_packet(pes, ts->pkt);
+            if (ret < 0)
+                return ret;
             ts->stop_parse = 1;
         } else {
             reset_pes_packet_state(pes);
@@ -1010,10 +1031,11 @@ static int mpegts_push_data(MpegTSFilter *filter,
                  * decide */
                 if (pes->header[0] == 0x00 && pes->header[1] == 0x00 &&
                     pes->header[2] == 0x01) {
-                    /* it must be an mpeg2 PES stream */
+                    /* it must be an MPEG-2 PES stream */
                     code = pes->header[3] | 0x100;
                     av_log(pes->stream, AV_LOG_TRACE, "pid=%x pes_code=%#x\n", pes->pid,
                             code);
+                    pes->stream_id = pes->header[3];
 
                     if ((pes->st && pes->st->discard == AVDISCARD_ALL &&
                          (!pes->sub_st ||
@@ -1050,7 +1072,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
                         code != 0x1ff && code != 0x1f2 && /* program_stream_directory, DSMCC_stream */
                         code != 0x1f8) {                  /* ITU-T Rec. H.222.1 type E stream */
                         pes->state = MPEGTS_PESHEADER;
-                        if (pes->st->codec->codec_id == AV_CODEC_ID_NONE && !pes->st->request_probe) {
+                        if (pes->st->codecpar->codec_id == AV_CODEC_ID_NONE && !pes->st->request_probe) {
                             av_log(pes->stream, AV_LOG_TRACE,
                                     "pid=%x stream_type=%x probing\n",
                                     pes->pid,
@@ -1147,8 +1169,8 @@ skip:
                     buf_size -= 5;
                 }
                 if (   pes->ts->fix_teletext_pts
-                    && (   pes->st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT
-                        || pes->st->codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE)
+                    && (   pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT
+                        || pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE)
                     ) {
                     AVProgram *p = NULL;
                     while ((p = av_find_program_from_stream(pes->stream, p, pes->st->index))) {
@@ -1164,7 +1186,7 @@ skip:
                                     int i;
                                     for (i = 0; i < p->nb_stream_indexes; i++) {
                                         AVStream *pst = pes->stream->streams[p->stream_index[i]];
-                                        if (pst->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+                                        if (pst->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
                                             st = pst;
                                     }
                                 }
@@ -1178,10 +1200,10 @@ skip:
                                     pes->st->pts_wrap_behavior = st->pts_wrap_behavior;
                                     if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) {
                                         pes->pts = pes->dts = pcr;
-                                    } else if (pes->st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT &&
+                                    } else if (pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT &&
                                                pes->dts > pcr + 3654 + 9000) {
                                         pes->pts = pes->dts = pcr + 3654 + 9000;
-                                    } else if (pes->st->codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE &&
+                                    } else if (pes->st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE &&
                                                pes->dts > pcr + 10*90000) { //10sec
                                         pes->pts = pes->dts = pcr + 3654 + 9000;
                                     }
@@ -1197,7 +1219,9 @@ skip:
             if (pes->buffer) {
                 if (pes->data_index > 0 &&
                     pes->data_index + buf_size > pes->total_size) {
-                    new_pes_packet(pes, ts->pkt);
+                    ret = new_pes_packet(pes, ts->pkt);
+                    if (ret < 0)
+                        return ret;
                     pes->total_size = MAX_PES_PAYLOAD;
                     pes->buffer = av_buffer_alloc(pes->total_size +
                                                   AV_INPUT_BUFFER_PADDING_SIZE);
@@ -1220,7 +1244,9 @@ skip:
                 if (!ts->stop_parse && pes->total_size < MAX_PES_PAYLOAD &&
                     pes->pes_header_size + pes->data_index == pes->total_size + PES_START_SIZE) {
                     ts->stop_parse = 1;
-                    new_pes_packet(pes, ts->pkt);
+                    ret = new_pes_packet(pes, ts->pkt);
+                    if (ret < 0)
+                        return ret;
                 }
             }
             buf_size = 0;
@@ -1342,6 +1368,8 @@ static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len)
 static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len)
 {
     int es_id = 0;
+    int ret   = 0;
+
     if (d->descr_count >= d->max_descr_count)
         return AVERROR_INVALIDDATA;
     ff_mp4_parse_es_descr(&d->pb, &es_id);
@@ -1349,12 +1377,13 @@ static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len)
 
     d->active_descr->es_id = es_id;
     update_offsets(&d->pb, &off, &len);
-    parse_mp4_descr(d, off, len, MP4DecConfigDescrTag);
+    if ((ret = parse_mp4_descr(d, off, len, MP4DecConfigDescrTag)) < 0)
+        return ret;
     update_offsets(&d->pb, &off, &len);
     if (len > 0)
-        parse_mp4_descr(d, off, len, MP4SLDescrTag);
+        ret = parse_mp4_descr(d, off, len, MP4SLDescrTag);
     d->active_descr = NULL;
-    return 0;
+    return ret;
 }
 
 static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off,
@@ -1378,6 +1407,14 @@ static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len)
     if (!descr)
         return AVERROR_INVALIDDATA;
 
+#define R8_CHECK_CLIP_MAX(dst, maxv) do {                       \
+    descr->sl.dst = avio_r8(&d->pb);                            \
+    if (descr->sl.dst > maxv) {                                 \
+        descr->sl.dst = maxv;                                   \
+        return AVERROR_INVALIDDATA;                             \
+    }                                                           \
+} while (0)
+
     predefined = avio_r8(&d->pb);
     if (!predefined) {
         int lengths;
@@ -1390,14 +1427,9 @@ static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len)
         descr->sl.use_idle        = !!(flags & 0x02);
         descr->sl.timestamp_res   = avio_rb32(&d->pb);
         avio_rb32(&d->pb);
-        descr->sl.timestamp_len      = avio_r8(&d->pb);
-        if (descr->sl.timestamp_len > 64) {
-            avpriv_request_sample(NULL, "timestamp_len > 64");
-            descr->sl.timestamp_len = 64;
-            return AVERROR_PATCHWELCOME;
-        }
-        descr->sl.ocr_len            = avio_r8(&d->pb);
-        descr->sl.au_len             = avio_r8(&d->pb);
+        R8_CHECK_CLIP_MAX(timestamp_len, 63);
+        R8_CHECK_CLIP_MAX(ocr_len,       63);
+        R8_CHECK_CLIP_MAX(au_len,        31);
         descr->sl.inst_bitrate_len   = avio_r8(&d->pb);
         lengths                      = avio_rb16(&d->pb);
         descr->sl.degr_prior_len     = lengths >> 12;
@@ -1415,6 +1447,8 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
 {
     int tag;
     int len1 = ff_mp4_read_descr(d->s, &d->pb, &tag);
+    int ret = 0;
+
     update_offsets(&d->pb, &off, &len);
     if (len < 0 || len1 > len || len1 <= 0) {
         av_log(d->s, AV_LOG_ERROR,
@@ -1425,30 +1459,32 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
 
     if (d->level++ >= MAX_LEVEL) {
         av_log(d->s, AV_LOG_ERROR, "Maximum MP4 descriptor level exceeded\n");
+        ret = AVERROR_INVALIDDATA;
         goto done;
     }
 
     if (target_tag && tag != target_tag) {
         av_log(d->s, AV_LOG_ERROR, "Found tag %x expected %x\n", tag,
                target_tag);
+        ret = AVERROR_INVALIDDATA;
         goto done;
     }
 
     switch (tag) {
     case MP4IODescrTag:
-        parse_MP4IODescrTag(d, off, len1);
+        ret = parse_MP4IODescrTag(d, off, len1);
         break;
     case MP4ODescrTag:
-        parse_MP4ODescrTag(d, off, len1);
+        ret = parse_MP4ODescrTag(d, off, len1);
         break;
     case MP4ESDescrTag:
-        parse_MP4ESDescrTag(d, off, len1);
+        ret = parse_MP4ESDescrTag(d, off, len1);
         break;
     case MP4DecConfigDescrTag:
-        parse_MP4DecConfigDescrTag(d, off, len1);
+        ret = parse_MP4DecConfigDescrTag(d, off, len1);
         break;
     case MP4SLDescrTag:
-        parse_MP4SLDescrTag(d, off, len1);
+        ret = parse_MP4SLDescrTag(d, off, len1);
         break;
     }
 
@@ -1456,7 +1492,7 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
 done:
     d->level--;
     avio_seek(&d->pb, off + len1, SEEK_SET);
-    return 0;
+    return ret;
 }
 
 static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size,
@@ -1539,14 +1575,15 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section,
                               mp4_descr[i].dec_config_descr_len, 0,
                               NULL, NULL, NULL, NULL);
             ff_mp4_read_dec_config_descr(s, st, &pb);
-            if (st->codec->codec_id == AV_CODEC_ID_AAC &&
-                st->codec->extradata_size > 0)
+            if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
+                st->codecpar->extradata_size > 0)
                 st->need_parsing = 0;
-            if (st->codec->codec_id == AV_CODEC_ID_H264 &&
-                st->codec->extradata_size > 0)
+            if (st->codecpar->codec_id == AV_CODEC_ID_H264 &&
+                st->codecpar->extradata_size > 0)
                 st->need_parsing = 0;
 
-            st->codec->codec_type = avcodec_get_type(st->codec->codec_id);
+            st->codecpar->codec_type = avcodec_get_type(st->codecpar->codec_id);
+            st->internal->need_context_update = 1;
         }
     }
     for (i = 0; i < mp4_descr_count; i++)
@@ -1594,7 +1631,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
 
     av_log(fc, AV_LOG_TRACE, "tag: 0x%02x len=%d\n", desc_tag, desc_len);
 
-    if ((st->codec->codec_id == AV_CODEC_ID_NONE || st->request_probe > 0) &&
+    if ((st->codecpar->codec_id == AV_CODEC_ID_NONE || st->request_probe > 0) &&
         stream_type == STREAM_TYPE_PRIVATE_DATA)
         mpegts_find_stream_type(st, desc_tag, DESC_types);
 
@@ -1613,10 +1650,12 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
                                   mp4_descr[i].dec_config_descr_len, 0,
                                   NULL, NULL, NULL, NULL);
                 ff_mp4_read_dec_config_descr(fc, st, &pb);
-                if (st->codec->codec_id == AV_CODEC_ID_AAC &&
-                    st->codec->extradata_size > 0)
+                if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
+                    st->codecpar->extradata_size > 0) {
                     st->need_parsing = 0;
-                if (st->codec->codec_id == AV_CODEC_ID_MPEG4SYSTEMS)
+                    st->internal->need_context_update = 1;
+                }
+                if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4SYSTEMS)
                     mpegts_open_section_filter(ts, pid, m4sl_cb, ts, 1);
             }
         break;
@@ -1624,8 +1663,8 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
         if (get16(pp, desc_end) < 0)
             break;
         if (mp4_descr_count > 0 &&
-            (st->codec->codec_id == AV_CODEC_ID_AAC_LATM ||
-             (st->request_probe == 0 && st->codec->codec_id == AV_CODEC_ID_NONE) ||
+            (st->codecpar->codec_id == AV_CODEC_ID_AAC_LATM ||
+             (st->request_probe == 0 && st->codecpar->codec_id == AV_CODEC_ID_NONE) ||
              st->request_probe > 0) &&
             mp4_descr->dec_config_descr_len && mp4_descr->es_id == pid) {
             AVIOContext pb;
@@ -1633,10 +1672,11 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
                               mp4_descr->dec_config_descr_len, 0,
                               NULL, NULL, NULL, NULL);
             ff_mp4_read_dec_config_descr(fc, st, &pb);
-            if (st->codec->codec_id == AV_CODEC_ID_AAC &&
-                st->codec->extradata_size > 0) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
+                st->codecpar->extradata_size > 0) {
                 st->request_probe = st->need_parsing = 0;
-                st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+                st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+                st->internal->need_context_update = 1;
             }
         }
         break;
@@ -1652,16 +1692,16 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
                 /* 4 bytes per language code (3 bytes) with comma or NUL byte should fit language buffer */
                 av_assert0(language_count <= sizeof(language) / 4);
 
-                if (st->codec->extradata == NULL) {
-                    if (ff_alloc_extradata(st->codec, language_count * 2)) {
+                if (st->codecpar->extradata == NULL) {
+                    if (ff_alloc_extradata(st->codecpar, language_count * 2)) {
                         return AVERROR(ENOMEM);
                     }
                 }
 
-               if (st->codec->extradata_size < language_count * 2)
+               if (st->codecpar->extradata_size < language_count * 2)
                    return AVERROR_INVALIDDATA;
 
-               extradata = st->codec->extradata;
+               extradata = st->codecpar->extradata;
 
                 for (i = 0; i < language_count; i++) {
                     language[i * 4 + 0] = get8(pp, desc_end);
@@ -1677,6 +1717,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
 
                 language[i * 4 - 1] = 0;
                 av_dict_set(&st->metadata, "language", language, 0);
+                st->internal->need_context_update = 1;
             }
         }
         break;
@@ -1702,16 +1743,16 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
                 /* 4 bytes per language code (3 bytes) with comma or NUL byte should fit language buffer */
                 av_assert0(language_count <= sizeof(language) / 4);
 
-                if (st->codec->extradata == NULL) {
-                    if (ff_alloc_extradata(st->codec, language_count * 5)) {
+                if (st->codecpar->extradata == NULL) {
+                    if (ff_alloc_extradata(st->codecpar, language_count * 5)) {
                         return AVERROR(ENOMEM);
                     }
                 }
 
-                if (st->codec->extradata_size < language_count * 5)
+                if (st->codecpar->extradata_size < language_count * 5)
                     return AVERROR_INVALIDDATA;
 
-                extradata = st->codec->extradata;
+                extradata = st->codecpar->extradata;
 
                 for (i = 0; i < language_count; i++) {
                     language[i * 4 + 0] = get8(pp, desc_end);
@@ -1740,6 +1781,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
 
                 language[i * 4 - 1] = 0;
                 av_dict_set(&st->metadata, "language", language, 0);
+                st->internal->need_context_update = 1;
             }
         }
         break;
@@ -1767,10 +1809,13 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
         }
         break;
     case 0x05: /* registration descriptor */
-        st->codec->codec_tag = bytestream_get_le32(pp);
-        av_log(fc, AV_LOG_TRACE, "reg_desc=%.4s\n", (char *)&st->codec->codec_tag);
-        if (st->codec->codec_id == AV_CODEC_ID_NONE || st->request_probe > 0)
-            mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types);
+        st->codecpar->codec_tag = bytestream_get_le32(pp);
+        av_log(fc, AV_LOG_TRACE, "reg_desc=%.4s\n", (char *)&st->codecpar->codec_tag);
+        if (st->codecpar->codec_id == AV_CODEC_ID_NONE || st->request_probe > 0) {
+            mpegts_find_stream_type(st, st->codecpar->codec_tag, REGD_types);
+            if (st->codecpar->codec_tag == MKTAG('B', 'S', 'S', 'D'))
+                st->request_probe = 50;
+        }
         break;
     case 0x52: /* stream identifier descriptor */
         st->stream_identifier = 1 + get8(pp, desc_end);
@@ -1779,39 +1824,40 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
         if (get16(pp, desc_end) == 0xFFFF)
             *pp += 4;
         if (get8(pp, desc_end) == 0xFF) {
-            st->codec->codec_tag = bytestream_get_le32(pp);
-            if (st->codec->codec_id == AV_CODEC_ID_NONE)
-                mpegts_find_stream_type(st, st->codec->codec_tag, METADATA_types);
+            st->codecpar->codec_tag = bytestream_get_le32(pp);
+            if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
+                mpegts_find_stream_type(st, st->codecpar->codec_tag, METADATA_types);
         }
         break;
     case 0x7f: /* DVB extension descriptor */
         ext_desc_tag = get8(pp, desc_end);
         if (ext_desc_tag < 0)
             return AVERROR_INVALIDDATA;
-        if (st->codec->codec_id == AV_CODEC_ID_OPUS &&
+        if (st->codecpar->codec_id == AV_CODEC_ID_OPUS &&
             ext_desc_tag == 0x80) { /* User defined (provisional Opus) */
-            if (!st->codec->extradata) {
-                st->codec->extradata = av_mallocz(sizeof(opus_default_extradata) +
-                                                  AV_INPUT_BUFFER_PADDING_SIZE);
-                if (!st->codec->extradata)
+            if (!st->codecpar->extradata) {
+                st->codecpar->extradata = av_mallocz(sizeof(opus_default_extradata) +
+                                                     AV_INPUT_BUFFER_PADDING_SIZE);
+                if (!st->codecpar->extradata)
                     return AVERROR(ENOMEM);
 
-                st->codec->extradata_size = sizeof(opus_default_extradata);
-                memcpy(st->codec->extradata, opus_default_extradata, sizeof(opus_default_extradata));
+                st->codecpar->extradata_size = sizeof(opus_default_extradata);
+                memcpy(st->codecpar->extradata, opus_default_extradata, sizeof(opus_default_extradata));
 
                 channel_config_code = get8(pp, desc_end);
                 if (channel_config_code < 0)
                     return AVERROR_INVALIDDATA;
                 if (channel_config_code <= 0x8) {
-                    st->codec->extradata[9]  = channels = channel_config_code ? channel_config_code : 2;
-                    st->codec->extradata[18] = channel_config_code ? (channels > 2) : /* Dual Mono */ 255;
-                    st->codec->extradata[19] = opus_stream_cnt[channel_config_code];
-                    st->codec->extradata[20] = opus_coupled_stream_cnt[channel_config_code];
-                    memcpy(&st->codec->extradata[21], opus_channel_map[channels - 1], channels);
+                    st->codecpar->extradata[9]  = channels = channel_config_code ? channel_config_code : 2;
+                    st->codecpar->extradata[18] = channel_config_code ? (channels > 2) : /* Dual Mono */ 255;
+                    st->codecpar->extradata[19] = opus_stream_cnt[channel_config_code];
+                    st->codecpar->extradata[20] = opus_coupled_stream_cnt[channel_config_code];
+                    memcpy(&st->codecpar->extradata[21], opus_channel_map[channels - 1], channels);
                 } else {
                     avpriv_request_sample(fc, "Opus in MPEG-TS - channel_config_code > 0x8");
                 }
                 st->need_parsing = AVSTREAM_PARSE_FULL;
+                st->internal->need_context_update = 1;
             }
         }
         break;
@@ -1848,8 +1894,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
     if (skip_identical(h, tssf))
         return;
 
-    av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d version=%d\n",
-            h->id, h->sec_num, h->last_sec_num, h->version);
+    av_log(ts->stream, AV_LOG_TRACE, "sid=0x%x sec_num=%d/%d version=%d tid=%d\n",
+            h->id, h->sec_num, h->last_sec_num, h->version, h->tid);
 
     if (h->tid != PMT_TID)
         return;
@@ -1948,7 +1994,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 if (!st)
                     goto out;
                 st->id = pid;
-                st->codec->codec_type = AVMEDIA_TYPE_DATA;
+                st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
             }
         }
 
@@ -1979,7 +2025,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
                 stream_type == 0x83 && pes->sub_st) {
                 av_program_add_stream_index(ts->stream, h->id,
                                             pes->sub_st->index);
-                pes->sub_st->codec->codec_tag = st->codec->codec_tag;
+                pes->sub_st->codecpar->codec_tag = st->codecpar->codec_tag;
             }
         }
         p = desc_list_end;
@@ -2263,7 +2309,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
                 int types = 0;
                 for (i = 0; i < ts->stream->nb_streams; i++) {
                     AVStream *st = ts->stream->streams[i];
-                    types |= 1<<st->codec->codec_type;
+                    types |= 1<<st->codecpar->codec_type;
                 }
                 if ((types & (1<<AVMEDIA_TYPE_AUDIO) && types & (1<<AVMEDIA_TYPE_VIDEO)) || pos > 100000) {
                     av_log(ts->stream, AV_LOG_DEBUG, "All programs have pmt, headers found\n");
@@ -2320,11 +2366,20 @@ static void reanalyze(MpegTSContext *ts) {
 
 /* XXX: try to find a better synchro over several packets (use
  * get_packet_size() ?) */
-static int mpegts_resync(AVFormatContext *s)
+static int mpegts_resync(AVFormatContext *s, int seekback, const uint8_t *current_packet)
 {
     MpegTSContext *ts = s->priv_data;
     AVIOContext *pb = s->pb;
     int c, i;
+    uint64_t pos = avio_tell(pb);
+
+    avio_seek(pb, -FFMIN(seekback, pos), SEEK_CUR);
+
+    //Special case for files like 01c56b0dc1.ts
+    if (current_packet[0] == 0x80 && current_packet[12] == 0x47) {
+        avio_seek(pb, 12, SEEK_CUR);
+        return 0;
+    }
 
     for (i = 0; i < ts->resync_size; i++) {
         c = avio_r8(pb);
@@ -2356,10 +2411,8 @@ static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size,
         /* check packet sync byte */
         if ((*data)[0] != 0x47) {
             /* find a new packet start */
-            uint64_t pos = avio_tell(pb);
-            avio_seek(pb, -FFMIN(raw_packet_size, pos), SEEK_CUR);
 
-            if (mpegts_resync(s) < 0)
+            if (mpegts_resync(s, raw_packet_size, *data) < 0)
                 return AVERROR(EAGAIN);
             else
                 continue;
@@ -2441,14 +2494,14 @@ static int mpegts_probe(AVProbeData *p)
 #define CHECK_COUNT 10
 #define CHECK_BLOCK 100
 
-    if (check_count < CHECK_COUNT)
+    if (!check_count)
         return 0;
 
     for (i = 0; i<check_count; i+=CHECK_BLOCK) {
         int left = FFMIN(check_count - i, CHECK_BLOCK);
-        int score      = analyze(p->buf + TS_PACKET_SIZE     *i, TS_PACKET_SIZE     *left, TS_PACKET_SIZE     , NULL, 1);
-        int dvhs_score = analyze(p->buf + TS_DVHS_PACKET_SIZE*i, TS_DVHS_PACKET_SIZE*left, TS_DVHS_PACKET_SIZE, NULL, 1);
-        int fec_score  = analyze(p->buf + TS_FEC_PACKET_SIZE *i, TS_FEC_PACKET_SIZE *left, TS_FEC_PACKET_SIZE , NULL, 1);
+        int score      = analyze(p->buf + TS_PACKET_SIZE     *i, TS_PACKET_SIZE     *left, TS_PACKET_SIZE     , 1);
+        int dvhs_score = analyze(p->buf + TS_DVHS_PACKET_SIZE*i, TS_DVHS_PACKET_SIZE*left, TS_DVHS_PACKET_SIZE, 1);
+        int fec_score  = analyze(p->buf + TS_FEC_PACKET_SIZE *i, TS_FEC_PACKET_SIZE *left, TS_FEC_PACKET_SIZE , 1);
         score = FFMAX3(score, dvhs_score, fec_score);
         sumscore += score;
         maxscore = FFMAX(maxscore, score);
@@ -2459,10 +2512,17 @@ static int mpegts_probe(AVProbeData *p)
 
     ff_dlog(0, "TS score: %d %d\n", sumscore, maxscore);
 
-    if      (sumscore > 6) return AVPROBE_SCORE_MAX   + sumscore - CHECK_COUNT;
-    else if (maxscore > 6) return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT;
-    else
+    if        (check_count > CHECK_COUNT && sumscore > 6) {
+        return AVPROBE_SCORE_MAX   + sumscore - CHECK_COUNT;
+    } else if (check_count >= CHECK_COUNT && sumscore > 6) {
+        return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT;
+    } else if (check_count >= CHECK_COUNT && maxscore > 6) {
+        return AVPROBE_SCORE_MAX/2 + sumscore - CHECK_COUNT;
+    } else if (sumscore > 6) {
+        return 2;
+    } else {
         return 0;
+    }
 }
 
 /* return the 90kHz PCR and the extension for the 27MHz PCR. return
@@ -2556,8 +2616,8 @@ static int mpegts_read_header(AVFormatContext *s)
         if (!st)
             return AVERROR(ENOMEM);
         avpriv_set_pts_info(st, 60, 1, 27000000);
-        st->codec->codec_type = AVMEDIA_TYPE_DATA;
-        st->codec->codec_id   = AV_CODEC_ID_MPEG2TS;
+        st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+        st->codecpar->codec_id   = AV_CODEC_ID_MPEG2TS;
 
         /* we iterate until we find two PCRs to estimate the bitrate */
         pcr_pid    = -1;
@@ -2588,7 +2648,7 @@ static int mpegts_read_header(AVFormatContext *s)
         ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]);
         ts->cur_pcr  = pcrs[0] - ts->pcr_incr * packet_count[0];
         s->bit_rate  = TS_PACKET_SIZE * 8 * 27000000LL / ts->pcr_incr;
-        st->codec->bit_rate = s->bit_rate;
+        st->codecpar->bit_rate = s->bit_rate;
         st->start_time      = ts->cur_pcr;
         av_log(ts->stream, AV_LOG_TRACE, "start=%0.3f pcr=%0.3f incr=%d\n",
                 st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);
@@ -2663,7 +2723,9 @@ static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt)
             if (ts->pids[i] && ts->pids[i]->type == MPEGTS_PES) {
                 PESContext *pes = ts->pids[i]->u.pes_filter.opaque;
                 if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) {
-                    new_pes_packet(pes, pkt);
+                    ret = new_pes_packet(pes, pkt);
+                    if (ret < 0)
+                        return ret;
                     pes->state = MPEGTS_SKIP;
                     ret = 0;
                     break;
@@ -2712,8 +2774,7 @@ static av_unused int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
         if (avio_read(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)
             return AV_NOPTS_VALUE;
         if (buf[0] != 0x47) {
-            avio_seek(s->pb, -TS_PACKET_SIZE, SEEK_CUR);
-            if (mpegts_resync(s) < 0)
+            if (mpegts_resync(s, TS_PACKET_SIZE, buf) < 0)
                 return AV_NOPTS_VALUE;
             pos = avio_tell(s->pb);
             continue;
diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h
index 0cdbc76..272e2be 100644
--- a/libavformat/mpegts.h
+++ b/libavformat/mpegts.h
@@ -1,5 +1,5 @@
 /*
- * MPEG2 transport stream defines
+ * MPEG-2 transport stream defines
  * Copyright (c) 2003 Fabrice Bellard
  *
  * This file is part of FFmpeg.
@@ -51,6 +51,7 @@
 #define STREAM_TYPE_AUDIO_AAC       0x0f
 #define STREAM_TYPE_AUDIO_AAC_LATM  0x11
 #define STREAM_TYPE_VIDEO_MPEG4     0x10
+#define STREAM_TYPE_METADATA        0x15
 #define STREAM_TYPE_VIDEO_H264      0x1b
 #define STREAM_TYPE_VIDEO_HEVC      0x24
 #define STREAM_TYPE_VIDEO_CAVS      0x42
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 6bf5461..b45a283 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -1,5 +1,5 @@
 /*
- * MPEG2 transport stream (aka DVB) muxer
+ * MPEG-2 transport stream (aka DVB) muxer
  * Copyright (c) 2003 Fabrice Bellard
  *
  * This file is part of FFmpeg.
@@ -38,6 +38,8 @@
 
 /* write DVB SI sections */
 
+#define DVB_PRIVATE_NETWORK_START 0xff01
+
 /*********************************************/
 /* mpegts section writer */
 
@@ -49,7 +51,7 @@ typedef struct MpegTSSection {
 } MpegTSSection;
 
 typedef struct MpegTSService {
-    MpegTSSection pmt; /* MPEG2 pmt table context */
+    MpegTSSection pmt; /* MPEG-2 PMT table context */
     int sid;           /* service ID */
     char *name;
     char *provider_name;
@@ -67,12 +69,13 @@ enum {
     MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_RADIO = 0x0A,
     MPEGTS_SERVICE_TYPE_MPEG2_DIGITAL_HDTV           = 0x11,
     MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_SDTV  = 0x16,
-    MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_HDTV  = 0x19
+    MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_HDTV  = 0x19,
+    MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV            = 0x1F,
 };
 typedef struct MpegTSWrite {
     const AVClass *av_class;
-    MpegTSSection pat; /* MPEG2 pat table */
-    MpegTSSection sdt; /* MPEG2 sdt table context */
+    MpegTSSection pat; /* MPEG-2 PAT table */
+    MpegTSSection sdt; /* MPEG-2 SDT table context */
     MpegTSService **services;
     int sdt_packet_count;
     int sdt_packet_period;
@@ -293,7 +296,7 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
             err = 1;
             break;
         }
-        switch (st->codec->codec_id) {
+        switch (st->codecpar->codec_id) {
         case AV_CODEC_ID_MPEG1VIDEO:
         case AV_CODEC_ID_MPEG2VIDEO:
             stream_type = STREAM_TYPE_VIDEO_MPEG2;
@@ -318,7 +321,12 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
             break;
         case AV_CODEC_ID_MP2:
         case AV_CODEC_ID_MP3:
-            stream_type = STREAM_TYPE_AUDIO_MPEG1;
+            if (   st->codecpar->sample_rate > 0
+                && st->codecpar->sample_rate < 32000) {
+                stream_type = STREAM_TYPE_AUDIO_MPEG2;
+            } else {
+                stream_type = STREAM_TYPE_AUDIO_MPEG1;
+            }
             break;
         case AV_CODEC_ID_AAC:
             stream_type = (ts->flags & MPEGTS_FLAG_AAC_LATM)
@@ -347,6 +355,9 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
         case AV_CODEC_ID_OPUS:
             stream_type = STREAM_TYPE_PRIVATE_DATA;
             break;
+        case AV_CODEC_ID_TIMED_ID3:
+            stream_type = STREAM_TYPE_METADATA;
+            break;
         default:
             stream_type = STREAM_TYPE_PRIVATE_DATA;
             break;
@@ -358,19 +369,19 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
         q += 2; /* patched after */
 
         /* write optional descriptors here */
-        switch (st->codec->codec_type) {
+        switch (st->codecpar->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
-            if (st->codec->codec_id==AV_CODEC_ID_AC3 && (ts->flags & MPEGTS_FLAG_SYSTEM_B)) {
+            if (st->codecpar->codec_id==AV_CODEC_ID_AC3 && (ts->flags & MPEGTS_FLAG_SYSTEM_B)) {
                 *q++=0x6a; // AC3 descriptor see A038 DVB SI
                 *q++=1; // 1 byte, all flags sets to 0
                 *q++=0; // omit all fields...
             }
-            if (st->codec->codec_id==AV_CODEC_ID_EAC3 && (ts->flags & MPEGTS_FLAG_SYSTEM_B)) {
+            if (st->codecpar->codec_id==AV_CODEC_ID_EAC3 && (ts->flags & MPEGTS_FLAG_SYSTEM_B)) {
                 *q++=0x7a; // EAC3 descriptor see A038 DVB SI
                 *q++=1; // 1 byte, all flags sets to 0
                 *q++=0; // omit all fields...
             }
-            if (st->codec->codec_id==AV_CODEC_ID_S302M) {
+            if (st->codecpar->codec_id==AV_CODEC_ID_S302M) {
                 *q++ = 0x05; /* MPEG-2 registration descriptor*/
                 *q++ = 4;
                 *q++ = 'B';
@@ -378,7 +389,7 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                 *q++ = 'S';
                 *q++ = 'D';
             }
-            if (st->codec->codec_id==AV_CODEC_ID_OPUS) {
+            if (st->codecpar->codec_id==AV_CODEC_ID_OPUS) {
                 /* 6 bytes registration descriptor, 4 bytes Opus audio descriptor */
                 if (q - data > SECTION_LENGTH - 6 - 4) {
                     err = 1;
@@ -396,12 +407,12 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                 *q++ = 2;
                 *q++ = 0x80;
 
-                if (st->codec->extradata && st->codec->extradata_size >= 19) {
-                    if (st->codec->extradata[18] == 0 && st->codec->channels <= 2) {
+                if (st->codecpar->extradata && st->codecpar->extradata_size >= 19) {
+                    if (st->codecpar->extradata[18] == 0 && st->codecpar->channels <= 2) {
                         /* RTP mapping family */
-                        *q++ = st->codec->channels;
-                    } else if (st->codec->extradata[18] == 1 && st->codec->channels <= 8 &&
-                               st->codec->extradata_size >= 21 + st->codec->channels) {
+                        *q++ = st->codecpar->channels;
+                    } else if (st->codecpar->extradata[18] == 1 && st->codecpar->channels <= 8 &&
+                               st->codecpar->extradata_size >= 21 + st->codecpar->channels) {
                         static const uint8_t coupled_stream_counts[9] = {
                             1, 0, 1, 1, 2, 2, 2, 3, 3
                         };
@@ -427,14 +438,14 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                         };
                         /* Vorbis mapping family */
 
-                        if (st->codec->extradata[19] == st->codec->channels - coupled_stream_counts[st->codec->channels] &&
-                            st->codec->extradata[20] == coupled_stream_counts[st->codec->channels] &&
-                            memcmp(&st->codec->extradata[21], channel_map_a[st->codec->channels-1], st->codec->channels) == 0) {
-                            *q++ = st->codec->channels;
-                        } else if (st->codec->channels >= 2 && st->codec->extradata[19] == st->codec->channels &&
-                                   st->codec->extradata[20] == 0 &&
-                                   memcmp(&st->codec->extradata[21], channel_map_b[st->codec->channels-1], st->codec->channels) == 0) {
-                            *q++ = st->codec->channels | 0x80;
+                        if (st->codecpar->extradata[19] == st->codecpar->channels - coupled_stream_counts[st->codecpar->channels] &&
+                            st->codecpar->extradata[20] == coupled_stream_counts[st->codecpar->channels] &&
+                            memcmp(&st->codecpar->extradata[21], channel_map_a[st->codecpar->channels-1], st->codecpar->channels) == 0) {
+                            *q++ = st->codecpar->channels;
+                        } else if (st->codecpar->channels >= 2 && st->codecpar->extradata[19] == st->codecpar->channels &&
+                                   st->codecpar->extradata[20] == 0 &&
+                                   memcmp(&st->codecpar->extradata[21], channel_map_b[st->codecpar->channels-1], st->codecpar->channels) == 0) {
+                            *q++ = st->codecpar->channels | 0x80;
                         } else {
                             /* Unsupported, could write an extended descriptor here */
                             av_log(s, AV_LOG_ERROR, "Unsupported Opus Vorbis-style channel mapping");
@@ -442,12 +453,12 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                         }
                     } else {
                         /* Unsupported */
-                        av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping for family %d", st->codec->extradata[18]);
+                        av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping for family %d", st->codecpar->extradata[18]);
                         *q++ = 0xff;
                     }
-                } else if (st->codec->channels <= 2) {
+                } else if (st->codecpar->channels <= 2) {
                     /* Assume RTP mapping family */
-                    *q++ = st->codec->channels;
+                    *q++ = st->codecpar->channels;
                 } else {
                     /* Unsupported */
                     av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping");
@@ -498,7 +509,7 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
            const char default_language[] = "und";
            const char *language = lang && strlen(lang->value) >= 3 ? lang->value : default_language;
 
-           if (st->codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE) {
+           if (st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE) {
                uint8_t *len_ptr;
                int extradata_copied = 0;
 
@@ -517,9 +528,9 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                    if (*language != '\0')
                        language++;
 
-                   if (st->codec->extradata_size - extradata_copied >= 5) {
-                       *q++ = st->codec->extradata[extradata_copied + 4]; /* subtitling_type */
-                       memcpy(q, st->codec->extradata + extradata_copied, 4); /* composition_page_id and ancillary_page_id */
+                   if (st->codecpar->extradata_size - extradata_copied >= 5) {
+                       *q++ = st->codecpar->extradata[extradata_copied + 4]; /* subtitling_type */
+                       memcpy(q, st->codecpar->extradata + extradata_copied, 4); /* composition_page_id and ancillary_page_id */
                        extradata_copied += 5;
                        q += 4;
                    } else {
@@ -527,9 +538,9 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                         * 0x10 - normal with no monitor aspect ratio criticality
                         * 0x20 - for the hard of hearing with no monitor aspect ratio criticality */
                        *q++ = (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) ? 0x20 : 0x10;
-                       if ((st->codec->extradata_size == 4) && (extradata_copied == 0)) {
+                       if ((st->codecpar->extradata_size == 4) && (extradata_copied == 0)) {
                            /* support of old 4-byte extradata format */
-                           memcpy(q, st->codec->extradata, 4); /* composition_page_id and ancillary_page_id */
+                           memcpy(q, st->codecpar->extradata, 4); /* composition_page_id and ancillary_page_id */
                            extradata_copied += 4;
                            q += 4;
                        } else {
@@ -540,7 +551,7 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                }
 
                *len_ptr = q - len_ptr - 1;
-           } else if (st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
+           } else if (st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
                uint8_t *len_ptr = NULL;
                int extradata_copied = 0;
 
@@ -556,8 +567,8 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                    if (*language != '\0')
                        language++;
 
-                   if (st->codec->extradata_size - 1 > extradata_copied) {
-                       memcpy(q, st->codec->extradata + extradata_copied, 2);
+                   if (st->codecpar->extradata_size - 1 > extradata_copied) {
+                       memcpy(q, st->codecpar->extradata + extradata_copied, 2);
                        extradata_copied += 2;
                        q += 2;
                    } else {
@@ -592,13 +603,20 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
             }
             break;
         case AVMEDIA_TYPE_DATA:
-            if (st->codec->codec_id == AV_CODEC_ID_SMPTE_KLV) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_SMPTE_KLV) {
                 *q++ = 0x05; /* MPEG-2 registration descriptor */
                 *q++ = 4;
                 *q++ = 'K';
                 *q++ = 'L';
                 *q++ = 'V';
                 *q++ = 'A';
+            } else if (st->codecpar->codec_id == AV_CODEC_ID_TIMED_ID3) {
+                *q++ = 0x5; /* MPEG-2 registration descriptor */
+                *q++ = 4;
+                *q++ = 'I';
+                *q++ = 'D';
+                *q++ = '3';
+                *q++ = ' ';
             }
             break;
         }
@@ -866,13 +884,13 @@ static int mpegts_init(AVFormatContext *s)
         ts_st->first_pts_check = 1;
         ts_st->cc              = 15;
         /* update PCR pid by using the first video stream */
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
             service->pcr_pid == 0x1fff) {
             service->pcr_pid = ts_st->pid;
             pcr_st           = st;
         }
-        if (st->codec->codec_id == AV_CODEC_ID_AAC &&
-            st->codec->extradata_size > 0) {
+        if (st->codecpar->codec_id == AV_CODEC_ID_AAC &&
+            st->codecpar->extradata_size > 0) {
             AVStream *ast;
             ts_st->amux = avformat_alloc_context();
             if (!ts_st->amux) {
@@ -890,7 +908,7 @@ static int mpegts_init(AVFormatContext *s)
                 ret = AVERROR(ENOMEM);
                 goto fail;
             }
-            ret = avcodec_copy_context(ast->codec, st->codec);
+            ret = avcodec_parameters_copy(ast->codecpar, st->codecpar);
             if (ret != 0)
                 goto fail;
             ast->time_base = st->time_base;
@@ -898,8 +916,8 @@ static int mpegts_init(AVFormatContext *s)
             if (ret < 0)
                 goto fail;
         }
-        if (st->codec->codec_id == AV_CODEC_ID_OPUS) {
-            ts_st->opus_pending_trim_start = st->codec->initial_padding * 48000 / st->codec->sample_rate;
+        if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) {
+            ts_st->opus_pending_trim_start = st->codecpar->initial_padding * 48000 / st->codecpar->sample_rate;
         }
     }
 
@@ -927,14 +945,15 @@ static int mpegts_init(AVFormatContext *s)
         /* Arbitrary values, PAT/PMT will also be written on video key frames */
         ts->sdt_packet_period = 200;
         ts->pat_packet_period = 40;
-        if (pcr_st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            if (!pcr_st->codec->frame_size) {
+        if (pcr_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            int frame_size = av_get_audio_frame_duration2(pcr_st->codecpar, 0);
+            if (!frame_size) {
                 av_log(s, AV_LOG_WARNING, "frame size not set\n");
                 service->pcr_packet_period =
-                    pcr_st->codec->sample_rate / (10 * 512);
+                    pcr_st->codecpar->sample_rate / (10 * 512);
             } else {
                 service->pcr_packet_period =
-                    pcr_st->codec->sample_rate / (10 * pcr_st->codec->frame_size);
+                    pcr_st->codecpar->sample_rate / (10 * frame_size);
             }
         } else {
             // max delta PCR 0.1s
@@ -985,7 +1004,7 @@ fail:
     return ret;
 }
 
-/* send SDT, PAT and PMT tables regulary */
+/* send SDT, PAT and PMT tables regularly */
 static void retransmit_si_info(AVFormatContext *s, int force_pat, int64_t dts)
 {
     MpegTSWrite *ts = s->priv_data;
@@ -1122,7 +1141,7 @@ static uint8_t *get_ts_payload_start(uint8_t *pkt)
  * NOTE: 'payload' contains a complete PES payload. */
 static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
                              const uint8_t *payload, int payload_size,
-                             int64_t pts, int64_t dts, int key)
+                             int64_t pts, int64_t dts, int key, int stream_id)
 {
     MpegTSWriteStream *ts_st = st->priv_data;
     MpegTSWrite *ts = s->priv_data;
@@ -1132,10 +1151,10 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
     int afc_len, stuffing_len;
     int64_t pcr = -1; /* avoid warning */
     int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE);
-    int force_pat = st->codec->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
+    int force_pat = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && key && !ts_st->prev_payload_key;
 
-    av_assert0(ts_st->payload != buf || st->codec->codec_type != AVMEDIA_TYPE_VIDEO);
-    if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    av_assert0(ts_st->payload != buf || st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO);
+    if (ts->flags & MPEGTS_FLAG_PAT_PMT_AT_FRAMES && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         force_pat = 1;
     }
 
@@ -1205,26 +1224,31 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
             *q++ = 0x01;
             is_dvb_subtitle = 0;
             is_dvb_teletext = 0;
-            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-                if (st->codec->codec_id == AV_CODEC_ID_DIRAC)
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+                if (st->codecpar->codec_id == AV_CODEC_ID_DIRAC)
                     *q++ = 0xfd;
                 else
                     *q++ = 0xe0;
-            } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
-                       (st->codec->codec_id == AV_CODEC_ID_MP2 ||
-                        st->codec->codec_id == AV_CODEC_ID_MP3 ||
-                        st->codec->codec_id == AV_CODEC_ID_AAC)) {
+            } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
+                       (st->codecpar->codec_id == AV_CODEC_ID_MP2 ||
+                        st->codecpar->codec_id == AV_CODEC_ID_MP3 ||
+                        st->codecpar->codec_id == AV_CODEC_ID_AAC)) {
                 *q++ = 0xc0;
-            } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
-                        st->codec->codec_id == AV_CODEC_ID_AC3 &&
+            } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
+                        st->codecpar->codec_id == AV_CODEC_ID_AC3 &&
                         ts->m2ts_mode) {
                 *q++ = 0xfd;
+            } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
+                *q++ = stream_id != -1 ? stream_id : 0xfc;
+
+                if (stream_id == 0xbd) /* asynchronous KLV */
+                    pts = dts = AV_NOPTS_VALUE;
             } else {
                 *q++ = 0xbd;
-                if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
-                    if (st->codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE) {
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+                    if (st->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE) {
                         is_dvb_subtitle = 1;
-                    } else if (st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
+                    } else if (st->codecpar->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
                         is_dvb_teletext = 1;
                     }
                 }
@@ -1239,8 +1263,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
                 header_len += 5;
                 flags      |= 0x40;
             }
-            if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
-                st->codec->codec_id == AV_CODEC_ID_DIRAC) {
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+                st->codecpar->codec_id == AV_CODEC_ID_DIRAC) {
                 /* set PES_extension_flag */
                 pes_extension = 1;
                 flags        |= 0x01;
@@ -1254,8 +1278,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
              * otherwise it will not play sound on blu-ray
              */
             if (ts->m2ts_mode &&
-                st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
-                st->codec->codec_id == AV_CODEC_ID_AC3) {
+                st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
+                st->codecpar->codec_id == AV_CODEC_ID_AC3) {
                         /* set PES_extension_flag */
                         pes_extension = 1;
                         flags |= 0x01;
@@ -1273,14 +1297,14 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
             }
             if (len > 0xffff)
                 len = 0;
-            if (ts->omit_video_pes_length && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+            if (ts->omit_video_pes_length && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
                 len = 0;
             }
             *q++ = len >> 8;
             *q++ = len;
             val  = 0x80;
             /* data alignment indicator is required for subtitle and data streams */
-            if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE || st->codec->codec_type == AVMEDIA_TYPE_DATA)
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE || st->codecpar->codec_type == AVMEDIA_TYPE_DATA)
                 val |= 0x04;
             *q++ = val;
             *q++ = flags;
@@ -1293,7 +1317,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
                 write_pts(q, 1, dts);
                 q += 5;
             }
-            if (pes_extension && st->codec->codec_id == AV_CODEC_ID_DIRAC) {
+            if (pes_extension && st->codecpar->codec_id == AV_CODEC_ID_DIRAC) {
                 flags = 0x01;  /* set PES_extension_flag_2 */
                 *q++  = flags;
                 *q++  = 0x80 | 0x01; /* marker bit + extension length */
@@ -1304,7 +1328,7 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
             /* For Blu-ray AC3 Audio Setting extended flags */
           if (ts->m2ts_mode &&
               pes_extension &&
-              st->codec->codec_id == AV_CODEC_ID_AC3) {
+              st->codecpar->codec_id == AV_CODEC_ID_AC3) {
                       flags = 0x01; /* set PES_extension_flag_2 */
                       *q++ = flags;
                       *q++ = 0x80 | 0x01; /* marker bit + extension length */
@@ -1462,6 +1486,15 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
     const int64_t delay = av_rescale(s->max_delay, 90000, AV_TIME_BASE) * 2;
     int64_t dts = pkt->dts, pts = pkt->pts;
     int opus_samples = 0;
+    int side_data_size;
+    char *side_data = NULL;
+    int stream_id = -1;
+
+    side_data = av_packet_get_side_data(pkt,
+                                        AV_PKT_DATA_MPEGTS_STREAM_ID,
+                                        &side_data_size);
+    if (side_data)
+        stream_id = side_data[0];
 
     if (ts->reemit_pat_pmt) {
         av_log(s, AV_LOG_WARNING,
@@ -1489,15 +1522,15 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
     }
     ts_st->first_pts_check = 0;
 
-    if (st->codec->codec_id == AV_CODEC_ID_H264) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
         const uint8_t *p = buf, *buf_end = p + size;
         uint32_t state = -1;
-        int extradd = (pkt->flags & AV_PKT_FLAG_KEY) ? st->codec->extradata_size : 0;
+        int extradd = (pkt->flags & AV_PKT_FLAG_KEY) ? st->codecpar->extradata_size : 0;
         int ret = ff_check_h264_startcode(s, st, pkt);
         if (ret < 0)
             return ret;
 
-        if (extradd && AV_RB24(st->codec->extradata) > 1)
+        if (extradd && AV_RB24(st->codecpar->extradata) > 1)
             extradd = 0;
 
         do {
@@ -1514,7 +1547,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
             data = av_malloc(pkt->size + 6 + extradd);
             if (!data)
                 return AVERROR(ENOMEM);
-            memcpy(data + 6, st->codec->extradata, extradd);
+            memcpy(data + 6, st->codecpar->extradata, extradd);
             memcpy(data + 6 + extradd, pkt->data, pkt->size);
             AV_WB32(data, 0x00000001);
             data[4] = 0x09;
@@ -1522,7 +1555,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
             buf     = data;
             size    = pkt->size + 6 + extradd;
         }
-    } else if (st->codec->codec_id == AV_CODEC_ID_AAC) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
         if (pkt->size < 2) {
             av_log(s, AV_LOG_ERROR, "AAC packet too short\n");
             return AVERROR_INVALIDDATA;
@@ -1555,11 +1588,11 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
             buf             = data;
             }
         }
-    } else if (st->codec->codec_id == AV_CODEC_ID_HEVC) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
         int ret = check_hevc_startcode(s, st, pkt);
         if (ret < 0)
             return ret;
-    } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) {
         if (pkt->size < 2) {
             av_log(s, AV_LOG_ERROR, "Opus packet too short\n");
             return AVERROR_INVALIDDATA;
@@ -1580,7 +1613,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
                                                 &side_data_size);
 
             if (side_data && side_data_size >= 10) {
-                trim_end = AV_RL32(side_data + 4) * 48000 / st->codec->sample_rate;
+                trim_end = AV_RL32(side_data + 4) * 48000 / st->codecpar->sample_rate;
             }
 
             ctrl_header_size = pkt->size + 2 + pkt->size / 255 + 1;
@@ -1640,8 +1673,8 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
             if (   ts_st2->payload_size
                && (ts_st2->payload_dts == AV_NOPTS_VALUE || dts - ts_st2->payload_dts > delay/2)) {
                 mpegts_write_pes(s, st2, ts_st2->payload, ts_st2->payload_size,
-                                ts_st2->payload_pts, ts_st2->payload_dts,
-                                ts_st2->payload_flags & AV_PKT_FLAG_KEY);
+                                 ts_st2->payload_pts, ts_st2->payload_dts,
+                                 ts_st2->payload_flags & AV_PKT_FLAG_KEY, stream_id);
                 ts_st2->payload_size = 0;
             }
         }
@@ -1654,16 +1687,16 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
         ts_st->opus_queued_samples + opus_samples >= 5760 /* 120ms */)) {
         mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size,
                          ts_st->payload_pts, ts_st->payload_dts,
-                         ts_st->payload_flags & AV_PKT_FLAG_KEY);
+                         ts_st->payload_flags & AV_PKT_FLAG_KEY, stream_id);
         ts_st->payload_size = 0;
         ts_st->opus_queued_samples = 0;
     }
 
-    if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO || size > ts->pes_payload_size) {
+    if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || size > ts->pes_payload_size) {
         av_assert0(!ts_st->payload_size);
         // for video and subtitle, write a single pes packet
         mpegts_write_pes(s, st, buf, size, pts, dts,
-                         pkt->flags & AV_PKT_FLAG_KEY);
+                         pkt->flags & AV_PKT_FLAG_KEY, stream_id);
         ts_st->opus_queued_samples = 0;
         av_free(data);
         return 0;
@@ -1695,7 +1728,7 @@ static void mpegts_write_flush(AVFormatContext *s)
         if (ts_st->payload_size > 0) {
             mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_size,
                              ts_st->payload_pts, ts_st->payload_dts,
-                             ts_st->payload_flags & AV_PKT_FLAG_KEY);
+                             ts_st->payload_flags & AV_PKT_FLAG_KEY, -1);
             ts_st->payload_size = 0;
             ts_st->opus_queued_samples = 0;
         }
@@ -1752,11 +1785,11 @@ static int mpegts_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt
     int ret = 1;
     AVStream *st = s->streams[pkt->stream_index];
 
-    if (st->codec->codec_id == AV_CODEC_ID_H264) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
         if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 &&
                               AV_RB24(pkt->data) != 0x000001)
             ret = ff_stream_add_bitstream_filter(st, "h264_mp4toannexb", NULL);
-    } else if (st->codec->codec_id == AV_CODEC_ID_HEVC) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_HEVC) {
         if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 &&
                               AV_RB24(pkt->data) != 0x000001)
             ret = ff_stream_add_bitstream_filter(st, "hevc_mp4toannexb", NULL);
@@ -1771,7 +1804,7 @@ static const AVOption options[] = {
       { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM },
     { "mpegts_original_network_id", "Set original_network_id field.",
       offsetof(MpegTSWrite, original_network_id), AV_OPT_TYPE_INT,
-      { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM },
+      { .i64 = DVB_PRIVATE_NETWORK_START }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM },
     { "mpegts_service_id", "Set service_id field.",
       offsetof(MpegTSWrite, service_id), AV_OPT_TYPE_INT,
       { .i64 = 0x0001 }, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM },
@@ -1799,6 +1832,9 @@ static const AVOption options[] = {
     { "advanced_codec_digital_hdtv", "Advanced Codec Digital HDTV.",
       0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_ADVANCED_CODEC_DIGITAL_HDTV }, 0x01, 0xff,
       AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" },
+    { "hevc_digital_hdtv", "HEVC Digital Television Service.",
+      0, AV_OPT_TYPE_CONST, { .i64 = MPEGTS_SERVICE_TYPE_HEVC_DIGITAL_HDTV }, 0x01, 0xff,
+      AV_OPT_FLAG_ENCODING_PARAM, "mpegts_service_type" },
     { "mpegts_pmt_start_pid", "Set the first pid of the PMT.",
       offsetof(MpegTSWrite, pmt_start_pid), AV_OPT_TYPE_INT,
       { .i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM },
diff --git a/libavformat/mpjpegdec.c b/libavformat/mpjpegdec.c
index 7a6bbe4..4c77644 100644
--- a/libavformat/mpjpegdec.c
+++ b/libavformat/mpjpegdec.c
@@ -124,7 +124,7 @@ static int mpjpeg_read_probe(AVProbeData *p)
     if (!pb)
         return 0;
 
-    ret = (parse_multipart_header(pb, &size, "--", NULL) > 0) ? AVPROBE_SCORE_MAX : 0;
+    ret = (parse_multipart_header(pb, &size, "--", NULL) >= 0) ? AVPROBE_SCORE_MAX : 0;
 
     av_free(pb);
 
@@ -151,8 +151,8 @@ static int mpjpeg_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_MJPEG;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_MJPEG;
 
     avpriv_set_pts_info(st, 60, 1, 25);
 
@@ -201,7 +201,7 @@ static int parse_multipart_header(AVIOContext *pb,
         if (log_ctx)
         av_log(log_ctx,
             AV_LOG_ERROR,
-            "Expected boundary '%s' not found, instead found a line of %zu bytes\n",
+            "Expected boundary '%s' not found, instead found a line of %"SIZE_SPECIFIER" bytes\n",
             expected_boundary,
             strlen(line));
 
@@ -398,7 +398,8 @@ AVInputFormat ff_mpjpeg_demuxer = {
     .read_header       = mpjpeg_read_header,
     .read_packet       = mpjpeg_read_packet,
     .read_close        = mpjpeg_read_close,
-    .priv_class        = &mpjpeg_demuxer_class
+    .priv_class        = &mpjpeg_demuxer_class,
+    .flags             = AVFMT_NOTIMESTAMPS,
 };
 
 
diff --git a/libavformat/mpl2dec.c b/libavformat/mpl2dec.c
index 81cc0bb..59589d5 100644
--- a/libavformat/mpl2dec.c
+++ b/libavformat/mpl2dec.c
@@ -80,8 +80,8 @@ static int mpl2_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 10);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_MPL2;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_MPL2;
 
     while (!avio_feof(s->pb)) {
         char line[4096];
diff --git a/libavformat/mpsubdec.c b/libavformat/mpsubdec.c
index c5a50ec..1236efa 100644
--- a/libavformat/mpsubdec.c
+++ b/libavformat/mpsubdec.c
@@ -100,8 +100,8 @@ static int mpsub_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_TEXT;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_TEXT;
 
     ff_subtitles_queue_finalize(s, &mpsub->q);
 
diff --git a/libavformat/msf.c b/libavformat/msf.c
index 73a5a01..0551e9b 100644
--- a/libavformat/msf.c
+++ b/libavformat/msf.c
@@ -34,6 +34,9 @@ static int msf_probe(AVProbeData *p)
     if (AV_RB32(p->buf+16) <= 0)
         return 0;
 
+    if (AV_RB32(p->buf+4) > 16)
+        return AVPROBE_SCORE_MAX / 5; //unsupported / unknown codec
+
     return AVPROBE_SCORE_MAX / 3 * 2;
 }
 
@@ -48,41 +51,41 @@ static int msf_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
     codec                  = avio_rb32(s->pb);
-    st->codec->channels    = avio_rb32(s->pb);
-    if (st->codec->channels <= 0 || st->codec->channels >= INT_MAX / 1024)
+    st->codecpar->channels    = avio_rb32(s->pb);
+    if (st->codecpar->channels <= 0 || st->codecpar->channels >= INT_MAX / 1024)
         return AVERROR_INVALIDDATA;
     size = avio_rb32(s->pb);
-    st->codec->sample_rate = avio_rb32(s->pb);
-    if (st->codec->sample_rate <= 0)
+    st->codecpar->sample_rate = avio_rb32(s->pb);
+    if (st->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
     align = avio_rb32(s->pb) ;
-    if (align > INT_MAX / st->codec->channels)
+    if (align > INT_MAX / st->codecpar->channels)
         return AVERROR_INVALIDDATA;
-    st->codec->block_align = align;
+    st->codecpar->block_align = align;
     switch (codec) {
-    case 0: st->codec->codec_id = AV_CODEC_ID_PCM_S16BE; break;
-    case 3: st->codec->block_align = 16 * st->codec->channels;
-            st->codec->codec_id = AV_CODEC_ID_ADPCM_PSX; break;
+    case 0: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; break;
+    case 3: st->codecpar->block_align = 16 * st->codecpar->channels;
+            st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; break;
     case 7: st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
-            st->codec->codec_id = AV_CODEC_ID_MP3;       break;
+            st->codecpar->codec_id = AV_CODEC_ID_MP3;       break;
     default:
             avpriv_request_sample(s, "Codec %d", codec);
             return AVERROR_PATCHWELCOME;
     }
-    st->duration = av_get_audio_frame_duration(st->codec, size);
+    st->duration = av_get_audio_frame_duration2(st->codecpar, size);
     avio_skip(s->pb, 0x40 - avio_tell(s->pb));
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
 
 static int msf_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
-    return av_get_packet(s->pb, pkt, codec->block_align ? codec->block_align : 1024 * codec->channels);
+    return av_get_packet(s->pb, pkt, par->block_align ? par->block_align : 1024 * par->channels);
 }
 
 AVInputFormat ff_msf_demuxer = {
diff --git a/libavformat/msnwc_tcp.c b/libavformat/msnwc_tcp.c
index 5abf006..3c73ac7 100644
--- a/libavformat/msnwc_tcp.c
+++ b/libavformat/msnwc_tcp.c
@@ -74,17 +74,17 @@ static int msnwc_tcp_probe(AVProbeData *p)
 static int msnwc_tcp_read_header(AVFormatContext *ctx)
 {
     AVIOContext *pb = ctx->pb;
-    AVCodecContext *codec;
+    AVCodecParameters *par;
     AVStream *st;
 
     st = avformat_new_stream(ctx, NULL);
     if (!st)
         return AVERROR(ENOMEM);
 
-    codec             = st->codec;
-    codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    codec->codec_id   = AV_CODEC_ID_MIMIC;
-    codec->codec_tag  = MKTAG('M', 'L', '2', '0');
+    par             = st->codecpar;
+    par->codec_type = AVMEDIA_TYPE_VIDEO;
+    par->codec_id   = AV_CODEC_ID_MIMIC;
+    par->codec_tag  = MKTAG('M', 'L', '2', '0');
 
     avpriv_set_pts_info(st, 32, 1, 1000);
 
diff --git a/libavformat/mtaf.c b/libavformat/mtaf.c
new file mode 100644
index 0000000..b25c2aa
--- /dev/null
+++ b/libavformat/mtaf.c
@@ -0,0 +1,81 @@
+/*
+ * MTAF demuxer
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * 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/channel_layout.h"
+#include "libavutil/intreadwrite.h"
+#include "avformat.h"
+#include "internal.h"
+
+static int mtaf_probe(AVProbeData *p)
+{
+    if (p->buf_size < 0x44)
+        return 0;
+
+    if (AV_RL32(p->buf) != MKTAG('M','T','A','F') ||
+        AV_RL32(p->buf + 0x40) != MKTAG('H','E','A','D'))
+        return 0;
+
+    return AVPROBE_SCORE_MAX;
+}
+
+static int mtaf_read_header(AVFormatContext *s)
+{
+    int stream_count;
+    AVStream *st;
+
+    st = avformat_new_stream(s, NULL);
+    if (!st)
+        return AVERROR(ENOMEM);
+
+    avio_skip(s->pb, 0x5c);
+    st->duration = avio_rl32(s->pb);
+    avio_skip(s->pb, 1);
+    stream_count = avio_r8(s->pb);
+    if (!stream_count)
+        return AVERROR_INVALIDDATA;
+
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_MTAF;
+    st->codecpar->channels    = 2 * stream_count;
+    st->codecpar->sample_rate = 48000;
+    st->codecpar->block_align = 0x110 * st->codecpar->channels / 2;
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
+
+    avio_seek(s->pb, 0x800, SEEK_SET);
+
+    return 0;
+}
+
+static int mtaf_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    AVCodecParameters *par = s->streams[0]->codecpar;
+
+    return av_get_packet(s->pb, pkt, par->block_align);
+}
+
+AVInputFormat ff_mtaf_demuxer = {
+    .name           = "mtaf",
+    .long_name      = NULL_IF_CONFIG_SMALL("Konami PS2 MTAF"),
+    .read_probe     = mtaf_probe,
+    .read_header    = mtaf_read_header,
+    .read_packet    = mtaf_read_packet,
+    .extensions     = "mtaf",
+};
diff --git a/libavformat/mtv.c b/libavformat/mtv.c
index a91e4c8..dcf4aa4 100644
--- a/libavformat/mtv.c
+++ b/libavformat/mtv.c
@@ -165,13 +165,13 @@ static int mtv_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     avpriv_set_pts_info(st, 64, 1, mtv->video_fps);
-    st->codec->codec_type      = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id        = AV_CODEC_ID_RAWVIDEO;
-    st->codec->pix_fmt         = AV_PIX_FMT_RGB565BE;
-    st->codec->width           = mtv->img_width;
-    st->codec->height          = mtv->img_height;
-    st->codec->extradata       = av_strdup("BottomUp");
-    st->codec->extradata_size  = 9;
+    st->codecpar->codec_type      = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id        = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->format          = AV_PIX_FMT_RGB565BE;
+    st->codecpar->width           = mtv->img_width;
+    st->codecpar->height          = mtv->img_height;
+    st->codecpar->extradata       = av_strdup("BottomUp");
+    st->codecpar->extradata_size  = 9;
 
     // audio - mp3
 
@@ -180,10 +180,10 @@ static int mtv_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     avpriv_set_pts_info(st, 64, 1, MTV_AUDIO_SAMPLING_RATE);
-    st->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id        = AV_CODEC_ID_MP3;
-    st->codec->bit_rate        = mtv->audio_br;
-    st->need_parsing           = AVSTREAM_PARSE_FULL;
+    st->codecpar->codec_type      = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id        = AV_CODEC_ID_MP3;
+    st->codecpar->bit_rate        = mtv->audio_br;
+    st->need_parsing              = AVSTREAM_PARSE_FULL;
 
     // Jump over header
 
diff --git a/libavformat/musx.c b/libavformat/musx.c
new file mode 100644
index 0000000..aff6c31
--- /dev/null
+++ b/libavformat/musx.c
@@ -0,0 +1,177 @@
+/*
+ * MUSX demuxer
+ * Copyright (c) 2016 Paul B Mahol
+ *
+ * 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/avassert.h"
+#include "avformat.h"
+#include "internal.h"
+
+static int musx_probe(AVProbeData *p)
+{
+    if (memcmp(p->buf, "MUSX", 4))
+        return 0;
+
+    return AVPROBE_SCORE_MAX / 5 * 2;
+}
+
+static int musx_read_header(AVFormatContext *s)
+{
+    unsigned type, version, coding, offset;
+    AVStream *st;
+
+    avio_skip(s->pb, 8);
+    version = avio_rl32(s->pb);
+    if (version != 10 &&
+        version != 6 &&
+        version != 5 &&
+        version != 4 &&
+        version != 201) {
+        avpriv_request_sample(s, "Unsupported version: %d", version);
+        return AVERROR_PATCHWELCOME;
+    }
+    avio_skip(s->pb, 4);
+
+    st = avformat_new_stream(s, NULL);
+    if (!st)
+        return AVERROR(ENOMEM);
+
+    if (version == 201) {
+        avio_skip(s->pb, 8);
+        offset = avio_rl32(s->pb);
+        st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_PSX;
+        st->codecpar->channels    = 2;
+        st->codecpar->sample_rate = 32000;
+        st->codecpar->block_align = 0x80 * st->codecpar->channels;
+    }  else if (version == 10) {
+        type = avio_rl32(s->pb);
+        st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+        offset = 0x800;
+        switch (type) {
+        case MKTAG('P', 'S', '3', '_'):
+            st->codecpar->channels    = 2;
+            st->codecpar->sample_rate = 44100;
+            avio_skip(s->pb, 44);
+            coding = avio_rl32(s->pb);
+            if (coding == MKTAG('D', 'A', 'T', '4') ||
+                coding == MKTAG('D', 'A', 'T', '8')) {
+                avio_skip(s->pb, 4);
+                st->codecpar->channels   = avio_rl32(s->pb);
+                if (st->codecpar->channels <= 0 ||
+                    st->codecpar->channels > INT_MAX / 0x20)
+                    return AVERROR_INVALIDDATA;
+                st->codecpar->sample_rate = avio_rl32(s->pb);
+            }
+            st->codecpar->codec_id   = AV_CODEC_ID_ADPCM_IMA_DAT4;
+            st->codecpar->block_align = 0x20 * st->codecpar->channels;
+            break;
+        case MKTAG('W', 'I', 'I', '_'):
+            avio_skip(s->pb, 44);
+            coding = avio_rl32(s->pb);
+            if (coding != MKTAG('D', 'A', 'T', '4') &&
+                coding != MKTAG('D', 'A', 'T', '8')) {
+                avpriv_request_sample(s, "Unsupported coding: %X", coding);
+                return AVERROR_PATCHWELCOME;
+            }
+            avio_skip(s->pb, 4);
+            st->codecpar->codec_id   = AV_CODEC_ID_ADPCM_IMA_DAT4;
+            st->codecpar->channels   = avio_rl32(s->pb);
+            if (st->codecpar->channels <= 0 ||
+                st->codecpar->channels > INT_MAX / 0x20)
+                return AVERROR_INVALIDDATA;
+            st->codecpar->sample_rate = avio_rl32(s->pb);
+            st->codecpar->block_align = 0x20 * st->codecpar->channels;
+            break;
+        case MKTAG('X', 'E', '_', '_'):
+            st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_IMA_DAT4;
+            st->codecpar->channels    = 2;
+            st->codecpar->sample_rate = 32000;
+            st->codecpar->block_align = 0x20 * st->codecpar->channels;
+            break;
+        case MKTAG('P', 'S', 'P', '_'):
+            st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_PSX;
+            st->codecpar->channels    = 2;
+            st->codecpar->sample_rate = 32768;
+            st->codecpar->block_align = 0x80 * st->codecpar->channels;
+            break;
+        case MKTAG('P', 'S', '2', '_'):
+            st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_PSX;
+            st->codecpar->channels    = 2;
+            st->codecpar->sample_rate = 32000;
+            st->codecpar->block_align = 0x80 * st->codecpar->channels;
+            break;
+        default:
+            avpriv_request_sample(s, "Unsupported type: %X", type);
+            return AVERROR_PATCHWELCOME;
+        }
+    } else if (version == 6 || version == 5 || version == 4) {
+        type = avio_rl32(s->pb);
+        avio_skip(s->pb, 20);
+        st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->channels    = 2;
+        switch (type) {
+        case MKTAG('G', 'C', '_', '_'):
+            st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_IMA_DAT4;
+            st->codecpar->block_align = 0x20 * st->codecpar->channels;
+            st->codecpar->sample_rate = 32000;
+            offset = avio_rb32(s->pb);
+            break;
+        case MKTAG('P', 'S', '2', '_'):
+            st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_PSX;
+            st->codecpar->block_align = 0x80 * st->codecpar->channels;
+            st->codecpar->sample_rate = 32000;
+            offset = avio_rl32(s->pb);
+            break;
+        case MKTAG('X', 'B', '_', '_'):
+            st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_IMA_DAT4;
+            st->codecpar->block_align = 0x20 * st->codecpar->channels;
+            st->codecpar->sample_rate = 44100;
+            offset = avio_rl32(s->pb);
+            break;
+        default:
+            avpriv_request_sample(s, "Unsupported type: %X", type);
+            return AVERROR_PATCHWELCOME;
+        }
+    } else {
+        av_assert0(0);
+    }
+
+    avio_seek(s->pb, offset, SEEK_SET);
+
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
+
+    return 0;
+}
+
+static int musx_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    AVCodecParameters *par = s->streams[0]->codecpar;
+
+    return av_get_packet(s->pb, pkt, par->block_align);
+}
+
+AVInputFormat ff_musx_demuxer = {
+    .name           = "musx",
+    .long_name      = NULL_IF_CONFIG_SMALL("Eurocom MUSX"),
+    .read_probe     = musx_probe,
+    .read_header    = musx_read_header,
+    .read_packet    = musx_read_packet,
+    .extensions     = "musx",
+};
diff --git a/libavformat/mux.c b/libavformat/mux.c
index f14bfd5..a447645 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -117,24 +117,24 @@ AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precisio
 
 enum AVChromaLocation ff_choose_chroma_location(AVFormatContext *s, AVStream *st)
 {
-    AVCodecContext *avctx = st->codec;
-    const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(avctx->pix_fmt);
+    AVCodecParameters *par = st->codecpar;
+    const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(par->format);
 
-    if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED)
-        return avctx->chroma_sample_location;
+    if (par->chroma_location != AVCHROMA_LOC_UNSPECIFIED)
+        return par->chroma_location;
 
     if (pix_desc) {
         if (pix_desc->log2_chroma_h == 0) {
             return AVCHROMA_LOC_TOPLEFT;
         } else if (pix_desc->log2_chroma_w == 1 && pix_desc->log2_chroma_h == 1) {
-            if (avctx->field_order == AV_FIELD_UNKNOWN || avctx->field_order == AV_FIELD_PROGRESSIVE) {
-                switch (avctx->codec_id) {
+            if (par->field_order == AV_FIELD_UNKNOWN || par->field_order == AV_FIELD_PROGRESSIVE) {
+                switch (par->codec_id) {
                 case AV_CODEC_ID_MJPEG:
                 case AV_CODEC_ID_MPEG1VIDEO: return AVCHROMA_LOC_CENTER;
                 }
             }
-            if (avctx->field_order == AV_FIELD_UNKNOWN || avctx->field_order != AV_FIELD_PROGRESSIVE) {
-                switch (avctx->codec_id) {
+            if (par->field_order == AV_FIELD_UNKNOWN || par->field_order != AV_FIELD_PROGRESSIVE) {
+                switch (par->codec_id) {
                 case AV_CODEC_ID_MPEG2VIDEO: return AVCHROMA_LOC_LEFT;
                 }
             }
@@ -214,12 +214,12 @@ static int validate_codec_tag(AVFormatContext *s, AVStream *st)
     for (n = 0; s->oformat->codec_tag[n]; n++) {
         avctag = s->oformat->codec_tag[n];
         while (avctag->id != AV_CODEC_ID_NONE) {
-            if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(st->codec->codec_tag)) {
+            if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(st->codecpar->codec_tag)) {
                 id = avctag->id;
-                if (id == st->codec->codec_id)
+                if (id == st->codecpar->codec_id)
                     return 1;
             }
-            if (avctag->id == st->codec->codec_id)
+            if (avctag->id == st->codecpar->codec_id)
                 tag = avctag->tag;
             avctag++;
         }
@@ -237,7 +237,7 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
     int ret = 0, i;
     AVStream *st;
     AVDictionary *tmp = NULL;
-    AVCodecContext *codec = NULL;
+    AVCodecParameters *par = NULL;
     AVOutputFormat *of = s->oformat;
     const AVCodecDescriptor *desc;
     AVDictionaryEntry *e;
@@ -251,6 +251,8 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
         (ret = av_opt_set_dict2(s->priv_data, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0)
         goto fail;
 
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
     if (s->nb_streams && s->streams[0]->codec->flags & AV_CODEC_FLAG_BITEXACT) {
         if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
 #if FF_API_LAVF_BITEXACT
@@ -268,6 +270,8 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
 #endif
         }
     }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     // some sanity checks
     if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) {
@@ -277,58 +281,78 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options)
     }
 
     for (i = 0; i < s->nb_streams; i++) {
-        st    = s->streams[i];
-        codec = st->codec;
+        st  = s->streams[i];
+        par = st->codecpar;
 
-#if FF_API_LAVF_CODEC_TB
+#if FF_API_LAVF_CODEC_TB && FF_API_LAVF_AVCTX
 FF_DISABLE_DEPRECATION_WARNINGS
-        if (!st->time_base.num && codec->time_base.num) {
+        if (!st->time_base.num && st->codec->time_base.num) {
             av_log(s, AV_LOG_WARNING, "Using AVStream.codec.time_base as a "
                    "timebase hint to the muxer is deprecated. Set "
                    "AVStream.time_base instead.\n");
-            avpriv_set_pts_info(st, 64, codec->time_base.num, codec->time_base.den);
+            avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den);
         }
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_UNKNOWN &&
+            st->codec->codec_type    != AVMEDIA_TYPE_UNKNOWN) {
+            av_log(s, AV_LOG_WARNING, "Using AVStream.codec to pass codec "
+                   "parameters to muxers is deprecated, use AVStream.codecpar "
+                   "instead.\n");
+            ret = avcodec_parameters_from_context(st->codecpar, st->codec);
+            if (ret < 0)
+                goto fail;
+        }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+        /* update internal context from codecpar, old bsf api needs this
+         * FIXME: remove when autobsf uses new bsf API */
+        ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
+        if (ret < 0)
+            goto fail;
+
         if (!st->time_base.num) {
             /* fall back on the default timebase values */
-            if (codec->codec_type == AVMEDIA_TYPE_AUDIO && codec->sample_rate)
-                avpriv_set_pts_info(st, 64, 1, codec->sample_rate);
+            if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->sample_rate)
+                avpriv_set_pts_info(st, 64, 1, par->sample_rate);
             else
                 avpriv_set_pts_info(st, 33, 1, 90000);
         }
 
-        switch (codec->codec_type) {
+        switch (par->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
-            if (codec->sample_rate <= 0) {
+            if (par->sample_rate <= 0) {
                 av_log(s, AV_LOG_ERROR, "sample rate not set\n");
                 ret = AVERROR(EINVAL);
                 goto fail;
             }
-            if (!codec->block_align)
-                codec->block_align = codec->channels *
-                                     av_get_bits_per_sample(codec->codec_id) >> 3;
+            if (!par->block_align)
+                par->block_align = par->channels *
+                                   av_get_bits_per_sample(par->codec_id) >> 3;
             break;
         case AVMEDIA_TYPE_VIDEO:
-            if ((codec->width <= 0 || codec->height <= 0) &&
+            if ((par->width <= 0 || par->height <= 0) &&
                 !(of->flags & AVFMT_NODIMENSIONS)) {
                 av_log(s, AV_LOG_ERROR, "dimensions not set\n");
                 ret = AVERROR(EINVAL);
                 goto fail;
             }
-            if (av_cmp_q(st->sample_aspect_ratio, codec->sample_aspect_ratio)
-                && fabs(av_q2d(st->sample_aspect_ratio) - av_q2d(codec->sample_aspect_ratio)) > 0.004*av_q2d(st->sample_aspect_ratio)
+            if (av_cmp_q(st->sample_aspect_ratio, par->sample_aspect_ratio)
+                && fabs(av_q2d(st->sample_aspect_ratio) - av_q2d(par->sample_aspect_ratio)) > 0.004*av_q2d(st->sample_aspect_ratio)
             ) {
                 if (st->sample_aspect_ratio.num != 0 &&
                     st->sample_aspect_ratio.den != 0 &&
-                    codec->sample_aspect_ratio.num != 0 &&
-                    codec->sample_aspect_ratio.den != 0) {
+                    par->sample_aspect_ratio.num != 0 &&
+                    par->sample_aspect_ratio.den != 0) {
                     av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between muxer "
                            "(%d/%d) and encoder layer (%d/%d)\n",
                            st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
-                           codec->sample_aspect_ratio.num,
-                           codec->sample_aspect_ratio.den);
+                           par->sample_aspect_ratio.num,
+                           par->sample_aspect_ratio.den);
                     ret = AVERROR(EINVAL);
                     goto fail;
                 }
@@ -336,36 +360,36 @@ FF_ENABLE_DEPRECATION_WARNINGS
             break;
         }
 
-        desc = avcodec_descriptor_get(codec->codec_id);
+        desc = avcodec_descriptor_get(par->codec_id);
         if (desc && desc->props & AV_CODEC_PROP_REORDER)
             st->internal->reorder = 1;
 
         if (of->codec_tag) {
-            if (   codec->codec_tag
-                && codec->codec_id == AV_CODEC_ID_RAWVIDEO
-                && (   av_codec_get_tag(of->codec_tag, codec->codec_id) == 0
-                    || av_codec_get_tag(of->codec_tag, codec->codec_id) == MKTAG('r', 'a', 'w', ' '))
+            if (   par->codec_tag
+                && par->codec_id == AV_CODEC_ID_RAWVIDEO
+                && (   av_codec_get_tag(of->codec_tag, par->codec_id) == 0
+                    || av_codec_get_tag(of->codec_tag, par->codec_id) == MKTAG('r', 'a', 'w', ' '))
                 && !validate_codec_tag(s, st)) {
                 // the current rawvideo encoding system ends up setting
                 // the wrong codec_tag for avi/mov, we override it here
-                codec->codec_tag = 0;
+                par->codec_tag = 0;
             }
-            if (codec->codec_tag) {
+            if (par->codec_tag) {
                 if (!validate_codec_tag(s, st)) {
                     char tagbuf[32], tagbuf2[32];
-                    av_get_codec_tag_string(tagbuf, sizeof(tagbuf), codec->codec_tag);
-                    av_get_codec_tag_string(tagbuf2, sizeof(tagbuf2), av_codec_get_tag(s->oformat->codec_tag, codec->codec_id));
+                    av_get_codec_tag_string(tagbuf, sizeof(tagbuf), par->codec_tag);
+                    av_get_codec_tag_string(tagbuf2, sizeof(tagbuf2), av_codec_get_tag(s->oformat->codec_tag, par->codec_id));
                     av_log(s, AV_LOG_ERROR,
                            "Tag %s/0x%08x incompatible with output codec id '%d' (%s)\n",
-                           tagbuf, codec->codec_tag, codec->codec_id, tagbuf2);
+                           tagbuf, par->codec_tag, par->codec_id, tagbuf2);
                     ret = AVERROR_INVALIDDATA;
                     goto fail;
                 }
             } else
-                codec->codec_tag = av_codec_get_tag(of->codec_tag, codec->codec_id);
+                par->codec_tag = av_codec_get_tag(of->codec_tag, par->codec_id);
         }
 
-        if (codec->codec_type != AVMEDIA_TYPE_ATTACHMENT)
+        if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT)
             s->internal->nb_interleaved_streams++;
     }
 
@@ -422,12 +446,12 @@ static int init_pts(AVFormatContext *s)
         int64_t den = AV_NOPTS_VALUE;
         st = s->streams[i];
 
-        switch (st->codec->codec_type) {
+        switch (st->codecpar->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
-            den = (int64_t)st->time_base.num * st->codec->sample_rate;
+            den = (int64_t)st->time_base.num * st->codecpar->sample_rate;
             break;
         case AVMEDIA_TYPE_VIDEO:
-            den = (int64_t)st->time_base.num * st->codec->time_base.den;
+            den = (int64_t)st->time_base.num * st->time_base.den;
             break;
         default:
             break;
@@ -449,6 +473,26 @@ static int init_pts(AVFormatContext *s)
     return 0;
 }
 
+static int write_header_internal(AVFormatContext *s)
+{
+    if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+        avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
+    if (s->oformat->write_header) {
+        int ret = s->oformat->write_header(s);
+        if (ret >= 0 && s->pb && s->pb->error < 0)
+            ret = s->pb->error;
+        s->internal->write_header_ret = ret;
+        if (ret < 0)
+            return ret;
+        if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
+            avio_flush(s->pb);
+    }
+    s->internal->header_written = 1;
+    if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+        avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN);
+    return 0;
+}
+
 int avformat_write_header(AVFormatContext *s, AVDictionary **options)
 {
     int ret = 0;
@@ -456,19 +500,14 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
     if ((ret = init_muxer(s, options)) < 0)
         return ret;
 
-    if (s->oformat->write_header && !s->oformat->check_bitstream) {
-        ret = s->oformat->write_header(s);
-        if (ret >= 0 && s->pb && s->pb->error < 0)
-            ret = s->pb->error;
+    if (!s->oformat->check_bitstream) {
+        ret = write_header_internal(s);
         if (ret < 0)
-            return ret;
-        if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
-            avio_flush(s->pb);
-        s->internal->header_written = 1;
+            goto fail;
     }
 
     if ((ret = init_pts(s)) < 0)
-        return ret;
+        goto fail;
 
     if (s->avoid_negative_ts < 0) {
         av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
@@ -479,6 +518,11 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
     }
 
     return 0;
+
+fail:
+    if (s->oformat->deinit)
+        s->oformat->deinit(s);
+    return ret;
 }
 
 #define AV_PKT_FLAG_UNCODED_FRAME 0x2000
@@ -490,11 +534,12 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
 #define UNCODED_FRAME_PACKET_SIZE (INT_MIN / 3 * 2 + (int)sizeof(AVFrame))
 
 
-#if FF_API_COMPUTE_PKT_FIELDS2
+#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
 //FIXME merge with compute_pkt_fields
 static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *pkt)
 {
-    int delay = FFMAX(st->codec->has_b_frames, st->codec->max_b_frames > 0);
+    int delay = FFMAX(st->codecpar->video_delay, st->internal->avctx->max_b_frames > 0);
     int num, den, i;
     int frame_size;
 
@@ -554,7 +599,8 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *
 
     if (st->cur_dts && st->cur_dts != AV_NOPTS_VALUE &&
         ((!(s->oformat->flags & AVFMT_TS_NONSTRICT) &&
-          st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE &&
+          st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE &&
+          st->codecpar->codec_type != AVMEDIA_TYPE_DATA &&
           st->cur_dts >= pkt->dts) || st->cur_dts > pkt->dts)) {
         av_log(s, AV_LOG_ERROR,
                "Application provided invalid, non monotonically increasing dts to muxer in stream %d: %s >= %s\n",
@@ -591,11 +637,12 @@ static int compute_muxer_pkt_fields(AVFormatContext *s, AVStream *st, AVPacket *
         }
         break;
     case AVMEDIA_TYPE_VIDEO:
-        frac_add(st->priv_pts, (int64_t)st->time_base.den * st->codec->time_base.num);
+        frac_add(st->priv_pts, (int64_t)st->time_base.den * st->time_base.num);
         break;
     }
     return 0;
 }
+FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
 /**
@@ -670,15 +717,10 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
 
     did_split = av_packet_split_side_data(pkt);
 
-    if (!s->internal->header_written && s->oformat->write_header) {
-        ret = s->oformat->write_header(s);
-        if (ret >= 0 && s->pb && s->pb->error < 0)
-            ret = s->pb->error;
+    if (!s->internal->header_written) {
+        ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s);
         if (ret < 0)
             goto fail;
-        if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
-            avio_flush(s->pb);
-        s->internal->header_written = 1;
     }
 
     if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) {
@@ -715,7 +757,7 @@ static int check_packet(AVFormatContext *s, AVPacket *pkt)
         return AVERROR(EINVAL);
     }
 
-    if (s->streams[pkt->stream_index]->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
+    if (s->streams[pkt->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
         av_log(s, AV_LOG_ERROR, "Received a packet for an attachment stream.\n");
         return AVERROR(EINVAL);
     }
@@ -731,7 +773,7 @@ static int prepare_input_packet(AVFormatContext *s, AVPacket *pkt)
     if (ret < 0)
         return ret;
 
-#if !FF_API_COMPUTE_PKT_FIELDS2
+#if !FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX
     /* sanitize the timestamps */
     if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) {
         AVStream *st = s->streams[pkt->stream_index];
@@ -785,6 +827,11 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
 
     if (!pkt) {
         if (s->oformat->flags & AVFMT_ALLOW_FLUSH) {
+            if (!s->internal->header_written) {
+                ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s);
+                if (ret < 0)
+                    return ret;
+            }
             ret = s->oformat->write_packet(s, NULL);
             if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
                 avio_flush(s->pb);
@@ -795,7 +842,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
         return 1;
     }
 
-#if FF_API_COMPUTE_PKT_FIELDS2
+#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX
     ret = compute_muxer_pkt_fields(s, s->streams[pkt->stream_index], pkt);
 
     if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
@@ -853,7 +900,7 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt,
             st->interleaver_chunk_size      = 0;
             this_pktl->pkt.flags |= CHUNK_START;
             if (max && st->interleaver_chunk_duration > max) {
-                int64_t syncoffset = (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)*max/2;
+                int64_t syncoffset = (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)*max/2;
                 int64_t syncto = av_rescale(pkt->dts + syncoffset, 1, max)*max - syncoffset;
 
                 st->interleaver_chunk_duration += (pkt->dts - syncto)/8 - max;
@@ -898,12 +945,12 @@ static int interleave_compare_dts(AVFormatContext *s, AVPacket *next,
     AVStream *st2 = s->streams[next->stream_index];
     int comp      = av_compare_ts(next->dts, st2->time_base, pkt->dts,
                                   st->time_base);
-    if (s->audio_preload && ((st->codec->codec_type == AVMEDIA_TYPE_AUDIO) != (st2->codec->codec_type == AVMEDIA_TYPE_AUDIO))) {
-        int64_t ts = av_rescale_q(pkt ->dts, st ->time_base, AV_TIME_BASE_Q) - s->audio_preload*(st ->codec->codec_type == AVMEDIA_TYPE_AUDIO);
-        int64_t ts2= av_rescale_q(next->dts, st2->time_base, AV_TIME_BASE_Q) - s->audio_preload*(st2->codec->codec_type == AVMEDIA_TYPE_AUDIO);
+    if (s->audio_preload && ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) != (st2->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))) {
+        int64_t ts = av_rescale_q(pkt ->dts, st ->time_base, AV_TIME_BASE_Q) - s->audio_preload*(st ->codecpar->codec_type == AVMEDIA_TYPE_AUDIO);
+        int64_t ts2= av_rescale_q(next->dts, st2->time_base, AV_TIME_BASE_Q) - s->audio_preload*(st2->codecpar->codec_type == AVMEDIA_TYPE_AUDIO);
         if (ts == ts2) {
-            ts= ( pkt ->dts* st->time_base.num*AV_TIME_BASE - s->audio_preload*(int64_t)(st ->codec->codec_type == AVMEDIA_TYPE_AUDIO)* st->time_base.den)*st2->time_base.den
-               -( next->dts*st2->time_base.num*AV_TIME_BASE - s->audio_preload*(int64_t)(st2->codec->codec_type == AVMEDIA_TYPE_AUDIO)*st2->time_base.den)* st->time_base.den;
+            ts= ( pkt ->dts* st->time_base.num*AV_TIME_BASE - s->audio_preload*(int64_t)(st ->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)* st->time_base.den)*st2->time_base.den
+               -( next->dts*st2->time_base.num*AV_TIME_BASE - s->audio_preload*(int64_t)(st2->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)*st2->time_base.den)* st->time_base.den;
             ts2=0;
         }
         comp= (ts>ts2) - (ts<ts2);
@@ -930,9 +977,9 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out,
     for (i = 0; i < s->nb_streams; i++) {
         if (s->streams[i]->last_in_packet_buffer) {
             ++stream_count;
-        } else if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_ATTACHMENT &&
-                   s->streams[i]->codec->codec_id != AV_CODEC_ID_VP8 &&
-                   s->streams[i]->codec->codec_id != AV_CODEC_ID_VP9) {
+        } else if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT &&
+                   s->streams[i]->codecpar->codec_id != AV_CODEC_ID_VP8 &&
+                   s->streams[i]->codecpar->codec_id != AV_CODEC_ID_VP9) {
             ++noninterleaved_count;
         }
     }
@@ -994,6 +1041,25 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out,
     }
 }
 
+const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream, int64_t *ts_offset)
+{
+    AVPacketList *pktl = s->internal->packet_buffer;
+    while (pktl) {
+        if (pktl->pkt.stream_index == stream) {
+            AVPacket *pkt = &pktl->pkt;
+            AVStream *st = s->streams[pkt->stream_index];
+            *ts_offset = st->mux_ts_offset;
+
+            if (s->output_ts_offset)
+                *ts_offset += av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, st->time_base);
+
+            return pkt;
+        }
+        pktl = pktl->next;
+    }
+    return NULL;
+}
+
 /**
  * Interleave an AVPacket correctly so it can be muxed.
  * @param out the interleaved packet will be output here
@@ -1016,7 +1082,7 @@ static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, in
 
 int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
 {
-    int ret, flush = 0;
+    int ret, flush = 0, i;
 
     ret = prepare_input_packet(s, pkt);
     if (ret < 0)
@@ -1025,11 +1091,56 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
     if (pkt) {
         AVStream *st = s->streams[pkt->stream_index];
 
+        if (s->oformat->check_bitstream) {
+            if (!st->internal->bitstream_checked) {
+                if ((ret = s->oformat->check_bitstream(s, pkt)) < 0)
+                    goto fail;
+                else if (ret == 1)
+                    st->internal->bitstream_checked = 1;
+            }
+        }
+
+        for (i = 0; i < st->internal->nb_bsfcs; i++) {
+            AVBSFContext *ctx = st->internal->bsfcs[i];
+            if (i > 0) {
+                AVBSFContext* prev_ctx = st->internal->bsfcs[i - 1];
+                if (prev_ctx->par_out->extradata_size != ctx->par_in->extradata_size) {
+                    if ((ret = avcodec_parameters_copy(ctx->par_in, prev_ctx->par_out)) < 0)
+                        goto fail;
+                }
+            }
+            // TODO: when any bitstream filter requires flushing at EOF, we'll need to
+            // flush each stream's BSF chain on write_trailer.
+            if ((ret = av_bsf_send_packet(ctx, pkt)) < 0) {
+                av_log(ctx, AV_LOG_ERROR,
+                       "Failed to send packet to filter %s for stream %d",
+                       ctx->filter->name, pkt->stream_index);
+                goto fail;
+            }
+            // TODO: when any automatically-added bitstream filter is generating multiple
+            // output packets for a single input one, we'll need to call this in a loop
+            // and write each output packet.
+            if ((ret = av_bsf_receive_packet(ctx, pkt)) < 0) {
+                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+                    return 0;
+                av_log(ctx, AV_LOG_ERROR,
+                       "Failed to send packet to filter %s for stream %d",
+                       ctx->filter->name, pkt->stream_index);
+                goto fail;
+            }
+            if (i == st->internal->nb_bsfcs - 1) {
+                if (ctx->par_out->extradata_size != st->codecpar->extradata_size) {
+                    if ((ret = avcodec_parameters_copy(st->codecpar, ctx->par_out)) < 0)
+                        goto fail;
+                }
+            }
+        }
+
         if (s->debug & FF_FDEBUG_TS)
             av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame size:%d dts:%s pts:%s\n",
                 pkt->size, av_ts2str(pkt->dts), av_ts2str(pkt->pts));
 
-#if FF_API_COMPUTE_PKT_FIELDS2
+#if FF_API_COMPUTE_PKT_FIELDS2 && FF_API_LAVF_AVCTX
         if ((ret = compute_muxer_pkt_fields(s, st, pkt)) < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS))
             goto fail;
 #endif
@@ -1038,17 +1149,6 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
             ret = AVERROR(EINVAL);
             goto fail;
         }
-
-        if (s->oformat->check_bitstream) {
-            if (!st->internal->bitstream_checked) {
-                if ((ret = s->oformat->check_bitstream(s, pkt)) < 0)
-                    goto fail;
-                else if (ret == 1)
-                    st->internal->bitstream_checked = 1;
-            }
-        }
-
-        av_apply_bitstream_filters(st->codec, pkt, st->internal->bsfc);
     } else {
         av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n");
         flush = 1;
@@ -1105,24 +1205,22 @@ int av_write_trailer(AVFormatContext *s)
             goto fail;
     }
 
-    if (!s->internal->header_written && s->oformat->write_header) {
-        ret = s->oformat->write_header(s);
-        if (ret >= 0 && s->pb && s->pb->error < 0)
-            ret = s->pb->error;
+    if (!s->internal->header_written) {
+        ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s);
         if (ret < 0)
             goto fail;
-        if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
-            avio_flush(s->pb);
-        s->internal->header_written = 1;
     }
 
 fail:
-    if ((s->internal->header_written || !s->oformat->write_header) && s->oformat->write_trailer)
+    if (s->internal->header_written && s->oformat->write_trailer) {
+        if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
+            avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
         if (ret >= 0) {
         ret = s->oformat->write_trailer(s);
         } else {
             s->oformat->write_trailer(s);
         }
+    }
 
     if (s->oformat->deinit)
         s->oformat->deinit(s);
diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c
index 7aa6452..80ef4b1 100644
--- a/libavformat/mvdec.c
+++ b/libavformat/mvdec.c
@@ -106,9 +106,9 @@ static int set_channels(AVFormatContext *avctx, AVStream *st, int channels)
         av_log(avctx, AV_LOG_ERROR, "Channel count %d invalid.\n", channels);
         return AVERROR_INVALIDDATA;
     }
-    st->codec->channels       = channels;
-    st->codec->channel_layout = (st->codec->channels == 1) ? AV_CH_LAYOUT_MONO
-                                                           : AV_CH_LAYOUT_STEREO;
+    st->codecpar->channels       = channels;
+    st->codecpar->channel_layout = (st->codecpar->channels == 1) ? AV_CH_LAYOUT_MONO
+                                                                 : AV_CH_LAYOUT_STEREO;
     return 0;
 }
 
@@ -156,10 +156,10 @@ static int parse_audio_var(AVFormatContext *avctx, AVStream *st,
     } else if (!strcmp(name, "NUM_CHANNELS")) {
         return set_channels(avctx, st, var_read_int(pb, size));
     } else if (!strcmp(name, "SAMPLE_RATE")) {
-        st->codec->sample_rate = var_read_int(pb, size);
-        avpriv_set_pts_info(st, 33, 1, st->codec->sample_rate);
+        st->codecpar->sample_rate = var_read_int(pb, size);
+        avpriv_set_pts_info(st, 33, 1, st->codecpar->sample_rate);
     } else if (!strcmp(name, "SAMPLE_WIDTH")) {
-        st->codec->bits_per_coded_sample = var_read_int(pb, size) * 8;
+        st->codecpar->bits_per_coded_sample = var_read_int(pb, size) * 8;
     } else
         return AVERROR_INVALIDDATA;
 
@@ -181,16 +181,16 @@ static int parse_video_var(AVFormatContext *avctx, AVStream *st,
         if (!str)
             return AVERROR_INVALIDDATA;
         if (!strcmp(str, "1")) {
-            st->codec->codec_id = AV_CODEC_ID_MVC1;
+            st->codecpar->codec_id = AV_CODEC_ID_MVC1;
         } else if (!strcmp(str, "2")) {
-            st->codec->pix_fmt  = AV_PIX_FMT_ABGR;
-            st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+            st->codecpar->format = AV_PIX_FMT_ABGR;
+            st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
         } else if (!strcmp(str, "3")) {
-            st->codec->codec_id = AV_CODEC_ID_SGIRLE;
+            st->codecpar->codec_id = AV_CODEC_ID_SGIRLE;
         } else if (!strcmp(str, "10")) {
-            st->codec->codec_id = AV_CODEC_ID_MJPEG;
+            st->codecpar->codec_id = AV_CODEC_ID_MJPEG;
         } else if (!strcmp(str, "MVC2")) {
-            st->codec->codec_id = AV_CODEC_ID_MVC2;
+            st->codecpar->codec_id = AV_CODEC_ID_MVC2;
         } else {
             avpriv_request_sample(avctx, "Video compression %s", str);
         }
@@ -200,18 +200,18 @@ static int parse_video_var(AVFormatContext *avctx, AVStream *st,
         avpriv_set_pts_info(st, 64, fps.den, fps.num);
         st->avg_frame_rate = fps;
     } else if (!strcmp(name, "HEIGHT")) {
-        st->codec->height = var_read_int(pb, size);
+        st->codecpar->height = var_read_int(pb, size);
     } else if (!strcmp(name, "PIXEL_ASPECT")) {
         st->sample_aspect_ratio = var_read_float(pb, size);
         av_reduce(&st->sample_aspect_ratio.num, &st->sample_aspect_ratio.den,
                   st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
                   INT_MAX);
     } else if (!strcmp(name, "WIDTH")) {
-        st->codec->width = var_read_int(pb, size);
+        st->codecpar->width = var_read_int(pb, size);
     } else if (!strcmp(name, "ORIENTATION")) {
         if (var_read_int(pb, size) == 1101) {
-            st->codec->extradata      = av_strdup("BottomUp");
-            st->codec->extradata_size = 9;
+            st->codecpar->extradata      = av_strdup("BottomUp");
+            st->codecpar->extradata_size = 9;
         }
     } else if (!strcmp(name, "Q_SPATIAL") || !strcmp(name, "Q_TEMPORAL")) {
         var_read_metadata(avctx, name, size);
@@ -259,8 +259,8 @@ static void read_index(AVIOContext *pb, AVStream *st)
         uint32_t size = avio_rb32(pb);
         avio_skip(pb, 8);
         av_add_index_entry(st, pos, timestamp, size, 0, AVINDEX_KEYFRAME);
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            timestamp += size / (st->codec->channels * 2);
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            timestamp += size / (st->codecpar->channels * 2);
         } else {
             timestamp++;
         }
@@ -293,37 +293,37 @@ static int mv_read_header(AVFormatContext *avctx)
         if (!vst)
             return AVERROR(ENOMEM);
         avpriv_set_pts_info(vst, 64, 1, 15);
-        vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+        vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
         vst->avg_frame_rate    = av_inv_q(vst->time_base);
         vst->nb_frames         = avio_rb32(pb);
         v = avio_rb32(pb);
         switch (v) {
         case 1:
-            vst->codec->codec_id = AV_CODEC_ID_MVC1;
+            vst->codecpar->codec_id = AV_CODEC_ID_MVC1;
             break;
         case 2:
-            vst->codec->pix_fmt  = AV_PIX_FMT_ARGB;
-            vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+            vst->codecpar->format = AV_PIX_FMT_ARGB;
+            vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
             break;
         default:
             avpriv_request_sample(avctx, "Video compression %i", v);
             break;
         }
-        vst->codec->codec_tag = 0;
-        vst->codec->width     = avio_rb32(pb);
-        vst->codec->height    = avio_rb32(pb);
+        vst->codecpar->codec_tag = 0;
+        vst->codecpar->width     = avio_rb32(pb);
+        vst->codecpar->height    = avio_rb32(pb);
         avio_skip(pb, 12);
 
-        ast->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
+        ast->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
         ast->nb_frames          = vst->nb_frames;
-        ast->codec->sample_rate = avio_rb32(pb);
-        avpriv_set_pts_info(ast, 33, 1, ast->codec->sample_rate);
+        ast->codecpar->sample_rate = avio_rb32(pb);
+        avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate);
         if (set_channels(avctx, ast, avio_rb32(pb)) < 0)
             return AVERROR_INVALIDDATA;
 
         v = avio_rb32(pb);
         if (v == AUDIO_FORMAT_SIGNED) {
-            ast->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
+            ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
         } else {
             avpriv_request_sample(avctx, "Audio compression (format %i)", v);
         }
@@ -341,7 +341,7 @@ static int mv_read_header(AVFormatContext *avctx)
             avio_skip(pb, 8);
             av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME);
             av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME);
-            timestamp += asize / (ast->codec->channels * 2);
+            timestamp += asize / (ast->codecpar->channels * 2);
         }
     } else if (!version && avio_rb16(pb) == 3) {
         avio_skip(pb, 4);
@@ -356,21 +356,21 @@ static int mv_read_header(AVFormatContext *avctx)
             ast = avformat_new_stream(avctx, NULL);
             if (!ast)
                 return AVERROR(ENOMEM);
-            ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+            ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
             if ((read_table(avctx, ast, parse_audio_var)) < 0)
                 return ret;
             if (mv->acompression == 100 &&
                 mv->aformat == AUDIO_FORMAT_SIGNED &&
-                ast->codec->bits_per_coded_sample == 16) {
-                ast->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
+                ast->codecpar->bits_per_coded_sample == 16) {
+                ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
             } else {
                 avpriv_request_sample(avctx,
                                       "Audio compression %i (format %i, sr %i)",
                                       mv->acompression, mv->aformat,
-                                      ast->codec->bits_per_coded_sample);
-                ast->codec->codec_id = AV_CODEC_ID_NONE;
+                                      ast->codecpar->bits_per_coded_sample);
+                ast->codecpar->codec_id = AV_CODEC_ID_NONE;
             }
-            if (ast->codec->channels <= 0) {
+            if (ast->codecpar->channels <= 0) {
                 av_log(avctx, AV_LOG_ERROR, "No valid channel count found.\n");
                 return AVERROR_INVALIDDATA;
             }
@@ -383,7 +383,7 @@ static int mv_read_header(AVFormatContext *avctx)
             vst = avformat_new_stream(avctx, NULL);
             if (!vst)
                 return AVERROR(ENOMEM);
-            vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+            vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
             if ((ret = read_table(avctx, vst, parse_video_var))<0)
                 return ret;
         }
diff --git a/libavformat/mvi.c b/libavformat/mvi.c
index a7cfcb9..9f90faf 100644
--- a/libavformat/mvi.c
+++ b/libavformat/mvi.c
@@ -54,18 +54,18 @@ static int read_header(AVFormatContext *s)
     if (!vst)
         return AVERROR(ENOMEM);
 
-    if (ff_alloc_extradata(vst->codec, 2))
+    if (ff_alloc_extradata(vst->codecpar, 2))
         return AVERROR(ENOMEM);
 
     version                  = avio_r8(pb);
-    vst->codec->extradata[0] = avio_r8(pb);
-    vst->codec->extradata[1] = avio_r8(pb);
+    vst->codecpar->extradata[0] = avio_r8(pb);
+    vst->codecpar->extradata[1] = avio_r8(pb);
     frames_count             = avio_rl32(pb);
     msecs_per_frame          = avio_rl32(pb);
-    vst->codec->width        = avio_rl16(pb);
-    vst->codec->height       = avio_rl16(pb);
+    vst->codecpar->width        = avio_rl16(pb);
+    vst->codecpar->height       = avio_rl16(pb);
     avio_r8(pb);
-    ast->codec->sample_rate  = avio_rl16(pb);
+    ast->codecpar->sample_rate  = avio_rl16(pb);
     mvi->audio_data_size     = avio_rl32(pb);
     avio_r8(pb);
     player_version           = avio_rl32(pb);
@@ -80,20 +80,20 @@ static int read_header(AVFormatContext *s)
         return AVERROR_INVALIDDATA;
     }
 
-    avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
-    ast->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
-    ast->codec->codec_id        = AV_CODEC_ID_PCM_U8;
-    ast->codec->channels        = 1;
-    ast->codec->channel_layout  = AV_CH_LAYOUT_MONO;
-    ast->codec->bits_per_coded_sample = 8;
-    ast->codec->bit_rate        = ast->codec->sample_rate * 8;
+    avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
+    ast->codecpar->codec_type      = AVMEDIA_TYPE_AUDIO;
+    ast->codecpar->codec_id        = AV_CODEC_ID_PCM_U8;
+    ast->codecpar->channels        = 1;
+    ast->codecpar->channel_layout  = AV_CH_LAYOUT_MONO;
+    ast->codecpar->bits_per_coded_sample = 8;
+    ast->codecpar->bit_rate        = ast->codecpar->sample_rate * 8;
 
     avpriv_set_pts_info(vst, 64, msecs_per_frame, 1000000);
     vst->avg_frame_rate    = av_inv_q(vst->time_base);
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_id   = AV_CODEC_ID_MOTIONPIXELS;
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_id   = AV_CODEC_ID_MOTIONPIXELS;
 
-    mvi->get_int = (vst->codec->width * vst->codec->height < (1 << 16)) ? avio_rl16 : avio_rl24;
+    mvi->get_int = (vst->codecpar->width * vst->codecpar->height < (1 << 16)) ? avio_rl16 : avio_rl24;
 
     mvi->audio_frame_size   = ((uint64_t)mvi->audio_data_size << MVI_FRAC_BITS) / frames_count;
     if (mvi->audio_frame_size <= 1 << MVI_FRAC_BITS - 1) {
@@ -103,7 +103,7 @@ static int read_header(AVFormatContext *s)
         return AVERROR_INVALIDDATA;
     }
 
-    mvi->audio_size_counter = (ast->codec->sample_rate * 830 / mvi->audio_frame_size - 1) * mvi->audio_frame_size;
+    mvi->audio_size_counter = (ast->codecpar->sample_rate * 830 / mvi->audio_frame_size - 1) * mvi->audio_frame_size;
     mvi->audio_size_left    = mvi->audio_data_size;
 
     return 0;
diff --git a/libavformat/mxf.c b/libavformat/mxf.c
index 4d77ada..e9c48e8 100644
--- a/libavformat/mxf.c
+++ b/libavformat/mxf.c
@@ -41,7 +41,7 @@ const MXFCodecUL ff_mxf_codec_uls[] = {
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* 422P at HL I-Frame */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x03 }, 14,      AV_CODEC_ID_MPEG4 }, /* XDCAM proxy_pal030926.mxf */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, 13,    AV_CODEC_ID_DVVIDEO }, /* DV25 IEC PAL */
-    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14,   AV_CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14,   AV_CODEC_ID_JPEG2000 }, /* JPEG 2000 code stream */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x04,0x01,0x00,0x00 }, 14,        AV_CODEC_ID_VC1 }, /* VC1 SP at LL */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x04,0x02,0x00,0x00 }, 14,        AV_CODEC_ID_VC1 }, /* VC1 SP at ML */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x04,0x03,0x00,0x00 }, 14,        AV_CODEC_ID_VC1 }, /* VC1 MP at LL */
@@ -52,8 +52,8 @@ const MXFCodecUL ff_mxf_codec_uls[] = {
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x04,0x08,0x00,0x00 }, 14,        AV_CODEC_ID_VC1 }, /* VC1 AP at L2 */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x04,0x09,0x00,0x00 }, 14,        AV_CODEC_ID_VC1 }, /* VC1 AP at L3 */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x04,0x0A,0x00,0x00 }, 14,        AV_CODEC_ID_VC1 }, /* VC1 AP at L4 */
-    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13,   AV_CODEC_ID_RAWVIDEO }, /* Uncompressed */
-    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, 15,   AV_CODEC_ID_RAWVIDEO }, /* Uncompressed 422 8-bit */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13,   AV_CODEC_ID_RAWVIDEO }, /* uncompressed */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, 15,   AV_CODEC_ID_RAWVIDEO }, /* uncompressed 422 8-bit */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x71,0x00,0x00,0x00 }, 13,      AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x03,0x02,0x00,0x00 }, 14,      AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0E,0x04,0x02,0x01,0x02,0x04,0x01,0x00 }, 16,      AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD Legacy Avid Media Composer MXF */
@@ -62,8 +62,8 @@ const MXFCodecUL ff_mxf_codec_uls[] = {
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x02,0x01 }, 16,       AV_CODEC_ID_V210 }, /* V210 */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0E,0x04,0x02,0x01,0x02,0x11,0x00,0x00 }, 14,     AV_CODEC_ID_PRORES }, /* Avid MC7 ProRes */
     /* SoundEssenceCompression */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14,        AV_CODEC_ID_AAC }, /* MPEG2 AAC ADTS (legacy) */
-    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13,  AV_CODEC_ID_PCM_S16LE }, /* Uncompressed */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14,        AV_CODEC_ID_AAC }, /* MPEG-2 AAC ADTS (legacy) */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13,  AV_CODEC_ID_PCM_S16LE }, /* uncompressed */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13,  AV_CODEC_ID_PCM_S16LE },
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x02,0x02,0x01,0x7E,0x00,0x00,0x00 }, 13,  AV_CODEC_ID_PCM_S16BE }, /* From Omneon MXF file */
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x04,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, 15,   AV_CODEC_ID_PCM_ALAW }, /* XDCAM Proxy C0023S01.mxf */
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index f4222fc..0affca9 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -283,6 +283,7 @@ static int mxf_read_close(AVFormatContext *s);
 static const uint8_t mxf_header_partition_pack_key[]       = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02 };
 static const uint8_t mxf_essence_element_key[]             = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01 };
 static const uint8_t mxf_avid_essence_element_key[]        = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0e,0x04,0x03,0x01 };
+static const uint8_t mxf_canopus_essence_element_key[]     = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x0a,0x0e,0x0f,0x03,0x01 };
 static const uint8_t mxf_system_item_key[]                 = { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x03,0x01,0x04 };
 static const uint8_t mxf_klv_key[]                         = { 0x06,0x0e,0x2b,0x34 };
 /* complete keys to match */
@@ -404,15 +405,15 @@ static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt,
     data_ptr = pkt->data;
     end_ptr = pkt->data + length;
     buf_ptr = pkt->data + 4; /* skip SMPTE 331M header */
-    for (; end_ptr - buf_ptr >= st->codec->channels * 4; ) {
-        for (i = 0; i < st->codec->channels; i++) {
+    for (; end_ptr - buf_ptr >= st->codecpar->channels * 4; ) {
+        for (i = 0; i < st->codecpar->channels; i++) {
             uint32_t sample = bytestream_get_le32(&buf_ptr);
-            if (st->codec->bits_per_coded_sample == 24)
+            if (st->codecpar->bits_per_coded_sample == 24)
                 bytestream_put_le24(&data_ptr, (sample >> 4) & 0xffffff);
             else
                 bytestream_put_le16(&data_ptr, (sample >> 12) & 0xffff);
         }
-        buf_ptr += 32 - st->codec->channels*4; // always 8 channels stored SMPTE 331M
+        buf_ptr += 32 - st->codecpar->channels*4; // always 8 channels stored SMPTE 331M
     }
     av_shrink_packet(pkt, data_ptr - pkt->data);
     return 0;
@@ -591,7 +592,7 @@ static int mxf_read_partition_pack(void *arg, AVIOContext *pb, int tag, int size
                partition->previous_partition);
     }
 
-    /* some files don'thave FooterPartition set in every partition */
+    /* some files don't have FooterPartition set in every partition */
     if (footer_partition) {
         if (mxf->footer_partition && mxf->footer_partition != footer_partition) {
             av_log(mxf->fc, AV_LOG_ERROR,
@@ -1122,26 +1123,28 @@ static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref, enum MXFMe
 static const MXFCodecUL mxf_picture_essence_container_uls[] = {
     // video essence container uls
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0c,0x01,0x00 }, 14,   AV_CODEC_ID_JPEG2000 },
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x10,0x60,0x01 }, 14,       AV_CODEC_ID_H264 }, /* H264 Frame wrapped */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x12,0x01,0x00 }, 14,        AV_CODEC_ID_VC1 }, /* VC-1 Frame wrapped */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x10,0x60,0x01 }, 14,       AV_CODEC_ID_H264 }, /* H.264 frame wrapped */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x12,0x01,0x00 }, 14,        AV_CODEC_ID_VC1 }, /* VC-1 frame wrapped */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES frame wrapped */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x04,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* Type D-10 mapping of 40Mbps 525/60-I */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14,    AV_CODEC_ID_DVVIDEO }, /* DV 625 25mbps */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14,   AV_CODEC_ID_RAWVIDEO }, /* Uncompressed Picture */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14,   AV_CODEC_ID_RAWVIDEO }, /* uncompressed picture */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x0f,0x03,0x01,0x02,0x20,0x01,0x01 }, 15,     AV_CODEC_ID_HQ_HQA },
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x0f,0x03,0x01,0x02,0x20,0x02,0x01 }, 15,        AV_CODEC_ID_HQX },
     { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4f }, 14,   AV_CODEC_ID_RAWVIDEO }, /* Legacy ?? Uncompressed Picture */
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,      AV_CODEC_ID_NONE },
 };
 
 /* EC ULs for intra-only formats */
 static const MXFCodecUL mxf_intra_only_essence_container_uls[] = {
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x00,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MXF-GC SMPTE D-10 Mappings */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x00,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MXF-GC SMPTE D-10 mappings */
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,       AV_CODEC_ID_NONE },
 };
 
 /* intra-only PictureEssenceCoding ULs, where no corresponding EC UL exists */
 static const MXFCodecUL mxf_intra_only_picture_essence_coding_uls[] = {
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, 14,       AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC Intra Profiles */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14,   AV_CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14,   AV_CODEC_ID_JPEG2000 }, /* JPEG 2000 code stream */
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,       AV_CODEC_ID_NONE },
 };
 
@@ -1160,7 +1163,7 @@ static const MXFCodecUL mxf_sound_essence_container_uls[] = {
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14,       AV_CODEC_ID_MP2 }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, AV_CODEC_ID_PCM_S16LE }, /* D-10 Mapping 50Mbps PAL Extended Template */
     { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4F }, 14, AV_CODEC_ID_PCM_S16LE }, /* 0001GL00.MXF.A1.mxf_opatom.mxf */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14,       AV_CODEC_ID_AAC }, /* MPEG2 AAC ADTS (legacy) */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14,       AV_CODEC_ID_AAC }, /* MPEG-2 AAC ADTS (legacy) */
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,      AV_CODEC_ID_NONE },
 };
 
@@ -1911,7 +1914,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
                 break;
             }
         }
-        if (!source_track || !component)
+        if (!source_track || !component || !source_package)
             continue;
 
         if (!(source_track->sequence = mxf_resolve_strong_ref(mxf, &source_track->sequence_ref, Sequence))) {
@@ -1966,7 +1969,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
 
         PRINT_KEY(mxf->fc, "data definition   ul", source_track->sequence->data_definition_ul);
         codec_ul = mxf_get_codec_ul(ff_mxf_data_definition_uls, &source_track->sequence->data_definition_ul);
-        st->codec->codec_type = codec_ul->id;
+        st->codecpar->codec_type = codec_ul->id;
 
         if (!descriptor) {
             av_log(mxf->fc, AV_LOG_INFO, "source track %d: stream %d, no descriptor found\n", source_track->track_id, st->index);
@@ -1990,14 +1993,14 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
 
         /* TODO: drop PictureEssenceCoding and SoundEssenceCompression, only check EssenceContainer */
         codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->essence_codec_ul);
-        st->codec->codec_id = (enum AVCodecID)codec_ul->id;
-        if (st->codec->codec_id == AV_CODEC_ID_NONE) {
+        st->codecpar->codec_id = (enum AVCodecID)codec_ul->id;
+        if (st->codecpar->codec_id == AV_CODEC_ID_NONE) {
             codec_ul = mxf_get_codec_ul(ff_mxf_codec_uls, &descriptor->codec_ul);
-            st->codec->codec_id = (enum AVCodecID)codec_ul->id;
+            st->codecpar->codec_id = (enum AVCodecID)codec_ul->id;
         }
 
         av_log(mxf->fc, AV_LOG_VERBOSE, "%s: Universal Label: ",
-               avcodec_get_name(st->codec->codec_id));
+               avcodec_get_name(st->codecpar->codec_id));
         for (k = 0; k < 16; k++) {
             av_log(mxf->fc, AV_LOG_VERBOSE, "%.2x",
                    descriptor->essence_codec_ul[k]);
@@ -2012,16 +2015,16 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
 
         mxf_parse_physical_source_package(mxf, source_track, st);
 
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             source_track->intra_only = mxf_is_intra_only(descriptor);
             container_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul);
-            if (st->codec->codec_id == AV_CODEC_ID_NONE)
-                st->codec->codec_id = container_ul->id;
-            st->codec->width = descriptor->width;
-            st->codec->height = descriptor->height; /* Field height, not frame height */
+            if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
+                st->codecpar->codec_id = container_ul->id;
+            st->codecpar->width = descriptor->width;
+            st->codecpar->height = descriptor->height; /* Field height, not frame height */
             switch (descriptor->frame_layout) {
                 case FullFrame:
-                    st->codec->field_order = AV_FIELD_PROGRESSIVE;
+                    st->codecpar->field_order = AV_FIELD_PROGRESSIVE;
                     break;
                 case OneField:
                     /* Every other line is stored and needs to be duplicated. */
@@ -2032,14 +2035,14 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
                 case MixedFields:
                     break;
                 case SegmentedFrame:
-                    st->codec->field_order = AV_FIELD_PROGRESSIVE;
+                    st->codecpar->field_order = AV_FIELD_PROGRESSIVE;
                 case SeparateFields:
                     switch (descriptor->field_dominance) {
                     case MXF_TFF:
-                        st->codec->field_order = AV_FIELD_TT;
+                        st->codecpar->field_order = AV_FIELD_TT;
                         break;
                     case MXF_BFF:
-                        st->codec->field_order = AV_FIELD_BB;
+                        st->codecpar->field_order = AV_FIELD_BB;
                         break;
                     default:
                         avpriv_request_sample(mxf->fc,
@@ -2049,27 +2052,27 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
                         break;
                     }
                     /* Turn field height into frame height. */
-                    st->codec->height *= 2;
+                    st->codecpar->height *= 2;
                     break;
                 default:
                     av_log(mxf->fc, AV_LOG_INFO, "Unknown frame layout type: %d\n", descriptor->frame_layout);
             }
-            if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO) {
-                st->codec->pix_fmt = descriptor->pix_fmt;
-                if (st->codec->pix_fmt == AV_PIX_FMT_NONE) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) {
+                st->codecpar->format = descriptor->pix_fmt;
+                if (st->codecpar->format == AV_PIX_FMT_NONE) {
                     pix_fmt_ul = mxf_get_codec_ul(ff_mxf_pixel_format_uls,
                                                   &descriptor->essence_codec_ul);
-                    st->codec->pix_fmt = (enum AVPixelFormat)pix_fmt_ul->id;
-                    if (st->codec->pix_fmt == AV_PIX_FMT_NONE) {
-                        st->codec->codec_tag = mxf_get_codec_ul(ff_mxf_codec_tag_uls,
-                                                                &descriptor->essence_codec_ul)->id;
-                        if (!st->codec->codec_tag) {
+                    st->codecpar->format = (enum AVPixelFormat)pix_fmt_ul->id;
+                    if (st->codecpar->format== AV_PIX_FMT_NONE) {
+                        st->codecpar->codec_tag = mxf_get_codec_ul(ff_mxf_codec_tag_uls,
+                                                                   &descriptor->essence_codec_ul)->id;
+                        if (!st->codecpar->codec_tag) {
                             /* support files created before RP224v10 by defaulting to UYVY422
                                if subsampling is 4:2:2 and component depth is 8-bit */
                             if (descriptor->horiz_subsampling == 2 &&
                                 descriptor->vert_subsampling == 1 &&
                                 descriptor->component_depth == 8) {
-                                st->codec->pix_fmt = AV_PIX_FMT_UYVY422;
+                                st->codecpar->format = AV_PIX_FMT_UYVY422;
                             }
                         }
                     }
@@ -2084,16 +2087,16 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
             }
             if (descriptor->aspect_ratio.num && descriptor->aspect_ratio.den)
                 st->display_aspect_ratio = descriptor->aspect_ratio;
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
             /* Only overwrite existing codec ID if it is unset or A-law, which is the default according to SMPTE RP 224. */
-            if (st->codec->codec_id == AV_CODEC_ID_NONE || (st->codec->codec_id == AV_CODEC_ID_PCM_ALAW && (enum AVCodecID)container_ul->id != AV_CODEC_ID_NONE))
-                st->codec->codec_id = (enum AVCodecID)container_ul->id;
-            st->codec->channels = descriptor->channels;
-            st->codec->bits_per_coded_sample = descriptor->bits_per_sample;
+            if (st->codecpar->codec_id == AV_CODEC_ID_NONE || (st->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW && (enum AVCodecID)container_ul->id != AV_CODEC_ID_NONE))
+                st->codecpar->codec_id = (enum AVCodecID)container_ul->id;
+            st->codecpar->channels = descriptor->channels;
+            st->codecpar->bits_per_coded_sample = descriptor->bits_per_sample;
 
             if (descriptor->sample_rate.den > 0) {
-                st->codec->sample_rate = descriptor->sample_rate.num / descriptor->sample_rate.den;
+                st->codecpar->sample_rate = descriptor->sample_rate.num / descriptor->sample_rate.den;
                 avpriv_set_pts_info(st, 64, descriptor->sample_rate.den, descriptor->sample_rate.num);
             } else {
                 av_log(mxf->fc, AV_LOG_WARNING, "invalid sample rate (%d/%d) "
@@ -2110,20 +2113,20 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
                                             st->time_base);
 
             /* TODO: implement AV_CODEC_ID_RAWAUDIO */
-            if (st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) {
                 if (descriptor->bits_per_sample > 16 && descriptor->bits_per_sample <= 24)
-                    st->codec->codec_id = AV_CODEC_ID_PCM_S24LE;
+                    st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
                 else if (descriptor->bits_per_sample == 32)
-                    st->codec->codec_id = AV_CODEC_ID_PCM_S32LE;
-            } else if (st->codec->codec_id == AV_CODEC_ID_PCM_S16BE) {
+                    st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
+            } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16BE) {
                 if (descriptor->bits_per_sample > 16 && descriptor->bits_per_sample <= 24)
-                    st->codec->codec_id = AV_CODEC_ID_PCM_S24BE;
+                    st->codecpar->codec_id = AV_CODEC_ID_PCM_S24BE;
                 else if (descriptor->bits_per_sample == 32)
-                    st->codec->codec_id = AV_CODEC_ID_PCM_S32BE;
-            } else if (st->codec->codec_id == AV_CODEC_ID_MP2) {
+                    st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
+            } else if (st->codecpar->codec_id == AV_CODEC_ID_MP2) {
                 st->need_parsing = AVSTREAM_PARSE_FULL;
             }
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
             int codec_id = mxf_get_codec_ul(mxf_data_essence_container_uls,
                                             essence_container_ul)->id;
             if (codec_id >= 0 &&
@@ -2133,19 +2136,19 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
             }
         }
         if (descriptor->extradata) {
-            if (!ff_alloc_extradata(st->codec, descriptor->extradata_size)) {
-                memcpy(st->codec->extradata, descriptor->extradata, descriptor->extradata_size);
+            if (!ff_alloc_extradata(st->codecpar, descriptor->extradata_size)) {
+                memcpy(st->codecpar->extradata, descriptor->extradata, descriptor->extradata_size);
             }
-        } else if (st->codec->codec_id == AV_CODEC_ID_H264) {
+        } else if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
             int coded_width = mxf_get_codec_ul(mxf_intra_only_picture_coded_width,
                                                &descriptor->essence_codec_ul)->id;
             if (coded_width)
-                st->codec->width = coded_width;
+                st->codecpar->width = coded_width;
             ret = ff_generate_avci_extradata(st);
             if (ret < 0)
                 return ret;
         }
-        if (st->codec->codec_type != AVMEDIA_TYPE_DATA && (*essence_container_ul)[15] > 0x01) {
+        if (st->codecpar->codec_type != AVMEDIA_TYPE_DATA && (*essence_container_ul)[15] > 0x01) {
             /* TODO: decode timestamps */
             st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
         }
@@ -2576,8 +2579,8 @@ static void mxf_handle_small_eubc(AVFormatContext *s)
 
     /* expect PCM with exactly one index table segment and a small (< 32) EUBC */
     if (s->nb_streams != 1                                     ||
-        s->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO ||
-        !is_pcm(s->streams[0]->codec->codec_id)                ||
+        s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO ||
+        !is_pcm(s->streams[0]->codecpar->codec_id)                ||
         mxf->nb_index_tables != 1                              ||
         mxf->index_tables[0].nb_segments != 1                  ||
         mxf->index_tables[0].segments[0]->edit_unit_byte_count >= 32)
@@ -2605,8 +2608,8 @@ static int mxf_handle_missing_index_segment(MXFContext *mxf)
     if (mxf->op != OPAtom)
         return 0;
 
-    /* TODO: support raw video without a index if they exist */
-    if (s->nb_streams != 1 || s->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO || !is_pcm(s->streams[0]->codec->codec_id))
+    /* TODO: support raw video without an index if they exist */
+    if (s->nb_streams != 1 || s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || !is_pcm(s->streams[0]->codecpar->codec_id))
         return 0;
 
     /* check if file already has a IndexTableSegment */
@@ -2640,7 +2643,7 @@ static int mxf_handle_missing_index_segment(MXFContext *mxf)
     st = s->streams[0];
     segment->type = IndexTableSegment;
     /* stream will be treated as small EditUnitByteCount */
-    segment->edit_unit_byte_count = (av_get_bits_per_sample(st->codec->codec_id) * st->codec->channels) >> 3;
+    segment->edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3;
     segment->index_start_position = 0;
     segment->index_duration = s->streams[0]->duration;
     segment->index_sid = p->index_sid;
@@ -2915,22 +2918,22 @@ static int mxf_compute_sample_count(MXFContext *mxf, int stream_index,
     return 0;
 }
 
-static int mxf_set_audio_pts(MXFContext *mxf, AVCodecContext *codec,
+static int mxf_set_audio_pts(MXFContext *mxf, AVCodecParameters *par,
                              AVPacket *pkt)
 {
     MXFTrack *track = mxf->fc->streams[pkt->stream_index]->priv_data;
-    int64_t bits_per_sample = codec->bits_per_coded_sample;
+    int64_t bits_per_sample = par->bits_per_coded_sample;
 
     if (!bits_per_sample)
-        bits_per_sample = av_get_bits_per_sample(codec->codec_id);
+        bits_per_sample = av_get_bits_per_sample(par->codec_id);
 
     pkt->pts = track->sample_count;
 
-    if (   codec->channels <= 0
+    if (   par->channels <= 0
         || bits_per_sample <= 0
-        || codec->channels * (int64_t)bits_per_sample < 8)
+        || par->channels * (int64_t)bits_per_sample < 8)
         return AVERROR(EINVAL);
-    track->sample_count += pkt->size / (codec->channels * (int64_t)bits_per_sample / 8);
+    track->sample_count += pkt->size / (par->channels * (int64_t)bits_per_sample / 8);
     return 0;
 }
 
@@ -2952,12 +2955,13 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
             return 0;
         }
         if (IS_KLV_KEY(klv.key, mxf_essence_element_key) ||
+            IS_KLV_KEY(klv.key, mxf_canopus_essence_element_key) ||
             IS_KLV_KEY(klv.key, mxf_avid_essence_element_key)) {
             int index = mxf_get_stream_index(s, &klv);
             int64_t next_ofs, next_klv;
             AVStream *st;
             MXFTrack *track;
-            AVCodecContext *codec;
+            AVCodecParameters *par;
 
             if (index < 0) {
                 av_log(s, AV_LOG_ERROR,
@@ -3002,9 +3006,9 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
             pkt->stream_index = index;
             pkt->pos = klv.offset;
 
-            codec = st->codec;
+            par = st->codecpar;
 
-            if (codec->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) {
+            if (par->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) {
                 /* mxf->current_edit_unit good - see if we have an
                  * index table to derive timestamps from */
                 MXFIndexTable *t = &mxf->index_tables[0];
@@ -3017,8 +3021,8 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
                      * let utils.c figure out DTS since it can be < PTS if low_delay = 0 (Sony IMX30) */
                     pkt->pts = mxf->current_edit_unit;
                 }
-            } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-                ret = mxf_set_audio_pts(mxf, codec, pkt);
+            } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
+                ret = mxf_set_audio_pts(mxf, par, pkt);
                 if (ret < 0)
                     return ret;
             }
@@ -3084,12 +3088,12 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
 
     pkt->stream_index = 0;
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && t->ptses &&
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && t->ptses &&
         mxf->current_edit_unit >= 0 && mxf->current_edit_unit < t->nb_ptses) {
         pkt->dts = mxf->current_edit_unit + t->first_dts;
         pkt->pts = t->ptses[mxf->current_edit_unit];
-    } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-        int ret = mxf_set_audio_pts(mxf, st->codec, pkt);
+    } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+        int ret = mxf_set_audio_pts(mxf, st->codecpar, pkt);
         if (ret < 0)
             return ret;
     }
@@ -3168,7 +3172,7 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
     MXFTrack *source_track = st->priv_data;
 
     /* if audio then truncate sample_time to EditRate */
-    if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
         sample_time = av_rescale_q(sample_time, st->time_base,
                                    av_inv_q(source_track->edit_rate));
 
@@ -3227,7 +3231,7 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
         AVStream *cur_st = s->streams[i];
         MXFTrack *cur_track = cur_st->priv_data;
         uint64_t current_sample_count = 0;
-        if (cur_st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (cur_st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             ret = mxf_compute_sample_count(mxf, i, &current_sample_count);
             if (ret < 0)
                 return ret;
diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index cd13f89..0c04a39 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -834,14 +834,14 @@ static void mxf_write_common_fields(AVFormatContext *s, AVStream *st)
     if (st == mxf->timecode_track)
         avio_write(pb, smpte_12m_timecode_track_data_ul, 16);
     else {
-        const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codec->codec_type);
+        const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codecpar->codec_type);
         avio_write(pb, data_def_ul->uid, 16);
     }
 
     // write duration
     mxf_write_local_tag(pb, 8, 0x0202);
 
-    if (st != mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer && st->codec->codec_type == AVMEDIA_TYPE_AUDIO){
+    if (st != mxf->timecode_track && s->oformat == &ff_mxf_opatom_muxer && st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO){
         avio_wb64(pb, mxf->body_offset / mxf->edit_unit_byte_count);
     } else {
         avio_wb64(pb, mxf->duration);
@@ -1010,7 +1010,7 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
 {
     MXFStreamContext *sc = st->priv_data;
     AVIOContext *pb = s->pb;
-    int stored_height = (st->codec->height+15)/16*16;
+    int stored_height = (st->codecpar->height+15)/16*16;
     int display_height;
     int f1, f2;
     unsigned desc_size = size+8+8+8+8+8+8+8+5+16+4+12+20+5;
@@ -1022,27 +1022,27 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
     mxf_write_generic_desc(s, st, key, desc_size);
 
     mxf_write_local_tag(pb, 4, 0x3203);
-    avio_wb32(pb, st->codec->width);
+    avio_wb32(pb, st->codecpar->width);
 
     mxf_write_local_tag(pb, 4, 0x3202);
     avio_wb32(pb, stored_height>>sc->interlaced);
 
     mxf_write_local_tag(pb, 4, 0x3209);
-    avio_wb32(pb, st->codec->width);
+    avio_wb32(pb, st->codecpar->width);
 
-    if (st->codec->height == 608) // PAL + VBI
+    if (st->codecpar->height == 608) // PAL + VBI
         display_height = 576;
-    else if (st->codec->height == 512)  // NTSC + VBI
+    else if (st->codecpar->height == 512)  // NTSC + VBI
         display_height = 486;
     else
-        display_height = st->codec->height;
+        display_height = st->codecpar->height;
 
     mxf_write_local_tag(pb, 4, 0x3208);
     avio_wb32(pb, display_height>>sc->interlaced);
 
     // presentation Y offset
     mxf_write_local_tag(pb, 4, 0x320B);
-    avio_wb32(pb, (st->codec->height - display_height)>>sc->interlaced);
+    avio_wb32(pb, (st->codecpar->height - display_height)>>sc->interlaced);
 
     // component depth
     mxf_write_local_tag(pb, 4, 0x3301);
@@ -1066,10 +1066,10 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
     avio_w8(pb, sc->interlaced);
 
     // video line map
-    switch (st->codec->height) {
-    case  576: f1 = 23; f2 = st->codec->codec_id == AV_CODEC_ID_DVVIDEO ? 335 : 336; break;
+    switch (st->codecpar->height) {
+    case  576: f1 = 23; f2 = st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO ? 335 : 336; break;
     case  608: f1 =  7; f2 = 320; break;
-    case  480: f1 = 20; f2 = st->codec->codec_id == AV_CODEC_ID_DVVIDEO ? 285 : 283; break;
+    case  480: f1 = 20; f2 = st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO ? 285 : 283; break;
     case  512: f1 =  7; f2 = 270; break;
     case  720: f1 = 26; f2 =   0; break; // progressive
     case 1080: f1 = 21; f2 = 584; break;
@@ -1111,9 +1111,9 @@ static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
 {
     AVIOContext *pb = s->pb;
     MXFStreamContext *sc = st->priv_data;
-    int profile_and_level = (st->codec->profile<<4) | st->codec->level;
+    int profile_and_level = (st->codecpar->profile<<4) | st->codecpar->level;
 
-    if (st->codec->codec_id != AV_CODEC_ID_H264) {
+    if (st->codecpar->codec_id != AV_CODEC_ID_H264) {
         mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 8+5);
 
         // bit rate
@@ -1122,7 +1122,7 @@ static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
 
         // profile and level
         mxf_write_local_tag(pb, 1, 0x8007);
-        if (!st->codec->profile)
+        if (!st->codecpar->profile)
             profile_and_level |= 0x80; // escape bit
         avio_w8(pb, profile_and_level);
     } else {
@@ -1153,16 +1153,16 @@ static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, con
 
     // write audio sampling rate
     mxf_write_local_tag(pb, 8, 0x3D03);
-    avio_wb32(pb, st->codec->sample_rate);
+    avio_wb32(pb, st->codecpar->sample_rate);
     avio_wb32(pb, 1);
 
     mxf_write_local_tag(pb, 4, 0x3D07);
     if (mxf->channel_count == -1) {
-        if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && (st->codec->channels != 4) && (st->codec->channels != 8))
+        if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && (st->codecpar->channels != 4) && (st->codecpar->channels != 8))
             av_log(s, AV_LOG_WARNING, "the number of audio channels shall be 4 or 8 : the output will not comply to MXF D-10 specs, use -d10_channelcount to fix this\n");
-        avio_wb32(pb, st->codec->channels);
+        avio_wb32(pb, st->codecpar->channels);
     } else if (s->oformat == &ff_mxf_d10_muxer) {
-        if (show_warnings && (mxf->channel_count < st->codec->channels))
+        if (show_warnings && (mxf->channel_count < st->codecpar->channels))
             av_log(s, AV_LOG_WARNING, "d10_channelcount < actual number of audio channels : some channels will be discarded\n");
         if (show_warnings && (mxf->channel_count != 4) && (mxf->channel_count != 8))
             av_log(s, AV_LOG_WARNING, "d10_channelcount shall be set to 4 or 8 : the output will not comply to MXF D-10 specs\n");
@@ -1170,11 +1170,11 @@ static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, con
     } else {
         if (show_warnings && mxf->channel_count != -1 && s->oformat != &ff_mxf_opatom_muxer)
             av_log(s, AV_LOG_ERROR, "-d10_channelcount requires MXF D-10 and will be ignored\n");
-        avio_wb32(pb, st->codec->channels);
+        avio_wb32(pb, st->codecpar->channels);
     }
 
     mxf_write_local_tag(pb, 4, 0x3D01);
-    avio_wb32(pb, av_get_bits_per_sample(st->codec->codec_id));
+    avio_wb32(pb, av_get_bits_per_sample(st->codecpar->codec_id));
 }
 
 static void mxf_write_wav_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size)
@@ -1184,11 +1184,11 @@ static void mxf_write_wav_common(AVFormatContext *s, AVStream *st, const UID key
     mxf_write_generic_sound_common(s, st, key, size+6+8);
 
     mxf_write_local_tag(pb, 2, 0x3D0A);
-    avio_wb16(pb, st->codec->block_align);
+    avio_wb16(pb, st->codecpar->block_align);
 
     // avg bytes per sec
     mxf_write_local_tag(pb, 4, 0x3D09);
-    avio_wb32(pb, st->codec->block_align*st->codec->sample_rate);
+    avio_wb32(pb, st->codecpar->block_align*st->codecpar->sample_rate);
 }
 
 static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st)
@@ -1496,7 +1496,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
         for (i = 0; i < mxf->edit_units_count; i++) {
             int temporal_offset = 0;
 
-            if (!(mxf->index_entries[i].flags & 0x33)) { // I frame
+            if (!(mxf->index_entries[i].flags & 0x33)) { // I-frame
                 mxf->last_key_index = key_index;
                 key_index = i;
             }
@@ -1523,7 +1523,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
                     mxf->last_key_index = key_index;
             }
 
-            if (!(mxf->index_entries[i].flags & 0x33) && // I frame
+            if (!(mxf->index_entries[i].flags & 0x33) && // I-frame
                 mxf->index_entries[i].flags & 0x40 && !temporal_offset)
                 mxf->index_entries[i].flags |= 0x80; // random access
             avio_w8(pb, mxf->index_entries[i].flags);
@@ -1729,10 +1729,10 @@ AVPacket *pkt)
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
         MXFStreamContext *sc = st->priv_data;
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             mxf->edit_unit_byte_count += 16 + 4 + sc->aic.samples[0]*sc->aic.sample_size;
             mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             mxf->edit_unit_byte_count += 16 + 4 + frame_size;
             mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
         }
@@ -1804,10 +1804,10 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
         MXFStreamContext *sc = st->priv_data;
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
             mxf->edit_unit_byte_count += 16 + 4 + sc->aic.samples[0]*sc->aic.sample_size;
             mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             mxf->edit_unit_byte_count += 16 + 4 + frame_size;
             mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
         }
@@ -1861,7 +1861,7 @@ static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st,
         --buf;
         switch (state & 0x1f) {
         case NAL_SPS:
-            st->codec->profile = buf[1];
+            st->codecpar->profile = buf[1];
             e->flags |= 0x40;
             break;
         case NAL_PPS:
@@ -1881,7 +1881,7 @@ static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st,
 
     sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for broadcast HD
     sc->component_depth = 10; // AVC Intra is always 10 Bit
-    sc->interlaced = st->codec->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0;
+    sc->interlaced = st->codecpar->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0;
     if (sc->interlaced)
         sc->field_dominance = 1; // top field first is mandatory for AVC Intra
 
@@ -1891,7 +1891,7 @@ static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st,
         if (frame_size == mxf_h264_codec_uls[i].frame_size && sc->interlaced == mxf_h264_codec_uls[i].interlaced) {
             sc->codec_ul = &mxf_h264_codec_uls[i].uid;
             return 1;
-        } else if (st->codec->profile == mxf_h264_codec_uls[i].profile) {
+        } else if (st->codecpar->profile == mxf_h264_codec_uls[i].profile) {
             sc->codec_ul = &mxf_h264_codec_uls[i].uid;
             uid_found = 1;
         }
@@ -1918,21 +1918,21 @@ static const UID mxf_mpeg2_codec_uls[] = {
     { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x05,0x03,0x00 }, // MP at H-14 Long GOP
 };
 
-static const UID *mxf_get_mpeg2_codec_ul(AVCodecContext *avctx)
+static const UID *mxf_get_mpeg2_codec_ul(AVCodecParameters *par)
 {
     int long_gop = 1;
 
-    if (avctx->profile == 4) { // Main
-        if (avctx->level == 8) // Main
+    if (par->profile == 4) { // Main
+        if (par->level == 8) // Main
             return &mxf_mpeg2_codec_uls[0+long_gop];
-        else if (avctx->level == 4) // High
+        else if (par->level == 4) // High
             return &mxf_mpeg2_codec_uls[4+long_gop];
-        else if (avctx->level == 6) // High 14
+        else if (par->level == 6) // High 14
             return &mxf_mpeg2_codec_uls[8+long_gop];
-    } else if (avctx->profile == 0) { // 422
-        if (avctx->level == 5) // Main
+    } else if (par->profile == 0) { // 422
+        if (par->level == 5) // Main
             return &mxf_mpeg2_codec_uls[2+long_gop];
-        else if (avctx->level == 2) // High
+        else if (par->level == 2) // High
             return &mxf_mpeg2_codec_uls[6+long_gop];
     }
     return NULL;
@@ -1949,8 +1949,8 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st,
         c = (c<<8) + pkt->data[i];
         if (c == 0x1b5) {
             if ((pkt->data[i+1] & 0xf0) == 0x10) { // seq ext
-                st->codec->profile = pkt->data[i+1] & 0x07;
-                st->codec->level   = pkt->data[i+2] >> 4;
+                st->codecpar->profile = pkt->data[i+1] & 0x07;
+                st->codecpar->level   = pkt->data[i+2] >> 4;
             } else if (i + 5 < pkt->size && (pkt->data[i+1] & 0xf0) == 0x80) { // pict coding ext
                 sc->interlaced = !(pkt->data[i+5] & 0x80); // progressive frame
                 if (sc->interlaced)
@@ -1971,15 +1971,15 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st,
             case 4:  sc->aspect_ratio = (AVRational){221,100}; break;
             default:
                 av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den,
-                          st->codec->width, st->codec->height, 1024*1024);
+                          st->codecpar->width, st->codecpar->height, 1024*1024);
             }
         } else if (c == 0x100) { // pic
             int pict_type = (pkt->data[i+2]>>3) & 0x07;
             e->temporal_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6);
-            if (pict_type == 2) { // P frame
+            if (pict_type == 2) { // P-frame
                 e->flags |= 0x22;
-                sc->closed_gop = 0; // reset closed gop, don't matter anymore
-            } else if (pict_type == 3) { // B frame
+                sc->closed_gop = 0; // reset closed GOP, don't matter anymore
+            } else if (pict_type == 3) { // B-frame
                 if (sc->closed_gop)
                     e->flags |= 0x13; // only backward prediction
                 else
@@ -1992,7 +1992,7 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st,
         }
     }
     if (s->oformat != &ff_mxf_d10_muxer)
-        sc->codec_ul = mxf_get_mpeg2_codec_ul(st->codec);
+        sc->codec_ul = mxf_get_mpeg2_codec_ul(st->codecpar);
     return !!sc->codec_ul;
 }
 
@@ -2061,13 +2061,13 @@ static int mxf_write_header(AVFormatContext *s)
             return AVERROR(ENOMEM);
         st->priv_data = sc;
 
-        if (((i == 0) ^ (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)) && s->oformat != &ff_mxf_opatom_muxer) {
+        if (((i == 0) ^ (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) && s->oformat != &ff_mxf_opatom_muxer) {
             av_log(s, AV_LOG_ERROR, "there must be exactly one video stream and it must be the first one\n");
             return -1;
         }
 
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-            const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(st->codec->pix_fmt);
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+            const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(st->codecpar->format);
             // TODO: should be avg_frame_rate
             AVRational rate, tbc = st->time_base;
             // Default component depth to 8
@@ -2099,7 +2099,7 @@ static int mxf_write_header(AVFormatContext *s)
             if((ret = mxf_init_timecode(s, st, rate)) < 0)
                 return ret;
 
-            sc->video_bit_rate = st->codec->bit_rate ? st->codec->bit_rate : st->codec->rc_max_rate;
+            sc->video_bit_rate = st->codecpar->bit_rate;
             if (s->oformat == &ff_mxf_d10_muxer) {
                 if ((sc->video_bit_rate == 50000000) && (mxf->time_base.den == 25)) {
                     sc->index = 3;
@@ -2127,31 +2127,31 @@ static int mxf_write_header(AVFormatContext *s)
             }
             if (mxf->signal_standard >= 0)
                 sc->signal_standard = mxf->signal_standard;
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            if (st->codec->sample_rate != 48000) {
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (st->codecpar->sample_rate != 48000) {
                 av_log(s, AV_LOG_ERROR, "only 48khz is implemented\n");
                 return -1;
             }
-            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+            avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
             if (s->oformat == &ff_mxf_d10_muxer) {
                 if (st->index != 1) {
                     av_log(s, AV_LOG_ERROR, "MXF D-10 only support one audio track\n");
                     return -1;
                 }
-                if (st->codec->codec_id != AV_CODEC_ID_PCM_S16LE &&
-                    st->codec->codec_id != AV_CODEC_ID_PCM_S24LE) {
+                if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE &&
+                    st->codecpar->codec_id != AV_CODEC_ID_PCM_S24LE) {
                     av_log(s, AV_LOG_ERROR, "MXF D-10 only support 16 or 24 bits le audio\n");
                 }
                 sc->index = ((MXFStreamContext*)s->streams[0]->priv_data)->index + 1;
             } else if (s->oformat == &ff_mxf_opatom_muxer) {
                 AVRational tbc = av_inv_q(mxf->audio_edit_rate);
 
-                if (st->codec->codec_id != AV_CODEC_ID_PCM_S16LE &&
-                    st->codec->codec_id != AV_CODEC_ID_PCM_S24LE) {
+                if (st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE &&
+                    st->codecpar->codec_id != AV_CODEC_ID_PCM_S24LE) {
                     av_log(s, AV_LOG_ERROR, "Only pcm_s16le and pcm_s24le audio codecs are implemented\n");
                     return AVERROR_PATCHWELCOME;
                 }
-                if (st->codec->channels != 1) {
+                if (st->codecpar->channels != 1) {
                     av_log(s, AV_LOG_ERROR, "MXF OPAtom only supports single channel audio\n");
                     return AVERROR(EINVAL);
                 }
@@ -2167,7 +2167,7 @@ static int mxf_write_header(AVFormatContext *s)
                     return ret;
 
                 mxf->timecode_base = (tbc.den + tbc.num/2) / tbc.num;
-                mxf->edit_unit_byte_count = (av_get_bits_per_sample(st->codec->codec_id) * st->codec->channels) >> 3;
+                mxf->edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3;
                 sc->index = 2;
             } else {
                 mxf->slice_count = 1;
@@ -2175,7 +2175,7 @@ static int mxf_write_header(AVFormatContext *s)
         }
 
         if (!sc->index) {
-            sc->index = mxf_get_essence_container_ul_index(st->codec->codec_id);
+            sc->index = mxf_get_essence_container_ul_index(st->codecpar->codec_id);
             if (sc->index == -1) {
                 av_log(s, AV_LOG_ERROR, "track %d: could not find essence container ul, "
                        "codec not currently supported in container\n", i);
@@ -2309,7 +2309,7 @@ static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacke
 {
     MXFContext *mxf = s->priv_data;
     AVIOContext *pb = s->pb;
-    int frame_size = pkt->size / st->codec->block_align;
+    int frame_size = pkt->size / st->codecpar->block_align;
     uint8_t *samples = pkt->data;
     uint8_t *end = pkt->data + pkt->size;
     int i;
@@ -2318,12 +2318,12 @@ static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacke
 
     avio_w8(pb, (frame_size == 1920 ? 0 : (mxf->edit_units_count-1) % 5 + 1));
     avio_wl16(pb, frame_size);
-    avio_w8(pb, (1<<st->codec->channels)-1);
+    avio_w8(pb, (1<<st->codecpar->channels)-1);
 
     while (samples < end) {
-        for (i = 0; i < st->codec->channels; i++) {
+        for (i = 0; i < st->codecpar->channels; i++) {
             uint32_t sample;
-            if (st->codec->codec_id == AV_CODEC_ID_PCM_S24LE) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE) {
                 sample = AV_RL24(samples)<< 4;
                 samples += 3;
             } else {
@@ -2406,22 +2406,22 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
         }
     }
 
-    if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
         if (!mxf_parse_mpeg2_frame(s, st, pkt, &ie)) {
             av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n");
             return -1;
         }
-    } else if (st->codec->codec_id == AV_CODEC_ID_DNXHD) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_DNXHD) {
         if (!mxf_parse_dnxhd_frame(s, st, pkt)) {
             av_log(s, AV_LOG_ERROR, "could not get dnxhd profile\n");
             return -1;
         }
-    } else if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_DVVIDEO) {
         if (!mxf_parse_dv_frame(s, st, pkt)) {
             av_log(s, AV_LOG_ERROR, "could not get dv profile\n");
             return -1;
         }
-    } else if (st->codec->codec_id == AV_CODEC_ID_H264) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
         if (!mxf_parse_h264_frame(s, st, pkt, &ie)) {
             av_log(s, AV_LOG_ERROR, "could not get h264 profile\n");
             return -1;
@@ -2447,7 +2447,7 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
     if (st->index == 0) {
         if (!mxf->edit_unit_byte_count &&
             (!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) &&
-            !(ie.flags & 0x33)) { // I frame, Gop start
+            !(ie.flags & 0x33)) { // I-frame, GOP start
             mxf_write_klv_fill(s);
             if ((err = mxf_write_partition(s, 1, 2, body_partition_key, 0)) < 0)
                 return err;
@@ -2477,7 +2477,7 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
     mxf_write_klv_fill(s);
     avio_write(pb, sc->track_essence_element_key, 16); // write key
     if (s->oformat == &ff_mxf_d10_muxer) {
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
             mxf_write_d10_video_packet(s, st, pkt);
         else
             mxf_write_d10_audio_packet(s, st, pkt);
diff --git a/libavformat/mxg.c b/libavformat/mxg.c
index 45cc5b5..6fbf99c 100644
--- a/libavformat/mxg.c
+++ b/libavformat/mxg.c
@@ -48,20 +48,20 @@ static int mxg_read_header(AVFormatContext *s)
     video_st = avformat_new_stream(s, NULL);
     if (!video_st)
         return AVERROR(ENOMEM);
-    video_st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    video_st->codec->codec_id = AV_CODEC_ID_MXPEG;
+    video_st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    video_st->codecpar->codec_id = AV_CODEC_ID_MXPEG;
     avpriv_set_pts_info(video_st, 64, 1, 1000000);
 
     audio_st = avformat_new_stream(s, NULL);
     if (!audio_st)
         return AVERROR(ENOMEM);
-    audio_st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    audio_st->codec->codec_id = AV_CODEC_ID_PCM_ALAW;
-    audio_st->codec->channels = 1;
-    audio_st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    audio_st->codec->sample_rate = 8000;
-    audio_st->codec->bits_per_coded_sample = 8;
-    audio_st->codec->block_align = 1;
+    audio_st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    audio_st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW;
+    audio_st->codecpar->channels = 1;
+    audio_st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    audio_st->codecpar->sample_rate = 8000;
+    audio_st->codecpar->bits_per_coded_sample = 8;
+    audio_st->codecpar->block_align = 1;
     avpriv_set_pts_info(audio_st, 64, 1, 1000000);
 
     mxg->soi_ptr = mxg->buffer_ptr = mxg->buffer = 0;
diff --git a/libavformat/ncdec.c b/libavformat/ncdec.c
index 745ba61..8cadcc7 100644
--- a/libavformat/ncdec.c
+++ b/libavformat/ncdec.c
@@ -51,8 +51,8 @@ static int nc_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_MPEG4;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_MPEG4;
     st->need_parsing      = AVSTREAM_PARSE_FULL;
 
     avpriv_set_pts_info(st, 64, 1, 100);
diff --git a/libavformat/nistspheredec.c b/libavformat/nistspheredec.c
index 2f17f9e..782d1df 100644
--- a/libavformat/nistspheredec.c
+++ b/libavformat/nistspheredec.c
@@ -34,7 +34,7 @@ static int nist_probe(AVProbeData *p)
 
 static int nist_read_header(AVFormatContext *s)
 {
-    char buffer[32], coding[32] = "pcm", format[32] = "01";
+    char buffer[256], coding[32] = "pcm", format[32] = "01";
     int bps = 0, be = 0;
     int32_t header_size = -1;
     AVStream *st;
@@ -43,7 +43,7 @@ static int nist_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
 
     ff_get_line(s->pb, buffer, sizeof(buffer));
     ff_get_line(s->pb, buffer, sizeof(buffer));
@@ -58,24 +58,29 @@ static int nist_read_header(AVFormatContext *s)
             return AVERROR_INVALIDDATA;
 
         if (!memcmp(buffer, "end_head", 8)) {
-            if (!st->codec->bits_per_coded_sample)
-                st->codec->bits_per_coded_sample = bps << 3;
+            if (!st->codecpar->bits_per_coded_sample)
+                st->codecpar->bits_per_coded_sample = bps << 3;
 
             if (!av_strcasecmp(coding, "pcm")) {
-                st->codec->codec_id = ff_get_pcm_codec_id(st->codec->bits_per_coded_sample,
-                                                          0, be, 0xFFFF);
+                if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
+                    st->codecpar->codec_id = ff_get_pcm_codec_id(st->codecpar->bits_per_coded_sample,
+                                                              0, be, 0xFFFF);
             } else if (!av_strcasecmp(coding, "alaw")) {
-                st->codec->codec_id = AV_CODEC_ID_PCM_ALAW;
+                st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW;
             } else if (!av_strcasecmp(coding, "ulaw") ||
                        !av_strcasecmp(coding, "mu-law")) {
-                st->codec->codec_id = AV_CODEC_ID_PCM_MULAW;
+                st->codecpar->codec_id = AV_CODEC_ID_PCM_MULAW;
+            } else if (!av_strncasecmp(coding, "pcm,embedded-shorten", 20)) {
+                st->codecpar->codec_id = AV_CODEC_ID_SHORTEN;
+                if (ff_alloc_extradata(st->codecpar, 1))
+                    st->codecpar->extradata[0] = 1;
             } else {
                 avpriv_request_sample(s, "coding %s", coding);
             }
 
-            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+            avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
-            st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8;
+            st->codecpar->block_align = st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8;
 
             if (avio_tell(s->pb) > header_size)
                 return AVERROR_INVALIDDATA;
@@ -84,7 +89,7 @@ static int nist_read_header(AVFormatContext *s)
 
             return 0;
         } else if (!memcmp(buffer, "channel_count", 13)) {
-            sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->channels);
+            sscanf(buffer, "%*s %*s %"SCNd32, &st->codecpar->channels);
         } else if (!memcmp(buffer, "sample_byte_format", 18)) {
             sscanf(buffer, "%*s %*s %31s", format);
 
@@ -92,6 +97,8 @@ static int nist_read_header(AVFormatContext *s)
                 be = 0;
             } else if (!av_strcasecmp(format, "10")) {
                 be = 1;
+            } else if (!av_strcasecmp(format, "mu-law")) {
+                st->codecpar->codec_id = AV_CODEC_ID_PCM_MULAW;
             } else if (av_strcasecmp(format, "1")) {
                 avpriv_request_sample(s, "sample byte format %s", format);
                 return AVERROR_PATCHWELCOME;
@@ -103,12 +110,12 @@ static int nist_read_header(AVFormatContext *s)
         } else if (!memcmp(buffer, "sample_n_bytes", 14)) {
             sscanf(buffer, "%*s %*s %"SCNd32, &bps);
         } else if (!memcmp(buffer, "sample_rate", 11)) {
-            sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->sample_rate);
+            sscanf(buffer, "%*s %*s %"SCNd32, &st->codecpar->sample_rate);
         } else if (!memcmp(buffer, "sample_sig_bits", 15)) {
-            sscanf(buffer, "%*s %*s %"SCNd32, &st->codec->bits_per_coded_sample);
+            sscanf(buffer, "%*s %*s %"SCNd32, &st->codecpar->bits_per_coded_sample);
         } else {
             char key[32], value[32];
-            if (sscanf(buffer, "%31s %*s %31s", key, value) == 3) {
+            if (sscanf(buffer, "%31s %*s %31s", key, value) == 2) {
                 av_dict_set(&s->metadata, key, value, AV_DICT_APPEND);
             } else {
                 av_log(s, AV_LOG_ERROR, "Failed to parse '%s' as metadata\n", buffer);
diff --git a/libavformat/noproxy-test.c b/libavformat/noproxy-test.c
deleted file mode 100644
index 4524764..0000000
--- a/libavformat/noproxy-test.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2013 Martin Storsjo
- *
- * 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 "network.h"
-
-static void test(const char *pattern, const char *host)
-{
-    int res = ff_http_match_no_proxy(pattern, host);
-    printf("The pattern \"%s\" %s the hostname %s\n",
-           pattern ? pattern : "(null)", res ? "matches" : "does not match",
-           host);
-}
-
-int main(void)
-{
-    test(NULL, "domain.com");
-    test("example.com domain.com", "domain.com");
-    test("example.com other.com", "domain.com");
-    test("example.com,domain.com", "domain.com");
-    test("example.com,domain.com", "otherdomain.com");
-    test("example.com, *.domain.com", "sub.domain.com");
-    test("example.com, *.domain.com", "domain.com");
-    test("example.com, .domain.com", "domain.com");
-    test("*", "domain.com");
-    return 0;
-}
diff --git a/libavformat/nsvdec.c b/libavformat/nsvdec.c
index 95fab64..507fb39 100644
--- a/libavformat/nsvdec.c
+++ b/libavformat/nsvdec.c
@@ -57,14 +57,14 @@
  * (that is the offset of the data table after the header).
  * After checking all samples from (S1) all confirms this.
  *
- * Then, about NSVf[12-15], faster.nsf has 179700. When veiwing it in VLC,
+ * Then, about NSVf[12-15], faster.nsf has 179700. When viewing it in VLC,
  * I noticed there was about 1 NVSs chunk/s, so I ran
  * strings faster.nsv | grep NSVs | wc -l
  * which gave me 180. That leads me to think that NSVf[12-15] might be the
  * file length in milliseconds.
  * Let's try that:
  * for f in *.nsv; do HTIME="$(od -t x4 "$f" | head -1 | sed 's/.* //')"; echo "'$f' $((0x$HTIME))s = $((0x$HTIME/1000/60)):$((0x$HTIME/1000%60))"; done
- * except for nstrailer (which doesn't have an NSVf header), it repports correct time.
+ * except for nsvtrailer (which doesn't have an NSVf header), it reports correct time.
  *
  * nsvtrailer.nsv (S1) does not have any NSVf header, only NSVs chunks,
  * so the header seems to not be mandatory. (for streaming).
@@ -434,12 +434,12 @@ static int nsv_parse_NSVs_header(AVFormatContext *s)
             if (!nst)
                 goto fail;
             st->priv_data = nst;
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_tag = vtag;
-            st->codec->codec_id = ff_codec_get_id(nsv_codec_video_tags, vtag);
-            st->codec->width = vwidth;
-            st->codec->height = vheight;
-            st->codec->bits_per_coded_sample = 24; /* depth XXX */
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_tag = vtag;
+            st->codecpar->codec_id = ff_codec_get_id(nsv_codec_video_tags, vtag);
+            st->codecpar->width = vwidth;
+            st->codecpar->height = vheight;
+            st->codecpar->bits_per_coded_sample = 24; /* depth XXX */
 
             avpriv_set_pts_info(st, 64, framerate.den, framerate.num);
             st->start_time = 0;
@@ -465,9 +465,9 @@ static int nsv_parse_NSVs_header(AVFormatContext *s)
             if (!nst)
                 goto fail;
             st->priv_data = nst;
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-            st->codec->codec_tag = atag;
-            st->codec->codec_id = ff_codec_get_id(nsv_codec_audio_tags, atag);
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_tag = atag;
+            st->codecpar->codec_id = ff_codec_get_id(nsv_codec_audio_tags, atag);
 
             st->need_parsing = AVSTREAM_PARSE_FULL; /* for PCM we will read a chunk later and put correct info */
 
@@ -579,7 +579,7 @@ null_chunk_retry:
               ((auxtag >> 24) & 0x0ff),
               auxsize);
         avio_skip(pb, auxsize);
-        vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming braindead */
+        vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming brain-dead */
     }
 
     if (avio_feof(pb))
@@ -614,7 +614,7 @@ null_chunk_retry:
         pkt = &nsv->ahead[NSV_ST_AUDIO];
         /* read raw audio specific header on the first audio chunk... */
         /* on ALL audio chunks ?? seems so! */
-        if (asize && st[NSV_ST_AUDIO]->codec->codec_tag == MKTAG('P', 'C', 'M', ' ')/* && fill_header*/) {
+        if (asize && st[NSV_ST_AUDIO]->codecpar->codec_tag == MKTAG('P', 'C', 'M', ' ')/* && fill_header*/) {
             uint8_t bps;
             uint8_t channels;
             uint16_t samplerate;
@@ -632,11 +632,11 @@ null_chunk_retry:
                 }
                 bps /= channels; // ???
                 if (bps == 8)
-                    st[NSV_ST_AUDIO]->codec->codec_id = AV_CODEC_ID_PCM_U8;
+                    st[NSV_ST_AUDIO]->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
                 samplerate /= 4;/* UGH ??? XXX */
                 channels = 1;
-                st[NSV_ST_AUDIO]->codec->channels = channels;
-                st[NSV_ST_AUDIO]->codec->sample_rate = samplerate;
+                st[NSV_ST_AUDIO]->codecpar->channels = channels;
+                st[NSV_ST_AUDIO]->codecpar->sample_rate = samplerate;
                 av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate);
             }
         }
@@ -683,7 +683,7 @@ static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt)
         }
     }
 
-    /* this restaurant is not approvisionned :^] */
+    /* this restaurant is not provisioned :^] */
     return -1;
 }
 
diff --git a/libavformat/nut.c b/libavformat/nut.c
index f4901e6..88d0dc2 100644
--- a/libavformat/nut.c
+++ b/libavformat/nut.c
@@ -27,7 +27,6 @@
 
 const AVCodecTag ff_nut_subtitle_tags[] = {
     { AV_CODEC_ID_TEXT,             MKTAG('U', 'T', 'F', '8') },
-    { AV_CODEC_ID_SSA,              MKTAG('S', 'S', 'A',  0 ) },
     { AV_CODEC_ID_DVD_SUBTITLE,     MKTAG('D', 'V', 'D', 'S') },
     { AV_CODEC_ID_DVB_SUBTITLE,     MKTAG('D', 'V', 'B', 'S') },
     { AV_CODEC_ID_DVB_TELETEXT,     MKTAG('D', 'V', 'B', 'T') },
diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c
index 4df6a57..2e309bc 100644
--- a/libavformat/nutdec.c
+++ b/libavformat/nutdec.c
@@ -415,11 +415,11 @@ static int decode_stream_header(NUTContext *nut)
 
     class                = ffio_read_varlen(bc);
     tmp                  = get_fourcc(bc);
-    st->codec->codec_tag = tmp;
+    st->codecpar->codec_tag = tmp;
     switch (class) {
     case 0:
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id   = av_codec_get_id((const AVCodecTag * const []) {
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_id   = av_codec_get_id((const AVCodecTag * const []) {
                                                     ff_nut_video_tags,
                                                     ff_codec_bmp_tags,
                                                     ff_codec_movvideo_tags,
@@ -428,8 +428,8 @@ static int decode_stream_header(NUTContext *nut)
                                                 tmp);
         break;
     case 1:
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id   = av_codec_get_id((const AVCodecTag * const []) {
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id   = av_codec_get_id((const AVCodecTag * const []) {
                                                     ff_nut_audio_tags,
                                                     ff_codec_wav_tags,
                                                     ff_nut_audio_extra_tags,
@@ -438,18 +438,18 @@ static int decode_stream_header(NUTContext *nut)
                                                 tmp);
         break;
     case 2:
-        st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-        st->codec->codec_id   = ff_codec_get_id(ff_nut_subtitle_tags, tmp);
+        st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+        st->codecpar->codec_id   = ff_codec_get_id(ff_nut_subtitle_tags, tmp);
         break;
     case 3:
-        st->codec->codec_type = AVMEDIA_TYPE_DATA;
-        st->codec->codec_id   = ff_codec_get_id(ff_nut_data_tags, tmp);
+        st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+        st->codecpar->codec_id   = ff_codec_get_id(ff_nut_data_tags, tmp);
         break;
     default:
         av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class);
         return AVERROR(ENOSYS);
     }
-    if (class < 3 && st->codec->codec_id == AV_CODEC_ID_NONE)
+    if (class < 3 && st->codecpar->codec_id == AV_CODEC_ID_NONE)
         av_log(s, AV_LOG_ERROR,
                "Unknown codec tag '0x%04x' for stream number %d\n",
                (unsigned int) tmp, stream_id);
@@ -458,18 +458,18 @@ static int decode_stream_header(NUTContext *nut)
     GET_V(stc->msb_pts_shift, tmp < 16);
     stc->max_pts_distance = ffio_read_varlen(bc);
     GET_V(stc->decode_delay, tmp < 1000); // sanity limit, raise this if Moore's law is true
-    st->codec->has_b_frames = stc->decode_delay;
+    st->codecpar->video_delay = stc->decode_delay;
     ffio_read_varlen(bc); // stream flags
 
-    GET_V(st->codec->extradata_size, tmp < (1 << 30));
-    if (st->codec->extradata_size) {
-        if (ff_get_extradata(st->codec, bc, st->codec->extradata_size) < 0)
+    GET_V(st->codecpar->extradata_size, tmp < (1 << 30));
+    if (st->codecpar->extradata_size) {
+        if (ff_get_extradata(s, st->codecpar, bc, st->codecpar->extradata_size) < 0)
             return AVERROR(ENOMEM);
     }
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-        GET_V(st->codec->width,  tmp > 0);
-        GET_V(st->codec->height, tmp > 0);
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+        GET_V(st->codecpar->width,  tmp > 0);
+        GET_V(st->codecpar->height, tmp > 0);
         st->sample_aspect_ratio.num = ffio_read_varlen(bc);
         st->sample_aspect_ratio.den = ffio_read_varlen(bc);
         if ((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)) {
@@ -479,10 +479,10 @@ static int decode_stream_header(NUTContext *nut)
             goto fail;
         }
         ffio_read_varlen(bc); /* csp type */
-    } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-        GET_V(st->codec->sample_rate, tmp > 0);
+    } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+        GET_V(st->codecpar->sample_rate, tmp > 0);
         ffio_read_varlen(bc); // samplerate_den
-        GET_V(st->codec->channels, tmp > 0);
+        GET_V(st->codecpar->channels, tmp > 0);
     }
     if (skip_reserved(bc, end) || ffio_get_checksum(bc)) {
         av_log(s, AV_LOG_ERROR,
@@ -495,9 +495,9 @@ static int decode_stream_header(NUTContext *nut)
                         stc->time_base->den);
     return 0;
 fail:
-    if (st && st->codec) {
-        av_freep(&st->codec->extradata);
-        st->codec->extradata_size = 0;
+    if (st && st->codecpar) {
+        av_freep(&st->codecpar->extradata);
+        st->codecpar->extradata_size = 0;
     }
     return ret;
 }
diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c
index b6582ef..9e422e1 100644
--- a/libavformat/nutenc.c
+++ b/libavformat/nutenc.c
@@ -35,32 +35,32 @@
 #include "avio_internal.h"
 #include "riff.h"
 
-static int find_expected_header(AVCodecContext *c, int size, int key_frame,
+static int find_expected_header(AVCodecParameters *p, int size, int key_frame,
                                 uint8_t out[64])
 {
-    int sample_rate = c->sample_rate;
+    int sample_rate = p->sample_rate;
 
     if (size > 4096)
         return 0;
 
     AV_WB24(out, 1);
 
-    if (c->codec_id == AV_CODEC_ID_MPEG4) {
+    if (p->codec_id == AV_CODEC_ID_MPEG4) {
         if (key_frame) {
             return 3;
         } else {
             out[3] = 0xB6;
             return 4;
         }
-    } else if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO ||
-               c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
+    } else if (p->codec_id == AV_CODEC_ID_MPEG1VIDEO ||
+               p->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
         return 3;
-    } else if (c->codec_id == AV_CODEC_ID_H264) {
+    } else if (p->codec_id == AV_CODEC_ID_H264) {
         return 3;
-    } else if (c->codec_id == AV_CODEC_ID_MP3 ||
-               c->codec_id == AV_CODEC_ID_MP2) {
+    } else if (p->codec_id == AV_CODEC_ID_MP3 ||
+               p->codec_id == AV_CODEC_ID_MP2) {
         int lsf, mpeg25, sample_rate_index, bitrate_index, frame_size;
-        int layer           = c->codec_id == AV_CODEC_ID_MP3 ? 3 : 2;
+        int layer           = p->codec_id == AV_CODEC_ID_MP3 ? 3 : 2;
         unsigned int header = 0xFFF00000;
 
         lsf           = sample_rate < (24000 + 32000) / 2;
@@ -102,12 +102,13 @@ static int find_expected_header(AVCodecContext *c, int size, int key_frame,
     return 0;
 }
 
-static int find_header_idx(AVFormatContext *s, AVCodecContext *c, int size, int frame_type)
+static int find_header_idx(AVFormatContext *s, AVCodecParameters *p, int size,
+                           int frame_type)
 {
     NUTContext *nut = s->priv_data;
     uint8_t out[64];
     int i;
-    int len = find_expected_header(c, size, frame_type, out);
+    int len = find_expected_header(p, size, frame_type, out);
 
     for (i = 1; i < nut->header_count; i++) {
         if (len == nut->header_len[i] && !memcmp(out, nut->header[i], len)) {
@@ -167,18 +168,18 @@ static void build_frame_code(AVFormatContext *s)
     for (stream_id = 0; stream_id < s->nb_streams; stream_id++) {
         int start2 = start + (end - start) * stream_id       / s->nb_streams;
         int end2   = start + (end - start) * (stream_id + 1) / s->nb_streams;
-        AVCodecContext *codec = s->streams[stream_id]->codec;
-        int is_audio          = codec->codec_type == AVMEDIA_TYPE_AUDIO;
+        AVCodecParameters *par        = s->streams[stream_id]->codecpar;
+        int is_audio                  = par->codec_type == AVMEDIA_TYPE_AUDIO;
         int intra_only        = /*codec->intra_only || */ is_audio;
         int pred_count;
         int frame_size = 0;
 
-        if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            frame_size = av_get_audio_frame_duration(codec, 0);
-            if (codec->codec_id == AV_CODEC_ID_VORBIS && !frame_size)
+        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
+            frame_size = av_get_audio_frame_duration2(par, 0);
+            if (par->codec_id == AV_CODEC_ID_VORBIS && !frame_size)
                 frame_size = 64;
         } else {
-            AVRational f = av_div_q(codec->time_base, *nut->stream[stream_id].time_base);
+            AVRational f = av_div_q(av_inv_q(s->streams[stream_id]->avg_frame_rate), *nut->stream[stream_id].time_base);
             if (f.den == 1 && f.num>0)
                 frame_size = f.num;
         }
@@ -193,7 +194,7 @@ static void build_frame_code(AVFormatContext *s)
                 ft->stream_id = stream_id;
                 ft->size_mul  = 1;
                 if (is_audio)
-                    ft->header_idx = find_header_idx(s, codec, -1, key_frame);
+                    ft->header_idx = find_header_idx(s, par, -1, key_frame);
                 start2++;
             }
         }
@@ -201,9 +202,16 @@ static void build_frame_code(AVFormatContext *s)
         key_frame = intra_only;
 #if 1
         if (is_audio) {
-            int frame_bytes = codec->frame_size * (int64_t)codec->bit_rate /
-                              (8 * codec->sample_rate);
+            int frame_bytes;
             int pts;
+
+            if (par->block_align > 0) {
+                frame_bytes = par->block_align;
+            } else {
+                int frame_size = av_get_audio_frame_duration2(par, 0);
+                frame_bytes = frame_size * (int64_t)par->bit_rate / (8 * par->sample_rate);
+            }
+
             for (pts = 0; pts < 2; pts++) {
                 for (pred = 0; pred < 2; pred++) {
                     FrameCode *ft  = &nut->frame_code[start2];
@@ -212,7 +220,7 @@ static void build_frame_code(AVFormatContext *s)
                     ft->size_mul   = frame_bytes + 2;
                     ft->size_lsb   = frame_bytes + pred;
                     ft->pts_delta  = pts * frame_size;
-                    ft->header_idx = find_header_idx(s, codec, frame_bytes + pred, key_frame);
+                    ft->header_idx = find_header_idx(s, par, frame_bytes + pred, key_frame);
                     start2++;
                 }
             }
@@ -226,14 +234,14 @@ static void build_frame_code(AVFormatContext *s)
         }
 #endif
 
-        if (codec->has_b_frames) {
+        if (par->video_delay) {
             pred_count    = 5;
             pred_table[0] = -2;
             pred_table[1] = -1;
             pred_table[2] = 1;
             pred_table[3] = 3;
             pred_table[4] = 4;
-        } else if (codec->codec_id == AV_CODEC_ID_VORBIS) {
+        } else if (par->codec_id == AV_CODEC_ID_VORBIS) {
             pred_count    = 3;
             pred_table[0] = 2;
             pred_table[1] = 9;
@@ -259,7 +267,7 @@ static void build_frame_code(AVFormatContext *s)
                 ft->size_lsb  = index - start3;
                 ft->pts_delta = pred_table[pred];
                 if (is_audio)
-                    ft->header_idx = find_header_idx(s, codec, -1, key_frame);
+                    ft->header_idx = find_header_idx(s, par, -1, key_frame);
             }
         }
     }
@@ -418,18 +426,19 @@ static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc,
                               AVStream *st, int i)
 {
     NUTContext *nut       = avctx->priv_data;
-    AVCodecContext *codec = st->codec;
+    AVCodecParameters *par = st->codecpar;
 
     ff_put_v(bc, i);
-    switch (codec->codec_type) {
+    switch (par->codec_type) {
     case AVMEDIA_TYPE_VIDEO:    ff_put_v(bc, 0); break;
     case AVMEDIA_TYPE_AUDIO:    ff_put_v(bc, 1); break;
     case AVMEDIA_TYPE_SUBTITLE: ff_put_v(bc, 2); break;
     default:                    ff_put_v(bc, 3); break;
     }
     ff_put_v(bc, 4);
-    if (codec->codec_tag) {
-        avio_wl32(bc, codec->codec_tag);
+
+    if (par->codec_tag) {
+        avio_wl32(bc, par->codec_tag);
     } else {
         av_log(avctx, AV_LOG_ERROR, "No codec tag defined for stream %d\n", i);
         return AVERROR(EINVAL);
@@ -438,21 +447,21 @@ static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc,
     ff_put_v(bc, nut->stream[i].time_base - nut->time_base);
     ff_put_v(bc, nut->stream[i].msb_pts_shift);
     ff_put_v(bc, nut->stream[i].max_pts_distance);
-    ff_put_v(bc, codec->has_b_frames);
+    ff_put_v(bc, par->video_delay);
     avio_w8(bc, 0); /* flags: 0x1 - fixed_fps, 0x2 - index_present */
 
-    ff_put_v(bc, codec->extradata_size);
-    avio_write(bc, codec->extradata, codec->extradata_size);
+    ff_put_v(bc, par->extradata_size);
+    avio_write(bc, par->extradata, par->extradata_size);
 
-    switch (codec->codec_type) {
+    switch (par->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
-        ff_put_v(bc, codec->sample_rate);
+        ff_put_v(bc, par->sample_rate);
         ff_put_v(bc, 1);
-        ff_put_v(bc, codec->channels);
+        ff_put_v(bc, par->channels);
         break;
     case AVMEDIA_TYPE_VIDEO:
-        ff_put_v(bc, codec->width);
-        ff_put_v(bc, codec->height);
+        ff_put_v(bc, par->width);
+        ff_put_v(bc, par->height);
 
         if (st->sample_aspect_ratio.num <= 0 ||
             st->sample_aspect_ratio.den <= 0) {
@@ -489,6 +498,7 @@ static int write_globalinfo(NUTContext *nut, AVIOContext *bc)
     if (ret < 0)
         return ret;
 
+    ff_standardize_creation_time(s);
     while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX)))
         count += add_info(dyn_bc, t->key, t->value);
 
@@ -522,12 +532,12 @@ static int write_streaminfo(NUTContext *nut, AVIOContext *bc, int stream_id) {
         if (st->disposition & ff_nut_dispositions[i].flag)
             count += add_info(dyn_bc, "Disposition", ff_nut_dispositions[i].str);
     }
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         uint8_t buf[256];
         if (st->r_frame_rate.num>0 && st->r_frame_rate.den>0)
             snprintf(buf, sizeof(buf), "%d/%d", st->r_frame_rate.num, st->r_frame_rate.den);
         else
-            snprintf(buf, sizeof(buf), "%d/%d", st->codec->time_base.den, st->codec->time_base.num);
+            snprintf(buf, sizeof(buf), "%d/%d", st->avg_frame_rate.num, st->avg_frame_rate.den);
         count += add_info(dyn_bc, "r_frame_rate", buf);
     }
     dyn_size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
@@ -722,8 +732,8 @@ static int nut_write_header(AVFormatContext *s)
         AVRational time_base;
         ff_parse_specific_params(st, &time_base.den, &ssize, &time_base.num);
 
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->codec->sample_rate) {
-            time_base = (AVRational) {1, st->codec->sample_rate};
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate) {
+            time_base = (AVRational) {1, st->codecpar->sample_rate};
         } else {
             time_base = ff_choose_timebase(s, st, 48000);
         }
diff --git a/libavformat/nuv.c b/libavformat/nuv.c
index c30da60..d920250 100644
--- a/libavformat/nuv.c
+++ b/libavformat/nuv.c
@@ -83,11 +83,11 @@ static int get_codec_data(AVIOContext *pb, AVStream *vst,
             avio_skip(pb, 6);
             size = PKTSIZE(avio_rl32(pb));
             if (vst && subtype == 'R') {
-                if (vst->codec->extradata) {
-                    av_freep(&vst->codec->extradata);
-                    vst->codec->extradata_size = 0;
+                if (vst->codecpar->extradata) {
+                    av_freep(&vst->codecpar->extradata);
+                    vst->codecpar->extradata_size = 0;
                 }
-                if (ff_get_extradata(vst->codec, pb, size) < 0)
+                if (ff_get_extradata(NULL, vst->codecpar, pb, size) < 0)
                     return AVERROR(ENOMEM);
                 size = 0;
                 if (!myth)
@@ -101,32 +101,32 @@ static int get_codec_data(AVIOContext *pb, AVStream *vst,
                 break;
             avio_rl32(pb); // version
             if (vst) {
-                vst->codec->codec_tag = avio_rl32(pb);
-                vst->codec->codec_id =
-                    ff_codec_get_id(ff_codec_bmp_tags, vst->codec->codec_tag);
-                if (vst->codec->codec_tag == MKTAG('R', 'J', 'P', 'G'))
-                    vst->codec->codec_id = AV_CODEC_ID_NUV;
+                vst->codecpar->codec_tag = avio_rl32(pb);
+                vst->codecpar->codec_id =
+                    ff_codec_get_id(ff_codec_bmp_tags, vst->codecpar->codec_tag);
+                if (vst->codecpar->codec_tag == MKTAG('R', 'J', 'P', 'G'))
+                    vst->codecpar->codec_id = AV_CODEC_ID_NUV;
             } else
                 avio_skip(pb, 4);
 
             if (ast) {
                 int id;
 
-                ast->codec->codec_tag             = avio_rl32(pb);
-                ast->codec->sample_rate           = avio_rl32(pb);
-                ast->codec->bits_per_coded_sample = avio_rl32(pb);
-                ast->codec->channels              = avio_rl32(pb);
-                ast->codec->channel_layout        = 0;
+                ast->codecpar->codec_tag             = avio_rl32(pb);
+                ast->codecpar->sample_rate           = avio_rl32(pb);
+                ast->codecpar->bits_per_coded_sample = avio_rl32(pb);
+                ast->codecpar->channels              = avio_rl32(pb);
+                ast->codecpar->channel_layout        = 0;
 
-                id = ff_wav_codec_get_id(ast->codec->codec_tag,
-                                         ast->codec->bits_per_coded_sample);
+                id = ff_wav_codec_get_id(ast->codecpar->codec_tag,
+                                         ast->codecpar->bits_per_coded_sample);
                 if (id == AV_CODEC_ID_NONE) {
-                    id = ff_codec_get_id(nuv_audio_tags, ast->codec->codec_tag);
+                    id = ff_codec_get_id(nuv_audio_tags, ast->codecpar->codec_tag);
                     if (id == AV_CODEC_ID_PCM_S16LE)
-                        id = ff_get_pcm_codec_id(ast->codec->bits_per_coded_sample,
+                        id = ff_get_pcm_codec_id(ast->codecpar->bits_per_coded_sample,
                                                  0, 0, ~1);
                 }
-                ast->codec->codec_id = id;
+                ast->codecpar->codec_id = id;
 
                 ast->need_parsing = AVSTREAM_PARSE_FULL;
             } else
@@ -195,15 +195,15 @@ static int nuv_header(AVFormatContext *s)
             return AVERROR(ENOMEM);
         ctx->v_id = vst->index;
 
-        ret = av_image_check_size(width, height, 0, ctx);
+        ret = av_image_check_size(width, height, 0, s);
         if (ret < 0)
             return ret;
 
-        vst->codec->codec_type            = AVMEDIA_TYPE_VIDEO;
-        vst->codec->codec_id              = AV_CODEC_ID_NUV;
-        vst->codec->width                 = width;
-        vst->codec->height                = height;
-        vst->codec->bits_per_coded_sample = 10;
+        vst->codecpar->codec_type            = AVMEDIA_TYPE_VIDEO;
+        vst->codecpar->codec_id              = AV_CODEC_ID_NUV;
+        vst->codecpar->width                 = width;
+        vst->codecpar->height                = height;
+        vst->codecpar->bits_per_coded_sample = 10;
         vst->sample_aspect_ratio          = av_d2q(aspect * height / width,
                                                    10000);
 #if FF_API_R_FRAME_RATE
@@ -220,14 +220,14 @@ static int nuv_header(AVFormatContext *s)
             return AVERROR(ENOMEM);
         ctx->a_id = ast->index;
 
-        ast->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
-        ast->codec->codec_id              = AV_CODEC_ID_PCM_S16LE;
-        ast->codec->channels              = 2;
-        ast->codec->channel_layout        = AV_CH_LAYOUT_STEREO;
-        ast->codec->sample_rate           = 44100;
-        ast->codec->bit_rate              = 2 * 2 * 44100 * 8;
-        ast->codec->block_align           = 2 * 2;
-        ast->codec->bits_per_coded_sample = 16;
+        ast->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
+        ast->codecpar->codec_id              = AV_CODEC_ID_PCM_S16LE;
+        ast->codecpar->channels              = 2;
+        ast->codecpar->channel_layout        = AV_CH_LAYOUT_STEREO;
+        ast->codecpar->sample_rate           = 44100;
+        ast->codecpar->bit_rate              = 2 * 2 * 44100 * 8;
+        ast->codecpar->block_align           = 2 * 2;
+        ast->codecpar->bits_per_coded_sample = 16;
         avpriv_set_pts_info(ast, 32, 1, 1000);
     } else
         ctx->a_id = -1;
@@ -235,7 +235,7 @@ static int nuv_header(AVFormatContext *s)
     if ((ret = get_codec_data(pb, vst, ast, is_mythtv)) < 0)
         return ret;
 
-    ctx->rtjpg_video = vst && vst->codec->codec_id == AV_CODEC_ID_NUV;
+    ctx->rtjpg_video = vst && vst->codecpar->codec_id == AV_CODEC_ID_NUV;
 
     return 0;
 }
diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c
index 2d99b4a..47a0cba 100644
--- a/libavformat/oggdec.c
+++ b/libavformat/oggdec.c
@@ -701,6 +701,7 @@ static int ogg_read_header(AVFormatContext *s)
         if (ogg->streams[i].header < 0) {
             av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
             ogg->streams[i].codec = NULL;
+            av_freep(&ogg->streams[i].private);
         } else if (os->codec && os->nb_header < os->codec->nb_header) {
             av_log(s, AV_LOG_WARNING,
                    "Headers mismatch for stream %d: "
@@ -760,7 +761,7 @@ static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int p
     struct ogg_stream *os = ogg->streams + idx;
     int invalid = 0;
     if (psize) {
-        switch (s->streams[idx]->codec->codec_id) {
+        switch (s->streams[idx]->codecpar->codec_id) {
         case AV_CODEC_ID_THEORA:
             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
         break;
@@ -864,7 +865,7 @@ static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
            && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
         if (i == stream_index) {
             struct ogg_stream *os = ogg->streams + stream_index;
-            // Do not trust the last timestamps of a ogm video
+            // Do not trust the last timestamps of an ogm video
             if (    (os->flags & OGG_FLAG_EOS)
                 && !(os->flags & OGG_FLAG_BOS)
                 && os->codec == &ff_ogm_video_codec)
@@ -903,7 +904,7 @@ static int ogg_read_seek(AVFormatContext *s, int stream_index,
 
     // Try seeking to a keyframe first. If this fails (very possible),
     // av_seek_frame will fall back to ignoring keyframes
-    if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
+    if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
         && !(flags & AVSEEK_FLAG_ANY))
         os->keyframe_seek = 1;
 
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index 4907512..f998af3 100644
--- a/libavformat/oggenc.c
+++ b/libavformat/oggenc.c
@@ -223,7 +223,7 @@ static int ogg_buffer_data(AVFormatContext *s, AVStream *st,
     // them as such, otherwise seeking will not work correctly at the very
     // least with old libogg versions.
     // Do not try to flush header packets though, that will create broken files.
-    if (st->codec->codec_id == AV_CODEC_ID_THEORA && !header &&
+    if (st->codecpar->codec_id == AV_CODEC_ID_THEORA && !header &&
         (ogg_granule_to_timestamp(oggstream, granule) >
          ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1 ||
          ogg_key_granule(oggstream, granule))) {
@@ -311,13 +311,13 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact,
     return p0;
 }
 
-static int ogg_build_flac_headers(AVCodecContext *avctx,
+static int ogg_build_flac_headers(AVCodecParameters *par,
                                   OGGStreamContext *oggstream, int bitexact,
                                   AVDictionary **m)
 {
     uint8_t *p;
 
-    if (avctx->extradata_size < FLAC_STREAMINFO_SIZE)
+    if (par->extradata_size < FLAC_STREAMINFO_SIZE)
         return AVERROR(EINVAL);
 
     // first packet: STREAMINFO
@@ -334,7 +334,7 @@ static int ogg_build_flac_headers(AVCodecContext *avctx,
     bytestream_put_buffer(&p, "fLaC", 4);
     bytestream_put_byte(&p, 0x00); // streaminfo
     bytestream_put_be24(&p, 34);
-    bytestream_put_buffer(&p, avctx->extradata, FLAC_STREAMINFO_SIZE);
+    bytestream_put_buffer(&p, par->extradata, FLAC_STREAMINFO_SIZE);
 
     // second packet: VorbisComment
     p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m, 0);
@@ -349,13 +349,13 @@ static int ogg_build_flac_headers(AVCodecContext *avctx,
 
 #define SPEEX_HEADER_SIZE 80
 
-static int ogg_build_speex_headers(AVCodecContext *avctx,
+static int ogg_build_speex_headers(AVCodecParameters *par,
                                    OGGStreamContext *oggstream, int bitexact,
                                    AVDictionary **m)
 {
     uint8_t *p;
 
-    if (avctx->extradata_size < SPEEX_HEADER_SIZE)
+    if (par->extradata_size < SPEEX_HEADER_SIZE)
         return AVERROR_INVALIDDATA;
 
     // first packet: Speex header
@@ -364,7 +364,7 @@ static int ogg_build_speex_headers(AVCodecContext *avctx,
         return AVERROR(ENOMEM);
     oggstream->header[0] = p;
     oggstream->header_len[0] = SPEEX_HEADER_SIZE;
-    bytestream_put_buffer(&p, avctx->extradata, SPEEX_HEADER_SIZE);
+    bytestream_put_buffer(&p, par->extradata, SPEEX_HEADER_SIZE);
     AV_WL32(&oggstream->header[0][68], 0);  // set extra_headers to 0
 
     // second packet: VorbisComment
@@ -378,22 +378,22 @@ static int ogg_build_speex_headers(AVCodecContext *avctx,
 
 #define OPUS_HEADER_SIZE 19
 
-static int ogg_build_opus_headers(AVCodecContext *avctx,
+static int ogg_build_opus_headers(AVCodecParameters *par,
                                   OGGStreamContext *oggstream, int bitexact,
                                   AVDictionary **m)
 {
     uint8_t *p;
 
-    if (avctx->extradata_size < OPUS_HEADER_SIZE)
+    if (par->extradata_size < OPUS_HEADER_SIZE)
         return AVERROR_INVALIDDATA;
 
     /* first packet: Opus header */
-    p = av_mallocz(avctx->extradata_size);
+    p = av_mallocz(par->extradata_size);
     if (!p)
         return AVERROR(ENOMEM);
     oggstream->header[0] = p;
-    oggstream->header_len[0] = avctx->extradata_size;
-    bytestream_put_buffer(&p, avctx->extradata, avctx->extradata_size);
+    oggstream->header_len[0] = par->extradata_size;
+    bytestream_put_buffer(&p, par->extradata, par->extradata_size);
 
     /* second packet: VorbisComment */
     p = ogg_write_vorbiscomment(8, bitexact, &oggstream->header_len[1], m, 0);
@@ -440,24 +440,24 @@ static int ogg_write_header(AVFormatContext *s)
         AVStream *st = s->streams[i];
         unsigned serial_num = i + ogg->serial_offset;
 
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            if (st->codec->codec_id == AV_CODEC_ID_OPUS)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_OPUS)
                 /* Opus requires a fixed 48kHz clock */
                 avpriv_set_pts_info(st, 64, 1, 48000);
             else
-                avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+                avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
         }
 
-        if (st->codec->codec_id != AV_CODEC_ID_VORBIS &&
-            st->codec->codec_id != AV_CODEC_ID_THEORA &&
-            st->codec->codec_id != AV_CODEC_ID_SPEEX  &&
-            st->codec->codec_id != AV_CODEC_ID_FLAC   &&
-            st->codec->codec_id != AV_CODEC_ID_OPUS) {
+        if (st->codecpar->codec_id != AV_CODEC_ID_VORBIS &&
+            st->codecpar->codec_id != AV_CODEC_ID_THEORA &&
+            st->codecpar->codec_id != AV_CODEC_ID_SPEEX  &&
+            st->codecpar->codec_id != AV_CODEC_ID_FLAC   &&
+            st->codecpar->codec_id != AV_CODEC_ID_OPUS) {
             av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i);
             return AVERROR(EINVAL);
         }
 
-        if (!st->codec->extradata || !st->codec->extradata_size) {
+        if (!st->codecpar->extradata || !st->codecpar->extradata_size) {
             av_log(s, AV_LOG_ERROR, "No extradata present\n");
             return AVERROR_INVALIDDATA;
         }
@@ -481,8 +481,8 @@ static int ogg_write_header(AVFormatContext *s)
         av_dict_copy(&st->metadata, s->metadata, AV_DICT_DONT_OVERWRITE);
 
         st->priv_data = oggstream;
-        if (st->codec->codec_id == AV_CODEC_ID_FLAC) {
-            int err = ogg_build_flac_headers(st->codec, oggstream,
+        if (st->codecpar->codec_id == AV_CODEC_ID_FLAC) {
+            int err = ogg_build_flac_headers(st->codecpar, oggstream,
                                              s->flags & AVFMT_FLAG_BITEXACT,
                                              &st->metadata);
             if (err) {
@@ -490,8 +490,8 @@ static int ogg_write_header(AVFormatContext *s)
                 av_freep(&st->priv_data);
                 return err;
             }
-        } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) {
-            int err = ogg_build_speex_headers(st->codec, oggstream,
+        } else if (st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
+            int err = ogg_build_speex_headers(st->codecpar, oggstream,
                                               s->flags & AVFMT_FLAG_BITEXACT,
                                               &st->metadata);
             if (err) {
@@ -499,8 +499,8 @@ static int ogg_write_header(AVFormatContext *s)
                 av_freep(&st->priv_data);
                 return err;
             }
-        } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) {
-            int err = ogg_build_opus_headers(st->codec, oggstream,
+        } else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) {
+            int err = ogg_build_opus_headers(st->codecpar, oggstream,
                                              s->flags & AVFMT_FLAG_BITEXACT,
                                              &st->metadata);
             if (err) {
@@ -510,12 +510,12 @@ static int ogg_write_header(AVFormatContext *s)
             }
         } else {
             uint8_t *p;
-            const char *cstr = st->codec->codec_id == AV_CODEC_ID_VORBIS ? "vorbis" : "theora";
-            int header_type = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 3 : 0x81;
-            int framing_bit = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 1 : 0;
+            const char *cstr = st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? "vorbis" : "theora";
+            int header_type = st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? 3 : 0x81;
+            int framing_bit = st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? 1 : 0;
 
-            if (avpriv_split_xiph_headers(st->codec->extradata, st->codec->extradata_size,
-                                      st->codec->codec_id == AV_CODEC_ID_VORBIS ? 30 : 42,
+            if (avpriv_split_xiph_headers(st->codecpar->extradata, st->codecpar->extradata_size,
+                                      st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? 30 : 42,
                                       (const uint8_t**)oggstream->header, oggstream->header_len) < 0) {
                 av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
                 av_freep(&st->priv_data);
@@ -532,7 +532,7 @@ static int ogg_write_header(AVFormatContext *s)
             bytestream_put_byte(&p, header_type);
             bytestream_put_buffer(&p, cstr, 6);
 
-            if (st->codec->codec_id == AV_CODEC_ID_THEORA) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_THEORA) {
                 /** KFGSHIFT is the width of the less significant section of the granule position
                     The less significant section is the frame count since the last keyframe */
                 oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstream->header[0][41]>>5);
@@ -575,7 +575,7 @@ static int ogg_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
     int ret;
     int64_t granule;
 
-    if (st->codec->codec_id == AV_CODEC_ID_THEORA) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_THEORA) {
         int64_t pts = oggstream->vrev < 1 ? pkt->pts : pkt->pts + pkt->duration;
         int pframe_count;
         if (pkt->flags & AV_PKT_FLAG_KEY)
@@ -587,10 +587,10 @@ static int ogg_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
             pframe_count = 0;
         }
         granule = (oggstream->last_kf_pts<<oggstream->kfgshift) | pframe_count;
-    } else if (st->codec->codec_id == AV_CODEC_ID_OPUS)
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS)
         granule = pkt->pts + pkt->duration +
-                  av_rescale_q(st->codec->initial_padding,
-                               (AVRational){ 1, st->codec->sample_rate },
+                  av_rescale_q(st->codecpar->initial_padding,
+                               (AVRational){ 1, st->codecpar->sample_rate },
                                st->time_base);
     else
         granule = pkt->pts + pkt->duration;
@@ -643,9 +643,9 @@ static int ogg_write_trailer(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st = s->streams[i];
         OGGStreamContext *oggstream = st->priv_data;
-        if (st->codec->codec_id == AV_CODEC_ID_FLAC ||
-            st->codec->codec_id == AV_CODEC_ID_SPEEX ||
-            st->codec->codec_id == AV_CODEC_ID_OPUS) {
+        if (st->codecpar->codec_id == AV_CODEC_ID_FLAC ||
+            st->codecpar->codec_id == AV_CODEC_ID_SPEEX ||
+            st->codecpar->codec_id == AV_CODEC_ID_OPUS) {
             av_freep(&oggstream->header[0]);
         }
         av_freep(&oggstream->header[1]);
diff --git a/libavformat/oggparsecelt.c b/libavformat/oggparsecelt.c
index 2c0c511..6d567f9 100644
--- a/libavformat/oggparsecelt.c
+++ b/libavformat/oggparsecelt.c
@@ -48,7 +48,7 @@ static int celt_header(AVFormatContext *s, int idx)
         priv = av_malloc(sizeof(struct oggcelt_private));
         if (!priv)
             return AVERROR(ENOMEM);
-        if (ff_alloc_extradata(st->codec, 2 * sizeof(uint32_t)) < 0) {
+        if (ff_alloc_extradata(st->codecpar, 2 * sizeof(uint32_t)) < 0) {
             av_free(priv);
             return AVERROR(ENOMEM);
         }
@@ -59,17 +59,17 @@ static int celt_header(AVFormatContext *s, int idx)
         overlap          = AV_RL32(p + 48);
         /* unused bytes per packet field skipped */
         extra_headers    = AV_RL32(p + 56);
-        st->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id       = AV_CODEC_ID_CELT;
-        st->codec->sample_rate    = sample_rate;
-        st->codec->channels       = nb_channels;
+        st->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id       = AV_CODEC_ID_CELT;
+        st->codecpar->sample_rate    = sample_rate;
+        st->codecpar->channels       = nb_channels;
         if (sample_rate)
             avpriv_set_pts_info(st, 64, 1, sample_rate);
         priv->extra_headers_left  = 1 + extra_headers;
         av_free(os->private);
         os->private = priv;
-        AV_WL32(st->codec->extradata + 0, overlap);
-        AV_WL32(st->codec->extradata + 4, version);
+        AV_WL32(st->codecpar->extradata + 0, overlap);
+        AV_WL32(st->codecpar->extradata + 4, version);
         return 1;
     } else if (priv && priv->extra_headers_left) {
         /* Extra headers (vorbiscomment) */
diff --git a/libavformat/oggparsedaala.c b/libavformat/oggparsedaala.c
index 3651ca1..89bda58 100644
--- a/libavformat/oggparsedaala.c
+++ b/libavformat/oggparsedaala.c
@@ -84,7 +84,7 @@ static int daala_header(AVFormatContext *s, int idx)
     struct ogg *ogg        = s->priv_data;
     struct ogg_stream *os  = ogg->streams + idx;
     AVStream *st           = s->streams[idx];
-    int cds                = st->codec->extradata_size + os->psize + 2;
+    int cds                = st->codecpar->extradata_size + os->psize + 2;
     DaalaInfoHeader *hdr   = os->private;
 
     if (!(os->buf[os->pstart] & 0x80))
@@ -106,8 +106,8 @@ static int daala_header(AVFormatContext *s, int idx)
         hdr->version_min = bytestream2_get_byte(&gb);
         hdr->version_sub = bytestream2_get_byte(&gb);
 
-        st->codec->width  = bytestream2_get_ne32(&gb);
-        st->codec->height = bytestream2_get_ne32(&gb);
+        st->codecpar->width  = bytestream2_get_ne32(&gb);
+        st->codecpar->height = bytestream2_get_ne32(&gb);
 
         st->sample_aspect_ratio.num = bytestream2_get_ne32(&gb);
         st->sample_aspect_ratio.den = bytestream2_get_ne32(&gb);
@@ -146,13 +146,13 @@ static int daala_header(AVFormatContext *s, int idx)
             hdr->format.ydec[i] = bytestream2_get_byte(&gb);
         }
 
-        if ((st->codec->pix_fmt = daala_match_pix_fmt(&hdr->format)) < 0)
+        if ((st->codecpar->format = daala_match_pix_fmt(&hdr->format)) < 0)
             av_log(s, AV_LOG_ERROR, "Unsupported pixel format - %i %i\n",
                    hdr->format.depth, hdr->format.planes);
 
-        st->codec->codec_id   = AV_CODEC_ID_DAALA;
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->need_parsing      = AVSTREAM_PARSE_HEADERS;
+        st->codecpar->codec_id   = AV_CODEC_ID_DAALA;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->need_parsing         = AVSTREAM_PARSE_HEADERS;
 
         hdr->init_d = 1;
         break;
@@ -173,18 +173,18 @@ static int daala_header(AVFormatContext *s, int idx)
         break;
     }
 
-    if ((err = av_reallocp(&st->codec->extradata,
+    if ((err = av_reallocp(&st->codecpar->extradata,
                            cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
-        st->codec->extradata_size = 0;
+        st->codecpar->extradata_size = 0;
         return err;
     }
 
-    memset(st->codec->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
-    cdp    = st->codec->extradata + st->codec->extradata_size;
+    memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+    cdp    = st->codecpar->extradata + st->codecpar->extradata_size;
     *cdp++ = os->psize >> 8;
     *cdp++ = os->psize & 0xff;
     memcpy(cdp, os->buf + os->pstart, os->psize);
-    st->codec->extradata_size = cds;
+    st->codecpar->extradata_size = cds;
 
     return 1;
 }
diff --git a/libavformat/oggparsedirac.c b/libavformat/oggparsedirac.c
index 3e5e393..74b9ba4 100644
--- a/libavformat/oggparsedirac.c
+++ b/libavformat/oggparsedirac.c
@@ -34,35 +34,35 @@ static int dirac_header(AVFormatContext *s, int idx)
     int ret;
 
     // already parsed the header
-    if (st->codec->codec_id == AV_CODEC_ID_DIRAC)
+    if (st->codecpar->codec_id == AV_CODEC_ID_DIRAC)
         return 0;
 
     ret = av_dirac_parse_sequence_header(&dsh, os->buf + os->pstart + 13, (os->psize - 13), s);
     if (ret < 0)
         return ret;
 
-    st->codec->codec_type      = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id        = AV_CODEC_ID_DIRAC;
-    st->codec->width           = dsh->width;
-    st->codec->height          = dsh->height;
-    st->codec->pix_fmt         = dsh->pix_fmt;
-    st->codec->color_range     = dsh->color_range;
-    st->codec->color_trc       = dsh->color_trc;
-    st->codec->color_primaries = dsh->color_primaries;
-    st->codec->colorspace      = dsh->colorspace;
-    st->codec->profile         = dsh->profile;
-    st->codec->level           = dsh->level;
-    if (av_image_check_sar(st->codec->width, st->codec->height, dsh->sample_aspect_ratio) >= 0)
+    st->codecpar->codec_type      = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id        = AV_CODEC_ID_DIRAC;
+    st->codecpar->width           = dsh->width;
+    st->codecpar->height          = dsh->height;
+    st->codecpar->format          = dsh->pix_fmt;
+    st->codecpar->color_range     = dsh->color_range;
+    st->codecpar->color_trc       = dsh->color_trc;
+    st->codecpar->color_primaries = dsh->color_primaries;
+    st->codecpar->color_space     = dsh->colorspace;
+    st->codecpar->profile         = dsh->profile;
+    st->codecpar->level           = dsh->level;
+    if (av_image_check_sar(st->codecpar->width, st->codecpar->height, dsh->sample_aspect_ratio) >= 0)
         st->sample_aspect_ratio = dsh->sample_aspect_ratio;
 
-    // dirac in ogg always stores timestamps as though the video were interlaced
+    // Dirac in Ogg always stores timestamps as though the video were interlaced
     avpriv_set_pts_info(st, 64, dsh->framerate.den, 2 * dsh->framerate.num);
 
     av_freep(&dsh);
     return 1;
 }
 
-// various undocument things: granule is signed (only for dirac!)
+// various undocumented things: granule is signed (only for Dirac!)
 static uint64_t dirac_gptopts(AVFormatContext *s, int idx, uint64_t granule,
                               int64_t *dts_out)
 {
@@ -93,8 +93,8 @@ static int old_dirac_header(AVFormatContext *s, int idx)
     if (buf[0] != 'K')
         return 0;
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_DIRAC;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_DIRAC;
     avpriv_set_pts_info(st, 64, AV_RB32(buf+12), AV_RB32(buf+8));
     return 1;
 }
diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c
index c7fb446..b5f1416 100644
--- a/libavformat/oggparseflac.c
+++ b/libavformat/oggparseflac.c
@@ -57,15 +57,15 @@ flac_header (AVFormatContext * s, int idx)
         if (get_bits_long(&gb, 32) != FLAC_STREAMINFO_SIZE)
             return -1;
 
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id = AV_CODEC_ID_FLAC;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id = AV_CODEC_ID_FLAC;
         st->need_parsing = AVSTREAM_PARSE_HEADERS;
 
-        if (ff_alloc_extradata(st->codec, FLAC_STREAMINFO_SIZE) < 0)
+        if (ff_alloc_extradata(st->codecpar, FLAC_STREAMINFO_SIZE) < 0)
             return AVERROR(ENOMEM);
-        memcpy(st->codec->extradata, streaminfo_start, st->codec->extradata_size);
+        memcpy(st->codecpar->extradata, streaminfo_start, st->codecpar->extradata_size);
 
-        samplerate = AV_RB24(st->codec->extradata + 10) >> 4;
+        samplerate = AV_RB24(st->codecpar->extradata + 10) >> 4;
         if (!samplerate)
             return AVERROR_INVALIDDATA;
 
@@ -84,28 +84,45 @@ old_flac_header (AVFormatContext * s, int idx)
     AVStream *st = s->streams[idx];
     struct ogg_stream *os = ogg->streams + idx;
     AVCodecParserContext *parser = av_parser_init(AV_CODEC_ID_FLAC);
-    int size;
+    AVCodecContext *avctx;
+    int size, ret;
     uint8_t *data;
 
     if (!parser)
         return -1;
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_FLAC;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_FLAC;
+
+    avctx = avcodec_alloc_context3(NULL);
+    if (!avctx) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ret = avcodec_parameters_to_context(avctx, st->codecpar);
+    if (ret < 0)
+        goto fail;
 
     parser->flags = PARSER_FLAG_COMPLETE_FRAMES;
-    av_parser_parse2(parser, st->codec,
+    av_parser_parse2(parser, avctx,
                      &data, &size, os->buf + os->pstart, os->psize,
                      AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1);
 
     av_parser_close(parser);
 
-    if (st->codec->sample_rate) {
-        avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    if (avctx->sample_rate) {
+        avpriv_set_pts_info(st, 64, 1, avctx->sample_rate);
+        avcodec_free_context(&avctx);
         return 0;
     }
 
+    avcodec_free_context(&avctx);
     return 1;
+fail:
+    av_parser_close(parser);
+    avcodec_free_context(&avctx);
+    return ret;
 }
 
 const struct ogg_codec ff_flac_codec = {
diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c
index d63c83b..f8e656d 100644
--- a/libavformat/oggparseogm.c
+++ b/libavformat/oggparseogm.c
@@ -23,10 +23,12 @@
 **/
 
 #include <stdlib.h>
+
 #include "libavutil/avassert.h"
 #include "libavutil/intreadwrite.h"
-#include "libavcodec/get_bits.h"
+
 #include "libavcodec/bytestream.h"
+
 #include "avformat.h"
 #include "internal.h"
 #include "oggdec.h"
@@ -52,28 +54,28 @@ ogm_header(AVFormatContext *s, int idx)
 
         if (bytestream2_peek_byte(&p) == 'v'){
             int tag;
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
             bytestream2_skip(&p, 8);
             tag = bytestream2_get_le32(&p);
-            st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag);
-            st->codec->codec_tag = tag;
-            if (st->codec->codec_id == AV_CODEC_ID_MPEG4)
+            st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag);
+            st->codecpar->codec_tag = tag;
+            if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4)
                 st->need_parsing = AVSTREAM_PARSE_HEADERS;
         } else if (bytestream2_peek_byte(&p) == 't') {
-            st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-            st->codec->codec_id = AV_CODEC_ID_TEXT;
+            st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+            st->codecpar->codec_id = AV_CODEC_ID_TEXT;
             bytestream2_skip(&p, 12);
         } else {
             uint8_t acid[5] = { 0 };
             int cid;
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
             bytestream2_skip(&p, 8);
             bytestream2_get_buffer(&p, acid, 4);
             acid[4] = 0;
             cid = strtol(acid, NULL, 16);
-            st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, cid);
+            st->codecpar->codec_id = ff_codec_get_id(ff_codec_wav_tags, cid);
             // our parser completely breaks AAC in Ogg
-            if (st->codec->codec_id != AV_CODEC_ID_AAC)
+            if (st->codecpar->codec_id != AV_CODEC_ID_AAC)
                 st->need_parsing = AVSTREAM_PARSE_FULL;
         }
 
@@ -89,25 +91,25 @@ ogm_header(AVFormatContext *s, int idx)
         bytestream2_skip(&p, 4);    /* default_len */
         bytestream2_skip(&p, 8);    /* buffersize + bits_per_sample */
 
-        if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
-            st->codec->width = bytestream2_get_le32(&p);
-            st->codec->height = bytestream2_get_le32(&p);
+        if(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
+            st->codecpar->width = bytestream2_get_le32(&p);
+            st->codecpar->height = bytestream2_get_le32(&p);
             avpriv_set_pts_info(st, 64, time_unit, spu * 10000000);
         } else {
-            st->codec->channels = bytestream2_get_le16(&p);
+            st->codecpar->channels = bytestream2_get_le16(&p);
             bytestream2_skip(&p, 2); /* block_align */
-            st->codec->bit_rate = bytestream2_get_le32(&p) * 8;
-            st->codec->sample_rate = spu * 10000000 / time_unit;
-            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
-            if (size >= 56 && st->codec->codec_id == AV_CODEC_ID_AAC) {
+            st->codecpar->bit_rate = bytestream2_get_le32(&p) * 8;
+            st->codecpar->sample_rate = spu * 10000000 / time_unit;
+            avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
+            if (size >= 56 && st->codecpar->codec_id == AV_CODEC_ID_AAC) {
                 bytestream2_skip(&p, 4);
                 size -= 4;
             }
             if (size > 52) {
                 av_assert0(AV_INPUT_BUFFER_PADDING_SIZE <= 52);
                 size -= 52;
-                ff_alloc_extradata(st->codec, size);
-                bytestream2_get_buffer(&p, st->codec->extradata, st->codec->extradata_size);
+                ff_alloc_extradata(st->codecpar, size);
+                bytestream2_get_buffer(&p, st->codecpar->extradata, st->codecpar->extradata_size);
             }
         }
     } else if (bytestream2_peek_byte(&p) == 3) {
@@ -141,20 +143,20 @@ ogm_dshow_header(AVFormatContext *s, int idx)
         if (os->psize < 184)
             return AVERROR_INVALIDDATA;
 
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68));
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68));
         avpriv_set_pts_info(st, 64, AV_RL64(p + 164), 10000000);
-        st->codec->width = AV_RL32(p + 176);
-        st->codec->height = AV_RL32(p + 180);
+        st->codecpar->width = AV_RL32(p + 176);
+        st->codecpar->height = AV_RL32(p + 180);
     } else if(t == 0x05589f81){
         if (os->psize < 136)
             return AVERROR_INVALIDDATA;
 
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124));
-        st->codec->channels = AV_RL16(p + 126);
-        st->codec->sample_rate = AV_RL32(p + 128);
-        st->codec->bit_rate = AV_RL32(p + 132) * 8;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124));
+        st->codecpar->channels = AV_RL16(p + 126);
+        st->codecpar->sample_rate = AV_RL32(p + 128);
+        st->codecpar->bit_rate = AV_RL32(p + 132) * 8;
     }
 
     return 1;
diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c
index c8b02fa..f45ad84 100644
--- a/libavformat/oggparseopus.c
+++ b/libavformat/oggparseopus.c
@@ -52,24 +52,24 @@ static int opus_header(AVFormatContext *avf, int idx)
     if (os->flags & OGG_FLAG_BOS) {
         if (os->psize < OPUS_HEAD_SIZE || (AV_RL8(packet + 8) & 0xF0) != 0)
             return AVERROR_INVALIDDATA;
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id   = AV_CODEC_ID_OPUS;
-        st->codec->channels   = AV_RL8 (packet + 9);
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id   = AV_CODEC_ID_OPUS;
+        st->codecpar->channels   = AV_RL8(packet + 9);
+
         priv->pre_skip        = AV_RL16(packet + 10);
-        st->codec->delay      = priv->pre_skip;
+        st->codecpar->initial_padding = priv->pre_skip;
         /*orig_sample_rate    = AV_RL32(packet + 12);*/
         /*gain                = AV_RL16(packet + 16);*/
         /*channel_map         = AV_RL8 (packet + 18);*/
 
-        if (ff_alloc_extradata(st->codec, os->psize))
+        if (ff_alloc_extradata(st->codecpar, os->psize))
             return AVERROR(ENOMEM);
 
-        memcpy(st->codec->extradata, packet, os->psize);
+        memcpy(st->codecpar->extradata, packet, os->psize);
 
-        st->codec->sample_rate = 48000;
-        av_codec_set_seek_preroll(st->codec,
-                                  av_rescale(OPUS_SEEK_PREROLL_MS,
-                                             st->codec->sample_rate, 1000));
+        st->codecpar->sample_rate = 48000;
+        st->codecpar->seek_preroll = av_rescale(OPUS_SEEK_PREROLL_MS,
+                                                st->codecpar->sample_rate, 1000);
         avpriv_set_pts_info(st, 64, 1, 48000);
         priv->need_comments = 1;
         return 1;
@@ -117,6 +117,10 @@ static int opus_packet(AVFormatContext *avf, int idx)
 
     if (!os->psize)
         return AVERROR_INVALIDDATA;
+    if (os->granule > (1LL << 62)) {
+        av_log(avf, AV_LOG_ERROR, "Unsupported huge granule pos %"PRId64 "\n", os->granule);
+        return AVERROR_INVALIDDATA;
+    }
 
     if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
         int seg, d;
diff --git a/libavformat/oggparseskeleton.c b/libavformat/oggparseskeleton.c
index 6c2105f..532fa6a 100644
--- a/libavformat/oggparseskeleton.c
+++ b/libavformat/oggparseskeleton.c
@@ -34,7 +34,7 @@ static int skeleton_header(AVFormatContext *s, int idx)
     uint64_t start_granule;
     int target_idx, start_time;
 
-    st->codec->codec_type = AVMEDIA_TYPE_DATA;
+    st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
 
     if ((os->flags & OGG_FLAG_EOS) && os->psize == 0)
         return 1;
diff --git a/libavformat/oggparsespeex.c b/libavformat/oggparsespeex.c
index c86b127..434b0fd 100644
--- a/libavformat/oggparsespeex.c
+++ b/libavformat/oggparsespeex.c
@@ -23,11 +23,13 @@
 **/
 
 #include <stdlib.h>
+
 #include "libavutil/bswap.h"
 #include "libavutil/avstring.h"
 #include "libavutil/channel_layout.h"
-#include "libavcodec/get_bits.h"
+
 #include "libavcodec/bytestream.h"
+
 #include "avformat.h"
 #include "internal.h"
 #include "oggdec.h"
@@ -57,33 +59,33 @@ static int speex_header(AVFormatContext *s, int idx) {
 
     if (spxp->seq == 0) {
         int frames_per_packet;
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id = AV_CODEC_ID_SPEEX;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id = AV_CODEC_ID_SPEEX;
 
         if (os->psize < 68) {
             av_log(s, AV_LOG_ERROR, "speex packet too small\n");
             return AVERROR_INVALIDDATA;
         }
 
-        st->codec->sample_rate = AV_RL32(p + 36);
-        st->codec->channels = AV_RL32(p + 48);
-        if (st->codec->channels < 1 || st->codec->channels > 2) {
+        st->codecpar->sample_rate = AV_RL32(p + 36);
+        st->codecpar->channels = AV_RL32(p + 48);
+        if (st->codecpar->channels < 1 || st->codecpar->channels > 2) {
             av_log(s, AV_LOG_ERROR, "invalid channel count. Speex must be mono or stereo.\n");
             return AVERROR_INVALIDDATA;
         }
-        st->codec->channel_layout = st->codec->channels == 1 ? AV_CH_LAYOUT_MONO :
-                                                               AV_CH_LAYOUT_STEREO;
+        st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO :
+                                                                     AV_CH_LAYOUT_STEREO;
 
         spxp->packet_size  = AV_RL32(p + 56);
         frames_per_packet  = AV_RL32(p + 64);
         if (frames_per_packet)
             spxp->packet_size *= frames_per_packet;
 
-        if (ff_alloc_extradata(st->codec, os->psize) < 0)
+        if (ff_alloc_extradata(st->codecpar, os->psize) < 0)
             return AVERROR(ENOMEM);
-        memcpy(st->codec->extradata, p, st->codec->extradata_size);
+        memcpy(st->codecpar->extradata, p, st->codecpar->extradata_size);
 
-        avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+        avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     } else
         ff_vorbis_stream_comment(s, st, p, os->psize);
 
diff --git a/libavformat/oggparsetheora.c b/libavformat/oggparsetheora.c
index 5f057c3..b14f9f0 100644
--- a/libavformat/oggparsetheora.c
+++ b/libavformat/oggparsetheora.c
@@ -41,7 +41,7 @@ static int theora_header(AVFormatContext *s, int idx)
     struct ogg_stream *os = ogg->streams + idx;
     AVStream *st          = s->streams[idx];
     TheoraParams *thp     = os->private;
-    int cds               = st->codec->extradata_size + os->psize + 2;
+    int cds               = st->codecpar->extradata_size + os->psize + 2;
     int err;
     uint8_t *cdp;
 
@@ -72,8 +72,8 @@ static int theora_header(AVFormatContext *s, int idx)
             return AVERROR(ENOSYS);
         }
 
-        st->codec->width  = get_bits(&gb, 16) << 4;
-        st->codec->height = get_bits(&gb, 16) << 4;
+        st->codecpar->width  = get_bits(&gb, 16) << 4;
+        st->codecpar->height = get_bits(&gb, 16) << 4;
 
         if (thp->version >= 0x030400)
             skip_bits(&gb, 100);
@@ -81,10 +81,10 @@ static int theora_header(AVFormatContext *s, int idx)
         if (thp->version >= 0x030200) {
             int width  = get_bits_long(&gb, 24);
             int height = get_bits_long(&gb, 24);
-            if (width  <= st->codec->width  && width  > st->codec->width  - 16 &&
-                height <= st->codec->height && height > st->codec->height - 16) {
-                st->codec->width  = width;
-                st->codec->height = height;
+            if (width  <= st->codecpar->width  && width  > st->codecpar->width  - 16 &&
+                height <= st->codecpar->height && height > st->codecpar->height - 16) {
+                st->codecpar->width  = width;
+                st->codecpar->height = height;
             }
 
             skip_bits(&gb, 16);
@@ -110,8 +110,8 @@ static int theora_header(AVFormatContext *s, int idx)
         thp->gpshift = get_bits(&gb, 5);
         thp->gpmask  = (1U << thp->gpshift) - 1;
 
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id   = AV_CODEC_ID_THEORA;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_id   = AV_CODEC_ID_THEORA;
         st->need_parsing      = AVSTREAM_PARSE_HEADERS;
     }
     break;
@@ -126,18 +126,18 @@ static int theora_header(AVFormatContext *s, int idx)
         return AVERROR_INVALIDDATA;
     }
 
-    if ((err = av_reallocp(&st->codec->extradata,
+    if ((err = av_reallocp(&st->codecpar->extradata,
                            cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
-        st->codec->extradata_size = 0;
+        st->codecpar->extradata_size = 0;
         return err;
     }
-    memset(st->codec->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+    memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
 
-    cdp    = st->codec->extradata + st->codec->extradata_size;
+    cdp    = st->codecpar->extradata + st->codecpar->extradata_size;
     *cdp++ = os->psize >> 8;
     *cdp++ = os->psize & 0xff;
     memcpy(cdp, os->buf + os->pstart, os->psize);
-    st->codec->extradata_size = cds;
+    st->codecpar->extradata_size = cds;
 
     return 1;
 }
diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index b96be98..65b1998 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -28,9 +28,10 @@
 #include "libavutil/base64.h"
 #include "libavutil/bswap.h"
 #include "libavutil/dict.h"
+
 #include "libavcodec/bytestream.h"
-#include "libavcodec/get_bits.h"
 #include "libavcodec/vorbis_parser.h"
+
 #include "avformat.h"
 #include "flac_picture.h"
 #include "internal.h"
@@ -152,8 +153,8 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m,
              * recommended way of embedding cover art within VorbisComments."
              */
             if (!strcmp(tt, "METADATA_BLOCK_PICTURE") && parse_picture) {
-                int ret;
-                char *pict = av_malloc(vl);
+                int ret, len = AV_BASE64_DECODE_SIZE(vl);
+                char *pict = av_malloc(len);
 
                 if (!pict) {
                     av_log(as, AV_LOG_WARNING, "out-of-memory error. Skipping cover art block.\n");
@@ -161,10 +162,11 @@ int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m,
                     av_freep(&ct);
                     continue;
                 }
-                if ((ret = av_base64_decode(pict, ct, vl)) > 0)
-                    ret = ff_flac_parse_picture(as, pict, ret);
+                ret = av_base64_decode(pict, ct, len);
                 av_freep(&tt);
                 av_freep(&ct);
+                if (ret > 0)
+                    ret = ff_flac_parse_picture(as, pict, ret);
                 av_freep(&pict);
                 if (ret < 0) {
                     av_log(as, AV_LOG_WARNING, "Failed to parse cover art block.\n");
@@ -335,14 +337,14 @@ static int vorbis_header(AVFormatContext *s, int idx)
             return AVERROR_INVALIDDATA;
 
         channels = bytestream_get_byte(&p);
-        if (st->codec->channels && channels != st->codec->channels) {
+        if (st->codecpar->channels && channels != st->codecpar->channels) {
             av_log(s, AV_LOG_ERROR, "Channel change is not supported\n");
             return AVERROR_PATCHWELCOME;
         }
-        st->codec->channels = channels;
+        st->codecpar->channels = channels;
         srate               = bytestream_get_le32(&p);
         p += 4; // skip maximum bitrate
-        st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
+        st->codecpar->bit_rate = bytestream_get_le32(&p); // nominal bitrate
         p += 4; // skip minimum bitrate
 
         blocksize = bytestream_get_byte(&p);
@@ -357,11 +359,11 @@ static int vorbis_header(AVFormatContext *s, int idx)
         if (bytestream_get_byte(&p) != 1) /* framing_flag */
             return AVERROR_INVALIDDATA;
 
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id   = AV_CODEC_ID_VORBIS;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id   = AV_CODEC_ID_VORBIS;
 
         if (srate > 0) {
-            st->codec->sample_rate = srate;
+            st->codecpar->sample_rate = srate;
             avpriv_set_pts_info(st, 64, 1, srate);
         }
     } else if (os->buf[os->pstart] == 3) {
@@ -381,17 +383,17 @@ static int vorbis_header(AVFormatContext *s, int idx)
             }
         }
     } else {
-        int ret = fixup_vorbis_headers(s, priv, &st->codec->extradata);
+        int ret = fixup_vorbis_headers(s, priv, &st->codecpar->extradata);
         if (ret < 0) {
-            st->codec->extradata_size = 0;
+            st->codecpar->extradata_size = 0;
             return ret;
         }
-        st->codec->extradata_size = ret;
+        st->codecpar->extradata_size = ret;
 
-        priv->vp = av_vorbis_parse_init(st->codec->extradata, st->codec->extradata_size);
+        priv->vp = av_vorbis_parse_init(st->codecpar->extradata, st->codecpar->extradata_size);
         if (!priv->vp) {
-            av_freep(&st->codec->extradata);
-            st->codec->extradata_size = 0;
+            av_freep(&st->codecpar->extradata);
+            st->codecpar->extradata_size = 0;
             return AVERROR_UNKNOWN;
         }
     }
diff --git a/libavformat/oggparsevp8.c b/libavformat/oggparsevp8.c
index 7aed8ab..d57419e 100644
--- a/libavformat/oggparsevp8.c
+++ b/libavformat/oggparsevp8.c
@@ -51,16 +51,16 @@ static int vp8_header(AVFormatContext *s, int idx)
             return AVERROR_INVALIDDATA;
         }
 
-        st->codec->width            = AV_RB16(p +  8);
-        st->codec->height           = AV_RB16(p + 10);
+        st->codecpar->width         = AV_RB16(p +  8);
+        st->codecpar->height        = AV_RB16(p + 10);
         st->sample_aspect_ratio.num = AV_RB24(p + 12);
         st->sample_aspect_ratio.den = AV_RB24(p + 15);
         framerate.num               = AV_RB32(p + 18);
         framerate.den               = AV_RB32(p + 22);
 
         avpriv_set_pts_info(st, 64, framerate.den, framerate.num);
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id   = AV_CODEC_ID_VP8;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_id   = AV_CODEC_ID_VP8;
         st->need_parsing      = AVSTREAM_PARSE_HEADERS;
         break;
     case 0x02:
diff --git a/libavformat/omadec.c b/libavformat/omadec.c
index 132992d..6e476db 100644
--- a/libavformat/omadec.c
+++ b/libavformat/omadec.c
@@ -342,10 +342,10 @@ static int oma_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     st->start_time = 0;
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_tag  = buf[32];
-    st->codec->codec_id   = ff_codec_get_id(ff_oma_codec_tags,
-                                            st->codec->codec_tag);
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_tag  = buf[32];
+    st->codecpar->codec_id   = ff_codec_get_id(ff_oma_codec_tags,
+                                               st->codecpar->codec_tag);
 
     switch (buf[32]) {
     case OMA_CODECID_ATRAC3:
@@ -362,17 +362,17 @@ static int oma_read_header(AVFormatContext *s)
         /* get stereo coding mode, 1 for joint-stereo */
         jsflag = (codec_params >> 17) & 1;
 
-        st->codec->channels    = 2;
-        st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
-        st->codec->sample_rate = samplerate;
-        st->codec->bit_rate    = st->codec->sample_rate * framesize * 8 / 1024;
+        st->codecpar->channels    = 2;
+        st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+        st->codecpar->sample_rate = samplerate;
+        st->codecpar->bit_rate    = st->codecpar->sample_rate * framesize * 8 / 1024;
 
         /* fake the ATRAC3 extradata
          * (wav format, makes stream copy to wav work) */
-        if (ff_alloc_extradata(st->codec, 14))
+        if (ff_alloc_extradata(st->codecpar, 14))
             return AVERROR(ENOMEM);
 
-        edata = st->codec->extradata;
+        edata = st->codecpar->extradata;
         AV_WL16(&edata[0],  1);             // always 1
         AV_WL32(&edata[2],  samplerate);    // samples rate
         AV_WL16(&edata[6],  jsflag);        // coding mode
@@ -380,7 +380,7 @@ static int oma_read_header(AVFormatContext *s)
         AV_WL16(&edata[10], 1);             // always 1
         // AV_WL16(&edata[12], 0);          // always 0
 
-        avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+        avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
         break;
     case OMA_CODECID_ATRAC3P:
         channel_id = (codec_params >> 10) & 7;
@@ -389,16 +389,16 @@ static int oma_read_header(AVFormatContext *s)
                    "Invalid ATRAC-X channel id: %"PRIu32"\n", channel_id);
             return AVERROR_INVALIDDATA;
         }
-        st->codec->channel_layout = ff_oma_chid_to_native_layout[channel_id - 1];
-        st->codec->channels       = ff_oma_chid_to_num_channels[channel_id - 1];
+        st->codecpar->channel_layout = ff_oma_chid_to_native_layout[channel_id - 1];
+        st->codecpar->channels       = ff_oma_chid_to_num_channels[channel_id - 1];
         framesize = ((codec_params & 0x3FF) * 8) + 8;
         samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100;
         if (!samplerate) {
             av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n");
             return AVERROR_INVALIDDATA;
         }
-        st->codec->sample_rate = samplerate;
-        st->codec->bit_rate    = samplerate * framesize * 8 / 2048;
+        st->codecpar->sample_rate = samplerate;
+        st->codecpar->bit_rate    = samplerate * framesize * 8 / 2048;
         avpriv_set_pts_info(st, 64, 1, samplerate);
         break;
     case OMA_CODECID_MP3:
@@ -407,22 +407,22 @@ static int oma_read_header(AVFormatContext *s)
         break;
     case OMA_CODECID_LPCM:
         /* PCM 44.1 kHz 16 bit stereo big-endian */
-        st->codec->channels = 2;
-        st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
-        st->codec->sample_rate = 44100;
+        st->codecpar->channels = 2;
+        st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+        st->codecpar->sample_rate = 44100;
         framesize = 1024;
         /* bit rate = sample rate x PCM block align (= 4) x 8 */
-        st->codec->bit_rate = st->codec->sample_rate * 32;
-        st->codec->bits_per_coded_sample =
-            av_get_bits_per_sample(st->codec->codec_id);
-        avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+        st->codecpar->bit_rate = st->codecpar->sample_rate * 32;
+        st->codecpar->bits_per_coded_sample =
+            av_get_bits_per_sample(st->codecpar->codec_id);
+        avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
         break;
     default:
         av_log(s, AV_LOG_ERROR, "Unsupported codec %d!\n", buf[32]);
         return AVERROR(ENOSYS);
     }
 
-    st->codec->block_align = framesize;
+    st->codecpar->block_align = framesize;
 
     return 0;
 }
@@ -432,8 +432,8 @@ static int oma_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     OMAContext *oc  = s->priv_data;
     AVStream *st    = s->streams[0];
-    int packet_size = st->codec->block_align;
-    int byte_rate   = st->codec->bit_rate >> 3;
+    int packet_size = st->codecpar->block_align;
+    int byte_rate   = st->codecpar->bit_rate >> 3;
     int64_t pos     = avio_tell(s->pb);
     int ret         = av_get_packet(s->pb, pkt, packet_size);
 
diff --git a/libavformat/omaenc.c b/libavformat/omaenc.c
index fe0669f..d89cc37 100644
--- a/libavformat/omaenc.c
+++ b/libavformat/omaenc.c
@@ -30,21 +30,21 @@
 static av_cold int oma_write_header(AVFormatContext *s)
 {
     int i;
-    AVCodecContext *format;
+    AVCodecParameters *par;
     int srate_index;
     int isjointstereo;
 
-    format = s->streams[0]->codec;
+    par = s->streams[0]->codecpar;
     /* check for support of the format first */
 
     for (srate_index = 0; ; srate_index++) {
         if (ff_oma_srate_tab[srate_index] == 0) {
             av_log(s, AV_LOG_ERROR, "Sample rate %d not supported in OpenMG audio\n",
-                   format->sample_rate);
+                   par->sample_rate);
             return AVERROR(EINVAL);
         }
 
-        if (ff_oma_srate_tab[srate_index] * 100 == format->sample_rate)
+        if (ff_oma_srate_tab[srate_index] * 100 == par->sample_rate)
             break;
     }
 
@@ -58,16 +58,16 @@ static av_cold int oma_write_header(AVFormatContext *s)
     for (i = 0; i < 6; i++)
         avio_wl32(s->pb, 0);        /* Padding + DRM id */
 
-    switch(format->codec_tag) {
+    switch (par->codec_tag) {
     case OMA_CODECID_ATRAC3:
-        if (format->channels != 2) {
+        if (par->channels != 2) {
             av_log(s, AV_LOG_ERROR, "ATRAC3 in OMA is only supported with 2 channels\n");
             return AVERROR(EINVAL);
         }
-        if (format->extradata_size == 14) /* WAV format extradata */
-            isjointstereo = format->extradata[6] != 0;
-        else if(format->extradata_size == 10) /* RM format extradata */
-            isjointstereo = format->extradata[8] == 0x12;
+        if (par->extradata_size == 14) /* WAV format extradata */
+            isjointstereo = par->extradata[6] != 0;
+        else if(par->extradata_size == 10) /* RM format extradata */
+            isjointstereo = par->extradata[8] == 0x12;
         else {
             av_log(s, AV_LOG_ERROR, "ATRAC3: Unsupported extradata size\n");
             return AVERROR(EINVAL);
@@ -75,17 +75,17 @@ static av_cold int oma_write_header(AVFormatContext *s)
         avio_wb32(s->pb, (OMA_CODECID_ATRAC3 << 24) |
                          (isjointstereo << 17) |
                          (srate_index << 13) |
-                         (format->block_align/8));
+                         (par->block_align/8));
         break;
     case OMA_CODECID_ATRAC3P:
         avio_wb32(s->pb, (OMA_CODECID_ATRAC3P << 24) |
                          (srate_index << 13) |
-                         (format->channels << 10) |
-                         (format->block_align/8 - 1));
+                         (par->channels << 10) |
+                         (par->block_align/8 - 1));
         break;
     default:
         av_log(s, AV_LOG_ERROR, "unsupported codec tag %d for write\n",
-               format->codec_tag);
+               par->codec_tag);
         return AVERROR(EINVAL);
     }
     for (i = 0; i < (EA3_HEADER_SIZE - 36)/4; i++)
diff --git a/libavformat/options.c b/libavformat/options.c
index 8fe0017..04d9c45 100644
--- a/libavformat/options.c
+++ b/libavformat/options.c
@@ -109,7 +109,7 @@ FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-    return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist);
+    return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist, s->protocol_blacklist);
 }
 
 static void io_close_default(AVFormatContext *s, AVIOContext *pb)
diff --git a/libavformat/options_table.h b/libavformat/options_table.h
index 8926fe5..3b74d1b 100644
--- a/libavformat/options_table.h
+++ b/libavformat/options_table.h
@@ -78,7 +78,7 @@ static const AVOption avformat_options[] = {
 {"careful",    "consider things that violate the spec, are fast to check and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, D, "err_detect"},
 {"compliant",  "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, D, "err_detect"},
 {"aggressive", "consider things that a sane encoder shouldn't do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, D, "err_detect"},
-{"use_wallclock_as_timestamps", "use wallclock as timestamps", OFFSET(use_wallclock_as_timestamps), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, D},
+{"use_wallclock_as_timestamps", "use wallclock as timestamps", OFFSET(use_wallclock_as_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D},
 {"skip_initial_bytes", "set number of bytes to skip before reading header and frames", OFFSET(skip_initial_bytes), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX-1, D},
 {"correct_ts_overflow", "correct single timestamp overflows", OFFSET(correct_ts_overflow), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, D},
 {"flush_packets", "enable flushing of the I/O context after each packet", OFFSET(flush_packets), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, E},
@@ -87,6 +87,7 @@ static const AVOption avformat_options[] = {
 {"max_interleave_delta", "maximum buffering duration for interleaving", OFFSET(max_interleave_delta), AV_OPT_TYPE_INT64, { .i64 = 10000000 }, 0, INT64_MAX, E },
 {"f_strict", "how strictly to follow the standards (deprecated; use strict, save via avconv)", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "strict"},
 {"strict", "how strictly to follow the standards", OFFSET(strict_std_compliance), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "strict"},
+{"very", "strictly conform to a older more strict version of the spec or reference software", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_VERY_STRICT }, INT_MIN, INT_MAX, D|E, "strict"},
 {"strict", "strictly conform to all the things in the spec no matter what the consequences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_STRICT }, INT_MIN, INT_MAX, D|E, "strict"},
 {"normal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_NORMAL }, INT_MIN, INT_MAX, D|E, "strict"},
 {"unofficial", "allow unofficial extensions", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_UNOFFICIAL }, INT_MIN, INT_MAX, D|E, "strict"},
@@ -101,6 +102,7 @@ static const AVOption avformat_options[] = {
 {"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
 {"format_whitelist", "List of demuxers that are allowed to be used", OFFSET(format_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
 {"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
+{"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
 {NULL},
 };
 
diff --git a/libavformat/os_support.h b/libavformat/os_support.h
index a332911..caf1a2f 100644
--- a/libavformat/os_support.h
+++ b/libavformat/os_support.h
@@ -182,6 +182,29 @@ DEF_FS_FUNCTION(unlink, _wunlink, _unlink)
 DEF_FS_FUNCTION(mkdir,  _wmkdir,  _mkdir)
 DEF_FS_FUNCTION(rmdir,  _wrmdir , _rmdir)
 
+#define DEF_FS_FUNCTION2(name, wfunc, afunc, partype)     \
+static inline int win32_##name(const char *filename_utf8, partype par) \
+{                                                         \
+    wchar_t *filename_w;                                  \
+    int ret;                                              \
+                                                          \
+    if (utf8towchar(filename_utf8, &filename_w))          \
+        return -1;                                        \
+    if (!filename_w)                                      \
+        goto fallback;                                    \
+                                                          \
+    ret = wfunc(filename_w, par);                         \
+    av_free(filename_w);                                  \
+    return ret;                                           \
+                                                          \
+fallback:                                                 \
+    /* filename may be be in CP_ACP */                    \
+    return afunc(filename_utf8, par);                     \
+}
+
+DEF_FS_FUNCTION2(access, _waccess, _access, int)
+DEF_FS_FUNCTION2(stat, _wstati64, _stati64, struct stat*)
+
 static inline int win32_rename(const char *src_utf8, const char *dest_utf8)
 {
     wchar_t *src_w, *dest_w;
@@ -231,6 +254,7 @@ fallback:
 #define rename      win32_rename
 #define rmdir       win32_rmdir
 #define unlink      win32_unlink
+#define access      win32_access
 
 #endif
 
diff --git a/libavformat/paf.c b/libavformat/paf.c
index 4fc5006..fa30cdd 100644
--- a/libavformat/paf.c
+++ b/libavformat/paf.c
@@ -104,13 +104,13 @@ static int read_header(AVFormatContext *s)
     p->nb_frames    = avio_rl32(pb);
     avio_skip(pb, 4);
 
-    vst->codec->width  = avio_rl32(pb);
-    vst->codec->height = avio_rl32(pb);
+    vst->codecpar->width  = avio_rl32(pb);
+    vst->codecpar->height = avio_rl32(pb);
     avio_skip(pb, 4);
 
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_tag  = 0;
-    vst->codec->codec_id   = AV_CODEC_ID_PAF_VIDEO;
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_tag  = 0;
+    vst->codecpar->codec_id   = AV_CODEC_ID_PAF_VIDEO;
     avpriv_set_pts_info(vst, 64, 1, 10);
 
     ast = avformat_new_stream(s, 0);
@@ -118,12 +118,12 @@ static int read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     ast->start_time            = 0;
-    ast->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
-    ast->codec->codec_tag      = 0;
-    ast->codec->codec_id       = AV_CODEC_ID_PAF_AUDIO;
-    ast->codec->channels       = 2;
-    ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
-    ast->codec->sample_rate    = 22050;
+    ast->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    ast->codecpar->codec_tag      = 0;
+    ast->codecpar->codec_id       = AV_CODEC_ID_PAF_AUDIO;
+    ast->codecpar->channels       = 2;
+    ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+    ast->codecpar->sample_rate    = 22050;
     avpriv_set_pts_info(ast, 64, 1, 22050);
 
     p->buffer_size    = avio_rl32(pb);
diff --git a/libavformat/pcm.c b/libavformat/pcm.c
index f62075f..806f91b 100644
--- a/libavformat/pcm.c
+++ b/libavformat/pcm.c
@@ -30,7 +30,7 @@ int ff_pcm_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     int ret, size;
 
-    size= RAW_SAMPLES*s->streams[0]->codec->block_align;
+    size= RAW_SAMPLES*s->streams[0]->codecpar->block_align;
     if (size <= 0)
         return AVERROR(EINVAL);
 
@@ -51,10 +51,10 @@ int ff_pcm_read_seek(AVFormatContext *s,
 
     st = s->streams[0];
 
-    block_align = st->codec->block_align ? st->codec->block_align :
-        (av_get_bits_per_sample(st->codec->codec_id) * st->codec->channels) >> 3;
-    byte_rate = st->codec->bit_rate ? st->codec->bit_rate >> 3 :
-        block_align * st->codec->sample_rate;
+    block_align = st->codecpar->block_align ? st->codecpar->block_align :
+        (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3;
+    byte_rate = st->codecpar->bit_rate ? st->codecpar->bit_rate >> 3 :
+        block_align * st->codecpar->sample_rate;
 
     if (block_align <= 0 || byte_rate <= 0)
         return -1;
diff --git a/libavformat/pcmdec.c b/libavformat/pcmdec.c
index 2584c33..df94345 100644
--- a/libavformat/pcmdec.c
+++ b/libavformat/pcmdec.c
@@ -42,20 +42,20 @@ static int pcm_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = s->iformat->raw_codec_id;
-    st->codec->sample_rate = s1->sample_rate;
-    st->codec->channels    = s1->channels;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = s->iformat->raw_codec_id;
+    st->codecpar->sample_rate = s1->sample_rate;
+    st->codecpar->channels    = s1->channels;
 
-    st->codec->bits_per_coded_sample =
-        av_get_bits_per_sample(st->codec->codec_id);
+    st->codecpar->bits_per_coded_sample =
+        av_get_bits_per_sample(st->codecpar->codec_id);
 
-    av_assert0(st->codec->bits_per_coded_sample > 0);
+    av_assert0(st->codecpar->bits_per_coded_sample > 0);
 
-    st->codec->block_align =
-        st->codec->bits_per_coded_sample * st->codec->channels / 8;
+    st->codecpar->block_align =
+        st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8;
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     return 0;
 }
 
diff --git a/libavformat/pjsdec.c b/libavformat/pjsdec.c
index a88d533..bb587b5 100644
--- a/libavformat/pjsdec.c
+++ b/libavformat/pjsdec.c
@@ -70,8 +70,8 @@ static int pjs_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 10);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_PJS;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_PJS;
 
     while (!avio_feof(s->pb)) {
         char line[4096];
diff --git a/libavformat/pmpdec.c b/libavformat/pmpdec.c
index ec966b3..0e80a09 100644
--- a/libavformat/pmpdec.c
+++ b/libavformat/pmpdec.c
@@ -54,22 +54,22 @@ static int pmp_header(AVFormatContext *s)
     AVStream *vst = avformat_new_stream(s, NULL);
     if (!vst)
         return AVERROR(ENOMEM);
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     avio_skip(pb, 8);
     switch (avio_rl32(pb)) {
     case 0:
-        vst->codec->codec_id = AV_CODEC_ID_MPEG4;
+        vst->codecpar->codec_id = AV_CODEC_ID_MPEG4;
         break;
     case 1:
-        vst->codec->codec_id = AV_CODEC_ID_H264;
+        vst->codecpar->codec_id = AV_CODEC_ID_H264;
         break;
     default:
         av_log(s, AV_LOG_ERROR, "Unsupported video format\n");
         break;
     }
-    index_cnt = avio_rl32(pb);
-    vst->codec->width  = avio_rl32(pb);
-    vst->codec->height = avio_rl32(pb);
+    index_cnt          = avio_rl32(pb);
+    vst->codecpar->width  = avio_rl32(pb);
+    vst->codecpar->height = avio_rl32(pb);
 
     tb_num = avio_rl32(pb);
     tb_den = avio_rl32(pb);
@@ -117,10 +117,10 @@ static int pmp_header(AVFormatContext *s)
         AVStream *ast = avformat_new_stream(s, NULL);
         if (!ast)
             return AVERROR(ENOMEM);
-        ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        ast->codec->codec_id = audio_codec_id;
-        ast->codec->channels = channels;
-        ast->codec->sample_rate = srate;
+        ast->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+        ast->codecpar->codec_id    = audio_codec_id;
+        ast->codecpar->channels    = channels;
+        ast->codecpar->sample_rate = srate;
         avpriv_set_pts_info(ast, 32, 1, srate);
     }
     return 0;
diff --git a/libavformat/protocols.c b/libavformat/protocols.c
new file mode 100644
index 0000000..124010c
--- /dev/null
+++ b/libavformat/protocols.c
@@ -0,0 +1,131 @@
+/*
+ * 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 "config.h"
+
+#include "libavutil/avstring.h"
+#include "libavutil/mem.h"
+
+#include "url.h"
+
+extern const URLProtocol ff_async_protocol;
+extern const URLProtocol ff_bluray_protocol;
+extern const URLProtocol ff_cache_protocol;
+extern const URLProtocol ff_concat_protocol;
+extern const URLProtocol ff_crypto_protocol;
+extern const URLProtocol ff_data_protocol;
+extern const URLProtocol ff_ffrtmpcrypt_protocol;
+extern const URLProtocol ff_ffrtmphttp_protocol;
+extern const URLProtocol ff_file_protocol;
+extern const URLProtocol ff_ftp_protocol;
+extern const URLProtocol ff_gopher_protocol;
+extern const URLProtocol ff_hls_protocol;
+extern const URLProtocol ff_http_protocol;
+extern const URLProtocol ff_httpproxy_protocol;
+extern const URLProtocol ff_https_protocol;
+extern const URLProtocol ff_icecast_protocol;
+extern const URLProtocol ff_mmsh_protocol;
+extern const URLProtocol ff_mmst_protocol;
+extern const URLProtocol ff_md5_protocol;
+extern const URLProtocol ff_pipe_protocol;
+extern const URLProtocol ff_rtmp_protocol;
+extern const URLProtocol ff_rtmpe_protocol;
+extern const URLProtocol ff_rtmps_protocol;
+extern const URLProtocol ff_rtmpt_protocol;
+extern const URLProtocol ff_rtmpte_protocol;
+extern const URLProtocol ff_rtmpts_protocol;
+extern const URLProtocol ff_rtp_protocol;
+extern const URLProtocol ff_sctp_protocol;
+extern const URLProtocol ff_srtp_protocol;
+extern const URLProtocol ff_subfile_protocol;
+extern const URLProtocol ff_tcp_protocol;
+extern const URLProtocol ff_tls_gnutls_protocol;
+extern const URLProtocol ff_tls_schannel_protocol;
+extern const URLProtocol ff_tls_securetransport_protocol;
+extern const URLProtocol ff_tls_openssl_protocol;
+extern const URLProtocol ff_udp_protocol;
+extern const URLProtocol ff_udplite_protocol;
+extern const URLProtocol ff_unix_protocol;
+extern const URLProtocol ff_librtmp_protocol;
+extern const URLProtocol ff_librtmpe_protocol;
+extern const URLProtocol ff_librtmps_protocol;
+extern const URLProtocol ff_librtmpt_protocol;
+extern const URLProtocol ff_librtmpte_protocol;
+extern const URLProtocol ff_libssh_protocol;
+extern const URLProtocol ff_libsmbclient_protocol;
+
+#include "libavformat/protocol_list.c"
+
+const AVClass *ff_urlcontext_child_class_next(const AVClass *prev)
+{
+    int i;
+
+    /* find the protocol that corresponds to prev */
+    for (i = 0; prev && url_protocols[i]; i++) {
+        if (url_protocols[i]->priv_data_class == prev) {
+            i++;
+            break;
+        }
+    }
+
+    /* find next protocol with priv options */
+    for (; url_protocols[i]; i++)
+        if (url_protocols[i]->priv_data_class)
+            return url_protocols[i]->priv_data_class;
+    return NULL;
+}
+
+
+const char *avio_enum_protocols(void **opaque, int output)
+{
+    const URLProtocol **p = *opaque;
+
+    p = p ? p + 1 : url_protocols;
+    *opaque = p;
+    if (!*p) {
+        *opaque = NULL;
+        return NULL;
+    }
+    if ((output && (*p)->url_write) || (!output && (*p)->url_read))
+        return (*p)->name;
+    return avio_enum_protocols(opaque, output);
+}
+
+const URLProtocol **ffurl_get_protocols(const char *whitelist,
+                                        const char *blacklist)
+{
+    const URLProtocol **ret;
+    int i, ret_idx = 0;
+
+    ret = av_mallocz_array(FF_ARRAY_ELEMS(url_protocols), sizeof(*ret));
+    if (!ret)
+        return NULL;
+
+    for (i = 0; url_protocols[i]; i++) {
+        const URLProtocol *up = url_protocols[i];
+
+        if (whitelist && *whitelist && !av_match_name(up->name, whitelist))
+            continue;
+        if (blacklist && *blacklist && av_match_name(up->name, blacklist))
+            continue;
+
+        ret[ret_idx++] = up;
+    }
+
+    return ret;
+}
diff --git a/libavformat/psxstr.c b/libavformat/psxstr.c
index b57981a..63598fe 100644
--- a/libavformat/psxstr.c
+++ b/libavformat/psxstr.c
@@ -1,6 +1,6 @@
 /*
  * Sony Playstation (PSX) STR File Demuxer
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -104,13 +104,7 @@ static int str_probe(AVProbeData *p)
                      && sector_count*VIDEO_DATA_CHUNK_SIZE >=frame_size)){
                     return 0;
                 }
-
-                /*st->codec->width      = AV_RL16(&sector[0x28]);
-                st->codec->height     = AV_RL16(&sector[0x2A]);*/
-
-//                 if (current_sector == sector_count-1) {
-                    vid++;
-//                 }
+                vid++;
 
             }
             break;
@@ -205,11 +199,11 @@ static int str_read_packet(AVFormatContext *s,
 
                     str->channels[channel].video_stream_index = st->index;
 
-                    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-                    st->codec->codec_id   = AV_CODEC_ID_MDEC;
-                    st->codec->codec_tag  = 0;  /* no fourcc */
-                    st->codec->width      = AV_RL16(&sector[0x28]);
-                    st->codec->height     = AV_RL16(&sector[0x2A]);
+                    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+                    st->codecpar->codec_id   = AV_CODEC_ID_MDEC;
+                    st->codecpar->codec_tag  = 0;  /* no fourcc */
+                    st->codecpar->width      = AV_RL16(&sector[0x28]);
+                    st->codecpar->height     = AV_RL16(&sector[0x2A]);
                 }
 
                 /* if this is the first sector of the frame, allocate a pkt */
@@ -254,22 +248,22 @@ static int str_read_packet(AVFormatContext *s,
 
                 str->channels[channel].audio_stream_index = st->index;
 
-                st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-                st->codec->codec_id    = AV_CODEC_ID_ADPCM_XA;
-                st->codec->codec_tag   = 0;  /* no fourcc */
+                st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+                st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_XA;
+                st->codecpar->codec_tag   = 0;  /* no fourcc */
                 if (fmt & 1) {
-                    st->codec->channels       = 2;
-                    st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+                    st->codecpar->channels       = 2;
+                    st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
                 } else {
-                    st->codec->channels       = 1;
-                    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+                    st->codecpar->channels       = 1;
+                    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
                 }
-                st->codec->sample_rate = (fmt&4)?18900:37800;
-            //    st->codec->bit_rate = 0; //FIXME;
-                st->codec->block_align = 128;
+                st->codecpar->sample_rate = (fmt&4)?18900:37800;
+            //    st->codecpar->bit_rate = 0; //FIXME;
+                st->codecpar->block_align = 128;
 
-                avpriv_set_pts_info(st, 64, 18 * 224 / st->codec->channels,
-                                    st->codec->sample_rate);
+                avpriv_set_pts_info(st, 64, 18 * 224 / st->codecpar->channels,
+                                    st->codecpar->sample_rate);
                 st->start_time = 0;
             }
             pkt = ret_pkt;
diff --git a/libavformat/pva.c b/libavformat/pva.c
index 900ad61..16381db 100644
--- a/libavformat/pva.c
+++ b/libavformat/pva.c
@@ -59,16 +59,16 @@ static int pva_read_header(AVFormatContext *s) {
 
     if (!(st = avformat_new_stream(s, NULL)))
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_MPEG2VIDEO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_MPEG2VIDEO;
     st->need_parsing      = AVSTREAM_PARSE_FULL;
     avpriv_set_pts_info(st, 32, 1, 90000);
     av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME);
 
     if (!(st = avformat_new_stream(s, NULL)))
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id   = AV_CODEC_ID_MP2;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id   = AV_CODEC_ID_MP2;
     st->need_parsing      = AVSTREAM_PARSE_FULL;
     avpriv_set_pts_info(st, 33, 1, 90000);
     av_add_index_entry(st, 0, 0, 0, 0, AVINDEX_KEYFRAME);
diff --git a/libavformat/pvfdec.c b/libavformat/pvfdec.c
index c678046..b9f6d4f 100644
--- a/libavformat/pvfdec.c
+++ b/libavformat/pvfdec.c
@@ -51,14 +51,14 @@ static int pvf_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->channels    = channels;
-    st->codec->sample_rate = sample_rate;
-    st->codec->codec_id    = ff_get_pcm_codec_id(bps, 0, 1, 0xFFFF);
-    st->codec->bits_per_coded_sample = bps;
-    st->codec->block_align = bps * st->codec->channels / 8;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channels    = channels;
+    st->codecpar->sample_rate = sample_rate;
+    st->codecpar->codec_id    = ff_get_pcm_codec_id(bps, 0, 1, 0xFFFF);
+    st->codecpar->bits_per_coded_sample = bps;
+    st->codecpar->block_align = bps * st->codecpar->channels / 8;
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
diff --git a/libavformat/qcp.c b/libavformat/qcp.c
index ad4a8ae..b842e26 100644
--- a/libavformat/qcp.c
+++ b/libavformat/qcp.c
@@ -101,29 +101,29 @@ static int qcp_read_header(AVFormatContext *s)
     avio_rb32(pb);                    // "RIFF"
     avio_skip(pb, 4 + 8 + 4 + 1 + 1);    // filesize + "QLCMfmt " + chunk-size + major-version + minor-version
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->channels   = 1;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channels   = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
     avio_read(pb, buf, 16);
     if (is_qcelp_13k_guid(buf)) {
-        st->codec->codec_id = AV_CODEC_ID_QCELP;
+        st->codecpar->codec_id = AV_CODEC_ID_QCELP;
     } else if (!memcmp(buf, guid_evrc, 16)) {
-        st->codec->codec_id = AV_CODEC_ID_EVRC;
+        st->codecpar->codec_id = AV_CODEC_ID_EVRC;
     } else if (!memcmp(buf, guid_smv, 16)) {
-        st->codec->codec_id = AV_CODEC_ID_SMV;
+        st->codecpar->codec_id = AV_CODEC_ID_SMV;
     } else if (!memcmp(buf, guid_4gv, 16)) {
-        st->codec->codec_id = AV_CODEC_ID_4GV;
+        st->codecpar->codec_id = AV_CODEC_ID_4GV;
     } else {
         av_log(s, AV_LOG_ERROR, "Unknown codec GUID "FF_PRI_GUID".\n",
                FF_ARG_GUID(buf));
         return AVERROR_INVALIDDATA;
     }
     avio_skip(pb, 2 + 80); // codec-version + codec-name
-    st->codec->bit_rate = avio_rl16(pb);
+    st->codecpar->bit_rate = avio_rl16(pb);
 
     s->packet_size = avio_rl16(pb);
     avio_skip(pb, 2); // block-size
-    st->codec->sample_rate = avio_rl16(pb);
+    st->codecpar->sample_rate = avio_rl16(pb);
     avio_skip(pb, 2); // sample-size
 
     memset(c->rates_per_mode, -1, sizeof(c->rates_per_mode));
diff --git a/libavformat/r3d.c b/libavformat/r3d.c
index 94c3015..b609488 100644
--- a/libavformat/r3d.c
+++ b/libavformat/r3d.c
@@ -62,8 +62,8 @@ static int r3d_read_red1(AVFormatContext *s)
 
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_JPEG2000;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_JPEG2000;
 
     tmp  = avio_r8(s->pb); // major version
     tmp2 = avio_r8(s->pb); // minor version
@@ -80,8 +80,8 @@ static int r3d_read_red1(AVFormatContext *s)
 
     avio_skip(s->pb, 32); // unknown
 
-    st->codec->width  = avio_rb32(s->pb);
-    st->codec->height = avio_rb32(s->pb);
+    st->codecpar->width  = avio_rb32(s->pb);
+    st->codecpar->height = avio_rb32(s->pb);
 
     tmp = avio_rb16(s->pb); // unknown
     av_log(s, AV_LOG_TRACE, "unknown2 %d\n", tmp);
@@ -103,7 +103,7 @@ static int r3d_read_red1(AVFormatContext *s)
     av_dict_set(&st->metadata, "filename", filename, 0);
 
     av_log(s, AV_LOG_TRACE, "filename %s\n", filename);
-    av_log(s, AV_LOG_TRACE, "resolution %dx%d\n", st->codec->width, st->codec->height);
+    av_log(s, AV_LOG_TRACE, "resolution %dx%d\n", st->codecpar->width, st->codecpar->height);
     av_log(s, AV_LOG_TRACE, "timescale %d\n", st->time_base.den);
     av_log(s, AV_LOG_TRACE, "frame rate %d/%d\n",
             framerate.num, framerate.den);
@@ -284,9 +284,9 @@ static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom)
         st = avformat_new_stream(s, NULL);
         if (!st)
             return AVERROR(ENOMEM);
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id = AV_CODEC_ID_PCM_S32BE;
-        st->codec->channels = r3d->audio_channels;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
+        st->codecpar->channels = r3d->audio_channels;
         avpriv_set_pts_info(st, 32, 1, s->streams[0]->time_base.den);
     } else {
         st = s->streams[1];
@@ -294,8 +294,8 @@ static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom)
 
     dts = avio_rb32(s->pb);
 
-    st->codec->sample_rate = avio_rb32(s->pb);
-    if (st->codec->sample_rate <= 0) {
+    st->codecpar->sample_rate = avio_rb32(s->pb);
+    if (st->codecpar->sample_rate <= 0) {
         av_log(s, AV_LOG_ERROR, "Bad sample rate\n");
         return AVERROR_INVALIDDATA;
     }
@@ -326,10 +326,10 @@ static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom)
 
     pkt->stream_index = 1;
     pkt->dts = dts;
-    if (st->codec->sample_rate)
-        pkt->duration = av_rescale(samples, st->time_base.den, st->codec->sample_rate);
+    if (st->codecpar->sample_rate)
+        pkt->duration = av_rescale(samples, st->time_base.den, st->codecpar->sample_rate);
     av_log(s, AV_LOG_TRACE, "pkt dts %"PRId64" duration %"PRId64" samples %d sample rate %d\n",
-            pkt->dts, pkt->duration, samples, st->codec->sample_rate);
+            pkt->dts, pkt->duration, samples, st->codecpar->sample_rate);
 
     return 0;
 }
diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c
index 35ad118..876a6e6 100644
--- a/libavformat/rawdec.c
+++ b/libavformat/rawdec.c
@@ -57,8 +57,8 @@ int ff_raw_audio_read_header(AVFormatContext *s)
     AVStream *st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = s->iformat->raw_codec_id;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = s->iformat->raw_codec_id;
     st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
     st->start_time = 0;
     /* the parameters will be extracted from the compressed bitstream */
@@ -80,12 +80,11 @@ int ff_raw_video_read_header(AVFormatContext *s)
         goto fail;
     }
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = s->iformat->raw_codec_id;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = s->iformat->raw_codec_id;
     st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
 
-    st->codec->framerate = s1->framerate;
-    st->codec->time_base = av_inv_q(s1->framerate);
+    st->internal->avctx->framerate = s1->framerate;
     avpriv_set_pts_info(st, 64, 1, 1200000);
 
 fail:
@@ -97,8 +96,8 @@ int ff_raw_data_read_header(AVFormatContext *s)
     AVStream *st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_DATA;
-    st->codec->codec_id = s->iformat->raw_codec_id;
+    st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
+    st->codecpar->codec_id = s->iformat->raw_codec_id;
     st->start_time = 0;
     return 0;
 }
@@ -108,7 +107,7 @@ int ff_raw_data_read_header(AVFormatContext *s)
 #define OFFSET(x) offsetof(FFRawVideoDemuxerContext, x)
 #define DEC AV_OPT_FLAG_DECODING_PARAM
 const AVOption ff_rawvideo_options[] = {
-    { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, DEC},
+    { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC},
     { NULL },
 };
 
diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c
index 358ee4e..4b8b41c 100644
--- a/libavformat/rawenc.c
+++ b/libavformat/rawenc.c
@@ -60,11 +60,11 @@ AVOutputFormat ff_ac3_muxer = {
 static int adx_write_trailer(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
-    AVCodecContext *avctx = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
     if (pb->seekable) {
         int64_t file_size = avio_tell(pb);
-        uint64_t sample_count = (file_size - 36) / avctx->channels / 18 * 32;
+        uint64_t sample_count = (file_size - 36) / par->channels / 18 * 32;
         if (sample_count <= UINT32_MAX) {
             avio_seek(pb, 12, SEEK_SET);
             avio_wb32(pb, sample_count);
@@ -193,6 +193,20 @@ AVOutputFormat ff_g723_1_muxer = {
 };
 #endif
 
+#if CONFIG_GSM_MUXER
+AVOutputFormat ff_gsm_muxer = {
+    .name              = "gsm",
+    .long_name         = NULL_IF_CONFIG_SMALL("raw GSM"),
+    .mime_type         = "audio/x-gsm",
+    .extensions        = "gsm",
+    .audio_codec       = AV_CODEC_ID_GSM,
+    .video_codec       = AV_CODEC_ID_NONE,
+    .write_header      = force_one_stream,
+    .write_packet      = ff_raw_write_packet,
+    .flags             = AVFMT_NOTIMESTAMPS,
+};
+#endif
+
 #if CONFIG_H261_MUXER
 AVOutputFormat ff_h261_muxer = {
     .name              = "h261",
diff --git a/libavformat/rawutils.c b/libavformat/rawutils.c
new file mode 100644
index 0000000..996412a
--- /dev/null
+++ b/libavformat/rawutils.c
@@ -0,0 +1,67 @@
+/*
+ * Raw video utils
+ * Copyright (c) 2016 Michael Niedermayer
+ *
+ * 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 "avformat.h"
+#include "internal.h"
+
+int ff_reshuffle_raw_rgb(AVFormatContext *s, AVPacket **ppkt, AVCodecParameters *par, int expected_stride)
+{
+    int ret;
+    AVPacket *pkt = *ppkt;
+    int64_t bpc = par->bits_per_coded_sample != 15 ? par->bits_per_coded_sample : 16;
+    int min_stride = (par->width * bpc + 7) >> 3;
+    int with_pal_size = min_stride * par->height + 1024;
+    int contains_pal = bpc == 8 && pkt->size == with_pal_size;
+    int size = contains_pal ? min_stride * par->height : pkt->size;
+    int stride = size / par->height;
+    int padding = expected_stride - FFMIN(expected_stride, stride);
+    int y;
+    AVPacket *new_pkt;
+
+    if (pkt->size == expected_stride * par->height)
+        return 0;
+    if (size != stride * par->height)
+        return 0;
+
+    new_pkt = av_packet_alloc();
+    if (!new_pkt)
+        return AVERROR(ENOMEM);
+
+    ret = av_new_packet(new_pkt, expected_stride * par->height);
+    if (ret < 0)
+        goto fail;
+
+    ret = av_packet_copy_props(new_pkt, pkt);
+    if (ret < 0)
+        goto fail;
+
+    for (y = 0; y<par->height; y++) {
+        memcpy(new_pkt->data + y*expected_stride, pkt->data + y*stride, FFMIN(expected_stride, stride));
+        memset(new_pkt->data + y*expected_stride + expected_stride - padding, 0, padding);
+    }
+
+    *ppkt = new_pkt;
+    return 1 + contains_pal;
+fail:
+    av_packet_free(&new_pkt);
+
+    return ret;
+}
diff --git a/libavformat/rawvideodec.c b/libavformat/rawvideodec.c
index 91bdba0..8bde22c 100644
--- a/libavformat/rawvideodec.c
+++ b/libavformat/rawvideodec.c
@@ -45,9 +45,9 @@ static int rawvideo_read_header(AVFormatContext *ctx)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
 
-    st->codec->codec_id = ctx->iformat->raw_codec_id;
+    st->codecpar->codec_id = ctx->iformat->raw_codec_id;
 
     if ((pix_fmt = av_get_pix_fmt(s->pixel_format)) == AV_PIX_FMT_NONE) {
         av_log(ctx, AV_LOG_ERROR, "No such pixel format: %s.\n",
@@ -57,14 +57,14 @@ static int rawvideo_read_header(AVFormatContext *ctx)
 
     avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num);
 
-    st->codec->width  = s->width;
-    st->codec->height = s->height;
-    st->codec->pix_fmt = pix_fmt;
-    packet_size = av_image_get_buffer_size(st->codec->pix_fmt, s->width, s->height, 1);
+    st->codecpar->width  = s->width;
+    st->codecpar->height = s->height;
+    st->codecpar->format = pix_fmt;
+    packet_size = av_image_get_buffer_size(st->codecpar->format, s->width, s->height, 1);
     if (packet_size < 0)
         return packet_size;
     ctx->packet_size = packet_size;
-    st->codec->bit_rate = av_rescale_q(ctx->packet_size,
+    st->codecpar->bit_rate = av_rescale_q(ctx->packet_size,
                                        (AVRational){8,1}, st->time_base);
 
     return 0;
@@ -89,7 +89,7 @@ static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt)
 static const AVOption rawvideo_options[] = {
     { "video_size", "set frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
     { "pixel_format", "set pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = "yuv420p"}, 0, 0, DEC },
-    { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, DEC },
+    { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC },
     { NULL },
 };
 
diff --git a/libavformat/rdt.c b/libavformat/rdt.c
index c3ac198..8670ead 100644
--- a/libavformat/rdt.c
+++ b/libavformat/rdt.c
@@ -44,7 +44,7 @@ struct RDTDemuxContext {
      * in the AVFormatContext, and this variable points to the offset in
      * that array such that the first is the first stream of this set. */
     AVStream **streams;
-    int n_streams; /**< streams with identifical content in this set */
+    int n_streams; /**< streams with identical content in this set */
     void *dynamic_protocol_context;
     DynamicPayloadPacketHandlerProc parse_packet;
     uint32_t prev_timestamp;
@@ -309,7 +309,7 @@ rdt_parse_packet (AVFormatContext *ctx, PayloadContext *rdt, AVStream *st,
         if (res < 0)
             return res;
         if (res > 0) {
-            if (st->codec->codec_id == AV_CODEC_ID_AAC) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
                 memcpy (rdt->buffer, buf + pos, len - pos);
                 rdt->rmctx->pb = avio_alloc_context (rdt->buffer, len - pos, 0,
                                                     NULL, NULL, NULL, NULL);
@@ -322,7 +322,7 @@ get_cache:
             ff_rm_retrieve_cache (rdt->rmctx, rdt->rmctx->pb,
                                   st, rdt->rmst[st->index], pkt);
         if (rdt->audio_pkt_cnt == 0 &&
-            st->codec->codec_id == AV_CODEC_ID_AAC)
+            st->codecpar->codec_id == AV_CODEC_ID_AAC)
             av_freep(&rdt->rmctx->pb);
     }
     pkt->stream_index = st->index;
@@ -448,7 +448,7 @@ real_parse_asm_rule(AVStream *st, const char *p, const char *end)
 {
     do {
         /* can be either averagebandwidth= or AverageBandwidth= */
-        if (sscanf(p, " %*1[Aa]verage%*1[Bb]andwidth=%"SCNd64, &st->codec->bit_rate) == 1)
+        if (sscanf(p, " %*1[Aa]verage%*1[Bb]andwidth=%"SCNd64, &st->codecpar->bit_rate) == 1)
             break;
         if (!(p = strchr(p, ',')) || p > end)
             p = end;
@@ -464,7 +464,7 @@ add_dstream(AVFormatContext *s, AVStream *orig_st)
     if (!(st = avformat_new_stream(s, NULL)))
         return NULL;
     st->id = orig_st->id;
-    st->codec->codec_type = orig_st->codec->codec_type;
+    st->codecpar->codec_type = orig_st->codecpar->codec_type;
     st->first_dts         = orig_st->first_dts;
 
     return st;
@@ -531,7 +531,7 @@ static av_cold int rdt_init(AVFormatContext *s, int st_index, PayloadContext *rd
     if (!rdt->rmctx)
         return AVERROR(ENOMEM);
 
-    if ((ret = ff_copy_whitelists(rdt->rmctx, s)) < 0)
+    if ((ret = ff_copy_whiteblacklists(rdt->rmctx, s)) < 0)
         return ret;
 
     return avformat_open_input(&rdt->rmctx, "", &ff_rdt_demuxer, NULL);
diff --git a/libavformat/realtextdec.c b/libavformat/realtextdec.c
index f13321c..618d4f7 100644
--- a/libavformat/realtextdec.c
+++ b/libavformat/realtextdec.c
@@ -70,8 +70,8 @@ static int realtext_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 100);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_REALTEXT;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_REALTEXT;
 
     av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
 
@@ -89,12 +89,12 @@ static int realtext_read_header(AVFormatContext *s)
 
             if (p)
                 duration = read_ts(p);
-            st->codec->extradata = av_strdup(buf.str);
-            if (!st->codec->extradata) {
+            st->codecpar->extradata = av_strdup(buf.str);
+            if (!st->codecpar->extradata) {
                 res = AVERROR(ENOMEM);
                 goto end;
             }
-            st->codec->extradata_size = buf.len + 1;
+            st->codecpar->extradata_size = buf.len + 1;
         } else {
             /* if we just read a <time> tag, introduce a new event, otherwise merge
              * with the previous one */
diff --git a/libavformat/redspark.c b/libavformat/redspark.c
index 5cea6e9..c247046 100644
--- a/libavformat/redspark.c
+++ b/libavformat/redspark.c
@@ -26,6 +26,7 @@
 #include "internal.h"
 
 #define HEADER_SIZE 4096
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
 
 typedef struct RedSparkContext {
     int         samples_count;
@@ -38,11 +39,13 @@ static int redspark_probe(AVProbeData *p)
 
     /* Decrypt first 8 bytes of the header */
     data = AV_RB32(p->buf);
-    data = data ^ (key = data ^ 0x52656453);
+    key  = data ^ 0x52656453;
+    data ^= key;
     AV_WB32(header, data);
-    key = (key << 11) | (key >> 21);
+    key = rol(key, 11);
 
-    data = AV_RB32(p->buf + 4) ^ (((key << 3) | (key >> 29)) + key);
+    key += rol(key, 3);
+    data = AV_RB32(p->buf + 4) ^ key;
     AV_WB32(header + 4, data);
 
     if (AV_RB64(header) == AV_RB64("RedSpark"))
@@ -55,92 +58,81 @@ static int redspark_read_header(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
     RedSparkContext *redspark = s->priv_data;
-    AVCodecContext *codec;
+    AVCodecParameters *par;
     GetByteContext gbc;
     int i, coef_off, ret = 0;
     uint32_t key, data;
-    uint8_t *header, *pbc;
+    uint8_t header[HEADER_SIZE];
     AVStream *st;
 
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    codec = st->codec;
-
-    header = av_malloc(HEADER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (!header)
-        return AVERROR(ENOMEM);
-    pbc = header;
+    par = st->codecpar;
 
     /* Decrypt header */
     data = avio_rb32(pb);
-    data = data ^ (key = data ^ 0x52656453);
-    bytestream_put_be32(&pbc, data);
-    key = (key << 11) | (key >> 21);
+    key  = data ^ 0x52656453;
+    data ^= key;
+    AV_WB32(header, data);
+    key = rol(key, 11);
 
     for (i = 4; i < HEADER_SIZE; i += 4) {
-        data = avio_rb32(pb) ^ (key = ((key << 3) | (key >> 29)) + key);
-        bytestream_put_be32(&pbc, data);
+        key += rol(key, 3);
+        data = avio_rb32(pb) ^ key;
+        AV_WB32(header + i, data);
     }
 
-    codec->codec_id    = AV_CODEC_ID_ADPCM_THP;
-    codec->codec_type  = AVMEDIA_TYPE_AUDIO;
+    par->codec_id    = AV_CODEC_ID_ADPCM_THP;
+    par->codec_type  = AVMEDIA_TYPE_AUDIO;
 
     bytestream2_init(&gbc, header, HEADER_SIZE);
     bytestream2_seek(&gbc, 0x3c, SEEK_SET);
-    codec->sample_rate = bytestream2_get_be32u(&gbc);
-    if (codec->sample_rate <= 0 || codec->sample_rate > 96000) {
-        av_log(s, AV_LOG_ERROR, "Invalid sample rate: %d\n", codec->sample_rate);
-        ret = AVERROR_INVALIDDATA;
-        goto fail;
+    par->sample_rate = bytestream2_get_be32u(&gbc);
+    if (par->sample_rate <= 0 || par->sample_rate > 96000) {
+        av_log(s, AV_LOG_ERROR, "Invalid sample rate: %d\n", par->sample_rate);
+        return AVERROR_INVALIDDATA;
     }
 
     st->duration = bytestream2_get_be32u(&gbc) * 14;
     redspark->samples_count = 0;
     bytestream2_skipu(&gbc, 10);
-    codec->channels = bytestream2_get_byteu(&gbc);
-    if (!codec->channels) {
-        ret = AVERROR_INVALIDDATA;
-        goto fail;
+    par->channels = bytestream2_get_byteu(&gbc);
+    if (!par->channels) {
+        return AVERROR_INVALIDDATA;
     }
 
-    coef_off = 0x54 + codec->channels * 8;
+    coef_off = 0x54 + par->channels * 8;
     if (bytestream2_get_byteu(&gbc)) // Loop flag
         coef_off += 16;
 
-    if (coef_off + codec->channels * (32 + 14) > HEADER_SIZE) {
-        ret = AVERROR_INVALIDDATA;
-        goto fail;
+    if (coef_off + par->channels * (32 + 14) > HEADER_SIZE) {
+        return AVERROR_INVALIDDATA;
     }
 
-    if (ff_alloc_extradata(codec, 32 * codec->channels)) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
+    if (ff_alloc_extradata(par, 32 * par->channels)) {
+        return AVERROR_INVALIDDATA;
     }
 
     /* Get the ADPCM table */
     bytestream2_seek(&gbc, coef_off, SEEK_SET);
-    for (i = 0; i < codec->channels; i++) {
-        if (bytestream2_get_bufferu(&gbc, codec->extradata + i * 32, 32) != 32) {
-            ret = AVERROR_INVALIDDATA;
-            goto fail;
+    for (i = 0; i < par->channels; i++) {
+        if (bytestream2_get_bufferu(&gbc, par->extradata + i * 32, 32) != 32) {
+            return AVERROR_INVALIDDATA;
         }
         bytestream2_skipu(&gbc, 14);
     }
 
-    avpriv_set_pts_info(st, 64, 1, codec->sample_rate);
-
-fail:
-    av_free(header);
+    avpriv_set_pts_info(st, 64, 1, par->sample_rate);
 
     return ret;
 }
 
 static int redspark_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     RedSparkContext *redspark = s->priv_data;
-    uint32_t size = 8 * codec->channels;
+    uint32_t size = 8 * par->channels;
     int ret;
 
     if (avio_feof(s->pb) || redspark->samples_count == s->streams[0]->duration)
diff --git a/libavformat/riff.c b/libavformat/riff.c
index cf5a2ff..913b42d 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -113,6 +113,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
     { AV_CODEC_ID_MPEG4,        MKTAG('G', 'L', 'V', '4') },
     { AV_CODEC_ID_MPEG4,        MKTAG('G', 'M', 'P', '4') }, /* GeoVision camera */
     { AV_CODEC_ID_MPEG4,        MKTAG('M', 'N', 'M', '4') }, /* March Networks DVR */
+    { AV_CODEC_ID_MPEG4,        MKTAG('G', 'T', 'M', '4') }, /* Telefactor */
     { AV_CODEC_ID_MSMPEG4V3,    MKTAG('M', 'P', '4', '3') },
     { AV_CODEC_ID_MSMPEG4V3,    MKTAG('D', 'I', 'V', '3') },
     { AV_CODEC_ID_MSMPEG4V3,    MKTAG('M', 'P', 'G', '3') },
@@ -168,6 +169,9 @@ const AVCodecTag ff_codec_bmp_tags[] = {
     { AV_CODEC_ID_MPEG2VIDEO,   MKTAG('E', 'M', '2', 'V') },
     /* Matrox MPEG-2 intra-only */
     { AV_CODEC_ID_MPEG2VIDEO,   MKTAG('M', '7', '0', '1') },
+    { AV_CODEC_ID_MPEG2VIDEO,   MKTAG('M', '7', '0', '2') },
+    { AV_CODEC_ID_MPEG2VIDEO,   MKTAG('M', '7', '0', '3') },
+    { AV_CODEC_ID_MPEG2VIDEO,   MKTAG('M', '7', '0', '4') },
     { AV_CODEC_ID_MPEG2VIDEO,   MKTAG('M', '7', '0', '5') },
     { AV_CODEC_ID_MPEG2VIDEO,   MKTAG('m', 'p', 'g', 'v') },
     { AV_CODEC_ID_MPEG1VIDEO,   MKTAG('B', 'W', '1', '0') },
@@ -351,6 +355,7 @@ const AVCodecTag ff_codec_bmp_tags[] = {
     { AV_CODEC_ID_FRAPS,        MKTAG('F', 'P', 'S', '1') },
     { AV_CODEC_ID_THEORA,       MKTAG('t', 'h', 'e', 'o') },
     { AV_CODEC_ID_TRUEMOTION2,  MKTAG('T', 'M', '2', '0') },
+    { AV_CODEC_ID_TRUEMOTION2RT,MKTAG('T', 'R', '2', '0') },
     { AV_CODEC_ID_CSCD,         MKTAG('C', 'S', 'C', 'D') },
     { AV_CODEC_ID_ZMBV,         MKTAG('Z', 'M', 'B', 'V') },
     { AV_CODEC_ID_KMVC,         MKTAG('K', 'M', 'V', 'C') },
@@ -386,6 +391,8 @@ const AVCodecTag ff_codec_bmp_tags[] = {
     { AV_CODEC_ID_UTVIDEO,      MKTAG('U', 'L', 'H', '0') },
     { AV_CODEC_ID_UTVIDEO,      MKTAG('U', 'L', 'H', '2') },
     { AV_CODEC_ID_UTVIDEO,      MKTAG('U', 'Q', 'Y', '2') },
+    { AV_CODEC_ID_UTVIDEO,      MKTAG('U', 'Q', 'R', 'A') },
+    { AV_CODEC_ID_UTVIDEO,      MKTAG('U', 'Q', 'R', 'G') },
     { AV_CODEC_ID_VBLE,         MKTAG('V', 'B', 'L', 'E') },
     { AV_CODEC_ID_ESCAPE130,    MKTAG('E', '1', '3', '0') },
     { AV_CODEC_ID_DXTORY,       MKTAG('x', 't', 'o', 'r') },
@@ -414,6 +421,11 @@ const AVCodecTag ff_codec_bmp_tags[] = {
     { AV_CODEC_ID_RSCC,         MKTAG('R', 'S', 'C', 'C') },
     { AV_CODEC_ID_RSCC,         MKTAG('I', 'S', 'C', 'C') },
     { AV_CODEC_ID_CFHD,         MKTAG('C', 'F', 'H', 'D') },
+    { AV_CODEC_ID_M101,         MKTAG('M', '1', '0', '1') },
+    { AV_CODEC_ID_M101,         MKTAG('M', '1', '0', '2') },
+    { AV_CODEC_ID_MAGICYUV,     MKTAG('M', 'A', 'G', 'Y') },
+    { AV_CODEC_ID_YLC,          MKTAG('Y', 'L', 'C', '0') },
+
     { AV_CODEC_ID_NONE,         0 }
 };
 
@@ -442,6 +454,8 @@ const AVCodecTag ff_codec_wav_tags[] = {
     { AV_CODEC_ID_AMR_NB,          0x0038 },  /* rogue format number */
     { AV_CODEC_ID_G723_1,          0x0042 },
     { AV_CODEC_ID_ADPCM_G726,      0x0045 },
+    { AV_CODEC_ID_ADPCM_G726,      0x0014 },  /* g723 Antex */
+    { AV_CODEC_ID_ADPCM_G726,      0x0040 },  /* g721 Antex */
     { AV_CODEC_ID_MP2,             0x0050 },
     { AV_CODEC_ID_MP3,             0x0055 },
     { AV_CODEC_ID_AMR_NB,          0x0057 },
diff --git a/libavformat/riff.h b/libavformat/riff.h
index 3b57bb4..fe87e81 100644
--- a/libavformat/riff.h
+++ b/libavformat/riff.h
@@ -45,7 +45,7 @@ void ff_end_tag(AVIOContext *pb, int64_t start);
  */
 int ff_get_bmp_header(AVIOContext *pb, AVStream *st, unsigned *esize);
 
-void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *tags, int for_asf, int ignore_extradata);
+void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, const AVCodecTag *tags, int for_asf, int ignore_extradata);
 
 /**
  * Tell ff_put_wav_header() to use WAVEFORMATEX even for PCM codecs.
@@ -64,10 +64,10 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *t
  *
  * @return the size or -1 on error
  */
-int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags);
+int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int flags);
 
 enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps);
-int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecContext *codec, int size, int big_endian);
+int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int size, int big_endian);
 
 extern const AVCodecTag ff_codec_bmp_tags[]; // exposed through avformat_get_riff_video_tags()
 extern const AVCodecTag ff_codec_wav_tags[];
diff --git a/libavformat/riffdec.c b/libavformat/riffdec.c
index d7b81a0..1602c31 100644
--- a/libavformat/riffdec.c
+++ b/libavformat/riffdec.c
@@ -58,27 +58,27 @@ enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid)
  * an openended structure.
  */
 
-static void parse_waveformatex(AVIOContext *pb, AVCodecContext *c)
+static void parse_waveformatex(AVIOContext *pb, AVCodecParameters *par)
 {
     ff_asf_guid subformat;
     int bps = avio_rl16(pb);
     if (bps)
-        c->bits_per_coded_sample = bps;
+        par->bits_per_coded_sample = bps;
 
-    c->channel_layout        = avio_rl32(pb); /* dwChannelMask */
+    par->channel_layout        = avio_rl32(pb); /* dwChannelMask */
 
     ff_get_guid(pb, &subformat);
     if (!memcmp(subformat + 4,
                 (const uint8_t[]){ FF_AMBISONIC_BASE_GUID }, 12) ||
         !memcmp(subformat + 4,
                 (const uint8_t[]){ FF_MEDIASUBTYPE_BASE_GUID }, 12)) {
-        c->codec_tag = AV_RL32(subformat);
-        c->codec_id  = ff_wav_codec_get_id(c->codec_tag,
-                                           c->bits_per_coded_sample);
+        par->codec_tag = AV_RL32(subformat);
+        par->codec_id  = ff_wav_codec_get_id(par->codec_tag,
+                                             par->bits_per_coded_sample);
     } else {
-        c->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat);
-        if (!c->codec_id)
-            av_log(c, AV_LOG_WARNING,
+        par->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat);
+        if (!par->codec_id)
+            av_log(pb, AV_LOG_WARNING,
                    "unknown subformat:"FF_PRI_GUID"\n",
                    FF_ARG_GUID(subformat));
     }
@@ -86,64 +86,64 @@ static void parse_waveformatex(AVIOContext *pb, AVCodecContext *c)
 
 /* "big_endian" values are needed for RIFX file format */
 int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
-                      AVCodecContext *codec, int size, int big_endian)
+                      AVCodecParameters *par, int size, int big_endian)
 {
     int id;
     uint64_t bitrate = 0;
 
     if (size < 14) {
-        avpriv_request_sample(codec, "wav header size < 14");
+        avpriv_request_sample(s, "wav header size < 14");
         return AVERROR_INVALIDDATA;
     }
 
-    codec->codec_type  = AVMEDIA_TYPE_AUDIO;
+    par->codec_type  = AVMEDIA_TYPE_AUDIO;
     if (!big_endian) {
         id                 = avio_rl16(pb);
         if (id != 0x0165) {
-            codec->channels    = avio_rl16(pb);
-            codec->sample_rate = avio_rl32(pb);
+            par->channels    = avio_rl16(pb);
+            par->sample_rate = avio_rl32(pb);
             bitrate            = avio_rl32(pb) * 8LL;
-            codec->block_align = avio_rl16(pb);
+            par->block_align = avio_rl16(pb);
         }
     } else {
         id                 = avio_rb16(pb);
-        codec->channels    = avio_rb16(pb);
-        codec->sample_rate = avio_rb32(pb);
+        par->channels    = avio_rb16(pb);
+        par->sample_rate = avio_rb32(pb);
         bitrate            = avio_rb32(pb) * 8LL;
-        codec->block_align = avio_rb16(pb);
+        par->block_align = avio_rb16(pb);
     }
     if (size == 14) {  /* We're dealing with plain vanilla WAVEFORMAT */
-        codec->bits_per_coded_sample = 8;
+        par->bits_per_coded_sample = 8;
     } else {
         if (!big_endian) {
-            codec->bits_per_coded_sample = avio_rl16(pb);
+            par->bits_per_coded_sample = avio_rl16(pb);
         } else {
-            codec->bits_per_coded_sample = avio_rb16(pb);
+            par->bits_per_coded_sample = avio_rb16(pb);
         }
     }
     if (id == 0xFFFE) {
-        codec->codec_tag = 0;
+        par->codec_tag = 0;
     } else {
-        codec->codec_tag = id;
-        codec->codec_id  = ff_wav_codec_get_id(id,
-                                               codec->bits_per_coded_sample);
+        par->codec_tag = id;
+        par->codec_id  = ff_wav_codec_get_id(id,
+                                             par->bits_per_coded_sample);
     }
     if (size >= 18 && id != 0x0165) {  /* We're obviously dealing with WAVEFORMATEX */
         int cbSize = avio_rl16(pb); /* cbSize */
         if (big_endian) {
-            avpriv_report_missing_feature(codec, "WAVEFORMATEX support for RIFX files\n");
+            avpriv_report_missing_feature(s, "WAVEFORMATEX support for RIFX files");
             return AVERROR_PATCHWELCOME;
         }
         size  -= 18;
         cbSize = FFMIN(size, cbSize);
         if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */
-            parse_waveformatex(pb, codec);
+            parse_waveformatex(pb, par);
             cbSize -= 22;
             size   -= 22;
         }
         if (cbSize > 0) {
-            av_freep(&codec->extradata);
-            if (ff_get_extradata(codec, pb, cbSize) < 0)
+            av_freep(&par->extradata);
+            if (ff_get_extradata(s, par, pb, cbSize) < 0)
                 return AVERROR(ENOMEM);
             size -= cbSize;
         }
@@ -155,35 +155,35 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
         int nb_streams, i;
 
         size -= 4;
-        av_freep(&codec->extradata);
-        if (ff_get_extradata(codec, pb, size) < 0)
+        av_freep(&par->extradata);
+        if (ff_get_extradata(s, par, pb, size) < 0)
             return AVERROR(ENOMEM);
-        nb_streams         = AV_RL16(codec->extradata + 4);
-        codec->sample_rate = AV_RL32(codec->extradata + 12);
-        codec->channels    = 0;
+        nb_streams         = AV_RL16(par->extradata + 4);
+        par->sample_rate   = AV_RL32(par->extradata + 12);
+        par->channels      = 0;
         bitrate            = 0;
         if (size < 8 + nb_streams * 20)
             return AVERROR_INVALIDDATA;
         for (i = 0; i < nb_streams; i++)
-            codec->channels += codec->extradata[8 + i * 20 + 17];
+            par->channels += par->extradata[8 + i * 20 + 17];
     }
 
-    codec->bit_rate = bitrate;
+    par->bit_rate = bitrate;
 
-    if (codec->sample_rate <= 0) {
+    if (par->sample_rate <= 0) {
         av_log(s, AV_LOG_ERROR,
-               "Invalid sample rate: %d\n", codec->sample_rate);
+               "Invalid sample rate: %d\n", par->sample_rate);
         return AVERROR_INVALIDDATA;
     }
-    if (codec->codec_id == AV_CODEC_ID_AAC_LATM) {
+    if (par->codec_id == AV_CODEC_ID_AAC_LATM) {
         /* Channels and sample_rate values are those prior to applying SBR
          * and/or PS. */
-        codec->channels    = 0;
-        codec->sample_rate = 0;
+        par->channels    = 0;
+        par->sample_rate = 0;
     }
     /* override bits_per_coded_sample for G.726 */
-    if (codec->codec_id == AV_CODEC_ID_ADPCM_G726 && codec->sample_rate)
-        codec->bits_per_coded_sample = codec->bit_rate / codec->sample_rate;
+    if (par->codec_id == AV_CODEC_ID_ADPCM_G726 && par->sample_rate)
+        par->bits_per_coded_sample = par->bit_rate / par->sample_rate;
 
     return 0;
 }
@@ -210,11 +210,11 @@ int ff_get_bmp_header(AVIOContext *pb, AVStream *st, unsigned *esize)
     int tag1;
     if(esize) *esize  = avio_rl32(pb);
     else                avio_rl32(pb);
-    st->codec->width  = avio_rl32(pb);
-    st->codec->height = (int32_t)avio_rl32(pb);
+    st->codecpar->width  = avio_rl32(pb);
+    st->codecpar->height = (int32_t)avio_rl32(pb);
     avio_rl16(pb); /* planes */
-    st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */
-    tag1                             = avio_rl32(pb);
+    st->codecpar->bits_per_coded_sample = avio_rl16(pb); /* depth */
+    tag1                                = avio_rl32(pb);
     avio_rl32(pb); /* ImageSize */
     avio_rl32(pb); /* XPelsPerMeter */
     avio_rl32(pb); /* YPelsPerMeter */
diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c
index ceb27f2..36e6ac7 100644
--- a/libavformat/riffenc.c
+++ b/libavformat/riffenc.c
@@ -51,7 +51,8 @@ void ff_end_tag(AVIOContext *pb, int64_t start)
 
 /* WAVEFORMATEX header */
 /* returns the size or -1 on error */
-int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags)
+int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb,
+                      AVCodecParameters *par, int flags)
 {
     int bps, blkalign, bytespersec, frame_size;
     int hdrsize;
@@ -61,89 +62,89 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags)
     uint8_t *riff_extradata       = temp;
     uint8_t *riff_extradata_start = temp;
 
-    if (!enc->codec_tag || enc->codec_tag > 0xffff)
+    if (!par->codec_tag || par->codec_tag > 0xffff)
         return -1;
 
     /* We use the known constant frame size for the codec if known, otherwise
      * fall back on using AVCodecContext.frame_size, which is not as reliable
      * for indicating packet duration. */
-    frame_size = av_get_audio_frame_duration(enc, enc->block_align);
+    frame_size = av_get_audio_frame_duration2(par, par->block_align);
 
-    waveformatextensible = (enc->channels > 2 && enc->channel_layout) ||
-                           enc->sample_rate > 48000 ||
-                           enc->codec_id == AV_CODEC_ID_EAC3 ||
-                           av_get_bits_per_sample(enc->codec_id) > 16;
+    waveformatextensible = (par->channels > 2 && par->channel_layout) ||
+                           par->sample_rate > 48000 ||
+                           par->codec_id == AV_CODEC_ID_EAC3 ||
+                           av_get_bits_per_sample(par->codec_id) > 16;
 
     if (waveformatextensible)
         avio_wl16(pb, 0xfffe);
     else
-        avio_wl16(pb, enc->codec_tag);
+        avio_wl16(pb, par->codec_tag);
 
-    avio_wl16(pb, enc->channels);
-    avio_wl32(pb, enc->sample_rate);
-    if (enc->codec_id == AV_CODEC_ID_ATRAC3 ||
-        enc->codec_id == AV_CODEC_ID_G723_1 ||
-        enc->codec_id == AV_CODEC_ID_MP2    ||
-        enc->codec_id == AV_CODEC_ID_MP3    ||
-        enc->codec_id == AV_CODEC_ID_GSM_MS) {
+    avio_wl16(pb, par->channels);
+    avio_wl32(pb, par->sample_rate);
+    if (par->codec_id == AV_CODEC_ID_ATRAC3 ||
+        par->codec_id == AV_CODEC_ID_G723_1 ||
+        par->codec_id == AV_CODEC_ID_MP2    ||
+        par->codec_id == AV_CODEC_ID_MP3    ||
+        par->codec_id == AV_CODEC_ID_GSM_MS) {
         bps = 0;
     } else {
-        if (!(bps = av_get_bits_per_sample(enc->codec_id))) {
-            if (enc->bits_per_coded_sample)
-                bps = enc->bits_per_coded_sample;
+        if (!(bps = av_get_bits_per_sample(par->codec_id))) {
+            if (par->bits_per_coded_sample)
+                bps = par->bits_per_coded_sample;
             else
                 bps = 16;  // default to 16
         }
     }
-    if (bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample) {
-        av_log(enc, AV_LOG_WARNING,
+    if (bps != par->bits_per_coded_sample && par->bits_per_coded_sample) {
+        av_log(s, AV_LOG_WARNING,
                "requested bits_per_coded_sample (%d) "
                "and actually stored (%d) differ\n",
-               enc->bits_per_coded_sample, bps);
+               par->bits_per_coded_sample, bps);
     }
 
-    if (enc->codec_id == AV_CODEC_ID_MP2) {
-        blkalign = (144 * enc->bit_rate - 1)/enc->sample_rate + 1;
-    } else if (enc->codec_id == AV_CODEC_ID_MP3) {
-        blkalign = 576 * (enc->sample_rate <= (24000 + 32000)/2 ? 1 : 2);
-    } else if (enc->codec_id == AV_CODEC_ID_AC3) {
+    if (par->codec_id == AV_CODEC_ID_MP2) {
+        blkalign = (144 * par->bit_rate - 1)/par->sample_rate + 1;
+    } else if (par->codec_id == AV_CODEC_ID_MP3) {
+        blkalign = 576 * (par->sample_rate <= (24000 + 32000)/2 ? 1 : 2);
+    } else if (par->codec_id == AV_CODEC_ID_AC3) {
         blkalign = 3840;                /* maximum bytes per frame */
-    } else if (enc->codec_id == AV_CODEC_ID_AAC) {
-        blkalign = 768 * enc->channels; /* maximum bytes per frame */
-    } else if (enc->codec_id == AV_CODEC_ID_G723_1) {
+    } else if (par->codec_id == AV_CODEC_ID_AAC) {
+        blkalign = 768 * par->channels; /* maximum bytes per frame */
+    } else if (par->codec_id == AV_CODEC_ID_G723_1) {
         blkalign = 24;
-    } else if (enc->block_align != 0) { /* specified by the codec */
-        blkalign = enc->block_align;
+    } else if (par->block_align != 0) { /* specified by the codec */
+        blkalign = par->block_align;
     } else
-        blkalign = bps * enc->channels / av_gcd(8, bps);
-    if (enc->codec_id == AV_CODEC_ID_PCM_U8 ||
-        enc->codec_id == AV_CODEC_ID_PCM_S24LE ||
-        enc->codec_id == AV_CODEC_ID_PCM_S32LE ||
-        enc->codec_id == AV_CODEC_ID_PCM_F32LE ||
-        enc->codec_id == AV_CODEC_ID_PCM_F64LE ||
-        enc->codec_id == AV_CODEC_ID_PCM_S16LE) {
-        bytespersec = enc->sample_rate * blkalign;
-    } else if (enc->codec_id == AV_CODEC_ID_G723_1) {
+        blkalign = bps * par->channels / av_gcd(8, bps);
+    if (par->codec_id == AV_CODEC_ID_PCM_U8 ||
+        par->codec_id == AV_CODEC_ID_PCM_S24LE ||
+        par->codec_id == AV_CODEC_ID_PCM_S32LE ||
+        par->codec_id == AV_CODEC_ID_PCM_F32LE ||
+        par->codec_id == AV_CODEC_ID_PCM_F64LE ||
+        par->codec_id == AV_CODEC_ID_PCM_S16LE) {
+        bytespersec = par->sample_rate * blkalign;
+    } else if (par->codec_id == AV_CODEC_ID_G723_1) {
         bytespersec = 800;
     } else {
-        bytespersec = enc->bit_rate / 8;
+        bytespersec = par->bit_rate / 8;
     }
     avio_wl32(pb, bytespersec); /* bytes per second */
     avio_wl16(pb, blkalign);    /* block align */
     avio_wl16(pb, bps);         /* bits per sample */
-    if (enc->codec_id == AV_CODEC_ID_MP3) {
+    if (par->codec_id == AV_CODEC_ID_MP3) {
         bytestream_put_le16(&riff_extradata, 1);    /* wID */
         bytestream_put_le32(&riff_extradata, 2);    /* fdwFlags */
         bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */
         bytestream_put_le16(&riff_extradata, 1);    /* nFramesPerBlock */
         bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */
-    } else if (enc->codec_id == AV_CODEC_ID_MP2) {
+    } else if (par->codec_id == AV_CODEC_ID_MP2) {
         /* fwHeadLayer */
         bytestream_put_le16(&riff_extradata, 2);
         /* dwHeadBitrate */
-        bytestream_put_le32(&riff_extradata, enc->bit_rate);
+        bytestream_put_le32(&riff_extradata, par->bit_rate);
         /* fwHeadMode */
-        bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8);
+        bytestream_put_le16(&riff_extradata, par->channels == 2 ? 1 : 8);
         /* fwHeadModeExt */
         bytestream_put_le16(&riff_extradata, 0);
         /* wHeadEmphasis */
@@ -154,40 +155,40 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags)
         bytestream_put_le32(&riff_extradata, 0);
         /* dwPTSHigh */
         bytestream_put_le32(&riff_extradata, 0);
-    } else if (enc->codec_id == AV_CODEC_ID_G723_1) {
+    } else if (par->codec_id == AV_CODEC_ID_G723_1) {
         bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */
         bytestream_put_le32(&riff_extradata, 0xaea2f732);
         bytestream_put_le16(&riff_extradata, 0xacde);
-    } else if (enc->codec_id == AV_CODEC_ID_GSM_MS ||
-               enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
+    } else if (par->codec_id == AV_CODEC_ID_GSM_MS ||
+               par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
         /* wSamplesPerBlock */
         bytestream_put_le16(&riff_extradata, frame_size);
-    } else if (enc->extradata_size) {
-        riff_extradata_start = enc->extradata;
-        riff_extradata       = enc->extradata + enc->extradata_size;
+    } else if (par->extradata_size) {
+        riff_extradata_start = par->extradata;
+        riff_extradata       = par->extradata + par->extradata_size;
     }
     /* write WAVEFORMATEXTENSIBLE extensions */
     if (waveformatextensible) {
         int write_channel_mask = !(flags & FF_PUT_WAV_HEADER_SKIP_CHANNELMASK) &&
-                                 (enc->strict_std_compliance < FF_COMPLIANCE_NORMAL ||
-                                  enc->channel_layout < 0x40000);
+                                 (s->strict_std_compliance < FF_COMPLIANCE_NORMAL ||
+                                  par->channel_layout < 0x40000);
         /* 22 is WAVEFORMATEXTENSIBLE size */
         avio_wl16(pb, riff_extradata - riff_extradata_start + 22);
         /* ValidBitsPerSample || SamplesPerBlock || Reserved */
         avio_wl16(pb, bps);
         /* dwChannelMask */
-        avio_wl32(pb, write_channel_mask ? enc->channel_layout : 0);
+        avio_wl32(pb, write_channel_mask ? par->channel_layout : 0);
         /* GUID + next 3 */
-        if (enc->codec_id == AV_CODEC_ID_EAC3) {
-            ff_put_guid(pb, ff_get_codec_guid(enc->codec_id, ff_codec_wav_guids));
+        if (par->codec_id == AV_CODEC_ID_EAC3) {
+            ff_put_guid(pb, ff_get_codec_guid(par->codec_id, ff_codec_wav_guids));
         } else {
-        avio_wl32(pb, enc->codec_tag);
+        avio_wl32(pb, par->codec_tag);
         avio_wl32(pb, 0x00100000);
         avio_wl32(pb, 0xAA000080);
         avio_wl32(pb, 0x719B3800);
         }
     } else if ((flags & FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX) ||
-               enc->codec_tag != 0x0001 /* PCM */ ||
+               par->codec_tag != 0x0001 /* PCM */ ||
                riff_extradata - riff_extradata_start) {
         /* WAVEFORMATEX */
         avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */
@@ -203,65 +204,86 @@ int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags)
 }
 
 /* BITMAPINFOHEADER header */
-void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc,
+void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par,
                        const AVCodecTag *tags, int for_asf, int ignore_extradata)
 {
-    int keep_height = enc->extradata_size >= 9 &&
-                      !memcmp(enc->extradata + enc->extradata_size - 9, "BottomUp", 9);
-    int extradata_size = enc->extradata_size - 9*keep_height;
+    int keep_height = par->extradata_size >= 9 &&
+                      !memcmp(par->extradata + par->extradata_size - 9, "BottomUp", 9);
+    int extradata_size = par->extradata_size - 9*keep_height;
+    enum AVPixelFormat pix_fmt = par->format;
+    int pal_avi;
 
-    /* size */
-    avio_wl32(pb, 40 + (ignore_extradata ? 0 :extradata_size));
-    avio_wl32(pb, enc->width);
+    if (pix_fmt == AV_PIX_FMT_NONE && par->bits_per_coded_sample == 1)
+        pix_fmt = AV_PIX_FMT_MONOWHITE;
+    pal_avi = !for_asf &&
+              (pix_fmt == AV_PIX_FMT_PAL8 ||
+               pix_fmt == AV_PIX_FMT_MONOWHITE ||
+               pix_fmt == AV_PIX_FMT_MONOBLACK);
+
+    /* Size (not including the size of the color table or color masks) */
+    avio_wl32(pb, 40 + (ignore_extradata || pal_avi ? 0 : extradata_size));
+    avio_wl32(pb, par->width);
     //We always store RGB TopDown
-    avio_wl32(pb, enc->codec_tag || keep_height ? enc->height : -enc->height);
+    avio_wl32(pb, par->codec_tag || keep_height ? par->height : -par->height);
     /* planes */
     avio_wl16(pb, 1);
     /* depth */
-    avio_wl16(pb, enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24);
+    avio_wl16(pb, par->bits_per_coded_sample ? par->bits_per_coded_sample : 24);
     /* compression type */
-    avio_wl32(pb, enc->codec_tag);
-    avio_wl32(pb, (enc->width * enc->height * (enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24)+7) / 8);
-    avio_wl32(pb, 0);
+    avio_wl32(pb, par->codec_tag);
+    avio_wl32(pb, (par->width * par->height * (par->bits_per_coded_sample ? par->bits_per_coded_sample : 24)+7) / 8);
     avio_wl32(pb, 0);
     avio_wl32(pb, 0);
+    /* Number of color indices in the color table that are used.
+     * A value of 0 means 2^biBitCount indices, but this doesn't work
+     * with Windows Media Player and files containing xxpc chunks. */
+    avio_wl32(pb, pal_avi ? 1 << par->bits_per_coded_sample : 0);
     avio_wl32(pb, 0);
 
     if (!ignore_extradata) {
-        avio_write(pb, enc->extradata, extradata_size);
-
-        if (!for_asf && extradata_size & 1)
-            avio_w8(pb, 0);
+        if (par->extradata_size) {
+            avio_write(pb, par->extradata, extradata_size);
+            if (!for_asf && extradata_size & 1)
+                avio_w8(pb, 0);
+        } else if (pal_avi) {
+            int i;
+            for (i = 0; i < 1 << par->bits_per_coded_sample; i++) {
+                /* Initialize 1 bpp palette to black & white */
+                if (i == 0 && pix_fmt == AV_PIX_FMT_MONOWHITE)
+                    avio_wl32(pb, 0xffffff);
+                else if (i == 1 && pix_fmt == AV_PIX_FMT_MONOBLACK)
+                    avio_wl32(pb, 0xffffff);
+                else
+                    avio_wl32(pb, 0);
+            }
+        }
     }
 }
 
 void ff_parse_specific_params(AVStream *st, int *au_rate,
                               int *au_ssize, int *au_scale)
 {
-    AVCodecContext *codec = st->codec;
+    AVCodecParameters *par = st->codecpar;
     int gcd;
     int audio_frame_size;
 
-    /* We use the known constant frame size for the codec if known, otherwise
-     * fall back on using AVCodecContext.frame_size, which is not as reliable
-     * for indicating packet duration. */
-    audio_frame_size = av_get_audio_frame_duration(codec, 0);
+    audio_frame_size = av_get_audio_frame_duration2(par, 0);
     if (!audio_frame_size)
-        audio_frame_size = codec->frame_size;
+        audio_frame_size = par->frame_size;
 
-    *au_ssize = codec->block_align;
-    if (audio_frame_size && codec->sample_rate) {
+    *au_ssize = par->block_align;
+    if (audio_frame_size && par->sample_rate) {
         *au_scale = audio_frame_size;
-        *au_rate  = codec->sample_rate;
-    } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO ||
-               codec->codec_type == AVMEDIA_TYPE_DATA ||
-               codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+        *au_rate  = par->sample_rate;
+    } else if (par->codec_type == AVMEDIA_TYPE_VIDEO ||
+               par->codec_type == AVMEDIA_TYPE_DATA ||
+               par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
         *au_scale = st->time_base.num;
         *au_rate  = st->time_base.den;
     } else {
-        *au_scale = codec->block_align ? codec->block_align * 8 : 8;
-        *au_rate  = codec->bit_rate ? codec->bit_rate :
-                    8 * codec->sample_rate;
+        *au_scale = par->block_align ? par->block_align * 8 : 8;
+        *au_rate  = par->bit_rate ? par->bit_rate :
+                    8 * par->sample_rate;
     }
     gcd        = av_gcd(*au_scale, *au_rate);
     *au_scale /= gcd;
diff --git a/libavformat/rl2.c b/libavformat/rl2.c
index 5017016..0bec8f1 100644
--- a/libavformat/rl2.c
+++ b/libavformat/rl2.c
@@ -104,7 +104,7 @@ static av_cold int rl2_read_header(AVFormatContext *s)
     if(back_size > INT_MAX/2  || frame_count > INT_MAX / sizeof(uint32_t))
         return AVERROR_INVALIDDATA;
 
-    avio_skip(pb, 2);         /* encoding mentod */
+    avio_skip(pb, 2);         /* encoding method */
     sound_rate = avio_rl16(pb);
     rate = avio_rl16(pb);
     channels = avio_rl16(pb);
@@ -115,19 +115,19 @@ static av_cold int rl2_read_header(AVFormatContext *s)
     if(!st)
          return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_RL2;
-    st->codec->codec_tag = 0;  /* no fourcc */
-    st->codec->width = 320;
-    st->codec->height = 200;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_RL2;
+    st->codecpar->codec_tag = 0;  /* no fourcc */
+    st->codecpar->width = 320;
+    st->codecpar->height = 200;
 
     /** allocate and fill extradata */
-    st->codec->extradata_size = EXTRADATA1_SIZE;
+    st->codecpar->extradata_size = EXTRADATA1_SIZE;
 
     if(signature == RLV3_TAG && back_size > 0)
-        st->codec->extradata_size += back_size;
+        st->codecpar->extradata_size += back_size;
 
-    if(ff_get_extradata(st->codec, pb, st->codec->extradata_size) < 0)
+    if(ff_get_extradata(s, st->codecpar, pb, st->codecpar->extradata_size) < 0)
         return AVERROR(ENOMEM);
 
     /** setup audio stream if present */
@@ -143,16 +143,16 @@ static av_cold int rl2_read_header(AVFormatContext *s)
         st = avformat_new_stream(s, NULL);
         if (!st)
             return AVERROR(ENOMEM);
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id = AV_CODEC_ID_PCM_U8;
-        st->codec->codec_tag = 1;
-        st->codec->channels = channels;
-        st->codec->bits_per_coded_sample = 8;
-        st->codec->sample_rate = rate;
-        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
-            st->codec->bits_per_coded_sample;
-        st->codec->block_align = st->codec->channels *
-            st->codec->bits_per_coded_sample / 8;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
+        st->codecpar->codec_tag = 1;
+        st->codecpar->channels = channels;
+        st->codecpar->bits_per_coded_sample = 8;
+        st->codecpar->sample_rate = rate;
+        st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+            st->codecpar->bits_per_coded_sample;
+        st->codecpar->block_align = st->codecpar->channels *
+            st->codecpar->bits_per_coded_sample / 8;
         avpriv_set_pts_info(st,32,1,rate);
     }
 
diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c
index 1a61b10..cb0481e 100644
--- a/libavformat/rmdec.c
+++ b/libavformat/rmdec.c
@@ -87,13 +87,13 @@ static void get_str8(AVIOContext *pb, char *buf, int buf_size)
     get_strl(pb, buf, buf_size, avio_r8(pb));
 }
 
-static int rm_read_extradata(AVIOContext *pb, AVCodecContext *avctx, unsigned size)
+static int rm_read_extradata(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, unsigned size)
 {
     if (size >= 1<<24) {
-        av_log(avctx, AV_LOG_ERROR, "extradata size %u too large\n", size);
+        av_log(s, AV_LOG_ERROR, "extradata size %u too large\n", size);
         return -1;
     }
-    if (ff_get_extradata(avctx, pb, size) < 0)
+    if (ff_get_extradata(s, par, pb, size) < 0)
         return AVERROR(ENOMEM);
     return 0;
 }
@@ -150,12 +150,12 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
         if ((startpos + header_size) > avio_tell(pb))
             avio_skip(pb, header_size + startpos - avio_tell(pb));
         if (bytes_per_minute)
-            st->codec->bit_rate = 8LL * bytes_per_minute / 60;
-        st->codec->sample_rate = 8000;
-        st->codec->channels = 1;
-        st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id = AV_CODEC_ID_RA_144;
+            st->codecpar->bit_rate = 8LL * bytes_per_minute / 60;
+        st->codecpar->sample_rate = 8000;
+        st->codecpar->channels = 1;
+        st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id = AV_CODEC_ID_RA_144;
         ast->deint_id = DEINT_ID_INT0;
     } else {
         int flavor, sub_packet_h, coded_framesize, sub_packet_size;
@@ -173,19 +173,19 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
         bytes_per_minute = avio_rb32(pb);
         if (version == 4) {
             if (bytes_per_minute)
-                st->codec->bit_rate = 8LL * bytes_per_minute / 60;
+                st->codecpar->bit_rate = 8LL * bytes_per_minute / 60;
         }
         avio_rb32(pb); /* ??? */
         ast->sub_packet_h = sub_packet_h = avio_rb16(pb); /* 1 */
-        st->codec->block_align= avio_rb16(pb); /* frame size */
+        st->codecpar->block_align= avio_rb16(pb); /* frame size */
         ast->sub_packet_size = sub_packet_size = avio_rb16(pb); /* sub packet size */
         avio_rb16(pb); /* ??? */
         if (version == 5) {
             avio_rb16(pb); avio_rb16(pb); avio_rb16(pb);
         }
-        st->codec->sample_rate = avio_rb16(pb);
+        st->codecpar->sample_rate = avio_rb16(pb);
         avio_rb32(pb);
-        st->codec->channels = avio_rb16(pb);
+        st->codecpar->channels = avio_rb16(pb);
         if (version == 5) {
             ast->deint_id = avio_rl32(pb);
             avio_read(pb, buf, 4);
@@ -196,19 +196,19 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
             ast->deint_id = AV_RL32(buf);
             get_str8(pb, buf, sizeof(buf)); /* desc */
         }
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_tag  = AV_RL32(buf);
-        st->codec->codec_id   = ff_codec_get_id(ff_rm_codec_tags,
-                                                st->codec->codec_tag);
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_tag  = AV_RL32(buf);
+        st->codecpar->codec_id   = ff_codec_get_id(ff_rm_codec_tags,
+                                                   st->codecpar->codec_tag);
 
-        switch (st->codec->codec_id) {
+        switch (st->codecpar->codec_id) {
         case AV_CODEC_ID_AC3:
             st->need_parsing = AVSTREAM_PARSE_FULL;
             break;
         case AV_CODEC_ID_RA_288:
-            st->codec->extradata_size= 0;
-            ast->audio_framesize = st->codec->block_align;
-            st->codec->block_align = coded_framesize;
+            st->codecpar->extradata_size= 0;
+            ast->audio_framesize = st->codecpar->block_align;
+            st->codecpar->block_align = coded_framesize;
             break;
         case AV_CODEC_ID_COOK:
             st->need_parsing = AVSTREAM_PARSE_HEADERS;
@@ -227,22 +227,22 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
                 }
             }
 
-            ast->audio_framesize = st->codec->block_align;
-            if (st->codec->codec_id == AV_CODEC_ID_SIPR) {
+            ast->audio_framesize = st->codecpar->block_align;
+            if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) {
                 if (flavor > 3) {
                     av_log(s, AV_LOG_ERROR, "bad SIPR file flavor %d\n",
                            flavor);
                     return -1;
                 }
-                st->codec->block_align = ff_sipr_subpk_size[flavor];
+                st->codecpar->block_align = ff_sipr_subpk_size[flavor];
             } else {
                 if(sub_packet_size <= 0){
                     av_log(s, AV_LOG_ERROR, "sub_packet_size is invalid\n");
                     return -1;
                 }
-                st->codec->block_align = ast->sub_packet_size;
+                st->codecpar->block_align = ast->sub_packet_size;
             }
-            if ((ret = rm_read_extradata(pb, st->codec, codecdata_length)) < 0)
+            if ((ret = rm_read_extradata(s, pb, st->codecpar, codecdata_length)) < 0)
                 return ret;
 
             break;
@@ -257,7 +257,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
             }
             if (codecdata_length >= 1) {
                 avio_r8(pb);
-                if ((ret = rm_read_extradata(pb, st->codec, codecdata_length - 1)) < 0)
+                if ((ret = rm_read_extradata(s, pb, st->codecpar, codecdata_length - 1)) < 0)
                     return ret;
             }
             break;
@@ -292,9 +292,9 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb,
         if (ast->deint_id == DEINT_ID_INT4 ||
             ast->deint_id == DEINT_ID_GENR ||
             ast->deint_id == DEINT_ID_SIPR) {
-            if (st->codec->block_align <= 0 ||
+            if (st->codecpar->block_align <= 0 ||
                 ast->audio_framesize * sub_packet_h > (unsigned)INT_MAX ||
-                ast->audio_framesize * sub_packet_h < st->codec->block_align)
+                ast->audio_framesize * sub_packet_h < st->codecpar->block_align)
                 return AVERROR_INVALIDDATA;
             if (av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h) < 0)
                 return AVERROR(ENOMEM);
@@ -334,13 +334,13 @@ int ff_rm_read_mdpr_codecdata(AVFormatContext *s, AVIOContext *pb,
             return -1;
     } else if (v == MKBETAG('L', 'S', 'D', ':')) {
         avio_seek(pb, -4, SEEK_CUR);
-        if ((ret = rm_read_extradata(pb, st->codec, codec_data_size)) < 0)
+        if ((ret = rm_read_extradata(s, pb, st->codecpar, codec_data_size)) < 0)
             return ret;
 
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_tag  = AV_RL32(st->codec->extradata);
-        st->codec->codec_id   = ff_codec_get_id(ff_rm_codec_tags,
-                                                st->codec->codec_tag);
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_tag  = AV_RL32(st->codecpar->extradata);
+        st->codecpar->codec_id   = ff_codec_get_id(ff_rm_codec_tags,
+                                                st->codecpar->codec_tag);
     } else if(mime && !strcmp(mime, "logical-fileinfo")){
         int stream_count, rule_count, property_count, i;
         ff_free_stream(s, st);
@@ -375,21 +375,21 @@ int ff_rm_read_mdpr_codecdata(AVFormatContext *s, AVIOContext *pb,
             av_log(s, AV_LOG_WARNING, "Unsupported stream type %08x\n", v);
             goto skip;
         }
-        st->codec->codec_tag = avio_rl32(pb);
-        st->codec->codec_id  = ff_codec_get_id(ff_rm_codec_tags,
-                                               st->codec->codec_tag);
-        av_log(s, AV_LOG_TRACE, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0'));
-        if (st->codec->codec_id == AV_CODEC_ID_NONE)
+        st->codecpar->codec_tag = avio_rl32(pb);
+        st->codecpar->codec_id  = ff_codec_get_id(ff_rm_codec_tags,
+                                                  st->codecpar->codec_tag);
+        av_log(s, AV_LOG_TRACE, "%X %X\n", st->codecpar->codec_tag, MKTAG('R', 'V', '2', '0'));
+        if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
             goto fail1;
-        st->codec->width  = avio_rb16(pb);
-        st->codec->height = avio_rb16(pb);
+        st->codecpar->width  = avio_rb16(pb);
+        st->codecpar->height = avio_rb16(pb);
         avio_skip(pb, 2); // looks like bits per sample
         avio_skip(pb, 4); // always zero?
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
         st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
         fps = avio_rb32(pb);
 
-        if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (avio_tell(pb) - codec_pos))) < 0)
+        if ((ret = rm_read_extradata(s, pb, st->codecpar, codec_data_size - (avio_tell(pb) - codec_pos))) < 0)
             return ret;
 
         if (fps > 0) {
@@ -511,10 +511,10 @@ static int rm_read_multi(AVFormatContext *s, AVIOContext *pb,
                 return ret;
             }
             st2->id = st->id + (i<<16);
-            st2->codec->bit_rate = st->codec->bit_rate;
+            st2->codecpar->bit_rate = st->codecpar->bit_rate;
             st2->start_time = st->start_time;
             st2->duration   = st->duration;
-            st2->codec->codec_type = AVMEDIA_TYPE_DATA;
+            st2->codecpar->codec_type = AVMEDIA_TYPE_DATA;
             st2->priv_data = ff_rm_alloc_rmstream();
             if (!st2->priv_data)
                 return AVERROR(ENOMEM);
@@ -598,7 +598,7 @@ static int rm_read_header(AVFormatContext *s)
             }
             st->id = avio_rb16(pb);
             avio_rb32(pb); /* max bit rate */
-            st->codec->bit_rate = avio_rb32(pb); /* bit rate */
+            st->codecpar->bit_rate = avio_rb32(pb); /* bit rate */
             avio_rb32(pb); /* max packet size */
             avio_rb32(pb); /* avg packet size */
             start_time = avio_rb32(pb); /* start time */
@@ -610,7 +610,7 @@ static int rm_read_header(AVFormatContext *s)
                 s->duration = AV_NOPTS_VALUE;
             get_str8(pb, buf, sizeof(buf)); /* desc */
             get_str8(pb, mime, sizeof(mime)); /* mimetype */
-            st->codec->codec_type = AVMEDIA_TYPE_DATA;
+            st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
             st->priv_data = ff_rm_alloc_rmstream();
             if (!st->priv_data)
                 return AVERROR(ENOMEM);
@@ -864,7 +864,7 @@ rm_ac3_swap_bytes (AVStream *st, AVPacket *pkt)
     uint8_t *ptr;
     int j;
 
-    if (st->codec->codec_id == AV_CODEC_ID_AC3) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_AC3) {
         ptr = pkt->data;
         for (j=0;j<pkt->size;j+=2) {
             FFSWAP(int, ptr[0], ptr[1]);
@@ -891,12 +891,12 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
     RMDemuxContext *rm = s->priv_data;
     int ret;
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         rm->current_stream= st->id;
         ret = rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, &timestamp);
         if(ret)
             return ret < 0 ? ret : -1; //got partial frame or error
-    } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+    } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
         if ((ast->deint_id == DEINT_ID_GENR) ||
             (ast->deint_id == DEINT_ID_INT4) ||
             (ast->deint_id == DEINT_ID_SIPR)) {
@@ -933,7 +933,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
 
              ast->sub_packet_cnt = 0;
              rm->audio_stream_num = st->index;
-             rm->audio_pkt_cnt = h * w / st->codec->block_align;
+             rm->audio_pkt_cnt = h * w / st->codecpar->block_align;
         } else if ((ast->deint_id == DEINT_ID_VBRF) ||
                    (ast->deint_id == DEINT_ID_VBRS)) {
             int x;
@@ -959,8 +959,8 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
     pkt->stream_index = st->index;
 
 #if 0
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-        if(st->codec->codec_id == AV_CODEC_ID_RV20){
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if(st->codecpar->codec_id == AV_CODEC_ID_RV20){
             int seq= 128*(pkt->data[2]&0x7F) + (pkt->data[3]>>1);
             av_log(s, AV_LOG_DEBUG, "%d %"PRId64" %d\n", *timestamp, *timestamp*512LL/25, seq);
 
@@ -975,7 +975,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
     if (flags & 2)
         pkt->flags |= AV_PKT_FLAG_KEY;
 
-    return st->codec->codec_type == AVMEDIA_TYPE_AUDIO ? rm->audio_pkt_cnt : 0;
+    return st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? rm->audio_pkt_cnt : 0;
 }
 
 int
@@ -992,12 +992,12 @@ ff_rm_retrieve_cache (AVFormatContext *s, AVIOContext *pb,
         if (ret < 0)
             return ret;
     } else {
-        int ret = av_new_packet(pkt, st->codec->block_align);
+        int ret = av_new_packet(pkt, st->codecpar->block_align);
         if (ret < 0)
             return ret;
-        memcpy(pkt->data, ast->pkt.data + st->codec->block_align * //FIXME avoid this
-               (ast->sub_packet_h * ast->audio_framesize / st->codec->block_align - rm->audio_pkt_cnt),
-               st->codec->block_align);
+        memcpy(pkt->data, ast->pkt.data + st->codecpar->block_align * //FIXME avoid this
+               (ast->sub_packet_h * ast->audio_framesize / st->codecpar->block_align - rm->audio_pkt_cnt),
+               st->codecpar->block_align);
     }
     rm->audio_pkt_cnt--;
     if ((pkt->pts = ast->audiotimestamp) != AV_NOPTS_VALUE) {
@@ -1114,7 +1114,7 @@ static int64_t rm_read_dts(AVFormatContext *s, int stream_index,
             return AV_NOPTS_VALUE;
 
         st = s->streams[stream_index2];
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             h= avio_r8(s->pb); len--;
             if(!(h & 0x40)){
                 seq = avio_r8(s->pb); len--;
diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c
index 33eaf63..3708f42 100644
--- a/libavformat/rmenc.c
+++ b/libavformat/rmenc.c
@@ -33,7 +33,7 @@ typedef struct StreamInfo {
     int nb_frames;    /* current frame number */
     int total_frames; /* total number of frames */
     int num;
-    AVCodecContext *enc;
+    AVCodecParameters *par;
 } StreamInfo;
 
 typedef struct RMMuxContext {
@@ -147,7 +147,7 @@ static int rv10_write_header(AVFormatContext *ctx,
 
         stream = &rm->streams[i];
 
-        if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (stream->par->codec_type == AVMEDIA_TYPE_AUDIO) {
             desc = "The Audio Stream";
             mimetype = "audio/x-pn-realaudio";
             codec_data_size = 73;
@@ -183,11 +183,11 @@ static int rv10_write_header(AVFormatContext *ctx,
         put_str8(s, mimetype);
         avio_wb32(s, codec_data_size);
 
-        if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) {
+        if (stream->par->codec_type == AVMEDIA_TYPE_AUDIO) {
             int coded_frame_size, fscode, sample_rate;
-            int frame_size = av_get_audio_frame_duration(stream->enc, 0);
-            sample_rate = stream->enc->sample_rate;
-            coded_frame_size = (stream->enc->bit_rate *
+            int frame_size = av_get_audio_frame_duration2(stream->par, 0);
+            sample_rate = stream->par->sample_rate;
+            coded_frame_size = (stream->par->bit_rate *
                                 frame_size) / (8 * sample_rate);
             /* audio codec info */
             avio_write(s, ".ra", 3);
@@ -222,19 +222,19 @@ static int rv10_write_header(AVFormatContext *ctx,
                 coded_frame_size--;
             avio_wb32(s, coded_frame_size); /* frame length */
             avio_wb32(s, 0x51540); /* unknown */
-            avio_wb32(s, stream->enc->bit_rate / 8 * 60); /* bytes per minute */
-            avio_wb32(s, stream->enc->bit_rate / 8 * 60); /* bytes per minute */
+            avio_wb32(s, stream->par->bit_rate / 8 * 60); /* bytes per minute */
+            avio_wb32(s, stream->par->bit_rate / 8 * 60); /* bytes per minute */
             avio_wb16(s, 0x01);
             /* frame length : seems to be very important */
             avio_wb16(s, coded_frame_size);
             avio_wb32(s, 0); /* unknown */
-            avio_wb16(s, stream->enc->sample_rate); /* sample rate */
+            avio_wb16(s, stream->par->sample_rate); /* sample rate */
             avio_wb32(s, 0x10); /* unknown */
-            avio_wb16(s, stream->enc->channels);
+            avio_wb16(s, stream->par->channels);
             put_str8(s, "Int0"); /* codec name */
-            if (stream->enc->codec_tag) {
+            if (stream->par->codec_tag) {
                 avio_w8(s, 4); /* tag length */
-                avio_wl32(s, stream->enc->codec_tag);
+                avio_wl32(s, stream->par->codec_tag);
             } else {
                 av_log(ctx, AV_LOG_ERROR, "Invalid codec tag\n");
                 return -1;
@@ -247,21 +247,21 @@ static int rv10_write_header(AVFormatContext *ctx,
             /* video codec info */
             avio_wb32(s,34); /* size */
             ffio_wfourcc(s, "VIDO");
-            if(stream->enc->codec_id == AV_CODEC_ID_RV10)
+            if(stream->par->codec_id == AV_CODEC_ID_RV10)
                 ffio_wfourcc(s,"RV10");
             else
                 ffio_wfourcc(s,"RV20");
-            avio_wb16(s, stream->enc->width);
-            avio_wb16(s, stream->enc->height);
+            avio_wb16(s, stream->par->width);
+            avio_wb16(s, stream->par->height);
             avio_wb16(s, stream->frame_rate.num / stream->frame_rate.den); /* frames per seconds ? */
             avio_wb32(s,0);     /* unknown meaning */
             avio_wb16(s, stream->frame_rate.num / stream->frame_rate.den);  /* unknown meaning */
             avio_wb32(s,0);     /* unknown meaning */
             avio_wb16(s, 8);    /* unknown meaning */
-            /* Seems to be the codec version: only use basic H263. The next
-               versions seems to add a diffential DC coding as in
-               MPEG... nothing new under the sun */
-            if(stream->enc->codec_id == AV_CODEC_ID_RV10)
+            /* Seems to be the codec version: only use basic H.263. The next
+               versions seems to add a differential DC coding as in
+               MPEG... nothing new under the sun. */
+            if(stream->par->codec_id == AV_CODEC_ID_RV10)
                 avio_wb32(s,0x10000000);
             else
                 avio_wb32(s,0x20103001);
@@ -312,7 +312,7 @@ static int rm_write_header(AVFormatContext *s)
     RMMuxContext *rm = s->priv_data;
     StreamInfo *stream;
     int n;
-    AVCodecContext *codec;
+    AVCodecParameters *par;
 
     if (s->nb_streams > 2) {
         av_log(s, AV_LOG_ERROR, "At most 2 streams are currently supported for muxing in RM\n");
@@ -324,18 +324,18 @@ static int rm_write_header(AVFormatContext *s)
         int frame_size;
 
         s->streams[n]->id = n;
-        codec = s->streams[n]->codec;
+        par = s->streams[n]->codecpar;
         stream = &rm->streams[n];
         memset(stream, 0, sizeof(StreamInfo));
         stream->num = n;
-        stream->bit_rate = codec->bit_rate;
-        stream->enc = codec;
+        stream->bit_rate = par->bit_rate;
+        stream->par = par;
 
-        switch(codec->codec_type) {
+        switch (par->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
             rm->audio_stream = stream;
-            frame_size = av_get_audio_frame_duration(codec, 0);
-            stream->frame_rate = (AVRational){codec->sample_rate, frame_size};
+            frame_size = av_get_audio_frame_duration2(par, 0);
+            stream->frame_rate = (AVRational){par->sample_rate, frame_size};
             /* XXX: dummy values */
             stream->packet_max_size = 1024;
             stream->nb_packets = 0;
@@ -370,7 +370,7 @@ static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int
 
     write_packet_header(s, stream, size, !!(flags & AV_PKT_FLAG_KEY));
 
-    if (stream->enc->codec_id == AV_CODEC_ID_AC3) {
+    if (stream->par->codec_id == AV_CODEC_ID_AC3) {
         /* for AC-3, the words seem to be reversed */
         for (i = 0; i < size; i += 2) {
             avio_w8(pb, buf[i + 1]);
@@ -402,7 +402,7 @@ static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int
     write_packet_header(s, stream, size + 7 + (size >= 0x4000)*4, key_frame);
     /* bit 7: '1' if final packet of a frame converted in several packets */
     avio_w8(pb, 0x81);
-    /* bit 7: '1' if I frame. bits 6..0 : sequence number in current
+    /* bit 7: '1' if I-frame. bits 6..0 : sequence number in current
        frame starting from 1 */
     if (key_frame) {
         avio_w8(pb, 0x81);
@@ -433,7 +433,7 @@ static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int
 
 static int rm_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    if (s->streams[pkt->stream_index]->codec->codec_type ==
+    if (s->streams[pkt->stream_index]->codecpar->codec_type ==
         AVMEDIA_TYPE_AUDIO)
         return rm_write_audio(s, pkt->data, pkt->size, pkt->flags);
     else
diff --git a/libavformat/rpl.c b/libavformat/rpl.c
index 76c385b..a794d3b 100644
--- a/libavformat/rpl.c
+++ b/libavformat/rpl.c
@@ -145,34 +145,34 @@ static int rpl_read_header(AVFormatContext *s)
     vst = avformat_new_stream(s, NULL);
     if (!vst)
         return AVERROR(ENOMEM);
-    vst->codec->codec_type      = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_tag       = read_line_and_int(pb, &error);  // video format
-    vst->codec->width           = read_line_and_int(pb, &error);  // video width
-    vst->codec->height          = read_line_and_int(pb, &error);  // video height
-    vst->codec->bits_per_coded_sample = read_line_and_int(pb, &error);  // video bits per sample
+    vst->codecpar->codec_type      = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_tag       = read_line_and_int(pb, &error);  // video format
+    vst->codecpar->width           = read_line_and_int(pb, &error);  // video width
+    vst->codecpar->height          = read_line_and_int(pb, &error);  // video height
+    vst->codecpar->bits_per_coded_sample = read_line_and_int(pb, &error);  // video bits per sample
     error |= read_line(pb, line, sizeof(line));                   // video frames per second
     fps = read_fps(line, &error);
     avpriv_set_pts_info(vst, 32, fps.den, fps.num);
 
     // Figure out the video codec
-    switch (vst->codec->codec_tag) {
+    switch (vst->codecpar->codec_tag) {
 #if 0
         case 122:
-            vst->codec->codec_id = AV_CODEC_ID_ESCAPE122;
+            vst->codecpar->codec_id = AV_CODEC_ID_ESCAPE122;
             break;
 #endif
         case 124:
-            vst->codec->codec_id = AV_CODEC_ID_ESCAPE124;
+            vst->codecpar->codec_id = AV_CODEC_ID_ESCAPE124;
             // The header is wrong here, at least sometimes
-            vst->codec->bits_per_coded_sample = 16;
+            vst->codecpar->bits_per_coded_sample = 16;
             break;
         case 130:
-            vst->codec->codec_id = AV_CODEC_ID_ESCAPE130;
+            vst->codecpar->codec_id = AV_CODEC_ID_ESCAPE130;
             break;
         default:
             avpriv_report_missing_feature(s, "Video format %i",
-                                          vst->codec->codec_tag);
-            vst->codec->codec_id = AV_CODEC_ID_NONE;
+                                          vst->codecpar->codec_tag);
+            vst->codecpar->codec_id = AV_CODEC_ID_NONE;
     }
 
     // Audio headers
@@ -184,57 +184,57 @@ static int rpl_read_header(AVFormatContext *s)
         ast = avformat_new_stream(s, NULL);
         if (!ast)
             return AVERROR(ENOMEM);
-        ast->codec->codec_type      = AVMEDIA_TYPE_AUDIO;
-        ast->codec->codec_tag       = audio_format;
-        ast->codec->sample_rate     = read_line_and_int(pb, &error);  // audio bitrate
-        ast->codec->channels        = read_line_and_int(pb, &error);  // number of audio channels
-        ast->codec->bits_per_coded_sample = read_line_and_int(pb, &error);  // audio bits per sample
+        ast->codecpar->codec_type      = AVMEDIA_TYPE_AUDIO;
+        ast->codecpar->codec_tag       = audio_format;
+        ast->codecpar->sample_rate     = read_line_and_int(pb, &error);  // audio bitrate
+        ast->codecpar->channels        = read_line_and_int(pb, &error);  // number of audio channels
+        ast->codecpar->bits_per_coded_sample = read_line_and_int(pb, &error);  // audio bits per sample
         // At least one sample uses 0 for ADPCM, which is really 4 bits
         // per sample.
-        if (ast->codec->bits_per_coded_sample == 0)
-            ast->codec->bits_per_coded_sample = 4;
+        if (ast->codecpar->bits_per_coded_sample == 0)
+            ast->codecpar->bits_per_coded_sample = 4;
 
-        ast->codec->bit_rate = ast->codec->sample_rate *
-                               ast->codec->bits_per_coded_sample *
-                               ast->codec->channels;
+        ast->codecpar->bit_rate = ast->codecpar->sample_rate *
+                                  ast->codecpar->bits_per_coded_sample *
+                                  ast->codecpar->channels;
 
-        ast->codec->codec_id = AV_CODEC_ID_NONE;
+        ast->codecpar->codec_id = AV_CODEC_ID_NONE;
         switch (audio_format) {
             case 1:
-                if (ast->codec->bits_per_coded_sample == 16) {
+                if (ast->codecpar->bits_per_coded_sample == 16) {
                     // 16-bit audio is always signed
-                    ast->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
+                    ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
                     break;
                 }
                 // There are some other formats listed as legal per the spec;
                 // samples needed.
                 break;
             case 101:
-                if (ast->codec->bits_per_coded_sample == 8) {
+                if (ast->codecpar->bits_per_coded_sample == 8) {
                     // The samples with this kind of audio that I have
                     // are all unsigned.
-                    ast->codec->codec_id = AV_CODEC_ID_PCM_U8;
+                    ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
                     break;
-                } else if (ast->codec->bits_per_coded_sample == 4) {
-                    ast->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_EA_SEAD;
+                } else if (ast->codecpar->bits_per_coded_sample == 4) {
+                    ast->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_EA_SEAD;
                     break;
                 }
                 break;
         }
-        if (ast->codec->codec_id == AV_CODEC_ID_NONE)
+        if (ast->codecpar->codec_id == AV_CODEC_ID_NONE)
             avpriv_request_sample(s, "Audio format %"PRId32,
                                   audio_format);
-        avpriv_set_pts_info(ast, 32, 1, ast->codec->bit_rate);
+        avpriv_set_pts_info(ast, 32, 1, ast->codecpar->bit_rate);
     } else {
         for (i = 0; i < 3; i++)
             error |= read_line(pb, line, sizeof(line));
     }
 
     rpl->frames_per_chunk = read_line_and_int(pb, &error);  // video frames per chunk
-    if (rpl->frames_per_chunk > 1 && vst->codec->codec_tag != 124)
+    if (rpl->frames_per_chunk > 1 && vst->codecpar->codec_tag != 124)
         av_log(s, AV_LOG_WARNING,
                "Don't know how to split frames for video format %i. "
-               "Video stream will be broken!\n", vst->codec->codec_tag);
+               "Video stream will be broken!\n", vst->codecpar->codec_tag);
 
     number_of_chunks = read_line_and_int(pb, &error);  // number of chunks in the file
     // The number in the header is actually the index of the last chunk.
@@ -296,8 +296,8 @@ static int rpl_read_packet(AVFormatContext *s, AVPacket *pkt)
         if (avio_seek(pb, index_entry->pos, SEEK_SET) < 0)
             return AVERROR(EIO);
 
-    if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
-        stream->codec->codec_tag == 124) {
+    if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
+        stream->codecpar->codec_tag == 124) {
         // We have to split Escape 124 frames because there are
         // multiple frames per chunk in Escape 124 samples.
         uint32_t frame_size;
@@ -332,7 +332,7 @@ static int rpl_read_packet(AVFormatContext *s, AVPacket *pkt)
             return AVERROR(EIO);
         }
 
-        if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             // frames_per_chunk should always be one here; the header
             // parsing will warn if it isn't.
             pkt->duration = rpl->frames_per_chunk;
diff --git a/libavformat/rsd.c b/libavformat/rsd.c
index dd1f372..ee6fdfb 100644
--- a/libavformat/rsd.c
+++ b/libavformat/rsd.c
@@ -56,7 +56,7 @@ static int rsd_read_header(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
     int i, ret, version, start = 0x800;
-    AVCodecContext *codec;
+    AVCodecParameters *par;
     AVStream *st = avformat_new_stream(s, NULL);
 
     if (!st)
@@ -65,16 +65,16 @@ static int rsd_read_header(AVFormatContext *s)
     avio_skip(pb, 3); // "RSD"
     version = avio_r8(pb) - '0';
 
-    codec = st->codec;
-    codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    codec->codec_tag  = avio_rl32(pb);
-    codec->codec_id   = ff_codec_get_id(rsd_tags, codec->codec_tag);
-    if (!codec->codec_id) {
+    par = st->codecpar;
+    par->codec_type = AVMEDIA_TYPE_AUDIO;
+    par->codec_tag  = avio_rl32(pb);
+    par->codec_id   = ff_codec_get_id(rsd_tags, par->codec_tag);
+    if (!par->codec_id) {
         char tag_buf[32];
 
-        av_get_codec_tag_string(tag_buf, sizeof(tag_buf), codec->codec_tag);
+        av_get_codec_tag_string(tag_buf, sizeof(tag_buf), par->codec_tag);
         for (i=0; i < FF_ARRAY_ELEMS(rsd_unsupported_tags); i++) {
-            if (codec->codec_tag == rsd_unsupported_tags[i]) {
+            if (par->codec_tag == rsd_unsupported_tags[i]) {
                 avpriv_request_sample(s, "Codec tag: %s", tag_buf);
                 return AVERROR_PATCHWELCOME;
             }
@@ -83,43 +83,43 @@ static int rsd_read_header(AVFormatContext *s)
         return AVERROR_INVALIDDATA;
     }
 
-    codec->channels = avio_rl32(pb);
-    if (!codec->channels)
+    par->channels = avio_rl32(pb);
+    if (!par->channels)
         return AVERROR_INVALIDDATA;
 
     avio_skip(pb, 4); // Bit depth
-    codec->sample_rate = avio_rl32(pb);
-    if (!codec->sample_rate)
+    par->sample_rate = avio_rl32(pb);
+    if (!par->sample_rate)
         return AVERROR_INVALIDDATA;
 
     avio_skip(pb, 4); // Unknown
 
-    switch (codec->codec_id) {
+    switch (par->codec_id) {
     case AV_CODEC_ID_XMA2:
-        codec->block_align = 2048;
-        ff_alloc_extradata(codec, 34);
-        if (!codec->extradata)
+        par->block_align = 2048;
+        ff_alloc_extradata(par, 34);
+        if (!par->extradata)
             return AVERROR(ENOMEM);
-        memset(codec->extradata, 0, 34);
+        memset(par->extradata, 0, 34);
         break;
     case AV_CODEC_ID_ADPCM_PSX:
-        codec->block_align = 16 * codec->channels;
+        par->block_align = 16 * par->channels;
         if (pb->seekable)
-            st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start);
+            st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start);
         break;
     case AV_CODEC_ID_ADPCM_IMA_RAD:
-        codec->block_align = 20 * codec->channels;
+        par->block_align = 20 * par->channels;
         if (pb->seekable)
-            st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start);
+            st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start);
         break;
     case AV_CODEC_ID_ADPCM_IMA_WAV:
         if (version == 2)
             start = avio_rl32(pb);
 
-        codec->bits_per_coded_sample = 4;
-        codec->block_align = 36 * codec->channels;
+        par->bits_per_coded_sample = 4;
+        par->block_align = 36 * par->channels;
         if (pb->seekable)
-            st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start);
+            st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start);
         break;
     case AV_CODEC_ID_ADPCM_THP_LE:
         /* RSD3GADP is mono, so only alloc enough memory
@@ -127,24 +127,24 @@ static int rsd_read_header(AVFormatContext *s)
 
         start = avio_rl32(pb);
 
-        if ((ret = ff_get_extradata(codec, s->pb, 32)) < 0)
+        if ((ret = ff_get_extradata(s, par, s->pb, 32)) < 0)
             return ret;
         if (pb->seekable)
-            st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start);
+            st->duration = av_get_audio_frame_duration2(par, avio_size(pb) - start);
         break;
     case AV_CODEC_ID_ADPCM_THP:
-        codec->block_align = 8 * codec->channels;
+        par->block_align = 8 * par->channels;
         avio_skip(s->pb, 0x1A4 - avio_tell(s->pb));
 
-        if ((ret = ff_alloc_extradata(st->codec, 32 * st->codec->channels)) < 0)
+        if ((ret = ff_alloc_extradata(st->codecpar, 32 * par->channels)) < 0)
             return ret;
 
-        for (i = 0; i < st->codec->channels; i++) {
-            avio_read(s->pb, st->codec->extradata + 32 * i, 32);
+        for (i = 0; i < par->channels; i++) {
+            avio_read(s->pb, st->codecpar->extradata + 32 * i, 32);
             avio_skip(s->pb, 8);
         }
         if (pb->seekable)
-            st->duration = (avio_size(pb) - start) / (8 * st->codec->channels) * 14;
+            st->duration = (avio_size(pb) - start) / (8 * par->channels) * 14;
         break;
     case AV_CODEC_ID_PCM_S16LE:
     case AV_CODEC_ID_PCM_S16BE:
@@ -152,24 +152,24 @@ static int rsd_read_header(AVFormatContext *s)
             start = avio_rl32(pb);
 
         if (pb->seekable)
-            st->duration = (avio_size(pb) - start) / 2 / codec->channels;
+            st->duration = (avio_size(pb) - start) / 2 / par->channels;
         break;
     }
 
     avio_skip(pb, start - avio_tell(pb));
-    if (codec->codec_id == AV_CODEC_ID_XMA2) {
+    if (par->codec_id == AV_CODEC_ID_XMA2) {
         avio_skip(pb, avio_rb32(pb) + avio_rb32(pb));
         st->duration = avio_rb32(pb);
     }
 
-    avpriv_set_pts_info(st, 64, 1, codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, par->sample_rate);
 
     return 0;
 }
 
 static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int ret, size = 1024;
     int64_t pos;
 
@@ -177,20 +177,20 @@ static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt)
         return AVERROR_EOF;
 
     pos = avio_tell(s->pb);
-    if (codec->codec_id == AV_CODEC_ID_ADPCM_IMA_RAD ||
-        codec->codec_id == AV_CODEC_ID_ADPCM_PSX     ||
-        codec->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
-        codec->codec_id == AV_CODEC_ID_XMA2) {
-        ret = av_get_packet(s->pb, pkt, codec->block_align);
-    } else if (codec->codec_tag == MKTAG('W','A','D','P') &&
-               codec->channels > 1) {
+    if (par->codec_id == AV_CODEC_ID_ADPCM_IMA_RAD ||
+        par->codec_id == AV_CODEC_ID_ADPCM_PSX     ||
+        par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV ||
+        par->codec_id == AV_CODEC_ID_XMA2) {
+        ret = av_get_packet(s->pb, pkt, par->block_align);
+    } else if (par->codec_tag == MKTAG('W','A','D','P') &&
+               par->channels > 1) {
         int i, ch;
 
-        ret = av_new_packet(pkt, codec->block_align);
+        ret = av_new_packet(pkt, par->block_align);
         if (ret < 0)
             return ret;
         for (i = 0; i < 4; i++) {
-            for (ch = 0; ch < codec->channels; ch++) {
+            for (ch = 0; ch < par->channels; ch++) {
                 pkt->data[ch * 8 + i * 2 + 0] = avio_r8(s->pb);
                 pkt->data[ch * 8 + i * 2 + 1] = avio_r8(s->pb);
             }
@@ -200,7 +200,7 @@ static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt)
         ret = av_get_packet(s->pb, pkt, size);
     }
 
-    if (codec->codec_id == AV_CODEC_ID_XMA2 && pkt->size >= 1)
+    if (par->codec_id == AV_CODEC_ID_XMA2 && pkt->size >= 1)
         pkt->duration = (pkt->data[0] >> 2) * 512;
 
     pkt->pos = pos;
diff --git a/libavformat/rsodec.c b/libavformat/rsodec.c
index 6e3ea0a..b2d9a7c 100644
--- a/libavformat/rsodec.c
+++ b/libavformat/rsodec.c
@@ -59,13 +59,13 @@ static int rso_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     st->duration            = (size * 8) / bps;
-    st->codec->codec_type   = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_tag    = id;
-    st->codec->codec_id     = codec;
-    st->codec->channels     = 1;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    st->codec->sample_rate  = rate;
-    st->codec->block_align  = 1;
+    st->codecpar->codec_type   = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_tag    = id;
+    st->codecpar->codec_id     = codec;
+    st->codecpar->channels     = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->sample_rate  = rate;
+    st->codecpar->block_align  = 1;
 
     avpriv_set_pts_info(st, 64, 1, rate);
 
diff --git a/libavformat/rsoenc.c b/libavformat/rsoenc.c
index 6da9594..3c5c118 100644
--- a/libavformat/rsoenc.c
+++ b/libavformat/rsoenc.c
@@ -28,12 +28,12 @@
 static int rso_write_header(AVFormatContext *s)
 {
     AVIOContext  *pb  = s->pb;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (!enc->codec_tag)
+    if (!par->codec_tag)
         return AVERROR_INVALIDDATA;
 
-    if (enc->channels != 1) {
+    if (par->channels != 1) {
         av_log(s, AV_LOG_ERROR, "RSO only supports mono\n");
         return AVERROR_INVALIDDATA;
     }
@@ -44,20 +44,20 @@ static int rso_write_header(AVFormatContext *s)
     }
 
     /* XXX: find legal sample rates (if any) */
-    if (enc->sample_rate >= 1u<<16) {
+    if (par->sample_rate >= 1u<<16) {
         av_log(s, AV_LOG_ERROR, "Sample rate must be < 65536\n");
         return AVERROR_INVALIDDATA;
     }
 
-    if (enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
+    if (par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
         av_log(s, AV_LOG_ERROR, "ADPCM in RSO not implemented\n");
         return AVERROR_PATCHWELCOME;
     }
 
     /* format header */
-    avio_wb16(pb, enc->codec_tag);   /* codec ID */
+    avio_wb16(pb, par->codec_tag);   /* codec ID */
     avio_wb16(pb, 0);                /* data size, will be written at EOF */
-    avio_wb16(pb, enc->sample_rate);
+    avio_wb16(pb, par->sample_rate);
     avio_wb16(pb, 0x0000);           /* play mode ? (0x0000 = don't loop) */
 
     avio_flush(pb);
diff --git a/libavformat/rtmpcrypt.c b/libavformat/rtmpcrypt.c
index 811c74c..c41ae43 100644
--- a/libavformat/rtmpcrypt.c
+++ b/libavformat/rtmpcrypt.c
@@ -266,7 +266,7 @@ static int rtmpe_open(URLContext *h, const char *uri, int flags)
     /* open the tcp or ffrtmphttp connection */
     if ((ret = ffurl_open_whitelist(&rt->stream, url, AVIO_FLAG_READ_WRITE,
                                     &h->interrupt_callback, NULL,
-                                    h->protocol_whitelist)) < 0) {
+                                    h->protocol_whitelist, h->protocol_blacklist, h)) < 0) {
         rtmpe_close(h);
         return ret;
     }
@@ -325,7 +325,7 @@ static const AVClass ffrtmpcrypt_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_ffrtmpcrypt_protocol = {
+const URLProtocol ff_ffrtmpcrypt_protocol = {
     .name            = "ffrtmpcrypt",
     .url_open        = rtmpe_open,
     .url_read        = rtmpe_read,
diff --git a/libavformat/rtmpdh.c b/libavformat/rtmpdh.c
index 42ad72c..1876fd4 100644
--- a/libavformat/rtmpdh.c
+++ b/libavformat/rtmpdh.c
@@ -26,10 +26,18 @@
  * RTMP Diffie-Hellmann utilities
  */
 
+#include <stdint.h>
+#include <string.h>
+
 #include "config.h"
-#include "rtmpdh.h"
+
+#include "libavutil/attributes.h"
+#include "libavutil/error.h"
+#include "libavutil/mem.h"
 #include "libavutil/random_seed.h"
 
+#include "rtmpdh.h"
+
 #define P1024                                          \
     "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
     "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
@@ -361,142 +369,3 @@ fail:
 
     return ret;
 }
-
-#ifdef TEST
-static int test_random_shared_secret(void)
-{
-    FF_DH *peer1 = NULL, *peer2 = NULL;
-    int ret;
-    uint8_t pubkey1[128], pubkey2[128];
-    uint8_t sharedkey1[128], sharedkey2[128];
-
-    peer1 = ff_dh_init(1024);
-    peer2 = ff_dh_init(1024);
-    if (!peer1 || !peer2) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-    if ((ret = ff_dh_generate_public_key(peer1)) < 0)
-        goto fail;
-    if ((ret = ff_dh_generate_public_key(peer2)) < 0)
-        goto fail;
-    if ((ret = ff_dh_write_public_key(peer1, pubkey1, sizeof(pubkey1))) < 0)
-        goto fail;
-    if ((ret = ff_dh_write_public_key(peer2, pubkey2, sizeof(pubkey2))) < 0)
-        goto fail;
-    if ((ret = ff_dh_compute_shared_secret_key(peer1, pubkey2, sizeof(pubkey2),
-                                               sharedkey1, sizeof(sharedkey1))) < 0)
-        goto fail;
-    if ((ret = ff_dh_compute_shared_secret_key(peer2, pubkey1, sizeof(pubkey1),
-                                               sharedkey2, sizeof(sharedkey2))) < 0)
-        goto fail;
-    if (memcmp(sharedkey1, sharedkey2, sizeof(sharedkey1))) {
-        printf("Mismatched generated shared key\n");
-        ret = AVERROR_INVALIDDATA;
-    } else {
-        printf("Generated shared key ok\n");
-    }
-fail:
-    ff_dh_free(peer1);
-    ff_dh_free(peer2);
-    return ret;
-}
-
-static const char *private_key =
-    "976C18FCADC255B456564F74F3EEDA59D28AF6B744D743F2357BFD2404797EF896EF1A"
-    "7C1CBEAAA3AB60AF3192D189CFF3F991C9CBBFD78119FCA2181384B94011943B6D6F28"
-    "9E1B708E2D1A0C7771169293F03DA27E561F15F16F0AC9BC858C77A80FA98FD088A232"
-    "19D08BE6F165DE0B02034B18705829FAD0ACB26A5B75EF";
-static const char *public_key =
-    "F272ECF8362257C5D2C3CC2229CF9C0A03225BC109B1DBC76A68C394F256ACA3EF5F64"
-    "FC270C26382BF315C19E97A76104A716FC998A651E8610A3AE6CF65D8FAE5D3F32EEA0"
-    "0B32CB9609B494116A825D7142D17B88E3D20EDD98743DE29CF37A23A9F6A58B960591"
-    "3157D5965FCB46DDA73A1F08DD897BAE88DFE6FC937CBA";
-static const uint8_t public_key_bin[] = {
-    0xf2, 0x72, 0xec, 0xf8, 0x36, 0x22, 0x57, 0xc5, 0xd2, 0xc3, 0xcc, 0x22,
-    0x29, 0xcf, 0x9c, 0x0a, 0x03, 0x22, 0x5b, 0xc1, 0x09, 0xb1, 0xdb, 0xc7,
-    0x6a, 0x68, 0xc3, 0x94, 0xf2, 0x56, 0xac, 0xa3, 0xef, 0x5f, 0x64, 0xfc,
-    0x27, 0x0c, 0x26, 0x38, 0x2b, 0xf3, 0x15, 0xc1, 0x9e, 0x97, 0xa7, 0x61,
-    0x04, 0xa7, 0x16, 0xfc, 0x99, 0x8a, 0x65, 0x1e, 0x86, 0x10, 0xa3, 0xae,
-    0x6c, 0xf6, 0x5d, 0x8f, 0xae, 0x5d, 0x3f, 0x32, 0xee, 0xa0, 0x0b, 0x32,
-    0xcb, 0x96, 0x09, 0xb4, 0x94, 0x11, 0x6a, 0x82, 0x5d, 0x71, 0x42, 0xd1,
-    0x7b, 0x88, 0xe3, 0xd2, 0x0e, 0xdd, 0x98, 0x74, 0x3d, 0xe2, 0x9c, 0xf3,
-    0x7a, 0x23, 0xa9, 0xf6, 0xa5, 0x8b, 0x96, 0x05, 0x91, 0x31, 0x57, 0xd5,
-    0x96, 0x5f, 0xcb, 0x46, 0xdd, 0xa7, 0x3a, 0x1f, 0x08, 0xdd, 0x89, 0x7b,
-    0xae, 0x88, 0xdf, 0xe6, 0xfc, 0x93, 0x7c, 0xba
-};
-static const uint8_t peer_public_key[] = {
-    0x58, 0x66, 0x05, 0x49, 0x94, 0x23, 0x2b, 0x66, 0x52, 0x13, 0xff, 0x46,
-    0xf2, 0xb3, 0x79, 0xa9, 0xee, 0xae, 0x1a, 0x13, 0xf0, 0x71, 0x52, 0xfb,
-    0x93, 0x4e, 0xee, 0x97, 0x05, 0x73, 0x50, 0x7d, 0xaf, 0x02, 0x07, 0x72,
-    0xac, 0xdc, 0xa3, 0x95, 0x78, 0xee, 0x9a, 0x19, 0x71, 0x7e, 0x99, 0x9f,
-    0x2a, 0xd4, 0xb3, 0xe2, 0x0c, 0x1d, 0x1a, 0x78, 0x4c, 0xde, 0xf1, 0xad,
-    0xb4, 0x60, 0xa8, 0x51, 0xac, 0x71, 0xec, 0x86, 0x70, 0xa2, 0x63, 0x36,
-    0x92, 0x7c, 0xe3, 0x87, 0xee, 0xe4, 0xf1, 0x62, 0x24, 0x74, 0xb4, 0x04,
-    0xfa, 0x5c, 0xdf, 0xba, 0xfa, 0xa3, 0xc2, 0xbb, 0x62, 0x27, 0xd0, 0xf4,
-    0xe4, 0x43, 0xda, 0x8a, 0x88, 0x69, 0x60, 0xe2, 0xdb, 0x75, 0x2a, 0x98,
-    0x9d, 0xb5, 0x50, 0xe3, 0x99, 0xda, 0xe0, 0xa6, 0x14, 0xc9, 0x80, 0x12,
-    0xf9, 0x3c, 0xac, 0x06, 0x02, 0x7a, 0xde, 0x74
-};
-static const uint8_t shared_secret[] = {
-    0xb2, 0xeb, 0xcb, 0x71, 0xf3, 0x61, 0xfb, 0x5b, 0x4e, 0x5c, 0x4c, 0xcf,
-    0x5c, 0x08, 0x5f, 0x96, 0x26, 0x77, 0x1d, 0x31, 0xf1, 0xe1, 0xf7, 0x4b,
-    0x92, 0xac, 0x82, 0x2a, 0x88, 0xc7, 0x83, 0xe1, 0xc7, 0xf3, 0xd3, 0x1a,
-    0x7d, 0xc8, 0x31, 0xe3, 0x97, 0xe4, 0xec, 0x31, 0x0e, 0x8f, 0x73, 0x1a,
-    0xe4, 0xf6, 0xd8, 0xc8, 0x94, 0xff, 0xa0, 0x03, 0x84, 0x03, 0x0f, 0xa5,
-    0x30, 0x5d, 0x67, 0xe0, 0x7a, 0x3b, 0x5f, 0xed, 0x4c, 0xf5, 0xbc, 0x18,
-    0xea, 0xd4, 0x77, 0xa9, 0x07, 0xb3, 0x54, 0x0b, 0x02, 0xd9, 0xc6, 0xb8,
-    0x66, 0x5e, 0xec, 0xa4, 0xcd, 0x47, 0xed, 0xc9, 0x38, 0xc6, 0x91, 0x08,
-    0xf3, 0x85, 0x9b, 0x69, 0x16, 0x78, 0x0d, 0xb7, 0x74, 0x51, 0xaa, 0x5b,
-    0x4d, 0x74, 0xe4, 0x29, 0x2e, 0x9e, 0x8e, 0xf7, 0xe5, 0x42, 0x83, 0xb0,
-    0x65, 0xb0, 0xce, 0xc6, 0xb2, 0x8f, 0x5b, 0xb0
-};
-
-static int test_ref_data(void)
-{
-    FF_DH *dh;
-    int ret = AVERROR(ENOMEM);
-    uint8_t pubkey_test[128];
-    uint8_t sharedkey_test[128];
-
-    dh = ff_dh_init(1024);
-    if (!dh)
-        goto fail;
-    bn_hex2bn(dh->priv_key, private_key, ret);
-    if (!ret)
-        goto fail;
-    bn_hex2bn(dh->pub_key, public_key, ret);
-    if (!ret)
-        goto fail;
-    if ((ret = ff_dh_write_public_key(dh, pubkey_test, sizeof(pubkey_test))) < 0)
-        goto fail;
-    if (memcmp(pubkey_test, public_key_bin, sizeof(pubkey_test))) {
-        printf("Mismatched generated public key\n");
-        ret = AVERROR_INVALIDDATA;
-        goto fail;
-    } else {
-        printf("Generated public key ok\n");
-    }
-    if ((ret = ff_dh_compute_shared_secret_key(dh, peer_public_key, sizeof(peer_public_key),
-                                               sharedkey_test, sizeof(sharedkey_test))) < 0)
-        goto fail;
-    if (memcmp(shared_secret, sharedkey_test, sizeof(sharedkey_test))) {
-        printf("Mismatched generated shared key\n");
-        ret = AVERROR_INVALIDDATA;
-    } else {
-        printf("Generated shared key ok\n");
-    }
-fail:
-    ff_dh_free(dh);
-    return ret;
-}
-
-int main(void)
-{
-    if (test_random_shared_secret() < 0)
-        return 1;
-    if (test_ref_data() < 0)
-        return 1;
-    return 0;
-}
-#endif
diff --git a/libavformat/rtmpdh.h b/libavformat/rtmpdh.h
index 95b2620..2b250f5 100644
--- a/libavformat/rtmpdh.h
+++ b/libavformat/rtmpdh.h
@@ -22,7 +22,8 @@
 #ifndef AVFORMAT_RTMPDH_H
 #define AVFORMAT_RTMPDH_H
 
-#include "avformat.h"
+#include <stdint.h>
+
 #include "config.h"
 
 #if CONFIG_GMP || CONFIG_GCRYPT
diff --git a/libavformat/rtmphttp.c b/libavformat/rtmphttp.c
index 8ed5eb1..31f5d43 100644
--- a/libavformat/rtmphttp.c
+++ b/libavformat/rtmphttp.c
@@ -129,7 +129,7 @@ static int rtmp_http_read(URLContext *h, uint8_t *buf, int size)
             } else {
                 if (rt->nb_bytes_read == 0) {
                     /* Wait 50ms before retrying to read a server reply in
-                     * order to reduce the number of idle requets. */
+                     * order to reduce the number of idle requests. */
                     av_usleep(50000);
                 }
 
@@ -265,7 +265,7 @@ static const AVClass ffrtmphttp_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_ffrtmphttp_protocol = {
+const URLProtocol ff_ffrtmphttp_protocol = {
     .name           = "ffrtmphttp",
     .url_open       = rtmp_http_open,
     .url_read       = rtmp_http_read,
diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index a5485ab..95d1c1d 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -451,7 +451,7 @@ static int read_connect(URLContext *s, RTMPContext *rt)
                tmpstr, rt->app);
     ff_rtmp_packet_destroy(&pkt);
 
-    // Send Window Acknowledgement Size (as defined in speficication)
+    // Send Window Acknowledgement Size (as defined in specification)
     if ((ret = ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL,
                                      RTMP_PT_SERVER_BW, 0, 4)) < 0)
         return ret;
@@ -581,7 +581,7 @@ static int gen_release_stream(URLContext *s, RTMPContext *rt)
 
 /**
  * Generate 'FCPublish' call and send it to the server. It should make
- * the server preapare for receiving media streams.
+ * the server prepare for receiving media streams.
  */
 static int gen_fcpublish_stream(URLContext *s, RTMPContext *rt)
 {
@@ -1120,7 +1120,7 @@ static int rtmp_calc_swfhash(URLContext *s)
     /* Get the SWF player file. */
     if ((ret = ffurl_open_whitelist(&stream, rt->swfverify, AVIO_FLAG_READ,
                                     &s->interrupt_callback, NULL,
-                                    s->protocol_whitelist)) < 0) {
+                                    s->protocol_whitelist, s->protocol_blacklist, s)) < 0) {
         av_log(s, AV_LOG_ERROR, "Cannot open connection %s.\n", rt->swfverify);
         goto fail;
     }
@@ -2000,7 +2000,7 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
  * successful response, we will return set the value to number (otherwise number
  * will not be changed).
  *
- * @return 0 if reading the value succeeds, negative value otherwiss
+ * @return 0 if reading the value succeeds, negative value otherwise
  */
 static int read_number_result(RTMPPacket *pkt, double *number)
 {
@@ -2023,7 +2023,7 @@ static int read_number_result(RTMPPacket *pkt, double *number)
     // Value 3/4: Null
     if (ff_amf_read_null(&gbc))
         return AVERROR_INVALIDDATA;
-    // Value 4/4: The resonse as AMF_NUMBER
+    // Value 4/4: The response as AMF_NUMBER
     if (ff_amf_read_number(&gbc, &numbuffer))
         return AVERROR_INVALIDDATA;
     else
@@ -2514,7 +2514,7 @@ static int rtmp_close(URLContext *h)
  */
 static int inject_fake_duration_metadata(RTMPContext *rt)
 {
-    // We need to insert the metdata packet directly after the FLV
+    // We need to insert the metadata packet directly after the FLV
     // header, i.e. we need to move all other already read data by the
     // size of our fake metadata packet.
 
@@ -2650,7 +2650,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
 reconnect:
     if ((ret = ffurl_open_whitelist(&rt->stream, buf, AVIO_FLAG_READ_WRITE,
                                     &s->interrupt_callback, &opts,
-                                    s->protocol_whitelist)) < 0) {
+                                    s->protocol_whitelist, s->protocol_blacklist, s)) < 0) {
         av_log(s , AV_LOG_ERROR, "Cannot open connection %s\n", buf);
         goto fail;
     }
@@ -3110,7 +3110,7 @@ static const AVClass flavor##_class = {          \
     .version    = LIBAVUTIL_VERSION_INT,         \
 };                                               \
                                                  \
-URLProtocol ff_##flavor##_protocol = {           \
+const URLProtocol ff_##flavor##_protocol = {     \
     .name           = #flavor,                   \
     .url_open       = rtmp_open,                 \
     .url_read       = rtmp_read,                 \
diff --git a/libavformat/rtp.c b/libavformat/rtp.c
index 4d41350..4745e54 100644
--- a/libavformat/rtp.c
+++ b/libavformat/rtp.c
@@ -68,19 +68,19 @@ static const struct {
   {-1, "",           AVMEDIA_TYPE_UNKNOWN, AV_CODEC_ID_NONE, -1, -1}
 };
 
-int ff_rtp_get_codec_info(AVCodecContext *codec, int payload_type)
+int ff_rtp_get_codec_info(AVCodecParameters *par, int payload_type)
 {
     int i = 0;
 
     for (i = 0; rtp_payload_types[i].pt >= 0; i++)
         if (rtp_payload_types[i].pt == payload_type) {
             if (rtp_payload_types[i].codec_id != AV_CODEC_ID_NONE) {
-                codec->codec_type = rtp_payload_types[i].codec_type;
-                codec->codec_id = rtp_payload_types[i].codec_id;
+                par->codec_type = rtp_payload_types[i].codec_type;
+                par->codec_id = rtp_payload_types[i].codec_id;
                 if (rtp_payload_types[i].audio_channels > 0)
-                    codec->channels = rtp_payload_types[i].audio_channels;
+                    par->channels = rtp_payload_types[i].audio_channels;
                 if (rtp_payload_types[i].clock_rate > 0)
-                    codec->sample_rate = rtp_payload_types[i].clock_rate;
+                    par->sample_rate = rtp_payload_types[i].clock_rate;
                 return 0;
             }
         }
@@ -88,7 +88,7 @@ int ff_rtp_get_codec_info(AVCodecContext *codec, int payload_type)
 }
 
 int ff_rtp_get_payload_type(AVFormatContext *fmt,
-                            AVCodecContext *codec, int idx)
+                            AVCodecParameters *par, int idx)
 {
     int i;
     AVOutputFormat *ofmt = fmt ? fmt->oformat : NULL;
@@ -103,27 +103,27 @@ int ff_rtp_get_payload_type(AVFormatContext *fmt,
 
     /* static payload type */
     for (i = 0; rtp_payload_types[i].pt >= 0; ++i)
-        if (rtp_payload_types[i].codec_id == codec->codec_id) {
-            if (codec->codec_id == AV_CODEC_ID_H263 && (!fmt || !fmt->oformat ||
+        if (rtp_payload_types[i].codec_id == par->codec_id) {
+            if (par->codec_id == AV_CODEC_ID_H263 && (!fmt || !fmt->oformat ||
                 !fmt->oformat->priv_class || !fmt->priv_data ||
                 !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190")))
                 continue;
             /* G722 has 8000 as nominal rate even if the sample rate is 16000,
              * see section 4.5.2 in RFC 3551. */
-            if (codec->codec_id == AV_CODEC_ID_ADPCM_G722 &&
-                codec->sample_rate == 16000 && codec->channels == 1)
+            if (par->codec_id == AV_CODEC_ID_ADPCM_G722 &&
+                par->sample_rate == 16000 && par->channels == 1)
                 return rtp_payload_types[i].pt;
-            if (codec->codec_type == AVMEDIA_TYPE_AUDIO &&
+            if (par->codec_type == AVMEDIA_TYPE_AUDIO &&
                 ((rtp_payload_types[i].clock_rate > 0 &&
-                  codec->sample_rate != rtp_payload_types[i].clock_rate) ||
+                  par->sample_rate != rtp_payload_types[i].clock_rate) ||
                  (rtp_payload_types[i].audio_channels > 0 &&
-                  codec->channels != rtp_payload_types[i].audio_channels)))
+                  par->channels != rtp_payload_types[i].audio_channels)))
                 continue;
             return rtp_payload_types[i].pt;
         }
 
     if (idx < 0)
-        idx = codec->codec_type == AVMEDIA_TYPE_AUDIO;
+        idx = par->codec_type == AVMEDIA_TYPE_AUDIO;
 
     /* dynamic payload type */
     return RTP_PT_PRIVATE + idx;
diff --git a/libavformat/rtp.h b/libavformat/rtp.h
index 66a4f3a..54512c6 100644
--- a/libavformat/rtp.h
+++ b/libavformat/rtp.h
@@ -32,11 +32,11 @@
  * The format context private option payload_type overrides both.
  *
  * @param fmt   The context of the format
- * @param codec The context of the codec
+ * @param par   The codec parameters
  * @param idx   The stream index
  * @return The payload type (the 'PT' field in the RTP header).
  */
-int ff_rtp_get_payload_type(AVFormatContext *fmt, AVCodecContext *codec,
+int ff_rtp_get_payload_type(AVFormatContext *fmt, AVCodecParameters *par,
                             int idx);
 
 /**
@@ -46,12 +46,12 @@ int ff_rtp_get_payload_type(AVFormatContext *fmt, AVCodecContext *codec,
  * information depending on the payload type; for audio codecs, the
  * channels and sample_rate fields are also filled.
  *
- * @param codec The context of the codec
+ * @param par The codec parameters
  * @param payload_type The payload type (the 'PT' field in the RTP header)
  * @return In case of unknown payload type or dynamic payload type, a
  * negative value is returned; otherwise, 0 is returned
  */
-int ff_rtp_get_codec_info(AVCodecContext *codec, int payload_type);
+int ff_rtp_get_codec_info(AVCodecParameters *par, int payload_type);
 
 /**
  * Return the encoding name (as defined in
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index c3e50d4..786be9f 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -105,6 +105,7 @@ void ff_register_rtp_dynamic_payload_handlers(void)
     ff_register_dynamic_payload_handler(&ff_quicktime_rtp_vid_handler);
     ff_register_dynamic_payload_handler(&ff_svq3_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler);
+    ff_register_dynamic_payload_handler(&ff_vc2hq_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_vorbis_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_vp8_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_vp9_dynamic_handler);
@@ -150,8 +151,7 @@ static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf,
         switch (buf[1]) {
         case RTCP_SR:
             if (payload_len < 20) {
-                av_log(NULL, AV_LOG_ERROR,
-                       "Invalid length for RTCP SR packet\n");
+                av_log(s->ic, AV_LOG_ERROR, "Invalid RTCP SR packet length\n");
                 return AVERROR_INVALIDDATA;
             }
 
@@ -504,7 +504,7 @@ int ff_rtp_send_rtcp_feedback(RTPDemuxContext *s, URLContext *fd,
 
 /**
  * open a new RTP parse context for stream 'st'. 'st' can be NULL for
- * MPEG2-TS streams.
+ * MPEG-2 TS streams.
  */
 RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st,
                                    int payload_type, int queue_size)
@@ -521,17 +521,17 @@ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st,
     s->st                  = st;
     s->queue_size          = queue_size;
 
-    av_log(s->st ? s->st->codec : NULL, AV_LOG_VERBOSE,
-            "setting jitter buffer size to %d\n", s->queue_size);
+    av_log(s->ic, AV_LOG_VERBOSE, "setting jitter buffer size to %d\n",
+           s->queue_size);
 
     rtp_init_statistics(&s->statistics, 0);
     if (st) {
-        switch (st->codec->codec_id) {
+        switch (st->codecpar->codec_id) {
         case AV_CODEC_ID_ADPCM_G722:
             /* According to RFC 3551, the stream clock rate is 8000
              * even if the sample rate is 16000. */
-            if (st->codec->sample_rate == 8000)
-                st->codec->sample_rate = 16000;
+            if (st->codecpar->sample_rate == 8000)
+                st->codecpar->sample_rate = 16000;
             break;
         default:
             break;
@@ -623,7 +623,7 @@ static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt,
     st = s->st;
     // only do something with this if all the rtp checks pass...
     if (!rtp_valid_packet_in_sequence(&s->statistics, seq)) {
-        av_log(st ? st->codec : NULL, AV_LOG_ERROR,
+        av_log(s->ic, AV_LOG_ERROR,
                "RTP: PT=%02x: bad cseq %04x expected=%04x\n",
                payload_type, seq, ((s->seq + 1) & 0xffff));
         return -1;
@@ -737,7 +737,7 @@ static int rtp_parse_queued_packet(RTPDemuxContext *s, AVPacket *pkt)
         return -1;
 
     if (!has_next_packet(s))
-        av_log(s->st ? s->st->codec : NULL, AV_LOG_WARNING,
+        av_log(s->ic, AV_LOG_WARNING,
                "RTP: missed %d packets\n", s->queue->seq - s->seq - 1);
 
     /* Parse the first packet in the queue, and dequeue it */
@@ -804,7 +804,7 @@ static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt,
         int16_t diff = seq - s->seq;
         if (diff < 0) {
             /* Packet older than the previously emitted one, drop */
-            av_log(s->st ? s->st->codec : NULL, AV_LOG_WARNING,
+            av_log(s->ic, AV_LOG_WARNING,
                    "RTP: dropping old packet received too late\n");
             return -1;
         } else if (diff <= 1) {
@@ -820,8 +820,7 @@ static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt,
             /* Return the first enqueued packet if the queue is full,
              * even if we're missing something */
             if (s->queue_len >= s->queue_size) {
-                av_log(s->st ? s->st->codec : NULL, AV_LOG_WARNING,
-                       "jitter buffer full\n");
+                av_log(s->ic, AV_LOG_WARNING, "jitter buffer full\n");
                 return rtp_parse_queued_packet(s, pkt);
             }
             return -1;
@@ -846,7 +845,7 @@ int ff_rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
         return -1;
     rv = rtp_parse_one_packet(s, pkt, bufptr, len);
     s->prev_ret = rv;
-    while (rv == AVERROR(EAGAIN) && has_next_packet(s))
+    while (rv < 0 && has_next_packet(s))
         rv = rtp_parse_queued_packet(s, pkt);
     return rv ? rv : has_next_packet(s);
 }
@@ -871,7 +870,7 @@ int ff_parse_fmtp(AVFormatContext *s,
     int value_size = strlen(p) + 1;
 
     if (!(value = av_malloc(value_size))) {
-        av_log(NULL, AV_LOG_ERROR, "Failed to allocate data for FMTP.\n");
+        av_log(s, AV_LOG_ERROR, "Failed to allocate data for FMTP.\n");
         return AVERROR(ENOMEM);
     }
 
diff --git a/libavformat/rtpdec_amr.c b/libavformat/rtpdec_amr.c
index 848db9d..8687e65 100644
--- a/libavformat/rtpdec_amr.c
+++ b/libavformat/rtpdec_amr.c
@@ -55,20 +55,20 @@ static int amr_handle_packet(AVFormatContext *ctx, PayloadContext *data,
     const uint8_t *speech_data;
     uint8_t *ptr;
 
-    if (st->codec->codec_id == AV_CODEC_ID_AMR_NB) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_AMR_NB) {
         frame_sizes = frame_sizes_nb;
-    } else if (st->codec->codec_id == AV_CODEC_ID_AMR_WB) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_AMR_WB) {
         frame_sizes = frame_sizes_wb;
     } else {
         av_log(ctx, AV_LOG_ERROR, "Bad codec ID\n");
         return AVERROR_INVALIDDATA;
     }
 
-    if (st->codec->channels != 1) {
+    if (st->codecpar->channels != 1) {
         av_log(ctx, AV_LOG_ERROR, "Only mono AMR is supported\n");
         return AVERROR_INVALIDDATA;
     }
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
 
     /* The AMR RTP packet consists of one header byte, followed
      * by one TOC byte for each AMR frame in the packet, followed
diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c
index 2b1ddf1..8459a51 100644
--- a/libavformat/rtpdec_asf.c
+++ b/libavformat/rtpdec_asf.c
@@ -131,7 +131,7 @@ int ff_wms_parse_sdp_a_line(AVFormatContext *s, const char *p)
         rt->asf_ctx->pb      = &pb;
         av_dict_set(&opts, "no_resync_search", "1", 0);
 
-        if ((ret = ff_copy_whitelists(rt->asf_ctx, s)) < 0) {
+        if ((ret = ff_copy_whiteblacklists(rt->asf_ctx, s)) < 0) {
             av_dict_free(&opts);
             return ret;
         }
@@ -165,12 +165,10 @@ static int asfrtp_parse_sdp_line(AVFormatContext *s, int stream_index,
 
             for (i = 0; i < rt->asf_ctx->nb_streams; i++) {
                 if (s->streams[stream_index]->id == rt->asf_ctx->streams[i]->id) {
-                    *s->streams[stream_index]->codec =
-                        *rt->asf_ctx->streams[i]->codec;
+                    avcodec_parameters_copy(s->streams[stream_index]->codecpar,
+                                            rt->asf_ctx->streams[i]->codecpar);
                     s->streams[stream_index]->need_parsing =
                         rt->asf_ctx->streams[i]->need_parsing;
-                    rt->asf_ctx->streams[i]->codec->extradata_size = 0;
-                    rt->asf_ctx->streams[i]->codec->extradata = NULL;
                     avpriv_set_pts_info(s->streams[stream_index], 32, 1, 1000);
                 }
            }
diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
index 50a2f4c..cf251a5 100644
--- a/libavformat/rtpdec_formats.h
+++ b/libavformat/rtpdec_formats.h
@@ -45,7 +45,7 @@ int ff_h264_handle_aggregated_packet(AVFormatContext *ctx, PayloadContext *data,
 int ff_h264_handle_frag_packet(AVPacket *pkt, const uint8_t *buf, int len,
                                int start_bit, const uint8_t *nal_header,
                                int nal_header_len);
-void ff_h264_parse_framesize(AVCodecContext *codec, const char *p);
+void ff_h264_parse_framesize(AVCodecParameters *par, const char *p);
 
 extern RTPDynamicProtocolHandler ff_ac3_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler;
@@ -80,6 +80,7 @@ extern RTPDynamicProtocolHandler ff_quicktime_rtp_aud_handler;
 extern RTPDynamicProtocolHandler ff_quicktime_rtp_vid_handler;
 extern RTPDynamicProtocolHandler ff_svq3_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_theora_dynamic_handler;
+extern RTPDynamicProtocolHandler ff_vc2hq_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_vorbis_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_vp8_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_vp9_dynamic_handler;
diff --git a/libavformat/rtpdec_g726.c b/libavformat/rtpdec_g726.c
index 7e9ef56..172a4b3 100644
--- a/libavformat/rtpdec_g726.c
+++ b/libavformat/rtpdec_g726.c
@@ -27,10 +27,10 @@ static av_cold int g726_ ## bitrate ##_init(AVFormatContext *s, int st_index, \
                                             PayloadContext *data) \
 { \
     AVStream *stream = s->streams[st_index]; \
-    AVCodecContext *codec = stream->codec; \
+    AVCodecParameters *par = stream->codecpar; \
 \
-    codec->bits_per_coded_sample = bitrate/8; \
-    codec->bit_rate = codec->bits_per_coded_sample * codec->sample_rate; \
+    par->bits_per_coded_sample = bitrate/8; \
+    par->bit_rate = par->bits_per_coded_sample * par->sample_rate; \
 \
     return 0; \
 } \
diff --git a/libavformat/rtpdec_h263_rfc2190.c b/libavformat/rtpdec_h263_rfc2190.c
index 33712e7..6ba2814 100644
--- a/libavformat/rtpdec_h263_rfc2190.c
+++ b/libavformat/rtpdec_h263_rfc2190.c
@@ -107,7 +107,7 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data,
             /* Invalid src for this format, and bits that should be zero
              * according to RFC 2190 aren't zero. */
             av_log(ctx, AV_LOG_WARNING,
-                   "Interpreting H263 RTP data as RFC 2429/4629 even though "
+                   "Interpreting H.263 RTP data as RFC 2429/4629 even though "
                    "signalled with a static payload type.\n");
             data->newformat = 1;
             return ff_h263_handle_packet(ctx, data, st, pkt, timestamp, buf,
diff --git a/libavformat/rtpdec_h264.c b/libavformat/rtpdec_h264.c
index b399be4..8dd56a5 100644
--- a/libavformat/rtpdec_h264.c
+++ b/libavformat/rtpdec_h264.c
@@ -1,5 +1,5 @@
 /*
- * RTP H264 Protocol (RFC3984)
+ * RTP H.264 Protocol (RFC3984)
  * Copyright (c) 2006 Ryan Martell
  *
  * This file is part of FFmpeg.
@@ -146,7 +146,7 @@ static int sdp_parse_fmtp_config_h264(AVFormatContext *s,
                                       PayloadContext *h264_data,
                                       const char *attr, const char *value)
 {
-    AVCodecContext *codec = stream->codec;
+    AVCodecParameters *par = stream->codecpar;
 
     if (!strcmp(attr, "packetization-mode")) {
         av_log(s, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
@@ -166,18 +166,22 @@ static int sdp_parse_fmtp_config_h264(AVFormatContext *s,
             parse_profile_level_id(s, h264_data, value);
     } else if (!strcmp(attr, "sprop-parameter-sets")) {
         int ret;
-        codec->extradata_size = 0;
-        av_freep(&codec->extradata);
-        ret = ff_h264_parse_sprop_parameter_sets(s, &codec->extradata,
-                                                 &codec->extradata_size, value);
+        if (value[strlen(value) - 1] == ',') {
+            av_log(s, AV_LOG_WARNING, "Missing PPS in sprop-parameter-sets, ignoring\n");
+            return 0;
+        }
+        par->extradata_size = 0;
+        av_freep(&par->extradata);
+        ret = ff_h264_parse_sprop_parameter_sets(s, &par->extradata,
+                                                 &par->extradata_size, value);
         av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)\n",
-               codec->extradata, codec->extradata_size);
+               par->extradata, par->extradata_size);
         return ret;
     }
     return 0;
 }
 
-void ff_h264_parse_framesize(AVCodecContext *codec, const char *p)
+void ff_h264_parse_framesize(AVCodecParameters *par, const char *p)
 {
     char buf1[50];
     char *dst = buf1;
@@ -195,8 +199,8 @@ void ff_h264_parse_framesize(AVCodecContext *codec, const char *p)
 
     // a='framesize:96 320-240'
     // set our parameters
-    codec->width   = atoi(buf1);
-    codec->height  = atoi(p + 1); // skip the -
+    par->width   = atoi(buf1);
+    par->height  = atoi(p + 1); // skip the -
 }
 
 int ff_h264_handle_aggregated_packet(AVFormatContext *ctx, PayloadContext *data, AVPacket *pkt,
@@ -285,7 +289,7 @@ static int h264_handle_packet_fu_a(AVFormatContext *ctx, PayloadContext *data, A
     uint8_t fu_indicator, fu_header, start_bit, nal_type, nal;
 
     if (len < 3) {
-        av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H264 RTP packet\n");
+        av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H.264 RTP packet\n");
         return AVERROR_INVALIDDATA;
     }
 
@@ -315,14 +319,14 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data,
     int result = 0;
 
     if (!len) {
-        av_log(ctx, AV_LOG_ERROR, "Empty H264 RTP packet\n");
+        av_log(ctx, AV_LOG_ERROR, "Empty H.264 RTP packet\n");
         return AVERROR_INVALIDDATA;
     }
     nal  = buf[0];
     type = nal & 0x1f;
 
-    /* Simplify the case (these are all the nal types used internally by
-     * the h264 codec). */
+    /* Simplify the case (these are all the NAL types used internally by
+     * the H.264 codec). */
     if (type >= 1 && type <= 23)
         type = 1;
     switch (type) {
@@ -347,10 +351,8 @@ static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data,
     case 26:                   // MTAP-16
     case 27:                   // MTAP-24
     case 29:                   // FU-B
-        av_log(ctx, AV_LOG_ERROR,
-               "Unhandled type (%d) (See RFC for implementation details)\n",
-               type);
-        result = AVERROR(ENOSYS);
+        avpriv_report_missing_feature(ctx, "RTP H.264 NAL unit type %d", type);
+        result = AVERROR_PATCHWELCOME;
         break;
 
     case 28:                   // FU-A (fragmented nal)
@@ -396,7 +398,7 @@ static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
     stream = s->streams[st_index];
 
     if (av_strstart(p, "framesize:", &p)) {
-        ff_h264_parse_framesize(stream->codec, p);
+        ff_h264_parse_framesize(stream->codecpar, p);
     } else if (av_strstart(p, "fmtp:", &p)) {
         return ff_parse_fmtp(s, stream, h264_data, p, sdp_parse_fmtp_config_h264);
     } else if (av_strstart(p, "cliprect:", &p)) {
diff --git a/libavformat/rtpdec_hevc.c b/libavformat/rtpdec_hevc.c
index 1f09a08..a0e3a7c 100644
--- a/libavformat/rtpdec_hevc.c
+++ b/libavformat/rtpdec_hevc.c
@@ -17,7 +17,6 @@
  * 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/avassert.h"
@@ -132,41 +131,41 @@ static av_cold int hevc_parse_sdp_line(AVFormatContext *ctx, int st_index,
                                        PayloadContext *hevc_data, const char *line)
 {
     AVStream *current_stream;
-    AVCodecContext *codec;
+    AVCodecParameters *par;
     const char *sdp_line_ptr = line;
 
     if (st_index < 0)
         return 0;
 
     current_stream = ctx->streams[st_index];
-    codec  = current_stream->codec;
+    par  = current_stream->codecpar;
 
     if (av_strstart(sdp_line_ptr, "framesize:", &sdp_line_ptr)) {
-        ff_h264_parse_framesize(codec, sdp_line_ptr);
+        ff_h264_parse_framesize(par, sdp_line_ptr);
     } else if (av_strstart(sdp_line_ptr, "fmtp:", &sdp_line_ptr)) {
         int ret = ff_parse_fmtp(ctx, current_stream, hevc_data, sdp_line_ptr,
                                 hevc_sdp_parse_fmtp_config);
         if (hevc_data->vps_size || hevc_data->sps_size ||
             hevc_data->pps_size || hevc_data->sei_size) {
-            av_freep(&codec->extradata);
-            codec->extradata_size = hevc_data->vps_size + hevc_data->sps_size +
-                                    hevc_data->pps_size + hevc_data->sei_size;
-            codec->extradata = av_malloc(codec->extradata_size +
-                                         AV_INPUT_BUFFER_PADDING_SIZE);
-            if (!codec->extradata) {
+            av_freep(&par->extradata);
+            par->extradata_size = hevc_data->vps_size + hevc_data->sps_size +
+                                  hevc_data->pps_size + hevc_data->sei_size;
+            par->extradata = av_malloc(par->extradata_size +
+                                       AV_INPUT_BUFFER_PADDING_SIZE);
+            if (!par->extradata) {
                 ret = AVERROR(ENOMEM);
-                codec->extradata_size = 0;
+                par->extradata_size = 0;
             } else {
                 int pos = 0;
-                memcpy(codec->extradata + pos, hevc_data->vps, hevc_data->vps_size);
+                memcpy(par->extradata + pos, hevc_data->vps, hevc_data->vps_size);
                 pos += hevc_data->vps_size;
-                memcpy(codec->extradata + pos, hevc_data->sps, hevc_data->sps_size);
+                memcpy(par->extradata + pos, hevc_data->sps, hevc_data->sps_size);
                 pos += hevc_data->sps_size;
-                memcpy(codec->extradata + pos, hevc_data->pps, hevc_data->pps_size);
+                memcpy(par->extradata + pos, hevc_data->pps, hevc_data->pps_size);
                 pos += hevc_data->pps_size;
-                memcpy(codec->extradata + pos, hevc_data->sei, hevc_data->sei_size);
+                memcpy(par->extradata + pos, hevc_data->sei, hevc_data->sei_size);
                 pos += hevc_data->sei_size;
-                memset(codec->extradata + pos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+                memset(par->extradata + pos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
             }
 
             av_freep(&hevc_data->vps);
diff --git a/libavformat/rtpdec_ilbc.c b/libavformat/rtpdec_ilbc.c
index 82109e1..cb48f76 100644
--- a/libavformat/rtpdec_ilbc.c
+++ b/libavformat/rtpdec_ilbc.c
@@ -31,10 +31,10 @@ static int ilbc_parse_fmtp(AVFormatContext *s,
         int mode = atoi(value);
         switch (mode) {
         case 20:
-            stream->codec->block_align = 38;
+            stream->codecpar->block_align = 38;
             break;
         case 30:
-            stream->codec->block_align = 50;
+            stream->codecpar->block_align = 50;
             break;
         default:
             av_log(s, AV_LOG_ERROR, "Unsupported iLBC mode %d\n", mode);
@@ -58,7 +58,7 @@ static int ilbc_parse_sdp_line(AVFormatContext *s, int st_index,
         int ret = ff_parse_fmtp(s, st, data, p, ilbc_parse_fmtp);
         if (ret < 0)
             return ret;
-        if (!st->codec->block_align) {
+        if (!st->codecpar->block_align) {
             av_log(s, AV_LOG_ERROR, "No iLBC mode set\n");
             return AVERROR(EINVAL);
         }
diff --git a/libavformat/rtpdec_latm.c b/libavformat/rtpdec_latm.c
index aebba57..e51f0cd 100644
--- a/libavformat/rtpdec_latm.c
+++ b/libavformat/rtpdec_latm.c
@@ -115,13 +115,13 @@ static int parse_fmtp_config(AVStream *st, const char *value)
         ret = AVERROR_PATCHWELCOME;
         goto end;
     }
-    av_freep(&st->codec->extradata);
-    if (ff_alloc_extradata(st->codec, (get_bits_left(&gb) + 7)/8)) {
+    av_freep(&st->codecpar->extradata);
+    if (ff_alloc_extradata(st->codecpar, (get_bits_left(&gb) + 7)/8)) {
         ret = AVERROR(ENOMEM);
         goto end;
     }
-    for (i = 0; i < st->codec->extradata_size; i++)
-        st->codec->extradata[i] = get_bits(&gb, 8);
+    for (i = 0; i < st->codecpar->extradata_size; i++)
+        st->codecpar->extradata[i] = get_bits(&gb, 8);
 
 end:
     av_free(config);
diff --git a/libavformat/rtpdec_mpeg12.c b/libavformat/rtpdec_mpeg12.c
index e6185ea..b93de3d 100644
--- a/libavformat/rtpdec_mpeg12.c
+++ b/libavformat/rtpdec_mpeg12.c
@@ -34,7 +34,7 @@ static int mpeg_parse_packet(AVFormatContext *ctx, PayloadContext *data,
     h    = AV_RB32(buf);
     buf += 4;
     len -= 4;
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && h & (1 << 26)) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && h & (1 << 26)) {
         /* MPEG-2 */
         if (len <= 4)
             return AVERROR_INVALIDDATA;
diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c
index 70e51f8..304699e 100644
--- a/libavformat/rtpdec_mpeg4.c
+++ b/libavformat/rtpdec_mpeg4.c
@@ -22,7 +22,7 @@
 
 /**
  * @file
- * @brief MPEG4 / RTP Code
+ * @brief MPEG-4 / RTP Code
  * @author Fabrice Bellard
  * @author Romain Degez
  */
@@ -97,14 +97,14 @@ static void close_context(PayloadContext *data)
     av_freep(&data->mode);
 }
 
-static int parse_fmtp_config(AVCodecContext *codec, const char *value)
+static int parse_fmtp_config(AVCodecParameters *par, char *value)
 {
     /* decode the hexa encoded parameter */
     int len = ff_hex_to_data(NULL, value);
-    av_freep(&codec->extradata);
-    if (ff_alloc_extradata(codec, len))
+    av_freep(&par->extradata);
+    if (ff_alloc_extradata(par, len))
         return AVERROR(ENOMEM);
-    ff_hex_to_data(codec->extradata, value);
+    ff_hex_to_data(par->extradata, value);
     return 0;
 }
 
@@ -274,17 +274,17 @@ static int parse_fmtp(AVFormatContext *s,
                       AVStream *stream, PayloadContext *data,
                       const char *attr, const char *value)
 {
-    AVCodecContext *codec = stream->codec;
+    AVCodecParameters *par = stream->codecpar;
     int res, i;
 
     if (!strcmp(attr, "config")) {
-        res = parse_fmtp_config(codec, value);
+        res = parse_fmtp_config(par, value);
 
         if (res < 0)
             return res;
     }
 
-    if (codec->codec_id == AV_CODEC_ID_AAC) {
+    if (par->codec_id == AV_CODEC_ID_AAC) {
         /* Looking for a known attribute */
         for (i = 0; attr_names[i].str; ++i) {
             if (!av_strcasecmp(attr, attr_names[i].str)) {
diff --git a/libavformat/rtpdec_qdm2.c b/libavformat/rtpdec_qdm2.c
index 22b419e..1f4fd5a 100644
--- a/libavformat/rtpdec_qdm2.c
+++ b/libavformat/rtpdec_qdm2.c
@@ -104,18 +104,18 @@ static int qdm2_parse_config(PayloadContext *qdm, AVStream *st,
             case 4: /* stream with extradata */
                 if (item_len < 30)
                     return AVERROR_INVALIDDATA;
-                av_freep(&st->codec->extradata);
-                if (ff_alloc_extradata(st->codec, 26 + item_len)) {
+                av_freep(&st->codecpar->extradata);
+                if (ff_alloc_extradata(st->codecpar, 26 + item_len)) {
                     return AVERROR(ENOMEM);
                 }
-                AV_WB32(st->codec->extradata, 12);
-                memcpy(st->codec->extradata + 4, "frma", 4);
-                memcpy(st->codec->extradata + 8, "QDM2", 4);
-                AV_WB32(st->codec->extradata + 12, 6 + item_len);
-                memcpy(st->codec->extradata + 16, "QDCA", 4);
-                memcpy(st->codec->extradata + 20, p + 2, item_len - 2);
-                AV_WB32(st->codec->extradata + 18 + item_len, 8);
-                AV_WB32(st->codec->extradata + 22 + item_len, 0);
+                AV_WB32(st->codecpar->extradata, 12);
+                memcpy(st->codecpar->extradata + 4, "frma", 4);
+                memcpy(st->codecpar->extradata + 8, "QDM2", 4);
+                AV_WB32(st->codecpar->extradata + 12, 6 + item_len);
+                memcpy(st->codecpar->extradata + 16, "QDCA", 4);
+                memcpy(st->codecpar->extradata + 20, p + 2, item_len - 2);
+                AV_WB32(st->codecpar->extradata + 18 + item_len, 8);
+                AV_WB32(st->codecpar->extradata + 22 + item_len, 0);
 
                 qdm->block_size = AV_RB32(p + 26);
                 break;
@@ -265,9 +265,9 @@ static int qdm2_parse_packet(AVFormatContext *s, PayloadContext *qdm,
              * carried within the RTP stream, not SDP. Here,
              * by setting codec_id to AV_CODEC_ID_QDM2, we are signalling
              * to the decoder that it is OK to initialize. */
-            st->codec->codec_id = AV_CODEC_ID_QDM2;
+            st->codecpar->codec_id = AV_CODEC_ID_QDM2;
         }
-        if (st->codec->codec_id == AV_CODEC_ID_NONE)
+        if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
             return AVERROR(EAGAIN);
 
         /* subpackets */
diff --git a/libavformat/rtpdec_qt.c b/libavformat/rtpdec_qt.c
index 2d1b58e..77a3ce4 100644
--- a/libavformat/rtpdec_qt.c
+++ b/libavformat/rtpdec_qt.c
@@ -93,7 +93,7 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
         if (pos + 12 > len)
             return AVERROR_INVALIDDATA;
 
-        skip_bits(&gb, 2); // has non-I frames:1, is sparse:1
+        skip_bits(&gb, 2); // has non-I-frames:1, is sparse:1
         is_start  = get_bits1(&gb);
         is_finish = get_bits1(&gb);
         if (!is_start || !is_finish) {
@@ -106,9 +106,9 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt,
 
         avio_seek(&pb, pos + 4, SEEK_SET);
         tag = avio_rl32(&pb);
-        if ((st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+        if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
                  tag != MKTAG('v','i','d','e')) ||
-            (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
+            (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
                  tag != MKTAG('s','o','u','n')))
             return AVERROR_INVALIDDATA;
         avpriv_set_pts_info(st, 32, 1, avio_rb32(&pb));
diff --git a/libavformat/rtpdec_svq3.c b/libavformat/rtpdec_svq3.c
index bad199f..18d79d2 100644
--- a/libavformat/rtpdec_svq3.c
+++ b/libavformat/rtpdec_svq3.c
@@ -59,22 +59,22 @@ static int svq3_parse_packet (AVFormatContext *s, PayloadContext *sv,
 
     if (config_packet) {
 
-        av_freep(&st->codec->extradata);
-        st->codec->extradata_size = 0;
+        av_freep(&st->codecpar->extradata);
+        st->codecpar->extradata_size = 0;
 
-        if (len < 2 || ff_alloc_extradata(st->codec, len + 8))
+        if (len < 2 || ff_alloc_extradata(st->codecpar, len + 8))
             return AVERROR_INVALIDDATA;
 
-        memcpy(st->codec->extradata, "SEQH", 4);
-        AV_WB32(st->codec->extradata + 4, len);
-        memcpy(st->codec->extradata + 8, buf, len);
+        memcpy(st->codecpar->extradata, "SEQH", 4);
+        AV_WB32(st->codecpar->extradata + 4, len);
+        memcpy(st->codecpar->extradata + 8, buf, len);
 
         /* We set codec_id to AV_CODEC_ID_NONE initially to
          * delay decoder initialization since extradata is
          * carried within the RTP stream, not SDP. Here,
          * by setting codec_id to AV_CODEC_ID_SVQ3, we are signalling
          * to the decoder that it is OK to initialize. */
-        st->codec->codec_id = AV_CODEC_ID_SVQ3;
+        st->codecpar->codec_id = AV_CODEC_ID_SVQ3;
 
         return AVERROR(EAGAIN);
     }
diff --git a/libavformat/rtpdec_vc2hq.c b/libavformat/rtpdec_vc2hq.c
new file mode 100644
index 0000000..8a3996a
--- /dev/null
+++ b/libavformat/rtpdec_vc2hq.c
@@ -0,0 +1,225 @@
+/*
+ * RTP parser for VC-2 HQ payload format (draft version 1) - experimental
+ * Copyright (c) 2016 Thomas Volkert <thomas at netzeal.de>
+ *
+ * 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/intreadwrite.h"
+#include "libavcodec/dirac.h"
+
+#include "avio_internal.h"
+#include "rtpdec_formats.h"
+
+#define RTP_VC2HQ_PL_HEADER_SIZE             4
+
+#define DIRAC_DATA_UNIT_HEADER_SIZE          13
+#define DIRAC_PIC_NR_SIZE                    4
+#define DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT      0xEC
+
+struct PayloadContext {
+    AVIOContext *buf;
+    uint32_t    frame_size;
+    uint32_t    frame_nr;
+    uint32_t    timestamp;
+    uint32_t    last_unit_size;
+    int         seen_sequence_header;
+};
+
+static const uint8_t start_sequence[] = { 'B', 'B', 'C', 'D' };
+
+static void fill_parse_info_header(PayloadContext *pl_ctx, uint8_t *buf,
+                                   uint8_t parse_code, uint32_t data_unit_size)
+{
+    memcpy(buf, start_sequence, sizeof(start_sequence));
+    buf[4]  = parse_code;
+    AV_WB32(&buf[5], data_unit_size);
+    AV_WB32(&buf[9], pl_ctx->last_unit_size);
+
+    pl_ctx->last_unit_size = data_unit_size;
+}
+
+static int vc2hq_handle_sequence_header(PayloadContext *pl_ctx, AVStream *st, AVPacket *pkt,
+                                        const uint8_t *buf, int len)
+{
+    int res;
+    uint32_t size = DIRAC_DATA_UNIT_HEADER_SIZE + len;
+
+    if ((res = av_new_packet(pkt, DIRAC_DATA_UNIT_HEADER_SIZE + len)) < 0)
+        return res;
+
+    fill_parse_info_header(pl_ctx, pkt->data, 0x00, size);
+    /* payload of seq. header */
+    memcpy(pkt->data + DIRAC_DATA_UNIT_HEADER_SIZE, buf, len);
+    pkt->stream_index = st->index;
+
+    pl_ctx->seen_sequence_header = 1;
+
+    return 0;
+}
+
+static int vc2hq_mark_end_of_sequence(PayloadContext *pl_ctx, AVStream *st, AVPacket *pkt)
+{
+    int res;
+    uint32_t size = 0;
+
+    /* create A/V packet */
+    if ((res = av_new_packet(pkt, DIRAC_DATA_UNIT_HEADER_SIZE)) < 0)
+        return res;
+
+    fill_parse_info_header(pl_ctx, pkt->data, 0x10, size);
+    pkt->stream_index = st->index;
+
+    pl_ctx->seen_sequence_header = 0;
+
+    return 0;
+}
+
+static int vc2hq_handle_frame_fragment(AVFormatContext *ctx, PayloadContext *pl_ctx, AVStream *st,
+                                       AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len,
+                                       int flags)
+{
+    int res;
+    uint32_t pic_nr;
+    uint16_t frag_len;
+    uint16_t no_slices;
+
+    /* sanity check for size of input packet: 16 bytes header in any case as minimum */
+    if (len < 16) {
+        av_log(ctx, AV_LOG_ERROR, "Too short RTP/VC2hq packet, got %d bytes\n", len);
+        return AVERROR_INVALIDDATA;
+    }
+
+    pic_nr = AV_RB32(&buf[4]);
+    frag_len = AV_RB16(&buf[12]);
+    no_slices = AV_RB16(&buf[14]);
+
+    if (pl_ctx->buf && pl_ctx->frame_nr != pic_nr) {
+        av_log(ctx, AV_LOG_WARNING, "Dropping buffered RTP/VC2hq packet fragments - non-continuous picture numbers\n");
+        ffio_free_dyn_buf(&pl_ctx->buf);
+    }
+
+    /* transform parameters? */
+    if (no_slices == 0) {
+        if (len < frag_len + 16) {
+            av_log(ctx, AV_LOG_ERROR, "Too short RTP/VC2hq packet, got %d bytes\n", len);
+            return AVERROR_INVALIDDATA;
+        }
+
+        /* start frame buffering with new dynamic buffer */
+        if (!pl_ctx->buf) {
+
+            res = avio_open_dyn_buf(&pl_ctx->buf);
+            if (res < 0)
+                return res;
+
+            /* reserve memory for frame header */
+            res = avio_seek(pl_ctx->buf, DIRAC_DATA_UNIT_HEADER_SIZE + DIRAC_PIC_NR_SIZE, SEEK_SET);
+            if (res < 0)
+                return res;
+
+            pl_ctx->frame_nr = pic_nr;
+            pl_ctx->timestamp = *timestamp;
+            pl_ctx->frame_size = DIRAC_DATA_UNIT_HEADER_SIZE + DIRAC_PIC_NR_SIZE;
+        }
+
+        avio_write(pl_ctx->buf, buf + 16 /* skip pl header */, frag_len);
+        pl_ctx->frame_size += frag_len;
+
+        return AVERROR(EAGAIN);
+    } else {
+        if (len < frag_len + 20) {
+            av_log(ctx, AV_LOG_ERROR, "Too short RTP/VC2hq packet, got %d bytes\n", len);
+            return AVERROR_INVALIDDATA;
+        }
+
+        /* transform parameters were missed, no buffer available */
+        if (!pl_ctx->buf)
+            return AVERROR_INVALIDDATA;
+
+        avio_write(pl_ctx->buf, buf + 20 /* skip pl header */, frag_len);
+        pl_ctx->frame_size += frag_len;
+
+        /* RTP marker bit means: last fragment of current frame was received;
+           otherwise, an additional fragment is needed for the current frame */
+        if (!(flags & RTP_FLAG_MARKER))
+            return AVERROR(EAGAIN);
+    }
+
+    /* close frame buffering and create A/V packet */
+    res = ff_rtp_finalize_packet(pkt, &pl_ctx->buf, st->index);
+    if (res < 0)
+        return res;
+
+    fill_parse_info_header(pl_ctx, pkt->data, DIRAC_PCODE_PICTURE_HQ, pl_ctx->frame_size);
+    AV_WB32(&pkt->data[13], pl_ctx->frame_nr);
+
+    pl_ctx->frame_size = 0;
+
+    return 0;
+}
+
+static int vc2hq_handle_packet(AVFormatContext *ctx, PayloadContext *pl_ctx,
+                               AVStream *st, AVPacket *pkt, uint32_t *timestamp,
+                               const uint8_t *buf, int len, uint16_t seq,
+                               int flags)
+{
+    uint8_t parse_code = 0;
+    int res = 0;
+
+    if (pl_ctx->buf && pl_ctx->timestamp != *timestamp) {
+        av_log(ctx, AV_LOG_WARNING, "Dropping buffered RTP/VC2hq packet fragments - non-continuous timestamps\n");
+        ffio_free_dyn_buf(&pl_ctx->buf);
+        pl_ctx->frame_size = 0;
+    }
+
+    /* sanity check for size of input packet: needed header data as minimum */
+    if (len < RTP_VC2HQ_PL_HEADER_SIZE) {
+        av_log(ctx, AV_LOG_ERROR, "Too short RTP/VC2hq packet, got %d bytes\n", len);
+        return AVERROR_INVALIDDATA;
+    }
+
+    parse_code = buf[3];
+
+    /* wait for next sequence header? */
+    if (pl_ctx->seen_sequence_header || parse_code == DIRAC_PCODE_SEQ_HEADER) {
+        switch(parse_code) {
+        /* sequence header */
+        case DIRAC_PCODE_SEQ_HEADER:
+            res = vc2hq_handle_sequence_header(pl_ctx, st, pkt, buf + RTP_VC2HQ_PL_HEADER_SIZE, len - RTP_VC2HQ_PL_HEADER_SIZE);
+            break;
+        /* end of sequence */
+        case DIRAC_PCODE_END_SEQ:
+            res = vc2hq_mark_end_of_sequence(pl_ctx, st, pkt);
+            break;
+        /* HQ picture fragment */
+        case DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT:
+            res = vc2hq_handle_frame_fragment(ctx, pl_ctx, st, pkt, timestamp, buf, len, flags);
+            break;
+        }
+    }
+
+    return res;
+}
+
+RTPDynamicProtocolHandler ff_vc2hq_dynamic_handler = {
+    .enc_name         = "VC2",
+    .codec_type       = AVMEDIA_TYPE_VIDEO,
+    .codec_id         = AV_CODEC_ID_DIRAC,
+    .priv_data_size   = sizeof(PayloadContext),
+    .parse_packet     = vc2hq_handle_packet
+};
diff --git a/libavformat/rtpdec_vp8.c b/libavformat/rtpdec_vp8.c
index d1e355d..f0e457b 100644
--- a/libavformat/rtpdec_vp8.c
+++ b/libavformat/rtpdec_vp8.c
@@ -46,7 +46,7 @@ struct PayloadContext {
     int          prev_pictureid;
     int          broken_frame;
     /* If sequence_dirty is set, we have lost some data (critical or
-     * non-critical) and decoding will have some sort of artefacts, and
+     * non-critical) and decoding will have some sort of artifacts, and
      * we thus should request a new keyframe.
      */
     int          sequence_dirty;
diff --git a/libavformat/rtpdec_vp9.c b/libavformat/rtpdec_vp9.c
index e50bede..4a7f934 100644
--- a/libavformat/rtpdec_vp9.c
+++ b/libavformat/rtpdec_vp9.c
@@ -1,5 +1,5 @@
 /*
- * RTP parser for VP9 payload format (draft version 0) - experimental
+ * RTP parser for VP9 payload format (draft version 02) - experimental
  * Copyright (c) 2015 Thomas Volkert <thomas at homer-conferencing.com>
  *
  * This file is part of FFmpeg.
@@ -45,8 +45,8 @@ static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
                              const uint8_t *buf, int len, uint16_t seq,
                              int flags)
 {
-    int has_pic_id, has_layer_idc, has_ref_idc, has_ss_data, has_su_data;
-    av_unused int pic_id = 0, non_key_frame = 0;
+    int has_pic_id, has_layer_idc, has_ref_idc, has_ss_data;
+    av_unused int pic_id = 0, non_key_frame = 0, inter_picture_layer_frame;
     av_unused int layer_temporal = -1, layer_spatial = -1, layer_quality = -1;
     int ref_fields = 0, has_ref_field_ext_pic_id = 0;
     int first_fragment, last_fragment;
@@ -68,24 +68,24 @@ static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
      *
      *      0 1 2 3 4 5 6 7
      *     +-+-+-+-+-+-+-+-+
-     *     |I|L|F|B|E|V|U|-| (REQUIRED)
+     *     |I|P|L|F|B|E|V|-| (REQUIRED)
      *     +-+-+-+-+-+-+-+-+
      *
      *     I: PictureID present
+     *     P: Inter-picture predicted layer frame
      *     L: Layer indices present
-     *     F: Reference indices present
+     *     F: Flexible mode
      *     B: Start of VP9 frame
      *     E: End of picture
      *     V: Scalability Structure (SS) present
-     *     U: Scalability Structure Update (SU) present
      */
     has_pic_id     = !!(buf[0] & 0x80);
-    has_layer_idc  = !!(buf[0] & 0x40);
-    has_ref_idc    = !!(buf[0] & 0x20);
-    first_fragment = !!(buf[0] & 0x10);
-    last_fragment  = !!(buf[0] & 0x08);
-    has_ss_data    = !!(buf[0] & 0x04);
-    has_su_data    = !!(buf[0] & 0x02);
+    inter_picture_layer_frame = !!(buf[0] & 0x40);
+    has_layer_idc  = !!(buf[0] & 0x20);
+    has_ref_idc    = !!(buf[0] & 0x10);
+    first_fragment = !!(buf[0] & 0x08);
+    last_fragment  = !!(buf[0] & 0x04);
+    has_ss_data    = !!(buf[0] & 0x02);
 
     rtp_m = !!(flags & RTP_FLAG_MARKER);
 
@@ -222,18 +222,64 @@ static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
      *   X: 1 if this layer index has an extended relative Picture ID.
      */
     if (has_ss_data) {
-        avpriv_report_missing_feature(ctx, "VP9 scalability structure data");
-        return AVERROR(ENOSYS);
-    }
-
-    /*
-     * decode the scalability update structure (SU)
-     *
-     *  spec. is tbd
-     */
-    if (has_su_data) {
-        avpriv_report_missing_feature(ctx, "VP9 scalability update structure data");
-        return AVERROR(ENOSYS);
+        int n_s, y, g, i;
+        if (len < 1) {
+            av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+            return AVERROR_INVALIDDATA;
+        }
+        n_s = buf[0] >> 5;
+        y = !!(buf[0] & 0x10);
+        g = !!(buf[0] & 0x08);
+        buf++;
+        len--;
+        if (n_s > 0) {
+            avpriv_report_missing_feature(ctx, "VP9 scalability structure with multiple layers");
+            return AVERROR_PATCHWELCOME;
+        }
+        if (y) {
+            if (len < 4 * (n_s + 1)) {
+                av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+                return AVERROR_INVALIDDATA;
+            }
+            for (i = 0; i < n_s + 1; i++) {
+                av_unused int w, h;
+                w = AV_RB16(buf);
+                h = AV_RB16(buf + 2);
+                buf += 4;
+                len -= 4;
+            }
+        }
+        if (g) {
+            int n_g;
+            if (len < 1) {
+                av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+                return AVERROR_INVALIDDATA;
+            }
+            n_g = buf[0];
+            buf++;
+            len--;
+            for (i = 0; i < n_g; i++) {
+                av_unused int t, u, r, j;
+                if (len < 1) {
+                    av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+                    return AVERROR_INVALIDDATA;
+                }
+                t = buf[0] >> 5;
+                u = !!(buf[0] & 0x10);
+                r = (buf[0] >> 2) & 0x03;
+                buf++;
+                len--;
+                if (len < r) {
+                    av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+                    return AVERROR_INVALIDDATA;
+                }
+                for (j = 0; j < r; j++) {
+                    av_unused int p_diff = buf[0];
+                    buf++;
+                    len--;
+                }
+            }
+        }
     }
 
     /*
@@ -279,11 +325,17 @@ static int vp9_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_vp9_ctx,
     return 0;
 }
 
+static void vp9_close_context(PayloadContext *vp9)
+{
+    ffio_free_dyn_buf(&vp9->buf);
+}
+
 RTPDynamicProtocolHandler ff_vp9_dynamic_handler = {
     .enc_name         = "VP9",
     .codec_type       = AVMEDIA_TYPE_VIDEO,
     .codec_id         = AV_CODEC_ID_VP9,
     .priv_data_size   = sizeof(PayloadContext),
     .init             = vp9_init,
+    .close            = vp9_close_context,
     .parse_packet     = vp9_handle_packet
 };
diff --git a/libavformat/rtpdec_xiph.c b/libavformat/rtpdec_xiph.c
index 6d9d0fd..26aef54 100644
--- a/libavformat/rtpdec_xiph.c
+++ b/libavformat/rtpdec_xiph.c
@@ -222,16 +222,17 @@ static int get_base128(const uint8_t ** buf, const uint8_t * buf_end)
  * Based off parse_packed_headers in Vorbis RTP
  */
 static int
-parse_packed_headers(const uint8_t * packed_headers,
+parse_packed_headers(AVFormatContext *s,
+                     const uint8_t * packed_headers,
                      const uint8_t * packed_headers_end,
-                     AVCodecContext * codec, PayloadContext * xiph_data)
+                     AVCodecParameters *par, PayloadContext * xiph_data)
 {
 
     unsigned num_packed, num_headers, length, length1, length2, extradata_alloc;
     uint8_t *ptr;
 
     if (packed_headers_end - packed_headers < 9) {
-        av_log(codec, AV_LOG_ERROR,
+        av_log(s, AV_LOG_ERROR,
                "Invalid %"PTRDIFF_SPECIFIER" byte packed header.",
                packed_headers_end - packed_headers);
         return AVERROR_INVALIDDATA;
@@ -245,7 +246,7 @@ parse_packed_headers(const uint8_t * packed_headers,
     length2            = get_base128(&packed_headers, packed_headers_end);
 
     if (num_packed != 1 || num_headers > 3) {
-        av_log(codec, AV_LOG_ERROR,
+        av_log(s, AV_LOG_ERROR,
                "Unimplemented number of headers: %d packed headers, %d headers\n",
                num_packed, num_headers);
         return AVERROR_PATCHWELCOME;
@@ -253,7 +254,7 @@ parse_packed_headers(const uint8_t * packed_headers,
 
     if (packed_headers_end - packed_headers != length ||
         length1 > length || length2 > length - length1) {
-        av_log(codec, AV_LOG_ERROR,
+        av_log(s, AV_LOG_ERROR,
                "Bad packed header lengths (%d,%d,%"PTRDIFF_SPECIFIER",%d)\n", length1,
                length2, packed_headers_end - packed_headers, length);
         return AVERROR_INVALIDDATA;
@@ -265,19 +266,19 @@ parse_packed_headers(const uint8_t * packed_headers,
      * -- AV_INPUT_BUFFER_PADDING_SIZE required */
     extradata_alloc = length + length/255 + 3 + AV_INPUT_BUFFER_PADDING_SIZE;
 
-    if (ff_alloc_extradata(codec, extradata_alloc)) {
-        av_log(codec, AV_LOG_ERROR, "Out of memory\n");
+    if (ff_alloc_extradata(par, extradata_alloc)) {
+        av_log(s, AV_LOG_ERROR, "Out of memory\n");
         return AVERROR(ENOMEM);
     }
-    ptr = codec->extradata;
+    ptr = par->extradata;
     *ptr++ = 2;
     ptr += av_xiphlacing(ptr, length1);
     ptr += av_xiphlacing(ptr, length2);
     memcpy(ptr, packed_headers, length);
     ptr += length;
-    codec->extradata_size = ptr - codec->extradata;
+    par->extradata_size = ptr - par->extradata;
     // clear out remaining parts of the buffer
-    memset(ptr, 0, extradata_alloc - codec->extradata_size);
+    memset(ptr, 0, extradata_alloc - par->extradata_size);
 
     return 0;
 }
@@ -287,16 +288,16 @@ static int xiph_parse_fmtp_pair(AVFormatContext *s,
                                 PayloadContext *xiph_data,
                                 const char *attr, const char *value)
 {
-    AVCodecContext *codec = stream->codec;
+    AVCodecParameters *par = stream->codecpar;
     int result = 0;
 
     if (!strcmp(attr, "sampling")) {
         if (!strcmp(value, "YCbCr-4:2:0")) {
-            codec->pix_fmt = AV_PIX_FMT_YUV420P;
+            par->format = AV_PIX_FMT_YUV420P;
         } else if (!strcmp(value, "YCbCr-4:4:2")) {
-            codec->pix_fmt = AV_PIX_FMT_YUV422P;
+            par->format = AV_PIX_FMT_YUV422P;
         } else if (!strcmp(value, "YCbCr-4:4:4")) {
-            codec->pix_fmt = AV_PIX_FMT_YUV444P;
+            par->format = AV_PIX_FMT_YUV444P;
         } else {
             av_log(s, AV_LOG_ERROR,
                    "Unsupported pixel format %s\n", attr);
@@ -305,12 +306,12 @@ static int xiph_parse_fmtp_pair(AVFormatContext *s,
     } else if (!strcmp(attr, "width")) {
         /* This is an integer between 1 and 1048561
          * and MUST be in multiples of 16. */
-        codec->width = atoi(value);
+        par->width = atoi(value);
         return 0;
     } else if (!strcmp(attr, "height")) {
         /* This is an integer between 1 and 1048561
          * and MUST be in multiples of 16. */
-        codec->height = atoi(value);
+        par->height = atoi(value);
         return 0;
     } else if (!strcmp(attr, "delivery-method")) {
         /* Possible values are: inline, in_band, out_band/specific_name. */
@@ -334,7 +335,7 @@ static int xiph_parse_fmtp_pair(AVFormatContext *s,
                     av_base64_decode(decoded_packet, value, decoded_alloc);
 
                 result = parse_packed_headers
-                    (decoded_packet, decoded_packet + packet_size, codec,
+                    (s, decoded_packet, decoded_packet + packet_size, par,
                     xiph_data);
             } else {
                 av_log(s, AV_LOG_ERROR,
diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
index 00b69f5..efa63a5 100644
--- a/libavformat/rtpenc.c
+++ b/libavformat/rtpenc.c
@@ -49,6 +49,7 @@ static const AVClass rtp_muxer_class = {
 static int is_supported(enum AVCodecID id)
 {
     switch(id) {
+    case AV_CODEC_ID_DIRAC:
     case AV_CODEC_ID_H261:
     case AV_CODEC_ID_H263:
     case AV_CODEC_ID_H263P:
@@ -74,6 +75,7 @@ static int is_supported(enum AVCodecID id)
     case AV_CODEC_ID_VORBIS:
     case AV_CODEC_ID_THEORA:
     case AV_CODEC_ID_VP8:
+    case AV_CODEC_ID_VP9:
     case AV_CODEC_ID_ADPCM_G722:
     case AV_CODEC_ID_ADPCM_G726:
     case AV_CODEC_ID_ILBC:
@@ -97,8 +99,8 @@ static int rtp_write_header(AVFormatContext *s1)
         return AVERROR(EINVAL);
     }
     st = s1->streams[0];
-    if (!is_supported(st->codec->codec_id)) {
-        av_log(s1, AV_LOG_ERROR, "Unsupported codec %s\n", avcodec_get_name(st->codec->codec_id));
+    if (!is_supported(st->codecpar->codec_id)) {
+        av_log(s1, AV_LOG_ERROR, "Unsupported codec %s\n", avcodec_get_name(st->codecpar->codec_id));
 
         return -1;
     }
@@ -106,7 +108,7 @@ static int rtp_write_header(AVFormatContext *s1)
     if (s->payload_type < 0) {
         /* Re-validate non-dynamic payload types */
         if (st->id < RTP_PT_PRIVATE)
-            st->id = ff_rtp_get_payload_type(s1, st->codec, -1);
+            st->id = ff_rtp_get_payload_type(s1, st->codecpar, -1);
 
         s->payload_type = st->id;
     } else {
@@ -152,13 +154,13 @@ static int rtp_write_header(AVFormatContext *s1)
     }
     s->max_payload_size = s1->packet_size - 12;
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-        avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+        avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate);
     } else {
         avpriv_set_pts_info(st, 32, 1, 90000);
     }
     s->buf_ptr = s->buf;
-    switch(st->codec->codec_id) {
+    switch(st->codecpar->codec_id) {
     case AV_CODEC_ID_MP2:
     case AV_CODEC_ID_MP3:
         s->buf_ptr = s->buf + 4;
@@ -173,10 +175,21 @@ static int rtp_write_header(AVFormatContext *s1)
             n = 1;
         s->max_payload_size = n * TS_PACKET_SIZE;
         break;
+    case AV_CODEC_ID_DIRAC:
+        if (s1->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
+            av_log(s, AV_LOG_ERROR,
+                   "Packetizing VC-2 is experimental and does not use all values "
+                   "of the specification "
+                   "(even though most receivers may handle it just fine). "
+                   "Please set -strict experimental in order to enable it.\n");
+            ret = AVERROR_EXPERIMENTAL;
+            goto fail;
+        }
+        break;
     case AV_CODEC_ID_H261:
         if (s1->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
             av_log(s, AV_LOG_ERROR,
-                   "Packetizing H261 is experimental and produces incorrect "
+                   "Packetizing H.261 is experimental and produces incorrect "
                    "packetization for cases where GOBs don't fit into packets "
                    "(even though most receivers may handle it just fine). "
                    "Please set -f_strict experimental in order to enable it.\n");
@@ -186,17 +199,27 @@ static int rtp_write_header(AVFormatContext *s1)
         break;
     case AV_CODEC_ID_H264:
         /* check for H.264 MP4 syntax */
-        if (st->codec->extradata_size > 4 && st->codec->extradata[0] == 1) {
-            s->nal_length_size = (st->codec->extradata[4] & 0x03) + 1;
+        if (st->codecpar->extradata_size > 4 && st->codecpar->extradata[0] == 1) {
+            s->nal_length_size = (st->codecpar->extradata[4] & 0x03) + 1;
         }
         break;
     case AV_CODEC_ID_HEVC:
         /* Only check for the standardized hvcC version of extradata, keeping
-         * things simple and similar to the avcC/H264 case above, instead
+         * things simple and similar to the avcC/H.264 case above, instead
          * of trying to handle the pre-standardization versions (as in
          * libavcodec/hevc.c). */
-        if (st->codec->extradata_size > 21 && st->codec->extradata[0] == 1) {
-            s->nal_length_size = (st->codec->extradata[21] & 0x03) + 1;
+        if (st->codecpar->extradata_size > 21 && st->codecpar->extradata[0] == 1) {
+            s->nal_length_size = (st->codecpar->extradata[21] & 0x03) + 1;
+        }
+        break;
+    case AV_CODEC_ID_VP9:
+        if (s1->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
+            av_log(s, AV_LOG_ERROR,
+                   "Packetizing VP9 is experimental and its specification is "
+                   "still in draft state. "
+                   "Please set -strict experimental in order to enable it.\n");
+            ret = AVERROR_EXPERIMENTAL;
+            goto fail;
         }
         break;
     case AV_CODEC_ID_VORBIS:
@@ -209,7 +232,7 @@ static int rtp_write_header(AVFormatContext *s1)
         avpriv_set_pts_info(st, 32, 1, 8000);
         break;
     case AV_CODEC_ID_OPUS:
-        if (st->codec->channels > 2) {
+        if (st->codecpar->channels > 2) {
             av_log(s1, AV_LOG_ERROR, "Multistream opus not supported in RTP\n");
             goto fail;
         }
@@ -219,16 +242,16 @@ static int rtp_write_header(AVFormatContext *s1)
         avpriv_set_pts_info(st, 32, 1, 48000);
         break;
     case AV_CODEC_ID_ILBC:
-        if (st->codec->block_align != 38 && st->codec->block_align != 50) {
+        if (st->codecpar->block_align != 38 && st->codecpar->block_align != 50) {
             av_log(s1, AV_LOG_ERROR, "Incorrect iLBC block size specified\n");
             goto fail;
         }
-        s->max_frames_per_packet = s->max_payload_size / st->codec->block_align;
+        s->max_frames_per_packet = s->max_payload_size / st->codecpar->block_align;
         break;
     case AV_CODEC_ID_AMR_NB:
     case AV_CODEC_ID_AMR_WB:
         s->max_frames_per_packet = 50;
-        if (st->codec->codec_id == AV_CODEC_ID_AMR_NB)
+        if (st->codecpar->codec_id == AV_CODEC_ID_AMR_NB)
             n = 31;
         else
             n = 61;
@@ -237,7 +260,7 @@ static int rtp_write_header(AVFormatContext *s1)
             av_log(s1, AV_LOG_ERROR, "RTP max payload size too small for AMR\n");
             goto fail;
         }
-        if (st->codec->channels != 1) {
+        if (st->codecpar->channels != 1) {
             av_log(s1, AV_LOG_ERROR, "Only mono is supported\n");
             goto fail;
         }
@@ -458,8 +481,8 @@ static int rtp_send_ilbc(AVFormatContext *s1, const uint8_t *buf, int size)
 {
     RTPMuxContext *s = s1->priv_data;
     AVStream *st = s1->streams[0];
-    int frame_duration = av_get_audio_frame_duration(st->codec, 0);
-    int frame_size = st->codec->block_align;
+    int frame_duration = av_get_audio_frame_duration2(st->codecpar, 0);
+    int frame_size = st->codecpar->block_align;
     int frames = size / frame_size;
 
     while (frames > 0) {
@@ -509,26 +532,26 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
     }
     s->cur_timestamp = s->base_timestamp + pkt->pts;
 
-    switch(st->codec->codec_id) {
+    switch(st->codecpar->codec_id) {
     case AV_CODEC_ID_PCM_MULAW:
     case AV_CODEC_ID_PCM_ALAW:
     case AV_CODEC_ID_PCM_U8:
     case AV_CODEC_ID_PCM_S8:
-        return rtp_send_samples(s1, pkt->data, size, 8 * st->codec->channels);
+        return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->channels);
     case AV_CODEC_ID_PCM_U16BE:
     case AV_CODEC_ID_PCM_U16LE:
     case AV_CODEC_ID_PCM_S16BE:
     case AV_CODEC_ID_PCM_S16LE:
-        return rtp_send_samples(s1, pkt->data, size, 16 * st->codec->channels);
+        return rtp_send_samples(s1, pkt->data, size, 16 * st->codecpar->channels);
     case AV_CODEC_ID_ADPCM_G722:
         /* The actual sample size is half a byte per sample, but since the
          * stream clock rate is 8000 Hz while the sample rate is 16000 Hz,
          * the correct parameter for send_samples_bits is 8 bits per stream
          * clock. */
-        return rtp_send_samples(s1, pkt->data, size, 8 * st->codec->channels);
+        return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->channels);
     case AV_CODEC_ID_ADPCM_G726:
         return rtp_send_samples(s1, pkt->data, size,
-                                st->codec->bits_per_coded_sample * st->codec->channels);
+                                st->codecpar->bits_per_coded_sample * st->codecpar->channels);
     case AV_CODEC_ID_MP2:
     case AV_CODEC_ID_MP3:
         rtp_send_mpegaudio(s1, pkt->data, size);
@@ -550,6 +573,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
     case AV_CODEC_ID_MPEG2TS:
         rtp_send_mpegts_raw(s1, pkt->data, size);
         break;
+    case AV_CODEC_ID_DIRAC:
+        ff_rtp_send_vc2hq(s1, pkt->data, size, st->codecpar->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0);
+        break;
     case AV_CODEC_ID_H264:
         ff_rtp_send_h264_hevc(s1, pkt->data, size);
         break;
@@ -579,6 +605,9 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
     case AV_CODEC_ID_VP8:
         ff_rtp_send_vp8(s1, pkt->data, size);
         break;
+    case AV_CODEC_ID_VP9:
+        ff_rtp_send_vp9(s1, pkt->data, size);
+        break;
     case AV_CODEC_ID_ILBC:
         rtp_send_ilbc(s1, pkt->data, size);
         break;
diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.h
index d34153f..62dc9ab 100644
--- a/libavformat/rtpenc.h
+++ b/libavformat/rtpenc.h
@@ -76,7 +76,7 @@ typedef struct RTPMuxContext RTPMuxContext;
     { "latm", "Use MP4A-LATM packetization instead of MPEG4-GENERIC for AAC", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_MP4A_LATM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
     { "rfc2190", "Use RFC 2190 packetization instead of RFC 4629 for H.263", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_RFC2190}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
     { "skip_rtcp", "Don't send RTCP sender reports", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_SKIP_RTCP}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
-    { "h264_mode0", "Use mode 0 for H264 in RTP", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_H264_MODE0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
+    { "h264_mode0", "Use mode 0 for H.264 in RTP", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_H264_MODE0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" }, \
     { "send_bye", "Send RTCP BYE packets when finishing", 0, AV_OPT_TYPE_CONST, {.i64 = FF_RTP_FLAG_SEND_BYE}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "rtpflags" } \
 
 void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m);
@@ -91,7 +91,9 @@ void ff_rtp_send_latm(AVFormatContext *s1, const uint8_t *buff, int size);
 void ff_rtp_send_amr(AVFormatContext *s1, const uint8_t *buff, int size);
 void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size);
 void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size);
+void ff_rtp_send_vc2hq(AVFormatContext *s1, const uint8_t *buf, int size, int interlaced);
 void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buff, int size);
+void ff_rtp_send_vp9(AVFormatContext *s1, const uint8_t *buff, int size);
 void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buff, int size);
 
 const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *av_restrict start,
diff --git a/libavformat/rtpenc_aac.c b/libavformat/rtpenc_aac.c
index f835183..fad8ea2 100644
--- a/libavformat/rtpenc_aac.c
+++ b/libavformat/rtpenc_aac.c
@@ -33,7 +33,7 @@ void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size)
     uint8_t *p;
 
     /* skip ADTS header, if present */
-    if ((s1->streams[0]->codec->extradata_size) == 0) {
+    if ((s1->streams[0]->codecpar->extradata_size) == 0) {
         size -= 7;
         buff += 7;
     }
diff --git a/libavformat/rtpenc_chain.c b/libavformat/rtpenc_chain.c
index 96e65ef..f768fb0 100644
--- a/libavformat/rtpenc_chain.c
+++ b/libavformat/rtpenc_chain.c
@@ -63,7 +63,7 @@ int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s,
     /* Get the payload type from the codec */
     if (st->id < RTP_PT_PRIVATE)
         rtpctx->streams[0]->id =
-            ff_rtp_get_payload_type(s, st->codec, idx);
+            ff_rtp_get_payload_type(s, st->codecpar, idx);
     else
         rtpctx->streams[0]->id = st->id;
 
@@ -74,7 +74,7 @@ int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s,
     /* Set the synchronized start time. */
     rtpctx->start_time_realtime = s->start_time_realtime;
 
-    avcodec_copy_context(rtpctx->streams[0]->codec, st->codec);
+    avcodec_parameters_copy(rtpctx->streams[0]->codecpar, st->codecpar);
     rtpctx->streams[0]->time_base = st->time_base;
 
     if (handle) {
diff --git a/libavformat/rtpenc_h261.c b/libavformat/rtpenc_h261.c
index fc50285..22461ca 100644
--- a/libavformat/rtpenc_h261.c
+++ b/libavformat/rtpenc_h261.c
@@ -72,12 +72,12 @@ void ff_rtp_send_h261(AVFormatContext *ctx, const uint8_t *frame_buf, int frame_
         rtp_ctx->buf[2] = 0; /* quant=0, hmvd=5 */
         rtp_ctx->buf[3] = 0; /* vmvd=0 */
         if (frame_size < 2 || frame_buf[0] != 0 || frame_buf[1] != 1) {
-            /* A full, correct fix for this would be to make the H261 encoder
+            /* A full, correct fix for this would be to make the H.261 encoder
              * support inserting extra GOB headers (triggered by setting e.g.
              * "-ps 1"), and including information about macroblock boundaries
              * (such as for h263_rfc2190). */
             av_log(ctx, AV_LOG_WARNING,
-                   "RTP/H261 packet not cut at a GOB boundary, not signaled correctly\n");
+                   "RTP/H.261 packet not cut at a GOB boundary, not signaled correctly\n");
         }
 
         cur_frame_size = FFMIN(rtp_ctx->max_payload_size - RTP_H261_HEADER_SIZE, frame_size);
diff --git a/libavformat/rtpenc_h263_rfc2190.c b/libavformat/rtpenc_h263_rfc2190.c
index 34b3906..3567202 100644
--- a/libavformat/rtpenc_h263_rfc2190.c
+++ b/libavformat/rtpenc_h263_rfc2190.c
@@ -114,7 +114,7 @@ void ff_rtp_send_h263_rfc2190(AVFormatContext *s1, const uint8_t *buf, int size,
     init_get_bits(&gb, buf, size*8);
     if (get_bits(&gb, 22) == 0x20) { /* Picture Start Code */
         info.tr  = get_bits(&gb, 8);
-        skip_bits(&gb, 2); /* PTYPE start, H261 disambiguation */
+        skip_bits(&gb, 2); /* PTYPE start, H.261 disambiguation */
         skip_bits(&gb, 3); /* Split screen, document camera, freeze picture release */
         info.src = get_bits(&gb, 3);
         info.i   = get_bits(&gb, 1);
@@ -168,7 +168,7 @@ void ff_rtp_send_h263_rfc2190(AVFormatContext *s1, const uint8_t *buf, int size,
                         mb_info_pos++;
                     }
                 } else {
-                    av_log(s1, AV_LOG_ERROR, "Unable to split H263 packet, "
+                    av_log(s1, AV_LOG_ERROR, "Unable to split H.263 packet, "
                            "use -mb_info %d or -ps 1.\n",
                            s->max_payload_size - 8);
                 }
diff --git a/libavformat/rtpenc_h264_hevc.c b/libavformat/rtpenc_h264_hevc.c
index 7234c7e..0c88fc2 100644
--- a/libavformat/rtpenc_h264_hevc.c
+++ b/libavformat/rtpenc_h264_hevc.c
@@ -40,7 +40,7 @@ static void flush_buffered(AVFormatContext *s1, int last)
         // If we're only sending one single NAL unit, send it as such, skip
         // the STAP-A/AP framing
         if (s->buffered_nals == 1) {
-            enum AVCodecID codec = s1->streams[0]->codec->codec_id;
+            enum AVCodecID codec = s1->streams[0]->codecpar->codec_id;
             if (codec == AV_CODEC_ID_H264)
                 ff_rtp_send_data(s1, s->buf + 3, s->buf_ptr - s->buf - 3, last);
             else
@@ -55,7 +55,7 @@ static void flush_buffered(AVFormatContext *s1, int last)
 static void nal_send(AVFormatContext *s1, const uint8_t *buf, int size, int last)
 {
     RTPMuxContext *s = s1->priv_data;
-    enum AVCodecID codec = s1->streams[0]->codec->codec_id;
+    enum AVCodecID codec = s1->streams[0]->codecpar->codec_id;
 
     av_log(s1, AV_LOG_DEBUG, "Sending NAL %x of len %d M=%d\n", buf[0] & 0x1F, size, last);
     if (size <= s->max_payload_size) {
diff --git a/libavformat/rtpenc_jpeg.c b/libavformat/rtpenc_jpeg.c
index 72c07c7..38eb2e6 100644
--- a/libavformat/rtpenc_jpeg.c
+++ b/libavformat/rtpenc_jpeg.c
@@ -42,24 +42,24 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size)
     s->timestamp = s->cur_timestamp;
 
     /* convert video pixel dimensions from pixels to blocks */
-    w = AV_CEIL_RSHIFT(s1->streams[0]->codec->width, 3);
-    h = AV_CEIL_RSHIFT(s1->streams[0]->codec->height, 3);
+    w = AV_CEIL_RSHIFT(s1->streams[0]->codecpar->width, 3);
+    h = AV_CEIL_RSHIFT(s1->streams[0]->codecpar->height, 3);
 
     /* get the pixel format type or fail */
-    if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ422P ||
-        (s1->streams[0]->codec->color_range == AVCOL_RANGE_JPEG &&
-         s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUV422P)) {
+    if (s1->streams[0]->codecpar->format == AV_PIX_FMT_YUVJ422P ||
+        (s1->streams[0]->codecpar->color_range == AVCOL_RANGE_JPEG &&
+         s1->streams[0]->codecpar->format == AV_PIX_FMT_YUV422P)) {
         type = 0;
-    } else if (s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUVJ420P ||
-               (s1->streams[0]->codec->color_range == AVCOL_RANGE_JPEG &&
-                s1->streams[0]->codec->pix_fmt == AV_PIX_FMT_YUV420P)) {
+    } else if (s1->streams[0]->codecpar->format == AV_PIX_FMT_YUVJ420P ||
+               (s1->streams[0]->codecpar->color_range == AVCOL_RANGE_JPEG &&
+                s1->streams[0]->codecpar->format == AV_PIX_FMT_YUV420P)) {
         type = 1;
     } else {
         av_log(s1, AV_LOG_ERROR, "Unsupported pixel format\n");
         return;
     }
 
-    /* preparse the header for getting some infos */
+    /* preparse the header for getting some info */
     for (i = 0; i < size; i++) {
         if (buf[i] != 0xff)
             continue;
diff --git a/libavformat/rtpenc_latm.c b/libavformat/rtpenc_latm.c
index 4430c44..7bda66a 100644
--- a/libavformat/rtpenc_latm.c
+++ b/libavformat/rtpenc_latm.c
@@ -34,7 +34,7 @@ void ff_rtp_send_latm(AVFormatContext *s1, const uint8_t *buff, int size)
     int len    = 0;
 
     /* skip ADTS header, if present */
-    if ((s1->streams[0]->codec->extradata_size) == 0) {
+    if ((s1->streams[0]->codecpar->extradata_size) == 0) {
         size -= 7;
         buff += 7;
     }
diff --git a/libavformat/rtpenc_mpegts.c b/libavformat/rtpenc_mpegts.c
index db1680e..7af02e0 100644
--- a/libavformat/rtpenc_mpegts.c
+++ b/libavformat/rtpenc_mpegts.c
@@ -66,7 +66,7 @@ static int rtp_mpegts_write_header(AVFormatContext *s)
             goto fail;
         st->time_base           = s->streams[i]->time_base;
         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
-        avcodec_copy_context(st->codec, s->streams[i]->codec);
+        avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
     }
     if ((ret = avio_open_dyn_buf(&mpegts_ctx->pb)) < 0)
         goto fail;
@@ -87,7 +87,7 @@ static int rtp_mpegts_write_header(AVFormatContext *s)
     st = avformat_new_stream(rtp_ctx, NULL);
     st->time_base.num   = 1;
     st->time_base.den   = 90000;
-    st->codec->codec_id = AV_CODEC_ID_MPEG2TS;
+    st->codecpar->codec_id = AV_CODEC_ID_MPEG2TS;
     rtp_ctx->pb = s->pb;
     if ((ret = avformat_write_header(rtp_ctx, NULL)) < 0)
         goto fail;
diff --git a/libavformat/rtpenc_vc2hq.c b/libavformat/rtpenc_vc2hq.c
new file mode 100644
index 0000000..085204f
--- /dev/null
+++ b/libavformat/rtpenc_vc2hq.c
@@ -0,0 +1,134 @@
+/*
+ * RTP packetizer for VC-2 HQ payload format (draft version 1) - experimental
+ * Copyright (c) 2016 Thomas Volkert <thomas at netzeal.de>
+ *
+ * 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/intreadwrite.h"
+#include "libavcodec/dirac.h"
+#include "libavcodec/get_bits.h"
+#include "libavcodec/golomb.h"
+
+#include "avformat.h"
+#include "rtpenc.h"
+
+#define RTP_VC2HQ_PL_HEADER_SIZE             4
+
+#define DIRAC_DATA_UNIT_HEADER_SIZE          13
+#define DIRAC_PIC_NR_SIZE                    4
+#define DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT      0xEC
+
+static void send_packet(AVFormatContext *ctx, uint8_t parse_code, int info_hdr_size, const uint8_t *buf, int size, int i, int f, int rtp_m)
+{
+    RTPMuxContext *rtp_ctx = ctx->priv_data;
+
+    AV_WB16(&rtp_ctx->buf[0], 0); /* extended sequence number */
+    AV_WB8 (&rtp_ctx->buf[2], i ? (f ? (0x03) : (0x02)) : 0x00); /* flags: interlaced, second field */
+    AV_WB8 (&rtp_ctx->buf[3], parse_code);
+    if (size > 0)
+        memcpy(&rtp_ctx->buf[4 + info_hdr_size], buf, size);
+    ff_rtp_send_data(ctx, rtp_ctx->buf, RTP_VC2HQ_PL_HEADER_SIZE + info_hdr_size + size, rtp_m);
+}
+
+static void send_picture(AVFormatContext *ctx, const uint8_t *buf, int size, int interlaced)
+{
+    RTPMuxContext *rtp_ctx = ctx->priv_data;
+    GetBitContext gc;
+    int lvl, second_field;
+    uint32_t pic_nr, wavelet_depth, prefix_bytes, size_scaler;
+    uint16_t frag_len;
+    char *info_hdr = &rtp_ctx->buf[4];
+
+    pic_nr = AV_RB32(&buf[0]);
+    buf += DIRAC_PIC_NR_SIZE;
+    size -= DIRAC_PIC_NR_SIZE;
+    second_field = interlaced && (pic_nr & 0x01);
+
+    init_get_bits(&gc, buf, 8  * size);
+                    get_interleaved_ue_golomb(&gc); /* wavelet_idx */
+    wavelet_depth = get_interleaved_ue_golomb(&gc);
+                    get_interleaved_ue_golomb(&gc); /* num_x */
+                    get_interleaved_ue_golomb(&gc); /* num_y */
+    prefix_bytes  = get_interleaved_ue_golomb(&gc);
+    size_scaler   = get_interleaved_ue_golomb(&gc);
+    /* pass the quantization matrices */
+    get_interleaved_ue_golomb(&gc);
+    for(lvl = 0; lvl < wavelet_depth; lvl++)
+    {
+        get_interleaved_ue_golomb(&gc);
+        get_interleaved_ue_golomb(&gc);
+        get_interleaved_ue_golomb(&gc);
+    }
+
+    frag_len = (get_bits_count(&gc) + 7) / 8; /* length of transform parameters */
+
+    AV_WB32(&info_hdr[ 0], pic_nr);
+    AV_WB16(&info_hdr[ 4], prefix_bytes);
+    AV_WB16(&info_hdr[ 6], size_scaler);
+    AV_WB16(&info_hdr[ 8], frag_len);
+    AV_WB16(&info_hdr[10], 0 /* nr. of slices */);
+    send_packet(ctx, DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT, 12, buf, frag_len, interlaced, second_field, 0);
+    buf += frag_len;
+    size -= frag_len;
+
+    while (size > 0) {
+        frag_len = FFMIN(rtp_ctx->max_payload_size - 20 /* pl header */, size);
+        AV_WB16(&info_hdr[ 8], frag_len);
+        AV_WB16(&info_hdr[10], 1 /* nr. of slices */);
+        AV_WB16(&info_hdr[12], 0 /* slice x */);
+        AV_WB16(&info_hdr[14], 0 /* slice y */);
+
+        size -= frag_len;
+        send_packet(ctx, DIRAC_RTP_PCODE_HQ_PIC_FRAGMENT, 16, buf, frag_len, interlaced, second_field, size > 0 ? 0 : 1);
+        buf += frag_len;
+    }
+}
+
+void ff_rtp_send_vc2hq(AVFormatContext *ctx, const uint8_t *frame_buf, int frame_size, int interlaced)
+{
+    const uint8_t *end = frame_buf + frame_size;
+    const uint8_t *unit = frame_buf;
+    uint8_t parse_code;
+    uint32_t unit_size;
+
+    while (unit < end) {
+        parse_code = unit[4];
+        unit_size = AV_RB32(&unit[5]);
+
+        switch (parse_code) {
+        /* sequence header */
+        /* end of sequence */
+        case DIRAC_PCODE_SEQ_HEADER:
+        case DIRAC_PCODE_END_SEQ:
+            send_packet(ctx, parse_code, 0, unit + DIRAC_DATA_UNIT_HEADER_SIZE, unit_size - DIRAC_DATA_UNIT_HEADER_SIZE, 0, 0, 0);
+            break;
+        /* HQ picture */
+        case DIRAC_PCODE_PICTURE_HQ:
+            send_picture(ctx, unit + DIRAC_DATA_UNIT_HEADER_SIZE, unit_size - DIRAC_DATA_UNIT_HEADER_SIZE, interlaced);
+            break;
+        /* parse codes without specification */
+        case DIRAC_PCODE_AUX:
+        case DIRAC_PCODE_PAD:
+            break;
+        default:
+            avpriv_report_missing_feature(ctx, "VC-2 parse code %d", parse_code);
+            break;
+        }
+        unit += unit_size;
+    }
+}
diff --git a/libavformat/rtpenc_vp9.c b/libavformat/rtpenc_vp9.c
new file mode 100644
index 0000000..172ab21
--- /dev/null
+++ b/libavformat/rtpenc_vp9.c
@@ -0,0 +1,54 @@
+/*
+ * RTP packetizer for VP9 payload format (draft version 02) - experimental
+ * Copyright (c) 2016 Thomas Volkert <thomas at netzeal.de>
+ *
+ * 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 "rtpenc.h"
+
+#define RTP_VP9_DESC_REQUIRED_SIZE 1
+
+void ff_rtp_send_vp9(AVFormatContext *ctx, const uint8_t *buf, int size)
+{
+    RTPMuxContext *rtp_ctx = ctx->priv_data;
+    int len;
+
+    rtp_ctx->timestamp  = rtp_ctx->cur_timestamp;
+    rtp_ctx->buf_ptr    = rtp_ctx->buf;
+
+    /* mark the first fragment */
+    *rtp_ctx->buf_ptr++ = 0x08;
+
+    while (size > 0) {
+        len = FFMIN(size, rtp_ctx->max_payload_size - RTP_VP9_DESC_REQUIRED_SIZE);
+
+        if (len == size) {
+            /* mark the last fragment */
+            rtp_ctx->buf[0] |= 0x04;
+        }
+
+        memcpy(rtp_ctx->buf_ptr, buf, len);
+        ff_rtp_send_data(ctx, rtp_ctx->buf, len + RTP_VP9_DESC_REQUIRED_SIZE, size == len);
+
+        size            -= len;
+        buf             += len;
+
+        /* clear the end bit */
+        rtp_ctx->buf[0] &= ~0x08;
+    }
+}
diff --git a/libavformat/rtpenc_xiph.c b/libavformat/rtpenc_xiph.c
index b4d950b..00c29a7 100644
--- a/libavformat/rtpenc_xiph.c
+++ b/libavformat/rtpenc_xiph.c
@@ -68,7 +68,7 @@ void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size)
     // 0 - whole frame (possibly multiple frames)
     // 1 - first fragment
     // 2 - fragment continuation
-    // 3 - last fragmement
+    // 3 - last fragment
     frag = size <= max_pkt_size ? 0 : 1;
 
     if (!frag && !xdt) { // do we have a whole frame of raw data?
diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index 538a7b2..fa1dcb5 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -323,6 +323,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
     char path[1024];
     const char *p;
     int i, max_retry_count = 3;
+    int rtcpflags;
 
     av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
                  path, sizeof(path), uri);
@@ -381,21 +382,22 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
                       hostname, rtp_port, s->local_rtpport,
                       sources, block);
         if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
-                                 NULL, h->protocol_whitelist) < 0)
+                                 NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
             goto fail;
         s->local_rtpport = ff_udp_get_local_port(s->rtp_hd);
         if(s->local_rtpport == 65535) {
             s->local_rtpport = -1;
             continue;
         }
+        rtcpflags = flags | AVIO_FLAG_WRITE;
         if (s->local_rtcpport < 0) {
             s->local_rtcpport = s->local_rtpport + 1;
             build_udp_url(s, buf, sizeof(buf),
                           hostname, s->rtcp_port, s->local_rtcpport,
                           sources, block);
-            if (ffurl_open_whitelist(&s->rtcp_hd, buf, flags,
+            if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags,
                                      &h->interrupt_callback, NULL,
-                                     h->protocol_whitelist) < 0) {
+                                     h->protocol_whitelist, h->protocol_blacklist, h) < 0) {
                 s->local_rtpport = s->local_rtcpport = -1;
                 continue;
             }
@@ -404,8 +406,8 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
         build_udp_url(s, buf, sizeof(buf),
                       hostname, s->rtcp_port, s->local_rtcpport,
                       sources, block);
-        if (ffurl_open_whitelist(&s->rtcp_hd, buf, flags, &h->interrupt_callback,
-                                 NULL, h->protocol_whitelist) < 0)
+        if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback,
+                                 NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0)
             goto fail;
         break;
     }
@@ -605,7 +607,7 @@ static int rtp_get_multi_file_handle(URLContext *h, int **handles,
     return 0;
 }
 
-URLProtocol ff_rtp_protocol = {
+const URLProtocol ff_rtp_protocol = {
     .name                      = "rtp",
     .url_open                  = rtp_open,
     .url_read                  = rtp_read,
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index d710469..21c80c1 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -206,11 +206,11 @@ static int get_sockaddr(AVFormatContext *s,
 static void init_rtp_handler(RTPDynamicProtocolHandler *handler,
                              RTSPStream *rtsp_st, AVStream *st)
 {
-    AVCodecContext *codec = st ? st->codec : NULL;
+    AVCodecParameters *par = st ? st->codecpar : NULL;
     if (!handler)
         return;
-    if (codec)
-        codec->codec_id          = handler->codec_id;
+    if (par)
+        par->codec_id          = handler->codec_id;
     rtsp_st->dynamic_handler = handler;
     if (st)
         st->need_parsing = handler->need_parsing;
@@ -245,10 +245,10 @@ static int sdp_parse_rtpmap(AVFormatContext *s,
                             AVStream *st, RTSPStream *rtsp_st,
                             int payload_type, const char *p)
 {
-    AVCodecContext *codec = st->codec;
+    AVCodecParameters *par = st->codecpar;
     char buf[256];
     int i;
-    AVCodec *c;
+    const AVCodecDescriptor *desc;
     const char *c_name;
 
     /* See if we can handle this kind of payload.
@@ -259,46 +259,46 @@ static int sdp_parse_rtpmap(AVFormatContext *s,
     if (payload_type < RTP_PT_PRIVATE) {
         /* We are in a standard case
          * (from http://www.iana.org/assignments/rtp-parameters). */
-        codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
+        par->codec_id = ff_rtp_codec_id(buf, par->codec_type);
     }
 
-    if (codec->codec_id == AV_CODEC_ID_NONE) {
+    if (par->codec_id == AV_CODEC_ID_NONE) {
         RTPDynamicProtocolHandler *handler =
-            ff_rtp_handler_find_by_name(buf, codec->codec_type);
+            ff_rtp_handler_find_by_name(buf, par->codec_type);
         init_rtp_handler(handler, rtsp_st, st);
         /* If no dynamic handler was found, check with the list of standard
          * allocated types, if such a stream for some reason happens to
          * use a private payload type. This isn't handled in rtpdec.c, since
          * the format name from the rtpmap line never is passed into rtpdec. */
         if (!rtsp_st->dynamic_handler)
-            codec->codec_id = ff_rtp_codec_id(buf, codec->codec_type);
+            par->codec_id = ff_rtp_codec_id(buf, par->codec_type);
     }
 
-    c = avcodec_find_decoder(codec->codec_id);
-    if (c && c->name)
-        c_name = c->name;
+    desc = avcodec_descriptor_get(par->codec_id);
+    if (desc && desc->name)
+        c_name = desc->name;
     else
         c_name = "(null)";
 
     get_word_sep(buf, sizeof(buf), "/", &p);
     i = atoi(buf);
-    switch (codec->codec_type) {
+    switch (par->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
         av_log(s, AV_LOG_DEBUG, "audio codec set to: %s\n", c_name);
-        codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
-        codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
+        par->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
+        par->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
         if (i > 0) {
-            codec->sample_rate = i;
-            avpriv_set_pts_info(st, 32, 1, codec->sample_rate);
+            par->sample_rate = i;
+            avpriv_set_pts_info(st, 32, 1, par->sample_rate);
             get_word_sep(buf, sizeof(buf), "/", &p);
             i = atoi(buf);
             if (i > 0)
-                codec->channels = i;
+                par->channels = i;
         }
         av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n",
-               codec->sample_rate);
+               par->sample_rate);
         av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n",
-               codec->channels);
+               par->channels);
         break;
     case AVMEDIA_TYPE_VIDEO:
         av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name);
@@ -503,17 +503,17 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
                 return;
             st->id = rt->nb_rtsp_streams - 1;
             rtsp_st->stream_index = st->index;
-            st->codec->codec_type = codec_type;
+            st->codecpar->codec_type = codec_type;
             if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
                 RTPDynamicProtocolHandler *handler;
                 /* if standard payload type, we can find the codec right now */
-                ff_rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type);
-                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
-                    st->codec->sample_rate > 0)
-                    avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
+                ff_rtp_get_codec_info(st->codecpar, rtsp_st->sdp_payload_type);
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
+                    st->codecpar->sample_rate > 0)
+                    avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate);
                 /* Even static payload types may need a custom depacketizer */
                 handler = ff_rtp_handler_find_by_id(
-                              rtsp_st->sdp_payload_type, st->codec->codec_type);
+                              rtsp_st->sdp_payload_type, st->codecpar->codec_type);
                 init_rtp_handler(handler, rtsp_st, st);
                 finalize_rtp_handler_init(s, rtsp_st, st);
             }
@@ -573,6 +573,10 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
                 s1->seen_fmtp = 1;
                 av_strlcpy(s1->delayed_fmtp, buf, sizeof(s1->delayed_fmtp));
             }
+        } else if (av_strstart(p, "ssrc:", &p) && s->nb_streams > 0) {
+            rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
+            get_word(buf1, sizeof(buf1), &p);
+            rtsp_st->ssrc = strtoll(buf1, NULL, 10);
         } else if (av_strstart(p, "range:", &p)) {
             int64_t start, end;
 
@@ -598,7 +602,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
         } else if (av_strstart(p, "SampleRate:integer;", &p) &&
                    s->nb_streams > 0) {
             st = s->streams[s->nb_streams - 1];
-            st->codec->sample_rate = atoi(p);
+            st->codecpar->sample_rate = atoi(p);
         } else if (av_strstart(p, "crypto:", &p) && s->nb_streams > 0) {
             // RFC 4568
             rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
@@ -831,6 +835,8 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st)
     if (!rtsp_st->transport_priv) {
          return AVERROR(ENOMEM);
     } else if (CONFIG_RTPDEC && rt->transport == RTSP_TRANSPORT_RTP) {
+        RTPDemuxContext *rtpctx = rtsp_st->transport_priv;
+        rtpctx->ssrc = rtsp_st->ssrc;
         if (rtsp_st->dynamic_handler) {
             ff_rtp_parse_set_dynamic_protocol(rtsp_st->transport_priv,
                                               rtsp_st->dynamic_protocol_context,
@@ -1469,7 +1475,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
                 /* we will use two ports per rtp stream (rtp and rtcp) */
                 j += 2;
                 err = ffurl_open_whitelist(&rtsp_st->rtp_handle, buf, AVIO_FLAG_READ_WRITE,
-                                 &s->interrupt_callback, &opts, s->protocol_whitelist);
+                                 &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist, NULL);
 
                 av_dict_free(&opts);
 
@@ -1501,7 +1507,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
              * will return an error. Therefore, we skip those streams. */
             if (rt->server_type == RTSP_SERVER_WMS &&
                 (rtsp_st->stream_index < 0 ||
-                 s->streams[rtsp_st->stream_index]->codec->codec_type ==
+                 s->streams[rtsp_st->stream_index]->codecpar->codec_type ==
                     AVMEDIA_TYPE_DATA))
                 continue;
             snprintf(transport, sizeof(transport) - 1,
@@ -1612,7 +1618,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
             ff_url_join(url, sizeof(url), "rtp", NULL, namebuf,
                         port, "%s", optbuf);
             if (ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
-                           &s->interrupt_callback, NULL, s->protocol_whitelist) < 0) {
+                           &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL) < 0) {
                 err = AVERROR_INVALIDDATA;
                 goto fail;
             }
@@ -1801,7 +1807,7 @@ redirect:
                     host, port,
                     "?timeout=%d", rt->stimeout);
         if ((ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
-                       &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
+                       &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL)) < 0) {
             err = ret;
             goto fail;
         }
@@ -2316,8 +2322,8 @@ static int sdp_read_header(AVFormatContext *s)
             append_source_addrs(url, sizeof(url), "block",
                                 rtsp_st->nb_exclude_source_addrs,
                                 rtsp_st->exclude_source_addrs);
-            err = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
-                           &s->interrupt_callback, &opts, s->protocol_whitelist);
+            err = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ,
+                           &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist, NULL);
 
             av_dict_free(&opts);
 
@@ -2377,7 +2383,7 @@ static int rtp_read_header(AVFormatContext *s)
     int ret, port;
     URLContext* in = NULL;
     int payload_type;
-    AVCodecContext codec = { 0 };
+    AVCodecParameters *par = NULL;
     struct sockaddr_storage addr;
     AVIOContext pb;
     socklen_t addrlen = sizeof(addr);
@@ -2387,7 +2393,7 @@ static int rtp_read_header(AVFormatContext *s)
         return AVERROR(EIO);
 
     ret = ffurl_open_whitelist(&in, s->filename, AVIO_FLAG_READ,
-                     &s->interrupt_callback, NULL, s->protocol_whitelist);
+                     &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL);
     if (ret)
         goto fail;
 
@@ -2418,13 +2424,19 @@ static int rtp_read_header(AVFormatContext *s)
     ffurl_close(in);
     in = NULL;
 
-    if (ff_rtp_get_codec_info(&codec, payload_type)) {
+    par = avcodec_parameters_alloc();
+    if (!par) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    if (ff_rtp_get_codec_info(par, payload_type)) {
         av_log(s, AV_LOG_ERROR, "Unable to receive RTP payload type %d "
                                 "without an SDP file describing it\n",
                                  payload_type);
         goto fail;
     }
-    if (codec.codec_type != AVMEDIA_TYPE_DATA) {
+    if (par->codec_type != AVMEDIA_TYPE_DATA) {
         av_log(s, AV_LOG_WARNING, "Guessing on RTP content - if not received "
                                   "properly you need an SDP file "
                                   "describing it\n");
@@ -2436,10 +2448,11 @@ static int rtp_read_header(AVFormatContext *s)
     snprintf(sdp, sizeof(sdp),
              "v=0\r\nc=IN IP%d %s\r\nm=%s %d RTP/AVP %d\r\n",
              addr.ss_family == AF_INET ? 4 : 6, host,
-             codec.codec_type == AVMEDIA_TYPE_DATA  ? "application" :
-             codec.codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio",
+             par->codec_type == AVMEDIA_TYPE_DATA  ? "application" :
+             par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio",
              port, payload_type);
     av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp);
+    avcodec_parameters_free(&par);
 
     ffio_init_context(&pb, sdp, strlen(sdp), 0, NULL, NULL, NULL, NULL);
     s->pb = &pb;
@@ -2454,6 +2467,7 @@ static int rtp_read_header(AVFormatContext *s)
     return ret;
 
 fail:
+    avcodec_parameters_free(&par);
     if (in)
         ffurl_close(in);
     ff_network_close();
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index bd837b5..852fd67 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -466,6 +466,9 @@ typedef struct RTSPStream {
     /** Enable sending RTCP feedback messages according to RFC 4585 */
     int feedback;
 
+    /** SSRC for this stream, to allow identifying RTCP packets before the first RTP packet */
+    uint32_t ssrc;
+
     char crypto_suite[40];
     char crypto_params[100];
 } RTSPStream;
diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c
index 17f04c0..a722b98 100644
--- a/libavformat/rtspdec.c
+++ b/libavformat/rtspdec.c
@@ -296,7 +296,7 @@ static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl)
             av_log(s, AV_LOG_TRACE, "Opening: %s", url);
             ret = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE,
                                        &s->interrupt_callback, &opts,
-                                       s->protocol_whitelist);
+                                       s->protocol_whitelist, s->protocol_blacklist, NULL);
             av_dict_free(&opts);
             if (ret)
                 localport += 2;
@@ -665,7 +665,7 @@ static int rtsp_listen(AVFormatContext *s)
 
     if (ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE,
                                    &s->interrupt_callback, NULL,
-                                   s->protocol_whitelist)) {
+                                   s->protocol_whitelist, s->protocol_blacklist, NULL)) {
         av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n");
         return ret;
     }
diff --git a/libavformat/samidec.c b/libavformat/samidec.c
index 11c674c..7ea1bdf 100644
--- a/libavformat/samidec.c
+++ b/libavformat/samidec.c
@@ -59,8 +59,8 @@ static int sami_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 1000);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_SAMI;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_SAMI;
 
     av_bprint_init(&buf,     0, AV_BPRINT_SIZE_UNLIMITED);
     av_bprint_init(&hdr_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
@@ -101,7 +101,7 @@ static int sami_read_header(AVFormatContext *s)
         av_bprint_clear(&buf);
     }
 
-    res = avpriv_bprint_to_extradata(st->codec, &hdr_buf);
+    res = ff_bprint_to_codecpar_extradata(st->codecpar, &hdr_buf);
     if (res < 0)
         goto end;
 
diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c
index 926795b..522b38d 100644
--- a/libavformat/sapdec.c
+++ b/libavformat/sapdec.c
@@ -87,7 +87,7 @@ static int sap_read_header(AVFormatContext *s)
                 port);
     ret = ffurl_open_whitelist(&sap->ann_fd, url, AVIO_FLAG_READ,
                                &s->interrupt_callback, NULL,
-                               s->protocol_whitelist);
+                               s->protocol_whitelist, s->protocol_blacklist, NULL);
     if (ret)
         goto fail;
 
@@ -161,7 +161,7 @@ static int sap_read_header(AVFormatContext *s)
     sap->sdp_ctx->pb        = &sap->sdp_pb;
     sap->sdp_ctx->interrupt_callback = s->interrupt_callback;
 
-    if ((ret = ff_copy_whitelists(sap->sdp_ctx, s)) < 0)
+    if ((ret = ff_copy_whiteblacklists(sap->sdp_ctx, s)) < 0)
         goto fail;
 
     ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL);
@@ -176,7 +176,7 @@ static int sap_read_header(AVFormatContext *s)
             goto fail;
         }
         st->id = i;
-        avcodec_copy_context(st->codec, sap->sdp_ctx->streams[i]->codec);
+        avcodec_parameters_copy(st->codecpar, sap->sdp_ctx->streams[i]->codecpar);
         st->time_base = sap->sdp_ctx->streams[i]->time_base;
     }
 
@@ -225,7 +225,7 @@ static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt)
                 return AVERROR(ENOMEM);
             }
             st->id = i;
-            avcodec_copy_context(st->codec, sap->sdp_ctx->streams[i]->codec);
+            avcodec_parameters_copy(st->codecpar, sap->sdp_ctx->streams[i]->codecpar);
             st->time_base = sap->sdp_ctx->streams[i]->time_base;
         }
     }
diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c
index b2f64b8..3098e34 100644
--- a/libavformat/sapenc.c
+++ b/libavformat/sapenc.c
@@ -151,7 +151,7 @@ static int sap_write_header(AVFormatContext *s)
             base_port += 2;
         ret = ffurl_open_whitelist(&fd, url, AVIO_FLAG_WRITE,
                                    &s->interrupt_callback, NULL,
-                                   s->protocol_whitelist);
+                                   s->protocol_whitelist, s->protocol_blacklist, NULL);
         if (ret) {
             ret = AVERROR(EIO);
             goto fail;
@@ -171,7 +171,7 @@ static int sap_write_header(AVFormatContext *s)
                 "?ttl=%d&connect=1", ttl);
     ret = ffurl_open_whitelist(&sap->ann_fd, url, AVIO_FLAG_WRITE,
                                &s->interrupt_callback, NULL,
-                               s->protocol_whitelist);
+                               s->protocol_whitelist, s->protocol_blacklist, NULL);
     if (ret) {
         ret = AVERROR(EIO);
         goto fail;
diff --git a/libavformat/sauce.c b/libavformat/sauce.c
index a2347b0..5ac9ca9 100644
--- a/libavformat/sauce.c
+++ b/libavformat/sauce.c
@@ -65,18 +65,18 @@ int ff_sauce_read(AVFormatContext *avctx, uint64_t *fsize, int *got_width, int g
     if (got_width && datatype && filetype) {
         if ((datatype == 1 && filetype <=2) || (datatype == 5 && filetype == 255) || datatype == 6) {
             if (t1) {
-                avctx->streams[0]->codec->width = t1<<3;
+                avctx->streams[0]->codecpar->width = t1<<3;
                 *got_width = 1;
             }
             if (get_height && t2)
-                avctx->streams[0]->codec->height = t2<<4;
+                avctx->streams[0]->codecpar->height = t2<<4;
         } else if (datatype == 5) {
             if (filetype) {
-                avctx->streams[0]->codec->width = (filetype == 1 ? t1 : filetype) << 4;
+                avctx->streams[0]->codecpar->width = (filetype == 1 ? t1 : filetype) << 4;
                 *got_width = 1;
             }
             if (get_height && t2)
-                avctx->streams[0]->codec->height = t2<<4;
+                avctx->streams[0]->codecpar->height = t2<<4;
         }
     }
 
diff --git a/libavformat/sbgdec.c b/libavformat/sbgdec.c
index 03cd922..bb020d7 100644
--- a/libavformat/sbgdec.c
+++ b/libavformat/sbgdec.c
@@ -1324,7 +1324,7 @@ static int generate_intervals(void *log, struct sbg_script *s, int sample_rate,
     return 0;
 }
 
-static int encode_intervals(struct sbg_script *s, AVCodecContext *avc,
+static int encode_intervals(struct sbg_script *s, AVCodecParameters *par,
                             struct ws_intervals *inter)
 {
     int i, edata_size = 4;
@@ -1336,9 +1336,9 @@ static int encode_intervals(struct sbg_script *s, AVCodecContext *avc,
         if (edata_size < 0)
             return AVERROR(ENOMEM);
     }
-    if (ff_alloc_extradata(avc, edata_size))
+    if (ff_alloc_extradata(par, edata_size))
         return AVERROR(ENOMEM);
-    edata = avc->extradata;
+    edata = par->extradata;
 
 #define ADD_EDATA32(v) do { AV_WL32(edata, (v)); edata += 4; } while(0)
 #define ADD_EDATA64(v) do { AV_WL64(edata, (v)); edata += 8; } while(0)
@@ -1362,7 +1362,7 @@ static int encode_intervals(struct sbg_script *s, AVCodecContext *avc,
                 break;
         }
     }
-    if (edata != avc->extradata + edata_size)
+    if (edata != par->extradata + edata_size)
         return AVERROR_BUG;
     return 0;
 }
@@ -1414,13 +1414,13 @@ static av_cold int sbg_read_header(AVFormatContext *avf)
     st = avformat_new_stream(avf, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id       = AV_CODEC_ID_FFWAVESYNTH;
-    st->codec->channels       = 2;
-    st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
-    st->codec->sample_rate    = sbg->sample_rate;
-    st->codec->frame_size     = sbg->frame_size;
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    st->codecpar->codec_type     = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id       = AV_CODEC_ID_FFWAVESYNTH;
+    st->codecpar->channels       = 2;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
+    st->codecpar->sample_rate    = sbg->sample_rate;
+    st->codecpar->frame_size     = sbg->frame_size;
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     st->probe_packets = 0;
     st->start_time    = av_rescale(script.start_ts,
                                    sbg->sample_rate, AV_TIME_BASE);
@@ -1428,7 +1428,7 @@ static av_cold int sbg_read_header(AVFormatContext *avf)
                         av_rescale(script.end_ts - script.start_ts,
                                    sbg->sample_rate, AV_TIME_BASE);
     st->cur_dts       = st->start_time;
-    r = encode_intervals(&script, st->codec, &inter);
+    r = encode_intervals(&script, st->codecpar, &inter);
     if (r < 0)
         goto fail;
 
@@ -1448,7 +1448,7 @@ static int sbg_read_packet(AVFormatContext *avf, AVPacket *packet)
     int64_t ts, end_ts;
 
     ts = avf->streams[0]->cur_dts;
-    end_ts = ts + avf->streams[0]->codec->frame_size;
+    end_ts = ts + avf->streams[0]->codecpar->frame_size;
     if (avf->streams[0]->duration != AV_NOPTS_VALUE)
         end_ts = FFMIN(avf->streams[0]->start_time + avf->streams[0]->duration,
                        end_ts);
diff --git a/libavformat/sctp.c b/libavformat/sctp.c
index 5fee7e3..9a80e9b 100644
--- a/libavformat/sctp.c
+++ b/libavformat/sctp.c
@@ -359,7 +359,7 @@ static int sctp_get_file_handle(URLContext *h)
     return s->fd;
 }
 
-URLProtocol ff_sctp_protocol = {
+const URLProtocol ff_sctp_protocol = {
     .name                = "sctp",
     .url_open            = sctp_open,
     .url_read            = sctp_read,
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index 2ab37a8..01b564b 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -151,24 +151,24 @@ static int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url)
 }
 
 #define MAX_PSET_SIZE 1024
-static char *extradata2psets(AVCodecContext *c)
+static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par)
 {
     char *psets, *p;
     const uint8_t *r;
     static const char pset_string[] = "; sprop-parameter-sets=";
     static const char profile_string[] = "; profile-level-id=";
-    uint8_t *extradata = c->extradata;
-    int extradata_size = c->extradata_size;
+    uint8_t *extradata = par->extradata;
+    int extradata_size = par->extradata_size;
     uint8_t *tmpbuf = NULL;
     const uint8_t *sps = NULL, *sps_end;
 
-    if (c->extradata_size > MAX_EXTRADATA_SIZE) {
-        av_log(c, AV_LOG_ERROR, "Too much extradata!\n");
+    if (par->extradata_size > MAX_EXTRADATA_SIZE) {
+        av_log(s, AV_LOG_ERROR, "Too much extradata!\n");
 
         return NULL;
     }
-    if (c->extradata[0] == 1) {
-        if (ff_avc_write_annexb_extradata(c->extradata, &extradata,
+    if (par->extradata[0] == 1) {
+        if (ff_avc_write_annexb_extradata(par->extradata, &extradata,
                                           &extradata_size))
             return NULL;
         tmpbuf = extradata;
@@ -176,7 +176,7 @@ static char *extradata2psets(AVCodecContext *c)
 
     psets = av_mallocz(MAX_PSET_SIZE);
     if (!psets) {
-        av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n");
+        av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n");
         av_free(tmpbuf);
         return NULL;
     }
@@ -203,7 +203,7 @@ static char *extradata2psets(AVCodecContext *c)
             sps_end = r1;
         }
         if (!av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r)) {
-            av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
+            av_log(s, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
             av_free(psets);
             av_free(tmpbuf);
 
@@ -223,11 +223,11 @@ static char *extradata2psets(AVCodecContext *c)
     return psets;
 }
 
-static char *extradata2psets_hevc(AVCodecContext *c)
+static char *extradata2psets_hevc(AVCodecParameters *par)
 {
     char *psets;
-    uint8_t *extradata = c->extradata;
-    int extradata_size = c->extradata_size;
+    uint8_t *extradata = par->extradata;
+    int extradata_size = par->extradata_size;
     uint8_t *tmpbuf = NULL;
     int ps_pos[3] = { 0 };
     static const char * const ps_names[3] = { "vps", "sps", "pps" };
@@ -238,11 +238,11 @@ static char *extradata2psets_hevc(AVCodecContext *c)
     // the same type, and we might need to convert from one format to the
     // other anyway, we get away with a little less work by using the hvcc
     // format.
-    if (c->extradata[0] != 1) {
+    if (par->extradata[0] != 1) {
         AVIOContext *pb;
         if (avio_open_dyn_buf(&pb) < 0)
             return NULL;
-        if (ff_isom_write_hvcc(pb, c->extradata, c->extradata_size, 0) < 0) {
+        if (ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0) < 0) {
             avio_close_dyn_buf(pb, &tmpbuf);
             goto err;
         }
@@ -261,7 +261,7 @@ static char *extradata2psets_hevc(AVCodecContext *c)
             goto err;
         nalu_type = extradata[pos] & 0x3f;
         // Not including libavcodec/hevc.h to avoid confusion between
-        // NAL_* with the same name for both H264 and HEVC.
+        // NAL_* with the same name for both H.264 and HEVC.
         if (nalu_type == 32) // VPS
             ps_pos[0] = pos;
         else if (nalu_type == 33) // SPS
@@ -324,35 +324,35 @@ err:
     return NULL;
 }
 
-static char *extradata2config(AVCodecContext *c)
+static char *extradata2config(AVFormatContext *s, AVCodecParameters *par)
 {
     char *config;
 
-    if (c->extradata_size > MAX_EXTRADATA_SIZE) {
-        av_log(c, AV_LOG_ERROR, "Too much extradata!\n");
+    if (par->extradata_size > MAX_EXTRADATA_SIZE) {
+        av_log(s, AV_LOG_ERROR, "Too much extradata!\n");
 
         return NULL;
     }
-    config = av_malloc(10 + c->extradata_size * 2);
+    config = av_malloc(10 + par->extradata_size * 2);
     if (!config) {
-        av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
+        av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
         return NULL;
     }
     memcpy(config, "; config=", 9);
-    ff_data_to_hex(config + 9, c->extradata, c->extradata_size, 0);
-    config[9 + c->extradata_size * 2] = 0;
+    ff_data_to_hex(config + 9, par->extradata, par->extradata_size, 0);
+    config[9 + par->extradata_size * 2] = 0;
 
     return config;
 }
 
-static char *xiph_extradata2config(AVCodecContext *c)
+static char *xiph_extradata2config(AVFormatContext *s, AVCodecParameters *par)
 {
     char *config, *encoded_config;
     const uint8_t *header_start[3];
     int headers_len, header_len[3], config_len;
     int first_header_size;
 
-    switch (c->codec_id) {
+    switch (par->codec_id) {
     case AV_CODEC_ID_THEORA:
         first_header_size = 42;
         break;
@@ -360,14 +360,14 @@ static char *xiph_extradata2config(AVCodecContext *c)
         first_header_size = 30;
         break;
     default:
-        av_log(c, AV_LOG_ERROR, "Unsupported Xiph codec ID\n");
+        av_log(s, AV_LOG_ERROR, "Unsupported Xiph codec ID\n");
         return NULL;
     }
 
-    if (avpriv_split_xiph_headers(c->extradata, c->extradata_size,
+    if (avpriv_split_xiph_headers(par->extradata, par->extradata_size,
                               first_header_size, header_start,
                               header_len) < 0) {
-        av_log(c, AV_LOG_ERROR, "Extradata corrupt.\n");
+        av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
         return NULL;
     }
 
@@ -409,12 +409,12 @@ static char *xiph_extradata2config(AVCodecContext *c)
     return encoded_config;
 
 xiph_fail:
-    av_log(c, AV_LOG_ERROR,
+    av_log(s, AV_LOG_ERROR,
            "Not enough memory for configuration string\n");
     return NULL;
 }
 
-static int latm_context2profilelevel(AVCodecContext *c)
+static int latm_context2profilelevel(AVCodecParameters *par)
 {
     /* MP4A-LATM
      * The RTP payload format specification is described in RFC 3016
@@ -425,17 +425,17 @@ static int latm_context2profilelevel(AVCodecContext *c)
     /* TODO: AAC Profile only supports AAC LC Object Type.
      * Different Object Types should implement different Profile Levels */
 
-    if (c->sample_rate <= 24000) {
-        if (c->channels <= 2)
+    if (par->sample_rate <= 24000) {
+        if (par->channels <= 2)
             profile_level = 0x28; // AAC Profile, Level 1
-    } else if (c->sample_rate <= 48000) {
-        if (c->channels <= 2) {
+    } else if (par->sample_rate <= 48000) {
+        if (par->channels <= 2) {
             profile_level = 0x29; // AAC Profile, Level 2
-        } else if (c->channels <= 5) {
+        } else if (par->channels <= 5) {
             profile_level = 0x2A; // AAC Profile, Level 4
         }
-    } else if (c->sample_rate <= 96000) {
-        if (c->channels <= 5) {
+    } else if (par->sample_rate <= 96000) {
+        if (par->channels <= 5) {
             profile_level = 0x2B; // AAC Profile, Level 5
         }
     }
@@ -443,7 +443,7 @@ static int latm_context2profilelevel(AVCodecContext *c)
     return profile_level;
 }
 
-static char *latm_context2config(AVCodecContext *c)
+static char *latm_context2config(AVFormatContext *s, AVCodecParameters *par)
 {
     /* MP4A-LATM
      * The RTP payload format specification is described in RFC 3016
@@ -454,23 +454,23 @@ static char *latm_context2config(AVCodecContext *c)
     char *config;
 
     for (rate_index = 0; rate_index < 16; rate_index++)
-        if (avpriv_mpeg4audio_sample_rates[rate_index] == c->sample_rate)
+        if (avpriv_mpeg4audio_sample_rates[rate_index] == par->sample_rate)
             break;
     if (rate_index == 16) {
-        av_log(c, AV_LOG_ERROR, "Unsupported sample rate\n");
+        av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n");
         return NULL;
     }
 
     config_byte[0] = 0x40;
     config_byte[1] = 0;
     config_byte[2] = 0x20 | rate_index;
-    config_byte[3] = c->channels << 4;
+    config_byte[3] = par->channels << 4;
     config_byte[4] = 0x3f;
     config_byte[5] = 0xc0;
 
     config = av_malloc(6*2+1);
     if (!config) {
-        av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
+        av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
         return NULL;
     }
     ff_data_to_hex(config, config_byte, 6, 1);
@@ -479,18 +479,22 @@ static char *latm_context2config(AVCodecContext *c)
     return config;
 }
 
-static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type, AVFormatContext *fmt)
+static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int payload_type, AVFormatContext *fmt)
 {
     char *config = NULL;
+    AVCodecParameters *p = st->codecpar;
 
-    switch (c->codec_id) {
+    switch (p->codec_id) {
+        case AV_CODEC_ID_DIRAC:
+            av_strlcatf(buff, size, "a=rtpmap:%d VC2/90000\r\n", payload_type);
+            break;
         case AV_CODEC_ID_H264: {
             int mode = 1;
             if (fmt && fmt->oformat && fmt->oformat->priv_class &&
                 av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0"))
                 mode = 0;
-            if (c->extradata_size) {
-                config = extradata2psets(c);
+            if (p->extradata_size) {
+                config = extradata2psets(fmt, p);
             }
             av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n"
                                     "a=fmtp:%d packetization-mode=%d%s\r\n",
@@ -502,9 +506,9 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
         {
             const char *pic_fmt = NULL;
             /* only QCIF and CIF are specified as supported in RFC 4587 */
-            if (c->width == 176 && c->height == 144)
+            if (p->width == 176 && p->height == 144)
                 pic_fmt = "QCIF=1";
-            else if (c->width == 352 && c->height == 288)
+            else if (p->width == 352 && p->height == 288)
                 pic_fmt = "CIF=1";
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d H261/90000\r\n", payload_type);
@@ -520,23 +524,23 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
              * stagefright and on Samsung bada. */
             if (!fmt || !fmt->oformat->priv_class ||
                 !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190") ||
-                c->codec_id == AV_CODEC_ID_H263P)
+                p->codec_id == AV_CODEC_ID_H263P)
             av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n"
                                     "a=framesize:%d %d-%d\r\n",
                                     payload_type,
-                                    payload_type, c->width, c->height);
+                                    payload_type, p->width, p->height);
             break;
         case AV_CODEC_ID_HEVC:
-            if (c->extradata_size)
-                config = extradata2psets_hevc(c);
+            if (p->extradata_size)
+                config = extradata2psets_hevc(p);
             av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type);
             if (config)
                 av_strlcatf(buff, size, "a=fmtp:%d %s\r\n",
                                          payload_type, config);
             break;
         case AV_CODEC_ID_MPEG4:
-            if (c->extradata_size) {
-                config = extradata2config(c);
+            if (p->extradata_size) {
+                config = extradata2config(fmt, p);
             }
             av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n"
                                     "a=fmtp:%d profile-level-id=1%s\r\n",
@@ -546,21 +550,21 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
         case AV_CODEC_ID_AAC:
             if (fmt && fmt->oformat && fmt->oformat->priv_class &&
                 av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) {
-                config = latm_context2config(c);
+                config = latm_context2config(fmt, p);
                 if (!config)
                     return NULL;
                 av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n"
                                         "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n",
-                                         payload_type, c->sample_rate, c->channels,
-                                         payload_type, latm_context2profilelevel(c), config);
+                                         payload_type, p->sample_rate, p->channels,
+                                         payload_type, latm_context2profilelevel(p), config);
             } else {
-                if (c->extradata_size) {
-                    config = extradata2config(c);
+                if (p->extradata_size) {
+                    config = extradata2config(fmt, p);
                 } else {
                     /* FIXME: maybe we can forge config information based on the
                      *        codec parameters...
                      */
-                    av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n");
+                    av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n");
                     return NULL;
                 }
                 if (!config) {
@@ -570,7 +574,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                         "a=fmtp:%d profile-level-id=1;"
                                         "mode=AAC-hbr;sizelength=13;indexlength=3;"
                                         "indexdeltalength=3%s\r\n",
-                                         payload_type, c->sample_rate, c->channels,
+                                         payload_type, p->sample_rate, p->channels,
                                          payload_type, config);
             }
             break;
@@ -578,48 +582,48 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n",
                                          payload_type,
-                                         c->sample_rate, c->channels);
+                                         p->sample_rate, p->channels);
             break;
         case AV_CODEC_ID_PCM_MULAW:
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n",
                                          payload_type,
-                                         c->sample_rate, c->channels);
+                                         p->sample_rate, p->channels);
             break;
         case AV_CODEC_ID_PCM_ALAW:
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n",
                                          payload_type,
-                                         c->sample_rate, c->channels);
+                                         p->sample_rate, p->channels);
             break;
         case AV_CODEC_ID_AMR_NB:
             av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n"
                                     "a=fmtp:%d octet-align=1\r\n",
-                                     payload_type, c->sample_rate, c->channels,
+                                     payload_type, p->sample_rate, p->channels,
                                      payload_type);
             break;
         case AV_CODEC_ID_AMR_WB:
             av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n"
                                     "a=fmtp:%d octet-align=1\r\n",
-                                     payload_type, c->sample_rate, c->channels,
+                                     payload_type, p->sample_rate, p->channels,
                                      payload_type);
             break;
         case AV_CODEC_ID_VORBIS:
-            if (c->extradata_size)
-                config = xiph_extradata2config(c);
+            if (p->extradata_size)
+                config = xiph_extradata2config(fmt, p);
             else
-                av_log(c, AV_LOG_ERROR, "Vorbis configuration info missing\n");
+                av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n");
             if (!config)
                 return NULL;
 
             av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n"
                                     "a=fmtp:%d configuration=%s\r\n",
-                                    payload_type, c->sample_rate, c->channels,
+                                    payload_type, p->sample_rate, p->channels,
                                     payload_type, config);
             break;
         case AV_CODEC_ID_THEORA: {
             const char *pix_fmt;
-            switch (c->pix_fmt) {
+            switch (p->format) {
             case AV_PIX_FMT_YUV420P:
                 pix_fmt = "YCbCr-4:2:0";
                 break;
@@ -630,14 +634,14 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                 pix_fmt = "YCbCr-4:4:4";
                 break;
             default:
-                av_log(c, AV_LOG_ERROR, "Unsupported pixel format.\n");
+                av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n");
                 return NULL;
             }
 
-            if (c->extradata_size)
-                config = xiph_extradata2config(c);
+            if (p->extradata_size)
+                config = xiph_extradata2config(fmt, p);
             else
-                av_log(c, AV_LOG_ERROR, "Theora configuation info missing\n");
+                av_log(fmt, AV_LOG_ERROR, "Theora configuation info missing\n");
             if (!config)
                 return NULL;
 
@@ -646,13 +650,17 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                     "width=%d; height=%d; sampling=%s; "
                                     "configuration=%s\r\n",
                                     payload_type, payload_type,
-                                    c->width, c->height, pix_fmt, config);
+                                    p->width, p->height, pix_fmt, config);
             break;
         }
         case AV_CODEC_ID_VP8:
             av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n",
                                      payload_type);
             break;
+        case AV_CODEC_ID_VP9:
+            av_strlcatf(buff, size, "a=rtpmap:%d VP9/90000\r\n",
+                                     payload_type);
+            break;
         case AV_CODEC_ID_MJPEG:
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d JPEG/90000\r\n",
@@ -662,32 +670,32 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n",
                                          payload_type,
-                                         8000, c->channels);
+                                         8000, p->channels);
             break;
         case AV_CODEC_ID_ADPCM_G726: {
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d G726-%d/%d\r\n",
                                          payload_type,
-                                         c->bits_per_coded_sample*8,
-                                         c->sample_rate);
+                                         p->bits_per_coded_sample*8,
+                                         p->sample_rate);
             break;
         }
         case AV_CODEC_ID_ILBC:
             av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n"
                                     "a=fmtp:%d mode=%d\r\n",
-                                     payload_type, c->sample_rate,
-                                     payload_type, c->block_align == 38 ? 20 : 30);
+                                     payload_type, p->sample_rate,
+                                     payload_type, p->block_align == 38 ? 20 : 30);
             break;
         case AV_CODEC_ID_SPEEX:
             av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n",
-                                     payload_type, c->sample_rate);
-            if (c->codec) {
+                                     payload_type, p->sample_rate);
+            if (st->codec) {
                 const char *mode;
                 uint64_t vad_option;
 
-                if (c->flags & AV_CODEC_FLAG_QSCALE)
+                if (st->codec->flags & AV_CODEC_FLAG_QSCALE)
                       mode = "on";
-                else if (!av_opt_get_int(c, "vad", AV_OPT_FLAG_ENCODING_PARAM, &vad_option) && vad_option)
+                else if (!av_opt_get_int(st->codec, "vad", AV_OPT_FLAG_ENCODING_PARAM, &vad_option) && vad_option)
                       mode = "vad";
                 else
                       mode = "off";
@@ -705,8 +713,8 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                receivers MUST be able to receive and process stereo packets. */
             av_strlcatf(buff, size, "a=rtpmap:%d opus/48000/2\r\n",
                                      payload_type);
-            if (c->channels == 2) {
-                av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo:1\r\n",
+            if (p->channels == 2) {
+                av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo=1\r\n",
                                          payload_type);
             }
             break;
@@ -724,13 +732,13 @@ void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx,
                         const char *dest_addr, const char *dest_type,
                         int port, int ttl, AVFormatContext *fmt)
 {
-    AVCodecContext *c = st->codec;
+    AVCodecParameters *p = st->codecpar;
     const char *type;
     int payload_type;
 
-    payload_type = ff_rtp_get_payload_type(fmt, c, idx);
+    payload_type = ff_rtp_get_payload_type(fmt, st->codecpar, idx);
 
-    switch (c->codec_type) {
+    switch (p->codec_type) {
         case AVMEDIA_TYPE_VIDEO   : type = "video"      ; break;
         case AVMEDIA_TYPE_AUDIO   : type = "audio"      ; break;
         case AVMEDIA_TYPE_SUBTITLE: type = "text"       ; break;
@@ -739,11 +747,11 @@ void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx,
 
     av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type);
     sdp_write_address(buff, size, dest_addr, dest_type, ttl);
-    if (c->bit_rate) {
-        av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", (int64_t)c->bit_rate / 1000);
+    if (p->bit_rate) {
+        av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", (int64_t)p->bit_rate / 1000);
     }
 
-    sdp_write_media_attributes(buff, size, c, payload_type, fmt);
+    sdp_write_media_attributes(buff, size, st, payload_type, fmt);
 }
 
 int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
diff --git a/libavformat/sdr2.c b/libavformat/sdr2.c
index edb454c..c995333 100644
--- a/libavformat/sdr2.c
+++ b/libavformat/sdr2.c
@@ -47,16 +47,16 @@ static int sdr2_read_header(AVFormatContext *s)
 
     avio_skip(s->pb, 20);
     avpriv_set_pts_info(st, 64, 1, avio_rl32(s->pb));
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->width      = avio_rl32(s->pb);
-    st->codec->height     = avio_rl32(s->pb);
-    st->codec->codec_id   = AV_CODEC_ID_H264;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->width      = avio_rl32(s->pb);
+    st->codecpar->height     = avio_rl32(s->pb);
+    st->codecpar->codec_id   = AV_CODEC_ID_H264;
     st->need_parsing      = AVSTREAM_PARSE_FULL;
 
-    ast->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    ast->codec->channels    = 1;
-    ast->codec->sample_rate = 8000;
-    ast->codec->codec_id    = AV_CODEC_ID_PCM_S16LE;
+    ast->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    ast->codecpar->channels    = 1;
+    ast->codecpar->sample_rate = 8000;
+    ast->codecpar->codec_id    = AV_CODEC_ID_PCM_S16LE;
     avpriv_set_pts_info(ast, 64, 1, 8000);
 
     avio_seek(s->pb, FIRST, SEEK_SET);
diff --git a/libavformat/seek-test.c b/libavformat/seek-test.c
deleted file mode 100644
index bfd06db..0000000
--- a/libavformat/seek-test.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2003 Fabrice Bellard
- * Copyright (c) 2007 Michael Niedermayer
- *
- * 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 <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "libavutil/common.h"
-#include "libavutil/mathematics.h"
-#include "libavformat/avformat.h"
-
-static char buffer[20];
-
-static const char *ret_str(int v)
-{
-    switch (v) {
-    case AVERROR_EOF:     return "-EOF";
-    case AVERROR(EIO):    return "-EIO";
-    case AVERROR(ENOMEM): return "-ENOMEM";
-    case AVERROR(EINVAL): return "-EINVAL";
-    default:
-        snprintf(buffer, sizeof(buffer), "%2d", v);
-        return buffer;
-    }
-}
-
-static void ts_str(char buffer[60], int64_t ts, AVRational base)
-{
-    if (ts == AV_NOPTS_VALUE) {
-        strcpy(buffer, " NOPTS   ");
-        return;
-    }
-    ts= av_rescale_q(ts, base, (AVRational){1, 1000000});
-    snprintf(buffer, 60, "%c%"PRId64".%06"PRId64"", ts<0 ? '-' : ' ', FFABS(ts)/1000000, FFABS(ts)%1000000);
-}
-
-int main(int argc, char **argv)
-{
-    const char *filename;
-    AVFormatContext *ic = avformat_alloc_context();
-    int i, ret, stream_id;
-    int j;
-    int64_t timestamp;
-    AVDictionary *format_opts = NULL;
-    int64_t seekfirst = AV_NOPTS_VALUE;
-    int firstback=0;
-    int frame_count = 1;
-    int duration = 4;
-
-    for(i=2; i<argc; i+=2){
-        if       (!strcmp(argv[i], "-seekforw")){
-            seekfirst = atoi(argv[i+1]);
-        } else if(!strcmp(argv[i], "-seekback")){
-            seekfirst = atoi(argv[i+1]);
-            firstback = 1;
-        } else if(!strcmp(argv[i], "-frames")){
-            frame_count = atoi(argv[i+1]);
-        } else if(!strcmp(argv[i], "-duration")){
-            duration = atoi(argv[i+1]);
-        } else if(!strcmp(argv[i], "-fastseek")) {
-            if (atoi(argv[i+1])) {
-                ic->flags |= AVFMT_FLAG_FAST_SEEK;
-            }
-        } else {
-            argc = 1;
-        }
-    }
-
-    av_dict_set(&format_opts, "channels", "1", 0);
-    av_dict_set(&format_opts, "sample_rate", "22050", 0);
-
-    /* initialize libavcodec, and register all codecs and formats */
-    av_register_all();
-
-    if (argc < 2) {
-        printf("usage: %s input_file\n"
-               "\n", argv[0]);
-        return 1;
-    }
-
-    filename = argv[1];
-
-    ret = avformat_open_input(&ic, filename, NULL, &format_opts);
-    av_dict_free(&format_opts);
-    if (ret < 0) {
-        fprintf(stderr, "cannot open %s\n", filename);
-        return 1;
-    }
-
-    ret = avformat_find_stream_info(ic, NULL);
-    if (ret < 0) {
-        fprintf(stderr, "%s: could not find codec parameters\n", filename);
-        return 1;
-    }
-
-    if(seekfirst != AV_NOPTS_VALUE){
-        if(firstback)   avformat_seek_file(ic, -1, INT64_MIN, seekfirst, seekfirst, 0);
-        else            avformat_seek_file(ic, -1, seekfirst, seekfirst, INT64_MAX, 0);
-    }
-    for(i=0; ; i++){
-        AVPacket pkt = { 0 };
-        AVStream *av_uninit(st);
-        char ts_buf[60];
-
-        if(ret>=0){
-            for(j=0; j<frame_count; j++) {
-            ret= av_read_frame(ic, &pkt);
-            if(ret>=0){
-                char dts_buf[60];
-                st= ic->streams[pkt.stream_index];
-                ts_str(dts_buf, pkt.dts, st->time_base);
-                ts_str(ts_buf,  pkt.pts, st->time_base);
-                printf("ret:%-10s st:%2d flags:%d dts:%s pts:%s pos:%7" PRId64 " size:%6d", ret_str(ret), pkt.stream_index, pkt.flags, dts_buf, ts_buf, pkt.pos, pkt.size);
-                av_packet_unref(&pkt);
-            } else
-                printf("ret:%s", ret_str(ret)); // necessary to avoid trailing whitespace
-            printf("\n");
-            }
-        }
-
-        if(i>25) break;
-
-        stream_id= (i>>1)%(ic->nb_streams+1) - 1;
-        timestamp= (i*19362894167LL) % (duration*AV_TIME_BASE) - AV_TIME_BASE;
-        if(stream_id>=0){
-            st= ic->streams[stream_id];
-            timestamp= av_rescale_q(timestamp, AV_TIME_BASE_Q, st->time_base);
-        }
-        //FIXME fully test the new seek API
-        if(i&1) ret = avformat_seek_file(ic, stream_id, INT64_MIN, timestamp, timestamp, 0);
-        else    ret = avformat_seek_file(ic, stream_id, timestamp, timestamp, INT64_MAX, 0);
-        ts_str(ts_buf, timestamp, stream_id < 0 ? AV_TIME_BASE_Q : st->time_base);
-        printf("ret:%-10s st:%2d flags:%d  ts:%s\n", ret_str(ret), stream_id, i&1, ts_buf);
-    }
-
-    avformat_close_input(&ic);
-
-    return 0;
-}
diff --git a/libavformat/segafilm.c b/libavformat/segafilm.c
index 94b3772..1fdef50 100644
--- a/libavformat/segafilm.c
+++ b/libavformat/segafilm.c
@@ -1,6 +1,6 @@
 /*
  * Sega FILM Format (CPK) Demuxer
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -150,15 +150,15 @@ static int film_read_header(AVFormatContext *s)
         if (!st)
             return AVERROR(ENOMEM);
         film->video_stream_index = st->index;
-        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        st->codec->codec_id = film->video_type;
-        st->codec->codec_tag = 0;  /* no fourcc */
-        st->codec->width = AV_RB32(&scratch[16]);
-        st->codec->height = AV_RB32(&scratch[12]);
+        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        st->codecpar->codec_id = film->video_type;
+        st->codecpar->codec_tag = 0;  /* no fourcc */
+        st->codecpar->width = AV_RB32(&scratch[16]);
+        st->codecpar->height = AV_RB32(&scratch[12]);
 
         if (film->video_type == AV_CODEC_ID_RAWVIDEO) {
             if (scratch[20] == 24) {
-                st->codec->pix_fmt = AV_PIX_FMT_RGB24;
+                st->codecpar->format = AV_PIX_FMT_RGB24;
             } else {
                 av_log(s, AV_LOG_ERROR, "raw video is using unhandled %dbpp\n", scratch[20]);
                 return -1;
@@ -171,24 +171,24 @@ static int film_read_header(AVFormatContext *s)
         if (!st)
             return AVERROR(ENOMEM);
         film->audio_stream_index = st->index;
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id = film->audio_type;
-        st->codec->codec_tag = 1;
-        st->codec->channels = film->audio_channels;
-        st->codec->sample_rate = film->audio_samplerate;
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id = film->audio_type;
+        st->codecpar->codec_tag = 1;
+        st->codecpar->channels = film->audio_channels;
+        st->codecpar->sample_rate = film->audio_samplerate;
 
         if (film->audio_type == AV_CODEC_ID_ADPCM_ADX) {
-            st->codec->bits_per_coded_sample = 18 * 8 / 32;
-            st->codec->block_align = st->codec->channels * 18;
+            st->codecpar->bits_per_coded_sample = 18 * 8 / 32;
+            st->codecpar->block_align = st->codecpar->channels * 18;
             st->need_parsing = AVSTREAM_PARSE_FULL;
         } else {
-            st->codec->bits_per_coded_sample = film->audio_bits;
-            st->codec->block_align = st->codec->channels *
-                st->codec->bits_per_coded_sample / 8;
+            st->codecpar->bits_per_coded_sample = film->audio_bits;
+            st->codecpar->block_align = st->codecpar->channels *
+                st->codecpar->bits_per_coded_sample / 8;
         }
 
-        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
-            st->codec->bits_per_coded_sample;
+        st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+            st->codecpar->bits_per_coded_sample;
     }
 
     /* load the sample table */
@@ -206,7 +206,7 @@ static int film_read_header(AVFormatContext *s)
 
     for (i = 0; i < s->nb_streams; i++) {
         st = s->streams[i];
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
             avpriv_set_pts_info(st, 33, 1, film->base_clock);
         else
             avpriv_set_pts_info(st, 64, 1, film->audio_samplerate);
diff --git a/libavformat/segment.c b/libavformat/segment.c
index dd3b092..4c6c6d4 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -41,6 +41,7 @@
 #include "libavutil/parseutils.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/time.h"
+#include "libavutil/timecode.h"
 #include "libavutil/time_internal.h"
 #include "libavutil/timestamp.h"
 
@@ -95,6 +96,7 @@ typedef struct SegmentContext {
     char *time_str;        ///< segment duration specification string
     int64_t time;          ///< segment duration
     int use_strftime;      ///< flag to expand filename with strftime
+    int increment_tc;      ///< flag to increment timecode if found
 
     char *times_str;       ///< segment times specification string
     int64_t *times;        ///< list of segment interval specification
@@ -116,6 +118,7 @@ typedef struct SegmentContext {
     char *reference_stream_specifier; ///< reference stream specifier
     int   reference_stream_index;
     int   break_non_keyframes;
+    int   write_empty;
 
     int use_rename;
     char temp_list_filename[1024];
@@ -159,22 +162,23 @@ static int segment_mux_init(AVFormatContext *s)
     oc->opaque             = s->opaque;
     oc->io_close           = s->io_close;
     oc->io_open            = s->io_open;
+    oc->flags              = s->flags;
 
     for (i = 0; i < s->nb_streams; i++) {
         AVStream *st;
-        AVCodecContext *icodec, *ocodec;
+        AVCodecParameters *ipar, *opar;
 
         if (!(st = avformat_new_stream(oc, NULL)))
             return AVERROR(ENOMEM);
-        icodec = s->streams[i]->codec;
-        ocodec = st->codec;
-        avcodec_copy_context(ocodec, icodec);
+        ipar = s->streams[i]->codecpar;
+        opar = st->codecpar;
+        avcodec_parameters_copy(opar, ipar);
         if (!oc->oformat->codec_tag ||
-            av_codec_get_id (oc->oformat->codec_tag, icodec->codec_tag) == ocodec->codec_id ||
-            av_codec_get_tag(oc->oformat->codec_tag, icodec->codec_id) <= 0) {
-            ocodec->codec_tag = icodec->codec_tag;
+            av_codec_get_id (oc->oformat->codec_tag, ipar->codec_tag) == opar->codec_id ||
+            av_codec_get_tag(oc->oformat->codec_tag, ipar->codec_id) <= 0) {
+            opar->codec_tag = ipar->codec_tag;
         } else {
-            ocodec->codec_tag = 0;
+            opar->codec_tag = 0;
         }
         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
         st->time_base = s->streams[i]->time_base;
@@ -254,7 +258,11 @@ static int segment_start(AVFormatContext *s, int write_header)
         av_opt_set(oc->priv_data, "mpegts_flags", "+resend_headers", 0);
 
     if (write_header) {
-        if ((err = avformat_write_header(oc, NULL)) < 0)
+        AVDictionary *options = NULL;
+        av_dict_copy(&options, seg->format_options, 0);
+        err = avformat_write_header(oc, &options);
+        av_dict_free(&options);
+        if (err < 0)
             return err;
     }
 
@@ -337,6 +345,12 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last)
     SegmentContext *seg = s->priv_data;
     AVFormatContext *oc = seg->avf;
     int ret = 0;
+    AVTimecode tc;
+    AVRational rate;
+    AVDictionaryEntry *tcr;
+    char buf[AV_TIMECODE_STR_SIZE];
+    int i;
+    int err;
 
     av_write_frame(oc, NULL); /* Flush any buffered data (fragmented mp4) */
     if (write_trailer)
@@ -390,6 +404,29 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last)
            seg->avf->filename, seg->segment_count);
     seg->segment_count++;
 
+    if (seg->increment_tc) {
+        tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
+        if (tcr) {
+            /* search the first video stream */
+            for (i = 0; i < s->nb_streams; i++) {
+                if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
+                    rate = s->streams[i]->avg_frame_rate;/* Get fps from the video stream */
+                    err = av_timecode_init_from_string(&tc, rate, tcr->value, s);
+                    if (err < 0) {
+                        av_log(s, AV_LOG_WARNING, "Could not increment timecode, error occurred during timecode creation.");
+                        break;
+                    }
+                    tc.start += (int)((seg->cur_entry.end_time - seg->cur_entry.start_time) * av_q2d(rate));/* increment timecode */
+                    av_dict_set(&s->metadata, "timecode",
+                                av_timecode_make_string(&tc, buf, 0), 0);
+                    break;
+                }
+            }
+        } else {
+            av_log(s, AV_LOG_WARNING, "Could not increment timecode, no timecode metadata found");
+        }
+    }
+
 end:
     ff_format_io_close(oc, &oc->pb);
 
@@ -556,7 +593,7 @@ static int select_reference_stream(AVFormatContext *s)
 
         /* select first index for each type */
         for (i = 0; i < s->nb_streams; i++) {
-            type = s->streams[i]->codec->codec_type;
+            type = s->streams[i]->codecpar->codec_type;
             if ((unsigned)type < AVMEDIA_TYPE_NB && type_index_map[type] == -1
                 /* ignore attached pictures/cover art streams */
                 && !(s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC))
@@ -597,10 +634,10 @@ static void seg_free_context(SegmentContext *seg)
     seg->avf = NULL;
 }
 
-static int seg_write_header(AVFormatContext *s)
+static int seg_init(AVFormatContext *s)
 {
     SegmentContext *seg = s->priv_data;
-    AVFormatContext *oc = NULL;
+    AVFormatContext *oc = seg->avf;
     AVDictionary *options = NULL;
     int ret;
     int i;
@@ -671,6 +708,7 @@ static int seg_write_header(AVFormatContext *s)
             seg->use_rename = proto && !strcmp(proto, "file");
         }
     }
+
     if (seg->list_type == LIST_TYPE_EXT)
         av_log(s, AV_LOG_WARNING, "'ext' list type option is deprecated in favor of 'csv'\n");
 
@@ -678,7 +716,7 @@ static int seg_write_header(AVFormatContext *s)
         goto fail;
     av_log(s, AV_LOG_VERBOSE, "Selected stream id:%d type:%s\n",
            seg->reference_stream_index,
-           av_get_media_type_string(s->streams[seg->reference_stream_index]->codec->codec_type));
+           av_get_media_type_string(s->streams[seg->reference_stream_index]->codecpar->codec_type));
 
     seg->oformat = av_guess_format(seg->format, s->filename, NULL);
 
@@ -695,10 +733,10 @@ static int seg_write_header(AVFormatContext *s)
 
     if ((ret = segment_mux_init(s)) < 0)
         goto fail;
-    oc = seg->avf;
 
     if ((ret = set_segment_filename(s)) < 0)
         goto fail;
+    oc = seg->avf;
 
     if (seg->write_header_trailer) {
         if ((ret = s->io_open(s, &oc->pb,
@@ -774,6 +812,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
     if (!seg->avf)
         return AVERROR(EINVAL);
 
+calc_times:
     if (seg->times) {
         end_pts = seg->segment_count < seg->nb_times ?
             seg->times[seg->segment_count] : INT64_MAX;
@@ -805,11 +844,11 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
 
     if (pkt->stream_index == seg->reference_stream_index &&
         (pkt->flags & AV_PKT_FLAG_KEY || seg->break_non_keyframes) &&
-        seg->segment_frame_count > 0 &&
+        (seg->segment_frame_count > 0 || seg->write_empty) &&
         (seg->cut_pending || seg->frame_count >= start_frame ||
          (pkt->pts != AV_NOPTS_VALUE &&
           av_compare_ts(pkt->pts, st->time_base,
-                        end_pts-seg->time_delta, AV_TIME_BASE_Q) >= 0))) {
+                        end_pts - seg->time_delta, AV_TIME_BASE_Q) >= 0))) {
         /* sanitize end time in case last packet didn't have a defined duration */
         if (seg->cur_entry.last_duration == 0)
             seg->cur_entry.end_time = (double)pkt->pts * av_q2d(st->time_base);
@@ -824,11 +863,16 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
         seg->cur_entry.index = seg->segment_idx + seg->segment_idx_wrap * seg->segment_idx_wrap_nb;
         seg->cur_entry.start_time = (double)pkt->pts * av_q2d(st->time_base);
         seg->cur_entry.start_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q);
-        seg->cur_entry.end_time = seg->cur_entry.start_time +
-            pkt->pts != AV_NOPTS_VALUE ? (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base) : 0;
-    } else if (pkt->pts != AV_NOPTS_VALUE && pkt->stream_index == seg->reference_stream_index) {
-        seg->cur_entry.end_time =
-            FFMAX(seg->cur_entry.end_time, (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base));
+        seg->cur_entry.end_time = seg->cur_entry.start_time;
+
+        if (seg->times || (!seg->frames && !seg->use_clocktime) && seg->write_empty)
+            goto calc_times;
+    }
+
+    if (pkt->stream_index == seg->reference_stream_index) {
+        if (pkt->pts != AV_NOPTS_VALUE)
+            seg->cur_entry.end_time =
+                FFMAX(seg->cur_entry.end_time, (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base));
         seg->cur_entry.last_duration = pkt->duration;
     }
 
@@ -913,6 +957,25 @@ fail:
     return ret;
 }
 
+static int seg_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
+{
+    SegmentContext *seg = s->priv_data;
+    AVFormatContext *oc = seg->avf;
+    if (oc->oformat->check_bitstream) {
+        int ret = oc->oformat->check_bitstream(oc, pkt);
+        if (ret == 1) {
+            AVStream *st = s->streams[pkt->stream_index];
+            AVStream *ost = oc->streams[pkt->stream_index];
+            st->internal->bsfcs = ost->internal->bsfcs;
+            st->internal->nb_bsfcs = ost->internal->nb_bsfcs;
+            ost->internal->bsfcs = NULL;
+            ost->internal->nb_bsfcs = 0;
+        }
+        return ret;
+    }
+    return 1;
+}
+
 #define OFFSET(x) offsetof(SegmentContext, x)
 #define E AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
@@ -948,12 +1011,14 @@ static const AVOption options[] = {
     { "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
     { "segment_wrap_number", "set the number of wrap before the first segment", OFFSET(segment_idx_wrap_nb), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
     { "strftime",          "set filename expansion with strftime at segment creation", OFFSET(use_strftime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
+    { "increment_tc", "increment timecode between each segment", OFFSET(increment_tc), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
     { "break_non_keyframes", "allow breaking segments on non-keyframes", OFFSET(break_non_keyframes), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
 
     { "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, E },
     { "write_header_trailer", "write a header to the first segment and a trailer to the last one", OFFSET(write_header_trailer), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, E },
     { "reset_timestamps", "reset timestamps at the begin of each segment", OFFSET(reset_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
     { "initial_offset", "set initial timestamp offset", OFFSET(initial_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E },
+    { "write_empty_segments", "allow writing empty 'filler' segments", OFFSET(write_empty), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
     { NULL },
 };
 
@@ -969,9 +1034,10 @@ AVOutputFormat ff_segment_muxer = {
     .long_name      = NULL_IF_CONFIG_SMALL("segment"),
     .priv_data_size = sizeof(SegmentContext),
     .flags          = AVFMT_NOFILE|AVFMT_GLOBALHEADER,
-    .write_header   = seg_write_header,
+    .init           = seg_init,
     .write_packet   = seg_write_packet,
     .write_trailer  = seg_write_trailer,
+    .check_bitstream = seg_check_bitstream,
     .priv_class     = &seg_class,
 };
 
@@ -987,8 +1053,9 @@ AVOutputFormat ff_stream_segment_muxer = {
     .long_name      = NULL_IF_CONFIG_SMALL("streaming segment muxer"),
     .priv_data_size = sizeof(SegmentContext),
     .flags          = AVFMT_NOFILE,
-    .write_header   = seg_write_header,
+    .init           = seg_init,
     .write_packet   = seg_write_packet,
     .write_trailer  = seg_write_trailer,
+    .check_bitstream = seg_check_bitstream,
     .priv_class     = &sseg_class,
 };
diff --git a/libavformat/sierravmd.c b/libavformat/sierravmd.c
index 2ab0e38..734a3f2 100644
--- a/libavformat/sierravmd.c
+++ b/libavformat/sierravmd.c
@@ -1,6 +1,6 @@
 /*
  * Sierra VMD Format Demuxer
- * Copyright (c) 2004 The FFmpeg Project
+ * Copyright (c) 2004 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -118,18 +118,18 @@ static int vmd_read_header(AVFormatContext *s)
             return AVERROR(ENOMEM);
         avpriv_set_pts_info(vst, 33, 1, 10);
         vmd->video_stream_index = vst->index;
-        vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        vst->codec->codec_id = vmd->is_indeo3 ? AV_CODEC_ID_INDEO3 : AV_CODEC_ID_VMDVIDEO;
-        vst->codec->codec_tag = 0;  /* no fourcc */
-        vst->codec->width = width;
-        vst->codec->height = height;
-        if(vmd->is_indeo3 && vst->codec->width > 320){
-            vst->codec->width >>= 1;
-            vst->codec->height >>= 1;
+        vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        vst->codecpar->codec_id = vmd->is_indeo3 ? AV_CODEC_ID_INDEO3 : AV_CODEC_ID_VMDVIDEO;
+        vst->codecpar->codec_tag = 0;  /* no fourcc */
+        vst->codecpar->width = width;
+        vst->codecpar->height = height;
+        if(vmd->is_indeo3 && vst->codecpar->width > 320){
+            vst->codecpar->width >>= 1;
+            vst->codecpar->height >>= 1;
         }
-        if (ff_alloc_extradata(vst->codec, VMD_HEADER_SIZE))
+        if (ff_alloc_extradata(vst->codecpar, VMD_HEADER_SIZE))
             return AVERROR(ENOMEM);
-        memcpy(vst->codec->extradata, vmd->vmd_header, VMD_HEADER_SIZE);
+        memcpy(vst->codecpar->extradata, vmd->vmd_header, VMD_HEADER_SIZE);
     }
 
     /* if sample rate is 0, assume no audio */
@@ -139,30 +139,30 @@ static int vmd_read_header(AVFormatContext *s)
         if (!st)
             return AVERROR(ENOMEM);
         vmd->audio_stream_index = st->index;
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id = AV_CODEC_ID_VMDAUDIO;
-        st->codec->codec_tag = 0;  /* no fourcc */
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id   = AV_CODEC_ID_VMDAUDIO;
+        st->codecpar->codec_tag  = 0;  /* no fourcc */
         if (vmd->vmd_header[811] & 0x80) {
-            st->codec->channels       = 2;
-            st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+            st->codecpar->channels       = 2;
+            st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
         } else {
-            st->codec->channels       = 1;
-            st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+            st->codecpar->channels       = 1;
+            st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
         }
-        st->codec->sample_rate = vmd->sample_rate;
-        st->codec->block_align = AV_RL16(&vmd->vmd_header[806]);
-        if (st->codec->block_align & 0x8000) {
-            st->codec->bits_per_coded_sample = 16;
-            st->codec->block_align = -(st->codec->block_align - 0x10000);
+        st->codecpar->sample_rate = vmd->sample_rate;
+        st->codecpar->block_align = AV_RL16(&vmd->vmd_header[806]);
+        if (st->codecpar->block_align & 0x8000) {
+            st->codecpar->bits_per_coded_sample = 16;
+            st->codecpar->block_align = -(st->codecpar->block_align - 0x10000);
         } else {
-            st->codec->bits_per_coded_sample = 8;
+            st->codecpar->bits_per_coded_sample = 8;
         }
-        st->codec->bit_rate = st->codec->sample_rate *
-            st->codec->bits_per_coded_sample * st->codec->channels;
+        st->codecpar->bit_rate = st->codecpar->sample_rate *
+            st->codecpar->bits_per_coded_sample * st->codecpar->channels;
 
         /* calculate pts */
-        num = st->codec->block_align;
-        den = st->codec->sample_rate * st->codec->channels;
+        num = st->codecpar->block_align;
+        den = st->codecpar->sample_rate * st->codecpar->channels;
         av_reduce(&num, &den, num, den, (1UL<<31)-1);
         if (vst)
             avpriv_set_pts_info(vst, 33, num, den);
diff --git a/libavformat/siff.c b/libavformat/siff.c
index 028f18b..ddd1715 100644
--- a/libavformat/siff.c
+++ b/libavformat/siff.c
@@ -78,12 +78,12 @@ static int create_audio_stream(AVFormatContext *s, SIFFContext *c)
     ast = avformat_new_stream(s, NULL);
     if (!ast)
         return AVERROR(ENOMEM);
-    ast->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
-    ast->codec->codec_id              = AV_CODEC_ID_PCM_U8;
-    ast->codec->channels              = 1;
-    ast->codec->channel_layout        = AV_CH_LAYOUT_MONO;
-    ast->codec->bits_per_coded_sample = 8;
-    ast->codec->sample_rate           = c->rate;
+    ast->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
+    ast->codecpar->codec_id              = AV_CODEC_ID_PCM_U8;
+    ast->codecpar->channels              = 1;
+    ast->codecpar->channel_layout        = AV_CH_LAYOUT_MONO;
+    ast->codecpar->bits_per_coded_sample = 8;
+    ast->codecpar->sample_rate           = c->rate;
     avpriv_set_pts_info(ast, 16, 1, c->rate);
     ast->start_time                   = 0;
     return 0;
@@ -123,14 +123,14 @@ static int siff_parse_vbv1(AVFormatContext *s, SIFFContext *c, AVIOContext *pb)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_VB;
-    st->codec->codec_tag  = MKTAG('V', 'B', 'V', '1');
-    st->codec->width      = width;
-    st->codec->height     = height;
-    st->codec->pix_fmt    = AV_PIX_FMT_PAL8;
-    st->nb_frames         =
-    st->duration          = c->frames;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_VB;
+    st->codecpar->codec_tag  = MKTAG('V', 'B', 'V', '1');
+    st->codecpar->width      = width;
+    st->codecpar->height     = height;
+    st->codecpar->format     = AV_PIX_FMT_PAL8;
+    st->nb_frames            =
+    st->duration             = c->frames;
     avpriv_set_pts_info(st, 16, 1, 12);
 
     c->cur_frame = 0;
diff --git a/libavformat/smacker.c b/libavformat/smacker.c
index de8bbdb..8a21cc0 100644
--- a/libavformat/smacker.c
+++ b/libavformat/smacker.c
@@ -175,12 +175,12 @@ static int smacker_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     smk->videoindex = st->index;
-    st->codec->width = smk->width;
-    st->codec->height = smk->height;
-    st->codec->pix_fmt = AV_PIX_FMT_PAL8;
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_SMACKVIDEO;
-    st->codec->codec_tag = smk->magic;
+    st->codecpar->width = smk->width;
+    st->codecpar->height = smk->height;
+    st->codecpar->format = AV_PIX_FMT_PAL8;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_SMACKVIDEO;
+    st->codecpar->codec_tag = smk->magic;
     /* Smacker uses 100000 as internal timebase */
     if(smk->pts_inc < 0)
         smk->pts_inc = -smk->pts_inc;
@@ -198,36 +198,36 @@ static int smacker_read_header(AVFormatContext *s)
             if (!ast[i])
                 return AVERROR(ENOMEM);
             smk->indexes[i] = ast[i]->index;
-            ast[i]->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+            ast[i]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
             if (smk->aflags[i] & SMK_AUD_BINKAUD) {
-                ast[i]->codec->codec_id = AV_CODEC_ID_BINKAUDIO_RDFT;
+                ast[i]->codecpar->codec_id = AV_CODEC_ID_BINKAUDIO_RDFT;
             } else if (smk->aflags[i] & SMK_AUD_USEDCT) {
-                ast[i]->codec->codec_id = AV_CODEC_ID_BINKAUDIO_DCT;
+                ast[i]->codecpar->codec_id = AV_CODEC_ID_BINKAUDIO_DCT;
             } else if (smk->aflags[i] & SMK_AUD_PACKED){
-                ast[i]->codec->codec_id = AV_CODEC_ID_SMACKAUDIO;
-                ast[i]->codec->codec_tag = MKTAG('S', 'M', 'K', 'A');
+                ast[i]->codecpar->codec_id = AV_CODEC_ID_SMACKAUDIO;
+                ast[i]->codecpar->codec_tag = MKTAG('S', 'M', 'K', 'A');
             } else {
-                ast[i]->codec->codec_id = AV_CODEC_ID_PCM_U8;
+                ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
             }
             if (smk->aflags[i] & SMK_AUD_STEREO) {
-                ast[i]->codec->channels       = 2;
-                ast[i]->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+                ast[i]->codecpar->channels       = 2;
+                ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
             } else {
-                ast[i]->codec->channels       = 1;
-                ast[i]->codec->channel_layout = AV_CH_LAYOUT_MONO;
+                ast[i]->codecpar->channels       = 1;
+                ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
             }
-            ast[i]->codec->sample_rate = smk->rates[i];
-            ast[i]->codec->bits_per_coded_sample = (smk->aflags[i] & SMK_AUD_16BITS) ? 16 : 8;
-            if(ast[i]->codec->bits_per_coded_sample == 16 && ast[i]->codec->codec_id == AV_CODEC_ID_PCM_U8)
-                ast[i]->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
-            avpriv_set_pts_info(ast[i], 64, 1, ast[i]->codec->sample_rate
-                    * ast[i]->codec->channels * ast[i]->codec->bits_per_coded_sample / 8);
+            ast[i]->codecpar->sample_rate = smk->rates[i];
+            ast[i]->codecpar->bits_per_coded_sample = (smk->aflags[i] & SMK_AUD_16BITS) ? 16 : 8;
+            if(ast[i]->codecpar->bits_per_coded_sample == 16 && ast[i]->codecpar->codec_id == AV_CODEC_ID_PCM_U8)
+                ast[i]->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
+            avpriv_set_pts_info(ast[i], 64, 1, ast[i]->codecpar->sample_rate
+                    * ast[i]->codecpar->channels * ast[i]->codecpar->bits_per_coded_sample / 8);
         }
     }
 
 
     /* load trees to extradata, they will be unpacked by decoder */
-    if(ff_alloc_extradata(st->codec, smk->treesize + 16)){
+    if(ff_alloc_extradata(st->codecpar, smk->treesize + 16)){
         av_log(s, AV_LOG_ERROR,
                "Cannot allocate %"PRIu32" bytes of extradata\n",
                smk->treesize + 16);
@@ -235,16 +235,16 @@ static int smacker_read_header(AVFormatContext *s)
         av_freep(&smk->frm_flags);
         return AVERROR(ENOMEM);
     }
-    ret = avio_read(pb, st->codec->extradata + 16, st->codec->extradata_size - 16);
-    if(ret != st->codec->extradata_size - 16){
+    ret = avio_read(pb, st->codecpar->extradata + 16, st->codecpar->extradata_size - 16);
+    if(ret != st->codecpar->extradata_size - 16){
         av_freep(&smk->frm_size);
         av_freep(&smk->frm_flags);
         return AVERROR(EIO);
     }
-    ((int32_t*)st->codec->extradata)[0] = av_le2ne32(smk->mmap_size);
-    ((int32_t*)st->codec->extradata)[1] = av_le2ne32(smk->mclr_size);
-    ((int32_t*)st->codec->extradata)[2] = av_le2ne32(smk->full_size);
-    ((int32_t*)st->codec->extradata)[3] = av_le2ne32(smk->type_size);
+    ((int32_t*)st->codecpar->extradata)[0] = av_le2ne32(smk->mmap_size);
+    ((int32_t*)st->codecpar->extradata)[1] = av_le2ne32(smk->mclr_size);
+    ((int32_t*)st->codecpar->extradata)[2] = av_le2ne32(smk->full_size);
+    ((int32_t*)st->codecpar->extradata)[3] = av_le2ne32(smk->type_size);
 
     smk->curstream = -1;
     smk->nextpos = avio_tell(pb);
diff --git a/libavformat/smjpegdec.c b/libavformat/smjpegdec.c
index 99ca2ff..c184c0d 100644
--- a/libavformat/smjpegdec.c
+++ b/libavformat/smjpegdec.c
@@ -88,13 +88,13 @@ static int smjpeg_read_header(AVFormatContext *s)
             ast = avformat_new_stream(s, 0);
             if (!ast)
                 return AVERROR(ENOMEM);
-            ast->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-            ast->codec->sample_rate = avio_rb16(pb);
-            ast->codec->bits_per_coded_sample = avio_r8(pb);
-            ast->codec->channels    = avio_r8(pb);
-            ast->codec->codec_tag   = avio_rl32(pb);
-            ast->codec->codec_id    = ff_codec_get_id(ff_codec_smjpeg_audio_tags,
-                                                      ast->codec->codec_tag);
+            ast->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+            ast->codecpar->sample_rate = avio_rb16(pb);
+            ast->codecpar->bits_per_coded_sample = avio_r8(pb);
+            ast->codecpar->channels    = avio_r8(pb);
+            ast->codecpar->codec_tag   = avio_rl32(pb);
+            ast->codecpar->codec_id    = ff_codec_get_id(ff_codec_smjpeg_audio_tags,
+                                                         ast->codecpar->codec_tag);
             ast->duration           = duration;
             sc->audio_stream_index  = ast->index;
             avpriv_set_pts_info(ast, 32, 1, 1000);
@@ -111,13 +111,13 @@ static int smjpeg_read_header(AVFormatContext *s)
             vst = avformat_new_stream(s, 0);
             if (!vst)
                 return AVERROR(ENOMEM);
-            vst->nb_frames         = avio_rb32(pb);
-            vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            vst->codec->width      = avio_rb16(pb);
-            vst->codec->height     = avio_rb16(pb);
-            vst->codec->codec_tag  = avio_rl32(pb);
-            vst->codec->codec_id   = ff_codec_get_id(ff_codec_smjpeg_video_tags,
-                                                     vst->codec->codec_tag);
+            vst->nb_frames            = avio_rb32(pb);
+            vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            vst->codecpar->width      = avio_rb16(pb);
+            vst->codecpar->height     = avio_rb16(pb);
+            vst->codecpar->codec_tag  = avio_rl32(pb);
+            vst->codecpar->codec_id   = ff_codec_get_id(ff_codec_smjpeg_video_tags,
+                                                        vst->codecpar->codec_tag);
             vst->duration          = duration;
             sc->video_stream_index = vst->index;
             avpriv_set_pts_info(vst, 32, 1, 1000);
diff --git a/libavformat/smjpegenc.c b/libavformat/smjpegenc.c
index 430a497..314593a 100644
--- a/libavformat/smjpegenc.c
+++ b/libavformat/smjpegenc.c
@@ -46,6 +46,7 @@ static int smjpeg_write_header(AVFormatContext *s)
     avio_wb32(pb, 0);
     avio_wb32(pb, 0);
 
+    ff_standardize_creation_time(s);
     while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) {
         avio_wl32(pb, SMJPEG_TXT);
         avio_wb32(pb, strlen(t->key) + strlen(t->value) + 3);
@@ -56,22 +57,22 @@ static int smjpeg_write_header(AVFormatContext *s)
 
     for (n = 0; n < s->nb_streams; n++) {
         AVStream *st = s->streams[n];
-        AVCodecContext *codec = st->codec;
-        if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            tag = ff_codec_get_tag(ff_codec_smjpeg_audio_tags, codec->codec_id);
+        AVCodecParameters *par = st->codecpar;
+        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
+            tag = ff_codec_get_tag(ff_codec_smjpeg_audio_tags, par->codec_id);
             if (!tag) {
                 av_log(s, AV_LOG_ERROR, "unsupported audio codec\n");
                 return AVERROR(EINVAL);
             }
             avio_wl32(pb, SMJPEG_SND);
             avio_wb32(pb, 8);
-            avio_wb16(pb, codec->sample_rate);
-            avio_w8(pb, codec->bits_per_coded_sample);
-            avio_w8(pb, codec->channels);
+            avio_wb16(pb, par->sample_rate);
+            avio_w8(pb, par->bits_per_coded_sample);
+            avio_w8(pb, par->channels);
             avio_wl32(pb, tag);
             avpriv_set_pts_info(st, 32, 1, 1000);
-        } else if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-            tag = ff_codec_get_tag(ff_codec_smjpeg_video_tags, codec->codec_id);
+        } else if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
+            tag = ff_codec_get_tag(ff_codec_smjpeg_video_tags, par->codec_id);
             if (!tag) {
                 av_log(s, AV_LOG_ERROR, "unsupported video codec\n");
                 return AVERROR(EINVAL);
@@ -79,8 +80,8 @@ static int smjpeg_write_header(AVFormatContext *s)
             avio_wl32(pb, SMJPEG_VID);
             avio_wb32(pb, 12);
             avio_wb32(pb, 0);
-            avio_wb16(pb, codec->width);
-            avio_wb16(pb, codec->height);
+            avio_wb16(pb, par->width);
+            avio_wb16(pb, par->height);
             avio_wl32(pb, tag);
             avpriv_set_pts_info(st, 32, 1, 1000);
         }
@@ -97,11 +98,11 @@ static int smjpeg_write_packet(AVFormatContext *s, AVPacket *pkt)
     SMJPEGMuxContext *smc = s->priv_data;
     AVIOContext *pb = s->pb;
     AVStream *st = s->streams[pkt->stream_index];
-    AVCodecContext *codec = st->codec;
+    AVCodecParameters *par = st->codecpar;
 
-    if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
+    if (par->codec_type == AVMEDIA_TYPE_AUDIO)
         avio_wl32(pb, SMJPEG_SNDD);
-    else if (codec->codec_type == AVMEDIA_TYPE_VIDEO)
+    else if (par->codec_type == AVMEDIA_TYPE_VIDEO)
         avio_wl32(pb, SMJPEG_VIDD);
     else
         return 0;
diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index f36e5fe..dabd1ea 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -122,8 +122,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
             AVDictionary *opts = NULL;
             os->tail_out = os->out;
             av_dict_set(&opts, "truncate", "0", 0);
-            ret = ffurl_open_whitelist(&os->out, frag->file, AVIO_FLAG_READ_WRITE,
-                                       &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist);
+            ret = ffurl_open_whitelist(&os->out, frag->file, AVIO_FLAG_WRITE,
+                                       &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist, os->ctx->protocol_blacklist, NULL);
             av_dict_free(&opts);
             if (ret < 0) {
                 os->out = os->tail_out;
@@ -131,8 +131,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
                 return ret;
             }
             av_dict_set(&opts, "truncate", "0", 0);
-            ffurl_open_whitelist(&os->out2, frag->infofile, AVIO_FLAG_READ_WRITE,
-                                 &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist);
+            ffurl_open_whitelist(&os->out2, frag->infofile, AVIO_FLAG_WRITE,
+                                 &os->ctx->interrupt_callback, &opts, os->ctx->protocol_whitelist, os->ctx->protocol_blacklist, NULL);
             av_dict_free(&opts);
             ffurl_seek(os->out, offset - frag->start_pos, SEEK_SET);
             if (os->out2)
@@ -146,14 +146,14 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
 
 static void get_private_data(OutputStream *os)
 {
-    AVCodecContext *codec = os->ctx->streams[0]->codec;
-    uint8_t *ptr = codec->extradata;
-    int size = codec->extradata_size;
+    AVCodecParameters *par = os->ctx->streams[0]->codecpar;
+    uint8_t *ptr = par->extradata;
+    int size = par->extradata_size;
     int i;
-    if (codec->codec_id == AV_CODEC_ID_H264) {
+    if (par->codec_id == AV_CODEC_ID_H264) {
         ff_avc_write_annexb_extradata(ptr, &ptr, &size);
         if (!ptr)
-            ptr = codec->extradata;
+            ptr = par->extradata;
     }
     if (!ptr)
         return;
@@ -163,7 +163,7 @@ static void get_private_data(OutputStream *os)
     for (i = 0; i < size; i++)
         snprintf(&os->private_str[2*i], 3, "%02x", ptr[i]);
 fail:
-    if (ptr != codec->extradata)
+    if (ptr != par->extradata)
         av_free(ptr);
 }
 
@@ -235,7 +235,7 @@ static int write_manifest(AVFormatContext *s, int final)
             Fragment *last = os->fragments[os->nb_fragments - 1];
             duration = last->start_time + last->duration;
         }
-        if (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             video_chunks = os->nb_fragments;
             video_streams++;
         } else {
@@ -260,10 +260,10 @@ static int write_manifest(AVFormatContext *s, int final)
         avio_printf(out, "<StreamIndex Type=\"video\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n", video_streams, video_chunks);
         for (i = 0; i < s->nb_streams; i++) {
             OutputStream *os = &c->streams[i];
-            if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
+            if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
                 continue;
             last = i;
-            avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%"PRId64"\" FourCC=\"%s\" MaxWidth=\"%d\" MaxHeight=\"%d\" CodecPrivateData=\"%s\" />\n", index, (int64_t)s->streams[i]->codec->bit_rate, os->fourcc, s->streams[i]->codec->width, s->streams[i]->codec->height, os->private_str);
+            avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%"PRId64"\" FourCC=\"%s\" MaxWidth=\"%d\" MaxHeight=\"%d\" CodecPrivateData=\"%s\" />\n", index, (int64_t)s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height, os->private_str);
             index++;
         }
         output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
@@ -274,10 +274,10 @@ static int write_manifest(AVFormatContext *s, int final)
         avio_printf(out, "<StreamIndex Type=\"audio\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n", audio_streams, audio_chunks);
         for (i = 0; i < s->nb_streams; i++) {
             OutputStream *os = &c->streams[i];
-            if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+            if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
                 continue;
             last = i;
-            avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%"PRId64"\" FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" BitsPerSample=\"16\" PacketSize=\"%d\" AudioTag=\"%d\" CodecPrivateData=\"%s\" />\n", index, (int64_t)s->streams[i]->codec->bit_rate, os->fourcc, s->streams[i]->codec->sample_rate, s->streams[i]->codec->channels, os->packet_size, os->audio_tag, os->private_str);
+            avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%"PRId64"\" FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" BitsPerSample=\"16\" PacketSize=\"%d\" AudioTag=\"%d\" CodecPrivateData=\"%s\" />\n", index, (int64_t)s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->sample_rate, s->streams[i]->codecpar->channels, os->packet_size, os->audio_tag, os->private_str);
             index++;
         }
         output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
@@ -319,12 +319,12 @@ static int ism_write_header(AVFormatContext *s)
         AVStream *st;
         AVDictionary *opts = NULL;
 
-        if (!s->streams[i]->codec->bit_rate) {
+        if (!s->streams[i]->codecpar->bit_rate) {
             av_log(s, AV_LOG_ERROR, "No bit rate set for stream %d\n", i);
             ret = AVERROR(EINVAL);
             goto fail;
         }
-        snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->filename, (int64_t)s->streams[i]->codec->bit_rate);
+        snprintf(os->dirname, sizeof(os->dirname), "%s/QualityLevels(%"PRId64")", s->filename, (int64_t)s->streams[i]->codecpar->bit_rate);
         if (mkdir(os->dirname, 0777) == -1 && errno != EEXIST) {
             ret = AVERROR(errno);
             av_log(s, AV_LOG_ERROR, "mkdir failed\n");
@@ -332,7 +332,7 @@ static int ism_write_header(AVFormatContext *s)
         }
 
         ctx = avformat_alloc_context();
-        if (!ctx || ff_copy_whitelists(ctx, s) < 0) {
+        if (!ctx || ff_copy_whiteblacklists(ctx, s) < 0) {
             ret = AVERROR(ENOMEM);
             goto fail;
         }
@@ -344,7 +344,7 @@ static int ism_write_header(AVFormatContext *s)
             ret = AVERROR(ENOMEM);
             goto fail;
         }
-        avcodec_copy_context(st->codec, s->streams[i]->codec);
+        avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
         st->time_base = s->streams[i]->time_base;
 
@@ -363,12 +363,12 @@ static int ism_write_header(AVFormatContext *s)
         avio_flush(ctx->pb);
         av_dict_free(&opts);
         s->streams[i]->time_base = st->time_base;
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             c->has_video = 1;
             os->stream_type_tag = "video";
-            if (st->codec->codec_id == AV_CODEC_ID_H264) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
                 os->fourcc = "H264";
-            } else if (st->codec->codec_id == AV_CODEC_ID_VC1) {
+            } else if (st->codecpar->codec_id == AV_CODEC_ID_VC1) {
                 os->fourcc = "WVC1";
             } else {
                 av_log(s, AV_LOG_ERROR, "Unsupported video codec\n");
@@ -378,10 +378,10 @@ static int ism_write_header(AVFormatContext *s)
         } else {
             c->has_audio = 1;
             os->stream_type_tag = "audio";
-            if (st->codec->codec_id == AV_CODEC_ID_AAC) {
+            if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
                 os->fourcc = "AACL";
                 os->audio_tag = 0xff;
-            } else if (st->codec->codec_id == AV_CODEC_ID_WMAPRO) {
+            } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) {
                 os->fourcc = "WMAP";
                 os->audio_tag = 0x0162;
             } else {
@@ -389,7 +389,7 @@ static int ism_write_header(AVFormatContext *s)
                 ret = AVERROR(EINVAL);
                 goto fail;
             }
-            os->packet_size = st->codec->block_align ? st->codec->block_align : 4;
+            os->packet_size = st->codecpar->block_align ? st->codecpar->block_align : 4;
         }
         get_private_data(os);
     }
@@ -526,7 +526,7 @@ static int ism_flush(AVFormatContext *s, int final)
             continue;
 
         snprintf(filename, sizeof(filename), "%s/temp", os->dirname);
-        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist);
+        ret = ffurl_open_whitelist(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL);
         if (ret < 0)
             break;
         os->cur_start_pos = os->tail_pos;
@@ -588,7 +588,7 @@ static int ism_write_packet(AVFormatContext *s, AVPacket *pkt)
     if (st->first_dts == AV_NOPTS_VALUE)
         st->first_dts = pkt->dts;
 
-    if ((!c->has_video || st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
+    if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
         av_compare_ts(pkt->dts - st->first_dts, st->time_base,
                       end_dts, AV_TIME_BASE_Q) >= 0 &&
         pkt->flags & AV_PKT_FLAG_KEY && os->packets_written) {
diff --git a/libavformat/smush.c b/libavformat/smush.c
index abb6989..5a9249a 100644
--- a/libavformat/smush.c
+++ b/libavformat/smush.c
@@ -151,19 +151,19 @@ static int smush_read_header(AVFormatContext *ctx)
     vst->duration          =
     vst->nb_frames         = nframes;
     vst->avg_frame_rate    = av_inv_q(vst->time_base);
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_id   = AV_CODEC_ID_SANM;
-    vst->codec->codec_tag  = 0;
-    vst->codec->width      = width;
-    vst->codec->height     = height;
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_id   = AV_CODEC_ID_SANM;
+    vst->codecpar->codec_tag  = 0;
+    vst->codecpar->width      = width;
+    vst->codecpar->height     = height;
 
     if (!smush->version) {
-        if (ff_alloc_extradata(vst->codec, 1024 + 2))
+        if (ff_alloc_extradata(vst->codecpar, 1024 + 2))
             return AVERROR(ENOMEM);
 
-        AV_WL16(vst->codec->extradata, subversion);
+        AV_WL16(vst->codecpar->extradata, subversion);
         for (i = 0; i < 256; i++)
-            AV_WL32(vst->codec->extradata + 2 + i * 4, palette[i]);
+            AV_WL32(vst->codecpar->extradata + 2 + i * 4, palette[i]);
     }
 
     if (got_audio) {
@@ -174,13 +174,13 @@ static int smush_read_header(AVFormatContext *ctx)
         smush->audio_stream_index = ast->index;
 
         ast->start_time         = 0;
-        ast->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-        ast->codec->codec_id    = AV_CODEC_ID_ADPCM_VIMA;
-        ast->codec->codec_tag   = 0;
-        ast->codec->sample_rate = sample_rate;
-        ast->codec->channels    = channels;
+        ast->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+        ast->codecpar->codec_id    = AV_CODEC_ID_ADPCM_VIMA;
+        ast->codecpar->codec_tag   = 0;
+        ast->codecpar->sample_rate = sample_rate;
+        ast->codecpar->channels    = channels;
 
-        avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
+        avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
     }
 
     return 0;
diff --git a/libavformat/sol.c b/libavformat/sol.c
index c943453..5796f8d 100644
--- a/libavformat/sol.c
+++ b/libavformat/sol.c
@@ -110,13 +110,13 @@ static int sol_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return -1;
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_tag = id;
-    st->codec->codec_id = codec;
-    st->codec->channels = channels;
-    st->codec->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO :
-                                                AV_CH_LAYOUT_STEREO;
-    st->codec->sample_rate = rate;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_tag = id;
+    st->codecpar->codec_id = codec;
+    st->codecpar->channels = channels;
+    st->codecpar->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO :
+                                                   AV_CH_LAYOUT_STEREO;
+    st->codecpar->sample_rate = rate;
     avpriv_set_pts_info(st, 64, 1, rate);
     return 0;
 }
diff --git a/libavformat/soxdec.c b/libavformat/soxdec.c
index aec4284..0a937e7 100644
--- a/libavformat/soxdec.c
+++ b/libavformat/soxdec.c
@@ -55,21 +55,21 @@ static int sox_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
 
     if (avio_rl32(pb) == SOX_TAG) {
-        st->codec->codec_id = AV_CODEC_ID_PCM_S32LE;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
         header_size         = avio_rl32(pb);
         avio_skip(pb, 8); /* sample count */
         sample_rate         = av_int2double(avio_rl64(pb));
-        st->codec->channels = avio_rl32(pb);
+        st->codecpar->channels = avio_rl32(pb);
         comment_size        = avio_rl32(pb);
     } else {
-        st->codec->codec_id = AV_CODEC_ID_PCM_S32BE;
+        st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE;
         header_size         = avio_rb32(pb);
         avio_skip(pb, 8); /* sample count */
         sample_rate         = av_int2double(avio_rb64(pb));
-        st->codec->channels = avio_rb32(pb);
+        st->codecpar->channels = avio_rb32(pb);
         comment_size        = avio_rb32(pb);
     }
 
@@ -90,7 +90,7 @@ static int sox_read_header(AVFormatContext *s)
                sample_rate_frac);
 
     if ((header_size + 4) & 7 || header_size < SOX_FIXED_HDR + comment_size
-        || st->codec->channels > 65535) /* Reserve top 16 bits */ {
+        || st->codecpar->channels > 65535) /* Reserve top 16 bits */ {
         av_log(s, AV_LOG_ERROR, "invalid header\n");
         return AVERROR_INVALIDDATA;
     }
@@ -111,15 +111,15 @@ static int sox_read_header(AVFormatContext *s)
 
     avio_skip(pb, header_size - SOX_FIXED_HDR - comment_size);
 
-    st->codec->sample_rate           = sample_rate;
-    st->codec->bits_per_coded_sample = 32;
-    st->codec->bit_rate              = st->codec->sample_rate *
-                                       st->codec->bits_per_coded_sample *
-                                       st->codec->channels;
-    st->codec->block_align           = st->codec->bits_per_coded_sample *
-                                       st->codec->channels / 8;
+    st->codecpar->sample_rate           = sample_rate;
+    st->codecpar->bits_per_coded_sample = 32;
+    st->codecpar->bit_rate              = st->codecpar->sample_rate *
+                                          st->codecpar->bits_per_coded_sample *
+                                          st->codecpar->channels;
+    st->codecpar->block_align           = st->codecpar->bits_per_coded_sample *
+                                          st->codecpar->channels / 8;
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
diff --git a/libavformat/soxenc.c b/libavformat/soxenc.c
index bfa9002..b307157 100644
--- a/libavformat/soxenc.c
+++ b/libavformat/soxenc.c
@@ -45,7 +45,7 @@ static int sox_write_header(AVFormatContext *s)
 {
     SoXContext *sox = s->priv_data;
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     AVDictionaryEntry *comment;
     size_t comment_len = 0, comment_size;
 
@@ -56,19 +56,19 @@ static int sox_write_header(AVFormatContext *s)
 
     sox->header_size = SOX_FIXED_HDR + comment_size;
 
-    if (enc->codec_id == AV_CODEC_ID_PCM_S32LE) {
+    if (par->codec_id == AV_CODEC_ID_PCM_S32LE) {
         ffio_wfourcc(pb, ".SoX");
         avio_wl32(pb, sox->header_size);
         avio_wl64(pb, 0); /* number of samples */
-        avio_wl64(pb, av_double2int(enc->sample_rate));
-        avio_wl32(pb, enc->channels);
+        avio_wl64(pb, av_double2int(par->sample_rate));
+        avio_wl32(pb, par->channels);
         avio_wl32(pb, comment_size);
-    } else if (enc->codec_id == AV_CODEC_ID_PCM_S32BE) {
+    } else if (par->codec_id == AV_CODEC_ID_PCM_S32BE) {
         ffio_wfourcc(pb, "XoS.");
         avio_wb32(pb, sox->header_size);
         avio_wb64(pb, 0); /* number of samples */
-        avio_wb64(pb, av_double2int(enc->sample_rate));
-        avio_wb32(pb, enc->channels);
+        avio_wb64(pb, av_double2int(par->sample_rate));
+        avio_wb32(pb, par->channels);
         avio_wb32(pb, comment_size);
     } else {
         av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n");
@@ -89,14 +89,14 @@ static int sox_write_trailer(AVFormatContext *s)
 {
     SoXContext *sox = s->priv_data;
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
     if (s->pb->seekable) {
         /* update number of samples */
         int64_t file_size = avio_tell(pb);
         int64_t num_samples = (file_size - sox->header_size - 4LL) >> 2LL;
         avio_seek(pb, 8, SEEK_SET);
-        if (enc->codec_id == AV_CODEC_ID_PCM_S32LE) {
+        if (par->codec_id == AV_CODEC_ID_PCM_S32LE) {
             avio_wl64(pb, num_samples);
         } else
             avio_wb64(pb, num_samples);
diff --git a/libavformat/spdif.h b/libavformat/spdif.h
index fee4ff7..0039fcf 100644
--- a/libavformat/spdif.h
+++ b/libavformat/spdif.h
@@ -54,8 +54,8 @@ enum IEC61937DataType {
 
 static const uint16_t spdif_mpeg_pkt_offset[2][3] = {
     //LAYER1  LAYER2  LAYER3
-    { 3072,    9216,   4608 }, // MPEG2 LSF
-    { 1536,    4608,   4608 }, // MPEG1
+    { 3072,    9216,   4608 }, // MPEG-2 LSF
+    { 1536,    4608,   4608 }, // MPEG-1
 };
 
 void ff_spdif_bswap_buf16(uint16_t *dst, const uint16_t *src, int w);
diff --git a/libavformat/spdifdec.c b/libavformat/spdifdec.c
index a2f06a9..f728837 100644
--- a/libavformat/spdifdec.c
+++ b/libavformat/spdifdec.c
@@ -215,17 +215,17 @@ int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt)
             av_packet_unref(pkt);
             return AVERROR(ENOMEM);
         }
-        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-        st->codec->codec_id = codec_id;
-    } else if (codec_id != s->streams[0]->codec->codec_id) {
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+        st->codecpar->codec_id = codec_id;
+    } else if (codec_id != s->streams[0]->codecpar->codec_id) {
         avpriv_report_missing_feature(s, "Codec change in IEC 61937");
         return AVERROR_PATCHWELCOME;
     }
 
-    if (!s->bit_rate && s->streams[0]->codec->sample_rate)
+    if (!s->bit_rate && s->streams[0]->codecpar->sample_rate)
         /* stream bitrate matches 16-bit stereo PCM bitrate for currently
            supported codecs */
-        s->bit_rate = 2 * 16 * s->streams[0]->codec->sample_rate;
+        s->bit_rate = 2 * 16 * s->streams[0]->codecpar->sample_rate;
 
     return 0;
 }
diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c
index 64c5f38..daf1c1f 100644
--- a/libavformat/spdifenc.c
+++ b/libavformat/spdifenc.c
@@ -32,7 +32,7 @@
 /*
  * Terminology used in specification:
  * data-burst - IEC61937 frame, contains header and encapsuled frame
- * burst-preambule - IEC61937 frame header, contains 16-bits words named Pa, Pb, Pc and Pd
+ * burst-preamble - IEC61937 frame header, contains 16-bit words named Pa, Pb, Pc and Pd
  * burst-payload - encapsuled frame
  * Pa, Pb - syncword - 0xF872, 0x4E1F
  * Pc - burst-info, contains data-type (bits 0-6), error flag (bit 7), data-type-dependent info (bits 8-12)
@@ -147,7 +147,7 @@ static int spdif_header_eac3(AVFormatContext *s, AVPacket *pkt)
  * DTS type IV (DTS-HD) can be transmitted with various frame repetition
  * periods; longer repetition periods allow for longer packets and therefore
  * higher bitrate. Longer repetition periods mean that the constant bitrate of
- * the outputted IEC 61937 stream is higher.
+ * the output IEC 61937 stream is higher.
  * The repetition period is measured in IEC 60958 frames (4 bytes).
  */
 static int spdif_dts4_subtype(int period)
@@ -319,8 +319,8 @@ static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt)
 
 static const enum IEC61937DataType mpeg_data_type[2][3] = {
     //     LAYER1                      LAYER2                  LAYER3
-    { IEC61937_MPEG2_LAYER1_LSF, IEC61937_MPEG2_LAYER2_LSF, IEC61937_MPEG2_LAYER3_LSF },//MPEG2 LSF
-    { IEC61937_MPEG1_LAYER1,     IEC61937_MPEG1_LAYER23,    IEC61937_MPEG1_LAYER23 },   //MPEG1
+    { IEC61937_MPEG2_LAYER1_LSF, IEC61937_MPEG2_LAYER2_LSF, IEC61937_MPEG2_LAYER3_LSF }, // MPEG-2 LSF
+    { IEC61937_MPEG1_LAYER1,     IEC61937_MPEG1_LAYER23,    IEC61937_MPEG1_LAYER23 },    // MPEG-1
 };
 
 static int spdif_header_mpeg(AVFormatContext *s, AVPacket *pkt)
@@ -444,7 +444,7 @@ static int spdif_write_header(AVFormatContext *s)
 {
     IEC61937Context *ctx = s->priv_data;
 
-    switch (s->streams[0]->codec->codec_id) {
+    switch (s->streams[0]->codecpar->codec_id) {
     case AV_CODEC_ID_AC3:
         ctx->header_info = spdif_header_ac3;
         break;
diff --git a/libavformat/srtdec.c b/libavformat/srtdec.c
index 6113f70..067db63 100644
--- a/libavformat/srtdec.c
+++ b/libavformat/srtdec.c
@@ -52,8 +52,11 @@ static int srt_probe(AVProbeData *p)
     /* Check if the next line matches a SRT timestamp */
     if (ff_subtitles_read_line(&tr, buf, sizeof(buf)) < 0)
         return 0;
-    if (buf[0] >= '0' && buf[0] <= '9' && strstr(buf, " --> ")
-        && sscanf(buf, "%*d:%*2d:%*2d%*1[,.]%*3d --> %*d:%*2d:%*2d%*1[,.]%3d", &v) == 1)
+    pbuf = buf;
+    if (buf[0] == '-')
+        pbuf++;
+    if (pbuf[0] >= '0' && pbuf[0] <= '9' && strstr(buf, " --> ")
+        && sscanf(buf, "%*d:%*d:%*d%*1[,.]%*d --> %*d:%*d:%*d%*1[,.]%d", &v) == 1)
         return AVPROBE_SCORE_MAX;
 
     return 0;
@@ -74,7 +77,7 @@ static int get_event_info(const char *line, struct event_info *ei)
     ei->x1 = ei->x2 = ei->y1 = ei->y2 = ei->duration = -1;
     ei->pts = AV_NOPTS_VALUE;
     ei->pos = -1;
-    if (sscanf(line, "%d:%2d:%2d%*1[,.]%3d --> %d:%2d:%2d%*1[,.]%3d"
+    if (sscanf(line, "%d:%d:%d%*1[,.]%d --> %d:%d:%d%*1[,.]%d"
                "%*[ ]X1:%u X2:%u Y1:%u Y2:%u",
                &hh1, &mm1, &ss1, &ms1,
                &hh2, &mm2, &ss2, &ms2,
@@ -135,8 +138,8 @@ static int srt_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 1000);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_SUBRIP;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_SUBRIP;
 
     av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
 
diff --git a/libavformat/srtenc.c b/libavformat/srtenc.c
index 24c25ec..d811a4d 100644
--- a/libavformat/srtenc.c
+++ b/libavformat/srtenc.c
@@ -39,16 +39,16 @@ static int srt_write_header(AVFormatContext *avf)
     SRTContext *srt = avf->priv_data;
 
     if (avf->nb_streams != 1 ||
-        avf->streams[0]->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) {
+        avf->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
         av_log(avf, AV_LOG_ERROR,
                "SRT supports only a single subtitles stream.\n");
         return AVERROR(EINVAL);
     }
-    if (avf->streams[0]->codec->codec_id != AV_CODEC_ID_TEXT &&
-        avf->streams[0]->codec->codec_id != AV_CODEC_ID_SUBRIP) {
+    if (avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_TEXT &&
+        avf->streams[0]->codecpar->codec_id != AV_CODEC_ID_SUBRIP) {
         av_log(avf, AV_LOG_ERROR,
                "Unsupported subtitles codec: %s\n",
-               avcodec_get_name(avf->streams[0]->codec->codec_id));
+               avcodec_get_name(avf->streams[0]->codecpar->codec_id));
         return AVERROR(EINVAL);
     }
     avpriv_set_pts_info(avf->streams[0], 64, 1, 1000);
diff --git a/libavformat/srtp.c b/libavformat/srtp.c
index b6e8211..f8b686c 100644
--- a/libavformat/srtp.c
+++ b/libavformat/srtp.c
@@ -323,150 +323,3 @@ int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len,
     len += hmac_size;
     return buf + len - out;
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-static const char *aes128_80_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
-
-static const uint8_t rtp_aes128_80[] = {
-    // RTP header
-    0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
-    // encrypted payload
-    0x62, 0x69, 0x76, 0xca, 0xc5,
-    // HMAC
-    0xa1, 0xac, 0x1b, 0xb4, 0xa0, 0x1c, 0xd5, 0x49, 0x28, 0x99,
-};
-
-static const uint8_t rtcp_aes128_80[] = {
-    // RTCP header
-    0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
-    // encrypted payload
-    0x8a, 0xac, 0xdc, 0xa5, 0x4c, 0xf6, 0x78, 0xa6, 0x62, 0x8f, 0x24, 0xda,
-    0x6c, 0x09, 0x3f, 0xa9, 0x28, 0x7a, 0xb5, 0x7f, 0x1f, 0x0f, 0xc9, 0x35,
-    // RTCP index
-    0x80, 0x00, 0x00, 0x03,
-    // HMAC
-    0xe9, 0x3b, 0xc0, 0x5c, 0x0c, 0x06, 0x9f, 0xab, 0xc0, 0xde,
-};
-
-static const char *aes128_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
-
-static const uint8_t rtp_aes128_32[] = {
-    // RTP header
-    0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
-    // encrypted payload
-    0x62, 0x69, 0x76, 0xca, 0xc5,
-    // HMAC
-    0xa1, 0xac, 0x1b, 0xb4,
-};
-
-static const uint8_t rtcp_aes128_32[] = {
-    // RTCP header
-    0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
-    // encrypted payload
-    0x35, 0xe9, 0xb5, 0xff, 0x0d, 0xd1, 0xde, 0x70, 0x74, 0x10, 0xaa, 0x1b,
-    0xb2, 0x8d, 0xf0, 0x20, 0x02, 0x99, 0x6b, 0x1b, 0x0b, 0xd0, 0x47, 0x34,
-    // RTCP index
-    0x80, 0x00, 0x00, 0x04,
-    // HMAC
-    0x5b, 0xd2, 0xa9, 0x9d,
-};
-
-static const char *aes128_80_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
-
-static const uint8_t rtp_aes128_80_32[] = {
-    // RTP header
-    0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
-    // encrypted payload
-    0x62, 0x69, 0x76, 0xca, 0xc5,
-    // HMAC
-    0xa1, 0xac, 0x1b, 0xb4,
-};
-
-static const uint8_t rtcp_aes128_80_32[] = {
-    // RTCP header
-    0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
-    // encrypted payload
-    0xd6, 0xae, 0xc1, 0x58, 0x63, 0x70, 0xc9, 0x88, 0x66, 0x26, 0x1c, 0x53,
-    0xff, 0x5d, 0x5d, 0x2b, 0x0f, 0x8c, 0x72, 0x3e, 0xc9, 0x1d, 0x43, 0xf9,
-    // RTCP index
-    0x80, 0x00, 0x00, 0x05,
-    // HMAC
-    0x09, 0x16, 0xb4, 0x27, 0x9a, 0xe9, 0x92, 0x26, 0x4e, 0x10,
-};
-
-static void print_data(const uint8_t *buf, int len)
-{
-    int i;
-    for (i = 0; i < len; i++)
-        printf("%02x", buf[i]);
-    printf("\n");
-}
-
-static int test_decrypt(struct SRTPContext *srtp, const uint8_t *in, int len,
-                        uint8_t *out)
-{
-    memcpy(out, in, len);
-    if (!ff_srtp_decrypt(srtp, out, &len)) {
-        print_data(out, len);
-        return len;
-    } else
-        return -1;
-}
-
-static void test_encrypt(const uint8_t *data, int in_len, const char *suite,
-                         const char *key)
-{
-    struct SRTPContext enc = { 0 }, dec = { 0 };
-    int len;
-    char buf[RTP_MAX_PACKET_LENGTH];
-    ff_srtp_set_crypto(&enc, suite, key);
-    ff_srtp_set_crypto(&dec, suite, key);
-    len = ff_srtp_encrypt(&enc, data, in_len, buf, sizeof(buf));
-    if (!ff_srtp_decrypt(&dec, buf, &len)) {
-        if (len == in_len && !memcmp(buf, data, len))
-            printf("Decrypted content matches input\n");
-        else
-            printf("Decrypted content doesn't match input\n");
-    } else {
-        printf("Decryption failed\n");
-    }
-    ff_srtp_free(&enc);
-    ff_srtp_free(&dec);
-}
-
-int main(void)
-{
-    static const char *aes128_80_suite = "AES_CM_128_HMAC_SHA1_80";
-    static const char *aes128_32_suite = "AES_CM_128_HMAC_SHA1_32";
-    static const char *aes128_80_32_suite = "SRTP_AES128_CM_HMAC_SHA1_32";
-    static const char *test_key = "abcdefghijklmnopqrstuvwxyz1234567890ABCD";
-    uint8_t buf[RTP_MAX_PACKET_LENGTH];
-    struct SRTPContext srtp = { 0 };
-    int len;
-    ff_srtp_set_crypto(&srtp, aes128_80_suite, aes128_80_key);
-    len = test_decrypt(&srtp, rtp_aes128_80, sizeof(rtp_aes128_80), buf);
-    test_encrypt(buf, len, aes128_80_suite, test_key);
-    test_encrypt(buf, len, aes128_32_suite, test_key);
-    test_encrypt(buf, len, aes128_80_32_suite, test_key);
-    test_decrypt(&srtp, rtcp_aes128_80, sizeof(rtcp_aes128_80), buf);
-    test_encrypt(buf, len, aes128_80_suite, test_key);
-    test_encrypt(buf, len, aes128_32_suite, test_key);
-    test_encrypt(buf, len, aes128_80_32_suite, test_key);
-    ff_srtp_free(&srtp);
-
-    memset(&srtp, 0, sizeof(srtp)); // Clear the context
-    ff_srtp_set_crypto(&srtp, aes128_32_suite, aes128_32_key);
-    test_decrypt(&srtp, rtp_aes128_32, sizeof(rtp_aes128_32), buf);
-    test_decrypt(&srtp, rtcp_aes128_32, sizeof(rtcp_aes128_32), buf);
-    ff_srtp_free(&srtp);
-
-    memset(&srtp, 0, sizeof(srtp)); // Clear the context
-    ff_srtp_set_crypto(&srtp, aes128_80_32_suite, aes128_80_32_key);
-    test_decrypt(&srtp, rtp_aes128_80_32, sizeof(rtp_aes128_80_32), buf);
-    test_decrypt(&srtp, rtcp_aes128_80_32, sizeof(rtcp_aes128_80_32), buf);
-    ff_srtp_free(&srtp);
-    return 0;
-}
-#endif /* TEST */
diff --git a/libavformat/srtpproto.c b/libavformat/srtpproto.c
index 460799a..5e6e516 100644
--- a/libavformat/srtpproto.c
+++ b/libavformat/srtpproto.c
@@ -81,7 +81,7 @@ static int srtp_open(URLContext *h, const char *uri, int flags)
                  path, sizeof(path), uri);
     ff_url_join(buf, sizeof(buf), "rtp", NULL, hostname, rtp_port, "%s", path);
     if ((ret = ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback,
-                                    NULL, h->protocol_whitelist)) < 0)
+                                    NULL, h->protocol_whitelist, h->protocol_blacklist, h)) < 0)
         goto fail;
 
     h->max_packet_size = FFMIN(s->rtp_hd->max_packet_size,
@@ -132,7 +132,7 @@ static int srtp_get_multi_file_handle(URLContext *h, int **handles,
     return ffurl_get_multi_file_handle(s->rtp_hd, handles, numhandles);
 }
 
-URLProtocol ff_srtp_protocol = {
+const URLProtocol ff_srtp_protocol = {
     .name                      = "srtp",
     .url_open                  = srtp_open,
     .url_read                  = srtp_read,
diff --git a/libavformat/stldec.c b/libavformat/stldec.c
index 8b1f0a6..35de493 100644
--- a/libavformat/stldec.c
+++ b/libavformat/stldec.c
@@ -77,8 +77,8 @@ static int stl_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 100);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_STL;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_STL;
 
     while (!avio_feof(s->pb)) {
         char line[4096];
diff --git a/libavformat/subfile.c b/libavformat/subfile.c
index 2b53438..fa971e1 100644
--- a/libavformat/subfile.c
+++ b/libavformat/subfile.c
@@ -78,7 +78,7 @@ static int subfile_open(URLContext *h, const char *filename, int flags,
     }
     av_strstart(filename, "subfile:", &filename);
     ret = ffurl_open_whitelist(&c->h, filename, flags, &h->interrupt_callback,
-                               options, h->protocol_whitelist);
+                               options, h->protocol_whitelist, h->protocol_blacklist, h);
     if (ret < 0)
         return ret;
     c->pos = c->start;
@@ -137,7 +137,7 @@ static int64_t subfile_seek(URLContext *h, int64_t pos, int whence)
     return c->pos - c->start;
 }
 
-URLProtocol ff_subfile_protocol = {
+const URLProtocol ff_subfile_protocol = {
     .name                = "subfile",
     .url_open2           = subfile_open,
     .url_read            = subfile_read,
diff --git a/libavformat/subviewer1dec.c b/libavformat/subviewer1dec.c
index 93db4eb..e579d1c 100644
--- a/libavformat/subviewer1dec.c
+++ b/libavformat/subviewer1dec.c
@@ -50,8 +50,8 @@ static int subviewer1_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 1);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_SUBVIEWER1;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_SUBVIEWER1;
 
     while (!avio_feof(s->pb)) {
         char line[4096];
diff --git a/libavformat/subviewerdec.c b/libavformat/subviewerdec.c
index d4b2fdf..af084f4 100644
--- a/libavformat/subviewerdec.c
+++ b/libavformat/subviewerdec.c
@@ -79,8 +79,8 @@ static int subviewer_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 100);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_SUBVIEWER;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_SUBVIEWER;
 
     av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED);
 
@@ -101,11 +101,11 @@ static int subviewer_read_header(AVFormatContext *s)
                 strstr(line, "[FONT]") || strstr(line, "[STYLE]"))
                 continue;
 
-            if (!st->codec->extradata) { // header not finalized yet
+            if (!st->codecpar->extradata) { // header not finalized yet
                 av_bprintf(&header, "%s\n", line);
                 if (!strncmp(line, "[END INFORMATION]", 17) || !strncmp(line, "[SUBTITLE]", 10)) {
                     /* end of header */
-                    res = avpriv_bprint_to_extradata(st->codec, &header);
+                    res = ff_bprint_to_codecpar_extradata(st->codecpar, &header);
                     if (res < 0)
                         goto end;
                 } else if (strncmp(line, "[INFORMATION]", 13)) {
diff --git a/libavformat/supdec.c b/libavformat/supdec.c
index 48083b2..0930dbc 100644
--- a/libavformat/supdec.c
+++ b/libavformat/supdec.c
@@ -27,8 +27,8 @@ static int sup_read_header(AVFormatContext *s)
     AVStream *st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id = AV_CODEC_ID_HDMV_PGS_SUBTITLE;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id = AV_CODEC_ID_HDMV_PGS_SUBTITLE;
     avpriv_set_pts_info(st, 32, 1, 90000);
 
     return 0;
diff --git a/libavformat/svag.c b/libavformat/svag.c
index 08fc06b..828b853 100644
--- a/libavformat/svag.c
+++ b/libavformat/svag.c
@@ -42,30 +42,30 @@ static int svag_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     size                   = avio_rl32(s->pb);
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = AV_CODEC_ID_ADPCM_PSX;
-    st->codec->sample_rate = avio_rl32(s->pb);
-    if (st->codec->sample_rate <= 0)
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_PSX;
+    st->codecpar->sample_rate = avio_rl32(s->pb);
+    if (st->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
-    st->codec->channels    = avio_rl32(s->pb);
-    if (st->codec->channels <= 0 || st->codec->channels > 8)
+    st->codecpar->channels    = avio_rl32(s->pb);
+    if (st->codecpar->channels <= 0 || st->codecpar->channels > 8)
         return AVERROR_INVALIDDATA;
-    st->duration           = size / (16 * st->codec->channels) * 28;
+    st->duration           = size / (16 * st->codecpar->channels) * 28;
     align                  = avio_rl32(s->pb);
-    if (align <= 0 || align > INT_MAX / st->codec->channels)
+    if (align <= 0 || align > INT_MAX / st->codecpar->channels)
         return AVERROR_INVALIDDATA;
-    st->codec->block_align = align * st->codec->channels;
+    st->codecpar->block_align = align * st->codecpar->channels;
     avio_skip(s->pb, 0x800 - avio_tell(s->pb));
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
 
 static int svag_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
-    return av_get_packet(s->pb, pkt, codec->block_align);
+    return av_get_packet(s->pb, pkt, par->block_align);
 }
 
 AVInputFormat ff_svag_demuxer = {
diff --git a/libavformat/swf.h b/libavformat/swf.h
index ab67c75..d0f0194 100644
--- a/libavformat/swf.h
+++ b/libavformat/swf.h
@@ -131,7 +131,7 @@ typedef struct SWFContext {
     int frame_rate;
     int tag;
     AVFifoBuffer *audio_fifo;
-    AVCodecContext *audio_enc, *video_enc;
+    AVCodecParameters *audio_par, *video_par;
     AVStream *video_st;
 #if CONFIG_ZLIB
 #define ZBUF_SIZE 4096
diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c
index eb17e82..fa2435e 100644
--- a/libavformat/swfdec.c
+++ b/libavformat/swfdec.c
@@ -181,21 +181,21 @@ static AVStream *create_new_audio_stream(AVFormatContext *s, int id, int info)
         return NULL;
     ast->id = id;
     if (info & 1) {
-        ast->codec->channels       = 2;
-        ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+        ast->codecpar->channels       = 2;
+        ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
     } else {
-        ast->codec->channels       = 1;
-        ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
+        ast->codecpar->channels       = 1;
+        ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
     }
-    ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    ast->codec->codec_id   = ff_codec_get_id(swf_audio_codec_tags, info>>4 & 15);
+    ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    ast->codecpar->codec_id   = ff_codec_get_id(swf_audio_codec_tags, info>>4 & 15);
     ast->need_parsing = AVSTREAM_PARSE_FULL;
     sample_rate_code = info>>2 & 3;
     sample_size_code = info>>1 & 1;
-    if (!sample_size_code && ast->codec->codec_id == AV_CODEC_ID_PCM_S16LE)
-        ast->codec->codec_id = AV_CODEC_ID_PCM_U8;
-    ast->codec->sample_rate = 44100 >> (3 - sample_rate_code);
-    avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
+    if (!sample_size_code && ast->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE)
+        ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
+    ast->codecpar->sample_rate = 44100 >> (3 - sample_rate_code);
+    avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
     return ast;
 }
 
@@ -226,7 +226,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
 
             for (i=0; i<s->nb_streams; i++) {
                 st = s->streams[i];
-                if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id)
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id)
                     goto skip;
             }
 
@@ -239,8 +239,8 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
             if (!vst)
                 return AVERROR(ENOMEM);
             vst->id = ch_id;
-            vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            vst->codec->codec_id = ff_codec_get_id(ff_swf_codec_tags, avio_r8(pb));
+            vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            vst->codecpar->codec_id = ff_codec_get_id(ff_swf_codec_tags, avio_r8(pb));
             avpriv_set_pts_info(vst, 16, 256, swf->frame_rate);
             len -= 8;
         } else if (tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) {
@@ -248,7 +248,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
 
             for (i=0; i<s->nb_streams; i++) {
                 st = s->streams[i];
-                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1)
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1)
                     goto skip;
             }
 
@@ -265,7 +265,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
 
             for (i=0; i<s->nb_streams; i++) {
                 st = s->streams[i];
-                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == ch_id)
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->id == ch_id)
                     goto skip;
             }
 
@@ -292,7 +292,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
             len -= 2;
             for(i=0; i<s->nb_streams; i++) {
                 st = s->streams[i];
-                if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) {
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->id == ch_id) {
                     frame = avio_rl16(pb);
                     len -= 2;
                     if (len <= 0)
@@ -368,7 +368,7 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
 
             for (i = 0; i < s->nb_streams; i++) {
                 st = s->streams[i];
-                if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && st->id == -3)
+                if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO && st->id == -3)
                     break;
             }
             if (i == s->nb_streams) {
@@ -378,17 +378,17 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
                     goto bitmap_end;
                 }
                 vst->id = -3; /* -3 to avoid clash with video stream and audio stream */
-                vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-                vst->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
+                vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+                vst->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
                 avpriv_set_pts_info(vst, 64, 256, swf->frame_rate);
                 st = vst;
             }
 
             if ((res = av_new_packet(pkt, out_len - colormapsize * colormapbpp)) < 0)
                 goto bitmap_end;
-            if (!st->codec->width && !st->codec->height) {
-                st->codec->width  = width;
-                st->codec->height = height;
+            if (!st->codecpar->width && !st->codecpar->height) {
+                st->codecpar->width  = width;
+                st->codecpar->height = height;
             } else {
                 ff_add_param_change(pkt, 0, 0, 0, width, height);
             }
@@ -417,10 +417,10 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
             default:
                 av_assert0(0);
             }
-            if (st->codec->pix_fmt != AV_PIX_FMT_NONE && st->codec->pix_fmt != pix_fmt) {
+            if (st->codecpar->format != AV_PIX_FMT_NONE && st->codecpar->format != pix_fmt) {
                 av_log(s, AV_LOG_ERROR, "pixel format change unsupported\n");
             } else
-                st->codec->pix_fmt = pix_fmt;
+                st->codecpar->format = pix_fmt;
 
             if (linesize * height > pkt->size) {
                 res = AVERROR_INVALIDDATA;
@@ -443,8 +443,8 @@ bitmap_end_skip:
         } else if (tag == TAG_STREAMBLOCK) {
             for (i = 0; i < s->nb_streams; i++) {
                 st = s->streams[i];
-                if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) {
-                    if (st->codec->codec_id == AV_CODEC_ID_MP3) {
+                if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->id == -1) {
+                    if (st->codecpar->codec_id == AV_CODEC_ID_MP3) {
                         avio_skip(pb, 4);
                         len -= 4;
                         if (len <= 0)
@@ -465,7 +465,7 @@ bitmap_end_skip:
         } else if (tag == TAG_JPEG2) {
             for (i=0; i<s->nb_streams; i++) {
                 st = s->streams[i];
-                if (st->codec->codec_id == AV_CODEC_ID_MJPEG && st->id == -2)
+                if (st->codecpar->codec_id == AV_CODEC_ID_MJPEG && st->id == -2)
                     break;
             }
             if (i == s->nb_streams) {
@@ -473,8 +473,8 @@ bitmap_end_skip:
                 if (!vst)
                     return AVERROR(ENOMEM);
                 vst->id = -2; /* -2 to avoid clash with video stream and audio stream */
-                vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-                vst->codec->codec_id = AV_CODEC_ID_MJPEG;
+                vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+                vst->codecpar->codec_id = AV_CODEC_ID_MJPEG;
                 avpriv_set_pts_info(vst, 64, 256, swf->frame_rate);
                 st = vst;
             }
diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c
index 8d5933e..3733a04 100644
--- a/libavformat/swfenc.c
+++ b/libavformat/swfenc.c
@@ -185,18 +185,14 @@ static int swf_write_header(AVFormatContext *s)
     swf->video_frame_number = 0;
 
     for(i=0;i<s->nb_streams;i++) {
-        AVCodecContext *enc = s->streams[i]->codec;
-        if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {
-            if (swf->audio_enc) {
+        AVCodecParameters *par = s->streams[i]->codecpar;
+        if (par->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (swf->audio_par) {
                 av_log(s, AV_LOG_ERROR, "SWF muxer only supports 1 audio stream\n");
                 return AVERROR_INVALIDDATA;
             }
-            if (enc->codec_id == AV_CODEC_ID_MP3) {
-                if (!enc->frame_size) {
-                    av_log(s, AV_LOG_ERROR, "audio frame size not set\n");
-                    return -1;
-                }
-                swf->audio_enc = enc;
+            if (par->codec_id == AV_CODEC_ID_MP3) {
+                swf->audio_par = par;
                 swf->audio_fifo= av_fifo_alloc(AUDIO_FIFO_SIZE);
                 if (!swf->audio_fifo)
                     return AVERROR(ENOMEM);
@@ -205,15 +201,15 @@ static int swf_write_header(AVFormatContext *s)
                 return -1;
             }
         } else {
-            if (swf->video_enc) {
+            if (swf->video_par) {
                 av_log(s, AV_LOG_ERROR, "SWF muxer only supports 1 video stream\n");
                 return AVERROR_INVALIDDATA;
             }
-            if (enc->codec_id == AV_CODEC_ID_VP6F ||
-                enc->codec_id == AV_CODEC_ID_FLV1 ||
-                enc->codec_id == AV_CODEC_ID_MJPEG) {
+            if (par->codec_id == AV_CODEC_ID_VP6F ||
+                par->codec_id == AV_CODEC_ID_FLV1 ||
+                par->codec_id == AV_CODEC_ID_MJPEG) {
                 swf->video_st  = s->streams[i];
-                swf->video_enc = enc;
+                swf->video_par = par;
             } else {
                 av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n");
                 return -1;
@@ -221,32 +217,32 @@ static int swf_write_header(AVFormatContext *s)
         }
     }
 
-    if (!swf->video_enc) {
+    if (!swf->video_par) {
         /* currently, cannot work correctly if audio only */
         width = 320;
         height = 200;
         rate = 10;
         rate_base= 1;
     } else {
-        width = swf->video_enc->width;
-        height = swf->video_enc->height;
+        width = swf->video_par->width;
+        height = swf->video_par->height;
         // TODO: should be avg_frame_rate
         rate = swf->video_st->time_base.den;
         rate_base = swf->video_st->time_base.num;
     }
 
-    if (!swf->audio_enc)
+    if (!swf->audio_par)
         swf->samples_per_frame = (44100LL * rate_base) / rate;
     else
-        swf->samples_per_frame = (swf->audio_enc->sample_rate * rate_base) / rate;
+        swf->samples_per_frame = (swf->audio_par->sample_rate * rate_base) / rate;
 
     avio_write(pb, "FWS", 3);
 
     if (!strcmp("avm2", s->oformat->name))
         version = 9;
-    else if (swf->video_enc && swf->video_enc->codec_id == AV_CODEC_ID_VP6F)
+    else if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_VP6F)
         version = 8; /* version 8 and above support VP6 codec */
-    else if (swf->video_enc && swf->video_enc->codec_id == AV_CODEC_ID_FLV1)
+    else if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_FLV1)
         version = 6; /* version 6 and above support FLV1 codec */
     else
         version = 4; /* version 4 for mpeg audio support */
@@ -272,7 +268,7 @@ static int swf_write_header(AVFormatContext *s)
     }
 
     /* define a shape with the jpeg inside */
-    if (swf->video_enc && swf->video_enc->codec_id == AV_CODEC_ID_MJPEG) {
+    if (swf->video_par && swf->video_par->codec_id == AV_CODEC_ID_MJPEG) {
         put_swf_tag(s, TAG_DEFINESHAPE);
 
         avio_wl16(pb, SHAPE_ID); /* ID of shape */
@@ -315,12 +311,12 @@ static int swf_write_header(AVFormatContext *s)
         put_swf_end_tag(s);
     }
 
-    if (swf->audio_enc && swf->audio_enc->codec_id == AV_CODEC_ID_MP3) {
+    if (swf->audio_par && swf->audio_par->codec_id == AV_CODEC_ID_MP3) {
         int v = 0;
 
         /* start sound */
         put_swf_tag(s, TAG_STREAMHEAD2);
-        switch(swf->audio_enc->sample_rate) {
+        switch(swf->audio_par->sample_rate) {
         case 11025: v |= 1 << 2; break;
         case 22050: v |= 2 << 2; break;
         case 44100: v |= 3 << 2; break;
@@ -330,7 +326,7 @@ static int swf_write_header(AVFormatContext *s)
             return -1;
         }
         v |= 0x02; /* 16 bit playback */
-        if (swf->audio_enc->channels == 2)
+        if (swf->audio_par->channels == 2)
             v |= 0x01; /* stereo playback */
         avio_w8(s->pb, v);
         v |= 0x20; /* mp3 compressed */
@@ -346,27 +342,27 @@ static int swf_write_header(AVFormatContext *s)
 }
 
 static int swf_write_video(AVFormatContext *s,
-                           AVCodecContext *enc, const uint8_t *buf, int size)
+                           AVCodecParameters *par, const uint8_t *buf, int size)
 {
     SWFContext *swf = s->priv_data;
     AVIOContext *pb = s->pb;
 
     /* Flash Player limit */
     if (swf->swf_frame_number == 16000)
-        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
+        av_log(s, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
 
-    if (enc->codec_id == AV_CODEC_ID_VP6F ||
-        enc->codec_id == AV_CODEC_ID_FLV1) {
+    if (par->codec_id == AV_CODEC_ID_VP6F ||
+        par->codec_id == AV_CODEC_ID_FLV1) {
         if (swf->video_frame_number == 0) {
             /* create a new video object */
             put_swf_tag(s, TAG_VIDEOSTREAM);
             avio_wl16(pb, VIDEO_ID);
             swf->vframes_pos = avio_tell(pb);
             avio_wl16(pb, 15000); /* hard flash player limit */
-            avio_wl16(pb, enc->width);
-            avio_wl16(pb, enc->height);
+            avio_wl16(pb, par->width);
+            avio_wl16(pb, par->height);
             avio_w8(pb, 0);
-            avio_w8(pb,ff_codec_get_tag(ff_swf_codec_tags, enc->codec_id));
+            avio_w8(pb,ff_codec_get_tag(ff_swf_codec_tags, par->codec_id));
             put_swf_end_tag(s);
 
             /* place the video object for the first time */
@@ -394,7 +390,7 @@ static int swf_write_video(AVFormatContext *s,
         avio_wl16(pb, swf->video_frame_number++);
         avio_write(pb, buf, size);
         put_swf_end_tag(s);
-    } else if (enc->codec_id == AV_CODEC_ID_MJPEG) {
+    } else if (par->codec_id == AV_CODEC_ID_MJPEG) {
         if (swf->swf_frame_number > 0) {
             /* remove the shape */
             put_swf_tag(s, TAG_REMOVEOBJECT);
@@ -431,7 +427,7 @@ static int swf_write_video(AVFormatContext *s,
     swf->swf_frame_number++;
 
     /* streaming sound always should be placed just before showframe tags */
-    if (swf->audio_enc && av_fifo_size(swf->audio_fifo)) {
+    if (swf->audio_par && av_fifo_size(swf->audio_fifo)) {
         int frame_size = av_fifo_size(swf->audio_fifo);
         put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
         avio_wl16(pb, swf->sound_samples);
@@ -451,13 +447,13 @@ static int swf_write_video(AVFormatContext *s,
 }
 
 static int swf_write_audio(AVFormatContext *s,
-                           AVCodecContext *enc, uint8_t *buf, int size)
+                           AVCodecParameters *par, uint8_t *buf, int size)
 {
     SWFContext *swf = s->priv_data;
 
     /* Flash Player limit */
     if (swf->swf_frame_number == 16000)
-        av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
+        av_log(s, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
 
     if (av_fifo_size(swf->audio_fifo) + size > AUDIO_FIFO_SIZE) {
         av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
@@ -465,36 +461,36 @@ static int swf_write_audio(AVFormatContext *s,
     }
 
     av_fifo_generic_write(swf->audio_fifo, buf, size, NULL);
-    swf->sound_samples += enc->frame_size;
+    swf->sound_samples += av_get_audio_frame_duration2(par, size);
 
     /* if audio only stream make sure we add swf frames */
-    if (!swf->video_enc)
-        swf_write_video(s, enc, 0, 0);
+    if (!swf->video_par)
+        swf_write_video(s, par, 0, 0);
 
     return 0;
 }
 
 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
-    if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
-        return swf_write_audio(s, codec, pkt->data, pkt->size);
+    AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
+    if (par->codec_type == AVMEDIA_TYPE_AUDIO)
+        return swf_write_audio(s, par, pkt->data, pkt->size);
     else
-        return swf_write_video(s, codec, pkt->data, pkt->size);
+        return swf_write_video(s, par, pkt->data, pkt->size);
 }
 
 static int swf_write_trailer(AVFormatContext *s)
 {
     SWFContext *swf = s->priv_data;
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc, *video_enc;
+    AVCodecParameters *par, *video_par;
     int file_size, i;
 
-    video_enc = NULL;
+    video_par = NULL;
     for(i=0;i<s->nb_streams;i++) {
-        enc = s->streams[i]->codec;
-        if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
-            video_enc = enc;
+        par = s->streams[i]->codecpar;
+        if (par->codec_type == AVMEDIA_TYPE_VIDEO)
+            video_par = par;
         else {
             av_fifo_freep(&swf->audio_fifo);
         }
@@ -504,7 +500,7 @@ static int swf_write_trailer(AVFormatContext *s)
     put_swf_end_tag(s);
 
     /* patch file size and number of frames if not streamed */
-    if (s->pb->seekable && video_enc) {
+    if (s->pb->seekable && video_par) {
         file_size = avio_tell(pb);
         avio_seek(pb, 4, SEEK_SET);
         avio_wl32(pb, file_size);
diff --git a/libavformat/takdec.c b/libavformat/takdec.c
index 970ab4a..4b4124f 100644
--- a/libavformat/takdec.c
+++ b/libavformat/takdec.c
@@ -58,9 +58,9 @@ static int tak_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id   = AV_CODEC_ID_TAK;
-    st->need_parsing      = AVSTREAM_PARSE_FULL_RAW;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id   = AV_CODEC_ID_TAK;
+    st->need_parsing         = AVSTREAM_PARSE_FULL_RAW;
 
     tc->mlast_frame = 0;
     if (avio_rl32(pb) != MKTAG('t', 'B', 'a', 'K')) {
@@ -145,15 +145,15 @@ static int tak_read_header(AVFormatContext *s)
             avpriv_tak_parse_streaminfo(&gb, &ti);
             if (ti.samples > 0)
                 st->duration = ti.samples;
-            st->codec->bits_per_coded_sample = ti.bps;
+            st->codecpar->bits_per_coded_sample = ti.bps;
             if (ti.ch_layout)
-                st->codec->channel_layout = ti.ch_layout;
-            st->codec->sample_rate           = ti.sample_rate;
-            st->codec->channels              = ti.channels;
+                st->codecpar->channel_layout = ti.ch_layout;
+            st->codecpar->sample_rate           = ti.sample_rate;
+            st->codecpar->channels              = ti.channels;
             st->start_time                   = 0;
-            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
-            st->codec->extradata             = buffer;
-            st->codec->extradata_size        = size - 3;
+            avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
+            st->codecpar->extradata             = buffer;
+            st->codecpar->extradata_size        = size - 3;
             buffer                           = NULL;
         } else if (type == TAK_METADATA_LAST_FRAME) {
             if (size != 11)
diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index 5738690..c105479 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -255,7 +255,7 @@ static int tcp_get_file_handle(URLContext *h)
     return s->fd;
 }
 
-URLProtocol ff_tcp_protocol = {
+const URLProtocol ff_tcp_protocol = {
     .name                = "tcp",
     .url_open            = tcp_open,
     .url_accept          = tcp_accept,
diff --git a/libavformat/tedcaptionsdec.c b/libavformat/tedcaptionsdec.c
index b6dc517..774d499 100644
--- a/libavformat/tedcaptionsdec.c
+++ b/libavformat/tedcaptionsdec.c
@@ -295,8 +295,8 @@ static av_cold int tedcaptions_read_header(AVFormatContext *avf)
     st = avformat_new_stream(avf, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type     = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id       = AV_CODEC_ID_TEXT;
+    st->codecpar->codec_type     = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id       = AV_CODEC_ID_TEXT;
     avpriv_set_pts_info(st, 64, 1, 1000);
     st->probe_packets = 0;
     st->start_time    = 0;
diff --git a/libavformat/tee.c b/libavformat/tee.c
index 1390705..9d0a4cb 100644
--- a/libavformat/tee.c
+++ b/libavformat/tee.c
@@ -27,21 +27,30 @@
 #include "avformat.h"
 #include "avio_internal.h"
 
-#define MAX_SLAVES 16
+typedef enum {
+    ON_SLAVE_FAILURE_ABORT  = 1,
+    ON_SLAVE_FAILURE_IGNORE = 2
+} SlaveFailurePolicy;
+
+#define DEFAULT_SLAVE_FAILURE_POLICY ON_SLAVE_FAILURE_ABORT
 
 typedef struct {
     AVFormatContext *avf;
     AVBitStreamFilterContext **bsfs; ///< bitstream filters per stream
 
+    SlaveFailurePolicy on_fail;
+
     /** map from input to output streams indexes,
      * disabled output streams are set to -1 */
     int *stream_map;
+    int header_written;
 } TeeSlave;
 
 typedef struct TeeContext {
     const AVClass *class;
     unsigned nb_slaves;
-    TeeSlave slaves[MAX_SLAVES];
+    unsigned nb_alive;
+    TeeSlave *slaves;
 } TeeContext;
 
 static const char *const slave_delim     = "|";
@@ -135,13 +144,73 @@ end:
     return ret;
 }
 
+static inline int parse_slave_failure_policy_option(const char *opt, TeeSlave *tee_slave)
+{
+    if (!opt) {
+        tee_slave->on_fail = DEFAULT_SLAVE_FAILURE_POLICY;
+        return 0;
+    } else if (!av_strcasecmp("abort", opt)) {
+        tee_slave->on_fail = ON_SLAVE_FAILURE_ABORT;
+        return 0;
+    } else if (!av_strcasecmp("ignore", opt)) {
+        tee_slave->on_fail = ON_SLAVE_FAILURE_IGNORE;
+        return 0;
+    }
+    /* Set failure behaviour to abort, so invalid option error will not be ignored */
+    tee_slave->on_fail = ON_SLAVE_FAILURE_ABORT;
+    return AVERROR(EINVAL);
+}
+
+static int close_slave(TeeSlave *tee_slave)
+{
+    AVFormatContext *avf;
+    unsigned i;
+    int ret = 0;
+
+    avf = tee_slave->avf;
+    if (!avf)
+        return 0;
+
+    if (tee_slave->header_written)
+        ret = av_write_trailer(avf);
+
+    if (tee_slave->bsfs) {
+        for (i = 0; i < avf->nb_streams; ++i) {
+            AVBitStreamFilterContext *bsf_next, *bsf = tee_slave->bsfs[i];
+            while (bsf) {
+                bsf_next = bsf->next;
+                av_bitstream_filter_close(bsf);
+                bsf = bsf_next;
+            }
+        }
+    }
+    av_freep(&tee_slave->stream_map);
+    av_freep(&tee_slave->bsfs);
+
+    ff_format_io_close(avf, &avf->pb);
+    avformat_free_context(avf);
+    tee_slave->avf = NULL;
+    return ret;
+}
+
+static void close_slaves(AVFormatContext *avf)
+{
+    TeeContext *tee = avf->priv_data;
+    unsigned i;
+
+    for (i = 0; i < tee->nb_slaves; i++) {
+        close_slave(&tee->slaves[i]);
+    }
+    av_freep(&tee->slaves);
+}
+
 static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
 {
     int i, ret;
     AVDictionary *options = NULL;
     AVDictionaryEntry *entry;
     char *filename;
-    char *format = NULL, *select = NULL;
+    char *format = NULL, *select = NULL, *on_fail = NULL;
     AVFormatContext *avf2 = NULL;
     AVStream *st, *st2;
     int stream_count;
@@ -161,10 +230,19 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
 
     STEAL_OPTION("f", format);
     STEAL_OPTION("select", select);
+    STEAL_OPTION("onfail", on_fail);
+
+    ret = parse_slave_failure_policy_option(on_fail, tee_slave);
+    if (ret < 0) {
+        av_log(avf, AV_LOG_ERROR,
+               "Invalid onfail option value, valid options are 'abort' and 'ignore'\n");
+        goto end;
+    }
 
     ret = avformat_alloc_output_context2(&avf2, NULL, format, filename);
     if (ret < 0)
         goto end;
+    tee_slave->avf = avf2;
     av_dict_copy(&avf2->metadata, avf->metadata, 0);
     avf2->opaque   = avf->opaque;
     avf2->io_open  = avf->io_open;
@@ -226,7 +304,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
         st2->sample_aspect_ratio = st->sample_aspect_ratio;
         st2->avg_frame_rate      = st->avg_frame_rate;
         av_dict_copy(&st2->metadata, st->metadata, 0);
-        if ((ret = avcodec_copy_context(st2->codec, st->codec)) < 0)
+        if ((ret = avcodec_parameters_copy(st2->codecpar, st->codecpar)) < 0)
             goto end;
     }
 
@@ -243,9 +321,9 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
                slave, av_err2str(ret));
         goto end;
     }
+    tee_slave->header_written = 1;
 
-    tee_slave->avf = avf2;
-    tee_slave->bsfs = av_calloc(avf2->nb_streams, sizeof(TeeSlave));
+    tee_slave->bsfs = av_calloc(avf2->nb_streams, sizeof(*tee_slave->bsfs));
     if (!tee_slave->bsfs) {
         ret = AVERROR(ENOMEM);
         goto end;
@@ -259,7 +337,8 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
                 av_log(avf, AV_LOG_ERROR,
                        "Specifier separator in '%s' is '%c', but only characters '%s' "
                        "are allowed\n", entry->key, *spec, slave_bsfs_spec_sep);
-                return AVERROR(EINVAL);
+                ret = AVERROR(EINVAL);
+                goto end;
             }
             spec++; /* consume separator */
         }
@@ -306,37 +385,12 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
 end:
     av_free(format);
     av_free(select);
+    av_free(on_fail);
     av_dict_free(&options);
     av_freep(&tmp_select);
     return ret;
 }
 
-static void close_slaves(AVFormatContext *avf)
-{
-    TeeContext *tee = avf->priv_data;
-    AVFormatContext *avf2;
-    unsigned i, j;
-
-    for (i = 0; i < tee->nb_slaves; i++) {
-        avf2 = tee->slaves[i].avf;
-
-        for (j = 0; j < avf2->nb_streams; j++) {
-            AVBitStreamFilterContext *bsf_next, *bsf = tee->slaves[i].bsfs[j];
-            while (bsf) {
-                bsf_next = bsf->next;
-                av_bitstream_filter_close(bsf);
-                bsf = bsf_next;
-            }
-        }
-        av_freep(&tee->slaves[i].stream_map);
-        av_freep(&tee->slaves[i].bsfs);
-
-        ff_format_io_close(avf2, &avf2->pb);
-        avformat_free_context(avf2);
-        tee->slaves[i].avf = NULL;
-    }
-}
-
 static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
 {
     int i;
@@ -347,8 +401,8 @@ static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
         AVBitStreamFilterContext *bsf = slave->bsfs[i];
 
         av_log(log_ctx, log_level, "    stream:%d codec:%s type:%s",
-               i, avcodec_get_name(st->codec->codec_id),
-               av_get_media_type_string(st->codec->codec_type));
+               i, avcodec_get_name(st->codecpar->codec_id),
+               av_get_media_type_string(st->codecpar->codec_type));
         if (bsf) {
             av_log(log_ctx, log_level, " bsfs:");
             while (bsf) {
@@ -361,71 +415,102 @@ static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
     }
 }
 
+static int tee_process_slave_failure(AVFormatContext *avf, unsigned slave_idx, int err_n)
+{
+    TeeContext *tee = avf->priv_data;
+    TeeSlave *tee_slave = &tee->slaves[slave_idx];
+
+    tee->nb_alive--;
+
+    close_slave(tee_slave);
+
+    if (!tee->nb_alive) {
+        av_log(avf, AV_LOG_ERROR, "All tee outputs failed.\n");
+        return err_n;
+    } else if (tee_slave->on_fail == ON_SLAVE_FAILURE_ABORT) {
+        av_log(avf, AV_LOG_ERROR, "Slave muxer #%u failed, aborting.\n", slave_idx);
+        return err_n;
+    } else {
+        av_log(avf, AV_LOG_ERROR, "Slave muxer #%u failed: %s, continuing with %u/%u slaves.\n",
+               slave_idx, av_err2str(err_n), tee->nb_alive, tee->nb_slaves);
+        return 0;
+    }
+}
+
 static int tee_write_header(AVFormatContext *avf)
 {
     TeeContext *tee = avf->priv_data;
     unsigned nb_slaves = 0, i;
     const char *filename = avf->filename;
-    char *slaves[MAX_SLAVES];
+    char **slaves = NULL;
     int ret;
 
     while (*filename) {
-        if (nb_slaves == MAX_SLAVES) {
-            av_log(avf, AV_LOG_ERROR, "Maximum %d slave muxers reached.\n",
-                   MAX_SLAVES);
-            ret = AVERROR_PATCHWELCOME;
+        char *slave = av_get_token(&filename, slave_delim);
+        if (!slave) {
+            ret = AVERROR(ENOMEM);
             goto fail;
         }
-        if (!(slaves[nb_slaves++] = av_get_token(&filename, slave_delim))) {
-            ret = AVERROR(ENOMEM);
+        ret = av_dynarray_add_nofree(&slaves, &nb_slaves, slave);
+        if (ret < 0) {
+            av_free(slave);
             goto fail;
         }
         if (strspn(filename, slave_delim))
             filename++;
     }
 
+    if (!(tee->slaves = av_mallocz_array(nb_slaves, sizeof(*tee->slaves)))) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+    tee->nb_slaves = tee->nb_alive = nb_slaves;
+
     for (i = 0; i < nb_slaves; i++) {
-        if ((ret = open_slave(avf, slaves[i], &tee->slaves[i])) < 0)
-            goto fail;
-        log_slave(&tee->slaves[i], avf, AV_LOG_VERBOSE);
+        if ((ret = open_slave(avf, slaves[i], &tee->slaves[i])) < 0) {
+            ret = tee_process_slave_failure(avf, i, ret);
+            if (ret < 0)
+                goto fail;
+        } else {
+            log_slave(&tee->slaves[i], avf, AV_LOG_VERBOSE);
+        }
         av_freep(&slaves[i]);
     }
 
-    tee->nb_slaves = nb_slaves;
-
     for (i = 0; i < avf->nb_streams; i++) {
         int j, mapped = 0;
         for (j = 0; j < tee->nb_slaves; j++)
-            mapped += tee->slaves[j].stream_map[i] >= 0;
+            if (tee->slaves[j].avf)
+                mapped += tee->slaves[j].stream_map[i] >= 0;
         if (!mapped)
             av_log(avf, AV_LOG_WARNING, "Input stream #%d is not mapped "
                    "to any slave.\n", i);
     }
+    av_free(slaves);
     return 0;
 
 fail:
     for (i = 0; i < nb_slaves; i++)
         av_freep(&slaves[i]);
     close_slaves(avf);
+    av_free(slaves);
     return ret;
 }
 
 static int tee_write_trailer(AVFormatContext *avf)
 {
     TeeContext *tee = avf->priv_data;
-    AVFormatContext *avf2;
     int ret_all = 0, ret;
     unsigned i;
 
     for (i = 0; i < tee->nb_slaves; i++) {
-        avf2 = tee->slaves[i].avf;
-        if ((ret = av_write_trailer(avf2)) < 0)
-            if (!ret_all)
+        if ((ret = close_slave(&tee->slaves[i])) < 0) {
+            ret = tee_process_slave_failure(avf, i, ret);
+            if (!ret_all && ret < 0)
                 ret_all = ret;
-        if (!(avf2->oformat->flags & AVFMT_NOFILE))
-            ff_format_io_close(avf2, &avf2->pb);
+        }
     }
-    close_slaves(avf);
+    av_freep(&tee->slaves);
     return ret_all;
 }
 
@@ -440,14 +525,16 @@ static int tee_write_packet(AVFormatContext *avf, AVPacket *pkt)
     AVRational tb, tb2;
 
     for (i = 0; i < tee->nb_slaves; i++) {
-        avf2 = tee->slaves[i].avf;
+        if (!(avf2 = tee->slaves[i].avf))
+            continue;
+
         s = pkt->stream_index;
         s2 = tee->slaves[i].stream_map[s];
         if (s2 < 0)
             continue;
 
-        if ((ret = av_copy_packet(&pkt2, pkt)) < 0 ||
-            (ret = av_dup_packet(&pkt2))< 0)
+        memset(&pkt2, 0, sizeof(AVPacket));
+        if ((ret = av_packet_ref(&pkt2, pkt)) < 0)
             if (!ret_all) {
                 ret_all = ret;
                 continue;
@@ -461,9 +548,11 @@ static int tee_write_packet(AVFormatContext *avf, AVPacket *pkt)
 
         if ((ret = av_apply_bitstream_filters(avf2->streams[s2]->codec, &pkt2,
                                               tee->slaves[i].bsfs[s2])) < 0 ||
-            (ret = av_interleaved_write_frame(avf2, &pkt2)) < 0)
-            if (!ret_all)
+            (ret = av_interleaved_write_frame(avf2, &pkt2)) < 0) {
+            ret = tee_process_slave_failure(avf, i, ret);
+            if (!ret_all && ret < 0)
                 ret_all = ret;
+        }
     }
     return ret_all;
 }
diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c
new file mode 100644
index 0000000..41cd4fc
--- /dev/null
+++ b/libavformat/tests/movenc.c
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 2015 Martin Storsjo
+ *
+ * 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 "config.h"
+
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/md5.h"
+
+#include "libavformat/avformat.h"
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+#define HASH_SIZE 16
+
+static const uint8_t h264_extradata[] = {
+    0x01, 0x4d, 0x40, 0x1e, 0xff, 0xe1, 0x00, 0x02, 0x67, 0x4d, 0x01, 0x00, 0x02, 0x68, 0xef
+};
+static const uint8_t aac_extradata[] = {
+    0x12, 0x10
+};
+
+
+static const char *format = "mp4";
+AVFormatContext *ctx;
+uint8_t iobuf[32768];
+AVDictionary *opts;
+
+int write_file;
+const char *cur_name;
+FILE* out;
+int out_size;
+struct AVMD5* md5;
+uint8_t hash[HASH_SIZE];
+
+AVStream *video_st, *audio_st;
+int64_t audio_dts, video_dts;
+
+int bframes;
+int64_t duration;
+int64_t audio_duration;
+int frames;
+int gop_size;
+int64_t next_p_pts;
+enum AVPictureType last_picture;
+int skip_write;
+int skip_write_audio;
+int clear_duration;
+int force_iobuf_size;
+int do_interleave;
+int fake_pkt_duration;
+
+int num_warnings;
+
+int check_faults;
+
+
+static void count_warnings(void *avcl, int level, const char *fmt, va_list vl)
+{
+    if (level == AV_LOG_WARNING)
+        num_warnings++;
+}
+
+static void init_count_warnings(void)
+{
+    av_log_set_callback(count_warnings);
+    num_warnings = 0;
+}
+
+static void reset_count_warnings(void)
+{
+    av_log_set_callback(av_log_default_callback);
+}
+
+static int io_write(void *opaque, uint8_t *buf, int size)
+{
+    out_size += size;
+    av_md5_update(md5, buf, size);
+    if (out)
+        fwrite(buf, 1, size, out);
+    return size;
+}
+
+static int io_write_data_type(void *opaque, uint8_t *buf, int size,
+                              enum AVIODataMarkerType type, int64_t time)
+{
+    char timebuf[30], content[5] = { 0 };
+    const char *str;
+    switch (type) {
+    case AVIO_DATA_MARKER_HEADER:         str = "header";   break;
+    case AVIO_DATA_MARKER_SYNC_POINT:     str = "sync";     break;
+    case AVIO_DATA_MARKER_BOUNDARY_POINT: str = "boundary"; break;
+    case AVIO_DATA_MARKER_UNKNOWN:        str = "unknown";  break;
+    case AVIO_DATA_MARKER_TRAILER:        str = "trailer";  break;
+    }
+    if (time == AV_NOPTS_VALUE)
+        snprintf(timebuf, sizeof(timebuf), "nopts");
+    else
+        snprintf(timebuf, sizeof(timebuf), "%"PRId64, time);
+    // There can be multiple header/trailer callbacks, only log the box type
+    // for header at out_size == 0
+    if (type != AVIO_DATA_MARKER_UNKNOWN &&
+        type != AVIO_DATA_MARKER_TRAILER &&
+        (type != AVIO_DATA_MARKER_HEADER || out_size == 0) &&
+        size >= 8)
+        memcpy(content, &buf[4], 4);
+    else
+        snprintf(content, sizeof(content), "-");
+    printf("write_data len %d, time %s, type %s atom %s\n", size, timebuf, str, content);
+    return io_write(opaque, buf, size);
+}
+
+static void init_out(const char *name)
+{
+    char buf[100];
+    cur_name = name;
+    snprintf(buf, sizeof(buf), "%s.%s", cur_name, format);
+
+    av_md5_init(md5);
+    if (write_file) {
+        out = fopen(buf, "wb");
+        if (!out)
+            perror(buf);
+    }
+    out_size = 0;
+}
+
+static void close_out(void)
+{
+    int i;
+    av_md5_final(md5, hash);
+    for (i = 0; i < HASH_SIZE; i++)
+        printf("%02x", hash[i]);
+    printf(" %d %s\n", out_size, cur_name);
+    if (out)
+        fclose(out);
+    out = NULL;
+}
+
+static void check_func(int value, int line, const char *msg, ...)
+{
+    if (!value) {
+        va_list ap;
+        va_start(ap, msg);
+        printf("%d: ", line);
+        vprintf(msg, ap);
+        printf("\n");
+        check_faults++;
+        va_end(ap);
+    }
+}
+#define check(value, ...) check_func(value, __LINE__, __VA_ARGS__)
+
+static void init_fps(int bf, int audio_preroll, int fps)
+{
+    AVStream *st;
+    int iobuf_size = force_iobuf_size ? force_iobuf_size : sizeof(iobuf);
+    ctx = avformat_alloc_context();
+    if (!ctx)
+        exit(1);
+    ctx->oformat = av_guess_format(format, NULL, NULL);
+    if (!ctx->oformat)
+        exit(1);
+    ctx->pb = avio_alloc_context(iobuf, iobuf_size, AVIO_FLAG_WRITE, NULL, NULL, io_write, NULL);
+    if (!ctx->pb)
+        exit(1);
+    ctx->pb->write_data_type = io_write_data_type;
+    ctx->flags |= AVFMT_FLAG_BITEXACT;
+
+    st = avformat_new_stream(ctx, NULL);
+    if (!st)
+        exit(1);
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_H264;
+    st->codecpar->width = 640;
+    st->codecpar->height = 480;
+    st->time_base.num = 1;
+    st->time_base.den = 30;
+    st->codecpar->extradata_size = sizeof(h264_extradata);
+    st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!st->codecpar->extradata)
+        exit(1);
+    memcpy(st->codecpar->extradata, h264_extradata, sizeof(h264_extradata));
+    video_st = st;
+
+    st = avformat_new_stream(ctx, NULL);
+    if (!st)
+        exit(1);
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_AAC;
+    st->codecpar->sample_rate = 44100;
+    st->codecpar->channels = 2;
+    st->time_base.num = 1;
+    st->time_base.den = 44100;
+    st->codecpar->extradata_size = sizeof(aac_extradata);
+    st->codecpar->extradata = av_mallocz(st->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (!st->codecpar->extradata)
+        exit(1);
+    memcpy(st->codecpar->extradata, aac_extradata, sizeof(aac_extradata));
+    audio_st = st;
+
+    if (avformat_write_header(ctx, &opts) < 0)
+        exit(1);
+    av_dict_free(&opts);
+
+    frames = 0;
+    gop_size = 30;
+    duration = video_st->time_base.den / fps;
+    audio_duration = 1024LL * audio_st->time_base.den / audio_st->codecpar->sample_rate;
+    if (audio_preroll)
+        audio_preroll = 2048LL * audio_st->time_base.den / audio_st->codecpar->sample_rate;
+
+    bframes = bf;
+    video_dts = bframes ? -duration : 0;
+    audio_dts = -audio_preroll;
+}
+
+static void init(int bf, int audio_preroll)
+{
+    init_fps(bf, audio_preroll, 30);
+}
+
+static void mux_frames(int n)
+{
+    int end_frames = frames + n;
+    while (1) {
+        AVPacket pkt;
+        uint8_t pktdata[8] = { 0 };
+        av_init_packet(&pkt);
+
+        if (av_compare_ts(audio_dts, audio_st->time_base, video_dts, video_st->time_base) < 0) {
+            pkt.dts = pkt.pts = audio_dts;
+            pkt.stream_index = 1;
+            pkt.duration = audio_duration;
+            audio_dts += audio_duration;
+        } else {
+            if (frames == end_frames)
+                break;
+            pkt.dts = video_dts;
+            pkt.stream_index = 0;
+            pkt.duration = duration;
+            if ((frames % gop_size) == 0) {
+                pkt.flags |= AV_PKT_FLAG_KEY;
+                last_picture = AV_PICTURE_TYPE_I;
+                pkt.pts = pkt.dts + duration;
+                video_dts = pkt.pts;
+            } else {
+                if (last_picture == AV_PICTURE_TYPE_P) {
+                    last_picture = AV_PICTURE_TYPE_B;
+                    pkt.pts = pkt.dts;
+                    video_dts = next_p_pts;
+                } else {
+                    last_picture = AV_PICTURE_TYPE_P;
+                    if (((frames + 1) % gop_size) == 0) {
+                        pkt.pts = pkt.dts + duration;
+                        video_dts = pkt.pts;
+                    } else {
+                        next_p_pts = pkt.pts = pkt.dts + 2 * duration;
+                        video_dts += duration;
+                    }
+                }
+            }
+            if (!bframes)
+                pkt.pts = pkt.dts;
+            if (fake_pkt_duration)
+                pkt.duration = fake_pkt_duration;
+            frames++;
+        }
+
+        if (clear_duration)
+            pkt.duration = 0;
+        AV_WB32(pktdata + 4, pkt.pts);
+        pkt.data = pktdata;
+        pkt.size = 8;
+        if (skip_write)
+            continue;
+        if (skip_write_audio && pkt.stream_index == 1)
+            continue;
+        if (do_interleave)
+            av_interleaved_write_frame(ctx, &pkt);
+        else
+            av_write_frame(ctx, &pkt);
+    }
+}
+
+static void mux_gops(int n)
+{
+    mux_frames(gop_size * n);
+}
+
+static void skip_gops(int n)
+{
+    skip_write = 1;
+    mux_gops(n);
+    skip_write = 0;
+}
+
+static void signal_init_ts(void)
+{
+    AVPacket pkt;
+    av_init_packet(&pkt);
+    pkt.size = 0;
+    pkt.data = NULL;
+
+    pkt.stream_index = 0;
+    pkt.dts = video_dts;
+    pkt.pts = 0;
+    av_write_frame(ctx, &pkt);
+
+    pkt.stream_index = 1;
+    pkt.dts = pkt.pts = audio_dts;
+    av_write_frame(ctx, &pkt);
+}
+
+static void finish(void)
+{
+    av_write_trailer(ctx);
+    av_free(ctx->pb);
+    avformat_free_context(ctx);
+    ctx = NULL;
+}
+
+static void help(void)
+{
+    printf("movenc-test [-w]\n"
+           "-w          write output into files\n");
+}
+
+int main(int argc, char **argv)
+{
+    int c;
+    uint8_t header[HASH_SIZE];
+    uint8_t content[HASH_SIZE];
+    int empty_moov_pos;
+    int prev_pos;
+
+    for (;;) {
+        c = getopt(argc, argv, "wh");
+        if (c == -1)
+            break;
+        switch (c) {
+        case 'w':
+            write_file = 1;
+            break;
+        default:
+        case 'h':
+            help();
+            return 0;
+        }
+    }
+
+    av_register_all();
+
+    md5 = av_md5_alloc();
+    if (!md5)
+        return 1;
+
+    // Write a fragmented file with an initial moov that actually contains some
+    // samples. One moov+mdat with 1 second of data and one moof+mdat with 1
+    // second of data.
+    init_out("non-empty-moov");
+    av_dict_set(&opts, "movflags", "frag_keyframe", 0);
+    init(0, 0);
+    mux_gops(2);
+    finish();
+    close_out();
+
+    // Write a similar file, but with B-frames and audio preroll, handled
+    // via an edit list.
+    init_out("non-empty-moov-elst");
+    av_dict_set(&opts, "movflags", "frag_keyframe", 0);
+    av_dict_set(&opts, "use_editlist", "1", 0);
+    init(1, 1);
+    mux_gops(2);
+    finish();
+    close_out();
+
+    // Use B-frames but no audio-preroll, but without an edit list.
+    // Due to avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO, the dts
+    // of the first audio packet is > 0, but it is set to zero since edit
+    // lists aren't used, increasing the duration of the first packet instead.
+    init_out("non-empty-moov-no-elst");
+    av_dict_set(&opts, "movflags", "frag_keyframe", 0);
+    av_dict_set(&opts, "use_editlist", "0", 0);
+    init(1, 0);
+    mux_gops(2);
+    finish();
+    close_out();
+
+    format = "ismv";
+    // Write an ISMV, with B-frames and audio preroll.
+    init_out("ismv");
+    av_dict_set(&opts, "movflags", "frag_keyframe", 0);
+    init(1, 1);
+    mux_gops(2);
+    finish();
+    close_out();
+    format = "mp4";
+
+    // An initial moov that doesn't contain any samples, followed by two
+    // moof+mdat pairs.
+    init_out("empty-moov");
+    av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
+    av_dict_set(&opts, "use_editlist", "0", 0);
+    init(0, 0);
+    mux_gops(2);
+    finish();
+    close_out();
+    memcpy(content, hash, HASH_SIZE);
+
+    // Similar to the previous one, but with input that doesn't start at
+    // pts/dts 0. avoid_negative_ts behaves in the same way as
+    // in non-empty-moov-no-elst above.
+    init_out("empty-moov-no-elst");
+    av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
+    init(1, 0);
+    mux_gops(2);
+    finish();
+    close_out();
+
+    // Same as the previous one, but disable avoid_negative_ts (which
+    // would require using an edit list, but with empty_moov, one can't
+    // write a sensible edit list, when the start timestamps aren't known).
+    // This should trigger a warning - we check that the warning is produced.
+    init_count_warnings();
+    init_out("empty-moov-no-elst-no-adjust");
+    av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
+    av_dict_set(&opts, "avoid_negative_ts", "0", 0);
+    init(1, 0);
+    mux_gops(2);
+    finish();
+    close_out();
+
+    reset_count_warnings();
+    check(num_warnings > 0, "No warnings printed for unhandled start offset");
+
+    // Verify that delay_moov produces the same as empty_moov for
+    // simple input
+    init_out("delay-moov");
+    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
+    av_dict_set(&opts, "use_editlist", "0", 0);
+    init(0, 0);
+    mux_gops(2);
+    finish();
+    close_out();
+    check(!memcmp(hash, content, HASH_SIZE), "delay_moov differs from empty_moov");
+
+    // Test writing content that requires an edit list using delay_moov
+    init_out("delay-moov-elst");
+    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
+    init(1, 1);
+    mux_gops(2);
+    finish();
+    close_out();
+
+    // Test writing a file with one track lacking packets, with delay_moov.
+    skip_write_audio = 1;
+    init_out("delay-moov-empty-track");
+    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
+    init(0, 0);
+    mux_gops(2);
+    // The automatic flushing shouldn't output anything, since we're still
+    // waiting for data for some tracks
+    check(out_size == 0, "delay_moov flushed prematurely");
+    // When closed (or manually flushed), all the written data should still
+    // be output.
+    finish();
+    close_out();
+    check(out_size > 0, "delay_moov didn't output anything");
+
+    // Check that manually flushing still outputs things as expected. This
+    // produces two fragments, while the one above produces only one.
+    init_out("delay-moov-empty-track-flush");
+    av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0);
+    init(0, 0);
+    mux_gops(1);
+    av_write_frame(ctx, NULL); // Force writing the moov
+    check(out_size > 0, "No moov written");
+    av_write_frame(ctx, NULL);
+    mux_gops(1);
+    av_write_frame(ctx, NULL);
+    finish();
+    close_out();
+
+    skip_write_audio = 0;
+
+
+
+    // Verify that the header written by delay_moov when manually flushed
+    // is identical to the one by empty_moov.
+    init_out("empty-moov-header");
+    av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0);
+    av_dict_set(&opts, "use_editlist", "0", 0);
+    init(0, 0);
+    close_out();
+    memcpy(header, hash, HASH_SIZE);
+    init_out("empty-moov-content");
+    mux_gops(2);
+    // Written 2 seconds of content, with an automatic flush after 1 second.
+    check(out_size > 0, "No automatic flush?");
+    empty_moov_pos = prev_pos = out_size;
+    // Manually flush the second fragment
+    av_write_frame(ctx, NULL);
+    check(out_size > prev_pos, "No second fragment flushed?");
+    prev_pos = out_size;
+    // Check that an extra flush doesn't output any more data
+    av_write_frame(ctx, NULL);
+    check(out_size == prev_pos, "More data written?");
+    close_out();
+    memcpy(content, hash, HASH_SIZE);
+    // Ignore the trailer written here
+    finish();
+
+    init_out("delay-moov-header");
+    av_dict_set(&opts, "movflags", "frag_custom+delay_moov", 0);
+    av_dict_set(&opts, "use_editlist", "0", 0);
+    init(0, 0);
+    check(out_size == 0, "Output written during init with delay_moov");
+    mux_gops(1); // Write 1 second of content
+    av_write_frame(ctx, NULL); // Force writing the moov
+    close_out();
+    check(!memcmp(hash, header, HASH_SIZE), "delay_moov header differs from empty_moov");
+    init_out("delay-moov-content");
+    av_write_frame(ctx, NULL); // Flush the first fragment
+    check(out_size == empty_moov_pos, "Manually flushed content differs from automatically flushed, %d vs %d", out_size, empty_moov_pos);
+    mux_gops(1); // Write the rest of the content
+    av_write_frame(ctx, NULL); // Flush the second fragment
+    close_out();
+    check(!memcmp(hash, content, HASH_SIZE), "delay_moov content differs from empty_moov");
+    finish();
+
+
+    // Verify that we can produce an identical second fragment without
+    // writing the first one. First write the reference fragments that
+    // we want to reproduce.
+    av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash", 0);
+    init(0, 0);
+    mux_gops(1);
+    av_write_frame(ctx, NULL); // Output the first fragment
+    init_out("empty-moov-second-frag");
+    mux_gops(1);
+    av_write_frame(ctx, NULL); // Output the second fragment
+    close_out();
+    memcpy(content, hash, HASH_SIZE);
+    finish();
+
+    // Produce the same second fragment without actually writing the first
+    // one before.
+    av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash+frag_discont", 0);
+    av_dict_set(&opts, "fragment_index", "2", 0);
+    av_dict_set(&opts, "avoid_negative_ts", "0", 0);
+    av_dict_set(&opts, "use_editlist", "0", 0);
+    init(0, 0);
+    skip_gops(1);
+    init_out("empty-moov-second-frag-discont");
+    mux_gops(1);
+    av_write_frame(ctx, NULL); // Output the second fragment
+    close_out();
+    check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
+    finish();
+
+    // Produce the same thing by using delay_moov, which requires a slightly
+    // different call sequence.
+    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
+    av_dict_set(&opts, "fragment_index", "2", 0);
+    init(0, 0);
+    skip_gops(1);
+    mux_gops(1);
+    av_write_frame(ctx, NULL); // Output the moov
+    init_out("delay-moov-second-frag-discont");
+    av_write_frame(ctx, NULL); // Output the second fragment
+    close_out();
+    check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
+    finish();
+
+
+    // Test discontinuously written fragments with B-frames (where the
+    // assumption of starting at pts=0 works) but not with audio preroll
+    // (which can't be guessed).
+    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0);
+    init(1, 0);
+    mux_gops(1);
+    init_out("delay-moov-elst-init");
+    av_write_frame(ctx, NULL); // Output the moov
+    close_out();
+    memcpy(header, hash, HASH_SIZE);
+    av_write_frame(ctx, NULL); // Output the first fragment
+    init_out("delay-moov-elst-second-frag");
+    mux_gops(1);
+    av_write_frame(ctx, NULL); // Output the second fragment
+    close_out();
+    memcpy(content, hash, HASH_SIZE);
+    finish();
+
+    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
+    av_dict_set(&opts, "fragment_index", "2", 0);
+    init(1, 0);
+    skip_gops(1);
+    mux_gops(1); // Write the second fragment
+    init_out("delay-moov-elst-init-discont");
+    av_write_frame(ctx, NULL); // Output the moov
+    close_out();
+    check(!memcmp(hash, header, HASH_SIZE), "discontinuously written header differs");
+    init_out("delay-moov-elst-second-frag-discont");
+    av_write_frame(ctx, NULL); // Output the second fragment
+    close_out();
+    check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
+    finish();
+
+
+    // Test discontinuously written fragments with B-frames and audio preroll,
+    // properly signaled.
+    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash", 0);
+    init(1, 1);
+    mux_gops(1);
+    init_out("delay-moov-elst-signal-init");
+    av_write_frame(ctx, NULL); // Output the moov
+    close_out();
+    memcpy(header, hash, HASH_SIZE);
+    av_write_frame(ctx, NULL); // Output the first fragment
+    init_out("delay-moov-elst-signal-second-frag");
+    mux_gops(1);
+    av_write_frame(ctx, NULL); // Output the second fragment
+    close_out();
+    memcpy(content, hash, HASH_SIZE);
+    finish();
+
+    av_dict_set(&opts, "movflags", "frag_custom+delay_moov+dash+frag_discont", 0);
+    av_dict_set(&opts, "fragment_index", "2", 0);
+    init(1, 1);
+    signal_init_ts();
+    skip_gops(1);
+    mux_gops(1); // Write the second fragment
+    init_out("delay-moov-elst-signal-init-discont");
+    av_write_frame(ctx, NULL); // Output the moov
+    close_out();
+    check(!memcmp(hash, header, HASH_SIZE), "discontinuously written header differs");
+    init_out("delay-moov-elst-signal-second-frag-discont");
+    av_write_frame(ctx, NULL); // Output the second fragment
+    close_out();
+    check(!memcmp(hash, content, HASH_SIZE), "discontinuously written fragment differs");
+    finish();
+
+
+    // Test VFR content, with sidx atoms (which declare the pts duration
+    // of a fragment, forcing overriding the start pts of the next one).
+    // Here, the fragment duration in pts is significantly different from
+    // the duration in dts. The video stream starts at dts=-10,pts=0, and
+    // the second fragment starts at dts=155,pts=156. The trun duration sum
+    // of the first fragment is 165, which also is written as
+    // baseMediaDecodeTime in the tfdt in the second fragment. The sidx for
+    // the first fragment says earliest_presentation_time = 0 and
+    // subsegment_duration = 156, which also matches the sidx in the second
+    // fragment. For the audio stream, the pts and dts durations also don't
+    // match - the input stream starts at pts=-2048, but that part is excluded
+    // by the edit list.
+    init_out("vfr");
+    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0);
+    init_fps(1, 1, 3);
+    mux_frames(gop_size/2);
+    duration /= 10;
+    mux_frames(gop_size/2);
+    mux_gops(1);
+    finish();
+    close_out();
+
+    // Test VFR content, with cleared duration fields. In these cases,
+    // the muxer must guess the duration of the last packet of each
+    // fragment. As long as the framerate doesn't vary (too much) at the
+    // fragment edge, it works just fine. Additionally, when automatically
+    // cutting fragments, the muxer already know the timestamps of the next
+    // packet for one stream (in most cases the video stream), avoiding
+    // having to use guesses for that one.
+    init_count_warnings();
+    clear_duration = 1;
+    init_out("vfr-noduration");
+    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov+dash", 0);
+    init_fps(1, 1, 3);
+    mux_frames(gop_size/2);
+    duration /= 10;
+    mux_frames(gop_size/2);
+    mux_gops(1);
+    finish();
+    close_out();
+    clear_duration = 0;
+    reset_count_warnings();
+    check(num_warnings > 0, "No warnings printed for filled in durations");
+
+    // Test with an IO buffer size that is too small to hold a full fragment;
+    // this will cause write_data_type to be called with the type unknown.
+    force_iobuf_size = 1500;
+    init_out("large_frag");
+    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
+    init_fps(1, 1, 3);
+    mux_gops(2);
+    finish();
+    close_out();
+    force_iobuf_size = 0;
+
+    // Test VFR content with bframes with interleaving.
+    // Here, using av_interleaved_write_frame allows the muxer to get the
+    // fragment end durations right. We always set the packet duration to
+    // the expected, but we simulate dropped frames at one point.
+    do_interleave = 1;
+    init_out("vfr-noduration-interleave");
+    av_dict_set(&opts, "movflags", "frag_keyframe+delay_moov", 0);
+    av_dict_set(&opts, "frag_duration", "650000", 0);
+    init_fps(1, 1, 30);
+    mux_frames(gop_size/2);
+    // Pretend that the packet duration is the normal, even if
+    // we actually skip a bunch of frames. (I.e., simulate that
+    // we don't know of the framedrop in advance.)
+    fake_pkt_duration = duration;
+    duration *= 10;
+    mux_frames(1);
+    fake_pkt_duration = 0;
+    duration /= 10;
+    mux_frames(gop_size/2 - 1);
+    mux_gops(1);
+    finish();
+    close_out();
+    clear_duration = 0;
+    do_interleave = 0;
+
+
+    av_free(md5);
+
+    return check_faults > 0 ? 1 : 0;
+}
diff --git a/libavformat/tests/noproxy.c b/libavformat/tests/noproxy.c
new file mode 100644
index 0000000..782356c
--- /dev/null
+++ b/libavformat/tests/noproxy.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Martin Storsjo
+ *
+ * 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 "libavformat/network.h"
+
+static void test(const char *pattern, const char *host)
+{
+    int res = ff_http_match_no_proxy(pattern, host);
+    printf("The pattern \"%s\" %s the hostname %s\n",
+           pattern ? pattern : "(null)", res ? "matches" : "does not match",
+           host);
+}
+
+int main(void)
+{
+    test(NULL, "domain.com");
+    test("example.com domain.com", "domain.com");
+    test("example.com other.com", "domain.com");
+    test("example.com,domain.com", "domain.com");
+    test("example.com,domain.com", "otherdomain.com");
+    test("example.com, *.domain.com", "sub.domain.com");
+    test("example.com, *.domain.com", "domain.com");
+    test("example.com, .domain.com", "domain.com");
+    test("*", "domain.com");
+    return 0;
+}
diff --git a/libavformat/tests/rtmpdh.c b/libavformat/tests/rtmpdh.c
new file mode 100644
index 0000000..929b3f3
--- /dev/null
+++ b/libavformat/tests/rtmpdh.c
@@ -0,0 +1,158 @@
+/*
+ * 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 "libavformat/rtmpdh.c"
+
+#include <stdio.h>
+
+static int test_random_shared_secret(void)
+{
+    FF_DH *peer1 = NULL, *peer2 = NULL;
+    int ret;
+    uint8_t pubkey1[128], pubkey2[128];
+    uint8_t sharedkey1[128], sharedkey2[128];
+
+    peer1 = ff_dh_init(1024);
+    peer2 = ff_dh_init(1024);
+    if (!peer1 || !peer2) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+    if ((ret = ff_dh_generate_public_key(peer1)) < 0)
+        goto fail;
+    if ((ret = ff_dh_generate_public_key(peer2)) < 0)
+        goto fail;
+    if ((ret = ff_dh_write_public_key(peer1, pubkey1, sizeof(pubkey1))) < 0)
+        goto fail;
+    if ((ret = ff_dh_write_public_key(peer2, pubkey2, sizeof(pubkey2))) < 0)
+        goto fail;
+    if ((ret = ff_dh_compute_shared_secret_key(peer1, pubkey2, sizeof(pubkey2),
+                                               sharedkey1, sizeof(sharedkey1))) < 0)
+        goto fail;
+    if ((ret = ff_dh_compute_shared_secret_key(peer2, pubkey1, sizeof(pubkey1),
+                                               sharedkey2, sizeof(sharedkey2))) < 0)
+        goto fail;
+    if (memcmp(sharedkey1, sharedkey2, sizeof(sharedkey1))) {
+        printf("Mismatched generated shared key\n");
+        ret = AVERROR_INVALIDDATA;
+    } else {
+        printf("Generated shared key ok\n");
+    }
+fail:
+    ff_dh_free(peer1);
+    ff_dh_free(peer2);
+    return ret;
+}
+
+static const char *private_key =
+    "976C18FCADC255B456564F74F3EEDA59D28AF6B744D743F2357BFD2404797EF896EF1A"
+    "7C1CBEAAA3AB60AF3192D189CFF3F991C9CBBFD78119FCA2181384B94011943B6D6F28"
+    "9E1B708E2D1A0C7771169293F03DA27E561F15F16F0AC9BC858C77A80FA98FD088A232"
+    "19D08BE6F165DE0B02034B18705829FAD0ACB26A5B75EF";
+static const char *public_key =
+    "F272ECF8362257C5D2C3CC2229CF9C0A03225BC109B1DBC76A68C394F256ACA3EF5F64"
+    "FC270C26382BF315C19E97A76104A716FC998A651E8610A3AE6CF65D8FAE5D3F32EEA0"
+    "0B32CB9609B494116A825D7142D17B88E3D20EDD98743DE29CF37A23A9F6A58B960591"
+    "3157D5965FCB46DDA73A1F08DD897BAE88DFE6FC937CBA";
+static const uint8_t public_key_bin[] = {
+    0xf2, 0x72, 0xec, 0xf8, 0x36, 0x22, 0x57, 0xc5, 0xd2, 0xc3, 0xcc, 0x22,
+    0x29, 0xcf, 0x9c, 0x0a, 0x03, 0x22, 0x5b, 0xc1, 0x09, 0xb1, 0xdb, 0xc7,
+    0x6a, 0x68, 0xc3, 0x94, 0xf2, 0x56, 0xac, 0xa3, 0xef, 0x5f, 0x64, 0xfc,
+    0x27, 0x0c, 0x26, 0x38, 0x2b, 0xf3, 0x15, 0xc1, 0x9e, 0x97, 0xa7, 0x61,
+    0x04, 0xa7, 0x16, 0xfc, 0x99, 0x8a, 0x65, 0x1e, 0x86, 0x10, 0xa3, 0xae,
+    0x6c, 0xf6, 0x5d, 0x8f, 0xae, 0x5d, 0x3f, 0x32, 0xee, 0xa0, 0x0b, 0x32,
+    0xcb, 0x96, 0x09, 0xb4, 0x94, 0x11, 0x6a, 0x82, 0x5d, 0x71, 0x42, 0xd1,
+    0x7b, 0x88, 0xe3, 0xd2, 0x0e, 0xdd, 0x98, 0x74, 0x3d, 0xe2, 0x9c, 0xf3,
+    0x7a, 0x23, 0xa9, 0xf6, 0xa5, 0x8b, 0x96, 0x05, 0x91, 0x31, 0x57, 0xd5,
+    0x96, 0x5f, 0xcb, 0x46, 0xdd, 0xa7, 0x3a, 0x1f, 0x08, 0xdd, 0x89, 0x7b,
+    0xae, 0x88, 0xdf, 0xe6, 0xfc, 0x93, 0x7c, 0xba
+};
+static const uint8_t peer_public_key[] = {
+    0x58, 0x66, 0x05, 0x49, 0x94, 0x23, 0x2b, 0x66, 0x52, 0x13, 0xff, 0x46,
+    0xf2, 0xb3, 0x79, 0xa9, 0xee, 0xae, 0x1a, 0x13, 0xf0, 0x71, 0x52, 0xfb,
+    0x93, 0x4e, 0xee, 0x97, 0x05, 0x73, 0x50, 0x7d, 0xaf, 0x02, 0x07, 0x72,
+    0xac, 0xdc, 0xa3, 0x95, 0x78, 0xee, 0x9a, 0x19, 0x71, 0x7e, 0x99, 0x9f,
+    0x2a, 0xd4, 0xb3, 0xe2, 0x0c, 0x1d, 0x1a, 0x78, 0x4c, 0xde, 0xf1, 0xad,
+    0xb4, 0x60, 0xa8, 0x51, 0xac, 0x71, 0xec, 0x86, 0x70, 0xa2, 0x63, 0x36,
+    0x92, 0x7c, 0xe3, 0x87, 0xee, 0xe4, 0xf1, 0x62, 0x24, 0x74, 0xb4, 0x04,
+    0xfa, 0x5c, 0xdf, 0xba, 0xfa, 0xa3, 0xc2, 0xbb, 0x62, 0x27, 0xd0, 0xf4,
+    0xe4, 0x43, 0xda, 0x8a, 0x88, 0x69, 0x60, 0xe2, 0xdb, 0x75, 0x2a, 0x98,
+    0x9d, 0xb5, 0x50, 0xe3, 0x99, 0xda, 0xe0, 0xa6, 0x14, 0xc9, 0x80, 0x12,
+    0xf9, 0x3c, 0xac, 0x06, 0x02, 0x7a, 0xde, 0x74
+};
+static const uint8_t shared_secret[] = {
+    0xb2, 0xeb, 0xcb, 0x71, 0xf3, 0x61, 0xfb, 0x5b, 0x4e, 0x5c, 0x4c, 0xcf,
+    0x5c, 0x08, 0x5f, 0x96, 0x26, 0x77, 0x1d, 0x31, 0xf1, 0xe1, 0xf7, 0x4b,
+    0x92, 0xac, 0x82, 0x2a, 0x88, 0xc7, 0x83, 0xe1, 0xc7, 0xf3, 0xd3, 0x1a,
+    0x7d, 0xc8, 0x31, 0xe3, 0x97, 0xe4, 0xec, 0x31, 0x0e, 0x8f, 0x73, 0x1a,
+    0xe4, 0xf6, 0xd8, 0xc8, 0x94, 0xff, 0xa0, 0x03, 0x84, 0x03, 0x0f, 0xa5,
+    0x30, 0x5d, 0x67, 0xe0, 0x7a, 0x3b, 0x5f, 0xed, 0x4c, 0xf5, 0xbc, 0x18,
+    0xea, 0xd4, 0x77, 0xa9, 0x07, 0xb3, 0x54, 0x0b, 0x02, 0xd9, 0xc6, 0xb8,
+    0x66, 0x5e, 0xec, 0xa4, 0xcd, 0x47, 0xed, 0xc9, 0x38, 0xc6, 0x91, 0x08,
+    0xf3, 0x85, 0x9b, 0x69, 0x16, 0x78, 0x0d, 0xb7, 0x74, 0x51, 0xaa, 0x5b,
+    0x4d, 0x74, 0xe4, 0x29, 0x2e, 0x9e, 0x8e, 0xf7, 0xe5, 0x42, 0x83, 0xb0,
+    0x65, 0xb0, 0xce, 0xc6, 0xb2, 0x8f, 0x5b, 0xb0
+};
+
+static int test_ref_data(void)
+{
+    FF_DH *dh;
+    int ret = AVERROR(ENOMEM);
+    uint8_t pubkey_test[128];
+    uint8_t sharedkey_test[128];
+
+    dh = ff_dh_init(1024);
+    if (!dh)
+        goto fail;
+    bn_hex2bn(dh->priv_key, private_key, ret);
+    if (!ret)
+        goto fail;
+    bn_hex2bn(dh->pub_key, public_key, ret);
+    if (!ret)
+        goto fail;
+    if ((ret = ff_dh_write_public_key(dh, pubkey_test, sizeof(pubkey_test))) < 0)
+        goto fail;
+    if (memcmp(pubkey_test, public_key_bin, sizeof(pubkey_test))) {
+        printf("Mismatched generated public key\n");
+        ret = AVERROR_INVALIDDATA;
+        goto fail;
+    } else {
+        printf("Generated public key ok\n");
+    }
+    if ((ret = ff_dh_compute_shared_secret_key(dh, peer_public_key, sizeof(peer_public_key),
+                                               sharedkey_test, sizeof(sharedkey_test))) < 0)
+        goto fail;
+    if (memcmp(shared_secret, sharedkey_test, sizeof(sharedkey_test))) {
+        printf("Mismatched generated shared key\n");
+        ret = AVERROR_INVALIDDATA;
+    } else {
+        printf("Generated shared key ok\n");
+    }
+fail:
+    ff_dh_free(dh);
+    return ret;
+}
+
+int main(void)
+{
+    if (test_random_shared_secret() < 0)
+        return 1;
+    if (test_ref_data() < 0)
+        return 1;
+    return 0;
+}
diff --git a/libavformat/tests/seek.c b/libavformat/tests/seek.c
new file mode 100644
index 0000000..7ed56ba
--- /dev/null
+++ b/libavformat/tests/seek.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2007 Michael Niedermayer
+ *
+ * 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 <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/common.h"
+#include "libavutil/mathematics.h"
+
+#include "libavformat/avformat.h"
+
+static char buffer[20];
+
+static const char *ret_str(int v)
+{
+    switch (v) {
+    case AVERROR_EOF:     return "-EOF";
+    case AVERROR(EIO):    return "-EIO";
+    case AVERROR(ENOMEM): return "-ENOMEM";
+    case AVERROR(EINVAL): return "-EINVAL";
+    default:
+        snprintf(buffer, sizeof(buffer), "%2d", v);
+        return buffer;
+    }
+}
+
+static void ts_str(char buffer[60], int64_t ts, AVRational base)
+{
+    if (ts == AV_NOPTS_VALUE) {
+        strcpy(buffer, " NOPTS   ");
+        return;
+    }
+    ts= av_rescale_q(ts, base, (AVRational){1, 1000000});
+    snprintf(buffer, 60, "%c%"PRId64".%06"PRId64"", ts<0 ? '-' : ' ', FFABS(ts)/1000000, FFABS(ts)%1000000);
+}
+
+int main(int argc, char **argv)
+{
+    const char *filename;
+    AVFormatContext *ic = avformat_alloc_context();
+    int i, ret, stream_id;
+    int j;
+    int64_t timestamp;
+    AVDictionary *format_opts = NULL;
+    int64_t seekfirst = AV_NOPTS_VALUE;
+    int firstback=0;
+    int frame_count = 1;
+    int duration = 4;
+
+    for(i=2; i<argc; i+=2){
+        if       (!strcmp(argv[i], "-seekforw")){
+            seekfirst = atoi(argv[i+1]);
+        } else if(!strcmp(argv[i], "-seekback")){
+            seekfirst = atoi(argv[i+1]);
+            firstback = 1;
+        } else if(!strcmp(argv[i], "-frames")){
+            frame_count = atoi(argv[i+1]);
+        } else if(!strcmp(argv[i], "-duration")){
+            duration = atoi(argv[i+1]);
+        } else if(!strcmp(argv[i], "-fastseek")) {
+            if (atoi(argv[i+1])) {
+                ic->flags |= AVFMT_FLAG_FAST_SEEK;
+            }
+        } else if(argv[i][0] == '-' && argv[i+1]) {
+            av_dict_set(&format_opts, argv[i] + 1, argv[i+1], 0);
+        } else {
+            argc = 1;
+        }
+    }
+
+    av_dict_set(&format_opts, "channels", "1", 0);
+    av_dict_set(&format_opts, "sample_rate", "22050", 0);
+
+    /* initialize libavcodec, and register all codecs and formats */
+    av_register_all();
+
+    if (argc < 2) {
+        printf("usage: %s input_file\n"
+               "\n", argv[0]);
+        return 1;
+    }
+
+    filename = argv[1];
+
+    ret = avformat_open_input(&ic, filename, NULL, &format_opts);
+    av_dict_free(&format_opts);
+    if (ret < 0) {
+        fprintf(stderr, "cannot open %s\n", filename);
+        return 1;
+    }
+
+    ret = avformat_find_stream_info(ic, NULL);
+    if (ret < 0) {
+        fprintf(stderr, "%s: could not find codec parameters\n", filename);
+        return 1;
+    }
+
+    if(seekfirst != AV_NOPTS_VALUE){
+        if(firstback)   avformat_seek_file(ic, -1, INT64_MIN, seekfirst, seekfirst, 0);
+        else            avformat_seek_file(ic, -1, seekfirst, seekfirst, INT64_MAX, 0);
+    }
+    for(i=0; ; i++){
+        AVPacket pkt = { 0 };
+        AVStream *av_uninit(st);
+        char ts_buf[60];
+
+        if(ret>=0){
+            for(j=0; j<frame_count; j++) {
+            ret= av_read_frame(ic, &pkt);
+            if(ret>=0){
+                char dts_buf[60];
+                st= ic->streams[pkt.stream_index];
+                ts_str(dts_buf, pkt.dts, st->time_base);
+                ts_str(ts_buf,  pkt.pts, st->time_base);
+                printf("ret:%-10s st:%2d flags:%d dts:%s pts:%s pos:%7" PRId64 " size:%6d", ret_str(ret), pkt.stream_index, pkt.flags, dts_buf, ts_buf, pkt.pos, pkt.size);
+                av_packet_unref(&pkt);
+            } else
+                printf("ret:%s", ret_str(ret)); // necessary to avoid trailing whitespace
+            printf("\n");
+            }
+        }
+
+        if(i>25) break;
+
+        stream_id= (i>>1)%(ic->nb_streams+1) - 1;
+        timestamp= (i*19362894167LL) % (duration*AV_TIME_BASE) - AV_TIME_BASE;
+        if(stream_id>=0){
+            st= ic->streams[stream_id];
+            timestamp= av_rescale_q(timestamp, AV_TIME_BASE_Q, st->time_base);
+        }
+        //FIXME fully test the new seek API
+        if(i&1) ret = avformat_seek_file(ic, stream_id, INT64_MIN, timestamp, timestamp, 0);
+        else    ret = avformat_seek_file(ic, stream_id, timestamp, timestamp, INT64_MAX, 0);
+        ts_str(ts_buf, timestamp, stream_id < 0 ? AV_TIME_BASE_Q : st->time_base);
+        printf("ret:%-10s st:%2d flags:%d  ts:%s\n", ret_str(ret), stream_id, i&1, ts_buf);
+    }
+
+    avformat_close_input(&ic);
+
+    return 0;
+}
diff --git a/libavformat/tests/srtp.c b/libavformat/tests/srtp.c
new file mode 100644
index 0000000..89450ce
--- /dev/null
+++ b/libavformat/tests/srtp.c
@@ -0,0 +1,167 @@
+/*
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavformat/rtpdec.h"
+#include "libavformat/srtp.h"
+
+static const char *aes128_80_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
+
+static const uint8_t rtp_aes128_80[] = {
+    // RTP header
+    0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
+    // encrypted payload
+    0x62, 0x69, 0x76, 0xca, 0xc5,
+    // HMAC
+    0xa1, 0xac, 0x1b, 0xb4, 0xa0, 0x1c, 0xd5, 0x49, 0x28, 0x99,
+};
+
+static const uint8_t rtcp_aes128_80[] = {
+    // RTCP header
+    0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
+    // encrypted payload
+    0x8a, 0xac, 0xdc, 0xa5, 0x4c, 0xf6, 0x78, 0xa6, 0x62, 0x8f, 0x24, 0xda,
+    0x6c, 0x09, 0x3f, 0xa9, 0x28, 0x7a, 0xb5, 0x7f, 0x1f, 0x0f, 0xc9, 0x35,
+    // RTCP index
+    0x80, 0x00, 0x00, 0x03,
+    // HMAC
+    0xe9, 0x3b, 0xc0, 0x5c, 0x0c, 0x06, 0x9f, 0xab, 0xc0, 0xde,
+};
+
+static const char *aes128_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
+
+static const uint8_t rtp_aes128_32[] = {
+    // RTP header
+    0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
+    // encrypted payload
+    0x62, 0x69, 0x76, 0xca, 0xc5,
+    // HMAC
+    0xa1, 0xac, 0x1b, 0xb4,
+};
+
+static const uint8_t rtcp_aes128_32[] = {
+    // RTCP header
+    0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
+    // encrypted payload
+    0x35, 0xe9, 0xb5, 0xff, 0x0d, 0xd1, 0xde, 0x70, 0x74, 0x10, 0xaa, 0x1b,
+    0xb2, 0x8d, 0xf0, 0x20, 0x02, 0x99, 0x6b, 0x1b, 0x0b, 0xd0, 0x47, 0x34,
+    // RTCP index
+    0x80, 0x00, 0x00, 0x04,
+    // HMAC
+    0x5b, 0xd2, 0xa9, 0x9d,
+};
+
+static const char *aes128_80_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
+
+static const uint8_t rtp_aes128_80_32[] = {
+    // RTP header
+    0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
+    // encrypted payload
+    0x62, 0x69, 0x76, 0xca, 0xc5,
+    // HMAC
+    0xa1, 0xac, 0x1b, 0xb4,
+};
+
+static const uint8_t rtcp_aes128_80_32[] = {
+    // RTCP header
+    0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
+    // encrypted payload
+    0xd6, 0xae, 0xc1, 0x58, 0x63, 0x70, 0xc9, 0x88, 0x66, 0x26, 0x1c, 0x53,
+    0xff, 0x5d, 0x5d, 0x2b, 0x0f, 0x8c, 0x72, 0x3e, 0xc9, 0x1d, 0x43, 0xf9,
+    // RTCP index
+    0x80, 0x00, 0x00, 0x05,
+    // HMAC
+    0x09, 0x16, 0xb4, 0x27, 0x9a, 0xe9, 0x92, 0x26, 0x4e, 0x10,
+};
+
+static void print_data(const uint8_t *buf, int len)
+{
+    int i;
+    for (i = 0; i < len; i++)
+        printf("%02x", buf[i]);
+    printf("\n");
+}
+
+static int test_decrypt(struct SRTPContext *srtp, const uint8_t *in, int len,
+                        uint8_t *out)
+{
+    memcpy(out, in, len);
+    if (!ff_srtp_decrypt(srtp, out, &len)) {
+        print_data(out, len);
+        return len;
+    } else
+        return -1;
+}
+
+static void test_encrypt(const uint8_t *data, int in_len, const char *suite,
+                         const char *key)
+{
+    struct SRTPContext enc = { 0 }, dec = { 0 };
+    int len;
+    char buf[RTP_MAX_PACKET_LENGTH];
+    ff_srtp_set_crypto(&enc, suite, key);
+    ff_srtp_set_crypto(&dec, suite, key);
+    len = ff_srtp_encrypt(&enc, data, in_len, buf, sizeof(buf));
+    if (!ff_srtp_decrypt(&dec, buf, &len)) {
+        if (len == in_len && !memcmp(buf, data, len))
+            printf("Decrypted content matches input\n");
+        else
+            printf("Decrypted content doesn't match input\n");
+    } else {
+        printf("Decryption failed\n");
+    }
+    ff_srtp_free(&enc);
+    ff_srtp_free(&dec);
+}
+
+int main(void)
+{
+    static const char *aes128_80_suite = "AES_CM_128_HMAC_SHA1_80";
+    static const char *aes128_32_suite = "AES_CM_128_HMAC_SHA1_32";
+    static const char *aes128_80_32_suite = "SRTP_AES128_CM_HMAC_SHA1_32";
+    static const char *test_key = "abcdefghijklmnopqrstuvwxyz1234567890ABCD";
+    uint8_t buf[RTP_MAX_PACKET_LENGTH];
+    struct SRTPContext srtp = { 0 };
+    int len;
+    ff_srtp_set_crypto(&srtp, aes128_80_suite, aes128_80_key);
+    len = test_decrypt(&srtp, rtp_aes128_80, sizeof(rtp_aes128_80), buf);
+    test_encrypt(buf, len, aes128_80_suite, test_key);
+    test_encrypt(buf, len, aes128_32_suite, test_key);
+    test_encrypt(buf, len, aes128_80_32_suite, test_key);
+    test_decrypt(&srtp, rtcp_aes128_80, sizeof(rtcp_aes128_80), buf);
+    test_encrypt(buf, len, aes128_80_suite, test_key);
+    test_encrypt(buf, len, aes128_32_suite, test_key);
+    test_encrypt(buf, len, aes128_80_32_suite, test_key);
+    ff_srtp_free(&srtp);
+
+    memset(&srtp, 0, sizeof(srtp)); // Clear the context
+    ff_srtp_set_crypto(&srtp, aes128_32_suite, aes128_32_key);
+    test_decrypt(&srtp, rtp_aes128_32, sizeof(rtp_aes128_32), buf);
+    test_decrypt(&srtp, rtcp_aes128_32, sizeof(rtcp_aes128_32), buf);
+    ff_srtp_free(&srtp);
+
+    memset(&srtp, 0, sizeof(srtp)); // Clear the context
+    ff_srtp_set_crypto(&srtp, aes128_80_32_suite, aes128_80_32_key);
+    test_decrypt(&srtp, rtp_aes128_80_32, sizeof(rtp_aes128_80_32), buf);
+    test_decrypt(&srtp, rtcp_aes128_80_32, sizeof(rtcp_aes128_80_32), buf);
+    ff_srtp_free(&srtp);
+    return 0;
+}
diff --git a/libavformat/tests/url.c b/libavformat/tests/url.c
new file mode 100644
index 0000000..1623179
--- /dev/null
+++ b/libavformat/tests/url.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012 Martin Storsjo
+ *
+ * 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 "libavformat/url.h"
+
+static void test(const char *base, const char *rel)
+{
+    char buf[200], buf2[200];
+    ff_make_absolute_url(buf, sizeof(buf), base, rel);
+    printf("%s\n", buf);
+    if (base) {
+        /* Test in-buffer replacement */
+        snprintf(buf2, sizeof(buf2), "%s", base);
+        ff_make_absolute_url(buf2, sizeof(buf2), buf2, rel);
+        if (strcmp(buf, buf2)) {
+            printf("In-place handling of %s + %s failed\n", base, rel);
+            exit(1);
+        }
+    }
+}
+
+int main(void)
+{
+    test(NULL, "baz");
+    test("/foo/bar", "baz");
+    test("/foo/bar", "../baz");
+    test("/foo/bar", "/baz");
+    test("http://server/foo/", "baz");
+    test("http://server/foo/bar", "baz");
+    test("http://server/foo/", "../baz");
+    test("http://server/foo/bar/123", "../../baz");
+    test("http://server/foo/bar/123", "/baz");
+    test("http://server/foo/bar/123", "https://other/url");
+    test("http://server/foo/bar?param=value/with/slashes", "/baz");
+    test("http://server/foo/bar?param&otherparam", "?someparam");
+    test("http://server/foo/bar", "//other/url");
+    return 0;
+}
diff --git a/libavformat/thp.c b/libavformat/thp.c
index 5569027..76b9b38 100644
--- a/libavformat/thp.c
+++ b/libavformat/thp.c
@@ -109,11 +109,12 @@ static int thp_read_header(AVFormatContext *s)
             /* The denominator and numerator are switched because 1/fps
                is required.  */
             avpriv_set_pts_info(st, 64, thp->fps.den, thp->fps.num);
-            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            st->codec->codec_id = AV_CODEC_ID_THP;
-            st->codec->codec_tag = 0;  /* no fourcc */
-            st->codec->width = avio_rb32(pb);
-            st->codec->height = avio_rb32(pb);
+            st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            st->codecpar->codec_id = AV_CODEC_ID_THP;
+            st->codecpar->codec_tag = 0;  /* no fourcc */
+            st->codecpar->width = avio_rb32(pb);
+            st->codecpar->height = avio_rb32(pb);
+            st->codecpar->sample_rate = av_q2d(thp->fps);
             st->nb_frames =
             st->duration = thp->framecnt;
             thp->vst = st;
@@ -130,14 +131,14 @@ static int thp_read_header(AVFormatContext *s)
             if (!st)
                 return AVERROR(ENOMEM);
 
-            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-            st->codec->codec_id = AV_CODEC_ID_ADPCM_THP;
-            st->codec->codec_tag = 0;  /* no fourcc */
-            st->codec->channels    = avio_rb32(pb); /* numChannels.  */
-            st->codec->sample_rate = avio_rb32(pb); /* Frequency.  */
+            st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+            st->codecpar->codec_id = AV_CODEC_ID_ADPCM_THP;
+            st->codecpar->codec_tag = 0;  /* no fourcc */
+            st->codecpar->channels    = avio_rb32(pb); /* numChannels.  */
+            st->codecpar->sample_rate = avio_rb32(pb); /* Frequency.  */
             st->duration           = avio_rb32(pb);
 
-            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+            avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
             thp->audio_stream_index = st->index;
             thp->has_audio = 1;
diff --git a/libavformat/tiertexseq.c b/libavformat/tiertexseq.c
index 659ba06..6e00692 100644
--- a/libavformat/tiertexseq.c
+++ b/libavformat/tiertexseq.c
@@ -214,11 +214,11 @@ static int seq_read_header(AVFormatContext *s)
 
     avpriv_set_pts_info(st, 32, 1, SEQ_FRAME_RATE);
     seq->video_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_TIERTEXSEQVIDEO;
-    st->codec->codec_tag = 0;  /* no fourcc */
-    st->codec->width = SEQ_FRAME_W;
-    st->codec->height = SEQ_FRAME_H;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_TIERTEXSEQVIDEO;
+    st->codecpar->codec_tag = 0;  /* no fourcc */
+    st->codecpar->width = SEQ_FRAME_W;
+    st->codecpar->height = SEQ_FRAME_H;
 
     /* initialize the audio decoder stream */
     st = avformat_new_stream(s, NULL);
@@ -228,15 +228,15 @@ static int seq_read_header(AVFormatContext *s)
     st->start_time = 0;
     avpriv_set_pts_info(st, 32, 1, SEQ_SAMPLE_RATE);
     seq->audio_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_PCM_S16BE;
-    st->codec->codec_tag = 0;  /* no tag */
-    st->codec->channels = 1;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    st->codec->sample_rate = SEQ_SAMPLE_RATE;
-    st->codec->bits_per_coded_sample = 16;
-    st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample * st->codec->channels;
-    st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample / 8;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE;
+    st->codecpar->codec_tag = 0;  /* no tag */
+    st->codecpar->channels = 1;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->sample_rate = SEQ_SAMPLE_RATE;
+    st->codecpar->bits_per_coded_sample = 16;
+    st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->channels;
+    st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample / 8;
 
     return 0;
 }
diff --git a/libavformat/tls.c b/libavformat/tls.c
index c625983..10e0792 100644
--- a/libavformat/tls.c
+++ b/libavformat/tls.c
@@ -106,5 +106,5 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV
 
     return ffurl_open_whitelist(&c->tcp, buf, AVIO_FLAG_READ_WRITE,
                                 &parent->interrupt_callback, options,
-                                parent->protocol_whitelist);
+                                parent->protocol_whitelist, parent->protocol_blacklist, parent);
 }
diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c
index 4bf9448..991b36b 100644
--- a/libavformat/tls_gnutls.c
+++ b/libavformat/tls_gnutls.c
@@ -247,7 +247,7 @@ static const AVClass tls_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_tls_gnutls_protocol = {
+const URLProtocol ff_tls_gnutls_protocol = {
     .name           = "tls",
     .url_open2      = tls_open,
     .url_read       = tls_read,
diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c
index 636d4ee..46eb3e6 100644
--- a/libavformat/tls_openssl.c
+++ b/libavformat/tls_openssl.c
@@ -295,7 +295,7 @@ static const AVClass tls_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_tls_openssl_protocol = {
+const URLProtocol ff_tls_openssl_protocol = {
     .name           = "tls",
     .url_open2      = tls_open,
     .url_read       = tls_read,
diff --git a/libavformat/tls_schannel.c b/libavformat/tls_schannel.c
index 85c01a0..c11b7d4 100644
--- a/libavformat/tls_schannel.c
+++ b/libavformat/tls_schannel.c
@@ -589,7 +589,7 @@ static const AVClass tls_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_tls_schannel_protocol = {
+const URLProtocol ff_tls_schannel_protocol = {
     .name           = "tls",
     .url_open2      = tls_open,
     .url_read       = tls_read,
diff --git a/libavformat/tls_securetransport.c b/libavformat/tls_securetransport.c
index 482771a..253c89c 100644
--- a/libavformat/tls_securetransport.c
+++ b/libavformat/tls_securetransport.c
@@ -83,7 +83,7 @@ static int import_pem(URLContext *h, char *path, CFArrayRef *array)
 
     if ((ret = ffio_open_whitelist(&s, path, AVIO_FLAG_READ,
                                    &h->interrupt_callback, NULL,
-                                   h->protocol_whitelist)) < 0)
+                                   h->protocol_whitelist, h->protocol_blacklist)) < 0)
         goto end;
 
     if ((ret = avio_size(s)) < 0)
@@ -387,7 +387,7 @@ static const AVClass tls_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-URLProtocol ff_tls_securetransport_protocol = {
+const URLProtocol ff_tls_securetransport_protocol = {
     .name           = "tls",
     .url_open2      = tls_open,
     .url_read       = tls_read,
diff --git a/libavformat/tmv.c b/libavformat/tmv.c
index ad172f4..2e35171 100644
--- a/libavformat/tmv.c
+++ b/libavformat/tmv.c
@@ -81,8 +81,8 @@ static int tmv_read_header(AVFormatContext *s)
     if (!(ast = avformat_new_stream(s, NULL)))
         return AVERROR(ENOMEM);
 
-    ast->codec->sample_rate = avio_rl16(pb);
-    if (!ast->codec->sample_rate) {
+    ast->codecpar->sample_rate = avio_rl16(pb);
+    if (!ast->codecpar->sample_rate) {
         av_log(s, AV_LOG_ERROR, "invalid sample rate\n");
         return -1;
     }
@@ -111,29 +111,29 @@ static int tmv_read_header(AVFormatContext *s)
         return -1;
     }
 
-    ast->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
-    ast->codec->codec_id              = AV_CODEC_ID_PCM_U8;
+    ast->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
+    ast->codecpar->codec_id              = AV_CODEC_ID_PCM_U8;
     if (features & TMV_STEREO) {
-        ast->codec->channels       = 2;
-        ast->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+        ast->codecpar->channels       = 2;
+        ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
     } else {
-        ast->codec->channels       = 1;
-        ast->codec->channel_layout = AV_CH_LAYOUT_MONO;
+        ast->codecpar->channels       = 1;
+        ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
     }
-    ast->codec->bits_per_coded_sample = 8;
-    ast->codec->bit_rate              = ast->codec->sample_rate *
-                                        ast->codec->bits_per_coded_sample;
-    avpriv_set_pts_info(ast, 32, 1, ast->codec->sample_rate);
+    ast->codecpar->bits_per_coded_sample = 8;
+    ast->codecpar->bit_rate              = ast->codecpar->sample_rate *
+                                           ast->codecpar->bits_per_coded_sample;
+    avpriv_set_pts_info(ast, 32, 1, ast->codecpar->sample_rate);
 
-    fps.num = ast->codec->sample_rate * ast->codec->channels;
+    fps.num = ast->codecpar->sample_rate * ast->codecpar->channels;
     fps.den = tmv->audio_chunk_size;
     av_reduce(&fps.num, &fps.den, fps.num, fps.den, 0xFFFFFFFFLL);
 
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_id   = AV_CODEC_ID_TMV;
-    vst->codec->pix_fmt    = AV_PIX_FMT_PAL8;
-    vst->codec->width      = char_cols * 8;
-    vst->codec->height     = char_rows * 8;
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_id   = AV_CODEC_ID_TMV;
+    vst->codecpar->format     = AV_PIX_FMT_PAL8;
+    vst->codecpar->width      = char_cols * 8;
+    vst->codecpar->height     = char_rows * 8;
     avpriv_set_pts_info(vst, 32, fps.den, fps.num);
 
     if (features & TMV_PADDING)
@@ -141,8 +141,8 @@ static int tmv_read_header(AVFormatContext *s)
             ((tmv->video_chunk_size + tmv->audio_chunk_size + 511) & ~511) -
              (tmv->video_chunk_size + tmv->audio_chunk_size);
 
-    vst->codec->bit_rate = ((tmv->video_chunk_size + tmv->padding) *
-                            fps.num * 8) / fps.den;
+    vst->codecpar->bit_rate = ((tmv->video_chunk_size + tmv->padding) *
+                               fps.num * 8) / fps.den;
 
     return 0;
 }
diff --git a/libavformat/tta.c b/libavformat/tta.c
index 7566939..02656ac 100644
--- a/libavformat/tta.c
+++ b/libavformat/tta.c
@@ -19,14 +19,15 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include "libavcodec/get_bits.h"
+#include "libavutil/crc.h"
+#include "libavutil/dict.h"
+#include "libavutil/intreadwrite.h"
+
 #include "apetag.h"
 #include "avformat.h"
 #include "avio_internal.h"
 #include "internal.h"
 #include "id3v1.h"
-#include "libavutil/crc.h"
-#include "libavutil/dict.h"
 
 typedef struct TTAContext {
     int totalframes, currentframe;
@@ -114,11 +115,11 @@ static int tta_read_header(AVFormatContext *s)
         return framepos;
     framepos += 4 * c->totalframes + 4;
 
-    if (ff_alloc_extradata(st->codec, avio_tell(s->pb) - start_offset))
+    if (ff_alloc_extradata(st->codecpar, avio_tell(s->pb) - start_offset))
         return AVERROR(ENOMEM);
 
     avio_seek(s->pb, start_offset, SEEK_SET);
-    avio_read(s->pb, st->codec->extradata, st->codec->extradata_size);
+    avio_read(s->pb, st->codecpar->extradata, st->codecpar->extradata_size);
 
     ffio_init_checksum(s->pb, tta_check_crc, UINT32_MAX);
     for (i = 0; i < c->totalframes; i++) {
@@ -135,11 +136,11 @@ static int tta_read_header(AVFormatContext *s)
         return AVERROR_INVALIDDATA;
     }
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_TTA;
-    st->codec->channels = channels;
-    st->codec->sample_rate = samplerate;
-    st->codec->bits_per_coded_sample = bps;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_TTA;
+    st->codecpar->channels = channels;
+    st->codecpar->sample_rate = samplerate;
+    st->codecpar->bits_per_coded_sample = bps;
 
     if (s->pb->seekable) {
         int64_t pos = avio_tell(s->pb);
diff --git a/libavformat/tty.c b/libavformat/tty.c
index 9022e91..b407645 100644
--- a/libavformat/tty.c
+++ b/libavformat/tty.c
@@ -82,12 +82,12 @@ static int read_header(AVFormatContext *avctx)
         ret = AVERROR(ENOMEM);
         goto fail;
     }
-    st->codec->codec_tag   = 0;
-    st->codec->codec_type  = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id    = AV_CODEC_ID_ANSI;
+    st->codecpar->codec_tag   = 0;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id    = AV_CODEC_ID_ANSI;
 
-    st->codec->width  = s->width;
-    st->codec->height = s->height;
+    st->codecpar->width  = s->width;
+    st->codecpar->height = s->height;
     avpriv_set_pts_info(st, 60, s->framerate.den, s->framerate.num);
     st->avg_frame_rate = s->framerate;
 
@@ -138,7 +138,7 @@ static int read_packet(AVFormatContext *avctx, AVPacket *pkt)
 static const AVOption options[] = {
     { "chars_per_frame", "", offsetof(TtyDemuxContext, chars_per_frame), AV_OPT_TYPE_INT, {.i64 = 6000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM},
     { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
-    { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, DEC },
+    { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC },
     { NULL },
 };
 
diff --git a/libavformat/txd.c b/libavformat/txd.c
index cac37d5..18c9683 100644
--- a/libavformat/txd.c
+++ b/libavformat/txd.c
@@ -44,8 +44,8 @@ static int txd_read_header(AVFormatContext *s) {
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_TXD;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_TXD;
     avpriv_set_pts_info(st, 64, 1, 5);
     st->avg_frame_rate = av_inv_q(st->time_base);
     /* the parameters will be extracted from the compressed bitstream */
diff --git a/libavformat/udp.c b/libavformat/udp.c
index ea80e52..8699c1c 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -29,6 +29,7 @@
 
 #include "avformat.h"
 #include "avio_internal.h"
+#include "libavutil/avassert.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/fifo.h"
 #include "libavutil/intreadwrite.h"
@@ -92,6 +93,9 @@ typedef struct UDPContext {
     int circular_buffer_size;
     AVFifoBuffer *fifo;
     int circular_buffer_error;
+    int64_t bitrate; /* number of bits to send per second */
+    int64_t burst_bits;
+    int close_req;
 #if HAVE_PTHREAD_CANCEL
     pthread_t circular_buffer_thread;
     pthread_mutex_t mutex;
@@ -112,6 +116,8 @@ typedef struct UDPContext {
 #define E AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
     { "buffer_size",    "System data size (in bytes)",                     OFFSET(buffer_size),    AV_OPT_TYPE_INT,    { .i64 = -1 },    -1, INT_MAX, .flags = D|E },
+    { "bitrate",        "Bits to send per second",                         OFFSET(bitrate),        AV_OPT_TYPE_INT64,  { .i64 = 0  },     0, INT64_MAX, .flags = E },
+    { "burst_bits",     "Max length of bursts in bits (when using bitrate)", OFFSET(burst_bits),   AV_OPT_TYPE_INT64,  { .i64 = 0  },     0, INT64_MAX, .flags = E },
     { "localport",      "Local port",                                      OFFSET(local_port),     AV_OPT_TYPE_INT,    { .i64 = -1 },    -1, INT_MAX, D|E },
     { "local_port",     "Local port",                                      OFFSET(local_port),     AV_OPT_TYPE_INT,    { .i64 = -1 },    -1, INT_MAX, .flags = D|E },
     { "localaddr",      "Local address",                                   OFFSET(localaddr),      AV_OPT_TYPE_STRING, { .str = NULL },               .flags = D|E },
@@ -260,7 +266,7 @@ static struct addrinfo *udp_resolve_host(URLContext *h,
         res = NULL;
         av_log(h, AV_LOG_ERROR, "getaddrinfo(%s, %s): %s\n",
                node ? node : "unknown",
-               service ? service : "unknown",
+               service,
                gai_strerror(error));
     }
 
@@ -486,7 +492,7 @@ static int udp_get_file_handle(URLContext *h)
 }
 
 #if HAVE_PTHREAD_CANCEL
-static void *circular_buffer_task( void *_URLContext)
+static void *circular_buffer_task_rx( void *_URLContext)
 {
     URLContext *h = _URLContext;
     UDPContext *s = h->priv_data;
@@ -542,6 +548,109 @@ end:
     pthread_mutex_unlock(&s->mutex);
     return NULL;
 }
+
+static void *circular_buffer_task_tx( void *_URLContext)
+{
+    URLContext *h = _URLContext;
+    UDPContext *s = h->priv_data;
+    int old_cancelstate;
+    int64_t target_timestamp = av_gettime_relative();
+    int64_t start_timestamp = av_gettime_relative();
+    int64_t sent_bits = 0;
+    int64_t burst_interval = s->bitrate ? (s->burst_bits * 1000000 / s->bitrate) : 0;
+    int64_t max_delay = s->bitrate ?  ((int64_t)h->max_packet_size * 8 * 1000000 / s->bitrate + 1) : 0;
+
+    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate);
+    pthread_mutex_lock(&s->mutex);
+
+    if (ff_socket_nonblock(s->udp_fd, 0) < 0) {
+        av_log(h, AV_LOG_ERROR, "Failed to set blocking mode");
+        s->circular_buffer_error = AVERROR(EIO);
+        goto end;
+    }
+
+    for(;;) {
+        int len;
+        const uint8_t *p;
+        uint8_t tmp[4];
+        int64_t timestamp;
+
+        len=av_fifo_size(s->fifo);
+
+        while (len<4) {
+            if (s->close_req)
+                goto end;
+            if (pthread_cond_wait(&s->cond, &s->mutex) < 0) {
+                goto end;
+            }
+            len=av_fifo_size(s->fifo);
+        }
+
+        av_fifo_generic_read(s->fifo, tmp, 4, NULL);
+        len=AV_RL32(tmp);
+
+        av_assert0(len >= 0);
+        av_assert0(len <= sizeof(s->tmp));
+
+        av_fifo_generic_read(s->fifo, s->tmp, len, NULL);
+
+        pthread_mutex_unlock(&s->mutex);
+        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelstate);
+
+        if (s->bitrate) {
+            timestamp = av_gettime_relative();
+            if (timestamp < target_timestamp) {
+                int64_t delay = target_timestamp - timestamp;
+                if (delay > max_delay) {
+                    delay = max_delay;
+                    start_timestamp = timestamp + delay;
+                    sent_bits = 0;
+                }
+                av_usleep(delay);
+            } else {
+                if (timestamp - burst_interval > target_timestamp) {
+                    start_timestamp = timestamp - burst_interval;
+                    sent_bits = 0;
+                }
+            }
+            sent_bits += len * 8;
+            target_timestamp = start_timestamp + sent_bits * 1000000 / s->bitrate;
+        }
+
+        p = s->tmp;
+        while (len) {
+            int ret;
+            av_assert0(len > 0);
+            if (!s->is_connected) {
+                ret = sendto (s->udp_fd, p, len, 0,
+                            (struct sockaddr *) &s->dest_addr,
+                            s->dest_addr_len);
+            } else
+                ret = send(s->udp_fd, p, len, 0);
+            if (ret >= 0) {
+                len -= ret;
+                p   += ret;
+            } else {
+                ret = ff_neterrno();
+                if (ret != AVERROR(EAGAIN) && ret != AVERROR(EINTR)) {
+                    pthread_mutex_lock(&s->mutex);
+                    s->circular_buffer_error = ret;
+                    pthread_mutex_unlock(&s->mutex);
+                    return NULL;
+                }
+            }
+        }
+
+        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate);
+        pthread_mutex_lock(&s->mutex);
+    }
+
+end:
+    pthread_mutex_unlock(&s->mutex);
+    return NULL;
+}
+
+
 #endif
 
 static int parse_source_list(char *buf, char **sources, int *num_sources,
@@ -650,6 +759,16 @@ static int udp_open(URLContext *h, const char *uri, int flags)
                        "'circular_buffer_size' option was set but it is not supported "
                        "on this build (pthread support is required)\n");
         }
+        if (av_find_info_tag(buf, sizeof(buf), "bitrate", p)) {
+            s->bitrate = strtoll(buf, NULL, 10);
+            if (!HAVE_PTHREAD_CANCEL)
+                av_log(h, AV_LOG_WARNING,
+                       "'bitrate' option was set but it is not supported "
+                       "on this build (pthread support is required)\n");
+        }
+        if (av_find_info_tag(buf, sizeof(buf), "burst_bits", p)) {
+            s->burst_bits = strtoll(buf, NULL, 10);
+        }
         if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
             av_strlcpy(localaddr, buf, sizeof(localaddr));
         }
@@ -829,7 +948,18 @@ static int udp_open(URLContext *h, const char *uri, int flags)
     s->udp_fd = udp_fd;
 
 #if HAVE_PTHREAD_CANCEL
-    if (!is_output && s->circular_buffer_size) {
+    /*
+      Create thread in case of:
+      1. Input and circular_buffer_size is set
+      2. Output and bitrate and circular_buffer_size is set
+    */
+
+    if (is_output && s->bitrate && !s->circular_buffer_size) {
+        /* Warn user in case of 'circular_buffer_size' is not set */
+        av_log(h, AV_LOG_WARNING,"'bitrate' option was set but 'circular_buffer_size' is not, but required\n");
+    }
+
+    if ((!is_output && s->circular_buffer_size) || (is_output && s->bitrate && s->circular_buffer_size)) {
         int ret;
 
         /* start the task going */
@@ -844,7 +974,7 @@ static int udp_open(URLContext *h, const char *uri, int flags)
             av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", strerror(ret));
             goto cond_fail;
         }
-        ret = pthread_create(&s->circular_buffer_thread, NULL, circular_buffer_task, h);
+        ret = pthread_create(&s->circular_buffer_thread, NULL, is_output?circular_buffer_task_tx:circular_buffer_task_rx, h);
         if (ret != 0) {
             av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", strerror(ret));
             goto thread_fail;
@@ -945,6 +1075,35 @@ static int udp_write(URLContext *h, const uint8_t *buf, int size)
     UDPContext *s = h->priv_data;
     int ret;
 
+#if HAVE_PTHREAD_CANCEL
+    if (s->fifo) {
+        uint8_t tmp[4];
+
+        pthread_mutex_lock(&s->mutex);
+
+        /*
+          Return error if last tx failed.
+          Here we can't know on which packet error was, but it needs to know that error exists.
+        */
+        if (s->circular_buffer_error<0) {
+            int err=s->circular_buffer_error;
+            pthread_mutex_unlock(&s->mutex);
+            return err;
+        }
+
+        if(av_fifo_space(s->fifo) < size + 4) {
+            /* What about a partial packet tx ? */
+            pthread_mutex_unlock(&s->mutex);
+            return AVERROR(ENOMEM);
+        }
+        AV_WL32(tmp, size);
+        av_fifo_generic_write(s->fifo, tmp, 4, NULL); /* size of packet */
+        av_fifo_generic_write(s->fifo, (uint8_t *)buf, size, NULL); /* the data */
+        pthread_cond_signal(&s->cond);
+        pthread_mutex_unlock(&s->mutex);
+        return size;
+    }
+#endif
     if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
         ret = ff_network_wait_fd(s->udp_fd, 1);
         if (ret < 0)
@@ -965,13 +1124,24 @@ static int udp_close(URLContext *h)
 {
     UDPContext *s = h->priv_data;
 
+#if HAVE_PTHREAD_CANCEL
+    // Request close once writing is finished
+    if (s->thread_started && !(h->flags & AVIO_FLAG_READ)) {
+        pthread_mutex_lock(&s->mutex);
+        s->close_req = 1;
+        pthread_cond_signal(&s->cond);
+        pthread_mutex_unlock(&s->mutex);
+    }
+#endif
+
     if (s->is_multicast && (h->flags & AVIO_FLAG_READ))
         udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr,(struct sockaddr *)&s->local_addr_storage);
-    closesocket(s->udp_fd);
 #if HAVE_PTHREAD_CANCEL
     if (s->thread_started) {
         int ret;
-        pthread_cancel(s->circular_buffer_thread);
+        // Cancel only read, as write has been signaled as success to the user
+        if (h->flags & AVIO_FLAG_READ)
+            pthread_cancel(s->circular_buffer_thread);
         ret = pthread_join(s->circular_buffer_thread, NULL);
         if (ret != 0)
             av_log(h, AV_LOG_ERROR, "pthread_join(): %s\n", strerror(ret));
@@ -979,11 +1149,12 @@ static int udp_close(URLContext *h)
         pthread_cond_destroy(&s->cond);
     }
 #endif
+    closesocket(s->udp_fd);
     av_fifo_freep(&s->fifo);
     return 0;
 }
 
-URLProtocol ff_udp_protocol = {
+const URLProtocol ff_udp_protocol = {
     .name                = "udp",
     .url_open            = udp_open,
     .url_read            = udp_read,
@@ -995,7 +1166,7 @@ URLProtocol ff_udp_protocol = {
     .flags               = URL_PROTOCOL_FLAG_NETWORK,
 };
 
-URLProtocol ff_udplite_protocol = {
+const URLProtocol ff_udplite_protocol = {
     .name                = "udplite",
     .url_open            = udplite_open,
     .url_read            = udp_read,
diff --git a/libavformat/uncodedframecrcenc.c b/libavformat/uncodedframecrcenc.c
index ed4532d..5e1a445 100644
--- a/libavformat/uncodedframecrcenc.c
+++ b/libavformat/uncodedframecrcenc.c
@@ -119,6 +119,11 @@ static void audio_frame_cksum(AVBPrint *bp, AVFrame *frame)
     }
 }
 
+static int write_header(struct AVFormatContext *s)
+{
+    return ff_framehash_write_header(s);
+}
+
 static int write_frame(struct AVFormatContext *s, int stream_index,
                        AVFrame **frame, unsigned flags)
 {
@@ -133,7 +138,7 @@ static int write_frame(struct AVFormatContext *s, int stream_index,
     av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
     av_bprintf(&bp, "%d, %10"PRId64"",
                stream_index, (*frame)->pts);
-    type = s->streams[stream_index]->codec->codec_type;
+    type = s->streams[stream_index]->codecpar->codec_type;
     type_name = av_get_media_type_string(type);
     av_bprintf(&bp, ", %s", type_name ? type_name : "unknown");
     switch (type) {
@@ -164,7 +169,7 @@ AVOutputFormat ff_uncodedframecrc_muxer = {
     .long_name         = NULL_IF_CONFIG_SMALL("uncoded framecrc testing"),
     .audio_codec       = AV_CODEC_ID_PCM_S16LE,
     .video_codec       = AV_CODEC_ID_RAWVIDEO,
-    .write_header      = ff_framehash_write_header,
+    .write_header      = write_header,
     .write_packet      = write_packet,
     .write_uncoded_frame = write_frame,
     .flags             = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT |
diff --git a/libavformat/unix.c b/libavformat/unix.c
index b3d5fac..4f01d14 100644
--- a/libavformat/unix.c
+++ b/libavformat/unix.c
@@ -23,7 +23,6 @@
  * @file
  *
  * Unix socket url_protocol
- *
  */
 
 #include "libavutil/avstring.h"
@@ -73,6 +72,9 @@ static int unix_open(URLContext *h, const char *filename, int flags)
     if ((fd = ff_socket(AF_UNIX, s->type, 0)) < 0)
         return ff_neterrno();
 
+    if (s->timeout < 0 && h->rw_timeout)
+        s->timeout = h->rw_timeout / 1000;
+
     if (s->listen) {
         ret = ff_listen_bind(fd, (struct sockaddr *)&s->addr,
                              sizeof(s->addr), s->timeout, h);
@@ -141,7 +143,7 @@ static int unix_get_file_handle(URLContext *h)
     return s->fd;
 }
 
-URLProtocol ff_unix_protocol = {
+const URLProtocol ff_unix_protocol = {
     .name                = "unix",
     .url_open            = unix_open,
     .url_read            = unix_read,
diff --git a/libavformat/url-test.c b/libavformat/url-test.c
deleted file mode 100644
index a1da82e..0000000
--- a/libavformat/url-test.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2012 Martin Storsjo
- *
- * 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 "url.h"
-
-static void test(const char *base, const char *rel)
-{
-    char buf[200], buf2[200];
-    ff_make_absolute_url(buf, sizeof(buf), base, rel);
-    printf("%s\n", buf);
-    if (base) {
-        /* Test in-buffer replacement */
-        snprintf(buf2, sizeof(buf2), "%s", base);
-        ff_make_absolute_url(buf2, sizeof(buf2), buf2, rel);
-        if (strcmp(buf, buf2)) {
-            printf("In-place handling of %s + %s failed\n", base, rel);
-            exit(1);
-        }
-    }
-}
-
-int main(void)
-{
-    test(NULL, "baz");
-    test("/foo/bar", "baz");
-    test("/foo/bar", "../baz");
-    test("/foo/bar", "/baz");
-    test("http://server/foo/", "baz");
-    test("http://server/foo/bar", "baz");
-    test("http://server/foo/", "../baz");
-    test("http://server/foo/bar/123", "../../baz");
-    test("http://server/foo/bar/123", "/baz");
-    test("http://server/foo/bar/123", "https://other/url");
-    test("http://server/foo/bar?param=value/with/slashes", "/baz");
-    test("http://server/foo/bar?param&otherparam", "?someparam");
-    test("http://server/foo/bar", "//other/url");
-    return 0;
-}
diff --git a/libavformat/url.h b/libavformat/url.h
index 0b4f2ee..5c50245 100644
--- a/libavformat/url.h
+++ b/libavformat/url.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -38,7 +37,7 @@ extern const AVClass ffurl_context_class;
 
 typedef struct URLContext {
     const AVClass *av_class;    /**< information for av_log(). Set by url_open(). */
-    struct URLProtocol *prot;
+    const struct URLProtocol *prot;
     void *priv_data;
     char *filename;             /**< specified URL */
     int flags;
@@ -48,6 +47,7 @@ typedef struct URLContext {
     AVIOInterruptCB interrupt_callback;
     int64_t rw_timeout;         /**< maximum time to wait for (network) read/write operation completion, in mcs */
     const char *protocol_whitelist;
+    const char *protocol_blacklist;
 } URLContext;
 
 typedef struct URLProtocol {
@@ -78,7 +78,6 @@ typedef struct URLProtocol {
     int     (*url_write)(URLContext *h, const unsigned char *buf, int size);
     int64_t (*url_seek)( URLContext *h, int64_t pos, int whence);
     int     (*url_close)(URLContext *h);
-    struct URLProtocol *next;
     int (*url_read_pause)(URLContext *h, int pause);
     int64_t (*url_read_seek)(URLContext *h, int stream_index,
                              int64_t timestamp, int flags);
@@ -137,12 +136,15 @@ int ffurl_connect(URLContext *uc, AVDictionary **options);
  * @param options  A dictionary filled with protocol-private options. On return
  * this parameter will be destroyed and replaced with a dict containing options
  * that were not found. May be NULL.
+ * @param parent An enclosing URLContext, whose generic options should
+ *               be applied to this URLContext as well.
  * @return >= 0 in case of success, a negative value corresponding to an
  * AVERROR code in case of failure
  */
 int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
                const AVIOInterruptCB *int_cb, AVDictionary **options,
-               const char *whitelist);
+               const char *whitelist, const char* blacklist,
+               URLContext *parent);
 
 int ffurl_open(URLContext **puc, const char *filename, int flags,
                const AVIOInterruptCB *int_cb, AVDictionary **options);
@@ -259,23 +261,11 @@ int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles);
 int ffurl_shutdown(URLContext *h, int flags);
 
 /**
- * Register the URLProtocol protocol.
- */
-int ffurl_register_protocol(URLProtocol *protocol);
-
-/**
- * Check if the user has requested to interrup a blocking function
+ * Check if the user has requested to interrupt a blocking function
  * associated with cb.
  */
 int ff_check_interrupt(AVIOInterruptCB *cb);
 
-/**
- * Iterate over all available protocols.
- *
- * @param prev result of the previous call to this functions or NULL.
- */
-URLProtocol *ffurl_protocol_next(const URLProtocol *prev);
-
 /* udp.c */
 int ff_udp_set_remote_url(URLContext *h, const char *uri);
 int ff_udp_get_local_port(URLContext *h);
@@ -323,5 +313,22 @@ void ff_make_absolute_url(char *buf, int size, const char *base,
  */
 AVIODirEntry *ff_alloc_dir_entry(void);
 
+const AVClass *ff_urlcontext_child_class_next(const AVClass *prev);
+
+/**
+ * Construct a list of protocols matching a given whitelist and/or blacklist.
+ *
+ * @param whitelist a comma-separated list of allowed protocol names or NULL. If
+ *                  this is a non-empty string, only protocols in this list will
+ *                  be included.
+ * @param blacklist a comma-separated list of forbidden protocol names or NULL.
+ *                  If this is a non-empty string, all protocols in this list
+ *                  will be excluded.
+ *
+ * @return a NULL-terminated array of matching protocols. The array must be
+ * freed by the caller.
+ */
+const URLProtocol **ffurl_get_protocols(const char *whitelist,
+                                        const char *blacklist);
 
 #endif /* AVFORMAT_URL_H */
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 3aa5beb..d2a709c 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -33,6 +33,7 @@
 #include "libavutil/parseutils.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/time.h"
+#include "libavutil/time_internal.h"
 #include "libavutil/timestamp.h"
 
 #include "libavcodec/bytestream.h"
@@ -141,18 +142,21 @@ void av_format_inject_global_side_data(AVFormatContext *s)
     }
 }
 
-int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src)
+int ff_copy_whiteblacklists(AVFormatContext *dst, AVFormatContext *src)
 {
     av_assert0(!dst->codec_whitelist &&
                !dst->format_whitelist &&
-               !dst->protocol_whitelist);
+               !dst->protocol_whitelist &&
+               !dst->protocol_blacklist);
     dst-> codec_whitelist = av_strdup(src->codec_whitelist);
     dst->format_whitelist = av_strdup(src->format_whitelist);
     dst->protocol_whitelist = av_strdup(src->protocol_whitelist);
+    dst->protocol_blacklist = av_strdup(src->protocol_blacklist);
     if (   (src-> codec_whitelist && !dst-> codec_whitelist)
         || (src->  format_whitelist && !dst->  format_whitelist)
-        || (src->protocol_whitelist && !dst->protocol_whitelist)) {
-        av_log(dst, AV_LOG_ERROR, "Failed to duplicate whitelist\n");
+        || (src->protocol_whitelist && !dst->protocol_whitelist)
+        || (src->protocol_blacklist && !dst->protocol_blacklist)) {
+        av_log(dst, AV_LOG_ERROR, "Failed to duplicate black/whitelist\n");
         return AVERROR(ENOMEM);
     }
     return 0;
@@ -160,10 +164,14 @@ int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src)
 
 static const AVCodec *find_decoder(AVFormatContext *s, AVStream *st, enum AVCodecID codec_id)
 {
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
     if (st->codec->codec)
         return st->codec->codec;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
-    switch (st->codec->codec_type) {
+    switch (st->codecpar->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
         if (s->video_codec)    return s->video_codec;
         break;
@@ -285,6 +293,7 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st,
         { "ac3",       AV_CODEC_ID_AC3,        AVMEDIA_TYPE_AUDIO },
         { "dts",       AV_CODEC_ID_DTS,        AVMEDIA_TYPE_AUDIO },
         { "dvbsub",    AV_CODEC_ID_DVB_SUBTITLE,AVMEDIA_TYPE_SUBTITLE },
+        { "dvbtxt",    AV_CODEC_ID_DVB_TELETEXT,AVMEDIA_TYPE_SUBTITLE },
         { "eac3",      AV_CODEC_ID_EAC3,       AVMEDIA_TYPE_AUDIO },
         { "h264",      AV_CODEC_ID_H264,       AVMEDIA_TYPE_VIDEO },
         { "hevc",      AV_CODEC_ID_HEVC,       AVMEDIA_TYPE_VIDEO },
@@ -292,6 +301,7 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st,
         { "m4v",       AV_CODEC_ID_MPEG4,      AVMEDIA_TYPE_VIDEO },
         { "mp3",       AV_CODEC_ID_MP3,        AVMEDIA_TYPE_AUDIO },
         { "mpegvideo", AV_CODEC_ID_MPEG2VIDEO, AVMEDIA_TYPE_VIDEO },
+        { "truehd",    AV_CODEC_ID_TRUEHD,     AVMEDIA_TYPE_AUDIO },
         { 0 }
     };
     int score;
@@ -305,8 +315,18 @@ static int set_codec_from_probe_data(AVFormatContext *s, AVStream *st,
                fmt->name, score);
         for (i = 0; fmt_id_type[i].name; i++) {
             if (!strcmp(fmt->name, fmt_id_type[i].name)) {
-                st->codec->codec_id   = fmt_id_type[i].id;
-                st->codec->codec_type = fmt_id_type[i].type;
+                if (fmt_id_type[i].type != AVMEDIA_TYPE_AUDIO &&
+                    st->codecpar->sample_rate)
+                    continue;
+                st->codecpar->codec_id   = fmt_id_type[i].id;
+                st->codecpar->codec_type = fmt_id_type[i].type;
+                st->internal->need_context_update = 1;
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+                st->codec->codec_type = st->codecpar->codec_type;
+                st->codec->codec_id   = st->codecpar->codec_id;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
                 return score;
             }
         }
@@ -419,11 +439,40 @@ int avformat_queue_attached_pictures(AVFormatContext *s)
     return 0;
 }
 
+static int update_stream_avctx(AVFormatContext *s)
+{
+    int i, ret;
+    for (i = 0; i < s->nb_streams; i++) {
+        AVStream *st = s->streams[i];
+
+        if (!st->internal->need_context_update)
+            continue;
+
+        /* update internal codec context, for the parser */
+        ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
+        if (ret < 0)
+            return ret;
+
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+        /* update deprecated public codec context */
+        ret = avcodec_parameters_to_context(st->codec, st->codecpar);
+        if (ret < 0)
+            return ret;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+        st->internal->need_context_update = 0;
+    }
+    return 0;
+}
+
+
 int avformat_open_input(AVFormatContext **ps, const char *filename,
                         AVInputFormat *fmt, AVDictionary **options)
 {
     AVFormatContext *s = *ps;
-    int ret = 0;
+    int i, ret = 0;
     AVDictionary *tmp = NULL;
     ID3v2ExtraMeta *id3v2_extra_meta = NULL;
 
@@ -457,6 +506,14 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
         }
     }
 
+    if (!s->protocol_blacklist && s->pb && s->pb->protocol_blacklist) {
+        s->protocol_blacklist = av_strdup(s->pb->protocol_blacklist);
+        if (!s->protocol_blacklist) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+
     if (s->format_whitelist && av_match_list(s->iformat->name, s->format_whitelist, ',') <= 0) {
         av_log(s, AV_LOG_ERROR, "Format not on whitelist \'%s\'\n", s->format_whitelist);
         ret = AVERROR(EINVAL);
@@ -516,6 +573,11 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
 
     s->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
 
+    update_stream_avctx(s);
+
+    for (i = 0; i < s->nb_streams; i++)
+        s->streams[i]->internal->orig_codec_id = s->streams[i]->codecpar->codec_id;
+
     if (options) {
         av_dict_free(options);
         *options = tmp;
@@ -537,18 +599,18 @@ fail:
 
 static void force_codec_ids(AVFormatContext *s, AVStream *st)
 {
-    switch (st->codec->codec_type) {
+    switch (st->codecpar->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
         if (s->video_codec_id)
-            st->codec->codec_id = s->video_codec_id;
+            st->codecpar->codec_id = s->video_codec_id;
         break;
     case AVMEDIA_TYPE_AUDIO:
         if (s->audio_codec_id)
-            st->codec->codec_id = s->audio_codec_id;
+            st->codecpar->codec_id = s->audio_codec_id;
         break;
     case AVMEDIA_TYPE_SUBTITLE:
         if (s->subtitle_codec_id)
-            st->codec->codec_id = s->subtitle_codec_id;
+            st->codecpar->codec_id = s->subtitle_codec_id;
         break;
     }
 }
@@ -587,12 +649,12 @@ no_packet:
 
         if (end || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) {
             int score = set_codec_from_probe_data(s, st, pd);
-            if (    (st->codec->codec_id != AV_CODEC_ID_NONE && score > AVPROBE_SCORE_STREAM_RETRY)
+            if (    (st->codecpar->codec_id != AV_CODEC_ID_NONE && score > AVPROBE_SCORE_STREAM_RETRY)
                 || end) {
                 pd->buf_size = 0;
                 av_freep(&pd->buf);
                 st->request_probe = -1;
-                if (st->codec->codec_id != AV_CODEC_ID_NONE) {
+                if (st->codecpar->codec_id != AV_CODEC_ID_NONE) {
                     av_log(s, AV_LOG_DEBUG, "probed stream %d\n", st->index);
                 } else
                     av_log(s, AV_LOG_WARNING, "probed stream %d failed\n", st->index);
@@ -790,13 +852,20 @@ static int determinable_frame_size(AVCodecContext *avctx)
 void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStream *st,
                                AVCodecParserContext *pc, AVPacket *pkt)
 {
-    AVRational codec_framerate = s->iformat ? st->codec->framerate :
-                                              av_mul_q(av_inv_q(st->codec->time_base), (AVRational){1, st->codec->ticks_per_frame});
-    int frame_size;
+    AVRational codec_framerate = s->iformat ? st->internal->avctx->framerate :
+                                              av_mul_q(av_inv_q(st->internal->avctx->time_base), (AVRational){1, st->internal->avctx->ticks_per_frame});
+    int frame_size, sample_rate;
+
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+    if ((!codec_framerate.den || !codec_framerate.num) && st->codec->time_base.den && st->codec->time_base.num)
+        codec_framerate = av_mul_q(av_inv_q(st->codec->time_base), (AVRational){1, st->codec->ticks_per_frame});
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     *pnum = 0;
     *pden = 0;
-    switch (st->codec->codec_type) {
+    switch (st->codecpar->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
         if (st->r_frame_rate.num && !pc && s->iformat) {
             *pnum = st->r_frame_rate.den;
@@ -805,10 +874,10 @@ void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStrea
             *pnum = st->time_base.num;
             *pden = st->time_base.den;
         } else if (codec_framerate.den * 1000LL > codec_framerate.num) {
-            av_assert0(st->codec->ticks_per_frame);
+            av_assert0(st->internal->avctx->ticks_per_frame);
             av_reduce(pnum, pden,
                       codec_framerate.den,
-                      codec_framerate.num * (int64_t)st->codec->ticks_per_frame,
+                      codec_framerate.num * (int64_t)st->internal->avctx->ticks_per_frame,
                       INT_MAX);
 
             if (pc && pc->repeat_pict) {
@@ -821,51 +890,51 @@ void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStrea
             /* If this codec can be interlaced or progressive then we need
              * a parser to compute duration of a packet. Thus if we have
              * no parser in such case leave duration undefined. */
-            if (st->codec->ticks_per_frame > 1 && !pc)
+            if (st->internal->avctx->ticks_per_frame > 1 && !pc)
                 *pnum = *pden = 0;
         }
         break;
     case AVMEDIA_TYPE_AUDIO:
-        frame_size = av_get_audio_frame_duration(st->codec, pkt->size);
-        if (frame_size <= 0 || st->codec->sample_rate <= 0)
+        if (st->internal->avctx_inited) {
+            frame_size = av_get_audio_frame_duration(st->internal->avctx, pkt->size);
+            sample_rate = st->internal->avctx->sample_rate;
+        } else {
+            frame_size = av_get_audio_frame_duration2(st->codecpar, pkt->size);
+            sample_rate = st->codecpar->sample_rate;
+        }
+        if (frame_size <= 0 || sample_rate <= 0)
             break;
         *pnum = frame_size;
-        *pden = st->codec->sample_rate;
+        *pden = sample_rate;
         break;
     default:
         break;
     }
 }
 
-static int is_intra_only(AVCodecContext *enc) {
-    const AVCodecDescriptor *desc;
-
-    if (enc->codec_type != AVMEDIA_TYPE_VIDEO)
-        return 1;
-
-    desc = av_codec_get_codec_descriptor(enc);
-    if (!desc) {
-        desc = avcodec_descriptor_get(enc->codec_id);
-        av_codec_set_codec_descriptor(enc, desc);
-    }
-    if (desc)
-        return !!(desc->props & AV_CODEC_PROP_INTRA_ONLY);
-    return 0;
+static int is_intra_only(enum AVCodecID id)
+{
+    const AVCodecDescriptor *d = avcodec_descriptor_get(id);
+    if (!d)
+        return 0;
+    if (d->type == AVMEDIA_TYPE_VIDEO && !(d->props & AV_CODEC_PROP_INTRA_ONLY))
+        return 0;
+    return 1;
 }
 
 static int has_decode_delay_been_guessed(AVStream *st)
 {
-    if (st->codec->codec_id != AV_CODEC_ID_H264) return 1;
+    if (st->codecpar->codec_id != AV_CODEC_ID_H264) return 1;
     if (!st->info) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy
         return 1;
 #if CONFIG_H264_DECODER
-    if (st->codec->has_b_frames &&
-       avpriv_h264_has_num_reorder_frames(st->codec) == st->codec->has_b_frames)
+    if (st->internal->avctx->has_b_frames &&
+       avpriv_h264_has_num_reorder_frames(st->internal->avctx) == st->internal->avctx->has_b_frames)
         return 1;
 #endif
-    if (st->codec->has_b_frames<3)
+    if (st->internal->avctx->has_b_frames<3)
         return st->nb_decoded_frames >= 7;
-    else if (st->codec->has_b_frames<4)
+    else if (st->internal->avctx->has_b_frames<4)
         return st->nb_decoded_frames >= 18;
     else
         return st->nb_decoded_frames >= 20;
@@ -881,11 +950,11 @@ static AVPacketList *get_next_pkt(AVFormatContext *s, AVStream *st, AVPacketList
 }
 
 static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t dts) {
-    int onein_oneout = st->codec->codec_id != AV_CODEC_ID_H264 &&
-                       st->codec->codec_id != AV_CODEC_ID_HEVC;
+    int onein_oneout = st->codecpar->codec_id != AV_CODEC_ID_H264 &&
+                       st->codecpar->codec_id != AV_CODEC_ID_HEVC;
 
     if(!onein_oneout) {
-        int delay = st->codec->has_b_frames;
+        int delay = st->internal->avctx->has_b_frames;
         int i;
 
         if (dts == AV_NOPTS_VALUE) {
@@ -922,14 +991,44 @@ static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t
     return dts;
 }
 
+/**
+ * Updates the dts of packets of a stream in pkt_buffer, by re-ordering the pts
+ * of the packets in a window.
+ */
+static void update_dts_from_pts(AVFormatContext *s, int stream_index,
+                                AVPacketList *pkt_buffer)
+{
+    AVStream *st       = s->streams[stream_index];
+    int delay          = st->internal->avctx->has_b_frames;
+    int i;
+
+    int64_t pts_buffer[MAX_REORDER_DELAY+1];
+
+    for (i = 0; i<MAX_REORDER_DELAY+1; i++)
+        pts_buffer[i] = AV_NOPTS_VALUE;
+
+    for (; pkt_buffer; pkt_buffer = get_next_pkt(s, st, pkt_buffer)) {
+        if (pkt_buffer->pkt.stream_index != stream_index)
+            continue;
+
+        if (pkt_buffer->pkt.pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY) {
+            pts_buffer[0] = pkt_buffer->pkt.pts;
+            for (i = 0; i<delay && pts_buffer[i] > pts_buffer[i + 1]; i++)
+                FFSWAP(int64_t, pts_buffer[i], pts_buffer[i + 1]);
+
+            pkt_buffer->pkt.dts = select_from_pts_buffer(st, pts_buffer, pkt_buffer->pkt.dts);
+        }
+    }
+}
+
 static void update_initial_timestamps(AVFormatContext *s, int stream_index,
                                       int64_t dts, int64_t pts, AVPacket *pkt)
 {
     AVStream *st       = s->streams[stream_index];
     AVPacketList *pktl = s->internal->packet_buffer ? s->internal->packet_buffer : s->internal->parse_queue;
-    int64_t pts_buffer[MAX_REORDER_DELAY+1];
+    AVPacketList *pktl_it;
+
     uint64_t shift;
-    int i, delay;
 
     if (st->first_dts != AV_NOPTS_VALUE ||
         dts           == AV_NOPTS_VALUE ||
@@ -937,40 +1036,38 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index,
         is_relative(dts))
         return;
 
-    delay         = st->codec->has_b_frames;
     st->first_dts = dts - (st->cur_dts - RELATIVE_TS_BASE);
     st->cur_dts   = dts;
     shift         = (uint64_t)st->first_dts - RELATIVE_TS_BASE;
 
-    for (i = 0; i<MAX_REORDER_DELAY+1; i++)
-        pts_buffer[i] = AV_NOPTS_VALUE;
-
     if (is_relative(pts))
         pts += shift;
 
-    for (; pktl; pktl = get_next_pkt(s, st, pktl)) {
-        if (pktl->pkt.stream_index != stream_index)
+    for (pktl_it = pktl; pktl_it; pktl_it = get_next_pkt(s, st, pktl_it)) {
+        if (pktl_it->pkt.stream_index != stream_index)
             continue;
-        if (is_relative(pktl->pkt.pts))
-            pktl->pkt.pts += shift;
-
-        if (is_relative(pktl->pkt.dts))
-            pktl->pkt.dts += shift;
+        if (is_relative(pktl_it->pkt.pts))
+            pktl_it->pkt.pts += shift;
 
-        if (st->start_time == AV_NOPTS_VALUE && pktl->pkt.pts != AV_NOPTS_VALUE)
-            st->start_time = pktl->pkt.pts;
+        if (is_relative(pktl_it->pkt.dts))
+            pktl_it->pkt.dts += shift;
 
-        if (pktl->pkt.pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY && has_decode_delay_been_guessed(st)) {
-            pts_buffer[0] = pktl->pkt.pts;
-            for (i = 0; i<delay && pts_buffer[i] > pts_buffer[i + 1]; i++)
-                FFSWAP(int64_t, pts_buffer[i], pts_buffer[i + 1]);
-
-            pktl->pkt.dts = select_from_pts_buffer(st, pts_buffer, pktl->pkt.dts);
+        if (st->start_time == AV_NOPTS_VALUE && pktl_it->pkt.pts != AV_NOPTS_VALUE) {
+            st->start_time = pktl_it->pkt.pts;
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate)
+                st->start_time += av_rescale_q(st->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base);
         }
     }
 
-    if (st->start_time == AV_NOPTS_VALUE)
+    if (has_decode_delay_been_guessed(st)) {
+        update_dts_from_pts(s, stream_index, pktl);
+    }
+
+    if (st->start_time == AV_NOPTS_VALUE) {
         st->start_time = pts;
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate)
+            st->start_time += av_rescale_q(st->skip_samples, (AVRational){1, st->codecpar->sample_rate}, st->time_base);
+    }
 }
 
 static void update_initial_durations(AVFormatContext *s, AVStream *st,
@@ -1014,9 +1111,9 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st,
             (pktl->pkt.dts == AV_NOPTS_VALUE || pktl->pkt.dts == st->first_dts) &&
             !pktl->pkt.duration) {
             pktl->pkt.dts = cur_dts;
-            if (!st->codec->has_b_frames)
+            if (!st->internal->avctx->has_b_frames)
                 pktl->pkt.pts = cur_dts;
-//            if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+//            if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
                 pktl->pkt.duration = duration;
         } else
             break;
@@ -1033,13 +1130,13 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
     int num, den, presentation_delayed, delay, i;
     int64_t offset;
     AVRational duration;
-    int onein_oneout = st->codec->codec_id != AV_CODEC_ID_H264 &&
-                       st->codec->codec_id != AV_CODEC_ID_HEVC;
+    int onein_oneout = st->codecpar->codec_id != AV_CODEC_ID_H264 &&
+                       st->codecpar->codec_id != AV_CODEC_ID_HEVC;
 
     if (s->flags & AVFMT_FLAG_NOFILLIN)
         return;
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && pkt->dts != AV_NOPTS_VALUE) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && pkt->dts != AV_NOPTS_VALUE) {
         if (pkt->dts == pkt->pts && st->last_dts_for_order_check != AV_NOPTS_VALUE) {
             if (st->last_dts_for_order_check <= pkt->dts) {
                 st->dts_ordered++;
@@ -1065,12 +1162,12 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
         pkt->dts = AV_NOPTS_VALUE;
 
     if (pc && pc->pict_type == AV_PICTURE_TYPE_B
-        && !st->codec->has_b_frames)
+        && !st->internal->avctx->has_b_frames)
         //FIXME Set low_delay = 0 when has_b_frames = 1
-        st->codec->has_b_frames = 1;
+        st->internal->avctx->has_b_frames = 1;
 
     /* do we have a video B-frame ? */
-    delay = st->codec->has_b_frames;
+    delay = st->internal->avctx->has_b_frames;
     presentation_delayed = 0;
 
     /* XXX: need has_b_frame, but cannot get it if the codec is
@@ -1206,7 +1303,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
             presentation_delayed, delay, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts));
 
     /* update flags */
-    if (is_intra_only(st->codec))
+    if (is_intra_only(st->codecpar->codec_id))
         pkt->flags |= AV_PKT_FLAG_KEY;
 #if FF_API_CONVERGENCE_DURATION
 FF_DISABLE_DEPRECATION_WARNINGS
@@ -1255,7 +1352,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
         int64_t next_dts = pkt->dts;
 
         av_init_packet(&out_pkt);
-        len = av_parser_parse2(st->parser, st->codec,
+        len = av_parser_parse2(st->parser, st->internal->avctx,
                                &out_pkt.data, &out_pkt.size, data, size,
                                pkt->pts, pkt->dts, pkt->pos);
 
@@ -1279,11 +1376,11 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
 
         /* set the duration */
         out_pkt.duration = (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES) ? pkt->duration : 0;
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            if (st->codec->sample_rate > 0) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (st->internal->avctx->sample_rate > 0) {
                 out_pkt.duration =
                     av_rescale_q_rnd(st->parser->duration,
-                                     (AVRational) { 1, st->codec->sample_rate },
+                                     (AVRational) { 1, st->internal->avctx->sample_rate },
                                      st->time_base,
                                      AV_ROUND_DOWN);
             }
@@ -1342,7 +1439,7 @@ static int read_from_packet_buffer(AVPacketList **pkt_buffer,
 
 static int64_t ts_to_samples(AVStream *st, int64_t ts)
 {
-    return av_rescale(ts, st->time_base.num * st->codec->sample_rate, st->time_base.den);
+    return av_rescale(ts, st->time_base.num * st->codecpar->sample_rate, st->time_base.den);
 }
 
 static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
@@ -1374,6 +1471,30 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
         ret = 0;
         st  = s->streams[cur_pkt.stream_index];
 
+        /* update context if required */
+        if (st->internal->need_context_update) {
+            if (avcodec_is_open(st->internal->avctx)) {
+                av_log(s, AV_LOG_DEBUG, "Demuxer context update while decoder is open, closing and trying to re-open\n");
+                avcodec_close(st->internal->avctx);
+                st->info->found_decoder = 0;
+            }
+
+            ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
+            if (ret < 0)
+                return ret;
+
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+            /* update deprecated public codec context */
+            ret = avcodec_parameters_to_context(st->codec, st->codecpar);
+            if (ret < 0)
+                return ret;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+            st->internal->need_context_update = 0;
+        }
+
         if (cur_pkt.pts != AV_NOPTS_VALUE &&
             cur_pkt.dts != AV_NOPTS_VALUE &&
             cur_pkt.pts < cur_pkt.dts) {
@@ -1393,11 +1514,11 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
                    cur_pkt.size, cur_pkt.duration, cur_pkt.flags);
 
         if (st->need_parsing && !st->parser && !(s->flags & AVFMT_FLAG_NOPARSE)) {
-            st->parser = av_parser_init(st->codec->codec_id);
+            st->parser = av_parser_init(st->codecpar->codec_id);
             if (!st->parser) {
                 av_log(s, AV_LOG_VERBOSE, "parser not found for codec "
                        "%s, packets or times may be invalid.\n",
-                       avcodec_get_name(st->codec->codec_id));
+                       avcodec_get_name(st->codecpar->codec_id));
                 /* no parser available: just output the raw packets */
                 st->need_parsing = AVSTREAM_PARSE_NONE;
             } else if (st->need_parsing == AVSTREAM_PARSE_HEADERS)
@@ -1422,6 +1543,11 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
         } else if (st->discard < AVDISCARD_ALL) {
             if ((ret = parse_packet(s, &cur_pkt, cur_pkt.stream_index)) < 0)
                 return ret;
+            st->codecpar->sample_rate = st->internal->avctx->sample_rate;
+            st->codecpar->bit_rate = st->internal->avctx->bit_rate;
+            st->codecpar->channels = st->internal->avctx->channels;
+            st->codecpar->channel_layout = st->internal->avctx->channel_layout;
+            st->codecpar->codec_id = st->internal->avctx->codec_id;
         } else {
             /* free packet */
             av_packet_unref(&cur_pkt);
@@ -1495,6 +1621,10 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
         av_opt_set_dict_val(s, "metadata", NULL, AV_OPT_SEARCH_CHILDREN);
     }
 
+#if FF_API_LAVF_AVCTX
+    update_stream_avctx(s);
+#endif
+
     if (s->debug & FF_FDEBUG_TS)
         av_log(s, AV_LOG_DEBUG,
                "read_frame_internal stream=%d, pts=%s, dts=%s, "
@@ -1629,15 +1759,15 @@ int av_find_default_stream_index(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++) {
         int score = 0;
         st = s->streams[i];
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
             if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
                 score -= 400;
-            if (st->codec->width && st->codec->height)
+            if (st->codecpar->width && st->codecpar->height)
                 score += 50;
             score+= 25;
         }
-        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            if (st->codec->sample_rate)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (st->codecpar->sample_rate)
                 score += 50;
         }
         if (st->codec_info_nb_frames)
@@ -2164,7 +2294,7 @@ static int seek_frame_generic(AVFormatContext *s, int stream_index,
                     av_packet_unref(&pkt);
                     break;
                 }
-                if (nonkey++ > 1000 && st->codec->codec_id != AV_CODEC_ID_CDGRAPHICS) {
+                if (nonkey++ > 1000 && st->codecpar->codec_id != AV_CODEC_ID_CDGRAPHICS) {
                     av_log(s, AV_LOG_ERROR,"seek_frame_generic failed as this stream seems to contain no keyframes after the target timestamp, %d non keyframes found\n", nonkey);
                     av_packet_unref(&pkt);
                     break;
@@ -2362,7 +2492,7 @@ static void update_stream_timings(AVFormatContext *ic)
         if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) {
             start_time1 = av_rescale_q(st->start_time, st->time_base,
                                        AV_TIME_BASE_Q);
-            if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE || st->codec->codec_type == AVMEDIA_TYPE_DATA) {
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE || st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
                 if (start_time1 < start_time_text)
                     start_time_text = start_time1;
             } else
@@ -2370,7 +2500,7 @@ static void update_stream_timings(AVFormatContext *ic)
             end_time1 = av_rescale_q_rnd(st->duration, st->time_base,
                                          AV_TIME_BASE_Q,
                                          AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
-            if (end_time1 != AV_NOPTS_VALUE) {
+            if (end_time1 != AV_NOPTS_VALUE && start_time1 <= INT64_MAX - end_time1) {
                 end_time1 += start_time1;
                 end_time = FFMAX(end_time, end_time1);
             }
@@ -2408,7 +2538,7 @@ static void update_stream_timings(AVFormatContext *ic)
     if (duration != INT64_MIN && duration > 0 && ic->duration == AV_NOPTS_VALUE) {
         ic->duration = duration;
     }
-    if (ic->pb && (filesize = avio_size(ic->pb)) > 0 && ic->duration != AV_NOPTS_VALUE) {
+    if (ic->pb && (filesize = avio_size(ic->pb)) > 0 && ic->duration > 0) {
         /* compute the bitrate */
         double bitrate = (double) filesize * 8.0 * AV_TIME_BASE /
                          (double) ic->duration;
@@ -2444,16 +2574,18 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
 
     /* if bit_rate is already set, we believe it */
     if (ic->bit_rate <= 0) {
-        int bit_rate = 0;
+        int64_t bit_rate = 0;
         for (i = 0; i < ic->nb_streams; i++) {
             st = ic->streams[i];
-            if (st->codec->bit_rate > 0) {
-                if (INT_MAX - st->codec->bit_rate < bit_rate) {
+            if (st->codecpar->bit_rate <= 0 && st->internal->avctx->bit_rate > 0)
+                st->codecpar->bit_rate = st->internal->avctx->bit_rate;
+            if (st->codecpar->bit_rate > 0) {
+                if (INT64_MAX - st->codecpar->bit_rate < bit_rate) {
                     bit_rate = 0;
                     break;
                 }
-                bit_rate += st->codec->bit_rate;
-            } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && st->codec_info_nb_frames > 1) {
+                bit_rate += st->codecpar->bit_rate;
+            } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->codec_info_nb_frames > 1) {
                 // If we have a videostream with packets but without a bitrate
                 // then consider the sum not known
                 bit_rate = 0;
@@ -2508,8 +2640,8 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
         st = ic->streams[i];
         if (st->start_time == AV_NOPTS_VALUE &&
             st->first_dts == AV_NOPTS_VALUE &&
-            st->codec->codec_type != AVMEDIA_TYPE_UNKNOWN)
-            av_log(st->codec, AV_LOG_WARNING,
+            st->codecpar->codec_type != AVMEDIA_TYPE_UNKNOWN)
+            av_log(ic, AV_LOG_WARNING,
                    "start time for stream %d is not set in estimate_timings_from_pts\n", i);
 
         if (st->parser) {
@@ -2574,7 +2706,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
             is_end = 1;
             for (i = 0; i < ic->nb_streams; i++) {
                 st = ic->streams[i];
-                switch (st->codec->codec_type) {
+                switch (st->codecpar->codec_type) {
                     case AVMEDIA_TYPE_VIDEO:
                     case AVMEDIA_TYPE_AUDIO:
                         if (st->duration == AV_NOPTS_VALUE)
@@ -2592,7 +2724,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
     for (i = 0; i < ic->nb_streams; i++) {
         st = ic->streams[i];
         if (st->duration == AV_NOPTS_VALUE) {
-            switch (st->codec->codec_type) {
+            switch (st->codecpar->codec_type) {
             case AVMEDIA_TYPE_VIDEO:
             case AVMEDIA_TYPE_AUDIO:
                 if (st->start_time != AV_NOPTS_VALUE || st->first_dts  != AV_NOPTS_VALUE) {
@@ -2652,12 +2784,12 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
         AVStream av_unused *st;
         for (i = 0; i < ic->nb_streams; i++) {
             st = ic->streams[i];
-            av_log(ic, AV_LOG_TRACE, "%d: start_time: %0.3f duration: %0.3f\n", i,
-                    (double) st->start_time / AV_TIME_BASE,
-                    (double) st->duration   / AV_TIME_BASE);
+            av_log(ic, AV_LOG_TRACE, "stream %d: start_time: %0.3f duration: %0.3f\n", i,
+                   (double) st->start_time * av_q2d(st->time_base),
+                   (double) st->duration   * av_q2d(st->time_base));
         }
         av_log(ic, AV_LOG_TRACE,
-                "stream: start_time: %0.3f duration: %0.3f bitrate=%"PRId64" kb/s\n",
+                "format: start_time: %0.3f duration: %0.3f bitrate=%"PRId64" kb/s\n",
                 (double) ic->start_time / AV_TIME_BASE,
                 (double) ic->duration   / AV_TIME_BASE,
                 (int64_t)ic->bit_rate / 1000);
@@ -2666,7 +2798,7 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
 
 static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
 {
-    AVCodecContext *avctx = st->codec;
+    AVCodecContext *avctx = st->internal->avctx;
 
 #define FAIL(errmsg) do {                                         \
         if (errmsg_ptr)                                           \
@@ -2696,8 +2828,8 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
             FAIL("unspecified size");
         if (st->info->found_decoder >= 0 && avctx->pix_fmt == AV_PIX_FMT_NONE)
             FAIL("unspecified pixel format");
-        if (st->codec->codec_id == AV_CODEC_ID_RV30 || st->codec->codec_id == AV_CODEC_ID_RV40)
-            if (!st->sample_aspect_ratio.num && !st->codec->sample_aspect_ratio.num && !st->codec_info_nb_frames)
+        if (st->codecpar->codec_id == AV_CODEC_ID_RV30 || st->codecpar->codec_id == AV_CODEC_ID_RV40)
+            if (!st->sample_aspect_ratio.num && !st->codecpar->sample_aspect_ratio.num && !st->codec_info_nb_frames)
                 FAIL("no frame in rv30/40 and no sar");
         break;
     case AVMEDIA_TYPE_SUBTITLE:
@@ -2715,6 +2847,7 @@ static int has_codec_parameters(AVStream *st, const char **errmsg_ptr)
 static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,
                             AVDictionary **options)
 {
+    AVCodecContext *avctx = st->internal->avctx;
     const AVCodec *codec;
     int got_picture = 1, ret = 0;
     AVFrame *frame = av_frame_alloc();
@@ -2726,15 +2859,15 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,
     if (!frame)
         return AVERROR(ENOMEM);
 
-    if (!avcodec_is_open(st->codec) &&
+    if (!avcodec_is_open(avctx) &&
         st->info->found_decoder <= 0 &&
-        (st->codec->codec_id != -st->info->found_decoder || !st->codec->codec_id)) {
+        (st->codecpar->codec_id != -st->info->found_decoder || !st->codecpar->codec_id)) {
         AVDictionary *thread_opt = NULL;
 
-        codec = find_decoder(s, st, st->codec->codec_id);
+        codec = find_decoder(s, st, st->codecpar->codec_id);
 
         if (!codec) {
-            st->info->found_decoder = -st->codec->codec_id;
+            st->info->found_decoder = -st->codecpar->codec_id;
             ret                     = -1;
             goto fail;
         }
@@ -2744,11 +2877,11 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,
         av_dict_set(options ? options : &thread_opt, "threads", "1", 0);
         if (s->codec_whitelist)
             av_dict_set(options ? options : &thread_opt, "codec_whitelist", s->codec_whitelist, 0);
-        ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt);
+        ret = avcodec_open2(avctx, codec, options ? options : &thread_opt);
         if (!options)
             av_dict_free(&thread_opt);
         if (ret < 0) {
-            st->info->found_decoder = -st->codec->codec_id;
+            st->info->found_decoder = -avctx->codec_id;
             goto fail;
         }
         st->info->found_decoder = 1;
@@ -2760,39 +2893,39 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,
         goto fail;
     }
 
-    if (st->codec->codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM) {
+    if (avpriv_codec_get_cap_skip_frame_fill_param(avctx->codec)) {
         do_skip_frame = 1;
-        skip_frame = st->codec->skip_frame;
-        st->codec->skip_frame = AVDISCARD_ALL;
+        skip_frame = avctx->skip_frame;
+        avctx->skip_frame = AVDISCARD_ALL;
     }
 
     while ((pkt.size > 0 || (!pkt.data && got_picture)) &&
            ret >= 0 &&
            (!has_codec_parameters(st, NULL) || !has_decode_delay_been_guessed(st) ||
             (!st->codec_info_nb_frames &&
-             (st->codec->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)))) {
+             (avctx->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)))) {
         got_picture = 0;
-        switch (st->codec->codec_type) {
-        case AVMEDIA_TYPE_VIDEO:
-            ret = avcodec_decode_video2(st->codec, frame,
-                                        &got_picture, &pkt);
-            break;
-        case AVMEDIA_TYPE_AUDIO:
-            ret = avcodec_decode_audio4(st->codec, frame, &got_picture, &pkt);
-            break;
-        case AVMEDIA_TYPE_SUBTITLE:
-            ret = avcodec_decode_subtitle2(st->codec, &subtitle,
+        if (avctx->codec_type == AVMEDIA_TYPE_VIDEO ||
+            avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
+            ret = avcodec_send_packet(avctx, &pkt);
+            if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
+                break;
+            if (ret >= 0)
+                pkt.size = 0;
+            ret = avcodec_receive_frame(avctx, frame);
+            if (ret >= 0)
+                got_picture = 1;
+            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+                ret = 0;
+        } else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+            ret = avcodec_decode_subtitle2(avctx, &subtitle,
                                            &got_picture, &pkt);
-            ret = pkt.size;
-            break;
-        default:
-            break;
+            if (ret >= 0)
+                pkt.size = 0;
         }
         if (ret >= 0) {
             if (got_picture)
                 st->nb_decoded_frames++;
-            pkt.data += ret;
-            pkt.size -= ret;
             ret       = got_picture;
         }
     }
@@ -2802,7 +2935,7 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, AVPacket *avpkt,
 
 fail:
     if (do_skip_frame) {
-        st->codec->skip_frame = skip_frame;
+        avctx->skip_frame = skip_frame;
     }
 
     av_frame_free(&frame);
@@ -2833,6 +2966,9 @@ enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag)
 
 enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags)
 {
+    if (bps <= 0 || bps > 64)
+        return AV_CODEC_ID_NONE;
+
     if (flt) {
         switch (bps) {
         case 32:
@@ -2916,7 +3052,7 @@ static void compute_chapters_end(AVFormatContext *s)
     unsigned int i, j;
     int64_t max_time = 0;
 
-    if (s->duration > 0)
+    if (s->duration > 0 && s->start_time < INT64_MAX - s->duration)
         max_time = s->duration +
                        ((s->start_time == AV_NOPTS_VALUE) ? 0 : s->start_time);
 
@@ -2977,37 +3113,37 @@ static int tb_unreliable(AVCodecContext *c)
     return 0;
 }
 
-int ff_alloc_extradata(AVCodecContext *avctx, int size)
+int ff_alloc_extradata(AVCodecParameters *par, int size)
 {
     int ret;
 
     if (size < 0 || size >= INT32_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
-        avctx->extradata = NULL;
-        avctx->extradata_size = 0;
+        par->extradata = NULL;
+        par->extradata_size = 0;
         return AVERROR(EINVAL);
     }
-    avctx->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
-    if (avctx->extradata) {
-        memset(avctx->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
-        avctx->extradata_size = size;
+    par->extradata = av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
+    if (par->extradata) {
+        memset(par->extradata + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+        par->extradata_size = size;
         ret = 0;
     } else {
-        avctx->extradata_size = 0;
+        par->extradata_size = 0;
         ret = AVERROR(ENOMEM);
     }
     return ret;
 }
 
-int ff_get_extradata(AVCodecContext *avctx, AVIOContext *pb, int size)
+int ff_get_extradata(AVFormatContext *s, AVCodecParameters *par, AVIOContext *pb, int size)
 {
-    int ret = ff_alloc_extradata(avctx, size);
+    int ret = ff_alloc_extradata(par, size);
     if (ret < 0)
         return ret;
-    ret = avio_read(pb, avctx->extradata, size);
+    ret = avio_read(pb, par->extradata, size);
     if (ret != size) {
-        av_freep(&avctx->extradata);
-        avctx->extradata_size = 0;
-        av_log(avctx, AV_LOG_ERROR, "Failed to read extradata of size %d\n", size);
+        av_freep(&par->extradata);
+        par->extradata_size = 0;
+        av_log(s, AV_LOG_ERROR, "Failed to read extradata of size %d\n", size);
         return ret < 0 ? ret : AVERROR_INVALIDDATA;
     }
 
@@ -3079,15 +3215,15 @@ void ff_rfps_calculate(AVFormatContext *ic)
     for (i = 0; i < ic->nb_streams; i++) {
         AVStream *st = ic->streams[i];
 
-        if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO)
+        if (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)
             continue;
         // the check for tb_unreliable() is not completely correct, since this is not about handling
-        // a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
+        // an unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
         // ipmovie.c produces.
-        if (tb_unreliable(st->codec) && st->info->duration_count > 15 && st->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num)
+        if (tb_unreliable(st->internal->avctx) && st->info->duration_count > 15 && st->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num)
             av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX);
         if (st->info->duration_count>1 && !st->r_frame_rate.num
-            && tb_unreliable(st->codec)) {
+            && tb_unreliable(st->internal->avctx)) {
             int num = 0;
             double best_error= 0.01;
             AVRational ref_rate = st->r_frame_rate.num ? st->r_frame_rate : av_inv_q(st->time_base);
@@ -3095,7 +3231,8 @@ void ff_rfps_calculate(AVFormatContext *ic)
             for (j= 0; j<MAX_STD_TIMEBASES; j++) {
                 int k;
 
-                if (st->info->codec_info_duration && st->info->codec_info_duration*av_q2d(st->time_base) < (1001*12.0)/get_std_framerate(j))
+                if (st->info->codec_info_duration &&
+                    st->info->codec_info_duration*av_q2d(st->time_base) < (1001*11.5)/get_std_framerate(j))
                     continue;
                 if (!st->info->codec_info_duration && get_std_framerate(j) < 1001*12)
                     continue;
@@ -3139,9 +3276,10 @@ void ff_rfps_calculate(AVFormatContext *ic)
 
 int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
 {
-    int i, count, ret = 0, j;
+    int i, count = 0, ret = 0, j;
     int64_t read_size;
     AVStream *st;
+    AVCodecContext *avctx;
     AVPacket pkt1, *pkt;
     int64_t old_offset  = avio_tell(ic->pb);
     // new streams might appear, no options for those
@@ -3151,6 +3289,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
     int64_t max_stream_analyze_duration;
     int64_t max_subtitle_analyze_duration;
     int64_t probesize = ic->probesize;
+    int eof_reached = 0;
 
     flush_codecs = probesize > 0;
 
@@ -3164,27 +3303,30 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
         max_subtitle_analyze_duration = 30*AV_TIME_BASE;
         if (!strcmp(ic->iformat->name, "flv"))
             max_stream_analyze_duration = 90*AV_TIME_BASE;
+        if (!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts"))
+            max_stream_analyze_duration = 7*AV_TIME_BASE;
     }
 
     if (ic->pb)
-        av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d\n",
-               avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count);
+        av_log(ic, AV_LOG_DEBUG, "Before avformat_find_stream_info() pos: %"PRId64" bytes read:%"PRId64" seeks:%d nb_streams:%d\n",
+               avio_tell(ic->pb), ic->pb->bytes_read, ic->pb->seek_count, ic->nb_streams);
 
     for (i = 0; i < ic->nb_streams; i++) {
         const AVCodec *codec;
         AVDictionary *thread_opt = NULL;
         st = ic->streams[i];
+        avctx = st->internal->avctx;
 
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
-            st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
+            st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) {
 /*            if (!st->time_base.num)
                 st->time_base = */
-            if (!st->codec->time_base.num)
-                st->codec->time_base = st->time_base;
+            if (!avctx->time_base.num)
+                avctx->time_base = st->time_base;
         }
         // only for the split stuff
         if (!st->parser && !(ic->flags & AVFMT_FLAG_NOPARSE) && st->request_probe <= 0) {
-            st->parser = av_parser_init(st->codec->codec_id);
+            st->parser = av_parser_init(st->codecpar->codec_id);
             if (st->parser) {
                 if (st->need_parsing == AVSTREAM_PARSE_HEADERS) {
                     st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
@@ -3194,10 +3336,30 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             } else if (st->need_parsing) {
                 av_log(ic, AV_LOG_VERBOSE, "parser not found for codec "
                        "%s, packets or times may be invalid.\n",
-                       avcodec_get_name(st->codec->codec_id));
+                       avcodec_get_name(st->codecpar->codec_id));
             }
         }
-        codec = find_decoder(ic, st, st->codec->codec_id);
+
+        /* check if the caller has overridden the codec id */
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+        if (st->codec->codec_id != st->internal->orig_codec_id) {
+            st->codecpar->codec_id   = st->codec->codec_id;
+            st->codecpar->codec_type = st->codec->codec_type;
+            st->internal->orig_codec_id = st->codec->codec_id;
+        }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+        if (st->codecpar->codec_id != st->internal->orig_codec_id)
+            st->internal->orig_codec_id = st->codecpar->codec_id;
+
+        ret = avcodec_parameters_to_context(avctx, st->codecpar);
+        if (ret < 0)
+            goto find_stream_info_err;
+        if (st->request_probe <= 0)
+            st->internal->avctx_inited = 1;
+
+        codec = find_decoder(ic, st, st->codecpar->codec_id);
 
         /* Force thread count to 1 since the H.264 decoder will not extract
          * SPS and PPS to extradata during multi-threaded decoding. */
@@ -3207,17 +3369,17 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             av_dict_set(options ? &options[i] : &thread_opt, "codec_whitelist", ic->codec_whitelist, 0);
 
         /* Ensure that subtitle_header is properly set. */
-        if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE
-            && codec && !st->codec->codec) {
-            if (avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt) < 0)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE
+            && codec && !avctx->codec) {
+            if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0)
                 av_log(ic, AV_LOG_WARNING,
                        "Failed to open codec in av_find_stream_info\n");
         }
 
         // Try to just open decoders, in case this is enough to get parameters.
         if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) {
-            if (codec && !st->codec->codec)
-                if (avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt) < 0)
+            if (codec && !avctx->codec)
+                if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0)
                     av_log(ic, AV_LOG_WARNING,
                            "Failed to open codec in av_find_stream_info\n");
         }
@@ -3233,7 +3395,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
         ic->streams[i]->info->fps_last_dts  = AV_NOPTS_VALUE;
     }
 
-    count     = 0;
     read_size = 0;
     for (;;) {
         int analyzed_all_streams;
@@ -3255,7 +3416,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
              * the correct fps. */
             if (av_q2d(st->time_base) > 0.0005)
                 fps_analyze_framecount *= 2;
-            if (!tb_unreliable(st->codec))
+            if (!tb_unreliable(st->internal->avctx))
                 fps_analyze_framecount = 0;
             if (ic->fps_probe_size >= 0)
                 fps_analyze_framecount = ic->fps_probe_size;
@@ -3263,7 +3424,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                 fps_analyze_framecount = 0;
             /* variable fps and no guess at the real fps */
             if (!(st->r_frame_rate.num && st->avg_frame_rate.num) &&
-                st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+                st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
                 int count = (ic->iformat->flags & AVFMT_NOTIMESTAMPS) ?
                     st->info->codec_info_duration_fields/2 :
                     st->info->duration_count;
@@ -3271,13 +3432,13 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                     break;
             }
             if (st->parser && st->parser->parser->split &&
-                !st->codec->extradata)
+                !st->codecpar->extradata)
                 break;
             if (st->first_dts == AV_NOPTS_VALUE &&
                 !(ic->iformat->flags & AVFMT_NOTIMESTAMPS) &&
-                st->codec_info_nb_frames < ic->max_ts_probe &&
-                (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
-                 st->codec->codec_type == AVMEDIA_TYPE_AUDIO))
+                st->codec_info_nb_frames < ((st->disposition & AV_DISPOSITION_ATTACHED_PIC) ? 1 : ic->max_ts_probe) &&
+                (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
+                 st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO))
                 break;
         }
         analyzed_all_streams = 0;
@@ -3301,7 +3462,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             for (i = 0; i < ic->nb_streams; i++)
                 if (!ic->streams[i]->r_frame_rate.num &&
                     ic->streams[i]->info->duration_count <= 1 &&
-                    ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+                    ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
                     strcmp(ic->iformat->name, "image2"))
                     av_log(ic, AV_LOG_WARNING,
                            "Stream #%d: not enough frames to estimate rate; "
@@ -3317,6 +3478,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
 
         if (ret < 0) {
             /* EOF or error*/
+            eof_reached = 1;
             break;
         }
 
@@ -3333,6 +3495,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
         if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC))
             read_size += pkt->size;
 
+        avctx = st->internal->avctx;
+        if (!st->internal->avctx_inited) {
+            ret = avcodec_parameters_to_context(avctx, st->codecpar);
+            if (ret < 0)
+                goto find_stream_info_err;
+            st->internal->avctx_inited = 1;
+        }
+
         if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) {
             /* check for non-increasing dts */
             if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
@@ -3388,7 +3558,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                 t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q));
 
             if (analyzed_all_streams)                                limit = max_analyze_duration;
-            else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) limit = max_subtitle_analyze_duration;
+            else if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE) limit = max_subtitle_analyze_duration;
             else                                                     limit = max_stream_analyze_duration;
 
             if (t >= limit) {
@@ -3400,24 +3570,27 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
                 break;
             }
             if (pkt->duration) {
-                if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE && pkt->pts != AV_NOPTS_VALUE && pkt->pts >= st->start_time) {
+                if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE && pkt->pts != AV_NOPTS_VALUE && pkt->pts >= st->start_time) {
                     st->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, st->info->codec_info_duration + pkt->duration);
                 } else
                     st->info->codec_info_duration += pkt->duration;
-                st->info->codec_info_duration_fields += st->parser && st->need_parsing && st->codec->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2;
+                st->info->codec_info_duration_fields += st->parser && st->need_parsing && avctx->ticks_per_frame ==2 ? st->parser->repeat_pict + 1 : 2;
             }
         }
 #if FF_API_R_FRAME_RATE
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+        if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
             ff_rfps_add_frame(ic, st, pkt->dts);
 #endif
-        if (st->parser && st->parser->parser->split && !st->codec->extradata) {
-            int i = st->parser->parser->split(st->codec, pkt->data, pkt->size);
+        if (st->parser && st->parser->parser->split && !avctx->extradata) {
+            int i = st->parser->parser->split(avctx, pkt->data, pkt->size);
             if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) {
-                if (ff_alloc_extradata(st->codec, i))
+                avctx->extradata_size = i;
+                avctx->extradata      = av_mallocz(avctx->extradata_size +
+                                                   AV_INPUT_BUFFER_PADDING_SIZE);
+                if (!avctx->extradata)
                     return AVERROR(ENOMEM);
-                memcpy(st->codec->extradata, pkt->data,
-                       st->codec->extradata_size);
+                memcpy(avctx->extradata, pkt->data,
+                       avctx->extradata_size);
             }
         }
 
@@ -3440,6 +3613,28 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
         count++;
     }
 
+    if (eof_reached) {
+        int stream_index;
+        for (stream_index = 0; stream_index < ic->nb_streams; stream_index++) {
+            st = ic->streams[stream_index];
+            avctx = st->internal->avctx;
+            if (!has_codec_parameters(st, NULL)) {
+                const AVCodec *codec = find_decoder(ic, st, st->codecpar->codec_id);
+                if (codec && !avctx->codec) {
+                    if (avcodec_open2(avctx, codec, (options && stream_index < orig_nb_streams) ? &options[stream_index] : NULL) < 0)
+                        av_log(ic, AV_LOG_WARNING,
+                            "Failed to open codec in av_find_stream_info\n");
+                }
+            }
+
+            // EOF already reached while reading the stream above.
+            // So continue with reoordering DTS with whatever delay we have.
+            if (ic->internal->packet_buffer && !has_decode_delay_been_guessed(st)) {
+                update_dts_from_pts(ic, stream_index, ic->internal->packet_buffer);
+            }
+        }
+    }
+
     if (flush_codecs) {
         AVPacket empty_pkt = { 0 };
         int err = 0;
@@ -3468,18 +3663,19 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
     // close codecs which were opened in try_decode_frame()
     for (i = 0; i < ic->nb_streams; i++) {
         st = ic->streams[i];
-        avcodec_close(st->codec);
+        avcodec_close(st->internal->avctx);
     }
 
     ff_rfps_calculate(ic);
 
     for (i = 0; i < ic->nb_streams; i++) {
         st = ic->streams[i];
-        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-            if (st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample) {
-                uint32_t tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
-                if (avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), tag) == st->codec->pix_fmt)
-                    st->codec->codec_tag= tag;
+        avctx = st->internal->avctx;
+        if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
+            if (avctx->codec_id == AV_CODEC_ID_RAWVIDEO && !avctx->codec_tag && !avctx->bits_per_coded_sample) {
+                uint32_t tag= avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt);
+                if (avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), tag) == avctx->pix_fmt)
+                    avctx->codec_tag= tag;
             }
 
             /* estimate average framerate if not set by demuxer */
@@ -3515,26 +3711,26 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
             }
 
             if (!st->r_frame_rate.num) {
-                if (    st->codec->time_base.den * (int64_t) st->time_base.num
-                    <= st->codec->time_base.num * st->codec->ticks_per_frame * (int64_t) st->time_base.den) {
-                    st->r_frame_rate.num = st->codec->time_base.den;
-                    st->r_frame_rate.den = st->codec->time_base.num * st->codec->ticks_per_frame;
+                if (    avctx->time_base.den * (int64_t) st->time_base.num
+                    <= avctx->time_base.num * avctx->ticks_per_frame * (int64_t) st->time_base.den) {
+                    st->r_frame_rate.num = avctx->time_base.den;
+                    st->r_frame_rate.den = avctx->time_base.num * avctx->ticks_per_frame;
                 } else {
                     st->r_frame_rate.num = st->time_base.den;
                     st->r_frame_rate.den = st->time_base.num;
                 }
             }
             if (st->display_aspect_ratio.num && st->display_aspect_ratio.den) {
-                AVRational hw_ratio = { st->codec->height, st->codec->width };
+                AVRational hw_ratio = { avctx->height, avctx->width };
                 st->sample_aspect_ratio = av_mul_q(st->display_aspect_ratio,
                                                    hw_ratio);
             }
-        } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-            if (!st->codec->bits_per_coded_sample)
-                st->codec->bits_per_coded_sample =
-                    av_get_bits_per_sample(st->codec->codec_id);
+        } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
+            if (!avctx->bits_per_coded_sample)
+                avctx->bits_per_coded_sample =
+                    av_get_bits_per_sample(avctx->codec_id);
             // set stream disposition based on audio service type
-            switch (st->codec->audio_service_type) {
+            switch (avctx->audio_service_type) {
             case AV_AUDIO_SERVICE_TYPE_EFFECTS:
                 st->disposition = AV_DISPOSITION_CLEAN_EFFECTS;
                 break;
@@ -3565,9 +3761,19 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
     for (i = 0; i < ic->nb_streams; i++) {
         const char *errmsg;
         st = ic->streams[i];
+
+        /* if no packet was ever seen, update context now for has_codec_parameters */
+        if (!st->internal->avctx_inited) {
+            if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
+                st->codecpar->format == AV_SAMPLE_FMT_NONE)
+                st->codecpar->format = st->internal->avctx->sample_fmt;
+            ret = avcodec_parameters_to_context(st->internal->avctx, st->codecpar);
+            if (ret < 0)
+                goto find_stream_info_err;
+        }
         if (!has_codec_parameters(st, &errmsg)) {
             char buf[256];
-            avcodec_string(buf, sizeof(buf), st->codec, 0);
+            avcodec_string(buf, sizeof(buf), st->internal->avctx, 0);
             av_log(ic, AV_LOG_WARNING,
                    "Could not find codec parameters for stream %d (%s): %s\n"
                    "Consider increasing the value for the 'analyzeduration' and 'probesize' options\n",
@@ -3579,11 +3785,63 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
 
     compute_chapters_end(ic);
 
+    /* update the stream parameters from the internal codec contexts */
+    for (i = 0; i < ic->nb_streams; i++) {
+        st = ic->streams[i];
+
+        if (st->internal->avctx_inited) {
+            int orig_w = st->codecpar->width;
+            int orig_h = st->codecpar->height;
+            ret = avcodec_parameters_from_context(st->codecpar, st->internal->avctx);
+            if (ret < 0)
+                goto find_stream_info_err;
+            // The decoder might reduce the video size by the lowres factor.
+            if (av_codec_get_lowres(st->internal->avctx) && orig_w) {
+                st->codecpar->width = orig_w;
+                st->codecpar->height = orig_h;
+            }
+        }
+
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+        ret = avcodec_parameters_to_context(st->codec, st->codecpar);
+        if (ret < 0)
+            goto find_stream_info_err;
+
+        // The old API (AVStream.codec) "requires" the resolution to be adjusted
+        // by the lowres factor.
+        if (av_codec_get_lowres(st->internal->avctx) && st->internal->avctx->width) {
+            av_codec_set_lowres(st->codec, av_codec_get_lowres(st->internal->avctx));
+            st->codec->width = st->internal->avctx->width;
+            st->codec->height = st->internal->avctx->height;
+        }
+
+        if (st->codec->codec_tag != MKTAG('t','m','c','d'))
+            st->codec->time_base = st->internal->avctx->time_base;
+        st->codec->framerate = st->avg_frame_rate;
+
+        if (st->internal->avctx->subtitle_header) {
+            st->codec->subtitle_header = av_malloc(st->internal->avctx->subtitle_header_size);
+            if (!st->codec->subtitle_header)
+                goto find_stream_info_err;
+            st->codec->subtitle_header_size = st->internal->avctx->subtitle_header_size;
+            memcpy(st->codec->subtitle_header, st->internal->avctx->subtitle_header,
+                   st->codec->subtitle_header_size);
+        }
+
+        // Fields unavailable in AVCodecParameters
+        st->codec->coded_width = st->internal->avctx->coded_width;
+        st->codec->coded_height = st->internal->avctx->coded_height;
+        st->codec->properties = st->internal->avctx->properties;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+        st->internal->avctx_inited = 0;
+    }
+
 find_stream_info_err:
     for (i = 0; i < ic->nb_streams; i++) {
         st = ic->streams[i];
-        if (ic->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
-            ic->streams[i]->codec->thread_count = 0;
         if (st->info)
             av_freep(&st->info->duration_error);
         av_freep(&ic->streams[i]->info);
@@ -3630,8 +3888,8 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,
     for (i = 0; i < nb_streams; i++) {
         int real_stream_index = program ? program[i] : i;
         AVStream *st          = ic->streams[real_stream_index];
-        AVCodecContext *avctx = st->codec;
-        if (avctx->codec_type != type)
+        AVCodecParameters *par = st->codecpar;
+        if (par->codec_type != type)
             continue;
         if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb)
             continue;
@@ -3639,10 +3897,10 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,
             st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED |
                                AV_DISPOSITION_VISUAL_IMPAIRED))
             continue;
-        if (type == AVMEDIA_TYPE_AUDIO && !(avctx->channels && avctx->sample_rate))
+        if (type == AVMEDIA_TYPE_AUDIO && !(par->channels && par->sample_rate))
             continue;
         if (decoder_ret) {
-            decoder = find_decoder(ic, st, st->codec->codec_id);
+            decoder = find_decoder(ic, st, par->codec_id);
             if (!decoder) {
                 if (ret < 0)
                     ret = AVERROR_DECODER_NOT_FOUND;
@@ -3650,9 +3908,7 @@ int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,
             }
         }
         count = st->codec_info_nb_frames;
-        bitrate = avctx->bit_rate;
-        if (!bitrate)
-            bitrate = avctx->rc_max_rate;
+        bitrate = par->bit_rate;
         multiframe = FFMIN(5, count);
         if ((best_multiframe >  multiframe) ||
             (best_multiframe == multiframe && best_bitrate >  bitrate) ||
@@ -3713,14 +3969,26 @@ static void free_stream(AVStream **pst)
     if (st->attached_pic.data)
         av_packet_unref(&st->attached_pic);
 
+    if (st->internal) {
+        avcodec_free_context(&st->internal->avctx);
+        for (i = 0; i < st->internal->nb_bsfcs; i++) {
+            av_bsf_free(&st->internal->bsfcs[i]);
+            av_freep(&st->internal->bsfcs);
+        }
+    }
     av_freep(&st->internal);
 
     av_dict_free(&st->metadata);
+    avcodec_parameters_free(&st->codecpar);
     av_freep(&st->probe_data.buf);
     av_freep(&st->index_entries);
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
     av_freep(&st->codec->extradata);
     av_freep(&st->codec->subtitle_header);
     av_freep(&st->codec);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
     av_freep(&st->priv_data);
     if (st->info)
         av_freep(&st->info->duration_error);
@@ -3825,20 +4093,36 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
     }
     st->info->last_dts = AV_NOPTS_VALUE;
 
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
     st->codec = avcodec_alloc_context3(c);
     if (!st->codec) {
         av_free(st->info);
         av_free(st);
         return NULL;
     }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
     st->internal = av_mallocz(sizeof(*st->internal));
     if (!st->internal)
         goto fail;
 
+    st->codecpar = avcodec_parameters_alloc();
+    if (!st->codecpar)
+        goto fail;
+
+    st->internal->avctx = avcodec_alloc_context3(NULL);
+    if (!st->internal->avctx)
+        goto fail;
+
     if (s->iformat) {
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
         /* no default bitrate if decoding */
         st->codec->bit_rate = 0;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
         /* default pts setting is MPEG-like */
         avpriv_set_pts_info(st, 33, 1, 90000);
@@ -3874,6 +4158,8 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
 
     st->inject_global_side_data = s->internal->inject_global_side_data;
 
+    st->internal->need_context_update = 1;
+
     s->streams[s->nb_streams++] = st;
     return st;
 fail:
@@ -4168,7 +4454,12 @@ void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits,
         return;
     }
     s->time_base     = new_tb;
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
     av_codec_set_pkt_timebase(s->codec, new_tb);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+    av_codec_set_pkt_timebase(s->internal->avctx, new_tb);
     s->pts_wrap_bits = pts_wrap_bits;
 }
 
@@ -4321,7 +4612,7 @@ AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *strea
 {
     AVRational undef = {0, 1};
     AVRational stream_sample_aspect_ratio = stream ? stream->sample_aspect_ratio : undef;
-    AVRational codec_sample_aspect_ratio  = stream && stream->codec ? stream->codec->sample_aspect_ratio : undef;
+    AVRational codec_sample_aspect_ratio  = stream && stream->codecpar ? stream->codecpar->sample_aspect_ratio : undef;
     AVRational frame_sample_aspect_ratio  = frame  ? frame->sample_aspect_ratio  : codec_sample_aspect_ratio;
 
     av_reduce(&stream_sample_aspect_ratio.num, &stream_sample_aspect_ratio.den,
@@ -4343,7 +4634,7 @@ AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *strea
 AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame)
 {
     AVRational fr = st->r_frame_rate;
-    AVRational codec_fr = st->codec->framerate;
+    AVRational codec_fr = st->internal->avctx->framerate;
     AVRational   avg_fr = st->avg_frame_rate;
 
     if (avg_fr.num > 0 && avg_fr.den > 0 && fr.num > 0 && fr.den > 0 &&
@@ -4352,7 +4643,7 @@ AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *f
     }
 
 
-    if (st->codec->ticks_per_frame > 1) {
+    if (st->internal->avctx->ticks_per_frame > 1) {
         if (   codec_fr.num > 0 && codec_fr.den > 0 &&
             (fr.num == 0 || av_q2d(codec_fr) < av_q2d(fr)*0.7 && fabs(1.0 - av_q2d(av_div_q(avg_fr, fr))) > 0.1))
             fr = codec_fr;
@@ -4380,17 +4671,37 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
         case 'V': type = AVMEDIA_TYPE_VIDEO; nopic = 1; break;
         default:  av_assert0(0);
         }
-        if (type != st->codec->codec_type)
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+        if (type != st->codecpar->codec_type
+           && (st->codecpar->codec_type != AVMEDIA_TYPE_UNKNOWN || st->codec->codec_type != type))
             return 0;
+FF_ENABLE_DEPRECATION_WARNINGS
+#else
+        if (type != st->codecpar->codec_type)
+            return 0;
+#endif
         if (nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC))
             return 0;
         if (*spec++ == ':') { /* possibly followed by :index */
             int i, index = strtol(spec, NULL, 0);
-            for (i = 0; i < s->nb_streams; i++)
-                if (s->streams[i]->codec->codec_type == type &&
+            for (i = 0; i < s->nb_streams; i++) {
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+                if ((s->streams[i]->codecpar->codec_type == type
+                      || s->streams[i]->codec->codec_type == type
+                    ) &&
+                    !(nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC)) &&
+                    index-- == 0)
+                    return i == st->index;
+FF_ENABLE_DEPRECATION_WARNINGS
+#else
+                if ((s->streams[i]->codecpar->codec_type == type) &&
                     !(nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC)) &&
                     index-- == 0)
                     return i == st->index;
+#endif
+            }
             return 0;
         }
         return 1;
@@ -4447,17 +4758,36 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
         av_freep(&key);
         return ret;
     } else if (*spec == 'u') {
-        AVCodecContext *avctx = st->codec;
+        AVCodecParameters *par = st->codecpar;
+#if FF_API_LAVF_AVCTX
+FF_DISABLE_DEPRECATION_WARNINGS
+        AVCodecContext *codec = st->codec;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
         int val;
-        switch (avctx->codec_type) {
+        switch (par->codec_type) {
         case AVMEDIA_TYPE_AUDIO:
-            val = avctx->sample_rate && avctx->channels;
-            if (avctx->sample_fmt == AV_SAMPLE_FMT_NONE)
+            val = par->sample_rate && par->channels;
+#if FF_API_LAVF_AVCTX
+            val = val || (codec->sample_rate && codec->channels);
+#endif
+            if (par->format == AV_SAMPLE_FMT_NONE
+#if FF_API_LAVF_AVCTX
+                && codec->sample_fmt == AV_SAMPLE_FMT_NONE
+#endif
+                )
                 return 0;
             break;
         case AVMEDIA_TYPE_VIDEO:
-            val = avctx->width && avctx->height;
-            if (avctx->pix_fmt == AV_PIX_FMT_NONE)
+            val = par->width && par->height;
+#if FF_API_LAVF_AVCTX
+            val = val || (codec->width && codec->height);
+#endif
+            if (par->format == AV_PIX_FMT_NONE
+#if FF_API_LAVF_AVCTX
+                && codec->pix_fmt == AV_PIX_FMT_NONE
+#endif
+                )
                 return 0;
             break;
         case AVMEDIA_TYPE_UNKNOWN:
@@ -4467,7 +4797,11 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st,
             val = 1;
             break;
         }
-        return avctx->codec_id != AV_CODEC_ID_NONE && val != 0;
+#if FF_API_LAVF_AVCTX
+        return (par->codec_id != AV_CODEC_ID_NONE || codec->codec_id != AV_CODEC_ID_NONE) && val != 0;
+#else
+        return par->codec_id != AV_CODEC_ID_NONE && val != 0;
+#endif
     } else if (!*spec) /* empty specifier, matches everything */
         return 1;
 
@@ -4576,26 +4910,26 @@ int ff_generate_avci_extradata(AVStream *st)
     const uint8_t *data = NULL;
     int size            = 0;
 
-    if (st->codec->width == 1920) {
-        if (st->codec->field_order == AV_FIELD_PROGRESSIVE) {
+    if (st->codecpar->width == 1920) {
+        if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) {
             data = avci100_1080p_extradata;
             size = sizeof(avci100_1080p_extradata);
         } else {
             data = avci100_1080i_extradata;
             size = sizeof(avci100_1080i_extradata);
         }
-    } else if (st->codec->width == 1440) {
-        if (st->codec->field_order == AV_FIELD_PROGRESSIVE) {
+    } else if (st->codecpar->width == 1440) {
+        if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) {
             data = avci50_1080p_extradata;
             size = sizeof(avci50_1080p_extradata);
         } else {
             data = avci50_1080i_extradata;
             size = sizeof(avci50_1080i_extradata);
         }
-    } else if (st->codec->width == 1280) {
+    } else if (st->codecpar->width == 1280) {
         data = avci100_720p_extradata;
         size = sizeof(avci100_720p_extradata);
-    } else if (st->codec->width == 960) {
+    } else if (st->codecpar->width == 960) {
         data = avci50_720p_extradata;
         size = sizeof(avci50_720p_extradata);
     }
@@ -4603,10 +4937,10 @@ int ff_generate_avci_extradata(AVStream *st)
     if (!size)
         return 0;
 
-    av_freep(&st->codec->extradata);
-    if (ff_alloc_extradata(st->codec, size))
+    av_freep(&st->codecpar->extradata);
+    if (ff_alloc_extradata(st->codecpar, size))
         return AVERROR(ENOMEM);
-    memcpy(st->codec->extradata, data, size);
+    memcpy(st->codecpar->extradata, data, size);
 
     return 0;
 }
@@ -4665,26 +4999,63 @@ uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type,
 
 int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args)
 {
-    AVBitStreamFilterContext *bsfc = NULL;
-    AVBitStreamFilterContext **dest = &st->internal->bsfc;
-    while (*dest && (*dest)->next)
-        dest = &(*dest)->next;
+    int ret;
+    const AVBitStreamFilter *bsf;
+    AVBSFContext *bsfc;
+    AVCodecParameters *in_par;
 
-    if (!(bsfc = av_bitstream_filter_init(name))) {
+    if (!(bsf = av_bsf_get_by_name(name))) {
         av_log(NULL, AV_LOG_ERROR, "Unknown bitstream filter '%s'\n", name);
-        return AVERROR(EINVAL);
+        return AVERROR_BSF_NOT_FOUND;
     }
-    if (args && !(bsfc->args = av_strdup(args))) {
-        av_bitstream_filter_close(bsfc);
-        return AVERROR(ENOMEM);
+
+    if ((ret = av_bsf_alloc(bsf, &bsfc)) < 0)
+        return ret;
+
+    if (st->internal->nb_bsfcs) {
+        in_par = st->internal->bsfcs[st->internal->nb_bsfcs - 1]->par_out;
+        bsfc->time_base_in = st->internal->bsfcs[st->internal->nb_bsfcs - 1]->time_base_out;
+    } else {
+        in_par = st->codecpar;
+        bsfc->time_base_in = st->time_base;
+    }
+
+    if ((ret = avcodec_parameters_copy(bsfc->par_in, in_par)) < 0) {
+        av_bsf_free(&bsfc);
+        return ret;
+    }
+
+    if (args && bsfc->filter->priv_class) {
+        const AVOption *opt = av_opt_next(bsfc->priv_data, NULL);
+        const char * shorthand[2] = {NULL};
+
+        if (opt)
+            shorthand[0] = opt->name;
+
+        if ((ret = av_opt_set_from_string(bsfc->priv_data, args, shorthand, "=", ":")) < 0) {
+            av_bsf_free(&bsfc);
+            return ret;
+        }
+    }
+
+    if ((ret = av_bsf_init(bsfc)) < 0) {
+        av_bsf_free(&bsfc);
+        return ret;
+    }
+
+    if ((ret = av_dynarray_add_nofree(&st->internal->bsfcs, &st->internal->nb_bsfcs, bsfc))) {
+        av_bsf_free(&bsfc);
+        return ret;
     }
-    av_log(st->codec, AV_LOG_VERBOSE,
+
+    av_log(NULL, AV_LOG_VERBOSE,
            "Automatically inserted bitstream filter '%s'; args='%s'\n",
            name, args ? args : "");
-    *dest = bsfc;
     return 1;
 }
 
+#if FF_API_OLD_BSF
+FF_DISABLE_DEPRECATION_WARNINGS
 int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt,
                                AVBitStreamFilterContext *bsfc)
 {
@@ -4695,6 +5066,11 @@ int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt,
                                            &new_pkt.data, &new_pkt.size,
                                            pkt->data, pkt->size,
                                            pkt->flags & AV_PKT_FLAG_KEY);
+        if (a == 0 && new_pkt.size == 0 && new_pkt.side_data_elems == 0) {
+            av_packet_unref(pkt);
+            memset(pkt, 0, sizeof(*pkt));
+            return 0;
+        }
         if(a == 0 && new_pkt.data != pkt->data) {
             uint8_t *t = av_malloc(new_pkt.size + AV_INPUT_BUFFER_PADDING_SIZE); //the new should be a subset of the old so cannot overflow
             if (t) {
@@ -4733,6 +5109,8 @@ int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt,
     }
     return ret;
 }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
 
 void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
 {
@@ -4757,3 +5135,72 @@ int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int
     }
     return 0;
 }
+
+int ff_standardize_creation_time(AVFormatContext *s)
+{
+    int64_t timestamp;
+    int ret = ff_parse_creation_time_metadata(s, &timestamp, 0);
+    if (ret == 1) {
+        time_t seconds = timestamp / 1000000;
+        struct tm *ptm, tmbuf;
+        ptm = gmtime_r(&seconds, &tmbuf);
+        if (ptm) {
+            char buf[32];
+            if (!strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", ptm))
+                return AVERROR_EXTERNAL;
+            av_strlcatf(buf, sizeof(buf), ".%06dZ", (int)(timestamp % 1000000));
+            av_dict_set(&s->metadata, "creation_time", buf, 0);
+        } else {
+            return AVERROR_EXTERNAL;
+        }
+    }
+    return ret;
+}
+
+int ff_get_packet_palette(AVFormatContext *s, AVPacket *pkt, int ret, uint32_t *palette)
+{
+    uint8_t *side_data;
+    int size;
+
+    side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size);
+    if (side_data) {
+        if (size != AVPALETTE_SIZE) {
+            av_log(s, AV_LOG_ERROR, "Invalid palette side data\n");
+            return AVERROR_INVALIDDATA;
+        }
+        memcpy(palette, side_data, AVPALETTE_SIZE);
+        return 1;
+    }
+
+    if (ret == CONTAINS_PAL) {
+        int i;
+        for (i = 0; i < AVPALETTE_COUNT; i++)
+            palette[i] = AV_RL32(pkt->data + pkt->size - AVPALETTE_SIZE + i*4);
+        return 1;
+    }
+
+    return 0;
+}
+
+int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf)
+{
+    int ret;
+    char *str;
+
+    ret = av_bprint_finalize(buf, &str);
+    if (ret < 0)
+        return ret;
+    if (!av_bprint_is_complete(buf)) {
+        av_free(str);
+        return AVERROR(ENOMEM);
+    }
+
+    par->extradata = str;
+    /* Note: the string is NUL terminated (so extradata can be read as a
+     * string), but the ending character is not accounted in the size (in
+     * binary formats you are likely not supposed to mux that character). When
+     * extradata is copied, it is also padded with AV_INPUT_BUFFER_PADDING_SIZE
+     * zeros. */
+    par->extradata_size = buf->len;
+    return 0;
+}
diff --git a/libavformat/v210.c b/libavformat/v210.c
index 31387a4..a90bd36 100644
--- a/libavformat/v210.c
+++ b/libavformat/v210.c
@@ -45,21 +45,21 @@ static int v210_read_header(AVFormatContext *ctx)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
 
-    st->codec->codec_id = ctx->iformat->raw_codec_id;
+    st->codecpar->codec_id = ctx->iformat->raw_codec_id;
 
     avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num);
 
     ret = av_image_check_size(s->width, s->height, 0, ctx);
     if (ret < 0)
         return ret;
-    st->codec->width    = s->width;
-    st->codec->height   = s->height;
-    st->codec->pix_fmt  = ctx->iformat->raw_codec_id == AV_CODEC_ID_V210 ?
-                          AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV422P16;
-    ctx->packet_size    = GET_PACKET_SIZE(s->width, s->height);
-    st->codec->bit_rate = av_rescale_q(ctx->packet_size,
+    st->codecpar->width    = s->width;
+    st->codecpar->height   = s->height;
+    st->codecpar->format   = ctx->iformat->raw_codec_id == AV_CODEC_ID_V210 ?
+                             AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV422P16;
+    ctx->packet_size       = GET_PACKET_SIZE(s->width, s->height);
+    st->codecpar->bit_rate = av_rescale_q(ctx->packet_size,
                                        (AVRational){8,1}, st->time_base);
 
     return 0;
@@ -83,7 +83,7 @@ static int v210_read_packet(AVFormatContext *s, AVPacket *pkt)
 #define DEC AV_OPT_FLAG_DECODING_PARAM
 static const AVOption v210_options[] = {
     { "video_size", "set frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
-    { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, 0, DEC },
+    { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC },
     { NULL },
 };
 
diff --git a/libavformat/vag.c b/libavformat/vag.c
index 2875db5..e8ebcaf 100644
--- a/libavformat/vag.c
+++ b/libavformat/vag.c
@@ -40,37 +40,37 @@ static int vag_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     avio_skip(s->pb, 4);
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = AV_CODEC_ID_ADPCM_PSX;
-    st->codec->channels    = 1 + (avio_rb32(s->pb) == 0x00000004);
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_PSX;
+    st->codecpar->channels    = 1 + (avio_rb32(s->pb) == 0x00000004);
     avio_skip(s->pb, 4);
-    if (st->codec->channels > 1) {
+    if (st->codecpar->channels > 1) {
         st->duration       = avio_rb32(s->pb);
     } else {
         st->duration       = avio_rb32(s->pb) / 16 * 28;
     }
-    st->codec->sample_rate = avio_rb32(s->pb);
-    if (st->codec->sample_rate <= 0)
+    st->codecpar->sample_rate = avio_rb32(s->pb);
+    if (st->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
     avio_seek(s->pb, 0x1000, SEEK_SET);
     if (avio_rl32(s->pb) == MKTAG('V','A','G','p')) {
-        st->codec->block_align = 0x1000 * st->codec->channels;
+        st->codecpar->block_align = 0x1000 * st->codecpar->channels;
         avio_seek(s->pb, 0, SEEK_SET);
         st->duration = st->duration / 16 * 28;
     } else {
-        st->codec->block_align = 16 * st->codec->channels;
-        avio_seek(s->pb, st->codec->channels > 1 ? 0x80 : 0x30, SEEK_SET);
+        st->codecpar->block_align = 16 * st->codecpar->channels;
+        avio_seek(s->pb, st->codecpar->channels > 1 ? 0x80 : 0x30, SEEK_SET);
     }
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
 
 static int vag_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
-    return av_get_packet(s->pb, pkt, codec->block_align);
+    return av_get_packet(s->pb, pkt, par->block_align);
 }
 
 AVInputFormat ff_vag_demuxer = {
diff --git a/libavformat/vc1test.c b/libavformat/vc1test.c
index 3afe398..a801f4b 100644
--- a/libavformat/vc1test.c
+++ b/libavformat/vc1test.c
@@ -58,13 +58,13 @@ static int vc1t_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_WMV3;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_WMV3;
 
-    if (ff_get_extradata(st->codec, pb, VC1_EXTRADATA_SIZE) < 0)
+    if (ff_get_extradata(s, st->codecpar, pb, VC1_EXTRADATA_SIZE) < 0)
         return AVERROR(ENOMEM);
-    st->codec->height = avio_rl32(pb);
-    st->codec->width = avio_rl32(pb);
+    st->codecpar->height = avio_rl32(pb);
+    st->codecpar->width = avio_rl32(pb);
     if(avio_rl32(pb) != 0xC)
         return AVERROR_INVALIDDATA;
     avio_skip(pb, 8);
diff --git a/libavformat/vc1testenc.c b/libavformat/vc1testenc.c
index 751333a..60fb894 100644
--- a/libavformat/vc1testenc.c
+++ b/libavformat/vc1testenc.c
@@ -27,19 +27,19 @@ typedef struct RCVContext {
 
 static int vc1test_write_header(AVFormatContext *s)
 {
-    AVCodecContext *avc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     AVIOContext *pb = s->pb;
 
-    if (avc->codec_id != AV_CODEC_ID_WMV3) {
+    if (par->codec_id != AV_CODEC_ID_WMV3) {
         av_log(s, AV_LOG_ERROR, "Only WMV3 is accepted!\n");
         return -1;
     }
     avio_wl24(pb, 0); //frames count will be here
     avio_w8(pb, 0xC5);
     avio_wl32(pb, 4);
-    avio_write(pb, avc->extradata, 4);
-    avio_wl32(pb, avc->height);
-    avio_wl32(pb, avc->width);
+    avio_write(pb, par->extradata, 4);
+    avio_wl32(pb, par->height);
+    avio_wl32(pb, par->width);
     avio_wl32(pb, 0xC);
     avio_wl24(pb, 0); // hrd_buffer
     avio_w8(pb, 0x80); // level|cbr|res1
diff --git a/libavformat/version.h b/libavformat/version.h
index 024ab91..47a8afb 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -29,8 +29,10 @@
 
 #include "libavutil/version.h"
 
+// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
+// Also please add any ticket numbers that you belive might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  57
-#define LIBAVFORMAT_VERSION_MINOR  25
+#define LIBAVFORMAT_VERSION_MINOR  41
 #define LIBAVFORMAT_VERSION_MICRO 100
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
@@ -74,6 +76,9 @@
 #ifndef FF_API_OLD_OPEN_CALLBACKS
 #define FF_API_OLD_OPEN_CALLBACKS       (LIBAVFORMAT_VERSION_MAJOR < 58)
 #endif
+#ifndef FF_API_LAVF_AVCTX
+#define FF_API_LAVF_AVCTX               (LIBAVFORMAT_VERSION_MAJOR < 58)
+#endif
 
 #ifndef FF_API_R_FRAME_RATE
 #define FF_API_R_FRAME_RATE            1
diff --git a/libavformat/vivo.c b/libavformat/vivo.c
index 10d81b9..a9effd5 100644
--- a/libavformat/vivo.c
+++ b/libavformat/vivo.c
@@ -131,7 +131,7 @@ static int vivo_read_header(AVFormatContext *s)
     if (!ast || !vst)
         return AVERROR(ENOMEM);
 
-    ast->codec->sample_rate = 8000;
+    ast->codecpar->sample_rate = 8000;
 
     while (1) {
         if ((ret = vivo_get_packet_header(s)) < 0)
@@ -182,15 +182,15 @@ static int vivo_read_header(AVFormatContext *s)
                 if (!strcmp(key, "Duration")) {
                     duration = value_int;
                 } else if (!strcmp(key, "Width")) {
-                    vst->codec->width = value_int;
+                    vst->codecpar->width = value_int;
                 } else if (!strcmp(key, "Height")) {
-                    vst->codec->height = value_int;
+                    vst->codecpar->height = value_int;
                 } else if (!strcmp(key, "TimeUnitNumerator")) {
                     fps.num = value_int / 1000;
                 } else if (!strcmp(key, "TimeUnitDenominator")) {
                     fps.den = value_int;
                 } else if (!strcmp(key, "SamplingFrequency")) {
-                    ast->codec->sample_rate = value_int;
+                    ast->codecpar->sample_rate = value_int;
                 } else if (!strcmp(key, "NominalBitrate")) {
                 } else if (!strcmp(key, "Length")) {
                     // size of file
@@ -216,27 +216,27 @@ static int vivo_read_header(AVFormatContext *s)
         }
     }
 
-    avpriv_set_pts_info(ast, 64, 1, ast->codec->sample_rate);
+    avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate);
     avpriv_set_pts_info(vst, 64, fps.num, fps.den);
     if (duration)
         s->duration = av_rescale(duration, 1000, 1);
 
     vst->start_time        = 0;
-    vst->codec->codec_tag  = 0;
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codecpar->codec_tag  = 0;
+    vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
 
     if (vivo->version == 1) {
-        vst->codec->codec_id = AV_CODEC_ID_H263;
-        ast->codec->codec_id = AV_CODEC_ID_G723_1;
-        ast->codec->bits_per_coded_sample = 8;
-        ast->codec->block_align = 24;
-        ast->codec->bit_rate = 6400;
+        vst->codecpar->codec_id = AV_CODEC_ID_H263;
+        ast->codecpar->codec_id = AV_CODEC_ID_G723_1;
+        ast->codecpar->bits_per_coded_sample = 8;
+        ast->codecpar->block_align = 24;
+        ast->codecpar->bit_rate = 6400;
     }
 
     ast->start_time        = 0;
-    ast->codec->codec_tag  = 0;
-    ast->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    ast->codec->channels = 1;
+    ast->codecpar->codec_tag  = 0;
+    ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    ast->codecpar->channels = 1;
 
     return 0;
 }
diff --git a/libavformat/voc_packet.c b/libavformat/voc_packet.c
new file mode 100644
index 0000000..5833a79
--- /dev/null
+++ b/libavformat/voc_packet.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2006  Aurelien Jacobs <aurel at gnuage.org>
+ *
+ * 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/intreadwrite.h"
+#include "avformat.h"
+#include "internal.h"
+#include "voc.h"
+
+int
+ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
+{
+    VocDecContext *voc = s->priv_data;
+    AVCodecParameters *par = st->codecpar;
+    AVIOContext *pb = s->pb;
+    VocType type;
+    int size, tmp_codec=-1;
+    int sample_rate = 0;
+    int channels = 1;
+    int64_t duration;
+    int ret;
+
+    av_add_index_entry(st,
+                       avio_tell(pb),
+                       voc->pts,
+                       voc->remaining_size,
+                       0,
+                       AVINDEX_KEYFRAME);
+
+    while (!voc->remaining_size) {
+        type = avio_r8(pb);
+        if (type == VOC_TYPE_EOF)
+            return AVERROR_EOF;
+        voc->remaining_size = avio_rl24(pb);
+        if (!voc->remaining_size) {
+            if (!s->pb->seekable)
+                return AVERROR(EIO);
+            voc->remaining_size = avio_size(pb) - avio_tell(pb);
+        }
+        max_size -= 4;
+
+        switch (type) {
+        case VOC_TYPE_VOICE_DATA:
+            if (!par->sample_rate) {
+                par->sample_rate = 1000000 / (256 - avio_r8(pb));
+                if (sample_rate)
+                    par->sample_rate = sample_rate;
+                avpriv_set_pts_info(st, 64, 1, par->sample_rate);
+                par->channels = channels;
+                par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id);
+            } else
+                avio_skip(pb, 1);
+            tmp_codec = avio_r8(pb);
+            voc->remaining_size -= 2;
+            max_size -= 2;
+            channels = 1;
+            break;
+
+        case VOC_TYPE_VOICE_DATA_CONT:
+            break;
+
+        case VOC_TYPE_EXTENDED:
+            sample_rate = avio_rl16(pb);
+            avio_r8(pb);
+            channels = avio_r8(pb) + 1;
+            sample_rate = 256000000 / (channels * (65536 - sample_rate));
+            voc->remaining_size = 0;
+            max_size -= 4;
+            break;
+
+        case VOC_TYPE_NEW_VOICE_DATA:
+            if (!par->sample_rate) {
+                par->sample_rate = avio_rl32(pb);
+                avpriv_set_pts_info(st, 64, 1, par->sample_rate);
+                par->bits_per_coded_sample = avio_r8(pb);
+                par->channels = avio_r8(pb);
+            } else
+                avio_skip(pb, 6);
+            tmp_codec = avio_rl16(pb);
+            avio_skip(pb, 4);
+            voc->remaining_size -= 12;
+            max_size -= 12;
+            break;
+
+        default:
+            avio_skip(pb, voc->remaining_size);
+            max_size -= voc->remaining_size;
+            voc->remaining_size = 0;
+            break;
+        }
+    }
+
+    if (tmp_codec >= 0) {
+        tmp_codec = ff_codec_get_id(ff_voc_codec_tags, tmp_codec);
+        if (par->codec_id == AV_CODEC_ID_NONE)
+            par->codec_id = tmp_codec;
+        else if (par->codec_id != tmp_codec)
+            av_log(s, AV_LOG_WARNING, "Ignoring mid-stream change in audio codec\n");
+        if (par->codec_id == AV_CODEC_ID_NONE) {
+            if (s->audio_codec_id == AV_CODEC_ID_NONE) {
+                av_log(s, AV_LOG_ERROR, "unknown codec tag\n");
+                return AVERROR(EINVAL);
+            }
+            av_log(s, AV_LOG_WARNING, "unknown codec tag\n");
+        }
+    }
+
+    par->bit_rate = par->sample_rate * par->channels * par->bits_per_coded_sample;
+
+    if (max_size <= 0)
+        max_size = 2048;
+    size = FFMIN(voc->remaining_size, max_size);
+    voc->remaining_size -= size;
+
+    ret = av_get_packet(pb, pkt, size);
+    pkt->dts = pkt->pts = voc->pts;
+
+    duration = av_get_audio_frame_duration2(st->codecpar, size);
+    if (duration > 0 && voc->pts != AV_NOPTS_VALUE)
+        voc->pts += duration;
+    else
+        voc->pts = AV_NOPTS_VALUE;
+
+    return ret;
+}
diff --git a/libavformat/vocdec.c b/libavformat/vocdec.c
index 70fa009..10df28b 100644
--- a/libavformat/vocdec.c
+++ b/libavformat/vocdec.c
@@ -23,124 +23,6 @@
 #include "voc.h"
 #include "internal.h"
 
-int
-ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size)
-{
-    VocDecContext *voc = s->priv_data;
-    AVCodecContext *dec = st->codec;
-    AVIOContext *pb = s->pb;
-    VocType type;
-    int size, tmp_codec=-1;
-    int sample_rate = 0;
-    int channels = 1;
-    int64_t duration;
-    int ret;
-
-    av_add_index_entry(st,
-                       avio_tell(pb),
-                       voc->pts,
-                       voc->remaining_size,
-                       0,
-                       AVINDEX_KEYFRAME);
-
-    while (!voc->remaining_size) {
-        type = avio_r8(pb);
-        if (type == VOC_TYPE_EOF)
-            return AVERROR_EOF;
-        voc->remaining_size = avio_rl24(pb);
-        if (!voc->remaining_size) {
-            if (!s->pb->seekable)
-                return AVERROR(EIO);
-            voc->remaining_size = avio_size(pb) - avio_tell(pb);
-        }
-        max_size -= 4;
-
-        switch (type) {
-        case VOC_TYPE_VOICE_DATA:
-            if (!dec->sample_rate) {
-                dec->sample_rate = 1000000 / (256 - avio_r8(pb));
-                if (sample_rate)
-                    dec->sample_rate = sample_rate;
-                avpriv_set_pts_info(st, 64, 1, dec->sample_rate);
-                dec->channels = channels;
-                dec->bits_per_coded_sample = av_get_bits_per_sample(dec->codec_id);
-            } else
-                avio_skip(pb, 1);
-            tmp_codec = avio_r8(pb);
-            voc->remaining_size -= 2;
-            max_size -= 2;
-            channels = 1;
-            break;
-
-        case VOC_TYPE_VOICE_DATA_CONT:
-            break;
-
-        case VOC_TYPE_EXTENDED:
-            sample_rate = avio_rl16(pb);
-            avio_r8(pb);
-            channels = avio_r8(pb) + 1;
-            sample_rate = 256000000 / (channels * (65536 - sample_rate));
-            voc->remaining_size = 0;
-            max_size -= 4;
-            break;
-
-        case VOC_TYPE_NEW_VOICE_DATA:
-            if (!dec->sample_rate) {
-                dec->sample_rate = avio_rl32(pb);
-                avpriv_set_pts_info(st, 64, 1, dec->sample_rate);
-                dec->bits_per_coded_sample = avio_r8(pb);
-                dec->channels = avio_r8(pb);
-            } else
-                avio_skip(pb, 6);
-            tmp_codec = avio_rl16(pb);
-            avio_skip(pb, 4);
-            voc->remaining_size -= 12;
-            max_size -= 12;
-            break;
-
-        default:
-            avio_skip(pb, voc->remaining_size);
-            max_size -= voc->remaining_size;
-            voc->remaining_size = 0;
-            break;
-        }
-    }
-
-    if (tmp_codec >= 0) {
-        tmp_codec = ff_codec_get_id(ff_voc_codec_tags, tmp_codec);
-        if (dec->codec_id == AV_CODEC_ID_NONE)
-            dec->codec_id = tmp_codec;
-        else if (dec->codec_id != tmp_codec)
-            av_log(s, AV_LOG_WARNING, "Ignoring mid-stream change in audio codec\n");
-        if (dec->codec_id == AV_CODEC_ID_NONE) {
-            if (s->audio_codec_id == AV_CODEC_ID_NONE) {
-                av_log(s, AV_LOG_ERROR, "unknown codec tag\n");
-                return AVERROR(EINVAL);
-            }
-            av_log(s, AV_LOG_WARNING, "unknown codec tag\n");
-        }
-    }
-
-    dec->bit_rate = dec->sample_rate * dec->channels * dec->bits_per_coded_sample;
-
-    if (max_size <= 0)
-        max_size = 2048;
-    size = FFMIN(voc->remaining_size, max_size);
-    voc->remaining_size -= size;
-
-    ret = av_get_packet(pb, pkt, size);
-    pkt->dts = pkt->pts = voc->pts;
-
-    duration = av_get_audio_frame_duration(st->codec, size);
-    if (duration > 0 && voc->pts != AV_NOPTS_VALUE)
-        voc->pts += duration;
-    else
-        voc->pts = AV_NOPTS_VALUE;
-
-    return ret;
-}
-
-#if CONFIG_VOC_DEMUXER
 static int voc_probe(AVProbeData *p)
 {
     int version, check;
@@ -160,7 +42,6 @@ static int voc_read_header(AVFormatContext *s)
     VocDecContext *voc = s->priv_data;
     AVIOContext *pb = s->pb;
     int header_size;
-    AVStream *st;
 
     avio_skip(pb, 20);
     header_size = avio_rl16(pb) - 22;
@@ -169,10 +50,8 @@ static int voc_read_header(AVFormatContext *s)
         return AVERROR(ENOSYS);
     }
     avio_skip(pb, header_size);
-    st = avformat_new_stream(s, NULL);
-    if (!st)
-        return AVERROR(ENOMEM);
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+
+    s->ctx_flags |= AVFMTCTX_NOHEADER;
 
     voc->remaining_size = 0;
     return 0;
@@ -180,6 +59,12 @@ static int voc_read_header(AVFormatContext *s)
 
 static int voc_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
+    if (!s->nb_streams) {
+        AVStream *st = avformat_new_stream(s, NULL);
+        if (!st)
+            return AVERROR(ENOMEM);
+        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    }
     return ff_voc_get_packet(s, pkt, s->streams[0], 0);
 }
 
@@ -187,8 +72,16 @@ static int voc_read_seek(AVFormatContext *s, int stream_index,
                          int64_t timestamp, int flags)
 {
     VocDecContext *voc = s->priv_data;
-    AVStream *st = s->streams[stream_index];
-    int index = av_index_search_timestamp(st, timestamp, flags);
+    AVStream *st;
+    int index;
+
+    if (s->nb_streams < 1) {
+        av_log(s, AV_LOG_ERROR, "cannot seek while no stream was found yet\n");
+        return AVERROR(EINVAL);
+    }
+
+    st = s->streams[stream_index];
+    index = av_index_search_timestamp(st, timestamp, flags);
 
     if (index >= 0 && index < st->nb_index_entries - 1) {
         AVIndexEntry *e = &st->index_entries[index];
@@ -215,4 +108,3 @@ AVInputFormat ff_voc_demuxer = {
     .read_seek      = voc_read_seek,
     .codec_tag      = (const AVCodecTag* const []){ ff_voc_codec_tags, 0 },
 };
-#endif /* CONFIG_VOC_DEMUXER */
diff --git a/libavformat/vocenc.c b/libavformat/vocenc.c
index 0bb532e..321b113 100644
--- a/libavformat/vocenc.c
+++ b/libavformat/vocenc.c
@@ -30,15 +30,15 @@ typedef struct voc_enc_context {
 static int voc_write_header(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     const int header_size = 26;
     const int version = 0x0114;
 
     if (s->nb_streams != 1
-        || s->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+        || s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
         return AVERROR_PATCHWELCOME;
 
-    if (!enc->codec_tag && enc->codec_id != AV_CODEC_ID_PCM_U8) {
+    if (!par->codec_tag && par->codec_id != AV_CODEC_ID_PCM_U8) {
         av_log(s, AV_LOG_ERROR, "unsupported codec\n");
         return AVERROR(EINVAL);
     }
@@ -54,30 +54,30 @@ static int voc_write_header(AVFormatContext *s)
 static int voc_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     VocEncContext *voc = s->priv_data;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     AVIOContext *pb = s->pb;
 
     if (!voc->param_written) {
-        if (enc->codec_tag > 3) {
+        if (par->codec_tag > 3) {
             avio_w8(pb, VOC_TYPE_NEW_VOICE_DATA);
             avio_wl24(pb, pkt->size + 12);
-            avio_wl32(pb, enc->sample_rate);
-            avio_w8(pb, enc->bits_per_coded_sample);
-            avio_w8(pb, enc->channels);
-            avio_wl16(pb, enc->codec_tag);
+            avio_wl32(pb, par->sample_rate);
+            avio_w8(pb, par->bits_per_coded_sample);
+            avio_w8(pb, par->channels);
+            avio_wl16(pb, par->codec_tag);
             avio_wl32(pb, 0);
         } else {
-            if (s->streams[0]->codec->channels > 1) {
+            if (s->streams[0]->codecpar->channels > 1) {
                 avio_w8(pb, VOC_TYPE_EXTENDED);
                 avio_wl24(pb, 4);
-                avio_wl16(pb, 65536-(256000000 + enc->sample_rate*enc->channels/2)/(enc->sample_rate*enc->channels));
-                avio_w8(pb, enc->codec_tag);
-                avio_w8(pb, enc->channels - 1);
+                avio_wl16(pb, 65536-(256000000 + par->sample_rate*par->channels/2)/(par->sample_rate*par->channels));
+                avio_w8(pb, par->codec_tag);
+                avio_w8(pb, par->channels - 1);
             }
             avio_w8(pb, VOC_TYPE_VOICE_DATA);
             avio_wl24(pb, pkt->size + 2);
-            avio_w8(pb, 256 - (1000000 + enc->sample_rate/2) / enc->sample_rate);
-            avio_w8(pb, enc->codec_tag);
+            avio_w8(pb, 256 - (1000000 + par->sample_rate/2) / par->sample_rate);
+            avio_w8(pb, par->codec_tag);
         }
         voc->param_written = 1;
     } else {
diff --git a/libavformat/vpcc.c b/libavformat/vpcc.c
new file mode 100644
index 0000000..2390e17
--- /dev/null
+++ b/libavformat/vpcc.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016 Google Inc.
+ * Copyright (c) 2016 KongQun Yang (kqyang at google.com)
+ *
+ * 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/pixdesc.h"
+#include "libavutil/pixfmt.h"
+#include "vpcc.h"
+
+enum VpxColorSpace
+{
+    VPX_COLOR_SPACE_UNSPECIFIED = 0,
+    VPX_COLOR_SPACE_BT601 = 1,
+    VPX_COLOR_SPACE_BT709 = 2,
+    VPX_COLOR_SPACE_SMPTE_170 = 3,
+    VPX_COLOR_SPACE_SMPTE_240 = 4,
+    VPX_COLOR_SPACE_BT2020_NCL = 5,
+    VPX_COLOR_SPACE_BT2020_CL = 6,
+    VPX_COLOR_SPACE_RGB = 7,
+};
+
+static int get_vpx_color_space(AVFormatContext *s,
+                               enum AVColorSpace color_space)
+{
+    switch (color_space) {
+    case AVCOL_SPC_RGB:
+        return VPX_COLOR_SPACE_RGB;
+    case AVCOL_SPC_BT709:
+        return VPX_COLOR_SPACE_BT709;
+    case AVCOL_SPC_UNSPECIFIED:
+        return VPX_COLOR_SPACE_UNSPECIFIED;
+    case AVCOL_SPC_BT470BG:
+        return VPX_COLOR_SPACE_BT601;
+    case AVCOL_SPC_SMPTE170M:
+        return VPX_COLOR_SPACE_SMPTE_170;
+    case AVCOL_SPC_SMPTE240M:
+        return VPX_COLOR_SPACE_SMPTE_240;
+    case AVCOL_SPC_BT2020_NCL:
+        return VPX_COLOR_SPACE_BT2020_NCL;
+    case AVCOL_SPC_BT2020_CL:
+        return VPX_COLOR_SPACE_BT2020_CL;
+    default:
+        av_log(s, AV_LOG_ERROR, "Unsupported color space (%d)\n", color_space);
+        return -1;
+    }
+}
+
+enum VPX_CHROMA_SUBSAMPLING
+{
+    VPX_SUBSAMPLING_420_VERTICAL = 0,
+    VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA = 1,
+    VPX_SUBSAMPLING_422 = 2,
+    VPX_SUBSAMPLING_444 = 3,
+};
+
+static int get_vpx_chroma_subsampling(AVFormatContext *s,
+                                      enum AVPixelFormat pixel_format,
+                                      enum AVChromaLocation chroma_location)
+{
+    int chroma_w, chroma_h;
+    if (av_pix_fmt_get_chroma_sub_sample(pixel_format, &chroma_w, &chroma_h) == 0) {
+        if (chroma_w == 1 && chroma_h == 1) {
+            return (chroma_location == AVCHROMA_LOC_LEFT)
+                       ? VPX_SUBSAMPLING_420_VERTICAL
+                       : VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA;
+        } else if (chroma_w == 1 && chroma_h == 0) {
+            return VPX_SUBSAMPLING_422;
+        } else if (chroma_w == 0 && chroma_h == 0) {
+            return VPX_SUBSAMPLING_444;
+        }
+    }
+    av_log(s, AV_LOG_ERROR, "Unsupported pixel format (%d)\n", pixel_format);
+    return -1;
+}
+
+static int get_bit_depth(AVFormatContext *s, enum AVPixelFormat pixel_format)
+{
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixel_format);
+    if (desc == NULL) {
+        av_log(s, AV_LOG_ERROR, "Unsupported pixel format (%d)\n",
+               pixel_format);
+        return -1;
+    }
+    return desc->comp[0].depth;
+}
+
+static int get_vpx_transfer_function(
+    enum AVColorTransferCharacteristic transfer)
+{
+    return transfer == AVCOL_TRC_SMPTEST2084;
+}
+
+static int get_vpx_video_full_range_flag(enum AVColorRange color_range)
+{
+    return color_range == AVCOL_RANGE_JPEG;
+}
+
+int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
+                       AVCodecParameters *par)
+{
+    int profile = par->profile;
+    int level = par->level == FF_LEVEL_UNKNOWN ? 0 : par->level;
+    int bit_depth = get_bit_depth(s, par->format);
+    int vpx_color_space = get_vpx_color_space(s, par->color_space);
+    int vpx_chroma_subsampling =
+        get_vpx_chroma_subsampling(s, par->format, par->chroma_location);
+    int vpx_transfer_function = get_vpx_transfer_function(par->color_trc);
+    int vpx_video_full_range_flag =
+        get_vpx_video_full_range_flag(par->color_range);
+
+    if (bit_depth < 0 || vpx_color_space < 0 || vpx_chroma_subsampling < 0)
+        return AVERROR_INVALIDDATA;
+
+    if (profile == FF_PROFILE_UNKNOWN) {
+        if (vpx_chroma_subsampling == VPX_SUBSAMPLING_420_VERTICAL ||
+            vpx_chroma_subsampling == VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA) {
+            profile = (bit_depth == 8) ? FF_PROFILE_VP9_0 : FF_PROFILE_VP9_2;
+        } else {
+            profile = (bit_depth == 8) ? FF_PROFILE_VP9_1 : FF_PROFILE_VP9_3;
+        }
+    }
+
+    avio_w8(pb, profile);
+    avio_w8(pb, level);
+    avio_w8(pb, (bit_depth << 4) | vpx_color_space);
+    avio_w8(pb, (vpx_chroma_subsampling << 4) | (vpx_transfer_function << 1) |
+                    vpx_video_full_range_flag);
+
+    // vp9 does not have codec initialization data.
+    avio_wb16(pb, 0);
+    return 0;
+}
diff --git a/libavformat/vpcc.h b/libavformat/vpcc.h
new file mode 100644
index 0000000..184e857
--- /dev/null
+++ b/libavformat/vpcc.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Google Inc.
+ * Copyright (c) 2016 KongQun Yang (kqyang at google.com)
+ *
+ * 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
+ * internal header for VPx codec configuration utilities.
+ */
+
+#ifndef AVFORMAT_VPCC_H
+#define AVFORMAT_VPCC_H
+
+#include <stdint.h>
+#include "avio.h"
+#include "avformat.h"
+#include "libavcodec/avcodec.h"
+
+/**
+ * Writes VP codec configuration to the provided AVIOContext.
+ *
+ * @param s address of the AVFormatContext for the logging context.
+ * @param pb address of the AVIOContext where the vpcC shall be written.
+ * @param par address of the AVCodecParameters which contains codec information.
+ * @return >=0 in case of success, a negative value corresponding to an AVERROR
+ *         code in case of failure
+ */
+int ff_isom_write_vpcc(AVFormatContext *s, AVIOContext *pb,
+                       AVCodecParameters *par);
+
+#endif /* AVFORMAT_VPCC_H */
diff --git a/libavformat/vpk.c b/libavformat/vpk.c
index 7519049..bb9eabb 100644
--- a/libavformat/vpk.c
+++ b/libavformat/vpk.c
@@ -52,41 +52,41 @@ static int vpk_read_header(AVFormatContext *s)
     avio_skip(s->pb, 4);
     st->duration           = avio_rl32(s->pb) * 28 / 16;
     offset                 = avio_rl32(s->pb);
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = AV_CODEC_ID_ADPCM_PSX;
-    st->codec->block_align = avio_rl32(s->pb);
-    st->codec->sample_rate = avio_rl32(s->pb);
-    if (st->codec->sample_rate <= 0)
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_PSX;
+    st->codecpar->block_align = avio_rl32(s->pb);
+    st->codecpar->sample_rate = avio_rl32(s->pb);
+    if (st->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
-    st->codec->channels    = avio_rl32(s->pb);
-    if (st->codec->channels <= 0)
+    st->codecpar->channels    = avio_rl32(s->pb);
+    if (st->codecpar->channels <= 0)
         return AVERROR_INVALIDDATA;
-    samples_per_block      = ((st->codec->block_align / st->codec->channels) * 28) / 16;
+    samples_per_block      = ((st->codecpar->block_align / st->codecpar->channels) * 28) / 16;
     if (samples_per_block <= 0)
         return AVERROR_INVALIDDATA;
     vpk->block_count       = (st->duration + (samples_per_block - 1)) / samples_per_block;
-    vpk->last_block_size   = (st->duration % samples_per_block) * 16 * st->codec->channels / 28;
+    vpk->last_block_size   = (st->duration % samples_per_block) * 16 * st->codecpar->channels / 28;
     avio_skip(s->pb, offset - avio_tell(s->pb));
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
 
 static int vpk_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     VPKDemuxContext *vpk = s->priv_data;
     int ret, i;
 
     vpk->current_block++;
     if (vpk->current_block == vpk->block_count) {
-        unsigned size = vpk->last_block_size / codec->channels;
-        unsigned skip = (codec->block_align - vpk->last_block_size) / codec->channels;
+        unsigned size = vpk->last_block_size / par->channels;
+        unsigned skip = (par->block_align - vpk->last_block_size) / par->channels;
 
         ret = av_new_packet(pkt, vpk->last_block_size);
         if (ret < 0)
             return ret;
-        for (i = 0; i < codec->channels; i++) {
+        for (i = 0; i < par->channels; i++) {
             ret = avio_read(s->pb, pkt->data + i * size, size);
             avio_skip(s->pb, skip);
             if (ret != size) {
@@ -97,7 +97,7 @@ static int vpk_read_packet(AVFormatContext *s, AVPacket *pkt)
         }
         pkt->stream_index = 0;
     } else if (vpk->current_block < vpk->block_count) {
-        ret = av_get_packet(s->pb, pkt, codec->block_align);
+        ret = av_get_packet(s->pb, pkt, par->block_align);
         pkt->stream_index = 0;
     } else {
         return AVERROR_EOF;
diff --git a/libavformat/vplayerdec.c b/libavformat/vplayerdec.c
index 860b778..897c408 100644
--- a/libavformat/vplayerdec.c
+++ b/libavformat/vplayerdec.c
@@ -36,7 +36,8 @@ static int vplayer_probe(AVProbeData *p)
     char c;
     const unsigned char *ptr = p->buf;
 
-    if (sscanf(ptr, "%*d:%*d:%*d.%*d%c", &c) == 1 && strchr(": =", c))
+    if ((sscanf(ptr, "%*d:%*d:%*d.%*d%c", &c) == 1 ||
+         sscanf(ptr, "%*d:%*d:%*d%c",     &c) == 1) && strchr(": =", c))
         return AVPROBE_SCORE_MAX;
     return 0;
 }
@@ -44,12 +45,12 @@ static int vplayer_probe(AVProbeData *p)
 static int64_t read_ts(char **line)
 {
     char c;
-    int hh, mm, ss, ms, len;
+    int hh, mm, ss, ms, n, len;
 
-    if (sscanf(*line, "%d:%d:%d.%d%c%n",
-               &hh, &mm, &ss, &ms, &c, &len) >= 5) {
+    if (((n = sscanf(*line, "%d:%d:%d.%d%c%n", &hh, &mm, &ss, &ms, &c, &len)) >= 5 ||
+         (n = sscanf(*line, "%d:%d:%d%c%n",    &hh, &mm, &ss,      &c, &len)) >= 4) && strchr(": =", c)) {
         *line += len;
-        return (hh*3600LL + mm*60LL + ss) * 100LL + ms;
+        return (hh*3600LL + mm*60LL + ss) * 100LL + (n < 5 ? 0 : ms);
     }
     return AV_NOPTS_VALUE;
 }
@@ -62,8 +63,8 @@ static int vplayer_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 100);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_VPLAYER;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_VPLAYER;
 
     while (!avio_feof(s->pb)) {
         char line[4096];
diff --git a/libavformat/vqf.c b/libavformat/vqf.c
index 3c897e1..969fbef 100644
--- a/libavformat/vqf.c
+++ b/libavformat/vqf.c
@@ -107,8 +107,8 @@ static int vqf_read_header(AVFormatContext *s)
 
     header_size = avio_rb32(s->pb);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id   = AV_CODEC_ID_TWINVQ;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id   = AV_CODEC_ID_TWINVQ;
     st->start_time = 0;
 
     do {
@@ -130,17 +130,17 @@ static int vqf_read_header(AVFormatContext *s)
         switch(chunk_tag){
         case MKTAG('C','O','M','M'):
             avio_read(s->pb, comm_chunk, 12);
-            st->codec->channels = AV_RB32(comm_chunk    ) + 1;
+            st->codecpar->channels = AV_RB32(comm_chunk    ) + 1;
             read_bitrate        = AV_RB32(comm_chunk + 4);
             rate_flag           = AV_RB32(comm_chunk + 8);
             avio_skip(s->pb, len-12);
 
-            if (st->codec->channels <= 0) {
+            if (st->codecpar->channels <= 0) {
                 av_log(s, AV_LOG_ERROR, "Invalid number of channels\n");
                 return AVERROR_INVALIDDATA;
             }
 
-            st->codec->bit_rate              = read_bitrate*1000;
+            st->codecpar->bit_rate = read_bitrate * 1000;
             break;
         case MKTAG('D','S','I','Z'): // size of compressed data
         {
@@ -169,32 +169,32 @@ static int vqf_read_header(AVFormatContext *s)
         av_log(s, AV_LOG_ERROR, "COMM tag not found!\n");
         return -1;
     case 44:
-        st->codec->sample_rate = 44100;
+        st->codecpar->sample_rate = 44100;
         break;
     case 22:
-        st->codec->sample_rate = 22050;
+        st->codecpar->sample_rate = 22050;
         break;
     case 11:
-        st->codec->sample_rate = 11025;
+        st->codecpar->sample_rate = 11025;
         break;
     default:
         if (rate_flag < 8 || rate_flag > 44) {
             av_log(s, AV_LOG_ERROR, "Invalid rate flag %d\n", rate_flag);
             return AVERROR_INVALIDDATA;
         }
-        st->codec->sample_rate = rate_flag*1000;
+        st->codecpar->sample_rate = rate_flag*1000;
         break;
     }
 
-    if (read_bitrate / st->codec->channels <  8 ||
-        read_bitrate / st->codec->channels > 48) {
+    if (read_bitrate / st->codecpar->channels <  8 ||
+        read_bitrate / st->codecpar->channels > 48) {
         av_log(s, AV_LOG_ERROR, "Invalid bitrate per channel %d\n",
-               read_bitrate / st->codec->channels);
+               read_bitrate / st->codecpar->channels);
         return AVERROR_INVALIDDATA;
     }
 
-    switch (((st->codec->sample_rate/1000) << 8) +
-            read_bitrate/st->codec->channels) {
+    switch (((st->codecpar->sample_rate/1000) << 8) +
+            read_bitrate/st->codecpar->channels) {
     case (11<<8) + 8 :
     case (8 <<8) + 8 :
     case (11<<8) + 10:
@@ -212,16 +212,16 @@ static int vqf_read_header(AVFormatContext *s)
         break;
     default:
         av_log(s, AV_LOG_ERROR, "Mode not supported: %d Hz, %"PRId64" kb/s.\n",
-               st->codec->sample_rate, (int64_t)st->codec->bit_rate);
+               st->codecpar->sample_rate, (int64_t)st->codecpar->bit_rate);
         return -1;
     }
-    c->frame_bit_len = st->codec->bit_rate*size/st->codec->sample_rate;
-    avpriv_set_pts_info(st, 64, size, st->codec->sample_rate);
+    c->frame_bit_len = st->codecpar->bit_rate*size/st->codecpar->sample_rate;
+    avpriv_set_pts_info(st, 64, size, st->codecpar->sample_rate);
 
     /* put first 12 bytes of COMM chunk in extradata */
-    if (ff_alloc_extradata(st->codec, 12))
+    if (ff_alloc_extradata(st->codecpar, 12))
         return AVERROR(ENOMEM);
-    memcpy(st->codec->extradata, comm_chunk, 12);
+    memcpy(st->codecpar->extradata, comm_chunk, 12);
 
     ff_metadata_conv_ctx(s, NULL, vqf_metadata_conv);
 
@@ -265,7 +265,7 @@ static int vqf_read_seek(AVFormatContext *s,
     int64_t pos;
 
     st = s->streams[stream_index];
-    pos = av_rescale_rnd(timestamp * st->codec->bit_rate,
+    pos = av_rescale_rnd(timestamp * st->codecpar->bit_rate,
                          st->time_base.num,
                          st->time_base.den * (int64_t)c->frame_bit_len,
                          (flags & AVSEEK_FLAG_BACKWARD) ?
@@ -273,7 +273,7 @@ static int vqf_read_seek(AVFormatContext *s,
     pos *= c->frame_bit_len;
 
     st->cur_dts = av_rescale(pos, st->time_base.den,
-                             st->codec->bit_rate * (int64_t)st->time_base.num);
+                             st->codecpar->bit_rate * (int64_t)st->time_base.num);
 
     if ((ret = avio_seek(s->pb, ((pos-7) >> 3) + s->internal->data_offset, SEEK_SET)) < 0)
         return ret;
diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c
index d95596f..7176cd6 100644
--- a/libavformat/wavdec.c
+++ b/libavformat/wavdec.c
@@ -60,6 +60,41 @@ typedef struct WAVDemuxContext {
     int rifx; // RIFX: integer byte order for parameters is big endian
 } WAVDemuxContext;
 
+static void set_spdif(AVFormatContext *s, WAVDemuxContext *wav)
+{
+    if (CONFIG_SPDIF_DEMUXER && s->streams[0]->codecpar->codec_tag == 1) {
+        enum AVCodecID codec;
+        uint8_t *buf = NULL;
+        int len = 1<<16;
+        int ret = ffio_ensure_seekback(s->pb, len);
+        int64_t pos = avio_tell(s->pb);
+
+        if (ret < 0)
+            goto end;
+
+        buf = av_malloc(len);
+        if (!buf) {
+            ret = AVERROR(ENOMEM);
+            goto end;
+        }
+
+        len = ret = avio_read(s->pb, buf, len);
+        if (ret < 0)
+            goto end;
+
+        ret = ff_spdif_probe(buf, len, &codec);
+        if (ret > AVPROBE_SCORE_EXTENSION) {
+            s->streams[0]->codecpar->codec_id = codec;
+            wav->spdif = 1;
+        }
+end:
+        avio_seek(s->pb, pos, SEEK_SET);
+        if (ret < 0)
+            av_log(s, AV_LOG_WARNING, "Cannot check for SPDIF\n");
+        av_free(buf);
+    }
+}
+
 #if CONFIG_WAV_DEMUXER
 
 static int64_t next_tag(AVIOContext *pb, uint32_t *tag, int big_endian)
@@ -117,7 +152,7 @@ static int wav_probe(AVProbeData *p)
 
 static void handle_stream_probing(AVStream *st)
 {
-    if (st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S16LE) {
         st->request_probe = AVPROBE_SCORE_EXTENSION;
         st->probe_packets = FFMIN(st->probe_packets, 32);
     }
@@ -134,14 +169,14 @@ static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st)
     if (!*st)
         return AVERROR(ENOMEM);
 
-    ret = ff_get_wav_header(s, pb, (*st)->codec, size, wav->rifx);
+    ret = ff_get_wav_header(s, pb, (*st)->codecpar, size, wav->rifx);
     if (ret < 0)
         return ret;
     handle_stream_probing(*st);
 
     (*st)->need_parsing = AVSTREAM_PARSE_FULL_RAW;
 
-    avpriv_set_pts_info(*st, 64, 1, (*st)->codec->sample_rate);
+    avpriv_set_pts_info(*st, 64, 1, (*st)->codecpar->sample_rate);
 
     return 0;
 }
@@ -158,16 +193,16 @@ static int wav_parse_xma2_tag(AVFormatContext *s, int64_t size, AVStream **st)
     if (!*st)
         return AVERROR(ENOMEM);
 
-    (*st)->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    (*st)->codec->codec_id   = AV_CODEC_ID_XMA2;
-    (*st)->need_parsing      = AVSTREAM_PARSE_FULL_RAW;
+    (*st)->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    (*st)->codecpar->codec_id   = AV_CODEC_ID_XMA2;
+    (*st)->need_parsing         = AVSTREAM_PARSE_FULL_RAW;
 
     avio_skip(pb, 1);
     num_streams = avio_r8(pb);
     if (size < 40 + num_streams * 4)
         return AVERROR_INVALIDDATA;
     avio_skip(pb, 10);
-    (*st)->codec->sample_rate = avio_rb32(pb);
+    (*st)->codecpar->sample_rate = avio_rb32(pb);
     avio_skip(pb, 12);
     (*st)->duration = avio_rb32(pb);
     avio_skip(pb, 8);
@@ -176,15 +211,15 @@ static int wav_parse_xma2_tag(AVFormatContext *s, int64_t size, AVStream **st)
         channels += avio_r8(pb);
         avio_skip(pb, 3);
     }
-    (*st)->codec->channels = channels;
+    (*st)->codecpar->channels = channels;
 
-    if ((*st)->codec->channels <= 0 || (*st)->codec->sample_rate <= 0)
+    if ((*st)->codecpar->channels <= 0 || (*st)->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
 
-    avpriv_set_pts_info(*st, 64, 1, (*st)->codec->sample_rate);
-    if (ff_alloc_extradata((*st)->codec, 34))
+    avpriv_set_pts_info(*st, 64, 1, (*st)->codecpar->sample_rate);
+    if (ff_alloc_extradata((*st)->codecpar, 34))
         return AVERROR(ENOMEM);
-    memset((*st)->codec->extradata, 0, 34);
+    memset((*st)->codecpar->extradata, 0, 34);
 
     return 0;
 }
@@ -430,11 +465,11 @@ static int wav_read_header(AVFormatContext *s)
                 return AVERROR(ENOMEM);
             avio_r8(pb);
             vst->id = 1;
-            vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-            vst->codec->codec_id = AV_CODEC_ID_SMVJPEG;
-            vst->codec->width  = avio_rl24(pb);
-            vst->codec->height = avio_rl24(pb);
-            if (ff_alloc_extradata(vst->codec, 4)) {
+            vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+            vst->codecpar->codec_id = AV_CODEC_ID_SMVJPEG;
+            vst->codecpar->width  = avio_rl24(pb);
+            vst->codecpar->height = avio_rl24(pb);
+            if (ff_alloc_extradata(vst->codecpar, 4)) {
                 av_log(s, AV_LOG_ERROR, "Could not allocate extradata.\n");
                 return AVERROR(ENOMEM);
             }
@@ -451,7 +486,7 @@ static int wav_read_header(AVFormatContext *s)
                 av_log(s, AV_LOG_ERROR, "too many frames per jpeg\n");
                 return AVERROR_INVALIDDATA;
             }
-            AV_WL32(vst->codec->extradata, wav->smv_frames_per_jpeg);
+            AV_WL32(vst->codecpar->extradata, wav->smv_frames_per_jpeg);
             wav->smv_cur_pt = 0;
             goto break_loop;
         case MKTAG('L', 'I', 'S', 'T'):
@@ -491,36 +526,36 @@ break_loop:
         data_size = 0;
     }
 
-    if (   st->codec->bit_rate > 0 && data_size > 0
-        && st->codec->sample_rate > 0
-        && sample_count > 0 && st->codec->channels > 1
-        && sample_count % st->codec->channels == 0) {
-        if (fabs(8.0 * data_size * st->codec->channels * st->codec->sample_rate /
-            sample_count /st->codec->bit_rate - 1.0) < 0.3)
-            sample_count /= st->codec->channels;
+    if (   st->codecpar->bit_rate > 0 && data_size > 0
+        && st->codecpar->sample_rate > 0
+        && sample_count > 0 && st->codecpar->channels > 1
+        && sample_count % st->codecpar->channels == 0) {
+        if (fabs(8.0 * data_size * st->codecpar->channels * st->codecpar->sample_rate /
+            sample_count /st->codecpar->bit_rate - 1.0) < 0.3)
+            sample_count /= st->codecpar->channels;
     }
 
-    if (   data_size > 0 && sample_count && st->codec->channels
-        && (data_size << 3) / sample_count / st->codec->channels > st->codec->bits_per_coded_sample  + 1) {
+    if (   data_size > 0 && sample_count && st->codecpar->channels
+        && (data_size << 3) / sample_count / st->codecpar->channels > st->codecpar->bits_per_coded_sample  + 1) {
         av_log(s, AV_LOG_WARNING, "ignoring wrong sample_count %"PRId64"\n", sample_count);
         sample_count = 0;
     }
 
     /* G.729 hack (for Ticket4577)
      * FIXME: Come up with cleaner, more general solution */
-    if (st->codec->codec_id == AV_CODEC_ID_G729 && sample_count && (data_size << 3) > sample_count) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_G729 && sample_count && (data_size << 3) > sample_count) {
         av_log(s, AV_LOG_WARNING, "ignoring wrong sample_count %"PRId64"\n", sample_count);
         sample_count = 0;
     }
 
-    if (!sample_count || av_get_exact_bits_per_sample(st->codec->codec_id) > 0)
-        if (   st->codec->channels
+    if (!sample_count || av_get_exact_bits_per_sample(st->codecpar->codec_id) > 0)
+        if (   st->codecpar->channels
             && data_size
-            && av_get_bits_per_sample(st->codec->codec_id)
+            && av_get_bits_per_sample(st->codecpar->codec_id)
             && wav->data_end <= avio_size(pb))
             sample_count = (data_size << 3)
                                   /
-                (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
+                (st->codecpar->channels * (uint64_t)av_get_bits_per_sample(st->codecpar->codec_id));
 
     if (sample_count)
         st->duration = sample_count;
@@ -528,6 +563,8 @@ break_loop:
     ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
     ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);
 
+    set_spdif(s, wav);
+
     return 0;
 }
 
@@ -561,18 +598,6 @@ static int wav_read_packet(AVFormatContext *s, AVPacket *pkt)
     AVStream *st;
     WAVDemuxContext *wav = s->priv_data;
 
-    if (CONFIG_SPDIF_DEMUXER && wav->spdif == 0 &&
-        s->streams[0]->codec->codec_tag == 1) {
-        enum AVCodecID codec;
-        ret = ff_spdif_probe(s->pb->buffer, s->pb->buf_end - s->pb->buffer,
-                             &codec);
-        if (ret > AVPROBE_SCORE_EXTENSION) {
-            s->streams[0]->codec->codec_id = codec;
-            wav->spdif = 1;
-        } else {
-            wav->spdif = -1;
-        }
-    }
     if (CONFIG_SPDIF_DEMUXER && wav->spdif == 1)
         return ff_spdif_read_packet(s, pkt);
 
@@ -643,10 +668,10 @@ smv_out:
     }
 
     size = MAX_SIZE;
-    if (st->codec->block_align > 1) {
-        if (size < st->codec->block_align)
-            size = st->codec->block_align;
-        size = (size / st->codec->block_align) * st->codec->block_align;
+    if (st->codecpar->block_align > 1) {
+        if (size < st->codecpar->block_align)
+            size = st->codecpar->block_align;
+        size = (size / st->codecpar->block_align) * st->codecpar->block_align;
     }
     size = FFMIN(size, left);
     ret  = av_get_packet(s->pb, pkt, size);
@@ -677,7 +702,7 @@ static int wav_read_seek(AVFormatContext *s,
     }
 
     st = s->streams[0];
-    switch (st->codec->codec_id) {
+    switch (st->codecpar->codec_id) {
     case AV_CODEC_ID_MP2:
     case AV_CODEC_ID_MP3:
     case AV_CODEC_ID_AC3:
@@ -767,12 +792,12 @@ static int w64_read_header(AVFormatContext *s)
 
         if (!memcmp(guid, ff_w64_guid_fmt, 16)) {
             /* subtract chunk header size - normal wav file doesn't count it */
-            ret = ff_get_wav_header(s, pb, st->codec, size - 24, 0);
+            ret = ff_get_wav_header(s, pb, st->codecpar, size - 24, 0);
             if (ret < 0)
                 return ret;
             avio_skip(pb, FFALIGN(size, INT64_C(8)) - size);
 
-            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+            avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
         } else if (!memcmp(guid, ff_w64_guid_fact, 16)) {
             int64_t samples;
 
@@ -833,6 +858,8 @@ static int w64_read_header(AVFormatContext *s)
 
     avio_seek(pb, data_ofs, SEEK_SET);
 
+    set_spdif(s, wav);
+
     return 0;
 }
 
diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c
index 0156f6e..a21d4c5 100644
--- a/libavformat/wavenc.c
+++ b/libavformat/wavenc.c
@@ -155,18 +155,19 @@ static av_cold void peak_free_buffers(AVFormatContext *s)
 static av_cold int peak_init_writer(AVFormatContext *s)
 {
     WAVMuxContext *wav = s->priv_data;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
-    if (enc->codec_id != AV_CODEC_ID_PCM_S8 &&
-        enc->codec_id != AV_CODEC_ID_PCM_S16LE &&
-        enc->codec_id != AV_CODEC_ID_PCM_U8 &&
-        enc->codec_id != AV_CODEC_ID_PCM_U16LE) {
+    if (par->codec_id != AV_CODEC_ID_PCM_S8 &&
+        par->codec_id != AV_CODEC_ID_PCM_S16LE &&
+        par->codec_id != AV_CODEC_ID_PCM_U8 &&
+        par->codec_id != AV_CODEC_ID_PCM_U16LE) {
+        AVCodec *codec = avcodec_find_decoder(s->streams[0]->codecpar->codec_id);
         av_log(s, AV_LOG_ERROR, "%s codec not supported for Peak Chunk\n",
-               s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
+               codec ? codec->name : "NONE");
         return -1;
     }
 
-    wav->peak_bps = av_get_bits_per_sample(enc->codec_id) / 8;
+    wav->peak_bps = av_get_bits_per_sample(par->codec_id) / 8;
 
     if (wav->peak_bps == 1 && wav->peak_format == PEAK_FORMAT_UINT16) {
         av_log(s, AV_LOG_ERROR,
@@ -174,8 +175,8 @@ static av_cold int peak_init_writer(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    wav->peak_maxpos = av_mallocz_array(enc->channels, sizeof(*wav->peak_maxpos));
-    wav->peak_maxneg = av_mallocz_array(enc->channels, sizeof(*wav->peak_maxneg));
+    wav->peak_maxpos = av_mallocz_array(par->channels, sizeof(*wav->peak_maxpos));
+    wav->peak_maxneg = av_mallocz_array(par->channels, sizeof(*wav->peak_maxneg));
     wav->peak_output = av_malloc(PEAK_BUFFER_SIZE);
     if (!wav->peak_maxpos || !wav->peak_maxneg || !wav->peak_output)
         goto nomem;
@@ -193,14 +194,14 @@ nomem:
 static void peak_write_frame(AVFormatContext *s)
 {
     WAVMuxContext *wav = s->priv_data;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int peak_of_peaks;
     int c;
 
     if (!wav->peak_output)
         return;
 
-    for (c = 0; c < enc->channels; c++) {
+    for (c = 0; c < par->channels; c++) {
         wav->peak_maxneg[c] = -wav->peak_maxneg[c];
 
         if (wav->peak_bps == 2 && wav->peak_format == PEAK_FORMAT_UINT8) {
@@ -256,7 +257,7 @@ static int peak_write_chunk(AVFormatContext *s)
 {
     WAVMuxContext *wav = s->priv_data;
     AVIOContext *pb = s->pb;
-    AVCodecContext *enc = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
     int64_t peak = ff_start_tag(s->pb, "levl");
     int64_t now0;
     time_t now_secs;
@@ -284,7 +285,7 @@ static int peak_write_chunk(AVFormatContext *s)
     avio_wl32(pb, wav->peak_format);            /* 8 or 16 bit */
     avio_wl32(pb, wav->peak_ppv);               /* positive and negative */
     avio_wl32(pb, wav->peak_block_size);        /* frames per value */
-    avio_wl32(pb, enc->channels);               /* number of channels */
+    avio_wl32(pb, par->channels);               /* number of channels */
     avio_wl32(pb, wav->peak_num_frames);        /* number of peak frames */
     avio_wl32(pb, wav->peak_pos_pop);           /* audio sample frame index */
     avio_wl32(pb, 128);                         /* equal to size of header */
@@ -333,8 +334,8 @@ static int wav_write_header(AVFormatContext *s)
     if (wav->write_peak != 2) {
         /* format header */
         fmt = ff_start_tag(pb, "fmt ");
-        if (ff_put_wav_header(pb, s->streams[0]->codec, 0) < 0) {
-            const AVCodecDescriptor *desc = avcodec_descriptor_get(s->streams[0]->codec->codec_id);
+        if (ff_put_wav_header(s, pb, s->streams[0]->codecpar, 0) < 0) {
+            const AVCodecDescriptor *desc = avcodec_descriptor_get(s->streams[0]->codecpar->codec_id);
             av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n",
                    desc ? desc->name : "unknown");
             return AVERROR(ENOSYS);
@@ -342,7 +343,7 @@ static int wav_write_header(AVFormatContext *s)
         ff_end_tag(pb, fmt);
     }
 
-    if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
+    if (s->streams[0]->codecpar->codec_tag != 0x01 /* hence for all other than PCM */
         && s->pb->seekable) {
         wav->fact_pos = ff_start_tag(pb, "fact");
         avio_wl32(pb, 0);
@@ -358,7 +359,7 @@ static int wav_write_header(AVFormatContext *s)
             return ret;
     }
 
-    avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
+    avpriv_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codecpar->sample_rate);
     wav->maxpts = wav->last_duration = 0;
     wav->minpts = INT64_MAX;
 
@@ -394,7 +395,7 @@ static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
                 wav->peak_maxpos[c] = FFMAX(wav->peak_maxpos[c], (int16_t)AV_RL16(pkt->data + i));
                 wav->peak_maxneg[c] = FFMIN(wav->peak_maxneg[c], (int16_t)AV_RL16(pkt->data + i));
             }
-            if (++c == s->streams[0]->codec->channels) {
+            if (++c == s->streams[0]->codecpar->channels) {
                 c = 0;
                 if (++wav->peak_block_pos == wav->peak_block_size) {
                     peak_write_frame(s);
@@ -453,10 +454,10 @@ static int wav_write_trailer(AVFormatContext *s)
         }
 
         number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration,
-                                       s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num,
+                                       s->streams[0]->codecpar->sample_rate * (int64_t)s->streams[0]->time_base.num,
                                        s->streams[0]->time_base.den);
 
-        if(s->streams[0]->codec->codec_tag != 0x01) {
+        if(s->streams[0]->codecpar->codec_tag != 0x01) {
             /* Update num_samps in fact chunk */
             avio_seek(pb, wav->fact_pos, SEEK_SET);
             if (rf64 || (wav->rf64 == RF64_AUTO && number_of_samples > UINT32_MAX)) {
@@ -574,14 +575,15 @@ static int w64_write_header(AVFormatContext *s)
     avio_wl64(pb, -1);
     avio_write(pb, ff_w64_guid_wave, sizeof(ff_w64_guid_wave));
     start_guid(pb, ff_w64_guid_fmt, &start);
-    if ((ret = ff_put_wav_header(pb, s->streams[0]->codec, 0)) < 0) {
+    if ((ret = ff_put_wav_header(s, pb, s->streams[0]->codecpar, 0)) < 0) {
+        AVCodec *codec = avcodec_find_decoder(s->streams[0]->codecpar->codec_id);
         av_log(s, AV_LOG_ERROR, "%s codec not supported\n",
-               s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
+               codec ? codec->name : "NONE");
         return ret;
     }
     end_guid(pb, start);
 
-    if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
+    if (s->streams[0]->codecpar->codec_tag != 0x01 /* hence for all other than PCM */
         && s->pb->seekable) {
         start_guid(pb, ff_w64_guid_fact, &wav->fact_pos);
         avio_wl64(pb, 0);
@@ -606,11 +608,11 @@ static int w64_write_trailer(AVFormatContext *s)
         avio_seek(pb, 16, SEEK_SET);
         avio_wl64(pb, file_size);
 
-        if (s->streams[0]->codec->codec_tag != 0x01) {
+        if (s->streams[0]->codecpar->codec_tag != 0x01) {
             int64_t number_of_samples;
 
             number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration,
-                                           s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num,
+                                           s->streams[0]->codecpar->sample_rate * (int64_t)s->streams[0]->time_base.num,
                                            s->streams[0]->time_base.den);
             avio_seek(pb, wav->fact_pos + 24, SEEK_SET);
             avio_wl64(pb, number_of_samples);
diff --git a/libavformat/wc3movie.c b/libavformat/wc3movie.c
index 04f8667..642dcbb 100644
--- a/libavformat/wc3movie.c
+++ b/libavformat/wc3movie.c
@@ -1,6 +1,6 @@
 /*
  * Wing Commander III Movie (.mve) File Demuxer
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -170,27 +170,27 @@ static int wc3_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
     wc3->video_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_XAN_WC3;
-    st->codec->codec_tag = 0;  /* no fourcc */
-    st->codec->width = wc3->width;
-    st->codec->height = wc3->height;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_XAN_WC3;
+    st->codecpar->codec_tag = 0;  /* no fourcc */
+    st->codecpar->width = wc3->width;
+    st->codecpar->height = wc3->height;
 
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
     wc3->audio_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
-    st->codec->codec_tag = 1;
-    st->codec->channels = WC3_AUDIO_CHANNELS;
-    st->codec->channel_layout = AV_CH_LAYOUT_MONO;
-    st->codec->bits_per_coded_sample = WC3_AUDIO_BITS;
-    st->codec->sample_rate = WC3_SAMPLE_RATE;
-    st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
-        st->codec->bits_per_coded_sample;
-    st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
+    st->codecpar->codec_tag = 1;
+    st->codecpar->channels = WC3_AUDIO_CHANNELS;
+    st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
+    st->codecpar->bits_per_coded_sample = WC3_AUDIO_BITS;
+    st->codecpar->sample_rate = WC3_SAMPLE_RATE;
+    st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate *
+        st->codecpar->bits_per_coded_sample;
+    st->codecpar->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
 
     return 0;
 }
diff --git a/libavformat/webm_chunk.c b/libavformat/webm_chunk.c
index 063eb3b..9db4fab 100644
--- a/libavformat/webm_chunk.c
+++ b/libavformat/webm_chunk.c
@@ -187,7 +187,7 @@ static int webm_chunk_write_packet(AVFormatContext *s, AVPacket *pkt)
     AVStream *st = s->streams[pkt->stream_index];
     int ret;
 
-    if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
         wc->duration_written += av_rescale_q(pkt->pts - wc->prev_pts,
                                              st->time_base,
                                              (AVRational) {1, 1000});
@@ -196,9 +196,9 @@ static int webm_chunk_write_packet(AVFormatContext *s, AVPacket *pkt)
 
     // For video, a new chunk is started only on key frames. For audio, a new
     // chunk is started based on chunk_duration.
-    if ((st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+    if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
          (pkt->flags & AV_PKT_FLAG_KEY)) ||
-        (st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
+        (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
          (pkt->pts == 0 || wc->duration_written >= wc->chunk_duration))) {
         wc->duration_written = 0;
         if ((ret = chunk_end(s)) < 0 || (ret = chunk_start(s)) < 0) {
diff --git a/libavformat/webmdashenc.c b/libavformat/webmdashenc.c
index 301c045..d4b3146 100644
--- a/libavformat/webmdashenc.c
+++ b/libavformat/webmdashenc.c
@@ -152,17 +152,17 @@ static int bitstream_switching(AVFormatContext *s, AdaptationSet *as) {
     int i;
     AVDictionaryEntry *gold_track_num = av_dict_get(s->streams[as->streams[0]]->metadata,
                                                     TRACK_NUMBER, NULL, 0);
-    AVCodecContext *gold_codec = s->streams[as->streams[0]]->codec;
+    AVCodecParameters *gold_par = s->streams[as->streams[0]]->codecpar;
     if (!gold_track_num) return 0;
     for (i = 1; i < as->nb_streams; i++) {
         AVDictionaryEntry *track_num = av_dict_get(s->streams[as->streams[i]]->metadata,
                                                    TRACK_NUMBER, NULL, 0);
-        AVCodecContext *codec = s->streams[as->streams[i]]->codec;
+        AVCodecParameters *par = s->streams[as->streams[i]]->codecpar;
         if (!track_num ||
             strncmp(gold_track_num->value, track_num->value, strlen(gold_track_num->value)) ||
-            gold_codec->codec_id != codec->codec_id ||
-            gold_codec->extradata_size != codec->extradata_size ||
-            memcmp(gold_codec->extradata, codec->extradata, codec->extradata_size)) {
+            gold_par->codec_id != par->codec_id ||
+            gold_par->extradata_size != par->extradata_size ||
+            memcmp(gold_par->extradata, par->extradata, par->extradata_size)) {
             return 0;
         }
     }
@@ -189,18 +189,18 @@ static int write_representation(AVFormatContext *s, AVStream *stream, char *id,
     avio_printf(s->pb, "<Representation id=\"%s\"", id);
     // FIXME: For live, This should be obtained from the input file or as an AVOption.
     avio_printf(s->pb, " bandwidth=\"%s\"",
-                w->is_live ? (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO ? "128000" : "1000000") : bandwidth->value);
-    if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO && output_width)
-        avio_printf(s->pb, " width=\"%d\"", stream->codec->width);
-    if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO && output_height)
-        avio_printf(s->pb, " height=\"%d\"", stream->codec->height);
-    if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO && output_sample_rate)
-        avio_printf(s->pb, " audioSamplingRate=\"%d\"", stream->codec->sample_rate);
+                w->is_live ? (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? "128000" : "1000000") : bandwidth->value);
+    if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && output_width)
+        avio_printf(s->pb, " width=\"%d\"", stream->codecpar->width);
+    if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && output_height)
+        avio_printf(s->pb, " height=\"%d\"", stream->codecpar->height);
+    if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && output_sample_rate)
+        avio_printf(s->pb, " audioSamplingRate=\"%d\"", stream->codecpar->sample_rate);
     if (w->is_live) {
         // For live streams, Codec and Mime Type always go in the Representation tag.
-        avio_printf(s->pb, " codecs=\"%s\"", get_codec_name(stream->codec->codec_id));
+        avio_printf(s->pb, " codecs=\"%s\"", get_codec_name(stream->codecpar->codec_id));
         avio_printf(s->pb, " mimeType=\"%s/webm\"",
-                    stream->codec->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
+                    stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
         // For live streams, subsegments always start with key frames. So this
         // is always 1.
         avio_printf(s->pb, " startsWithSAP=\"1\"");
@@ -224,9 +224,9 @@ static int write_representation(AVFormatContext *s, AVStream *stream, char *id,
 static int check_matching_width(AVFormatContext *s, AdaptationSet *as) {
     int first_width, i;
     if (as->nb_streams < 2) return 1;
-    first_width = s->streams[as->streams[0]]->codec->width;
+    first_width = s->streams[as->streams[0]]->codecpar->width;
     for (i = 1; i < as->nb_streams; i++)
-        if (first_width != s->streams[as->streams[i]]->codec->width)
+        if (first_width != s->streams[as->streams[i]]->codecpar->width)
           return 0;
     return 1;
 }
@@ -237,9 +237,9 @@ static int check_matching_width(AVFormatContext *s, AdaptationSet *as) {
 static int check_matching_height(AVFormatContext *s, AdaptationSet *as) {
     int first_height, i;
     if (as->nb_streams < 2) return 1;
-    first_height = s->streams[as->streams[0]]->codec->height;
+    first_height = s->streams[as->streams[0]]->codecpar->height;
     for (i = 1; i < as->nb_streams; i++)
-        if (first_height != s->streams[as->streams[i]]->codec->height)
+        if (first_height != s->streams[as->streams[i]]->codecpar->height)
           return 0;
     return 1;
 }
@@ -250,9 +250,9 @@ static int check_matching_height(AVFormatContext *s, AdaptationSet *as) {
 static int check_matching_sample_rate(AVFormatContext *s, AdaptationSet *as) {
     int first_sample_rate, i;
     if (as->nb_streams < 2) return 1;
-    first_sample_rate = s->streams[as->streams[0]]->codec->sample_rate;
+    first_sample_rate = s->streams[as->streams[0]]->codecpar->sample_rate;
     for (i = 1; i < as->nb_streams; i++)
-        if (first_sample_rate != s->streams[as->streams[i]]->codec->sample_rate)
+        if (first_sample_rate != s->streams[as->streams[i]]->codecpar->sample_rate)
           return 0;
     return 1;
 }
@@ -319,7 +319,7 @@ static int write_adaptation_set(AVFormatContext *s, int as_index)
 {
     WebMDashMuxContext *w = s->priv_data;
     AdaptationSet *as = &w->as[as_index];
-    AVCodecContext *codec = s->streams[as->streams[0]]->codec;
+    AVCodecParameters *par = s->streams[as->streams[0]]->codecpar;
     AVDictionaryEntry *lang;
     int i;
     static const char boolean[2][6] = { "false", "true" };
@@ -330,7 +330,7 @@ static int write_adaptation_set(AVFormatContext *s, int as_index)
     // on their respective Representation tag. For live streams, they always go
     // in the Representation tag.
     int width_in_as = 1, height_in_as = 1, sample_rate_in_as = 1;
-    if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (par->codec_type == AVMEDIA_TYPE_VIDEO) {
       width_in_as = !w->is_live && check_matching_width(s, as);
       height_in_as = !w->is_live && check_matching_height(s, as);
     } else {
@@ -339,18 +339,18 @@ static int write_adaptation_set(AVFormatContext *s, int as_index)
 
     avio_printf(s->pb, "<AdaptationSet id=\"%s\"", as->id);
     avio_printf(s->pb, " mimeType=\"%s/webm\"",
-                codec->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
-    avio_printf(s->pb, " codecs=\"%s\"", get_codec_name(codec->codec_id));
+                par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
+    avio_printf(s->pb, " codecs=\"%s\"", get_codec_name(par->codec_id));
 
     lang = av_dict_get(s->streams[as->streams[0]]->metadata, "language", NULL, 0);
     if (lang) avio_printf(s->pb, " lang=\"%s\"", lang->value);
 
-    if (codec->codec_type == AVMEDIA_TYPE_VIDEO && width_in_as)
-        avio_printf(s->pb, " width=\"%d\"", codec->width);
-    if (codec->codec_type == AVMEDIA_TYPE_VIDEO && height_in_as)
-        avio_printf(s->pb, " height=\"%d\"", codec->height);
-    if (codec->codec_type == AVMEDIA_TYPE_AUDIO && sample_rate_in_as)
-        avio_printf(s->pb, " audioSamplingRate=\"%d\"", codec->sample_rate);
+    if (par->codec_type == AVMEDIA_TYPE_VIDEO && width_in_as)
+        avio_printf(s->pb, " width=\"%d\"", par->width);
+    if (par->codec_type == AVMEDIA_TYPE_VIDEO && height_in_as)
+        avio_printf(s->pb, " height=\"%d\"", par->height);
+    if (par->codec_type == AVMEDIA_TYPE_AUDIO && sample_rate_in_as)
+        avio_printf(s->pb, " audioSamplingRate=\"%d\"", par->sample_rate);
 
     avio_printf(s->pb, " bitstreamSwitching=\"%s\"",
                 boolean[bitstream_switching(s, as)]);
@@ -374,7 +374,7 @@ static int write_adaptation_set(AVFormatContext *s, int as_index)
                                  &media_pattern);
         if (ret) return ret;
         avio_printf(s->pb, "<ContentComponent id=\"1\" type=\"%s\"/>\n",
-                    codec->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
+                    par->codec_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
         avio_printf(s->pb, "<SegmentTemplate");
         avio_printf(s->pb, " timescale=\"1000\"");
         avio_printf(s->pb, " duration=\"%d\"", w->chunk_duration);
diff --git a/libavformat/webpenc.c b/libavformat/webpenc.c
index 2a21730..2e0147c 100644
--- a/libavformat/webpenc.c
+++ b/libavformat/webpenc.c
@@ -42,7 +42,7 @@ static int webp_write_header(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
     st = s->streams[0];
-    if (st->codec->codec_id != AV_CODEC_ID_WEBP) {
+    if (st->codecpar->codec_id != AV_CODEC_ID_WEBP) {
         av_log(s, AV_LOG_ERROR, "Only WebP is supported\n");
         return AVERROR(EINVAL);
     }
@@ -115,8 +115,8 @@ static int flush(AVFormatContext *s, int trailer, int64_t pts)
                 avio_wl32(s->pb, 10);
                 avio_w8(s->pb, flags);
                 avio_wl24(s->pb, 0);
-                avio_wl24(s->pb, st->codec->width - 1);
-                avio_wl24(s->pb, st->codec->height - 1);
+                avio_wl24(s->pb, st->codecpar->width - 1);
+                avio_wl24(s->pb, st->codecpar->height - 1);
             }
             if (!trailer) {
                 avio_write(s->pb, "ANIM", 4);
@@ -131,8 +131,8 @@ static int flush(AVFormatContext *s, int trailer, int64_t pts)
             avio_wl32(s->pb, 16 + w->last_pkt.size - skip);
             avio_wl24(s->pb, 0);
             avio_wl24(s->pb, 0);
-            avio_wl24(s->pb, st->codec->width - 1);
-            avio_wl24(s->pb, st->codec->height - 1);
+            avio_wl24(s->pb, st->codecpar->width - 1);
+            avio_wl24(s->pb, st->codecpar->height - 1);
             if (w->last_pkt.pts != AV_NOPTS_VALUE && pts != AV_NOPTS_VALUE) {
                 avio_wl24(s->pb, pts - w->last_pkt.pts);
             } else
diff --git a/libavformat/webvttdec.c b/libavformat/webvttdec.c
index 47a3255..0aeb8a6 100644
--- a/libavformat/webvttdec.c
+++ b/libavformat/webvttdec.c
@@ -67,8 +67,8 @@ static int webvtt_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
     avpriv_set_pts_info(st, 64, 1, 1000);
-    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
-    st->codec->codec_id   = AV_CODEC_ID_WEBVTT;
+    st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codecpar->codec_id   = AV_CODEC_ID_WEBVTT;
     st->disposition |= webvtt->kind;
 
     av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED);
diff --git a/libavformat/webvttenc.c b/libavformat/webvttenc.c
index c386538..4827de0 100644
--- a/libavformat/webvttenc.c
+++ b/libavformat/webvttenc.c
@@ -46,10 +46,10 @@ static void webvtt_write_time(AVIOContext *pb, int64_t millisec)
 static int webvtt_write_header(AVFormatContext *ctx)
 {
     AVStream     *s = ctx->streams[0];
-    AVCodecContext *avctx = ctx->streams[0]->codec;
+    AVCodecParameters *par = ctx->streams[0]->codecpar;
     AVIOContext *pb = ctx->pb;
 
-    if (ctx->nb_streams != 1 || avctx->codec_id != AV_CODEC_ID_WEBVTT) {
+    if (ctx->nb_streams != 1 || par->codec_id != AV_CODEC_ID_WEBVTT) {
         av_log(ctx, AV_LOG_ERROR, "Exactly one WebVTT stream is needed.\n");
         return AVERROR(EINVAL);
     }
diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c
index 6d8dbdb..4750167 100644
--- a/libavformat/westwood_aud.c
+++ b/libavformat/westwood_aud.c
@@ -1,6 +1,6 @@
 /*
  * Westwood Studios AUD Format Demuxer
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -105,23 +105,23 @@ static int wsaud_read_header(AVFormatContext *s)
             avpriv_request_sample(s, "Stereo WS-SND1");
             return AVERROR_PATCHWELCOME;
         }
-        st->codec->codec_id = AV_CODEC_ID_WESTWOOD_SND1;
+        st->codecpar->codec_id = AV_CODEC_ID_WESTWOOD_SND1;
         break;
     case 99:
-        st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;
-        st->codec->bits_per_coded_sample = 4;
-        st->codec->bit_rate = channels * sample_rate * 4;
+        st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;
+        st->codecpar->bits_per_coded_sample = 4;
+        st->codecpar->bit_rate = channels * sample_rate * 4;
         break;
     default:
         avpriv_request_sample(s, "Unknown codec: %d", codec);
         return AVERROR_PATCHWELCOME;
     }
     avpriv_set_pts_info(st, 64, 1, sample_rate);
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->channels    = channels;
-    st->codec->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO :
-                                                AV_CH_LAYOUT_STEREO;
-    st->codec->sample_rate = sample_rate;
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->channels    = channels;
+    st->codecpar->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO :
+                                                   AV_CH_LAYOUT_STEREO;
+    st->codecpar->sample_rate = sample_rate;
 
     return 0;
 }
@@ -145,7 +145,7 @@ static int wsaud_read_packet(AVFormatContext *s,
 
     chunk_size = AV_RL16(&preamble[0]);
 
-    if (st->codec->codec_id == AV_CODEC_ID_WESTWOOD_SND1) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_WESTWOOD_SND1) {
         /* For Westwood SND1 audio we need to add the output size and input
            size to the start of the packet to match what is in VQA.
            Specifically, this is needed to signal when a packet should be
@@ -165,7 +165,7 @@ static int wsaud_read_packet(AVFormatContext *s,
             return AVERROR(EIO);
 
         /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */
-        pkt->duration = (chunk_size * 2) / st->codec->channels;
+        pkt->duration = (chunk_size * 2) / st->codecpar->channels;
     }
     pkt->stream_index = st->index;
 
diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c
index 546164c..3635c6a 100644
--- a/libavformat/westwood_vqa.c
+++ b/libavformat/westwood_vqa.c
@@ -1,6 +1,6 @@
 /*
  * Westwood Studios VQA Format Demuxer
- * Copyright (c) 2003 The FFmpeg Project
+ * Copyright (c) 2003 The FFmpeg project
  *
  * This file is part of FFmpeg.
  *
@@ -93,19 +93,19 @@ static int wsvqa_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
     st->start_time = 0;
     wsvqa->video_stream_index = st->index;
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id = AV_CODEC_ID_WS_VQA;
-    st->codec->codec_tag = 0;  /* no fourcc */
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id = AV_CODEC_ID_WS_VQA;
+    st->codecpar->codec_tag = 0;  /* no fourcc */
 
     /* skip to the start of the VQA header */
     avio_seek(pb, 20, SEEK_SET);
 
     /* the VQA header needs to go to the decoder */
-    if (ff_get_extradata(st->codec, pb, VQA_HEADER_SIZE) < 0)
+    if (ff_get_extradata(s, st->codecpar, pb, VQA_HEADER_SIZE) < 0)
         return AVERROR(ENOMEM);
-    header = st->codec->extradata;
-    st->codec->width = AV_RL16(&header[6]);
-    st->codec->height = AV_RL16(&header[8]);
+    header = st->codecpar->extradata;
+    st->codecpar->width = AV_RL16(&header[6]);
+    st->codecpar->height = AV_RL16(&header[8]);
     fps = header[12];
     st->nb_frames =
     st->duration  = AV_RL16(&header[4]);
@@ -131,7 +131,7 @@ static int wsvqa_read_header(AVFormatContext *s)
         chunk_tag = AV_RB32(&scratch[0]);
         chunk_size = AV_RB32(&scratch[4]);
 
-        /* catch any unknown header tags, for curiousity */
+        /* catch any unknown header tags, for curiosity */
         switch (chunk_tag) {
         case CINF_TAG:
         case CINH_TAG:
@@ -196,28 +196,28 @@ static int wsvqa_read_packet(AVFormatContext *s,
                         wsvqa->channels = 1;
                     if (!wsvqa->bps)
                         wsvqa->bps = 8;
-                    st->codec->sample_rate = wsvqa->sample_rate;
-                    st->codec->bits_per_coded_sample = wsvqa->bps;
-                    st->codec->channels = wsvqa->channels;
-                    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+                    st->codecpar->sample_rate = wsvqa->sample_rate;
+                    st->codecpar->bits_per_coded_sample = wsvqa->bps;
+                    st->codecpar->channels = wsvqa->channels;
+                    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
 
-                    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+                    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
                     switch (chunk_type) {
                     case SND0_TAG:
                         if (wsvqa->bps == 16)
-                            st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
+                            st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
                         else
-                            st->codec->codec_id = AV_CODEC_ID_PCM_U8;
+                            st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
                         break;
                     case SND1_TAG:
-                        st->codec->codec_id = AV_CODEC_ID_WESTWOOD_SND1;
+                        st->codecpar->codec_id = AV_CODEC_ID_WESTWOOD_SND1;
                         break;
                     case SND2_TAG:
-                        st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;
-                        if (ff_alloc_extradata(st->codec, 2))
+                        st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WS;
+                        if (ff_alloc_extradata(st->codecpar, 2))
                             return AVERROR(ENOMEM);
-                        AV_WL16(st->codec->extradata, wsvqa->version);
+                        AV_WL16(st->codecpar->extradata, wsvqa->version);
                         break;
                     }
                 }
diff --git a/libavformat/wsddec.c b/libavformat/wsddec.c
new file mode 100644
index 0000000..9ca0576
--- /dev/null
+++ b/libavformat/wsddec.c
@@ -0,0 +1,173 @@
+/*
+ * Wideband Single-bit Data (WSD) demuxer
+ * Copyright (c) 2014 Peter Ross
+ *
+ * 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/intreadwrite.h"
+#include "libavutil/timecode.h"
+#include "avformat.h"
+#include "internal.h"
+#include "rawdec.h"
+
+static int wsd_probe(AVProbeData *p)
+{
+    if (p->buf_size < 45 || memcmp(p->buf, "1bit", 4) ||
+        !AV_RB32(p->buf + 36) || !p->buf[44] ||
+        (p->buf[0] >= 0x10 && (AV_RB32(p->buf + 20) < 0x80 || AV_RB32(p->buf + 24) < 0x80)))
+       return 0;
+    return AVPROBE_SCORE_MAX;
+}
+
+static int empty_string(const char *buf, unsigned size)
+{
+    while (size--) {
+       if (*buf++ != ' ')
+           return 0;
+    }
+    return 1;
+}
+
+static int wsd_to_av_channel_layoyt(AVFormatContext *s, int bit)
+{
+    switch (bit) {
+    case 2: return AV_CH_BACK_RIGHT;
+    case 3:
+        avpriv_request_sample(s, "Rr-middle");
+        break;
+    case 4: return AV_CH_BACK_CENTER;
+    case 5:
+        avpriv_request_sample(s, "Lr-middle");
+        break;
+    case 6: return AV_CH_BACK_LEFT;
+    case 24: return AV_CH_LOW_FREQUENCY;
+    case 26: return AV_CH_FRONT_RIGHT;
+    case 27: return AV_CH_FRONT_RIGHT_OF_CENTER;
+    case 28: return AV_CH_FRONT_CENTER;
+    case 29: return AV_CH_FRONT_LEFT_OF_CENTER;
+    case 30: return AV_CH_FRONT_LEFT;
+    default:
+        av_log(s, AV_LOG_WARNING, "reserved channel assignment\n");
+        break;
+    }
+    return 0;
+}
+
+static int get_metadata(AVFormatContext *s, const char *const tag, const unsigned size)
+{
+    uint8_t *buf;
+    if (!(size + 1))
+        return AVERROR(ENOMEM);
+
+    buf = av_malloc(size + 1);
+    if (!buf)
+        return AVERROR(ENOMEM);
+
+    if (avio_read(s->pb, buf, size) != size) {
+        av_free(buf);
+        return AVERROR(EIO);
+    }
+
+    if (empty_string(buf, size)) {
+        av_free(buf);
+        return 0;
+    }
+
+    buf[size] = 0;
+    av_dict_set(&s->metadata, tag, buf, AV_DICT_DONT_STRDUP_VAL);
+    return 0;
+}
+
+static int wsd_read_header(AVFormatContext *s)
+{
+    AVIOContext *pb = s->pb;
+    AVStream *st;
+    int version;
+    uint32_t text_offset, data_offset, channel_assign;
+    char playback_time[AV_TIMECODE_STR_SIZE];
+
+    st = avformat_new_stream(s, NULL);
+    if (!st)
+        return AVERROR(ENOMEM);
+
+    avio_skip(pb, 8);
+    version = avio_r8(pb);
+    av_log(s, AV_LOG_DEBUG, "version: %i.%i\n", version >> 4, version & 0xF);
+    avio_skip(pb, 11);
+
+    if (version < 0x10) {
+        text_offset = 0x80;
+        data_offset = 0x800;
+        avio_skip(pb, 8);
+    } else {
+        text_offset = avio_rb32(pb);
+        data_offset = avio_rb32(pb);
+    }
+
+    avio_skip(pb, 4);
+    av_timecode_make_smpte_tc_string(playback_time, avio_rb32(pb), 0);
+    av_dict_set(&s->metadata, "playback_time", playback_time, 0);
+
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = s->iformat->raw_codec_id;
+    st->codecpar->sample_rate = avio_rb32(pb) / 8;
+    avio_skip(pb, 4);
+    st->codecpar->channels    = avio_r8(pb) & 0xF;
+    st->codecpar->bit_rate    = st->codecpar->channels * st->codecpar->sample_rate * 8LL;
+    if (!st->codecpar->channels)
+        return AVERROR_INVALIDDATA;
+
+    avio_skip(pb, 3);
+    channel_assign         = avio_rb32(pb);
+    if (!(channel_assign & 1)) {
+        int i;
+        for (i = 1; i < 32; i++)
+            if (channel_assign & (1 << i))
+                st->codecpar->channel_layout |= wsd_to_av_channel_layoyt(s, i);
+    }
+
+    avio_skip(pb, 16);
+    if (avio_rb32(pb))
+       avpriv_request_sample(s, "emphasis");
+
+    if (avio_seek(pb, text_offset, SEEK_SET) >= 0) {
+        get_metadata(s, "title",       128);
+        get_metadata(s, "composer",    128);
+        get_metadata(s, "song_writer", 128);
+        get_metadata(s, "artist",      128);
+        get_metadata(s, "album",       128);
+        get_metadata(s, "genre",        32);
+        get_metadata(s, "date",         32);
+        get_metadata(s, "location",     32);
+        get_metadata(s, "comment",     512);
+        get_metadata(s, "user",        512);
+    }
+
+    return avio_seek(pb, data_offset, SEEK_SET);
+}
+
+AVInputFormat ff_wsd_demuxer = {
+    .name         = "wsd",
+    .long_name    = NULL_IF_CONFIG_SMALL("Wideband Single-bit Data (WSD)"),
+    .read_probe   = wsd_probe,
+    .read_header  = wsd_read_header,
+    .read_packet  = ff_raw_read_partial_packet,
+    .extensions   = "wsd",
+    .flags        = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK,
+    .raw_codec_id = AV_CODEC_ID_DSD_MSBF,
+};
diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c
index 71deaf0..bd32d70 100644
--- a/libavformat/wtvdec.c
+++ b/libavformat/wtvdec.c
@@ -36,7 +36,7 @@
 #include "wtv.h"
 #include "mpegts.h"
 
-/* Macros for formating GUIDs */
+/* Macros for formatting GUIDs */
 #define PRI_PRETTY_GUID \
     "%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%02x%02x%02x%02x%02x%02x%02x%02x"
 #define ARG_PRETTY_GUID(g) \
@@ -44,9 +44,7 @@
 #define LEN_PRETTY_GUID 34
 
 /*
- *
  * File system routines
- *
  */
 
 typedef struct WtvFile {
@@ -311,9 +309,7 @@ static void wtvfile_close(AVIOContext *pb)
 }
 
 /*
- *
  * Main demuxer
- *
  */
 
 typedef struct WtvStream {
@@ -324,7 +320,7 @@ typedef struct WtvContext {
     AVIOContext *pb;       /**< timeline file */
     int64_t epoch;
     int64_t pts;             /**< pts for next data chunk */
-    int64_t last_valid_pts;  /**< latest valid pts, used for interative seeking */
+    int64_t last_valid_pts;  /**< latest valid pts, used for interactive seeking */
 
     /* maintain private seek index, as the AVIndexEntry->pos is relative to the
        start of the 'timeline' file, not the file system (AVFormatContext->pb) */
@@ -451,8 +447,8 @@ static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length)
     if (!st)
         goto done;
     av_dict_set(&st->metadata, "title", description, 0);
-    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id   = AV_CODEC_ID_MJPEG;
+    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id   = AV_CODEC_ID_MJPEG;
     st->id = -1;
     ret = av_get_packet(pb, &st->attached_pic, filesize);
     if (ret < 0)
@@ -569,7 +565,7 @@ static int parse_videoinfoheader2(AVFormatContext *s, AVStream *st)
     AVIOContext *pb = wtv->pb;
 
     avio_skip(pb, 72);  // picture aspect ratio is unreliable
-    st->codec->codec_tag = ff_get_bmp_header(pb, st, NULL);
+    st->codecpar->codec_tag = ff_get_bmp_header(pb, st, NULL);
 
     return 72 + 40;
 }
@@ -580,23 +576,23 @@ static int parse_videoinfoheader2(AVFormatContext *s, AVStream *st)
 static void parse_mpeg1waveformatex(AVStream *st)
 {
     /* fwHeadLayer */
-    switch (AV_RL16(st->codec->extradata)) {
-    case 0x0001 : st->codec->codec_id = AV_CODEC_ID_MP1; break;
-    case 0x0002 : st->codec->codec_id = AV_CODEC_ID_MP2; break;
-    case 0x0004 : st->codec->codec_id = AV_CODEC_ID_MP3; break;
+    switch (AV_RL16(st->codecpar->extradata)) {
+    case 0x0001 : st->codecpar->codec_id = AV_CODEC_ID_MP1; break;
+    case 0x0002 : st->codecpar->codec_id = AV_CODEC_ID_MP2; break;
+    case 0x0004 : st->codecpar->codec_id = AV_CODEC_ID_MP3; break;
     }
 
-    st->codec->bit_rate = AV_RL32(st->codec->extradata + 2); /* dwHeadBitrate */
+    st->codecpar->bit_rate = AV_RL32(st->codecpar->extradata + 2); /* dwHeadBitrate */
 
     /* dwHeadMode */
-    switch (AV_RL16(st->codec->extradata + 6)) {
+    switch (AV_RL16(st->codecpar->extradata + 6)) {
     case 1 :
     case 2 :
-    case 4 : st->codec->channels       = 2;
-             st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
+    case 4 : st->codecpar->channels       = 2;
+             st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO;
              break;
-    case 8 : st->codec->channels       = 1;
-             st->codec->channel_layout = AV_CH_LAYOUT_MONO;
+    case 8 : st->codecpar->channels       = 1;
+             st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
              break;
     }
 }
@@ -609,9 +605,9 @@ static void parse_mpeg1waveformatex(AVStream *st)
 static AVStream * new_stream(AVFormatContext *s, AVStream *st, int sid, int codec_type)
 {
     if (st) {
-        if (st->codec->extradata) {
-            av_freep(&st->codec->extradata);
-            st->codec->extradata_size = 0;
+        if (st->codecpar->extradata) {
+            av_freep(&st->codecpar->extradata);
+            st->codecpar->extradata_size = 0;
         }
     } else {
         WtvStream *wst = av_mallocz(sizeof(WtvStream));
@@ -625,7 +621,7 @@ static AVStream * new_stream(AVFormatContext *s, AVStream *st, int sid, int code
         st->id = sid;
         st->priv_data = wst;
     }
-    st->codec->codec_type = codec_type;
+    st->codecpar->codec_type = codec_type;
     st->need_parsing      = AVSTREAM_PARSE_FULL;
     avpriv_set_pts_info(st, 64, 1, 10000000);
     return st;
@@ -670,7 +666,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
         if (!st)
             return NULL;
         if (!ff_guidcmp(formattype, ff_format_waveformatex)) {
-            int ret = ff_get_wav_header(s, pb, st->codec, size, 0);
+            int ret = ff_get_wav_header(s, pb, st->codecpar, size, 0);
             if (ret < 0)
                 return NULL;
         } else {
@@ -680,15 +676,15 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
         }
 
         if (!memcmp(subtype + 4, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12)) {
-            st->codec->codec_id = ff_wav_codec_get_id(AV_RL32(subtype), st->codec->bits_per_coded_sample);
+            st->codecpar->codec_id = ff_wav_codec_get_id(AV_RL32(subtype), st->codecpar->bits_per_coded_sample);
         } else if (!ff_guidcmp(subtype, mediasubtype_mpeg1payload)) {
-            if (st->codec->extradata && st->codec->extradata_size >= 22)
+            if (st->codecpar->extradata && st->codecpar->extradata_size >= 22)
                 parse_mpeg1waveformatex(st);
             else
                 av_log(s, AV_LOG_WARNING, "MPEG1WAVEFORMATEX underflow\n");
         } else {
-            st->codec->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subtype);
-            if (st->codec->codec_id == AV_CODEC_ID_NONE)
+            st->codecpar->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subtype);
+            if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
                 av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype));
         }
         return st;
@@ -710,11 +706,11 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
         }
 
         if (!memcmp(subtype + 4, (const uint8_t[]){FF_MEDIASUBTYPE_BASE_GUID}, 12)) {
-            st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(subtype));
+            st->codecpar->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(subtype));
         } else {
-            st->codec->codec_id = ff_codec_guid_get_id(ff_video_guids, subtype);
+            st->codecpar->codec_id = ff_codec_guid_get_id(ff_video_guids, subtype);
         }
-        if (st->codec->codec_id == AV_CODEC_ID_NONE)
+        if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
             av_log(s, AV_LOG_WARNING, "unknown subtype:"FF_PRI_GUID"\n", FF_ARG_GUID(subtype));
         return st;
     } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_pes) &&
@@ -725,7 +721,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
         if (ff_guidcmp(formattype, ff_format_none))
             av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
         avio_skip(pb, size);
-        st->codec->codec_id = AV_CODEC_ID_DVB_SUBTITLE;
+        st->codecpar->codec_id = AV_CODEC_ID_DVB_SUBTITLE;
         return st;
     } else if (!ff_guidcmp(mediatype, mediatype_mstvcaption) &&
                (!ff_guidcmp(subtype, mediasubtype_teletext) || !ff_guidcmp(subtype, mediasubtype_dtvccdata))) {
@@ -735,7 +731,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid,
         if (ff_guidcmp(formattype, ff_format_none))
             av_log(s, AV_LOG_WARNING, "unknown formattype:"FF_PRI_GUID"\n", FF_ARG_GUID(formattype));
         avio_skip(pb, size);
-        st->codec->codec_id = !ff_guidcmp(subtype, mediasubtype_teletext) ? AV_CODEC_ID_DVB_TELETEXT : AV_CODEC_ID_EIA_608;
+        st->codecpar->codec_id = !ff_guidcmp(subtype, mediasubtype_teletext) ? AV_CODEC_ID_DVB_TELETEXT : AV_CODEC_ID_EIA_608;
         return st;
     } else if (!ff_guidcmp(mediatype, mediatype_mpeg2_sections) &&
                !ff_guidcmp(subtype, mediasubtype_mpeg2_sections)) {
@@ -1009,6 +1005,8 @@ static int read_header(AVFormatContext *s)
         wtvfile_close(pb);
     }
 
+    s->ctx_flags |= AVFMTCTX_NOHEADER; // Needed for noStreams.wtv
+
     /* read seek index */
     if (s->nb_streams) {
         AVStream *st = s->streams[0];
diff --git a/libavformat/wtvenc.c b/libavformat/wtvenc.c
index 0894b7f..a7ca1c3 100644
--- a/libavformat/wtvenc.c
+++ b/libavformat/wtvenc.c
@@ -215,22 +215,22 @@ static void finish_chunk(AVFormatContext *s)
 
 static void put_videoinfoheader2(AVIOContext *pb, AVStream *st)
 {
-    AVRational dar = av_mul_q(st->sample_aspect_ratio, (AVRational){st->codec->width, st->codec->height});
+    AVRational dar = av_mul_q(st->sample_aspect_ratio, (AVRational){st->codecpar->width, st->codecpar->height});
     unsigned int num, den;
     av_reduce(&num, &den, dar.num, dar.den, 0xFFFFFFFF);
 
     /* VIDEOINFOHEADER2 */
     avio_wl32(pb, 0);
     avio_wl32(pb, 0);
-    avio_wl32(pb, st->codec->width);
-    avio_wl32(pb, st->codec->height);
+    avio_wl32(pb, st->codecpar->width);
+    avio_wl32(pb, st->codecpar->height);
 
     avio_wl32(pb, 0);
     avio_wl32(pb, 0);
     avio_wl32(pb, 0);
     avio_wl32(pb, 0);
 
-    avio_wl32(pb, st->codec->bit_rate);
+    avio_wl32(pb, st->codecpar->bit_rate);
     avio_wl32(pb, 0);
     avio_wl64(pb, st->avg_frame_rate.num && st->avg_frame_rate.den ? INT64_C(10000000) / av_q2d(st->avg_frame_rate) : 0);
     avio_wl32(pb, 0);
@@ -241,17 +241,17 @@ static void put_videoinfoheader2(AVIOContext *pb, AVStream *st)
     avio_wl32(pb, 0);
     avio_wl32(pb, 0);
 
-    ff_put_bmp_header(pb, st->codec, ff_codec_bmp_tags, 0, 1);
+    ff_put_bmp_header(pb, st->codecpar, ff_codec_bmp_tags, 0, 1);
 
-    if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
-        int padding = (st->codec->extradata_size & 3) ? 4 - (st->codec->extradata_size & 3) : 0;
+    if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
+        int padding = (st->codecpar->extradata_size & 3) ? 4 - (st->codecpar->extradata_size & 3) : 0;
         /* MPEG2VIDEOINFO */
         avio_wl32(pb, 0);
-        avio_wl32(pb, st->codec->extradata_size + padding);
+        avio_wl32(pb, st->codecpar->extradata_size + padding);
         avio_wl32(pb, -1);
         avio_wl32(pb, -1);
         avio_wl32(pb, 0);
-        avio_write(pb, st->codec->extradata, st->codec->extradata_size);
+        avio_write(pb, st->codecpar->extradata, st->codecpar->extradata_size);
         ffio_fill(pb, 0, padding);
     }
 }
@@ -264,18 +264,18 @@ static int write_stream_codec_info(AVFormatContext *s, AVStream *st)
     int64_t  hdr_pos_start;
     int hdr_size = 0;
 
-    if (st->codec->codec_type  == AVMEDIA_TYPE_VIDEO) {
-        g = ff_get_codec_guid(st->codec->codec_id, ff_video_guids);
+    if (st->codecpar->codec_type  == AVMEDIA_TYPE_VIDEO) {
+        g = ff_get_codec_guid(st->codecpar->codec_id, ff_video_guids);
         media_type = &ff_mediatype_video;
-        format_type = st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO ? &ff_format_mpeg2_video : &ff_format_videoinfo2;
+        format_type = st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO ? &ff_format_mpeg2_video : &ff_format_videoinfo2;
         tags = ff_codec_bmp_tags;
-    } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
-        g = ff_get_codec_guid(st->codec->codec_id, ff_codec_wav_guids);
+    } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
+        g = ff_get_codec_guid(st->codecpar->codec_id, ff_codec_wav_guids);
         media_type = &ff_mediatype_audio;
         format_type = &ff_format_waveformatex;
         tags = ff_codec_wav_tags;
     } else {
-        av_log(s, AV_LOG_ERROR, "unknown codec_type (0x%x)\n", st->codec->codec_type);
+        av_log(s, AV_LOG_ERROR, "unknown codec_type (0x%x)\n", st->codecpar->codec_type);
         return -1;
     }
 
@@ -286,10 +286,10 @@ static int write_stream_codec_info(AVFormatContext *s, AVStream *st)
     avio_wl32(pb, 0); // size
 
     hdr_pos_start = avio_tell(pb);
-    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
         put_videoinfoheader2(pb, st);
     } else {
-        if (ff_put_wav_header(pb, st->codec, 0) < 0)
+        if (ff_put_wav_header(s, pb, st->codecpar, 0) < 0)
             format_type = &ff_format_none;
     }
     hdr_size = avio_tell(pb) - hdr_pos_start;
@@ -301,9 +301,9 @@ static int write_stream_codec_info(AVFormatContext *s, AVStream *st)
     if (g) {
         ff_put_guid(pb, g);           // actual_subtype
     } else {
-        int tag = ff_codec_get_tag(tags, st->codec->codec_id);
+        int tag = ff_codec_get_tag(tags, st->codecpar->codec_id);
         if (!tag) {
-            av_log(s, AV_LOG_ERROR, "unsupported codec_id (0x%x)\n", st->codec->codec_id);
+            av_log(s, AV_LOG_ERROR, "unsupported codec_id (0x%x)\n", st->codecpar->codec_id);
             return -1;
         }
         avio_wl32(pb, tag);
@@ -326,7 +326,7 @@ static int write_stream_codec(AVFormatContext *s, AVStream * st)
 
     ret = write_stream_codec_info(s, st);
     if (ret < 0) {
-        av_log(s, AV_LOG_ERROR, "write stream codec info failed codec_type(0x%x)\n", st->codec->codec_type);
+        av_log(s, AV_LOG_ERROR, "write stream codec info failed codec_type(0x%x)\n", st->codecpar->codec_type);
         return -1;
     }
 
@@ -364,7 +364,7 @@ static int write_stream_data(AVFormatContext *s, AVStream *st)
 
     ret = write_stream_codec_info(s, st);
     if (ret < 0) {
-        av_log(s, AV_LOG_ERROR, "write stream codec info failed codec_type(0x%x)\n", st->codec->codec_type);
+        av_log(s, AV_LOG_ERROR, "write stream codec info failed codec_type(0x%x)\n", st->codecpar->codec_type);
         return -1;
     }
     finish_chunk(s);
@@ -411,11 +411,11 @@ static int write_header(AVFormatContext *s)
 
     for (i = 0; i < s->nb_streams; i++) {
         st = s->streams[i];
-        if (st->codec->codec_id == AV_CODEC_ID_MJPEG)
+        if (st->codecpar->codec_id == AV_CODEC_ID_MJPEG)
             continue;
         ret = write_stream_codec(s, st);
         if (ret < 0) {
-            av_log(s, AV_LOG_ERROR, "write stream codec failed codec_type(0x%x)\n", st->codec->codec_type);
+            av_log(s, AV_LOG_ERROR, "write stream codec failed codec_type(0x%x)\n", st->codecpar->codec_type);
             return -1;
         }
         if (!i)
@@ -424,11 +424,11 @@ static int write_header(AVFormatContext *s)
 
     for (i = 0; i < s->nb_streams; i++) {
         st = s->streams[i];
-        if (st->codec->codec_id == AV_CODEC_ID_MJPEG)
+        if (st->codecpar->codec_id == AV_CODEC_ID_MJPEG)
             continue;
         ret  = write_stream_data(s, st);
         if (ret < 0) {
-            av_log(s, AV_LOG_ERROR, "write stream data failed codec_type(0x%x)\n", st->codec->codec_type);
+            av_log(s, AV_LOG_ERROR, "write stream data failed codec_type(0x%x)\n", st->codecpar->codec_type);
             return -1;
         }
     }
@@ -443,7 +443,7 @@ static void write_timestamp(AVFormatContext *s, AVPacket *pkt)
 {
     AVIOContext *pb = s->pb;
     WtvContext  *wctx = s->priv_data;
-    AVCodecContext *enc = s->streams[pkt->stream_index]->codec;
+    AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
 
     write_chunk_header(s, &ff_timestamp_guid, 56, 0x40000000 | (INDEX_BASE + pkt->stream_index));
     write_pad(pb, 8);
@@ -451,7 +451,7 @@ static void write_timestamp(AVFormatContext *s, AVPacket *pkt)
     avio_wl64(pb, pkt->pts == AV_NOPTS_VALUE ? -1 : pkt->pts);
     avio_wl64(pb, pkt->pts == AV_NOPTS_VALUE ? -1 : pkt->pts);
     avio_wl64(pb, 0);
-    avio_wl64(pb, enc->codec_type == AVMEDIA_TYPE_VIDEO && (pkt->flags & AV_PKT_FLAG_KEY) ? 1 : 0);
+    avio_wl64(pb, par->codec_type == AVMEDIA_TYPE_VIDEO && (pkt->flags & AV_PKT_FLAG_KEY) ? 1 : 0);
     avio_wl64(pb, 0);
 
     wctx->last_timestamp_pos = wctx->last_chunk_pos;
@@ -463,10 +463,10 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
     WtvContext  *wctx = s->priv_data;
     AVStream    *st   = s->streams[pkt->stream_index];
 
-    if (st->codec->codec_id == AV_CODEC_ID_MJPEG && !wctx->thumbnail.size) {
+    if (st->codecpar->codec_id == AV_CODEC_ID_MJPEG && !wctx->thumbnail.size) {
         av_copy_packet(&wctx->thumbnail, pkt);
         return 0;
-    } else if (st->codec->codec_id == AV_CODEC_ID_H264) {
+    } else if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
         int ret = ff_check_h264_startcode(s, st, pkt);
         if (ret < 0)
             return ret;
@@ -672,6 +672,7 @@ static void write_table_entries_attrib(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     AVDictionaryEntry *tag = 0;
 
+    ff_standardize_creation_time(s);
     //FIXME: translate special tags (e.g. WM/Bitrate) to binary representation
     ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL);
     while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
diff --git a/libavformat/wvdec.c b/libavformat/wvdec.c
index 042f96b..1ec52f6 100644
--- a/libavformat/wvdec.c
+++ b/libavformat/wvdec.c
@@ -230,12 +230,12 @@ static int wv_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id              = AV_CODEC_ID_WAVPACK;
-    st->codec->channels              = wc->chan;
-    st->codec->channel_layout        = wc->chmask;
-    st->codec->sample_rate           = wc->rate;
-    st->codec->bits_per_coded_sample = wc->bpp;
+    st->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id              = AV_CODEC_ID_WAVPACK;
+    st->codecpar->channels              = wc->chan;
+    st->codecpar->channel_layout        = wc->chmask;
+    st->codecpar->sample_rate           = wc->rate;
+    st->codecpar->bits_per_coded_sample = wc->bpp;
     avpriv_set_pts_info(st, 64, 1, wc->rate);
     st->start_time = 0;
     if (wc->header.total_samples != 0xFFFFFFFFu)
diff --git a/libavformat/wvedec.c b/libavformat/wvedec.c
index 8e74abe..89c0001 100644
--- a/libavformat/wvedec.c
+++ b/libavformat/wvedec.c
@@ -40,13 +40,13 @@ static int wve_read_header(AVFormatContext *s)
 
     avio_skip(s->pb, 18);
     st->duration           = avio_rb32(s->pb);
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = AV_CODEC_ID_PCM_ALAW;
-    st->codec->sample_rate = 8000;
-    st->codec->channels    = 1;
-    st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id);
-    st->codec->block_align = st->codec->bits_per_coded_sample * st->codec->channels / 8;
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id    = AV_CODEC_ID_PCM_ALAW;
+    st->codecpar->sample_rate = 8000;
+    st->codecpar->channels    = 1;
+    st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id);
+    st->codecpar->block_align = st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8;
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     avio_skip(s->pb, 10);
 
     return 0;
diff --git a/libavformat/wvenc.c b/libavformat/wvenc.c
index b0d74ca..48e371a 100644
--- a/libavformat/wvenc.c
+++ b/libavformat/wvenc.c
@@ -33,7 +33,7 @@ typedef struct WvMuxContext {
 static av_cold int wv_write_header(AVFormatContext *ctx)
 {
     if (ctx->nb_streams > 1 ||
-        ctx->streams[0]->codec->codec_id != AV_CODEC_ID_WAVPACK) {
+        ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_WAVPACK) {
         av_log(ctx, AV_LOG_ERROR, "This muxer only supports a single WavPack stream.\n");
         return AVERROR(EINVAL);
     }
diff --git a/libavformat/xa.c b/libavformat/xa.c
index 43661de..810e0c0 100644
--- a/libavformat/xa.c
+++ b/libavformat/xa.c
@@ -73,24 +73,24 @@ static int xa_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type   = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id     = AV_CODEC_ID_ADPCM_EA_MAXIS_XA;
+    st->codecpar->codec_type   = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_id     = AV_CODEC_ID_ADPCM_EA_MAXIS_XA;
     avio_skip(pb, 4);       /* Skip the XA ID */
     xa->out_size            =  avio_rl32(pb);
     avio_skip(pb, 2);       /* Skip the tag */
-    st->codec->channels     = avio_rl16(pb);
-    st->codec->sample_rate  = avio_rl32(pb);
+    st->codecpar->channels     = avio_rl16(pb);
+    st->codecpar->sample_rate  = avio_rl32(pb);
     avio_skip(pb, 4);       /* Skip average byte rate */
     avio_skip(pb, 2);       /* Skip block align */
     avio_skip(pb, 2);       /* Skip bits-per-sample */
 
-    if (!st->codec->channels || !st->codec->sample_rate)
+    if (!st->codecpar->channels || !st->codecpar->sample_rate)
         return AVERROR_INVALIDDATA;
 
-    st->codec->bit_rate = av_clip(15LL * st->codec->channels * 8 *
-                                  st->codec->sample_rate / 28, 0, INT_MAX);
+    st->codecpar->bit_rate = av_clip(15LL * st->codecpar->channels * 8 *
+                                  st->codecpar->sample_rate / 28, 0, INT_MAX);
 
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
     st->start_time = 0;
 
     return 0;
@@ -108,7 +108,7 @@ static int xa_read_packet(AVFormatContext *s,
     if (xa->sent_bytes >= xa->out_size)
         return AVERROR_EOF;
     /* 1 byte header and 14 bytes worth of samples * number channels per block */
-    packet_size = 15*st->codec->channels;
+    packet_size = 15*st->codecpar->channels;
 
     ret = av_get_packet(pb, pkt, packet_size);
     if(ret < 0)
diff --git a/libavformat/xmv.c b/libavformat/xmv.c
index 45e5ebc..b85d0cc 100644
--- a/libavformat/xmv.c
+++ b/libavformat/xmv.c
@@ -53,6 +53,7 @@
 
 /** A video packet with an XMV file. */
 typedef struct XMVVideoPacket {
+    int created;
     int stream_index; ///< The decoder stream index for this video packet.
 
     uint32_t data_size;   ///< The size of the remaining video data.
@@ -70,6 +71,7 @@ typedef struct XMVVideoPacket {
 
 /** An audio packet with an XMV file. */
 typedef struct XMVAudioPacket {
+    int created;
     int stream_index; ///< The decoder stream index for this audio packet.
 
     /* Stream format properties. */
@@ -105,6 +107,10 @@ typedef struct XMVDemuxContext {
     uint16_t current_stream; ///< The index of the stream currently handling.
     uint16_t stream_count;   ///< The number of streams in this file.
 
+    uint32_t video_duration;
+    uint32_t video_width;
+    uint32_t video_height;
+
     XMVVideoPacket  video; ///< The video packet contained in each packet.
     XMVAudioPacket *audio; ///< The audio packets contained in each packet.
 } XMVDemuxContext;
@@ -139,13 +145,14 @@ static int xmv_read_header(AVFormatContext *s)
 {
     XMVDemuxContext *xmv = s->priv_data;
     AVIOContext     *pb  = s->pb;
-    AVStream        *vst = NULL;
 
     uint32_t file_version;
     uint32_t this_packet_size;
     uint16_t audio_track;
     int ret;
 
+    s->ctx_flags |= AVFMTCTX_NOHEADER;
+
     avio_skip(pb, 4); /* Next packet size */
 
     this_packet_size = avio_rl32(pb);
@@ -157,24 +164,11 @@ static int xmv_read_header(AVFormatContext *s)
     if ((file_version != 4) && (file_version != 2))
         avpriv_request_sample(s, "Uncommon version %"PRIu32"", file_version);
 
+    /* Video tracks */
 
-    /* Video track */
-
-    vst = avformat_new_stream(s, NULL);
-    if (!vst)
-        return AVERROR(ENOMEM);
-
-    avpriv_set_pts_info(vst, 32, 1, 1000);
-
-    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-    vst->codec->codec_id   = AV_CODEC_ID_WMV2;
-    vst->codec->codec_tag  = MKBETAG('W', 'M', 'V', '2');
-    vst->codec->width      = avio_rl32(pb);
-    vst->codec->height     = avio_rl32(pb);
-
-    vst->duration          = avio_rl32(pb);
-
-    xmv->video.stream_index = vst->index;
+    xmv->video_width    = avio_rl32(pb);
+    xmv->video_height   = avio_rl32(pb);
+    xmv->video_duration = avio_rl32(pb);
 
     /* Audio tracks */
 
@@ -182,7 +176,7 @@ static int xmv_read_header(AVFormatContext *s)
 
     avio_skip(pb, 2); /* Unknown (padding?) */
 
-    xmv->audio = av_malloc_array(xmv->audio_track_count, sizeof(XMVAudioPacket));
+    xmv->audio = av_mallocz_array(xmv->audio_track_count, sizeof(XMVAudioPacket));
     if (!xmv->audio) {
         ret = AVERROR(ENOMEM);
         goto fail;
@@ -190,7 +184,6 @@ static int xmv_read_header(AVFormatContext *s)
 
     for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
         XMVAudioPacket *packet = &xmv->audio[audio_track];
-        AVStream *ast = NULL;
 
         packet->compression     = avio_rl16(pb);
         packet->channels        = avio_rl16(pb);
@@ -224,27 +217,6 @@ static int xmv_read_header(AVFormatContext *s)
             ret = AVERROR_INVALIDDATA;
             goto fail;
         }
-
-        ast = avformat_new_stream(s, NULL);
-        if (!ast) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-
-        ast->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
-        ast->codec->codec_id              = packet->codec_id;
-        ast->codec->codec_tag             = packet->compression;
-        ast->codec->channels              = packet->channels;
-        ast->codec->sample_rate           = packet->sample_rate;
-        ast->codec->bits_per_coded_sample = packet->bits_per_sample;
-        ast->codec->bit_rate              = packet->bit_rate;
-        ast->codec->block_align           = 36 * packet->channels;
-
-        avpriv_set_pts_info(ast, 32, packet->block_samples, packet->sample_rate);
-
-        packet->stream_index = ast->index;
-
-        ast->duration = vst->duration;
     }
 
 
@@ -315,6 +287,26 @@ static int xmv_process_packet_header(AVFormatContext *s)
 
     xmv->video.has_extradata = (data[3] & 0x80) != 0;
 
+    if (!xmv->video.created) {
+        AVStream *vst = avformat_new_stream(s, NULL);
+        if (!vst)
+            return AVERROR(ENOMEM);
+
+        avpriv_set_pts_info(vst, 32, 1, 1000);
+
+        vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
+        vst->codecpar->codec_id   = AV_CODEC_ID_WMV2;
+        vst->codecpar->codec_tag  = MKBETAG('W', 'M', 'V', '2');
+        vst->codecpar->width      = xmv->video_width;
+        vst->codecpar->height     = xmv->video_height;
+
+        vst->duration = xmv->video_duration;
+
+        xmv->video.stream_index = vst->index;
+
+        xmv->video.created = 1;
+    }
+
     /* Adding the audio data sizes and the video data size keeps you 4 bytes
      * short for every audio track. But as playing around with XMV files with
      * ADPCM audio showed, taking the extra 4 bytes from the audio data gives
@@ -340,6 +332,29 @@ static int xmv_process_packet_header(AVFormatContext *s)
         if (avio_read(pb, data, 4) != 4)
             return AVERROR(EIO);
 
+        if (!packet->created) {
+            AVStream *ast = avformat_new_stream(s, NULL);
+            if (!ast)
+                return AVERROR(ENOMEM);
+
+            ast->codecpar->codec_type            = AVMEDIA_TYPE_AUDIO;
+            ast->codecpar->codec_id              = packet->codec_id;
+            ast->codecpar->codec_tag             = packet->compression;
+            ast->codecpar->channels              = packet->channels;
+            ast->codecpar->sample_rate           = packet->sample_rate;
+            ast->codecpar->bits_per_coded_sample = packet->bits_per_sample;
+            ast->codecpar->bit_rate              = packet->bit_rate;
+            ast->codecpar->block_align           = 36 * packet->channels;
+
+            avpriv_set_pts_info(ast, 32, packet->block_samples, packet->sample_rate);
+
+            packet->stream_index = ast->index;
+
+            ast->duration = xmv->video_duration;
+
+            packet->created = 1;
+        }
+
         packet->data_size = AV_RL32(data) & 0x007FFFFF;
         if ((packet->data_size == 0) && (audio_track != 0))
             /* This happens when I create an XMV with several identical audio
@@ -381,14 +396,14 @@ static int xmv_process_packet_header(AVFormatContext *s)
 
                 av_assert0(xmv->video.stream_index < s->nb_streams);
 
-                if (vst->codec->extradata_size < 4) {
-                    av_freep(&vst->codec->extradata);
+                if (vst->codecpar->extradata_size < 4) {
+                    av_freep(&vst->codecpar->extradata);
 
-                    if ((ret = ff_alloc_extradata(vst->codec, 4)) < 0)
+                    if ((ret = ff_alloc_extradata(vst->codecpar, 4)) < 0)
                         return ret;
                 }
 
-                memcpy(vst->codec->extradata, xmv->video.extradata, 4);
+                memcpy(vst->codecpar->extradata, xmv->video.extradata, 4);
             }
         }
     }
diff --git a/libavformat/xvag.c b/libavformat/xvag.c
index 92c80a4..5ef4fb0 100644
--- a/libavformat/xvag.c
+++ b/libavformat/xvag.c
@@ -43,7 +43,7 @@ static int xvag_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
 
     offset     = avio_rl32(s->pb);
     big_endian = offset > av_bswap32(offset);
@@ -51,30 +51,30 @@ static int xvag_read_header(AVFormatContext *s)
         offset                 = av_bswap32(offset);
         avio_skip(s->pb, 28);
         codec                  = avio_rb32(s->pb);
-        st->codec->channels    = avio_rb32(s->pb);
+        st->codecpar->channels = avio_rb32(s->pb);
         avio_skip(s->pb, 4);
         st->duration           = avio_rb32(s->pb);
         avio_skip(s->pb, 8);
-        st->codec->sample_rate = avio_rb32(s->pb);
+        st->codecpar->sample_rate = avio_rb32(s->pb);
     } else {
         avio_skip(s->pb, 28);
         codec                  = avio_rl32(s->pb);
-        st->codec->channels    = avio_rl32(s->pb);
+        st->codecpar->channels = avio_rl32(s->pb);
         avio_skip(s->pb, 4);
         st->duration           = avio_rl32(s->pb);
         avio_skip(s->pb, 8);
-        st->codec->sample_rate = avio_rl32(s->pb);
+        st->codecpar->sample_rate = avio_rl32(s->pb);
     }
 
-    if (st->codec->sample_rate <= 0)
+    if (st->codecpar->sample_rate <= 0)
         return AVERROR_INVALIDDATA;
-    if (st->codec->channels <= 0)
+    if (st->codecpar->channels <= 0)
         return AVERROR_INVALIDDATA;
 
     switch (codec) {
     case 0x1c:
-        st->codec->codec_id    = AV_CODEC_ID_ADPCM_PSX;
-        st->codec->block_align = 16 * st->codec->channels;
+        st->codecpar->codec_id    = AV_CODEC_ID_ADPCM_PSX;
+        st->codecpar->block_align = 16 * st->codecpar->channels;
         break;
     default:
         avpriv_request_sample(s, "codec %X", codec);
@@ -84,22 +84,22 @@ static int xvag_read_header(AVFormatContext *s)
     avio_skip(s->pb, offset - avio_tell(s->pb));
 
     if (avio_rb16(s->pb) == 0xFFFB) {
-        st->codec->codec_id    = AV_CODEC_ID_MP3;
-        st->codec->block_align = 0x1000;
+        st->codecpar->codec_id    = AV_CODEC_ID_MP3;
+        st->codecpar->block_align = 0x1000;
         st->need_parsing       = AVSTREAM_PARSE_FULL_RAW;
     }
 
     avio_skip(s->pb, -2);
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     return 0;
 }
 
 static int xvag_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
-    AVCodecContext *codec = s->streams[0]->codec;
+    AVCodecParameters *par = s->streams[0]->codecpar;
 
-    return av_get_packet(s->pb, pkt, codec->block_align);
+    return av_get_packet(s->pb, pkt, par->block_align);
 }
 
 AVInputFormat ff_xvag_demuxer = {
diff --git a/libavformat/xwma.c b/libavformat/xwma.c
index d516b76..df84d25 100644
--- a/libavformat/xwma.c
+++ b/libavformat/xwma.c
@@ -75,7 +75,7 @@ static int xwma_read_header(AVFormatContext *s)
     if (!st)
         return AVERROR(ENOMEM);
 
-    ret = ff_get_wav_header(s, pb, st->codec, size, 0);
+    ret = ff_get_wav_header(s, pb, st->codecpar, size, 0);
     if (ret < 0)
         return ret;
     st->need_parsing = AVSTREAM_PARSE_NONE;
@@ -85,10 +85,10 @@ static int xwma_read_header(AVFormatContext *s)
      * extradata for that. Thus, ask the user for feedback, but try to go on
      * anyway.
      */
-    if (st->codec->codec_id != AV_CODEC_ID_WMAV2 &&
-        st->codec->codec_id != AV_CODEC_ID_WMAPRO) {
+    if (st->codecpar->codec_id != AV_CODEC_ID_WMAV2 &&
+        st->codecpar->codec_id != AV_CODEC_ID_WMAPRO) {
         avpriv_request_sample(s, "Unexpected codec (tag 0x04%x; id %d)",
-                              st->codec->codec_tag, st->codec->codec_id);
+                              st->codecpar->codec_tag, st->codecpar->codec_id);
     } else {
         /* In all xWMA files I have seen, there is no extradata. But the WMA
          * codecs require extradata, so we provide our own fake extradata.
@@ -97,43 +97,43 @@ static int xwma_read_header(AVFormatContext *s)
          * there was, then try to use it, after asking the user to provide a
          * sample of this unusual file.
          */
-        if (st->codec->extradata_size != 0) {
+        if (st->codecpar->extradata_size != 0) {
             /* Surprise, surprise: We *did* get some extradata. No idea
              * if it will work, but just go on and try it, after asking
              * the user for a sample.
              */
             avpriv_request_sample(s, "Unexpected extradata (%d bytes)",
-                                  st->codec->extradata_size);
-        } else if (st->codec->codec_id == AV_CODEC_ID_WMAPRO) {
-            if (ff_alloc_extradata(st->codec, 18))
+                                  st->codecpar->extradata_size);
+        } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) {
+            if (ff_alloc_extradata(st->codecpar, 18))
                 return AVERROR(ENOMEM);
 
-            memset(st->codec->extradata, 0, st->codec->extradata_size);
-            st->codec->extradata[ 0] = st->codec->bits_per_coded_sample;
-            st->codec->extradata[14] = 224;
+            memset(st->codecpar->extradata, 0, st->codecpar->extradata_size);
+            st->codecpar->extradata[ 0] = st->codecpar->bits_per_coded_sample;
+            st->codecpar->extradata[14] = 224;
         } else {
-            if (ff_alloc_extradata(st->codec, 6))
+            if (ff_alloc_extradata(st->codecpar, 6))
                 return AVERROR(ENOMEM);
 
-            memset(st->codec->extradata, 0, st->codec->extradata_size);
+            memset(st->codecpar->extradata, 0, st->codecpar->extradata_size);
             /* setup extradata with our experimentally obtained value */
-            st->codec->extradata[4] = 31;
+            st->codecpar->extradata[4] = 31;
         }
     }
 
-    if (!st->codec->channels) {
+    if (!st->codecpar->channels) {
         av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n",
-               st->codec->channels);
+               st->codecpar->channels);
         return AVERROR_INVALIDDATA;
     }
-    if (!st->codec->bits_per_coded_sample) {
+    if (!st->codecpar->bits_per_coded_sample) {
         av_log(s, AV_LOG_WARNING, "Invalid bits_per_coded_sample: %d\n",
-               st->codec->bits_per_coded_sample);
+               st->codecpar->bits_per_coded_sample);
         return AVERROR_INVALIDDATA;
     }
 
     /* set the sample rate */
-    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
 
     /* parse the remaining RIFF chunks */
     for (;;) {
@@ -153,7 +153,7 @@ static int xwma_read_header(AVFormatContext *s)
              * number of bytes accumulated after the corresponding xWMA packet
              * is decoded in order."
              *
-             * Each packet has size equal to st->codec->block_align, which in
+             * Each packet has size equal to st->codecpar->block_align, which in
              * all cases I saw so far was always 2230. Thus, we can use the
              * dpds data to compute a seeking index.
              */
@@ -207,7 +207,7 @@ static int xwma_read_header(AVFormatContext *s)
     if (dpds_table && dpds_table_size) {
         int64_t cur_pos;
         const uint32_t bytes_per_sample
-                = (st->codec->channels * st->codec->bits_per_coded_sample) >> 3;
+                = (st->codecpar->channels * st->codecpar->bits_per_coded_sample) >> 3;
 
         /* Estimate the duration from the total number of output bytes. */
         const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1];
@@ -215,7 +215,7 @@ static int xwma_read_header(AVFormatContext *s)
         if (!bytes_per_sample) {
             av_log(s, AV_LOG_ERROR,
                    "Invalid bits_per_coded_sample %d for %d channels\n",
-                   st->codec->bits_per_coded_sample, st->codec->channels);
+                   st->codecpar->bits_per_coded_sample, st->codecpar->channels);
             ret = AVERROR_INVALIDDATA;
             goto fail;
         }
@@ -238,18 +238,18 @@ static int xwma_read_header(AVFormatContext *s)
              * an offset / timestamp pair.
              */
             av_add_index_entry(st,
-                               cur_pos + (i+1) * st->codec->block_align, /* pos */
-                               dpds_table[i] / bytes_per_sample,         /* timestamp */
-                               st->codec->block_align,                   /* size */
-                               0,                                        /* duration */
+                               cur_pos + (i+1) * st->codecpar->block_align, /* pos */
+                               dpds_table[i] / bytes_per_sample,            /* timestamp */
+                               st->codecpar->block_align,                   /* size */
+                               0,                                           /* duration */
                                AVINDEX_KEYFRAME);
         }
-    } else if (st->codec->bit_rate) {
+    } else if (st->codecpar->bit_rate) {
         /* No dpds chunk was present (or only an empty one), so estimate
          * the total duration using the average bits per sample and the
          * total data length.
          */
-        st->duration = (size<<3) * st->codec->sample_rate / st->codec->bit_rate;
+        st->duration = (size<<3) * st->codecpar->sample_rate / st->codecpar->bit_rate;
     }
 
 fail:
@@ -273,7 +273,7 @@ static int xwma_read_packet(AVFormatContext *s, AVPacket *pkt)
     }
 
     /* read a single block; the default block size is 2230. */
-    size = (st->codec->block_align > 1) ? st->codec->block_align : 2230;
+    size = (st->codecpar->block_align > 1) ? st->codecpar->block_align : 2230;
     size = FFMIN(size, left);
 
     ret  = av_get_packet(s->pb, pkt, size);
diff --git a/libavformat/yop.c b/libavformat/yop.c
index 9b77f6e..e6fd896 100644
--- a/libavformat/yop.c
+++ b/libavformat/yop.c
@@ -58,7 +58,7 @@ static int yop_read_header(AVFormatContext *s)
     YopDecContext *yop = s->priv_data;
     AVIOContext *pb  = s->pb;
 
-    AVCodecContext *audio_dec, *video_dec;
+    AVCodecParameters *audio_par, *video_par;
     AVStream *audio_stream, *video_stream;
 
     int frame_rate, ret;
@@ -69,39 +69,39 @@ static int yop_read_header(AVFormatContext *s)
         return AVERROR(ENOMEM);
 
     // Extra data that will be passed to the decoder
-    if (ff_alloc_extradata(video_stream->codec, 8))
+    if (ff_alloc_extradata(video_stream->codecpar, 8))
         return AVERROR(ENOMEM);
 
     // Audio
-    audio_dec               = audio_stream->codec;
-    audio_dec->codec_type   = AVMEDIA_TYPE_AUDIO;
-    audio_dec->codec_id     = AV_CODEC_ID_ADPCM_IMA_APC;
-    audio_dec->channels     = 1;
-    audio_dec->channel_layout = AV_CH_LAYOUT_MONO;
-    audio_dec->sample_rate  = 22050;
+    audio_par                 = audio_stream->codecpar;
+    audio_par->codec_type     = AVMEDIA_TYPE_AUDIO;
+    audio_par->codec_id       = AV_CODEC_ID_ADPCM_IMA_APC;
+    audio_par->channels       = 1;
+    audio_par->channel_layout = AV_CH_LAYOUT_MONO;
+    audio_par->sample_rate    = 22050;
 
     // Video
-    video_dec               = video_stream->codec;
-    video_dec->codec_type   = AVMEDIA_TYPE_VIDEO;
-    video_dec->codec_id     = AV_CODEC_ID_YOP;
+    video_par               = video_stream->codecpar;
+    video_par->codec_type   = AVMEDIA_TYPE_VIDEO;
+    video_par->codec_id     = AV_CODEC_ID_YOP;
 
     avio_skip(pb, 6);
 
     frame_rate              = avio_r8(pb);
     yop->frame_size         = avio_r8(pb) * 2048;
-    video_dec->width        = avio_rl16(pb);
-    video_dec->height       = avio_rl16(pb);
+    video_par->width        = avio_rl16(pb);
+    video_par->height       = avio_rl16(pb);
 
     video_stream->sample_aspect_ratio = (AVRational){1, 2};
 
-    ret = avio_read(pb, video_dec->extradata, 8);
+    ret = avio_read(pb, video_par->extradata, 8);
     if (ret < 8)
         return ret < 0 ? ret : AVERROR_EOF;
 
-    yop->palette_size       = video_dec->extradata[0] * 3 + 4;
-    yop->audio_block_length = AV_RL16(video_dec->extradata + 6);
+    yop->palette_size       = video_par->extradata[0] * 3 + 4;
+    yop->audio_block_length = AV_RL16(video_par->extradata + 6);
 
-    video_dec->bit_rate     = 8 * (yop->frame_size - yop->audio_block_length) * frame_rate;
+    video_par->bit_rate     = 8 * (yop->frame_size - yop->audio_block_length) * frame_rate;
 
     // 1840 samples per frame, 1 nibble per sample; hence 1840/2 = 920
     if (yop->audio_block_length < 920 ||
diff --git a/libavformat/yuv4mpegdec.c b/libavformat/yuv4mpegdec.c
index ea1ae25..a91645f 100644
--- a/libavformat/yuv4mpegdec.c
+++ b/libavformat/yuv4mpegdec.c
@@ -247,18 +247,18 @@ static int yuv4_read_header(AVFormatContext *s)
     st = avformat_new_stream(s, NULL);
     if (!st)
         return AVERROR(ENOMEM);
-    st->codec->width  = width;
-    st->codec->height = height;
+    st->codecpar->width  = width;
+    st->codecpar->height = height;
     av_reduce(&raten, &rated, raten, rated, (1UL << 31) - 1);
     avpriv_set_pts_info(st, 64, rated, raten);
     st->avg_frame_rate                = av_inv_q(st->time_base);
-    st->codec->pix_fmt                = pix_fmt;
-    st->codec->codec_type             = AVMEDIA_TYPE_VIDEO;
-    st->codec->codec_id               = AV_CODEC_ID_RAWVIDEO;
+    st->codecpar->format              = pix_fmt;
+    st->codecpar->codec_type          = AVMEDIA_TYPE_VIDEO;
+    st->codecpar->codec_id            = AV_CODEC_ID_RAWVIDEO;
     st->sample_aspect_ratio           = (AVRational){ aspectn, aspectd };
-    st->codec->chroma_sample_location = chroma_sample_location;
-    st->codec->field_order            = field_order;
-    s->packet_size = av_image_get_buffer_size(st->codec->pix_fmt, width, height, 1) + Y4M_FRAME_MAGIC_LEN;
+    st->codecpar->chroma_location     = chroma_sample_location;
+    st->codecpar->field_order         = field_order;
+    s->packet_size = av_image_get_buffer_size(st->codecpar->format, width, height, 1) + Y4M_FRAME_MAGIC_LEN;
     if ((int) s->packet_size < 0)
         return s->packet_size;
     s->internal->data_offset = avio_tell(pb);
@@ -307,7 +307,8 @@ static int yuv4_read_packet(AVFormatContext *s, AVPacket *pkt)
 static int yuv4_read_seek(AVFormatContext *s, int stream_index,
                           int64_t pts, int flags)
 {
-    avio_seek(s->pb, pts * s->packet_size + s->internal->data_offset, SEEK_SET);
+    if (avio_seek(s->pb, pts * s->packet_size + s->internal->data_offset, SEEK_SET) < 0)
+        return -1;
     return 0;
 }
 
diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c
index 6120c7e..b4dc6e9 100644
--- a/libavformat/yuv4mpegenc.c
+++ b/libavformat/yuv4mpegenc.c
@@ -33,10 +33,12 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf)
     int raten, rated, aspectn, aspectd, n;
     char inter;
     const char *colorspace = "";
+    int field_order;
 
     st     = s->streams[0];
-    width  = st->codec->width;
-    height = st->codec->height;
+    width  = st->codecpar->width;
+    height = st->codecpar->height;
+    field_order = st->codecpar->field_order;
 
     // TODO: should be avg_frame_rate
     av_reduce(&raten, &rated, st->time_base.den,
@@ -48,7 +50,14 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf)
     if (aspectn == 0 && aspectd == 1)
         aspectd = 0;  // 0:0 means unknown
 
-    switch (st->codec->field_order) {
+#if FF_API_LAVF_AVCTX
+    FF_DISABLE_DEPRECATION_WARNINGS
+    if (field_order != st->codec->field_order && st->codec->field_order != AV_FIELD_UNKNOWN)
+        field_order = st->codec->field_order;
+    FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+    switch (field_order) {
     case AV_FIELD_TB:
     case AV_FIELD_TT: inter = 't'; break;
     case AV_FIELD_BT:
@@ -56,7 +65,7 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf)
     default:          inter = 'p'; break;
     }
 
-    switch (st->codec->pix_fmt) {
+    switch (st->codecpar->format) {
     case AV_PIX_FMT_GRAY8:
         colorspace = " Cmono";
         break;
@@ -67,7 +76,7 @@ static int yuv4_generate_header(AVFormatContext *s, char* buf)
         colorspace = " C411 XYSCSS=411";
         break;
     case AV_PIX_FMT_YUV420P:
-        switch (st->codec->chroma_sample_location) {
+        switch (st->codecpar->chroma_location) {
         case AVCHROMA_LOC_TOPLEFT: colorspace = " C420paldv XYSCSS=420PALDV"; break;
         case AVCHROMA_LOC_LEFT:    colorspace = " C420mpeg2 XYSCSS=420MPEG2"; break;
         default:                   colorspace = " C420jpeg XYSCSS=420JPEG";   break;
@@ -163,12 +172,12 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
 
     avio_printf(s->pb, "%s\n", Y4M_FRAME_MAGIC);
 
-    width  = st->codec->width;
-    height = st->codec->height;
+    width  = st->codecpar->width;
+    height = st->codecpar->height;
 
     ptr = frame->data[0];
 
-    switch (st->codec->pix_fmt) {
+    switch (st->codecpar->format) {
     case AV_PIX_FMT_GRAY8:
     case AV_PIX_FMT_YUV411P:
     case AV_PIX_FMT_YUV420P:
@@ -195,7 +204,7 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
         break;
     default:
         av_log(s, AV_LOG_ERROR, "The pixel format '%s' is not supported.\n",
-               av_get_pix_fmt_name(st->codec->pix_fmt));
+               av_get_pix_fmt_name(st->codecpar->format));
         return AVERROR(EINVAL);
     }
 
@@ -204,11 +213,12 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt)
         ptr += frame->linesize[0];
     }
 
-    if (st->codec->pix_fmt != AV_PIX_FMT_GRAY8 &&
-        st->codec->pix_fmt != AV_PIX_FMT_GRAY16) {
+    if (st->codecpar->format != AV_PIX_FMT_GRAY8 &&
+        st->codecpar->format != AV_PIX_FMT_GRAY16) {
         // Adjust for smaller Cb and Cr planes
-        av_pix_fmt_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift,
+        av_pix_fmt_get_chroma_sub_sample(st->codecpar->format, &h_chroma_shift,
                                          &v_chroma_shift);
+        // Shift right, rounding up
         width  = AV_CEIL_RSHIFT(width,  h_chroma_shift);
         height = AV_CEIL_RSHIFT(height, v_chroma_shift);
 
@@ -234,12 +244,12 @@ static int yuv4_write_header(AVFormatContext *s)
     if (s->nb_streams != 1)
         return AVERROR(EIO);
 
-    if (s->streams[0]->codec->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME) {
+    if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME) {
         av_log(s, AV_LOG_ERROR, "ERROR: Codec not supported.\n");
         return AVERROR_INVALIDDATA;
     }
 
-    switch (s->streams[0]->codec->pix_fmt) {
+    switch (s->streams[0]->codecpar->format) {
     case AV_PIX_FMT_YUV411P:
         av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV "
                "stream, some mjpegtools might not work.\n");
@@ -266,9 +276,9 @@ static int yuv4_write_header(AVFormatContext *s)
     case AV_PIX_FMT_YUV422P16:
     case AV_PIX_FMT_YUV444P16:
         if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
-            av_log(s, AV_LOG_ERROR, "'%s' is not a official yuv4mpegpipe pixel format. "
+            av_log(s, AV_LOG_ERROR, "'%s' is not an official yuv4mpegpipe pixel format. "
                    "Use '-strict -1' to encode to this pixel format.\n",
-                   av_get_pix_fmt_name(s->streams[0]->codec->pix_fmt));
+                   av_get_pix_fmt_name(s->streams[0]->codecpar->format));
             return AVERROR(EINVAL);
         }
         av_log(s, AV_LOG_WARNING, "Warning: generating non standard YUV stream. "
diff --git a/libavresample/aarch64/Makefile b/libavresample/aarch64/Makefile
index 1d9e5f8..f92699e 100644
--- a/libavresample/aarch64/Makefile
+++ b/libavresample/aarch64/Makefile
@@ -1,7 +1,7 @@
-OBJS                             += aarch64/audio_convert_init.o    \
-                                    aarch64/resample_init.o         \
+OBJS                             += aarch64/audio_convert_init.o        \
+                                    aarch64/resample_init.o             \
 
 OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o
 
-NEON-OBJS                        += aarch64/audio_convert_neon.o    \
-                                    aarch64/resample_neon.o         \
+NEON-OBJS                        += aarch64/audio_convert_neon.o        \
+                                    aarch64/resample_neon.o             \
diff --git a/libavresample/arm/Makefile b/libavresample/arm/Makefile
index affc2bf..352d1a8 100644
--- a/libavresample/arm/Makefile
+++ b/libavresample/arm/Makefile
@@ -1,7 +1,7 @@
-OBJS      += arm/audio_convert_init.o \
-             arm/resample_init.o
+OBJS                            += arm/audio_convert_init.o             \
+                                   arm/resample_init.o
 
 OBJS-$(CONFIG_NEON_CLOBBER_TEST) += arm/neontest.o
 
-NEON-OBJS += arm/audio_convert_neon.o \
-             arm/resample_neon.o
+NEON-OBJS                        += arm/audio_convert_neon.o            \
+                                    arm/resample_neon.o
diff --git a/libavresample/avresample-test.c b/libavresample/avresample-test.c
deleted file mode 100644
index 290ae94..0000000
--- a/libavresample/avresample-test.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (c) 2002 Fabrice Bellard
- * Copyright (c) 2012 Justin Ruggles <justin.ruggles at gmail.com>
- *
- * 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 <stdint.h>
-#include <stdio.h>
-
-#include "libavutil/avstring.h"
-#include "libavutil/common.h"
-#include "libavutil/lfg.h"
-#include "libavutil/libm.h"
-#include "libavutil/log.h"
-#include "libavutil/mem.h"
-#include "libavutil/opt.h"
-#include "libavutil/samplefmt.h"
-#include "avresample.h"
-
-static double dbl_rand(AVLFG *lfg)
-{
-    return 2.0 * (av_lfg_get(lfg) / (double)UINT_MAX) - 1.0;
-}
-
-#define PUT_FUNC(name, fmt, type, expr)                                     \
-static void put_sample_ ## name(void **data, enum AVSampleFormat sample_fmt,\
-                                int channels, int sample, int ch,           \
-                                double v_dbl)                               \
-{                                                                           \
-    type v = expr;                                                          \
-    type **out = (type **)data;                                             \
-    if (av_sample_fmt_is_planar(sample_fmt))                                \
-        out[ch][sample] = v;                                                \
-    else                                                                    \
-        out[0][sample * channels + ch] = v;                                 \
-}
-
-PUT_FUNC(u8,  AV_SAMPLE_FMT_U8,  uint8_t, av_clip_uint8 ( lrint(v_dbl * (1  <<  7)) + 128))
-PUT_FUNC(s16, AV_SAMPLE_FMT_S16, int16_t, av_clip_int16 ( lrint(v_dbl * (1  << 15))))
-PUT_FUNC(s32, AV_SAMPLE_FMT_S32, int32_t, av_clipl_int32(llrint(v_dbl * (1U << 31))))
-PUT_FUNC(flt, AV_SAMPLE_FMT_FLT, float,   v_dbl)
-PUT_FUNC(dbl, AV_SAMPLE_FMT_DBL, double,  v_dbl)
-
-static void put_sample(void **data, enum AVSampleFormat sample_fmt,
-                       int channels, int sample, int ch, double v_dbl)
-{
-    switch (av_get_packed_sample_fmt(sample_fmt)) {
-    case AV_SAMPLE_FMT_U8:
-        put_sample_u8(data, sample_fmt, channels, sample, ch, v_dbl);
-        break;
-    case AV_SAMPLE_FMT_S16:
-        put_sample_s16(data, sample_fmt, channels, sample, ch, v_dbl);
-        break;
-    case AV_SAMPLE_FMT_S32:
-        put_sample_s32(data, sample_fmt, channels, sample, ch, v_dbl);
-        break;
-    case AV_SAMPLE_FMT_FLT:
-        put_sample_flt(data, sample_fmt, channels, sample, ch, v_dbl);
-        break;
-    case AV_SAMPLE_FMT_DBL:
-        put_sample_dbl(data, sample_fmt, channels, sample, ch, v_dbl);
-        break;
-    }
-}
-
-static void audiogen(AVLFG *rnd, void **data, enum AVSampleFormat sample_fmt,
-                     int channels, int sample_rate, int nb_samples)
-{
-    int i, ch, k;
-    double v, f, a, ampa;
-    double tabf1[AVRESAMPLE_MAX_CHANNELS];
-    double tabf2[AVRESAMPLE_MAX_CHANNELS];
-    double taba[AVRESAMPLE_MAX_CHANNELS];
-
-#define PUT_SAMPLE put_sample(data, sample_fmt, channels, k, ch, v);
-
-    k = 0;
-
-    /* 1 second of single freq sine at 1000 Hz */
-    a = 0;
-    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
-        v = sin(a) * 0.30;
-        for (ch = 0; ch < channels; ch++)
-            PUT_SAMPLE
-        a += M_PI * 1000.0 * 2.0 / sample_rate;
-    }
-
-    /* 1 second of varying frequency between 100 and 10000 Hz */
-    a = 0;
-    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
-        v = sin(a) * 0.30;
-        for (ch = 0; ch < channels; ch++)
-            PUT_SAMPLE
-        f  = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
-        a += M_PI * f * 2.0 / sample_rate;
-    }
-
-    /* 0.5 second of low amplitude white noise */
-    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
-        v = dbl_rand(rnd) * 0.30;
-        for (ch = 0; ch < channels; ch++)
-            PUT_SAMPLE
-    }
-
-    /* 0.5 second of high amplitude white noise */
-    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
-        v = dbl_rand(rnd);
-        for (ch = 0; ch < channels; ch++)
-            PUT_SAMPLE
-    }
-
-    /* 1 second of unrelated ramps for each channel */
-    for (ch = 0; ch < channels; ch++) {
-        taba[ch]  = 0;
-        tabf1[ch] = 100 + av_lfg_get(rnd) % 5000;
-        tabf2[ch] = 100 + av_lfg_get(rnd) % 5000;
-    }
-    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
-        for (ch = 0; ch < channels; ch++) {
-            v = sin(taba[ch]) * 0.30;
-            PUT_SAMPLE
-            f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
-            taba[ch] += M_PI * f * 2.0 / sample_rate;
-        }
-    }
-
-    /* 2 seconds of 500 Hz with varying volume */
-    a    = 0;
-    ampa = 0;
-    for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
-        for (ch = 0; ch < channels; ch++) {
-            double amp = (1.0 + sin(ampa)) * 0.15;
-            if (ch & 1)
-                amp = 0.30 - amp;
-            v = sin(a) * amp;
-            PUT_SAMPLE
-            a    += M_PI * 500.0 * 2.0 / sample_rate;
-            ampa += M_PI *  2.0 / sample_rate;
-        }
-    }
-}
-
-/* formats, rates, and layouts are ordered for priority in testing.
-   e.g. 'avresample-test 4 2 2' will test all input/output combinations of
-   S16/FLTP/S16P/FLT, 48000/44100, and stereo/mono */
-
-static const enum AVSampleFormat formats[] = {
-    AV_SAMPLE_FMT_S16,
-    AV_SAMPLE_FMT_FLTP,
-    AV_SAMPLE_FMT_S16P,
-    AV_SAMPLE_FMT_FLT,
-    AV_SAMPLE_FMT_S32P,
-    AV_SAMPLE_FMT_S32,
-    AV_SAMPLE_FMT_U8P,
-    AV_SAMPLE_FMT_U8,
-    AV_SAMPLE_FMT_DBLP,
-    AV_SAMPLE_FMT_DBL,
-};
-
-static const int rates[] = {
-    48000,
-    44100,
-    16000
-};
-
-static const uint64_t layouts[] = {
-    AV_CH_LAYOUT_STEREO,
-    AV_CH_LAYOUT_MONO,
-    AV_CH_LAYOUT_5POINT1,
-    AV_CH_LAYOUT_7POINT1,
-};
-
-int main(int argc, char **argv)
-{
-    AVAudioResampleContext *s;
-    AVLFG rnd;
-    int ret = 0;
-    uint8_t *in_buf = NULL;
-    uint8_t *out_buf = NULL;
-    unsigned int in_buf_size;
-    unsigned int out_buf_size;
-    uint8_t  *in_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
-    uint8_t *out_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
-    int in_linesize;
-    int out_linesize;
-    uint64_t in_ch_layout;
-    int in_channels;
-    enum AVSampleFormat in_fmt;
-    int in_rate;
-    uint64_t out_ch_layout;
-    int out_channels;
-    enum AVSampleFormat out_fmt;
-    int out_rate;
-    int num_formats, num_rates, num_layouts;
-    int i, j, k, l, m, n;
-
-    num_formats = 2;
-    num_rates   = 2;
-    num_layouts = 2;
-    if (argc > 1) {
-        if (!av_strncasecmp(argv[1], "-h", 3)) {
-            av_log(NULL, AV_LOG_INFO, "Usage: avresample-test [<num formats> "
-                   "[<num sample rates> [<num channel layouts>]]]\n"
-                   "Default is 2 2 2\n");
-            return 0;
-        }
-        num_formats = strtol(argv[1], NULL, 0);
-        num_formats = av_clip(num_formats, 1, FF_ARRAY_ELEMS(formats));
-    }
-    if (argc > 2) {
-        num_rates = strtol(argv[2], NULL, 0);
-        num_rates = av_clip(num_rates, 1, FF_ARRAY_ELEMS(rates));
-    }
-    if (argc > 3) {
-        num_layouts = strtol(argv[3], NULL, 0);
-        num_layouts = av_clip(num_layouts, 1, FF_ARRAY_ELEMS(layouts));
-    }
-
-    av_log_set_level(AV_LOG_DEBUG);
-
-    av_lfg_init(&rnd, 0xC0FFEE);
-
-    in_buf_size = av_samples_get_buffer_size(&in_linesize, 8, 48000 * 6,
-                                             AV_SAMPLE_FMT_DBLP, 0);
-    out_buf_size = in_buf_size;
-
-    in_buf = av_malloc(in_buf_size);
-    if (!in_buf)
-        goto end;
-    out_buf = av_malloc(out_buf_size);
-    if (!out_buf)
-        goto end;
-
-    s = avresample_alloc_context();
-    if (!s) {
-        av_log(NULL, AV_LOG_ERROR, "Error allocating AVAudioResampleContext\n");
-        ret = 1;
-        goto end;
-    }
-
-    for (i = 0; i < num_formats; i++) {
-        in_fmt = formats[i];
-        for (k = 0; k < num_layouts; k++) {
-            in_ch_layout = layouts[k];
-            in_channels  = av_get_channel_layout_nb_channels(in_ch_layout);
-            for (m = 0; m < num_rates; m++) {
-                in_rate = rates[m];
-
-                ret = av_samples_fill_arrays(in_data, &in_linesize, in_buf,
-                                             in_channels, in_rate * 6,
-                                             in_fmt, 0);
-                if (ret < 0) {
-                    av_log(s, AV_LOG_ERROR, "failed in_data fill arrays\n");
-                    goto end;
-                }
-                audiogen(&rnd, (void **)in_data, in_fmt, in_channels, in_rate, in_rate * 6);
-
-                for (j = 0; j < num_formats; j++) {
-                    out_fmt = formats[j];
-                    for (l = 0; l < num_layouts; l++) {
-                        out_ch_layout = layouts[l];
-                        out_channels  = av_get_channel_layout_nb_channels(out_ch_layout);
-                        for (n = 0; n < num_rates; n++) {
-                            out_rate = rates[n];
-
-                            av_log(NULL, AV_LOG_INFO, "%s to %s, %d to %d channels, %d Hz to %d Hz\n",
-                                   av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt),
-                                   in_channels, out_channels, in_rate, out_rate);
-
-                            ret = av_samples_fill_arrays(out_data, &out_linesize,
-                                                         out_buf, out_channels,
-                                                         out_rate * 6, out_fmt, 0);
-                            if (ret < 0) {
-                                av_log(s, AV_LOG_ERROR, "failed out_data fill arrays\n");
-                                goto end;
-                            }
-
-                            av_opt_set_int(s, "in_channel_layout",  in_ch_layout,  0);
-                            av_opt_set_int(s, "in_sample_fmt",      in_fmt,        0);
-                            av_opt_set_int(s, "in_sample_rate",     in_rate,       0);
-                            av_opt_set_int(s, "out_channel_layout", out_ch_layout, 0);
-                            av_opt_set_int(s, "out_sample_fmt",     out_fmt,       0);
-                            av_opt_set_int(s, "out_sample_rate",    out_rate,      0);
-
-                            av_opt_set_int(s, "internal_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
-
-                            ret = avresample_open(s);
-                            if (ret < 0) {
-                                av_log(s, AV_LOG_ERROR, "Error opening context\n");
-                                goto end;
-                            }
-
-                            ret = avresample_convert(s, out_data, out_linesize, out_rate * 6,
-                                                         in_data,  in_linesize,  in_rate * 6);
-                            if (ret < 0) {
-                                char errbuf[256];
-                                av_strerror(ret, errbuf, sizeof(errbuf));
-                                av_log(NULL, AV_LOG_ERROR, "%s\n", errbuf);
-                                goto end;
-                            }
-                            av_log(NULL, AV_LOG_INFO, "Converted %d samples to %d samples\n",
-                                   in_rate * 6, ret);
-                            if (avresample_get_delay(s) > 0)
-                                av_log(NULL, AV_LOG_INFO, "%d delay samples not converted\n",
-                                       avresample_get_delay(s));
-                            if (avresample_available(s) > 0)
-                                av_log(NULL, AV_LOG_INFO, "%d samples available for output\n",
-                                       avresample_available(s));
-                            av_log(NULL, AV_LOG_INFO, "\n");
-
-                            avresample_close(s);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    ret = 0;
-
-end:
-    av_freep(&in_buf);
-    av_freep(&out_buf);
-    avresample_free(&s);
-    return ret;
-}
diff --git a/libavresample/dither.h b/libavresample/dither.h
index c53e822..72f09cb 100644
--- a/libavresample/dither.h
+++ b/libavresample/dither.h
@@ -37,8 +37,8 @@ typedef struct DitherDSPContext {
      */
     void (*quantize)(int16_t *dst, const float *src, float *dither, int len);
 
-    int ptr_align;      ///< src and dst constraits for quantize()
-    int samples_align;  ///< len constraits for quantize()
+    int ptr_align;      ///< src and dst constraints for quantize()
+    int samples_align;  ///< len constraints for quantize()
 
     /**
      * Convert dither noise from int to float with triangular distribution.
diff --git a/libavresample/resample.c b/libavresample/resample.c
index 651670d..dc14cc2 100644
--- a/libavresample/resample.c
+++ b/libavresample/resample.c
@@ -46,7 +46,7 @@
 #include "resample_template.c"
 
 
-/* 0th order modified bessel function of the first kind. */
+/* 0th order modified Bessel function of the first kind. */
 static double bessel(double x)
 {
     double v     = 1;
diff --git a/libavresample/tests/avresample.c b/libavresample/tests/avresample.c
new file mode 100644
index 0000000..8c377ba
--- /dev/null
+++ b/libavresample/tests/avresample.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2002 Fabrice Bellard
+ * Copyright (c) 2012 Justin Ruggles <justin.ruggles at gmail.com>
+ *
+ * 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 <stdint.h>
+#include <stdio.h>
+
+#include "libavutil/avstring.h"
+#include "libavutil/common.h"
+#include "libavutil/lfg.h"
+#include "libavutil/libm.h"
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+#include "libavutil/samplefmt.h"
+
+#include "libavresample/avresample.h"
+
+static double dbl_rand(AVLFG *lfg)
+{
+    return 2.0 * (av_lfg_get(lfg) / (double)UINT_MAX) - 1.0;
+}
+
+#define PUT_FUNC(name, fmt, type, expr)                                     \
+static void put_sample_ ## name(void **data, enum AVSampleFormat sample_fmt,\
+                                int channels, int sample, int ch,           \
+                                double v_dbl)                               \
+{                                                                           \
+    type v = expr;                                                          \
+    type **out = (type **)data;                                             \
+    if (av_sample_fmt_is_planar(sample_fmt))                                \
+        out[ch][sample] = v;                                                \
+    else                                                                    \
+        out[0][sample * channels + ch] = v;                                 \
+}
+
+PUT_FUNC(u8,  AV_SAMPLE_FMT_U8,  uint8_t, av_clip_uint8 ( lrint(v_dbl * (1  <<  7)) + 128))
+PUT_FUNC(s16, AV_SAMPLE_FMT_S16, int16_t, av_clip_int16 ( lrint(v_dbl * (1  << 15))))
+PUT_FUNC(s32, AV_SAMPLE_FMT_S32, int32_t, av_clipl_int32(llrint(v_dbl * (1U << 31))))
+PUT_FUNC(flt, AV_SAMPLE_FMT_FLT, float,   v_dbl)
+PUT_FUNC(dbl, AV_SAMPLE_FMT_DBL, double,  v_dbl)
+
+static void put_sample(void **data, enum AVSampleFormat sample_fmt,
+                       int channels, int sample, int ch, double v_dbl)
+{
+    switch (av_get_packed_sample_fmt(sample_fmt)) {
+    case AV_SAMPLE_FMT_U8:
+        put_sample_u8(data, sample_fmt, channels, sample, ch, v_dbl);
+        break;
+    case AV_SAMPLE_FMT_S16:
+        put_sample_s16(data, sample_fmt, channels, sample, ch, v_dbl);
+        break;
+    case AV_SAMPLE_FMT_S32:
+        put_sample_s32(data, sample_fmt, channels, sample, ch, v_dbl);
+        break;
+    case AV_SAMPLE_FMT_FLT:
+        put_sample_flt(data, sample_fmt, channels, sample, ch, v_dbl);
+        break;
+    case AV_SAMPLE_FMT_DBL:
+        put_sample_dbl(data, sample_fmt, channels, sample, ch, v_dbl);
+        break;
+    }
+}
+
+static void audiogen(AVLFG *rnd, void **data, enum AVSampleFormat sample_fmt,
+                     int channels, int sample_rate, int nb_samples)
+{
+    int i, ch, k;
+    double v, f, a, ampa;
+    double tabf1[AVRESAMPLE_MAX_CHANNELS];
+    double tabf2[AVRESAMPLE_MAX_CHANNELS];
+    double taba[AVRESAMPLE_MAX_CHANNELS];
+
+#define PUT_SAMPLE put_sample(data, sample_fmt, channels, k, ch, v);
+
+    k = 0;
+
+    /* 1 second of single freq sine at 1000 Hz */
+    a = 0;
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
+        v = sin(a) * 0.30;
+        for (ch = 0; ch < channels; ch++)
+            PUT_SAMPLE
+        a += M_PI * 1000.0 * 2.0 / sample_rate;
+    }
+
+    /* 1 second of varying frequency between 100 and 10000 Hz */
+    a = 0;
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
+        v = sin(a) * 0.30;
+        for (ch = 0; ch < channels; ch++)
+            PUT_SAMPLE
+        f  = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
+        a += M_PI * f * 2.0 / sample_rate;
+    }
+
+    /* 0.5 second of low amplitude white noise */
+    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
+        v = dbl_rand(rnd) * 0.30;
+        for (ch = 0; ch < channels; ch++)
+            PUT_SAMPLE
+    }
+
+    /* 0.5 second of high amplitude white noise */
+    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
+        v = dbl_rand(rnd);
+        for (ch = 0; ch < channels; ch++)
+            PUT_SAMPLE
+    }
+
+    /* 1 second of unrelated ramps for each channel */
+    for (ch = 0; ch < channels; ch++) {
+        taba[ch]  = 0;
+        tabf1[ch] = 100 + av_lfg_get(rnd) % 5000;
+        tabf2[ch] = 100 + av_lfg_get(rnd) % 5000;
+    }
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
+        for (ch = 0; ch < channels; ch++) {
+            v = sin(taba[ch]) * 0.30;
+            PUT_SAMPLE
+            f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
+            taba[ch] += M_PI * f * 2.0 / sample_rate;
+        }
+    }
+
+    /* 2 seconds of 500 Hz with varying volume */
+    a    = 0;
+    ampa = 0;
+    for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
+        for (ch = 0; ch < channels; ch++) {
+            double amp = (1.0 + sin(ampa)) * 0.15;
+            if (ch & 1)
+                amp = 0.30 - amp;
+            v = sin(a) * amp;
+            PUT_SAMPLE
+            a    += M_PI * 500.0 * 2.0 / sample_rate;
+            ampa += M_PI *  2.0 / sample_rate;
+        }
+    }
+}
+
+/* formats, rates, and layouts are ordered for priority in testing.
+   e.g. 'avresample-test 4 2 2' will test all input/output combinations of
+   S16/FLTP/S16P/FLT, 48000/44100, and stereo/mono */
+
+static const enum AVSampleFormat formats[] = {
+    AV_SAMPLE_FMT_S16,
+    AV_SAMPLE_FMT_FLTP,
+    AV_SAMPLE_FMT_S16P,
+    AV_SAMPLE_FMT_FLT,
+    AV_SAMPLE_FMT_S32P,
+    AV_SAMPLE_FMT_S32,
+    AV_SAMPLE_FMT_U8P,
+    AV_SAMPLE_FMT_U8,
+    AV_SAMPLE_FMT_DBLP,
+    AV_SAMPLE_FMT_DBL,
+};
+
+static const int rates[] = {
+    48000,
+    44100,
+    16000
+};
+
+static const uint64_t layouts[] = {
+    AV_CH_LAYOUT_STEREO,
+    AV_CH_LAYOUT_MONO,
+    AV_CH_LAYOUT_5POINT1,
+    AV_CH_LAYOUT_7POINT1,
+};
+
+int main(int argc, char **argv)
+{
+    AVAudioResampleContext *s;
+    AVLFG rnd;
+    int ret = 0;
+    uint8_t *in_buf = NULL;
+    uint8_t *out_buf = NULL;
+    unsigned int in_buf_size;
+    unsigned int out_buf_size;
+    uint8_t  *in_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
+    uint8_t *out_data[AVRESAMPLE_MAX_CHANNELS] = { 0 };
+    int in_linesize;
+    int out_linesize;
+    uint64_t in_ch_layout;
+    int in_channels;
+    enum AVSampleFormat in_fmt;
+    int in_rate;
+    uint64_t out_ch_layout;
+    int out_channels;
+    enum AVSampleFormat out_fmt;
+    int out_rate;
+    int num_formats, num_rates, num_layouts;
+    int i, j, k, l, m, n;
+
+    num_formats = 2;
+    num_rates   = 2;
+    num_layouts = 2;
+    if (argc > 1) {
+        if (!av_strncasecmp(argv[1], "-h", 3)) {
+            av_log(NULL, AV_LOG_INFO, "Usage: avresample-test [<num formats> "
+                   "[<num sample rates> [<num channel layouts>]]]\n"
+                   "Default is 2 2 2\n");
+            return 0;
+        }
+        num_formats = strtol(argv[1], NULL, 0);
+        num_formats = av_clip(num_formats, 1, FF_ARRAY_ELEMS(formats));
+    }
+    if (argc > 2) {
+        num_rates = strtol(argv[2], NULL, 0);
+        num_rates = av_clip(num_rates, 1, FF_ARRAY_ELEMS(rates));
+    }
+    if (argc > 3) {
+        num_layouts = strtol(argv[3], NULL, 0);
+        num_layouts = av_clip(num_layouts, 1, FF_ARRAY_ELEMS(layouts));
+    }
+
+    av_log_set_level(AV_LOG_DEBUG);
+
+    av_lfg_init(&rnd, 0xC0FFEE);
+
+    in_buf_size = av_samples_get_buffer_size(&in_linesize, 8, 48000 * 6,
+                                             AV_SAMPLE_FMT_DBLP, 0);
+    out_buf_size = in_buf_size;
+
+    in_buf = av_malloc(in_buf_size);
+    if (!in_buf)
+        goto end;
+    out_buf = av_malloc(out_buf_size);
+    if (!out_buf)
+        goto end;
+
+    s = avresample_alloc_context();
+    if (!s) {
+        av_log(NULL, AV_LOG_ERROR, "Error allocating AVAudioResampleContext\n");
+        ret = 1;
+        goto end;
+    }
+
+    for (i = 0; i < num_formats; i++) {
+        in_fmt = formats[i];
+        for (k = 0; k < num_layouts; k++) {
+            in_ch_layout = layouts[k];
+            in_channels  = av_get_channel_layout_nb_channels(in_ch_layout);
+            for (m = 0; m < num_rates; m++) {
+                in_rate = rates[m];
+
+                ret = av_samples_fill_arrays(in_data, &in_linesize, in_buf,
+                                             in_channels, in_rate * 6,
+                                             in_fmt, 0);
+                if (ret < 0) {
+                    av_log(s, AV_LOG_ERROR, "failed in_data fill arrays\n");
+                    goto end;
+                }
+                audiogen(&rnd, (void **)in_data, in_fmt, in_channels, in_rate, in_rate * 6);
+
+                for (j = 0; j < num_formats; j++) {
+                    out_fmt = formats[j];
+                    for (l = 0; l < num_layouts; l++) {
+                        out_ch_layout = layouts[l];
+                        out_channels  = av_get_channel_layout_nb_channels(out_ch_layout);
+                        for (n = 0; n < num_rates; n++) {
+                            out_rate = rates[n];
+
+                            av_log(NULL, AV_LOG_INFO, "%s to %s, %d to %d channels, %d Hz to %d Hz\n",
+                                   av_get_sample_fmt_name(in_fmt), av_get_sample_fmt_name(out_fmt),
+                                   in_channels, out_channels, in_rate, out_rate);
+
+                            ret = av_samples_fill_arrays(out_data, &out_linesize,
+                                                         out_buf, out_channels,
+                                                         out_rate * 6, out_fmt, 0);
+                            if (ret < 0) {
+                                av_log(s, AV_LOG_ERROR, "failed out_data fill arrays\n");
+                                goto end;
+                            }
+
+                            av_opt_set_int(s, "in_channel_layout",  in_ch_layout,  0);
+                            av_opt_set_int(s, "in_sample_fmt",      in_fmt,        0);
+                            av_opt_set_int(s, "in_sample_rate",     in_rate,       0);
+                            av_opt_set_int(s, "out_channel_layout", out_ch_layout, 0);
+                            av_opt_set_int(s, "out_sample_fmt",     out_fmt,       0);
+                            av_opt_set_int(s, "out_sample_rate",    out_rate,      0);
+
+                            av_opt_set_int(s, "internal_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
+
+                            ret = avresample_open(s);
+                            if (ret < 0) {
+                                av_log(s, AV_LOG_ERROR, "Error opening context\n");
+                                goto end;
+                            }
+
+                            ret = avresample_convert(s, out_data, out_linesize, out_rate * 6,
+                                                         in_data,  in_linesize,  in_rate * 6);
+                            if (ret < 0) {
+                                char errbuf[256];
+                                av_strerror(ret, errbuf, sizeof(errbuf));
+                                av_log(NULL, AV_LOG_ERROR, "%s\n", errbuf);
+                                goto end;
+                            }
+                            av_log(NULL, AV_LOG_INFO, "Converted %d samples to %d samples\n",
+                                   in_rate * 6, ret);
+                            if (avresample_get_delay(s) > 0)
+                                av_log(NULL, AV_LOG_INFO, "%d delay samples not converted\n",
+                                       avresample_get_delay(s));
+                            if (avresample_available(s) > 0)
+                                av_log(NULL, AV_LOG_INFO, "%d samples available for output\n",
+                                       avresample_available(s));
+                            av_log(NULL, AV_LOG_INFO, "\n");
+
+                            avresample_close(s);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    ret = 0;
+
+end:
+    av_freep(&in_buf);
+    av_freep(&out_buf);
+    avresample_free(&s);
+    return ret;
+}
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 65b2d25..1e06176 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -22,6 +22,7 @@ HEADERS = adler32.h                                                     \
           cpu.h                                                         \
           crc.h                                                         \
           des.h                                                         \
+          dict.h                                                        \
           display.h                                                     \
           downmix_info.h                                                \
           error.h                                                       \
@@ -31,6 +32,11 @@ HEADERS = adler32.h                                                     \
           frame.h                                                       \
           hash.h                                                        \
           hmac.h                                                        \
+          hwcontext.h                                                   \
+          hwcontext_cuda.h                                              \
+          hwcontext_dxva2.h                                             \
+          hwcontext_vaapi.h                                             \
+          hwcontext_vdpau.h                                             \
           imgutils.h                                                    \
           intfloat.h                                                    \
           intreadwrite.h                                                \
@@ -43,7 +49,6 @@ HEADERS = adler32.h                                                     \
           mem.h                                                         \
           motion_vector.h                                               \
           murmur3.h                                                     \
-          dict.h                                                        \
           opt.h                                                         \
           parseutils.h                                                  \
           pixdesc.h                                                     \
@@ -51,8 +56,8 @@ HEADERS = adler32.h                                                     \
           pixfmt.h                                                      \
           random_seed.h                                                 \
           rc4.h                                                         \
-          replaygain.h                                                  \
           rational.h                                                    \
+          replaygain.h                                                  \
           ripemd.h                                                      \
           samplefmt.h                                                   \
           sha.h                                                         \
@@ -96,6 +101,7 @@ OBJS = adler32.o                                                        \
        cpu.o                                                            \
        crc.o                                                            \
        des.o                                                            \
+       dict.o                                                           \
        display.o                                                        \
        downmix_info.o                                                   \
        error.o                                                          \
@@ -108,6 +114,7 @@ OBJS = adler32.o                                                        \
        frame.o                                                          \
        hash.o                                                           \
        hmac.o                                                           \
+       hwcontext.o                                                      \
        imgutils.o                                                       \
        integer.o                                                        \
        intmath.o                                                        \
@@ -120,7 +127,6 @@ OBJS = adler32.o                                                        \
        md5.o                                                            \
        mem.o                                                            \
        murmur3.o                                                        \
-       dict.o                                                           \
        opt.o                                                            \
        parseutils.o                                                     \
        pixdesc.o                                                        \
@@ -146,14 +152,22 @@ OBJS = adler32.o                                                        \
 
 OBJS-$(!HAVE_ATOMICS_NATIVE)            += atomic.o                     \
 
+OBJS-$(CONFIG_CUDA)                     += hwcontext_cuda.o
+OBJS-$(CONFIG_DXVA2)                    += hwcontext_dxva2.o
 OBJS-$(CONFIG_LZO)                      += lzo.o
 OBJS-$(CONFIG_OPENCL)                   += opencl.o opencl_internal.o
+OBJS-$(CONFIG_VAAPI)                    += hwcontext_vaapi.o
+OBJS-$(CONFIG_VDPAU)                    += hwcontext_vdpau.o
 
 OBJS += $(COMPAT_OBJS:%=../compat/%)
 
 # Windows resource file
 SLIBOBJS-$(HAVE_GNU_WINDRES)            += avutilres.o
 
+SKIPHEADERS-$(CONFIG_CUDA)             += hwcontext_cuda.h
+SKIPHEADERS-$(CONFIG_DXVA2)            += hwcontext_dxva2.h
+SKIPHEADERS-$(CONFIG_VAAPI)            += hwcontext_vaapi.h
+SKIPHEADERS-$(CONFIG_VDPAU)            += hwcontext_vdpau.h
 SKIPHEADERS-$(HAVE_ATOMICS_GCC)        += atomic_gcc.h
 SKIPHEADERS-$(HAVE_ATOMICS_SUNCC)      += atomic_suncc.h
 SKIPHEADERS-$(HAVE_ATOMICS_WIN32)      += atomic_win32.h
@@ -168,15 +182,18 @@ TESTPROGS = adler32                                                     \
             bprint                                                      \
             cast5                                                       \
             camellia                                                    \
+            color_utils                                                 \
             cpu                                                         \
             crc                                                         \
             des                                                         \
             dict                                                        \
+            display                                                     \
             error                                                       \
             eval                                                        \
             file                                                        \
             fifo                                                        \
             float_dsp                                                   \
+            hash                                                        \
             hmac                                                        \
             lfg                                                         \
             lls                                                         \
@@ -207,4 +224,4 @@ TOOLS = crypto_bench ffhash ffeval ffescape
 tools/crypto_bench$(EXESUF): ELIBS += $(if $(VERSUS),$(subst +, -l,+$(VERSUS)),)
 tools/crypto_bench$(EXESUF): CFLAGS += -DUSE_EXT_LIBS=0$(if $(VERSUS),$(subst +,+USE_,+$(VERSUS)),)
 
-$(SUBDIR)lzo-test$(EXESUF): ELIBS = -llzo2
+$(SUBDIR)tests/lzo$(EXESUF): ELIBS = -llzo2
diff --git a/libavutil/adler32.c b/libavutil/adler32.c
index 64c8767..c87d5e2 100644
--- a/libavutil/adler32.c
+++ b/libavutil/adler32.c
@@ -95,38 +95,3 @@ unsigned long av_adler32_update(unsigned long adler, const uint8_t * buf,
     }
     return (s2 << 16) | s1;
 }
-
-#ifdef TEST
-// LCOV_EXCL_START
-#include <string.h>
-#include "log.h"
-#include "timer.h"
-#define LEN 7001
-
-static volatile int checksum;
-
-int main(int argc, char **argv)
-{
-    int i;
-    uint8_t data[LEN];
-
-    av_log_set_level(AV_LOG_DEBUG);
-
-    for (i = 0; i < LEN; i++)
-        data[i] = ((i * i) >> 3) + 123 * i;
-
-    if (argc > 1 && !strcmp(argv[1], "-t")) {
-        for (i = 0; i < 1000; i++) {
-            START_TIMER;
-            checksum = av_adler32_update(1, data, LEN);
-            STOP_TIMER("adler");
-        }
-    } else {
-        checksum = av_adler32_update(1, data, LEN);
-    }
-
-    av_log(NULL, AV_LOG_DEBUG, "%X (expected 50E6E508)\n", checksum);
-    return checksum == 0x50e6e508 ? 0 : 1;
-}
-// LCOV_EXCL_STOP
-#endif
diff --git a/libavutil/aes.c b/libavutil/aes.c
index 9096f03..397ea77 100644
--- a/libavutil/aes.c
+++ b/libavutil/aes.c
@@ -34,7 +34,7 @@ struct AVAES *av_aes_alloc(void)
 }
 
 static const uint8_t rcon[10] = {
-  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
+    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
 };
 
 static uint8_t     sbox[256];
@@ -97,7 +97,8 @@ static void subshift(av_aes_block s0[2], int s, const uint8_t *box)
     s3[0].u8[ 5] = box[s3[1].u8[ 1]];
 }
 
-static inline int mix_core(uint32_t multbl[][256], int a, int b, int c, int d){
+static inline int mix_core(uint32_t multbl[][256], int a, int b, int c, int d)
+{
 #if CONFIG_SMALL
     return multbl[0][a] ^ ROT(multbl[0][b], 8) ^ ROT(multbl[0][c], 16) ^ ROT(multbl[0][d], 24);
 #else
@@ -105,12 +106,13 @@ static inline int mix_core(uint32_t multbl[][256], int a, int b, int c, int d){
 #endif
 }
 
-static inline void mix(av_aes_block state[2], uint32_t multbl[][256], int s1, int s3){
+static inline void mix(av_aes_block state[2], uint32_t multbl[][256], int s1, int s3)
+{
     uint8_t (*src)[4] = state[1].u8x4;
-    state[0].u32[0] = mix_core(multbl, src[0][0], src[s1  ][1], src[2][2], src[s3  ][3]);
-    state[0].u32[1] = mix_core(multbl, src[1][0], src[s3-1][1], src[3][2], src[s1-1][3]);
-    state[0].u32[2] = mix_core(multbl, src[2][0], src[s3  ][1], src[0][2], src[s1  ][3]);
-    state[0].u32[3] = mix_core(multbl, src[3][0], src[s1-1][1], src[1][2], src[s3-1][3]);
+    state[0].u32[0] = mix_core(multbl, src[0][0], src[s1    ][1], src[2][2], src[s3    ][3]);
+    state[0].u32[1] = mix_core(multbl, src[1][0], src[s3 - 1][1], src[3][2], src[s1 - 1][3]);
+    state[0].u32[2] = mix_core(multbl, src[2][0], src[s3    ][1], src[0][2], src[s1    ][3]);
+    state[0].u32[3] = mix_core(multbl, src[3][0], src[s1 - 1][1], src[1][2], src[s3 - 1][3]);
 }
 
 static inline void aes_crypt(AVAES *a, int s, const uint8_t *sbox,
@@ -179,7 +181,7 @@ static void init_multbl2(uint32_t tbl[][256], const int c[4],
             l = alog8[x + log8[c[1]]];
             m = alog8[x + log8[c[2]]];
             n = alog8[x + log8[c[3]]];
-            tbl[0][i] = AV_NE(MKBETAG(k,l,m,n), MKTAG(k,l,m,n));
+            tbl[0][i] = AV_NE(MKBETAG(k, l, m, n), MKTAG(k, l, m, n));
 #if !CONFIG_SMALL
             tbl[1][i] = ROT(tbl[0][i], 8);
             tbl[2][i] = ROT(tbl[0][i], 16);
@@ -201,7 +203,7 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
 
     a->crypt = decrypt ? aes_decrypt : aes_encrypt;
 
-    if (!enc_multbl[FF_ARRAY_ELEMS(enc_multbl)-1][FF_ARRAY_ELEMS(enc_multbl[0])-1]) {
+    if (!enc_multbl[FF_ARRAY_ELEMS(enc_multbl) - 1][FF_ARRAY_ELEMS(enc_multbl[0]) - 1]) {
         j = 1;
         for (i = 0; i < 255; i++) {
             alog8[i] = alog8[i + 255] = j;
@@ -215,7 +217,7 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
             j ^= (j << 1) ^ (j << 2) ^ (j << 3) ^ (j << 4);
             j = (j ^ (j >> 8) ^ 99) & 255;
             inv_sbox[j] = i;
-            sbox[i] = j;
+            sbox[i]     = j;
         }
         init_multbl2(dec_multbl, (const int[4]) { 0xe, 0x9, 0xd, 0xb },
                      log8, alog8, inv_sbox);
@@ -257,96 +259,10 @@ int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
             a->round_key[i] = tmp[0];
         }
     } else {
-        for (i = 0; i < (rounds + 1) >> 1; i++) {
-            FFSWAP(av_aes_block, a->round_key[i], a->round_key[rounds-i]);
-        }
+        for (i = 0; i < (rounds + 1) >> 1; i++)
+            FFSWAP(av_aes_block, a->round_key[i], a->round_key[rounds - i]);
     }
 
     return 0;
 }
 
-#ifdef TEST
-// LCOV_EXCL_START
-#include <string.h>
-#include "lfg.h"
-#include "log.h"
-
-int main(int argc, char **argv)
-{
-    int i, j;
-    AVAES b;
-    uint8_t rkey[2][16] = {
-        { 0 },
-        { 0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3,
-          0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59 }
-    };
-    uint8_t pt[32], rpt[2][16]= {
-        { 0x6a, 0x84, 0x86, 0x7c, 0xd7, 0x7e, 0x12, 0xad,
-          0x07, 0xea, 0x1b, 0xe8, 0x95, 0xc5, 0x3f, 0xa3 },
-        { 0 }
-    };
-    uint8_t rct[2][16]= {
-        { 0x73, 0x22, 0x81, 0xc0, 0xa0, 0xaa, 0xb8, 0xf7,
-          0xa5, 0x4a, 0x0c, 0x67, 0xa0, 0xc4, 0x5e, 0xcf },
-        { 0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0,
-          0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65 }
-    };
-    uint8_t temp[32];
-    uint8_t iv[2][16];
-    int err = 0;
-
-    av_log_set_level(AV_LOG_DEBUG);
-
-    for (i = 0; i < 2; i++) {
-        av_aes_init(&b, rkey[i], 128, 1);
-        av_aes_crypt(&b, temp, rct[i], 1, NULL, 1);
-        for (j = 0; j < 16; j++) {
-            if (rpt[i][j] != temp[j]) {
-                av_log(NULL, AV_LOG_ERROR, "%d %02X %02X\n",
-                       j, rpt[i][j], temp[j]);
-                err = 1;
-            }
-        }
-    }
-
-    if (argc > 1 && !strcmp(argv[1], "-t")) {
-        AVAES ae, ad;
-        AVLFG prng;
-
-        av_aes_init(&ae, (const uint8_t*)"PI=3.141592654..", 128, 0);
-        av_aes_init(&ad, (const uint8_t*)"PI=3.141592654..", 128, 1);
-        av_lfg_init(&prng, 1);
-
-        for (i = 0; i < 10000; i++) {
-            for (j = 0; j < 32; j++) {
-                pt[j] = av_lfg_get(&prng);
-            }
-            for (j = 0; j < 16; j++) {
-                iv[0][j] = iv[1][j] = av_lfg_get(&prng);
-            }
-            {
-                START_TIMER;
-                av_aes_crypt(&ae, temp, pt, 2, iv[0], 0);
-                if (!(i & (i - 1)))
-                    av_log(NULL, AV_LOG_ERROR, "%02X %02X %02X %02X\n",
-                           temp[0], temp[5], temp[10], temp[15]);
-                av_aes_crypt(&ad, temp, temp, 2, iv[1], 1);
-                av_aes_crypt(&ae, temp, pt, 2, NULL, 0);
-                if (!(i & (i - 1)))
-                    av_log(NULL, AV_LOG_ERROR, "%02X %02X %02X %02X\n",
-                           temp[0], temp[5], temp[10], temp[15]);
-                av_aes_crypt(&ad, temp, temp, 2, NULL, 1);
-                STOP_TIMER("aes");
-            }
-            for (j = 0; j < 16; j++) {
-                if (pt[j] != temp[j]) {
-                    av_log(NULL, AV_LOG_ERROR, "%d %d %02X %02X\n",
-                           i, j, pt[j], temp[j]);
-                }
-            }
-        }
-    }
-    return err;
-}
-// LCOV_EXCL_STOP
-#endif
diff --git a/libavutil/atomic.c b/libavutil/atomic.c
index b13725d..64cff25 100644
--- a/libavutil/atomic.c
+++ b/libavutil/atomic.c
@@ -107,21 +107,3 @@ void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
 #endif /* HAVE_PTHREADS */
 
 #endif /* !HAVE_ATOMICS_NATIVE */
-
-#ifdef TEST
-#include "avassert.h"
-
-int main(void)
-{
-    volatile int val = 1;
-    int res;
-
-    res = avpriv_atomic_int_add_and_fetch(&val, 1);
-    av_assert0(res == 2);
-    avpriv_atomic_int_set(&val, 3);
-    res = avpriv_atomic_int_get(&val);
-    av_assert0(res == 3);
-
-    return 0;
-}
-#endif
diff --git a/libavutil/atomic_suncc.h b/libavutil/atomic_suncc.h
index 3cad24a..a75a37b 100644
--- a/libavutil/atomic_suncc.h
+++ b/libavutil/atomic_suncc.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
diff --git a/libavutil/audio_fifo.c b/libavutil/audio_fifo.c
index d5298cc..e4d38e0 100644
--- a/libavutil/audio_fifo.c
+++ b/libavutil/audio_fifo.c
@@ -155,6 +155,30 @@ int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples)
     return nb_samples;
 }
 
+int av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offset)
+{
+    int i, ret, size;
+
+    if (offset < 0 || offset >= af->nb_samples)
+        return AVERROR(EINVAL);
+    if (nb_samples < 0)
+        return AVERROR(EINVAL);
+    nb_samples = FFMIN(nb_samples, af->nb_samples);
+    if (!nb_samples)
+        return 0;
+    if (offset > af->nb_samples - nb_samples)
+        return AVERROR(EINVAL);
+
+    offset *= af->sample_size;
+    size = nb_samples * af->sample_size;
+    for (i = 0; i < af->nb_buffers; i++) {
+        if ((ret = av_fifo_generic_peek_at(af->buf[i], data[i], offset, size, NULL)) < 0)
+            return AVERROR_BUG;
+    }
+
+    return nb_samples;
+}
+
 int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples)
 {
     int i, ret, size;
diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h
index 24f91da..d8a9194 100644
--- a/libavutil/audio_fifo.h
+++ b/libavutil/audio_fifo.h
@@ -111,6 +111,23 @@ int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples);
 int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples);
 
 /**
+ * Peek data from an AVAudioFifo.
+ *
+ * @see enum AVSampleFormat
+ * The documentation for AVSampleFormat describes the data layout.
+ *
+ * @param af          AVAudioFifo to read from
+ * @param data        audio data plane pointers
+ * @param nb_samples  number of samples to peek
+ * @param offset      offset from current read position
+ * @return            number of samples actually peek, or negative AVERROR code
+ *                    on failure. The number of samples actually peek will not
+ *                    be greater than nb_samples, and will only be less than
+ *                    nb_samples if av_audio_fifo_size is less than nb_samples.
+ */
+int av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offset);
+
+/**
  * Read data from an AVAudioFifo.
  *
  * @see enum AVSampleFormat
diff --git a/libavutil/avassert.h b/libavutil/avassert.h
index 41f5e0e..f473637 100644
--- a/libavutil/avassert.h
+++ b/libavutil/avassert.h
@@ -45,7 +45,7 @@
 
 /**
  * assert() equivalent, that does not lie in speed critical code.
- * These asserts() thus can be enabled without fearing speedloss.
+ * These asserts() thus can be enabled without fearing speed loss.
  */
 #if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 0
 #define av_assert1(cond) av_assert0(cond)
diff --git a/libavutil/avr32/intreadwrite.h b/libavutil/avr32/intreadwrite.h
index c6fd3aa..95179f1 100644
--- a/libavutil/avr32/intreadwrite.h
+++ b/libavutil/avr32/intreadwrite.h
@@ -27,7 +27,7 @@
 
 /*
  * AVR32 does not support unaligned memory accesses, except for the AP
- * series which suppports unaligned 32-bit loads and stores.  16-bit
+ * series which supports unaligned 32-bit loads and stores.  16-bit
  * and 64-bit accesses must be aligned to 16 and 32 bits, respectively.
  * This means we cannot use the byte-swapping load/store instructions
  * here.
diff --git a/libavutil/avstring.c b/libavutil/avstring.c
index 85fb3e9..1787a1e 100644
--- a/libavutil/avstring.c
+++ b/libavutil/avstring.c
@@ -144,7 +144,7 @@ char *av_d2str(double d)
     return str;
 }
 
-#define WHITESPACES " \n\t"
+#define WHITESPACES " \n\t\r"
 
 char *av_get_token(const char **buf, const char *term)
 {
@@ -435,67 +435,3 @@ int av_match_list(const char *name, const char *list, char separator)
 
     return 0;
 }
-
-#ifdef TEST
-
-int main(void)
-{
-    int i;
-    char *fullpath;
-    static const char * const strings[] = {
-        "''",
-        "",
-        ":",
-        "\\",
-        "'",
-        "    ''    :",
-        "    ''  ''  :",
-        "foo   '' :",
-        "'foo'",
-        "foo     ",
-        "  '  foo  '  ",
-        "foo\\",
-        "foo':  blah:blah",
-        "foo\\:  blah:blah",
-        "foo\'",
-        "'foo :  '  :blahblah",
-        "\\ :blah",
-        "     foo",
-        "      foo       ",
-        "      foo     \\ ",
-        "foo ':blah",
-        " foo   bar    :   blahblah",
-        "\\f\\o\\o",
-        "'foo : \\ \\  '   : blahblah",
-        "'\\fo\\o:': blahblah",
-        "\\'fo\\o\\:':  foo  '  :blahblah"
-    };
-
-    printf("Testing av_get_token()\n");
-    for (i = 0; i < FF_ARRAY_ELEMS(strings); i++) {
-        const char *p = strings[i];
-        char *q;
-        printf("|%s|", p);
-        q = av_get_token(&p, ":");
-        printf(" -> |%s|", q);
-        printf(" + |%s|\n", p);
-        av_free(q);
-    }
-
-    printf("Testing av_append_path_component()\n");
-    #define TEST_APPEND_PATH_COMPONENT(path, component, expected) \
-        fullpath = av_append_path_component((path), (component)); \
-        printf("%s = %s\n", fullpath ? fullpath : "(null)", expected); \
-        av_free(fullpath);
-    TEST_APPEND_PATH_COMPONENT(NULL, NULL, "(null)")
-    TEST_APPEND_PATH_COMPONENT("path", NULL, "path");
-    TEST_APPEND_PATH_COMPONENT(NULL, "comp", "comp");
-    TEST_APPEND_PATH_COMPONENT("path", "comp", "path/comp");
-    TEST_APPEND_PATH_COMPONENT("path/", "comp", "path/comp");
-    TEST_APPEND_PATH_COMPONENT("path", "/comp", "path/comp");
-    TEST_APPEND_PATH_COMPONENT("path/", "/comp", "path/comp");
-    TEST_APPEND_PATH_COMPONENT("path/path2/", "/comp/comp2", "path/path2/comp/comp2");
-    return 0;
-}
-
-#endif /* TEST */
diff --git a/libavutil/avstring.h b/libavutil/avstring.h
index 15b04ba..dd28769 100644
--- a/libavutil/avstring.h
+++ b/libavutil/avstring.h
@@ -156,7 +156,7 @@ static inline size_t av_strnlen(const char *s, size_t len)
 char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2);
 
 /**
- * Convert a number to a av_malloced string.
+ * Convert a number to an av_malloced string.
  */
 char *av_d2str(double d);
 
diff --git a/libavutil/avutil.h b/libavutil/avutil.h
index 9bcf674..c1f76c1 100644
--- a/libavutil/avutil.h
+++ b/libavutil/avutil.h
@@ -266,7 +266,7 @@ enum AVPictureType {
     AV_PICTURE_TYPE_I,     ///< Intra
     AV_PICTURE_TYPE_P,     ///< Predicted
     AV_PICTURE_TYPE_B,     ///< Bi-dir predicted
-    AV_PICTURE_TYPE_S,     ///< S(GMC)-VOP MPEG4
+    AV_PICTURE_TYPE_S,     ///< S(GMC)-VOP MPEG-4
     AV_PICTURE_TYPE_SI,    ///< Switching Intra
     AV_PICTURE_TYPE_SP,    ///< Switching Predicted
     AV_PICTURE_TYPE_BI,    ///< BI type
diff --git a/libavutil/base64.c b/libavutil/base64.c
index 03ebce8..25ae8c4 100644
--- a/libavutil/base64.c
+++ b/libavutil/base64.c
@@ -172,110 +172,3 @@ char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
 
     return ret;
 }
-
-#ifdef TEST
-// LCOV_EXCL_START
-
-#define MAX_DATA_SIZE    1024
-#define MAX_ENCODED_SIZE 2048
-
-static int test_encode_decode(const uint8_t *data, unsigned int data_size,
-                              const char *encoded_ref)
-{
-    char  encoded[MAX_ENCODED_SIZE];
-    uint8_t data2[MAX_DATA_SIZE];
-    int data2_size, max_data2_size = MAX_DATA_SIZE;
-
-    if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) {
-        printf("Failed: cannot encode the input data\n");
-        return 1;
-    }
-    if (encoded_ref && strcmp(encoded, encoded_ref)) {
-        printf("Failed: encoded string differs from reference\n"
-               "Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref);
-        return 1;
-    }
-
-    if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) != data_size) {
-        printf("Failed: cannot decode the encoded string\n"
-               "Encoded:\n%s\n", encoded);
-        return 1;
-    }
-    if ((data2_size = av_base64_decode(data2, encoded, data_size)) != data_size) {
-        printf("Failed: cannot decode with minimal buffer\n"
-               "Encoded:\n%s\n", encoded);
-        return 1;
-    }
-    if (memcmp(data2, data, data_size)) {
-        printf("Failed: encoded/decoded data differs from original data\n");
-        return 1;
-    }
-    if (av_base64_decode(NULL, encoded, 0) != 0) {
-        printf("Failed: decode to NULL buffer\n");
-        return 1;
-    }
-    if (strlen(encoded)) {
-        char *end = strchr(encoded, '=');
-        if (!end)
-            end = encoded + strlen(encoded) - 1;
-        *end = '%';
-        if (av_base64_decode(NULL, encoded, 0) >= 0) {
-            printf("Failed: error detection\n");
-            return 1;
-        }
-    }
-
-    printf("Passed!\n");
-    return 0;
-}
-
-int main(int argc, char ** argv)
-{
-    int i, error_count = 0;
-    struct test {
-        const uint8_t *data;
-        const char *encoded_ref;
-    } tests[] = {
-        { "",        ""},
-        { "1",       "MQ=="},
-        { "22",      "MjI="},
-        { "333",     "MzMz"},
-        { "4444",    "NDQ0NA=="},
-        { "55555",   "NTU1NTU="},
-        { "666666",  "NjY2NjY2"},
-        { "abc:def", "YWJjOmRlZg=="},
-    };
-    char in[1024], out[2048];
-
-    printf("Encoding/decoding tests\n");
-    for (i = 0; i < FF_ARRAY_ELEMS(tests); i++)
-        error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref);
-
-    if (argc>1 && !strcmp(argv[1], "-t")) {
-        memset(in, 123, sizeof(in));
-        for(i=0; i<10000; i++){
-            START_TIMER
-            av_base64_encode(out, sizeof(out), in, sizeof(in));
-            STOP_TIMER("encode")
-        }
-        for(i=0; i<10000; i++){
-            START_TIMER
-            av_base64_decode(in, out, sizeof(in));
-            STOP_TIMER("decode")
-        }
-
-        for(i=0; i<10000; i++){
-            START_TIMER
-            av_base64_decode(NULL, out, 0);
-            STOP_TIMER("syntax check")
-        }
-    }
-
-    if (error_count)
-        printf("Error Count: %d.\n", error_count);
-
-    return !!error_count;
-}
-
-// LCOV_EXCL_STOP
-#endif
diff --git a/libavutil/base64.h b/libavutil/base64.h
index 514498e..2954c12 100644
--- a/libavutil/base64.h
+++ b/libavutil/base64.h
@@ -29,20 +29,25 @@
  * @{
  */
 
-
 /**
  * Decode a base64-encoded string.
  *
  * @param out      buffer for decoded data
  * @param in       null-terminated input string
  * @param out_size size in bytes of the out buffer, must be at
- *                 least 3/4 of the length of in
+ *                 least 3/4 of the length of in, that is AV_BASE64_DECODE_SIZE(strlen(in))
  * @return         number of bytes written, or a negative value in case of
  *                 invalid input
  */
 int av_base64_decode(uint8_t *out, const char *in, int out_size);
 
 /**
+ * Calculate the output size in bytes needed to decode a base64 string
+ * with length x to a data buffer.
+ */
+#define AV_BASE64_DECODE_SIZE(x) ((x) * 3LL / 4)
+
+/**
  * Encode data to base64 and null-terminate.
  *
  * @param out      buffer for encoded data
diff --git a/libavutil/blowfish.c b/libavutil/blowfish.c
index 0ab104e..abc0e03 100644
--- a/libavutil/blowfish.c
+++ b/libavutil/blowfish.c
@@ -422,173 +422,3 @@ void av_blowfish_crypt(AVBlowfish *ctx, uint8_t *dst, const uint8_t *src,
         }
     }
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-#define NUM_VARIABLE_KEY_TESTS 34
-
-/* plaintext bytes -- left halves */
-static const uint32_t plaintext_l[NUM_VARIABLE_KEY_TESTS] = {
-    0x00000000, 0xFFFFFFFF, 0x10000000, 0x11111111, 0x11111111,
-    0x01234567, 0x00000000, 0x01234567, 0x01A1D6D0, 0x5CD54CA8,
-    0x0248D438, 0x51454B58, 0x42FD4430, 0x059B5E08, 0x0756D8E0,
-    0x762514B8, 0x3BDD1190, 0x26955F68, 0x164D5E40, 0x6B056E18,
-    0x004BD6EF, 0x480D3900, 0x437540C8, 0x072D43A0, 0x02FE5577,
-    0x1D9D5C50, 0x30553228, 0x01234567, 0x01234567, 0x01234567,
-    0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF
-};
-
-/* plaintext bytes -- right halves */
-static const uint32_t plaintext_r[NUM_VARIABLE_KEY_TESTS] = {
-    0x00000000, 0xFFFFFFFF, 0x00000001, 0x11111111, 0x11111111,
-    0x89ABCDEF, 0x00000000, 0x89ABCDEF, 0x39776742, 0x3DEF57DA,
-    0x06F67172, 0x2DDF440A, 0x59577FA2, 0x51CF143A, 0x774761D2,
-    0x29BF486A, 0x49372802, 0x35AF609A, 0x4F275232, 0x759F5CCA,
-    0x09176062, 0x6EE762F2, 0x698F3CFA, 0x77075292, 0x8117F12A,
-    0x18F728C2, 0x6D6F295A, 0x89ABCDEF, 0x89ABCDEF, 0x89ABCDEF,
-    0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF
-};
-
-/* key bytes for variable key tests */
-static const uint8_t variable_key[NUM_VARIABLE_KEY_TESTS][8] = {
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
-    { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-    { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 },
-    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
-    { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 },
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-    { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 },
-    { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 },
-    { 0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E },
-    { 0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86 },
-    { 0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E },
-    { 0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6 },
-    { 0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE },
-    { 0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6 },
-    { 0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE },
-    { 0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16 },
-    { 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F },
-    { 0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46 },
-    { 0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E },
-    { 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76 },
-    { 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07 },
-    { 0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F },
-    { 0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7 },
-    { 0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF },
-    { 0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6 },
-    { 0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF },
-    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
-    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
-    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
-    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
-    { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }
-};
-
-/* ciphertext bytes -- left halves */
-static const uint32_t ciphertext_l[NUM_VARIABLE_KEY_TESTS] = {
-    0x4EF99745, 0x51866FD5, 0x7D856F9A, 0x2466DD87, 0x61F9C380,
-    0x7D0CC630, 0x4EF99745, 0x0ACEAB0F, 0x59C68245, 0xB1B8CC0B,
-    0x1730E577, 0xA25E7856, 0x353882B1, 0x48F4D088, 0x432193B7,
-    0x13F04154, 0x2EEDDA93, 0xD887E039, 0x5F99D04F, 0x4A057A3B,
-    0x452031C1, 0x7555AE39, 0x53C55F9C, 0x7A8E7BFA, 0xCF9C5D7A,
-    0xD1ABB290, 0x55CB3774, 0xFA34EC48, 0xA7907951, 0xC39E072D,
-    0x014933E0, 0xF21E9A77, 0x24594688, 0x6B5C5A9C
-};
-
-/* ciphertext bytes -- right halves */
-static const uint32_t ciphertext_r[NUM_VARIABLE_KEY_TESTS] = {
-    0x6198DD78, 0xB85ECB8A, 0x613063F2, 0x8B963C9D, 0x2281B096,
-    0xAFDA1EC7, 0x6198DD78, 0xC6A0A28D, 0xEB05282B, 0x250F09A0,
-    0x8BEA1DA4, 0xCF2651EB, 0x09CE8F1A, 0x4C379918, 0x8951FC98,
-    0xD69D1AE5, 0xFFD39C79, 0x3C2DA6E3, 0x5B163969, 0x24D3977B,
-    0xE4FADA8E, 0xF59B87BD, 0xB49FC019, 0x937E89A3, 0x4986ADB5,
-    0x658BC778, 0xD13EF201, 0x47B268B2, 0x08EA3CAE, 0x9FAC631D,
-    0xCDAFF6E4, 0xB71C49BC, 0x5754369A, 0x5D9E0A5A
-};
-
-/* plaintext bytes */
-static const uint8_t plaintext[8] = "BLOWFISH";
-
-static const uint8_t plaintext2[16] = "BLOWFISHBLOWFISH";
-
-/* ciphertext bytes */
-static const uint8_t ciphertext[8] = {
-    0x32, 0x4E, 0xD0, 0xFE, 0xF4, 0x13, 0xA2, 0x03
-};
-
-static const uint8_t ciphertext2[16] = {
-    0x53, 0x00, 0x40, 0x06, 0x63, 0xf2, 0x1d, 0x99,
-    0x3b, 0x9b, 0x27, 0x64, 0x46, 0xfd, 0x20, 0xc1,
-};
-
-#define IV "blowfish"
-
-static void test_blowfish(AVBlowfish *ctx, uint8_t *dst, const uint8_t *src,
-                          const uint8_t *ref, int len, uint8_t *iv, int dir,
-                          const char *test)
-{
-    av_blowfish_crypt(ctx, dst, src, len, iv, dir);
-    if (memcmp(dst, ref, 8*len)) {
-        int i;
-        printf("%s failed\ngot      ", test);
-        for (i = 0; i < 8*len; i++)
-            printf("%02x ", dst[i]);
-        printf("\nexpected ");
-        for (i = 0; i < 8*len; i++)
-            printf("%02x ", ref[i]);
-        printf("\n");
-        exit(1);
-    }
-}
-
-int main(void)
-{
-    AVBlowfish ctx;
-    uint32_t tmptext_l[NUM_VARIABLE_KEY_TESTS];
-    uint32_t tmptext_r[NUM_VARIABLE_KEY_TESTS];
-    uint8_t tmp[16], iv[8];
-    int i;
-
-    av_blowfish_init(&ctx, "abcdefghijklmnopqrstuvwxyz", 26);
-
-    test_blowfish(&ctx, tmp, plaintext, ciphertext, 1, NULL, 0, "encryption");
-    test_blowfish(&ctx, tmp, ciphertext, plaintext, 1, NULL, 1, "decryption");
-    test_blowfish(&ctx, tmp, tmp, ciphertext, 1, NULL, 0, "Inplace encryption");
-    test_blowfish(&ctx, tmp, tmp, plaintext,  1, NULL, 1, "Inplace decryption");
-    memcpy(iv, IV, 8);
-    test_blowfish(&ctx, tmp, plaintext2, ciphertext2, 2, iv, 0, "CBC encryption");
-    memcpy(iv, IV, 8);
-    test_blowfish(&ctx, tmp, ciphertext2, plaintext2, 2, iv, 1, "CBC decryption");
-    memcpy(iv, IV, 8);
-    test_blowfish(&ctx, tmp, tmp, ciphertext2, 2, iv, 0, "Inplace CBC encryption");
-    memcpy(iv, IV, 8);
-    test_blowfish(&ctx, tmp, tmp, plaintext2,  2, iv, 1, "Inplace CBC decryption");
-
-    memcpy(tmptext_l, plaintext_l, sizeof(*plaintext_l) * NUM_VARIABLE_KEY_TESTS);
-    memcpy(tmptext_r, plaintext_r, sizeof(*plaintext_r) * NUM_VARIABLE_KEY_TESTS);
-
-    for (i = 0; i < NUM_VARIABLE_KEY_TESTS; i++) {
-        av_blowfish_init(&ctx, variable_key[i], 8);
-
-        av_blowfish_crypt_ecb(&ctx, &tmptext_l[i], &tmptext_r[i], 0);
-        if (tmptext_l[i] != ciphertext_l[i] || tmptext_r[i] != ciphertext_r[i]) {
-            printf("Test encryption failed.\n");
-            return 1;
-        }
-
-        av_blowfish_crypt_ecb(&ctx, &tmptext_l[i], &tmptext_r[i], 1);
-        if (tmptext_l[i] != plaintext_l[i] || tmptext_r[i] != plaintext_r[i]) {
-            printf("Test decryption failed.\n");
-            return 1;
-        }
-    }
-    printf("Test encryption/decryption success.\n");
-
-    return 0;
-}
-
-#endif
diff --git a/libavutil/bprint.c b/libavutil/bprint.c
index 0a0d078..2f059c5 100644
--- a/libavutil/bprint.c
+++ b/libavutil/bprint.c
@@ -260,7 +260,7 @@ int av_bprint_finalize(AVBPrint *buf, char **ret_str)
     return ret;
 }
 
-#define WHITESPACES " \n\t"
+#define WHITESPACES " \n\t\r"
 
 void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars,
                       enum AVEscapeMode mode, int flags)
@@ -303,79 +303,3 @@ void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_cha
         break;
     }
 }
-
-#ifdef TEST
-
-#undef printf
-
-static void bprint_pascal(AVBPrint *b, unsigned size)
-{
-    unsigned i, j;
-    unsigned p[42];
-
-    av_assert0(size < FF_ARRAY_ELEMS(p));
-
-    p[0] = 1;
-    av_bprintf(b, "%8d\n", 1);
-    for (i = 1; i <= size; i++) {
-        p[i] = 1;
-        for (j = i - 1; j > 0; j--)
-            p[j] = p[j] + p[j - 1];
-        for (j = 0; j <= i; j++)
-            av_bprintf(b, "%8d", p[j]);
-        av_bprintf(b, "\n");
-    }
-}
-
-int main(void)
-{
-    AVBPrint b;
-    char buf[256];
-    struct tm testtime = { .tm_year = 100, .tm_mon = 11, .tm_mday = 20 };
-
-    av_bprint_init(&b, 0, -1);
-    bprint_pascal(&b, 5);
-    printf("Short text in unlimited buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
-    printf("%s\n", b.str);
-    av_bprint_finalize(&b, NULL);
-
-    av_bprint_init(&b, 0, -1);
-    bprint_pascal(&b, 25);
-    printf("Long text in unlimited buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
-    av_bprint_finalize(&b, NULL);
-
-    av_bprint_init(&b, 0, 2048);
-    bprint_pascal(&b, 25);
-    printf("Long text in limited buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
-    av_bprint_finalize(&b, NULL);
-
-    av_bprint_init(&b, 0, 1);
-    bprint_pascal(&b, 5);
-    printf("Short text in automatic buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
-
-    av_bprint_init(&b, 0, 1);
-    bprint_pascal(&b, 25);
-    printf("Long text in automatic buffer: %u/%u\n", (unsigned)strlen(b.str)/8*8, b.len);
-    /* Note that the size of the automatic buffer is arch-dependent. */
-
-    av_bprint_init(&b, 0, 0);
-    bprint_pascal(&b, 25);
-    printf("Long text count only buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
-
-    av_bprint_init_for_buffer(&b, buf, sizeof(buf));
-    bprint_pascal(&b, 25);
-    printf("Long text count only buffer: %u/%u\n", (unsigned)strlen(buf), b.len);
-
-    av_bprint_init(&b, 0, -1);
-    av_bprint_strftime(&b, "%Y-%m-%d", &testtime);
-    printf("strftime full: %u/%u \"%s\"\n", (unsigned)strlen(buf), b.len, b.str);
-    av_bprint_finalize(&b, NULL);
-
-    av_bprint_init(&b, 0, 8);
-    av_bprint_strftime(&b, "%Y-%m-%d", &testtime);
-    printf("strftime truncated: %u/%u \"%s\"\n", (unsigned)strlen(buf), b.len, b.str);
-
-    return 0;
-}
-
-#endif
diff --git a/libavutil/buffer.c b/libavutil/buffer.c
index bb112c2..694e116 100644
--- a/libavutil/buffer.c
+++ b/libavutil/buffer.c
@@ -214,6 +214,26 @@ int av_buffer_realloc(AVBufferRef **pbuf, int size)
     return 0;
 }
 
+AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
+                                   AVBufferRef* (*alloc)(void *opaque, int size),
+                                   void (*pool_free)(void *opaque))
+{
+    AVBufferPool *pool = av_mallocz(sizeof(*pool));
+    if (!pool)
+        return NULL;
+
+    ff_mutex_init(&pool->mutex, NULL);
+
+    pool->size      = size;
+    pool->opaque    = opaque;
+    pool->alloc2    = alloc;
+    pool->pool_free = pool_free;
+
+    avpriv_atomic_int_set(&pool->refcount, 1);
+
+    return pool;
+}
+
 AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size))
 {
     AVBufferPool *pool = av_mallocz(sizeof(*pool));
@@ -244,6 +264,10 @@ static void buffer_pool_free(AVBufferPool *pool)
         av_freep(&buf);
     }
     ff_mutex_destroy(&pool->mutex);
+
+    if (pool->pool_free)
+        pool->pool_free(pool->opaque);
+
     av_freep(&pool);
 }
 
@@ -326,7 +350,8 @@ static AVBufferRef *pool_alloc_buffer(AVBufferPool *pool)
     BufferPoolEntry *buf;
     AVBufferRef     *ret;
 
-    ret = pool->alloc(pool->size);
+    ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) :
+                         pool->alloc(pool->size);
     if (!ret)
         return NULL;
 
diff --git a/libavutil/buffer.h b/libavutil/buffer.h
index b4399fd..0c0ce12 100644
--- a/libavutil/buffer.h
+++ b/libavutil/buffer.h
@@ -249,13 +249,29 @@ typedef struct AVBufferPool AVBufferPool;
 AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size));
 
 /**
+ * Allocate and initialize a buffer pool with a more complex allocator.
+ *
+ * @param size size of each buffer in this pool
+ * @param opaque arbitrary user data used by the allocator
+ * @param alloc a function that will be used to allocate new buffers when the
+ *              pool is empty.
+ * @param pool_free a function that will be called immediately before the pool
+ *                  is freed. I.e. after av_buffer_pool_can_uninit() is called
+ *                  by the pool and all the frames are returned to the pool and
+ *                  freed. It is intended to uninitialize the user opaque data.
+ * @return newly created buffer pool on success, NULL on error.
+ */
+AVBufferPool *av_buffer_pool_init2(int size, void *opaque,
+                                   AVBufferRef* (*alloc)(void *opaque, int size),
+                                   void (*pool_free)(void *opaque));
+
+/**
  * Mark the pool as being available for freeing. It will actually be freed only
  * once all the allocated buffers associated with the pool are released. Thus it
  * is safe to call this function while some of the allocated buffers are still
  * in use.
  *
  * @param pool pointer to the pool to be freed. It will be set to NULL.
- * @see av_buffer_pool_can_uninit()
  */
 void av_buffer_pool_uninit(AVBufferPool **pool);
 
diff --git a/libavutil/buffer_internal.h b/libavutil/buffer_internal.h
index e653048..29ce8a6 100644
--- a/libavutil/buffer_internal.h
+++ b/libavutil/buffer_internal.h
@@ -90,7 +90,10 @@ struct AVBufferPool {
     volatile int nb_allocated;
 
     int size;
+    void *opaque;
     AVBufferRef* (*alloc)(int size);
+    AVBufferRef* (*alloc2)(void *opaque, int size);
+    void         (*pool_free)(void *opaque);
 };
 
 #endif /* AVUTIL_BUFFER_INTERNAL_H */
diff --git a/libavutil/camellia.c b/libavutil/camellia.c
index f21ca12..f33ee9b 100644
--- a/libavutil/camellia.c
+++ b/libavutil/camellia.c
@@ -410,61 +410,3 @@ void av_camellia_crypt(AVCAMELLIA *cs, uint8_t *dst, const uint8_t *src, int cou
         dst = dst + 16;
     }
 }
-
-#ifdef TEST
-#include<stdio.h>
-#include<stdlib.h>
-#include"log.h"
-
-int main(int argc, char *argv[])
-{
-    const uint8_t Key[3][32] = {
-        {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
-        {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77},
-        {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
-    };
-    const uint8_t rct[3][16] = {
-        {0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43},
-        {0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9,0x96, 0xf8, 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9},
-        {0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09}
-    };
-    const uint8_t rpt[32] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
-    const int kbits[3] = {128, 192, 256};
-    int i, j, err = 0;
-    uint8_t temp[32], iv[16];
-    AVCAMELLIA *cs;
-    cs = av_camellia_alloc();
-    if (!cs)
-        return 1;
-    for (j = 0; j < 3; j++) {
-        av_camellia_init(cs, Key[j], kbits[j]);
-        av_camellia_crypt(cs, temp, rpt, 1, NULL, 0);
-        for (i = 0; i < 16; i++) {
-            if (rct[j][i] != temp[i]) {
-                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[j][i], temp[i]);
-                err = 1;
-            }
-        }
-        av_camellia_crypt(cs, temp, rct[j], 1, NULL, 1);
-        for (i = 0; i < 16; i++) {
-            if (rpt[i] != temp[i]) {
-                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
-                err = 1;
-            }
-        }
-    }
-    av_camellia_init(cs, Key[0], 128);
-    memcpy(iv, "HALLO123HALLO123", 16);
-    av_camellia_crypt(cs, temp, rpt, 2, iv, 0);
-    memcpy(iv, "HALLO123HALLO123", 16);
-    av_camellia_crypt(cs, temp, temp, 2, iv, 1);
-    for (i = 0; i < 32; i++) {
-        if (rpt[i] != temp[i]) {
-            av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
-            err = 1;
-        }
-    }
-    av_free(cs);
-    return err;
-}
-#endif
diff --git a/libavutil/cast5.c b/libavutil/cast5.c
index a47697b..445eb55 100644
--- a/libavutil/cast5.c
+++ b/libavutil/cast5.c
@@ -505,89 +505,3 @@ void av_cast5_crypt(AVCAST5* cs, uint8_t* dst, const uint8_t* src, int count, in
         dst = dst + 8;
     }
 }
-
-#ifdef TEST
-#include<stdio.h>
-#include<stdlib.h>
-#include"log.h"
-
-int main(int argc, char** argv)
-{
-
-    static const uint8_t Key[3][16] = {
-        {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a},
-        {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45},
-        {0x01, 0x23, 0x45, 0x67, 0x12}
-    };
-    static const uint8_t rpt[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
-    static const uint8_t rct[3][8] = {
-        {0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2},
-        {0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b},
-        {0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e}
-    };
-    static const uint8_t rct2[2][16] = {
-        {0xee, 0xa9, 0xd0, 0xa2, 0x49, 0xfd, 0x3b, 0xa6, 0xb3, 0x43, 0x6f, 0xb8, 0x9d, 0x6d, 0xca, 0x92},
-        {0xb2, 0xc9, 0x5e, 0xb0, 0x0c, 0x31, 0xad, 0x71, 0x80, 0xac, 0x05, 0xb8, 0xe8, 0x3d, 0x69, 0x6e}
-    };
-    static const uint8_t iv[8] = {0xee, 0xa9, 0xd0, 0xa2, 0x49, 0xfd, 0x3b, 0xa6};
-    static uint8_t rpt2[2][16];
-    int i, j, err = 0;
-    static const int key_bits[3] = {128, 80, 40};
-    uint8_t temp[8];
-    AVCAST5 *cs;
-    cs = av_cast5_alloc();
-    if (!cs)
-        return 1;
-    for (j = 0; j < 3; j++){
-
-        av_cast5_init(cs, Key[j], key_bits[j]);
-        av_cast5_crypt(cs, temp, rpt, 1, 0);
-        for (i = 0;i < 8; i++){
-            if (rct[j][i] != temp[i]){
-                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[j][i], temp[i]);
-                err = 1;
-            }
-        }
-
-        av_cast5_crypt(cs, temp, rct[j], 1, 1);
-        for (i =0; i < 8; i++) {
-            if (rpt[i] != temp[i]) {
-                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
-                err = 1;
-            }
-        }
-    }
-    memcpy(rpt2[0], Key[0], 16);
-    memcpy(rpt2[1], Key[0], 16);
-    for (i = 0; i < 1000000; i++){
-        av_cast5_init(cs, rpt2[1], 128);
-        av_cast5_crypt(cs, rpt2[0], rpt2[0], 2, 0);
-        av_cast5_init(cs, rpt2[0], 128);
-        av_cast5_crypt(cs, rpt2[1], rpt2[1], 2, 0);
-    }
-    for (j = 0; j < 2; j++) {
-        for (i = 0; i < 16; i++) {
-            if (rct2[j][i] != rpt2[j][i]) {
-                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct2[j][i], rpt2[j][i]);
-                err = 1;
-            }
-        }
-    }
-    for (j = 0; j < 3; j++) {
-
-        av_cast5_init(cs, Key[j], key_bits[j]);
-        memcpy(temp, iv, 8);
-        av_cast5_crypt2(cs, rpt2[0], rct2[0], 2, temp, 0);
-        memcpy(temp, iv, 8);
-        av_cast5_crypt2(cs, rpt2[0], rpt2[0], 2, temp, 1);
-        for (i = 0; i < 16; i++) {
-            if (rct2[0][i] != rpt2[0][i]) {
-                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct2[0][i], rpt2[0][i]);
-                err = 1;
-            }
-        }
-    }
-    av_free(cs);
-    return err;
-}
-#endif
diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c
index b68b402..eb8bc7b 100644
--- a/libavutil/color_utils.c
+++ b/libavutil/color_utils.c
@@ -21,6 +21,7 @@
 #include <stddef.h>
 #include <math.h>
 
+#include "common.h"
 #include "libavutil/color_utils.h"
 #include "libavutil/pixfmt.h"
 
@@ -154,6 +155,18 @@ static double avpriv_trc_smpte_st428_1(double Lc)
          :              pow(48.0 * Lc / 52.37, 1.0 / 2.6);
 }
 
+
+static double avpriv_trc_arib_std_b67(double Lc) {
+    // The function uses the definition from HEVC, which assumes that the peak
+    // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and
+    // using the definition from the ARIB STD-B67 spec)
+    const double a = 0.17883277;
+    const double b = 0.28466892;
+    const double c = 0.55991073;
+    return (0.0 > Lc) ? 0.0 :
+        (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c);
+}
+
 avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc)
 {
     avpriv_trc_function func = NULL;
@@ -208,6 +221,10 @@ avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharact
             func = avpriv_trc_smpte_st428_1;
             break;
 
+        case AVCOL_TRC_ARIB_STD_B67:
+            func = avpriv_trc_arib_std_b67;
+            break;
+
         case AVCOL_TRC_RESERVED0:
         case AVCOL_TRC_UNSPECIFIED:
         case AVCOL_TRC_RESERVED:
diff --git a/libavutil/colorspace.h b/libavutil/colorspace.h
index 7d3f711..b6dba2c 100644
--- a/libavutil/colorspace.h
+++ b/libavutil/colorspace.h
@@ -41,16 +41,17 @@
     b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\
 }
 
-#define YUV_TO_RGB1_CCIR_BT709(cb1, cr1)\
-{\
-    cb = (cb1) - 128;\
-    cr = (cr1) - 128;\
-    r_add = FIX(1.5747*255.0/224.0) * cr + ONE_HALF;\
-    g_add = - FIX(0.1873*255.0/224.0) * cb - FIX(0.4682*255.0/224.0) * cr + \
-            ONE_HALF;\
-    b_add = FIX(1.8556*255.0/224.0) * cb + ONE_HALF;\
-}
-
+#define YUV_TO_RGB1_CCIR_BT709(cb1, cr1)                      \
+    {                                                         \
+        cb    = (cb1) - 128;                                  \
+        cr    = (cr1) - 128;                                  \
+        r_add = ONE_HALF + FIX(1.5747 * 255.0 / 224.0) * cr;  \
+        g_add = ONE_HALF - FIX(0.1873 * 255.0 / 224.0) * cb - \
+                           FIX(0.4682 * 255.0 / 224.0) * cr;  \
+        b_add = ONE_HALF + FIX(1.8556 * 255.0 / 224.0) * cb;  \
+    }
+
+// To be used for the BT709 variant as well
 #define YUV_TO_RGB2_CCIR(r, g, b, y1)\
 {\
     y = ((y1) - 16) * FIX(255.0/219.0);\
diff --git a/libavutil/cpu.c b/libavutil/cpu.c
index cd55d3b..f5785fc 100644
--- a/libavutil/cpu.c
+++ b/libavutil/cpu.c
@@ -294,130 +294,3 @@ int av_cpu_count(void)
 
     return nb_cpus;
 }
-
-#ifdef TEST
-
-#include <stdio.h>
-#include "avstring.h"
-
-#if !HAVE_GETOPT
-#include "compat/getopt.c"
-#endif
-
-static const struct {
-    int flag;
-    const char *name;
-} cpu_flag_tab[] = {
-#if   ARCH_AARCH64
-    { AV_CPU_FLAG_ARMV8,     "armv8"      },
-    { AV_CPU_FLAG_NEON,      "neon"       },
-    { AV_CPU_FLAG_VFP,       "vfp"        },
-#elif ARCH_ARM
-    { AV_CPU_FLAG_ARMV5TE,   "armv5te"    },
-    { AV_CPU_FLAG_ARMV6,     "armv6"      },
-    { AV_CPU_FLAG_ARMV6T2,   "armv6t2"    },
-    { AV_CPU_FLAG_VFP,       "vfp"        },
-    { AV_CPU_FLAG_VFP_VM,    "vfp_vm"     },
-    { AV_CPU_FLAG_VFPV3,     "vfpv3"      },
-    { AV_CPU_FLAG_NEON,      "neon"       },
-    { AV_CPU_FLAG_SETEND,    "setend"     },
-#elif ARCH_PPC
-    { AV_CPU_FLAG_ALTIVEC,   "altivec"    },
-#elif ARCH_X86
-    { AV_CPU_FLAG_MMX,       "mmx"        },
-    { AV_CPU_FLAG_MMXEXT,    "mmxext"     },
-    { AV_CPU_FLAG_SSE,       "sse"        },
-    { AV_CPU_FLAG_SSE2,      "sse2"       },
-    { AV_CPU_FLAG_SSE2SLOW,  "sse2slow"   },
-    { AV_CPU_FLAG_SSE3,      "sse3"       },
-    { AV_CPU_FLAG_SSE3SLOW,  "sse3slow"   },
-    { AV_CPU_FLAG_SSSE3,     "ssse3"      },
-    { AV_CPU_FLAG_ATOM,      "atom"       },
-    { AV_CPU_FLAG_SSE4,      "sse4.1"     },
-    { AV_CPU_FLAG_SSE42,     "sse4.2"     },
-    { AV_CPU_FLAG_AVX,       "avx"        },
-    { AV_CPU_FLAG_AVXSLOW,   "avxslow"    },
-    { AV_CPU_FLAG_XOP,       "xop"        },
-    { AV_CPU_FLAG_FMA3,      "fma3"       },
-    { AV_CPU_FLAG_FMA4,      "fma4"       },
-    { AV_CPU_FLAG_3DNOW,     "3dnow"      },
-    { AV_CPU_FLAG_3DNOWEXT,  "3dnowext"   },
-    { AV_CPU_FLAG_CMOV,      "cmov"       },
-    { AV_CPU_FLAG_AVX2,      "avx2"       },
-    { AV_CPU_FLAG_BMI1,      "bmi1"       },
-    { AV_CPU_FLAG_BMI2,      "bmi2"       },
-    { AV_CPU_FLAG_AESNI,     "aesni"      },
-#endif
-    { 0 }
-};
-
-static void print_cpu_flags(int cpu_flags, const char *type)
-{
-    int i;
-
-    printf("cpu_flags(%s) = 0x%08X\n", type, cpu_flags);
-    printf("cpu_flags_str(%s) =", type);
-    for (i = 0; cpu_flag_tab[i].flag; i++)
-        if (cpu_flags & cpu_flag_tab[i].flag)
-            printf(" %s", cpu_flag_tab[i].name);
-    printf("\n");
-}
-
-
-int main(int argc, char **argv)
-{
-    int cpu_flags_raw = av_get_cpu_flags();
-    int cpu_flags_eff;
-    int cpu_count = av_cpu_count();
-    char threads[5] = "auto";
-    int i;
-
-    for(i = 0; cpu_flag_tab[i].flag; i++) {
-        unsigned tmp = 0;
-        if (av_parse_cpu_caps(&tmp, cpu_flag_tab[i].name) < 0) {
-            fprintf(stderr, "Table missing %s\n", cpu_flag_tab[i].name);
-            return 4;
-        }
-    }
-
-    if (cpu_flags_raw < 0)
-        return 1;
-
-    for (;;) {
-        int c = getopt(argc, argv, "c:t:");
-        if (c == -1)
-            break;
-        switch (c) {
-        case 'c':
-        {
-            unsigned flags = av_get_cpu_flags();
-            if (av_parse_cpu_caps(&flags, optarg) < 0)
-                return 2;
-
-            av_force_cpu_flags(flags);
-            break;
-        }
-        case 't':
-        {
-            int len = av_strlcpy(threads, optarg, sizeof(threads));
-            if (len >= sizeof(threads)) {
-                fprintf(stderr, "Invalid thread count '%s'\n", optarg);
-                return 2;
-            }
-        }
-        }
-    }
-
-    cpu_flags_eff = av_get_cpu_flags();
-
-    if (cpu_flags_eff < 0)
-        return 3;
-
-    print_cpu_flags(cpu_flags_raw, "raw");
-    print_cpu_flags(cpu_flags_eff, "effective");
-    printf("threads = %s (cpu_count = %d)\n", threads, cpu_count);
-
-    return 0;
-}
-
-#endif
diff --git a/libavutil/cpu.h b/libavutil/cpu.h
index cc4e30c..4bff167 100644
--- a/libavutil/cpu.h
+++ b/libavutil/cpu.h
@@ -70,7 +70,7 @@
 /**
  * Return the flags which specify extensions supported by the CPU.
  * The returned value is affected by av_force_cpu_flags() if that was used
- * before. So av_get_cpu_flags() can easily be used in a application to
+ * before. So av_get_cpu_flags() can easily be used in an application to
  * detect the enabled cpu flags.
  */
 int av_get_cpu_flags(void);
diff --git a/libavutil/crc.c b/libavutil/crc.c
index 5a1ddf0..495732b 100644
--- a/libavutil/crc.c
+++ b/libavutil/crc.c
@@ -19,8 +19,9 @@
  */
 
 #include "config.h"
-#include "common.h"
+
 #include "bswap.h"
+#include "common.h"
 #include "crc.h"
 
 #if CONFIG_HARDCODED_TABLES
@@ -332,7 +333,7 @@ int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size)
     if (ctx_size >= sizeof(AVCRC) * 1024)
         for (i = 0; i < 256; i++)
             for (j = 0; j < 3; j++)
-                ctx[256 *(j + 1) + i] =
+                ctx[256 * (j + 1) + i] =
                     (ctx[256 * j + i] >> 8) ^ ctx[ctx[256 * j + i] & 0xFF];
 #endif
 
@@ -377,29 +378,3 @@ uint32_t av_crc(const AVCRC *ctx, uint32_t crc,
 
     return crc;
 }
-
-#ifdef TEST
-int main(void)
-{
-    uint8_t buf[1999];
-    int i;
-    unsigned
-        p[6][3] = { { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 },
-                    { AV_CRC_32_IEEE   , 0x04C11DB7, 0xC0F5BAE0 },
-                    { AV_CRC_24_IEEE   , 0x864CFB  , 0xB704CE   },
-                    { AV_CRC_16_ANSI_LE, 0xA001    , 0xBFD8     },
-                    { AV_CRC_16_ANSI   , 0x8005    , 0x1FBB     },
-                    { AV_CRC_8_ATM     , 0x07      , 0xE3       }
-    };
-    const AVCRC *ctx;
-
-    for (i = 0; i < sizeof(buf); i++)
-        buf[i] = i + i * i;
-
-    for (i = 0; i < 6; i++) {
-        ctx = av_crc_get_table(p[i][0]);
-        printf("crc %08X = %X\n", p[i][1], av_crc(ctx, 0, buf, sizeof(buf)));
-    }
-    return 0;
-}
-#endif
diff --git a/libavutil/des.c b/libavutil/des.c
index 3ccbf89..6957666 100644
--- a/libavutil/des.c
+++ b/libavutil/des.c
@@ -18,14 +18,16 @@
  * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
-#include <inttypes.h>
+
+#include <stdint.h>
+
 #include "avutil.h"
 #include "common.h"
 #include "intreadwrite.h"
 #include "mem.h"
 #include "des.h"
 
-#define T(a, b, c, d, e, f, g, h) 64-a,64-b,64-c,64-d,64-e,64-f,64-g,64-h
+#define T(a, b, c, d, e, f, g, h) 64 - a, 64 - b, 64 - c, 64 - d, 64 - e, 64 - f, 64 - g, 64 - h
 static const uint8_t IP_shuffle[] = {
     T(58, 50, 42, 34, 26, 18, 10, 2),
     T(60, 52, 44, 36, 28, 20, 12, 4),
@@ -39,7 +41,7 @@ static const uint8_t IP_shuffle[] = {
 #undef T
 
 #if CONFIG_SMALL || defined(GENTABLES)
-#define T(a, b, c, d) 32-a,32-b,32-c,32-d
+#define T(a, b, c, d) 32 - a, 32 - b, 32 - c, 32 - d
 static const uint8_t P_shuffle[] = {
     T(16,  7, 20, 21),
     T(29, 12, 28, 17),
@@ -53,7 +55,7 @@ static const uint8_t P_shuffle[] = {
 #undef T
 #endif
 
-#define T(a, b, c, d, e, f, g) 64-a,64-b,64-c,64-d,64-e,64-f,64-g
+#define T(a, b, c, d, e, f, g) 64 - a, 64 - b, 64 - c, 64 - d, 64 - e, 64 - f, 64 - g
 static const uint8_t PC1_shuffle[] = {
     T(57, 49, 41, 33, 25, 17,  9),
     T( 1, 58, 50, 42, 34, 26, 18),
@@ -66,7 +68,7 @@ static const uint8_t PC1_shuffle[] = {
 };
 #undef T
 
-#define T(a, b, c, d, e, f) 56-a,56-b,56-c,56-d,56-e,56-f
+#define T(a, b, c, d, e, f) 56 - a, 56 - b, 56 - c, 56 - d, 56 - e, 56 - f
 static const uint8_t PC2_shuffle[] = {
     T(14, 17, 11, 24,  1,  5),
     T( 3, 28, 15,  6, 21, 10),
@@ -81,122 +83,99 @@ static const uint8_t PC2_shuffle[] = {
 
 #if CONFIG_SMALL
 static const uint8_t S_boxes[8][32] = {
-    {
-    0x0e, 0xf4, 0x7d, 0x41, 0xe2, 0x2f, 0xdb, 0x18, 0xa3, 0x6a, 0xc6, 0xbc, 0x95, 0x59, 0x30, 0x87,
-    0xf4, 0xc1, 0x8e, 0x28, 0x4d, 0x96, 0x12, 0x7b, 0x5f, 0xbc, 0x39, 0xe7, 0xa3, 0x0a, 0x65, 0xd0,
-    }, {
-    0x3f, 0xd1, 0x48, 0x7e, 0xf6, 0x2b, 0x83, 0xe4, 0xc9, 0x07, 0x12, 0xad, 0x6c, 0x90, 0xb5, 0x5a,
-    0xd0, 0x8e, 0xa7, 0x1b, 0x3a, 0xf4, 0x4d, 0x21, 0xb5, 0x68, 0x7c, 0xc6, 0x09, 0x53, 0xe2, 0x9f,
-    }, {
-    0xda, 0x70, 0x09, 0x9e, 0x36, 0x43, 0x6f, 0xa5, 0x21, 0x8d, 0x5c, 0xe7, 0xcb, 0xb4, 0xf2, 0x18,
-    0x1d, 0xa6, 0xd4, 0x09, 0x68, 0x9f, 0x83, 0x70, 0x4b, 0xf1, 0xe2, 0x3c, 0xb5, 0x5a, 0x2e, 0xc7,
-    }, {
-    0xd7, 0x8d, 0xbe, 0x53, 0x60, 0xf6, 0x09, 0x3a, 0x41, 0x72, 0x28, 0xc5, 0x1b, 0xac, 0xe4, 0x9f,
-    0x3a, 0xf6, 0x09, 0x60, 0xac, 0x1b, 0xd7, 0x8d, 0x9f, 0x41, 0x53, 0xbe, 0xc5, 0x72, 0x28, 0xe4,
-    }, {
-    0xe2, 0xbc, 0x24, 0xc1, 0x47, 0x7a, 0xdb, 0x16, 0x58, 0x05, 0xf3, 0xaf, 0x3d, 0x90, 0x8e, 0x69,
-    0xb4, 0x82, 0xc1, 0x7b, 0x1a, 0xed, 0x27, 0xd8, 0x6f, 0xf9, 0x0c, 0x95, 0xa6, 0x43, 0x50, 0x3e,
-    }, {
-    0xac, 0xf1, 0x4a, 0x2f, 0x79, 0xc2, 0x96, 0x58, 0x60, 0x1d, 0xd3, 0xe4, 0x0e, 0xb7, 0x35, 0x8b,
-    0x49, 0x3e, 0x2f, 0xc5, 0x92, 0x58, 0xfc, 0xa3, 0xb7, 0xe0, 0x14, 0x7a, 0x61, 0x0d, 0x8b, 0xd6,
-    }, {
-    0xd4, 0x0b, 0xb2, 0x7e, 0x4f, 0x90, 0x18, 0xad, 0xe3, 0x3c, 0x59, 0xc7, 0x25, 0xfa, 0x86, 0x61,
-    0x61, 0xb4, 0xdb, 0x8d, 0x1c, 0x43, 0xa7, 0x7e, 0x9a, 0x5f, 0x06, 0xf8, 0xe0, 0x25, 0x39, 0xc2,
-    }, {
-    0x1d, 0xf2, 0xd8, 0x84, 0xa6, 0x3f, 0x7b, 0x41, 0xca, 0x59, 0x63, 0xbe, 0x05, 0xe0, 0x9c, 0x27,
-    0x27, 0x1b, 0xe4, 0x71, 0x49, 0xac, 0x8e, 0xd2, 0xf0, 0xc6, 0x9a, 0x0d, 0x3f, 0x53, 0x65, 0xb8,
+    { 0x0e, 0xf4, 0x7d, 0x41, 0xe2, 0x2f, 0xdb, 0x18, 0xa3, 0x6a, 0xc6, 0xbc, 0x95, 0x59, 0x30, 0x87,
+      0xf4, 0xc1, 0x8e, 0x28, 0x4d, 0x96, 0x12, 0x7b, 0x5f, 0xbc, 0x39, 0xe7, 0xa3, 0x0a, 0x65, 0xd0, },
+    { 0x3f, 0xd1, 0x48, 0x7e, 0xf6, 0x2b, 0x83, 0xe4, 0xc9, 0x07, 0x12, 0xad, 0x6c, 0x90, 0xb5, 0x5a,
+      0xd0, 0x8e, 0xa7, 0x1b, 0x3a, 0xf4, 0x4d, 0x21, 0xb5, 0x68, 0x7c, 0xc6, 0x09, 0x53, 0xe2, 0x9f, },
+    { 0xda, 0x70, 0x09, 0x9e, 0x36, 0x43, 0x6f, 0xa5, 0x21, 0x8d, 0x5c, 0xe7, 0xcb, 0xb4, 0xf2, 0x18,
+      0x1d, 0xa6, 0xd4, 0x09, 0x68, 0x9f, 0x83, 0x70, 0x4b, 0xf1, 0xe2, 0x3c, 0xb5, 0x5a, 0x2e, 0xc7, },
+    { 0xd7, 0x8d, 0xbe, 0x53, 0x60, 0xf6, 0x09, 0x3a, 0x41, 0x72, 0x28, 0xc5, 0x1b, 0xac, 0xe4, 0x9f,
+      0x3a, 0xf6, 0x09, 0x60, 0xac, 0x1b, 0xd7, 0x8d, 0x9f, 0x41, 0x53, 0xbe, 0xc5, 0x72, 0x28, 0xe4, },
+    { 0xe2, 0xbc, 0x24, 0xc1, 0x47, 0x7a, 0xdb, 0x16, 0x58, 0x05, 0xf3, 0xaf, 0x3d, 0x90, 0x8e, 0x69,
+      0xb4, 0x82, 0xc1, 0x7b, 0x1a, 0xed, 0x27, 0xd8, 0x6f, 0xf9, 0x0c, 0x95, 0xa6, 0x43, 0x50, 0x3e, },
+    { 0xac, 0xf1, 0x4a, 0x2f, 0x79, 0xc2, 0x96, 0x58, 0x60, 0x1d, 0xd3, 0xe4, 0x0e, 0xb7, 0x35, 0x8b,
+      0x49, 0x3e, 0x2f, 0xc5, 0x92, 0x58, 0xfc, 0xa3, 0xb7, 0xe0, 0x14, 0x7a, 0x61, 0x0d, 0x8b, 0xd6, },
+    { 0xd4, 0x0b, 0xb2, 0x7e, 0x4f, 0x90, 0x18, 0xad, 0xe3, 0x3c, 0x59, 0xc7, 0x25, 0xfa, 0x86, 0x61,
+      0x61, 0xb4, 0xdb, 0x8d, 0x1c, 0x43, 0xa7, 0x7e, 0x9a, 0x5f, 0x06, 0xf8, 0xe0, 0x25, 0x39, 0xc2, },
+    { 0x1d, 0xf2, 0xd8, 0x84, 0xa6, 0x3f, 0x7b, 0x41, 0xca, 0x59, 0x63, 0xbe, 0x05, 0xe0, 0x9c, 0x27,
+      0x27, 0x1b, 0xe4, 0x71, 0x49, 0xac, 0x8e, 0xd2, 0xf0, 0xc6, 0x9a, 0x0d, 0x3f, 0x53, 0x65, 0xb8,
     }
 };
 #else
 /**
  * This table contains the results of applying both the S-box and P-shuffle.
- * It can be regenerated by compiling this file with -DCONFIG_SMALL -DTEST -DGENTABLES
+ * It can be regenerated by compiling tests/des.c with "-DCONFIG_SMALL -DGENTABLES".
  */
 static const uint32_t S_boxes_P_shuffle[8][64] = {
-    {
-    0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000,
-    0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002,
-    0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
-    0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000,
-    0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200,
-    0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
-    0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200,
-    0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002,
-    },
-    {
-    0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010,
-    0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010,
-    0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
-    0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010,
-    0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000,
-    0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
-    0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010,
-    0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000,
-    },
-    {
-    0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100,
-    0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104,
-    0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
-    0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000,
-    0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000,
-    0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
-    0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004,
-    0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100,
-    },
-    {
-    0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000,
-    0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000,
-    0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
-    0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040,
-    0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000,
-    0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
-    0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040,
-    0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040,
-    },
-    {
-    0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000,
-    0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000,
-    0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
-    0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080,
-    0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080,
-    0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
-    0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000,
-    0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080,
-    },
-    {
-    0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000,
-    0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008,
-    0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
-    0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000,
-    0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008,
-    0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
-    0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008,
-    0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008,
-    },
-    {
-    0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400,
-    0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401,
-    0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
-    0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400,
-    0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001,
-    0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
-    0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401,
-    0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001,
-    },
-    {
-    0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000,
-    0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020,
-    0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
-    0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000,
-    0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820,
-    0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
-    0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000,
-    0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800,
-    },
+    { 0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000,
+      0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002,
+      0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
+      0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000,
+      0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200,
+      0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
+      0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200,
+      0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002, },
+    { 0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010,
+      0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010,
+      0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
+      0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010,
+      0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000,
+      0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
+      0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010,
+      0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000, },
+    { 0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100,
+      0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104,
+      0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
+      0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000,
+      0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000,
+      0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
+      0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004,
+      0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100, },
+    { 0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000,
+      0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000,
+      0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
+      0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040,
+      0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000,
+      0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
+      0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040,
+      0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040, },
+    { 0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000,
+      0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000,
+      0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
+      0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080,
+      0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080,
+      0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
+      0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000,
+      0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080, },
+    { 0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000,
+      0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008,
+      0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
+      0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000,
+      0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008,
+      0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
+      0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008,
+      0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008, },
+    { 0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400,
+      0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401,
+      0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
+      0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400,
+      0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001,
+      0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
+      0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401,
+      0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001, },
+    { 0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000,
+      0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020,
+      0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
+      0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000,
+      0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820,
+      0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
+      0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000,
+      0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800, },
 };
 #endif
 
-static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len) {
+static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len)
+{
     int i;
     uint64_t res = 0;
     for (i = 0; i < shuffle_len; i++)
@@ -204,7 +183,8 @@ static uint64_t shuffle(uint64_t in, const uint8_t *shuffle, int shuffle_len) {
     return res;
 }
 
-static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len) {
+static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len)
+{
     int i;
     uint64_t res = 0;
     shuffle += shuffle_len - 1;
@@ -215,7 +195,8 @@ static uint64_t shuffle_inv(uint64_t in, const uint8_t *shuffle, int shuffle_len
     return res;
 }
 
-static uint32_t f_func(uint32_t r, uint64_t k) {
+static uint32_t f_func(uint32_t r, uint64_t k)
+{
     int i;
     uint32_t out = 0;
     // rotate to get first part of E-shuffle in the lowest 6 bits
@@ -225,13 +206,14 @@ static uint32_t f_func(uint32_t r, uint64_t k) {
         uint8_t tmp = (r ^ k) & 0x3f;
 #if CONFIG_SMALL
         uint8_t v = S_boxes[i][tmp >> 1];
-        if (tmp & 1) v >>= 4;
+        if (tmp & 1)
+            v >>= 4;
         out = (out >> 4) | (v << 28);
 #else
         out |= S_boxes_P_shuffle[i][tmp];
 #endif
         // get next 6 bits of E-shuffle and round key k into the lowest bits
-        r = (r >> 4) | (r << 28);
+        r   = (r >> 4) | (r << 28);
         k >>= 6;
     }
 #if CONFIG_SMALL
@@ -246,15 +228,17 @@ static uint32_t f_func(uint32_t r, uint64_t k) {
  * Note: the specification calls this "shift", so I kept it although
  * it is confusing.
  */
-static uint64_t key_shift_left(uint64_t CDn) {
+static uint64_t key_shift_left(uint64_t CDn)
+{
     uint64_t carries = (CDn >> 27) & 0x10000001;
     CDn <<= 1;
-    CDn &= ~0x10000001;
-    CDn |= carries;
+    CDn  &= ~0x10000001;
+    CDn  |= carries;
     return CDn;
 }
 
-static void gen_roundkeys(uint64_t K[16], uint64_t key) {
+static void gen_roundkeys(uint64_t K[16], uint64_t key)
+{
     int i;
     // discard parity bits from key and shuffle it into C and D parts
     uint64_t CDn = shuffle(key, PC1_shuffle, sizeof(PC1_shuffle));
@@ -267,7 +251,8 @@ static void gen_roundkeys(uint64_t K[16], uint64_t key) {
     }
 }
 
-static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt) {
+static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt)
+{
     int i;
     // used to apply round keys in reverse order for decryption
     decrypt = decrypt ? 15 : 0;
@@ -276,8 +261,8 @@ static uint64_t des_encdec(uint64_t in, uint64_t K[16], int decrypt) {
     for (i = 0; i < 16; i++) {
         uint32_t f_res;
         f_res = f_func(in, K[decrypt ^ i]);
-        in = (in << 32) | (in >> 32);
-        in ^= f_res;
+        in    = (in << 32) | (in >> 32);
+        in   ^= f_res;
     }
     in = (in << 32) | (in >> 32);
     // reverse shuffle used to ease hardware implementations
@@ -302,7 +287,9 @@ int av_des_init(AVDES *d, const uint8_t *key, int key_bits, av_unused int decryp
     return 0;
 }
 
-static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt, int mac) {
+static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src,
+                             int count, uint8_t *iv, int decrypt, int mac)
+{
     uint64_t iv_val = iv ? AV_RB64(iv) : 0;
     while (count-- > 0) {
         uint64_t dst_val;
@@ -314,7 +301,7 @@ static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int cou
                 src_val = des_encdec(src_val, d->round_keys[1], 0);
             }
             dst_val = des_encdec(src_val, d->round_keys[0], 1) ^ iv_val;
-            iv_val = iv ? tmp : 0;
+            iv_val  = iv ? tmp : 0;
         } else {
             dst_val = des_encdec(src_val ^ iv_val, d->round_keys[0], 0);
             if (d->triple_des) {
@@ -332,116 +319,13 @@ static void av_des_crypt_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int cou
         AV_WB64(iv, iv_val);
 }
 
-void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt) {
+void av_des_crypt(AVDES *d, uint8_t *dst, const uint8_t *src,
+                  int count, uint8_t *iv, int decrypt)
+{
     av_des_crypt_mac(d, dst, src, count, iv, decrypt, 0);
 }
 
-void av_des_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count) {
-    av_des_crypt_mac(d, dst, src, count, (uint8_t[8]){0}, 0, 1);
-}
-
-#ifdef TEST
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "time.h"
-
-static uint64_t rand64(void) {
-    uint64_t r = rand();
-    r = (r << 32) | rand();
-    return r;
-}
-
-static const uint8_t test_key[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
-static const DECLARE_ALIGNED(8, uint8_t, plain)[] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
-static const DECLARE_ALIGNED(8, uint8_t, crypt)[] = {0x4a, 0xb6, 0x5b, 0x3d, 0x4b, 0x06, 0x15, 0x18};
-static DECLARE_ALIGNED(8, uint8_t, tmp)[8];
-static DECLARE_ALIGNED(8, uint8_t, large_buffer)[10002][8];
-static const uint8_t cbc_key[] = {
-    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
-    0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
-    0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
-};
-
-static int run_test(int cbc, int decrypt) {
-    AVDES d;
-    int delay = cbc && !decrypt ? 2 : 1;
-    uint64_t res;
-    AV_WB64(large_buffer[0], 0x4e6f772069732074ULL);
-    AV_WB64(large_buffer[1], 0x1234567890abcdefULL);
-    AV_WB64(tmp,             0x1234567890abcdefULL);
-    av_des_init(&d, cbc_key, 192, decrypt);
-    av_des_crypt(&d, large_buffer[delay], large_buffer[0], 10000, cbc ? tmp : NULL, decrypt);
-    res = AV_RB64(large_buffer[9999 + delay]);
-    if (cbc) {
-        if (decrypt)
-            return res == 0xc5cecf63ecec514cULL;
-        else
-            return res == 0xcb191f85d1ed8439ULL;
-    } else {
-        if (decrypt)
-            return res == 0x8325397644091a0aULL;
-        else
-            return res == 0xdd17e8b8b437d232ULL;
-    }
-}
-
-int main(void) {
-    AVDES d;
-    int i;
-#ifdef GENTABLES
-    int j;
-#endif
-    uint64_t key[3];
-    uint64_t data;
-    uint64_t ct;
-    uint64_t roundkeys[16];
-    srand(av_gettime());
-    key[0] = AV_RB64(test_key);
-    data = AV_RB64(plain);
-    gen_roundkeys(roundkeys, key[0]);
-    if (des_encdec(data, roundkeys, 0) != AV_RB64(crypt)) {
-        printf("Test 1 failed\n");
-        return 1;
-    }
-    av_des_init(&d, test_key, 64, 0);
-    av_des_crypt(&d, tmp, plain, 1, NULL, 0);
-    if (memcmp(tmp, crypt, sizeof(crypt))) {
-        printf("Public API decryption failed\n");
-        return 1;
-    }
-    if (!run_test(0, 0) || !run_test(0, 1) || !run_test(1, 0) || !run_test(1, 1)) {
-        printf("Partial Monte-Carlo test failed\n");
-        return 1;
-    }
-    for (i = 0; i < 1000; i++) {
-        key[0] = rand64(); key[1] = rand64(); key[2] = rand64();
-        data = rand64();
-        av_des_init(&d, (uint8_t*)key, 192, 0);
-        av_des_crypt(&d, (uint8_t*)&ct, (uint8_t*)&data, 1, NULL, 0);
-        av_des_init(&d, (uint8_t*)key, 192, 1);
-        av_des_crypt(&d, (uint8_t*)&ct, (uint8_t*)&ct, 1, NULL, 1);
-        if (ct != data) {
-            printf("Test 2 failed\n");
-            return 1;
-        }
-    }
-#ifdef GENTABLES
-    printf("static const uint32_t S_boxes_P_shuffle[8][64] = {\n");
-    for (i = 0; i < 8; i++) {
-        printf("    {");
-        for (j = 0; j < 64; j++) {
-            uint32_t v = S_boxes[i][j >> 1];
-            v = j & 1 ? v >> 4 : v & 0xf;
-            v <<= 28 - 4 * i;
-            v = shuffle(v, P_shuffle, sizeof(P_shuffle));
-            printf((j & 7) == 0 ? "\n    " : " ");
-            printf("0x%08X,", v);
-        }
-        printf("\n    },\n");
-    }
-    printf("};\n");
-#endif
-    return 0;
+void av_des_mac(AVDES *d, uint8_t *dst, const uint8_t *src, int count)
+{
+    av_des_crypt_mac(d, dst, src, count, (uint8_t[8]) { 0 }, 0, 1);
 }
-#endif
diff --git a/libavutil/dict.c b/libavutil/dict.c
index 8bb65a1..f70c7e0 100644
--- a/libavutil/dict.c
+++ b/libavutil/dict.c
@@ -70,9 +70,12 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value,
                 int flags)
 {
     AVDictionary *m = *pm;
-    AVDictionaryEntry *tag = av_dict_get(m, key, NULL, flags);
+    AVDictionaryEntry *tag = NULL;
     char *oldval = NULL, *copy_key = NULL, *copy_value = NULL;
 
+    if (!(flags & AV_DICT_MULTIKEY)) {
+        tag = av_dict_get(m, key, NULL, flags);
+    }
     if (flags & AV_DICT_DONT_STRDUP_KEY)
         copy_key = (void *)key;
     else
@@ -98,7 +101,7 @@ int av_dict_set(AVDictionary **pm, const char *key, const char *value,
             av_free(tag->value);
         av_free(tag->key);
         *tag = m->elems[--m->count];
-    } else {
+    } else if (copy_value) {
         AVDictionaryEntry *tmp = av_realloc(m->elems,
                                             (m->count + 1) * sizeof(*m->elems));
         if (!tmp)
@@ -250,117 +253,3 @@ int av_dict_get_string(const AVDictionary *m, char **buffer,
     }
     return av_bprint_finalize(&bprint, buffer);
 }
-
-#ifdef TEST
-static void print_dict(const AVDictionary *m)
-{
-    AVDictionaryEntry *t = NULL;
-    while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX)))
-        printf("%s %s   ", t->key, t->value);
-    printf("\n");
-}
-
-static void test_separators(const AVDictionary *m, const char pair, const char val)
-{
-    AVDictionary *dict = NULL;
-    char pairs[] = {pair , '\0'};
-    char vals[]  = {val, '\0'};
-
-    char *buffer = NULL;
-    av_dict_copy(&dict, m, 0);
-    print_dict(dict);
-    av_dict_get_string(dict, &buffer, val, pair);
-    printf("%s\n", buffer);
-    av_dict_free(&dict);
-    av_dict_parse_string(&dict, buffer, vals, pairs, 0);
-    av_freep(&buffer);
-    print_dict(dict);
-    av_dict_free(&dict);
-}
-
-int main(void)
-{
-    AVDictionary *dict = NULL;
-    AVDictionaryEntry *e;
-    char *buffer = NULL;
-
-    printf("Testing av_dict_get_string() and av_dict_parse_string()\n");
-    av_dict_get_string(dict, &buffer, '=', ',');
-    printf("%s\n", buffer);
-    av_freep(&buffer);
-    av_dict_set(&dict, "aaa", "aaa", 0);
-    av_dict_set(&dict, "b,b", "bbb", 0);
-    av_dict_set(&dict, "c=c", "ccc", 0);
-    av_dict_set(&dict, "ddd", "d,d", 0);
-    av_dict_set(&dict, "eee", "e=e", 0);
-    av_dict_set(&dict, "f,f", "f=f", 0);
-    av_dict_set(&dict, "g=g", "g,g", 0);
-    test_separators(dict, ',', '=');
-    av_dict_free(&dict);
-    av_dict_set(&dict, "aaa", "aaa", 0);
-    av_dict_set(&dict, "bbb", "bbb", 0);
-    av_dict_set(&dict, "ccc", "ccc", 0);
-    av_dict_set(&dict, "\\,=\'\"", "\\,=\'\"", 0);
-    test_separators(dict, '"',  '=');
-    test_separators(dict, '\'', '=');
-    test_separators(dict, ',', '"');
-    test_separators(dict, ',', '\'');
-    test_separators(dict, '\'', '"');
-    test_separators(dict, '"', '\'');
-    av_dict_free(&dict);
-
-    printf("\nTesting av_dict_set()\n");
-    av_dict_set(&dict, "a", "a", 0);
-    av_dict_set(&dict, "b", av_strdup("b"), AV_DICT_DONT_STRDUP_VAL);
-    av_dict_set(&dict, av_strdup("c"), "c", AV_DICT_DONT_STRDUP_KEY);
-    av_dict_set(&dict, av_strdup("d"), av_strdup("d"), AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
-    av_dict_set(&dict, "e", "e", AV_DICT_DONT_OVERWRITE);
-    av_dict_set(&dict, "e", "f", AV_DICT_DONT_OVERWRITE);
-    av_dict_set(&dict, "f", "f", 0);
-    av_dict_set(&dict, "f", NULL, 0);
-    av_dict_set(&dict, "ff", "f", 0);
-    av_dict_set(&dict, "ff", "f", AV_DICT_APPEND);
-    e = NULL;
-    while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
-        printf("%s %s\n", e->key, e->value);
-    av_dict_free(&dict);
-
-    av_dict_set(&dict, NULL, "a", 0);
-    av_dict_set(&dict, NULL, "b", 0);
-    av_dict_get(dict, NULL, NULL, 0);
-    e = NULL;
-    while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
-        printf("'%s' '%s'\n", e->key, e->value);
-    av_dict_free(&dict);
-
-
-    //valgrind sensible test
-    printf("\nTesting av_dict_set_int()\n");
-    av_dict_set_int(&dict, "1", 1, AV_DICT_DONT_STRDUP_VAL);
-    av_dict_set_int(&dict, av_strdup("2"), 2, AV_DICT_DONT_STRDUP_KEY);
-    av_dict_set_int(&dict, av_strdup("3"), 3, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
-    av_dict_set_int(&dict, "4", 4, 0);
-    av_dict_set_int(&dict, "5", 5, AV_DICT_DONT_OVERWRITE);
-    av_dict_set_int(&dict, "5", 6, AV_DICT_DONT_OVERWRITE);
-    av_dict_set_int(&dict, "12", 1, 0);
-    av_dict_set_int(&dict, "12", 2, AV_DICT_APPEND);
-    e = NULL;
-    while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
-        printf("%s %s\n", e->key, e->value);
-    av_dict_free(&dict);
-
-    //valgrind sensible test
-    printf("\nTesting av_dict_set() with existing AVDictionaryEntry.key as key\n");
-    av_dict_set(&dict, "key", "old", 0);
-    e = av_dict_get(dict, "key", NULL, 0);
-    av_dict_set(&dict, e->key, "new val OK", 0);
-    e = av_dict_get(dict, "key", NULL, 0);
-    printf("%s\n", e->value);
-    av_dict_set(&dict, e->key, e->value, 0);
-    e = av_dict_get(dict, "key", NULL, 0);
-    printf("%s\n", e->value);
-    av_dict_free(&dict);
-
-    return 0;
-}
-#endif
diff --git a/libavutil/dict.h b/libavutil/dict.h
index 5b8d003..118f1f0 100644
--- a/libavutil/dict.h
+++ b/libavutil/dict.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -65,7 +64,6 @@
    }
    av_dict_free(&d);
  @endcode
- *
  */
 
 #define AV_DICT_MATCH_CASE      1   /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */
@@ -78,6 +76,7 @@
 #define AV_DICT_DONT_OVERWRITE 16   ///< Don't overwrite existing entries.
 #define AV_DICT_APPEND         32   /**< If the entry already exists, append to it.  Note that no
                                       delimiter is added, the strings are simply concatenated. */
+#define AV_DICT_MULTIKEY       64   /**< Allow to store several equal keys in the dictionary */
 
 typedef struct AVDictionaryEntry {
     char *key;
@@ -118,10 +117,13 @@ int av_dict_count(const AVDictionary *m);
  * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set,
  * these arguments will be freed on error.
  *
+ * Warning: Adding a new entry to a dictionary invalidates all existing entries
+ * previously returned with av_dict_get.
+ *
  * @param pm pointer to a pointer to a dictionary struct. If *pm is NULL
  * a dictionary struct is allocated and put in *pm.
- * @param key entry key to add to *pm (will be av_strduped depending on flags)
- * @param value entry value to add to *pm (will be av_strduped depending on flags).
+ * @param key entry key to add to *pm (will either be av_strduped or added as a new key depending on flags)
+ * @param value entry value to add to *pm (will be av_strduped or added as a new key depending on flags).
  *        Passing a NULL value will cause an existing entry to be deleted.
  * @return >= 0 on success otherwise an error code <0
  */
diff --git a/libavutil/display.h b/libavutil/display.h
index c0cfee3..39c15ee 100644
--- a/libavutil/display.h
+++ b/libavutil/display.h
@@ -22,6 +22,7 @@
 #define AVUTIL_DISPLAY_H
 
 #include <stdint.h>
+#include "common.h"
 
 /**
  * The display transformation matrix specifies an affine transformation that
diff --git a/libavutil/error.c b/libavutil/error.c
index 8df73db..b963048 100644
--- a/libavutil/error.c
+++ b/libavutil/error.c
@@ -127,25 +127,3 @@ int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
 
     return ret;
 }
-
-#ifdef TEST
-
-#undef printf
-
-int main(void)
-{
-    int i;
-
-    for (i = 0; i < FF_ARRAY_ELEMS(error_entries); i++) {
-        const struct error_entry *entry = &error_entries[i];
-        printf("%d: %s [%s]\n", entry->num, av_err2str(entry->num), entry->tag);
-    }
-
-    for (i = 0; i < 256; i++) {
-        printf("%d: %s\n", -i, av_err2str(-i));
-    }
-
-    return 0;
-}
-
-#endif /* TEST */
diff --git a/libavutil/eval.c b/libavutil/eval.c
index 2acbbb4..d291c5d 100644
--- a/libavutil/eval.c
+++ b/libavutil/eval.c
@@ -31,6 +31,7 @@
 #include "avutil.h"
 #include "common.h"
 #include "eval.h"
+#include "ffmath.h"
 #include "internal.h"
 #include "log.h"
 #include "mathematics.h"
@@ -736,156 +737,3 @@ int av_expr_parse_and_eval(double *d, const char *s,
     av_expr_free(e);
     return isnan(*d) ? AVERROR(EINVAL) : 0;
 }
-
-#ifdef TEST
-#include <string.h>
-
-static const double const_values[] = {
-    M_PI,
-    M_E,
-    0
-};
-
-static const char *const const_names[] = {
-    "PI",
-    "E",
-    0
-};
-
-int main(int argc, char **argv)
-{
-    int i;
-    double d;
-    const char *const *expr;
-    static const char *const exprs[] = {
-        "",
-        "1;2",
-        "-20",
-        "-PI",
-        "+PI",
-        "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
-        "80G/80Gi",
-        "1k",
-        "1Gi",
-        "1gi",
-        "1GiFoo",
-        "1k+1k",
-        "1Gi*3foo",
-        "foo",
-        "foo(",
-        "foo()",
-        "foo)",
-        "sin",
-        "sin(",
-        "sin()",
-        "sin)",
-        "sin 10",
-        "sin(1,2,3)",
-        "sin(1 )",
-        "1",
-        "1foo",
-        "bar + PI + E + 100f*2 + foo",
-        "13k + 12f - foo(1, 2)",
-        "1gi",
-        "1Gi",
-        "st(0, 123)",
-        "st(1, 123); ld(1)",
-        "lte(0, 1)",
-        "lte(1, 1)",
-        "lte(1, 0)",
-        "lt(0, 1)",
-        "lt(1, 1)",
-        "gt(1, 0)",
-        "gt(2, 7)",
-        "gte(122, 122)",
-        /* compute 1+2+...+N */
-        "st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)",
-        /* compute Fib(N) */
-        "st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)",
-        "while(0, 10)",
-        "st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))",
-        "isnan(1)",
-        "isnan(NAN)",
-        "isnan(INF)",
-        "isinf(1)",
-        "isinf(NAN)",
-        "isinf(INF)",
-        "floor(NAN)",
-        "floor(123.123)",
-        "floor(-123.123)",
-        "trunc(123.123)",
-        "trunc(-123.123)",
-        "ceil(123.123)",
-        "ceil(-123.123)",
-        "sqrt(1764)",
-        "isnan(sqrt(-1))",
-        "not(1)",
-        "not(NAN)",
-        "not(0)",
-        "6.0206dB",
-        "-3.0103dB",
-        "pow(0,1.23)",
-        "pow(PI,1.23)",
-        "PI^1.23",
-        "pow(-1,1.23)",
-        "if(1, 2)",
-        "if(1, 1, 2)",
-        "if(0, 1, 2)",
-        "ifnot(0, 23)",
-        "ifnot(1, NaN) + if(0, 1)",
-        "ifnot(1, 1, 2)",
-        "ifnot(0, 1, 2)",
-        "taylor(1, 1)",
-        "taylor(eq(mod(ld(1),4),1)-eq(mod(ld(1),4),3), PI/2, 1)",
-        "root(sin(ld(0))-1, 2)",
-        "root(sin(ld(0))+6+sin(ld(0)/12)-log(ld(0)), 100)",
-        "7000000B*random(0)",
-        "squish(2)",
-        "gauss(0.1)",
-        "hypot(4,3)",
-        "gcd(30,55)*print(min(9,1))",
-        "bitor(42, 12)",
-        "bitand(42, 12)",
-        "bitand(NAN, 1)",
-        "between(10, -3, 10)",
-        "between(-4, -2, -1)",
-        "between(1,2)",
-        "clip(0, 2, 1)",
-        "clip(0/0, 1, 2)",
-        "clip(0, 0/0, 1)",
-        NULL
-    };
-
-    for (expr = exprs; *expr; expr++) {
-        printf("Evaluating '%s'\n", *expr);
-        av_expr_parse_and_eval(&d, *expr,
-                               const_names, const_values,
-                               NULL, NULL, NULL, NULL, NULL, 0, NULL);
-        if (isnan(d))
-            printf("'%s' -> nan\n\n", *expr);
-        else
-            printf("'%s' -> %f\n\n", *expr, d);
-    }
-
-    av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
-                           const_names, const_values,
-                           NULL, NULL, NULL, NULL, NULL, 0, NULL);
-    printf("%f == 12.7\n", d);
-    av_expr_parse_and_eval(&d, "80G/80Gi",
-                           const_names, const_values,
-                           NULL, NULL, NULL, NULL, NULL, 0, NULL);
-    printf("%f == 0.931322575\n", d);
-
-    if (argc > 1 && !strcmp(argv[1], "-t")) {
-        for (i = 0; i < 1050; i++) {
-            START_TIMER;
-            av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
-                                   const_names, const_values,
-                                   NULL, NULL, NULL, NULL, NULL, 0, NULL);
-            STOP_TIMER("av_expr_parse_and_eval");
-        }
-    }
-
-    return 0;
-}
-#endif
diff --git a/libavutil/ffmath.h b/libavutil/ffmath.h
new file mode 100644
index 0000000..aad1347
--- /dev/null
+++ b/libavutil/ffmath.h
@@ -0,0 +1,67 @@
+/*
+ * copyright (c) 2016 Ganesh Ajjanagadde <gajjanag at gmail.com>
+ *
+ * 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
+ * internal math functions header
+ */
+
+#ifndef AVUTIL_FFMATH_H
+#define AVUTIL_FFMATH_H
+
+#include "attributes.h"
+#include "libm.h"
+
+/**
+ * Compute 10^x for floating point values. Note: this function is by no means
+ * "correctly rounded", and is meant as a fast, reasonably accurate approximation.
+ * For instance, maximum relative error for the double precision variant is
+ * ~ 1e-13 for very small and very large values.
+ * This is ~2x faster than GNU libm's approach, which is still off by 2ulp on
+ * some inputs.
+ * @param x exponent
+ * @return 10^x
+ */
+static av_always_inline double ff_exp10(double x)
+{
+    return exp2(M_LOG2_10 * x);
+}
+
+static av_always_inline float ff_exp10f(float x)
+{
+    return exp2f(M_LOG2_10 * x);
+}
+
+/**
+ * Compute x^y for floating point x, y. Note: this function is faster than the
+ * libm variant due to mainly 2 reasons:
+ * 1. It does not handle any edge cases. In particular, this is only guaranteed
+ * to work correctly for x > 0.
+ * 2. It is not as accurate as a standard nearly "correctly rounded" libm variant.
+ * @param x base
+ * @param y exponent
+ * @return x^y
+ */
+static av_always_inline float ff_fast_powf(float x, float y)
+{
+    return expf(logf(x) * y);
+}
+
+#endif /* AVUTIL_FFMATH_H */
diff --git a/libavutil/fifo.c b/libavutil/fifo.c
index 7bd48a2..1060aed 100644
--- a/libavutil/fifo.c
+++ b/libavutil/fifo.c
@@ -113,7 +113,7 @@ int av_fifo_grow(AVFifoBuffer *f, unsigned int size)
     size += av_fifo_size(f);
 
     if (old_size < size)
-        return av_fifo_realloc2(f, FFMAX(size, 2*size));
+        return av_fifo_realloc2(f, FFMAX(size, 2*old_size));
     return 0;
 }
 
@@ -238,60 +238,3 @@ void av_fifo_drain(AVFifoBuffer *f, int size)
         f->rptr -= f->end - f->buffer;
     f->rndx += size;
 }
-
-#ifdef TEST
-
-int main(void)
-{
-    /* create a FIFO buffer */
-    AVFifoBuffer *fifo = av_fifo_alloc(13 * sizeof(int));
-    int i, j, n;
-
-    /* fill data */
-    for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++)
-        av_fifo_generic_write(fifo, &i, sizeof(int), NULL);
-
-    /* peek at FIFO */
-    n = av_fifo_size(fifo) / sizeof(int);
-    for (i = -n + 1; i < n; i++) {
-        int *v = (int *)av_fifo_peek2(fifo, i * sizeof(int));
-        printf("%d: %d\n", i, *v);
-    }
-    printf("\n");
-
-    /* peek_at at FIFO */
-    n = av_fifo_size(fifo) / sizeof(int);
-    for (i = 0; i < n; i++) {
-        av_fifo_generic_peek_at(fifo, &j, i * sizeof(int), sizeof(j), NULL);
-        printf("%d: %d\n", i, j);
-    }
-    printf("\n");
-
-    /* read data */
-    for (i = 0; av_fifo_size(fifo) >= sizeof(int); i++) {
-        av_fifo_generic_read(fifo, &j, sizeof(int), NULL);
-        printf("%d ", j);
-    }
-    printf("\n");
-
-    /* test *ndx overflow */
-    av_fifo_reset(fifo);
-    fifo->rndx = fifo->wndx = ~(uint32_t)0 - 5;
-
-    /* fill data */
-    for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++)
-        av_fifo_generic_write(fifo, &i, sizeof(int), NULL);
-
-    /* peek_at at FIFO */
-    n = av_fifo_size(fifo) / sizeof(int);
-    for (i = 0; i < n; i++) {
-        av_fifo_generic_peek_at(fifo, &j, i * sizeof(int), sizeof(j), NULL);
-        printf("%d: %d\n", i, j);
-    }
-
-    av_fifo_free(fifo);
-
-    return 0;
-}
-
-#endif
diff --git a/libavutil/file.c b/libavutil/file.c
index 2a06be4..7bdf6cd 100644
--- a/libavutil/file.c
+++ b/libavutil/file.c
@@ -137,69 +137,6 @@ void av_file_unmap(uint8_t *bufptr, size_t size)
 #endif
 }
 
-int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx)
-{
-    FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };
-    int fd = -1;
-#if !HAVE_MKSTEMP
-    void *ptr= tempnam(NULL, prefix);
-    if(!ptr)
-        ptr= tempnam(".", prefix);
-    *filename = av_strdup(ptr);
-#undef free
-    free(ptr);
-#else
-    size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */
-    *filename  = av_malloc(len);
-#endif
-    /* -----common section-----*/
-    if (!*filename) {
-        av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n");
-        return AVERROR(ENOMEM);
-    }
-#if !HAVE_MKSTEMP
-#   ifndef O_BINARY
-#       define O_BINARY 0
-#   endif
-#   ifndef O_EXCL
-#       define O_EXCL 0
-#   endif
-    fd = open(*filename, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600);
-#else
-    snprintf(*filename, len, "/tmp/%sXXXXXX", prefix);
-    fd = mkstemp(*filename);
-#ifdef _WIN32
-    if (fd < 0) {
-        snprintf(*filename, len, "./%sXXXXXX", prefix);
-        fd = mkstemp(*filename);
-    }
-#endif
-#endif
-    /* -----common section-----*/
-    if (fd < 0) {
-        int err = AVERROR(errno);
-        av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename);
-        av_freep(filename);
-        return err;
-    }
-    return fd; /* success */
+int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx) {
+    return avpriv_tempfile(prefix, filename, log_offset, log_ctx);
 }
-
-#ifdef TEST
-
-#undef printf
-
-int main(void)
-{
-    uint8_t *buf;
-    size_t size;
-    if (av_file_map("file.c", &buf, &size, 0, NULL) < 0)
-        return 1;
-
-    buf[0] = 's';
-    printf("%s", buf);
-    av_file_unmap(buf, size);
-    return 0;
-}
-#endif
-
diff --git a/libavutil/file.h b/libavutil/file.h
index e931be7..8666c7b 100644
--- a/libavutil/file.h
+++ b/libavutil/file.h
@@ -62,6 +62,7 @@ void av_file_unmap(uint8_t *bufptr, size_t size);
  * @note On very old libcs it is necessary to set a secure umask before
  *       calling this, av_tempfile() can't call umask itself as it is used in
  *       libraries and could interfere with the calling application.
+ * @deprecated as fd numbers cannot be passed saftely between libs on some platforms
  */
 int av_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx);
 
diff --git a/libavutil/file_open.c b/libavutil/file_open.c
index 9e76127..34070d9 100644
--- a/libavutil/file_open.c
+++ b/libavutil/file_open.c
@@ -92,6 +92,65 @@ int avpriv_open(const char *filename, int flags, ...)
     return fd;
 }
 
+typedef struct FileLogContext {
+    const AVClass *class;
+    int   log_offset;
+    void *log_ctx;
+} FileLogContext;
+
+static const AVClass file_log_ctx_class = {
+    "TEMPFILE", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT,
+    offsetof(FileLogContext, log_offset), offsetof(FileLogContext, log_ctx)
+};
+
+int avpriv_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx)
+{
+    FileLogContext file_log_ctx = { &file_log_ctx_class, log_offset, log_ctx };
+    int fd = -1;
+#if !HAVE_MKSTEMP
+    void *ptr= tempnam(NULL, prefix);
+    if(!ptr)
+        ptr= tempnam(".", prefix);
+    *filename = av_strdup(ptr);
+#undef free
+    free(ptr);
+#else
+    size_t len = strlen(prefix) + 12; /* room for "/tmp/" and "XXXXXX\0" */
+    *filename  = av_malloc(len);
+#endif
+    /* -----common section-----*/
+    if (!*filename) {
+        av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot allocate file name\n");
+        return AVERROR(ENOMEM);
+    }
+#if !HAVE_MKSTEMP
+#   ifndef O_BINARY
+#       define O_BINARY 0
+#   endif
+#   ifndef O_EXCL
+#       define O_EXCL 0
+#   endif
+    fd = open(*filename, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600);
+#else
+    snprintf(*filename, len, "/tmp/%sXXXXXX", prefix);
+    fd = mkstemp(*filename);
+#if defined(_WIN32) || defined (__ANDROID__)
+    if (fd < 0) {
+        snprintf(*filename, len, "./%sXXXXXX", prefix);
+        fd = mkstemp(*filename);
+    }
+#endif
+#endif
+    /* -----common section-----*/
+    if (fd < 0) {
+        int err = AVERROR(errno);
+        av_log(&file_log_ctx, AV_LOG_ERROR, "ff_tempfile: Cannot open temporary file %s\n", *filename);
+        av_freep(filename);
+        return err;
+    }
+    return fd; /* success */
+}
+
 FILE *av_fopen_utf8(const char *path, const char *mode)
 {
     int fd;
diff --git a/libavutil/float_dsp.c b/libavutil/float_dsp.c
index 49e0ae7..c85daff 100644
--- a/libavutil/float_dsp.c
+++ b/libavutil/float_dsp.c
@@ -144,321 +144,3 @@ av_cold AVFloatDSPContext *avpriv_float_dsp_alloc(int bit_exact)
         ff_float_dsp_init_mips(fdsp);
     return fdsp;
 }
-
-
-#ifdef TEST
-
-#include <float.h>
-#include <math.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#if HAVE_UNISTD_H
-#include <unistd.h> /* for getopt */
-#endif
-#if !HAVE_GETOPT
-#include "compat/getopt.c"
-#endif
-
-#include "common.h"
-#include "cpu.h"
-#include "internal.h"
-#include "lfg.h"
-#include "log.h"
-#include "random_seed.h"
-
-#define LEN 240
-
-static void fill_float_array(AVLFG *lfg, float *a, int len)
-{
-    int i;
-    double bmg[2], stddev = 10.0, mean = 0.0;
-
-    for (i = 0; i < len; i += 2) {
-        av_bmg_get(lfg, bmg);
-        a[i]     = bmg[0] * stddev + mean;
-        a[i + 1] = bmg[1] * stddev + mean;
-    }
-}
-static int compare_floats(const float *a, const float *b, int len,
-                          float max_diff)
-{
-    int i;
-    for (i = 0; i < len; i++) {
-        if (fabsf(a[i] - b[i]) > max_diff) {
-            av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n",
-                   i, a[i], b[i], a[i] - b[i]);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static void fill_double_array(AVLFG *lfg, double *a, int len)
-{
-    int i;
-    double bmg[2], stddev = 10.0, mean = 0.0;
-
-    for (i = 0; i < len; i += 2) {
-        av_bmg_get(lfg, bmg);
-        a[i]     = bmg[0] * stddev + mean;
-        a[i + 1] = bmg[1] * stddev + mean;
-    }
-}
-
-static int compare_doubles(const double *a, const double *b, int len,
-                           double max_diff)
-{
-    int i;
-
-    for (i = 0; i < len; i++) {
-        if (fabs(a[i] - b[i]) > max_diff) {
-            av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n",
-                   i, a[i], b[i], a[i] - b[i]);
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static int test_vector_fmul(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
-                            const float *v1, const float *v2)
-{
-    LOCAL_ALIGNED(32, float, cdst, [LEN]);
-    LOCAL_ALIGNED(32, float, odst, [LEN]);
-    int ret;
-
-    cdsp->vector_fmul(cdst, v1, v2, LEN);
-    fdsp->vector_fmul(odst, v1, v2, LEN);
-
-    if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON))
-        av_log(NULL, AV_LOG_ERROR, "vector_fmul failed\n");
-
-    return ret;
-}
-
-#define ARBITRARY_FMAC_SCALAR_CONST 0.005
-static int test_vector_fmac_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
-                                   const float *v1, const float *src0, float scale)
-{
-    LOCAL_ALIGNED(32, float, cdst, [LEN]);
-    LOCAL_ALIGNED(32, float, odst, [LEN]);
-    int ret;
-
-    memcpy(cdst, v1, LEN * sizeof(*v1));
-    memcpy(odst, v1, LEN * sizeof(*v1));
-
-    cdsp->vector_fmac_scalar(cdst, src0, scale, LEN);
-    fdsp->vector_fmac_scalar(odst, src0, scale, LEN);
-
-    if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMAC_SCALAR_CONST))
-        av_log(NULL, AV_LOG_ERROR, "vector_fmac_scalar failed\n");
-
-    return ret;
-}
-
-static int test_vector_fmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
-                                   const float *v1, float scale)
-{
-    LOCAL_ALIGNED(32, float, cdst, [LEN]);
-    LOCAL_ALIGNED(32, float, odst, [LEN]);
-    int ret;
-
-    cdsp->vector_fmul_scalar(cdst, v1, scale, LEN);
-    fdsp->vector_fmul_scalar(odst, v1, scale, LEN);
-
-    if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON))
-        av_log(NULL, AV_LOG_ERROR, "vector_fmul_scalar failed\n");
-
-    return ret;
-}
-
-static int test_vector_dmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
-                                   const double *v1, double scale)
-{
-    LOCAL_ALIGNED(32, double, cdst, [LEN]);
-    LOCAL_ALIGNED(32, double, odst, [LEN]);
-    int ret;
-
-    cdsp->vector_dmul_scalar(cdst, v1, scale, LEN);
-    fdsp->vector_dmul_scalar(odst, v1, scale, LEN);
-
-    if (ret = compare_doubles(cdst, odst, LEN, DBL_EPSILON))
-        av_log(NULL, AV_LOG_ERROR, "vector_dmul_scalar failed\n");
-
-    return ret;
-}
-
-#define ARBITRARY_FMUL_WINDOW_CONST 0.008
-static int test_vector_fmul_window(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
-                                   const float *v1, const float *v2, const float *v3)
-{
-    LOCAL_ALIGNED(32, float, cdst, [LEN]);
-    LOCAL_ALIGNED(32, float, odst, [LEN]);
-    int ret;
-
-    cdsp->vector_fmul_window(cdst, v1, v2, v3, LEN / 2);
-    fdsp->vector_fmul_window(odst, v1, v2, v3, LEN / 2);
-
-    if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_WINDOW_CONST))
-        av_log(NULL, AV_LOG_ERROR, "vector_fmul_window failed\n");
-
-    return ret;
-}
-
-#define ARBITRARY_FMUL_ADD_CONST 0.005
-static int test_vector_fmul_add(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
-                                const float *v1, const float *v2, const float *v3)
-{
-    LOCAL_ALIGNED(32, float, cdst, [LEN]);
-    LOCAL_ALIGNED(32, float, odst, [LEN]);
-    int ret;
-
-    cdsp->vector_fmul_add(cdst, v1, v2, v3, LEN);
-    fdsp->vector_fmul_add(odst, v1, v2, v3, LEN);
-
-    if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_ADD_CONST))
-        av_log(NULL, AV_LOG_ERROR, "vector_fmul_add failed\n");
-
-    return ret;
-}
-
-static int test_vector_fmul_reverse(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
-                                    const float *v1, const float *v2)
-{
-    LOCAL_ALIGNED(32, float, cdst, [LEN]);
-    LOCAL_ALIGNED(32, float, odst, [LEN]);
-    int ret;
-
-    cdsp->vector_fmul_reverse(cdst, v1, v2, LEN);
-    fdsp->vector_fmul_reverse(odst, v1, v2, LEN);
-
-    if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON))
-        av_log(NULL, AV_LOG_ERROR, "vector_fmul_reverse failed\n");
-
-    return ret;
-}
-
-static int test_butterflies_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
-                                  const float *v1, const float *v2)
-{
-    LOCAL_ALIGNED(32, float, cv1, [LEN]);
-    LOCAL_ALIGNED(32, float, cv2, [LEN]);
-    LOCAL_ALIGNED(32, float, ov1, [LEN]);
-    LOCAL_ALIGNED(32, float, ov2, [LEN]);
-    int ret;
-
-    memcpy(cv1, v1, LEN * sizeof(*v1));
-    memcpy(cv2, v2, LEN * sizeof(*v2));
-    memcpy(ov1, v1, LEN * sizeof(*v1));
-    memcpy(ov2, v2, LEN * sizeof(*v2));
-
-    cdsp->butterflies_float(cv1, cv2, LEN);
-    fdsp->butterflies_float(ov1, ov2, LEN);
-
-    if ((ret = compare_floats(cv1, ov1, LEN, FLT_EPSILON)) ||
-        (ret = compare_floats(cv2, ov2, LEN, FLT_EPSILON)))
-        av_log(NULL, AV_LOG_ERROR, "butterflies_float failed\n");
-
-    return ret;
-}
-
-#define ARBITRARY_SCALARPRODUCT_CONST 0.2
-static int test_scalarproduct_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
-                                    const float *v1, const float *v2)
-{
-    float cprod, oprod;
-    int ret;
-
-    cprod = cdsp->scalarproduct_float(v1, v2, LEN);
-    oprod = fdsp->scalarproduct_float(v1, v2, LEN);
-
-    if (ret = compare_floats(&cprod, &oprod, 1, ARBITRARY_SCALARPRODUCT_CONST))
-        av_log(NULL, AV_LOG_ERROR, "scalarproduct_float failed\n");
-
-    return ret;
-}
-
-int main(int argc, char **argv)
-{
-    int ret = 0, seeded = 0;
-    uint32_t seed;
-    AVFloatDSPContext *fdsp, *cdsp;
-    AVLFG lfg;
-
-    LOCAL_ALIGNED(32, float, src0, [LEN]);
-    LOCAL_ALIGNED(32, float, src1, [LEN]);
-    LOCAL_ALIGNED(32, float, src2, [LEN]);
-    LOCAL_ALIGNED(32, double, dbl_src0, [LEN]);
-    LOCAL_ALIGNED(32, double, dbl_src1, [LEN]);
-
-    for (;;) {
-        int arg = getopt(argc, argv, "s:c:");
-        if (arg == -1)
-            break;
-        switch (arg) {
-        case 's':
-            seed = strtoul(optarg, NULL, 10);
-            seeded = 1;
-            break;
-        case 'c':
-        {
-            int cpuflags = av_get_cpu_flags();
-
-            if (av_parse_cpu_caps(&cpuflags, optarg) < 0)
-                return 1;
-
-            av_force_cpu_flags(cpuflags);
-            break;
-        }
-        }
-    }
-    if (!seeded)
-        seed = av_get_random_seed();
-
-    av_log(NULL, AV_LOG_INFO, "float_dsp-test: %s %u\n", seeded ? "seed" : "random seed", seed);
-
-    fdsp = avpriv_float_dsp_alloc(1);
-    av_force_cpu_flags(0);
-    cdsp = avpriv_float_dsp_alloc(1);
-
-    if (!fdsp || !cdsp) {
-        ret = 1;
-        goto end;
-    }
-
-    av_lfg_init(&lfg, seed);
-
-    fill_float_array(&lfg, src0, LEN);
-    fill_float_array(&lfg, src1, LEN);
-    fill_float_array(&lfg, src2, LEN);
-
-    fill_double_array(&lfg, dbl_src0, LEN);
-    fill_double_array(&lfg, dbl_src1, LEN);
-
-    if (test_vector_fmul(fdsp, cdsp, src0, src1))
-        ret -= 1 << 0;
-    if (test_vector_fmac_scalar(fdsp, cdsp, src2, src0, src1[0]))
-        ret -= 1 << 1;
-    if (test_vector_fmul_scalar(fdsp, cdsp, src0, src1[0]))
-        ret -= 1 << 2;
-    if (test_vector_fmul_window(fdsp, cdsp, src0, src1, src2))
-        ret -= 1 << 3;
-    if (test_vector_fmul_add(fdsp, cdsp, src0, src1, src2))
-        ret -= 1 << 4;
-    if (test_vector_fmul_reverse(fdsp, cdsp, src0, src1))
-        ret -= 1 << 5;
-    if (test_butterflies_float(fdsp, cdsp, src0, src1))
-        ret -= 1 << 6;
-    if (test_scalarproduct_float(fdsp, cdsp, src0, src1))
-        ret -= 1 << 7;
-    if (test_vector_dmul_scalar(fdsp, cdsp, dbl_src0, dbl_src1[0]))
-        ret -= 1 << 8;
-
-end:
-    av_freep(&fdsp);
-    av_freep(&cdsp);
-    return ret;
-}
-
-#endif /* TEST */
diff --git a/libavutil/frame.c b/libavutil/frame.c
index 033f013..d5c7c9f 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -376,6 +375,9 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src)
 {
     int i, ret = 0;
 
+    av_assert1(dst->width == 0 && dst->height == 0);
+    av_assert1(dst->channels == 0);
+
     dst->format         = src->format;
     dst->width          = src->width;
     dst->height         = src->height;
@@ -429,6 +431,14 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src)
         }
     }
 
+    if (src->hw_frames_ctx) {
+        dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
+        if (!dst->hw_frames_ctx) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+
     /* duplicate extended data */
     if (src->extended_data != src->data) {
         int ch = src->channels;
@@ -490,11 +500,16 @@ void av_frame_unref(AVFrame *frame)
     av_buffer_unref(&frame->qp_table_buf);
 #endif
 
+    av_buffer_unref(&frame->hw_frames_ctx);
+
     get_frame_defaults(frame);
 }
 
 void av_frame_move_ref(AVFrame *dst, AVFrame *src)
 {
+    av_assert1(dst->width == 0 && dst->height == 0);
+    av_assert1(dst->channels == 0);
+
     *dst = *src;
     if (src->extended_data == src->data)
         dst->extended_data = dst->data;
diff --git a/libavutil/frame.h b/libavutil/frame.h
index 8dc4049..2b5c332 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
@@ -177,6 +176,10 @@ typedef struct AVFrameSideData {
  * Similarly fields that are marked as to be only accessed by
  * av_opt_ptr() can be reordered. This allows 2 forks to add fields
  * without breaking compatibility with each other.
+ *
+ * Fields can be accessed through AVOptions, the name string used, matches the
+ * C structure field name for fields accessable through AVOptions. The AVClass
+ * for AVFrame can be obtained from avcodec_get_frame_class()
  */
 typedef struct AVFrame {
 #define AV_NUM_DATA_POINTERS 8
@@ -188,6 +191,9 @@ typedef struct AVFrame {
      * see avcodec_align_dimensions2(). Some filters and swscale can read
      * up to 16 bytes beyond the planes, if these filters are to be used,
      * then 16 extra bytes must be allocated.
+     *
+     * NOTE: Except for hwaccel formats, pointers not needed by the format
+     * MUST be set to NULL.
      */
     uint8_t *data[AV_NUM_DATA_POINTERS];
 
@@ -322,7 +328,7 @@ typedef struct AVFrame {
     int palette_has_changed;
 
     /**
-     * reordered opaque 64bit (generally an integer or a double precision float
+     * reordered opaque 64 bits (generally an integer or a double precision float
      * PTS but can be anything).
      * The user sets AVCodecContext.reordered_opaque to represent the input at
      * that time,
@@ -512,6 +518,11 @@ typedef struct AVFrame {
      */
     AVBufferRef *qp_table_buf;
 #endif
+    /**
+     * For hwaccel-format frames, this should be a reference to the
+     * AVHWFramesContext describing the frame.
+     */
+    AVBufferRef *hw_frames_ctx;
 } AVFrame;
 
 /**
@@ -583,6 +594,10 @@ void av_frame_free(AVFrame **frame);
  * If src is not reference counted, new buffers are allocated and the data is
  * copied.
  *
+ * @warning: dst MUST have been either unreferenced with av_frame_unref(dst),
+ *           or newly allocated with av_frame_alloc() before calling this
+ *           function, or undefined behavior will occur.
+ *
  * @return 0 on success, a negative AVERROR on error
  */
 int av_frame_ref(AVFrame *dst, const AVFrame *src);
@@ -603,6 +618,10 @@ void av_frame_unref(AVFrame *frame);
 
 /**
  * Move everything contained in src to dst and reset src.
+ *
+ * @warning: dst is not unreferenced, but directly overwritten without reading
+ *           or deallocating its contents. Call av_frame_unref(dst) manually
+ *           before calling this function to ensure that no memory is leaked.
  */
 void av_frame_move_ref(AVFrame *dst, AVFrame *src);
 
@@ -618,6 +637,10 @@ void av_frame_move_ref(AVFrame *dst, AVFrame *src);
  * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf.
  * For planar formats, one buffer will be allocated for each plane.
  *
+ * @warning: if frame already has been allocated, calling this function will
+ *           leak memory. In addition, undefined behavior can occur in certain
+ *           cases.
+ *
  * @param frame frame in which to store the new buffers.
  * @param align required buffer size alignment
  *
diff --git a/libavutil/hmac.c b/libavutil/hmac.c
index 3e11509..8ec6d70 100644
--- a/libavutil/hmac.c
+++ b/libavutil/hmac.c
@@ -183,84 +183,3 @@ int av_hmac_calc(AVHMAC *c, const uint8_t *data, unsigned int len,
     av_hmac_update(c, data, len);
     return av_hmac_final(c, out, outlen);
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-static void test(AVHMAC *hmac, const uint8_t *key, int keylen,
-                 const uint8_t *data, int datalen)
-{
-    uint8_t buf[MAX_HASHLEN];
-    int out, i;
-    // Some of the test vectors are strings, where sizeof() includes the
-    // trailing null byte - remove that.
-    if (!key[keylen - 1])
-        keylen--;
-    if (!data[datalen - 1])
-        datalen--;
-    out = av_hmac_calc(hmac, data, datalen, key, keylen, buf, sizeof(buf));
-    for (i = 0; i < out; i++)
-        printf("%02x", buf[i]);
-    printf("\n");
-}
-
-int main(void)
-{
-    uint8_t key1[20], key3[131], data3[50];
-    AVHMAC *hmac;
-    enum AVHMACType i;
-    static const uint8_t key2[]  = "Jefe";
-    static const uint8_t data1[] = "Hi There";
-    static const uint8_t data2[] = "what do ya want for nothing?";
-    static const uint8_t data4[] = "Test Using Larger Than Block-Size Key - Hash Key First";
-    static const uint8_t data5[] = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data";
-    static const uint8_t data6[] = "This is a test using a larger than block-size key and a larger "
-                            "than block-size data. The key needs to be hashed before being used"
-                            " by the HMAC algorithm.";
-    memset(key1, 0x0b, sizeof(key1));
-    memset(key3, 0xaa, sizeof(key3));
-    memset(data3, 0xdd, sizeof(data3));
-
-    /* MD5, SHA-1 */
-    for (i = AV_HMAC_MD5; i <= AV_HMAC_SHA1; i++) {
-        hmac = av_hmac_alloc(i);
-        if (!hmac)
-            return 1;
-        // RFC 2202 test vectors
-        test(hmac, key1, hmac->hashlen, data1, sizeof(data1));
-        test(hmac, key2, sizeof(key2),  data2, sizeof(data2));
-        test(hmac, key3, hmac->hashlen, data3, sizeof(data3));
-        test(hmac, key3, 80,            data4, sizeof(data4));
-        test(hmac, key3, 80,            data5, sizeof(data5));
-        av_hmac_free(hmac);
-    }
-
-    /* SHA-2 */
-    for (i = AV_HMAC_SHA224; i <= AV_HMAC_SHA256; i++) {
-        hmac = av_hmac_alloc(i);
-        if (!hmac)
-            return 1;
-        // RFC 4231 test vectors
-        test(hmac, key1, sizeof(key1), data1, sizeof(data1));
-        test(hmac, key2, sizeof(key2), data2, sizeof(data2));
-        test(hmac, key3, 20,           data3, sizeof(data3));
-        test(hmac, key3, sizeof(key3), data4, sizeof(data4));
-        test(hmac, key3, sizeof(key3), data6, sizeof(data6));
-        av_hmac_free(hmac);
-    }
-
-    for (i = AV_HMAC_SHA384; i <= AV_HMAC_SHA512; i++) {
-        hmac = av_hmac_alloc(i);
-        if (!hmac)
-            return 1;
-        // RFC 4231 test vectors
-        test(hmac, key1, sizeof(key1), data1, sizeof(data1));
-        test(hmac, key2, sizeof(key2), data2, sizeof(data2));
-        test(hmac, key3, 20, data3, sizeof(data3));
-        test(hmac, key3, sizeof(key3), data4, sizeof(data4));
-        test(hmac, key3, sizeof(key3), data6, sizeof(data6));
-        av_hmac_free(hmac);
-    }
-    return 0;
-}
-#endif /* TEST */
diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
new file mode 100644
index 0000000..1e9e913
--- /dev/null
+++ b/libavutil/hwcontext.c
@@ -0,0 +1,490 @@
+/*
+ * 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 "config.h"
+
+#include "buffer.h"
+#include "common.h"
+#include "hwcontext.h"
+#include "hwcontext_internal.h"
+#include "imgutils.h"
+#include "log.h"
+#include "mem.h"
+#include "pixdesc.h"
+#include "pixfmt.h"
+
+static const HWContextType *hw_table[] = {
+#if CONFIG_CUDA
+    &ff_hwcontext_type_cuda,
+#endif
+#if CONFIG_DXVA2
+    &ff_hwcontext_type_dxva2,
+#endif
+#if CONFIG_VAAPI
+    &ff_hwcontext_type_vaapi,
+#endif
+#if CONFIG_VDPAU
+    &ff_hwcontext_type_vdpau,
+#endif
+    NULL,
+};
+
+static const AVClass hwdevice_ctx_class = {
+    .class_name = "AVHWDeviceContext",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static void hwdevice_ctx_free(void *opaque, uint8_t *data)
+{
+    AVHWDeviceContext *ctx = (AVHWDeviceContext*)data;
+
+    /* uninit might still want access the hw context and the user
+     * free() callback might destroy it, so uninit has to be called first */
+    if (ctx->internal->hw_type->device_uninit)
+        ctx->internal->hw_type->device_uninit(ctx);
+
+    if (ctx->free)
+        ctx->free(ctx);
+
+    av_freep(&ctx->hwctx);
+    av_freep(&ctx->internal->priv);
+    av_freep(&ctx->internal);
+    av_freep(&ctx);
+}
+
+AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
+{
+    AVHWDeviceContext *ctx;
+    AVBufferRef *buf;
+    const HWContextType *hw_type = NULL;
+    int i;
+
+    for (i = 0; hw_table[i]; i++) {
+        if (hw_table[i]->type == type) {
+            hw_type = hw_table[i];
+            break;
+        }
+    }
+    if (!hw_type)
+        return NULL;
+
+    ctx = av_mallocz(sizeof(*ctx));
+    if (!ctx)
+        return NULL;
+
+    ctx->internal = av_mallocz(sizeof(*ctx->internal));
+    if (!ctx->internal)
+        goto fail;
+
+    if (hw_type->device_priv_size) {
+        ctx->internal->priv = av_mallocz(hw_type->device_priv_size);
+        if (!ctx->internal->priv)
+            goto fail;
+    }
+
+    if (hw_type->device_hwctx_size) {
+        ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
+        if (!ctx->hwctx)
+            goto fail;
+    }
+
+    buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
+                           hwdevice_ctx_free, NULL,
+                           AV_BUFFER_FLAG_READONLY);
+    if (!buf)
+        goto fail;
+
+    ctx->type     = type;
+    ctx->av_class = &hwdevice_ctx_class;
+
+    ctx->internal->hw_type = hw_type;
+
+    return buf;
+
+fail:
+    if (ctx->internal)
+        av_freep(&ctx->internal->priv);
+    av_freep(&ctx->internal);
+    av_freep(&ctx->hwctx);
+    av_freep(&ctx);
+    return NULL;
+}
+
+int av_hwdevice_ctx_init(AVBufferRef *ref)
+{
+    AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
+    int ret;
+
+    if (ctx->internal->hw_type->device_init) {
+        ret = ctx->internal->hw_type->device_init(ctx);
+        if (ret < 0)
+            goto fail;
+    }
+
+    return 0;
+fail:
+    if (ctx->internal->hw_type->device_uninit)
+        ctx->internal->hw_type->device_uninit(ctx);
+    return ret;
+}
+
+static const AVClass hwframe_ctx_class = {
+    .class_name = "AVHWFramesContext",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static void hwframe_ctx_free(void *opaque, uint8_t *data)
+{
+    AVHWFramesContext *ctx = (AVHWFramesContext*)data;
+
+    if (ctx->internal->pool_internal)
+        av_buffer_pool_uninit(&ctx->internal->pool_internal);
+
+    if (ctx->internal->hw_type->frames_uninit)
+        ctx->internal->hw_type->frames_uninit(ctx);
+
+    if (ctx->free)
+        ctx->free(ctx);
+
+    av_buffer_unref(&ctx->device_ref);
+
+    av_freep(&ctx->hwctx);
+    av_freep(&ctx->internal->priv);
+    av_freep(&ctx->internal);
+    av_freep(&ctx);
+}
+
+AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
+{
+    AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data;
+    const HWContextType  *hw_type = device_ctx->internal->hw_type;
+    AVHWFramesContext *ctx;
+    AVBufferRef *buf, *device_ref = NULL;
+
+    ctx = av_mallocz(sizeof(*ctx));
+    if (!ctx)
+        return NULL;
+
+    ctx->internal = av_mallocz(sizeof(*ctx->internal));
+    if (!ctx->internal)
+        goto fail;
+
+    if (hw_type->frames_priv_size) {
+        ctx->internal->priv = av_mallocz(hw_type->frames_priv_size);
+        if (!ctx->internal->priv)
+            goto fail;
+    }
+
+    if (hw_type->frames_hwctx_size) {
+        ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
+        if (!ctx->hwctx)
+            goto fail;
+    }
+
+    device_ref = av_buffer_ref(device_ref_in);
+    if (!device_ref)
+        goto fail;
+
+    buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
+                           hwframe_ctx_free, NULL,
+                           AV_BUFFER_FLAG_READONLY);
+    if (!buf)
+        goto fail;
+
+    ctx->av_class   = &hwframe_ctx_class;
+    ctx->device_ref = device_ref;
+    ctx->device_ctx = device_ctx;
+    ctx->format     = AV_PIX_FMT_NONE;
+    ctx->sw_format  = AV_PIX_FMT_NONE;
+
+    ctx->internal->hw_type = hw_type;
+
+    return buf;
+
+fail:
+    if (device_ref)
+        av_buffer_unref(&device_ref);
+    if (ctx->internal)
+        av_freep(&ctx->internal->priv);
+    av_freep(&ctx->internal);
+    av_freep(&ctx->hwctx);
+    av_freep(&ctx);
+    return NULL;
+}
+
+static int hwframe_pool_prealloc(AVBufferRef *ref)
+{
+    AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
+    AVFrame **frames;
+    int i, ret = 0;
+
+    frames = av_mallocz_array(ctx->initial_pool_size, sizeof(*frames));
+    if (!frames)
+        return AVERROR(ENOMEM);
+
+    for (i = 0; i < ctx->initial_pool_size; i++) {
+        frames[i] = av_frame_alloc();
+        if (!frames[i])
+            goto fail;
+
+        ret = av_hwframe_get_buffer(ref, frames[i], 0);
+        if (ret < 0)
+            goto fail;
+    }
+
+fail:
+    for (i = 0; i < ctx->initial_pool_size; i++)
+        av_frame_free(&frames[i]);
+    av_freep(&frames);
+
+    return ret;
+}
+
+int av_hwframe_ctx_init(AVBufferRef *ref)
+{
+    AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
+    const enum AVPixelFormat *pix_fmt;
+    int ret;
+
+    /* validate the pixel format */
+    for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) {
+        if (*pix_fmt == ctx->format)
+            break;
+    }
+    if (*pix_fmt == AV_PIX_FMT_NONE) {
+        av_log(ctx, AV_LOG_ERROR,
+               "The hardware pixel format '%s' is not supported by the device type '%s'\n",
+               av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name);
+        return AVERROR(ENOSYS);
+    }
+
+    /* validate the dimensions */
+    ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
+    if (ret < 0)
+        return ret;
+
+    /* format-specific init */
+    if (ctx->internal->hw_type->frames_init) {
+        ret = ctx->internal->hw_type->frames_init(ctx);
+        if (ret < 0)
+            goto fail;
+    }
+
+    if (ctx->internal->pool_internal && !ctx->pool)
+        ctx->pool = ctx->internal->pool_internal;
+
+    /* preallocate the frames in the pool, if requested */
+    if (ctx->initial_pool_size > 0) {
+        ret = hwframe_pool_prealloc(ref);
+        if (ret < 0)
+            goto fail;
+    }
+
+    return 0;
+fail:
+    if (ctx->internal->hw_type->frames_uninit)
+        ctx->internal->hw_type->frames_uninit(ctx);
+    return ret;
+}
+
+int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref,
+                                    enum AVHWFrameTransferDirection dir,
+                                    enum AVPixelFormat **formats, int flags)
+{
+    AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
+
+    if (!ctx->internal->hw_type->transfer_get_formats)
+        return AVERROR(ENOSYS);
+
+    return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats);
+}
+
+static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
+{
+    AVFrame *frame_tmp;
+    int ret = 0;
+
+    frame_tmp = av_frame_alloc();
+    if (!frame_tmp)
+        return AVERROR(ENOMEM);
+
+    /* if the format is set, use that
+     * otherwise pick the first supported one */
+    if (dst->format >= 0) {
+        frame_tmp->format = dst->format;
+    } else {
+        enum AVPixelFormat *formats;
+
+        ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx,
+                                              AV_HWFRAME_TRANSFER_DIRECTION_FROM,
+                                              &formats, 0);
+        if (ret < 0)
+            goto fail;
+        frame_tmp->format = formats[0];
+        av_freep(&formats);
+    }
+    frame_tmp->width  = src->width;
+    frame_tmp->height = src->height;
+
+    ret = av_frame_get_buffer(frame_tmp, 32);
+    if (ret < 0)
+        goto fail;
+
+    ret = av_hwframe_transfer_data(frame_tmp, src, flags);
+    if (ret < 0)
+        goto fail;
+
+    av_frame_move_ref(dst, frame_tmp);
+
+fail:
+    av_frame_free(&frame_tmp);
+    return ret;
+}
+
+int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
+{
+    AVHWFramesContext *ctx;
+    int ret;
+
+    if (!dst->buf[0])
+        return transfer_data_alloc(dst, src, flags);
+
+    if (src->hw_frames_ctx) {
+        ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
+
+        ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
+        if (ret < 0)
+            return ret;
+    } else if (dst->hw_frames_ctx) {
+        ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
+
+        ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
+        if (ret < 0)
+            return ret;
+    } else
+        return AVERROR(ENOSYS);
+
+    return 0;
+}
+
+int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
+{
+    AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
+    int ret;
+
+    if (!ctx->internal->hw_type->frames_get_buffer)
+        return AVERROR(ENOSYS);
+
+    if (!ctx->pool)
+        return AVERROR(EINVAL);
+
+    frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
+    if (!frame->hw_frames_ctx)
+        return AVERROR(ENOMEM);
+
+    ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame);
+    if (ret < 0) {
+        av_buffer_unref(&frame->hw_frames_ctx);
+        return ret;
+    }
+
+    return 0;
+}
+
+void *av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
+{
+    AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
+    const HWContextType  *hw_type = ctx->internal->hw_type;
+
+    if (hw_type->device_hwconfig_size == 0)
+        return NULL;
+
+    return av_mallocz(hw_type->device_hwconfig_size);
+}
+
+AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,
+                                                           const void *hwconfig)
+{
+    AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
+    const HWContextType  *hw_type = ctx->internal->hw_type;
+    AVHWFramesConstraints *constraints;
+
+    if (!hw_type->frames_get_constraints)
+        return NULL;
+
+    constraints = av_mallocz(sizeof(*constraints));
+    if (!constraints)
+        return NULL;
+
+    constraints->min_width = constraints->min_height = 0;
+    constraints->max_width = constraints->max_height = INT_MAX;
+
+    if (hw_type->frames_get_constraints(ctx, hwconfig, constraints) >= 0) {
+        return constraints;
+    } else {
+        av_hwframe_constraints_free(&constraints);
+        return NULL;
+    }
+}
+
+void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
+{
+    if (*constraints) {
+        av_freep(&(*constraints)->valid_hw_formats);
+        av_freep(&(*constraints)->valid_sw_formats);
+    }
+    av_freep(constraints);
+}
+
+int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type,
+                           const char *device, AVDictionary *opts, int flags)
+{
+    AVBufferRef *device_ref = NULL;
+    AVHWDeviceContext *device_ctx;
+    int ret = 0;
+
+    device_ref = av_hwdevice_ctx_alloc(type);
+    if (!device_ref) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+    device_ctx = (AVHWDeviceContext*)device_ref->data;
+
+    if (!device_ctx->internal->hw_type->device_create) {
+        ret = AVERROR(ENOSYS);
+        goto fail;
+    }
+
+    ret = device_ctx->internal->hw_type->device_create(device_ctx, device,
+                                                       opts, flags);
+    if (ret < 0)
+        goto fail;
+
+    ret = av_hwdevice_ctx_init(device_ref);
+    if (ret < 0)
+        goto fail;
+
+    *pdevice_ref = device_ref;
+    return 0;
+fail:
+    av_buffer_unref(&device_ref);
+    *pdevice_ref = NULL;
+    return ret;
+}
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
new file mode 100644
index 0000000..4e9da02
--- /dev/null
+++ b/libavutil/hwcontext.h
@@ -0,0 +1,428 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_HWCONTEXT_H
+#define AVUTIL_HWCONTEXT_H
+
+#include "buffer.h"
+#include "frame.h"
+#include "log.h"
+#include "pixfmt.h"
+
+enum AVHWDeviceType {
+    AV_HWDEVICE_TYPE_VDPAU,
+    AV_HWDEVICE_TYPE_CUDA,
+    AV_HWDEVICE_TYPE_VAAPI,
+    AV_HWDEVICE_TYPE_DXVA2,
+};
+
+typedef struct AVHWDeviceInternal AVHWDeviceInternal;
+
+/**
+ * This struct aggregates all the (hardware/vendor-specific) "high-level" state,
+ * i.e. state that is not tied to a concrete processing configuration.
+ * E.g., in an API that supports hardware-accelerated encoding and decoding,
+ * this struct will (if possible) wrap the state that is common to both encoding
+ * and decoding and from which specific instances of encoders or decoders can be
+ * derived.
+ *
+ * This struct is reference-counted with the AVBuffer mechanism. The
+ * av_hwdevice_ctx_alloc() constructor yields a reference, whose data field
+ * points to the actual AVHWDeviceContext. Further objects derived from
+ * AVHWDeviceContext (such as AVHWFramesContext, describing a frame pool with
+ * specific properties) will hold an internal reference to it. After all the
+ * references are released, the AVHWDeviceContext itself will be freed,
+ * optionally invoking a user-specified callback for uninitializing the hardware
+ * state.
+ */
+typedef struct AVHWDeviceContext {
+    /**
+     * A class for logging. Set by av_hwdevice_ctx_alloc().
+     */
+    const AVClass *av_class;
+
+    /**
+     * Private data used internally by libavutil. Must not be accessed in any
+     * way by the caller.
+     */
+    AVHWDeviceInternal *internal;
+
+    /**
+     * This field identifies the underlying API used for hardware access.
+     *
+     * This field is set when this struct is allocated and never changed
+     * afterwards.
+     */
+    enum AVHWDeviceType type;
+
+    /**
+     * The format-specific data, allocated and freed by libavutil along with
+     * this context.
+     *
+     * Should be cast by the user to the format-specific context defined in the
+     * corresponding header (hwcontext_*.h) and filled as described in the
+     * documentation before calling av_hwdevice_ctx_init().
+     *
+     * After calling av_hwdevice_ctx_init() this struct should not be modified
+     * by the caller.
+     */
+    void *hwctx;
+
+    /**
+     * This field may be set by the caller before calling av_hwdevice_ctx_init().
+     *
+     * If non-NULL, this callback will be called when the last reference to
+     * this context is unreferenced, immediately before it is freed.
+     *
+     * @note when other objects (e.g an AVHWFramesContext) are derived from this
+     *       struct, this callback will be invoked after all such child objects
+     *       are fully uninitialized and their respective destructors invoked.
+     */
+    void (*free)(struct AVHWDeviceContext *ctx);
+
+    /**
+     * Arbitrary user data, to be used e.g. by the free() callback.
+     */
+    void *user_opaque;
+} AVHWDeviceContext;
+
+typedef struct AVHWFramesInternal AVHWFramesInternal;
+
+/**
+ * This struct describes a set or pool of "hardware" frames (i.e. those with
+ * data not located in normal system memory). All the frames in the pool are
+ * assumed to be allocated in the same way and interchangeable.
+ *
+ * This struct is reference-counted with the AVBuffer mechanism and tied to a
+ * given AVHWDeviceContext instance. The av_hwframe_ctx_alloc() constructor
+ * yields a reference, whose data field points to the actual AVHWFramesContext
+ * struct.
+ */
+typedef struct AVHWFramesContext {
+    /**
+     * A class for logging.
+     */
+    const AVClass *av_class;
+
+    /**
+     * Private data used internally by libavutil. Must not be accessed in any
+     * way by the caller.
+     */
+    AVHWFramesInternal *internal;
+
+    /**
+     * A reference to the parent AVHWDeviceContext. This reference is owned and
+     * managed by the enclosing AVHWFramesContext, but the caller may derive
+     * additional references from it.
+     */
+    AVBufferRef *device_ref;
+
+    /**
+     * The parent AVHWDeviceContext. This is simply a pointer to
+     * device_ref->data provided for convenience.
+     *
+     * Set by libavutil in av_hwframe_ctx_init().
+     */
+    AVHWDeviceContext *device_ctx;
+
+    /**
+     * The format-specific data, allocated and freed automatically along with
+     * this context.
+     *
+     * Should be cast by the user to the format-specific context defined in the
+     * corresponding header (hwframe_*.h) and filled as described in the
+     * documentation before calling av_hwframe_ctx_init().
+     *
+     * After any frames using this context are created, the contents of this
+     * struct should not be modified by the caller.
+     */
+    void *hwctx;
+
+    /**
+     * This field may be set by the caller before calling av_hwframe_ctx_init().
+     *
+     * If non-NULL, this callback will be called when the last reference to
+     * this context is unreferenced, immediately before it is freed.
+     */
+    void (*free)(struct AVHWFramesContext *ctx);
+
+    /**
+     * Arbitrary user data, to be used e.g. by the free() callback.
+     */
+    void *user_opaque;
+
+    /**
+     * A pool from which the frames are allocated by av_hwframe_get_buffer().
+     * This field may be set by the caller before calling av_hwframe_ctx_init().
+     * The buffers returned by calling av_buffer_pool_get() on this pool must
+     * have the properties described in the documentation in the corresponding hw
+     * type's header (hwcontext_*.h). The pool will be freed strictly before
+     * this struct's free() callback is invoked.
+     *
+     * This field may be NULL, then libavutil will attempt to allocate a pool
+     * internally. Note that certain device types enforce pools allocated at
+     * fixed size (frame count), which cannot be extended dynamically. In such a
+     * case, initial_pool_size must be set appropriately.
+     */
+    AVBufferPool *pool;
+
+    /**
+     * Initial size of the frame pool. If a device type does not support
+     * dynamically resizing the pool, then this is also the maximum pool size.
+     *
+     * May be set by the caller before calling av_hwframe_ctx_init(). Must be
+     * set if pool is NULL and the device type does not support dynamic pools.
+     */
+    int initial_pool_size;
+
+    /**
+     * The pixel format identifying the underlying HW surface type.
+     *
+     * Must be a hwaccel format, i.e. the corresponding descriptor must have the
+     * AV_PIX_FMT_FLAG_HWACCEL flag set.
+     *
+     * Must be set by the user before calling av_hwframe_ctx_init().
+     */
+    enum AVPixelFormat format;
+
+    /**
+     * The pixel format identifying the actual data layout of the hardware
+     * frames.
+     *
+     * Must be set by the caller before calling av_hwframe_ctx_init().
+     *
+     * @note when the underlying API does not provide the exact data layout, but
+     * only the colorspace/bit depth, this field should be set to the fully
+     * planar version of that format (e.g. for 8-bit 420 YUV it should be
+     * AV_PIX_FMT_YUV420P, not AV_PIX_FMT_NV12 or anything else).
+     */
+    enum AVPixelFormat sw_format;
+
+    /**
+     * The allocated dimensions of the frames in this pool.
+     *
+     * Must be set by the user before calling av_hwframe_ctx_init().
+     */
+    int width, height;
+} AVHWFramesContext;
+
+/**
+ * Allocate an AVHWDeviceContext for a given pixel format.
+ *
+ * @param format a hwaccel pixel format (AV_PIX_FMT_FLAG_HWACCEL must be set
+ *               on the corresponding format descriptor)
+ * @return a reference to the newly created AVHWDeviceContext on success or NULL
+ *         on failure.
+ */
+AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type);
+
+/**
+ * Finalize the device context before use. This function must be called after
+ * the context is filled with all the required information and before it is
+ * used in any way.
+ *
+ * @param ref a reference to the AVHWDeviceContext
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_hwdevice_ctx_init(AVBufferRef *ref);
+
+/**
+ * Open a device of the specified type and create an AVHWDeviceContext for it.
+ *
+ * This is a convenience function intended to cover the simple cases. Callers
+ * who need to fine-tune device creation/management should open the device
+ * manually and then wrap it in an AVHWDeviceContext using
+ * av_hwdevice_ctx_alloc()/av_hwdevice_ctx_init().
+ *
+ * The returned context is already initialized and ready for use, the caller
+ * should not call av_hwdevice_ctx_init() on it. The user_opaque/free fields of
+ * the created AVHWDeviceContext are set by this function and should not be
+ * touched by the caller.
+ *
+ * @param device_ctx On success, a reference to the newly-created device context
+ *                   will be written here. The reference is owned by the caller
+ *                   and must be released with av_buffer_unref() when no longer
+ *                   needed. On failure, NULL will be written to this pointer.
+ * @param type The type of the device to create.
+ * @param device A type-specific string identifying the device to open.
+ * @param opts A dictionary of additional (type-specific) options to use in
+ *             opening the device. The dictionary remains owned by the caller.
+ * @param flags currently unused
+ *
+ * @return 0 on success, a negative AVERROR code on failure.
+ */
+int av_hwdevice_ctx_create(AVBufferRef **device_ctx, enum AVHWDeviceType type,
+                           const char *device, AVDictionary *opts, int flags);
+
+/**
+ * Allocate an AVHWFramesContext tied to a given device context.
+ *
+ * @param device_ctx a reference to a AVHWDeviceContext. This function will make
+ *                   a new reference for internal use, the one passed to the
+ *                   function remains owned by the caller.
+ * @return a reference to the newly created AVHWFramesContext on success or NULL
+ *         on failure.
+ */
+AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ctx);
+
+/**
+ * Finalize the context before use. This function must be called after the
+ * context is filled with all the required information and before it is attached
+ * to any frames.
+ *
+ * @param ref a reference to the AVHWFramesContext
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_hwframe_ctx_init(AVBufferRef *ref);
+
+/**
+ * Allocate a new frame attached to the given AVHWFramesContext.
+ *
+ * @param hwframe_ctx a reference to an AVHWFramesContext
+ * @param frame an empty (freshly allocated or unreffed) frame to be filled with
+ *              newly allocated buffers.
+ * @param flags currently unused, should be set to zero
+ * @return 0 on success, a negative AVERROR code on failure
+ */
+int av_hwframe_get_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame, int flags);
+
+/**
+ * Copy data to or from a hw surface. At least one of dst/src must have an
+ * AVHWFramesContext attached.
+ *
+ * If src has an AVHWFramesContext attached, then the format of dst (if set)
+ * must use one of the formats returned by av_hwframe_transfer_get_formats(src,
+ * AV_HWFRAME_TRANSFER_DIRECTION_FROM).
+ * If dst has an AVHWFramesContext attached, then the format of src must use one
+ * of the formats returned by av_hwframe_transfer_get_formats(dst,
+ * AV_HWFRAME_TRANSFER_DIRECTION_TO)
+ *
+ * dst may be "clean" (i.e. with data/buf pointers unset), in which case the
+ * data buffers will be allocated by this function using av_frame_get_buffer().
+ * If dst->format is set, then this format will be used, otherwise (when
+ * dst->format is AV_PIX_FMT_NONE) the first acceptable format will be chosen.
+ *
+ * @param dst the destination frame. dst is not touched on failure.
+ * @param src the source frame.
+ * @param flags currently unused, should be set to zero
+ * @return 0 on success, a negative AVERROR error code on failure.
+ */
+int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags);
+
+enum AVHWFrameTransferDirection {
+    /**
+     * Transfer the data from the queried hw frame.
+     */
+    AV_HWFRAME_TRANSFER_DIRECTION_FROM,
+
+    /**
+     * Transfer the data to the queried hw frame.
+     */
+    AV_HWFRAME_TRANSFER_DIRECTION_TO,
+};
+
+/**
+ * Get a list of possible source or target formats usable in
+ * av_hwframe_transfer_data().
+ *
+ * @param hwframe_ctx the frame context to obtain the information for
+ * @param dir the direction of the transfer
+ * @param formats the pointer to the output format list will be written here.
+ *                The list is terminated with AV_PIX_FMT_NONE and must be freed
+ *                by the caller when no longer needed using av_free().
+ *                If this function returns successfully, the format list will
+ *                have at least one item (not counting the terminator).
+ *                On failure, the contents of this pointer are unspecified.
+ * @param flags currently unused, should be set to zero
+ * @return 0 on success, a negative AVERROR code on failure.
+ */
+int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ctx,
+                                    enum AVHWFrameTransferDirection dir,
+                                    enum AVPixelFormat **formats, int flags);
+
+
+/**
+ * This struct describes the constraints on hardware frames attached to
+ * a given device with a hardware-specific configuration.  This is returned
+ * by av_hwdevice_get_hwframe_constraints() and must be freed by
+ * av_hwframe_constraints_free() after use.
+ */
+typedef struct AVHWFramesConstraints {
+    /**
+     * A list of possible values for format in the hw_frames_ctx,
+     * terminated by AV_PIX_FMT_NONE.  This member will always be filled.
+     */
+    enum AVPixelFormat *valid_hw_formats;
+
+    /**
+     * A list of possible values for sw_format in the hw_frames_ctx,
+     * terminated by AV_PIX_FMT_NONE.  Can be NULL if this information is
+     * not known.
+     */
+    enum AVPixelFormat *valid_sw_formats;
+
+    /**
+     * The minimum size of frames in this hw_frames_ctx.
+     * (Zero if not known.)
+     */
+    int min_width;
+    int min_height;
+
+    /**
+     * The maximum size of frames in this hw_frames_ctx.
+     * (INT_MAX if not known / no limit.)
+     */
+    int max_width;
+    int max_height;
+} AVHWFramesConstraints;
+
+/**
+ * Allocate a HW-specific configuration structure for a given HW device.
+ * After use, the user must free all members as required by the specific
+ * hardware structure being used, then free the structure itself with
+ * av_free().
+ *
+ * @param device_ctx a reference to the associated AVHWDeviceContext.
+ * @return The newly created HW-specific configuration structure on
+ *         success or NULL on failure.
+ */
+void *av_hwdevice_hwconfig_alloc(AVBufferRef *device_ctx);
+
+/**
+ * Get the constraints on HW frames given a device and the HW-specific
+ * configuration to be used with that device.  If no HW-specific
+ * configuration is provided, returns the maximum possible capabilities
+ * of the device.
+ *
+ * @param device_ctx a reference to the associated AVHWDeviceContext.
+ * @param hwconfig a filled HW-specific configuration structure, or NULL
+ *        to return the maximum possible capabilities of the device.
+ * @return AVHWFramesConstraints structure describing the constraints
+ *         on the device, or NULL if not available.
+ */
+AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,
+                                                           const void *hwconfig);
+
+/**
+ * Free an AVHWFrameConstraints structure.
+ *
+ * @param constraints The (filled or unfilled) AVHWFrameConstraints structure.
+ */
+void av_hwframe_constraints_free(AVHWFramesConstraints **constraints);
+
+#endif /* AVUTIL_HWCONTEXT_H */
diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c
new file mode 100644
index 0000000..fa24c5d
--- /dev/null
+++ b/libavutil/hwcontext_cuda.c
@@ -0,0 +1,314 @@
+/*
+ * 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 "buffer.h"
+#include "common.h"
+#include "hwcontext.h"
+#include "hwcontext_internal.h"
+#include "hwcontext_cuda.h"
+#include "mem.h"
+#include "pixdesc.h"
+#include "pixfmt.h"
+
+typedef struct CUDAFramesContext {
+    int shift_width, shift_height;
+} CUDAFramesContext;
+
+static const enum AVPixelFormat supported_formats[] = {
+    AV_PIX_FMT_NV12,
+    AV_PIX_FMT_YUV420P,
+    AV_PIX_FMT_YUV444P,
+};
+
+static void cuda_buffer_free(void *opaque, uint8_t *data)
+{
+    AVHWFramesContext *ctx = opaque;
+    AVCUDADeviceContext *hwctx = ctx->device_ctx->hwctx;
+
+    CUcontext dummy;
+
+    cuCtxPushCurrent(hwctx->cuda_ctx);
+
+    cuMemFree((CUdeviceptr)data);
+
+    cuCtxPopCurrent(&dummy);
+}
+
+static AVBufferRef *cuda_pool_alloc(void *opaque, int size)
+{
+    AVHWFramesContext     *ctx = opaque;
+    AVCUDADeviceContext *hwctx = ctx->device_ctx->hwctx;
+
+    AVBufferRef *ret = NULL;
+    CUcontext dummy = NULL;
+    CUdeviceptr data;
+    CUresult err;
+
+    err = cuCtxPushCurrent(hwctx->cuda_ctx);
+    if (err != CUDA_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Error setting current CUDA context\n");
+        return NULL;
+    }
+
+    err = cuMemAlloc(&data, size);
+    if (err != CUDA_SUCCESS)
+        goto fail;
+
+    ret = av_buffer_create((uint8_t*)data, size, cuda_buffer_free, ctx, 0);
+    if (!ret) {
+        cuMemFree(data);
+        goto fail;
+    }
+
+fail:
+    cuCtxPopCurrent(&dummy);
+    return ret;
+}
+
+static int cuda_frames_init(AVHWFramesContext *ctx)
+{
+    CUDAFramesContext *priv = ctx->internal->priv;
+    int i;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
+        if (ctx->sw_format == supported_formats[i])
+            break;
+    }
+    if (i == FF_ARRAY_ELEMS(supported_formats)) {
+        av_log(ctx, AV_LOG_ERROR, "Pixel format '%s' is not supported\n",
+               av_get_pix_fmt_name(ctx->sw_format));
+        return AVERROR(ENOSYS);
+    }
+
+    av_pix_fmt_get_chroma_sub_sample(ctx->sw_format, &priv->shift_width, &priv->shift_height);
+
+    if (!ctx->pool) {
+        int size;
+
+        switch (ctx->sw_format) {
+        case AV_PIX_FMT_NV12:
+        case AV_PIX_FMT_YUV420P:
+            size = ctx->width * ctx->height * 3 / 2;
+            break;
+        case AV_PIX_FMT_YUV444P:
+            size = ctx->width * ctx->height * 3;
+            break;
+        }
+
+        ctx->internal->pool_internal = av_buffer_pool_init2(size, ctx, cuda_pool_alloc, NULL);
+        if (!ctx->internal->pool_internal)
+            return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
+static int cuda_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
+{
+    frame->buf[0] = av_buffer_pool_get(ctx->pool);
+    if (!frame->buf[0])
+        return AVERROR(ENOMEM);
+
+    switch (ctx->sw_format) {
+    case AV_PIX_FMT_NV12:
+        frame->data[0]     = frame->buf[0]->data;
+        frame->data[1]     = frame->data[0] + ctx->width * ctx->height;
+        frame->linesize[0] = ctx->width;
+        frame->linesize[1] = ctx->width;
+        break;
+    case AV_PIX_FMT_YUV420P:
+        frame->data[0]     = frame->buf[0]->data;
+        frame->data[2]     = frame->data[0] + ctx->width * ctx->height;
+        frame->data[1]     = frame->data[2] + ctx->width * ctx->height / 4;
+        frame->linesize[0] = ctx->width;
+        frame->linesize[1] = ctx->width / 2;
+        frame->linesize[2] = ctx->width / 2;
+        break;
+    case AV_PIX_FMT_YUV444P:
+        frame->data[0]     = frame->buf[0]->data;
+        frame->data[1]     = frame->data[0] + ctx->width * ctx->height;
+        frame->data[2]     = frame->data[1] + ctx->width * ctx->height;
+        frame->linesize[0] = ctx->width;
+        frame->linesize[1] = ctx->width;
+        frame->linesize[2] = ctx->width;
+        break;
+    default:
+        av_frame_unref(frame);
+        return AVERROR_BUG;
+    }
+
+    frame->format = AV_PIX_FMT_CUDA;
+    frame->width  = ctx->width;
+    frame->height = ctx->height;
+
+    return 0;
+}
+
+static int cuda_transfer_get_formats(AVHWFramesContext *ctx,
+                                     enum AVHWFrameTransferDirection dir,
+                                     enum AVPixelFormat **formats)
+{
+    enum AVPixelFormat *fmts;
+
+    fmts = av_malloc_array(2, sizeof(*fmts));
+    if (!fmts)
+        return AVERROR(ENOMEM);
+
+    fmts[0] = ctx->sw_format;
+    fmts[1] = AV_PIX_FMT_NONE;
+
+    *formats = fmts;
+
+    return 0;
+}
+
+static int cuda_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst,
+                                   const AVFrame *src)
+{
+    CUDAFramesContext           *priv = ctx->internal->priv;
+    AVCUDADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
+
+    CUcontext dummy;
+    CUresult err;
+    int i;
+
+    err = cuCtxPushCurrent(device_hwctx->cuda_ctx);
+    if (err != CUDA_SUCCESS)
+        return AVERROR_UNKNOWN;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) {
+        CUDA_MEMCPY2D cpy = {
+            .srcMemoryType = CU_MEMORYTYPE_DEVICE,
+            .dstMemoryType = CU_MEMORYTYPE_HOST,
+            .srcDevice     = (CUdeviceptr)src->data[i],
+            .dstHost       = dst->data[i],
+            .srcPitch      = src->linesize[i],
+            .dstPitch      = dst->linesize[i],
+            .WidthInBytes  = FFMIN(src->linesize[i], dst->linesize[i]),
+            .Height        = src->height >> (i ? priv->shift_height : 0),
+        };
+
+        err = cuMemcpy2D(&cpy);
+        if (err != CUDA_SUCCESS) {
+            av_log(ctx, AV_LOG_ERROR, "Error transferring the data from the CUDA frame\n");
+            return AVERROR_UNKNOWN;
+        }
+    }
+
+    cuCtxPopCurrent(&dummy);
+
+    return 0;
+}
+
+static int cuda_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
+                                 const AVFrame *src)
+{
+    CUDAFramesContext           *priv = ctx->internal->priv;
+    AVCUDADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
+
+    CUcontext dummy;
+    CUresult err;
+    int i;
+
+    err = cuCtxPushCurrent(device_hwctx->cuda_ctx);
+    if (err != CUDA_SUCCESS)
+        return AVERROR_UNKNOWN;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(src->data) && src->data[i]; i++) {
+        CUDA_MEMCPY2D cpy = {
+            .srcMemoryType = CU_MEMORYTYPE_HOST,
+            .dstMemoryType = CU_MEMORYTYPE_DEVICE,
+            .srcHost       = src->data[i],
+            .dstDevice     = (CUdeviceptr)dst->data[i],
+            .srcPitch      = src->linesize[i],
+            .dstPitch      = dst->linesize[i],
+            .WidthInBytes  = FFMIN(src->linesize[i], dst->linesize[i]),
+            .Height        = src->height >> (i ? priv->shift_height : 0),
+        };
+
+        err = cuMemcpy2D(&cpy);
+        if (err != CUDA_SUCCESS) {
+            av_log(ctx, AV_LOG_ERROR, "Error transferring the data from the CUDA frame\n");
+            return AVERROR_UNKNOWN;
+        }
+    }
+
+    cuCtxPopCurrent(&dummy);
+
+    return 0;
+}
+
+static void cuda_device_free(AVHWDeviceContext *ctx)
+{
+    AVCUDADeviceContext *hwctx = ctx->hwctx;
+    cuCtxDestroy(hwctx->cuda_ctx);
+}
+
+static int cuda_device_create(AVHWDeviceContext *ctx, const char *device,
+                              AVDictionary *opts, int flags)
+{
+    AVCUDADeviceContext *hwctx = ctx->hwctx;
+    CUdevice cu_device;
+    CUcontext dummy;
+    CUresult err;
+    int device_idx = 0;
+
+    if (device)
+        device_idx = strtol(device, NULL, 0);
+
+    err = cuInit(0);
+    if (err != CUDA_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Could not initialize the CUDA driver API\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    err = cuDeviceGet(&cu_device, device_idx);
+    if (err != CUDA_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Could not get the device number %d\n", device_idx);
+        return AVERROR_UNKNOWN;
+    }
+
+    err = cuCtxCreate(&hwctx->cuda_ctx, 0, cu_device);
+    if (err != CUDA_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Error creating a CUDA context\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    cuCtxPopCurrent(&dummy);
+
+    ctx->free = cuda_device_free;
+
+    return 0;
+}
+
+const HWContextType ff_hwcontext_type_cuda = {
+    .type                 = AV_HWDEVICE_TYPE_CUDA,
+    .name                 = "CUDA",
+
+    .device_hwctx_size    = sizeof(AVCUDADeviceContext),
+    .frames_priv_size     = sizeof(CUDAFramesContext),
+
+    .device_create        = cuda_device_create,
+    .frames_init          = cuda_frames_init,
+    .frames_get_buffer    = cuda_get_buffer,
+    .transfer_get_formats = cuda_transfer_get_formats,
+    .transfer_data_to     = cuda_transfer_data_to,
+    .transfer_data_from   = cuda_transfer_data_from,
+
+    .pix_fmts             = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE },
+};
diff --git a/libavutil/hwcontext_cuda.h b/libavutil/hwcontext_cuda.h
new file mode 100644
index 0000000..23a77ce
--- /dev/null
+++ b/libavutil/hwcontext_cuda.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef AVUTIL_HWCONTEXT_CUDA_H
+#define AVUTIL_HWCONTEXT_CUDA_H
+
+#include <cuda.h>
+
+#include "pixfmt.h"
+
+/**
+ * @file
+ * An API-specific header for AV_HWDEVICE_TYPE_CUDA.
+ *
+ * This API supports dynamic frame pools. AVHWFramesContext.pool must return
+ * AVBufferRefs whose data pointer is a CUdeviceptr.
+ */
+
+/**
+ * This struct is allocated as AVHWDeviceContext.hwctx
+ */
+typedef struct AVCUDADeviceContext {
+    CUcontext cuda_ctx;
+} AVCUDADeviceContext;
+
+/**
+ * AVHWFramesContext.hwctx is currently not used
+ */
+
+#endif /* AVUTIL_HWCONTEXT_CUDA_H */
diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c
new file mode 100644
index 0000000..e79254b
--- /dev/null
+++ b/libavutil/hwcontext_dxva2.c
@@ -0,0 +1,439 @@
+/*
+ * 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 <windows.h>
+
+#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#endif
+#define DXVA2API_USE_BITFIELDS
+#define COBJMACROS
+
+#include <d3d9.h>
+#include <dxva2api.h>
+#include <initguid.h>
+
+#include "avassert.h"
+#include "common.h"
+#include "hwcontext.h"
+#include "hwcontext_dxva2.h"
+#include "hwcontext_internal.h"
+#include "imgutils.h"
+#include "pixdesc.h"
+#include "pixfmt.h"
+
+typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT);
+typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **);
+
+typedef struct DXVA2FramesContext {
+    IDirect3DSurface9 **surfaces_internal;
+    int              nb_surfaces_used;
+
+    HANDLE  device_handle;
+    IDirectXVideoAccelerationService *service;
+
+    D3DFORMAT format;
+} DXVA2FramesContext;
+
+typedef struct DXVA2DevicePriv {
+    HMODULE d3dlib;
+    HMODULE dxva2lib;
+
+    HANDLE device_handle;
+
+    IDirect3D9       *d3d9;
+    IDirect3DDevice9 *d3d9device;
+} DXVA2DevicePriv;
+
+static const struct {
+    D3DFORMAT d3d_format;
+    enum AVPixelFormat pix_fmt;
+} supported_formats[] = {
+    { MKTAG('N', 'V', '1', '2'), AV_PIX_FMT_NV12 },
+    { MKTAG('P', '0', '1', '0'), AV_PIX_FMT_P010 },
+};
+
+DEFINE_GUID(video_decoder_service,   0xfc51a551, 0xd5e7, 0x11d9, 0xaf, 0x55, 0x00, 0x05, 0x4e, 0x43, 0xff, 0x02);
+DEFINE_GUID(video_processor_service, 0xfc51a552, 0xd5e7, 0x11d9, 0xaf, 0x55, 0x00, 0x05, 0x4e, 0x43, 0xff, 0x02);
+
+static void dxva2_frames_uninit(AVHWFramesContext *ctx)
+{
+    AVDXVA2DeviceContext *device_hwctx = ctx->device_ctx->hwctx;
+    AVDXVA2FramesContext *frames_hwctx = ctx->hwctx;
+    DXVA2FramesContext *s = ctx->internal->priv;
+    int i;
+
+    if (frames_hwctx->decoder_to_release)
+        IDirectXVideoDecoder_Release(frames_hwctx->decoder_to_release);
+
+    if (s->surfaces_internal) {
+        for (i = 0; i < frames_hwctx->nb_surfaces; i++) {
+            if (s->surfaces_internal[i])
+                IDirect3DSurface9_Release(s->surfaces_internal[i]);
+        }
+    }
+    av_freep(&s->surfaces_internal);
+
+    if (s->service) {
+        IDirectXVideoAccelerationService_Release(s->service);
+        s->service = NULL;
+    }
+
+    if (s->device_handle != INVALID_HANDLE_VALUE) {
+        IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, s->device_handle);
+        s->device_handle = INVALID_HANDLE_VALUE;
+    }
+}
+
+static AVBufferRef *dxva2_pool_alloc(void *opaque, int size)
+{
+    AVHWFramesContext      *ctx = (AVHWFramesContext*)opaque;
+    DXVA2FramesContext       *s = ctx->internal->priv;
+    AVDXVA2FramesContext *hwctx = ctx->hwctx;
+
+    if (s->nb_surfaces_used < hwctx->nb_surfaces) {
+        s->nb_surfaces_used++;
+        return av_buffer_create((uint8_t*)s->surfaces_internal[s->nb_surfaces_used - 1],
+                                sizeof(*hwctx->surfaces), NULL, 0, 0);
+    }
+
+    return NULL;
+}
+
+static int dxva2_init_pool(AVHWFramesContext *ctx)
+{
+    AVDXVA2FramesContext *frames_hwctx = ctx->hwctx;
+    AVDXVA2DeviceContext *device_hwctx = ctx->device_ctx->hwctx;
+    DXVA2FramesContext              *s = ctx->internal->priv;
+    int decode = (frames_hwctx->surface_type == DXVA2_VideoDecoderRenderTarget);
+
+    int i;
+    HRESULT hr;
+
+    if (ctx->initial_pool_size <= 0)
+        return 0;
+
+    hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, &s->device_handle);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr,
+                                                 s->device_handle,
+                                                 decode ? &video_decoder_service : &video_processor_service,
+                                                 (void **)&s->service);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create the video service\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
+        if (ctx->sw_format == supported_formats[i].pix_fmt) {
+            s->format = supported_formats[i].d3d_format;
+            break;
+        }
+    }
+    if (i == FF_ARRAY_ELEMS(supported_formats)) {
+        av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n",
+               av_get_pix_fmt_name(ctx->sw_format));
+        return AVERROR(EINVAL);
+    }
+
+    s->surfaces_internal = av_mallocz_array(ctx->initial_pool_size,
+                                            sizeof(*s->surfaces_internal));
+    if (!s->surfaces_internal)
+        return AVERROR(ENOMEM);
+
+    hr = IDirectXVideoAccelerationService_CreateSurface(s->service,
+                                                        ctx->width, ctx->height,
+                                                        ctx->initial_pool_size - 1,
+                                                        s->format, D3DPOOL_DEFAULT, 0,
+                                                        frames_hwctx->surface_type,
+                                                        s->surfaces_internal, NULL);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Could not create the surfaces\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(*s->surfaces_internal),
+                                                        ctx, dxva2_pool_alloc, NULL);
+    if (!ctx->internal->pool_internal)
+        return AVERROR(ENOMEM);
+
+    frames_hwctx->surfaces    = s->surfaces_internal;
+    frames_hwctx->nb_surfaces = ctx->initial_pool_size;
+
+    return 0;
+}
+
+static int dxva2_frames_init(AVHWFramesContext *ctx)
+{
+    AVDXVA2FramesContext *hwctx = ctx->hwctx;
+    DXVA2FramesContext       *s = ctx->internal->priv;
+    int ret;
+
+    if (hwctx->surface_type != DXVA2_VideoDecoderRenderTarget &&
+        hwctx->surface_type != DXVA2_VideoProcessorRenderTarget) {
+        av_log(ctx, AV_LOG_ERROR, "Unknown surface type: %lu\n",
+               hwctx->surface_type);
+        return AVERROR(EINVAL);
+    }
+
+    s->device_handle = INVALID_HANDLE_VALUE;
+
+    /* init the frame pool if the caller didn't provide one */
+    if (!ctx->pool) {
+        ret = dxva2_init_pool(ctx);
+        if (ret < 0) {
+            av_log(ctx, AV_LOG_ERROR, "Error creating an internal frame pool\n");
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
+static int dxva2_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
+{
+    frame->buf[0] = av_buffer_pool_get(ctx->pool);
+    if (!frame->buf[0])
+        return AVERROR(ENOMEM);
+
+    frame->data[3] = frame->buf[0]->data;
+    frame->format  = AV_PIX_FMT_DXVA2_VLD;
+    frame->width   = ctx->width;
+    frame->height  = ctx->height;
+
+    return 0;
+}
+
+static int dxva2_transfer_get_formats(AVHWFramesContext *ctx,
+                                      enum AVHWFrameTransferDirection dir,
+                                      enum AVPixelFormat **formats)
+{
+    enum AVPixelFormat *fmts;
+
+    fmts = av_malloc_array(2, sizeof(*fmts));
+    if (!fmts)
+        return AVERROR(ENOMEM);
+
+    fmts[0] = ctx->sw_format;
+    fmts[1] = AV_PIX_FMT_NONE;
+
+    *formats = fmts;
+
+    return 0;
+}
+
+static int dxva2_transfer_data(AVHWFramesContext *ctx, AVFrame *dst,
+                               const AVFrame *src)
+{
+    IDirect3DSurface9 *surface;
+    D3DSURFACE_DESC    surfaceDesc;
+    D3DLOCKED_RECT     LockedRect;
+    HRESULT            hr;
+
+    int download = !!src->hw_frames_ctx;
+    int bytes_per_component;
+
+    switch (ctx->sw_format) {
+        case AV_PIX_FMT_NV12:
+            bytes_per_component = 1;
+            break;
+        case AV_PIX_FMT_P010:
+            bytes_per_component = 2;
+            break;
+        default:
+            av_assert0(0);
+    }
+
+    surface = (IDirect3DSurface9*)(download ? src->data[3] : dst->data[3]);
+
+    hr = IDirect3DSurface9_GetDesc(surface, &surfaceDesc);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Error getting a surface description\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL,
+                                    download ? D3DLOCK_READONLY : D3DLOCK_DISCARD);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    if (download) {
+        av_image_copy_plane(dst->data[0], dst->linesize[0],
+                            (uint8_t*)LockedRect.pBits, LockedRect.Pitch,
+                            src->width * bytes_per_component, src->height);
+        av_image_copy_plane(dst->data[1], dst->linesize[1],
+                            (uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height,
+                            LockedRect.Pitch, src->width * bytes_per_component, src->height / 2);
+    } else {
+        av_image_copy_plane((uint8_t*)LockedRect.pBits, LockedRect.Pitch,
+                            dst->data[0], dst->linesize[0],
+                            src->width * bytes_per_component, src->height);
+        av_image_copy_plane((uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height,
+                            LockedRect.Pitch, dst->data[1], dst->linesize[1],
+                            src->width * bytes_per_component, src->height / 2);
+    }
+
+    IDirect3DSurface9_UnlockRect(surface);
+
+    return 0;
+}
+
+static void dxva2_device_free(AVHWDeviceContext *ctx)
+{
+    AVDXVA2DeviceContext *hwctx = ctx->hwctx;
+    DXVA2DevicePriv       *priv = ctx->user_opaque;
+
+    if (hwctx->devmgr && priv->device_handle != INVALID_HANDLE_VALUE)
+        IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, priv->device_handle);
+
+    if (hwctx->devmgr)
+        IDirect3DDeviceManager9_Release(hwctx->devmgr);
+
+    if (priv->d3d9device)
+        IDirect3DDevice9_Release(priv->d3d9device);
+
+    if (priv->d3d9)
+        IDirect3D9_Release(priv->d3d9);
+
+    if (priv->d3dlib)
+        FreeLibrary(priv->d3dlib);
+
+    if (priv->dxva2lib)
+        FreeLibrary(priv->dxva2lib);
+
+    av_freep(&ctx->user_opaque);
+}
+
+static int dxva2_device_create(AVHWDeviceContext *ctx, const char *device,
+                               AVDictionary *opts, int flags)
+{
+    AVDXVA2DeviceContext *hwctx = ctx->hwctx;
+    DXVA2DevicePriv *priv;
+
+    pDirect3DCreate9 *createD3D = NULL;
+    pCreateDeviceManager9 *createDeviceManager = NULL;
+    D3DPRESENT_PARAMETERS d3dpp = {0};
+    D3DDISPLAYMODE        d3ddm;
+    unsigned resetToken = 0;
+    UINT adapter = D3DADAPTER_DEFAULT;
+    HRESULT hr;
+
+    if (device)
+        adapter = atoi(device);
+
+    priv = av_mallocz(sizeof(*priv));
+    if (!priv)
+        return AVERROR(ENOMEM);
+
+    ctx->user_opaque = priv;
+    ctx->free        = dxva2_device_free;
+
+    priv->device_handle = INVALID_HANDLE_VALUE;
+
+    priv->d3dlib = LoadLibrary("d3d9.dll");
+    if (!priv->d3dlib) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to load D3D9 library\n");
+        return AVERROR_UNKNOWN;
+    }
+    priv->dxva2lib = LoadLibrary("dxva2.dll");
+    if (!priv->dxva2lib) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to load DXVA2 library\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    createD3D = (pDirect3DCreate9 *)GetProcAddress(priv->d3dlib, "Direct3DCreate9");
+    if (!createD3D) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to locate Direct3DCreate9\n");
+        return AVERROR_UNKNOWN;
+    }
+    createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(priv->dxva2lib,
+                                                                  "DXVA2CreateDirect3DDeviceManager9");
+    if (!createDeviceManager) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    priv->d3d9 = createD3D(D3D_SDK_VERSION);
+    if (!priv->d3d9) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create IDirect3D object\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    IDirect3D9_GetAdapterDisplayMode(priv->d3d9, adapter, &d3ddm);
+    d3dpp.Windowed         = TRUE;
+    d3dpp.BackBufferWidth  = 640;
+    d3dpp.BackBufferHeight = 480;
+    d3dpp.BackBufferCount  = 0;
+    d3dpp.BackBufferFormat = d3ddm.Format;
+    d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
+    d3dpp.Flags            = D3DPRESENTFLAG_VIDEO;
+
+    hr = IDirect3D9_CreateDevice(priv->d3d9, adapter, D3DDEVTYPE_HAL, GetDesktopWindow(),
+                                 D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
+                                 &d3dpp, &priv->d3d9device);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    hr = createDeviceManager(&resetToken, &hwctx->devmgr);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device manager\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    hr = IDirect3DDeviceManager9_ResetDevice(hwctx->devmgr, priv->d3d9device, resetToken);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to bind Direct3D device to device manager\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    hr = IDirect3DDeviceManager9_OpenDeviceHandle(hwctx->devmgr, &priv->device_handle);
+    if (FAILED(hr)) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to open device handle\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    return 0;
+}
+
+const HWContextType ff_hwcontext_type_dxva2 = {
+    .type                 = AV_HWDEVICE_TYPE_DXVA2,
+    .name                 = "DXVA2",
+
+    .device_hwctx_size    = sizeof(AVDXVA2DeviceContext),
+    .frames_hwctx_size    = sizeof(AVDXVA2FramesContext),
+    .frames_priv_size     = sizeof(DXVA2FramesContext),
+
+    .device_create        = dxva2_device_create,
+    .frames_init          = dxva2_frames_init,
+    .frames_uninit        = dxva2_frames_uninit,
+    .frames_get_buffer    = dxva2_get_buffer,
+    .transfer_get_formats = dxva2_transfer_get_formats,
+    .transfer_data_to     = dxva2_transfer_data,
+    .transfer_data_from   = dxva2_transfer_data,
+
+    .pix_fmts             = (const enum AVPixelFormat[]){ AV_PIX_FMT_DXVA2_VLD, AV_PIX_FMT_NONE },
+};
diff --git a/libavutil/hwcontext_dxva2.h b/libavutil/hwcontext_dxva2.h
new file mode 100644
index 0000000..6c36cb4
--- /dev/null
+++ b/libavutil/hwcontext_dxva2.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#ifndef AVUTIL_HWCONTEXT_DXVA2_H
+#define AVUTIL_HWCONTEXT_DXVA2_H
+
+/**
+ * @file
+ * An API-specific header for AV_HWDEVICE_TYPE_DXVA2.
+ *
+ * Only fixed-size pools are supported.
+ *
+ * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs
+ * with the data pointer set to a pointer to IDirect3DSurface9.
+ */
+
+#include <d3d9.h>
+#include <dxva2api.h>
+
+/**
+ * This struct is allocated as AVHWDeviceContext.hwctx
+ */
+typedef struct AVDXVA2DeviceContext {
+    IDirect3DDeviceManager9 *devmgr;
+} AVDXVA2DeviceContext;
+
+/**
+ * This struct is allocated as AVHWFramesContext.hwctx
+ */
+typedef struct AVDXVA2FramesContext {
+    /**
+     * The surface type (e.g. DXVA2_VideoProcessorRenderTarget or
+     * DXVA2_VideoDecoderRenderTarget). Must be set by the caller.
+     */
+    DWORD               surface_type;
+
+    /**
+     * The surface pool. When an external pool is not provided by the caller,
+     * this will be managed (allocated and filled on init, freed on uninit) by
+     * libavutil.
+     */
+    IDirect3DSurface9 **surfaces;
+    int              nb_surfaces;
+
+    /**
+     * Certain drivers require the decoder to be destroyed before the surfaces.
+     * To allow internally managed pools to work properly in such cases, this
+     * field is provided.
+     *
+     * If it is non-NULL, libavutil will call IDirectXVideoDecoder_Release() on
+     * it just before the internal surface pool is freed.
+     */
+    IDirectXVideoDecoder *decoder_to_release;
+} AVDXVA2FramesContext;
+
+#endif /* AVUTIL_HWCONTEXT_DXVA2_H */
diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h
new file mode 100644
index 0000000..cf832fe
--- /dev/null
+++ b/libavutil/hwcontext_internal.h
@@ -0,0 +1,107 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_HWCONTEXT_INTERNAL_H
+#define AVUTIL_HWCONTEXT_INTERNAL_H
+
+#include <stddef.h>
+
+#include "buffer.h"
+#include "hwcontext.h"
+#include "frame.h"
+#include "pixfmt.h"
+
+typedef struct HWContextType {
+    enum AVHWDeviceType type;
+    const char         *name;
+
+    /**
+     * An array of pixel formats supported by the AVHWFramesContext instances
+     * Terminated by AV_PIX_FMT_NONE.
+     */
+    const enum AVPixelFormat *pix_fmts;
+
+    /**
+     * size of the public hardware-specific context,
+     * i.e. AVHWDeviceContext.hwctx
+     */
+    size_t             device_hwctx_size;
+    /**
+     * size of the private data, i.e.
+     * AVHWDeviceInternal.priv
+     */
+    size_t             device_priv_size;
+
+    /**
+     * Size of the hardware-specific device configuration.
+     * (Used to query hwframe constraints.)
+     */
+    size_t             device_hwconfig_size;
+
+    /**
+     * size of the public frame pool hardware-specific context,
+     * i.e. AVHWFramesContext.hwctx
+     */
+    size_t             frames_hwctx_size;
+    /**
+     * size of the private data, i.e.
+     * AVHWFramesInternal.priv
+     */
+    size_t             frames_priv_size;
+
+    int              (*device_create)(AVHWDeviceContext *ctx, const char *device,
+                                      AVDictionary *opts, int flags);
+
+    int              (*device_init)(AVHWDeviceContext *ctx);
+    void             (*device_uninit)(AVHWDeviceContext *ctx);
+
+    int              (*frames_get_constraints)(AVHWDeviceContext *ctx,
+                                               const void *hwconfig,
+                                               AVHWFramesConstraints *constraints);
+
+    int              (*frames_init)(AVHWFramesContext *ctx);
+    void             (*frames_uninit)(AVHWFramesContext *ctx);
+
+    int              (*frames_get_buffer)(AVHWFramesContext *ctx, AVFrame *frame);
+    int              (*transfer_get_formats)(AVHWFramesContext *ctx,
+                                             enum AVHWFrameTransferDirection dir,
+                                             enum AVPixelFormat **formats);
+    int              (*transfer_data_to)(AVHWFramesContext *ctx, AVFrame *dst,
+                                         const AVFrame *src);
+    int              (*transfer_data_from)(AVHWFramesContext *ctx, AVFrame *dst,
+                                           const AVFrame *src);
+} HWContextType;
+
+struct AVHWDeviceInternal {
+    const HWContextType *hw_type;
+    void                *priv;
+};
+
+struct AVHWFramesInternal {
+    const HWContextType *hw_type;
+    void                *priv;
+
+    AVBufferPool *pool_internal;
+};
+
+extern const HWContextType ff_hwcontext_type_cuda;
+extern const HWContextType ff_hwcontext_type_dxva2;
+extern const HWContextType ff_hwcontext_type_vaapi;
+extern const HWContextType ff_hwcontext_type_vdpau;
+
+#endif /* AVUTIL_HWCONTEXT_INTERNAL_H */
diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c
new file mode 100644
index 0000000..3c1493b
--- /dev/null
+++ b/libavutil/hwcontext_vaapi.c
@@ -0,0 +1,973 @@
+/*
+ * 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 "config.h"
+
+#if HAVE_VAAPI_X11
+#   include <va/va_x11.h>
+#endif
+#if HAVE_VAAPI_DRM
+#   include <va/va_drm.h>
+#endif
+
+#include <fcntl.h>
+#if HAVE_UNISTD_H
+#   include <unistd.h>
+#endif
+
+
+#include "avassert.h"
+#include "buffer.h"
+#include "common.h"
+#include "hwcontext.h"
+#include "hwcontext_internal.h"
+#include "hwcontext_vaapi.h"
+#include "mem.h"
+#include "pixdesc.h"
+#include "pixfmt.h"
+
+typedef struct VAAPIDevicePriv {
+#if HAVE_VAAPI_X11
+    Display *x11_display;
+#endif
+
+    int drm_fd;
+} VAAPIDevicePriv;
+
+typedef struct VAAPISurfaceFormat {
+    enum AVPixelFormat pix_fmt;
+    VAImageFormat image_format;
+} VAAPISurfaceFormat;
+
+typedef struct VAAPIDeviceContext {
+    // Surface formats which can be used with this device.
+    VAAPISurfaceFormat *formats;
+    int              nb_formats;
+} VAAPIDeviceContext;
+
+typedef struct VAAPIFramesContext {
+    // Surface attributes set at create time.
+    VASurfaceAttrib *attributes;
+    int           nb_attributes;
+    // RT format of the underlying surface (Intel driver ignores this anyway).
+    unsigned int rt_format;
+    // Whether vaDeriveImage works.
+    int derive_works;
+} VAAPIFramesContext;
+
+enum {
+    VAAPI_MAP_READ   = 0x01,
+    VAAPI_MAP_WRITE  = 0x02,
+    VAAPI_MAP_DIRECT = 0x04,
+};
+
+typedef struct VAAPISurfaceMap {
+    // The source hardware frame of this mapping (with hw_frames_ctx set).
+    const AVFrame *source;
+    // VAAPI_MAP_* flags which apply to this mapping.
+    int flags;
+    // Handle to the derived or copied image which is mapped.
+    VAImage image;
+} VAAPISurfaceMap;
+
+#define MAP(va, rt, av) { \
+        VA_FOURCC_ ## va, \
+        VA_RT_FORMAT_ ## rt, \
+        AV_PIX_FMT_ ## av \
+    }
+// The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V
+// plane swap cases.  The frame handling below tries to hide these.
+static struct {
+    unsigned int fourcc;
+    unsigned int rt_format;
+    enum AVPixelFormat pix_fmt;
+} vaapi_format_map[] = {
+    MAP(NV12, YUV420,  NV12),
+    MAP(YV12, YUV420,  YUV420P), // With U/V planes swapped.
+    MAP(IYUV, YUV420,  YUV420P),
+  //MAP(I420, YUV420,  YUV420P), // Not in libva but used by Intel driver.
+#ifdef VA_FOURCC_YV16
+    MAP(YV16, YUV422,  YUV422P), // With U/V planes swapped.
+#endif
+    MAP(422H, YUV422,  YUV422P),
+    MAP(UYVY, YUV422,  UYVY422),
+    MAP(YUY2, YUV422,  YUYV422),
+    MAP(Y800, YUV400,  GRAY8),
+#ifdef VA_FOURCC_P010
+    MAP(P010, YUV420_10BPP, P010),
+#endif
+    MAP(BGRA, RGB32,   BGRA),
+    MAP(BGRX, RGB32,   BGR0),
+    MAP(RGBA, RGB32,   RGBA),
+    MAP(RGBX, RGB32,   RGB0),
+    MAP(ABGR, RGB32,   ABGR),
+    MAP(XBGR, RGB32,   0BGR),
+    MAP(ARGB, RGB32,   ARGB),
+    MAP(XRGB, RGB32,   0RGB),
+};
+#undef MAP
+
+static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
+{
+    int i;
+    for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
+        if (vaapi_format_map[i].fourcc == fourcc)
+            return vaapi_format_map[i].pix_fmt;
+    return AV_PIX_FMT_NONE;
+}
+
+static int vaapi_get_image_format(AVHWDeviceContext *hwdev,
+                                  enum AVPixelFormat pix_fmt,
+                                  VAImageFormat **image_format)
+{
+    VAAPIDeviceContext *ctx = hwdev->internal->priv;
+    int i;
+
+    for (i = 0; i < ctx->nb_formats; i++) {
+        if (ctx->formats[i].pix_fmt == pix_fmt) {
+            *image_format = &ctx->formats[i].image_format;
+            return 0;
+        }
+    }
+    return AVERROR(EINVAL);
+}
+
+static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev,
+                                        const void *hwconfig,
+                                        AVHWFramesConstraints *constraints)
+{
+    AVVAAPIDeviceContext *hwctx = hwdev->hwctx;
+    const AVVAAPIHWConfig *config = hwconfig;
+    AVVAAPIHWConfig *tmp_config;
+    VASurfaceAttrib *attr_list = NULL;
+    VAStatus vas;
+    enum AVPixelFormat pix_fmt;
+    unsigned int fourcc;
+    int err, i, j, attr_count, pix_fmt_count;
+
+    if (!hwconfig) {
+        // No configuration was provided, so we create a temporary pipeline
+        // configuration in order to query all supported image formats.
+
+        tmp_config = av_mallocz(sizeof(*config));
+        if (!tmp_config)
+            return AVERROR(ENOMEM);
+
+        vas = vaCreateConfig(hwctx->display,
+                             VAProfileNone, VAEntrypointVideoProc,
+                             NULL, 0, &tmp_config->config_id);
+        if (vas != VA_STATUS_SUCCESS) {
+            // No vpp.  We might still be able to do something useful if
+            // codecs are supported, so try to make the most-commonly
+            // supported decoder configuration we can to query instead.
+            vas = vaCreateConfig(hwctx->display,
+                                 VAProfileH264ConstrainedBaseline,
+                                 VAEntrypointVLD, NULL, 0,
+                                 &tmp_config->config_id);
+            if (vas != VA_STATUS_SUCCESS) {
+                av_freep(&tmp_config);
+                return AVERROR(ENOSYS);
+            }
+        }
+
+        config = tmp_config;
+    }
+
+    attr_count = 0;
+    vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
+                                   0, &attr_count);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(ENOSYS);
+        goto fail;
+    }
+
+    attr_list = av_malloc(attr_count * sizeof(*attr_list));
+    if (!attr_list) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
+                                   attr_list, &attr_count);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        err = AVERROR(ENOSYS);
+        goto fail;
+    }
+
+    pix_fmt_count = 0;
+    for (i = 0; i < attr_count; i++) {
+        switch (attr_list[i].type) {
+        case VASurfaceAttribPixelFormat:
+            fourcc = attr_list[i].value.value.i;
+            pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
+            if (pix_fmt != AV_PIX_FMT_NONE) {
+                ++pix_fmt_count;
+            } else {
+                // Something unsupported - ignore.
+            }
+            break;
+        case VASurfaceAttribMinWidth:
+            constraints->min_width  = attr_list[i].value.value.i;
+            break;
+        case VASurfaceAttribMinHeight:
+            constraints->min_height = attr_list[i].value.value.i;
+            break;
+        case VASurfaceAttribMaxWidth:
+            constraints->max_width  = attr_list[i].value.value.i;
+            break;
+        case VASurfaceAttribMaxHeight:
+            constraints->max_height = attr_list[i].value.value.i;
+            break;
+        }
+    }
+    if (pix_fmt_count == 0) {
+        // Nothing usable found.  Presumably there exists something which
+        // works, so leave the set null to indicate unknown.
+        constraints->valid_sw_formats = NULL;
+    } else {
+        constraints->valid_sw_formats = av_malloc_array(pix_fmt_count + 1,
+                                                        sizeof(pix_fmt));
+        if (!constraints->valid_sw_formats) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+        for (i = j = 0; i < attr_count; i++) {
+            if (attr_list[i].type != VASurfaceAttribPixelFormat)
+                continue;
+            fourcc = attr_list[i].value.value.i;
+            pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
+            if (pix_fmt != AV_PIX_FMT_NONE)
+                constraints->valid_sw_formats[j++] = pix_fmt;
+        }
+        av_assert0(j == pix_fmt_count);
+        constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE;
+    }
+
+    constraints->valid_hw_formats = av_malloc_array(2, sizeof(pix_fmt));
+    if (!constraints->valid_hw_formats) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    constraints->valid_hw_formats[0] = AV_PIX_FMT_VAAPI;
+    constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
+
+    err = 0;
+fail:
+    av_freep(&attr_list);
+    if (!hwconfig) {
+        vaDestroyConfig(hwctx->display, tmp_config->config_id);
+        av_freep(&tmp_config);
+    }
+    return err;
+}
+
+static int vaapi_device_init(AVHWDeviceContext *hwdev)
+{
+    VAAPIDeviceContext *ctx = hwdev->internal->priv;
+    AVVAAPIDeviceContext *hwctx = hwdev->hwctx;
+    AVHWFramesConstraints *constraints = NULL;
+    VAImageFormat *image_list = NULL;
+    VAStatus vas;
+    int err, i, j, image_count;
+    enum AVPixelFormat pix_fmt;
+    unsigned int fourcc;
+
+    constraints = av_mallocz(sizeof(*constraints));
+    if (!constraints)
+        goto fail;
+
+    err = vaapi_frames_get_constraints(hwdev, NULL, constraints);
+    if (err < 0)
+        goto fail;
+
+    image_count = vaMaxNumImageFormats(hwctx->display);
+    if (image_count <= 0) {
+        err = AVERROR(EIO);
+        goto fail;
+    }
+    image_list = av_malloc(image_count * sizeof(*image_list));
+    if (!image_list) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    vas = vaQueryImageFormats(hwctx->display, image_list, &image_count);
+    if (vas != VA_STATUS_SUCCESS) {
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    ctx->formats  = av_malloc(image_count * sizeof(*ctx->formats));
+    if (!ctx->formats) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+    ctx->nb_formats = 0;
+    for (i = 0; i < image_count; i++) {
+        fourcc  = image_list[i].fourcc;
+        pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
+        for (j = 0; constraints->valid_sw_formats[j] != AV_PIX_FMT_NONE; j++) {
+            if (pix_fmt == constraints->valid_sw_formats[j])
+                break;
+        }
+        if (constraints->valid_sw_formats[j] != AV_PIX_FMT_NONE) {
+            av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> %s.\n",
+                   fourcc, av_get_pix_fmt_name(pix_fmt));
+            ctx->formats[ctx->nb_formats].pix_fmt      = pix_fmt;
+            ctx->formats[ctx->nb_formats].image_format = image_list[i];
+            ++ctx->nb_formats;
+        } else {
+            av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> unknown.\n", fourcc);
+        }
+    }
+
+    av_free(image_list);
+    av_hwframe_constraints_free(&constraints);
+    return 0;
+fail:
+    av_freep(&ctx->formats);
+    av_free(image_list);
+    av_hwframe_constraints_free(&constraints);
+    return err;
+}
+
+static void vaapi_device_uninit(AVHWDeviceContext *hwdev)
+{
+    VAAPIDeviceContext *ctx = hwdev->internal->priv;
+
+    av_freep(&ctx->formats);
+}
+
+static void vaapi_buffer_free(void *opaque, uint8_t *data)
+{
+    AVHWFramesContext     *hwfc = opaque;
+    AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
+    VASurfaceID surface_id;
+    VAStatus vas;
+
+    surface_id = (VASurfaceID)(uintptr_t)data;
+
+    vas = vaDestroySurfaces(hwctx->display, &surface_id, 1);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(hwfc, AV_LOG_ERROR, "Failed to destroy surface %#x: "
+               "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
+    }
+}
+
+static AVBufferRef *vaapi_pool_alloc(void *opaque, int size)
+{
+    AVHWFramesContext     *hwfc = opaque;
+    VAAPIFramesContext     *ctx = hwfc->internal->priv;
+    AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
+    AVVAAPIFramesContext  *avfc = hwfc->hwctx;
+    VASurfaceID surface_id;
+    VAStatus vas;
+    AVBufferRef *ref;
+
+    vas = vaCreateSurfaces(hwctx->display, ctx->rt_format,
+                           hwfc->width, hwfc->height,
+                           &surface_id, 1,
+                           ctx->attributes, ctx->nb_attributes);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(hwfc, AV_LOG_ERROR, "Failed to create surface: "
+               "%d (%s).\n", vas, vaErrorStr(vas));
+        return NULL;
+    }
+    av_log(hwfc, AV_LOG_DEBUG, "Created surface %#x.\n", surface_id);
+
+    ref = av_buffer_create((uint8_t*)(uintptr_t)surface_id,
+                           sizeof(surface_id), &vaapi_buffer_free,
+                           hwfc, AV_BUFFER_FLAG_READONLY);
+    if (!ref) {
+        vaDestroySurfaces(hwctx->display, &surface_id, 1);
+        return NULL;
+    }
+
+    if (hwfc->initial_pool_size > 0) {
+        // This is a fixed-size pool, so we must still be in the initial
+        // allocation sequence.
+        av_assert0(avfc->nb_surfaces < hwfc->initial_pool_size);
+        avfc->surface_ids[avfc->nb_surfaces] = surface_id;
+        ++avfc->nb_surfaces;
+    }
+
+    return ref;
+}
+
+static int vaapi_frames_init(AVHWFramesContext *hwfc)
+{
+    AVVAAPIFramesContext  *avfc = hwfc->hwctx;
+    VAAPIFramesContext     *ctx = hwfc->internal->priv;
+    AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
+    VAImageFormat *expected_format;
+    AVBufferRef *test_surface = NULL;
+    VASurfaceID test_surface_id;
+    VAImage test_image;
+    VAStatus vas;
+    int err, i;
+    unsigned int fourcc, rt_format;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) {
+        if (vaapi_format_map[i].pix_fmt == hwfc->sw_format) {
+            fourcc    = vaapi_format_map[i].fourcc;
+            rt_format = vaapi_format_map[i].rt_format;
+            break;
+        }
+    }
+    if (i >= FF_ARRAY_ELEMS(vaapi_format_map)) {
+        av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n",
+               av_get_pix_fmt_name(hwfc->sw_format));
+        return AVERROR(EINVAL);
+    }
+
+    if (!hwfc->pool) {
+        int need_memory_type = 1, need_pixel_format = 1;
+        for (i = 0; i < avfc->nb_attributes; i++) {
+            if (ctx->attributes[i].type == VASurfaceAttribMemoryType)
+                need_memory_type  = 0;
+            if (ctx->attributes[i].type == VASurfaceAttribPixelFormat)
+                need_pixel_format = 0;
+        }
+        ctx->nb_attributes =
+            avfc->nb_attributes + need_memory_type + need_pixel_format;
+
+        ctx->attributes = av_malloc(ctx->nb_attributes *
+                                        sizeof(*ctx->attributes));
+        if (!ctx->attributes) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+        for (i = 0; i < avfc->nb_attributes; i++)
+            ctx->attributes[i] = avfc->attributes[i];
+        if (need_memory_type) {
+            ctx->attributes[i++] = (VASurfaceAttrib) {
+                .type          = VASurfaceAttribMemoryType,
+                .flags         = VA_SURFACE_ATTRIB_SETTABLE,
+                .value.type    = VAGenericValueTypeInteger,
+                .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA,
+            };
+        }
+        if (need_pixel_format) {
+            ctx->attributes[i++] = (VASurfaceAttrib) {
+                .type          = VASurfaceAttribPixelFormat,
+                .flags         = VA_SURFACE_ATTRIB_SETTABLE,
+                .value.type    = VAGenericValueTypeInteger,
+                .value.value.i = fourcc,
+            };
+        }
+        av_assert0(i == ctx->nb_attributes);
+
+        ctx->rt_format = rt_format;
+
+        if (hwfc->initial_pool_size > 0) {
+            // This pool will be usable as a render target, so we need to store
+            // all of the surface IDs somewhere that vaCreateContext() calls
+            // will be able to access them.
+            avfc->nb_surfaces = 0;
+            avfc->surface_ids = av_malloc(hwfc->initial_pool_size *
+                                          sizeof(*avfc->surface_ids));
+            if (!avfc->surface_ids) {
+                err = AVERROR(ENOMEM);
+                goto fail;
+            }
+        } else {
+            // This pool allows dynamic sizing, and will not be usable as a
+            // render target.
+            avfc->nb_surfaces = 0;
+            avfc->surface_ids = NULL;
+        }
+
+        hwfc->internal->pool_internal =
+            av_buffer_pool_init2(sizeof(VASurfaceID), hwfc,
+                                 &vaapi_pool_alloc, NULL);
+        if (!hwfc->internal->pool_internal) {
+            av_log(hwfc, AV_LOG_ERROR, "Failed to create VAAPI surface pool.\n");
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+
+    // Allocate a single surface to test whether vaDeriveImage() is going
+    // to work for the specific configuration.
+    if (hwfc->pool) {
+        test_surface = av_buffer_pool_get(hwfc->pool);
+        if (!test_surface) {
+            av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from "
+                   "user-configured buffer pool.\n");
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+    } else {
+        test_surface = av_buffer_pool_get(hwfc->internal->pool_internal);
+        if (!test_surface) {
+            av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from "
+                   "internal buffer pool.\n");
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+    }
+    test_surface_id = (VASurfaceID)(uintptr_t)test_surface->data;
+
+    ctx->derive_works = 0;
+
+    err = vaapi_get_image_format(hwfc->device_ctx,
+                                 hwfc->sw_format, &expected_format);
+    if (err == 0) {
+        vas = vaDeriveImage(hwctx->display, test_surface_id, &test_image);
+        if (vas == VA_STATUS_SUCCESS) {
+            if (expected_format->fourcc == test_image.format.fourcc) {
+                av_log(hwfc, AV_LOG_DEBUG, "Direct mapping possible.\n");
+                ctx->derive_works = 1;
+            } else {
+                av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
+                       "derived image format %08x does not match "
+                       "expected format %08x.\n",
+                       expected_format->fourcc, test_image.format.fourcc);
+            }
+            vaDestroyImage(hwctx->display, test_image.image_id);
+        } else {
+            av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
+                   "deriving image does not work: "
+                   "%d (%s).\n", vas, vaErrorStr(vas));
+        }
+    } else {
+        av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
+               "image format is not supported.\n");
+    }
+
+    av_buffer_unref(&test_surface);
+    return 0;
+
+fail:
+    av_buffer_unref(&test_surface);
+    av_freep(&avfc->surface_ids);
+    av_freep(&ctx->attributes);
+    return err;
+}
+
+static void vaapi_frames_uninit(AVHWFramesContext *hwfc)
+{
+    AVVAAPIFramesContext *avfc = hwfc->hwctx;
+    VAAPIFramesContext    *ctx = hwfc->internal->priv;
+
+    av_freep(&avfc->surface_ids);
+    av_freep(&ctx->attributes);
+}
+
+static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
+{
+    frame->buf[0] = av_buffer_pool_get(hwfc->pool);
+    if (!frame->buf[0])
+        return AVERROR(ENOMEM);
+
+    frame->data[3] = frame->buf[0]->data;
+    frame->format  = AV_PIX_FMT_VAAPI;
+    frame->width   = hwfc->width;
+    frame->height  = hwfc->height;
+
+    return 0;
+}
+
+static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc,
+                                      enum AVHWFrameTransferDirection dir,
+                                      enum AVPixelFormat **formats)
+{
+    VAAPIDeviceContext *ctx = hwfc->device_ctx->internal->priv;
+    enum AVPixelFormat *pix_fmts, preferred_format;
+    int i, k;
+
+    preferred_format = hwfc->sw_format;
+
+    pix_fmts = av_malloc((ctx->nb_formats + 1) * sizeof(*pix_fmts));
+    if (!pix_fmts)
+        return AVERROR(ENOMEM);
+
+    pix_fmts[0] = preferred_format;
+    k = 1;
+    for (i = 0; i < ctx->nb_formats; i++) {
+        if (ctx->formats[i].pix_fmt == preferred_format)
+            continue;
+        av_assert0(k < ctx->nb_formats);
+        pix_fmts[k++] = ctx->formats[i].pix_fmt;
+    }
+    av_assert0(k == ctx->nb_formats);
+    pix_fmts[k] = AV_PIX_FMT_NONE;
+
+    *formats = pix_fmts;
+    return 0;
+}
+
+static void vaapi_unmap_frame(void *opaque, uint8_t *data)
+{
+    AVHWFramesContext *hwfc = opaque;
+    AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
+    VAAPISurfaceMap *map = (VAAPISurfaceMap*)data;
+    const AVFrame *src;
+    VASurfaceID surface_id;
+    VAStatus vas;
+
+    src = map->source;
+    surface_id = (VASurfaceID)(uintptr_t)src->data[3];
+    av_log(hwfc, AV_LOG_DEBUG, "Unmap surface %#x.\n", surface_id);
+
+    vas = vaUnmapBuffer(hwctx->display, map->image.buf);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(hwfc, AV_LOG_ERROR, "Failed to unmap image from surface "
+               "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
+    }
+
+    if ((map->flags & VAAPI_MAP_WRITE) &&
+        !(map->flags & VAAPI_MAP_DIRECT)) {
+        vas = vaPutImage(hwctx->display, surface_id, map->image.image_id,
+                         0, 0, hwfc->width, hwfc->height,
+                         0, 0, hwfc->width, hwfc->height);
+        if (vas != VA_STATUS_SUCCESS) {
+            av_log(hwfc, AV_LOG_ERROR, "Failed to write image to surface "
+                   "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
+        }
+    }
+
+    vas = vaDestroyImage(hwctx->display, map->image.image_id);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image from surface "
+               "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
+    }
+
+    av_free(map);
+}
+
+static int vaapi_map_frame(AVHWFramesContext *hwfc,
+                           AVFrame *dst, const AVFrame *src, int flags)
+{
+    AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
+    VAAPIFramesContext *ctx = hwfc->internal->priv;
+    VASurfaceID surface_id;
+    VAImageFormat *image_format;
+    VAAPISurfaceMap *map;
+    VAStatus vas;
+    void *address = NULL;
+    int err, i;
+
+    surface_id = (VASurfaceID)(uintptr_t)src->data[3];
+    av_log(hwfc, AV_LOG_DEBUG, "Map surface %#x.\n", surface_id);
+
+    if (!ctx->derive_works && (flags & VAAPI_MAP_DIRECT)) {
+        // Requested direct mapping but it is not possible.
+        return AVERROR(EINVAL);
+    }
+    if (dst->format == AV_PIX_FMT_NONE)
+        dst->format = hwfc->sw_format;
+    if (dst->format != hwfc->sw_format && (flags & VAAPI_MAP_DIRECT)) {
+        // Requested direct mapping but the formats do not match.
+        return AVERROR(EINVAL);
+    }
+
+    err = vaapi_get_image_format(hwfc->device_ctx, dst->format, &image_format);
+    if (err < 0) {
+        // Requested format is not a valid output format.
+        return AVERROR(EINVAL);
+    }
+
+    map = av_malloc(sizeof(VAAPISurfaceMap));
+    if (!map)
+        return AVERROR(ENOMEM);
+
+    map->source         = src;
+    map->flags          = flags;
+    map->image.image_id = VA_INVALID_ID;
+
+    vas = vaSyncSurface(hwctx->display, surface_id);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface "
+               "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    // The memory which we map using derive need not be connected to the CPU
+    // in a way conducive to fast access.  On Gen7-Gen9 Intel graphics, the
+    // memory is mappable but not cached, so normal memcpy()-like access is
+    // very slow to read it (but writing is ok).  It is possible to read much
+    // faster with a copy routine which is aware of the limitation, but we
+    // assume for now that the user is not aware of that and would therefore
+    // prefer not to be given direct-mapped memory if they request read access.
+    if (ctx->derive_works &&
+        ((flags & VAAPI_MAP_DIRECT) || !(flags & VAAPI_MAP_READ))) {
+        vas = vaDeriveImage(hwctx->display, surface_id, &map->image);
+        if (vas != VA_STATUS_SUCCESS) {
+            av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
+                   "surface %#x: %d (%s).\n",
+                   surface_id, vas, vaErrorStr(vas));
+            err = AVERROR(EIO);
+            goto fail;
+        }
+        if (map->image.format.fourcc != image_format->fourcc) {
+            av_log(hwfc, AV_LOG_ERROR, "Derive image of surface %#x "
+                   "is in wrong format: expected %#08x, got %#08x.\n",
+                   surface_id, image_format->fourcc, map->image.format.fourcc);
+            err = AVERROR(EIO);
+            goto fail;
+        }
+        map->flags |= VAAPI_MAP_DIRECT;
+    } else {
+        vas = vaCreateImage(hwctx->display, image_format,
+                            hwfc->width, hwfc->height, &map->image);
+        if (vas != VA_STATUS_SUCCESS) {
+            av_log(hwfc, AV_LOG_ERROR, "Failed to create image for "
+                   "surface %#x: %d (%s).\n",
+                   surface_id, vas, vaErrorStr(vas));
+            err = AVERROR(EIO);
+            goto fail;
+        }
+        if (flags & VAAPI_MAP_READ) {
+            vas = vaGetImage(hwctx->display, surface_id, 0, 0,
+                             hwfc->width, hwfc->height, map->image.image_id);
+            if (vas != VA_STATUS_SUCCESS) {
+                av_log(hwfc, AV_LOG_ERROR, "Failed to read image from "
+                       "surface %#x: %d (%s).\n",
+                       surface_id, vas, vaErrorStr(vas));
+                err = AVERROR(EIO);
+                goto fail;
+            }
+        }
+    }
+
+    vas = vaMapBuffer(hwctx->display, map->image.buf, &address);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface "
+               "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
+        err = AVERROR(EIO);
+        goto fail;
+    }
+
+    dst->width  = src->width;
+    dst->height = src->height;
+
+    for (i = 0; i < map->image.num_planes; i++) {
+        dst->data[i] = (uint8_t*)address + map->image.offsets[i];
+        dst->linesize[i] = map->image.pitches[i];
+    }
+    if (
+#ifdef VA_FOURCC_YV16
+        map->image.format.fourcc == VA_FOURCC_YV16 ||
+#endif
+        map->image.format.fourcc == VA_FOURCC_YV12) {
+        // Chroma planes are YVU rather than YUV, so swap them.
+        FFSWAP(uint8_t*, dst->data[1], dst->data[2]);
+    }
+
+    dst->buf[0] = av_buffer_create((uint8_t*)map, sizeof(*map),
+                                   &vaapi_unmap_frame, hwfc, 0);
+    if (!dst->buf[0]) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    return 0;
+
+fail:
+    if (map) {
+        if (address)
+            vaUnmapBuffer(hwctx->display, map->image.buf);
+        if (map->image.image_id != VA_INVALID_ID)
+            vaDestroyImage(hwctx->display, map->image.image_id);
+        av_free(map);
+    }
+    return err;
+}
+
+static int vaapi_transfer_data_from(AVHWFramesContext *hwfc,
+                                    AVFrame *dst, const AVFrame *src)
+{
+    AVFrame *map;
+    int err;
+
+    map = av_frame_alloc();
+    if (!map)
+        return AVERROR(ENOMEM);
+    map->format = dst->format;
+
+    err = vaapi_map_frame(hwfc, map, src, VAAPI_MAP_READ);
+    if (err)
+        goto fail;
+
+    err = av_frame_copy(dst, map);
+    if (err)
+        goto fail;
+
+    err = 0;
+fail:
+    av_frame_free(&map);
+    return err;
+}
+
+static int vaapi_transfer_data_to(AVHWFramesContext *hwfc,
+                                  AVFrame *dst, const AVFrame *src)
+{
+    AVFrame *map;
+    int err;
+
+    map = av_frame_alloc();
+    if (!map)
+        return AVERROR(ENOMEM);
+    map->format = src->format;
+
+    err = vaapi_map_frame(hwfc, map, dst, VAAPI_MAP_WRITE);
+    if (err)
+        goto fail;
+
+    err = av_frame_copy(map, src);
+    if (err)
+        goto fail;
+
+    err = 0;
+fail:
+    av_frame_free(&map);
+    return err;
+}
+
+static void vaapi_device_free(AVHWDeviceContext *ctx)
+{
+    AVVAAPIDeviceContext *hwctx = ctx->hwctx;
+    VAAPIDevicePriv      *priv  = ctx->user_opaque;
+
+    if (hwctx->display)
+        vaTerminate(hwctx->display);
+
+#if HAVE_VAAPI_X11
+    if (priv->x11_display)
+        XCloseDisplay(priv->x11_display);
+#endif
+
+    if (priv->drm_fd >= 0)
+        close(priv->drm_fd);
+
+    av_freep(&priv);
+}
+
+static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
+                               AVDictionary *opts, int flags)
+{
+    AVVAAPIDeviceContext *hwctx = ctx->hwctx;
+    VAAPIDevicePriv *priv;
+    VADisplay display = 0;
+    VAStatus vas;
+    int major, minor;
+
+    priv = av_mallocz(sizeof(*priv));
+    if (!priv)
+        return AVERROR(ENOMEM);
+
+    priv->drm_fd = -1;
+
+    ctx->user_opaque = priv;
+    ctx->free        = vaapi_device_free;
+
+#if HAVE_VAAPI_X11
+    if (!display && !(device && device[0] == '/')) {
+        // Try to open the device as an X11 display.
+        priv->x11_display = XOpenDisplay(device);
+        if (!priv->x11_display) {
+            av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
+                   "%s.\n", XDisplayName(device));
+        } else {
+            display = vaGetDisplay(priv->x11_display);
+            if (!display) {
+                av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
+                       "from X11 display %s.\n", XDisplayName(device));
+                return AVERROR_UNKNOWN;
+            }
+
+            av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
+                   "X11 display %s.\n", XDisplayName(device));
+        }
+    }
+#endif
+
+#if HAVE_VAAPI_DRM
+    if (!display && device) {
+        // Try to open the device as a DRM path.
+        priv->drm_fd = open(device, O_RDWR);
+        if (priv->drm_fd < 0) {
+            av_log(ctx, AV_LOG_VERBOSE, "Cannot open DRM device %s.\n",
+                   device);
+        } else {
+            display = vaGetDisplayDRM(priv->drm_fd);
+            if (!display) {
+                av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
+                       "from DRM device %s.\n", device);
+                return AVERROR_UNKNOWN;
+            }
+
+            av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
+                   "DRM device %s.\n", device);
+        }
+    }
+#endif
+
+    if (!display) {
+        av_log(ctx, AV_LOG_ERROR, "No VA display found for "
+               "device: %s.\n", device ? device : "");
+        return AVERROR(EINVAL);
+    }
+
+    hwctx->display = display;
+
+    vas = vaInitialize(display, &major, &minor);
+    if (vas != VA_STATUS_SUCCESS) {
+        av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI "
+               "connection: %d (%s).\n", vas, vaErrorStr(vas));
+        return AVERROR(EIO);
+    }
+    av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: "
+           "version %d.%d\n", major, minor);
+
+    return 0;
+}
+
+const HWContextType ff_hwcontext_type_vaapi = {
+    .type                   = AV_HWDEVICE_TYPE_VAAPI,
+    .name                   = "VAAPI",
+
+    .device_hwctx_size      = sizeof(AVVAAPIDeviceContext),
+    .device_priv_size       = sizeof(VAAPIDeviceContext),
+    .device_hwconfig_size   = sizeof(AVVAAPIHWConfig),
+    .frames_hwctx_size      = sizeof(AVVAAPIFramesContext),
+    .frames_priv_size       = sizeof(VAAPIFramesContext),
+
+    .device_create          = &vaapi_device_create,
+    .device_init            = &vaapi_device_init,
+    .device_uninit          = &vaapi_device_uninit,
+    .frames_get_constraints = &vaapi_frames_get_constraints,
+    .frames_init            = &vaapi_frames_init,
+    .frames_uninit          = &vaapi_frames_uninit,
+    .frames_get_buffer      = &vaapi_get_buffer,
+    .transfer_get_formats   = &vaapi_transfer_get_formats,
+    .transfer_data_to       = &vaapi_transfer_data_to,
+    .transfer_data_from     = &vaapi_transfer_data_from,
+
+    .pix_fmts = (const enum AVPixelFormat[]) {
+        AV_PIX_FMT_VAAPI,
+        AV_PIX_FMT_NONE
+    },
+};
diff --git a/libavutil/hwcontext_vaapi.h b/libavutil/hwcontext_vaapi.h
new file mode 100644
index 0000000..7fd1a36
--- /dev/null
+++ b/libavutil/hwcontext_vaapi.h
@@ -0,0 +1,82 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_HWCONTEXT_VAAPI_H
+#define AVUTIL_HWCONTEXT_VAAPI_H
+
+#include <va/va.h>
+
+/**
+ * @file
+ * API-specific header for AV_HWDEVICE_TYPE_VAAPI.
+ *
+ * Dynamic frame pools are supported, but note that any pool used as a render
+ * target is required to be of fixed size in order to be be usable as an
+ * argument to vaCreateContext().
+ *
+ * For user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs
+ * with the data pointer set to a VASurfaceID.
+ */
+
+/**
+ * VAAPI connection details.
+ *
+ * Allocated as AVHWDeviceContext.hwctx
+ */
+typedef struct AVVAAPIDeviceContext {
+    /**
+     * The VADisplay handle, to be filled by the user.
+     */
+    VADisplay display;
+} AVVAAPIDeviceContext;
+
+/**
+ * VAAPI-specific data associated with a frame pool.
+ *
+ * Allocated as AVHWFramesContext.hwctx.
+ */
+typedef struct AVVAAPIFramesContext {
+    /**
+     * Set by the user to apply surface attributes to all surfaces in
+     * the frame pool.  If null, default settings are used.
+     */
+    VASurfaceAttrib *attributes;
+    int           nb_attributes;
+    /**
+     * The surfaces IDs of all surfaces in the pool after creation.
+     * Only valid if AVHWFramesContext.initial_pool_size was positive.
+     * These are intended to be used as the render_targets arguments to
+     * vaCreateContext().
+     */
+    VASurfaceID     *surface_ids;
+    int           nb_surfaces;
+} AVVAAPIFramesContext;
+
+/**
+ * VAAPI hardware pipeline configuration details.
+ *
+ * Allocated with av_hwdevice_hwconfig_alloc().
+ */
+typedef struct AVVAAPIHWConfig {
+    /**
+     * ID of a VAAPI pipeline configuration.
+     */
+    VAConfigID config_id;
+} AVVAAPIHWConfig;
+
+#endif /* AVUTIL_HWCONTEXT_VAAPI_H */
diff --git a/libavutil/hwcontext_vdpau.c b/libavutil/hwcontext_vdpau.c
new file mode 100644
index 0000000..2b0fad3
--- /dev/null
+++ b/libavutil/hwcontext_vdpau.c
@@ -0,0 +1,489 @@
+/*
+ * 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 "config.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#include <vdpau/vdpau.h>
+
+#include "buffer.h"
+#include "common.h"
+#include "hwcontext.h"
+#include "hwcontext_internal.h"
+#include "hwcontext_vdpau.h"
+#include "mem.h"
+#include "pixfmt.h"
+#include "pixdesc.h"
+
+typedef struct VDPAUDeviceContext {
+    VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *get_transfer_caps;
+    VdpVideoSurfaceGetBitsYCbCr                     *get_data;
+    VdpVideoSurfacePutBitsYCbCr                     *put_data;
+    VdpVideoSurfaceCreate                           *surf_create;
+    VdpVideoSurfaceDestroy                          *surf_destroy;
+
+    enum AVPixelFormat *pix_fmts[3];
+    int              nb_pix_fmts[3];
+} VDPAUDeviceContext;
+
+typedef struct VDPAUFramesContext {
+    VdpVideoSurfaceGetBitsYCbCr *get_data;
+    VdpVideoSurfacePutBitsYCbCr *put_data;
+    VdpChromaType chroma_type;
+    int chroma_idx;
+
+    const enum AVPixelFormat *pix_fmts;
+    int                       nb_pix_fmts;
+} VDPAUFramesContext;
+
+typedef struct VDPAUPixFmtMap {
+    VdpYCbCrFormat vdpau_fmt;
+    enum AVPixelFormat pix_fmt;
+} VDPAUPixFmtMap;
+
+static const VDPAUPixFmtMap pix_fmts_420[] = {
+    { VDP_YCBCR_FORMAT_NV12, AV_PIX_FMT_NV12    },
+    { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV420P },
+    { 0,                     AV_PIX_FMT_NONE,   },
+};
+
+static const VDPAUPixFmtMap pix_fmts_422[] = {
+    { VDP_YCBCR_FORMAT_NV12, AV_PIX_FMT_NV16    },
+    { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV422P },
+    { VDP_YCBCR_FORMAT_UYVY, AV_PIX_FMT_UYVY422 },
+    { VDP_YCBCR_FORMAT_YUYV, AV_PIX_FMT_YUYV422 },
+    { 0,                     AV_PIX_FMT_NONE,   },
+};
+
+static const VDPAUPixFmtMap pix_fmts_444[] = {
+    { VDP_YCBCR_FORMAT_YV12, AV_PIX_FMT_YUV444P },
+    { 0,                     AV_PIX_FMT_NONE,   },
+};
+
+static const struct {
+    VdpChromaType chroma_type;
+    const VDPAUPixFmtMap *map;
+} vdpau_pix_fmts[] = {
+    { VDP_CHROMA_TYPE_420, pix_fmts_420 },
+    { VDP_CHROMA_TYPE_422, pix_fmts_422 },
+    { VDP_CHROMA_TYPE_444, pix_fmts_444 },
+};
+
+static int count_pixfmts(const VDPAUPixFmtMap *map)
+{
+    int count = 0;
+    while (map->pix_fmt != AV_PIX_FMT_NONE) {
+        map++;
+        count++;
+    }
+    return count;
+}
+
+static int vdpau_init_pixmfts(AVHWDeviceContext *ctx)
+{
+    AVVDPAUDeviceContext *hwctx = ctx->hwctx;
+    VDPAUDeviceContext    *priv = ctx->internal->priv;
+    int i;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(priv->pix_fmts); i++) {
+        const VDPAUPixFmtMap *map = vdpau_pix_fmts[i].map;
+        int nb_pix_fmts;
+
+        nb_pix_fmts = count_pixfmts(map);
+        priv->pix_fmts[i] = av_malloc_array(nb_pix_fmts + 1, sizeof(*priv->pix_fmts[i]));
+        if (!priv->pix_fmts[i])
+            return AVERROR(ENOMEM);
+
+        nb_pix_fmts = 0;
+        while (map->pix_fmt != AV_PIX_FMT_NONE) {
+            VdpBool supported;
+            VdpStatus err = priv->get_transfer_caps(hwctx->device, vdpau_pix_fmts[i].chroma_type,
+                                                    map->vdpau_fmt, &supported);
+            if (err == VDP_STATUS_OK && supported)
+                priv->pix_fmts[i][nb_pix_fmts++] = map->pix_fmt;
+            map++;
+        }
+        priv->pix_fmts[i][nb_pix_fmts++] = AV_PIX_FMT_NONE;
+        priv->nb_pix_fmts[i]             = nb_pix_fmts;
+    }
+
+    return 0;
+}
+
+static int vdpau_device_init(AVHWDeviceContext *ctx)
+{
+    AVVDPAUDeviceContext *hwctx = ctx->hwctx;
+    VDPAUDeviceContext   *priv  = ctx->internal->priv;
+    VdpStatus             err;
+    int                   ret;
+
+#define GET_CALLBACK(id, result)                                                \
+do {                                                                            \
+    void *tmp;                                                                  \
+    err = hwctx->get_proc_address(hwctx->device, id, &tmp);                     \
+    if (err != VDP_STATUS_OK) {                                                 \
+        av_log(ctx, AV_LOG_ERROR, "Error getting the " #id " callback.\n");     \
+        return AVERROR_UNKNOWN;                                                 \
+    }                                                                           \
+    priv->result = tmp;                                                         \
+} while (0)
+
+    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES,
+                 get_transfer_caps);
+    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, get_data);
+    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR, put_data);
+    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_CREATE,           surf_create);
+    GET_CALLBACK(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY,          surf_destroy);
+
+    ret = vdpau_init_pixmfts(ctx);
+    if (ret < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Error querying the supported pixel formats\n");
+        return ret;
+    }
+
+    return 0;
+}
+
+static void vdpau_device_uninit(AVHWDeviceContext *ctx)
+{
+    VDPAUDeviceContext *priv = ctx->internal->priv;
+    int i;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(priv->pix_fmts); i++)
+        av_freep(&priv->pix_fmts[i]);
+}
+
+static void vdpau_buffer_free(void *opaque, uint8_t *data)
+{
+    AVHWFramesContext          *ctx = opaque;
+    VDPAUDeviceContext *device_priv = ctx->device_ctx->internal->priv;
+    VdpVideoSurface            surf = (VdpVideoSurface)(uintptr_t)data;
+
+    device_priv->surf_destroy(surf);
+}
+
+static AVBufferRef *vdpau_pool_alloc(void *opaque, int size)
+{
+    AVHWFramesContext             *ctx = opaque;
+    VDPAUFramesContext           *priv = ctx->internal->priv;
+    AVVDPAUDeviceContext *device_hwctx = ctx->device_ctx->hwctx;
+    VDPAUDeviceContext    *device_priv = ctx->device_ctx->internal->priv;
+
+    AVBufferRef *ret;
+    VdpVideoSurface surf;
+    VdpStatus err;
+
+    err = device_priv->surf_create(device_hwctx->device, priv->chroma_type,
+                                   ctx->width, ctx->height, &surf);
+    if (err != VDP_STATUS_OK) {
+        av_log(ctx, AV_LOG_ERROR, "Error allocating a VDPAU video surface\n");
+        return NULL;
+    }
+
+    ret = av_buffer_create((uint8_t*)(uintptr_t)surf, sizeof(surf),
+                           vdpau_buffer_free, ctx, AV_BUFFER_FLAG_READONLY);
+    if (!ret) {
+        device_priv->surf_destroy(surf);
+        return NULL;
+    }
+
+    return ret;
+}
+
+static int vdpau_frames_init(AVHWFramesContext *ctx)
+{
+    VDPAUDeviceContext *device_priv = ctx->device_ctx->internal->priv;
+    VDPAUFramesContext        *priv = ctx->internal->priv;
+
+    int i;
+
+    switch (ctx->sw_format) {
+    case AV_PIX_FMT_YUV420P: priv->chroma_type = VDP_CHROMA_TYPE_420; break;
+    case AV_PIX_FMT_YUV422P: priv->chroma_type = VDP_CHROMA_TYPE_422; break;
+    case AV_PIX_FMT_YUV444P: priv->chroma_type = VDP_CHROMA_TYPE_444; break;
+    default:
+        av_log(ctx, AV_LOG_ERROR, "Unsupported data layout: %s\n",
+               av_get_pix_fmt_name(ctx->sw_format));
+        return AVERROR(ENOSYS);
+    }
+
+    for (i = 0; i < FF_ARRAY_ELEMS(vdpau_pix_fmts); i++) {
+        if (vdpau_pix_fmts[i].chroma_type == priv->chroma_type) {
+            priv->chroma_idx  = i;
+            priv->pix_fmts    = device_priv->pix_fmts[i];
+            priv->nb_pix_fmts = device_priv->nb_pix_fmts[i];
+            break;
+        }
+    }
+    if (!priv->pix_fmts) {
+        av_log(ctx, AV_LOG_ERROR, "Unsupported chroma type: %d\n", priv->chroma_type);
+        return AVERROR(ENOSYS);
+    }
+
+    if (!ctx->pool) {
+        ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(VdpVideoSurface), ctx,
+                                                            vdpau_pool_alloc, NULL);
+        if (!ctx->internal->pool_internal)
+            return AVERROR(ENOMEM);
+    }
+
+    priv->get_data = device_priv->get_data;
+    priv->put_data = device_priv->put_data;
+
+    return 0;
+}
+
+static int vdpau_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
+{
+    frame->buf[0] = av_buffer_pool_get(ctx->pool);
+    if (!frame->buf[0])
+        return AVERROR(ENOMEM);
+
+    frame->data[3] = frame->buf[0]->data;
+    frame->format  = AV_PIX_FMT_VDPAU;
+    frame->width   = ctx->width;
+    frame->height  = ctx->height;
+
+    return 0;
+}
+
+static int vdpau_transfer_get_formats(AVHWFramesContext *ctx,
+                                      enum AVHWFrameTransferDirection dir,
+                                      enum AVPixelFormat **formats)
+{
+    VDPAUFramesContext *priv  = ctx->internal->priv;
+
+    enum AVPixelFormat *fmts;
+
+    if (priv->nb_pix_fmts == 1) {
+        av_log(ctx, AV_LOG_ERROR,
+               "No target formats are supported for this chroma type\n");
+        return AVERROR(ENOSYS);
+    }
+
+    fmts = av_malloc_array(priv->nb_pix_fmts, sizeof(*fmts));
+    if (!fmts)
+        return AVERROR(ENOMEM);
+
+    memcpy(fmts, priv->pix_fmts, sizeof(*fmts) * (priv->nb_pix_fmts));
+    *formats = fmts;
+
+    return 0;
+}
+
+static int vdpau_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst,
+                                    const AVFrame *src)
+{
+    VDPAUFramesContext *priv = ctx->internal->priv;
+    VdpVideoSurface     surf = (VdpVideoSurface)(uintptr_t)src->data[3];
+
+    void *data[3];
+    uint32_t linesize[3];
+
+    const VDPAUPixFmtMap *map;
+    VdpYCbCrFormat vdpau_format;
+    VdpStatus err;
+    int i;
+
+    for (i = 0; i< FF_ARRAY_ELEMS(data) && dst->data[i]; i++) {
+        data[i] = dst->data[i];
+        if (dst->linesize[i] < 0 || (uint64_t)dst->linesize > UINT32_MAX) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "The linesize %d cannot be represented as uint32\n",
+                   dst->linesize[i]);
+            return AVERROR(ERANGE);
+        }
+        linesize[i] = dst->linesize[i];
+    }
+
+    map = vdpau_pix_fmts[priv->chroma_idx].map;
+    for (i = 0; map[i].pix_fmt != AV_PIX_FMT_NONE; i++) {
+        if (map[i].pix_fmt == dst->format) {
+            vdpau_format = map[i].vdpau_fmt;
+            break;
+        }
+    }
+    if (map[i].pix_fmt == AV_PIX_FMT_NONE) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Unsupported target pixel format: %s\n",
+               av_get_pix_fmt_name(dst->format));
+        return AVERROR(EINVAL);
+    }
+
+    if (vdpau_format == VDP_YCBCR_FORMAT_YV12)
+        FFSWAP(void*, data[1], data[2]);
+
+    err = priv->get_data(surf, vdpau_format, data, linesize);
+    if (err != VDP_STATUS_OK) {
+        av_log(ctx, AV_LOG_ERROR, "Error retrieving the data from a VDPAU surface\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    return 0;
+}
+
+static int vdpau_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst,
+                                  const AVFrame *src)
+{
+    VDPAUFramesContext *priv = ctx->internal->priv;
+    VdpVideoSurface     surf = (VdpVideoSurface)(uintptr_t)dst->data[3];
+
+    const void *data[3];
+    uint32_t linesize[3];
+
+    const VDPAUPixFmtMap *map;
+    VdpYCbCrFormat vdpau_format;
+    VdpStatus err;
+    int i;
+
+    for (i = 0; i< FF_ARRAY_ELEMS(data) && src->data[i]; i++) {
+        data[i] = src->data[i];
+        if (src->linesize[i] < 0 || (uint64_t)src->linesize > UINT32_MAX) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "The linesize %d cannot be represented as uint32\n",
+                   src->linesize[i]);
+            return AVERROR(ERANGE);
+        }
+        linesize[i] = src->linesize[i];
+    }
+
+    map = vdpau_pix_fmts[priv->chroma_idx].map;
+    for (i = 0; map[i].pix_fmt != AV_PIX_FMT_NONE; i++) {
+        if (map[i].pix_fmt == src->format) {
+            vdpau_format = map[i].vdpau_fmt;
+            break;
+        }
+    }
+    if (map[i].pix_fmt == AV_PIX_FMT_NONE) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Unsupported source pixel format: %s\n",
+               av_get_pix_fmt_name(src->format));
+        return AVERROR(EINVAL);
+    }
+
+    if (vdpau_format == VDP_YCBCR_FORMAT_YV12)
+        FFSWAP(const void*, data[1], data[2]);
+
+    err = priv->put_data(surf, vdpau_format, data, linesize);
+    if (err != VDP_STATUS_OK) {
+        av_log(ctx, AV_LOG_ERROR, "Error uploading the data to a VDPAU surface\n");
+        return AVERROR_UNKNOWN;
+    }
+
+    return 0;
+}
+
+#if HAVE_VDPAU_X11
+#include <vdpau/vdpau_x11.h>
+#include <X11/Xlib.h>
+
+typedef struct VDPAUDevicePriv {
+    VdpDeviceDestroy *device_destroy;
+    Display *dpy;
+} VDPAUDevicePriv;
+
+static void vdpau_device_free(AVHWDeviceContext *ctx)
+{
+    AVVDPAUDeviceContext *hwctx = ctx->hwctx;
+    VDPAUDevicePriv       *priv = ctx->user_opaque;
+
+    if (priv->device_destroy)
+        priv->device_destroy(hwctx->device);
+    if (priv->dpy)
+        XCloseDisplay(priv->dpy);
+    av_freep(&priv);
+}
+
+static int vdpau_device_create(AVHWDeviceContext *ctx, const char *device,
+                               AVDictionary *opts, int flags)
+{
+    AVVDPAUDeviceContext *hwctx = ctx->hwctx;
+
+    VDPAUDevicePriv *priv;
+    VdpStatus err;
+    VdpGetInformationString *get_information_string;
+    const char *display, *vendor;
+
+    priv = av_mallocz(sizeof(*priv));
+    if (!priv)
+        return AVERROR(ENOMEM);
+
+    ctx->user_opaque = priv;
+    ctx->free        = vdpau_device_free;
+
+    priv->dpy = XOpenDisplay(device);
+    if (!priv->dpy) {
+        av_log(ctx, AV_LOG_ERROR, "Cannot open the X11 display %s.\n",
+               XDisplayName(device));
+        return AVERROR_UNKNOWN;
+    }
+    display = XDisplayString(priv->dpy);
+
+    err = vdp_device_create_x11(priv->dpy, XDefaultScreen(priv->dpy),
+                                &hwctx->device, &hwctx->get_proc_address);
+    if (err != VDP_STATUS_OK) {
+        av_log(ctx, AV_LOG_ERROR, "VDPAU device creation on X11 display %s failed.\n",
+               display);
+        return AVERROR_UNKNOWN;
+    }
+
+#define GET_CALLBACK(id, result)                                                \
+do {                                                                            \
+    void *tmp;                                                                  \
+    err = hwctx->get_proc_address(hwctx->device, id, &tmp);                     \
+    if (err != VDP_STATUS_OK) {                                                 \
+        av_log(ctx, AV_LOG_ERROR, "Error getting the " #id " callback.\n");     \
+        return AVERROR_UNKNOWN;                                                 \
+    }                                                                           \
+    result = tmp;                                                               \
+} while (0)
+
+    GET_CALLBACK(VDP_FUNC_ID_GET_INFORMATION_STRING, get_information_string);
+    GET_CALLBACK(VDP_FUNC_ID_DEVICE_DESTROY,         priv->device_destroy);
+
+    get_information_string(&vendor);
+    av_log(ctx, AV_LOG_VERBOSE, "Successfully created a VDPAU device (%s) on "
+           "X11 display %s\n", vendor, display);
+
+    return 0;
+}
+#endif
+
+const HWContextType ff_hwcontext_type_vdpau = {
+    .type                 = AV_HWDEVICE_TYPE_VDPAU,
+    .name                 = "VDPAU",
+
+    .device_hwctx_size    = sizeof(AVVDPAUDeviceContext),
+    .device_priv_size     = sizeof(VDPAUDeviceContext),
+    .frames_priv_size     = sizeof(VDPAUFramesContext),
+
+#if HAVE_VDPAU_X11
+    .device_create        = vdpau_device_create,
+#endif
+    .device_init          = vdpau_device_init,
+    .device_uninit        = vdpau_device_uninit,
+    .frames_init          = vdpau_frames_init,
+    .frames_get_buffer    = vdpau_get_buffer,
+    .transfer_get_formats = vdpau_transfer_get_formats,
+    .transfer_data_to     = vdpau_transfer_data_to,
+    .transfer_data_from   = vdpau_transfer_data_from,
+
+    .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VDPAU, AV_PIX_FMT_NONE },
+};
diff --git a/libavutil/hwcontext_vdpau.h b/libavutil/hwcontext_vdpau.h
new file mode 100644
index 0000000..1b7ea1e
--- /dev/null
+++ b/libavutil/hwcontext_vdpau.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_HWCONTEXT_VDPAU_H
+#define AVUTIL_HWCONTEXT_VDPAU_H
+
+#include <vdpau/vdpau.h>
+
+/**
+ * @file
+ * An API-specific header for AV_HWDEVICE_TYPE_VDPAU.
+ *
+ * This API supports dynamic frame pools. AVHWFramesContext.pool must return
+ * AVBufferRefs whose data pointer is a VdpVideoSurface.
+ */
+
+/**
+ * This struct is allocated as AVHWDeviceContext.hwctx
+ */
+typedef struct AVVDPAUDeviceContext {
+    VdpDevice          device;
+    VdpGetProcAddress *get_proc_address;
+} AVVDPAUDeviceContext;
+
+/**
+ * AVHWFramesContext.hwctx is currently not used
+ */
+
+#endif /* AVUTIL_HWCONTEXT_VDPAU_H */
diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c
index 1474482..37808e5 100644
--- a/libavutil/imgutils.c
+++ b/libavutil/imgutils.c
@@ -389,6 +389,7 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size,
     int i, j, nb_planes = 0, linesize[4];
     int size = av_image_get_buffer_size(pix_fmt, width, height, align);
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
+    int ret;
 
     if (size > dst_size || size < 0 || !desc)
         return AVERROR(EINVAL);
@@ -398,7 +399,9 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size,
 
     nb_planes++;
 
-    av_image_fill_linesizes(linesize, pix_fmt, width);
+    ret = av_image_fill_linesizes(linesize, pix_fmt, width);
+    av_assert0(ret >= 0); // was checked previously
+
     for (i = 0; i < nb_planes; i++) {
         int h, shift = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
         const uint8_t *src = src_data[i];
diff --git a/libavutil/internal.h b/libavutil/internal.h
index 44f8c1e..61784b5 100644
--- a/libavutil/internal.h
+++ b/libavutil/internal.h
@@ -244,6 +244,7 @@ void avpriv_request_sample(void *avc,
 #endif
 
 #define avpriv_open ff_open
+#define avpriv_tempfile ff_tempfile
 #define PTRDIFF_SPECIFIER "Id"
 #define SIZE_SPECIFIER "Iu"
 #else
@@ -294,47 +295,24 @@ static av_always_inline av_const int64_t ff_rint64_clip(double a, int64_t amin,
 }
 
 /**
- * Compute 10^x for floating point values. Note: this function is by no means
- * "correctly rounded", and is meant as a fast, reasonably accurate approximation.
- * For instance, maximum relative error for the double precision variant is
- * ~ 1e-13 for very small and very large values.
- * This is ~2x faster than GNU libm's approach, which is still off by 2ulp on
- * some inputs.
- * @param x exponent
- * @return 10^x
- */
-static av_always_inline double ff_exp10(double x)
-{
-    return exp2(M_LOG2_10 * x);
-}
-
-static av_always_inline float ff_exp10f(float x)
-{
-    return exp2f(M_LOG2_10 * x);
-}
-
-/**
- * Compute x^y for floating point x, y. Note: this function is faster than the
- * libm variant due to mainly 2 reasons:
- * 1. It does not handle any edge cases. In particular, this is only guaranteed
- * to work correctly for x > 0.
- * 2. It is not as accurate as a standard nearly "correctly rounded" libm variant.
- * @param x base
- * @param y exponent
- * @return x^y
- */
-static av_always_inline float ff_fast_powf(float x, float y)
-{
-    return expf(logf(x) * y);
-}
-
-
-/**
  * A wrapper for open() setting O_CLOEXEC.
  */
 av_warn_unused_result
 int avpriv_open(const char *filename, int flags, ...);
 
+/**
+ * Wrapper to work around the lack of mkstemp() on mingw.
+ * Also, tries to create file in /tmp first, if possible.
+ * *prefix can be a character constant; *filename will be allocated internally.
+ * @return file descriptor of opened file (or negative value corresponding to an
+ * AVERROR code on error)
+ * and opened file name in **filename.
+ * @note On very old libcs it is necessary to set a secure umask before
+ *       calling this, av_tempfile() can't call umask itself as it is used in
+ *       libraries and could interfere with the calling application.
+ */
+int avpriv_tempfile(const char *prefix, char **filename, int log_offset, void *log_ctx);
+
 int avpriv_set_systematic_pal2(uint32_t pal[256], enum AVPixelFormat pix_fmt);
 
 static av_always_inline av_const int avpriv_mirror(int x, int w)
diff --git a/libavutil/lfg.c b/libavutil/lfg.c
index ffa2f1f..08a4f67 100644
--- a/libavutil/lfg.c
+++ b/libavutil/lfg.c
@@ -58,45 +58,3 @@ void av_bmg_get(AVLFG *lfg, double out[2])
     out[0] = x1 * w;
     out[1] = x2 * w;
 }
-
-#ifdef TEST
-#include "log.h"
-#include "timer.h"
-
-int main(void)
-{
-    int x = 0;
-    int i, j;
-    AVLFG state;
-
-    av_lfg_init(&state, 0xdeadbeef);
-    for (j = 0; j < 10000; j++) {
-        START_TIMER
-        for (i = 0; i < 624; i++) {
-            //av_log(NULL, AV_LOG_ERROR, "%X\n", av_lfg_get(&state));
-            x += av_lfg_get(&state);
-        }
-        STOP_TIMER("624 calls of av_lfg_get");
-    }
-    av_log(NULL, AV_LOG_ERROR, "final value:%X\n", x);
-
-    /* BMG usage example */
-    {
-        double mean   = 1000;
-        double stddev = 53;
-
-        av_lfg_init(&state, 42);
-
-        for (i = 0; i < 1000; i += 2) {
-            double bmg_out[2];
-            av_bmg_get(&state, bmg_out);
-            av_log(NULL, AV_LOG_INFO,
-                   "%f\n%f\n",
-                   bmg_out[0] * stddev + mean,
-                   bmg_out[1] * stddev + mean);
-        }
-    }
-
-    return 0;
-}
-#endif
diff --git a/libavutil/lls.c b/libavutil/lls.c
index 7dd718d..0560b6a 100644
--- a/libavutil/lls.c
+++ b/libavutil/lls.c
@@ -29,7 +29,6 @@
 #include <string.h>
 
 #include "attributes.h"
-#include "config.h"
 #include "internal.h"
 #include "version.h"
 #include "lls.h"
@@ -122,41 +121,3 @@ av_cold void avpriv_init_lls(LLSModel *m, int indep_count)
     if (ARCH_X86)
         ff_init_lls_x86(m);
 }
-
-#ifdef TEST
-
-#include <stdio.h>
-#include <limits.h>
-#include "lfg.h"
-
-int main(void)
-{
-    LLSModel m;
-    int i, order;
-    AVLFG lfg;
-
-    av_lfg_init(&lfg, 1);
-    avpriv_init_lls(&m, 3);
-
-    for (i = 0; i < 100; i++) {
-        LOCAL_ALIGNED(32, double, var, [4]);
-        double eval;
-
-        var[0] = (av_lfg_get(&lfg) / (double) UINT_MAX - 0.5) * 2;
-        var[1] = var[0] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5;
-        var[2] = var[1] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5;
-        var[3] = var[2] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5;
-        m.update_lls(&m, var);
-        avpriv_solve_lls(&m, 0.001, 0);
-        for (order = 0; order < 3; order++) {
-            eval = m.evaluate_lls(&m, var + 1, order);
-            printf("real:%9f order:%d pred:%9f var:%f coeffs:%f %9f %9f\n",
-                   var[0], order, eval, sqrt(m.variance[order] / (i + 1)),
-                   m.coeff[order][0], m.coeff[order][1],
-                   m.coeff[order][2]);
-        }
-    }
-    return 0;
-}
-
-#endif
diff --git a/libavutil/log.c b/libavutil/log.c
index 4583519..44c11cb 100644
--- a/libavutil/log.c
+++ b/libavutil/log.c
@@ -284,10 +284,19 @@ static void format_line(void *avcl, int level, const char *fmt, va_list vl,
 void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl,
                         char *line, int line_size, int *print_prefix)
 {
+    av_log_format_line2(ptr, level, fmt, vl, line, line_size, print_prefix);
+}
+
+int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl,
+                        char *line, int line_size, int *print_prefix)
+{
     AVBPrint part[4];
+    int ret;
+
     format_line(ptr, level, fmt, vl, part, print_prefix, NULL);
-    snprintf(line, line_size, "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str);
+    ret = snprintf(line, line_size, "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str);
     av_bprint_finalize(part+3, NULL);
+    return ret;
 }
 
 void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl)
@@ -430,26 +439,3 @@ void avpriv_report_missing_feature(void *avc, const char *msg, ...)
     missing_feature_sample(0, avc, msg, argument_list);
     va_end(argument_list);
 }
-
-#ifdef TEST
-// LCOV_EXCL_START
-#include <string.h>
-
-int main(int argc, char **argv)
-{
-    int i;
-    av_log_set_level(AV_LOG_DEBUG);
-    for (use_color=0; use_color<=256; use_color = 255*use_color+1) {
-        av_log(NULL, AV_LOG_FATAL, "use_color: %d\n", use_color);
-        for (i = AV_LOG_DEBUG; i>=AV_LOG_QUIET; i-=8) {
-            av_log(NULL, i, " %d", i);
-            av_log(NULL, AV_LOG_INFO, "e ");
-            av_log(NULL, i + 256*123, "C%d", i);
-            av_log(NULL, AV_LOG_INFO, "e");
-        }
-        av_log(NULL, AV_LOG_PANIC, "\n");
-    }
-    return 0;
-}
-// LCOV_EXCL_STOP
-#endif
diff --git a/libavutil/log.h b/libavutil/log.h
index 321748c..0acc1b9 100644
--- a/libavutil/log.h
+++ b/libavutil/log.h
@@ -317,6 +317,23 @@ AVClassCategory av_default_get_category(void *ptr);
 void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl,
                         char *line, int line_size, int *print_prefix);
 
+/**
+ * Format a line of log the same way as the default callback.
+ * @param line          buffer to receive the formatted line;
+ *                      may be NULL if line_size is 0
+ * @param line_size     size of the buffer; at most line_size-1 characters will
+ *                      be written to the buffer, plus one null terminator
+ * @param print_prefix  used to store whether the prefix must be printed;
+ *                      must point to a persistent integer initially set to 1
+ * @return Returns a negative value if an error occurred, otherwise returns
+ *         the number of characters that would have been written for a
+ *         sufficiently large buffer, not including the terminating null
+ *         character. If the return value is not less than line_size, it means
+ *         that the log message was truncated to fit the buffer.
+ */
+int av_log_format_line2(void *ptr, int level, const char *fmt, va_list vl,
+                        char *line, int line_size, int *print_prefix);
+
 #if FF_API_DLOG
 /**
  * av_dlog macros
diff --git a/libavutil/lzo.c b/libavutil/lzo.c
index bca10ec..1ae076e 100644
--- a/libavutil/lzo.c
+++ b/libavutil/lzo.c
@@ -203,58 +203,3 @@ int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen)
     *outlen = c.out_end - c.out;
     return c.error;
 }
-
-#ifdef TEST
-#include <stdio.h>
-#include <lzo/lzo1x.h>
-#include "log.h"
-#define MAXSZ (10*1024*1024)
-
-/* Define one of these to 1 if you wish to benchmark liblzo
- * instead of our native implementation. */
-#define BENCHMARK_LIBLZO_SAFE   0
-#define BENCHMARK_LIBLZO_UNSAFE 0
-
-int main(int argc, char *argv[]) {
-    FILE *in = fopen(argv[1], "rb");
-    int comp_level = argc > 2 ? atoi(argv[2]) : 0;
-    uint8_t *orig = av_malloc(MAXSZ + 16);
-    uint8_t *comp = av_malloc(2*MAXSZ + 16);
-    uint8_t *decomp = av_malloc(MAXSZ + 16);
-    size_t s = fread(orig, 1, MAXSZ, in);
-    lzo_uint clen = 0;
-    long tmp[LZO1X_MEM_COMPRESS];
-    int inlen, outlen;
-    int i;
-    av_log_set_level(AV_LOG_DEBUG);
-    if (comp_level == 0) {
-        lzo1x_1_compress(orig, s, comp, &clen, tmp);
-    } else if (comp_level == 11) {
-        lzo1x_1_11_compress(orig, s, comp, &clen, tmp);
-    } else if (comp_level == 12) {
-        lzo1x_1_12_compress(orig, s, comp, &clen, tmp);
-    } else if (comp_level == 15) {
-        lzo1x_1_15_compress(orig, s, comp, &clen, tmp);
-    } else
-        lzo1x_999_compress(orig, s, comp, &clen, tmp);
-    for (i = 0; i < 300; i++) {
-START_TIMER
-        inlen = clen; outlen = MAXSZ;
-#if BENCHMARK_LIBLZO_SAFE
-        if (lzo1x_decompress_safe(comp, inlen, decomp, &outlen, NULL))
-#elif BENCHMARK_LIBLZO_UNSAFE
-        if (lzo1x_decompress(comp, inlen, decomp, &outlen, NULL))
-#else
-        if (av_lzo1x_decode(decomp, &outlen, comp, &inlen))
-#endif
-            av_log(NULL, AV_LOG_ERROR, "decompression error\n");
-STOP_TIMER("lzod")
-    }
-    if (memcmp(orig, decomp, s))
-        av_log(NULL, AV_LOG_ERROR, "decompression incorrect\n");
-    else
-        av_log(NULL, AV_LOG_ERROR, "decompression OK\n");
-    fclose(in);
-    return 0;
-}
-#endif
diff --git a/libavutil/md5.c b/libavutil/md5.c
index 876bd55..8c36aa8 100644
--- a/libavutil/md5.c
+++ b/libavutil/md5.c
@@ -8,7 +8,7 @@
  *
  * based on http://ubiqx.org/libcifs/source/Auth/MD5.c
  *          from Christopher R. Hertel (crh at ubiqx.mn.org)
- * Simplified, cleaned and IMO redundant comments removed by michael.
+ * Simplified, cleaned and IMO redundant comments removed by Michael.
  *
  * If you use gcc, then version 4.1 or later and -fomit-frame-pointer is
  * strongly recommended.
@@ -31,12 +31,13 @@
  */
 
 #include <stdint.h>
+
 #include "bswap.h"
 #include "intreadwrite.h"
-#include "md5.h"
 #include "mem.h"
+#include "md5.h"
 
-typedef struct AVMD5{
+typedef struct AVMD5 {
     uint64_t len;
     uint8_t  block[64];
     uint32_t ABCD[4];
@@ -78,16 +79,21 @@ static const uint32_t T[64] = { // T[i]= fabs(sin(i+1)<<32)
     0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
 };
 
-#define CORE(i, a, b, c, d) do {                                        \
-        t = S[i >> 4][i & 3];                                           \
+#define CORE(i, a, b, c, d)                                             \
+    do {                                                                \
+        t  = S[i >> 4][i & 3];                                          \
         a += T[i];                                                      \
                                                                         \
         if (i < 32) {                                                   \
-            if (i < 16) a += (d ^ (b & (c ^ d)))  + X[       i  & 15];  \
-            else        a += ((d & b) | (~d & c)) + X[(1 + 5*i) & 15];  \
+            if (i < 16)                                                 \
+                a += (d ^ (b & (c ^ d)))  + X[       i  & 15];          \
+            else                                                        \
+                a += ((d & b) | (~d & c)) + X[(1 + 5*i) & 15];          \
         } else {                                                        \
-            if (i < 48) a += (b ^ c ^ d)          + X[(5 + 3*i) & 15];  \
-            else        a += (c ^ (b | ~d))       + X[(    7*i) & 15];  \
+            if (i < 48)                                                 \
+                a += (b ^ c ^ d)          + X[(5 + 3*i) & 15];          \
+            else                                                        \
+                a += (c ^ (b | ~d))       + X[(    7*i) & 15];          \
         }                                                               \
         a = b + (a << t | a >> (32 - t));                               \
     } while (0)
@@ -122,10 +128,13 @@ static void body(uint32_t ABCD[4], uint32_t *src, int nblocks)
         }
 #else
 #define CORE2(i)                                                        \
-        CORE( i,   a,b,c,d); CORE((i+1),d,a,b,c);                       \
-        CORE((i+2),c,d,a,b); CORE((i+3),b,c,d,a)
-#define CORE4(i) CORE2(i); CORE2((i+4)); CORE2((i+8)); CORE2((i+12))
-        CORE4(0); CORE4(16); CORE4(32); CORE4(48);
+        CORE(i, a, b, c, d); CORE((i + 1), d, a, b, c);                 \
+        CORE((i + 2), c, d, a, b); CORE((i + 3), b, c, d, a)
+#define CORE4(i) CORE2(i); CORE2((i + 4)); CORE2((i + 8)); CORE2((i + 12))
+        CORE4(0);
+        CORE4(16);
+        CORE4(32);
+        CORE4(48);
 #endif
 
         ABCD[0] += d;
@@ -150,7 +159,7 @@ void av_md5_update(AVMD5 *ctx, const uint8_t *src, int len)
     const uint8_t *end;
     int j;
 
-    j = ctx->len & 63;
+    j         = ctx->len & 63;
     ctx->len += len;
 
     if (j) {
@@ -189,10 +198,10 @@ void av_md5_final(AVMD5 *ctx, uint8_t *dst)
     while ((ctx->len & 63) != 56)
         av_md5_update(ctx, "", 1);
 
-    av_md5_update(ctx, (uint8_t *)&finalcount, 8);
+    av_md5_update(ctx, (uint8_t *) &finalcount, 8);
 
     for (i = 0; i < 4; i++)
-        AV_WL32(dst + 4*i, ctx->ABCD[3 - i]);
+        AV_WL32(dst + 4 * i, ctx->ABCD[3 - i]);
 }
 
 void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len)
@@ -203,34 +212,3 @@ void av_md5_sum(uint8_t *dst, const uint8_t *src, const int len)
     av_md5_update(&ctx, src, len);
     av_md5_final(&ctx, dst);
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-static void print_md5(uint8_t *md5)
-{
-    int i;
-    for (i = 0; i < 16; i++)
-        printf("%02x", md5[i]);
-    printf("\n");
-}
-
-int main(void){
-    uint8_t md5val[16];
-    int i;
-    volatile uint8_t in[1000]; // volatile to workaround http://llvm.org/bugs/show_bug.cgi?id=20849
-    // FIXME remove volatile once it has been fixed and all fate clients are updated
-
-    for (i = 0; i < 1000; i++)
-        in[i] = i * i;
-    av_md5_sum(md5val, in, 1000); print_md5(md5val);
-    av_md5_sum(md5val, in,   63); print_md5(md5val);
-    av_md5_sum(md5val, in,   64); print_md5(md5val);
-    av_md5_sum(md5val, in,   65); print_md5(md5val);
-    for (i = 0; i < 1000; i++)
-        in[i] = i % 127;
-    av_md5_sum(md5val, in,  999); print_md5(md5val);
-
-    return 0;
-}
-#endif
diff --git a/libavutil/mips/asmdefs.h b/libavutil/mips/asmdefs.h
index fdf82a0..7481199 100644
--- a/libavutil/mips/asmdefs.h
+++ b/libavutil/mips/asmdefs.h
@@ -28,19 +28,31 @@
 #define AVUTIL_MIPS_ASMDEFS_H
 
 #if defined(_ABI64) && _MIPS_SIM == _ABI64
+# define mips_reg       int64_t
 # define PTRSIZE        " 8 "
 # define PTRLOG         " 3 "
 # define PTR_ADDU       "daddu "
 # define PTR_ADDIU      "daddiu "
+# define PTR_ADDI       "daddi "
 # define PTR_SUBU       "dsubu "
 # define PTR_L          "ld "
+# define PTR_S          "sd "
+# define PTR_SRA        "dsra "
+# define PTR_SRL        "dsrl "
+# define PTR_SLL        "dsll "
 #else
+# define mips_reg       int32_t
 # define PTRSIZE        " 4 "
 # define PTRLOG         " 2 "
 # define PTR_ADDU       "addu "
 # define PTR_ADDIU      "addiu "
+# define PTR_ADDI       "addi "
 # define PTR_SUBU       "subu "
 # define PTR_L          "lw "
+# define PTR_S          "sw "
+# define PTR_SRA        "sra "
+# define PTR_SRL        "srl "
+# define PTR_SLL        "sll "
 #endif
 
 #endif /* AVCODEC_MIPS_ASMDEFS_H */
diff --git a/libavutil/murmur3.c b/libavutil/murmur3.c
index c4d8dcb..4271e01 100644
--- a/libavutil/murmur3.c
+++ b/libavutil/murmur3.c
@@ -153,40 +153,3 @@ void av_murmur3_final(AVMurMur3 *c, uint8_t dst[16])
     AV_WL64(dst, h1);
     AV_WL64(dst + 8, h2);
 }
-
-#ifdef TEST
-int main(void)
-{
-    int i;
-    uint8_t hash_result[16] = {0};
-    AVMurMur3 *ctx = av_murmur3_alloc();
-#if 1
-    uint8_t in[256] = {0};
-    uint8_t *hashes = av_mallocz(256 * 16);
-    for (i = 0; i < 256; i++)
-    {
-        in[i] = i;
-        av_murmur3_init_seeded(ctx, 256 - i);
-        // Note: this actually tests hashing 0 bytes
-        av_murmur3_update(ctx, in, i);
-        av_murmur3_final(ctx, hashes + 16 * i);
-    }
-    av_murmur3_init_seeded(ctx, 0);
-    av_murmur3_update(ctx, hashes, 256 * 16);
-    av_murmur3_final(ctx, hash_result);
-    av_free(hashes);
-    av_freep(&ctx);
-    printf("result: 0x%"PRIx64" 0x%"PRIx64"\n", AV_RL64(hash_result), AV_RL64(hash_result + 8));
-    // official reference value is 32 bit
-    return AV_RL32(hash_result) != 0x6384ba69;
-#else
-    uint8_t *in = av_mallocz(512*1024);
-    av_murmur3_init(ctx);
-    for (i = 0; i < 40*1024; i++)
-        av_murmur3_update(ctx, in, 512*1024);
-    av_murmur3_final(ctx, hash_result);
-    av_free(in);
-    return hash_result[0];
-#endif
-}
-#endif
diff --git a/libavutil/opencl.c b/libavutil/opencl.c
index 08b5034..af35770 100644
--- a/libavutil/opencl.c
+++ b/libavutil/opencl.c
@@ -445,7 +445,7 @@ cl_program av_opencl_compile(const char *program_name, const char *build_opts)
     int i;
     cl_int status, build_status;
     int kernel_code_idx = 0;
-    const char *kernel_source;
+    const char *kernel_source = NULL;
     size_t kernel_code_len;
     char* ptr = NULL;
     cl_program program = NULL;
diff --git a/libavutil/opt.c b/libavutil/opt.c
index eae4f75..cd16bd1 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -30,13 +30,13 @@
 #include "avstring.h"
 #include "channel_layout.h"
 #include "common.h"
-#include "opt.h"
-#include "eval.h"
 #include "dict.h"
+#include "eval.h"
 #include "log.h"
 #include "parseutils.h"
 #include "pixdesc.h"
 #include "mathematics.h"
+#include "opt.h"
 #include "samplefmt.h"
 #include "bprint.h"
 
@@ -58,20 +58,37 @@ const AVOption *av_opt_next(const void *obj, const AVOption *last)
 static int read_number(const AVOption *o, const void *dst, double *num, int *den, int64_t *intnum)
 {
     switch (o->type) {
-    case AV_OPT_TYPE_FLAGS:     *intnum = *(unsigned int*)dst;return 0;
-    case AV_OPT_TYPE_PIXEL_FMT: *intnum = *(enum AVPixelFormat *)dst;return 0;
-    case AV_OPT_TYPE_SAMPLE_FMT:*intnum = *(enum AVSampleFormat*)dst;return 0;
+    case AV_OPT_TYPE_FLAGS:
+        *intnum = *(unsigned int*)dst;
+        return 0;
+    case AV_OPT_TYPE_PIXEL_FMT:
+        *intnum = *(enum AVPixelFormat *)dst;
+        return 0;
+    case AV_OPT_TYPE_SAMPLE_FMT:
+        *intnum = *(enum AVSampleFormat *)dst;
+        return 0;
     case AV_OPT_TYPE_BOOL:
-    case AV_OPT_TYPE_INT:       *intnum = *(int         *)dst;return 0;
+    case AV_OPT_TYPE_INT:
+        *intnum = *(int *)dst;
+        return 0;
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
     case AV_OPT_TYPE_DURATION:
-    case AV_OPT_TYPE_INT64:     *intnum = *(int64_t     *)dst;return 0;
-    case AV_OPT_TYPE_FLOAT:     *num    = *(float       *)dst;return 0;
-    case AV_OPT_TYPE_DOUBLE:    *num    = *(double      *)dst;return 0;
-    case AV_OPT_TYPE_RATIONAL:  *intnum = ((AVRational*)dst)->num;
-                                *den    = ((AVRational*)dst)->den;
-                                                        return 0;
-    case AV_OPT_TYPE_CONST:     *num    = o->default_val.dbl; return 0;
+    case AV_OPT_TYPE_INT64:
+        *intnum = *(int64_t *)dst;
+        return 0;
+    case AV_OPT_TYPE_FLOAT:
+        *num = *(float *)dst;
+        return 0;
+    case AV_OPT_TYPE_DOUBLE:
+        *num = *(double *)dst;
+        return 0;
+    case AV_OPT_TYPE_RATIONAL:
+        *intnum = ((AVRational *)dst)->num;
+        *den    = ((AVRational *)dst)->den;
+        return 0;
+    case AV_OPT_TYPE_CONST:
+        *num = o->default_val.dbl;
+        return 0;
     }
     return AVERROR(EINVAL);
 }
@@ -80,7 +97,7 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
 {
     if (o->type != AV_OPT_TYPE_FLAGS &&
         (o->max * den < num * intnum || o->min * den > num * intnum)) {
-        num = den ? num*intnum/den : (num*intnum ? INFINITY : NAN);
+        num = den ? num * intnum / den : (num * intnum ? INFINITY : NAN);
         av_log(obj, AV_LOG_ERROR, "Value %f for parameter '%s' out of range [%g - %g]\n",
                num, o->name, o->min, o->max);
         return AVERROR(ERANGE);
@@ -96,19 +113,34 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
     }
 
     switch (o->type) {
-    case AV_OPT_TYPE_PIXEL_FMT: *(enum AVPixelFormat *)dst = llrint(num/den) * intnum; break;
-    case AV_OPT_TYPE_SAMPLE_FMT:*(enum AVSampleFormat*)dst = llrint(num/den) * intnum; break;
+    case AV_OPT_TYPE_PIXEL_FMT:
+        *(enum AVPixelFormat *)dst = llrint(num / den) * intnum;
+        break;
+    case AV_OPT_TYPE_SAMPLE_FMT:
+        *(enum AVSampleFormat *)dst = llrint(num / den) * intnum;
+        break;
     case AV_OPT_TYPE_BOOL:
     case AV_OPT_TYPE_FLAGS:
-    case AV_OPT_TYPE_INT:   *(int       *)dst= llrint(num/den)*intnum; break;
+    case AV_OPT_TYPE_INT:
+        *(int *)dst = llrint(num / den) * intnum;
+        break;
     case AV_OPT_TYPE_DURATION:
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
-    case AV_OPT_TYPE_INT64: *(int64_t   *)dst= llrint(num/den)*intnum; break;
-    case AV_OPT_TYPE_FLOAT: *(float     *)dst= num*intnum/den;         break;
-    case AV_OPT_TYPE_DOUBLE:*(double    *)dst= num*intnum/den;         break;
+    case AV_OPT_TYPE_INT64:
+        *(int64_t *)dst = llrint(num / den) * intnum;
+        break;
+    case AV_OPT_TYPE_FLOAT:
+        *(float *)dst = num * intnum / den;
+        break;
+    case AV_OPT_TYPE_DOUBLE:
+        *(double    *)dst = num * intnum / den;
+        break;
     case AV_OPT_TYPE_RATIONAL:
-        if ((int)num == num) *(AVRational*)dst= (AVRational){num*intnum, den};
-        else                 *(AVRational*)dst= av_d2q(num*intnum/den, 1<<24);
+    case AV_OPT_TYPE_VIDEO_RATE:
+        if ((int) num == num)
+            *(AVRational *)dst = (AVRational) { num *intnum, den };
+        else
+            *(AVRational *)dst = av_d2q(num * intnum / den, 1 << 24);
         break;
     default:
         return AVERROR(EINVAL);
@@ -117,9 +149,12 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int
 }
 
 static int hexchar2int(char c) {
-    if (c >= '0' && c <= '9') return c - '0';
-    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
-    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
+    if (c >= '0' && c <= '9')
+        return c - '0';
+    if (c >= 'a' && c <= 'f')
+        return c - 'a' + 10;
+    if (c >= 'A' && c <= 'F')
+        return c - 'A' + 10;
     return -1;
 }
 
@@ -151,7 +186,7 @@ static int set_string_binary(void *obj, const AVOption *o, const char *val, uint
         }
         *ptr++ = (a << 4) | b;
     }
-    *dst = bin;
+    *dst    = bin;
     *lendst = len;
 
     return 0;
@@ -167,8 +202,9 @@ static int set_string(void *obj, const AVOption *o, const char *val, uint8_t **d
 #define DEFAULT_NUMVAL(opt) ((opt->type == AV_OPT_TYPE_INT64 || \
                               opt->type == AV_OPT_TYPE_CONST || \
                               opt->type == AV_OPT_TYPE_FLAGS || \
-                              opt->type == AV_OPT_TYPE_INT) ? \
-                             opt->default_val.i64 : opt->default_val.dbl)
+                              opt->type == AV_OPT_TYPE_INT)     \
+                             ? opt->default_val.i64             \
+                             : opt->default_val.dbl)
 
 static int set_string_number(void *obj, void *target_obj, const AVOption *o, const char *val, void *dst)
 {
@@ -243,8 +279,10 @@ static int set_string_number(void *obj, void *target_obj, const AVOption *o, con
         }
         if (o->type == AV_OPT_TYPE_FLAGS) {
             read_number(o, dst, NULL, NULL, &intnum);
-            if      (cmd == '+') d = intnum | (int64_t)d;
-            else if (cmd == '-') d = intnum &~(int64_t)d;
+            if (cmd == '+')
+                d = intnum | (int64_t)d;
+            else if (cmd == '-')
+                d = intnum &~(int64_t)d;
         }
 
         if ((ret = write_number(obj, o, dst, d, 1, 1)) < 0)
@@ -407,21 +445,34 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
     if (o->flags & AV_OPT_FLAG_READONLY)
         return AVERROR(EINVAL);
 
-    dst = ((uint8_t*)target_obj) + o->offset;
+    dst = ((uint8_t *)target_obj) + o->offset;
     switch (o->type) {
-    case AV_OPT_TYPE_BOOL:     return set_string_bool(obj, o, val, dst);
-    case AV_OPT_TYPE_STRING:   return set_string(obj, o, val, dst);
-    case AV_OPT_TYPE_BINARY:   return set_string_binary(obj, o, val, dst);
+    case AV_OPT_TYPE_BOOL:
+        return set_string_bool(obj, o, val, dst);
+    case AV_OPT_TYPE_STRING:
+        return set_string(obj, o, val, dst);
+    case AV_OPT_TYPE_BINARY:
+        return set_string_binary(obj, o, val, dst);
     case AV_OPT_TYPE_FLAGS:
     case AV_OPT_TYPE_INT:
     case AV_OPT_TYPE_INT64:
     case AV_OPT_TYPE_FLOAT:
     case AV_OPT_TYPE_DOUBLE:
-    case AV_OPT_TYPE_RATIONAL: return set_string_number(obj, target_obj, o, val, dst);
-    case AV_OPT_TYPE_IMAGE_SIZE: return set_string_image_size(obj, o, val, dst);
-    case AV_OPT_TYPE_VIDEO_RATE: return set_string_video_rate(obj, o, val, dst);
-    case AV_OPT_TYPE_PIXEL_FMT:  return set_string_pixel_fmt(obj, o, val, dst);
-    case AV_OPT_TYPE_SAMPLE_FMT: return set_string_sample_fmt(obj, o, val, dst);
+    case AV_OPT_TYPE_RATIONAL:
+        return set_string_number(obj, target_obj, o, val, dst);
+    case AV_OPT_TYPE_IMAGE_SIZE:
+        return set_string_image_size(obj, o, val, dst);
+    case AV_OPT_TYPE_VIDEO_RATE: {
+        AVRational tmp;
+        ret = set_string_video_rate(obj, o, val, &tmp);
+        if (ret < 0)
+            return ret;
+        return write_number(obj, o, dst, 1, tmp.den, tmp.num);
+    }
+    case AV_OPT_TYPE_PIXEL_FMT:
+        return set_string_pixel_fmt(obj, o, val, dst);
+    case AV_OPT_TYPE_SAMPLE_FMT:
+        return set_string_sample_fmt(obj, o, val, dst);
     case AV_OPT_TYPE_DURATION:
         if (!val) {
             *(int64_t *)dst = 0;
@@ -432,7 +483,8 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
             return ret;
         }
         break;
-    case AV_OPT_TYPE_COLOR:      return set_string_color(obj, o, val, dst);
+    case AV_OPT_TYPE_COLOR:
+        return set_string_color(obj, o, val, dst);
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
         if (!val || !strcmp(val, "none")) {
             *(int64_t *)dst = 0;
@@ -452,13 +504,14 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
     return AVERROR(EINVAL);
 }
 
-#define OPT_EVAL_NUMBER(name, opttype, vartype)\
-    int av_opt_eval_ ## name(void *obj, const AVOption *o, const char *val, vartype *name ## _out)\
-    {\
-        if (!o || o->type != opttype || o->flags & AV_OPT_FLAG_READONLY)\
-            return AVERROR(EINVAL);\
-        return set_string_number(obj, obj, o, val, name ## _out);\
-    }
+#define OPT_EVAL_NUMBER(name, opttype, vartype)                         \
+int av_opt_eval_ ## name(void *obj, const AVOption *o,                  \
+                         const char *val, vartype *name ## _out)        \
+{                                                                       \
+    if (!o || o->type != opttype || o->flags & AV_OPT_FLAG_READONLY)    \
+        return AVERROR(EINVAL);                                         \
+    return set_string_number(obj, obj, o, val, name ## _out);           \
+}
 
 OPT_EVAL_NUMBER(flags,  AV_OPT_TYPE_FLAGS,    int)
 OPT_EVAL_NUMBER(int,    AV_OPT_TYPE_INT,      int)
@@ -468,7 +521,7 @@ OPT_EVAL_NUMBER(double, AV_OPT_TYPE_DOUBLE,   double)
 OPT_EVAL_NUMBER(q,      AV_OPT_TYPE_RATIONAL, AVRational)
 
 static int set_number(void *obj, const char *name, double num, int den, int64_t intnum,
-                                  int search_flags)
+                      int search_flags)
 {
     void *dst, *target_obj;
     const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj);
@@ -479,7 +532,7 @@ static int set_number(void *obj, const char *name, double num, int den, int64_t
     if (o->flags & AV_OPT_FLAG_READONLY)
         return AVERROR(EINVAL);
 
-    dst = ((uint8_t*)target_obj) + o->offset;
+    dst = ((uint8_t *)target_obj) + o->offset;
     return write_number(obj, o, dst, num, den, intnum);
 }
 
@@ -516,11 +569,11 @@ int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int
     if (len && !ptr)
         return AVERROR(ENOMEM);
 
-    dst = (uint8_t **)(((uint8_t *)target_obj) + o->offset);
+    dst    = (uint8_t **)(((uint8_t *)target_obj) + o->offset);
     lendst = (int *)(dst + 1);
 
     av_free(*dst);
-    *dst = ptr;
+    *dst    = ptr;
     *lendst = len;
     if (len)
         memcpy(ptr, val, len);
@@ -622,7 +675,8 @@ int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int searc
     return 0;
 }
 
-int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags)
+int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val,
+                        int search_flags)
 {
     void *target_obj;
     AVDictionary **dst;
@@ -686,24 +740,38 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
     if (!o || !target_obj || (o->offset<=0 && o->type != AV_OPT_TYPE_CONST))
         return AVERROR_OPTION_NOT_FOUND;
 
-    dst = (uint8_t*)target_obj + o->offset;
+    dst = (uint8_t *)target_obj + o->offset;
 
     buf[0] = 0;
     switch (o->type) {
     case AV_OPT_TYPE_BOOL:
         ret = snprintf(buf, sizeof(buf), "%s", (char *)av_x_if_null(get_bool_name(*(int *)dst), "invalid"));
         break;
-    case AV_OPT_TYPE_FLAGS:     ret = snprintf(buf, sizeof(buf), "0x%08X",  *(int    *)dst);break;
-    case AV_OPT_TYPE_INT:       ret = snprintf(buf, sizeof(buf), "%d" ,     *(int    *)dst);break;
-    case AV_OPT_TYPE_INT64:     ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t*)dst);break;
-    case AV_OPT_TYPE_FLOAT:     ret = snprintf(buf, sizeof(buf), "%f" ,     *(float  *)dst);break;
-    case AV_OPT_TYPE_DOUBLE:    ret = snprintf(buf, sizeof(buf), "%f" ,     *(double *)dst);break;
+    case AV_OPT_TYPE_FLAGS:
+        ret = snprintf(buf, sizeof(buf), "0x%08X", *(int *)dst);
+        break;
+    case AV_OPT_TYPE_INT:
+        ret = snprintf(buf, sizeof(buf), "%d", *(int *)dst);
+        break;
+    case AV_OPT_TYPE_INT64:
+        ret = snprintf(buf, sizeof(buf), "%"PRId64, *(int64_t *)dst);
+        break;
+    case AV_OPT_TYPE_FLOAT:
+        ret = snprintf(buf, sizeof(buf), "%f", *(float *)dst);
+        break;
+    case AV_OPT_TYPE_DOUBLE:
+        ret = snprintf(buf, sizeof(buf), "%f", *(double *)dst);
+        break;
     case AV_OPT_TYPE_VIDEO_RATE:
-    case AV_OPT_TYPE_RATIONAL:  ret = snprintf(buf, sizeof(buf), "%d/%d",   ((AVRational*)dst)->num, ((AVRational*)dst)->den);break;
-    case AV_OPT_TYPE_CONST:     ret = snprintf(buf, sizeof(buf), "%f" ,     o->default_val.dbl);break;
+    case AV_OPT_TYPE_RATIONAL:
+        ret = snprintf(buf, sizeof(buf), "%d/%d", ((AVRational *)dst)->num, ((AVRational *)dst)->den);
+        break;
+    case AV_OPT_TYPE_CONST:
+        ret = snprintf(buf, sizeof(buf), "%f", o->default_val.dbl);
+        break;
     case AV_OPT_TYPE_STRING:
-        if (*(uint8_t**)dst) {
-            *out_val = av_strdup(*(uint8_t**)dst);
+        if (*(uint8_t **)dst) {
+            *out_val = av_strdup(*(uint8_t **)dst);
         } else if (search_flags & AV_OPT_ALLOW_NULL) {
             *out_val = NULL;
             return 0;
@@ -712,22 +780,22 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val)
         }
         return *out_val ? 0 : AVERROR(ENOMEM);
     case AV_OPT_TYPE_BINARY:
-        if (!*(uint8_t**)dst && (search_flags & AV_OPT_ALLOW_NULL)) {
+        if (!*(uint8_t **)dst && (search_flags & AV_OPT_ALLOW_NULL)) {
             *out_val = NULL;
             return 0;
         }
-        len = *(int*)(((uint8_t *)dst) + sizeof(uint8_t *));
-        if ((uint64_t)len*2 + 1 > INT_MAX)
+        len = *(int *)(((uint8_t *)dst) + sizeof(uint8_t *));
+        if ((uint64_t)len * 2 + 1 > INT_MAX)
             return AVERROR(EINVAL);
-        if (!(*out_val = av_malloc(len*2 + 1)))
+        if (!(*out_val = av_malloc(len * 2 + 1)))
             return AVERROR(ENOMEM);
         if (!len) {
             *out_val[0] = '\0';
             return 0;
         }
-        bin = *(uint8_t**)dst;
+        bin = *(uint8_t **)dst;
         for (i = 0; i < len; i++)
-            snprintf(*out_val + i*2, 3, "%02X", bin[i]);
+            snprintf(*out_val + i * 2, 3, "%02X", bin[i]);
         return 0;
     case AV_OPT_TYPE_IMAGE_SIZE:
         ret = snprintf(buf, sizeof(buf), "%dx%d", ((int *)dst)[0], ((int *)dst)[1]);
@@ -770,46 +838,47 @@ static int get_number(void *obj, const char *name, const AVOption **o_out, doubl
     if (!o || !target_obj)
         goto error;
 
-    dst = ((uint8_t*)target_obj) + o->offset;
+    dst = ((uint8_t *)target_obj) + o->offset;
 
     if (o_out) *o_out= o;
 
     return read_number(o, dst, num, den, intnum);
 
 error:
-    *den=*intnum=0;
+    *den    =
+    *intnum = 0;
     return -1;
 }
 
 int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_val)
 {
     int64_t intnum = 1;
-    double     num = 1;
-    int   ret, den = 1;
+    double num = 1;
+    int ret, den = 1;
 
     if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
         return ret;
-    *out_val = num*intnum/den;
+    *out_val = num * intnum / den;
     return 0;
 }
 
 int av_opt_get_double(void *obj, const char *name, int search_flags, double *out_val)
 {
     int64_t intnum = 1;
-    double     num = 1;
-    int   ret, den = 1;
+    double num = 1;
+    int ret, den = 1;
 
     if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
         return ret;
-    *out_val = num*intnum/den;
+    *out_val = num * intnum / den;
     return 0;
 }
 
 int av_opt_get_q(void *obj, const char *name, int search_flags, AVRational *out_val)
 {
     int64_t intnum = 1;
-    double     num = 1;
-    int   ret, den = 1;
+    double num = 1;
+    int ret, den = 1;
 
     if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0)
         return ret;
@@ -849,9 +918,9 @@ int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRatio
         return ret;
 
     if (num == 1.0 && (int)intnum == intnum)
-        *out_val = (AVRational){intnum, den};
+        *out_val = (AVRational) { intnum, den };
     else
-        *out_val = av_d2q(num*intnum/den, 1<<24);
+        *out_val = av_d2q(num * intnum / den, 1 << 24);
     return 0;
 }
 
@@ -1000,7 +1069,7 @@ static char *get_opt_flags_string(void *obj, const char *unit, int64_t value)
 static void opt_list(void *obj, void *av_log_obj, const char *unit,
                      int req_flags, int rej_flags)
 {
-    const AVOption *opt=NULL;
+    const AVOption *opt = NULL;
     AVOptionRanges *r;
     int i;
 
@@ -1012,11 +1081,11 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
          * Don't print anything but CONST's on level two.
          * Only print items from the requested unit.
          */
-        if (!unit && opt->type==AV_OPT_TYPE_CONST)
+        if (!unit && opt->type == AV_OPT_TYPE_CONST)
             continue;
-        else if (unit && opt->type!=AV_OPT_TYPE_CONST)
+        else if (unit && opt->type != AV_OPT_TYPE_CONST)
             continue;
-        else if (unit && opt->type==AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
+        else if (unit && opt->type == AV_OPT_TYPE_CONST && strcmp(unit, opt->unit))
             continue;
         else if (unit && opt->type == AV_OPT_TYPE_CONST)
             av_log(av_log_obj, AV_LOG_INFO, "     %-15s ", opt->name);
@@ -1175,9 +1244,8 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit,
         }
 
         av_log(av_log_obj, AV_LOG_INFO, "\n");
-        if (opt->unit && opt->type != AV_OPT_TYPE_CONST) {
+        if (opt->unit && opt->type != AV_OPT_TYPE_CONST)
             opt_list(obj, av_log_obj, opt->unit, req_flags, rej_flags);
-        }
     }
 }
 
@@ -1186,7 +1254,7 @@ int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags)
     if (!obj)
         return -1;
 
-    av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass**)obj)->class_name);
+    av_log(av_log_obj, AV_LOG_INFO, "%s AVOptions:\n", (*(AVClass **)obj)->class_name);
 
     opt_list(obj, av_log_obj, NULL, req_flags, rej_flags);
 
@@ -1213,7 +1281,7 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
         switch (opt->type) {
             case AV_OPT_TYPE_CONST:
                 /* Nothing to be done here */
-            break;
+                break;
             case AV_OPT_TYPE_BOOL:
             case AV_OPT_TYPE_FLAGS:
             case AV_OPT_TYPE_INT:
@@ -1255,8 +1323,9 @@ void av_opt_set_defaults2(void *s, int mask, int flags)
             case AV_OPT_TYPE_DICT:
                 /* Cannot set defaults for these types */
             break;
-            default:
-                av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n", opt->type, opt->name);
+        default:
+            av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n",
+                   opt->type, opt->name);
         }
     }
 }
@@ -1332,7 +1401,7 @@ int av_set_options_string(void *ctx, const char *opts,
     return count;
 }
 
-#define WHITESPACES " \n\t"
+#define WHITESPACES " \n\t\r"
 
 static int is_key_char(char c)
 {
@@ -1546,7 +1615,7 @@ const AVOption *av_opt_find2(void *obj, const char *name, const char *unit,
 
 void *av_opt_child_next(void *obj, void *prev)
 {
-    const AVClass *c = *(AVClass**)obj;
+    const AVClass *c = *(AVClass **)obj;
     if (c->child_next)
         return c->child_next(obj, prev);
     return NULL;
@@ -1572,22 +1641,33 @@ static int opt_size(enum AVOptionType type)
     switch(type) {
     case AV_OPT_TYPE_BOOL:
     case AV_OPT_TYPE_INT:
-    case AV_OPT_TYPE_FLAGS:     return sizeof(int);
+    case AV_OPT_TYPE_FLAGS:
+        return sizeof(int);
     case AV_OPT_TYPE_DURATION:
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
-    case AV_OPT_TYPE_INT64:     return sizeof(int64_t);
-    case AV_OPT_TYPE_DOUBLE:    return sizeof(double);
-    case AV_OPT_TYPE_FLOAT:     return sizeof(float);
-    case AV_OPT_TYPE_STRING:    return sizeof(uint8_t*);
+    case AV_OPT_TYPE_INT64:
+        return sizeof(int64_t);
+    case AV_OPT_TYPE_DOUBLE:
+        return sizeof(double);
+    case AV_OPT_TYPE_FLOAT:
+        return sizeof(float);
+    case AV_OPT_TYPE_STRING:
+        return sizeof(uint8_t*);
     case AV_OPT_TYPE_VIDEO_RATE:
-    case AV_OPT_TYPE_RATIONAL:  return sizeof(AVRational);
-    case AV_OPT_TYPE_BINARY:    return sizeof(uint8_t*) + sizeof(int);
-    case AV_OPT_TYPE_IMAGE_SIZE:return sizeof(int[2]);
-    case AV_OPT_TYPE_PIXEL_FMT: return sizeof(enum AVPixelFormat);
-    case AV_OPT_TYPE_SAMPLE_FMT:return sizeof(enum AVSampleFormat);
-    case AV_OPT_TYPE_COLOR:     return 4;
+    case AV_OPT_TYPE_RATIONAL:
+        return sizeof(AVRational);
+    case AV_OPT_TYPE_BINARY:
+        return sizeof(uint8_t*) + sizeof(int);
+    case AV_OPT_TYPE_IMAGE_SIZE:
+        return sizeof(int[2]);
+    case AV_OPT_TYPE_PIXEL_FMT:
+        return sizeof(enum AVPixelFormat);
+    case AV_OPT_TYPE_SAMPLE_FMT:
+        return sizeof(enum AVSampleFormat);
+    case AV_OPT_TYPE_COLOR:
+        return 4;
     }
-    return 0;
+    return AVERROR(EINVAL);
 }
 
 int av_opt_copy(void *dst, const void *src)
@@ -1597,17 +1677,17 @@ int av_opt_copy(void *dst, const void *src)
     int ret = 0;
 
     if (!src)
-        return 0;
+        return AVERROR(EINVAL);
 
-    c = *(AVClass**)src;
-    if (*(AVClass**)dst && c != *(AVClass**)dst)
+    c = *(AVClass **)src;
+    if (!c || c != *(AVClass **)dst)
         return AVERROR(EINVAL);
 
     while ((o = av_opt_next(src, o))) {
-        void *field_dst = ((uint8_t*)dst) + o->offset;
-        void *field_src = ((uint8_t*)src) + o->offset;
-        uint8_t **field_dst8 = (uint8_t**)field_dst;
-        uint8_t **field_src8 = (uint8_t**)field_src;
+        void *field_dst = (uint8_t *)dst + o->offset;
+        void *field_src = (uint8_t *)src + o->offset;
+        uint8_t **field_dst8 = (uint8_t **)field_dst;
+        uint8_t **field_src8 = (uint8_t **)field_src;
 
         if (o->type == AV_OPT_TYPE_STRING) {
             if (*field_dst8 != *field_src8)
@@ -1616,7 +1696,7 @@ int av_opt_copy(void *dst, const void *src)
             if (*field_src8 && !*field_dst8)
                 ret = AVERROR(ENOMEM);
         } else if (o->type == AV_OPT_TYPE_BINARY) {
-            int len = *(int*)(field_src8 + 1);
+            int len = *(int *)(field_src8 + 1);
             if (*field_dst8 != *field_src8)
                 av_freep(field_dst8);
             *field_dst8 = av_memdup(*field_src8, len);
@@ -1624,7 +1704,7 @@ int av_opt_copy(void *dst, const void *src)
                 ret = AVERROR(ENOMEM);
                 len = 0;
             }
-            *(int*)(field_dst8 + 1) = len;
+            *(int *)(field_dst8 + 1) = len;
         } else if (o->type == AV_OPT_TYPE_CONST) {
             // do nothing
         } else if (o->type == AV_OPT_TYPE_DICT) {
@@ -1637,7 +1717,11 @@ int av_opt_copy(void *dst, const void *src)
             if (av_dict_count(*sdict) != av_dict_count(*ddict))
                 ret = AVERROR(ENOMEM);
         } else {
-            memcpy(field_dst, field_src, opt_size(o->type));
+            int size = opt_size(o->type);
+            if (size < 0)
+                ret = size;
+            else
+                memcpy(field_dst, field_src, size);
         }
     }
     return ret;
@@ -1908,291 +1992,3 @@ int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
     av_bprint_finalize(&bprint, buffer);
     return 0;
 }
-
-#ifdef TEST
-
-typedef struct TestContext
-{
-    const AVClass *class;
-    int num;
-    int toggle;
-    char *string;
-    int flags;
-    AVRational rational;
-    AVRational video_rate;
-    int w, h;
-    enum AVPixelFormat pix_fmt;
-    enum AVSampleFormat sample_fmt;
-    int64_t duration;
-    uint8_t color[4];
-    int64_t channel_layout;
-    void *binary;
-    int binary_size;
-    void *binary1;
-    int binary_size1;
-    void *binary2;
-    int binary_size2;
-    int64_t num64;
-    float flt;
-    double dbl;
-    char *escape;
-    int bool1;
-    int bool2;
-    int bool3;
-} TestContext;
-
-#define OFFSET(x) offsetof(TestContext, x)
-
-#define TEST_FLAG_COOL 01
-#define TEST_FLAG_LAME 02
-#define TEST_FLAG_MU   04
-
-static const AVOption test_options[]= {
-{"num",      "set num",        OFFSET(num),      AV_OPT_TYPE_INT,      {.i64 = 0},       0,        100, 1              },
-{"toggle",   "set toggle",     OFFSET(toggle),   AV_OPT_TYPE_INT,      {.i64 = 1},       0,        1,   1              },
-{"rational", "set rational",   OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 1},       0,        10,  1              },
-{"string",   "set string",     OFFSET(string),   AV_OPT_TYPE_STRING,   {.str = "default"}, CHAR_MIN, CHAR_MAX, 1       },
-{"escape",   "set escape str", OFFSET(escape),   AV_OPT_TYPE_STRING,   {.str = "\\=,"}, CHAR_MIN, CHAR_MAX, 1          },
-{"flags",    "set flags",      OFFSET(flags),    AV_OPT_TYPE_FLAGS,    {.i64 = 1},       0,        INT_MAX, 1, "flags" },
-{"cool",     "set cool flag",  0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_COOL}, INT_MIN,  INT_MAX, 1, "flags" },
-{"lame",     "set lame flag",  0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_LAME}, INT_MIN,  INT_MAX, 1, "flags" },
-{"mu",       "set mu flag",    0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_MU},   INT_MIN,  INT_MAX, 1, "flags" },
-{"size",     "set size",       OFFSET(w),        AV_OPT_TYPE_IMAGE_SIZE,{.str="200x300"},             0,        0, 1},
-{"pix_fmt",  "set pixfmt",     OFFSET(pix_fmt),  AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_0BGR}, -1, INT_MAX, 1},
-{"sample_fmt", "set samplefmt", OFFSET(sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64 = AV_SAMPLE_FMT_S16}, -1, INT_MAX, 1},
-{"video_rate", "set videorate", OFFSET(video_rate), AV_OPT_TYPE_VIDEO_RATE,  {.str = "25"}, 0,     0                   , 1},
-{"duration", "set duration",   OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 1000}, 0, INT64_MAX, 1},
-{"color", "set color",   OFFSET(color), AV_OPT_TYPE_COLOR, {.str = "pink"}, 0, 0, 1},
-{"cl", "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64 = AV_CH_LAYOUT_HEXAGONAL}, 0, INT64_MAX, 1},
-{"bin", "set binary value",    OFFSET(binary),   AV_OPT_TYPE_BINARY,   {.str="62696e00"}, 0,        0, 1 },
-{"bin1", "set binary value",   OFFSET(binary1),  AV_OPT_TYPE_BINARY,   {.str=NULL},       0,        0, 1 },
-{"bin2", "set binary value",   OFFSET(binary2),  AV_OPT_TYPE_BINARY,   {.str=""},         0,        0, 1 },
-{"num64",    "set num 64bit",  OFFSET(num64),    AV_OPT_TYPE_INT64,    {.i64 = 1},        0,        100, 1 },
-{"flt",      "set float",      OFFSET(flt),      AV_OPT_TYPE_FLOAT,    {.dbl = 1.0/3},    0,        100, 1},
-{"dbl",      "set double",     OFFSET(dbl),      AV_OPT_TYPE_DOUBLE,   {.dbl = 1.0/3},    0,        100, 1 },
-{"bool1", "set boolean value",  OFFSET(bool1),   AV_OPT_TYPE_BOOL,     {.i64 = -1},      -1,        1, 1 },
-{"bool2", "set boolean value",  OFFSET(bool2),   AV_OPT_TYPE_BOOL,     {.i64 = 1},       -1,        1, 1 },
-{"bool3", "set boolean value",  OFFSET(bool3),   AV_OPT_TYPE_BOOL,     {.i64 = 0},        0,        1, 1 },
-{NULL},
-};
-
-static const char *test_get_name(void *ctx)
-{
-    return "test";
-}
-
-static const AVClass test_class = {
-    "TestContext",
-    test_get_name,
-    test_options
-};
-
-static void log_callback_help(void *ptr, int level, const char *fmt, va_list vl)
-{
-    vfprintf(stdout, fmt, vl);
-}
-
-int main(void)
-{
-    int i;
-
-    av_log_set_level(AV_LOG_DEBUG);
-    av_log_set_callback(log_callback_help);
-
-    printf("Testing default values\n");
-    {
-        TestContext test_ctx = { 0 };
-        test_ctx.class = &test_class;
-        av_opt_set_defaults(&test_ctx);
-
-        printf("num=%d\n", test_ctx.num);
-        printf("toggle=%d\n", test_ctx.toggle);
-        printf("string=%s\n", test_ctx.string);
-        printf("escape=%s\n", test_ctx.escape);
-        printf("flags=%d\n", test_ctx.flags);
-        printf("rational=%d/%d\n", test_ctx.rational.num, test_ctx.rational.den);
-        printf("video_rate=%d/%d\n", test_ctx.video_rate.num, test_ctx.video_rate.den);
-        printf("width=%d height=%d\n", test_ctx.w, test_ctx.h);
-        printf("pix_fmt=%s\n", av_get_pix_fmt_name(test_ctx.pix_fmt));
-        printf("sample_fmt=%s\n", av_get_sample_fmt_name(test_ctx.sample_fmt));
-        printf("duration=%"PRId64"\n", test_ctx.duration);
-        printf("color=%d %d %d %d\n", test_ctx.color[0], test_ctx.color[1], test_ctx.color[2], test_ctx.color[3]);
-        printf("channel_layout=%"PRId64"=%"PRId64"\n", test_ctx.channel_layout, (int64_t)AV_CH_LAYOUT_HEXAGONAL);
-        if (test_ctx.binary)
-            printf("binary=%x %x %x %x\n", ((uint8_t*)test_ctx.binary)[0], ((uint8_t*)test_ctx.binary)[1], ((uint8_t*)test_ctx.binary)[2], ((uint8_t*)test_ctx.binary)[3]);
-        printf("binary_size=%d\n", test_ctx.binary_size);
-        printf("num64=%"PRId64"\n", test_ctx.num64);
-        printf("flt=%.6f\n", test_ctx.flt);
-        printf("dbl=%.6f\n", test_ctx.dbl);
-
-        av_opt_show2(&test_ctx, NULL, -1, 0);
-
-        av_opt_free(&test_ctx);
-    }
-
-    printf("\nTesting av_opt_is_set_to_default()\n");
-    {
-        int ret;
-        TestContext test_ctx = { 0 };
-        const AVOption *o = NULL;
-        test_ctx.class = &test_class;
-
-        av_log_set_level(AV_LOG_QUIET);
-
-        while (o = av_opt_next(&test_ctx, o)) {
-            ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0);
-            printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : "");
-        }
-        av_opt_set_defaults(&test_ctx);
-        while (o = av_opt_next(&test_ctx, o)) {
-            ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0);
-            printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : "");
-        }
-        av_opt_free(&test_ctx);
-    }
-
-    printf("\nTest av_opt_serialize()\n");
-    {
-        TestContext test_ctx = { 0 };
-        char *buf;
-        test_ctx.class = &test_class;
-
-        av_log_set_level(AV_LOG_QUIET);
-
-        av_opt_set_defaults(&test_ctx);
-        if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
-            printf("%s\n", buf);
-            av_opt_free(&test_ctx);
-            memset(&test_ctx, 0, sizeof(test_ctx));
-            test_ctx.class = &test_class;
-            av_set_options_string(&test_ctx, buf, "=", ",");
-            av_free(buf);
-            if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
-                printf("%s\n", buf);
-                av_free(buf);
-            }
-        }
-        av_opt_free(&test_ctx);
-    }
-
-    printf("\nTesting av_set_options_string()\n");
-    {
-        TestContext test_ctx = { 0 };
-        static const char * const options[] = {
-            "",
-            ":",
-            "=",
-            "foo=:",
-            ":=foo",
-            "=foo",
-            "foo=",
-            "foo",
-            "foo=val",
-            "foo==val",
-            "toggle=:",
-            "string=:",
-            "toggle=1 : foo",
-            "toggle=100",
-            "toggle==1",
-            "flags=+mu-lame : num=42: toggle=0",
-            "num=42 : string=blahblah",
-            "rational=0 : rational=1/2 : rational=1/-1",
-            "rational=-1/0",
-            "size=1024x768",
-            "size=pal",
-            "size=bogus",
-            "pix_fmt=yuv420p",
-            "pix_fmt=2",
-            "pix_fmt=bogus",
-            "sample_fmt=s16",
-            "sample_fmt=2",
-            "sample_fmt=bogus",
-            "video_rate=pal",
-            "video_rate=25",
-            "video_rate=30000/1001",
-            "video_rate=30/1.001",
-            "video_rate=bogus",
-            "duration=bogus",
-            "duration=123.45",
-            "duration=1\\:23\\:45.67",
-            "color=blue",
-            "color=0x223300",
-            "color=0x42FF07AA",
-            "cl=stereo+downmix",
-            "cl=foo",
-            "bin=boguss",
-            "bin=111",
-            "bin=ffff",
-            "num64=bogus",
-            "num64=44",
-            "num64=44.4",
-            "num64=-1",
-            "num64=101",
-            "flt=bogus",
-            "flt=2",
-            "flt=2.2",
-            "flt=-1",
-            "flt=101",
-            "dbl=bogus",
-            "dbl=2",
-            "dbl=2.2",
-            "dbl=-1",
-            "dbl=101",
-            "bool1=true",
-            "bool2=auto",
-        };
-
-        test_ctx.class = &test_class;
-        av_opt_set_defaults(&test_ctx);
-
-        av_log_set_level(AV_LOG_QUIET);
-
-        for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
-            int silence_log = !strcmp(options[i], "rational=-1/0"); // inf formating differs between platforms
-            av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
-            if (silence_log)
-                av_log_set_callback(NULL);
-            if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
-                printf("Error '%s'\n", options[i]);
-            else
-                printf("OK    '%s'\n", options[i]);
-            av_log_set_callback(log_callback_help);
-        }
-        av_opt_free(&test_ctx);
-    }
-
-    printf("\nTesting av_opt_set_from_string()\n");
-    {
-        TestContext test_ctx = { 0 };
-        static const char * const options[] = {
-            "",
-            "5",
-            "5:hello",
-            "5:hello:size=pal",
-            "5:size=pal:hello",
-            ":",
-            "=",
-            " 5 : hello : size = pal ",
-            "a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42"
-        };
-        static const char * const shorthand[] = { "num", "string", NULL };
-
-        test_ctx.class = &test_class;
-        av_opt_set_defaults(&test_ctx);
-
-        av_log_set_level(AV_LOG_QUIET);
-
-        for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
-            av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
-            if (av_opt_set_from_string(&test_ctx, options[i], shorthand, "=", ":") < 0)
-                printf("Error '%s'\n", options[i]);
-            else
-                printf("OK    '%s'\n", options[i]);
-        }
-        av_opt_free(&test_ctx);
-    }
-
-    return 0;
-}
-
-#endif
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 753434d..9a76a47 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -281,7 +281,7 @@ typedef struct AVOption {
 #define AV_OPT_FLAG_VIDEO_PARAM     16
 #define AV_OPT_FLAG_SUBTITLE_PARAM  32
 /**
- * The option is inteded for exporting values to the caller.
+ * The option is intended for exporting values to the caller.
  */
 #define AV_OPT_FLAG_EXPORT          64
 /**
diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c
index 0097bec..a4efd79 100644
--- a/libavutil/parseutils.c
+++ b/libavutil/parseutils.c
@@ -739,192 +739,3 @@ int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info
     }
     return 0;
 }
-
-#ifdef TEST
-
-static uint32_t randomv = MKTAG('L','A','V','U');
-
-static uint32_t av_get_random_seed_deterministic(void)
-{
-    return randomv = randomv * 1664525 + 1013904223;
-}
-
-int main(void)
-{
-    printf("Testing av_parse_video_rate()\n");
-    {
-        int i;
-        static const char *const rates[] = {
-            "-inf",
-            "inf",
-            "nan",
-            "123/0",
-            "-123 / 0",
-            "",
-            "/",
-            " 123  /  321",
-            "foo/foo",
-            "foo/1",
-            "1/foo",
-            "0/0",
-            "/0",
-            "1/",
-            "1",
-            "0",
-            "-123/123",
-            "-foo",
-            "123.23",
-            ".23",
-            "-.23",
-            "-0.234",
-            "-0.0000001",
-            "  21332.2324   ",
-            " -21332.2324   ",
-        };
-
-        for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
-            int ret;
-            AVRational q = { 0, 0 };
-            ret = av_parse_video_rate(&q, rates[i]);
-            printf("'%s' -> %d/%d %s\n",
-                   rates[i], q.num, q.den, ret ? "ERROR" : "OK");
-        }
-    }
-
-    printf("\nTesting av_parse_color()\n");
-    {
-        int i;
-        uint8_t rgba[4];
-        static const char *const color_names[] = {
-            "bikeshed",
-            "RaNdOm",
-            "foo",
-            "red",
-            "Red ",
-            "RED",
-            "Violet",
-            "Yellow",
-            "Red",
-            "0x000000",
-            "0x0000000",
-            "0xff000000",
-            "0x3e34ff",
-            "0x3e34ffaa",
-            "0xffXXee",
-            "0xfoobar",
-            "0xffffeeeeeeee",
-            "#ff0000",
-            "#ffXX00",
-            "ff0000",
-            "ffXX00",
-            "red at foo",
-            "random at 10",
-            "0xff0000 at 1.0",
-            "red@",
-            "red at 0xfff",
-            "red at 0xf",
-            "red at 2",
-            "red at 0.1",
-            "red at -1",
-            "red at 0.5",
-            "red at 1.0",
-            "red at 256",
-            "red at 10foo",
-            "red at -1.0",
-            "red at -0.0",
-        };
-
-        av_log_set_level(AV_LOG_DEBUG);
-
-        for (i = 0;  i < FF_ARRAY_ELEMS(color_names); i++) {
-            if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
-                printf("%s -> R(%d) G(%d) B(%d) A(%d)\n",
-                       color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
-            else
-                printf("%s -> error\n", color_names[i]);
-        }
-    }
-
-    printf("\nTesting av_small_strptime()\n");
-    {
-        int i;
-        struct tm tm = { 0 };
-        struct fmt_timespec_entry {
-            const char *fmt, *timespec;
-        } fmt_timespec_entries[] = {
-            { "%Y-%m-%d",                    "2012-12-21" },
-            { "%Y - %m - %d",                "2012-12-21" },
-            { "%Y-%m-%d %H:%M:%S",           "2012-12-21 20:12:21" },
-            { "  %Y - %m - %d %H : %M : %S", "   2012 - 12 -  21   20 : 12 : 21" },
-        };
-
-        av_log_set_level(AV_LOG_DEBUG);
-        for (i = 0;  i < FF_ARRAY_ELEMS(fmt_timespec_entries); i++) {
-            char *p;
-            struct fmt_timespec_entry *e = &fmt_timespec_entries[i];
-            printf("fmt:'%s' spec:'%s' -> ", e->fmt, e->timespec);
-            p = av_small_strptime(e->timespec, e->fmt, &tm);
-            if (p) {
-                printf("%04d-%02d-%2d %02d:%02d:%02d\n",
-                       1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
-                       tm.tm_hour, tm.tm_min, tm.tm_sec);
-            } else {
-                printf("error\n");
-            }
-        }
-    }
-
-    printf("\nTesting av_parse_time()\n");
-    {
-        int i;
-        int64_t tv;
-        time_t tvi;
-        struct tm *tm;
-        static char tzstr[] = "TZ=CET-1";
-        static const char * const time_string[] = {
-            "now",
-            "12:35:46",
-            "2000-12-20 0:02:47.5z",
-            "2012 - 02-22  17:44:07",
-            "2000-12-20T010247.6",
-            "2000-12-12 1:35:46+05:30",
-            "2002-12-12 22:30:40-02",
-        };
-        static const char * const duration_string[] = {
-            "2:34:56.79",
-            "-1:23:45.67",
-            "42.1729",
-            "-1729.42",
-            "12:34",
-        };
-
-        av_log_set_level(AV_LOG_DEBUG);
-        putenv(tzstr);
-        printf("(now is 2012-03-17 09:14:13.2 +0100, local time is UTC+1)\n");
-        for (i = 0;  i < FF_ARRAY_ELEMS(time_string); i++) {
-            printf("%-24s -> ", time_string[i]);
-            if (av_parse_time(&tv, time_string[i], 0)) {
-                printf("error\n");
-            } else {
-                tvi = tv / 1000000;
-                tm = gmtime(&tvi);
-                printf("%14"PRIi64".%06d = %04d-%02d-%02dT%02d:%02d:%02dZ\n",
-                       tv / 1000000, (int)(tv % 1000000),
-                       tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
-                       tm->tm_hour, tm->tm_min, tm->tm_sec);
-            }
-        }
-        for (i = 0;  i < FF_ARRAY_ELEMS(duration_string); i++) {
-            printf("%-24s -> ", duration_string[i]);
-            if (av_parse_time(&tv, duration_string[i], 1)) {
-                printf("error\n");
-            } else {
-                printf("%+21"PRIi64"\n", tv);
-            }
-        }
-    }
-
-    return 0;
-}
-
-#endif /* TEST */
diff --git a/libavutil/pca.c b/libavutil/pca.c
index 1d88ff3..4e52c7b 100644
--- a/libavutil/pca.c
+++ b/libavutil/pca.c
@@ -171,86 +171,3 @@ int ff_pca(PCA *pca, double *eigenvector, double *eigenvalue){
 
     return -1;
 }
-
-#ifdef TEST
-
-#undef printf
-#include <stdio.h>
-#include <stdlib.h>
-#include "lfg.h"
-
-int main(void){
-    PCA *pca;
-    int i, j, k;
-#define LEN 8
-    double eigenvector[LEN*LEN];
-    double eigenvalue[LEN];
-    AVLFG prng;
-
-    av_lfg_init(&prng, 1);
-
-    pca= ff_pca_init(LEN);
-
-    for(i=0; i<9000000; i++){
-        double v[2*LEN+100];
-        double sum=0;
-        int pos = av_lfg_get(&prng) % LEN;
-        int v2  = av_lfg_get(&prng) % 101 - 50;
-        v[0]    = av_lfg_get(&prng) % 101 - 50;
-        for(j=1; j<8; j++){
-            if(j<=pos) v[j]= v[0];
-            else       v[j]= v2;
-            sum += v[j];
-        }
-/*        for(j=0; j<LEN; j++){
-            v[j] -= v[pos];
-        }*/
-//        sum += av_lfg_get(&prng) % 10;
-/*        for(j=0; j<LEN; j++){
-            v[j] -= sum/LEN;
-        }*/
-//        lbt1(v+100,v+100,LEN);
-        ff_pca_add(pca, v);
-    }
-
-
-    ff_pca(pca, eigenvector, eigenvalue);
-    for(i=0; i<LEN; i++){
-        pca->count= 1;
-        pca->mean[i]= 0;
-
-//        (0.5^|x|)^2 = 0.5^2|x| = 0.25^|x|
-
-
-//        pca.covariance[i + i*LEN]= pow(0.5, fabs
-        for(j=i; j<LEN; j++){
-            printf("%f ", pca->covariance[i + j*LEN]);
-        }
-        printf("\n");
-    }
-
-    for(i=0; i<LEN; i++){
-        double v[LEN];
-        double error=0;
-        memset(v, 0, sizeof(v));
-        for(j=0; j<LEN; j++){
-            for(k=0; k<LEN; k++){
-                v[j] += pca->covariance[FFMIN(k,j) + FFMAX(k,j)*LEN] * eigenvector[i + k*LEN];
-            }
-            v[j] /= eigenvalue[i];
-            error += fabs(v[j] - eigenvector[i + j*LEN]);
-        }
-        printf("%f ", error);
-    }
-    printf("\n");
-
-    for(i=0; i<LEN; i++){
-        for(j=0; j<LEN; j++){
-            printf("%9.6f ", eigenvector[i + j*LEN]);
-        }
-        printf("  %9.1f %f\n", eigenvalue[i], eigenvalue[i]/eigenvalue[0]);
-    }
-
-    return 0;
-}
-#endif
diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
index dd7de7e..0dffa4d 100644
--- a/libavutil/pixdesc.c
+++ b/libavutil/pixdesc.c
@@ -1978,6 +1978,10 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
         .name = "mmal",
         .flags = AV_PIX_FMT_FLAG_HWACCEL,
     },
+    [AV_PIX_FMT_CUDA] = {
+        .name = "cuda",
+        .flags = AV_PIX_FMT_FLAG_HWACCEL,
+    },
     [AV_PIX_FMT_AYUV64LE] = {
         .name = "ayuv64le",
         .nb_components = 4,
@@ -2028,6 +2032,62 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
         },
         .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE,
     },
+    [AV_PIX_FMT_GBRAP12LE] = {
+        .name = "gbrap12le",
+        .nb_components = 4,
+        .log2_chroma_w = 0,
+        .log2_chroma_h = 0,
+        .comp = {
+            { 2, 2, 0, 0, 12, 1, 11, 1 },       /* R */
+            { 0, 2, 0, 0, 12, 1, 11, 1 },       /* G */
+            { 1, 2, 0, 0, 12, 1, 11, 1 },       /* B */
+            { 3, 2, 0, 0, 12, 1, 11, 1 },       /* A */
+        },
+        .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB |
+                 AV_PIX_FMT_FLAG_ALPHA,
+    },
+    [AV_PIX_FMT_GBRAP12BE] = {
+        .name = "gbrap12be",
+        .nb_components = 4,
+        .log2_chroma_w = 0,
+        .log2_chroma_h = 0,
+        .comp = {
+            { 2, 2, 0, 0, 12, 1, 11, 1 },       /* R */
+            { 0, 2, 0, 0, 12, 1, 11, 1 },       /* G */
+            { 1, 2, 0, 0, 12, 1, 11, 1 },       /* B */
+            { 3, 2, 0, 0, 12, 1, 11, 1 },       /* A */
+        },
+        .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR |
+                 AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA,
+    },
+    [AV_PIX_FMT_GBRAP10LE] = {
+        .name = "gbrap10le",
+        .nb_components = 4,
+        .log2_chroma_w = 0,
+        .log2_chroma_h = 0,
+        .comp = {
+            { 2, 2, 0, 0, 10, 1, 9, 1 },       /* R */
+            { 0, 2, 0, 0, 10, 1, 9, 1 },       /* G */
+            { 1, 2, 0, 0, 10, 1, 9, 1 },       /* B */
+            { 3, 2, 0, 0, 10, 1, 9, 1 },       /* A */
+        },
+        .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB |
+                 AV_PIX_FMT_FLAG_ALPHA,
+    },
+    [AV_PIX_FMT_GBRAP10BE] = {
+        .name = "gbrap10be",
+        .nb_components = 4,
+        .log2_chroma_w = 0,
+        .log2_chroma_h = 0,
+        .comp = {
+            { 2, 2, 0, 0, 10, 1, 9, 1 },       /* R */
+            { 0, 2, 0, 0, 10, 1, 9, 1 },       /* G */
+            { 1, 2, 0, 0, 10, 1, 9, 1 },       /* B */
+            { 3, 2, 0, 0, 10, 1, 9, 1 },       /* A */
+        },
+        .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR |
+                 AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA,
+    },
 };
 #if FF_API_PLUS1_MINUS1
 FF_ENABLE_DEPRECATION_WARNINGS
@@ -2048,6 +2108,7 @@ static const char *color_transfer_names[AVCOL_TRC_NB] = {
     "bt470bg", "smpte170m", "smpte240m", "linear", "log100",
     "log316", "iec61966-2-4", "bt1361e", "iec61966-2-1",
     "bt2020-10", "bt2020-20", "smpte2084", "smpte428-1",
+    "arib-std-b67"
 };
 
 static const char *color_space_names[AVCOL_SPC_NB] = {
@@ -2061,7 +2122,6 @@ static const char *chroma_location_names[AVCHROMA_LOC_NB] = {
     "top", "bottomleft", "bottom",
 };
 
-FF_DISABLE_DEPRECATION_WARNINGS
 static enum AVPixelFormat get_pix_fmt_internal(const char *name)
 {
     enum AVPixelFormat pix_fmt;
@@ -2103,6 +2163,11 @@ enum AVPixelFormat av_get_pix_fmt(const char *name)
         snprintf(name2, sizeof(name2), "%s%s", name, X_NE("be", "le"));
         pix_fmt = get_pix_fmt_internal(name2);
     }
+
+#if FF_API_VAAPI
+    if (pix_fmt == AV_PIX_FMT_NONE && !strcmp(name, "vaapi"))
+        pix_fmt = AV_PIX_FMT_VAAPI;
+#endif
     return pix_fmt;
 }
 
@@ -2249,7 +2314,6 @@ void ff_check_pixfmt_descriptors(void){
         }
     }
 }
-FF_ENABLE_DEPRECATION_WARNINGS
 
 
 enum AVPixelFormat av_pix_fmt_swap_endianness(enum AVPixelFormat pix_fmt)
@@ -2497,32 +2561,3 @@ const char *av_chroma_location_name(enum AVChromaLocation location)
     return (unsigned) location < AVCHROMA_LOC_NB ?
         chroma_location_names[location] : NULL;
 }
-
-#ifdef TEST
-
-int main(void){
-    int i;
-    int err=0;
-    int skip = 0;
-
-    for (i=0; i<AV_PIX_FMT_NB*2; i++) {
-        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i);
-        if(!desc || !desc->name) {
-            skip ++;
-            continue;
-        }
-        if (skip) {
-            av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip);
-            skip = 0;
-        }
-        av_log(NULL, AV_LOG_INFO, "pix fmt %s avg_bpp:%d colortype:%d\n", desc->name, av_get_padded_bits_per_pixel(desc), get_color_type(desc));
-        if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) {
-            av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n");
-            err = 1;
-        }
-    }
-    return err;
-}
-
-#endif
-
diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h
index b1d218d..3b0bcdb 100644
--- a/libavutil/pixdesc.h
+++ b/libavutil/pixdesc.h
@@ -85,16 +85,16 @@ typedef struct AVPixFmtDescriptor {
     /**
      * Amount to shift the luma width right to find the chroma width.
      * For YV12 this is 1 for example.
-     * chroma_width = -((-luma_width) >> log2_chroma_w)
+     * chroma_width = AV_CEIL_RSHIFT(luma_width, log2_chroma_w)
      * The note above is needed to ensure rounding up.
      * This value only refers to the chroma components.
      */
-    uint8_t log2_chroma_w;  ///< chroma_width = -((-luma_width )>>log2_chroma_w)
+    uint8_t log2_chroma_w;
 
     /**
      * Amount to shift the luma height right to find the chroma height.
      * For YV12 this is 1 for example.
-     * chroma_height= -((-luma_height) >> log2_chroma_h)
+     * chroma_height= AV_CEIL_RSHIFT(luma_height, log2_chroma_h)
      * The note above is needed to ensure rounding up.
      * This value only refers to the chroma components.
      */
diff --git a/libavutil/pixelutils.c b/libavutil/pixelutils.c
index 1ec4fbb..b663027 100644
--- a/libavutil/pixelutils.c
+++ b/libavutil/pixelutils.c
@@ -85,138 +85,3 @@ av_pixelutils_sad_fn av_pixelutils_get_sad_fn(int w_bits, int h_bits, int aligne
     return sad[w_bits - 1];
 #endif
 }
-
-#ifdef TEST
-#define W1 320
-#define H1 240
-#define W2 640
-#define H2 480
-
-static int run_single_test(const char *test,
-                           const uint8_t *block1, ptrdiff_t stride1,
-                           const uint8_t *block2, ptrdiff_t stride2,
-                           int align, int n)
-{
-    int out, ref;
-    av_pixelutils_sad_fn f_ref = sad_c[n - 1];
-    av_pixelutils_sad_fn f_out = av_pixelutils_get_sad_fn(n, n, align, NULL);
-
-    switch (align) {
-    case 0: block1++; block2++; break;
-    case 1:           block2++; break;
-    case 2:                     break;
-    }
-
-    out = f_out(block1, stride1, block2, stride2);
-    ref = f_ref(block1, stride1, block2, stride2);
-    printf("[%s] [%c%c] SAD [%s] %dx%d=%d ref=%d\n",
-           out == ref ? "OK" : "FAIL",
-           align ? 'A' : 'U', align == 2 ? 'A' : 'U',
-           test, 1<<n, 1<<n, out, ref);
-    return out != ref;
-}
-
-static int run_test(const char *test,
-                    const uint8_t *b1, const uint8_t *b2)
-{
-    int i, a, ret = 0;
-
-    for (a = 0; a < 3; a++) {
-        const uint8_t *block1 = b1;
-        const uint8_t *block2 = b2;
-
-        switch (a) {
-        case 0: block1++; block2++; break;
-        case 1:           block2++; break;
-        case 2:                     break;
-        }
-        for (i = 1; i <= FF_ARRAY_ELEMS(sad_c); i++) {
-            int r = run_single_test(test, b1, W1, b2, W2, a, i);
-            if (r)
-                ret = r;
-        }
-    }
-    return ret;
-}
-
-int main(void)
-{
-    int i, align, ret;
-    uint8_t *buf1 = av_malloc(W1*H1);
-    uint8_t *buf2 = av_malloc(W2*H2);
-    uint32_t state = 0;
-
-    if (!buf1 || !buf2) {
-        fprintf(stderr, "malloc failure\n");
-        ret = 1;
-        goto end;
-    }
-
-    ff_check_pixfmt_descriptors();
-
-#define RANDOM_INIT(buf, size) do {             \
-    int k;                                      \
-    for (k = 0; k < size; k++) {                \
-        state = state * 1664525 + 1013904223;   \
-        buf[k] = state>>24;                     \
-    }                                           \
-} while (0)
-
-    /* Normal test with different strides */
-    RANDOM_INIT(buf1, W1*H1);
-    RANDOM_INIT(buf2, W2*H2);
-    ret = run_test("random", buf1, buf2);
-    if (ret < 0)
-        goto end;
-
-    /* Check for maximum SAD */
-    memset(buf1, 0xff, W1*H1);
-    memset(buf2, 0x00, W2*H2);
-    ret = run_test("max", buf1, buf2);
-    if (ret < 0)
-        goto end;
-
-    /* Check for minimum SAD */
-    memset(buf1, 0x90, W1*H1);
-    memset(buf2, 0x90, W2*H2);
-    ret = run_test("min", buf1, buf2);
-    if (ret < 0)
-        goto end;
-
-    /* Exact buffer sizes, to check for overreads */
-    for (i = 1; i <= 4; i++) {
-        for (align = 0; align < 3; align++) {
-            int size1, size2;
-
-            av_freep(&buf1);
-            av_freep(&buf2);
-
-            size1 = size2 = 1 << (i << 1);
-
-            switch (align) {
-            case 0: size1++; size2++; break;
-            case 1:          size2++; break;
-            case 2:                   break;
-            }
-
-            buf1 = av_malloc(size1);
-            buf2 = av_malloc(size2);
-            if (!buf1 || !buf2) {
-                fprintf(stderr, "malloc failure\n");
-                ret = 1;
-                goto end;
-            }
-            RANDOM_INIT(buf1, size1);
-            RANDOM_INIT(buf2, size2);
-            ret = run_single_test("small", buf1, 1<<i, buf2, 1<<i, align, i);
-            if (ret < 0)
-                goto end;
-        }
-    }
-
-end:
-    av_free(buf1);
-    av_free(buf2);
-    return ret;
-}
-#endif /* TEST */
diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
index c01c057..0ed01c4 100644
--- a/libavutil/pixfmt.h
+++ b/libavutil/pixfmt.h
@@ -24,7 +24,6 @@
 /**
  * @file
  * pixel format definitions
- *
  */
 
 #include "libavutil/avconfig.h"
@@ -54,7 +53,7 @@
  * to run on the IBM VGA graphics adapter use 6-bit palette components.
  *
  * @par
- * For all the 8bit per pixel formats, an RGB32 palette is in data[1] like
+ * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like
  * for pal8. This palette is filled in automatically by the function
  * allocating the picture.
  */
@@ -71,7 +70,7 @@ enum AVPixelFormat {
     AV_PIX_FMT_GRAY8,     ///<        Y        ,  8bpp
     AV_PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
     AV_PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
-    AV_PIX_FMT_PAL8,      ///< 8 bit with AV_PIX_FMT_RGB32 palette
+    AV_PIX_FMT_PAL8,      ///< 8 bits with AV_PIX_FMT_RGB32 palette
     AV_PIX_FMT_YUVJ420P,  ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range
     AV_PIX_FMT_YUVJ422P,  ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range
     AV_PIX_FMT_YUVJ444P,  ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range
@@ -126,7 +125,7 @@ enum AVPixelFormat {
     /**@{*/
     AV_PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
     AV_PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
-    AV_PIX_FMT_VAAPI_VLD,  ///< HW decoding through VA API, Picture.data[3] contains a vaapi_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+    AV_PIX_FMT_VAAPI_VLD,  ///< HW decoding through VA API, Picture.data[3] contains a VASurfaceID
     /**@}*/
     AV_PIX_FMT_VAAPI = AV_PIX_FMT_VAAPI_VLD,
 #else
@@ -144,7 +143,7 @@ enum AVPixelFormat {
     AV_PIX_FMT_YUV444P16LE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
     AV_PIX_FMT_YUV444P16BE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
 #if FF_API_VDPAU
-    AV_PIX_FMT_VDPAU_MPEG4,  ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+    AV_PIX_FMT_VDPAU_MPEG4,  ///< MPEG-4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
 #endif
     AV_PIX_FMT_DXVA2_VLD,    ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
 
@@ -152,7 +151,7 @@ enum AVPixelFormat {
     AV_PIX_FMT_RGB444BE,  ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian,    X=unused/undefined
     AV_PIX_FMT_BGR444LE,  ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined
     AV_PIX_FMT_BGR444BE,  ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian,    X=unused/undefined
-    AV_PIX_FMT_YA8,       ///< 8bit gray, 8bit alpha
+    AV_PIX_FMT_YA8,       ///< 8 bits gray, 8 bits alpha
 
     AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8
     AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8
@@ -223,8 +222,8 @@ enum AVPixelFormat {
 
     AV_PIX_FMT_VDA,          ///< HW acceleration through VDA, data[3] contains a CVPixelBufferRef
 
-    AV_PIX_FMT_YA16BE,       ///< 16bit gray, 16bit alpha (big-endian)
-    AV_PIX_FMT_YA16LE,       ///< 16bit gray, 16bit alpha (little-endian)
+    AV_PIX_FMT_YA16BE,       ///< 16 bits gray, 16 bits alpha (big-endian)
+    AV_PIX_FMT_YA16LE,       ///< 16 bits gray, 16 bits alpha (little-endian)
 
     AV_PIX_FMT_GBRAP,        ///< planar GBRA 4:4:4:4 32bpp
     AV_PIX_FMT_GBRAP16BE,    ///< planar GBRA 4:4:4:4 64bpp, big-endian
@@ -242,6 +241,12 @@ enum AVPixelFormat {
 
     AV_PIX_FMT_D3D11VA_VLD,  ///< HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
 
+    /**
+     * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers
+     * exactly as for system memory frames.
+     */
+    AV_PIX_FMT_CUDA,
+
     AV_PIX_FMT_0RGB=0x123+4,///< packed RGB 8:8:8, 32bpp, XRGBXRGB...   X=unused/undefined
     AV_PIX_FMT_RGB0,        ///< packed RGB 8:8:8, 32bpp, RGBXRGBX...   X=unused/undefined
     AV_PIX_FMT_0BGR,        ///< packed BGR 8:8:8, 32bpp, XBGRXBGR...   X=unused/undefined
@@ -292,6 +297,12 @@ enum AVPixelFormat {
     AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian
     AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian
 
+    AV_PIX_FMT_GBRAP12BE,  ///< planar GBR 4:4:4:4 48bpp, big-endian
+    AV_PIX_FMT_GBRAP12LE,  ///< planar GBR 4:4:4:4 48bpp, little-endian
+
+    AV_PIX_FMT_GBRAP10BE,  ///< planar GBR 4:4:4:4 40bpp, big-endian
+    AV_PIX_FMT_GBRAP10LE,  ///< planar GBR 4:4:4:4 40bpp, little-endian
+
     AV_PIX_FMT_NB,        ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
 };
 
@@ -347,6 +358,8 @@ enum AVPixelFormat {
 #define AV_PIX_FMT_GBRP12    AV_PIX_FMT_NE(GBRP12BE,    GBRP12LE)
 #define AV_PIX_FMT_GBRP14    AV_PIX_FMT_NE(GBRP14BE,    GBRP14LE)
 #define AV_PIX_FMT_GBRP16    AV_PIX_FMT_NE(GBRP16BE,    GBRP16LE)
+#define AV_PIX_FMT_GBRAP10   AV_PIX_FMT_NE(GBRAP10BE,   GBRAP10LE)
+#define AV_PIX_FMT_GBRAP12   AV_PIX_FMT_NE(GBRAP12BE,   GBRAP12LE)
 #define AV_PIX_FMT_GBRAP16   AV_PIX_FMT_NE(GBRAP16BE,   GBRAP16LE)
 
 #define AV_PIX_FMT_BAYER_BGGR16 AV_PIX_FMT_NE(BAYER_BGGR16BE,    BAYER_BGGR16LE)
@@ -407,10 +420,11 @@ enum AVColorTransferCharacteristic {
     AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4
     AVCOL_TRC_BT1361_ECG   = 12, ///< ITU-R BT1361 Extended Colour Gamut
     AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)
-    AVCOL_TRC_BT2020_10    = 14, ///< ITU-R BT2020 for 10 bit system
-    AVCOL_TRC_BT2020_12    = 15, ///< ITU-R BT2020 for 12 bit system
-    AVCOL_TRC_SMPTEST2084  = 16, ///< SMPTE ST 2084 for 10, 12, 14 and 16 bit systems
+    AVCOL_TRC_BT2020_10    = 14, ///< ITU-R BT2020 for 10-bit system
+    AVCOL_TRC_BT2020_12    = 15, ///< ITU-R BT2020 for 12-bit system
+    AVCOL_TRC_SMPTEST2084  = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems
     AVCOL_TRC_SMPTEST428_1 = 17, ///< SMPTE ST 428-1
+    AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"
     AVCOL_TRC_NB,                ///< Not part of ABI
 };
 
@@ -424,8 +438,8 @@ enum AVColorSpace {
     AVCOL_SPC_RESERVED    = 3,
     AVCOL_SPC_FCC         = 4,  ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
     AVCOL_SPC_BT470BG     = 5,  ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
-    AVCOL_SPC_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
-    AVCOL_SPC_SMPTE240M   = 7,
+    AVCOL_SPC_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
+    AVCOL_SPC_SMPTE240M   = 7,  ///< functionally identical to above
     AVCOL_SPC_YCOCG       = 8,  ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
     AVCOL_SPC_BT2020_NCL  = 9,  ///< ITU-R BT2020 non-constant luminance system
     AVCOL_SPC_BT2020_CL   = 10, ///< ITU-R BT2020 constant luminance system
@@ -461,8 +475,8 @@ enum AVColorRange {
  */
 enum AVChromaLocation {
     AVCHROMA_LOC_UNSPECIFIED = 0,
-    AVCHROMA_LOC_LEFT        = 1, ///< mpeg2/4 4:2:0, h264 default for 4:2:0
-    AVCHROMA_LOC_CENTER      = 2, ///< mpeg1 4:2:0, jpeg 4:2:0, h263 4:2:0
+    AVCHROMA_LOC_LEFT        = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0
+    AVCHROMA_LOC_CENTER      = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0
     AVCHROMA_LOC_TOPLEFT     = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2
     AVCHROMA_LOC_TOP         = 4,
     AVCHROMA_LOC_BOTTOMLEFT  = 5,
diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c
index 0821550..d1ded7b 100644
--- a/libavutil/random_seed.c
+++ b/libavutil/random_seed.c
@@ -136,29 +136,3 @@ uint32_t av_get_random_seed(void)
         return seed;
     return get_generic_seed();
 }
-
-#if TEST
-#undef printf
-#define N 256
-#include <stdio.h>
-
-int main(void)
-{
-    int i, j, retry;
-    uint32_t seeds[N];
-
-    for (retry=0; retry<3; retry++){
-        for (i=0; i<N; i++){
-            seeds[i] = av_get_random_seed();
-            for (j=0; j<i; j++)
-                if (seeds[j] == seeds[i])
-                    goto retry;
-        }
-        printf("seeds OK\n");
-        return 0;
-        retry:;
-    }
-    printf("FAIL at %d with %X\n", j, seeds[j]);
-    return 1;
-}
-#endif
diff --git a/libavutil/rational.c b/libavutil/rational.c
index 6b3f50a..35ee088 100644
--- a/libavutil/rational.c
+++ b/libavutil/rational.c
@@ -115,7 +115,8 @@ AVRational av_d2q(double d, int max)
     frexp(d, &exponent);
     exponent = FFMAX(exponent-1, 0);
     den = 1LL << (61 - exponent);
-    // (int64_t)rint() and llrint() do not work with gcc on ia64 and sparc64
+    // (int64_t)rint() and llrint() do not work with gcc on ia64 and sparc64,
+    // see Ticket2713 for affected gcc/glibc versions
     av_reduce(&a.num, &a.den, floor(d * den + 0.5), den, max);
     if ((!a.num || !a.den) && d && max>0 && max<INT_MAX)
         av_reduce(&a.num, &a.den, floor(d * den + 0.5), den, INT_MAX);
@@ -181,119 +182,3 @@ uint32_t av_q2intfloat(AVRational q) {
 
     return sign<<31 | (150-shift)<<23 | (n - (1<<23));
 }
-
-#ifdef TEST
-
-#include "integer.h"
-
-int main(void)
-{
-    AVRational a,b,r;
-    int i,j,k;
-    static const int64_t numlist[] = {
-        INT64_MIN, INT64_MIN+1, INT64_MAX, INT32_MIN, INT32_MAX, 1,0,-1,
-        123456789, INT32_MAX-1, INT32_MAX+1LL, UINT32_MAX-1, UINT32_MAX, UINT32_MAX+1LL
-    };
-
-    for (a.num = -2; a.num <= 2; a.num++) {
-        for (a.den = -2; a.den <= 2; a.den++) {
-            for (b.num = -2; b.num <= 2; b.num++) {
-                for (b.den = -2; b.den <= 2; b.den++) {
-                    int c = av_cmp_q(a,b);
-                    double d = av_q2d(a) == av_q2d(b) ?
-                               0 : (av_q2d(a) - av_q2d(b));
-                    if (d > 0)       d = 1;
-                    else if (d < 0)  d = -1;
-                    else if (d != d) d = INT_MIN;
-                    if (c != d)
-                        av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %f\n", a.num,
-                               a.den, b.num, b.den, c,d);
-                    r = av_sub_q(av_add_q(b,a), b);
-                    if(b.den && (r.num*a.den != a.num*r.den || !r.num != !a.num || !r.den != !a.den))
-                        av_log(NULL, AV_LOG_ERROR, "%d/%d ", r.num, r.den);
-                }
-            }
-        }
-    }
-
-    for (i = 0; i < FF_ARRAY_ELEMS(numlist); i++) {
-        int64_t a = numlist[i];
-
-        for (j = 0; j < FF_ARRAY_ELEMS(numlist); j++) {
-            int64_t b = numlist[j];
-            if (b<=0)
-                continue;
-            for (k = 0; k < FF_ARRAY_ELEMS(numlist); k++) {
-                int64_t c = numlist[k];
-                int64_t res;
-                AVInteger ai;
-
-                if (c<=0)
-                    continue;
-                res = av_rescale_rnd(a,b,c, AV_ROUND_ZERO);
-
-                ai = av_mul_i(av_int2i(a), av_int2i(b));
-                ai = av_div_i(ai, av_int2i(c));
-
-                if (av_cmp_i(ai, av_int2i(INT64_MAX)) > 0 && res == INT64_MIN)
-                    continue;
-                if (av_cmp_i(ai, av_int2i(INT64_MIN)) < 0 && res == INT64_MIN)
-                    continue;
-                if (av_cmp_i(ai, av_int2i(res)) == 0)
-                    continue;
-
-                // Special exception for INT64_MIN, remove this in case INT64_MIN is handled without off by 1 error
-                if (av_cmp_i(ai, av_int2i(res-1)) == 0 && a == INT64_MIN)
-                    continue;
-
-                av_log(NULL, AV_LOG_ERROR, "%"PRId64" * %"PRId64" / %"PRId64" = %"PRId64" or %"PRId64"\n", a,b,c, res, av_i2int(ai));
-            }
-        }
-    }
-
-    for (a.num = 1; a.num <= 10; a.num++) {
-        for (a.den = 1; a.den <= 10; a.den++) {
-            if (av_gcd(a.num, a.den) > 1)
-                continue;
-            for (b.num = 1; b.num <= 10; b.num++) {
-                for (b.den = 1; b.den <= 10; b.den++) {
-                    int start;
-                    if (av_gcd(b.num, b.den) > 1)
-                        continue;
-                    if (av_cmp_q(b, a) < 0)
-                        continue;
-                    for (start = 0; start < 10 ; start++) {
-                        int acc= start;
-                        int i;
-
-                        for (i = 0; i<100; i++) {
-                            int exact = start + av_rescale_q(i+1, b, a);
-                            acc = av_add_stable(a, acc, b, 1);
-                            if (FFABS(acc - exact) > 2) {
-                                av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %d\n", a.num,
-                                       a.den, b.num, b.den, acc, exact);
-                                return 1;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    for (a.den = 1; a.den < 0x100000000U/3; a.den*=3) {
-        for (a.num = -1; a.num < (1<<27); a.num += 1 + a.num/100) {
-            float f  = av_int2float(av_q2intfloat(a));
-            float f2 = av_q2d(a);
-            if (fabs(f - f2) > fabs(f)/5000000) {
-                av_log(NULL, AV_LOG_ERROR, "%d/%d %f %f\n", a.num,
-                       a.den, f, f2);
-                return 1;
-            }
-
-        }
-    }
-
-    return 0;
-}
-#endif
diff --git a/libavutil/replaygain.h b/libavutil/replaygain.h
index 5c03e19..b49bf1a 100644
--- a/libavutil/replaygain.h
+++ b/libavutil/replaygain.h
@@ -1,5 +1,4 @@
 /*
- *
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
diff --git a/libavutil/ripemd.c b/libavutil/ripemd.c
index 6777c99..b0db297 100644
--- a/libavutil/ripemd.c
+++ b/libavutil/ripemd.c
@@ -549,57 +549,3 @@ void av_ripemd_final(AVRIPEMD* ctx, uint8_t *digest)
     for (i = 0; i < ctx->digest_len; i++)
         AV_WL32(digest + i*4, ctx->state[i]);
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-int main(void)
-{
-    int i, j, k;
-    AVRIPEMD ctx;
-    unsigned char digest[40];
-    static const int lengths[4] = { 128, 160, 256, 320 };
-
-    for (j = 0; j < 4; j++) {
-        printf("Testing RIPEMD-%d\n", lengths[j]);
-        for (k = 0; k < 3; k++) {
-            av_ripemd_init(&ctx, lengths[j]);
-            if (k == 0)
-                av_ripemd_update(&ctx, "abc", 3);
-            else if (k == 1)
-                av_ripemd_update(&ctx, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56);
-            else
-                for (i = 0; i < 1000*1000; i++)
-                    av_ripemd_update(&ctx, "a", 1);
-            av_ripemd_final(&ctx, digest);
-            for (i = 0; i < lengths[j] >> 3; i++)
-                printf("%02X", digest[i]);
-            putchar('\n');
-        }
-        switch (j) { //test vectors (from ISO:IEC 10118-3 (2004) and http://homes.esat.kuleuven.be/~bosselae/ripemd160.html)
-        case 0:
-            printf("c14a1219 9c66e4ba 84636b0f 69144c77\n"
-                   "a1aa0689 d0fafa2d dc22e88b 49133a06\n"
-                   "4a7f5723 f954eba1 216c9d8f 6320431f\n");
-            break;
-        case 1:
-            printf("8eb208f7 e05d987a 9b044a8e 98c6b087 f15a0bfc\n"
-                   "12a05338 4a9c0c88 e405a06c 27dcf49a da62eb2b\n"
-                   "52783243 c1697bdb e16d37f9 7f68f083 25dc1528\n");
-            break;
-        case 2:
-            printf("afbd6e22 8b9d8cbb cef5ca2d 03e6dba1 0ac0bc7d cbe4680e 1e42d2e9 75459b65\n"
-                   "38430455 83aac6c8 c8d91285 73e7a980 9afb2a0f 34ccc36e a9e72f16 f6368e3f\n"
-                   "ac953744 e10e3151 4c150d4d 8d7b6773 42e33399 788296e4 3ae4850c e4f97978\n");
-            break;
-        case 3:
-            printf("de4c01b3 054f8930 a79d09ae 738e9230 1e5a1708 5beffdc1 b8d11671 3e74f82f a942d64c dbc4682d\n"
-                   "d034a795 0cf72202 1ba4b84d f769a5de 2060e259 df4c9bb4 a4268c0e 935bbc74 70a969c9 d072a1ac\n"
-                   "bdee37f4 371e2064 6b8b0d86 2dda1629 2ae36f40 965e8c85 09e63d1d bddecc50 3e2b63eb 9245bb66\n");
-            break;
-        }
-    }
-
-    return 0;
-}
-#endif
diff --git a/libavutil/samplefmt.h b/libavutil/samplefmt.h
index 6a8a031..57da278 100644
--- a/libavutil/samplefmt.h
+++ b/libavutil/samplefmt.h
@@ -32,7 +32,6 @@
  *
  * Audio sample format enumeration and related convenience functions.
  * @{
- *
  */
 
 /**
diff --git a/libavutil/sha.c b/libavutil/sha.c
index 748bb9c..5b42ccf 100644
--- a/libavutil/sha.c
+++ b/libavutil/sha.c
@@ -350,55 +350,3 @@ void av_sha_final(AVSHA* ctx, uint8_t *digest)
     for (i = 0; i < ctx->digest_len; i++)
         AV_WB32(digest + i*4, ctx->state[i]);
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-int main(void)
-{
-    int i, j, k;
-    AVSHA ctx;
-    unsigned char digest[32];
-    static const int lengths[3] = { 160, 224, 256 };
-
-    for (j = 0; j < 3; j++) {
-        printf("Testing SHA-%d\n", lengths[j]);
-        for (k = 0; k < 3; k++) {
-            av_sha_init(&ctx, lengths[j]);
-            if (k == 0)
-                av_sha_update(&ctx, "abc", 3);
-            else if (k == 1)
-                av_sha_update(&ctx, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56);
-            else
-                for (i = 0; i < 1000*1000; i++)
-                    av_sha_update(&ctx, "a", 1);
-            av_sha_final(&ctx, digest);
-            for (i = 0; i < lengths[j] >> 3; i++)
-                printf("%02X", digest[i]);
-            putchar('\n');
-        }
-        switch (j) {
-        case 0:
-            //test vectors (from FIPS PUB 180-1)
-            printf("A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n"
-                   "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\n"
-                   "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n");
-            break;
-        case 1:
-            //test vectors (from FIPS PUB 180-2 Appendix A)
-            printf("23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7\n"
-                   "75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525\n"
-                   "20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67\n");
-            break;
-        case 2:
-            //test vectors (from FIPS PUB 180-2)
-            printf("ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad\n"
-                   "248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1\n"
-                   "cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0\n");
-            break;
-        }
-    }
-
-    return 0;
-}
-#endif
diff --git a/libavutil/sha512.c b/libavutil/sha512.c
index e2fc58a..2c5da25 100644
--- a/libavutil/sha512.c
+++ b/libavutil/sha512.c
@@ -281,65 +281,3 @@ void av_sha512_final(AVSHA512* ctx, uint8_t *digest)
     if (ctx->digest_len & 1) /* SHA512/224 is 28 bytes, and is not divisible by 8. */
         AV_WB32(digest + i*8, ctx->state[i] >> 32);
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-int main(void)
-{
-    int i, j, k;
-    AVSHA512 ctx;
-    unsigned char digest[64];
-    static const int lengths[4] = { 224, 256, 384, 512 };
-
-    for (j = 0; j < 4; j++) {
-        if (j < 2) printf("Testing SHA-512/%d\n", lengths[j]);
-        else       printf("Testing SHA-%d\n", lengths[j]);
-        for (k = 0; k < 3; k++) {
-            av_sha512_init(&ctx, lengths[j]);
-            if (k == 0)
-                av_sha512_update(&ctx, "abc", 3);
-            else if (k == 1)
-                av_sha512_update(&ctx, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
-                                       "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112);
-            else
-                for (i = 0; i < 1000*1000; i++)
-                    av_sha512_update(&ctx, "a", 1);
-            av_sha512_final(&ctx, digest);
-            for (i = 0; i < lengths[j] >> 3; i++)
-                printf("%02X", digest[i]);
-            putchar('\n');
-        }
-        switch (j) { //test vectors (from FIPS PUB 180-4 Apendix A)
-        case 0:
-            printf("4634270f 707b6a54 daae7530 460842e2 0e37ed26 5ceee9a4 3e8924aa\n"
-                   "23fec5bb 94d60b23 30819264 0b0c4533 35d66473 4fe40e72 68674af9\n"
-                   "37ab331d 76f0d36d e422bd0e deb22a28 accd487b 7a8453ae 965dd287\n");
-            break;
-        case 1:
-            printf("53048e26 81941ef9 9b2e29b7 6b4c7dab e4c2d0c6 34fc6d46 e0e2f131 07e7af23\n"
-                   "3928e184 fb8690f8 40da3988 121d31be 65cb9d3e f83ee614 6feac861 e19b563a\n"
-                   "9a59a052 930187a9 7038cae6 92f30708 aa649192 3ef51943 94dc68d5 6c74fb21\n");
-            break;
-        case 2:
-            printf("cb00753f 45a35e8b b5a03d69 9ac65007 272c32ab 0eded163 "
-                   "1a8b605a 43ff5bed 8086072b a1e7cc23 58baeca1 34c825a7\n"
-                   "09330c33 f71147e8 3d192fc7 82cd1b47 53111b17 3b3b05d2 "
-                   "2fa08086 e3b0f712 fcc7c71a 557e2db9 66c3e9fa 91746039\n"
-                   "9d0e1809 716474cb 086e834e 310a4a1c ed149e9c 00f24852 "
-                   "7972cec5 704c2a5b 07b8b3dc 38ecc4eb ae97ddd8 7f3d8985\n");
-            break;
-        case 3:
-            printf("ddaf35a1 93617aba cc417349 ae204131 12e6fa4e 89a97ea2 0a9eeee6 4b55d39a "
-                   "2192992a 274fc1a8 36ba3c23 a3feebbd 454d4423 643ce80e 2a9ac94f a54ca49f\n"
-                   "8e959b75 dae313da 8cf4f728 14fc143f 8f7779c6 eb9f7fa1 7299aead b6889018 "
-                   "501d289e 4900f7e4 331b99de c4b5433a c7d329ee b6dd2654 5e96e55b 874be909\n"
-                   "e718483d 0ce76964 4e2e42c7 bc15b463 8e1f98b1 3b204428 5632a803 afa973eb "
-                   "de0ff244 877ea60a 4cb0432c e577c31b eb009c5c 2c49aa2e 4eadb217 ad8cc09b\n");
-            break;
-        }
-    }
-
-    return 0;
-}
-#endif
diff --git a/libavutil/softfloat.c b/libavutil/softfloat.c
deleted file mode 100644
index 4bfbbb2..0000000
--- a/libavutil/softfloat.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * copyright (c) 2006 Michael Niedermayer <michaelni at gmx.at>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <inttypes.h>
-#include "softfloat.h"
-#include "common.h"
-#include "log.h"
-
-#ifdef TEST
-#include <stdio.h>
-
-static const SoftFloat FLOAT_0_017776489257 = {0x1234, 12};
-static const SoftFloat FLOAT_1374_40625 = {0xabcd, 25};
-static const SoftFloat FLOAT_0_1249694824218 = {0xFFF, 15};
-
-
-int main(void){
-    SoftFloat one= av_int2sf(1, 0);
-    SoftFloat sf1, sf2, sf3;
-    double d1, d2, d3;
-    int i, j;
-    av_log_set_level(AV_LOG_DEBUG);
-
-    d1= 1;
-    for(i= 0; i<10; i++){
-        d1= 1/(d1+1);
-    }
-    printf("test1 double=%d\n", (int)(d1 * (1<<24)));
-
-    sf1= one;
-    for(i= 0; i<10; i++){
-        sf1= av_div_sf(one, av_normalize_sf(av_add_sf(one, sf1)));
-    }
-    printf("test1 sf    =%d\n", av_sf2int(sf1, 24));
-
-
-    for(i= 0; i<100; i++){
-        START_TIMER
-        d1= i;
-        d2= i/100.0;
-        for(j= 0; j<1000; j++){
-            d1= (d1+1)*d2;
-        }
-        STOP_TIMER("float add mul")
-    }
-    printf("test2 double=%d\n", (int)(d1 * (1<<24)));
-
-    for(i= 0; i<100; i++){
-        START_TIMER
-        sf1= av_int2sf(i, 0);
-        sf2= av_div_sf(av_int2sf(i, 2), av_int2sf(200, 3));
-        for(j= 0; j<1000; j++){
-            sf1= av_mul_sf(av_add_sf(sf1, one),sf2);
-        }
-        STOP_TIMER("softfloat add mul")
-    }
-    printf("test2 sf    =%d (%d %d)\n", av_sf2int(sf1, 24), sf1.exp, sf1.mant);
-
-    d1 = 0.0177764893;
-    d2 = 1374.40625;
-    d3 = 0.1249694824;
-    d2 += d1;
-    d3 += d2;
-    printf("test3 double: %.10lf\n", d3);
-
-    sf1 = FLOAT_0_017776489257;
-    sf2 = FLOAT_1374_40625;
-    sf3 = FLOAT_0_1249694824218;
-    sf2 = av_add_sf(sf1, sf2);
-    sf3 = av_add_sf(sf3, sf2);
-    printf("test3 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf3), sf3.mant, sf3.exp);
-
-    sf1 = av_int2sf(0xFFFFFFF0, 0);
-    printf("test4 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
-    sf1 = av_int2sf(0x00000010, 0);
-    printf("test4 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
-
-    sf1 = av_int2sf(0x1FFFFFFF, 0);
-    printf("test4 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
-    sf1 = av_int2sf(0xE0000001, 0);
-    printf("test4 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
-
-
-    sf1 = (SoftFloat){ 0x20000000,   MIN_EXP };
-    sf1 = av_mul_sf(sf1, sf1);
-    printf("test5 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
-
-    sf1 = (SoftFloat){ 0x20000000,   MIN_EXP };
-    sf2 = (SoftFloat){ 0x20000000,   MAX_EXP };
-    i = av_cmp_sf(sf1, sf2);
-    j = av_cmp_sf(sf2, sf1);
-    sf1 = av_div_sf(sf1, sf2);
-    printf("test6 softfloat: %.10lf (0x%08x %d) %d %d\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp, i, j);
-
-    for(i= -50; i<50; i++) {
-        sf1= av_int2sf(i, 0);
-        for(j= -50; j<50; j++) {
-            int c;
-            sf2= av_int2sf(j, 0);
-            c = av_cmp_sf(sf1, sf2);
-            if (FFDIFFSIGN(i,j) != c && (FFDIFFSIGN(i,j)^c)<0) {
-                printf("av_cmp_sf failed at %d %d as %X\n", i, j, c);
-            }
-            c = av_gt_sf(sf1, sf2);
-            if ((i>j) != c) {
-                printf("av_gt_sf failed at %d %d as %X\n", i, j, c);
-            }
-        }
-        sf1 = av_int2sf(1, i);
-        for(j = -50; j < 50; j++) {
-            int c;
-            sf2 = av_int2sf(1, j);
-            c = av_cmp_sf(sf2, sf1);
-            if (FFDIFFSIGN(i,j) != c && (FFDIFFSIGN(i,j)^c) < 0) {
-                printf("av_cmp_sf failed2 at %d %d as %X\n", i, j, c);
-            }
-            c = av_gt_sf(sf1, sf2);
-            if ((i<j) != c) {
-                printf("av_gt_sf failed2 at %d %d as %X\n", i, j, c);
-            }
-        }
-    }
-
-
-    for(i= 0; i<4*36; i++){
-        int s, c;
-        double errs, errc;
-
-        av_sincos_sf(i*(1ULL<<32)/36/4, &s, &c);
-        errs = (double)s/ (1<<30) - sin(i*M_PI/36);
-        errc = (double)c/ (1<<30) - cos(i*M_PI/36);
-        if (fabs(errs) > 0.00000002 || fabs(errc) >0.001) {
-            printf("sincos FAIL %d %f %f %f %f\n", i, (float)s/ (1<<30), (float)c/ (1<<30), sin(i*M_PI/36), cos(i*M_PI/36));
-        }
-
-    }
-    return 0;
-
-}
-#endif
diff --git a/libavutil/softfloat.h b/libavutil/softfloat.h
index 4b895f0..a3b2238 100644
--- a/libavutil/softfloat.h
+++ b/libavutil/softfloat.h
@@ -36,14 +36,18 @@ typedef struct SoftFloat{
     int32_t  exp;
 }SoftFloat;
 
-static const SoftFloat FLOAT_0          = {          0,   MIN_EXP};
-static const SoftFloat FLOAT_05         = { 0x20000000,   0};
-static const SoftFloat FLOAT_1          = { 0x20000000,   1};
-static const SoftFloat FLOAT_EPSILON    = { 0x29F16B12, -16};
-static const SoftFloat FLOAT_1584893192 = { 0x32B771ED,   1};
-static const SoftFloat FLOAT_100000     = { 0x30D40000,  17};
-static const SoftFloat FLOAT_0999999    = { 0x3FFFFBCE,   0};
+static const SoftFloat FLOAT_0          = {          0,   MIN_EXP};             ///< 0.0
+static const SoftFloat FLOAT_05         = { 0x20000000,   0};                   ///< 0.5
+static const SoftFloat FLOAT_1          = { 0x20000000,   1};                   ///< 1.0
+static const SoftFloat FLOAT_EPSILON    = { 0x29F16B12, -16};                   ///< A small value
+static const SoftFloat FLOAT_1584893192 = { 0x32B771ED,   1};                   ///< 1.584893192 (10^.2)
+static const SoftFloat FLOAT_100000     = { 0x30D40000,  17};                   ///< 100000
+static const SoftFloat FLOAT_0999999    = { 0x3FFFFBCE,   0};                   ///< 0.999999
 
+
+/**
+ * Convert a SoftFloat to a double precision float.
+ */
 static inline av_const double av_sf2double(SoftFloat v) {
     v.exp -= ONE_BITS +1;
     if(v.exp > 0) return (double)v.mant * (double)(1 << v.exp);
@@ -118,6 +122,12 @@ static inline av_const SoftFloat av_div_sf(SoftFloat a, SoftFloat b){
     return a;
 }
 
+/**
+ * Compares two SoftFloats.
+ * @returns < 0 if the first is less
+ *          > 0 if the first is greater
+ *            0 if they are equal
+ */
 static inline av_const int av_cmp_sf(SoftFloat a, SoftFloat b){
     int t= a.exp - b.exp;
     if      (t <-31) return                  -  b.mant      ;
@@ -126,6 +136,10 @@ static inline av_const int av_cmp_sf(SoftFloat a, SoftFloat b){
     else             return  a.mant                         ;
 }
 
+/**
+ * Compares two SoftFloats.
+ * @returns 1 if a is greater than b, 0 otherwise
+ */
 static inline av_const int av_gt_sf(SoftFloat a, SoftFloat b)
 {
     int t= a.exp - b.exp;
@@ -135,6 +149,9 @@ static inline av_const int av_gt_sf(SoftFloat a, SoftFloat b)
     else             return  a.mant          >  0           ;
 }
 
+/**
+ * @returns the sum of 2 SoftFloats.
+ */
 static inline av_const SoftFloat av_add_sf(SoftFloat a, SoftFloat b){
     int t= a.exp - b.exp;
     if      (t <-31) return b;
@@ -143,6 +160,9 @@ static inline av_const SoftFloat av_add_sf(SoftFloat a, SoftFloat b){
     else             return a;
 }
 
+/**
+ * @returns the difference of 2 SoftFloats.
+ */
 static inline av_const SoftFloat av_sub_sf(SoftFloat a, SoftFloat b){
     return av_add_sf(a, (SoftFloat){ -b.mant, b.exp});
 }
@@ -163,6 +183,7 @@ static inline av_const SoftFloat av_int2sf(int v, int frac_bits){
 }
 
 /**
+ * Converts a SoftFloat to an integer.
  * Rounding is to -inf.
  */
 static inline av_const int av_sf2int(SoftFloat v, int frac_bits){
diff --git a/libavutil/stereo3d.c b/libavutil/stereo3d.c
index 50cd928..a538364 100644
--- a/libavutil/stereo3d.c
+++ b/libavutil/stereo3d.c
@@ -21,6 +21,7 @@
 #include <stdint.h>
 #include <string.h>
 
+#include "common.h"
 #include "mem.h"
 #include "stereo3d.h"
 
@@ -41,3 +42,35 @@ AVStereo3D *av_stereo3d_create_side_data(AVFrame *frame)
 
     return (AVStereo3D *)side_data->data;
 }
+
+static const char *stereo3d_type_names[] = {
+    [AV_STEREO3D_2D]                  = "2D",
+    [AV_STEREO3D_SIDEBYSIDE]          = "side by side",
+    [AV_STEREO3D_TOPBOTTOM]           = "top and bottom",
+    [AV_STEREO3D_FRAMESEQUENCE]       = "frame alternate",
+    [AV_STEREO3D_CHECKERBOARD]        = "checkerboard",
+    [AV_STEREO3D_SIDEBYSIDE_QUINCUNX] = "side by side (quincunx subsampling)",
+    [AV_STEREO3D_LINES]               = "interleaved lines",
+    [AV_STEREO3D_COLUMNS]             = "interleaved columns",
+};
+
+const char *av_stereo3d_type_name(unsigned int type)
+{
+    if (type >= FF_ARRAY_ELEMS(stereo3d_type_names))
+        return "unknown";
+
+    return stereo3d_type_names[type];
+}
+
+int av_stereo3d_from_name(const char *name)
+{
+    int i;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(stereo3d_type_names); i++) {
+        size_t len = strlen(stereo3d_type_names[i]);
+        if (!strncmp(stereo3d_type_names[i], name, len))
+            return i;
+    }
+
+    return -1;
+}
diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h
index 1135dc9..19c5416 100644
--- a/libavutil/stereo3d.h
+++ b/libavutil/stereo3d.h
@@ -149,4 +149,22 @@ AVStereo3D *av_stereo3d_alloc(void);
  */
 AVStereo3D *av_stereo3d_create_side_data(AVFrame *frame);
 
+/**
+ * Provide a human-readable name of a given stereo3d type.
+ *
+ * @param type The input stereo3d type value.
+ *
+ * @return The name of the stereo3d value, or "unknown".
+ */
+const char *av_stereo3d_type_name(unsigned int type);
+
+/**
+ * Get the AVStereo3DType form a human-readable name.
+ *
+ * @param type The input string.
+ *
+ * @return The AVStereo3DType value, or -1 if not found.
+ */
+int av_stereo3d_from_name(const char *name);
+
 #endif /* AVUTIL_STEREO3D_H */
diff --git a/libavutil/tea.c b/libavutil/tea.c
index bf76718..b138f8b 100644
--- a/libavutil/tea.c
+++ b/libavutil/tea.c
@@ -119,95 +119,3 @@ void av_tea_crypt(AVTEA *ctx, uint8_t *dst, const uint8_t *src, int count,
         }
     }
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-#define TEA_NUM_TESTS 4
-
-// https://github.com/logandrews/TeaCrypt/blob/master/tea/tea_test.go
-static const uint8_t tea_test_key[TEA_NUM_TESTS][16] = {
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-    },
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-    },
-    { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-      0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
-    },
-    { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-      0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
-    }
-};
-
-static const uint8_t tea_test_pt[TEA_NUM_TESTS][8] = {
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-    { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
-    { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
-    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }
-};
-
-static const uint8_t tea_test_ct[TEA_NUM_TESTS][8] = {
-    { 0x41, 0xEA, 0x3A, 0x0A, 0x94, 0xBA, 0xA9, 0x40 },
-    { 0x6A, 0x2F, 0x9C, 0xF3, 0xFC, 0xCF, 0x3C, 0x55 },
-    { 0xDE, 0xB1, 0xC0, 0xA2, 0x7E, 0x74, 0x5D, 0xB3 },
-    { 0x12, 0x6C, 0x6B, 0x92, 0xC0, 0x65, 0x3A, 0x3E }
-};
-
-static void test_tea(AVTEA *ctx, uint8_t *dst, const uint8_t *src,
-                     const uint8_t *ref, int len, uint8_t *iv, int dir,
-                     const char *test)
-{
-    av_tea_crypt(ctx, dst, src, len, iv, dir);
-    if (memcmp(dst, ref, 8*len)) {
-        int i;
-        printf("%s failed\ngot      ", test);
-        for (i = 0; i < 8*len; i++)
-            printf("%02x ", dst[i]);
-        printf("\nexpected ");
-        for (i = 0; i < 8*len; i++)
-            printf("%02x ", ref[i]);
-        printf("\n");
-        exit(1);
-    }
-}
-
-int main(void)
-{
-    AVTEA *ctx;
-    uint8_t buf[8], iv[8];
-    int i;
-    static const uint8_t src[32] = "HelloWorldHelloWorldHelloWorld";
-    uint8_t ct[32];
-    uint8_t pl[32];
-
-    ctx = av_tea_alloc();
-    if (!ctx)
-        return 1;
-
-    for (i = 0; i < TEA_NUM_TESTS; i++) {
-        av_tea_init(ctx, tea_test_key[i], 64);
-
-        test_tea(ctx, buf, tea_test_pt[i], tea_test_ct[i], 1, NULL, 0, "encryption");
-        test_tea(ctx, buf, tea_test_ct[i], tea_test_pt[i], 1, NULL, 1, "decryption");
-
-        /* encrypt */
-        memcpy(iv, "HALLO123", 8);
-        av_tea_crypt(ctx, ct, src, 4, iv, 0);
-
-        /* decrypt into pl */
-        memcpy(iv, "HALLO123", 8);
-        test_tea(ctx, pl, ct, src, 4, iv, 1, "CBC decryption");
-
-        memcpy(iv, "HALLO123", 8);
-        test_tea(ctx, ct, ct, src, 4, iv, 1, "CBC inplace decryption");
-    }
-
-    printf("Test encryption/decryption success.\n");
-    av_free(ctx);
-
-    return 0;
-}
-
-#endif
diff --git a/libavutil/tests/adler32.c b/libavutil/tests/adler32.c
new file mode 100644
index 0000000..511bf1e
--- /dev/null
+++ b/libavutil/tests/adler32.c
@@ -0,0 +1,53 @@
+/*
+ * 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
+ */
+
+// LCOV_EXCL_START
+#include <string.h>
+
+#include "libavutil/log.h"
+#include "libavutil/timer.h"
+#include "libavutil/adler32.h"
+
+#define LEN 7001
+
+static volatile int checksum;
+
+int main(int argc, char **argv)
+{
+    int i;
+    uint8_t data[LEN];
+
+    av_log_set_level(AV_LOG_DEBUG);
+
+    for (i = 0; i < LEN; i++)
+        data[i] = ((i * i) >> 3) + 123 * i;
+
+    if (argc > 1 && !strcmp(argv[1], "-t")) {
+        for (i = 0; i < 1000; i++) {
+            START_TIMER;
+            checksum = av_adler32_update(1, data, LEN);
+            STOP_TIMER("adler");
+        }
+    } else {
+        checksum = av_adler32_update(1, data, LEN);
+    }
+
+    av_log(NULL, AV_LOG_DEBUG, "%X (expected 50E6E508)\n", checksum);
+    return checksum == 0x50e6e508 ? 0 : 1;
+}
+// LCOV_EXCL_STOP
diff --git a/libavutil/tests/aes.c b/libavutil/tests/aes.c
new file mode 100644
index 0000000..1291ad6
--- /dev/null
+++ b/libavutil/tests/aes.c
@@ -0,0 +1,119 @@
+/*
+ * 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
+ */
+
+// LCOV_EXCL_START
+#include <string.h>
+
+#include "libavutil/aes.h"
+#include "libavutil/lfg.h"
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+
+int main(int argc, char **argv)
+{
+    int i, j;
+    struct AVAES *b;
+    static const uint8_t rkey[2][16] = {
+        { 0 },
+        { 0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3,
+          0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59 }
+    };
+    static const uint8_t rpt[2][16] = {
+        { 0x6a, 0x84, 0x86, 0x7c, 0xd7, 0x7e, 0x12, 0xad,
+          0x07, 0xea, 0x1b, 0xe8, 0x95, 0xc5, 0x3f, 0xa3 },
+        { 0 }
+    };
+    static const uint8_t rct[2][16] = {
+        { 0x73, 0x22, 0x81, 0xc0, 0xa0, 0xaa, 0xb8, 0xf7,
+          0xa5, 0x4a, 0x0c, 0x67, 0xa0, 0xc4, 0x5e, 0xcf },
+        { 0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0,
+          0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65 }
+    };
+    uint8_t pt[32];
+    uint8_t temp[32];
+    uint8_t iv[2][16];
+    int err = 0;
+
+    b = av_aes_alloc();
+    if (!b)
+        return 1;
+
+    av_log_set_level(AV_LOG_DEBUG);
+
+    for (i = 0; i < 2; i++) {
+        av_aes_init(b, rkey[i], 128, 1);
+        av_aes_crypt(b, temp, rct[i], 1, NULL, 1);
+        for (j = 0; j < 16; j++) {
+            if (rpt[i][j] != temp[j]) {
+                av_log(NULL, AV_LOG_ERROR, "%d %02X %02X\n",
+                       j, rpt[i][j], temp[j]);
+                err = 1;
+            }
+        }
+    }
+    av_free(b);
+
+    if (argc > 1 && !strcmp(argv[1], "-t")) {
+        struct AVAES *ae, *ad;
+        AVLFG prng;
+
+        ae = av_aes_alloc();
+        ad = av_aes_alloc();
+
+        if (!ae || !ad) {
+            av_free(ae);
+            av_free(ad);
+            return 1;
+        }
+
+        av_aes_init(ae, (const uint8_t*)"PI=3.141592654..", 128, 0);
+        av_aes_init(ad, (const uint8_t*)"PI=3.141592654..", 128, 1);
+        av_lfg_init(&prng, 1);
+
+        for (i = 0; i < 10000; i++) {
+            for (j = 0; j < 32; j++)
+                pt[j] = av_lfg_get(&prng);
+            for (j = 0; j < 16; j++)
+                iv[0][j] = iv[1][j] = av_lfg_get(&prng);
+            {
+                START_TIMER;
+                av_aes_crypt(ae, temp, pt, 2, iv[0], 0);
+                if (!(i & (i - 1)))
+                    av_log(NULL, AV_LOG_ERROR, "%02X %02X %02X %02X\n",
+                           temp[0], temp[5], temp[10], temp[15]);
+                av_aes_crypt(ad, temp, temp, 2, iv[1], 1);
+                av_aes_crypt(ae, temp, pt, 2, NULL, 0);
+                if (!(i & (i - 1)))
+                    av_log(NULL, AV_LOG_ERROR, "%02X %02X %02X %02X\n",
+                           temp[0], temp[5], temp[10], temp[15]);
+                av_aes_crypt(ad, temp, temp, 2, NULL, 1);
+                STOP_TIMER("aes");
+            }
+            for (j = 0; j < 16; j++) {
+                if (pt[j] != temp[j]) {
+                    av_log(NULL, AV_LOG_ERROR, "%d %d %02X %02X\n",
+                           i, j, pt[j], temp[j]);
+                }
+            }
+        }
+        av_free(ae);
+        av_free(ad);
+    }
+    return err;
+}
+// LCOV_EXCL_STOP
diff --git a/libavutil/tests/atomic.c b/libavutil/tests/atomic.c
new file mode 100644
index 0000000..c92f220
--- /dev/null
+++ b/libavutil/tests/atomic.c
@@ -0,0 +1,34 @@
+/*
+ * 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/atomic.h"
+#include "libavutil/avassert.h"
+
+int main(void)
+{
+    volatile int val = 1;
+    int res;
+
+    res = avpriv_atomic_int_add_and_fetch(&val, 1);
+    av_assert0(res == 2);
+    avpriv_atomic_int_set(&val, 3);
+    res = avpriv_atomic_int_get(&val);
+    av_assert0(res == 3);
+
+    return 0;
+}
diff --git a/libavutil/tests/avstring.c b/libavutil/tests/avstring.c
new file mode 100644
index 0000000..1242b3f
--- /dev/null
+++ b/libavutil/tests/avstring.c
@@ -0,0 +1,83 @@
+/*
+ * 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 <stdio.h>
+
+#include "libavutil/common.h"
+#include "libavutil/mem.h"
+#include "libavutil/avstring.h"
+
+int main(void)
+{
+    int i;
+    char *fullpath;
+    static const char * const strings[] = {
+        "''",
+        "",
+        ":",
+        "\\",
+        "'",
+        "    ''    :",
+        "    ''  ''  :",
+        "foo   '' :",
+        "'foo'",
+        "foo     ",
+        "  '  foo  '  ",
+        "foo\\",
+        "foo':  blah:blah",
+        "foo\\:  blah:blah",
+        "foo\'",
+        "'foo :  '  :blahblah",
+        "\\ :blah",
+        "     foo",
+        "      foo       ",
+        "      foo     \\ ",
+        "foo ':blah",
+        " foo   bar    :   blahblah",
+        "\\f\\o\\o",
+        "'foo : \\ \\  '   : blahblah",
+        "'\\fo\\o:': blahblah",
+        "\\'fo\\o\\:':  foo  '  :blahblah"
+    };
+
+    printf("Testing av_get_token()\n");
+    for (i = 0; i < FF_ARRAY_ELEMS(strings); i++) {
+        const char *p = strings[i];
+        char *q;
+        printf("|%s|", p);
+        q = av_get_token(&p, ":");
+        printf(" -> |%s|", q);
+        printf(" + |%s|\n", p);
+        av_free(q);
+    }
+
+    printf("Testing av_append_path_component()\n");
+    #define TEST_APPEND_PATH_COMPONENT(path, component, expected) \
+        fullpath = av_append_path_component((path), (component)); \
+        printf("%s = %s\n", fullpath ? fullpath : "(null)", expected); \
+        av_free(fullpath);
+    TEST_APPEND_PATH_COMPONENT(NULL, NULL, "(null)")
+    TEST_APPEND_PATH_COMPONENT("path", NULL, "path");
+    TEST_APPEND_PATH_COMPONENT(NULL, "comp", "comp");
+    TEST_APPEND_PATH_COMPONENT("path", "comp", "path/comp");
+    TEST_APPEND_PATH_COMPONENT("path/", "comp", "path/comp");
+    TEST_APPEND_PATH_COMPONENT("path", "/comp", "path/comp");
+    TEST_APPEND_PATH_COMPONENT("path/", "/comp", "path/comp");
+    TEST_APPEND_PATH_COMPONENT("path/path2/", "/comp/comp2", "path/path2/comp/comp2");
+    return 0;
+}
diff --git a/libavutil/tests/base64.c b/libavutil/tests/base64.c
new file mode 100644
index 0000000..88fd55c
--- /dev/null
+++ b/libavutil/tests/base64.c
@@ -0,0 +1,128 @@
+/*
+ * 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
+ */
+
+// LCOV_EXCL_START
+#include <stdint.h>
+#include <stdio.h>
+
+#include "libavutil/common.h"
+#include "libavutil/base64.h"
+#include "libavutil/timer.h"
+
+#define MAX_DATA_SIZE    1024
+#define MAX_ENCODED_SIZE 2048
+
+static int test_encode_decode(const uint8_t *data, unsigned int data_size,
+                              const char *encoded_ref)
+{
+    char  encoded[MAX_ENCODED_SIZE];
+    uint8_t data2[MAX_DATA_SIZE];
+    int data2_size, max_data2_size = MAX_DATA_SIZE;
+
+    if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) {
+        printf("Failed: cannot encode the input data\n");
+        return 1;
+    }
+    if (encoded_ref && strcmp(encoded, encoded_ref)) {
+        printf("Failed: encoded string differs from reference\n"
+               "Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref);
+        return 1;
+    }
+
+    if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) != data_size) {
+        printf("Failed: cannot decode the encoded string\n"
+               "Encoded:\n%s\n", encoded);
+        return 1;
+    }
+    if ((data2_size = av_base64_decode(data2, encoded, data_size)) != data_size) {
+        printf("Failed: cannot decode with minimal buffer\n"
+               "Encoded:\n%s\n", encoded);
+        return 1;
+    }
+    if (memcmp(data2, data, data_size)) {
+        printf("Failed: encoded/decoded data differs from original data\n");
+        return 1;
+    }
+    if (av_base64_decode(NULL, encoded, 0) != 0) {
+        printf("Failed: decode to NULL buffer\n");
+        return 1;
+    }
+    if (strlen(encoded)) {
+        char *end = strchr(encoded, '=');
+        if (!end)
+            end = encoded + strlen(encoded) - 1;
+        *end = '%';
+        if (av_base64_decode(NULL, encoded, 0) >= 0) {
+            printf("Failed: error detection\n");
+            return 1;
+        }
+    }
+
+    printf("Passed!\n");
+    return 0;
+}
+
+int main(int argc, char ** argv)
+{
+    int i, error_count = 0;
+    struct test {
+        const uint8_t *data;
+        const char *encoded_ref;
+    } tests[] = {
+        { "",        ""},
+        { "1",       "MQ=="},
+        { "22",      "MjI="},
+        { "333",     "MzMz"},
+        { "4444",    "NDQ0NA=="},
+        { "55555",   "NTU1NTU="},
+        { "666666",  "NjY2NjY2"},
+        { "abc:def", "YWJjOmRlZg=="},
+    };
+    char in[1024], out[2048];
+
+    printf("Encoding/decoding tests\n");
+    for (i = 0; i < FF_ARRAY_ELEMS(tests); i++)
+        error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref);
+
+    if (argc>1 && !strcmp(argv[1], "-t")) {
+        memset(in, 123, sizeof(in));
+        for(i=0; i<10000; i++){
+            START_TIMER
+            av_base64_encode(out, sizeof(out), in, sizeof(in));
+            STOP_TIMER("encode")
+        }
+        for(i=0; i<10000; i++){
+            START_TIMER
+            av_base64_decode(in, out, sizeof(in));
+            STOP_TIMER("decode")
+        }
+
+        for(i=0; i<10000; i++){
+            START_TIMER
+            av_base64_decode(NULL, out, 0);
+            STOP_TIMER("syntax check")
+        }
+    }
+
+    if (error_count)
+        printf("Error Count: %d.\n", error_count);
+
+    return !!error_count;
+}
+
+// LCOV_EXCL_STOP
diff --git a/libavutil/tests/blowfish.c b/libavutil/tests/blowfish.c
new file mode 100644
index 0000000..f4c9ced
--- /dev/null
+++ b/libavutil/tests/blowfish.c
@@ -0,0 +1,194 @@
+/*
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libavutil/mem.h"
+#include "libavutil/blowfish.h"
+
+#define NUM_VARIABLE_KEY_TESTS 34
+
+/* plaintext bytes -- left halves */
+static const uint32_t plaintext_l[NUM_VARIABLE_KEY_TESTS] = {
+    0x00000000, 0xFFFFFFFF, 0x10000000, 0x11111111, 0x11111111,
+    0x01234567, 0x00000000, 0x01234567, 0x01A1D6D0, 0x5CD54CA8,
+    0x0248D438, 0x51454B58, 0x42FD4430, 0x059B5E08, 0x0756D8E0,
+    0x762514B8, 0x3BDD1190, 0x26955F68, 0x164D5E40, 0x6B056E18,
+    0x004BD6EF, 0x480D3900, 0x437540C8, 0x072D43A0, 0x02FE5577,
+    0x1D9D5C50, 0x30553228, 0x01234567, 0x01234567, 0x01234567,
+    0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF
+};
+
+/* plaintext bytes -- right halves */
+static const uint32_t plaintext_r[NUM_VARIABLE_KEY_TESTS] = {
+    0x00000000, 0xFFFFFFFF, 0x00000001, 0x11111111, 0x11111111,
+    0x89ABCDEF, 0x00000000, 0x89ABCDEF, 0x39776742, 0x3DEF57DA,
+    0x06F67172, 0x2DDF440A, 0x59577FA2, 0x51CF143A, 0x774761D2,
+    0x29BF486A, 0x49372802, 0x35AF609A, 0x4F275232, 0x759F5CCA,
+    0x09176062, 0x6EE762F2, 0x698F3CFA, 0x77075292, 0x8117F12A,
+    0x18F728C2, 0x6D6F295A, 0x89ABCDEF, 0x89ABCDEF, 0x89ABCDEF,
+    0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF
+};
+
+/* key bytes for variable key tests */
+static const uint8_t variable_key[NUM_VARIABLE_KEY_TESTS][8] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
+    { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 },
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 },
+    { 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57 },
+    { 0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E },
+    { 0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86 },
+    { 0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E },
+    { 0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6 },
+    { 0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE },
+    { 0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6 },
+    { 0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE },
+    { 0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16 },
+    { 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F },
+    { 0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46 },
+    { 0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E },
+    { 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76 },
+    { 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07 },
+    { 0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F },
+    { 0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7 },
+    { 0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF },
+    { 0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6 },
+    { 0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF },
+    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
+    { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }
+};
+
+/* ciphertext bytes -- left halves */
+static const uint32_t ciphertext_l[NUM_VARIABLE_KEY_TESTS] = {
+    0x4EF99745, 0x51866FD5, 0x7D856F9A, 0x2466DD87, 0x61F9C380,
+    0x7D0CC630, 0x4EF99745, 0x0ACEAB0F, 0x59C68245, 0xB1B8CC0B,
+    0x1730E577, 0xA25E7856, 0x353882B1, 0x48F4D088, 0x432193B7,
+    0x13F04154, 0x2EEDDA93, 0xD887E039, 0x5F99D04F, 0x4A057A3B,
+    0x452031C1, 0x7555AE39, 0x53C55F9C, 0x7A8E7BFA, 0xCF9C5D7A,
+    0xD1ABB290, 0x55CB3774, 0xFA34EC48, 0xA7907951, 0xC39E072D,
+    0x014933E0, 0xF21E9A77, 0x24594688, 0x6B5C5A9C
+};
+
+/* ciphertext bytes -- right halves */
+static const uint32_t ciphertext_r[NUM_VARIABLE_KEY_TESTS] = {
+    0x6198DD78, 0xB85ECB8A, 0x613063F2, 0x8B963C9D, 0x2281B096,
+    0xAFDA1EC7, 0x6198DD78, 0xC6A0A28D, 0xEB05282B, 0x250F09A0,
+    0x8BEA1DA4, 0xCF2651EB, 0x09CE8F1A, 0x4C379918, 0x8951FC98,
+    0xD69D1AE5, 0xFFD39C79, 0x3C2DA6E3, 0x5B163969, 0x24D3977B,
+    0xE4FADA8E, 0xF59B87BD, 0xB49FC019, 0x937E89A3, 0x4986ADB5,
+    0x658BC778, 0xD13EF201, 0x47B268B2, 0x08EA3CAE, 0x9FAC631D,
+    0xCDAFF6E4, 0xB71C49BC, 0x5754369A, 0x5D9E0A5A
+};
+
+/* plaintext bytes */
+static const uint8_t plaintext[8] = "BLOWFISH";
+
+static const uint8_t plaintext2[16] = "BLOWFISHBLOWFISH";
+
+/* ciphertext bytes */
+static const uint8_t ciphertext[8] = {
+    0x32, 0x4E, 0xD0, 0xFE, 0xF4, 0x13, 0xA2, 0x03
+};
+
+static const uint8_t ciphertext2[16] = {
+    0x53, 0x00, 0x40, 0x06, 0x63, 0xf2, 0x1d, 0x99,
+    0x3b, 0x9b, 0x27, 0x64, 0x46, 0xfd, 0x20, 0xc1,
+};
+
+#define IV "blowfish"
+
+static void test_blowfish(AVBlowfish *ctx, uint8_t *dst, const uint8_t *src,
+                          const uint8_t *ref, int len, uint8_t *iv, int dir,
+                          const char *test)
+{
+    av_blowfish_crypt(ctx, dst, src, len, iv, dir);
+    if (memcmp(dst, ref, 8*len)) {
+        int i;
+        printf("%s failed\ngot      ", test);
+        for (i = 0; i < 8*len; i++)
+            printf("%02x ", dst[i]);
+        printf("\nexpected ");
+        for (i = 0; i < 8*len; i++)
+            printf("%02x ", ref[i]);
+        printf("\n");
+        exit(1);
+    }
+}
+
+int main(void)
+{
+    uint32_t tmptext_l[NUM_VARIABLE_KEY_TESTS];
+    uint32_t tmptext_r[NUM_VARIABLE_KEY_TESTS];
+    uint8_t tmp[16], iv[8];
+    int i;
+    AVBlowfish *ctx = av_blowfish_alloc();
+    if (!ctx)
+        return 1;
+
+    av_blowfish_init(ctx, "abcdefghijklmnopqrstuvwxyz", 26);
+
+    test_blowfish(ctx, tmp, plaintext, ciphertext, 1, NULL, 0, "encryption");
+    test_blowfish(ctx, tmp, ciphertext, plaintext, 1, NULL, 1, "decryption");
+    test_blowfish(ctx, tmp, tmp, ciphertext, 1, NULL, 0, "Inplace encryption");
+    test_blowfish(ctx, tmp, tmp, plaintext,  1, NULL, 1, "Inplace decryption");
+    memcpy(iv, IV, 8);
+    test_blowfish(ctx, tmp, plaintext2, ciphertext2, 2, iv, 0, "CBC encryption");
+    memcpy(iv, IV, 8);
+    test_blowfish(ctx, tmp, ciphertext2, plaintext2, 2, iv, 1, "CBC decryption");
+    memcpy(iv, IV, 8);
+    test_blowfish(ctx, tmp, tmp, ciphertext2, 2, iv, 0, "Inplace CBC encryption");
+    memcpy(iv, IV, 8);
+    test_blowfish(ctx, tmp, tmp, plaintext2,  2, iv, 1, "Inplace CBC decryption");
+
+    memcpy(tmptext_l, plaintext_l, sizeof(*plaintext_l) * NUM_VARIABLE_KEY_TESTS);
+    memcpy(tmptext_r, plaintext_r, sizeof(*plaintext_r) * NUM_VARIABLE_KEY_TESTS);
+
+    for (i = 0; i < NUM_VARIABLE_KEY_TESTS; i++) {
+        av_blowfish_init(ctx, variable_key[i], 8);
+
+        av_blowfish_crypt_ecb(ctx, &tmptext_l[i], &tmptext_r[i], 0);
+        if (tmptext_l[i] != ciphertext_l[i] || tmptext_r[i] != ciphertext_r[i]) {
+            printf("Test encryption failed.\n");
+            return 2;
+        }
+
+        av_blowfish_crypt_ecb(ctx, &tmptext_l[i], &tmptext_r[i], 1);
+        if (tmptext_l[i] != plaintext_l[i] || tmptext_r[i] != plaintext_r[i]) {
+            printf("Test decryption failed.\n");
+            return 3;
+        }
+    }
+    printf("Test encryption/decryption success.\n");
+    av_free(ctx);
+
+    return 0;
+}
+
diff --git a/libavutil/tests/bprint.c b/libavutil/tests/bprint.c
new file mode 100644
index 0000000..d7f381d
--- /dev/null
+++ b/libavutil/tests/bprint.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2012 Nicolas George
+ *
+ * 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/bprint.c"
+
+#undef printf
+
+static void bprint_pascal(AVBPrint *b, unsigned size)
+{
+    unsigned i, j;
+    unsigned p[42];
+
+    av_assert0(size < FF_ARRAY_ELEMS(p));
+
+    p[0] = 1;
+    av_bprintf(b, "%8d\n", 1);
+    for (i = 1; i <= size; i++) {
+        p[i] = 1;
+        for (j = i - 1; j > 0; j--)
+            p[j] = p[j] + p[j - 1];
+        for (j = 0; j <= i; j++)
+            av_bprintf(b, "%8d", p[j]);
+        av_bprintf(b, "\n");
+    }
+}
+
+int main(void)
+{
+    AVBPrint b;
+    char buf[256];
+    struct tm testtime = { .tm_year = 100, .tm_mon = 11, .tm_mday = 20 };
+
+    av_bprint_init(&b, 0, -1);
+    bprint_pascal(&b, 5);
+    printf("Short text in unlimited buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
+    printf("%s\n", b.str);
+    av_bprint_finalize(&b, NULL);
+
+    av_bprint_init(&b, 0, -1);
+    bprint_pascal(&b, 25);
+    printf("Long text in unlimited buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
+    av_bprint_finalize(&b, NULL);
+
+    av_bprint_init(&b, 0, 2048);
+    bprint_pascal(&b, 25);
+    printf("Long text in limited buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
+    av_bprint_finalize(&b, NULL);
+
+    av_bprint_init(&b, 0, 1);
+    bprint_pascal(&b, 5);
+    printf("Short text in automatic buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
+
+    av_bprint_init(&b, 0, 1);
+    bprint_pascal(&b, 25);
+    printf("Long text in automatic buffer: %u/%u\n", (unsigned)strlen(b.str)/8*8, b.len);
+    /* Note that the size of the automatic buffer is arch-dependent. */
+
+    av_bprint_init(&b, 0, 0);
+    bprint_pascal(&b, 25);
+    printf("Long text count only buffer: %u/%u\n", (unsigned)strlen(b.str), b.len);
+
+    av_bprint_init_for_buffer(&b, buf, sizeof(buf));
+    bprint_pascal(&b, 25);
+    printf("Long text count only buffer: %u/%u\n", (unsigned)strlen(buf), b.len);
+
+    av_bprint_init(&b, 0, -1);
+    av_bprint_strftime(&b, "%Y-%m-%d", &testtime);
+    printf("strftime full: %u/%u \"%s\"\n", (unsigned)strlen(buf), b.len, b.str);
+    av_bprint_finalize(&b, NULL);
+
+    av_bprint_init(&b, 0, 8);
+    av_bprint_strftime(&b, "%Y-%m-%d", &testtime);
+    printf("strftime truncated: %u/%u \"%s\"\n", (unsigned)strlen(buf), b.len, b.str);
+
+    return 0;
+}
diff --git a/libavutil/tests/camellia.c b/libavutil/tests/camellia.c
new file mode 100644
index 0000000..1716b59
--- /dev/null
+++ b/libavutil/tests/camellia.c
@@ -0,0 +1,75 @@
+/*
+ * An implementation of the CAMELLIA algorithm as mentioned in RFC3713
+ * Copyright (c) 2014 Supraja Meedinti
+ *
+ * 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/camellia.h"
+#include "libavutil/log.h"
+
+int main(int argc, char *argv[])
+{
+    const uint8_t Key[3][32] = {
+        {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+        {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77},
+        {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
+    };
+    const uint8_t rct[3][16] = {
+        {0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43},
+        {0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9,0x96, 0xf8, 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9},
+        {0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09}
+    };
+    const uint8_t rpt[32] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
+    const int kbits[3] = {128, 192, 256};
+    int i, j, err = 0;
+    uint8_t temp[32], iv[16];
+    struct AVCAMELLIA *cs;
+    cs = av_camellia_alloc();
+    if (!cs)
+        return 1;
+    for (j = 0; j < 3; j++) {
+        av_camellia_init(cs, Key[j], kbits[j]);
+        av_camellia_crypt(cs, temp, rpt, 1, NULL, 0);
+        for (i = 0; i < 16; i++) {
+            if (rct[j][i] != temp[i]) {
+                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[j][i], temp[i]);
+                err = 1;
+            }
+        }
+        av_camellia_crypt(cs, temp, rct[j], 1, NULL, 1);
+        for (i = 0; i < 16; i++) {
+            if (rpt[i] != temp[i]) {
+                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
+                err = 1;
+            }
+        }
+    }
+    av_camellia_init(cs, Key[0], 128);
+    memcpy(iv, "HALLO123HALLO123", 16);
+    av_camellia_crypt(cs, temp, rpt, 2, iv, 0);
+    memcpy(iv, "HALLO123HALLO123", 16);
+    av_camellia_crypt(cs, temp, temp, 2, iv, 1);
+    for (i = 0; i < 32; i++) {
+        if (rpt[i] != temp[i]) {
+            av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
+            err = 1;
+        }
+    }
+    av_free(cs);
+    return err;
+}
diff --git a/libavutil/tests/cast5.c b/libavutil/tests/cast5.c
new file mode 100644
index 0000000..ce3aa80
--- /dev/null
+++ b/libavutil/tests/cast5.c
@@ -0,0 +1,103 @@
+/*
+ * An implementation of the CAST128 algorithm as mentioned in RFC2144
+ * Copyright (c) 2014 Supraja Meedinti
+ *
+ * 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/cast5.h"
+#include "libavutil/log.h"
+
+int main(int argc, char** argv)
+{
+
+    static const uint8_t Key[3][16] = {
+        {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a},
+        {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45},
+        {0x01, 0x23, 0x45, 0x67, 0x12}
+    };
+    static const uint8_t rpt[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
+    static const uint8_t rct[3][8] = {
+        {0x23, 0x8b, 0x4f, 0xe5, 0x84, 0x7e, 0x44, 0xb2},
+        {0xeb, 0x6a, 0x71, 0x1a, 0x2c, 0x02, 0x27, 0x1b},
+        {0x7a, 0xc8, 0x16, 0xd1, 0x6e, 0x9b, 0x30, 0x2e}
+    };
+    static const uint8_t rct2[2][16] = {
+        {0xee, 0xa9, 0xd0, 0xa2, 0x49, 0xfd, 0x3b, 0xa6, 0xb3, 0x43, 0x6f, 0xb8, 0x9d, 0x6d, 0xca, 0x92},
+        {0xb2, 0xc9, 0x5e, 0xb0, 0x0c, 0x31, 0xad, 0x71, 0x80, 0xac, 0x05, 0xb8, 0xe8, 0x3d, 0x69, 0x6e}
+    };
+    static const uint8_t iv[8] = {0xee, 0xa9, 0xd0, 0xa2, 0x49, 0xfd, 0x3b, 0xa6};
+    static uint8_t rpt2[2][16];
+    int i, j, err = 0;
+    static const int key_bits[3] = {128, 80, 40};
+    uint8_t temp[8];
+    struct AVCAST5 *cs;
+    cs = av_cast5_alloc();
+    if (!cs)
+        return 1;
+    for (j = 0; j < 3; j++){
+
+        av_cast5_init(cs, Key[j], key_bits[j]);
+        av_cast5_crypt(cs, temp, rpt, 1, 0);
+        for (i = 0;i < 8; i++){
+            if (rct[j][i] != temp[i]){
+                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[j][i], temp[i]);
+                err = 1;
+            }
+        }
+
+        av_cast5_crypt(cs, temp, rct[j], 1, 1);
+        for (i =0; i < 8; i++) {
+            if (rpt[i] != temp[i]) {
+                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
+                err = 1;
+            }
+        }
+    }
+    memcpy(rpt2[0], Key[0], 16);
+    memcpy(rpt2[1], Key[0], 16);
+    for (i = 0; i < 1000000; i++){
+        av_cast5_init(cs, rpt2[1], 128);
+        av_cast5_crypt(cs, rpt2[0], rpt2[0], 2, 0);
+        av_cast5_init(cs, rpt2[0], 128);
+        av_cast5_crypt(cs, rpt2[1], rpt2[1], 2, 0);
+    }
+    for (j = 0; j < 2; j++) {
+        for (i = 0; i < 16; i++) {
+            if (rct2[j][i] != rpt2[j][i]) {
+                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct2[j][i], rpt2[j][i]);
+                err = 1;
+            }
+        }
+    }
+    for (j = 0; j < 3; j++) {
+
+        av_cast5_init(cs, Key[j], key_bits[j]);
+        memcpy(temp, iv, 8);
+        av_cast5_crypt2(cs, rpt2[0], rct2[0], 2, temp, 0);
+        memcpy(temp, iv, 8);
+        av_cast5_crypt2(cs, rpt2[0], rpt2[0], 2, temp, 1);
+        for (i = 0; i < 16; i++) {
+            if (rct2[0][i] != rpt2[0][i]) {
+                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct2[0][i], rpt2[0][i]);
+                err = 1;
+            }
+        }
+    }
+    av_free(cs);
+    return err;
+}
diff --git a/libavutil/tests/color_utils.c b/libavutil/tests/color_utils.c
new file mode 100644
index 0000000..ea01271
--- /dev/null
+++ b/libavutil/tests/color_utils.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley at gmail.com>
+ *
+ * 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/color_utils.c"
+
+int main(int argc, char *argv[])
+{
+  int i, j;
+  static const double test_data[] = {
+      -0.1, -0.018053968510807, -0.01, -0.00449, 0.0, 0.00316227760, 0.005,
+      0.009, 0.015, 0.1, 1.0, 52.37, 125.098765, 1999.11123, 6945.443,
+      15123.4567, 19845.88923, 98678.4231, 99999.899998
+  };
+
+  for(i = 0; i < AVCOL_TRC_NB; i++) {
+      avpriv_trc_function func = avpriv_get_trc_function_from_trc(i);
+      for(j = 0; j < FF_ARRAY_ELEMS(test_data); j++) {
+          if(func != NULL) {
+              double result = func(test_data[j]);
+              printf("AVColorTransferCharacteristic=%d calling func(%f) expected=%f\n",
+                     i, test_data[j], result);
+          }
+      }
+  }
+
+}
diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c
new file mode 100644
index 0000000..f02a54c
--- /dev/null
+++ b/libavutil/tests/cpu.c
@@ -0,0 +1,147 @@
+/*
+ * 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 <stdio.h>
+
+#include "config.h"
+
+#include "libavutil/cpu.h"
+#include "libavutil/avstring.h"
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+static const struct {
+    int flag;
+    const char *name;
+} cpu_flag_tab[] = {
+#if   ARCH_AARCH64
+    { AV_CPU_FLAG_ARMV8,     "armv8"      },
+    { AV_CPU_FLAG_NEON,      "neon"       },
+    { AV_CPU_FLAG_VFP,       "vfp"        },
+#elif ARCH_ARM
+    { AV_CPU_FLAG_ARMV5TE,   "armv5te"    },
+    { AV_CPU_FLAG_ARMV6,     "armv6"      },
+    { AV_CPU_FLAG_ARMV6T2,   "armv6t2"    },
+    { AV_CPU_FLAG_VFP,       "vfp"        },
+    { AV_CPU_FLAG_VFP_VM,    "vfp_vm"     },
+    { AV_CPU_FLAG_VFPV3,     "vfpv3"      },
+    { AV_CPU_FLAG_NEON,      "neon"       },
+    { AV_CPU_FLAG_SETEND,    "setend"     },
+#elif ARCH_PPC
+    { AV_CPU_FLAG_ALTIVEC,   "altivec"    },
+#elif ARCH_X86
+    { AV_CPU_FLAG_MMX,       "mmx"        },
+    { AV_CPU_FLAG_MMXEXT,    "mmxext"     },
+    { AV_CPU_FLAG_SSE,       "sse"        },
+    { AV_CPU_FLAG_SSE2,      "sse2"       },
+    { AV_CPU_FLAG_SSE2SLOW,  "sse2slow"   },
+    { AV_CPU_FLAG_SSE3,      "sse3"       },
+    { AV_CPU_FLAG_SSE3SLOW,  "sse3slow"   },
+    { AV_CPU_FLAG_SSSE3,     "ssse3"      },
+    { AV_CPU_FLAG_ATOM,      "atom"       },
+    { AV_CPU_FLAG_SSE4,      "sse4.1"     },
+    { AV_CPU_FLAG_SSE42,     "sse4.2"     },
+    { AV_CPU_FLAG_AVX,       "avx"        },
+    { AV_CPU_FLAG_AVXSLOW,   "avxslow"    },
+    { AV_CPU_FLAG_XOP,       "xop"        },
+    { AV_CPU_FLAG_FMA3,      "fma3"       },
+    { AV_CPU_FLAG_FMA4,      "fma4"       },
+    { AV_CPU_FLAG_3DNOW,     "3dnow"      },
+    { AV_CPU_FLAG_3DNOWEXT,  "3dnowext"   },
+    { AV_CPU_FLAG_CMOV,      "cmov"       },
+    { AV_CPU_FLAG_AVX2,      "avx2"       },
+    { AV_CPU_FLAG_BMI1,      "bmi1"       },
+    { AV_CPU_FLAG_BMI2,      "bmi2"       },
+    { AV_CPU_FLAG_AESNI,     "aesni"      },
+#endif
+    { 0 }
+};
+
+static void print_cpu_flags(int cpu_flags, const char *type)
+{
+    int i;
+
+    printf("cpu_flags(%s) = 0x%08X\n", type, cpu_flags);
+    printf("cpu_flags_str(%s) =", type);
+    for (i = 0; cpu_flag_tab[i].flag; i++)
+        if (cpu_flags & cpu_flag_tab[i].flag)
+            printf(" %s", cpu_flag_tab[i].name);
+    printf("\n");
+}
+
+
+int main(int argc, char **argv)
+{
+    int cpu_flags_raw = av_get_cpu_flags();
+    int cpu_flags_eff;
+    int cpu_count = av_cpu_count();
+    char threads[5] = "auto";
+    int i;
+
+    for(i = 0; cpu_flag_tab[i].flag; i++) {
+        unsigned tmp = 0;
+        if (av_parse_cpu_caps(&tmp, cpu_flag_tab[i].name) < 0) {
+            fprintf(stderr, "Table missing %s\n", cpu_flag_tab[i].name);
+            return 4;
+        }
+    }
+
+    if (cpu_flags_raw < 0)
+        return 1;
+
+    for (;;) {
+        int c = getopt(argc, argv, "c:t:");
+        if (c == -1)
+            break;
+        switch (c) {
+        case 'c':
+        {
+            unsigned flags = av_get_cpu_flags();
+            if (av_parse_cpu_caps(&flags, optarg) < 0)
+                return 2;
+
+            av_force_cpu_flags(flags);
+            break;
+        }
+        case 't':
+        {
+            int len = av_strlcpy(threads, optarg, sizeof(threads));
+            if (len >= sizeof(threads)) {
+                fprintf(stderr, "Invalid thread count '%s'\n", optarg);
+                return 2;
+            }
+        }
+        }
+    }
+
+    cpu_flags_eff = av_get_cpu_flags();
+
+    if (cpu_flags_eff < 0)
+        return 3;
+
+    print_cpu_flags(cpu_flags_raw, "raw");
+    print_cpu_flags(cpu_flags_eff, "effective");
+    printf("threads = %s (cpu_count = %d)\n", threads, cpu_count);
+
+    return 0;
+}
diff --git a/libavutil/tests/crc.c b/libavutil/tests/crc.c
new file mode 100644
index 0000000..9825d6b
--- /dev/null
+++ b/libavutil/tests/crc.c
@@ -0,0 +1,46 @@
+/*
+ * 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 <stdint.h>
+#include <stdio.h>
+
+#include "libavutil/crc.h"
+
+int main(void)
+{
+    uint8_t buf[1999];
+    int i;
+    static const unsigned p[6][3] = {
+        { AV_CRC_32_IEEE_LE, 0xEDB88320, 0x3D5CDD04 },
+        { AV_CRC_32_IEEE   , 0x04C11DB7, 0xC0F5BAE0 },
+        { AV_CRC_24_IEEE   , 0x864CFB  , 0xB704CE   },
+        { AV_CRC_16_ANSI_LE, 0xA001    , 0xBFD8     },
+        { AV_CRC_16_ANSI   , 0x8005    , 0x1FBB     },
+        { AV_CRC_8_ATM     , 0x07      , 0xE3       }
+    };
+    const AVCRC *ctx;
+
+    for (i = 0; i < sizeof(buf); i++)
+        buf[i] = i + i * i;
+
+    for (i = 0; i < 6; i++) {
+        ctx = av_crc_get_table(p[i][0]);
+        printf("crc %08X = %X\n", p[i][1], av_crc(ctx, 0, buf, sizeof(buf)));
+    }
+    return 0;
+}
diff --git a/libavutil/tests/des.c b/libavutil/tests/des.c
new file mode 100644
index 0000000..ed04fad
--- /dev/null
+++ b/libavutil/tests/des.c
@@ -0,0 +1,128 @@
+/*
+ * 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/des.c"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libavutil/time.h"
+
+static uint64_t rand64(void)
+{
+    uint64_t r = rand();
+    r = (r << 32) | rand();
+    return r;
+}
+
+static const uint8_t test_key[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 };
+static const DECLARE_ALIGNED(8, uint8_t, plain)[] = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
+static const DECLARE_ALIGNED(8, uint8_t, crypt)[] = { 0x4a, 0xb6, 0x5b, 0x3d, 0x4b, 0x06, 0x15, 0x18 };
+static DECLARE_ALIGNED(8, uint8_t, tmp)[8];
+static DECLARE_ALIGNED(8, uint8_t, large_buffer)[10002][8];
+static const uint8_t cbc_key[] = {
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+    0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
+    0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
+};
+
+static int run_test(int cbc, int decrypt)
+{
+    AVDES d;
+    int delay = cbc && !decrypt ? 2 : 1;
+    uint64_t res;
+    AV_WB64(large_buffer[0], 0x4e6f772069732074ULL);
+    AV_WB64(large_buffer[1], 0x1234567890abcdefULL);
+    AV_WB64(tmp,             0x1234567890abcdefULL);
+    av_des_init(&d, cbc_key, 192, decrypt);
+    av_des_crypt(&d, large_buffer[delay], large_buffer[0], 10000, cbc ? tmp : NULL, decrypt);
+    res = AV_RB64(large_buffer[9999 + delay]);
+    if (cbc) {
+        if (decrypt)
+            return res == 0xc5cecf63ecec514cULL;
+        else
+            return res == 0xcb191f85d1ed8439ULL;
+    } else {
+        if (decrypt)
+            return res == 0x8325397644091a0aULL;
+        else
+            return res == 0xdd17e8b8b437d232ULL;
+    }
+}
+
+int main(void)
+{
+    AVDES d;
+    int i;
+    uint64_t key[3];
+    uint64_t data;
+    uint64_t ct;
+    uint64_t roundkeys[16];
+    srand(av_gettime());
+    key[0] = AV_RB64(test_key);
+    data   = AV_RB64(plain);
+    gen_roundkeys(roundkeys, key[0]);
+    if (des_encdec(data, roundkeys, 0) != AV_RB64(crypt)) {
+        printf("Test 1 failed\n");
+        return 1;
+    }
+    av_des_init(&d, test_key, 64, 0);
+    av_des_crypt(&d, tmp, plain, 1, NULL, 0);
+    if (memcmp(tmp, crypt, sizeof(crypt))) {
+        printf("Public API decryption failed\n");
+        return 1;
+    }
+    if (!run_test(0, 0) || !run_test(0, 1) || !run_test(1, 0) || !run_test(1, 1)) {
+        printf("Partial Monte-Carlo test failed\n");
+        return 1;
+    }
+    for (i = 0; i < 1000; i++) {
+        key[0] = rand64();
+        key[1] = rand64();
+        key[2] = rand64();
+        data   = rand64();
+        av_des_init(&d, (uint8_t *) key, 192, 0);
+        av_des_crypt(&d, (uint8_t *) &ct, (uint8_t *) &data, 1, NULL, 0);
+        av_des_init(&d, (uint8_t *) key, 192, 1);
+        av_des_crypt(&d, (uint8_t *) &ct, (uint8_t *) &ct, 1, NULL, 1);
+        if (ct != data) {
+            printf("Test 2 failed\n");
+            return 1;
+        }
+    }
+#ifdef GENTABLES
+    printf("static const uint32_t S_boxes_P_shuffle[8][64] = {\n");
+    for (i = 0; i < 8; i++) {
+        int j;
+        printf("    {");
+        for (j = 0; j < 64; j++) {
+            uint32_t v = S_boxes[i][j >> 1];
+            v   = j & 1 ? v >> 4 : v & 0xf;
+            v <<= 28 - 4 * i;
+            v   = shuffle(v, P_shuffle, sizeof(P_shuffle));
+            printf((j & 7) == 0 ? "\n    " : " ");
+            printf("0x%08X,", v);
+        }
+        printf("\n    },\n");
+    }
+    printf("};\n");
+#endif
+    return 0;
+}
diff --git a/libavutil/tests/dict.c b/libavutil/tests/dict.c
new file mode 100644
index 0000000..0039ba5
--- /dev/null
+++ b/libavutil/tests/dict.c
@@ -0,0 +1,133 @@
+/*
+ * copyright (c) 2009 Michael Niedermayer
+ *
+ * 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/dict.c"
+
+static void print_dict(const AVDictionary *m)
+{
+    AVDictionaryEntry *t = NULL;
+    while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX)))
+        printf("%s %s   ", t->key, t->value);
+    printf("\n");
+}
+
+static void test_separators(const AVDictionary *m, const char pair, const char val)
+{
+    AVDictionary *dict = NULL;
+    char pairs[] = {pair , '\0'};
+    char vals[]  = {val, '\0'};
+
+    char *buffer = NULL;
+    av_dict_copy(&dict, m, 0);
+    print_dict(dict);
+    av_dict_get_string(dict, &buffer, val, pair);
+    printf("%s\n", buffer);
+    av_dict_free(&dict);
+    av_dict_parse_string(&dict, buffer, vals, pairs, 0);
+    av_freep(&buffer);
+    print_dict(dict);
+    av_dict_free(&dict);
+}
+
+int main(void)
+{
+    AVDictionary *dict = NULL;
+    AVDictionaryEntry *e;
+    char *buffer = NULL;
+
+    printf("Testing av_dict_get_string() and av_dict_parse_string()\n");
+    av_dict_get_string(dict, &buffer, '=', ',');
+    printf("%s\n", buffer);
+    av_freep(&buffer);
+    av_dict_set(&dict, "aaa", "aaa", 0);
+    av_dict_set(&dict, "b,b", "bbb", 0);
+    av_dict_set(&dict, "c=c", "ccc", 0);
+    av_dict_set(&dict, "ddd", "d,d", 0);
+    av_dict_set(&dict, "eee", "e=e", 0);
+    av_dict_set(&dict, "f,f", "f=f", 0);
+    av_dict_set(&dict, "g=g", "g,g", 0);
+    test_separators(dict, ',', '=');
+    av_dict_free(&dict);
+    av_dict_set(&dict, "aaa", "aaa", 0);
+    av_dict_set(&dict, "bbb", "bbb", 0);
+    av_dict_set(&dict, "ccc", "ccc", 0);
+    av_dict_set(&dict, "\\,=\'\"", "\\,=\'\"", 0);
+    test_separators(dict, '"',  '=');
+    test_separators(dict, '\'', '=');
+    test_separators(dict, ',', '"');
+    test_separators(dict, ',', '\'');
+    test_separators(dict, '\'', '"');
+    test_separators(dict, '"', '\'');
+    av_dict_free(&dict);
+
+    printf("\nTesting av_dict_set()\n");
+    av_dict_set(&dict, "a", "a", 0);
+    av_dict_set(&dict, "b", av_strdup("b"), AV_DICT_DONT_STRDUP_VAL);
+    av_dict_set(&dict, av_strdup("c"), "c", AV_DICT_DONT_STRDUP_KEY);
+    av_dict_set(&dict, av_strdup("d"), av_strdup("d"), AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
+    av_dict_set(&dict, "e", "e", AV_DICT_DONT_OVERWRITE);
+    av_dict_set(&dict, "e", "f", AV_DICT_DONT_OVERWRITE);
+    av_dict_set(&dict, "f", "f", 0);
+    av_dict_set(&dict, "f", NULL, 0);
+    av_dict_set(&dict, "ff", "f", 0);
+    av_dict_set(&dict, "ff", "f", AV_DICT_APPEND);
+    e = NULL;
+    while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
+        printf("%s %s\n", e->key, e->value);
+    av_dict_free(&dict);
+
+    av_dict_set(&dict, NULL, "a", 0);
+    av_dict_set(&dict, NULL, "b", 0);
+    av_dict_get(dict, NULL, NULL, 0);
+    e = NULL;
+    while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
+        printf("'%s' '%s'\n", e->key, e->value);
+    av_dict_free(&dict);
+
+
+    //valgrind sensible test
+    printf("\nTesting av_dict_set_int()\n");
+    av_dict_set_int(&dict, "1", 1, AV_DICT_DONT_STRDUP_VAL);
+    av_dict_set_int(&dict, av_strdup("2"), 2, AV_DICT_DONT_STRDUP_KEY);
+    av_dict_set_int(&dict, av_strdup("3"), 3, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
+    av_dict_set_int(&dict, "4", 4, 0);
+    av_dict_set_int(&dict, "5", 5, AV_DICT_DONT_OVERWRITE);
+    av_dict_set_int(&dict, "5", 6, AV_DICT_DONT_OVERWRITE);
+    av_dict_set_int(&dict, "12", 1, 0);
+    av_dict_set_int(&dict, "12", 2, AV_DICT_APPEND);
+    e = NULL;
+    while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
+        printf("%s %s\n", e->key, e->value);
+    av_dict_free(&dict);
+
+    //valgrind sensible test
+    printf("\nTesting av_dict_set() with existing AVDictionaryEntry.key as key\n");
+    av_dict_set(&dict, "key", "old", 0);
+    e = av_dict_get(dict, "key", NULL, 0);
+    av_dict_set(&dict, e->key, "new val OK", 0);
+    e = av_dict_get(dict, "key", NULL, 0);
+    printf("%s\n", e->value);
+    av_dict_set(&dict, e->key, e->value, 0);
+    e = av_dict_get(dict, "key", NULL, 0);
+    printf("%s\n", e->value);
+    av_dict_free(&dict);
+
+    return 0;
+}
diff --git a/libavutil/tests/display.c b/libavutil/tests/display.c
new file mode 100644
index 0000000..893ebb5
--- /dev/null
+++ b/libavutil/tests/display.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014 Vittorio Giovara <vittorio.giovara at gmail.com>
+ *
+ * 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/display.c"
+
+static void print_matrix(int32_t matrix[9])
+{
+    int i, j;
+
+    for (i = 0; i < 3; ++i) {
+        for (j = 0; j < 3 - 1; ++j)
+            printf("%d ", matrix[i*3 + j]);
+
+        printf("%d\n", matrix[i*3 + j]);
+    }
+}
+
+int main(void)
+{
+    int32_t matrix[9];
+
+    // Set the matrix to 90 degrees
+    av_display_rotation_set(matrix, 90);
+    print_matrix(matrix);
+    printf("degrees: %f\n", av_display_rotation_get(matrix));
+
+    // Set the matrix to -45 degrees
+    av_display_rotation_set(matrix, -45);
+    print_matrix(matrix);
+    printf("degrees: %f\n", av_display_rotation_get(matrix));
+
+    // flip horizontal
+    av_display_matrix_flip(matrix, 1, 0);
+    print_matrix(matrix);
+    printf("degrees: %f\n", av_display_rotation_get(matrix));
+
+    // flip vertical
+    av_display_matrix_flip(matrix, 0, 1);
+    print_matrix(matrix);
+    printf("degrees: %f\n", av_display_rotation_get(matrix));
+
+    return 0;
+
+}
diff --git a/libavutil/tests/error.c b/libavutil/tests/error.c
new file mode 100644
index 0000000..16efc8a
--- /dev/null
+++ b/libavutil/tests/error.c
@@ -0,0 +1,37 @@
+/*
+ * 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/error.c"
+
+#undef printf
+
+int main(void)
+{
+    int i;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(error_entries); i++) {
+        const struct error_entry *entry = &error_entries[i];
+        printf("%d: %s [%s]\n", entry->num, av_err2str(entry->num), entry->tag);
+    }
+
+    for (i = 0; i < 256; i++) {
+        printf("%d: %s\n", -i, av_err2str(-i));
+    }
+
+    return 0;
+}
diff --git a/libavutil/tests/eval.c b/libavutil/tests/eval.c
new file mode 100644
index 0000000..2a1afcc
--- /dev/null
+++ b/libavutil/tests/eval.c
@@ -0,0 +1,183 @@
+/*
+ * 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 <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/libm.h"
+#include "libavutil/timer.h"
+#include "libavutil/eval.h"
+
+static const double const_values[] = {
+    M_PI,
+    M_E,
+    0
+};
+
+static const char *const const_names[] = {
+    "PI",
+    "E",
+    0
+};
+
+int main(int argc, char **argv)
+{
+    int i;
+    double d;
+    const char *const *expr;
+    static const char *const exprs[] = {
+        "",
+        "1;2",
+        "-20",
+        "-PI",
+        "+PI",
+        "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
+        "80G/80Gi",
+        "1k",
+        "1Gi",
+        "1gi",
+        "1GiFoo",
+        "1k+1k",
+        "1Gi*3foo",
+        "foo",
+        "foo(",
+        "foo()",
+        "foo)",
+        "sin",
+        "sin(",
+        "sin()",
+        "sin)",
+        "sin 10",
+        "sin(1,2,3)",
+        "sin(1 )",
+        "1",
+        "1foo",
+        "bar + PI + E + 100f*2 + foo",
+        "13k + 12f - foo(1, 2)",
+        "1gi",
+        "1Gi",
+        "st(0, 123)",
+        "st(1, 123); ld(1)",
+        "lte(0, 1)",
+        "lte(1, 1)",
+        "lte(1, 0)",
+        "lt(0, 1)",
+        "lt(1, 1)",
+        "gt(1, 0)",
+        "gt(2, 7)",
+        "gte(122, 122)",
+        /* compute 1+2+...+N */
+        "st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)",
+        /* compute Fib(N) */
+        "st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)",
+        "while(0, 10)",
+        "st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))",
+        "isnan(1)",
+        "isnan(NAN)",
+        "isnan(INF)",
+        "isinf(1)",
+        "isinf(NAN)",
+        "isinf(INF)",
+        "floor(NAN)",
+        "floor(123.123)",
+        "floor(-123.123)",
+        "trunc(123.123)",
+        "trunc(-123.123)",
+        "ceil(123.123)",
+        "ceil(-123.123)",
+        "sqrt(1764)",
+        "isnan(sqrt(-1))",
+        "not(1)",
+        "not(NAN)",
+        "not(0)",
+        "6.0206dB",
+        "-3.0103dB",
+        "pow(0,1.23)",
+        "pow(PI,1.23)",
+        "PI^1.23",
+        "pow(-1,1.23)",
+        "if(1, 2)",
+        "if(1, 1, 2)",
+        "if(0, 1, 2)",
+        "ifnot(0, 23)",
+        "ifnot(1, NaN) + if(0, 1)",
+        "ifnot(1, 1, 2)",
+        "ifnot(0, 1, 2)",
+        "taylor(1, 1)",
+        "taylor(eq(mod(ld(1),4),1)-eq(mod(ld(1),4),3), PI/2, 1)",
+        "root(sin(ld(0))-1, 2)",
+        "root(sin(ld(0))+6+sin(ld(0)/12)-log(ld(0)), 100)",
+        "7000000B*random(0)",
+        "squish(2)",
+        "gauss(0.1)",
+        "hypot(4,3)",
+        "gcd(30,55)*print(min(9,1))",
+        "bitor(42, 12)",
+        "bitand(42, 12)",
+        "bitand(NAN, 1)",
+        "between(10, -3, 10)",
+        "between(-4, -2, -1)",
+        "between(1,2)",
+        "clip(0, 2, 1)",
+        "clip(0/0, 1, 2)",
+        "clip(0, 0/0, 1)",
+        NULL
+    };
+    int ret;
+
+    for (expr = exprs; *expr; expr++) {
+        printf("Evaluating '%s'\n", *expr);
+        ret = av_expr_parse_and_eval(&d, *expr,
+                               const_names, const_values,
+                               NULL, NULL, NULL, NULL, NULL, 0, NULL);
+        if (isnan(d))
+            printf("'%s' -> nan\n\n", *expr);
+        else
+            printf("'%s' -> %f\n\n", *expr, d);
+        if (ret < 0)
+            printf("av_expr_parse_and_eval failed\n");
+    }
+
+    ret = av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
+                           const_names, const_values,
+                           NULL, NULL, NULL, NULL, NULL, 0, NULL);
+    printf("%f == 12.7\n", d);
+    if (ret < 0)
+        printf("av_expr_parse_and_eval failed\n");
+    ret = av_expr_parse_and_eval(&d, "80G/80Gi",
+                           const_names, const_values,
+                           NULL, NULL, NULL, NULL, NULL, 0, NULL);
+    printf("%f == 0.931322575\n", d);
+    if (ret < 0)
+        printf("av_expr_parse_and_eval failed\n");
+
+    if (argc > 1 && !strcmp(argv[1], "-t")) {
+        for (i = 0; i < 1050; i++) {
+            START_TIMER;
+            ret = av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
+                                   const_names, const_values,
+                                   NULL, NULL, NULL, NULL, NULL, 0, NULL);
+            if (ret < 0)
+                printf("av_expr_parse_and_eval failed\n");
+            STOP_TIMER("av_expr_parse_and_eval");
+        }
+    }
+
+    return 0;
+}
diff --git a/libavutil/tests/fifo.c b/libavutil/tests/fifo.c
new file mode 100644
index 0000000..e4d7edf
--- /dev/null
+++ b/libavutil/tests/fifo.c
@@ -0,0 +1,74 @@
+/*
+ * 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 <stdio.h>
+
+#include "libavutil/fifo.h"
+
+int main(void)
+{
+    /* create a FIFO buffer */
+    AVFifoBuffer *fifo = av_fifo_alloc(13 * sizeof(int));
+    int i, j, n;
+
+    /* fill data */
+    for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++)
+        av_fifo_generic_write(fifo, &i, sizeof(int), NULL);
+
+    /* peek at FIFO */
+    n = av_fifo_size(fifo) / sizeof(int);
+    for (i = -n + 1; i < n; i++) {
+        int *v = (int *)av_fifo_peek2(fifo, i * sizeof(int));
+        printf("%d: %d\n", i, *v);
+    }
+    printf("\n");
+
+    /* peek_at at FIFO */
+    n = av_fifo_size(fifo) / sizeof(int);
+    for (i = 0; i < n; i++) {
+        av_fifo_generic_peek_at(fifo, &j, i * sizeof(int), sizeof(j), NULL);
+        printf("%d: %d\n", i, j);
+    }
+    printf("\n");
+
+    /* read data */
+    for (i = 0; av_fifo_size(fifo) >= sizeof(int); i++) {
+        av_fifo_generic_read(fifo, &j, sizeof(int), NULL);
+        printf("%d ", j);
+    }
+    printf("\n");
+
+    /* test *ndx overflow */
+    av_fifo_reset(fifo);
+    fifo->rndx = fifo->wndx = ~(uint32_t)0 - 5;
+
+    /* fill data */
+    for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++)
+        av_fifo_generic_write(fifo, &i, sizeof(int), NULL);
+
+    /* peek_at at FIFO */
+    n = av_fifo_size(fifo) / sizeof(int);
+    for (i = 0; i < n; i++) {
+        av_fifo_generic_peek_at(fifo, &j, i * sizeof(int), sizeof(j), NULL);
+        printf("%d: %d\n", i, j);
+    }
+
+    av_fifo_free(fifo);
+
+    return 0;
+}
diff --git a/libavutil/tests/file.c b/libavutil/tests/file.c
new file mode 100644
index 0000000..3608bcc
--- /dev/null
+++ b/libavutil/tests/file.c
@@ -0,0 +1,34 @@
+/*
+ * 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/file.c"
+
+#undef printf
+
+int main(void)
+{
+    uint8_t *buf;
+    size_t size;
+    if (av_file_map("file.c", &buf, &size, 0, NULL) < 0)
+        return 1;
+
+    buf[0] = 's';
+    printf("%s", buf);
+    av_file_unmap(buf, size);
+    return 0;
+}
diff --git a/libavutil/tests/float_dsp.c b/libavutil/tests/float_dsp.c
new file mode 100644
index 0000000..053324d
--- /dev/null
+++ b/libavutil/tests/float_dsp.c
@@ -0,0 +1,333 @@
+/*
+ * 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 "config.h"
+
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h> /* for getopt */
+#endif
+#if !HAVE_GETOPT
+#include "compat/getopt.c"
+#endif
+
+#include "libavutil/common.h"
+#include "libavutil/cpu.h"
+#include "libavutil/internal.h"
+#include "libavutil/lfg.h"
+#include "libavutil/log.h"
+#include "libavutil/random_seed.h"
+#include "libavutil/float_dsp.h"
+
+#define LEN 240
+
+static void fill_float_array(AVLFG *lfg, float *a, int len)
+{
+    int i;
+    double bmg[2], stddev = 10.0, mean = 0.0;
+
+    for (i = 0; i < len; i += 2) {
+        av_bmg_get(lfg, bmg);
+        a[i]     = bmg[0] * stddev + mean;
+        a[i + 1] = bmg[1] * stddev + mean;
+    }
+}
+static int compare_floats(const float *a, const float *b, int len,
+                          float max_diff)
+{
+    int i;
+    for (i = 0; i < len; i++) {
+        if (fabsf(a[i] - b[i]) > max_diff) {
+            av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n",
+                   i, a[i], b[i], a[i] - b[i]);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static void fill_double_array(AVLFG *lfg, double *a, int len)
+{
+    int i;
+    double bmg[2], stddev = 10.0, mean = 0.0;
+
+    for (i = 0; i < len; i += 2) {
+        av_bmg_get(lfg, bmg);
+        a[i]     = bmg[0] * stddev + mean;
+        a[i + 1] = bmg[1] * stddev + mean;
+    }
+}
+
+static int compare_doubles(const double *a, const double *b, int len,
+                           double max_diff)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        if (fabs(a[i] - b[i]) > max_diff) {
+            av_log(NULL, AV_LOG_ERROR, "%d: %- .12f - %- .12f = % .12g\n",
+                   i, a[i], b[i], a[i] - b[i]);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int test_vector_fmul(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
+                            const float *v1, const float *v2)
+{
+    LOCAL_ALIGNED(32, float, cdst, [LEN]);
+    LOCAL_ALIGNED(32, float, odst, [LEN]);
+    int ret;
+
+    cdsp->vector_fmul(cdst, v1, v2, LEN);
+    fdsp->vector_fmul(odst, v1, v2, LEN);
+
+    if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON))
+        av_log(NULL, AV_LOG_ERROR, "vector_fmul failed\n");
+
+    return ret;
+}
+
+#define ARBITRARY_FMAC_SCALAR_CONST 0.005
+static int test_vector_fmac_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
+                                   const float *v1, const float *src0, float scale)
+{
+    LOCAL_ALIGNED(32, float, cdst, [LEN]);
+    LOCAL_ALIGNED(32, float, odst, [LEN]);
+    int ret;
+
+    memcpy(cdst, v1, LEN * sizeof(*v1));
+    memcpy(odst, v1, LEN * sizeof(*v1));
+
+    cdsp->vector_fmac_scalar(cdst, src0, scale, LEN);
+    fdsp->vector_fmac_scalar(odst, src0, scale, LEN);
+
+    if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMAC_SCALAR_CONST))
+        av_log(NULL, AV_LOG_ERROR, "vector_fmac_scalar failed\n");
+
+    return ret;
+}
+
+static int test_vector_fmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
+                                   const float *v1, float scale)
+{
+    LOCAL_ALIGNED(32, float, cdst, [LEN]);
+    LOCAL_ALIGNED(32, float, odst, [LEN]);
+    int ret;
+
+    cdsp->vector_fmul_scalar(cdst, v1, scale, LEN);
+    fdsp->vector_fmul_scalar(odst, v1, scale, LEN);
+
+    if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON))
+        av_log(NULL, AV_LOG_ERROR, "vector_fmul_scalar failed\n");
+
+    return ret;
+}
+
+static int test_vector_dmul_scalar(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
+                                   const double *v1, double scale)
+{
+    LOCAL_ALIGNED(32, double, cdst, [LEN]);
+    LOCAL_ALIGNED(32, double, odst, [LEN]);
+    int ret;
+
+    cdsp->vector_dmul_scalar(cdst, v1, scale, LEN);
+    fdsp->vector_dmul_scalar(odst, v1, scale, LEN);
+
+    if (ret = compare_doubles(cdst, odst, LEN, DBL_EPSILON))
+        av_log(NULL, AV_LOG_ERROR, "vector_dmul_scalar failed\n");
+
+    return ret;
+}
+
+#define ARBITRARY_FMUL_WINDOW_CONST 0.008
+static int test_vector_fmul_window(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
+                                   const float *v1, const float *v2, const float *v3)
+{
+    LOCAL_ALIGNED(32, float, cdst, [LEN]);
+    LOCAL_ALIGNED(32, float, odst, [LEN]);
+    int ret;
+
+    cdsp->vector_fmul_window(cdst, v1, v2, v3, LEN / 2);
+    fdsp->vector_fmul_window(odst, v1, v2, v3, LEN / 2);
+
+    if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_WINDOW_CONST))
+        av_log(NULL, AV_LOG_ERROR, "vector_fmul_window failed\n");
+
+    return ret;
+}
+
+#define ARBITRARY_FMUL_ADD_CONST 0.005
+static int test_vector_fmul_add(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
+                                const float *v1, const float *v2, const float *v3)
+{
+    LOCAL_ALIGNED(32, float, cdst, [LEN]);
+    LOCAL_ALIGNED(32, float, odst, [LEN]);
+    int ret;
+
+    cdsp->vector_fmul_add(cdst, v1, v2, v3, LEN);
+    fdsp->vector_fmul_add(odst, v1, v2, v3, LEN);
+
+    if (ret = compare_floats(cdst, odst, LEN, ARBITRARY_FMUL_ADD_CONST))
+        av_log(NULL, AV_LOG_ERROR, "vector_fmul_add failed\n");
+
+    return ret;
+}
+
+static int test_vector_fmul_reverse(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
+                                    const float *v1, const float *v2)
+{
+    LOCAL_ALIGNED(32, float, cdst, [LEN]);
+    LOCAL_ALIGNED(32, float, odst, [LEN]);
+    int ret;
+
+    cdsp->vector_fmul_reverse(cdst, v1, v2, LEN);
+    fdsp->vector_fmul_reverse(odst, v1, v2, LEN);
+
+    if (ret = compare_floats(cdst, odst, LEN, FLT_EPSILON))
+        av_log(NULL, AV_LOG_ERROR, "vector_fmul_reverse failed\n");
+
+    return ret;
+}
+
+static int test_butterflies_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
+                                  const float *v1, const float *v2)
+{
+    LOCAL_ALIGNED(32, float, cv1, [LEN]);
+    LOCAL_ALIGNED(32, float, cv2, [LEN]);
+    LOCAL_ALIGNED(32, float, ov1, [LEN]);
+    LOCAL_ALIGNED(32, float, ov2, [LEN]);
+    int ret;
+
+    memcpy(cv1, v1, LEN * sizeof(*v1));
+    memcpy(cv2, v2, LEN * sizeof(*v2));
+    memcpy(ov1, v1, LEN * sizeof(*v1));
+    memcpy(ov2, v2, LEN * sizeof(*v2));
+
+    cdsp->butterflies_float(cv1, cv2, LEN);
+    fdsp->butterflies_float(ov1, ov2, LEN);
+
+    if ((ret = compare_floats(cv1, ov1, LEN, FLT_EPSILON)) ||
+        (ret = compare_floats(cv2, ov2, LEN, FLT_EPSILON)))
+        av_log(NULL, AV_LOG_ERROR, "butterflies_float failed\n");
+
+    return ret;
+}
+
+#define ARBITRARY_SCALARPRODUCT_CONST 0.2
+static int test_scalarproduct_float(AVFloatDSPContext *fdsp, AVFloatDSPContext *cdsp,
+                                    const float *v1, const float *v2)
+{
+    float cprod, oprod;
+    int ret;
+
+    cprod = cdsp->scalarproduct_float(v1, v2, LEN);
+    oprod = fdsp->scalarproduct_float(v1, v2, LEN);
+
+    if (ret = compare_floats(&cprod, &oprod, 1, ARBITRARY_SCALARPRODUCT_CONST))
+        av_log(NULL, AV_LOG_ERROR, "scalarproduct_float failed\n");
+
+    return ret;
+}
+
+int main(int argc, char **argv)
+{
+    int ret = 0, seeded = 0;
+    uint32_t seed;
+    AVFloatDSPContext *fdsp, *cdsp;
+    AVLFG lfg;
+
+    LOCAL_ALIGNED(32, float, src0, [LEN]);
+    LOCAL_ALIGNED(32, float, src1, [LEN]);
+    LOCAL_ALIGNED(32, float, src2, [LEN]);
+    LOCAL_ALIGNED(32, double, dbl_src0, [LEN]);
+    LOCAL_ALIGNED(32, double, dbl_src1, [LEN]);
+
+    for (;;) {
+        int arg = getopt(argc, argv, "s:c:");
+        if (arg == -1)
+            break;
+        switch (arg) {
+        case 's':
+            seed = strtoul(optarg, NULL, 10);
+            seeded = 1;
+            break;
+        case 'c':
+        {
+            int cpuflags = av_get_cpu_flags();
+
+            if (av_parse_cpu_caps(&cpuflags, optarg) < 0)
+                return 1;
+
+            av_force_cpu_flags(cpuflags);
+            break;
+        }
+        }
+    }
+    if (!seeded)
+        seed = av_get_random_seed();
+
+    av_log(NULL, AV_LOG_INFO, "float_dsp-test: %s %u\n", seeded ? "seed" : "random seed", seed);
+
+    fdsp = avpriv_float_dsp_alloc(1);
+    av_force_cpu_flags(0);
+    cdsp = avpriv_float_dsp_alloc(1);
+
+    if (!fdsp || !cdsp) {
+        ret = 1;
+        goto end;
+    }
+
+    av_lfg_init(&lfg, seed);
+
+    fill_float_array(&lfg, src0, LEN);
+    fill_float_array(&lfg, src1, LEN);
+    fill_float_array(&lfg, src2, LEN);
+
+    fill_double_array(&lfg, dbl_src0, LEN);
+    fill_double_array(&lfg, dbl_src1, LEN);
+
+    if (test_vector_fmul(fdsp, cdsp, src0, src1))
+        ret -= 1 << 0;
+    if (test_vector_fmac_scalar(fdsp, cdsp, src2, src0, src1[0]))
+        ret -= 1 << 1;
+    if (test_vector_fmul_scalar(fdsp, cdsp, src0, src1[0]))
+        ret -= 1 << 2;
+    if (test_vector_fmul_window(fdsp, cdsp, src0, src1, src2))
+        ret -= 1 << 3;
+    if (test_vector_fmul_add(fdsp, cdsp, src0, src1, src2))
+        ret -= 1 << 4;
+    if (test_vector_fmul_reverse(fdsp, cdsp, src0, src1))
+        ret -= 1 << 5;
+    if (test_butterflies_float(fdsp, cdsp, src0, src1))
+        ret -= 1 << 6;
+    if (test_scalarproduct_float(fdsp, cdsp, src0, src1))
+        ret -= 1 << 7;
+    if (test_vector_dmul_scalar(fdsp, cdsp, dbl_src0, dbl_src1[0]))
+        ret -= 1 << 8;
+
+end:
+    av_freep(&fdsp);
+    av_freep(&cdsp);
+    return ret;
+}
diff --git a/libavutil/tests/hash.c b/libavutil/tests/hash.c
new file mode 100644
index 0000000..4f2ad52
--- /dev/null
+++ b/libavutil/tests/hash.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 Reimar Döffinger <Reimar.Doeffinger at gmx.de>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+
+#include "libavutil/hash.h"
+
+#define SRC_BUF_SIZE 64
+#define DST_BUF_SIZE (AV_HASH_MAX_SIZE * 8)
+
+int main(void)
+{
+   struct AVHashContext *ctx = NULL;
+   int i, j, numhashes = 0;
+   static const uint8_t src[SRC_BUF_SIZE] = { 0 };
+   uint8_t dst[DST_BUF_SIZE];
+
+   while (av_hash_names(numhashes))
+       numhashes++;
+
+   for (i = 0; i < numhashes; i++) {
+       if (av_hash_alloc(&ctx, av_hash_names(i)) < 0)
+           return 1;
+
+       av_hash_init(ctx);
+       av_hash_update(ctx, src, SRC_BUF_SIZE);
+       memset(dst, 0, DST_BUF_SIZE);
+       av_hash_final_hex(ctx, dst, DST_BUF_SIZE);
+       printf("%s hex: %s\n", av_hash_get_name(ctx), dst);
+
+       av_hash_init(ctx);
+       av_hash_update(ctx, src, SRC_BUF_SIZE);
+       av_hash_final_bin(ctx, dst, DST_BUF_SIZE);
+       printf("%s bin: ", av_hash_get_name(ctx));
+       for (j = 0; j < av_hash_get_size(ctx); j++) {
+           printf("%#x ", dst[j]);
+       }
+       printf("\n");
+
+       av_hash_init(ctx);
+       av_hash_update(ctx, src, SRC_BUF_SIZE);
+       av_hash_final_b64(ctx, dst, DST_BUF_SIZE);
+       printf("%s b64: %s\n", av_hash_get_name(ctx), dst);
+       av_hash_freep(&ctx);
+   }
+   return 0;
+}
diff --git a/libavutil/tests/hmac.c b/libavutil/tests/hmac.c
new file mode 100644
index 0000000..5eeb63c
--- /dev/null
+++ b/libavutil/tests/hmac.c
@@ -0,0 +1,99 @@
+/*
+ * 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/hmac.c"
+
+#include <stdio.h>
+#include <string.h>
+
+static void test(AVHMAC *hmac, const uint8_t *key, int keylen,
+                 const uint8_t *data, int datalen)
+{
+    uint8_t buf[MAX_HASHLEN];
+    int out, i;
+    // Some of the test vectors are strings, where sizeof() includes the
+    // trailing null byte - remove that.
+    if (!key[keylen - 1])
+        keylen--;
+    if (!data[datalen - 1])
+        datalen--;
+    out = av_hmac_calc(hmac, data, datalen, key, keylen, buf, sizeof(buf));
+    for (i = 0; i < out; i++)
+        printf("%02x", buf[i]);
+    printf("\n");
+}
+
+int main(void)
+{
+    uint8_t key1[20], key3[131], data3[50];
+    AVHMAC *hmac;
+    enum AVHMACType i;
+    static const uint8_t key2[]  = "Jefe";
+    static const uint8_t data1[] = "Hi There";
+    static const uint8_t data2[] = "what do ya want for nothing?";
+    static const uint8_t data4[] = "Test Using Larger Than Block-Size Key - Hash Key First";
+    static const uint8_t data5[] = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data";
+    static const uint8_t data6[] = "This is a test using a larger than block-size key and a larger "
+                            "than block-size data. The key needs to be hashed before being used"
+                            " by the HMAC algorithm.";
+    memset(key1, 0x0b, sizeof(key1));
+    memset(key3, 0xaa, sizeof(key3));
+    memset(data3, 0xdd, sizeof(data3));
+
+    /* MD5, SHA-1 */
+    for (i = AV_HMAC_MD5; i <= AV_HMAC_SHA1; i++) {
+        hmac = av_hmac_alloc(i);
+        if (!hmac)
+            return 1;
+        // RFC 2202 test vectors
+        test(hmac, key1, hmac->hashlen, data1, sizeof(data1));
+        test(hmac, key2, sizeof(key2),  data2, sizeof(data2));
+        test(hmac, key3, hmac->hashlen, data3, sizeof(data3));
+        test(hmac, key3, 80,            data4, sizeof(data4));
+        test(hmac, key3, 80,            data5, sizeof(data5));
+        av_hmac_free(hmac);
+    }
+
+    /* SHA-2 */
+    for (i = AV_HMAC_SHA224; i <= AV_HMAC_SHA256; i++) {
+        hmac = av_hmac_alloc(i);
+        if (!hmac)
+            return 1;
+        // RFC 4231 test vectors
+        test(hmac, key1, sizeof(key1), data1, sizeof(data1));
+        test(hmac, key2, sizeof(key2), data2, sizeof(data2));
+        test(hmac, key3, 20,           data3, sizeof(data3));
+        test(hmac, key3, sizeof(key3), data4, sizeof(data4));
+        test(hmac, key3, sizeof(key3), data6, sizeof(data6));
+        av_hmac_free(hmac);
+    }
+
+    for (i = AV_HMAC_SHA384; i <= AV_HMAC_SHA512; i++) {
+        hmac = av_hmac_alloc(i);
+        if (!hmac)
+            return 1;
+        // RFC 4231 test vectors
+        test(hmac, key1, sizeof(key1), data1, sizeof(data1));
+        test(hmac, key2, sizeof(key2), data2, sizeof(data2));
+        test(hmac, key3, 20, data3, sizeof(data3));
+        test(hmac, key3, sizeof(key3), data4, sizeof(data4));
+        test(hmac, key3, sizeof(key3), data6, sizeof(data6));
+        av_hmac_free(hmac);
+    }
+    return 0;
+}
diff --git a/libavutil/tests/lfg.c b/libavutil/tests/lfg.c
new file mode 100644
index 0000000..1425e02
--- /dev/null
+++ b/libavutil/tests/lfg.c
@@ -0,0 +1,74 @@
+/*
+ * 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/log.h"
+#include "libavutil/timer.h"
+#include "libavutil/lfg.h"
+
+int main(void)
+{
+    int x = 0;
+    int i, j;
+    AVLFG state;
+
+    av_lfg_init(&state, 0xdeadbeef);
+    for (j = 0; j < 10000; j++) {
+        START_TIMER
+        for (i = 0; i < 624; i++) {
+            //av_log(NULL, AV_LOG_ERROR, "%X\n", av_lfg_get(&state));
+            x += av_lfg_get(&state);
+        }
+        STOP_TIMER("624 calls of av_lfg_get");
+    }
+    av_log(NULL, AV_LOG_ERROR, "final value:%X\n", x);
+
+    /* BMG usage example */
+    {
+        double mean   = 1000;
+        double stddev = 53;
+        double samp_mean = 0.0, samp_stddev = 0.0;
+        double samp0, samp1;
+
+        av_lfg_init(&state, 42);
+
+        for (i = 0; i < 1000; i += 2) {
+            double bmg_out[2];
+            av_bmg_get(&state, bmg_out);
+            samp0 = bmg_out[0] * stddev + mean;
+            samp1 = bmg_out[1] * stddev + mean;
+            samp_mean += samp0 + samp1;
+            samp_stddev += samp0 * samp0 + samp1 * samp1;
+            av_log(NULL, AV_LOG_INFO,
+                   "%f\n%f\n",
+                   samp0,
+                   samp1);
+        }
+        /* TODO: add proper normality test */
+        samp_mean /= 1000;
+        samp_stddev /= 999;
+        samp_stddev -= (1000.0/999.0)*samp_mean*samp_mean;
+        samp_stddev = sqrt(samp_stddev);
+        av_log(NULL, AV_LOG_INFO, "sample mean  : %f\n"
+                                  "true mean    : %f\n"
+                                  "sample stddev: %f\n"
+                                  "true stddev  : %f\n",
+                                   samp_mean, mean, samp_stddev, stddev);
+    }
+
+    return 0;
+}
diff --git a/libavutil/tests/lls.c b/libavutil/tests/lls.c
new file mode 100644
index 0000000..965b0f4
--- /dev/null
+++ b/libavutil/tests/lls.c
@@ -0,0 +1,54 @@
+/*
+ * 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 <limits.h>
+#include <stdio.h>
+
+#include "libavutil/internal.h"
+#include "libavutil/lfg.h"
+#include "libavutil/lls.h"
+
+int main(void)
+{
+    LLSModel m;
+    int i, order;
+    AVLFG lfg;
+
+    av_lfg_init(&lfg, 1);
+    avpriv_init_lls(&m, 3);
+
+    for (i = 0; i < 100; i++) {
+        LOCAL_ALIGNED(32, double, var, [4]);
+        double eval;
+
+        var[0] =         (av_lfg_get(&lfg) / (double) UINT_MAX - 0.5) * 2;
+        var[1] = var[0] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5;
+        var[2] = var[1] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5;
+        var[3] = var[2] + av_lfg_get(&lfg) / (double) UINT_MAX - 0.5;
+        m.update_lls(&m, var);
+        avpriv_solve_lls(&m, 0.001, 0);
+        for (order = 0; order < 3; order++) {
+            eval = m.evaluate_lls(&m, var + 1, order);
+            printf("real:%9f order:%d pred:%9f var:%f coeffs:%f %9f %9f\n",
+                   var[0], order, eval, sqrt(m.variance[order] / (i + 1)),
+                   m.coeff[order][0], m.coeff[order][1],
+                   m.coeff[order][2]);
+        }
+    }
+    return 0;
+}
diff --git a/libavutil/tests/log.c b/libavutil/tests/log.c
new file mode 100644
index 0000000..8fe9461
--- /dev/null
+++ b/libavutil/tests/log.c
@@ -0,0 +1,71 @@
+/*
+ * log functions
+ * Copyright (c) 2003 Michel Bardiaux
+ *
+ * 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/log.c"
+
+#include <string.h>
+
+static int call_log_format_line2(const char *fmt, char *buffer, int buffer_size, ...)
+{
+    va_list args;
+    int ret;
+    int print_prefix=1;
+    va_start(args, buffer_size);
+    ret = av_log_format_line2(NULL, AV_LOG_INFO, fmt, args, buffer, buffer_size, &print_prefix);
+    va_end(args);
+    return ret;
+}
+
+int main(int argc, char **argv)
+{
+    int i;
+    av_log_set_level(AV_LOG_DEBUG);
+    for (use_color=0; use_color<=256; use_color = 255*use_color+1) {
+        av_log(NULL, AV_LOG_FATAL, "use_color: %d\n", use_color);
+        for (i = AV_LOG_DEBUG; i>=AV_LOG_QUIET; i-=8) {
+            av_log(NULL, i, " %d", i);
+            av_log(NULL, AV_LOG_INFO, "e ");
+            av_log(NULL, i + 256*123, "C%d", i);
+            av_log(NULL, AV_LOG_INFO, "e");
+        }
+        av_log(NULL, AV_LOG_PANIC, "\n");
+    }
+    {
+        int result;
+        char buffer[4];
+        result = call_log_format_line2("foo", NULL, 0);
+        if(result != 3) {
+            printf("Test NULL buffer failed.\n");
+            return 1;
+        }
+        result = call_log_format_line2("foo", buffer, 2);
+        if(result != 3 || strncmp(buffer, "f", 2)) {
+            printf("Test buffer too small failed.\n");
+            return 1;
+        }
+        result = call_log_format_line2("foo", buffer, 4);
+        if(result != 3 || strncmp(buffer, "foo", 4)) {
+            printf("Test buffer sufficiently big failed.\n");
+            return 1;
+        }
+    }
+    return 0;
+}
diff --git a/libavutil/tests/lzo.c b/libavutil/tests/lzo.c
new file mode 100644
index 0000000..0147ab5
--- /dev/null
+++ b/libavutil/tests/lzo.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2006 Reimar Doeffinger
+ *
+ * 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 <stdio.h>
+#include <lzo/lzo1x.h>
+
+#include "libavutil/log.h"
+#include "libavutil/lzo.h"
+#include "libavutil/mem.h"
+
+#define MAXSZ (10*1024*1024)
+
+/* Define one of these to 1 if you wish to benchmark liblzo
+ * instead of our native implementation. */
+#define BENCHMARK_LIBLZO_SAFE   0
+#define BENCHMARK_LIBLZO_UNSAFE 0
+
+int main(int argc, char *argv[]) {
+    FILE *in = fopen(argv[1], "rb");
+    int comp_level = argc > 2 ? atoi(argv[2]) : 0;
+    uint8_t *orig = av_malloc(MAXSZ + 16);
+    uint8_t *comp = av_malloc(2*MAXSZ + 16);
+    uint8_t *decomp = av_malloc(MAXSZ + 16);
+    size_t s = fread(orig, 1, MAXSZ, in);
+    lzo_uint clen = 0;
+    long tmp[LZO1X_MEM_COMPRESS];
+    int inlen, outlen;
+    int i;
+    av_log_set_level(AV_LOG_DEBUG);
+    if (comp_level == 0) {
+        lzo1x_1_compress(orig, s, comp, &clen, tmp);
+    } else if (comp_level == 11) {
+        lzo1x_1_11_compress(orig, s, comp, &clen, tmp);
+    } else if (comp_level == 12) {
+        lzo1x_1_12_compress(orig, s, comp, &clen, tmp);
+    } else if (comp_level == 15) {
+        lzo1x_1_15_compress(orig, s, comp, &clen, tmp);
+    } else
+        lzo1x_999_compress(orig, s, comp, &clen, tmp);
+    for (i = 0; i < 300; i++) {
+START_TIMER
+        inlen = clen; outlen = MAXSZ;
+#if BENCHMARK_LIBLZO_SAFE
+        if (lzo1x_decompress_safe(comp, inlen, decomp, &outlen, NULL))
+#elif BENCHMARK_LIBLZO_UNSAFE
+        if (lzo1x_decompress(comp, inlen, decomp, &outlen, NULL))
+#else
+        if (av_lzo1x_decode(decomp, &outlen, comp, &inlen))
+#endif
+            av_log(NULL, AV_LOG_ERROR, "decompression error\n");
+STOP_TIMER("lzod")
+    }
+    if (memcmp(orig, decomp, s))
+        av_log(NULL, AV_LOG_ERROR, "decompression incorrect\n");
+    else
+        av_log(NULL, AV_LOG_ERROR, "decompression OK\n");
+    fclose(in);
+    av_free(orig);
+    av_free(comp);
+    av_free(decomp);
+    return 0;
+}
diff --git a/libavutil/tests/md5.c b/libavutil/tests/md5.c
new file mode 100644
index 0000000..42e4538
--- /dev/null
+++ b/libavutil/tests/md5.c
@@ -0,0 +1,55 @@
+/*
+ * 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 <stdint.h>
+#include <stdio.h>
+
+#include "libavutil/md5.h"
+
+static void print_md5(uint8_t *md5)
+{
+    int i;
+    for (i = 0; i < 16; i++)
+        printf("%02x", md5[i]);
+    printf("\n");
+}
+
+int main(void)
+{
+    uint8_t md5val[16];
+    int i;
+    volatile uint8_t in[1000]; // volatile to workaround http://llvm.org/bugs/show_bug.cgi?id=20849
+    // FIXME remove volatile once it has been fixed and all fate clients are updated
+
+    for (i = 0; i < 1000; i++)
+        in[i] = i * i;
+    av_md5_sum(md5val, in, 1000);
+    print_md5(md5val);
+    av_md5_sum(md5val, in, 63);
+    print_md5(md5val);
+    av_md5_sum(md5val, in, 64);
+    print_md5(md5val);
+    av_md5_sum(md5val, in, 65);
+    print_md5(md5val);
+    for (i = 0; i < 1000; i++)
+        in[i] = i % 127;
+    av_md5_sum(md5val, in, 999);
+    print_md5(md5val);
+
+    return 0;
+}
diff --git a/libavutil/tests/murmur3.c b/libavutil/tests/murmur3.c
new file mode 100644
index 0000000..b8d6b1f
--- /dev/null
+++ b/libavutil/tests/murmur3.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 Reimar Döffinger <Reimar.Doeffinger at gmx.de>
+ *
+ * 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/intreadwrite.h"
+#include "libavutil/mem.h"
+#include "libavutil/murmur3.h"
+
+int main(void)
+{
+    int i;
+    uint8_t hash_result[16] = {0};
+    struct AVMurMur3 *ctx = av_murmur3_alloc();
+#if 1
+    uint8_t in[256] = {0};
+    uint8_t *hashes = av_mallocz(256 * 16);
+    for (i = 0; i < 256; i++)
+    {
+        in[i] = i;
+        av_murmur3_init_seeded(ctx, 256 - i);
+        // Note: this actually tests hashing 0 bytes
+        av_murmur3_update(ctx, in, i);
+        av_murmur3_final(ctx, hashes + 16 * i);
+    }
+    av_murmur3_init_seeded(ctx, 0);
+    av_murmur3_update(ctx, hashes, 256 * 16);
+    av_murmur3_final(ctx, hash_result);
+    av_free(hashes);
+    av_freep(&ctx);
+    printf("result: 0x%"PRIx64" 0x%"PRIx64"\n", AV_RL64(hash_result), AV_RL64(hash_result + 8));
+    // official reference value is 32 bit
+    return AV_RL32(hash_result) != 0x6384ba69;
+#else
+    uint8_t *in = av_mallocz(512*1024);
+    av_murmur3_init(ctx);
+    for (i = 0; i < 40*1024; i++)
+        av_murmur3_update(ctx, in, 512*1024);
+    av_murmur3_final(ctx, hash_result);
+    av_free(in);
+    return hash_result[0];
+#endif
+}
diff --git a/libavutil/tests/opt.c b/libavutil/tests/opt.c
new file mode 100644
index 0000000..568eb45
--- /dev/null
+++ b/libavutil/tests/opt.c
@@ -0,0 +1,312 @@
+/*
+ * 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 <limits.h>
+#include <stdio.h>
+
+#include "libavutil/common.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/error.h"
+#include "libavutil/log.h"
+#include "libavutil/mem.h"
+#include "libavutil/rational.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+
+typedef struct TestContext {
+    const AVClass *class;
+    int num;
+    int toggle;
+    char *string;
+    int flags;
+    AVRational rational;
+    AVRational video_rate;
+    int w, h;
+    enum AVPixelFormat pix_fmt;
+    enum AVSampleFormat sample_fmt;
+    int64_t duration;
+    uint8_t color[4];
+    int64_t channel_layout;
+    void *binary;
+    int binary_size;
+    void *binary1;
+    int binary_size1;
+    void *binary2;
+    int binary_size2;
+    int64_t num64;
+    float flt;
+    double dbl;
+    char *escape;
+    int bool1;
+    int bool2;
+    int bool3;
+} TestContext;
+
+#define OFFSET(x) offsetof(TestContext, x)
+
+#define TEST_FLAG_COOL 01
+#define TEST_FLAG_LAME 02
+#define TEST_FLAG_MU   04
+
+static const AVOption test_options[]= {
+    {"num",        "set num",            OFFSET(num),            AV_OPT_TYPE_INT,            { .i64 = 0 },                      0,       100, 1 },
+    {"toggle",     "set toggle",         OFFSET(toggle),         AV_OPT_TYPE_INT,            { .i64 = 1 },                      0,         1, 1 },
+    {"rational",   "set rational",       OFFSET(rational),       AV_OPT_TYPE_RATIONAL,       { .dbl = 1 },                      0,        10, 1 },
+    {"string",     "set string",         OFFSET(string),         AV_OPT_TYPE_STRING,         { .str = "default" },       CHAR_MIN,  CHAR_MAX, 1 },
+    {"escape",     "set escape str",     OFFSET(escape),         AV_OPT_TYPE_STRING,         { .str = "\\=," },          CHAR_MIN,  CHAR_MAX, 1 },
+    {"flags",      "set flags",          OFFSET(flags),          AV_OPT_TYPE_FLAGS,          { .i64 = 1 },                      0,   INT_MAX, 1, "flags" },
+    {"cool",       "set cool flag",      0,                      AV_OPT_TYPE_CONST,          { .i64 = TEST_FLAG_COOL },   INT_MIN,   INT_MAX, 1, "flags" },
+    {"lame",       "set lame flag",      0,                      AV_OPT_TYPE_CONST,          { .i64 = TEST_FLAG_LAME },   INT_MIN,   INT_MAX, 1, "flags" },
+    {"mu",         "set mu flag",        0,                      AV_OPT_TYPE_CONST,          { .i64 = TEST_FLAG_MU },     INT_MIN,   INT_MAX, 1, "flags" },
+    {"size",       "set size",           OFFSET(w),              AV_OPT_TYPE_IMAGE_SIZE,     { .str="200x300" },                0,         0, 1 },
+    {"pix_fmt",    "set pixfmt",         OFFSET(pix_fmt),        AV_OPT_TYPE_PIXEL_FMT,      { .i64 = AV_PIX_FMT_0BGR },       -1,   INT_MAX, 1 },
+    {"sample_fmt", "set samplefmt",      OFFSET(sample_fmt),     AV_OPT_TYPE_SAMPLE_FMT,     { .i64 = AV_SAMPLE_FMT_S16 },     -1,   INT_MAX, 1 },
+    {"video_rate", "set videorate",      OFFSET(video_rate),     AV_OPT_TYPE_VIDEO_RATE,     { .str = "25" },                   0,         INT_MAX, 1 },
+    {"duration",   "set duration",       OFFSET(duration),       AV_OPT_TYPE_DURATION,       { .i64 = 1000 },                   0, INT64_MAX, 1 },
+    {"color",      "set color",          OFFSET(color),          AV_OPT_TYPE_COLOR,          { .str = "pink" },                 0,         0, 1 },
+    {"cl",         "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, { .i64 = AV_CH_LAYOUT_HEXAGONAL }, 0, INT64_MAX, 1 },
+    {"bin",        "set binary value",   OFFSET(binary),         AV_OPT_TYPE_BINARY,         { .str="62696e00" },               0,         0, 1 },
+    {"bin1",       "set binary value",   OFFSET(binary1),        AV_OPT_TYPE_BINARY,         { .str=NULL },                     0,         0, 1 },
+    {"bin2",       "set binary value",   OFFSET(binary2),        AV_OPT_TYPE_BINARY,         { .str="" },                       0,         0, 1 },
+    {"num64",      "set num 64bit",      OFFSET(num64),          AV_OPT_TYPE_INT64,          { .i64 = 1 },                      0,       100, 1 },
+    {"flt",        "set float",          OFFSET(flt),            AV_OPT_TYPE_FLOAT,          { .dbl = 1.0 / 3 },                0,       100, 1 },
+    {"dbl",        "set double",         OFFSET(dbl),            AV_OPT_TYPE_DOUBLE,         { .dbl = 1.0 / 3 },                0,       100, 1 },
+    {"bool1",      "set boolean value",  OFFSET(bool1),          AV_OPT_TYPE_BOOL,           { .i64 = -1 },                    -1,         1, 1 },
+    {"bool2",      "set boolean value",  OFFSET(bool2),          AV_OPT_TYPE_BOOL,           { .i64 = 1 },                     -1,         1, 1 },
+    {"bool3",      "set boolean value",  OFFSET(bool3),          AV_OPT_TYPE_BOOL,           { .i64 = 0 },                      0,         1, 1 },
+    { NULL },
+};
+
+static const char *test_get_name(void *ctx)
+{
+    return "test";
+}
+
+static const AVClass test_class = {
+    "TestContext",
+    test_get_name,
+    test_options
+};
+
+static void log_callback_help(void *ptr, int level, const char *fmt, va_list vl)
+{
+    vfprintf(stdout, fmt, vl);
+}
+
+int main(void)
+{
+    int i;
+
+    av_log_set_level(AV_LOG_DEBUG);
+    av_log_set_callback(log_callback_help);
+
+    printf("Testing default values\n");
+    {
+        TestContext test_ctx = { 0 };
+        test_ctx.class = &test_class;
+        av_opt_set_defaults(&test_ctx);
+
+        printf("num=%d\n", test_ctx.num);
+        printf("toggle=%d\n", test_ctx.toggle);
+        printf("string=%s\n", test_ctx.string);
+        printf("escape=%s\n", test_ctx.escape);
+        printf("flags=%d\n", test_ctx.flags);
+        printf("rational=%d/%d\n", test_ctx.rational.num, test_ctx.rational.den);
+        printf("video_rate=%d/%d\n", test_ctx.video_rate.num, test_ctx.video_rate.den);
+        printf("width=%d height=%d\n", test_ctx.w, test_ctx.h);
+        printf("pix_fmt=%s\n", av_get_pix_fmt_name(test_ctx.pix_fmt));
+        printf("sample_fmt=%s\n", av_get_sample_fmt_name(test_ctx.sample_fmt));
+        printf("duration=%"PRId64"\n", test_ctx.duration);
+        printf("color=%d %d %d %d\n", test_ctx.color[0], test_ctx.color[1], test_ctx.color[2], test_ctx.color[3]);
+        printf("channel_layout=%"PRId64"=%"PRId64"\n", test_ctx.channel_layout, (int64_t)AV_CH_LAYOUT_HEXAGONAL);
+        if (test_ctx.binary)
+            printf("binary=%x %x %x %x\n", ((uint8_t*)test_ctx.binary)[0], ((uint8_t*)test_ctx.binary)[1], ((uint8_t*)test_ctx.binary)[2], ((uint8_t*)test_ctx.binary)[3]);
+        printf("binary_size=%d\n", test_ctx.binary_size);
+        printf("num64=%"PRId64"\n", test_ctx.num64);
+        printf("flt=%.6f\n", test_ctx.flt);
+        printf("dbl=%.6f\n", test_ctx.dbl);
+
+        av_opt_show2(&test_ctx, NULL, -1, 0);
+
+        av_opt_free(&test_ctx);
+    }
+
+    printf("\nTesting av_opt_is_set_to_default()\n");
+    {
+        int ret;
+        TestContext test_ctx = { 0 };
+        const AVOption *o = NULL;
+        test_ctx.class = &test_class;
+
+        av_log_set_level(AV_LOG_QUIET);
+
+        while (o = av_opt_next(&test_ctx, o)) {
+            ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0);
+            printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : "");
+        }
+        av_opt_set_defaults(&test_ctx);
+        while (o = av_opt_next(&test_ctx, o)) {
+            ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0);
+            printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : "");
+        }
+        av_opt_free(&test_ctx);
+    }
+
+    printf("\nTest av_opt_serialize()\n");
+    {
+        TestContext test_ctx = { 0 };
+        char *buf;
+        test_ctx.class = &test_class;
+
+        av_log_set_level(AV_LOG_QUIET);
+
+        av_opt_set_defaults(&test_ctx);
+        if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
+            printf("%s\n", buf);
+            av_opt_free(&test_ctx);
+            memset(&test_ctx, 0, sizeof(test_ctx));
+            test_ctx.class = &test_class;
+            av_set_options_string(&test_ctx, buf, "=", ",");
+            av_free(buf);
+            if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
+                printf("%s\n", buf);
+                av_free(buf);
+            }
+        }
+        av_opt_free(&test_ctx);
+    }
+
+    printf("\nTesting av_set_options_string()\n");
+    {
+        TestContext test_ctx = { 0 };
+        static const char * const options[] = {
+            "",
+            ":",
+            "=",
+            "foo=:",
+            ":=foo",
+            "=foo",
+            "foo=",
+            "foo",
+            "foo=val",
+            "foo==val",
+            "toggle=:",
+            "string=:",
+            "toggle=1 : foo",
+            "toggle=100",
+            "toggle==1",
+            "flags=+mu-lame : num=42: toggle=0",
+            "num=42 : string=blahblah",
+            "rational=0 : rational=1/2 : rational=1/-1",
+            "rational=-1/0",
+            "size=1024x768",
+            "size=pal",
+            "size=bogus",
+            "pix_fmt=yuv420p",
+            "pix_fmt=2",
+            "pix_fmt=bogus",
+            "sample_fmt=s16",
+            "sample_fmt=2",
+            "sample_fmt=bogus",
+            "video_rate=pal",
+            "video_rate=25",
+            "video_rate=30000/1001",
+            "video_rate=30/1.001",
+            "video_rate=bogus",
+            "duration=bogus",
+            "duration=123.45",
+            "duration=1\\:23\\:45.67",
+            "color=blue",
+            "color=0x223300",
+            "color=0x42FF07AA",
+            "cl=stereo+downmix",
+            "cl=foo",
+            "bin=boguss",
+            "bin=111",
+            "bin=ffff",
+            "num64=bogus",
+            "num64=44",
+            "num64=44.4",
+            "num64=-1",
+            "num64=101",
+            "flt=bogus",
+            "flt=2",
+            "flt=2.2",
+            "flt=-1",
+            "flt=101",
+            "dbl=bogus",
+            "dbl=2",
+            "dbl=2.2",
+            "dbl=-1",
+            "dbl=101",
+            "bool1=true",
+            "bool2=auto",
+        };
+
+        test_ctx.class = &test_class;
+        av_opt_set_defaults(&test_ctx);
+
+        av_log_set_level(AV_LOG_QUIET);
+
+        for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
+            int silence_log = !strcmp(options[i], "rational=-1/0"); // inf formating differs between platforms
+            av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
+            if (silence_log)
+                av_log_set_callback(NULL);
+            if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
+                printf("Error '%s'\n", options[i]);
+            else
+                printf("OK    '%s'\n", options[i]);
+            av_log_set_callback(log_callback_help);
+        }
+        av_opt_free(&test_ctx);
+    }
+
+    printf("\nTesting av_opt_set_from_string()\n");
+    {
+        TestContext test_ctx = { 0 };
+        static const char * const options[] = {
+            "",
+            "5",
+            "5:hello",
+            "5:hello:size=pal",
+            "5:size=pal:hello",
+            ":",
+            "=",
+            " 5 : hello : size = pal ",
+            "a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42"
+        };
+        static const char * const shorthand[] = { "num", "string", NULL };
+
+        test_ctx.class = &test_class;
+        av_opt_set_defaults(&test_ctx);
+
+        av_log_set_level(AV_LOG_QUIET);
+
+        for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
+            av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
+            if (av_opt_set_from_string(&test_ctx, options[i], shorthand, "=", ":") < 0)
+                printf("Error '%s'\n", options[i]);
+            else
+                printf("OK    '%s'\n", options[i]);
+        }
+        av_opt_free(&test_ctx);
+    }
+
+    return 0;
+}
diff --git a/libavutil/tests/parseutils.c b/libavutil/tests/parseutils.c
new file mode 100644
index 0000000..682b390
--- /dev/null
+++ b/libavutil/tests/parseutils.c
@@ -0,0 +1,260 @@
+/*
+ * 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
+ */
+
+#define TEST
+#include "libavutil/parseutils.c"
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "libavutil/common.h"
+#include "libavutil/log.h"
+#include "libavutil/rational.h"
+
+static uint32_t randomv = MKTAG('L','A','V','U');
+
+static uint32_t av_get_random_seed_deterministic(void)
+{
+    return randomv = randomv * 1664525 + 1013904223;
+}
+
+static void test_av_parse_video_rate(void)
+{
+    int i;
+    static const char *const rates[] = {
+        "-inf",
+        "inf",
+        "nan",
+        "123/0",
+        "-123 / 0",
+        "",
+        "/",
+        " 123  /  321",
+        "foo/foo",
+        "foo/1",
+        "1/foo",
+        "0/0",
+        "/0",
+        "1/",
+        "1",
+        "0",
+        "-123/123",
+        "-foo",
+        "123.23",
+        ".23",
+        "-.23",
+        "-0.234",
+        "-0.0000001",
+        "  21332.2324   ",
+        " -21332.2324   ",
+    };
+
+    for (i = 0; i < FF_ARRAY_ELEMS(rates); i++) {
+        int ret;
+        AVRational q = { 0, 0 };
+        ret = av_parse_video_rate(&q, rates[i]);
+        printf("'%s' -> %d/%d %s\n",
+               rates[i], q.num, q.den, ret ? "ERROR" : "OK");
+    }
+}
+
+static void test_av_parse_color(void)
+{
+    int i;
+    uint8_t rgba[4];
+    static const char *const color_names[] = {
+        "bikeshed",
+        "RaNdOm",
+        "foo",
+        "red",
+        "Red ",
+        "RED",
+        "Violet",
+        "Yellow",
+        "Red",
+        "0x000000",
+        "0x0000000",
+        "0xff000000",
+        "0x3e34ff",
+        "0x3e34ffaa",
+        "0xffXXee",
+        "0xfoobar",
+        "0xffffeeeeeeee",
+        "#ff0000",
+        "#ffXX00",
+        "ff0000",
+        "ffXX00",
+        "red at foo",
+        "random at 10",
+        "0xff0000 at 1.0",
+        "red@",
+        "red at 0xfff",
+        "red at 0xf",
+        "red at 2",
+        "red at 0.1",
+        "red at -1",
+        "red at 0.5",
+        "red at 1.0",
+        "red at 256",
+        "red at 10foo",
+        "red at -1.0",
+        "red at -0.0",
+    };
+
+    av_log_set_level(AV_LOG_DEBUG);
+
+    for (i = 0;  i < FF_ARRAY_ELEMS(color_names); i++) {
+        if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
+            printf("%s -> R(%d) G(%d) B(%d) A(%d)\n",
+                   color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
+        else
+            printf("%s -> error\n", color_names[i]);
+    }
+}
+
+static void test_av_small_strptime(void)
+{
+    int i;
+    struct tm tm = { 0 };
+    struct fmt_timespec_entry {
+        const char *fmt, *timespec;
+    } fmt_timespec_entries[] = {
+        { "%Y-%m-%d",                    "2012-12-21" },
+        { "%Y - %m - %d",                "2012-12-21" },
+        { "%Y-%m-%d %H:%M:%S",           "2012-12-21 20:12:21" },
+        { "  %Y - %m - %d %H : %M : %S", "   2012 - 12 -  21   20 : 12 : 21" },
+    };
+
+    av_log_set_level(AV_LOG_DEBUG);
+    for (i = 0;  i < FF_ARRAY_ELEMS(fmt_timespec_entries); i++) {
+        char *p;
+        struct fmt_timespec_entry *e = &fmt_timespec_entries[i];
+        printf("fmt:'%s' spec:'%s' -> ", e->fmt, e->timespec);
+        p = av_small_strptime(e->timespec, e->fmt, &tm);
+        if (p) {
+            printf("%04d-%02d-%2d %02d:%02d:%02d\n",
+                   1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday,
+                   tm.tm_hour, tm.tm_min, tm.tm_sec);
+        } else {
+            printf("error\n");
+        }
+    }
+}
+
+static void test_av_parse_time(void)
+{
+    int i;
+    int64_t tv;
+    time_t tvi;
+    struct tm *tm;
+    static char tzstr[] = "TZ=CET-1";
+    static const char * const time_string[] = {
+        "now",
+        "12:35:46",
+        "2000-12-20 0:02:47.5z",
+        "2012 - 02-22  17:44:07",
+        "2000-12-20T010247.6",
+        "2000-12-12 1:35:46+05:30",
+        "2002-12-12 22:30:40-02",
+    };
+    static const char * const duration_string[] = {
+        "2:34:56.79",
+        "-1:23:45.67",
+        "42.1729",
+        "-1729.42",
+        "12:34",
+    };
+
+    av_log_set_level(AV_LOG_DEBUG);
+    putenv(tzstr);
+    printf("(now is 2012-03-17 09:14:13.2 +0100, local time is UTC+1)\n");
+    for (i = 0;  i < FF_ARRAY_ELEMS(time_string); i++) {
+        printf("%-24s -> ", time_string[i]);
+        if (av_parse_time(&tv, time_string[i], 0)) {
+            printf("error\n");
+        } else {
+            tvi = tv / 1000000;
+            tm = gmtime(&tvi);
+            printf("%14"PRIi64".%06d = %04d-%02d-%02dT%02d:%02d:%02dZ\n",
+                   tv / 1000000, (int)(tv % 1000000),
+                   tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+                   tm->tm_hour, tm->tm_min, tm->tm_sec);
+        }
+    }
+    for (i = 0;  i < FF_ARRAY_ELEMS(duration_string); i++) {
+        printf("%-24s -> ", duration_string[i]);
+        if (av_parse_time(&tv, duration_string[i], 1)) {
+            printf("error\n");
+        } else {
+            printf("%+21"PRIi64"\n", tv);
+        }
+    }
+}
+
+static void test_av_get_known_color_name(void)
+{
+    int i;
+    const uint8_t *rgba;
+    const char *color;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(color_table); ++i) {
+        color = av_get_known_color_name(i, &rgba);
+        if (color)
+            printf("%s -> R(%d) G(%d) B(%d) A(%d)\n",
+                    color, rgba[0], rgba[1], rgba[2], rgba[3]);
+        else
+            printf("Color ID: %d not found\n", i);
+    }
+}
+
+static void test_av_find_info_tag(void)
+{
+    static const char args[] = "?tag1=val1&tag2=val2&tag3=val3&tag41=value 41&tag42=random1";
+    static const char *tags[] = {"tag1", "tag2", "tag3", "tag4", "tag41", "41", "random1"};
+    char buff[16];
+    int i;
+
+    for (i = 0; i < FF_ARRAY_ELEMS(tags); ++i) {
+        if (av_find_info_tag(buff, sizeof(buff), tags[i], args))
+            printf("%d. %s found: %s\n", i, tags[i], buff);
+        else
+            printf("%d. %s not found\n", i, tags[i]);
+    }
+}
+
+int main(void)
+{
+    printf("Testing av_parse_video_rate()\n");
+    test_av_parse_video_rate();
+
+    printf("\nTesting av_parse_color()\n");
+    test_av_parse_color();
+
+    printf("\nTesting av_small_strptime()\n");
+    test_av_small_strptime();
+
+    printf("\nTesting av_parse_time()\n");
+    test_av_parse_time();
+
+    printf("\nTesting av_get_known_color_name()\n");
+    test_av_get_known_color_name();
+
+    printf("\nTesting av_find_info_tag()\n");
+    test_av_find_info_tag();
+    return 0;
+}
diff --git a/libavutil/tests/pca.c b/libavutil/tests/pca.c
new file mode 100644
index 0000000..2d9eb8f
--- /dev/null
+++ b/libavutil/tests/pca.c
@@ -0,0 +1,102 @@
+/*
+ * principal component analysis (PCA)
+ * Copyright (c) 2004 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/pca.c"
+#include "libavutil/lfg.h"
+
+#undef printf
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(void){
+    PCA *pca;
+    int i, j, k;
+#define LEN 8
+    double eigenvector[LEN*LEN];
+    double eigenvalue[LEN];
+    AVLFG prng;
+
+    av_lfg_init(&prng, 1);
+
+    pca= ff_pca_init(LEN);
+
+    for(i=0; i<9000000; i++){
+        double v[2*LEN+100];
+        double sum=0;
+        int pos = av_lfg_get(&prng) % LEN;
+        int v2  = av_lfg_get(&prng) % 101 - 50;
+        v[0]    = av_lfg_get(&prng) % 101 - 50;
+        for(j=1; j<8; j++){
+            if(j<=pos) v[j]= v[0];
+            else       v[j]= v2;
+            sum += v[j];
+        }
+/*        for(j=0; j<LEN; j++){
+            v[j] -= v[pos];
+        }*/
+//        sum += av_lfg_get(&prng) % 10;
+/*        for(j=0; j<LEN; j++){
+            v[j] -= sum/LEN;
+        }*/
+//        lbt1(v+100,v+100,LEN);
+        ff_pca_add(pca, v);
+    }
+
+
+    ff_pca(pca, eigenvector, eigenvalue);
+    for(i=0; i<LEN; i++){
+        pca->count= 1;
+        pca->mean[i]= 0;
+
+//        (0.5^|x|)^2 = 0.5^2|x| = 0.25^|x|
+
+
+//        pca.covariance[i + i*LEN]= pow(0.5, fabs
+        for(j=i; j<LEN; j++){
+            printf("%f ", pca->covariance[i + j*LEN]);
+        }
+        printf("\n");
+    }
+
+    for(i=0; i<LEN; i++){
+        double v[LEN];
+        double error=0;
+        memset(v, 0, sizeof(v));
+        for(j=0; j<LEN; j++){
+            for(k=0; k<LEN; k++){
+                v[j] += pca->covariance[FFMIN(k,j) + FFMAX(k,j)*LEN] * eigenvector[i + k*LEN];
+            }
+            v[j] /= eigenvalue[i];
+            error += fabs(v[j] - eigenvector[i + j*LEN]);
+        }
+        printf("%f ", error);
+    }
+    printf("\n");
+
+    for(i=0; i<LEN; i++){
+        for(j=0; j<LEN; j++){
+            printf("%9.6f ", eigenvector[i + j*LEN]);
+        }
+        printf("  %9.1f %f\n", eigenvalue[i], eigenvalue[i]/eigenvalue[0]);
+    }
+
+    return 0;
+}
diff --git a/libavutil/tests/pixdesc.c b/libavutil/tests/pixdesc.c
new file mode 100644
index 0000000..7fbfeea
--- /dev/null
+++ b/libavutil/tests/pixdesc.c
@@ -0,0 +1,46 @@
+/*
+ * pixel format descriptor
+ * Copyright (c) 2009 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/pixdesc.c"
+
+int main(void){
+    int i;
+    int err=0;
+    int skip = 0;
+
+    for (i=0; i<AV_PIX_FMT_NB*2; i++) {
+        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(i);
+        if(!desc || !desc->name) {
+            skip ++;
+            continue;
+        }
+        if (skip) {
+            av_log(NULL, AV_LOG_INFO, "%3d unused pixel format values\n", skip);
+            skip = 0;
+        }
+        av_log(NULL, AV_LOG_INFO, "pix fmt %s avg_bpp:%d colortype:%d\n", desc->name, av_get_padded_bits_per_pixel(desc), get_color_type(desc));
+        if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) != (desc->nb_components != 2 && desc->nb_components != 4)) {
+            av_log(NULL, AV_LOG_ERROR, "Alpha flag mismatch\n");
+            err = 1;
+        }
+    }
+    return err;
+}
diff --git a/libavutil/tests/pixelutils.c b/libavutil/tests/pixelutils.c
new file mode 100644
index 0000000..ec4dc8f
--- /dev/null
+++ b/libavutil/tests/pixelutils.c
@@ -0,0 +1,152 @@
+/*
+ * 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/pixelutils.c"
+
+#define W1 320
+#define H1 240
+#define W2 640
+#define H2 480
+
+static int run_single_test(const char *test,
+                           const uint8_t *block1, ptrdiff_t stride1,
+                           const uint8_t *block2, ptrdiff_t stride2,
+                           int align, int n)
+{
+    int out, ref;
+    av_pixelutils_sad_fn f_ref = sad_c[n - 1];
+    av_pixelutils_sad_fn f_out = av_pixelutils_get_sad_fn(n, n, align, NULL);
+
+    switch (align) {
+    case 0: block1++; block2++; break;
+    case 1:           block2++; break;
+    case 2:                     break;
+    }
+
+    out = f_out(block1, stride1, block2, stride2);
+    ref = f_ref(block1, stride1, block2, stride2);
+    printf("[%s] [%c%c] SAD [%s] %dx%d=%d ref=%d\n",
+           out == ref ? "OK" : "FAIL",
+           align ? 'A' : 'U', align == 2 ? 'A' : 'U',
+           test, 1<<n, 1<<n, out, ref);
+    return out != ref;
+}
+
+static int run_test(const char *test,
+                    const uint8_t *b1, const uint8_t *b2)
+{
+    int i, a, ret = 0;
+
+    for (a = 0; a < 3; a++) {
+        const uint8_t *block1 = b1;
+        const uint8_t *block2 = b2;
+
+        switch (a) {
+        case 0: block1++; block2++; break;
+        case 1:           block2++; break;
+        case 2:                     break;
+        }
+        for (i = 1; i <= FF_ARRAY_ELEMS(sad_c); i++) {
+            int r = run_single_test(test, b1, W1, b2, W2, a, i);
+            if (r)
+                ret = r;
+        }
+    }
+    return ret;
+}
+
+int main(void)
+{
+    int i, align, ret;
+    uint8_t *buf1 = av_malloc(W1*H1);
+    uint8_t *buf2 = av_malloc(W2*H2);
+    uint32_t state = 0;
+
+    if (!buf1 || !buf2) {
+        fprintf(stderr, "malloc failure\n");
+        ret = 1;
+        goto end;
+    }
+
+    ff_check_pixfmt_descriptors();
+
+#define RANDOM_INIT(buf, size) do {             \
+    int k;                                      \
+    for (k = 0; k < size; k++) {                \
+        state = state * 1664525 + 1013904223;   \
+        buf[k] = state>>24;                     \
+    }                                           \
+} while (0)
+
+    /* Normal test with different strides */
+    RANDOM_INIT(buf1, W1*H1);
+    RANDOM_INIT(buf2, W2*H2);
+    ret = run_test("random", buf1, buf2);
+    if (ret < 0)
+        goto end;
+
+    /* Check for maximum SAD */
+    memset(buf1, 0xff, W1*H1);
+    memset(buf2, 0x00, W2*H2);
+    ret = run_test("max", buf1, buf2);
+    if (ret < 0)
+        goto end;
+
+    /* Check for minimum SAD */
+    memset(buf1, 0x90, W1*H1);
+    memset(buf2, 0x90, W2*H2);
+    ret = run_test("min", buf1, buf2);
+    if (ret < 0)
+        goto end;
+
+    /* Exact buffer sizes, to check for overreads */
+    for (i = 1; i <= 4; i++) {
+        for (align = 0; align < 3; align++) {
+            int size1, size2;
+
+            av_freep(&buf1);
+            av_freep(&buf2);
+
+            size1 = size2 = 1 << (i << 1);
+
+            switch (align) {
+            case 0: size1++; size2++; break;
+            case 1:          size2++; break;
+            case 2:                   break;
+            }
+
+            buf1 = av_malloc(size1);
+            buf2 = av_malloc(size2);
+            if (!buf1 || !buf2) {
+                fprintf(stderr, "malloc failure\n");
+                ret = 1;
+                goto end;
+            }
+            RANDOM_INIT(buf1, size1);
+            RANDOM_INIT(buf2, size2);
+            ret = run_single_test("small", buf1, 1<<i, buf2, 1<<i, align, i);
+            if (ret < 0)
+                goto end;
+        }
+    }
+
+end:
+    av_free(buf1);
+    av_free(buf2);
+    return ret;
+}
diff --git a/libavutil/tests/random_seed.c b/libavutil/tests/random_seed.c
new file mode 100644
index 0000000..ebe9b3e
--- /dev/null
+++ b/libavutil/tests/random_seed.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier at gmail.com>
+ *
+ * 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
+ */
+
+#define TEST 1
+#include "libavutil/random_seed.c"
+
+#undef printf
+#define N 256
+#include <stdio.h>
+
+int main(void)
+{
+    int i, j, retry;
+    uint32_t seeds[N];
+
+    for (retry=0; retry<3; retry++){
+        for (i=0; i<N; i++){
+            seeds[i] = av_get_random_seed();
+            for (j=0; j<i; j++)
+                if (seeds[j] == seeds[i])
+                    goto retry;
+        }
+        printf("seeds OK\n");
+        return 0;
+        retry:;
+    }
+    printf("FAIL at %d with %X\n", j, seeds[j]);
+    return 1;
+}
diff --git a/libavutil/tests/rational.c b/libavutil/tests/rational.c
new file mode 100644
index 0000000..caec07d
--- /dev/null
+++ b/libavutil/tests/rational.c
@@ -0,0 +1,134 @@
+/*
+ * rational numbers
+ * Copyright (c) 2003 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/rational.c"
+#include "libavutil/integer.h"
+
+int main(void)
+{
+    AVRational a,b,r;
+    int i,j,k;
+    static const int64_t numlist[] = {
+        INT64_MIN, INT64_MIN+1, INT64_MAX, INT32_MIN, INT32_MAX, 1,0,-1,
+        123456789, INT32_MAX-1, INT32_MAX+1LL, UINT32_MAX-1, UINT32_MAX, UINT32_MAX+1LL
+    };
+
+    for (a.num = -2; a.num <= 2; a.num++) {
+        for (a.den = -2; a.den <= 2; a.den++) {
+            for (b.num = -2; b.num <= 2; b.num++) {
+                for (b.den = -2; b.den <= 2; b.den++) {
+                    int c = av_cmp_q(a,b);
+                    double d = av_q2d(a) == av_q2d(b) ?
+                               0 : (av_q2d(a) - av_q2d(b));
+                    if (d > 0)       d = 1;
+                    else if (d < 0)  d = -1;
+                    else if (d != d) d = INT_MIN;
+                    if (c != d)
+                        av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %f\n", a.num,
+                               a.den, b.num, b.den, c,d);
+                    r = av_sub_q(av_add_q(b,a), b);
+                    if(b.den && (r.num*a.den != a.num*r.den || !r.num != !a.num || !r.den != !a.den))
+                        av_log(NULL, AV_LOG_ERROR, "%d/%d ", r.num, r.den);
+                }
+            }
+        }
+    }
+
+    for (i = 0; i < FF_ARRAY_ELEMS(numlist); i++) {
+        int64_t a = numlist[i];
+
+        for (j = 0; j < FF_ARRAY_ELEMS(numlist); j++) {
+            int64_t b = numlist[j];
+            if (b<=0)
+                continue;
+            for (k = 0; k < FF_ARRAY_ELEMS(numlist); k++) {
+                int64_t c = numlist[k];
+                int64_t res;
+                AVInteger ai;
+
+                if (c<=0)
+                    continue;
+                res = av_rescale_rnd(a,b,c, AV_ROUND_ZERO);
+
+                ai = av_mul_i(av_int2i(a), av_int2i(b));
+                ai = av_div_i(ai, av_int2i(c));
+
+                if (av_cmp_i(ai, av_int2i(INT64_MAX)) > 0 && res == INT64_MIN)
+                    continue;
+                if (av_cmp_i(ai, av_int2i(INT64_MIN)) < 0 && res == INT64_MIN)
+                    continue;
+                if (av_cmp_i(ai, av_int2i(res)) == 0)
+                    continue;
+
+                // Special exception for INT64_MIN, remove this in case INT64_MIN is handled without off by 1 error
+                if (av_cmp_i(ai, av_int2i(res-1)) == 0 && a == INT64_MIN)
+                    continue;
+
+                av_log(NULL, AV_LOG_ERROR, "%"PRId64" * %"PRId64" / %"PRId64" = %"PRId64" or %"PRId64"\n", a,b,c, res, av_i2int(ai));
+            }
+        }
+    }
+
+    for (a.num = 1; a.num <= 10; a.num++) {
+        for (a.den = 1; a.den <= 10; a.den++) {
+            if (av_gcd(a.num, a.den) > 1)
+                continue;
+            for (b.num = 1; b.num <= 10; b.num++) {
+                for (b.den = 1; b.den <= 10; b.den++) {
+                    int start;
+                    if (av_gcd(b.num, b.den) > 1)
+                        continue;
+                    if (av_cmp_q(b, a) < 0)
+                        continue;
+                    for (start = 0; start < 10 ; start++) {
+                        int acc= start;
+                        int i;
+
+                        for (i = 0; i<100; i++) {
+                            int exact = start + av_rescale_q(i+1, b, a);
+                            acc = av_add_stable(a, acc, b, 1);
+                            if (FFABS(acc - exact) > 2) {
+                                av_log(NULL, AV_LOG_ERROR, "%d/%d %d/%d, %d %d\n", a.num,
+                                       a.den, b.num, b.den, acc, exact);
+                                return 1;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    for (a.den = 1; a.den < 0x100000000U/3; a.den*=3) {
+        for (a.num = -1; a.num < (1<<27); a.num += 1 + a.num/100) {
+            float f  = av_int2float(av_q2intfloat(a));
+            float f2 = av_q2d(a);
+            if (fabs(f - f2) > fabs(f)/5000000) {
+                av_log(NULL, AV_LOG_ERROR, "%d/%d %f %f\n", a.num,
+                       a.den, f, f2);
+                return 1;
+            }
+
+        }
+    }
+
+    return 0;
+}
diff --git a/libavutil/tests/ripemd.c b/libavutil/tests/ripemd.c
new file mode 100644
index 0000000..58e5fce
--- /dev/null
+++ b/libavutil/tests/ripemd.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 Michael Niedermayer <michaelni at gmx.at>
+ * Copyright (C) 2013 James Almer
+ *
+ * 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 <stdio.h>
+
+#include "libavutil/mem.h"
+#include "libavutil/ripemd.h"
+
+int main(void)
+{
+    int i, j, k;
+    struct AVRIPEMD *ctx;
+    unsigned char digest[40];
+    static const int lengths[4] = { 128, 160, 256, 320 };
+
+    ctx = av_ripemd_alloc();
+    if (!ctx)
+        return 1;
+
+    for (j = 0; j < 4; j++) {
+        printf("Testing RIPEMD-%d\n", lengths[j]);
+        for (k = 0; k < 3; k++) {
+            av_ripemd_init(ctx, lengths[j]);
+            if (k == 0)
+                av_ripemd_update(ctx, "abc", 3);
+            else if (k == 1)
+                av_ripemd_update(ctx, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56);
+            else
+                for (i = 0; i < 1000*1000; i++)
+                    av_ripemd_update(ctx, "a", 1);
+            av_ripemd_final(ctx, digest);
+            for (i = 0; i < lengths[j] >> 3; i++)
+                printf("%02X", digest[i]);
+            putchar('\n');
+        }
+        switch (j) { //test vectors (from ISO:IEC 10118-3 (2004) and http://homes.esat.kuleuven.be/~bosselae/ripemd160.html)
+        case 0:
+            printf("c14a1219 9c66e4ba 84636b0f 69144c77\n"
+                   "a1aa0689 d0fafa2d dc22e88b 49133a06\n"
+                   "4a7f5723 f954eba1 216c9d8f 6320431f\n");
+            break;
+        case 1:
+            printf("8eb208f7 e05d987a 9b044a8e 98c6b087 f15a0bfc\n"
+                   "12a05338 4a9c0c88 e405a06c 27dcf49a da62eb2b\n"
+                   "52783243 c1697bdb e16d37f9 7f68f083 25dc1528\n");
+            break;
+        case 2:
+            printf("afbd6e22 8b9d8cbb cef5ca2d 03e6dba1 0ac0bc7d cbe4680e 1e42d2e9 75459b65\n"
+                   "38430455 83aac6c8 c8d91285 73e7a980 9afb2a0f 34ccc36e a9e72f16 f6368e3f\n"
+                   "ac953744 e10e3151 4c150d4d 8d7b6773 42e33399 788296e4 3ae4850c e4f97978\n");
+            break;
+        case 3:
+            printf("de4c01b3 054f8930 a79d09ae 738e9230 1e5a1708 5beffdc1 b8d11671 3e74f82f a942d64c dbc4682d\n"
+                   "d034a795 0cf72202 1ba4b84d f769a5de 2060e259 df4c9bb4 a4268c0e 935bbc74 70a969c9 d072a1ac\n"
+                   "bdee37f4 371e2064 6b8b0d86 2dda1629 2ae36f40 965e8c85 09e63d1d bddecc50 3e2b63eb 9245bb66\n");
+            break;
+        }
+    }
+    av_free(ctx);
+
+    return 0;
+}
diff --git a/libavutil/tests/sha.c b/libavutil/tests/sha.c
new file mode 100644
index 0000000..a95b3a0
--- /dev/null
+++ b/libavutil/tests/sha.c
@@ -0,0 +1,75 @@
+/*
+ * 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 <stdio.h>
+
+#include "libavutil/mem.h"
+#include "libavutil/sha.h"
+
+int main(void)
+{
+    int i, j, k;
+    struct AVSHA *ctx;
+    unsigned char digest[32];
+    static const int lengths[3] = { 160, 224, 256 };
+
+    ctx = av_sha_alloc();
+    if (!ctx)
+        return 1;
+
+    for (j = 0; j < 3; j++) {
+        printf("Testing SHA-%d\n", lengths[j]);
+        for (k = 0; k < 3; k++) {
+            av_sha_init(ctx, lengths[j]);
+            if (k == 0)
+                av_sha_update(ctx, "abc", 3);
+            else if (k == 1)
+                av_sha_update(ctx, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56);
+            else
+                for (i = 0; i < 1000*1000; i++)
+                    av_sha_update(ctx, "a", 1);
+            av_sha_final(ctx, digest);
+            for (i = 0; i < lengths[j] >> 3; i++)
+                printf("%02X", digest[i]);
+            putchar('\n');
+        }
+        switch (j) {
+        case 0:
+            //test vectors (from FIPS PUB 180-1)
+            printf("A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n"
+                   "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\n"
+                   "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n");
+            break;
+        case 1:
+            //test vectors (from FIPS PUB 180-2 Appendix A)
+            printf("23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7\n"
+                   "75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525\n"
+                   "20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67\n");
+            break;
+        case 2:
+            //test vectors (from FIPS PUB 180-2)
+            printf("ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad\n"
+                   "248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1\n"
+                   "cdc76e5c 9914fb92 81a1c7e2 84d73e67 f1809a48 a497200e 046d39cc c7112cd0\n");
+            break;
+        }
+    }
+    av_free(ctx);
+
+    return 0;
+}
diff --git a/libavutil/tests/sha512.c b/libavutil/tests/sha512.c
new file mode 100644
index 0000000..f3b90fd
--- /dev/null
+++ b/libavutil/tests/sha512.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007 Michael Niedermayer <michaelni at gmx.at>
+ * Copyright (C) 2009 Konstantin Shishkov
+ * Copyright (C) 2013 James Almer
+ * based on BSD-licensed SHA-2 code by Aaron D. Gifford
+ *
+ * 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 <stdio.h>
+
+#include "libavutil/mem.h"
+#include "libavutil/sha512.h"
+
+int main(void)
+{
+    int i, j, k;
+    struct AVSHA512 *ctx;
+    unsigned char digest[64];
+    static const int lengths[4] = { 224, 256, 384, 512 };
+
+    ctx = av_sha512_alloc();
+    if (!ctx)
+        return 1;
+
+    for (j = 0; j < 4; j++) {
+        if (j < 2) printf("Testing SHA-512/%d\n", lengths[j]);
+        else       printf("Testing SHA-%d\n", lengths[j]);
+        for (k = 0; k < 3; k++) {
+            av_sha512_init(ctx, lengths[j]);
+            if (k == 0)
+                av_sha512_update(ctx, "abc", 3);
+            else if (k == 1)
+                av_sha512_update(ctx, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+                                       "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112);
+            else
+                for (i = 0; i < 1000*1000; i++)
+                    av_sha512_update(ctx, "a", 1);
+            av_sha512_final(ctx, digest);
+            for (i = 0; i < lengths[j] >> 3; i++)
+                printf("%02X", digest[i]);
+            putchar('\n');
+        }
+        switch (j) { //test vectors (from FIPS PUB 180-4 Apendix A)
+        case 0:
+            printf("4634270f 707b6a54 daae7530 460842e2 0e37ed26 5ceee9a4 3e8924aa\n"
+                   "23fec5bb 94d60b23 30819264 0b0c4533 35d66473 4fe40e72 68674af9\n"
+                   "37ab331d 76f0d36d e422bd0e deb22a28 accd487b 7a8453ae 965dd287\n");
+            break;
+        case 1:
+            printf("53048e26 81941ef9 9b2e29b7 6b4c7dab e4c2d0c6 34fc6d46 e0e2f131 07e7af23\n"
+                   "3928e184 fb8690f8 40da3988 121d31be 65cb9d3e f83ee614 6feac861 e19b563a\n"
+                   "9a59a052 930187a9 7038cae6 92f30708 aa649192 3ef51943 94dc68d5 6c74fb21\n");
+            break;
+        case 2:
+            printf("cb00753f 45a35e8b b5a03d69 9ac65007 272c32ab 0eded163 "
+                   "1a8b605a 43ff5bed 8086072b a1e7cc23 58baeca1 34c825a7\n"
+                   "09330c33 f71147e8 3d192fc7 82cd1b47 53111b17 3b3b05d2 "
+                   "2fa08086 e3b0f712 fcc7c71a 557e2db9 66c3e9fa 91746039\n"
+                   "9d0e1809 716474cb 086e834e 310a4a1c ed149e9c 00f24852 "
+                   "7972cec5 704c2a5b 07b8b3dc 38ecc4eb ae97ddd8 7f3d8985\n");
+            break;
+        case 3:
+            printf("ddaf35a1 93617aba cc417349 ae204131 12e6fa4e 89a97ea2 0a9eeee6 4b55d39a "
+                   "2192992a 274fc1a8 36ba3c23 a3feebbd 454d4423 643ce80e 2a9ac94f a54ca49f\n"
+                   "8e959b75 dae313da 8cf4f728 14fc143f 8f7779c6 eb9f7fa1 7299aead b6889018 "
+                   "501d289e 4900f7e4 331b99de c4b5433a c7d329ee b6dd2654 5e96e55b 874be909\n"
+                   "e718483d 0ce76964 4e2e42c7 bc15b463 8e1f98b1 3b204428 5632a803 afa973eb "
+                   "de0ff244 877ea60a 4cb0432c e577c31b eb009c5c 2c49aa2e 4eadb217 ad8cc09b\n");
+            break;
+        }
+    }
+    av_free(ctx);
+
+    return 0;
+}
diff --git a/libavutil/tests/softfloat.c b/libavutil/tests/softfloat.c
new file mode 100644
index 0000000..16788d4
--- /dev/null
+++ b/libavutil/tests/softfloat.c
@@ -0,0 +1,156 @@
+/*
+ * copyright (c) 2006 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <inttypes.h>
+
+#include "libavutil/softfloat.h"
+#include "libavutil/common.h"
+#include "libavutil/log.h"
+
+#include <stdio.h>
+
+static const SoftFloat FLOAT_0_017776489257 = {0x1234, 12};
+static const SoftFloat FLOAT_1374_40625 = {0xabcd, 25};
+static const SoftFloat FLOAT_0_1249694824218 = {0xFFF, 15};
+
+
+int main(void){
+    SoftFloat one= av_int2sf(1, 0);
+    SoftFloat sf1, sf2, sf3;
+    double d1, d2, d3;
+    int i, j;
+    av_log_set_level(AV_LOG_DEBUG);
+
+    d1= 1;
+    for(i= 0; i<10; i++){
+        d1= 1/(d1+1);
+    }
+    printf("test1 double=%d\n", (int)(d1 * (1<<24)));
+
+    sf1= one;
+    for(i= 0; i<10; i++){
+        sf1= av_div_sf(one, av_normalize_sf(av_add_sf(one, sf1)));
+    }
+    printf("test1 sf    =%d\n", av_sf2int(sf1, 24));
+
+
+    for(i= 0; i<100; i++){
+        START_TIMER
+        d1= i;
+        d2= i/100.0;
+        for(j= 0; j<1000; j++){
+            d1= (d1+1)*d2;
+        }
+        STOP_TIMER("float add mul")
+    }
+    printf("test2 double=%d\n", (int)(d1 * (1<<24)));
+
+    for(i= 0; i<100; i++){
+        START_TIMER
+        sf1= av_int2sf(i, 0);
+        sf2= av_div_sf(av_int2sf(i, 2), av_int2sf(200, 3));
+        for(j= 0; j<1000; j++){
+            sf1= av_mul_sf(av_add_sf(sf1, one),sf2);
+        }
+        STOP_TIMER("softfloat add mul")
+    }
+    printf("test2 sf    =%d (%d %d)\n", av_sf2int(sf1, 24), sf1.exp, sf1.mant);
+
+    d1 = 0.0177764893;
+    d2 = 1374.40625;
+    d3 = 0.1249694824;
+    d2 += d1;
+    d3 += d2;
+    printf("test3 double: %.10lf\n", d3);
+
+    sf1 = FLOAT_0_017776489257;
+    sf2 = FLOAT_1374_40625;
+    sf3 = FLOAT_0_1249694824218;
+    sf2 = av_add_sf(sf1, sf2);
+    sf3 = av_add_sf(sf3, sf2);
+    printf("test3 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf3), sf3.mant, sf3.exp);
+
+    sf1 = av_int2sf(0xFFFFFFF0, 0);
+    printf("test4 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
+    sf1 = av_int2sf(0x00000010, 0);
+    printf("test4 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
+
+    sf1 = av_int2sf(0x1FFFFFFF, 0);
+    printf("test4 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
+    sf1 = av_int2sf(0xE0000001, 0);
+    printf("test4 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
+
+
+    sf1 = (SoftFloat){ 0x20000000,   MIN_EXP };
+    sf1 = av_mul_sf(sf1, sf1);
+    printf("test5 softfloat: %.10lf (0x%08x %d)\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp);
+
+    sf1 = (SoftFloat){ 0x20000000,   MIN_EXP };
+    sf2 = (SoftFloat){ 0x20000000,   MAX_EXP };
+    i = av_cmp_sf(sf1, sf2);
+    j = av_cmp_sf(sf2, sf1);
+    sf1 = av_div_sf(sf1, sf2);
+    printf("test6 softfloat: %.10lf (0x%08x %d) %d %d\n", (double)av_sf2double(sf1), sf1.mant, sf1.exp, i, j);
+
+    for(i= -50; i<50; i++) {
+        sf1= av_int2sf(i, 0);
+        for(j= -50; j<50; j++) {
+            int c;
+            sf2= av_int2sf(j, 0);
+            c = av_cmp_sf(sf1, sf2);
+            if (FFDIFFSIGN(i,j) != c && (FFDIFFSIGN(i,j)^c)<0) {
+                printf("av_cmp_sf failed at %d %d as %X\n", i, j, c);
+            }
+            c = av_gt_sf(sf1, sf2);
+            if ((i>j) != c) {
+                printf("av_gt_sf failed at %d %d as %X\n", i, j, c);
+            }
+        }
+        sf1 = av_int2sf(1, i);
+        for(j = -50; j < 50; j++) {
+            int c;
+            sf2 = av_int2sf(1, j);
+            c = av_cmp_sf(sf2, sf1);
+            if (FFDIFFSIGN(i,j) != c && (FFDIFFSIGN(i,j)^c) < 0) {
+                printf("av_cmp_sf failed2 at %d %d as %X\n", i, j, c);
+            }
+            c = av_gt_sf(sf1, sf2);
+            if ((i<j) != c) {
+                printf("av_gt_sf failed2 at %d %d as %X\n", i, j, c);
+            }
+        }
+    }
+
+
+    for(i= 0; i<4*36; i++){
+        int s, c;
+        double errs, errc;
+
+        av_sincos_sf(i*(1ULL<<32)/36/4, &s, &c);
+        errs = (double)s/ (1<<30) - sin(i*M_PI/36);
+        errc = (double)c/ (1<<30) - cos(i*M_PI/36);
+        if (fabs(errs) > 0.00000002 || fabs(errc) >0.001) {
+            printf("sincos FAIL %d %f %f %f %f\n", i, (float)s/ (1<<30), (float)c/ (1<<30), sin(i*M_PI/36), cos(i*M_PI/36));
+        }
+
+    }
+    return 0;
+
+}
diff --git a/libavutil/tests/tea.c b/libavutil/tests/tea.c
new file mode 100644
index 0000000..605bb52
--- /dev/null
+++ b/libavutil/tests/tea.c
@@ -0,0 +1,115 @@
+/*
+ * A 32-bit implementation of the TEA algorithm
+ * Copyright (c) 2015 Vesselin Bontchev
+ *
+ * Loosely based on the implementation of David Wheeler and Roger Needham,
+ * https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm#Reference_code
+ *
+ * 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 <stdio.h>
+
+#include "libavutil/common.h"
+#include "libavutil/tea.h"
+
+#define TEA_NUM_TESTS 4
+
+// https://github.com/logandrews/TeaCrypt/blob/master/tea/tea_test.go
+static const uint8_t tea_test_key[TEA_NUM_TESTS][16] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    },
+    { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+      0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
+    },
+    { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+      0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
+    }
+};
+
+static const uint8_t tea_test_pt[TEA_NUM_TESTS][8] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
+    { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }
+};
+
+static const uint8_t tea_test_ct[TEA_NUM_TESTS][8] = {
+    { 0x41, 0xEA, 0x3A, 0x0A, 0x94, 0xBA, 0xA9, 0x40 },
+    { 0x6A, 0x2F, 0x9C, 0xF3, 0xFC, 0xCF, 0x3C, 0x55 },
+    { 0xDE, 0xB1, 0xC0, 0xA2, 0x7E, 0x74, 0x5D, 0xB3 },
+    { 0x12, 0x6C, 0x6B, 0x92, 0xC0, 0x65, 0x3A, 0x3E }
+};
+
+static void test_tea(struct AVTEA *ctx, uint8_t *dst, const uint8_t *src,
+                     const uint8_t *ref, int len, uint8_t *iv, int dir,
+                     const char *test)
+{
+    av_tea_crypt(ctx, dst, src, len, iv, dir);
+    if (memcmp(dst, ref, 8*len)) {
+        int i;
+        printf("%s failed\ngot      ", test);
+        for (i = 0; i < 8*len; i++)
+            printf("%02x ", dst[i]);
+        printf("\nexpected ");
+        for (i = 0; i < 8*len; i++)
+            printf("%02x ", ref[i]);
+        printf("\n");
+        exit(1);
+    }
+}
+
+int main(void)
+{
+    struct AVTEA *ctx;
+    uint8_t buf[8], iv[8];
+    int i;
+    static const uint8_t src[32] = "HelloWorldHelloWorldHelloWorld";
+    uint8_t ct[32];
+    uint8_t pl[32];
+
+    ctx = av_tea_alloc();
+    if (!ctx)
+        return 1;
+
+    for (i = 0; i < TEA_NUM_TESTS; i++) {
+        av_tea_init(ctx, tea_test_key[i], 64);
+
+        test_tea(ctx, buf, tea_test_pt[i], tea_test_ct[i], 1, NULL, 0, "encryption");
+        test_tea(ctx, buf, tea_test_ct[i], tea_test_pt[i], 1, NULL, 1, "decryption");
+
+        /* encrypt */
+        memcpy(iv, "HALLO123", 8);
+        av_tea_crypt(ctx, ct, src, 4, iv, 0);
+
+        /* decrypt into pl */
+        memcpy(iv, "HALLO123", 8);
+        test_tea(ctx, pl, ct, src, 4, iv, 1, "CBC decryption");
+
+        memcpy(iv, "HALLO123", 8);
+        test_tea(ctx, ct, ct, src, 4, iv, 1, "CBC inplace decryption");
+    }
+
+    printf("Test encryption/decryption success.\n");
+    av_free(ctx);
+
+    return 0;
+}
diff --git a/libavutil/tests/tree.c b/libavutil/tests/tree.c
new file mode 100644
index 0000000..7503228
--- /dev/null
+++ b/libavutil/tests/tree.c
@@ -0,0 +1,108 @@
+/*
+ * 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/tree.c"
+
+#include <stdint.h>
+
+#include "libavutil/common.h"
+#include "libavutil/lfg.h"
+#include "libavutil/log.h"
+
+static int check(AVTreeNode *t)
+{
+    if (t) {
+        int left  = check(t->child[0]);
+        int right = check(t->child[1]);
+
+        if (left > 999 || right > 999)
+            return 1000;
+        if (right - left != t->state)
+            return 1000;
+        if (t->state > 1 || t->state < -1)
+            return 1000;
+        return FFMAX(left, right) + 1;
+    }
+    return 0;
+}
+
+static void print(AVTreeNode *t, int depth)
+{
+    int i;
+    for (i = 0; i < depth * 4; i++)
+        av_log(NULL, AV_LOG_ERROR, " ");
+    if (t) {
+        av_log(NULL, AV_LOG_ERROR, "Node %p %2d %p\n", t, t->state, t->elem);
+        print(t->child[0], depth + 1);
+        print(t->child[1], depth + 1);
+    } else
+        av_log(NULL, AV_LOG_ERROR, "NULL\n");
+}
+
+static int cmp(const void *a, const void *b)
+{
+    return (const uint8_t *) a - (const uint8_t *) b;
+}
+
+int main(int argc, char **argv)
+{
+    int i;
+    void *k;
+    AVTreeNode *root = NULL, *node = NULL;
+    AVLFG prng;
+    int log_level = argc <= 1 ? AV_LOG_INFO : atoi(argv[1]);
+
+    av_log_set_level(log_level);
+
+    av_lfg_init(&prng, 1);
+
+    for (i = 0; i < 10000; i++) {
+        intptr_t j = av_lfg_get(&prng) % 86294;
+
+        if (check(root) > 999) {
+            av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i);
+            print(root, 0);
+            return 1;
+        }
+        av_log(NULL, AV_LOG_DEBUG, "inserting %4d\n", (int)j);
+
+        if (!node)
+            node = av_tree_node_alloc();
+        if (!node) {
+            av_log(NULL, AV_LOG_ERROR, "Memory allocation failure.\n");
+            return 1;
+        }
+        av_tree_insert(&root, (void *)(j + 1), cmp, &node);
+
+        j = av_lfg_get(&prng) % 86294;
+        {
+            AVTreeNode *node2 = NULL;
+            av_log(NULL, AV_LOG_DEBUG, "removing %4d\n", (int)j);
+            av_tree_insert(&root, (void *)(j + 1), cmp, &node2);
+            k = av_tree_find(root, (void *)(j + 1), cmp, NULL);
+            if (k)
+                av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i);
+            av_free(node2);
+        }
+    }
+    av_free(node);
+
+    av_tree_destroy(root);
+
+    return 0;
+}
diff --git a/libavutil/tests/twofish.c b/libavutil/tests/twofish.c
new file mode 100644
index 0000000..74e0926
--- /dev/null
+++ b/libavutil/tests/twofish.c
@@ -0,0 +1,94 @@
+/*
+ * An implementation of the TwoFish algorithm
+ * Copyright (c) 2015 Supraja Meedinti
+ *
+ * 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/log.h"
+#include "libavutil/twofish.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+    uint8_t Key[32] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
+    };
+    const uint8_t rct[6][16] = {
+        {0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a},
+        {0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf, 0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48},
+        {0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8, 0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20},
+        {0x5d, 0x9d, 0x4e, 0xef, 0xfa, 0x91, 0x51, 0x57, 0x55, 0x24, 0xf1, 0x15, 0x81, 0x5a, 0x12, 0xe0},
+        {0xe7, 0x54, 0x49, 0x21, 0x2b, 0xee, 0xf9, 0xf4, 0xa3, 0x90, 0xbd, 0x86, 0x0a, 0x64, 0x09, 0x41},
+        {0x37, 0xfe, 0x26, 0xff, 0x1c, 0xf6, 0x61, 0x75, 0xf5, 0xdd, 0xf4, 0xc3, 0x3b, 0x97, 0xa2, 0x05}
+    };
+    uint8_t temp[32], iv[16], rpt[32] = {0};
+    const int kbits[3] = {128, 192, 256};
+    int i, j, err = 0;
+    struct AVTWOFISH *cs;
+    cs = av_twofish_alloc();
+    if (!cs)
+        return 1;
+    for (j = 1; j < 3; j++) {
+        av_twofish_init(cs, Key, kbits[j]);
+        av_twofish_crypt(cs, temp, rpt, 1, NULL, 0);
+        for (i = 0; i < 16; i++) {
+            if (rct[j][i] != temp[i]) {
+                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[j][i], temp[i]);
+                err = 1;
+            }
+        }
+        av_twofish_crypt(cs, temp, rct[j], 1, NULL, 1);
+        for (i = 0; i < 16; i++) {
+            if (rpt[i] != temp[i]) {
+                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
+                err = 1;
+            }
+        }
+    }
+    for (j = 0; j < 3; j++) {
+        memset(Key, 0, sizeof(Key));
+        memset(rpt, 0, sizeof(rpt));
+        for (i = 1; i < 50; i++) {
+            av_twofish_init(cs, Key, kbits[j]);
+            av_twofish_crypt(cs, temp, rpt, 1, NULL, 0);
+            memcpy(Key+16,Key,(kbits[j]-128) >> 3);
+            memcpy(Key,rpt,16);
+            memcpy(rpt,temp,16);
+        }
+        for (i = 0; i < 16; i++) {
+            if (rct[3 + j][i] != temp[i]) {
+                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[3 + j][i], temp[i]);
+                err = 1;
+            }
+        }
+    }
+    memset(rpt, 0, sizeof(rpt));
+    memcpy(iv, "HALLO123HALLO123", 16);
+    av_twofish_crypt(cs, temp, rpt, 2, iv, 0);
+    memcpy(iv, "HALLO123HALLO123", 16);
+    av_twofish_crypt(cs, temp, temp, 2, iv, 1);
+    for (i = 0; i < 32; i++) {
+        if (rpt[i] != temp[i]) {
+            av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
+            err = 1;
+        }
+    }
+    av_free(cs);
+    return err;
+}
diff --git a/libavutil/tests/utf8.c b/libavutil/tests/utf8.c
new file mode 100644
index 0000000..37a2802
--- /dev/null
+++ b/libavutil/tests/utf8.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 Stefano Sabatini
+ *
+ * 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 <stdio.h>
+
+#include "libavutil/avstring.h"
+#include "libavutil/file.h"
+
+static void print_sequence(const char *p, int l, int indent)
+{
+    int i;
+    for (i = 0; i < l; i++)
+        printf("%02X", (uint8_t)p[i]);
+    printf("%*s", indent-l*2, "");
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+    char *filename = argv[1];
+    uint8_t *file_buf;
+    size_t file_buf_size;
+    uint32_t code;
+    const uint8_t *p, *endp;
+
+    ret = av_file_map(filename, &file_buf, &file_buf_size, 0, NULL);
+    if (ret < 0)
+        return 1;
+
+    p = file_buf;
+    endp = file_buf + file_buf_size;
+    while (p < endp) {
+        int l, r;
+        const uint8_t *p0 = p;
+        code = UINT32_MAX;
+        r = av_utf8_decode(&code, &p, endp, 0);
+        l = (int)(p-p0);
+        print_sequence(p0, l, 20);
+        if (code != UINT32_MAX) {
+            printf("%-10d 0x%-10X %-5d ", code, code, l);
+            if (r >= 0) {
+                if (*p0 == '\n') printf("\\n\n");
+                else             printf ("%.*s\n", l, p0);
+            } else {
+                printf("invalid code range\n");
+            }
+        } else {
+            printf("invalid sequence\n");
+        }
+    }
+
+    av_file_unmap(file_buf, file_buf_size);
+    return 0;
+}
diff --git a/libavutil/tests/xtea.c b/libavutil/tests/xtea.c
new file mode 100644
index 0000000..6a8c647
--- /dev/null
+++ b/libavutil/tests/xtea.c
@@ -0,0 +1,125 @@
+/*
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem.h"
+#include "libavutil/xtea.h"
+
+#define XTEA_NUM_TESTS 6
+
+static const uint8_t xtea_test_key[XTEA_NUM_TESTS][16] = {
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static const uint8_t xtea_test_pt[XTEA_NUM_TESTS][8] = {
+    { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+    { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
+    { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+    { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }
+};
+
+static const uint8_t xtea_test_ct[XTEA_NUM_TESTS][8] = {
+    { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 },
+    { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 },
+    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
+    { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 },
+    { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d },
+    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
+};
+
+static void test_xtea(AVXTEA *ctx, uint8_t *dst, const uint8_t *src,
+                      const uint8_t *ref, int len, uint8_t *iv, int dir,
+                      const char *test,
+                      void (*crypt)(AVXTEA *, uint8_t *, const uint8_t *, int, uint8_t *, int))
+{
+    crypt(ctx, dst, src, len, iv, dir);
+    if (memcmp(dst, ref, 8*len)) {
+        int i;
+        printf("%s failed\ngot      ", test);
+        for (i = 0; i < 8*len; i++)
+            printf("%02x ", dst[i]);
+        printf("\nexpected ");
+        for (i = 0; i < 8*len; i++)
+            printf("%02x ", ref[i]);
+        printf("\n");
+        exit(1);
+    }
+}
+
+int main(void)
+{
+    uint8_t buf[16], iv[8];
+    int i, j;
+    static const uint8_t src[32] = "HelloWorldHelloWorldHelloWorld";
+    uint8_t ct[32];
+    uint8_t pl[32];
+    AVXTEA *ctx = av_xtea_alloc();
+    if (!ctx)
+        return 1;
+
+    for (i = 0; i < XTEA_NUM_TESTS; i++) {
+        av_xtea_init(ctx, xtea_test_key[i]);
+
+        test_xtea(ctx, buf, xtea_test_pt[i], xtea_test_ct[i], 1, NULL, 0, "encryption", av_xtea_crypt);
+        test_xtea(ctx, buf, xtea_test_ct[i], xtea_test_pt[i], 1, NULL, 1, "decryption", av_xtea_crypt);
+
+        for (j = 0; j < 4; j++)
+            AV_WL32(&buf[4*j], AV_RB32(&xtea_test_key[i][4*j]));
+        av_xtea_le_init(ctx, buf);
+        for (j = 0; j < 2; j++) {
+            AV_WL32(&ct[4*j], AV_RB32(&xtea_test_ct[i][4*j]));
+            AV_WL32(&pl[4*j], AV_RB32(&xtea_test_pt[i][4*j]));
+        }
+        test_xtea(ctx, buf, pl, ct, 1, NULL, 0, "encryption", av_xtea_le_crypt);
+        test_xtea(ctx, buf, ct, pl, 1, NULL, 1, "decryption", av_xtea_le_crypt);
+
+        /* encrypt */
+        memcpy(iv, "HALLO123", 8);
+        av_xtea_crypt(ctx, ct, src, 4, iv, 0);
+
+        /* decrypt into pl */
+        memcpy(iv, "HALLO123", 8);
+        test_xtea(ctx, pl, ct, src, 4, iv, 1, "CBC decryption", av_xtea_crypt);
+
+        memcpy(iv, "HALLO123", 8);
+        test_xtea(ctx, ct, ct, src, 4, iv, 1, "CBC inplace decryption", av_xtea_crypt);
+    }
+
+    printf("Test encryption/decryption success.\n");
+    av_free(ctx);
+
+    return 0;
+}
diff --git a/libavutil/threadmessage.h b/libavutil/threadmessage.h
index e256cae..8480a0a 100644
--- a/libavutil/threadmessage.h
+++ b/libavutil/threadmessage.h
@@ -69,10 +69,10 @@ int av_thread_message_queue_recv(AVThreadMessageQueue *mq,
 /**
  * Set the sending error code.
  *
- * If the error code is set to non-zero, av_thread_message_queue_recv() will
- * return it immediately when there are no longer available messages.
- * Conventional values, such as AVERROR_EOF or AVERROR(EAGAIN), can be used
- * to cause the receiving thread to stop or suspend its operation.
+ * If the error code is set to non-zero, av_thread_message_queue_send() will
+ * return it immediately. Conventional values, such as AVERROR_EOF or
+ * AVERROR(EAGAIN), can be used to cause the sending thread to stop or
+ * suspend its operation.
  */
 void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq,
                                           int err);
@@ -80,10 +80,10 @@ void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq,
 /**
  * Set the receiving error code.
  *
- * If the error code is set to non-zero, av_thread_message_queue_send() will
- * return it immediately. Conventional values, such as AVERROR_EOF or
- * AVERROR(EAGAIN), can be used to cause the sending thread to stop or
- * suspend its operation.
+ * If the error code is set to non-zero, av_thread_message_queue_recv() will
+ * return it immediately when there are no longer available messages.
+ * Conventional values, such as AVERROR_EOF or AVERROR(EAGAIN), can be used
+ * to cause the receiving thread to stop or suspend its operation.
  */
 void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq,
                                           int err);
diff --git a/libavutil/tree.c b/libavutil/tree.c
index 2495cdf..7b57b2d 100644
--- a/libavutil/tree.c
+++ b/libavutil/tree.c
@@ -166,92 +166,3 @@ void av_tree_enumerate(AVTreeNode *t, void *opaque,
             av_tree_enumerate(t->child[1], opaque, cmp, enu);
     }
 }
-
-#ifdef TEST
-
-#include "common.h"
-#include "lfg.h"
-
-static int check(AVTreeNode *t)
-{
-    if (t) {
-        int left  = check(t->child[0]);
-        int right = check(t->child[1]);
-
-        if (left > 999 || right > 999)
-            return 1000;
-        if (right - left != t->state)
-            return 1000;
-        if (t->state > 1 || t->state < -1)
-            return 1000;
-        return FFMAX(left, right) + 1;
-    }
-    return 0;
-}
-
-static void print(AVTreeNode *t, int depth)
-{
-    int i;
-    for (i = 0; i < depth * 4; i++)
-        av_log(NULL, AV_LOG_ERROR, " ");
-    if (t) {
-        av_log(NULL, AV_LOG_ERROR, "Node %p %2d %p\n", t, t->state, t->elem);
-        print(t->child[0], depth + 1);
-        print(t->child[1], depth + 1);
-    } else
-        av_log(NULL, AV_LOG_ERROR, "NULL\n");
-}
-
-static int cmp(const void *a, const void *b)
-{
-    return (const uint8_t *) a - (const uint8_t *) b;
-}
-
-int main(int argc, char **argv)
-{
-    int i;
-    void *k;
-    AVTreeNode *root = NULL, *node = NULL;
-    AVLFG prng;
-    int log_level = argc <= 1 ? AV_LOG_INFO : atoi(argv[1]);
-
-    av_log_set_level(log_level);
-
-    av_lfg_init(&prng, 1);
-
-    for (i = 0; i < 10000; i++) {
-        intptr_t j = av_lfg_get(&prng) % 86294;
-
-        if (check(root) > 999) {
-            av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i);
-            print(root, 0);
-            return 1;
-        }
-        av_log(NULL, AV_LOG_DEBUG, "inserting %4d\n", (int)j);
-
-        if (!node)
-            node = av_tree_node_alloc();
-        if (!node) {
-            av_log(NULL, AV_LOG_ERROR, "Memory allocation failure.\n");
-            return 1;
-        }
-        av_tree_insert(&root, (void *)(j + 1), cmp, &node);
-
-        j = av_lfg_get(&prng) % 86294;
-        {
-            AVTreeNode *node2 = NULL;
-            av_log(NULL, AV_LOG_DEBUG, "removing %4d\n", (int)j);
-            av_tree_insert(&root, (void *)(j + 1), cmp, &node2);
-            k = av_tree_find(root, (void *)(j + 1), cmp, NULL);
-            if (k)
-                av_log(NULL, AV_LOG_ERROR, "removal failure %d\n", i);
-            av_free(node2);
-        }
-    }
-    av_free(node);
-
-    av_tree_destroy(root);
-
-    return 0;
-}
-#endif
diff --git a/libavutil/tree.h b/libavutil/tree.h
index e1aefaa..9a9e11b 100644
--- a/libavutil/tree.h
+++ b/libavutil/tree.h
@@ -120,8 +120,8 @@ void av_tree_destroy(struct AVTreeNode *t);
 /**
  * Apply enu(opaque, &elem) to all the elements in the tree in a given range.
  *
- * @param cmp a comparison function that returns < 0 for a element below the
- *            range, > 0 for a element above the range and == 0 for a
+ * @param cmp a comparison function that returns < 0 for an element below the
+ *            range, > 0 for an element above the range and == 0 for an
  *            element inside the range
  *
  * @note The cmp function should use the same ordering used to construct the
diff --git a/libavutil/twofish.c b/libavutil/twofish.c
index 162069b..d84fa4f 100644
--- a/libavutil/twofish.c
+++ b/libavutil/twofish.c
@@ -329,77 +329,3 @@ void av_twofish_crypt(AVTWOFISH *cs, uint8_t *dst, const uint8_t *src, int count
         dst = dst + 16;
     }
 }
-
-#ifdef TEST
-#include<stdio.h>
-#include<stdlib.h>
-#include"log.h"
-
-int main(int argc, char *argv[])
-{
-    uint8_t Key[32] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
-    };
-    const uint8_t rct[6][16] = {
-        {0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32, 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a},
-        {0xcf, 0xd1, 0xd2, 0xe5, 0xa9, 0xbe, 0x9c, 0xdf, 0x50, 0x1f, 0x13, 0xb8, 0x92, 0xbd, 0x22, 0x48},
-        {0x37, 0x52, 0x7b, 0xe0, 0x05, 0x23, 0x34, 0xb8, 0x9f, 0x0c, 0xfc, 0xca, 0xe8, 0x7c, 0xfa, 0x20},
-        {0x5d, 0x9d, 0x4e, 0xef, 0xfa, 0x91, 0x51, 0x57, 0x55, 0x24, 0xf1, 0x15, 0x81, 0x5a, 0x12, 0xe0},
-        {0xe7, 0x54, 0x49, 0x21, 0x2b, 0xee, 0xf9, 0xf4, 0xa3, 0x90, 0xbd, 0x86, 0x0a, 0x64, 0x09, 0x41},
-        {0x37, 0xfe, 0x26, 0xff, 0x1c, 0xf6, 0x61, 0x75, 0xf5, 0xdd, 0xf4, 0xc3, 0x3b, 0x97, 0xa2, 0x05}
-    };
-    uint8_t temp[32], iv[16], rpt[32] = {0};
-    const int kbits[3] = {128, 192, 256};
-    int i, j, err = 0;
-    AVTWOFISH *cs;
-    cs = av_twofish_alloc();
-    if (!cs)
-        return 1;
-    for (j = 1; j < 3; j++) {
-        av_twofish_init(cs, Key, kbits[j]);
-        av_twofish_crypt(cs, temp, rpt, 1, NULL, 0);
-        for (i = 0; i < 16; i++) {
-            if (rct[j][i] != temp[i]) {
-                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[j][i], temp[i]);
-                err = 1;
-            }
-        }
-        av_twofish_crypt(cs, temp, rct[j], 1, NULL, 1);
-        for (i = 0; i < 16; i++) {
-            if (rpt[i] != temp[i]) {
-                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
-                err = 1;
-            }
-        }
-    }
-    for (j = 0; j < 3; j++) {
-        memset(Key, 0, sizeof(Key));
-        memset(rpt, 0, sizeof(rpt));
-        for (i = 1; i < 50; i++) {
-            av_twofish_init(cs, Key, kbits[j]);
-            av_twofish_crypt(cs, temp, rpt, 1, NULL, 0);
-            memcpy(Key+16,Key,(kbits[j]-128) >> 3);
-            memcpy(Key,rpt,16);
-            memcpy(rpt,temp,16);
-        }
-        for (i = 0; i < 16; i++) {
-            if (rct[3 + j][i] != temp[i]) {
-                av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[3 + j][i], temp[i]);
-                err = 1;
-            }
-        }
-    }
-    memset(rpt, 0, sizeof(rpt));
-    memcpy(iv, "HALLO123HALLO123", 16);
-    av_twofish_crypt(cs, temp, rpt, 2, iv, 0);
-    memcpy(iv, "HALLO123HALLO123", 16);
-    av_twofish_crypt(cs, temp, temp, 2, iv, 1);
-    for (i = 0; i < 32; i++) {
-        if (rpt[i] != temp[i]) {
-            av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]);
-            err = 1;
-        }
-    }
-    av_free(cs);
-    return err;
-}
-#endif
diff --git a/libavutil/utf8.c b/libavutil/utf8.c
deleted file mode 100644
index 3447a51..0000000
--- a/libavutil/utf8.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2013 Stefano Sabatini
- *
- * 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
- */
-
-#ifdef TEST
-#include <stdio.h>
-
-#include "libavutil/avstring.h"
-#include "libavutil/file.h"
-
-static void print_sequence(const char *p, int l, int indent)
-{
-    int i;
-    for (i = 0; i < l; i++)
-        printf("%02X", (uint8_t)p[i]);
-    printf("%*s", indent-l*2, "");
-}
-
-int main(int argc, char **argv)
-{
-    int ret;
-    char *filename = argv[1];
-    uint8_t *file_buf;
-    size_t file_buf_size;
-    uint32_t code;
-    const uint8_t *p, *endp;
-
-    ret = av_file_map(filename, &file_buf, &file_buf_size, 0, NULL);
-    if (ret < 0)
-        return 1;
-
-    p = file_buf;
-    endp = file_buf + file_buf_size;
-    while (p < endp) {
-        int l, r;
-        const uint8_t *p0 = p;
-        code = UINT32_MAX;
-        r = av_utf8_decode(&code, &p, endp, 0);
-        l = (int)(p-p0);
-        print_sequence(p0, l, 20);
-        if (code != UINT32_MAX) {
-            printf("%-10d 0x%-10X %-5d ", code, code, l);
-            if (r >= 0) {
-                if (*p0 == '\n') printf("\\n\n");
-                else             printf ("%.*s\n", l, p0);
-            } else {
-                printf("invalid code range\n");
-            }
-        } else {
-            printf("invalid sequence\n");
-        }
-    }
-
-    av_file_unmap(file_buf, file_buf_size);
-    return 0;
-}
-#endif
diff --git a/libavutil/version.h b/libavutil/version.h
index 0ea8c79..07618fc 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -64,8 +64,8 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR  55
-#define LIBAVUTIL_VERSION_MINOR  17
-#define LIBAVUTIL_VERSION_MICRO 103
+#define LIBAVUTIL_VERSION_MINOR  28
+#define LIBAVUTIL_VERSION_MICRO 100
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
                                                LIBAVUTIL_VERSION_MINOR, \
diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c
index bb63daa..b9f239b 100644
--- a/libavutil/x86/cpu.c
+++ b/libavutil/x86/cpu.c
@@ -182,7 +182,7 @@ int ff_get_cpu_flags_x86(void)
 
         /* Similar to the above but for AVX functions on AMD processors.
            This is necessary only for functions using YMM registers on Bulldozer
-           and Jaguar based CPUs as they lack 256-bits execution units. SSE/AVX
+           and Jaguar based CPUs as they lack 256-bit execution units. SSE/AVX
            functions using XMM registers are always faster on them.
            AV_CPU_FLAG_AVX and AV_CPU_FLAG_AVXSLOW are both set so that AVX is
            used unless explicitly disabled by checking AV_CPU_FLAG_AVXSLOW. */
diff --git a/libavutil/x86/intmath.h b/libavutil/x86/intmath.h
index f58b0d0..e83971c 100644
--- a/libavutil/x86/intmath.h
+++ b/libavutil/x86/intmath.h
@@ -47,6 +47,7 @@ static av_always_inline av_const int ff_log2_x86(unsigned int v)
 #   endif
 #   define ff_log2_16bit av_log2
 
+#if defined(__INTEL_COMPILER) || (defined(_MSC_VER) && (_MSC_VER >= 1700))
 #   define ff_ctz(v) _tzcnt_u32(v)
 
 #   if ARCH_X86_64
@@ -58,6 +59,7 @@ static av_always_inline av_const int ff_ctzll_x86(long long v)
     return ((uint32_t)v == 0) ? _tzcnt_u32((uint32_t)(v >> 32)) + 32 : _tzcnt_u32((uint32_t)v);
 }
 #   endif
+#endif /* _MSC_VER */
 
 #endif /* __INTEL_COMPILER */
 
diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm
index 3a0a261..b2e9c60 100644
--- a/libavutil/x86/x86inc.asm
+++ b/libavutil/x86/x86inc.asm
@@ -1097,7 +1097,7 @@ INIT_XMM
 ;%1 == instruction
 ;%2 == minimal instruction set
 ;%3 == 1 if float, 0 if int
-;%4 == 1 if non-destructive or 4-operand (xmm, xmm, xmm, imm), 0 otherwise
+;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation)
 ;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not
 ;%6+: operands
 %macro RUN_AVX_INSTR 6-9+
@@ -1130,14 +1130,12 @@ INIT_XMM
     %if __emulate_avx
         %xdefine __src1 %7
         %xdefine __src2 %8
-        %ifnidn %6, %7
-            %if %0 >= 9
-                CHECK_AVX_INSTR_EMU {%1 %6, %7, %8, %9}, %6, %8, %9
-            %else
-                CHECK_AVX_INSTR_EMU {%1 %6, %7, %8}, %6, %8
-            %endif
-            %if %5 && %4 == 0
-                %ifnid %8
+        %if %5 && %4 == 0
+            %ifnidn %6, %7
+                %ifidn %6, %8
+                    %xdefine __src1 %8
+                    %xdefine __src2 %7
+                %elifnnum sizeof%8
                     ; 3-operand AVX instructions with a memory arg can only have it in src2,
                     ; whereas SSE emulation prefers to have it in src1 (i.e. the mov).
                     ; So, if the instruction is commutative with a memory arg, swap them.
@@ -1145,6 +1143,13 @@ INIT_XMM
                     %xdefine __src2 %7
                 %endif
             %endif
+        %endif
+        %ifnidn %6, __src1
+            %if %0 >= 9
+                CHECK_AVX_INSTR_EMU {%1 %6, %7, %8, %9}, %6, __src2, %9
+            %else
+                CHECK_AVX_INSTR_EMU {%1 %6, %7, %8}, %6, __src2
+            %endif
             %if __sizeofreg == 8
                 MOVQ %6, __src1
             %elif %3
@@ -1172,9 +1177,9 @@ INIT_XMM
 ;%1 == instruction
 ;%2 == minimal instruction set
 ;%3 == 1 if float, 0 if int
-;%4 == 1 if non-destructive or 4-operand (xmm, xmm, xmm, imm), 0 otherwise
+;%4 == 1 if 4-operand emulation, 0 if 3-operand emulation, 255 otherwise (no emulation)
 ;%5 == 1 if commutative (i.e. doesn't matter which src arg is which), 0 if not
-%macro AVX_INSTR 1-5 fnord, 0, 1, 0
+%macro AVX_INSTR 1-5 fnord, 0, 255, 0
     %macro %1 1-10 fnord, fnord, fnord, fnord, %1, %2, %3, %4, %5
         %ifidn %2, fnord
             RUN_AVX_INSTR %6, %7, %8, %9, %10, %1
@@ -1194,8 +1199,8 @@ INIT_XMM
 ; Non-destructive instructions are written without parameters
 AVX_INSTR addpd, sse2, 1, 0, 1
 AVX_INSTR addps, sse, 1, 0, 1
-AVX_INSTR addsd, sse2, 1, 0, 1
-AVX_INSTR addss, sse, 1, 0, 1
+AVX_INSTR addsd, sse2, 1, 0, 0
+AVX_INSTR addss, sse, 1, 0, 0
 AVX_INSTR addsubpd, sse3, 1, 0, 0
 AVX_INSTR addsubps, sse3, 1, 0, 0
 AVX_INSTR aesdec, aesni, 0, 0, 0
@@ -1208,10 +1213,10 @@ AVX_INSTR andnpd, sse2, 1, 0, 0
 AVX_INSTR andnps, sse, 1, 0, 0
 AVX_INSTR andpd, sse2, 1, 0, 1
 AVX_INSTR andps, sse, 1, 0, 1
-AVX_INSTR blendpd, sse4, 1, 0, 0
-AVX_INSTR blendps, sse4, 1, 0, 0
-AVX_INSTR blendvpd, sse4, 1, 0, 0
-AVX_INSTR blendvps, sse4, 1, 0, 0
+AVX_INSTR blendpd, sse4, 1, 1, 0
+AVX_INSTR blendps, sse4, 1, 1, 0
+AVX_INSTR blendvpd, sse4 ; can't be emulated
+AVX_INSTR blendvps, sse4 ; can't be emulated
 AVX_INSTR cmppd, sse2, 1, 1, 0
 AVX_INSTR cmpps, sse, 1, 1, 0
 AVX_INSTR cmpsd, sse2, 1, 1, 0
@@ -1225,10 +1230,10 @@ AVX_INSTR cvtpd2ps, sse2
 AVX_INSTR cvtps2dq, sse2
 AVX_INSTR cvtps2pd, sse2
 AVX_INSTR cvtsd2si, sse2
-AVX_INSTR cvtsd2ss, sse2
-AVX_INSTR cvtsi2sd, sse2
-AVX_INSTR cvtsi2ss, sse
-AVX_INSTR cvtss2sd, sse2
+AVX_INSTR cvtsd2ss, sse2, 1, 0, 0
+AVX_INSTR cvtsi2sd, sse2, 1, 0, 0
+AVX_INSTR cvtsi2ss, sse, 1, 0, 0
+AVX_INSTR cvtss2sd, sse2, 1, 0, 0
 AVX_INSTR cvtss2si, sse
 AVX_INSTR cvttpd2dq, sse2
 AVX_INSTR cvttps2dq, sse2
@@ -1251,12 +1256,12 @@ AVX_INSTR ldmxcsr, sse
 AVX_INSTR maskmovdqu, sse2
 AVX_INSTR maxpd, sse2, 1, 0, 1
 AVX_INSTR maxps, sse, 1, 0, 1
-AVX_INSTR maxsd, sse2, 1, 0, 1
-AVX_INSTR maxss, sse, 1, 0, 1
+AVX_INSTR maxsd, sse2, 1, 0, 0
+AVX_INSTR maxss, sse, 1, 0, 0
 AVX_INSTR minpd, sse2, 1, 0, 1
 AVX_INSTR minps, sse, 1, 0, 1
-AVX_INSTR minsd, sse2, 1, 0, 1
-AVX_INSTR minss, sse, 1, 0, 1
+AVX_INSTR minsd, sse2, 1, 0, 0
+AVX_INSTR minss, sse, 1, 0, 0
 AVX_INSTR movapd, sse2
 AVX_INSTR movaps, sse
 AVX_INSTR movd, mmx
@@ -1282,11 +1287,11 @@ AVX_INSTR movsldup, sse3
 AVX_INSTR movss, sse, 1, 0, 0
 AVX_INSTR movupd, sse2
 AVX_INSTR movups, sse
-AVX_INSTR mpsadbw, sse4
+AVX_INSTR mpsadbw, sse4, 0, 1, 0
 AVX_INSTR mulpd, sse2, 1, 0, 1
 AVX_INSTR mulps, sse, 1, 0, 1
-AVX_INSTR mulsd, sse2, 1, 0, 1
-AVX_INSTR mulss, sse, 1, 0, 1
+AVX_INSTR mulsd, sse2, 1, 0, 0
+AVX_INSTR mulss, sse, 1, 0, 0
 AVX_INSTR orpd, sse2, 1, 0, 1
 AVX_INSTR orps, sse, 1, 0, 1
 AVX_INSTR pabsb, ssse3
@@ -1304,14 +1309,18 @@ AVX_INSTR paddsb, mmx, 0, 0, 1
 AVX_INSTR paddsw, mmx, 0, 0, 1
 AVX_INSTR paddusb, mmx, 0, 0, 1
 AVX_INSTR paddusw, mmx, 0, 0, 1
-AVX_INSTR palignr, ssse3
+AVX_INSTR palignr, ssse3, 0, 1, 0
 AVX_INSTR pand, mmx, 0, 0, 1
 AVX_INSTR pandn, mmx, 0, 0, 0
 AVX_INSTR pavgb, mmx2, 0, 0, 1
 AVX_INSTR pavgw, mmx2, 0, 0, 1
-AVX_INSTR pblendvb, sse4, 0, 0, 0
-AVX_INSTR pblendw, sse4
-AVX_INSTR pclmulqdq
+AVX_INSTR pblendvb, sse4 ; can't be emulated
+AVX_INSTR pblendw, sse4, 0, 1, 0
+AVX_INSTR pclmulqdq, fnord, 0, 1, 0
+AVX_INSTR pclmulhqhqdq, fnord, 0, 0, 0
+AVX_INSTR pclmulhqlqdq, fnord, 0, 0, 0
+AVX_INSTR pclmullqhqdq, fnord, 0, 0, 0
+AVX_INSTR pclmullqlqdq, fnord, 0, 0, 0
 AVX_INSTR pcmpestri, sse42
 AVX_INSTR pcmpestrm, sse42
 AVX_INSTR pcmpistri, sse42
@@ -1335,10 +1344,10 @@ AVX_INSTR phminposuw, sse4
 AVX_INSTR phsubw, ssse3, 0, 0, 0
 AVX_INSTR phsubd, ssse3, 0, 0, 0
 AVX_INSTR phsubsw, ssse3, 0, 0, 0
-AVX_INSTR pinsrb, sse4
-AVX_INSTR pinsrd, sse4
-AVX_INSTR pinsrq, sse4
-AVX_INSTR pinsrw, mmx2
+AVX_INSTR pinsrb, sse4, 0, 1, 0
+AVX_INSTR pinsrd, sse4, 0, 1, 0
+AVX_INSTR pinsrq, sse4, 0, 1, 0
+AVX_INSTR pinsrw, mmx2, 0, 1, 0
 AVX_INSTR pmaddwd, mmx, 0, 0, 1
 AVX_INSTR pmaddubsw, ssse3, 0, 0, 0
 AVX_INSTR pmaxsb, sse4, 0, 0, 1
@@ -1410,18 +1419,18 @@ AVX_INSTR punpcklwd, mmx, 0, 0, 0
 AVX_INSTR punpckldq, mmx, 0, 0, 0
 AVX_INSTR punpcklqdq, sse2, 0, 0, 0
 AVX_INSTR pxor, mmx, 0, 0, 1
-AVX_INSTR rcpps, sse, 1, 0, 0
+AVX_INSTR rcpps, sse
 AVX_INSTR rcpss, sse, 1, 0, 0
 AVX_INSTR roundpd, sse4
 AVX_INSTR roundps, sse4
-AVX_INSTR roundsd, sse4
-AVX_INSTR roundss, sse4
-AVX_INSTR rsqrtps, sse, 1, 0, 0
+AVX_INSTR roundsd, sse4, 1, 1, 0
+AVX_INSTR roundss, sse4, 1, 1, 0
+AVX_INSTR rsqrtps, sse
 AVX_INSTR rsqrtss, sse, 1, 0, 0
 AVX_INSTR shufpd, sse2, 1, 1, 0
 AVX_INSTR shufps, sse, 1, 1, 0
-AVX_INSTR sqrtpd, sse2, 1, 0, 0
-AVX_INSTR sqrtps, sse, 1, 0, 0
+AVX_INSTR sqrtpd, sse2
+AVX_INSTR sqrtps, sse
 AVX_INSTR sqrtsd, sse2, 1, 0, 0
 AVX_INSTR sqrtss, sse, 1, 0, 0
 AVX_INSTR stmxcsr, sse
@@ -1497,7 +1506,7 @@ FMA_INSTR pmadcswd, pmaddwd, paddd
                 v%5%6 %1, %2, %3, %4
             %elifidn %1, %2
                 ; If %3 or %4 is a memory operand it needs to be encoded as the last operand.
-                %ifid %3
+                %ifnum sizeof%3
                     v%{5}213%6 %2, %3, %4
                 %else
                     v%{5}132%6 %2, %4, %3
diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm
index b09fa81..e7493f4 100644
--- a/libavutil/x86/x86util.asm
+++ b/libavutil/x86/x86util.asm
@@ -357,6 +357,17 @@
 %endif
 %endmacro
 
+%macro HADDPS 3 ; dst, src, tmp
+%if cpuflag(sse3)
+    haddps  %1, %1, %2
+%else
+    movaps  %3, %1
+    shufps  %1, %2, q2020
+    shufps  %3, %2, q3131
+    addps   %1, %3
+%endif
+%endmacro
+
 %macro PALIGNR 4-5
 %if cpuflag(ssse3)
 %if %0==5
diff --git a/libavutil/xtea.c b/libavutil/xtea.c
index 2139aa5..f7892af 100644
--- a/libavutil/xtea.c
+++ b/libavutil/xtea.c
@@ -251,104 +251,3 @@ void av_xtea_le_crypt(AVXTEA *ctx, uint8_t *dst, const uint8_t *src, int count,
 {
     xtea_crypt(ctx, dst, src, count, iv, decrypt, xtea_le_crypt_ecb);
 }
-
-#ifdef TEST
-#include <stdio.h>
-
-#define XTEA_NUM_TESTS 6
-
-static const uint8_t xtea_test_key[XTEA_NUM_TESTS][16] = {
-    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-    { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
-};
-
-static const uint8_t xtea_test_pt[XTEA_NUM_TESTS][8] = {
-    { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
-    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
-    { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f },
-    { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
-    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
-    { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }
-};
-
-static const uint8_t xtea_test_ct[XTEA_NUM_TESTS][8] = {
-    { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 },
-    { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 },
-    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 },
-    { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 },
-    { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d },
-    { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }
-};
-
-static void test_xtea(AVXTEA *ctx, uint8_t *dst, const uint8_t *src,
-                      const uint8_t *ref, int len, uint8_t *iv, int dir,
-                      const char *test,
-                      void (*crypt)(AVXTEA *, uint8_t *, const uint8_t *, int, uint8_t *, int))
-{
-    crypt(ctx, dst, src, len, iv, dir);
-    if (memcmp(dst, ref, 8*len)) {
-        int i;
-        printf("%s failed\ngot      ", test);
-        for (i = 0; i < 8*len; i++)
-            printf("%02x ", dst[i]);
-        printf("\nexpected ");
-        for (i = 0; i < 8*len; i++)
-            printf("%02x ", ref[i]);
-        printf("\n");
-        exit(1);
-    }
-}
-
-int main(void)
-{
-    AVXTEA ctx;
-    uint8_t buf[16], iv[8];
-    int i, j;
-    static const uint8_t src[32] = "HelloWorldHelloWorldHelloWorld";
-    uint8_t ct[32];
-    uint8_t pl[32];
-
-    for (i = 0; i < XTEA_NUM_TESTS; i++) {
-        av_xtea_init(&ctx, xtea_test_key[i]);
-
-        test_xtea(&ctx, buf, xtea_test_pt[i], xtea_test_ct[i], 1, NULL, 0, "encryption", av_xtea_crypt);
-        test_xtea(&ctx, buf, xtea_test_ct[i], xtea_test_pt[i], 1, NULL, 1, "decryption", av_xtea_crypt);
-
-        for (j = 0; j < 4; j++)
-            AV_WL32(&buf[4*j], AV_RB32(&xtea_test_key[i][4*j]));
-        av_xtea_le_init(&ctx, buf);
-        for (j = 0; j < 2; j++) {
-            AV_WL32(&ct[4*j], AV_RB32(&xtea_test_ct[i][4*j]));
-            AV_WL32(&pl[4*j], AV_RB32(&xtea_test_pt[i][4*j]));
-        }
-        test_xtea(&ctx, buf, pl, ct, 1, NULL, 0, "encryption", av_xtea_le_crypt);
-        test_xtea(&ctx, buf, ct, pl, 1, NULL, 1, "decryption", av_xtea_le_crypt);
-
-        /* encrypt */
-        memcpy(iv, "HALLO123", 8);
-        av_xtea_crypt(&ctx, ct, src, 4, iv, 0);
-
-        /* decrypt into pl */
-        memcpy(iv, "HALLO123", 8);
-        test_xtea(&ctx, pl, ct, src, 4, iv, 1, "CBC decryption", av_xtea_crypt);
-
-        memcpy(iv, "HALLO123", 8);
-        test_xtea(&ctx, ct, ct, src, 4, iv, 1, "CBC inplace decryption", av_xtea_crypt);
-    }
-
-    printf("Test encryption/decryption success.\n");
-
-    return 0;
-}
-
-#endif
diff --git a/library.mak b/library.mak
index 3e1082c..ae2d3f2 100644
--- a/library.mak
+++ b/library.mak
@@ -10,18 +10,6 @@ INSTHEADERS := $(INSTHEADERS) $(HEADERS:%=$(SUBDIR)%)
 all-$(CONFIG_STATIC): $(SUBDIR)$(LIBNAME)
 all-$(CONFIG_SHARED): $(SUBDIR)$(SLIBNAME)
 
-$(SUBDIR)%-test.o: $(SUBDIR)%-test.c
-	$(COMPILE_C)
-
-$(SUBDIR)%-test.o: $(SUBDIR)%.c
-	$(COMPILE_C)
-
-$(SUBDIR)%-test.i: $(SUBDIR)%-test.c
-	$(CC) $(CCFLAGS) $(CC_E) $<
-
-$(SUBDIR)%-test.i: $(SUBDIR)%.c
-	$(CC) $(CCFLAGS) $(CC_E) $<
-
 $(SUBDIR)x86/%$(DEFAULT_YASMD).asm: $(SUBDIR)x86/%.asm
 	$(DEPYASM) $(YASMFLAGS) -I $(<D)/ -M -o $@ $< > $(@:.asm=.d)
 	$(YASM) $(YASMFLAGS) -I $(<D)/ -e $< | sed '/^%/d;/^$$/d;' > $@
@@ -33,7 +21,6 @@ $(SUBDIR)x86/%.o: $(SUBDIR)x86/%$(YASMD).asm
 
 LIBOBJS := $(OBJS) $(SUBDIR)%.h.o $(TESTOBJS)
 $(LIBOBJS) $(LIBOBJS:.o=.s) $(LIBOBJS:.o=.i):   CPPFLAGS += -DHAVE_AV_CONFIG_H
-$(TESTOBJS) $(TESTOBJS:.o=.i): CPPFLAGS += -DTEST
 $(TESTOBJS) $(TESTOBJS:.o=.i): CFLAGS += -Umain
 
 $(SUBDIR)$(LIBNAME): $(OBJS)
@@ -66,11 +53,12 @@ $(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(DEP_LIBS)
 endif
 
 clean::
-	$(RM) $(addprefix $(SUBDIR),*-test$(EXESUF) $(CLEANFILES) $(CLEANSUFFIXES) $(LIBSUFFIXES)) \
-	    $(CLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%)
-
+	$(RM) $(addprefix $(SUBDIR),$(CLEANFILES) $(CLEANSUFFIXES) $(LIBSUFFIXES)) \
+	    $(CLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) $(CLEANSUFFIXES:%=$(SUBDIR)tests/%)
+ 
 distclean:: clean
-	$(RM) $(DISTCLEANSUFFIXES:%=$(SUBDIR)%) $(DISTCLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%)
+	$(RM) $(DISTCLEANSUFFIXES:%=$(SUBDIR)%) $(DISTCLEANSUFFIXES:%=$(SUBDIR)$(ARCH)/%) \
+            $(DISTCLEANSUFFIXES:%=$(SUBDIR)tests/%)
 
 install-lib$(NAME)-shared: $(SUBDIR)$(SLIBNAME)
 	$(Q)mkdir -p "$(SHLIBDIR)"
diff --git a/libswresample/arm/Makefile b/libswresample/arm/Makefile
index 60f3f6d..53ab462 100644
--- a/libswresample/arm/Makefile
+++ b/libswresample/arm/Makefile
@@ -1,5 +1,8 @@
-OBJS      += arm/audio_convert_init.o
+OBJS      += arm/audio_convert_init.o \
+             arm/resample_init.o
+
 
 OBJS-$(CONFIG_NEON_CLOBBER_TEST) += arm/neontest.o
 
-NEON-OBJS += arm/audio_convert_neon.o
+NEON-OBJS += arm/audio_convert_neon.o \
+             arm/resample.o
diff --git a/libswresample/arm/resample.S b/libswresample/arm/resample.S
new file mode 100644
index 0000000..c231301
--- /dev/null
+++ b/libswresample/arm/resample.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * 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/arm/asm.S"
+
+function ff_resample_common_apply_filter_x4_float_neon, export=1
+    vmov.f32            q0, #0.0                                       @ accumulator
+1:  vld1.32             {q1}, [r1]!                                    @ src
+    vld1.32             {q2}, [r2]!                                    @ filter
+    vmla.f32            q0, q1, q2                                     @ accumulator += src + {0..3} * filter + {0..3}
+    subs                r3, #4                                         @ filter_length -= 4
+    bgt                 1b                                             @ loop until filter_length
+    vpadd.f32           d0, d0, d1                                     @ pair adding of the 4x32-bit accumulated values
+    vpadd.f32           d0, d0, d0                                     @ pair adding of the 4x32-bit accumulator values
+    vst1.32             {d0[0]}, [r0]                                  @ write accumulator
+    mov pc, lr
+endfunc
+
+function ff_resample_common_apply_filter_x8_float_neon, export=1
+    vmov.f32            q0, #0.0                                       @ accumulator
+1:  vld1.32             {q1}, [r1]!                                    @ src
+    vld1.32             {q2}, [r2]!                                    @ filter
+    vld1.32             {q8}, [r1]!                                    @ src
+    vld1.32             {q9}, [r2]!                                    @ filter
+    vmla.f32            q0, q1, q2                                     @ accumulator += src + {0..3} * filter + {0..3}
+    vmla.f32            q0, q8, q9                                     @ accumulator += src + {4..7} * filter + {4..7}
+    subs                r3, #8                                         @ filter_length -= 8
+    bgt                 1b                                             @ loop until filter_length
+    vpadd.f32           d0, d0, d1                                     @ pair adding of the 4x32-bit accumulated values
+    vpadd.f32           d0, d0, d0                                     @ pair adding of the 4x32-bit accumulator values
+    vst1.32             {d0[0]}, [r0]                                  @ write accumulator
+    mov pc, lr
+endfunc
+
+function ff_resample_common_apply_filter_x4_s16_neon, export=1
+    vmov.s32            q0, #0                                         @ accumulator
+1:  vld1.16             {d2}, [r1]!                                    @ src
+    vld1.16             {d4}, [r2]!                                    @ filter
+    vmlal.s16           q0, d2, d4                                     @ accumulator += src + {0..3} * filter + {0..3}
+    subs                r3, #4                                         @ filter_length -= 4
+    bgt                 1b                                             @ loop until filter_length
+    vpadd.s32           d0, d0, d1                                     @ pair adding of the 4x32-bit accumulated values
+    vpadd.s32           d0, d0, d0                                     @ pair adding of the 4x32-bit accumulator values
+    vst1.32             {d0[0]}, [r0]                                  @ write accumulator
+    mov pc, lr
+endfunc
+
+function ff_resample_common_apply_filter_x8_s16_neon, export=1
+    vmov.s32            q0, #0                                         @ accumulator
+1:  vld1.16             {q1}, [r1]!                                    @ src
+    vld1.16             {q2}, [r2]!                                    @ filter
+    vmlal.s16           q0, d2, d4                                     @ accumulator += src + {0..3} * filter + {0..3}
+    vmlal.s16           q0, d3, d5                                     @ accumulator += src + {4..7} * filter + {4..7}
+    subs                r3, #8                                         @ filter_length -= 8
+    bgt                 1b                                             @ loop until filter_length
+    vpadd.s32           d0, d0, d1                                     @ pair adding of the 4x32-bit accumulated values
+    vpadd.s32           d0, d0, d0                                     @ pair adding of the 4x32-bit accumulator values
+    vst1.32             {d0[0]}, [r0]                                  @ write accumulator
+    mov pc, lr
+endfunc
diff --git a/libswresample/arm/resample_init.c b/libswresample/arm/resample_init.c
new file mode 100644
index 0000000..003fafd
--- /dev/null
+++ b/libswresample/arm/resample_init.c
@@ -0,0 +1,122 @@
+/*
+ * Audio resampling
+ *
+ * Copyright (c) 2004-2012 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include "libavutil/cpu.h"
+#include "libavutil/avassert.h"
+
+#include "libavutil/arm/cpu.h"
+#include "libswresample/resample.h"
+
+#define DECLARE_RESAMPLE_COMMON_TEMPLATE(TYPE, DELEM, FELEM, FELEM2, OUT)                         \
+                                                                                                  \
+void ff_resample_common_apply_filter_x4_##TYPE##_neon(FELEM2 *acc, const DELEM *src,              \
+                                                      const FELEM *filter, int length);           \
+                                                                                                  \
+void ff_resample_common_apply_filter_x8_##TYPE##_neon(FELEM2 *acc, const DELEM *src,              \
+                                                      const FELEM *filter, int length);           \
+                                                                                                  \
+static int ff_resample_common_##TYPE##_neon(ResampleContext *c, void *dest, const void *source,   \
+                                            int n, int update_ctx)                                \
+{                                                                                                 \
+    DELEM *dst = dest;                                                                            \
+    const DELEM *src = source;                                                                    \
+    int dst_index;                                                                                \
+    int index= c->index;                                                                          \
+    int frac= c->frac;                                                                            \
+    int sample_index = 0;                                                                         \
+    int x4_aligned_filter_length = c->filter_length & ~3;                                         \
+    int x8_aligned_filter_length = c->filter_length & ~7;                                         \
+                                                                                                  \
+    while (index >= c->phase_count) {                                                             \
+        sample_index++;                                                                           \
+        index -= c->phase_count;                                                                  \
+    }                                                                                             \
+                                                                                                  \
+    for (dst_index = 0; dst_index < n; dst_index++) {                                             \
+        FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;                     \
+                                                                                                  \
+        FELEM2 val=0;                                                                             \
+        int i = 0;                                                                                \
+        if (x8_aligned_filter_length >= 8) {                                                      \
+            ff_resample_common_apply_filter_x8_##TYPE##_neon(&val, &src[sample_index],            \
+                                                             filter, x8_aligned_filter_length);   \
+            i += x8_aligned_filter_length;                                                        \
+                                                                                                  \
+        } else if (x4_aligned_filter_length >= 4) {                                               \
+            ff_resample_common_apply_filter_x4_##TYPE##_neon(&val, &src[sample_index],            \
+                                                             filter, x4_aligned_filter_length);   \
+            i += x4_aligned_filter_length;                                                        \
+        }                                                                                         \
+        for (; i < c->filter_length; i++) {                                                       \
+            val += src[sample_index + i] * (FELEM2)filter[i];                                     \
+        }                                                                                         \
+        OUT(dst[dst_index], val);                                                                 \
+                                                                                                  \
+        frac  += c->dst_incr_mod;                                                                 \
+        index += c->dst_incr_div;                                                                 \
+        if (frac >= c->src_incr) {                                                                \
+            frac -= c->src_incr;                                                                  \
+            index++;                                                                              \
+        }                                                                                         \
+                                                                                                  \
+        while (index >= c->phase_count) {                                                         \
+            sample_index++;                                                                       \
+            index -= c->phase_count;                                                              \
+        }                                                                                         \
+    }                                                                                             \
+                                                                                                  \
+    if(update_ctx){                                                                               \
+        c->frac= frac;                                                                            \
+        c->index= index;                                                                          \
+    }                                                                                             \
+                                                                                                  \
+    return sample_index;                                                                          \
+}                                                                                                 \
+
+#define OUT(d, v) d = v
+DECLARE_RESAMPLE_COMMON_TEMPLATE(float, float, float, float, OUT)
+#undef OUT
+
+#define OUT(d, v) (v) = ((v) + (1<<(14)))>>15; (d) = av_clip_int16(v)
+DECLARE_RESAMPLE_COMMON_TEMPLATE(s16, int16_t, int16_t, int32_t, OUT)
+#undef OUT
+
+av_cold void swri_resample_dsp_arm_init(ResampleContext *c)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (!have_neon(cpu_flags))
+        return;
+
+    switch(c->format) {
+    case AV_SAMPLE_FMT_FLTP:
+        if (!c->linear)
+            c->dsp.resample = ff_resample_common_float_neon;
+        break;
+    case AV_SAMPLE_FMT_S16P:
+        if (!c->linear)
+            c->dsp.resample = ff_resample_common_s16_neon;
+        break;
+    }
+}
diff --git a/libswresample/options.c b/libswresample/options.c
index eac1a7c..816ce47 100644
--- a/libswresample/options.c
+++ b/libswresample/options.c
@@ -85,6 +85,7 @@ static const AVOption options[]={
 {"filter_size"          , "set swr resampling filter size", OFFSET(filter_size)  , AV_OPT_TYPE_INT  , {.i64=32                    }, 0      , INT_MAX   , PARAM },
 {"phase_shift"          , "set swr resampling phase shift", OFFSET(phase_shift)  , AV_OPT_TYPE_INT  , {.i64=10                    }, 0      , 24        , PARAM },
 {"linear_interp"        , "enable linear interpolation" , OFFSET(linear_interp)  , AV_OPT_TYPE_BOOL , {.i64=0                     }, 0      , 1         , PARAM },
+{"exact_rational"       , "enable exact rational"       , OFFSET(exact_rational) , AV_OPT_TYPE_BOOL , {.i64=0                     }, 0      , 1         , PARAM },
 {"cutoff"               , "set cutoff frequency ratio"  , OFFSET(cutoff)         , AV_OPT_TYPE_DOUBLE,{.dbl=0.                    }, 0      , 1         , PARAM },
 
 /* duplicate option in order to work with avconv */
diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c
index 932088f..ddba043 100644
--- a/libswresample/rematrix.c
+++ b/libswresample/rematrix.c
@@ -32,6 +32,9 @@
 
 #define TEMPLATE_REMATRIX_S16
 #include "rematrix_template.c"
+#define TEMPLATE_CLIP
+#include "rematrix_template.c"
+#undef TEMPLATE_CLIP
 #undef TEMPLATE_REMATRIX_S16
 
 #define TEMPLATE_REMATRIX_S32
@@ -367,17 +370,33 @@ av_cold int swri_rematrix_init(SwrContext *s){
             return r;
     }
     if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){
+        int maxsum = 0;
         s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
         s->native_one    = av_mallocz(sizeof(int));
         if (!s->native_matrix || !s->native_one)
             return AVERROR(ENOMEM);
-        for (i = 0; i < nb_out; i++)
-            for (j = 0; j < nb_in; j++)
-                ((int*)s->native_matrix)[i * nb_in + j] = lrintf(s->matrix[i][j] * 32768);
+        for (i = 0; i < nb_out; i++) {
+            double rem = 0;
+            int sum = 0;
+
+            for (j = 0; j < nb_in; j++) {
+                double target = s->matrix[i][j] * 32768 + rem;
+                ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target);
+                rem += target - ((int*)s->native_matrix)[i * nb_in + j];
+                sum += FFABS(((int*)s->native_matrix)[i * nb_in + j]);
+            }
+            maxsum = FFMAX(maxsum, sum);
+        }
         *((int*)s->native_one) = 32768;
-        s->mix_1_1_f = (mix_1_1_func_type*)copy_s16;
-        s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16;
-        s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s);
+        if (maxsum <= 32768) {
+            s->mix_1_1_f = (mix_1_1_func_type*)copy_s16;
+            s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16;
+            s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s);
+        } else {
+            s->mix_1_1_f = (mix_1_1_func_type*)copy_clip_s16;
+            s->mix_2_1_f = (mix_2_1_func_type*)sum2_clip_s16;
+            s->mix_any_f = (mix_any_func_type*)get_mix_any_func_clip_s16(s);
+        }
     }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){
         s->native_matrix = av_calloc(nb_in * nb_out, sizeof(float));
         s->native_one    = av_mallocz(sizeof(float));
diff --git a/libswresample/rematrix_template.c b/libswresample/rematrix_template.c
index 95a3b9a..add65e3 100644
--- a/libswresample/rematrix_template.c
+++ b/libswresample/rematrix_template.c
@@ -31,11 +31,16 @@
 #    define INTER double
 #    define RENAME(x) x ## _double
 #elif defined(TEMPLATE_REMATRIX_S16)
-#    define R(x) (((x) + 16384)>>15)
 #    define SAMPLE int16_t
 #    define COEFF int
 #    define INTER int
+#  ifdef TEMPLATE_CLIP
+#    define R(x) av_clip_int16(((x) + 16384)>>15)
+#    define RENAME(x) x ## _clip_s16
+#  else
+#    define R(x) (((x) + 16384)>>15)
 #    define RENAME(x) x ## _s16
+#  endif
 #elif defined(TEMPLATE_REMATRIX_S32)
 #    define R(x) (((x) + 16384)>>15)
 #    define SAMPLE int32_t
diff --git a/libswresample/resample.c b/libswresample/resample.c
index 7888e57..b834248 100644
--- a/libswresample/resample.c
+++ b/libswresample/resample.c
@@ -144,9 +144,10 @@ static double bessel(double x) {
 static int build_filter(ResampleContext *c, void *filter, double factor, int tap_count, int alloc, int phase_count, int scale,
                         int filter_type, double kaiser_beta){
     int ph, i;
+    int ph_nb = phase_count % 2 ? phase_count : phase_count / 2 + 1;
     double x, y, w, t, s;
     double *tab = av_malloc_array(tap_count+1,  sizeof(*tab));
-    double *sin_lut = av_malloc_array(phase_count / 2 + 1, sizeof(*sin_lut));
+    double *sin_lut = av_malloc_array(ph_nb, sizeof(*sin_lut));
     const int center= (tap_count-1)/2;
 
     if (!tab || !sin_lut)
@@ -156,13 +157,11 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
     if (factor > 1.0)
         factor = 1.0;
 
-    av_assert0(phase_count == 1 || phase_count % 2 == 0);
-
     if (factor == 1.0) {
-        for (ph = 0; ph <= phase_count / 2; ph++)
+        for (ph = 0; ph < ph_nb; ph++)
             sin_lut[ph] = sin(M_PI * ph / phase_count);
     }
-    for(ph = 0; ph <= phase_count / 2; ph++) {
+    for(ph = 0; ph < ph_nb; ph++) {
         double norm = 0;
         s = sin_lut[ph];
         for(i=0;i<=tap_count;i++) {
@@ -203,7 +202,8 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
         case AV_SAMPLE_FMT_S16P:
             for(i=0;i<tap_count;i++)
                 ((int16_t*)filter)[ph * alloc + i] = av_clip_int16(lrintf(tab[i] * scale / norm));
-            if (tap_count % 2 == 0) {
+            if (phase_count % 2) break;
+            if (tap_count % 2 == 0 || tap_count == 1) {
                 for (i = 0; i < tap_count; i++)
                     ((int16_t*)filter)[(phase_count-ph) * alloc + tap_count-1-i] = ((int16_t*)filter)[ph * alloc + i];
             }
@@ -216,7 +216,8 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
         case AV_SAMPLE_FMT_S32P:
             for(i=0;i<tap_count;i++)
                 ((int32_t*)filter)[ph * alloc + i] = av_clipl_int32(llrint(tab[i] * scale / norm));
-            if (tap_count % 2 == 0) {
+            if (phase_count % 2) break;
+            if (tap_count % 2 == 0 || tap_count == 1) {
                 for (i = 0; i < tap_count; i++)
                     ((int32_t*)filter)[(phase_count-ph) * alloc + tap_count-1-i] = ((int32_t*)filter)[ph * alloc + i];
             }
@@ -229,7 +230,8 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
         case AV_SAMPLE_FMT_FLTP:
             for(i=0;i<tap_count;i++)
                 ((float*)filter)[ph * alloc + i] = tab[i] * scale / norm;
-            if (tap_count % 2 == 0) {
+            if (phase_count % 2) break;
+            if (tap_count % 2 == 0 || tap_count == 1) {
                 for (i = 0; i < tap_count; i++)
                     ((float*)filter)[(phase_count-ph) * alloc + tap_count-1-i] = ((float*)filter)[ph * alloc + i];
             }
@@ -241,7 +243,8 @@ static int build_filter(ResampleContext *c, void *filter, double factor, int tap
         case AV_SAMPLE_FMT_DBLP:
             for(i=0;i<tap_count;i++)
                 ((double*)filter)[ph * alloc + i] = tab[i] * scale / norm;
-            if (tap_count % 2 == 0) {
+            if (phase_count % 2) break;
+            if (tap_count % 2 == 0 || tap_count == 1) {
                 for (i = 0; i < tap_count; i++)
                     ((double*)filter)[(phase_count-ph) * alloc + tap_count-1-i] = ((double*)filter)[ph * alloc + i];
             }
@@ -297,13 +300,24 @@ fail:
 
 static ResampleContext *resample_init(ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
                                     double cutoff0, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta,
-                                    double precision, int cheby)
+                                    double precision, int cheby, int exact_rational)
 {
     double cutoff = cutoff0? cutoff0 : 0.97;
     double factor= FFMIN(out_rate * cutoff / in_rate, 1.0);
     int phase_count= 1<<phase_shift;
+    int phase_count_compensation = phase_count;
+
+    if (exact_rational) {
+        int phase_count_exact, phase_count_exact_den;
+
+        av_reduce(&phase_count_exact, &phase_count_exact_den, out_rate, in_rate, INT_MAX);
+        if (phase_count_exact <= phase_count) {
+            phase_count_compensation = phase_count_exact * (phase_count / phase_count_exact);
+            phase_count = phase_count_exact;
+        }
+    }
 
-    if (!c || c->phase_shift != phase_shift || c->linear!=linear || c->factor != factor
+    if (!c || c->phase_count != phase_count || c->linear!=linear || c->factor != factor
            || c->filter_length != FFMAX((int)ceil(filter_size/factor), 1) || c->format != format
            || c->filter_type != filter_type || c->kaiser_beta != kaiser_beta) {
         c = av_mallocz(sizeof(*c));
@@ -335,8 +349,7 @@ static ResampleContext *resample_init(ResampleContext *c, int out_rate, int in_r
             goto error;
         }
 
-        c->phase_shift   = phase_shift;
-        c->phase_mask    = phase_count - 1;
+        c->phase_count   = phase_count;
         c->linear        = linear;
         c->factor        = factor;
         c->filter_length = FFMAX((int)ceil(filter_size/factor), 1);
@@ -344,6 +357,7 @@ static ResampleContext *resample_init(ResampleContext *c, int out_rate, int in_r
         c->filter_bank   = av_calloc(c->filter_alloc, (phase_count+1)*c->felem_size);
         c->filter_type   = filter_type;
         c->kaiser_beta   = kaiser_beta;
+        c->phase_count_compensation = phase_count_compensation;
         if (!c->filter_bank)
             goto error;
         if (build_filter(c, (void*)c->filter_bank, factor, c->filter_length, c->filter_alloc, phase_count, 1<<c->filter_shift, filter_type, kaiser_beta))
@@ -382,7 +396,63 @@ static void resample_free(ResampleContext **c){
     av_freep(c);
 }
 
+static int rebuild_filter_bank_with_compensation(ResampleContext *c)
+{
+    uint8_t *new_filter_bank;
+    int new_src_incr, new_dst_incr;
+    int phase_count = c->phase_count_compensation;
+    int ret;
+
+    if (phase_count == c->phase_count)
+        return 0;
+
+    av_assert0(!c->frac && !c->dst_incr_mod && !c->compensation_distance);
+
+    new_filter_bank = av_calloc(c->filter_alloc, (phase_count + 1) * c->felem_size);
+    if (!new_filter_bank)
+        return AVERROR(ENOMEM);
+
+    ret = build_filter(c, new_filter_bank, c->factor, c->filter_length, c->filter_alloc,
+                       phase_count, 1 << c->filter_shift, c->filter_type, c->kaiser_beta);
+    if (ret < 0) {
+        av_freep(&new_filter_bank);
+        return ret;
+    }
+    memcpy(new_filter_bank + (c->filter_alloc*phase_count+1)*c->felem_size, new_filter_bank, (c->filter_alloc-1)*c->felem_size);
+    memcpy(new_filter_bank + (c->filter_alloc*phase_count  )*c->felem_size, new_filter_bank + (c->filter_alloc - 1)*c->felem_size, c->felem_size);
+
+    if (!av_reduce(&new_src_incr, &new_dst_incr, c->src_incr,
+                   c->dst_incr * (int64_t)(phase_count/c->phase_count), INT32_MAX/2))
+    {
+        av_freep(&new_filter_bank);
+        return AVERROR(EINVAL);
+    }
+
+    c->src_incr = new_src_incr;
+    c->dst_incr = new_dst_incr;
+    while (c->dst_incr < (1<<20) && c->src_incr < (1<<20)) {
+        c->dst_incr *= 2;
+        c->src_incr *= 2;
+    }
+    c->ideal_dst_incr = c->dst_incr;
+    c->dst_incr_div   = c->dst_incr / c->src_incr;
+    c->dst_incr_mod   = c->dst_incr % c->src_incr;
+    c->index         *= phase_count / c->phase_count;
+    c->phase_count    = phase_count;
+    av_freep(&c->filter_bank);
+    c->filter_bank = new_filter_bank;
+    return 0;
+}
+
 static int set_compensation(ResampleContext *c, int sample_delta, int compensation_distance){
+    int ret;
+
+    if (compensation_distance) {
+        ret = rebuild_filter_bank_with_compensation(c);
+        if (ret < 0)
+            return ret;
+    }
+
     c->compensation_distance= compensation_distance;
     if (compensation_distance)
         c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * (int64_t)sample_delta / compensation_distance;
@@ -399,7 +469,7 @@ static int swri_resample(ResampleContext *c,
                          uint8_t *dst, const uint8_t *src, int *consumed,
                          int src_size, int dst_size, int update_ctx)
 {
-    if (c->filter_length == 1 && c->phase_shift == 0) {
+    if (c->filter_length == 1 && c->phase_count == 1) {
         int index= c->index;
         int frac= c->frac;
         int64_t index2= (1LL<<32)*c->frac/c->src_incr + (1LL<<32)*index;
@@ -418,7 +488,7 @@ static int swri_resample(ResampleContext *c,
             c->index = 0;
         }
     } else {
-        int64_t end_index = (1LL + src_size - c->filter_length) << c->phase_shift;
+        int64_t end_index = (1LL + src_size - c->filter_length) * c->phase_count;
         int64_t delta_frac = (end_index - c->index) * c->src_incr - c->frac;
         int delta_n = (delta_frac + c->dst_incr - 1) / c->dst_incr;
 
@@ -438,7 +508,7 @@ static int multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, A
     int av_unused mm_flags = av_get_cpu_flags();
     int need_emms = c->format == AV_SAMPLE_FMT_S16P && ARCH_X86_32 &&
                     (mm_flags & (AV_CPU_FLAG_MMX2 | AV_CPU_FLAG_SSE2)) == AV_CPU_FLAG_MMX2;
-    int64_t max_src_size = (INT64_MAX >> (c->phase_shift+1)) / c->src_incr;
+    int64_t max_src_size = (INT64_MAX/2 / c->phase_count) / c->src_incr;
 
     if (c->compensation_distance)
         dst_size = FFMIN(dst_size, c->compensation_distance);
@@ -466,11 +536,11 @@ static int multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, A
 static int64_t get_delay(struct SwrContext *s, int64_t base){
     ResampleContext *c = s->resample;
     int64_t num = s->in_buffer_count - (c->filter_length-1)/2;
-    num *= 1 << c->phase_shift;
+    num *= c->phase_count;
     num -= c->index;
     num *= c->src_incr;
     num -= c->frac;
-    return av_rescale(num, base, s->in_sample_rate*(int64_t)c->src_incr << c->phase_shift);
+    return av_rescale(num, base, s->in_sample_rate*(int64_t)c->src_incr * c->phase_count);
 }
 
 static int64_t get_out_samples(struct SwrContext *s, int in_samples) {
@@ -479,9 +549,9 @@ static int64_t get_out_samples(struct SwrContext *s, int in_samples) {
     // They also make it easier to proof that changes and optimizations do not
     // break the upper bound.
     int64_t num = s->in_buffer_count + 2LL + in_samples;
-    num *= 1 << c->phase_shift;
+    num *= c->phase_count;
     num -= c->index;
-    num = av_rescale_rnd(num, s->out_sample_rate, ((int64_t)s->in_sample_rate) << c->phase_shift, AV_ROUND_UP) + 2;
+    num = av_rescale_rnd(num, s->out_sample_rate, ((int64_t)s->in_sample_rate) * c->phase_count, AV_ROUND_UP) + 2;
 
     if (c->compensation_distance) {
         if (num > INT_MAX)
@@ -545,10 +615,13 @@ static int invert_initial_buffer(ResampleContext *c, AudioData *dst, const Audio
     }
 
     res = num - *out_sz;
-    *out_idx = c->filter_length + (c->index >> c->phase_shift);
+    *out_idx = c->filter_length;
+    while (c->index < 0) {
+        --*out_idx;
+        c->index += c->phase_count;
+    }
     *out_sz = FFMAX(*out_sz + c->filter_length,
                     1 + c->filter_length * 2) - *out_idx;
-    c->index &= c->phase_mask;
 
     return FFMAX(res, 0);
 }
diff --git a/libswresample/resample.h b/libswresample/resample.h
index a126b11..7fe9b97 100644
--- a/libswresample/resample.h
+++ b/libswresample/resample.h
@@ -40,8 +40,7 @@ typedef struct ResampleContext {
     int frac;
     int src_incr;
     int compensation_distance;
-    int phase_shift;
-    int phase_mask;
+    int phase_count;
     int linear;
     enum SwrFilterType filter_type;
     double kaiser_beta;
@@ -49,6 +48,7 @@ typedef struct ResampleContext {
     enum AVSampleFormat format;
     int felem_size;
     int filter_shift;
+    int phase_count_compensation;      /* desired phase_count when compensation is enabled */
 
     struct {
         void (*resample_one)(void *dst, const void *src,
@@ -60,5 +60,6 @@ typedef struct ResampleContext {
 
 void swri_resample_dsp_init(ResampleContext *c);
 void swri_resample_dsp_x86_init(ResampleContext *c);
+void swri_resample_dsp_arm_init(ResampleContext *c);
 
 #endif /* SWRESAMPLE_RESAMPLE_H */
diff --git a/libswresample/resample_dsp.c b/libswresample/resample_dsp.c
index a811b8b..41369f3 100644
--- a/libswresample/resample_dsp.c
+++ b/libswresample/resample_dsp.c
@@ -65,4 +65,5 @@ void swri_resample_dsp_init(ResampleContext *c)
     }
 
     if (ARCH_X86) swri_resample_dsp_x86_init(c);
+    else if (ARCH_ARM) swri_resample_dsp_arm_init(c);
 }
diff --git a/libswresample/resample_template.c b/libswresample/resample_template.c
index d71efd6..1636f4e 100644
--- a/libswresample/resample_template.c
+++ b/libswresample/resample_template.c
@@ -92,9 +92,13 @@ static int RENAME(resample_common)(ResampleContext *c,
     int dst_index;
     int index= c->index;
     int frac= c->frac;
-    int sample_index = index >> c->phase_shift;
+    int sample_index = 0;
+
+    while (index >= c->phase_count) {
+        sample_index++;
+        index -= c->phase_count;
+    }
 
-    index &= c->phase_mask;
     for (dst_index = 0; dst_index < n; dst_index++) {
         FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;
 
@@ -111,8 +115,11 @@ static int RENAME(resample_common)(ResampleContext *c,
             frac -= c->src_incr;
             index++;
         }
-        sample_index += index >> c->phase_shift;
-        index &= c->phase_mask;
+
+        while (index >= c->phase_count) {
+            sample_index++;
+            index -= c->phase_count;
+        }
     }
 
     if(update_ctx){
@@ -132,12 +139,16 @@ static int RENAME(resample_linear)(ResampleContext *c,
     int dst_index;
     int index= c->index;
     int frac= c->frac;
-    int sample_index = index >> c->phase_shift;
+    int sample_index = 0;
 #if FILTER_SHIFT == 0
     double inv_src_incr = 1.0 / c->src_incr;
 #endif
 
-    index &= c->phase_mask;
+    while (index >= c->phase_count) {
+        sample_index++;
+        index -= c->phase_count;
+    }
+
     for (dst_index = 0; dst_index < n; dst_index++) {
         FELEM *filter = ((FELEM *) c->filter_bank) + c->filter_alloc * index;
         FELEM2 val=0, v2 = 0;
@@ -164,8 +175,11 @@ static int RENAME(resample_linear)(ResampleContext *c,
             frac -= c->src_incr;
             index++;
         }
-        sample_index += index >> c->phase_shift;
-        index &= c->phase_mask;
+
+        while (index >= c->phase_count) {
+            sample_index++;
+            index -= c->phase_count;
+        }
     }
 
     if(update_ctx){
diff --git a/libswresample/soxr_resample.c b/libswresample/soxr_resample.c
index 807f508..b9c6735 100644
--- a/libswresample/soxr_resample.c
+++ b/libswresample/soxr_resample.c
@@ -30,7 +30,7 @@
 #include <soxr.h>
 
 static struct ResampleContext *create(struct ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
-        double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta, double precision, int cheby){
+        double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta, double precision, int cheby, int exact_rational){
     soxr_error_t error;
 
     soxr_datatype_t type =
diff --git a/libswresample/swresample-test.c b/libswresample/swresample-test.c
deleted file mode 100644
index 0aa47c8..0000000
--- a/libswresample/swresample-test.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright (C) 2011-2012 Michael Niedermayer (michaelni at gmx.at)
- * Copyright (c) 2002 Fabrice Bellard
- *
- * This file is part of libswresample
- *
- * libswresample 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.
- *
- * libswresample 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 libswresample; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/avassert.h"
-#include "libavutil/channel_layout.h"
-#include "libavutil/common.h"
-#include "libavutil/opt.h"
-#include "swresample.h"
-
-#undef time
-#include "time.h"
-#undef fprintf
-
-#define SAMPLES 1000
-
-#define SWR_CH_MAX 32
-
-#define ASSERT_LEVEL 2
-
-static double get(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f){
-    const uint8_t *p;
-    if(av_sample_fmt_is_planar(f)){
-        f= av_get_alt_sample_fmt(f, 0);
-        p= a[ch];
-    }else{
-        p= a[0];
-        index= ch + index*ch_count;
-    }
-
-    switch(f){
-    case AV_SAMPLE_FMT_U8 : return ((const uint8_t*)p)[index]/127.0-1.0;
-    case AV_SAMPLE_FMT_S16: return ((const int16_t*)p)[index]/32767.0;
-    case AV_SAMPLE_FMT_S32: return ((const int32_t*)p)[index]/2147483647.0;
-    case AV_SAMPLE_FMT_FLT: return ((const float  *)p)[index];
-    case AV_SAMPLE_FMT_DBL: return ((const double *)p)[index];
-    default: av_assert0(0);
-    }
-}
-
-static void  set(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f, double v){
-    uint8_t *p;
-    if(av_sample_fmt_is_planar(f)){
-        f= av_get_alt_sample_fmt(f, 0);
-        p= a[ch];
-    }else{
-        p= a[0];
-        index= ch + index*ch_count;
-    }
-    switch(f){
-    case AV_SAMPLE_FMT_U8 : ((uint8_t*)p)[index]= av_clip_uint8 (lrint((v+1.0)*127));     break;
-    case AV_SAMPLE_FMT_S16: ((int16_t*)p)[index]= av_clip_int16 (lrint(v*32767));         break;
-    case AV_SAMPLE_FMT_S32: ((int32_t*)p)[index]= av_clipl_int32(llrint(v*2147483647));   break;
-    case AV_SAMPLE_FMT_FLT: ((float  *)p)[index]= v;                                      break;
-    case AV_SAMPLE_FMT_DBL: ((double *)p)[index]= v;                                      break;
-    default: av_assert2(0);
-    }
-}
-
-static void shift(uint8_t *a[], int index, int ch_count, enum AVSampleFormat f){
-    int ch;
-
-    if(av_sample_fmt_is_planar(f)){
-        f= av_get_alt_sample_fmt(f, 0);
-        for(ch= 0; ch<ch_count; ch++)
-            a[ch] += index*av_get_bytes_per_sample(f);
-    }else{
-        a[0] += index*ch_count*av_get_bytes_per_sample(f);
-    }
-}
-
-static const enum AVSampleFormat formats[] = {
-    AV_SAMPLE_FMT_S16,
-    AV_SAMPLE_FMT_FLTP,
-    AV_SAMPLE_FMT_S16P,
-    AV_SAMPLE_FMT_FLT,
-    AV_SAMPLE_FMT_S32P,
-    AV_SAMPLE_FMT_S32,
-    AV_SAMPLE_FMT_U8P,
-    AV_SAMPLE_FMT_U8,
-    AV_SAMPLE_FMT_DBLP,
-    AV_SAMPLE_FMT_DBL,
-};
-
-static const int rates[] = {
-    8000,
-    11025,
-    16000,
-    22050,
-    32000,
-    48000,
-};
-
-static const uint64_t layouts[]={
-    AV_CH_LAYOUT_MONO                    ,
-    AV_CH_LAYOUT_STEREO                  ,
-    AV_CH_LAYOUT_2_1                     ,
-    AV_CH_LAYOUT_SURROUND                ,
-    AV_CH_LAYOUT_4POINT0                 ,
-    AV_CH_LAYOUT_2_2                     ,
-    AV_CH_LAYOUT_QUAD                    ,
-    AV_CH_LAYOUT_5POINT0                 ,
-    AV_CH_LAYOUT_5POINT1                 ,
-    AV_CH_LAYOUT_5POINT0_BACK            ,
-    AV_CH_LAYOUT_5POINT1_BACK            ,
-    AV_CH_LAYOUT_7POINT0                 ,
-    AV_CH_LAYOUT_7POINT1                 ,
-    AV_CH_LAYOUT_7POINT1_WIDE            ,
-};
-
-static void setup_array(uint8_t *out[SWR_CH_MAX], uint8_t *in, enum AVSampleFormat format, int samples){
-    if(av_sample_fmt_is_planar(format)){
-        int i;
-        int plane_size= av_get_bytes_per_sample(format&0xFF)*samples;
-        format&=0xFF;
-        for(i=0; i<SWR_CH_MAX; i++){
-            out[i]= in + i*plane_size;
-        }
-    }else{
-        out[0]= in;
-    }
-}
-
-static int cmp(const void *a, const void *b){
-    return *(const int *)a - *(const int *)b;
-}
-
-static void audiogen(void *data, enum AVSampleFormat sample_fmt,
-                     int channels, int sample_rate, int nb_samples)
-{
-    int i, ch, k;
-    double v, f, a, ampa;
-    double tabf1[SWR_CH_MAX];
-    double tabf2[SWR_CH_MAX];
-    double taba[SWR_CH_MAX];
-    unsigned static rnd;
-
-#define PUT_SAMPLE set(data, ch, k, channels, sample_fmt, v);
-#define uint_rand(x) ((x) = (x) * 1664525 + 1013904223)
-#define dbl_rand(x) (uint_rand(x)*2.0 / (double)UINT_MAX - 1)
-    k = 0;
-
-    /* 1 second of single freq sinus at 1000 Hz */
-    a = 0;
-    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
-        v = sin(a) * 0.30;
-        for (ch = 0; ch < channels; ch++)
-            PUT_SAMPLE
-        a += M_PI * 1000.0 * 2.0 / sample_rate;
-    }
-
-    /* 1 second of varying frequency between 100 and 10000 Hz */
-    a = 0;
-    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
-        v = sin(a) * 0.30;
-        for (ch = 0; ch < channels; ch++)
-            PUT_SAMPLE
-        f  = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
-        a += M_PI * f * 2.0 / sample_rate;
-    }
-
-    /* 0.5 second of low amplitude white noise */
-    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
-        v = dbl_rand(rnd) * 0.30;
-        for (ch = 0; ch < channels; ch++)
-            PUT_SAMPLE
-    }
-
-    /* 0.5 second of high amplitude white noise */
-    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
-        v = dbl_rand(rnd);
-        for (ch = 0; ch < channels; ch++)
-            PUT_SAMPLE
-    }
-
-    /* 1 second of unrelated ramps for each channel */
-    for (ch = 0; ch < channels; ch++) {
-        taba[ch]  = 0;
-        tabf1[ch] = 100 + uint_rand(rnd) % 5000;
-        tabf2[ch] = 100 + uint_rand(rnd) % 5000;
-    }
-    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
-        for (ch = 0; ch < channels; ch++) {
-            v = sin(taba[ch]) * 0.30;
-            PUT_SAMPLE
-            f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
-            taba[ch] += M_PI * f * 2.0 / sample_rate;
-        }
-    }
-
-    /* 2 seconds of 500 Hz with varying volume */
-    a    = 0;
-    ampa = 0;
-    for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
-        for (ch = 0; ch < channels; ch++) {
-            double amp = (1.0 + sin(ampa)) * 0.15;
-            if (ch & 1)
-                amp = 0.30 - amp;
-            v = sin(a) * amp;
-            PUT_SAMPLE
-            a    += M_PI * 500.0 * 2.0 / sample_rate;
-            ampa += M_PI *  2.0 / sample_rate;
-        }
-    }
-}
-
-int main(int argc, char **argv){
-    int in_sample_rate, out_sample_rate, ch ,i, flush_count;
-    uint64_t in_ch_layout, out_ch_layout;
-    enum AVSampleFormat in_sample_fmt, out_sample_fmt;
-    uint8_t array_in[SAMPLES*8*8];
-    uint8_t array_mid[SAMPLES*8*8*3];
-    uint8_t array_out[SAMPLES*8*8+100];
-    uint8_t *ain[SWR_CH_MAX];
-    uint8_t *aout[SWR_CH_MAX];
-    uint8_t *amid[SWR_CH_MAX];
-    int flush_i=0;
-    int mode;
-    int num_tests = 10000;
-    uint32_t seed = 0;
-    uint32_t rand_seed = 0;
-    int remaining_tests[FF_ARRAY_ELEMS(rates) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats)];
-    int max_tests = FF_ARRAY_ELEMS(remaining_tests);
-    int test;
-    int specific_test= -1;
-
-    struct SwrContext * forw_ctx= NULL;
-    struct SwrContext *backw_ctx= NULL;
-
-    if (argc > 1) {
-        if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
-            av_log(NULL, AV_LOG_INFO, "Usage: swresample-test [<num_tests>[ <test>]]  \n"
-                   "num_tests           Default is %d\n", num_tests);
-            return 0;
-        }
-        num_tests = strtol(argv[1], NULL, 0);
-        if(num_tests < 0) {
-            num_tests = -num_tests;
-            rand_seed = time(0);
-        }
-        if(num_tests<= 0 || num_tests>max_tests)
-            num_tests = max_tests;
-        if(argc > 2) {
-            specific_test = strtol(argv[1], NULL, 0);
-        }
-    }
-
-    for(i=0; i<max_tests; i++)
-        remaining_tests[i] = i;
-
-    for(test=0; test<num_tests; test++){
-        unsigned r;
-        uint_rand(seed);
-        r = (seed * (uint64_t)(max_tests - test)) >>32;
-        FFSWAP(int, remaining_tests[r], remaining_tests[max_tests - test - 1]);
-    }
-    qsort(remaining_tests + max_tests - num_tests, num_tests, sizeof(remaining_tests[0]), cmp);
-    in_sample_rate=16000;
-    for(test=0; test<num_tests; test++){
-        char  in_layout_string[256];
-        char out_layout_string[256];
-        unsigned vector= remaining_tests[max_tests - test - 1];
-        int in_ch_count;
-        int out_count, mid_count, out_ch_count;
-
-        in_ch_layout    = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);
-        out_ch_layout   = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);
-        in_sample_fmt   = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);
-        out_sample_fmt  = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);
-        out_sample_rate = rates  [vector % FF_ARRAY_ELEMS(rates  )]; vector /= FF_ARRAY_ELEMS(rates);
-        av_assert0(!vector);
-
-        if(specific_test == 0){
-            if(out_sample_rate != in_sample_rate || in_ch_layout != out_ch_layout)
-                continue;
-        }
-
-        in_ch_count= av_get_channel_layout_nb_channels(in_ch_layout);
-        out_ch_count= av_get_channel_layout_nb_channels(out_ch_layout);
-        av_get_channel_layout_string( in_layout_string, sizeof( in_layout_string),  in_ch_count,  in_ch_layout);
-        av_get_channel_layout_string(out_layout_string, sizeof(out_layout_string), out_ch_count, out_ch_layout);
-        fprintf(stderr, "TEST: %s->%s, rate:%5d->%5d, fmt:%s->%s\n",
-                in_layout_string, out_layout_string,
-                in_sample_rate, out_sample_rate,
-                av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));
-        forw_ctx  = swr_alloc_set_opts(forw_ctx, out_ch_layout, out_sample_fmt,  out_sample_rate,
-                                                    in_ch_layout,  in_sample_fmt,  in_sample_rate,
-                                        0, 0);
-        backw_ctx = swr_alloc_set_opts(backw_ctx, in_ch_layout,  in_sample_fmt,             in_sample_rate,
-                                                    out_ch_layout, out_sample_fmt, out_sample_rate,
-                                        0, 0);
-        if(!forw_ctx) {
-            fprintf(stderr, "Failed to init forw_cts\n");
-            return 1;
-        }
-        if(!backw_ctx) {
-            fprintf(stderr, "Failed to init backw_ctx\n");
-            return 1;
-        }
-        if (uint_rand(rand_seed) % 3 == 0)
-            av_opt_set_int(forw_ctx, "ich", 0, 0);
-        if (uint_rand(rand_seed) % 3 == 0)
-            av_opt_set_int(forw_ctx, "och", 0, 0);
-
-        if(swr_init( forw_ctx) < 0)
-            fprintf(stderr, "swr_init(->) failed\n");
-        if(swr_init(backw_ctx) < 0)
-            fprintf(stderr, "swr_init(<-) failed\n");
-                //FIXME test planar
-        setup_array(ain , array_in ,  in_sample_fmt,   SAMPLES);
-        setup_array(amid, array_mid, out_sample_fmt, 3*SAMPLES);
-        setup_array(aout, array_out,  in_sample_fmt           ,   SAMPLES);
-#if 0
-        for(ch=0; ch<in_ch_count; ch++){
-            for(i=0; i<SAMPLES; i++)
-                set(ain, ch, i, in_ch_count, in_sample_fmt, sin(i*i*3/SAMPLES));
-        }
-#else
-        audiogen(ain, in_sample_fmt, in_ch_count, SAMPLES/6+1, SAMPLES);
-#endif
-        mode = uint_rand(rand_seed) % 3;
-        if(mode==0 /*|| out_sample_rate == in_sample_rate*/) {
-            mid_count= swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain, SAMPLES);
-        } else if(mode==1){
-            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain, SAMPLES);
-            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
-        } else {
-            int tmp_count;
-            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain,       1);
-            av_assert0(mid_count==0);
-            shift(ain,  1, in_ch_count, in_sample_fmt);
-            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
-            shift(amid,  mid_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
-            mid_count+=swr_convert(forw_ctx, amid,         2, (const uint8_t **)ain,       2);
-            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
-            shift(ain,  2, in_ch_count, in_sample_fmt);
-            mid_count+=swr_convert(forw_ctx, amid,         1, (const uint8_t **)ain, SAMPLES-3);
-            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
-            shift(ain, -3, in_ch_count, in_sample_fmt);
-            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
-            shift(amid,  -tmp_count, out_ch_count, out_sample_fmt);
-        }
-        out_count= swr_convert(backw_ctx,aout, SAMPLES, (const uint8_t **)amid, mid_count);
-
-        for(ch=0; ch<in_ch_count; ch++){
-            double sse, maxdiff=0;
-            double sum_a= 0;
-            double sum_b= 0;
-            double sum_aa= 0;
-            double sum_bb= 0;
-            double sum_ab= 0;
-            for(i=0; i<out_count; i++){
-                double a= get(ain , ch, i, in_ch_count, in_sample_fmt);
-                double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
-                sum_a += a;
-                sum_b += b;
-                sum_aa+= a*a;
-                sum_bb+= b*b;
-                sum_ab+= a*b;
-                maxdiff= FFMAX(maxdiff, fabs(a-b));
-            }
-            sse= sum_aa + sum_bb - 2*sum_ab;
-            if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error
-
-            fprintf(stderr, "[e:%f c:%f max:%f] len:%5d\n", out_count ? sqrt(sse/out_count) : 0, sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, out_count);
-        }
-
-        flush_i++;
-        flush_i%=21;
-        flush_count = swr_convert(backw_ctx,aout, flush_i, 0, 0);
-        shift(aout,  flush_i, in_ch_count, in_sample_fmt);
-        flush_count+= swr_convert(backw_ctx,aout, SAMPLES-flush_i, 0, 0);
-        shift(aout, -flush_i, in_ch_count, in_sample_fmt);
-        if(flush_count){
-            for(ch=0; ch<in_ch_count; ch++){
-                double sse, maxdiff=0;
-                double sum_a= 0;
-                double sum_b= 0;
-                double sum_aa= 0;
-                double sum_bb= 0;
-                double sum_ab= 0;
-                for(i=0; i<flush_count; i++){
-                    double a= get(ain , ch, i+out_count, in_ch_count, in_sample_fmt);
-                    double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
-                    sum_a += a;
-                    sum_b += b;
-                    sum_aa+= a*a;
-                    sum_bb+= b*b;
-                    sum_ab+= a*b;
-                    maxdiff= FFMAX(maxdiff, fabs(a-b));
-                }
-                sse= sum_aa + sum_bb - 2*sum_ab;
-                if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error
-
-                fprintf(stderr, "[e:%f c:%f max:%f] len:%5d F:%3d\n", sqrt(sse/flush_count), sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, flush_count, flush_i);
-            }
-        }
-
-
-        fprintf(stderr, "\n");
-    }
-
-    return 0;
-}
diff --git a/libswresample/swresample.c b/libswresample/swresample.c
index 8e23899..351623b 100644
--- a/libswresample/swresample.c
+++ b/libswresample/swresample.c
@@ -213,10 +213,10 @@ av_cold int swr_init(struct SwrContext *s){
                  s->rematrix_custom;
 
     if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){
-        if(   av_get_planar_sample_fmt(s-> in_sample_fmt) <= AV_SAMPLE_FMT_S16P
-           && av_get_planar_sample_fmt(s->out_sample_fmt) <= AV_SAMPLE_FMT_S16P){
+        if(   av_get_bytes_per_sample(s-> in_sample_fmt) <= 2
+           && av_get_bytes_per_sample(s->out_sample_fmt) <= 2){
             s->int_sample_fmt= AV_SAMPLE_FMT_S16P;
-        }else if(   av_get_planar_sample_fmt(s-> in_sample_fmt) <= AV_SAMPLE_FMT_S16P
+        }else if(   av_get_bytes_per_sample(s-> in_sample_fmt) <= 2
            && !s->rematrix
            && s->out_sample_rate==s->in_sample_rate
            && !(s->flags & SWR_FLAG_RESAMPLE)){
@@ -226,7 +226,7 @@ av_cold int swr_init(struct SwrContext *s){
                  && !s->rematrix
                  && s->engine != SWR_ENGINE_SOXR){
             s->int_sample_fmt= AV_SAMPLE_FMT_S32P;
-        }else if(av_get_planar_sample_fmt(s->in_sample_fmt) <= AV_SAMPLE_FMT_FLTP){
+        }else if(av_get_bytes_per_sample(s->in_sample_fmt) <= 4){
             s->int_sample_fmt= AV_SAMPLE_FMT_FLTP;
         }else{
             s->int_sample_fmt= AV_SAMPLE_FMT_DBLP;
@@ -262,7 +262,7 @@ av_cold int swr_init(struct SwrContext *s){
     }
 
     if (s->out_sample_rate!=s->in_sample_rate || (s->flags & SWR_FLAG_RESAMPLE)){
-        s->resample = s->resampler->init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type, s->kaiser_beta, s->precision, s->cheby);
+        s->resample = s->resampler->init(s->resample, s->out_sample_rate, s->in_sample_rate, s->filter_size, s->phase_shift, s->linear_interp, s->cutoff, s->int_sample_fmt, s->filter_type, s->kaiser_beta, s->precision, s->cheby, s->exact_rational);
         if (!s->resample) {
             av_log(s, AV_LOG_ERROR, "Failed to initialize resampler\n");
             return AVERROR(ENOMEM);
diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h
index 5d61de4..3828b72 100644
--- a/libswresample/swresample_internal.h
+++ b/libswresample/swresample_internal.h
@@ -69,7 +69,7 @@ struct DitherContext {
 };
 
 typedef struct ResampleContext * (* resample_init_func)(struct ResampleContext *c, int out_rate, int in_rate, int filter_size, int phase_shift, int linear,
-                                    double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta, double precision, int cheby);
+                                    double cutoff, enum AVSampleFormat format, enum SwrFilterType filter_type, double kaiser_beta, double precision, int cheby, int exact_rational);
 typedef void    (* resample_free_func)(struct ResampleContext **c);
 typedef int     (* multiple_resample_func)(struct ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed);
 typedef int     (* resample_flush_func)(struct SwrContext *c);
@@ -126,6 +126,7 @@ struct SwrContext {
     int filter_size;                                /**< length of each FIR filter in the resampling filterbank relative to the cutoff frequency */
     int phase_shift;                                /**< log2 of the number of entries in the resampling polyphase filterbank */
     int linear_interp;                              /**< if 1 then the resampling FIR filter will be linearly interpolated */
+    int exact_rational;                             /**< if 1 then enable non power of 2 phase_count */
     double cutoff;                                  /**< resampling cutoff frequency (swr: 6dB point; soxr: 0dB point). 1.0 corresponds to half the output sample rate */
     int filter_type;                                /**< swr resampling filter type */
     double kaiser_beta;                                /**< swr beta value for Kaiser window (only applicable if filter_type == AV_FILTER_TYPE_KAISER) */
diff --git a/libswresample/tests/swresample.c b/libswresample/tests/swresample.c
new file mode 100644
index 0000000..5389658
--- /dev/null
+++ b/libswresample/tests/swresample.c
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2011-2012 Michael Niedermayer (michaelni at gmx.at)
+ * Copyright (c) 2002 Fabrice Bellard
+ *
+ * This file is part of libswresample
+ *
+ * libswresample 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.
+ *
+ * libswresample 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 libswresample; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/common.h"
+#include "libavutil/opt.h"
+
+#include "libswresample/swresample.h"
+
+#undef time
+#include <time.h>
+#undef fprintf
+
+#define SAMPLES 1000
+
+#define SWR_CH_MAX 32
+
+#define ASSERT_LEVEL 2
+
+static double get(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f){
+    const uint8_t *p;
+    if(av_sample_fmt_is_planar(f)){
+        f= av_get_alt_sample_fmt(f, 0);
+        p= a[ch];
+    }else{
+        p= a[0];
+        index= ch + index*ch_count;
+    }
+
+    switch(f){
+    case AV_SAMPLE_FMT_U8 : return ((const uint8_t*)p)[index]/127.0-1.0;
+    case AV_SAMPLE_FMT_S16: return ((const int16_t*)p)[index]/32767.0;
+    case AV_SAMPLE_FMT_S32: return ((const int32_t*)p)[index]/2147483647.0;
+    case AV_SAMPLE_FMT_FLT: return ((const float  *)p)[index];
+    case AV_SAMPLE_FMT_DBL: return ((const double *)p)[index];
+    default: av_assert0(0);
+    }
+}
+
+static void  set(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f, double v){
+    uint8_t *p;
+    if(av_sample_fmt_is_planar(f)){
+        f= av_get_alt_sample_fmt(f, 0);
+        p= a[ch];
+    }else{
+        p= a[0];
+        index= ch + index*ch_count;
+    }
+    switch(f){
+    case AV_SAMPLE_FMT_U8 : ((uint8_t*)p)[index]= av_clip_uint8 (lrint((v+1.0)*127));     break;
+    case AV_SAMPLE_FMT_S16: ((int16_t*)p)[index]= av_clip_int16 (lrint(v*32767));         break;
+    case AV_SAMPLE_FMT_S32: ((int32_t*)p)[index]= av_clipl_int32(llrint(v*2147483647));   break;
+    case AV_SAMPLE_FMT_FLT: ((float  *)p)[index]= v;                                      break;
+    case AV_SAMPLE_FMT_DBL: ((double *)p)[index]= v;                                      break;
+    default: av_assert2(0);
+    }
+}
+
+static void shift(uint8_t *a[], int index, int ch_count, enum AVSampleFormat f){
+    int ch;
+
+    if(av_sample_fmt_is_planar(f)){
+        f= av_get_alt_sample_fmt(f, 0);
+        for(ch= 0; ch<ch_count; ch++)
+            a[ch] += index*av_get_bytes_per_sample(f);
+    }else{
+        a[0] += index*ch_count*av_get_bytes_per_sample(f);
+    }
+}
+
+static const enum AVSampleFormat formats[] = {
+    AV_SAMPLE_FMT_S16,
+    AV_SAMPLE_FMT_FLTP,
+    AV_SAMPLE_FMT_S16P,
+    AV_SAMPLE_FMT_FLT,
+    AV_SAMPLE_FMT_S32P,
+    AV_SAMPLE_FMT_S32,
+    AV_SAMPLE_FMT_U8P,
+    AV_SAMPLE_FMT_U8,
+    AV_SAMPLE_FMT_DBLP,
+    AV_SAMPLE_FMT_DBL,
+};
+
+static const int rates[] = {
+    8000,
+    11025,
+    16000,
+    22050,
+    32000,
+    48000,
+};
+
+static const uint64_t layouts[]={
+    AV_CH_LAYOUT_MONO                    ,
+    AV_CH_LAYOUT_STEREO                  ,
+    AV_CH_LAYOUT_2_1                     ,
+    AV_CH_LAYOUT_SURROUND                ,
+    AV_CH_LAYOUT_4POINT0                 ,
+    AV_CH_LAYOUT_2_2                     ,
+    AV_CH_LAYOUT_QUAD                    ,
+    AV_CH_LAYOUT_5POINT0                 ,
+    AV_CH_LAYOUT_5POINT1                 ,
+    AV_CH_LAYOUT_5POINT0_BACK            ,
+    AV_CH_LAYOUT_5POINT1_BACK            ,
+    AV_CH_LAYOUT_7POINT0                 ,
+    AV_CH_LAYOUT_7POINT1                 ,
+    AV_CH_LAYOUT_7POINT1_WIDE            ,
+};
+
+static void setup_array(uint8_t *out[SWR_CH_MAX], uint8_t *in, enum AVSampleFormat format, int samples){
+    if(av_sample_fmt_is_planar(format)){
+        int i;
+        int plane_size= av_get_bytes_per_sample(format&0xFF)*samples;
+        format&=0xFF;
+        for(i=0; i<SWR_CH_MAX; i++){
+            out[i]= in + i*plane_size;
+        }
+    }else{
+        out[0]= in;
+    }
+}
+
+static int cmp(const void *a, const void *b){
+    return *(const int *)a - *(const int *)b;
+}
+
+static void audiogen(void *data, enum AVSampleFormat sample_fmt,
+                     int channels, int sample_rate, int nb_samples)
+{
+    int i, ch, k;
+    double v, f, a, ampa;
+    double tabf1[SWR_CH_MAX];
+    double tabf2[SWR_CH_MAX];
+    double taba[SWR_CH_MAX];
+    unsigned static rnd;
+
+#define PUT_SAMPLE set(data, ch, k, channels, sample_fmt, v);
+#define uint_rand(x) ((x) = (x) * 1664525 + 1013904223)
+#define dbl_rand(x) (uint_rand(x)*2.0 / (double)UINT_MAX - 1)
+    k = 0;
+
+    /* 1 second of single freq sinus at 1000 Hz */
+    a = 0;
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
+        v = sin(a) * 0.30;
+        for (ch = 0; ch < channels; ch++)
+            PUT_SAMPLE
+        a += M_PI * 1000.0 * 2.0 / sample_rate;
+    }
+
+    /* 1 second of varying frequency between 100 and 10000 Hz */
+    a = 0;
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
+        v = sin(a) * 0.30;
+        for (ch = 0; ch < channels; ch++)
+            PUT_SAMPLE
+        f  = 100.0 + (((10000.0 - 100.0) * i) / sample_rate);
+        a += M_PI * f * 2.0 / sample_rate;
+    }
+
+    /* 0.5 second of low amplitude white noise */
+    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
+        v = dbl_rand(rnd) * 0.30;
+        for (ch = 0; ch < channels; ch++)
+            PUT_SAMPLE
+    }
+
+    /* 0.5 second of high amplitude white noise */
+    for (i = 0; i < sample_rate / 2 && k < nb_samples; i++, k++) {
+        v = dbl_rand(rnd);
+        for (ch = 0; ch < channels; ch++)
+            PUT_SAMPLE
+    }
+
+    /* 1 second of unrelated ramps for each channel */
+    for (ch = 0; ch < channels; ch++) {
+        taba[ch]  = 0;
+        tabf1[ch] = 100 + uint_rand(rnd) % 5000;
+        tabf2[ch] = 100 + uint_rand(rnd) % 5000;
+    }
+    for (i = 0; i < 1 * sample_rate && k < nb_samples; i++, k++) {
+        for (ch = 0; ch < channels; ch++) {
+            v = sin(taba[ch]) * 0.30;
+            PUT_SAMPLE
+            f = tabf1[ch] + (((tabf2[ch] - tabf1[ch]) * i) / sample_rate);
+            taba[ch] += M_PI * f * 2.0 / sample_rate;
+        }
+    }
+
+    /* 2 seconds of 500 Hz with varying volume */
+    a    = 0;
+    ampa = 0;
+    for (i = 0; i < 2 * sample_rate && k < nb_samples; i++, k++) {
+        for (ch = 0; ch < channels; ch++) {
+            double amp = (1.0 + sin(ampa)) * 0.15;
+            if (ch & 1)
+                amp = 0.30 - amp;
+            v = sin(a) * amp;
+            PUT_SAMPLE
+            a    += M_PI * 500.0 * 2.0 / sample_rate;
+            ampa += M_PI *  2.0 / sample_rate;
+        }
+    }
+}
+
+int main(int argc, char **argv){
+    int in_sample_rate, out_sample_rate, ch ,i, flush_count;
+    uint64_t in_ch_layout, out_ch_layout;
+    enum AVSampleFormat in_sample_fmt, out_sample_fmt;
+    uint8_t array_in[SAMPLES*8*8];
+    uint8_t array_mid[SAMPLES*8*8*3];
+    uint8_t array_out[SAMPLES*8*8+100];
+    uint8_t *ain[SWR_CH_MAX];
+    uint8_t *aout[SWR_CH_MAX];
+    uint8_t *amid[SWR_CH_MAX];
+    int flush_i=0;
+    int mode;
+    int num_tests = 10000;
+    uint32_t seed = 0;
+    uint32_t rand_seed = 0;
+    int remaining_tests[FF_ARRAY_ELEMS(rates) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats) * FF_ARRAY_ELEMS(layouts) * FF_ARRAY_ELEMS(formats)];
+    int max_tests = FF_ARRAY_ELEMS(remaining_tests);
+    int test;
+    int specific_test= -1;
+
+    struct SwrContext * forw_ctx= NULL;
+    struct SwrContext *backw_ctx= NULL;
+
+    if (argc > 1) {
+        if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
+            av_log(NULL, AV_LOG_INFO, "Usage: swresample-test [<num_tests>[ <test>]]  \n"
+                   "num_tests           Default is %d\n", num_tests);
+            return 0;
+        }
+        num_tests = strtol(argv[1], NULL, 0);
+        if(num_tests < 0) {
+            num_tests = -num_tests;
+            rand_seed = time(0);
+        }
+        if(num_tests<= 0 || num_tests>max_tests)
+            num_tests = max_tests;
+        if(argc > 2) {
+            specific_test = strtol(argv[1], NULL, 0);
+        }
+    }
+
+    for(i=0; i<max_tests; i++)
+        remaining_tests[i] = i;
+
+    for(test=0; test<num_tests; test++){
+        unsigned r;
+        uint_rand(seed);
+        r = (seed * (uint64_t)(max_tests - test)) >>32;
+        FFSWAP(int, remaining_tests[r], remaining_tests[max_tests - test - 1]);
+    }
+    qsort(remaining_tests + max_tests - num_tests, num_tests, sizeof(remaining_tests[0]), cmp);
+    in_sample_rate=16000;
+    for(test=0; test<num_tests; test++){
+        char  in_layout_string[256];
+        char out_layout_string[256];
+        unsigned vector= remaining_tests[max_tests - test - 1];
+        int in_ch_count;
+        int out_count, mid_count, out_ch_count;
+
+        in_ch_layout    = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);
+        out_ch_layout   = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts);
+        in_sample_fmt   = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);
+        out_sample_fmt  = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats);
+        out_sample_rate = rates  [vector % FF_ARRAY_ELEMS(rates  )]; vector /= FF_ARRAY_ELEMS(rates);
+        av_assert0(!vector);
+
+        if(specific_test == 0){
+            if(out_sample_rate != in_sample_rate || in_ch_layout != out_ch_layout)
+                continue;
+        }
+
+        in_ch_count= av_get_channel_layout_nb_channels(in_ch_layout);
+        out_ch_count= av_get_channel_layout_nb_channels(out_ch_layout);
+        av_get_channel_layout_string( in_layout_string, sizeof( in_layout_string),  in_ch_count,  in_ch_layout);
+        av_get_channel_layout_string(out_layout_string, sizeof(out_layout_string), out_ch_count, out_ch_layout);
+        fprintf(stderr, "TEST: %s->%s, rate:%5d->%5d, fmt:%s->%s\n",
+                in_layout_string, out_layout_string,
+                in_sample_rate, out_sample_rate,
+                av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt));
+        forw_ctx  = swr_alloc_set_opts(forw_ctx, out_ch_layout, out_sample_fmt,  out_sample_rate,
+                                                    in_ch_layout,  in_sample_fmt,  in_sample_rate,
+                                        0, 0);
+        backw_ctx = swr_alloc_set_opts(backw_ctx, in_ch_layout,  in_sample_fmt,             in_sample_rate,
+                                                    out_ch_layout, out_sample_fmt, out_sample_rate,
+                                        0, 0);
+        if(!forw_ctx) {
+            fprintf(stderr, "Failed to init forw_cts\n");
+            return 1;
+        }
+        if(!backw_ctx) {
+            fprintf(stderr, "Failed to init backw_ctx\n");
+            return 1;
+        }
+        if (uint_rand(rand_seed) % 3 == 0)
+            av_opt_set_int(forw_ctx, "ich", 0, 0);
+        if (uint_rand(rand_seed) % 3 == 0)
+            av_opt_set_int(forw_ctx, "och", 0, 0);
+
+        if(swr_init( forw_ctx) < 0)
+            fprintf(stderr, "swr_init(->) failed\n");
+        if(swr_init(backw_ctx) < 0)
+            fprintf(stderr, "swr_init(<-) failed\n");
+                //FIXME test planar
+        setup_array(ain , array_in ,  in_sample_fmt,   SAMPLES);
+        setup_array(amid, array_mid, out_sample_fmt, 3*SAMPLES);
+        setup_array(aout, array_out,  in_sample_fmt           ,   SAMPLES);
+#if 0
+        for(ch=0; ch<in_ch_count; ch++){
+            for(i=0; i<SAMPLES; i++)
+                set(ain, ch, i, in_ch_count, in_sample_fmt, sin(i*i*3/SAMPLES));
+        }
+#else
+        audiogen(ain, in_sample_fmt, in_ch_count, SAMPLES/6+1, SAMPLES);
+#endif
+        mode = uint_rand(rand_seed) % 3;
+        if(mode==0 /*|| out_sample_rate == in_sample_rate*/) {
+            mid_count= swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain, SAMPLES);
+        } else if(mode==1){
+            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain, SAMPLES);
+            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
+        } else {
+            int tmp_count;
+            mid_count= swr_convert(forw_ctx, amid,         0, (const uint8_t **)ain,       1);
+            av_assert0(mid_count==0);
+            shift(ain,  1, in_ch_count, in_sample_fmt);
+            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
+            shift(amid,  mid_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
+            mid_count+=swr_convert(forw_ctx, amid,         2, (const uint8_t **)ain,       2);
+            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
+            shift(ain,  2, in_ch_count, in_sample_fmt);
+            mid_count+=swr_convert(forw_ctx, amid,         1, (const uint8_t **)ain, SAMPLES-3);
+            shift(amid,  mid_count-tmp_count, out_ch_count, out_sample_fmt); tmp_count = mid_count;
+            shift(ain, -3, in_ch_count, in_sample_fmt);
+            mid_count+=swr_convert(forw_ctx, amid, 3*SAMPLES, (const uint8_t **)ain,       0);
+            shift(amid,  -tmp_count, out_ch_count, out_sample_fmt);
+        }
+        out_count= swr_convert(backw_ctx,aout, SAMPLES, (const uint8_t **)amid, mid_count);
+
+        for(ch=0; ch<in_ch_count; ch++){
+            double sse, maxdiff=0;
+            double sum_a= 0;
+            double sum_b= 0;
+            double sum_aa= 0;
+            double sum_bb= 0;
+            double sum_ab= 0;
+            for(i=0; i<out_count; i++){
+                double a= get(ain , ch, i, in_ch_count, in_sample_fmt);
+                double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
+                sum_a += a;
+                sum_b += b;
+                sum_aa+= a*a;
+                sum_bb+= b*b;
+                sum_ab+= a*b;
+                maxdiff= FFMAX(maxdiff, fabs(a-b));
+            }
+            sse= sum_aa + sum_bb - 2*sum_ab;
+            if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error
+
+            fprintf(stderr, "[e:%f c:%f max:%f] len:%5d\n", out_count ? sqrt(sse/out_count) : 0, sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, out_count);
+        }
+
+        flush_i++;
+        flush_i%=21;
+        flush_count = swr_convert(backw_ctx,aout, flush_i, 0, 0);
+        shift(aout,  flush_i, in_ch_count, in_sample_fmt);
+        flush_count+= swr_convert(backw_ctx,aout, SAMPLES-flush_i, 0, 0);
+        shift(aout, -flush_i, in_ch_count, in_sample_fmt);
+        if(flush_count){
+            for(ch=0; ch<in_ch_count; ch++){
+                double sse, maxdiff=0;
+                double sum_a= 0;
+                double sum_b= 0;
+                double sum_aa= 0;
+                double sum_bb= 0;
+                double sum_ab= 0;
+                for(i=0; i<flush_count; i++){
+                    double a= get(ain , ch, i+out_count, in_ch_count, in_sample_fmt);
+                    double b= get(aout, ch, i, in_ch_count, in_sample_fmt);
+                    sum_a += a;
+                    sum_b += b;
+                    sum_aa+= a*a;
+                    sum_bb+= b*b;
+                    sum_ab+= a*b;
+                    maxdiff= FFMAX(maxdiff, fabs(a-b));
+                }
+                sse= sum_aa + sum_bb - 2*sum_ab;
+                if(sse < 0 && sse > -0.00001) sse=0; //fix rounding error
+
+                fprintf(stderr, "[e:%f c:%f max:%f] len:%5d F:%3d\n", sqrt(sse/flush_count), sum_ab/(sqrt(sum_aa*sum_bb)), maxdiff, flush_count, flush_i);
+            }
+        }
+
+
+        fprintf(stderr, "\n");
+    }
+
+    return 0;
+}
diff --git a/libswresample/version.h b/libswresample/version.h
index 830f00e..b8e32c0 100644
--- a/libswresample/version.h
+++ b/libswresample/version.h
@@ -29,8 +29,8 @@
 #include "libavutil/avutil.h"
 
 #define LIBSWRESAMPLE_VERSION_MAJOR   2
-#define LIBSWRESAMPLE_VERSION_MINOR   0
-#define LIBSWRESAMPLE_VERSION_MICRO 101
+#define LIBSWRESAMPLE_VERSION_MINOR   1
+#define LIBSWRESAMPLE_VERSION_MICRO 100
 
 #define LIBSWRESAMPLE_VERSION_INT  AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \
                                                   LIBSWRESAMPLE_VERSION_MINOR, \
diff --git a/libswresample/x86/resample.asm b/libswresample/x86/resample.asm
index 4989aa6..4163df1 100644
--- a/libswresample/x86/resample.asm
+++ b/libswresample/x86/resample.asm
@@ -41,8 +41,7 @@ struc ResampleContext
     .frac:                  resd 1
     .src_incr:              resd 1
     .compensation_distance: resd 1
-    .phase_shift:           resd 1
-    .phase_mask:            resd 1
+    .phase_count:           resd 1
 
     ; there's a few more here but we only care about the first few
 endstruc
@@ -55,11 +54,12 @@ pd_0x4000: dd 0x4000
 
 SECTION .text
 
+; FIXME remove unneeded variables (index_incr, phase_mask)
 %macro RESAMPLE_FNS 3-5 ; format [float or int16], bps, log2_bps, float op suffix [s or d], 1.0 constant
 ; int resample_common_$format(ResampleContext *ctx, $format *dst,
 ;                             const $format *src, int size, int update_ctx)
 %if ARCH_X86_64 ; unix64 and win64
-cglobal resample_common_%1, 0, 15, 2, ctx, dst, src, phase_shift, index, frac, \
+cglobal resample_common_%1, 0, 15, 2, ctx, dst, src, phase_count, index, frac, \
                                       dst_incr_mod, size, min_filter_count_x4, \
                                       min_filter_len_x4, dst_incr_div, src_incr, \
                                       phase_mask, dst_end, filter_bank
@@ -76,7 +76,6 @@ cglobal resample_common_%1, 0, 15, 2, ctx, dst, src, phase_shift, index, frac, \
     ; load as many variables in registers as possible; for the rest, store
     ; on stack so that we have 'ctx' available as one extra register
     mov                        sized, r3d
-    mov                  phase_maskd, [ctxq+ResampleContext.phase_mask]
 %if UNIX64
     mov        update_context_stackd, r4d
 %endif
@@ -92,17 +91,17 @@ cglobal resample_common_%1, 0, 15, 2, ctx, dst, src, phase_shift, index, frac, \
     lea                     dst_endq, [dstq+sizeq*%2]
 
 %if UNIX64
-    mov                          ecx, [ctxq+ResampleContext.phase_shift]
+    mov                          ecx, [ctxq+ResampleContext.phase_count]
     mov                          edi, [ctxq+ResampleContext.filter_alloc]
 
-    DEFINE_ARGS filter_alloc, dst, src, phase_shift, index, frac, dst_incr_mod, \
+    DEFINE_ARGS filter_alloc, dst, src, phase_count, index, frac, dst_incr_mod, \
                 filter, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \
                 src_incr, phase_mask, dst_end, filter_bank
 %elif WIN64
     mov                          R9d, [ctxq+ResampleContext.filter_alloc]
-    mov                          ecx, [ctxq+ResampleContext.phase_shift]
+    mov                          ecx, [ctxq+ResampleContext.phase_count]
 
-    DEFINE_ARGS phase_shift, dst, src, filter_alloc, index, frac, dst_incr_mod, \
+    DEFINE_ARGS phase_count, dst, src, filter_alloc, index, frac, dst_incr_mod, \
                 filter, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \
                 src_incr, phase_mask, dst_end, filter_bank
 %endif
@@ -112,7 +111,7 @@ cglobal resample_common_%1, 0, 15, 2, ctx, dst, src, phase_shift, index, frac, \
     sub                         srcq, min_filter_len_x4q
     mov                   src_stackq, srcq
 %else ; x86-32
-cglobal resample_common_%1, 1, 7, 2, ctx, phase_shift, dst, frac, \
+cglobal resample_common_%1, 1, 7, 2, ctx, phase_count, dst, frac, \
                                      index, min_filter_length_x4, filter_bank
 
     ; push temp variables to stack
@@ -127,7 +126,7 @@ cglobal resample_common_%1, 1, 7, 2, ctx, phase_shift, dst, frac, \
     PUSH                              dword [ctxq+ResampleContext.dst_incr_mod]
     PUSH                              dword [ctxq+ResampleContext.filter_alloc]
     PUSH                              r3
-    PUSH                              dword [ctxq+ResampleContext.phase_mask]
+    PUSH                              dword [ctxq+ResampleContext.phase_count]  ; unneeded replacement for phase_mask
     PUSH                              dword [ctxq+ResampleContext.src_incr]
     mov        min_filter_length_x4d, [ctxq+ResampleContext.filter_length]
     mov                       indexd, [ctxq+ResampleContext.index]
@@ -139,9 +138,9 @@ cglobal resample_common_%1, 1, 7, 2, ctx, phase_shift, dst, frac, \
     sub                 filter_bankq, min_filter_length_x4q
     PUSH                              min_filter_length_x4q
     PUSH                              filter_bankq
-    mov                 phase_shiftd, [ctxq+ResampleContext.phase_shift]
+    mov                 phase_countd, [ctxq+ResampleContext.phase_count]
 
-    DEFINE_ARGS src, phase_shift, dst, frac, index, min_filter_count_x4, filter
+    DEFINE_ARGS src, phase_count, dst, frac, index, min_filter_count_x4, filter
 
 %define filter_bankq          dword [rsp+0x0]
 %define min_filter_length_x4q dword [rsp+0x4]
@@ -222,28 +221,32 @@ cglobal resample_common_%1, 1, 7, 2, ctx, phase_shift, dst, frac, \
     inc                       indexd
 
 %if UNIX64
-    DEFINE_ARGS filter_alloc, dst, src, phase_shift, index, frac, dst_incr_mod, \
+    DEFINE_ARGS filter_alloc, dst, src, phase_count, index, frac, dst_incr_mod, \
                 index_incr, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \
                 src_incr, phase_mask, dst_end, filter_bank
 %elif WIN64
-    DEFINE_ARGS phase_shift, dst, src, filter_alloc, index, frac, dst_incr_mod, \
+    DEFINE_ARGS phase_count, dst, src, filter_alloc, index, frac, dst_incr_mod, \
                 index_incr, min_filter_count_x4, min_filter_len_x4, dst_incr_div, \
                 src_incr, phase_mask, dst_end, filter_bank
 %else ; x86-32
-    DEFINE_ARGS src, phase_shift, dst, frac, index, index_incr
+    DEFINE_ARGS src, phase_count, dst, frac, index, index_incr
 %endif
 
 .skip:
-    mov                  index_incrd, indexd
     add                         dstq, %2
-    and                       indexd, phase_maskd
-    sar                  index_incrd, phase_shiftb
-    lea                         srcq, [srcq+index_incrq*%2]
+    cmp                       indexd, phase_countd
+    jb .index_skip
+.index_while:
+    sub                       indexd, phase_countd
+    lea                         srcq, [srcq+%2]
+    cmp                       indexd, phase_countd
+    jnb .index_while
+.index_skip:
     cmp                         dstq, dst_endq
     jne .loop
 
 %if ARCH_X86_64
-    DEFINE_ARGS ctx, dst, src, phase_shift, index, frac
+    DEFINE_ARGS ctx, dst, src, phase_count, index, frac
 %else ; x86-32
     DEFINE_ARGS src, ctx, update_context, frac, index
 %endif
@@ -270,14 +273,14 @@ cglobal resample_common_%1, 1, 7, 2, ctx, phase_shift, dst, frac, \
 ;                             const float *src, int size, int update_ctx)
 %if ARCH_X86_64 ; unix64 and win64
 %if UNIX64
-cglobal resample_linear_%1, 0, 15, 5, ctx, dst, phase_mask, phase_shift, index, frac, \
+cglobal resample_linear_%1, 0, 15, 5, ctx, dst, phase_mask, phase_count, index, frac, \
                                       size, dst_incr_mod, min_filter_count_x4, \
                                       min_filter_len_x4, dst_incr_div, src_incr, \
                                       src, dst_end, filter_bank
 
     mov                         srcq, r2mp
 %else ; win64
-cglobal resample_linear_%1, 0, 15, 5, ctx, phase_mask, src, phase_shift, index, frac, \
+cglobal resample_linear_%1, 0, 15, 5, ctx, phase_mask, src, phase_count, index, frac, \
                                       size, dst_incr_mod, min_filter_count_x4, \
                                       min_filter_len_x4, dst_incr_div, src_incr, \
                                       dst, dst_end, filter_bank
@@ -298,7 +301,6 @@ cglobal resample_linear_%1, 0, 15, 5, ctx, phase_mask, src, phase_shift, index,
     ; load as many variables in registers as possible; for the rest, store
     ; on stack so that we have 'ctx' available as one extra register
     mov                        sized, r3d
-    mov                  phase_maskd, [ctxq+ResampleContext.phase_mask]
 %if UNIX64
     mov        update_context_stackd, r4d
 %endif
@@ -308,7 +310,6 @@ cglobal resample_linear_%1, 0, 15, 5, ctx, phase_mask, src, phase_shift, index,
     mov                 filter_bankq, [ctxq+ResampleContext.filter_bank]
     mov                    src_incrd, [ctxq+ResampleContext.src_incr]
     mov                   ctx_stackq, ctxq
-    mov            phase_mask_stackd, phase_maskd
     mov           min_filter_len_x4d, [ctxq+ResampleContext.filter_length]
 %ifidn %1, int16
     movd                          m4, [pd_0x4000]
@@ -322,17 +323,17 @@ cglobal resample_linear_%1, 0, 15, 5, ctx, phase_mask, src, phase_shift, index,
     lea                     dst_endq, [dstq+sizeq*%2]
 
 %if UNIX64
-    mov                          ecx, [ctxq+ResampleContext.phase_shift]
+    mov                          ecx, [ctxq+ResampleContext.phase_count]
     mov                          edi, [ctxq+ResampleContext.filter_alloc]
 
-    DEFINE_ARGS filter_alloc, dst, filter2, phase_shift, index, frac, filter1, \
+    DEFINE_ARGS filter_alloc, dst, filter2, phase_count, index, frac, filter1, \
                 dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
                 dst_incr_div, src_incr, src, dst_end, filter_bank
 %elif WIN64
     mov                          R9d, [ctxq+ResampleContext.filter_alloc]
-    mov                          ecx, [ctxq+ResampleContext.phase_shift]
+    mov                          ecx, [ctxq+ResampleContext.phase_count]
 
-    DEFINE_ARGS phase_shift, filter2, src, filter_alloc, index, frac, filter1, \
+    DEFINE_ARGS phase_count, filter2, src, filter_alloc, index, frac, filter1, \
                 dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
                 dst_incr_div, src_incr, dst, dst_end, filter_bank
 %endif
@@ -361,7 +362,7 @@ cglobal resample_linear_%1, 1, 7, 5, ctx, min_filter_length_x4, filter2, \
     shl                           r3, %3
     PUSH                              r3
     mov                           r3, dword [ctxq+ResampleContext.src_incr]
-    PUSH                              dword [ctxq+ResampleContext.phase_mask]
+    PUSH                              dword [ctxq+ResampleContext.phase_count]  ; unneeded replacement of phase_mask
     PUSH                              r3d
 %ifidn %1, int16
     movd                          m4, [pd_0x4000]
@@ -380,11 +381,11 @@ cglobal resample_linear_%1, 1, 7, 5, ctx, min_filter_length_x4, filter2, \
     sub                 filter_bankq, min_filter_length_x4q
     PUSH                              min_filter_length_x4q
     PUSH                              filter_bankq
-    PUSH                              dword [ctxq+ResampleContext.phase_shift]
+    PUSH                              dword [ctxq+ResampleContext.phase_count]
 
     DEFINE_ARGS filter1, min_filter_count_x4, filter2, frac, index, dst, src
 
-%define phase_shift_stackd    dword [rsp+0x0]
+%define phase_count_stackd    dword [rsp+0x0]
 %define filter_bankq          dword [rsp+0x4]
 %define min_filter_length_x4q dword [rsp+0x8]
 %define src_incrd             dword [rsp+0xc]
@@ -519,35 +520,39 @@ cglobal resample_linear_%1, 1, 7, 5, ctx, min_filter_length_x4, filter2, \
     inc                       indexd
 
 %if UNIX64
-    DEFINE_ARGS filter_alloc, dst, filter2, phase_shift, index, frac, index_incr, \
+    DEFINE_ARGS filter_alloc, dst, filter2, phase_count, index, frac, index_incr, \
                 dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
                 dst_incr_div, src_incr, src, dst_end, filter_bank
 %elif WIN64
-    DEFINE_ARGS phase_shift, filter2, src, filter_alloc, index, frac, index_incr, \
+    DEFINE_ARGS phase_count, filter2, src, filter_alloc, index, frac, index_incr, \
                 dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
                 dst_incr_div, src_incr, dst, dst_end, filter_bank
 %else ; x86-32
-    DEFINE_ARGS filter1, phase_shift, index_incr, frac, index, dst, src
+    DEFINE_ARGS filter1, phase_count, index_incr, frac, index, dst, src
 %endif
 
 .skip:
 %if ARCH_X86_32
-    mov                 phase_shiftd, phase_shift_stackd
+    mov                 phase_countd, phase_count_stackd
 %endif
-    mov                  index_incrd, indexd
     add                         dstq, %2
-    and                       indexd, phase_mask_stackd
-    sar                  index_incrd, phase_shiftb
-    lea                         srcq, [srcq+index_incrq*%2]
+    cmp                       indexd, phase_countd
+    jb .index_skip
+.index_while:
+    sub                       indexd, phase_countd
+    lea                         srcq, [srcq+%2]
+    cmp                       indexd, phase_countd
+    jnb .index_while
+.index_skip:
     cmp                         dstq, dst_endq
     jne .loop
 
 %if UNIX64
-    DEFINE_ARGS ctx, dst, filter2, phase_shift, index, frac, index_incr, \
+    DEFINE_ARGS ctx, dst, filter2, phase_count, index, frac, index_incr, \
                 dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
                 dst_incr_div, src_incr, src, dst_end, filter_bank
 %elif WIN64
-    DEFINE_ARGS ctx, filter2, src, phase_shift, index, frac, index_incr, \
+    DEFINE_ARGS ctx, filter2, src, phase_count, index, frac, index_incr, \
                 dst_incr_mod, min_filter_count_x4, min_filter_len_x4, \
                 dst_incr_div, src_incr, dst, dst_end, filter_bank
 %else ; x86-32
diff --git a/libswscale/Makefile b/libswscale/Makefile
index a9f9e03..0272039 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -6,19 +6,19 @@ HEADERS = swscale.h                                                     \
           version.h                                                     \
 
 OBJS = alphablend.o                                     \
+       hscale.o                                         \
        hscale_fast_bilinear.o                           \
+       gamma.o                                          \
        input.o                                          \
        options.o                                        \
        output.o                                         \
        rgb2rgb.o                                        \
+       slice.o                                          \
        swscale.o                                        \
        swscale_unscaled.o                               \
        utils.o                                          \
        yuv2rgb.o                                        \
-       slice.o                                          \
-       hscale.o                                         \
        vscale.o                                         \
-       gamma.o                                          \
 
 OBJS-$(CONFIG_SHARED)        += log2_tab.o
 
diff --git a/libswscale/aarch64/Makefile b/libswscale/aarch64/Makefile
new file mode 100644
index 0000000..64a3fe2
--- /dev/null
+++ b/libswscale/aarch64/Makefile
@@ -0,0 +1,6 @@
+OBJS        += aarch64/swscale.o                \
+               aarch64/swscale_unscaled.o       \
+
+NEON-OBJS   += aarch64/hscale.o                 \
+               aarch64/output.o                 \
+               aarch64/yuv2rgb_neon.o           \
diff --git a/libswscale/aarch64/hscale.S b/libswscale/aarch64/hscale.S
new file mode 100644
index 0000000..cc78c19
--- /dev/null
+++ b/libswscale/aarch64/hscale.S
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Clément Bœsch <clement stupeflix.com>
+ *
+ * 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/aarch64/asm.S"
+
+function ff_hscale_8_to_15_neon, export=1
+        add                 x10, x4, w6, UXTW #1        // filter2 = filter + filterSize*2 (x2 because int16)
+1:      ldr                 w8, [x5], #4                // filterPos[0]
+        ldr                 w9, [x5], #4                // filterPos[1]
+        movi                v4.4S, #0                   // val sum part 1 (for dst[0])
+        movi                v5.4S, #0                   // val sum part 2 (for dst[1])
+        mov                 w7, w6                      // filterSize counter
+        mov                 x13, x3                     // srcp = src
+2:      add                 x11, x13, w8, UXTW          // srcp + filterPos[0]
+        add                 x12, x13, w9, UXTW          // srcp + filterPos[1]
+        ld1                 {v0.8B}, [x11]              // srcp[filterPos[0] + {0..7}]
+        ld1                 {v1.8B}, [x12]              // srcp[filterPos[1] + {0..7}]
+        ld1                 {v2.8H}, [x4],  #16         // load 8x16-bit filter values, part 1
+        ld1                 {v3.8H}, [x10], #16         // ditto at filter+filterSize for part 2
+        uxtl                v0.8H, v0.8B                // unpack part 1 to 16-bit
+        uxtl                v1.8H, v1.8B                // unpack part 2 to 16-bit
+        smull               v16.4S, v0.4H, v2.4H        // v16.i32{0..3} = part 1 of: srcp[filterPos[0] + {0..7}] * filter[{0..7}]
+        smull               v18.4S, v1.4H, v3.4H        // v18.i32{0..3} = part 1 of: srcp[filterPos[1] + {0..7}] * filter[{0..7}]
+        smull2              v17.4S, v0.8H, v2.8H        // v17.i32{0..3} = part 2 of: srcp[filterPos[0] + {0..7}] * filter[{0..7}]
+        smull2              v19.4S, v1.8H, v3.8H        // v19.i32{0..3} = part 2 of: srcp[filterPos[1] + {0..7}] * filter[{0..7}]
+        addp                v16.4S, v16.4S, v17.4S      // horizontal pair adding of the 8x32-bit multiplied values for part 1 into 4x32-bit
+        addp                v18.4S, v18.4S, v19.4S      // horizontal pair adding of the 8x32-bit multiplied values for part 2 into 4x32-bit
+        add                 v4.4S, v4.4S, v16.4S        // update val accumulator for part 1
+        add                 v5.4S, v5.4S, v18.4S        // update val accumulator for part 2
+        add                 x13, x13, #8                // srcp += 8
+        subs                w7, w7, #8                  // processed 8/filterSize
+        b.gt                2b                          // inner loop if filterSize not consumed completely
+        mov                 x4, x10                     // filter = filter2
+        add                 x10, x10, w6, UXTW #1       // filter2 += filterSize*2
+        addp                v4.4S, v4.4S, v5.4S         // horizontal pair adding of the 8x32-bit sums into 4x32-bit
+        addp                v4.4S, v4.4S, v4.4S         // horizontal pair adding of the 4x32-bit sums into 2x32-bit
+        sqshrn              v4.4H, v4.4S, #7            // shift and clip the 2x16-bit final values
+        st1                 {v4.S}[0], [x1], #4         // write to destination
+        subs                w2, w2, #2                  // dstW -= 2
+        b.gt                1b                          // loop until end of line
+        ret
+endfunc
diff --git a/libswscale/aarch64/output.S b/libswscale/aarch64/output.S
new file mode 100644
index 0000000..90d3b57
--- /dev/null
+++ b/libswscale/aarch64/output.S
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016 Clément Bœsch <clement stupeflix.com>
+ *
+ * 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/aarch64/asm.S"
+
+function ff_yuv2planeX_8_neon, export=1
+        ld1                 {v0.8B}, [x5]                   // load 8x8-bit dither
+        cbz                 w6, 1f                          // check if offsetting present
+        ext                 v0.8B, v0.8B, v0.8B, #3         // honor offsetting which can be 0 or 3 only
+1:      uxtl                v0.8H, v0.8B                    // extend dither to 16-bit
+        ushll               v1.4S, v0.4H, #12               // extend dither to 32-bit with left shift by 12 (part 1)
+        ushll2              v2.4S, v0.8H, #12               // extend dither to 32-bit with left shift by 12 (part 2)
+        mov                 x7, #0                          // i = 0
+2:      mov                 v3.16B, v1.16B                  // initialize accumulator part 1 with dithering value
+        mov                 v4.16B, v2.16B                  // initialize accumulator part 2 with dithering value
+        mov                 w8, w1                          // tmpfilterSize = filterSize
+        mov                 x9, x2                          // srcp    = src
+        mov                 x10, x0                         // filterp = filter
+3:      ldp                 x11, x12, [x9], #16             // get 2 pointers: src[j] and src[j+1]
+        add                 x11, x11, x7, lsl #1            // &src[j  ][i]
+        add                 x12, x12, x7, lsl #1            // &src[j+1][i]
+        ld1                 {v5.8H}, [x11]                  // read 8x16-bit @ src[j  ][i + {0..7}]: A,B,C,D,E,F,G,H
+        ld1                 {v6.8H}, [x12]                  // read 8x16-bit @ src[j+1][i + {0..7}]: I,J,K,L,M,N,O,P
+        ldr                 w11, [x10], #4                  // read 2x16-bit coeffs (X, Y) at (filter[j], filter[j+1])
+        zip1                v16.8H, v5.8H, v6.8H            // A,I,B,J,C,K,D,L
+        zip2                v17.8H, v5.8H, v6.8H            // E,M,F,N,F,O,H,P
+        dup                 v7.4S, w11                      // X,Y,X,Y,X,Y,X,Y
+        smull               v18.4S, v16.4H, v7.4H           // A.X I.Y B.X J.Y
+        smull               v20.4S, v17.4H, v7.4H           // E.X M.Y F.X N.Y
+        smull2              v19.4S, v16.8H, v7.8H           // C.X K.Y D.X L.Y
+        smull2              v21.4S, v17.8H, v7.8H           // G.X O.Y H.X P.Y
+        addp                v16.4S, v18.4S, v19.4S          // A.X+I.Y B.X+J.Y C.X+K.Y D.X+L.Y
+        addp                v17.4S, v20.4S, v21.4S          // E.X+M.Y F.X+N.Y F.X+O.Y H.X+P.Y
+        add                 v3.4S, v3.4S, v16.4S            // update val accumulator for part 1
+        add                 v4.4S, v4.4S, v17.4S            // update val accumulator for part 2
+        subs                w8, w8, #2                      // tmpfilterSize -= 2
+        b.gt                3b                              // loop until filterSize consumed
+        sshr                v3.4S, v3.4S, #19               // val>>19 (part 1)
+        sshr                v4.4S, v4.4S, #19               // val>>19 (part 2)
+        sqxtun              v3.4H, v3.4S                    // clip16(val>>19) (part 1)
+        sqxtun              v4.4H, v4.4S                    // clip16(val>>19) (part 2)
+        mov                 v3.D[1], v4.D[0]                // merge part 1 and part 2
+        uqxtn               v3.8B, v3.8H                    // clip8(val>>19)
+        st1                 {v3.1D}, [x3], #8               // write to destination
+        add                 x7, x7, #8                      // i += 8
+        subs                w4, w4, #8                      // dstW -= 8
+        b.gt                2b                              // loop until width consumed
+        ret
+endfunc
diff --git a/libswscale/aarch64/swscale.c b/libswscale/aarch64/swscale.c
new file mode 100644
index 0000000..54a3bea
--- /dev/null
+++ b/libswscale/aarch64/swscale.c
@@ -0,0 +1,44 @@
+/*
+ * 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 "config.h"
+#include "libswscale/swscale.h"
+#include "libswscale/swscale_internal.h"
+#include "libavutil/aarch64/cpu.h"
+
+void ff_hscale_8_to_15_neon(SwsContext *c, int16_t *dst, int dstW,
+                            const uint8_t *src, const int16_t *filter,
+                            const int32_t *filterPos, int filterSize);
+
+void ff_yuv2planeX_8_neon(const int16_t *filter, int filterSize,
+                          const int16_t **src, uint8_t *dest, int dstW,
+                          const uint8_t *dither, int offset);
+
+av_cold void ff_sws_init_swscale_aarch64(SwsContext *c)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (have_neon(cpu_flags)) {
+        if (c->srcBpc == 8 && c->dstBpc <= 14) {
+            c->hyScale = c->hcScale = ff_hscale_8_to_15_neon;
+        }
+        if (c->dstBpc == 8) {
+            c->yuv2planeX = ff_yuv2planeX_8_neon;
+        }
+    }
+}
diff --git a/libswscale/aarch64/swscale_unscaled.c b/libswscale/aarch64/swscale_unscaled.c
new file mode 100644
index 0000000..551daad
--- /dev/null
+++ b/libswscale/aarch64/swscale_unscaled.c
@@ -0,0 +1,132 @@
+/*
+ * 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 "config.h"
+#include "libswscale/swscale.h"
+#include "libswscale/swscale_internal.h"
+#include "libavutil/aarch64/cpu.h"
+
+#define YUV_TO_RGB_TABLE                                                                    \
+        c->yuv2rgb_v2r_coeff,                                                               \
+        c->yuv2rgb_u2g_coeff,                                                               \
+        c->yuv2rgb_v2g_coeff,                                                               \
+        c->yuv2rgb_u2b_coeff,                                                               \
+
+#define DECLARE_FF_YUVX_TO_RGBX_FUNCS(ifmt, ofmt)                                           \
+int ff_##ifmt##_to_##ofmt##_neon(int w, int h,                                              \
+                                 uint8_t *dst, int linesize,                                \
+                                 const uint8_t *srcY, int linesizeY,                        \
+                                 const uint8_t *srcU, int linesizeU,                        \
+                                 const uint8_t *srcV, int linesizeV,                        \
+                                 const int16_t *table,                                      \
+                                 int y_offset,                                              \
+                                 int y_coeff);                                              \
+                                                                                            \
+static int ifmt##_to_##ofmt##_neon_wrapper(SwsContext *c, const uint8_t *src[],             \
+                                           int srcStride[], int srcSliceY, int srcSliceH,   \
+                                           uint8_t *dst[], int dstStride[]) {               \
+    const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
+                                                                                            \
+    ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                        \
+                                 dst[0] + srcSliceY * dstStride[0], dstStride[0],           \
+                                 src[0], srcStride[0],                                      \
+                                 src[1], srcStride[1],                                      \
+                                 src[2], srcStride[2],                                      \
+                                 yuv2rgb_table,                                             \
+                                 c->yuv2rgb_y_offset >> 6,                                  \
+                                 c->yuv2rgb_y_coeff);                                       \
+    return 0;                                                                               \
+}                                                                                           \
+
+#define DECLARE_FF_YUVX_TO_ALL_RGBX_FUNCS(yuvx)                                             \
+DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, argb)                                                   \
+DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, rgba)                                                   \
+DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, abgr)                                                   \
+DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, bgra)                                                   \
+
+DECLARE_FF_YUVX_TO_ALL_RGBX_FUNCS(yuv420p)
+DECLARE_FF_YUVX_TO_ALL_RGBX_FUNCS(yuv422p)
+
+#define DECLARE_FF_NVX_TO_RGBX_FUNCS(ifmt, ofmt)                                            \
+int ff_##ifmt##_to_##ofmt##_neon(int w, int h,                                              \
+                                 uint8_t *dst, int linesize,                                \
+                                 const uint8_t *srcY, int linesizeY,                        \
+                                 const uint8_t *srcC, int linesizeC,                        \
+                                 const int16_t *table,                                      \
+                                 int y_offset,                                              \
+                                 int y_coeff);                                              \
+                                                                                            \
+static int ifmt##_to_##ofmt##_neon_wrapper(SwsContext *c, const uint8_t *src[],             \
+                                           int srcStride[], int srcSliceY, int srcSliceH,   \
+                                           uint8_t *dst[], int dstStride[]) {               \
+    const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
+                                                                                            \
+    ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                        \
+                                 dst[0] + srcSliceY * dstStride[0], dstStride[0],           \
+                                 src[0], srcStride[0], src[1], srcStride[1],                \
+                                 yuv2rgb_table,                                             \
+                                 c->yuv2rgb_y_offset >> 6,                                  \
+                                 c->yuv2rgb_y_coeff);                                       \
+                                                                                            \
+    return 0;                                                                               \
+}                                                                                           \
+
+#define DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nvx)                                               \
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, argb)                                                     \
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, rgba)                                                     \
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, abgr)                                                     \
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, bgra)                                                     \
+
+DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv12)
+DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21)
+
+/* We need a 16 pixel width alignment. This constraint can easily be removed
+ * for input reading but for the output which is 4-bytes per pixel (RGBA) the
+ * assembly might be writing as much as 4*15=60 extra bytes at the end of the
+ * line, which won't fit the 32-bytes buffer alignment. */
+#define SET_FF_NVX_TO_RGBX_FUNC(ifmt, IFMT, ofmt, OFMT, accurate_rnd) do {                  \
+    if (c->srcFormat == AV_PIX_FMT_##IFMT                                                   \
+        && c->dstFormat == AV_PIX_FMT_##OFMT                                                \
+        && !(c->srcH & 1)                                                                   \
+        && !(c->srcW & 15)                                                                  \
+        && !accurate_rnd)                                                                   \
+        c->swscale = ifmt##_to_##ofmt##_neon_wrapper;                                       \
+} while (0)
+
+#define SET_FF_NVX_TO_ALL_RGBX_FUNC(nvx, NVX, accurate_rnd) do {                            \
+    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, argb, ARGB, accurate_rnd);                            \
+    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, rgba, RGBA, accurate_rnd);                            \
+    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, abgr, ABGR, accurate_rnd);                            \
+    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, bgra, BGRA, accurate_rnd);                            \
+} while (0)
+
+static void get_unscaled_swscale_neon(SwsContext *c) {
+    int accurate_rnd = c->flags & SWS_ACCURATE_RND;
+
+    SET_FF_NVX_TO_ALL_RGBX_FUNC(nv12, NV12, accurate_rnd);
+    SET_FF_NVX_TO_ALL_RGBX_FUNC(nv21, NV21, accurate_rnd);
+    SET_FF_NVX_TO_ALL_RGBX_FUNC(yuv420p, YUV420P, accurate_rnd);
+    SET_FF_NVX_TO_ALL_RGBX_FUNC(yuv422p, YUV422P, accurate_rnd);
+}
+
+void ff_get_unscaled_swscale_aarch64(SwsContext *c)
+{
+    int cpu_flags = av_get_cpu_flags();
+    if (have_neon(cpu_flags))
+        get_unscaled_swscale_neon(c);
+}
diff --git a/libswscale/aarch64/yuv2rgb_neon.S b/libswscale/aarch64/yuv2rgb_neon.S
new file mode 100644
index 0000000..b7446aa
--- /dev/null
+++ b/libswscale/aarch64/yuv2rgb_neon.S
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ * Copyright (c) 2016 Clément Bœsch <clement stupeflix.com>
+ *
+ * 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/aarch64/asm.S"
+
+.macro load_yoff_ycoeff yoff ycoeff
+#if defined(__APPLE__)
+    ldp                 w9, w10, [sp, #\yoff]
+#else
+    ldr                 w9,  [sp, #\yoff]
+    ldr                 w10, [sp, #\ycoeff]
+#endif
+.endm
+
+.macro load_args_nv12
+    ldr                 x8,  [sp]                                       // table
+    load_yoff_ycoeff    8, 16                                           // y_offset, y_coeff
+    ld1                 {v1.1D}, [x8]
+    dup                 v0.8H, w10
+    dup                 v3.8H, w9
+    sub                 w3, w3, w0, lsl #2                              // w3 = linesize  - width * 4 (padding)
+    sub                 w5, w5, w0                                      // w5 = linesizeY - width     (paddingY)
+    sub                 w7, w7, w0                                      // w7 = linesizeC - width     (paddingC)
+    neg                 w11, w0
+.endm
+
+.macro load_args_nv21
+    load_args_nv12
+.endm
+
+.macro load_args_yuv420p
+    ldr                 x13, [sp]                                       // srcV
+    ldr                 w14, [sp, #8]                                   // linesizeV
+    ldr                 x8,  [sp, #16]                                  // table
+    load_yoff_ycoeff    24, 32                                          // y_offset, y_coeff
+    ld1                 {v1.1D}, [x8]
+    dup                 v0.8H, w10
+    dup                 v3.8H, w9
+    sub                 w3, w3, w0, lsl #2                              // w3 = linesize  - width * 4 (padding)
+    sub                 w5, w5, w0                                      // w5 = linesizeY - width     (paddingY)
+    sub                 w7,  w7,  w0, lsr #1                            // w7  = linesizeU - width / 2 (paddingU)
+    sub                 w14, w14, w0, lsr #1                            // w14 = linesizeV - width / 2 (paddingV)
+    lsr                 w11, w0, #1
+    neg                 w11, w11
+.endm
+
+.macro load_args_yuv422p
+    ldr                 x13, [sp]                                       // srcV
+    ldr                 w14, [sp, #8]                                   // linesizeV
+    ldr                 x8,  [sp, #16]                                  // table
+    load_yoff_ycoeff    24, 32                                          // y_offset, y_coeff
+    ld1                 {v1.1D}, [x8]
+    dup                 v0.8H, w10
+    dup                 v3.8H, w9
+    sub                 w3, w3, w0, lsl #2                              // w3 = linesize  - width * 4 (padding)
+    sub                 w5, w5, w0                                      // w5 = linesizeY - width     (paddingY)
+    sub                 w7,  w7,  w0, lsr #1                            // w7  = linesizeU - width / 2 (paddingU)
+    sub                 w14, w14, w0, lsr #1                            // w14 = linesizeV - width / 2 (paddingV)
+.endm
+
+.macro load_chroma_nv12
+    ld2                 {v16.8B, v17.8B}, [x6], #16
+    ushll               v18.8H, v16.8B, #3
+    ushll               v19.8H, v17.8B, #3
+.endm
+
+.macro load_chroma_nv21
+    ld2                 {v16.8B, v17.8B}, [x6], #16
+    ushll               v19.8H, v16.8B, #3
+    ushll               v18.8H, v17.8B, #3
+.endm
+
+.macro load_chroma_yuv420p
+    ld1                 {v16.8B}, [ x6], #8
+    ld1                 {v17.8B}, [x13], #8
+    ushll               v18.8H, v16.8B, #3
+    ushll               v19.8H, v17.8B, #3
+.endm
+
+.macro load_chroma_yuv422p
+    load_chroma_yuv420p
+.endm
+
+.macro increment_nv12
+    ands                w15, w1, #1
+    csel                w16, w7, w11, ne                                // incC = (h & 1) ? paddincC : -width
+    add                 x6,  x6, w16, SXTW                              // srcC += incC
+.endm
+
+.macro increment_nv21
+    increment_nv12
+.endm
+
+.macro increment_yuv420p
+    ands                w15, w1, #1
+    csel                w16,  w7, w11, ne                               // incU = (h & 1) ? paddincU : -width/2
+    csel                w17, w14, w11, ne                               // incV = (h & 1) ? paddincV : -width/2
+    add                 x6,  x6,  w16, SXTW                             // srcU += incU
+    add                 x13, x13, w17, SXTW                             // srcV += incV
+.endm
+
+.macro increment_yuv422p
+    add                 x6,  x6,  w7, UXTW                              // srcU += incU
+    add                 x13, x13, w14, UXTW                             // srcV += incV
+.endm
+
+.macro compute_rgba r1 g1 b1 a1 r2 g2 b2 a2
+    add                 v20.8H, v26.8H, v20.8H                          // Y1 + R1
+    add                 v21.8H, v27.8H, v21.8H                          // Y2 + R2
+    add                 v22.8H, v26.8H, v22.8H                          // Y1 + G1
+    add                 v23.8H, v27.8H, v23.8H                          // Y2 + G2
+    add                 v24.8H, v26.8H, v24.8H                          // Y1 + B1
+    add                 v25.8H, v27.8H, v25.8H                          // Y2 + B2
+    sqrshrun            \r1, v20.8H, #1                                 // clip_u8((Y1 + R1) >> 1)
+    sqrshrun            \r2, v21.8H, #1                                 // clip_u8((Y2 + R1) >> 1)
+    sqrshrun            \g1, v22.8H, #1                                 // clip_u8((Y1 + G1) >> 1)
+    sqrshrun            \g2, v23.8H, #1                                 // clip_u8((Y2 + G1) >> 1)
+    sqrshrun            \b1, v24.8H, #1                                 // clip_u8((Y1 + B1) >> 1)
+    sqrshrun            \b2, v25.8H, #1                                 // clip_u8((Y2 + B1) >> 1)
+    movi                \a1, #255
+    movi                \a2, #255
+.endm
+
+.macro declare_func ifmt ofmt
+function ff_\ifmt\()_to_\ofmt\()_neon, export=1
+    load_args_\ifmt
+1:
+    mov                 w8, w0                                          // w8 = width
+2:
+    movi                v5.8H, #4, lsl #8                               // 128 * (1<<3)
+    load_chroma_\ifmt
+    sub                 v18.8H, v18.8H, v5.8H                           // U*(1<<3) - 128*(1<<3)
+    sub                 v19.8H, v19.8H, v5.8H                           // V*(1<<3) - 128*(1<<3)
+    sqdmulh             v20.8H, v19.8H, v1.H[0]                         // V * v2r            (R)
+    sqdmulh             v22.8H, v18.8H, v1.H[1]                         // U * u2g
+    sqdmulh             v19.8H, v19.8H, v1.H[2]                         //           V * v2g
+    add                 v22.8H, v22.8H, v19.8H                          // U * u2g + V * v2g  (G)
+    sqdmulh             v24.8H, v18.8H, v1.H[3]                         // U * u2b            (B)
+    zip2                v21.8H, v20.8H, v20.8H                          // R2
+    zip1                v20.8H, v20.8H, v20.8H                          // R1
+    zip2                v23.8H, v22.8H, v22.8H                          // G2
+    zip1                v22.8H, v22.8H, v22.8H                          // G1
+    zip2                v25.8H, v24.8H, v24.8H                          // B2
+    zip1                v24.8H, v24.8H, v24.8H                          // B1
+    ld1                 {v2.16B}, [x4], #16                             // load luma
+    ushll               v26.8H, v2.8B,  #3                              // Y1*(1<<3)
+    ushll2              v27.8H, v2.16B, #3                              // Y2*(1<<3)
+    sub                 v26.8H, v26.8H, v3.8H                           // Y1*(1<<3) - y_offset
+    sub                 v27.8H, v27.8H, v3.8H                           // Y2*(1<<3) - y_offset
+    sqdmulh             v26.8H, v26.8H, v0.8H                           // ((Y1*(1<<3) - y_offset) * y_coeff) >> 15
+    sqdmulh             v27.8H, v27.8H, v0.8H                           // ((Y2*(1<<3) - y_offset) * y_coeff) >> 15
+
+.ifc \ofmt,argb // 1 2 3 0
+    compute_rgba        v5.8B,v6.8B,v7.8B,v4.8B, v17.8B,v18.8B,v19.8B,v16.8B
+.endif
+
+.ifc \ofmt,rgba // 0 1 2 3
+    compute_rgba        v4.8B,v5.8B,v6.8B,v7.8B, v16.8B,v17.8B,v18.8B,v19.8B
+.endif
+
+.ifc \ofmt,abgr // 3 2 1 0
+    compute_rgba        v7.8B,v6.8B,v5.8B,v4.8B, v19.8B,v18.8B,v17.8B,v16.8B
+.endif
+
+.ifc \ofmt,bgra // 2 1 0 3
+    compute_rgba        v6.8B,v5.8B,v4.8B,v7.8B, v18.8B,v17.8B,v16.8B,v19.8B
+.endif
+
+    st4                 { v4.8B, v5.8B, v6.8B, v7.8B}, [x2], #32
+    st4                 {v16.8B,v17.8B,v18.8B,v19.8B}, [x2], #32
+    subs                w8, w8, #16                                     // width -= 16
+    b.gt                2b
+    add                 x2, x2, w3, UXTW                                // dst  += padding
+    add                 x4, x4, w5, UXTW                                // srcY += paddingY
+    increment_\ifmt
+    subs                w1, w1, #1                                      // height -= 1
+    b.gt                1b
+    ret
+endfunc
+.endm
+
+.macro declare_rgb_funcs ifmt
+    declare_func \ifmt, argb
+    declare_func \ifmt, rgba
+    declare_func \ifmt, abgr
+    declare_func \ifmt, bgra
+.endm
+
+declare_rgb_funcs nv12
+declare_rgb_funcs nv21
+declare_rgb_funcs yuv420p
+declare_rgb_funcs yuv422p
diff --git a/libswscale/arm/Makefile b/libswscale/arm/Makefile
index 97b3561..792da6b 100644
--- a/libswscale/arm/Makefile
+++ b/libswscale/arm/Makefile
@@ -1,5 +1,8 @@
-OBJS        += arm/swscale_unscaled.o
+OBJS        += arm/swscale.o                    \
+               arm/swscale_unscaled.o           \
 
-# NEON-OBJS   += arm/rgb2yuv_neon_32.o
-# NEON-OBJS   += arm/rgb2yuv_neon_16.o
-NEON-OBJS   += arm/yuv2rgb_neon.o
+NEON-OBJS   += arm/rgb2yuv_neon_32.o
+NEON-OBJS   += arm/rgb2yuv_neon_16.o
+NEON-OBJS   += arm/hscale.o                     \
+               arm/output.o                     \
+               arm/yuv2rgb_neon.o               \
diff --git a/libswscale/arm/hscale.S b/libswscale/arm/hscale.S
new file mode 100644
index 0000000..dd4d453
--- /dev/null
+++ b/libswscale/arm/hscale.S
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016 Clément Bœsch <clement stupeflix.com>
+ * Copyright (c) 2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * 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/arm/asm.S"
+
+function ff_hscale_8_to_15_neon, export=1
+    push                {r4-r12, lr}
+    vpush               {q4-q7}
+    ldr                 r4, [sp, #104]                                 @ filter
+    ldr                 r5, [sp, #108]                                 @ filterPos
+    ldr                 r6, [sp, #112]                                 @ filterSize
+    add                 r10, r4, r6, lsl #1                            @ filter2 = filter + filterSize * 2
+1:  ldr                 r8, [r5], #4                                   @ filterPos[0]
+    ldr                 r9, [r5], #4                                   @ filterPos[1]
+    vmov.s32            q4, #0                                         @ val accumulator
+    vmov.s32            q5, #0                                         @ val accumulator
+    mov                 r7, r6                                         @ tmpfilterSize = filterSize
+    mov                 r0, r3                                         @ srcp
+2:  add                 r11, r0, r8                                    @ srcp + filterPos[0]
+    add                 r12, r0, r9                                    @ srcp + filterPos[1]
+    vld1.8              d0, [r11]                                      @ srcp[filterPos[0] + {0..7}]
+    vld1.8              d2, [r12]                                      @ srcp[filterPos[1] + {0..7}]
+    vld1.16             {q2}, [r4]!                                    @ load 8x16-bit filter values
+    vld1.16             {q3}, [r10]!                                   @ load 8x16-bit filter values
+    vmovl.u8            q0, d0                                         @ unpack src values to 16-bit
+    vmovl.u8            q1, d2                                         @ unpack src values to 16-bit
+    vmull.s16           q8, d0, d4                                     @ srcp[filterPos[0] + {0..7}] * filter[{0..7}] (part 1)
+    vmull.s16           q9, d1, d5                                     @ srcp[filterPos[0] + {0..7}] * filter[{0..7}] (part 2)
+    vmull.s16           q10, d2, d6                                    @ srcp[filterPos[1] + {0..7}] * filter[{0..7}] (part 1)
+    vmull.s16           q11, d3, d7                                    @ srcp[filterPos[1] + {0..7}] * filter[{0..7}] (part 2)
+    vpadd.s32           d16, d16, d17                                  @ horizontal pair adding of the 8x32-bit multiplied values into 4x32-bit (part 1)
+    vpadd.s32           d17, d18, d19                                  @ horizontal pair adding of the 8x32-bit multiplied values into 4x32-bit (part 2)
+    vpadd.s32           d20, d20, d21                                  @ horizontal pair adding of the 8x32-bit multiplied values into 4x32-bit (part 1)
+    vpadd.s32           d21, d22, d23                                  @ horizontal pair adding of the 8x32-bit multiplied values into 4x32-bit (part 2)
+    vadd.s32            q4, q8                                         @ update val accumulator
+    vadd.s32            q5, q10                                        @ update val accumulator
+    add                 r0, #8                                         @ srcp += 8
+    subs                r7, #8                                         @ tmpfilterSize -= 8
+    bgt                 2b                                             @ loop until tmpfilterSize is consumed
+    mov                 r4, r10                                        @ filter = filter2
+    add                 r10, r10, r6, lsl #1                           @ filter2 += filterSize * 2
+    vpadd.s32           d8, d8, d9                                     @ horizontal pair adding of the 8x32-bit sums into 4x32-bit (part 1)
+    vpadd.s32           d9, d10, d11                                   @ horizontal pair adding of the 8x32-bit sums into 4x32-bit (part 2)
+    vpadd.s32           d8, d8, d9                                     @ horizontal pair adding of the 4x32-bit sums into 2x32-bit
+    vqshrn.s32          d8, q4, #7                                     @ shift and clip the 2x16-bit final values
+    vst1.32             {d8[0]},[r1]!                                  @ write destination
+    subs                r2, #2                                         @ dstW -= 2
+    bgt                 1b                                             @ loop until end of line
+    vpop                {q4-q7}
+    pop                 {r4-r12, lr}
+    mov pc, lr
+endfunc
diff --git a/libswscale/arm/output.S b/libswscale/arm/output.S
new file mode 100644
index 0000000..70846de
--- /dev/null
+++ b/libswscale/arm/output.S
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016 Clément Bœsch <clement stupeflix.com>
+ * Copyright (c) 2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
+ *
+ * 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/arm/asm.S"
+
+function ff_yuv2planeX_8_neon, export=1
+    push {r4-r12, lr}
+    vpush {q4-q7}
+    ldr                 r4, [sp, #104]                                 @ dstW
+    ldr                 r5, [sp, #108]                                 @ dither
+    ldr                 r6, [sp, #112]                                 @ offset
+    vld1.8              {d0}, [r5]                                     @ load 8x8-bit dither values
+    cmp                 r6, #0                                         @ check offsetting which can be 0 or 3 only
+    beq                 1f
+    vext.u8             d0, d0, d0, #3                                 @ honor offseting which can be 3 only
+1:  vmovl.u8            q0, d0                                         @ extend dither to 16-bit
+    vshll.u16           q1, d0, #12                                    @ extend dither to 32-bit with left shift by 12 (part 1)
+    vshll.u16           q2, d1, #12                                    @ extend dither to 32-bit with left shift by 12 (part 2)
+    mov                 r7, #0                                         @ i = 0
+2:  vmov.u8             q3, q1                                         @ initialize accumulator with dithering values (part 1)
+    vmov.u8             q4, q2                                         @ initialize accumulator with dithering values (part 2)
+    mov                 r8, r1                                         @ tmpFilterSize = filterSize
+    mov                 r9, r2                                         @ srcp
+    mov                 r10, r0                                        @ filterp
+3:  ldr                 r11, [r9], #4                                  @ get pointer @ src[j]
+    ldr                 r12, [r9], #4                                  @ get pointer @ src[j+1]
+    add                 r11, r11, r7, lsl #1                           @ &src[j][i]
+    add                 r12, r12, r7, lsl #1                           @ &src[j+1][i]
+    vld1.16             {q5}, [r11]                                    @ read 8x16-bit @ src[j  ][i + {0..7}]: A,B,C,D,E,F,G,H
+    vld1.16             {q6}, [r12]                                    @ read 8x16-bit @ src[j+1][i + {0..7}]: I,J,K,L,M,N,O,P
+    ldr                 r11, [r10], #4                                 @ read 2x16-bit coeffs (X, Y) at (filter[j], filter[j+1])
+    vmov.16             q7, q5                                         @ copy 8x16-bit @ src[j  ][i + {0..7}] for following inplace zip instruction
+    vmov.16             q8, q6                                         @ copy 8x16-bit @ src[j+1][i + {0..7}] for following inplace zip instruction
+    vzip.16             q7, q8                                         @ A,I,B,J,C,K,D,L,E,M,F,N,G,O,H,P
+    vdup.32             q15, r11                                       @ X,Y,X,Y,X,Y,X,Y
+    vmull.s16           q9, d14, d30                                   @ A*X,I*Y,B*X,J*Y
+    vmull.s16           q10, d15, d31                                  @ C*X,K*Y,D*X,L*Y
+    vmull.s16           q11, d16, d30                                  @ E*X,M*Y,F*X,N*Y
+    vmull.s16           q12, d17, d31                                  @ G*X,O*Y,H*X,P*Y
+    vpadd.s32           d10, d18, d19                                  @ A*X+I*Y,B*X+J*Y
+    vpadd.s32           d11, d20, d21                                  @ C*X+K*Y,D*X+L*Y
+    vpadd.s32           d12, d22, d23                                  @ E*X+M*Y,F*X+N*Y
+    vpadd.s32           d13, d24, d25                                  @ G*X+O*Y,H*X+P*Y
+    vadd.s32            q3, q5                                         @ update val accumulator (part 1)
+    vadd.s32            q4, q6                                         @ update val accumulator (part 2)
+    subs                r8, #2                                         @ tmpFilterSize -= 2
+    bgt                 3b                                             @ loop until filterSize is consumed
+    vshr.s32            q3, q3, #19                                    @ val>>19 (part 1)
+    vshr.s32            q4, q4, #19                                    @ val>>19 (part 2)
+    vqmovun.s32         d6, q3                                         @ clip16(val>>19) (part 1)
+    vqmovun.s32         d7, q4                                         @ clip16(val>>19) (part 2)
+    vqmovn.u16          d6, q3                                         @ merge part 1 and part 2
+    vst1.8              {d6}, [r3]!                                    @ write destination
+    add                 r7, #8                                         @ i += 8
+    subs                r4, r4, #8                                     @ dstW -= 8
+    bgt                 2b                                             @ loop until width is consumed
+    vpop                {q4-q7}
+    pop                 {r4-r12, lr}
+    mov                 pc, lr
+endfunc
diff --git a/libswscale/arm/swscale.c b/libswscale/arm/swscale.c
new file mode 100644
index 0000000..1ec360f
--- /dev/null
+++ b/libswscale/arm/swscale.c
@@ -0,0 +1,44 @@
+/*
+ * 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 "config.h"
+#include "libswscale/swscale.h"
+#include "libswscale/swscale_internal.h"
+#include "libavutil/arm/cpu.h"
+
+void ff_hscale_8_to_15_neon(SwsContext *c, int16_t *dst, int dstW,
+                            const uint8_t *src, const int16_t *filter,
+                            const int32_t *filterPos, int filterSize);
+
+void ff_yuv2planeX_8_neon(const int16_t *filter, int filterSize,
+                          const int16_t **src, uint8_t *dest, int dstW,
+                          const uint8_t *dither, int offset);
+
+av_cold void ff_sws_init_swscale_arm(SwsContext *c)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (have_neon(cpu_flags)) {
+        if (c->srcBpc == 8 && c->dstBpc <= 14) {
+            c->hyScale = c->hcScale = ff_hscale_8_to_15_neon;
+        }
+        if (c->dstBpc == 8) {
+            c->yuv2planeX = ff_yuv2planeX_8_neon;
+        }
+    }
+}
diff --git a/libswscale/arm/swscale_unscaled.c b/libswscale/arm/swscale_unscaled.c
index ac1e4a9..e1597ab 100644
--- a/libswscale/arm/swscale_unscaled.c
+++ b/libswscale/arm/swscale_unscaled.c
@@ -23,7 +23,6 @@
 #include "libswscale/swscale_internal.h"
 #include "libavutil/arm/cpu.h"
 
-#if 0
 extern void rgbx_to_nv12_neon_32(const uint8_t *src, uint8_t *y, uint8_t *chroma,
                 int width, int height,
                 int y_stride, int c_stride, int src_stride,
@@ -61,16 +60,15 @@ static int rgbx_to_nv12_neon_16_wrapper(SwsContext *context, const uint8_t *src[
 
     return 0;
 }
-#endif
 
-#define YUV_TO_RGB_TABLE(precision)                                                         \
-        c->yuv2rgb_v2r_coeff / ((precision) == 16 ? 1 << 7 : 1),                            \
-        c->yuv2rgb_u2g_coeff / ((precision) == 16 ? 1 << 7 : 1),                            \
-        c->yuv2rgb_v2g_coeff / ((precision) == 16 ? 1 << 7 : 1),                            \
-        c->yuv2rgb_u2b_coeff / ((precision) == 16 ? 1 << 7 : 1),                            \
+#define YUV_TO_RGB_TABLE                                                                    \
+        c->yuv2rgb_v2r_coeff,                                                               \
+        c->yuv2rgb_u2g_coeff,                                                               \
+        c->yuv2rgb_v2g_coeff,                                                               \
+        c->yuv2rgb_u2b_coeff,                                                               \
 
-#define DECLARE_FF_YUVX_TO_RGBX_FUNCS(ifmt, ofmt, precision)                                \
-int ff_##ifmt##_to_##ofmt##_neon_##precision(int w, int h,                                  \
+#define DECLARE_FF_YUVX_TO_RGBX_FUNCS(ifmt, ofmt)                                           \
+int ff_##ifmt##_to_##ofmt##_neon(int w, int h,                                              \
                                  uint8_t *dst, int linesize,                                \
                                  const uint8_t *srcY, int linesizeY,                        \
                                  const uint8_t *srcU, int linesizeU,                        \
@@ -79,37 +77,34 @@ int ff_##ifmt##_to_##ofmt##_neon_##precision(int w, int h,
                                  int y_offset,                                              \
                                  int y_coeff);                                              \
                                                                                             \
-static int ifmt##_to_##ofmt##_neon_wrapper_##precision(SwsContext *c, const uint8_t *src[], \
+static int ifmt##_to_##ofmt##_neon_wrapper(SwsContext *c, const uint8_t *src[],             \
                                            int srcStride[], int srcSliceY, int srcSliceH,   \
                                            uint8_t *dst[], int dstStride[]) {               \
-    const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE(precision) };                        \
+    const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
                                                                                             \
-    ff_##ifmt##_to_##ofmt##_neon_##precision(c->srcW, srcSliceH,                            \
+    ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                        \
                                  dst[0] + srcSliceY * dstStride[0], dstStride[0],           \
                                  src[0], srcStride[0],                                      \
                                  src[1], srcStride[1],                                      \
                                  src[2], srcStride[2],                                      \
                                  yuv2rgb_table,                                             \
-                                 c->yuv2rgb_y_offset >> 9,                                  \
-                                 c->yuv2rgb_y_coeff / ((precision) == 16 ? 1 << 7 : 1));    \
+                                 c->yuv2rgb_y_offset >> 6,                                  \
+                                 c->yuv2rgb_y_coeff);                                       \
                                                                                             \
     return 0;                                                                               \
 }                                                                                           \
 
-#define DECLARE_FF_YUVX_TO_ALL_RGBX_FUNCS(yuvx, precision)                                  \
-DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, argb, precision)                                        \
-DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, rgba, precision)                                        \
-DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, abgr, precision)                                        \
-DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, bgra, precision)                                        \
+#define DECLARE_FF_YUVX_TO_ALL_RGBX_FUNCS(yuvx)                                             \
+DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, argb)                                                   \
+DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, rgba)                                                   \
+DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, abgr)                                                   \
+DECLARE_FF_YUVX_TO_RGBX_FUNCS(yuvx, bgra)                                                   \
 
-#define DECLARE_FF_YUVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(yuvx)                               \
-DECLARE_FF_YUVX_TO_ALL_RGBX_FUNCS(yuvx, 16)                                                 \
+DECLARE_FF_YUVX_TO_ALL_RGBX_FUNCS(yuv420p)
+DECLARE_FF_YUVX_TO_ALL_RGBX_FUNCS(yuv422p)
 
-DECLARE_FF_YUVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(yuv420p)
-DECLARE_FF_YUVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(yuv422p)
-
-#define DECLARE_FF_NVX_TO_RGBX_FUNCS(ifmt, ofmt, precision)                                 \
-int ff_##ifmt##_to_##ofmt##_neon_##precision(int w, int h,                                  \
+#define DECLARE_FF_NVX_TO_RGBX_FUNCS(ifmt, ofmt)                                            \
+int ff_##ifmt##_to_##ofmt##_neon(int w, int h,                                              \
                                  uint8_t *dst, int linesize,                                \
                                  const uint8_t *srcY, int linesizeY,                        \
                                  const uint8_t *srcC, int linesizeC,                        \
@@ -117,32 +112,29 @@ int ff_##ifmt##_to_##ofmt##_neon_##precision(int w, int h,
                                  int y_offset,                                              \
                                  int y_coeff);                                              \
                                                                                             \
-static int ifmt##_to_##ofmt##_neon_wrapper_##precision(SwsContext *c, const uint8_t *src[], \
+static int ifmt##_to_##ofmt##_neon_wrapper(SwsContext *c, const uint8_t *src[],             \
                                            int srcStride[], int srcSliceY, int srcSliceH,   \
                                            uint8_t *dst[], int dstStride[]) {               \
-    const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE(precision) };                        \
+    const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE };                                   \
                                                                                             \
-    ff_##ifmt##_to_##ofmt##_neon_##precision(c->srcW, srcSliceH,                            \
+    ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                        \
                                  dst[0] + srcSliceY * dstStride[0], dstStride[0],           \
                                  src[0], srcStride[0], src[1], srcStride[1],                \
                                  yuv2rgb_table,                                             \
-                                 c->yuv2rgb_y_offset >> 9,                                  \
-                                 c->yuv2rgb_y_coeff / ((precision) == 16 ? 1 << 7 : 1));    \
+                                 c->yuv2rgb_y_offset >> 6,                                  \
+                                 c->yuv2rgb_y_coeff);                                       \
                                                                                             \
     return 0;                                                                               \
 }                                                                                           \
 
-#define DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nvx, precision)                                    \
-DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, argb, precision)                                          \
-DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, rgba, precision)                                          \
-DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, abgr, precision)                                          \
-DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, bgra, precision)                                          \
-
-#define DECLARE_FF_NVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(nvx)                                 \
-DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nvx, 16)                                                   \
+#define DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nvx)                                               \
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, argb)                                                     \
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, rgba)                                                     \
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, abgr)                                                     \
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, bgra)                                                     \
 
-DECLARE_FF_NVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(nv12)
-DECLARE_FF_NVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(nv21)
+DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv12)
+DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21)
 
 /* We need a 16 pixel width alignment. This constraint can easily be removed
  * for input reading but for the output which is 4-bytes per pixel (RGBA) the
@@ -154,7 +146,7 @@ DECLARE_FF_NVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(nv21)
         && !(c->srcH & 1)                                                                   \
         && !(c->srcW & 15)                                                                  \
         && !accurate_rnd) {                                                                 \
-        c->swscale = ifmt##_to_##ofmt##_neon_wrapper_16;                                    \
+        c->swscale = ifmt##_to_##ofmt##_neon_wrapper;                                       \
     }                                                                                       \
 } while (0)
 
@@ -167,14 +159,12 @@ DECLARE_FF_NVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(nv21)
 
 static void get_unscaled_swscale_neon(SwsContext *c) {
     int accurate_rnd = c->flags & SWS_ACCURATE_RND;
-#if 0
     if (c->srcFormat == AV_PIX_FMT_RGBA
             && c->dstFormat == AV_PIX_FMT_NV12
             && (c->srcW >= 16)) {
         c->swscale = accurate_rnd ? rgbx_to_nv12_neon_32_wrapper
                         : rgbx_to_nv12_neon_16_wrapper;
     }
-#endif
 
     SET_FF_NVX_TO_ALL_RGBX_FUNC(nv12, NV12, accurate_rnd);
     SET_FF_NVX_TO_ALL_RGBX_FUNC(nv21, NV21, accurate_rnd);
diff --git a/libswscale/arm/yuv2rgb_neon.S b/libswscale/arm/yuv2rgb_neon.S
index 829e1b6..10950e7 100644
--- a/libswscale/arm/yuv2rgb_neon.S
+++ b/libswscale/arm/yuv2rgb_neon.S
@@ -22,186 +22,80 @@
 #include "libavutil/arm/asm.S"
 
 
-.macro compute_premult_16 half_u1, half_u2, half_v1, half_v2
-    vmov                d2, \half_u1                                   @ copy left q14 to left q1
-    vmov                d3, \half_u1                                   @ copy left q14 to right q1
-    vmov                d4, \half_u2                                   @ copy right q14 to left q2
-    vmov                d5, \half_u2                                   @ copy right q14 to right q2
-
-    vmov                d6, \half_v1                                   @ copy left q15 to left q3
-    vmov                d7, \half_v1                                   @ copy left q15 to right q3
-    vmov                d8, \half_v2                                   @ copy right q15 to left q4
-    vmov                d9, \half_v2                                   @ copy right q15 to right q4
-
-    vzip.16             d2, d3                                         @ U1U1U2U2U3U3U4U4
-    vzip.16             d4, d5                                         @ U5U5U6U6U7U7U8U8
-
-    vzip.16             d6, d7                                         @ V1V1V2V2V3V3V4V4
-    vzip.16             d8, d9                                         @ V5V5V6V6V7V7V8V8
-
-    vmul.s16            q8,  q3, d1[0]                                 @  V * v2r             (left,  red)
-    vmul.s16            q9,  q4, d1[0]                                 @  V * v2r             (right, red)
-    vmul.s16            q10, q1, d1[1]                                 @  U * u2g
-    vmul.s16            q11, q2, d1[1]                                 @  U * u2g
-    vmla.s16            q10, q3, d1[2]                                 @  U * u2g + V * v2g   (left,  green)
-    vmla.s16            q11, q4, d1[2]                                 @  U * u2g + V * v2g   (right, green)
-    vmul.s16            q12, q1, d1[3]                                 @  U * u2b             (left,  blue)
-    vmul.s16            q13, q2, d1[3]                                 @  U * u2b             (right, blue)
+.macro compute_premult
+    vsub.u16            q14,q11                                        @ q14 = U * (1 << 3) - 128 * (1 << 3)
+    vsub.u16            q15,q11                                        @ q15 = V * (1 << 3) - 128 * (1 << 3)
+    vqdmulh.s16         q8, q15, d1[0]                                 @ q8  = V * v2r
+    vqdmulh.s16         q9, q14, d1[1]                                 @ q9  = U * u2g
+    vqdmulh.s16         q5, q15, d1[2]                                 @ q5  = V * v2g
+    vadd.s16            q9, q5                                         @ q9  = U * u2g + V * v2g
+    vqdmulh.s16         q10,q14, d1[3]                                 @ q10 = U * u2b
 .endm
 
-.macro compute_premult_32 half_u half_v
-    vmov                d2, \half_u                                    @ copy left q14 to left q1
-    vmov                d3, \half_u                                    @ copy left q14 to right q1
-    vmov                d4, \half_v                                    @ copy left q15 to left q2
-    vmov                d5, \half_v                                    @ copy left q15 to right q2
-
-    vzip.16             d2, d3                                         @ U1U1U2U2U3U3U4U4
-    vzip.16             d4, d5                                         @ V1V1V2V2V3V3V4V4
-
-    vmull.s16           q8,  d4, d1[0]                                 @  V * v2r             (left,  red)
-    vmull.s16           q9,  d5, d1[0]                                 @  V * v2r             (right, red)
-    vmull.s16           q10, d2, d1[1]                                 @  U * u2g
-    vmull.s16           q11, d3, d1[1]                                 @  U * u2g
-    vmlal.s16           q10, d4, d1[2]                                 @  U * u2g + V * v2g   (left,  green)
-    vmlal.s16           q11, d5, d1[2]                                 @  U * u2g + V * v2g   (right, green)
-    vmull.s16           q12, d2, d1[3]                                 @  U * u2b             (left,  blue)
-    vmull.s16           q13, d3, d1[3]                                 @  U * u2b             (right, blue)
+.macro compute_color dst_comp1 dst_comp2 pre
+    vadd.s16            q1, q14, \pre
+    vadd.s16            q2, q15, \pre
+    vqrshrun.s16        \dst_comp1, q1, #1
+    vqrshrun.s16        \dst_comp2, q2, #1
 .endm
 
-.macro compute_color_16 dst_comp1 dst_comp2 pre1 pre2
-    vadd.s16            q1, q14, \pre1
-    vadd.s16            q2, q15, \pre2
-    vqrshrun.s16        \dst_comp1, q1, #6
-    vqrshrun.s16        \dst_comp2, q2, #6
-.endm
-
-.macro compute_color_32 dst_comp pre1 pre2
-    vadd.s32            q3, q1, \pre1
-    vadd.s32            q4, q2, \pre2
-    vqrshrun.s32        d10, q3, #13
-    vqrshrun.s32        d11, q4, #13                                   @ q5 = ({q3,q4} + (1<<12)) >> 13
-    vqmovn.u16          \dst_comp, q5                                  @ saturate 16bit -> 8bit
-.endm
-
-.macro compute_rgba_16 r1 r2 g1 g2 b1 b2 a1 a2
-    compute_color_16    \r1, \r2, q8,  q9
-    compute_color_16    \g1, \g2, q10, q11
-    compute_color_16    \b1, \b2, q12, q13
+.macro compute_rgba r1 g1 b1 a1 r2 g2 b2 a2
+    compute_color       \r1, \r2, q8
+    compute_color       \g1, \g2, q9
+    compute_color       \b1, \b2, q10
     vmov.u8             \a1, #255
     vmov.u8             \a2, #255
 .endm
 
-.macro compute_rgba_32 r g b a
-    compute_color_32    \r, q8,  q9
-    compute_color_32    \g, q10, q11
-    compute_color_32    \b, q12, q13
-    vmov.u8             \a, #255
-.endm
-
-.macro compute_16px_16 dst y0 y1 ofmt
-    vmovl.u8            q14, \y0                                       @ 8px of y
-    vmovl.u8            q15, \y1                                       @ 8px of y
-
-    vdup.16             q5, r9                                         @ q5  = y_offset
-    vmov                d14, d0                                        @ q7  = y_coeff
-    vmov                d15, d0                                        @ q7  = y_coeff
-
-    vsub.s16            q14, q5
-    vsub.s16            q15, q5
-
-    vmul.s16            q14, q7                                        @ q14 = (srcY - y_offset) * y_coeff (left)
-    vmul.s16            q15, q7                                        @ q15 = (srcY - y_offset) * y_coeff (right)
-
+.macro compute dst ofmt
+    vshll.u8            q14, d14, #3                                   @ q14 = Y * (1 << 3)
+    vshll.u8            q15, d15, #3                                   @ q15 = Y * (1 << 3)
+    vsub.s16            q14, q12                                       @ q14 = (Y - y_offset)
+    vsub.s16            q15, q12                                       @ q15 = (Y - y_offset)
+    vqdmulh.s16         q14, q13                                       @ q14 = (Y - y_offset) * y_coeff
+    vqdmulh.s16         q15, q13                                       @ q15 = (Y - y_offset) * y_coeff
 
 .ifc \ofmt,argb
-    compute_rgba_16     d7, d11, d8, d12, d9, d13, d6, d10
+    compute_rgba        d7, d8, d9, d6, d11, d12, d13, d10
 .endif
 
 .ifc \ofmt,rgba
-    compute_rgba_16     d6, d10, d7, d11, d8, d12, d9, d13
+    compute_rgba        d6, d7, d8, d9, d10, d11, d12, d13
 .endif
 
 .ifc \ofmt,abgr
-    compute_rgba_16     d9, d13, d8, d12, d7, d11, d6, d10
+    compute_rgba        d9, d8, d7, d6, d13, d12, d11, d10
 .endif
 
 .ifc \ofmt,bgra
-    compute_rgba_16     d8, d12, d7, d11, d6, d10, d9, d13
+    compute_rgba        d8, d7, d6, d9, d12, d11, d10, d13
 .endif
+
+    vzip.8              d6, d10                                        @ d6 = R1R2R3R4R5R6R7R8 d10 = R9R10R11R12R13R14R15R16
+    vzip.8              d7, d11                                        @ d7 = G1G2G3G4G5G6G7G8 d11 = G9G10G11G12G13G14G15G16
+    vzip.8              d8, d12                                        @ d8 = B1B2B3B4B5B6B7B8 d12 = B9B10B11B12B13B14B15B16
+    vzip.8              d9, d13                                        @ d9 = A1A2A3A4A5A6A7A8 d13 = A9A10A11A12A13A14A15A16
     vst4.8              {q3, q4}, [\dst,:128]!
     vst4.8              {q5, q6}, [\dst,:128]!
-
 .endm
 
-.macro compute_8px_32 dst half_y ofmt
-    vmovl.u8            q7, \half_y                                    @ 8px of Y
-    vdup.16             q5, r9
-    vsub.s16            q7, q5
-    vmull.s16           q1, d14, d0                                    @ q1 = (srcY - y_offset) * y_coeff (left)
-    vmull.s16           q2, d15, d0                                    @ q2 = (srcY - y_offset) * y_coeff (right)
-
-.ifc \ofmt,argb
-    compute_rgba_32     d13, d14, d15, d12
-.endif
-
-.ifc \ofmt,rgba
-    compute_rgba_32     d12, d13, d14, d15
-.endif
-
-.ifc \ofmt,abgr
-    compute_rgba_32     d15, d14, d13, d12
-.endif
-
-.ifc \ofmt,bgra
-    compute_rgba_32     d14, d13, d12, d15
-.endif
-
-    vst4.8              {q6, q7}, [\dst,:128]!
+.macro process_1l_internal dst src ofmt
+    vld2.8              {d14, d15}, [\src]!                            @ q7 = Y (interleaved)
+    compute             \dst, \ofmt
 .endm
 
-.macro process_1l_16px_16 ofmt
-    compute_premult_16  d28, d29, d30, d31
-    vld1.8              {q7}, [r4]!
-    compute_16px_16     r2, d14, d15, \ofmt
+.macro process_1l ofmt
+    compute_premult
+    process_1l_internal r2, r4, \ofmt
 .endm
 
-.macro process_1l_16px_32 ofmt
-    compute_premult_32  d28, d30
-    vld1.8              {q7}, [r4]!
-    vmov                d28, d15                                       @ save right of the line of luma for later use
-    compute_8px_32      r2, d14, \ofmt
-
-    compute_premult_32  d29, d31
-    compute_8px_32      r2,  d28, \ofmt
+.macro process_2l ofmt
+    compute_premult
+    process_1l_internal r2, r4, \ofmt
+    process_1l_internal r11,r12,\ofmt
 .endm
 
-.macro process_2l_16px_16 ofmt
-    compute_premult_16  d28, d29, d30, d31
-
-    vld1.8              {q7}, [r4]!                                    @ first line of luma
-    compute_16px_16     r2, d14, d15, \ofmt
-
-    vld1.8              {q7}, [r12]!                                   @ second line of luma
-    compute_16px_16     r11, d14, d15, \ofmt
-.endm
-
-.macro process_2l_16px_32 ofmt
-    compute_premult_32  d28, d30
-
-    vld1.8              {q7}, [r4]!                                    @ first line of luma
-    vmov                d28, d15                                       @ save right of the first line of luma for later use
-    compute_8px_32      r2, d14, \ofmt
-
-    vld1.8              {q7}, [r12]!                                   @ second line of luma
-    vmov                d30, d15                                       @ save right of the second line of luma for later use
-    compute_8px_32      r11, d14, \ofmt
-
-    compute_premult_32  d29, d31
-    compute_8px_32      r2,  d28, \ofmt
-    compute_8px_32      r11, d30, \ofmt
-.endm
-
-.macro load_args_nvx
+.macro load_args_nv12
     push                {r4-r12, lr}
     vpush               {q4-q7}
     ldr                 r4, [sp, #104]                                 @ r4  = srcY
@@ -217,12 +111,15 @@
     add                 r12, r4, r5                                    @ r12 = srcY + linesizeY (srcY2)
     lsl                 r3, r3, #1
     lsl                 r5, r5, #1
-    lsl                 r8, r0, #2
-    sub                 r3, r3, r8                                     @ r3 = linesize  * 2 - width * 4 (padding)
+    sub                 r3, r3, r0, lsl #2                             @ r3 = linesize  * 2 - width * 4 (padding)
     sub                 r5, r5, r0                                     @ r5 = linesizeY * 2 - width     (paddingY)
     sub                 r7, r7, r0                                     @ r7 = linesizeC     - width     (paddingC)
 .endm
 
+.macro load_args_nv21
+    load_args_nv12
+.endm
+
 .macro load_args_yuv420p
     push                {r4-r12, lr}
     vpush               {q4-q7}
@@ -238,8 +135,7 @@
     add                 r12, r4, r5                                    @ r12 = srcY + linesizeY (srcY2)
     lsl                 r3, r3, #1
     lsl                 r5, r5, #1
-    lsl                 r8, r0, #2
-    sub                 r3, r3, r8                                     @ r3 = linesize  * 2 - width * 4 (padding)
+    sub                 r3, r3, r0, lsl #2                             @ r3 = linesize  * 2 - width * 4 (padding)
     sub                 r5, r5, r0                                     @ r5 = linesizeY * 2 - width     (paddingY)
     ldr                 r10,[sp, #120]                                 @ r10 = srcV
 .endm
@@ -257,151 +153,128 @@
     ldr                 r10,[sp, #136]                                 @ r10 = y_coeff
     vdup.16             d0, r10                                        @ d0  = y_coeff
     vld1.16             {d1}, [r8]                                     @ d1  = *table
-    add                 r11, r2, r3                                    @ r11 = dst + linesize (dst2)
-    lsl                 r8, r0, #2
-    sub                 r3, r3, r8                                     @ r3 = linesize  * 2 - width * 4 (padding)
-    sub                 r5, r5, r0                                     @ r5 = linesizeY * 2 - width     (paddingY)
-    sub                 r7, r7, r0, lsr #1                             @ r7 = linesizeU     - width / 2 (paddingU)
-    sub                 r12,r12,r0, lsr #1                             @ r12 = linesizeV    - width / 2 (paddingV)
+    sub                 r3, r3, r0, lsl #2                             @ r3  = linesize  - width * 4 (padding)
+    sub                 r5, r5, r0                                     @ r5  = linesizeY - width     (paddingY)
+    sub                 r7, r7, r0, lsr #1                             @ r7  = linesizeU - width / 2 (paddingU)
+    sub                 r12,r12,r0, lsr #1                             @ r12 = linesizeV - width / 2 (paddingV)
     ldr                 r10,[sp, #120]                                 @ r10 = srcV
 .endm
 
-.macro declare_func ifmt ofmt precision
-function ff_\ifmt\()_to_\ofmt\()_neon_\precision\(), export=1
-
-.ifc \ifmt,nv12
-    load_args_nvx
-.endif
-
-.ifc \ifmt,nv21
-    load_args_nvx
-.endif
-
-.ifc \ifmt,yuv420p
-    load_args_yuv420p
-.endif
-
-
-.ifc \ifmt,yuv422p
-    load_args_yuv422p
-.endif
-
-1:
-    mov                 r8, r0                                         @ r8 = width
-2:
-    pld [r6, #64*3]
-    pld [r4, #64*3]
-
-    vmov.i8             d10, #128
-
-.ifc \ifmt,nv12
+.macro load_chroma_nv12
     pld [r12, #64*3]
 
     vld2.8              {d2, d3}, [r6]!                                @ q1: interleaved chroma line
-    vsubl.u8            q14, d2, d10                                   @ q14 = U - 128
-    vsubl.u8            q15, d3, d10                                   @ q15 = V - 128
-
-    process_2l_16px_\precision \ofmt
-.endif
+    vshll.u8            q14, d2, #3                                    @ q14 = U * (1 << 3)
+    vshll.u8            q15, d3, #3                                    @ q15 = V * (1 << 3)
+.endm
 
-.ifc \ifmt,nv21
+.macro load_chroma_nv21
     pld [r12, #64*3]
 
     vld2.8              {d2, d3}, [r6]!                                @ q1: interleaved chroma line
-    vsubl.u8            q14, d3, d10                                   @ q14 = U - 128
-    vsubl.u8            q15, d2, d10                                   @ q15 = V - 128
-
-    process_2l_16px_\precision \ofmt
-.endif
+    vshll.u8            q14, d3, #3                                    @ q14 = U * (1 << 3)
+    vshll.u8            q15, d2, #3                                    @ q15 = V * (1 << 3)
+.endm
 
-.ifc \ifmt,yuv420p
+.macro load_chroma_yuv420p
     pld [r10, #64*3]
     pld [r12, #64*3]
 
     vld1.8              d2, [r6]!                                      @ d2: chroma red line
     vld1.8              d3, [r10]!                                     @ d3: chroma blue line
-    vsubl.u8            q14, d2, d10                                   @ q14 = U - 128
-    vsubl.u8            q15, d3, d10                                   @ q15 = V - 128
-
-    process_2l_16px_\precision \ofmt
-.endif
+    vshll.u8            q14, d2, #3                                    @ q14 = U * (1 << 3)
+    vshll.u8            q15, d3, #3                                    @ q15 = V * (1 << 3)
+.endm
 
-.ifc \ifmt,yuv422p
+.macro load_chroma_yuv422p
     pld [r10, #64*3]
 
     vld1.8              d2, [r6]!                                      @ d2: chroma red line
     vld1.8              d3, [r10]!                                     @ d3: chroma blue line
-    vsubl.u8            q14, d2, d10                                   @ q14 = U - 128
-    vsubl.u8            q15, d3, d10                                   @ q15 = V - 128
-
-    process_1l_16px_\precision \ofmt
-.endif
-
-    subs                r8, r8, #16                                    @ width -= 16
-    bgt                 2b
-
-    add                 r2, r2, r3                                     @ dst   += padding
-    add                 r4, r4, r5                                     @ srcY  += paddingY
+    vshll.u8            q14, d2, #3                                    @ q14 = U * (1 << 3)
+    vshll.u8            q15, d3, #3                                    @ q15 = V * (1 << 3)
+.endm
 
-.ifc \ifmt,nv12
+.macro increment_and_test_nv12
     add                 r11, r11, r3                                   @ dst2  += padding
     add                 r12, r12, r5                                   @ srcY2 += paddingY
-
     add                 r6, r6, r7                                     @ srcC  += paddingC
-
     subs                r1, r1, #2                                     @ height -= 2
-.endif
-
-.ifc \ifmt,nv21
-    add                 r11, r11, r3                                   @ dst2  += padding
-    add                 r12, r12, r5                                   @ srcY2 += paddingY
+.endm
 
-    add                 r6, r6, r7                                     @ srcC  += paddingC
-    subs                r1, r1, #2                                     @ height -= 2
-.endif
+.macro increment_and_test_nv21
+    increment_and_test_nv12
+.endm
 
-.ifc \ifmt,yuv420p
+.macro increment_and_test_yuv420p
     add                 r11, r11, r3                                   @ dst2  += padding
     add                 r12, r12, r5                                   @ srcY2 += paddingY
-
     ldr                 r7, [sp, #116]                                 @ r7     = linesizeU
     sub                 r7, r7, r0, lsr #1                             @ r7     = linesizeU - width / 2 (paddingU)
     add                 r6, r6, r7                                     @ srcU  += paddingU
-
     ldr                 r7, [sp, #124]                                 @ r7     = linesizeV
     sub                 r7, r7, r0, lsr #1                             @ r7     = linesizeV - width / 2 (paddingV)
     add                 r10, r10, r7                                   @ srcV  += paddingV
-
     subs                r1, r1, #2                                     @ height -= 2
-.endif
+.endm
 
-.ifc \ifmt,yuv422p
+.macro increment_and_test_yuv422p
     add                 r6, r6, r7                                     @ srcU  += paddingU
     add                 r10,r10,r12                                    @ srcV  += paddingV
-
     subs                r1, r1, #1                                     @ height -= 1
-.endif
+.endm
 
-    bgt                 1b
+.macro process_nv12 ofmt
+    process_2l \ofmt
+.endm
+
+.macro process_nv21 ofmt
+    process_2l \ofmt
+.endm
+
+.macro process_yuv420p ofmt
+    process_2l \ofmt
+.endm
+
+.macro process_yuv422p ofmt
+    process_1l \ofmt
+.endm
 
+.macro declare_func ifmt ofmt
+function ff_\ifmt\()_to_\ofmt\()_neon, export=1
+    load_args_\ifmt
+    vmov.u16            q11, #1024                                     @ q11 = 128 * (1 << 3)
+    vdup.16             q12, r9                                        @ q12 = y_offset
+    vmov                d26, d0                                        @ q13 = y_coeff
+    vmov                d27, d0                                        @ q13 = y_coeff
+1:
+    mov                 r8, r0                                         @ r8 = width
+2:
+    pld [r6, #64*3]
+    pld [r4, #64*3]
+    vmov.i8             d10, #128
+    load_chroma_\ifmt
+    process_\ifmt \ofmt
+    subs                r8, r8, #16                                    @ width -= 16
+    bgt                 2b
+    add                 r2, r2, r3                                     @ dst   += padding
+    add                 r4, r4, r5                                     @ srcY  += paddingY
+    increment_and_test_\ifmt
+    bgt                 1b
     vpop                {q4-q7}
     pop                 {r4-r12, lr}
     mov                 pc, lr
 endfunc
 .endm
 
-.macro declare_rgb_funcs ifmt precision
-    declare_func \ifmt, argb, \precision
-    declare_func \ifmt, rgba, \precision
-    declare_func \ifmt, abgr, \precision
-    declare_func \ifmt, bgra, \precision
+.macro declare_rgb_funcs ifmt
+    declare_func \ifmt, argb
+    declare_func \ifmt, rgba
+    declare_func \ifmt, abgr
+    declare_func \ifmt, bgra
 .endm
 
-declare_rgb_funcs nv12, 16
-declare_rgb_funcs nv21, 16
-declare_rgb_funcs nv12, 32
-declare_rgb_funcs nv21, 32
-declare_rgb_funcs yuv420p, 16
-declare_rgb_funcs yuv420p, 32
-declare_rgb_funcs yuv422p, 16
-declare_rgb_funcs yuv422p, 32
+declare_rgb_funcs nv12
+declare_rgb_funcs nv21
+declare_rgb_funcs yuv420p
+declare_rgb_funcs yuv422p
diff --git a/libswscale/colorspace-test.c b/libswscale/colorspace-test.c
deleted file mode 100644
index f6e0c92..0000000
--- a/libswscale/colorspace-test.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2002 Michael Niedermayer <michaelni at gmx.at>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <stdio.h>
-#include <string.h>              /* for memset() */
-#include <stdlib.h>
-#include <inttypes.h>
-
-#include "swscale.h"
-#include "rgb2rgb.h"
-#include "libavutil/mem.h"
-
-#define SIZE    1000
-#define srcByte 0x55
-#define dstByte 0xBB
-
-#define FUNC(s, d, n) { s, d, #n, n }
-
-int main(int argc, char **argv)
-{
-    int i, funcNum;
-    uint8_t *srcBuffer = av_malloc(SIZE);
-    uint8_t *dstBuffer = av_malloc(SIZE);
-    int failedNum      = 0;
-    int passedNum      = 0;
-
-    if (!srcBuffer || !dstBuffer)
-        return -1;
-
-    av_log(NULL, AV_LOG_INFO, "memory corruption test ...\n");
-    ff_sws_rgb2rgb_init();
-
-    for (funcNum = 0; ; funcNum++) {
-        struct func_info_s {
-            int src_bpp;
-            int dst_bpp;
-            const char *name;
-            void (*func)(const uint8_t *src, uint8_t *dst, int src_size);
-        } func_info[] = {
-            FUNC(2, 2, rgb12to15),
-            FUNC(2, 2, rgb15to16),
-            FUNC(2, 3, rgb15to24),
-            FUNC(2, 4, rgb15to32),
-            FUNC(2, 3, rgb16to24),
-            FUNC(2, 4, rgb16to32),
-            FUNC(3, 2, rgb24to15),
-            FUNC(3, 2, rgb24to16),
-            FUNC(3, 4, rgb24to32),
-            FUNC(4, 2, rgb32to15),
-            FUNC(4, 2, rgb32to16),
-            FUNC(4, 3, rgb32to24),
-            FUNC(2, 2, rgb16to15),
-            FUNC(2, 2, rgb12tobgr12),
-            FUNC(2, 2, rgb15tobgr15),
-            FUNC(2, 2, rgb15tobgr16),
-            FUNC(2, 3, rgb15tobgr24),
-            FUNC(2, 4, rgb15tobgr32),
-            FUNC(2, 2, rgb16tobgr15),
-            FUNC(2, 2, rgb16tobgr16),
-            FUNC(2, 3, rgb16tobgr24),
-            FUNC(2, 4, rgb16tobgr32),
-            FUNC(3, 2, rgb24tobgr15),
-            FUNC(3, 2, rgb24tobgr16),
-            FUNC(3, 3, rgb24tobgr24),
-            FUNC(3, 4, rgb24tobgr32),
-            FUNC(4, 2, rgb32tobgr15),
-            FUNC(4, 2, rgb32tobgr16),
-            FUNC(4, 3, rgb32tobgr24),
-            FUNC(4, 4, shuffle_bytes_2103), /* rgb32tobgr32 */
-            FUNC(6, 6, rgb48tobgr48_nobswap),
-            FUNC(6, 6, rgb48tobgr48_bswap),
-            FUNC(8, 6, rgb64to48_nobswap),
-            FUNC(8, 6, rgb64to48_bswap),
-            FUNC(8, 6, rgb64tobgr48_nobswap),
-            FUNC(8, 6, rgb64tobgr48_bswap),
-            FUNC(0, 0, NULL)
-        };
-        int width;
-        int failed = 0;
-        int srcBpp = 0;
-        int dstBpp = 0;
-
-        if (!func_info[funcNum].func)
-            break;
-
-        av_log(NULL, AV_LOG_INFO, ".");
-        memset(srcBuffer, srcByte, SIZE);
-
-        for (width = 63; width > 0; width--) {
-            int dstOffset;
-            for (dstOffset = 128; dstOffset < 196; dstOffset += 4) {
-                int srcOffset;
-                memset(dstBuffer, dstByte, SIZE);
-
-                for (srcOffset = 128; srcOffset < 196; srcOffset += 4) {
-                    uint8_t *src     = srcBuffer + srcOffset;
-                    uint8_t *dst     = dstBuffer + dstOffset;
-                    const char *name = NULL;
-
-                    // don't fill the screen with shit ...
-                    if (failed)
-                        break;
-
-                    srcBpp = func_info[funcNum].src_bpp;
-                    dstBpp = func_info[funcNum].dst_bpp;
-                    name   = func_info[funcNum].name;
-
-                    func_info[funcNum].func(src, dst, width * srcBpp);
-
-                    if (!srcBpp)
-                        break;
-
-                    for (i = 0; i < SIZE; i++) {
-                        if (srcBuffer[i] != srcByte) {
-                            av_log(NULL, AV_LOG_INFO,
-                                   "src damaged at %d w:%d src:%d dst:%d %s\n",
-                                   i, width, srcOffset, dstOffset, name);
-                            failed = 1;
-                            break;
-                        }
-                    }
-                    for (i = 0; i < dstOffset; i++) {
-                        if (dstBuffer[i] != dstByte) {
-                            av_log(NULL, AV_LOG_INFO,
-                                   "dst damaged at %d w:%d src:%d dst:%d %s\n",
-                                   i, width, srcOffset, dstOffset, name);
-                            failed = 1;
-                            break;
-                        }
-                    }
-                    for (i = dstOffset + width * dstBpp; i < SIZE; i++) {
-                        if (dstBuffer[i] != dstByte) {
-                            av_log(NULL, AV_LOG_INFO,
-                                   "dst damaged at %d w:%d src:%d dst:%d %s\n",
-                                   i, width, srcOffset, dstOffset, name);
-                            failed = 1;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-        if (failed)
-            failedNum++;
-        else if (srcBpp)
-            passedNum++;
-    }
-
-    av_log(NULL, AV_LOG_INFO,
-           "\n%d converters passed, %d converters randomly overwrote memory\n",
-           passedNum, failedNum);
-    return failedNum;
-}
diff --git a/libswscale/input.c b/libswscale/input.c
index ac76aee..14ab5ab 100644
--- a/libswscale/input.c
+++ b/libswscale/input.c
@@ -978,9 +978,11 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
     case AV_PIX_FMT_GBRP9LE:
         c->readChrPlanar = planar_rgb9le_to_uv;
         break;
+    case AV_PIX_FMT_GBRAP10LE:
     case AV_PIX_FMT_GBRP10LE:
         c->readChrPlanar = planar_rgb10le_to_uv;
         break;
+    case AV_PIX_FMT_GBRAP12LE:
     case AV_PIX_FMT_GBRP12LE:
         c->readChrPlanar = planar_rgb12le_to_uv;
         break;
@@ -994,9 +996,11 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
     case AV_PIX_FMT_GBRP9BE:
         c->readChrPlanar = planar_rgb9be_to_uv;
         break;
+    case AV_PIX_FMT_GBRAP10BE:
     case AV_PIX_FMT_GBRP10BE:
         c->readChrPlanar = planar_rgb10be_to_uv;
         break;
+    case AV_PIX_FMT_GBRAP12BE:
     case AV_PIX_FMT_GBRP12BE:
         c->readChrPlanar = planar_rgb12be_to_uv;
         break;
@@ -1256,9 +1260,13 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
     case AV_PIX_FMT_GBRP9LE:
         c->readLumPlanar = planar_rgb9le_to_y;
         break;
+    case AV_PIX_FMT_GBRAP10LE:
+        c->readAlpPlanar = planar_rgb10le_to_a;
     case AV_PIX_FMT_GBRP10LE:
         c->readLumPlanar = planar_rgb10le_to_y;
         break;
+    case AV_PIX_FMT_GBRAP12LE:
+        c->readAlpPlanar = planar_rgb12le_to_a;
     case AV_PIX_FMT_GBRP12LE:
         c->readLumPlanar = planar_rgb12le_to_y;
         break;
@@ -1273,9 +1281,13 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
     case AV_PIX_FMT_GBRP9BE:
         c->readLumPlanar = planar_rgb9be_to_y;
         break;
+    case AV_PIX_FMT_GBRAP10BE:
+        c->readAlpPlanar = planar_rgb10be_to_a;
     case AV_PIX_FMT_GBRP10BE:
         c->readLumPlanar = planar_rgb10be_to_y;
         break;
+    case AV_PIX_FMT_GBRAP12BE:
+        c->readAlpPlanar = planar_rgb12be_to_a;
     case AV_PIX_FMT_GBRP12BE:
         c->readLumPlanar = planar_rgb12be_to_y;
         break;
@@ -1476,7 +1488,7 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c)
         c->lumToYV12 = p010BEToY_c;
         break;
     }
-    if (c->alpPixBuf) {
+    if (c->needAlpha) {
         if (is16BPS(srcFormat) || isNBPS(srcFormat)) {
             if (HAVE_BIGENDIAN == !isBE(srcFormat))
                 c->alpToYV12 = bswap16Y_c;
diff --git a/libswscale/output.c b/libswscale/output.c
index 0c763c3..de40e4b 100644
--- a/libswscale/output.c
+++ b/libswscale/output.c
@@ -722,7 +722,7 @@ yuv2rgba64_X_c_template(SwsContext *c, const int16_t *lumFilter,
             A2 += 0x20002000;
         }
 
-        // 8bit: 12+15=27; 16-bit: 12+19=31
+        // 8 bits: 12+15=27; 16 bits: 12+19=31
         Y1 >>= 14; // 10
         Y1 += 0x10000;
         Y2 >>= 14;
@@ -730,20 +730,20 @@ yuv2rgba64_X_c_template(SwsContext *c, const int16_t *lumFilter,
         U  >>= 14;
         V  >>= 14;
 
-        // 8bit: 27 -> 17bit, 16bit: 31 - 14 = 17bit
+        // 8 bits: 27 -> 17 bits, 16 bits: 31 - 14 = 17 bits
         Y1 -= c->yuv2rgb_y_offset;
         Y2 -= c->yuv2rgb_y_offset;
         Y1 *= c->yuv2rgb_y_coeff;
         Y2 *= c->yuv2rgb_y_coeff;
         Y1 += 1 << 13; // 21
         Y2 += 1 << 13;
-        // 8bit: 17 + 13bit = 30bit, 16bit: 17 + 13bit = 30bit
+        // 8 bits: 17 + 13 bits = 30 bits, 16 bits: 17 + 13 bits = 30 bits
 
         R = V * c->yuv2rgb_v2r_coeff;
         G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
         B =                            U * c->yuv2rgb_u2b_coeff;
 
-        // 8bit: 30 - 22 = 8bit, 16bit: 30bit - 14 = 16bit
+        // 8 bits: 30 - 22 = 8 bits, 16 bits: 30 bits - 14 = 16 bits
         output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
         output_pixel(&dest[1], av_clip_uintp2(  G + Y1, 30) >> 14);
         output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
@@ -1294,7 +1294,7 @@ yuv2rgb_write(uint8_t *_dest, int i, int Y1, int Y2,
 
         dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1];
         dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2];
-    } else /* 8/4-bit */ {
+    } else /* 8/4 bits */ {
         uint8_t *dest = (uint8_t *) _dest;
         const uint8_t *r = (const uint8_t *) _r;
         const uint8_t *g = (const uint8_t *) _g;
@@ -1513,8 +1513,8 @@ static void name ## ext ## _1_c(SwsContext *c, const int16_t *buf0, \
 }
 
 #if CONFIG_SMALL
-YUV2RGBWRAPPER(yuv2rgb,,  32_1,  AV_PIX_FMT_RGB32_1,   CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
-YUV2RGBWRAPPER(yuv2rgb,,  32,    AV_PIX_FMT_RGB32,     CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
+YUV2RGBWRAPPER(yuv2rgb,,  32_1,  AV_PIX_FMT_RGB32_1,   CONFIG_SWSCALE_ALPHA && c->needAlpha)
+YUV2RGBWRAPPER(yuv2rgb,,  32,    AV_PIX_FMT_RGB32,     CONFIG_SWSCALE_ALPHA && c->needAlpha)
 #else
 #if CONFIG_SWSCALE_ALPHA
 YUV2RGBWRAPPER(yuv2rgb,, a32_1,  AV_PIX_FMT_RGB32_1,   1)
@@ -1823,10 +1823,10 @@ yuv2rgb_full_1_c_template(SwsContext *c, const int16_t *buf0,
 }
 
 #if CONFIG_SMALL
-YUV2RGBWRAPPER(yuv2, rgb_full, bgra32_full, AV_PIX_FMT_BGRA,  CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
-YUV2RGBWRAPPER(yuv2, rgb_full, abgr32_full, AV_PIX_FMT_ABGR,  CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
-YUV2RGBWRAPPER(yuv2, rgb_full, rgba32_full, AV_PIX_FMT_RGBA,  CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
-YUV2RGBWRAPPER(yuv2, rgb_full, argb32_full, AV_PIX_FMT_ARGB,  CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
+YUV2RGBWRAPPER(yuv2, rgb_full, bgra32_full, AV_PIX_FMT_BGRA,  CONFIG_SWSCALE_ALPHA && c->needAlpha)
+YUV2RGBWRAPPER(yuv2, rgb_full, abgr32_full, AV_PIX_FMT_ABGR,  CONFIG_SWSCALE_ALPHA && c->needAlpha)
+YUV2RGBWRAPPER(yuv2, rgb_full, rgba32_full, AV_PIX_FMT_RGBA,  CONFIG_SWSCALE_ALPHA && c->needAlpha)
+YUV2RGBWRAPPER(yuv2, rgb_full, argb32_full, AV_PIX_FMT_ARGB,  CONFIG_SWSCALE_ALPHA && c->needAlpha)
 #else
 #if CONFIG_SWSCALE_ALPHA
 YUV2RGBWRAPPER(yuv2, rgb_full, bgra32_full, AV_PIX_FMT_BGRA,  1)
@@ -2119,7 +2119,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
                 *yuv2packed1 = yuv2rgba32_full_1_c;
 #else
 #if CONFIG_SWSCALE_ALPHA
-                if (c->alpPixBuf) {
+                if (c->needAlpha) {
                     *yuv2packedX = yuv2rgba32_full_X_c;
                     *yuv2packed2 = yuv2rgba32_full_2_c;
                     *yuv2packed1 = yuv2rgba32_full_1_c;
@@ -2139,7 +2139,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
                 *yuv2packed1 = yuv2argb32_full_1_c;
 #else
 #if CONFIG_SWSCALE_ALPHA
-                if (c->alpPixBuf) {
+                if (c->needAlpha) {
                     *yuv2packedX = yuv2argb32_full_X_c;
                     *yuv2packed2 = yuv2argb32_full_2_c;
                     *yuv2packed1 = yuv2argb32_full_1_c;
@@ -2159,7 +2159,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
                 *yuv2packed1 = yuv2bgra32_full_1_c;
 #else
 #if CONFIG_SWSCALE_ALPHA
-                if (c->alpPixBuf) {
+                if (c->needAlpha) {
                     *yuv2packedX = yuv2bgra32_full_X_c;
                     *yuv2packed2 = yuv2bgra32_full_2_c;
                     *yuv2packed1 = yuv2bgra32_full_1_c;
@@ -2179,7 +2179,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
                 *yuv2packed1 = yuv2abgr32_full_1_c;
 #else
 #if CONFIG_SWSCALE_ALPHA
-                if (c->alpPixBuf) {
+                if (c->needAlpha) {
                     *yuv2packedX = yuv2abgr32_full_X_c;
                     *yuv2packed2 = yuv2abgr32_full_2_c;
                     *yuv2packed1 = yuv2abgr32_full_1_c;
@@ -2194,7 +2194,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
                 break;
         case AV_PIX_FMT_RGBA64LE:
 #if CONFIG_SWSCALE_ALPHA
-            if (c->alpPixBuf) {
+            if (c->needAlpha) {
                 *yuv2packedX = yuv2rgba64le_full_X_c;
                 *yuv2packed2 = yuv2rgba64le_full_2_c;
                 *yuv2packed1 = yuv2rgba64le_full_1_c;
@@ -2208,7 +2208,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
             break;
         case AV_PIX_FMT_RGBA64BE:
 #if CONFIG_SWSCALE_ALPHA
-            if (c->alpPixBuf) {
+            if (c->needAlpha) {
                 *yuv2packedX = yuv2rgba64be_full_X_c;
                 *yuv2packed2 = yuv2rgba64be_full_2_c;
                 *yuv2packed1 = yuv2rgba64be_full_1_c;
@@ -2222,7 +2222,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
             break;
         case AV_PIX_FMT_BGRA64LE:
 #if CONFIG_SWSCALE_ALPHA
-            if (c->alpPixBuf) {
+            if (c->needAlpha) {
                 *yuv2packedX = yuv2bgra64le_full_X_c;
                 *yuv2packed2 = yuv2bgra64le_full_2_c;
                 *yuv2packed1 = yuv2bgra64le_full_1_c;
@@ -2236,7 +2236,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
             break;
         case AV_PIX_FMT_BGRA64BE:
 #if CONFIG_SWSCALE_ALPHA
-            if (c->alpPixBuf) {
+            if (c->needAlpha) {
                 *yuv2packedX = yuv2bgra64be_full_X_c;
                 *yuv2packed2 = yuv2bgra64be_full_2_c;
                 *yuv2packed1 = yuv2bgra64be_full_1_c;
@@ -2321,7 +2321,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
         switch (dstFormat) {
         case AV_PIX_FMT_RGBA64LE:
 #if CONFIG_SWSCALE_ALPHA
-            if (c->alpPixBuf) {
+            if (c->needAlpha) {
                 *yuv2packed1 = yuv2rgba64le_1_c;
                 *yuv2packed2 = yuv2rgba64le_2_c;
                 *yuv2packedX = yuv2rgba64le_X_c;
@@ -2335,7 +2335,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
             break;
         case AV_PIX_FMT_RGBA64BE:
 #if CONFIG_SWSCALE_ALPHA
-            if (c->alpPixBuf) {
+            if (c->needAlpha) {
                 *yuv2packed1 = yuv2rgba64be_1_c;
                 *yuv2packed2 = yuv2rgba64be_2_c;
                 *yuv2packedX = yuv2rgba64be_X_c;
@@ -2349,7 +2349,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
             break;
         case AV_PIX_FMT_BGRA64LE:
 #if CONFIG_SWSCALE_ALPHA
-            if (c->alpPixBuf) {
+            if (c->needAlpha) {
                 *yuv2packed1 = yuv2bgra64le_1_c;
                 *yuv2packed2 = yuv2bgra64le_2_c;
                 *yuv2packedX = yuv2bgra64le_X_c;
@@ -2363,7 +2363,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
             break;
         case AV_PIX_FMT_BGRA64BE:
 #if CONFIG_SWSCALE_ALPHA
-            if (c->alpPixBuf) {
+            if (c->needAlpha) {
                 *yuv2packed1 = yuv2bgra64be_1_c;
                 *yuv2packed2 = yuv2bgra64be_2_c;
                 *yuv2packedX = yuv2bgra64be_X_c;
@@ -2403,7 +2403,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
             *yuv2packedX = yuv2rgb32_X_c;
 #else
 #if CONFIG_SWSCALE_ALPHA
-                if (c->alpPixBuf) {
+                if (c->needAlpha) {
                     *yuv2packed1 = yuv2rgba32_1_c;
                     *yuv2packed2 = yuv2rgba32_2_c;
                     *yuv2packedX = yuv2rgba32_X_c;
@@ -2424,7 +2424,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c,
                 *yuv2packedX = yuv2rgb32_1_X_c;
 #else
 #if CONFIG_SWSCALE_ALPHA
-                if (c->alpPixBuf) {
+                if (c->needAlpha) {
                     *yuv2packed1 = yuv2rgba32_1_1_c;
                     *yuv2packed2 = yuv2rgba32_1_2_c;
                     *yuv2packedX = yuv2rgba32_1_X_c;
diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c
index af9fc88..35a08c4 100644
--- a/libswscale/ppc/swscale_altivec.c
+++ b/libswscale/ppc/swscale_altivec.c
@@ -339,13 +339,13 @@ av_cold void ff_sws_init_swscale_ppc(SwsContext *c)
     }
     if (!is16BPS(dstFormat) && !is9_OR_10BPS(dstFormat) &&
         dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 &&
-        !c->alpPixBuf) {
+        !c->needAlpha) {
         c->yuv2planeX = yuv2planeX_altivec;
     }
 
     /* The following list of supported dstFormat values should
      * match what's found in the body of ff_yuv2packedX_altivec() */
-    if (!(c->flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->alpPixBuf) {
+    if (!(c->flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) {
         switch (c->dstFormat) {
         case AV_PIX_FMT_ABGR:
             c->yuv2packedX = ff_yuv2abgr_X_altivec;
diff --git a/libswscale/ppc/yuv2rgb_altivec.c b/libswscale/ppc/yuv2rgb_altivec.c
index 638706f..c1e2852 100644
--- a/libswscale/ppc/yuv2rgb_altivec.c
+++ b/libswscale/ppc/yuv2rgb_altivec.c
@@ -89,7 +89,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <inttypes.h>
-#include <assert.h>
 
 #include "config.h"
 #include "libswscale/rgb2rgb.h"
@@ -142,7 +141,6 @@ typedef signed char   sbyte;
  *           brgb|rgbr|gbrg|brgb
  *           1001 0010 0100 1001
  *           a67b 89cA BdCD eEFf
- *
  */
 static const vector unsigned char
     perm_rgb_0 = { 0x00, 0x01, 0x10, 0x02, 0x03, 0x11, 0x04, 0x05,
diff --git a/libswscale/slice.c b/libswscale/slice.c
index 66fe413..e14456f 100644
--- a/libswscale/slice.c
+++ b/libswscale/slice.c
@@ -159,9 +159,9 @@ int ff_init_slice_from_src(SwsSlice * s, uint8_t *src[4], int stride[4], int src
                         lumY + lumH};
 
     const uint8_t *src_[4] = {src[0] + (relative ? 0 : start[0]) * stride[0],
-                              src[1] + (relative ? 0 : start[1]) * stride[0],
-                              src[2] + (relative ? 0 : start[2]) * stride[0],
-                              src[3] + (relative ? 0 : start[3]) * stride[0]};
+                              src[1] + (relative ? 0 : start[1]) * stride[1],
+                              src[2] + (relative ? 0 : start[2]) * stride[2],
+                              src[3] + (relative ? 0 : start[3]) * stride[3]};
 
     s->width = srcW;
 
@@ -210,6 +210,42 @@ static void fill_ones(SwsSlice *s, int n, int is16bit)
     }
 }
 
+/*
+ Calculates the minimum ring buffer size, it should be able to store vFilterSize
+ more n lines where n is the max difference between each adjacent slice which
+ outputs a line.
+ The n lines are needed only when there is not enough src lines to output a single
+ dst line, then we should buffer these lines to process them on the next call to scale.
+*/
+static void get_min_buffer_size(SwsContext *c, int *out_lum_size, int *out_chr_size)
+{
+    int lumY;
+    int dstH = c->dstH;
+    int chrDstH = c->chrDstH;
+    int *lumFilterPos = c->vLumFilterPos;
+    int *chrFilterPos = c->vChrFilterPos;
+    int lumFilterSize = c->vLumFilterSize;
+    int chrFilterSize = c->vChrFilterSize;
+    int chrSubSample = c->chrSrcVSubSample;
+
+    *out_lum_size = lumFilterSize;
+    *out_chr_size = chrFilterSize;
+
+    for (lumY = 0; lumY < dstH; lumY++) {
+        int chrY      = (int64_t)lumY * chrDstH / dstH;
+        int nextSlice = FFMAX(lumFilterPos[lumY] + lumFilterSize - 1,
+                              ((chrFilterPos[chrY] + chrFilterSize - 1)
+                               << chrSubSample));
+
+        nextSlice >>= chrSubSample;
+        nextSlice <<= chrSubSample;
+        (*out_lum_size) = FFMAX((*out_lum_size), nextSlice - lumFilterPos[lumY]);
+        (*out_chr_size) = FFMAX((*out_chr_size), (nextSlice >> chrSubSample) - chrFilterPos[chrY]);
+    }
+}
+
+
+
 int ff_init_filters(SwsContext * c)
 {
     int i;
@@ -226,6 +262,13 @@ int ff_init_filters(SwsContext * c)
     uint32_t * pal = usePal(c->srcFormat) ? c->pal_yuv : (uint32_t*)c->input_rgb2yuv_table;
     int res = 0;
 
+    int lumBufSize;
+    int chrBufSize;
+
+    get_min_buffer_size(c, &lumBufSize, &chrBufSize);
+    lumBufSize = FFMAX(lumBufSize, c->vLumFilterSize + MAX_LINES_AHEAD);
+    chrBufSize = FFMAX(chrBufSize, c->vChrFilterSize + MAX_LINES_AHEAD);
+
     if (c->dstBpc == 16)
         dst_stride <<= 1;
 
@@ -248,13 +291,13 @@ int ff_init_filters(SwsContext * c)
     res = alloc_slice(&c->slice[0], c->srcFormat, c->srcH, c->chrSrcH, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
     if (res < 0) goto cleanup;
     for (i = 1; i < c->numSlice-2; ++i) {
-        res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize + MAX_LINES_AHEAD, c->vChrFilterSize + MAX_LINES_AHEAD, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
+        res = alloc_slice(&c->slice[i], c->srcFormat, lumBufSize, chrBufSize, c->chrSrcHSubSample, c->chrSrcVSubSample, 0);
         if (res < 0) goto cleanup;
         res = alloc_lines(&c->slice[i], FFALIGN(c->srcW*2+78, 16), c->srcW);
         if (res < 0) goto cleanup;
     }
     // horizontal scaler output
-    res = alloc_slice(&c->slice[i], c->srcFormat, c->vLumFilterSize + MAX_LINES_AHEAD, c->vChrFilterSize + MAX_LINES_AHEAD, c->chrDstHSubSample, c->chrDstVSubSample, 1);
+    res = alloc_slice(&c->slice[i], c->srcFormat, lumBufSize, chrBufSize, c->chrDstHSubSample, c->chrDstVSubSample, 1);
     if (res < 0) goto cleanup;
     res = alloc_lines(&c->slice[i], dst_stride, c->dstW);
     if (res < 0) goto cleanup;
@@ -279,7 +322,7 @@ int ff_init_filters(SwsContext * c)
     if (need_lum_conv) {
         res = ff_init_desc_fmt_convert(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx], pal);
         if (res < 0) goto cleanup;
-        c->desc[index].alpha = c->alpPixBuf != 0;
+        c->desc[index].alpha = c->needAlpha;
         ++index;
         srcIdx = dstIdx;
     }
@@ -288,7 +331,7 @@ int ff_init_filters(SwsContext * c)
     dstIdx = FFMAX(num_ydesc, num_cdesc);
     res = ff_init_desc_hscale(&c->desc[index], &c->slice[srcIdx], &c->slice[dstIdx], c->hLumFilter, c->hLumFilterPos, c->hLumFilterSize, c->lumXInc);
     if (res < 0) goto cleanup;
-    c->desc[index].alpha = c->alpPixBuf != 0;
+    c->desc[index].alpha = c->needAlpha;
 
 
     ++index;
diff --git a/libswscale/swscale-test.c b/libswscale/swscale-test.c
deleted file mode 100644
index 4d8d08b..0000000
--- a/libswscale/swscale-test.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright (C) 2003-2011 Michael Niedermayer <michaelni at gmx.at>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-#include <stdarg.h>
-
-#undef HAVE_AV_CONFIG_H
-#include "libavutil/imgutils.h"
-#include "libavutil/mem.h"
-#include "libavutil/avutil.h"
-#include "libavutil/crc.h"
-#include "libavutil/pixdesc.h"
-#include "libavutil/lfg.h"
-#include "swscale.h"
-
-/* HACK Duplicated from swscale_internal.h.
- * Should be removed when a cleaner pixel format system exists. */
-#define isGray(x)                      \
-    ((x) == AV_PIX_FMT_GRAY8       ||     \
-     (x) == AV_PIX_FMT_YA8         ||     \
-     (x) == AV_PIX_FMT_GRAY16BE    ||     \
-     (x) == AV_PIX_FMT_GRAY16LE    ||     \
-     (x) == AV_PIX_FMT_YA16BE      ||     \
-     (x) == AV_PIX_FMT_YA16LE)
-#define hasChroma(x)                   \
-    (!(isGray(x)                ||     \
-       (x) == AV_PIX_FMT_MONOBLACK ||     \
-       (x) == AV_PIX_FMT_MONOWHITE))
-#define isALPHA(x)                     \
-    ((x) == AV_PIX_FMT_BGR32   ||         \
-     (x) == AV_PIX_FMT_BGR32_1 ||         \
-     (x) == AV_PIX_FMT_RGB32   ||         \
-     (x) == AV_PIX_FMT_RGB32_1 ||         \
-     (x) == AV_PIX_FMT_YUVA420P)
-
-static uint64_t getSSD(const uint8_t *src1, const uint8_t *src2, int stride1,
-                       int stride2, int w, int h)
-{
-    int x, y;
-    uint64_t ssd = 0;
-
-    for (y = 0; y < h; y++) {
-        for (x = 0; x < w; x++) {
-            int d = src1[x + y * stride1] - src2[x + y * stride2];
-            ssd += d * d;
-        }
-    }
-    return ssd;
-}
-
-struct Results {
-    uint64_t ssdY;
-    uint64_t ssdU;
-    uint64_t ssdV;
-    uint64_t ssdA;
-    uint32_t crc;
-};
-
-// test by ref -> src -> dst -> out & compare out against ref
-// ref & out are YV12
-static int doTest(uint8_t *ref[4], int refStride[4], int w, int h,
-                  enum AVPixelFormat srcFormat, enum AVPixelFormat dstFormat,
-                  int srcW, int srcH, int dstW, int dstH, int flags,
-                  struct Results *r)
-{
-    const AVPixFmtDescriptor *desc_yuva420p = av_pix_fmt_desc_get(AV_PIX_FMT_YUVA420P);
-    const AVPixFmtDescriptor *desc_src      = av_pix_fmt_desc_get(srcFormat);
-    const AVPixFmtDescriptor *desc_dst      = av_pix_fmt_desc_get(dstFormat);
-    static enum AVPixelFormat cur_srcFormat;
-    static int cur_srcW, cur_srcH;
-    static uint8_t *src[4];
-    static int srcStride[4];
-    uint8_t *dst[4] = { 0 };
-    uint8_t *out[4] = { 0 };
-    int dstStride[4] = {0};
-    int i;
-    uint64_t ssdY, ssdU = 0, ssdV = 0, ssdA = 0;
-    struct SwsContext *dstContext = NULL, *outContext = NULL;
-    uint32_t crc = 0;
-    int res      = 0;
-
-    if (cur_srcFormat != srcFormat || cur_srcW != srcW || cur_srcH != srcH) {
-        struct SwsContext *srcContext = NULL;
-        int p;
-
-        for (p = 0; p < 4; p++)
-            av_freep(&src[p]);
-
-        res = av_image_fill_linesizes(srcStride, srcFormat, srcW);
-        if (res < 0) {
-            fprintf(stderr, "av_image_fill_linesizes failed\n");
-            goto end;
-        }
-        for (p = 0; p < 4; p++) {
-            srcStride[p] = FFALIGN(srcStride[p], 16);
-            if (srcStride[p])
-                src[p] = av_mallocz(srcStride[p] * srcH + 16);
-            if (srcStride[p] && !src[p]) {
-                perror("Malloc");
-                res = -1;
-                goto end;
-            }
-        }
-        srcContext = sws_getContext(w, h, AV_PIX_FMT_YUVA420P, srcW, srcH,
-                                    srcFormat, SWS_BILINEAR, NULL, NULL, NULL);
-        if (!srcContext) {
-            fprintf(stderr, "Failed to get %s ---> %s\n",
-                    desc_yuva420p->name,
-                    desc_src->name);
-            res = -1;
-            goto end;
-        }
-        sws_scale(srcContext, (const uint8_t * const*)ref, refStride, 0, h, src, srcStride);
-        sws_freeContext(srcContext);
-
-        cur_srcFormat = srcFormat;
-        cur_srcW      = srcW;
-        cur_srcH      = srcH;
-    }
-
-    res = av_image_fill_linesizes(dstStride, dstFormat, dstW);
-    if (res < 0) {
-        fprintf(stderr, "av_image_fill_linesizes failed\n");
-        goto end;
-    }
-
-    for (i = 0; i < 4; i++) {
-        /* Image buffers passed into libswscale can be allocated any way you
-         * prefer, as long as they're aligned enough for the architecture, and
-         * they're freed appropriately (such as using av_free for buffers
-         * allocated with av_malloc). */
-        /* An extra 16 bytes is being allocated because some scalers may write
-         * out of bounds. */
-        dstStride[i] = FFALIGN(dstStride[i], 16);
-        if (dstStride[i])
-            dst[i] = av_mallocz(dstStride[i] * dstH + 16);
-        if (dstStride[i] && !dst[i]) {
-            perror("Malloc");
-            res = -1;
-
-            goto end;
-        }
-    }
-
-    dstContext = sws_getContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat,
-                                flags, NULL, NULL, NULL);
-    if (!dstContext) {
-        fprintf(stderr, "Failed to get %s ---> %s\n",
-                desc_src->name, desc_dst->name);
-        res = -1;
-        goto end;
-    }
-
-    printf(" %s %dx%d -> %s %3dx%3d flags=%2d",
-           desc_src->name, srcW, srcH,
-           desc_dst->name, dstW, dstH,
-           flags);
-    fflush(stdout);
-
-    sws_scale(dstContext, (const uint8_t * const*)src, srcStride, 0, srcH, dst, dstStride);
-
-    for (i = 0; i < 4 && dstStride[i]; i++)
-        crc = av_crc(av_crc_get_table(AV_CRC_32_IEEE), crc, dst[i],
-                     dstStride[i] * dstH);
-
-    if (r && crc == r->crc) {
-        ssdY = r->ssdY;
-        ssdU = r->ssdU;
-        ssdV = r->ssdV;
-        ssdA = r->ssdA;
-    } else {
-        for (i = 0; i < 4; i++) {
-            refStride[i] = FFALIGN(refStride[i], 16);
-            if (refStride[i])
-                out[i] = av_mallocz(refStride[i] * h);
-            if (refStride[i] && !out[i]) {
-                perror("Malloc");
-                res = -1;
-                goto end;
-            }
-        }
-        outContext = sws_getContext(dstW, dstH, dstFormat, w, h,
-                                    AV_PIX_FMT_YUVA420P, SWS_BILINEAR,
-                                    NULL, NULL, NULL);
-        if (!outContext) {
-            fprintf(stderr, "Failed to get %s ---> %s\n",
-                    desc_dst->name,
-                    desc_yuva420p->name);
-            res = -1;
-            goto end;
-        }
-        sws_scale(outContext, (const uint8_t * const*)dst, dstStride, 0, dstH, out, refStride);
-
-        ssdY = getSSD(ref[0], out[0], refStride[0], refStride[0], w, h);
-        if (hasChroma(srcFormat) && hasChroma(dstFormat)) {
-            //FIXME check that output is really gray
-            ssdU = getSSD(ref[1], out[1], refStride[1], refStride[1],
-                          (w + 1) >> 1, (h + 1) >> 1);
-            ssdV = getSSD(ref[2], out[2], refStride[2], refStride[2],
-                          (w + 1) >> 1, (h + 1) >> 1);
-        }
-        if (isALPHA(srcFormat) && isALPHA(dstFormat))
-            ssdA = getSSD(ref[3], out[3], refStride[3], refStride[3], w, h);
-
-        ssdY /= w * h;
-        ssdU /= w * h / 4;
-        ssdV /= w * h / 4;
-        ssdA /= w * h;
-
-        sws_freeContext(outContext);
-
-        for (i = 0; i < 4; i++)
-            if (refStride[i])
-                av_free(out[i]);
-    }
-
-    printf(" CRC=%08x SSD=%5"PRId64 ",%5"PRId64 ",%5"PRId64 ",%5"PRId64 "\n",
-           crc, ssdY, ssdU, ssdV, ssdA);
-
-end:
-    sws_freeContext(dstContext);
-
-    for (i = 0; i < 4; i++)
-        if (dstStride[i])
-            av_free(dst[i]);
-
-    return res;
-}
-
-static void selfTest(uint8_t *ref[4], int refStride[4], int w, int h,
-                     enum AVPixelFormat srcFormat_in,
-                     enum AVPixelFormat dstFormat_in)
-{
-    const int flags[] = { SWS_FAST_BILINEAR, SWS_BILINEAR, SWS_BICUBIC,
-                          SWS_X, SWS_POINT, SWS_AREA, 0 };
-    const int srcW   = w;
-    const int srcH   = h;
-    const int dstW[] = { srcW - srcW / 3, srcW, srcW + srcW / 3, 0 };
-    const int dstH[] = { srcH - srcH / 3, srcH, srcH + srcH / 3, 0 };
-    enum AVPixelFormat srcFormat, dstFormat;
-    const AVPixFmtDescriptor *desc_src, *desc_dst;
-
-    for (srcFormat = srcFormat_in != AV_PIX_FMT_NONE ? srcFormat_in : 0;
-         srcFormat < AV_PIX_FMT_NB; srcFormat++) {
-        if (!sws_isSupportedInput(srcFormat) ||
-            !sws_isSupportedOutput(srcFormat))
-            continue;
-
-        desc_src = av_pix_fmt_desc_get(srcFormat);
-
-        for (dstFormat = dstFormat_in != AV_PIX_FMT_NONE ? dstFormat_in : 0;
-             dstFormat < AV_PIX_FMT_NB; dstFormat++) {
-            int i, j, k;
-            int res = 0;
-
-            if (!sws_isSupportedInput(dstFormat) ||
-                !sws_isSupportedOutput(dstFormat))
-                continue;
-
-            desc_dst = av_pix_fmt_desc_get(dstFormat);
-
-            printf("%s -> %s\n", desc_src->name, desc_dst->name);
-            fflush(stdout);
-
-            for (k = 0; flags[k] && !res; k++)
-                for (i = 0; dstW[i] && !res; i++)
-                    for (j = 0; dstH[j] && !res; j++)
-                        res = doTest(ref, refStride, w, h,
-                                     srcFormat, dstFormat,
-                                     srcW, srcH, dstW[i], dstH[j], flags[k],
-                                     NULL);
-            if (dstFormat_in != AV_PIX_FMT_NONE)
-                break;
-        }
-        if (srcFormat_in != AV_PIX_FMT_NONE)
-            break;
-    }
-}
-
-static int fileTest(uint8_t *ref[4], int refStride[4], int w, int h, FILE *fp,
-                    enum AVPixelFormat srcFormat_in,
-                    enum AVPixelFormat dstFormat_in)
-{
-    char buf[256];
-
-    while (fgets(buf, sizeof(buf), fp)) {
-        struct Results r;
-        enum AVPixelFormat srcFormat;
-        char srcStr[12];
-        int srcW, srcH;
-        enum AVPixelFormat dstFormat;
-        char dstStr[12];
-        int dstW, dstH;
-        int flags;
-        int ret;
-
-        ret = sscanf(buf,
-                     " %12s %dx%d -> %12s %dx%d flags=%d CRC=%x"
-                     " SSD=%"SCNd64 ", %"SCNd64 ", %"SCNd64 ", %"SCNd64 "\n",
-                     srcStr, &srcW, &srcH, dstStr, &dstW, &dstH,
-                     &flags, &r.crc, &r.ssdY, &r.ssdU, &r.ssdV, &r.ssdA);
-        if (ret != 12) {
-            srcStr[0] = dstStr[0] = 0;
-            ret       = sscanf(buf, "%12s -> %12s\n", srcStr, dstStr);
-        }
-
-        srcFormat = av_get_pix_fmt(srcStr);
-        dstFormat = av_get_pix_fmt(dstStr);
-
-        if (srcFormat == AV_PIX_FMT_NONE || dstFormat == AV_PIX_FMT_NONE ||
-            srcW > 8192U || srcH > 8192U || dstW > 8192U || dstH > 8192U) {
-            fprintf(stderr, "malformed input file\n");
-            return -1;
-        }
-        if ((srcFormat_in != AV_PIX_FMT_NONE && srcFormat_in != srcFormat) ||
-            (dstFormat_in != AV_PIX_FMT_NONE && dstFormat_in != dstFormat))
-            continue;
-        if (ret != 12) {
-            printf("%s", buf);
-            continue;
-        }
-
-        doTest(ref, refStride, w, h,
-               srcFormat, dstFormat,
-               srcW, srcH, dstW, dstH, flags,
-               &r);
-    }
-
-    return 0;
-}
-
-#define W 96
-#define H 96
-
-int main(int argc, char **argv)
-{
-    enum AVPixelFormat srcFormat = AV_PIX_FMT_NONE;
-    enum AVPixelFormat dstFormat = AV_PIX_FMT_NONE;
-    uint8_t *rgb_data   = av_malloc(W * H * 4);
-    const uint8_t * const rgb_src[4] = { rgb_data, NULL, NULL, NULL };
-    int rgb_stride[4]   = { 4 * W, 0, 0, 0 };
-    uint8_t *data       = av_malloc(4 * W * H);
-    uint8_t *src[4]     = { data, data + W * H, data + W * H * 2, data + W * H * 3 };
-    int stride[4]       = { W, W, W, W };
-    int x, y;
-    struct SwsContext *sws;
-    AVLFG rand;
-    int res = -1;
-    int i;
-    FILE *fp = NULL;
-
-    if (!rgb_data || !data)
-        return -1;
-
-    for (i = 1; i < argc; i += 2) {
-        if (argv[i][0] != '-' || i + 1 == argc)
-            goto bad_option;
-        if (!strcmp(argv[i], "-ref")) {
-            fp = fopen(argv[i + 1], "r");
-            if (!fp) {
-                fprintf(stderr, "could not open '%s'\n", argv[i + 1]);
-                goto error;
-            }
-        } else if (!strcmp(argv[i], "-src")) {
-            srcFormat = av_get_pix_fmt(argv[i + 1]);
-            if (srcFormat == AV_PIX_FMT_NONE) {
-                fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
-                return -1;
-            }
-        } else if (!strcmp(argv[i], "-dst")) {
-            dstFormat = av_get_pix_fmt(argv[i + 1]);
-            if (dstFormat == AV_PIX_FMT_NONE) {
-                fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
-                return -1;
-            }
-        } else {
-bad_option:
-            fprintf(stderr, "bad option or argument missing (%s)\n", argv[i]);
-            goto error;
-        }
-    }
-
-    sws = sws_getContext(W / 12, H / 12, AV_PIX_FMT_RGB32, W, H,
-                         AV_PIX_FMT_YUVA420P, SWS_BILINEAR, NULL, NULL, NULL);
-
-    av_lfg_init(&rand, 1);
-
-    for (y = 0; y < H; y++)
-        for (x = 0; x < W * 4; x++)
-            rgb_data[ x + y * 4 * W] = av_lfg_get(&rand);
-    sws_scale(sws, rgb_src, rgb_stride, 0, H / 12, src, stride);
-    sws_freeContext(sws);
-    av_free(rgb_data);
-
-    if(fp) {
-        res = fileTest(src, stride, W, H, fp, srcFormat, dstFormat);
-        fclose(fp);
-    } else {
-        selfTest(src, stride, W, H, srcFormat, dstFormat);
-        res = 0;
-    }
-error:
-    av_free(data);
-
-    return res;
-}
diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index 8d20577..bbea0fe 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -52,24 +52,6 @@ DECLARE_ALIGNED(8, static const uint8_t, sws_pb_64)[8] = {
     64, 64, 64, 64, 64, 64, 64, 64
 };
 
-#ifndef NEW_FILTER
-static void gamma_convert(uint8_t * src[], int width, uint16_t *gamma)
-{
-    int i;
-    uint16_t *src1 = (uint16_t*)src[0];
-
-    for (i = 0; i < width; ++i) {
-        uint16_t r = AV_RL16(src1 + i*4 + 0);
-        uint16_t g = AV_RL16(src1 + i*4 + 1);
-        uint16_t b = AV_RL16(src1 + i*4 + 2);
-
-        AV_WL16(src1 + i*4 + 0, gamma[r]);
-        AV_WL16(src1 + i*4 + 1, gamma[g]);
-        AV_WL16(src1 + i*4 + 2, gamma[b]);
-    }
-}
-#endif
-
 static av_always_inline void fillPlane(uint8_t *plane, int stride, int width,
                                        int height, int y, uint8_t val)
 {
@@ -240,79 +222,6 @@ static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
         dst[i] = (dst[i]*(14071/4) + (33561947<<4)/4)>>12;
 }
 
-#ifndef NEW_FILTER
-// *** horizontal scale Y line to temp buffer
-static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth,
-                                     const uint8_t *src_in[4],
-                                     int srcW, int xInc,
-                                     const int16_t *hLumFilter,
-                                     const int32_t *hLumFilterPos,
-                                     int hLumFilterSize,
-                                     uint8_t *formatConvBuffer,
-                                     uint32_t *pal, int isAlpha)
-{
-    void (*toYV12)(uint8_t *, const uint8_t *, const uint8_t *, const uint8_t *, int, uint32_t *) =
-        isAlpha ? c->alpToYV12 : c->lumToYV12;
-    void (*convertRange)(int16_t *, int) = isAlpha ? NULL : c->lumConvertRange;
-    const uint8_t *src = src_in[isAlpha ? 3 : 0];
-
-    if (toYV12) {
-        toYV12(formatConvBuffer, src, src_in[1], src_in[2], srcW, pal);
-        src = formatConvBuffer;
-    } else if (c->readLumPlanar && !isAlpha) {
-        c->readLumPlanar(formatConvBuffer, src_in, srcW, c->input_rgb2yuv_table);
-        src = formatConvBuffer;
-    } else if (c->readAlpPlanar && isAlpha) {
-        c->readAlpPlanar(formatConvBuffer, src_in, srcW, NULL);
-        src = formatConvBuffer;
-    }
-
-    if (!c->hyscale_fast) {
-        c->hyScale(c, dst, dstWidth, src, hLumFilter,
-                   hLumFilterPos, hLumFilterSize);
-    } else { // fast bilinear upscale / crap downscale
-        c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc);
-    }
-
-    if (convertRange)
-        convertRange(dst, dstWidth);
-}
-
-static av_always_inline void hcscale(SwsContext *c, int16_t *dst1,
-                                     int16_t *dst2, int dstWidth,
-                                     const uint8_t *src_in[4],
-                                     int srcW, int xInc,
-                                     const int16_t *hChrFilter,
-                                     const int32_t *hChrFilterPos,
-                                     int hChrFilterSize,
-                                     uint8_t *formatConvBuffer, uint32_t *pal)
-{
-    const uint8_t *src1 = src_in[1], *src2 = src_in[2];
-    if (c->chrToYV12) {
-        uint8_t *buf2 = formatConvBuffer +
-                        FFALIGN(srcW*2+78, 16);
-        c->chrToYV12(formatConvBuffer, buf2, src_in[0], src1, src2, srcW, pal);
-        src1= formatConvBuffer;
-        src2= buf2;
-    } else if (c->readChrPlanar) {
-        uint8_t *buf2 = formatConvBuffer +
-                        FFALIGN(srcW*2+78, 16);
-        c->readChrPlanar(formatConvBuffer, buf2, src_in, srcW, c->input_rgb2yuv_table);
-        src1 = formatConvBuffer;
-        src2 = buf2;
-    }
-
-    if (!c->hcscale_fast) {
-        c->hcScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize);
-        c->hcScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize);
-    } else { // fast bilinear upscale / crap downscale
-        c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc);
-    }
-
-    if (c->chrConvertRange)
-        c->chrConvertRange(dst1, dst2, dstWidth);
-}
-#endif /* NEW_FILTER */
 
 #define DEBUG_SWSCALE_BUFFERS 0
 #define DEBUG_BUFFERS(...)                      \
@@ -325,46 +234,17 @@ static int swscale(SwsContext *c, const uint8_t *src[],
 {
     /* load a few things into local vars to make the code more readable?
      * and faster */
-#ifndef NEW_FILTER
-    const int srcW                   = c->srcW;
-#endif
     const int dstW                   = c->dstW;
     const int dstH                   = c->dstH;
-#ifndef NEW_FILTER
-    const int chrDstW                = c->chrDstW;
-    const int chrSrcW                = c->chrSrcW;
-    const int lumXInc                = c->lumXInc;
-    const int chrXInc                = c->chrXInc;
-#endif
+
     const enum AVPixelFormat dstFormat = c->dstFormat;
     const int flags                  = c->flags;
     int32_t *vLumFilterPos           = c->vLumFilterPos;
     int32_t *vChrFilterPos           = c->vChrFilterPos;
-#ifndef NEW_FILTER
-    int32_t *hLumFilterPos           = c->hLumFilterPos;
-    int32_t *hChrFilterPos           = c->hChrFilterPos;
-    int16_t *hLumFilter              = c->hLumFilter;
-    int16_t *hChrFilter              = c->hChrFilter;
-    int32_t *lumMmxFilter            = c->lumMmxFilter;
-    int32_t *chrMmxFilter            = c->chrMmxFilter;
-#endif
+
     const int vLumFilterSize         = c->vLumFilterSize;
     const int vChrFilterSize         = c->vChrFilterSize;
-#ifndef NEW_FILTER
-    const int hLumFilterSize         = c->hLumFilterSize;
-    const int hChrFilterSize         = c->hChrFilterSize;
-    int16_t **lumPixBuf              = c->lumPixBuf;
-    int16_t **chrUPixBuf             = c->chrUPixBuf;
-    int16_t **chrVPixBuf             = c->chrVPixBuf;
-#endif
-    int16_t **alpPixBuf              = c->alpPixBuf;
-    const int vLumBufSize            = c->vLumBufSize;
-    const int vChrBufSize            = c->vChrBufSize;
-#ifndef NEW_FILTER
-    uint8_t *formatConvBuffer        = c->formatConvBuffer;
-    uint32_t *pal                    = c->pal_yuv;
-    int perform_gamma = c->is_internal_gamma;
-#endif
+
     yuv2planar1_fn yuv2plane1        = c->yuv2plane1;
     yuv2planarX_fn yuv2planeX        = c->yuv2planeX;
     yuv2interleavedX_fn yuv2nv12cX   = c->yuv2nv12cX;
@@ -385,7 +265,7 @@ static int swscale(SwsContext *c, const uint8_t *src[],
     int lastInLumBuf = c->lastInLumBuf;
     int lastInChrBuf = c->lastInChrBuf;
 
-#ifdef NEW_FILTER
+
     int lumStart = 0;
     int lumEnd = c->descIndex[0];
     int chrStart = lumEnd;
@@ -397,15 +277,12 @@ static int swscale(SwsContext *c, const uint8_t *src[],
     SwsSlice *vout_slice = &c->slice[c->numSlice-1];
     SwsFilterDescriptor *desc = c->desc;
 
+
+    int needAlpha = c->needAlpha;
+
     int hasLumHoles = 1;
     int hasChrHoles = 1;
-#endif
 
-#ifndef NEW_FILTER
-    if (!usePal(c->srcFormat)) {
-        pal = c->input_rgb2yuv_table;
-    }
-#endif
 
     if (isPacked(c->srcFormat)) {
         src[0] =
@@ -427,8 +304,8 @@ static int swscale(SwsContext *c, const uint8_t *src[],
                   dst[2], dstStride[2], dst[3], dstStride[3]);
     DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
                   srcSliceY, srcSliceH, dstY, dstH);
-    DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n",
-                  vLumFilterSize, vLumBufSize, vChrFilterSize, vChrBufSize);
+    DEBUG_BUFFERS("vLumFilterSize: %d vChrFilterSize: %d\n",
+                  vLumFilterSize, vChrFilterSize);
 
     if (dstStride[0]&15 || dstStride[1]&15 ||
         dstStride[2]&15 || dstStride[3]&15) {
@@ -470,7 +347,6 @@ static int swscale(SwsContext *c, const uint8_t *src[],
     }
     lastDstY = dstY;
 
-#ifdef NEW_FILTER
     ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
                    yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, c->use_mmx_vfilter);
 
@@ -492,18 +368,9 @@ static int swscale(SwsContext *c, const uint8_t *src[],
         hout_slice->plane[3].sliceH = 0;
         hout_slice->width = dstW;
     }
-#endif
 
     for (; dstY < dstH; dstY++) {
         const int chrDstY = dstY >> c->chrDstVSubSample;
-#ifndef NEW_FILTER
-        uint8_t *dest[4]  = {
-            dst[0] + dstStride[0] * dstY,
-            dst[1] + dstStride[1] * chrDstY,
-            dst[2] + dstStride[2] * chrDstY,
-            (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3] + dstStride[3] * dstY : NULL,
-        };
-#endif
         int use_mmx_vfilter= c->use_mmx_vfilter;
 
         // First line needed as input
@@ -517,14 +384,13 @@ static int swscale(SwsContext *c, const uint8_t *src[],
         int lastLumSrcY2 = FFMIN(c->srcH,    firstLumSrcY2 + vLumFilterSize) - 1;
         int lastChrSrcY  = FFMIN(c->chrSrcH, firstChrSrcY  + vChrFilterSize) - 1;
         int enough_lines;
-#ifdef NEW_FILTER
+
         int i;
         int posY, cPosY, firstPosY, lastPosY, firstCPosY, lastCPosY;
-#endif
 
         // handle holes (FAST_BILINEAR & weird filters)
         if (firstLumSrcY > lastInLumBuf) {
-#ifdef NEW_FILTER
+
             hasLumHoles = lastInLumBuf != firstLumSrcY - 1;
             if (hasLumHoles) {
                 hout_slice->plane[0].sliceY = firstLumSrcY;
@@ -532,11 +398,11 @@ static int swscale(SwsContext *c, const uint8_t *src[],
                 hout_slice->plane[0].sliceH =
                 hout_slice->plane[3].sliceH = 0;
             }
-#endif
+
             lastInLumBuf = firstLumSrcY - 1;
         }
         if (firstChrSrcY > lastInChrBuf) {
-#ifdef NEW_FILTER
+
             hasChrHoles = lastInChrBuf != firstChrSrcY - 1;
             if (hasChrHoles) {
                 hout_slice->plane[1].sliceY = firstChrSrcY;
@@ -544,11 +410,9 @@ static int swscale(SwsContext *c, const uint8_t *src[],
                 hout_slice->plane[1].sliceH =
                 hout_slice->plane[2].sliceH = 0;
             }
-#endif
+
             lastInChrBuf = firstChrSrcY - 1;
         }
-        av_assert0(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1);
-        av_assert0(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1);
 
         DEBUG_BUFFERS("dstY: %d\n", dstY);
         DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
@@ -567,11 +431,14 @@ static int swscale(SwsContext *c, const uint8_t *src[],
                           lastLumSrcY, lastChrSrcY);
         }
 
-#ifdef NEW_FILTER
+        av_assert0((lastLumSrcY - firstLumSrcY + 1) <= hout_slice->plane[0].available_lines);
+        av_assert0((lastChrSrcY - firstChrSrcY + 1) <= hout_slice->plane[1].available_lines);
+
+
         posY = hout_slice->plane[0].sliceY + hout_slice->plane[0].sliceH;
         if (posY <= lastLumSrcY && !hasLumHoles) {
             firstPosY = FFMAX(firstLumSrcY, posY);
-            lastPosY = FFMIN(lastLumSrcY + MAX_LINES_AHEAD, srcSliceY + srcSliceH - 1);
+            lastPosY = FFMIN(firstLumSrcY + hout_slice->plane[0].available_lines - 1, srcSliceY + srcSliceH - 1);
         } else {
             firstPosY = lastInLumBuf + 1;
             lastPosY = lastLumSrcY;
@@ -580,7 +447,7 @@ static int swscale(SwsContext *c, const uint8_t *src[],
         cPosY = hout_slice->plane[1].sliceY + hout_slice->plane[1].sliceH;
         if (cPosY <= lastChrSrcY && !hasChrHoles) {
             firstCPosY = FFMAX(firstChrSrcY, cPosY);
-            lastCPosY = FFMIN(lastChrSrcY + MAX_LINES_AHEAD, AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample) - 1);
+            lastCPosY = FFMIN(firstChrSrcY + hout_slice->plane[1].available_lines - 1, AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample) - 1);
         } else {
             firstCPosY = lastInChrBuf + 1;
             lastCPosY = lastChrSrcY;
@@ -604,62 +471,11 @@ static int swscale(SwsContext *c, const uint8_t *src[],
         chrBufIndex += lastChrSrcY - lastInChrBuf;
         lastInChrBuf = lastChrSrcY;
 
-#else
-        // Do horizontal scaling
-        while (lastInLumBuf < lastLumSrcY) {
-            const uint8_t *src1[4] = {
-                src[0] + (lastInLumBuf + 1 - srcSliceY) * srcStride[0],
-                src[1] + (lastInLumBuf + 1 - srcSliceY) * srcStride[1],
-                src[2] + (lastInLumBuf + 1 - srcSliceY) * srcStride[2],
-                src[3] + (lastInLumBuf + 1 - srcSliceY) * srcStride[3],
-            };
-            lumBufIndex++;
-            av_assert0(lumBufIndex < 2 * vLumBufSize);
-            av_assert0(lastInLumBuf + 1 - srcSliceY < srcSliceH);
-            av_assert0(lastInLumBuf + 1 - srcSliceY >= 0);
-
-            if (perform_gamma)
-                gamma_convert((uint8_t **)src1, srcW, c->inv_gamma);
-
-            hyscale(c, lumPixBuf[lumBufIndex], dstW, src1, srcW, lumXInc,
-                    hLumFilter, hLumFilterPos, hLumFilterSize,
-                    formatConvBuffer, pal, 0);
-            if (CONFIG_SWSCALE_ALPHA && alpPixBuf)
-                hyscale(c, alpPixBuf[lumBufIndex], dstW, src1, srcW,
-                        lumXInc, hLumFilter, hLumFilterPos, hLumFilterSize,
-                        formatConvBuffer, pal, 1);
-            lastInLumBuf++;
-            DEBUG_BUFFERS("\t\tlumBufIndex %d: lastInLumBuf: %d\n",
-                          lumBufIndex, lastInLumBuf);
-        }
-        while (lastInChrBuf < lastChrSrcY) {
-            const uint8_t *src1[4] = {
-                src[0] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[0],
-                src[1] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[1],
-                src[2] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[2],
-                src[3] + (lastInChrBuf + 1 - chrSrcSliceY) * srcStride[3],
-            };
-            chrBufIndex++;
-            av_assert0(chrBufIndex < 2 * vChrBufSize);
-            av_assert0(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));
-            av_assert0(lastInChrBuf + 1 - chrSrcSliceY >= 0);
-            // FIXME replace parameters through context struct (some at least)
-
-            if (c->needs_hcscale)
-                hcscale(c, chrUPixBuf[chrBufIndex], chrVPixBuf[chrBufIndex],
-                        chrDstW, src1, chrSrcW, chrXInc,
-                        hChrFilter, hChrFilterPos, hChrFilterSize,
-                        formatConvBuffer, pal);
-            lastInChrBuf++;
-            DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n",
-                          chrBufIndex, lastInChrBuf);
-        }
-#endif
         // wrap buf index around to stay inside the ring buffer
-        if (lumBufIndex >= vLumBufSize)
-            lumBufIndex -= vLumBufSize;
-        if (chrBufIndex >= vChrBufSize)
-            chrBufIndex -= vChrBufSize;
+        if (lumBufIndex >= vLumFilterSize)
+            lumBufIndex -= vLumFilterSize;
+        if (chrBufIndex >= vChrFilterSize)
+            chrBufIndex -= vChrFilterSize;
         if (!enough_lines)
             break;  // we can't output a dstY line so let's try with the next slice
 
@@ -682,119 +498,11 @@ static int swscale(SwsContext *c, const uint8_t *src[],
         }
 
         {
-#ifdef NEW_FILTER
             for (i = vStart; i < vEnd; ++i)
                 desc[i].process(c, &desc[i], dstY, 1);
-#else
-            const int16_t **lumSrcPtr  = (const int16_t **)(void*) lumPixBuf  + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
-            const int16_t **chrUSrcPtr = (const int16_t **)(void*) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
-            const int16_t **chrVSrcPtr = (const int16_t **)(void*) chrVPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
-            const int16_t **alpSrcPtr  = (CONFIG_SWSCALE_ALPHA && alpPixBuf) ?
-                                         (const int16_t **)(void*) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
-            int16_t *vLumFilter = c->vLumFilter;
-            int16_t *vChrFilter = c->vChrFilter;
-
-            if (isPlanarYUV(dstFormat) ||
-                (isGray(dstFormat) && !isALPHA(dstFormat))) { // YV12 like
-                const int chrSkipMask = (1 << c->chrDstVSubSample) - 1;
-
-                vLumFilter +=    dstY * vLumFilterSize;
-                vChrFilter += chrDstY * vChrFilterSize;
-
-//                 av_assert0(use_mmx_vfilter != (
-//                                yuv2planeX == yuv2planeX_10BE_c
-//                             || yuv2planeX == yuv2planeX_10LE_c
-//                             || yuv2planeX == yuv2planeX_9BE_c
-//                             || yuv2planeX == yuv2planeX_9LE_c
-//                             || yuv2planeX == yuv2planeX_16BE_c
-//                             || yuv2planeX == yuv2planeX_16LE_c
-//                             || yuv2planeX == yuv2planeX_8_c) || !ARCH_X86);
-
-                if(use_mmx_vfilter){
-                    vLumFilter= (int16_t *)c->lumMmxFilter;
-                    vChrFilter= (int16_t *)c->chrMmxFilter;
-                }
-
-                if (vLumFilterSize == 1) {
-                    yuv2plane1(lumSrcPtr[0], dest[0], dstW, c->lumDither8, 0);
-                } else {
-                    yuv2planeX(vLumFilter, vLumFilterSize,
-                               lumSrcPtr, dest[0],
-                               dstW, c->lumDither8, 0);
-                }
-
-                if (!((dstY & chrSkipMask) || isGray(dstFormat))) {
-                    if (yuv2nv12cX) {
-                        yuv2nv12cX(c, vChrFilter,
-                                   vChrFilterSize, chrUSrcPtr, chrVSrcPtr,
-                                   dest[1], chrDstW);
-                    } else if (vChrFilterSize == 1) {
-                        yuv2plane1(chrUSrcPtr[0], dest[1], chrDstW, c->chrDither8, 0);
-                        yuv2plane1(chrVSrcPtr[0], dest[2], chrDstW, c->chrDither8, 3);
-                    } else {
-                        yuv2planeX(vChrFilter,
-                                   vChrFilterSize, chrUSrcPtr, dest[1],
-                                   chrDstW, c->chrDither8, 0);
-                        yuv2planeX(vChrFilter,
-                                   vChrFilterSize, chrVSrcPtr, dest[2],
-                                   chrDstW, c->chrDither8, use_mmx_vfilter ? (c->uv_offx2 >> 1) : 3);
-                    }
-                }
-
-                if (CONFIG_SWSCALE_ALPHA && alpPixBuf) {
-                    if(use_mmx_vfilter){
-                        vLumFilter= (int16_t *)c->alpMmxFilter;
-                    }
-                    if (vLumFilterSize == 1) {
-                        yuv2plane1(alpSrcPtr[0], dest[3], dstW,
-                                   c->lumDither8, 0);
-                    } else {
-                        yuv2planeX(vLumFilter,
-                                   vLumFilterSize, alpSrcPtr, dest[3],
-                                   dstW, c->lumDither8, 0);
-                    }
-                }
-            } else if (yuv2packedX) {
-                av_assert1(lumSrcPtr  + vLumFilterSize - 1 < (const int16_t **)lumPixBuf  + vLumBufSize * 2);
-                av_assert1(chrUSrcPtr + vChrFilterSize - 1 < (const int16_t **)chrUPixBuf + vChrBufSize * 2);
-                if (c->yuv2packed1 && vLumFilterSize == 1 &&
-                    vChrFilterSize <= 2) { // unscaled RGB
-                    int chrAlpha = vChrFilterSize == 1 ? 0 : vChrFilter[2 * dstY + 1];
-                    yuv2packed1(c, *lumSrcPtr, chrUSrcPtr, chrVSrcPtr,
-                                alpPixBuf ? *alpSrcPtr : NULL,
-                                dest[0], dstW, chrAlpha, dstY);
-                } else if (c->yuv2packed2 && vLumFilterSize == 2 &&
-                           vChrFilterSize == 2) { // bilinear upscale RGB
-                    int lumAlpha = vLumFilter[2 * dstY + 1];
-                    int chrAlpha = vChrFilter[2 * dstY + 1];
-                    lumMmxFilter[2] =
-                    lumMmxFilter[3] = vLumFilter[2 * dstY]    * 0x10001;
-                    chrMmxFilter[2] =
-                    chrMmxFilter[3] = vChrFilter[2 * chrDstY] * 0x10001;
-                    yuv2packed2(c, lumSrcPtr, chrUSrcPtr, chrVSrcPtr,
-                                alpPixBuf ? alpSrcPtr : NULL,
-                                dest[0], dstW, lumAlpha, chrAlpha, dstY);
-                } else { // general RGB
-                    yuv2packedX(c, vLumFilter + dstY * vLumFilterSize,
-                                lumSrcPtr, vLumFilterSize,
-                                vChrFilter + dstY * vChrFilterSize,
-                                chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
-                                alpSrcPtr, dest[0], dstW, dstY);
-                }
-            } else {
-                av_assert1(!yuv2packed1 && !yuv2packed2);
-                yuv2anyX(c, vLumFilter + dstY * vLumFilterSize,
-                         lumSrcPtr, vLumFilterSize,
-                         vChrFilter + dstY * vChrFilterSize,
-                         chrUSrcPtr, chrVSrcPtr, vChrFilterSize,
-                         alpSrcPtr, dest, dstW, dstY);
-            }
-            if (perform_gamma)
-                gamma_convert(dest, dstW, c->gamma);
-#endif
         }
     }
-    if (isPlanar(dstFormat) && isALPHA(dstFormat) && !alpPixBuf) {
+    if (isPlanar(dstFormat) && isALPHA(dstFormat) && !needAlpha) {
         int length = dstW;
         int height = dstY - lastDstY;
 
@@ -889,6 +597,10 @@ SwsFunc ff_getSwsFunc(SwsContext *c)
         ff_sws_init_swscale_ppc(c);
     if (ARCH_X86)
         ff_sws_init_swscale_x86(c);
+    if (ARCH_AARCH64)
+        ff_sws_init_swscale_aarch64(c);
+    if (ARCH_ARM)
+        ff_sws_init_swscale_arm(c);
 
     return swscale;
 }
diff --git a/libswscale/swscale.h b/libswscale/swscale.h
index da9dd2e..efcbef3 100644
--- a/libswscale/swscale.h
+++ b/libswscale/swscale.h
@@ -73,7 +73,7 @@ const char *swscale_license(void);
 #define SWS_PRINT_INFO              0x1000
 
 //the following 3 flags are not completely implemented
-//internal chrominace subsampling info
+//internal chrominance subsampling info
 #define SWS_FULL_CHR_H_INT    0x2000
 //input subsampling info
 #define SWS_FULL_CHR_H_INP    0x4000
@@ -91,6 +91,7 @@ const char *swscale_license(void);
 #define SWS_CS_SMPTE170M      5
 #define SWS_CS_SMPTE240M      7
 #define SWS_CS_DEFAULT        5
+#define SWS_CS_BT2020         9
 
 /**
  * Return a pointer to yuv<->rgb coefficients for the given colorspace
@@ -248,18 +249,6 @@ SwsVector *sws_allocVec(int length);
 SwsVector *sws_getGaussianVec(double variance, double quality);
 
 /**
- * Allocate and return a vector with length coefficients, all
- * with the same value c.
- */
-SwsVector *sws_getConstVec(double c, int length);
-
-/**
- * Allocate and return a vector with just one coefficient, with
- * value 1.0.
- */
-SwsVector *sws_getIdentityVec(void);
-
-/**
  * Scale all the coefficients of a by the scalar value.
  */
 void sws_scaleVec(SwsVector *a, double scalar);
@@ -268,22 +257,17 @@ void sws_scaleVec(SwsVector *a, double scalar);
  * Scale all the coefficients of a so that their sum equals height.
  */
 void sws_normalizeVec(SwsVector *a, double height);
-void sws_convVec(SwsVector *a, SwsVector *b);
-void sws_addVec(SwsVector *a, SwsVector *b);
-void sws_subVec(SwsVector *a, SwsVector *b);
-void sws_shiftVec(SwsVector *a, int shift);
 
-/**
- * Allocate and return a clone of the vector a, that is a vector
- * with the same coefficients as a.
- */
-SwsVector *sws_cloneVec(SwsVector *a);
-
-/**
- * Print with av_log() a textual representation of the vector a
- * if log_level <= av_log_level.
- */
-void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level);
+#if FF_API_SWS_VECTOR
+attribute_deprecated SwsVector *sws_getConstVec(double c, int length);
+attribute_deprecated SwsVector *sws_getIdentityVec(void);
+attribute_deprecated void sws_convVec(SwsVector *a, SwsVector *b);
+attribute_deprecated void sws_addVec(SwsVector *a, SwsVector *b);
+attribute_deprecated void sws_subVec(SwsVector *a, SwsVector *b);
+attribute_deprecated void sws_shiftVec(SwsVector *a, int shift);
+attribute_deprecated SwsVector *sws_cloneVec(SwsVector *a);
+attribute_deprecated void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level);
+#endif
 
 void sws_freeVec(SwsVector *a);
 
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 1e29ec3..54cd85c 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -91,9 +91,9 @@ typedef int (*SwsFunc)(struct SwsContext *context, const uint8_t *src[],
  * Write one line of horizontally scaled data to planar output
  * without any additional vertical scaling (or point-scaling).
  *
- * @param src     scaled source data, 15bit for 8-10bit output,
- *                19-bit for 16bit output (in int32_t)
- * @param dest    pointer to the output plane. For >8bit
+ * @param src     scaled source data, 15 bits for 8-10-bit output,
+ *                19 bits for 16-bit output (in int32_t)
+ * @param dest    pointer to the output plane. For >8-bit
  *                output, this is in uint16_t
  * @param dstW    width of destination in pixels
  * @param dither  ordered dither array of type int16_t and size 8
@@ -106,11 +106,11 @@ typedef void (*yuv2planar1_fn)(const int16_t *src, uint8_t *dest, int dstW,
  * Write one line of horizontally scaled data to planar output
  * with multi-point vertical scaling between input pixels.
  *
- * @param filter        vertical luma/alpha scaling coefficients, 12bit [0,4096]
- * @param src           scaled luma (Y) or alpha (A) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
+ * @param filter        vertical luma/alpha scaling coefficients, 12 bits [0,4096]
+ * @param src           scaled luma (Y) or alpha (A) source data, 15 bits for
+ *                      8-10-bit output, 19 bits for 16-bit output (in int32_t)
  * @param filterSize    number of vertical input lines to scale
- * @param dest          pointer to output plane. For >8bit
+ * @param dest          pointer to output plane. For >8-bit
  *                      output, this is in uint16_t
  * @param dstW          width of destination pixels
  * @param offset        Dither offset
@@ -124,13 +124,13 @@ typedef void (*yuv2planarX_fn)(const int16_t *filter, int filterSize,
  * with multi-point vertical scaling between input pixels.
  *
  * @param c             SWS scaling context
- * @param chrFilter     vertical chroma scaling coefficients, 12bit [0,4096]
- * @param chrUSrc       scaled chroma (U) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
- * @param chrVSrc       scaled chroma (V) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
+ * @param chrFilter     vertical chroma scaling coefficients, 12 bits [0,4096]
+ * @param chrUSrc       scaled chroma (U) source data, 15 bits for 8-10-bit
+ *                      output, 19 bits for 16-bit output (in int32_t)
+ * @param chrVSrc       scaled chroma (V) source data, 15 bits for 8-10-bit
+ *                      output, 19 bits for 16-bit output (in int32_t)
  * @param chrFilterSize number of vertical chroma input lines to scale
- * @param dest          pointer to the output plane. For >8bit
+ * @param dest          pointer to the output plane. For >8-bit
  *                      output, this is in uint16_t
  * @param dstW          width of chroma planes
  */
@@ -147,15 +147,15 @@ typedef void (*yuv2interleavedX_fn)(struct SwsContext *c,
  * that this function may do chroma scaling, see the "uvalpha" argument.
  *
  * @param c       SWS scaling context
- * @param lumSrc  scaled luma (Y) source data, 15bit for 8-10bit output,
- *                19-bit for 16bit output (in int32_t)
- * @param chrUSrc scaled chroma (U) source data, 15bit for 8-10bit output,
- *                19-bit for 16bit output (in int32_t)
- * @param chrVSrc scaled chroma (V) source data, 15bit for 8-10bit output,
- *                19-bit for 16bit output (in int32_t)
- * @param alpSrc  scaled alpha (A) source data, 15bit for 8-10bit output,
- *                19-bit for 16bit output (in int32_t)
- * @param dest    pointer to the output plane. For 16bit output, this is
+ * @param lumSrc  scaled luma (Y) source data, 15 bits for 8-10-bit output,
+ *                19 bits for 16-bit output (in int32_t)
+ * @param chrUSrc scaled chroma (U) source data, 15 bits for 8-10-bit output,
+ *                19 bits for 16-bit output (in int32_t)
+ * @param chrVSrc scaled chroma (V) source data, 15 bits for 8-10-bit output,
+ *                19 bits for 16-bit output (in int32_t)
+ * @param alpSrc  scaled alpha (A) source data, 15 bits for 8-10-bit output,
+ *                19 bits for 16-bit output (in int32_t)
+ * @param dest    pointer to the output plane. For 16-bit output, this is
  *                uint16_t
  * @param dstW    width of lumSrc and alpSrc in pixels, number of pixels
  *                to write into dest[]
@@ -180,15 +180,15 @@ typedef void (*yuv2packed1_fn)(struct SwsContext *c, const int16_t *lumSrc,
  * output by doing bilinear scaling between two input lines.
  *
  * @param c       SWS scaling context
- * @param lumSrc  scaled luma (Y) source data, 15bit for 8-10bit output,
- *                19-bit for 16bit output (in int32_t)
- * @param chrUSrc scaled chroma (U) source data, 15bit for 8-10bit output,
- *                19-bit for 16bit output (in int32_t)
- * @param chrVSrc scaled chroma (V) source data, 15bit for 8-10bit output,
- *                19-bit for 16bit output (in int32_t)
- * @param alpSrc  scaled alpha (A) source data, 15bit for 8-10bit output,
- *                19-bit for 16bit output (in int32_t)
- * @param dest    pointer to the output plane. For 16bit output, this is
+ * @param lumSrc  scaled luma (Y) source data, 15 bits for 8-10-bit output,
+ *                19 bits for 16-bit output (in int32_t)
+ * @param chrUSrc scaled chroma (U) source data, 15 bits for 8-10-bit output,
+ *                19 bits for 16-bit output (in int32_t)
+ * @param chrVSrc scaled chroma (V) source data, 15 bits for 8-10-bit output,
+ *                19 bits for 16-bit output (in int32_t)
+ * @param alpSrc  scaled alpha (A) source data, 15 bits for 8-10-bit output,
+ *                19 bits for 16-bit output (in int32_t)
+ * @param dest    pointer to the output plane. For 16-bit output, this is
  *                uint16_t
  * @param dstW    width of lumSrc and alpSrc in pixels, number of pixels
  *                to write into dest[]
@@ -214,19 +214,19 @@ typedef void (*yuv2packed2_fn)(struct SwsContext *c, const int16_t *lumSrc[2],
  * output by doing multi-point vertical scaling between input pixels.
  *
  * @param c             SWS scaling context
- * @param lumFilter     vertical luma/alpha scaling coefficients, 12bit [0,4096]
- * @param lumSrc        scaled luma (Y) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
+ * @param lumFilter     vertical luma/alpha scaling coefficients, 12 bits [0,4096]
+ * @param lumSrc        scaled luma (Y) source data, 15 bits for 8-10-bit output,
+ *                      19 bits for 16-bit output (in int32_t)
  * @param lumFilterSize number of vertical luma/alpha input lines to scale
- * @param chrFilter     vertical chroma scaling coefficients, 12bit [0,4096]
- * @param chrUSrc       scaled chroma (U) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
- * @param chrVSrc       scaled chroma (V) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
+ * @param chrFilter     vertical chroma scaling coefficients, 12 bits [0,4096]
+ * @param chrUSrc       scaled chroma (U) source data, 15 bits for 8-10-bit output,
+ *                      19 bits for 16-bit output (in int32_t)
+ * @param chrVSrc       scaled chroma (V) source data, 15 bits for 8-10-bit output,
+ *                      19 bits for 16-bit output (in int32_t)
  * @param chrFilterSize number of vertical chroma input lines to scale
- * @param alpSrc        scaled alpha (A) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
- * @param dest          pointer to the output plane. For 16bit output, this is
+ * @param alpSrc        scaled alpha (A) source data, 15 bits for 8-10-bit output,
+ *                      19 bits for 16-bit output (in int32_t)
+ * @param dest          pointer to the output plane. For 16-bit output, this is
  *                      uint16_t
  * @param dstW          width of lumSrc and alpSrc in pixels, number of pixels
  *                      to write into dest[]
@@ -248,19 +248,19 @@ typedef void (*yuv2packedX_fn)(struct SwsContext *c, const int16_t *lumFilter,
  * output by doing multi-point vertical scaling between input pixels.
  *
  * @param c             SWS scaling context
- * @param lumFilter     vertical luma/alpha scaling coefficients, 12bit [0,4096]
- * @param lumSrc        scaled luma (Y) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
+ * @param lumFilter     vertical luma/alpha scaling coefficients, 12 bits [0,4096]
+ * @param lumSrc        scaled luma (Y) source data, 15 bits for 8-10-bit output,
+ *                      19 bits for 16-bit output (in int32_t)
  * @param lumFilterSize number of vertical luma/alpha input lines to scale
- * @param chrFilter     vertical chroma scaling coefficients, 12bit [0,4096]
- * @param chrUSrc       scaled chroma (U) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
- * @param chrVSrc       scaled chroma (V) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
+ * @param chrFilter     vertical chroma scaling coefficients, 12 bits [0,4096]
+ * @param chrUSrc       scaled chroma (U) source data, 15 bits for 8-10-bit output,
+ *                      19 bits for 16-bit output (in int32_t)
+ * @param chrVSrc       scaled chroma (V) source data, 15 bits for 8-10-bit output,
+ *                      19 bits for 16-bit output (in int32_t)
  * @param chrFilterSize number of vertical chroma input lines to scale
- * @param alpSrc        scaled alpha (A) source data, 15bit for 8-10bit output,
- *                      19-bit for 16bit output (in int32_t)
- * @param dest          pointer to the output planes. For 16bit output, this is
+ * @param alpSrc        scaled alpha (A) source data, 15 bits for 8-10-bit output,
+ *                      19 bits for 16-bit output (in int32_t)
+ * @param dest          pointer to the output planes. For 16-bit output, this is
  *                      uint16_t
  * @param dstW          width of lumSrc and alpSrc in pixels, number of pixels
  *                      to write into dest[]
@@ -350,12 +350,6 @@ typedef struct SwsContext {
      * vertical scaler is called.
      */
     //@{
-    int16_t **lumPixBuf;          ///< Ring buffer for scaled horizontal luma   plane lines to be fed to the vertical scaler.
-    int16_t **chrUPixBuf;         ///< Ring buffer for scaled horizontal chroma plane lines to be fed to the vertical scaler.
-    int16_t **chrVPixBuf;         ///< Ring buffer for scaled horizontal chroma plane lines to be fed to the vertical scaler.
-    int16_t **alpPixBuf;          ///< Ring buffer for scaled horizontal alpha  plane lines to be fed to the vertical scaler.
-    int vLumBufSize;              ///< Number of vertical luma/alpha lines allocated in the ring buffer.
-    int vChrBufSize;              ///< Number of vertical chroma     lines allocated in the ring buffer.
     int lastInLumBuf;             ///< Last scaled horizontal luma/alpha line from source in the ring buffer.
     int lastInChrBuf;             ///< Last scaled horizontal chroma     line from source in the ring buffer.
     int lumBufIndex;              ///< Index in ring buffer of the last scaled horizontal luma/alpha line from source.
@@ -363,6 +357,7 @@ typedef struct SwsContext {
     //@}
 
     uint8_t *formatConvBuffer;
+    int needAlpha;
 
     /**
      * @name Horizontal and vertical filters.
@@ -559,7 +554,7 @@ typedef struct SwsContext {
      * Scale one horizontal line of input data using a bilinear filter
      * to produce one line of output data. Compared to SwsContext->hScale(),
      * please take note of the following caveats when using these:
-     * - Scaling is done using only 7bit instead of 14bit coefficients.
+     * - Scaling is done using only 7 bits instead of 14-bit coefficients.
      * - You can use no more than 5 input pixels to produce 4 output
      *   pixels. Therefore, this filter should not be used for downscaling
      *   by more than ~20% in width (because that equals more than 5/4th
@@ -590,15 +585,15 @@ typedef struct SwsContext {
      * @param dst        pointer to destination buffer for horizontally scaled
      *                   data. If the number of bits per component of one
      *                   destination pixel (SwsContext->dstBpc) is <= 10, data
-     *                   will be 15bpc in 16bits (int16_t) width. Else (i.e.
+     *                   will be 15 bpc in 16 bits (int16_t) width. Else (i.e.
      *                   SwsContext->dstBpc == 16), data will be 19bpc in
-     *                   32bits (int32_t) width.
+     *                   32 bits (int32_t) width.
      * @param dstW       width of destination image
      * @param src        pointer to source data to be scaled. If the number of
      *                   bits per component of a source pixel (SwsContext->srcBpc)
-     *                   is 8, this is 8bpc in 8bits (uint8_t) width. Else
+     *                   is 8, this is 8bpc in 8 bits (uint8_t) width. Else
      *                   (i.e. SwsContext->dstBpc > 8), this is native depth
-     *                   in 16bits (uint16_t) width. In other words, for 9-bit
+     *                   in 16 bits (uint16_t) width. In other words, for 9-bit
      *                   YUV input, this is 9bpc, for 10-bit YUV input, this is
      *                   10bpc, and for 16-bit RGB or YUV, this is 16bpc.
      * @param filter     filter coefficients to be used per output pixel for
@@ -866,7 +861,7 @@ extern const uint8_t ff_dither_8x8_73[9][8];
 extern const uint8_t ff_dither_8x8_128[9][8];
 extern const uint8_t ff_dither_8x8_220[9][8];
 
-extern const int32_t ff_yuv2rgb_coeffs[8][4];
+extern const int32_t ff_yuv2rgb_coeffs[11][4];
 
 extern const AVClass ff_sws_context_class;
 
@@ -877,6 +872,7 @@ extern const AVClass ff_sws_context_class;
 void ff_get_unscaled_swscale(SwsContext *c);
 void ff_get_unscaled_swscale_ppc(SwsContext *c);
 void ff_get_unscaled_swscale_arm(SwsContext *c);
+void ff_get_unscaled_swscale_aarch64(SwsContext *c);
 
 /**
  * Return function pointer to fastest main scaler path function depending
@@ -895,6 +891,8 @@ void ff_sws_init_output_funcs(SwsContext *c,
                               yuv2anyX_fn *yuv2anyX);
 void ff_sws_init_swscale_ppc(SwsContext *c);
 void ff_sws_init_swscale_x86(SwsContext *c);
+void ff_sws_init_swscale_aarch64(SwsContext *c);
+void ff_sws_init_swscale_arm(SwsContext *c);
 
 void ff_hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth,
                        const uint8_t *src, int srcW, int xInc);
@@ -959,7 +957,7 @@ typedef struct SwsPlane
 } SwsPlane;
 
 /**
- * Struct which defines a slice of an image to be scaled or a output for
+ * Struct which defines a slice of an image to be scaled or an output for
  * a scaled slice.
  * A slice can also be used as intermediate ring buffer for scaling steps.
  */
@@ -1036,7 +1034,4 @@ void ff_init_vscale_pfn(SwsContext *c, yuv2planar1_fn yuv2plane1, yuv2planarX_fn
 //number of extra lines to process
 #define MAX_LINES_AHEAD 4
 
-// enable use of refactored scaler code
-#define NEW_FILTER
-
 #endif /* SWSCALE_SWSCALE_INTERNAL_H */
diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c
index 74f3467..b231abe 100644
--- a/libswscale/swscale_unscaled.c
+++ b/libswscale/swscale_unscaled.c
@@ -575,7 +575,7 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsContext *c, const uint8_t *src[],
     case AV_PIX_FMT_RGB48BE:
     case AV_PIX_FMT_RGBA64LE:
     case AV_PIX_FMT_RGBA64BE:
-        packed16togbra16(src[0] + srcSliceY * srcStride[0], srcStride[0],
+        packed16togbra16(src[0], srcStride[0],
                          dst2013, stride2013, srcSliceH, alpha, swap,
                          16 - bpc, c->srcW);
         break;
@@ -583,7 +583,7 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsContext *c, const uint8_t *src[],
     case AV_PIX_FMT_BGR48BE:
     case AV_PIX_FMT_BGRA64LE:
     case AV_PIX_FMT_BGRA64BE:
-        packed16togbra16(src[0] + srcSliceY * srcStride[0], srcStride[0],
+        packed16togbra16(src[0], srcStride[0],
                          dst1023, stride1023, srcSliceH, alpha, swap,
                          16 - bpc, c->srcW);
         break;
@@ -1643,6 +1643,7 @@ void ff_get_unscaled_swscale(SwsContext *c)
          dstFormat == AV_PIX_FMT_GBRP12LE || dstFormat == AV_PIX_FMT_GBRP12BE ||
          dstFormat == AV_PIX_FMT_GBRP14LE || dstFormat == AV_PIX_FMT_GBRP14BE ||
          dstFormat == AV_PIX_FMT_GBRP16LE || dstFormat == AV_PIX_FMT_GBRP16BE ||
+         dstFormat == AV_PIX_FMT_GBRAP12LE || dstFormat == AV_PIX_FMT_GBRAP12BE ||
          dstFormat == AV_PIX_FMT_GBRAP16LE || dstFormat == AV_PIX_FMT_GBRAP16BE ))
         c->swscale = Rgb16ToPlanarRgb16Wrapper;
 
@@ -1651,6 +1652,7 @@ void ff_get_unscaled_swscale(SwsContext *c)
          srcFormat == AV_PIX_FMT_GBRP10LE || srcFormat == AV_PIX_FMT_GBRP10BE ||
          srcFormat == AV_PIX_FMT_GBRP12LE || srcFormat == AV_PIX_FMT_GBRP12BE ||
          srcFormat == AV_PIX_FMT_GBRP14LE || srcFormat == AV_PIX_FMT_GBRP14BE ||
+         srcFormat == AV_PIX_FMT_GBRAP12LE || srcFormat == AV_PIX_FMT_GBRAP12BE ||
          srcFormat == AV_PIX_FMT_GBRAP16LE || srcFormat == AV_PIX_FMT_GBRAP16BE) &&
         (dstFormat == AV_PIX_FMT_RGB48LE  || dstFormat == AV_PIX_FMT_RGB48BE  ||
          dstFormat == AV_PIX_FMT_BGR48LE  || dstFormat == AV_PIX_FMT_BGR48BE  ||
@@ -1692,6 +1694,7 @@ void ff_get_unscaled_swscale(SwsContext *c)
         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP12) ||
         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP14) ||
         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRP16) ||
+        IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP12) ||
         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_GBRAP16) ||
         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB444) ||
         IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, AV_PIX_FMT_RGB48)  ||
@@ -1776,6 +1779,8 @@ void ff_get_unscaled_swscale(SwsContext *c)
         ff_get_unscaled_swscale_ppc(c);
      if (ARCH_ARM)
          ff_get_unscaled_swscale_arm(c);
+    if (ARCH_AARCH64)
+        ff_get_unscaled_swscale_aarch64(c);
 }
 
 /* Convert the palette to the same packed 32-bit format as the palette */
diff --git a/libswscale/tests/colorspace.c b/libswscale/tests/colorspace.c
new file mode 100644
index 0000000..d1eddc8
--- /dev/null
+++ b/libswscale/tests/colorspace.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2002 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <string.h>              /* for memset() */
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "libavutil/mem.h"
+
+#include "libswscale/swscale.h"
+#include "libswscale/rgb2rgb.h"
+
+#define SIZE    1000
+#define srcByte 0x55
+#define dstByte 0xBB
+
+#define FUNC(s, d, n) { s, d, #n, n }
+
+int main(int argc, char **argv)
+{
+    int i, funcNum;
+    uint8_t *srcBuffer = av_malloc(SIZE);
+    uint8_t *dstBuffer = av_malloc(SIZE);
+    int failedNum      = 0;
+    int passedNum      = 0;
+
+    if (!srcBuffer || !dstBuffer)
+        return -1;
+
+    av_log(NULL, AV_LOG_INFO, "memory corruption test ...\n");
+    ff_sws_rgb2rgb_init();
+
+    for (funcNum = 0; ; funcNum++) {
+        struct func_info_s {
+            int src_bpp;
+            int dst_bpp;
+            const char *name;
+            void (*func)(const uint8_t *src, uint8_t *dst, int src_size);
+        } func_info[] = {
+            FUNC(2, 2, rgb12to15),
+            FUNC(2, 2, rgb15to16),
+            FUNC(2, 3, rgb15to24),
+            FUNC(2, 4, rgb15to32),
+            FUNC(2, 3, rgb16to24),
+            FUNC(2, 4, rgb16to32),
+            FUNC(3, 2, rgb24to15),
+            FUNC(3, 2, rgb24to16),
+            FUNC(3, 4, rgb24to32),
+            FUNC(4, 2, rgb32to15),
+            FUNC(4, 2, rgb32to16),
+            FUNC(4, 3, rgb32to24),
+            FUNC(2, 2, rgb16to15),
+            FUNC(2, 2, rgb12tobgr12),
+            FUNC(2, 2, rgb15tobgr15),
+            FUNC(2, 2, rgb15tobgr16),
+            FUNC(2, 3, rgb15tobgr24),
+            FUNC(2, 4, rgb15tobgr32),
+            FUNC(2, 2, rgb16tobgr15),
+            FUNC(2, 2, rgb16tobgr16),
+            FUNC(2, 3, rgb16tobgr24),
+            FUNC(2, 4, rgb16tobgr32),
+            FUNC(3, 2, rgb24tobgr15),
+            FUNC(3, 2, rgb24tobgr16),
+            FUNC(3, 3, rgb24tobgr24),
+            FUNC(3, 4, rgb24tobgr32),
+            FUNC(4, 2, rgb32tobgr15),
+            FUNC(4, 2, rgb32tobgr16),
+            FUNC(4, 3, rgb32tobgr24),
+            FUNC(4, 4, shuffle_bytes_2103), /* rgb32tobgr32 */
+            FUNC(6, 6, rgb48tobgr48_nobswap),
+            FUNC(6, 6, rgb48tobgr48_bswap),
+            FUNC(8, 6, rgb64to48_nobswap),
+            FUNC(8, 6, rgb64to48_bswap),
+            FUNC(8, 6, rgb64tobgr48_nobswap),
+            FUNC(8, 6, rgb64tobgr48_bswap),
+            FUNC(0, 0, NULL)
+        };
+        int width;
+        int failed = 0;
+        int srcBpp = 0;
+        int dstBpp = 0;
+
+        if (!func_info[funcNum].func)
+            break;
+
+        av_log(NULL, AV_LOG_INFO, ".");
+        memset(srcBuffer, srcByte, SIZE);
+
+        for (width = 63; width > 0; width--) {
+            int dstOffset;
+            for (dstOffset = 128; dstOffset < 196; dstOffset += 4) {
+                int srcOffset;
+                memset(dstBuffer, dstByte, SIZE);
+
+                for (srcOffset = 128; srcOffset < 196; srcOffset += 4) {
+                    uint8_t *src     = srcBuffer + srcOffset;
+                    uint8_t *dst     = dstBuffer + dstOffset;
+                    const char *name = NULL;
+
+                    // don't fill the screen with shit ...
+                    if (failed)
+                        break;
+
+                    srcBpp = func_info[funcNum].src_bpp;
+                    dstBpp = func_info[funcNum].dst_bpp;
+                    name   = func_info[funcNum].name;
+
+                    func_info[funcNum].func(src, dst, width * srcBpp);
+
+                    if (!srcBpp)
+                        break;
+
+                    for (i = 0; i < SIZE; i++) {
+                        if (srcBuffer[i] != srcByte) {
+                            av_log(NULL, AV_LOG_INFO,
+                                   "src damaged at %d w:%d src:%d dst:%d %s\n",
+                                   i, width, srcOffset, dstOffset, name);
+                            failed = 1;
+                            break;
+                        }
+                    }
+                    for (i = 0; i < dstOffset; i++) {
+                        if (dstBuffer[i] != dstByte) {
+                            av_log(NULL, AV_LOG_INFO,
+                                   "dst damaged at %d w:%d src:%d dst:%d %s\n",
+                                   i, width, srcOffset, dstOffset, name);
+                            failed = 1;
+                            break;
+                        }
+                    }
+                    for (i = dstOffset + width * dstBpp; i < SIZE; i++) {
+                        if (dstBuffer[i] != dstByte) {
+                            av_log(NULL, AV_LOG_INFO,
+                                   "dst damaged at %d w:%d src:%d dst:%d %s\n",
+                                   i, width, srcOffset, dstOffset, name);
+                            failed = 1;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        if (failed)
+            failedNum++;
+        else if (srcBpp)
+            passedNum++;
+    }
+
+    av_log(NULL, AV_LOG_INFO,
+           "\n%d converters passed, %d converters randomly overwrote memory\n",
+           passedNum, failedNum);
+    return failedNum;
+}
diff --git a/libswscale/tests/swscale.c b/libswscale/tests/swscale.c
new file mode 100644
index 0000000..58c2114
--- /dev/null
+++ b/libswscale/tests/swscale.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2003-2011 Michael Niedermayer <michaelni at gmx.at>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdarg.h>
+
+#undef HAVE_AV_CONFIG_H
+#include "libavutil/imgutils.h"
+#include "libavutil/mem.h"
+#include "libavutil/avutil.h"
+#include "libavutil/crc.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/lfg.h"
+
+#include "libswscale/swscale.h"
+
+/* HACK Duplicated from swscale_internal.h.
+ * Should be removed when a cleaner pixel format system exists. */
+#define isGray(x)                      \
+    ((x) == AV_PIX_FMT_GRAY8       ||     \
+     (x) == AV_PIX_FMT_YA8         ||     \
+     (x) == AV_PIX_FMT_GRAY16BE    ||     \
+     (x) == AV_PIX_FMT_GRAY16LE    ||     \
+     (x) == AV_PIX_FMT_YA16BE      ||     \
+     (x) == AV_PIX_FMT_YA16LE)
+#define hasChroma(x)                   \
+    (!(isGray(x)                ||     \
+       (x) == AV_PIX_FMT_MONOBLACK ||     \
+       (x) == AV_PIX_FMT_MONOWHITE))
+#define isALPHA(x)                     \
+    ((x) == AV_PIX_FMT_BGR32   ||         \
+     (x) == AV_PIX_FMT_BGR32_1 ||         \
+     (x) == AV_PIX_FMT_RGB32   ||         \
+     (x) == AV_PIX_FMT_RGB32_1 ||         \
+     (x) == AV_PIX_FMT_YUVA420P)
+
+static uint64_t getSSD(const uint8_t *src1, const uint8_t *src2, int stride1,
+                       int stride2, int w, int h)
+{
+    int x, y;
+    uint64_t ssd = 0;
+
+    for (y = 0; y < h; y++) {
+        for (x = 0; x < w; x++) {
+            int d = src1[x + y * stride1] - src2[x + y * stride2];
+            ssd += d * d;
+        }
+    }
+    return ssd;
+}
+
+struct Results {
+    uint64_t ssdY;
+    uint64_t ssdU;
+    uint64_t ssdV;
+    uint64_t ssdA;
+    uint32_t crc;
+};
+
+// test by ref -> src -> dst -> out & compare out against ref
+// ref & out are YV12
+static int doTest(uint8_t *ref[4], int refStride[4], int w, int h,
+                  enum AVPixelFormat srcFormat, enum AVPixelFormat dstFormat,
+                  int srcW, int srcH, int dstW, int dstH, int flags,
+                  struct Results *r)
+{
+    const AVPixFmtDescriptor *desc_yuva420p = av_pix_fmt_desc_get(AV_PIX_FMT_YUVA420P);
+    const AVPixFmtDescriptor *desc_src      = av_pix_fmt_desc_get(srcFormat);
+    const AVPixFmtDescriptor *desc_dst      = av_pix_fmt_desc_get(dstFormat);
+    static enum AVPixelFormat cur_srcFormat;
+    static int cur_srcW, cur_srcH;
+    static uint8_t *src[4];
+    static int srcStride[4];
+    uint8_t *dst[4] = { 0 };
+    uint8_t *out[4] = { 0 };
+    int dstStride[4] = {0};
+    int i;
+    uint64_t ssdY, ssdU = 0, ssdV = 0, ssdA = 0;
+    struct SwsContext *dstContext = NULL, *outContext = NULL;
+    uint32_t crc = 0;
+    int res      = 0;
+
+    if (cur_srcFormat != srcFormat || cur_srcW != srcW || cur_srcH != srcH) {
+        struct SwsContext *srcContext = NULL;
+        int p;
+
+        for (p = 0; p < 4; p++)
+            av_freep(&src[p]);
+
+        res = av_image_fill_linesizes(srcStride, srcFormat, srcW);
+        if (res < 0) {
+            fprintf(stderr, "av_image_fill_linesizes failed\n");
+            goto end;
+        }
+        for (p = 0; p < 4; p++) {
+            srcStride[p] = FFALIGN(srcStride[p], 16);
+            if (srcStride[p])
+                src[p] = av_mallocz(srcStride[p] * srcH + 16);
+            if (srcStride[p] && !src[p]) {
+                perror("Malloc");
+                res = -1;
+                goto end;
+            }
+        }
+        srcContext = sws_getContext(w, h, AV_PIX_FMT_YUVA420P, srcW, srcH,
+                                    srcFormat, SWS_BILINEAR, NULL, NULL, NULL);
+        if (!srcContext) {
+            fprintf(stderr, "Failed to get %s ---> %s\n",
+                    desc_yuva420p->name,
+                    desc_src->name);
+            res = -1;
+            goto end;
+        }
+        sws_scale(srcContext, (const uint8_t * const*)ref, refStride, 0, h, src, srcStride);
+        sws_freeContext(srcContext);
+
+        cur_srcFormat = srcFormat;
+        cur_srcW      = srcW;
+        cur_srcH      = srcH;
+    }
+
+    res = av_image_fill_linesizes(dstStride, dstFormat, dstW);
+    if (res < 0) {
+        fprintf(stderr, "av_image_fill_linesizes failed\n");
+        goto end;
+    }
+
+    for (i = 0; i < 4; i++) {
+        /* Image buffers passed into libswscale can be allocated any way you
+         * prefer, as long as they're aligned enough for the architecture, and
+         * they're freed appropriately (such as using av_free for buffers
+         * allocated with av_malloc). */
+        /* An extra 16 bytes is being allocated because some scalers may write
+         * out of bounds. */
+        dstStride[i] = FFALIGN(dstStride[i], 16);
+        if (dstStride[i])
+            dst[i] = av_mallocz(dstStride[i] * dstH + 16);
+        if (dstStride[i] && !dst[i]) {
+            perror("Malloc");
+            res = -1;
+
+            goto end;
+        }
+    }
+
+    dstContext = sws_getContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat,
+                                flags, NULL, NULL, NULL);
+    if (!dstContext) {
+        fprintf(stderr, "Failed to get %s ---> %s\n",
+                desc_src->name, desc_dst->name);
+        res = -1;
+        goto end;
+    }
+
+    printf(" %s %dx%d -> %s %3dx%3d flags=%2d",
+           desc_src->name, srcW, srcH,
+           desc_dst->name, dstW, dstH,
+           flags);
+    fflush(stdout);
+
+    sws_scale(dstContext, (const uint8_t * const*)src, srcStride, 0, srcH, dst, dstStride);
+
+    for (i = 0; i < 4 && dstStride[i]; i++)
+        crc = av_crc(av_crc_get_table(AV_CRC_32_IEEE), crc, dst[i],
+                     dstStride[i] * dstH);
+
+    if (r && crc == r->crc) {
+        ssdY = r->ssdY;
+        ssdU = r->ssdU;
+        ssdV = r->ssdV;
+        ssdA = r->ssdA;
+    } else {
+        for (i = 0; i < 4; i++) {
+            refStride[i] = FFALIGN(refStride[i], 16);
+            if (refStride[i])
+                out[i] = av_mallocz(refStride[i] * h);
+            if (refStride[i] && !out[i]) {
+                perror("Malloc");
+                res = -1;
+                goto end;
+            }
+        }
+        outContext = sws_getContext(dstW, dstH, dstFormat, w, h,
+                                    AV_PIX_FMT_YUVA420P, SWS_BILINEAR,
+                                    NULL, NULL, NULL);
+        if (!outContext) {
+            fprintf(stderr, "Failed to get %s ---> %s\n",
+                    desc_dst->name,
+                    desc_yuva420p->name);
+            res = -1;
+            goto end;
+        }
+        sws_scale(outContext, (const uint8_t * const*)dst, dstStride, 0, dstH, out, refStride);
+
+        ssdY = getSSD(ref[0], out[0], refStride[0], refStride[0], w, h);
+        if (hasChroma(srcFormat) && hasChroma(dstFormat)) {
+            //FIXME check that output is really gray
+            ssdU = getSSD(ref[1], out[1], refStride[1], refStride[1],
+                          (w + 1) >> 1, (h + 1) >> 1);
+            ssdV = getSSD(ref[2], out[2], refStride[2], refStride[2],
+                          (w + 1) >> 1, (h + 1) >> 1);
+        }
+        if (isALPHA(srcFormat) && isALPHA(dstFormat))
+            ssdA = getSSD(ref[3], out[3], refStride[3], refStride[3], w, h);
+
+        ssdY /= w * h;
+        ssdU /= w * h / 4;
+        ssdV /= w * h / 4;
+        ssdA /= w * h;
+
+        sws_freeContext(outContext);
+
+        for (i = 0; i < 4; i++)
+            if (refStride[i])
+                av_free(out[i]);
+    }
+
+    printf(" CRC=%08x SSD=%5"PRId64 ",%5"PRId64 ",%5"PRId64 ",%5"PRId64 "\n",
+           crc, ssdY, ssdU, ssdV, ssdA);
+
+end:
+    sws_freeContext(dstContext);
+
+    for (i = 0; i < 4; i++)
+        if (dstStride[i])
+            av_free(dst[i]);
+
+    return res;
+}
+
+static void selfTest(uint8_t *ref[4], int refStride[4], int w, int h,
+                     enum AVPixelFormat srcFormat_in,
+                     enum AVPixelFormat dstFormat_in)
+{
+    const int flags[] = { SWS_FAST_BILINEAR, SWS_BILINEAR, SWS_BICUBIC,
+                          SWS_X, SWS_POINT, SWS_AREA, 0 };
+    const int srcW   = w;
+    const int srcH   = h;
+    const int dstW[] = { srcW - srcW / 3, srcW, srcW + srcW / 3, 0 };
+    const int dstH[] = { srcH - srcH / 3, srcH, srcH + srcH / 3, 0 };
+    enum AVPixelFormat srcFormat, dstFormat;
+    const AVPixFmtDescriptor *desc_src, *desc_dst;
+
+    for (srcFormat = srcFormat_in != AV_PIX_FMT_NONE ? srcFormat_in : 0;
+         srcFormat < AV_PIX_FMT_NB; srcFormat++) {
+        if (!sws_isSupportedInput(srcFormat) ||
+            !sws_isSupportedOutput(srcFormat))
+            continue;
+
+        desc_src = av_pix_fmt_desc_get(srcFormat);
+
+        for (dstFormat = dstFormat_in != AV_PIX_FMT_NONE ? dstFormat_in : 0;
+             dstFormat < AV_PIX_FMT_NB; dstFormat++) {
+            int i, j, k;
+            int res = 0;
+
+            if (!sws_isSupportedInput(dstFormat) ||
+                !sws_isSupportedOutput(dstFormat))
+                continue;
+
+            desc_dst = av_pix_fmt_desc_get(dstFormat);
+
+            printf("%s -> %s\n", desc_src->name, desc_dst->name);
+            fflush(stdout);
+
+            for (k = 0; flags[k] && !res; k++)
+                for (i = 0; dstW[i] && !res; i++)
+                    for (j = 0; dstH[j] && !res; j++)
+                        res = doTest(ref, refStride, w, h,
+                                     srcFormat, dstFormat,
+                                     srcW, srcH, dstW[i], dstH[j], flags[k],
+                                     NULL);
+            if (dstFormat_in != AV_PIX_FMT_NONE)
+                break;
+        }
+        if (srcFormat_in != AV_PIX_FMT_NONE)
+            break;
+    }
+}
+
+static int fileTest(uint8_t *ref[4], int refStride[4], int w, int h, FILE *fp,
+                    enum AVPixelFormat srcFormat_in,
+                    enum AVPixelFormat dstFormat_in)
+{
+    char buf[256];
+
+    while (fgets(buf, sizeof(buf), fp)) {
+        struct Results r;
+        enum AVPixelFormat srcFormat;
+        char srcStr[12];
+        int srcW, srcH;
+        enum AVPixelFormat dstFormat;
+        char dstStr[12];
+        int dstW, dstH;
+        int flags;
+        int ret;
+
+        ret = sscanf(buf,
+                     " %12s %dx%d -> %12s %dx%d flags=%d CRC=%x"
+                     " SSD=%"SCNd64 ", %"SCNd64 ", %"SCNd64 ", %"SCNd64 "\n",
+                     srcStr, &srcW, &srcH, dstStr, &dstW, &dstH,
+                     &flags, &r.crc, &r.ssdY, &r.ssdU, &r.ssdV, &r.ssdA);
+        if (ret != 12) {
+            srcStr[0] = dstStr[0] = 0;
+            ret       = sscanf(buf, "%12s -> %12s\n", srcStr, dstStr);
+        }
+
+        srcFormat = av_get_pix_fmt(srcStr);
+        dstFormat = av_get_pix_fmt(dstStr);
+
+        if (srcFormat == AV_PIX_FMT_NONE || dstFormat == AV_PIX_FMT_NONE ||
+            srcW > 8192U || srcH > 8192U || dstW > 8192U || dstH > 8192U) {
+            fprintf(stderr, "malformed input file\n");
+            return -1;
+        }
+        if ((srcFormat_in != AV_PIX_FMT_NONE && srcFormat_in != srcFormat) ||
+            (dstFormat_in != AV_PIX_FMT_NONE && dstFormat_in != dstFormat))
+            continue;
+        if (ret != 12) {
+            printf("%s", buf);
+            continue;
+        }
+
+        doTest(ref, refStride, w, h,
+               srcFormat, dstFormat,
+               srcW, srcH, dstW, dstH, flags,
+               &r);
+    }
+
+    return 0;
+}
+
+#define W 96
+#define H 96
+
+int main(int argc, char **argv)
+{
+    enum AVPixelFormat srcFormat = AV_PIX_FMT_NONE;
+    enum AVPixelFormat dstFormat = AV_PIX_FMT_NONE;
+    uint8_t *rgb_data   = av_malloc(W * H * 4);
+    const uint8_t * const rgb_src[4] = { rgb_data, NULL, NULL, NULL };
+    int rgb_stride[4]   = { 4 * W, 0, 0, 0 };
+    uint8_t *data       = av_malloc(4 * W * H);
+    uint8_t *src[4]     = { data, data + W * H, data + W * H * 2, data + W * H * 3 };
+    int stride[4]       = { W, W, W, W };
+    int x, y;
+    struct SwsContext *sws;
+    AVLFG rand;
+    int res = -1;
+    int i;
+    FILE *fp = NULL;
+
+    if (!rgb_data || !data)
+        return -1;
+
+    for (i = 1; i < argc; i += 2) {
+        if (argv[i][0] != '-' || i + 1 == argc)
+            goto bad_option;
+        if (!strcmp(argv[i], "-ref")) {
+            fp = fopen(argv[i + 1], "r");
+            if (!fp) {
+                fprintf(stderr, "could not open '%s'\n", argv[i + 1]);
+                goto error;
+            }
+        } else if (!strcmp(argv[i], "-src")) {
+            srcFormat = av_get_pix_fmt(argv[i + 1]);
+            if (srcFormat == AV_PIX_FMT_NONE) {
+                fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
+                return -1;
+            }
+        } else if (!strcmp(argv[i], "-dst")) {
+            dstFormat = av_get_pix_fmt(argv[i + 1]);
+            if (dstFormat == AV_PIX_FMT_NONE) {
+                fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]);
+                return -1;
+            }
+        } else {
+bad_option:
+            fprintf(stderr, "bad option or argument missing (%s)\n", argv[i]);
+            goto error;
+        }
+    }
+
+    sws = sws_getContext(W / 12, H / 12, AV_PIX_FMT_RGB32, W, H,
+                         AV_PIX_FMT_YUVA420P, SWS_BILINEAR, NULL, NULL, NULL);
+
+    av_lfg_init(&rand, 1);
+
+    for (y = 0; y < H; y++)
+        for (x = 0; x < W * 4; x++)
+            rgb_data[ x + y * 4 * W] = av_lfg_get(&rand);
+    sws_scale(sws, rgb_src, rgb_stride, 0, H / 12, src, stride);
+    sws_freeContext(sws);
+    av_free(rgb_data);
+
+    if(fp) {
+        res = fileTest(src, stride, W, H, fp, srcFormat, dstFormat);
+        fclose(fp);
+    } else {
+        selfTest(src, stride, W, H, srcFormat, dstFormat);
+        res = 0;
+    }
+error:
+    av_free(data);
+
+    return res;
+}
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 0beb753..576d8f0 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -49,13 +49,27 @@
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/aarch64/cpu.h"
 #include "libavutil/ppc/cpu.h"
 #include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
+
+// We have to implement deprecated functions until they are removed, this is the
+// simplest way to prevent warnings
+#undef attribute_deprecated
+#define attribute_deprecated
+
 #include "rgb2rgb.h"
 #include "swscale.h"
 #include "swscale_internal.h"
 
+#if !FF_API_SWS_VECTOR
+static SwsVector *sws_getIdentityVec(void);
+static void sws_addVec(SwsVector *a, SwsVector *b);
+static void sws_shiftVec(SwsVector *a, int shift);
+static void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level);
+#endif
+
 static void handle_formats(SwsContext *c);
 
 unsigned swscale_version(void)
@@ -204,8 +218,12 @@ static const FormatEntry format_entries[AV_PIX_FMT_NB] = {
     [AV_PIX_FMT_GBRP9BE]     = { 1, 1 },
     [AV_PIX_FMT_GBRP10LE]    = { 1, 1 },
     [AV_PIX_FMT_GBRP10BE]    = { 1, 1 },
+    [AV_PIX_FMT_GBRAP10LE]   = { 1, 0 },
+    [AV_PIX_FMT_GBRAP10BE]   = { 1, 0 },
     [AV_PIX_FMT_GBRP12LE]    = { 1, 1 },
     [AV_PIX_FMT_GBRP12BE]    = { 1, 1 },
+    [AV_PIX_FMT_GBRAP12LE]   = { 1, 0 },
+    [AV_PIX_FMT_GBRAP12BE]   = { 1, 0 },
     [AV_PIX_FMT_GBRP14LE]    = { 1, 1 },
     [AV_PIX_FMT_GBRP14BE]    = { 1, 1 },
     [AV_PIX_FMT_GBRP16LE]    = { 1, 0 },
@@ -1083,6 +1101,12 @@ static enum AVPixelFormat alphaless_fmt(enum AVPixelFormat fmt)
 
     case AV_PIX_FMT_GBRAP:              return AV_PIX_FMT_GBRP;
 
+    case AV_PIX_FMT_GBRAP10LE:          return AV_PIX_FMT_GBRP10;
+    case AV_PIX_FMT_GBRAP10BE:          return AV_PIX_FMT_GBRP10;
+
+    case AV_PIX_FMT_GBRAP12LE:          return AV_PIX_FMT_GBRP12;
+    case AV_PIX_FMT_GBRAP12BE:          return AV_PIX_FMT_GBRP12;
+
     case AV_PIX_FMT_GBRAP16LE:          return AV_PIX_FMT_GBRP16;
     case AV_PIX_FMT_GBRAP16BE:          return AV_PIX_FMT_GBRP16;
 
@@ -1123,7 +1147,7 @@ static enum AVPixelFormat alphaless_fmt(enum AVPixelFormat fmt)
 av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
                              SwsFilter *dstFilter)
 {
-    int i, j;
+    int i;
     int usesVFilter, usesHFilter;
     int unscaled;
     SwsFilter dummyFilter = { NULL, NULL, NULL, NULL };
@@ -1351,7 +1375,9 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
         srcFormat != AV_PIX_FMT_RGB4_BYTE && srcFormat != AV_PIX_FMT_BGR4_BYTE &&
         srcFormat != AV_PIX_FMT_GBRP9BE   && srcFormat != AV_PIX_FMT_GBRP9LE  &&
         srcFormat != AV_PIX_FMT_GBRP10BE  && srcFormat != AV_PIX_FMT_GBRP10LE &&
+        srcFormat != AV_PIX_FMT_GBRAP10BE && srcFormat != AV_PIX_FMT_GBRAP10LE &&
         srcFormat != AV_PIX_FMT_GBRP12BE  && srcFormat != AV_PIX_FMT_GBRP12LE &&
+        srcFormat != AV_PIX_FMT_GBRAP12BE && srcFormat != AV_PIX_FMT_GBRAP12LE &&
         srcFormat != AV_PIX_FMT_GBRP14BE  && srcFormat != AV_PIX_FMT_GBRP14LE &&
         srcFormat != AV_PIX_FMT_GBRP16BE  && srcFormat != AV_PIX_FMT_GBRP16LE &&
         srcFormat != AV_PIX_FMT_GBRAP16BE  && srcFormat != AV_PIX_FMT_GBRAP16LE &&
@@ -1608,7 +1634,8 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
 #endif /* HAVE_MMXEXT_INLINE */
         {
             const int filterAlign = X86_MMX(cpu_flags)     ? 4 :
-                                    PPC_ALTIVEC(cpu_flags) ? 8 : 1;
+                                    PPC_ALTIVEC(cpu_flags) ? 8 :
+                                    have_neon(cpu_flags)   ? 8 : 1;
 
             if ((ret = initFilter(&c->hLumFilter, &c->hLumFilterPos,
                            &c->hLumFilterSize, c->lumXInc,
@@ -1634,7 +1661,8 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
     /* precalculate vertical scaler filter coefficients */
     {
         const int filterAlign = X86_MMX(cpu_flags)     ? 2 :
-                                PPC_ALTIVEC(cpu_flags) ? 8 : 1;
+                                PPC_ALTIVEC(cpu_flags) ? 8 :
+                                have_neon(cpu_flags)   ? 2 : 1;
 
         if ((ret = initFilter(&c->vLumFilter, &c->vLumFilterPos, &c->vLumFilterSize,
                        c->lumYInc, srcH, dstH, filterAlign, (1 << 12),
@@ -1675,69 +1703,14 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter,
 #endif
     }
 
-    // calculate buffer sizes so that they won't run out while handling these damn slices
-    c->vLumBufSize = c->vLumFilterSize;
-    c->vChrBufSize = c->vChrFilterSize;
-    for (i = 0; i < dstH; i++) {
-        int chrI      = (int64_t)i * c->chrDstH / dstH;
-        int nextSlice = FFMAX(c->vLumFilterPos[i] + c->vLumFilterSize - 1,
-                              ((c->vChrFilterPos[chrI] + c->vChrFilterSize - 1)
-                               << c->chrSrcVSubSample));
-
-        nextSlice >>= c->chrSrcVSubSample;
-        nextSlice <<= c->chrSrcVSubSample;
-        if (c->vLumFilterPos[i] + c->vLumBufSize < nextSlice)
-            c->vLumBufSize = nextSlice - c->vLumFilterPos[i];
-        if (c->vChrFilterPos[chrI] + c->vChrBufSize <
-            (nextSlice >> c->chrSrcVSubSample))
-            c->vChrBufSize = (nextSlice >> c->chrSrcVSubSample) -
-                             c->vChrFilterPos[chrI];
-    }
-
     for (i = 0; i < 4; i++)
         FF_ALLOCZ_OR_GOTO(c, c->dither_error[i], (c->dstW+2) * sizeof(int), fail);
 
-    /* Allocate pixbufs (we use dynamic allocation because otherwise we would
-     * need to allocate several megabytes to handle all possible cases) */
-    FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf,  c->vLumBufSize * 3 * sizeof(int16_t *), fail);
-    FF_ALLOCZ_OR_GOTO(c, c->chrUPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
-    FF_ALLOCZ_OR_GOTO(c, c->chrVPixBuf, c->vChrBufSize * 3 * sizeof(int16_t *), fail);
-    if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat))
-        FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf, c->vLumBufSize * 3 * sizeof(int16_t *), fail);
-    /* Note we need at least one pixel more at the end because of the MMX code
-     * (just in case someone wants to replace the 4000/8000). */
-    /* align at 16 bytes for AltiVec */
-    for (i = 0; i < c->vLumBufSize; i++) {
-        FF_ALLOCZ_OR_GOTO(c, c->lumPixBuf[i + c->vLumBufSize],
-                          dst_stride + 16, fail);
-        c->lumPixBuf[i] = c->lumPixBuf[i + c->vLumBufSize];
-    }
+    c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) ? 1 : 0;
+
     // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate)
     c->uv_off   = (dst_stride>>1) + 64 / (c->dstBpc &~ 7);
     c->uv_offx2 = dst_stride + 16;
-    for (i = 0; i < c->vChrBufSize; i++) {
-        FF_ALLOC_OR_GOTO(c, c->chrUPixBuf[i + c->vChrBufSize],
-                         dst_stride * 2 + 32, fail);
-        c->chrUPixBuf[i] = c->chrUPixBuf[i + c->vChrBufSize];
-        c->chrVPixBuf[i] = c->chrVPixBuf[i + c->vChrBufSize]
-                         = c->chrUPixBuf[i] + (dst_stride >> 1) + 8;
-    }
-    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
-        for (i = 0; i < c->vLumBufSize; i++) {
-            FF_ALLOCZ_OR_GOTO(c, c->alpPixBuf[i + c->vLumBufSize],
-                              dst_stride + 16, fail);
-            c->alpPixBuf[i] = c->alpPixBuf[i + c->vLumBufSize];
-        }
-
-    // try to avoid drawing green stuff between the right end and the stride end
-    for (i = 0; i < c->vChrBufSize; i++)
-        if(desc_dst->comp[0].depth == 16){
-            av_assert0(c->dstBpc > 14);
-            for(j=0; j<dst_stride/2+1; j++)
-                ((int32_t*)(c->chrUPixBuf[i]))[j] = 1<<18;
-        } else
-            for(j=0; j<dst_stride+1; j++)
-                ((int16_t*)(c->chrUPixBuf[i]))[j] = 1<<14;
 
     av_assert0(c->chrDstH <= dstH);
 
@@ -2041,6 +2014,13 @@ SwsVector *sws_getGaussianVec(double variance, double quality)
     return vec;
 }
 
+/**
+ * Allocate and return a vector with length coefficients, all
+ * with the same value c.
+ */
+#if !FF_API_SWS_VECTOR
+static
+#endif
 SwsVector *sws_getConstVec(double c, int length)
 {
     int i;
@@ -2055,6 +2035,13 @@ SwsVector *sws_getConstVec(double c, int length)
     return vec;
 }
 
+/**
+ * Allocate and return a vector with just one coefficient, with
+ * value 1.0.
+ */
+#if !FF_API_SWS_VECTOR
+static
+#endif
 SwsVector *sws_getIdentityVec(void)
 {
     return sws_getConstVec(1.0, 1);
@@ -2084,6 +2071,7 @@ void sws_normalizeVec(SwsVector *a, double height)
     sws_scaleVec(a, height / sws_dcVec(a));
 }
 
+#if FF_API_SWS_VECTOR
 static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b)
 {
     int length = a->length + b->length - 1;
@@ -2101,6 +2089,7 @@ static SwsVector *sws_getConvVec(SwsVector *a, SwsVector *b)
 
     return vec;
 }
+#endif
 
 static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b)
 {
@@ -2119,6 +2108,7 @@ static SwsVector *sws_sumVec(SwsVector *a, SwsVector *b)
     return vec;
 }
 
+#if FF_API_SWS_VECTOR
 static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b)
 {
     int length = FFMAX(a->length, b->length);
@@ -2135,6 +2125,7 @@ static SwsVector *sws_diffVec(SwsVector *a, SwsVector *b)
 
     return vec;
 }
+#endif
 
 /* shift left / or right if "shift" is negative */
 static SwsVector *sws_getShiftedVec(SwsVector *a, int shift)
@@ -2154,6 +2145,9 @@ static SwsVector *sws_getShiftedVec(SwsVector *a, int shift)
     return vec;
 }
 
+#if !FF_API_SWS_VECTOR
+static
+#endif
 void sws_shiftVec(SwsVector *a, int shift)
 {
     SwsVector *shifted = sws_getShiftedVec(a, shift);
@@ -2167,6 +2161,9 @@ void sws_shiftVec(SwsVector *a, int shift)
     av_free(shifted);
 }
 
+#if !FF_API_SWS_VECTOR
+static
+#endif
 void sws_addVec(SwsVector *a, SwsVector *b)
 {
     SwsVector *sum = sws_sumVec(a, b);
@@ -2180,6 +2177,7 @@ void sws_addVec(SwsVector *a, SwsVector *b)
     av_free(sum);
 }
 
+#if FF_API_SWS_VECTOR
 void sws_subVec(SwsVector *a, SwsVector *b)
 {
     SwsVector *diff = sws_diffVec(a, b);
@@ -2217,7 +2215,15 @@ SwsVector *sws_cloneVec(SwsVector *a)
 
     return vec;
 }
+#endif
 
+/**
+ * Print with av_log() a textual representation of the vector a
+ * if log_level <= av_log_level.
+ */
+#if !FF_API_SWS_VECTOR
+static
+#endif
 void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level)
 {
     int i;
@@ -2271,25 +2277,6 @@ void sws_freeContext(SwsContext *c)
     if (!c)
         return;
 
-    if (c->lumPixBuf) {
-        for (i = 0; i < c->vLumBufSize; i++)
-            av_freep(&c->lumPixBuf[i]);
-        av_freep(&c->lumPixBuf);
-    }
-
-    if (c->chrUPixBuf) {
-        for (i = 0; i < c->vChrBufSize; i++)
-            av_freep(&c->chrUPixBuf[i]);
-        av_freep(&c->chrUPixBuf);
-        av_freep(&c->chrVPixBuf);
-    }
-
-    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
-        for (i = 0; i < c->vLumBufSize; i++)
-            av_freep(&c->alpPixBuf[i]);
-        av_freep(&c->alpPixBuf);
-    }
-
     for (i = 0; i < 4; i++)
         av_freep(&c->dither_error[i]);
 
diff --git a/libswscale/version.h b/libswscale/version.h
index 24908b8..d03a5cb 100644
--- a/libswscale/version.h
+++ b/libswscale/version.h
@@ -27,7 +27,7 @@
 #include "libavutil/version.h"
 
 #define LIBSWSCALE_VERSION_MAJOR   4
-#define LIBSWSCALE_VERSION_MINOR   0
+#define LIBSWSCALE_VERSION_MINOR   1
 #define LIBSWSCALE_VERSION_MICRO 100
 
 #define LIBSWSCALE_VERSION_INT  AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \
@@ -46,4 +46,8 @@
  * the public API and may change, break or disappear at any time.
  */
 
+#ifndef FF_API_SWS_VECTOR
+#define FF_API_SWS_VECTOR            (LIBSWSCALE_VERSION_MAJOR < 6)
+#endif
+
 #endif /* SWSCALE_VERSION_H */
diff --git a/libswscale/vscale.c b/libswscale/vscale.c
index 72f799d..72352de 100644
--- a/libswscale/vscale.c
+++ b/libswscale/vscale.c
@@ -218,7 +218,7 @@ int ff_init_vscale(SwsContext *c, SwsFilterDescriptor *desc, SwsSlice *src, SwsS
         desc[0].instance = lumCtx;
         desc[0].src = src;
         desc[0].dst = dst;
-        desc[0].alpha = c->alpPixBuf != 0;
+        desc[0].alpha = c->needAlpha;
 
         if (!isGray(c->dstFormat)) {
             chrCtx = av_mallocz(sizeof(VScalerContext));
@@ -239,7 +239,7 @@ int ff_init_vscale(SwsContext *c, SwsFilterDescriptor *desc, SwsSlice *src, SwsS
         desc[0].instance = lumCtx;
         desc[0].src = src;
         desc[0].dst = dst;
-        desc[0].alpha = c->alpPixBuf != 0;
+        desc[0].alpha = c->needAlpha;
     }
 
     ff_init_vscale_pfn(c, c->yuv2plane1, c->yuv2planeX, c->yuv2nv12cX,
diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm
index 133817c..db3e993 100644
--- a/libswscale/x86/output.asm
+++ b/libswscale/x86/output.asm
@@ -50,17 +50,17 @@ SECTION .text
 ;                                     const uint8_t *dither, int offset)
 ;
 ; Scale one or $filterSize lines of source data to generate one line of output
-; data. The input is 15-bit in int16_t if $output_size is [8,10] and 19-bit in
-; int32_t if $output_size is 16. $filter is 12-bits. $filterSize is a multiple
+; data. The input is 15 bits in int16_t if $output_size is [8,10] and 19 bits in
+; int32_t if $output_size is 16. $filter is 12 bits. $filterSize is a multiple
 ; of 2. $offset is either 0 or 3. $dither holds 8 values.
 ;-----------------------------------------------------------------------------
 %macro yuv2planeX_mainloop 2
 .pixelloop_%2:
 %assign %%i 0
-    ; the rep here is for the 8bit output mmx case, where dither covers
+    ; the rep here is for the 8-bit output MMX case, where dither covers
     ; 8 pixels but we can only handle 2 pixels per register, and thus 4
     ; pixels per iteration. In order to not have to keep track of where
-    ; we are w.r.t. dithering, we unroll the mmx/8bit loop x2.
+    ; we are w.r.t. dithering, we unroll the MMX/8-bit loop x2.
 %if %1 == 8
 %assign %%repcnt 16/mmsize
 %else
diff --git a/libswscale/x86/rgb2rgb.c b/libswscale/x86/rgb2rgb.c
index b80e869..ffd12e1 100644
--- a/libswscale/x86/rgb2rgb.c
+++ b/libswscale/x86/rgb2rgb.c
@@ -27,7 +27,6 @@
 
 #include "config.h"
 #include "libavutil/attributes.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavutil/cpu.h"
 #include "libavutil/bswap.h"
diff --git a/libswscale/x86/scale.asm b/libswscale/x86/scale.asm
index 7af92f7..f978170 100644
--- a/libswscale/x86/scale.asm
+++ b/libswscale/x86/scale.asm
@@ -39,10 +39,10 @@ SECTION .text
 ;                                const int16_t *filter,
 ;                                const int32_t *filterPos, int filterSize);
 ;
-; Scale one horizontal line. Input is either 8-bits width or 16-bits width
+; Scale one horizontal line. Input is either 8-bit width or 16-bit width
 ; ($source_width can be either 8, 9, 10 or 16, difference is whether we have to
-; downscale before multiplying). Filter is 14-bits. Output is either 15bits
-; (in int16_t) or 19bits (in int32_t), as given in $intermediate_nbits. Each
+; downscale before multiplying). Filter is 14 bits. Output is either 15 bits
+; (in int16_t) or 19 bits (in int32_t), as given in $intermediate_nbits. Each
 ; output pixel is generated from $filterSize input pixels, the position of
 ; the first pixel is given in filterPos[nOutputPixel].
 ;-----------------------------------------------------------------------------
diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c
index 66ac7d5..7356692 100644
--- a/libswscale/x86/swscale.c
+++ b/libswscale/x86/swscale.c
@@ -25,7 +25,6 @@
 #include "libavutil/attributes.h"
 #include "libavutil/avassert.h"
 #include "libavutil/intreadwrite.h"
-#include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavutil/cpu.h"
 #include "libavutil/pixdesc.h"
@@ -85,18 +84,12 @@ void ff_updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrB
 {
     const int dstH= c->dstH;
     const int flags= c->flags;
-#ifdef NEW_FILTER
+
     SwsPlane *lumPlane = &c->slice[c->numSlice-2].plane[0];
     SwsPlane *chrUPlane = &c->slice[c->numSlice-2].plane[1];
     SwsPlane *alpPlane = &c->slice[c->numSlice-2].plane[3];
-#else
-    int16_t **lumPixBuf= c->lumPixBuf;
-    int16_t **chrUPixBuf= c->chrUPixBuf;
-    int16_t **alpPixBuf= c->alpPixBuf;
-    const int vLumBufSize= c->vLumBufSize;
-    const int vChrBufSize= c->vChrBufSize;
-#endif
-    int hasAlpha = c->alpPixBuf != NULL;
+
+    int hasAlpha = c->needAlpha;
     int32_t *vLumFilterPos= c->vLumFilterPos;
     int32_t *vChrFilterPos= c->vChrFilterPos;
     int16_t *vLumFilter= c->vLumFilter;
@@ -117,22 +110,14 @@ void ff_updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrB
         c->greenDither= ff_dither4[dstY&1];
     c->redDither= ff_dither8[(dstY+1)&1];
     if (dstY < dstH - 2) {
-#ifdef NEW_FILTER
         const int16_t **lumSrcPtr  = (const int16_t **)(void*) lumPlane->line + firstLumSrcY - lumPlane->sliceY;
         const int16_t **chrUSrcPtr = (const int16_t **)(void*) chrUPlane->line + firstChrSrcY - chrUPlane->sliceY;
-        const int16_t **alpSrcPtr  = (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) ? (const int16_t **)(void*) alpPlane->line + firstLumSrcY - alpPlane->sliceY : NULL;
-#else
-        const int16_t **lumSrcPtr= (const int16_t **)(void*) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;
-        const int16_t **chrUSrcPtr= (const int16_t **)(void*) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;
-        const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **)(void*) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;
-#endif
+        const int16_t **alpSrcPtr  = (CONFIG_SWSCALE_ALPHA && hasAlpha) ? (const int16_t **)(void*) alpPlane->line + firstLumSrcY - alpPlane->sliceY : NULL;
+
         int i;
         if (firstLumSrcY < 0 || firstLumSrcY + vLumFilterSize > c->srcH) {
-#ifdef NEW_FILTER
             const int16_t **tmpY = (const int16_t **) lumPlane->tmp;
-#else
-            const int16_t **tmpY = (const int16_t **) lumPixBuf + 2 * vLumBufSize;
-#endif
+
             int neg = -firstLumSrcY, i, end = FFMIN(c->srcH - firstLumSrcY, vLumFilterSize);
             for (i = 0; i < neg;            i++)
                 tmpY[i] = lumSrcPtr[neg];
@@ -143,11 +128,7 @@ void ff_updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrB
             lumSrcPtr = tmpY;
 
             if (alpSrcPtr) {
-#ifdef NEW_FILTER
                 const int16_t **tmpA = (const int16_t **) alpPlane->tmp;
-#else
-                const int16_t **tmpA = (const int16_t **) alpPixBuf + 2 * vLumBufSize;
-#endif
                 for (i = 0; i < neg;            i++)
                     tmpA[i] = alpSrcPtr[neg];
                 for (     ; i < end;            i++)
@@ -158,11 +139,7 @@ void ff_updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrB
             }
         }
         if (firstChrSrcY < 0 || firstChrSrcY + vChrFilterSize > c->chrSrcH) {
-#ifdef NEW_FILTER
             const int16_t **tmpU = (const int16_t **) chrUPlane->tmp;
-#else
-            const int16_t **tmpU = (const int16_t **) chrUPixBuf + 2 * vChrBufSize;
-#endif
             int neg = -firstChrSrcY, i, end = FFMIN(c->chrSrcH - firstChrSrcY, vChrFilterSize);
             for (i = 0; i < neg;            i++) {
                 tmpU[i] = chrUSrcPtr[neg];
@@ -479,7 +456,7 @@ switch(c->dstBpc){ \
         switch (c->srcFormat) {
         case AV_PIX_FMT_YA8:
             c->lumToYV12 = ff_yuyvToY_mmx;
-            if (c->alpPixBuf)
+            if (c->needAlpha)
                 c->alpToYV12 = ff_uyvyToY_mmx;
             break;
         case AV_PIX_FMT_YUYV422:
@@ -528,7 +505,7 @@ switch(c->dstBpc){ \
         switch (c->srcFormat) {
         case AV_PIX_FMT_YA8:
             c->lumToYV12 = ff_yuyvToY_sse2;
-            if (c->alpPixBuf)
+            if (c->needAlpha)
                 c->alpToYV12 = ff_uyvyToY_sse2;
             break;
         case AV_PIX_FMT_YUYV422:
diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c
index bbda6d0..3b38e98 100644
--- a/libswscale/x86/swscale_template.c
+++ b/libswscale/x86/swscale_template.c
@@ -348,7 +348,7 @@ static void RENAME(yuv2rgb32_X_ar)(SwsContext *c, const int16_t *lumFilter,
     x86_reg dstW_reg = dstW;
     x86_reg uv_off = c->uv_offx2;
 
-    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
+    if (CONFIG_SWSCALE_ALPHA && c->needAlpha) {
         YSCALEYUV2PACKEDX_ACCURATE
         YSCALEYUV2RGBX
         "movq                      %%mm2, "U_TEMP"(%0)  \n\t"
@@ -381,7 +381,7 @@ static void RENAME(yuv2rgb32_X)(SwsContext *c, const int16_t *lumFilter,
     x86_reg dstW_reg = dstW;
     x86_reg uv_off = c->uv_offx2;
 
-    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
+    if (CONFIG_SWSCALE_ALPHA && c->needAlpha) {
         YSCALEYUV2PACKEDX
         YSCALEYUV2RGBX
         YSCALEYUV2PACKEDX_YA(ALP_MMX_FILTER_OFFSET, %%mm0, %%mm3, %%mm6, %%mm1, %%mm7)
@@ -410,7 +410,7 @@ static void RENAME(yuv2bgr32_X)(SwsContext *c, const int16_t *lumFilter,
     x86_reg dstW_reg = dstW;
     x86_reg uv_off = c->uv_offx2;
 
-    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
+    if (CONFIG_SWSCALE_ALPHA && c->needAlpha) {
         YSCALEYUV2PACKEDX
         YSCALEYUV2RGBX
         YSCALEYUV2PACKEDX_YA(ALP_MMX_FILTER_OFFSET, %%mm0, %%mm3, %%mm6, %%mm1, %%mm7)
@@ -889,7 +889,7 @@ static void RENAME(yuv2rgb32_2)(SwsContext *c, const int16_t *buf[2],
     const int16_t *buf0  = buf[0],  *buf1  = buf[1],
                   *ubuf0 = ubuf[0], *ubuf1 = ubuf[1];
 
-    if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
+    if (CONFIG_SWSCALE_ALPHA && c->needAlpha) {
         const int16_t *abuf0 = abuf[0], *abuf1 = abuf[1];
 #if ARCH_X86_64
         __asm__ volatile(
@@ -1215,7 +1215,7 @@ static void RENAME(yuv2rgb32_1)(SwsContext *c, const int16_t *buf0,
 
     if (uvalpha < 2048) { // note this is not correct (shifts chrominance by 0.5 pixels) but it is a bit faster
         const int16_t *ubuf1 = ubuf[0];
-        if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
+        if (CONFIG_SWSCALE_ALPHA && c->needAlpha) {
             __asm__ volatile(
                 "mov %%"REG_b", "ESP_OFFSET"(%5)        \n\t"
                 "mov        %4, %%"REG_b"               \n\t"
@@ -1244,7 +1244,7 @@ static void RENAME(yuv2rgb32_1)(SwsContext *c, const int16_t *buf0,
         }
     } else {
         const int16_t *ubuf1 = ubuf[1];
-        if (CONFIG_SWSCALE_ALPHA && c->alpPixBuf) {
+        if (CONFIG_SWSCALE_ALPHA && c->needAlpha) {
             __asm__ volatile(
                 "mov %%"REG_b", "ESP_OFFSET"(%5)        \n\t"
                 "mov        %4, %%"REG_b"               \n\t"
diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c
index 3671fe3..1fe5abe 100644
--- a/libswscale/yuv2rgb.c
+++ b/libswscale/yuv2rgb.c
@@ -46,20 +46,23 @@
  *
  * where Y = cr * R + cg * G + cb * B and cr + cg + cb = 1.
  */
-const int32_t ff_yuv2rgb_coeffs[8][4] = {
-    { 117504, 138453, 13954, 34903 }, /* no sequence_display_extension */
-    { 117504, 138453, 13954, 34903 }, /* ITU-R Rec. 709 (1990) */
+const int32_t ff_yuv2rgb_coeffs[11][4] = {
+    { 117489, 138438, 13975, 34925 }, /* no sequence_display_extension */
+    { 117489, 138438, 13975, 34925 }, /* ITU-R Rec. 709 (1990) */
     { 104597, 132201, 25675, 53279 }, /* unspecified */
     { 104597, 132201, 25675, 53279 }, /* reserved */
     { 104448, 132798, 24759, 53109 }, /* FCC */
     { 104597, 132201, 25675, 53279 }, /* ITU-R Rec. 624-4 System B, G */
     { 104597, 132201, 25675, 53279 }, /* SMPTE 170M */
-    { 117579, 136230, 16907, 35559 }  /* SMPTE 240M (1987) */
+    { 117579, 136230, 16907, 35559 }, /* SMPTE 240M (1987) */
+    {      0                       }, /* YCgCo */
+    { 110013, 140363, 12277, 42626 }, /* Bt-2020-NCL */
+    { 110013, 140363, 12277, 42626 }, /* Bt-2020-CL */
 };
 
 const int *sws_getCoefficients(int colorspace)
 {
-    if (colorspace > 7 || colorspace < 0)
+    if (colorspace > 10 || colorspace < 0 || colorspace == 8)
         colorspace = SWS_CS_DEFAULT;
     return ff_yuv2rgb_coeffs[colorspace];
 }
@@ -817,25 +820,25 @@ av_cold int ff_yuv2rgb_c_init_tables(SwsContext *c, const int inv_table[4],
 
     c->uOffset = 0x0400040004000400LL;
     c->vOffset = 0x0400040004000400LL;
-    c->yCoeff  = roundToInt16(cy  * 8192) * 0x0001000100010001ULL;
-    c->vrCoeff = roundToInt16(crv * 8192) * 0x0001000100010001ULL;
-    c->ubCoeff = roundToInt16(cbu * 8192) * 0x0001000100010001ULL;
-    c->vgCoeff = roundToInt16(cgv * 8192) * 0x0001000100010001ULL;
-    c->ugCoeff = roundToInt16(cgu * 8192) * 0x0001000100010001ULL;
-    c->yOffset = roundToInt16(oy  *    8) * 0x0001000100010001ULL;
-
-    c->yuv2rgb_y_coeff   = (int16_t)roundToInt16(cy  << 13);
-    c->yuv2rgb_y_offset  = (int16_t)roundToInt16(oy  <<  9);
-    c->yuv2rgb_v2r_coeff = (int16_t)roundToInt16(crv << 13);
-    c->yuv2rgb_v2g_coeff = (int16_t)roundToInt16(cgv << 13);
-    c->yuv2rgb_u2g_coeff = (int16_t)roundToInt16(cgu << 13);
-    c->yuv2rgb_u2b_coeff = (int16_t)roundToInt16(cbu << 13);
+    c->yCoeff  = roundToInt16(cy  * (1 << 13)) * 0x0001000100010001ULL;
+    c->vrCoeff = roundToInt16(crv * (1 << 13)) * 0x0001000100010001ULL;
+    c->ubCoeff = roundToInt16(cbu * (1 << 13)) * 0x0001000100010001ULL;
+    c->vgCoeff = roundToInt16(cgv * (1 << 13)) * 0x0001000100010001ULL;
+    c->ugCoeff = roundToInt16(cgu * (1 << 13)) * 0x0001000100010001ULL;
+    c->yOffset = roundToInt16(oy  * (1 <<  3)) * 0x0001000100010001ULL;
+
+    c->yuv2rgb_y_coeff   = (int16_t)roundToInt16(cy  * (1 << 13));
+    c->yuv2rgb_y_offset  = (int16_t)roundToInt16(oy  * (1 <<  9));
+    c->yuv2rgb_v2r_coeff = (int16_t)roundToInt16(crv * (1 << 13));
+    c->yuv2rgb_v2g_coeff = (int16_t)roundToInt16(cgv * (1 << 13));
+    c->yuv2rgb_u2g_coeff = (int16_t)roundToInt16(cgu * (1 << 13));
+    c->yuv2rgb_u2b_coeff = (int16_t)roundToInt16(cbu * (1 << 13));
 
     //scale coefficients by cy
-    crv = ((crv << 16) + 0x8000) / FFMAX(cy, 1);
-    cbu = ((cbu << 16) + 0x8000) / FFMAX(cy, 1);
-    cgu = ((cgu << 16) + 0x8000) / FFMAX(cy, 1);
-    cgv = ((cgv << 16) + 0x8000) / FFMAX(cy, 1);
+    crv = ((crv * (1 << 16)) + 0x8000) / FFMAX(cy, 1);
+    cbu = ((cbu * (1 << 16)) + 0x8000) / FFMAX(cy, 1);
+    cgu = ((cgu * (1 << 16)) + 0x8000) / FFMAX(cy, 1);
+    cgv = ((cgv * (1 << 16)) + 0x8000) / FFMAX(cy, 1);
 
     av_freep(&c->yuvTable);
 
diff --git a/tests/Makefile b/tests/Makefile
index 6e5dfa6..e72b8df 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -97,6 +97,7 @@ include $(SRC_PATH)/$(APITESTSDIR)/Makefile
 
 include $(SRC_PATH)/tests/fate/acodec.mak
 include $(SRC_PATH)/tests/fate/vcodec.mak
+
 include $(SRC_PATH)/tests/fate/avformat.mak
 include $(SRC_PATH)/tests/fate/seek.mak
 
@@ -124,10 +125,10 @@ include $(SRC_PATH)/tests/fate/ea.mak
 include $(SRC_PATH)/tests/fate/exif.mak
 include $(SRC_PATH)/tests/fate/ffmpeg.mak
 include $(SRC_PATH)/tests/fate/ffprobe.mak
+include $(SRC_PATH)/tests/fate/fft.mak
 include $(SRC_PATH)/tests/fate/filter-audio.mak
 include $(SRC_PATH)/tests/fate/filter-video.mak
 include $(SRC_PATH)/tests/fate/flac.mak
-include $(SRC_PATH)/tests/fate/fft.mak
 include $(SRC_PATH)/tests/fate/gapless.mak
 include $(SRC_PATH)/tests/fate/gif.mak
 include $(SRC_PATH)/tests/fate/h264.mak
@@ -142,6 +143,7 @@ include $(SRC_PATH)/tests/fate/libavutil.mak
 include $(SRC_PATH)/tests/fate/libswresample.mak
 include $(SRC_PATH)/tests/fate/lossless-audio.mak
 include $(SRC_PATH)/tests/fate/lossless-video.mak
+include $(SRC_PATH)/tests/fate/matroska.mak
 include $(SRC_PATH)/tests/fate/microsoft.mak
 include $(SRC_PATH)/tests/fate/monkeysaudio.mak
 include $(SRC_PATH)/tests/fate/mp3.mak
@@ -200,7 +202,7 @@ $(FATE_EXTERN):
 	@echo "$@ requires external samples and SAMPLES not specified"; false
 endif
 
-FATE_UTILS = base64 tiny_psnr tiny_ssim
+FATE_UTILS = base64 tiny_psnr tiny_ssim audiomatch
 
 TOOL = ffmpeg
 
@@ -227,7 +229,7 @@ lcov: coverage.info
 
 lcov-reset: TAG = LCOV
 lcov-reset:
-	$(M)lcov -d $(CURDIR) --zerocounters
+	$(M)lcov -q -d $(CURDIR) --zerocounters
 	$(Q)$(RM) -f coverage.info
 
 clean:: testclean
diff --git a/tests/api/api-band-test.c b/tests/api/api-band-test.c
index 8644e7d..5ccba4f 100644
--- a/tests/api/api-band-test.c
+++ b/tests/api/api-band-test.c
@@ -67,7 +67,8 @@ static void draw_horiz_band(AVCodecContext *ctx, const AVFrame *fr, int offset[4
 static int video_decode(const char *input_filename)
 {
     AVCodec *codec = NULL;
-    AVCodecContext *origin_ctx = NULL, *ctx= NULL;
+    AVCodecContext *ctx= NULL;
+    AVCodecParameters *origin_par = NULL;
     uint8_t *byte_buffer = NULL;
     AVFrame *fr = NULL;
     AVPacket pkt;
@@ -99,9 +100,9 @@ static int video_decode(const char *input_filename)
       return -1;
     }
 
-    origin_ctx = fmt_ctx->streams[video_stream]->codec;
+    origin_par = fmt_ctx->streams[video_stream]->codecpar;
 
-    codec = avcodec_find_decoder(origin_ctx->codec_id);
+    codec = avcodec_find_decoder(origin_par->codec_id);
     if (!codec) {
         av_log(NULL, AV_LOG_ERROR, "Can't find decoder\n");
         return -1;
@@ -113,7 +114,7 @@ static int video_decode(const char *input_filename)
         return AVERROR(ENOMEM);
     }
 
-    result = avcodec_copy_context(ctx, origin_ctx);
+    result = avcodec_parameters_to_context(ctx, origin_par);
     if (result) {
         av_log(NULL, AV_LOG_ERROR, "Can't copy decoder context\n");
         return result;
diff --git a/tests/api/api-codec-param-test.c b/tests/api/api-codec-param-test.c
index fa51964..377a5e9 100644
--- a/tests/api/api-codec-param-test.c
+++ b/tests/api/api-codec-param-test.c
@@ -50,7 +50,7 @@ static int try_decode_video_frame(AVCodecContext *codec_ctx, AVPacket *pkt, int
         goto end;
     }
 
-    if (!decode && codec_ctx->codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM) {
+    if (!decode && avpriv_codec_get_cap_skip_frame_fill_param(codec_ctx->codec)) {
         codec_ctx->skip_frame = AVDISCARD_ALL;
     }
 
diff --git a/tests/api/api-h264-test.c b/tests/api/api-h264-test.c
index acf1636..ef3a1fe 100644
--- a/tests/api/api-h264-test.c
+++ b/tests/api/api-h264-test.c
@@ -32,7 +32,8 @@
 static int video_decode_example(const char *input_filename)
 {
     AVCodec *codec = NULL;
-    AVCodecContext *origin_ctx = NULL, *ctx= NULL;
+    AVCodecContext *ctx= NULL;
+    AVCodecParameters *origin_par = NULL;
     AVFrame *fr = NULL;
     uint8_t *byte_buffer = NULL;
     AVPacket pkt;
@@ -63,9 +64,9 @@ static int video_decode_example(const char *input_filename)
       return -1;
     }
 
-    origin_ctx = fmt_ctx->streams[video_stream]->codec;
+    origin_par = fmt_ctx->streams[video_stream]->codecpar;
 
-    codec = avcodec_find_decoder(origin_ctx->codec_id);
+    codec = avcodec_find_decoder(origin_par->codec_id);
     if (!codec) {
         av_log(NULL, AV_LOG_ERROR, "Can't find decoder\n");
         return -1;
@@ -77,7 +78,7 @@ static int video_decode_example(const char *input_filename)
         return AVERROR(ENOMEM);
     }
 
-    result = avcodec_copy_context(ctx, origin_ctx);
+    result = avcodec_parameters_to_context(ctx, origin_par);
     if (result) {
         av_log(NULL, AV_LOG_ERROR, "Can't copy decoder context\n");
         return result;
diff --git a/tests/api/api-seek-test.c b/tests/api/api-seek-test.c
index 135b972..df47a5f 100644
--- a/tests/api/api-seek-test.c
+++ b/tests/api/api-seek-test.c
@@ -174,7 +174,8 @@ static long int read_seek_range(const char *string_with_number)
 static int seek_test(const char *input_filename, const char *start, const char *end)
 {
     AVCodec *codec = NULL;
-    AVCodecContext *origin_ctx = NULL, *ctx= NULL;
+    AVCodecContext *ctx= NULL;
+    AVCodecParameters *origin_par = NULL;
     AVFrame *fr = NULL;
     AVFormatContext *fmt_ctx = NULL;
     int video_stream;
@@ -210,9 +211,9 @@ static int seek_test(const char *input_filename, const char *start, const char *
       return -1;
     }
 
-    origin_ctx = fmt_ctx->streams[video_stream]->codec;
+    origin_par = fmt_ctx->streams[video_stream]->codecpar;
 
-    codec = avcodec_find_decoder(origin_ctx->codec_id);
+    codec = avcodec_find_decoder(origin_par->codec_id);
     if (!codec) {
         av_log(NULL, AV_LOG_ERROR, "Can't find decoder\n");
         return -1;
@@ -224,7 +225,7 @@ static int seek_test(const char *input_filename, const char *start, const char *
         return AVERROR(ENOMEM);
     }
 
-    result = avcodec_copy_context(ctx, origin_ctx);
+    result = avcodec_parameters_to_context(ctx, origin_par);
     if (result) {
         av_log(NULL, AV_LOG_ERROR, "Can't copy decoder context\n");
         return result;
diff --git a/tests/audiomatch.c b/tests/audiomatch.c
new file mode 100644
index 0000000..9752f68
--- /dev/null
+++ b/tests/audiomatch.c
@@ -0,0 +1,110 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <inttypes.h>
+
+#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
+#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
+
+static int64_t fsize(FILE *f){
+    int64_t end, pos= ftell(f);
+    fseek(f, 0, SEEK_END);
+    end = ftell(f);
+    fseek(f, pos, SEEK_SET);
+    return end;
+}
+
+int main(int argc, char **argv){
+    FILE *f[2];
+    int i, pos;
+    int siglen, datlen;
+    int bestpos;
+    double bestc=0;
+    double sigamp= 0;
+    int16_t *signal, *data;
+    int maxshift= 16384;
+
+    if (argc < 3) {
+        printf("audiomatch <testfile> <reffile>\n");
+        printf("WAV headers are skipped automatically.\n");
+        return 1;
+    }
+
+    f[0] = fopen(argv[1], "rb");
+    f[1] = fopen(argv[2], "rb");
+    if (!f[0] || !f[1]) {
+        fprintf(stderr, "Could not open input files.\n");
+        return 1;
+    }
+
+    for (i = 0; i < 2; i++) {
+        uint8_t p[100];
+        if (fread(p, 1, 12, f[i]) != 12)
+            return 1;
+        if (!memcmp(p, "RIFF", 4) &&
+            !memcmp(p + 8, "WAVE", 4)) {
+            if (fread(p, 1, 8, f[i]) != 8)
+                return 1;
+            while (memcmp(p, "data", 4)) {
+                int s = p[4] | p[5] << 8 | p[6] << 16 | p[7] << 24;
+                fseek(f[i], s, SEEK_CUR);
+                if (fread(p, 1, 8, f[i]) != 8)
+                    return 1;
+            }
+        } else {
+            fseek(f[i], -12, SEEK_CUR);
+        }
+    }
+
+    datlen = fsize(f[0]) - ftell(f[0]);
+    siglen = fsize(f[1]) - ftell(f[1]);
+    data   = malloc(datlen * sizeof(*data));
+    signal = malloc(siglen * sizeof(*signal));
+
+    fread(data  , 1, datlen, f[0]);
+    fread(signal, 1, siglen, f[1]);
+    datlen /= 2;
+    siglen /= 2;
+
+    for(i=0; i<siglen; i++){
+        signal[i] = ((uint8_t*)(signal + i))[0] + 256*((uint8_t*)(signal + i))[1];
+        sigamp += signal[i] * signal[i];
+    }
+    for(i=0; i<datlen; i++)
+        data[i] = ((uint8_t*)(data + i))[0] + 256*((uint8_t*)(data + i))[1];
+
+    for(pos = 0; pos<maxshift; pos = pos < 0 ? -pos: -pos-1){
+        int64_t c= 0;
+        int testlen = FFMIN(siglen, datlen-pos);
+        for(i=FFMAX(0, -pos); i<testlen; i++){
+            int j= pos+i;
+            c += signal[i] * data[j];
+        }
+        if(fabs(c) > sigamp * 0.94)
+            maxshift = FFMIN(maxshift, fabs(pos)+32);
+        if(fabs(c)>fabs(bestc)){
+            bestc= c;
+            bestpos = pos;
+        }
+    }
+    printf("presig: %d postsig:%d c:%7.4f lenerr:%d\n", bestpos, datlen - siglen - bestpos, bestc / sigamp, datlen - siglen);
+}
diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile
index bfd7c11..9f62844 100644
--- a/tests/checkasm/Makefile
+++ b/tests/checkasm/Makefile
@@ -1,20 +1,28 @@
 # libavcodec tests
-AVCODECOBJS-$(CONFIG_ALAC_DECODER) += alacdsp.o
-AVCODECOBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o
+# subsystems
 AVCODECOBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o
-AVCODECOBJS-$(CONFIG_DCA_DECODER) += synth_filter.o
 AVCODECOBJS-$(CONFIG_FLACDSP)  += flacdsp.o
 AVCODECOBJS-$(CONFIG_FMTCONVERT)   += fmtconvert.o
 AVCODECOBJS-$(CONFIG_H264PRED) += h264pred.o
 AVCODECOBJS-$(CONFIG_H264QPEL) += h264qpel.o
+AVCODECOBJS-$(CONFIG_VIDEODSP) += videodsp.o
+
+# decoders/encoders
+AVCODECOBJS-$(CONFIG_ALAC_DECODER) += alacdsp.o
+AVCODECOBJS-$(CONFIG_DCA_DECODER) += synth_filter.o
 AVCODECOBJS-$(CONFIG_JPEG2000_DECODER) += jpeg2000dsp.o
 AVCODECOBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o
 AVCODECOBJS-$(CONFIG_V210_ENCODER) += v210enc.o
 AVCODECOBJS-$(CONFIG_VP9_DECODER) += vp9dsp.o
-AVCODECOBJS-$(CONFIG_VIDEODSP) += videodsp.o
 
 CHECKASMOBJS-$(CONFIG_AVCODEC) += $(AVCODECOBJS-yes)
 
+# libavfilter tests
+AVFILTEROBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o
+AVFILTEROBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o
+
+CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes)
+
 
 -include $(SRC_PATH)/tests/checkasm/$(ARCH)/Makefile
 
diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index 1e73e34..5191f83 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -68,9 +68,6 @@ static const struct {
     #if CONFIG_ALAC_DECODER
         { "alacdsp", checkasm_check_alacdsp },
     #endif
-    #if CONFIG_BLEND_FILTER
-        { "vf_blend", checkasm_check_blend },
-    #endif
     #if CONFIG_BSWAPDSP
         { "bswapdsp", checkasm_check_bswapdsp },
     #endif
@@ -92,7 +89,7 @@ static const struct {
     #if CONFIG_JPEG2000_DECODER
         { "jpeg2000dsp", checkasm_check_jpeg2000dsp },
     #endif
-    #if CONFIG_PIXBLOCKDSP
+    #if CONFIG_PIXBLOCKDSP && !(ARCH_PPC64 && HAVE_BIGENDIAN)
         { "pixblockdsp", checkasm_check_pixblockdsp },
     #endif
     #if CONFIG_V210_ENCODER
@@ -105,6 +102,14 @@ static const struct {
         { "videodsp", checkasm_check_videodsp },
     #endif
 #endif
+#if CONFIG_AVFILTER
+    #if CONFIG_BLEND_FILTER
+        { "vf_blend", checkasm_check_blend },
+    #endif
+    #if CONFIG_COLORSPACE_FILTER
+        { "vf_colorspace", checkasm_check_colorspace },
+    #endif
+#endif
     { NULL }
 };
 
diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h
index 0c8bc2d..5a76f74 100644
--- a/tests/checkasm/checkasm.h
+++ b/tests/checkasm/checkasm.h
@@ -33,6 +33,7 @@
 void checkasm_check_alacdsp(void);
 void checkasm_check_blend(void);
 void checkasm_check_bswapdsp(void);
+void checkasm_check_colorspace(void);
 void checkasm_check_flacdsp(void);
 void checkasm_check_fmtconvert(void);
 void checkasm_check_h264pred(void);
@@ -172,4 +173,4 @@ void checkasm_checked_call(void *func, ...);
 #define bench_new(...) while(0)
 #endif
 
-#endif
+#endif /* TESTS_CHECKASM_CHECKASM_H */
diff --git a/tests/checkasm/h264pred.c b/tests/checkasm/h264pred.c
index 4028405..59dcb2f 100644
--- a/tests/checkasm/h264pred.c
+++ b/tests/checkasm/h264pred.c
@@ -29,7 +29,7 @@
 static const int codec_ids[4] = { AV_CODEC_ID_H264, AV_CODEC_ID_VP8, AV_CODEC_ID_RV40, AV_CODEC_ID_SVQ3 };
 
 static const char * const pred4x4_modes[4][15] = {
-    { /* H264 */
+    { /* H.264 */
         [VERT_PRED           ] = "vertical",
         [HOR_PRED            ] = "horizontal",
         [DC_PRED             ] = "dc",
@@ -65,7 +65,7 @@ static const char * const pred4x4_modes[4][15] = {
 };
 
 static const char * const pred8x8_modes[4][11] = {
-    { /* H264 */
+    { /* H.264 */
         [DC_PRED8x8              ] = "dc",
         [HOR_PRED8x8             ] = "horizontal",
         [VERT_PRED8x8            ] = "vertical",
@@ -92,7 +92,7 @@ static const char * const pred8x8_modes[4][11] = {
 };
 
 static const char * const pred16x16_modes[4][9] = {
-    { /* H264 */
+    { /* H.264 */
         [DC_PRED8x8     ] = "dc",
         [HOR_PRED8x8    ] = "horizontal",
         [VERT_PRED8x8   ] = "vertical",
diff --git a/tests/checkasm/vf_blend.c b/tests/checkasm/vf_blend.c
index cfc389b..aa568c0 100644
--- a/tests/checkasm/vf_blend.c
+++ b/tests/checkasm/vf_blend.c
@@ -79,9 +79,9 @@
                      dst2 + dst_offset, WIDTH, WIDTH, HEIGHT, &param, NULL);               \
             if (memcmp(top1, top2, BUF_SIZE) || memcmp(bot1, bot2, BUF_SIZE) || memcmp(dst1, dst2, BUF_SIZE)) \
                 fail();                                                                    \
-            bench_new(top2 + src_offset, WIDTH, bot2 + src_offset, WIDTH,                  \
-                      dst2, WIDTH, WIDTH, HEIGHT, &param, NULL);                           \
         }                                                                                  \
+        bench_new(top2, WIDTH / 4, bot2, WIDTH / 4, dst2, WIDTH / 4,                       \
+                  WIDTH / 4, HEIGHT / 4, &param, NULL);                                    \
     } while (0)
 
 void checkasm_check_blend(void)
diff --git a/tests/checkasm/vf_colorspace.c b/tests/checkasm/vf_colorspace.c
new file mode 100644
index 0000000..10b7b83
--- /dev/null
+++ b/tests/checkasm/vf_colorspace.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2016 Ronald S. Bultje <rsbultje at gmail.com>
+ *
+ * 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 <string.h>
+#include "checkasm.h"
+#include "libavfilter/colorspacedsp.h"
+#include "libavutil/common.h"
+#include "libavutil/internal.h"
+#include "libavutil/intreadwrite.h"
+
+#define W 64
+#define H 64
+
+#define randomize_buffers()                     \
+    do {                                        \
+        unsigned mask = bpp_mask[idepth];       \
+        int n, m;                               \
+        int bpp = 1 + (!!idepth);               \
+        int buf_size = W * H * bpp;             \
+        for (m = 0; m < 3; m++) {               \
+            int ss = m ? ss_w + ss_h : 0;       \
+            int plane_sz = buf_size >> ss;      \
+            for (n = 0; n < plane_sz; n += 4) { \
+                unsigned r = rnd() & mask;      \
+                AV_WN32A(&src[m][n], r);        \
+            }                                   \
+        }                                       \
+    } while (0)
+
+static const char *format_string[] = {
+    "444", "422", "420"
+};
+
+static const unsigned bpp_mask[] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff };
+
+static void check_yuv2yuv(void)
+{
+    declare_func(void, uint8_t *dst[3], ptrdiff_t dst_stride[3],
+                 uint8_t *src[3], ptrdiff_t src_stride[3],
+                 int w, int h, const int16_t coeff[3][3][8],
+                 const int16_t off[2][8]);
+    ColorSpaceDSPContext dsp;
+    int idepth, odepth, fmt, n;
+    LOCAL_ALIGNED_32(uint8_t, src_y, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, src_u, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, src_v, [W * H * 2]);
+    uint8_t *src[3] = { src_y, src_u, src_v };
+    LOCAL_ALIGNED_32(uint8_t, dst0_y, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst0_u, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst0_v, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst1_y, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst1_u, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst1_v, [W * H * 2]);
+    uint8_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
+    LOCAL_ALIGNED_32(int16_t, offset_buf, [16]);
+    LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
+    int16_t (*offset)[8] = (int16_t(*)[8]) offset_buf;
+    int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
+
+    ff_colorspacedsp_init(&dsp);
+    for (n = 0; n < 8; n++) {
+        offset[0][n] = offset[1][n] = 16;
+
+        coeff[0][0][n] = (1 << 14) + (1 << 7) + 1;
+        coeff[0][1][n] = (1 << 7) - 1;
+        coeff[0][2][n] = -(1 << 8);
+        coeff[1][0][n] = coeff[2][0][n] = 0;
+        coeff[1][1][n] = (1 << 14) + (1 << 7);
+        coeff[1][2][n] = -(1 << 7);
+        coeff[2][2][n] = (1 << 14) - (1 << 6);
+        coeff[2][1][n] = 1 << 6;
+    }
+    for (idepth = 0; idepth < 3; idepth++) {
+        for (odepth = 0; odepth < 3; odepth++) {
+            for (fmt = 0; fmt < 3; fmt++) {
+                if (check_func(dsp.yuv2yuv[idepth][odepth][fmt],
+                               "ff_colorspacedsp_yuv2yuv_%sp%dto%d",
+                               format_string[fmt],
+                               idepth * 2 + 8, odepth * 2 + 8)) {
+                    int ss_w = !!fmt, ss_h = fmt == 2;
+                    int y_src_stride = W << !!idepth, y_dst_stride = W << !!odepth;
+                    int uv_src_stride = y_src_stride >> ss_w, uv_dst_stride = y_dst_stride >> ss_w;
+
+                    randomize_buffers();
+                    call_ref(dst0, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
+                             src, (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
+                             W, H, coeff, offset);
+                    call_new(dst1, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
+                             src, (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
+                             W, H, coeff, offset);
+                    if (memcmp(dst0[0], dst1[0], y_dst_stride * H) ||
+                        memcmp(dst0[1], dst1[1], uv_dst_stride * H >> ss_h) ||
+                        memcmp(dst0[2], dst1[2], uv_dst_stride * H >> ss_h)) {
+                        fail();
+                    }
+                }
+            }
+        }
+    }
+
+    report("yuv2yuv");
+}
+
+static void check_yuv2rgb(void)
+{
+    declare_func(void, int16_t *dst[3], ptrdiff_t dst_stride,
+                 uint8_t *src[3], ptrdiff_t src_stride[3],
+                 int w, int h, const int16_t coeff[3][3][8],
+                 const int16_t off[8]);
+    ColorSpaceDSPContext dsp;
+    int idepth, fmt, n;
+    LOCAL_ALIGNED_32(uint8_t, src_y, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, src_u, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, src_v, [W * H * 2]);
+    uint8_t *src[3] = { src_y, src_u, src_v };
+    LOCAL_ALIGNED_32(int16_t, dst0_y, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst0_u, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst0_v, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst1_y, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst1_u, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst1_v, [W * H]);
+    int16_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
+    LOCAL_ALIGNED_32(int16_t, offset, [8]);
+    LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
+    int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
+
+    ff_colorspacedsp_init(&dsp);
+    for (n = 0; n < 8; n++) {
+        offset[n] = 16;
+
+        coeff[0][0][n] = coeff[1][0][n] = coeff[2][0][n] = (1 << 14) | 1;
+        coeff[0][1][n] = coeff[2][2][n] = 0;
+        coeff[0][2][n] = 1 << 13;
+        coeff[1][1][n] = -(1 << 12);
+        coeff[1][2][n] = 1 << 12;
+        coeff[2][1][n] = 1 << 11;
+    }
+    for (idepth = 0; idepth < 3; idepth++) {
+        for (fmt = 0; fmt < 3; fmt++) {
+            if (check_func(dsp.yuv2rgb[idepth][fmt],
+                           "ff_colorspacedsp_yuv2rgb_%sp%d",
+                           format_string[fmt], idepth * 2 + 8)) {
+                int ss_w = !!fmt, ss_h = fmt == 2;
+                int y_src_stride = W << !!idepth;
+                int uv_src_stride = y_src_stride >> ss_w;
+
+                randomize_buffers();
+                call_ref(dst0, W, src,
+                         (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
+                         W, H, coeff, offset);
+                call_new(dst1, W, src,
+                         (ptrdiff_t[3]) { y_src_stride, uv_src_stride, uv_src_stride },
+                         W, H, coeff, offset);
+                if (memcmp(dst0[0], dst1[0], W * H * sizeof(int16_t)) ||
+                    memcmp(dst0[1], dst1[1], W * H * sizeof(int16_t)) ||
+                    memcmp(dst0[2], dst1[2], W * H * sizeof(int16_t))) {
+                    fail();
+                }
+            }
+        }
+    }
+
+    report("yuv2rgb");
+}
+
+#undef randomize_buffers
+#define randomize_buffers()                     \
+    do {                                        \
+        int y, x, p;                            \
+        for (p = 0; p < 3; p++) {               \
+            for (y = 0; y < H; y++) {           \
+                for (x = 0; x < W; x++) {       \
+                    int r = rnd() & 0x7fff;     \
+                    r -= (32768 - 28672) >> 1;  \
+                    src[p][y * W + x] = r;      \
+                }                               \
+            }                                   \
+        }                                       \
+    } while (0)
+
+static void check_rgb2yuv(void)
+{
+    declare_func(void, uint8_t *dst[3], ptrdiff_t dst_stride[3],
+                 int16_t *src[3], ptrdiff_t src_stride,
+                 int w, int h, const int16_t coeff[3][3][8],
+                 const int16_t off[8]);
+    ColorSpaceDSPContext dsp;
+    int odepth, fmt, n;
+    LOCAL_ALIGNED_32(int16_t, src_y, [W * H * 2]);
+    LOCAL_ALIGNED_32(int16_t, src_u, [W * H * 2]);
+    LOCAL_ALIGNED_32(int16_t, src_v, [W * H * 2]);
+    int16_t *src[3] = { src_y, src_u, src_v };
+    LOCAL_ALIGNED_32(uint8_t, dst0_y, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst0_u, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst0_v, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst1_y, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst1_u, [W * H * 2]);
+    LOCAL_ALIGNED_32(uint8_t, dst1_v, [W * H * 2]);
+    uint8_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
+    LOCAL_ALIGNED_32(int16_t, offset, [8]);
+    LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
+    int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
+
+    ff_colorspacedsp_init(&dsp);
+    for (n = 0; n < 8; n++) {
+        offset[n] = 16;
+
+        // these somewhat resemble bt601/smpte170m coefficients
+        coeff[0][0][n] = lrint(0.3 * (1 << 14));
+        coeff[0][1][n] = lrint(0.6 * (1 << 14));
+        coeff[0][2][n] = lrint(0.1 * (1 << 14));
+        coeff[1][0][n] = lrint(-0.15 * (1 << 14));
+        coeff[1][1][n] = lrint(-0.35 * (1 << 14));
+        coeff[1][2][n] = lrint(0.5 * (1 << 14));
+        coeff[2][0][n] = lrint(0.5 * (1 << 14));
+        coeff[2][1][n] = lrint(-0.42 * (1 << 14));
+        coeff[2][2][n] = lrint(-0.08 * (1 << 14));
+    }
+    for (odepth = 0; odepth < 3; odepth++) {
+        for (fmt = 0; fmt < 3; fmt++) {
+            if (check_func(dsp.rgb2yuv[odepth][fmt],
+                           "ff_colorspacedsp_rgb2yuv_%sp%d",
+                           format_string[fmt], odepth * 2 + 8)) {
+                int ss_w = !!fmt, ss_h = fmt == 2;
+                int y_dst_stride = W << !!odepth;
+                int uv_dst_stride = y_dst_stride >> ss_w;
+
+                randomize_buffers();
+                call_ref(dst0, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
+                         src, W, W, H, coeff, offset);
+                call_new(dst1, (ptrdiff_t[3]) { y_dst_stride, uv_dst_stride, uv_dst_stride },
+                         src, W, W, H, coeff, offset);
+                if (memcmp(dst0[0], dst1[0], H * y_dst_stride) ||
+                    memcmp(dst0[1], dst1[1], H * uv_dst_stride >> ss_h) ||
+                    memcmp(dst0[2], dst1[2], H * uv_dst_stride >> ss_h)) {
+                    fail();
+                }
+            }
+        }
+    }
+
+    report("rgb2yuv");
+}
+
+static void check_multiply3x3(void)
+{
+    declare_func(void, int16_t *data[3], ptrdiff_t stride,
+                 int w, int h, const int16_t coeff[3][3][8]);
+    ColorSpaceDSPContext dsp;
+    LOCAL_ALIGNED_32(int16_t, dst0_y, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst0_u, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst0_v, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst1_y, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst1_u, [W * H]);
+    LOCAL_ALIGNED_32(int16_t, dst1_v, [W * H]);
+    int16_t *dst0[3] = { dst0_y, dst0_u, dst0_v }, *dst1[3] = { dst1_y, dst1_u, dst1_v };
+    int16_t **src = dst0;
+    LOCAL_ALIGNED_32(int16_t, coeff_buf, [3 * 3 * 8]);
+    int16_t (*coeff)[3][8] = (int16_t(*)[3][8]) coeff_buf;
+    int n;
+
+    ff_colorspacedsp_init(&dsp);
+    for (n = 0; n < 8; n++) {
+        coeff[0][0][n] = lrint(0.85 * (1 << 14));
+        coeff[0][1][n] = lrint(0.10 * (1 << 14));
+        coeff[0][2][n] = lrint(0.05 * (1 << 14));
+        coeff[1][0][n] = lrint(-0.1 * (1 << 14));
+        coeff[1][1][n] = lrint(0.95 * (1 << 14));
+        coeff[1][2][n] = lrint(0.15 * (1 << 14));
+        coeff[2][0][n] = lrint(-0.2 * (1 << 14));
+        coeff[2][1][n] = lrint(0.30 * (1 << 14));
+        coeff[2][2][n] = lrint(0.90 * (1 << 14));
+    }
+    if (check_func(dsp.multiply3x3, "ff_colorspacedsp_multiply3x3")) {
+        randomize_buffers();
+        memcpy(dst1_y, dst0_y, W * H * sizeof(*dst1_y));
+        memcpy(dst1_u, dst0_u, W * H * sizeof(*dst1_u));
+        memcpy(dst1_v, dst0_v, W * H * sizeof(*dst1_v));
+        call_ref(dst0, W, W, H, coeff);
+        call_new(dst1, W, W, H, coeff);
+        if (memcmp(dst0[0], dst1[0], H * W * sizeof(*dst0_y)) ||
+            memcmp(dst0[1], dst1[1], H * W * sizeof(*dst0_u)) ||
+            memcmp(dst0[2], dst1[2], H * W * sizeof(*dst0_v))) {
+            fail();
+        }
+    }
+
+    report("multiply3x3");
+}
+
+void checkasm_check_colorspace(void)
+{
+    check_yuv2yuv();
+    check_yuv2rgb();
+    check_rgb2yuv();
+    check_multiply3x3();
+}
diff --git a/tests/fate-run.sh b/tests/fate-run.sh
index 16087cb..c898695 100755
--- a/tests/fate-run.sh
+++ b/tests/fate-run.sh
@@ -96,6 +96,25 @@ probeframes(){
     run ffprobe${PROGSUF} -show_frames -v 0 "$@"
 }
 
+probechapters(){
+    run ffprobe${PROGSUF} -show_chapters -v 0 "$@"
+}
+
+probegaplessinfo(){
+    filename="$1"
+    shift
+    run ffprobe${PROGSUF} -bitexact -select_streams a -show_entries format=start_time,duration:stream=index,start_pts,duration_ts -v 0 "$filename" "$@"
+    pktfile1="${outdir}/${test}.pkts"
+    framefile1="${outdir}/${test}.frames"
+    cleanfiles="$cleanfiles $pktfile1 $framefile1"
+    run ffprobe${PROGSUF} -bitexact -select_streams a -of compact -count_packets -show_entries packet=pts,dts,duration:stream=nb_read_packets -v 0 "$filename" "$@" > "$pktfile1"
+    head -n 8 "$pktfile1"
+    tail -n 9 "$pktfile1"
+    run ffprobe${PROGSUF} -bitexact -select_streams a -of compact -count_frames -show_entries frame=pkt_pts,pkt_dts,best_effort_timestamp,pkt_duration,nb_samples:stream=nb_read_frames -v 0 "$filename" "$@" > "$framefile1"
+    head -n 8 "$framefile1"
+    tail -n 9 "$framefile1"
+}
+
 ffmpeg(){
     dec_opts="-hwaccel $hwaccel -threads $threads -thread_type $thread_type"
     ffmpeg_args="-nostdin -nostats -cpuflags $cpuflags"
@@ -202,7 +221,7 @@ pixfmts(){
     prefilter_chain=$2
     nframes=${3:-1}
 
-    showfiltfmts="$target_exec $target_path/libavfilter/filtfmts-test"
+    showfiltfmts="$target_exec $target_path/libavfilter/tests/filtfmts"
     scale_exclude_fmts=${outfile}_scale_exclude_fmts
     scale_in_fmts=${outfile}_scale_in_fmts
     scale_out_fmts=${outfile}_scale_out_fmts
@@ -249,6 +268,31 @@ gapless(){
     do_md5sum $decfile3
 }
 
+gaplessenc(){
+    sample=$(target_path $1)
+    format=$2
+    codec=$3
+
+    file1="${outdir}/${test}.out-1"
+    cleanfiles="$cleanfiles $file1"
+
+    # test data after reencoding
+    ffmpeg -i "$sample" -flags +bitexact -fflags +bitexact -map 0:a -c:a $codec -f $format -y "$file1"
+    probegaplessinfo "$file1"
+}
+
+audio_match(){
+    sample=$(target_path $1)
+    trefile=$(target_path $2)
+    extra_args=$3
+
+    decfile="${outdir}/${test}.wav"
+    cleanfiles="$cleanfiles $decfile"
+
+    ffmpeg -i "$sample" -flags +bitexact -fflags +bitexact $extra_args -y $decfile
+    tests/audiomatch $decfile $trefile
+}
+
 concat(){
     template=$1
     sample=$2
diff --git a/tests/fate.sh b/tests/fate.sh
index 6ce8c48..885ea17 100755
--- a/tests/fate.sh
+++ b/tests/fate.sh
@@ -37,7 +37,7 @@ checkout(){
 update()(
     cd ${src} || return
     case "$repo" in
-        git:*) git fetch --force && git reset --hard "origin/$branch" ;;
+        git:*) git fetch --quiet --force && git reset --quiet --hard "origin/$branch" ;;
     esac
 )
 
@@ -86,7 +86,7 @@ report(){
     date=$(date -u +%Y%m%d%H%M%S)
     echo "fate:1:${date}:${slot}:${version}:$1:$2:${branch}:${comment}" >report
     cat ${build}/config.fate >>report
-    cat ${build}/tests/data/fate/*.rep >>report || for i in ${build}/tests/data/fate/*.rep ; do cat "$i" >>report ; done
+    cat ${build}/tests/data/fate/*.rep >>report || for i in ${build}/tests/data/fate/*.rep ; do cat "$i" >>report 2>/dev/null; done
     test -n "$fate_recv" && $tar report *.log | gzip | $fate_recv
 }
 
diff --git a/tests/fate/aac.mak b/tests/fate/aac.mak
index 324b05d..3d64031 100644
--- a/tests/fate/aac.mak
+++ b/tests/fate/aac.mak
@@ -213,6 +213,17 @@ fate-aac-ltp-encode: CMP_TARGET = 1270
 fate-aac-ltp-encode: SIZE_TOLERANCE = 3560
 fate-aac-ltp-encode: FUZZ = 17
 
+#Ticket1784
+FATE_AAC_ENCODE += fate-aac-yoraw-encode
+fate-aac-yoraw-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/yo.raw-short.wav -c:a aac -fflags +bitexact -flags +bitexact
+fate-aac-yoraw-encode: CMP = stddev
+fate-aac-yoraw-encode: REF = $(SAMPLES)/audio-reference/yo.raw-short.wav
+fate-aac-yoraw-encode: CMP_SHIFT = -12288
+fate-aac-yoraw-encode: CMP_TARGET = 259
+fate-aac-yoraw-encode: SIZE_TOLERANCE = 3560
+fate-aac-yoraw-encode: FUZZ = 17
+
+
 FATE_AAC_ENCODE += fate-aac-pred-encode
 fate-aac-pred-encode: CMD = enc_dec_pcm adts wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -profile:a aac_main -c:a aac -aac_is 0 -aac_pns 0 -aac_ms 0 -aac_tns 0 -b:a 128k -cutoff 22050
 fate-aac-pred-encode: CMP = stddev
diff --git a/tests/fate/api.mak b/tests/fate/api.mak
index 2ebc531..266f6f9 100644
--- a/tests/fate/api.mak
+++ b/tests/fate/api.mak
@@ -14,7 +14,7 @@ FATE_API_SAMPLES_LIBAVFORMAT-$(call DEMDEC, H264, H264) += fate-api-h264
 fate-api-h264: $(APITESTSDIR)/api-h264-test$(EXESUF)
 fate-api-h264: CMD = run $(APITESTSDIR)/api-h264-test $(TARGET_SAMPLES)/h264-conformance/SVA_NL2_E.264
 
-FATE_API_LIBAVFORMAT-yes += fate-api-seek
+FATE_API_LIBAVFORMAT-$(call DEMDEC, FLV, FLV) += fate-api-seek
 fate-api-seek: $(APITESTSDIR)/api-seek-test$(EXESUF) fate-lavf
 fate-api-seek: CMD = run $(APITESTSDIR)/api-seek-test $(TARGET_PATH)/tests/data/lavf/lavf.flv 0 720
 fate-api-seek: CMP = null
diff --git a/tests/fate/avformat.mak b/tests/fate/avformat.mak
index 54bfb97..bcfe2e3 100644
--- a/tests/fate/avformat.mak
+++ b/tests/fate/avformat.mak
@@ -69,6 +69,8 @@ fate-lavf:     $(FATE_LAVF)
 FATE_LAVF_FATE-$(call ALLYES, MATROSKA_DEMUXER   OGG_MUXER)          += ogg_vp3
 FATE_LAVF_FATE-$(call ALLYES, MOV_DEMUXER        LATM_MUXER)         += latm
 FATE_LAVF_FATE-$(call ALLYES, MP3_DEMUXER        MP3_MUXER)          += mp3
+FATE_LAVF_FATE-$(call ALLYES, MOV_DEMUXER        MOV_MUXER)          += mov_qtrle_mace6
+FATE_LAVF_FATE-$(call ALLYES, AVI_DEMUXER        AVI_MUXER)          += avi_cram
 
 FATE_LAVF_FATE +=  $(FATE_LAVF_FATE-yes:%=fate-lavf-fate-%)
 $(FATE_LAVF_FATE): CMD = lavffatetest
diff --git a/tests/fate/dca.mak b/tests/fate/dca.mak
index 6a6614d..b1681c6 100644
--- a/tests/fate/dca.mak
+++ b/tests/fate/dca.mak
@@ -60,7 +60,7 @@ $(FATE_DCADEC_LOSSY): CMP = oneoff
 $(FATE_DCADEC_LOSSY): CMP_UNIT = f32
 $(FATE_DCADEC_LOSSY): FUZZ = 9
 
-FATE_DCA-$(call DEMDEC, DTS, DCA) += $(FATE_DCADEC_LOSSLESS) $(FATE_DCADEC_LOSSY)
+FATE_DCA-$(call DEMDEC, DTSHD, DCA) += $(FATE_DCADEC_LOSSLESS) $(FATE_DCADEC_LOSSY)
 
 FATE_DCA-$(call DEMDEC, MPEGTS, DCA) += fate-dca-core
 fate-dca-core: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts.ts
diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak
index e48d398..cee4bd4 100644
--- a/tests/fate/demux.mak
+++ b/tests/fate/demux.mak
@@ -1,7 +1,7 @@
 FATE_SAMPLES_DEMUX-$(call DEMDEC, AVI, FRAPS) += fate-avio-direct
 fate-avio-direct: CMD = framecrc -avioflags direct -i $(TARGET_SAMPLES)/fraps/fraps-v5-bouncing-balls-partial.avi -avioflags direct
 
-FATE_SAMPLES_DEMUX-$(CONFIG_AAC_DEMUXER) += fate-adts-demux
+FATE_SAMPLES_DEMUX-$(DEMDEC, AAC, AAC) += fate-adts-demux
 fate-adts-demux: CMD = crc -i $(TARGET_SAMPLES)/aac/ct_faac-adts.aac -acodec copy
 
 FATE_SAMPLES_DEMUX-$(CONFIG_AEA_DEMUXER) += fate-aea-demux
@@ -35,16 +35,19 @@ fate-d-cinema-demux: CMD = framecrc -i $(TARGET_SAMPLES)/d-cinema/THX_Science_FL
 FATE_SAMPLES_DEMUX-$(CONFIG_EA_DEMUXER) += fate-d-eavp6-demux
 fate-d-eavp6-demux: CMD = framecrc -i $(TARGET_SAMPLES)/ea-vp6/SmallRing.vp6 -map 0 -vcodec copy
 
+FATE_SAMPLES_DEMUX-$(CONFIG_FLV_DEMUXER) += fate-flv-demux
+fate-flv-demux: CMD = framecrc -i $(TARGET_SAMPLES)/flv/Enigma_Principles_of_Lust-part.flv -codec copy
+
 FATE_SAMPLES_DEMUX-$(CONFIG_GIF_DEMUXER) += fate-gif-demux
 fate-gif-demux: CMD = framecrc -i $(TARGET_SAMPLES)/gif/Newtons_cradle_animation_book_2.gif -vcodec copy
 
-FATE_SAMPLES_DEMUX-$(CONFIG_IV8_DEMUXER) += fate-iv8-demux
+FATE_SAMPLES_DEMUX-$(call ALLYES, IV8_DEMUXER MPEG4VIDEO_PARSER) += fate-iv8-demux
 fate-iv8-demux: CMD = framecrc -i $(TARGET_SAMPLES)/iv8/zzz-partial.mpg -vcodec copy
 
 FATE_SAMPLES_DEMUX-$(CONFIG_JV_DEMUXER) += fate-jv-demux
 fate-jv-demux: CMD = framecrc -i $(TARGET_SAMPLES)/jv/intro.jv -vcodec copy -acodec copy
 
-FATE_SAMPLES_DEMUX-$(CONFIG_LMLM4_DEMUXER) += fate-lmlm4-demux
+FATE_SAMPLES_DEMUX-$(call ALLYES, LMLM4_DEMUXER MPEG4VIDEO_PARSER) += fate-lmlm4-demux
 fate-lmlm4-demux: CMD = framecrc -i $(TARGET_SAMPLES)/lmlm4/LMLM4_CIFat30fps.divx -t 3 -acodec copy -vcodec copy
 
 FATE_SAMPLES_DEMUX-$(CONFIG_XA_DEMUXER) += fate-maxis-xa
@@ -53,16 +56,26 @@ fate-maxis-xa: CMD = framecrc -i $(TARGET_SAMPLES)/maxis-xa/SC2KBUG.XA -frames:a
 FATE_SAMPLES_DEMUX-$(call DEMDEC, MATROSKA, H264) += fate-mkv
 fate-mkv: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/test7_cut.mkv -c copy
 
+#No dts errors or duplicate DTS should be in this
+FATE_SAMPLES_DEMUX-$(call DEMDEC, MATROSKA, H264) += fate-mkv-1242
+fate-mkv-1242: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/1242-small.mkv -c copy -vframes 11
+
 FATE_SAMPLES_DEMUX-$(CONFIG_MLV_DEMUXER) += fate-mlv-demux
 fate-mlv-demux: CMD = crc -i $(TARGET_SAMPLES)/mlv/M19-0333-cut.MLV -c copy
 
+FATE_SAMPLES_DEMUX-$(CONFIG_MOV_DEMUXER) += fate-mov-mp3-demux
+fate-mov-mp3-demux: CMD = framecrc -i $(TARGET_SAMPLES)/mpegaudio/packed_maindata.mp3.mp4 -c copy
+
+FATE_SAMPLES_DEMUX-$(CONFIG_MPEGTS_DEMUXER) += fate-ts-opus-demux
+fate-ts-opus-demux: CMD = framecrc -i $(TARGET_SAMPLES)/opus/test-8-7.1.opus-small.ts -c copy
+
 FATE_SAMPLES_DEMUX-$(CONFIG_MTV_DEMUXER) += fate-mtv
 fate-mtv: CMD = framecrc -i $(TARGET_SAMPLES)/mtv/comedian_auto-partial.mtv -c copy
 
-FATE_SAMPLES_DEMUX-$(CONFIG_MXF_DEMUXER) += fate-mxf-demux
+FATE_SAMPLES_DEMUX-$(call DEMDEC, MXF, MPEG4) += fate-mxf-demux
 fate-mxf-demux: CMD = framecrc -i $(TARGET_SAMPLES)/mxf/C0023S01.mxf -acodec copy -vcodec copy
 
-FATE_SAMPLES_DEMUX-$(CONFIG_NC_DEMUXER) += fate-nc-demux
+FATE_SAMPLES_DEMUX-$(call ALLYES, NC_DEMUXER MPEG4VIDEO_PARSER) += fate-nc-demux
 fate-nc-demux: CMD = framecrc -i $(TARGET_SAMPLES)/nc-camera/nc-sample-partial -vcodec copy
 
 FATE_SAMPLES_DEMUX-$(CONFIG_NISTSPHERE_DEMUXER) += fate-nistsphere-demux
@@ -71,6 +84,9 @@ fate-nistsphere-demux: CMD = crc -i $(TARGET_SAMPLES)/nistsphere/nist-ulaw.nist
 FATE_SAMPLES_DEMUX-$(CONFIG_NSV_DEMUXER) += fate-nsv-demux
 fate-nsv-demux: CMD = framecrc -i $(TARGET_SAMPLES)/nsv/witchblade-51kbps.nsv -t 6 -vcodec copy -acodec copy
 
+FATE_SAMPLES_DEMUX-$(CONFIG_OGG_DEMUXER) += fate-oggopus-demux
+fate-oggopus-demux: CMD = framecrc -i $(TARGET_SAMPLES)/ogg/intro-partial.opus -c:a copy
+
 FATE_SAMPLES_DEMUX-$(CONFIG_OGG_DEMUXER) += fate-oggvp8-demux
 fate-oggvp8-demux: CMD = framecrc -i $(TARGET_SAMPLES)/ogg/videotest.ogv -c:v copy
 
@@ -107,10 +123,13 @@ fate-siff-demux: CMD = framecrc -i $(TARGET_SAMPLES)/SIFF/INTRO_B.VB -c copy
 FATE_SAMPLES_DEMUX-$(CONFIG_SMJPEG_DEMUXER) += fate-smjpeg-demux
 fate-smjpeg-demux: CMD = framecrc -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -c copy
 
+FATE_SAMPLES_DEMUX-$(CONFIG_WAV_DEMUXER) += fate-wav-ac3
+fate-wav-ac3: CMD = framecrc -i $(TARGET_SAMPLES)/ac3/diatonis_invisible_order_anfos_ac3-small.wav -c copy
+
 FATE_SAMPLES_DEMUX-$(CONFIG_WSAUD_DEMUXER) += fate-westwood-aud
 fate-westwood-aud: CMD = framecrc -i $(TARGET_SAMPLES)/westwood-aud/excellent.aud -c copy
 
-FATE_SAMPLES_DEMUX-$(CONFIG_WTV_DEMUXER) += fate-wtv-demux
+FATE_SAMPLES_DEMUX-$(call ALLYES, WTV_DEMUXER MPEGVIDEO_PARSER) += fate-wtv-demux
 fate-wtv-demux: CMD = framecrc -i $(TARGET_SAMPLES)/wtv/law-and-order-partial.wtv -vcodec copy -acodec copy
 
 FATE_SAMPLES_DEMUX-$(CONFIG_XMV_DEMUXER) += fate-xmv-demux
@@ -119,6 +138,9 @@ fate-xmv-demux: CMD = framecrc -i $(TARGET_SAMPLES)/xmv/logos1p.fmv -vcodec copy
 FATE_SAMPLES_DEMUX-$(CONFIG_XWMA_DEMUXER) += fate-xwma-demux
 fate-xwma-demux: CMD = crc -i $(TARGET_SAMPLES)/xwma/ergon.xwma -acodec copy
 
+FATE_SAMPLES_DEMUX-$(CONFIG_MPEGTS_DEMUXER) += fate-ts-demux
+fate-ts-demux: CMD = framecrc -i $(TARGET_SAMPLES)/ac3/mp3ac325-4864-small.ts -codec copy
+
 FATE_SAMPLES_DEMUX += $(FATE_SAMPLES_DEMUX-yes)
 FATE_SAMPLES_FFMPEG += $(FATE_SAMPLES_DEMUX)
 fate-demux: $(FATE_SAMPLES_DEMUX)
diff --git a/tests/fate/dnxhd.mak b/tests/fate/dnxhd.mak
index 6d79f3b..b7f8b17 100644
--- a/tests/fate/dnxhd.mak
+++ b/tests/fate/dnxhd.mak
@@ -1,8 +1,10 @@
 FATE_DNXHD = fate-dnxhd-mbaff     \
-             fate-dnxhr-444
+             fate-dnxhr-444       \
+             fate-dnxhr-parse
 
 FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, DNXHD) += $(FATE_DNXHD)
 fate-dnxhd: $(FATE_DNXHD) $(FATE_VCODEC_DNXHD)
 
 fate-dnxhd-mbaff: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhd100_cid1260.mov -pix_fmt yuv422p10le
 fate-dnxhr-444:   CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhr444_cid1270.mov -pix_fmt yuv444p10le
+fate-dnxhr-parse: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhr_cid1274.dnxhr -pix_fmt yuv422p
diff --git a/tests/fate/fft.mak b/tests/fate/fft.mak
index 9fdca2b..f42dded 100644
--- a/tests/fate/fft.mak
+++ b/tests/fate/fft.mak
@@ -1,8 +1,8 @@
 define DEF_FFT
-FATE_FFT-$(CONFIG_DCT)  += fate-dct1d-$(1) fate-idct1d-$(1)
-FATE_FFT-$(CONFIG_FFT)  += fate-fft-$(1)   fate-ifft-$(1)
-FATE_FFT-$(CONFIG_MDCT) += fate-mdct-$(1)  fate-imdct-$(1)
-FATE_FFT-$(CONFIG_RDFT) += fate-rdft-$(1)  fate-irdft-$(1)
+FATE_DCT-$(CONFIG_DCT)   += fate-dct1d-$(1) fate-idct1d-$(1)
+FATE_FFT-$(CONFIG_FFT)   += fate-fft-$(1)   fate-ifft-$(1)
+FATE_MDCT-$(CONFIG_MDCT) += fate-mdct-$(1)  fate-imdct-$(1)
+FATE_RDFT-$(CONFIG_RDFT) += fate-rdft-$(1)  fate-irdft-$(1)
 
 fate-fft-$(N):    ARGS = -n$(1)
 fate-ifft-$(N):   ARGS = -n$(1) -i
@@ -16,14 +16,19 @@ endef
 
 $(foreach N, 4 5 6 7 8 9 10 11 12, $(eval $(call DEF_FFT,$(N))))
 
+fate-dct-float: $(FATE_DCT-yes)
 fate-fft-float: $(FATE_FFT-yes)
-$(FATE_FFT-yes): libavcodec/fft-test$(EXESUF)
-$(FATE_FFT-yes): CMD = run libavcodec/fft-test $(CPUFLAGS:%=-c%) $(ARGS)
-$(FATE_FFT-yes): REF = /dev/null
+fate-mdct-float: $(FATE_MDCT-yes)
+fate-rdft-float: $(FATE_RDFT-yes)
+
+FATE_FFT_ALL = $(FATE_DCT-yes) $(FATE_FFT-yes) $(FATE_MDCT-yes) $(FATE_RDFT-yes)
+
+$(FATE_FFT_ALL): libavcodec/tests/fft$(EXESUF)
+$(FATE_FFT_ALL): CMD = run libavcodec/tests/fft $(CPUFLAGS:%=-c%) $(ARGS)
 
 define DEF_FFT_FIXED
-FATE_FFT_FIXED-$(CONFIG_FFT)  += fate-fft-fixed-$(1)  fate-ifft-fixed-$(1)
-FATE_FFT_FIXED-$(CONFIG_MDCT) += fate-mdct-fixed-$(1) fate-imdct-fixed-$(1)
+FATE_FFT_FIXED-$(CONFIG_FFT)   += fate-fft-fixed-$(1)  fate-ifft-fixed-$(1)
+FATE_MDCT_FIXED-$(CONFIG_MDCT) += fate-mdct-fixed-$(1) fate-imdct-fixed-$(1)
 
 fate-fft-fixed-$(1):   ARGS = -n$(1)
 fate-ifft-fixed-$(1):  ARGS = -n$(1) -i
@@ -34,9 +39,14 @@ endef
 $(foreach N, 4 5 6 7 8 9 10 11 12, $(eval $(call DEF_FFT_FIXED,$(N))))
 
 fate-fft-fixed: $(FATE_FFT_FIXED-yes)
-$(FATE_FFT_FIXED-yes): libavcodec/fft-fixed-test$(EXESUF)
-$(FATE_FFT_FIXED-yes): CMD = run libavcodec/fft-fixed-test $(CPUFLAGS:%=-c%) $(ARGS)
-$(FATE_FFT_FIXED-yes): REF = /dev/null
+fate-mdct-fixed: $(FATE_MDCT_FIXED-yes)
+
+FATE_FFT_FIXED_ALL = $(FATE_FFT_FIXED-yes) $(FATE_MDCT_FIXED-yes)
+
+$(FATE_FFT_FIXED_ALL): libavcodec/tests/fft-fixed$(EXESUF)
+$(FATE_FFT_FIXED_ALL): CMD = run libavcodec/tests/fft-fixed $(CPUFLAGS:%=-c%) $(ARGS)
+
+$(FATE_FFT_ALL) $(FATE_FFT_FIXED_ALL): REF = /dev/null
 
 define DEF_FFT_FIXED32
 FATE_FFT_FIXED32 += fate-fft-fixed32-$(1)   fate-ifft-fixed32-$(1)  \
@@ -50,10 +60,15 @@ endef
 
 $(foreach N, 4 5 6 7 8 9 10 11 12, $(eval $(call DEF_FFT_FIXED32,$(N))))
 
-fate-fft-fixed32-test: $(FATE_FFT_FIXED32)
-$(FATE_FFT_FIXED32): libavcodec/fft-fixed32-test$(EXESUF)
-$(FATE_FFT_FIXED32): CMD = run libavcodec/fft-fixed32-test $(CPUFLAGS:%=-c%) $(ARGS)
+fate-fft-fixed32: $(FATE_FFT_FIXED32)
+$(FATE_FFT_FIXED32): libavcodec/tests/fft-fixed32$(EXESUF)
+$(FATE_FFT_FIXED32): CMD = run libavcodec/tests/fft-fixed32 $(CPUFLAGS:%=-c%) $(ARGS)
 $(FATE_FFT_FIXED32): REF = /dev/null
 
-FATE-$(call ALLYES, AVCODEC FFT MDCT) += $(FATE_FFT-yes) $(FATE_FFT_FIXED-yes) $(FATE_FFT_FIXED32)
-fate-fft: $(FATE_FFT-yes) $(FATE_FFT_FIXED-yes) $(FATE_FFT_FIXED32)
+fate-dct: fate-dct-float
+fate-fft: fate-fft-float fate-fft-fixed fate-fft-fixed32
+fate-mdct: fate-mdct-float fate-mdct-fixed
+fate-rdft: fate-rdft-float
+
+FATE-$(call ALLYES, AVCODEC FFT MDCT) += $(FATE_FFT_ALL) $(FATE_FFT_FIXED_ALL) $(FATE_FFT_FIXED32)
+fate-fft-all: $(FATE_FFT_ALL) $(FATE_FFT_FIXED_ALL) $(FATE_FFT_FIXED32)
diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak
index 85a36d2..acac4c0 100644
--- a/tests/fate/filter-audio.mak
+++ b/tests/fate/filter-audio.mak
@@ -3,6 +3,97 @@ fate-filter-adelay: tests/data/asynth-44100-2.wav
 fate-filter-adelay: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
 fate-filter-adelay: CMD = framecrc -i $(SRC) -af adelay=42
 
+FATE_AFILTER-$(call FILTERDEMDECENCMUX, AECHO, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-aecho
+fate-filter-aecho: tests/data/asynth-44100-2.wav
+fate-filter-aecho: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-aecho: CMD = framecrc -i $(SRC) -af aecho=0.5:0.5:32:0.5
+
+FATE_FILTER_AEMPHASIS += fate-filter-aemphasis-50fm
+fate-filter-aemphasis-50fm: tests/data/asynth-44100-2.wav
+fate-filter-aemphasis-50fm: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-aemphasis-50fm: CMD = framecrc -i $(SRC) -af aemphasis=1:5:reproduction:50fm
+
+FATE_FILTER_AEMPHASIS += fate-filter-aemphasis-75kf
+fate-filter-aemphasis-75kf: tests/data/asynth-44100-2.wav
+fate-filter-aemphasis-75kf: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-aemphasis-75kf: CMD = framecrc -i $(SRC) -af aemphasis=2:8:reproduction:75kf
+
+FATE_AFILTER-$(call FILTERDEMDECENCMUX, AEMPHASIS, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_FILTER_AEMPHASIS)
+
+FATE_FILTER_AFADE += fate-filter-afade-qsin
+fate-filter-afade-qsin: tests/data/asynth-44100-2.wav
+fate-filter-afade-qsin: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-afade-qsin: CMD = framecrc -i $(SRC) -af afade=t=in:ss=0:d=2:curve=qsin
+
+FATE_FILTER_AFADE += fate-filter-afade-iqsin
+fate-filter-afade-iqsin: tests/data/asynth-44100-2.wav
+fate-filter-afade-iqsin: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-afade-iqsin: CMD = framecrc -i $(SRC) -af afade=t=in:ss=0:d=2:curve=iqsin
+
+FATE_FILTER_AFADE += fate-filter-afade-esin
+fate-filter-afade-esin: tests/data/asynth-44100-2.wav
+fate-filter-afade-esin: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-afade-esin: CMD = framecrc -i $(SRC) -af afade=t=in:ss=0:d=2:curve=esin
+
+FATE_FILTER_AFADE += fate-filter-afade-hsin
+fate-filter-afade-hsin: tests/data/asynth-44100-2.wav
+fate-filter-afade-hsin: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-afade-hsin: CMD = framecrc -i $(SRC) -af afade=t=in:ss=0:d=2:curve=hsin
+
+FATE_FILTER_AFADE += fate-filter-afade-exp
+fate-filter-afade-exp: tests/data/asynth-44100-2.wav
+fate-filter-afade-exp: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-afade-exp: CMD = framecrc -i $(SRC) -af afade=t=in:ss=0:d=2:curve=exp
+
+FATE_FILTER_AFADE += fate-filter-afade-log
+fate-filter-afade-log: tests/data/asynth-44100-2.wav
+fate-filter-afade-log: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-afade-log: CMD = framecrc -i $(SRC) -af afade=t=in:ss=1:d=2.5:curve=log
+
+FATE_AFILTER-$(call FILTERDEMDECENCMUX, AFADE, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_FILTER_AFADE)
+
+FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, ACROSSFADE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-acrossfade
+fate-filter-acrossfade: tests/data/asynth-44100-2.wav
+fate-filter-acrossfade: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-acrossfade: SRC2 = $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
+fate-filter-acrossfade: CMD = framecrc -i $(SRC) -i $(SRC2) -filter_complex acrossfade=d=2:c1=log:c2=exp
+
+FATE_AFILTER-$(call FILTERDEMDECENCMUX, AFADE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-agate
+fate-filter-agate: tests/data/asynth-44100-2.wav
+fate-filter-agate: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-agate: CMD = framecrc -i $(SRC) -af agate=level_in=10:range=0:threshold=1:ratio=1:attack=1:knee=1:makeup=4
+
+FATE_AFILTER-$(call FILTERDEMDECENCMUX, AFADE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-alimiter
+fate-filter-alimiter: tests/data/asynth-44100-2.wav
+fate-filter-alimiter: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-alimiter: CMD = framecrc -i $(SRC) -af alimiter=level_in=1:level_out=2:limit=0.2
+
+FATE_AFILTER-$(call FILTERDEMDECENCMUX, AMERGE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-amerge
+fate-filter-amerge: tests/data/asynth-44100-1.wav
+fate-filter-amerge: SRC = $(TARGET_PATH)/tests/data/asynth-44100-1.wav
+fate-filter-amerge: CMD = framecrc -i $(SRC) -i $(SRC) -filter_complex "[0:a][1:a]amerge=inputs=2[aout]" -map "[aout]"
+
+FATE_AFILTER-$(call FILTERDEMDECENCMUX, APAD, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-apad
+fate-filter-apad: tests/data/asynth-44100-2.wav
+fate-filter-apad: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-apad: CMD = framecrc -i $(SRC) -af apad=pad_len=10
+
+FATE_AFILTER-$(call FILTERDEMDECENCMUX, ANEQUALIZER, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-anequalizer
+fate-filter-anequalizer: tests/data/asynth-44100-2.wav
+fate-filter-anequalizer: tests/data/filtergraphs/anequalizer
+fate-filter-anequalizer: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
+fate-filter-anequalizer: CMD = framecrc -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/anequalizer
+
+tests/data/hls-list.m3u8: TAG = GEN
+tests/data/hls-list.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data
+	$(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \
+        -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t)::d=20" -f segment -segment_time 10 -map 0 -flags +bitexact -codec:a mp2fixed \
+        -segment_list $(TARGET_PATH)/$@ -y $(TARGET_PATH)/tests/data/hls-out-%03d.ts 2>/dev/null
+
+FATE_AFILTER-$(call ALLYES, HLS_DEMUXER MPEGTS_MUXER MPEGTS_DEMUXER AEVALSRC_FILTER LAVFI_INDEV MP2FIXED_ENCODER) += fate-filter-hls
+fate-filter-hls: tests/data/hls-list.m3u8
+fate-filter-hls: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hls-list.m3u8
+
 FATE_AMIX += fate-filter-amix-simple
 fate-filter-amix-simple: CMD = ffmpeg -filter_complex amix -i $(SRC) -ss 3 -i $(SRC1) -f f32le -
 fate-filter-amix-simple: REF = $(SAMPLES)/filter/amix_simple.pcm
@@ -17,20 +108,20 @@ fate-filter-amix-transition: SRC2 = $(TARGET_PATH)/tests/data/asynth-44100-2-3.w
 fate-filter-amix-transition: CMD = ffmpeg -filter_complex amix=inputs=3:dropout_transition=0.5 -i $(SRC) -ss 2 -i $(SRC1) -ss 4 -i $(SRC2) -f f32le -
 fate-filter-amix-transition: REF = $(SAMPLES)/filter/amix_transition.pcm
 
-FATE_AFILTER-$(call FILTERDEMDECENCMUX, AMIX, WAV, PCM_S16LE, PCM_F32LE, PCM_F32LE) += $(FATE_AMIX)
+FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, AMIX, WAV, PCM_S16LE, PCM_F32LE, PCM_F32LE) += $(FATE_AMIX)
 $(FATE_AMIX): tests/data/asynth-44100-2.wav tests/data/asynth-44100-2-2.wav
 $(FATE_AMIX): SRC  = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
 $(FATE_AMIX): SRC1 = $(TARGET_PATH)/tests/data/asynth-44100-2-2.wav
 $(FATE_AMIX): CMP  = oneoff
 $(FATE_AMIX): CMP_UNIT = f32
 
-FATE_AFILTER-$(call FILTERDEMDECMUX, ASYNCTS, FLV, NELLYMOSER, PCM_S16LE) += fate-filter-asyncts
+FATE_AFILTER_SAMPLES-$(call FILTERDEMDECMUX, ASYNCTS, FLV, NELLYMOSER, PCM_S16LE) += fate-filter-asyncts
 fate-filter-asyncts: SRC = $(TARGET_SAMPLES)/nellymoser/nellymoser-discont.flv
 fate-filter-asyncts: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af asyncts
 fate-filter-asyncts: CMP = oneoff
 fate-filter-asyncts: REF = $(SAMPLES)/nellymoser/nellymoser-discont-async-v3.pcm
 
-FATE_FILTER-$(CONFIG_ARESAMPLE_FILTER) += fate-filter-aresample
+FATE_AFILTER_SAMPLES-$(CONFIG_ARESAMPLE_FILTER) += fate-filter-aresample
 fate-filter-aresample: SRC = $(TARGET_SAMPLES)/nellymoser/nellymoser-discont.flv
 fate-filter-aresample: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af aresample=min_comp=0.001:min_hard_comp=0.1:first_pts=0
 fate-filter-aresample: CMP = oneoff
@@ -50,7 +141,7 @@ fate-filter-atrim-time: CMD = framecrc -i $(SRC) -af atrim=0.1:0.2
 $(FATE_ATRIM): tests/data/asynth-44100-2.wav
 $(FATE_ATRIM): SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
 
-FATE_FILTER-$(call FILTERDEMDECENCMUX, ATRIM, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_ATRIM)
+FATE_AFILTER-$(call FILTERDEMDECENCMUX, ATRIM, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_ATRIM)
 
 FATE_FILTER_CHANNELMAP += fate-filter-channelmap-one-int
 fate-filter-channelmap-one-int: tests/data/filtergraphs/channelmap_one_int
@@ -92,9 +183,16 @@ fate-filter-volume: CMD = md5 -i $(SRC) -af aperms=random,volume=precision=fixed
 fate-filter-volume: CMP = oneline
 fate-filter-volume: REF = 4d6ba75ef3e32d305d066b9bc771d6f4
 
+FATE_AFILTER_SAMPLES-$(call FILTERDEMDECENCMUX, HDCD, FLAC, FLAC, PCM_S24LE, PCM_S24LE) += fate-filter-hdcd
+fate-filter-hdcd: SRC = $(TARGET_SAMPLES)/filter/hdcd.flac
+fate-filter-hdcd: CMD = md5 -i $(SRC) -af hdcd -f s24le
+fate-filter-hdcd: CMP = oneline
+fate-filter-hdcd: REF = 5db465a58d2fd0d06ca944b883b33476
+
 FATE_AFILTER-yes += fate-filter-formats
-fate-filter-formats: libavfilter/formats-test$(EXESUF)
-fate-filter-formats: CMD = run libavfilter/formats-test
+fate-filter-formats: libavfilter/tests/formats$(EXESUF)
+fate-filter-formats: CMD = run libavfilter/tests/formats
 
-FATE_SAMPLES_AVCONV += $(FATE_AFILTER-yes)
-fate-afilter: $(FATE_AFILTER-yes)
+FATE_SAMPLES_AVCONV += $(FATE_AFILTER_SAMPLES-yes)
+FATE_FFMPEG += $(FATE_AFILTER-yes)
+fate-afilter: $(FATE_AFILTER-yes) $(FATE_AFILTER_SAMPLES-yes)
diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak
index 4186996..0084802 100644
--- a/tests/fate/filter-video.mak
+++ b/tests/fate/filter-video.mak
@@ -1,4 +1,4 @@
-FATE_FILTER-$(call ALLYES, PERMS_FILTER DELOGO_FILTER RM_DEMUXER RV30_DECODER) += fate-filter-delogo
+FATE_FILTER_SAMPLES-$(call ALLYES, PERMS_FILTER DELOGO_FILTER RM_DEMUXER RV30_DECODER) += fate-filter-delogo
 fate-filter-delogo: CMD = framecrc -i $(TARGET_SAMPLES)/real/rv30.rm -vf perms=random,delogo=show=0:x=290:y=25:w=26:h=16 -an
 
 FATE_YADIF += fate-filter-yadif-mode0
@@ -13,7 +13,7 @@ fate-filter-yadif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAM
 FATE_YADIF += fate-filter-yadif16
 fate-filter-yadif16: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p16le -vframes 30 -vf yadif=0
 
-FATE_FILTER-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += $(FATE_YADIF)
+FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += $(FATE_YADIF)
 
 FATE_W3FDIF += fate-filter-w3fdif-simple
 fate-filter-w3fdif-simple: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 30 -vf w3fdif=0
@@ -21,7 +21,7 @@ fate-filter-w3fdif-simple: CMD = framecrc -flags bitexact -idct simple -i $(TARG
 FATE_W3FDIF += fate-filter-w3fdif-complex
 fate-filter-w3fdif-complex: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 30 -vf w3fdif=1
 
-FATE_FILTER-$(call FILTERDEMDEC, W3FDIF, MPEGTS, MPEG2VIDEO) += $(FATE_W3FDIF)
+FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, W3FDIF, MPEGTS, MPEG2VIDEO) += $(FATE_W3FDIF)
 
 FATE_MCDEINT += fate-filter-mcdeint-fast
 fate-filter-mcdeint-fast: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 30 -vf mcdeint=fast
@@ -29,12 +29,12 @@ fate-filter-mcdeint-fast: CMD = framecrc -flags bitexact -idct simple -i $(TARGE
 FATE_MCDEINT += fate-filter-mcdeint-medium
 fate-filter-mcdeint-medium: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -vframes 30 -vf mcdeint=mode=medium
 
-FATE_FILTER-$(call ALLYES, MCDEINT_FILTER, MPEGTS_DEMUXER, MPEG2VIDEO_DECODER SNOW_ENCODER) += $(FATE_MCDEINT)
+FATE_FILTER_SAMPLES-$(call ALLYES, MCDEINT_FILTER, MPEGTS_DEMUXER, MPEG2VIDEO_DECODER SNOW_ENCODER) += $(FATE_MCDEINT)
 
-FATE_FILTER-$(call ALLYES, CODECVIEW_FILTER RM_DEMUXER RV40_DECODER) += fate-filter-codecview-mvs
+FATE_FILTER_SAMPLES-$(call ALLYES, CODECVIEW_FILTER RM_DEMUXER RV40_DECODER) += fate-filter-codecview-mvs
 fate-filter-codecview-mvs: CMD = framecrc -flags2 +export_mvs -i $(TARGET_SAMPLES)/real/spygames-2MB.rmvb -vf codecview=mv=pf+bf+bb -vframes 60 -an
 
-FATE_FILTER-$(call ALLYES, SHOWPALETTE_FILTER FLIC_DEMUXER FLIC_DECODER) += fate-filter-showpalette
+FATE_FILTER_SAMPLES-$(call ALLYES, SHOWPALETTE_FILTER FLIC_DEMUXER FLIC_DECODER) += fate-filter-showpalette
 fate-filter-showpalette: CMD = framecrc -i $(TARGET_SAMPLES)/fli/fli-engines.fli -vf showpalette=3 -pix_fmt bgra
 
 FATE_FILTER_PALETTEGEN += fate-filter-palettegen-1
@@ -44,7 +44,7 @@ FATE_FILTER_PALETTEGEN += fate-filter-palettegen-2
 fate-filter-palettegen-2: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -vf palettegen=max_colors=128:reserve_transparent=0:stats_mode=diff -pix_fmt bgra
 
 fate-filter-palettegen: $(FATE_FILTER_PALETTEGEN)
-FATE_FILTER-$(call ALLYES, PALETTEGEN_FILTER MATROSKA_DEMUXER H264_DECODER) += $(FATE_FILTER_PALETTEGEN)
+FATE_FILTER_SAMPLES-$(call ALLYES, PALETTEGEN_FILTER MATROSKA_DEMUXER H264_DECODER) += $(FATE_FILTER_PALETTEGEN)
 
 FATE_FILTER_PALETTEUSE += fate-filter-paletteuse-nodither
 fate-filter-paletteuse-nodither: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=none -pix_fmt bgra
@@ -56,9 +56,7 @@ FATE_FILTER_PALETTEUSE += fate-filter-paletteuse-sierra2_4a
 fate-filter-paletteuse-sierra2_4a: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=sierra2_4a:diff_mode=rectangle -pix_fmt bgra
 
 fate-filter-paletteuse: $(FATE_FILTER_PALETTEUSE)
-FATE_FILTER-$(call ALLYES, PALETTEUSE_FILTER MATROSKA_DEMUXER H264_DECODER IMAGE2_DEMUXER PNG_DECODER) += $(FATE_FILTER_PALETTEUSE)
-
-FATE_SAMPLES_AVCONV += $(FATE_FILTER-yes)
+FATE_FILTER_SAMPLES-$(call ALLYES, PALETTEUSE_FILTER MATROSKA_DEMUXER H264_DECODER IMAGE2_DEMUXER PNG_DECODER) += $(FATE_FILTER_PALETTEUSE)
 
 FATE_FILTER-$(call ALLYES, AVDEVICE LIFE_FILTER) += fate-filter-lavd-life
 fate-filter-lavd-life: CMD = framecrc -f lavfi -i life=s=40x40:r=5:seed=42:mold=64:ratio=0.1:death_color=red:life_color=green -t 2
@@ -300,28 +298,32 @@ FATE_FILTER_VSYNTH-$(CONFIG_TRIM_FILTER) += $(FATE_TRIM)
 FATE_FILTER_VSYNTH-$(CONFIG_UNSHARP_FILTER) += fate-filter-unsharp
 fate-filter-unsharp: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf unsharp=11:11:-1.5:11:11:-1.5
 
-FATE_FILTER-$(call ALLYES, SMJPEG_DEMUXER MJPEG_DECODER PERMS_FILTER HQDN3D_FILTER) += fate-filter-hqdn3d-sample
+FATE_FILTER_SAMPLES-$(call ALLYES, SMJPEG_DEMUXER MJPEG_DECODER PERMS_FILTER HQDN3D_FILTER) += fate-filter-hqdn3d-sample
 fate-filter-hqdn3d-sample: tests/data/filtergraphs/hqdn3d
 fate-filter-hqdn3d-sample: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/hqdn3d -an
 
+FATE_FILTER_SAMPLES-$(call ALLYES, MATROSKA_DEMUXER OVERLAY_FILTER H264_DECODER DVDSUB_DECODER) += fate-filter-overlay-dvdsub-2397
+fate-filter-overlay-dvdsub-2397: tests/data/filtergraphs/overlay-dvdsub-2397
+fate-filter-overlay-dvdsub-2397: CMD = framecrc -flags bitexact -i $(TARGET_SAMPLES)/filter/242_4.mkv -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay-dvdsub-2397 -c:a copy
+
 FATE_FILTER_HQX-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER HQX_FILTER) = fate-filter-hq2x fate-filter-hq3x fate-filter-hq4x
-FATE_FILTER-yes += $(FATE_FILTER_HQX-yes)
+FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_HQX-yes)
 fate-filter-hq2x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=2 -pix_fmt bgra
 fate-filter-hq3x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=3 -pix_fmt bgra
 fate-filter-hq4x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=4 -pix_fmt bgra
 fate-filter-hqx: $(FATE_FILTER_HQX-yes)
 
 FATE_FILTER_XBR-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER XBR_FILTER) = fate-filter-2xbr fate-filter-3xbr fate-filter-4xbr
-FATE_FILTER-yes += $(FATE_FILTER_XBR-yes)
+FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_XBR-yes)
 fate-filter-2xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf xbr=2 -pix_fmt bgra
 fate-filter-3xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf xbr=3 -pix_fmt bgra
 fate-filter-4xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf xbr=4 -pix_fmt bgra
 fate-filter-xbr: $(FATE_FILTER_XBR-yes)
 
-FATE_FILTER-$(call ALLYES, UTVIDEO_DECODER AVI_DEMUXER PERMS_FILTER CURVES_FILTER) += fate-filter-curves
+FATE_FILTER_SAMPLES-$(call ALLYES, UTVIDEO_DECODER AVI_DEMUXER PERMS_FILTER CURVES_FILTER) += fate-filter-curves
 fate-filter-curves: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgb_median.avi -vf perms=random,curves=vintage
 
-FATE_FILTER-$(call ALLYES, VMD_DEMUXER VMDVIDEO_DECODER FORMAT_FILTER PERMS_FILTER GRADFUN_FILTER) += fate-filter-gradfun-sample
+FATE_FILTER_SAMPLES-$(call ALLYES, VMD_DEMUXER VMDVIDEO_DECODER FORMAT_FILTER PERMS_FILTER GRADFUN_FILTER) += fate-filter-gradfun-sample
 fate-filter-gradfun-sample: tests/data/filtergraphs/gradfun
 fate-filter-gradfun-sample: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -filter_script $(TARGET_PATH)/tests/data/filtergraphs/gradfun -an -frames:v 20
 
@@ -332,6 +334,11 @@ fate-filter-concat: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/d
 FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER FPS_FILTER MPDECIMATE_FILTER) += fate-filter-mpdecimate
 fate-filter-mpdecimate: CMD = framecrc -lavfi testsrc2=r=2:d=10,fps=3,mpdecimate -r 3 -pix_fmt yuv420p
 
+FATE_FILTER_SAMPLES-$(call ALLYES, MOV_DEMUXER FPS_FILTER QTRLE_DECODER) += fate-filter-fps-cfr fate-filter-fps fate-filter-fps-r
+fate-filter-fps-cfr: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vsync cfr -pix_fmt yuv420p
+fate-filter-fps-r:   CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vf fps -pix_fmt yuv420p
+fate-filter-fps:     CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -vf fps=30 -pix_fmt yuv420p
+
 FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER SPLIT_FILTER ALPHAEXTRACT_FILTER ALPHAMERGE_FILTER) += fate-filter-alphaextract_alphamerge_rgb
 fate-filter-alphaextract_alphamerge_rgb: tests/data/filtergraphs/alphamerge_alphaextract_rgb
 fate-filter-alphaextract_alphamerge_rgb: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_rgb
@@ -578,7 +585,7 @@ fate-filter-pixfmts-tinterlace_pad: CMD = pixfmts "pad"
 FATE_FILTER_PIXFMTS-$(CONFIG_VFLIP_FILTER) += fate-filter-pixfmts-vflip
 fate-filter-pixfmts-vflip: CMD = pixfmts
 
-$(FATE_FILTER_PIXFMTS-yes): libavfilter/filtfmts-test$(EXESUF)
+$(FATE_FILTER_PIXFMTS-yes): libavfilter/tests/filtfmts$(EXESUF)
 FATE_FILTER_VSYNTH-$(CONFIG_FORMAT_FILTER) += $(FATE_FILTER_PIXFMTS-yes)
 
 fate-filter-pixfmts: $(FATE_FILTER_PIXFMTS-yes)
@@ -599,6 +606,12 @@ FATE_METADATA_FILTER-$(call ALLYES, $(SCENEDETECT_DEPS)) += fate-filter-metadata
 fate-filter-metadata-scenedetect: SRC = $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3.mov
 fate-filter-metadata-scenedetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',select=gt(scene\,.4)"
 
+CROPDETECT_DEPS = FFPROBE LAVFI_INDEV MOVIE_FILTER CROPDETECT_FILTER SCALE_FILTER \
+                  AVCODEC AVDEVICE MOV_DEMUXER H264_DECODER
+FATE_METADATA_FILTER-$(call ALLYES, $(CROPDETECT_DEPS)) += fate-filter-metadata-cropdetect
+fate-filter-metadata-cropdetect: SRC = $(TARGET_SAMPLES)/filter/cropdetect.mp4
+fate-filter-metadata-cropdetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',cropdetect=max_outliers=3"
+
 SILENCEDETECT_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER AMR_DEMUXER AMRWB_DECODER SILENCEDETECT_FILTER
 FATE_METADATA_FILTER-$(call ALLYES, $(SILENCEDETECT_DEPS)) += fate-filter-metadata-silencedetect
 fate-filter-metadata-silencedetect: SRC = $(TARGET_SAMPLES)/amrwb/seed-12k65.awb
@@ -609,8 +622,29 @@ FATE_METADATA_FILTER-$(call ALLYES, $(EBUR128_METADATA_DEPS)) += fate-filter-met
 fate-filter-metadata-ebur128: SRC = $(TARGET_SAMPLES)/filter/seq-3341-7_seq-3342-5-24bit.flac
 fate-filter-metadata-ebur128: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',ebur128=metadata=1"
 
+READVITC_METADATA_DEPS = FFPROBE LAVFI_INDEV MOVIE_FILTER AVCODEC AVDEVICE \
+                         AVI_DEMUXER FFVHUFF_DECODER READVITC_FILTER
+FATE_METADATA_FILTER-$(call ALLYES, $(READVITC_METADATA_DEPS)) += fate-filter-metadata-readvitc-def
+fate-filter-metadata-readvitc-def: SRC = $(TARGET_SAMPLES)/filter/sample-vitc.avi
+fate-filter-metadata-readvitc-def: CMD = run $(FILTER_METADATA_COMMAND) "movie='$(SRC)',readvitc"
+
+FATE_METADATA_FILTER-$(call ALLYES, $(READVITC_METADATA_DEPS)) += fate-filter-metadata-readvitc-thr
+fate-filter-metadata-readvitc-thr: SRC = $(TARGET_SAMPLES)/filter/sample-vitc.avi
+fate-filter-metadata-readvitc-thr: CMD = run $(FILTER_METADATA_COMMAND) "movie='$(SRC)',readvitc=thr_b=0.3:thr_w=0.5"
+
+tests/data/file4560-override2rotate0.mov: TAG = GEN
+tests/data/file4560-override2rotate0.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data
+	$(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \
+	-i $(TARGET_SAMPLES)/filter/sample-in-issue-505.mov -c copy -flags +bitexact -metadata:s:v:0 rotate=0 $(TARGET_PATH)/$@ -y 2>/dev/null
+
+FATE_FILTER_SAMPLES-$(call ALLYES, MOV_DEMUXER H264_DECODER AAC_FIXED_DECODER PCM_S16LE_ENCODER MOV_MUXER) += fate-filter-meta-4560-rotate0
+fate-filter-meta-4560-rotate0: tests/data/file4560-override2rotate0.mov
+fate-filter-meta-4560-rotate0: CMD = framecrc -flags +bitexact -c:a aac_fixed -i $(TARGET_PATH)/tests/data/file4560-override2rotate0.mov
+
 FATE_SAMPLES_FFPROBE += $(FATE_METADATA_FILTER-yes)
+FATE_SAMPLES_FFMPEG += $(FATE_FILTER_SAMPLES-yes)
+FATE_FFMPEG += $(FATE_FILTER-yes)
 
-fate-vfilter: $(FATE_FILTER-yes) $(FATE_FILTER_VSYNTH-yes)
+fate-vfilter: $(FATE_FILTER-yes) $(FATE_FILTER_SAMPLES-yes) $(FATE_FILTER_VSYNTH-yes)
 
 fate-filter: fate-afilter fate-vfilter $(FATE_METADATA_FILTER-yes)
diff --git a/tests/fate/gapless.mak b/tests/fate/gapless.mak
index 2fb005f..0253b9e 100644
--- a/tests/fate/gapless.mak
+++ b/tests/fate/gapless.mak
@@ -1,7 +1,125 @@
 FATE_GAPLESS-$(CONFIG_MP3_DEMUXER) += fate-gapless-mp3
 fate-gapless-mp3: CMD = gapless $(TARGET_SAMPLES)/gapless/gapless.mp3
 
+FATE_GAPLESS-$(CONFIG_MP3_DEMUXER) += fate-audiomatch-square-mp3
+fate-audiomatch-square-mp3: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/square3.mp3 $(TARGET_SAMPLES)/audiomatch/square3.wav
+
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-square-aac
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-16000-mono-lc-adts    fate-audiomatch-afconvert-16000-mono-lc-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-44100-mono-lc-adts    fate-audiomatch-afconvert-44100-mono-lc-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-16000-mono-he-adts    fate-audiomatch-afconvert-16000-mono-he-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-44100-mono-he-adts    fate-audiomatch-afconvert-44100-mono-he-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-16000-stereo-he-adts  fate-audiomatch-afconvert-16000-stereo-he-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-44100-stereo-he-adts  fate-audiomatch-afconvert-44100-stereo-he-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-16000-stereo-he2-adts fate-audiomatch-afconvert-16000-stereo-he2-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-44100-stereo-he2-adts fate-audiomatch-afconvert-44100-stereo-he2-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-16000-stereo-lc-adts  fate-audiomatch-afconvert-16000-stereo-lc-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-afconvert-44100-stereo-lc-adts  fate-audiomatch-afconvert-44100-stereo-lc-m4a
+
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-faac-16000-mono-lc-adts    fate-audiomatch-faac-16000-mono-lc-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-faac-44100-mono-lc-adts    fate-audiomatch-faac-44100-mono-lc-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-faac-16000-stereo-lc-adts  fate-audiomatch-faac-16000-stereo-lc-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-faac-44100-stereo-lc-adts  fate-audiomatch-faac-44100-stereo-lc-m4a
+
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-dolby-44100-mono-lc-mp4
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-dolby-44100-mono-he-mp4
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-dolby-44100-stereo-he-mp4
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-dolby-44100-stereo-he2-mp4
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-dolby-44100-stereo-lc-mp4
+
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-16000-mono-lc-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-44100-mono-lc-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-16000-mono-he-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-44100-mono-he-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-16000-stereo-he-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-44100-stereo-he-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-16000-stereo-he2-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-44100-stereo-he2-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-16000-stereo-lc-m4a
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-nero-44100-stereo-lc-m4a
+
+FATE_GAPLESS-$(CONFIG_MOV_DEMUXER) += fate-audiomatch-quicktime7-44100-stereo-lc-mp4 fate-audiomatch-quicktimeX-44100-stereo-lc-m4a
+
+fate-audiomatch-square-aac: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/square3.m4a $(TARGET_SAMPLES)/audiomatch/square3.wav
+
+fate-audiomatch-afconvert-16000-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.adts  $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav
+fate-audiomatch-afconvert-16000-mono-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav
+fate-audiomatch-afconvert-16000-mono-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_he.adts  $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav "-ac 1 -ar 16000"
+fate-audiomatch-afconvert-16000-mono-he-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_he.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav "-ac 1 -ar 16000"
+fate-audiomatch-afconvert-16000-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_lc.adts  $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav
+fate-audiomatch-afconvert-16000-stereo-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav
+fate-audiomatch-afconvert-16000-stereo-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he.adts  $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000"
+fate-audiomatch-afconvert-16000-stereo-he-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000"
+fate-audiomatch-afconvert-16000-stereo-he2-adts:CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he2.adts $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000"
+fate-audiomatch-afconvert-16000-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_stereo_aac_he2.m4a  $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav "-ar 16000"
+fate-audiomatch-afconvert-44100-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_lc.adts  $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav
+fate-audiomatch-afconvert-44100-mono-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav
+fate-audiomatch-afconvert-44100-mono-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_he.adts  $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav "-ac 1"
+fate-audiomatch-afconvert-44100-mono-he-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_mono_aac_he.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav "-ac 1"
+fate-audiomatch-afconvert-44100-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_lc.adts  $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-afconvert-44100-stereo-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-afconvert-44100-stereo-he-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he.adts  $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-afconvert-44100-stereo-he-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-afconvert-44100-stereo-he2-adts:CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he2.adts $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-afconvert-44100-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he2.m4a  $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+
+fate-audiomatch-dolby-44100-mono-lc-mp4:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_mono_aac_lc.mp4   $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav
+fate-audiomatch-dolby-44100-mono-he-mp4:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_mono_aac_he.mp4   $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav "-ac 1"
+fate-audiomatch-dolby-44100-stereo-lc-mp4:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_stereo_aac_lc.mp4   $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-dolby-44100-stereo-he-mp4:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_stereo_aac_he.mp4   $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-dolby-44100-stereo-he2-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_dolby_44100_stereo_aac_he2.mp4  $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+
+fate-audiomatch-faac-16000-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_mono_aac_lc.adts  $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav
+fate-audiomatch-faac-16000-mono-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_mono_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav
+fate-audiomatch-faac-16000-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_stereo_aac_lc.adts  $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav
+fate-audiomatch-faac-16000-stereo-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_16000_stereo_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav
+fate-audiomatch-faac-44100-mono-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_mono_aac_lc.adts  $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav
+fate-audiomatch-faac-44100-mono-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_mono_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav
+fate-audiomatch-faac-44100-stereo-lc-adts: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_stereo_aac_lc.adts  $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-faac-44100-stereo-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_faac_44100_stereo_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+
+fate-audiomatch-nero-16000-mono-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_mono_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav
+fate-audiomatch-nero-16000-mono-he-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_mono_aac_he.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_mono.wav
+fate-audiomatch-nero-16000-stereo-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_stereo_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav
+fate-audiomatch-nero-16000-stereo-he-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_stereo_aac_he.m4a   $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav
+fate-audiomatch-nero-16000-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_16000_stereo_aac_he2.m4a  $(TARGET_SAMPLES)/audiomatch/tones_16000_stereo.wav
+fate-audiomatch-nero-44100-mono-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_mono_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav
+fate-audiomatch-nero-44100-mono-he-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_mono_aac_he.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_mono.wav
+fate-audiomatch-nero-44100-stereo-lc-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_stereo_aac_lc.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-nero-44100-stereo-he-m4a:  CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_stereo_aac_he.m4a   $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-nero-44100-stereo-he2-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_nero_44100_stereo_aac_he2.m4a  $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+
+fate-audiomatch-quicktime7-44100-stereo-lc-mp4: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_quicktime7_44100_stereo_aac_lc.mp4  $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+fate-audiomatch-quicktimeX-44100-stereo-lc-m4a: CMD = audio_match $(TARGET_SAMPLES)/audiomatch/tones_quicktimeX_44100_stereo_aac_lc.m4a  $(TARGET_SAMPLES)/audiomatch/tones_44100_stereo.wav
+
+
 FATE_GAPLESS = $(FATE_GAPLESS-yes)
 
+FATE_GAPLESSINFO_PROBE-$(call DEMDEC, MOV, AAC) += fate-gaplessinfo-itunes1
+fate-gaplessinfo-itunes1: ffprobe$(PROGSSUF)$(EXESUF)
+fate-gaplessinfo-itunes1: CMD = probegaplessinfo $(TARGET_SAMPLES)/cover_art/Owner-iTunes_9.0.3.15.m4a
+
+FATE_GAPLESSINFO_PROBE-$(call DEMDEC, MOV, AAC) += fate-gaplessinfo-itunes2
+fate-gaplessinfo-itunes2: ffprobe$(PROGSSUF)$(EXESUF)
+fate-gaplessinfo-itunes2: CMD = probegaplessinfo $(TARGET_SAMPLES)/gapless/102400samples_qt-lc-aac.m4a
+
+FATE_GAPLESSENC_PROBE-$(call ENCDEC, AAC, MOV) += fate-gaplessenc-itunes-to-ipod-aac
+fate-gaplessenc-itunes-to-ipod-aac: ffprobe$(PROGSSUF)$(EXESUF)
+fate-gaplessenc-itunes-to-ipod-aac: CMD = gaplessenc $(TARGET_SAMPLES)/gapless/102400samples_qt-lc-aac.m4a ipod aac
+
+FATE_GAPLESSENC_PROBE-$(call ENCDEC, AAC, MOV) += fate-gaplessenc-pcm-to-mov-aac
+fate-gaplessenc-pcm-to-mov-aac: $(AREF)
+fate-gaplessenc-pcm-to-mov-aac: ffprobe$(PROGSSUF)$(EXESUF)
+fate-gaplessenc-pcm-to-mov-aac: CMD = gaplessenc $(AREF) mov aac
+
+FATE_GAPLESSINFO-$(CONFIG_FFPROBE) = $(FATE_GAPLESSINFO_PROBE-yes)
+FATE_GAPLESSINFO = $(FATE_GAPLESSINFO-yes)
+
+FATE_GAPLESSENC-$(CONFIG_FFPROBE) = $(FATE_GAPLESSENC_PROBE-yes)
+FATE_GAPLESSENC = $(FATE_GAPLESSENC-yes)
+
 FATE_SAMPLES_AVCONV += $(FATE_GAPLESS)
-fate-gapless: $(FATE_GAPLESS)
+FATE_SAMPLES_AVCONV += $(FATE_GAPLESSINFO)
+FATE_SAMPLES_AVCONV += $(FATE_GAPLESSENC)
+
+fate-gapless: $(FATE_GAPLESS) $(FATE_GAPLESSINFO) $(FATE_GAPLESSENC)
diff --git a/tests/fate/gif.mak b/tests/fate/gif.mak
index 3dc50b3..9bd9631 100644
--- a/tests/fate/gif.mak
+++ b/tests/fate/gif.mak
@@ -10,6 +10,9 @@ fate-gif-disposal-restore: CMD = framecrc -i $(TARGET_SAMPLES)/gif/banner2.gif -
 FATE_GIF += fate-gif-gray
 fate-gif-gray: CMD = framecrc -i $(TARGET_SAMPLES)/gif/Newtons_cradle_animation_book_2.gif -pix_fmt bgra
 
+FATE_GIF += fate-gif-deal
+fate-gif-deal: CMD = framecrc -i $(TARGET_SAMPLES)/gif/deal.gif -vsync cfr -pix_fmt bgra
+
 fate-gifenc%: fate-gif-color
 fate-gifenc%: PIXFMT = $(word 3, $(subst -, ,$(@)))
 fate-gifenc%: SRC = $(TARGET_SAMPLES)/gif/tc217.gif
diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak
index 46178cd..4ae1305 100644
--- a/tests/fate/h264.mak
+++ b/tests/fate/h264.mak
@@ -196,29 +196,45 @@ FATE_H264  := $(FATE_H264:%=fate-h264-conformance-%)                    \
 FATE_H264-$(call DEMDEC, H264, H264) += $(FATE_H264)
 FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-crop-to-container
 FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-interlace-crop
+
+# this sample has invalid reference list modification, but decodes fine
+# by using a previous ref frame instead of a missing one
+FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-invalid-ref-mod
+
+# this sample has invalid extradata that is not escaped
+FATE_H264-$(call DEMDEC,  MOV, H264) += fate-h264-unescaped-extradata
+
 FATE_H264-$(call ALLYES, MOV_DEMUXER H264_MP4TOANNEXB_BSF) += fate-h264-bsf-mp4toannexb
 FATE_H264-$(call DEMDEC, MATROSKA, H264) += fate-h264-direct-bff
+FATE_H264-$(call DEMDEC, FLV, H264) += fate-h264-brokensps-2580
+FATE_H264-$(call DEMDEC, MXF, H264) += fate-h264-xavc-4389
+FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-attachment-631
+FATE_H264_FFPROBE-$(call DEMDEC, MATROSKA, H264) += fate-h264-dts_5frames
 
 FATE_SAMPLES_AVCONV += $(FATE_H264-yes)
-fate-h264: $(FATE_H264-yes)
+FATE_SAMPLES_FFPROBE += $(FATE_H264_FFPROBE-yes)
+fate-h264: $(FATE_H264-yes) $(FATE_H264_FFPROBE-yes)
 
 fate-h264-conformance-aud_mw_e:                   CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/AUD_MW_E.264
-fate-h264-conformance-ba1_ft_c:                   CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/BA1_FT_C.264
-fate-h264-conformance-ba1_sony_d:                 CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/BA1_Sony_D.jsv
-fate-h264-conformance-ba2_sony_f:                 CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/BA2_Sony_F.jsv
-fate-h264-conformance-ba3_sva_c:                  CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/BA3_SVA_C.264
-fate-h264-conformance-ba_mw_d:                    CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/BA_MW_D.264
-fate-h264-conformance-bamq1_jvc_c:                CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/BAMQ1_JVC_C.264
-fate-h264-conformance-bamq2_jvc_c:                CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/BAMQ2_JVC_C.264
-fate-h264-conformance-banm_mw_d:                  CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/BANM_MW_D.264
-fate-h264-conformance-basqp1_sony_c:              CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/BASQP1_Sony_C.jsv
-fate-h264-conformance-caba1_sony_d:               CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABA1_Sony_D.jsv
-fate-h264-conformance-caba1_sva_b:                CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABA1_SVA_B.264
-fate-h264-conformance-caba2_sony_e:               CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABA2_Sony_E.jsv
-fate-h264-conformance-caba2_sva_b:                CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABA2_SVA_B.264
-fate-h264-conformance-caba3_sony_c:               CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABA3_Sony_C.jsv
-fate-h264-conformance-caba3_sva_b:                CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABA3_SVA_B.264
-fate-h264-conformance-caba3_toshiba_e:            CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/CABA3_TOSHIBA_E.264
+
+#force framerate so that the option is tested, theres no other case that tests it, its not needed at all otherwise here
+fate-h264-conformance-ba1_ft_c:                   CMD = framecrc -framerate 19 -i $(TARGET_SAMPLES)/h264-conformance/BA1_FT_C.264
+
+fate-h264-conformance-ba1_sony_d:                 CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BA1_Sony_D.jsv
+fate-h264-conformance-ba2_sony_f:                 CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BA2_Sony_F.jsv
+fate-h264-conformance-ba3_sva_c:                  CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BA3_SVA_C.264
+fate-h264-conformance-ba_mw_d:                    CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BA_MW_D.264
+fate-h264-conformance-bamq1_jvc_c:                CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BAMQ1_JVC_C.264
+fate-h264-conformance-bamq2_jvc_c:                CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BAMQ2_JVC_C.264
+fate-h264-conformance-banm_mw_d:                  CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BANM_MW_D.264
+fate-h264-conformance-basqp1_sony_c:              CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/BASQP1_Sony_C.jsv
+fate-h264-conformance-caba1_sony_d:               CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA1_Sony_D.jsv
+fate-h264-conformance-caba1_sva_b:                CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA1_SVA_B.264
+fate-h264-conformance-caba2_sony_e:               CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA2_Sony_E.jsv
+fate-h264-conformance-caba2_sva_b:                CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA2_SVA_B.264
+fate-h264-conformance-caba3_sony_c:               CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA3_Sony_C.jsv
+fate-h264-conformance-caba3_sva_b:                CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA3_SVA_B.264
+fate-h264-conformance-caba3_toshiba_e:            CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/CABA3_TOSHIBA_E.264
 fate-h264-conformance-cabac_mot_fld0_full:        CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_fld0_full.26l
 fate-h264-conformance-cabac_mot_frm0_full:        CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_frm0_full.26l
 fate-h264-conformance-cabac_mot_mbaff0_full:      CMD = framecrc -vsync drop -i $(TARGET_SAMPLES)/h264-conformance/camp_mot_mbaff0_full.26l
@@ -393,5 +409,12 @@ fate-h264-extreme-plane-pred:                     CMD = framemd5 -i $(TARGET_SAM
 fate-h264-interlace-crop:                         CMD = framecrc -i $(TARGET_SAMPLES)/h264/interlaced_crop.mp4 -vframes 3
 fate-h264-lossless:                               CMD = framecrc -i $(TARGET_SAMPLES)/h264/lossless.h264
 fate-h264-direct-bff:                             CMD = framecrc -i $(TARGET_SAMPLES)/h264/direct-bff.mkv
+fate-h264-brokensps-2580:                         CMD = framecrc -i $(TARGET_SAMPLES)/h264/brokensps.flv -vf format=yuv420p,scale=w=192:h=144 -sws_flags bitexact+bilinear
+fate-h264-xavc-4389:                              CMD = framecrc -i $(TARGET_SAMPLES)/h264/SonyXAVC_LongGOP_green_pixelation_early_Frames.MXF -pix_fmt yuv422p10le
+fate-h264-attachment-631:                         CMD = framecrc -i $(TARGET_SAMPLES)/h264/attachment631-small.mp4 -an -max_error_rate 0.95
+fate-h264-invalid-ref-mod:                        CMD = framecrc -i $(TARGET_SAMPLES)/h264/h264refframeregression.mp4 -an -frames 10 -pix_fmt yuv420p10le
+fate-h264-unescaped-extradata:                    CMD = framecrc -i $(TARGET_SAMPLES)/h264/unescaped_extradata.mp4 -an -frames 10
 
 fate-h264-reinit-%:                               CMD = framecrc -i $(TARGET_SAMPLES)/h264/$(@:fate-h264-%=%).h264 -vf format=yuv444p10le,scale=w=352:h=288
+
+fate-h264-dts_5frames:                            CMD = probeframes $(TARGET_SAMPLES)/h264/dts_5frames.mkv
diff --git a/tests/fate/image.mak b/tests/fate/image.mak
index 2224e3e..a67c07f 100644
--- a/tests/fate/image.mak
+++ b/tests/fate/image.mak
@@ -37,7 +37,54 @@ endef
 
 DDS_OPTS_pal     = -sws_flags +accurate_rnd+bitexact -pix_fmt rgba
 DDS_OPTS_pal-ati = -sws_flags +accurate_rnd+bitexact -pix_fmt rgba
-DDS_FMT = argb argb-aexp dx10-bc1 dx10-bc1a dx10-bc2 dx10-bc3 dx10-bc4 dx10-bc5 dxt1 dxt1a dxt1-normalmap dxt2 dxt3 dxt4 dxt5 dxt5-aexp dxt5-normalmap dxt5-normalmap-ati dxt5-rbxg dxt5-rgxb dxt5-rxbg dxt5-rxgb dxt5-xgbr dxt5-xgxr dxt5-xrbg dxt5-ycocg dxt5-ycocg-scaled pal pal-ati rgb16 rgb24 rgba rgtc1s rgtc1u rgtc2s rgtc2u rgtc2u-xy uyvy xbgr xrgb y ya ycocg yuyv
+DDS_FMT          = alpha8                                               \
+                   argb                                                 \
+                   argb-aexp                                            \
+                   dx10-bc1                                             \
+                   dx10-bc1a                                            \
+                   dx10-bc2                                             \
+                   dx10-bc3                                             \
+                   dx10-bc4                                             \
+                   dx10-bc5                                             \
+                   dxt1                                                 \
+                   dxt1a                                                \
+                   dxt1-normalmap                                       \
+                   dxt2                                                 \
+                   dxt3                                                 \
+                   dxt4                                                 \
+                   dxt5                                                 \
+                   dxt5-aexp                                            \
+                   dxt5-normalmap                                       \
+                   dxt5-normalmap-ati                                   \
+                   dxt5-rbxg                                            \
+                   dxt5-rgxb                                            \
+                   dxt5-rxbg                                            \
+                   dxt5-rxgb                                            \
+                   dxt5-xgbr                                            \
+                   dxt5-xgxr                                            \
+                   dxt5-xrbg                                            \
+                   dxt5-ycocg                                           \
+                   dxt5-ycocg-scaled                                    \
+                   monob                                                \
+                   pal                                                  \
+                   pal-ati                                              \
+                   rgb1555                                              \
+                   rgb16                                                \
+                   rgb24                                                \
+                   rgb555                                               \
+                   rgba                                                 \
+                   rgtc1s                                               \
+                   rgtc1u                                               \
+                   rgtc2s                                               \
+                   rgtc2u                                               \
+                   rgtc2u-xy                                            \
+                   uyvy                                                 \
+                   xbgr                                                 \
+                   xrgb                                                 \
+                   y                                                    \
+                   ya                                                   \
+                   ycocg                                                \
+                   yuyv
 $(foreach FMT,$(DDS_FMT),$(eval $(call FATE_IMGSUITE_DDS,$(FMT))))
 
 FATE_DDS-$(call DEMDEC, IMAGE2, DDS) += $(FATE_DDS)
@@ -65,6 +112,30 @@ fate-exr-slice-zip16: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_slice_zip16.e
 FATE_EXR += fate-exr-slice-pxr24
 fate-exr-slice-pxr24: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_slice_pxr24.exr -pix_fmt rgb48le
 
+FATE_EXR += fate-exr-rgb-scanline-pxr24-float-12x8
+fate-exr-rgb-scanline-pxr24-float-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_float_12x8.exr -pix_fmt rgb48le
+
+FATE_EXR += fate-exr-rgba-multiscanline-half-b44
+fate-exr-rgba-multiscanline-half-b44: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgba_multiscanline_half_b44.exr -pix_fmt rgba64le
+
+FATE_EXR += fate-exr-rgb-scanline-float-b44
+fate-exr-rgb-scanline-float-b44: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_float_b44.exr -pix_fmt rgb48le
+
+FATE_EXR += fate-exr-rgb-scanline-half-b44-12x8
+fate-exr-rgb-scanline-half-b44-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_b44_12x8.exr -pix_fmt rgb48le
+
+FATE_EXR += fate-exr-rgb-scanline-half-b44-13x9
+fate-exr-rgb-scanline-half-b44-13x9: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_scanline_half_b44_13x9.exr -pix_fmt rgb48le
+
+FATE_EXR += fate-exr-rgb-tile-float-raw-12x8
+fate-exr-rgb-tile-float-raw-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_float_raw_12x8.exr -pix_fmt rgb48le
+
+FATE_EXR += fate-exr-rgb-tile-float-raw-150x130
+fate-exr-rgb-tile-float-raw-150x130: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_float_raw_150x130.exr -pix_fmt rgb48le
+
+FATE_EXR += fate-exr-rgb-tile-half-raw-12x8
+fate-exr-rgb-tile-half-raw-12x8: CMD = framecrc -i $(TARGET_SAMPLES)/exr/rgb_tile_half_raw_12x8.exr -pix_fmt rgb48le
+
 FATE_EXR-$(call DEMDEC, IMAGE2, EXR) += $(FATE_EXR)
 
 FATE_IMAGE += $(FATE_EXR-yes)
diff --git a/tests/fate/indeo.mak b/tests/fate/indeo.mak
index e725a6b..bb3c154 100644
--- a/tests/fate/indeo.mak
+++ b/tests/fate/indeo.mak
@@ -1,12 +1,21 @@
-FATE_INDEO-$(call DEMDEC, AVI, INDEO2) += fate-indeo2
-fate-indeo2: CMD = framecrc -i $(TARGET_SAMPLES)/rt21/VPAR0026.AVI
+FATE_INDEO2 += fate-indeo2-delta
+fate-indeo2-delta: CMD = framecrc -i $(TARGET_SAMPLES)/rt21/ISKATE.AVI -an
 
-FATE_INDEO-$(call DEMDEC, MOV, INDEO3) += fate-indeo3
-fate-indeo3: CMD = framecrc -i $(TARGET_SAMPLES)/iv32/cubes.mov
+FATE_INDEO2 += fate-indeo2-intra
+fate-indeo2-intra: CMD = framecrc -i $(TARGET_SAMPLES)/rt21/VPAR0026.AVI
 
-FATE_INDEO-$(call DEMDEC, AVI, INDEO3) += fate-indeo3-2
+FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, INDEO2) += $(FATE_INDEO2)
+fate-indeo2: $(FATE_INDEO2)
+
+FATE_INDEO3-$(CONFIG_MOV_DEMUXER) += fate-indeo3-1
+fate-indeo3-1: CMD = framecrc -i $(TARGET_SAMPLES)/iv32/cubes.mov
+
+FATE_INDEO3-$(CONFIG_AVI_DEMUXER) += fate-indeo3-2
 fate-indeo3-2: CMD = framecrc -i $(TARGET_SAMPLES)/iv32/OPENINGH.avi
 
+FATE_SAMPLES_AVCONV-$(CONFIG_INDEO3_DECODER) += $(FATE_INDEO3-yes)
+fate-indeo3: $(FATE_INDEO3-yes)
+
 FATE_INDEO-$(call DEMDEC, AVI, INDEO4) += fate-indeo4
 fate-indeo4: CMD = framecrc -i $(TARGET_SAMPLES)/iv41/indeo41-partial.avi -an
 
@@ -14,4 +23,4 @@ FATE_INDEO-$(call DEMDEC, AVI, INDEO5) += fate-indeo5
 fate-indeo5: CMD = framecrc -i $(TARGET_SAMPLES)/iv50/Educ_Movie_DeadlyForce.avi -an
 
 FATE_SAMPLES_AVCONV += $(FATE_INDEO-yes)
-fate-indeo: $(FATE_INDEO-yes)
+fate-indeo: $(FATE_INDEO2) $(FATE_INDEO3-yes) $(FATE_INDEO-yes)
diff --git a/tests/fate/libavcodec.mak b/tests/fate/libavcodec.mak
index 22c0839..cf25285 100644
--- a/tests/fate/libavcodec.mak
+++ b/tests/fate/libavcodec.mak
@@ -1,43 +1,48 @@
 FATE_LIBAVCODEC-$(CONFIG_CABAC) += fate-cabac
-fate-cabac: libavcodec/cabac-test$(EXESUF)
-fate-cabac: CMD = run libavcodec/cabac-test
+fate-cabac: libavcodec/tests/cabac$(EXESUF)
+fate-cabac: CMD = run libavcodec/tests/cabac
 fate-cabac: REF = /dev/null
 
 FATE_LIBAVCODEC-$(CONFIG_GOLOMB) += fate-golomb
-fate-golomb: libavcodec/golomb-test$(EXESUF)
-fate-golomb: CMD = run libavcodec/golomb-test
+fate-golomb: libavcodec/tests/golomb$(EXESUF)
+fate-golomb: CMD = run libavcodec/tests/golomb
 fate-golomb: REF = /dev/null
 
 FATE_LIBAVCODEC-$(CONFIG_IDCTDSP) += fate-idct8x8
-fate-idct8x8: libavcodec/dct-test$(EXESUF)
-fate-idct8x8: CMD = run libavcodec/dct-test -i
+fate-idct8x8: libavcodec/tests/dct$(EXESUF)
+fate-idct8x8: CMD = run libavcodec/tests/dct -i
 fate-idct8x8: CMP = null
 fate-idct8x8: REF = /dev/null
 
 FATE_LIBAVCODEC-$(CONFIG_IIRFILTER) += fate-iirfilter
-fate-iirfilter: libavcodec/iirfilter-test$(EXESUF)
-fate-iirfilter: CMD = run libavcodec/iirfilter-test
+fate-iirfilter: libavcodec/tests/iirfilter$(EXESUF)
+fate-iirfilter: CMD = run libavcodec/tests/iirfilter
 
 FATE_LIBAVCODEC-yes += fate-libavcodec-options
-fate-libavcodec-options: libavcodec/options-test$(EXESUF)
-fate-libavcodec-options: CMD = run libavcodec/options-test
+fate-libavcodec-options: libavcodec/tests/options$(EXESUF)
+fate-libavcodec-options: CMD = run libavcodec/tests/options
 
 FATE_LIBAVCODEC-$(CONFIG_RANGECODER) += fate-rangecoder
-fate-rangecoder: libavcodec/rangecoder-test$(EXESUF)
-fate-rangecoder: CMD = run libavcodec/rangecoder-test
+fate-rangecoder: libavcodec/tests/rangecoder$(EXESUF)
+fate-rangecoder: CMD = run libavcodec/tests/rangecoder
 fate-rangecoder: CMP = null
 fate-rangecoder: REF = /dev/null
 
 FATE_LIBAVCODEC-yes += fate-mathops
-fate-mathops: libavcodec/mathops-test$(EXESUF)
-fate-mathops: CMD = run libavcodec/mathops-test
+fate-mathops: libavcodec/tests/mathops$(EXESUF)
+fate-mathops: CMD = run libavcodec/tests/mathops
 fate-mathops: CMP = null
 fate-mathops: REF = /dev/null
 
 FATE_LIBAVCODEC-$(CONFIG_JPEG2000_ENCODER) += fate-j2k-dwt
-fate-j2k-dwt: libavcodec/jpeg2000dwt-test$(EXESUF)
-fate-j2k-dwt: CMD = run libavcodec/jpeg2000dwt-test
-
+fate-j2k-dwt: libavcodec/tests/jpeg2000dwt$(EXESUF)
+fate-j2k-dwt: CMD = run libavcodec/tests/jpeg2000dwt
+
+FATE_LIBAVCODEC-yes += fate-libavcodec-utils
+fate-libavcodec-utils: libavcodec/tests/utils$(EXESUF)
+fate-libavcodec-utils: CMD = run libavcodec/tests/utils
+fate-libavcodec-utils: CMP = null
+fate-libavcodec-utils: REF = /dev/null
 
 FATE-$(CONFIG_AVCODEC) += $(FATE_LIBAVCODEC-yes)
 fate-libavcodec: $(FATE_LIBAVCODEC-yes)
diff --git a/tests/fate/libavdevice.mak b/tests/fate/libavdevice.mak
index cb6af51..e983327 100644
--- a/tests/fate/libavdevice.mak
+++ b/tests/fate/libavdevice.mak
@@ -1,6 +1,6 @@
-FATE_LIBAVDEVICE-yes += fate-timefilter
-fate-timefilter: libavdevice/timefilter-test$(EXESUF)
-fate-timefilter: CMD = run libavdevice/timefilter-test
+FATE_LIBAVDEVICE-$(CONFIG_JACK_INDEV) += fate-timefilter
+fate-timefilter: libavdevice/tests/timefilter$(EXESUF)
+fate-timefilter: CMD = run libavdevice/tests/timefilter
 
 FATE-$(CONFIG_AVDEVICE) += $(FATE_LIBAVDEVICE-yes)
 fate-libavdevice: $(FATE_LIBAVDEVICE-yes)
diff --git a/tests/fate/libavformat.mak b/tests/fate/libavformat.mak
index 1d6aa86..cf1ba18 100644
--- a/tests/fate/libavformat.mak
+++ b/tests/fate/libavformat.mak
@@ -1,26 +1,27 @@
-FATE_LIBAVFORMAT-$(HAVE_PTHREADS) += fate-async
-fate-async: libavformat/async-test$(EXESUF)
-fate-async: CMD = run libavformat/async-test
+#FATE_LIBAVFORMAT-$(HAVE_PTHREADS) += fate-async
+#fate-async: libavformat/tests/async$(EXESUF)
+#fate-async: CMD = run libavformat/tests/async
 
 FATE_LIBAVFORMAT-$(CONFIG_NETWORK) += fate-noproxy
-fate-noproxy: libavformat/noproxy-test$(EXESUF)
-fate-noproxy: CMD = run libavformat/noproxy-test
+fate-noproxy: libavformat/tests/noproxy$(EXESUF)
+fate-noproxy: CMD = run libavformat/tests/noproxy
 
 FATE_LIBAVFORMAT-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += fate-rtmpdh
-fate-rtmpdh: libavformat/rtmpdh-test$(EXESUF)
-fate-rtmpdh: CMD = run libavformat/rtmpdh-test
+fate-rtmpdh: libavformat/tests/rtmpdh$(EXESUF)
+fate-rtmpdh: CMD = run libavformat/tests/rtmpdh
 
-FATE_LIBAVFORMAT-yes += fate-srtp
-fate-srtp: libavformat/srtp-test$(EXESUF)
-fate-srtp: CMD = run libavformat/srtp-test
+FATE_LIBAVFORMAT-$(CONFIG_SRTP) += fate-srtp
+fate-srtp: libavformat/tests/srtp$(EXESUF)
+fate-srtp: CMD = run libavformat/tests/srtp
 
 FATE_LIBAVFORMAT-yes += fate-url
-fate-url: libavformat/url-test$(EXESUF)
-fate-url: CMD = run libavformat/url-test
+fate-url: libavformat/tests/url$(EXESUF)
+fate-url: CMD = run libavformat/tests/url
 
 FATE_LIBAVFORMAT-$(CONFIG_MOV_MUXER) += fate-movenc
-fate-movenc: libavformat/movenc-test$(EXESUF)
-fate-movenc: CMD = run libavformat/movenc-test
+fate-movenc: libavformat/tests/movenc$(EXESUF)
+fate-movenc: CMD = run libavformat/tests/movenc
 
-FATE-$(CONFIG_AVFORMAT) += $(FATE_LIBAVFORMAT-yes)
+FATE_LIBAVFORMAT += $(FATE_LIBAVFORMAT-yes)
+FATE-$(CONFIG_AVFORMAT) += $(FATE_LIBAVFORMAT)
 fate-libavformat: $(FATE_LIBAVFORMAT)
diff --git a/tests/fate/libavresample.mak b/tests/fate/libavresample.mak
index 65c0898..da5cbb3 100644
--- a/tests/fate/libavresample.mak
+++ b/tests/fate/libavresample.mak
@@ -1,7 +1,7 @@
-CROSS_TEST = $(foreach I,$(1),                                        \
-                 $(foreach J,$(1),                                    \
-                     $(if $(filter-out $(I),$(J)),                    \
-                         $(eval $(call $(2),$(I),$(J),$(3),$(4),$(5))),    \
+CROSS_TEST = $(foreach I,$(1),                                          \
+                 $(foreach J,$(1),                                      \
+                     $(if $(filter-out $(I),$(J)),                      \
+                         $(eval $(call $(2),$(I),$(J),$(3),$(4),$(5))), \
                      )))
 
 MIX_CHANNELS = 1 2 3 4 5 6 7 8
diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak
index 022ae6a..6fbad64 100644
--- a/tests/fate/libavutil.mak
+++ b/tests/fate/libavutil.mak
@@ -1,133 +1,145 @@
 FATE_LIBAVUTIL += fate-adler32
-fate-adler32: libavutil/adler32-test$(EXESUF)
-fate-adler32: CMD = run libavutil/adler32-test
+fate-adler32: libavutil/tests/adler32$(EXESUF)
+fate-adler32: CMD = run libavutil/tests/adler32
 fate-adler32: REF = /dev/null
 
 FATE_LIBAVUTIL += fate-aes
-fate-aes: libavutil/aes-test$(EXESUF)
-fate-aes: CMD = run libavutil/aes-test
+fate-aes: libavutil/tests/aes$(EXESUF)
+fate-aes: CMD = run libavutil/tests/aes
 fate-aes: REF = /dev/null
 
 FATE_LIBAVUTIL += fate-camellia
-fate-camellia: libavutil/camellia-test$(EXESUF)
-fate-camellia: CMD = run libavutil/camellia-test
+fate-camellia: libavutil/tests/camellia$(EXESUF)
+fate-camellia: CMD = run libavutil/tests/camellia
 fate-camellia: REF = /dev/null
 
 FATE_LIBAVUTIL += fate-cast5
-fate-cast5: libavutil/cast5-test$(EXESUF)
-fate-cast5: CMD = run libavutil/cast5-test
+fate-cast5: libavutil/tests/cast5$(EXESUF)
+fate-cast5: CMD = run libavutil/tests/cast5
 fate-cast5: REF = /dev/null
 
 FATE_LIBAVUTIL += fate-atomic
-fate-atomic: libavutil/atomic-test$(EXESUF)
-fate-atomic: CMD = run libavutil/atomic-test
+fate-atomic: libavutil/tests/atomic$(EXESUF)
+fate-atomic: CMD = run libavutil/tests/atomic
 fate-atomic: REF = /dev/null
 
 FATE_LIBAVUTIL += fate-avstring
-fate-avstring: libavutil/avstring-test$(EXESUF)
-fate-avstring: CMD = run libavutil/avstring-test
+fate-avstring: libavutil/tests/avstring$(EXESUF)
+fate-avstring: CMD = run libavutil/tests/avstring
 
 FATE_LIBAVUTIL += fate-base64
-fate-base64: libavutil/base64-test$(EXESUF)
-fate-base64: CMD = run libavutil/base64-test
+fate-base64: libavutil/tests/base64$(EXESUF)
+fate-base64: CMD = run libavutil/tests/base64
 
 FATE_LIBAVUTIL += fate-blowfish
-fate-blowfish: libavutil/blowfish-test$(EXESUF)
-fate-blowfish: CMD = run libavutil/blowfish-test
+fate-blowfish: libavutil/tests/blowfish$(EXESUF)
+fate-blowfish: CMD = run libavutil/tests/blowfish
 
 FATE_LIBAVUTIL += fate-bprint
-fate-bprint: libavutil/bprint-test$(EXESUF)
-fate-bprint: CMD = run libavutil/bprint-test
+fate-bprint: libavutil/tests/bprint$(EXESUF)
+fate-bprint: CMD = run libavutil/tests/bprint
 
 FATE_LIBAVUTIL += fate-cpu
-fate-cpu: libavutil/cpu-test$(EXESUF)
-fate-cpu: CMD = runecho libavutil/cpu-test $(CPUFLAGS:%=-c%) $(THREADS:%=-t%)
+fate-cpu: libavutil/tests/cpu$(EXESUF)
+fate-cpu: CMD = runecho libavutil/tests/cpu $(CPUFLAGS:%=-c%) $(THREADS:%=-t%)
 fate-cpu: REF = /dev/null
 
 FATE_LIBAVUTIL += fate-crc
-fate-crc: libavutil/crc-test$(EXESUF)
-fate-crc: CMD = run libavutil/crc-test
+fate-crc: libavutil/tests/crc$(EXESUF)
+fate-crc: CMD = run libavutil/tests/crc
+
+FATE_LIBAVUTIL += fate-color_utils
+fate-color_utils: libavutil/tests/color_utils$(EXESUF)
+fate-color_utils: CMD = run libavutil/tests/color_utils
 
 FATE_LIBAVUTIL += fate-des
-fate-des: libavutil/des-test$(EXESUF)
-fate-des: CMD = run libavutil/des-test
+fate-des: libavutil/tests/des$(EXESUF)
+fate-des: CMD = run libavutil/tests/des
 fate-des: REF = /dev/null
 
 FATE_LIBAVUTIL += fate-dict
-fate-dict: libavutil/dict-test$(EXESUF)
-fate-dict: CMD = run libavutil/dict-test
+fate-dict: libavutil/tests/dict$(EXESUF)
+fate-dict: CMD = run libavutil/tests/dict
 
 FATE_LIBAVUTIL += fate-eval
-fate-eval: libavutil/eval-test$(EXESUF)
-fate-eval: CMD = run libavutil/eval-test
+fate-eval: libavutil/tests/eval$(EXESUF)
+fate-eval: CMD = run libavutil/tests/eval
 
 FATE_LIBAVUTIL += fate-fifo
-fate-fifo: libavutil/fifo-test$(EXESUF)
-fate-fifo: CMD = run libavutil/fifo-test
+fate-fifo: libavutil/tests/fifo$(EXESUF)
+fate-fifo: CMD = run libavutil/tests/fifo
 
 FATE_LIBAVUTIL += fate-float-dsp
-fate-float-dsp: libavutil/float_dsp-test$(EXESUF)
-fate-float-dsp: CMD = run libavutil/float_dsp-test $(CPUFLAGS:%=-c%)
+fate-float-dsp: libavutil/tests/float_dsp$(EXESUF)
+fate-float-dsp: CMD = run libavutil/tests/float_dsp $(CPUFLAGS:%=-c%)
 fate-float-dsp: CMP = null
 fate-float-dsp: REF = /dev/null
 
+FATE_LIBAVUTIL += fate-hash
+fate-hash: libavutil/tests/hash$(EXESUF)
+fate-hash: CMD = run libavutil/tests/hash
+
 FATE_LIBAVUTIL += fate-hmac
-fate-hmac: libavutil/hmac-test$(EXESUF)
-fate-hmac: CMD = run libavutil/hmac-test
+fate-hmac: libavutil/tests/hmac$(EXESUF)
+fate-hmac: CMD = run libavutil/tests/hmac
 
 FATE_LIBAVUTIL += fate-md5
-fate-md5: libavutil/md5-test$(EXESUF)
-fate-md5: CMD = run libavutil/md5-test
+fate-md5: libavutil/tests/md5$(EXESUF)
+fate-md5: CMD = run libavutil/tests/md5
 
 FATE_LIBAVUTIL += fate-murmur3
-fate-murmur3: libavutil/murmur3-test$(EXESUF)
-fate-murmur3: CMD = run libavutil/murmur3-test
+fate-murmur3: libavutil/tests/murmur3$(EXESUF)
+fate-murmur3: CMD = run libavutil/tests/murmur3
 
 FATE_LIBAVUTIL += fate-parseutils
-fate-parseutils: libavutil/parseutils-test$(EXESUF)
-fate-parseutils: CMD = run libavutil/parseutils-test
+fate-parseutils: libavutil/tests/parseutils$(EXESUF)
+fate-parseutils: CMD = run libavutil/tests/parseutils
 
 FATE_LIBAVUTIL-$(CONFIG_PIXELUTILS) += fate-pixelutils
-fate-pixelutils: libavutil/pixelutils-test$(EXESUF)
-fate-pixelutils: CMD = run libavutil/pixelutils-test
+fate-pixelutils: libavutil/tests/pixelutils$(EXESUF)
+fate-pixelutils: CMD = run libavutil/tests/pixelutils
+
+FATE_LIBAVUTIL += fate-display
+fate-display: libavutil/tests/display$(EXESUF)
+fate-display: CMD = run libavutil/tests/display
 
 FATE_LIBAVUTIL += fate-random_seed
-fate-random_seed: libavutil/random_seed-test$(EXESUF)
-fate-random_seed: CMD = run libavutil/random_seed-test
+fate-random_seed: libavutil/tests/random_seed$(EXESUF)
+fate-random_seed: CMD = run libavutil/tests/random_seed
 
 FATE_LIBAVUTIL += fate-ripemd
-fate-ripemd: libavutil/ripemd-test$(EXESUF)
-fate-ripemd: CMD = run libavutil/ripemd-test
+fate-ripemd: libavutil/tests/ripemd$(EXESUF)
+fate-ripemd: CMD = run libavutil/tests/ripemd
 
 FATE_LIBAVUTIL += fate-sha
-fate-sha: libavutil/sha-test$(EXESUF)
-fate-sha: CMD = run libavutil/sha-test
+fate-sha: libavutil/tests/sha$(EXESUF)
+fate-sha: CMD = run libavutil/tests/sha
 
 FATE_LIBAVUTIL += fate-sha512
-fate-sha512: libavutil/sha512-test$(EXESUF)
-fate-sha512: CMD = run libavutil/sha512-test
+fate-sha512: libavutil/tests/sha512$(EXESUF)
+fate-sha512: CMD = run libavutil/tests/sha512
 
 FATE_LIBAVUTIL += fate-tree
-fate-tree: libavutil/tree-test$(EXESUF)
-fate-tree: CMD = run libavutil/tree-test
+fate-tree: libavutil/tests/tree$(EXESUF)
+fate-tree: CMD = run libavutil/tests/tree
 fate-tree: REF = /dev/null
 
 FATE_LIBAVUTIL += fate-twofish
-fate-twofish: libavutil/twofish-test$(EXESUF)
-fate-twofish: CMD = run libavutil/twofish-test
+fate-twofish: libavutil/tests/twofish$(EXESUF)
+fate-twofish: CMD = run libavutil/tests/twofish
 fate-twofish: REF = /dev/null
 
 FATE_LIBAVUTIL += fate-xtea
-fate-xtea: libavutil/xtea-test$(EXESUF)
-fate-xtea: CMD = run libavutil/xtea-test
+fate-xtea: libavutil/tests/xtea$(EXESUF)
+fate-xtea: CMD = run libavutil/tests/xtea
 
 FATE_LIBAVUTIL += fate-tea
-fate-tea: libavutil/tea-test$(EXESUF)
-fate-tea: CMD = run libavutil/tea-test
+fate-tea: libavutil/tests/tea$(EXESUF)
+fate-tea: CMD = run libavutil/tests/tea
 
 FATE_LIBAVUTIL += fate-opt
-fate-opt: libavutil/opt-test$(EXESUF)
-fate-opt: CMD = run libavutil/opt-test
+fate-opt: libavutil/tests/opt$(EXESUF)
+fate-opt: CMD = run libavutil/tests/opt
 
 FATE_LIBAVUTIL += $(FATE_LIBAVUTIL-yes)
 FATE-$(CONFIG_AVUTIL) += $(FATE_LIBAVUTIL)
diff --git a/tests/fate/libswresample.mak b/tests/fate/libswresample.mak
index 064c0f6..93b8d6e 100644
--- a/tests/fate/libswresample.mak
+++ b/tests/fate/libswresample.mak
@@ -378,6 +378,340 @@ fate-swr-resample_async-s16p-44100-8000: SIZE_TOLERANCE = 529200 - 20310
 fate-swr-resample_async-s16p-8000-44100: CMP_TARGET = 11187.01
 fate-swr-resample_async-s16p-8000-44100: SIZE_TOLERANCE = 96000 - 20344
 
+define ARESAMPLE_EXACT
+FATE_SWR_RESAMPLE += fate-swr-resample_exact-$(3)-$(1)-$(2)
+fate-swr-resample_exact-$(3)-$(1)-$(2): tests/data/asynth-$(1)-1.wav
+fate-swr-resample_exact-$(3)-$(1)-$(2): CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-$(1)-1.wav -af atrim=end_sample=10240,aresample=$(2):internal_sample_fmt=$(3):exact_rational=on,aformat=$(3),aresample=$(1):internal_sample_fmt=$(3):exact_rational=on -f wav -acodec pcm_s16le -
+
+fate-swr-resample_exact-$(3)-$(1)-$(2): CMP = stddev
+fate-swr-resample_exact-$(3)-$(1)-$(2): CMP_UNIT = $(5)
+fate-swr-resample_exact-$(3)-$(1)-$(2): FUZZ = 0.1
+fate-swr-resample_exact-$(3)-$(1)-$(2): REF = tests/data/asynth-$(1)-1.wav
+endef
+
+fate-swr-resample_exact-dblp-2626-44100: CMP_TARGET = 1352.68
+fate-swr-resample_exact-dblp-2626-44100: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-dblp-2626-48000: CMP_TARGET = 1352.65
+fate-swr-resample_exact-dblp-2626-48000: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-dblp-2626-8000: CMP_TARGET = 1353.08
+fate-swr-resample_exact-dblp-2626-8000: SIZE_TOLERANCE = 31512 - 20482
+
+fate-swr-resample_exact-dblp-2626-96000: CMP_TARGET = 1352.67
+fate-swr-resample_exact-dblp-2626-96000: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-dblp-44100-2626: CMP_TARGET = 185.82
+fate-swr-resample_exact-dblp-44100-2626: SIZE_TOLERANCE = 529200 - 20490
+
+fate-swr-resample_exact-dblp-44100-48000: CMP_TARGET = 9.65
+fate-swr-resample_exact-dblp-44100-48000: SIZE_TOLERANCE = 529200 - 20482
+
+fate-swr-resample_exact-dblp-44100-8000: CMP_TARGET = 75.38
+fate-swr-resample_exact-dblp-44100-8000: SIZE_TOLERANCE = 529200 - 20486
+
+fate-swr-resample_exact-dblp-44100-96000: CMP_TARGET = 11.45
+fate-swr-resample_exact-dblp-44100-96000: SIZE_TOLERANCE = 529200 - 20482
+
+fate-swr-resample_exact-dblp-48000-2626: CMP_TARGET = 456.51
+fate-swr-resample_exact-dblp-48000-2626: SIZE_TOLERANCE = 576000 - 20510
+
+fate-swr-resample_exact-dblp-48000-44100: CMP_TARGET = 0.26
+fate-swr-resample_exact-dblp-48000-44100: SIZE_TOLERANCE = 576000 - 20480
+
+fate-swr-resample_exact-dblp-48000-8000: CMP_TARGET = 62.36
+fate-swr-resample_exact-dblp-48000-8000: SIZE_TOLERANCE = 576000 - 20484
+
+fate-swr-resample_exact-dblp-48000-96000: CMP_TARGET = 0.47
+fate-swr-resample_exact-dblp-48000-96000: SIZE_TOLERANCE = 576000 - 20480
+
+fate-swr-resample_exact-dblp-8000-2626: CMP_TARGET = 2506.02
+fate-swr-resample_exact-dblp-8000-2626: SIZE_TOLERANCE = 96000 - 20486
+
+fate-swr-resample_exact-dblp-8000-44100: CMP_TARGET = 14.59
+fate-swr-resample_exact-dblp-8000-44100: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-dblp-8000-48000: CMP_TARGET = 14.50
+fate-swr-resample_exact-dblp-8000-48000: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-dblp-8000-96000: CMP_TARGET = 13.62
+fate-swr-resample_exact-dblp-8000-96000: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-dblp-96000-2626: CMP_TARGET = 675.08
+fate-swr-resample_exact-dblp-96000-2626: SIZE_TOLERANCE = 1152000 - 20474
+
+fate-swr-resample_exact-dblp-96000-44100: CMP_TARGET = 1.26
+fate-swr-resample_exact-dblp-96000-44100: SIZE_TOLERANCE = 1152000 - 20480
+
+fate-swr-resample_exact-dblp-96000-48000: CMP_TARGET = 1.00
+fate-swr-resample_exact-dblp-96000-48000: SIZE_TOLERANCE = 1152000 - 20480
+
+fate-swr-resample_exact-dblp-96000-8000: CMP_TARGET = 58.52
+fate-swr-resample_exact-dblp-96000-8000: SIZE_TOLERANCE = 1152000 - 20496
+
+fate-swr-resample_exact-fltp-2626-44100: CMP_TARGET = 1352.68
+fate-swr-resample_exact-fltp-2626-44100: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-fltp-2626-48000: CMP_TARGET = 1352.65
+fate-swr-resample_exact-fltp-2626-48000: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-fltp-2626-8000: CMP_TARGET = 1353.08
+fate-swr-resample_exact-fltp-2626-8000: SIZE_TOLERANCE = 31512 - 20482
+
+fate-swr-resample_exact-fltp-2626-96000: CMP_TARGET = 1352.67
+fate-swr-resample_exact-fltp-2626-96000: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-fltp-44100-2626: CMP_TARGET = 185.82
+fate-swr-resample_exact-fltp-44100-2626: SIZE_TOLERANCE = 529200 - 20490
+
+fate-swr-resample_exact-fltp-44100-48000: CMP_TARGET = 9.65
+fate-swr-resample_exact-fltp-44100-48000: SIZE_TOLERANCE = 529200 - 20482
+
+fate-swr-resample_exact-fltp-44100-8000: CMP_TARGET = 75.38
+fate-swr-resample_exact-fltp-44100-8000: SIZE_TOLERANCE = 529200 - 20486
+
+fate-swr-resample_exact-fltp-44100-96000: CMP_TARGET = 11.45
+fate-swr-resample_exact-fltp-44100-96000: SIZE_TOLERANCE = 529200 - 20482
+
+fate-swr-resample_exact-fltp-48000-2626: CMP_TARGET = 456.51
+fate-swr-resample_exact-fltp-48000-2626: SIZE_TOLERANCE = 576000 - 20510
+
+fate-swr-resample_exact-fltp-48000-44100: CMP_TARGET = 0.26
+fate-swr-resample_exact-fltp-48000-44100: SIZE_TOLERANCE = 576000 - 20480
+
+fate-swr-resample_exact-fltp-48000-8000: CMP_TARGET = 62.36
+fate-swr-resample_exact-fltp-48000-8000: SIZE_TOLERANCE = 576000 - 20484
+
+fate-swr-resample_exact-fltp-48000-96000: CMP_TARGET = 0.47
+fate-swr-resample_exact-fltp-48000-96000: SIZE_TOLERANCE = 576000 - 20480
+
+fate-swr-resample_exact-fltp-8000-2626: CMP_TARGET = 2506.02
+fate-swr-resample_exact-fltp-8000-2626: SIZE_TOLERANCE = 96000 - 20486
+
+fate-swr-resample_exact-fltp-8000-44100: CMP_TARGET = 14.59
+fate-swr-resample_exact-fltp-8000-44100: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-fltp-8000-48000: CMP_TARGET = 14.50
+fate-swr-resample_exact-fltp-8000-48000: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-fltp-8000-96000: CMP_TARGET = 13.62
+fate-swr-resample_exact-fltp-8000-96000: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-fltp-96000-2626: CMP_TARGET = 675.08
+fate-swr-resample_exact-fltp-96000-2626: SIZE_TOLERANCE = 1152000 - 20474
+
+fate-swr-resample_exact-fltp-96000-44100: CMP_TARGET = 1.26
+fate-swr-resample_exact-fltp-96000-44100: SIZE_TOLERANCE = 1152000 - 20480
+
+fate-swr-resample_exact-fltp-96000-48000: CMP_TARGET = 1.00
+fate-swr-resample_exact-fltp-96000-48000: SIZE_TOLERANCE = 1152000 - 20480
+
+fate-swr-resample_exact-fltp-96000-8000: CMP_TARGET = 58.52
+fate-swr-resample_exact-fltp-96000-8000: SIZE_TOLERANCE = 1152000 - 20496
+
+fate-swr-resample_exact-s16p-2626-44100: CMP_TARGET = 1393.01
+fate-swr-resample_exact-s16p-2626-44100: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-s16p-2626-48000: CMP_TARGET = 1392.99
+fate-swr-resample_exact-s16p-2626-48000: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-s16p-2626-8000: CMP_TARGET = 1393.90
+fate-swr-resample_exact-s16p-2626-8000: SIZE_TOLERANCE = 31512 - 20482
+
+fate-swr-resample_exact-s16p-2626-96000: CMP_TARGET = 1393.08
+fate-swr-resample_exact-s16p-2626-96000: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-s16p-44100-2626: CMP_TARGET = 185.84
+fate-swr-resample_exact-s16p-44100-2626: SIZE_TOLERANCE = 529200 - 20490
+
+fate-swr-resample_exact-s16p-44100-48000: CMP_TARGET = 9.67
+fate-swr-resample_exact-s16p-44100-48000: SIZE_TOLERANCE = 529200 - 20482
+
+fate-swr-resample_exact-s16p-44100-8000: CMP_TARGET = 75.43
+fate-swr-resample_exact-s16p-44100-8000: SIZE_TOLERANCE = 529200 - 20486
+
+fate-swr-resample_exact-s16p-44100-96000: CMP_TARGET = 11.46
+fate-swr-resample_exact-s16p-44100-96000: SIZE_TOLERANCE = 529200 - 20482
+
+fate-swr-resample_exact-s16p-48000-2626: CMP_TARGET = 456.55
+fate-swr-resample_exact-s16p-48000-2626: SIZE_TOLERANCE = 576000 - 20510
+
+fate-swr-resample_exact-s16p-48000-44100: CMP_TARGET = 0.72
+fate-swr-resample_exact-s16p-48000-44100: SIZE_TOLERANCE = 576000 - 20480
+
+fate-swr-resample_exact-s16p-48000-8000: CMP_TARGET = 62.39
+fate-swr-resample_exact-s16p-48000-8000: SIZE_TOLERANCE = 576000 - 20484
+
+fate-swr-resample_exact-s16p-48000-96000: CMP_TARGET = 0.50
+fate-swr-resample_exact-s16p-48000-96000: SIZE_TOLERANCE = 576000 - 20480
+
+fate-swr-resample_exact-s16p-8000-2626: CMP_TARGET = 2506.02
+fate-swr-resample_exact-s16p-8000-2626: SIZE_TOLERANCE = 96000 - 20486
+
+fate-swr-resample_exact-s16p-8000-44100: CMP_TARGET = 14.63
+fate-swr-resample_exact-s16p-8000-44100: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-s16p-8000-48000: CMP_TARGET = 14.54
+fate-swr-resample_exact-s16p-8000-48000: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-s16p-8000-96000: CMP_TARGET = 13.65
+fate-swr-resample_exact-s16p-8000-96000: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-s16p-96000-2626: CMP_TARGET = 675.14
+fate-swr-resample_exact-s16p-96000-2626: SIZE_TOLERANCE = 1152000 - 20474
+
+fate-swr-resample_exact-s16p-96000-44100: CMP_TARGET = 1.45
+fate-swr-resample_exact-s16p-96000-44100: SIZE_TOLERANCE = 1152000 - 20480
+
+fate-swr-resample_exact-s16p-96000-48000: CMP_TARGET = 1.03
+fate-swr-resample_exact-s16p-96000-48000: SIZE_TOLERANCE = 1152000 - 20480
+
+fate-swr-resample_exact-s16p-96000-8000: CMP_TARGET = 58.56
+fate-swr-resample_exact-s16p-96000-8000: SIZE_TOLERANCE = 1152000 - 20496
+
+fate-swr-resample_exact-s32p-2626-44100: CMP_TARGET = 1393.01
+fate-swr-resample_exact-s32p-2626-44100: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-s32p-2626-48000: CMP_TARGET = 1392.99
+fate-swr-resample_exact-s32p-2626-48000: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-s32p-2626-8000: CMP_TARGET = 1393.89
+fate-swr-resample_exact-s32p-2626-8000: SIZE_TOLERANCE = 31512 - 20482
+
+fate-swr-resample_exact-s32p-2626-96000: CMP_TARGET = 1393.00
+fate-swr-resample_exact-s32p-2626-96000: SIZE_TOLERANCE = 31512 - 20480
+
+fate-swr-resample_exact-s32p-44100-2626: CMP_TARGET = 185.82
+fate-swr-resample_exact-s32p-44100-2626: SIZE_TOLERANCE = 529200 - 20490
+
+fate-swr-resample_exact-s32p-44100-48000: CMP_TARGET = 9.65
+fate-swr-resample_exact-s32p-44100-48000: SIZE_TOLERANCE = 529200 - 20482
+
+fate-swr-resample_exact-s32p-44100-8000: CMP_TARGET = 75.38
+fate-swr-resample_exact-s32p-44100-8000: SIZE_TOLERANCE = 529200 - 20486
+
+fate-swr-resample_exact-s32p-44100-96000: CMP_TARGET = 11.45
+fate-swr-resample_exact-s32p-44100-96000: SIZE_TOLERANCE = 529200 - 20482
+
+fate-swr-resample_exact-s32p-48000-2626: CMP_TARGET = 456.51
+fate-swr-resample_exact-s32p-48000-2626: SIZE_TOLERANCE = 576000 - 20510
+
+fate-swr-resample_exact-s32p-48000-44100: CMP_TARGET = 0.26
+fate-swr-resample_exact-s32p-48000-44100: SIZE_TOLERANCE = 576000 - 20480
+
+fate-swr-resample_exact-s32p-48000-8000: CMP_TARGET = 62.36
+fate-swr-resample_exact-s32p-48000-8000: SIZE_TOLERANCE = 576000 - 20484
+
+fate-swr-resample_exact-s32p-48000-96000: CMP_TARGET = 0.47
+fate-swr-resample_exact-s32p-48000-96000: SIZE_TOLERANCE = 576000 - 20480
+
+fate-swr-resample_exact-s32p-8000-2626: CMP_TARGET = 2506.02
+fate-swr-resample_exact-s32p-8000-2626: SIZE_TOLERANCE = 96000 - 20486
+
+fate-swr-resample_exact-s32p-8000-44100: CMP_TARGET = 14.59
+fate-swr-resample_exact-s32p-8000-44100: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-s32p-8000-48000: CMP_TARGET = 14.50
+fate-swr-resample_exact-s32p-8000-48000: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-s32p-8000-96000: CMP_TARGET = 13.62
+fate-swr-resample_exact-s32p-8000-96000: SIZE_TOLERANCE = 96000 - 20480
+
+fate-swr-resample_exact-s32p-96000-2626: CMP_TARGET = 675.08
+fate-swr-resample_exact-s32p-96000-2626: SIZE_TOLERANCE = 1152000 - 20474
+
+fate-swr-resample_exact-s32p-96000-44100: CMP_TARGET = 1.26
+fate-swr-resample_exact-s32p-96000-44100: SIZE_TOLERANCE = 1152000 - 20480
+
+fate-swr-resample_exact-s32p-96000-48000: CMP_TARGET = 1.00
+fate-swr-resample_exact-s32p-96000-48000: SIZE_TOLERANCE = 1152000 - 20480
+
+fate-swr-resample_exact-s32p-96000-8000: CMP_TARGET = 58.52
+fate-swr-resample_exact-s32p-96000-8000: SIZE_TOLERANCE = 1152000 - 20496
+
+define ARESAMPLE_EXACT_ASYNC
+FATE_SWR_RESAMPLE += fate-swr-resample_exact_async-$(3)-$(1)-$(2)
+fate-swr-resample_exact_async-$(3)-$(1)-$(2): tests/data/asynth-$(1)-1.wav
+fate-swr-resample_exact_async-$(3)-$(1)-$(2): CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-$(1)-1.wav -af atrim=end_sample=10240,asetpts=PTS+random\(0\)*200-100,aresample=$(2):async=50:min_hard_comp=0.100000:first_pts=0:internal_sample_fmt=$(3):exact_rational=on,aformat=$(3),aresample=$(1):internal_sample_fmt=$(3):exact_rational=on -f wav -acodec pcm_s16le -
+
+fate-swr-resample_exact_async-$(3)-$(1)-$(2): CMP = stddev
+fate-swr-resample_exact_async-$(3)-$(1)-$(2): CMP_UNIT = $(5)
+fate-swr-resample_exact_async-$(3)-$(1)-$(2): FUZZ = 0.1
+fate-swr-resample_exact_async-$(3)-$(1)-$(2): REF = tests/data/asynth-$(1)-1.wav
+endef
+
+fate-swr-resample_exact_async-dblp-44100-48000: CMP_TARGET = 7791.55
+fate-swr-resample_exact_async-dblp-44100-48000: SIZE_TOLERANCE = 529200 - 20300
+
+fate-swr-resample_exact_async-dblp-44100-8000: CMP_TARGET = 4022.89
+fate-swr-resample_exact_async-dblp-44100-8000: SIZE_TOLERANCE = 529200 - 20310
+
+fate-swr-resample_exact_async-dblp-48000-44100: CMP_TARGET = 1923.99
+fate-swr-resample_exact_async-dblp-48000-44100: SIZE_TOLERANCE = 576000 - 20298
+
+fate-swr-resample_exact_async-dblp-48000-8000: CMP_TARGET = 2592.02
+fate-swr-resample_exact_async-dblp-48000-8000: SIZE_TOLERANCE = 576000 - 20304
+
+fate-swr-resample_exact_async-dblp-8000-44100: CMP_TARGET = 11187.37
+fate-swr-resample_exact_async-dblp-8000-44100: SIZE_TOLERANCE = 96000 - 20344
+
+fate-swr-resample_exact_async-dblp-8000-48000: CMP_TARGET = 11326.82
+fate-swr-resample_exact_async-dblp-8000-48000: SIZE_TOLERANCE = 96000 - 20344
+
+fate-swr-resample_exact_async-fltp-44100-48000: CMP_TARGET = 7791.55
+fate-swr-resample_exact_async-fltp-44100-48000: SIZE_TOLERANCE = 529200 - 20300
+
+fate-swr-resample_exact_async-fltp-44100-8000: CMP_TARGET = 4022.89
+fate-swr-resample_exact_async-fltp-44100-8000: SIZE_TOLERANCE = 529200 - 20310
+
+fate-swr-resample_exact_async-fltp-48000-44100: CMP_TARGET = 1923.98
+fate-swr-resample_exact_async-fltp-48000-44100: SIZE_TOLERANCE = 576000 - 20298
+
+fate-swr-resample_exact_async-fltp-48000-8000: CMP_TARGET = 2592.02
+fate-swr-resample_exact_async-fltp-48000-8000: SIZE_TOLERANCE = 576000 - 20304
+
+fate-swr-resample_exact_async-fltp-8000-44100: CMP_TARGET = 11187.37
+fate-swr-resample_exact_async-fltp-8000-44100: SIZE_TOLERANCE = 96000 - 20344
+
+fate-swr-resample_exact_async-fltp-8000-48000: CMP_TARGET = 11326.82
+fate-swr-resample_exact_async-fltp-8000-48000: SIZE_TOLERANCE = 96000 - 20344
+
+fate-swr-resample_exact_async-s16p-44100-48000: CMP_TARGET = 7791.56
+fate-swr-resample_exact_async-s16p-44100-48000: SIZE_TOLERANCE = 529200 - 20300
+
+fate-swr-resample_exact_async-s16p-44100-8000: CMP_TARGET = 4023.06
+fate-swr-resample_exact_async-s16p-44100-8000: SIZE_TOLERANCE = 529200 - 20310
+
+fate-swr-resample_exact_async-s16p-48000-44100: CMP_TARGET = 1923.98
+fate-swr-resample_exact_async-s16p-48000-44100: SIZE_TOLERANCE = 576000 - 20298
+
+fate-swr-resample_exact_async-s16p-48000-8000: CMP_TARGET = 2592.15
+fate-swr-resample_exact_async-s16p-48000-8000: SIZE_TOLERANCE = 576000 - 20304
+
+fate-swr-resample_exact_async-s16p-8000-44100: CMP_TARGET = 11187.62
+fate-swr-resample_exact_async-s16p-8000-44100: SIZE_TOLERANCE = 96000 - 20344
+
+fate-swr-resample_exact_async-s16p-8000-48000: CMP_TARGET = 11327.50
+fate-swr-resample_exact_async-s16p-8000-48000: SIZE_TOLERANCE = 96000 - 20344
+
+fate-swr-resample_exact_async-s32p-44100-48000: CMP_TARGET = 7791.55
+fate-swr-resample_exact_async-s32p-44100-48000: SIZE_TOLERANCE = 529200 - 20300
+
+fate-swr-resample_exact_async-s32p-44100-8000: CMP_TARGET = 4022.89
+fate-swr-resample_exact_async-s32p-44100-8000: SIZE_TOLERANCE = 529200 - 20310
+
+fate-swr-resample_exact_async-s32p-48000-44100: CMP_TARGET = 1923.98
+fate-swr-resample_exact_async-s32p-48000-44100: SIZE_TOLERANCE = 576000 - 20298
+
+fate-swr-resample_exact_async-s32p-48000-8000: CMP_TARGET = 2592.02
+fate-swr-resample_exact_async-s32p-48000-8000: SIZE_TOLERANCE = 576000 - 20304
+
+fate-swr-resample_exact_async-s32p-8000-44100: CMP_TARGET = 11187.37
+fate-swr-resample_exact_async-s32p-8000-44100: SIZE_TOLERANCE = 96000 - 20344
+
+fate-swr-resample_exact_async-s32p-8000-48000: CMP_TARGET = 11326.82
+fate-swr-resample_exact_async-s32p-8000-48000: SIZE_TOLERANCE = 96000 - 20344
+
 $(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE,s16p,s16le,s16)
 $(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE,s32p,s32le,s16)
 $(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE,fltp,f32le,s16)
@@ -393,6 +727,15 @@ $(call CROSS_TEST,$(SAMPLERATES_NN),ARESAMPLE_NN,fltp,f32le,s16)
 $(call CROSS_TEST,$(SAMPLERATES_NN),ARESAMPLE_ASYNC,s16p,s16le,s16)
 $(call CROSS_TEST,$(SAMPLERATES_NN),ARESAMPLE_ASYNC,fltp,f32le,s16)
 
+$(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE_EXACT,s16p,s16le,s16)
+$(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE_EXACT,s32p,s32le,s16)
+$(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE_EXACT,fltp,f32le,s16)
+$(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE_EXACT,dblp,f64le,s16)
+
+$(call CROSS_TEST,$(SAMPLERATES_LITE),ARESAMPLE_EXACT_ASYNC,s16p,s16le,s16)
+$(call CROSS_TEST,$(SAMPLERATES_LITE),ARESAMPLE_EXACT_ASYNC,s32p,s32le,s16)
+$(call CROSS_TEST,$(SAMPLERATES_LITE),ARESAMPLE_EXACT_ASYNC,fltp,f32le,s16)
+$(call CROSS_TEST,$(SAMPLERATES_LITE),ARESAMPLE_EXACT_ASYNC,dblp,f64le,s16)
 
 FATE_SWR_RESAMPLE-$(call FILTERDEMDECENCMUX, ARESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += $(FATE_SWR_RESAMPLE)
 fate-swr-resample: $(FATE_SWR_RESAMPLE-yes)
diff --git a/tests/fate/lossless-audio.mak b/tests/fate/lossless-audio.mak
index 58641ab..d292853 100644
--- a/tests/fate/lossless-audio.mak
+++ b/tests/fate/lossless-audio.mak
@@ -25,8 +25,12 @@ fate-lossless-tta: CMD = crc -i $(TARGET_SAMPLES)/lossless-audio/inside.tta
 FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, TTA, TTA) += fate-lossless-tta-encrypted
 fate-lossless-tta-encrypted: CMD = crc -password ffmpeg -i $(TARGET_SAMPLES)/lossless-audio/encrypted.tta
 
-FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, ASF, WMALOSSLESS) += fate-lossless-wma
+FATE_SAMPLES_LOSSLESS_AUDIO-$(call DEMDEC, ASF, WMALOSSLESS) += fate-lossless-wma fate-lossless-wma24-1 fate-lossless-wma24-2 fate-lossless-wma24-rawtile
 fate-lossless-wma: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.wma -f s16le -frames 209
+fate-lossless-wma24-1: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/master_audio_2.0_24bit.wma -f s24le
+fate-lossless-wma24-2: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/Mega_Weird_Audio_Test_24bit.wma -f s24le
+fate-lossless-wma24-rawtile: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/g2_24bit.wma -f s24le
+fate-lossless-wmall: fate-lossless-wma fate-lossless-wma24-1 fate-lossless-wma24-2 fate-lossless-wma24-rawtile
 
 FATE_SAMPLES_LOSSLESS_AUDIO += $(FATE_SAMPLES_LOSSLESS_AUDIO-yes)
 
diff --git a/tests/fate/lossless-video.mak b/tests/fate/lossless-video.mak
index 514d6fd..bfbed83 100644
--- a/tests/fate/lossless-video.mak
+++ b/tests/fate/lossless-video.mak
@@ -25,6 +25,13 @@ fate-lagarith-yv12: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lag-yv12.avi
 FATE_LAGARITH += fate-lagarith-red
 fate-lagarith-red: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-red.avi
 
+FATE_LAGARITH += fate-lagarith-ticket4119 fate-lagarith-ticket4119-cfr fate-lagarith-ticket4119-vfr fate-lagarith-ticket4119-pass fate-lagarith-ticket4119-drop
+fate-lagarith-ticket4119: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi
+fate-lagarith-ticket4119-cfr : CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync cfr
+fate-lagarith-ticket4119-vfr : CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync vfr
+fate-lagarith-ticket4119-pass: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync passthrough
+fate-lagarith-ticket4119-drop: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync drop
+
 FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, LAGARITH) += $(FATE_LAGARITH)
 fate-lagarith: $(FATE_LAGARITH)
 
diff --git a/tests/fate/matroska.mak b/tests/fate/matroska.mak
new file mode 100644
index 0000000..8cf1734
--- /dev/null
+++ b/tests/fate/matroska.mak
@@ -0,0 +1,9 @@
+# This tests that the matroska demuxer supports modifying the colorspace
+# properties in remuxing (-c:v copy)
+# It also tests automatic insertion of the vp9_superframe bitstream filter
+FATE_MATROSKA-$(call DEMMUX, MATROSKA, MATROSKA) += fate-matroska-remux
+fate-matroska-remux: CMD = md5 -i $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-2pass-akiyo.webm -color_trc 4 -c:v copy -fflags +bitexact -strict -2 -f matroska
+fate-matroska-remux: CMP = oneline
+fate-matroska-remux: REF = 5ebcfaa8e3d534f8a800a58fd2b0aca6
+
+FATE_SAMPLES_AVCONV += $(FATE_MATROSKA-yes)
diff --git a/tests/fate/microsoft.mak b/tests/fate/microsoft.mak
index 3da25a7..2354f4d 100644
--- a/tests/fate/microsoft.mak
+++ b/tests/fate/microsoft.mak
@@ -1,6 +1,9 @@
 FATE_MICROSOFT-$(call DEMDEC, AVI, MSMPEG4V1) += fate-msmpeg4v1
 fate-msmpeg4v1: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/msmpeg4v1/mpg4.avi -an
 
+FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MSS1) += fate-mss1-pal
+fate-mss1-pal: CMD = framecrc -i $(TARGET_SAMPLES)/mss1/screen_codec.wmv -an
+
 FATE_MSS2 += fate-mss2-pal
 fate-mss2-pal: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rlepal.wmv
 
@@ -19,6 +22,12 @@ fate-mss2-wmv: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/msscreencodec.wmv -an -f
 FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MSS2) += $(FATE_MSS2)
 fate-mss2: $(FATE_MSS2)
 
+FATE_MTS2 += fate-mts2-xesc
+fate-mts2-xesc: CMD = framecrc -i $(TARGET_SAMPLES)/mts2/sample.xesc -pix_fmt yuv444p
+
+FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MTS2) += $(FATE_MTS2)
+fate-mts2: $(FATE_MTS2)
+
 FATE_MSVIDEO1 += fate-msvideo1-8bit
 fate-msvideo1-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/skating.avi -t 1 -pix_fmt rgb24
 
@@ -28,6 +37,9 @@ fate-msvideo1-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/clock-cram16.avi -
 FATE_MICROSOFT-$(call DEMDEC, AVI, MSVIDEO1) += $(FATE_MSVIDEO1)
 fate-msvideo1: $(FATE_MSVIDEO1)
 
+FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MTS2) += fate-mts2
+fate-mts2: CMD = framecrc -i $(TARGET_SAMPLES)/mts2/ScreenCapture.xesc
+
 FATE_WMV8_DRM += fate-wmv8-drm
 # discard last packet to avoid fails due to overread of VC-1 decoder
 fate-wmv8-drm: CMD = framecrc -cryptokey 137381538c84c068111902a59c5cf6c340247c39 -i $(TARGET_SAMPLES)/wmv8/wmv_drm.wmv -an -frames:v 129
@@ -35,13 +47,12 @@ fate-wmv8-drm: CMD = framecrc -cryptokey 137381538c84c068111902a59c5cf6c340247c3
 FATE_WMV8_DRM += fate-wmv8-drm-nodec
 fate-wmv8-drm-nodec: CMD = framecrc -cryptokey 137381538c84c068111902a59c5cf6c340247c39 -i $(TARGET_SAMPLES)/wmv8/wmv_drm.wmv -acodec copy -vcodec copy
 
-#FATE_MICROSOFT += fate-wmv8-x8intra
-FATE_TESTS-no += fate-wmv8-x8intra
-fate-wmv8-x8intra: CMD = framecrc -flags +bitexact -idct 19 -i $(TARGET_SAMPLES)/wmv8/wmv8_x8intra.wmv -an
-
 FATE_MICROSOFT-$(call DEMDEC, ASF, WMV3) += $(FATE_WMV8_DRM)
 fate-wmv8_drm: $(FATE_WMV8_DRM)
 
+FATE_MICROSOFT-$(call DEMDEC, ASF, WMV2) += fate-wmv8-x8intra
+fate-wmv8-x8intra: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/wmv8/wmv8_x8intra.wmv -an
+
 FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_sa00040
 fate-vc1_sa00040: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SA00040.vc1
 
diff --git a/tests/fate/mpeg4.mak b/tests/fate/mpeg4.mak
index 47dfb7f..ed6a2fa 100644
--- a/tests/fate/mpeg4.mak
+++ b/tests/fate/mpeg4.mak
@@ -8,5 +8,12 @@ FATE_MPEG4-$(call DEMDEC, H263, H263) := $(addprefix fate-mpeg4-resolution-chang
 fate-mpeg4-bsf-unpack-bframes: CMD = md5 -i $(TARGET_SAMPLES)/mpeg4/packed_bframes.avi -flags +bitexact -fflags +bitexact -c:v copy -bsf mpeg4_unpack_bframes -f avi
 FATE_MPEG4-$(call ALLYES, AVI_DEMUXER MPEG4_UNPACK_BFRAMES_BSF AVI_MUXER) += fate-mpeg4-bsf-unpack-bframes
 
+fate-mpeg4-packed: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/packed_bframes.avi -flags +bitexact -fflags +bitexact -vsync 1
+FATE_MPEG4-$(call ALLYES, AVI_DEMUXER MPEG4_DECODER) += fate-mpeg4-packed
+
+FATE_MPEG4-$(call DEMDEC, M4V, MPEG4) += fate-m4v  fate-m4v-cfr
+fate-m4v:     CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/demo.m4v
+fate-m4v-cfr: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/demo.m4v -vf fps=5
+
 FATE_SAMPLES_AVCONV += $(FATE_MPEG4-yes)
 fate-mpeg4: $(FATE_MPEG4-yes)
diff --git a/tests/fate/prores.mak b/tests/fate/prores.mak
index e88df5f..fe1e772 100644
--- a/tests/fate/prores.mak
+++ b/tests/fate/prores.mak
@@ -6,6 +6,7 @@ FATE_PRORES = fate-prores-422                                           \
               fate-prores-alpha_skip                                    \
               fate-prores-transparency                                  \
               fate-prores-transparency_skip                             \
+              fate-prores-gray                                          \
 
 FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, PRORES) += $(FATE_PRORES)
 fate-prores: $(FATE_PRORES)
@@ -18,3 +19,4 @@ fate-prores-alpha:     CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/pror
 fate-prores-alpha_skip: CMD = framecrc -flags +bitexact -skip_alpha 1 -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_with_Alpha.mov -pix_fmt yuv444p10le
 fate-prores-transparency: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/prores4444_with_transparency.mov -pix_fmt yuva444p10le
 fate-prores-transparency_skip: CMD = framecrc -flags +bitexact -skip_alpha 1 -i $(TARGET_SAMPLES)/prores/prores4444_with_transparency.mov -pix_fmt yuv444p10le
+fate-prores-gray:      CMD = framecrc -flags +bitexact -acodec aac_fixed -i $(TARGET_SAMPLES)/prores/gray.mov -pix_fmt yuv422p10le
diff --git a/tests/fate/real.mak b/tests/fate/real.mak
index c123e44..f9073dd 100644
--- a/tests/fate/real.mak
+++ b/tests/fate/real.mak
@@ -20,6 +20,9 @@ fate-ra-cook: CMD = pcm -i $(TARGET_SAMPLES)/real/ra_cook.rm
 fate-ra-cook: CMP = oneoff
 fate-ra-cook: REF = $(SAMPLES)/real/ra_cook.pcm
 
+FATE_REALMEDIA_VIDEO-$(call DEMDEC, RM, RV20) += fate-rv20-1239
+fate-rv20-1239: CMD = framecrc -flags +bitexact -idct simple -lowres 1 -i $(TARGET_SAMPLES)/real/G2_with_SVT_320_240.rm
+
 FATE_REALMEDIA_VIDEO-$(call DEMDEC, RM, RV30) += fate-rv30
 fate-rv30: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/real/rv30.rm -an
 
diff --git a/tests/fate/screen.mak b/tests/fate/screen.mak
index 635e5c4..eb70ea2 100644
--- a/tests/fate/screen.mak
+++ b/tests/fate/screen.mak
@@ -3,7 +3,7 @@ FATE_SCREEN-$(call DEMDEC, AVI, CSCD) += fate-cscd
 fate-cscd: CMD = framecrc -i $(TARGET_SAMPLES)/CSCD/sample_video.avi -an -pix_fmt rgb24
 
 FATE_SCREEN-$(call DEMDEC, AVI, DXTORY) += fate-dxtory
-fate-dxtory: CMD = framecrc -i $(TARGET_SAMPLES)/dxtory/dxtory_mic.avi
+fate-dxtory: CMD = framecrc -i $(TARGET_SAMPLES)/dxtory/dxtory_mic.avi -an
 
 FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, FIC) += fate-fic-avi
 fate-fic-avi: CMD = framecrc -i $(TARGET_SAMPLES)/fic/fic-partial-2MB.avi -an
@@ -41,11 +41,32 @@ fate-g2m4: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/g2m/g2m4.asf
 FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, G2M) += $(FATE_G2M)
 fate-g2m: $(FATE_G2M)
 
-FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, RSCC) += fate-rscc
-fate-rscc: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/pip.avi -an
+FATE_RSCC += fate-iscc
+fate-iscc: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/pip.avi -an
 
-FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, SCREENPRESSO) += fate-screenpresso
-fate-screenpresso: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/bunny.avi
+FATE_RSCC += fate-rscc-16bit
+fate-rscc-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/16bpp_555.avi -an
+
+FATE_RSCC += fate-rscc-24bit
+fate-rscc-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/24bpp.avi -an
+
+FATE_RSCC += fate-rscc-32bit
+fate-rscc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/32bpp.avi -an
+
+FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, RSCC) += $(FATE_RSCC)
+fate-rscc: $(FATE_RSCC)
+
+FATE_SCREENPRESSO += fate-screenpresso-16bit
+fate-screenpresso-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/16bpp_555.avi -an
+
+FATE_SCREENPRESSO += fate-screenpresso-24bit
+fate-screenpresso-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/bunny.avi -an
+
+FATE_SCREENPRESSO += fate-screenpresso-32bit
+fate-screenpresso-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/32bpp.avi -an
+
+FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, SCREENPRESSO) += $(FATE_SCREENPRESSO)
+fate-screenpresso: $(FATE_SCREENPRESSO)
 
 FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, TDSC) += fate-tdsc
 fate-tdsc: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/tdsc/tdsc.asf -an -pix_fmt bgr24
diff --git a/tests/fate/seek.mak b/tests/fate/seek.mak
index a229e72..f120f56 100644
--- a/tests/fate/seek.mak
+++ b/tests/fate/seek.mak
@@ -79,16 +79,16 @@ FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, JPEGLS,        AVI)     += jpegls
 FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, LJPEG MJPEG,   AVI)     += ljpeg
 FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MJPEG,         AVI)     += mjpeg
 
-FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG1VIDEO, MPEG1VIDEO MPEGVIDEO) +=          \
-                                                    mpeg1                      \
+FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG1VIDEO, MPEG1VIDEO MPEGVIDEO) +=    \
+                                                    mpeg1                    \
                                                     mpeg1b
 
-FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG2VIDEO, MPEG2VIDEO MPEGVIDEO) +=          \
-                                                    mpeg2-422                  \
-                                                    mpeg2-idct-int             \
-                                                    mpeg2-ilace                \
-                                                    mpeg2-ivlc-qprd            \
-                                                    mpeg2-thread               \
+FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG2VIDEO, MPEG2VIDEO MPEGVIDEO) +=    \
+                                                    mpeg2-422                \
+                                                    mpeg2-idct-int           \
+                                                    mpeg2-ilace              \
+                                                    mpeg2-ivlc-qprd          \
+                                                    mpeg2-thread             \
                                                     mpeg2-thread-ivlc
 
 FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG4,         MP4 MOV) += mpeg4
@@ -244,12 +244,14 @@ FATE_SEEK += $(FATE_SEEK_LAVF-yes:%=fate-seek-lavf-%)
 # extra files
 
 FATE_SEEK_EXTRA-$(CONFIG_MP3_DEMUXER)   += fate-seek-extra-mp3
-fate-seek-extra-mp3:  CMD = run libavformat/seek-test$(EXESUF) $(TARGET_SAMPLES)/gapless/gapless.mp3 -fastseek 1
+FATE_SEEK_EXTRA-$(call ALLYES, CACHE_PROTOCOL PIPE_PROTOCOL MP3_DEMUXER) += fate-seek-cache-pipe
+fate-seek-extra-mp3:  CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_SAMPLES)/gapless/gapless.mp3 -fastseek 1
+fate-seek-cache-pipe: CMD = cat $(TARGET_SAMPLES)/gapless/gapless.mp3 | run libavformat/tests/seek$(EXESUF) cache:pipe:0 -read_ahead_limit -1
 FATE_SEEK_EXTRA += $(FATE_SEEK_EXTRA-yes)
 
 
-$(FATE_SEEK) $(FATE_SAMPLES_SEEK) $(FATE_SEEK_EXTRA): libavformat/seek-test$(EXESUF)
-$(FATE_SEEK) $(FATE_SAMPLES_SEEK): CMD = run libavformat/seek-test$(EXESUF) $(TARGET_PATH)/tests/data/$(SRC)
+$(FATE_SEEK) $(FATE_SAMPLES_SEEK) $(FATE_SEEK_EXTRA): libavformat/tests/seek$(EXESUF)
+$(FATE_SEEK) $(FATE_SAMPLES_SEEK): CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_PATH)/tests/data/$(SRC)
 $(FATE_SEEK) $(FATE_SAMPLES_SEEK): fate-seek-%: fate-%
 fate-seek-%: REF = $(SRC_PATH)/tests/ref/seek/$(@:fate-seek-%=%)
 
diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak
index ccf88ce..0e08894 100644
--- a/tests/fate/vcodec.mak
+++ b/tests/fate/vcodec.mak
@@ -29,6 +29,19 @@ FATE_VCODEC-$(call ENCDEC, DNXHD, DNXHD) += dnxhd-720p                  \
                                             dnxhd-720p-rd               \
                                             dnxhd-720p-10bit
 
+FATE_VCODEC-$(call ENCDEC, VC2 DIRAC, MOV) += vc2-420p vc2-420p10 vc2-420p12 \
+                                              vc2-422p vc2-422p10 vc2-422p12 \
+                                              vc2-444p vc2-444p10 vc2-444p12
+fate-vsynth1-vc2-%:              FMT      = mov
+fate-vsynth1-vc2-%:              ENCOPTS = -pix_fmt yuv$(@:fate-vsynth1-vc2-%=%) \
+                                           -vcodec vc2 -frames 5 -strict -1
+fate-vsynth2-vc2-%:              FMT      = mov
+fate-vsynth2-vc2-%:              ENCOPTS = -pix_fmt yuv$(@:fate-vsynth2-vc2-%=%) \
+                                           -vcodec vc2 -frames 5 -strict -1
+fate-vsynth_lena-vc2-%:          FMT      = mov
+fate-vsynth_lena-vc2-%:          ENCOPTS = -pix_fmt yuv$(@:fate-vsynth_lena-vc2-%=%) \
+                                           -vcodec vc2 -frames 5 -strict -1
+
 fate-vsynth%-dnxhd-720p:         ENCOPTS = -s hd720 -b 90M              \
                                            -pix_fmt yuv422p -frames 5 -qmax 8
 fate-vsynth%-dnxhd-720p:         FMT     = dnxhd
@@ -356,7 +369,9 @@ FATE_VSYNTH2 = $(FATE_VCODEC:%=fate-vsynth2-%)
 FATE_VSYNTH_LENA = $(FATE_VCODEC:%=fate-vsynth_lena-%)
 # Redundant tests because they just resize the input
 RESIZE_OFF   = dnxhd-720p dnxhd-720p-rd dnxhd-720p-10bit dnxhd-1080i \
-               dv dv-411 dv-50 avui snow snow-hpel snow-ll
+               dv dv-411 dv-50 avui snow snow-hpel snow-ll vc2-420p \
+               vc2-420p10 vc2-420p12 vc2-422p vc2-422p10 vc2-422p12 \
+               vc2-444p vc2-444p10 vc2-444p12
 # Incorrect parameters - usually size or color format restrictions
 INC_PAR_OFF  = cinepak h261 h261-trellis h263 h263p h263-obmc msvideo1 \
                roqvideo rv10 rv20 y41p qtrlegray
diff --git a/tests/fate/video.mak b/tests/fate/video.mak
index 8b70b08..2f4ab6d 100644
--- a/tests/fate/video.mak
+++ b/tests/fate/video.mak
@@ -7,6 +7,9 @@ fate-4xm-2: CMD = framecrc -i $(TARGET_SAMPLES)/4xm/version2.4xm -pix_fmt rgb24
 FATE_VIDEO-$(call DEMDEC, FOURXM, FOURXM) += $(FATE_4XM)
 fate-4xm: $(FATE_4XM)
 
+FATE_VIDEO-$(call DEMDEC, AVI, ZERO12V) += fate-012v
+fate-012v: CMD = framecrc -i $(TARGET_SAMPLES)/012v/sample.avi -pix_fmt yuv422p16le
+
 FATE_VIDEO-$(call DEMDEC, AVI, AASC) += fate-aasc
 fate-aasc: CMD = framecrc -i $(TARGET_SAMPLES)/aasc/AASC-1.5MB.AVI -pix_fmt rgb24
 
@@ -93,6 +96,9 @@ fate-cljr: CMD = framecrc -i $(TARGET_SAMPLES)/cljr/testcljr-partial.avi
 FATE_VIDEO-$(call DEMDEC, AVI, PNG) += fate-corepng
 fate-corepng: CMD = framecrc -i $(TARGET_SAMPLES)/png1/corepng-partial.avi
 
+FATE_VIDEO-$(call DEMDEC, AVI, PNG) += fate-rgbapng-4816
+fate-rgbapng-4816: CMD = framecrc -i $(TARGET_SAMPLES)/png1/55c99e750a5fd6_50314226.png
+
 FATE_VIDEO-$(call DEMDEC, AVS, AVS) += fate-creatureshock-avs
 fate-creatureshock-avs: CMD = framecrc -i $(TARGET_SAMPLES)/creatureshock-avs/OUTATIME.AVS -pix_fmt rgb24
 
diff --git a/tests/fate/voice.mak b/tests/fate/voice.mak
index 7389c43..f3a2892 100644
--- a/tests/fate/voice.mak
+++ b/tests/fate/voice.mak
@@ -7,7 +7,7 @@ fate-g722-encode: SRC = tests/data/asynth-16000-1.wav
 fate-g722-encode: CMD = enc_dec_pcm wav framemd5 s16le $(SRC) -c:a g722
 
 FATE_VOICE-yes += $(FATE_G722-yes)
-fate-g722: $(FATE_G722)
+fate-g722: $(FATE_G722-yes)
 
 FATE_G723_1 += fate-g723_1-dec-1
 fate-g723_1-dec-1: CMD = framecrc -postfilter 0 -i $(TARGET_SAMPLES)/g723_1/ineqd53.tco
@@ -33,8 +33,7 @@ fate-g723_1-dec-7: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/dtx6
 FATE_G723_1 += fate-g723_1-dec-8
 fate-g723_1-dec-8: CMD = framecrc -postfilter 1 -i $(TARGET_SAMPLES)/g723_1/dtx63e.tco
 
-FATE_G723_1-$(call DEMDEC, G723_1, G723_1) += $(FATE_G723_1)
-FATE_SAMPLES_AVCONV += $(FATE_G723_1-yes)
+FATE_VOICE-$(call DEMDEC, G723_1, G723_1) += $(FATE_G723_1)
 fate-g723_1: $(FATE_G723_1)
 
 FATE_G726 += fate-g726-encode-2bit
@@ -62,7 +61,7 @@ FATE_GSM-$(call DEMDEC, MOV, GSM) += fate-gsm-toast
 fate-gsm-toast: CMD = framecrc -i $(TARGET_SAMPLES)/gsm/sample-gsm-8000.mov -t 10
 
 FATE_VOICE-yes += $(FATE_GSM-yes)
-fate-gsm: $(FATE_GSM)
+fate-gsm: $(FATE_GSM-yes)
 
 FATE_VOICE-$(call DEMDEC, QCP, QCELP) += fate-qcelp
 fate-qcelp: CMD = pcm -i $(TARGET_SAMPLES)/qcp/0036580847.QCP
diff --git a/tests/fate/vorbis.mak b/tests/fate/vorbis.mak
index 4b72373..354cc57 100644
--- a/tests/fate/vorbis.mak
+++ b/tests/fate/vorbis.mak
@@ -1,3 +1,11 @@
+FATE_VORBIS += fate-vorbis-encode
+fate-vorbis-encode: CMD = enc_dec_pcm ogg wav s16le $(TARGET_SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav -c:a vorbis -strict experimental
+fate-vorbis-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
+fate-vorbis-encode: CMP_SHIFT = 0
+fate-vorbis-encode: CMP_TARGET = 296
+fate-vorbis-encode: SIZE_TOLERANCE = 3560
+fate-vorbis-encode: FUZZ = 30
+
 FATE_VORBIS += fate-vorbis-1
 fate-vorbis-1: CMD = pcm -i $(TARGET_SAMPLES)/vorbis/1.0.1-test_small.ogg
 fate-vorbis-1: REF = $(SAMPLES)/vorbis/1.0.1-test_small.pcm
@@ -80,6 +88,12 @@ FATE_VORBIS += fate-vorbis-20
 fate-vorbis-20: CMD = pcm -i $(TARGET_SAMPLES)/vorbis/6.ogg
 fate-vorbis-20: REF = $(SAMPLES)/vorbis/6.pcm
 
+FATE_VORBIS_FFPROBE-$(CONFIG_OGG_DEMUXER) += fate-vorbis-1833-chapters
+fate-vorbis-1833-chapters: CMD = probechapters $(TARGET_SAMPLES)/vorbis/vorbis_chapter_extension_demo.ogg
+
+FATE_SAMPLES_FFPROBE += $(FATE_VORBIS_FFPROBE-yes)
+
 FATE_SAMPLES_AVCONV-$(call DEMDEC, OGG, VORBIS) += $(FATE_VORBIS)
-fate-vorbis: $(FATE_VORBIS)
+fate-vorbis: $(FATE_VORBIS) $(FATE_VORBIS_FFPROBE-yes)
 $(FATE_VORBIS): CMP = oneoff
+fate-vorbis-encode: CMP = stddev
diff --git a/tests/fate/vpx.mak b/tests/fate/vpx.mak
index a4067d3..f0bcfac 100644
--- a/tests/fate/vpx.mak
+++ b/tests/fate/vpx.mak
@@ -20,10 +20,10 @@ FATE_VP6-$(call DEMDEC, EA, VP6) += fate-vp61
 fate-vp61: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/ea-vp6/MovieSkirmishGondor.vp6 -t 4
 
 FATE_VP6-$(call DEMDEC, FLV, VP6A) += fate-vp6a
-fate-vp6a: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/flash-vp6/300x180-Scr-f8-056alpha.flv
+fate-vp6a: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/flash-vp6/300x180-Scr-f8-056alpha.mov
 
 FATE_VP6-$(call DEMDEC, FLV, VP6A) += fate-vp6a-skip_alpha
-fate-vp6a-skip_alpha: CMD = framecrc -flags +bitexact -skip_alpha 1 -i $(TARGET_SAMPLES)/flash-vp6/300x180-Scr-f8-056alpha.flv
+fate-vp6a-skip_alpha: CMD = framecrc -flags +bitexact -skip_alpha 1 -i $(TARGET_SAMPLES)/flash-vp6/300x180-Scr-f8-056alpha.mov
 
 FATE_VP6-$(call DEMDEC, FLV, VP6F) += fate-vp6f
 fate-vp6f: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/flash-vp6/clip1024.flv
@@ -46,6 +46,9 @@ fate-webm-dash-manifest-representations: CMD = run $(FFMPEG) -f webm_dash_manife
 FATE_VP8-$(call DEMDEC, WEBM_DASH_MANIFEST, VP8) += fate-webm-dash-manifest-live
 fate-webm-dash-manifest-live: CMD = run $(FFMPEG) -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_video_360.hdr -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_audio_171.hdr -c copy -map 0 -map 1 -f webm_dash_manifest -live 1 -adaptation_sets "id=0,streams=0 id=1,streams=1" -chunk_start_index 1 -chunk_duration_ms 5000 -time_shift_buffer_depth 7200 -minimum_update_period 60 -debug_mode 1 -
 
+FATE_VP8-$(call DEMDEC, MATROSKA, VP8) += fate-vp8-2451
+fate-vp8-2451: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp8/RRSF49-short.webm -vsync cfr -an
+
 FATE_SAMPLES_AVCONV += $(FATE_VP6-yes)
 fate-vp6: $(FATE_VP6-yes)
 
diff --git a/tests/filtergraphs/anequalizer b/tests/filtergraphs/anequalizer
new file mode 100644
index 0000000..fd4a86f
--- /dev/null
+++ b/tests/filtergraphs/anequalizer
@@ -0,0 +1 @@
+anequalizer='c0 f=200 w=200 g=-80 t=1'
diff --git a/tests/filtergraphs/overlay-dvdsub-2397 b/tests/filtergraphs/overlay-dvdsub-2397
new file mode 100644
index 0000000..64133ff
--- /dev/null
+++ b/tests/filtergraphs/overlay-dvdsub-2397
@@ -0,0 +1,2 @@
+sws_flags=+accurate_rnd+bitexact;
+[0:v][0:s:1]overlay
diff --git a/tests/lavf-regression.sh b/tests/lavf-regression.sh
index a37f714..f390dd9 100755
--- a/tests/lavf-regression.sh
+++ b/tests/lavf-regression.sh
@@ -122,6 +122,7 @@ if [ -n "$do_mov" ] ; then
 mov_common_opt="-acodec pcm_alaw -vcodec mpeg4 -threads 1"
 do_lavf mov "" "-movflags +rtphint $mov_common_opt"
 do_lavf_timecode mov "-movflags +faststart $mov_common_opt"
+do_lavf_timecode mp4 "-vcodec mpeg4 -an -threads 1"
 fi
 
 if [ -n "$do_ismv" ] ; then
@@ -164,6 +165,16 @@ DEC_OPTS="$DEC_OPTS -idct auto"
 do_lavf_fate ogg "vp3/coeff_level64.mkv"
 fi
 
+if [ -n "$do_mov_qtrle_mace6" ] ; then
+DEC_OPTS="$DEC_OPTS -idct auto"
+do_lavf_fate mov "qtrle/Animation-16Greys.mov"
+fi
+
+if [ -n "$do_avi_cram" ] ; then
+DEC_OPTS="$DEC_OPTS -idct auto"
+do_lavf_fate avi "cram/toon.avi"
+fi
+
 if [ -n "$do_wtv" ] ; then
 do_lavf wtv "" "-acodec mp2 -threads 1"
 fi
diff --git a/tests/ref/acodec/pcm-s16be_planar b/tests/ref/acodec/pcm-s16be_planar
index 3d7d7b1..12ebdee 100644
--- a/tests/ref/acodec/pcm-s16be_planar
+++ b/tests/ref/acodec/pcm-s16be_planar
@@ -1,4 +1,4 @@
-a2d4da448a83dac7cbe11eea96e679fb *tests/data/fate/acodec-pcm-s16be_planar.nut
-1060722 tests/data/fate/acodec-pcm-s16be_planar.nut
+b2acc0309be76b5f6200b525281a9037 *tests/data/fate/acodec-pcm-s16be_planar.nut
+1060727 tests/data/fate/acodec-pcm-s16be_planar.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s16be_planar.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-s16le_planar b/tests/ref/acodec/pcm-s16le_planar
index c635c72..cc5c3c6 100644
--- a/tests/ref/acodec/pcm-s16le_planar
+++ b/tests/ref/acodec/pcm-s16le_planar
@@ -1,4 +1,4 @@
-761404c11c5b4b0a8bba0061704f70a4 *tests/data/fate/acodec-pcm-s16le_planar.nut
-1060722 tests/data/fate/acodec-pcm-s16le_planar.nut
+15aa8f9d8ca30a17c7821acfcd9d87f9 *tests/data/fate/acodec-pcm-s16le_planar.nut
+1060727 tests/data/fate/acodec-pcm-s16le_planar.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s16le_planar.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-s24le_planar b/tests/ref/acodec/pcm-s24le_planar
index 67393d9..5e83a19 100644
--- a/tests/ref/acodec/pcm-s24le_planar
+++ b/tests/ref/acodec/pcm-s24le_planar
@@ -1,4 +1,4 @@
-aa9f8ca95de20b2e83f66dcbb15cc307 *tests/data/fate/acodec-pcm-s24le_planar.nut
-1590251 tests/data/fate/acodec-pcm-s24le_planar.nut
+1c746862c9d79c57e275266f63822b29 *tests/data/fate/acodec-pcm-s24le_planar.nut
+1590256 tests/data/fate/acodec-pcm-s24le_planar.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s24le_planar.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-s32le_planar b/tests/ref/acodec/pcm-s32le_planar
index 643659f..ff3051b 100644
--- a/tests/ref/acodec/pcm-s32le_planar
+++ b/tests/ref/acodec/pcm-s32le_planar
@@ -1,4 +1,4 @@
-d2a712fe08b1792bc65f255f54bb980e *tests/data/fate/acodec-pcm-s32le_planar.nut
-2120197 tests/data/fate/acodec-pcm-s32le_planar.nut
+d142973733ff4d61644b704438a4ba32 *tests/data/fate/acodec-pcm-s32le_planar.nut
+2120202 tests/data/fate/acodec-pcm-s32le_planar.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-s32le_planar.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-s8_planar b/tests/ref/acodec/pcm-s8_planar
index 301e715..9cd795d 100644
--- a/tests/ref/acodec/pcm-s8_planar
+++ b/tests/ref/acodec/pcm-s8_planar
@@ -1,4 +1,4 @@
-c0e10e4a5106137082131807b6674a71 *tests/data/fate/acodec-pcm-s8_planar.nut
-531100 tests/data/fate/acodec-pcm-s8_planar.nut
+f04f79b2e90921a513f2d22fdab0dc47 *tests/data/fate/acodec-pcm-s8_planar.nut
+531105 tests/data/fate/acodec-pcm-s8_planar.nut
 652edf30f35ad89bf27bcc9d2f9c7b53 *tests/data/fate/acodec-pcm-s8_planar.out.wav
 stddev:  147.89 PSNR: 52.93 MAXDIFF:  255 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-u16be b/tests/ref/acodec/pcm-u16be
index 3fd831d..015340c 100644
--- a/tests/ref/acodec/pcm-u16be
+++ b/tests/ref/acodec/pcm-u16be
@@ -1,4 +1,4 @@
-753d5bfdc38d314fa3b1a2eb34449aea *tests/data/fate/acodec-pcm-u16be.nut
-1060715 tests/data/fate/acodec-pcm-u16be.nut
+abc31c722aee72f21b5f858731c28fb9 *tests/data/fate/acodec-pcm-u16be.nut
+1060720 tests/data/fate/acodec-pcm-u16be.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u16be.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-u16le b/tests/ref/acodec/pcm-u16le
index ea724bb..7efb086 100644
--- a/tests/ref/acodec/pcm-u16le
+++ b/tests/ref/acodec/pcm-u16le
@@ -1,4 +1,4 @@
-cee38dc471b6b72d97e44d1667591362 *tests/data/fate/acodec-pcm-u16le.nut
-1060715 tests/data/fate/acodec-pcm-u16le.nut
+80cf805a16a6b4f02f46ff9008ca16f7 *tests/data/fate/acodec-pcm-u16le.nut
+1060720 tests/data/fate/acodec-pcm-u16le.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u16le.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-u24be b/tests/ref/acodec/pcm-u24be
index 3c19637..ef423ea 100644
--- a/tests/ref/acodec/pcm-u24be
+++ b/tests/ref/acodec/pcm-u24be
@@ -1,4 +1,4 @@
-84c2b6f7197840e40c5f646efd8a43a4 *tests/data/fate/acodec-pcm-u24be.nut
-1590244 tests/data/fate/acodec-pcm-u24be.nut
+c5b7d1898d8f5d6675ba543d2830bbaf *tests/data/fate/acodec-pcm-u24be.nut
+1590249 tests/data/fate/acodec-pcm-u24be.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u24be.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-u24le b/tests/ref/acodec/pcm-u24le
index b82d6bc..4010a1a 100644
--- a/tests/ref/acodec/pcm-u24le
+++ b/tests/ref/acodec/pcm-u24le
@@ -1,4 +1,4 @@
-5afea1f1b1d0590dbae2ac2e0092f434 *tests/data/fate/acodec-pcm-u24le.nut
-1590244 tests/data/fate/acodec-pcm-u24le.nut
+884a3a562a8005084fde088fc3a74283 *tests/data/fate/acodec-pcm-u24le.nut
+1590249 tests/data/fate/acodec-pcm-u24le.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u24le.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-u32be b/tests/ref/acodec/pcm-u32be
index 909a130..358a01e 100644
--- a/tests/ref/acodec/pcm-u32be
+++ b/tests/ref/acodec/pcm-u32be
@@ -1,4 +1,4 @@
-529f523fcd04002791fce9cee797783b *tests/data/fate/acodec-pcm-u32be.nut
-2120190 tests/data/fate/acodec-pcm-u32be.nut
+88d1f0b98e2878f0a45abde7ad73e9f1 *tests/data/fate/acodec-pcm-u32be.nut
+2120195 tests/data/fate/acodec-pcm-u32be.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u32be.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/pcm-u32le b/tests/ref/acodec/pcm-u32le
index 16a183f..6857ec0 100644
--- a/tests/ref/acodec/pcm-u32le
+++ b/tests/ref/acodec/pcm-u32le
@@ -1,4 +1,4 @@
-87f75abd86f84571bafc656e06b63038 *tests/data/fate/acodec-pcm-u32le.nut
-2120190 tests/data/fate/acodec-pcm-u32le.nut
+7257d6251524479c563c9f17a2642222 *tests/data/fate/acodec-pcm-u32le.nut
+2120195 tests/data/fate/acodec-pcm-u32le.nut
 95e54b261530a1bcf6de6fe3b21dc5f6 *tests/data/fate/acodec-pcm-u32le.out.wav
 stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  1058400/  1058400
diff --git a/tests/ref/acodec/s302m b/tests/ref/acodec/s302m
index f19eebe..5eca9e3 100644
--- a/tests/ref/acodec/s302m
+++ b/tests/ref/acodec/s302m
@@ -1,4 +1,4 @@
-2d1494ad78292dca556fd079ec27f28d *tests/data/fate/acodec-s302m.mpegts
+f6908214498489799b50e332ac42ebf3 *tests/data/fate/acodec-s302m.mpegts
 1589164 tests/data/fate/acodec-s302m.mpegts
 f9b6528eee1aea04640ee83400c78689 *tests/data/fate/acodec-s302m.out.wav
 stddev:  986.97 PSNR: 36.44 MAXDIFF:18642 bytes:  1058400/  1056708
diff --git a/tests/ref/fate/012v b/tests/ref/fate/012v
new file mode 100644
index 0000000..198bba3
--- /dev/null
+++ b/tests/ref/fate/012v
@@ -0,0 +1,6 @@
+#tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 316x240
+#sar 0: 0/1
+0,          0,          0,        1,   303360, 0xc5439580
diff --git a/tests/ref/fate/4xm-1 b/tests/ref/fate/4xm-1
index 37371aa..96f3539 100644
--- a/tests/ref/fate/4xm-1
+++ b/tests/ref/fate/4xm-1
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0xd82e4d57
 0,          1,          1,        1,   921600, 0x83f2349c
 0,          2,          2,        1,   921600, 0x70d87db0
diff --git a/tests/ref/fate/4xm-2 b/tests/ref/fate/4xm-2
index 6895d12..c28dc14 100644
--- a/tests/ref/fate/4xm-2
+++ b/tests/ref/fate/4xm-2
@@ -1,4 +1,8 @@
 #tb 0: 4/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 240x112
+#sar 0: 0/1
 0,          0,          0,        1,    80640, 0x00000000
 0,          1,          1,        1,    80640, 0x3a942680
 0,          2,          2,        1,    80640, 0x3a942680
diff --git a/tests/ref/fate/8bps b/tests/ref/fate/8bps
index 9db9430..c6287ff 100644
--- a/tests/ref/fate/8bps
+++ b/tests/ref/fate/8bps
@@ -1,5 +1,13 @@
 #tb 0: 2/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 360x240
+#sar 0: 9/10
 #tb 1: 1/22050
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 22050
+#channel_layout 1: 4
 0,          0,          0,        1,   259200, 0x7e91df07
 1,          0,          0,     1024,     2048, 0x3d042426
 1,       1024,       1024,     1024,     2048, 0x5bcae456
diff --git a/tests/ref/fate/aasc b/tests/ref/fate/aasc
index 83f83b9..f69376e 100644
--- a/tests/ref/fate/aasc
+++ b/tests/ref/fate/aasc
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x175
+#sar 0: 0/1
 0,          0,          0,        1,   168000, 0x00000000
 0,          1,          1,        1,   168000, 0x00000000
 0,          2,          2,        1,   168000, 0x00000000
diff --git a/tests/ref/fate/adpcm-4xm b/tests/ref/fate/adpcm-4xm
index eb5cfe6..cb725e5 100644
--- a/tests/ref/fate/adpcm-4xm
+++ b/tests/ref/fate/adpcm-4xm
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,     1472,     5888, 0x9086e310
 0,       1476,       1476,     1472,     5888, 0xac8491f5
 0,       2952,       2952,     1472,     5888, 0xc9a08b6b
diff --git a/tests/ref/fate/adpcm-afc b/tests/ref/fate/adpcm-afc
index d1a1c36..0cf61a9 100644
--- a/tests/ref/fate/adpcm-afc
+++ b/tests/ref/fate/adpcm-afc
@@ -1,4 +1,8 @@
 #tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
 0,          0,          0,    17920,    71680, 0x52373bc9
 0,      17920,      17920,    17920,    71680, 0x1f854b27
 0,      35840,      35840,    17920,    71680, 0x3d265a6d
diff --git a/tests/ref/fate/adpcm-dtk b/tests/ref/fate/adpcm-dtk
index 3640e1c..acdf033 100644
--- a/tests/ref/fate/adpcm-dtk
+++ b/tests/ref/fate/adpcm-dtk
@@ -1,4 +1,8 @@
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 48000
+#channel_layout 0: 3
 0,          0,          0,      896,     3584, 0xdae789d5
 0,        896,        896,      896,     3584, 0x168ed9b6
 0,       1792,       1792,      896,     3584, 0x8920c8d5
diff --git a/tests/ref/fate/adpcm-ea-1 b/tests/ref/fate/adpcm-ea-1
index f5a33df..fa9906c 100644
--- a/tests/ref/fate/adpcm-ea-1
+++ b/tests/ref/fate/adpcm-ea-1
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,     1484,     5936, 0x00000000
 0,       1484,       1484,     1456,     5824, 0x00000000
 0,       2940,       2940,     1484,     5936, 0x00000000
diff --git a/tests/ref/fate/adpcm-ea-2 b/tests/ref/fate/adpcm-ea-2
index f58d9a0..4743e3d 100644
--- a/tests/ref/fate/adpcm-ea-2
+++ b/tests/ref/fate/adpcm-ea-2
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,     1484,     5936, 0xea261a29
 0,       1484,       1484,     1456,     5824, 0x253df061
 0,       2940,       2940,     1484,     5936, 0x603a5bd7
diff --git a/tests/ref/fate/adpcm-ea-maxis-xa b/tests/ref/fate/adpcm-ea-maxis-xa
index 5d6b5c0..b300c32 100644
--- a/tests/ref/fate/adpcm-ea-maxis-xa
+++ b/tests/ref/fate/adpcm-ea-maxis-xa
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,       28,      112, 0x291d1be4
 0,         28,         28,       28,      112, 0xf08d33cc
 0,         56,         56,       28,      112, 0x5b1521de
diff --git a/tests/ref/fate/adpcm-ea-r1 b/tests/ref/fate/adpcm-ea-r1
index 74d15c6..2208eb0 100644
--- a/tests/ref/fate/adpcm-ea-r1
+++ b/tests/ref/fate/adpcm-ea-r1
@@ -1,4 +1,8 @@
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 48000
+#channel_layout 0: 3
 0,          0,          0,     1624,     6496, 0x00000000
 0,       1624,       1624,     1596,     6384, 0x00000000
 0,       3220,       3220,     1596,     6384, 0x00000000
diff --git a/tests/ref/fate/adpcm-ima-amv b/tests/ref/fate/adpcm-ima-amv
index 4bd22af..def9279 100644
--- a/tests/ref/fate/adpcm-ima-amv
+++ b/tests/ref/fate/adpcm-ima-amv
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 4
 0,          0,          0,     1378,     2756, 0x0af35034
 0,       1378,       1378,     1378,     2756, 0x8462443f
 0,       2756,       2756,     1378,     2756, 0x9f493ba6
diff --git a/tests/ref/fate/adpcm-ima-ea-eacs b/tests/ref/fate/adpcm-ima-ea-eacs
index 9887296..d5ea2e5 100644
--- a/tests/ref/fate/adpcm-ima-ea-eacs
+++ b/tests/ref/fate/adpcm-ima-ea-eacs
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,     1468,     5872, 0x00000000
 0,       1468,       1468,     1468,     5872, 0x00000000
 0,       2936,       2936,     1468,     5872, 0x00000000
diff --git a/tests/ref/fate/adpcm-ima-ea-sead b/tests/ref/fate/adpcm-ima-ea-sead
index 17c1087..563bb49 100644
--- a/tests/ref/fate/adpcm-ima-ea-sead
+++ b/tests/ref/fate/adpcm-ima-ea-sead
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,      736,     2944, 0x00000000
 0,        736,        736,     1472,     5888, 0x5ae3c2a4
 0,       2208,       2208,     1472,     5888, 0x158fbcb4
diff --git a/tests/ref/fate/adpcm-ima-smjpeg b/tests/ref/fate/adpcm-ima-smjpeg
index 3a746b6..f88520d 100644
--- a/tests/ref/fate/adpcm-ima-smjpeg
+++ b/tests/ref/fate/adpcm-ima-smjpeg
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 4
 0,          0,          0,      512,     1024, 0x00000000
 0,        512,        512,      512,     1024, 0x00000000
 0,       1024,       1024,      512,     1024, 0xed2d3f6b
diff --git a/tests/ref/fate/adpcm-ima-ws b/tests/ref/fate/adpcm-ima-ws
index 61e0def..0e41e1e 100644
--- a/tests/ref/fate/adpcm-ima-ws
+++ b/tests/ref/fate/adpcm-ima-ws
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 4
 0,          0,          0,    11024,    22048, 0x0665d7f4
 0,      11024,      11024,     1470,     2940, 0x0f3c64cb
 0,      12494,      12494,     1470,     2940, 0xc90b9e78
diff --git a/tests/ref/fate/adpcm-ms-mono b/tests/ref/fate/adpcm-ms-mono
index c456708..254dc8a 100644
--- a/tests/ref/fate/adpcm-ms-mono
+++ b/tests/ref/fate/adpcm-ms-mono
@@ -1,4 +1,8 @@
 #tb 0: 1/11025
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 11025
+#channel_layout 0: 4
 0,          0,          0,      500,     1000, 0x64cd9403
 0,        500,        500,      500,     1000, 0xa4ef8a9d
 0,       1000,       1000,      500,     1000, 0x75c19868
diff --git a/tests/ref/fate/adpcm-thp b/tests/ref/fate/adpcm-thp
index 0063b6c..ff49303 100644
--- a/tests/ref/fate/adpcm-thp
+++ b/tests/ref/fate/adpcm-thp
@@ -1,4 +1,8 @@
 #tb 0: 1/32000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 32000
+#channel_layout 0: 3
 0,          0,          0,     1078,     4312, 0x469714f6
 0,       1078,       1078,     1064,     4256, 0x6ca28f25
 0,       2142,       2142,     1078,     4312, 0xd466f806
diff --git a/tests/ref/fate/adpcm-vima b/tests/ref/fate/adpcm-vima
index 6984c5d..5bc62c3 100644
--- a/tests/ref/fate/adpcm-vima
+++ b/tests/ref/fate/adpcm-vima
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,    73500,   294000, 0x37d439ee
 0,      73500,      73500,     1470,     5880, 0xe524b177
 0,      74970,      74970,     1470,     5880, 0x9e784af1
diff --git a/tests/ref/fate/adpcm-xa b/tests/ref/fate/adpcm-xa
index 04be2b9..e365227 100644
--- a/tests/ref/fate/adpcm-xa
+++ b/tests/ref/fate/adpcm-xa
@@ -1,4 +1,8 @@
 #tb 0: 1/37800
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 37800
+#channel_layout 0: 3
 0,          0,          0,     2016,     8064, 0xa307ed8c
 0,       2016,       2016,     2016,     8064, 0xd2551927
 0,       4032,       4032,     2016,     8064, 0x3264a799
diff --git a/tests/ref/fate/aic b/tests/ref/fate/aic
index 90692f1..1f50350 100644
--- a/tests/ref/fate/aic
+++ b/tests/ref/fate/aic
@@ -1,4 +1,8 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1440x1080
+#sar 0: 4/3
 0,          0,          0,        1,  2332800, 0xd941b42f
 0,          1,          1,        1,  2332800, 0xd941b42f
 0,          2,          2,        1,  2332800, 0xae0f5983
diff --git a/tests/ref/fate/aic-oddsize b/tests/ref/fate/aic-oddsize
index 9183089..3763e32 100644
--- a/tests/ref/fate/aic-oddsize
+++ b/tests/ref/fate/aic-oddsize
@@ -1,4 +1,8 @@
 #tb 0: 1000/14587
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 481x241
+#sar 0: 0/1
 0,          0,          0,        1,   174243, 0xa40491e1
 0,          1,          1,        1,   174243, 0xa12cbb56
 0,          2,          2,        1,   174243, 0xa12cbb56
diff --git a/tests/ref/fate/alg-mm b/tests/ref/fate/alg-mm
index 5d97de9..5788012 100644
--- a/tests/ref/fate/alg-mm
+++ b/tests/ref/fate/alg-mm
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x160
+#sar 0: 0/1
 0,          0,          0,        1,   122880, 0x4ed8123f
 0,          1,          1,        1,   122880, 0xc4c35304
 0,          2,          2,        1,   122880, 0xbd3015fd
diff --git a/tests/ref/fate/aliaspix-bgr b/tests/ref/fate/aliaspix-bgr
index 8671d3e..f5c6b7d 100644
--- a/tests/ref/fate/aliaspix-bgr
+++ b/tests/ref/fate/aliaspix-bgr
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 201x79
+#sar 0: 0/1
 0,          0,          0,        1,    47637, 0xcb77368f
diff --git a/tests/ref/fate/aliaspix-gray b/tests/ref/fate/aliaspix-gray
index 0433a36..aa7b464 100644
--- a/tests/ref/fate/aliaspix-gray
+++ b/tests/ref/fate/aliaspix-gray
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 199x81
+#sar 0: 0/1
 0,          0,          0,        1,    16119, 0x3d0785f5
diff --git a/tests/ref/fate/amv b/tests/ref/fate/amv
index 407f077..4b2c168 100644
--- a/tests/ref/fate/amv
+++ b/tests/ref/fate/amv
@@ -1,4 +1,8 @@
 #tb 0: 1/16
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    28800, 0x026058a9
 0,          1,          1,        1,    28800, 0x5dc728de
 0,          2,          2,        1,    28800, 0x83e19a2c
diff --git a/tests/ref/fate/ansi b/tests/ref/fate/ansi
index 78e853f..5cf6ff9 100644
--- a/tests/ref/fate/ansi
+++ b/tests/ref/fate/ansi
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x400
+#sar 0: 0/1
 0,          0,          0,        1,   768000, 0x772dd3d0
 0,          1,          1,        1,   768000, 0xd7dab1d1
 0,          2,          2,        1,   768000, 0x0e56f2d3
diff --git a/tests/ref/fate/ansi256 b/tests/ref/fate/ansi256
index 94acd45..f68a0d1 100644
--- a/tests/ref/fate/ansi256
+++ b/tests/ref/fate/ansi256
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x400
+#sar 0: 0/1
 0,          0,          0,        1,   768000, 0x4dfbb6d0
 0,          1,          1,        1,   768000, 0x22652a22
 0,          2,          2,        1,   768000, 0x6c613e8c
diff --git a/tests/ref/fate/api-mjpeg-codec-param b/tests/ref/fate/api-mjpeg-codec-param
index 6f8da74..c67d1b1 100644
--- a/tests/ref/fate/api-mjpeg-codec-param
+++ b/tests/ref/fate/api-mjpeg-codec-param
@@ -62,6 +62,7 @@ stream=0, decode=0
     bits_per_coded_sample=0
     pred=0
     aspect=180/180
+    sar=180/180
     debug=0x00000000
     vismv=0x00000000
     cmp=0
@@ -145,6 +146,7 @@ stream=0, decode=0
     pkt_timebase=1/25
     sub_charenc=
     sub_charenc_mode=0x00000000
+    sub_text_format=1
     refcounted_frames=false
     side_data_only_packets=true
     skip_alpha=false
@@ -217,6 +219,7 @@ stream=0, decode=1
     bits_per_coded_sample=0
     pred=0
     aspect=180/180
+    sar=180/180
     debug=0x00000000
     vismv=0x00000000
     cmp=0
@@ -300,6 +303,7 @@ stream=0, decode=1
     pkt_timebase=1/25
     sub_charenc=
     sub_charenc_mode=0x00000000
+    sub_text_format=1
     refcounted_frames=false
     side_data_only_packets=true
     skip_alpha=false
diff --git a/tests/ref/fate/api-png-codec-param b/tests/ref/fate/api-png-codec-param
index 2263774..bd53441 100644
--- a/tests/ref/fate/api-png-codec-param
+++ b/tests/ref/fate/api-png-codec-param
@@ -62,6 +62,7 @@ stream=0, decode=0
     bits_per_coded_sample=0
     pred=0
     aspect=2835/2835
+    sar=2835/2835
     debug=0x00000000
     vismv=0x00000000
     cmp=0
@@ -145,6 +146,7 @@ stream=0, decode=0
     pkt_timebase=1/25
     sub_charenc=
     sub_charenc_mode=0x00000000
+    sub_text_format=1
     refcounted_frames=false
     side_data_only_packets=true
     skip_alpha=false
@@ -217,6 +219,7 @@ stream=0, decode=1
     bits_per_coded_sample=0
     pred=0
     aspect=2835/2835
+    sar=2835/2835
     debug=0x00000000
     vismv=0x00000000
     cmp=0
@@ -300,6 +303,7 @@ stream=0, decode=1
     pkt_timebase=1/25
     sub_charenc=
     sub_charenc_mode=0x00000000
+    sub_text_format=1
     refcounted_frames=false
     side_data_only_packets=true
     skip_alpha=false
diff --git a/tests/ref/fate/armovie-escape124 b/tests/ref/fate/armovie-escape124
index 83614c2..5c8f051 100644
--- a/tests/ref/fate/armovie-escape124
+++ b/tests/ref/fate/armovie-escape124
@@ -1,5 +1,13 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 #tb 1: 1/44100
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 44100
+#channel_layout 1: 3
 0,          0,          0,        1,   230400, 0xd133e177
 1,          0,          0,    44100,   176400, 0xdd61578c
 0,          1,          1,        1,   230400, 0xe3501bb2
diff --git a/tests/ref/fate/armovie-escape130 b/tests/ref/fate/armovie-escape130
index ee4ec26..6925a48 100644
--- a/tests/ref/fate/armovie-escape130
+++ b/tests/ref/fate/armovie-escape130
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x160
+#sar 0: 0/1
 0,          0,          0,        1,    76800, 0x860502ee
 0,          1,          1,        1,    76800, 0x055da755
 0,          2,          2,        1,    76800, 0x67969220
diff --git a/tests/ref/fate/asf-repldata b/tests/ref/fate/asf-repldata
index ff12ff0..9474456 100644
--- a/tests/ref/fate/asf-repldata
+++ b/tests/ref/fate/asf-repldata
@@ -1,4 +1,8 @@
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: msmpeg4v3
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        0,    23374, 0x8725b3b8
 0,        122,        122,        0,    13732, 0x3ac8531a, F=0x0
 0,        245,        245,        0,      615, 0xd31641b4, F=0x0
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-mono-he-adts b/tests/ref/fate/audiomatch-afconvert-16000-mono-he-adts
new file mode 100644
index 0000000..bbbf8ff
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-mono-he-adts
@@ -0,0 +1 @@
+presig: 2593 postsig:223 c: 0.9835 lenerr:2816
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-mono-he-m4a b/tests/ref/fate/audiomatch-afconvert-16000-mono-he-m4a
new file mode 100644
index 0000000..f6f8df5
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-mono-he-m4a
@@ -0,0 +1 @@
+presig: 481 postsig:223 c: 0.9835 lenerr:704
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-mono-lc-adts b/tests/ref/fate/audiomatch-afconvert-16000-mono-lc-adts
new file mode 100644
index 0000000..bf6ecf6
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-mono-lc-adts
@@ -0,0 +1 @@
+presig: 2112 postsig:704 c: 0.9842 lenerr:2816
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-mono-lc-m4a b/tests/ref/fate/audiomatch-afconvert-16000-mono-lc-m4a
new file mode 100644
index 0000000..75cd54e
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-mono-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:704 c: 0.9842 lenerr:704
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-stereo-he-adts b/tests/ref/fate/audiomatch-afconvert-16000-stereo-he-adts
new file mode 100644
index 0000000..2e29599
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-stereo-he-adts
@@ -0,0 +1 @@
+presig: 5186 postsig:446 c: 0.9895 lenerr:5632
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-stereo-he-m4a b/tests/ref/fate/audiomatch-afconvert-16000-stereo-he-m4a
new file mode 100644
index 0000000..9ba0ef2
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-stereo-he-m4a
@@ -0,0 +1 @@
+presig: 962 postsig:446 c: 0.9895 lenerr:1408
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-stereo-he2-adts b/tests/ref/fate/audiomatch-afconvert-16000-stereo-he2-adts
new file mode 100644
index 0000000..32b2627
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-stereo-he2-adts
@@ -0,0 +1 @@
+presig: 5186 postsig:446 c: 0.9839 lenerr:5632
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-stereo-he2-m4a b/tests/ref/fate/audiomatch-afconvert-16000-stereo-he2-m4a
new file mode 100644
index 0000000..d4fc21b
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-stereo-he2-m4a
@@ -0,0 +1 @@
+presig: 962 postsig:446 c: 0.9839 lenerr:1408
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-stereo-lc-adts b/tests/ref/fate/audiomatch-afconvert-16000-stereo-lc-adts
new file mode 100644
index 0000000..360049f
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-stereo-lc-adts
@@ -0,0 +1 @@
+presig: 4224 postsig:1408 c: 0.9985 lenerr:5632
diff --git a/tests/ref/fate/audiomatch-afconvert-16000-stereo-lc-m4a b/tests/ref/fate/audiomatch-afconvert-16000-stereo-lc-m4a
new file mode 100644
index 0000000..f86ccb4
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-16000-stereo-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:1408 c: 0.9985 lenerr:1408
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-mono-he-adts b/tests/ref/fate/audiomatch-afconvert-44100-mono-he-adts
new file mode 100644
index 0000000..f339483
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-mono-he-adts
@@ -0,0 +1 @@
+presig: 5186 postsig:822 c: 0.9911 lenerr:6008
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-mono-he-m4a b/tests/ref/fate/audiomatch-afconvert-44100-mono-he-m4a
new file mode 100644
index 0000000..0ad4911
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-mono-he-m4a
@@ -0,0 +1 @@
+presig: 962 postsig:822 c: 0.9911 lenerr:1784
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-mono-lc-adts b/tests/ref/fate/audiomatch-afconvert-44100-mono-lc-adts
new file mode 100644
index 0000000..523cb1f
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-mono-lc-adts
@@ -0,0 +1 @@
+presig: 2112 postsig:824 c: 0.9995 lenerr:2936
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-mono-lc-m4a b/tests/ref/fate/audiomatch-afconvert-44100-mono-lc-m4a
new file mode 100644
index 0000000..9db2d81
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-mono-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:824 c: 0.9995 lenerr:824
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-stereo-he-adts b/tests/ref/fate/audiomatch-afconvert-44100-stereo-he-adts
new file mode 100644
index 0000000..b8fd805
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-stereo-he-adts
@@ -0,0 +1 @@
+presig: 10372 postsig:1644 c: 0.9890 lenerr:12016
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-stereo-he-m4a b/tests/ref/fate/audiomatch-afconvert-44100-stereo-he-m4a
new file mode 100644
index 0000000..ff5540b
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-stereo-he-m4a
@@ -0,0 +1 @@
+presig: 1924 postsig:1644 c: 0.9890 lenerr:3568
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-stereo-he2-adts b/tests/ref/fate/audiomatch-afconvert-44100-stereo-he2-adts
new file mode 100644
index 0000000..7e72d37
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-stereo-he2-adts
@@ -0,0 +1 @@
+presig: 10372 postsig:1644 c: 0.9909 lenerr:12016
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-stereo-he2-m4a b/tests/ref/fate/audiomatch-afconvert-44100-stereo-he2-m4a
new file mode 100644
index 0000000..f8214cf
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-stereo-he2-m4a
@@ -0,0 +1 @@
+presig: 1924 postsig:1644 c: 0.9909 lenerr:3568
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-stereo-lc-adts b/tests/ref/fate/audiomatch-afconvert-44100-stereo-lc-adts
new file mode 100644
index 0000000..bca902b
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-stereo-lc-adts
@@ -0,0 +1 @@
+presig: 4224 postsig:1648 c: 1.0006 lenerr:5872
diff --git a/tests/ref/fate/audiomatch-afconvert-44100-stereo-lc-m4a b/tests/ref/fate/audiomatch-afconvert-44100-stereo-lc-m4a
new file mode 100644
index 0000000..51f23c7
--- /dev/null
+++ b/tests/ref/fate/audiomatch-afconvert-44100-stereo-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:1648 c: 1.0006 lenerr:1648
diff --git a/tests/ref/fate/audiomatch-dolby-44100-mono-he-mp4 b/tests/ref/fate/audiomatch-dolby-44100-mono-he-mp4
new file mode 100644
index 0000000..698c196
--- /dev/null
+++ b/tests/ref/fate/audiomatch-dolby-44100-mono-he-mp4
@@ -0,0 +1 @@
+presig: 5569 postsig:-1609 c: 0.9702 lenerr:3960
diff --git a/tests/ref/fate/audiomatch-dolby-44100-mono-lc-mp4 b/tests/ref/fate/audiomatch-dolby-44100-mono-lc-mp4
new file mode 100644
index 0000000..dfc030e
--- /dev/null
+++ b/tests/ref/fate/audiomatch-dolby-44100-mono-lc-mp4
@@ -0,0 +1 @@
+presig: 2973 postsig:-37 c: 0.9998 lenerr:2936
diff --git a/tests/ref/fate/audiomatch-dolby-44100-stereo-he-mp4 b/tests/ref/fate/audiomatch-dolby-44100-stereo-he-mp4
new file mode 100644
index 0000000..2de86ac
--- /dev/null
+++ b/tests/ref/fate/audiomatch-dolby-44100-stereo-he-mp4
@@ -0,0 +1 @@
+presig: 11160 postsig:-3240 c: 0.9703 lenerr:7920
diff --git a/tests/ref/fate/audiomatch-dolby-44100-stereo-he2-mp4 b/tests/ref/fate/audiomatch-dolby-44100-stereo-he2-mp4
new file mode 100644
index 0000000..67edc2b
--- /dev/null
+++ b/tests/ref/fate/audiomatch-dolby-44100-stereo-he2-mp4
@@ -0,0 +1 @@
+presig: 15884 postsig:228 c: 0.8390 lenerr:16112
diff --git a/tests/ref/fate/audiomatch-dolby-44100-stereo-lc-mp4 b/tests/ref/fate/audiomatch-dolby-44100-stereo-lc-mp4
new file mode 100644
index 0000000..f1be5cb
--- /dev/null
+++ b/tests/ref/fate/audiomatch-dolby-44100-stereo-lc-mp4
@@ -0,0 +1 @@
+presig: 5760 postsig:-1936 c: 0.9837 lenerr:3824
diff --git a/tests/ref/fate/audiomatch-faac-16000-mono-lc-adts b/tests/ref/fate/audiomatch-faac-16000-mono-lc-adts
new file mode 100644
index 0000000..b2615df
--- /dev/null
+++ b/tests/ref/fate/audiomatch-faac-16000-mono-lc-adts
@@ -0,0 +1 @@
+presig: 0 postsig:768 c: 1.0011 lenerr:768
diff --git a/tests/ref/fate/audiomatch-faac-16000-mono-lc-m4a b/tests/ref/fate/audiomatch-faac-16000-mono-lc-m4a
new file mode 100644
index 0000000..b2615df
--- /dev/null
+++ b/tests/ref/fate/audiomatch-faac-16000-mono-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:768 c: 1.0011 lenerr:768
diff --git a/tests/ref/fate/audiomatch-faac-16000-stereo-lc-adts b/tests/ref/fate/audiomatch-faac-16000-stereo-lc-adts
new file mode 100644
index 0000000..b0fa495
--- /dev/null
+++ b/tests/ref/fate/audiomatch-faac-16000-stereo-lc-adts
@@ -0,0 +1 @@
+presig: 0 postsig:1536 c: 1.0011 lenerr:1536
diff --git a/tests/ref/fate/audiomatch-faac-16000-stereo-lc-m4a b/tests/ref/fate/audiomatch-faac-16000-stereo-lc-m4a
new file mode 100644
index 0000000..b0fa495
--- /dev/null
+++ b/tests/ref/fate/audiomatch-faac-16000-stereo-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:1536 c: 1.0011 lenerr:1536
diff --git a/tests/ref/fate/audiomatch-faac-44100-mono-lc-adts b/tests/ref/fate/audiomatch-faac-44100-mono-lc-adts
new file mode 100644
index 0000000..66faeb6
--- /dev/null
+++ b/tests/ref/fate/audiomatch-faac-44100-mono-lc-adts
@@ -0,0 +1 @@
+presig: 0 postsig:888 c: 0.9882 lenerr:888
diff --git a/tests/ref/fate/audiomatch-faac-44100-mono-lc-m4a b/tests/ref/fate/audiomatch-faac-44100-mono-lc-m4a
new file mode 100644
index 0000000..66faeb6
--- /dev/null
+++ b/tests/ref/fate/audiomatch-faac-44100-mono-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:888 c: 0.9882 lenerr:888
diff --git a/tests/ref/fate/audiomatch-faac-44100-stereo-lc-adts b/tests/ref/fate/audiomatch-faac-44100-stereo-lc-adts
new file mode 100644
index 0000000..c40a48e
--- /dev/null
+++ b/tests/ref/fate/audiomatch-faac-44100-stereo-lc-adts
@@ -0,0 +1 @@
+presig: 0 postsig:1776 c: 0.9882 lenerr:1776
diff --git a/tests/ref/fate/audiomatch-faac-44100-stereo-lc-m4a b/tests/ref/fate/audiomatch-faac-44100-stereo-lc-m4a
new file mode 100644
index 0000000..c40a48e
--- /dev/null
+++ b/tests/ref/fate/audiomatch-faac-44100-stereo-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:1776 c: 0.9882 lenerr:1776
diff --git a/tests/ref/fate/audiomatch-nero-16000-mono-he-m4a b/tests/ref/fate/audiomatch-nero-16000-mono-he-m4a
new file mode 100644
index 0000000..4ee764e
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-16000-mono-he-m4a
@@ -0,0 +1 @@
+presig: -4 postsig:196 c: 0.9736 lenerr:192
diff --git a/tests/ref/fate/audiomatch-nero-16000-mono-lc-m4a b/tests/ref/fate/audiomatch-nero-16000-mono-lc-m4a
new file mode 100644
index 0000000..440c419
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-16000-mono-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:192 c: 0.9965 lenerr:192
diff --git a/tests/ref/fate/audiomatch-nero-16000-stereo-he-m4a b/tests/ref/fate/audiomatch-nero-16000-stereo-he-m4a
new file mode 100644
index 0000000..cdc31c1
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-16000-stereo-he-m4a
@@ -0,0 +1 @@
+presig: -8 postsig:392 c: 0.9777 lenerr:384
diff --git a/tests/ref/fate/audiomatch-nero-16000-stereo-he2-m4a b/tests/ref/fate/audiomatch-nero-16000-stereo-he2-m4a
new file mode 100644
index 0000000..74d5497
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-16000-stereo-he2-m4a
@@ -0,0 +1 @@
+presig: 2 postsig:2590 c: 0.9934 lenerr:2592
diff --git a/tests/ref/fate/audiomatch-nero-16000-stereo-lc-m4a b/tests/ref/fate/audiomatch-nero-16000-stereo-lc-m4a
new file mode 100644
index 0000000..f36c3c8
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-16000-stereo-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:384 c: 0.9961 lenerr:384
diff --git a/tests/ref/fate/audiomatch-nero-44100-mono-he-m4a b/tests/ref/fate/audiomatch-nero-44100-mono-he-m4a
new file mode 100644
index 0000000..b5dcd9d
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-44100-mono-he-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:1336 c: 0.9973 lenerr:1336
diff --git a/tests/ref/fate/audiomatch-nero-44100-mono-lc-m4a b/tests/ref/fate/audiomatch-nero-44100-mono-lc-m4a
new file mode 100644
index 0000000..87b074a
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-44100-mono-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:312 c: 0.9986 lenerr:312
diff --git a/tests/ref/fate/audiomatch-nero-44100-stereo-he-m4a b/tests/ref/fate/audiomatch-nero-44100-stereo-he-m4a
new file mode 100644
index 0000000..42a87c0
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-44100-stereo-he-m4a
@@ -0,0 +1 @@
+presig: -2 postsig:2674 c: 0.9986 lenerr:2672
diff --git a/tests/ref/fate/audiomatch-nero-44100-stereo-he2-m4a b/tests/ref/fate/audiomatch-nero-44100-stereo-he2-m4a
new file mode 100644
index 0000000..3fa2cdb
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-44100-stereo-he2-m4a
@@ -0,0 +1 @@
+presig: 2 postsig:782 c: 0.9980 lenerr:784
diff --git a/tests/ref/fate/audiomatch-nero-44100-stereo-lc-m4a b/tests/ref/fate/audiomatch-nero-44100-stereo-lc-m4a
new file mode 100644
index 0000000..11bc41f
--- /dev/null
+++ b/tests/ref/fate/audiomatch-nero-44100-stereo-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:624 c: 0.9954 lenerr:624
diff --git a/tests/ref/fate/audiomatch-quicktime7-44100-stereo-lc-mp4 b/tests/ref/fate/audiomatch-quicktime7-44100-stereo-lc-mp4
new file mode 100644
index 0000000..b11a486
--- /dev/null
+++ b/tests/ref/fate/audiomatch-quicktime7-44100-stereo-lc-mp4
@@ -0,0 +1 @@
+presig: 4220 postsig:-2444 c: 0.9768 lenerr:1776
diff --git a/tests/ref/fate/audiomatch-quicktimeX-44100-stereo-lc-m4a b/tests/ref/fate/audiomatch-quicktimeX-44100-stereo-lc-m4a
new file mode 100644
index 0000000..9fdaf22
--- /dev/null
+++ b/tests/ref/fate/audiomatch-quicktimeX-44100-stereo-lc-m4a
@@ -0,0 +1 @@
+presig: 0 postsig:1648 c: 0.9994 lenerr:1648
diff --git a/tests/ref/fate/audiomatch-square-aac b/tests/ref/fate/audiomatch-square-aac
new file mode 100644
index 0000000..b3480d5
--- /dev/null
+++ b/tests/ref/fate/audiomatch-square-aac
@@ -0,0 +1 @@
+presig: 0 postsig:892 c: 0.9983 lenerr:892
diff --git a/tests/ref/fate/audiomatch-square-mp3 b/tests/ref/fate/audiomatch-square-mp3
new file mode 100644
index 0000000..8de55c2
--- /dev/null
+++ b/tests/ref/fate/audiomatch-square-mp3
@@ -0,0 +1 @@
+presig: 0 postsig:0 c: 0.9447 lenerr:0
diff --git a/tests/ref/fate/auravision-v1 b/tests/ref/fate/auravision-v1
index 456f399..25a15ce 100644
--- a/tests/ref/fate/auravision-v1
+++ b/tests/ref/fate/auravision-v1
@@ -1,4 +1,8 @@
 #tb 0: 33339/500000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    28800, 0x4a4efbbc
 0,          1,          1,        1,    28800, 0xc6c7e26a
 0,          2,          2,        1,    28800, 0x6cd40913
diff --git a/tests/ref/fate/auravision-v2 b/tests/ref/fate/auravision-v2
index f1e8e3a..498944a 100644
--- a/tests/ref/fate/auravision-v2
+++ b/tests/ref/fate/auravision-v2
@@ -1,3 +1,7 @@
 #tb 0: 33333/1000000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x180
+#sar 0: 0/1
 0,          0,          0,        1,   115200, 0x2f247f66
 0,          1,          1,        1,   115200, 0xf492929e
diff --git a/tests/ref/fate/avio-direct b/tests/ref/fate/avio-direct
index 599683a..c0628e9 100644
--- a/tests/ref/fate/avio-direct
+++ b/tests/ref/fate/avio-direct
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 288x168
+#sar 0: 0/1
 0,          0,          0,        1,   145152, 0x8458d4cb
 0,          1,          1,        1,   145152, 0xa694d7c7
 0,          2,          2,        1,   145152, 0x2bd4bfc9
diff --git a/tests/ref/fate/bethsoft-vid b/tests/ref/fate/bethsoft-vid
index 9f96da1..ccb0d37 100644
--- a/tests/ref/fate/bethsoft-vid
+++ b/tests/ref/fate/bethsoft-vid
@@ -1,5 +1,13 @@
 #tb 0: 1/14
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 #tb 1: 1/11111
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 11111
+#channel_layout 1: 4
 0,          0,          0,        1,   192000, 0x00000000
 1,          0,          0,      740,     1480, 0x00000000
 1,        740,        740,      740,     1480, 0x20a92bd4
diff --git a/tests/ref/fate/bfi b/tests/ref/fate/bfi
index 0d3d8f2..807615c 100644
--- a/tests/ref/fate/bfi
+++ b/tests/ref/fate/bfi
@@ -1,5 +1,13 @@
 #tb 0: 1/9
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x140
+#sar 0: 0/1
 #tb 1: 1/11025
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 11025
+#channel_layout 1: 4
 0,          0,          0,        1,   134400, 0xc218b00c
 1,          0,          0,     8884,    17768, 0x07df135c
 0,          1,          1,        1,   134400, 0x114daf7c
diff --git a/tests/ref/fate/bink-video-b b/tests/ref/fate/bink-video-b
index c772eda..663457a 100644
--- a/tests/ref/fate/bink-video-b
+++ b/tests/ref/fate/bink-video-b
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x116
+#sar 0: 0/1
 0,          0,          0,        1,    34800, 0x4fd0a8e4
 0,          1,          1,        1,    34800, 0xd381a7b7
 0,          2,          2,        1,    34800, 0x688ca315
diff --git a/tests/ref/fate/bink-video-f b/tests/ref/fate/bink-video-f
index 40bc5a9..912ceed 100644
--- a/tests/ref/fate/bink-video-f
+++ b/tests/ref/fate/bink-video-f
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   460800, 0xb06f7841
 0,          1,          1,        1,   460800, 0x7ed06412
 0,          2,          2,        1,   460800, 0xe82b5c3d
diff --git a/tests/ref/fate/bink-video-i b/tests/ref/fate/bink-video-i
index 32c5e10..0d67e98 100644
--- a/tests/ref/fate/bink-video-i
+++ b/tests/ref/fate/bink-video-i
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   460800, 0xaef133d9
 0,          1,          1,        1,   460800, 0x2da1248b
 0,          2,          2,        1,   460800, 0x3d7945b4
diff --git a/tests/ref/fate/bmp-15bit b/tests/ref/fate/bmp-15bit
index a0f3bbf..29b6335 100644
--- a/tests/ref/fate/bmp-15bit
+++ b/tests/ref/fate/bmp-15bit
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    16256, 0xdbcf881d
diff --git a/tests/ref/fate/bmp-15bit-mask b/tests/ref/fate/bmp-15bit-mask
index a0f3bbf..29b6335 100644
--- a/tests/ref/fate/bmp-15bit-mask
+++ b/tests/ref/fate/bmp-15bit-mask
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    16256, 0xdbcf881d
diff --git a/tests/ref/fate/bmp-16bit-mask b/tests/ref/fate/bmp-16bit-mask
index afa5ab4..8760ff8 100644
--- a/tests/ref/fate/bmp-16bit-mask
+++ b/tests/ref/fate/bmp-16bit-mask
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    16256, 0x44675948
diff --git a/tests/ref/fate/bmp-1bit b/tests/ref/fate/bmp-1bit
index 1c825b1..a40328f 100644
--- a/tests/ref/fate/bmp-1bit
+++ b/tests/ref/fate/bmp-1bit
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    24384, 0x4c968301
diff --git a/tests/ref/fate/bmp-24bit b/tests/ref/fate/bmp-24bit
index 8f1a615..6394d2f 100644
--- a/tests/ref/fate/bmp-24bit
+++ b/tests/ref/fate/bmp-24bit
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    24384, 0x325dd8d9
diff --git a/tests/ref/fate/bmp-32bit b/tests/ref/fate/bmp-32bit
index 8f1a615..6394d2f 100644
--- a/tests/ref/fate/bmp-32bit
+++ b/tests/ref/fate/bmp-32bit
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    24384, 0x325dd8d9
diff --git a/tests/ref/fate/bmp-32bit-mask b/tests/ref/fate/bmp-32bit-mask
index 8f1a615..6394d2f 100644
--- a/tests/ref/fate/bmp-32bit-mask
+++ b/tests/ref/fate/bmp-32bit-mask
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    24384, 0x325dd8d9
diff --git a/tests/ref/fate/bmp-4bit b/tests/ref/fate/bmp-4bit
index c0eedf1..b4262c9 100644
--- a/tests/ref/fate/bmp-4bit
+++ b/tests/ref/fate/bmp-4bit
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    24384, 0x322d81f4
diff --git a/tests/ref/fate/bmp-4bit-os2 b/tests/ref/fate/bmp-4bit-os2
index 8a5f658..9cf9cf0 100644
--- a/tests/ref/fate/bmp-4bit-os2
+++ b/tests/ref/fate/bmp-4bit-os2
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 300x22
+#sar 0: 0/1
 0,          0,          0,        1,    19800, 0x563b599a
diff --git a/tests/ref/fate/bmp-8bit b/tests/ref/fate/bmp-8bit
index 887113c..3ecea53 100644
--- a/tests/ref/fate/bmp-8bit
+++ b/tests/ref/fate/bmp-8bit
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    24384, 0xa7aa6b9b
diff --git a/tests/ref/fate/bmp-8bit-os2 b/tests/ref/fate/bmp-8bit-os2
index 887113c..3ecea53 100644
--- a/tests/ref/fate/bmp-8bit-os2
+++ b/tests/ref/fate/bmp-8bit-os2
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    24384, 0xa7aa6b9b
diff --git a/tests/ref/fate/bmp-rle4 b/tests/ref/fate/bmp-rle4
index c0eedf1..b4262c9 100644
--- a/tests/ref/fate/bmp-rle4
+++ b/tests/ref/fate/bmp-rle4
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    24384, 0x322d81f4
diff --git a/tests/ref/fate/bmp-rle8 b/tests/ref/fate/bmp-rle8
index 887113c..3ecea53 100644
--- a/tests/ref/fate/bmp-rle8
+++ b/tests/ref/fate/bmp-rle8
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 127x64
+#sar 0: 0/1
 0,          0,          0,        1,    24384, 0xa7aa6b9b
diff --git a/tests/ref/fate/bmpparser b/tests/ref/fate/bmpparser
index 3cdd986..9340743 100644
--- a/tests/ref/fate/bmpparser
+++ b/tests/ref/fate/bmpparser
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 40x30
+#sar 0: 0/1
 0,          0,          0,        1,     3600, 0xd3a7c583
 0,          1,          1,        1,     3600, 0x4602bbf9
 0,          2,          2,        1,     3600, 0x3a96b8f8
diff --git a/tests/ref/fate/bmv-audio b/tests/ref/fate/bmv-audio
index 746bb0c..62f9c5e 100644
--- a/tests/ref/fate/bmv-audio
+++ b/tests/ref/fate/bmv-audio
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,     1856,     7424, 0x18540b36
 0,       1856,       1856,     1824,     7296, 0x5acd2484
 0,       3680,       3680,     1856,     7424, 0xa1bc5c5a
diff --git a/tests/ref/fate/bmv-video b/tests/ref/fate/bmv-video
index f19cd45..d360d58 100644
--- a/tests/ref/fate/bmv-video
+++ b/tests/ref/fate/bmv-video
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x429
+#sar 0: 0/1
 0,          0,          0,        1,   823680, 0xddb8a306
 0,          1,          1,        1,   823680, 0xa95375c8
 0,          2,          2,        1,   823680, 0xa95375c8
diff --git a/tests/ref/fate/brenderpix-24 b/tests/ref/fate/brenderpix-24
index 32b29a0..be81fc2 100644
--- a/tests/ref/fate/brenderpix-24
+++ b/tests/ref/fate/brenderpix-24
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    32768, 0x18bc6caa
diff --git a/tests/ref/fate/brenderpix-565 b/tests/ref/fate/brenderpix-565
index c243a4c..bc92766 100644
--- a/tests/ref/fate/brenderpix-565
+++ b/tests/ref/fate/brenderpix-565
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    32768, 0xfd855dda
diff --git a/tests/ref/fate/brenderpix-defpal b/tests/ref/fate/brenderpix-defpal
index 6c55740..c5632ae 100644
--- a/tests/ref/fate/brenderpix-defpal
+++ b/tests/ref/fate/brenderpix-defpal
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 0/1
 0,          0,          0,        1,   196608, 0xada11d14
diff --git a/tests/ref/fate/brenderpix-intpal b/tests/ref/fate/brenderpix-intpal
index 473b153..789c87d 100644
--- a/tests/ref/fate/brenderpix-intpal
+++ b/tests/ref/fate/brenderpix-intpal
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 0/1
 0,          0,          0,        1,   196608, 0x9662f917
diff --git a/tests/ref/fate/brenderpix-y400a b/tests/ref/fate/brenderpix-y400a
index 00e1540..1f7c8db 100644
--- a/tests/ref/fate/brenderpix-y400a
+++ b/tests/ref/fate/brenderpix-y400a
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x96
+#sar 0: 0/1
 0,          0,          0,        1,     3072, 0x48280456
diff --git a/tests/ref/fate/canopus-cllc-argb b/tests/ref/fate/canopus-cllc-argb
index 4a5dce5..bab7ed7 100644
--- a/tests/ref/fate/canopus-cllc-argb
+++ b/tests/ref/fate/canopus-cllc-argb
@@ -1,4 +1,8 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 1/1
 0,          0,          0,        1,  3686400, 0xb37a6e69
 0,          1,          1,        1,  3686400, 0x66a45032
 0,          2,          2,        1,  3686400, 0xdf0c861f
diff --git a/tests/ref/fate/canopus-cllc-rgb b/tests/ref/fate/canopus-cllc-rgb
index b4ca055..e9f54d1 100644
--- a/tests/ref/fate/canopus-cllc-rgb
+++ b/tests/ref/fate/canopus-cllc-rgb
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 1/1
 0,          0,          0,        1,   921600, 0x82e44cb9
 0,          1,          1,        1,   921600, 0x6ecc8a6c
 0,          2,          2,        1,   921600, 0x0dc31839
diff --git a/tests/ref/fate/canopus-cllc-yuy2-noblock b/tests/ref/fate/canopus-cllc-yuy2-noblock
index 6ad59d5..6242a82 100644
--- a/tests/ref/fate/canopus-cllc-yuy2-noblock
+++ b/tests/ref/fate/canopus-cllc-yuy2-noblock
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 1/1
 0,          0,          0,        1,   614400, 0x088c51de
 0,          1,          1,        1,   614400, 0x93fff662
 0,          2,          2,        1,   614400, 0x90ba6c28
diff --git a/tests/ref/fate/canopus-hq_hqa-hq b/tests/ref/fate/canopus-hq_hqa-hq
index ca376dc..657e1e1 100644
--- a/tests/ref/fate/canopus-hq_hqa-hq
+++ b/tests/ref/fate/canopus-hq_hqa-hq
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 64/45
 0,          0,          0,        1,   829440, 0x8b6b2f6d
 0,          1,          1,        1,   829440, 0x70382bf0
 0,          2,          2,        1,   829440, 0xbfdf1f8d
diff --git a/tests/ref/fate/canopus-hq_hqa-hqa b/tests/ref/fate/canopus-hq_hqa-hqa
index 0996500..1fd5bf7 100644
--- a/tests/ref/fate/canopus-hq_hqa-hqa
+++ b/tests/ref/fate/canopus-hq_hqa-hqa
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 0,          0,          0,        1,  6220800, 0x2b2b17cc
diff --git a/tests/ref/fate/canopus-hq_hqa-inter b/tests/ref/fate/canopus-hq_hqa-inter
index 2880c95..e4bbb5e 100644
--- a/tests/ref/fate/canopus-hq_hqa-inter
+++ b/tests/ref/fate/canopus-hq_hqa-inter
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 0,          0,          0,        1,  4147200, 0x418ecfe5
diff --git a/tests/ref/fate/canopus-hqx422 b/tests/ref/fate/canopus-hqx422
index 2e1fdf1..5501abd 100644
--- a/tests/ref/fate/canopus-hqx422
+++ b/tests/ref/fate/canopus-hqx422
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 64/45
 0,          0,          0,        1,  1658880, 0x823fcbac
diff --git a/tests/ref/fate/canopus-hqx422a b/tests/ref/fate/canopus-hqx422a
index 0fd2577..e22af12 100644
--- a/tests/ref/fate/canopus-hqx422a
+++ b/tests/ref/fate/canopus-hqx422a
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 0,          0,          0,        1,  8294400, 0x9a22bebf
diff --git a/tests/ref/fate/cavs b/tests/ref/fate/cavs
index 87cf9ca..31b9d29 100644
--- a/tests/ref/fate/cavs
+++ b/tests/ref/fate/cavs
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 0/1
 0,          0,          0,        1,   622080, 0x2276bc78
 0,          1,          1,        1,   622080, 0xda1f698a
 0,          2,          2,        1,   622080, 0xb9907023
diff --git a/tests/ref/fate/cdgraphics b/tests/ref/fate/cdgraphics
index ee02f5d..f079bd4 100644
--- a/tests/ref/fate/cdgraphics
+++ b/tests/ref/fate/cdgraphics
@@ -1,4 +1,8 @@
 #tb 0: 1/300
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 300x216
+#sar 0: 0/1
 0,          0,          0,        1,   259200, 0x29aeb27e
 0,          1,          1,        1,   259200, 0x29aeb27e
 0,          2,          2,        1,   259200, 0x6779f55d
diff --git a/tests/ref/fate/cdxl-bitline-ham6 b/tests/ref/fate/cdxl-bitline-ham6
index 9ba7404..37c1459 100644
--- a/tests/ref/fate/cdxl-bitline-ham6
+++ b/tests/ref/fate/cdxl-bitline-ham6
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 162x130
+#sar 0: 0/1
 0,          0,          0,        1,    63180, 0xcda82c16
 0,          1,          1,        1,    63180, 0xa6097bf9
 0,          2,          2,        1,    63180, 0x4c2fb091
diff --git a/tests/ref/fate/cdxl-demux b/tests/ref/fate/cdxl-demux
index 7e4c4c8..828b2c9 100644
--- a/tests/ref/fate/cdxl-demux
+++ b/tests/ref/fate/cdxl-demux
@@ -1,5 +1,13 @@
 #tb 0: 1/11025
+#media_type 0: video
+#codec_id 0: cdxl
+#dimensions 0: 176x128
+#sar 0: 0/1
 #tb 1: 1/11025
+#media_type 1: audio
+#codec_id 1: pcm_s8
+#sample_rate 1: 11025
+#channel_layout 1: 4
 0,          0,          0,     1884,    22688, 0xc954a244
 1,          0,          0,     1884,     1884, 0x06925e3e
 0,       1884,       1884,     1884,    22688, 0x3ee4a304
diff --git a/tests/ref/fate/cdxl-ham6 b/tests/ref/fate/cdxl-ham6
index 6426d45..1602c8a 100644
--- a/tests/ref/fate/cdxl-ham6
+++ b/tests/ref/fate/cdxl-ham6
@@ -1,4 +1,8 @@
 #tb 0: 52/525
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    57600, 0x87887a7b
 0,          1,          1,        1,    57600, 0x10c301d2
 0,          2,          2,        1,    57600, 0xd1a6f910
diff --git a/tests/ref/fate/cdxl-ham8 b/tests/ref/fate/cdxl-ham8
index 1eebea3..ab1f76a 100644
--- a/tests/ref/fate/cdxl-ham8
+++ b/tests/ref/fate/cdxl-ham8
@@ -1,2 +1,6 @@
 #tb 0: 12/281
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x128
+#sar 0: 0/1
 0,          0,          0,        1,    67584, 0xce0cade5
diff --git a/tests/ref/fate/cdxl-pal8 b/tests/ref/fate/cdxl-pal8
index b2fb045..a242b0c 100644
--- a/tests/ref/fate/cdxl-pal8
+++ b/tests/ref/fate/cdxl-pal8
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x128
+#sar 0: 0/1
 0,          0,          0,        1,    67584, 0x5eae629b
 0,          1,          1,        1,    67584, 0x32591227
 0,          2,          2,        1,    67584, 0x4e4424c7
diff --git a/tests/ref/fate/cdxl-pal8-small b/tests/ref/fate/cdxl-pal8-small
index f7a1a46..326eef7 100644
--- a/tests/ref/fate/cdxl-pal8-small
+++ b/tests/ref/fate/cdxl-pal8-small
@@ -1,4 +1,8 @@
 #tb 0: 368/11025
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x80
+#sar 0: 0/1
 0,          0,          0,        1,    30720, 0x0d552cfd
 0,          1,          1,        1,    30720, 0x3cf93291
 0,          2,          2,        1,    30720, 0xe45b2868
diff --git a/tests/ref/fate/cljr b/tests/ref/fate/cljr
index 5842541..ad4388d 100644
--- a/tests/ref/fate/cljr
+++ b/tests/ref/fate/cljr
@@ -1,4 +1,8 @@
 #tb 0: 3521/100000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 240x180
+#sar 0: 0/1
 0,          0,          0,        1,    64800, 0x63132a60
 0,          1,          1,        1,    64800, 0xb3c729a3
 0,          2,          2,        1,    64800, 0xa27b1e0e
diff --git a/tests/ref/fate/color_utils b/tests/ref/fate/color_utils
new file mode 100644
index 0000000..10f8055
--- /dev/null
+++ b/tests/ref/fate/color_utils
@@ -0,0 +1,304 @@
+AVColorTransferCharacteristic=1 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=1 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=1 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=1 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=1 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=1 calling func(0.003162) expected=0.014230
+AVColorTransferCharacteristic=1 calling func(0.005000) expected=0.022500
+AVColorTransferCharacteristic=1 calling func(0.009000) expected=0.040500
+AVColorTransferCharacteristic=1 calling func(0.015000) expected=0.067500
+AVColorTransferCharacteristic=1 calling func(0.100000) expected=0.290748
+AVColorTransferCharacteristic=1 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=1 calling func(52.370000) expected=6.427531
+AVColorTransferCharacteristic=1 calling func(125.098765) expected=9.558517
+AVColorTransferCharacteristic=1 calling func(1999.111230) expected=33.512490
+AVColorTransferCharacteristic=1 calling func(6945.443000) expected=58.768794
+AVColorTransferCharacteristic=1 calling func(15123.456700) expected=83.452916
+AVColorTransferCharacteristic=1 calling func(19845.889230) expected=94.321297
+AVColorTransferCharacteristic=1 calling func(98678.423100) expected=194.219568
+AVColorTransferCharacteristic=1 calling func(99999.899998) expected=195.386306
+AVColorTransferCharacteristic=4 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=4 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=4 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=4 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=4 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=4 calling func(0.003162) expected=0.073053
+AVColorTransferCharacteristic=4 calling func(0.005000) expected=0.089966
+AVColorTransferCharacteristic=4 calling func(0.009000) expected=0.117520
+AVColorTransferCharacteristic=4 calling func(0.015000) expected=0.148235
+AVColorTransferCharacteristic=4 calling func(0.100000) expected=0.351119
+AVColorTransferCharacteristic=4 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=4 calling func(52.370000) expected=6.045068
+AVColorTransferCharacteristic=4 calling func(125.098765) expected=8.980424
+AVColorTransferCharacteristic=4 calling func(1999.111230) expected=31.650490
+AVColorTransferCharacteristic=4 calling func(6945.443000) expected=55.747738
+AVColorTransferCharacteristic=4 calling func(15123.456700) expected=79.403820
+AVColorTransferCharacteristic=4 calling func(19845.889230) expected=89.843491
+AVColorTransferCharacteristic=4 calling func(98678.423100) expected=186.252024
+AVColorTransferCharacteristic=4 calling func(99999.899998) expected=187.381657
+AVColorTransferCharacteristic=5 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=5 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=5 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=5 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=5 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=5 calling func(0.003162) expected=0.127980
+AVColorTransferCharacteristic=5 calling func(0.005000) expected=0.150731
+AVColorTransferCharacteristic=5 calling func(0.009000) expected=0.185940
+AVColorTransferCharacteristic=5 calling func(0.015000) expected=0.223154
+AVColorTransferCharacteristic=5 calling func(0.100000) expected=0.439397
+AVColorTransferCharacteristic=5 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=5 calling func(52.370000) expected=4.111100
+AVColorTransferCharacteristic=5 calling func(125.098765) expected=5.610724
+AVColorTransferCharacteristic=5 calling func(1999.111230) expected=15.096294
+AVColorTransferCharacteristic=5 calling func(6945.443000) expected=23.552429
+AVColorTransferCharacteristic=5 calling func(15123.456700) expected=31.098005
+AVColorTransferCharacteristic=5 calling func(19845.889230) expected=34.267494
+AVColorTransferCharacteristic=5 calling func(98678.423100) expected=60.764620
+AVColorTransferCharacteristic=5 calling func(99999.899998) expected=61.054001
+AVColorTransferCharacteristic=6 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=6 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=6 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=6 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=6 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=6 calling func(0.003162) expected=0.014230
+AVColorTransferCharacteristic=6 calling func(0.005000) expected=0.022500
+AVColorTransferCharacteristic=6 calling func(0.009000) expected=0.040500
+AVColorTransferCharacteristic=6 calling func(0.015000) expected=0.067500
+AVColorTransferCharacteristic=6 calling func(0.100000) expected=0.290748
+AVColorTransferCharacteristic=6 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=6 calling func(52.370000) expected=6.427531
+AVColorTransferCharacteristic=6 calling func(125.098765) expected=9.558517
+AVColorTransferCharacteristic=6 calling func(1999.111230) expected=33.512490
+AVColorTransferCharacteristic=6 calling func(6945.443000) expected=58.768794
+AVColorTransferCharacteristic=6 calling func(15123.456700) expected=83.452916
+AVColorTransferCharacteristic=6 calling func(19845.889230) expected=94.321297
+AVColorTransferCharacteristic=6 calling func(98678.423100) expected=194.219568
+AVColorTransferCharacteristic=6 calling func(99999.899998) expected=195.386306
+AVColorTransferCharacteristic=7 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=7 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=7 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=7 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=7 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=7 calling func(0.003162) expected=0.012649
+AVColorTransferCharacteristic=7 calling func(0.005000) expected=0.020000
+AVColorTransferCharacteristic=7 calling func(0.009000) expected=0.036000
+AVColorTransferCharacteristic=7 calling func(0.015000) expected=0.060000
+AVColorTransferCharacteristic=7 calling func(0.100000) expected=0.282875
+AVColorTransferCharacteristic=7 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=7 calling func(52.370000) expected=6.487781
+AVColorTransferCharacteristic=7 calling func(125.098765) expected=9.653524
+AVColorTransferCharacteristic=7 calling func(1999.111230) expected=33.873408
+AVColorTransferCharacteristic=7 calling func(6945.443000) expected=59.410079
+AVColorTransferCharacteristic=7 calling func(15123.456700) expected=84.368216
+AVColorTransferCharacteristic=7 calling func(19845.889230) expected=95.357247
+AVColorTransferCharacteristic=7 calling func(98678.423100) expected=196.364477
+AVColorTransferCharacteristic=7 calling func(99999.899998) expected=197.544167
+AVColorTransferCharacteristic=8 calling func(-0.100000) expected=-0.100000
+AVColorTransferCharacteristic=8 calling func(-0.018054) expected=-0.018054
+AVColorTransferCharacteristic=8 calling func(-0.010000) expected=-0.010000
+AVColorTransferCharacteristic=8 calling func(-0.004490) expected=-0.004490
+AVColorTransferCharacteristic=8 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=8 calling func(0.003162) expected=0.003162
+AVColorTransferCharacteristic=8 calling func(0.005000) expected=0.005000
+AVColorTransferCharacteristic=8 calling func(0.009000) expected=0.009000
+AVColorTransferCharacteristic=8 calling func(0.015000) expected=0.015000
+AVColorTransferCharacteristic=8 calling func(0.100000) expected=0.100000
+AVColorTransferCharacteristic=8 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=8 calling func(52.370000) expected=52.370000
+AVColorTransferCharacteristic=8 calling func(125.098765) expected=125.098765
+AVColorTransferCharacteristic=8 calling func(1999.111230) expected=1999.111230
+AVColorTransferCharacteristic=8 calling func(6945.443000) expected=6945.443000
+AVColorTransferCharacteristic=8 calling func(15123.456700) expected=15123.456700
+AVColorTransferCharacteristic=8 calling func(19845.889230) expected=19845.889230
+AVColorTransferCharacteristic=8 calling func(98678.423100) expected=98678.423100
+AVColorTransferCharacteristic=8 calling func(99999.899998) expected=99999.899998
+AVColorTransferCharacteristic=9 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=9 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=9 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=9 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=9 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=9 calling func(0.003162) expected=0.000000
+AVColorTransferCharacteristic=9 calling func(0.005000) expected=0.000000
+AVColorTransferCharacteristic=9 calling func(0.009000) expected=0.000000
+AVColorTransferCharacteristic=9 calling func(0.015000) expected=0.088046
+AVColorTransferCharacteristic=9 calling func(0.100000) expected=0.500000
+AVColorTransferCharacteristic=9 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=9 calling func(52.370000) expected=1.859541
+AVColorTransferCharacteristic=9 calling func(125.098765) expected=2.048627
+AVColorTransferCharacteristic=9 calling func(1999.111230) expected=2.650418
+AVColorTransferCharacteristic=9 calling func(6945.443000) expected=2.920850
+AVColorTransferCharacteristic=9 calling func(15123.456700) expected=3.089826
+AVColorTransferCharacteristic=9 calling func(19845.889230) expected=3.148835
+AVColorTransferCharacteristic=9 calling func(98678.423100) expected=3.497111
+AVColorTransferCharacteristic=9 calling func(99999.899998) expected=3.500000
+AVColorTransferCharacteristic=10 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=10 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=10 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=10 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=10 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=10 calling func(0.003162) expected=0.000000
+AVColorTransferCharacteristic=10 calling func(0.005000) expected=0.079588
+AVColorTransferCharacteristic=10 calling func(0.009000) expected=0.181697
+AVColorTransferCharacteristic=10 calling func(0.015000) expected=0.270437
+AVColorTransferCharacteristic=10 calling func(0.100000) expected=0.600000
+AVColorTransferCharacteristic=10 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=10 calling func(52.370000) expected=1.687633
+AVColorTransferCharacteristic=10 calling func(125.098765) expected=1.838901
+AVColorTransferCharacteristic=10 calling func(1999.111230) expected=2.320335
+AVColorTransferCharacteristic=10 calling func(6945.443000) expected=2.536680
+AVColorTransferCharacteristic=10 calling func(15123.456700) expected=2.671860
+AVColorTransferCharacteristic=10 calling func(19845.889230) expected=2.719068
+AVColorTransferCharacteristic=10 calling func(98678.423100) expected=2.997689
+AVColorTransferCharacteristic=10 calling func(99999.899998) expected=3.000000
+AVColorTransferCharacteristic=11 calling func(-0.100000) expected=-0.290748
+AVColorTransferCharacteristic=11 calling func(-0.018054) expected=-0.081243
+AVColorTransferCharacteristic=11 calling func(-0.010000) expected=-0.045000
+AVColorTransferCharacteristic=11 calling func(-0.004490) expected=-0.020205
+AVColorTransferCharacteristic=11 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=11 calling func(0.003162) expected=0.014230
+AVColorTransferCharacteristic=11 calling func(0.005000) expected=0.022500
+AVColorTransferCharacteristic=11 calling func(0.009000) expected=0.040500
+AVColorTransferCharacteristic=11 calling func(0.015000) expected=0.067500
+AVColorTransferCharacteristic=11 calling func(0.100000) expected=0.290748
+AVColorTransferCharacteristic=11 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=11 calling func(52.370000) expected=6.427531
+AVColorTransferCharacteristic=11 calling func(125.098765) expected=9.558517
+AVColorTransferCharacteristic=11 calling func(1999.111230) expected=33.512490
+AVColorTransferCharacteristic=11 calling func(6945.443000) expected=58.768794
+AVColorTransferCharacteristic=11 calling func(15123.456700) expected=83.452916
+AVColorTransferCharacteristic=11 calling func(19845.889230) expected=94.321297
+AVColorTransferCharacteristic=11 calling func(98678.423100) expected=194.219568
+AVColorTransferCharacteristic=11 calling func(99999.899998) expected=195.386306
+AVColorTransferCharacteristic=12 calling func(-0.100000) expected=-0.206787
+AVColorTransferCharacteristic=12 calling func(-0.018054) expected=-0.109049
+AVColorTransferCharacteristic=12 calling func(-0.010000) expected=-0.089387
+AVColorTransferCharacteristic=12 calling func(-0.004490) expected=-0.020205
+AVColorTransferCharacteristic=12 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=12 calling func(0.003162) expected=0.014230
+AVColorTransferCharacteristic=12 calling func(0.005000) expected=0.022500
+AVColorTransferCharacteristic=12 calling func(0.009000) expected=0.040500
+AVColorTransferCharacteristic=12 calling func(0.015000) expected=0.067500
+AVColorTransferCharacteristic=12 calling func(0.100000) expected=0.290748
+AVColorTransferCharacteristic=12 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=12 calling func(52.370000) expected=6.427531
+AVColorTransferCharacteristic=12 calling func(125.098765) expected=9.558517
+AVColorTransferCharacteristic=12 calling func(1999.111230) expected=33.512490
+AVColorTransferCharacteristic=12 calling func(6945.443000) expected=58.768794
+AVColorTransferCharacteristic=12 calling func(15123.456700) expected=83.452916
+AVColorTransferCharacteristic=12 calling func(19845.889230) expected=94.321297
+AVColorTransferCharacteristic=12 calling func(98678.423100) expected=194.219568
+AVColorTransferCharacteristic=12 calling func(99999.899998) expected=195.386306
+AVColorTransferCharacteristic=13 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=13 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=13 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=13 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=13 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=13 calling func(0.003162) expected=0.040849
+AVColorTransferCharacteristic=13 calling func(0.005000) expected=0.061009
+AVColorTransferCharacteristic=13 calling func(0.009000) expected=0.093202
+AVColorTransferCharacteristic=13 calling func(0.015000) expected=0.128354
+AVColorTransferCharacteristic=13 calling func(0.100000) expected=0.349190
+AVColorTransferCharacteristic=13 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=13 calling func(52.370000) expected=5.434552
+AVColorTransferCharacteristic=13 calling func(125.098765) expected=7.835561
+AVColorTransferCharacteristic=13 calling func(1999.111230) expected=24.983090
+AVColorTransferCharacteristic=13 calling func(6945.443000) expected=42.013863
+AVColorTransferCharacteristic=13 calling func(15123.456700) expected=58.125003
+AVColorTransferCharacteristic=13 calling func(19845.889230) expected=65.100117
+AVColorTransferCharacteristic=13 calling func(98678.423100) expected=127.054607
+AVColorTransferCharacteristic=13 calling func(99999.899998) expected=127.761115
+AVColorTransferCharacteristic=14 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=14 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=14 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=14 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=14 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=14 calling func(0.003162) expected=0.014230
+AVColorTransferCharacteristic=14 calling func(0.005000) expected=0.022500
+AVColorTransferCharacteristic=14 calling func(0.009000) expected=0.040500
+AVColorTransferCharacteristic=14 calling func(0.015000) expected=0.067500
+AVColorTransferCharacteristic=14 calling func(0.100000) expected=0.290748
+AVColorTransferCharacteristic=14 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=14 calling func(52.370000) expected=6.427531
+AVColorTransferCharacteristic=14 calling func(125.098765) expected=9.558517
+AVColorTransferCharacteristic=14 calling func(1999.111230) expected=33.512490
+AVColorTransferCharacteristic=14 calling func(6945.443000) expected=58.768794
+AVColorTransferCharacteristic=14 calling func(15123.456700) expected=83.452916
+AVColorTransferCharacteristic=14 calling func(19845.889230) expected=94.321297
+AVColorTransferCharacteristic=14 calling func(98678.423100) expected=194.219568
+AVColorTransferCharacteristic=14 calling func(99999.899998) expected=195.386306
+AVColorTransferCharacteristic=15 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=15 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=15 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=15 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=15 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=15 calling func(0.003162) expected=0.014230
+AVColorTransferCharacteristic=15 calling func(0.005000) expected=0.022500
+AVColorTransferCharacteristic=15 calling func(0.009000) expected=0.040500
+AVColorTransferCharacteristic=15 calling func(0.015000) expected=0.067500
+AVColorTransferCharacteristic=15 calling func(0.100000) expected=0.290748
+AVColorTransferCharacteristic=15 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=15 calling func(52.370000) expected=6.427531
+AVColorTransferCharacteristic=15 calling func(125.098765) expected=9.558517
+AVColorTransferCharacteristic=15 calling func(1999.111230) expected=33.512490
+AVColorTransferCharacteristic=15 calling func(6945.443000) expected=58.768794
+AVColorTransferCharacteristic=15 calling func(15123.456700) expected=83.452916
+AVColorTransferCharacteristic=15 calling func(19845.889230) expected=94.321297
+AVColorTransferCharacteristic=15 calling func(98678.423100) expected=194.219568
+AVColorTransferCharacteristic=15 calling func(99999.899998) expected=195.386306
+AVColorTransferCharacteristic=16 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=16 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=16 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=16 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=16 calling func(0.000000) expected=0.000001
+AVColorTransferCharacteristic=16 calling func(0.003162) expected=0.011839
+AVColorTransferCharacteristic=16 calling func(0.005000) expected=0.015076
+AVColorTransferCharacteristic=16 calling func(0.009000) expected=0.020379
+AVColorTransferCharacteristic=16 calling func(0.015000) expected=0.026255
+AVColorTransferCharacteristic=16 calling func(0.100000) expected=0.062337
+AVColorTransferCharacteristic=16 calling func(1.000000) expected=0.149946
+AVColorTransferCharacteristic=16 calling func(52.370000) expected=0.444693
+AVColorTransferCharacteristic=16 calling func(125.098765) expected=0.530719
+AVColorTransferCharacteristic=16 calling func(1999.111230) expected=0.827376
+AVColorTransferCharacteristic=16 calling func(6945.443000) expected=0.961586
+AVColorTransferCharacteristic=16 calling func(15123.456700) expected=1.042921
+AVColorTransferCharacteristic=16 calling func(19845.889230) expected=1.070677
+AVColorTransferCharacteristic=16 calling func(98678.423100) expected=1.225908
+AVColorTransferCharacteristic=16 calling func(99999.899998) expected=1.227127
+AVColorTransferCharacteristic=17 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=17 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=17 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=17 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=17 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=17 calling func(0.003162) expected=0.105659
+AVColorTransferCharacteristic=17 calling func(0.005000) expected=0.126018
+AVColorTransferCharacteristic=17 calling func(0.009000) expected=0.157985
+AVColorTransferCharacteristic=17 calling func(0.015000) expected=0.192284
+AVColorTransferCharacteristic=17 calling func(0.100000) expected=0.398869
+AVColorTransferCharacteristic=17 calling func(1.000000) expected=0.967043
+AVColorTransferCharacteristic=17 calling func(52.370000) expected=4.432321
+AVColorTransferCharacteristic=17 calling func(125.098765) expected=6.195572
+AVColorTransferCharacteristic=17 calling func(1999.111230) expected=17.988639
+AVColorTransferCharacteristic=17 calling func(6945.443000) expected=29.041734
+AVColorTransferCharacteristic=17 calling func(15123.456700) expected=39.174525
+AVColorTransferCharacteristic=17 calling func(19845.889230) expected=43.490646
+AVColorTransferCharacteristic=17 calling func(98678.423100) expected=80.593559
+AVColorTransferCharacteristic=17 calling func(99999.899998) expected=81.006971
+AVColorTransferCharacteristic=18 calling func(-0.100000) expected=0.000000
+AVColorTransferCharacteristic=18 calling func(-0.018054) expected=0.000000
+AVColorTransferCharacteristic=18 calling func(-0.010000) expected=0.000000
+AVColorTransferCharacteristic=18 calling func(-0.004490) expected=0.000000
+AVColorTransferCharacteristic=18 calling func(0.000000) expected=0.000000
+AVColorTransferCharacteristic=18 calling func(0.003162) expected=0.097400
+AVColorTransferCharacteristic=18 calling func(0.005000) expected=0.122474
+AVColorTransferCharacteristic=18 calling func(0.009000) expected=0.164317
+AVColorTransferCharacteristic=18 calling func(0.015000) expected=0.212132
+AVColorTransferCharacteristic=18 calling func(0.100000) expected=0.544089
+AVColorTransferCharacteristic=18 calling func(1.000000) expected=1.000000
+AVColorTransferCharacteristic=18 calling func(52.370000) expected=1.712092
+AVColorTransferCharacteristic=18 calling func(125.098765) expected=1.867862
+AVColorTransferCharacteristic=18 calling func(1999.111230) expected=2.363502
+AVColorTransferCharacteristic=18 calling func(6945.443000) expected=2.586219
+AVColorTransferCharacteristic=18 calling func(15123.456700) expected=2.725380
+AVColorTransferCharacteristic=18 calling func(19845.889230) expected=2.773978
+AVColorTransferCharacteristic=18 calling func(98678.423100) expected=3.060803
+AVColorTransferCharacteristic=18 calling func(99999.899998) expected=3.063182
diff --git a/tests/ref/fate/concat-demuxer-extended-lavf-mxf b/tests/ref/fate/concat-demuxer-extended-lavf-mxf
index 4caec5a..b894938 100644
--- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf
+++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf
@@ -1 +1 @@
-37b4a84fce71b3f8b129f8b866c5f55a *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe
+0aa1ca6ff6e2e5aa926454d22fdaecd5 *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe
diff --git a/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 b/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10
index 1965050..b378a2d 100644
--- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10
+++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10
@@ -1 +1 @@
-2f5e935f86304c843be1454b1354a4b7 *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe
+14c2b8d8f82f261c9627b33c481c0e8c *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe
diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf
index c28db28..3fc7957 100644
--- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf
+++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf
@@ -120,5 +120,5 @@ audio|1|65280|1.360000|65280|1.360000|1920|0.040000|N/A|N/A|3840|206848|K|1
 Strings Metadata|8
 video|0|37|1.480000|34|1.360000|1|0.040000|N/A|N/A|24786|211456|K|1
 Strings Metadata|8
-0|mpeg2video|4|video|1/50|[0][0][0][0]|0x0000|352|288|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|00:00:00:00|1|N/A|25/1|25/1|1/25|N/A|N/A|N/A|N/A|N/A|104857200|N/A|N/A|N/A|51|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001
+0|mpeg2video|4|video|1/25|[0][0][0][0]|0x0000|352|288|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|N/A|1|N/A|25/1|25/1|1/25|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|51|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001
 1|pcm_s16le|unknown|audio|1/48000|[0][0][0][0]|0x0000|s16|48000|1|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|768000|N/A|N/A|N/A|N/A|50|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001
diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10
index 3b6e3fe..0ff1b04 100644
--- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10
+++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10
@@ -78,5 +78,5 @@ video|0|34|1.360000|34|1.360000|1|0.040000|N/A|N/A|150000|1923072|K|1
 Strings Metadata|8
 audio|1|65280|1.360000|65280|1.360000|1920|0.040000|N/A|N/A|7680|2073600|K|1
 Strings Metadata|8
-0|mpeg2video|0|video|1/50|[0][0][0][0]|0x0000|720|608|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|00:00:00:00|1|N/A|25/1|25/1|1/25|0|0.000000|N/A|N/A|30000000|30000000|N/A|N/A|N/A|35|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001
+0|mpeg2video|0|video|1/25|[0][0][0][0]|0x0000|720|608|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|N/A|1|N/A|25/1|25/1|1/25|0|0.000000|N/A|N/A|30000000|N/A|N/A|N/A|N/A|35|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001
 1|pcm_s16le|unknown|audio|1/48000|[0][0][0][0]|0x0000|s16|48000|2|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|1536000|N/A|N/A|N/A|N/A|35|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001
diff --git a/tests/ref/fate/concat-demuxer-simple2-lavf-ts b/tests/ref/fate/concat-demuxer-simple2-lavf-ts
index fb2713c..33337cf 100644
--- a/tests/ref/fate/concat-demuxer-simple2-lavf-ts
+++ b/tests/ref/fate/concat-demuxer-simple2-lavf-ts
@@ -1,12 +1,12 @@
-video|1|982|0.010911|-2618|-0.029089|3600|0.040000|N/A|N/A|24801|564|K
-video|1|4582|0.050911|982|0.010911|3600|0.040000|N/A|N/A|16429|27072|_
-video|1|8182|0.090911|4582|0.050911|3600|0.040000|N/A|N/A|14508|44932|_
-video|1|11782|0.130911|8182|0.090911|3600|0.040000|N/A|N/A|12622|60536|_
-video|1|15382|0.170911|11782|0.130911|3600|0.040000|N/A|N/A|13393|74260|_
-video|1|18982|0.210911|15382|0.170911|3600|0.040000|N/A|N/A|13092|88924|_
-video|1|22582|0.250911|18982|0.210911|3600|0.040000|N/A|N/A|12755|102836|_
-video|1|26182|0.290911|22582|0.250911|3600|0.040000|N/A|N/A|12023|116748|_
-audio|0|0|0.000000|0|0.000000|2351|0.026122|N/A|N/A|208|159988|K
+video|1|982|0.010911|-2618|-0.029089|3600|0.040000|N/A|N/A|24815|564|K
+video|1|4582|0.050911|982|0.010911|3600|0.040000|N/A|N/A|16443|27072|_
+video|1|8182|0.090911|4582|0.050911|3600|0.040000|N/A|N/A|14522|44932|_
+video|1|11782|0.130911|8182|0.090911|3600|0.040000|N/A|N/A|12636|60536|_
+video|1|15382|0.170911|11782|0.130911|3600|0.040000|N/A|N/A|13407|74260|_
+video|1|18982|0.210911|15382|0.170911|3600|0.040000|N/A|N/A|13106|88924|_
+video|1|22582|0.250911|18982|0.210911|3600|0.040000|N/A|N/A|12769|102836|_
+video|1|26182|0.290911|22582|0.250911|3600|0.040000|N/A|N/A|12037|116748|_
+audio|0|0|0.000000|0|0.000000|2351|0.026122|N/A|N/A|222|159988|K
 audio|0|2351|0.026122|2351|0.026122|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|4702|0.052244|4702|0.052244|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|7053|0.078367|7053|0.078367|2351|0.026122|N/A|N/A|209|N/A|K
@@ -20,17 +20,17 @@ audio|0|23510|0.261222|23510|0.261222|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|25861|0.287344|25861|0.287344|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|28212|0.313467|28212|0.313467|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|30563|0.339589|30563|0.339589|2351|0.026122|N/A|N/A|209|N/A|K
-video|1|29782|0.330911|26182|0.290911|3600|0.040000|N/A|N/A|14098|130096|_
-video|1|33382|0.370911|29782|0.330911|3600|0.040000|N/A|N/A|13329|145324|_
-video|1|36982|0.410911|33382|0.370911|3600|0.040000|N/A|N/A|12135|162996|_
-video|1|40582|0.450911|36982|0.410911|3600|0.040000|N/A|N/A|12282|176344|_
-video|1|44182|0.490911|40582|0.450911|3600|0.040000|N/A|N/A|24786|189692|K
-video|1|47782|0.530911|44182|0.490911|3600|0.040000|N/A|N/A|17440|216388|_
-video|1|51382|0.570911|47782|0.530911|3600|0.040000|N/A|N/A|15019|235000|_
-video|1|54982|0.610911|51382|0.570911|3600|0.040000|N/A|N/A|13449|251356|_
-video|1|58582|0.650911|54982|0.610911|3600|0.040000|N/A|N/A|12398|266020|_
-video|1|62182|0.690911|58582|0.650911|3600|0.040000|N/A|N/A|13455|279744|_
-audio|0|32915|0.365722|32915|0.365722|2351|0.026122|N/A|N/A|209|322608|K
+video|1|29782|0.330911|26182|0.290911|3600|0.040000|N/A|N/A|14112|130096|_
+video|1|33382|0.370911|29782|0.330911|3600|0.040000|N/A|N/A|13343|145324|_
+video|1|36982|0.410911|33382|0.370911|3600|0.040000|N/A|N/A|12149|162996|_
+video|1|40582|0.450911|36982|0.410911|3600|0.040000|N/A|N/A|12296|176344|_
+video|1|44182|0.490911|40582|0.450911|3600|0.040000|N/A|N/A|24800|189692|K
+video|1|47782|0.530911|44182|0.490911|3600|0.040000|N/A|N/A|17454|216388|_
+video|1|51382|0.570911|47782|0.530911|3600|0.040000|N/A|N/A|15033|235000|_
+video|1|54982|0.610911|51382|0.570911|3600|0.040000|N/A|N/A|13463|251356|_
+video|1|58582|0.650911|54982|0.610911|3600|0.040000|N/A|N/A|12412|266020|_
+video|1|62182|0.690911|58582|0.650911|3600|0.040000|N/A|N/A|13469|279744|_
+audio|0|32915|0.365722|32915|0.365722|2351|0.026122|N/A|N/A|223|322608|K
 audio|0|35266|0.391844|35266|0.391844|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|37617|0.417967|37617|0.417967|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|39968|0.444089|39968|0.444089|2351|0.026122|N/A|N/A|209|N/A|K
@@ -44,12 +44,12 @@ audio|0|56425|0.626944|56425|0.626944|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|58776|0.653067|58776|0.653067|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|61127|0.679189|61127|0.679189|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|63478|0.705311|63478|0.705311|2351|0.026122|N/A|N/A|209|N/A|K
-video|1|65782|0.730911|62182|0.690911|3600|0.040000|N/A|N/A|13836|294408|_
-video|1|69382|0.770911|65782|0.730911|3600|0.040000|N/A|N/A|12163|309448|_
-video|1|72982|0.810911|69382|0.770911|3600|0.040000|N/A|N/A|12692|325992|_
-video|1|76582|0.850911|72982|0.810911|3600|0.040000|N/A|N/A|10824|339528|_
-video|1|80182|0.890911|76582|0.850911|3600|0.040000|N/A|N/A|11286|351372|_
-audio|0|65829|0.731433|65829|0.731433|2351|0.026122|N/A|N/A|209|404576|K
+video|1|65782|0.730911|62182|0.690911|3600|0.040000|N/A|N/A|13850|294408|_
+video|1|69382|0.770911|65782|0.730911|3600|0.040000|N/A|N/A|12177|309448|_
+video|1|72982|0.810911|69382|0.770911|3600|0.040000|N/A|N/A|12706|325992|_
+video|1|76582|0.850911|72982|0.810911|3600|0.040000|N/A|N/A|10838|339528|_
+video|1|80182|0.890911|76582|0.850911|3600|0.040000|N/A|N/A|11300|351372|_
+audio|0|65829|0.731433|65829|0.731433|2351|0.026122|N/A|N/A|223|404576|K
 audio|0|68180|0.757556|68180|0.757556|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|70531|0.783678|70531|0.783678|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|72882|0.809800|72882|0.809800|2351|0.026122|N/A|N/A|209|N/A|K
@@ -60,17 +60,17 @@ audio|0|82286|0.914289|82286|0.914289|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|84637|0.940411|84637|0.940411|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|86988|0.966533|86988|0.966533|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|89339|0.992656|89339|0.992656|2351|0.026122|N/A|N/A|209|N/A|K
-video|1|83782|0.930911|80182|0.890911|3600|0.040000|N/A|N/A|12678|363592|_
+video|1|83782|0.930911|80182|0.890911|3600|0.040000|N/A|N/A|12692|363592|_
 video|1|87382|0.970911|83782|0.930911|3600|0.040000|N/A|N/A|24711|377880|K
-video|1|91964|1.021822|88364|0.981822|3600|0.040000|N/A|N/A|24801|564|K
-video|1|95564|1.061822|91964|1.021822|3600|0.040000|N/A|N/A|16429|27072|_
-video|1|99164|1.101822|95564|1.061822|3600|0.040000|N/A|N/A|14508|44932|_
-video|1|102764|1.141822|99164|1.101822|3600|0.040000|N/A|N/A|12622|60536|_
-video|1|106364|1.181822|102764|1.141822|3600|0.040000|N/A|N/A|13393|74260|_
-video|1|109964|1.221822|106364|1.181822|3600|0.040000|N/A|N/A|13092|88924|_
-video|1|113564|1.261822|109964|1.221822|3600|0.040000|N/A|N/A|12755|102836|_
-video|1|117164|1.301822|113564|1.261822|3600|0.040000|N/A|N/A|12023|116748|_
-audio|0|90982|1.010911|90982|1.010911|2351|0.026122|N/A|N/A|208|159988|K
+video|1|91964|1.021822|88364|0.981822|3600|0.040000|N/A|N/A|24815|564|K
+video|1|95564|1.061822|91964|1.021822|3600|0.040000|N/A|N/A|16443|27072|_
+video|1|99164|1.101822|95564|1.061822|3600|0.040000|N/A|N/A|14522|44932|_
+video|1|102764|1.141822|99164|1.101822|3600|0.040000|N/A|N/A|12636|60536|_
+video|1|106364|1.181822|102764|1.141822|3600|0.040000|N/A|N/A|13407|74260|_
+video|1|109964|1.221822|106364|1.181822|3600|0.040000|N/A|N/A|13106|88924|_
+video|1|113564|1.261822|109964|1.221822|3600|0.040000|N/A|N/A|12769|102836|_
+video|1|117164|1.301822|113564|1.261822|3600|0.040000|N/A|N/A|12037|116748|_
+audio|0|90982|1.010911|90982|1.010911|2351|0.026122|N/A|N/A|222|159988|K
 audio|0|93333|1.037033|93333|1.037033|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|95684|1.063156|95684|1.063156|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|98035|1.089278|98035|1.089278|2351|0.026122|N/A|N/A|209|N/A|K
@@ -84,17 +84,17 @@ audio|0|114492|1.272133|114492|1.272133|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|116843|1.298256|116843|1.298256|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|119194|1.324378|119194|1.324378|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|121545|1.350500|121545|1.350500|2351|0.026122|N/A|N/A|209|N/A|K
-video|1|120764|1.341822|117164|1.301822|3600|0.040000|N/A|N/A|14098|130096|_
-video|1|124364|1.381822|120764|1.341822|3600|0.040000|N/A|N/A|13329|145324|_
-video|1|127964|1.421822|124364|1.381822|3600|0.040000|N/A|N/A|12135|162996|_
-video|1|131564|1.461822|127964|1.421822|3600|0.040000|N/A|N/A|12282|176344|_
-video|1|135164|1.501822|131564|1.461822|3600|0.040000|N/A|N/A|24786|189692|K
-video|1|138764|1.541822|135164|1.501822|3600|0.040000|N/A|N/A|17440|216388|_
-video|1|142364|1.581822|138764|1.541822|3600|0.040000|N/A|N/A|15019|235000|_
-video|1|145964|1.621822|142364|1.581822|3600|0.040000|N/A|N/A|13449|251356|_
-video|1|149564|1.661822|145964|1.621822|3600|0.040000|N/A|N/A|12398|266020|_
-video|1|153164|1.701822|149564|1.661822|3600|0.040000|N/A|N/A|13455|279744|_
-audio|0|123897|1.376633|123897|1.376633|2351|0.026122|N/A|N/A|209|322608|K
+video|1|120764|1.341822|117164|1.301822|3600|0.040000|N/A|N/A|14112|130096|_
+video|1|124364|1.381822|120764|1.341822|3600|0.040000|N/A|N/A|13343|145324|_
+video|1|127964|1.421822|124364|1.381822|3600|0.040000|N/A|N/A|12149|162996|_
+video|1|131564|1.461822|127964|1.421822|3600|0.040000|N/A|N/A|12296|176344|_
+video|1|135164|1.501822|131564|1.461822|3600|0.040000|N/A|N/A|24800|189692|K
+video|1|138764|1.541822|135164|1.501822|3600|0.040000|N/A|N/A|17454|216388|_
+video|1|142364|1.581822|138764|1.541822|3600|0.040000|N/A|N/A|15033|235000|_
+video|1|145964|1.621822|142364|1.581822|3600|0.040000|N/A|N/A|13463|251356|_
+video|1|149564|1.661822|145964|1.621822|3600|0.040000|N/A|N/A|12412|266020|_
+video|1|153164|1.701822|149564|1.661822|3600|0.040000|N/A|N/A|13469|279744|_
+audio|0|123897|1.376633|123897|1.376633|2351|0.026122|N/A|N/A|223|322608|K
 audio|0|126248|1.402756|126248|1.402756|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|128599|1.428878|128599|1.428878|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|130950|1.455000|130950|1.455000|2351|0.026122|N/A|N/A|209|N/A|K
@@ -108,12 +108,12 @@ audio|0|147407|1.637856|147407|1.637856|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|149758|1.663978|149758|1.663978|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|152109|1.690100|152109|1.690100|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|154460|1.716222|154460|1.716222|2351|0.026122|N/A|N/A|209|N/A|K
-video|1|156764|1.741822|153164|1.701822|3600|0.040000|N/A|N/A|13836|294408|_
-video|1|160364|1.781822|156764|1.741822|3600|0.040000|N/A|N/A|12163|309448|_
-video|1|163964|1.821822|160364|1.781822|3600|0.040000|N/A|N/A|12692|325992|_
-video|1|167564|1.861822|163964|1.821822|3600|0.040000|N/A|N/A|10824|339528|_
-video|1|171164|1.901822|167564|1.861822|3600|0.040000|N/A|N/A|11286|351372|_
-audio|0|156811|1.742344|156811|1.742344|2351|0.026122|N/A|N/A|209|404576|K
+video|1|156764|1.741822|153164|1.701822|3600|0.040000|N/A|N/A|13850|294408|_
+video|1|160364|1.781822|156764|1.741822|3600|0.040000|N/A|N/A|12177|309448|_
+video|1|163964|1.821822|160364|1.781822|3600|0.040000|N/A|N/A|12706|325992|_
+video|1|167564|1.861822|163964|1.821822|3600|0.040000|N/A|N/A|10838|339528|_
+video|1|171164|1.901822|167564|1.861822|3600|0.040000|N/A|N/A|11300|351372|_
+audio|0|156811|1.742344|156811|1.742344|2351|0.026122|N/A|N/A|223|404576|K
 audio|0|159162|1.768467|159162|1.768467|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|161513|1.794589|161513|1.794589|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|163864|1.820711|163864|1.820711|2351|0.026122|N/A|N/A|209|N/A|K
@@ -124,12 +124,12 @@ audio|0|173268|1.925200|173268|1.925200|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|175619|1.951322|175619|1.951322|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|177970|1.977444|177970|1.977444|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|180321|2.003567|180321|2.003567|2351|0.026122|N/A|N/A|209|N/A|K
-video|1|174764|1.941822|171164|1.901822|3600|0.040000|N/A|N/A|12678|363592|_
+video|1|174764|1.941822|171164|1.901822|3600|0.040000|N/A|N/A|12692|363592|_
 video|1|178364|1.981822|174764|1.941822|3600|0.040000|N/A|N/A|24711|377880|K
-video|1|139582|1.550911|135982|1.510911|3600|0.040000|N/A|N/A|12692|325992|_
-video|1|143182|1.590911|139582|1.550911|3600|0.040000|N/A|N/A|10824|339528|_
-video|1|146782|1.630911|143182|1.590911|3600|0.040000|N/A|N/A|11286|351372|_
-audio|0|132429|1.471433|132429|1.471433|2351|0.026122|N/A|N/A|209|404576|K
+video|1|139582|1.550911|135982|1.510911|3600|0.040000|N/A|N/A|12706|325992|_
+video|1|143182|1.590911|139582|1.550911|3600|0.040000|N/A|N/A|10838|339528|_
+video|1|146782|1.630911|143182|1.590911|3600|0.040000|N/A|N/A|11300|351372|_
+audio|0|132429|1.471433|132429|1.471433|2351|0.026122|N/A|N/A|223|404576|K
 audio|0|134780|1.497556|134780|1.497556|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|137131|1.523678|137131|1.523678|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|139482|1.549800|139482|1.549800|2351|0.026122|N/A|N/A|209|N/A|K
@@ -140,12 +140,12 @@ audio|0|148886|1.654289|148886|1.654289|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|151237|1.680411|151237|1.680411|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|153588|1.706533|153588|1.706533|2351|0.026122|N/A|N/A|209|N/A|K
 audio|0|155939|1.732656|155939|1.732656|2351|0.026122|N/A|N/A|209|N/A|K
-video|1|150382|1.670911|146782|1.630911|3600|0.040000|N/A|N/A|12678|363592|_
+video|1|150382|1.670911|146782|1.630911|3600|0.040000|N/A|N/A|12692|363592|_
 video|1|153982|1.710911|150382|1.670911|3600|0.040000|N/A|N/A|24711|377880|K
-video|1|161182|1.790911|157582|1.750911|3600|0.040000|N/A|N/A|12135|162996|_
-video|1|164782|1.830911|161182|1.790911|3600|0.040000|N/A|N/A|12282|176344|_
-video|1|168382|1.870911|164782|1.830911|3600|0.040000|N/A|N/A|24786|189692|K
-video|1|171982|1.910911|168382|1.870911|3600|0.040000|N/A|N/A|17440|216388|_
-video|1|175582|1.950911|171982|1.910911|3600|0.040000|N/A|N/A|15019|235000|_
+video|1|161182|1.790911|157582|1.750911|3600|0.040000|N/A|N/A|12149|162996|_
+video|1|164782|1.830911|161182|1.790911|3600|0.040000|N/A|N/A|12296|176344|_
+video|1|168382|1.870911|164782|1.830911|3600|0.040000|N/A|N/A|24800|189692|K
+video|1|171982|1.910911|168382|1.870911|3600|0.040000|N/A|N/A|17454|216388|_
+video|1|175582|1.950911|171982|1.910911|3600|0.040000|N/A|N/A|15033|235000|_
 0|mp2|unknown|audio|1/44100|[3][0][0][0]|0x0003|s16p|44100|1|mono|0|N/A|0/0|0/0|1/90000|0|0.000000|N/A|N/A|64000|N/A|N/A|N/A|N/A|89|0|0|0|0|0|0|0|0|0|0|0
-1|mpeg2video|4|video|1/50|[2][0][0][0]|0x0002|352|288|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|00:00:00:00|1|N/A|25/1|25/1|1/90000|N/A|N/A|N/A|N/A|N/A|104857200|N/A|N/A|N/A|60|0|0|0|0|0|0|0|0|0|0|0
+1|mpeg2video|4|video|1/25|[2][0][0][0]|0x0002|352|288|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|N/A|1|N/A|25/1|25/1|1/90000|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|60|0|0|0|0|0|0|0|0|0|0|0
diff --git a/tests/ref/fate/corepng b/tests/ref/fate/corepng
index e200714..4c106ed 100644
--- a/tests/ref/fate/corepng
+++ b/tests/ref/fate/corepng
@@ -1,5 +1,13 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 #tb 1: 1/11025
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 11025
+#channel_layout 1: 4
 0,          0,          0,        1,   230400, 0x03e25ead
 1,          0,          0,     5513,    11026, 0x27ad637c
 0,          1,          1,        1,   230400, 0x0a520ffd
diff --git a/tests/ref/fate/creatureshock-avs b/tests/ref/fate/creatureshock-avs
index 4c721d8..82460b2 100644
--- a/tests/ref/fate/creatureshock-avs
+++ b/tests/ref/fate/creatureshock-avs
@@ -1,5 +1,13 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 318x198
+#sar 0: 0/1
 #tb 1: 1/22222
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 22222
+#channel_layout 1: 4
 0,          0,          0,        1,   188892, 0x9f47a5ec
 1,          0,          0,     8186,    16372, 0xfaaab59d
 0,          1,          1,        1,   188892, 0xdece0269
diff --git a/tests/ref/fate/cscd b/tests/ref/fate/cscd
index 74fe94e..9af7b2f 100644
--- a/tests/ref/fate/cscd
+++ b/tests/ref/fate/cscd
@@ -1,4 +1,8 @@
 #tb 0: 1/200
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 300x300
+#sar 0: 0/1
 0,          0,          0,        1,   270000, 0xf90015d8
 0,          9,          9,        1,   270000, 0xf90015d8
 0,         15,         15,        1,   270000, 0xf90015d8
diff --git a/tests/ref/fate/cvid-grayscale b/tests/ref/fate/cvid-grayscale
index 1b586b3..a4f8dde 100644
--- a/tests/ref/fate/cvid-grayscale
+++ b/tests/ref/fate/cvid-grayscale
@@ -1,4 +1,8 @@
 #tb 0: 99561/500000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 100x75
+#sar 0: 0/1
 0,          0,          0,        1,    22500, 0x0f8e562e
 0,          1,          1,        1,    22500, 0x507aef06
 0,          2,          2,        1,    22500, 0x059d6137
diff --git a/tests/ref/fate/cvid-palette b/tests/ref/fate/cvid-palette
index 49de1c1..eae4161 100644
--- a/tests/ref/fate/cvid-palette
+++ b/tests/ref/fate/cvid-palette
@@ -1,4 +1,8 @@
 #tb 0: 200/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    57600, 0x1f5c89b7
 0,          1,          1,        1,    57600, 0xd2055aaf
 0,          2,          2,        1,    57600, 0x22336052
diff --git a/tests/ref/fate/cvid-partial b/tests/ref/fate/cvid-partial
index bb368a1..990939d 100644
--- a/tests/ref/fate/cvid-partial
+++ b/tests/ref/fate/cvid-partial
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 400x187
+#sar 0: 0/1
 0,          0,          0,        1,   224400, 0xd8f2f310
 0,          1,          1,        1,   224400, 0xe38676c2
 0,          2,          2,        1,   224400, 0x7163b6ad
diff --git a/tests/ref/fate/cyberia-c93 b/tests/ref/fate/cyberia-c93
index f02435c..5eb4336 100644
--- a/tests/ref/fate/cyberia-c93
+++ b/tests/ref/fate/cyberia-c93
@@ -1,5 +1,13 @@
 #tb 0: 2/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x192
+#sar 0: 5/6
 #tb 1: 1/16129
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 16129
+#channel_layout 1: 4
 0,          0,          0,        1,   184320, 0x8433f0f8
 1,          0,          0,    14184,    28368, 0xaacc96a5
 0,          1,          1,        1,   184320, 0xd0d480f7
diff --git a/tests/ref/fate/cyuv b/tests/ref/fate/cyuv
index 37bdd2f..18caeb8 100644
--- a/tests/ref/fate/cyuv
+++ b/tests/ref/fate/cyuv
@@ -1,4 +1,8 @@
 #tb 0: 33333/1000000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x501e6abe
 0,          1,          1,        1,    38016, 0x84976f13
 0,          2,          2,        1,    38016, 0x8c487acb
diff --git a/tests/ref/fate/d-cinema-demux b/tests/ref/fate/d-cinema-demux
index 2f28e46..8e747de 100644
--- a/tests/ref/fate/d-cinema-demux
+++ b/tests/ref/fate/d-cinema-demux
@@ -1,4 +1,8 @@
 #tb 0: 1/90000
+#media_type 0: audio
+#codec_id 0: pcm_s24daud
+#sample_rate 0: 96000
+#channel_layout 0: 60f
 0,          0,          0,     1875,    36000, 0xd592781d
 0,       1875,       1875,     1875,    36000, 0xd592781d
 0,       3750,       3750,     1875,    36000, 0xd592781d
diff --git a/tests/ref/fate/d-eavp6-demux b/tests/ref/fate/d-eavp6-demux
index 3587a08..7cc13cf 100644
--- a/tests/ref/fate/d-eavp6-demux
+++ b/tests/ref/fate/d-eavp6-demux
@@ -1,5 +1,13 @@
 #tb 0: 32767/982027
+#media_type 0: video
+#codec_id 0: vp6
+#dimensions 0: 64x64
+#sar 0: 0/1
 #tb 1: 32767/982027
+#media_type 1: video
+#codec_id 1: vp6
+#dimensions 1: 64x64
+#sar 1: 0/1
 0,          0,          0,        1,     1860, 0xbd548c4c
 1,          0,          0,        1,     1748, 0x96046284
 0,          1,          1,        1,     1044, 0x814efc86, F=0x0
diff --git a/tests/ref/fate/dca-xll_51_16_192_768_0 b/tests/ref/fate/dca-xll_51_16_192_768_0
index 0e22d5d..acbae84 100644
--- a/tests/ref/fate/dca-xll_51_16_192_768_0
+++ b/tests/ref/fate/dca-xll_51_16_192_768_0
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/192000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 192000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
 0,       2048,       2048,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
diff --git a/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_2 b/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_2
index 0e22d5d..acbae84 100644
--- a/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_2
+++ b/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/192000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 192000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
 0,       2048,       2048,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
diff --git a/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_6 b/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_6
index 0e22d5d..acbae84 100644
--- a/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_6
+++ b/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/192000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 192000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
 0,       2048,       2048,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
diff --git a/tests/ref/fate/dca-xll_51_16_192_768_1 b/tests/ref/fate/dca-xll_51_16_192_768_1
index 0e22d5d..acbae84 100644
--- a/tests/ref/fate/dca-xll_51_16_192_768_1
+++ b/tests/ref/fate/dca-xll_51_16_192_768_1
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/192000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 192000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
 0,       2048,       2048,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
diff --git a/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_2 b/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_2
index d97ad2f..3486971 100644
--- a/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_2
+++ b/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/192000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 192000
+#channel_layout 0: 3
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     2048,     8192, 0829f71740aab1ab98b33eae21dee122
 0,       2048,       2048,     2048,     8192, c8ca1cff44674809d464ec39cf1bd1e9
diff --git a/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_6 b/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_6
index 0e22d5d..acbae84 100644
--- a/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_6
+++ b/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/192000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 192000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
 0,       2048,       2048,     2048,    24576, 91ff0dac5df86e798bfef5e573536b08
diff --git a/tests/ref/fate/dca-xll_51_24_48_768 b/tests/ref/fate/dca-xll_51_24_48_768
index 47a62ec..8e7be8b 100644
--- a/tests/ref/fate/dca-xll_51_24_48_768
+++ b/tests/ref/fate/dca-xll_51_24_48_768
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,     9216, 13a95890b5f0947d6f058ca9c30a3e01
 0,        512,        512,      512,     9216, 13a95890b5f0947d6f058ca9c30a3e01
diff --git a/tests/ref/fate/dca-xll_51_24_48_768-dmix_2 b/tests/ref/fate/dca-xll_51_24_48_768-dmix_2
index 1a736cf..5f57619 100644
--- a/tests/ref/fate/dca-xll_51_24_48_768-dmix_2
+++ b/tests/ref/fate/dca-xll_51_24_48_768-dmix_2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 3
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,     3072, d2a70550489de356a2cd6bfc40711204
 0,        512,        512,      512,     3072, d2a70550489de356a2cd6bfc40711204
diff --git a/tests/ref/fate/dca-xll_51_24_48_768-dmix_6 b/tests/ref/fate/dca-xll_51_24_48_768-dmix_6
index 47a62ec..8e7be8b 100644
--- a/tests/ref/fate/dca-xll_51_24_48_768-dmix_6
+++ b/tests/ref/fate/dca-xll_51_24_48_768-dmix_6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,     9216, 13a95890b5f0947d6f058ca9c30a3e01
 0,        512,        512,      512,     9216, 13a95890b5f0947d6f058ca9c30a3e01
diff --git a/tests/ref/fate/dca-xll_51_24_48_none b/tests/ref/fate/dca-xll_51_24_48_none
index dffc587..a1994e7 100644
--- a/tests/ref/fate/dca-xll_51_24_48_none
+++ b/tests/ref/fate/dca-xll_51_24_48_none
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
 0,       1024,       1024,     1024,    18432, 6707daa7724fdc552869e522a7936f26
diff --git a/tests/ref/fate/dca-xll_51_24_48_none-dmix_2 b/tests/ref/fate/dca-xll_51_24_48_none-dmix_2
index dffc587..a1994e7 100644
--- a/tests/ref/fate/dca-xll_51_24_48_none-dmix_2
+++ b/tests/ref/fate/dca-xll_51_24_48_none-dmix_2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
 0,       1024,       1024,     1024,    18432, 6707daa7724fdc552869e522a7936f26
diff --git a/tests/ref/fate/dca-xll_51_24_48_none-dmix_6 b/tests/ref/fate/dca-xll_51_24_48_none-dmix_6
index dffc587..a1994e7 100644
--- a/tests/ref/fate/dca-xll_51_24_48_none-dmix_6
+++ b/tests/ref/fate/dca-xll_51_24_48_none-dmix_6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
 0,       1024,       1024,     1024,    18432, 6707daa7724fdc552869e522a7936f26
diff --git a/tests/ref/fate/dca-xll_71_24_48_768_0 b/tests/ref/fate/dca-xll_71_24_48_768_0
index c122c6a..387b07e 100644
--- a/tests/ref/fate/dca-xll_71_24_48_768_0
+++ b/tests/ref/fate/dca-xll_71_24_48_768_0
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 63f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,    12288, ca9f8c8eb1b9b311cb79999fa376c7f0
 0,        512,        512,      512,    12288, 4072783b8efb99a9e5817067d68f61c6
diff --git a/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_2 b/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_2
index d653af8..e1169e1 100644
--- a/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_2
+++ b/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,     9216, a2b724b146069938f0e2cb82490dea54
 0,        512,        512,      512,     9216, 13a95890b5f0947d6f058ca9c30a3e01
diff --git a/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_6 b/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_6
index d653af8..e1169e1 100644
--- a/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_6
+++ b/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,     9216, a2b724b146069938f0e2cb82490dea54
 0,        512,        512,      512,     9216, 13a95890b5f0947d6f058ca9c30a3e01
diff --git a/tests/ref/fate/dca-xll_71_24_48_768_1 b/tests/ref/fate/dca-xll_71_24_48_768_1
index c122c6a..387b07e 100644
--- a/tests/ref/fate/dca-xll_71_24_48_768_1
+++ b/tests/ref/fate/dca-xll_71_24_48_768_1
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 63f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,    12288, ca9f8c8eb1b9b311cb79999fa376c7f0
 0,        512,        512,      512,    12288, 4072783b8efb99a9e5817067d68f61c6
diff --git a/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_2 b/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_2
index 58c381c..44bc5a0 100644
--- a/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_2
+++ b/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 3
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,     3072, d2a70550489de356a2cd6bfc40711204
 0,        512,        512,      512,     3072, d2a70550489de356a2cd6bfc40711204
diff --git a/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_6 b/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_6
index d61048c..ef6a113 100644
--- a/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_6
+++ b/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,     9216, a2b724b146069938f0e2cb82490dea54
 0,        512,        512,      512,     9216, 13a95890b5f0947d6f058ca9c30a3e01
diff --git a/tests/ref/fate/dca-xll_71_24_96_768 b/tests/ref/fate/dca-xll_71_24_96_768
index 72da526..a2a02e0 100644
--- a/tests/ref/fate/dca-xll_71_24_96_768
+++ b/tests/ref/fate/dca-xll_71_24_96_768
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/96000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 96000
+#channel_layout 0: 63f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     1024,    24576, 0b24a527d66f2b0cab97f37e4cd79987
 0,       1024,       1024,     1024,    24576, 91ff0dac5df86e798bfef5e573536b08
diff --git a/tests/ref/fate/dca-xll_71_24_96_768-dmix_2 b/tests/ref/fate/dca-xll_71_24_96_768-dmix_2
index b24c717..9f2877d 100644
--- a/tests/ref/fate/dca-xll_71_24_96_768-dmix_2
+++ b/tests/ref/fate/dca-xll_71_24_96_768-dmix_2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/96000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 96000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     1024,    18432, 0a675f172b0e1a171c46dfaa4f1d0f00
 0,       1024,       1024,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
diff --git a/tests/ref/fate/dca-xll_71_24_96_768-dmix_6 b/tests/ref/fate/dca-xll_71_24_96_768-dmix_6
index b24c717..9f2877d 100644
--- a/tests/ref/fate/dca-xll_71_24_96_768-dmix_6
+++ b/tests/ref/fate/dca-xll_71_24_96_768-dmix_6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/96000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 96000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     1024,    18432, 0a675f172b0e1a171c46dfaa4f1d0f00
 0,       1024,       1024,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
diff --git a/tests/ref/fate/dca-xll_x96_51_24_96_1509 b/tests/ref/fate/dca-xll_x96_51_24_96_1509
index 150ab25..39a9e79 100644
--- a/tests/ref/fate/dca-xll_x96_51_24_96_1509
+++ b/tests/ref/fate/dca-xll_x96_51_24_96_1509
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/96000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 96000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
 0,       1024,       1024,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
diff --git a/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_2 b/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_2
index 150ab25..39a9e79 100644
--- a/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_2
+++ b/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/96000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 96000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
 0,       1024,       1024,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
diff --git a/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_6 b/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_6
index 150ab25..39a9e79 100644
--- a/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_6
+++ b/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/96000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 96000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
 0,       1024,       1024,     1024,    18432, f9debe3f07be68533bf0295e3d2ba68a
diff --git a/tests/ref/fate/dca-xll_xch_61_24_48_768 b/tests/ref/fate/dca-xll_xch_61_24_48_768
index 211aee1..e3ac859 100644
--- a/tests/ref/fate/dca-xll_xch_61_24_48_768
+++ b/tests/ref/fate/dca-xll_xch_61_24_48_768
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 70f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,    10752, c3c5b236c266a9090378def1ad497a21
 0,        512,        512,      512,    10752, 36eb6749f8d9ce9f94860dcc447253ac
diff --git a/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_2 b/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_2
index 9309d8d..b53a528 100644
--- a/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_2
+++ b/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,     9216, 652c4e61f9abe9fba9de792242e2d31d
 0,        512,        512,      512,     9216, 13a95890b5f0947d6f058ca9c30a3e01
diff --git a/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_6 b/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_6
index 9309d8d..b53a528 100644
--- a/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_6
+++ b/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s24le
+#sample_rate 0: 48000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      512,     9216, 652c4e61f9abe9fba9de792242e2d31d
 0,        512,        512,      512,     9216, 13a95890b5f0947d6f058ca9c30a3e01
diff --git a/tests/ref/fate/dcinema-encode b/tests/ref/fate/dcinema-encode
index 93ac172..27865d6 100644
--- a/tests/ref/fate/dcinema-encode
+++ b/tests/ref/fate/dcinema-encode
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/96000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 96000
+#channel_layout 0: 60f
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,      341,     4092, 697cddfcd0e21f24782af0705b7048f3
 0,        341,        341,      341,     4092, a057b18cd493923fed33c18578f61e0b
diff --git a/tests/ref/fate/dds-alpha8 b/tests/ref/fate/dds-alpha8
new file mode 100644
index 0000000..7358684
--- /dev/null
+++ b/tests/ref/fate/dds-alpha8
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 122x122
+#sar 0: 0/1
+0,          0,          0,        1,    14884, 0xf81c47f5
diff --git a/tests/ref/fate/dds-argb b/tests/ref/fate/dds-argb
index fbde424..f230133 100644
--- a/tests/ref/fate/dds-argb
+++ b/tests/ref/fate/dds-argb
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 220x64
+#sar 0: 0/1
 0,          0,          0,        1,    56320, 0xfcaa920b
diff --git a/tests/ref/fate/dds-argb-aexp b/tests/ref/fate/dds-argb-aexp
index f52410f..0e2b9af 100644
--- a/tests/ref/fate/dds-argb-aexp
+++ b/tests/ref/fate/dds-argb-aexp
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xfdd37c43
diff --git a/tests/ref/fate/dds-dx10-bc1 b/tests/ref/fate/dds-dx10-bc1
index 84efd9f..e99bf00 100644
--- a/tests/ref/fate/dds-dx10-bc1
+++ b/tests/ref/fate/dds-dx10-bc1
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xed2f850f
diff --git a/tests/ref/fate/dds-dx10-bc1a b/tests/ref/fate/dds-dx10-bc1a
index 8cb4589..53a2256 100644
--- a/tests/ref/fate/dds-dx10-bc1a
+++ b/tests/ref/fate/dds-dx10-bc1a
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x473b484b
diff --git a/tests/ref/fate/dds-dx10-bc2 b/tests/ref/fate/dds-dx10-bc2
index a25180d..5c31b38 100644
--- a/tests/ref/fate/dds-dx10-bc2
+++ b/tests/ref/fate/dds-dx10-bc2
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x2bce3baa
diff --git a/tests/ref/fate/dds-dx10-bc3 b/tests/ref/fate/dds-dx10-bc3
index 296c945..4bc4ef4 100644
--- a/tests/ref/fate/dds-dx10-bc3
+++ b/tests/ref/fate/dds-dx10-bc3
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xb91d3c62
diff --git a/tests/ref/fate/dds-dx10-bc4 b/tests/ref/fate/dds-dx10-bc4
index 4583d25..8d57cfa 100644
--- a/tests/ref/fate/dds-dx10-bc4
+++ b/tests/ref/fate/dds-dx10-bc4
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xfdfd1751
diff --git a/tests/ref/fate/dds-dx10-bc5 b/tests/ref/fate/dds-dx10-bc5
index bf595eb..d8e4734 100644
--- a/tests/ref/fate/dds-dx10-bc5
+++ b/tests/ref/fate/dds-dx10-bc5
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x79bd207e
diff --git a/tests/ref/fate/dds-dxt1 b/tests/ref/fate/dds-dxt1
index 2477406..f1c6c9c 100644
--- a/tests/ref/fate/dds-dxt1
+++ b/tests/ref/fate/dds-dxt1
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x64
+#sar 0: 0/1
 0,          0,          0,        1,    32768, 0xf52adc80
diff --git a/tests/ref/fate/dds-dxt1-normalmap b/tests/ref/fate/dds-dxt1-normalmap
index 3f77547..15d63b1 100644
--- a/tests/ref/fate/dds-dxt1-normalmap
+++ b/tests/ref/fate/dds-dxt1-normalmap
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x2b411855
diff --git a/tests/ref/fate/dds-dxt1a b/tests/ref/fate/dds-dxt1a
index 05be314..1786b49 100644
--- a/tests/ref/fate/dds-dxt1a
+++ b/tests/ref/fate/dds-dxt1a
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xcabb50ea
diff --git a/tests/ref/fate/dds-dxt2 b/tests/ref/fate/dds-dxt2
index 40bcf6e..b5bdfba 100644
--- a/tests/ref/fate/dds-dxt2
+++ b/tests/ref/fate/dds-dxt2
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x11cebeb0
diff --git a/tests/ref/fate/dds-dxt3 b/tests/ref/fate/dds-dxt3
index 41401da..d93e35c 100644
--- a/tests/ref/fate/dds-dxt3
+++ b/tests/ref/fate/dds-dxt3
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x729b74ba
diff --git a/tests/ref/fate/dds-dxt4 b/tests/ref/fate/dds-dxt4
index dc5d73f..136dfd8 100644
--- a/tests/ref/fate/dds-dxt4
+++ b/tests/ref/fate/dds-dxt4
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x31aaacd6
diff --git a/tests/ref/fate/dds-dxt5 b/tests/ref/fate/dds-dxt5
index 399d6d9..696e038 100644
--- a/tests/ref/fate/dds-dxt5
+++ b/tests/ref/fate/dds-dxt5
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xfd3166aa
diff --git a/tests/ref/fate/dds-dxt5-aexp b/tests/ref/fate/dds-dxt5-aexp
index ff91afd..334dcc1 100644
--- a/tests/ref/fate/dds-dxt5-aexp
+++ b/tests/ref/fate/dds-dxt5-aexp
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x3c987914
diff --git a/tests/ref/fate/dds-dxt5-normalmap b/tests/ref/fate/dds-dxt5-normalmap
index 680d1b7..b562b19 100644
--- a/tests/ref/fate/dds-dxt5-normalmap
+++ b/tests/ref/fate/dds-dxt5-normalmap
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xd29b1ea1
diff --git a/tests/ref/fate/dds-dxt5-normalmap-ati b/tests/ref/fate/dds-dxt5-normalmap-ati
index 7f088f7..b1fb53d 100644
--- a/tests/ref/fate/dds-dxt5-normalmap-ati
+++ b/tests/ref/fate/dds-dxt5-normalmap-ati
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x54cb212f
diff --git a/tests/ref/fate/dds-dxt5-rbxg b/tests/ref/fate/dds-dxt5-rbxg
index 7dbecf4..0177946 100644
--- a/tests/ref/fate/dds-dxt5-rbxg
+++ b/tests/ref/fate/dds-dxt5-rbxg
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x37588d12
diff --git a/tests/ref/fate/dds-dxt5-rgxb b/tests/ref/fate/dds-dxt5-rgxb
index 137913d..522679c 100644
--- a/tests/ref/fate/dds-dxt5-rgxb
+++ b/tests/ref/fate/dds-dxt5-rgxb
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xfb6b91cf
diff --git a/tests/ref/fate/dds-dxt5-rxbg b/tests/ref/fate/dds-dxt5-rxbg
index b6e12d3..cc6a239 100644
--- a/tests/ref/fate/dds-dxt5-rxbg
+++ b/tests/ref/fate/dds-dxt5-rxbg
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xc6cb8cbe
diff --git a/tests/ref/fate/dds-dxt5-rxgb b/tests/ref/fate/dds-dxt5-rxgb
index a4190d5..9d70af8 100644
--- a/tests/ref/fate/dds-dxt5-rxgb
+++ b/tests/ref/fate/dds-dxt5-rxgb
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xb67d936a
diff --git a/tests/ref/fate/dds-dxt5-xgbr b/tests/ref/fate/dds-dxt5-xgbr
index 95404f2..2f82cdc 100644
--- a/tests/ref/fate/dds-dxt5-xgbr
+++ b/tests/ref/fate/dds-dxt5-xgbr
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xb0e69293
diff --git a/tests/ref/fate/dds-dxt5-xgxr b/tests/ref/fate/dds-dxt5-xgxr
index 3ed73c3..3555449 100644
--- a/tests/ref/fate/dds-dxt5-xgxr
+++ b/tests/ref/fate/dds-dxt5-xgxr
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xa93de1ad
diff --git a/tests/ref/fate/dds-dxt5-xrbg b/tests/ref/fate/dds-dxt5-xrbg
index f647955..e6228f7 100644
--- a/tests/ref/fate/dds-dxt5-xrbg
+++ b/tests/ref/fate/dds-dxt5-xrbg
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xf20d8b69
diff --git a/tests/ref/fate/dds-dxt5-ycocg b/tests/ref/fate/dds-dxt5-ycocg
index 1dd8bef..7f98652 100644
--- a/tests/ref/fate/dds-dxt5-ycocg
+++ b/tests/ref/fate/dds-dxt5-ycocg
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x0d0c8d20
diff --git a/tests/ref/fate/dds-dxt5-ycocg-scaled b/tests/ref/fate/dds-dxt5-ycocg-scaled
index 5a70b49..2e74a84 100644
--- a/tests/ref/fate/dds-dxt5-ycocg-scaled
+++ b/tests/ref/fate/dds-dxt5-ycocg-scaled
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x5a089973
diff --git a/tests/ref/fate/dds-monob b/tests/ref/fate/dds-monob
new file mode 100644
index 0000000..629b417
--- /dev/null
+++ b/tests/ref/fate/dds-monob
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 122x122
+#sar 0: 0/1
+0,          0,          0,        1,     1952, 0x716498a1
diff --git a/tests/ref/fate/dds-pal b/tests/ref/fate/dds-pal
index 575a4bd..08c14a2 100644
--- a/tests/ref/fate/dds-pal
+++ b/tests/ref/fate/dds-pal
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    65536, 0x4287e5cd
diff --git a/tests/ref/fate/dds-pal-ati b/tests/ref/fate/dds-pal-ati
index 6de8adb..3303f76 100644
--- a/tests/ref/fate/dds-pal-ati
+++ b/tests/ref/fate/dds-pal-ati
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x6ac18060
diff --git a/tests/ref/fate/dds-rgb1555 b/tests/ref/fate/dds-rgb1555
new file mode 100644
index 0000000..95e701f
--- /dev/null
+++ b/tests/ref/fate/dds-rgb1555
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 122x122
+#sar 0: 0/1
+0,          0,          0,        1,    29768, 0xbdc099db
diff --git a/tests/ref/fate/dds-rgb16 b/tests/ref/fate/dds-rgb16
index 40a9938..7865070 100644
--- a/tests/ref/fate/dds-rgb16
+++ b/tests/ref/fate/dds-rgb16
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xc8910265
diff --git a/tests/ref/fate/dds-rgb24 b/tests/ref/fate/dds-rgb24
index 3eeb1eb..2d4e7ed 100644
--- a/tests/ref/fate/dds-rgb24
+++ b/tests/ref/fate/dds-rgb24
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x64
+#sar 0: 0/1
 0,          0,          0,        1,    24576, 0xef0f9653
diff --git a/tests/ref/fate/dds-rgb555 b/tests/ref/fate/dds-rgb555
new file mode 100644
index 0000000..70c320e
--- /dev/null
+++ b/tests/ref/fate/dds-rgb555
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 122x122
+#sar 0: 0/1
+0,          0,          0,        1,    29768, 0x277d8628
diff --git a/tests/ref/fate/dds-rgba b/tests/ref/fate/dds-rgba
index 803b40a..7a14673 100644
--- a/tests/ref/fate/dds-rgba
+++ b/tests/ref/fate/dds-rgba
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 80x80
+#sar 0: 0/1
 0,          0,          0,        1,    25600, 0xa2a47b2f
diff --git a/tests/ref/fate/dds-rgtc1s b/tests/ref/fate/dds-rgtc1s
index 5085962..f0e271b 100644
--- a/tests/ref/fate/dds-rgtc1s
+++ b/tests/ref/fate/dds-rgtc1s
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xcda652a4
diff --git a/tests/ref/fate/dds-rgtc1u b/tests/ref/fate/dds-rgtc1u
index b7cff66..5ef5c05 100644
--- a/tests/ref/fate/dds-rgtc1u
+++ b/tests/ref/fate/dds-rgtc1u
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x629a1b44
diff --git a/tests/ref/fate/dds-rgtc2s b/tests/ref/fate/dds-rgtc2s
index 7227602..9e8653b 100644
--- a/tests/ref/fate/dds-rgtc2s
+++ b/tests/ref/fate/dds-rgtc2s
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0xa0135ca8
diff --git a/tests/ref/fate/dds-rgtc2u b/tests/ref/fate/dds-rgtc2u
index 0b6678b..9d3683f 100644
--- a/tests/ref/fate/dds-rgtc2u
+++ b/tests/ref/fate/dds-rgtc2u
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x38cb221a
diff --git a/tests/ref/fate/dds-rgtc2u-xy b/tests/ref/fate/dds-rgtc2u-xy
index bf595eb..d8e4734 100644
--- a/tests/ref/fate/dds-rgtc2u-xy
+++ b/tests/ref/fate/dds-rgtc2u-xy
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x79bd207e
diff --git a/tests/ref/fate/dds-uyvy b/tests/ref/fate/dds-uyvy
index 2bcbaa0..b6fa221 100644
--- a/tests/ref/fate/dds-uyvy
+++ b/tests/ref/fate/dds-uyvy
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,     8192, 0x3c658750
diff --git a/tests/ref/fate/dds-xbgr b/tests/ref/fate/dds-xbgr
index eb7a024..d4f4d98 100644
--- a/tests/ref/fate/dds-xbgr
+++ b/tests/ref/fate/dds-xbgr
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x70336a28
diff --git a/tests/ref/fate/dds-xrgb b/tests/ref/fate/dds-xrgb
index 63e5225..23d4667 100644
--- a/tests/ref/fate/dds-xrgb
+++ b/tests/ref/fate/dds-xrgb
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x702f6a28
diff --git a/tests/ref/fate/dds-y b/tests/ref/fate/dds-y
index ae62091..9a8f01d 100644
--- a/tests/ref/fate/dds-y
+++ b/tests/ref/fate/dds-y
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x64
+#sar 0: 0/1
 0,          0,          0,        1,     8192, 0x56eca90f
diff --git a/tests/ref/fate/dds-ya b/tests/ref/fate/dds-ya
index d6527c6..a0f12b5 100644
--- a/tests/ref/fate/dds-ya
+++ b/tests/ref/fate/dds-ya
@@ -1,2 +1,6 @@
 #tb 0: 1/25
-0,          0,          0,        1,    28160, 0xd3981fcb
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 220x64
+#sar 0: 0/1
+0,          0,          0,        1,    28160, 0x5aa41fcb
diff --git a/tests/ref/fate/dds-ycocg b/tests/ref/fate/dds-ycocg
index f3dd727..6d22842 100644
--- a/tests/ref/fate/dds-ycocg
+++ b/tests/ref/fate/dds-ycocg
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x4cb08d0a
diff --git a/tests/ref/fate/dds-yuyv b/tests/ref/fate/dds-yuyv
index e65c950..07efd87 100644
--- a/tests/ref/fate/dds-yuyv
+++ b/tests/ref/fate/dds-yuyv
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,     8192, 0xc1108750
diff --git a/tests/ref/fate/delphine-cin-audio b/tests/ref/fate/delphine-cin-audio
index 1a94a6b..5a69640 100644
--- a/tests/ref/fate/delphine-cin-audio
+++ b/tests/ref/fate/delphine-cin-audio
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 4
 0,          0,          0,    88224,   176448, 0x541ddc55
 0,      88224,      88224,     1838,     3676, 0xaf455081
 0,      90062,      90062,     1838,     3676, 0x27ef4e91
diff --git a/tests/ref/fate/delphine-cin-video b/tests/ref/fate/delphine-cin-video
index feaea26..6d25164 100644
--- a/tests/ref/fate/delphine-cin-video
+++ b/tests/ref/fate/delphine-cin-video
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x160
+#sar 0: 0/1
 0,          0,          0,        1,   153600, 0x00000000
 0,          1,          1,        1,   153600, 0x9c77862c
 0,          2,          2,        1,   153600, 0xd487c33c
diff --git a/tests/ref/fate/deluxepaint-anm b/tests/ref/fate/deluxepaint-anm
index e69b95e..e466f25 100644
--- a/tests/ref/fate/deluxepaint-anm
+++ b/tests/ref/fate/deluxepaint-anm
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x82a79641
 0,          1,          1,        1,   192000, 0x43079971
 0,          2,          2,        1,   192000, 0x6311f1e5
diff --git a/tests/ref/fate/dfa1 b/tests/ref/fate/dfa1
index 7bc5bf1..3764391 100644
--- a/tests/ref/fate/dfa1
+++ b/tests/ref/fate/dfa1
@@ -1,4 +1,8 @@
 #tb 0: 16/125
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0xb69faa34
 0,          1,          1,        1,   921600, 0x38680829
 0,          2,          2,        1,   921600, 0xa7263c5a
diff --git a/tests/ref/fate/dfa10 b/tests/ref/fate/dfa10
index a799f03..8e0e3c9 100644
--- a/tests/ref/fate/dfa10
+++ b/tests/ref/fate/dfa10
@@ -1,4 +1,8 @@
 #tb 0: 71/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x7384f9b2
 0,          1,          1,        1,   192000, 0xd1f61c71
 0,          2,          2,        1,   192000, 0x0c6937d1
diff --git a/tests/ref/fate/dfa11 b/tests/ref/fate/dfa11
index 30b4b71..22571b5 100644
--- a/tests/ref/fate/dfa11
+++ b/tests/ref/fate/dfa11
@@ -1,4 +1,8 @@
 #tb 0: 71/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x4269d703
 0,          1,          1,        1,   192000, 0xdf8667e7
 0,          2,          2,        1,   192000, 0x450026ad
diff --git a/tests/ref/fate/dfa2 b/tests/ref/fate/dfa2
index cc4b454..0fd55b7 100644
--- a/tests/ref/fate/dfa2
+++ b/tests/ref/fate/dfa2
@@ -1,4 +1,8 @@
 #tb 0: 71/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0x8a5d15df
 0,          1,          1,        1,   921600, 0x92c01362
 0,          2,          2,        1,   921600, 0xe1a31643
diff --git a/tests/ref/fate/dfa3 b/tests/ref/fate/dfa3
index 9b170ec..417250c 100644
--- a/tests/ref/fate/dfa3
+++ b/tests/ref/fate/dfa3
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x236a1b54
 0,          1,          1,        1,   192000, 0xfb438b68
 0,          2,          2,        1,   192000, 0xde504563
diff --git a/tests/ref/fate/dfa4 b/tests/ref/fate/dfa4
index 0e0dc02..76a4ede 100644
--- a/tests/ref/fate/dfa4
+++ b/tests/ref/fate/dfa4
@@ -1,4 +1,8 @@
 #tb 0: 71/500
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0x00000000
 0,          1,          1,        1,   921600, 0xd9e060e3
 0,          2,          2,        1,   921600, 0x15e28dc7
diff --git a/tests/ref/fate/dfa5 b/tests/ref/fate/dfa5
index 3be3c52..c836bf7 100644
--- a/tests/ref/fate/dfa5
+++ b/tests/ref/fate/dfa5
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x9754890f
 0,          1,          1,        1,   192000, 0x01668965
 0,          2,          2,        1,   192000, 0xbd1b5e12
diff --git a/tests/ref/fate/dfa6 b/tests/ref/fate/dfa6
index 535f98b..83b1998 100644
--- a/tests/ref/fate/dfa6
+++ b/tests/ref/fate/dfa6
@@ -1,4 +1,8 @@
 #tb 0: 71/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0xb718dc63
 0,          1,          1,        1,   192000, 0x2efb7b89
 0,          2,          2,        1,   192000, 0x70827047
diff --git a/tests/ref/fate/dfa7 b/tests/ref/fate/dfa7
index 28122c5..6a62f72 100644
--- a/tests/ref/fate/dfa7
+++ b/tests/ref/fate/dfa7
@@ -1,4 +1,8 @@
 #tb 0: 71/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 46x57
+#sar 0: 0/1
 0,          0,          0,        1,     7866, 0xab73dae7
 0,          1,          1,        1,     7866, 0x100adec8
 0,          2,          2,        1,     7866, 0x1a20ddfa
diff --git a/tests/ref/fate/dfa8 b/tests/ref/fate/dfa8
index 866260a..7b83f3e 100644
--- a/tests/ref/fate/dfa8
+++ b/tests/ref/fate/dfa8
@@ -1,4 +1,8 @@
 #tb 0: 71/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 218x206
+#sar 0: 0/1
 0,          0,          0,        1,   134724, 0x53784ca9
 0,          1,          1,        1,   134724, 0x14c345b7
 0,          2,          2,        1,   134724, 0xe0d0dd51
diff --git a/tests/ref/fate/dfa9 b/tests/ref/fate/dfa9
index 99eb3f6..74b596f 100644
--- a/tests/ref/fate/dfa9
+++ b/tests/ref/fate/dfa9
@@ -1,4 +1,8 @@
 #tb 0: 71/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 338x225
+#sar 0: 0/1
 0,          0,          0,        1,   228150, 0xde68df49
 0,          1,          1,        1,   228150, 0x8e12bcaf
 0,          2,          2,        1,   228150, 0x851b04f7
diff --git a/tests/ref/fate/dirac b/tests/ref/fate/dirac
index 7781b4e..f3f3daf 100644
--- a/tests/ref/fate/dirac
+++ b/tests/ref/fate/dirac
@@ -1,3 +1,7 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   115200, 0xf73819e8
 0,          1,          1,        1,   115200, 0x082e3788
diff --git a/tests/ref/fate/display b/tests/ref/fate/display
new file mode 100644
index 0000000..251e7e0
--- /dev/null
+++ b/tests/ref/fate/display
@@ -0,0 +1,16 @@
+0 65536 0
+-65536 0 0
+0 0 1073741824
+degrees: -90.000000
+46340 -46340 0
+46340 46340 0
+0 0 1073741824
+degrees: 45.000000
+-46340 -46340 0
+-46340 46340 0
+0 0 1073741824
+degrees: 135.000000
+-46340 46340 0
+-46340 -46340 0
+0 0 1073741824
+degrees: -135.000000
diff --git a/tests/ref/fate/dnxhd-mbaff b/tests/ref/fate/dnxhd-mbaff
index 171c244..d694cfe 100644
--- a/tests/ref/fate/dnxhd-mbaff
+++ b/tests/ref/fate/dnxhd-mbaff
@@ -1,2 +1,6 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1440x1080
+#sar 0: 4/3
 0,          0,          0,        1,  6220800, 0xe78198c0
diff --git a/tests/ref/fate/dnxhr-444 b/tests/ref/fate/dnxhr-444
index f9e73c3..25f4219 100644
--- a/tests/ref/fate/dnxhr-444
+++ b/tests/ref/fate/dnxhr-444
@@ -1,2 +1,6 @@
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x839
+#sar 0: 0/1
 0,          0,          0,        1,  9665280, 0x19ef4057
diff --git a/tests/ref/fate/dnxhr-parse b/tests/ref/fate/dnxhr-parse
new file mode 100644
index 0000000..2fc5a47
--- /dev/null
+++ b/tests/ref/fate/dnxhr-parse
@@ -0,0 +1,9 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 3840x2160
+#sar 0: 0/1
+0,          0,          0,        1, 16588800, 0x67ebfdb1
+0,          1,          1,        1, 16588800, 0x7fa687e6
+0,          2,          2,        1, 16588800, 0x4e13f5eb
+0,          3,          3,        1, 16588800, 0x054a642d
diff --git a/tests/ref/fate/dpcm-idroq b/tests/ref/fate/dpcm-idroq
index 85e8efb..39f2c79 100644
--- a/tests/ref/fate/dpcm-idroq
+++ b/tests/ref/fate/dpcm-idroq
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,     7456,    29824, 0x77e265b7
 0,       7456,       7456,      736,     2944, 0x8dcdf50b
 0,       8192,       8192,      736,     2944, 0xb135cd2a
diff --git a/tests/ref/fate/dpcm-interplay b/tests/ref/fate/dpcm-interplay
index bda8a8f..87a2862 100644
--- a/tests/ref/fate/dpcm-interplay
+++ b/tests/ref/fate/dpcm-interplay
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,     1462,     5848, 0xea04292b
 0,       1462,       1462,     1472,     5888, 0x0e59e942
 0,       2934,       2934,     1472,     5888, 0x56d480f6
diff --git a/tests/ref/fate/dpx b/tests/ref/fate/dpx
index fdb85ca..d5f0ecb 100644
--- a/tests/ref/fate/dpx
+++ b/tests/ref/fate/dpx
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 768x512
+#sar 0: 0/1
 0,          0,          0,        1,  2359296, 0x30d4d24f
diff --git a/tests/ref/fate/dpxparser b/tests/ref/fate/dpxparser
index 0ecc36c..c21ad74 100644
--- a/tests/ref/fate/dpxparser
+++ b/tests/ref/fate/dpxparser
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 130x130
+#sar 0: 0/1
 0,          0,          0,        1,    50700, 0xe7153545
 0,          1,          1,        1,    50700, 0x2bc92ece
 0,          2,          2,        1,    50700, 0x83c731bb
diff --git a/tests/ref/fate/dss-lp b/tests/ref/fate/dss-lp
index b5bee18..6b5a7db 100644
--- a/tests/ref/fate/dss-lp
+++ b/tests/ref/fate/dss-lp
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      240,      480, 0xf1107658
 0,        240,        240,      240,      480, 0x50dee179
 0,        480,        480,      240,      480, 0x40090802
diff --git a/tests/ref/fate/dss-sp b/tests/ref/fate/dss-sp
index 111c621..5caa469 100644
--- a/tests/ref/fate/dss-sp
+++ b/tests/ref/fate/dss-sp
@@ -1,4 +1,8 @@
 #tb 0: 1/11025
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 11025
+#channel_layout 0: 4
 0,          0,          0,      264,      528, 0xa2579e96
 0,        264,        264,      264,      528, 0xf9b23172
 0,        528,        528,      264,      528, 0x5571a0fe
diff --git a/tests/ref/fate/dxa-feeble b/tests/ref/fate/dxa-feeble
index 74b43dc..5fa4175 100644
--- a/tests/ref/fate/dxa-feeble
+++ b/tests/ref/fate/dxa-feeble
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0x0d03844f
 0,          1,          1,        1,   921600, 0x0d03844f
 0,          2,          2,        1,   921600, 0x649cdcea
diff --git a/tests/ref/fate/dxa-scummvm b/tests/ref/fate/dxa-scummvm
index 308a896..e8817cb 100644
--- a/tests/ref/fate/dxa-scummvm
+++ b/tests/ref/fate/dxa-scummvm
@@ -1,4 +1,8 @@
 #tb 0: 8333/100000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x200
+#sar 0: 0/1
 0,          0,          0,        1,   384000, 0xef37f34b
 0,          1,          1,        1,   384000, 0xef37f34b
 0,          2,          2,        1,   384000, 0xfca3cd8b
diff --git a/tests/ref/fate/dxtory b/tests/ref/fate/dxtory
index 7d3ecbd..4ebcaf6 100644
--- a/tests/ref/fate/dxtory
+++ b/tests/ref/fate/dxtory
@@ -1,3 +1,6 @@
 #tb 0: 1/25
-#tb 1: 1/48000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  1382400, 0x44373645
diff --git a/tests/ref/fate/dxv-dxt1 b/tests/ref/fate/dxv-dxt1
index 128daba..d9f5ece 100644
--- a/tests/ref/fate/dxv-dxt1
+++ b/tests/ref/fate/dxv-dxt1
@@ -1,2 +1,6 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x0797cd53
diff --git a/tests/ref/fate/dxv-dxt5 b/tests/ref/fate/dxv-dxt5
index 128daba..d9f5ece 100644
--- a/tests/ref/fate/dxv-dxt5
+++ b/tests/ref/fate/dxv-dxt5
@@ -1,2 +1,6 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x0797cd53
diff --git a/tests/ref/fate/dxv3-dxt1 b/tests/ref/fate/dxv3-dxt1
index e0f1f94..96ce669 100644
--- a/tests/ref/fate/dxv3-dxt1
+++ b/tests/ref/fate/dxv3-dxt1
@@ -1,2 +1,6 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x98bbcc85
diff --git a/tests/ref/fate/dxv3-dxt5 b/tests/ref/fate/dxv3-dxt5
index 128daba..d9f5ece 100644
--- a/tests/ref/fate/dxv3-dxt5
+++ b/tests/ref/fate/dxv3-dxt5
@@ -1,2 +1,6 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x0797cd53
diff --git a/tests/ref/fate/ea-cmv b/tests/ref/fate/ea-cmv
index 8f9049e..793cb84 100644
--- a/tests/ref/fate/ea-cmv
+++ b/tests/ref/fate/ea-cmv
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x200
+#sar 0: 0/1
 0,          0,          0,        1,   120000, 0x34ac91d2
 0,          1,          1,        1,   120000, 0x17150729
 0,          2,          2,        1,   120000, 0xc3f510bb
diff --git a/tests/ref/fate/ea-mad b/tests/ref/fate/ea-mad
index 1ea92fd..ea92fe1 100644
--- a/tests/ref/fate/ea-mad
+++ b/tests/ref/fate/ea-mad
@@ -1,4 +1,8 @@
 #tb 0: 33/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x496
+#sar 0: 0/1
 0,          0,          0,        1,   535680, 0x889c32cf
 0,          1,          1,        1,   535680, 0x0b1ef044
 0,          2,          2,        1,   535680, 0xa7d0818b
diff --git a/tests/ref/fate/ea-tgq b/tests/ref/fate/ea-tgq
index 5c0648d..2f38e71 100644
--- a/tests/ref/fate/ea-tgq
+++ b/tests/ref/fate/ea-tgq
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 208x112
+#sar 0: 0/1
 0,          0,          0,        1,    34944, 0xe33671a4
 0,          1,          1,        1,    34944, 0xe33671a4
 0,          2,          2,        1,    34944, 0xe33671a4
diff --git a/tests/ref/fate/ea-tgv-1 b/tests/ref/fate/ea-tgv-1
index fc92181..7533af0 100644
--- a/tests/ref/fate/ea-tgv-1
+++ b/tests/ref/fate/ea-tgv-1
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0xfbf2581e
 0,          1,          1,        1,   230400, 0xfbf2581e
 0,          2,          2,        1,   230400, 0xfbf2581e
diff --git a/tests/ref/fate/ea-tgv-2 b/tests/ref/fate/ea-tgv-2
index 5e9de02..cfa100f 100644
--- a/tests/ref/fate/ea-tgv-2
+++ b/tests/ref/fate/ea-tgv-2
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0xdfc2f225
 0,          1,          1,        1,   192000, 0x059b57bd
 0,          2,          2,        1,   192000, 0x766cb086
diff --git a/tests/ref/fate/ea-tqi b/tests/ref/fate/ea-tqi
index 72afb81..926ab6d 100644
--- a/tests/ref/fate/ea-tqi
+++ b/tests/ref/fate/ea-tqi
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 400x192
+#sar 0: 0/1
 0,          0,          0,        1,   115200, 0x375ec573
 0,          1,          1,        1,   115200, 0x375ec573
 0,          2,          2,        1,   115200, 0x375ec573
diff --git a/tests/ref/fate/eval b/tests/ref/fate/eval
index 914b13c..5b4d93f 100644
--- a/tests/ref/fate/eval
+++ b/tests/ref/fate/eval
@@ -1,6 +1,7 @@
 Evaluating ''
 '' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating '1;2'
 '1;2' -> 2.000000
 
@@ -28,45 +29,58 @@ Evaluating '1Gi'
 Evaluating '1gi'
 '1gi' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating '1GiFoo'
 '1GiFoo' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating '1k+1k'
 '1k+1k' -> 2000.000000
 
 Evaluating '1Gi*3foo'
 '1Gi*3foo' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'foo'
 'foo' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'foo('
 'foo(' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'foo()'
 'foo()' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'foo)'
 'foo)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'sin'
 'sin' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'sin('
 'sin(' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'sin()'
 'sin()' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'sin)'
 'sin)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'sin 10'
 'sin 10' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'sin(1,2,3)'
 'sin(1,2,3)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'sin(1 )'
 'sin(1 )' -> 0.841471
 
@@ -76,15 +90,19 @@ Evaluating '1'
 Evaluating '1foo'
 '1foo' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'bar + PI + E + 100f*2 + foo'
 'bar + PI + E + 100f*2 + foo' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating '13k + 12f - foo(1, 2)'
 '13k + 12f - foo(1, 2)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating '1gi'
 '1gi' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating '1Gi'
 '1Gi' -> 1073741824.000000
 
@@ -127,6 +145,7 @@ Evaluating 'st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)
 Evaluating 'while(0, 10)'
 'while(0, 10)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))'
 'st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))' -> 101.000000
 
@@ -151,6 +170,7 @@ Evaluating 'isinf(INF)'
 Evaluating 'floor(NAN)'
 'floor(NAN)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'floor(123.123)'
 'floor(123.123)' -> 123.000000
 
@@ -202,6 +222,7 @@ Evaluating 'PI^1.23'
 Evaluating 'pow(-1,1.23)'
 'pow(-1,1.23)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'if(1, 2)'
 'if(1, 2)' -> 2.000000
 
@@ -259,6 +280,7 @@ Evaluating 'bitand(42, 12)'
 Evaluating 'bitand(NAN, 1)'
 'bitand(NAN, 1)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'between(10, -3, 10)'
 'between(10, -3, 10)' -> 1.000000
 
@@ -268,14 +290,18 @@ Evaluating 'between(-4, -2, -1)'
 Evaluating 'between(1,2)'
 'between(1,2)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'clip(0, 2, 1)'
 'clip(0, 2, 1)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'clip(0/0, 1, 2)'
 'clip(0/0, 1, 2)' -> nan
 
+av_expr_parse_and_eval failed
 Evaluating 'clip(0, 0/0, 1)'
 'clip(0, 0/0, 1)' -> nan
 
+av_expr_parse_and_eval failed
 12.700000 == 12.7
 0.931323 == 0.931322575
diff --git a/tests/ref/fate/exr-rgb-scanline-float-b44 b/tests/ref/fate/exr-rgb-scanline-float-b44
new file mode 100644
index 0000000..91b0e1f
--- /dev/null
+++ b/tests/ref/fate/exr-rgb-scanline-float-b44
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 12x8
+#sar 0: 1/1
+0,          0,          0,        1,      576, 0x39c8e03e
diff --git a/tests/ref/fate/exr-rgb-scanline-half-b44-12x8 b/tests/ref/fate/exr-rgb-scanline-half-b44-12x8
new file mode 100644
index 0000000..8464203
--- /dev/null
+++ b/tests/ref/fate/exr-rgb-scanline-half-b44-12x8
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 12x8
+#sar 0: 1/1
+0,          0,          0,        1,      576, 0x506469f9
diff --git a/tests/ref/fate/exr-rgb-scanline-half-b44-13x9 b/tests/ref/fate/exr-rgb-scanline-half-b44-13x9
new file mode 100644
index 0000000..675d2f0
--- /dev/null
+++ b/tests/ref/fate/exr-rgb-scanline-half-b44-13x9
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 13x9
+#sar 0: 1/1
+0,          0,          0,        1,      702, 0x6914838a
diff --git a/tests/ref/fate/exr-rgb-scanline-pxr24-float-12x8 b/tests/ref/fate/exr-rgb-scanline-pxr24-float-12x8
new file mode 100644
index 0000000..13946d8
--- /dev/null
+++ b/tests/ref/fate/exr-rgb-scanline-pxr24-float-12x8
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 12x8
+#sar 0: 1/1
+0,          0,          0,        1,      576, 0x7120e072
diff --git a/tests/ref/fate/exr-rgb-tile-float-raw-12x8 b/tests/ref/fate/exr-rgb-tile-float-raw-12x8
new file mode 100644
index 0000000..abe41b8
--- /dev/null
+++ b/tests/ref/fate/exr-rgb-tile-float-raw-12x8
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 12x8
+#sar 0: 1/1
+0,          0,          0,        1,      576, 0x6b950ce3
diff --git a/tests/ref/fate/exr-rgb-tile-float-raw-150x130 b/tests/ref/fate/exr-rgb-tile-float-raw-150x130
new file mode 100644
index 0000000..3ac5c28
--- /dev/null
+++ b/tests/ref/fate/exr-rgb-tile-float-raw-150x130
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 150x130
+#sar 0: 1/1
+0,          0,          0,        1,   117000, 0xabc5eab2
diff --git a/tests/ref/fate/exr-rgb-tile-half-raw-12x8 b/tests/ref/fate/exr-rgb-tile-half-raw-12x8
new file mode 100644
index 0000000..f59e248
--- /dev/null
+++ b/tests/ref/fate/exr-rgb-tile-half-raw-12x8
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 12x8
+#sar 0: 1/1
+0,          0,          0,        1,      576, 0x667903f5
diff --git a/tests/ref/fate/exr-rgba-multiscanline-half-b44 b/tests/ref/fate/exr-rgba-multiscanline-half-b44
new file mode 100644
index 0000000..4b9a88b
--- /dev/null
+++ b/tests/ref/fate/exr-rgba-multiscanline-half-b44
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 935x251
+#sar 0: 1/1
+0,          0,          0,        1,  1877480, 0x6f28b860
diff --git a/tests/ref/fate/exr-slice-pxr24 b/tests/ref/fate/exr-slice-pxr24
index c46e897..99fbc05 100644
--- a/tests/ref/fate/exr-slice-pxr24
+++ b/tests/ref/fate/exr-slice-pxr24
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 800x800
+#sar 0: 1/1
 0,          0,          0,        1,  3840000, 0xdcfb341d
diff --git a/tests/ref/fate/exr-slice-raw b/tests/ref/fate/exr-slice-raw
index a8b4b27..cbe124b 100644
--- a/tests/ref/fate/exr-slice-raw
+++ b/tests/ref/fate/exr-slice-raw
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 587x675
+#sar 0: 1/1
 0,          0,          0,        1,  3169800, 0x6a356d0d
diff --git a/tests/ref/fate/exr-slice-rle b/tests/ref/fate/exr-slice-rle
index a8b4b27..cbe124b 100644
--- a/tests/ref/fate/exr-slice-rle
+++ b/tests/ref/fate/exr-slice-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 587x675
+#sar 0: 1/1
 0,          0,          0,        1,  3169800, 0x6a356d0d
diff --git a/tests/ref/fate/exr-slice-zip1 b/tests/ref/fate/exr-slice-zip1
index a8b4b27..cbe124b 100644
--- a/tests/ref/fate/exr-slice-zip1
+++ b/tests/ref/fate/exr-slice-zip1
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 587x675
+#sar 0: 1/1
 0,          0,          0,        1,  3169800, 0x6a356d0d
diff --git a/tests/ref/fate/exr-slice-zip16 b/tests/ref/fate/exr-slice-zip16
index a8b4b27..cbe124b 100644
--- a/tests/ref/fate/exr-slice-zip16
+++ b/tests/ref/fate/exr-slice-zip16
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 587x675
+#sar 0: 1/1
 0,          0,          0,        1,  3169800, 0x6a356d0d
diff --git a/tests/ref/fate/ffmpeg-filter_colorkey b/tests/ref/fate/ffmpeg-filter_colorkey
index 0e4780b..9fbdfeb 100644
--- a/tests/ref/fate/ffmpeg-filter_colorkey
+++ b/tests/ref/fate/ffmpeg-filter_colorkey
@@ -1,5 +1,13 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 0/1
 #tb 1: 1/48000
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 48000
+#channel_layout 1: 3
 0,          0,          0,        1,   622080, 0x4e30accb
 1,          0,          0,     1152,     4608, 0x00000000
 1,       1152,       1152,     1152,     4608, 0xbca29063
diff --git a/tests/ref/fate/ffmpeg-filter_complex b/tests/ref/fate/ffmpeg-filter_complex
index 54d318d..d85a4aa 100644
--- a/tests/ref/fate/ffmpeg-filter_complex
+++ b/tests/ref/fate/ffmpeg-filter_complex
@@ -1,4 +1,8 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   115200, 0x375ec573
 0,          1,          1,        1,   115200, 0x375ec573
 0,          2,          2,        1,   115200, 0x375ec573
diff --git a/tests/ref/fate/ffmpeg-lavfi b/tests/ref/fate/ffmpeg-lavfi
index 54d318d..d85a4aa 100644
--- a/tests/ref/fate/ffmpeg-lavfi
+++ b/tests/ref/fate/ffmpeg-lavfi
@@ -1,4 +1,8 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   115200, 0x375ec573
 0,          1,          1,        1,   115200, 0x375ec573
 0,          2,          2,        1,   115200, 0x375ec573
diff --git a/tests/ref/fate/ffprobe_compact b/tests/ref/fate/ffprobe_compact
index 0d9ef30..d529bb6 100644
--- a/tests/ref/fate/ffprobe_compact
+++ b/tests/ref/fate/ffprobe_compact
@@ -1,32 +1,32 @@
-packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=642|flags=K
-frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=642|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
-packet|codec_type=video|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=2717|flags=K
-frame|media_type=video|stream_index=1|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=2717|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
-packet|codec_type=video|stream_index=2|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=233138|flags=K
-frame|media_type=video|stream_index=2|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=233138|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
-packet|codec_type=audio|stream_index=0|pts=1024|pts_time=0.023220|dts=1024|dts_time=0.023220|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=263143|flags=K
-frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=1024|pkt_pts_time=0.023220|pkt_dts=1024|pkt_dts_time=0.023220|best_effort_timestamp=1024|best_effort_timestamp_time=0.023220|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=263143|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
-packet|codec_type=video|stream_index=1|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=265221|flags=K
-frame|media_type=video|stream_index=1|key_frame=1|pkt_pts=2048|pkt_pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=265221|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
-packet|codec_type=video|stream_index=2|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=495645|flags=K
-frame|media_type=video|stream_index=2|key_frame=1|pkt_pts=2048|pkt_pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=495645|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
-packet|codec_type=audio|stream_index=0|pts=2048|pts_time=0.046440|dts=2048|dts_time=0.046440|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=525650|flags=K
-frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=2048|pkt_pts_time=0.046440|pkt_dts=2048|pkt_dts_time=0.046440|best_effort_timestamp=2048|best_effort_timestamp_time=0.046440|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=525650|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
-packet|codec_type=audio|stream_index=0|pts=3072|pts_time=0.069660|dts=3072|dts_time=0.069660|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=527721|flags=K
-frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=3072|pkt_pts_time=0.069660|pkt_dts=3072|pkt_dts_time=0.069660|best_effort_timestamp=3072|best_effort_timestamp_time=0.069660|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=527721|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
-packet|codec_type=video|stream_index=1|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=529799|flags=K
-frame|media_type=video|stream_index=1|key_frame=1|pkt_pts=4096|pkt_pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=529799|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
-packet|codec_type=video|stream_index=2|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=760223|flags=K
-frame|media_type=video|stream_index=2|key_frame=1|pkt_pts=4096|pkt_pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=760223|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
-packet|codec_type=audio|stream_index=0|pts=4096|pts_time=0.092880|dts=4096|dts_time=0.092880|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=790228|flags=K
-frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=4096|pkt_pts_time=0.092880|pkt_dts=4096|pkt_dts_time=0.092880|best_effort_timestamp=4096|best_effort_timestamp_time=0.092880|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=790228|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
-packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=792299|flags=K
-frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=5120|pkt_pts_time=0.116100|pkt_dts=5120|pkt_dts_time=0.116100|best_effort_timestamp=5120|best_effort_timestamp_time=0.116100|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=792299|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
-packet|codec_type=video|stream_index=1|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=794377|flags=K
-frame|media_type=video|stream_index=1|key_frame=1|pkt_pts=6144|pkt_pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=794377|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
-packet|codec_type=video|stream_index=2|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=1024801|flags=K
-frame|media_type=video|stream_index=2|key_frame=1|pkt_pts=6144|pkt_pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=1024801|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
+packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=647|flags=K
+frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=647|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
+packet|codec_type=video|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=2722|flags=K
+frame|media_type=video|stream_index=1|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=2722|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
+packet|codec_type=video|stream_index=2|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=233143|flags=K
+frame|media_type=video|stream_index=2|key_frame=1|pkt_pts=0|pkt_pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=233143|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
+packet|codec_type=audio|stream_index=0|pts=1024|pts_time=0.023220|dts=1024|dts_time=0.023220|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=263148|flags=K
+frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=1024|pkt_pts_time=0.023220|pkt_dts=1024|pkt_dts_time=0.023220|best_effort_timestamp=1024|best_effort_timestamp_time=0.023220|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=263148|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
+packet|codec_type=video|stream_index=1|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=265226|flags=K
+frame|media_type=video|stream_index=1|key_frame=1|pkt_pts=2048|pkt_pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=265226|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
+packet|codec_type=video|stream_index=2|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=495650|flags=K
+frame|media_type=video|stream_index=2|key_frame=1|pkt_pts=2048|pkt_pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=495650|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
+packet|codec_type=audio|stream_index=0|pts=2048|pts_time=0.046440|dts=2048|dts_time=0.046440|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=525655|flags=K
+frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=2048|pkt_pts_time=0.046440|pkt_dts=2048|pkt_dts_time=0.046440|best_effort_timestamp=2048|best_effort_timestamp_time=0.046440|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=525655|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
+packet|codec_type=audio|stream_index=0|pts=3072|pts_time=0.069660|dts=3072|dts_time=0.069660|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=527726|flags=K
+frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=3072|pkt_pts_time=0.069660|pkt_dts=3072|pkt_dts_time=0.069660|best_effort_timestamp=3072|best_effort_timestamp_time=0.069660|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=527726|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
+packet|codec_type=video|stream_index=1|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=529804|flags=K
+frame|media_type=video|stream_index=1|key_frame=1|pkt_pts=4096|pkt_pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=529804|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
+packet|codec_type=video|stream_index=2|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=760228|flags=K
+frame|media_type=video|stream_index=2|key_frame=1|pkt_pts=4096|pkt_pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=760228|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
+packet|codec_type=audio|stream_index=0|pts=4096|pts_time=0.092880|dts=4096|dts_time=0.092880|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=790233|flags=K
+frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=4096|pkt_pts_time=0.092880|pkt_dts=4096|pkt_dts_time=0.092880|best_effort_timestamp=4096|best_effort_timestamp_time=0.092880|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=790233|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
+packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=1024|duration_time=0.023220|convergence_duration=N/A|convergence_duration_time=N/A|size=2048|pos=792304|flags=K
+frame|media_type=audio|stream_index=0|key_frame=1|pkt_pts=5120|pkt_pts_time=0.116100|pkt_dts=5120|pkt_dts_time=0.116100|best_effort_timestamp=5120|best_effort_timestamp_time=0.116100|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=792304|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
+packet|codec_type=video|stream_index=1|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=230400|pos=794382|flags=K
+frame|media_type=video|stream_index=1|key_frame=1|pkt_pts=6144|pkt_pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=794382|pkt_size=230400|width=320|height=240|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
+packet|codec_type=video|stream_index=2|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|convergence_duration=N/A|convergence_duration_time=N/A|size=30000|pos=1024806|flags=K
+frame|media_type=video|stream_index=2|key_frame=1|pkt_pts=6144|pkt_pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=1024806|pkt_size=30000|width=100|height=100|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0
 stream|index=0|codec_name=pcm_s16le|profile=unknown|codec_type=audio|codec_time_base=1/44100|codec_tag_string=PSD[16]|codec_tag=0x10445350|sample_fmt=s16|sample_rate=44100|channels=1|channel_layout=unknown|bits_per_sample=16|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/44100|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=705600|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=6|nb_read_packets=6|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:E=mc²|tag:encoder=Lavc pcm_s16le
-stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_time_base=1/51200|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|coded_width=320|coded_height=240|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=4:3|pix_fmt=rgb24|level=-99|color_range=N/A|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|timecode=N/A|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:title=foobar|tag:duration_ts=field-and-tags-conflict-attempt|tag:encoder=Lavc rawvideo
-stream|index=2|codec_name=rawvideo|profile=unknown|codec_type=video|codec_time_base=1/51200|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=100|height=100|coded_width=100|coded_height=100|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=1:1|pix_fmt=rgb24|level=-99|color_range=N/A|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|timecode=N/A|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:encoder=Lavc rawvideo
-format|filename=tests/data/ffprobe-test.nut|nb_streams=3|nb_programs=0|format_name=nut|start_time=0.000000|duration=0.120000|size=1054882|bit_rate=70325466|probe_score=100|tag:title=ffprobe test file|tag:comment='A comment with CSV, XML & JSON special chars': <tag value="x">|tag:comment2=I ♥ Üñîçød€
+stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_time_base=1/25|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|coded_width=320|coded_height=240|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=4:3|pix_fmt=rgb24|level=-99|color_range=N/A|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|timecode=N/A|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:title=foobar|tag:duration_ts=field-and-tags-conflict-attempt|tag:encoder=Lavc rawvideo
+stream|index=2|codec_name=rawvideo|profile=unknown|codec_type=video|codec_time_base=1/25|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=100|height=100|coded_width=100|coded_height=100|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=1:1|pix_fmt=rgb24|level=-99|color_range=N/A|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|timecode=N/A|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|tag:encoder=Lavc rawvideo
+format|filename=tests/data/ffprobe-test.nut|nb_streams=3|nb_programs=0|format_name=nut|start_time=0.000000|duration=0.120000|size=1054887|bit_rate=70325800|probe_score=100|tag:title=ffprobe test file|tag:comment='A comment with CSV, XML & JSON special chars': <tag value="x">|tag:comment2=I ♥ Üñîçød€
diff --git a/tests/ref/fate/ffprobe_csv b/tests/ref/fate/ffprobe_csv
index 9186eba..882c1b8 100644
--- a/tests/ref/fate/ffprobe_csv
+++ b/tests/ref/fate/ffprobe_csv
@@ -1,32 +1,32 @@
-packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,N/A,N/A,2048,642,K
-frame,audio,0,1,0,0.000000,0,0.000000,0,0.000000,1024,0.023220,642,2048,s16,1024,1,unknown
-packet,video,1,0,0.000000,0,0.000000,2048,0.040000,N/A,N/A,230400,2717,K
-frame,video,1,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2717,230400,320,240,rgb24,1:1,I,0,0,0,0,0
-packet,video,2,0,0.000000,0,0.000000,2048,0.040000,N/A,N/A,30000,233138,K
-frame,video,2,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233138,30000,100,100,rgb24,1:1,I,0,0,0,0,0
-packet,audio,0,1024,0.023220,1024,0.023220,1024,0.023220,N/A,N/A,2048,263143,K
-frame,audio,0,1,1024,0.023220,1024,0.023220,1024,0.023220,1024,0.023220,263143,2048,s16,1024,1,unknown
-packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,N/A,N/A,230400,265221,K
-frame,video,1,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265221,230400,320,240,rgb24,1:1,I,0,0,0,0,0
-packet,video,2,2048,0.040000,2048,0.040000,2048,0.040000,N/A,N/A,30000,495645,K
-frame,video,2,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495645,30000,100,100,rgb24,1:1,I,0,0,0,0,0
-packet,audio,0,2048,0.046440,2048,0.046440,1024,0.023220,N/A,N/A,2048,525650,K
-frame,audio,0,1,2048,0.046440,2048,0.046440,2048,0.046440,1024,0.023220,525650,2048,s16,1024,1,unknown
-packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,N/A,N/A,2048,527721,K
-frame,audio,0,1,3072,0.069660,3072,0.069660,3072,0.069660,1024,0.023220,527721,2048,s16,1024,1,unknown
-packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,N/A,N/A,230400,529799,K
-frame,video,1,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529799,230400,320,240,rgb24,1:1,I,0,0,0,0,0
-packet,video,2,4096,0.080000,4096,0.080000,2048,0.040000,N/A,N/A,30000,760223,K
-frame,video,2,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760223,30000,100,100,rgb24,1:1,I,0,0,0,0,0
-packet,audio,0,4096,0.092880,4096,0.092880,1024,0.023220,N/A,N/A,2048,790228,K
-frame,audio,0,1,4096,0.092880,4096,0.092880,4096,0.092880,1024,0.023220,790228,2048,s16,1024,1,unknown
-packet,audio,0,5120,0.116100,5120,0.116100,1024,0.023220,N/A,N/A,2048,792299,K
-frame,audio,0,1,5120,0.116100,5120,0.116100,5120,0.116100,1024,0.023220,792299,2048,s16,1024,1,unknown
-packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,N/A,N/A,230400,794377,K
-frame,video,1,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,794377,230400,320,240,rgb24,1:1,I,0,0,0,0,0
-packet,video,2,6144,0.120000,6144,0.120000,2048,0.040000,N/A,N/A,30000,1024801,K
-frame,video,2,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1024801,30000,100,100,rgb24,1:1,I,0,0,0,0,0
+packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,N/A,N/A,2048,647,K
+frame,audio,0,1,0,0.000000,0,0.000000,0,0.000000,1024,0.023220,647,2048,s16,1024,1,unknown
+packet,video,1,0,0.000000,0,0.000000,2048,0.040000,N/A,N/A,230400,2722,K
+frame,video,1,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2722,230400,320,240,rgb24,1:1,I,0,0,0,0,0
+packet,video,2,0,0.000000,0,0.000000,2048,0.040000,N/A,N/A,30000,233143,K
+frame,video,2,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233143,30000,100,100,rgb24,1:1,I,0,0,0,0,0
+packet,audio,0,1024,0.023220,1024,0.023220,1024,0.023220,N/A,N/A,2048,263148,K
+frame,audio,0,1,1024,0.023220,1024,0.023220,1024,0.023220,1024,0.023220,263148,2048,s16,1024,1,unknown
+packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,N/A,N/A,230400,265226,K
+frame,video,1,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265226,230400,320,240,rgb24,1:1,I,0,0,0,0,0
+packet,video,2,2048,0.040000,2048,0.040000,2048,0.040000,N/A,N/A,30000,495650,K
+frame,video,2,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495650,30000,100,100,rgb24,1:1,I,0,0,0,0,0
+packet,audio,0,2048,0.046440,2048,0.046440,1024,0.023220,N/A,N/A,2048,525655,K
+frame,audio,0,1,2048,0.046440,2048,0.046440,2048,0.046440,1024,0.023220,525655,2048,s16,1024,1,unknown
+packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,N/A,N/A,2048,527726,K
+frame,audio,0,1,3072,0.069660,3072,0.069660,3072,0.069660,1024,0.023220,527726,2048,s16,1024,1,unknown
+packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,N/A,N/A,230400,529804,K
+frame,video,1,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529804,230400,320,240,rgb24,1:1,I,0,0,0,0,0
+packet,video,2,4096,0.080000,4096,0.080000,2048,0.040000,N/A,N/A,30000,760228,K
+frame,video,2,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760228,30000,100,100,rgb24,1:1,I,0,0,0,0,0
+packet,audio,0,4096,0.092880,4096,0.092880,1024,0.023220,N/A,N/A,2048,790233,K
+frame,audio,0,1,4096,0.092880,4096,0.092880,4096,0.092880,1024,0.023220,790233,2048,s16,1024,1,unknown
+packet,audio,0,5120,0.116100,5120,0.116100,1024,0.023220,N/A,N/A,2048,792304,K
+frame,audio,0,1,5120,0.116100,5120,0.116100,5120,0.116100,1024,0.023220,792304,2048,s16,1024,1,unknown
+packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,N/A,N/A,230400,794382,K
+frame,video,1,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,794382,230400,320,240,rgb24,1:1,I,0,0,0,0,0
+packet,video,2,6144,0.120000,6144,0.120000,2048,0.040000,N/A,N/A,30000,1024806,K
+frame,video,2,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1024806,30000,100,100,rgb24,1:1,I,0,0,0,0,0
 stream,0,pcm_s16le,unknown,audio,1/44100,PSD[16],0x10445350,s16,44100,1,unknown,16,N/A,0/0,0/0,1/44100,0,0.000000,N/A,N/A,705600,N/A,N/A,N/A,6,6,0,0,0,0,0,0,0,0,0,0,0,mc²,Lavc pcm_s16le
-stream,1,rawvideo,unknown,video,1/51200,RGB[24],0x18424752,320,240,320,240,0,1:1,4:3,rgb24,-99,N/A,unknown,unknown,unknown,unspecified,N/A,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,foobar,field-and-tags-conflict-attempt,Lavc rawvideo
-stream,2,rawvideo,unknown,video,1/51200,RGB[24],0x18424752,100,100,100,100,0,1:1,1:1,rgb24,-99,N/A,unknown,unknown,unknown,unspecified,N/A,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,Lavc rawvideo
-format,tests/data/ffprobe-test.nut,3,0,nut,0.000000,0.120000,1054882,70325466,100,ffprobe test file,"'A comment with CSV, XML & JSON special chars': <tag value=""x"">",I ♥ Üñîçød€
+stream,1,rawvideo,unknown,video,1/25,RGB[24],0x18424752,320,240,320,240,0,1:1,4:3,rgb24,-99,N/A,unknown,unknown,unknown,unspecified,N/A,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,foobar,field-and-tags-conflict-attempt,Lavc rawvideo
+stream,2,rawvideo,unknown,video,1/25,RGB[24],0x18424752,100,100,100,100,0,1:1,1:1,rgb24,-99,N/A,unknown,unknown,unknown,unspecified,N/A,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,Lavc rawvideo
+format,tests/data/ffprobe-test.nut,3,0,nut,0.000000,0.120000,1054887,70325800,100,ffprobe test file,"'A comment with CSV, XML & JSON special chars': <tag value=""x"">",I ♥ Üñîçød€
diff --git a/tests/ref/fate/ffprobe_default b/tests/ref/fate/ffprobe_default
index df97796..4adb330 100644
--- a/tests/ref/fate/ffprobe_default
+++ b/tests/ref/fate/ffprobe_default
@@ -10,7 +10,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=642
+pos=647
 flags=K
 [/PACKET]
 [FRAME]
@@ -25,7 +25,7 @@ best_effort_timestamp=0
 best_effort_timestamp_time=0.000000
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=642
+pkt_pos=647
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -44,7 +44,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=230400
-pos=2717
+pos=2722
 flags=K
 [/PACKET]
 [FRAME]
@@ -59,7 +59,7 @@ best_effort_timestamp=0
 best_effort_timestamp_time=0.000000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=2717
+pkt_pos=2722
 pkt_size=230400
 width=320
 height=240
@@ -84,7 +84,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=30000
-pos=233138
+pos=233143
 flags=K
 [/PACKET]
 [FRAME]
@@ -99,7 +99,7 @@ best_effort_timestamp=0
 best_effort_timestamp_time=0.000000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=233138
+pkt_pos=233143
 pkt_size=30000
 width=100
 height=100
@@ -124,7 +124,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=263143
+pos=263148
 flags=K
 [/PACKET]
 [FRAME]
@@ -139,7 +139,7 @@ best_effort_timestamp=1024
 best_effort_timestamp_time=0.023220
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=263143
+pkt_pos=263148
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -158,7 +158,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=230400
-pos=265221
+pos=265226
 flags=K
 [/PACKET]
 [FRAME]
@@ -173,7 +173,7 @@ best_effort_timestamp=2048
 best_effort_timestamp_time=0.040000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=265221
+pkt_pos=265226
 pkt_size=230400
 width=320
 height=240
@@ -198,7 +198,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=30000
-pos=495645
+pos=495650
 flags=K
 [/PACKET]
 [FRAME]
@@ -213,7 +213,7 @@ best_effort_timestamp=2048
 best_effort_timestamp_time=0.040000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=495645
+pkt_pos=495650
 pkt_size=30000
 width=100
 height=100
@@ -238,7 +238,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=525650
+pos=525655
 flags=K
 [/PACKET]
 [FRAME]
@@ -253,7 +253,7 @@ best_effort_timestamp=2048
 best_effort_timestamp_time=0.046440
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=525650
+pkt_pos=525655
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -272,7 +272,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=527721
+pos=527726
 flags=K
 [/PACKET]
 [FRAME]
@@ -287,7 +287,7 @@ best_effort_timestamp=3072
 best_effort_timestamp_time=0.069660
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=527721
+pkt_pos=527726
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -306,7 +306,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=230400
-pos=529799
+pos=529804
 flags=K
 [/PACKET]
 [FRAME]
@@ -321,7 +321,7 @@ best_effort_timestamp=4096
 best_effort_timestamp_time=0.080000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=529799
+pkt_pos=529804
 pkt_size=230400
 width=320
 height=240
@@ -346,7 +346,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=30000
-pos=760223
+pos=760228
 flags=K
 [/PACKET]
 [FRAME]
@@ -361,7 +361,7 @@ best_effort_timestamp=4096
 best_effort_timestamp_time=0.080000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=760223
+pkt_pos=760228
 pkt_size=30000
 width=100
 height=100
@@ -386,7 +386,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=790228
+pos=790233
 flags=K
 [/PACKET]
 [FRAME]
@@ -401,7 +401,7 @@ best_effort_timestamp=4096
 best_effort_timestamp_time=0.092880
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=790228
+pkt_pos=790233
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -420,7 +420,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=792299
+pos=792304
 flags=K
 [/PACKET]
 [FRAME]
@@ -435,7 +435,7 @@ best_effort_timestamp=5120
 best_effort_timestamp_time=0.116100
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=792299
+pkt_pos=792304
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -454,7 +454,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=230400
-pos=794377
+pos=794382
 flags=K
 [/PACKET]
 [FRAME]
@@ -469,7 +469,7 @@ best_effort_timestamp=6144
 best_effort_timestamp_time=0.120000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=794377
+pkt_pos=794382
 pkt_size=230400
 width=320
 height=240
@@ -494,7 +494,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=30000
-pos=1024801
+pos=1024806
 flags=K
 [/PACKET]
 [FRAME]
@@ -509,7 +509,7 @@ best_effort_timestamp=6144
 best_effort_timestamp_time=0.120000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=1024801
+pkt_pos=1024806
 pkt_size=30000
 width=100
 height=100
@@ -568,7 +568,7 @@ index=1
 codec_name=rawvideo
 profile=unknown
 codec_type=video
-codec_time_base=1/51200
+codec_time_base=1/25
 codec_tag_string=RGB[24]
 codec_tag=0x18424752
 width=320
@@ -621,7 +621,7 @@ index=2
 codec_name=rawvideo
 profile=unknown
 codec_type=video
-codec_time_base=1/51200
+codec_time_base=1/25
 codec_tag_string=RGB[24]
 codec_tag=0x18424752
 width=100
@@ -674,8 +674,8 @@ nb_programs=0
 format_name=nut
 start_time=0.000000
 duration=0.120000
-size=1054882
-bit_rate=70325466
+size=1054887
+bit_rate=70325800
 probe_score=100
 TAG:title=ffprobe test file
 TAG:comment='A comment with CSV, XML & JSON special chars': <tag value="x">
diff --git a/tests/ref/fate/ffprobe_flat b/tests/ref/fate/ffprobe_flat
index 5a8cb77..4b2c91a 100644
--- a/tests/ref/fate/ffprobe_flat
+++ b/tests/ref/fate/ffprobe_flat
@@ -9,7 +9,7 @@ packets_and_frames.packet.0.duration_time="0.023220"
 packets_and_frames.packet.0.convergence_duration="N/A"
 packets_and_frames.packet.0.convergence_duration_time="N/A"
 packets_and_frames.packet.0.size="2048"
-packets_and_frames.packet.0.pos="642"
+packets_and_frames.packet.0.pos="647"
 packets_and_frames.packet.0.flags="K"
 packets_and_frames.frame.0.media_type="audio"
 packets_and_frames.frame.0.stream_index=0
@@ -22,7 +22,7 @@ packets_and_frames.frame.0.best_effort_timestamp=0
 packets_and_frames.frame.0.best_effort_timestamp_time="0.000000"
 packets_and_frames.frame.0.pkt_duration=1024
 packets_and_frames.frame.0.pkt_duration_time="0.023220"
-packets_and_frames.frame.0.pkt_pos="642"
+packets_and_frames.frame.0.pkt_pos="647"
 packets_and_frames.frame.0.pkt_size="2048"
 packets_and_frames.frame.0.sample_fmt="s16"
 packets_and_frames.frame.0.nb_samples=1024
@@ -39,7 +39,7 @@ packets_and_frames.packet.1.duration_time="0.040000"
 packets_and_frames.packet.1.convergence_duration="N/A"
 packets_and_frames.packet.1.convergence_duration_time="N/A"
 packets_and_frames.packet.1.size="230400"
-packets_and_frames.packet.1.pos="2717"
+packets_and_frames.packet.1.pos="2722"
 packets_and_frames.packet.1.flags="K"
 packets_and_frames.frame.1.media_type="video"
 packets_and_frames.frame.1.stream_index=1
@@ -52,7 +52,7 @@ packets_and_frames.frame.1.best_effort_timestamp=0
 packets_and_frames.frame.1.best_effort_timestamp_time="0.000000"
 packets_and_frames.frame.1.pkt_duration=2048
 packets_and_frames.frame.1.pkt_duration_time="0.040000"
-packets_and_frames.frame.1.pkt_pos="2717"
+packets_and_frames.frame.1.pkt_pos="2722"
 packets_and_frames.frame.1.pkt_size="230400"
 packets_and_frames.frame.1.width=320
 packets_and_frames.frame.1.height=240
@@ -75,7 +75,7 @@ packets_and_frames.packet.2.duration_time="0.040000"
 packets_and_frames.packet.2.convergence_duration="N/A"
 packets_and_frames.packet.2.convergence_duration_time="N/A"
 packets_and_frames.packet.2.size="30000"
-packets_and_frames.packet.2.pos="233138"
+packets_and_frames.packet.2.pos="233143"
 packets_and_frames.packet.2.flags="K"
 packets_and_frames.frame.2.media_type="video"
 packets_and_frames.frame.2.stream_index=2
@@ -88,7 +88,7 @@ packets_and_frames.frame.2.best_effort_timestamp=0
 packets_and_frames.frame.2.best_effort_timestamp_time="0.000000"
 packets_and_frames.frame.2.pkt_duration=2048
 packets_and_frames.frame.2.pkt_duration_time="0.040000"
-packets_and_frames.frame.2.pkt_pos="233138"
+packets_and_frames.frame.2.pkt_pos="233143"
 packets_and_frames.frame.2.pkt_size="30000"
 packets_and_frames.frame.2.width=100
 packets_and_frames.frame.2.height=100
@@ -111,7 +111,7 @@ packets_and_frames.packet.3.duration_time="0.023220"
 packets_and_frames.packet.3.convergence_duration="N/A"
 packets_and_frames.packet.3.convergence_duration_time="N/A"
 packets_and_frames.packet.3.size="2048"
-packets_and_frames.packet.3.pos="263143"
+packets_and_frames.packet.3.pos="263148"
 packets_and_frames.packet.3.flags="K"
 packets_and_frames.frame.3.media_type="audio"
 packets_and_frames.frame.3.stream_index=0
@@ -124,7 +124,7 @@ packets_and_frames.frame.3.best_effort_timestamp=1024
 packets_and_frames.frame.3.best_effort_timestamp_time="0.023220"
 packets_and_frames.frame.3.pkt_duration=1024
 packets_and_frames.frame.3.pkt_duration_time="0.023220"
-packets_and_frames.frame.3.pkt_pos="263143"
+packets_and_frames.frame.3.pkt_pos="263148"
 packets_and_frames.frame.3.pkt_size="2048"
 packets_and_frames.frame.3.sample_fmt="s16"
 packets_and_frames.frame.3.nb_samples=1024
@@ -141,7 +141,7 @@ packets_and_frames.packet.4.duration_time="0.040000"
 packets_and_frames.packet.4.convergence_duration="N/A"
 packets_and_frames.packet.4.convergence_duration_time="N/A"
 packets_and_frames.packet.4.size="230400"
-packets_and_frames.packet.4.pos="265221"
+packets_and_frames.packet.4.pos="265226"
 packets_and_frames.packet.4.flags="K"
 packets_and_frames.frame.4.media_type="video"
 packets_and_frames.frame.4.stream_index=1
@@ -154,7 +154,7 @@ packets_and_frames.frame.4.best_effort_timestamp=2048
 packets_and_frames.frame.4.best_effort_timestamp_time="0.040000"
 packets_and_frames.frame.4.pkt_duration=2048
 packets_and_frames.frame.4.pkt_duration_time="0.040000"
-packets_and_frames.frame.4.pkt_pos="265221"
+packets_and_frames.frame.4.pkt_pos="265226"
 packets_and_frames.frame.4.pkt_size="230400"
 packets_and_frames.frame.4.width=320
 packets_and_frames.frame.4.height=240
@@ -177,7 +177,7 @@ packets_and_frames.packet.5.duration_time="0.040000"
 packets_and_frames.packet.5.convergence_duration="N/A"
 packets_and_frames.packet.5.convergence_duration_time="N/A"
 packets_and_frames.packet.5.size="30000"
-packets_and_frames.packet.5.pos="495645"
+packets_and_frames.packet.5.pos="495650"
 packets_and_frames.packet.5.flags="K"
 packets_and_frames.frame.5.media_type="video"
 packets_and_frames.frame.5.stream_index=2
@@ -190,7 +190,7 @@ packets_and_frames.frame.5.best_effort_timestamp=2048
 packets_and_frames.frame.5.best_effort_timestamp_time="0.040000"
 packets_and_frames.frame.5.pkt_duration=2048
 packets_and_frames.frame.5.pkt_duration_time="0.040000"
-packets_and_frames.frame.5.pkt_pos="495645"
+packets_and_frames.frame.5.pkt_pos="495650"
 packets_and_frames.frame.5.pkt_size="30000"
 packets_and_frames.frame.5.width=100
 packets_and_frames.frame.5.height=100
@@ -213,7 +213,7 @@ packets_and_frames.packet.6.duration_time="0.023220"
 packets_and_frames.packet.6.convergence_duration="N/A"
 packets_and_frames.packet.6.convergence_duration_time="N/A"
 packets_and_frames.packet.6.size="2048"
-packets_and_frames.packet.6.pos="525650"
+packets_and_frames.packet.6.pos="525655"
 packets_and_frames.packet.6.flags="K"
 packets_and_frames.frame.6.media_type="audio"
 packets_and_frames.frame.6.stream_index=0
@@ -226,7 +226,7 @@ packets_and_frames.frame.6.best_effort_timestamp=2048
 packets_and_frames.frame.6.best_effort_timestamp_time="0.046440"
 packets_and_frames.frame.6.pkt_duration=1024
 packets_and_frames.frame.6.pkt_duration_time="0.023220"
-packets_and_frames.frame.6.pkt_pos="525650"
+packets_and_frames.frame.6.pkt_pos="525655"
 packets_and_frames.frame.6.pkt_size="2048"
 packets_and_frames.frame.6.sample_fmt="s16"
 packets_and_frames.frame.6.nb_samples=1024
@@ -243,7 +243,7 @@ packets_and_frames.packet.7.duration_time="0.023220"
 packets_and_frames.packet.7.convergence_duration="N/A"
 packets_and_frames.packet.7.convergence_duration_time="N/A"
 packets_and_frames.packet.7.size="2048"
-packets_and_frames.packet.7.pos="527721"
+packets_and_frames.packet.7.pos="527726"
 packets_and_frames.packet.7.flags="K"
 packets_and_frames.frame.7.media_type="audio"
 packets_and_frames.frame.7.stream_index=0
@@ -256,7 +256,7 @@ packets_and_frames.frame.7.best_effort_timestamp=3072
 packets_and_frames.frame.7.best_effort_timestamp_time="0.069660"
 packets_and_frames.frame.7.pkt_duration=1024
 packets_and_frames.frame.7.pkt_duration_time="0.023220"
-packets_and_frames.frame.7.pkt_pos="527721"
+packets_and_frames.frame.7.pkt_pos="527726"
 packets_and_frames.frame.7.pkt_size="2048"
 packets_and_frames.frame.7.sample_fmt="s16"
 packets_and_frames.frame.7.nb_samples=1024
@@ -273,7 +273,7 @@ packets_and_frames.packet.8.duration_time="0.040000"
 packets_and_frames.packet.8.convergence_duration="N/A"
 packets_and_frames.packet.8.convergence_duration_time="N/A"
 packets_and_frames.packet.8.size="230400"
-packets_and_frames.packet.8.pos="529799"
+packets_and_frames.packet.8.pos="529804"
 packets_and_frames.packet.8.flags="K"
 packets_and_frames.frame.8.media_type="video"
 packets_and_frames.frame.8.stream_index=1
@@ -286,7 +286,7 @@ packets_and_frames.frame.8.best_effort_timestamp=4096
 packets_and_frames.frame.8.best_effort_timestamp_time="0.080000"
 packets_and_frames.frame.8.pkt_duration=2048
 packets_and_frames.frame.8.pkt_duration_time="0.040000"
-packets_and_frames.frame.8.pkt_pos="529799"
+packets_and_frames.frame.8.pkt_pos="529804"
 packets_and_frames.frame.8.pkt_size="230400"
 packets_and_frames.frame.8.width=320
 packets_and_frames.frame.8.height=240
@@ -309,7 +309,7 @@ packets_and_frames.packet.9.duration_time="0.040000"
 packets_and_frames.packet.9.convergence_duration="N/A"
 packets_and_frames.packet.9.convergence_duration_time="N/A"
 packets_and_frames.packet.9.size="30000"
-packets_and_frames.packet.9.pos="760223"
+packets_and_frames.packet.9.pos="760228"
 packets_and_frames.packet.9.flags="K"
 packets_and_frames.frame.9.media_type="video"
 packets_and_frames.frame.9.stream_index=2
@@ -322,7 +322,7 @@ packets_and_frames.frame.9.best_effort_timestamp=4096
 packets_and_frames.frame.9.best_effort_timestamp_time="0.080000"
 packets_and_frames.frame.9.pkt_duration=2048
 packets_and_frames.frame.9.pkt_duration_time="0.040000"
-packets_and_frames.frame.9.pkt_pos="760223"
+packets_and_frames.frame.9.pkt_pos="760228"
 packets_and_frames.frame.9.pkt_size="30000"
 packets_and_frames.frame.9.width=100
 packets_and_frames.frame.9.height=100
@@ -345,7 +345,7 @@ packets_and_frames.packet.10.duration_time="0.023220"
 packets_and_frames.packet.10.convergence_duration="N/A"
 packets_and_frames.packet.10.convergence_duration_time="N/A"
 packets_and_frames.packet.10.size="2048"
-packets_and_frames.packet.10.pos="790228"
+packets_and_frames.packet.10.pos="790233"
 packets_and_frames.packet.10.flags="K"
 packets_and_frames.frame.10.media_type="audio"
 packets_and_frames.frame.10.stream_index=0
@@ -358,7 +358,7 @@ packets_and_frames.frame.10.best_effort_timestamp=4096
 packets_and_frames.frame.10.best_effort_timestamp_time="0.092880"
 packets_and_frames.frame.10.pkt_duration=1024
 packets_and_frames.frame.10.pkt_duration_time="0.023220"
-packets_and_frames.frame.10.pkt_pos="790228"
+packets_and_frames.frame.10.pkt_pos="790233"
 packets_and_frames.frame.10.pkt_size="2048"
 packets_and_frames.frame.10.sample_fmt="s16"
 packets_and_frames.frame.10.nb_samples=1024
@@ -375,7 +375,7 @@ packets_and_frames.packet.11.duration_time="0.023220"
 packets_and_frames.packet.11.convergence_duration="N/A"
 packets_and_frames.packet.11.convergence_duration_time="N/A"
 packets_and_frames.packet.11.size="2048"
-packets_and_frames.packet.11.pos="792299"
+packets_and_frames.packet.11.pos="792304"
 packets_and_frames.packet.11.flags="K"
 packets_and_frames.frame.11.media_type="audio"
 packets_and_frames.frame.11.stream_index=0
@@ -388,7 +388,7 @@ packets_and_frames.frame.11.best_effort_timestamp=5120
 packets_and_frames.frame.11.best_effort_timestamp_time="0.116100"
 packets_and_frames.frame.11.pkt_duration=1024
 packets_and_frames.frame.11.pkt_duration_time="0.023220"
-packets_and_frames.frame.11.pkt_pos="792299"
+packets_and_frames.frame.11.pkt_pos="792304"
 packets_and_frames.frame.11.pkt_size="2048"
 packets_and_frames.frame.11.sample_fmt="s16"
 packets_and_frames.frame.11.nb_samples=1024
@@ -405,7 +405,7 @@ packets_and_frames.packet.12.duration_time="0.040000"
 packets_and_frames.packet.12.convergence_duration="N/A"
 packets_and_frames.packet.12.convergence_duration_time="N/A"
 packets_and_frames.packet.12.size="230400"
-packets_and_frames.packet.12.pos="794377"
+packets_and_frames.packet.12.pos="794382"
 packets_and_frames.packet.12.flags="K"
 packets_and_frames.frame.12.media_type="video"
 packets_and_frames.frame.12.stream_index=1
@@ -418,7 +418,7 @@ packets_and_frames.frame.12.best_effort_timestamp=6144
 packets_and_frames.frame.12.best_effort_timestamp_time="0.120000"
 packets_and_frames.frame.12.pkt_duration=2048
 packets_and_frames.frame.12.pkt_duration_time="0.040000"
-packets_and_frames.frame.12.pkt_pos="794377"
+packets_and_frames.frame.12.pkt_pos="794382"
 packets_and_frames.frame.12.pkt_size="230400"
 packets_and_frames.frame.12.width=320
 packets_and_frames.frame.12.height=240
@@ -441,7 +441,7 @@ packets_and_frames.packet.13.duration_time="0.040000"
 packets_and_frames.packet.13.convergence_duration="N/A"
 packets_and_frames.packet.13.convergence_duration_time="N/A"
 packets_and_frames.packet.13.size="30000"
-packets_and_frames.packet.13.pos="1024801"
+packets_and_frames.packet.13.pos="1024806"
 packets_and_frames.packet.13.flags="K"
 packets_and_frames.frame.13.media_type="video"
 packets_and_frames.frame.13.stream_index=2
@@ -454,7 +454,7 @@ packets_and_frames.frame.13.best_effort_timestamp=6144
 packets_and_frames.frame.13.best_effort_timestamp_time="0.120000"
 packets_and_frames.frame.13.pkt_duration=2048
 packets_and_frames.frame.13.pkt_duration_time="0.040000"
-packets_and_frames.frame.13.pkt_pos="1024801"
+packets_and_frames.frame.13.pkt_pos="1024806"
 packets_and_frames.frame.13.pkt_size="30000"
 packets_and_frames.frame.13.width=100
 packets_and_frames.frame.13.height=100
@@ -509,7 +509,7 @@ streams.stream.1.index=1
 streams.stream.1.codec_name="rawvideo"
 streams.stream.1.profile="unknown"
 streams.stream.1.codec_type="video"
-streams.stream.1.codec_time_base="1/51200"
+streams.stream.1.codec_time_base="1/25"
 streams.stream.1.codec_tag_string="RGB[24]"
 streams.stream.1.codec_tag="0x18424752"
 streams.stream.1.width=320
@@ -560,7 +560,7 @@ streams.stream.2.index=2
 streams.stream.2.codec_name="rawvideo"
 streams.stream.2.profile="unknown"
 streams.stream.2.codec_type="video"
-streams.stream.2.codec_time_base="1/51200"
+streams.stream.2.codec_time_base="1/25"
 streams.stream.2.codec_tag_string="RGB[24]"
 streams.stream.2.codec_tag="0x18424752"
 streams.stream.2.width=100
@@ -611,8 +611,8 @@ format.nb_programs=0
 format.format_name="nut"
 format.start_time="0.000000"
 format.duration="0.120000"
-format.size="1054882"
-format.bit_rate="70325466"
+format.size="1054887"
+format.bit_rate="70325800"
 format.probe_score=100
 format.tags.title="ffprobe test file"
 format.tags.comment="'A comment with CSV, XML & JSON special chars': <tag value=\"x\">"
diff --git a/tests/ref/fate/ffprobe_ini b/tests/ref/fate/ffprobe_ini
index db5ea8b..ba59d61 100644
--- a/tests/ref/fate/ffprobe_ini
+++ b/tests/ref/fate/ffprobe_ini
@@ -12,7 +12,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=642
+pos=647
 flags=K
 
 [packets_and_frames.frame.0]
@@ -27,7 +27,7 @@ best_effort_timestamp=0
 best_effort_timestamp_time=0.000000
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=642
+pkt_pos=647
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -46,7 +46,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=230400
-pos=2717
+pos=2722
 flags=K
 
 [packets_and_frames.frame.1]
@@ -61,7 +61,7 @@ best_effort_timestamp=0
 best_effort_timestamp_time=0.000000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=2717
+pkt_pos=2722
 pkt_size=230400
 width=320
 height=240
@@ -86,7 +86,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=30000
-pos=233138
+pos=233143
 flags=K
 
 [packets_and_frames.frame.2]
@@ -101,7 +101,7 @@ best_effort_timestamp=0
 best_effort_timestamp_time=0.000000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=233138
+pkt_pos=233143
 pkt_size=30000
 width=100
 height=100
@@ -126,7 +126,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=263143
+pos=263148
 flags=K
 
 [packets_and_frames.frame.3]
@@ -141,7 +141,7 @@ best_effort_timestamp=1024
 best_effort_timestamp_time=0.023220
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=263143
+pkt_pos=263148
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -160,7 +160,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=230400
-pos=265221
+pos=265226
 flags=K
 
 [packets_and_frames.frame.4]
@@ -175,7 +175,7 @@ best_effort_timestamp=2048
 best_effort_timestamp_time=0.040000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=265221
+pkt_pos=265226
 pkt_size=230400
 width=320
 height=240
@@ -200,7 +200,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=30000
-pos=495645
+pos=495650
 flags=K
 
 [packets_and_frames.frame.5]
@@ -215,7 +215,7 @@ best_effort_timestamp=2048
 best_effort_timestamp_time=0.040000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=495645
+pkt_pos=495650
 pkt_size=30000
 width=100
 height=100
@@ -240,7 +240,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=525650
+pos=525655
 flags=K
 
 [packets_and_frames.frame.6]
@@ -255,7 +255,7 @@ best_effort_timestamp=2048
 best_effort_timestamp_time=0.046440
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=525650
+pkt_pos=525655
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -274,7 +274,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=527721
+pos=527726
 flags=K
 
 [packets_and_frames.frame.7]
@@ -289,7 +289,7 @@ best_effort_timestamp=3072
 best_effort_timestamp_time=0.069660
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=527721
+pkt_pos=527726
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -308,7 +308,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=230400
-pos=529799
+pos=529804
 flags=K
 
 [packets_and_frames.frame.8]
@@ -323,7 +323,7 @@ best_effort_timestamp=4096
 best_effort_timestamp_time=0.080000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=529799
+pkt_pos=529804
 pkt_size=230400
 width=320
 height=240
@@ -348,7 +348,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=30000
-pos=760223
+pos=760228
 flags=K
 
 [packets_and_frames.frame.9]
@@ -363,7 +363,7 @@ best_effort_timestamp=4096
 best_effort_timestamp_time=0.080000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=760223
+pkt_pos=760228
 pkt_size=30000
 width=100
 height=100
@@ -388,7 +388,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=790228
+pos=790233
 flags=K
 
 [packets_and_frames.frame.10]
@@ -403,7 +403,7 @@ best_effort_timestamp=4096
 best_effort_timestamp_time=0.092880
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=790228
+pkt_pos=790233
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -422,7 +422,7 @@ duration_time=0.023220
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=2048
-pos=792299
+pos=792304
 flags=K
 
 [packets_and_frames.frame.11]
@@ -437,7 +437,7 @@ best_effort_timestamp=5120
 best_effort_timestamp_time=0.116100
 pkt_duration=1024
 pkt_duration_time=0.023220
-pkt_pos=792299
+pkt_pos=792304
 pkt_size=2048
 sample_fmt=s16
 nb_samples=1024
@@ -456,7 +456,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=230400
-pos=794377
+pos=794382
 flags=K
 
 [packets_and_frames.frame.12]
@@ -471,7 +471,7 @@ best_effort_timestamp=6144
 best_effort_timestamp_time=0.120000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=794377
+pkt_pos=794382
 pkt_size=230400
 width=320
 height=240
@@ -496,7 +496,7 @@ duration_time=0.040000
 convergence_duration=N/A
 convergence_duration_time=N/A
 size=30000
-pos=1024801
+pos=1024806
 flags=K
 
 [packets_and_frames.frame.13]
@@ -511,7 +511,7 @@ best_effort_timestamp=6144
 best_effort_timestamp_time=0.120000
 pkt_duration=2048
 pkt_duration_time=0.040000
-pkt_pos=1024801
+pkt_pos=1024806
 pkt_size=30000
 width=100
 height=100
@@ -574,7 +574,7 @@ index=1
 codec_name=rawvideo
 profile=unknown
 codec_type=video
-codec_time_base=1/51200
+codec_time_base=1/25
 codec_tag_string=RGB[24]
 codec_tag=0x18424752
 width=320
@@ -631,7 +631,7 @@ index=2
 codec_name=rawvideo
 profile=unknown
 codec_type=video
-codec_time_base=1/51200
+codec_time_base=1/25
 codec_tag_string=RGB[24]
 codec_tag=0x18424752
 width=100
@@ -688,8 +688,8 @@ nb_programs=0
 format_name=nut
 start_time=0.000000
 duration=0.120000
-size=1054882
-bit_rate=70325466
+size=1054887
+bit_rate=70325800
 probe_score=100
 
 [format.tags]
diff --git a/tests/ref/fate/ffprobe_json b/tests/ref/fate/ffprobe_json
index 64108ce..8d7abda 100644
--- a/tests/ref/fate/ffprobe_json
+++ b/tests/ref/fate/ffprobe_json
@@ -11,7 +11,7 @@
             "duration": 1024,
             "duration_time": "0.023220",
             "size": "2048",
-            "pos": "642",
+            "pos": "647",
             "flags": "K"
         },
         {
@@ -27,7 +27,7 @@
             "best_effort_timestamp_time": "0.000000",
             "pkt_duration": 1024,
             "pkt_duration_time": "0.023220",
-            "pkt_pos": "642",
+            "pkt_pos": "647",
             "pkt_size": "2048",
             "sample_fmt": "s16",
             "nb_samples": 1024,
@@ -44,7 +44,7 @@
             "duration": 2048,
             "duration_time": "0.040000",
             "size": "230400",
-            "pos": "2717",
+            "pos": "2722",
             "flags": "K"
         },
         {
@@ -60,7 +60,7 @@
             "best_effort_timestamp_time": "0.000000",
             "pkt_duration": 2048,
             "pkt_duration_time": "0.040000",
-            "pkt_pos": "2717",
+            "pkt_pos": "2722",
             "pkt_size": "230400",
             "width": 320,
             "height": 240,
@@ -84,7 +84,7 @@
             "duration": 2048,
             "duration_time": "0.040000",
             "size": "30000",
-            "pos": "233138",
+            "pos": "233143",
             "flags": "K"
         },
         {
@@ -100,7 +100,7 @@
             "best_effort_timestamp_time": "0.000000",
             "pkt_duration": 2048,
             "pkt_duration_time": "0.040000",
-            "pkt_pos": "233138",
+            "pkt_pos": "233143",
             "pkt_size": "30000",
             "width": 100,
             "height": 100,
@@ -124,7 +124,7 @@
             "duration": 1024,
             "duration_time": "0.023220",
             "size": "2048",
-            "pos": "263143",
+            "pos": "263148",
             "flags": "K"
         },
         {
@@ -140,7 +140,7 @@
             "best_effort_timestamp_time": "0.023220",
             "pkt_duration": 1024,
             "pkt_duration_time": "0.023220",
-            "pkt_pos": "263143",
+            "pkt_pos": "263148",
             "pkt_size": "2048",
             "sample_fmt": "s16",
             "nb_samples": 1024,
@@ -157,7 +157,7 @@
             "duration": 2048,
             "duration_time": "0.040000",
             "size": "230400",
-            "pos": "265221",
+            "pos": "265226",
             "flags": "K"
         },
         {
@@ -173,7 +173,7 @@
             "best_effort_timestamp_time": "0.040000",
             "pkt_duration": 2048,
             "pkt_duration_time": "0.040000",
-            "pkt_pos": "265221",
+            "pkt_pos": "265226",
             "pkt_size": "230400",
             "width": 320,
             "height": 240,
@@ -197,7 +197,7 @@
             "duration": 2048,
             "duration_time": "0.040000",
             "size": "30000",
-            "pos": "495645",
+            "pos": "495650",
             "flags": "K"
         },
         {
@@ -213,7 +213,7 @@
             "best_effort_timestamp_time": "0.040000",
             "pkt_duration": 2048,
             "pkt_duration_time": "0.040000",
-            "pkt_pos": "495645",
+            "pkt_pos": "495650",
             "pkt_size": "30000",
             "width": 100,
             "height": 100,
@@ -237,7 +237,7 @@
             "duration": 1024,
             "duration_time": "0.023220",
             "size": "2048",
-            "pos": "525650",
+            "pos": "525655",
             "flags": "K"
         },
         {
@@ -253,7 +253,7 @@
             "best_effort_timestamp_time": "0.046440",
             "pkt_duration": 1024,
             "pkt_duration_time": "0.023220",
-            "pkt_pos": "525650",
+            "pkt_pos": "525655",
             "pkt_size": "2048",
             "sample_fmt": "s16",
             "nb_samples": 1024,
@@ -270,7 +270,7 @@
             "duration": 1024,
             "duration_time": "0.023220",
             "size": "2048",
-            "pos": "527721",
+            "pos": "527726",
             "flags": "K"
         },
         {
@@ -286,7 +286,7 @@
             "best_effort_timestamp_time": "0.069660",
             "pkt_duration": 1024,
             "pkt_duration_time": "0.023220",
-            "pkt_pos": "527721",
+            "pkt_pos": "527726",
             "pkt_size": "2048",
             "sample_fmt": "s16",
             "nb_samples": 1024,
@@ -303,7 +303,7 @@
             "duration": 2048,
             "duration_time": "0.040000",
             "size": "230400",
-            "pos": "529799",
+            "pos": "529804",
             "flags": "K"
         },
         {
@@ -319,7 +319,7 @@
             "best_effort_timestamp_time": "0.080000",
             "pkt_duration": 2048,
             "pkt_duration_time": "0.040000",
-            "pkt_pos": "529799",
+            "pkt_pos": "529804",
             "pkt_size": "230400",
             "width": 320,
             "height": 240,
@@ -343,7 +343,7 @@
             "duration": 2048,
             "duration_time": "0.040000",
             "size": "30000",
-            "pos": "760223",
+            "pos": "760228",
             "flags": "K"
         },
         {
@@ -359,7 +359,7 @@
             "best_effort_timestamp_time": "0.080000",
             "pkt_duration": 2048,
             "pkt_duration_time": "0.040000",
-            "pkt_pos": "760223",
+            "pkt_pos": "760228",
             "pkt_size": "30000",
             "width": 100,
             "height": 100,
@@ -383,7 +383,7 @@
             "duration": 1024,
             "duration_time": "0.023220",
             "size": "2048",
-            "pos": "790228",
+            "pos": "790233",
             "flags": "K"
         },
         {
@@ -399,7 +399,7 @@
             "best_effort_timestamp_time": "0.092880",
             "pkt_duration": 1024,
             "pkt_duration_time": "0.023220",
-            "pkt_pos": "790228",
+            "pkt_pos": "790233",
             "pkt_size": "2048",
             "sample_fmt": "s16",
             "nb_samples": 1024,
@@ -416,7 +416,7 @@
             "duration": 1024,
             "duration_time": "0.023220",
             "size": "2048",
-            "pos": "792299",
+            "pos": "792304",
             "flags": "K"
         },
         {
@@ -432,7 +432,7 @@
             "best_effort_timestamp_time": "0.116100",
             "pkt_duration": 1024,
             "pkt_duration_time": "0.023220",
-            "pkt_pos": "792299",
+            "pkt_pos": "792304",
             "pkt_size": "2048",
             "sample_fmt": "s16",
             "nb_samples": 1024,
@@ -449,7 +449,7 @@
             "duration": 2048,
             "duration_time": "0.040000",
             "size": "230400",
-            "pos": "794377",
+            "pos": "794382",
             "flags": "K"
         },
         {
@@ -465,7 +465,7 @@
             "best_effort_timestamp_time": "0.120000",
             "pkt_duration": 2048,
             "pkt_duration_time": "0.040000",
-            "pkt_pos": "794377",
+            "pkt_pos": "794382",
             "pkt_size": "230400",
             "width": 320,
             "height": 240,
@@ -489,7 +489,7 @@
             "duration": 2048,
             "duration_time": "0.040000",
             "size": "30000",
-            "pos": "1024801",
+            "pos": "1024806",
             "flags": "K"
         },
         {
@@ -505,7 +505,7 @@
             "best_effort_timestamp_time": "0.120000",
             "pkt_duration": 2048,
             "pkt_duration_time": "0.040000",
-            "pkt_pos": "1024801",
+            "pkt_pos": "1024806",
             "pkt_size": "30000",
             "width": 100,
             "height": 100,
@@ -561,7 +561,7 @@
             "index": 1,
             "codec_name": "rawvideo",
             "codec_type": "video",
-            "codec_time_base": "1/51200",
+            "codec_time_base": "1/25",
             "codec_tag_string": "RGB[24]",
             "codec_tag": "0x18424752",
             "width": 320,
@@ -604,7 +604,7 @@
             "index": 2,
             "codec_name": "rawvideo",
             "codec_type": "video",
-            "codec_time_base": "1/51200",
+            "codec_time_base": "1/25",
             "codec_tag_string": "RGB[24]",
             "codec_tag": "0x18424752",
             "width": 100,
@@ -649,8 +649,8 @@
         "format_name": "nut",
         "start_time": "0.000000",
         "duration": "0.120000",
-        "size": "1054882",
-        "bit_rate": "70325466",
+        "size": "1054887",
+        "bit_rate": "70325800",
         "probe_score": 100,
         "tags": {
             "title": "ffprobe test file",
diff --git a/tests/ref/fate/ffprobe_xml b/tests/ref/fate/ffprobe_xml
index 2fdd81b..b51b0c6 100644
--- a/tests/ref/fate/ffprobe_xml
+++ b/tests/ref/fate/ffprobe_xml
@@ -1,34 +1,34 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ffprobe>
     <packets_and_frames>
-        <packet codec_type="audio" stream_index="0" pts="0" pts_time="0.000000" dts="0" dts_time="0.000000" duration="1024" duration_time="0.023220" size="2048" pos="642" flags="K"/>
-        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="0" pkt_pts_time="0.000000" pkt_dts="0" pkt_dts_time="0.000000" best_effort_timestamp="0" best_effort_timestamp_time="0.000000" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="642" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
-        <packet codec_type="video" stream_index="1" pts="0" pts_time="0.000000" dts="0" dts_time="0.000000" duration="2048" duration_time="0.040000" size="230400" pos="2717" flags="K"/>
-        <frame media_type="video" stream_index="1" key_frame="1" pkt_pts="0" pkt_pts_time="0.000000" pkt_dts="0" pkt_dts_time="0.000000" best_effort_timestamp="0" best_effort_timestamp_time="0.000000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="2717" pkt_size="230400" width="320" height="240" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
-        <packet codec_type="video" stream_index="2" pts="0" pts_time="0.000000" dts="0" dts_time="0.000000" duration="2048" duration_time="0.040000" size="30000" pos="233138" flags="K"/>
-        <frame media_type="video" stream_index="2" key_frame="1" pkt_pts="0" pkt_pts_time="0.000000" pkt_dts="0" pkt_dts_time="0.000000" best_effort_timestamp="0" best_effort_timestamp_time="0.000000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="233138" pkt_size="30000" width="100" height="100" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
-        <packet codec_type="audio" stream_index="0" pts="1024" pts_time="0.023220" dts="1024" dts_time="0.023220" duration="1024" duration_time="0.023220" size="2048" pos="263143" flags="K"/>
-        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="1024" pkt_pts_time="0.023220" pkt_dts="1024" pkt_dts_time="0.023220" best_effort_timestamp="1024" best_effort_timestamp_time="0.023220" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="263143" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
-        <packet codec_type="video" stream_index="1" pts="2048" pts_time="0.040000" dts="2048" dts_time="0.040000" duration="2048" duration_time="0.040000" size="230400" pos="265221" flags="K"/>
-        <frame media_type="video" stream_index="1" key_frame="1" pkt_pts="2048" pkt_pts_time="0.040000" pkt_dts="2048" pkt_dts_time="0.040000" best_effort_timestamp="2048" best_effort_timestamp_time="0.040000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="265221" pkt_size="230400" width="320" height="240" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
-        <packet codec_type="video" stream_index="2" pts="2048" pts_time="0.040000" dts="2048" dts_time="0.040000" duration="2048" duration_time="0.040000" size="30000" pos="495645" flags="K"/>
-        <frame media_type="video" stream_index="2" key_frame="1" pkt_pts="2048" pkt_pts_time="0.040000" pkt_dts="2048" pkt_dts_time="0.040000" best_effort_timestamp="2048" best_effort_timestamp_time="0.040000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="495645" pkt_size="30000" width="100" height="100" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
-        <packet codec_type="audio" stream_index="0" pts="2048" pts_time="0.046440" dts="2048" dts_time="0.046440" duration="1024" duration_time="0.023220" size="2048" pos="525650" flags="K"/>
-        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="2048" pkt_pts_time="0.046440" pkt_dts="2048" pkt_dts_time="0.046440" best_effort_timestamp="2048" best_effort_timestamp_time="0.046440" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="525650" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
-        <packet codec_type="audio" stream_index="0" pts="3072" pts_time="0.069660" dts="3072" dts_time="0.069660" duration="1024" duration_time="0.023220" size="2048" pos="527721" flags="K"/>
-        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="3072" pkt_pts_time="0.069660" pkt_dts="3072" pkt_dts_time="0.069660" best_effort_timestamp="3072" best_effort_timestamp_time="0.069660" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="527721" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
-        <packet codec_type="video" stream_index="1" pts="4096" pts_time="0.080000" dts="4096" dts_time="0.080000" duration="2048" duration_time="0.040000" size="230400" pos="529799" flags="K"/>
-        <frame media_type="video" stream_index="1" key_frame="1" pkt_pts="4096" pkt_pts_time="0.080000" pkt_dts="4096" pkt_dts_time="0.080000" best_effort_timestamp="4096" best_effort_timestamp_time="0.080000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="529799" pkt_size="230400" width="320" height="240" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
-        <packet codec_type="video" stream_index="2" pts="4096" pts_time="0.080000" dts="4096" dts_time="0.080000" duration="2048" duration_time="0.040000" size="30000" pos="760223" flags="K"/>
-        <frame media_type="video" stream_index="2" key_frame="1" pkt_pts="4096" pkt_pts_time="0.080000" pkt_dts="4096" pkt_dts_time="0.080000" best_effort_timestamp="4096" best_effort_timestamp_time="0.080000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="760223" pkt_size="30000" width="100" height="100" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
-        <packet codec_type="audio" stream_index="0" pts="4096" pts_time="0.092880" dts="4096" dts_time="0.092880" duration="1024" duration_time="0.023220" size="2048" pos="790228" flags="K"/>
-        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="4096" pkt_pts_time="0.092880" pkt_dts="4096" pkt_dts_time="0.092880" best_effort_timestamp="4096" best_effort_timestamp_time="0.092880" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="790228" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
-        <packet codec_type="audio" stream_index="0" pts="5120" pts_time="0.116100" dts="5120" dts_time="0.116100" duration="1024" duration_time="0.023220" size="2048" pos="792299" flags="K"/>
-        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="5120" pkt_pts_time="0.116100" pkt_dts="5120" pkt_dts_time="0.116100" best_effort_timestamp="5120" best_effort_timestamp_time="0.116100" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="792299" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
-        <packet codec_type="video" stream_index="1" pts="6144" pts_time="0.120000" dts="6144" dts_time="0.120000" duration="2048" duration_time="0.040000" size="230400" pos="794377" flags="K"/>
-        <frame media_type="video" stream_index="1" key_frame="1" pkt_pts="6144" pkt_pts_time="0.120000" pkt_dts="6144" pkt_dts_time="0.120000" best_effort_timestamp="6144" best_effort_timestamp_time="0.120000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="794377" pkt_size="230400" width="320" height="240" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
-        <packet codec_type="video" stream_index="2" pts="6144" pts_time="0.120000" dts="6144" dts_time="0.120000" duration="2048" duration_time="0.040000" size="30000" pos="1024801" flags="K"/>
-        <frame media_type="video" stream_index="2" key_frame="1" pkt_pts="6144" pkt_pts_time="0.120000" pkt_dts="6144" pkt_dts_time="0.120000" best_effort_timestamp="6144" best_effort_timestamp_time="0.120000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="1024801" pkt_size="30000" width="100" height="100" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
+        <packet codec_type="audio" stream_index="0" pts="0" pts_time="0.000000" dts="0" dts_time="0.000000" duration="1024" duration_time="0.023220" size="2048" pos="647" flags="K"/>
+        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="0" pkt_pts_time="0.000000" pkt_dts="0" pkt_dts_time="0.000000" best_effort_timestamp="0" best_effort_timestamp_time="0.000000" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="647" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
+        <packet codec_type="video" stream_index="1" pts="0" pts_time="0.000000" dts="0" dts_time="0.000000" duration="2048" duration_time="0.040000" size="230400" pos="2722" flags="K"/>
+        <frame media_type="video" stream_index="1" key_frame="1" pkt_pts="0" pkt_pts_time="0.000000" pkt_dts="0" pkt_dts_time="0.000000" best_effort_timestamp="0" best_effort_timestamp_time="0.000000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="2722" pkt_size="230400" width="320" height="240" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
+        <packet codec_type="video" stream_index="2" pts="0" pts_time="0.000000" dts="0" dts_time="0.000000" duration="2048" duration_time="0.040000" size="30000" pos="233143" flags="K"/>
+        <frame media_type="video" stream_index="2" key_frame="1" pkt_pts="0" pkt_pts_time="0.000000" pkt_dts="0" pkt_dts_time="0.000000" best_effort_timestamp="0" best_effort_timestamp_time="0.000000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="233143" pkt_size="30000" width="100" height="100" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
+        <packet codec_type="audio" stream_index="0" pts="1024" pts_time="0.023220" dts="1024" dts_time="0.023220" duration="1024" duration_time="0.023220" size="2048" pos="263148" flags="K"/>
+        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="1024" pkt_pts_time="0.023220" pkt_dts="1024" pkt_dts_time="0.023220" best_effort_timestamp="1024" best_effort_timestamp_time="0.023220" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="263148" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
+        <packet codec_type="video" stream_index="1" pts="2048" pts_time="0.040000" dts="2048" dts_time="0.040000" duration="2048" duration_time="0.040000" size="230400" pos="265226" flags="K"/>
+        <frame media_type="video" stream_index="1" key_frame="1" pkt_pts="2048" pkt_pts_time="0.040000" pkt_dts="2048" pkt_dts_time="0.040000" best_effort_timestamp="2048" best_effort_timestamp_time="0.040000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="265226" pkt_size="230400" width="320" height="240" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
+        <packet codec_type="video" stream_index="2" pts="2048" pts_time="0.040000" dts="2048" dts_time="0.040000" duration="2048" duration_time="0.040000" size="30000" pos="495650" flags="K"/>
+        <frame media_type="video" stream_index="2" key_frame="1" pkt_pts="2048" pkt_pts_time="0.040000" pkt_dts="2048" pkt_dts_time="0.040000" best_effort_timestamp="2048" best_effort_timestamp_time="0.040000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="495650" pkt_size="30000" width="100" height="100" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
+        <packet codec_type="audio" stream_index="0" pts="2048" pts_time="0.046440" dts="2048" dts_time="0.046440" duration="1024" duration_time="0.023220" size="2048" pos="525655" flags="K"/>
+        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="2048" pkt_pts_time="0.046440" pkt_dts="2048" pkt_dts_time="0.046440" best_effort_timestamp="2048" best_effort_timestamp_time="0.046440" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="525655" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
+        <packet codec_type="audio" stream_index="0" pts="3072" pts_time="0.069660" dts="3072" dts_time="0.069660" duration="1024" duration_time="0.023220" size="2048" pos="527726" flags="K"/>
+        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="3072" pkt_pts_time="0.069660" pkt_dts="3072" pkt_dts_time="0.069660" best_effort_timestamp="3072" best_effort_timestamp_time="0.069660" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="527726" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
+        <packet codec_type="video" stream_index="1" pts="4096" pts_time="0.080000" dts="4096" dts_time="0.080000" duration="2048" duration_time="0.040000" size="230400" pos="529804" flags="K"/>
+        <frame media_type="video" stream_index="1" key_frame="1" pkt_pts="4096" pkt_pts_time="0.080000" pkt_dts="4096" pkt_dts_time="0.080000" best_effort_timestamp="4096" best_effort_timestamp_time="0.080000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="529804" pkt_size="230400" width="320" height="240" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
+        <packet codec_type="video" stream_index="2" pts="4096" pts_time="0.080000" dts="4096" dts_time="0.080000" duration="2048" duration_time="0.040000" size="30000" pos="760228" flags="K"/>
+        <frame media_type="video" stream_index="2" key_frame="1" pkt_pts="4096" pkt_pts_time="0.080000" pkt_dts="4096" pkt_dts_time="0.080000" best_effort_timestamp="4096" best_effort_timestamp_time="0.080000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="760228" pkt_size="30000" width="100" height="100" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
+        <packet codec_type="audio" stream_index="0" pts="4096" pts_time="0.092880" dts="4096" dts_time="0.092880" duration="1024" duration_time="0.023220" size="2048" pos="790233" flags="K"/>
+        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="4096" pkt_pts_time="0.092880" pkt_dts="4096" pkt_dts_time="0.092880" best_effort_timestamp="4096" best_effort_timestamp_time="0.092880" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="790233" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
+        <packet codec_type="audio" stream_index="0" pts="5120" pts_time="0.116100" dts="5120" dts_time="0.116100" duration="1024" duration_time="0.023220" size="2048" pos="792304" flags="K"/>
+        <frame media_type="audio" stream_index="0" key_frame="1" pkt_pts="5120" pkt_pts_time="0.116100" pkt_dts="5120" pkt_dts_time="0.116100" best_effort_timestamp="5120" best_effort_timestamp_time="0.116100" pkt_duration="1024" pkt_duration_time="0.023220" pkt_pos="792304" pkt_size="2048" sample_fmt="s16" nb_samples="1024" channels="1"/>
+        <packet codec_type="video" stream_index="1" pts="6144" pts_time="0.120000" dts="6144" dts_time="0.120000" duration="2048" duration_time="0.040000" size="230400" pos="794382" flags="K"/>
+        <frame media_type="video" stream_index="1" key_frame="1" pkt_pts="6144" pkt_pts_time="0.120000" pkt_dts="6144" pkt_dts_time="0.120000" best_effort_timestamp="6144" best_effort_timestamp_time="0.120000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="794382" pkt_size="230400" width="320" height="240" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
+        <packet codec_type="video" stream_index="2" pts="6144" pts_time="0.120000" dts="6144" dts_time="0.120000" duration="2048" duration_time="0.040000" size="30000" pos="1024806" flags="K"/>
+        <frame media_type="video" stream_index="2" key_frame="1" pkt_pts="6144" pkt_pts_time="0.120000" pkt_dts="6144" pkt_dts_time="0.120000" best_effort_timestamp="6144" best_effort_timestamp_time="0.120000" pkt_duration="2048" pkt_duration_time="0.040000" pkt_pos="1024806" pkt_size="30000" width="100" height="100" pix_fmt="rgb24" sample_aspect_ratio="1:1" pict_type="I" coded_picture_number="0" display_picture_number="0" interlaced_frame="0" top_field_first="0" repeat_pict="0"/>
     </packets_and_frames>
 
     <streams>
@@ -37,19 +37,19 @@
             <tag key="E" value="mc²"/>
             <tag key="encoder" value="Lavc pcm_s16le"/>
         </stream>
-        <stream index="1" codec_name="rawvideo" codec_type="video" codec_time_base="1/51200" codec_tag_string="RGB[24]" codec_tag="0x18424752" width="320" height="240" coded_width="320" coded_height="240" has_b_frames="0" sample_aspect_ratio="1:1" display_aspect_ratio="4:3" pix_fmt="rgb24" level="-99" refs="1" r_frame_rate="25/1" avg_frame_rate="25/1" time_base="1/51200" start_pts="0" start_time="0.000000" nb_read_frames="4" nb_read_packets="4">
+        <stream index="1" codec_name="rawvideo" codec_type="video" codec_time_base="1/25" codec_tag_string="RGB[24]" codec_tag="0x18424752" width="320" height="240" coded_width="320" coded_height="240" has_b_frames="0" sample_aspect_ratio="1:1" display_aspect_ratio="4:3" pix_fmt="rgb24" level="-99" refs="1" r_frame_rate="25/1" avg_frame_rate="25/1" time_base="1/51200" start_pts="0" start_time="0.000000" nb_read_frames="4" nb_read_packets="4">
             <disposition default="0" dub="0" original="0" comment="0" lyrics="0" karaoke="0" forced="0" hearing_impaired="0" visual_impaired="0" clean_effects="0" attached_pic="0"/>
             <tag key="title" value="foobar"/>
             <tag key="duration_ts" value="field-and-tags-conflict-attempt"/>
             <tag key="encoder" value="Lavc rawvideo"/>
         </stream>
-        <stream index="2" codec_name="rawvideo" codec_type="video" codec_time_base="1/51200" codec_tag_string="RGB[24]" codec_tag="0x18424752" width="100" height="100" coded_width="100" coded_height="100" has_b_frames="0" sample_aspect_ratio="1:1" display_aspect_ratio="1:1" pix_fmt="rgb24" level="-99" refs="1" r_frame_rate="25/1" avg_frame_rate="25/1" time_base="1/51200" start_pts="0" start_time="0.000000" nb_read_frames="4" nb_read_packets="4">
+        <stream index="2" codec_name="rawvideo" codec_type="video" codec_time_base="1/25" codec_tag_string="RGB[24]" codec_tag="0x18424752" width="100" height="100" coded_width="100" coded_height="100" has_b_frames="0" sample_aspect_ratio="1:1" display_aspect_ratio="1:1" pix_fmt="rgb24" level="-99" refs="1" r_frame_rate="25/1" avg_frame_rate="25/1" time_base="1/51200" start_pts="0" start_time="0.000000" nb_read_frames="4" nb_read_packets="4">
             <disposition default="0" dub="0" original="0" comment="0" lyrics="0" karaoke="0" forced="0" hearing_impaired="0" visual_impaired="0" clean_effects="0" attached_pic="0"/>
             <tag key="encoder" value="Lavc rawvideo"/>
         </stream>
     </streams>
 
-    <format filename="tests/data/ffprobe-test.nut" nb_streams="3" nb_programs="0" format_name="nut" start_time="0.000000" duration="0.120000" size="1054882" bit_rate="70325466" probe_score="100">
+    <format filename="tests/data/ffprobe-test.nut" nb_streams="3" nb_programs="0" format_name="nut" start_time="0.000000" duration="0.120000" size="1054887" bit_rate="70325800" probe_score="100">
         <tag key="title" value="ffprobe test file"/>
         <tag key="comment" value="'A comment with CSV, XML & JSON special chars': <tag value="x">"/>
         <tag key="comment2" value="I ♥ Üñîçød€"/>
diff --git a/tests/ref/fate/fic-avi b/tests/ref/fate/fic-avi
index cc4ea5d..df55789 100644
--- a/tests/ref/fate/fic-avi
+++ b/tests/ref/fate/fic-avi
@@ -1,4 +1,8 @@
 #tb 0: 1/60
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1360x768
+#sar 0: 0/1
 0,          0,          0,        1,  1566720, 0x7dae32e0
 0,          1,          1,        1,  1566720, 0x7dae32e0
 0,          2,          2,        1,  1566720, 0x6d1a9dc8
diff --git a/tests/ref/fate/film-cvid b/tests/ref/fate/film-cvid
index 3ca7b59..24540bf 100644
--- a/tests/ref/fate/film-cvid
+++ b/tests/ref/fate/film-cvid
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x224
+#sar 0: 0/1
 0,          0,          0,        1,   215040, 0x067c5362
 0,          2,          2,        1,   215040, 0xd9eacb98
 0,          4,          4,        1,   215040, 0x3c8a4cbd
diff --git a/tests/ref/fate/filter-2xbr b/tests/ref/fate/filter-2xbr
index 91e1d4c..1114c31 100644
--- a/tests/ref/fate/filter-2xbr
+++ b/tests/ref/fate/filter-2xbr
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 382x574
+#sar 0: 1/1
 0,          0,          0,        1,   877072, 0x5142c6cd
 0,          1,          1,        1,   877072, 0xa01a3f47
diff --git a/tests/ref/fate/filter-3xbr b/tests/ref/fate/filter-3xbr
index 013f6a3..0ed0028 100644
--- a/tests/ref/fate/filter-3xbr
+++ b/tests/ref/fate/filter-3xbr
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 573x861
+#sar 0: 1/1
 0,          0,          0,        1,  1973412, 0xd4cf257b
 0,          1,          1,        1,  1973412, 0x63fcd614
diff --git a/tests/ref/fate/filter-4xbr b/tests/ref/fate/filter-4xbr
index 92b70d9..a656737 100644
--- a/tests/ref/fate/filter-4xbr
+++ b/tests/ref/fate/filter-4xbr
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 764x1148
+#sar 0: 1/1
 0,          0,          0,        1,  3508288, 0xc7b1d170
 0,          1,          1,        1,  3508288, 0x3fd0c3fb
diff --git a/tests/ref/fate/filter-acrossfade b/tests/ref/fate/filter-acrossfade
new file mode 100644
index 0000000..b89f25d
--- /dev/null
+++ b/tests/ref/fate/filter-acrossfade
@@ -0,0 +1,502 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,      888,     3552, 0x592ce6cc
+0,        888,        888,     1024,     4096, 0x20f6f6a9
+0,       1912,       1912,     1024,     4096, 0x3f840122
+0,       2936,       2936,     1024,     4096, 0xa905f9d1
+0,       3960,       3960,     1024,     4096, 0x1547eb1b
+0,       4984,       4984,     1024,     4096, 0xab54067e
+0,       6008,       6008,     1024,     4096, 0x06c6f5ef
+0,       7032,       7032,     1024,     4096, 0xc5c1f5bb
+0,       8056,       8056,     1024,     4096, 0x6a89fd31
+0,       9080,       9080,     1024,     4096, 0xb9d3ffa1
+0,      10104,      10104,     1024,     4096, 0x4262e2ff
+0,      11128,      11128,     1024,     4096, 0x7afffe9d
+0,      12152,      12152,     1024,     4096, 0xdc1d0274
+0,      13176,      13176,     1024,     4096, 0xad97f96f
+0,      14200,      14200,     1024,     4096, 0xb26ee1cb
+0,      15224,      15224,     1024,     4096, 0xbe90fb3d
+0,      16248,      16248,     1024,     4096, 0xf1d30268
+0,      17272,      17272,     1024,     4096, 0x697ffa2d
+0,      18296,      18296,     1024,     4096, 0x5531efc3
+0,      19320,      19320,     1024,     4096, 0xf857f707
+0,      20344,      20344,     1024,     4096, 0x63b005c8
+0,      21368,      21368,     1024,     4096, 0xec82ea67
+0,      22392,      22392,     1024,     4096, 0x9f6dfae9
+0,      23416,      23416,     1024,     4096, 0xdebbfb1d
+0,      24440,      24440,     1024,     4096, 0xd454efab
+0,      25464,      25464,     1024,     4096, 0xd093f135
+0,      26488,      26488,     1024,     4096, 0x52530de6
+0,      27512,      27512,     1024,     4096, 0x23f6f239
+0,      28536,      28536,     1024,     4096, 0xb179ee71
+0,      29560,      29560,     1024,     4096, 0xea3ff767
+0,      30584,      30584,     1024,     4096, 0xf40e0f1c
+0,      31608,      31608,     1024,     4096, 0xc960f597
+0,      32632,      32632,     1024,     4096, 0x9c1bee7d
+0,      33656,      33656,     1024,     4096, 0x20f6f6a9
+0,      34680,      34680,     1024,     4096, 0x3f840122
+0,      35704,      35704,     1024,     4096, 0xa905f9d1
+0,      36728,      36728,     1024,     4096, 0x1547eb1b
+0,      37752,      37752,     1024,     4096, 0xab54067e
+0,      38776,      38776,     1024,     4096, 0x06c6f5ef
+0,      39800,      39800,     1024,     4096, 0xc5c1f5bb
+0,      40824,      40824,     1024,     4096, 0x6a89fd31
+0,      41848,      41848,     1024,     4096, 0xb9d3ffa1
+0,      42872,      42872,     1024,     4096, 0x4262e2ff
+0,      43896,      43896,     1024,     4096, 0x78b0e7fb
+0,      44920,      44920,     1024,     4096, 0x498cf37b
+0,      45944,      45944,     1024,     4096, 0xdedfdf2b
+0,      46968,      46968,     1024,     4096, 0x430efa55
+0,      47992,      47992,     1024,     4096, 0xa487044e
+0,      49016,      49016,     1024,     4096, 0x0dfff373
+0,      50040,      50040,     1024,     4096, 0xf922f9e1
+0,      51064,      51064,     1024,     4096, 0xc577f857
+0,      52088,      52088,     1024,     4096, 0x33b5ee21
+0,      53112,      53112,     1024,     4096, 0x3e5ff725
+0,      54136,      54136,     1024,     4096, 0x909f0630
+0,      55160,      55160,     1024,     4096, 0xe087f33f
+0,      56184,      56184,     1024,     4096, 0x8162efc1
+0,      57208,      57208,     1024,     4096, 0x6c953c36
+0,      58232,      58232,     1024,     4096, 0x413d0d22
+0,      59256,      59256,     1024,     4096, 0xeed90a6c
+0,      60280,      60280,     1024,     4096, 0x15c6f533
+0,      61304,      61304,     1024,     4096, 0xb7a1eb5f
+0,      62328,      62328,     1024,     4096, 0x9a83e815
+0,      63352,      63352,     1024,     4096, 0x3370056e
+0,      64376,      64376,     1024,     4096, 0xea3ee86b
+0,      65400,      65400,     1024,     4096, 0xc05be2c5
+0,      66424,      66424,     1024,     4096, 0x4b41001a
+0,      67448,      67448,     1024,     4096, 0x8aa1fd37
+0,      68472,      68472,     1024,     4096, 0x940df3d9
+0,      69496,      69496,     1024,     4096, 0x6d8f0206
+0,      70520,      70520,     1024,     4096, 0xbfd9dea3
+0,      71544,      71544,     1024,     4096, 0x1e8309a0
+0,      72568,      72568,     1024,     4096, 0xf188fe8d
+0,      73592,      73592,     1024,     4096, 0x498ffb27
+0,      74616,      74616,     1024,     4096, 0x64fc009a
+0,      75640,      75640,     1024,     4096, 0x196df42b
+0,      76664,      76664,     1024,     4096, 0x4863297a
+0,      77688,      77688,     1024,     4096, 0xbaac05c2
+0,      78712,      78712,     1024,     4096, 0xf47e0996
+0,      79736,      79736,     1024,     4096, 0xafa4e80b
+0,      80760,      80760,     1024,     4096, 0x0240f325
+0,      81784,      81784,     1024,     4096, 0x5c1d0962
+0,      82808,      82808,     1024,     4096, 0x5bfa50e2
+0,      83832,      83832,     1024,     4096, 0x666becf9
+0,      84856,      84856,     1024,     4096, 0x96060590
+0,      85880,      85880,     1024,     4096, 0x05060204
+0,      86904,      86904,     1024,     4096, 0x05cf0c16
+0,      87928,      87928,     1024,     4096, 0xb348e18d
+0,      88952,      88952,     1024,     4096, 0xfc88d47b
+0,      89976,      89976,     1024,     4096, 0xd445b2b9
+0,      91000,      91000,     1024,     4096, 0x5d83bd97
+0,      92024,      92024,     1024,     4096, 0x43fa9721
+0,      93048,      93048,     1024,     4096, 0x25219dbd
+0,      94072,      94072,     1024,     4096, 0x1759bc3f
+0,      95096,      95096,     1024,     4096, 0x4925b38d
+0,      96120,      96120,     1024,     4096, 0xa8a7c7e7
+0,      97144,      97144,     1024,     4096, 0x9dbbfe19
+0,      98168,      98168,     1024,     4096, 0x8b2182a9
+0,      99192,      99192,     1024,     4096, 0x3601b417
+0,     100216,     100216,     1024,     4096, 0xdedaed89
+0,     101240,     101240,     1024,     4096, 0xffacd8db
+0,     102264,     102264,     1024,     4096, 0x7df9d58d
+0,     103288,     103288,     1024,     4096, 0x9cecae51
+0,     104312,     104312,     1024,     4096, 0xc163cc3f
+0,     105336,     105336,     1024,     4096, 0x3d25b799
+0,     106360,     106360,     1024,     4096, 0x815192fb
+0,     107384,     107384,     1024,     4096, 0xaeb1ad99
+0,     108408,     108408,     1024,     4096, 0x9f05ed2b
+0,     109432,     109432,     1024,     4096, 0xf3bacd99
+0,     110456,     110456,     1024,     4096, 0x56e4f28b
+0,     111480,     111480,     1024,     4096, 0xe733e81d
+0,     112504,     112504,     1024,     4096, 0x9e54195e
+0,     113528,     113528,     1024,     4096, 0x4e61fa9f
+0,     114552,     114552,     1024,     4096, 0x5425ed95
+0,     115576,     115576,     1024,     4096, 0x0ba4ed4d
+0,     116600,     116600,     1024,     4096, 0x1027fc33
+0,     117624,     117624,     1024,     4096, 0x1622c7e5
+0,     118648,     118648,     1024,     4096, 0x0471ff05
+0,     119672,     119672,     1024,     4096, 0x69a40e10
+0,     120696,     120696,     1024,     4096, 0x22e413ba
+0,     121720,     121720,     1024,     4096, 0x78fafea9
+0,     122744,     122744,     1024,     4096, 0x30f1f61d
+0,     123768,     123768,     1024,     4096, 0x5e24f561
+0,     124792,     124792,     1024,     4096, 0xab19ceb5
+0,     125816,     125816,     1024,     4096, 0x0c16c3dd
+0,     126840,     126840,     1024,     4096, 0xe13afd1b
+0,     127864,     127864,     1024,     4096, 0xb3a0f46d
+0,     128888,     128888,     1024,     4096, 0xe1f4f585
+0,     129912,     129912,     1024,     4096, 0x51cd28e2
+0,     130936,     130936,     1024,     4096, 0x34c1047e
+0,     131960,     131960,     1024,     4096, 0x5c04f360
+0,     132984,     132984,     1024,     4096, 0x17bfe876
+0,     134008,     134008,     1024,     4096, 0x4d7fea40
+0,     135032,     135032,     1024,     4096, 0x8d23f2da
+0,     136056,     136056,     1024,     4096, 0xfc140395
+0,     137080,     137080,     1024,     4096, 0x891f0008
+0,     138104,     138104,     1024,     4096, 0x28d0188a
+0,     139128,     139128,     1024,     4096, 0xbf0df63e
+0,     140152,     140152,     1024,     4096, 0x1751e8f0
+0,     141176,     141176,     1024,     4096, 0xe1beee48
+0,     142200,     142200,     1024,     4096, 0x27adfc7c
+0,     143224,     143224,     1024,     4096, 0x2314d632
+0,     144248,     144248,     1024,     4096, 0xf39aff11
+0,     145272,     145272,     1024,     4096, 0xd1fb0d61
+0,     146296,     146296,     1024,     4096, 0xf51b0083
+0,     147320,     147320,     1024,     4096, 0x9822f530
+0,     148344,     148344,     1024,     4096, 0x6dc8df31
+0,     149368,     149368,     1024,     4096, 0x6f2e0184
+0,     150392,     150392,     1024,     4096, 0x7a9afdb9
+0,     151416,     151416,     1024,     4096, 0x2f85001a
+0,     152440,     152440,     1024,     4096, 0x3a6cf053
+0,     153464,     153464,     1024,     4096, 0x030a131d
+0,     154488,     154488,     1024,     4096, 0xfc050025
+0,     155512,     155512,     1024,     4096, 0xd1a9d654
+0,     156536,     156536,     1024,     4096, 0x199ff4fe
+0,     157560,     157560,     1024,     4096, 0xa84bee80
+0,     158584,     158584,     1024,     4096, 0xda96e946
+0,     159608,     159608,     1024,     4096, 0xc026e284
+0,     160632,     160632,     1024,     4096, 0x1400185d
+0,     161656,     161656,     1024,     4096, 0xd9a2f887
+0,     162680,     162680,     1024,     4096, 0xaa8bfdfe
+0,     163704,     163704,     1024,     4096, 0x49a9e7df
+0,     164728,     164728,     1024,     4096, 0x159e0717
+0,     165752,     165752,     1024,     4096, 0x9a3eff6b
+0,     166776,     166776,     1024,     4096, 0xaa5ef364
+0,     167800,     167800,     1024,     4096, 0x32c20b32
+0,     168824,     168824,     1024,     4096, 0x67f0f55b
+0,     169848,     169848,     1024,     4096, 0x1002eff5
+0,     170872,     170872,     1024,     4096, 0x7fa0ea71
+0,     171896,     171896,     1024,     4096, 0x0c61e8ea
+0,     172920,     172920,     1024,     4096, 0xd68fe4bf
+0,     173944,     173944,     1024,     4096, 0x2aa00648
+0,     174968,     174968,     1024,     4096, 0x74ffeeae
+0,     175992,     175992,      408,     1632, 0x28353dae
+0,     176400,     176400,    88200,   352800, 0x4fb492af
+0,     264600,     264600,     1912,     7648, 0xf0c93a5a
+0,     266512,     266512,     1024,     4096, 0x35b6d595
+0,     267536,     267536,     1024,     4096, 0xc4481118
+0,     268560,     268560,     1024,     4096, 0x5dc0b58d
+0,     269584,     269584,     1024,     4096, 0x4a53a7f1
+0,     270608,     270608,     1024,     4096, 0xc38e9bec
+0,     271632,     271632,     1024,     4096, 0xc9443282
+0,     272656,     272656,     1024,     4096, 0x8018d290
+0,     273680,     273680,     1024,     4096, 0xf32d9a70
+0,     274704,     274704,     1024,     4096, 0xc63ae76a
+0,     275728,     275728,     1024,     4096, 0xcd5d1222
+0,     276752,     276752,     1024,     4096, 0x8226c5de
+0,     277776,     277776,     1024,     4096, 0xf2fb1f27
+0,     278800,     278800,     1024,     4096, 0x9fb0ba34
+0,     279824,     279824,     1024,     4096, 0xf178e325
+0,     280848,     280848,     1024,     4096, 0x9c2b2db4
+0,     281872,     281872,     1024,     4096, 0x1336d63c
+0,     282896,     282896,     1024,     4096, 0x0688ef16
+0,     283920,     283920,     1024,     4096, 0xd833f93f
+0,     284944,     284944,     1024,     4096, 0xab7fad69
+0,     285968,     285968,     1024,     4096, 0x5c3c09fb
+0,     286992,     286992,     1024,     4096, 0x41c9e4ed
+0,     288016,     288016,     1024,     4096, 0xb670a66c
+0,     289040,     289040,     1024,     4096, 0x86a0af26
+0,     290064,     290064,     1024,     4096, 0x55afec1f
+0,     291088,     291088,     1024,     4096, 0x36d51c13
+0,     292112,     292112,     1024,     4096, 0x54a15642
+0,     293136,     293136,     1024,     4096, 0x0e3edeaf
+0,     294160,     294160,     1024,     4096, 0x63d74a2d
+0,     295184,     295184,     1024,     4096, 0x2a60f9ee
+0,     296208,     296208,     1024,     4096, 0xa562fd0b
+0,     297232,     297232,     1024,     4096, 0xf382907c
+0,     298256,     298256,     1024,     4096, 0x32aafa99
+0,     299280,     299280,     1024,     4096, 0xb1da3640
+0,     300304,     300304,     1024,     4096, 0x3da8d51a
+0,     301328,     301328,     1024,     4096, 0x3afe27bc
+0,     302352,     302352,     1024,     4096, 0x05d30d0f
+0,     303376,     303376,     1024,     4096, 0x86214868
+0,     304400,     304400,     1024,     4096, 0x6283507f
+0,     305424,     305424,     1024,     4096, 0x3fb53fe7
+0,     306448,     306448,     1024,     4096, 0x5d907ea8
+0,     307472,     307472,     1024,     4096, 0xa7c389de
+0,     308496,     308496,     1024,     4096, 0xe28ba1f2
+0,     309520,     309520,     1024,     4096, 0x9932afac
+0,     310544,     310544,     1024,     4096, 0x82f1e0c2
+0,     311568,     311568,     1024,     4096, 0x5c80bb5f
+0,     312592,     312592,     1024,     4096, 0x6b73c24f
+0,     313616,     313616,     1024,     4096, 0x22b3ae86
+0,     314640,     314640,     1024,     4096, 0x9ea7b6ec
+0,     315664,     315664,     1024,     4096, 0x5c5813a2
+0,     316688,     316688,     1024,     4096, 0x0058fcee
+0,     317712,     317712,     1024,     4096, 0xc0717d58
+0,     318736,     318736,     1024,     4096, 0xc891c3df
+0,     319760,     319760,     1024,     4096, 0xe4e3ac85
+0,     320784,     320784,     1024,     4096, 0x3bdd40c6
+0,     321808,     321808,     1024,     4096, 0xd57e116c
+0,     322832,     322832,     1024,     4096, 0x494c72ab
+0,     323856,     323856,     1024,     4096, 0xcb661c13
+0,     324880,     324880,     1024,     4096, 0xb55811f9
+0,     325904,     325904,     1024,     4096, 0xbff22c30
+0,     326928,     326928,     1024,     4096, 0x9332e605
+0,     327952,     327952,     1024,     4096, 0x90bb6299
+0,     328976,     328976,     1024,     4096, 0xebdd4500
+0,     330000,     330000,     1024,     4096, 0x3d940413
+0,     331024,     331024,     1024,     4096, 0x3445f60f
+0,     332048,     332048,     1024,     4096, 0x613e016c
+0,     333072,     333072,     1024,     4096, 0xd565de1c
+0,     334096,     334096,     1024,     4096, 0xba771399
+0,     335120,     335120,     1024,     4096, 0x730b7c1e
+0,     336144,     336144,     1024,     4096, 0xc2f003a3
+0,     337168,     337168,     1024,     4096, 0x9186ff8e
+0,     338192,     338192,     1024,     4096, 0x7356b98c
+0,     339216,     339216,     1024,     4096, 0xbc02af51
+0,     340240,     340240,     1024,     4096, 0xac922f72
+0,     341264,     341264,     1024,     4096, 0x53d1060e
+0,     342288,     342288,     1024,     4096, 0xe598611b
+0,     343312,     343312,     1024,     4096, 0xd7ac93df
+0,     344336,     344336,     1024,     4096, 0x59b77247
+0,     345360,     345360,     1024,     4096, 0x206418c9
+0,     346384,     346384,     1024,     4096, 0xd360c906
+0,     347408,     347408,     1024,     4096, 0x7b92c2c0
+0,     348432,     348432,     1024,     4096, 0x021dcb06
+0,     349456,     349456,     1024,     4096, 0xc9b9a3ee
+0,     350480,     350480,     1024,     4096, 0xa6e01534
+0,     351504,     351504,     1024,     4096, 0xb0d74c80
+0,     352528,     352528,     1024,     4096, 0x63f1a8c4
+0,     353552,     353552,     1024,     4096, 0xe45a00df
+0,     354576,     354576,     1024,     4096, 0xd75032fc
+0,     355600,     355600,     1024,     4096, 0x553459cf
+0,     356624,     356624,     1024,     4096, 0x1b33a1bc
+0,     357648,     357648,     1024,     4096, 0x624d9fa5
+0,     358672,     358672,     1024,     4096, 0x69ef01c2
+0,     359696,     359696,     1024,     4096, 0x2abae91b
+0,     360720,     360720,     1024,     4096, 0x677619c8
+0,     361744,     361744,     1024,     4096, 0xdc47f672
+0,     362768,     362768,     1024,     4096, 0x3ca75283
+0,     363792,     363792,     1024,     4096, 0x8edec474
+0,     364816,     364816,     1024,     4096, 0x323d1977
+0,     365840,     365840,     1024,     4096, 0x70d8200e
+0,     366864,     366864,     1024,     4096, 0xf0fc692d
+0,     367888,     367888,     1024,     4096, 0x9d7e9451
+0,     368912,     368912,     1024,     4096, 0x56110ed6
+0,     369936,     369936,     1024,     4096, 0x8308d382
+0,     370960,     370960,     1024,     4096, 0xc12e8455
+0,     371984,     371984,     1024,     4096, 0xbab70fc3
+0,     373008,     373008,     1024,     4096, 0x3974c794
+0,     374032,     374032,     1024,     4096, 0x92268867
+0,     375056,     375056,     1024,     4096, 0x07bc5db6
+0,     376080,     376080,     1024,     4096, 0x3a69a60c
+0,     377104,     377104,     1024,     4096, 0x213b8da2
+0,     378128,     378128,     1024,     4096, 0x39ddbcb5
+0,     379152,     379152,     1024,     4096, 0x6b107851
+0,     380176,     380176,     1024,     4096, 0xaa735be6
+0,     381200,     381200,     1024,     4096, 0x3becca60
+0,     382224,     382224,     1024,     4096, 0x1383217b
+0,     383248,     383248,     1024,     4096, 0x2a93fb25
+0,     384272,     384272,     1024,     4096, 0x057e076d
+0,     385296,     385296,     1024,     4096, 0xf306219b
+0,     386320,     386320,     1024,     4096, 0x3d1f238b
+0,     387344,     387344,     1024,     4096, 0x4bdaeb13
+0,     388368,     388368,     1024,     4096, 0xbe12e587
+0,     389392,     389392,     1024,     4096, 0xf428fc99
+0,     390416,     390416,     1024,     4096, 0x25131fac
+0,     391440,     391440,     1024,     4096, 0xaaddd43a
+0,     392464,     392464,     1024,     4096, 0x082d1b1f
+0,     393488,     393488,     1024,     4096, 0xec8d6067
+0,     394512,     394512,     1024,     4096, 0x69880a4a
+0,     395536,     395536,     1024,     4096, 0x98892785
+0,     396560,     396560,     1024,     4096, 0x90d48fe5
+0,     397584,     397584,     1024,     4096, 0xf2c77de0
+0,     398608,     398608,     1024,     4096, 0xbf883f1e
+0,     399632,     399632,     1024,     4096, 0x2366eed3
+0,     400656,     400656,     1024,     4096, 0x99a61a4b
+0,     401680,     401680,     1024,     4096, 0x6496ff68
+0,     402704,     402704,     1024,     4096, 0x43d4ae23
+0,     403728,     403728,     1024,     4096, 0xfcbbdd39
+0,     404752,     404752,     1024,     4096, 0x8e8491d2
+0,     405776,     405776,     1024,     4096, 0x166bdaa7
+0,     406800,     406800,     1024,     4096, 0x5936e4de
+0,     407824,     407824,     1024,     4096, 0x5da0f74c
+0,     408848,     408848,     1024,     4096, 0x284c1816
+0,     409872,     409872,     1024,     4096, 0x9ae2fb10
+0,     410896,     410896,     1024,     4096, 0xef4f09f9
+0,     411920,     411920,     1024,     4096, 0x7d7146b2
+0,     412944,     412944,     1024,     4096, 0x3543f90c
+0,     413968,     413968,     1024,     4096, 0x9f350dea
+0,     414992,     414992,     1024,     4096, 0x89a761f8
+0,     416016,     416016,     1024,     4096, 0x7ed69125
+0,     417040,     417040,     1024,     4096, 0x75ddbd7b
+0,     418064,     418064,     1024,     4096, 0xb59ff6ba
+0,     419088,     419088,     1024,     4096, 0xbe8e35d8
+0,     420112,     420112,     1024,     4096, 0x9c3acb27
+0,     421136,     421136,     1024,     4096, 0x8bdefcc4
+0,     422160,     422160,     1024,     4096, 0xd9796b89
+0,     423184,     423184,     1024,     4096, 0x09ef18e5
+0,     424208,     424208,     1024,     4096, 0xa34eec05
+0,     425232,     425232,     1024,     4096, 0x59a4e5fe
+0,     426256,     426256,     1024,     4096, 0x7cf68f50
+0,     427280,     427280,     1024,     4096, 0x5635a169
+0,     428304,     428304,     1024,     4096, 0x9c8ba2ee
+0,     429328,     429328,     1024,     4096, 0x31bda22b
+0,     430352,     430352,     1024,     4096, 0xd33732d9
+0,     431376,     431376,     1024,     4096, 0x6041e3bf
+0,     432400,     432400,     1024,     4096, 0x7661d8e4
+0,     433424,     433424,     1024,     4096, 0x8744e56f
+0,     434448,     434448,     1024,     4096, 0x0d90222c
+0,     435472,     435472,     1024,     4096, 0xb749b6ee
+0,     436496,     436496,     1024,     4096, 0xc501e611
+0,     437520,     437520,     1024,     4096, 0x54bc9dae
+0,     438544,     438544,     1024,     4096, 0x7ebd8901
+0,     439568,     439568,     1024,     4096, 0xd48f55ab
+0,     440592,     440592,     1024,     4096, 0xf1f0979b
+0,     441616,     441616,     1024,     4096, 0x0532a2d2
+0,     442640,     442640,     1024,     4096, 0x1000e7a2
+0,     443664,     443664,     1024,     4096, 0x461d9b08
+0,     444688,     444688,     1024,     4096, 0xb119bcf8
+0,     445712,     445712,     1024,     4096, 0x03f2eb83
+0,     446736,     446736,     1024,     4096, 0xeba9f3b4
+0,     447760,     447760,     1024,     4096, 0x9a6ffc8e
+0,     448784,     448784,     1024,     4096, 0x52f54bc2
+0,     449808,     449808,     1024,     4096, 0xd17ec7d6
+0,     450832,     450832,     1024,     4096, 0x18b01fba
+0,     451856,     451856,     1024,     4096, 0x5d5af13e
+0,     452880,     452880,     1024,     4096, 0xe04a2919
+0,     453904,     453904,     1024,     4096, 0xc68c00b2
+0,     454928,     454928,     1024,     4096, 0x83a17a70
+0,     455952,     455952,     1024,     4096, 0x9de07f7f
+0,     456976,     456976,     1024,     4096, 0x2ef91463
+0,     458000,     458000,     1024,     4096, 0x9eaee29e
+0,     459024,     459024,     1024,     4096, 0xdfe3010b
+0,     460048,     460048,     1024,     4096, 0x0b0828b4
+0,     461072,     461072,     1024,     4096, 0x3ba8cee9
+0,     462096,     462096,     1024,     4096, 0x4b8bfe1f
+0,     463120,     463120,     1024,     4096, 0xc9da5ee4
+0,     464144,     464144,     1024,     4096, 0x951f70f3
+0,     465168,     465168,     1024,     4096, 0xba34e5a5
+0,     466192,     466192,     1024,     4096, 0x433716a1
+0,     467216,     467216,     1024,     4096, 0x39b24efb
+0,     468240,     468240,     1024,     4096, 0xe4a4b039
+0,     469264,     469264,     1024,     4096, 0x7906f2e6
+0,     470288,     470288,     1024,     4096, 0x40c8c726
+0,     471312,     471312,     1024,     4096, 0x6554cc46
+0,     472336,     472336,     1024,     4096, 0xf5b5d919
+0,     473360,     473360,     1024,     4096, 0x4437d4b0
+0,     474384,     474384,     1024,     4096, 0xa291f38f
+0,     475408,     475408,     1024,     4096, 0x0f81ad0b
+0,     476432,     476432,     1024,     4096, 0x4fb2c3e0
+0,     477456,     477456,     1024,     4096, 0xa2be4072
+0,     478480,     478480,     1024,     4096, 0x0674126f
+0,     479504,     479504,     1024,     4096, 0x3ab7e86c
+0,     480528,     480528,     1024,     4096, 0x736e87ae
+0,     481552,     481552,     1024,     4096, 0x1a050d8d
+0,     482576,     482576,     1024,     4096, 0xe92a59df
+0,     483600,     483600,     1024,     4096, 0xed8cb3bf
+0,     484624,     484624,     1024,     4096, 0xb5520d14
+0,     485648,     485648,     1024,     4096, 0x437d4e88
+0,     486672,     486672,     1024,     4096, 0xc67a4422
+0,     487696,     487696,     1024,     4096, 0x1f7f912d
+0,     488720,     488720,     1024,     4096, 0x67429495
+0,     489744,     489744,     1024,     4096, 0xd7ffb252
+0,     490768,     490768,     1024,     4096, 0x517ade18
+0,     491792,     491792,     1024,     4096, 0x527a31d7
+0,     492816,     492816,     1024,     4096, 0xdbc0a560
+0,     493840,     493840,     1024,     4096, 0x029048da
+0,     494864,     494864,     1024,     4096, 0x85df6c55
+0,     495888,     495888,     1024,     4096, 0xc68983a2
+0,     496912,     496912,     1024,     4096, 0x951a140b
+0,     497936,     497936,     1024,     4096, 0xc1560b9b
+0,     498960,     498960,     1024,     4096, 0xb27302c3
+0,     499984,     499984,     1024,     4096, 0x50ad5360
+0,     501008,     501008,     1024,     4096, 0x1ccbf240
+0,     502032,     502032,     1024,     4096, 0x85b2a928
+0,     503056,     503056,     1024,     4096, 0xd3f8d0b8
+0,     504080,     504080,     1024,     4096, 0xe7833196
+0,     505104,     505104,     1024,     4096, 0xd6ac1184
+0,     506128,     506128,     1024,     4096, 0x27466545
+0,     507152,     507152,     1024,     4096, 0x11119fb9
+0,     508176,     508176,     1024,     4096, 0x6b383b60
+0,     509200,     509200,     1024,     4096, 0x14f78f30
+0,     510224,     510224,     1024,     4096, 0xda4c3aca
+0,     511248,     511248,     1024,     4096, 0xdd24bf6e
+0,     512272,     512272,     1024,     4096, 0x165d0a06
+0,     513296,     513296,     1024,     4096, 0x42e5407b
+0,     514320,     514320,     1024,     4096, 0x8e5d3def
+0,     515344,     515344,     1024,     4096, 0x367c9896
+0,     516368,     516368,     1024,     4096, 0xe27455a0
+0,     517392,     517392,     1024,     4096, 0xb331cb8c
+0,     518416,     518416,     1024,     4096, 0x8cf7fa69
+0,     519440,     519440,     1024,     4096, 0x713f08f7
+0,     520464,     520464,     1024,     4096, 0x9308e552
+0,     521488,     521488,     1024,     4096, 0xb14cf9bd
+0,     522512,     522512,     1024,     4096, 0xf408d356
+0,     523536,     523536,     1024,     4096, 0xe4adda2e
+0,     524560,     524560,     1024,     4096, 0x62ca992c
+0,     525584,     525584,     1024,     4096, 0xedcb7048
+0,     526608,     526608,     1024,     4096, 0xfafd3ac3
+0,     527632,     527632,     1024,     4096, 0x4018aec3
+0,     528656,     528656,     1024,     4096, 0x7e0a0e23
+0,     529680,     529680,     1024,     4096, 0xb58992db
+0,     530704,     530704,     1024,     4096, 0xe39b3301
+0,     531728,     531728,     1024,     4096, 0x2c9a85bb
+0,     532752,     532752,     1024,     4096, 0x0aae1d68
+0,     533776,     533776,     1024,     4096, 0x36f8b423
+0,     534800,     534800,     1024,     4096, 0x44c10fec
+0,     535824,     535824,     1024,     4096, 0xc0b5e715
+0,     536848,     536848,     1024,     4096, 0xa09ff7ec
+0,     537872,     537872,     1024,     4096, 0x53d42436
+0,     538896,     538896,     1024,     4096, 0x1d630a0a
+0,     539920,     539920,     1024,     4096, 0x71a1f91c
+0,     540944,     540944,     1024,     4096, 0x65331b70
+0,     541968,     541968,     1024,     4096, 0x8cd33518
+0,     542992,     542992,     1024,     4096, 0x067de410
+0,     544016,     544016,     1024,     4096, 0x8d4a4618
+0,     545040,     545040,     1024,     4096, 0x3632d993
+0,     546064,     546064,     1024,     4096, 0x6259b193
+0,     547088,     547088,     1024,     4096, 0xbdb7bcbf
+0,     548112,     548112,     1024,     4096, 0x8625af9b
+0,     549136,     549136,     1024,     4096, 0x4d3e7b07
+0,     550160,     550160,     1024,     4096, 0x76d6cf52
+0,     551184,     551184,     1024,     4096, 0x54f07eb8
+0,     552208,     552208,     1024,     4096, 0x93cb65a1
+0,     553232,     553232,     1024,     4096, 0x5f9b3df7
+0,     554256,     554256,     1024,     4096, 0x5fa8e05e
+0,     555280,     555280,     1024,     4096, 0xeaebf0ab
+0,     556304,     556304,     1024,     4096, 0xd317ed69
+0,     557328,     557328,     1024,     4096, 0x66fd1a32
+0,     558352,     558352,     1024,     4096, 0x9608a614
+0,     559376,     559376,     1024,     4096, 0xa1c661c6
+0,     560400,     560400,     1024,     4096, 0xaa21d89e
+0,     561424,     561424,     1024,     4096, 0xca8820c0
+0,     562448,     562448,     1024,     4096, 0x25c4a979
+0,     563472,     563472,     1024,     4096, 0xfc1ae730
+0,     564496,     564496,     1024,     4096, 0xd681f6cb
+0,     565520,     565520,     1024,     4096, 0x4f8497ca
+0,     566544,     566544,     1024,     4096, 0xc1a033d6
+0,     567568,     567568,     1024,     4096, 0xada5f805
+0,     568592,     568592,     1024,     4096, 0x75ee4703
+0,     569616,     569616,     1024,     4096, 0x722521ff
+0,     570640,     570640,     1024,     4096, 0xd26c503f
+0,     571664,     571664,     1024,     4096, 0x9f62715e
+0,     572688,     572688,     1024,     4096, 0x32ff9d07
+0,     573712,     573712,     1024,     4096, 0x333646aa
+0,     574736,     574736,     1024,     4096, 0x9c590e90
+0,     575760,     575760,     1024,     4096, 0x5ed119e1
+0,     576784,     576784,     1024,     4096, 0xde2a8d38
+0,     577808,     577808,     1024,     4096, 0xdad9fca7
+0,     578832,     578832,     1024,     4096, 0x51f5e65d
+0,     579856,     579856,     1024,     4096, 0x61910e01
+0,     580880,     580880,     1024,     4096, 0xb4d10d4f
+0,     581904,     581904,     1024,     4096, 0x892a5875
+0,     582928,     582928,     1024,     4096, 0x64c828e5
+0,     583952,     583952,     1024,     4096, 0x6db0da46
+0,     584976,     584976,     1024,     4096, 0x9c10dc3f
+0,     586000,     586000,     1024,     4096, 0x96c02ce6
+0,     587024,     587024,     1024,     4096, 0x3bec5ed2
+0,     588048,     588048,     1024,     4096, 0x40f263f0
+0,     589072,     589072,     1024,     4096, 0x7750137d
+0,     590096,     590096,     1024,     4096, 0x044dc19b
+0,     591120,     591120,     1024,     4096, 0x58a8dda4
+0,     592144,     592144,     1024,     4096, 0xe02ec285
+0,     593168,     593168,     1024,     4096, 0x722a2f2a
+0,     594192,     594192,     1024,     4096, 0xca5e4d42
+0,     595216,     595216,      134,      536, 0x45fd3d3d
diff --git a/tests/ref/fate/filter-adelay b/tests/ref/fate/filter-adelay
index ac1c584..a03f516 100644
--- a/tests/ref/fate/filter-adelay
+++ b/tests/ref/fate/filter-adelay
@@ -1,4 +1,8 @@
 #tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
 0,          0,          0,     1024,     4096, 0x9d7bf760
 0,       1024,       1024,     1024,     4096, 0xdf42c46b
 0,       2048,       2048,     1024,     4096, 0x2214fd20
diff --git a/tests/ref/fate/filter-aecho b/tests/ref/fate/filter-aecho
new file mode 100644
index 0000000..f564fcc
--- /dev/null
+++ b/tests/ref/fate/filter-aecho
@@ -0,0 +1,265 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0x3019edd5
+0,       1024,       1024,     1024,     4096, 0x2df2fe2f
+0,       2048,       2048,     1024,     4096, 0xde37ff37
+0,       3072,       3072,     1024,     4096, 0xe933f6a5
+0,       4096,       4096,     1024,     4096, 0xd5acf1f3
+0,       5120,       5120,     1024,     4096, 0x82a6f903
+0,       6144,       6144,     1024,     4096, 0x1792f923
+0,       7168,       7168,     1024,     4096, 0x01500504
+0,       8192,       8192,     1024,     4096, 0xe306efc3
+0,       9216,       9216,     1024,     4096, 0x3abcecaf
+0,      10240,      10240,     1024,     4096, 0x5059f861
+0,      11264,      11264,     1024,     4096, 0xc172ff61
+0,      12288,      12288,     1024,     4096, 0x857dfc1b
+0,      13312,      13312,     1024,     4096, 0x5899ed35
+0,      14336,      14336,     1024,     4096, 0x9ae9f709
+0,      15360,      15360,     1024,     4096, 0xd5620036
+0,      16384,      16384,     1024,     4096, 0xc5ba0940
+0,      17408,      17408,     1024,     4096, 0x0c3af2ff
+0,      18432,      18432,     1024,     4096, 0x5eddf1b1
+0,      19456,      19456,     1024,     4096, 0x9ec8f84d
+0,      20480,      20480,     1024,     4096, 0x8a4f00ee
+0,      21504,      21504,     1024,     4096, 0x0cd3fbe7
+0,      22528,      22528,     1024,     4096, 0x2ce0f199
+0,      23552,      23552,     1024,     4096, 0x9086e9bb
+0,      24576,      24576,     1024,     4096, 0x0d6efb0b
+0,      25600,      25600,     1024,     4096, 0x9dee020c
+0,      26624,      26624,     1024,     4096, 0x96aff453
+0,      27648,      27648,     1024,     4096, 0xe1e9f177
+0,      28672,      28672,     1024,     4096, 0x13b8f893
+0,      29696,      29696,     1024,     4096, 0x4f3a01c8
+0,      30720,      30720,     1024,     4096, 0xa498fa25
+0,      31744,      31744,     1024,     4096, 0x0cd3f293
+0,      32768,      32768,     1024,     4096, 0x6de2eb8f
+0,      33792,      33792,     1024,     4096, 0x0a0d01dc
+0,      34816,      34816,     1024,     4096, 0xde37ff37
+0,      35840,      35840,     1024,     4096, 0xe933f6a5
+0,      36864,      36864,     1024,     4096, 0xd5acf1f3
+0,      37888,      37888,     1024,     4096, 0x82a6f903
+0,      38912,      38912,     1024,     4096, 0x1792f923
+0,      39936,      39936,     1024,     4096, 0x01500504
+0,      40960,      40960,     1024,     4096, 0xe306efc3
+0,      41984,      41984,     1024,     4096, 0x3abcecaf
+0,      43008,      43008,     1024,     4096, 0x5059f861
+0,      44032,      44032,     1024,     4096, 0x9128d187
+0,      45056,      45056,     1024,     4096, 0x61471c76
+0,      46080,      46080,     1024,     4096, 0xd4057d4f
+0,      47104,      47104,     1024,     4096, 0xe5fed87f
+0,      48128,      48128,     1024,     4096, 0x5b0d059a
+0,      49152,      49152,     1024,     4096, 0xfba4c1ad
+0,      50176,      50176,     1024,     4096, 0x4c83f489
+0,      51200,      51200,     1024,     4096, 0xdbebe473
+0,      52224,      52224,     1024,     4096, 0x86efd467
+0,      53248,      53248,     1024,     4096, 0x1919f2f1
+0,      54272,      54272,     1024,     4096, 0x745b12d8
+0,      55296,      55296,     1024,     4096, 0xca86ff49
+0,      56320,      56320,     1024,     4096, 0x2914fdf3
+0,      57344,      57344,     1024,     4096, 0xf949f24f
+0,      58368,      58368,     1024,     4096, 0x6436f791
+0,      59392,      59392,     1024,     4096, 0x693eebaf
+0,      60416,      60416,     1024,     4096, 0xd0740bf0
+0,      61440,      61440,     1024,     4096, 0x08690478
+0,      62464,      62464,     1024,     4096, 0x23a8e259
+0,      63488,      63488,     1024,     4096, 0xba2d0152
+0,      64512,      64512,     1024,     4096, 0xbe65117e
+0,      65536,      65536,     1024,     4096, 0xc8710c58
+0,      66560,      66560,     1024,     4096, 0x25db1d60
+0,      67584,      67584,     1024,     4096, 0xf960016e
+0,      68608,      68608,     1024,     4096, 0x4db0f367
+0,      69632,      69632,     1024,     4096, 0x4154e591
+0,      70656,      70656,     1024,     4096, 0x8c95162c
+0,      71680,      71680,     1024,     4096, 0x2502ffa9
+0,      72704,      72704,     1024,     4096, 0xe66a0792
+0,      73728,      73728,     1024,     4096, 0x6837e7fd
+0,      74752,      74752,     1024,     4096, 0x9613e317
+0,      75776,      75776,     1024,     4096, 0xe087ea1f
+0,      76800,      76800,     1024,     4096, 0x625ae70f
+0,      77824,      77824,     1024,     4096, 0xd9b7fbbb
+0,      78848,      78848,     1024,     4096, 0xb2f800e0
+0,      79872,      79872,     1024,     4096, 0x4fb0134c
+0,      80896,      80896,     1024,     4096, 0xf90ed3ab
+0,      81920,      81920,     1024,     4096, 0x8c13fd53
+0,      82944,      82944,     1024,     4096, 0xdf26d95b
+0,      83968,      83968,     1024,     4096, 0x45e707fc
+0,      84992,      84992,     1024,     4096, 0xd576fe23
+0,      86016,      86016,     1024,     4096, 0x168405f4
+0,      87040,      87040,     1024,     4096, 0x4a78db97
+0,      88064,      88064,     1024,     4096, 0x6d87f713
+0,      89088,      89088,     1024,     4096, 0x30750408
+0,      90112,      90112,     1024,     4096, 0xb011e7b5
+0,      91136,      91136,     1024,     4096, 0x19090af4
+0,      92160,      92160,     1024,     4096, 0x3122f1a7
+0,      93184,      93184,     1024,     4096, 0x3dc4b113
+0,      94208,      94208,     1024,     4096, 0x23c4ec7b
+0,      95232,      95232,     1024,     4096, 0x3340159a
+0,      96256,      96256,     1024,     4096, 0xb06cda91
+0,      97280,      97280,     1024,     4096, 0xd17445ec
+0,      98304,      98304,     1024,     4096, 0xd222d3a1
+0,      99328,      99328,     1024,     4096, 0xd855e61d
+0,     100352,     100352,     1024,     4096, 0x444eebc5
+0,     101376,     101376,     1024,     4096, 0xad3607c0
+0,     102400,     102400,     1024,     4096, 0x549b1aca
+0,     103424,     103424,     1024,     4096, 0x7c6a0a1a
+0,     104448,     104448,     1024,     4096, 0x04d2b3e9
+0,     105472,     105472,     1024,     4096, 0xf15d0216
+0,     106496,     106496,     1024,     4096, 0x5d15f709
+0,     107520,     107520,     1024,     4096, 0x47a7178e
+0,     108544,     108544,     1024,     4096, 0x2aa5e665
+0,     109568,     109568,     1024,     4096, 0x2a9f1a08
+0,     110592,     110592,     1024,     4096, 0xeaa6e103
+0,     111616,     111616,     1024,     4096, 0x8ae100d6
+0,     112640,     112640,     1024,     4096, 0x9585251c
+0,     113664,     113664,     1024,     4096, 0x5eb2289a
+0,     114688,     114688,     1024,     4096, 0x0d0c0cfc
+0,     115712,     115712,     1024,     4096, 0x7e5cd58f
+0,     116736,     116736,     1024,     4096, 0xca3fc9c7
+0,     117760,     117760,     1024,     4096, 0xdda3ebe7
+0,     118784,     118784,     1024,     4096, 0x084dcb41
+0,     119808,     119808,     1024,     4096, 0x0adc2a9c
+0,     120832,     120832,     1024,     4096, 0x64b0fa0f
+0,     121856,     121856,     1024,     4096, 0x225ffadd
+0,     122880,     122880,     1024,     4096, 0x40b0a487
+0,     123904,     123904,     1024,     4096, 0xc2edf0f3
+0,     124928,     124928,     1024,     4096, 0x5078d595
+0,     125952,     125952,     1024,     4096, 0x4ac9bb29
+0,     126976,     126976,     1024,     4096, 0x8a50ad77
+0,     128000,     128000,     1024,     4096, 0xf6bbebc7
+0,     129024,     129024,     1024,     4096, 0x9d33ca29
+0,     130048,     130048,     1024,     4096, 0x863b9ba7
+0,     131072,     131072,     1024,     4096, 0x41cbf17f
+0,     132096,     132096,     1024,     4096, 0x519df567
+0,     133120,     133120,     1024,     4096, 0x59b50359
+0,     134144,     134144,     1024,     4096, 0x5640f0fc
+0,     135168,     135168,     1024,     4096, 0x547df2b8
+0,     136192,     136192,     1024,     4096, 0xae6af2a8
+0,     137216,     137216,     1024,     4096, 0xb370f9ee
+0,     138240,     138240,     1024,     4096, 0x0d691a7f
+0,     139264,     139264,     1024,     4096, 0x8b2cf30d
+0,     140288,     140288,     1024,     4096, 0x8868efce
+0,     141312,     141312,     1024,     4096, 0x6602eb88
+0,     142336,     142336,     1024,     4096, 0x5fbbefd4
+0,     143360,     143360,     1024,     4096, 0xdf81e435
+0,     144384,     144384,     1024,     4096, 0x06b4e637
+0,     145408,     145408,     1024,     4096, 0x741803fb
+0,     146432,     146432,     1024,     4096, 0xf2a7dff9
+0,     147456,     147456,     1024,     4096, 0xbd2ffe0b
+0,     148480,     148480,     1024,     4096, 0xed19f9eb
+0,     149504,     149504,     1024,     4096, 0xa3c4f4a4
+0,     150528,     150528,     1024,     4096, 0xfac20796
+0,     151552,     151552,     1024,     4096, 0x315cf81e
+0,     152576,     152576,     1024,     4096, 0xaf0df76e
+0,     153600,     153600,     1024,     4096, 0x6f92e4ca
+0,     154624,     154624,     1024,     4096, 0xad32079c
+0,     155648,     155648,     1024,     4096, 0xcd03e6e7
+0,     156672,     156672,     1024,     4096, 0xff01f923
+0,     157696,     157696,     1024,     4096, 0xee4d1713
+0,     158720,     158720,     1024,     4096, 0x8db9e3f4
+0,     159744,     159744,     1024,     4096, 0xeef9f20a
+0,     160768,     160768,     1024,     4096, 0xa329d900
+0,     161792,     161792,     1024,     4096, 0xf9d0003b
+0,     162816,     162816,     1024,     4096, 0x9e42f62c
+0,     163840,     163840,     1024,     4096, 0x31f2ee64
+0,     164864,     164864,     1024,     4096, 0x8d340bb6
+0,     165888,     165888,     1024,     4096, 0xd7cbf004
+0,     166912,     166912,     1024,     4096, 0x262105c9
+0,     167936,     167936,     1024,     4096, 0xf3d30dc7
+0,     168960,     168960,     1024,     4096, 0x09adf291
+0,     169984,     169984,     1024,     4096, 0xf2b207e3
+0,     171008,     171008,     1024,     4096, 0x58df0639
+0,     172032,     172032,     1024,     4096, 0x373ad9cd
+0,     173056,     173056,     1024,     4096, 0xb0b2fc8b
+0,     174080,     174080,     1024,     4096, 0xb72af6b8
+0,     175104,     175104,     1024,     4096, 0xcee1f544
+0,     176128,     176128,     1024,     4096, 0xe88dded4
+0,     177152,     177152,     1024,     4096, 0xc606e4d4
+0,     178176,     178176,     1024,     4096, 0x6220006d
+0,     179200,     179200,     1024,     4096, 0xde870592
+0,     180224,     180224,     1024,     4096, 0xb5a6eaaf
+0,     181248,     181248,     1024,     4096, 0xe4eaf266
+0,     182272,     182272,     1024,     4096, 0xdb55f225
+0,     183296,     183296,     1024,     4096, 0x40550828
+0,     184320,     184320,     1024,     4096, 0x3f80fabd
+0,     185344,     185344,     1024,     4096, 0xe9c8eb8d
+0,     186368,     186368,     1024,     4096, 0xd25fe663
+0,     187392,     187392,     1024,     4096, 0x41720adb
+0,     188416,     188416,     1024,     4096, 0x5fd1fc96
+0,     189440,     189440,     1024,     4096, 0x007cf9ec
+0,     190464,     190464,     1024,     4096, 0xeab3efe0
+0,     191488,     191488,     1024,     4096, 0xcb75ee4c
+0,     192512,     192512,     1024,     4096, 0xd866f6c1
+0,     193536,     193536,     1024,     4096, 0xe0c4f911
+0,     194560,     194560,     1024,     4096, 0x7268e790
+0,     195584,     195584,     1024,     4096, 0x6258ee4a
+0,     196608,     196608,     1024,     4096, 0x880b003a
+0,     197632,     197632,     1024,     4096, 0x117bfd71
+0,     198656,     198656,     1024,     4096, 0x1b7900c7
+0,     199680,     199680,     1024,     4096, 0xcf3fe8b5
+0,     200704,     200704,     1024,     4096, 0x9de2f010
+0,     201728,     201728,     1024,     4096, 0xe6b4ff4a
+0,     202752,     202752,     1024,     4096, 0x37420c72
+0,     203776,     203776,     1024,     4096, 0x0560e821
+0,     204800,     204800,     1024,     4096, 0xd676f037
+0,     205824,     205824,     1024,     4096, 0xe141f3e1
+0,     206848,     206848,     1024,     4096, 0x8af10210
+0,     207872,     207872,     1024,     4096, 0x30c5fb99
+0,     208896,     208896,     1024,     4096, 0x39cdf501
+0,     209920,     209920,     1024,     4096, 0x8e37f69d
+0,     210944,     210944,     1024,     4096, 0x6220006d
+0,     211968,     211968,     1024,     4096, 0xde870592
+0,     212992,     212992,     1024,     4096, 0xb5a6eaaf
+0,     214016,     214016,     1024,     4096, 0xe4eaf266
+0,     215040,     215040,     1024,     4096, 0xdb55f225
+0,     216064,     216064,     1024,     4096, 0x40550828
+0,     217088,     217088,     1024,     4096, 0x3f80fabd
+0,     218112,     218112,     1024,     4096, 0xe9c8eb8d
+0,     219136,     219136,     1024,     4096, 0xd25fe663
+0,     220160,     220160,     1024,     4096, 0x41720adb
+0,     221184,     221184,     1024,     4096, 0x5fd1fc96
+0,     222208,     222208,     1024,     4096, 0x007cf9ec
+0,     223232,     223232,     1024,     4096, 0xeab3efe0
+0,     224256,     224256,     1024,     4096, 0xcb75ee4c
+0,     225280,     225280,     1024,     4096, 0xd866f6c1
+0,     226304,     226304,     1024,     4096, 0xe0c4f911
+0,     227328,     227328,     1024,     4096, 0x7268e790
+0,     228352,     228352,     1024,     4096, 0x6258ee4a
+0,     229376,     229376,     1024,     4096, 0x880b003a
+0,     230400,     230400,     1024,     4096, 0x117bfd71
+0,     231424,     231424,     1024,     4096, 0x1b7900c7
+0,     232448,     232448,     1024,     4096, 0xcf3fe8b5
+0,     233472,     233472,     1024,     4096, 0x9de2f010
+0,     234496,     234496,     1024,     4096, 0xe6b4ff4a
+0,     235520,     235520,     1024,     4096, 0x37420c72
+0,     236544,     236544,     1024,     4096, 0x0560e821
+0,     237568,     237568,     1024,     4096, 0xd676f037
+0,     238592,     238592,     1024,     4096, 0xe141f3e1
+0,     239616,     239616,     1024,     4096, 0x8af10210
+0,     240640,     240640,     1024,     4096, 0x30c5fb99
+0,     241664,     241664,     1024,     4096, 0x39cdf501
+0,     242688,     242688,     1024,     4096, 0x8e37f69d
+0,     243712,     243712,     1024,     4096, 0x6220006d
+0,     244736,     244736,     1024,     4096, 0xde870592
+0,     245760,     245760,     1024,     4096, 0xb5a6eaaf
+0,     246784,     246784,     1024,     4096, 0xe4eaf266
+0,     247808,     247808,     1024,     4096, 0xdb55f225
+0,     248832,     248832,     1024,     4096, 0x40550828
+0,     249856,     249856,     1024,     4096, 0x3f80fabd
+0,     250880,     250880,     1024,     4096, 0xe9c8eb8d
+0,     251904,     251904,     1024,     4096, 0xd25fe663
+0,     252928,     252928,     1024,     4096, 0x41720adb
+0,     253952,     253952,     1024,     4096, 0x5fd1fc96
+0,     254976,     254976,     1024,     4096, 0x007cf9ec
+0,     256000,     256000,     1024,     4096, 0xeab3efe0
+0,     257024,     257024,     1024,     4096, 0xcb75ee4c
+0,     258048,     258048,     1024,     4096, 0xd866f6c1
+0,     259072,     259072,     1024,     4096, 0xe0c4f911
+0,     260096,     260096,     1024,     4096, 0x7268e790
+0,     261120,     261120,     1024,     4096, 0x6258ee4a
+0,     262144,     262144,     1024,     4096, 0x880b003a
+0,     263168,     263168,     1024,     4096, 0x117bfd71
+0,     264192,     264192,      408,     1632, 0x495d360a
+0,     264600,     264600,     1411,     5644, 0x34920173
diff --git a/tests/ref/fate/filter-aemphasis b/tests/ref/fate/filter-aemphasis
new file mode 100644
index 0000000..9509e43
--- /dev/null
+++ b/tests/ref/fate/filter-aemphasis
@@ -0,0 +1,528 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0xb9c5fefd
+0,       1024,       1024,     1024,     4096, 0xb2ae0a90
+0,       2048,       2048,     1024,     4096, 0x97e6e9f3
+0,       3072,       3072,     1024,     4096, 0x5837f26f
+0,       4096,       4096,     1024,     4096, 0x71500376
+0,       5120,       5120,     1024,     4096, 0xb4650378
+0,       6144,       6144,     1024,     4096, 0xd261f5b1
+0,       7168,       7168,     1024,     4096, 0x3038f3fd
+0,       8192,       8192,     1024,     4096, 0x8e1908c6
+0,       9216,       9216,     1024,     4096, 0x1d6bfd33
+0,      10240,      10240,     1024,     4096, 0x7036f23f
+0,      11264,      11264,     1024,     4096, 0xaf73e9a1
+0,      12288,      12288,     1024,     4096, 0x0ba70404
+0,      13312,      13312,     1024,     4096, 0xd34bf249
+0,      14336,      14336,     1024,     4096, 0x0c88fc2b
+0,      15360,      15360,     1024,     4096, 0x55ebf9cf
+0,      16384,      16384,     1024,     4096, 0xc16df0bd
+0,      17408,      17408,     1024,     4096, 0xa635eac5
+0,      18432,      18432,     1024,     4096, 0xb41d059e
+0,      19456,      19456,     1024,     4096, 0xa905f4d3
+0,      20480,      20480,     1024,     4096, 0x2736f1fb
+0,      21504,      21504,     1024,     4096, 0x1a89f007
+0,      22528,      22528,     1024,     4096, 0x81d1fdab
+0,      23552,      23552,     1024,     4096, 0x6156f97d
+0,      24576,      24576,     1024,     4096, 0x1971ec89
+0,      25600,      25600,     1024,     4096, 0xdca1ec4f
+0,      26624,      26624,     1024,     4096, 0x116ffcf5
+0,      27648,      27648,     1024,     4096, 0xc391fdc9
+0,      28672,      28672,     1024,     4096, 0x85e0ef45
+0,      29696,      29696,     1024,     4096, 0x81d3012c
+0,      30720,      30720,     1024,     4096, 0x403ef11b
+0,      31744,      31744,     1024,     4096, 0x3ca6f16d
+0,      32768,      32768,     1024,     4096, 0x6775feb1
+0,      33792,      33792,     1024,     4096, 0xb2ae0a90
+0,      34816,      34816,     1024,     4096, 0x97e6e9f3
+0,      35840,      35840,     1024,     4096, 0x5837f26f
+0,      36864,      36864,     1024,     4096, 0x71500376
+0,      37888,      37888,     1024,     4096, 0xb4650378
+0,      38912,      38912,     1024,     4096, 0xd261f5b1
+0,      39936,      39936,     1024,     4096, 0x3038f3fd
+0,      40960,      40960,     1024,     4096, 0x8e1908c6
+0,      41984,      41984,     1024,     4096, 0x1d6bfd33
+0,      43008,      43008,     1024,     4096, 0x7036f23f
+0,      44032,      44032,     1024,     4096, 0xabb8fbdb
+0,      45056,      45056,     1024,     4096, 0x8980f03f
+0,      46080,      46080,     1024,     4096, 0xc5a0f4ed
+0,      47104,      47104,     1024,     4096, 0x04ac0314
+0,      48128,      48128,     1024,     4096, 0xfdd0dca7
+0,      49152,      49152,     1024,     4096, 0x799bf1fd
+0,      50176,      50176,     1024,     4096, 0xbaa9fdfd
+0,      51200,      51200,     1024,     4096, 0xeb7cf571
+0,      52224,      52224,     1024,     4096, 0xe33b0e5a
+0,      53248,      53248,     1024,     4096, 0x8017f117
+0,      54272,      54272,     1024,     4096, 0x5fccf35b
+0,      55296,      55296,     1024,     4096, 0xbd69f9cb
+0,      56320,      56320,     1024,     4096, 0x4d09f905
+0,      57344,      57344,     1024,     4096, 0xfa53f185
+0,      58368,      58368,     1024,     4096, 0x35b907e4
+0,      59392,      59392,     1024,     4096, 0xf639fedb
+0,      60416,      60416,     1024,     4096, 0x1e58f771
+0,      61440,      61440,     1024,     4096, 0xb13d18d4
+0,      62464,      62464,     1024,     4096, 0xc7930842
+0,      63488,      63488,     1024,     4096, 0x1b4702d4
+0,      64512,      64512,     1024,     4096, 0xad75dd27
+0,      65536,      65536,     1024,     4096, 0x9a1ceb7b
+0,      66560,      66560,     1024,     4096, 0xead809ac
+0,      67584,      67584,     1024,     4096, 0xbdaf1b5a
+0,      68608,      68608,     1024,     4096, 0xa90a00a6
+0,      69632,      69632,     1024,     4096, 0xb39f0d0a
+0,      70656,      70656,     1024,     4096, 0xbaf60950
+0,      71680,      71680,     1024,     4096, 0x57d3eb53
+0,      72704,      72704,     1024,     4096, 0x8a77f7ff
+0,      73728,      73728,     1024,     4096, 0xd2bfe3b9
+0,      74752,      74752,     1024,     4096, 0xd4c5e287
+0,      75776,      75776,     1024,     4096, 0x8b940480
+0,      76800,      76800,     1024,     4096, 0x63a9134e
+0,      77824,      77824,     1024,     4096, 0x2215ee4d
+0,      78848,      78848,     1024,     4096, 0x8777f743
+0,      79872,      79872,     1024,     4096, 0x633e05ac
+0,      80896,      80896,     1024,     4096, 0x3b1ee685
+0,      81920,      81920,     1024,     4096, 0x57d30238
+0,      82944,      82944,     1024,     4096, 0xfb241180
+0,      83968,      83968,     1024,     4096, 0x733aea25
+0,      84992,      84992,     1024,     4096, 0x1677ea57
+0,      86016,      86016,     1024,     4096, 0xdf5fd6d7
+0,      87040,      87040,     1024,     4096, 0x36520bca
+0,      88064,      88064,     1024,     4096, 0x1e860a06
+0,      89088,      89088,     1024,     4096, 0x3305428c
+0,      90112,      90112,     1024,     4096, 0xe1a8008c
+0,      91136,      91136,     1024,     4096, 0xd81ff15f
+0,      92160,      92160,     1024,     4096, 0x0ccad2e7
+0,      93184,      93184,     1024,     4096, 0xc613bf29
+0,      94208,      94208,     1024,     4096, 0x5411ef73
+0,      95232,      95232,     1024,     4096, 0x51f7e01b
+0,      96256,      96256,     1024,     4096, 0x23d1ee5b
+0,      97280,      97280,     1024,     4096, 0xbc9721e2
+0,      98304,      98304,     1024,     4096, 0x0d49c94b
+0,      99328,      99328,     1024,     4096, 0xa102d963
+0,     100352,     100352,     1024,     4096, 0x5fd8fe95
+0,     101376,     101376,     1024,     4096, 0xd8c738e0
+0,     102400,     102400,     1024,     4096, 0xa9882686
+0,     103424,     103424,     1024,     4096, 0xfa30c4b1
+0,     104448,     104448,     1024,     4096, 0x76ecdb31
+0,     105472,     105472,     1024,     4096, 0x540ccff9
+0,     106496,     106496,     1024,     4096, 0xb365cf5f
+0,     107520,     107520,     1024,     4096, 0x3ab51dcc
+0,     108544,     108544,     1024,     4096, 0x266fd553
+0,     109568,     109568,     1024,     4096, 0xdac42f58
+0,     110592,     110592,     1024,     4096, 0x3ab23628
+0,     111616,     111616,     1024,     4096, 0x94c9a8bf
+0,     112640,     112640,     1024,     4096, 0x7ba5ff41
+0,     113664,     113664,     1024,     4096, 0xc6bfd5db
+0,     114688,     114688,     1024,     4096, 0x6b9ef98f
+0,     115712,     115712,     1024,     4096, 0xe5621a02
+0,     116736,     116736,     1024,     4096, 0xeedd28ec
+0,     117760,     117760,     1024,     4096, 0xddf5e045
+0,     118784,     118784,     1024,     4096, 0x49f0e0a9
+0,     119808,     119808,     1024,     4096, 0xd18f0ca0
+0,     120832,     120832,     1024,     4096, 0xa0fa00c6
+0,     121856,     121856,     1024,     4096, 0x9e406e6c
+0,     122880,     122880,     1024,     4096, 0x1a3f23bc
+0,     123904,     123904,     1024,     4096, 0xcbf409d0
+0,     124928,     124928,     1024,     4096, 0x499b3ac8
+0,     125952,     125952,     1024,     4096, 0x2ef93980
+0,     126976,     126976,     1024,     4096, 0x83092bfa
+0,     128000,     128000,     1024,     4096, 0x4838093a
+0,     129024,     129024,     1024,     4096, 0xd1bff209
+0,     130048,     130048,     1024,     4096, 0xdef04f12
+0,     131072,     131072,     1024,     4096, 0x130dd787
+0,     132096,     132096,     1024,     4096, 0xc8621030
+0,     133120,     133120,     1024,     4096, 0x1b2bf867
+0,     134144,     134144,     1024,     4096, 0x01220341
+0,     135168,     135168,     1024,     4096, 0x7c8dfdb1
+0,     136192,     136192,     1024,     4096, 0xe81df813
+0,     137216,     137216,     1024,     4096, 0xf820fe8d
+0,     138240,     138240,     1024,     4096, 0x1f9dfe49
+0,     139264,     139264,     1024,     4096, 0x2f84f144
+0,     140288,     140288,     1024,     4096, 0xab9deec8
+0,     141312,     141312,     1024,     4096, 0x7d7bf5b9
+0,     142336,     142336,     1024,     4096, 0xbecff5ea
+0,     143360,     143360,     1024,     4096, 0x2872e5c0
+0,     144384,     144384,     1024,     4096, 0x6e2ff713
+0,     145408,     145408,     1024,     4096, 0x0b2df757
+0,     146432,     146432,     1024,     4096, 0x5030fa0a
+0,     147456,     147456,     1024,     4096, 0xb5b5f3da
+0,     148480,     148480,     1024,     4096, 0xce4cf9a6
+0,     149504,     149504,     1024,     4096, 0x9eacf61f
+0,     150528,     150528,     1024,     4096, 0x3bfff549
+0,     151552,     151552,     1024,     4096, 0x4eeae60a
+0,     152576,     152576,     1024,     4096, 0x188ef258
+0,     153600,     153600,     1024,     4096, 0xb546f30d
+0,     154624,     154624,     1024,     4096, 0x0a84e6f8
+0,     155648,     155648,     1024,     4096, 0xe7b0ee27
+0,     156672,     156672,     1024,     4096, 0x04d0f6ee
+0,     157696,     157696,     1024,     4096, 0x09fa042a
+0,     158720,     158720,     1024,     4096, 0x5a3cf418
+0,     159744,     159744,     1024,     4096, 0x89d8017f
+0,     160768,     160768,     1024,     4096, 0x64eb0320
+0,     161792,     161792,     1024,     4096, 0xe40df279
+0,     162816,     162816,     1024,     4096, 0x4dc4fd25
+0,     163840,     163840,     1024,     4096, 0x466af97c
+0,     164864,     164864,     1024,     4096, 0x7306f4e2
+0,     165888,     165888,     1024,     4096, 0x9782eda4
+0,     166912,     166912,     1024,     4096, 0x3635fad8
+0,     167936,     167936,     1024,     4096, 0x3344eabe
+0,     168960,     168960,     1024,     4096, 0x9143fda0
+0,     169984,     169984,     1024,     4096, 0x33e7eb7f
+0,     171008,     171008,     1024,     4096, 0x4ca0e947
+0,     172032,     172032,     1024,     4096, 0x5b1bf80d
+0,     173056,     173056,     1024,     4096, 0xbb15eab7
+0,     174080,     174080,     1024,     4096, 0xd800f7cb
+0,     175104,     175104,     1024,     4096, 0xd3d4e960
+0,     176128,     176128,     1024,     4096, 0x2fc30f2f
+0,     177152,     177152,     1024,     4096, 0xb410f092
+0,     178176,     178176,     1024,     4096, 0x4350fddf
+0,     179200,     179200,     1024,     4096, 0x477a07c6
+0,     180224,     180224,     1024,     4096, 0x9d48ed59
+0,     181248,     181248,     1024,     4096, 0xd6ae02a8
+0,     182272,     182272,     1024,     4096, 0x206be433
+0,     183296,     183296,     1024,     4096, 0xf465fc54
+0,     184320,     184320,     1024,     4096, 0x745dacb9
+0,     185344,     185344,     1024,     4096, 0x3783e765
+0,     186368,     186368,     1024,     4096, 0x479feb48
+0,     187392,     187392,     1024,     4096, 0x34f2050f
+0,     188416,     188416,     1024,     4096, 0x9df1f441
+0,     189440,     189440,     1024,     4096, 0x1864f225
+0,     190464,     190464,     1024,     4096, 0xebacf084
+0,     191488,     191488,     1024,     4096, 0xaa14f082
+0,     192512,     192512,     1024,     4096, 0xbac10f8b
+0,     193536,     193536,     1024,     4096, 0xa4520210
+0,     194560,     194560,     1024,     4096, 0xfee4f8c3
+0,     195584,     195584,     1024,     4096, 0xadf5e4c2
+0,     196608,     196608,     1024,     4096, 0x7bf20584
+0,     197632,     197632,     1024,     4096, 0x541debf5
+0,     198656,     198656,     1024,     4096, 0x9a350796
+0,     199680,     199680,     1024,     4096, 0x1388fa83
+0,     200704,     200704,     1024,     4096, 0x9839b0c2
+0,     201728,     201728,     1024,     4096, 0xfc9afff0
+0,     202752,     202752,     1024,     4096, 0x73100a7c
+0,     203776,     203776,     1024,     4096, 0xb56df070
+0,     204800,     204800,     1024,     4096, 0x71d8efa7
+0,     205824,     205824,     1024,     4096, 0xde800412
+0,     206848,     206848,     1024,     4096, 0x7bf7f840
+0,     207872,     207872,     1024,     4096, 0x1480044d
+0,     208896,     208896,     1024,     4096, 0x60201217
+0,     209920,     209920,     1024,     4096, 0xb410f092
+0,     210944,     210944,     1024,     4096, 0x4350fddf
+0,     211968,     211968,     1024,     4096, 0x477a07c6
+0,     212992,     212992,     1024,     4096, 0x9d48ed59
+0,     214016,     214016,     1024,     4096, 0xd6ae02a8
+0,     215040,     215040,     1024,     4096, 0x206be433
+0,     216064,     216064,     1024,     4096, 0xf465fc54
+0,     217088,     217088,     1024,     4096, 0x745dacb9
+0,     218112,     218112,     1024,     4096, 0x3783e765
+0,     219136,     219136,     1024,     4096, 0x479feb48
+0,     220160,     220160,     1024,     4096, 0x34f2050f
+0,     221184,     221184,     1024,     4096, 0x9df1f441
+0,     222208,     222208,     1024,     4096, 0x1864f225
+0,     223232,     223232,     1024,     4096, 0xebacf084
+0,     224256,     224256,     1024,     4096, 0xaa14f082
+0,     225280,     225280,     1024,     4096, 0xbac10f8b
+0,     226304,     226304,     1024,     4096, 0xa4520210
+0,     227328,     227328,     1024,     4096, 0xfee4f8c3
+0,     228352,     228352,     1024,     4096, 0xadf5e4c2
+0,     229376,     229376,     1024,     4096, 0x7bf20584
+0,     230400,     230400,     1024,     4096, 0x541debf5
+0,     231424,     231424,     1024,     4096, 0x9a350796
+0,     232448,     232448,     1024,     4096, 0x1388fa83
+0,     233472,     233472,     1024,     4096, 0x9839b0c2
+0,     234496,     234496,     1024,     4096, 0xfc9afff0
+0,     235520,     235520,     1024,     4096, 0x73100a7c
+0,     236544,     236544,     1024,     4096, 0xb56df070
+0,     237568,     237568,     1024,     4096, 0x71d8efa7
+0,     238592,     238592,     1024,     4096, 0xde800412
+0,     239616,     239616,     1024,     4096, 0x7bf7f840
+0,     240640,     240640,     1024,     4096, 0x1480044d
+0,     241664,     241664,     1024,     4096, 0x60201217
+0,     242688,     242688,     1024,     4096, 0xb410f092
+0,     243712,     243712,     1024,     4096, 0x4350fddf
+0,     244736,     244736,     1024,     4096, 0x477a07c6
+0,     245760,     245760,     1024,     4096, 0x9d48ed59
+0,     246784,     246784,     1024,     4096, 0xd6ae02a8
+0,     247808,     247808,     1024,     4096, 0x206be433
+0,     248832,     248832,     1024,     4096, 0xf465fc54
+0,     249856,     249856,     1024,     4096, 0x745dacb9
+0,     250880,     250880,     1024,     4096, 0x3783e765
+0,     251904,     251904,     1024,     4096, 0x479feb48
+0,     252928,     252928,     1024,     4096, 0x34f2050f
+0,     253952,     253952,     1024,     4096, 0x9df1f441
+0,     254976,     254976,     1024,     4096, 0x1864f225
+0,     256000,     256000,     1024,     4096, 0xebacf084
+0,     257024,     257024,     1024,     4096, 0xaa14f082
+0,     258048,     258048,     1024,     4096, 0xbac10f8b
+0,     259072,     259072,     1024,     4096, 0xa4520210
+0,     260096,     260096,     1024,     4096, 0xfee4f8c3
+0,     261120,     261120,     1024,     4096, 0xadf5e4c2
+0,     262144,     262144,     1024,     4096, 0x7bf20584
+0,     263168,     263168,     1024,     4096, 0x541debf5
+0,     264192,     264192,      408,     1632, 0xadd02d39
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0xfd510c8e
+0,       1024,       1024,     1024,     4096, 0x09dcf895
+0,       2048,       2048,     1024,     4096, 0xd8cbe29f
+0,       3072,       3072,     1024,     4096, 0xefcffb51
+0,       4096,       4096,     1024,     4096, 0xa3840ebe
+0,       5120,       5120,     1024,     4096, 0xfcf0f60f
+0,       6144,       6144,     1024,     4096, 0x3d82f4ad
+0,       7168,       7168,     1024,     4096, 0x17960344
+0,       8192,       8192,     1024,     4096, 0xdecbf6f9
+0,       9216,       9216,     1024,     4096, 0x783d000e
+0,      10240,      10240,     1024,     4096, 0xea4607fe
+0,      11264,      11264,     1024,     4096, 0xabc7f8ad
+0,      12288,      12288,     1024,     4096, 0xda22f07d
+0,      13312,      13312,     1024,     4096, 0xbcebfc6b
+0,      14336,      14336,     1024,     4096, 0xc7020a20
+0,      15360,      15360,     1024,     4096, 0xfa28f94b
+0,      16384,      16384,     1024,     4096, 0x926ee3b5
+0,      17408,      17408,     1024,     4096, 0x161cf985
+0,      18432,      18432,     1024,     4096, 0x40e909ce
+0,      19456,      19456,     1024,     4096, 0x1bf8f2ef
+0,      20480,      20480,     1024,     4096, 0x322fe983
+0,      21504,      21504,     1024,     4096, 0xead2fe3f
+0,      22528,      22528,     1024,     4096, 0xcb51fb99
+0,      23552,      23552,     1024,     4096, 0xd430e117
+0,      24576,      24576,     1024,     4096, 0x3d72f74f
+0,      25600,      25600,     1024,     4096, 0x12b1f269
+0,      26624,      26624,     1024,     4096, 0x0469e035
+0,      27648,      27648,     1024,     4096, 0xd164f5bf
+0,      28672,      28672,     1024,     4096, 0xa6f803aa
+0,      29696,      29696,     1024,     4096, 0x3569f3e9
+0,      30720,      30720,     1024,     4096, 0x8662ec45
+0,      31744,      31744,     1024,     4096, 0x92fdfeb7
+0,      32768,      32768,     1024,     4096, 0x915f12ce
+0,      33792,      33792,     1024,     4096, 0x09dcf895
+0,      34816,      34816,     1024,     4096, 0xd8cbe29f
+0,      35840,      35840,     1024,     4096, 0xefcffb51
+0,      36864,      36864,     1024,     4096, 0xa3840ebe
+0,      37888,      37888,     1024,     4096, 0xfcf0f60f
+0,      38912,      38912,     1024,     4096, 0x3d82f4ad
+0,      39936,      39936,     1024,     4096, 0x17960344
+0,      40960,      40960,     1024,     4096, 0xdecbf6f9
+0,      41984,      41984,     1024,     4096, 0x783d000e
+0,      43008,      43008,     1024,     4096, 0xea4607fe
+0,      44032,      44032,     1024,     4096, 0x3e840b8a
+0,      45056,      45056,     1024,     4096, 0x45d30e80
+0,      46080,      46080,     1024,     4096, 0xc31bef4f
+0,      47104,      47104,     1024,     4096, 0x8b1302e4
+0,      48128,      48128,     1024,     4096, 0x0b21144e
+0,      49152,      49152,     1024,     4096, 0xb873e7b1
+0,      50176,      50176,     1024,     4096, 0x914e07ee
+0,      51200,      51200,     1024,     4096, 0x7e9dfc37
+0,      52224,      52224,     1024,     4096, 0x8255f9b7
+0,      53248,      53248,     1024,     4096, 0x98a7ebeb
+0,      54272,      54272,     1024,     4096, 0xf438eeb1
+0,      55296,      55296,     1024,     4096, 0x31f40542
+0,      56320,      56320,     1024,     4096, 0x5fb7eb35
+0,      57344,      57344,     1024,     4096, 0xe9220582
+0,      58368,      58368,     1024,     4096, 0xf1a80e3a
+0,      59392,      59392,     1024,     4096, 0xe8ff0f14
+0,      60416,      60416,     1024,     4096, 0x48980ac2
+0,      61440,      61440,     1024,     4096, 0x98d9ffdd
+0,      62464,      62464,     1024,     4096, 0x6db8f2f5
+0,      63488,      63488,     1024,     4096, 0x892f06fa
+0,      64512,      64512,     1024,     4096, 0xa8defbcb
+0,      65536,      65536,     1024,     4096, 0xd39d0f38
+0,      66560,      66560,     1024,     4096, 0xe9bef09b
+0,      67584,      67584,     1024,     4096, 0xa930fd67
+0,      68608,      68608,     1024,     4096, 0x78cc1e42
+0,      69632,      69632,     1024,     4096, 0x7a2eeeeb
+0,      70656,      70656,     1024,     4096, 0xdf660c6a
+0,      71680,      71680,     1024,     4096, 0x00ff0240
+0,      72704,      72704,     1024,     4096, 0x421dd4a5
+0,      73728,      73728,     1024,     4096, 0x7abdd0a3
+0,      74752,      74752,     1024,     4096, 0x172e2578
+0,      75776,      75776,     1024,     4096, 0x24b5e26d
+0,      76800,      76800,     1024,     4096, 0xaf3e136c
+0,      77824,      77824,     1024,     4096, 0xb1ccf1dd
+0,      78848,      78848,     1024,     4096, 0xd08ef9f9
+0,      79872,      79872,     1024,     4096, 0x76c415f8
+0,      80896,      80896,     1024,     4096, 0x0269f63f
+0,      81920,      81920,     1024,     4096, 0xe65f07fe
+0,      82944,      82944,     1024,     4096, 0xc9831ccc
+0,      83968,      83968,     1024,     4096, 0x6907f72b
+0,      84992,      84992,     1024,     4096, 0x9cfae861
+0,      86016,      86016,     1024,     4096, 0x2ed7fbbf
+0,      87040,      87040,     1024,     4096, 0x3b1718f0
+0,      88064,      88064,     1024,     4096, 0xe066fe41
+0,      89088,      89088,     1024,     4096, 0xf4fee887
+0,      90112,      90112,     1024,     4096, 0xc0220baa
+0,      91136,      91136,     1024,     4096, 0x32abcc4b
+0,      92160,      92160,     1024,     4096, 0x96dbc677
+0,      93184,      93184,     1024,     4096, 0x1b72dd23
+0,      94208,      94208,     1024,     4096, 0x2ae0eaef
+0,      95232,      95232,     1024,     4096, 0x3218fc25
+0,      96256,      96256,     1024,     4096, 0x5ed8f2a7
+0,      97280,      97280,     1024,     4096, 0x4df02c50
+0,      98304,      98304,     1024,     4096, 0x50e3a51d
+0,      99328,      99328,     1024,     4096, 0xaf52dc95
+0,     100352,     100352,     1024,     4096, 0x60a101a8
+0,     101376,     101376,     1024,     4096, 0x01c20386
+0,     102400,     102400,     1024,     4096, 0xb017e893
+0,     103424,     103424,     1024,     4096, 0x5a39f907
+0,     104448,     104448,     1024,     4096, 0xbf05e505
+0,     105472,     105472,     1024,     4096, 0x1797d237
+0,     106496,     106496,     1024,     4096, 0xb06bc281
+0,     107520,     107520,     1024,     4096, 0xb49f0402
+0,     108544,     108544,     1024,     4096, 0x4bfdb3a3
+0,     109568,     109568,     1024,     4096, 0x601302ae
+0,     110592,     110592,     1024,     4096, 0x2dad13ac
+0,     111616,     111616,     1024,     4096, 0xe95ed0a3
+0,     112640,     112640,     1024,     4096, 0x8df2dfe3
+0,     113664,     113664,     1024,     4096, 0x4183e52f
+0,     114688,     114688,     1024,     4096, 0x23f1ecad
+0,     115712,     115712,     1024,     4096, 0xb40c20e0
+0,     116736,     116736,     1024,     4096, 0x11bf2d2c
+0,     117760,     117760,     1024,     4096, 0x85f8f2cb
+0,     118784,     118784,     1024,     4096, 0x7961e007
+0,     119808,     119808,     1024,     4096, 0x63a9207a
+0,     120832,     120832,     1024,     4096, 0x7383e583
+0,     121856,     121856,     1024,     4096, 0xa3e36e6a
+0,     122880,     122880,     1024,     4096, 0xd2803f22
+0,     123904,     123904,     1024,     4096, 0x11a70252
+0,     124928,     124928,     1024,     4096, 0x4cfe20f6
+0,     125952,     125952,     1024,     4096, 0x2e66307e
+0,     126976,     126976,     1024,     4096, 0x87c9229c
+0,     128000,     128000,     1024,     4096, 0x8ecdfddb
+0,     129024,     129024,     1024,     4096, 0x7e41e4b7
+0,     130048,     130048,     1024,     4096, 0x568d46fc
+0,     131072,     131072,     1024,     4096, 0x3c97b403
+0,     132096,     132096,     1024,     4096, 0xe04105c2
+0,     133120,     133120,     1024,     4096, 0xe8d6f531
+0,     134144,     134144,     1024,     4096, 0x9a410079
+0,     135168,     135168,     1024,     4096, 0x12631511
+0,     136192,     136192,     1024,     4096, 0x530ff27c
+0,     137216,     137216,     1024,     4096, 0x41f0f3ab
+0,     138240,     138240,     1024,     4096, 0x6985f567
+0,     139264,     139264,     1024,     4096, 0xffc80074
+0,     140288,     140288,     1024,     4096, 0xc6c21def
+0,     141312,     141312,     1024,     4096, 0xf5ddf852
+0,     142336,     142336,     1024,     4096, 0xf61af464
+0,     143360,     143360,     1024,     4096, 0xccabfbd1
+0,     144384,     144384,     1024,     4096, 0x466e062c
+0,     145408,     145408,     1024,     4096, 0xec68ee08
+0,     146432,     146432,     1024,     4096, 0xead4f61a
+0,     147456,     147456,     1024,     4096, 0xb3feef14
+0,     148480,     148480,     1024,     4096, 0x8f03e128
+0,     149504,     149504,     1024,     4096, 0x0c54fd08
+0,     150528,     150528,     1024,     4096, 0x1ae6f4cf
+0,     151552,     151552,     1024,     4096, 0x34bae7d5
+0,     152576,     152576,     1024,     4096, 0xeefc1293
+0,     153600,     153600,     1024,     4096, 0x0c2bfd50
+0,     154624,     154624,     1024,     4096, 0x432ef6f5
+0,     155648,     155648,     1024,     4096, 0xd0f0e4a6
+0,     156672,     156672,     1024,     4096, 0xdeb4fe78
+0,     157696,     157696,     1024,     4096, 0xa6eeef90
+0,     158720,     158720,     1024,     4096, 0xad6701b6
+0,     159744,     159744,     1024,     4096, 0x9865f521
+0,     160768,     160768,     1024,     4096, 0xd7c301a0
+0,     161792,     161792,     1024,     4096, 0x3e82f05d
+0,     162816,     162816,     1024,     4096, 0x09d1fe12
+0,     163840,     163840,     1024,     4096, 0x5b3eeab5
+0,     164864,     164864,     1024,     4096, 0xa8f8e69d
+0,     165888,     165888,     1024,     4096, 0x7b1efe94
+0,     166912,     166912,     1024,     4096, 0xb65dfae6
+0,     167936,     167936,     1024,     4096, 0xf90ffa31
+0,     168960,     168960,     1024,     4096, 0x62e805fe
+0,     169984,     169984,     1024,     4096, 0xe20cfa8e
+0,     171008,     171008,     1024,     4096, 0x1cbdf820
+0,     172032,     172032,     1024,     4096, 0x79e8e729
+0,     173056,     173056,     1024,     4096, 0xfa8bf6ac
+0,     174080,     174080,     1024,     4096, 0xe294f8a6
+0,     175104,     175104,     1024,     4096, 0xa4800572
+0,     176128,     176128,     1024,     4096, 0x8a0e1b32
+0,     177152,     177152,     1024,     4096, 0x00bcf36c
+0,     178176,     178176,     1024,     4096, 0xb3a4eec2
+0,     179200,     179200,     1024,     4096, 0x137a03bd
+0,     180224,     180224,     1024,     4096, 0xb8770bf1
+0,     181248,     181248,     1024,     4096, 0xcc66f90a
+0,     182272,     182272,     1024,     4096, 0x66be04d4
+0,     183296,     183296,     1024,     4096, 0x80a40461
+0,     184320,     184320,     1024,     4096, 0xe4a2b95d
+0,     185344,     185344,     1024,     4096, 0x2537edf0
+0,     186368,     186368,     1024,     4096, 0xc3e8e74f
+0,     187392,     187392,     1024,     4096, 0xd2a40021
+0,     188416,     188416,     1024,     4096, 0xb366f18a
+0,     189440,     189440,     1024,     4096, 0x1d3a0b8a
+0,     190464,     190464,     1024,     4096, 0xac40f416
+0,     191488,     191488,     1024,     4096, 0xc90bf16c
+0,     192512,     192512,     1024,     4096, 0xd6931f86
+0,     193536,     193536,     1024,     4096, 0xf9170265
+0,     194560,     194560,     1024,     4096, 0xb024f8dc
+0,     195584,     195584,     1024,     4096, 0x31cdf143
+0,     196608,     196608,     1024,     4096, 0x1fe1e5e0
+0,     197632,     197632,     1024,     4096, 0x0f1ef3af
+0,     198656,     198656,     1024,     4096, 0x3c86ee15
+0,     199680,     199680,     1024,     4096, 0xf151ecf2
+0,     200704,     200704,     1024,     4096, 0x81fbb354
+0,     201728,     201728,     1024,     4096, 0x88c903e8
+0,     202752,     202752,     1024,     4096, 0x1f480608
+0,     203776,     203776,     1024,     4096, 0x15f4f3cf
+0,     204800,     204800,     1024,     4096, 0xb1ed0d3d
+0,     205824,     205824,     1024,     4096, 0xa074ecfe
+0,     206848,     206848,     1024,     4096, 0xc38100c8
+0,     207872,     207872,     1024,     4096, 0xd43000d8
+0,     208896,     208896,     1024,     4096, 0x59e61b3b
+0,     209920,     209920,     1024,     4096, 0x00bcf36c
+0,     210944,     210944,     1024,     4096, 0xb3a4eec2
+0,     211968,     211968,     1024,     4096, 0x137a03bd
+0,     212992,     212992,     1024,     4096, 0xb8770bf1
+0,     214016,     214016,     1024,     4096, 0xcc66f90a
+0,     215040,     215040,     1024,     4096, 0x66be04d4
+0,     216064,     216064,     1024,     4096, 0x80a40461
+0,     217088,     217088,     1024,     4096, 0xe4a2b95d
+0,     218112,     218112,     1024,     4096, 0x2537edf0
+0,     219136,     219136,     1024,     4096, 0xc3e8e74f
+0,     220160,     220160,     1024,     4096, 0xd2a40021
+0,     221184,     221184,     1024,     4096, 0xb366f18a
+0,     222208,     222208,     1024,     4096, 0x1d3a0b8a
+0,     223232,     223232,     1024,     4096, 0xac40f416
+0,     224256,     224256,     1024,     4096, 0xc90bf16c
+0,     225280,     225280,     1024,     4096, 0xd6931f86
+0,     226304,     226304,     1024,     4096, 0xf9170265
+0,     227328,     227328,     1024,     4096, 0xb024f8dc
+0,     228352,     228352,     1024,     4096, 0x31cdf143
+0,     229376,     229376,     1024,     4096, 0x1fe1e5e0
+0,     230400,     230400,     1024,     4096, 0x0f1ef3af
+0,     231424,     231424,     1024,     4096, 0x3c86ee15
+0,     232448,     232448,     1024,     4096, 0xf151ecf2
+0,     233472,     233472,     1024,     4096, 0x81fbb354
+0,     234496,     234496,     1024,     4096, 0x88c903e8
+0,     235520,     235520,     1024,     4096, 0x1f480608
+0,     236544,     236544,     1024,     4096, 0x15f4f3cf
+0,     237568,     237568,     1024,     4096, 0xb1ed0d3d
+0,     238592,     238592,     1024,     4096, 0xa074ecfe
+0,     239616,     239616,     1024,     4096, 0xc38100c8
+0,     240640,     240640,     1024,     4096, 0xd43000d8
+0,     241664,     241664,     1024,     4096, 0x59e61b3b
+0,     242688,     242688,     1024,     4096, 0x00bcf36c
+0,     243712,     243712,     1024,     4096, 0xb3a4eec2
+0,     244736,     244736,     1024,     4096, 0x137a03bd
+0,     245760,     245760,     1024,     4096, 0xb8770bf1
+0,     246784,     246784,     1024,     4096, 0xcc66f90a
+0,     247808,     247808,     1024,     4096, 0x66be04d4
+0,     248832,     248832,     1024,     4096, 0x80a40461
+0,     249856,     249856,     1024,     4096, 0xe4a2b95d
+0,     250880,     250880,     1024,     4096, 0x2537edf0
+0,     251904,     251904,     1024,     4096, 0xc3e8e74f
+0,     252928,     252928,     1024,     4096, 0xd2a40021
+0,     253952,     253952,     1024,     4096, 0xb366f18a
+0,     254976,     254976,     1024,     4096, 0x1d3a0b8a
+0,     256000,     256000,     1024,     4096, 0xac40f416
+0,     257024,     257024,     1024,     4096, 0xc90bf16c
+0,     258048,     258048,     1024,     4096, 0xd6931f86
+0,     259072,     259072,     1024,     4096, 0xf9170265
+0,     260096,     260096,     1024,     4096, 0xb024f8dc
+0,     261120,     261120,     1024,     4096, 0x31cdf143
+0,     262144,     262144,     1024,     4096, 0x1fe1e5e0
+0,     263168,     263168,     1024,     4096, 0x0f1ef3af
+0,     264192,     264192,      408,     1632, 0x70682eea
diff --git a/tests/ref/fate/filter-aemphasis-50fm b/tests/ref/fate/filter-aemphasis-50fm
new file mode 100644
index 0000000..bae123c
--- /dev/null
+++ b/tests/ref/fate/filter-aemphasis-50fm
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0xb9c5fefd
+0,       1024,       1024,     1024,     4096, 0xb2ae0a90
+0,       2048,       2048,     1024,     4096, 0x97e6e9f3
+0,       3072,       3072,     1024,     4096, 0x5837f26f
+0,       4096,       4096,     1024,     4096, 0x71500376
+0,       5120,       5120,     1024,     4096, 0xb4650378
+0,       6144,       6144,     1024,     4096, 0xd261f5b1
+0,       7168,       7168,     1024,     4096, 0x3038f3fd
+0,       8192,       8192,     1024,     4096, 0x8e1908c6
+0,       9216,       9216,     1024,     4096, 0x1d6bfd33
+0,      10240,      10240,     1024,     4096, 0x7036f23f
+0,      11264,      11264,     1024,     4096, 0xaf73e9a1
+0,      12288,      12288,     1024,     4096, 0x0ba70404
+0,      13312,      13312,     1024,     4096, 0xd34bf249
+0,      14336,      14336,     1024,     4096, 0x0c88fc2b
+0,      15360,      15360,     1024,     4096, 0x55ebf9cf
+0,      16384,      16384,     1024,     4096, 0xc16df0bd
+0,      17408,      17408,     1024,     4096, 0xa635eac5
+0,      18432,      18432,     1024,     4096, 0xb41d059e
+0,      19456,      19456,     1024,     4096, 0xa905f4d3
+0,      20480,      20480,     1024,     4096, 0x2736f1fb
+0,      21504,      21504,     1024,     4096, 0x1a89f007
+0,      22528,      22528,     1024,     4096, 0x81d1fdab
+0,      23552,      23552,     1024,     4096, 0x6156f97d
+0,      24576,      24576,     1024,     4096, 0x1971ec89
+0,      25600,      25600,     1024,     4096, 0xdca1ec4f
+0,      26624,      26624,     1024,     4096, 0x116ffcf5
+0,      27648,      27648,     1024,     4096, 0xc391fdc9
+0,      28672,      28672,     1024,     4096, 0x85e0ef45
+0,      29696,      29696,     1024,     4096, 0x81d3012c
+0,      30720,      30720,     1024,     4096, 0x403ef11b
+0,      31744,      31744,     1024,     4096, 0x3ca6f16d
+0,      32768,      32768,     1024,     4096, 0x6775feb1
+0,      33792,      33792,     1024,     4096, 0xb2ae0a90
+0,      34816,      34816,     1024,     4096, 0x97e6e9f3
+0,      35840,      35840,     1024,     4096, 0x5837f26f
+0,      36864,      36864,     1024,     4096, 0x71500376
+0,      37888,      37888,     1024,     4096, 0xb4650378
+0,      38912,      38912,     1024,     4096, 0xd261f5b1
+0,      39936,      39936,     1024,     4096, 0x3038f3fd
+0,      40960,      40960,     1024,     4096, 0x8e1908c6
+0,      41984,      41984,     1024,     4096, 0x1d6bfd33
+0,      43008,      43008,     1024,     4096, 0x7036f23f
+0,      44032,      44032,     1024,     4096, 0xabb8fbdb
+0,      45056,      45056,     1024,     4096, 0x8980f03f
+0,      46080,      46080,     1024,     4096, 0xc5a0f4ed
+0,      47104,      47104,     1024,     4096, 0x04ac0314
+0,      48128,      48128,     1024,     4096, 0xfdd0dca7
+0,      49152,      49152,     1024,     4096, 0x799bf1fd
+0,      50176,      50176,     1024,     4096, 0xbaa9fdfd
+0,      51200,      51200,     1024,     4096, 0xeb7cf571
+0,      52224,      52224,     1024,     4096, 0xe33b0e5a
+0,      53248,      53248,     1024,     4096, 0x8017f117
+0,      54272,      54272,     1024,     4096, 0x5fccf35b
+0,      55296,      55296,     1024,     4096, 0xbd69f9cb
+0,      56320,      56320,     1024,     4096, 0x4d09f905
+0,      57344,      57344,     1024,     4096, 0xfa53f185
+0,      58368,      58368,     1024,     4096, 0x35b907e4
+0,      59392,      59392,     1024,     4096, 0xf639fedb
+0,      60416,      60416,     1024,     4096, 0x1e58f771
+0,      61440,      61440,     1024,     4096, 0xb13d18d4
+0,      62464,      62464,     1024,     4096, 0xc7930842
+0,      63488,      63488,     1024,     4096, 0x1b4702d4
+0,      64512,      64512,     1024,     4096, 0xad75dd27
+0,      65536,      65536,     1024,     4096, 0x9a1ceb7b
+0,      66560,      66560,     1024,     4096, 0xead809ac
+0,      67584,      67584,     1024,     4096, 0xbdaf1b5a
+0,      68608,      68608,     1024,     4096, 0xa90a00a6
+0,      69632,      69632,     1024,     4096, 0xb39f0d0a
+0,      70656,      70656,     1024,     4096, 0xbaf60950
+0,      71680,      71680,     1024,     4096, 0x57d3eb53
+0,      72704,      72704,     1024,     4096, 0x8a77f7ff
+0,      73728,      73728,     1024,     4096, 0xd2bfe3b9
+0,      74752,      74752,     1024,     4096, 0xd4c5e287
+0,      75776,      75776,     1024,     4096, 0x8b940480
+0,      76800,      76800,     1024,     4096, 0x63a9134e
+0,      77824,      77824,     1024,     4096, 0x2215ee4d
+0,      78848,      78848,     1024,     4096, 0x8777f743
+0,      79872,      79872,     1024,     4096, 0x633e05ac
+0,      80896,      80896,     1024,     4096, 0x3b1ee685
+0,      81920,      81920,     1024,     4096, 0x57d30238
+0,      82944,      82944,     1024,     4096, 0xfb241180
+0,      83968,      83968,     1024,     4096, 0x733aea25
+0,      84992,      84992,     1024,     4096, 0x1677ea57
+0,      86016,      86016,     1024,     4096, 0xdf5fd6d7
+0,      87040,      87040,     1024,     4096, 0x36520bca
+0,      88064,      88064,     1024,     4096, 0x1e860a06
+0,      89088,      89088,     1024,     4096, 0x3305428c
+0,      90112,      90112,     1024,     4096, 0xe1a8008c
+0,      91136,      91136,     1024,     4096, 0xd81ff15f
+0,      92160,      92160,     1024,     4096, 0x0ccad2e7
+0,      93184,      93184,     1024,     4096, 0xc613bf29
+0,      94208,      94208,     1024,     4096, 0x5411ef73
+0,      95232,      95232,     1024,     4096, 0x51f7e01b
+0,      96256,      96256,     1024,     4096, 0x23d1ee5b
+0,      97280,      97280,     1024,     4096, 0xbc9721e2
+0,      98304,      98304,     1024,     4096, 0x0d49c94b
+0,      99328,      99328,     1024,     4096, 0xa102d963
+0,     100352,     100352,     1024,     4096, 0x5fd8fe95
+0,     101376,     101376,     1024,     4096, 0xd8c738e0
+0,     102400,     102400,     1024,     4096, 0xa9882686
+0,     103424,     103424,     1024,     4096, 0xfa30c4b1
+0,     104448,     104448,     1024,     4096, 0x76ecdb31
+0,     105472,     105472,     1024,     4096, 0x540ccff9
+0,     106496,     106496,     1024,     4096, 0xb365cf5f
+0,     107520,     107520,     1024,     4096, 0x3ab51dcc
+0,     108544,     108544,     1024,     4096, 0x266fd553
+0,     109568,     109568,     1024,     4096, 0xdac42f58
+0,     110592,     110592,     1024,     4096, 0x3ab23628
+0,     111616,     111616,     1024,     4096, 0x94c9a8bf
+0,     112640,     112640,     1024,     4096, 0x7ba5ff41
+0,     113664,     113664,     1024,     4096, 0xc6bfd5db
+0,     114688,     114688,     1024,     4096, 0x6b9ef98f
+0,     115712,     115712,     1024,     4096, 0xe5621a02
+0,     116736,     116736,     1024,     4096, 0xeedd28ec
+0,     117760,     117760,     1024,     4096, 0xddf5e045
+0,     118784,     118784,     1024,     4096, 0x49f0e0a9
+0,     119808,     119808,     1024,     4096, 0xd18f0ca0
+0,     120832,     120832,     1024,     4096, 0xa0fa00c6
+0,     121856,     121856,     1024,     4096, 0x9e406e6c
+0,     122880,     122880,     1024,     4096, 0x1a3f23bc
+0,     123904,     123904,     1024,     4096, 0xcbf409d0
+0,     124928,     124928,     1024,     4096, 0x499b3ac8
+0,     125952,     125952,     1024,     4096, 0x2ef93980
+0,     126976,     126976,     1024,     4096, 0x83092bfa
+0,     128000,     128000,     1024,     4096, 0x4838093a
+0,     129024,     129024,     1024,     4096, 0xd1bff209
+0,     130048,     130048,     1024,     4096, 0xdef04f12
+0,     131072,     131072,     1024,     4096, 0x130dd787
+0,     132096,     132096,     1024,     4096, 0xc8621030
+0,     133120,     133120,     1024,     4096, 0x1b2bf867
+0,     134144,     134144,     1024,     4096, 0x01220341
+0,     135168,     135168,     1024,     4096, 0x7c8dfdb1
+0,     136192,     136192,     1024,     4096, 0xe81df813
+0,     137216,     137216,     1024,     4096, 0xf820fe8d
+0,     138240,     138240,     1024,     4096, 0x1f9dfe49
+0,     139264,     139264,     1024,     4096, 0x2f84f144
+0,     140288,     140288,     1024,     4096, 0xab9deec8
+0,     141312,     141312,     1024,     4096, 0x7d7bf5b9
+0,     142336,     142336,     1024,     4096, 0xbecff5ea
+0,     143360,     143360,     1024,     4096, 0x2872e5c0
+0,     144384,     144384,     1024,     4096, 0x6e2ff713
+0,     145408,     145408,     1024,     4096, 0x0b2df757
+0,     146432,     146432,     1024,     4096, 0x5030fa0a
+0,     147456,     147456,     1024,     4096, 0xb5b5f3da
+0,     148480,     148480,     1024,     4096, 0xce4cf9a6
+0,     149504,     149504,     1024,     4096, 0x9eacf61f
+0,     150528,     150528,     1024,     4096, 0x3bfff549
+0,     151552,     151552,     1024,     4096, 0x4eeae60a
+0,     152576,     152576,     1024,     4096, 0x188ef258
+0,     153600,     153600,     1024,     4096, 0xb546f30d
+0,     154624,     154624,     1024,     4096, 0x0a84e6f8
+0,     155648,     155648,     1024,     4096, 0xe7b0ee27
+0,     156672,     156672,     1024,     4096, 0x04d0f6ee
+0,     157696,     157696,     1024,     4096, 0x09fa042a
+0,     158720,     158720,     1024,     4096, 0x5a3cf418
+0,     159744,     159744,     1024,     4096, 0x89d8017f
+0,     160768,     160768,     1024,     4096, 0x64eb0320
+0,     161792,     161792,     1024,     4096, 0xe40df279
+0,     162816,     162816,     1024,     4096, 0x4dc4fd25
+0,     163840,     163840,     1024,     4096, 0x466af97c
+0,     164864,     164864,     1024,     4096, 0x7306f4e2
+0,     165888,     165888,     1024,     4096, 0x9782eda4
+0,     166912,     166912,     1024,     4096, 0x3635fad8
+0,     167936,     167936,     1024,     4096, 0x3344eabe
+0,     168960,     168960,     1024,     4096, 0x9143fda0
+0,     169984,     169984,     1024,     4096, 0x33e7eb7f
+0,     171008,     171008,     1024,     4096, 0x4ca0e947
+0,     172032,     172032,     1024,     4096, 0x5b1bf80d
+0,     173056,     173056,     1024,     4096, 0xbb15eab7
+0,     174080,     174080,     1024,     4096, 0xd800f7cb
+0,     175104,     175104,     1024,     4096, 0xd3d4e960
+0,     176128,     176128,     1024,     4096, 0x2fc30f2f
+0,     177152,     177152,     1024,     4096, 0xb410f092
+0,     178176,     178176,     1024,     4096, 0x4350fddf
+0,     179200,     179200,     1024,     4096, 0x477a07c6
+0,     180224,     180224,     1024,     4096, 0x9d48ed59
+0,     181248,     181248,     1024,     4096, 0xd6ae02a8
+0,     182272,     182272,     1024,     4096, 0x206be433
+0,     183296,     183296,     1024,     4096, 0xf465fc54
+0,     184320,     184320,     1024,     4096, 0x745dacb9
+0,     185344,     185344,     1024,     4096, 0x3783e765
+0,     186368,     186368,     1024,     4096, 0x479feb48
+0,     187392,     187392,     1024,     4096, 0x34f2050f
+0,     188416,     188416,     1024,     4096, 0x9df1f441
+0,     189440,     189440,     1024,     4096, 0x1864f225
+0,     190464,     190464,     1024,     4096, 0xebacf084
+0,     191488,     191488,     1024,     4096, 0xaa14f082
+0,     192512,     192512,     1024,     4096, 0xbac10f8b
+0,     193536,     193536,     1024,     4096, 0xa4520210
+0,     194560,     194560,     1024,     4096, 0xfee4f8c3
+0,     195584,     195584,     1024,     4096, 0xadf5e4c2
+0,     196608,     196608,     1024,     4096, 0x7bf20584
+0,     197632,     197632,     1024,     4096, 0x541debf5
+0,     198656,     198656,     1024,     4096, 0x9a350796
+0,     199680,     199680,     1024,     4096, 0x1388fa83
+0,     200704,     200704,     1024,     4096, 0x9839b0c2
+0,     201728,     201728,     1024,     4096, 0xfc9afff0
+0,     202752,     202752,     1024,     4096, 0x73100a7c
+0,     203776,     203776,     1024,     4096, 0xb56df070
+0,     204800,     204800,     1024,     4096, 0x71d8efa7
+0,     205824,     205824,     1024,     4096, 0xde800412
+0,     206848,     206848,     1024,     4096, 0x7bf7f840
+0,     207872,     207872,     1024,     4096, 0x1480044d
+0,     208896,     208896,     1024,     4096, 0x60201217
+0,     209920,     209920,     1024,     4096, 0xb410f092
+0,     210944,     210944,     1024,     4096, 0x4350fddf
+0,     211968,     211968,     1024,     4096, 0x477a07c6
+0,     212992,     212992,     1024,     4096, 0x9d48ed59
+0,     214016,     214016,     1024,     4096, 0xd6ae02a8
+0,     215040,     215040,     1024,     4096, 0x206be433
+0,     216064,     216064,     1024,     4096, 0xf465fc54
+0,     217088,     217088,     1024,     4096, 0x745dacb9
+0,     218112,     218112,     1024,     4096, 0x3783e765
+0,     219136,     219136,     1024,     4096, 0x479feb48
+0,     220160,     220160,     1024,     4096, 0x34f2050f
+0,     221184,     221184,     1024,     4096, 0x9df1f441
+0,     222208,     222208,     1024,     4096, 0x1864f225
+0,     223232,     223232,     1024,     4096, 0xebacf084
+0,     224256,     224256,     1024,     4096, 0xaa14f082
+0,     225280,     225280,     1024,     4096, 0xbac10f8b
+0,     226304,     226304,     1024,     4096, 0xa4520210
+0,     227328,     227328,     1024,     4096, 0xfee4f8c3
+0,     228352,     228352,     1024,     4096, 0xadf5e4c2
+0,     229376,     229376,     1024,     4096, 0x7bf20584
+0,     230400,     230400,     1024,     4096, 0x541debf5
+0,     231424,     231424,     1024,     4096, 0x9a350796
+0,     232448,     232448,     1024,     4096, 0x1388fa83
+0,     233472,     233472,     1024,     4096, 0x9839b0c2
+0,     234496,     234496,     1024,     4096, 0xfc9afff0
+0,     235520,     235520,     1024,     4096, 0x73100a7c
+0,     236544,     236544,     1024,     4096, 0xb56df070
+0,     237568,     237568,     1024,     4096, 0x71d8efa7
+0,     238592,     238592,     1024,     4096, 0xde800412
+0,     239616,     239616,     1024,     4096, 0x7bf7f840
+0,     240640,     240640,     1024,     4096, 0x1480044d
+0,     241664,     241664,     1024,     4096, 0x60201217
+0,     242688,     242688,     1024,     4096, 0xb410f092
+0,     243712,     243712,     1024,     4096, 0x4350fddf
+0,     244736,     244736,     1024,     4096, 0x477a07c6
+0,     245760,     245760,     1024,     4096, 0x9d48ed59
+0,     246784,     246784,     1024,     4096, 0xd6ae02a8
+0,     247808,     247808,     1024,     4096, 0x206be433
+0,     248832,     248832,     1024,     4096, 0xf465fc54
+0,     249856,     249856,     1024,     4096, 0x745dacb9
+0,     250880,     250880,     1024,     4096, 0x3783e765
+0,     251904,     251904,     1024,     4096, 0x479feb48
+0,     252928,     252928,     1024,     4096, 0x34f2050f
+0,     253952,     253952,     1024,     4096, 0x9df1f441
+0,     254976,     254976,     1024,     4096, 0x1864f225
+0,     256000,     256000,     1024,     4096, 0xebacf084
+0,     257024,     257024,     1024,     4096, 0xaa14f082
+0,     258048,     258048,     1024,     4096, 0xbac10f8b
+0,     259072,     259072,     1024,     4096, 0xa4520210
+0,     260096,     260096,     1024,     4096, 0xfee4f8c3
+0,     261120,     261120,     1024,     4096, 0xadf5e4c2
+0,     262144,     262144,     1024,     4096, 0x7bf20584
+0,     263168,     263168,     1024,     4096, 0x541debf5
+0,     264192,     264192,      408,     1632, 0xadd02d39
diff --git a/tests/ref/fate/filter-aemphasis-75kf b/tests/ref/fate/filter-aemphasis-75kf
new file mode 100644
index 0000000..c40a389
--- /dev/null
+++ b/tests/ref/fate/filter-aemphasis-75kf
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0x7b2101ec
+0,       1024,       1024,     1024,     4096, 0x5c16fc93
+0,       2048,       2048,     1024,     4096, 0x62bdee5d
+0,       3072,       3072,     1024,     4096, 0x0299ee41
+0,       4096,       4096,     1024,     4096, 0xdd2efe95
+0,       5120,       5120,     1024,     4096, 0xe9380628
+0,       6144,       6144,     1024,     4096, 0x5d84f1f3
+0,       7168,       7168,     1024,     4096, 0x598beeb3
+0,       8192,       8192,     1024,     4096, 0x21fefb25
+0,       9216,       9216,     1024,     4096, 0x053afefb
+0,      10240,      10240,     1024,     4096, 0xb993fd2b
+0,      11264,      11264,     1024,     4096, 0xa05aeae1
+0,      12288,      12288,     1024,     4096, 0x3e1ff497
+0,      13312,      13312,     1024,     4096, 0x7f5a086c
+0,      14336,      14336,     1024,     4096, 0xad580300
+0,      15360,      15360,     1024,     4096, 0xbcaff05d
+0,      16384,      16384,     1024,     4096, 0xfd8def91
+0,      17408,      17408,     1024,     4096, 0x5cfdfa7b
+0,      18432,      18432,     1024,     4096, 0xd67dff11
+0,      19456,      19456,     1024,     4096, 0x01b2ff0f
+0,      20480,      20480,     1024,     4096, 0x7138ec9d
+0,      21504,      21504,     1024,     4096, 0xb09ef761
+0,      22528,      22528,     1024,     4096, 0x92f3f97b
+0,      23552,      23552,     1024,     4096, 0x2ee8fe7d
+0,      24576,      24576,     1024,     4096, 0x290ef437
+0,      25600,      25600,     1024,     4096, 0x37daee71
+0,      26624,      26624,     1024,     4096, 0x63e9f5e1
+0,      27648,      27648,     1024,     4096, 0x643008d0
+0,      28672,      28672,     1024,     4096, 0xa427fc59
+0,      29696,      29696,     1024,     4096, 0xf196ed25
+0,      30720,      30720,     1024,     4096, 0xc1edeab9
+0,      31744,      31744,     1024,     4096, 0xaf9a0280
+0,      32768,      32768,     1024,     4096, 0x86cf0026
+0,      33792,      33792,     1024,     4096, 0x5c16fc93
+0,      34816,      34816,     1024,     4096, 0x62bdee5d
+0,      35840,      35840,     1024,     4096, 0x0299ee41
+0,      36864,      36864,     1024,     4096, 0xdd2efe95
+0,      37888,      37888,     1024,     4096, 0xe9380628
+0,      38912,      38912,     1024,     4096, 0x5d84f1f3
+0,      39936,      39936,     1024,     4096, 0x598beeb3
+0,      40960,      40960,     1024,     4096, 0x21fefb25
+0,      41984,      41984,     1024,     4096, 0x053afefb
+0,      43008,      43008,     1024,     4096, 0xb993fd2b
+0,      44032,      44032,     1024,     4096, 0xeccc08c6
+0,      45056,      45056,     1024,     4096, 0xceb5f1af
+0,      46080,      46080,     1024,     4096, 0xfee9e279
+0,      47104,      47104,     1024,     4096, 0x4b2a02cc
+0,      48128,      48128,     1024,     4096, 0xdc22ff19
+0,      49152,      49152,     1024,     4096, 0x557cf4e9
+0,      50176,      50176,     1024,     4096, 0x7fe2042c
+0,      51200,      51200,     1024,     4096, 0x0793eb0b
+0,      52224,      52224,     1024,     4096, 0x8bba058e
+0,      53248,      53248,     1024,     4096, 0x3336f807
+0,      54272,      54272,     1024,     4096, 0x86cef823
+0,      55296,      55296,     1024,     4096, 0x07cbefb1
+0,      56320,      56320,     1024,     4096, 0x01c3fab1
+0,      57344,      57344,     1024,     4096, 0xb9a60534
+0,      58368,      58368,     1024,     4096, 0xf8cf0e82
+0,      59392,      59392,     1024,     4096, 0x5caef379
+0,      60416,      60416,     1024,     4096, 0xe2a9dbbd
+0,      61440,      61440,     1024,     4096, 0xe31c09a6
+0,      62464,      62464,     1024,     4096, 0x0524f37d
+0,      63488,      63488,     1024,     4096, 0x92101602
+0,      64512,      64512,     1024,     4096, 0xed00d97b
+0,      65536,      65536,     1024,     4096, 0x2058f609
+0,      66560,      66560,     1024,     4096, 0x30d20634
+0,      67584,      67584,     1024,     4096, 0xa0ddf055
+0,      68608,      68608,     1024,     4096, 0xe23e1946
+0,      69632,      69632,     1024,     4096, 0x2c1af97f
+0,      70656,      70656,     1024,     4096, 0x77f6f2a9
+0,      71680,      71680,     1024,     4096, 0x2b67ff03
+0,      72704,      72704,     1024,     4096, 0x3e26f14b
+0,      73728,      73728,     1024,     4096, 0x0439e425
+0,      74752,      74752,     1024,     4096, 0xb08ef9d1
+0,      75776,      75776,     1024,     4096, 0xac9fede5
+0,      76800,      76800,     1024,     4096, 0xa637f3e7
+0,      77824,      77824,     1024,     4096, 0xbf7307b0
+0,      78848,      78848,     1024,     4096, 0xce41f5b3
+0,      79872,      79872,     1024,     4096, 0xd6b8f619
+0,      80896,      80896,     1024,     4096, 0x5837097e
+0,      81920,      81920,     1024,     4096, 0xc6affc23
+0,      82944,      82944,     1024,     4096, 0x630e070c
+0,      83968,      83968,     1024,     4096, 0x570ffcd5
+0,      84992,      84992,     1024,     4096, 0x71ede781
+0,      86016,      86016,     1024,     4096, 0x703afda5
+0,      87040,      87040,     1024,     4096, 0x71390f4c
+0,      88064,      88064,     1024,     4096, 0x3961f293
+0,      89088,      89088,     1024,     4096, 0xd288b2b9
+0,      90112,      90112,     1024,     4096, 0xbf4c2946
+0,      91136,      91136,     1024,     4096, 0x71deea79
+0,      92160,      92160,     1024,     4096, 0xbb37625e
+0,      93184,      93184,     1024,     4096, 0xd84df25b
+0,      94208,      94208,     1024,     4096, 0xfde1fc9f
+0,      95232,      95232,     1024,     4096, 0x1a49de0f
+0,      96256,      96256,     1024,     4096, 0x1b11eb13
+0,      97280,      97280,     1024,     4096, 0x4ae88343
+0,      98304,      98304,     1024,     4096, 0x299c361a
+0,      99328,      99328,     1024,     4096, 0x14b7d5cd
+0,     100352,     100352,     1024,     4096, 0x40a318fc
+0,     101376,     101376,     1024,     4096, 0x7fb1d8c7
+0,     102400,     102400,     1024,     4096, 0xfe57c82d
+0,     103424,     103424,     1024,     4096, 0xf9a605fc
+0,     104448,     104448,     1024,     4096, 0x29c912f2
+0,     105472,     105472,     1024,     4096, 0x9886da01
+0,     106496,     106496,     1024,     4096, 0x0398f57f
+0,     107520,     107520,     1024,     4096, 0xed1901c8
+0,     108544,     108544,     1024,     4096, 0xa439ef27
+0,     109568,     109568,     1024,     4096, 0xf1a0ca51
+0,     110592,     110592,     1024,     4096, 0xea605b14
+0,     111616,     111616,     1024,     4096, 0xf014a837
+0,     112640,     112640,     1024,     4096, 0x363e3b90
+0,     113664,     113664,     1024,     4096, 0x24a10ca4
+0,     114688,     114688,     1024,     4096, 0x5b562146
+0,     115712,     115712,     1024,     4096, 0xb1291324
+0,     116736,     116736,     1024,     4096, 0xd4797cbe
+0,     117760,     117760,     1024,     4096, 0x526813b4
+0,     118784,     118784,     1024,     4096, 0x634bc887
+0,     119808,     119808,     1024,     4096, 0x6523e6c3
+0,     120832,     120832,     1024,     4096, 0xa244da0d
+0,     121856,     121856,     1024,     4096, 0xec5ba956
+0,     122880,     122880,     1024,     4096, 0xf31b57a6
+0,     123904,     123904,     1024,     4096, 0xf5262d84
+0,     124928,     124928,     1024,     4096, 0x50c37f34
+0,     125952,     125952,     1024,     4096, 0x81286432
+0,     126976,     126976,     1024,     4096, 0x4d2340a2
+0,     128000,     128000,     1024,     4096, 0x37be060a
+0,     129024,     129024,     1024,     4096, 0xdad60e30
+0,     130048,     130048,     1024,     4096, 0x376c38f6
+0,     131072,     131072,     1024,     4096, 0xe44fe77d
+0,     132096,     132096,     1024,     4096, 0xe7a4f806
+0,     133120,     133120,     1024,     4096, 0xc652fc4c
+0,     134144,     134144,     1024,     4096, 0xb8e8fbb6
+0,     135168,     135168,     1024,     4096, 0x95480279
+0,     136192,     136192,     1024,     4096, 0x095b0036
+0,     137216,     137216,     1024,     4096, 0x5397fc40
+0,     138240,     138240,     1024,     4096, 0xb836f79b
+0,     139264,     139264,     1024,     4096, 0x370ef64f
+0,     140288,     140288,     1024,     4096, 0xd6aefae9
+0,     141312,     141312,     1024,     4096, 0xbe08f80a
+0,     142336,     142336,     1024,     4096, 0x5b41ff1c
+0,     143360,     143360,     1024,     4096, 0x5b86faee
+0,     144384,     144384,     1024,     4096, 0x3a0ff0b5
+0,     145408,     145408,     1024,     4096, 0x6157fa3f
+0,     146432,     146432,     1024,     4096, 0x60a9f906
+0,     147456,     147456,     1024,     4096, 0x8ecdfc26
+0,     148480,     148480,     1024,     4096, 0x0146f112
+0,     149504,     149504,     1024,     4096, 0xc163fe87
+0,     150528,     150528,     1024,     4096, 0x2e78f5c4
+0,     151552,     151552,     1024,     4096, 0x3e9bed7d
+0,     152576,     152576,     1024,     4096, 0xb776009c
+0,     153600,     153600,     1024,     4096, 0xea1efaba
+0,     154624,     154624,     1024,     4096, 0x45f2ea57
+0,     155648,     155648,     1024,     4096, 0x5456f53f
+0,     156672,     156672,     1024,     4096, 0x7e3bf2b9
+0,     157696,     157696,     1024,     4096, 0x0952fd4b
+0,     158720,     158720,     1024,     4096, 0xb8e6f10c
+0,     159744,     159744,     1024,     4096, 0xa07ff79c
+0,     160768,     160768,     1024,     4096, 0x55bafbfd
+0,     161792,     161792,     1024,     4096, 0xab81ed83
+0,     162816,     162816,     1024,     4096, 0x5a610066
+0,     163840,     163840,     1024,     4096, 0x0ac90160
+0,     164864,     164864,     1024,     4096, 0x5745f93f
+0,     165888,     165888,     1024,     4096, 0x9cf2f284
+0,     166912,     166912,     1024,     4096, 0xd350ef0b
+0,     167936,     167936,     1024,     4096, 0x3f47f217
+0,     168960,     168960,     1024,     4096, 0xf178fbae
+0,     169984,     169984,     1024,     4096, 0xf74a056a
+0,     171008,     171008,     1024,     4096, 0xc345ede5
+0,     172032,     172032,     1024,     4096, 0xa672f2be
+0,     173056,     173056,     1024,     4096, 0xd5bcf917
+0,     174080,     174080,     1024,     4096, 0x8126f699
+0,     175104,     175104,     1024,     4096, 0xa0d3ebfd
+0,     176128,     176128,     1024,     4096, 0x577f1d75
+0,     177152,     177152,     1024,     4096, 0x6047ffe4
+0,     178176,     178176,     1024,     4096, 0xe89df7c9
+0,     179200,     179200,     1024,     4096, 0x2ea3f621
+0,     180224,     180224,     1024,     4096, 0xda4f05ef
+0,     181248,     181248,     1024,     4096, 0x5d7c07ba
+0,     182272,     182272,     1024,     4096, 0x461be644
+0,     183296,     183296,     1024,     4096, 0xce47f434
+0,     184320,     184320,     1024,     4096, 0xb30bacee
+0,     185344,     185344,     1024,     4096, 0x1c85f71d
+0,     186368,     186368,     1024,     4096, 0xc9a0f1cd
+0,     187392,     187392,     1024,     4096, 0xd939edde
+0,     188416,     188416,     1024,     4096, 0xa8e0e086
+0,     189440,     189440,     1024,     4096, 0xc0b6ff00
+0,     190464,     190464,     1024,     4096, 0xdd84005e
+0,     191488,     191488,     1024,     4096, 0x97d103bf
+0,     192512,     192512,     1024,     4096, 0xa0241ffc
+0,     193536,     193536,     1024,     4096, 0x91a4f35a
+0,     194560,     194560,     1024,     4096, 0x61abf0b0
+0,     195584,     195584,     1024,     4096, 0xa5d10111
+0,     196608,     196608,     1024,     4096, 0x0e71f5ce
+0,     197632,     197632,     1024,     4096, 0x4796f9fa
+0,     198656,     198656,     1024,     4096, 0x561bf893
+0,     199680,     199680,     1024,     4096, 0x70ddfb78
+0,     200704,     200704,     1024,     4096, 0xe4f4c2b6
+0,     201728,     201728,     1024,     4096, 0x5452f356
+0,     202752,     202752,     1024,     4096, 0x84e2fd14
+0,     203776,     203776,     1024,     4096, 0xd04b00a5
+0,     204800,     204800,     1024,     4096, 0x01ca0f7c
+0,     205824,     205824,     1024,     4096, 0x1685ef21
+0,     206848,     206848,     1024,     4096, 0x50effa4f
+0,     207872,     207872,     1024,     4096, 0xb5a9e82f
+0,     208896,     208896,     1024,     4096, 0xa7343704
+0,     209920,     209920,     1024,     4096, 0x6047ffe4
+0,     210944,     210944,     1024,     4096, 0xe89df7c9
+0,     211968,     211968,     1024,     4096, 0x2ea3f621
+0,     212992,     212992,     1024,     4096, 0xda4f05ef
+0,     214016,     214016,     1024,     4096, 0x5d7c07ba
+0,     215040,     215040,     1024,     4096, 0x461be644
+0,     216064,     216064,     1024,     4096, 0xce47f434
+0,     217088,     217088,     1024,     4096, 0xb30bacee
+0,     218112,     218112,     1024,     4096, 0x1c85f71d
+0,     219136,     219136,     1024,     4096, 0xc9a0f1cd
+0,     220160,     220160,     1024,     4096, 0xd939edde
+0,     221184,     221184,     1024,     4096, 0xa8e0e086
+0,     222208,     222208,     1024,     4096, 0xc0b6ff00
+0,     223232,     223232,     1024,     4096, 0xdd84005e
+0,     224256,     224256,     1024,     4096, 0x97d103bf
+0,     225280,     225280,     1024,     4096, 0xa0241ffc
+0,     226304,     226304,     1024,     4096, 0x91a4f35a
+0,     227328,     227328,     1024,     4096, 0x61abf0b0
+0,     228352,     228352,     1024,     4096, 0xa5d10111
+0,     229376,     229376,     1024,     4096, 0x0e71f5ce
+0,     230400,     230400,     1024,     4096, 0x4796f9fa
+0,     231424,     231424,     1024,     4096, 0x561bf893
+0,     232448,     232448,     1024,     4096, 0x70ddfb78
+0,     233472,     233472,     1024,     4096, 0xe4f4c2b6
+0,     234496,     234496,     1024,     4096, 0x5452f356
+0,     235520,     235520,     1024,     4096, 0x84e2fd14
+0,     236544,     236544,     1024,     4096, 0xd04b00a5
+0,     237568,     237568,     1024,     4096, 0x01ca0f7c
+0,     238592,     238592,     1024,     4096, 0x1685ef21
+0,     239616,     239616,     1024,     4096, 0x50effa4f
+0,     240640,     240640,     1024,     4096, 0xb5a9e82f
+0,     241664,     241664,     1024,     4096, 0xa7343704
+0,     242688,     242688,     1024,     4096, 0x6047ffe4
+0,     243712,     243712,     1024,     4096, 0xe89df7c9
+0,     244736,     244736,     1024,     4096, 0x2ea3f621
+0,     245760,     245760,     1024,     4096, 0xda4f05ef
+0,     246784,     246784,     1024,     4096, 0x5d7c07ba
+0,     247808,     247808,     1024,     4096, 0x461be644
+0,     248832,     248832,     1024,     4096, 0xce47f434
+0,     249856,     249856,     1024,     4096, 0xb30bacee
+0,     250880,     250880,     1024,     4096, 0x1c85f71d
+0,     251904,     251904,     1024,     4096, 0xc9a0f1cd
+0,     252928,     252928,     1024,     4096, 0xd939edde
+0,     253952,     253952,     1024,     4096, 0xa8e0e086
+0,     254976,     254976,     1024,     4096, 0xc0b6ff00
+0,     256000,     256000,     1024,     4096, 0xdd84005e
+0,     257024,     257024,     1024,     4096, 0x97d103bf
+0,     258048,     258048,     1024,     4096, 0xa0241ffc
+0,     259072,     259072,     1024,     4096, 0x91a4f35a
+0,     260096,     260096,     1024,     4096, 0x61abf0b0
+0,     261120,     261120,     1024,     4096, 0xa5d10111
+0,     262144,     262144,     1024,     4096, 0x0e71f5ce
+0,     263168,     263168,     1024,     4096, 0x4796f9fa
+0,     264192,     264192,      408,     1632, 0x31842eec
diff --git a/tests/ref/fate/filter-afade-esin b/tests/ref/fate/filter-afade-esin
new file mode 100644
index 0000000..b02c7ff
--- /dev/null
+++ b/tests/ref/fate/filter-afade-esin
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0x06e0d68a
+0,       1024,       1024,     1024,     4096, 0xb325d915
+0,       2048,       2048,     1024,     4096, 0xc0a5f1f1
+0,       3072,       3072,     1024,     4096, 0x47dbf54d
+0,       4096,       4096,     1024,     4096, 0x9f76e869
+0,       5120,       5120,     1024,     4096, 0xfbcaeb51
+0,       6144,       6144,     1024,     4096, 0xa16309a6
+0,       7168,       7168,     1024,     4096, 0x2890fe67
+0,       8192,       8192,     1024,     4096, 0x1cefee6b
+0,       9216,       9216,     1024,     4096, 0x0ad7ea27
+0,      10240,      10240,     1024,     4096, 0x8df7f895
+0,      11264,      11264,     1024,     4096, 0x19c0fa19
+0,      12288,      12288,     1024,     4096, 0x5cb4fdc5
+0,      13312,      13312,     1024,     4096, 0xcfc2f1ef
+0,      14336,      14336,     1024,     4096, 0x24b8f073
+0,      15360,      15360,     1024,     4096, 0x2ff6fa85
+0,      16384,      16384,     1024,     4096, 0x6fcffd03
+0,      17408,      17408,     1024,     4096, 0xe576e477
+0,      18432,      18432,     1024,     4096, 0xe0f6f54f
+0,      19456,      19456,     1024,     4096, 0xc225f5f7
+0,      20480,      20480,     1024,     4096, 0xe6d9fe57
+0,      21504,      21504,     1024,     4096, 0x8bc60f78
+0,      22528,      22528,     1024,     4096, 0xc907eeb1
+0,      23552,      23552,     1024,     4096, 0xd691f071
+0,      24576,      24576,     1024,     4096, 0x939402ee
+0,      25600,      25600,     1024,     4096, 0x19270cc4
+0,      26624,      26624,     1024,     4096, 0x25c5ed9b
+0,      27648,      27648,     1024,     4096, 0x0dbce7eb
+0,      28672,      28672,     1024,     4096, 0x035fff0f
+0,      29696,      29696,     1024,     4096, 0x514a0802
+0,      30720,      30720,     1024,     4096, 0x0de0043e
+0,      31744,      31744,     1024,     4096, 0xb576e1ab
+0,      32768,      32768,     1024,     4096, 0xcf30ee2f
+0,      33792,      33792,     1024,     4096, 0xae49f86d
+0,      34816,      34816,     1024,     4096, 0x42a202ac
+0,      35840,      35840,     1024,     4096, 0x762af249
+0,      36864,      36864,     1024,     4096, 0xb966eba5
+0,      37888,      37888,     1024,     4096, 0xeefeec79
+0,      38912,      38912,     1024,     4096, 0x62b00688
+0,      39936,      39936,     1024,     4096, 0x206efe91
+0,      40960,      40960,     1024,     4096, 0x2f69ef73
+0,      41984,      41984,     1024,     4096, 0x375cf043
+0,      43008,      43008,     1024,     4096, 0x096affd3
+0,      44032,      44032,     1024,     4096, 0x076ef11f
+0,      45056,      45056,     1024,     4096, 0x2e3201a0
+0,      46080,      46080,     1024,     4096, 0xb53f1ba4
+0,      47104,      47104,     1024,     4096, 0x5b13e019
+0,      48128,      48128,     1024,     4096, 0x22640338
+0,      49152,      49152,     1024,     4096, 0xb502f22d
+0,      50176,      50176,     1024,     4096, 0x53dfd61f
+0,      51200,      51200,     1024,     4096, 0x2044f1f1
+0,      52224,      52224,     1024,     4096, 0x94ccf2c7
+0,      53248,      53248,     1024,     4096, 0xbddee399
+0,      54272,      54272,     1024,     4096, 0xf305ec59
+0,      55296,      55296,     1024,     4096, 0x49acfc6f
+0,      56320,      56320,     1024,     4096, 0xc855d77d
+0,      57344,      57344,     1024,     4096, 0x1ca1faf5
+0,      58368,      58368,     1024,     4096, 0x9bd41038
+0,      59392,      59392,     1024,     4096, 0x4b83f6b7
+0,      60416,      60416,     1024,     4096, 0xe9b2ff4b
+0,      61440,      61440,     1024,     4096, 0xd7afe26b
+0,      62464,      62464,     1024,     4096, 0x4282057a
+0,      63488,      63488,     1024,     4096, 0xbea2ebd1
+0,      64512,      64512,     1024,     4096, 0x434ef413
+0,      65536,      65536,     1024,     4096, 0x8cd70e28
+0,      66560,      66560,     1024,     4096, 0xcef91d96
+0,      67584,      67584,     1024,     4096, 0xd9abfa75
+0,      68608,      68608,     1024,     4096, 0x9793f0c7
+0,      69632,      69632,     1024,     4096, 0x734b090c
+0,      70656,      70656,     1024,     4096, 0xdcf0f981
+0,      71680,      71680,     1024,     4096, 0x05af1302
+0,      72704,      72704,     1024,     4096, 0x9d80f677
+0,      73728,      73728,     1024,     4096, 0xc4e10628
+0,      74752,      74752,     1024,     4096, 0xfa8ef6a9
+0,      75776,      75776,     1024,     4096, 0xf8c1f72f
+0,      76800,      76800,     1024,     4096, 0xcf9b028a
+0,      77824,      77824,     1024,     4096, 0x80c7f3cb
+0,      78848,      78848,     1024,     4096, 0x97e2e6e5
+0,      79872,      79872,     1024,     4096, 0x9301dc81
+0,      80896,      80896,     1024,     4096, 0x1a8aeaed
+0,      81920,      81920,     1024,     4096, 0xfd751e70
+0,      82944,      82944,     1024,     4096, 0xe7643dc0
+0,      83968,      83968,     1024,     4096, 0xe08f0788
+0,      84992,      84992,     1024,     4096, 0x4f1105cc
+0,      86016,      86016,     1024,     4096, 0xb25806c6
+0,      87040,      87040,     1024,     4096, 0xd66d282a
+0,      88064,      88064,     1024,     4096, 0x457ddf0d
+0,      89088,      89088,     1024,     4096, 0xe68dda8f
+0,      90112,      90112,     1024,     4096, 0xe457b505
+0,      91136,      91136,     1024,     4096, 0xda25a409
+0,      92160,      92160,     1024,     4096, 0x5b5d9d3b
+0,      93184,      93184,     1024,     4096, 0xa61eb13d
+0,      94208,      94208,     1024,     4096, 0xac93b66f
+0,      95232,      95232,     1024,     4096, 0xc7aeb33f
+0,      96256,      96256,     1024,     4096, 0x52cccfb5
+0,      97280,      97280,     1024,     4096, 0x4e4cf487
+0,      98304,      98304,     1024,     4096, 0x19c07f35
+0,      99328,      99328,     1024,     4096, 0x63ecd34f
+0,     100352,     100352,     1024,     4096, 0x122aec53
+0,     101376,     101376,     1024,     4096, 0x6581c0ad
+0,     102400,     102400,     1024,     4096, 0x640edb15
+0,     103424,     103424,     1024,     4096, 0x5d66c66f
+0,     104448,     104448,     1024,     4096, 0x069e9d35
+0,     105472,     105472,     1024,     4096, 0x5c9fd0e9
+0,     106496,     106496,     1024,     4096, 0x72468667
+0,     107520,     107520,     1024,     4096, 0x6e6dd02b
+0,     108544,     108544,     1024,     4096, 0x93edce33
+0,     109568,     109568,     1024,     4096, 0xcdfbd519
+0,     110592,     110592,     1024,     4096, 0x8463f2bb
+0,     111616,     111616,     1024,     4096, 0x5ca6f869
+0,     112640,     112640,     1024,     4096, 0x099a0398
+0,     113664,     113664,     1024,     4096, 0xa7fa10f0
+0,     114688,     114688,     1024,     4096, 0x28caddd3
+0,     115712,     115712,     1024,     4096, 0x4852ef8b
+0,     116736,     116736,     1024,     4096, 0x0250ee7b
+0,     117760,     117760,     1024,     4096, 0x9583da21
+0,     118784,     118784,     1024,     4096, 0x7365fb33
+0,     119808,     119808,     1024,     4096, 0x28c82066
+0,     120832,     120832,     1024,     4096, 0x94650be4
+0,     121856,     121856,     1024,     4096, 0xeb21f8eb
+0,     122880,     122880,     1024,     4096, 0xcd88f455
+0,     123904,     123904,     1024,     4096, 0x66a9efaf
+0,     124928,     124928,     1024,     4096, 0x5500c6ed
+0,     125952,     125952,     1024,     4096, 0x0ee0c62d
+0,     126976,     126976,     1024,     4096, 0x34d30762
+0,     128000,     128000,     1024,     4096, 0x8c0dec9f
+0,     129024,     129024,     1024,     4096, 0x790011d8
+0,     130048,     130048,     1024,     4096, 0xb76a1136
+0,     131072,     131072,     1024,     4096, 0x7dddfea7
+0,     132096,     132096,     1024,     4096, 0xdfa3ed49
+0,     133120,     133120,     1024,     4096, 0xc129f54e
+0,     134144,     134144,     1024,     4096, 0x9a86f077
+0,     135168,     135168,     1024,     4096, 0xc9eef209
+0,     136192,     136192,     1024,     4096, 0x72d4029b
+0,     137216,     137216,     1024,     4096, 0x8ec20590
+0,     138240,     138240,     1024,     4096, 0xd48f18ed
+0,     139264,     139264,     1024,     4096, 0xd807eadc
+0,     140288,     140288,     1024,     4096, 0x1e2bea09
+0,     141312,     141312,     1024,     4096, 0x937af12e
+0,     142336,     142336,     1024,     4096, 0xdedbf303
+0,     143360,     143360,     1024,     4096, 0xdc75df88
+0,     144384,     144384,     1024,     4096, 0x1845ffd6
+0,     145408,     145408,     1024,     4096, 0x20e8150c
+0,     146432,     146432,     1024,     4096, 0x5ea7eeef
+0,     147456,     147456,     1024,     4096, 0x4c7efa21
+0,     148480,     148480,     1024,     4096, 0x8b97e30e
+0,     149504,     149504,     1024,     4096, 0xe5040228
+0,     150528,     150528,     1024,     4096, 0x6283f78c
+0,     151552,     151552,     1024,     4096, 0xe7100140
+0,     152576,     152576,     1024,     4096, 0x9ea6f9b2
+0,     153600,     153600,     1024,     4096, 0x5f0e1563
+0,     154624,     154624,     1024,     4096, 0x510bf18e
+0,     155648,     155648,     1024,     4096, 0x5f4fe425
+0,     156672,     156672,     1024,     4096, 0x507af3c0
+0,     157696,     157696,     1024,     4096, 0xbf14ddc6
+0,     158720,     158720,     1024,     4096, 0x1871ed69
+0,     159744,     159744,     1024,     4096, 0xc349ef9f
+0,     160768,     160768,     1024,     4096, 0x4e2c1834
+0,     161792,     161792,     1024,     4096, 0x2383fe04
+0,     162816,     162816,     1024,     4096, 0x6626f415
+0,     163840,     163840,     1024,     4096, 0x283be379
+0,     164864,     164864,     1024,     4096, 0xc76c0ceb
+0,     165888,     165888,     1024,     4096, 0xa0b8040f
+0,     166912,     166912,     1024,     4096, 0x2535eb6d
+0,     167936,     167936,     1024,     4096, 0xeb180bb5
+0,     168960,     168960,     1024,     4096, 0xbc5cf059
+0,     169984,     169984,     1024,     4096, 0x1862f1ac
+0,     171008,     171008,     1024,     4096, 0x9cc2ea2b
+0,     172032,     172032,     1024,     4096, 0xbb9ae754
+0,     173056,     173056,     1024,     4096, 0x716debb5
+0,     174080,     174080,     1024,     4096, 0xff3aff2a
+0,     175104,     175104,     1024,     4096, 0x755dfa5c
+0,     176128,     176128,     1024,     4096, 0x3b830605
+0,     177152,     177152,     1024,     4096, 0x0030dc9e
+0,     178176,     178176,     1024,     4096, 0xb017fd54
+0,     179200,     179200,     1024,     4096, 0x5c7dfa2e
+0,     180224,     180224,     1024,     4096, 0x7887e599
+0,     181248,     181248,     1024,     4096, 0xb730e72f
+0,     182272,     182272,     1024,     4096, 0x6bb3fae4
+0,     183296,     183296,     1024,     4096, 0xcc08fc36
+0,     184320,     184320,     1024,     4096, 0x5afd9ec2
+0,     185344,     185344,     1024,     4096, 0xa1d3e83d
+0,     186368,     186368,     1024,     4096, 0x7f96013c
+0,     187392,     187392,     1024,     4096, 0x7a0afe31
+0,     188416,     188416,     1024,     4096, 0xa37d1701
+0,     189440,     189440,     1024,     4096, 0x4615ebc2
+0,     190464,     190464,     1024,     4096, 0x217005c1
+0,     191488,     191488,     1024,     4096, 0x1755f789
+0,     192512,     192512,     1024,     4096, 0x83e6db65
+0,     193536,     193536,     1024,     4096, 0x92ab1447
+0,     194560,     194560,     1024,     4096, 0xedbdf383
+0,     195584,     195584,     1024,     4096, 0x4316f6a9
+0,     196608,     196608,     1024,     4096, 0x1a6a0b4c
+0,     197632,     197632,     1024,     4096, 0xdfd809b7
+0,     198656,     198656,     1024,     4096, 0x1d2cf5f1
+0,     199680,     199680,     1024,     4096, 0xd366f4a1
+0,     200704,     200704,     1024,     4096, 0x6a2f86e0
+0,     201728,     201728,     1024,     4096, 0xf51f08a9
+0,     202752,     202752,     1024,     4096, 0x05edefa8
+0,     203776,     203776,     1024,     4096, 0x255df2a6
+0,     204800,     204800,     1024,     4096, 0xe881d9e4
+0,     205824,     205824,     1024,     4096, 0x50380523
+0,     206848,     206848,     1024,     4096, 0x8b93eb26
+0,     207872,     207872,     1024,     4096, 0x759cf94c
+0,     208896,     208896,     1024,     4096, 0x8474f591
+0,     209920,     209920,     1024,     4096, 0x0030dc9e
+0,     210944,     210944,     1024,     4096, 0xb017fd54
+0,     211968,     211968,     1024,     4096, 0x5c7dfa2e
+0,     212992,     212992,     1024,     4096, 0x7887e599
+0,     214016,     214016,     1024,     4096, 0xb730e72f
+0,     215040,     215040,     1024,     4096, 0x6bb3fae4
+0,     216064,     216064,     1024,     4096, 0xcc08fc36
+0,     217088,     217088,     1024,     4096, 0x5afd9ec2
+0,     218112,     218112,     1024,     4096, 0xa1d3e83d
+0,     219136,     219136,     1024,     4096, 0x7f96013c
+0,     220160,     220160,     1024,     4096, 0x7a0afe31
+0,     221184,     221184,     1024,     4096, 0xa37d1701
+0,     222208,     222208,     1024,     4096, 0x4615ebc2
+0,     223232,     223232,     1024,     4096, 0x217005c1
+0,     224256,     224256,     1024,     4096, 0x1755f789
+0,     225280,     225280,     1024,     4096, 0x83e6db65
+0,     226304,     226304,     1024,     4096, 0x92ab1447
+0,     227328,     227328,     1024,     4096, 0xedbdf383
+0,     228352,     228352,     1024,     4096, 0x4316f6a9
+0,     229376,     229376,     1024,     4096, 0x1a6a0b4c
+0,     230400,     230400,     1024,     4096, 0xdfd809b7
+0,     231424,     231424,     1024,     4096, 0x1d2cf5f1
+0,     232448,     232448,     1024,     4096, 0xd366f4a1
+0,     233472,     233472,     1024,     4096, 0x6a2f86e0
+0,     234496,     234496,     1024,     4096, 0xf51f08a9
+0,     235520,     235520,     1024,     4096, 0x05edefa8
+0,     236544,     236544,     1024,     4096, 0x255df2a6
+0,     237568,     237568,     1024,     4096, 0xe881d9e4
+0,     238592,     238592,     1024,     4096, 0x50380523
+0,     239616,     239616,     1024,     4096, 0x8b93eb26
+0,     240640,     240640,     1024,     4096, 0x759cf94c
+0,     241664,     241664,     1024,     4096, 0x8474f591
+0,     242688,     242688,     1024,     4096, 0x0030dc9e
+0,     243712,     243712,     1024,     4096, 0xb017fd54
+0,     244736,     244736,     1024,     4096, 0x5c7dfa2e
+0,     245760,     245760,     1024,     4096, 0x7887e599
+0,     246784,     246784,     1024,     4096, 0xb730e72f
+0,     247808,     247808,     1024,     4096, 0x6bb3fae4
+0,     248832,     248832,     1024,     4096, 0xcc08fc36
+0,     249856,     249856,     1024,     4096, 0x5afd9ec2
+0,     250880,     250880,     1024,     4096, 0xa1d3e83d
+0,     251904,     251904,     1024,     4096, 0x7f96013c
+0,     252928,     252928,     1024,     4096, 0x7a0afe31
+0,     253952,     253952,     1024,     4096, 0xa37d1701
+0,     254976,     254976,     1024,     4096, 0x4615ebc2
+0,     256000,     256000,     1024,     4096, 0x217005c1
+0,     257024,     257024,     1024,     4096, 0x1755f789
+0,     258048,     258048,     1024,     4096, 0x83e6db65
+0,     259072,     259072,     1024,     4096, 0x92ab1447
+0,     260096,     260096,     1024,     4096, 0xedbdf383
+0,     261120,     261120,     1024,     4096, 0x4316f6a9
+0,     262144,     262144,     1024,     4096, 0x1a6a0b4c
+0,     263168,     263168,     1024,     4096, 0xdfd809b7
+0,     264192,     264192,      408,     1632, 0xf412313e
diff --git a/tests/ref/fate/filter-afade-exp b/tests/ref/fate/filter-afade-exp
new file mode 100644
index 0000000..f98db38
--- /dev/null
+++ b/tests/ref/fate/filter-afade-exp
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0x00000000
+0,       1024,       1024,     1024,     4096, 0x00000000
+0,       2048,       2048,     1024,     4096, 0x00000000
+0,       3072,       3072,     1024,     4096, 0x00000000
+0,       4096,       4096,     1024,     4096, 0x00000000
+0,       5120,       5120,     1024,     4096, 0x00000000
+0,       6144,       6144,     1024,     4096, 0x00000000
+0,       7168,       7168,     1024,     4096, 0x00000000
+0,       8192,       8192,     1024,     4096, 0x00000000
+0,       9216,       9216,     1024,     4096, 0x00000000
+0,      10240,      10240,     1024,     4096, 0x00000000
+0,      11264,      11264,     1024,     4096, 0x00000000
+0,      12288,      12288,     1024,     4096, 0x00000000
+0,      13312,      13312,     1024,     4096, 0x00000000
+0,      14336,      14336,     1024,     4096, 0x00000000
+0,      15360,      15360,     1024,     4096, 0x00000000
+0,      16384,      16384,     1024,     4096, 0x00000000
+0,      17408,      17408,     1024,     4096, 0xfc60376d
+0,      18432,      18432,     1024,     4096, 0xfbe8d6c0
+0,      19456,      19456,     1024,     4096, 0x3b98ba4f
+0,      20480,      20480,     1024,     4096, 0x127b81e8
+0,      21504,      21504,     1024,     4096, 0xeeadf5b8
+0,      22528,      22528,     1024,     4096, 0xef824db7
+0,      23552,      23552,     1024,     4096, 0x48f6a58f
+0,      24576,      24576,     1024,     4096, 0x6c5c0d42
+0,      25600,      25600,     1024,     4096, 0x22e15d00
+0,      26624,      26624,     1024,     4096, 0x64ac7524
+0,      27648,      27648,     1024,     4096, 0x2726994c
+0,      28672,      28672,     1024,     4096, 0x755bd4fa
+0,      29696,      29696,     1024,     4096, 0x9acb1493
+0,      30720,      30720,     1024,     4096, 0xc4172c91
+0,      31744,      31744,     1024,     4096, 0xcd69291d
+0,      32768,      32768,     1024,     4096, 0xd3d64131
+0,      33792,      33792,     1024,     4096, 0xb3656c7f
+0,      34816,      34816,     1024,     4096, 0x763c93f3
+0,      35840,      35840,     1024,     4096, 0x994c84a5
+0,      36864,      36864,     1024,     4096, 0xcc9f8d75
+0,      37888,      37888,     1024,     4096, 0x2e259d03
+0,      38912,      38912,     1024,     4096, 0xcbdfcb9b
+0,      39936,      39936,     1024,     4096, 0xb01dcb79
+0,      40960,      40960,     1024,     4096, 0x4857b15f
+0,      41984,      41984,     1024,     4096, 0x04d9be25
+0,      43008,      43008,     1024,     4096, 0xc199cc25
+0,      44032,      44032,     1024,     4096, 0x068ec625
+0,      45056,      45056,     1024,     4096, 0xa659e141
+0,      46080,      46080,     1024,     4096, 0xebaaf33b
+0,      47104,      47104,     1024,     4096, 0x7142c21d
+0,      48128,      48128,     1024,     4096, 0x7859ec77
+0,      49152,      49152,     1024,     4096, 0x2944ec67
+0,      50176,      50176,     1024,     4096, 0x5b39e887
+0,      51200,      51200,     1024,     4096, 0x21c4e84d
+0,      52224,      52224,     1024,     4096, 0xd803fd77
+0,      53248,      53248,     1024,     4096, 0xae9ae32b
+0,      54272,      54272,     1024,     4096, 0x31b3e87f
+0,      55296,      55296,     1024,     4096, 0x287201ec
+0,      56320,      56320,     1024,     4096, 0xfa79e70d
+0,      57344,      57344,     1024,     4096, 0x7867fc9b
+0,      58368,      58368,     1024,     4096, 0xa5ec116c
+0,      59392,      59392,     1024,     4096, 0xe948f5d7
+0,      60416,      60416,     1024,     4096, 0xdcbbf6a3
+0,      61440,      61440,     1024,     4096, 0xc1fcdeeb
+0,      62464,      62464,     1024,     4096, 0x17b6f4a1
+0,      63488,      63488,     1024,     4096, 0x7f6e0294
+0,      64512,      64512,     1024,     4096, 0x3c8ce06b
+0,      65536,      65536,     1024,     4096, 0x0901140a
+0,      66560,      66560,     1024,     4096, 0x6162e9a7
+0,      67584,      67584,     1024,     4096, 0x22efe78f
+0,      68608,      68608,     1024,     4096, 0x329afcd7
+0,      69632,      69632,     1024,     4096, 0x747908ca
+0,      70656,      70656,     1024,     4096, 0x5cd9f1db
+0,      71680,      71680,     1024,     4096, 0x113a3a4a
+0,      72704,      72704,     1024,     4096, 0x89bedd25
+0,      73728,      73728,     1024,     4096, 0x3baac187
+0,      74752,      74752,     1024,     4096, 0xd569d461
+0,      75776,      75776,     1024,     4096, 0x7d9b1c42
+0,      76800,      76800,     1024,     4096, 0xfbf0e679
+0,      77824,      77824,     1024,     4096, 0x9ece0f62
+0,      78848,      78848,     1024,     4096, 0xeb72f071
+0,      79872,      79872,     1024,     4096, 0xad5bdf6d
+0,      80896,      80896,     1024,     4096, 0xa6af0554
+0,      81920,      81920,     1024,     4096, 0xe0902960
+0,      82944,      82944,     1024,     4096, 0x077cfdf3
+0,      83968,      83968,     1024,     4096, 0xa48b059a
+0,      84992,      84992,     1024,     4096, 0x4e7df3db
+0,      86016,      86016,     1024,     4096, 0x0550e899
+0,      87040,      87040,     1024,     4096, 0xa63ff5a9
+0,      88064,      88064,     1024,     4096, 0x9c15bfa7
+0,      89088,      89088,     1024,     4096, 0xe68dda8f
+0,      90112,      90112,     1024,     4096, 0xe457b505
+0,      91136,      91136,     1024,     4096, 0xda25a409
+0,      92160,      92160,     1024,     4096, 0x5b5d9d3b
+0,      93184,      93184,     1024,     4096, 0xa61eb13d
+0,      94208,      94208,     1024,     4096, 0xac93b66f
+0,      95232,      95232,     1024,     4096, 0xc7aeb33f
+0,      96256,      96256,     1024,     4096, 0x52cccfb5
+0,      97280,      97280,     1024,     4096, 0x4e4cf487
+0,      98304,      98304,     1024,     4096, 0x19c07f35
+0,      99328,      99328,     1024,     4096, 0x63ecd34f
+0,     100352,     100352,     1024,     4096, 0x122aec53
+0,     101376,     101376,     1024,     4096, 0x6581c0ad
+0,     102400,     102400,     1024,     4096, 0x640edb15
+0,     103424,     103424,     1024,     4096, 0x5d66c66f
+0,     104448,     104448,     1024,     4096, 0x069e9d35
+0,     105472,     105472,     1024,     4096, 0x5c9fd0e9
+0,     106496,     106496,     1024,     4096, 0x72468667
+0,     107520,     107520,     1024,     4096, 0x6e6dd02b
+0,     108544,     108544,     1024,     4096, 0x93edce33
+0,     109568,     109568,     1024,     4096, 0xcdfbd519
+0,     110592,     110592,     1024,     4096, 0x8463f2bb
+0,     111616,     111616,     1024,     4096, 0x5ca6f869
+0,     112640,     112640,     1024,     4096, 0x099a0398
+0,     113664,     113664,     1024,     4096, 0xa7fa10f0
+0,     114688,     114688,     1024,     4096, 0x28caddd3
+0,     115712,     115712,     1024,     4096, 0x4852ef8b
+0,     116736,     116736,     1024,     4096, 0x0250ee7b
+0,     117760,     117760,     1024,     4096, 0x9583da21
+0,     118784,     118784,     1024,     4096, 0x7365fb33
+0,     119808,     119808,     1024,     4096, 0x28c82066
+0,     120832,     120832,     1024,     4096, 0x94650be4
+0,     121856,     121856,     1024,     4096, 0xeb21f8eb
+0,     122880,     122880,     1024,     4096, 0xcd88f455
+0,     123904,     123904,     1024,     4096, 0x66a9efaf
+0,     124928,     124928,     1024,     4096, 0x5500c6ed
+0,     125952,     125952,     1024,     4096, 0x0ee0c62d
+0,     126976,     126976,     1024,     4096, 0x34d30762
+0,     128000,     128000,     1024,     4096, 0x8c0dec9f
+0,     129024,     129024,     1024,     4096, 0x790011d8
+0,     130048,     130048,     1024,     4096, 0xb76a1136
+0,     131072,     131072,     1024,     4096, 0x7dddfea7
+0,     132096,     132096,     1024,     4096, 0xdfa3ed49
+0,     133120,     133120,     1024,     4096, 0xc129f54e
+0,     134144,     134144,     1024,     4096, 0x9a86f077
+0,     135168,     135168,     1024,     4096, 0xc9eef209
+0,     136192,     136192,     1024,     4096, 0x72d4029b
+0,     137216,     137216,     1024,     4096, 0x8ec20590
+0,     138240,     138240,     1024,     4096, 0xd48f18ed
+0,     139264,     139264,     1024,     4096, 0xd807eadc
+0,     140288,     140288,     1024,     4096, 0x1e2bea09
+0,     141312,     141312,     1024,     4096, 0x937af12e
+0,     142336,     142336,     1024,     4096, 0xdedbf303
+0,     143360,     143360,     1024,     4096, 0xdc75df88
+0,     144384,     144384,     1024,     4096, 0x1845ffd6
+0,     145408,     145408,     1024,     4096, 0x20e8150c
+0,     146432,     146432,     1024,     4096, 0x5ea7eeef
+0,     147456,     147456,     1024,     4096, 0x4c7efa21
+0,     148480,     148480,     1024,     4096, 0x8b97e30e
+0,     149504,     149504,     1024,     4096, 0xe5040228
+0,     150528,     150528,     1024,     4096, 0x6283f78c
+0,     151552,     151552,     1024,     4096, 0xe7100140
+0,     152576,     152576,     1024,     4096, 0x9ea6f9b2
+0,     153600,     153600,     1024,     4096, 0x5f0e1563
+0,     154624,     154624,     1024,     4096, 0x510bf18e
+0,     155648,     155648,     1024,     4096, 0x5f4fe425
+0,     156672,     156672,     1024,     4096, 0x507af3c0
+0,     157696,     157696,     1024,     4096, 0xbf14ddc6
+0,     158720,     158720,     1024,     4096, 0x1871ed69
+0,     159744,     159744,     1024,     4096, 0xc349ef9f
+0,     160768,     160768,     1024,     4096, 0x4e2c1834
+0,     161792,     161792,     1024,     4096, 0x2383fe04
+0,     162816,     162816,     1024,     4096, 0x6626f415
+0,     163840,     163840,     1024,     4096, 0x283be379
+0,     164864,     164864,     1024,     4096, 0xc76c0ceb
+0,     165888,     165888,     1024,     4096, 0xa0b8040f
+0,     166912,     166912,     1024,     4096, 0x2535eb6d
+0,     167936,     167936,     1024,     4096, 0xeb180bb5
+0,     168960,     168960,     1024,     4096, 0xbc5cf059
+0,     169984,     169984,     1024,     4096, 0x1862f1ac
+0,     171008,     171008,     1024,     4096, 0x9cc2ea2b
+0,     172032,     172032,     1024,     4096, 0xbb9ae754
+0,     173056,     173056,     1024,     4096, 0x716debb5
+0,     174080,     174080,     1024,     4096, 0xff3aff2a
+0,     175104,     175104,     1024,     4096, 0x755dfa5c
+0,     176128,     176128,     1024,     4096, 0x3b830605
+0,     177152,     177152,     1024,     4096, 0x0030dc9e
+0,     178176,     178176,     1024,     4096, 0xb017fd54
+0,     179200,     179200,     1024,     4096, 0x5c7dfa2e
+0,     180224,     180224,     1024,     4096, 0x7887e599
+0,     181248,     181248,     1024,     4096, 0xb730e72f
+0,     182272,     182272,     1024,     4096, 0x6bb3fae4
+0,     183296,     183296,     1024,     4096, 0xcc08fc36
+0,     184320,     184320,     1024,     4096, 0x5afd9ec2
+0,     185344,     185344,     1024,     4096, 0xa1d3e83d
+0,     186368,     186368,     1024,     4096, 0x7f96013c
+0,     187392,     187392,     1024,     4096, 0x7a0afe31
+0,     188416,     188416,     1024,     4096, 0xa37d1701
+0,     189440,     189440,     1024,     4096, 0x4615ebc2
+0,     190464,     190464,     1024,     4096, 0x217005c1
+0,     191488,     191488,     1024,     4096, 0x1755f789
+0,     192512,     192512,     1024,     4096, 0x83e6db65
+0,     193536,     193536,     1024,     4096, 0x92ab1447
+0,     194560,     194560,     1024,     4096, 0xedbdf383
+0,     195584,     195584,     1024,     4096, 0x4316f6a9
+0,     196608,     196608,     1024,     4096, 0x1a6a0b4c
+0,     197632,     197632,     1024,     4096, 0xdfd809b7
+0,     198656,     198656,     1024,     4096, 0x1d2cf5f1
+0,     199680,     199680,     1024,     4096, 0xd366f4a1
+0,     200704,     200704,     1024,     4096, 0x6a2f86e0
+0,     201728,     201728,     1024,     4096, 0xf51f08a9
+0,     202752,     202752,     1024,     4096, 0x05edefa8
+0,     203776,     203776,     1024,     4096, 0x255df2a6
+0,     204800,     204800,     1024,     4096, 0xe881d9e4
+0,     205824,     205824,     1024,     4096, 0x50380523
+0,     206848,     206848,     1024,     4096, 0x8b93eb26
+0,     207872,     207872,     1024,     4096, 0x759cf94c
+0,     208896,     208896,     1024,     4096, 0x8474f591
+0,     209920,     209920,     1024,     4096, 0x0030dc9e
+0,     210944,     210944,     1024,     4096, 0xb017fd54
+0,     211968,     211968,     1024,     4096, 0x5c7dfa2e
+0,     212992,     212992,     1024,     4096, 0x7887e599
+0,     214016,     214016,     1024,     4096, 0xb730e72f
+0,     215040,     215040,     1024,     4096, 0x6bb3fae4
+0,     216064,     216064,     1024,     4096, 0xcc08fc36
+0,     217088,     217088,     1024,     4096, 0x5afd9ec2
+0,     218112,     218112,     1024,     4096, 0xa1d3e83d
+0,     219136,     219136,     1024,     4096, 0x7f96013c
+0,     220160,     220160,     1024,     4096, 0x7a0afe31
+0,     221184,     221184,     1024,     4096, 0xa37d1701
+0,     222208,     222208,     1024,     4096, 0x4615ebc2
+0,     223232,     223232,     1024,     4096, 0x217005c1
+0,     224256,     224256,     1024,     4096, 0x1755f789
+0,     225280,     225280,     1024,     4096, 0x83e6db65
+0,     226304,     226304,     1024,     4096, 0x92ab1447
+0,     227328,     227328,     1024,     4096, 0xedbdf383
+0,     228352,     228352,     1024,     4096, 0x4316f6a9
+0,     229376,     229376,     1024,     4096, 0x1a6a0b4c
+0,     230400,     230400,     1024,     4096, 0xdfd809b7
+0,     231424,     231424,     1024,     4096, 0x1d2cf5f1
+0,     232448,     232448,     1024,     4096, 0xd366f4a1
+0,     233472,     233472,     1024,     4096, 0x6a2f86e0
+0,     234496,     234496,     1024,     4096, 0xf51f08a9
+0,     235520,     235520,     1024,     4096, 0x05edefa8
+0,     236544,     236544,     1024,     4096, 0x255df2a6
+0,     237568,     237568,     1024,     4096, 0xe881d9e4
+0,     238592,     238592,     1024,     4096, 0x50380523
+0,     239616,     239616,     1024,     4096, 0x8b93eb26
+0,     240640,     240640,     1024,     4096, 0x759cf94c
+0,     241664,     241664,     1024,     4096, 0x8474f591
+0,     242688,     242688,     1024,     4096, 0x0030dc9e
+0,     243712,     243712,     1024,     4096, 0xb017fd54
+0,     244736,     244736,     1024,     4096, 0x5c7dfa2e
+0,     245760,     245760,     1024,     4096, 0x7887e599
+0,     246784,     246784,     1024,     4096, 0xb730e72f
+0,     247808,     247808,     1024,     4096, 0x6bb3fae4
+0,     248832,     248832,     1024,     4096, 0xcc08fc36
+0,     249856,     249856,     1024,     4096, 0x5afd9ec2
+0,     250880,     250880,     1024,     4096, 0xa1d3e83d
+0,     251904,     251904,     1024,     4096, 0x7f96013c
+0,     252928,     252928,     1024,     4096, 0x7a0afe31
+0,     253952,     253952,     1024,     4096, 0xa37d1701
+0,     254976,     254976,     1024,     4096, 0x4615ebc2
+0,     256000,     256000,     1024,     4096, 0x217005c1
+0,     257024,     257024,     1024,     4096, 0x1755f789
+0,     258048,     258048,     1024,     4096, 0x83e6db65
+0,     259072,     259072,     1024,     4096, 0x92ab1447
+0,     260096,     260096,     1024,     4096, 0xedbdf383
+0,     261120,     261120,     1024,     4096, 0x4316f6a9
+0,     262144,     262144,     1024,     4096, 0x1a6a0b4c
+0,     263168,     263168,     1024,     4096, 0xdfd809b7
+0,     264192,     264192,      408,     1632, 0xf412313e
diff --git a/tests/ref/fate/filter-afade-hsin b/tests/ref/fate/filter-afade-hsin
new file mode 100644
index 0000000..7e51a8c
--- /dev/null
+++ b/tests/ref/fate/filter-afade-hsin
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0x2042232e
+0,       1024,       1024,     1024,     4096, 0x2c073cf7
+0,       2048,       2048,     1024,     4096, 0x92fecae5
+0,       3072,       3072,     1024,     4096, 0xfd68df81
+0,       4096,       4096,     1024,     4096, 0xd7e0dcdd
+0,       5120,       5120,     1024,     4096, 0xfb12e849
+0,       6144,       6144,     1024,     4096, 0xdaa8fd25
+0,       7168,       7168,     1024,     4096, 0x28b101d6
+0,       8192,       8192,     1024,     4096, 0x4418e817
+0,       9216,       9216,     1024,     4096, 0x65d6e44d
+0,      10240,      10240,     1024,     4096, 0xc575f781
+0,      11264,      11264,     1024,     4096, 0xdf0bfdcd
+0,      12288,      12288,     1024,     4096, 0xd517faed
+0,      13312,      13312,     1024,     4096, 0x369de9b5
+0,      14336,      14336,     1024,     4096, 0x2245f4d9
+0,      15360,      15360,     1024,     4096, 0xf979fd8b
+0,      16384,      16384,     1024,     4096, 0xafcbfb8d
+0,      17408,      17408,     1024,     4096, 0xee6bf9e3
+0,      18432,      18432,     1024,     4096, 0x3bf1edfb
+0,      19456,      19456,     1024,     4096, 0x26b7faa1
+0,      20480,      20480,     1024,     4096, 0x559bf2db
+0,      21504,      21504,     1024,     4096, 0xe488fe45
+0,      22528,      22528,     1024,     4096, 0x8928e8fd
+0,      23552,      23552,     1024,     4096, 0xfc82f6cd
+0,      24576,      24576,     1024,     4096, 0xe8b6ed4b
+0,      25600,      25600,     1024,     4096, 0x73340aba
+0,      26624,      26624,     1024,     4096, 0xb934ecbf
+0,      27648,      27648,     1024,     4096, 0x0581f125
+0,      28672,      28672,     1024,     4096, 0x4e2cf113
+0,      29696,      29696,     1024,     4096, 0x716b0062
+0,      30720,      30720,     1024,     4096, 0x4de513aa
+0,      31744,      31744,     1024,     4096, 0x6a17ea33
+0,      32768,      32768,     1024,     4096, 0x6c28f127
+0,      33792,      33792,     1024,     4096, 0xdd81f81b
+0,      34816,      34816,     1024,     4096, 0x63f2fd47
+0,      35840,      35840,     1024,     4096, 0x9ab2ee63
+0,      36864,      36864,     1024,     4096, 0xf310f265
+0,      37888,      37888,     1024,     4096, 0xdb2eed95
+0,      38912,      38912,     1024,     4096, 0x3cf3fa13
+0,      39936,      39936,     1024,     4096, 0x632107da
+0,      40960,      40960,     1024,     4096, 0xb3030964
+0,      41984,      41984,     1024,     4096, 0x4001ec91
+0,      43008,      43008,     1024,     4096, 0xacd8ee23
+0,      44032,      44032,     1024,     4096, 0x49adf5b3
+0,      45056,      45056,     1024,     4096, 0x8a7a0b54
+0,      46080,      46080,     1024,     4096, 0xfe4e284c
+0,      47104,      47104,     1024,     4096, 0x9d7dfc1b
+0,      48128,      48128,     1024,     4096, 0x3fbafc3d
+0,      49152,      49152,     1024,     4096, 0x7846190e
+0,      50176,      50176,     1024,     4096, 0x81c706e8
+0,      51200,      51200,     1024,     4096, 0x0449edef
+0,      52224,      52224,     1024,     4096, 0xe4c9044c
+0,      53248,      53248,     1024,     4096, 0x11bcf517
+0,      54272,      54272,     1024,     4096, 0x7693fc23
+0,      55296,      55296,     1024,     4096, 0xfaa3ec59
+0,      56320,      56320,     1024,     4096, 0x1bbbffd1
+0,      57344,      57344,     1024,     4096, 0x750e0b66
+0,      58368,      58368,     1024,     4096, 0xff79fe49
+0,      59392,      59392,     1024,     4096, 0x9c2e2414
+0,      60416,      60416,     1024,     4096, 0xf5a8e3b1
+0,      61440,      61440,     1024,     4096, 0x4171eabd
+0,      62464,      62464,     1024,     4096, 0xe5dfd0b9
+0,      63488,      63488,     1024,     4096, 0x88d6e751
+0,      64512,      64512,     1024,     4096, 0x1aceeebb
+0,      65536,      65536,     1024,     4096, 0xfddde939
+0,      66560,      66560,     1024,     4096, 0x635d14d6
+0,      67584,      67584,     1024,     4096, 0x1216f111
+0,      68608,      68608,     1024,     4096, 0x76d1f751
+0,      69632,      69632,     1024,     4096, 0x2cfbe33d
+0,      70656,      70656,     1024,     4096, 0xaa5bf83d
+0,      71680,      71680,     1024,     4096, 0xc6dc2846
+0,      72704,      72704,     1024,     4096, 0x0f811cf6
+0,      73728,      73728,     1024,     4096, 0x699bf871
+0,      74752,      74752,     1024,     4096, 0x066be26f
+0,      75776,      75776,     1024,     4096, 0xfadff369
+0,      76800,      76800,     1024,     4096, 0x1581ff61
+0,      77824,      77824,     1024,     4096, 0xe3fc05fa
+0,      78848,      78848,     1024,     4096, 0x2333fcaf
+0,      79872,      79872,     1024,     4096, 0x5c0d2a24
+0,      80896,      80896,     1024,     4096, 0x0955ef21
+0,      81920,      81920,     1024,     4096, 0xe798fbc9
+0,      82944,      82944,     1024,     4096, 0x5cdf138c
+0,      83968,      83968,     1024,     4096, 0x3ffee37d
+0,      84992,      84992,     1024,     4096, 0x4bcff517
+0,      86016,      86016,     1024,     4096, 0x9b7f0722
+0,      87040,      87040,     1024,     4096, 0xb6fa1982
+0,      88064,      88064,     1024,     4096, 0x1b1ac8b7
+0,      89088,      89088,     1024,     4096, 0xe68dda8f
+0,      90112,      90112,     1024,     4096, 0xe457b505
+0,      91136,      91136,     1024,     4096, 0xda25a409
+0,      92160,      92160,     1024,     4096, 0x5b5d9d3b
+0,      93184,      93184,     1024,     4096, 0xa61eb13d
+0,      94208,      94208,     1024,     4096, 0xac93b66f
+0,      95232,      95232,     1024,     4096, 0xc7aeb33f
+0,      96256,      96256,     1024,     4096, 0x52cccfb5
+0,      97280,      97280,     1024,     4096, 0x4e4cf487
+0,      98304,      98304,     1024,     4096, 0x19c07f35
+0,      99328,      99328,     1024,     4096, 0x63ecd34f
+0,     100352,     100352,     1024,     4096, 0x122aec53
+0,     101376,     101376,     1024,     4096, 0x6581c0ad
+0,     102400,     102400,     1024,     4096, 0x640edb15
+0,     103424,     103424,     1024,     4096, 0x5d66c66f
+0,     104448,     104448,     1024,     4096, 0x069e9d35
+0,     105472,     105472,     1024,     4096, 0x5c9fd0e9
+0,     106496,     106496,     1024,     4096, 0x72468667
+0,     107520,     107520,     1024,     4096, 0x6e6dd02b
+0,     108544,     108544,     1024,     4096, 0x93edce33
+0,     109568,     109568,     1024,     4096, 0xcdfbd519
+0,     110592,     110592,     1024,     4096, 0x8463f2bb
+0,     111616,     111616,     1024,     4096, 0x5ca6f869
+0,     112640,     112640,     1024,     4096, 0x099a0398
+0,     113664,     113664,     1024,     4096, 0xa7fa10f0
+0,     114688,     114688,     1024,     4096, 0x28caddd3
+0,     115712,     115712,     1024,     4096, 0x4852ef8b
+0,     116736,     116736,     1024,     4096, 0x0250ee7b
+0,     117760,     117760,     1024,     4096, 0x9583da21
+0,     118784,     118784,     1024,     4096, 0x7365fb33
+0,     119808,     119808,     1024,     4096, 0x28c82066
+0,     120832,     120832,     1024,     4096, 0x94650be4
+0,     121856,     121856,     1024,     4096, 0xeb21f8eb
+0,     122880,     122880,     1024,     4096, 0xcd88f455
+0,     123904,     123904,     1024,     4096, 0x66a9efaf
+0,     124928,     124928,     1024,     4096, 0x5500c6ed
+0,     125952,     125952,     1024,     4096, 0x0ee0c62d
+0,     126976,     126976,     1024,     4096, 0x34d30762
+0,     128000,     128000,     1024,     4096, 0x8c0dec9f
+0,     129024,     129024,     1024,     4096, 0x790011d8
+0,     130048,     130048,     1024,     4096, 0xb76a1136
+0,     131072,     131072,     1024,     4096, 0x7dddfea7
+0,     132096,     132096,     1024,     4096, 0xdfa3ed49
+0,     133120,     133120,     1024,     4096, 0xc129f54e
+0,     134144,     134144,     1024,     4096, 0x9a86f077
+0,     135168,     135168,     1024,     4096, 0xc9eef209
+0,     136192,     136192,     1024,     4096, 0x72d4029b
+0,     137216,     137216,     1024,     4096, 0x8ec20590
+0,     138240,     138240,     1024,     4096, 0xd48f18ed
+0,     139264,     139264,     1024,     4096, 0xd807eadc
+0,     140288,     140288,     1024,     4096, 0x1e2bea09
+0,     141312,     141312,     1024,     4096, 0x937af12e
+0,     142336,     142336,     1024,     4096, 0xdedbf303
+0,     143360,     143360,     1024,     4096, 0xdc75df88
+0,     144384,     144384,     1024,     4096, 0x1845ffd6
+0,     145408,     145408,     1024,     4096, 0x20e8150c
+0,     146432,     146432,     1024,     4096, 0x5ea7eeef
+0,     147456,     147456,     1024,     4096, 0x4c7efa21
+0,     148480,     148480,     1024,     4096, 0x8b97e30e
+0,     149504,     149504,     1024,     4096, 0xe5040228
+0,     150528,     150528,     1024,     4096, 0x6283f78c
+0,     151552,     151552,     1024,     4096, 0xe7100140
+0,     152576,     152576,     1024,     4096, 0x9ea6f9b2
+0,     153600,     153600,     1024,     4096, 0x5f0e1563
+0,     154624,     154624,     1024,     4096, 0x510bf18e
+0,     155648,     155648,     1024,     4096, 0x5f4fe425
+0,     156672,     156672,     1024,     4096, 0x507af3c0
+0,     157696,     157696,     1024,     4096, 0xbf14ddc6
+0,     158720,     158720,     1024,     4096, 0x1871ed69
+0,     159744,     159744,     1024,     4096, 0xc349ef9f
+0,     160768,     160768,     1024,     4096, 0x4e2c1834
+0,     161792,     161792,     1024,     4096, 0x2383fe04
+0,     162816,     162816,     1024,     4096, 0x6626f415
+0,     163840,     163840,     1024,     4096, 0x283be379
+0,     164864,     164864,     1024,     4096, 0xc76c0ceb
+0,     165888,     165888,     1024,     4096, 0xa0b8040f
+0,     166912,     166912,     1024,     4096, 0x2535eb6d
+0,     167936,     167936,     1024,     4096, 0xeb180bb5
+0,     168960,     168960,     1024,     4096, 0xbc5cf059
+0,     169984,     169984,     1024,     4096, 0x1862f1ac
+0,     171008,     171008,     1024,     4096, 0x9cc2ea2b
+0,     172032,     172032,     1024,     4096, 0xbb9ae754
+0,     173056,     173056,     1024,     4096, 0x716debb5
+0,     174080,     174080,     1024,     4096, 0xff3aff2a
+0,     175104,     175104,     1024,     4096, 0x755dfa5c
+0,     176128,     176128,     1024,     4096, 0x3b830605
+0,     177152,     177152,     1024,     4096, 0x0030dc9e
+0,     178176,     178176,     1024,     4096, 0xb017fd54
+0,     179200,     179200,     1024,     4096, 0x5c7dfa2e
+0,     180224,     180224,     1024,     4096, 0x7887e599
+0,     181248,     181248,     1024,     4096, 0xb730e72f
+0,     182272,     182272,     1024,     4096, 0x6bb3fae4
+0,     183296,     183296,     1024,     4096, 0xcc08fc36
+0,     184320,     184320,     1024,     4096, 0x5afd9ec2
+0,     185344,     185344,     1024,     4096, 0xa1d3e83d
+0,     186368,     186368,     1024,     4096, 0x7f96013c
+0,     187392,     187392,     1024,     4096, 0x7a0afe31
+0,     188416,     188416,     1024,     4096, 0xa37d1701
+0,     189440,     189440,     1024,     4096, 0x4615ebc2
+0,     190464,     190464,     1024,     4096, 0x217005c1
+0,     191488,     191488,     1024,     4096, 0x1755f789
+0,     192512,     192512,     1024,     4096, 0x83e6db65
+0,     193536,     193536,     1024,     4096, 0x92ab1447
+0,     194560,     194560,     1024,     4096, 0xedbdf383
+0,     195584,     195584,     1024,     4096, 0x4316f6a9
+0,     196608,     196608,     1024,     4096, 0x1a6a0b4c
+0,     197632,     197632,     1024,     4096, 0xdfd809b7
+0,     198656,     198656,     1024,     4096, 0x1d2cf5f1
+0,     199680,     199680,     1024,     4096, 0xd366f4a1
+0,     200704,     200704,     1024,     4096, 0x6a2f86e0
+0,     201728,     201728,     1024,     4096, 0xf51f08a9
+0,     202752,     202752,     1024,     4096, 0x05edefa8
+0,     203776,     203776,     1024,     4096, 0x255df2a6
+0,     204800,     204800,     1024,     4096, 0xe881d9e4
+0,     205824,     205824,     1024,     4096, 0x50380523
+0,     206848,     206848,     1024,     4096, 0x8b93eb26
+0,     207872,     207872,     1024,     4096, 0x759cf94c
+0,     208896,     208896,     1024,     4096, 0x8474f591
+0,     209920,     209920,     1024,     4096, 0x0030dc9e
+0,     210944,     210944,     1024,     4096, 0xb017fd54
+0,     211968,     211968,     1024,     4096, 0x5c7dfa2e
+0,     212992,     212992,     1024,     4096, 0x7887e599
+0,     214016,     214016,     1024,     4096, 0xb730e72f
+0,     215040,     215040,     1024,     4096, 0x6bb3fae4
+0,     216064,     216064,     1024,     4096, 0xcc08fc36
+0,     217088,     217088,     1024,     4096, 0x5afd9ec2
+0,     218112,     218112,     1024,     4096, 0xa1d3e83d
+0,     219136,     219136,     1024,     4096, 0x7f96013c
+0,     220160,     220160,     1024,     4096, 0x7a0afe31
+0,     221184,     221184,     1024,     4096, 0xa37d1701
+0,     222208,     222208,     1024,     4096, 0x4615ebc2
+0,     223232,     223232,     1024,     4096, 0x217005c1
+0,     224256,     224256,     1024,     4096, 0x1755f789
+0,     225280,     225280,     1024,     4096, 0x83e6db65
+0,     226304,     226304,     1024,     4096, 0x92ab1447
+0,     227328,     227328,     1024,     4096, 0xedbdf383
+0,     228352,     228352,     1024,     4096, 0x4316f6a9
+0,     229376,     229376,     1024,     4096, 0x1a6a0b4c
+0,     230400,     230400,     1024,     4096, 0xdfd809b7
+0,     231424,     231424,     1024,     4096, 0x1d2cf5f1
+0,     232448,     232448,     1024,     4096, 0xd366f4a1
+0,     233472,     233472,     1024,     4096, 0x6a2f86e0
+0,     234496,     234496,     1024,     4096, 0xf51f08a9
+0,     235520,     235520,     1024,     4096, 0x05edefa8
+0,     236544,     236544,     1024,     4096, 0x255df2a6
+0,     237568,     237568,     1024,     4096, 0xe881d9e4
+0,     238592,     238592,     1024,     4096, 0x50380523
+0,     239616,     239616,     1024,     4096, 0x8b93eb26
+0,     240640,     240640,     1024,     4096, 0x759cf94c
+0,     241664,     241664,     1024,     4096, 0x8474f591
+0,     242688,     242688,     1024,     4096, 0x0030dc9e
+0,     243712,     243712,     1024,     4096, 0xb017fd54
+0,     244736,     244736,     1024,     4096, 0x5c7dfa2e
+0,     245760,     245760,     1024,     4096, 0x7887e599
+0,     246784,     246784,     1024,     4096, 0xb730e72f
+0,     247808,     247808,     1024,     4096, 0x6bb3fae4
+0,     248832,     248832,     1024,     4096, 0xcc08fc36
+0,     249856,     249856,     1024,     4096, 0x5afd9ec2
+0,     250880,     250880,     1024,     4096, 0xa1d3e83d
+0,     251904,     251904,     1024,     4096, 0x7f96013c
+0,     252928,     252928,     1024,     4096, 0x7a0afe31
+0,     253952,     253952,     1024,     4096, 0xa37d1701
+0,     254976,     254976,     1024,     4096, 0x4615ebc2
+0,     256000,     256000,     1024,     4096, 0x217005c1
+0,     257024,     257024,     1024,     4096, 0x1755f789
+0,     258048,     258048,     1024,     4096, 0x83e6db65
+0,     259072,     259072,     1024,     4096, 0x92ab1447
+0,     260096,     260096,     1024,     4096, 0xedbdf383
+0,     261120,     261120,     1024,     4096, 0x4316f6a9
+0,     262144,     262144,     1024,     4096, 0x1a6a0b4c
+0,     263168,     263168,     1024,     4096, 0xdfd809b7
+0,     264192,     264192,      408,     1632, 0xf412313e
diff --git a/tests/ref/fate/filter-afade-iqsin b/tests/ref/fate/filter-afade-iqsin
new file mode 100644
index 0000000..aa7eea7
--- /dev/null
+++ b/tests/ref/fate/filter-afade-iqsin
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0x220e908d
+0,       1024,       1024,     1024,     4096, 0xdd65002e
+0,       2048,       2048,     1024,     4096, 0x8072fb25
+0,       3072,       3072,     1024,     4096, 0xe82efbb5
+0,       4096,       4096,     1024,     4096, 0xf0aceaad
+0,       5120,       5120,     1024,     4096, 0x0702f14d
+0,       6144,       6144,     1024,     4096, 0xde010588
+0,       7168,       7168,     1024,     4096, 0x65d0ff3d
+0,       8192,       8192,     1024,     4096, 0xfcd3eceb
+0,       9216,       9216,     1024,     4096, 0x0046ee27
+0,      10240,      10240,     1024,     4096, 0x9811fd1f
+0,      11264,      11264,     1024,     4096, 0x2486026e
+0,      12288,      12288,     1024,     4096, 0x5f15fa05
+0,      13312,      13312,     1024,     4096, 0xf481f255
+0,      14336,      14336,     1024,     4096, 0x473df0cf
+0,      15360,      15360,     1024,     4096, 0x65b3ffe5
+0,      16384,      16384,     1024,     4096, 0x46c10642
+0,      17408,      17408,     1024,     4096, 0x6647f01f
+0,      18432,      18432,     1024,     4096, 0x8682f66f
+0,      19456,      19456,     1024,     4096, 0x2fe1f87d
+0,      20480,      20480,     1024,     4096, 0x33ddfadb
+0,      21504,      21504,     1024,     4096, 0x8e1cfeaf
+0,      22528,      22528,     1024,     4096, 0x8f87eb79
+0,      23552,      23552,     1024,     4096, 0x79ddf2b7
+0,      24576,      24576,     1024,     4096, 0x74b6ee5d
+0,      25600,      25600,     1024,     4096, 0xd4240c2a
+0,      26624,      26624,     1024,     4096, 0x7e75e153
+0,      27648,      27648,     1024,     4096, 0xe46fee4f
+0,      28672,      28672,     1024,     4096, 0x7bddec1d
+0,      29696,      29696,     1024,     4096, 0xb1590b70
+0,      30720,      30720,     1024,     4096, 0x66fb00fa
+0,      31744,      31744,     1024,     4096, 0xf19dea17
+0,      32768,      32768,     1024,     4096, 0x831efdb7
+0,      33792,      33792,     1024,     4096, 0x1ef4f41d
+0,      34816,      34816,     1024,     4096, 0x0fa603ea
+0,      35840,      35840,     1024,     4096, 0x7fa6f915
+0,      36864,      36864,     1024,     4096, 0x3ed1f89f
+0,      37888,      37888,     1024,     4096, 0x4ac6e845
+0,      38912,      38912,     1024,     4096, 0xda9f108c
+0,      39936,      39936,     1024,     4096, 0xa88506fa
+0,      40960,      40960,     1024,     4096, 0xdcbee81d
+0,      41984,      41984,     1024,     4096, 0x2441ece7
+0,      43008,      43008,     1024,     4096, 0x7784fbbd
+0,      44032,      44032,     1024,     4096, 0xec83fbf3
+0,      45056,      45056,     1024,     4096, 0xe18704ca
+0,      46080,      46080,     1024,     4096, 0x4d7d2026
+0,      47104,      47104,     1024,     4096, 0x8d1fedeb
+0,      48128,      48128,     1024,     4096, 0xffb8f301
+0,      49152,      49152,     1024,     4096, 0x4c8dd537
+0,      50176,      50176,     1024,     4096, 0xaa9cf755
+0,      51200,      51200,     1024,     4096, 0x15aee753
+0,      52224,      52224,     1024,     4096, 0xe71e19c4
+0,      53248,      53248,     1024,     4096, 0x5e6cd725
+0,      54272,      54272,     1024,     4096, 0x02ebfde7
+0,      55296,      55296,     1024,     4096, 0xa565f353
+0,      56320,      56320,     1024,     4096, 0x24badf45
+0,      57344,      57344,     1024,     4096, 0x8d9af215
+0,      58368,      58368,     1024,     4096, 0xfb20045e
+0,      59392,      59392,     1024,     4096, 0x01adff9b
+0,      60416,      60416,     1024,     4096, 0xd686e6d3
+0,      61440,      61440,     1024,     4096, 0xe25bf975
+0,      62464,      62464,     1024,     4096, 0xd54c0ad6
+0,      63488,      63488,     1024,     4096, 0xb48eea55
+0,      64512,      64512,     1024,     4096, 0xe4d5fbeb
+0,      65536,      65536,     1024,     4096, 0x169dfe7b
+0,      66560,      66560,     1024,     4096, 0x5eebf921
+0,      67584,      67584,     1024,     4096, 0xc2a5de3f
+0,      68608,      68608,     1024,     4096, 0xa7b9db85
+0,      69632,      69632,     1024,     4096, 0xa52ee4b7
+0,      70656,      70656,     1024,     4096, 0x5ac1104a
+0,      71680,      71680,     1024,     4096, 0x3ed334b6
+0,      72704,      72704,     1024,     4096, 0x94d30f06
+0,      73728,      73728,     1024,     4096, 0x0721e755
+0,      74752,      74752,     1024,     4096, 0x4503043c
+0,      75776,      75776,     1024,     4096, 0xed11e7b9
+0,      76800,      76800,     1024,     4096, 0xf4f807d0
+0,      77824,      77824,     1024,     4096, 0x0f2bf579
+0,      78848,      78848,     1024,     4096, 0x9facf6b1
+0,      79872,      79872,     1024,     4096, 0x244206a2
+0,      80896,      80896,     1024,     4096, 0xfd4ff779
+0,      81920,      81920,     1024,     4096, 0x342010c0
+0,      82944,      82944,     1024,     4096, 0xa93a1c46
+0,      83968,      83968,     1024,     4096, 0x88f5263e
+0,      84992,      84992,     1024,     4096, 0x67b4fa25
+0,      86016,      86016,     1024,     4096, 0x1276e9b5
+0,      87040,      87040,     1024,     4096, 0x55d70f0c
+0,      88064,      88064,     1024,     4096, 0x281bc8af
+0,      89088,      89088,     1024,     4096, 0xe68dda8f
+0,      90112,      90112,     1024,     4096, 0xe457b505
+0,      91136,      91136,     1024,     4096, 0xda25a409
+0,      92160,      92160,     1024,     4096, 0x5b5d9d3b
+0,      93184,      93184,     1024,     4096, 0xa61eb13d
+0,      94208,      94208,     1024,     4096, 0xac93b66f
+0,      95232,      95232,     1024,     4096, 0xc7aeb33f
+0,      96256,      96256,     1024,     4096, 0x52cccfb5
+0,      97280,      97280,     1024,     4096, 0x4e4cf487
+0,      98304,      98304,     1024,     4096, 0x19c07f35
+0,      99328,      99328,     1024,     4096, 0x63ecd34f
+0,     100352,     100352,     1024,     4096, 0x122aec53
+0,     101376,     101376,     1024,     4096, 0x6581c0ad
+0,     102400,     102400,     1024,     4096, 0x640edb15
+0,     103424,     103424,     1024,     4096, 0x5d66c66f
+0,     104448,     104448,     1024,     4096, 0x069e9d35
+0,     105472,     105472,     1024,     4096, 0x5c9fd0e9
+0,     106496,     106496,     1024,     4096, 0x72468667
+0,     107520,     107520,     1024,     4096, 0x6e6dd02b
+0,     108544,     108544,     1024,     4096, 0x93edce33
+0,     109568,     109568,     1024,     4096, 0xcdfbd519
+0,     110592,     110592,     1024,     4096, 0x8463f2bb
+0,     111616,     111616,     1024,     4096, 0x5ca6f869
+0,     112640,     112640,     1024,     4096, 0x099a0398
+0,     113664,     113664,     1024,     4096, 0xa7fa10f0
+0,     114688,     114688,     1024,     4096, 0x28caddd3
+0,     115712,     115712,     1024,     4096, 0x4852ef8b
+0,     116736,     116736,     1024,     4096, 0x0250ee7b
+0,     117760,     117760,     1024,     4096, 0x9583da21
+0,     118784,     118784,     1024,     4096, 0x7365fb33
+0,     119808,     119808,     1024,     4096, 0x28c82066
+0,     120832,     120832,     1024,     4096, 0x94650be4
+0,     121856,     121856,     1024,     4096, 0xeb21f8eb
+0,     122880,     122880,     1024,     4096, 0xcd88f455
+0,     123904,     123904,     1024,     4096, 0x66a9efaf
+0,     124928,     124928,     1024,     4096, 0x5500c6ed
+0,     125952,     125952,     1024,     4096, 0x0ee0c62d
+0,     126976,     126976,     1024,     4096, 0x34d30762
+0,     128000,     128000,     1024,     4096, 0x8c0dec9f
+0,     129024,     129024,     1024,     4096, 0x790011d8
+0,     130048,     130048,     1024,     4096, 0xb76a1136
+0,     131072,     131072,     1024,     4096, 0x7dddfea7
+0,     132096,     132096,     1024,     4096, 0xdfa3ed49
+0,     133120,     133120,     1024,     4096, 0xc129f54e
+0,     134144,     134144,     1024,     4096, 0x9a86f077
+0,     135168,     135168,     1024,     4096, 0xc9eef209
+0,     136192,     136192,     1024,     4096, 0x72d4029b
+0,     137216,     137216,     1024,     4096, 0x8ec20590
+0,     138240,     138240,     1024,     4096, 0xd48f18ed
+0,     139264,     139264,     1024,     4096, 0xd807eadc
+0,     140288,     140288,     1024,     4096, 0x1e2bea09
+0,     141312,     141312,     1024,     4096, 0x937af12e
+0,     142336,     142336,     1024,     4096, 0xdedbf303
+0,     143360,     143360,     1024,     4096, 0xdc75df88
+0,     144384,     144384,     1024,     4096, 0x1845ffd6
+0,     145408,     145408,     1024,     4096, 0x20e8150c
+0,     146432,     146432,     1024,     4096, 0x5ea7eeef
+0,     147456,     147456,     1024,     4096, 0x4c7efa21
+0,     148480,     148480,     1024,     4096, 0x8b97e30e
+0,     149504,     149504,     1024,     4096, 0xe5040228
+0,     150528,     150528,     1024,     4096, 0x6283f78c
+0,     151552,     151552,     1024,     4096, 0xe7100140
+0,     152576,     152576,     1024,     4096, 0x9ea6f9b2
+0,     153600,     153600,     1024,     4096, 0x5f0e1563
+0,     154624,     154624,     1024,     4096, 0x510bf18e
+0,     155648,     155648,     1024,     4096, 0x5f4fe425
+0,     156672,     156672,     1024,     4096, 0x507af3c0
+0,     157696,     157696,     1024,     4096, 0xbf14ddc6
+0,     158720,     158720,     1024,     4096, 0x1871ed69
+0,     159744,     159744,     1024,     4096, 0xc349ef9f
+0,     160768,     160768,     1024,     4096, 0x4e2c1834
+0,     161792,     161792,     1024,     4096, 0x2383fe04
+0,     162816,     162816,     1024,     4096, 0x6626f415
+0,     163840,     163840,     1024,     4096, 0x283be379
+0,     164864,     164864,     1024,     4096, 0xc76c0ceb
+0,     165888,     165888,     1024,     4096, 0xa0b8040f
+0,     166912,     166912,     1024,     4096, 0x2535eb6d
+0,     167936,     167936,     1024,     4096, 0xeb180bb5
+0,     168960,     168960,     1024,     4096, 0xbc5cf059
+0,     169984,     169984,     1024,     4096, 0x1862f1ac
+0,     171008,     171008,     1024,     4096, 0x9cc2ea2b
+0,     172032,     172032,     1024,     4096, 0xbb9ae754
+0,     173056,     173056,     1024,     4096, 0x716debb5
+0,     174080,     174080,     1024,     4096, 0xff3aff2a
+0,     175104,     175104,     1024,     4096, 0x755dfa5c
+0,     176128,     176128,     1024,     4096, 0x3b830605
+0,     177152,     177152,     1024,     4096, 0x0030dc9e
+0,     178176,     178176,     1024,     4096, 0xb017fd54
+0,     179200,     179200,     1024,     4096, 0x5c7dfa2e
+0,     180224,     180224,     1024,     4096, 0x7887e599
+0,     181248,     181248,     1024,     4096, 0xb730e72f
+0,     182272,     182272,     1024,     4096, 0x6bb3fae4
+0,     183296,     183296,     1024,     4096, 0xcc08fc36
+0,     184320,     184320,     1024,     4096, 0x5afd9ec2
+0,     185344,     185344,     1024,     4096, 0xa1d3e83d
+0,     186368,     186368,     1024,     4096, 0x7f96013c
+0,     187392,     187392,     1024,     4096, 0x7a0afe31
+0,     188416,     188416,     1024,     4096, 0xa37d1701
+0,     189440,     189440,     1024,     4096, 0x4615ebc2
+0,     190464,     190464,     1024,     4096, 0x217005c1
+0,     191488,     191488,     1024,     4096, 0x1755f789
+0,     192512,     192512,     1024,     4096, 0x83e6db65
+0,     193536,     193536,     1024,     4096, 0x92ab1447
+0,     194560,     194560,     1024,     4096, 0xedbdf383
+0,     195584,     195584,     1024,     4096, 0x4316f6a9
+0,     196608,     196608,     1024,     4096, 0x1a6a0b4c
+0,     197632,     197632,     1024,     4096, 0xdfd809b7
+0,     198656,     198656,     1024,     4096, 0x1d2cf5f1
+0,     199680,     199680,     1024,     4096, 0xd366f4a1
+0,     200704,     200704,     1024,     4096, 0x6a2f86e0
+0,     201728,     201728,     1024,     4096, 0xf51f08a9
+0,     202752,     202752,     1024,     4096, 0x05edefa8
+0,     203776,     203776,     1024,     4096, 0x255df2a6
+0,     204800,     204800,     1024,     4096, 0xe881d9e4
+0,     205824,     205824,     1024,     4096, 0x50380523
+0,     206848,     206848,     1024,     4096, 0x8b93eb26
+0,     207872,     207872,     1024,     4096, 0x759cf94c
+0,     208896,     208896,     1024,     4096, 0x8474f591
+0,     209920,     209920,     1024,     4096, 0x0030dc9e
+0,     210944,     210944,     1024,     4096, 0xb017fd54
+0,     211968,     211968,     1024,     4096, 0x5c7dfa2e
+0,     212992,     212992,     1024,     4096, 0x7887e599
+0,     214016,     214016,     1024,     4096, 0xb730e72f
+0,     215040,     215040,     1024,     4096, 0x6bb3fae4
+0,     216064,     216064,     1024,     4096, 0xcc08fc36
+0,     217088,     217088,     1024,     4096, 0x5afd9ec2
+0,     218112,     218112,     1024,     4096, 0xa1d3e83d
+0,     219136,     219136,     1024,     4096, 0x7f96013c
+0,     220160,     220160,     1024,     4096, 0x7a0afe31
+0,     221184,     221184,     1024,     4096, 0xa37d1701
+0,     222208,     222208,     1024,     4096, 0x4615ebc2
+0,     223232,     223232,     1024,     4096, 0x217005c1
+0,     224256,     224256,     1024,     4096, 0x1755f789
+0,     225280,     225280,     1024,     4096, 0x83e6db65
+0,     226304,     226304,     1024,     4096, 0x92ab1447
+0,     227328,     227328,     1024,     4096, 0xedbdf383
+0,     228352,     228352,     1024,     4096, 0x4316f6a9
+0,     229376,     229376,     1024,     4096, 0x1a6a0b4c
+0,     230400,     230400,     1024,     4096, 0xdfd809b7
+0,     231424,     231424,     1024,     4096, 0x1d2cf5f1
+0,     232448,     232448,     1024,     4096, 0xd366f4a1
+0,     233472,     233472,     1024,     4096, 0x6a2f86e0
+0,     234496,     234496,     1024,     4096, 0xf51f08a9
+0,     235520,     235520,     1024,     4096, 0x05edefa8
+0,     236544,     236544,     1024,     4096, 0x255df2a6
+0,     237568,     237568,     1024,     4096, 0xe881d9e4
+0,     238592,     238592,     1024,     4096, 0x50380523
+0,     239616,     239616,     1024,     4096, 0x8b93eb26
+0,     240640,     240640,     1024,     4096, 0x759cf94c
+0,     241664,     241664,     1024,     4096, 0x8474f591
+0,     242688,     242688,     1024,     4096, 0x0030dc9e
+0,     243712,     243712,     1024,     4096, 0xb017fd54
+0,     244736,     244736,     1024,     4096, 0x5c7dfa2e
+0,     245760,     245760,     1024,     4096, 0x7887e599
+0,     246784,     246784,     1024,     4096, 0xb730e72f
+0,     247808,     247808,     1024,     4096, 0x6bb3fae4
+0,     248832,     248832,     1024,     4096, 0xcc08fc36
+0,     249856,     249856,     1024,     4096, 0x5afd9ec2
+0,     250880,     250880,     1024,     4096, 0xa1d3e83d
+0,     251904,     251904,     1024,     4096, 0x7f96013c
+0,     252928,     252928,     1024,     4096, 0x7a0afe31
+0,     253952,     253952,     1024,     4096, 0xa37d1701
+0,     254976,     254976,     1024,     4096, 0x4615ebc2
+0,     256000,     256000,     1024,     4096, 0x217005c1
+0,     257024,     257024,     1024,     4096, 0x1755f789
+0,     258048,     258048,     1024,     4096, 0x83e6db65
+0,     259072,     259072,     1024,     4096, 0x92ab1447
+0,     260096,     260096,     1024,     4096, 0xedbdf383
+0,     261120,     261120,     1024,     4096, 0x4316f6a9
+0,     262144,     262144,     1024,     4096, 0x1a6a0b4c
+0,     263168,     263168,     1024,     4096, 0xdfd809b7
+0,     264192,     264192,      408,     1632, 0xf412313e
diff --git a/tests/ref/fate/filter-afade-log b/tests/ref/fate/filter-afade-log
new file mode 100644
index 0000000..03d5794
--- /dev/null
+++ b/tests/ref/fate/filter-afade-log
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0xf01adbd3
+0,       1024,       1024,     1024,     4096, 0xbbe10f8e
+0,       2048,       2048,     1024,     4096, 0xbf04fccf
+0,       3072,       3072,     1024,     4096, 0x70e5fc39
+0,       4096,       4096,     1024,     4096, 0x93a2ecdf
+0,       5120,       5120,     1024,     4096, 0x1680e311
+0,       6144,       6144,     1024,     4096, 0xb73ef96d
+0,       7168,       7168,     1024,     4096, 0x3dbcfe5f
+0,       8192,       8192,     1024,     4096, 0xfdbd029c
+0,       9216,       9216,     1024,     4096, 0x4f8fea8f
+0,      10240,      10240,     1024,     4096, 0x54580154
+0,      11264,      11264,     1024,     4096, 0x471d1012
+0,      12288,      12288,     1024,     4096, 0xf6cefe57
+0,      13312,      13312,     1024,     4096, 0x6a550156
+0,      14336,      14336,     1024,     4096, 0xba5c06ca
+0,      15360,      15360,     1024,     4096, 0xa280fd09
+0,      16384,      16384,     1024,     4096, 0x06b30e68
+0,      17408,      17408,     1024,     4096, 0xd3f1f92d
+0,      18432,      18432,     1024,     4096, 0xf75de519
+0,      19456,      19456,     1024,     4096, 0x411cf0e5
+0,      20480,      20480,     1024,     4096, 0xeeb80566
+0,      21504,      21504,     1024,     4096, 0xa57c064c
+0,      22528,      22528,     1024,     4096, 0x6476f72f
+0,      23552,      23552,     1024,     4096, 0x6e1bef53
+0,      24576,      24576,     1024,     4096, 0x911ff843
+0,      25600,      25600,     1024,     4096, 0x4e3713c4
+0,      26624,      26624,     1024,     4096, 0x3434fb71
+0,      27648,      27648,     1024,     4096, 0xd3c1eaed
+0,      28672,      28672,     1024,     4096, 0x8804e87d
+0,      29696,      29696,     1024,     4096, 0xd1fa03e2
+0,      30720,      30720,     1024,     4096, 0x9d56fc21
+0,      31744,      31744,     1024,     4096, 0x63d6f2fb
+0,      32768,      32768,     1024,     4096, 0xa1ddfa6d
+0,      33792,      33792,     1024,     4096, 0x998309ee
+0,      34816,      34816,     1024,     4096, 0xcebc0632
+0,      35840,      35840,     1024,     4096, 0x9860e503
+0,      36864,      36864,     1024,     4096, 0xa3e910d8
+0,      37888,      37888,     1024,     4096, 0x2449caed
+0,      38912,      38912,     1024,     4096, 0x1faf0e9a
+0,      39936,      39936,     1024,     4096, 0xe18fdb59
+0,      40960,      40960,     1024,     4096, 0xaa0b057e
+0,      41984,      41984,     1024,     4096, 0x2b18cae1
+0,      43008,      43008,     1024,     4096, 0x6f0a1338
+0,      44032,      44032,     1024,     4096, 0x59af03b2
+0,      45056,      45056,     1024,     4096, 0xd204f533
+0,      46080,      46080,     1024,     4096, 0xae5b0ed2
+0,      47104,      47104,     1024,     4096, 0xfebfc253
+0,      48128,      48128,     1024,     4096, 0x268bd8d9
+0,      49152,      49152,     1024,     4096, 0x5c78024a
+0,      50176,      50176,     1024,     4096, 0x5a36f343
+0,      51200,      51200,     1024,     4096, 0x1899cc19
+0,      52224,      52224,     1024,     4096, 0x8b27dea9
+0,      53248,      53248,     1024,     4096, 0x1ed7cbbf
+0,      54272,      54272,     1024,     4096, 0x0c8e15c4
+0,      55296,      55296,     1024,     4096, 0xb864004c
+0,      56320,      56320,     1024,     4096, 0x327effbf
+0,      57344,      57344,     1024,     4096, 0x5c3e2056
+0,      58368,      58368,     1024,     4096, 0xb704086a
+0,      59392,      59392,     1024,     4096, 0x0efdff09
+0,      60416,      60416,     1024,     4096, 0x979406e0
+0,      61440,      61440,     1024,     4096, 0x1115e93d
+0,      62464,      62464,     1024,     4096, 0x3d62f097
+0,      63488,      63488,     1024,     4096, 0xe6f8e051
+0,      64512,      64512,     1024,     4096, 0x30d40464
+0,      65536,      65536,     1024,     4096, 0x5c2f1726
+0,      66560,      66560,     1024,     4096, 0x2ac3cdd5
+0,      67584,      67584,     1024,     4096, 0x92c20b12
+0,      68608,      68608,     1024,     4096, 0xae10cd6f
+0,      69632,      69632,     1024,     4096, 0x4c8fd6fb
+0,      70656,      70656,     1024,     4096, 0xfbffeb71
+0,      71680,      71680,     1024,     4096, 0xed641b28
+0,      72704,      72704,     1024,     4096, 0x35eef925
+0,      73728,      73728,     1024,     4096, 0xe098d85d
+0,      74752,      74752,     1024,     4096, 0x8d03f22b
+0,      75776,      75776,     1024,     4096, 0x00d7f5ed
+0,      76800,      76800,     1024,     4096, 0xb80917ce
+0,      77824,      77824,     1024,     4096, 0xc255fb89
+0,      78848,      78848,     1024,     4096, 0xfef9063c
+0,      79872,      79872,     1024,     4096, 0x7286f151
+0,      80896,      80896,     1024,     4096, 0x24c8ee71
+0,      81920,      81920,     1024,     4096, 0xcf5f169a
+0,      82944,      82944,     1024,     4096, 0xb2fa1b5c
+0,      83968,      83968,     1024,     4096, 0xddfaf895
+0,      84992,      84992,     1024,     4096, 0xfe170e94
+0,      86016,      86016,     1024,     4096, 0x27d21960
+0,      87040,      87040,     1024,     4096, 0x8edd09c6
+0,      88064,      88064,     1024,     4096, 0x7c2f0074
+0,      89088,      89088,     1024,     4096, 0xaa9dfa4b
+0,      90112,      90112,     1024,     4096, 0xd543db09
+0,      91136,      91136,     1024,     4096, 0x25c0c7a9
+0,      92160,      92160,     1024,     4096, 0xccf5ac8f
+0,      93184,      93184,     1024,     4096, 0x131fdf1b
+0,      94208,      94208,     1024,     4096, 0xeb3ff7eb
+0,      95232,      95232,     1024,     4096, 0xf6d50958
+0,      96256,      96256,     1024,     4096, 0xdd3bfea5
+0,      97280,      97280,     1024,     4096, 0x6ad02eba
+0,      98304,      98304,     1024,     4096, 0x30c3de97
+0,      99328,      99328,     1024,     4096, 0xc78b1b02
+0,     100352,     100352,     1024,     4096, 0x017014e8
+0,     101376,     101376,     1024,     4096, 0x2c90ff59
+0,     102400,     102400,     1024,     4096, 0x88f71eb2
+0,     103424,     103424,     1024,     4096, 0xeed806e0
+0,     104448,     104448,     1024,     4096, 0x478df91b
+0,     105472,     105472,     1024,     4096, 0xc278f18b
+0,     106496,     106496,     1024,     4096, 0xc457cb7f
+0,     107520,     107520,     1024,     4096, 0x87a6081a
+0,     108544,     108544,     1024,     4096, 0xef15075c
+0,     109568,     109568,     1024,     4096, 0x5f4f076e
+0,     110592,     110592,     1024,     4096, 0x8463f2bb
+0,     111616,     111616,     1024,     4096, 0x5ca6f869
+0,     112640,     112640,     1024,     4096, 0x099a0398
+0,     113664,     113664,     1024,     4096, 0xa7fa10f0
+0,     114688,     114688,     1024,     4096, 0x28caddd3
+0,     115712,     115712,     1024,     4096, 0x4852ef8b
+0,     116736,     116736,     1024,     4096, 0x0250ee7b
+0,     117760,     117760,     1024,     4096, 0x9583da21
+0,     118784,     118784,     1024,     4096, 0x7365fb33
+0,     119808,     119808,     1024,     4096, 0x28c82066
+0,     120832,     120832,     1024,     4096, 0x94650be4
+0,     121856,     121856,     1024,     4096, 0xeb21f8eb
+0,     122880,     122880,     1024,     4096, 0xcd88f455
+0,     123904,     123904,     1024,     4096, 0x66a9efaf
+0,     124928,     124928,     1024,     4096, 0x5500c6ed
+0,     125952,     125952,     1024,     4096, 0x0ee0c62d
+0,     126976,     126976,     1024,     4096, 0x34d30762
+0,     128000,     128000,     1024,     4096, 0x8c0dec9f
+0,     129024,     129024,     1024,     4096, 0x790011d8
+0,     130048,     130048,     1024,     4096, 0xb76a1136
+0,     131072,     131072,     1024,     4096, 0x7dddfea7
+0,     132096,     132096,     1024,     4096, 0xdfa3ed49
+0,     133120,     133120,     1024,     4096, 0xc129f54e
+0,     134144,     134144,     1024,     4096, 0x9a86f077
+0,     135168,     135168,     1024,     4096, 0xc9eef209
+0,     136192,     136192,     1024,     4096, 0x72d4029b
+0,     137216,     137216,     1024,     4096, 0x8ec20590
+0,     138240,     138240,     1024,     4096, 0xd48f18ed
+0,     139264,     139264,     1024,     4096, 0xd807eadc
+0,     140288,     140288,     1024,     4096, 0x1e2bea09
+0,     141312,     141312,     1024,     4096, 0x937af12e
+0,     142336,     142336,     1024,     4096, 0xdedbf303
+0,     143360,     143360,     1024,     4096, 0xdc75df88
+0,     144384,     144384,     1024,     4096, 0x1845ffd6
+0,     145408,     145408,     1024,     4096, 0x20e8150c
+0,     146432,     146432,     1024,     4096, 0x5ea7eeef
+0,     147456,     147456,     1024,     4096, 0x4c7efa21
+0,     148480,     148480,     1024,     4096, 0x8b97e30e
+0,     149504,     149504,     1024,     4096, 0xe5040228
+0,     150528,     150528,     1024,     4096, 0x6283f78c
+0,     151552,     151552,     1024,     4096, 0xe7100140
+0,     152576,     152576,     1024,     4096, 0x9ea6f9b2
+0,     153600,     153600,     1024,     4096, 0x5f0e1563
+0,     154624,     154624,     1024,     4096, 0x510bf18e
+0,     155648,     155648,     1024,     4096, 0x5f4fe425
+0,     156672,     156672,     1024,     4096, 0x507af3c0
+0,     157696,     157696,     1024,     4096, 0xbf14ddc6
+0,     158720,     158720,     1024,     4096, 0x1871ed69
+0,     159744,     159744,     1024,     4096, 0xc349ef9f
+0,     160768,     160768,     1024,     4096, 0x4e2c1834
+0,     161792,     161792,     1024,     4096, 0x2383fe04
+0,     162816,     162816,     1024,     4096, 0x6626f415
+0,     163840,     163840,     1024,     4096, 0x283be379
+0,     164864,     164864,     1024,     4096, 0xc76c0ceb
+0,     165888,     165888,     1024,     4096, 0xa0b8040f
+0,     166912,     166912,     1024,     4096, 0x2535eb6d
+0,     167936,     167936,     1024,     4096, 0xeb180bb5
+0,     168960,     168960,     1024,     4096, 0xbc5cf059
+0,     169984,     169984,     1024,     4096, 0x1862f1ac
+0,     171008,     171008,     1024,     4096, 0x9cc2ea2b
+0,     172032,     172032,     1024,     4096, 0xbb9ae754
+0,     173056,     173056,     1024,     4096, 0x716debb5
+0,     174080,     174080,     1024,     4096, 0xff3aff2a
+0,     175104,     175104,     1024,     4096, 0x755dfa5c
+0,     176128,     176128,     1024,     4096, 0x3b830605
+0,     177152,     177152,     1024,     4096, 0x0030dc9e
+0,     178176,     178176,     1024,     4096, 0xb017fd54
+0,     179200,     179200,     1024,     4096, 0x5c7dfa2e
+0,     180224,     180224,     1024,     4096, 0x7887e599
+0,     181248,     181248,     1024,     4096, 0xb730e72f
+0,     182272,     182272,     1024,     4096, 0x6bb3fae4
+0,     183296,     183296,     1024,     4096, 0xcc08fc36
+0,     184320,     184320,     1024,     4096, 0x5afd9ec2
+0,     185344,     185344,     1024,     4096, 0xa1d3e83d
+0,     186368,     186368,     1024,     4096, 0x7f96013c
+0,     187392,     187392,     1024,     4096, 0x7a0afe31
+0,     188416,     188416,     1024,     4096, 0xa37d1701
+0,     189440,     189440,     1024,     4096, 0x4615ebc2
+0,     190464,     190464,     1024,     4096, 0x217005c1
+0,     191488,     191488,     1024,     4096, 0x1755f789
+0,     192512,     192512,     1024,     4096, 0x83e6db65
+0,     193536,     193536,     1024,     4096, 0x92ab1447
+0,     194560,     194560,     1024,     4096, 0xedbdf383
+0,     195584,     195584,     1024,     4096, 0x4316f6a9
+0,     196608,     196608,     1024,     4096, 0x1a6a0b4c
+0,     197632,     197632,     1024,     4096, 0xdfd809b7
+0,     198656,     198656,     1024,     4096, 0x1d2cf5f1
+0,     199680,     199680,     1024,     4096, 0xd366f4a1
+0,     200704,     200704,     1024,     4096, 0x6a2f86e0
+0,     201728,     201728,     1024,     4096, 0xf51f08a9
+0,     202752,     202752,     1024,     4096, 0x05edefa8
+0,     203776,     203776,     1024,     4096, 0x255df2a6
+0,     204800,     204800,     1024,     4096, 0xe881d9e4
+0,     205824,     205824,     1024,     4096, 0x50380523
+0,     206848,     206848,     1024,     4096, 0x8b93eb26
+0,     207872,     207872,     1024,     4096, 0x759cf94c
+0,     208896,     208896,     1024,     4096, 0x8474f591
+0,     209920,     209920,     1024,     4096, 0x0030dc9e
+0,     210944,     210944,     1024,     4096, 0xb017fd54
+0,     211968,     211968,     1024,     4096, 0x5c7dfa2e
+0,     212992,     212992,     1024,     4096, 0x7887e599
+0,     214016,     214016,     1024,     4096, 0xb730e72f
+0,     215040,     215040,     1024,     4096, 0x6bb3fae4
+0,     216064,     216064,     1024,     4096, 0xcc08fc36
+0,     217088,     217088,     1024,     4096, 0x5afd9ec2
+0,     218112,     218112,     1024,     4096, 0xa1d3e83d
+0,     219136,     219136,     1024,     4096, 0x7f96013c
+0,     220160,     220160,     1024,     4096, 0x7a0afe31
+0,     221184,     221184,     1024,     4096, 0xa37d1701
+0,     222208,     222208,     1024,     4096, 0x4615ebc2
+0,     223232,     223232,     1024,     4096, 0x217005c1
+0,     224256,     224256,     1024,     4096, 0x1755f789
+0,     225280,     225280,     1024,     4096, 0x83e6db65
+0,     226304,     226304,     1024,     4096, 0x92ab1447
+0,     227328,     227328,     1024,     4096, 0xedbdf383
+0,     228352,     228352,     1024,     4096, 0x4316f6a9
+0,     229376,     229376,     1024,     4096, 0x1a6a0b4c
+0,     230400,     230400,     1024,     4096, 0xdfd809b7
+0,     231424,     231424,     1024,     4096, 0x1d2cf5f1
+0,     232448,     232448,     1024,     4096, 0xd366f4a1
+0,     233472,     233472,     1024,     4096, 0x6a2f86e0
+0,     234496,     234496,     1024,     4096, 0xf51f08a9
+0,     235520,     235520,     1024,     4096, 0x05edefa8
+0,     236544,     236544,     1024,     4096, 0x255df2a6
+0,     237568,     237568,     1024,     4096, 0xe881d9e4
+0,     238592,     238592,     1024,     4096, 0x50380523
+0,     239616,     239616,     1024,     4096, 0x8b93eb26
+0,     240640,     240640,     1024,     4096, 0x759cf94c
+0,     241664,     241664,     1024,     4096, 0x8474f591
+0,     242688,     242688,     1024,     4096, 0x0030dc9e
+0,     243712,     243712,     1024,     4096, 0xb017fd54
+0,     244736,     244736,     1024,     4096, 0x5c7dfa2e
+0,     245760,     245760,     1024,     4096, 0x7887e599
+0,     246784,     246784,     1024,     4096, 0xb730e72f
+0,     247808,     247808,     1024,     4096, 0x6bb3fae4
+0,     248832,     248832,     1024,     4096, 0xcc08fc36
+0,     249856,     249856,     1024,     4096, 0x5afd9ec2
+0,     250880,     250880,     1024,     4096, 0xa1d3e83d
+0,     251904,     251904,     1024,     4096, 0x7f96013c
+0,     252928,     252928,     1024,     4096, 0x7a0afe31
+0,     253952,     253952,     1024,     4096, 0xa37d1701
+0,     254976,     254976,     1024,     4096, 0x4615ebc2
+0,     256000,     256000,     1024,     4096, 0x217005c1
+0,     257024,     257024,     1024,     4096, 0x1755f789
+0,     258048,     258048,     1024,     4096, 0x83e6db65
+0,     259072,     259072,     1024,     4096, 0x92ab1447
+0,     260096,     260096,     1024,     4096, 0xedbdf383
+0,     261120,     261120,     1024,     4096, 0x4316f6a9
+0,     262144,     262144,     1024,     4096, 0x1a6a0b4c
+0,     263168,     263168,     1024,     4096, 0xdfd809b7
+0,     264192,     264192,      408,     1632, 0xf412313e
diff --git a/tests/ref/fate/filter-afade-qsin b/tests/ref/fate/filter-afade-qsin
new file mode 100644
index 0000000..a6586b1
--- /dev/null
+++ b/tests/ref/fate/filter-afade-qsin
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0xd977ce0f
+0,       1024,       1024,     1024,     4096, 0x9333f5b1
+0,       2048,       2048,     1024,     4096, 0xf1a30794
+0,       3072,       3072,     1024,     4096, 0xbfb1f7af
+0,       4096,       4096,     1024,     4096, 0x9c0be73f
+0,       5120,       5120,     1024,     4096, 0xe77af231
+0,       6144,       6144,     1024,     4096, 0x60ae0600
+0,       7168,       7168,     1024,     4096, 0x7ecff8d1
+0,       8192,       8192,     1024,     4096, 0xa1a1ec0f
+0,       9216,       9216,     1024,     4096, 0x26f2e4eb
+0,      10240,      10240,     1024,     4096, 0x875d01bc
+0,      11264,      11264,     1024,     4096, 0x56a5edef
+0,      12288,      12288,     1024,     4096, 0xdadeff81
+0,      13312,      13312,     1024,     4096, 0x2198efe7
+0,      14336,      14336,     1024,     4096, 0x6666f8e3
+0,      15360,      15360,     1024,     4096, 0xbc1702e4
+0,      16384,      16384,     1024,     4096, 0x3e32fa1f
+0,      17408,      17408,     1024,     4096, 0x36eff5c7
+0,      18432,      18432,     1024,     4096, 0xda75ec39
+0,      19456,      19456,     1024,     4096, 0x3aeef987
+0,      20480,      20480,     1024,     4096, 0x311f0090
+0,      21504,      21504,     1024,     4096, 0xf40002ae
+0,      22528,      22528,     1024,     4096, 0x390ef101
+0,      23552,      23552,     1024,     4096, 0x1599ff6b
+0,      24576,      24576,     1024,     4096, 0xcd54edef
+0,      25600,      25600,     1024,     4096, 0x0c991178
+0,      26624,      26624,     1024,     4096, 0x7e69f3db
+0,      27648,      27648,     1024,     4096, 0x1c72f871
+0,      28672,      28672,     1024,     4096, 0xb51af385
+0,      29696,      29696,     1024,     4096, 0xc8cb0038
+0,      30720,      30720,     1024,     4096, 0xc3760a10
+0,      31744,      31744,     1024,     4096, 0x77baef51
+0,      32768,      32768,     1024,     4096, 0x0f9cec85
+0,      33792,      33792,     1024,     4096, 0xf78ff8a3
+0,      34816,      34816,     1024,     4096, 0x5a550f7c
+0,      35840,      35840,     1024,     4096, 0x522eef61
+0,      36864,      36864,     1024,     4096, 0x8738e879
+0,      37888,      37888,     1024,     4096, 0x6accf54f
+0,      38912,      38912,     1024,     4096, 0x1ceef2d3
+0,      39936,      39936,     1024,     4096, 0xacd3e885
+0,      40960,      40960,     1024,     4096, 0xed18e503
+0,      41984,      41984,     1024,     4096, 0xa5c5f85d
+0,      43008,      43008,     1024,     4096, 0x4f75049e
+0,      44032,      44032,     1024,     4096, 0xe017e021
+0,      45056,      45056,     1024,     4096, 0xe52e0580
+0,      46080,      46080,     1024,     4096, 0x101613ba
+0,      47104,      47104,     1024,     4096, 0x131eebef
+0,      48128,      48128,     1024,     4096, 0x97f3e1ef
+0,      49152,      49152,     1024,     4096, 0xb6d0ed0b
+0,      50176,      50176,     1024,     4096, 0x524b0300
+0,      51200,      51200,     1024,     4096, 0xdd39c011
+0,      52224,      52224,     1024,     4096, 0xd7ff1126
+0,      53248,      53248,     1024,     4096, 0x6019ed21
+0,      54272,      54272,     1024,     4096, 0x771f1a84
+0,      55296,      55296,     1024,     4096, 0x1a5ef595
+0,      56320,      56320,     1024,     4096, 0x9c53eb6b
+0,      57344,      57344,     1024,     4096, 0x0a95f2e5
+0,      58368,      58368,     1024,     4096, 0x6c631296
+0,      59392,      59392,     1024,     4096, 0xb6a0fbeb
+0,      60416,      60416,     1024,     4096, 0x34bbf835
+0,      61440,      61440,     1024,     4096, 0x7536f37f
+0,      62464,      62464,     1024,     4096, 0xaeac02a0
+0,      63488,      63488,     1024,     4096, 0xfc5cd7c5
+0,      64512,      64512,     1024,     4096, 0x0427ea85
+0,      65536,      65536,     1024,     4096, 0x207003a6
+0,      66560,      66560,     1024,     4096, 0x339ef8c7
+0,      67584,      67584,     1024,     4096, 0x6839f2a9
+0,      68608,      68608,     1024,     4096, 0xc7630330
+0,      69632,      69632,     1024,     4096, 0xd2570b4e
+0,      70656,      70656,     1024,     4096, 0xa2a5e381
+0,      71680,      71680,     1024,     4096, 0xbe941104
+0,      72704,      72704,     1024,     4096, 0x5feef0eb
+0,      73728,      73728,     1024,     4096, 0x9513ead5
+0,      74752,      74752,     1024,     4096, 0x045aeb69
+0,      75776,      75776,     1024,     4096, 0xed6f1042
+0,      76800,      76800,     1024,     4096, 0xd79604a2
+0,      77824,      77824,     1024,     4096, 0xb37dedb3
+0,      78848,      78848,     1024,     4096, 0x666bfa95
+0,      79872,      79872,     1024,     4096, 0x53b10308
+0,      80896,      80896,     1024,     4096, 0xae09fbb7
+0,      81920,      81920,     1024,     4096, 0xba852b80
+0,      82944,      82944,     1024,     4096, 0x76fe2bb2
+0,      83968,      83968,     1024,     4096, 0x2d5fff49
+0,      84992,      84992,     1024,     4096, 0x40dc0136
+0,      86016,      86016,     1024,     4096, 0x483e0522
+0,      87040,      87040,     1024,     4096, 0x756e1596
+0,      88064,      88064,     1024,     4096, 0x1b1ac8b7
+0,      89088,      89088,     1024,     4096, 0xe68dda8f
+0,      90112,      90112,     1024,     4096, 0xe457b505
+0,      91136,      91136,     1024,     4096, 0xda25a409
+0,      92160,      92160,     1024,     4096, 0x5b5d9d3b
+0,      93184,      93184,     1024,     4096, 0xa61eb13d
+0,      94208,      94208,     1024,     4096, 0xac93b66f
+0,      95232,      95232,     1024,     4096, 0xc7aeb33f
+0,      96256,      96256,     1024,     4096, 0x52cccfb5
+0,      97280,      97280,     1024,     4096, 0x4e4cf487
+0,      98304,      98304,     1024,     4096, 0x19c07f35
+0,      99328,      99328,     1024,     4096, 0x63ecd34f
+0,     100352,     100352,     1024,     4096, 0x122aec53
+0,     101376,     101376,     1024,     4096, 0x6581c0ad
+0,     102400,     102400,     1024,     4096, 0x640edb15
+0,     103424,     103424,     1024,     4096, 0x5d66c66f
+0,     104448,     104448,     1024,     4096, 0x069e9d35
+0,     105472,     105472,     1024,     4096, 0x5c9fd0e9
+0,     106496,     106496,     1024,     4096, 0x72468667
+0,     107520,     107520,     1024,     4096, 0x6e6dd02b
+0,     108544,     108544,     1024,     4096, 0x93edce33
+0,     109568,     109568,     1024,     4096, 0xcdfbd519
+0,     110592,     110592,     1024,     4096, 0x8463f2bb
+0,     111616,     111616,     1024,     4096, 0x5ca6f869
+0,     112640,     112640,     1024,     4096, 0x099a0398
+0,     113664,     113664,     1024,     4096, 0xa7fa10f0
+0,     114688,     114688,     1024,     4096, 0x28caddd3
+0,     115712,     115712,     1024,     4096, 0x4852ef8b
+0,     116736,     116736,     1024,     4096, 0x0250ee7b
+0,     117760,     117760,     1024,     4096, 0x9583da21
+0,     118784,     118784,     1024,     4096, 0x7365fb33
+0,     119808,     119808,     1024,     4096, 0x28c82066
+0,     120832,     120832,     1024,     4096, 0x94650be4
+0,     121856,     121856,     1024,     4096, 0xeb21f8eb
+0,     122880,     122880,     1024,     4096, 0xcd88f455
+0,     123904,     123904,     1024,     4096, 0x66a9efaf
+0,     124928,     124928,     1024,     4096, 0x5500c6ed
+0,     125952,     125952,     1024,     4096, 0x0ee0c62d
+0,     126976,     126976,     1024,     4096, 0x34d30762
+0,     128000,     128000,     1024,     4096, 0x8c0dec9f
+0,     129024,     129024,     1024,     4096, 0x790011d8
+0,     130048,     130048,     1024,     4096, 0xb76a1136
+0,     131072,     131072,     1024,     4096, 0x7dddfea7
+0,     132096,     132096,     1024,     4096, 0xdfa3ed49
+0,     133120,     133120,     1024,     4096, 0xc129f54e
+0,     134144,     134144,     1024,     4096, 0x9a86f077
+0,     135168,     135168,     1024,     4096, 0xc9eef209
+0,     136192,     136192,     1024,     4096, 0x72d4029b
+0,     137216,     137216,     1024,     4096, 0x8ec20590
+0,     138240,     138240,     1024,     4096, 0xd48f18ed
+0,     139264,     139264,     1024,     4096, 0xd807eadc
+0,     140288,     140288,     1024,     4096, 0x1e2bea09
+0,     141312,     141312,     1024,     4096, 0x937af12e
+0,     142336,     142336,     1024,     4096, 0xdedbf303
+0,     143360,     143360,     1024,     4096, 0xdc75df88
+0,     144384,     144384,     1024,     4096, 0x1845ffd6
+0,     145408,     145408,     1024,     4096, 0x20e8150c
+0,     146432,     146432,     1024,     4096, 0x5ea7eeef
+0,     147456,     147456,     1024,     4096, 0x4c7efa21
+0,     148480,     148480,     1024,     4096, 0x8b97e30e
+0,     149504,     149504,     1024,     4096, 0xe5040228
+0,     150528,     150528,     1024,     4096, 0x6283f78c
+0,     151552,     151552,     1024,     4096, 0xe7100140
+0,     152576,     152576,     1024,     4096, 0x9ea6f9b2
+0,     153600,     153600,     1024,     4096, 0x5f0e1563
+0,     154624,     154624,     1024,     4096, 0x510bf18e
+0,     155648,     155648,     1024,     4096, 0x5f4fe425
+0,     156672,     156672,     1024,     4096, 0x507af3c0
+0,     157696,     157696,     1024,     4096, 0xbf14ddc6
+0,     158720,     158720,     1024,     4096, 0x1871ed69
+0,     159744,     159744,     1024,     4096, 0xc349ef9f
+0,     160768,     160768,     1024,     4096, 0x4e2c1834
+0,     161792,     161792,     1024,     4096, 0x2383fe04
+0,     162816,     162816,     1024,     4096, 0x6626f415
+0,     163840,     163840,     1024,     4096, 0x283be379
+0,     164864,     164864,     1024,     4096, 0xc76c0ceb
+0,     165888,     165888,     1024,     4096, 0xa0b8040f
+0,     166912,     166912,     1024,     4096, 0x2535eb6d
+0,     167936,     167936,     1024,     4096, 0xeb180bb5
+0,     168960,     168960,     1024,     4096, 0xbc5cf059
+0,     169984,     169984,     1024,     4096, 0x1862f1ac
+0,     171008,     171008,     1024,     4096, 0x9cc2ea2b
+0,     172032,     172032,     1024,     4096, 0xbb9ae754
+0,     173056,     173056,     1024,     4096, 0x716debb5
+0,     174080,     174080,     1024,     4096, 0xff3aff2a
+0,     175104,     175104,     1024,     4096, 0x755dfa5c
+0,     176128,     176128,     1024,     4096, 0x3b830605
+0,     177152,     177152,     1024,     4096, 0x0030dc9e
+0,     178176,     178176,     1024,     4096, 0xb017fd54
+0,     179200,     179200,     1024,     4096, 0x5c7dfa2e
+0,     180224,     180224,     1024,     4096, 0x7887e599
+0,     181248,     181248,     1024,     4096, 0xb730e72f
+0,     182272,     182272,     1024,     4096, 0x6bb3fae4
+0,     183296,     183296,     1024,     4096, 0xcc08fc36
+0,     184320,     184320,     1024,     4096, 0x5afd9ec2
+0,     185344,     185344,     1024,     4096, 0xa1d3e83d
+0,     186368,     186368,     1024,     4096, 0x7f96013c
+0,     187392,     187392,     1024,     4096, 0x7a0afe31
+0,     188416,     188416,     1024,     4096, 0xa37d1701
+0,     189440,     189440,     1024,     4096, 0x4615ebc2
+0,     190464,     190464,     1024,     4096, 0x217005c1
+0,     191488,     191488,     1024,     4096, 0x1755f789
+0,     192512,     192512,     1024,     4096, 0x83e6db65
+0,     193536,     193536,     1024,     4096, 0x92ab1447
+0,     194560,     194560,     1024,     4096, 0xedbdf383
+0,     195584,     195584,     1024,     4096, 0x4316f6a9
+0,     196608,     196608,     1024,     4096, 0x1a6a0b4c
+0,     197632,     197632,     1024,     4096, 0xdfd809b7
+0,     198656,     198656,     1024,     4096, 0x1d2cf5f1
+0,     199680,     199680,     1024,     4096, 0xd366f4a1
+0,     200704,     200704,     1024,     4096, 0x6a2f86e0
+0,     201728,     201728,     1024,     4096, 0xf51f08a9
+0,     202752,     202752,     1024,     4096, 0x05edefa8
+0,     203776,     203776,     1024,     4096, 0x255df2a6
+0,     204800,     204800,     1024,     4096, 0xe881d9e4
+0,     205824,     205824,     1024,     4096, 0x50380523
+0,     206848,     206848,     1024,     4096, 0x8b93eb26
+0,     207872,     207872,     1024,     4096, 0x759cf94c
+0,     208896,     208896,     1024,     4096, 0x8474f591
+0,     209920,     209920,     1024,     4096, 0x0030dc9e
+0,     210944,     210944,     1024,     4096, 0xb017fd54
+0,     211968,     211968,     1024,     4096, 0x5c7dfa2e
+0,     212992,     212992,     1024,     4096, 0x7887e599
+0,     214016,     214016,     1024,     4096, 0xb730e72f
+0,     215040,     215040,     1024,     4096, 0x6bb3fae4
+0,     216064,     216064,     1024,     4096, 0xcc08fc36
+0,     217088,     217088,     1024,     4096, 0x5afd9ec2
+0,     218112,     218112,     1024,     4096, 0xa1d3e83d
+0,     219136,     219136,     1024,     4096, 0x7f96013c
+0,     220160,     220160,     1024,     4096, 0x7a0afe31
+0,     221184,     221184,     1024,     4096, 0xa37d1701
+0,     222208,     222208,     1024,     4096, 0x4615ebc2
+0,     223232,     223232,     1024,     4096, 0x217005c1
+0,     224256,     224256,     1024,     4096, 0x1755f789
+0,     225280,     225280,     1024,     4096, 0x83e6db65
+0,     226304,     226304,     1024,     4096, 0x92ab1447
+0,     227328,     227328,     1024,     4096, 0xedbdf383
+0,     228352,     228352,     1024,     4096, 0x4316f6a9
+0,     229376,     229376,     1024,     4096, 0x1a6a0b4c
+0,     230400,     230400,     1024,     4096, 0xdfd809b7
+0,     231424,     231424,     1024,     4096, 0x1d2cf5f1
+0,     232448,     232448,     1024,     4096, 0xd366f4a1
+0,     233472,     233472,     1024,     4096, 0x6a2f86e0
+0,     234496,     234496,     1024,     4096, 0xf51f08a9
+0,     235520,     235520,     1024,     4096, 0x05edefa8
+0,     236544,     236544,     1024,     4096, 0x255df2a6
+0,     237568,     237568,     1024,     4096, 0xe881d9e4
+0,     238592,     238592,     1024,     4096, 0x50380523
+0,     239616,     239616,     1024,     4096, 0x8b93eb26
+0,     240640,     240640,     1024,     4096, 0x759cf94c
+0,     241664,     241664,     1024,     4096, 0x8474f591
+0,     242688,     242688,     1024,     4096, 0x0030dc9e
+0,     243712,     243712,     1024,     4096, 0xb017fd54
+0,     244736,     244736,     1024,     4096, 0x5c7dfa2e
+0,     245760,     245760,     1024,     4096, 0x7887e599
+0,     246784,     246784,     1024,     4096, 0xb730e72f
+0,     247808,     247808,     1024,     4096, 0x6bb3fae4
+0,     248832,     248832,     1024,     4096, 0xcc08fc36
+0,     249856,     249856,     1024,     4096, 0x5afd9ec2
+0,     250880,     250880,     1024,     4096, 0xa1d3e83d
+0,     251904,     251904,     1024,     4096, 0x7f96013c
+0,     252928,     252928,     1024,     4096, 0x7a0afe31
+0,     253952,     253952,     1024,     4096, 0xa37d1701
+0,     254976,     254976,     1024,     4096, 0x4615ebc2
+0,     256000,     256000,     1024,     4096, 0x217005c1
+0,     257024,     257024,     1024,     4096, 0x1755f789
+0,     258048,     258048,     1024,     4096, 0x83e6db65
+0,     259072,     259072,     1024,     4096, 0x92ab1447
+0,     260096,     260096,     1024,     4096, 0xedbdf383
+0,     261120,     261120,     1024,     4096, 0x4316f6a9
+0,     262144,     262144,     1024,     4096, 0x1a6a0b4c
+0,     263168,     263168,     1024,     4096, 0xdfd809b7
+0,     264192,     264192,      408,     1632, 0xf412313e
diff --git a/tests/ref/fate/filter-agate b/tests/ref/fate/filter-agate
new file mode 100644
index 0000000..4f7b10e
--- /dev/null
+++ b/tests/ref/fate/filter-agate
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0x1af20090
+0,       1024,       1024,     1024,     4096, 0x0b05ef2d
+0,       2048,       2048,     1024,     4096, 0x574bf11d
+0,       3072,       3072,     1024,     4096, 0x774af5d3
+0,       4096,       4096,     1024,     4096, 0x7b51ff33
+0,       5120,       5120,     1024,     4096, 0xf610f9bf
+0,       6144,       6144,     1024,     4096, 0x3c20ef79
+0,       7168,       7168,     1024,     4096, 0x427bef59
+0,       8192,       8192,     1024,     4096, 0x8773fa99
+0,       9216,       9216,     1024,     4096, 0xbf1dfe89
+0,      10240,      10240,     1024,     4096, 0x462df4dd
+0,      11264,      11264,     1024,     4096, 0x1170f169
+0,      12288,      12288,     1024,     4096, 0xcb9cf633
+0,      13312,      13312,     1024,     4096, 0x7e8c01da
+0,      14336,      14336,     1024,     4096, 0x93c202d0
+0,      15360,      15360,     1024,     4096, 0xd882ec6d
+0,      16384,      16384,     1024,     4096, 0x03fbec6d
+0,      17408,      17408,     1024,     4096, 0x73f400d4
+0,      18432,      18432,     1024,     4096, 0xea8c01da
+0,      19456,      19456,     1024,     4096, 0x23cbf82f
+0,      20480,      20480,     1024,     4096, 0x85cdf169
+0,      21504,      21504,     1024,     4096, 0x8e27f2e1
+0,      22528,      22528,     1024,     4096, 0x91bffe89
+0,      23552,      23552,     1024,     4096, 0xc31afd95
+0,      24576,      24576,     1024,     4096, 0x5c23ee59
+0,      25600,      25600,     1024,     4096, 0x58d0ef79
+0,      26624,      26624,     1024,     4096, 0xfccff7c3
+0,      27648,      27648,     1024,     4096, 0x7084ff33
+0,      28672,      28672,     1024,     4096, 0x7f1bf7cf
+0,      29696,      29696,     1024,     4096, 0x8037f11d
+0,      30720,      30720,     1024,     4096, 0xd106ed31
+0,      31744,      31744,     1024,     4096, 0xaf820090
+0,      32768,      32768,     1024,     4096, 0x1af20090
+0,      33792,      33792,     1024,     4096, 0x0b05ef2d
+0,      34816,      34816,     1024,     4096, 0x574bf11d
+0,      35840,      35840,     1024,     4096, 0x774af5d3
+0,      36864,      36864,     1024,     4096, 0x7b51ff33
+0,      37888,      37888,     1024,     4096, 0xf610f9bf
+0,      38912,      38912,     1024,     4096, 0x3c20ef79
+0,      39936,      39936,     1024,     4096, 0x427bef59
+0,      40960,      40960,     1024,     4096, 0x8773fa99
+0,      41984,      41984,     1024,     4096, 0xbf1dfe89
+0,      43008,      43008,     1024,     4096, 0x462df4dd
+0,      44032,      44032,     1024,     4096, 0x41650472
+0,      45056,      45056,     1024,     4096, 0x1081f133
+0,      46080,      46080,     1024,     4096, 0x9da3e58b
+0,      47104,      47104,     1024,     4096, 0x752614ac
+0,      48128,      48128,     1024,     4096, 0x0f23034c
+0,      49152,      49152,     1024,     4096, 0x768fe8a1
+0,      50176,      50176,     1024,     4096, 0xf0f9079e
+0,      51200,      51200,     1024,     4096, 0x8543ed93
+0,      52224,      52224,     1024,     4096, 0x9f96fe9d
+0,      53248,      53248,     1024,     4096, 0x94f3facf
+0,      54272,      54272,     1024,     4096, 0xc0defe4d
+0,      55296,      55296,     1024,     4096, 0x4e22f5ff
+0,      56320,      56320,     1024,     4096, 0xb604ed7d
+0,      57344,      57344,     1024,     4096, 0xb6400124
+0,      58368,      58368,     1024,     4096, 0xadadf519
+0,      59392,      59392,     1024,     4096, 0x2520fb85
+0,      60416,      60416,     1024,     4096, 0x1ffbf4a9
+0,      61440,      61440,     1024,     4096, 0x380e05cc
+0,      62464,      62464,     1024,     4096, 0x366af6cf
+0,      63488,      63488,     1024,     4096, 0x4f64f355
+0,      64512,      64512,     1024,     4096, 0x7aa0e89f
+0,      65536,      65536,     1024,     4096, 0x1f160524
+0,      66560,      66560,     1024,     4096, 0x6bba0292
+0,      67584,      67584,     1024,     4096, 0x5243ed4d
+0,      68608,      68608,     1024,     4096, 0x304ffcb1
+0,      69632,      69632,     1024,     4096, 0xfb1bfc9b
+0,      70656,      70656,     1024,     4096, 0x0259e9d3
+0,      71680,      71680,     1024,     4096, 0x90fee749
+0,      72704,      72704,     1024,     4096, 0x8626eff9
+0,      73728,      73728,     1024,     4096, 0x29a4fe41
+0,      74752,      74752,     1024,     4096, 0x0dacf2bb
+0,      75776,      75776,     1024,     4096, 0x875b0046
+0,      76800,      76800,     1024,     4096, 0x009b0068
+0,      77824,      77824,     1024,     4096, 0x50f8eee1
+0,      78848,      78848,     1024,     4096, 0xa73ef503
+0,      79872,      79872,     1024,     4096, 0xaac8f7e5
+0,      80896,      80896,     1024,     4096, 0x0229f31b
+0,      81920,      81920,     1024,     4096, 0x7eb0edc9
+0,      82944,      82944,     1024,     4096, 0x88e0eddd
+0,      83968,      83968,     1024,     4096, 0x7982fe3f
+0,      84992,      84992,     1024,     4096, 0x91caf665
+0,      86016,      86016,     1024,     4096, 0x2fd1f3d7
+0,      87040,      87040,     1024,     4096, 0x9b3de465
+0,      88064,      88064,     1024,     4096, 0xd3f5e99d
+0,      89088,      89088,     1024,     4096, 0xeb00b4df
+0,      90112,      90112,     1024,     4096, 0xc0a5e92f
+0,      91136,      91136,     1024,     4096, 0xaed2ef59
+0,      92160,      92160,     1024,     4096, 0x80591586
+0,      93184,      93184,     1024,     4096, 0x32d4f0ef
+0,      94208,      94208,     1024,     4096, 0x8ba4f0f9
+0,      95232,      95232,     1024,     4096, 0x8d3bc631
+0,      96256,      96256,     1024,     4096, 0xddede7c5
+0,      97280,      97280,     1024,     4096, 0x6a459463
+0,      98304,      98304,     1024,     4096, 0xeca818b8
+0,      99328,      99328,     1024,     4096, 0x0c91c6c9
+0,     100352,     100352,     1024,     4096, 0x6241e69b
+0,     101376,     101376,     1024,     4096, 0xe220d9a7
+0,     102400,     102400,     1024,     4096, 0x9f4bcbd5
+0,     103424,     103424,     1024,     4096, 0x2c1ad90b
+0,     104448,     104448,     1024,     4096, 0x3974feb3
+0,     105472,     105472,     1024,     4096, 0x8d1ae2e1
+0,     106496,     106496,     1024,     4096, 0xa609f955
+0,     107520,     107520,     1024,     4096, 0xc5fcdd19
+0,     108544,     108544,     1024,     4096, 0xe233d8c5
+0,     109568,     109568,     1024,     4096, 0xd1d7d61d
+0,     110592,     110592,     1024,     4096, 0x52522f58
+0,     111616,     111616,     1024,     4096, 0x16d8cd63
+0,     112640,     112640,     1024,     4096, 0x3994e847
+0,     113664,     113664,     1024,     4096, 0x6fd8ea07
+0,     114688,     114688,     1024,     4096, 0x582723be
+0,     115712,     115712,     1024,     4096, 0x44d40ff6
+0,     116736,     116736,     1024,     4096, 0x98d22050
+0,     117760,     117760,     1024,     4096, 0x2cc8063c
+0,     118784,     118784,     1024,     4096, 0xf645ed8d
+0,     119808,     119808,     1024,     4096, 0xcb49dbe1
+0,     120832,     120832,     1024,     4096, 0x7efbf369
+0,     121856,     121856,     1024,     4096, 0x797333ac
+0,     122880,     122880,     1024,     4096, 0x157130fa
+0,     123904,     123904,     1024,     4096, 0x23530594
+0,     124928,     124928,     1024,     4096, 0x46783b6c
+0,     125952,     125952,     1024,     4096, 0x5fac436e
+0,     126976,     126976,     1024,     4096, 0x2a9e1c76
+0,     128000,     128000,     1024,     4096, 0x152202ac
+0,     129024,     129024,     1024,     4096, 0xe5cdf369
+0,     130048,     130048,     1024,     4096, 0x6fe2feeb
+0,     131072,     131072,     1024,     4096, 0xee24ec7f
+0,     132096,     132096,     1024,     4096, 0x6f33fd5d
+0,     133120,     133120,     1024,     4096, 0x3f52fd51
+0,     134144,     134144,     1024,     4096, 0x2292e8e6
+0,     135168,     135168,     1024,     4096, 0xbc13f7bb
+0,     136192,     136192,     1024,     4096, 0xc271f708
+0,     137216,     137216,     1024,     4096, 0x9f1ff6ec
+0,     138240,     138240,     1024,     4096, 0xdf88f599
+0,     139264,     139264,     1024,     4096, 0x6614f6ae
+0,     140288,     140288,     1024,     4096, 0x7cf9f3c4
+0,     141312,     141312,     1024,     4096, 0xcdc1f588
+0,     142336,     142336,     1024,     4096, 0xa4a1ffa9
+0,     143360,     143360,     1024,     4096, 0xcb15f5d4
+0,     144384,     144384,     1024,     4096, 0x2fd0f58f
+0,     145408,     145408,     1024,     4096, 0x08eff948
+0,     146432,     146432,     1024,     4096, 0x71f9f39f
+0,     147456,     147456,     1024,     4096, 0x70f5f4ed
+0,     148480,     148480,     1024,     4096, 0x3ccaf424
+0,     149504,     149504,     1024,     4096, 0xc170f215
+0,     150528,     150528,     1024,     4096, 0xdecfeb38
+0,     151552,     151552,     1024,     4096, 0xb7a6f0e5
+0,     152576,     152576,     1024,     4096, 0x14ecf42d
+0,     153600,     153600,     1024,     4096, 0x3af8eefc
+0,     154624,     154624,     1024,     4096, 0xec57fa8b
+0,     155648,     155648,     1024,     4096, 0x206bf602
+0,     156672,     156672,     1024,     4096, 0x15a7f45d
+0,     157696,     157696,     1024,     4096, 0xb23dea6e
+0,     158720,     158720,     1024,     4096, 0x6b6af81c
+0,     159744,     159744,     1024,     4096, 0xae73f6c7
+0,     160768,     160768,     1024,     4096, 0x19c8f293
+0,     161792,     161792,     1024,     4096, 0x752ef8aa
+0,     162816,     162816,     1024,     4096, 0xfac6f812
+0,     163840,     163840,     1024,     4096, 0xff9dfb00
+0,     164864,     164864,     1024,     4096, 0x8305f5b2
+0,     165888,     165888,     1024,     4096, 0xe2f3fea4
+0,     166912,     166912,     1024,     4096, 0xb377f0e6
+0,     167936,     167936,     1024,     4096, 0x0344f0a9
+0,     168960,     168960,     1024,     4096, 0x389afaf4
+0,     169984,     169984,     1024,     4096, 0x5f63fa0d
+0,     171008,     171008,     1024,     4096, 0xce88f5ae
+0,     172032,     172032,     1024,     4096, 0x7e55f852
+0,     173056,     173056,     1024,     4096, 0x5af0f555
+0,     174080,     174080,     1024,     4096, 0x5753fa5a
+0,     175104,     175104,     1024,     4096, 0x443ce89b
+0,     176128,     176128,     1024,     4096, 0x0068de8c
+0,     177152,     177152,     1024,     4096, 0x5209f51f
+0,     178176,     178176,     1024,     4096, 0x97e8eb3a
+0,     179200,     179200,     1024,     4096, 0xd97fe978
+0,     180224,     180224,     1024,     4096, 0x8cadff37
+0,     181248,     181248,     1024,     4096, 0x8dd40290
+0,     182272,     182272,     1024,     4096, 0x2369eb74
+0,     183296,     183296,     1024,     4096, 0x50e8e9ee
+0,     184320,     184320,     1024,     4096, 0x1e727c22
+0,     185344,     185344,     1024,     4096, 0xbe8be7ed
+0,     186368,     186368,     1024,     4096, 0xb6f0f37a
+0,     187392,     187392,     1024,     4096, 0x8a9af2a2
+0,     188416,     188416,     1024,     4096, 0x6917f395
+0,     189440,     189440,     1024,     4096, 0x649df5b4
+0,     190464,     190464,     1024,     4096, 0xebb7fc9a
+0,     191488,     191488,     1024,     4096, 0xba3eef09
+0,     192512,     192512,     1024,     4096, 0x0cf9ba5e
+0,     193536,     193536,     1024,     4096, 0x0f83eb2d
+0,     194560,     194560,     1024,     4096, 0xcd86f62c
+0,     195584,     195584,     1024,     4096, 0x1f6d05b6
+0,     196608,     196608,     1024,     4096, 0x988ff2ed
+0,     197632,     197632,     1024,     4096, 0xe066eb10
+0,     198656,     198656,     1024,     4096, 0x608be99e
+0,     199680,     199680,     1024,     4096, 0xba97e994
+0,     200704,     200704,     1024,     4096, 0xe92a8b76
+0,     201728,     201728,     1024,     4096, 0xe12ee0e2
+0,     202752,     202752,     1024,     4096, 0xc202ef7d
+0,     203776,     203776,     1024,     4096, 0xcd8afebb
+0,     204800,     204800,     1024,     4096, 0x0fc2fcbf
+0,     205824,     205824,     1024,     4096, 0x2d4df1bb
+0,     206848,     206848,     1024,     4096, 0x7282ee1f
+0,     207872,     207872,     1024,     4096, 0xaa4ee359
+0,     208896,     208896,     1024,     4096, 0x10c0deb1
+0,     209920,     209920,     1024,     4096, 0x5209f51f
+0,     210944,     210944,     1024,     4096, 0x97e8eb3a
+0,     211968,     211968,     1024,     4096, 0xd97fe978
+0,     212992,     212992,     1024,     4096, 0x8cadff37
+0,     214016,     214016,     1024,     4096, 0x8dd40290
+0,     215040,     215040,     1024,     4096, 0x2369eb74
+0,     216064,     216064,     1024,     4096, 0x50e8e9ee
+0,     217088,     217088,     1024,     4096, 0x1e727c22
+0,     218112,     218112,     1024,     4096, 0xbe8be7ed
+0,     219136,     219136,     1024,     4096, 0xb6f0f37a
+0,     220160,     220160,     1024,     4096, 0x8a9af2a2
+0,     221184,     221184,     1024,     4096, 0x6917f395
+0,     222208,     222208,     1024,     4096, 0x649df5b4
+0,     223232,     223232,     1024,     4096, 0xebb7fc9a
+0,     224256,     224256,     1024,     4096, 0xba3eef09
+0,     225280,     225280,     1024,     4096, 0x0cf9ba5e
+0,     226304,     226304,     1024,     4096, 0x0f83eb2d
+0,     227328,     227328,     1024,     4096, 0xcd86f62c
+0,     228352,     228352,     1024,     4096, 0x1f6d05b6
+0,     229376,     229376,     1024,     4096, 0x988ff2ed
+0,     230400,     230400,     1024,     4096, 0xe066eb10
+0,     231424,     231424,     1024,     4096, 0x608be99e
+0,     232448,     232448,     1024,     4096, 0xba97e994
+0,     233472,     233472,     1024,     4096, 0xe92a8b76
+0,     234496,     234496,     1024,     4096, 0xe12ee0e2
+0,     235520,     235520,     1024,     4096, 0xc202ef7d
+0,     236544,     236544,     1024,     4096, 0xcd8afebb
+0,     237568,     237568,     1024,     4096, 0x0fc2fcbf
+0,     238592,     238592,     1024,     4096, 0x2d4df1bb
+0,     239616,     239616,     1024,     4096, 0x7282ee1f
+0,     240640,     240640,     1024,     4096, 0xaa4ee359
+0,     241664,     241664,     1024,     4096, 0x10c0deb1
+0,     242688,     242688,     1024,     4096, 0x5209f51f
+0,     243712,     243712,     1024,     4096, 0x97e8eb3a
+0,     244736,     244736,     1024,     4096, 0xd97fe978
+0,     245760,     245760,     1024,     4096, 0x8cadff37
+0,     246784,     246784,     1024,     4096, 0x8dd40290
+0,     247808,     247808,     1024,     4096, 0x2369eb74
+0,     248832,     248832,     1024,     4096, 0x50e8e9ee
+0,     249856,     249856,     1024,     4096, 0x1e727c22
+0,     250880,     250880,     1024,     4096, 0xbe8be7ed
+0,     251904,     251904,     1024,     4096, 0xb6f0f37a
+0,     252928,     252928,     1024,     4096, 0x8a9af2a2
+0,     253952,     253952,     1024,     4096, 0x6917f395
+0,     254976,     254976,     1024,     4096, 0x649df5b4
+0,     256000,     256000,     1024,     4096, 0xebb7fc9a
+0,     257024,     257024,     1024,     4096, 0xba3eef09
+0,     258048,     258048,     1024,     4096, 0x0cf9ba5e
+0,     259072,     259072,     1024,     4096, 0x0f83eb2d
+0,     260096,     260096,     1024,     4096, 0xcd86f62c
+0,     261120,     261120,     1024,     4096, 0x1f6d05b6
+0,     262144,     262144,     1024,     4096, 0x988ff2ed
+0,     263168,     263168,     1024,     4096, 0xe066eb10
+0,     264192,     264192,      408,     1632, 0xe00c26bc
diff --git a/tests/ref/fate/filter-alimiter b/tests/ref/fate/filter-alimiter
new file mode 100644
index 0000000..06e23f1
--- /dev/null
+++ b/tests/ref/fate/filter-alimiter
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0xd4194af4
+0,       1024,       1024,     1024,     4096, 0x686af4ab
+0,       2048,       2048,     1024,     4096, 0xe80cee61
+0,       3072,       3072,     1024,     4096, 0xa686fbad
+0,       4096,       4096,     1024,     4096, 0x191e062c
+0,       5120,       5120,     1024,     4096, 0x1a13edb1
+0,       6144,       6144,     1024,     4096, 0xab21f8ef
+0,       7168,       7168,     1024,     4096, 0xaa30e757
+0,       8192,       8192,     1024,     4096, 0x5afdf69f
+0,       9216,       9216,     1024,     4096, 0x765e05ec
+0,      10240,      10240,     1024,     4096, 0x6484f551
+0,      11264,      11264,     1024,     4096, 0x61b9e9f7
+0,      12288,      12288,     1024,     4096, 0xa735feb3
+0,      13312,      13312,     1024,     4096, 0xb47203aa
+0,      14336,      14336,     1024,     4096, 0xb6b5fbf5
+0,      15360,      15360,     1024,     4096, 0xbc66f14f
+0,      16384,      16384,     1024,     4096, 0x2003ff5b
+0,      17408,      17408,     1024,     4096, 0x1160f17d
+0,      18432,      18432,     1024,     4096, 0x308001a4
+0,      19456,      19456,     1024,     4096, 0x9df9f429
+0,      20480,      20480,     1024,     4096, 0x3e6eec0f
+0,      21504,      21504,     1024,     4096, 0xca3301f2
+0,      22528,      22528,     1024,     4096, 0x9eb1f961
+0,      23552,      23552,     1024,     4096, 0xd0a50c8c
+0,      24576,      24576,     1024,     4096, 0x071ee96b
+0,      25600,      25600,     1024,     4096, 0x7a46f05b
+0,      26624,      26624,     1024,     4096, 0x2cb2f475
+0,      27648,      27648,     1024,     4096, 0x5bda0a52
+0,      28672,      28672,     1024,     4096, 0x33c0f727
+0,      29696,      29696,     1024,     4096, 0x53cfee59
+0,      30720,      30720,     1024,     4096, 0x1588f221
+0,      31744,      31744,     1024,     4096, 0x95d400d6
+0,      32768,      32768,     1024,     4096, 0x0078009a
+0,      33792,      33792,     1024,     4096, 0x686af4ab
+0,      34816,      34816,     1024,     4096, 0xe80cee61
+0,      35840,      35840,     1024,     4096, 0xa686fbad
+0,      36864,      36864,     1024,     4096, 0x191e062c
+0,      37888,      37888,     1024,     4096, 0x1a13edb1
+0,      38912,      38912,     1024,     4096, 0xab21f8ef
+0,      39936,      39936,     1024,     4096, 0xaa30e757
+0,      40960,      40960,     1024,     4096, 0x5afdf69f
+0,      41984,      41984,     1024,     4096, 0x765e05ec
+0,      43008,      43008,     1024,     4096, 0x6484f551
+0,      44032,      44032,     1024,     4096, 0x755e0600
+0,      45056,      45056,     1024,     4096, 0x5056ecb9
+0,      46080,      46080,     1024,     4096, 0xdcb609a8
+0,      47104,      47104,     1024,     4096, 0xc87bf4a1
+0,      48128,      48128,     1024,     4096, 0xecdfef95
+0,      49152,      49152,     1024,     4096, 0x905ff13f
+0,      50176,      50176,     1024,     4096, 0x4e69eeb3
+0,      51200,      51200,     1024,     4096, 0x16e1082c
+0,      52224,      52224,     1024,     4096, 0x606c0a22
+0,      53248,      53248,     1024,     4096, 0x9f94f351
+0,      54272,      54272,     1024,     4096, 0x2c47f63f
+0,      55296,      55296,     1024,     4096, 0x9e14ebf9
+0,      56320,      56320,     1024,     4096, 0x7804fbcb
+0,      57344,      57344,     1024,     4096, 0xc7c6ffb7
+0,      58368,      58368,     1024,     4096, 0xa547f68d
+0,      59392,      59392,     1024,     4096, 0x0c87fed7
+0,      60416,      60416,     1024,     4096, 0x88b5fef1
+0,      61440,      61440,     1024,     4096, 0x325af00d
+0,      62464,      62464,     1024,     4096, 0xd826edd9
+0,      63488,      63488,     1024,     4096, 0x1fbe1138
+0,      64512,      64512,     1024,     4096, 0xdf85da7b
+0,      65536,      65536,     1024,     4096, 0xf987f9b3
+0,      66560,      66560,     1024,     4096, 0x5df5e12f
+0,      67584,      67584,     1024,     4096, 0x259cf8ef
+0,      68608,      68608,     1024,     4096, 0xa191eb4f
+0,      69632,      69632,     1024,     4096, 0xfe5bf1fd
+0,      70656,      70656,     1024,     4096, 0x7675e2cb
+0,      71680,      71680,     1024,     4096, 0x796a2f90
+0,      72704,      72704,     1024,     4096, 0xaa52e7a5
+0,      73728,      73728,     1024,     4096, 0x2b56fd81
+0,      74752,      74752,     1024,     4096, 0xbf7c02ee
+0,      75776,      75776,     1024,     4096, 0xfe4cebb1
+0,      76800,      76800,     1024,     4096, 0xe5b7fdf7
+0,      77824,      77824,     1024,     4096, 0xd271ece7
+0,      78848,      78848,     1024,     4096, 0x96e0f69f
+0,      79872,      79872,     1024,     4096, 0x6e5eef33
+0,      80896,      80896,     1024,     4096, 0x78b70b6e
+0,      81920,      81920,     1024,     4096, 0x61f2f075
+0,      82944,      82944,     1024,     4096, 0xf1dc47dc
+0,      83968,      83968,     1024,     4096, 0xf4b406d2
+0,      84992,      84992,     1024,     4096, 0xe33806fe
+0,      86016,      86016,     1024,     4096, 0x5b5ef087
+0,      87040,      87040,     1024,     4096, 0x3fa207da
+0,      88064,      88064,     1024,     4096, 0x4719f201
+0,      89088,      89088,     1024,     4096, 0x641feaad
+0,      90112,      90112,     1024,     4096, 0x905402ec
+0,      91136,      91136,     1024,     4096, 0xf529e11f
+0,      92160,      92160,     1024,     4096, 0x65a41838
+0,      93184,      93184,     1024,     4096, 0x651efb6f
+0,      94208,      94208,     1024,     4096, 0x251b1390
+0,      95232,      95232,     1024,     4096, 0x45ea05a8
+0,      96256,      96256,     1024,     4096, 0xe65be141
+0,      97280,      97280,     1024,     4096, 0xd452d3dd
+0,      98304,      98304,     1024,     4096, 0x3bdff821
+0,      99328,      99328,     1024,     4096, 0x74da00e6
+0,     100352,     100352,     1024,     4096, 0x4474fa19
+0,     101376,     101376,     1024,     4096, 0x11ddedef
+0,     102400,     102400,     1024,     4096, 0xf027d72b
+0,     103424,     103424,     1024,     4096, 0xaa0a1ce6
+0,     104448,     104448,     1024,     4096, 0x7168145e
+0,     105472,     105472,     1024,     4096, 0x94a710a4
+0,     106496,     106496,     1024,     4096, 0x6f55ecf1
+0,     107520,     107520,     1024,     4096, 0xc12de6d7
+0,     108544,     108544,     1024,     4096, 0x8ff7db15
+0,     109568,     109568,     1024,     4096, 0x366d0cc6
+0,     110592,     110592,     1024,     4096, 0xb04afa4f
+0,     111616,     111616,     1024,     4096, 0xf6abbee7
+0,     112640,     112640,     1024,     4096, 0xbe9910dc
+0,     113664,     113664,     1024,     4096, 0x96c3047e
+0,     114688,     114688,     1024,     4096, 0x9dc1e8e1
+0,     115712,     115712,     1024,     4096, 0x4b2c1092
+0,     116736,     116736,     1024,     4096, 0x592d212c
+0,     117760,     117760,     1024,     4096, 0x5c3bda15
+0,     118784,     118784,     1024,     4096, 0x43c8e90f
+0,     119808,     119808,     1024,     4096, 0x3bfa074e
+0,     120832,     120832,     1024,     4096, 0xa2d7d443
+0,     121856,     121856,     1024,     4096, 0xd4b02844
+0,     122880,     122880,     1024,     4096, 0x9f5d2a92
+0,     123904,     123904,     1024,     4096, 0xc19bf69d
+0,     124928,     124928,     1024,     4096, 0x47b8fe75
+0,     125952,     125952,     1024,     4096, 0x337334b0
+0,     126976,     126976,     1024,     4096, 0x96ed14f0
+0,     128000,     128000,     1024,     4096, 0x9af0f67b
+0,     129024,     129024,     1024,     4096, 0xdf541a60
+0,     130048,     130048,     1024,     4096, 0x684f0c06
+0,     131072,     131072,     1024,     4096, 0xe3d0015e
+0,     132096,     132096,     1024,     4096, 0xf648d73c
+0,     133120,     133120,     1024,     4096, 0x4041f3ee
+0,     134144,     134144,     1024,     4096, 0x1421025f
+0,     135168,     135168,     1024,     4096, 0x4eb5fc97
+0,     136192,     136192,     1024,     4096, 0x510f02fe
+0,     137216,     137216,     1024,     4096, 0x85e9e95e
+0,     138240,     138240,     1024,     4096, 0xb1d0fe10
+0,     139264,     139264,     1024,     4096, 0xda66f5f8
+0,     140288,     140288,     1024,     4096, 0x3826eaa8
+0,     141312,     141312,     1024,     4096, 0xa7cc0176
+0,     142336,     142336,     1024,     4096, 0x71e8fe5a
+0,     143360,     143360,     1024,     4096, 0x0149fcfa
+0,     144384,     144384,     1024,     4096, 0xbd36fd8e
+0,     145408,     145408,     1024,     4096, 0xec1afcc6
+0,     146432,     146432,     1024,     4096, 0xea80ec5e
+0,     147456,     147456,     1024,     4096, 0x8da1f0ac
+0,     148480,     148480,     1024,     4096, 0x63c3e61c
+0,     149504,     149504,     1024,     4096, 0x188cf09b
+0,     150528,     150528,     1024,     4096, 0x7eebea85
+0,     151552,     151552,     1024,     4096, 0x7ef6f718
+0,     152576,     152576,     1024,     4096, 0xcd9fecfb
+0,     153600,     153600,     1024,     4096, 0x1aa7f624
+0,     154624,     154624,     1024,     4096, 0xcab5f1e3
+0,     155648,     155648,     1024,     4096, 0x36e9f795
+0,     156672,     156672,     1024,     4096, 0x952cf54d
+0,     157696,     157696,     1024,     4096, 0x54a4ed3b
+0,     158720,     158720,     1024,     4096, 0x1e24f992
+0,     159744,     159744,     1024,     4096, 0xab6bfa09
+0,     160768,     160768,     1024,     4096, 0xa021020b
+0,     161792,     161792,     1024,     4096, 0xaa0600f5
+0,     162816,     162816,     1024,     4096, 0xadf7ec92
+0,     163840,     163840,     1024,     4096, 0x5dd5f63f
+0,     164864,     164864,     1024,     4096, 0xc01bff89
+0,     165888,     165888,     1024,     4096, 0x05dbf1e7
+0,     166912,     166912,     1024,     4096, 0x44f00038
+0,     167936,     167936,     1024,     4096, 0x6dc5f886
+0,     168960,     168960,     1024,     4096, 0xeb88e729
+0,     169984,     169984,     1024,     4096, 0xfe5cf53e
+0,     171008,     171008,     1024,     4096, 0x2692f7a0
+0,     172032,     172032,     1024,     4096, 0xe984f24b
+0,     173056,     173056,     1024,     4096, 0x1a4ef732
+0,     174080,     174080,     1024,     4096, 0x3b60010b
+0,     175104,     175104,     1024,     4096, 0x6dd0eaf2
+0,     176128,     176128,     1024,     4096, 0x313de851
+0,     177152,     177152,     1024,     4096, 0x239ef043
+0,     178176,     178176,     1024,     4096, 0x2366fe43
+0,     179200,     179200,     1024,     4096, 0xbfd6f3b9
+0,     180224,     180224,     1024,     4096, 0xb34bf67b
+0,     181248,     181248,     1024,     4096, 0x00def7c1
+0,     182272,     182272,     1024,     4096, 0xa6d0f466
+0,     183296,     183296,     1024,     4096, 0xd1a1f1c2
+0,     184320,     184320,     1024,     4096, 0x32f8923c
+0,     185344,     185344,     1024,     4096, 0x137001d2
+0,     186368,     186368,     1024,     4096, 0xb881f6cd
+0,     187392,     187392,     1024,     4096, 0xf44e034a
+0,     188416,     188416,     1024,     4096, 0xb43fecf7
+0,     189440,     189440,     1024,     4096, 0xe62ced50
+0,     190464,     190464,     1024,     4096, 0x221dfd0d
+0,     191488,     191488,     1024,     4096, 0x85400147
+0,     192512,     192512,     1024,     4096, 0x8bf8d054
+0,     193536,     193536,     1024,     4096, 0x08370170
+0,     194560,     194560,     1024,     4096, 0xec62effa
+0,     195584,     195584,     1024,     4096, 0xd58cf67c
+0,     196608,     196608,     1024,     4096, 0xf597f9a1
+0,     197632,     197632,     1024,     4096, 0x63fcf0b0
+0,     198656,     198656,     1024,     4096, 0x8cc8fd32
+0,     199680,     199680,     1024,     4096, 0xf8c2072c
+0,     200704,     200704,     1024,     4096, 0x0c7e93a5
+0,     201728,     201728,     1024,     4096, 0x1cc3f612
+0,     202752,     202752,     1024,     4096, 0x83adf8ee
+0,     203776,     203776,     1024,     4096, 0x680e0195
+0,     204800,     204800,     1024,     4096, 0x9d34fd2e
+0,     205824,     205824,     1024,     4096, 0x44cdfb34
+0,     206848,     206848,     1024,     4096, 0x193df790
+0,     207872,     207872,     1024,     4096, 0xb337ef64
+0,     208896,     208896,     1024,     4096, 0x0074ee38
+0,     209920,     209920,     1024,     4096, 0x239ef043
+0,     210944,     210944,     1024,     4096, 0x2366fe43
+0,     211968,     211968,     1024,     4096, 0xbfd6f3b9
+0,     212992,     212992,     1024,     4096, 0xb34bf67b
+0,     214016,     214016,     1024,     4096, 0x00def7c1
+0,     215040,     215040,     1024,     4096, 0xa6d0f466
+0,     216064,     216064,     1024,     4096, 0xd1a1f1c2
+0,     217088,     217088,     1024,     4096, 0x32f8923c
+0,     218112,     218112,     1024,     4096, 0x137001d2
+0,     219136,     219136,     1024,     4096, 0xb881f6cd
+0,     220160,     220160,     1024,     4096, 0xf44e034a
+0,     221184,     221184,     1024,     4096, 0xb43fecf7
+0,     222208,     222208,     1024,     4096, 0xe62ced50
+0,     223232,     223232,     1024,     4096, 0x221dfd0d
+0,     224256,     224256,     1024,     4096, 0x85400147
+0,     225280,     225280,     1024,     4096, 0x8bf8d054
+0,     226304,     226304,     1024,     4096, 0x08370170
+0,     227328,     227328,     1024,     4096, 0xec62effa
+0,     228352,     228352,     1024,     4096, 0xd58cf67c
+0,     229376,     229376,     1024,     4096, 0xf597f9a1
+0,     230400,     230400,     1024,     4096, 0x63fcf0b0
+0,     231424,     231424,     1024,     4096, 0x8cc8fd32
+0,     232448,     232448,     1024,     4096, 0xf8c2072c
+0,     233472,     233472,     1024,     4096, 0x0c7e93a5
+0,     234496,     234496,     1024,     4096, 0x1cc3f612
+0,     235520,     235520,     1024,     4096, 0x83adf8ee
+0,     236544,     236544,     1024,     4096, 0x680e0195
+0,     237568,     237568,     1024,     4096, 0x9d34fd2e
+0,     238592,     238592,     1024,     4096, 0x44cdfb34
+0,     239616,     239616,     1024,     4096, 0x193df790
+0,     240640,     240640,     1024,     4096, 0xb337ef64
+0,     241664,     241664,     1024,     4096, 0x0074ee38
+0,     242688,     242688,     1024,     4096, 0x239ef043
+0,     243712,     243712,     1024,     4096, 0x2366fe43
+0,     244736,     244736,     1024,     4096, 0xbfd6f3b9
+0,     245760,     245760,     1024,     4096, 0xb34bf67b
+0,     246784,     246784,     1024,     4096, 0x00def7c1
+0,     247808,     247808,     1024,     4096, 0xa6d0f466
+0,     248832,     248832,     1024,     4096, 0xd1a1f1c2
+0,     249856,     249856,     1024,     4096, 0x32f8923c
+0,     250880,     250880,     1024,     4096, 0x137001d2
+0,     251904,     251904,     1024,     4096, 0xb881f6cd
+0,     252928,     252928,     1024,     4096, 0xf44e034a
+0,     253952,     253952,     1024,     4096, 0xb43fecf7
+0,     254976,     254976,     1024,     4096, 0xe62ced50
+0,     256000,     256000,     1024,     4096, 0x221dfd0d
+0,     257024,     257024,     1024,     4096, 0x85400147
+0,     258048,     258048,     1024,     4096, 0x8bf8d054
+0,     259072,     259072,     1024,     4096, 0x08370170
+0,     260096,     260096,     1024,     4096, 0xec62effa
+0,     261120,     261120,     1024,     4096, 0xd58cf67c
+0,     262144,     262144,     1024,     4096, 0xf597f9a1
+0,     263168,     263168,     1024,     4096, 0x63fcf0b0
+0,     264192,     264192,      408,     1632, 0xedfa314a
diff --git a/tests/ref/fate/filter-alphaextract_alphamerge_rgb b/tests/ref/fate/filter-alphaextract_alphamerge_rgb
index 1b1a48d..eac9971 100644
--- a/tests/ref/fate/filter-alphaextract_alphamerge_rgb
+++ b/tests/ref/fate/filter-alphaextract_alphamerge_rgb
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   405504, 0x6d5666c8
 0,          1,          1,        1,   405504, 0x4813ba17
 0,          2,          2,        1,   405504, 0x23880ee1
diff --git a/tests/ref/fate/filter-alphaextract_alphamerge_yuv b/tests/ref/fate/filter-alphaextract_alphamerge_yuv
index 37c3486..2cae357 100644
--- a/tests/ref/fate/filter-alphaextract_alphamerge_yuv
+++ b/tests/ref/fate/filter-alphaextract_alphamerge_yuv
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   253440, 0x1ada7ac4
 0,          1,          1,        1,   253440, 0x711c1599
 0,          2,          2,        1,   253440, 0x533017ea
diff --git a/tests/ref/fate/filter-amerge b/tests/ref/fate/filter-amerge
new file mode 100644
index 0000000..006383a
--- /dev/null
+++ b/tests/ref/fate/filter-amerge
@@ -0,0 +1,135 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     2048,     8192, 0x120efa65
+0,       2048,       2048,     2048,     8192, 0x7b3cebf7
+0,       4096,       4096,     2048,     8192, 0x0fb8ee01
+0,       6144,       6144,     2048,     8192, 0x47a9f271
+0,       8192,       8192,     2048,     8192, 0x47a8ed5b
+0,      10240,      10240,     2048,     8192, 0xdab6f33f
+0,      12288,      12288,     2048,     8192, 0xda4df7eb
+0,      14336,      14336,     2048,     8192, 0xc83ce449
+0,      16384,      16384,     2048,     8192, 0x4954e765
+0,      18432,      18432,     2048,     8192, 0x0214f5d5
+0,      20480,      20480,     2048,     8192, 0x2302f3c9
+0,      22528,      22528,     2048,     8192, 0x2b57ef5b
+0,      24576,      24576,     2048,     8192, 0xad22f075
+0,      26624,      26624,     2048,     8192, 0x9bd5ee8b
+0,      28672,      28672,     2048,     8192, 0x91a4e9e1
+0,      30720,      30720,     2048,     8192, 0x85a9fd7f
+0,      32768,      32768,     2048,     8192, 0x120efa65
+0,      34816,      34816,     2048,     8192, 0x7b3cebf7
+0,      36864,      36864,     2048,     8192, 0x0fb8ee01
+0,      38912,      38912,     2048,     8192, 0x47a9f271
+0,      40960,      40960,     2048,     8192, 0x47a8ed5b
+0,      43008,      43008,     2048,     8192, 0x76f7c64f
+0,      45056,      45056,     2048,     8192, 0xade0f6f5
+0,      47104,      47104,     2048,     8192, 0xcc1ce131
+0,      49152,      49152,     2048,     8192, 0x11aaf88b
+0,      51200,      51200,     2048,     8192, 0xcd50e409
+0,      53248,      53248,     2048,     8192, 0x7f72ee63
+0,      55296,      55296,     2048,     8192, 0xf7b4ff5d
+0,      57344,      57344,     2048,     8192, 0xd8bc4192
+0,      59392,      59392,     2048,     8192, 0xc8fb0418
+0,      61440,      61440,     2048,     8192, 0x0859cac9
+0,      63488,      63488,     2048,     8192, 0x7529f279
+0,      65536,      65536,     2048,     8192, 0x0ee0df7b
+0,      67584,      67584,     2048,     8192, 0x07edef6d
+0,      69632,      69632,     2048,     8192, 0x7d02ea45
+0,      71680,      71680,     2048,     8192, 0x770104a8
+0,      73728,      73728,     2048,     8192, 0x7124f553
+0,      75776,      75776,     2048,     8192, 0x6df6269a
+0,      77824,      77824,     2048,     8192, 0x4218002c
+0,      79872,      79872,     2048,     8192, 0x274fe03d
+0,      81920,      81920,     2048,     8192, 0xd00f5aae
+0,      83968,      83968,     2048,     8192, 0x907dfe51
+0,      86016,      86016,     2048,     8192, 0xc2c10ed2
+0,      88064,      88064,     2048,     8192, 0x293aa355
+0,      90112,      90112,     2048,     8192, 0xb84a591d
+0,      92160,      92160,     2048,     8192, 0x44f64e87
+0,      94208,      94208,     2048,     8192, 0x0f6869bd
+0,      96256,      96256,     2048,     8192, 0xb3dcc44b
+0,      98304,      98304,     2048,     8192, 0x44f85293
+0,     100352,     100352,     2048,     8192, 0x8545ad0f
+0,     102400,     102400,     2048,     8192, 0xdee2a193
+0,     104448,     104448,     2048,     8192, 0x46a96e2d
+0,     106496,     106496,     2048,     8192, 0xcebc56a1
+0,     108544,     108544,     2048,     8192, 0x5353a35b
+0,     110592,     110592,     2048,     8192, 0x74aceb33
+0,     112640,     112640,     2048,     8192, 0x34fa1488
+0,     114688,     114688,     2048,     8192, 0x711ecd6d
+0,     116736,     116736,     2048,     8192, 0x277ac8ab
+0,     118784,     118784,     2048,     8192, 0xb7b91ba8
+0,     120832,     120832,     2048,     8192, 0xcab704de
+0,     122880,     122880,     2048,     8192, 0x695ae413
+0,     124928,     124928,     2048,     8192, 0xee618d29
+0,     126976,     126976,     2048,     8192, 0xe7caf401
+0,     129024,     129024,     2048,     8192, 0xc12c230e
+0,     131072,     131072,     2048,     8192, 0x9124ec71
+0,     133120,     133120,     2048,     8192, 0xd2bad2f7
+0,     135168,     135168,     2048,     8192, 0x2fc6da33
+0,     137216,     137216,     2048,     8192, 0x66d92c28
+0,     139264,     139264,     2048,     8192, 0x3373ddfd
+0,     141312,     141312,     2048,     8192, 0x419ae325
+0,     143360,     143360,     2048,     8192, 0x6b5ad233
+0,     145408,     145408,     2048,     8192, 0xb62f11a0
+0,     147456,     147456,     2048,     8192, 0x7084c5ef
+0,     149504,     149504,     2048,     8192, 0x42c8f8bd
+0,     151552,     151552,     2048,     8192, 0xd0e2d5a3
+0,     153600,     153600,     2048,     8192, 0xcf8f0826
+0,     155648,     155648,     2048,     8192, 0x164cc963
+0,     157696,     157696,     2048,     8192, 0xb14db49f
+0,     159744,     159744,     2048,     8192, 0x0fe50df4
+0,     161792,     161792,     2048,     8192, 0x7669207a
+0,     163840,     163840,     2048,     8192, 0x2a16f23b
+0,     165888,     165888,     2048,     8192, 0xc629f685
+0,     167936,     167936,     2048,     8192, 0x79ee0298
+0,     169984,     169984,     2048,     8192, 0xf9bdf179
+0,     172032,     172032,     2048,     8192, 0x5220d047
+0,     174080,     174080,     2048,     8192, 0x915ae8b7
+0,     176128,     176128,     2048,     8192, 0x8c26e3af
+0,     178176,     178176,     2048,     8192, 0x72e5c661
+0,     180224,     180224,     2048,     8192, 0xfca2d795
+0,     182272,     182272,     2048,     8192, 0x6367f5a9
+0,     184320,     184320,     2048,     8192, 0x32f8d0d1
+0,     186368,     186368,     2048,     8192, 0x7a08c3c7
+0,     188416,     188416,     2048,     8192, 0xe2f0fb55
+0,     190464,     190464,     2048,     8192, 0x3fd706e8
+0,     192512,     192512,     2048,     8192, 0xf5845786
+0,     194560,     194560,     2048,     8192, 0x2a8fdcbd
+0,     196608,     196608,     2048,     8192, 0xa71f03fc
+0,     198656,     198656,     2048,     8192, 0xc1210dce
+0,     200704,     200704,     2048,     8192, 0x0cd21800
+0,     202752,     202752,     2048,     8192, 0x2e8cfb47
+0,     204800,     204800,     2048,     8192, 0x2ab816ec
+0,     206848,     206848,     2048,     8192, 0xc2b40256
+0,     208896,     208896,     2048,     8192, 0xf72d0018
+0,     210944,     210944,     2048,     8192, 0xc7e01b76
+0,     212992,     212992,     2048,     8192, 0xbcf50a48
+0,     215040,     215040,     2048,     8192, 0x1101ec23
+0,     217088,     217088,     2048,     8192, 0x066a1108
+0,     219136,     219136,     2048,     8192, 0xda831e12
+0,     221184,     221184,     2048,     8192, 0x92f9e677
+0,     223232,     223232,     2048,     8192, 0x3439daf3
+0,     225280,     225280,     2048,     8192, 0xf812694a
+0,     227328,     227328,     2048,     8192, 0x3751051e
+0,     229376,     229376,     2048,     8192, 0x9f4cdddd
+0,     231424,     231424,     2048,     8192, 0xae4ad40b
+0,     233472,     233472,     2048,     8192, 0x569ec9db
+0,     235520,     235520,     2048,     8192, 0x2056e683
+0,     237568,     237568,     2048,     8192, 0x84d8caef
+0,     239616,     239616,     2048,     8192, 0x9eefdf83
+0,     241664,     241664,     2048,     8192, 0x4feee1c1
+0,     243712,     243712,     2048,     8192, 0x72e5c661
+0,     245760,     245760,     2048,     8192, 0xfca2d795
+0,     247808,     247808,     2048,     8192, 0x6367f5a9
+0,     249856,     249856,     2048,     8192, 0x32f8d0d1
+0,     251904,     251904,     2048,     8192, 0x7a08c3c7
+0,     253952,     253952,     2048,     8192, 0xe2f0fb55
+0,     256000,     256000,     2048,     8192, 0x3fd706e8
+0,     258048,     258048,     2048,     8192, 0xf5845786
+0,     260096,     260096,     2048,     8192, 0x2a8fdcbd
+0,     262144,     262144,     2048,     8192, 0xa71f03fc
+0,     264192,     264192,      408,     1632, 0x53c44589
diff --git a/tests/ref/fate/filter-anequalizer b/tests/ref/fate/filter-anequalizer
new file mode 100644
index 0000000..21c7aaf
--- /dev/null
+++ b/tests/ref/fate/filter-anequalizer
@@ -0,0 +1,264 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0x8e1bf8e0
+0,       1024,       1024,     1024,     4096, 0xe315f564
+0,       2048,       2048,     1024,     4096, 0x3d0efa98
+0,       3072,       3072,     1024,     4096, 0x5c1bf6b2
+0,       4096,       4096,     1024,     4096, 0xb5b4ff02
+0,       5120,       5120,     1024,     4096, 0xb9b1f4b6
+0,       6144,       6144,     1024,     4096, 0x86e9f411
+0,       7168,       7168,     1024,     4096, 0x36aafbd3
+0,       8192,       8192,     1024,     4096, 0x05d2f63f
+0,       9216,       9216,     1024,     4096, 0x1d95fd16
+0,      10240,      10240,     1024,     4096, 0x4fb0f009
+0,      11264,      11264,     1024,     4096, 0x6a6301c6
+0,      12288,      12288,     1024,     4096, 0x299cfbd8
+0,      13312,      13312,     1024,     4096, 0x2a7ffe8c
+0,      14336,      14336,     1024,     4096, 0xceace509
+0,      15360,      15360,     1024,     4096, 0xd084feec
+0,      16384,      16384,     1024,     4096, 0xd956f613
+0,      17408,      17408,     1024,     4096, 0xf61dfa8c
+0,      18432,      18432,     1024,     4096, 0x6ebcf53e
+0,      19456,      19456,     1024,     4096, 0x8601f9f2
+0,      20480,      20480,     1024,     4096, 0x6a4bf2d9
+0,      21504,      21504,     1024,     4096, 0xb917fc1d
+0,      22528,      22528,     1024,     4096, 0x85cffbca
+0,      23552,      23552,     1024,     4096, 0x80d9f509
+0,      24576,      24576,     1024,     4096, 0xa4acf898
+0,      25600,      25600,     1024,     4096, 0x7614f3c0
+0,      26624,      26624,     1024,     4096, 0x5f3700dc
+0,      27648,      27648,     1024,     4096, 0x4308ef21
+0,      28672,      28672,     1024,     4096, 0x670df4fe
+0,      29696,      29696,     1024,     4096, 0x98d0f24f
+0,      30720,      30720,     1024,     4096, 0xed360be0
+0,      31744,      31744,     1024,     4096, 0xbe10f1eb
+0,      32768,      32768,     1024,     4096, 0xb5d0fac0
+0,      33792,      33792,     1024,     4096, 0x94c1f649
+0,      34816,      34816,     1024,     4096, 0x3617fb9b
+0,      35840,      35840,     1024,     4096, 0x1840f6e6
+0,      36864,      36864,     1024,     4096, 0x0ce8fdfa
+0,      37888,      37888,     1024,     4096, 0xd7c1f4b8
+0,      38912,      38912,     1024,     4096, 0x86e9f411
+0,      39936,      39936,     1024,     4096, 0x36aafbd3
+0,      40960,      40960,     1024,     4096, 0x05d2f63f
+0,      41984,      41984,     1024,     4096, 0x1d95fd16
+0,      43008,      43008,     1024,     4096, 0x4fb0f009
+0,      44032,      44032,     1024,     4096, 0xc6de743e
+0,      45056,      45056,     1024,     4096, 0xe878f6e3
+0,      46080,      46080,     1024,     4096, 0x40c3fdf9
+0,      47104,      47104,     1024,     4096, 0x19def744
+0,      48128,      48128,     1024,     4096, 0x9e3d0016
+0,      49152,      49152,     1024,     4096, 0x2d3bfaee
+0,      50176,      50176,     1024,     4096, 0x0ae800c8
+0,      51200,      51200,     1024,     4096, 0xd6530007
+0,      52224,      52224,     1024,     4096, 0x3ec6fa96
+0,      53248,      53248,     1024,     4096, 0x4f3df4c4
+0,      54272,      54272,     1024,     4096, 0x8584f574
+0,      55296,      55296,     1024,     4096, 0xaa2311e8
+0,      56320,      56320,     1024,     4096, 0xfc04ed39
+0,      57344,      57344,     1024,     4096, 0xdefc1dcf
+0,      58368,      58368,     1024,     4096, 0x26120297
+0,      59392,      59392,     1024,     4096, 0x12db0600
+0,      60416,      60416,     1024,     4096, 0x590cfb36
+0,      61440,      61440,     1024,     4096, 0x03d2e732
+0,      62464,      62464,     1024,     4096, 0xa0b1eecb
+0,      63488,      63488,     1024,     4096, 0x89e6f0f8
+0,      64512,      64512,     1024,     4096, 0x96c3fde6
+0,      65536,      65536,     1024,     4096, 0x5d3ef320
+0,      66560,      66560,     1024,     4096, 0x780beba1
+0,      67584,      67584,     1024,     4096, 0x8a6ef641
+0,      68608,      68608,     1024,     4096, 0x716df2d2
+0,      69632,      69632,     1024,     4096, 0xe02bf742
+0,      70656,      70656,     1024,     4096, 0x636f0676
+0,      71680,      71680,     1024,     4096, 0x211fef81
+0,      72704,      72704,     1024,     4096, 0x230d03c2
+0,      73728,      73728,     1024,     4096, 0x78c7ec7e
+0,      74752,      74752,     1024,     4096, 0x57aaf08e
+0,      75776,      75776,     1024,     4096, 0xf35c034e
+0,      76800,      76800,     1024,     4096, 0xa52120e1
+0,      77824,      77824,     1024,     4096, 0xcd0ffe7c
+0,      78848,      78848,     1024,     4096, 0x76a40264
+0,      79872,      79872,     1024,     4096, 0x3daae73c
+0,      80896,      80896,     1024,     4096, 0x02bfebb8
+0,      81920,      81920,     1024,     4096, 0x2fad0aef
+0,      82944,      82944,     1024,     4096, 0xaf3d1e35
+0,      83968,      83968,     1024,     4096, 0x1577f70b
+0,      84992,      84992,     1024,     4096, 0x7330ff44
+0,      86016,      86016,     1024,     4096, 0xfc10f794
+0,      87040,      87040,     1024,     4096, 0xf883ff53
+0,      88064,      88064,     1024,     4096, 0x4d91f664
+0,      89088,      89088,     1024,     4096, 0x7bbcf94a
+0,      90112,      90112,     1024,     4096, 0x5243da5a
+0,      91136,      91136,     1024,     4096, 0xc9f2b510
+0,      92160,      92160,     1024,     4096, 0xd45daee9
+0,      93184,      93184,     1024,     4096, 0xf040cbe7
+0,      94208,      94208,     1024,     4096, 0xc755db61
+0,      95232,      95232,     1024,     4096, 0x2a2bdb39
+0,      96256,      96256,     1024,     4096, 0xd180faf7
+0,      97280,      97280,     1024,     4096, 0xe05bf3b3
+0,      98304,      98304,     1024,     4096, 0xee84c6a1
+0,      99328,      99328,     1024,     4096, 0xb05ec71b
+0,     100352,     100352,     1024,     4096, 0xf788e856
+0,     101376,     101376,     1024,     4096, 0x884fe6b4
+0,     102400,     102400,     1024,     4096, 0xc474ef2f
+0,     103424,     103424,     1024,     4096, 0x8ea2e3e3
+0,     104448,     104448,     1024,     4096, 0x32e2ba03
+0,     105472,     105472,     1024,     4096, 0xde62e2be
+0,     106496,     106496,     1024,     4096, 0xd9c1a387
+0,     107520,     107520,     1024,     4096, 0xb923e9c8
+0,     108544,     108544,     1024,     4096, 0xe0e2ef73
+0,     109568,     109568,     1024,     4096, 0xdc66f037
+0,     110592,     110592,     1024,     4096, 0x4c5ddb65
+0,     111616,     111616,     1024,     4096, 0xddc5e6dc
+0,     112640,     112640,     1024,     4096, 0x2c2afa48
+0,     113664,     113664,     1024,     4096, 0xfe1cefab
+0,     114688,     114688,     1024,     4096, 0xa761d9b1
+0,     115712,     115712,     1024,     4096, 0xac1af519
+0,     116736,     116736,     1024,     4096, 0x1d3e0455
+0,     117760,     117760,     1024,     4096, 0xca8bdaec
+0,     118784,     118784,     1024,     4096, 0x1c890dd7
+0,     119808,     119808,     1024,     4096, 0xd01023ec
+0,     120832,     120832,     1024,     4096, 0xd608fa07
+0,     121856,     121856,     1024,     4096, 0xa01bdceb
+0,     122880,     122880,     1024,     4096, 0x5b6e0428
+0,     123904,     123904,     1024,     4096, 0x699bffc9
+0,     124928,     124928,     1024,     4096, 0x7200d6ea
+0,     125952,     125952,     1024,     4096, 0x60ece933
+0,     126976,     126976,     1024,     4096, 0x6d1305ad
+0,     128000,     128000,     1024,     4096, 0xf932e234
+0,     129024,     129024,     1024,     4096, 0xc88dfc53
+0,     130048,     130048,     1024,     4096, 0xecaafd32
+0,     131072,     131072,     1024,     4096, 0x4683eec4
+0,     132096,     132096,     1024,     4096, 0x01a40877
+0,     133120,     133120,     1024,     4096, 0x68affdb9
+0,     134144,     134144,     1024,     4096, 0x3d50049a
+0,     135168,     135168,     1024,     4096, 0x28c3e64a
+0,     136192,     136192,     1024,     4096, 0xe77eff83
+0,     137216,     137216,     1024,     4096, 0x778ef1d7
+0,     138240,     138240,     1024,     4096, 0x8632016c
+0,     139264,     139264,     1024,     4096, 0x113ff74d
+0,     140288,     140288,     1024,     4096, 0x8a410144
+0,     141312,     141312,     1024,     4096, 0xf1f8032c
+0,     142336,     142336,     1024,     4096, 0x4ea9f305
+0,     143360,     143360,     1024,     4096, 0x08beed52
+0,     144384,     144384,     1024,     4096, 0xe62e0599
+0,     145408,     145408,     1024,     4096, 0xabc1f9cb
+0,     146432,     146432,     1024,     4096, 0x0a3cf37c
+0,     147456,     147456,     1024,     4096, 0x9d84eaec
+0,     148480,     148480,     1024,     4096, 0x0ecafb82
+0,     149504,     149504,     1024,     4096, 0x3898f9f9
+0,     150528,     150528,     1024,     4096, 0xbe95f626
+0,     151552,     151552,     1024,     4096, 0x2bd01290
+0,     152576,     152576,     1024,     4096, 0xb3ccf9cc
+0,     153600,     153600,     1024,     4096, 0x1d6510a7
+0,     154624,     154624,     1024,     4096, 0xb758f5ec
+0,     155648,     155648,     1024,     4096, 0xe163f2f7
+0,     156672,     156672,     1024,     4096, 0x208cf625
+0,     157696,     157696,     1024,     4096, 0x0e7ee529
+0,     158720,     158720,     1024,     4096, 0x82fef772
+0,     159744,     159744,     1024,     4096, 0xbcadfd1a
+0,     160768,     160768,     1024,     4096, 0xb84914e1
+0,     161792,     161792,     1024,     4096, 0xae9de78e
+0,     162816,     162816,     1024,     4096, 0x17afdd4d
+0,     163840,     163840,     1024,     4096, 0x6f41e1ac
+0,     164864,     164864,     1024,     4096, 0x07b2019e
+0,     165888,     165888,     1024,     4096, 0x92a9f923
+0,     166912,     166912,     1024,     4096, 0xb284f10b
+0,     167936,     167936,     1024,     4096, 0x6a3ffa40
+0,     168960,     168960,     1024,     4096, 0xaee7e8bd
+0,     169984,     169984,     1024,     4096, 0xa409e2f3
+0,     171008,     171008,     1024,     4096, 0x26f3f5ff
+0,     172032,     172032,     1024,     4096, 0x1a89eca5
+0,     173056,     173056,     1024,     4096, 0x8a49f293
+0,     174080,     174080,     1024,     4096, 0x9d4506f7
+0,     175104,     175104,     1024,     4096, 0x0ca2f075
+0,     176128,     176128,     1024,     4096, 0x7beb063f
+0,     177152,     177152,     1024,     4096, 0xe2b1e8a0
+0,     178176,     178176,     1024,     4096, 0xcc77fbd0
+0,     179200,     179200,     1024,     4096, 0x7c93f956
+0,     180224,     180224,     1024,     4096, 0xdb28fb69
+0,     181248,     181248,     1024,     4096, 0xe49afc39
+0,     182272,     182272,     1024,     4096, 0x60e904b5
+0,     183296,     183296,     1024,     4096, 0xbb67ebbc
+0,     184320,     184320,     1024,     4096, 0xc1e4ca2b
+0,     185344,     185344,     1024,     4096, 0xdcb8e550
+0,     186368,     186368,     1024,     4096, 0xe70bfe5d
+0,     187392,     187392,     1024,     4096, 0x5da3f4d4
+0,     188416,     188416,     1024,     4096, 0xfe9f04f6
+0,     189440,     189440,     1024,     4096, 0xf960f3cd
+0,     190464,     190464,     1024,     4096, 0xe6b7fc42
+0,     191488,     191488,     1024,     4096, 0xb8b9f1e2
+0,     192512,     192512,     1024,     4096, 0x520dd814
+0,     193536,     193536,     1024,     4096, 0x00f30212
+0,     194560,     194560,     1024,     4096, 0x8298f610
+0,     195584,     195584,     1024,     4096, 0xf0d9f47f
+0,     196608,     196608,     1024,     4096, 0x5063f4c4
+0,     197632,     197632,     1024,     4096, 0x6910f4bf
+0,     198656,     198656,     1024,     4096, 0x8c27ec24
+0,     199680,     199680,     1024,     4096, 0xf803052a
+0,     200704,     200704,     1024,     4096, 0xe31b1507
+0,     201728,     201728,     1024,     4096, 0x0ca30bbf
+0,     202752,     202752,     1024,     4096, 0x2659f272
+0,     203776,     203776,     1024,     4096, 0x54c0fc05
+0,     204800,     204800,     1024,     4096, 0x7427ebec
+0,     205824,     205824,     1024,     4096, 0xb652fd0c
+0,     206848,     206848,     1024,     4096, 0xa6c9f494
+0,     207872,     207872,     1024,     4096, 0xd429fef3
+0,     208896,     208896,     1024,     4096, 0xbbd5f8e3
+0,     209920,     209920,     1024,     4096, 0x8b74eed4
+0,     210944,     210944,     1024,     4096, 0xf21cfac1
+0,     211968,     211968,     1024,     4096, 0x055efc5f
+0,     212992,     212992,     1024,     4096, 0x334efc0f
+0,     214016,     214016,     1024,     4096, 0x29e7fc16
+0,     215040,     215040,     1024,     4096, 0xf0f904c0
+0,     216064,     216064,     1024,     4096, 0xaec3ebbb
+0,     217088,     217088,     1024,     4096, 0xc1e4ca2b
+0,     218112,     218112,     1024,     4096, 0xdcb8e550
+0,     219136,     219136,     1024,     4096, 0xe70bfe5d
+0,     220160,     220160,     1024,     4096, 0x5da3f4d4
+0,     221184,     221184,     1024,     4096, 0xfe9f04f6
+0,     222208,     222208,     1024,     4096, 0xf960f3cd
+0,     223232,     223232,     1024,     4096, 0xe6b7fc42
+0,     224256,     224256,     1024,     4096, 0xb8b9f1e2
+0,     225280,     225280,     1024,     4096, 0x520dd814
+0,     226304,     226304,     1024,     4096, 0x00f30212
+0,     227328,     227328,     1024,     4096, 0x8298f610
+0,     228352,     228352,     1024,     4096, 0xf0d9f47f
+0,     229376,     229376,     1024,     4096, 0x5063f4c4
+0,     230400,     230400,     1024,     4096, 0x6910f4bf
+0,     231424,     231424,     1024,     4096, 0x8c27ec24
+0,     232448,     232448,     1024,     4096, 0xf803052a
+0,     233472,     233472,     1024,     4096, 0xe31b1507
+0,     234496,     234496,     1024,     4096, 0x0ca30bbf
+0,     235520,     235520,     1024,     4096, 0x2659f272
+0,     236544,     236544,     1024,     4096, 0x54c0fc05
+0,     237568,     237568,     1024,     4096, 0x7427ebec
+0,     238592,     238592,     1024,     4096, 0xb652fd0c
+0,     239616,     239616,     1024,     4096, 0xa6c9f494
+0,     240640,     240640,     1024,     4096, 0xd429fef3
+0,     241664,     241664,     1024,     4096, 0xbbd5f8e3
+0,     242688,     242688,     1024,     4096, 0x8b74eed4
+0,     243712,     243712,     1024,     4096, 0xf21cfac1
+0,     244736,     244736,     1024,     4096, 0x055efc5f
+0,     245760,     245760,     1024,     4096, 0x334efc0f
+0,     246784,     246784,     1024,     4096, 0x29e7fc16
+0,     247808,     247808,     1024,     4096, 0xf0f904c0
+0,     248832,     248832,     1024,     4096, 0xaec3ebbb
+0,     249856,     249856,     1024,     4096, 0xc1e4ca2b
+0,     250880,     250880,     1024,     4096, 0xdcb8e550
+0,     251904,     251904,     1024,     4096, 0xe70bfe5d
+0,     252928,     252928,     1024,     4096, 0x5da3f4d4
+0,     253952,     253952,     1024,     4096, 0xfe9f04f6
+0,     254976,     254976,     1024,     4096, 0xf960f3cd
+0,     256000,     256000,     1024,     4096, 0xe6b7fc42
+0,     257024,     257024,     1024,     4096, 0xb8b9f1e2
+0,     258048,     258048,     1024,     4096, 0x520dd814
+0,     259072,     259072,     1024,     4096, 0x00f30212
+0,     260096,     260096,     1024,     4096, 0x8298f610
+0,     261120,     261120,     1024,     4096, 0xf0d9f47f
+0,     262144,     262144,     1024,     4096, 0x5063f4c4
+0,     263168,     263168,     1024,     4096, 0x6910f4bf
+0,     264192,     264192,      408,     1632, 0xe6d032c8
diff --git a/tests/ref/fate/filter-apad b/tests/ref/fate/filter-apad
new file mode 100644
index 0000000..194a459
--- /dev/null
+++ b/tests/ref/fate/filter-apad
@@ -0,0 +1,265 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1024,     4096, 0x29e3eecf
+0,       1024,       1024,     1024,     4096, 0x18390b96
+0,       2048,       2048,     1024,     4096, 0xc477fa99
+0,       3072,       3072,     1024,     4096, 0x3bc0f14f
+0,       4096,       4096,     1024,     4096, 0x2379ed91
+0,       5120,       5120,     1024,     4096, 0xfd6a0070
+0,       6144,       6144,     1024,     4096, 0x0b01f4cf
+0,       7168,       7168,     1024,     4096, 0x6716fd93
+0,       8192,       8192,     1024,     4096, 0x1840f25b
+0,       9216,       9216,     1024,     4096, 0x9c1ffaf1
+0,      10240,      10240,     1024,     4096, 0xcbedefaf
+0,      11264,      11264,     1024,     4096, 0x3e050390
+0,      12288,      12288,     1024,     4096, 0xb30e0090
+0,      13312,      13312,     1024,     4096, 0x26b8f75b
+0,      14336,      14336,     1024,     4096, 0xd706e311
+0,      15360,      15360,     1024,     4096, 0x0c480138
+0,      16384,      16384,     1024,     4096, 0x6c9a0216
+0,      17408,      17408,     1024,     4096, 0x7abce54f
+0,      18432,      18432,     1024,     4096, 0xda45f63f
+0,      19456,      19456,     1024,     4096, 0x50d5ff87
+0,      20480,      20480,     1024,     4096, 0x59be0352
+0,      21504,      21504,     1024,     4096, 0xa61af077
+0,      22528,      22528,     1024,     4096, 0x84c4fc07
+0,      23552,      23552,     1024,     4096, 0x4a35f345
+0,      24576,      24576,     1024,     4096, 0xbb65fa81
+0,      25600,      25600,     1024,     4096, 0xf6c7f5e5
+0,      26624,      26624,     1024,     4096, 0xd3270138
+0,      27648,      27648,     1024,     4096, 0x4782ed53
+0,      28672,      28672,     1024,     4096, 0xe308f055
+0,      29696,      29696,     1024,     4096, 0x7d33f97d
+0,      30720,      30720,     1024,     4096, 0xb8b00dd4
+0,      31744,      31744,     1024,     4096, 0x7ff7efab
+0,      32768,      32768,     1024,     4096, 0x29e3eecf
+0,      33792,      33792,     1024,     4096, 0x18390b96
+0,      34816,      34816,     1024,     4096, 0xc477fa99
+0,      35840,      35840,     1024,     4096, 0x3bc0f14f
+0,      36864,      36864,     1024,     4096, 0x2379ed91
+0,      37888,      37888,     1024,     4096, 0xfd6a0070
+0,      38912,      38912,     1024,     4096, 0x0b01f4cf
+0,      39936,      39936,     1024,     4096, 0x6716fd93
+0,      40960,      40960,     1024,     4096, 0x1840f25b
+0,      41984,      41984,     1024,     4096, 0x9c1ffaf1
+0,      43008,      43008,     1024,     4096, 0xcbedefaf
+0,      44032,      44032,     1024,     4096, 0xda37d691
+0,      45056,      45056,     1024,     4096, 0x7193ecbf
+0,      46080,      46080,     1024,     4096, 0x6e4a0a36
+0,      47104,      47104,     1024,     4096, 0x61cfe70d
+0,      48128,      48128,     1024,     4096, 0xc19ffa15
+0,      49152,      49152,     1024,     4096, 0x7b32fb3d
+0,      50176,      50176,     1024,     4096, 0xdacefd3f
+0,      51200,      51200,     1024,     4096, 0x3964f64d
+0,      52224,      52224,     1024,     4096, 0xdcf2edad
+0,      53248,      53248,     1024,     4096, 0x1367f69b
+0,      54272,      54272,     1024,     4096, 0xd4c6f7b9
+0,      55296,      55296,     1024,     4096, 0x9e041186
+0,      56320,      56320,     1024,     4096, 0xe939edd7
+0,      57344,      57344,     1024,     4096, 0xa932336a
+0,      58368,      58368,     1024,     4096, 0x5f510e28
+0,      59392,      59392,     1024,     4096, 0x4b8501c8
+0,      60416,      60416,     1024,     4096, 0xfbc30250
+0,      61440,      61440,     1024,     4096, 0x5e7fd855
+0,      62464,      62464,     1024,     4096, 0x8ef1f265
+0,      63488,      63488,     1024,     4096, 0x9f7601c2
+0,      64512,      64512,     1024,     4096, 0xb400f0b7
+0,      65536,      65536,     1024,     4096, 0x4c91e10b
+0,      66560,      66560,     1024,     4096, 0x3f41fe61
+0,      67584,      67584,     1024,     4096, 0x74fff9b9
+0,      68608,      68608,     1024,     4096, 0x18bbf5a5
+0,      69632,      69632,     1024,     4096, 0x51a70180
+0,      70656,      70656,     1024,     4096, 0x29f3e8c5
+0,      71680,      71680,     1024,     4096, 0x562efdb9
+0,      72704,      72704,     1024,     4096, 0xa2e006e0
+0,      73728,      73728,     1024,     4096, 0xa1bff541
+0,      74752,      74752,     1024,     4096, 0xd95b0012
+0,      75776,      75776,     1024,     4096, 0xd93e0912
+0,      76800,      76800,     1024,     4096, 0x6c2a1d88
+0,      77824,      77824,     1024,     4096, 0xb4d8fb8b
+0,      78848,      78848,     1024,     4096, 0xf14b0492
+0,      79872,      79872,     1024,     4096, 0x1c7be7b7
+0,      80896,      80896,     1024,     4096, 0xc181f877
+0,      81920,      81920,     1024,     4096, 0xba132d14
+0,      82944,      82944,     1024,     4096, 0xabae2d9a
+0,      83968,      83968,     1024,     4096, 0xb07fff15
+0,      84992,      84992,     1024,     4096, 0xa0c1ff2d
+0,      86016,      86016,     1024,     4096, 0x19f7fd1f
+0,      87040,      87040,     1024,     4096, 0xcb6d11a4
+0,      88064,      88064,     1024,     4096, 0x166ac8b7
+0,      89088,      89088,     1024,     4096, 0xe68dda8f
+0,      90112,      90112,     1024,     4096, 0xe457b505
+0,      91136,      91136,     1024,     4096, 0xda25a409
+0,      92160,      92160,     1024,     4096, 0x5b5d9d3b
+0,      93184,      93184,     1024,     4096, 0xa61eb13d
+0,      94208,      94208,     1024,     4096, 0xac93b66f
+0,      95232,      95232,     1024,     4096, 0xc7aeb33f
+0,      96256,      96256,     1024,     4096, 0x52cccfb5
+0,      97280,      97280,     1024,     4096, 0x4e4cf487
+0,      98304,      98304,     1024,     4096, 0x19c07f35
+0,      99328,      99328,     1024,     4096, 0x63ecd34f
+0,     100352,     100352,     1024,     4096, 0x122aec53
+0,     101376,     101376,     1024,     4096, 0x6581c0ad
+0,     102400,     102400,     1024,     4096, 0x640edb15
+0,     103424,     103424,     1024,     4096, 0x5d66c66f
+0,     104448,     104448,     1024,     4096, 0x069e9d35
+0,     105472,     105472,     1024,     4096, 0x5c9fd0e9
+0,     106496,     106496,     1024,     4096, 0x72468667
+0,     107520,     107520,     1024,     4096, 0x6e6dd02b
+0,     108544,     108544,     1024,     4096, 0x93edce33
+0,     109568,     109568,     1024,     4096, 0xcdfbd519
+0,     110592,     110592,     1024,     4096, 0x8463f2bb
+0,     111616,     111616,     1024,     4096, 0x5ca6f869
+0,     112640,     112640,     1024,     4096, 0x099a0398
+0,     113664,     113664,     1024,     4096, 0xa7fa10f0
+0,     114688,     114688,     1024,     4096, 0x28caddd3
+0,     115712,     115712,     1024,     4096, 0x4852ef8b
+0,     116736,     116736,     1024,     4096, 0x0250ee7b
+0,     117760,     117760,     1024,     4096, 0x9583da21
+0,     118784,     118784,     1024,     4096, 0x7365fb33
+0,     119808,     119808,     1024,     4096, 0x28c82066
+0,     120832,     120832,     1024,     4096, 0x94650be4
+0,     121856,     121856,     1024,     4096, 0xeb21f8eb
+0,     122880,     122880,     1024,     4096, 0xcd88f455
+0,     123904,     123904,     1024,     4096, 0x66a9efaf
+0,     124928,     124928,     1024,     4096, 0x5500c6ed
+0,     125952,     125952,     1024,     4096, 0x0ee0c62d
+0,     126976,     126976,     1024,     4096, 0x34d30762
+0,     128000,     128000,     1024,     4096, 0x8c0dec9f
+0,     129024,     129024,     1024,     4096, 0x790011d8
+0,     130048,     130048,     1024,     4096, 0xb76a1136
+0,     131072,     131072,     1024,     4096, 0x7dddfea7
+0,     132096,     132096,     1024,     4096, 0xdfa3ed49
+0,     133120,     133120,     1024,     4096, 0xc129f54e
+0,     134144,     134144,     1024,     4096, 0x9a86f077
+0,     135168,     135168,     1024,     4096, 0xc9eef209
+0,     136192,     136192,     1024,     4096, 0x72d4029b
+0,     137216,     137216,     1024,     4096, 0x8ec20590
+0,     138240,     138240,     1024,     4096, 0xd48f18ed
+0,     139264,     139264,     1024,     4096, 0xd807eadc
+0,     140288,     140288,     1024,     4096, 0x1e2bea09
+0,     141312,     141312,     1024,     4096, 0x937af12e
+0,     142336,     142336,     1024,     4096, 0xdedbf303
+0,     143360,     143360,     1024,     4096, 0xdc75df88
+0,     144384,     144384,     1024,     4096, 0x1845ffd6
+0,     145408,     145408,     1024,     4096, 0x20e8150c
+0,     146432,     146432,     1024,     4096, 0x5ea7eeef
+0,     147456,     147456,     1024,     4096, 0x4c7efa21
+0,     148480,     148480,     1024,     4096, 0x8b97e30e
+0,     149504,     149504,     1024,     4096, 0xe5040228
+0,     150528,     150528,     1024,     4096, 0x6283f78c
+0,     151552,     151552,     1024,     4096, 0xe7100140
+0,     152576,     152576,     1024,     4096, 0x9ea6f9b2
+0,     153600,     153600,     1024,     4096, 0x5f0e1563
+0,     154624,     154624,     1024,     4096, 0x510bf18e
+0,     155648,     155648,     1024,     4096, 0x5f4fe425
+0,     156672,     156672,     1024,     4096, 0x507af3c0
+0,     157696,     157696,     1024,     4096, 0xbf14ddc6
+0,     158720,     158720,     1024,     4096, 0x1871ed69
+0,     159744,     159744,     1024,     4096, 0xc349ef9f
+0,     160768,     160768,     1024,     4096, 0x4e2c1834
+0,     161792,     161792,     1024,     4096, 0x2383fe04
+0,     162816,     162816,     1024,     4096, 0x6626f415
+0,     163840,     163840,     1024,     4096, 0x283be379
+0,     164864,     164864,     1024,     4096, 0xc76c0ceb
+0,     165888,     165888,     1024,     4096, 0xa0b8040f
+0,     166912,     166912,     1024,     4096, 0x2535eb6d
+0,     167936,     167936,     1024,     4096, 0xeb180bb5
+0,     168960,     168960,     1024,     4096, 0xbc5cf059
+0,     169984,     169984,     1024,     4096, 0x1862f1ac
+0,     171008,     171008,     1024,     4096, 0x9cc2ea2b
+0,     172032,     172032,     1024,     4096, 0xbb9ae754
+0,     173056,     173056,     1024,     4096, 0x716debb5
+0,     174080,     174080,     1024,     4096, 0xff3aff2a
+0,     175104,     175104,     1024,     4096, 0x755dfa5c
+0,     176128,     176128,     1024,     4096, 0x3b830605
+0,     177152,     177152,     1024,     4096, 0x0030dc9e
+0,     178176,     178176,     1024,     4096, 0xb017fd54
+0,     179200,     179200,     1024,     4096, 0x5c7dfa2e
+0,     180224,     180224,     1024,     4096, 0x7887e599
+0,     181248,     181248,     1024,     4096, 0xb730e72f
+0,     182272,     182272,     1024,     4096, 0x6bb3fae4
+0,     183296,     183296,     1024,     4096, 0xcc08fc36
+0,     184320,     184320,     1024,     4096, 0x5afd9ec2
+0,     185344,     185344,     1024,     4096, 0xa1d3e83d
+0,     186368,     186368,     1024,     4096, 0x7f96013c
+0,     187392,     187392,     1024,     4096, 0x7a0afe31
+0,     188416,     188416,     1024,     4096, 0xa37d1701
+0,     189440,     189440,     1024,     4096, 0x4615ebc2
+0,     190464,     190464,     1024,     4096, 0x217005c1
+0,     191488,     191488,     1024,     4096, 0x1755f789
+0,     192512,     192512,     1024,     4096, 0x83e6db65
+0,     193536,     193536,     1024,     4096, 0x92ab1447
+0,     194560,     194560,     1024,     4096, 0xedbdf383
+0,     195584,     195584,     1024,     4096, 0x4316f6a9
+0,     196608,     196608,     1024,     4096, 0x1a6a0b4c
+0,     197632,     197632,     1024,     4096, 0xdfd809b7
+0,     198656,     198656,     1024,     4096, 0x1d2cf5f1
+0,     199680,     199680,     1024,     4096, 0xd366f4a1
+0,     200704,     200704,     1024,     4096, 0x6a2f86e0
+0,     201728,     201728,     1024,     4096, 0xf51f08a9
+0,     202752,     202752,     1024,     4096, 0x05edefa8
+0,     203776,     203776,     1024,     4096, 0x255df2a6
+0,     204800,     204800,     1024,     4096, 0xe881d9e4
+0,     205824,     205824,     1024,     4096, 0x50380523
+0,     206848,     206848,     1024,     4096, 0x8b93eb26
+0,     207872,     207872,     1024,     4096, 0x759cf94c
+0,     208896,     208896,     1024,     4096, 0x8474f591
+0,     209920,     209920,     1024,     4096, 0x0030dc9e
+0,     210944,     210944,     1024,     4096, 0xb017fd54
+0,     211968,     211968,     1024,     4096, 0x5c7dfa2e
+0,     212992,     212992,     1024,     4096, 0x7887e599
+0,     214016,     214016,     1024,     4096, 0xb730e72f
+0,     215040,     215040,     1024,     4096, 0x6bb3fae4
+0,     216064,     216064,     1024,     4096, 0xcc08fc36
+0,     217088,     217088,     1024,     4096, 0x5afd9ec2
+0,     218112,     218112,     1024,     4096, 0xa1d3e83d
+0,     219136,     219136,     1024,     4096, 0x7f96013c
+0,     220160,     220160,     1024,     4096, 0x7a0afe31
+0,     221184,     221184,     1024,     4096, 0xa37d1701
+0,     222208,     222208,     1024,     4096, 0x4615ebc2
+0,     223232,     223232,     1024,     4096, 0x217005c1
+0,     224256,     224256,     1024,     4096, 0x1755f789
+0,     225280,     225280,     1024,     4096, 0x83e6db65
+0,     226304,     226304,     1024,     4096, 0x92ab1447
+0,     227328,     227328,     1024,     4096, 0xedbdf383
+0,     228352,     228352,     1024,     4096, 0x4316f6a9
+0,     229376,     229376,     1024,     4096, 0x1a6a0b4c
+0,     230400,     230400,     1024,     4096, 0xdfd809b7
+0,     231424,     231424,     1024,     4096, 0x1d2cf5f1
+0,     232448,     232448,     1024,     4096, 0xd366f4a1
+0,     233472,     233472,     1024,     4096, 0x6a2f86e0
+0,     234496,     234496,     1024,     4096, 0xf51f08a9
+0,     235520,     235520,     1024,     4096, 0x05edefa8
+0,     236544,     236544,     1024,     4096, 0x255df2a6
+0,     237568,     237568,     1024,     4096, 0xe881d9e4
+0,     238592,     238592,     1024,     4096, 0x50380523
+0,     239616,     239616,     1024,     4096, 0x8b93eb26
+0,     240640,     240640,     1024,     4096, 0x759cf94c
+0,     241664,     241664,     1024,     4096, 0x8474f591
+0,     242688,     242688,     1024,     4096, 0x0030dc9e
+0,     243712,     243712,     1024,     4096, 0xb017fd54
+0,     244736,     244736,     1024,     4096, 0x5c7dfa2e
+0,     245760,     245760,     1024,     4096, 0x7887e599
+0,     246784,     246784,     1024,     4096, 0xb730e72f
+0,     247808,     247808,     1024,     4096, 0x6bb3fae4
+0,     248832,     248832,     1024,     4096, 0xcc08fc36
+0,     249856,     249856,     1024,     4096, 0x5afd9ec2
+0,     250880,     250880,     1024,     4096, 0xa1d3e83d
+0,     251904,     251904,     1024,     4096, 0x7f96013c
+0,     252928,     252928,     1024,     4096, 0x7a0afe31
+0,     253952,     253952,     1024,     4096, 0xa37d1701
+0,     254976,     254976,     1024,     4096, 0x4615ebc2
+0,     256000,     256000,     1024,     4096, 0x217005c1
+0,     257024,     257024,     1024,     4096, 0x1755f789
+0,     258048,     258048,     1024,     4096, 0x83e6db65
+0,     259072,     259072,     1024,     4096, 0x92ab1447
+0,     260096,     260096,     1024,     4096, 0xedbdf383
+0,     261120,     261120,     1024,     4096, 0x4316f6a9
+0,     262144,     262144,     1024,     4096, 0x1a6a0b4c
+0,     263168,     263168,     1024,     4096, 0xdfd809b7
+0,     264192,     264192,      408,     1632, 0xf412313e
+0,     264600,     264600,       10,       40, 0x00000000
diff --git a/tests/ref/fate/filter-atrim-duration b/tests/ref/fate/filter-atrim-duration
index a51dff7..6f16c8f 100644
--- a/tests/ref/fate/filter-atrim-duration
+++ b/tests/ref/fate/filter-atrim-duration
@@ -1,2 +1,6 @@
 #tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
 0,       4410,       4410,      441,     1764, 0x61e374f7
diff --git a/tests/ref/fate/filter-atrim-mixed b/tests/ref/fate/filter-atrim-mixed
index ae3281a..8f8b4ed 100644
--- a/tests/ref/fate/filter-atrim-mixed
+++ b/tests/ref/fate/filter-atrim-mixed
@@ -1,4 +1,8 @@
 #tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
 0,       1025,       1025,     1023,     4092, 0x78560a4c
 0,       2048,       2048,     1024,     4096, 0xc477fa99
 0,       3072,       3072,     1024,     4096, 0x3bc0f14f
diff --git a/tests/ref/fate/filter-atrim-samples b/tests/ref/fate/filter-atrim-samples
index 3461666..4dcb333 100644
--- a/tests/ref/fate/filter-atrim-samples
+++ b/tests/ref/fate/filter-atrim-samples
@@ -1,2 +1,6 @@
 #tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
 0,         26,         26,       54,      216, 0x6b376c6c
diff --git a/tests/ref/fate/filter-atrim-time b/tests/ref/fate/filter-atrim-time
index a368210..4ca3d73 100644
--- a/tests/ref/fate/filter-atrim-time
+++ b/tests/ref/fate/filter-atrim-time
@@ -1,4 +1,8 @@
 #tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
 0,       4410,       4410,      710,     2840, 0x658982a3
 0,       5120,       5120,     1024,     4096, 0xfd6a0070
 0,       6144,       6144,     1024,     4096, 0x0b01f4cf
diff --git a/tests/ref/fate/filter-boxblur b/tests/ref/fate/filter-boxblur
index acb2beb..d332f3a 100644
--- a/tests/ref/fate/filter-boxblur
+++ b/tests/ref/fate/filter-boxblur
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x113489f8
 0,          1,          1,        1,   152064, 0x650a64ca
 0,          2,          2,        1,   152064, 0x29ecf6b1
diff --git a/tests/ref/fate/filter-codecview-mvs b/tests/ref/fate/filter-codecview-mvs
index 13286f0..4e1e53d 100644
--- a/tests/ref/fate/filter-codecview-mvs
+++ b/tests/ref/fate/filter-codecview-mvs
@@ -1,4 +1,8 @@
 #tb 0: 32768/785647
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 576x320
+#sar 0: 0/1
 0,          0,          0,        1,   276480, 0x5f7a0d4f
 0,          1,          1,        1,   276480, 0x5f7a0d4f
 0,          2,          2,        1,   276480, 0x5f7a0d4f
diff --git a/tests/ref/fate/filter-colorchannelmixer b/tests/ref/fate/filter-colorchannelmixer
index 4e9e9d3..93f9a39 100644
--- a/tests/ref/fate/filter-colorchannelmixer
+++ b/tests/ref/fate/filter-colorchannelmixer
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0x42900c13
 0,          1,          1,        1,   304128, 0xfb0439bc
 0,          2,          2,        1,   304128, 0x967b9f0d
diff --git a/tests/ref/fate/filter-colormatrix1 b/tests/ref/fate/filter-colormatrix1
index 0f008e0..2f25f6c 100644
--- a/tests/ref/fate/filter-colormatrix1
+++ b/tests/ref/fate/filter-colormatrix1
@@ -1 +1 @@
-colormatrix1        0a0640b2d4ccd4e793f4919d82a89523
+colormatrix1        1593e24a71db42d07781b92665cf99a9
diff --git a/tests/ref/fate/filter-colormatrix2 b/tests/ref/fate/filter-colormatrix2
index 7f3232e..b57b594 100644
--- a/tests/ref/fate/filter-colormatrix2
+++ b/tests/ref/fate/filter-colormatrix2
@@ -1 +1 @@
-colormatrix2        5eb17671c03496ae43723e49832ab17a
+colormatrix2        cafba294debb89f59143b519f3cd1673
diff --git a/tests/ref/fate/filter-concat b/tests/ref/fate/filter-concat
index 73e4185..f8f7353 100644
--- a/tests/ref/fate/filter-concat
+++ b/tests/ref/fate/filter-concat
@@ -1,5 +1,13 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 #tb 1: 1/44100
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 44100
+#channel_layout 1: 4
 0,          0,          0,        1,   230400, 0x88c4d19a
 1,          0,          0,     1024,     2048, 0xb3f10192
 1,       1024,       1024,     1024,     2048, 0xb340fe4e
diff --git a/tests/ref/fate/filter-curves b/tests/ref/fate/filter-curves
index a96f0ee..401bd2e 100644
--- a/tests/ref/fate/filter-curves
+++ b/tests/ref/fate/filter-curves
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0xcf426780
 0,          1,          1,        1,   921600, 0x7642892d
 0,          2,          2,        1,   921600, 0x13c1ab7e
diff --git a/tests/ref/fate/filter-delogo b/tests/ref/fate/filter-delogo
index bf2b751..0e59f82 100644
--- a/tests/ref/fate/filter-delogo
+++ b/tests/ref/fate/filter-delogo
@@ -1,4 +1,8 @@
 #tb 0: 32768/982057
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x240
+#sar 0: 0/1
 0,          0,          0,        1,   126720, 0xcefaec47
 0,          1,          1,        1,   126720, 0xa416ece5
 0,          2,          2,        1,   126720, 0xa416ece5
diff --git a/tests/ref/fate/filter-drawbox b/tests/ref/fate/filter-drawbox
index c63d2fc..8ffd381 100644
--- a/tests/ref/fate/filter-drawbox
+++ b/tests/ref/fate/filter-drawbox
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9ada9be9
 0,          1,          1,        1,   152064, 0xb0ec7d59
 0,          2,          2,        1,   152064, 0x938816b8
diff --git a/tests/ref/fate/filter-fade b/tests/ref/fate/filter-fade
index 9d691ce..2ba7671 100644
--- a/tests/ref/fate/filter-fade
+++ b/tests/ref/fate/filter-fade
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xb4e6c735
 0,          1,          1,        1,   152064, 0xb4e6c735
 0,          2,          2,        1,   152064, 0xb4e6c735
diff --git a/tests/ref/fate/filter-fieldorder b/tests/ref/fate/filter-fieldorder
index 6bb647a..9a73e6e 100644
--- a/tests/ref/fate/filter-fieldorder
+++ b/tests/ref/fate/filter-fieldorder
@@ -1,4 +1,8 @@
 #tb 0: 2/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   202752, 0x789424b6
 0,          1,          1,        1,   202752, 0x7a1f47a9
 0,          2,          2,        1,   202752, 0xa55a9aba
diff --git a/tests/ref/fate/filter-fps b/tests/ref/fate/filter-fps
new file mode 100644
index 0000000..55712cf
--- /dev/null
+++ b/tests/ref/fate/filter-fps
@@ -0,0 +1,87 @@
+#tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 112x182
+#sar 0: 0/1
+0,          0,          0,        1,    30576, 0xcdc29b3d
+0,          1,          1,        1,    30576, 0xcdc29b3d
+0,          2,          2,        1,    30576, 0xcdc29b3d
+0,          3,          3,        1,    30576, 0xcdc29b3d
+0,          4,          4,        1,    30576, 0xcdc29b3d
+0,          5,          5,        1,    30576, 0xcdc29b3d
+0,          6,          6,        1,    30576, 0x5c83656c
+0,          7,          7,        1,    30576, 0x5c83656c
+0,          8,          8,        1,    30576, 0x5c83656c
+0,          9,          9,        1,    30576, 0x5c83656c
+0,         10,         10,        1,    30576, 0x5c83656c
+0,         11,         11,        1,    30576, 0x5c83656c
+0,         12,         12,        1,    30576, 0x5c83656c
+0,         13,         13,        1,    30576, 0x26b67f83
+0,         14,         14,        1,    30576, 0x26b67f83
+0,         15,         15,        1,    30576, 0x26b67f83
+0,         16,         16,        1,    30576, 0x26b67f83
+0,         17,         17,        1,    30576, 0x26b67f83
+0,         18,         18,        1,    30576, 0x26b67f83
+0,         19,         19,        1,    30576, 0x26b67f83
+0,         20,         20,        1,    30576, 0x26b67f83
+0,         21,         21,        1,    30576, 0x26b67f83
+0,         22,         22,        1,    30576, 0x26b67f83
+0,         23,         23,        1,    30576, 0x26b67f83
+0,         24,         24,        1,    30576, 0x26b67f83
+0,         25,         25,        1,    30576, 0x26b67f83
+0,         26,         26,        1,    30576, 0x26b67f83
+0,         27,         27,        1,    30576, 0x26b67f83
+0,         28,         28,        1,    30576, 0x26b67f83
+0,         29,         29,        1,    30576, 0x26b67f83
+0,         30,         30,        1,    30576, 0x26b67f83
+0,         31,         31,        1,    30576, 0x26b67f83
+0,         32,         32,        1,    30576, 0x26b67f83
+0,         33,         33,        1,    30576, 0x26b67f83
+0,         34,         34,        1,    30576, 0x26b67f83
+0,         35,         35,        1,    30576, 0x26b67f83
+0,         36,         36,        1,    30576, 0x26b67f83
+0,         37,         37,        1,    30576, 0x26b67f83
+0,         38,         38,        1,    30576, 0x26b67f83
+0,         39,         39,        1,    30576, 0x26b67f83
+0,         40,         40,        1,    30576, 0x26b67f83
+0,         41,         41,        1,    30576, 0x26b67f83
+0,         42,         42,        1,    30576, 0x26b67f83
+0,         43,         43,        1,    30576, 0x26b67f83
+0,         44,         44,        1,    30576, 0x26b67f83
+0,         45,         45,        1,    30576, 0x26b67f83
+0,         46,         46,        1,    30576, 0x26b67f83
+0,         47,         47,        1,    30576, 0x26b67f83
+0,         48,         48,        1,    30576, 0x26b67f83
+0,         49,         49,        1,    30576, 0x26b67f83
+0,         50,         50,        1,    30576, 0x26b67f83
+0,         51,         51,        1,    30576, 0x26b67f83
+0,         52,         52,        1,    30576, 0x26b67f83
+0,         53,         53,        1,    30576, 0x26b67f83
+0,         54,         54,        1,    30576, 0x26b67f83
+0,         55,         55,        1,    30576, 0x26b67f83
+0,         56,         56,        1,    30576, 0x26b67f83
+0,         57,         57,        1,    30576, 0x26b67f83
+0,         58,         58,        1,    30576, 0x26b67f83
+0,         59,         59,        1,    30576, 0x26b67f83
+0,         60,         60,        1,    30576, 0x26b67f83
+0,         61,         61,        1,    30576, 0x26b67f83
+0,         62,         62,        1,    30576, 0x26b67f83
+0,         63,         63,        1,    30576, 0x26b67f83
+0,         64,         64,        1,    30576, 0x26b67f83
+0,         65,         65,        1,    30576, 0x26b67f83
+0,         66,         66,        1,    30576, 0x26b67f83
+0,         67,         67,        1,    30576, 0x26b67f83
+0,         68,         68,        1,    30576, 0x26b67f83
+0,         69,         69,        1,    30576, 0x26b67f83
+0,         70,         70,        1,    30576, 0x26b67f83
+0,         71,         71,        1,    30576, 0x26b67f83
+0,         72,         72,        1,    30576, 0x26b67f83
+0,         73,         73,        1,    30576, 0xa2fcd06f
+0,         74,         74,        1,    30576, 0xa2fcd06f
+0,         75,         75,        1,    30576, 0xa2fcd06f
+0,         76,         76,        1,    30576, 0xa2fcd06f
+0,         77,         77,        1,    30576, 0xa2fcd06f
+0,         78,         78,        1,    30576, 0xa2fcd06f
+0,         79,         79,        1,    30576, 0xa2fcd06f
+0,         80,         80,        1,    30576, 0xa2fcd06f
+0,         81,         81,        1,    30576, 0xd4150aad
diff --git a/tests/ref/fate/filter-fps-cfr b/tests/ref/fate/filter-fps-cfr
new file mode 100644
index 0000000..fa71b59
--- /dev/null
+++ b/tests/ref/fate/filter-fps-cfr
@@ -0,0 +1,94 @@
+#tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 112x182
+#sar 0: 0/1
+0,          0,          0,        1,    30576, 0xcdc29b3d
+0,          1,          1,        1,    30576, 0xcdc29b3d
+0,          2,          2,        1,    30576, 0xcdc29b3d
+0,          3,          3,        1,    30576, 0xcdc29b3d
+0,          4,          4,        1,    30576, 0xcdc29b3d
+0,          5,          5,        1,    30576, 0xcdc29b3d
+0,          6,          6,        1,    30576, 0x5c83656c
+0,          7,          7,        1,    30576, 0x5c83656c
+0,          8,          8,        1,    30576, 0x5c83656c
+0,          9,          9,        1,    30576, 0x5c83656c
+0,         10,         10,        1,    30576, 0x5c83656c
+0,         11,         11,        1,    30576, 0x5c83656c
+0,         12,         12,        1,    30576, 0x5c83656c
+0,         13,         13,        1,    30576, 0x26b67f83
+0,         14,         14,        1,    30576, 0x26b67f83
+0,         15,         15,        1,    30576, 0x26b67f83
+0,         16,         16,        1,    30576, 0x26b67f83
+0,         17,         17,        1,    30576, 0x26b67f83
+0,         18,         18,        1,    30576, 0x26b67f83
+0,         19,         19,        1,    30576, 0x26b67f83
+0,         20,         20,        1,    30576, 0x26b67f83
+0,         21,         21,        1,    30576, 0x26b67f83
+0,         22,         22,        1,    30576, 0x26b67f83
+0,         23,         23,        1,    30576, 0x26b67f83
+0,         24,         24,        1,    30576, 0x26b67f83
+0,         25,         25,        1,    30576, 0x26b67f83
+0,         26,         26,        1,    30576, 0x26b67f83
+0,         27,         27,        1,    30576, 0x26b67f83
+0,         28,         28,        1,    30576, 0x26b67f83
+0,         29,         29,        1,    30576, 0x26b67f83
+0,         30,         30,        1,    30576, 0x26b67f83
+0,         31,         31,        1,    30576, 0x26b67f83
+0,         32,         32,        1,    30576, 0x26b67f83
+0,         33,         33,        1,    30576, 0x26b67f83
+0,         34,         34,        1,    30576, 0x26b67f83
+0,         35,         35,        1,    30576, 0x26b67f83
+0,         36,         36,        1,    30576, 0x26b67f83
+0,         37,         37,        1,    30576, 0x26b67f83
+0,         38,         38,        1,    30576, 0x26b67f83
+0,         39,         39,        1,    30576, 0x26b67f83
+0,         40,         40,        1,    30576, 0x26b67f83
+0,         41,         41,        1,    30576, 0x26b67f83
+0,         42,         42,        1,    30576, 0x26b67f83
+0,         43,         43,        1,    30576, 0x26b67f83
+0,         44,         44,        1,    30576, 0x26b67f83
+0,         45,         45,        1,    30576, 0x26b67f83
+0,         46,         46,        1,    30576, 0x26b67f83
+0,         47,         47,        1,    30576, 0x26b67f83
+0,         48,         48,        1,    30576, 0x26b67f83
+0,         49,         49,        1,    30576, 0x26b67f83
+0,         50,         50,        1,    30576, 0x26b67f83
+0,         51,         51,        1,    30576, 0x26b67f83
+0,         52,         52,        1,    30576, 0x26b67f83
+0,         53,         53,        1,    30576, 0x26b67f83
+0,         54,         54,        1,    30576, 0x26b67f83
+0,         55,         55,        1,    30576, 0x26b67f83
+0,         56,         56,        1,    30576, 0x26b67f83
+0,         57,         57,        1,    30576, 0x26b67f83
+0,         58,         58,        1,    30576, 0x26b67f83
+0,         59,         59,        1,    30576, 0x26b67f83
+0,         60,         60,        1,    30576, 0x26b67f83
+0,         61,         61,        1,    30576, 0x26b67f83
+0,         62,         62,        1,    30576, 0x26b67f83
+0,         63,         63,        1,    30576, 0x26b67f83
+0,         64,         64,        1,    30576, 0x26b67f83
+0,         65,         65,        1,    30576, 0x26b67f83
+0,         66,         66,        1,    30576, 0x26b67f83
+0,         67,         67,        1,    30576, 0x26b67f83
+0,         68,         68,        1,    30576, 0x26b67f83
+0,         69,         69,        1,    30576, 0x26b67f83
+0,         70,         70,        1,    30576, 0x26b67f83
+0,         71,         71,        1,    30576, 0x26b67f83
+0,         72,         72,        1,    30576, 0x26b67f83
+0,         73,         73,        1,    30576, 0xa2fcd06f
+0,         74,         74,        1,    30576, 0xa2fcd06f
+0,         75,         75,        1,    30576, 0xa2fcd06f
+0,         76,         76,        1,    30576, 0xa2fcd06f
+0,         77,         77,        1,    30576, 0xa2fcd06f
+0,         78,         78,        1,    30576, 0xa2fcd06f
+0,         79,         79,        1,    30576, 0xa2fcd06f
+0,         80,         80,        1,    30576, 0xa2fcd06f
+0,         81,         81,        1,    30576, 0xd4150aad
+0,         82,         82,        1,    30576, 0xd4150aad
+0,         83,         83,        1,    30576, 0xd4150aad
+0,         84,         84,        1,    30576, 0xd4150aad
+0,         85,         85,        1,    30576, 0xd4150aad
+0,         86,         86,        1,    30576, 0xd4150aad
+0,         87,         87,        1,    30576, 0xd4150aad
+0,         88,         88,        1,    30576, 0xd4150aad
diff --git a/tests/ref/fate/filter-fps-r b/tests/ref/fate/filter-fps-r
new file mode 100644
index 0000000..826b1ed
--- /dev/null
+++ b/tests/ref/fate/filter-fps-r
@@ -0,0 +1,74 @@
+#tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 112x182
+#sar 0: 0/1
+0,          0,          0,        1,    30576, 0xcdc29b3d
+0,          1,          1,        1,    30576, 0xcdc29b3d
+0,          2,          2,        1,    30576, 0xcdc29b3d
+0,          4,          4,        1,    30576, 0xcdc29b3d
+0,          5,          5,        1,    30576, 0xcdc29b3d
+0,          6,          6,        1,    30576, 0x5c83656c
+0,          7,          7,        1,    30576, 0x5c83656c
+0,          8,          8,        1,    30576, 0x5c83656c
+0,         10,         10,        1,    30576, 0x5c83656c
+0,         11,         11,        1,    30576, 0x5c83656c
+0,         12,         12,        1,    30576, 0x5c83656c
+0,         13,         13,        1,    30576, 0x26b67f83
+0,         14,         14,        1,    30576, 0x26b67f83
+0,         16,         16,        1,    30576, 0x26b67f83
+0,         17,         17,        1,    30576, 0x26b67f83
+0,         18,         18,        1,    30576, 0x26b67f83
+0,         19,         19,        1,    30576, 0x26b67f83
+0,         20,         20,        1,    30576, 0x26b67f83
+0,         22,         22,        1,    30576, 0x26b67f83
+0,         23,         23,        1,    30576, 0x26b67f83
+0,         24,         24,        1,    30576, 0x26b67f83
+0,         25,         25,        1,    30576, 0x26b67f83
+0,         26,         26,        1,    30576, 0x26b67f83
+0,         28,         28,        1,    30576, 0x26b67f83
+0,         29,         29,        1,    30576, 0x26b67f83
+0,         30,         30,        1,    30576, 0x26b67f83
+0,         31,         31,        1,    30576, 0x26b67f83
+0,         32,         32,        1,    30576, 0x26b67f83
+0,         34,         34,        1,    30576, 0x26b67f83
+0,         35,         35,        1,    30576, 0x26b67f83
+0,         36,         36,        1,    30576, 0x26b67f83
+0,         37,         37,        1,    30576, 0x26b67f83
+0,         38,         38,        1,    30576, 0x26b67f83
+0,         40,         40,        1,    30576, 0x26b67f83
+0,         41,         41,        1,    30576, 0x26b67f83
+0,         42,         42,        1,    30576, 0x26b67f83
+0,         43,         43,        1,    30576, 0x26b67f83
+0,         44,         44,        1,    30576, 0x26b67f83
+0,         46,         46,        1,    30576, 0x26b67f83
+0,         47,         47,        1,    30576, 0x26b67f83
+0,         48,         48,        1,    30576, 0x26b67f83
+0,         49,         49,        1,    30576, 0x26b67f83
+0,         50,         50,        1,    30576, 0x26b67f83
+0,         52,         52,        1,    30576, 0x26b67f83
+0,         53,         53,        1,    30576, 0x26b67f83
+0,         54,         54,        1,    30576, 0x26b67f83
+0,         55,         55,        1,    30576, 0x26b67f83
+0,         56,         56,        1,    30576, 0x26b67f83
+0,         58,         58,        1,    30576, 0x26b67f83
+0,         59,         59,        1,    30576, 0x26b67f83
+0,         60,         60,        1,    30576, 0x26b67f83
+0,         61,         61,        1,    30576, 0x26b67f83
+0,         62,         62,        1,    30576, 0x26b67f83
+0,         64,         64,        1,    30576, 0x26b67f83
+0,         65,         65,        1,    30576, 0x26b67f83
+0,         66,         66,        1,    30576, 0x26b67f83
+0,         67,         67,        1,    30576, 0x26b67f83
+0,         68,         68,        1,    30576, 0x26b67f83
+0,         70,         70,        1,    30576, 0x26b67f83
+0,         71,         71,        1,    30576, 0x26b67f83
+0,         72,         72,        1,    30576, 0x26b67f83
+0,         73,         73,        1,    30576, 0xa2fcd06f
+0,         74,         74,        1,    30576, 0xa2fcd06f
+0,         76,         76,        1,    30576, 0xa2fcd06f
+0,         77,         77,        1,    30576, 0xa2fcd06f
+0,         78,         78,        1,    30576, 0xa2fcd06f
+0,         79,         79,        1,    30576, 0xa2fcd06f
+0,         80,         80,        1,    30576, 0xa2fcd06f
+0,         82,         82,        1,    30576, 0xd4150aad
diff --git a/tests/ref/fate/filter-framepack-columns b/tests/ref/fate/filter-framepack-columns
index f387632..ac688c9 100644
--- a/tests/ref/fate/filter-framepack-columns
+++ b/tests/ref/fate/filter-framepack-columns
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 704x288
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0x8cde13ed
 0,          1,          1,        1,   304128, 0xc97fcaa2
 0,          2,          2,        1,   304128, 0x8139eca3
diff --git a/tests/ref/fate/filter-framepack-frameseq b/tests/ref/fate/filter-framepack-frameseq
index 83c08a0..7174fe4 100644
--- a/tests/ref/fate/filter-framepack-frameseq
+++ b/tests/ref/fate/filter-framepack-frameseq
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x05b789ef
 0,          1,          1,        1,   152064, 0x05b789ef
 0,          2,          2,        1,   152064, 0x4bb46551
diff --git a/tests/ref/fate/filter-framepack-lines b/tests/ref/fate/filter-framepack-lines
index d714462..d8cc289 100644
--- a/tests/ref/fate/filter-framepack-lines
+++ b/tests/ref/fate/filter-framepack-lines
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x576
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0x901a13ed
 0,          1,          1,        1,   304128, 0x793ccaa2
 0,          2,          2,        1,   304128, 0x9eafeca3
diff --git a/tests/ref/fate/filter-framepack-sbs b/tests/ref/fate/filter-framepack-sbs
index d714462..d4b47f0 100644
--- a/tests/ref/fate/filter-framepack-sbs
+++ b/tests/ref/fate/filter-framepack-sbs
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 704x288
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0x901a13ed
 0,          1,          1,        1,   304128, 0x793ccaa2
 0,          2,          2,        1,   304128, 0x9eafeca3
diff --git a/tests/ref/fate/filter-framepack-tab b/tests/ref/fate/filter-framepack-tab
index 0346f06..500cfb7 100644
--- a/tests/ref/fate/filter-framepack-tab
+++ b/tests/ref/fate/filter-framepack-tab
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x576
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0x0b6b13ed
 0,          1,          1,        1,   304128, 0x406bcaa2
 0,          2,          2,        1,   304128, 0xb0deeca3
diff --git a/tests/ref/fate/filter-gradfun b/tests/ref/fate/filter-gradfun
index 794fae9..cadb9cb 100644
--- a/tests/ref/fate/filter-gradfun
+++ b/tests/ref/fate/filter-gradfun
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xaebf898f
 0,          1,          1,        1,   152064, 0x217b6560
 0,          2,          2,        1,   152064, 0x0269f62d
diff --git a/tests/ref/fate/filter-gradfun-sample b/tests/ref/fate/filter-gradfun-sample
index 595f82a..e6e2dc8 100644
--- a/tests/ref/fate/filter-gradfun-sample
+++ b/tests/ref/fate/filter-gradfun-sample
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,    76800, 0xea62ab65
 0,          1,          1,        1,    76800, 0xbc0d8b58
 0,          2,          2,        1,    76800, 0x682967d0
diff --git a/tests/ref/fate/filter-histogram-levels b/tests/ref/fate/filter-histogram-levels
index bd268ca..697d7d1 100644
--- a/tests/ref/fate/filter-histogram-levels
+++ b/tests/ref/fate/filter-histogram-levels
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x636
+#sar 0: 1/1
 0,          0,          0,        1,   488448, 0xc27a6cac
 0,          1,          1,        1,   488448, 0xf00a152e
 0,          2,          2,        1,   488448, 0x060b8c70
diff --git a/tests/ref/fate/filter-hls b/tests/ref/fate/filter-hls
new file mode 100644
index 0000000..47bc514
--- /dev/null
+++ b/tests/ref/fate/filter-hls
@@ -0,0 +1,772 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 4
+0,          0,          0,     1152,     2304, 0x907cb7fa
+0,       1152,       1152,     1152,     2304, 0xb8dc7525
+0,       2304,       2304,     1152,     2304, 0x3e7d6905
+0,       3456,       3456,     1152,     2304, 0xef47877b
+0,       4608,       4608,     1152,     2304, 0xfe916b7e
+0,       5760,       5760,     1152,     2304, 0xe3d08cde
+0,       6912,       6912,     1152,     2304, 0xff7f86cf
+0,       8064,       8064,     1152,     2304, 0x843e6f95
+0,       9216,       9216,     1152,     2304, 0x81577c26
+0,      10368,      10368,     1152,     2304, 0x04a085d5
+0,      11520,      11520,     1152,     2304, 0x1c5a76f5
+0,      12672,      12672,     1152,     2304, 0x4ee78623
+0,      13824,      13824,     1152,     2304, 0x8ec861dc
+0,      14976,      14976,     1152,     2304, 0x0ca179d8
+0,      16128,      16128,     1152,     2304, 0xc6da750f
+0,      17280,      17280,     1152,     2304, 0xf6bf79b5
+0,      18432,      18432,     1152,     2304, 0x97b88a43
+0,      19584,      19584,     1152,     2304, 0xf13c7b9c
+0,      20736,      20736,     1152,     2304, 0xdfba83af
+0,      21888,      21888,     1152,     2304, 0xc9467d4b
+0,      23040,      23040,     1152,     2304, 0xbbb58e2b
+0,      24192,      24192,     1152,     2304, 0x3a1078ea
+0,      25344,      25344,     1152,     2304, 0xe9587a5c
+0,      26496,      26496,     1152,     2304, 0xef5a8039
+0,      27648,      27648,     1152,     2304, 0x9d5f782f
+0,      28800,      28800,     1152,     2304, 0x1a548291
+0,      29952,      29952,     1152,     2304, 0x07517701
+0,      31104,      31104,     1152,     2304, 0x78127d6e
+0,      32256,      32256,     1152,     2304, 0x62e2788a
+0,      33408,      33408,     1152,     2304, 0x29397ad9
+0,      34560,      34560,     1152,     2304, 0x45da82d6
+0,      35712,      35712,     1152,     2304, 0x8ed66e51
+0,      36864,      36864,     1152,     2304, 0x660775cd
+0,      38016,      38016,     1152,     2304, 0x802c767a
+0,      39168,      39168,     1152,     2304, 0xcc055840
+0,      40320,      40320,     1152,     2304, 0x701b7eaf
+0,      41472,      41472,     1152,     2304, 0x8290749f
+0,      42624,      42624,     1152,     2304, 0x2c7b7d30
+0,      43776,      43776,     1152,     2304, 0xe4f17743
+0,      44928,      44928,     1152,     2304, 0x0e747d6e
+0,      46080,      46080,     1152,     2304, 0xbe7775a0
+0,      47232,      47232,     1152,     2304, 0xcf797673
+0,      48384,      48384,     1152,     2304, 0x29cb7800
+0,      49536,      49536,     1152,     2304, 0xfc947890
+0,      50688,      50688,     1152,     2304, 0x62757fc6
+0,      51840,      51840,     1152,     2304, 0x098876d0
+0,      52992,      52992,     1152,     2304, 0xa9567ee2
+0,      54144,      54144,     1152,     2304, 0xe3bb9173
+0,      55296,      55296,     1152,     2304, 0xcc2d6dee
+0,      56448,      56448,     1152,     2304, 0xe94591ab
+0,      57600,      57600,     1152,     2304, 0x5c7588de
+0,      58752,      58752,     1152,     2304, 0xfd83643c
+0,      59904,      59904,     1152,     2304, 0x528177f1
+0,      61056,      61056,     1152,     2304, 0x65d08474
+0,      62208,      62208,     1152,     2304, 0x738d765b
+0,      63360,      63360,     1152,     2304, 0xdd3d810e
+0,      64512,      64512,     1152,     2304, 0xef4f90d3
+0,      65664,      65664,     1152,     2304, 0x61e28d43
+0,      66816,      66816,     1152,     2304, 0x9a11796b
+0,      67968,      67968,     1152,     2304, 0x96c97dcd
+0,      69120,      69120,     1152,     2304, 0xa8fe8621
+0,      70272,      70272,     1152,     2304, 0x499b7d38
+0,      71424,      71424,     1152,     2304, 0xfcb078a9
+0,      72576,      72576,     1152,     2304, 0x40d78651
+0,      73728,      73728,     1152,     2304, 0xa4af7234
+0,      74880,      74880,     1152,     2304, 0x6831870a
+0,      76032,      76032,     1152,     2304, 0x030e7b9d
+0,      77184,      77184,     1152,     2304, 0x445a75b6
+0,      78336,      78336,     1152,     2304, 0x09857389
+0,      79488,      79488,     1152,     2304, 0x0d018866
+0,      80640,      80640,     1152,     2304, 0x2afe810a
+0,      81792,      81792,     1152,     2304, 0x0bcf7c43
+0,      82944,      82944,     1152,     2304, 0x13737c12
+0,      84096,      84096,     1152,     2304, 0x716c7bba
+0,      85248,      85248,     1152,     2304, 0xb801823b
+0,      86400,      86400,     1152,     2304, 0x0fd573ee
+0,      87552,      87552,     1152,     2304, 0xe1ab879c
+0,      88704,      88704,     1152,     2304, 0x49e6764f
+0,      89856,      89856,     1152,     2304, 0xd5f26ddc
+0,      91008,      91008,     1152,     2304, 0x076775ff
+0,      92160,      92160,     1152,     2304, 0xfbb86fce
+0,      93312,      93312,     1152,     2304, 0x20c56858
+0,      94464,      94464,     1152,     2304, 0x043e6891
+0,      95616,      95616,     1152,     2304, 0x59648729
+0,      96768,      96768,     1152,     2304, 0xd4907a63
+0,      97920,      97920,     1152,     2304, 0xd0208a4c
+0,      99072,      99072,     1152,     2304, 0xce968383
+0,     100224,     100224,     1152,     2304, 0x3cfc7cd1
+0,     101376,     101376,     1152,     2304, 0x628a7bf5
+0,     102528,     102528,     1152,     2304, 0x9cfe8a4f
+0,     103680,     103680,     1152,     2304, 0xdf6f7c6d
+0,     104832,     104832,     1152,     2304, 0x6cf6882a
+0,     105984,     105984,     1152,     2304, 0x099773a3
+0,     107136,     107136,     1152,     2304, 0x4a1c7649
+0,     108288,     108288,     1152,     2304, 0x31ea71cb
+0,     109440,     109440,     1152,     2304, 0xed127ed9
+0,     110592,     110592,     1152,     2304, 0x5b156954
+0,     111744,     111744,     1152,     2304, 0xdd638532
+0,     112896,     112896,     1152,     2304, 0xf1a271f2
+0,     114048,     114048,     1152,     2304, 0x779184d7
+0,     115200,     115200,     1152,     2304, 0x49a88aa8
+0,     116352,     116352,     1152,     2304, 0xa11b7c90
+0,     117504,     117504,     1152,     2304, 0xbf488274
+0,     118656,     118656,     1152,     2304, 0x002f79a8
+0,     119808,     119808,     1152,     2304, 0x0ed97e2f
+0,     120960,     120960,     1152,     2304, 0x7845878f
+0,     122112,     122112,     1152,     2304, 0x46d777dc
+0,     123264,     123264,     1152,     2304, 0x8d0179e3
+0,     124416,     124416,     1152,     2304, 0x38917f9f
+0,     125568,     125568,     1152,     2304, 0x449876e7
+0,     126720,     126720,     1152,     2304, 0x001a8769
+0,     127872,     127872,     1152,     2304, 0x06c1826b
+0,     129024,     129024,     1152,     2304, 0x41b68047
+0,     130176,     130176,     1152,     2304, 0xeb9782c6
+0,     131328,     131328,     1152,     2304, 0x7cd9719c
+0,     132480,     132480,     1152,     2304, 0x3a4a767c
+0,     133632,     133632,     1152,     2304, 0x7f887e81
+0,     134784,     134784,     1152,     2304, 0xf75d714b
+0,     135936,     135936,     1152,     2304, 0x33b57e9f
+0,     137088,     137088,     1152,     2304, 0xc732749e
+0,     138240,     138240,     1152,     2304, 0x386f7e1a
+0,     139392,     139392,     1152,     2304, 0x6b9c767d
+0,     140544,     140544,     1152,     2304, 0x701c83e5
+0,     141696,     141696,     1152,     2304, 0xb92571e1
+0,     142848,     142848,     1152,     2304, 0x833a84bc
+0,     144000,     144000,     1152,     2304, 0x1b6984e0
+0,     145152,     145152,     1152,     2304, 0x1b2474ba
+0,     146304,     146304,     1152,     2304, 0xc22775a6
+0,     147456,     147456,     1152,     2304, 0x3e8f7972
+0,     148608,     148608,     1152,     2304, 0x17a28a65
+0,     149760,     149760,     1152,     2304, 0x9b6178a4
+0,     150912,     150912,     1152,     2304, 0x5d707873
+0,     152064,     152064,     1152,     2304, 0x68e2645a
+0,     153216,     153216,     1152,     2304, 0x1e377d28
+0,     154368,     154368,     1152,     2304, 0x54b384be
+0,     155520,     155520,     1152,     2304, 0x0617808c
+0,     156672,     156672,     1152,     2304, 0xbc2b8a6c
+0,     157824,     157824,     1152,     2304, 0x7ced7180
+0,     158976,     158976,     1152,     2304, 0xf22180ab
+0,     160128,     160128,     1152,     2304, 0xf13682c9
+0,     161280,     161280,     1152,     2304, 0x7eff87fd
+0,     162432,     162432,     1152,     2304, 0x5a0b5cec
+0,     163584,     163584,     1152,     2304, 0x57c18906
+0,     164736,     164736,     1152,     2304, 0xb55a6a16
+0,     165888,     165888,     1152,     2304, 0xf2608371
+0,     167040,     167040,     1152,     2304, 0x36df7576
+0,     168192,     168192,     1152,     2304, 0xdb106fb4
+0,     169344,     169344,     1152,     2304, 0x7e4f85d0
+0,     170496,     170496,     1152,     2304, 0xe3ee78ab
+0,     171648,     171648,     1152,     2304, 0xd36b7dc7
+0,     172800,     172800,     1152,     2304, 0xadab7c5c
+0,     173952,     173952,     1152,     2304, 0x70786f26
+0,     175104,     175104,     1152,     2304, 0xcd5d717e
+0,     176256,     176256,     1152,     2304, 0xc1a96f9a
+0,     177408,     177408,     1152,     2304, 0xad777887
+0,     178560,     178560,     1152,     2304, 0x98277c16
+0,     179712,     179712,     1152,     2304, 0x868882c5
+0,     180864,     180864,     1152,     2304, 0xc48092b9
+0,     182016,     182016,     1152,     2304, 0x230069da
+0,     183168,     183168,     1152,     2304, 0x14147ad6
+0,     184320,     184320,     1152,     2304, 0xc9007172
+0,     185472,     185472,     1152,     2304, 0x85d67bcc
+0,     186624,     186624,     1152,     2304, 0x22418bab
+0,     187776,     187776,     1152,     2304, 0xe53c8b71
+0,     188928,     188928,     1152,     2304, 0x5a1a9053
+0,     190080,     190080,     1152,     2304, 0x9cd179af
+0,     191232,     191232,     1152,     2304, 0xbb3c7d72
+0,     192384,     192384,     1152,     2304, 0x477a8677
+0,     193536,     193536,     1152,     2304, 0xe3337834
+0,     194688,     194688,     1152,     2304, 0x1cb56d77
+0,     195840,     195840,     1152,     2304, 0xe89d6dac
+0,     196992,     196992,     1152,     2304, 0xd468827e
+0,     198144,     198144,     1152,     2304, 0xebc46b87
+0,     199296,     199296,     1152,     2304, 0x5fbb78d2
+0,     200448,     200448,     1152,     2304, 0xa1b483d6
+0,     201600,     201600,     1152,     2304, 0x6fec7cab
+0,     202752,     202752,     1152,     2304, 0xd86d6f6c
+0,     203904,     203904,     1152,     2304, 0x8c2c7d51
+0,     205056,     205056,     1152,     2304, 0xe8377cd7
+0,     206208,     206208,     1152,     2304, 0xb57071b4
+0,     207360,     207360,     1152,     2304, 0xc35c71fd
+0,     208512,     208512,     1152,     2304, 0x789079e9
+0,     209664,     209664,     1152,     2304, 0x413b710e
+0,     210816,     210816,     1152,     2304, 0x82678332
+0,     211968,     211968,     1152,     2304, 0xe1576e75
+0,     213120,     213120,     1152,     2304, 0x7c0b7ad6
+0,     214272,     214272,     1152,     2304, 0xc6b6786d
+0,     215424,     215424,     1152,     2304, 0x736f7b89
+0,     216576,     216576,     1152,     2304, 0x0ded72f1
+0,     217728,     217728,     1152,     2304, 0xcb877a3c
+0,     218880,     218880,     1152,     2304, 0x7c497d40
+0,     220032,     220032,     1152,     2304, 0xaefc798c
+0,     221184,     221184,     1152,     2304, 0x4cce748c
+0,     222336,     222336,     1152,     2304, 0xaa187fbe
+0,     223488,     223488,     1152,     2304, 0x1aa77db9
+0,     224640,     224640,     1152,     2304, 0x9e0074b8
+0,     225792,     225792,     1152,     2304, 0x74ee822b
+0,     226944,     226944,     1152,     2304, 0x975c6ff6
+0,     228096,     228096,     1152,     2304, 0xe1847bb4
+0,     229248,     229248,     1152,     2304, 0xe0828777
+0,     230400,     230400,     1152,     2304, 0xf4027205
+0,     231552,     231552,     1152,     2304, 0x535e7a20
+0,     232704,     232704,     1152,     2304, 0x5bd88404
+0,     233856,     233856,     1152,     2304, 0xf29478b1
+0,     235008,     235008,     1152,     2304, 0x9b7c7d88
+0,     236160,     236160,     1152,     2304, 0xaeb07335
+0,     237312,     237312,     1152,     2304, 0xbef06e08
+0,     238464,     238464,     1152,     2304, 0x795f7b8c
+0,     239616,     239616,     1152,     2304, 0x435a674d
+0,     240768,     240768,     1152,     2304, 0xd8ee7a09
+0,     241920,     241920,     1152,     2304, 0x9059812e
+0,     243072,     243072,     1152,     2304, 0x7481744a
+0,     244224,     244224,     1152,     2304, 0xdff27475
+0,     245376,     245376,     1152,     2304, 0xb17783ab
+0,     246528,     246528,     1152,     2304, 0x42e9706b
+0,     247680,     247680,     1152,     2304, 0x9f0d86b4
+0,     248832,     248832,     1152,     2304, 0x2963955f
+0,     249984,     249984,     1152,     2304, 0x059a6957
+0,     251136,     251136,     1152,     2304, 0x85948206
+0,     252288,     252288,     1152,     2304, 0x185e8400
+0,     253440,     253440,     1152,     2304, 0xe98e70df
+0,     254592,     254592,     1152,     2304, 0x69057b27
+0,     255744,     255744,     1152,     2304, 0x49e26f21
+0,     256896,     256896,     1152,     2304, 0xb0867da5
+0,     258048,     258048,     1152,     2304, 0x785980ff
+0,     259200,     259200,     1152,     2304, 0xf4b774be
+0,     260352,     260352,     1152,     2304, 0x63897e8c
+0,     261504,     261504,     1152,     2304, 0x248b89af
+0,     262656,     262656,     1152,     2304, 0xd3627c4a
+0,     263808,     263808,     1152,     2304, 0x5a4d9349
+0,     264960,     264960,     1152,     2304, 0xe2ce7c4c
+0,     266112,     266112,     1152,     2304, 0x321f6c0b
+0,     267264,     267264,     1152,     2304, 0x51ac74e0
+0,     268416,     268416,     1152,     2304, 0x8efa91ba
+0,     269568,     269568,     1152,     2304, 0x8b4b784c
+0,     270720,     270720,     1152,     2304, 0xe9e4879e
+0,     271872,     271872,     1152,     2304, 0x8dc28081
+0,     273024,     273024,     1152,     2304, 0x44b477b0
+0,     274176,     274176,     1152,     2304, 0xf7b67084
+0,     275328,     275328,     1152,     2304, 0x4b198c17
+0,     276480,     276480,     1152,     2304, 0x9c947194
+0,     277632,     277632,     1152,     2304, 0x6eaa7f15
+0,     278784,     278784,     1152,     2304, 0x119f7c1d
+0,     279936,     279936,     1152,     2304, 0x157b7f43
+0,     281088,     281088,     1152,     2304, 0xcd2e7acc
+0,     282240,     282240,     1152,     2304, 0x97597247
+0,     283392,     283392,     1152,     2304, 0x7ba06acb
+0,     284544,     284544,     1152,     2304, 0x233c7995
+0,     285696,     285696,     1152,     2304, 0x08e28587
+0,     286848,     286848,     1152,     2304, 0x92be84b5
+0,     288000,     288000,     1152,     2304, 0xbb857d43
+0,     289152,     289152,     1152,     2304, 0x168e7c74
+0,     290304,     290304,     1152,     2304, 0xac5465d9
+0,     291456,     291456,     1152,     2304, 0x18f58831
+0,     292608,     292608,     1152,     2304, 0x19b48196
+0,     293760,     293760,     1152,     2304, 0x20297653
+0,     294912,     294912,     1152,     2304, 0x93397a82
+0,     296064,     296064,     1152,     2304, 0x65ea7deb
+0,     297216,     297216,     1152,     2304, 0xd7316e20
+0,     298368,     298368,     1152,     2304, 0x94107f2b
+0,     299520,     299520,     1152,     2304, 0xec3b7dc6
+0,     300672,     300672,     1152,     2304, 0x2d3783aa
+0,     301824,     301824,     1152,     2304, 0x07e47340
+0,     302976,     302976,     1152,     2304, 0xbc117893
+0,     304128,     304128,     1152,     2304, 0x8bd97851
+0,     305280,     305280,     1152,     2304, 0xc27376a9
+0,     306432,     306432,     1152,     2304, 0x30d88c83
+0,     307584,     307584,     1152,     2304, 0x19c2704c
+0,     308736,     308736,     1152,     2304, 0x093b7b6e
+0,     309888,     309888,     1152,     2304, 0x221a7349
+0,     311040,     311040,     1152,     2304, 0xa4fd82cd
+0,     312192,     312192,     1152,     2304, 0x762e6bc9
+0,     313344,     313344,     1152,     2304, 0x270075d4
+0,     314496,     314496,     1152,     2304, 0xa5f27b90
+0,     315648,     315648,     1152,     2304, 0xf72e7edc
+0,     316800,     316800,     1152,     2304, 0x42178486
+0,     317952,     317952,     1152,     2304, 0x5f7978e8
+0,     319104,     319104,     1152,     2304, 0x5d7c6703
+0,     320256,     320256,     1152,     2304, 0x2c4483d5
+0,     321408,     321408,     1152,     2304, 0x31bd951d
+0,     322560,     322560,     1152,     2304, 0x99487af0
+0,     323712,     323712,     1152,     2304, 0x0bd27ee7
+0,     324864,     324864,     1152,     2304, 0xc3e07ac4
+0,     326016,     326016,     1152,     2304, 0x98a16ba7
+0,     327168,     327168,     1152,     2304, 0xd7a5747b
+0,     328320,     328320,     1152,     2304, 0x96fb811c
+0,     329472,     329472,     1152,     2304, 0x7cee8109
+0,     330624,     330624,     1152,     2304, 0x52b18ba2
+0,     331776,     331776,     1152,     2304, 0x33be8861
+0,     332928,     332928,     1152,     2304, 0xf41282a0
+0,     334080,     334080,     1152,     2304, 0xb4268993
+0,     335232,     335232,     1152,     2304, 0x52126a1c
+0,     336384,     336384,     1152,     2304, 0x050b6f7a
+0,     337536,     337536,     1152,     2304, 0x67a26fc3
+0,     338688,     338688,     1152,     2304, 0x966c7cf2
+0,     339840,     339840,     1152,     2304, 0x22097750
+0,     340992,     340992,     1152,     2304, 0xfbb0796c
+0,     342144,     342144,     1152,     2304, 0xbd508964
+0,     343296,     343296,     1152,     2304, 0xc24478d8
+0,     344448,     344448,     1152,     2304, 0x3913769d
+0,     345600,     345600,     1152,     2304, 0x8aab872f
+0,     346752,     346752,     1152,     2304, 0x7cb4822f
+0,     347904,     347904,     1152,     2304, 0xea318144
+0,     349056,     349056,     1152,     2304, 0xaf0f86d2
+0,     350208,     350208,     1152,     2304, 0x24f27598
+0,     351360,     351360,     1152,     2304, 0xd76f6d40
+0,     352512,     352512,     1152,     2304, 0x085071a7
+0,     353664,     353664,     1152,     2304, 0x1d11704c
+0,     354816,     354816,     1152,     2304, 0x21517cbd
+0,     355968,     355968,     1152,     2304, 0xcdca8d32
+0,     357120,     357120,     1152,     2304, 0x71c18433
+0,     358272,     358272,     1152,     2304, 0xd39d7d81
+0,     359424,     359424,     1152,     2304, 0x7a0d7a43
+0,     360576,     360576,     1152,     2304, 0x007c8884
+0,     361728,     361728,     1152,     2304, 0x403282d0
+0,     362880,     362880,     1152,     2304, 0xe3737214
+0,     364032,     364032,     1152,     2304, 0xaf906f47
+0,     365184,     365184,     1152,     2304, 0x54f57b3b
+0,     366336,     366336,     1152,     2304, 0x29be7791
+0,     367488,     367488,     1152,     2304, 0xe3c663d5
+0,     368640,     368640,     1152,     2304, 0xd7258238
+0,     369792,     369792,     1152,     2304, 0x3719820d
+0,     370944,     370944,     1152,     2304, 0xbe04814f
+0,     372096,     372096,     1152,     2304, 0x556c815e
+0,     373248,     373248,     1152,     2304, 0xb2447e10
+0,     374400,     374400,     1152,     2304, 0x7c16867c
+0,     375552,     375552,     1152,     2304, 0x6a7b78ed
+0,     376704,     376704,     1152,     2304, 0x5d307b81
+0,     377856,     377856,     1152,     2304, 0xaab680d3
+0,     379008,     379008,     1152,     2304, 0xb5d37a23
+0,     380160,     380160,     1152,     2304, 0x7f7d6f76
+0,     381312,     381312,     1152,     2304, 0x317a8296
+0,     382464,     382464,     1152,     2304, 0x8a987b3d
+0,     383616,     383616,     1152,     2304, 0x4f317a27
+0,     384768,     384768,     1152,     2304, 0xfc65852f
+0,     385920,     385920,     1152,     2304, 0x40527719
+0,     387072,     387072,     1152,     2304, 0x84988e13
+0,     388224,     388224,     1152,     2304, 0x318b6ddc
+0,     389376,     389376,     1152,     2304, 0x94cf7939
+0,     390528,     390528,     1152,     2304, 0x6f22819d
+0,     391680,     391680,     1152,     2304, 0xa7dd80a9
+0,     392832,     392832,     1152,     2304, 0x1c7968fa
+0,     393984,     393984,     1152,     2304, 0xd9937bae
+0,     395136,     395136,     1152,     2304, 0xf7137cf9
+0,     396288,     396288,     1152,     2304, 0xeadb84b5
+0,     397440,     397440,     1152,     2304, 0x9a2390ac
+0,     398592,     398592,     1152,     2304, 0xdb6a73f6
+0,     399744,     399744,     1152,     2304, 0x69e07507
+0,     400896,     400896,     1152,     2304, 0xbc8478b2
+0,     402048,     402048,     1152,     2304, 0x32cf8638
+0,     403200,     403200,     1152,     2304, 0x2b8d755a
+0,     404352,     404352,     1152,     2304, 0x52e05bd2
+0,     405504,     405504,     1152,     2304, 0x2aed8c49
+0,     406656,     406656,     1152,     2304, 0x587a896e
+0,     407808,     407808,     1152,     2304, 0x6dd87dee
+0,     408960,     408960,     1152,     2304, 0xd2858338
+0,     410112,     410112,     1152,     2304, 0xd90f7842
+0,     411264,     411264,     1152,     2304, 0xd6fb6d4a
+0,     412416,     412416,     1152,     2304, 0x85498aea
+0,     413568,     413568,     1152,     2304, 0x18597790
+0,     414720,     414720,     1152,     2304, 0x3cd78fea
+0,     415872,     415872,     1152,     2304, 0x94377fbc
+0,     417024,     417024,     1152,     2304, 0xf9db73f5
+0,     418176,     418176,     1152,     2304, 0x14fb6fca
+0,     419328,     419328,     1152,     2304, 0xe9d17d69
+0,     420480,     420480,     1152,     2304, 0xdeb57286
+0,     421632,     421632,     1152,     2304, 0xa5d37e17
+0,     422784,     422784,     1152,     2304, 0xcf6882fb
+0,     423936,     423936,     1152,     2304, 0x31758066
+0,     425088,     425088,     1152,     2304, 0x6b4d8175
+0,     426240,     426240,     1152,     2304, 0x2a3d7f8e
+0,     427392,     427392,     1152,     2304, 0xc066743b
+0,     428544,     428544,     1152,     2304, 0xcab88146
+0,     429696,     429696,     1152,     2304, 0x2b4c6e13
+0,     430848,     430848,     1152,     2304, 0x00b36b6f
+0,     432000,     432000,     1152,     2304, 0x664a88d3
+0,     433152,     433152,     1152,     2304, 0x18a66f76
+0,     434304,     434304,     1152,     2304, 0x4f828a8b
+0,     435456,     435456,     1152,     2304, 0x9cc7728e
+0,     436608,     436608,     1152,     2304, 0xbe357936
+0,     437760,     437760,     1152,     2304, 0x19878f8d
+0,     438912,     438912,     1152,     2304, 0x227b7c71
+0,     440064,     440064,     1152,     2304, 0xf7c879ec
+0,     441216,     441216,     1152,     2304, 0x0bca7b50
+0,     442368,     442368,     1152,     2304, 0xe4398304
+0,     443520,     443520,     1152,     2304, 0xf5da75c7
+0,     444672,     444672,     1152,     2304, 0x9f9070a3
+0,     445824,     445824,     1152,     2304, 0x789076f6
+0,     446976,     446976,     1152,     2304, 0x362977cc
+0,     448128,     448128,     1152,     2304, 0x4d0a8928
+0,     449280,     449280,     1152,     2304, 0x1bb767ec
+0,     450432,     450432,     1152,     2304, 0xbe727fa5
+0,     451584,     451584,     1152,     2304, 0x27f38347
+0,     452736,     452736,     1152,     2304, 0x0a3c8783
+0,     453888,     453888,     1152,     2304, 0x8249639c
+0,     455040,     455040,     1152,     2304, 0x3b076f69
+0,     456192,     456192,     1152,     2304, 0xd9597ee3
+0,     457344,     457344,     1152,     2304, 0x026e7fad
+0,     458496,     458496,     1152,     2304, 0xbd7a6de4
+0,     459648,     459648,     1152,     2304, 0x7d718a4d
+0,     460800,     460800,     1152,     2304, 0x1f5e83b4
+0,     461952,     461952,     1152,     2304, 0x597d7755
+0,     463104,     463104,     1152,     2304, 0x3fb080bd
+0,     464256,     464256,     1152,     2304, 0xdcbd7b16
+0,     465408,     465408,     1152,     2304, 0x5c48865f
+0,     466560,     466560,     1152,     2304, 0xcda37ae8
+0,     467712,     467712,     1152,     2304, 0x4810796d
+0,     468864,     468864,     1152,     2304, 0x34317fd0
+0,     470016,     470016,     1152,     2304, 0x5c0e7456
+0,     471168,     471168,     1152,     2304, 0x44d78040
+0,     472320,     472320,     1152,     2304, 0x88587882
+0,     473472,     473472,     1152,     2304, 0x77687d5e
+0,     474624,     474624,     1152,     2304, 0x116d68bb
+0,     475776,     475776,     1152,     2304, 0x3e5b6f60
+0,     476928,     476928,     1152,     2304, 0x64ea783c
+0,     478080,     478080,     1152,     2304, 0x23547f7d
+0,     479232,     479232,     1152,     2304, 0x2eee7892
+0,     480384,     480384,     1152,     2304, 0xfb837cba
+0,     481536,     481536,     1152,     2304, 0x86518209
+0,     482688,     482688,     1152,     2304, 0x672f7bba
+0,     483840,     483840,     1152,     2304, 0x6ab583fb
+0,     484992,     484992,     1152,     2304, 0xc1297428
+0,     486144,     486144,     1152,     2304, 0x164e7717
+0,     487296,     487296,     1152,     2304, 0xb754976d
+0,     488448,     488448,     1152,     2304, 0xb99d81b2
+0,     489600,     489600,     1152,     2304, 0x79046fd6
+0,     490752,     490752,     1152,     2304, 0x9a3f8426
+0,     491904,     491904,     1152,     2304, 0x896371f5
+0,     493056,     493056,     1152,     2304, 0x63d1799f
+0,     494208,     494208,     1152,     2304, 0x4842844e
+0,     495360,     495360,     1152,     2304, 0x850e8372
+0,     496512,     496512,     1152,     2304, 0x85d07022
+0,     497664,     497664,     1152,     2304, 0x9e6683d1
+0,     498816,     498816,     1152,     2304, 0x301b8981
+0,     499968,     499968,     1152,     2304, 0x1f1e98c5
+0,     501120,     501120,     1152,     2304, 0xc8797b03
+0,     502272,     502272,     1152,     2304, 0xf9d189f5
+0,     503424,     503424,     1152,     2304, 0x0e0d88be
+0,     504576,     504576,     1152,     2304, 0x6c1d7843
+0,     505728,     505728,     1152,     2304, 0xd13b8a38
+0,     506880,     506880,     1152,     2304, 0x9b8f773c
+0,     508032,     508032,     1152,     2304, 0x9acd7309
+0,     509184,     509184,     1152,     2304, 0x5e7d7d15
+0,     510336,     510336,     1152,     2304, 0xf09d7640
+0,     511488,     511488,     1152,     2304, 0xaebb718f
+0,     512640,     512640,     1152,     2304, 0x0c8570f4
+0,     513792,     513792,     1152,     2304, 0x3c93862c
+0,     514944,     514944,     1152,     2304, 0xcee46696
+0,     516096,     516096,     1152,     2304, 0x01ba7e20
+0,     517248,     517248,     1152,     2304, 0x7fcb7a09
+0,     518400,     518400,     1152,     2304, 0xddf18c14
+0,     519552,     519552,     1152,     2304, 0xd2e97eeb
+0,     520704,     520704,     1152,     2304, 0x514d8719
+0,     521856,     521856,     1152,     2304, 0xe89279c9
+0,     523008,     523008,     1152,     2304, 0x806d6a95
+0,     524160,     524160,     1152,     2304, 0xbc7a8a60
+0,     525312,     525312,     1152,     2304, 0x302f8fa8
+0,     526464,     526464,     1152,     2304, 0xb136784c
+0,     527616,     527616,     1152,     2304, 0x9b0f6aab
+0,     528768,     528768,     1152,     2304, 0xd8e27582
+0,     529920,     529920,     1152,     2304, 0xdaaf78b1
+0,     531072,     531072,     1152,     2304, 0x65967f5f
+0,     532224,     532224,     1152,     2304, 0x6f917aa4
+0,     533376,     533376,     1152,     2304, 0x7f607444
+0,     534528,     534528,     1152,     2304, 0xfd316f2c
+0,     535680,     535680,     1152,     2304, 0x776e83c7
+0,     536832,     536832,     1152,     2304, 0xb9c17e16
+0,     537984,     537984,     1152,     2304, 0xdf287de8
+0,     539136,     539136,     1152,     2304, 0xf33d96a3
+0,     540288,     540288,     1152,     2304, 0xad216e5b
+0,     541440,     541440,     1152,     2304, 0x4a328342
+0,     542592,     542592,     1152,     2304, 0xcf3f8079
+0,     543744,     543744,     1152,     2304, 0xb46f77b0
+0,     544896,     544896,     1152,     2304, 0x3199713d
+0,     546048,     546048,     1152,     2304, 0x5e667a0d
+0,     547200,     547200,     1152,     2304, 0xa3047ae3
+0,     548352,     548352,     1152,     2304, 0x9edf8594
+0,     549504,     549504,     1152,     2304, 0xd16382d5
+0,     550656,     550656,     1152,     2304, 0x6e838328
+0,     551808,     551808,     1152,     2304, 0xa1f697c1
+0,     552960,     552960,     1152,     2304, 0xefcc749c
+0,     554112,     554112,     1152,     2304, 0x1f94839e
+0,     555264,     555264,     1152,     2304, 0x429e7c5b
+0,     556416,     556416,     1152,     2304, 0x9b59711c
+0,     557568,     557568,     1152,     2304, 0xdac27323
+0,     558720,     558720,     1152,     2304, 0xa4856d2b
+0,     559872,     559872,     1152,     2304, 0x07a37498
+0,     561024,     561024,     1152,     2304, 0xe1ce7512
+0,     562176,     562176,     1152,     2304, 0x15e182c3
+0,     563328,     563328,     1152,     2304, 0x0fa46b8c
+0,     564480,     564480,     1152,     2304, 0xbdf07bfd
+0,     565632,     565632,     1152,     2304, 0xe0238b2a
+0,     566784,     566784,     1152,     2304, 0xab537267
+0,     567936,     567936,     1152,     2304, 0xd46b75f3
+0,     569088,     569088,     1152,     2304, 0xec73794b
+0,     570240,     570240,     1152,     2304, 0x680580c1
+0,     571392,     571392,     1152,     2304, 0x1ace8f6c
+0,     572544,     572544,     1152,     2304, 0x19d583ac
+0,     573696,     573696,     1152,     2304, 0x4b6b8105
+0,     574848,     574848,     1152,     2304, 0x392a78b2
+0,     576000,     576000,     1152,     2304, 0xd3916dad
+0,     577152,     577152,     1152,     2304, 0x569c7a75
+0,     578304,     578304,     1152,     2304, 0xf5ac814b
+0,     579456,     579456,     1152,     2304, 0x18d77e98
+0,     580608,     580608,     1152,     2304, 0x007074ce
+0,     581760,     581760,     1152,     2304, 0x0fe38373
+0,     582912,     582912,     1152,     2304, 0x5a967920
+0,     584064,     584064,     1152,     2304, 0x22167501
+0,     585216,     585216,     1152,     2304, 0xf0828cab
+0,     586368,     586368,     1152,     2304, 0xaeec71b7
+0,     587520,     587520,     1152,     2304, 0xc47b62ff
+0,     588672,     588672,     1152,     2304, 0xab688478
+0,     589824,     589824,     1152,     2304, 0xf35e7bd2
+0,     590976,     590976,     1152,     2304, 0x9cff763e
+0,     592128,     592128,     1152,     2304, 0x59568dc8
+0,     593280,     593280,     1152,     2304, 0x51a278ac
+0,     594432,     594432,     1152,     2304, 0xc08a6e68
+0,     595584,     595584,     1152,     2304, 0xd3067ef4
+0,     596736,     596736,     1152,     2304, 0x54767c49
+0,     597888,     597888,     1152,     2304, 0xf8ff8386
+0,     599040,     599040,     1152,     2304, 0xef267f63
+0,     600192,     600192,     1152,     2304, 0xe2537cd9
+0,     601344,     601344,     1152,     2304, 0x77a57680
+0,     602496,     602496,     1152,     2304, 0x325c74ad
+0,     603648,     603648,     1152,     2304, 0xd7fe87c4
+0,     604800,     604800,     1152,     2304, 0x2e756310
+0,     605952,     605952,     1152,     2304, 0x6a81796b
+0,     607104,     607104,     1152,     2304, 0x2f057daf
+0,     608256,     608256,     1152,     2304, 0xcd9f7c9d
+0,     609408,     609408,     1152,     2304, 0xc91560a0
+0,     610560,     610560,     1152,     2304, 0x962a91eb
+0,     611712,     611712,     1152,     2304, 0xa0ff7416
+0,     612864,     612864,     1152,     2304, 0xcb5c7dff
+0,     614016,     614016,     1152,     2304, 0xd3527041
+0,     615168,     615168,     1152,     2304, 0xc89d77c2
+0,     616320,     616320,     1152,     2304, 0xe1ce7ccf
+0,     617472,     617472,     1152,     2304, 0xe3417c4c
+0,     618624,     618624,     1152,     2304, 0x3f1a7166
+0,     619776,     619776,     1152,     2304, 0xcdcc7e23
+0,     620928,     620928,     1152,     2304, 0x4e727e97
+0,     622080,     622080,     1152,     2304, 0x53427ff1
+0,     623232,     623232,     1152,     2304, 0x173f6ca9
+0,     624384,     624384,     1152,     2304, 0x962887ec
+0,     625536,     625536,     1152,     2304, 0xcbec67f4
+0,     626688,     626688,     1152,     2304, 0x7a2c943d
+0,     627840,     627840,     1152,     2304, 0x8b877570
+0,     628992,     628992,     1152,     2304, 0xcf337323
+0,     630144,     630144,     1152,     2304, 0x8c8682a4
+0,     631296,     631296,     1152,     2304, 0x94c3753c
+0,     632448,     632448,     1152,     2304, 0x86898d79
+0,     633600,     633600,     1152,     2304, 0xdf667312
+0,     634752,     634752,     1152,     2304, 0x062f8ba8
+0,     635904,     635904,     1152,     2304, 0xa2c36f08
+0,     637056,     637056,     1152,     2304, 0x5bca7358
+0,     638208,     638208,     1152,     2304, 0x5648804d
+0,     639360,     639360,     1152,     2304, 0xefac87c8
+0,     640512,     640512,     1152,     2304, 0x66bf7dcf
+0,     641664,     641664,     1152,     2304, 0x62ad73bc
+0,     642816,     642816,     1152,     2304, 0x72fe630c
+0,     643968,     643968,     1152,     2304, 0xeebe87da
+0,     645120,     645120,     1152,     2304, 0x11c870cf
+0,     646272,     646272,     1152,     2304, 0x18fb7c27
+0,     647424,     647424,     1152,     2304, 0x39047145
+0,     648576,     648576,     1152,     2304, 0xdcf07032
+0,     649728,     649728,     1152,     2304, 0x61027c50
+0,     650880,     650880,     1152,     2304, 0x6e2e89de
+0,     652032,     652032,     1152,     2304, 0xc50c6d1d
+0,     653184,     653184,     1152,     2304, 0xeed587ee
+0,     654336,     654336,     1152,     2304, 0xe38269c7
+0,     655488,     655488,     1152,     2304, 0xcf66806e
+0,     656640,     656640,     1152,     2304, 0x2d3b7c1b
+0,     657792,     657792,     1152,     2304, 0xa4127d48
+0,     658944,     658944,     1152,     2304, 0x480b8325
+0,     660096,     660096,     1152,     2304, 0xc1527221
+0,     661248,     661248,     1152,     2304, 0x94c1769a
+0,     662400,     662400,     1152,     2304, 0xcfb37271
+0,     663552,     663552,     1152,     2304, 0x946d7a96
+0,     664704,     664704,     1152,     2304, 0xdfc18e50
+0,     665856,     665856,     1152,     2304, 0x10c48393
+0,     667008,     667008,     1152,     2304, 0x58556b10
+0,     668160,     668160,     1152,     2304, 0x997b7993
+0,     669312,     669312,     1152,     2304, 0x4a787992
+0,     670464,     670464,     1152,     2304, 0x11406c20
+0,     671616,     671616,     1152,     2304, 0x04a4874a
+0,     672768,     672768,     1152,     2304, 0xf3077164
+0,     673920,     673920,     1152,     2304, 0x08ac80e3
+0,     675072,     675072,     1152,     2304, 0x268370d0
+0,     676224,     676224,     1152,     2304, 0x1d137778
+0,     677376,     677376,     1152,     2304, 0xfa148e97
+0,     678528,     678528,     1152,     2304, 0xec50717c
+0,     679680,     679680,     1152,     2304, 0xcbf46b75
+0,     680832,     680832,     1152,     2304, 0xd4168038
+0,     681984,     681984,     1152,     2304, 0xdd9577f0
+0,     683136,     683136,     1152,     2304, 0xc7077685
+0,     684288,     684288,     1152,     2304, 0x34d25e91
+0,     685440,     685440,     1152,     2304, 0x96537e6d
+0,     686592,     686592,     1152,     2304, 0xb12e7940
+0,     687744,     687744,     1152,     2304, 0x861d64c0
+0,     688896,     688896,     1152,     2304, 0xa2bc64ed
+0,     690048,     690048,     1152,     2304, 0x0c5f8261
+0,     691200,     691200,     1152,     2304, 0x540584ff
+0,     692352,     692352,     1152,     2304, 0xe8328b09
+0,     693504,     693504,     1152,     2304, 0x1e777079
+0,     694656,     694656,     1152,     2304, 0x453483b4
+0,     695808,     695808,     1152,     2304, 0x1cab7a1e
+0,     696960,     696960,     1152,     2304, 0xcb37856d
+0,     698112,     698112,     1152,     2304, 0x5a4883ed
+0,     699264,     699264,     1152,     2304, 0xd1f27cbf
+0,     700416,     700416,     1152,     2304, 0x0d377a4d
+0,     701568,     701568,     1152,     2304, 0x264e76df
+0,     702720,     702720,     1152,     2304, 0x2a68771e
+0,     703872,     703872,     1152,     2304, 0xcb317a31
+0,     705024,     705024,     1152,     2304, 0xfc5d7a27
+0,     706176,     706176,     1152,     2304, 0x6e067d96
+0,     707328,     707328,     1152,     2304, 0x0c538560
+0,     708480,     708480,     1152,     2304, 0xfbad717a
+0,     709632,     709632,     1152,     2304, 0xf9fc7608
+0,     710784,     710784,     1152,     2304, 0xb1817c8f
+0,     711936,     711936,     1152,     2304, 0x57c37f82
+0,     713088,     713088,     1152,     2304, 0x8cac8356
+0,     714240,     714240,     1152,     2304, 0x97108186
+0,     715392,     715392,     1152,     2304, 0x095d81bb
+0,     716544,     716544,     1152,     2304, 0x475f6b2b
+0,     717696,     717696,     1152,     2304, 0xdf7c8cc5
+0,     718848,     718848,     1152,     2304, 0x979c77be
+0,     720000,     720000,     1152,     2304, 0x56a7844b
+0,     721152,     721152,     1152,     2304, 0x7ee46b21
+0,     722304,     722304,     1152,     2304, 0x05b67220
+0,     723456,     723456,     1152,     2304, 0x25787252
+0,     724608,     724608,     1152,     2304, 0x8ad278ad
+0,     725760,     725760,     1152,     2304, 0x67bd722e
+0,     726912,     726912,     1152,     2304, 0x204f77be
+0,     728064,     728064,     1152,     2304, 0x82d27ae2
+0,     729216,     729216,     1152,     2304, 0x23fa82e4
+0,     730368,     730368,     1152,     2304, 0xa9cf8159
+0,     731520,     731520,     1152,     2304, 0x13f08749
+0,     732672,     732672,     1152,     2304, 0xf84f71b5
+0,     733824,     733824,     1152,     2304, 0x1cb777c8
+0,     734976,     734976,     1152,     2304, 0x11236722
+0,     736128,     736128,     1152,     2304, 0x10197cac
+0,     737280,     737280,     1152,     2304, 0xbd417e65
+0,     738432,     738432,     1152,     2304, 0x9a1c7d05
+0,     739584,     739584,     1152,     2304, 0x4c3a85de
+0,     740736,     740736,     1152,     2304, 0x03816eb7
+0,     741888,     741888,     1152,     2304, 0x80186e6c
+0,     743040,     743040,     1152,     2304, 0x5c097928
+0,     744192,     744192,     1152,     2304, 0x94aa823d
+0,     745344,     745344,     1152,     2304, 0xa1c27f04
+0,     746496,     746496,     1152,     2304, 0x6ddb74a9
+0,     747648,     747648,     1152,     2304, 0x5ea67901
+0,     748800,     748800,     1152,     2304, 0xd710742d
+0,     749952,     749952,     1152,     2304, 0xf8c27add
+0,     751104,     751104,     1152,     2304, 0xf1717011
+0,     752256,     752256,     1152,     2304, 0xb59072d0
+0,     753408,     753408,     1152,     2304, 0xc8dc84a7
+0,     754560,     754560,     1152,     2304, 0x33116737
+0,     755712,     755712,     1152,     2304, 0x86216bdd
+0,     756864,     756864,     1152,     2304, 0xa2f87866
+0,     758016,     758016,     1152,     2304, 0x5d77771e
+0,     759168,     759168,     1152,     2304, 0x5d8c77fd
+0,     760320,     760320,     1152,     2304, 0x23cc89cb
+0,     761472,     761472,     1152,     2304, 0x334e7407
+0,     762624,     762624,     1152,     2304, 0x01c976ff
+0,     763776,     763776,     1152,     2304, 0x3a3b7b15
+0,     764928,     764928,     1152,     2304, 0xfa427de9
+0,     766080,     766080,     1152,     2304, 0xbeaa7c91
+0,     767232,     767232,     1152,     2304, 0xd6988b31
+0,     768384,     768384,     1152,     2304, 0x4db47f80
+0,     769536,     769536,     1152,     2304, 0xea687d9e
+0,     770688,     770688,     1152,     2304, 0x1a6281ce
+0,     771840,     771840,     1152,     2304, 0xe1958003
+0,     772992,     772992,     1152,     2304, 0xb4ae7c5e
+0,     774144,     774144,     1152,     2304, 0x28827c8a
+0,     775296,     775296,     1152,     2304, 0x1fb88b25
+0,     776448,     776448,     1152,     2304, 0x588d71e8
+0,     777600,     777600,     1152,     2304, 0x68227c34
+0,     778752,     778752,     1152,     2304, 0xee4d73e8
+0,     779904,     779904,     1152,     2304, 0x69287c6d
+0,     781056,     781056,     1152,     2304, 0xbb04926a
+0,     782208,     782208,     1152,     2304, 0x89456cec
+0,     783360,     783360,     1152,     2304, 0xabe18992
+0,     784512,     784512,     1152,     2304, 0x50cc7f6c
+0,     785664,     785664,     1152,     2304, 0x6d7270be
+0,     786816,     786816,     1152,     2304, 0x664c6fef
+0,     787968,     787968,     1152,     2304, 0x7f7982f3
+0,     789120,     789120,     1152,     2304, 0x6ca170e9
+0,     790272,     790272,     1152,     2304, 0x36437d5b
+0,     791424,     791424,     1152,     2304, 0xfd2380e8
+0,     792576,     792576,     1152,     2304, 0x2e3c6e9f
+0,     793728,     793728,     1152,     2304, 0xc8427f3f
+0,     794880,     794880,     1152,     2304, 0x962a79ad
+0,     796032,     796032,     1152,     2304, 0xc9597c8b
+0,     797184,     797184,     1152,     2304, 0x899580bb
+0,     798336,     798336,     1152,     2304, 0x2d179dff
+0,     799488,     799488,     1152,     2304, 0x4ac1707c
+0,     800640,     800640,     1152,     2304, 0x32ea7e95
+0,     801792,     801792,     1152,     2304, 0x265e9a2d
+0,     802944,     802944,     1152,     2304, 0x1c6484d0
+0,     804096,     804096,     1152,     2304, 0x39ae6884
+0,     805248,     805248,     1152,     2304, 0x82ed7bc5
+0,     806400,     806400,     1152,     2304, 0x556b7b3c
+0,     807552,     807552,     1152,     2304, 0xb7f778dd
+0,     808704,     808704,     1152,     2304, 0x74447d55
+0,     809856,     809856,     1152,     2304, 0x0c66861e
+0,     811008,     811008,     1152,     2304, 0x15ba7932
+0,     812160,     812160,     1152,     2304, 0xb19170fc
+0,     813312,     813312,     1152,     2304, 0x19d37551
+0,     814464,     814464,     1152,     2304, 0xdc529142
+0,     815616,     815616,     1152,     2304, 0xf2637e77
+0,     816768,     816768,     1152,     2304, 0xd065944b
+0,     817920,     817920,     1152,     2304, 0x22878123
+0,     819072,     819072,     1152,     2304, 0xc21a8bf7
+0,     820224,     820224,     1152,     2304, 0x2e3582dc
+0,     821376,     821376,     1152,     2304, 0xd42f7987
+0,     822528,     822528,     1152,     2304, 0x69b88236
+0,     823680,     823680,     1152,     2304, 0x7c988f90
+0,     824832,     824832,     1152,     2304, 0x2cd66ded
+0,     825984,     825984,     1152,     2304, 0x3e65828b
+0,     827136,     827136,     1152,     2304, 0x7e9871c9
+0,     828288,     828288,     1152,     2304, 0xf1f2806b
+0,     829440,     829440,     1152,     2304, 0xf5087c7b
+0,     830592,     830592,     1152,     2304, 0x62b98097
+0,     831744,     831744,     1152,     2304, 0xec457c43
+0,     832896,     832896,     1152,     2304, 0x87af87a6
+0,     834048,     834048,     1152,     2304, 0x97cc757d
+0,     835200,     835200,     1152,     2304, 0x08ca76bd
+0,     836352,     836352,     1152,     2304, 0x14ae7cbd
+0,     837504,     837504,     1152,     2304, 0x1f79709a
+0,     838656,     838656,     1152,     2304, 0x17948207
+0,     839808,     839808,     1152,     2304, 0x16ee7228
+0,     840960,     840960,     1152,     2304, 0x76cc82d7
+0,     842112,     842112,     1152,     2304, 0x8f327a8e
+0,     843264,     843264,     1152,     2304, 0x14ee7756
+0,     844416,     844416,     1152,     2304, 0x15996d2f
+0,     845568,     845568,     1152,     2304, 0x4c707d5c
+0,     846720,     846720,     1152,     2304, 0x268c6fee
+0,     847872,     847872,     1152,     2304, 0x6d838c76
+0,     849024,     849024,     1152,     2304, 0xafa17e64
+0,     850176,     850176,     1152,     2304, 0xb6546e66
+0,     851328,     851328,     1152,     2304, 0x945d8b9f
+0,     852480,     852480,     1152,     2304, 0x5bfb7446
+0,     853632,     853632,     1152,     2304, 0xae6086f9
+0,     854784,     854784,     1152,     2304, 0xa01380cd
+0,     855936,     855936,     1152,     2304, 0x06f0828f
+0,     857088,     857088,     1152,     2304, 0x0ae07176
+0,     858240,     858240,     1152,     2304, 0x66f07522
+0,     859392,     859392,     1152,     2304, 0x44018106
+0,     860544,     860544,     1152,     2304, 0x8cd283da
+0,     861696,     861696,     1152,     2304, 0x14257f45
+0,     862848,     862848,     1152,     2304, 0x04979537
+0,     864000,     864000,     1152,     2304, 0x8b5f797c
+0,     865152,     865152,     1152,     2304, 0x12d67493
+0,     866304,     866304,     1152,     2304, 0xc8886a25
+0,     867456,     867456,     1152,     2304, 0x614b803a
+0,     868608,     868608,     1152,     2304, 0x75667d35
+0,     869760,     869760,     1152,     2304, 0xe42c7b00
+0,     870912,     870912,     1152,     2304, 0x37787927
+0,     872064,     872064,     1152,     2304, 0x85db8409
+0,     873216,     873216,     1152,     2304, 0x823b822c
+0,     874368,     874368,     1152,     2304, 0xa1658479
+0,     875520,     875520,     1152,     2304, 0xdbe58ff7
+0,     876672,     876672,     1152,     2304, 0x725175e2
+0,     877824,     877824,     1152,     2304, 0xb2ae7741
+0,     878976,     878976,     1152,     2304, 0x4de169e4
+0,     880128,     880128,     1152,     2304, 0x3cb18530
+0,     881280,     881280,     1152,     2304, 0x48b95d6c
+0,     882432,     882432,     1152,     2304, 0xcff707ef
diff --git a/tests/ref/fate/filter-hq2x b/tests/ref/fate/filter-hq2x
index dcf2a29..2c1d8b7 100644
--- a/tests/ref/fate/filter-hq2x
+++ b/tests/ref/fate/filter-hq2x
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 382x574
+#sar 0: 1/1
 0,          0,          0,        1,   877072, 0x9369339e
 0,          1,          1,        1,   877072, 0x32d119a1
diff --git a/tests/ref/fate/filter-hq3x b/tests/ref/fate/filter-hq3x
index 8215388..a7db99e 100644
--- a/tests/ref/fate/filter-hq3x
+++ b/tests/ref/fate/filter-hq3x
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 573x861
+#sar 0: 1/1
 0,          0,          0,        1,  1973412, 0xafc227fa
 0,          1,          1,        1,  1973412, 0x93aebf19
diff --git a/tests/ref/fate/filter-hq4x b/tests/ref/fate/filter-hq4x
index c1d6fd8..6702fe4 100644
--- a/tests/ref/fate/filter-hq4x
+++ b/tests/ref/fate/filter-hq4x
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 764x1148
+#sar 0: 1/1
 0,          0,          0,        1,  3508288, 0x034ef75e
 0,          1,          1,        1,  3508288, 0x738e9bbb
diff --git a/tests/ref/fate/filter-hqdn3d b/tests/ref/fate/filter-hqdn3d
index 6f121c3..d649629 100644
--- a/tests/ref/fate/filter-hqdn3d
+++ b/tests/ref/fate/filter-hqdn3d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x0c09883a
 0,          1,          1,        1,   152064, 0xfc2748a0
 0,          2,          2,        1,   152064, 0xb746eea8
diff --git a/tests/ref/fate/filter-hqdn3d-sample b/tests/ref/fate/filter-hqdn3d-sample
index 97718f9..24d25a6 100644
--- a/tests/ref/fate/filter-hqdn3d-sample
+++ b/tests/ref/fate/filter-hqdn3d-sample
@@ -1,4 +1,8 @@
 #tb 0: 1/9
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   115200, 0x2c810465
 0,          1,          1,        1,   115200, 0x957c0563
 0,          2,          2,        1,   115200, 0x786c6d5b
diff --git a/tests/ref/fate/filter-idet b/tests/ref/fate/filter-idet
index 6283039..a0f579d 100644
--- a/tests/ref/fate/filter-idet
+++ b/tests/ref/fate/filter-idet
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x432
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x6e4f89ef
 0,          1,          1,        1,   152064, 0x7f5f6551
 0,          2,          2,        1,   152064, 0xc566f64a
diff --git a/tests/ref/fate/filter-interlace b/tests/ref/fate/filter-interlace
index 4659942..24423cc 100644
--- a/tests/ref/fate/filter-interlace
+++ b/tests/ref/fate/filter-interlace
@@ -1,4 +1,8 @@
 #tb 0: 2/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x6077db38
 0,          1,          1,        1,   152064, 0x3d4f1b15
 0,          2,          2,        1,   152064, 0x447594f6
diff --git a/tests/ref/fate/filter-lavd-life b/tests/ref/fate/filter-lavd-life
index 565f88a..48546ab 100644
--- a/tests/ref/fate/filter-lavd-life
+++ b/tests/ref/fate/filter-lavd-life
@@ -1,4 +1,8 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 40x40
+#sar 0: 1/1
 0,          0,          0,        1,     4800, 0xf2a15b15
 0,          1,          1,        1,     4800, 0x78c29dcf
 0,          2,          2,        1,     4800, 0x28509d6e
diff --git a/tests/ref/fate/filter-lavd-scalenorm b/tests/ref/fate/filter-lavd-scalenorm
index c946b5c..7b9a60a 100644
--- a/tests/ref/fate/filter-lavd-scalenorm
+++ b/tests/ref/fate/filter-lavd-scalenorm
@@ -1,4 +1,8 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x96
+#sar 0: 1/1
 0,          0,          0,        1,    18432, 0xac484db5
 0,          1,          1,        1,    18432, 0x94734db6
 0,          2,          2,        1,    18432, 0x3fac4db3
diff --git a/tests/ref/fate/filter-lavd-testsrc b/tests/ref/fate/filter-lavd-testsrc
index 0ea5a49..a421cc4 100644
--- a/tests/ref/fate/filter-lavd-testsrc
+++ b/tests/ref/fate/filter-lavd-testsrc
@@ -1,4 +1,8 @@
 #tb 0: 1/7
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   230400, 0x88c4d19a
 0,          1,          1,        1,   230400, 0xcc930a2e
 0,          2,          2,        1,   230400, 0x8e1b0e23
diff --git a/tests/ref/fate/filter-mcdeint-fast b/tests/ref/fate/filter-mcdeint-fast
index 000d43b..228be5e 100644
--- a/tests/ref/fate/filter-mcdeint-fast
+++ b/tests/ref/fate/filter-mcdeint-fast
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
 0,          9,          9,        1,   622080, 0xb3b66c5c
 0,         10,         10,        1,   622080, 0xc6568bd7
 0,         11,         11,        1,   622080, 0xa5b543c3
diff --git a/tests/ref/fate/filter-mcdeint-medium b/tests/ref/fate/filter-mcdeint-medium
index cfd504f..05d1d72 100644
--- a/tests/ref/fate/filter-mcdeint-medium
+++ b/tests/ref/fate/filter-mcdeint-medium
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
 0,          9,          9,        1,   622080, 0xb3b66c5c
 0,         10,         10,        1,   622080, 0x26a29152
 0,         11,         11,        1,   622080, 0x787adddc
diff --git a/tests/ref/fate/filter-mergeplanes b/tests/ref/fate/filter-mergeplanes
index 841d14f..e136703 100644
--- a/tests/ref/fate/filter-mergeplanes
+++ b/tests/ref/fate/filter-mergeplanes
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0x90660272
 0,          1,          1,        1,   304128, 0x6b09c8a6
 0,          2,          2,        1,   304128, 0x343858f3
diff --git a/tests/ref/fate/filter-meta-4560-rotate0 b/tests/ref/fate/filter-meta-4560-rotate0
new file mode 100644
index 0000000..6e870c7
--- /dev/null
+++ b/tests/ref/fate/filter-meta-4560-rotate0
@@ -0,0 +1,267 @@
+#tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 480x272
+#sar 0: 0/1
+#tb 1: 1/44100
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 44100
+#channel_layout 1: 4
+0,          0,          0,        1,   195840, 0x0602351d
+1,          0,          0,     1024,     2048, 0x00000000
+1,       1024,       1024,     1024,     2048, 0xe6b00ffc
+0,          1,          1,        1,   195840, 0xcad55625
+1,       2048,       2048,     1024,     2048, 0x9275068a
+0,          2,          2,        1,   195840, 0x1a47a5ca
+1,       3072,       3072,     1024,     2048, 0xcd35a7ce
+1,       4096,       4096,     1024,     2048, 0x3f846a1e
+0,          3,          3,        1,   195840, 0x5cd02d7c
+1,       5120,       5120,     1024,     2048, 0x60ff5fd1
+0,          4,          4,        1,   195840, 0x07d08f16
+1,       6144,       6144,     1024,     2048, 0x9e9d96ee
+1,       7168,       7168,     1024,     2048, 0xb2622c29
+0,          5,          5,        1,   195840, 0xe8abf6dd
+1,       8192,       8192,     1024,     2048, 0xdeddcd6a
+0,          6,          6,        1,   195840, 0x096a5c58
+1,       9216,       9216,     1024,     2048, 0xc8798b23
+1,      10240,      10240,     1024,     2048, 0xea1dac49
+0,          7,          7,        1,   195840, 0x4e1a17bd
+1,      11264,      11264,     1024,     2048, 0x6b50813e
+0,          8,          8,        1,   195840, 0x96349c20
+1,      12288,      12288,     1024,     2048, 0x89698347
+0,          9,          9,        1,   195840, 0x6bb16907
+1,      13312,      13312,     1024,     2048, 0xaa608a47
+1,      14336,      14336,     1024,     2048, 0x169b8cf7
+0,         10,         10,        1,   195840, 0x7e44e4dd
+1,      15360,      15360,     1024,     2048, 0x2f127455
+0,         11,         11,        1,   195840, 0x4c3c0cf1
+1,      16384,      16384,     1024,     2048, 0x269c7583
+1,      17408,      17408,     1024,     2048, 0x917f7279
+0,         12,         12,        1,   195840, 0x4f2e3f2d
+1,      18432,      18432,     1024,     2048, 0x27055ffb
+0,         13,         13,        1,   195840, 0xcba539cd
+1,      19456,      19456,     1024,     2048, 0x7eca49e4
+1,      20480,      20480,     1024,     2048, 0xad067184
+0,         14,         14,        1,   195840, 0xf2811c9b
+1,      21504,      21504,     1024,     2048, 0xca406454
+0,         15,         15,        1,   195840, 0x8357eab2
+1,      22528,      22528,     1024,     2048, 0x69d48a55
+0,         16,         16,        1,   195840, 0xdba9c438
+1,      23552,      23552,     1024,     2048, 0x0a836c14
+1,      24576,      24576,     1024,     2048, 0xa9e967f9
+0,         17,         17,        1,   195840, 0x58bcb594
+1,      25600,      25600,     1024,     2048, 0xd7f73f35
+0,         18,         18,        1,   195840, 0x3edc5a1c
+1,      26624,      26624,     1024,     2048, 0x70ed8364
+1,      27648,      27648,     1024,     2048, 0x913f9b73
+0,         19,         19,        1,   195840, 0x94e4c186
+1,      28672,      28672,     1024,     2048, 0x7db083eb
+0,         20,         20,        1,   195840, 0xffad5f59
+1,      29696,      29696,     1024,     2048, 0x951b97a9
+1,      30720,      30720,     1024,     2048, 0x072ea78e
+0,         21,         21,        1,   195840, 0x84d1b114
+1,      31744,      31744,     1024,     2048, 0x9b127ba5
+0,         22,         22,        1,   195840, 0x358c1d0a
+1,      32768,      32768,     1024,     2048, 0x051c90c0
+1,      33792,      33792,     1024,     2048, 0x232d93b5
+0,         23,         23,        1,   195840, 0x3ed1ffc8
+1,      34816,      34816,     1024,     2048, 0x76b89477
+0,         24,         24,        1,   195840, 0xf048f47c
+1,      35840,      35840,     1024,     2048, 0x50b2568d
+0,         25,         25,        1,   195840, 0x3c2a3de6
+1,      36864,      36864,     1024,     2048, 0x97947e5e
+1,      37888,      37888,     1024,     2048, 0x21569819
+0,         26,         26,        1,   195840, 0x7ca208b1
+1,      38912,      38912,     1024,     2048, 0xc4358de4
+0,         27,         27,        1,   195840, 0x105cf9fc
+1,      39936,      39936,     1024,     2048, 0x69964977
+1,      40960,      40960,     1024,     2048, 0xef81892e
+0,         28,         28,        1,   195840, 0x9fe50c29
+1,      41984,      41984,     1024,     2048, 0x6f7084e7
+0,         29,         29,        1,   195840, 0xb459720f
+1,      43008,      43008,     1024,     2048, 0x7be080f7
+1,      44032,      44032,     1024,     2048, 0xadb18939
+0,         30,         30,        1,   195840, 0x6eda17b0
+1,      45056,      45056,     1024,     2048, 0x6cd9506d
+0,         31,         31,        1,   195840, 0x098871b0
+1,      46080,      46080,     1024,     2048, 0xba88ab8b
+0,         32,         32,        1,   195840, 0xc664cc79
+1,      47104,      47104,     1024,     2048, 0xe0bd726b
+1,      48128,      48128,     1024,     2048, 0x15604a65
+0,         33,         33,        1,   195840, 0x8d02708d
+1,      49152,      49152,     1024,     2048, 0x2a89f85b
+0,         34,         34,        1,   195840, 0xe90a8705
+1,      50176,      50176,     1024,     2048, 0xd71857dd
+1,      51200,      51200,     1024,     2048, 0x93d98aee
+0,         35,         35,        1,   195840, 0x55f6c5b6
+1,      52224,      52224,     1024,     2048, 0xcc537c08
+0,         36,         36,        1,   195840, 0xe4ad145d
+1,      53248,      53248,     1024,     2048, 0xe0ea7c21
+1,      54272,      54272,     1024,     2048, 0x883ba380
+0,         37,         37,        1,   195840, 0x9e766d50
+1,      55296,      55296,     1024,     2048, 0xaaf65ca7
+0,         38,         38,        1,   195840, 0xc2eac289
+1,      56320,      56320,     1024,     2048, 0xe01e98ca
+0,         39,         39,        1,   195840, 0x0baf5871
+1,      57344,      57344,     1024,     2048, 0xca85a551
+1,      58368,      58368,     1024,     2048, 0x6fea7f82
+0,         40,         40,        1,   195840, 0x15f85f38
+1,      59392,      59392,     1024,     2048, 0x9fd59843
+0,         41,         41,        1,   195840, 0x77b03072
+1,      60416,      60416,     1024,     2048, 0xd7419d35
+1,      61440,      61440,     1024,     2048, 0xc285bc0e
+0,         42,         42,        1,   195840, 0x0abb7abf
+1,      62464,      62464,     1024,     2048, 0x5180419c
+0,         43,         43,        1,   195840, 0x05076724
+1,      63488,      63488,     1024,     2048, 0xac9fd91b
+1,      64512,      64512,     1024,     2048, 0x6de689b3
+0,         44,         44,        1,   195840, 0x2e8c6163
+1,      65536,      65536,     1024,     2048, 0x655bb415
+0,         45,         45,        1,   195840, 0x4f350cde
+1,      66560,      66560,     1024,     2048, 0xe59d7404
+1,      67584,      67584,     1024,     2048, 0xaa9356b9
+0,         46,         46,        1,   195840, 0xefc6bda1
+1,      68608,      68608,     1024,     2048, 0xe193549d
+0,         47,         47,        1,   195840, 0xe2cdee68
+1,      69632,      69632,     1024,     2048, 0xd05c9736
+0,         48,         48,        1,   195840, 0xcc62401e
+1,      70656,      70656,     1024,     2048, 0x086f6829
+1,      71680,      71680,     1024,     2048, 0x79624f93
+0,         49,         49,        1,   195840, 0x4ed76e1b
+1,      72704,      72704,     1024,     2048, 0xf70a2f21
+0,         50,         50,        1,   195840, 0xf4f8599a
+1,      73728,      73728,     1024,     2048, 0xd32c643c
+1,      74752,      74752,     1024,     2048, 0xd6f07035
+0,         51,         51,        1,   195840, 0xb05edf96
+1,      75776,      75776,     1024,     2048, 0x137c6ca0
+0,         52,         52,        1,   195840, 0xfb1a1e15
+1,      76800,      76800,     1024,     2048, 0x916242de
+1,      77824,      77824,     1024,     2048, 0x0d910367
+0,         53,         53,        1,   195840, 0x970ebb58
+1,      78848,      78848,     1024,     2048, 0x460b8f1e
+0,         54,         54,        1,   195840, 0xf4046957
+1,      79872,      79872,     1024,     2048, 0x616a6102
+0,         55,         55,        1,   195840, 0xd5eca339
+1,      80896,      80896,     1024,     2048, 0xfc507e1d
+1,      81920,      81920,     1024,     2048, 0x34accc94
+0,         56,         56,        1,   195840, 0x52d3cb24
+1,      82944,      82944,     1024,     2048, 0xcf679f1a
+0,         57,         57,        1,   195840, 0x259cac47
+1,      83968,      83968,     1024,     2048, 0x72c45d8a
+1,      84992,      84992,     1024,     2048, 0xfd21264a
+0,         58,         58,        1,   195840, 0x9190a95b
+1,      86016,      86016,     1024,     2048, 0x02895c31
+0,         59,         59,        1,   195840, 0x5baccfb5
+1,      87040,      87040,     1024,     2048, 0xdc041e9c
+1,      88064,      88064,     1024,     2048, 0x266407a5
+0,         60,         60,        1,   195840, 0x80d19a09
+1,      89088,      89088,     1024,     2048, 0x8f111c49
+0,         61,         61,        1,   195840, 0x5ad44ce3
+1,      90112,      90112,     1024,     2048, 0xead031dd
+1,      91136,      91136,     1024,     2048, 0x238325d4
+0,         62,         62,        1,   195840, 0x7b1ad12b
+1,      92160,      92160,     1024,     2048, 0x24171913
+0,         63,         63,        1,   195840, 0x57e1a5e5
+1,      93184,      93184,     1024,     2048, 0xbcda41c5
+0,         64,         64,        1,   195840, 0x70cb6d38
+1,      94208,      94208,     1024,     2048, 0x124f5eed
+1,      95232,      95232,     1024,     2048, 0x4cadc088
+0,         65,         65,        1,   195840, 0x39dac35a
+1,      96256,      96256,     1024,     2048, 0x062cd95a
+0,         66,         66,        1,   195840, 0x4f9fccca
+1,      97280,      97280,     1024,     2048, 0xc26a888d
+1,      98304,      98304,     1024,     2048, 0x864f1a68
+0,         67,         67,        1,   195840, 0xadcb5585
+1,      99328,      99328,     1024,     2048, 0x4bb1ecf4
+0,         68,         68,        1,   195840, 0xe596c1b4
+1,     100352,     100352,     1024,     2048, 0xb4ddc0a7
+1,     101376,     101376,     1024,     2048, 0x665badb3
+0,         69,         69,        1,   195840, 0x64a05339
+1,     102400,     102400,     1024,     2048, 0x70beaa68
+0,         70,         70,        1,   195840, 0xaefa0990
+1,     103424,     103424,     1024,     2048, 0x8ac7c7de
+0,         71,         71,        1,   195840, 0x9c0b5c3d
+1,     104448,     104448,     1024,     2048, 0x158cad8e
+1,     105472,     105472,     1024,     2048, 0x0ab8faf2
+0,         72,         72,        1,   195840, 0xbae8bd6b
+1,     106496,     106496,     1024,     2048, 0x994e79f1
+0,         73,         73,        1,   195840, 0xb2ac7857
+1,     107520,     107520,     1024,     2048, 0xc727104e
+1,     108544,     108544,     1024,     2048, 0x1e1f720a
+0,         74,         74,        1,   195840, 0xcf2865e3
+1,     109568,     109568,     1024,     2048, 0x7232bede
+0,         75,         75,        1,   195840, 0x4e8589af
+1,     110592,     110592,     1024,     2048, 0x015fd697
+1,     111616,     111616,     1024,     2048, 0x4b33ebc9
+0,         76,         76,        1,   195840, 0x31c21938
+1,     112640,     112640,     1024,     2048, 0x8e61948a
+0,         77,         77,        1,   195840, 0xe6163c50
+1,     113664,     113664,     1024,     2048, 0x83fab6ac
+0,         78,         78,        1,   195840, 0x888ef74f
+1,     114688,     114688,     1024,     2048, 0x8d55d683
+1,     115712,     115712,     1024,     2048, 0x4e91a2c7
+0,         79,         79,        1,   195840, 0x00d822f7
+1,     116736,     116736,     1024,     2048, 0x8c79c692
+0,         80,         80,        1,   195840, 0xcbe77d2b
+1,     117760,     117760,     1024,     2048, 0xe744d102
+1,     118784,     118784,     1024,     2048, 0x2bf4e6b1
+0,         81,         81,        1,   195840, 0x9f2ff6e5
+1,     119808,     119808,     1024,     2048, 0xd6fd9b91
+0,         82,         82,        1,   195840, 0x08f65f5f
+1,     120832,     120832,     1024,     2048, 0xedcd8e8a
+1,     121856,     121856,     1024,     2048, 0x67b422bd
+0,         83,         83,        1,   195840, 0xd3950469
+1,     122880,     122880,     1024,     2048, 0xa0329606
+0,         84,         84,        1,   195840, 0xb8e014b8
+1,     123904,     123904,     1024,     2048, 0xae47c015
+1,     124928,     124928,     1024,     2048, 0xaec1dfb2
+0,         85,         85,        1,   195840, 0xa4399742
+1,     125952,     125952,     1024,     2048, 0x719e9bac
+0,         86,         86,        1,   195840, 0x84b5a8ec
+1,     126976,     126976,     1024,     2048, 0x5d99a16c
+0,         87,         87,        1,   195840, 0x1bfaa027
+1,     128000,     128000,     1024,     2048, 0x87aacd09
+1,     129024,     129024,     1024,     2048, 0x1473be08
+0,         88,         88,        1,   195840, 0x7bdbb172
+1,     130048,     130048,     1024,     2048, 0xdee3d975
+0,         89,         89,        1,   195840, 0x00f2b3f7
+1,     131072,     131072,     1024,     2048, 0x0180b050
+1,     132096,     132096,     1024,     2048, 0xb035d915
+0,         90,         90,        1,   195840, 0x86503bc7
+1,     133120,     133120,     1024,     2048, 0x1b77a3fd
+0,         91,         91,        1,   195840, 0xc4ab358e
+1,     134144,     134144,     1024,     2048, 0xf233b7bc
+1,     135168,     135168,     1024,     2048, 0xf1fad173
+0,         92,         92,        1,   195840, 0x1b330ba0
+1,     136192,     136192,     1024,     2048, 0x8b6ac5b9
+0,         93,         93,        1,   195840, 0xccc9822f
+1,     137216,     137216,     1024,     2048, 0x1228c03f
+0,         94,         94,        1,   195840, 0xffe3486d
+1,     138240,     138240,     1024,     2048, 0xbe99cc61
+1,     139264,     139264,     1024,     2048, 0x8486bad7
+0,         95,         95,        1,   195840, 0x30dc0efe
+1,     140288,     140288,     1024,     2048, 0x423ca644
+0,         96,         96,        1,   195840, 0x6bfae71e
+1,     141312,     141312,     1024,     2048, 0x33afb5a3
+1,     142336,     142336,     1024,     2048, 0x90c33f49
+0,         97,         97,        1,   195840, 0x0fa017b8
+1,     143360,     143360,     1024,     2048, 0x0e59f9d7
+0,         98,         98,        1,   195840, 0x1d0c9810
+1,     144384,     144384,     1024,     2048, 0x4f513d3d
+1,     145408,     145408,     1024,     2048, 0xe2f1406b
+0,         99,         99,        1,   195840, 0x775778f0
+1,     146432,     146432,     1024,     2048, 0xe55d2a99
+0,        100,        100,        1,   195840, 0xdcb0ede5
+1,     147456,     147456,     1024,     2048, 0xb0e236c2
+0,        101,        101,        1,   195840, 0x67624270
+1,     148480,     148480,     1024,     2048, 0xdc80c8fb
+1,     149504,     149504,     1024,     2048, 0x97c30778
+0,        102,        102,        1,   195840, 0xce86f6a3
+1,     150528,     150528,     1024,     2048, 0x6e403113
+0,        103,        103,        1,   195840, 0xa4b3e032
+1,     151552,     151552,     1024,     2048, 0x429605a1
+1,     152576,     152576,     1024,     2048, 0x25d61b75
+0,        104,        104,        1,   195840, 0x46851b87
+1,     153600,     153600,     1024,     2048, 0xa32cf42d
+0,        105,        105,        1,   195840, 0x02d97dc4
diff --git a/tests/ref/fate/filter-metadata-cropdetect b/tests/ref/fate/filter-metadata-cropdetect
new file mode 100644
index 0000000..c49f9f0
--- /dev/null
+++ b/tests/ref/fate/filter-metadata-cropdetect
@@ -0,0 +1,32 @@
+pkt_pts=0
+pkt_pts=400
+pkt_pts=800|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=1200|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=1600|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=2000|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=2400|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=2800|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=3200|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=3600|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=4000|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=4400|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=4800|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=5200|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=5600|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=6000|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=6400|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=6800|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=7200|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=7600|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=8000|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=8400|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=8800|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=9200|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=9600|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=10000|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=10400|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=10800|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=11200|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=11600|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=12000|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
+pkt_pts=12400|tag:lavfi.cropdetect.x1=0|tag:lavfi.cropdetect.x2=719|tag:lavfi.cropdetect.y1=61|tag:lavfi.cropdetect.y2=424|tag:lavfi.cropdetect.w=720|tag:lavfi.cropdetect.h=352|tag:lavfi.cropdetect.x=0|tag:lavfi.cropdetect.y=68
diff --git a/tests/ref/fate/filter-metadata-readvitc-def b/tests/ref/fate/filter-metadata-readvitc-def
new file mode 100644
index 0000000..8a650f1
--- /dev/null
+++ b/tests/ref/fate/filter-metadata-readvitc-def
@@ -0,0 +1,5 @@
+pkt_pts=0|tag:lavfi.readvitc.found=0
+pkt_pts=1|tag:lavfi.readvitc.found=1|tag:lavfi.readvitc.tc_str=05:01:02:21
+pkt_pts=2|tag:lavfi.readvitc.found=1|tag:lavfi.readvitc.tc_str=05:01:02:22
+pkt_pts=3|tag:lavfi.readvitc.found=1|tag:lavfi.readvitc.tc_str=05:01:02:23
+pkt_pts=4|tag:lavfi.readvitc.found=0
diff --git a/tests/ref/fate/filter-metadata-readvitc-thr b/tests/ref/fate/filter-metadata-readvitc-thr
new file mode 100644
index 0000000..4086663
--- /dev/null
+++ b/tests/ref/fate/filter-metadata-readvitc-thr
@@ -0,0 +1,5 @@
+pkt_pts=0|tag:lavfi.readvitc.found=1|tag:lavfi.readvitc.tc_str=05:01:02:20
+pkt_pts=1|tag:lavfi.readvitc.found=1|tag:lavfi.readvitc.tc_str=05:01:02:21
+pkt_pts=2|tag:lavfi.readvitc.found=1|tag:lavfi.readvitc.tc_str=05:01:02:22
+pkt_pts=3|tag:lavfi.readvitc.found=1|tag:lavfi.readvitc.tc_str=05:01:02:23
+pkt_pts=4|tag:lavfi.readvitc.found=1|tag:lavfi.readvitc.tc_str=05:01:02:24
diff --git a/tests/ref/fate/filter-mpdecimate b/tests/ref/fate/filter-mpdecimate
index 1e9652e..d438dac 100644
--- a/tests/ref/fate/filter-mpdecimate
+++ b/tests/ref/fate/filter-mpdecimate
@@ -1,4 +1,8 @@
 #tb 0: 1/3
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   115200, 0x3744b3ed
 0,          2,          2,        1,   115200, 0x6e318ba0
 0,          3,          3,        1,   115200, 0x48d65876
diff --git a/tests/ref/fate/filter-negate b/tests/ref/fate/filter-negate
index 1d2ea73..88d0471 100644
--- a/tests/ref/fate/filter-negate
+++ b/tests/ref/fate/filter-negate
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xef20e1ec
 0,          1,          1,        1,   152064, 0x899606ec
 0,          2,          2,        1,   152064, 0xaea175d2
diff --git a/tests/ref/fate/filter-overlay b/tests/ref/fate/filter-overlay
index f0f03d6..bcbde54 100644
--- a/tests/ref/fate/filter-overlay
+++ b/tests/ref/fate/filter-overlay
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x2b1a7a92
 0,          1,          1,        1,   152064, 0x6f28685a
 0,          2,          2,        1,   152064, 0xeac9f99c
diff --git a/tests/ref/fate/filter-overlay-dvdsub-2397 b/tests/ref/fate/filter-overlay-dvdsub-2397
new file mode 100644
index 0000000..0e0444d
--- /dev/null
+++ b/tests/ref/fate/filter-overlay-dvdsub-2397
@@ -0,0 +1,856 @@
+#tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 1/1
+#tb 1: 1/1000
+#media_type 1: audio
+#codec_id 1: dts
+#sample_rate 1: 48000
+#channel_layout 1: 60f
+0,          0,          0,        1,   518400, 0x6b05d48a
+1,         27,         27,       10,     2013, 0x68e7b03a
+0,          1,          1,        1,   518400, 0x2c2219cd
+1,         37,         37,       10,     2013, 0x0b1d88d3
+1,         47,         47,       10,     2013, 0x65febc94
+1,         57,         57,       10,     2013, 0x1bb4b445
+0,          2,          2,        1,   518400, 0xa71638c3
+1,         67,         67,       10,     2013, 0x88819a72
+1,         77,         77,       10,     2013, 0x35b89574
+1,         87,         87,       10,     2013, 0x1f08c7e3
+1,         97,         97,       10,     2013, 0x0afc948f
+0,          3,          3,        1,   518400, 0x54bda463
+1,        112,        112,       10,     2013, 0x1d14a693
+1,        122,        122,       10,     2013, 0x53acb554
+1,        132,        132,       10,     2013, 0x71d0a075
+0,          4,          4,        1,   518400, 0xd1e00574
+1,        142,        142,       10,     2013, 0xdcc8a88a
+1,        152,        152,       10,     2013, 0xd1b6a8a2
+1,        162,        162,       10,     2013, 0x46bba243
+0,          5,          5,        1,   518400, 0x53b07f2d
+1,        172,        172,       10,     2013, 0xdcbe9933
+1,        182,        182,       10,     2013, 0xdef5ab52
+1,        198,        198,       10,     2013, 0xd16e8245
+0,          6,          6,        1,   518400, 0x4d19c80b
+1,        208,        208,       10,     2013, 0x5567acd7
+1,        218,        218,       10,     2013, 0xfb129919
+1,        228,        228,       10,     2013, 0x26f8b101
+0,          7,          7,        1,   518400, 0xd34866a2
+1,        238,        238,       10,     2013, 0xa903aff2
+1,        248,        248,       10,     2013, 0x056ba445
+1,        258,        258,       10,     2013, 0xd30ab214
+0,          8,          8,        1,   518400, 0x0321c3db
+1,        268,        268,       10,     2013, 0x35409ef0
+1,        283,        283,       10,     2013, 0xa01b99a8
+1,        293,        293,       10,     2013, 0x776da122
+0,          9,          9,        1,   518400, 0x3f460a79
+1,        303,        303,       10,     2013, 0x411ea855
+1,        313,        313,       10,     2013, 0x0f199df4
+1,        323,        323,       10,     2013, 0xb0598e93
+1,        333,        333,       10,     2013, 0xc63a905a
+0,         10,         10,        1,   518400, 0x71202482
+1,        343,        343,       10,     2013, 0x3fbabd24
+1,        353,        353,       10,     2013, 0xfd55ba5c
+0,         11,         11,        1,   518400, 0x2f7df36e
+1,        368,        368,       10,     2013, 0xf260b04e
+1,        378,        378,       10,     2013, 0xa1f6a1cf
+1,        388,        388,       10,     2013, 0x3559a529
+1,        398,        398,       10,     2013, 0x956e95ed
+0,         12,         12,        1,   518400, 0xaf9888c4
+1,        408,        408,       10,     2013, 0xb9d3a2f8
+1,        418,        418,       10,     2013, 0x3eda8113
+1,        428,        428,       10,     2013, 0x367fa367
+0,         13,         13,        1,   518400, 0x2055a657
+1,        438,        438,       10,     2013, 0xc2fe9685
+1,        454,        454,       10,     2013, 0xf7aead38
+1,        464,        464,       10,     2013, 0x49ada587
+0,         14,         14,        1,   518400, 0x22ccda4c
+1,        474,        474,       10,     2013, 0x8c0ca225
+1,        484,        484,       10,     2013, 0x29ee9122
+1,        494,        494,       10,     2013, 0x6ce1976a
+0,         15,         15,        1,   518400, 0xd6adb9a7
+1,        504,        504,       10,     2013, 0x6a0b9d5b
+1,        514,        514,       10,     2013, 0x1337a33b
+1,        524,        524,       10,     2013, 0xaa12a3b0
+0,         16,         16,        1,   518400, 0x6a7dd791
+1,        539,        539,       10,     2013, 0xaf59aaf4
+1,        549,        549,       10,     2013, 0x4ffab2c5
+1,        559,        559,       10,     2013, 0x56249944
+0,         17,         17,        1,   518400, 0x5c3319c7
+1,        569,        569,       10,     2013, 0x95f6ad07
+1,        579,        579,       10,     2013, 0xb8e6a610
+1,        589,        589,       10,     2013, 0xaee2948b
+1,        599,        599,       10,     2013, 0xc686adac
+0,         18,         18,        1,   518400, 0xe9b5a47d
+1,        609,        609,       10,     2013, 0x6bcdb073
+1,        624,        624,       10,     2013, 0x26d496b2
+0,         19,         19,        1,   518400, 0xf0bd6556
+1,        634,        634,       10,     2013, 0xaa419b09
+1,        644,        644,       10,     2013, 0xee6ba974
+1,        654,        654,       10,     2013, 0x690893b8
+1,        664,        664,       10,     2013, 0xaa7eb6c5
+0,         20,         20,        1,   518400, 0x6b16e31b
+1,        674,        674,       10,     2013, 0x73e094c3
+1,        684,        684,       10,     2013, 0xa297a539
+1,        694,        694,       10,     2013, 0x15e7a304
+0,         21,         21,        1,   518400, 0x859b3832
+1,        710,        710,       10,     2013, 0xc8dfaa11
+1,        720,        720,       10,     2013, 0xc2b5939b
+1,        730,        730,       10,     2013, 0xecaaab92
+0,         22,         22,        1,   518400, 0x36b426b8
+1,        740,        740,       10,     2013, 0xc522ab70
+1,        750,        750,       10,     2013, 0x1668985c
+1,        760,        760,       10,     2013, 0x59a596f7
+0,         23,         23,        1,   518400, 0x60f3e06a
+1,        770,        770,       10,     2013, 0x12d8a3c4
+1,        780,        780,       10,     2013, 0x71f1b02f
+1,        795,        795,       10,     2013, 0x7138c757
+0,         24,         24,        1,   518400, 0xe56a65a3
+1,        805,        805,       10,     2013, 0x199d9631
+1,        815,        815,       10,     2013, 0x8955ae90
+1,        825,        825,       10,     2013, 0xbdf0a97d
+0,         25,         25,        1,   518400, 0x5641e549
+1,        835,        835,       10,     2013, 0x47faa1e7
+1,        845,        845,       10,     2013, 0x01bbb638
+1,        855,        855,       10,     2013, 0x4e4da199
+1,        865,        865,       10,     2013, 0x3ba7abf4
+0,         26,         26,        1,   518400, 0x7b51a06b
+1,        880,        880,       10,     2013, 0xa3fda508
+1,        890,        890,       10,     2013, 0x81c0ad1d
+1,        900,        900,       10,     2013, 0x93beaf3b
+0,         27,         27,        1,   518400, 0xc6f53f46
+1,        910,        910,       10,     2013, 0xe30eac59
+1,        920,        920,       10,     2013, 0x797eaa78
+1,        930,        930,       10,     2013, 0xca4e8f1e
+0,         28,         28,        1,   518400, 0x2e12e6c4
+1,        940,        940,       10,     2013, 0x39fa945d
+1,        950,        950,       10,     2013, 0xff31b5d6
+1,        966,        966,       10,     2013, 0x3b7e9efa
+0,         29,         29,        1,   518400, 0xebc97246
+1,        976,        976,       10,     2013, 0xc3e6b7b5
+1,        986,        986,       10,     2013, 0x37c7c3f9
+1,        996,        996,       10,     2013, 0x2966c8b8
+0,         30,         30,        1,   518400, 0x814ca8fa
+1,       1006,       1006,       10,     2013, 0xc1b79ccd
+1,       1016,       1016,       10,     2013, 0x80afad19
+1,       1026,       1026,       10,     2013, 0xb2f2adc4
+0,         31,         31,        1,   518400, 0xc875f1f8
+1,       1036,       1036,       10,     2013, 0xfed29216
+1,       1051,       1051,       10,     2013, 0x47ebb382
+1,       1061,       1061,       10,     2013, 0x5f89bb83
+0,         32,         32,        1,   518400, 0x11295e3b
+1,       1071,       1071,       10,     2013, 0x0e07ab5d
+1,       1081,       1081,       10,     2013, 0x6f00af38
+1,       1091,       1091,       10,     2013, 0xe7fcadfb
+1,       1101,       1101,       10,     2013, 0x34c0a648
+0,         33,         33,        1,   518400, 0x5895f2f4
+1,       1111,       1111,       10,     2013, 0x24c88fe2
+1,       1121,       1121,       10,     2013, 0xe57e9d1f
+0,         34,         34,        1,   518400, 0x2bdbb858
+1,       1136,       1136,       10,     2013, 0xda03a3d8
+1,       1146,       1146,       10,     2013, 0x5655b308
+1,       1156,       1156,       10,     2013, 0x13a7c01d
+1,       1166,       1166,       10,     2013, 0x56559682
+0,         35,         35,        1,   518400, 0x5f296abe
+1,       1176,       1176,       10,     2013, 0x26d8cca6
+1,       1186,       1186,       10,     2013, 0x0ac79ed5
+1,       1196,       1196,       10,     2013, 0x353fadcf
+0,         36,         36,        1,   518400, 0x0b00e1f2
+1,       1206,       1206,       10,     2013, 0xc5d9a96e
+1,       1222,       1222,       10,     2013, 0xf51ba278
+1,       1232,       1232,       10,     2013, 0x7bf0b79e
+0,         37,         37,        1,   518400, 0x64afd3fc
+1,       1242,       1242,       10,     2013, 0xbbc58df7
+1,       1252,       1252,       10,     2013, 0xa1739cc8
+1,       1262,       1262,       10,     2013, 0x34deaec6
+0,         38,         38,        1,   518400, 0xc1ae1d85
+1,       1272,       1272,       10,     2013, 0x750ba20b
+1,       1282,       1282,       10,     2013, 0xaaccacfa
+1,       1292,       1292,       10,     2013, 0x02cc9b72
+0,         39,         39,        1,   518400, 0x5189f5e6
+1,       1307,       1307,       10,     2013, 0xc1c6aa7e
+1,       1317,       1317,       10,     2013, 0xd609ab26
+1,       1327,       1327,       10,     2013, 0xc880a135
+0,         40,         40,        1,   518400, 0x61c7dc36
+1,       1337,       1337,       10,     2013, 0xddc4bc69
+1,       1347,       1347,       10,     2013, 0x934caf65
+1,       1357,       1357,       10,     2013, 0xafa6af4a
+1,       1367,       1367,       10,     2013, 0x886eab2b
+0,         41,         41,        1,   518400, 0xc0e617c8
+1,       1377,       1377,       10,     2013, 0x7880a5ac
+1,       1392,       1392,       10,     2013, 0x55cf9a72
+0,         42,         42,        1,   518400, 0xcc78bfbf
+1,       1402,       1402,       10,     2013, 0xff199a41
+1,       1412,       1412,       10,     2013, 0xdbc7a029
+1,       1422,       1422,       10,     2013, 0x1012940a
+0,         43,         43,        1,   518400, 0x8a9b924f
+1,       1435,       1435,       10,     2013, 0x0598b84f
+1,       1445,       1445,       10,     2013, 0x2dea9296
+1,       1455,       1455,       10,     2013, 0x443580c3
+1,       1465,       1465,       10,     2013, 0x8d319f10
+0,         44,         44,        1,   518400, 0xb21db38a
+1,       1475,       1475,       10,     2013, 0xacf4acfe
+1,       1485,       1485,       10,     2013, 0x82b0ac7b
+1,       1495,       1495,       10,     2013, 0x9a7cb71c
+0,         45,         45,        1,   518400, 0xd5ab5f27
+1,       1505,       1505,       10,     2013, 0xbe7c9bc4
+1,       1520,       1520,       10,     2013, 0x93cba1fd
+1,       1530,       1530,       10,     2013, 0x7fb7b11f
+0,         46,         46,        1,   518400, 0xc1b7b060
+1,       1540,       1540,       10,     2013, 0xd9dea46b
+1,       1550,       1550,       10,     2013, 0xfe11a5b2
+1,       1560,       1560,       10,     2013, 0x0243a937
+0,         47,         47,        1,   518400, 0x4cd477e8
+1,       1570,       1570,       10,     2013, 0x1eaba981
+1,       1580,       1580,       10,     2013, 0x088f9626
+1,       1590,       1590,       10,     2013, 0x4f1aa59a
+0,         48,         48,        1,   518400, 0x84fb48b3
+1,       1606,       1606,       10,     2013, 0x0352b14d
+1,       1616,       1616,       10,     2013, 0x03cc9bf9
+1,       1626,       1626,       10,     2013, 0xa9949060
+0,         49,         49,        1,   518400, 0x6d2fdd37
+1,       1636,       1636,       10,     2013, 0x07a89509
+1,       1646,       1646,       10,     2013, 0x1e588e8a
+1,       1656,       1656,       10,     2013, 0x7845b7c1
+1,       1666,       1666,       10,     2013, 0x676fa3c7
+0,         50,         50,        1,   518400, 0xf754edd8
+1,       1676,       1676,       10,     2013, 0xe5bfae55
+1,       1691,       1691,       10,     2013, 0xb1bc9249
+1,       1701,       1701,       10,     2013, 0xecd7abfb
+0,         51,         51,        1,   518400, 0x520cbdcd
+1,       1711,       1711,       10,     2013, 0x0389a6d5
+1,       1721,       1721,       10,     2013, 0xf9b69da1
+1,       1731,       1731,       10,     2013, 0x2bbaafc4
+0,         52,         52,        1,   518400, 0x54a53c59
+1,       1741,       1741,       10,     2013, 0x45738eb2
+1,       1751,       1751,       10,     2013, 0xf28ea9b6
+1,       1761,       1761,       10,     2013, 0x0d6dab7a
+0,         53,         53,        1,   518400, 0xbb9d3c93
+1,       1776,       1776,       10,     2013, 0x6c04b586
+1,       1786,       1786,       10,     2013, 0x74e4b50c
+1,       1796,       1796,       10,     2013, 0x7cd6ad9b
+0,         54,         54,        1,   518400, 0xbb84e583
+1,       1806,       1806,       10,     2013, 0x70c79d83
+1,       1816,       1816,       10,     2013, 0x741eab3c
+1,       1826,       1826,       10,     2013, 0xb972a8cf
+0,         55,         55,        1,   518400, 0xf03b9f4f
+1,       1836,       1836,       10,     2013, 0x4143a734
+1,       1846,       1846,       10,     2013, 0xa98cb454
+1,       1862,       1862,       10,     2013, 0x51e89073
+0,         56,         56,        1,   518400, 0x8b88635d
+1,       1872,       1872,       10,     2013, 0x192cb418
+1,       1882,       1882,       10,     2013, 0x6c55aa29
+1,       1892,       1892,       10,     2013, 0xf86fad70
+0,         57,         57,        1,   518400, 0x975fb58d
+1,       1902,       1902,       10,     2013, 0x06eca62d
+1,       1912,       1912,       10,     2013, 0xe4f2a1d2
+1,       1922,       1922,       10,     2013, 0xe542afb6
+1,       1932,       1932,       10,     2013, 0x77f1b0c3
+0,         58,         58,        1,   518400, 0x9d63c101
+1,       1947,       1947,       10,     2013, 0x27ce9cd1
+1,       1957,       1957,       10,     2013, 0x6c8d8f02
+1,       1967,       1967,       10,     2013, 0x32afa383
+0,         59,         59,        1,   518400, 0x6e739153
+1,       1977,       1977,       10,     2013, 0xb90c88a7
+1,       1987,       1987,       10,     2013, 0x10b494ed
+1,       1997,       1997,       10,     2013, 0x0cf8a595
+0,         60,         60,        1,   518400, 0xaf6a5fac
+1,       2007,       2007,       10,     2013, 0x09f88863
+1,       2017,       2017,       10,     2013, 0x67f5a87e
+1,       2032,       2032,       10,     2013, 0xc63892b8
+0,         61,         61,        1,   518400, 0xc87efe9c
+1,       2042,       2042,       10,     2013, 0x6de9935c
+1,       2052,       2052,       10,     2013, 0xadfcb473
+1,       2062,       2062,       10,     2013, 0x7ba9abe7
+0,         62,         62,        1,   518400, 0xdf47969f
+1,       2072,       2072,       10,     2013, 0x6b79b6c8
+1,       2082,       2082,       10,     2013, 0xae46b670
+1,       2092,       2092,       10,     2013, 0xa3fb9961
+1,       2102,       2102,       10,     2013, 0x3413a4cb
+0,         63,         63,        1,   518400, 0xfa5d2ab0
+1,       2118,       2118,       10,     2013, 0x2c16b48e
+1,       2128,       2128,       10,     2013, 0xd2559fd5
+0,         64,         64,        1,   518400, 0x7428a46a
+1,       2138,       2138,       10,     2013, 0xafdeb68d
+1,       2148,       2148,       10,     2013, 0x52f79c97
+1,       2158,       2158,       10,     2013, 0x6f2091e1
+1,       2168,       2168,       10,     2013, 0x03fca1fd
+0,         65,         65,        1,   518400, 0x3c6c93d9
+1,       2178,       2178,       10,     2013, 0x62d98a8b
+1,       2188,       2188,       10,     2013, 0x727c9845
+0,         66,         66,        1,   518400, 0x9a2fde5d
+1,       2203,       2203,       10,     2013, 0x8103ae15
+1,       2213,       2213,       10,     2013, 0x7bcaa4fc
+1,       2223,       2223,       10,     2013, 0x2d809a43
+1,       2233,       2233,       10,     2013, 0xaa20ab9d
+0,         67,         67,        1,   518400, 0x3858fd67
+1,       2243,       2243,       10,     2013, 0x40c0b8f1
+1,       2253,       2253,       10,     2013, 0x412c9a7e
+1,       2263,       2263,       10,     2013, 0xc7159943
+0,         68,         68,        1,   518400, 0x7d65fc58
+1,       2273,       2273,       10,     2013, 0x3c83a3c1
+1,       2288,       2288,       10,     2013, 0xf1b0b7b5
+1,       2298,       2298,       10,     2013, 0xf7b8a928
+0,         69,         69,        1,   518400, 0xdcbd4b53
+1,       2308,       2308,       10,     2013, 0xb3ec9f8c
+1,       2318,       2318,       10,     2013, 0x088db3b4
+1,       2328,       2328,       10,     2013, 0xd3b7b01d
+0,         70,         70,        1,   518400, 0x03f733d2
+1,       2338,       2338,       10,     2013, 0x26e9c747
+1,       2348,       2348,       10,     2013, 0xb34978e2
+1,       2358,       2358,       10,     2013, 0x91dbb10c
+0,         71,         71,        1,   518400, 0x58d917b0
+1,       2374,       2374,       10,     2013, 0xd9d3a2f1
+1,       2384,       2384,       10,     2013, 0x39f5b151
+1,       2394,       2394,       10,     2013, 0x29fb91e0
+0,         72,         72,        1,   518400, 0x1898371f
+1,       2404,       2404,       10,     2013, 0x93d4b550
+1,       2414,       2414,       10,     2013, 0x290fa162
+1,       2424,       2424,       10,     2013, 0x5e169f0b
+1,       2434,       2434,       10,     2013, 0x2f53acff
+0,         73,         73,        1,   518400, 0x2f5b5418
+1,       2444,       2444,       10,     2013, 0x0173ab1d
+1,       2459,       2459,       10,     2013, 0x3f37a8f8
+1,       2469,       2469,       10,     2013, 0xe61baa50
+0,         74,         74,        1,   518400, 0xa71f5a29
+1,       2479,       2479,       10,     2013, 0x25be9bb7
+1,       2489,       2489,       10,     2013, 0x73109dcc
+1,       2499,       2499,       10,     2013, 0x2d89b116
+0,         75,         75,        1,   518400, 0xad78426b
+1,       2509,       2509,       10,     2013, 0x0ae5adbe
+1,       2519,       2519,       10,     2013, 0x64a798ae
+1,       2529,       2529,       10,     2013, 0x583fac0c
+0,         76,         76,        1,   518400, 0x0c9155e3
+1,       2544,       2544,       10,     2013, 0xe752b7be
+1,       2554,       2554,       10,     2013, 0xb3fb9d5d
+1,       2564,       2564,       10,     2013, 0xaeb0bf93
+0,         77,         77,        1,   518400, 0x4fac4817
+1,       2574,       2574,       10,     2013, 0xab61c17d
+1,       2584,       2584,       10,     2013, 0x92d2add0
+1,       2594,       2594,       10,     2013, 0xb34b96ec
+0,         78,         78,        1,   518400, 0xcacb963e
+1,       2604,       2604,       10,     2013, 0x9cb19d35
+1,       2614,       2614,       10,     2013, 0xb7b3b961
+1,       2630,       2630,       10,     2013, 0x2a52a20b
+0,         79,         79,        1,   518400, 0x3a6183cc
+1,       2640,       2640,       10,     2013, 0x059eaf06
+1,       2650,       2650,       10,     2013, 0x0d49ac8a
+1,       2660,       2660,       10,     2013, 0x095b97cf
+0,         80,         80,        1,   518400, 0x65d47e90
+1,       2670,       2670,       10,     2013, 0x03e28d94
+1,       2680,       2680,       10,     2013, 0x50d79f48
+1,       2690,       2690,       10,     2013, 0x71c9a459
+1,       2700,       2700,       10,     2013, 0x8cd6affc
+0,         81,         81,        1,   518400, 0xf9b7e517
+1,       2715,       2715,       10,     2013, 0x89fba9c9
+1,       2725,       2725,       10,     2013, 0x74a1b800
+1,       2735,       2735,       10,     2013, 0x675dc84d
+0,         82,         82,        1,   518400, 0x8aac2e66
+1,       2745,       2745,       10,     2013, 0x25fe8f0c
+1,       2755,       2755,       10,     2013, 0xf38da26b
+1,       2765,       2765,       10,     2013, 0x1d04a500
+0,         83,         83,        1,   518400, 0x555456e4
+1,       2775,       2775,       10,     2013, 0xf01cb227
+1,       2785,       2785,       10,     2013, 0xe37e9028
+1,       2800,       2800,       10,     2013, 0xf6b5aa7c
+0,         84,         84,        1,   518400, 0x73bc6194
+1,       2810,       2810,       10,     2013, 0xea2391b0
+1,       2820,       2820,       10,     2013, 0xb234abcd
+1,       2830,       2830,       10,     2013, 0x5840a50f
+0,         85,         85,        1,   518400, 0x147b678a
+1,       2840,       2840,       10,     2013, 0x482cad7b
+1,       2850,       2850,       10,     2013, 0xd085a629
+1,       2860,       2860,       10,     2013, 0x1adf8ea8
+0,         86,         86,        1,   518400, 0x67209622
+1,       2870,       2870,       10,     2013, 0xbc3aba31
+1,       2886,       2886,       10,     2013, 0x5e7ea857
+1,       2896,       2896,       10,     2013, 0x7e669671
+0,         87,         87,        1,   518400, 0xdbf0438b
+1,       2906,       2906,       10,     2013, 0xe2d39670
+1,       2916,       2916,       10,     2013, 0xe829b4a8
+1,       2926,       2926,       10,     2013, 0x5b73a363
+1,       2936,       2936,       10,     2013, 0xc1ffa824
+0,         88,         88,        1,   518400, 0xe712b764
+1,       2946,       2946,       10,     2013, 0x919ba91a
+1,       2956,       2956,       10,     2013, 0xa1799be7
+0,         89,         89,        1,   518400, 0xf396de88
+1,       2971,       2971,       10,     2013, 0x9b8e92c1
+1,       2981,       2981,       10,     2013, 0x5ddeb554
+1,       2991,       2991,       10,     2013, 0xf6b99d0b
+1,       3001,       3001,       10,     2013, 0x6987c4a4
+0,         90,         90,        1,   518400, 0x5bb4a81d
+1,       3011,       3011,       10,     2013, 0xf3be9f72
+1,       3021,       3021,       10,     2013, 0xae51a2ef
+1,       3031,       3031,       10,     2013, 0x5c23aaac
+0,         91,         91,        1,   518400, 0x731a98c8
+1,       3041,       3041,       10,     2013, 0xe7a9a994
+1,       3056,       3056,       10,     2013, 0xdd10a997
+1,       3066,       3066,       10,     2013, 0x76e0a749
+0,         92,         92,        1,   518400, 0xb0f61608
+1,       3076,       3076,       10,     2013, 0x899ea6fb
+1,       3086,       3086,       10,     2013, 0xc8449029
+1,       3096,       3096,       10,     2013, 0x6a34b469
+0,         93,         93,        1,   518400, 0x86845d11
+1,       3106,       3106,       10,     2013, 0xf6f1b172
+1,       3116,       3116,       10,     2013, 0x790796f8
+1,       3126,       3126,       10,     2013, 0x190a874a
+0,         94,         94,        1,   518400, 0x2511350a
+1,       3142,       3142,       10,     2013, 0x99a4a5e3
+1,       3152,       3152,       10,     2013, 0x9b619c33
+1,       3162,       3162,       10,     2013, 0x2462a1c0
+0,         95,         95,        1,   518400, 0xd08f20d1
+1,       3172,       3172,       10,     2013, 0xd446b781
+1,       3182,       3182,       10,     2013, 0xd421aec0
+1,       3192,       3192,       10,     2013, 0x6a9d9164
+1,       3202,       3202,       10,     2013, 0x02cbaf7f
+0,         96,         96,        1,   518400, 0x0619c067
+1,       3212,       3212,       10,     2013, 0x5ab1a098
+1,       3227,       3227,       10,     2013, 0xe280ace1
+0,         97,         97,        1,   518400, 0x9f54a84a
+1,       3237,       3237,       10,     2013, 0x32d0aecf
+1,       3247,       3247,       10,     2013, 0xb805a758
+1,       3257,       3257,       10,     2013, 0x618ab629
+1,       3267,       3267,       10,     2013, 0xe4c29e0d
+0,         98,         98,        1,   518400, 0x00486dcf
+1,       3277,       3277,       10,     2013, 0x9119a3ba
+1,       3287,       3287,       10,     2013, 0x1f5ea3d0
+1,       3297,       3297,       10,     2013, 0x903e99c2
+0,         99,         99,        1,   518400, 0x6881078c
+1,       3312,       3312,       10,     2013, 0x126b9e64
+1,       3322,       3322,       10,     2013, 0xd207aa91
+1,       3332,       3332,       10,     2013, 0x7a229fad
+0,        100,        100,        1,   518400, 0x4873f7c2
+1,       3342,       3342,       10,     2013, 0x7651aeda
+1,       3352,       3352,       10,     2013, 0xb74c7f0c
+1,       3362,       3362,       10,     2013, 0xaf9fbb89
+0,        101,        101,        1,   518400, 0x63ab53c8
+1,       3372,       3372,       10,     2013, 0xf0f5a62f
+1,       3382,       3382,       10,     2013, 0xa2009133
+1,       3398,       3398,       10,     2013, 0xb6d9a556
+0,        102,        102,        1,   518400, 0xc768db1a
+1,       3408,       3408,       10,     2013, 0x0f95a286
+1,       3418,       3418,       10,     2013, 0x4fbe8975
+1,       3428,       3428,       10,     2013, 0x18f19c54
+0,        103,        103,        1,   518400, 0x5a4eb9c0
+1,       3440,       3440,       10,     2013, 0x95769be6
+1,       3450,       3450,       10,     2013, 0x739ba722
+1,       3460,       3460,       10,     2013, 0xc7dda687
+1,       3470,       3470,       10,     2013, 0xe322a3a4
+0,        104,        104,        1,   518400, 0x0616fddd
+1,       3480,       3480,       10,     2013, 0x4ce7ba9c
+1,       3490,       3490,       10,     2013, 0x33748c20
+1,       3500,       3500,       10,     2013, 0xdd98b65d
+0,        105,        105,        1,   518400, 0xfdf176d6
+1,       3510,       3510,       10,     2013, 0xd02e9cd6
+1,       3526,       3526,       10,     2013, 0x81dbb3c7
+1,       3536,       3536,       10,     2013, 0x3afba1e0
+0,        106,        106,        1,   518400, 0x674998a2
+1,       3546,       3546,       10,     2013, 0x735994ff
+1,       3556,       3556,       10,     2013, 0xf54cbda2
+1,       3566,       3566,       10,     2013, 0x3c53ad5b
+0,        107,        107,        1,   518400, 0xc2401937
+1,       3576,       3576,       10,     2013, 0x3a2595a8
+1,       3586,       3586,       10,     2013, 0xb7b39f34
+1,       3596,       3596,       10,     2013, 0x269fa949
+0,        108,        108,        1,   518400, 0xbfa320f6
+1,       3611,       3611,       10,     2013, 0x3519ab0b
+1,       3621,       3621,       10,     2013, 0xb9f2a7c1
+1,       3631,       3631,       10,     2013, 0xff47844c
+0,        109,        109,        1,   518400, 0x4b4fa759
+1,       3641,       3641,       10,     2013, 0x835ea1ef
+1,       3651,       3651,       10,     2013, 0xf491bc4e
+1,       3661,       3661,       10,     2013, 0x90bc88f0
+0,        110,        110,        1,   518400, 0x0d3f30fa
+1,       3671,       3671,       10,     2013, 0x6718ac48
+1,       3681,       3681,       10,     2013, 0xfa85bdb6
+1,       3696,       3696,       10,     2013, 0x645cb677
+0,        111,        111,        1,   518400, 0x8e8b9202
+1,       3706,       3706,       10,     2013, 0x6c47c630
+1,       3716,       3716,       10,     2013, 0x10aa8813
+1,       3726,       3726,       10,     2013, 0xfcb0afb3
+1,       3736,       3736,       10,     2013, 0x5f499be8
+0,        112,        112,        1,   518400, 0xf4b693c6
+1,       3746,       3746,       10,     2013, 0xd1b5a128
+1,       3756,       3756,       10,     2013, 0x303cc102
+1,       3766,       3766,       10,     2013, 0xb6ca93df
+0,        113,        113,        1,   518400, 0xce3dc275
+1,       3782,       3782,       10,     2013, 0x0db7a475
+1,       3792,       3792,       10,     2013, 0xf3f49ed7
+1,       3802,       3802,       10,     2013, 0xf495a819
+0,        114,        114,        1,   518400, 0xefbb7496
+1,       3812,       3812,       10,     2013, 0x2b67a99d
+1,       3822,       3822,       10,     2013, 0xe4efb19a
+1,       3832,       3832,       10,     2013, 0xb0e897ca
+0,        115,        115,        1,   518400, 0x6842b14e
+1,       3842,       3842,       10,     2013, 0x338ebe28
+1,       3852,       3852,       10,     2013, 0x0583ad3f
+1,       3867,       3867,       10,     2013, 0x7ae1a08d
+0,        116,        116,        1,   518400, 0x7a3fd65c
+1,       3877,       3877,       10,     2013, 0x95a39f9c
+1,       3887,       3887,       10,     2013, 0x4f7ea123
+1,       3897,       3897,       10,     2013, 0x9efb9ba1
+0,        117,        117,        1,   518400, 0x949e1e8b
+1,       3907,       3907,       10,     2013, 0xf395b2cd
+1,       3917,       3917,       10,     2013, 0x261a881e
+1,       3927,       3927,       10,     2013, 0x7f2d9f72
+1,       3937,       3937,       10,     2013, 0x0105b38d
+0,        118,        118,        1,   518400, 0xfc6c09aa
+1,       3952,       3952,       10,     2013, 0x0e5db67e
+1,       3962,       3962,       10,     2013, 0xfc9baf97
+0,        119,        119,        1,   518400, 0x561c2ff5
+1,       3972,       3972,       10,     2013, 0x8e02a1b1
+1,       3982,       3982,       10,     2013, 0x6eecaac8
+1,       3992,       3992,       10,     2013, 0xf5558f0c
+1,       4002,       4002,       10,     2013, 0x512ba99b
+0,        120,        120,        1,   518400, 0xfd62e6bd
+1,       4012,       4012,       10,     2013, 0x932b9932
+1,       4022,       4022,       10,     2013, 0xc01ea987
+0,        121,        121,        1,   518400, 0x0427a070
+1,       4038,       4038,       10,     2013, 0x10879cf7
+1,       4048,       4048,       10,     2013, 0x90679338
+1,       4058,       4058,       10,     2013, 0x077d8a9e
+1,       4068,       4068,       10,     2013, 0x969fa57c
+0,        122,        122,        1,   518400, 0x0bf48fff
+1,       4078,       4078,       10,     2013, 0xe049ab07
+1,       4088,       4088,       10,     2013, 0xf535b3b3
+1,       4098,       4098,       10,     2013, 0xfe76bd37
+0,        123,        123,        1,   518400, 0x354d4700
+1,       4108,       4108,       10,     2013, 0xde79ad8c
+1,       4123,       4123,       10,     2013, 0xe89b9c47
+1,       4133,       4133,       10,     2013, 0xc570b0f0
+0,        124,        124,        1,   518400, 0x6081c80c
+1,       4143,       4143,       10,     2013, 0xee709cd9
+1,       4153,       4153,       10,     2013, 0xcfe5afab
+1,       4163,       4163,       10,     2013, 0x98ff8ce4
+0,        125,        125,        1,   518400, 0x9c6c51c6
+1,       4173,       4173,       10,     2013, 0x9d19b44c
+1,       4183,       4183,       10,     2013, 0x4349917a
+1,       4193,       4193,       10,     2013, 0xbf54a59a
+0,        126,        126,        1,   518400, 0xaacd34d7
+1,       4208,       4208,       10,     2013, 0xc4a399e0
+1,       4218,       4218,       10,     2013, 0x1bf58ff0
+1,       4228,       4228,       10,     2013, 0x3518ac56
+0,        127,        127,        1,   518400, 0x566bce8e
+1,       4238,       4238,       10,     2013, 0xcd38c1de
+1,       4248,       4248,       10,     2013, 0xbe7d9c4d
+1,       4258,       4258,       10,     2013, 0xe113a306
+1,       4268,       4268,       10,     2013, 0x083197ea
+0,        128,        128,        1,   518400, 0xb14f68b3
+1,       4278,       4278,       10,     2013, 0x1929b1eb
+1,       4294,       4294,       10,     2013, 0x5d6ea5af
+1,       4304,       4304,       10,     2013, 0x05519d53
+0,        129,        129,        1,   518400, 0x00545b29
+1,       4314,       4314,       10,     2013, 0x5773b380
+1,       4324,       4324,       10,     2013, 0xaa70a8f5
+1,       4334,       4334,       10,     2013, 0x990db0ec
+0,        130,        130,        1,   518400, 0x984bede5
+1,       4344,       4344,       10,     2013, 0x91d3a623
+1,       4354,       4354,       10,     2013, 0xc91f9824
+1,       4364,       4364,       10,     2013, 0x1d058abf
+0,        131,        131,        1,   518400, 0x6b9319c6
+1,       4379,       4379,       10,     2013, 0x8de1b8d5
+1,       4389,       4389,       10,     2013, 0x7872b06b
+1,       4399,       4399,       10,     2013, 0xa084c203
+0,        132,        132,        1,   518400, 0x1582ae8c
+1,       4409,       4409,       10,     2013, 0xff90ae8d
+1,       4419,       4419,       10,     2013, 0x61dead8e
+1,       4429,       4429,       10,     2013, 0xee76b284
+0,        133,        133,        1,   518400, 0xece339b6
+1,       4439,       4439,       10,     2013, 0xe888af7f
+1,       4449,       4449,       10,     2013, 0x5d57b115
+1,       4464,       4464,       10,     2013, 0xcdbfb1d0
+0,        134,        134,        1,   518400, 0x74946b8b
+1,       4474,       4474,       10,     2013, 0x2e28a952
+1,       4484,       4484,       10,     2013, 0x4795a994
+1,       4494,       4494,       10,     2013, 0x7e7ea304
+1,       4504,       4504,       10,     2013, 0x9502c1e1
+0,        135,        135,        1,   518400, 0x5dffc0d6
+1,       4514,       4514,       10,     2013, 0xf7c78ab2
+1,       4524,       4524,       10,     2013, 0x24049816
+1,       4534,       4534,       10,     2013, 0x52089dcf
+0,        136,        136,        1,   518400, 0x3f85c053
+1,       4550,       4550,       10,     2013, 0x2150a0b1
+1,       4560,       4560,       10,     2013, 0x3c2e9b93
+1,       4570,       4570,       10,     2013, 0x491f932b
+0,        137,        137,        1,   518400, 0x7124125d
+1,       4580,       4580,       10,     2013, 0x31359cf8
+1,       4590,       4590,       10,     2013, 0x1b00ac3f
+1,       4600,       4600,       10,     2013, 0x8d7ab3cb
+0,        138,        138,        1,   518400, 0x46b736d5
+1,       4610,       4610,       10,     2013, 0xb2c2a4de
+1,       4620,       4620,       10,     2013, 0x80a4abf2
+1,       4635,       4635,       10,     2013, 0x0701a4ee
+0,        139,        139,        1,   518400, 0x7bcac123
+1,       4645,       4645,       10,     2013, 0xdc1ba5bc
+1,       4655,       4655,       10,     2013, 0x6083a8a4
+1,       4665,       4665,       10,     2013, 0x6226ad45
+0,        140,        140,        1,   518400, 0x79899382
+1,       4675,       4675,       10,     2013, 0x2732a205
+1,       4685,       4685,       10,     2013, 0x0f62a0d3
+1,       4695,       4695,       10,     2013, 0xc1799249
+0,        141,        141,        1,   518400, 0x4a56acef
+1,       4705,       4705,       10,     2013, 0xbccfa9c8
+1,       4720,       4720,       10,     2013, 0xded096e7
+1,       4730,       4730,       10,     2013, 0x7f0daf43
+0,        142,        142,        1,   518400, 0xb0a983e5
+1,       4740,       4740,       10,     2013, 0xc47ea682
+1,       4750,       4750,       10,     2013, 0x5a72b07a
+1,       4760,       4760,       10,     2013, 0x386faa8c
+1,       4770,       4770,       10,     2013, 0xf9919a91
+0,        143,        143,        1,   518400, 0xb49255cc
+1,       4780,       4780,       10,     2013, 0x4908897e
+1,       4790,       4790,       10,     2013, 0x4882b594
+0,        144,        144,        1,   518400, 0x48808663
+1,       4806,       4806,       10,     2013, 0x113e98d1
+1,       4816,       4816,       10,     2013, 0x5098b30d
+1,       4826,       4826,       10,     2013, 0x0ef7b857
+1,       4836,       4836,       10,     2013, 0x216ea176
+0,        145,        145,        1,   518400, 0xf5be828c
+1,       4846,       4846,       10,     2013, 0xf906944a
+1,       4856,       4856,       10,     2013, 0xee9b92fb
+1,       4866,       4866,       10,     2013, 0xd6029209
+0,        146,        146,        1,   518400, 0xb6688ea3
+1,       4876,       4876,       10,     2013, 0x2256a12e
+1,       4891,       4891,       10,     2013, 0x89de8e4a
+1,       4901,       4901,       10,     2013, 0x0bf0a584
+0,        147,        147,        1,   518400, 0x9eb2bfd1
+1,       4911,       4911,       10,     2013, 0x6a5ebd58
+1,       4921,       4921,       10,     2013, 0x3edd9aa4
+1,       4931,       4931,       10,     2013, 0xbd66ac26
+0,        148,        148,        1,   518400, 0xab3bdfb5
+1,       4941,       4941,       10,     2013, 0x313896ea
+1,       4951,       4951,       10,     2013, 0x6b83a6a0
+1,       4961,       4961,       10,     2013, 0x9aafb109
+0,        149,        149,        1,   518400, 0xe65f1d81
+1,       4976,       4976,       10,     2013, 0x5192a85a
+1,       4986,       4986,       10,     2013, 0x1f919f79
+1,       4996,       4996,       10,     2013, 0xc0799c40
+0,        150,        150,        1,   518400, 0x61ca8d13
+1,       5006,       5006,       10,     2013, 0x2988bcd8
+1,       5016,       5016,       10,     2013, 0x1482913a
+1,       5026,       5026,       10,     2013, 0x74da9a94
+1,       5036,       5036,       10,     2013, 0x763eb709
+0,        151,        151,        1,   518400, 0xbdd0d82f
+1,       5046,       5046,       10,     2013, 0x1285b405
+1,       5062,       5062,       10,     2013, 0xb6ab9dfc
+0,        152,        152,        1,   518400, 0xab1acaad
+1,       5072,       5072,       10,     2013, 0xe4c8bf19
+1,       5082,       5082,       10,     2013, 0xabbbade8
+1,       5092,       5092,       10,     2013, 0xf8b69d89
+1,       5102,       5102,       10,     2013, 0xce04a866
+0,        153,        153,        1,   518400, 0x1889f31c
+1,       5112,       5112,       10,     2013, 0x07528abf
+1,       5122,       5122,       10,     2013, 0x74fb98bf
+1,       5132,       5132,       10,     2013, 0x579fb1c9
+0,        154,        154,        1,   518400, 0x02484cce
+1,       5147,       5147,       10,     2013, 0x7ddea2ed
+1,       5157,       5157,       10,     2013, 0x296caa2c
+1,       5167,       5167,       10,     2013, 0x346d9c4f
+0,        155,        155,        1,   518400, 0x59998165
+1,       5177,       5177,       10,     2013, 0x3e1fba15
+1,       5187,       5187,       10,     2013, 0x48a2908f
+1,       5197,       5197,       10,     2013, 0xc1938d09
+0,        156,        156,        1,   518400, 0x0f3dd671
+1,       5207,       5207,       10,     2013, 0x0e96a060
+1,       5217,       5217,       10,     2013, 0x7b6a9e06
+1,       5232,       5232,       10,     2013, 0x5b779d28
+0,        157,        157,        1,   518400, 0x378bee63
+1,       5242,       5242,       10,     2013, 0xf600aca1
+1,       5252,       5252,       10,     2013, 0x3a6c9e68
+1,       5262,       5262,       10,     2013, 0x0c8dc1b0
+0,        158,        158,        1,   518400, 0x0d8e17d2
+1,       5272,       5272,       10,     2013, 0x26beb245
+1,       5282,       5282,       10,     2013, 0x2bc09557
+1,       5292,       5292,       10,     2013, 0x27fc8845
+1,       5302,       5302,       10,     2013, 0x1025aa47
+0,        159,        159,        1,   518400, 0x61f113bf
+1,       5318,       5318,       10,     2013, 0xc2e69baa
+1,       5328,       5328,       10,     2013, 0xdb249b92
+1,       5338,       5338,       10,     2013, 0x6ccda29e
+0,        160,        160,        1,   518400, 0x44ec211a
+1,       5348,       5348,       10,     2013, 0xeaf6a1cf
+1,       5358,       5358,       10,     2013, 0x509ba397
+1,       5368,       5368,       10,     2013, 0xfaf8a2df
+0,        161,        161,        1,   518400, 0xcb036306
+1,       5378,       5378,       10,     2013, 0x41388f28
+1,       5388,       5388,       10,     2013, 0xfe5eab39
+1,       5403,       5403,       10,     2013, 0xd5ffa066
+0,        162,        162,        1,   518400, 0x7f1dec7d
+1,       5413,       5413,       10,     2013, 0x6813a30a
+1,       5423,       5423,       10,     2013, 0x9be89718
+1,       5433,       5433,       10,     2013, 0xaec3a27b
+0,        163,        163,        1,   518400, 0x8b8c6640
+1,       5446,       5446,       10,     2013, 0x579a983e
+1,       5456,       5456,       10,     2013, 0x98cea21f
+1,       5466,       5466,       10,     2013, 0xca77a58a
+0,        164,        164,        1,   518400, 0xea04737c
+1,       5476,       5476,       10,     2013, 0xcbc3b1ee
+1,       5486,       5486,       10,     2013, 0xf3bb8f07
+1,       5496,       5496,       10,     2013, 0x6aeebd92
+0,        165,        165,        1,   518400, 0xe779fe0c
+1,       5506,       5506,       10,     2013, 0xe955a449
+1,       5516,       5516,       10,     2013, 0x9436aa5b
+1,       5531,       5531,       10,     2013, 0x4f0a8f9f
+0,        166,        166,        1,   518400, 0xcd78bf13
+1,       5541,       5541,       10,     2013, 0x3551b22d
+1,       5551,       5551,       10,     2013, 0x0959a3d4
+1,       5561,       5561,       10,     2013, 0x2ed5a11b
+1,       5571,       5571,       10,     2013, 0x8f52a5c3
+0,        167,        167,        1,   518400, 0x45b0c048
+1,       5581,       5581,       10,     2013, 0x6552978d
+1,       5591,       5591,       10,     2013, 0x7dcca0c1
+1,       5601,       5601,       10,     2013, 0xbcd4a3c9
+0,        168,        168,        1,   518400, 0x9783dcd8
+1,       5616,       5616,       10,     2013, 0xfe41a8d8
+1,       5626,       5626,       10,     2013, 0xc85aae14
+1,       5636,       5636,       10,     2013, 0x1185b346
+0,        169,        169,        1,   518400, 0xbcd1514c
+1,       5646,       5646,       10,     2013, 0xf7429a0d
+1,       5656,       5656,       10,     2013, 0x48c2a160
+1,       5666,       5666,       10,     2013, 0x9d85a85d
+0,        170,        170,        1,   518400, 0xf229575f
+1,       5676,       5676,       10,     2013, 0xbbe89fe9
+1,       5686,       5686,       10,     2013, 0xea429fe2
+1,       5702,       5702,       10,     2013, 0x221ca1d4
+0,        171,        171,        1,   518400, 0x576e365e
+1,       5712,       5712,       10,     2013, 0x394b925b
+1,       5722,       5722,       10,     2013, 0x556dc26f
+1,       5732,       5732,       10,     2013, 0xce21a5e1
+0,        172,        172,        1,   518400, 0xa2d2d87b
+1,       5742,       5742,       10,     2013, 0xbc87c0a8
+1,       5752,       5752,       10,     2013, 0xbac4ac07
+1,       5762,       5762,       10,     2013, 0xdeefa4aa
+1,       5772,       5772,       10,     2013, 0x1f15b362
+0,        173,        173,        1,   518400, 0x3804d74a
+1,       5787,       5787,       10,     2013, 0x6406b7b2
+1,       5797,       5797,       10,     2013, 0x8030a03d
+0,        174,        174,        1,   518400, 0xf05de372
+1,       5807,       5807,       10,     2013, 0x0373a5b1
+1,       5817,       5817,       10,     2013, 0x34ef93da
+1,       5827,       5827,       10,     2013, 0x94c198fe
+1,       5837,       5837,       10,     2013, 0xfefcabad
+0,        175,        175,        1,   518400, 0x21035b4f
+1,       5847,       5847,       10,     2013, 0x8755b3ec
+1,       5857,       5857,       10,     2013, 0xe436a6fd
+1,       5872,       5872,       10,     2013, 0x9cf5a11e
+0,        176,        176,        1,   518400, 0x6e97d583
+1,       5882,       5882,       10,     2013, 0x03b8a98c
+1,       5892,       5892,       10,     2013, 0x6216a138
+1,       5902,       5902,       10,     2013, 0xd87b9f12
+0,        177,        177,        1,   518400, 0x197879a9
+1,       5912,       5912,       10,     2013, 0x4ce99653
+1,       5922,       5922,       10,     2013, 0x6c2ea9e2
+1,       5932,       5932,       10,     2013, 0x918cae4c
+0,        178,        178,        1,   518400, 0x787780ee
+1,       5942,       5942,       10,     2013, 0xd19fa5f2
+1,       5958,       5958,       10,     2013, 0x0bdda7c6
+1,       5968,       5968,       10,     2013, 0x0f9ab0ca
+0,        179,        179,        1,   518400, 0x13fcc74d
+1,       5978,       5978,       10,     2013, 0x410a92b1
+1,       5988,       5988,       10,     2013, 0xcfbe9d1c
+1,       5998,       5998,       10,     2013, 0x59ed9d15
+0,        180,        180,        1,   518400, 0x9bd1c5da
+1,       6008,       6008,       10,     2013, 0x4e129e27
+1,       6018,       6018,       10,     2013, 0x7bb9ac0a
+1,       6028,       6028,       10,     2013, 0x826ca82b
+0,        181,        181,        1,   518400, 0x8e21e4ba
+1,       6043,       6043,       10,     2013, 0x9ad5a74b
+1,       6053,       6053,       10,     2013, 0x6c5f969a
+1,       6063,       6063,       10,     2013, 0x8479a0e5
+0,        182,        182,        1,   518400, 0x5fe59996
+1,       6073,       6073,       10,     2013, 0x165298ef
+1,       6083,       6083,       10,     2013, 0xdcadb4a1
+1,       6093,       6093,       10,     2013, 0xa90e987c
+1,       6103,       6103,       10,     2013, 0x1ac5b510
+0,        183,        183,        1,   518400, 0x308af432
+1,       6113,       6113,       10,     2013, 0x66728d85
+1,       6128,       6128,       10,     2013, 0xe4859fc5
+1,       6138,       6138,       10,     2013, 0x9901786e
+0,        184,        184,        1,   518400, 0xc05a9eb1
+1,       6148,       6148,       10,     2013, 0x6aebb406
+1,       6158,       6158,       10,     2013, 0x7d13a2cc
+1,       6168,       6168,       10,     2013, 0x99b7a8cc
+0,        185,        185,        1,   518400, 0xb9a02e51
+1,       6178,       6178,       10,     2013, 0x80b8a624
+1,       6188,       6188,       10,     2013, 0xbb6aa271
+1,       6198,       6198,       10,     2013, 0x17af9e4a
+0,        186,        186,        1,   518400, 0xbd9543aa
+1,       6214,       6214,       10,     2013, 0xfaf0a8f1
+1,       6224,       6224,       10,     2013, 0xd6849b93
+1,       6234,       6234,       10,     2013, 0xe9829669
+0,        187,        187,        1,   518400, 0x0a0cb795
+1,       6244,       6244,       10,     2013, 0x7ec98944
+1,       6254,       6254,       10,     2013, 0x2b2099a4
+1,       6264,       6264,       10,     2013, 0x1033a82f
+0,        188,        188,        1,   518400, 0xe4bb8a0c
+1,       6274,       6274,       10,     2013, 0x5ec88990
+1,       6284,       6284,       10,     2013, 0xd2a19b3d
+1,       6299,       6299,       10,     2013, 0xa377b268
+0,        189,        189,        1,   518400, 0x226fd11e
+1,       6309,       6309,       10,     2013, 0xfa859901
+1,       6319,       6319,       10,     2013, 0x1713955a
+1,       6329,       6329,       10,     2013, 0x70aab0da
+1,       6339,       6339,       10,     2013, 0xcdaea422
+0,        190,        190,        1,   518400, 0x76e1604d
+1,       6349,       6349,       10,     2013, 0x65c3bf80
+1,       6359,       6359,       10,     2013, 0x1d75a55f
+1,       6369,       6369,       10,     2013, 0xa5bea4de
+0,        191,        191,        1,   518400, 0xca06117c
+1,       6384,       6384,       10,     2013, 0x184db71c
+1,       6394,       6394,       10,     2013, 0x99858ec8
+1,       6404,       6404,       10,     2013, 0xb8f2aee5
+0,        192,        192,        1,   518400, 0xeca14952
+1,       6414,       6414,       10,     2013, 0x4435b2ef
+1,       6424,       6424,       10,     2013, 0x8acfa6c7
+1,       6434,       6434,       10,     2013, 0x42b4c01f
+0,        193,        193,        1,   518400, 0x3106dbee
+1,       6444,       6444,       10,     2013, 0x6e308c13
+1,       6454,       6454,       10,     2013, 0x8227a0f6
+1,       6470,       6470,       10,     2013, 0x6f12a7a2
+0,        194,        194,        1,   518400, 0x57fa6392
+1,       6480,       6480,       10,     2013, 0x785392be
+1,       6490,       6490,       10,     2013, 0x81849c2b
+1,       6500,       6500,       10,     2013, 0x5cf2af65
+0,        195,        195,        1,   518400, 0x47651ac8
+1,       6510,       6510,       10,     2013, 0x0c6ca6b4
+1,       6520,       6520,       10,     2013, 0x412fab9f
+1,       6530,       6530,       10,     2013, 0x08e792b4
+0,        196,        196,        1,   518400, 0x3c1ba6a5
+1,       6540,       6540,       10,     2013, 0x407aace3
+1,       6555,       6555,       10,     2013, 0xd26bac16
+1,       6565,       6565,       10,     2013, 0xac8bb295
+0,        197,        197,        1,   518400, 0xbc3ec05b
+1,       6575,       6575,       10,     2013, 0xddd1949c
+1,       6585,       6585,       10,     2013, 0x6b26b868
+1,       6595,       6595,       10,     2013, 0x5eaba587
+1,       6605,       6605,       10,     2013, 0xef0793b9
+0,        198,        198,        1,   518400, 0xd6ae59da
+1,       6615,       6615,       10,     2013, 0xdef19bd6
+1,       6625,       6625,       10,     2013, 0xca98a635
+0,        199,        199,        1,   518400, 0xc62f0e63
+1,       6640,       6640,       10,     2013, 0x06269a5a
+1,       6650,       6650,       10,     2013, 0x32cb9952
+1,       6660,       6660,       10,     2013, 0xf01fa95a
+1,       6670,       6670,       10,     2013, 0xefab9e55
+0,        200,        200,        1,   518400, 0xae96cc02
+1,       6680,       6680,       10,     2013, 0x55a3b63a
+1,       6690,       6690,       10,     2013, 0xcd36a553
+1,       6700,       6700,       10,     2013, 0x2ec19877
+0,        201,        201,        1,   518400, 0x2aa0917b
+1,       6710,       6710,       10,     2013, 0xc18b924c
+1,       6726,       6726,       10,     2013, 0xf132b04c
+1,       6736,       6736,       10,     2013, 0x7975a44d
+0,        202,        202,        1,   518400, 0xf0d13b48
+1,       6746,       6746,       10,     2013, 0x2aaf94cb
+1,       6756,       6756,       10,     2013, 0x58cfa60f
+1,       6766,       6766,       10,     2013, 0x9757a658
+0,        203,        203,        1,   518400, 0x067f56f8
+1,       6776,       6776,       10,     2013, 0x67ebc0d5
+1,       6786,       6786,       10,     2013, 0x3c50a70e
+1,       6796,       6796,       10,     2013, 0x9c5799c6
+0,        204,        204,        1,   518400, 0x1026025c
+1,       6811,       6811,       10,     2013, 0x018d85b2
+1,       6821,       6821,       10,     2013, 0x5367a956
+0,        205,        205,        1,   518400, 0x11ee7f7f
+0,        208,        208,        1,   518400, 0x30a6b398
+0,        240,        240,        1,   518400, 0x9d2e3977
diff --git a/tests/ref/fate/filter-overlay_rgb b/tests/ref/fate/filter-overlay_rgb
index cb94aa5..89a0177 100644
--- a/tests/ref/fate/filter-overlay_rgb
+++ b/tests/ref/fate/filter-overlay_rgb
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0x027e34c6
 0,          1,          1,        1,   304128, 0xc436b3d2
 0,          2,          2,        1,   304128, 0x86b77f58
diff --git a/tests/ref/fate/filter-overlay_yuv420 b/tests/ref/fate/filter-overlay_yuv420
index a1f6787..7cd0708 100644
--- a/tests/ref/fate/filter-overlay_yuv420
+++ b/tests/ref/fate/filter-overlay_yuv420
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xfbd72a27
 0,          1,          1,        1,   152064, 0x06d10a14
 0,          2,          2,        1,   152064, 0x629e9a71
diff --git a/tests/ref/fate/filter-overlay_yuv422 b/tests/ref/fate/filter-overlay_yuv422
index 982386b..99ce8c5 100644
--- a/tests/ref/fate/filter-overlay_yuv422
+++ b/tests/ref/fate/filter-overlay_yuv422
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0x9b9e09b2
 0,          1,          1,        1,   304128, 0x33addb48
 0,          2,          2,        1,   304128, 0xd5b973e9
diff --git a/tests/ref/fate/filter-overlay_yuv444 b/tests/ref/fate/filter-overlay_yuv444
index 0b2d9f7..3b6e53a 100644
--- a/tests/ref/fate/filter-overlay_yuv444
+++ b/tests/ref/fate/filter-overlay_yuv444
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   405504, 0xaa82add0
 0,          1,          1,        1,   405504, 0x0e9d65d0
 0,          2,          2,        1,   405504, 0xd8470d82
diff --git a/tests/ref/fate/filter-palettegen-1 b/tests/ref/fate/filter-palettegen-1
index 98b7159..bebfd24 100644
--- a/tests/ref/fate/filter-palettegen-1
+++ b/tests/ref/fate/filter-palettegen-1
@@ -1,2 +1,6 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x16
+#sar 0: 1/1
 0,          0,          0,        1,     1024, 0x3395ef5a
diff --git a/tests/ref/fate/filter-palettegen-2 b/tests/ref/fate/filter-palettegen-2
index 2f58b64..aa07b6c 100644
--- a/tests/ref/fate/filter-palettegen-2
+++ b/tests/ref/fate/filter-palettegen-2
@@ -1,2 +1,6 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x16
+#sar 0: 1/1
 0,          0,          0,        1,     1024, 0x906ff5aa
diff --git a/tests/ref/fate/filter-paletteuse-bayer b/tests/ref/fate/filter-paletteuse-bayer
index 4b44939..5ca0115 100644
--- a/tests/ref/fate/filter-paletteuse-bayer
+++ b/tests/ref/fate/filter-paletteuse-bayer
@@ -1,4 +1,8 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x180
+#sar 0: 1/1
 0,          0,          0,        1,   230400, 0x7b259d08
 0,          1,          1,        1,   230400, 0xf04095e0
 0,          2,          2,        1,   230400, 0x84d49cd5
diff --git a/tests/ref/fate/filter-paletteuse-nodither b/tests/ref/fate/filter-paletteuse-nodither
index 8171ffa..a2e61c3 100644
--- a/tests/ref/fate/filter-paletteuse-nodither
+++ b/tests/ref/fate/filter-paletteuse-nodither
@@ -1,4 +1,8 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x180
+#sar 0: 1/1
 0,          0,          0,        1,   230400, 0x690560cb
 0,          1,          1,        1,   230400, 0x197a5a54
 0,          2,          2,        1,   230400, 0x665961db
diff --git a/tests/ref/fate/filter-paletteuse-sierra2_4a b/tests/ref/fate/filter-paletteuse-sierra2_4a
index 95d7636..d257820 100644
--- a/tests/ref/fate/filter-paletteuse-sierra2_4a
+++ b/tests/ref/fate/filter-paletteuse-sierra2_4a
@@ -1,4 +1,8 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x180
+#sar 0: 1/1
 0,          0,          0,        1,   230400, 0xa4f85758
 0,          1,          1,        1,   230400, 0xbe83505c
 0,          2,          2,        1,   230400, 0x0a09584e
diff --git a/tests/ref/fate/filter-phase b/tests/ref/fate/filter-phase
index e0ec8d6..b0f8a25 100644
--- a/tests/ref/fate/filter-phase
+++ b/tests/ref/fate/filter-phase
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x05b789ef
 0,          1,          1,        1,   152064, 0x4bb46551
 0,          2,          2,        1,   152064, 0x9dddf64a
diff --git a/tests/ref/fate/filter-pixfmts-fieldmatch b/tests/ref/fate/filter-pixfmts-fieldmatch
index 44622d0..99946c8 100644
--- a/tests/ref/fate/filter-pixfmts-fieldmatch
+++ b/tests/ref/fate/filter-pixfmts-fieldmatch
@@ -1,5 +1,5 @@
 yuv410p             a6c9b4065e8253d8120772f69be0bf04
 yuv411p             b913e634ad37ce046240252bed8681fb
-yuv420p             d448d95326eadeeb12ea0cc348067958
+yuv420p             a9286560141eb14595e427dbe5829b00
 yuv422p             11ad22ce00c5e8a30d0472f29fb15434
 yuv444p             9350a3f23cd7d95ec441a49f63f55953
diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad
index 9e474b9..e94db4f 100644
--- a/tests/ref/fate/filter-pixfmts-pad
+++ b/tests/ref/fate/filter-pixfmts-pad
@@ -7,20 +7,54 @@ bgr24               f8b65ad845905c7d0c93ca28dfbb826f
 bgra                929aac15e848038e367c250037575f9f
 gbrap               6712984b4a068ffa534f0cb35b2adc6f
 gbrp                3c94d39256db2409015df913fd330a90
+gbrp10le            f206db2a32ad484a59cf3e596bdc2866
+gbrp12le            be6463331985e2c8ed7bd910093ca4a2
+gbrp14le            9ae804cf217bec0a737c36c20573cbe5
+gbrp9le             9a86dab5661c213ce2b7e00ae48b4d1f
 gray                ddc663a0491df3959d9c5795dceaa72e
+gray16le            468bda6155bdc7a7a20c34d6e599fd16
+nv12                381574979cb04be10c9168540310afad
+nv21                0fdeb2cdd56cf5a7147dc273456fa217
 rgb0                78d500c8361ab6423a4826a00268c908
 rgb24               17f9e2e0c609009acaf2175c42d4a2a5
 rgba                b157c90191463d34fb3ce77b36c96386
+xyz12le             85abf80b77a9236a76ba0b00fcbdea2d
 ya8                 5fc0f471207ddf7aa01b07027d56b672
 yuv410p             cb871dcc1e84a7ef1d21f9237b88cf6e
 yuv411p             aec2c1740de9a62db0d41f4dda9121b0
 yuv420p             4398e408fc35436ce4b20468946f58b6
+yuv420p10le         74518a7d68457c54da3300e80c683e9c
+yuv420p12le         32086c64c814315aa9253580708a192e
+yuv420p14le         265e9fefb8b92f3cae678eb3cf4e00b4
+yuv420p16le         1ca89e47164d5f2481e39d4ac6eab2ed
+yuv420p9le          59f0209084d1d1dd2861e058d1df63f4
 yuv422p             e43d68568d9f782908ba56bf1e09d5d5
+yuv422p10le         18667cf7f87d8ffe1c4cc3db2100c559
+yuv422p12le         71e32220fa1bbdcac95fb57ba0dbd4f0
+yuv422p14le         a0064be4d29079a811e5a315341da09a
+yuv422p16le         836057e9999c763697c66c21869492b8
+yuv422p9le          3213bed797e7b4cefa4f174dc33bf246
 yuv440p             a7e34de74c96b0224fe1381ec1db2ba7
+yuv440p10le         f91a481e27be7ea4a38a878e5e4330a3
+yuv440p12le         0e9953a09ac09fe5f1523b350cf7cb72
 yuv444p             6bfd89286dc36f2789b77d747ed8fa22
+yuv444p10le         b10afb5fda970dbce8aac5aab981a8cb
+yuv444p12le         8f1b4b0f91d309fdaaec8a1ba6c7107f
+yuv444p14le         2a87a84fa01237de9c08dd7e9ffbf78d
+yuv444p16le         28508867fe7470c3539f8a84e8fb8271
+yuv444p9le          99d39ef897c6037d6c7aa6e7a0398f84
 yuva420p            842c27169ecdcf6de79f2b787367b51c
+yuva420p10le        336fcb42c5b665c2028661e73325b359
+yuva420p16le        ff45de790e7bdd3c25d8aad51289aba9
+yuva420p9le         8ef1f3b3e01b5ce222e4caeec3dec396
 yuva422p            91dcecc4bfdff1f0db9ef8b9b5b9ac2a
+yuva422p10le        1ba292c74c8646fd077a6116142b1bc8
+yuva422p16le        383226550fe9c93d6e8bf0d45d1423d1
+yuva422p9le         0fb76788c905c6d448143aa3c5eae116
 yuva444p            fb60941a57596b277417a3c7c00aa194
+yuva444p10le        251ea4ead8300d752eb355a08cbb0352
+yuva444p16le        5b65287e1862d2d9f1ad2cfdcde94661
+yuva444p9le         e6946c10b94c271e7ea24b3bcff314e1
 yuvj411p            ca967e68759a4956729dd366adc7e7fa
 yuvj420p            c00611cd5f1558047d579d8a7d30e381
 yuvj422p            b3acdf07147a7598836065836ad8420b
diff --git a/tests/ref/fate/filter-pp b/tests/ref/fate/filter-pp
index c1311be..5c0e299 100644
--- a/tests/ref/fate/filter-pp
+++ b/tests/ref/fate/filter-pp
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 0,          1,          1,        1,   152064, 0x0af8a873
 0,          2,          2,        1,   152064, 0xaeb99897
 0,          3,          3,        1,   152064, 0x8f3712c8
diff --git a/tests/ref/fate/filter-removegrain-mode-00 b/tests/ref/fate/filter-removegrain-mode-00
index 115bc45..b38d3f4 100644
--- a/tests/ref/fate/filter-removegrain-mode-00
+++ b/tests/ref/fate/filter-removegrain-mode-00
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x05b789ef
diff --git a/tests/ref/fate/filter-removegrain-mode-01 b/tests/ref/fate/filter-removegrain-mode-01
index 0e74927..8108ab6 100644
--- a/tests/ref/fate/filter-removegrain-mode-01
+++ b/tests/ref/fate/filter-removegrain-mode-01
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x4f234e65
diff --git a/tests/ref/fate/filter-removegrain-mode-02 b/tests/ref/fate/filter-removegrain-mode-02
index be7a419..5e12fdf 100644
--- a/tests/ref/fate/filter-removegrain-mode-02
+++ b/tests/ref/fate/filter-removegrain-mode-02
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xc2dd0535
diff --git a/tests/ref/fate/filter-removegrain-mode-03 b/tests/ref/fate/filter-removegrain-mode-03
index 7f98bec..61b64f6 100644
--- a/tests/ref/fate/filter-removegrain-mode-03
+++ b/tests/ref/fate/filter-removegrain-mode-03
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x09dbc38a
diff --git a/tests/ref/fate/filter-removegrain-mode-04 b/tests/ref/fate/filter-removegrain-mode-04
index 510371d..d029896 100644
--- a/tests/ref/fate/filter-removegrain-mode-04
+++ b/tests/ref/fate/filter-removegrain-mode-04
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x32c6a66e
diff --git a/tests/ref/fate/filter-removegrain-mode-05 b/tests/ref/fate/filter-removegrain-mode-05
index 11ddc89..8fc5e25 100644
--- a/tests/ref/fate/filter-removegrain-mode-05
+++ b/tests/ref/fate/filter-removegrain-mode-05
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xc3c64ec6
diff --git a/tests/ref/fate/filter-removegrain-mode-06 b/tests/ref/fate/filter-removegrain-mode-06
index 8d3d318..c000f01 100644
--- a/tests/ref/fate/filter-removegrain-mode-06
+++ b/tests/ref/fate/filter-removegrain-mode-06
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x38e84065
diff --git a/tests/ref/fate/filter-removegrain-mode-07 b/tests/ref/fate/filter-removegrain-mode-07
index 9ce7217..c1a9836 100644
--- a/tests/ref/fate/filter-removegrain-mode-07
+++ b/tests/ref/fate/filter-removegrain-mode-07
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xfbdeec94
diff --git a/tests/ref/fate/filter-removegrain-mode-08 b/tests/ref/fate/filter-removegrain-mode-08
index 3a05d10..f382c11 100644
--- a/tests/ref/fate/filter-removegrain-mode-08
+++ b/tests/ref/fate/filter-removegrain-mode-08
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x8f7c85a2
diff --git a/tests/ref/fate/filter-removegrain-mode-09 b/tests/ref/fate/filter-removegrain-mode-09
index 4787c22..3bb63fc 100644
--- a/tests/ref/fate/filter-removegrain-mode-09
+++ b/tests/ref/fate/filter-removegrain-mode-09
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9609a659
diff --git a/tests/ref/fate/filter-removegrain-mode-10 b/tests/ref/fate/filter-removegrain-mode-10
index 7f76854..cf72639 100644
--- a/tests/ref/fate/filter-removegrain-mode-10
+++ b/tests/ref/fate/filter-removegrain-mode-10
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x4adb45d6
diff --git a/tests/ref/fate/filter-removegrain-mode-11 b/tests/ref/fate/filter-removegrain-mode-11
index f2c3be0..aa8793d 100644
--- a/tests/ref/fate/filter-removegrain-mode-11
+++ b/tests/ref/fate/filter-removegrain-mode-11
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xd0d891ff
diff --git a/tests/ref/fate/filter-removegrain-mode-12 b/tests/ref/fate/filter-removegrain-mode-12
index f2c3be0..aa8793d 100644
--- a/tests/ref/fate/filter-removegrain-mode-12
+++ b/tests/ref/fate/filter-removegrain-mode-12
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xd0d891ff
diff --git a/tests/ref/fate/filter-removegrain-mode-13 b/tests/ref/fate/filter-removegrain-mode-13
index b481928..b70b9a1 100644
--- a/tests/ref/fate/filter-removegrain-mode-13
+++ b/tests/ref/fate/filter-removegrain-mode-13
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x09d4da80
diff --git a/tests/ref/fate/filter-removegrain-mode-14 b/tests/ref/fate/filter-removegrain-mode-14
index 7355a61..2211372 100644
--- a/tests/ref/fate/filter-removegrain-mode-14
+++ b/tests/ref/fate/filter-removegrain-mode-14
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x145f34c8
diff --git a/tests/ref/fate/filter-removegrain-mode-15 b/tests/ref/fate/filter-removegrain-mode-15
index 4c11088..fa9b94c 100644
--- a/tests/ref/fate/filter-removegrain-mode-15
+++ b/tests/ref/fate/filter-removegrain-mode-15
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x11eea9b4
diff --git a/tests/ref/fate/filter-removegrain-mode-16 b/tests/ref/fate/filter-removegrain-mode-16
index 9b1ab23..9d81e15 100644
--- a/tests/ref/fate/filter-removegrain-mode-16
+++ b/tests/ref/fate/filter-removegrain-mode-16
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x8bc800ee
diff --git a/tests/ref/fate/filter-removegrain-mode-17 b/tests/ref/fate/filter-removegrain-mode-17
index 29b383e..4f4b758 100644
--- a/tests/ref/fate/filter-removegrain-mode-17
+++ b/tests/ref/fate/filter-removegrain-mode-17
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x7195b9a7
diff --git a/tests/ref/fate/filter-removegrain-mode-18 b/tests/ref/fate/filter-removegrain-mode-18
index 84aa1ec..a4422a7 100644
--- a/tests/ref/fate/filter-removegrain-mode-18
+++ b/tests/ref/fate/filter-removegrain-mode-18
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xb47a081c
diff --git a/tests/ref/fate/filter-removegrain-mode-19 b/tests/ref/fate/filter-removegrain-mode-19
index 86887a6..9ff3613 100644
--- a/tests/ref/fate/filter-removegrain-mode-19
+++ b/tests/ref/fate/filter-removegrain-mode-19
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x948dc65d
diff --git a/tests/ref/fate/filter-removegrain-mode-20 b/tests/ref/fate/filter-removegrain-mode-20
index def86fe..449ced8 100644
--- a/tests/ref/fate/filter-removegrain-mode-20
+++ b/tests/ref/fate/filter-removegrain-mode-20
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x64a388ea
diff --git a/tests/ref/fate/filter-removegrain-mode-21 b/tests/ref/fate/filter-removegrain-mode-21
index 832c1b1..473b4fc 100644
--- a/tests/ref/fate/filter-removegrain-mode-21
+++ b/tests/ref/fate/filter-removegrain-mode-21
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xb7ae17f5
diff --git a/tests/ref/fate/filter-removegrain-mode-22 b/tests/ref/fate/filter-removegrain-mode-22
index f689e3f..8185750 100644
--- a/tests/ref/fate/filter-removegrain-mode-22
+++ b/tests/ref/fate/filter-removegrain-mode-22
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xe5736698
diff --git a/tests/ref/fate/filter-removegrain-mode-23 b/tests/ref/fate/filter-removegrain-mode-23
index b0a588b..1e8109d 100644
--- a/tests/ref/fate/filter-removegrain-mode-23
+++ b/tests/ref/fate/filter-removegrain-mode-23
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x8d15a472
diff --git a/tests/ref/fate/filter-removegrain-mode-24 b/tests/ref/fate/filter-removegrain-mode-24
index 286ce22..b246312 100644
--- a/tests/ref/fate/filter-removegrain-mode-24
+++ b/tests/ref/fate/filter-removegrain-mode-24
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x77f6d439
diff --git a/tests/ref/fate/filter-scalechroma b/tests/ref/fate/filter-scalechroma
index 930ffef..842769c 100644
--- a/tests/ref/fate/filter-scalechroma
+++ b/tests/ref/fate/filter-scalechroma
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xdcab783a
 0,          1,          1,        1,   152064, 0x79c7f1f6
 0,          2,          2,        1,   152064, 0x3b810afb
diff --git a/tests/ref/fate/filter-select b/tests/ref/fate/filter-select
index 7c30292..e0584e9 100644
--- a/tests/ref/fate/filter-select
+++ b/tests/ref/fate/filter-select
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x432
+#sar 0: 0/1
 0,          1,          1,        1,   152064, 0x7f5f6551
 0,          5,          5,        1,   152064, 0x287da8e6
 0,          7,          7,        1,   152064, 0xe9028bac
diff --git a/tests/ref/fate/filter-select-alternate b/tests/ref/fate/filter-select-alternate
index 0776694..044189d 100644
--- a/tests/ref/fate/filter-select-alternate
+++ b/tests/ref/fate/filter-select-alternate
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x05b789ef
 0,          2,          2,        1,   152064, 0x9dddf64a
 0,          4,          4,        1,   152064, 0x4de3b652
diff --git a/tests/ref/fate/filter-separatefields b/tests/ref/fate/filter-separatefields
index 46cb470..fb757cc 100644
--- a/tests/ref/fate/filter-separatefields
+++ b/tests/ref/fate/filter-separatefields
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x144
+#sar 0: 0/1
 0,          0,          0,        1,    76032, 0x99276ab9
 0,          1,          1,        1,    76032, 0x0b071f36
 0,          2,          2,        1,    76032, 0x8b03b0e8
diff --git a/tests/ref/fate/filter-setpts b/tests/ref/fate/filter-setpts
index 5b1d734..efdcf6a 100644
--- a/tests/ref/fate/filter-setpts
+++ b/tests/ref/fate/filter-setpts
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x05b789ef
 0,          1,          1,        1,   152064, 0x4bb46551
 0,          2,          2,        1,   152064, 0x9dddf64a
diff --git a/tests/ref/fate/filter-showpalette b/tests/ref/fate/filter-showpalette
index 1a13c23..c5e699a 100644
--- a/tests/ref/fate/filter-showpalette
+++ b/tests/ref/fate/filter-showpalette
@@ -1,4 +1,8 @@
 #tb 0: 1/35
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 48x48
+#sar 0: 0/1
 0,          0,          0,        1,     9216, 0xc72e034e
 0,          1,          1,        1,     9216, 0xc72e034e
 0,          2,          2,        1,     9216, 0xc72e034e
diff --git a/tests/ref/fate/filter-shuffleplanes-dup-luma b/tests/ref/fate/filter-shuffleplanes-dup-luma
index 52041fa..da111c2 100644
--- a/tests/ref/fate/filter-shuffleplanes-dup-luma
+++ b/tests/ref/fate/filter-shuffleplanes-dup-luma
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   405504, 0x76625893
 0,          1,          1,        1,   405504, 0x348f0b97
 0,          2,          2,        1,   405504, 0x3de02149
diff --git a/tests/ref/fate/filter-shuffleplanes-swapuv b/tests/ref/fate/filter-shuffleplanes-swapuv
index 95da149..9ff175b 100644
--- a/tests/ref/fate/filter-shuffleplanes-swapuv
+++ b/tests/ref/fate/filter-shuffleplanes-swapuv
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x68b189ef
 0,          1,          1,        1,   152064, 0x5cc66551
 0,          2,          2,        1,   152064, 0x88f0f64a
diff --git a/tests/ref/fate/filter-stereo3d-abr-ml b/tests/ref/fate/filter-stereo3d-abr-ml
index d0597a7..07c4cb7 100644
--- a/tests/ref/fate/filter-stereo3d-abr-ml
+++ b/tests/ref/fate/filter-stereo3d-abr-ml
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x144
+#sar 0: 0/1
 0,          0,          0,        1,    76032, 0xad4c8a22
 0,          1,          1,        1,    76032, 0x0dfdc6ad
 0,          2,          2,        1,    76032, 0x6341da83
diff --git a/tests/ref/fate/filter-stereo3d-abr-mr b/tests/ref/fate/filter-stereo3d-abr-mr
index 44a8091..4e9edea 100644
--- a/tests/ref/fate/filter-stereo3d-abr-mr
+++ b/tests/ref/fate/filter-stereo3d-abr-mr
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x144
+#sar 0: 0/1
 0,          0,          0,        1,    76032, 0x5d0effbe
 0,          1,          1,        1,    76032, 0x5bb49e95
 0,          2,          2,        1,    76032, 0xb6301bc7
diff --git a/tests/ref/fate/filter-stereo3d-al-sbsl b/tests/ref/fate/filter-stereo3d-al-sbsl
index b19cbb8..6f42820 100644
--- a/tests/ref/fate/filter-stereo3d-al-sbsl
+++ b/tests/ref/fate/filter-stereo3d-al-sbsl
@@ -1,4 +1,8 @@
 #tb 0: 2/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 704x288
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0xb9c0ef40
 0,          1,          1,        1,   304128, 0xfa0b7709
 0,          2,          2,        1,   304128, 0x14255f47
diff --git a/tests/ref/fate/filter-stereo3d-ar-abl b/tests/ref/fate/filter-stereo3d-ar-abl
index 0358199..6b5a971 100644
--- a/tests/ref/fate/filter-stereo3d-ar-abl
+++ b/tests/ref/fate/filter-stereo3d-ar-abl
@@ -1,4 +1,8 @@
 #tb 0: 2/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x576
+#sar 0: 0/1
 0,          0,          0,        1,   304128, 0x7babef40
 0,          1,          1,        1,   304128, 0x287d7709
 0,          2,          2,        1,   304128, 0x385f5f47
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-abl b/tests/ref/fate/filter-stereo3d-sbsl-abl
index 273e520..f0edf34 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-abl
+++ b/tests/ref/fate/filter-stereo3d-sbsl-abl
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x576
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x2f9389ef
 0,          1,          1,        1,   152064, 0x16c66551
 0,          2,          2,        1,   152064, 0xd779f64a
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-abr b/tests/ref/fate/filter-stereo3d-sbsl-abr
index c827e3c..2756d38 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-abr
+++ b/tests/ref/fate/filter-stereo3d-sbsl-abr
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x576
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xd1f489ef
 0,          1,          1,        1,   152064, 0xe4fe6551
 0,          2,          2,        1,   152064, 0xd0d9f64a
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-agmc b/tests/ref/fate/filter-stereo3d-sbsl-agmc
index 3a515b8..d86a226 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-agmc
+++ b/tests/ref/fate/filter-stereo3d-sbsl-agmc
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xa950d0d9
 0,          1,          1,        1,   152064, 0x6a6933c3
 0,          2,          2,        1,   152064, 0x66a1da3a
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-agmd b/tests/ref/fate/filter-stereo3d-sbsl-agmd
index 7d188d4..ab915d6 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-agmd
+++ b/tests/ref/fate/filter-stereo3d-sbsl-agmd
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x962d1371
 0,          1,          1,        1,   152064, 0xe7db1d51
 0,          2,          2,        1,   152064, 0x3bb0c409
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-agmg b/tests/ref/fate/filter-stereo3d-sbsl-agmg
index 3cae6f3..4ad85b6 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-agmg
+++ b/tests/ref/fate/filter-stereo3d-sbsl-agmg
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x45a6c9a8
 0,          1,          1,        1,   152064, 0xe7ba65fc
 0,          2,          2,        1,   152064, 0x88ab8fcc
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-agmh b/tests/ref/fate/filter-stereo3d-sbsl-agmh
index e6853a6..b50f5af 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-agmh
+++ b/tests/ref/fate/filter-stereo3d-sbsl-agmh
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x96464057
 0,          1,          1,        1,   152064, 0x58c4e280
 0,          2,          2,        1,   152064, 0xaf76fd24
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-al b/tests/ref/fate/filter-stereo3d-sbsl-al
index 5c8a429..1f9aaa4 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-al
+++ b/tests/ref/fate/filter-stereo3d-sbsl-al
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,    76032, 0x3ff06515
 0,          1,          1,        1,    76032, 0x00d824da
 0,          2,          2,        1,    76032, 0x64a33c64
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-arbg b/tests/ref/fate/filter-stereo3d-sbsl-arbg
index 1e87271..b5e4996 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-arbg
+++ b/tests/ref/fate/filter-stereo3d-sbsl-arbg
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x4d83ea30
 0,          1,          1,        1,   152064, 0xa4a3be5b
 0,          2,          2,        1,   152064, 0x21032989
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-arcc b/tests/ref/fate/filter-stereo3d-sbsl-arcc
index 56f17fd..bcecd87 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-arcc
+++ b/tests/ref/fate/filter-stereo3d-sbsl-arcc
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x2760b14a
 0,          1,          1,        1,   152064, 0xcf94baaf
 0,          2,          2,        1,   152064, 0x9b5e0e0a
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-arcd b/tests/ref/fate/filter-stereo3d-sbsl-arcd
index fd9806b..b5f11e2 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-arcd
+++ b/tests/ref/fate/filter-stereo3d-sbsl-arcd
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xa0261570
 0,          1,          1,        1,   152064, 0x678403c8
 0,          2,          2,        1,   152064, 0x1087e7b6
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-arcg b/tests/ref/fate/filter-stereo3d-sbsl-arcg
index 68f3f54..f5c5845 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-arcg
+++ b/tests/ref/fate/filter-stereo3d-sbsl-arcg
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x70f5c9a8
 0,          1,          1,        1,   152064, 0x56f165fc
 0,          2,          2,        1,   152064, 0xe59f8fcc
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-arch b/tests/ref/fate/filter-stereo3d-sbsl-arch
index 9c2fcd1..d6767df 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-arch
+++ b/tests/ref/fate/filter-stereo3d-sbsl-arch
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x81ab8dad
 0,          1,          1,        1,   152064, 0x820fd98a
 0,          2,          2,        1,   152064, 0x1ccc712b
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-argg b/tests/ref/fate/filter-stereo3d-sbsl-argg
index 91fb064..82fa276 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-argg
+++ b/tests/ref/fate/filter-stereo3d-sbsl-argg
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x2cfbea30
 0,          1,          1,        1,   152064, 0x4c44be5b
 0,          2,          2,        1,   152064, 0x87462989
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-aybc b/tests/ref/fate/filter-stereo3d-sbsl-aybc
index 72bd15c..1c24262 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-aybc
+++ b/tests/ref/fate/filter-stereo3d-sbsl-aybc
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xae8c985d
 0,          1,          1,        1,   152064, 0x489e1535
 0,          2,          2,        1,   152064, 0x01a83b2b
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-aybd b/tests/ref/fate/filter-stereo3d-sbsl-aybd
index d963480..0aa4e8b 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-aybd
+++ b/tests/ref/fate/filter-stereo3d-sbsl-aybd
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x7dc98468
 0,          1,          1,        1,   152064, 0xf72db6c9
 0,          2,          2,        1,   152064, 0x1630f53f
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-aybg b/tests/ref/fate/filter-stereo3d-sbsl-aybg
index 53f7f72..ebd8ba2 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-aybg
+++ b/tests/ref/fate/filter-stereo3d-sbsl-aybg
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x1a57c9a8
 0,          1,          1,        1,   152064, 0x789265fc
 0,          2,          2,        1,   152064, 0x2bb78fcc
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-aybh b/tests/ref/fate/filter-stereo3d-sbsl-aybh
index c6fdd14..1b9edeb 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-aybh
+++ b/tests/ref/fate/filter-stereo3d-sbsl-aybh
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf3ee182f
 0,          1,          1,        1,   152064, 0x8b1c25f1
 0,          2,          2,        1,   152064, 0xe78de2ac
diff --git a/tests/ref/fate/filter-stereo3d-sbsl-sbsr b/tests/ref/fate/filter-stereo3d-sbsl-sbsr
index b417ae4..9a5da96 100644
--- a/tests/ref/fate/filter-stereo3d-sbsl-sbsr
+++ b/tests/ref/fate/filter-stereo3d-sbsl-sbsr
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xbe2f89ef
 0,          1,          1,        1,   152064, 0x4c806551
 0,          2,          2,        1,   152064, 0x8165f64a
diff --git a/tests/ref/fate/filter-tblend b/tests/ref/fate/filter-tblend
index 3ff689a..80fea84 100644
--- a/tests/ref/fate/filter-tblend
+++ b/tests/ref/fate/filter-tblend
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          1,          1,        1,   152064, 0x8e50e5e5
 0,          2,          2,        1,   152064, 0x7187a95e
 0,          3,          3,        1,   152064, 0xbd73863e
diff --git a/tests/ref/fate/filter-telecine b/tests/ref/fate/filter-telecine
index b8a13a9..6d3545e 100644
--- a/tests/ref/fate/filter-telecine
+++ b/tests/ref/fate/filter-telecine
@@ -1,4 +1,8 @@
 #tb 0: 4/125
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x05b789ef
 0,          1,          1,        1,   152064, 0x4bb46551
 0,          2,          2,        1,   152064, 0x40692c80
diff --git a/tests/ref/fate/filter-testsrc2-rgb24 b/tests/ref/fate/filter-testsrc2-rgb24
index 2fdfa00..207ddfc 100644
--- a/tests/ref/fate/filter-testsrc2-rgb24
+++ b/tests/ref/fate/filter-testsrc2-rgb24
@@ -1,4 +1,8 @@
 #tb 0: 1/7
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   230400, 0x1c012312
 0,          1,          1,        1,   230400, 0xf7cf4e81
 0,          2,          2,        1,   230400, 0x29a45e1c
diff --git a/tests/ref/fate/filter-testsrc2-yuv420p b/tests/ref/fate/filter-testsrc2-yuv420p
index 804e5fa..aaf93ba 100644
--- a/tests/ref/fate/filter-testsrc2-yuv420p
+++ b/tests/ref/fate/filter-testsrc2-yuv420p
@@ -1,4 +1,8 @@
 #tb 0: 1/7
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   115200, 0x3744b3ed
 0,          1,          1,        1,   115200, 0x0c1062d6
 0,          2,          2,        1,   115200, 0x201b9db1
diff --git a/tests/ref/fate/filter-testsrc2-yuv444p b/tests/ref/fate/filter-testsrc2-yuv444p
index c8cc7c1..4b60e6a 100644
--- a/tests/ref/fate/filter-testsrc2-yuv444p
+++ b/tests/ref/fate/filter-testsrc2-yuv444p
@@ -1,4 +1,8 @@
 #tb 0: 1/7
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   230400, 0xbfb96366
 0,          1,          1,        1,   230400, 0xe63ca6e9
 0,          2,          2,        1,   230400, 0xc6acccc8
diff --git a/tests/ref/fate/filter-transpose b/tests/ref/fate/filter-transpose
index 0f23423..2a5151b 100644
--- a/tests/ref/fate/filter-transpose
+++ b/tests/ref/fate/filter-transpose
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 288x352
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xab5889ef
 0,          1,          1,        1,   152064, 0x898b6551
 0,          2,          2,        1,   152064, 0x231bf64a
diff --git a/tests/ref/fate/filter-trim-duration b/tests/ref/fate/filter-trim-duration
index db74add..9ba86f8 100644
--- a/tests/ref/fate/filter-trim-duration
+++ b/tests/ref/fate/filter-trim-duration
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x432
+#sar 0: 0/1
 0,         10,         10,        1,   152064, 0xb45c4760
diff --git a/tests/ref/fate/filter-trim-frame b/tests/ref/fate/filter-trim-frame
index 1749afd..5dbf6b7 100644
--- a/tests/ref/fate/filter-trim-frame
+++ b/tests/ref/fate/filter-trim-frame
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x432
+#sar 0: 0/1
 0,          3,          3,        1,   152064, 0xceb080b0
 0,          4,          4,        1,   152064, 0x473db652
 0,          5,          5,        1,   152064, 0x287da8e6
diff --git a/tests/ref/fate/filter-trim-mixed b/tests/ref/fate/filter-trim-mixed
index 5e003f6..6b1a98c 100644
--- a/tests/ref/fate/filter-trim-mixed
+++ b/tests/ref/fate/filter-trim-mixed
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x432
+#sar 0: 0/1
 0,          1,          1,        1,   152064, 0x7f5f6551
 0,          2,          2,        1,   152064, 0xc566f64a
 0,          3,          3,        1,   152064, 0xceb080b0
diff --git a/tests/ref/fate/filter-trim-time b/tests/ref/fate/filter-trim-time
index 2f86025..ce9fac6 100644
--- a/tests/ref/fate/filter-trim-time
+++ b/tests/ref/fate/filter-trim-time
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x432
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x6e4f89ef
 0,          1,          1,        1,   152064, 0x7f5f6551
diff --git a/tests/ref/fate/filter-unsharp b/tests/ref/fate/filter-unsharp
index 613163b..c128241 100644
--- a/tests/ref/fate/filter-unsharp
+++ b/tests/ref/fate/filter-unsharp
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x58100735
 0,          1,          1,        1,   152064, 0x2967e43d
 0,          2,          2,        1,   152064, 0x6f0c786d
diff --git a/tests/ref/fate/filter-vectorscope_color b/tests/ref/fate/filter-vectorscope_color
index 3d184f6..57875ab 100644
--- a/tests/ref/fate/filter-vectorscope_color
+++ b/tests/ref/fate/filter-vectorscope_color
@@ -1,4 +1,8 @@
 #tb 0: 1/25
-0,          0,          0,        1,   196608, 0x1890aa30
-0,          1,          1,        1,   196608, 0xa490acf9
-0,          2,          2,        1,   196608, 0x404a775d
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 1/1
+0,          0,          0,        1,   196608, 0xf6e3aa30
+0,          1,          1,        1,   196608, 0x5584acf9
+0,          2,          2,        1,   196608, 0xa862775d
diff --git a/tests/ref/fate/filter-vectorscope_color2 b/tests/ref/fate/filter-vectorscope_color2
index be69443..3b2ad90 100644
--- a/tests/ref/fate/filter-vectorscope_color2
+++ b/tests/ref/fate/filter-vectorscope_color2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
-0,          0,          0,        1,   196608, 0x9bfcfae5
-0,          1,          1,        1,   196608, 0x1ac6fcbf
-0,          2,          2,        1,   196608, 0x31cb1088
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 1/1
+0,          0,          0,        1,   196608, 0x5e62fae5
+0,          1,          1,        1,   196608, 0x4c27fcbf
+0,          2,          2,        1,   196608, 0xb7531088
diff --git a/tests/ref/fate/filter-vectorscope_color3 b/tests/ref/fate/filter-vectorscope_color3
index f297efd..4baecca 100644
--- a/tests/ref/fate/filter-vectorscope_color3
+++ b/tests/ref/fate/filter-vectorscope_color3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
-0,          0,          0,        1,   196608, 0x6e698770
-0,          1,          1,        1,   196608, 0x374d74a7
-0,          2,          2,        1,   196608, 0x3d817143
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 1/1
+0,          0,          0,        1,   196608, 0x83df8770
+0,          1,          1,        1,   196608, 0xa6a674a7
+0,          2,          2,        1,   196608, 0x11757143
diff --git a/tests/ref/fate/filter-vectorscope_color4 b/tests/ref/fate/filter-vectorscope_color4
index 5ede41f..21d6762 100644
--- a/tests/ref/fate/filter-vectorscope_color4
+++ b/tests/ref/fate/filter-vectorscope_color4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
-0,          0,          0,        1,   196608, 0x4d2e53c4
-0,          1,          1,        1,   196608, 0x795e1dcc
-0,          2,          2,        1,   196608, 0xe4268800
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 1/1
+0,          0,          0,        1,   196608, 0x326953c4
+0,          1,          1,        1,   196608, 0x870e1dcc
+0,          2,          2,        1,   196608, 0x87cb8800
diff --git a/tests/ref/fate/filter-vectorscope_gray b/tests/ref/fate/filter-vectorscope_gray
index ed41cc0..a81fbf8 100644
--- a/tests/ref/fate/filter-vectorscope_gray
+++ b/tests/ref/fate/filter-vectorscope_gray
@@ -1,4 +1,8 @@
 #tb 0: 1/25
-0,          0,          0,        1,   196608, 0x8e4171e2
-0,          1,          1,        1,   196608, 0xf3d371e2
-0,          2,          2,        1,   196608, 0xb9cb71e2
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 1/1
+0,          0,          0,        1,   196608, 0x79ba71e2
+0,          1,          1,        1,   196608, 0x909271e2
+0,          2,          2,        1,   196608, 0x143971e2
diff --git a/tests/ref/fate/filter-vectorscope_xy b/tests/ref/fate/filter-vectorscope_xy
index 6a4b8f8..83b7194 100644
--- a/tests/ref/fate/filter-vectorscope_xy
+++ b/tests/ref/fate/filter-vectorscope_xy
@@ -1,4 +1,8 @@
 #tb 0: 1/25
-0,          0,          0,        1,   196608, 0xa0939af1
-0,          1,          1,        1,   196608, 0x43699af1
-0,          2,          2,        1,   196608, 0x69a19af1
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 1/1
+0,          0,          0,        1,   196608, 0xa2899af1
+0,          1,          1,        1,   196608, 0x26409af1
+0,          2,          2,        1,   196608, 0xf5209af1
diff --git a/tests/ref/fate/filter-w3fdif-complex b/tests/ref/fate/filter-w3fdif-complex
index 32eadc9..4b334da 100644
--- a/tests/ref/fate/filter-w3fdif-complex
+++ b/tests/ref/fate/filter-w3fdif-complex
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
 0,         18,         18,        1,   622080, 0x21d21485
 0,         19,         19,        1,   622080, 0x600a5468
 0,         20,         20,        1,   622080, 0x9526f7b8
diff --git a/tests/ref/fate/filter-w3fdif-simple b/tests/ref/fate/filter-w3fdif-simple
index 137d989..62efaae 100644
--- a/tests/ref/fate/filter-w3fdif-simple
+++ b/tests/ref/fate/filter-w3fdif-simple
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
 0,         18,         18,        1,   622080, 0xc73774f5
 0,         19,         19,        1,   622080, 0x4ea3a400
 0,         20,         20,        1,   622080, 0x95153cda
diff --git a/tests/ref/fate/filter-waveform_column b/tests/ref/fate/filter-waveform_column
index 0222f33..f35fb24 100644
--- a/tests/ref/fate/filter-waveform_column
+++ b/tests/ref/fate/filter-waveform_column
@@ -1,51 +1,55 @@
 #tb 0: 1/25
-0,          0,          0,        1,   135168, 0xef68cdfa
-0,          1,          1,        1,   135168, 0x3db0cdfa
-0,          2,          2,        1,   135168, 0xd5e6cdfa
-0,          3,          3,        1,   135168, 0x7f71cdfa
-0,          4,          4,        1,   135168, 0x9df7cdfa
-0,          5,          5,        1,   135168, 0xff48cdfa
-0,          6,          6,        1,   135168, 0xb46acdfa
-0,          7,          7,        1,   135168, 0x485acdfa
-0,          8,          8,        1,   135168, 0x8be2cdfa
-0,          9,          9,        1,   135168, 0x86dbcdfa
-0,         10,         10,        1,   135168, 0xdecacdfa
-0,         11,         11,        1,   135168, 0x29a3cdfa
-0,         12,         12,        1,   135168, 0x04c5cdfa
-0,         13,         13,        1,   135168, 0x5f2ccdfa
-0,         14,         14,        1,   135168, 0x9680cdfa
-0,         15,         15,        1,   135168, 0xe397cdfa
-0,         16,         16,        1,   135168, 0xa40ecdfa
-0,         17,         17,        1,   135168, 0x5f35cdfa
-0,         18,         18,        1,   135168, 0x32fbcdfa
-0,         19,         19,        1,   135168, 0x983dcdfa
-0,         20,         20,        1,   135168, 0xb67dcdfa
-0,         21,         21,        1,   135168, 0x5d41cdfa
-0,         22,         22,        1,   135168, 0x35cecdfa
-0,         23,         23,        1,   135168, 0xee17cdfa
-0,         24,         24,        1,   135168, 0x6599cdfa
-0,         25,         25,        1,   135168, 0x918bcdfa
-0,         26,         26,        1,   135168, 0xbd30cdfa
-0,         27,         27,        1,   135168, 0xc2a6cdfa
-0,         28,         28,        1,   135168, 0x688fcdfa
-0,         29,         29,        1,   135168, 0xb11bcdfa
-0,         30,         30,        1,   135168, 0x8316cdfa
-0,         31,         31,        1,   135168, 0x8073cdfa
-0,         32,         32,        1,   135168, 0x3bc1cdfa
-0,         33,         33,        1,   135168, 0xb581cdfa
-0,         34,         34,        1,   135168, 0xdf90cdfa
-0,         35,         35,        1,   135168, 0x6297cdfa
-0,         36,         36,        1,   135168, 0xe8e8cdfa
-0,         37,         37,        1,   135168, 0xa238cdfa
-0,         38,         38,        1,   135168, 0xdc68cdfa
-0,         39,         39,        1,   135168, 0x7545cdfa
-0,         40,         40,        1,   135168, 0xa29dcdfa
-0,         41,         41,        1,   135168, 0x874bcdfa
-0,         42,         42,        1,   135168, 0x7dfacdfa
-0,         43,         43,        1,   135168, 0x7fdfcdfa
-0,         44,         44,        1,   135168, 0xebb4cdfa
-0,         45,         45,        1,   135168, 0x7295cdfa
-0,         46,         46,        1,   135168, 0x54eecdfa
-0,         47,         47,        1,   135168, 0x18c4cdfa
-0,         48,         48,        1,   135168, 0xaa8fcdfa
-0,         49,         49,        1,   135168, 0x99edcdfa
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x256
+#sar 0: 1/1
+0,          0,          0,        1,   270336, 0x3af3cd54
+0,          1,          1,        1,   270336, 0x892ccd54
+0,          2,          2,        1,   270336, 0x2171cd54
+0,          3,          3,        1,   270336, 0xcaedcd54
+0,          4,          4,        1,   270336, 0xe973cd54
+0,          5,          5,        1,   270336, 0x4ad3cd54
+0,          6,          6,        1,   270336, 0xffe6cd54
+0,          7,          7,        1,   270336, 0x93d6cd54
+0,          8,          8,        1,   270336, 0xd75ecd54
+0,          9,          9,        1,   270336, 0xd257cd54
+0,         10,         10,        1,   270336, 0x2a55cd54
+0,         11,         11,        1,   270336, 0x751fcd54
+0,         12,         12,        1,   270336, 0x5041cd54
+0,         13,         13,        1,   270336, 0xaaa8cd54
+0,         14,         14,        1,   270336, 0xe1fccd54
+0,         15,         15,        1,   270336, 0x2f22cd54
+0,         16,         16,        1,   270336, 0xef8acd54
+0,         17,         17,        1,   270336, 0xaab1cd54
+0,         18,         18,        1,   270336, 0x7e77cd54
+0,         19,         19,        1,   270336, 0xe3b9cd54
+0,         20,         20,        1,   270336, 0x0208cd54
+0,         21,         21,        1,   270336, 0xa8bdcd54
+0,         22,         22,        1,   270336, 0x814acd54
+0,         23,         23,        1,   270336, 0x39a2cd54
+0,         24,         24,        1,   270336, 0xb115cd54
+0,         25,         25,        1,   270336, 0xdd07cd54
+0,         26,         26,        1,   270336, 0x08bbcd54
+0,         27,         27,        1,   270336, 0x0e31cd54
+0,         28,         28,        1,   270336, 0xb40bcd54
+0,         29,         29,        1,   270336, 0xfc97cd54
+0,         30,         30,        1,   270336, 0xce92cd54
+0,         31,         31,        1,   270336, 0xcbefcd54
+0,         32,         32,        1,   270336, 0x873dcd54
+0,         33,         33,        1,   270336, 0x010ccd54
+0,         34,         34,        1,   270336, 0x2b1bcd54
+0,         35,         35,        1,   270336, 0xae13cd54
+0,         36,         36,        1,   270336, 0x3473cd54
+0,         37,         37,        1,   270336, 0xedb4cd54
+0,         38,         38,        1,   270336, 0x27f3cd54
+0,         39,         39,        1,   270336, 0xc0c1cd54
+0,         40,         40,        1,   270336, 0xee19cd54
+0,         41,         41,        1,   270336, 0xd2c7cd54
+0,         42,         42,        1,   270336, 0xc976cd54
+0,         43,         43,        1,   270336, 0xcb5bcd54
+0,         44,         44,        1,   270336, 0x373fcd54
+0,         45,         45,        1,   270336, 0xbe11cd54
+0,         46,         46,        1,   270336, 0xa06acd54
+0,         47,         47,        1,   270336, 0x6440cd54
+0,         48,         48,        1,   270336, 0xf60bcd54
+0,         49,         49,        1,   270336, 0xe569cd54
diff --git a/tests/ref/fate/filter-waveform_envelope b/tests/ref/fate/filter-waveform_envelope
index a0d1f30..13130c4 100644
--- a/tests/ref/fate/filter-waveform_envelope
+++ b/tests/ref/fate/filter-waveform_envelope
@@ -1,51 +1,55 @@
 #tb 0: 1/25
-0,          0,          0,        1,   135168, 0x60746d0d
-0,          1,          1,        1,   135168, 0x3a19788d
-0,          2,          2,        1,   135168, 0x18e0d247
-0,          3,          3,        1,   135168, 0x8b4c177f
-0,          4,          4,        1,   135168, 0xc4b34d26
-0,          5,          5,        1,   135168, 0xba364556
-0,          6,          6,        1,   135168, 0xfcab7319
-0,          7,          7,        1,   135168, 0x363d77ce
-0,          8,          8,        1,   135168, 0x04367b07
-0,          9,          9,        1,   135168, 0x6e5b55a0
-0,         10,         10,        1,   135168, 0x33918421
-0,         11,         11,        1,   135168, 0x05ba7ff3
-0,         12,         12,        1,   135168, 0xcae09d62
-0,         13,         13,        1,   135168, 0xca78c5cb
-0,         14,         14,        1,   135168, 0x1542db51
-0,         15,         15,        1,   135168, 0xe013f307
-0,         16,         16,        1,   135168, 0x064008dd
-0,         17,         17,        1,   135168, 0xeb7010d5
-0,         18,         18,        1,   135168, 0x0cd313e1
-0,         19,         19,        1,   135168, 0xaf1b135f
-0,         20,         20,        1,   135168, 0x1b3c02c0
-0,         21,         21,        1,   135168, 0x50940658
-0,         22,         22,        1,   135168, 0x83a2046e
-0,         23,         23,        1,   135168, 0x1edf0a54
-0,         24,         24,        1,   135168, 0x37141206
-0,         25,         25,        1,   135168, 0x7832163e
-0,         26,         26,        1,   135168, 0xd4ba13dc
-0,         27,         27,        1,   135168, 0x9ba710a3
-0,         28,         28,        1,   135168, 0x434a108f
-0,         29,         29,        1,   135168, 0x86b01071
-0,         30,         30,        1,   135168, 0x7bd91c8d
-0,         31,         31,        1,   135168, 0x7a4c179c
-0,         32,         32,        1,   135168, 0x023f15b2
-0,         33,         33,        1,   135168, 0xe8901b20
-0,         34,         34,        1,   135168, 0x49d3157b
-0,         35,         35,        1,   135168, 0xdc990af9
-0,         36,         36,        1,   135168, 0x1ff707a2
-0,         37,         37,        1,   135168, 0xe6610022
-0,         38,         38,        1,   135168, 0x6fc3f168
-0,         39,         39,        1,   135168, 0x719809ff
-0,         40,         40,        1,   135168, 0xd1d9144f
-0,         41,         41,        1,   135168, 0x2f801797
-0,         42,         42,        1,   135168, 0x111c1eae
-0,         43,         43,        1,   135168, 0x23c11c4c
-0,         44,         44,        1,   135168, 0x07351d23
-0,         45,         45,        1,   135168, 0x04f1173d
-0,         46,         46,        1,   135168, 0xb2b71c10
-0,         47,         47,        1,   135168, 0x58c01a53
-0,         48,         48,        1,   135168, 0xadd11b7a
-0,         49,         49,        1,   135168, 0x924123c2
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x256
+#sar 0: 1/1
+0,          0,          0,        1,   270336, 0x24a46c67
+0,          1,          1,        1,   270336, 0x622077e7
+0,          2,          2,        1,   270336, 0xb96dd1a1
+0,          3,          3,        1,   270336, 0x180b16d9
+0,          4,          4,        1,   270336, 0x3db34c80
+0,          5,          5,        1,   270336, 0x417444b0
+0,          6,          6,        1,   270336, 0x3c017273
+0,          7,          7,        1,   270336, 0x572e7728
+0,          8,          8,        1,   270336, 0x18e17a61
+0,          9,          9,        1,   270336, 0x8d9f54fa
+0,         10,         10,        1,   270336, 0x01e5837b
+0,         11,         11,        1,   270336, 0x72ae7f4d
+0,         12,         12,        1,   270336, 0xb6ab9cbc
+0,         13,         13,        1,   270336, 0x28c5c525
+0,         14,         14,        1,   270336, 0x6d89daab
+0,         15,         15,        1,   270336, 0x761ff261
+0,         16,         16,        1,   270336, 0xae200837
+0,         17,         17,        1,   270336, 0x09fe102f
+0,         18,         18,        1,   270336, 0x4999133b
+0,         19,         19,        1,   270336, 0xbc2d12b9
+0,         20,         20,        1,   270336, 0x35f8021a
+0,         21,         21,        1,   270336, 0x5a8605b2
+0,         22,         22,        1,   270336, 0xb25703c8
+0,         23,         23,        1,   270336, 0x641909ae
+0,         24,         24,        1,   270336, 0x8a6e1160
+0,         25,         25,        1,   270336, 0xce181598
+0,         26,         26,        1,   270336, 0xc0ea1336
+0,         27,         27,        1,   270336, 0x941d0ffd
+0,         28,         28,        1,   270336, 0xf94a0fe9
+0,         29,         29,        1,   270336, 0x591d0fcb
+0,         30,         30,        1,   270336, 0x84fb1be7
+0,         31,         31,        1,   270336, 0xda8016f6
+0,         32,         32,        1,   270336, 0x8736150c
+0,         33,         33,        1,   270336, 0xf5931a7a
+0,         34,         34,        1,   270336, 0x582b14d5
+0,         35,         35,        1,   270336, 0x85ce0a53
+0,         36,         36,        1,   270336, 0xf1c106fc
+0,         37,         37,        1,   270336, 0xd023ff6d
+0,         38,         38,        1,   270336, 0xe398f0c2
+0,         39,         39,        1,   270336, 0x5c910959
+0,         40,         40,        1,   270336, 0xfbec13a9
+0,         41,         41,        1,   270336, 0x3f1e16f1
+0,         42,         42,        1,   270336, 0x6c1a1e08
+0,         43,         43,        1,   270336, 0x15091ba6
+0,         44,         44,        1,   270336, 0x82721c7d
+0,         45,         45,        1,   270336, 0x69a91697
+0,         46,         46,        1,   270336, 0xdcbb1b6a
+0,         47,         47,        1,   270336, 0x7cfa19ad
+0,         48,         48,        1,   270336, 0x65ba1ad4
+0,         49,         49,        1,   270336, 0xca65231c
diff --git a/tests/ref/fate/filter-waveform_row b/tests/ref/fate/filter-waveform_row
index 8bc7f36..b436be5 100644
--- a/tests/ref/fate/filter-waveform_row
+++ b/tests/ref/fate/filter-waveform_row
@@ -1,51 +1,55 @@
 #tb 0: 1/25
-0,          0,          0,        1,   110592, 0xa6deed0a
-0,          1,          1,        1,   110592, 0xe659ed0a
-0,          2,          2,        1,   110592, 0x1ca5ed0a
-0,          3,          3,        1,   110592, 0xc2e8ed0a
-0,          4,          4,        1,   110592, 0x78d4ed0a
-0,          5,          5,        1,   110592, 0xbe2eed0a
-0,          6,          6,        1,   110592, 0x482ded0a
-0,          7,          7,        1,   110592, 0x994eed0a
-0,          8,          8,        1,   110592, 0x93aeed0a
-0,          9,          9,        1,   110592, 0xbba8ed0a
-0,         10,         10,        1,   110592, 0xeb2bed0a
-0,         11,         11,        1,   110592, 0xe41ced0a
-0,         12,         12,        1,   110592, 0xb404ed0a
-0,         13,         13,        1,   110592, 0xbad1ed0a
-0,         14,         14,        1,   110592, 0x952aed0a
-0,         15,         15,        1,   110592, 0xbed4ed0a
-0,         16,         16,        1,   110592, 0x5c7ded0a
-0,         17,         17,        1,   110592, 0xbfe8ed0a
-0,         18,         18,        1,   110592, 0xbb6bed0a
-0,         19,         19,        1,   110592, 0x7473ed0a
-0,         20,         20,        1,   110592, 0x7489ed0a
-0,         21,         21,        1,   110592, 0x88a4ed0a
-0,         22,         22,        1,   110592, 0xff0ced0a
-0,         23,         23,        1,   110592, 0x04b8ed0a
-0,         24,         24,        1,   110592, 0xeb8ded0a
-0,         25,         25,        1,   110592, 0xc752ed0a
-0,         26,         26,        1,   110592, 0x5b1bed0a
-0,         27,         27,        1,   110592, 0x1c97ed0a
-0,         28,         28,        1,   110592, 0x0a28ed0a
-0,         29,         29,        1,   110592, 0x302ced0a
-0,         30,         30,        1,   110592, 0x280bed0a
-0,         31,         31,        1,   110592, 0xaa30ed0a
-0,         32,         32,        1,   110592, 0xce59ed0a
-0,         33,         33,        1,   110592, 0xe5f6ed0a
-0,         34,         34,        1,   110592, 0x5b34ed0a
-0,         35,         35,        1,   110592, 0x1b97ed0a
-0,         36,         36,        1,   110592, 0x3283ed0a
-0,         37,         37,        1,   110592, 0xe0d1ed0a
-0,         38,         38,        1,   110592, 0x03f1ed0a
-0,         39,         39,        1,   110592, 0x5744ed0a
-0,         40,         40,        1,   110592, 0x8bbfed0a
-0,         41,         41,        1,   110592, 0xde8fed0a
-0,         42,         42,        1,   110592, 0x9975ed0a
-0,         43,         43,        1,   110592, 0x72eded0a
-0,         44,         44,        1,   110592, 0xe3efed0a
-0,         45,         45,        1,   110592, 0xee7fed0a
-0,         46,         46,        1,   110592, 0x44ffed0a
-0,         47,         47,        1,   110592, 0x91e6ed0a
-0,         48,         48,        1,   110592, 0x0a58ed0a
-0,         49,         49,        1,   110592, 0x68d2ed0a
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x288
+#sar 0: 1/1
+0,          0,          0,        1,   221184, 0x2a1149a3
+0,          1,          1,        1,   221184, 0x698c49a3
+0,          2,          2,        1,   221184, 0x9fc949a3
+0,          3,          3,        1,   221184, 0x461b49a3
+0,          4,          4,        1,   221184, 0xfbf849a3
+0,          5,          5,        1,   221184, 0x416149a3
+0,          6,          6,        1,   221184, 0xcb5149a3
+0,          7,          7,        1,   221184, 0x1c8149a3
+0,          8,          8,        1,   221184, 0x16e149a3
+0,          9,          9,        1,   221184, 0x3edb49a3
+0,         10,         10,        1,   221184, 0x6e5e49a3
+0,         11,         11,        1,   221184, 0x674f49a3
+0,         12,         12,        1,   221184, 0x373749a3
+0,         13,         13,        1,   221184, 0x3e0449a3
+0,         14,         14,        1,   221184, 0x185d49a3
+0,         15,         15,        1,   221184, 0x420749a3
+0,         16,         16,        1,   221184, 0xdfa149a3
+0,         17,         17,        1,   221184, 0x431b49a3
+0,         18,         18,        1,   221184, 0x3e9e49a3
+0,         19,         19,        1,   221184, 0xf79749a3
+0,         20,         20,        1,   221184, 0xf7ad49a3
+0,         21,         21,        1,   221184, 0x0bd749a3
+0,         22,         22,        1,   221184, 0x823f49a3
+0,         23,         23,        1,   221184, 0x87dc49a3
+0,         24,         24,        1,   221184, 0x6ec049a3
+0,         25,         25,        1,   221184, 0x4a8549a3
+0,         26,         26,        1,   221184, 0xde3f49a3
+0,         27,         27,        1,   221184, 0x9fbb49a3
+0,         28,         28,        1,   221184, 0x8d4c49a3
+0,         29,         29,        1,   221184, 0xb35049a3
+0,         30,         30,        1,   221184, 0xab2f49a3
+0,         31,         31,        1,   221184, 0x2d6349a3
+0,         32,         32,        1,   221184, 0x518c49a3
+0,         33,         33,        1,   221184, 0x692949a3
+0,         34,         34,        1,   221184, 0xde5849a3
+0,         35,         35,        1,   221184, 0x9ebb49a3
+0,         36,         36,        1,   221184, 0xb5a749a3
+0,         37,         37,        1,   221184, 0x640449a3
+0,         38,         38,        1,   221184, 0x871549a3
+0,         39,         39,        1,   221184, 0xda6849a3
+0,         40,         40,        1,   221184, 0x0ef249a3
+0,         41,         41,        1,   221184, 0x61c249a3
+0,         42,         42,        1,   221184, 0x1ca849a3
+0,         43,         43,        1,   221184, 0xf61149a3
+0,         44,         44,        1,   221184, 0x672249a3
+0,         45,         45,        1,   221184, 0x71b249a3
+0,         46,         46,        1,   221184, 0xc82349a3
+0,         47,         47,        1,   221184, 0x151949a3
+0,         48,         48,        1,   221184, 0x8d7c49a3
+0,         49,         49,        1,   221184, 0xebf649a3
diff --git a/tests/ref/fate/filter-waveform_uv b/tests/ref/fate/filter-waveform_uv
index 8c3fc70..8cb3bc8 100644
--- a/tests/ref/fate/filter-waveform_uv
+++ b/tests/ref/fate/filter-waveform_uv
@@ -1,51 +1,55 @@
 #tb 0: 1/25
-0,          0,          0,        1,   270336, 0x7be065a8
-0,          1,          1,        1,   270336, 0xa4e56622
-0,          2,          2,        1,   270336, 0xae4a662a
-0,          3,          3,        1,   270336, 0x367e6678
-0,          4,          4,        1,   270336, 0x970f667c
-0,          5,          5,        1,   270336, 0xdf7565f6
-0,          6,          6,        1,   270336, 0xc4a36652
-0,          7,          7,        1,   270336, 0x2f426630
-0,          8,          8,        1,   270336, 0xc095662c
-0,          9,          9,        1,   270336, 0x75fa6626
-0,         10,         10,        1,   270336, 0x95616592
-0,         11,         11,        1,   270336, 0x78916608
-0,         12,         12,        1,   270336, 0x118c65bc
-0,         13,         13,        1,   270336, 0x75446604
-0,         14,         14,        1,   270336, 0xe5fb6612
-0,         15,         15,        1,   270336, 0x3b8f6618
-0,         16,         16,        1,   270336, 0xdeee6646
-0,         17,         17,        1,   270336, 0xede46606
-0,         18,         18,        1,   270336, 0x64336606
-0,         19,         19,        1,   270336, 0xfc50663a
-0,         20,         20,        1,   270336, 0xe5fc660a
-0,         21,         21,        1,   270336, 0x6ecb6612
-0,         22,         22,        1,   270336, 0x06a4662a
-0,         23,         23,        1,   270336, 0xc7b66656
-0,         24,         24,        1,   270336, 0x033e6636
-0,         25,         25,        1,   270336, 0xc14f6650
-0,         26,         26,        1,   270336, 0x7462662c
-0,         27,         27,        1,   270336, 0xf8cb65e4
-0,         28,         28,        1,   270336, 0x6351665e
-0,         29,         29,        1,   270336, 0x44e6666e
-0,         30,         30,        1,   270336, 0x1d5f660e
-0,         31,         31,        1,   270336, 0xc248662e
-0,         32,         32,        1,   270336, 0x36256642
-0,         33,         33,        1,   270336, 0xe4426598
-0,         34,         34,        1,   270336, 0xde81665a
-0,         35,         35,        1,   270336, 0xaeab6622
-0,         36,         36,        1,   270336, 0x134e6668
-0,         37,         37,        1,   270336, 0x6c6e665e
-0,         38,         38,        1,   270336, 0x500b6670
-0,         39,         39,        1,   270336, 0x2c4c6648
-0,         40,         40,        1,   270336, 0xe4ae664c
-0,         41,         41,        1,   270336, 0x9b7e664c
-0,         42,         42,        1,   270336, 0xfefb6570
-0,         43,         43,        1,   270336, 0x04e96600
-0,         44,         44,        1,   270336, 0xcbba6670
-0,         45,         45,        1,   270336, 0x9f9666a6
-0,         46,         46,        1,   270336, 0x85b76642
-0,         47,         47,        1,   270336, 0x1a0e667c
-0,         48,         48,        1,   270336, 0x92c9662a
-0,         49,         49,        1,   270336, 0x9ed76682
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x512
+#sar 0: 1/1
+0,          0,          0,        1,   540672, 0x8a2521d6
+0,          1,          1,        1,   540672, 0xb9a321d6
+0,          2,          2,        1,   540672, 0x325421d6
+0,          3,          3,        1,   540672, 0xafee21d2
+0,          4,          4,        1,   540672, 0x172121d6
+0,          5,          5,        1,   540672, 0x24d121d6
+0,          6,          6,        1,   540672, 0x7fec21d6
+0,          7,          7,        1,   540672, 0xa8a021d6
+0,          8,          8,        1,   540672, 0x29fd21d6
+0,          9,          9,        1,   540672, 0x6dfe21d6
+0,         10,         10,        1,   540672, 0xe39821d6
+0,         11,         11,        1,   540672, 0x83f521d6
+0,         12,         12,        1,   540672, 0x57aa21d6
+0,         13,         13,        1,   540672, 0x67b221d6
+0,         14,         14,        1,   540672, 0x535821d6
+0,         15,         15,        1,   540672, 0xb8ac21d6
+0,         16,         16,        1,   540672, 0x27f621d6
+0,         17,         17,        1,   540672, 0x775221d6
+0,         18,         18,        1,   540672, 0x8e6621d6
+0,         19,         19,        1,   540672, 0x74c921d6
+0,         20,         20,        1,   540672, 0x04cd21d6
+0,         21,         21,        1,   540672, 0xccd421d6
+0,         22,         22,        1,   540672, 0x317221d6
+0,         23,         23,        1,   540672, 0xd79321d6
+0,         24,         24,        1,   540672, 0xa2ac21d6
+0,         25,         25,        1,   540672, 0x7f0a21d6
+0,         26,         26,        1,   540672, 0x483521d6
+0,         27,         27,        1,   540672, 0xb65721d6
+0,         28,         28,        1,   540672, 0xb77021d6
+0,         29,         29,        1,   540672, 0x9fd521d6
+0,         30,         30,        1,   540672, 0xb72121d6
+0,         31,         31,        1,   540672, 0x540221d6
+0,         32,         32,        1,   540672, 0xa34121d6
+0,         33,         33,        1,   540672, 0xe01421d6
+0,         34,         34,        1,   540672, 0x6fc721d6
+0,         35,         35,        1,   540672, 0x7fa621d6
+0,         36,         36,        1,   540672, 0xc48c21d6
+0,         37,         37,        1,   540672, 0x40f021d6
+0,         38,         38,        1,   540672, 0xdf3f21d6
+0,         39,         39,        1,   540672, 0xb04321d6
+0,         40,         40,        1,   540672, 0x222821d6
+0,         41,         41,        1,   540672, 0x2a5521d6
+0,         42,         42,        1,   540672, 0x6a4621be
+0,         43,         43,        1,   540672, 0xed7f21d6
+0,         44,         44,        1,   540672, 0xb16521d6
+0,         45,         45,        1,   540672, 0x9f5621d6
+0,         46,         46,        1,   540672, 0x204321d6
+0,         47,         47,        1,   540672, 0xc26e21d6
+0,         48,         48,        1,   540672, 0x3e8321d6
+0,         49,         49,        1,   540672, 0xaaee21d6
diff --git a/tests/ref/fate/filter-yadif-mode0 b/tests/ref/fate/filter-yadif-mode0
index 4d42890..2c6346b 100644
--- a/tests/ref/fate/filter-yadif-mode0
+++ b/tests/ref/fate/filter-yadif-mode0
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
 0,          9,          9,        1,   622080, 0x6331caee
 0,         10,         10,        1,   622080, 0xa459e690
 0,         11,         11,        1,   622080, 0x6429c648
diff --git a/tests/ref/fate/filter-yadif-mode1 b/tests/ref/fate/filter-yadif-mode1
index 08cd518..e2d14d5 100644
--- a/tests/ref/fate/filter-yadif-mode1
+++ b/tests/ref/fate/filter-yadif-mode1
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
 0,         18,         18,        1,   622080, 0x6331caee
 0,         19,         19,        1,   622080, 0x625da883
 0,         20,         20,        1,   622080, 0xa459e690
diff --git a/tests/ref/fate/filter-yadif10 b/tests/ref/fate/filter-yadif10
index aa27bfc..09ab745 100644
--- a/tests/ref/fate/filter-yadif10
+++ b/tests/ref/fate/filter-yadif10
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
 0,          9,          9,        1,  1244160, 0x5b49e0c0
 0,         10,         10,        1,  1244160, 0x76ba6bab
 0,         11,         11,        1,  1244160, 0x0298cb8d
diff --git a/tests/ref/fate/filter-yadif16 b/tests/ref/fate/filter-yadif16
index 65427a2..3386b02 100644
--- a/tests/ref/fate/filter-yadif16
+++ b/tests/ref/fate/filter-yadif16
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
 0,          9,          9,        1,  1244160, 0xfb65caee
 0,         10,         10,        1,  1244160, 0x6222e690
 0,         11,         11,        1,  1244160, 0x020ac648
diff --git a/tests/ref/fate/flic-af11-palette-change b/tests/ref/fate/flic-af11-palette-change
index cd702b6..acf0004 100644
--- a/tests/ref/fate/flic-af11-palette-change
+++ b/tests/ref/fate/flic-af11-palette-change
@@ -1,4 +1,8 @@
 #tb 0: 1/35
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x508ff8ac
 0,          1,          1,        1,   192000, 0xef0d4274
 0,          2,          2,        1,   192000, 0x0d50e0dd
diff --git a/tests/ref/fate/flic-af12 b/tests/ref/fate/flic-af12
index 227f26a..4683346 100644
--- a/tests/ref/fate/flic-af12
+++ b/tests/ref/fate/flic-af12
@@ -1,4 +1,8 @@
 #tb 0: 9/125
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0x50a87396
 0,          1,          1,        1,   921600, 0xa6e65d9e
 0,          2,          2,        1,   921600, 0x05956f62
diff --git a/tests/ref/fate/flic-magiccarpet b/tests/ref/fate/flic-magiccarpet
index 23a9342..b8d3fc2 100644
--- a/tests/ref/fate/flic-magiccarpet
+++ b/tests/ref/fate/flic-magiccarpet
@@ -1,4 +1,8 @@
 #tb 0: 1/14
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x00000000
 0,          1,          1,        1,   192000, 0x03567eeb
 0,          2,          2,        1,   192000, 0xe73db12c
diff --git a/tests/ref/fate/flv-demux b/tests/ref/fate/flv-demux
new file mode 100644
index 0000000..0a4598c
--- /dev/null
+++ b/tests/ref/fate/flv-demux
@@ -0,0 +1,615 @@
+#extradata 0:       39, 0xf8aa0d44
+#extradata 1:        2, 0x00b600a3
+#tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: h264
+#dimensions 0: 426x240
+#sar 0: 1/1
+#tb 1: 1/1000
+#media_type 1: audio
+#codec_id 1: aac
+#sample_rate 1: 22050
+#channel_layout 1: 3
+0,          0,          0,       33,      135, 0x78b33078, S=1,       39, 0xf8aa0d44
+1,          0,          0,       46,        9, 0x07bc01b8, S=1,        2, 0x00b600a3
+0,         33,         33,       33,       92, 0x0d891dd0, F=0x0
+1,         46,         46,       46,        9, 0x07bc01b8
+0,         67,         67,       33,       14, 0x0f0f0310, F=0x0
+1,         93,         93,       46,        9, 0x08bc01d8
+0,        100,        100,       33,       14, 0x0f460317, F=0x0
+0,        133,        133,       33,      117, 0xb0db33b7, F=0x0
+1,        139,        139,       46,       89, 0x6d552ac1
+0,        167,        167,       33,       14, 0x0eb202ee, F=0x0
+1,        186,        186,       46,      155, 0x1a5a5037
+0,        200,        200,       33,       14, 0x0eea02f6, F=0x0
+1,        232,        232,       46,      281, 0xb40082f9
+0,        234,        234,       33,      117, 0xf3673453, F=0x0
+0,        267,        267,       33,       14, 0x0f790309, F=0x0
+1,        279,        279,       46,      548, 0x9b031e86
+0,        300,        300,       33,       14, 0x0fb10311, F=0x0
+1,        325,        325,       46,      472, 0xee3def63
+0,        334,        334,       33,      117, 0xff73346f, F=0x0
+0,        367,        367,       33,       14, 0x10410325, F=0x0
+1,        372,        372,       46,      489, 0xfa45f463
+0,        400,        400,       33,       14, 0x1079032d, F=0x0
+1,        418,        418,       46,      357, 0x7b01ae7d
+0,        434,        434,       33,      207, 0x19755ca1, F=0x0
+1,        464,        464,       46,      262, 0x19db8399
+0,        467,        467,       33,       14, 0x110a0342, F=0x0
+0,        501,        501,       33,       14, 0x1142034a, F=0x0
+1,        511,        511,       46,      294, 0x047897e0
+0,        534,        534,       33,      179, 0xedd45a40, F=0x0
+1,        557,        557,       46,      204, 0x719961d0
+0,        567,        567,       33,       14, 0x11d1035d, F=0x0
+0,        601,        601,       33,       14, 0x120a0366, F=0x0
+1,        604,        604,       46,      275, 0xca758590
+0,        634,        634,       33,       32, 0xcee90e8b, F=0x0
+1,        650,        650,       46,      309, 0x2e799850
+0,        667,        667,       33,       30, 0xc2d20eeb, F=0x0
+1,        697,        697,       46,      280, 0xdc2b8064
+0,        701,        701,       33,       16, 0x23150504, F=0x0
+0,        734,        734,       33,       33, 0xcccf0d2d, F=0x0
+1,        743,        743,       46,      106, 0xd4cf30df
+0,        767,        767,       33,       16, 0x2385050c, F=0x0
+1,        789,        789,       46,      133, 0xcd964165
+0,        801,        801,       33,       16, 0x23f50518, F=0x0
+0,        834,        834,       33,       22, 0x4ff5086a, F=0x0
+1,        836,        836,       46,      380, 0x4c6bbc27
+0,        868,        868,       33,       14, 0x14aa03c2, F=0x0
+1,        882,        882,       46,      378, 0x2b58b2d6
+0,        901,        901,       33,       14, 0x14e103c9, F=0x0
+1,        929,        929,       46,      108, 0x1998392e
+0,        934,        934,       33,       55, 0xb6ef1b85, F=0x0
+0,        968,        968,       33,       14, 0x153a03da, F=0x0
+1,        975,        975,       46,      279, 0x67a488cb
+0,       1001,       1001,       33,       14, 0x14bd035f, F=0x0
+1,       1022,       1022,       46,      134, 0x228c4193
+0,       1034,       1034,       33,       58, 0xe2911ae2, F=0x0
+0,       1068,       1068,       33,       39, 0x1cff1129, F=0x0
+1,       1068,       1068,       46,      162, 0x67ea49c7
+0,       1101,       1101,       33,       48, 0xaa11138a, F=0x0
+1,       1115,       1115,       46,       46, 0x40f91737
+0,       1134,       1134,       33,      319, 0x7be7a0d8, F=0x0
+1,       1161,       1161,       46,      150, 0x6be143fc
+0,       1168,       1168,       33,      204, 0x23f56562, F=0x0
+0,       1201,       1201,       33,      240, 0xd3d372e2, F=0x0
+1,       1207,       1207,       46,      427, 0xc078d716
+0,       1235,       1235,       33,      305, 0x34199655, F=0x0
+1,       1254,       1254,       46,      616, 0x5f013db0
+0,       1268,       1268,       33,      217, 0x31416760, F=0x0
+1,       1300,       1300,       46,      736, 0x16978a5f
+0,       1301,       1301,       33,      236, 0x150379fd, F=0x0
+0,       1335,       1335,       33,      222, 0xf71472b6, F=0x0
+1,       1347,       1347,       46,      708, 0x0d9f6e16
+0,       1368,       1368,       33,     1295, 0x2c78860b
+1,       1393,       1393,       46,      717, 0xa2737c00
+0,       1401,       1401,       33,      653, 0x9aaf3eeb, F=0x0
+0,       1435,       1435,       33,      335, 0x5c24a7f2, F=0x0
+1,       1440,       1440,       46,      730, 0x0fc07b4f
+0,       1468,       1468,       33,      765, 0xa7ee7d86, F=0x0
+1,       1486,       1486,       46,      756, 0xeb2d987b
+0,       1502,       1502,       33,      213, 0x67c6696e, F=0x0
+1,       1533,       1533,       46,      664, 0x1c684d9f
+0,       1535,       1535,       33,      464, 0x7043ec2c, F=0x0
+0,       1568,       1568,       33,      561, 0x0080105c, F=0x0
+1,       1579,       1579,       46,      751, 0xc1878274
+0,       1602,       1602,       33,      876, 0x14e3b309, F=0x0
+1,       1625,       1625,       46,      780, 0x72de91f8
+0,       1635,       1635,       33,      473, 0x3af6e71a, F=0x0
+0,       1668,       1668,       33,      272, 0x2f577eb7, F=0x0
+1,       1672,       1672,       46,      404, 0x7cadbec3
+0,       1702,       1702,       33,      281, 0xa8988539, F=0x0
+1,       1718,       1718,       46,      326, 0x15afa178
+0,       1735,       1735,       33,      315, 0xa3ed9945, F=0x0
+1,       1765,       1765,       46,       77, 0x3c7021fb
+0,       1768,       1768,       33,      653, 0x143d49a0, F=0x0
+0,       1802,       1802,       33,      228, 0x81036d0c, F=0x0
+1,       1811,       1811,       46,      132, 0xc1094091
+0,       1835,       1835,       33,      265, 0x5c2481af, F=0x0
+1,       1858,       1858,       46,      266, 0x16848764
+0,       1869,       1869,       33,      362, 0xe6a4b15f, F=0x0
+0,       1902,       1902,       33,      362, 0x7e75af89, F=0x0
+1,       1904,       1904,       46,      297, 0x4ab19f82
+0,       1935,       1935,       33,      297, 0xe07e8bd9, F=0x0
+1,       1950,       1950,       46,        9, 0x13c503df
+0,       1969,       1969,       33,      395, 0xa7f8ba2e, F=0x0
+1,       1997,       1997,       46,        9, 0x0abc0218
+0,       2002,       2002,       33,      149, 0xbc114287, F=0x0
+0,       2035,       2035,       33,      141, 0x644342c1, F=0x0
+1,       2043,       2043,       46,        9, 0x07bc01b8
+0,       2069,       2069,       33,      317, 0x59bb9bbb, F=0x0
+1,       2090,       2090,       46,        9, 0x07bc01b8
+0,       2102,       2102,       33,      170, 0x97464bff, F=0x0
+0,       2135,       2135,       33,      443, 0x4ff1e517, F=0x0
+1,       2136,       2136,       46,        9, 0x07bc01b8
+0,       2169,       2169,       33,      224, 0xc64e6a1b, F=0x0
+1,       2183,       2183,       46,        9, 0x07bc01b8
+0,       2202,       2202,       33,      472, 0xadd9e8af, F=0x0
+1,       2229,       2229,       46,        9, 0x07bc01b8
+0,       2236,       2236,       33,      188, 0xac6a570f, F=0x0
+0,       2269,       2269,       33,      302, 0xaff49847, F=0x0
+1,       2276,       2276,       46,        9, 0x07bc01b8
+0,       2302,       2302,       33,      125, 0x01bf3c0c, F=0x0
+1,       2322,       2322,       46,        9, 0x07bc01b8
+0,       2336,       2336,       33,      810, 0x5c048b9a, F=0x0
+1,       2368,       2368,       46,      304, 0x5c7a9945
+0,       2369,       2369,       33,      158, 0x53d450f5, F=0x0
+0,       2402,       2402,       33,      561, 0x65a7233a, F=0x0
+1,       2415,       2415,       46,      683, 0xff1f50c3
+0,       2436,       2436,       33,      383, 0xced8b27f, F=0x0
+1,       2461,       2461,       46,      681, 0xa9d462e5
+0,       2469,       2469,       33,      218, 0x10c86819, F=0x0
+0,       2503,       2503,       33,      270, 0x81a886fb, F=0x0
+1,       2508,       2508,       46,      663, 0xede65a46
+0,       2536,       2536,       33,      182, 0xfa7b5cba, F=0x0
+1,       2554,       2554,       46,      671, 0x7c3859ed
+0,       2569,       2569,       33,     1063, 0x3498fd03
+1,       2601,       2601,       46,      682, 0xdce263f2
+0,       2603,       2603,       33,     3687, 0x7b022d91, F=0x0
+0,       2636,       2636,       33,      280, 0x4de69154, F=0x0
+1,       2647,       2647,       46,      698, 0x78076903
+0,       2669,       2669,       33,      475, 0x426cdeaa, F=0x0
+1,       2694,       2694,       46,      697, 0xfac9612a
+0,       2703,       2703,       33,      488, 0x03dcf37e, F=0x0
+0,       2736,       2736,       33,      532, 0xb2c70c7b, F=0x0
+1,       2740,       2740,       46,      674, 0x3de15e5a
+0,       2769,       2769,       33,      590, 0x674d2283, F=0x0
+1,       2786,       2786,       46,      651, 0xa4c75606
+0,       2803,       2803,       33,      683, 0x38c54334, F=0x0
+1,       2833,       2833,       46,      672, 0xc8c34e54
+0,       2836,       2836,       33,      836, 0xabb49ab2, F=0x0
+0,       2870,       2870,       33,      676, 0x03124fc9, F=0x0
+1,       2879,       2879,       46,      665, 0x928f5897
+0,       2903,       2903,       33,      731, 0x98aa5ca4, F=0x0
+1,       2926,       2926,       46,      734, 0xf0e9626f
+0,       2936,       2936,       33,      839, 0xd4a69b32, F=0x0
+0,       2970,       2970,       33,      787, 0x86867c4f, F=0x0
+1,       2972,       2972,       46,      732, 0x6561709d
+0,       3003,       3003,       33,     1039, 0x071b0fa8, F=0x0
+1,       3019,       3019,       46,      742, 0x700d7d86
+0,       3036,       3036,       33,      851, 0x600fafab, F=0x0
+1,       3065,       3065,       46,      748, 0xfd026ad1
+0,       3070,       3070,       33,      928, 0x8ea9cb74, F=0x0
+0,       3103,       3103,       33,      840, 0x8b41a170, F=0x0
+1,       3111,       3111,       46,      671, 0xbfa75606
+0,       3136,       3136,       33,      889, 0x2dd8ae89, F=0x0
+1,       3158,       3158,       46,      645, 0x2b4c50bd
+0,       3170,       3170,       33,      789, 0x27af87cb, F=0x0
+0,       3203,       3203,       33,     1037, 0x6e71063c, F=0x0
+1,       3204,       3204,       46,      724, 0xaaa77c18
+0,       3237,       3237,       33,     1201, 0xbfbc5455, F=0x0
+1,       3251,       3251,       46,      757, 0xce638153
+0,       3270,       3270,       33,      934, 0x7be8d884, F=0x0
+1,       3297,       3297,       46,      710, 0x427b6cf9
+0,       3303,       3303,       33,     1028, 0xfa9af5d0, F=0x0
+0,       3337,       3337,       33,     1007, 0xb40b0013, F=0x0
+1,       3344,       3344,       46,      705, 0xdb9d5e6b
+0,       3370,       3370,       33,      944, 0xdba1d534, F=0x0
+1,       3390,       3390,       46,      693, 0x84b562bc
+0,       3403,       3403,       33,     1121, 0x18f61f5a, F=0x0
+0,       3437,       3437,       33,     1321, 0x28cb9aa8, F=0x0
+1,       3437,       3437,       46,      683, 0x0ba85781
+0,       3470,       3470,       33,     1229, 0x2d6f62ef, F=0x0
+1,       3483,       3483,       46,      668, 0x96454b35
+0,       3504,       3504,       33,     1166, 0xc3b141b9, F=0x0
+1,       3529,       3529,       46,      624, 0x89672d22
+0,       3537,       3537,       33,     1055, 0xc53e0e48, F=0x0
+0,       3570,       3570,       33,      947, 0x4faecfa6, F=0x0
+1,       3576,       3576,       46,      570, 0xe1da1fc2
+0,       3604,       3604,       33,     1117, 0xb8fa31d9, F=0x0
+1,       3622,       3622,       46,      579, 0xd091239c
+0,       3637,       3637,       33,     1397, 0xb228be1a, F=0x0
+1,       3669,       3669,       46,      558, 0xdb951ae5
+0,       3670,       3670,       33,     1097, 0x955227ea, F=0x0
+0,       3704,       3704,       33,     1207, 0x5ba850c0, F=0x0
+1,       3715,       3715,       46,      510, 0x33d5069a
+0,       3737,       3737,       33,     1109, 0x577d2fcd, F=0x0
+1,       3762,       3762,       46,      518, 0x21e4fc96
+0,       3770,       3770,       33,      994, 0xf3daf299, F=0x0
+0,       3804,       3804,       33,     1144, 0x3d574b78, F=0x0
+1,       3808,       3808,       46,      481, 0x7d7deda0
+0,       3837,       3837,       33,     1409, 0xf148c4bb, F=0x0
+1,       3855,       3855,       46,      443, 0xc9bbe042
+0,       3871,       3871,       33,     1205, 0xaada4f06, F=0x0
+1,       3901,       3901,       46,      413, 0xb428ca8a
+0,       3904,       3904,       33,     1159, 0x3bf83010, F=0x0
+0,       3937,       3937,       33,     1207, 0x2a6457c1, F=0x0
+1,       3947,       3947,       46,      398, 0x7369c402
+0,       3971,       3971,       33,     1084, 0x77271e1d, F=0x0
+1,       3994,       3994,       46,      377, 0x8e1db9a9
+0,       4004,       4004,       33,     1539, 0xb1a9fade, F=0x0
+0,       4037,       4037,       33,     1409, 0xdcf7b97d, F=0x0
+1,       4040,       4040,       46,      364, 0xa399a9c2
+0,       4071,       4071,       33,     1275, 0x993b7ef9, F=0x0
+1,       4087,       4087,       46,      374, 0x8a30ad84
+0,       4104,       4104,       33,     1317, 0xf2f29754, F=0x0
+1,       4133,       4133,       46,      355, 0x7ad6aaa1
+0,       4137,       4137,       33,     1146, 0xae633238, F=0x0
+0,       4171,       4171,       33,     1166, 0x89be313d, F=0x0
+1,       4180,       4180,       46,      341, 0x3e549a7b
+0,       4204,       4204,       33,     1272, 0x75e07674, F=0x0
+1,       4226,       4226,       46,      364, 0xb134a056
+0,       4238,       4238,       33,     1550, 0x6630039d, F=0x0
+0,       4271,       4271,       33,     1353, 0x51f6ad16, F=0x0
+1,       4272,       4272,       46,      350, 0x1f6a9ee2
+0,       4304,       4304,       33,     1251, 0x05046828, F=0x0
+1,       4319,       4319,       46,      356, 0x2aa5ad2c
+0,       4338,       4338,       33,     1339, 0x44e78a57, F=0x0
+1,       4365,       4365,       46,      365, 0x26e7a5eb
+0,       4371,       4371,       33,     1216, 0x2fb55067, F=0x0
+0,       4404,       4404,       33,     1222, 0xd051743c, F=0x0
+1,       4412,       4412,       46,      352, 0x89ffa564
+0,       4438,       4438,       33,     1665, 0x5a6a41dd, F=0x0
+1,       4458,       4458,       46,      374, 0x8333b502
+0,       4471,       4471,       33,     1372, 0x3abca4f1, F=0x0
+0,       4505,       4505,       33,     1611, 0x99ad11fe, F=0x0
+1,       4505,       4505,       46,      375, 0x22e4b95a
+0,       4538,       4538,       33,     7010, 0x7a699d02
+1,       4551,       4551,       46,      375, 0xfb95adce
+0,       4571,       4571,       33,      549, 0x0ae5102e, F=0x0
+1,       4598,       4598,       46,      376, 0xa910b02a
+0,       4605,       4605,       33,     1021, 0xe53aea67, F=0x0
+0,       4638,       4638,       33,     1281, 0x53808ad5, F=0x0
+1,       4644,       4644,       46,      372, 0x5d84a2e6
+0,       4671,       4671,       33,     1267, 0x2a3c6a6d, F=0x0
+1,       4690,       4690,       46,      371, 0x6849a7b1
+0,       4705,       4705,       33,     1140, 0xe2a436ad, F=0x0
+1,       4737,       4737,       46,      365, 0xb0eaa876
+0,       4738,       4738,       33,     1289, 0xa1227538, F=0x0
+0,       4771,       4771,       33,     1127, 0xe2ad2de9, F=0x0
+1,       4783,       4783,       46,      385, 0xbea3ba29
+0,       4805,       4805,       33,     1196, 0xa16f445e, F=0x0
+1,       4830,       4830,       46,      362, 0xd20da339
+0,       4838,       4838,       33,     1520, 0x4a72f136, F=0x0
+0,       4872,       4872,       33,     1370, 0xdd6e9bda, F=0x0
+1,       4876,       4876,       46,      370, 0xf774b39b
+0,       4905,       4905,       33,     1232, 0x928f6640, F=0x0
+1,       4923,       4923,       46,      369, 0x7381aca3
+0,       4938,       4938,       33,     1159, 0x9de43e90, F=0x0
+1,       4969,       4969,       46,      341, 0xbfd5ac4c
+0,       4972,       4972,       33,     1183, 0xc36251d9, F=0x0
+0,       5005,       5005,       33,     1469, 0xb2b1f147, F=0x0
+1,       5016,       5016,       46,      351, 0xd044a810
+0,       5038,       5038,       33,     1468, 0xb985dd18, F=0x0
+1,       5062,       5062,       46,      365, 0xdc80af91
+0,       5072,       5072,       33,     1355, 0xf58c9413, F=0x0
+0,       5105,       5105,       33,     1303, 0x14157d32, F=0x0
+1,       5108,       5108,       46,      358, 0xd6c8b0b0
+0,       5138,       5138,       33,     1316, 0x3fc89532, F=0x0
+1,       5155,       5155,       46,      373, 0xafa1ad7e
+0,       5172,       5172,       33,     1196, 0x869a529d, F=0x0
+1,       5201,       5201,       46,      367, 0x7361ad07
+0,       5205,       5205,       33,     1283, 0xd7717841, F=0x0
+0,       5239,       5239,       33,     1489, 0x13abed4a, F=0x0
+1,       5248,       5248,       46,      364, 0x2103ac58
+0,       5272,       5272,       33,     1507, 0xdbaee51a, F=0x0
+1,       5294,       5294,       46,      346, 0x01d59dbe
+0,       5305,       5305,       33,     1237, 0x81b8669f, F=0x0
+0,       5339,       5339,       33,     1217, 0x3f3f6661, F=0x0
+1,       5341,       5341,       46,      362, 0xe11fad7f
+0,       5372,       5372,       33,     1224, 0xe0e8653c, F=0x0
+1,       5387,       5387,       46,      360, 0x63b5a7a5
+0,       5405,       5405,       33,     1554, 0x88bf1cbc, F=0x0
+1,       5433,       5433,       46,      356, 0xce49acce
+0,       5439,       5439,       33,     1465, 0xf42ddd75, F=0x0
+0,       5472,       5472,       33,     1862, 0x423c930e, F=0x0
+1,       5480,       5480,       46,      364, 0x5e1eaebb
+0,       5506,       5506,       33,     1604, 0xb4e22b5d, F=0x0
+1,       5526,       5526,       46,      365, 0x3f92aad4
+0,       5539,       5539,       33,     1541, 0x1e52dd7b, F=0x0
+0,       5572,       5572,       33,     1534, 0x96adf8bb, F=0x0
+1,       5573,       5573,       46,      357, 0x8492abda
+0,       5606,       5606,       33,     1336, 0x0aaa91dd, F=0x0
+1,       5619,       5619,       46,      367, 0x5524aafb
+0,       5639,       5639,       33,     1761, 0xde4b6b31, F=0x0
+1,       5666,       5666,       46,      361, 0xfcc4b013
+0,       5672,       5672,       33,     1722, 0xa29a5aaf, F=0x0
+0,       5706,       5706,       33,     1442, 0xea0ce0a5, F=0x0
+1,       5712,       5712,       46,      367, 0x07d7a469
+0,       5739,       5739,       33,     1313, 0x28f889e1, F=0x0
+1,       5759,       5759,       46,      375, 0xd7d1b2cc
+0,       5772,       5772,       33,     1436, 0x5464d32b, F=0x0
+1,       5805,       5805,       46,      357, 0x3e05a67b
+0,       5806,       5806,       33,     1689, 0x812d4d33, F=0x0
+0,       5839,       5839,       33,     1472, 0x63f8cee6, F=0x0
+1,       5851,       5851,       46,      379, 0x968bad9d
+0,       5873,       5873,       33,     1730, 0xae13704c, F=0x0
+1,       5898,       5898,       46,      361, 0xa40aac26
+0,       5906,       5906,       33,     1555, 0xfe7011be, F=0x0
+0,       5939,       5939,       33,     1486, 0x6dccd60b, F=0x0
+1,       5944,       5944,       46,      350, 0x4261a2a7
+0,       5973,       5973,       33,     1311, 0x4a64822b, F=0x0
+1,       5991,       5991,       46,      339, 0x030da15f
+0,       6006,       6006,       33,     1700, 0x42583def, F=0x0
+1,       6037,       6037,       46,      336, 0x2bb699db
+0,       6039,       6039,       33,     1647, 0x97a53e7d, F=0x0
+0,       6073,       6073,       33,     1663, 0x72363852, F=0x0
+1,       6084,       6084,       46,      331, 0xc3b19edc
+0,       6106,       6106,       33,     1512, 0xda11e80a, F=0x0
+1,       6130,       6130,       46,      335, 0xda6e9891
+0,       6139,       6139,       33,     1370, 0x2618a927, F=0x0
+0,       6173,       6173,       33,     1440, 0xadd7baf0, F=0x0
+1,       6177,       6177,       46,      323, 0xdcd9943f
+0,       6206,       6206,       33,     1574, 0xa2e305e8, F=0x0
+1,       6223,       6223,       46,      333, 0x34f69630
+0,       6240,       6240,       33,     1328, 0x53baa035, F=0x0
+1,       6269,       6269,       46,      335, 0x2ed79dab
+0,       6273,       6273,       33,     1802, 0xc91782aa, F=0x0
+0,       6306,       6306,       33,     1619, 0x443c3ae6, F=0x0
+1,       6316,       6316,       46,      334, 0x2b0e9704
+0,       6340,       6340,       33,     1471, 0xe3a8defc, F=0x0
+1,       6362,       6362,       46,      342, 0xf47f9c97
+0,       6373,       6373,       33,     1226, 0xfd2f5b3b, F=0x0
+0,       6406,       6406,       33,     1485, 0xed8be011, F=0x0
+1,       6409,       6409,       46,      358, 0xd6a6aad9
+0,       6440,       6440,       33,     1786, 0xf98572ee, F=0x0
+1,       6455,       6455,       46,      360, 0xbf5ea460
+0,       6473,       6473,       33,     1345, 0xc7d39a6a, F=0x0
+1,       6502,       6502,       46,      357, 0xe5bba75c
+0,       6507,       6507,       33,     8275, 0x7a7115f7
+0,       6540,       6540,       33,      698, 0x45955de0, F=0x0
+1,       6548,       6548,       46,      336, 0x9da89baf
+0,       6573,       6573,       33,     1298, 0x382a8e39, F=0x0
+1,       6594,       6594,       46,      343, 0x0f749ed3
+0,       6607,       6607,       33,     1454, 0xb6e4c8c1, F=0x0
+0,       6640,       6640,       33,     1352, 0x39738c55, F=0x0
+1,       6641,       6641,       46,      324, 0x63989376
+0,       6673,       6673,       33,     1609, 0xaf601cb7, F=0x0
+1,       6687,       6687,       46,      322, 0x5c429514
+0,       6707,       6707,       33,     1476, 0xc020de0c, F=0x0
+1,       6734,       6734,       46,      328, 0xad669039
+0,       6740,       6740,       33,     1391, 0xd45baf0c, F=0x0
+0,       6773,       6773,       33,     1203, 0x22855ed0, F=0x0
+1,       6780,       6780,       46,      332, 0x21fb9787
+0,       6807,       6807,       33,     1489, 0x1ce4e3d6, F=0x0
+1,       6827,       6827,       46,      343, 0x663c9d7a
+0,       6840,       6840,       33,     1655, 0x0f5c30f1, F=0x0
+1,       6873,       6873,       46,      343, 0xea86a902
+0,       6874,       6874,       33,     1363, 0x97b7ad8e, F=0x0
+0,       6907,       6907,       33,     1492, 0x177eed5d, F=0x0
+1,       6920,       6920,       46,      327, 0xc3659486
+0,       6940,       6940,       33,     1397, 0xff57bf4b, F=0x0
+1,       6966,       6966,       46,      326, 0x3245a088
+0,       6974,       6974,       33,     1251, 0x1bcd7221, F=0x0
+0,       7007,       7007,       33,     1586, 0xe8d102ac, F=0x0
+1,       7012,       7012,       46,      324, 0x3f9a8f1d
+0,       7040,       7040,       33,     1333, 0x2bf0a1da, F=0x0
+1,       7059,       7059,       46,      312, 0xbc969286
+0,       7074,       7074,       33,     2723, 0x576f3ace, F=0x0
+1,       7105,       7105,       46,      308, 0xbc0a8c96
+0,       7107,       7107,       33,      632, 0xe9253efd, F=0x0
+0,       7140,       7140,       33,      444, 0x701ed924, F=0x0
+1,       7152,       7152,       46,      308, 0xfda38345
+0,       7174,       7174,       33,     1013, 0xd27f0123, F=0x0
+1,       7198,       7198,       46,      318, 0x469893ad
+0,       7207,       7207,       33,     1357, 0x46979205, F=0x0
+0,       7241,       7241,       33,     1586, 0x3e9824f8, F=0x0
+1,       7245,       7245,       46,      331, 0x2d629ee2
+0,       7274,       7274,       33,     2514, 0x4329eb3d, F=0x0
+1,       7291,       7291,       46,      329, 0x6361948e
+0,       7307,       7307,       33,      450, 0xa710e3d3, F=0x0
+1,       7338,       7338,       46,      333, 0x6e169a21
+0,       7341,       7341,       33,      423, 0xb239c6cf, F=0x0
+0,       7374,       7374,       33,     1161, 0x2e813244, F=0x0
+1,       7384,       7384,       46,      314, 0x37e78615
+0,       7407,       7407,       33,     1366, 0xc85eab74, F=0x0
+1,       7430,       7430,       46,      304, 0x580d9236
+0,       7441,       7441,       33,     1325, 0x53938a95, F=0x0
+0,       7474,       7474,       33,     2687, 0x40383547, F=0x0
+1,       7477,       7477,       46,      299, 0x3e41899a
+0,       7508,       7508,       33,      678, 0x0c56575d, F=0x0
+1,       7523,       7523,       46,      311, 0xf62f881b
+0,       7541,       7541,       33,      491, 0xdafef05e, F=0x0
+1,       7570,       7570,       46,      323, 0x68a09353
+0,       7574,       7574,       33,     1056, 0x3e5616fc, F=0x0
+0,       7608,       7608,       33,     1549, 0x5dcb04c7, F=0x0
+1,       7616,       7616,       46,      317, 0xf9f88de8
+0,       7641,       7641,       33,     2502, 0x1c21dd6b, F=0x0
+1,       7663,       7663,       46,      322, 0x204a970f
+0,       7674,       7674,       33,      539, 0xef1d0e8d, F=0x0
+0,       7708,       7708,       33,      594, 0x15f324d6, F=0x0
+1,       7709,       7709,       46,      329, 0x1c4c9ee8
+0,       7741,       7741,       33,     1254, 0xe49078cb, F=0x0
+1,       7755,       7755,       46,      342, 0xc825aa35
+0,       7774,       7774,       33,     1341, 0xfb789386, F=0x0
+1,       7802,       7802,       46,      331, 0x6d1c9c33
+0,       7808,       7808,       33,     1358, 0x5a7194ad, F=0x0
+0,       7841,       7841,       33,     2336, 0x538f8a16, F=0x0
+1,       7848,       7848,       46,      343, 0x577ca504
+0,       7875,       7875,       33,      339, 0x9935a5f9, F=0x0
+1,       7895,       7895,       46,      327, 0xafb79bfe
+0,       7908,       7908,       33,     2159, 0x20654dbc, F=0x0
+0,       7941,       7941,       33,      390, 0xe6c8bd90, F=0x0
+1,       7941,       7941,       46,      317, 0x773e8778
+0,       7975,       7975,       33,      479, 0xefbaf020, F=0x0
+1,       7988,       7988,       46,      313, 0x357d93ad
+0,       8008,       8008,       33,     2157, 0x5cc5398b, F=0x0
+1,       8034,       8034,       46,      312, 0xaa978945
+0,       8041,       8041,       33,      429, 0x5dbecb52, F=0x0
+0,       8075,       8075,       33,     1953, 0xdb55d429, F=0x0
+1,       8081,       8081,       46,      318, 0x7a0d8c19
+0,       8108,       8108,       33,      379, 0x1d62ba4e, F=0x0
+1,       8127,       8127,       46,      325, 0x577a9868
+0,       8141,       8141,       33,     1817, 0x44fa8996, F=0x0
+1,       8173,       8173,       46,      317, 0x8ef994a7
+0,       8175,       8175,       33,      372, 0x023db80e, F=0x0
+0,       8208,       8208,       33,     1664, 0xd2d14b3f, F=0x0
+1,       8220,       8220,       46,      308, 0x0fbd8e91
+0,       8242,       8242,       33,      340, 0xc537aa42, F=0x0
+1,       8266,       8266,       46,      309, 0x31c28f1d
+0,       8275,       8275,       33,     1955, 0x76f8cdb3, F=0x0
+0,       8308,       8308,       33,      485, 0x5b05f1d6, F=0x0
+1,       8313,       8313,       46,      315, 0xc27f8cbb
+0,       8342,       8342,       33,     1705, 0x18385a59, F=0x0
+1,       8359,       8359,       46,      340, 0x21b3a33f
+0,       8375,       8375,       33,      411, 0x70d7cae5, F=0x0
+1,       8406,       8406,       46,      326, 0xc4fd90f3
+0,       8408,       8408,       33,     1818, 0x9d6381eb, F=0x0
+0,       8442,       8442,       33,      304, 0x7825921f, F=0x0
+1,       8452,       8452,       46,      333, 0xe874961c
+0,       8475,       8475,       33,     6302, 0x016c66ef
+1,       8499,       8499,       46,      340, 0x342c9ce8
+0,       8509,       8509,       33,     1498, 0x42b4ef91, F=0x0
+0,       8542,       8542,       33,      434, 0xa285db46, F=0x0
+1,       8545,       8545,       46,      338, 0x204b9c1d
+0,       8575,       8575,       33,     1643, 0xe0d322b1, F=0x0
+1,       8591,       8591,       46,      357, 0xa4b09fab
+0,       8609,       8609,       33,      213, 0xfc1b64b4, F=0x0
+1,       8638,       8638,       46,      340, 0x7bfa9f7d
+0,       8642,       8642,       33,     1820, 0x612577a5, F=0x0
+0,       8675,       8675,       33,      264, 0x1b3b7d63, F=0x0
+1,       8684,       8684,       46,      335, 0x965e9ca0
+0,       8709,       8709,       33,     1461, 0x6392d1d0, F=0x0
+1,       8731,       8731,       46,      322, 0x278791b7
+0,       8742,       8742,       33,      239, 0x34206e81, F=0x0
+0,       8775,       8775,       33,     1581, 0xa53714ca, F=0x0
+1,       8777,       8777,       46,      318, 0xac96910c
+0,       8809,       8809,       33,      212, 0x356e6502, F=0x0
+1,       8824,       8824,       46,      326, 0xdb2897c6
+0,       8842,       8842,       33,     1351, 0x42f5bb96, F=0x0
+1,       8870,       8870,       46,      341, 0x6e00a7ba
+0,       8876,       8876,       33,      448, 0x82afd887, F=0x0
+0,       8909,       8909,       33,     1403, 0x461cc0fa, F=0x0
+1,       8916,       8916,       46,      319, 0xfe8d8f11
+0,       8942,       8942,       33,      491, 0xcc36f0ac, F=0x0
+1,       8963,       8963,       46,      303, 0xa81c8418
+0,       8976,       8976,       33,     1606, 0xe6572381, F=0x0
+0,       9009,       9009,       33,      304, 0x17d49e7b, F=0x0
+1,       9009,       9009,       46,      291, 0x931a88a8
+0,       9042,       9042,       33,     1537, 0x2506027c, F=0x0
+1,       9056,       9056,       46,      307, 0xd06c8de9
+0,       9076,       9076,       33,      342, 0x27c1a7d7, F=0x0
+1,       9102,       9102,       46,      335, 0xc4449e94
+0,       9109,       9109,       33,     1405, 0x2fbbcb89, F=0x0
+0,       9142,       9142,       33,      351, 0x5529b047, F=0x0
+1,       9149,       9149,       46,      348, 0xb347a000
+0,       9176,       9176,       33,     1451, 0x9455d96b, F=0x0
+1,       9195,       9195,       46,      346, 0xb36ea5a2
+0,       9209,       9209,       33,      490, 0xda00f1ab, F=0x0
+1,       9242,       9242,       46,      333, 0xfec69e56
+0,       9243,       9243,       33,     1524, 0x7752edff, F=0x0
+0,       9276,       9276,       33,      556, 0xea4f0e24, F=0x0
+1,       9288,       9288,       46,      338, 0x24a694c0
+0,       9309,       9309,       33,     1414, 0x780ecb26, F=0x0
+1,       9334,       9334,       46,      328, 0xbf0498ea
+0,       9343,       9343,       33,      808, 0xe60b85d4, F=0x0
+0,       9376,       9376,       33,      871, 0xc49ab01a, F=0x0
+1,       9381,       9381,       46,      334, 0x725b97da
+0,       9409,       9409,       33,      562, 0x5bf11537, F=0x0
+1,       9427,       9427,       46,      364, 0x44089f50
+0,       9443,       9443,       33,      711, 0x41db5a9a, F=0x0
+1,       9474,       9474,       46,      350, 0xedeb9e1d
+0,       9476,       9476,       33,     1209, 0x977c4e31, F=0x0
+0,       9510,       9510,       33,      483, 0xd883e689, F=0x0
+1,       9520,       9520,       46,      348, 0x5dd39c4a
+0,       9543,       9543,       33,      422, 0xf7e3d366, F=0x0
+1,       9567,       9567,       46,      354, 0x202d9eff
+0,       9576,       9576,       33,      533, 0x7da70555, F=0x0
+0,       9610,       9610,       33,      490, 0xb209e261, F=0x0
+1,       9613,       9613,       46,      358, 0xdd3ea998
+0,       9643,       9643,       33,      972, 0x0cf2e4b0, F=0x0
+1,       9660,       9660,       46,      361, 0xa7b6a4c6
+0,       9676,       9676,       33,      370, 0x75bfafd5, F=0x0
+1,       9706,       9706,       46,      354, 0xa20aa059
+0,       9710,       9710,       33,      348, 0xf094a48a, F=0x0
+0,       9743,       9743,       33,      449, 0xa08de29e, F=0x0
+1,       9752,       9752,       46,      369, 0x81c9af74
+0,       9776,       9776,       33,      447, 0x9392d7bf, F=0x0
+1,       9799,       9799,       46,      359, 0xbbd4b06e
+0,       9810,       9810,       33,      414, 0xcc62c97e, F=0x0
+0,       9843,       9843,       33,      467, 0x37a5e9e0, F=0x0
+1,       9845,       9845,       46,      348, 0x1f2ba0bb
+0,       9877,       9877,       33,      890, 0x107fb1a3, F=0x0
+1,       9892,       9892,       46,      346, 0x0ad5a08c
+0,       9910,       9910,       33,      387, 0x876ec0ab, F=0x0
+1,       9938,       9938,       46,      350, 0x9802a830
+0,       9943,       9943,       33,      351, 0x2ed7a355, F=0x0
+0,       9977,       9977,       33,      720, 0x153d6916, F=0x0
+1,       9985,       9985,       46,      359, 0xce55a942
+0,      10010,      10010,       33,      855, 0xc2f4a51e, F=0x0
+1,      10031,      10031,       46,      355, 0xa31ca014
+0,      10043,      10043,       33,      742, 0xc13b6868, F=0x0
+0,      10077,      10077,       33,      835, 0x5c80a1fd, F=0x0
+1,      10077,      10077,       46,      320, 0xb71b8f6a
+0,      10110,      10110,       33,     1610, 0xba612dab, F=0x0
+1,      10124,      10124,       46,      348, 0x221b9e6d
+0,      10143,      10143,       33,      637, 0xc25a3725, F=0x0
+1,      10170,      10170,       46,      370, 0xe989a4ed
+0,      10177,      10177,       33,      614, 0xb7922aa2, F=0x0
+0,      10210,      10210,       33,     1143, 0x576a3cac, F=0x0
+1,      10217,      10217,       46,      353, 0x3e11a44b
+0,      10244,      10244,       33,     1262, 0xa7f475fb, F=0x0
+1,      10263,      10263,       46,      367, 0x9644abd4
+0,      10277,      10277,       33,     1618, 0x36443ddd, F=0x0
+0,      10310,      10310,       33,     2345, 0x25ad71dc, F=0x0
+1,      10310,      10310,       46,      350, 0xa088a836
+0,      10344,      10344,       33,     1029, 0x597303d7, F=0x0
+1,      10356,      10356,       46,      353, 0x7d9fa7d0
+0,      10377,      10377,       33,      932, 0x064bcca7, F=0x0
+1,      10403,      10403,       46,      336, 0x397398a2
+0,      10410,      10410,       33,     1688, 0x5ed257c1, F=0x0
+0,      10444,      10444,       33,     4159, 0x897c3370
+1,      10449,      10449,       46,      334, 0xa321a038
+0,      10477,      10477,       33,     2039, 0x930cfb12, F=0x0
+1,      10495,      10495,       46,      358, 0x61e2a2c5
+0,      10511,      10511,       33,      614, 0x1edc250b, F=0x0
+1,      10542,      10542,       46,      344, 0xa7189dd0
+0,      10544,      10544,       33,     1749, 0x79655b63, F=0x0
+0,      10577,      10577,       33,     2609, 0x834f110a, F=0x0
+1,      10588,      10588,       46,      344, 0x85739a8f
+0,      10611,      10611,       33,      689, 0x47c85a40, F=0x0
+1,      10635,      10635,       46,      356, 0x54b4a63b
+0,      10644,      10644,       33,     2259, 0xfbef6b65, F=0x0
+0,      10677,      10677,       33,     2494, 0x3f5fc8d0, F=0x0
+1,      10681,      10681,       46,      354, 0x1528aa5c
+0,      10711,      10711,       33,     2457, 0xc427c17e, F=0x0
+1,      10728,      10728,       46,      330, 0xe44f959b
+0,      10744,      10744,       33,     2476, 0x8bbbd064, F=0x0
+1,      10774,      10774,       46,      328, 0x0b70968c
+0,      10777,      10777,       33,     2560, 0x0b04f7d7, F=0x0
+0,      10811,      10811,       33,     2679, 0x02d74002, F=0x0
+1,      10820,      10820,       46,      351, 0xcef29fe7
+0,      10844,      10844,       33,     2795, 0x6a166090, F=0x0
+1,      10867,      10867,       46,      364, 0xe542aed9
+0,      10878,      10878,       33,     2927, 0xfdb899de, F=0x0
+0,      10911,      10911,       33,     2437, 0x5ac9ba9b, F=0x0
+1,      10913,      10913,       46,      365, 0x3697a967
+0,      10944,      10944,       33,     2663, 0xa4412f2e, F=0x0
+1,      10960,      10960,       46,      341, 0xe1a59f5c
+0,      10978,      10978,       33,     2688, 0x48db425f, F=0x0
+1,      11006,      11006,       46,      330, 0x96fb8da1
+0,      11011,      11011,       33,     2727, 0x12db4729, F=0x0
+0,      11044,      11044,       33,     2747, 0xc3945324, F=0x0
+1,      11053,      11053,       46,      358, 0x89eca01e
+0,      11078,      11078,       33,     3602, 0x32bd0c05, F=0x0
+1,      11099,      11099,       46,      367, 0x77f2b3d3
+0,      11111,      11111,       33,     1334, 0x1cdfa159, F=0x0
+0,      11144,      11144,       33,     2562, 0x4985e43f, F=0x0
+1,      11146,      11146,       46,      353, 0x73499f01
+0,      11178,      11178,       33,     2917, 0x7b999fc2, F=0x0
+1,      11192,      11192,       46,      336, 0xb8b9a2a0
+0,      11211,      11211,       33,     2788, 0x94a75a97, F=0x0
+1,      11238,      11238,       46,      329, 0xb80a8e3f
+0,      11245,      11245,       33,     2876, 0x4da3a1e2, F=0x0
+0,      11278,      11278,       33,     2782, 0x0018739c, F=0x0
+1,      11285,      11285,       46,      323, 0x36929c3b
+0,      11311,      11311,       33,     2393, 0xd5d6b66d, F=0x0
+1,      11331,      11331,       46,      328, 0xc22b9604
+0,      11345,      11345,       33,     2773, 0x969452e3, F=0x0
+0,      11378,      11378,       33,     2972, 0xcf93d2ca, F=0x0
+1,      11378,      11378,       46,      345, 0x76eda9c7
+0,      11411,      11411,       33,     3480, 0x7000d659, F=0x0
+1,      11424,      11424,       46,      345, 0xd34da6bb
+0,      11445,      11445,       33,     1078, 0xd89b1b88, F=0x0
+1,      11471,      11471,       46,      349, 0xa7a1a1a9
+0,      11478,      11478,       33,     3385, 0xb57695e3, F=0x0
+0,      11512,      11512,       33,     1408, 0xe155b5f3, F=0x0
+1,      11517,      11517,       46,      340, 0x5ae5942f
+0,      11545,      11545,       33,     2543, 0x77d5eee5, F=0x0
+1,      11564,      11564,       46,      352, 0xf105a26a
+0,      11578,      11578,       33,     3609, 0x3a02f82d, F=0x0
+1,      11610,      11610,       46,      345, 0xf6a29dda
+0,      11612,      11612,       33,     1078, 0x501d1c72, F=0x0
+0,      11645,      11645,       33,     2600, 0xdf370d24, F=0x0
+1,      11656,      11656,       46,      346, 0x8899a188
+0,      11678,      11678,       33,     1190, 0xdc1e4c99, F=0x0
diff --git a/tests/ref/fate/force_key_frames b/tests/ref/fate/force_key_frames
index 0a41378..26de090 100644
--- a/tests/ref/fate/force_key_frames
+++ b/tests/ref/fate/force_key_frames
@@ -1,4 +1,4 @@
 07567b9528b8de523faaf49e4e1e0fc6 *tests/data/fate/force_key_frames.avi
 113312 tests/data/fate/force_key_frames.avi
-8f68ad2e602ecd87a3e0c097ba99d773 *tests/data/fate/force_key_frames.out.framecrc
-stddev:34363.01 PSNR:  5.61 MAXDIFF:56305 bytes:  7603200/      186
+b2e92b97bac0243242281d71108ffdbd *tests/data/fate/force_key_frames.out.framecrc
+stddev:34612.83 PSNR:  5.54 MAXDIFF:61408 bytes:  7603200/      264
diff --git a/tests/ref/fate/fraps-v0 b/tests/ref/fate/fraps-v0
index 3cba831..97ada13 100644
--- a/tests/ref/fate/fraps-v0
+++ b/tests/ref/fate/fraps-v0
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 312x216
+#sar 0: 0/1
 0,          0,          0,        1,   101088, 0x7bf448f8
 0,          1,          1,        1,   101088, 0x1ba749ec
 0,          2,          2,        1,   101088, 0x94eb4dc4
diff --git a/tests/ref/fate/fraps-v1 b/tests/ref/fate/fraps-v1
index 29c7e37..36fb7d8 100644
--- a/tests/ref/fate/fraps-v1
+++ b/tests/ref/fate/fraps-v1
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0x23c29d17
diff --git a/tests/ref/fate/fraps-v2 b/tests/ref/fate/fraps-v2
index 06e0024..3d85333 100644
--- a/tests/ref/fate/fraps-v2
+++ b/tests/ref/fate/fraps-v2
@@ -1,3 +1,7 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x768
+#sar 0: 0/1
 0,          0,          0,        1,  1179648, 0x99f80436
 0,          5,          5,        1,  1179648, 0xe8ae7a30
diff --git a/tests/ref/fate/fraps-v3 b/tests/ref/fate/fraps-v3
index 139ee7e..93286d1 100644
--- a/tests/ref/fate/fraps-v3
+++ b/tests/ref/fate/fraps-v3
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x384
+#sar 0: 0/1
 0,          0,          0,        1,   589824, 0x0b181bbf
 0,          1,          1,        1,   589824, 0xcd740f79
 0,          2,          2,        1,   589824, 0x16f8f90e
diff --git a/tests/ref/fate/fraps-v4 b/tests/ref/fate/fraps-v4
index 007916d..c97f29b 100644
--- a/tests/ref/fate/fraps-v4
+++ b/tests/ref/fate/fraps-v4
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x512
+#sar 0: 0/1
 0,          0,          0,        1,   491520, 0x68ff12c0
 0,          1,          1,        1,   491520, 0x22d36f0d
 0,          2,          2,        1,   491520, 0xce6f877d
diff --git a/tests/ref/fate/fraps-v5 b/tests/ref/fate/fraps-v5
index 599683a..c0628e9 100644
--- a/tests/ref/fate/fraps-v5
+++ b/tests/ref/fate/fraps-v5
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 288x168
+#sar 0: 0/1
 0,          0,          0,        1,   145152, 0x8458d4cb
 0,          1,          1,        1,   145152, 0xa694d7c7
 0,          2,          2,        1,   145152, 0x2bd4bfc9
diff --git a/tests/ref/fate/frwu b/tests/ref/fate/frwu
index 32eaa6f..918ef6c 100644
--- a/tests/ref/fate/frwu
+++ b/tests/ref/fate/frwu
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   153600, 0x050422c0
 0,          1,          1,        1,   153600, 0x0cf35359
 0,          2,          2,        1,   153600, 0x2ae95db0
diff --git a/tests/ref/fate/g2m2 b/tests/ref/fate/g2m2
index 710dbd1..42b7b6f 100644
--- a/tests/ref/fate/g2m2
+++ b/tests/ref/fate/g2m2
@@ -1,4 +1,8 @@
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x768
+#sar 0: 0/1
 0,         47,         47,        0,  2359296, 0xb4434e4f
 0,         62,         62,        0,  2359296, 0x59cb5027
 0,         78,         78,        0,  2359296, 0xe9bc578d
diff --git a/tests/ref/fate/g2m3 b/tests/ref/fate/g2m3
index e8fe692..b665d56 100644
--- a/tests/ref/fate/g2m3
+++ b/tests/ref/fate/g2m3
@@ -1,4 +1,8 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x996
+#sar 0: 0/1
 0,          0,          0,        1,  3824640, 0x9a253d29
 0,         12,         12,        1,  3824640, 0xcb232b06
 0,         15,         15,        1,  3824640, 0xb03c288c
diff --git a/tests/ref/fate/g2m4 b/tests/ref/fate/g2m4
index c9a6e12..d5ecaeb 100644
--- a/tests/ref/fate/g2m4
+++ b/tests/ref/fate/g2m4
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x1024
+#sar 0: 0/1
 0,          0,          0,        1,  3932160, 0x109148ee
 0,          1,          1,        1,  3932160, 0xa87b7bff
 0,          2,          2,        1,  3932160, 0x00e14d16
diff --git a/tests/ref/fate/g722-encode b/tests/ref/fate/g722-encode
index 3f6b3cf..ddf97c9 100644
--- a/tests/ref/fate/g722-encode
+++ b/tests/ref/fate/g722-encode
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/16000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 16000
+#channel_layout 0: 4
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     8192,    16384, 1dd9c285eb608038f3257d1a8e02eb75
 0,       8192,       8192,     8192,    16384, f7459334cbe70c06bc0897edfe64e840
diff --git a/tests/ref/fate/g722dec-1 b/tests/ref/fate/g722dec-1
index e94c3e6..b7ec0d3 100644
--- a/tests/ref/fate/g722dec-1
+++ b/tests/ref/fate/g722dec-1
@@ -1,4 +1,8 @@
 #tb 0: 1/16000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 16000
+#channel_layout 0: 4
 0,          0,          0,     2048,     4096, 0x4f9228b3
 0,       2048,       2048,     2048,     4096, 0xfab58157
 0,       4096,       4096,     2048,     4096, 0x0b641c78
diff --git a/tests/ref/fate/g723_1-dec-1 b/tests/ref/fate/g723_1-dec-1
index a3a7f67..01176fd 100644
--- a/tests/ref/fate/g723_1-dec-1
+++ b/tests/ref/fate/g723_1-dec-1
@@ -1,3 +1,7 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      240,      480, 0x7f6f3970
 0,        240,        240,      240,      480, 0x1105a0d3
diff --git a/tests/ref/fate/g723_1-dec-2 b/tests/ref/fate/g723_1-dec-2
index e7fc9b2..0711ae4 100644
--- a/tests/ref/fate/g723_1-dec-2
+++ b/tests/ref/fate/g723_1-dec-2
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      240,      480, 0x5d9d9091
 0,        240,        240,      240,      480, 0x425095b7
 0,        480,        480,      240,      480, 0xe7b6a1a7
diff --git a/tests/ref/fate/g723_1-dec-3 b/tests/ref/fate/g723_1-dec-3
index d1a2946..c1dde0c 100644
--- a/tests/ref/fate/g723_1-dec-3
+++ b/tests/ref/fate/g723_1-dec-3
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      240,      480, 0xce908869
 0,        240,        240,      240,      480, 0xfa63588e
 0,        480,        480,      240,      480, 0x11ce850c
diff --git a/tests/ref/fate/g723_1-dec-4 b/tests/ref/fate/g723_1-dec-4
index 792899d..34817ee 100644
--- a/tests/ref/fate/g723_1-dec-4
+++ b/tests/ref/fate/g723_1-dec-4
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      240,      480, 0xa697b314
 0,        240,        240,      240,      480, 0x43c5dc5a
 0,        480,        480,      240,      480, 0xd2438147
diff --git a/tests/ref/fate/g723_1-dec-5 b/tests/ref/fate/g723_1-dec-5
index bdc2982..7076fac 100644
--- a/tests/ref/fate/g723_1-dec-5
+++ b/tests/ref/fate/g723_1-dec-5
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      240,      480, 0x4dce9773
 0,        240,        240,      240,      480, 0xe6367ab8
 0,        480,        480,      240,      480, 0xf36a589d
diff --git a/tests/ref/fate/g723_1-dec-6 b/tests/ref/fate/g723_1-dec-6
index eb0e4fa..b493b37 100644
--- a/tests/ref/fate/g723_1-dec-6
+++ b/tests/ref/fate/g723_1-dec-6
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      240,      480, 0x4fa1aed9
 0,        240,        240,      240,      480, 0x6d7ef391
 0,        480,        480,      240,      480, 0xaecaf2c1
diff --git a/tests/ref/fate/g723_1-dec-7 b/tests/ref/fate/g723_1-dec-7
index cc30187..bd960f5 100644
--- a/tests/ref/fate/g723_1-dec-7
+++ b/tests/ref/fate/g723_1-dec-7
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      240,      480, 0x35e4a1fd
 0,        240,        240,      240,      480, 0x2f7bdd60
 0,        480,        480,      240,      480, 0x0407e499
diff --git a/tests/ref/fate/g723_1-dec-8 b/tests/ref/fate/g723_1-dec-8
index fc4d9f3..3399d7a 100644
--- a/tests/ref/fate/g723_1-dec-8
+++ b/tests/ref/fate/g723_1-dec-8
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      240,      480, 0x17930e0f
 0,        240,        240,      240,      480, 0x7c7f4247
 0,        480,        480,      240,      480, 0xbf3489e5
diff --git a/tests/ref/fate/g726-encode-2bit b/tests/ref/fate/g726-encode-2bit
index 2e61310..fdb42ff 100644
--- a/tests/ref/fate/g726-encode-2bit
+++ b/tests/ref/fate/g726-encode-2bit
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,    16384,    32768, b28b116d2315323aeba6b66b58b7f4ed
 0,      16384,      16384,    16384,    32768, e9cfbebe99490bd4987341ee748291c4
diff --git a/tests/ref/fate/g726-encode-3bit b/tests/ref/fate/g726-encode-3bit
index ce43d32..92ea73d 100644
--- a/tests/ref/fate/g726-encode-3bit
+++ b/tests/ref/fate/g726-encode-3bit
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,    10920,    21840, 517dd6d1ce566b998251f0d215fa69c0
 0,      10920,      10920,    10920,    21840, b0268e2bcc67acb524753790123c65fd
diff --git a/tests/ref/fate/g726-encode-4bit b/tests/ref/fate/g726-encode-4bit
index 1ccc180..ce7e1cb 100644
--- a/tests/ref/fate/g726-encode-4bit
+++ b/tests/ref/fate/g726-encode-4bit
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     8192,    16384, a0cf3a0953adce1a1032a4fd2da00a52
 0,       8192,       8192,     8192,    16384, c750c1b76a203556dd60d73d261529e9
diff --git a/tests/ref/fate/g726-encode-5bit b/tests/ref/fate/g726-encode-5bit
index 219c73d..bd0946f 100644
--- a/tests/ref/fate/g726-encode-5bit
+++ b/tests/ref/fate/g726-encode-5bit
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,     6552,    13104, 6fe3f75df1262c5f956887de9c32df40
 0,       6552,       6552,     6552,    13104, f955518de6f61f94253280d11d64d68b
diff --git a/tests/ref/fate/gapless-mp3 b/tests/ref/fate/gapless-mp3
index 2ce4b8c..ebe7bfa 100644
--- a/tests/ref/fate/gapless-mp3
+++ b/tests/ref/fate/gapless-mp3
@@ -1,5 +1,5 @@
-d5c88cf38416329a052a9b0cb140fb4c *tests/data/fate/gapless-mp3.out-1
+37534a3bcc3ef306e8c5ebfcfedfc41c *tests/data/fate/gapless-mp3.out-1
 c96c3ae7bd3300fd2f4debac222de5b7
-3386bc2009b31b7ef39247918cbb02a5 *tests/data/fate/gapless-mp3.out-2
+0cd1cdbcfd5cdbf6270cd98219bf31cd *tests/data/fate/gapless-mp3.out-2
 c96c3ae7bd3300fd2f4debac222de5b7
-3ce35ec2a9a59b7459ecd6c98d8fa123 *tests/data/fate/gapless-mp3.out-3
+9d3d8ba8a61b534f2d02ee648d6a8229 *tests/data/fate/gapless-mp3.out-3
diff --git a/tests/ref/fate/gaplessenc-itunes-to-ipod-aac b/tests/ref/fate/gaplessenc-itunes-to-ipod-aac
new file mode 100644
index 0000000..aacb058
--- /dev/null
+++ b/tests/ref/fate/gaplessenc-itunes-to-ipod-aac
@@ -0,0 +1,43 @@
+[STREAM]
+index=0
+start_pts=0
+duration_ts=104384
+[/STREAM]
+[FORMAT]
+start_time=0.000000
+duration=2.367000
+[/FORMAT]
+packet|pts=-1024|dts=-1024|duration=1024
+packet|pts=0|dts=0|duration=1024
+packet|pts=1024|dts=1024|duration=1024
+packet|pts=2048|dts=2048|duration=1024
+packet|pts=3072|dts=3072|duration=1024
+packet|pts=4096|dts=4096|duration=1024
+packet|pts=5120|dts=5120|duration=1024
+packet|pts=6144|dts=6144|duration=1024
+packet|pts=95232|dts=95232|duration=1024
+packet|pts=96256|dts=96256|duration=1024
+packet|pts=97280|dts=97280|duration=1024
+packet|pts=98304|dts=98304|duration=1024
+packet|pts=99328|dts=99328|duration=1024
+packet|pts=100352|dts=100352|duration=1024
+packet|pts=101376|dts=101376|duration=1024
+packet|pts=102400|dts=102400|duration=1984
+stream|nb_read_packets=102
+frame|pkt_pts=0|pkt_dts=0|best_effort_timestamp=0|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1024|pkt_dts=1024|best_effort_timestamp=1024|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=2048|pkt_dts=2048|best_effort_timestamp=2048|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=3072|pkt_dts=3072|best_effort_timestamp=3072|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=4096|pkt_dts=4096|best_effort_timestamp=4096|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=5120|pkt_dts=5120|best_effort_timestamp=5120|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=6144|pkt_dts=6144|best_effort_timestamp=6144|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=7168|pkt_dts=7168|best_effort_timestamp=7168|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=95232|pkt_dts=95232|best_effort_timestamp=95232|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=96256|pkt_dts=96256|best_effort_timestamp=96256|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=97280|pkt_dts=97280|best_effort_timestamp=97280|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=98304|pkt_dts=98304|best_effort_timestamp=98304|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=99328|pkt_dts=99328|best_effort_timestamp=99328|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=100352|pkt_dts=100352|best_effort_timestamp=100352|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=101376|pkt_dts=101376|best_effort_timestamp=101376|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=102400|pkt_dts=102400|best_effort_timestamp=102400|pkt_duration=1984|nb_samples=1024
+stream|nb_read_frames=101
diff --git a/tests/ref/fate/gaplessenc-pcm-to-mov-aac b/tests/ref/fate/gaplessenc-pcm-to-mov-aac
new file mode 100644
index 0000000..05dff6e
--- /dev/null
+++ b/tests/ref/fate/gaplessenc-pcm-to-mov-aac
@@ -0,0 +1,43 @@
+[STREAM]
+index=0
+start_pts=0
+duration_ts=530224
+[/STREAM]
+[FORMAT]
+start_time=0.000000
+duration=12.024000
+[/FORMAT]
+packet|pts=-1024|dts=-1024|duration=1024
+packet|pts=0|dts=0|duration=1024
+packet|pts=1024|dts=1024|duration=1024
+packet|pts=2048|dts=2048|duration=1024
+packet|pts=3072|dts=3072|duration=1024
+packet|pts=4096|dts=4096|duration=1024
+packet|pts=5120|dts=5120|duration=1024
+packet|pts=6144|dts=6144|duration=1024
+packet|pts=521216|dts=521216|duration=1024
+packet|pts=522240|dts=522240|duration=1024
+packet|pts=523264|dts=523264|duration=1024
+packet|pts=524288|dts=524288|duration=1024
+packet|pts=525312|dts=525312|duration=1024
+packet|pts=526336|dts=526336|duration=1024
+packet|pts=527360|dts=527360|duration=1024
+packet|pts=528384|dts=528384|duration=1840
+stream|nb_read_packets=518
+frame|pkt_pts=0|pkt_dts=0|best_effort_timestamp=0|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1024|pkt_dts=1024|best_effort_timestamp=1024|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=2048|pkt_dts=2048|best_effort_timestamp=2048|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=3072|pkt_dts=3072|best_effort_timestamp=3072|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=4096|pkt_dts=4096|best_effort_timestamp=4096|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=5120|pkt_dts=5120|best_effort_timestamp=5120|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=6144|pkt_dts=6144|best_effort_timestamp=6144|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=7168|pkt_dts=7168|best_effort_timestamp=7168|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=521216|pkt_dts=521216|best_effort_timestamp=521216|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=522240|pkt_dts=522240|best_effort_timestamp=522240|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=523264|pkt_dts=523264|best_effort_timestamp=523264|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=524288|pkt_dts=524288|best_effort_timestamp=524288|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=525312|pkt_dts=525312|best_effort_timestamp=525312|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=526336|pkt_dts=526336|best_effort_timestamp=526336|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=527360|pkt_dts=527360|best_effort_timestamp=527360|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=528384|pkt_dts=528384|best_effort_timestamp=528384|pkt_duration=1840|nb_samples=1024
+stream|nb_read_frames=517
diff --git a/tests/ref/fate/gaplessinfo-itunes1 b/tests/ref/fate/gaplessinfo-itunes1
new file mode 100644
index 0000000..717a2a8
--- /dev/null
+++ b/tests/ref/fate/gaplessinfo-itunes1
@@ -0,0 +1,43 @@
+[STREAM]
+index=0
+start_pts=2112
+duration_ts=1294336
+[/STREAM]
+[FORMAT]
+start_time=0.047889
+duration=29.350023
+[/FORMAT]
+packet|pts=0|dts=0|duration=1024
+packet|pts=1024|dts=1024|duration=1024
+packet|pts=2048|dts=2048|duration=1024
+packet|pts=3072|dts=3072|duration=1024
+packet|pts=4096|dts=4096|duration=1024
+packet|pts=5120|dts=5120|duration=1024
+packet|pts=6144|dts=6144|duration=1024
+packet|pts=7168|dts=7168|duration=1024
+packet|pts=1286144|dts=1286144|duration=1024
+packet|pts=1287168|dts=1287168|duration=1024
+packet|pts=1288192|dts=1288192|duration=1024
+packet|pts=1289216|dts=1289216|duration=1024
+packet|pts=1290240|dts=1290240|duration=1024
+packet|pts=1291264|dts=1291264|duration=1024
+packet|pts=1292288|dts=1292288|duration=1024
+packet|pts=1293312|dts=1293312|duration=1024
+stream|nb_read_packets=1264
+frame|pkt_pts=2112|pkt_dts=2112|best_effort_timestamp=2048|pkt_duration=960|nb_samples=960
+frame|pkt_pts=3072|pkt_dts=3072|best_effort_timestamp=3072|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=4096|pkt_dts=4096|best_effort_timestamp=4096|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=5120|pkt_dts=5120|best_effort_timestamp=5120|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=6144|pkt_dts=6144|best_effort_timestamp=6144|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=7168|pkt_dts=7168|best_effort_timestamp=7168|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=8192|pkt_dts=8192|best_effort_timestamp=8192|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=9216|pkt_dts=9216|best_effort_timestamp=9216|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1286144|pkt_dts=1286144|best_effort_timestamp=1286144|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1287168|pkt_dts=1287168|best_effort_timestamp=1287168|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1288192|pkt_dts=1288192|best_effort_timestamp=1288192|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1289216|pkt_dts=1289216|best_effort_timestamp=1289216|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1290240|pkt_dts=1290240|best_effort_timestamp=1290240|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1291264|pkt_dts=1291264|best_effort_timestamp=1291264|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1292288|pkt_dts=1292288|best_effort_timestamp=1292288|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=1293312|pkt_dts=1293312|best_effort_timestamp=1293312|pkt_duration=1024|nb_samples=1024
+stream|nb_read_frames=1262
diff --git a/tests/ref/fate/gaplessinfo-itunes2 b/tests/ref/fate/gaplessinfo-itunes2
new file mode 100644
index 0000000..be15113
--- /dev/null
+++ b/tests/ref/fate/gaplessinfo-itunes2
@@ -0,0 +1,43 @@
+[STREAM]
+index=0
+start_pts=2112
+duration_ts=105472
+[/STREAM]
+[FORMAT]
+start_time=0.047891
+duration=2.391655
+[/FORMAT]
+packet|pts=0|dts=0|duration=1024
+packet|pts=1024|dts=1024|duration=1024
+packet|pts=2048|dts=2048|duration=1024
+packet|pts=3072|dts=3072|duration=1024
+packet|pts=4096|dts=4096|duration=1024
+packet|pts=5120|dts=5120|duration=1024
+packet|pts=6144|dts=6144|duration=1024
+packet|pts=7168|dts=7168|duration=1024
+packet|pts=97280|dts=97280|duration=1024
+packet|pts=98304|dts=98304|duration=1024
+packet|pts=99328|dts=99328|duration=1024
+packet|pts=100352|dts=100352|duration=1024
+packet|pts=101376|dts=101376|duration=1024
+packet|pts=102400|dts=102400|duration=1024
+packet|pts=103424|dts=103424|duration=1024
+packet|pts=104448|dts=104448|duration=1024
+stream|nb_read_packets=103
+frame|pkt_pts=2112|pkt_dts=2112|best_effort_timestamp=2048|pkt_duration=960|nb_samples=960
+frame|pkt_pts=3072|pkt_dts=3072|best_effort_timestamp=3072|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=4096|pkt_dts=4096|best_effort_timestamp=4096|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=5120|pkt_dts=5120|best_effort_timestamp=5120|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=6144|pkt_dts=6144|best_effort_timestamp=6144|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=7168|pkt_dts=7168|best_effort_timestamp=7168|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=8192|pkt_dts=8192|best_effort_timestamp=8192|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=9216|pkt_dts=9216|best_effort_timestamp=9216|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=97280|pkt_dts=97280|best_effort_timestamp=97280|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=98304|pkt_dts=98304|best_effort_timestamp=98304|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=99328|pkt_dts=99328|best_effort_timestamp=99328|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=100352|pkt_dts=100352|best_effort_timestamp=100352|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=101376|pkt_dts=101376|best_effort_timestamp=101376|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=102400|pkt_dts=102400|best_effort_timestamp=102400|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=103424|pkt_dts=103424|best_effort_timestamp=103424|pkt_duration=1024|nb_samples=1024
+frame|pkt_pts=104448|pkt_dts=104448|best_effort_timestamp=104448|pkt_duration=1024|nb_samples=1024
+stream|nb_read_frames=101
diff --git a/tests/ref/fate/gif-color b/tests/ref/fate/gif-color
index 5559186..c88a05d 100644
--- a/tests/ref/fate/gif-color
+++ b/tests/ref/fate/gif-color
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 217x217
+#sar 0: 0/1
 0,          0,          0,        1,   188356, 0xf0944065
 0,          1,          1,        1,   188356, 0x146ed4c4
 0,          2,          2,        1,   188356, 0x96866a6f
diff --git a/tests/ref/fate/gif-deal b/tests/ref/fate/gif-deal
new file mode 100644
index 0000000..96b7723
--- /dev/null
+++ b/tests/ref/fate/gif-deal
@@ -0,0 +1,31 @@
+#tb 0: 12/109
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 430x181
+#sar 0: 0/1
+0,          0,          0,        1,   311320, 0x71905396
+0,          1,          1,        1,   311320, 0xed46b01e
+0,          2,          2,        1,   311320, 0xcbb56aa8
+0,          3,          3,        1,   311320, 0xafaab599
+0,          4,          4,        1,   311320, 0x43133abf
+0,          5,          5,        1,   311320, 0xd9677d13
+0,          6,          6,        1,   311320, 0x78abea28
+0,          7,          7,        1,   311320, 0xcb6ca011
+0,          8,          8,        1,   311320, 0x8fd40670
+0,          9,          9,        1,   311320, 0x8fd40670
+0,         10,         10,        1,   311320, 0x8fd40670
+0,         11,         11,        1,   311320, 0x8fd40670
+0,         12,         12,        1,   311320, 0x8fd40670
+0,         13,         13,        1,   311320, 0x8fd40670
+0,         14,         14,        1,   311320, 0x8fd40670
+0,         15,         15,        1,   311320, 0x8fd40670
+0,         16,         16,        1,   311320, 0x8fd40670
+0,         17,         17,        1,   311320, 0x8fd40670
+0,         18,         18,        1,   311320, 0x8fd40670
+0,         19,         19,        1,   311320, 0x8fd40670
+0,         20,         20,        1,   311320, 0x8fd40670
+0,         21,         21,        1,   311320, 0x8fd40670
+0,         22,         22,        1,   311320, 0x8fd40670
+0,         23,         23,        1,   311320, 0x8fd40670
+0,         24,         24,        1,   311320, 0x8fd40670
+0,         25,         25,        1,   311320, 0x8fd40670
diff --git a/tests/ref/fate/gif-demux b/tests/ref/fate/gif-demux
index 547b9ce..3d46441 100644
--- a/tests/ref/fate/gif-demux
+++ b/tests/ref/fate/gif-demux
@@ -1,4 +1,8 @@
 #tb 0: 1/100
+#media_type 0: video
+#codec_id 0: gif
+#dimensions 0: 480x360
+#sar 0: 0/1
 0,          0,          0,        5,    74699, 0xef7e91c8
 0,          5,          5,        2,    10079, 0x2892d9e2, F=0x0
 0,          7,          7,        2,    12369, 0xd7d73286, F=0x0
diff --git a/tests/ref/fate/gif-disposal-background b/tests/ref/fate/gif-disposal-background
index 838745b..cd0d827 100644
--- a/tests/ref/fate/gif-disposal-background
+++ b/tests/ref/fate/gif-disposal-background
@@ -1,4 +1,8 @@
 #tb 0: 1/2
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 72x36
+#sar 0: 0/1
 0,          0,          0,        1,    10368, 0x8b200cc8
 0,          1,          1,        1,    10368, 0x4e208e4f
 0,          2,          2,        1,    10368, 0x044dba8b
diff --git a/tests/ref/fate/gif-disposal-restore b/tests/ref/fate/gif-disposal-restore
index 0ff1715..b1282f6 100644
--- a/tests/ref/fate/gif-disposal-restore
+++ b/tests/ref/fate/gif-disposal-restore
@@ -1,4 +1,8 @@
 #tb 0: 1/1
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 468x60
+#sar 0: 0/1
 0,          0,          0,        1,   112320, 0xb8afe429
 0,          1,          1,        1,   112320, 0xae588a4b
 0,          3,          3,        1,   112320, 0xccdd27b7
diff --git a/tests/ref/fate/gif-gray b/tests/ref/fate/gif-gray
index 5a133bd..18705d0 100644
--- a/tests/ref/fate/gif-gray
+++ b/tests/ref/fate/gif-gray
@@ -1,4 +1,8 @@
 #tb 0: 1/100
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 480x360
+#sar 0: 0/1
 0,          0,          0,        1,   691200, 0xef6c0f3d
 0,          5,          5,        1,   691200, 0xc18b32de
 0,          7,          7,        1,   691200, 0x2395a3d7
diff --git a/tests/ref/fate/gifenc-bgr4_byte b/tests/ref/fate/gifenc-bgr4_byte
index c0d39bd..3495a8b 100644
--- a/tests/ref/fate/gifenc-bgr4_byte
+++ b/tests/ref/fate/gifenc-bgr4_byte
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: gif
+#dimensions 0: 217x217
+#sar 0: 0/1
 0,          0,          0,        1,      508, 0xa1b80fc0
 0,          1,          1,        1,      213, 0x4f554bd7, S=1,     1024, 0xb6327c81
 0,          2,          2,        1,      131, 0x283b2988, S=1,     1024, 0xae3a7c81
diff --git a/tests/ref/fate/gifenc-bgr8 b/tests/ref/fate/gifenc-bgr8
index f3b7772..0a4e5d4 100644
--- a/tests/ref/fate/gifenc-bgr8
+++ b/tests/ref/fate/gifenc-bgr8
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: gif
+#dimensions 0: 217x217
+#sar 0: 0/1
 0,          0,          0,        1,      552, 0x271a2dd3
 0,          1,          1,        1,      297, 0x90168a95, S=1,     1024, 0xf351799f
 0,          2,          2,        1,      438, 0x91efce1b, S=1,     1024, 0xf351799f
diff --git a/tests/ref/fate/gifenc-gray b/tests/ref/fate/gifenc-gray
index c11e132..81cdd18 100644
--- a/tests/ref/fate/gifenc-gray
+++ b/tests/ref/fate/gifenc-gray
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: gif
+#dimensions 0: 217x217
+#sar 0: 0/1
 0,          0,          0,        1,      579, 0x0d0e3ab8
 0,          1,          1,        1,      150, 0x178b3a8c, S=1,     1024, 0xc2f67c9f
 0,          2,          2,        1,      155, 0x941743f5, S=1,     1024, 0xc2f67c9f
diff --git a/tests/ref/fate/gifenc-pal8 b/tests/ref/fate/gifenc-pal8
index a84efa0..a6d5741 100644
--- a/tests/ref/fate/gifenc-pal8
+++ b/tests/ref/fate/gifenc-pal8
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: gif
+#dimensions 0: 217x217
+#sar 0: 0/1
 0,          0,          0,        1,      552, 0x271a2dd3, S=1,     1024, 0xec907a9e
 0,          1,          1,        1,      297, 0x90168a95, S=1,     1024, 0xf351799f
 0,          2,          2,        1,      438, 0x91efce1b, S=1,     1024, 0xf351799f
diff --git a/tests/ref/fate/gifenc-rgb4_byte b/tests/ref/fate/gifenc-rgb4_byte
index 9b00103..067accd 100644
--- a/tests/ref/fate/gifenc-rgb4_byte
+++ b/tests/ref/fate/gifenc-rgb4_byte
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: gif
+#dimensions 0: 217x217
+#sar 0: 0/1
 0,          0,          0,        1,      508, 0xf04a113b
 0,          1,          1,        1,      213, 0x23c24d3d, S=1,     1024, 0xf7700427
 0,          2,          2,        1,      131, 0x56d22a39, S=1,     1024, 0x03730427
diff --git a/tests/ref/fate/gifenc-rgb8 b/tests/ref/fate/gifenc-rgb8
index d1a990d..490e4d0 100644
--- a/tests/ref/fate/gifenc-rgb8
+++ b/tests/ref/fate/gifenc-rgb8
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: gif
+#dimensions 0: 217x217
+#sar 0: 0/1
 0,          0,          0,        1,      552, 0x47602c6c
 0,          1,          1,        1,      297, 0x49dd8847, S=1,     1024, 0xcfc8799f
 0,          2,          2,        1,      438, 0x4776d352, S=1,     1024, 0xcfc8799f
diff --git a/tests/ref/fate/gsm-ms b/tests/ref/fate/gsm-ms
index 6d15cb8..92d78f3 100644
--- a/tests/ref/fate/gsm-ms
+++ b/tests/ref/fate/gsm-ms
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      320,      640, 0xf79c59ee
 0,        320,        320,      320,      640, 0x6e6248be
 0,        640,        640,      320,      640, 0x2a5b3aed
diff --git a/tests/ref/fate/gsm-toast b/tests/ref/fate/gsm-toast
index 721e4e4..ebbfbbf 100644
--- a/tests/ref/fate/gsm-toast
+++ b/tests/ref/fate/gsm-toast
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      160,      320, 0x4c32ab06
 0,        160,        160,      160,      320, 0x2052a4e7
 0,        320,        320,      160,      320, 0xe9aeafca
diff --git a/tests/ref/fate/h264-attachment-631 b/tests/ref/fate/h264-attachment-631
new file mode 100644
index 0000000..ebb5eb4
--- /dev/null
+++ b/tests/ref/fate/h264-attachment-631
@@ -0,0 +1,20 @@
+#tb 0: 1/60
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 8/9
+0,        598,        598,        1,   518400, 0xc3c0f1cf
+0,        603,        603,        1,   518400, 0x21a5df80
+0,        607,        607,        1,   518400, 0x5b8e115b
+0,        611,        611,        1,   518400, 0x7ce09331
+0,        615,        615,        1,   518400, 0x30ff1f1f
+0,        619,        619,        1,   518400, 0x64f091ed
+0,        623,        623,        1,   518400, 0xb3c117a2
+0,        627,        627,        1,   518400, 0x0fbe146d
+0,        631,        631,        1,   518400, 0x75209293
+0,        635,        635,        1,   518400, 0xa3030208
+0,        639,        639,        1,   518400, 0x8cea6941
+0,        643,        643,        1,   518400, 0xf41d1dbd
+0,        647,        647,        1,   518400, 0xcc9fe95e
+0,        651,        651,        1,   518400, 0xa2a60dbc
+0,        655,        655,        1,   518400, 0x3f5eecdb
diff --git a/tests/ref/fate/h264-brokensps-2580 b/tests/ref/fate/h264-brokensps-2580
new file mode 100644
index 0000000..0bdb1da
--- /dev/null
+++ b/tests/ref/fate/h264-brokensps-2580
@@ -0,0 +1,84 @@
+#tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x144
+#sar 0: 0/1
+0,          0,          0,        1,    41472, 0x89c63720
+0,          2,          2,        1,    41472, 0x4605aca8
+0,          4,          4,        1,    41472, 0xc1c6fdf7
+0,          6,          6,        1,    41472, 0x09f7f4c9
+0,          8,          8,        1,    41472, 0x823abdcb
+0,         10,         10,        1,    41472, 0xc338b5e3
+0,         12,         12,        1,    41472, 0xb961599b
+0,         14,         14,        1,    41472, 0x871b59ea
+0,         16,         16,        1,    41472, 0x949a2948
+0,         18,         18,        1,    41472, 0x32561424
+0,         20,         20,        1,    41472, 0x54920aec
+0,         22,         22,        1,    41472, 0x14d6ec9d
+0,         24,         24,        1,    41472, 0x2a30e4ba
+0,         26,         26,        1,    41472, 0x8774de8b
+0,         28,         28,        1,    41472, 0xf33cd23f
+0,         32,         32,        1,    41472, 0x41059fc9
+0,         34,         34,        1,    41472, 0x65a3a3b9
+0,         36,         36,        1,    41472, 0xbf28a6bc
+0,         38,         38,        1,    41472, 0xc69bab99
+0,         40,         40,        1,    41472, 0xc5f4ae3f
+0,         42,         42,        1,    41472, 0x4c98b28e
+0,         44,         44,        1,    41472, 0x81d8afa5
+0,         46,         46,        1,    41472, 0x5293b73c
+0,         48,         48,        1,    41472, 0x5ba2bb28
+0,         50,         50,        1,    41472, 0x7fcfc16d
+0,         52,         52,        1,    41472, 0x86a4bd93
+0,         54,         54,        1,    41472, 0x7337bd9f
+0,         56,         56,        1,    41472, 0x6f84bfa0
+0,         58,         58,        1,    41472, 0x4868c1fe
+0,         60,         60,        1,    41472, 0x38d8ada8
+0,         62,         62,        1,    41472, 0x4bb988aa
+0,         64,         64,        1,    41472, 0x33a67dc5
+0,         66,         66,        1,    41472, 0xaf187be9
+0,         68,         68,        1,    41472, 0xf7d27ca8
+0,         70,         70,        1,    41472, 0xf9807fb3
+0,         72,         72,        1,    41472, 0x14447ee3
+0,         74,         74,        1,    41472, 0xf66285e9
+0,         76,         76,        1,    41472, 0x10b38fa5
+0,         78,         78,        1,    41472, 0x335d916d
+0,         80,         80,        1,    41472, 0xe82e93be
+0,         82,         82,        1,    41472, 0x2b3393d5
+0,         84,         84,        1,    41472, 0x95239770
+0,         86,         86,        1,    41472, 0xe3989676
+0,         88,         88,        1,    41472, 0x627398fd
+0,         90,         90,        1,    41472, 0xd2639c33
+0,         92,         92,        1,    41472, 0x361fa861
+0,         94,         94,        1,    41472, 0x0bf6a938
+0,         96,         96,        1,    41472, 0xf2caab81
+0,         98,         98,        1,    41472, 0xae2aab1b
+0,        100,        100,        1,    41472, 0x1c54a705
+0,        102,        102,        1,    41472, 0xe681a95f
+0,        104,        104,        1,    41472, 0x4ee7abc6
+0,        125,        125,        1,    41472, 0x68a45a04
+0,        131,        131,        1,    41472, 0xf41a4071
+0,        133,        133,        1,    41472, 0xa269adab
+0,        135,        135,        1,    41472, 0xaa1eb23d
+0,        137,        137,        1,    41472, 0xae605bff
+0,        139,        139,        1,    41472, 0xabc75beb
+0,        141,        141,        1,    41472, 0x3f988c08
+0,        143,        143,        1,    41472, 0xc2968ef7
+0,        145,        145,        1,    41472, 0x90d75ca9
+0,        147,        147,        1,    41472, 0x57096134
+0,        149,        149,        1,    41472, 0x32398f58
+0,        151,        151,        1,    41472, 0xde0c8b4c
+0,        153,        153,        1,    41472, 0x7c489797
+0,        155,        155,        1,    41472, 0xaa4e9f12
+0,        157,        157,        1,    41472, 0x9c29a032
+0,        159,        159,        1,    41472, 0x75154e97
+0,        161,        161,        1,    41472, 0x090ba403
+0,        163,        163,        1,    41472, 0xefbfa8bd
+0,        165,        165,        1,    41472, 0x7ce0289a
+0,        167,        167,        1,    41472, 0x48cc318b
+0,        169,        169,        1,    41472, 0xaf6fae87
+0,        171,        171,        1,    41472, 0xf7bab36b
+0,        173,        173,        1,    41472, 0x4a5b38cd
+0,        175,        175,        1,    41472, 0x73de3c81
+0,        177,        177,        1,    41472, 0x46e2aba0
+0,        179,        179,        1,    41472, 0xe75eb500
+0,        181,        181,        1,    41472, 0xfaf40d50
diff --git a/tests/ref/fate/h264-conformance-aud_mw_e b/tests/ref/fate/h264-conformance-aud_mw_e
index 83c6fae..890c7ff 100644
--- a/tests/ref/fate/h264-conformance-aud_mw_e
+++ b/tests/ref/fate/h264-conformance-aud_mw_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xa6d63b2e
 0,          1,          1,        1,    38016, 0x28bae101
 0,          2,          2,        1,    38016, 0x139f9b29
diff --git a/tests/ref/fate/h264-conformance-ba1_ft_c b/tests/ref/fate/h264-conformance-ba1_ft_c
index 9f6bc23..0b8f66e 100644
--- a/tests/ref/fate/h264-conformance-ba1_ft_c
+++ b/tests/ref/fate/h264-conformance-ba1_ft_c
@@ -1,4 +1,8 @@
-#tb 0: 1/25
+#tb 0: 1/19
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xa6f9b2a8
 0,          1,          1,        1,   152064, 0x936a8ed6
 0,          2,          2,        1,   152064, 0xa9f47652
diff --git a/tests/ref/fate/h264-conformance-ba1_sony_d b/tests/ref/fate/h264-conformance-ba1_sony_d
index b0145cd..c64462f 100644
--- a/tests/ref/fate/h264-conformance-ba1_sony_d
+++ b/tests/ref/fate/h264-conformance-ba1_sony_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb3883478
 0,          1,          1,        1,    38016, 0x99e1fe60
 0,          2,          2,        1,    38016, 0x65eace24
diff --git a/tests/ref/fate/h264-conformance-ba2_sony_f b/tests/ref/fate/h264-conformance-ba2_sony_f
index 13a6462..86b2df3 100644
--- a/tests/ref/fate/h264-conformance-ba2_sony_f
+++ b/tests/ref/fate/h264-conformance-ba2_sony_f
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb3883478
 0,          1,          1,        1,    38016, 0x47b90d4b
 0,          2,          2,        1,    38016, 0x3e99dfcf
diff --git a/tests/ref/fate/h264-conformance-ba3_sva_c b/tests/ref/fate/h264-conformance-ba3_sva_c
index cb775db..52d6bb0 100644
--- a/tests/ref/fate/h264-conformance-ba3_sva_c
+++ b/tests/ref/fate/h264-conformance-ba3_sva_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xbf5f1df5
 0,          1,          1,        1,    38016, 0x8de61f39
 0,          2,          2,        1,    38016, 0xaeec0a18
diff --git a/tests/ref/fate/h264-conformance-ba_mw_d b/tests/ref/fate/h264-conformance-ba_mw_d
index 18a6717..e237b58 100644
--- a/tests/ref/fate/h264-conformance-ba_mw_d
+++ b/tests/ref/fate/h264-conformance-ba_mw_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x3ae838ee
 0,          1,          1,        1,    38016, 0x9ed7e141
 0,          2,          2,        1,    38016, 0x393097f9
diff --git a/tests/ref/fate/h264-conformance-bamq1_jvc_c b/tests/ref/fate/h264-conformance-bamq1_jvc_c
index 4a3066c..a62ef08 100644
--- a/tests/ref/fate/h264-conformance-bamq1_jvc_c
+++ b/tests/ref/fate/h264-conformance-bamq1_jvc_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x6951213f
 0,          1,          1,        1,    38016, 0x82ddf39d
 0,          2,          2,        1,    38016, 0x3f81c6b1
diff --git a/tests/ref/fate/h264-conformance-bamq2_jvc_c b/tests/ref/fate/h264-conformance-bamq2_jvc_c
index 3308f77..ef6d7bd 100644
--- a/tests/ref/fate/h264-conformance-bamq2_jvc_c
+++ b/tests/ref/fate/h264-conformance-bamq2_jvc_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x6951213f
 0,          1,          1,        1,    38016, 0xd1bbf830
 0,          2,          2,        1,    38016, 0x79dcc8cb
diff --git a/tests/ref/fate/h264-conformance-banm_mw_d b/tests/ref/fate/h264-conformance-banm_mw_d
index 6108ca3..00b27bb 100644
--- a/tests/ref/fate/h264-conformance-banm_mw_d
+++ b/tests/ref/fate/h264-conformance-banm_mw_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x3ae838ee
 0,          1,          1,        1,    38016, 0x9ed7e141
 0,          2,          2,        1,    38016, 0xaf9d9753
diff --git a/tests/ref/fate/h264-conformance-basqp1_sony_c b/tests/ref/fate/h264-conformance-basqp1_sony_c
index a5038e4..2407431 100644
--- a/tests/ref/fate/h264-conformance-basqp1_sony_c
+++ b/tests/ref/fate/h264-conformance-basqp1_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xe2d73230
 0,          1,          1,        1,    38016, 0xda4dfc8e
 0,          2,          2,        1,    38016, 0x7334cb99
diff --git a/tests/ref/fate/h264-conformance-caba1_sony_d b/tests/ref/fate/h264-conformance-caba1_sony_d
index 3579820..dcd5976 100644
--- a/tests/ref/fate/h264-conformance-caba1_sony_d
+++ b/tests/ref/fate/h264-conformance-caba1_sony_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb3883478
 0,          1,          1,        1,    38016, 0x99e1fe60
 0,          2,          2,        1,    38016, 0x65eace24
diff --git a/tests/ref/fate/h264-conformance-caba1_sva_b b/tests/ref/fate/h264-conformance-caba1_sva_b
index 8b255bc..19daf44 100644
--- a/tests/ref/fate/h264-conformance-caba1_sva_b
+++ b/tests/ref/fate/h264-conformance-caba1_sva_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xee831fe4
 0,          1,          1,        1,    38016, 0x1098ff23
 0,          2,          2,        1,    38016, 0x8fc3e078
diff --git a/tests/ref/fate/h264-conformance-caba2_sony_e b/tests/ref/fate/h264-conformance-caba2_sony_e
index c30083c..acfc842 100644
--- a/tests/ref/fate/h264-conformance-caba2_sony_e
+++ b/tests/ref/fate/h264-conformance-caba2_sony_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb3883478
 0,          1,          1,        1,    38016, 0x23a30e47
 0,          2,          2,        1,    38016, 0xa0b7df0f
diff --git a/tests/ref/fate/h264-conformance-caba2_sva_b b/tests/ref/fate/h264-conformance-caba2_sva_b
index ca89226..8c77add 100644
--- a/tests/ref/fate/h264-conformance-caba2_sva_b
+++ b/tests/ref/fate/h264-conformance-caba2_sva_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xee831fe4
 0,          1,          1,        1,    38016, 0xd9130e19
 0,          2,          2,        1,    38016, 0x8ad70cae
diff --git a/tests/ref/fate/h264-conformance-caba3_sony_c b/tests/ref/fate/h264-conformance-caba3_sony_c
index c7aee37..4e35930 100644
--- a/tests/ref/fate/h264-conformance-caba3_sony_c
+++ b/tests/ref/fate/h264-conformance-caba3_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb3883478
 0,          1,          1,        1,    38016, 0xb6261cdd
 0,          2,          2,        1,    38016, 0x42ecede9
diff --git a/tests/ref/fate/h264-conformance-caba3_sva_b b/tests/ref/fate/h264-conformance-caba3_sva_b
index 7bdb3f8..cfa3c16 100644
--- a/tests/ref/fate/h264-conformance-caba3_sva_b
+++ b/tests/ref/fate/h264-conformance-caba3_sva_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x0e091175
 0,          1,          1,        1,    38016, 0xe8f81506
 0,          2,          2,        1,    38016, 0xf706f5cd
diff --git a/tests/ref/fate/h264-conformance-caba3_toshiba_e b/tests/ref/fate/h264-conformance-caba3_toshiba_e
index b31efe1..7c6c4c3 100644
--- a/tests/ref/fate/h264-conformance-caba3_toshiba_e
+++ b/tests/ref/fate/h264-conformance-caba3_toshiba_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x72723ce4
 0,          1,          1,        1,    38016, 0x347219d7
 0,          2,          2,        1,    38016, 0x813ff182
diff --git a/tests/ref/fate/h264-conformance-cabac_mot_fld0_full b/tests/ref/fate/h264-conformance-cabac_mot_fld0_full
index b131cda..8778fef 100644
--- a/tests/ref/fate/h264-conformance-cabac_mot_fld0_full
+++ b/tests/ref/fate/h264-conformance-cabac_mot_fld0_full
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xbf168f4e
 0,          1,          1,        1,   518400, 0xeda5e54f
 0,          2,          2,        1,   518400, 0xef496d43
diff --git a/tests/ref/fate/h264-conformance-cabac_mot_frm0_full b/tests/ref/fate/h264-conformance-cabac_mot_frm0_full
index 58949e2..3774cfd 100644
--- a/tests/ref/fate/h264-conformance-cabac_mot_frm0_full
+++ b/tests/ref/fate/h264-conformance-cabac_mot_frm0_full
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x40c7e2d9
 0,          1,          1,        1,   518400, 0xb16701a5
 0,          2,          2,        1,   518400, 0x12c2f5b1
diff --git a/tests/ref/fate/h264-conformance-cabac_mot_mbaff0_full b/tests/ref/fate/h264-conformance-cabac_mot_mbaff0_full
index 1e9313e..120871f 100644
--- a/tests/ref/fate/h264-conformance-cabac_mot_mbaff0_full
+++ b/tests/ref/fate/h264-conformance-cabac_mot_mbaff0_full
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x8336b7db
 0,          1,          1,        1,   518400, 0x9818c309
 0,          2,          2,        1,   518400, 0x5417b6f9
diff --git a/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full b/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full
index 484025e..5651e4b 100644
--- a/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full
+++ b/tests/ref/fate/h264-conformance-cabac_mot_picaff0_full
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xd8b58a23
 0,          1,          1,        1,   518400, 0xe53b4aba
 0,          2,          2,        1,   518400, 0x6cbca47a
diff --git a/tests/ref/fate/h264-conformance-cabaci3_sony_b b/tests/ref/fate/h264-conformance-cabaci3_sony_b
index 9dc4884..bcfce03 100644
--- a/tests/ref/fate/h264-conformance-cabaci3_sony_b
+++ b/tests/ref/fate/h264-conformance-cabaci3_sony_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x705f2f41
 0,          1,          1,        1,    38016, 0xa76d1766
 0,          2,          2,        1,    38016, 0xf367e6f4
diff --git a/tests/ref/fate/h264-conformance-cabast3_sony_e b/tests/ref/fate/h264-conformance-cabast3_sony_e
index 00519ef..38da464 100644
--- a/tests/ref/fate/h264-conformance-cabast3_sony_e
+++ b/tests/ref/fate/h264-conformance-cabast3_sony_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x96ebb3a2
 0,          1,          1,        1,   152064, 0x5184d912
 0,          2,          2,        1,   152064, 0xfa0c9abe
diff --git a/tests/ref/fate/h264-conformance-cabastbr3_sony_b b/tests/ref/fate/h264-conformance-cabastbr3_sony_b
index 765f53f..0a35250 100644
--- a/tests/ref/fate/h264-conformance-cabastbr3_sony_b
+++ b/tests/ref/fate/h264-conformance-cabastbr3_sony_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x96ebb3a2
 0,          1,          1,        1,   152064, 0x5184d912
 0,          2,          2,        1,   152064, 0xb7b5ba68
diff --git a/tests/ref/fate/h264-conformance-cabref3_sand_d b/tests/ref/fate/h264-conformance-cabref3_sand_d
index 9e555f6..d5cd445 100644
--- a/tests/ref/fate/h264-conformance-cabref3_sand_d
+++ b/tests/ref/fate/h264-conformance-cabref3_sand_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x2061bbd0
 0,          1,          1,        1,   152064, 0x41adb750
 0,          2,          2,        1,   152064, 0x6e889e90
diff --git a/tests/ref/fate/h264-conformance-cacqp3_sony_d b/tests/ref/fate/h264-conformance-cacqp3_sony_d
index c368529..788a0a5 100644
--- a/tests/ref/fate/h264-conformance-cacqp3_sony_d
+++ b/tests/ref/fate/h264-conformance-cacqp3_sony_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x295a375c
 0,          1,          1,        1,    38016, 0xd0da1f37
 0,          2,          2,        1,    38016, 0x0e5ed514
diff --git a/tests/ref/fate/h264-conformance-cafi1_sva_c b/tests/ref/fate/h264-conformance-cafi1_sva_c
index 180adf1..11d958f 100644
--- a/tests/ref/fate/h264-conformance-cafi1_sva_c
+++ b/tests/ref/fate/h264-conformance-cafi1_sva_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x47bd73fa
 0,          1,          1,        1,   518400, 0xfe3ea7cc
 0,          2,          2,        1,   518400, 0x9bc549ae
diff --git a/tests/ref/fate/h264-conformance-cama1_sony_c b/tests/ref/fate/h264-conformance-cama1_sony_c
index 6685216..9a29e30 100644
--- a/tests/ref/fate/h264-conformance-cama1_sony_c
+++ b/tests/ref/fate/h264-conformance-cama1_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x75701511
 0,          1,          1,        1,   518400, 0xa7eeaa16
 0,          2,          2,        1,   518400, 0xe0f32e35
diff --git a/tests/ref/fate/h264-conformance-cama1_toshiba_b b/tests/ref/fate/h264-conformance-cama1_toshiba_b
index ab2da4a..6e854f2 100644
--- a/tests/ref/fate/h264-conformance-cama1_toshiba_b
+++ b/tests/ref/fate/h264-conformance-cama1_toshiba_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9a9ce366
 0,          1,          1,        1,   152064, 0xf4639828
 0,          2,          2,        1,   152064, 0x625024a3
diff --git a/tests/ref/fate/h264-conformance-cama1_vtc_c b/tests/ref/fate/h264-conformance-cama1_vtc_c
index eeb66b0..bb86304 100644
--- a/tests/ref/fate/h264-conformance-cama1_vtc_c
+++ b/tests/ref/fate/h264-conformance-cama1_vtc_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x41c2ce17
 0,          1,          1,        1,   518400, 0x39f217da
 0,          2,          2,        1,   518400, 0x5a108db9
diff --git a/tests/ref/fate/h264-conformance-cama2_vtc_b b/tests/ref/fate/h264-conformance-cama2_vtc_b
index 0dfe6a9..c5c58a6 100644
--- a/tests/ref/fate/h264-conformance-cama2_vtc_b
+++ b/tests/ref/fate/h264-conformance-cama2_vtc_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 0/1
 0,          0,          0,        1,   622080, 0x004bb93f
 0,          1,          1,        1,   622080, 0xe70e193c
 0,          2,          2,        1,   622080, 0xd394cf17
diff --git a/tests/ref/fate/h264-conformance-cama3_sand_e b/tests/ref/fate/h264-conformance-cama3_sand_e
index f89bc40..e1e9784 100644
--- a/tests/ref/fate/h264-conformance-cama3_sand_e
+++ b/tests/ref/fate/h264-conformance-cama3_sand_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf772f152
 0,          1,          1,        1,   152064, 0x7c501772
 0,          2,          2,        1,   152064, 0x98ed0a07
diff --git a/tests/ref/fate/h264-conformance-cama3_vtc_b b/tests/ref/fate/h264-conformance-cama3_vtc_b
index 46821c1..288ddd1 100644
--- a/tests/ref/fate/h264-conformance-cama3_vtc_b
+++ b/tests/ref/fate/h264-conformance-cama3_vtc_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 0/1
 0,          0,          0,        1,   622080, 0xf3f0bf86
 0,          1,          1,        1,   622080, 0x6aaf3d42
 0,          2,          2,        1,   622080, 0xe53bcd5d
diff --git a/tests/ref/fate/h264-conformance-camaci3_sony_c b/tests/ref/fate/h264-conformance-camaci3_sony_c
index 5896460..9d75d00 100644
--- a/tests/ref/fate/h264-conformance-camaci3_sony_c
+++ b/tests/ref/fate/h264-conformance-camaci3_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x128
+#sar 0: 0/1
 0,          0,          0,        1,    36864, 0x9b5dcf28
 0,          1,          1,        1,    36864, 0xb13d4fee
 0,          2,          2,        1,    36864, 0x11c512ac
diff --git a/tests/ref/fate/h264-conformance-camanl1_toshiba_b b/tests/ref/fate/h264-conformance-camanl1_toshiba_b
index 2c3c557..a62f917 100644
--- a/tests/ref/fate/h264-conformance-camanl1_toshiba_b
+++ b/tests/ref/fate/h264-conformance-camanl1_toshiba_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xb1edd842
 0,          1,          1,        1,   152064, 0x551f8f45
 0,          2,          2,        1,   152064, 0xb4931cb2
diff --git a/tests/ref/fate/h264-conformance-camanl2_toshiba_b b/tests/ref/fate/h264-conformance-camanl2_toshiba_b
index 066c57f..6a2f321 100644
--- a/tests/ref/fate/h264-conformance-camanl2_toshiba_b
+++ b/tests/ref/fate/h264-conformance-camanl2_toshiba_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xb1edd842
 0,          1,          1,        1,   152064, 0x551f8f45
 0,          2,          2,        1,   152064, 0xb4931cb2
diff --git a/tests/ref/fate/h264-conformance-camanl3_sand_e b/tests/ref/fate/h264-conformance-camanl3_sand_e
index a76170c..901e4d0 100644
--- a/tests/ref/fate/h264-conformance-camanl3_sand_e
+++ b/tests/ref/fate/h264-conformance-camanl3_sand_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x6c1ff6a7
 0,          1,          1,        1,   152064, 0x17f1ff3a
 0,          2,          2,        1,   152064, 0xf7ddcda8
diff --git a/tests/ref/fate/h264-conformance-camasl3_sony_b b/tests/ref/fate/h264-conformance-camasl3_sony_b
index 0cb41e1..5bb38ab 100644
--- a/tests/ref/fate/h264-conformance-camasl3_sony_b
+++ b/tests/ref/fate/h264-conformance-camasl3_sony_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x128
+#sar 0: 0/1
 0,          0,          0,        1,    36864, 0xfe2ad849
 0,          1,          1,        1,    36864, 0x37954ba1
 0,          2,          2,        1,    36864, 0xaf0e0877
diff --git a/tests/ref/fate/h264-conformance-camp_mot_mbaff_l30 b/tests/ref/fate/h264-conformance-camp_mot_mbaff_l30
index c4f2782..ab02c2b 100644
--- a/tests/ref/fate/h264-conformance-camp_mot_mbaff_l30
+++ b/tests/ref/fate/h264-conformance-camp_mot_mbaff_l30
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x672279df
 0,          1,          1,        1,   518400, 0xb248a762
 0,          2,          2,        1,   518400, 0x4399de88
diff --git a/tests/ref/fate/h264-conformance-camp_mot_mbaff_l31 b/tests/ref/fate/h264-conformance-camp_mot_mbaff_l31
index 1bee037..dc82250 100644
--- a/tests/ref/fate/h264-conformance-camp_mot_mbaff_l31
+++ b/tests/ref/fate/h264-conformance-camp_mot_mbaff_l31
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x077637bf
 0,          1,          1,        1,   518400, 0xbd096d55
 0,          2,          2,        1,   518400, 0x58b58820
diff --git a/tests/ref/fate/h264-conformance-canl1_sony_e b/tests/ref/fate/h264-conformance-canl1_sony_e
index d90e957..849ccef 100644
--- a/tests/ref/fate/h264-conformance-canl1_sony_e
+++ b/tests/ref/fate/h264-conformance-canl1_sony_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xc805351d
 0,          1,          1,        1,    38016, 0x3809fec3
 0,          2,          2,        1,    38016, 0xf698ce3c
diff --git a/tests/ref/fate/h264-conformance-canl1_sva_b b/tests/ref/fate/h264-conformance-canl1_sva_b
index 0436f43..42ed8d7 100644
--- a/tests/ref/fate/h264-conformance-canl1_sva_b
+++ b/tests/ref/fate/h264-conformance-canl1_sva_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x0bd22424
 0,          1,          1,        1,    38016, 0x4eb601f0
 0,          2,          2,        1,    38016, 0xe16de459
diff --git a/tests/ref/fate/h264-conformance-canl1_toshiba_g b/tests/ref/fate/h264-conformance-canl1_toshiba_g
index ced4c92..73e6b7e 100644
--- a/tests/ref/fate/h264-conformance-canl1_toshiba_g
+++ b/tests/ref/fate/h264-conformance-canl1_toshiba_g
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x58892149
 0,          1,          1,        1,    38016, 0xda2ded74
 0,          2,          2,        1,    38016, 0x2661cdb0
diff --git a/tests/ref/fate/h264-conformance-canl2_sony_e b/tests/ref/fate/h264-conformance-canl2_sony_e
index 9a3b48f..567e35f 100644
--- a/tests/ref/fate/h264-conformance-canl2_sony_e
+++ b/tests/ref/fate/h264-conformance-canl2_sony_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xc805351d
 0,          1,          1,        1,    38016, 0x3017107e
 0,          2,          2,        1,    38016, 0xe172e2d2
diff --git a/tests/ref/fate/h264-conformance-canl2_sva_b b/tests/ref/fate/h264-conformance-canl2_sva_b
index 0436f43..42ed8d7 100644
--- a/tests/ref/fate/h264-conformance-canl2_sva_b
+++ b/tests/ref/fate/h264-conformance-canl2_sva_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x0bd22424
 0,          1,          1,        1,    38016, 0x4eb601f0
 0,          2,          2,        1,    38016, 0xe16de459
diff --git a/tests/ref/fate/h264-conformance-canl3_sony_c b/tests/ref/fate/h264-conformance-canl3_sony_c
index 2e726cf..80d8029 100644
--- a/tests/ref/fate/h264-conformance-canl3_sony_c
+++ b/tests/ref/fate/h264-conformance-canl3_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xc805351d
 0,          1,          1,        1,    38016, 0xa0b41fef
 0,          2,          2,        1,    38016, 0x965cf070
diff --git a/tests/ref/fate/h264-conformance-canl3_sva_b b/tests/ref/fate/h264-conformance-canl3_sva_b
index dd56a43..775550a 100644
--- a/tests/ref/fate/h264-conformance-canl3_sva_b
+++ b/tests/ref/fate/h264-conformance-canl3_sva_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x0bd22424
 0,          1,          1,        1,    38016, 0xc45d1947
 0,          2,          2,        1,    38016, 0x9d3d1218
diff --git a/tests/ref/fate/h264-conformance-canl4_sva_b b/tests/ref/fate/h264-conformance-canl4_sva_b
index a9a2dd3..9945b0b 100644
--- a/tests/ref/fate/h264-conformance-canl4_sva_b
+++ b/tests/ref/fate/h264-conformance-canl4_sva_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x5d9514e3
 0,          1,          1,        1,    38016, 0xf5e8155c
 0,          2,          2,        1,    38016, 0xc0a5f88b
diff --git a/tests/ref/fate/h264-conformance-canlma2_sony_c b/tests/ref/fate/h264-conformance-canlma2_sony_c
index b6a759a..ba3e6bd 100644
--- a/tests/ref/fate/h264-conformance-canlma2_sony_c
+++ b/tests/ref/fate/h264-conformance-canlma2_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xfbca00c6
 0,          1,          1,        1,   518400, 0x82b80adf
 0,          2,          2,        1,   518400, 0x87ecdf4a
diff --git a/tests/ref/fate/h264-conformance-canlma3_sony_c b/tests/ref/fate/h264-conformance-canlma3_sony_c
index 87ce786..57dda52 100644
--- a/tests/ref/fate/h264-conformance-canlma3_sony_c
+++ b/tests/ref/fate/h264-conformance-canlma3_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xfbca00c6
 0,          1,          1,        1,   518400, 0x82b80adf
 0,          2,          2,        1,   518400, 0x4874c24c
diff --git a/tests/ref/fate/h264-conformance-capa1_toshiba_b b/tests/ref/fate/h264-conformance-capa1_toshiba_b
index a0336f8..c88dc54 100644
--- a/tests/ref/fate/h264-conformance-capa1_toshiba_b
+++ b/tests/ref/fate/h264-conformance-capa1_toshiba_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x4040d2fc
 0,          1,          1,        1,   152064, 0x0d8f9897
 0,          2,          2,        1,   152064, 0xc23321cd
diff --git a/tests/ref/fate/h264-conformance-capama3_sand_f b/tests/ref/fate/h264-conformance-capama3_sand_f
index b621b81..b847b9a 100644
--- a/tests/ref/fate/h264-conformance-capama3_sand_f
+++ b/tests/ref/fate/h264-conformance-capama3_sand_f
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf772f152
 0,          1,          1,        1,   152064, 0xc416d300
 0,          2,          2,        1,   152064, 0xc2275c94
diff --git a/tests/ref/fate/h264-conformance-capcm1_sand_e b/tests/ref/fate/h264-conformance-capcm1_sand_e
index 392e8b4..2987c74 100644
--- a/tests/ref/fate/h264-conformance-capcm1_sand_e
+++ b/tests/ref/fate/h264-conformance-capcm1_sand_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9989b588
 0,          1,          1,        1,   152064, 0x7cbf85d4
 0,          2,          2,        1,   152064, 0x72615cf1
diff --git a/tests/ref/fate/h264-conformance-capcmnl1_sand_e b/tests/ref/fate/h264-conformance-capcmnl1_sand_e
index baee0ae..d738158 100644
--- a/tests/ref/fate/h264-conformance-capcmnl1_sand_e
+++ b/tests/ref/fate/h264-conformance-capcmnl1_sand_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf973b384
 0,          1,          1,        1,   152064, 0x84418532
 0,          2,          2,        1,   152064, 0x63165bc0
diff --git a/tests/ref/fate/h264-conformance-capm3_sony_d b/tests/ref/fate/h264-conformance-capm3_sony_d
index ab2b280..72f1e35 100644
--- a/tests/ref/fate/h264-conformance-capm3_sony_d
+++ b/tests/ref/fate/h264-conformance-capm3_sony_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xa3b72d2f
 0,          1,          1,        1,    38016, 0x77d918ae
 0,          2,          2,        1,    38016, 0x181ad684
diff --git a/tests/ref/fate/h264-conformance-caqp1_sony_b b/tests/ref/fate/h264-conformance-caqp1_sony_b
index beca1c5..874d6eb 100644
--- a/tests/ref/fate/h264-conformance-caqp1_sony_b
+++ b/tests/ref/fate/h264-conformance-caqp1_sony_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x25f92b0e
 0,          1,          1,        1,    38016, 0x2ecbe752
 0,          2,          2,        1,    38016, 0x3432e744
diff --git a/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b b/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b
index f80c3be..0ee9a39 100644
--- a/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b
+++ b/tests/ref/fate/h264-conformance-cavlc_mot_fld0_full_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x99d0df36
 0,          1,          1,        1,   518400, 0xa8601c1a
 0,          2,          2,        1,   518400, 0x4a17d235
diff --git a/tests/ref/fate/h264-conformance-cavlc_mot_frm0_full_b b/tests/ref/fate/h264-conformance-cavlc_mot_frm0_full_b
index edee4bf..611ffcd 100644
--- a/tests/ref/fate/h264-conformance-cavlc_mot_frm0_full_b
+++ b/tests/ref/fate/h264-conformance-cavlc_mot_frm0_full_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x21baedbf
 0,          1,          1,        1,   518400, 0x6003273c
 0,          2,          2,        1,   518400, 0x935d45d7
diff --git a/tests/ref/fate/h264-conformance-cavlc_mot_mbaff0_full_b b/tests/ref/fate/h264-conformance-cavlc_mot_mbaff0_full_b
index 7d3ae3e..5915f98 100644
--- a/tests/ref/fate/h264-conformance-cavlc_mot_mbaff0_full_b
+++ b/tests/ref/fate/h264-conformance-cavlc_mot_mbaff0_full_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x4cecc821
 0,          1,          1,        1,   518400, 0xee49ea81
 0,          2,          2,        1,   518400, 0x78b0d65f
diff --git a/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b b/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b
index ed5e02e..c0f6a5e 100644
--- a/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b
+++ b/tests/ref/fate/h264-conformance-cavlc_mot_picaff0_full_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xf6b83a0e
 0,          1,          1,        1,   518400, 0xc5e8b8ee
 0,          2,          2,        1,   518400, 0xb3bc6e43
diff --git a/tests/ref/fate/h264-conformance-cawp1_toshiba_e b/tests/ref/fate/h264-conformance-cawp1_toshiba_e
index e5a6944..111b228 100644
--- a/tests/ref/fate/h264-conformance-cawp1_toshiba_e
+++ b/tests/ref/fate/h264-conformance-cawp1_toshiba_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xabf9ae05
 0,          1,          1,        1,   152064, 0x20418b16
 0,          2,          2,        1,   152064, 0xc26760ae
diff --git a/tests/ref/fate/h264-conformance-cawp5_toshiba_e b/tests/ref/fate/h264-conformance-cawp5_toshiba_e
index 5b48f8f..2b055c2 100644
--- a/tests/ref/fate/h264-conformance-cawp5_toshiba_e
+++ b/tests/ref/fate/h264-conformance-cawp5_toshiba_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xabf9ae05
 0,          1,          1,        1,   152064, 0x20418b16
 0,          2,          2,        1,   152064, 0x20f72775
diff --git a/tests/ref/fate/h264-conformance-ci1_ft_b b/tests/ref/fate/h264-conformance-ci1_ft_b
index 08e40f4..650d5b5 100644
--- a/tests/ref/fate/h264-conformance-ci1_ft_b
+++ b/tests/ref/fate/h264-conformance-ci1_ft_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xb291a678
 0,          1,          1,        1,   152064, 0x913c5a5d
 0,          2,          2,        1,   152064, 0x9558a372
diff --git a/tests/ref/fate/h264-conformance-ci_mw_d b/tests/ref/fate/h264-conformance-ci_mw_d
index 7b5a7dc..275affa 100644
--- a/tests/ref/fate/h264-conformance-ci_mw_d
+++ b/tests/ref/fate/h264-conformance-ci_mw_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x3ae838ee
 0,          1,          1,        1,    38016, 0x8523e136
 0,          2,          2,        1,    38016, 0xcffc99dd
diff --git a/tests/ref/fate/h264-conformance-cvbs3_sony_c b/tests/ref/fate/h264-conformance-cvbs3_sony_c
index ad7485a..7c3ec26 100644
--- a/tests/ref/fate/h264-conformance-cvbs3_sony_c
+++ b/tests/ref/fate/h264-conformance-cvbs3_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb3883478
 0,          1,          1,        1,    38016, 0xddf01d9d
 0,          2,          2,        1,    38016, 0xb177ece2
diff --git a/tests/ref/fate/h264-conformance-cvcanlma2_sony_c b/tests/ref/fate/h264-conformance-cvcanlma2_sony_c
index b6a759a..ba3e6bd 100644
--- a/tests/ref/fate/h264-conformance-cvcanlma2_sony_c
+++ b/tests/ref/fate/h264-conformance-cvcanlma2_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xfbca00c6
 0,          1,          1,        1,   518400, 0x82b80adf
 0,          2,          2,        1,   518400, 0x87ecdf4a
diff --git a/tests/ref/fate/h264-conformance-cvfc1_sony_c b/tests/ref/fate/h264-conformance-cvfc1_sony_c
index 1abe67f..541432d 100644
--- a/tests/ref/fate/h264-conformance-cvfc1_sony_c
+++ b/tests/ref/fate/h264-conformance-cvfc1_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 300x168
+#sar 0: 0/1
 0,          0,          0,        1,    75600, 0x6f6a8c48
 0,          1,          1,        1,    75600, 0x4b7ac558
 0,          2,          2,        1,    75600, 0x907feda3
diff --git a/tests/ref/fate/h264-conformance-cvfi1_sony_d b/tests/ref/fate/h264-conformance-cvfi1_sony_d
index 195c7d6..bf998bc 100644
--- a/tests/ref/fate/h264-conformance-cvfi1_sony_d
+++ b/tests/ref/fate/h264-conformance-cvfi1_sony_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xd9444d71
 0,          1,          1,        1,   518400, 0x5d8928cd
 0,          2,          2,        1,   518400, 0xea5bc08b
diff --git a/tests/ref/fate/h264-conformance-cvfi1_sva_c b/tests/ref/fate/h264-conformance-cvfi1_sva_c
index c19bc0d..5562884 100644
--- a/tests/ref/fate/h264-conformance-cvfi1_sva_c
+++ b/tests/ref/fate/h264-conformance-cvfi1_sva_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x8f022263
 0,          1,          1,        1,   518400, 0x02692654
 0,          2,          2,        1,   518400, 0x55eff579
diff --git a/tests/ref/fate/h264-conformance-cvfi2_sony_h b/tests/ref/fate/h264-conformance-cvfi2_sony_h
index 0914e22..deb9b38 100644
--- a/tests/ref/fate/h264-conformance-cvfi2_sony_h
+++ b/tests/ref/fate/h264-conformance-cvfi2_sony_h
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xd9444d71
 0,          1,          1,        1,   518400, 0x491faf75
 0,          2,          2,        1,   518400, 0xf8b4d15c
diff --git a/tests/ref/fate/h264-conformance-cvfi2_sva_c b/tests/ref/fate/h264-conformance-cvfi2_sva_c
index 7c3162a..e2a0b6d 100644
--- a/tests/ref/fate/h264-conformance-cvfi2_sva_c
+++ b/tests/ref/fate/h264-conformance-cvfi2_sva_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x4073cc0b
 0,          1,          1,        1,   518400, 0x5f599a48
 0,          2,          2,        1,   518400, 0xc6fe555a
diff --git a/tests/ref/fate/h264-conformance-cvma1_sony_d b/tests/ref/fate/h264-conformance-cvma1_sony_d
index 6685216..9a29e30 100644
--- a/tests/ref/fate/h264-conformance-cvma1_sony_d
+++ b/tests/ref/fate/h264-conformance-cvma1_sony_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x75701511
 0,          1,          1,        1,   518400, 0xa7eeaa16
 0,          2,          2,        1,   518400, 0xe0f32e35
diff --git a/tests/ref/fate/h264-conformance-cvma1_toshiba_b b/tests/ref/fate/h264-conformance-cvma1_toshiba_b
index ab2da4a..6e854f2 100644
--- a/tests/ref/fate/h264-conformance-cvma1_toshiba_b
+++ b/tests/ref/fate/h264-conformance-cvma1_toshiba_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9a9ce366
 0,          1,          1,        1,   152064, 0xf4639828
 0,          2,          2,        1,   152064, 0x625024a3
diff --git a/tests/ref/fate/h264-conformance-cvmanl1_toshiba_b b/tests/ref/fate/h264-conformance-cvmanl1_toshiba_b
index 2c3c557..a62f917 100644
--- a/tests/ref/fate/h264-conformance-cvmanl1_toshiba_b
+++ b/tests/ref/fate/h264-conformance-cvmanl1_toshiba_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xb1edd842
 0,          1,          1,        1,   152064, 0x551f8f45
 0,          2,          2,        1,   152064, 0xb4931cb2
diff --git a/tests/ref/fate/h264-conformance-cvmanl2_toshiba_b b/tests/ref/fate/h264-conformance-cvmanl2_toshiba_b
index 066c57f..6a2f321 100644
--- a/tests/ref/fate/h264-conformance-cvmanl2_toshiba_b
+++ b/tests/ref/fate/h264-conformance-cvmanl2_toshiba_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xb1edd842
 0,          1,          1,        1,   152064, 0x551f8f45
 0,          2,          2,        1,   152064, 0xb4931cb2
diff --git a/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e b/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e
index 094fc98..8cc81e6 100644
--- a/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e
+++ b/tests/ref/fate/h264-conformance-cvmapaqp3_sony_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x80dffda2
 0,          1,          1,        1,   518400, 0x9450183b
 0,          2,          2,        1,   518400, 0x85d429a7
diff --git a/tests/ref/fate/h264-conformance-cvmaqp2_sony_g b/tests/ref/fate/h264-conformance-cvmaqp2_sony_g
index 886ea4c..a7f3e29 100644
--- a/tests/ref/fate/h264-conformance-cvmaqp2_sony_g
+++ b/tests/ref/fate/h264-conformance-cvmaqp2_sony_g
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x128
+#sar 0: 0/1
 0,          0,          0,        1,    36864, 0xdee3d4e3
 0,          1,          1,        1,    36864, 0xaa1a67ca
 0,          2,          2,        1,    36864, 0xe00e0dec
diff --git a/tests/ref/fate/h264-conformance-cvmaqp3_sony_d b/tests/ref/fate/h264-conformance-cvmaqp3_sony_d
index 7c3d96d..073422c 100644
--- a/tests/ref/fate/h264-conformance-cvmaqp3_sony_d
+++ b/tests/ref/fate/h264-conformance-cvmaqp3_sony_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x128
+#sar 0: 0/1
 0,          0,          0,        1,    36864, 0xdee3d4e3
 0,          1,          1,        1,    36864, 0xabec8d44
 0,          2,          2,        1,    36864, 0x95d029fe
diff --git a/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b b/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b
index 57fa2f7..94d4dff 100644
--- a/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b
+++ b/tests/ref/fate/h264-conformance-cvmp_mot_fld_l30_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xe9c7643e
 0,          1,          1,        1,   518400, 0xba7456ec
 0,          2,          2,        1,   518400, 0xdeb96749
diff --git a/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b b/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b
index bc7e81e..fc6b1b7 100644
--- a/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b
+++ b/tests/ref/fate/h264-conformance-cvmp_mot_frm_l31_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x7b2475e3
 0,          1,          1,        1,   518400, 0xda786a87
 0,          2,          2,        1,   518400, 0xb1dd8108
diff --git a/tests/ref/fate/h264-conformance-cvnlfi1_sony_c b/tests/ref/fate/h264-conformance-cvnlfi1_sony_c
index aa3c220..02a6b53 100644
--- a/tests/ref/fate/h264-conformance-cvnlfi1_sony_c
+++ b/tests/ref/fate/h264-conformance-cvnlfi1_sony_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x0fbb4e71
 0,          1,          1,        1,   518400, 0x4b816734
 0,          2,          2,        1,   518400, 0x0c350f19
diff --git a/tests/ref/fate/h264-conformance-cvnlfi2_sony_h b/tests/ref/fate/h264-conformance-cvnlfi2_sony_h
index fe2e4d1..c7128ba 100644
--- a/tests/ref/fate/h264-conformance-cvnlfi2_sony_h
+++ b/tests/ref/fate/h264-conformance-cvnlfi2_sony_h
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x0fbb4e71
 0,          1,          1,        1,   518400, 0xc46bec04
 0,          2,          2,        1,   518400, 0xc50ffc1d
diff --git a/tests/ref/fate/h264-conformance-cvpa1_toshiba_b b/tests/ref/fate/h264-conformance-cvpa1_toshiba_b
index fd0911b..6bf9ee3 100644
--- a/tests/ref/fate/h264-conformance-cvpa1_toshiba_b
+++ b/tests/ref/fate/h264-conformance-cvpa1_toshiba_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x128cd77a
 0,          1,          1,        1,   152064, 0x565b9fc1
 0,          2,          2,        1,   152064, 0xbe322679
diff --git a/tests/ref/fate/h264-conformance-cvpcmnl1_sva_c b/tests/ref/fate/h264-conformance-cvpcmnl1_sva_c
index 95c9903..528d2a5 100644
--- a/tests/ref/fate/h264-conformance-cvpcmnl1_sva_c
+++ b/tests/ref/fate/h264-conformance-cvpcmnl1_sva_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x19b8407d
 0,          1,          1,        1,   152064, 0xab8bede6
 0,          2,          2,        1,   152064, 0xf59acd09
diff --git a/tests/ref/fate/h264-conformance-cvpcmnl2_sva_c b/tests/ref/fate/h264-conformance-cvpcmnl2_sva_c
index 4f92eab..0303bc2 100644
--- a/tests/ref/fate/h264-conformance-cvpcmnl2_sva_c
+++ b/tests/ref/fate/h264-conformance-cvpcmnl2_sva_c
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  1382400, 0xccbe6bf8
 0,          1,          1,        1,  1382400, 0x49c0cfd7
diff --git a/tests/ref/fate/h264-conformance-cvwp1_toshiba_e b/tests/ref/fate/h264-conformance-cvwp1_toshiba_e
index b184c84..e7e6ec3 100644
--- a/tests/ref/fate/h264-conformance-cvwp1_toshiba_e
+++ b/tests/ref/fate/h264-conformance-cvwp1_toshiba_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xabf9ae05
 0,          1,          1,        1,   152064, 0x20418b16
 0,          2,          2,        1,   152064, 0xe941572f
diff --git a/tests/ref/fate/h264-conformance-cvwp2_toshiba_e b/tests/ref/fate/h264-conformance-cvwp2_toshiba_e
index 627f4b8..cd93fbc 100644
--- a/tests/ref/fate/h264-conformance-cvwp2_toshiba_e
+++ b/tests/ref/fate/h264-conformance-cvwp2_toshiba_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf503fb79
 0,          1,          1,        1,   152064, 0xeaa4ba5d
 0,          2,          2,        1,   152064, 0x50865a33
diff --git a/tests/ref/fate/h264-conformance-cvwp3_toshiba_e b/tests/ref/fate/h264-conformance-cvwp3_toshiba_e
index ca3b7b8..285892e 100644
--- a/tests/ref/fate/h264-conformance-cvwp3_toshiba_e
+++ b/tests/ref/fate/h264-conformance-cvwp3_toshiba_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x3b3ffd31
 0,          1,          1,        1,   152064, 0x14e0b899
 0,          2,          2,        1,   152064, 0x50865a33
diff --git a/tests/ref/fate/h264-conformance-cvwp5_toshiba_e b/tests/ref/fate/h264-conformance-cvwp5_toshiba_e
index 5b48f8f..2b055c2 100644
--- a/tests/ref/fate/h264-conformance-cvwp5_toshiba_e
+++ b/tests/ref/fate/h264-conformance-cvwp5_toshiba_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xabf9ae05
 0,          1,          1,        1,   152064, 0x20418b16
 0,          2,          2,        1,   152064, 0x20f72775
diff --git a/tests/ref/fate/h264-conformance-fi1_sony_e b/tests/ref/fate/h264-conformance-fi1_sony_e
index 6b5e0db..c483066 100644
--- a/tests/ref/fate/h264-conformance-fi1_sony_e
+++ b/tests/ref/fate/h264-conformance-fi1_sony_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x128
+#sar 0: 0/1
 0,          0,          0,        1,    36864, 0x3d54d3e3
 0,          1,          1,        1,    36864, 0xa9573ef0
 0,          2,          2,        1,    36864, 0x0ea5f263
diff --git a/tests/ref/fate/h264-conformance-frext-alphaconformanceg b/tests/ref/fate/h264-conformance-frext-alphaconformanceg
index dee1c42..1e894cf 100644
--- a/tests/ref/fate/h264-conformance-frext-alphaconformanceg
+++ b/tests/ref/fate/h264-conformance-frext-alphaconformanceg
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 960x544
+#sar 0: 0/1
 0,          0,          0,        1,   783360, 0xbc458a9a
 0,          1,          1,        1,   783360, 0xc2b4a765
 0,          2,          2,        1,   783360, 0x40a8ca87
diff --git a/tests/ref/fate/h264-conformance-frext-bcrm_freh10 b/tests/ref/fate/h264-conformance-frext-bcrm_freh10
index 272a4aa..7592f6c 100644
--- a/tests/ref/fate/h264-conformance-frext-bcrm_freh10
+++ b/tests/ref/fate/h264-conformance-frext-bcrm_freh10
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xbdc2b880
 0,          1,          1,        1,   152064, 0x4ebf93fe
 0,          2,          2,        1,   152064, 0xe30d6871
diff --git a/tests/ref/fate/h264-conformance-frext-brcm_freh11 b/tests/ref/fate/h264-conformance-frext-brcm_freh11
index 3183c4d..5bb9aa4 100644
--- a/tests/ref/fate/h264-conformance-frext-brcm_freh11
+++ b/tests/ref/fate/h264-conformance-frext-brcm_freh11
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9744ac59
 0,          1,          1,        1,   152064, 0x3eba88bf
 0,          2,          2,        1,   152064, 0xd4105c5a
diff --git a/tests/ref/fate/h264-conformance-frext-brcm_freh3 b/tests/ref/fate/h264-conformance-frext-brcm_freh3
index 9a40148..932354f 100644
--- a/tests/ref/fate/h264-conformance-frext-brcm_freh3
+++ b/tests/ref/fate/h264-conformance-frext-brcm_freh3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9f9caf3c
 0,          1,          1,        1,   152064, 0x4e8e9dc4
 0,          2,          2,        1,   152064, 0x7eab62be
diff --git a/tests/ref/fate/h264-conformance-frext-brcm_freh4 b/tests/ref/fate/h264-conformance-frext-brcm_freh4
index ad3a3ec..9898def 100644
--- a/tests/ref/fate/h264-conformance-frext-brcm_freh4
+++ b/tests/ref/fate/h264-conformance-frext-brcm_freh4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9744ac59
 0,          1,          1,        1,   152064, 0xe1c69d97
 0,          2,          2,        1,   152064, 0x9ae85f93
diff --git a/tests/ref/fate/h264-conformance-frext-brcm_freh5 b/tests/ref/fate/h264-conformance-frext-brcm_freh5
index 9057c82..10ff8d0 100644
--- a/tests/ref/fate/h264-conformance-frext-brcm_freh5
+++ b/tests/ref/fate/h264-conformance-frext-brcm_freh5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xd816ae9a
 0,          1,          1,        1,   152064, 0x970e9c33
 0,          2,          2,        1,   152064, 0xbdd14635
diff --git a/tests/ref/fate/h264-conformance-frext-brcm_freh8 b/tests/ref/fate/h264-conformance-frext-brcm_freh8
index 4cc7f0e..552d5e8 100644
--- a/tests/ref/fate/h264-conformance-frext-brcm_freh8
+++ b/tests/ref/fate/h264-conformance-frext-brcm_freh8
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xdcc4ac76
 0,          1,          1,        1,   152064, 0xfde6871a
 0,          2,          2,        1,   152064, 0xe8a351b5
diff --git a/tests/ref/fate/h264-conformance-frext-brcm_freh9 b/tests/ref/fate/h264-conformance-frext-brcm_freh9
index 44d5d1a..7773710 100644
--- a/tests/ref/fate/h264-conformance-frext-brcm_freh9
+++ b/tests/ref/fate/h264-conformance-frext-brcm_freh9
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9f9caf3c
 0,          1,          1,        1,   152064, 0x68f285b1
 0,          2,          2,        1,   152064, 0x28bd4987
diff --git a/tests/ref/fate/h264-conformance-frext-freh12_b b/tests/ref/fate/h264-conformance-frext-freh12_b
index 9455cc2..e32839f 100644
--- a/tests/ref/fate/h264-conformance-frext-freh12_b
+++ b/tests/ref/fate/h264-conformance-frext-freh12_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x9f9caf3c
 0,          1,          1,        1,   152064, 0x0ff688a6
 0,          2,          2,        1,   152064, 0x247d4215
diff --git a/tests/ref/fate/h264-conformance-frext-freh1_b b/tests/ref/fate/h264-conformance-frext-freh1_b
index c5c0b25..8bf4b58 100644
--- a/tests/ref/fate/h264-conformance-frext-freh1_b
+++ b/tests/ref/fate/h264-conformance-frext-freh1_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x42a3d9ce
 0,          1,          1,        1,   152064, 0xa95cc2ed
 0,          2,          2,        1,   152064, 0xc48f8fdc
diff --git a/tests/ref/fate/h264-conformance-frext-freh2_b b/tests/ref/fate/h264-conformance-frext-freh2_b
index ff12025..9ba128e 100644
--- a/tests/ref/fate/h264-conformance-frext-freh2_b
+++ b/tests/ref/fate/h264-conformance-frext-freh2_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x1668b41a
 0,          1,          1,        1,   152064, 0x953ca7fb
 0,          2,          2,        1,   152064, 0x3e38bc6e
diff --git a/tests/ref/fate/h264-conformance-frext-freh6 b/tests/ref/fate/h264-conformance-frext-freh6
index c769038..57ac261 100644
--- a/tests/ref/fate/h264-conformance-frext-freh6
+++ b/tests/ref/fate/h264-conformance-frext-freh6
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x3b21d6cd
 0,          1,          1,        1,   152064, 0xc32088c6
 0,          2,          2,        1,   152064, 0x65a64cee
diff --git a/tests/ref/fate/h264-conformance-frext-freh7_b b/tests/ref/fate/h264-conformance-frext-freh7_b
index 519c346..b078cf1 100644
--- a/tests/ref/fate/h264-conformance-frext-freh7_b
+++ b/tests/ref/fate/h264-conformance-frext-freh7_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x89f2e8d5
 0,          1,          1,        1,   152064, 0x35b99397
 0,          2,          2,        1,   152064, 0x6ef46744
diff --git a/tests/ref/fate/h264-conformance-frext-frext01_jvc_d b/tests/ref/fate/h264-conformance-frext-frext01_jvc_d
index b82151e..ac992a8 100644
--- a/tests/ref/fate/h264-conformance-frext-frext01_jvc_d
+++ b/tests/ref/fate/h264-conformance-frext-frext01_jvc_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x31bc935e
 0,          1,          1,        1,   152064, 0x501ea92a
 0,          2,          2,        1,   152064, 0x8b2f6ead
diff --git a/tests/ref/fate/h264-conformance-frext-frext02_jvc_c b/tests/ref/fate/h264-conformance-frext-frext02_jvc_c
index b82151e..ac992a8 100644
--- a/tests/ref/fate/h264-conformance-frext-frext02_jvc_c
+++ b/tests/ref/fate/h264-conformance-frext-frext02_jvc_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x31bc935e
 0,          1,          1,        1,   152064, 0x501ea92a
 0,          2,          2,        1,   152064, 0x8b2f6ead
diff --git a/tests/ref/fate/h264-conformance-frext-frext1_panasonic_c b/tests/ref/fate/h264-conformance-frext-frext1_panasonic_c
index 81748f7..7f3992d 100644
--- a/tests/ref/fate/h264-conformance-frext-frext1_panasonic_c
+++ b/tests/ref/fate/h264-conformance-frext-frext1_panasonic_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf9c30518
 0,          1,          1,        1,   152064, 0x509dd18f
 0,          2,          2,        1,   152064, 0x7f5c8f07
diff --git a/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b b/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b
index 7c53b5c..76e4d26 100644
--- a/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b
+++ b/tests/ref/fate/h264-conformance-frext-frext2_panasonic_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x0147a2a9
 0,          1,          1,        1,   152064, 0xe2365351
 0,          2,          2,        1,   152064, 0xb5f9daee
diff --git a/tests/ref/fate/h264-conformance-frext-frext3_panasonic_d b/tests/ref/fate/h264-conformance-frext-frext3_panasonic_d
index 71b743e..80ee19f 100644
--- a/tests/ref/fate/h264-conformance-frext-frext3_panasonic_d
+++ b/tests/ref/fate/h264-conformance-frext-frext3_panasonic_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xdd346292
 0,          1,          1,        1,   152064, 0xb07e6efd
 0,          2,          2,        1,   152064, 0x81b4d540
diff --git a/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a b/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a
index c0886e4..5640228 100644
--- a/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-frext4_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xd604d440
 0,          1,          1,        1,   152064, 0x08ef262c
 0,          2,          2,        1,   152064, 0x992fca8e
diff --git a/tests/ref/fate/h264-conformance-frext-frext_mmco4_sony_b b/tests/ref/fate/h264-conformance-frext-frext_mmco4_sony_b
index a964a38..dc78378 100644
--- a/tests/ref/fate/h264-conformance-frext-frext_mmco4_sony_b
+++ b/tests/ref/fate/h264-conformance-frext-frext_mmco4_sony_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x24846654
 0,          1,          1,        1,   152064, 0xd33945be
 0,          2,          2,        1,   152064, 0x961cbbfb
diff --git a/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b b/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b
index eb41d46..67badb6 100644
--- a/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b
+++ b/tests/ref/fate/h264-conformance-frext-hcaff1_hhi_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xb055a9bd
 0,          1,          1,        1,   152064, 0x9e1eadb6
 0,          2,          2,        1,   152064, 0x48f117d2
diff --git a/tests/ref/fate/h264-conformance-frext-hcafr1_hhi_c b/tests/ref/fate/h264-conformance-frext-hcafr1_hhi_c
index 285f057..7035983 100644
--- a/tests/ref/fate/h264-conformance-frext-hcafr1_hhi_c
+++ b/tests/ref/fate/h264-conformance-frext-hcafr1_hhi_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xd48c87b3
 0,          1,          1,        1,   152064, 0xb7a67f8f
 0,          2,          2,        1,   152064, 0x3c3f3c11
diff --git a/tests/ref/fate/h264-conformance-frext-hcafr2_hhi_a b/tests/ref/fate/h264-conformance-frext-hcafr2_hhi_a
index 7149850..4bc95d9 100644
--- a/tests/ref/fate/h264-conformance-frext-hcafr2_hhi_a
+++ b/tests/ref/fate/h264-conformance-frext-hcafr2_hhi_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xd5448f0e
 0,          1,          1,        1,   152064, 0x93d022ba
 0,          2,          2,        1,   152064, 0x1eaed76e
diff --git a/tests/ref/fate/h264-conformance-frext-hcafr3_hhi_a b/tests/ref/fate/h264-conformance-frext-hcafr3_hhi_a
index 2ec9dce..4fc2d99 100644
--- a/tests/ref/fate/h264-conformance-frext-hcafr3_hhi_a
+++ b/tests/ref/fate/h264-conformance-frext-hcafr3_hhi_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xd5448f0e
 0,          1,          1,        1,   152064, 0x665e33b5
 0,          2,          2,        1,   152064, 0x6648e99d
diff --git a/tests/ref/fate/h264-conformance-frext-hcafr4_hhi_a b/tests/ref/fate/h264-conformance-frext-hcafr4_hhi_a
index 00af8ff..0814654 100644
--- a/tests/ref/fate/h264-conformance-frext-hcafr4_hhi_a
+++ b/tests/ref/fate/h264-conformance-frext-hcafr4_hhi_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xc7d8832d
 0,          1,          1,        1,   152064, 0x8d9ffc59
 0,          2,          2,        1,   152064, 0xaf3ea0d1
diff --git a/tests/ref/fate/h264-conformance-frext-hcamff1_hhi_b b/tests/ref/fate/h264-conformance-frext-hcamff1_hhi_b
index df85212..a56d7e2 100644
--- a/tests/ref/fate/h264-conformance-frext-hcamff1_hhi_b
+++ b/tests/ref/fate/h264-conformance-frext-hcamff1_hhi_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x18f494ec
 0,          1,          1,        1,   152064, 0x7515e6d7
 0,          2,          2,        1,   152064, 0xaa8ee665
diff --git a/tests/ref/fate/h264-conformance-frext-hi422fr10_sony_b b/tests/ref/fate/h264-conformance-frext-hi422fr10_sony_b
index 244e546..15dfc4b 100644
--- a/tests/ref/fate/h264-conformance-frext-hi422fr10_sony_b
+++ b/tests/ref/fate/h264-conformance-frext-hi422fr10_sony_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   202752, 0xffa1c502
 0,          1,          1,        1,   202752, 0x51752f3c
 0,          2,          2,        1,   202752, 0xe683991d
diff --git a/tests/ref/fate/h264-conformance-frext-hi422fr13_sony_b b/tests/ref/fate/h264-conformance-frext-hi422fr13_sony_b
index 016abbc..8758bf5 100644
--- a/tests/ref/fate/h264-conformance-frext-hi422fr13_sony_b
+++ b/tests/ref/fate/h264-conformance-frext-hi422fr13_sony_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   405504, 0xe0f40e71
 0,          1,          1,        1,   405504, 0x9bdb5900
 0,          2,          2,        1,   405504, 0x527003ca
diff --git a/tests/ref/fate/h264-conformance-frext-hi422fr1_sony_a b/tests/ref/fate/h264-conformance-frext-hi422fr1_sony_a
index 93a3aa4..7db8672 100644
--- a/tests/ref/fate/h264-conformance-frext-hi422fr1_sony_a
+++ b/tests/ref/fate/h264-conformance-frext-hi422fr1_sony_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   202752, 0xd5a1e49f
 0,          1,          1,        1,   202752, 0x08352d61
 0,          2,          2,        1,   202752, 0x43f78f47
diff --git a/tests/ref/fate/h264-conformance-frext-hi422fr6_sony_a b/tests/ref/fate/h264-conformance-frext-hi422fr6_sony_a
index 4141eee..6d26ee4 100644
--- a/tests/ref/fate/h264-conformance-frext-hi422fr6_sony_a
+++ b/tests/ref/fate/h264-conformance-frext-hi422fr6_sony_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   405504, 0x049ab58e
 0,          1,          1,        1,   405504, 0x4f6226cb
 0,          2,          2,        1,   405504, 0xaa5fcb44
diff --git a/tests/ref/fate/h264-conformance-frext-hpca_brcm_c b/tests/ref/fate/h264-conformance-frext-hpca_brcm_c
index d608d89..2d0cd5f 100644
--- a/tests/ref/fate/h264-conformance-frext-hpca_brcm_c
+++ b/tests/ref/fate/h264-conformance-frext-hpca_brcm_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x995bb4bd
 0,          1,          1,        1,   152064, 0xad287357
 0,          2,          2,        1,   152064, 0x38fa4661
diff --git a/tests/ref/fate/h264-conformance-frext-hpcadq_brcm_b b/tests/ref/fate/h264-conformance-frext-hpcadq_brcm_b
index 49249b3..0d5794a 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcadq_brcm_b
+++ b/tests/ref/fate/h264-conformance-frext-hpcadq_brcm_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf3c68dea
 0,          1,          1,        1,   152064, 0xf52d483f
 0,          2,          2,        1,   152064, 0x612f1792
diff --git a/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c b/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c
index dbfec43..0febed6 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c
+++ b/tests/ref/fate/h264-conformance-frext-hpcafl_bcrm_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x502ec077
 0,          1,          1,        1,   152064, 0x84807243
 0,          2,          2,        1,   152064, 0xd7474a6e
diff --git a/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c b/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c
index 65a366e..9958f16 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c
+++ b/tests/ref/fate/h264-conformance-frext-hpcaflnl_bcrm_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x3e39c08b
 0,          1,          1,        1,   152064, 0xabc67990
 0,          2,          2,        1,   152064, 0x19614e74
diff --git a/tests/ref/fate/h264-conformance-frext-hpcalq_brcm_b b/tests/ref/fate/h264-conformance-frext-hpcalq_brcm_b
index 49249b3..0d5794a 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcalq_brcm_b
+++ b/tests/ref/fate/h264-conformance-frext-hpcalq_brcm_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf3c68dea
 0,          1,          1,        1,   152064, 0xf52d483f
 0,          2,          2,        1,   152064, 0x612f1792
diff --git a/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b b/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b
index a81e91f..1b03e88 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b
+++ b/tests/ref/fate/h264-conformance-frext-hpcamapalq_bcrm_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf8248ceb
 0,          1,          1,        1,   152064, 0xb6204c81
 0,          2,          2,        1,   152064, 0x22fb1737
diff --git a/tests/ref/fate/h264-conformance-frext-hpcamolq_brcm_b b/tests/ref/fate/h264-conformance-frext-hpcamolq_brcm_b
index 00f04fd..33e0688 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcamolq_brcm_b
+++ b/tests/ref/fate/h264-conformance-frext-hpcamolq_brcm_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xac83f54f
 0,          1,          1,        1,   152064, 0x4d673b43
 0,          2,          2,        1,   152064, 0x9050731f
diff --git a/tests/ref/fate/h264-conformance-frext-hpcanl_brcm_c b/tests/ref/fate/h264-conformance-frext-hpcanl_brcm_c
index 23ad267..f3edba1 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcanl_brcm_c
+++ b/tests/ref/fate/h264-conformance-frext-hpcanl_brcm_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x2744afa1
 0,          1,          1,        1,   152064, 0x17246583
 0,          2,          2,        1,   152064, 0x501836ed
diff --git a/tests/ref/fate/h264-conformance-frext-hpcaq2lq_brcm_b b/tests/ref/fate/h264-conformance-frext-hpcaq2lq_brcm_b
index 460f86c..b0412db 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcaq2lq_brcm_b
+++ b/tests/ref/fate/h264-conformance-frext-hpcaq2lq_brcm_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x712a2ad3
 0,          1,          1,        1,   152064, 0x83420c9d
 0,          2,          2,        1,   152064, 0xf3d77f46
diff --git a/tests/ref/fate/h264-conformance-frext-hpcv_brcm_a b/tests/ref/fate/h264-conformance-frext-hpcv_brcm_a
index d608d89..2d0cd5f 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcv_brcm_a
+++ b/tests/ref/fate/h264-conformance-frext-hpcv_brcm_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x995bb4bd
 0,          1,          1,        1,   152064, 0xad287357
 0,          2,          2,        1,   152064, 0x38fa4661
diff --git a/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a b/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a
index dbfec43..0febed6 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a
+++ b/tests/ref/fate/h264-conformance-frext-hpcvfl_bcrm_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x502ec077
 0,          1,          1,        1,   152064, 0x84807243
 0,          2,          2,        1,   152064, 0xd7474a6e
diff --git a/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a b/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a
index 65a366e..9958f16 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a
+++ b/tests/ref/fate/h264-conformance-frext-hpcvflnl_bcrm_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x3e39c08b
 0,          1,          1,        1,   152064, 0xabc67990
 0,          2,          2,        1,   152064, 0x19614e74
diff --git a/tests/ref/fate/h264-conformance-frext-hpcvmolq_brcm_b b/tests/ref/fate/h264-conformance-frext-hpcvmolq_brcm_b
index 4179ace..f722388 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcvmolq_brcm_b
+++ b/tests/ref/fate/h264-conformance-frext-hpcvmolq_brcm_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xa18cfb97
 0,          1,          1,        1,   152064, 0x509b54d2
 0,          2,          2,        1,   152064, 0x1ba0fb8e
diff --git a/tests/ref/fate/h264-conformance-frext-hpcvnl_brcm_a b/tests/ref/fate/h264-conformance-frext-hpcvnl_brcm_a
index 23ad267..f3edba1 100644
--- a/tests/ref/fate/h264-conformance-frext-hpcvnl_brcm_a
+++ b/tests/ref/fate/h264-conformance-frext-hpcvnl_brcm_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0x2744afa1
 0,          1,          1,        1,   152064, 0x17246583
 0,          2,          2,        1,   152064, 0x501836ed
diff --git a/tests/ref/fate/h264-conformance-frext-pph10i1_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph10i1_panasonic_a
index 91e3436..ccd9328 100644
--- a/tests/ref/fate/h264-conformance-frext-pph10i1_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph10i1_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  2764800, 0xcc4df07d
 0,          1,          1,        1,  2764800, 0x85f9e6d4
 0,          2,          2,        1,  2764800, 0x23ffe90d
diff --git a/tests/ref/fate/h264-conformance-frext-pph10i2_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph10i2_panasonic_a
index 1d6d4b5..835c495 100644
--- a/tests/ref/fate/h264-conformance-frext-pph10i2_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph10i2_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  2764800, 0x4f710132
 0,          1,          1,        1,  2764800, 0x57e5b713
 0,          2,          2,        1,  2764800, 0xcca01477
diff --git a/tests/ref/fate/h264-conformance-frext-pph10i3_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph10i3_panasonic_a
index a09e397..f46dfaa 100644
--- a/tests/ref/fate/h264-conformance-frext-pph10i3_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph10i3_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  2764800, 0xda69f69e
 0,          1,          1,        1,  2764800, 0x29ed832f
 0,          2,          2,        1,  2764800, 0xb3244cc4
diff --git a/tests/ref/fate/h264-conformance-frext-pph10i4_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph10i4_panasonic_a
index adec664..c7dfa8e 100644
--- a/tests/ref/fate/h264-conformance-frext-pph10i4_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph10i4_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  6220800, 0xca2a2a5e
 0,          1,          1,        1,  6220800, 0x8009a65e
 0,          2,          2,        1,  6220800, 0x63e72b3b
diff --git a/tests/ref/fate/h264-conformance-frext-pph10i5_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph10i5_panasonic_a
index a475197..52b3d24 100644
--- a/tests/ref/fate/h264-conformance-frext-pph10i5_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph10i5_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  6220800, 0x1df58ce9
 0,          1,          1,        1,  6220800, 0x8f2859ce
 0,          2,          2,        1,  6220800, 0x229cc7ff
diff --git a/tests/ref/fate/h264-conformance-frext-pph10i6_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph10i6_panasonic_a
index 25d0eec..d1eaf65 100644
--- a/tests/ref/fate/h264-conformance-frext-pph10i6_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph10i6_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  6220800, 0x408daf70
 0,          1,          1,        1,  6220800, 0x59b254a3
 0,          2,          2,        1,  6220800, 0x4cf4279c
diff --git a/tests/ref/fate/h264-conformance-frext-pph10i7_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph10i7_panasonic_a
index 1090b49..7d55719 100644
--- a/tests/ref/fate/h264-conformance-frext-pph10i7_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph10i7_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  6220800, 0xf81873fe
 0,          1,          1,        1,  6220800, 0x7b96fbdc
 0,          2,          2,        1,  6220800, 0x75dbafc4
diff --git a/tests/ref/fate/h264-conformance-frext-pph422i1_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph422i1_panasonic_a
index 0957654..3163089 100644
--- a/tests/ref/fate/h264-conformance-frext-pph422i1_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph422i1_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  3686400, 0x1f9b5bee
 0,          1,          1,        1,  3686400, 0x657c3609
 0,          2,          2,        1,  3686400, 0x75753934
diff --git a/tests/ref/fate/h264-conformance-frext-pph422i2_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph422i2_panasonic_a
index 79e69eb..faa75ca 100644
--- a/tests/ref/fate/h264-conformance-frext-pph422i2_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph422i2_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  3686400, 0x8b3ff360
 0,          1,          1,        1,  3686400, 0x422dead1
 0,          2,          2,        1,  3686400, 0xbdd0e431
diff --git a/tests/ref/fate/h264-conformance-frext-pph422i3_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph422i3_panasonic_a
index fc4cc50..a9befbd 100644
--- a/tests/ref/fate/h264-conformance-frext-pph422i3_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph422i3_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  3686400, 0x97c36ae3
 0,          1,          1,        1,  3686400, 0x6a0aa629
 0,          2,          2,        1,  3686400, 0xc658d722
diff --git a/tests/ref/fate/h264-conformance-frext-pph422i4_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph422i4_panasonic_a
index 0aae9fe..6289caa 100644
--- a/tests/ref/fate/h264-conformance-frext-pph422i4_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph422i4_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0xf50992f3
 0,          1,          1,        1,  8294400, 0xd34cdf98
 0,          2,          2,        1,  8294400, 0x76bced00
diff --git a/tests/ref/fate/h264-conformance-frext-pph422i5_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph422i5_panasonic_a
index c74483c..b187532 100644
--- a/tests/ref/fate/h264-conformance-frext-pph422i5_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph422i5_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x96d051a1
 0,          1,          1,        1,  8294400, 0xf3c2974e
 0,          2,          2,        1,  8294400, 0xb18f3ed0
diff --git a/tests/ref/fate/h264-conformance-frext-pph422i6_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph422i6_panasonic_a
index 26d41d4..817bc9c 100644
--- a/tests/ref/fate/h264-conformance-frext-pph422i6_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph422i6_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x1b2f1079
 0,          1,          1,        1,  8294400, 0x6646f91c
 0,          2,          2,        1,  8294400, 0x17dc9f51
diff --git a/tests/ref/fate/h264-conformance-frext-pph422i7_panasonic_a b/tests/ref/fate/h264-conformance-frext-pph422i7_panasonic_a
index 3f9bfed..3219da0 100644
--- a/tests/ref/fate/h264-conformance-frext-pph422i7_panasonic_a
+++ b/tests/ref/fate/h264-conformance-frext-pph422i7_panasonic_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0xaa37ceea
 0,          1,          1,        1,  8294400, 0xa7546d5c
 0,          2,          2,        1,  8294400, 0xf2abaace
diff --git a/tests/ref/fate/h264-conformance-hcbp2_hhi_a b/tests/ref/fate/h264-conformance-hcbp2_hhi_a
index 977107e..36d39c9 100644
--- a/tests/ref/fate/h264-conformance-hcbp2_hhi_a
+++ b/tests/ref/fate/h264-conformance-hcbp2_hhi_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xf9deb95a
 0,          1,          1,        1,   152064, 0xdce9c541
 0,          2,          2,        1,   152064, 0xc45a8a77
diff --git a/tests/ref/fate/h264-conformance-hcmp1_hhi_a b/tests/ref/fate/h264-conformance-hcmp1_hhi_a
index be619da..578f98d 100644
--- a/tests/ref/fate/h264-conformance-hcmp1_hhi_a
+++ b/tests/ref/fate/h264-conformance-hcmp1_hhi_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   152064, 0xda244f3f
 0,          1,          1,        1,   152064, 0x35a1cb02
 0,          2,          2,        1,   152064, 0xa729d9ca
diff --git a/tests/ref/fate/h264-conformance-ls_sva_d b/tests/ref/fate/h264-conformance-ls_sva_d
index 9d1d219..d3826ab 100644
--- a/tests/ref/fate/h264-conformance-ls_sva_d
+++ b/tests/ref/fate/h264-conformance-ls_sva_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x85d20fc6
 0,          1,          1,        1,    38016, 0xc0432c21
 0,          2,          2,        1,    38016, 0x1450168f
diff --git a/tests/ref/fate/h264-conformance-midr_mw_d b/tests/ref/fate/h264-conformance-midr_mw_d
index 51b7c0e..3afa65f 100644
--- a/tests/ref/fate/h264-conformance-midr_mw_d
+++ b/tests/ref/fate/h264-conformance-midr_mw_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x3ae838ee
 0,          1,          1,        1,    38016, 0x9ed7e141
 0,          2,          2,        1,    38016, 0x393097f9
diff --git a/tests/ref/fate/h264-conformance-mps_mw_a b/tests/ref/fate/h264-conformance-mps_mw_a
index 959a0ae..ae38cfc 100644
--- a/tests/ref/fate/h264-conformance-mps_mw_a
+++ b/tests/ref/fate/h264-conformance-mps_mw_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x06150e88
 0,          1,          1,        1,    38016, 0x32d90103
 0,          2,          2,        1,    38016, 0x5b5f2fae
diff --git a/tests/ref/fate/h264-conformance-mr1_bt_a b/tests/ref/fate/h264-conformance-mr1_bt_a
index 11eb590..273ee08 100644
--- a/tests/ref/fate/h264-conformance-mr1_bt_a
+++ b/tests/ref/fate/h264-conformance-mr1_bt_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xc6658719
 0,          1,          1,        1,    38016, 0x8a7c7423
 0,          2,          2,        1,    38016, 0x97e99b66
diff --git a/tests/ref/fate/h264-conformance-mr1_mw_a b/tests/ref/fate/h264-conformance-mr1_mw_a
index da7631d..7b154ba 100644
--- a/tests/ref/fate/h264-conformance-mr1_mw_a
+++ b/tests/ref/fate/h264-conformance-mr1_mw_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xc8981780
 0,          1,          1,        1,    38016, 0xf089d880
 0,          2,          2,        1,    38016, 0x5eee0731
diff --git a/tests/ref/fate/h264-conformance-mr2_mw_a b/tests/ref/fate/h264-conformance-mr2_mw_a
index fd4b5d9..833cea9 100644
--- a/tests/ref/fate/h264-conformance-mr2_mw_a
+++ b/tests/ref/fate/h264-conformance-mr2_mw_a
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x06150e88
 0,          1,          1,        1,    38016, 0x32d90103
 0,          2,          2,        1,    38016, 0xb32d338f
diff --git a/tests/ref/fate/h264-conformance-mr2_tandberg_e b/tests/ref/fate/h264-conformance-mr2_tandberg_e
index 8fbac9f..c0e1d83 100644
--- a/tests/ref/fate/h264-conformance-mr2_tandberg_e
+++ b/tests/ref/fate/h264-conformance-mr2_tandberg_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb96f1feb
 0,          1,          1,        1,    38016, 0xca461abd
 0,          2,          2,        1,    38016, 0x578a0c87
diff --git a/tests/ref/fate/h264-conformance-mr3_tandberg_b b/tests/ref/fate/h264-conformance-mr3_tandberg_b
index ee8014e..b094844 100644
--- a/tests/ref/fate/h264-conformance-mr3_tandberg_b
+++ b/tests/ref/fate/h264-conformance-mr3_tandberg_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb96f1feb
 0,          1,          1,        1,    38016, 0xca461abd
 0,          2,          2,        1,    38016, 0x578a0c87
diff --git a/tests/ref/fate/h264-conformance-mr4_tandberg_c b/tests/ref/fate/h264-conformance-mr4_tandberg_c
index 0d5f646..87bcaa4 100644
--- a/tests/ref/fate/h264-conformance-mr4_tandberg_c
+++ b/tests/ref/fate/h264-conformance-mr4_tandberg_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb96f1feb
 0,          1,          1,        1,    38016, 0x0ff111f0
 0,          2,          2,        1,    38016, 0xbac70271
diff --git a/tests/ref/fate/h264-conformance-mr5_tandberg_c b/tests/ref/fate/h264-conformance-mr5_tandberg_c
index 0d5f646..87bcaa4 100644
--- a/tests/ref/fate/h264-conformance-mr5_tandberg_c
+++ b/tests/ref/fate/h264-conformance-mr5_tandberg_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb96f1feb
 0,          1,          1,        1,    38016, 0x0ff111f0
 0,          2,          2,        1,    38016, 0xbac70271
diff --git a/tests/ref/fate/h264-conformance-mr6_bt_b b/tests/ref/fate/h264-conformance-mr6_bt_b
index 3b02506..34aa8bf 100644
--- a/tests/ref/fate/h264-conformance-mr6_bt_b
+++ b/tests/ref/fate/h264-conformance-mr6_bt_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x128
+#sar 0: 0/1
 0,          0,          0,        1,    36864, 0x954464be
 0,          1,          1,        1,    36864, 0xace1d90b
 0,          2,          2,        1,    36864, 0x8f149f03
diff --git a/tests/ref/fate/h264-conformance-mr7_bt_b b/tests/ref/fate/h264-conformance-mr7_bt_b
index 25b7054..551767c 100644
--- a/tests/ref/fate/h264-conformance-mr7_bt_b
+++ b/tests/ref/fate/h264-conformance-mr7_bt_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x128
+#sar 0: 0/1
 0,          0,          0,        1,    36864, 0x579e6274
 0,          1,          1,        1,    36864, 0x8650c61c
 0,          2,          2,        1,    36864, 0xbc359647
diff --git a/tests/ref/fate/h264-conformance-mr8_bt_b b/tests/ref/fate/h264-conformance-mr8_bt_b
index 220acf1..7981c42 100644
--- a/tests/ref/fate/h264-conformance-mr8_bt_b
+++ b/tests/ref/fate/h264-conformance-mr8_bt_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x128
+#sar 0: 0/1
 0,          0,          0,        1,    36864, 0x36df68f4
 0,          1,          1,        1,    36864, 0x52d4c6d9
 0,          2,          2,        1,    36864, 0xad16b0be
diff --git a/tests/ref/fate/h264-conformance-mr9_bt_b b/tests/ref/fate/h264-conformance-mr9_bt_b
index 3744802..bbd90e6 100644
--- a/tests/ref/fate/h264-conformance-mr9_bt_b
+++ b/tests/ref/fate/h264-conformance-mr9_bt_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x128
+#sar 0: 0/1
 0,          0,          0,        1,    36864, 0xb4c5642e
 0,          1,          1,        1,    36864, 0x929fd05f
 0,          2,          2,        1,    36864, 0x447c9b69
diff --git a/tests/ref/fate/h264-conformance-mv1_brcm_d b/tests/ref/fate/h264-conformance-mv1_brcm_d
index 47517ee..a3ab27b 100644
--- a/tests/ref/fate/h264-conformance-mv1_brcm_d
+++ b/tests/ref/fate/h264-conformance-mv1_brcm_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0x230d7aa6
 0,          1,          1,        1,   518400, 0x9fc976e0
 0,          2,          2,        1,   518400, 0x51052db9
diff --git a/tests/ref/fate/h264-conformance-nl1_sony_d b/tests/ref/fate/h264-conformance-nl1_sony_d
index 98a5673..d6e0df9 100644
--- a/tests/ref/fate/h264-conformance-nl1_sony_d
+++ b/tests/ref/fate/h264-conformance-nl1_sony_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xc805351d
 0,          1,          1,        1,    38016, 0x3809fec3
 0,          2,          2,        1,    38016, 0xf698ce3c
diff --git a/tests/ref/fate/h264-conformance-nl2_sony_h b/tests/ref/fate/h264-conformance-nl2_sony_h
index 73eb858..1e7bfb3 100644
--- a/tests/ref/fate/h264-conformance-nl2_sony_h
+++ b/tests/ref/fate/h264-conformance-nl2_sony_h
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xc805351d
 0,          1,          1,        1,    38016, 0x320510a8
 0,          2,          2,        1,    38016, 0x3ef6e4c6
diff --git a/tests/ref/fate/h264-conformance-nl3_sva_e b/tests/ref/fate/h264-conformance-nl3_sva_e
index a4d6db6..a09e083 100644
--- a/tests/ref/fate/h264-conformance-nl3_sva_e
+++ b/tests/ref/fate/h264-conformance-nl3_sva_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x2fad15e2
 0,          1,          1,        1,    38016, 0x7e391566
 0,          2,          2,        1,    38016, 0x954001d4
diff --git a/tests/ref/fate/h264-conformance-nlmq1_jvc_c b/tests/ref/fate/h264-conformance-nlmq1_jvc_c
index 3030125..dbcdcdf 100644
--- a/tests/ref/fate/h264-conformance-nlmq1_jvc_c
+++ b/tests/ref/fate/h264-conformance-nlmq1_jvc_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xde1a2194
 0,          1,          1,        1,    38016, 0x2957f3e5
 0,          2,          2,        1,    38016, 0x9df4c6cf
diff --git a/tests/ref/fate/h264-conformance-nlmq2_jvc_c b/tests/ref/fate/h264-conformance-nlmq2_jvc_c
index 5258eb2..8dc6285 100644
--- a/tests/ref/fate/h264-conformance-nlmq2_jvc_c
+++ b/tests/ref/fate/h264-conformance-nlmq2_jvc_c
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xde1a2194
 0,          1,          1,        1,    38016, 0x8b6cf842
 0,          2,          2,        1,    38016, 0x6dc7c88b
diff --git a/tests/ref/fate/h264-conformance-nrf_mw_e b/tests/ref/fate/h264-conformance-nrf_mw_e
index ee5f719..b68a6a7 100644
--- a/tests/ref/fate/h264-conformance-nrf_mw_e
+++ b/tests/ref/fate/h264-conformance-nrf_mw_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x3ae838ee
 0,          1,          1,        1,    38016, 0x9ed7e141
 0,          2,          2,        1,    38016, 0x354e83ed
diff --git a/tests/ref/fate/h264-conformance-sharp_mp_field_1_b b/tests/ref/fate/h264-conformance-sharp_mp_field_1_b
index 8512102..cdabcce 100644
--- a/tests/ref/fate/h264-conformance-sharp_mp_field_1_b
+++ b/tests/ref/fate/h264-conformance-sharp_mp_field_1_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xc93c7c47
 0,          1,          1,        1,   518400, 0xa3f2e502
 0,          2,          2,        1,   518400, 0xb98920a4
diff --git a/tests/ref/fate/h264-conformance-sharp_mp_field_2_b b/tests/ref/fate/h264-conformance-sharp_mp_field_2_b
index 5808141..0574f8f 100644
--- a/tests/ref/fate/h264-conformance-sharp_mp_field_2_b
+++ b/tests/ref/fate/h264-conformance-sharp_mp_field_2_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xc93c7c47
 0,          1,          1,        1,   518400, 0xf0c4b44a
 0,          2,          2,        1,   518400, 0x3f5dc91c
diff --git a/tests/ref/fate/h264-conformance-sharp_mp_field_3_b b/tests/ref/fate/h264-conformance-sharp_mp_field_3_b
index a572030..6a92245 100644
--- a/tests/ref/fate/h264-conformance-sharp_mp_field_3_b
+++ b/tests/ref/fate/h264-conformance-sharp_mp_field_3_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xc93c7c47
 0,          1,          1,        1,   518400, 0x7112ac25
 0,          2,          2,        1,   518400, 0x28bc28d2
diff --git a/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2 b/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2
index d1a347f..8a7aa24 100644
--- a/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2
+++ b/tests/ref/fate/h264-conformance-sharp_mp_paff_1r2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xc93c7c47
 0,          1,          1,        1,   518400, 0xfb452a9c
 0,          2,          2,        1,   518400, 0x2f7a35bd
diff --git a/tests/ref/fate/h264-conformance-sharp_mp_paff_2r b/tests/ref/fate/h264-conformance-sharp_mp_paff_2r
index f2bf06f..ded91a9 100644
--- a/tests/ref/fate/h264-conformance-sharp_mp_paff_2r
+++ b/tests/ref/fate/h264-conformance-sharp_mp_paff_2r
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,   518400, 0xc93c7c47
 0,          1,          1,        1,   518400, 0xfb452a9c
 0,          2,          2,        1,   518400, 0x2f7a35bd
diff --git a/tests/ref/fate/h264-conformance-sl1_sva_b b/tests/ref/fate/h264-conformance-sl1_sva_b
index a2f16b4..572d5a0 100644
--- a/tests/ref/fate/h264-conformance-sl1_sva_b
+++ b/tests/ref/fate/h264-conformance-sl1_sva_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x666c110c
 0,          1,          1,        1,    38016, 0xc87421f6
 0,          2,          2,        1,    38016, 0x1b74033d
diff --git a/tests/ref/fate/h264-conformance-sva_ba1_b b/tests/ref/fate/h264-conformance-sva_ba1_b
index cc55ac9..6b38348 100644
--- a/tests/ref/fate/h264-conformance-sva_ba1_b
+++ b/tests/ref/fate/h264-conformance-sva_ba1_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x359316a1
 0,          1,          1,        1,    38016, 0xd5fafa54
 0,          2,          2,        1,    38016, 0xea99e9be
diff --git a/tests/ref/fate/h264-conformance-sva_ba2_d b/tests/ref/fate/h264-conformance-sva_ba2_d
index b94086f..7c5ec98 100644
--- a/tests/ref/fate/h264-conformance-sva_ba2_d
+++ b/tests/ref/fate/h264-conformance-sva_ba2_d
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x359316a1
 0,          1,          1,        1,    38016, 0xd7bb1285
 0,          2,          2,        1,    38016, 0x3c36059f
diff --git a/tests/ref/fate/h264-conformance-sva_base_b b/tests/ref/fate/h264-conformance-sva_base_b
index 30663ff..3ed51fd 100644
--- a/tests/ref/fate/h264-conformance-sva_base_b
+++ b/tests/ref/fate/h264-conformance-sva_base_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x1c131302
 0,          1,          1,        1,    38016, 0xbbca0c4f
 0,          2,          2,        1,    38016, 0x81f5fd7b
diff --git a/tests/ref/fate/h264-conformance-sva_cl1_e b/tests/ref/fate/h264-conformance-sva_cl1_e
index 27cba6d..2f32114 100644
--- a/tests/ref/fate/h264-conformance-sva_cl1_e
+++ b/tests/ref/fate/h264-conformance-sva_cl1_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x6811161f
 0,          1,          1,        1,    38016, 0x243a0d4e
 0,          2,          2,        1,    38016, 0x0bc700de
diff --git a/tests/ref/fate/h264-conformance-sva_fm1_e b/tests/ref/fate/h264-conformance-sva_fm1_e
index 0e5f3e0..52ed49b 100644
--- a/tests/ref/fate/h264-conformance-sva_fm1_e
+++ b/tests/ref/fate/h264-conformance-sva_fm1_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x1c131302
 0,          1,          1,        1,    38016, 0x89dd0c15
 0,          2,          2,        1,    38016, 0xaf7700bd
diff --git a/tests/ref/fate/h264-conformance-sva_nl1_b b/tests/ref/fate/h264-conformance-sva_nl1_b
index f2033d8..c59aa2c 100644
--- a/tests/ref/fate/h264-conformance-sva_nl1_b
+++ b/tests/ref/fate/h264-conformance-sva_nl1_b
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb9ac19bd
 0,          1,          1,        1,    38016, 0x3898fc35
 0,          2,          2,        1,    38016, 0xf6f4ed19
diff --git a/tests/ref/fate/h264-conformance-sva_nl2_e b/tests/ref/fate/h264-conformance-sva_nl2_e
index 1770eff..5f8006b 100644
--- a/tests/ref/fate/h264-conformance-sva_nl2_e
+++ b/tests/ref/fate/h264-conformance-sva_nl2_e
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0xb9ac19bd
 0,          1,          1,        1,    38016, 0x53c91566
 0,          2,          2,        1,    38016, 0xb5bd089f
diff --git a/tests/ref/fate/h264-crop-to-container b/tests/ref/fate/h264-crop-to-container
index 4932bdd..855c93d 100644
--- a/tests/ref/fate/h264-crop-to-container
+++ b/tests/ref/fate/h264-crop-to-container
@@ -1,6 +1,10 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,  3110400, 43a312e1eebc7dca1bd23456302a44e3
diff --git a/tests/ref/fate/h264-direct-bff b/tests/ref/fate/h264-direct-bff
index 4d233b5..802733e 100644
--- a/tests/ref/fate/h264-direct-bff
+++ b/tests/ref/fate/h264-direct-bff
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x484
+#sar 0: 1/1
 0,          0,          0,        1,   522720, 0x1ccad503
 0,          1,          1,        1,   522720, 0xd266d6e8
 0,          2,          2,        1,   522720, 0x535473b3
diff --git a/tests/ref/fate/h264-dts_5frames b/tests/ref/fate/h264-dts_5frames
new file mode 100644
index 0000000..1c4c349
--- /dev/null
+++ b/tests/ref/fate/h264-dts_5frames
@@ -0,0 +1,125 @@
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=1
+pkt_pts=0
+pkt_pts_time=0.000000
+pkt_dts=0
+pkt_dts_time=0.000000
+best_effort_timestamp=0
+best_effort_timestamp_time=0.000000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=651
+pkt_size=14428
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=I
+coded_picture_number=0
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=0
+pkt_pts=167
+pkt_pts_time=0.167000
+pkt_dts=167
+pkt_dts_time=0.167000
+best_effort_timestamp=167
+best_effort_timestamp_time=0.167000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=15085
+pkt_size=11
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=P
+coded_picture_number=1
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=0
+pkt_pts=333
+pkt_pts_time=0.333000
+pkt_dts=333
+pkt_dts_time=0.333000
+best_effort_timestamp=333
+best_effort_timestamp_time=0.333000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=15102
+pkt_size=11
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=P
+coded_picture_number=2
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=0
+pkt_pts=500
+pkt_pts_time=0.500000
+pkt_dts=500
+pkt_dts_time=0.500000
+best_effort_timestamp=500
+best_effort_timestamp_time=0.500000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=15119
+pkt_size=11
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=P
+coded_picture_number=3
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
+[FRAME]
+media_type=video
+stream_index=0
+key_frame=0
+pkt_pts=667
+pkt_pts_time=0.667000
+pkt_dts=667
+pkt_dts_time=0.667000
+best_effort_timestamp=667
+best_effort_timestamp_time=0.667000
+pkt_duration=166
+pkt_duration_time=0.166000
+pkt_pos=15136
+pkt_size=11
+width=512
+height=256
+pix_fmt=yuv420p
+sample_aspect_ratio=1:1
+pict_type=P
+coded_picture_number=4
+display_picture_number=0
+interlaced_frame=0
+top_field_first=0
+repeat_pict=0
+[/FRAME]
diff --git a/tests/ref/fate/h264-extreme-plane-pred b/tests/ref/fate/h264-extreme-plane-pred
index 96c2bf4..2940ec0 100644
--- a/tests/ref/fate/h264-extreme-plane-pred
+++ b/tests/ref/fate/h264-extreme-plane-pred
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 1e857d2dfeea75297e090ffe9e37a249
 0,          1,          1,        1,   152064, 29d8336b4e9b77298025074dbad641d1
diff --git a/tests/ref/fate/h264-interlace-crop b/tests/ref/fate/h264-interlace-crop
index 81b979c..8dc7308 100644
--- a/tests/ref/fate/h264-interlace-crop
+++ b/tests/ref/fate/h264-interlace-crop
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x360
+#sar 0: 1/1
 0,          0,          0,        1,   345600, 0xa9cb7e5a
 0,          1,          1,        1,   345600, 0x73e47555
 0,          2,          2,        1,   345600, 0x87aac593
diff --git a/tests/ref/fate/h264-invalid-ref-mod b/tests/ref/fate/h264-invalid-ref-mod
new file mode 100644
index 0000000..09271fe
--- /dev/null
+++ b/tests/ref/fate/h264-invalid-ref-mod
@@ -0,0 +1,15 @@
+#tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
+0,          1,          1,        1,  6220800, 0x89daa15e
+0,          2,          2,        1,  6220800, 0xcf52e254
+0,          3,          3,        1,  6220800, 0x91132c13
+0,          4,          4,        1,  6220800, 0x37b8be91
+0,          5,          5,        1,  6220800, 0x2b09bafa
+0,          6,          6,        1,  6220800, 0x06d79d8d
+0,          7,          7,        1,  6220800, 0x8e793c1d
+0,          8,          8,        1,  6220800, 0xea0fd885
+0,          9,          9,        1,  6220800, 0x7786a2ad
+0,         10,         10,        1,  6220800, 0xed4f9dd9
diff --git a/tests/ref/fate/h264-lossless b/tests/ref/fate/h264-lossless
index 44cb13b..9c86db8 100644
--- a/tests/ref/fate/h264-lossless
+++ b/tests/ref/fate/h264-lossless
@@ -1,4 +1,8 @@
 #tb 0: 83333/5000000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   460800, 0x7731dd2f
 0,          2,          2,        1,   460800, 0x944b8c64
 0,          3,          3,        1,   460800, 0xbe833041
diff --git a/tests/ref/fate/h264-reinit-large_420_8-to-small_420_8 b/tests/ref/fate/h264-reinit-large_420_8-to-small_420_8
index 8518855..2c28386 100644
--- a/tests/ref/fate/h264-reinit-large_420_8-to-small_420_8
+++ b/tests/ref/fate/h264-reinit-large_420_8-to-small_420_8
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   608256, 0x65574c43
 0,          1,          1,        1,   608256, 0x5e5a1aa4
 0,          2,          2,        1,   608256, 0xa9a5cbc5
diff --git a/tests/ref/fate/h264-reinit-small_420_8-to-large_444_10 b/tests/ref/fate/h264-reinit-small_420_8-to-large_444_10
index 7e7631a..e727d07 100644
--- a/tests/ref/fate/h264-reinit-small_420_8-to-large_444_10
+++ b/tests/ref/fate/h264-reinit-small_420_8-to-large_444_10
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   608256, 0x27a069a3
 0,          1,          1,        1,   608256, 0x22a5ff96
 0,          2,          2,        1,   608256, 0x29ad753f
diff --git a/tests/ref/fate/h264-reinit-small_420_9-to-small_420_8 b/tests/ref/fate/h264-reinit-small_420_9-to-small_420_8
index 662db29..9b3d114 100644
--- a/tests/ref/fate/h264-reinit-small_420_9-to-small_420_8
+++ b/tests/ref/fate/h264-reinit-small_420_9-to-small_420_8
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   608256, 0xee06377f
 0,          1,          1,        1,   608256, 0x9c22c5ee
 0,          2,          2,        1,   608256, 0x322abee2
diff --git a/tests/ref/fate/h264-reinit-small_422_9-to-small_420_9 b/tests/ref/fate/h264-reinit-small_422_9-to-small_420_9
index b5a9505..15115b6 100644
--- a/tests/ref/fate/h264-reinit-small_422_9-to-small_420_9
+++ b/tests/ref/fate/h264-reinit-small_422_9-to-small_420_9
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 0,          0,          0,        1,   608256, 0x3aef31f3
 0,          1,          1,        1,   608256, 0x05afe4e8
 0,          2,          2,        1,   608256, 0x9d7dc9b1
diff --git a/tests/ref/fate/h264-unescaped-extradata b/tests/ref/fate/h264-unescaped-extradata
new file mode 100644
index 0000000..5e44bc2
--- /dev/null
+++ b/tests/ref/fate/h264-unescaped-extradata
@@ -0,0 +1,15 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x176
+#sar 0: 0/1
+0,          0,          0,        1,    84480, 0x0699eb38
+0,          1,          1,        1,    84480, 0xce902c32
+0,          2,          2,        1,    84480, 0xb6d125f7
+0,          3,          3,        1,    84480, 0x2555e93b
+0,          4,          4,        1,    84480, 0xaea5c08c
+0,          5,          5,        1,    84480, 0x848eb3da
+0,          6,          6,        1,    84480, 0x6cfabe90
+0,          7,          7,        1,    84480, 0xed16cc5e
+0,          8,          8,        1,    84480, 0xda8df8f8
+0,          9,          9,        1,    84480, 0x83fa054b
diff --git a/tests/ref/fate/h264-xavc-4389 b/tests/ref/fate/h264-xavc-4389
new file mode 100644
index 0000000..b1158b8
--- /dev/null
+++ b/tests/ref/fate/h264-xavc-4389
@@ -0,0 +1,22 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
+#tb 1: 1/48000
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 48000
+#channel_layout 1: 4
+0,          0,          0,        1,  8294400, 0x9a02ecf2
+1,          0,          0,     1920,     3840, 0x38074ac8
+0,          1,          1,        1,  8294400, 0x626f870a
+1,       1920,       1920,     1920,     3840, 0xd154829c
+0,          2,          2,        1,  8294400, 0x2d60557c
+1,       3840,       3840,     1920,     3840, 0x52515421
+0,          3,          3,        1,  8294400, 0x9c582956
+1,       5760,       5760,     1920,     3840, 0xdb8869d8
+0,          4,          4,        1,  8294400, 0x1c071f9a
+1,       7680,       7680,     1920,     3840, 0x5b2f7758
+0,          5,          5,        1,  8294400, 0x727f33cc
+1,       9600,       9600,     1920,     3840, 0xd099976a
diff --git a/tests/ref/fate/hap-chunk b/tests/ref/fate/hap-chunk
index 1e7b976..8dd5039 100644
--- a/tests/ref/fate/hap-chunk
+++ b/tests/ref/fate/hap-chunk
@@ -1,2 +1,6 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x096d409e
diff --git a/tests/ref/fate/hap1 b/tests/ref/fate/hap1
index d3bdeae..fcdf985 100644
--- a/tests/ref/fate/hap1
+++ b/tests/ref/fate/hap1
@@ -1,2 +1,6 @@
 #tb 0: 62/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,  1228800, 0x0fa946bc
diff --git a/tests/ref/fate/hap5 b/tests/ref/fate/hap5
index 458981e..f46fe78 100644
--- a/tests/ref/fate/hap5
+++ b/tests/ref/fate/hap5
@@ -1,2 +1,6 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,  1228800, 0xb71ecf93
diff --git a/tests/ref/fate/hapy b/tests/ref/fate/hapy
index e7d7608..61feb2e 100644
--- a/tests/ref/fate/hapy
+++ b/tests/ref/fate/hapy
@@ -1,2 +1,6 @@
 #tb 0: 62/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,  1228800, 0x5993522d
diff --git a/tests/ref/fate/hash b/tests/ref/fate/hash
new file mode 100644
index 0000000..6e5a580
--- /dev/null
+++ b/tests/ref/fate/hash
@@ -0,0 +1,45 @@
+MD5 hex: 3b5d3c7d207e37dceeedd301e35e2e58
+MD5 bin: 0x3b 0x5d 0x3c 0x7d 0x20 0x7e 0x37 0xdc 0xee 0xed 0xd3 0x1 0xe3 0x5e 0x2e 0x58
+MD5 b64: O108fSB+N9zu7dMB414uWA==
+murmur3 hex: 6e484695e1d7b4e37d838791cc263395
+murmur3 bin: 0x6e 0x48 0x46 0x95 0xe1 0xd7 0xb4 0xe3 0x7d 0x83 0x87 0x91 0xcc 0x26 0x33 0x95
+murmur3 b64: bkhGleHXtON9g4eRzCYzlQ==
+RIPEMD128 hex: 082bfa9b829ef3a9e220dcc54e4c6383
+RIPEMD128 bin: 0x8 0x2b 0xfa 0x9b 0x82 0x9e 0xf3 0xa9 0xe2 0x20 0xdc 0xc5 0x4e 0x4c 0x63 0x83
+RIPEMD128 b64: CCv6m4Ke86niINzFTkxjgw==
+RIPEMD160 hex: 9b8ccc2f374ae313a914763cc9cdfb47bfe1c229
+RIPEMD160 bin: 0x9b 0x8c 0xcc 0x2f 0x37 0x4a 0xe3 0x13 0xa9 0x14 0x76 0x3c 0xc9 0xcd 0xfb 0x47 0xbf 0xe1 0xc2 0x29
+RIPEMD160 b64: m4zMLzdK4xOpFHY8yc37R7/hwik=
+RIPEMD256 hex: 26ba693759787f275f47dd5ab16e78c2fcd763b004fd05fc554e354223d6eab5
+RIPEMD256 bin: 0x26 0xba 0x69 0x37 0x59 0x78 0x7f 0x27 0x5f 0x47 0xdd 0x5a 0xb1 0x6e 0x78 0xc2 0xfc 0xd7 0x63 0xb0 0x4 0xfd 0x5 0xfc 0x55 0x4e 0x35 0x42 0x23 0xd6 0xea 0xb5
+RIPEMD256 b64: JrppN1l4fydfR91asW54wvzXY7AE/QX8VU41QiPW6rU=
+RIPEMD320 hex: 409a3111ffd3d4c8058ff5c231401c1d47210a5d22e6c90bf95d45c1c95c528463c69ce4bff3b884
+RIPEMD320 bin: 0x40 0x9a 0x31 0x11 0xff 0xd3 0xd4 0xc8 0x5 0x8f 0xf5 0xc2 0x31 0x40 0x1c 0x1d 0x47 0x21 0xa 0x5d 0x22 0xe6 0xc9 0xb 0xf9 0x5d 0x45 0xc1 0xc9 0x5c 0x52 0x84 0x63 0xc6 0x9c 0xe4 0xbf 0xf3 0xb8 0x84
+RIPEMD320 b64: QJoxEf/T1MgFj/XCMUAcHUchCl0i5skL+V1FwclcUoRjxpzkv/O4hA==
+SHA160 hex: c8d7d0ef0eedfa82d2ea1aa592845b9a6d4b02b7
+SHA160 bin: 0xc8 0xd7 0xd0 0xef 0xe 0xed 0xfa 0x82 0xd2 0xea 0x1a 0xa5 0x92 0x84 0x5b 0x9a 0x6d 0x4b 0x2 0xb7
+SHA160 b64: yNfQ7w7t+oLS6hqlkoRbmm1LArc=
+SHA224 hex: 750d81a39c18d3ce27ff3e5ece30b0088f12d8fd0450fe435326294b
+SHA224 bin: 0x75 0xd 0x81 0xa3 0x9c 0x18 0xd3 0xce 0x27 0xff 0x3e 0x5e 0xce 0x30 0xb0 0x8 0x8f 0x12 0xd8 0xfd 0x4 0x50 0xfe 0x43 0x53 0x26 0x29 0x4b
+SHA224 b64: dQ2Bo5wY084n/z5ezjCwCI8S2P0EUP5DUyYpSw==
+SHA256 hex: f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b
+SHA256 bin: 0xf5 0xa5 0xfd 0x42 0xd1 0x6a 0x20 0x30 0x27 0x98 0xef 0x6e 0xd3 0x9 0x97 0x9b 0x43 0 0x3d 0x23 0x20 0xd9 0xf0 0xe8 0xea 0x98 0x31 0xa9 0x27 0x59 0xfb 0x4b
+SHA256 b64: 9aX9QtFqIDAnmO9u0wmXm0MAPSMg2fDo6pgxqSdZ+0s=
+SHA512/224 hex: 1319d9b322452068e6f43c0ed3da115fbeccc169711dbbaee2846f90
+SHA512/224 bin: 0x13 0x19 0xd9 0xb3 0x22 0x45 0x20 0x68 0xe6 0xf4 0x3c 0xe 0xd3 0xda 0x11 0x5f 0xbe 0xcc 0xc1 0x69 0x71 0x1d 0xbb 0xae 0xe2 0x84 0x6f 0x90
+SHA512/224 b64: ExnZsyJFIGjm9DwO09oRX77MwWlxHbuu4oRvkA==
+SHA512/256 hex: 8aeecfa0b9f2ac7818863b1362241e4f32d06b100ae9d1c0fbcc4ed61b91b17a
+SHA512/256 bin: 0x8a 0xee 0xcf 0xa0 0xb9 0xf2 0xac 0x78 0x18 0x86 0x3b 0x13 0x62 0x24 0x1e 0x4f 0x32 0xd0 0x6b 0x10 0xa 0xe9 0xd1 0xc0 0xfb 0xcc 0x4e 0xd6 0x1b 0x91 0xb1 0x7a
+SHA512/256 b64: iu7PoLnyrHgYhjsTYiQeTzLQaxAK6dHA+8xO1huRsXo=
+SHA384 hex: c516aa8d3b457c636c6826937099c0d23a13f2c3701a388b3c8fe4bc2073281b0c4462610369884c4ababa8e97b6debe
+SHA384 bin: 0xc5 0x16 0xaa 0x8d 0x3b 0x45 0x7c 0x63 0x6c 0x68 0x26 0x93 0x70 0x99 0xc0 0xd2 0x3a 0x13 0xf2 0xc3 0x70 0x1a 0x38 0x8b 0x3c 0x8f 0xe4 0xbc 0x20 0x73 0x28 0x1b 0xc 0x44 0x62 0x61 0x3 0x69 0x88 0x4c 0x4a 0xba 0xba 0x8e 0x97 0xb6 0xde 0xbe
+SHA384 b64: xRaqjTtFfGNsaCaTcJnA0joT8sNwGjiLPI/kvCBzKBsMRGJhA2mITEq6uo6Xtt6+
+SHA512 hex: 7be9fda48f4179e611c698a73cff09faf72869431efee6eaad14de0cb44bbf66503f752b7a8eb17083355f3ce6eb7d2806f236b25af96a24e22b887405c20081
+SHA512 bin: 0x7b 0xe9 0xfd 0xa4 0x8f 0x41 0x79 0xe6 0x11 0xc6 0x98 0xa7 0x3c 0xff 0x9 0xfa 0xf7 0x28 0x69 0x43 0x1e 0xfe 0xe6 0xea 0xad 0x14 0xde 0xc 0xb4 0x4b 0xbf 0x66 0x50 0x3f 0x75 0x2b 0x7a 0x8e 0xb1 0x70 0x83 0x35 0x5f 0x3c 0xe6 0xeb 0x7d 0x28 0x6 0xf2 0x36 0xb2 0x5a 0xf9 0x6a 0x24 0xe2 0x2b 0x88 0x74 0x5 0xc2 0 0x81
+SHA512 b64: e+n9pI9BeeYRxpinPP8J+vcoaUMe/ubqrRTeDLRLv2ZQP3Ureo6xcIM1Xzzm630oBvI2slr5aiTiK4h0BcIAgQ==
+CRC32 hex: 758d6336
+CRC32 bin: 0x75 0x8d 0x63 0x36
+CRC32 b64: dY1jNg==
+adler32 hex: 00400001
+adler32 bin: 0 0x40 0 0x1
+adler32 b64: AEAAAQ==
diff --git a/tests/ref/fate/hevc-conformance-ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_1 b/tests/ref/fate/hevc-conformance-ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_1
index f73569f..953fcf8 100644
--- a/tests/ref/fate/hevc-conformance-ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_1
+++ b/tests/ref/fate/hevc-conformance-ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0xa061c78c
 0,          1,          1,        1,  8294400, 0x60250c76
 0,          2,          2,        1,  8294400, 0x48e3fbdb
diff --git a/tests/ref/fate/hevc-conformance-AMP_A_Samsung_4 b/tests/ref/fate/hevc-conformance-AMP_A_Samsung_4
index 84487a5..e5938e2 100644
--- a/tests/ref/fate/hevc-conformance-AMP_A_Samsung_4
+++ b/tests/ref/fate/hevc-conformance-AMP_A_Samsung_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2560x1600
+#sar 0: 0/1
 0,          0,          0,        1,  6144000, 0xf7da9a00
 0,          1,          1,        1,  6144000, 0xf5cfc76f
 0,          2,          2,        1,  6144000, 0x20663e82
diff --git a/tests/ref/fate/hevc-conformance-AMP_A_Samsung_6 b/tests/ref/fate/hevc-conformance-AMP_A_Samsung_6
index 7693050..c5f59be 100644
--- a/tests/ref/fate/hevc-conformance-AMP_A_Samsung_6
+++ b/tests/ref/fate/hevc-conformance-AMP_A_Samsung_6
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2560x1600
+#sar 0: 0/1
 0,          0,          0,        1,  6144000, 0x6f9dd380
 0,          1,          1,        1,  6144000, 0x3ad765f8
 0,          2,          2,        1,  6144000, 0xe301292d
diff --git a/tests/ref/fate/hevc-conformance-AMP_B_Samsung_4 b/tests/ref/fate/hevc-conformance-AMP_B_Samsung_4
index 034f7b8..10db6c3 100644
--- a/tests/ref/fate/hevc-conformance-AMP_B_Samsung_4
+++ b/tests/ref/fate/hevc-conformance-AMP_B_Samsung_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2560x1600
+#sar 0: 0/1
 0,          0,          0,        1,  6144000, 0xcd32ef33
 0,          1,          1,        1,  6144000, 0x58ce681d
 0,          2,          2,        1,  6144000, 0x77a732b6
diff --git a/tests/ref/fate/hevc-conformance-AMP_B_Samsung_6 b/tests/ref/fate/hevc-conformance-AMP_B_Samsung_6
index fd99c82..518d937 100644
--- a/tests/ref/fate/hevc-conformance-AMP_B_Samsung_6
+++ b/tests/ref/fate/hevc-conformance-AMP_B_Samsung_6
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2560x1600
+#sar 0: 0/1
 0,          0,          0,        1,  6144000, 0x4217e40e
 0,          1,          1,        1,  6144000, 0xafa3a676
 0,          2,          2,        1,  6144000, 0xb8285522
diff --git a/tests/ref/fate/hevc-conformance-AMP_D_Hisilicon b/tests/ref/fate/hevc-conformance-AMP_D_Hisilicon
index 6e17b83..8d4e079 100644
--- a/tests/ref/fate/hevc-conformance-AMP_D_Hisilicon
+++ b/tests/ref/fate/hevc-conformance-AMP_D_Hisilicon
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x1559c293
 0,          1,          1,        1,  3110400, 0xd0802706
 0,          2,          2,        1,  3110400, 0xb48cf229
diff --git a/tests/ref/fate/hevc-conformance-AMP_E_Hisilicon b/tests/ref/fate/hevc-conformance-AMP_E_Hisilicon
index c1b7f2e..075d024 100644
--- a/tests/ref/fate/hevc-conformance-AMP_E_Hisilicon
+++ b/tests/ref/fate/hevc-conformance-AMP_E_Hisilicon
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0xf9342188
 0,          1,          1,        1,  3110400, 0x46638dc4
 0,          2,          2,        1,  3110400, 0x96da436e
diff --git a/tests/ref/fate/hevc-conformance-AMP_F_Hisilicon_3 b/tests/ref/fate/hevc-conformance-AMP_F_Hisilicon_3
index 71ce9c7..4a8849f 100644
--- a/tests/ref/fate/hevc-conformance-AMP_F_Hisilicon_3
+++ b/tests/ref/fate/hevc-conformance-AMP_F_Hisilicon_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0xa5d2b8b0
 0,          1,          1,        1,  3110400, 0x13035cfa
 0,          2,          2,        1,  3110400, 0x96b16f86
diff --git a/tests/ref/fate/hevc-conformance-AMVP_A_MTK_4 b/tests/ref/fate/hevc-conformance-AMVP_A_MTK_4
index 59115fb..f44c174 100644
--- a/tests/ref/fate/hevc-conformance-AMVP_A_MTK_4
+++ b/tests/ref/fate/hevc-conformance-AMVP_A_MTK_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x88619f80
 0,          1,          1,        1,   149760, 0x550bdaf0
 0,          2,          2,        1,   149760, 0xb769fa4c
diff --git a/tests/ref/fate/hevc-conformance-AMVP_B_MTK_4 b/tests/ref/fate/hevc-conformance-AMVP_B_MTK_4
index 1f998c4..3fd21e2 100644
--- a/tests/ref/fate/hevc-conformance-AMVP_B_MTK_4
+++ b/tests/ref/fate/hevc-conformance-AMVP_B_MTK_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xcfffa013
 0,          1,          1,        1,   149760, 0x5166146a
 0,          2,          2,        1,   149760, 0xc3cc318e
diff --git a/tests/ref/fate/hevc-conformance-AMVP_C_Samsung_4 b/tests/ref/fate/hevc-conformance-AMVP_C_Samsung_4
index 16d3446..649be46 100644
--- a/tests/ref/fate/hevc-conformance-AMVP_C_Samsung_4
+++ b/tests/ref/fate/hevc-conformance-AMVP_C_Samsung_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x8087662a
 0,          1,          1,        1,   599040, 0x5278d8db
 0,          2,          2,        1,   599040, 0x73c74090
diff --git a/tests/ref/fate/hevc-conformance-AMVP_C_Samsung_6 b/tests/ref/fate/hevc-conformance-AMVP_C_Samsung_6
index 5ed71e2..36d5577 100644
--- a/tests/ref/fate/hevc-conformance-AMVP_C_Samsung_6
+++ b/tests/ref/fate/hevc-conformance-AMVP_C_Samsung_6
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xd70f52b4
 0,          1,          1,        1,   599040, 0xaf3d1311
 0,          2,          2,        1,   599040, 0xc1b05eef
diff --git a/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1 b/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1
index 2638729..fe89004 100644
--- a/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1
+++ b/tests/ref/fate/hevc-conformance-BUMPING_A_ericsson_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8ce7200b
 0,          1,          1,        1,   149760, 0x73610669
 0,          2,          2,        1,   149760, 0xc01620f4
diff --git a/tests/ref/fate/hevc-conformance-CAINIT_A_SHARP_4 b/tests/ref/fate/hevc-conformance-CAINIT_A_SHARP_4
index 53b621b..2ad98af 100644
--- a/tests/ref/fate/hevc-conformance-CAINIT_A_SHARP_4
+++ b/tests/ref/fate/hevc-conformance-CAINIT_A_SHARP_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x001f0c48
 0,          1,          1,        1,   599040, 0x83120d87
 0,          2,          2,        1,   599040, 0x10c267aa
diff --git a/tests/ref/fate/hevc-conformance-CAINIT_B_SHARP_4 b/tests/ref/fate/hevc-conformance-CAINIT_B_SHARP_4
index 9aeb3b1..2ac9782 100644
--- a/tests/ref/fate/hevc-conformance-CAINIT_B_SHARP_4
+++ b/tests/ref/fate/hevc-conformance-CAINIT_B_SHARP_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x001f0c48
 0,          1,          1,        1,   599040, 0xf8160d82
 0,          2,          2,        1,   599040, 0x5f2060e2
diff --git a/tests/ref/fate/hevc-conformance-CAINIT_C_SHARP_3 b/tests/ref/fate/hevc-conformance-CAINIT_C_SHARP_3
index c891c44..11c98cb 100644
--- a/tests/ref/fate/hevc-conformance-CAINIT_C_SHARP_3
+++ b/tests/ref/fate/hevc-conformance-CAINIT_C_SHARP_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x2b58dee2
 0,          1,          1,        1,   599040, 0x2b58dee2
 0,          2,          2,        1,   599040, 0xcd9295f4
diff --git a/tests/ref/fate/hevc-conformance-CAINIT_D_SHARP_3 b/tests/ref/fate/hevc-conformance-CAINIT_D_SHARP_3
index 0294a7e..ad303fa 100644
--- a/tests/ref/fate/hevc-conformance-CAINIT_D_SHARP_3
+++ b/tests/ref/fate/hevc-conformance-CAINIT_D_SHARP_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x2b58dee2
 0,          1,          1,        1,   599040, 0x2b58dee2
 0,          2,          2,        1,   599040, 0xb055b638
diff --git a/tests/ref/fate/hevc-conformance-CAINIT_E_SHARP_3 b/tests/ref/fate/hevc-conformance-CAINIT_E_SHARP_3
index 430426b..6dfd221 100644
--- a/tests/ref/fate/hevc-conformance-CAINIT_E_SHARP_3
+++ b/tests/ref/fate/hevc-conformance-CAINIT_E_SHARP_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x1cf21d79
 0,          1,          1,        1,   599040, 0x1cf21d79
 0,          2,          2,        1,   599040, 0xb54ee9e0
diff --git a/tests/ref/fate/hevc-conformance-CAINIT_F_SHARP_3 b/tests/ref/fate/hevc-conformance-CAINIT_F_SHARP_3
index aeba53b..cbe498b 100644
--- a/tests/ref/fate/hevc-conformance-CAINIT_F_SHARP_3
+++ b/tests/ref/fate/hevc-conformance-CAINIT_F_SHARP_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x1cf21d79
 0,          1,          1,        1,   599040, 0x1cf21d79
 0,          2,          2,        1,   599040, 0xc182eaa8
diff --git a/tests/ref/fate/hevc-conformance-CAINIT_G_SHARP_3 b/tests/ref/fate/hevc-conformance-CAINIT_G_SHARP_3
index e0501be..e7cc4bb 100644
--- a/tests/ref/fate/hevc-conformance-CAINIT_G_SHARP_3
+++ b/tests/ref/fate/hevc-conformance-CAINIT_G_SHARP_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xd9b73cbe
 0,          1,          1,        1,   599040, 0xd9b73cbe
 0,          2,          2,        1,   599040, 0xe4e5dd7c
diff --git a/tests/ref/fate/hevc-conformance-CAINIT_H_SHARP_3 b/tests/ref/fate/hevc-conformance-CAINIT_H_SHARP_3
index 01ab258..aadc24a 100644
--- a/tests/ref/fate/hevc-conformance-CAINIT_H_SHARP_3
+++ b/tests/ref/fate/hevc-conformance-CAINIT_H_SHARP_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xd9b73cbe
 0,          1,          1,        1,   599040, 0xd9b73cbe
 0,          2,          2,        1,   599040, 0x93a3fabf
diff --git a/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3 b/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3
index afa4854..3adef2f 100644
--- a/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3
+++ b/tests/ref/fate/hevc-conformance-CIP_A_Panasonic_3
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x6e1f16d0
 0,          1,          1,        1,   149760, 0x5be5bde9
diff --git a/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2 b/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2
index 3346e20..8e6c681 100644
--- a/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2
+++ b/tests/ref/fate/hevc-conformance-CIP_C_Panasonic_2
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xcd1019b2
 0,          1,          1,        1,   149760, 0xeb39efeb
diff --git a/tests/ref/fate/hevc-conformance-CONFWIN_A_Sony_1 b/tests/ref/fate/hevc-conformance-CONFWIN_A_Sony_1
index 3cd7a26..1d4af3d 100644
--- a/tests/ref/fate/hevc-conformance-CONFWIN_A_Sony_1
+++ b/tests/ref/fate/hevc-conformance-CONFWIN_A_Sony_1
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 412x236
+#sar 0: 0/1
 0,          0,          0,        1,   145848, 0xad4f07d0
 0,          1,          1,        1,   145848, 0x5825120c
 0,          2,          2,        1,   145848, 0x3eeb0da2
diff --git a/tests/ref/fate/hevc-conformance-DBLK_A_MAIN10_VIXS_3 b/tests/ref/fate/hevc-conformance-DBLK_A_MAIN10_VIXS_3
index 50be4f1..f33b162 100644
--- a/tests/ref/fate/hevc-conformance-DBLK_A_MAIN10_VIXS_3
+++ b/tests/ref/fate/hevc-conformance-DBLK_A_MAIN10_VIXS_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    76032, 0x4313935b
 0,          1,          1,        1,    76032, 0x4c8071b5
 0,          2,          2,        1,    76032, 0x5e627edc
diff --git a/tests/ref/fate/hevc-conformance-DBLK_A_SONY_3 b/tests/ref/fate/hevc-conformance-DBLK_A_SONY_3
index 589cbf3..4571119 100644
--- a/tests/ref/fate/hevc-conformance-DBLK_A_SONY_3
+++ b/tests/ref/fate/hevc-conformance-DBLK_A_SONY_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x154e6dd9
 0,          1,          1,        1,   599040, 0xcce25693
 0,          2,          2,        1,   599040, 0x3dd84e88
diff --git a/tests/ref/fate/hevc-conformance-DBLK_B_SONY_3 b/tests/ref/fate/hevc-conformance-DBLK_B_SONY_3
index 077b38e..eebb5a3 100644
--- a/tests/ref/fate/hevc-conformance-DBLK_B_SONY_3
+++ b/tests/ref/fate/hevc-conformance-DBLK_B_SONY_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xda0cb5d4
 0,          1,          1,        1,   599040, 0x352bc397
 0,          2,          2,        1,   599040, 0x72bc28fe
diff --git a/tests/ref/fate/hevc-conformance-DBLK_C_SONY_3 b/tests/ref/fate/hevc-conformance-DBLK_C_SONY_3
index 823988d..c452c19 100644
--- a/tests/ref/fate/hevc-conformance-DBLK_C_SONY_3
+++ b/tests/ref/fate/hevc-conformance-DBLK_C_SONY_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x57369bf4
 0,          1,          1,        1,   599040, 0x319aab9c
 0,          2,          2,        1,   599040, 0xbc1b7698
diff --git a/tests/ref/fate/hevc-conformance-DBLK_D_VIXS_2 b/tests/ref/fate/hevc-conformance-DBLK_D_VIXS_2
index 2bdc548..4a15b95 100644
--- a/tests/ref/fate/hevc-conformance-DBLK_D_VIXS_2
+++ b/tests/ref/fate/hevc-conformance-DBLK_D_VIXS_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  1382400, 0x6ef5c76e
 0,          1,          1,        1,  1382400, 0x1e1926b1
 0,          2,          2,        1,  1382400, 0x69888786
diff --git a/tests/ref/fate/hevc-conformance-DBLK_E_VIXS_2 b/tests/ref/fate/hevc-conformance-DBLK_E_VIXS_2
index 4c8b07d..8bde7a7 100644
--- a/tests/ref/fate/hevc-conformance-DBLK_E_VIXS_2
+++ b/tests/ref/fate/hevc-conformance-DBLK_E_VIXS_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  1382400, 0xecfdf606
 0,          1,          1,        1,  1382400, 0x0b0382e1
 0,          2,          2,        1,  1382400, 0xbef3afd6
diff --git a/tests/ref/fate/hevc-conformance-DBLK_F_VIXS_2 b/tests/ref/fate/hevc-conformance-DBLK_F_VIXS_2
index 3ff62e5..8794dbb 100644
--- a/tests/ref/fate/hevc-conformance-DBLK_F_VIXS_2
+++ b/tests/ref/fate/hevc-conformance-DBLK_F_VIXS_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  1382400, 0xea27f7bd
 0,          1,          1,        1,  1382400, 0x423e555b
 0,          2,          2,        1,  1382400, 0x87898ae0
diff --git a/tests/ref/fate/hevc-conformance-DBLK_G_VIXS_2 b/tests/ref/fate/hevc-conformance-DBLK_G_VIXS_2
index 4c8b07d..8bde7a7 100644
--- a/tests/ref/fate/hevc-conformance-DBLK_G_VIXS_2
+++ b/tests/ref/fate/hevc-conformance-DBLK_G_VIXS_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  1382400, 0xecfdf606
 0,          1,          1,        1,  1382400, 0x0b0382e1
 0,          2,          2,        1,  1382400, 0xbef3afd6
diff --git a/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4 b/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4
index d2ab0f5..2abd58b 100644
--- a/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4
+++ b/tests/ref/fate/hevc-conformance-DELTAQP_A_BRCM_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1088
+#sar 0: 0/1
 0,          0,          0,        1,  3133440, 0xfbd10331
 0,          1,          1,        1,  3133440, 0x7764ad70
 0,          2,          2,        1,  3133440, 0xaeaf44c1
diff --git a/tests/ref/fate/hevc-conformance-DELTAQP_B_SONY_3 b/tests/ref/fate/hevc-conformance-DELTAQP_B_SONY_3
index 3ba3bb5..b88c9f8 100644
--- a/tests/ref/fate/hevc-conformance-DELTAQP_B_SONY_3
+++ b/tests/ref/fate/hevc-conformance-DELTAQP_B_SONY_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x7ea9597c
 0,          1,          1,        1,   599040, 0x3e7365e4
 0,          2,          2,        1,   599040, 0x4a9149c9
diff --git a/tests/ref/fate/hevc-conformance-DELTAQP_C_SONY_3 b/tests/ref/fate/hevc-conformance-DELTAQP_C_SONY_3
index d616bac..56d4f05 100644
--- a/tests/ref/fate/hevc-conformance-DELTAQP_C_SONY_3
+++ b/tests/ref/fate/hevc-conformance-DELTAQP_C_SONY_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xcb2969c5
 0,          1,          1,        1,   599040, 0xd9825d1f
 0,          2,          2,        1,   599040, 0x5ff4245a
diff --git a/tests/ref/fate/hevc-conformance-DSLICE_A_HHI_5 b/tests/ref/fate/hevc-conformance-DSLICE_A_HHI_5
index 6cd113b..999a76a 100644
--- a/tests/ref/fate/hevc-conformance-DSLICE_A_HHI_5
+++ b/tests/ref/fate/hevc-conformance-DSLICE_A_HHI_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0xdc18cd12
 0,          1,          1,        1,  3110400, 0x42f7020d
 0,          2,          2,        1,  3110400, 0x6ac4421a
diff --git a/tests/ref/fate/hevc-conformance-DSLICE_B_HHI_5 b/tests/ref/fate/hevc-conformance-DSLICE_B_HHI_5
index 7626d76..84a0c79 100644
--- a/tests/ref/fate/hevc-conformance-DSLICE_B_HHI_5
+++ b/tests/ref/fate/hevc-conformance-DSLICE_B_HHI_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x96995c57
 0,          1,          1,        1,  3110400, 0x2924a10f
 0,          2,          2,        1,  3110400, 0x892e146c
diff --git a/tests/ref/fate/hevc-conformance-DSLICE_C_HHI_5 b/tests/ref/fate/hevc-conformance-DSLICE_C_HHI_5
index c4275cb..4b0d108 100644
--- a/tests/ref/fate/hevc-conformance-DSLICE_C_HHI_5
+++ b/tests/ref/fate/hevc-conformance-DSLICE_C_HHI_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x62a2ceab
 0,          1,          1,        1,  3110400, 0x5e4d6adc
 0,          2,          2,        1,  3110400, 0x4ad0955d
diff --git a/tests/ref/fate/hevc-conformance-ENTP_A_Qualcomm_1 b/tests/ref/fate/hevc-conformance-ENTP_A_Qualcomm_1
index 4454bfa..26848c5 100644
--- a/tests/ref/fate/hevc-conformance-ENTP_A_Qualcomm_1
+++ b/tests/ref/fate/hevc-conformance-ENTP_A_Qualcomm_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x26663e50
 0,          1,          1,        1,  3110400, 0x64ae36c1
 0,          2,          2,        1,  3110400, 0x5c72ac0b
diff --git a/tests/ref/fate/hevc-conformance-ENTP_B_Qualcomm_1 b/tests/ref/fate/hevc-conformance-ENTP_B_Qualcomm_1
index 547b590..70f0a6d 100644
--- a/tests/ref/fate/hevc-conformance-ENTP_B_Qualcomm_1
+++ b/tests/ref/fate/hevc-conformance-ENTP_B_Qualcomm_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x7d014690
 0,          1,          1,        1,  3110400, 0xe02cd173
 0,          2,          2,        1,  3110400, 0x2f9794c5
diff --git a/tests/ref/fate/hevc-conformance-ENTP_C_Qualcomm_1 b/tests/ref/fate/hevc-conformance-ENTP_C_Qualcomm_1
index 2c21f35..fd2c47f 100644
--- a/tests/ref/fate/hevc-conformance-ENTP_C_Qualcomm_1
+++ b/tests/ref/fate/hevc-conformance-ENTP_C_Qualcomm_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x4ea3fa57
 0,          1,          1,        1,  3110400, 0xbe33724f
 0,          2,          2,        1,  3110400, 0x9011755e
diff --git a/tests/ref/fate/hevc-conformance-EXT_A_ericsson_4 b/tests/ref/fate/hevc-conformance-EXT_A_ericsson_4
index bf4616a..4e186d6 100644
--- a/tests/ref/fate/hevc-conformance-EXT_A_ericsson_4
+++ b/tests/ref/fate/hevc-conformance-EXT_A_ericsson_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8ce7200b
 0,          1,          1,        1,   149760, 0xf97412f6
 0,          2,          2,        1,   149760, 0x0ea132c4
diff --git a/tests/ref/fate/hevc-conformance-FILLER_A_Sony_1 b/tests/ref/fate/hevc-conformance-FILLER_A_Sony_1
index 809b4cd..08c3375 100644
--- a/tests/ref/fate/hevc-conformance-FILLER_A_Sony_1
+++ b/tests/ref/fate/hevc-conformance-FILLER_A_Sony_1
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x83261e41
 0,          1,          1,        1,   149760, 0xa8c02e8e
 0,          2,          2,        1,   149760, 0xb89d1fa0
diff --git a/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_2 b/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_2
index d887df2..81f25a5 100644
--- a/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_2
+++ b/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_2
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x49bcac59
 0,          1,          1,        1,   149760, 0x30ffadcd
 0,          2,          2,        1,   149760, 0x85ccc14a
diff --git a/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_3 b/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_3
index 7446ae8..534874b 100644
--- a/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_3
+++ b/tests/ref/fate/hevc-conformance-HRD_A_Fujitsu_3
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xa329afaa
 0,          1,          1,        1,   149760, 0xb326c405
 0,          2,          2,        1,   149760, 0x7834b936
diff --git a/tests/ref/fate/hevc-conformance-INITQP_A_Sony_1 b/tests/ref/fate/hevc-conformance-INITQP_A_Sony_1
index e99e389..8cc652f 100644
--- a/tests/ref/fate/hevc-conformance-INITQP_A_Sony_1
+++ b/tests/ref/fate/hevc-conformance-INITQP_A_Sony_1
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x59891e4e
 0,          1,          1,        1,   149760, 0x6c152de8
 0,          2,          2,        1,   149760, 0x6f2c0f37
diff --git a/tests/ref/fate/hevc-conformance-INITQP_B_Sony_1 b/tests/ref/fate/hevc-conformance-INITQP_B_Sony_1
index e00c29f..ca98245 100644
--- a/tests/ref/fate/hevc-conformance-INITQP_B_Sony_1
+++ b/tests/ref/fate/hevc-conformance-INITQP_B_Sony_1
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   299520, 0x5514958a
 0,          1,          1,        1,   299520, 0x06725ede
 0,          2,          2,        1,   299520, 0xa71d1493
diff --git a/tests/ref/fate/hevc-conformance-IPCM_A_RExt_NEC b/tests/ref/fate/hevc-conformance-IPCM_A_RExt_NEC
index d05de74..a0ed530 100644
--- a/tests/ref/fate/hevc-conformance-IPCM_A_RExt_NEC
+++ b/tests/ref/fate/hevc-conformance-IPCM_A_RExt_NEC
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   399360, 0xbac29a51
diff --git a/tests/ref/fate/hevc-conformance-IPCM_B_RExt_NEC b/tests/ref/fate/hevc-conformance-IPCM_B_RExt_NEC
index a01c3b5..94c1247 100644
--- a/tests/ref/fate/hevc-conformance-IPCM_B_RExt_NEC
+++ b/tests/ref/fate/hevc-conformance-IPCM_B_RExt_NEC
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x1f808406
diff --git a/tests/ref/fate/hevc-conformance-IPRED_A_docomo_2 b/tests/ref/fate/hevc-conformance-IPRED_A_docomo_2
index 33878fd..a666524 100644
--- a/tests/ref/fate/hevc-conformance-IPRED_A_docomo_2
+++ b/tests/ref/fate/hevc-conformance-IPRED_A_docomo_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xac658d10
 0,          1,          1,        1,   599040, 0xe3f65389
 0,          2,          2,        1,   599040, 0xfbd644b0
diff --git a/tests/ref/fate/hevc-conformance-IPRED_B_Nokia_3 b/tests/ref/fate/hevc-conformance-IPRED_B_Nokia_3
index 4de7c3c..f3e8d6b 100644
--- a/tests/ref/fate/hevc-conformance-IPRED_B_Nokia_3
+++ b/tests/ref/fate/hevc-conformance-IPRED_B_Nokia_3
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x11ef5ddd
diff --git a/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_3 b/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_3
index 72a12e8..9426a72 100644
--- a/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_3
+++ b/tests/ref/fate/hevc-conformance-IPRED_C_Mitsubishi_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x6b61371d
 0,          1,          1,        1,   599040, 0xd38a2e50
 0,          2,          2,        1,   599040, 0xe8eb34bd
diff --git a/tests/ref/fate/hevc-conformance-LS_A_Orange_2 b/tests/ref/fate/hevc-conformance-LS_A_Orange_2
index 4dd4ad4..f49ae01 100644
--- a/tests/ref/fate/hevc-conformance-LS_A_Orange_2
+++ b/tests/ref/fate/hevc-conformance-LS_A_Orange_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x94a51701
 0,          1,          1,        1,   149760, 0x67c71885
 0,          2,          2,        1,   149760, 0x218f1751
diff --git a/tests/ref/fate/hevc-conformance-LS_B_ORANGE_4 b/tests/ref/fate/hevc-conformance-LS_B_ORANGE_4
index 34dc379..e8d815b 100644
--- a/tests/ref/fate/hevc-conformance-LS_B_ORANGE_4
+++ b/tests/ref/fate/hevc-conformance-LS_B_ORANGE_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x25267761
 0,          1,          1,        1,   599040, 0x4b4b6846
 0,          2,          2,        1,   599040, 0x78e251e8
diff --git a/tests/ref/fate/hevc-conformance-LTRPSPS_A_Qualcomm_1 b/tests/ref/fate/hevc-conformance-LTRPSPS_A_Qualcomm_1
index ddf25c9..3479d62 100644
--- a/tests/ref/fate/hevc-conformance-LTRPSPS_A_Qualcomm_1
+++ b/tests/ref/fate/hevc-conformance-LTRPSPS_A_Qualcomm_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xcfffa013
 0,          1,          1,        1,   149760, 0x8ae80654
 0,          2,          2,        1,   149760, 0xa79915b8
diff --git a/tests/ref/fate/hevc-conformance-MAXBINS_A_TI_4 b/tests/ref/fate/hevc-conformance-MAXBINS_A_TI_4
index 9110cf6..433e215 100644
--- a/tests/ref/fate/hevc-conformance-MAXBINS_A_TI_4
+++ b/tests/ref/fate/hevc-conformance-MAXBINS_A_TI_4
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x9cad90f9
 0,          1,          1,        1,   149760, 0x7deeab1c
diff --git a/tests/ref/fate/hevc-conformance-MAXBINS_B_TI_4 b/tests/ref/fate/hevc-conformance-MAXBINS_B_TI_4
index 5cad961..c18c13a 100644
--- a/tests/ref/fate/hevc-conformance-MAXBINS_B_TI_4
+++ b/tests/ref/fate/hevc-conformance-MAXBINS_B_TI_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x211e8487
 0,          1,          1,        1,   149760, 0xa53b13d8
 0,          2,          2,        1,   149760, 0xb63cc103
diff --git a/tests/ref/fate/hevc-conformance-MAXBINS_C_TI_4 b/tests/ref/fate/hevc-conformance-MAXBINS_C_TI_4
index 2eb3843..db0e3f7 100644
--- a/tests/ref/fate/hevc-conformance-MAXBINS_C_TI_4
+++ b/tests/ref/fate/hevc-conformance-MAXBINS_C_TI_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xa8d7adfa
 0,          1,          1,        1,   149760, 0x76d1ddfe
 0,          2,          2,        1,   149760, 0x56599cae
diff --git a/tests/ref/fate/hevc-conformance-MERGE_A_TI_3 b/tests/ref/fate/hevc-conformance-MERGE_A_TI_3
index 0ab6acc..447fb6b 100644
--- a/tests/ref/fate/hevc-conformance-MERGE_A_TI_3
+++ b/tests/ref/fate/hevc-conformance-MERGE_A_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0x16eb25a8
 0,          2,          2,        1,   149760, 0xcfff29c8
diff --git a/tests/ref/fate/hevc-conformance-MERGE_B_TI_3 b/tests/ref/fate/hevc-conformance-MERGE_B_TI_3
index 2f9395f..dcab89e 100644
--- a/tests/ref/fate/hevc-conformance-MERGE_B_TI_3
+++ b/tests/ref/fate/hevc-conformance-MERGE_B_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0xb5932505
 0,          2,          2,        1,   149760, 0xa5b20e66
diff --git a/tests/ref/fate/hevc-conformance-MERGE_C_TI_3 b/tests/ref/fate/hevc-conformance-MERGE_C_TI_3
index bcc5a1a..703480c 100644
--- a/tests/ref/fate/hevc-conformance-MERGE_C_TI_3
+++ b/tests/ref/fate/hevc-conformance-MERGE_C_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0x88cb1216
 0,          2,          2,        1,   149760, 0x6d1024da
diff --git a/tests/ref/fate/hevc-conformance-MERGE_D_TI_3 b/tests/ref/fate/hevc-conformance-MERGE_D_TI_3
index 7b4df26..c74094b 100644
--- a/tests/ref/fate/hevc-conformance-MERGE_D_TI_3
+++ b/tests/ref/fate/hevc-conformance-MERGE_D_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0x3220183c
 0,          2,          2,        1,   149760, 0x43a21acc
diff --git a/tests/ref/fate/hevc-conformance-MERGE_E_TI_3 b/tests/ref/fate/hevc-conformance-MERGE_E_TI_3
index 8491172..b300f87 100644
--- a/tests/ref/fate/hevc-conformance-MERGE_E_TI_3
+++ b/tests/ref/fate/hevc-conformance-MERGE_E_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0x187419b5
 0,          2,          2,        1,   149760, 0x61100980
diff --git a/tests/ref/fate/hevc-conformance-MERGE_F_MTK_4 b/tests/ref/fate/hevc-conformance-MERGE_F_MTK_4
index 34a0979..005ba59 100644
--- a/tests/ref/fate/hevc-conformance-MERGE_F_MTK_4
+++ b/tests/ref/fate/hevc-conformance-MERGE_F_MTK_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xcfffa013
 0,          1,          1,        1,   149760, 0xec800e71
 0,          2,          2,        1,   149760, 0x9fb014c7
diff --git a/tests/ref/fate/hevc-conformance-MERGE_G_HHI_4 b/tests/ref/fate/hevc-conformance-MERGE_G_HHI_4
index 2e88350..6f66e4b 100644
--- a/tests/ref/fate/hevc-conformance-MERGE_G_HHI_4
+++ b/tests/ref/fate/hevc-conformance-MERGE_G_HHI_4
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x65433cfe
 0,          1,          1,        1,   599040, 0x9309e2c5
diff --git a/tests/ref/fate/hevc-conformance-MVCLIP_A_qualcomm_3 b/tests/ref/fate/hevc-conformance-MVCLIP_A_qualcomm_3
index 6756221..f1cf7e3 100644
--- a/tests/ref/fate/hevc-conformance-MVCLIP_A_qualcomm_3
+++ b/tests/ref/fate/hevc-conformance-MVCLIP_A_qualcomm_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xa5b11720
 0,          1,          1,        1,   149760, 0x42e52c6e
 0,          2,          2,        1,   149760, 0x27b15a30
diff --git a/tests/ref/fate/hevc-conformance-MVDL1ZERO_A_docomo_3 b/tests/ref/fate/hevc-conformance-MVDL1ZERO_A_docomo_3
index 2019db2..789cd7c 100644
--- a/tests/ref/fate/hevc-conformance-MVDL1ZERO_A_docomo_3
+++ b/tests/ref/fate/hevc-conformance-MVDL1ZERO_A_docomo_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x9b27dc7d
 0,          1,          1,        1,   599040, 0x796cdd26
 0,          2,          2,        1,   599040, 0xd3c9dca9
diff --git a/tests/ref/fate/hevc-conformance-MVEDGE_A_qualcomm_3 b/tests/ref/fate/hevc-conformance-MVEDGE_A_qualcomm_3
index 0db06c5..4c676ea 100644
--- a/tests/ref/fate/hevc-conformance-MVEDGE_A_qualcomm_3
+++ b/tests/ref/fate/hevc-conformance-MVEDGE_A_qualcomm_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x1d68213a
 0,          1,          1,        1,   149760, 0x9cc81d30
 0,          2,          2,        1,   149760, 0xa3cf6438
diff --git a/tests/ref/fate/hevc-conformance-Main_422_10_A_RExt_Sony_1 b/tests/ref/fate/hevc-conformance-Main_422_10_A_RExt_Sony_1
index 6c43693..43cfb61 100644
--- a/tests/ref/fate/hevc-conformance-Main_422_10_A_RExt_Sony_1
+++ b/tests/ref/fate/hevc-conformance-Main_422_10_A_RExt_Sony_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0xa189c341
 0,          1,          1,        1,  8294400, 0xefe07f3f
 0,          2,          2,        1,  8294400, 0xf11cd41f
diff --git a/tests/ref/fate/hevc-conformance-Main_422_10_B_RExt_Sony_1 b/tests/ref/fate/hevc-conformance-Main_422_10_B_RExt_Sony_1
index 2267a09..dd95b52 100644
--- a/tests/ref/fate/hevc-conformance-Main_422_10_B_RExt_Sony_1
+++ b/tests/ref/fate/hevc-conformance-Main_422_10_B_RExt_Sony_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2560x1600
+#sar 0: 0/1
 0,          0,          0,        1, 16384000, 0xbf300829
 0,          1,          1,        1, 16384000, 0x7beeab61
 0,          2,          2,        1, 16384000, 0x5e55cd13
diff --git a/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5 b/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5
index fe65880..7ac223e 100644
--- a/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5
+++ b/tests/ref/fate/hevc-conformance-NUT_A_ericsson_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8ce7200b
 0,          1,          1,        1,   149760, 0x73610669
 0,          2,          2,        1,   149760, 0x42942047
diff --git a/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1 b/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1
index 48ca5ad..5de9da9 100644
--- a/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1
+++ b/tests/ref/fate/hevc-conformance-NoOutPrior_A_Qualcomm_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x91d452d5
 0,          1,          1,        1,   599040, 0x1b482509
 0,          2,          2,        1,   599040, 0xbc51425c
diff --git a/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1 b/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1
index 872c5c2..f107e93 100644
--- a/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1
+++ b/tests/ref/fate/hevc-conformance-NoOutPrior_B_Qualcomm_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x91d452d5
 0,          1,          1,        1,   599040, 0x1b482509
 0,          2,          2,        1,   599040, 0xbc51425c
diff --git a/tests/ref/fate/hevc-conformance-OPFLAG_A_Qualcomm_1 b/tests/ref/fate/hevc-conformance-OPFLAG_A_Qualcomm_1
index 74849eb..ed2e9ec 100644
--- a/tests/ref/fate/hevc-conformance-OPFLAG_A_Qualcomm_1
+++ b/tests/ref/fate/hevc-conformance-OPFLAG_A_Qualcomm_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xcfffa013
 0,          1,          1,        1,   149760, 0x8ae80654
 0,          2,          2,        1,   149760, 0xa79915b8
diff --git a/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1 b/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1
index 55e4be0..cc4a22f 100644
--- a/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1
+++ b/tests/ref/fate/hevc-conformance-OPFLAG_B_Qualcomm_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x4246702a
 0,          1,          1,        1,   599040, 0x25e02747
 0,          2,          2,        1,   599040, 0x0894b9de
diff --git a/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1 b/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1
index e45005f..233b042 100644
--- a/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1
+++ b/tests/ref/fate/hevc-conformance-OPFLAG_C_Qualcomm_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x91d452d5
 0,          1,          1,        1,   599040, 0x1b482509
 0,          2,          2,        1,   599040, 0xbc51425c
diff --git a/tests/ref/fate/hevc-conformance-PERSIST_RPARAM_A_RExt_Sony_1 b/tests/ref/fate/hevc-conformance-PERSIST_RPARAM_A_RExt_Sony_1
index 4e49caa..54f4db8 100644
--- a/tests/ref/fate/hevc-conformance-PERSIST_RPARAM_A_RExt_Sony_1
+++ b/tests/ref/fate/hevc-conformance-PERSIST_RPARAM_A_RExt_Sony_1
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 400x384
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0x702f0d67
 0,          1,          1,        1,   921600, 0x99822b52
diff --git a/tests/ref/fate/hevc-conformance-PICSIZE_A_Bossen_1 b/tests/ref/fate/hevc-conformance-PICSIZE_A_Bossen_1
index 4c09ca5..5bb3f53 100644
--- a/tests/ref/fate/hevc-conformance-PICSIZE_A_Bossen_1
+++ b/tests/ref/fate/hevc-conformance-PICSIZE_A_Bossen_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1056x8440
+#sar 0: 0/1
 0,          0,          0,        1, 13368960, 0x830b3a1d
 0,          1,          1,        1, 13368960, 0x120ca009
 0,          2,          2,        1, 13368960, 0xc94e0d86
diff --git a/tests/ref/fate/hevc-conformance-PICSIZE_B_Bossen_1 b/tests/ref/fate/hevc-conformance-PICSIZE_B_Bossen_1
index a3ab7c8..c1c6170 100644
--- a/tests/ref/fate/hevc-conformance-PICSIZE_B_Bossen_1
+++ b/tests/ref/fate/hevc-conformance-PICSIZE_B_Bossen_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8440x1056
+#sar 0: 0/1
 0,          0,          0,        1, 13368960, 0xe1e32c3d
 0,          1,          1,        1, 13368960, 0x75a503d3
 0,          2,          2,        1, 13368960, 0x71f33a0a
diff --git a/tests/ref/fate/hevc-conformance-PICSIZE_C_Bossen_1 b/tests/ref/fate/hevc-conformance-PICSIZE_C_Bossen_1
index 10520d1..f3e2e02 100644
--- a/tests/ref/fate/hevc-conformance-PICSIZE_C_Bossen_1
+++ b/tests/ref/fate/hevc-conformance-PICSIZE_C_Bossen_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 528x4216
+#sar 0: 0/1
 0,          0,          0,        1,  3339072, 0x28be238d
 0,          1,          1,        1,  3339072, 0x43b62aae
 0,          2,          2,        1,  3339072, 0x36259da6
diff --git a/tests/ref/fate/hevc-conformance-PICSIZE_D_Bossen_1 b/tests/ref/fate/hevc-conformance-PICSIZE_D_Bossen_1
index 6f1c4fb..a73a969 100644
--- a/tests/ref/fate/hevc-conformance-PICSIZE_D_Bossen_1
+++ b/tests/ref/fate/hevc-conformance-PICSIZE_D_Bossen_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 4216x528
+#sar 0: 0/1
 0,          0,          0,        1,  3339072, 0xcb16f53e
 0,          1,          1,        1,  3339072, 0x6f1da8ec
 0,          2,          2,        1,  3339072, 0x978dae98
diff --git a/tests/ref/fate/hevc-conformance-PMERGE_A_TI_3 b/tests/ref/fate/hevc-conformance-PMERGE_A_TI_3
index 8491172..b300f87 100644
--- a/tests/ref/fate/hevc-conformance-PMERGE_A_TI_3
+++ b/tests/ref/fate/hevc-conformance-PMERGE_A_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0x187419b5
 0,          2,          2,        1,   149760, 0x61100980
diff --git a/tests/ref/fate/hevc-conformance-PMERGE_B_TI_3 b/tests/ref/fate/hevc-conformance-PMERGE_B_TI_3
index 1f15a02..046c90a 100644
--- a/tests/ref/fate/hevc-conformance-PMERGE_B_TI_3
+++ b/tests/ref/fate/hevc-conformance-PMERGE_B_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0xcebf1b76
 0,          2,          2,        1,   149760, 0x33930fb0
diff --git a/tests/ref/fate/hevc-conformance-PMERGE_C_TI_3 b/tests/ref/fate/hevc-conformance-PMERGE_C_TI_3
index bf474cc..1269e53 100644
--- a/tests/ref/fate/hevc-conformance-PMERGE_C_TI_3
+++ b/tests/ref/fate/hevc-conformance-PMERGE_C_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0x2c271a9b
 0,          2,          2,        1,   149760, 0x53e419f3
diff --git a/tests/ref/fate/hevc-conformance-PMERGE_D_TI_3 b/tests/ref/fate/hevc-conformance-PMERGE_D_TI_3
index 2af0e1f..474626c 100644
--- a/tests/ref/fate/hevc-conformance-PMERGE_D_TI_3
+++ b/tests/ref/fate/hevc-conformance-PMERGE_D_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0xf11a32ce
 0,          2,          2,        1,   149760, 0x0802237c
diff --git a/tests/ref/fate/hevc-conformance-PMERGE_E_TI_3 b/tests/ref/fate/hevc-conformance-PMERGE_E_TI_3
index df97237..e859699 100644
--- a/tests/ref/fate/hevc-conformance-PMERGE_E_TI_3
+++ b/tests/ref/fate/hevc-conformance-PMERGE_E_TI_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0xea7b30bf
 0,          2,          2,        1,   149760, 0x273d092a
diff --git a/tests/ref/fate/hevc-conformance-POC_A_Bossen_3 b/tests/ref/fate/hevc-conformance-POC_A_Bossen_3
index 885d0e4..940eede 100644
--- a/tests/ref/fate/hevc-conformance-POC_A_Bossen_3
+++ b/tests/ref/fate/hevc-conformance-POC_A_Bossen_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xda17acd4
 0,          1,          1,        1,   149760, 0x1691b47f
 0,          2,          2,        1,   149760, 0xeebeac0c
diff --git a/tests/ref/fate/hevc-conformance-PPS_A_qualcomm_7 b/tests/ref/fate/hevc-conformance-PPS_A_qualcomm_7
index ef57f74..de68310 100644
--- a/tests/ref/fate/hevc-conformance-PPS_A_qualcomm_7
+++ b/tests/ref/fate/hevc-conformance-PPS_A_qualcomm_7
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x87159328
 0,          1,          1,        1,   599040, 0x825672ff
 0,          2,          2,        1,   599040, 0x2f4224ff
diff --git a/tests/ref/fate/hevc-conformance-PS_A_VIDYO_3 b/tests/ref/fate/hevc-conformance-PS_A_VIDYO_3
index 8f7e5e6..59b82b7 100644
--- a/tests/ref/fate/hevc-conformance-PS_A_VIDYO_3
+++ b/tests/ref/fate/hevc-conformance-PS_A_VIDYO_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x88619f80
 0,          1,          1,        1,   149760, 0x550bdaf0
 0,          2,          2,        1,   149760, 0x4121f7a2
diff --git a/tests/ref/fate/hevc-conformance-PS_B_VIDYO_3 b/tests/ref/fate/hevc-conformance-PS_B_VIDYO_3
index 8f7e5e6..59b82b7 100644
--- a/tests/ref/fate/hevc-conformance-PS_B_VIDYO_3
+++ b/tests/ref/fate/hevc-conformance-PS_B_VIDYO_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x88619f80
 0,          1,          1,        1,   149760, 0x550bdaf0
 0,          2,          2,        1,   149760, 0x4121f7a2
diff --git a/tests/ref/fate/hevc-conformance-QMATRIX_A_RExt_Sony_1 b/tests/ref/fate/hevc-conformance-QMATRIX_A_RExt_Sony_1
index 63baa95..98d0bb3 100644
--- a/tests/ref/fate/hevc-conformance-QMATRIX_A_RExt_Sony_1
+++ b/tests/ref/fate/hevc-conformance-QMATRIX_A_RExt_Sony_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  2764800, 0xde442361
 0,          1,          1,        1,  2764800, 0x8d482fdf
 0,          2,          2,        1,  2764800, 0x9b431e37
diff --git a/tests/ref/fate/hevc-conformance-RAP_A_docomo_4 b/tests/ref/fate/hevc-conformance-RAP_A_docomo_4
index 268f4cd..51ea08b 100644
--- a/tests/ref/fate/hevc-conformance-RAP_A_docomo_4
+++ b/tests/ref/fate/hevc-conformance-RAP_A_docomo_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x1ae5f13d
 0,          1,          1,        1,   149760, 0x0a6ad0e3
 0,          2,          2,        1,   149760, 0x2415af05
diff --git a/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1 b/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1
index 56f5b44..53e733b 100644
--- a/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1
+++ b/tests/ref/fate/hevc-conformance-RAP_B_Bossen_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xb989ae7a
 0,          1,          1,        1,   149760, 0x4765caed
 0,          2,          2,        1,   149760, 0xd908c148
diff --git a/tests/ref/fate/hevc-conformance-RPLM_A_qualcomm_4 b/tests/ref/fate/hevc-conformance-RPLM_A_qualcomm_4
index 372d120..7cb2bdf 100644
--- a/tests/ref/fate/hevc-conformance-RPLM_A_qualcomm_4
+++ b/tests/ref/fate/hevc-conformance-RPLM_A_qualcomm_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xdb5e3b56
 0,          1,          1,        1,   149760, 0xd5320970
 0,          2,          2,        1,   149760, 0x9387ed18
diff --git a/tests/ref/fate/hevc-conformance-RPLM_B_qualcomm_4 b/tests/ref/fate/hevc-conformance-RPLM_B_qualcomm_4
index a34dcc0..5515c67 100644
--- a/tests/ref/fate/hevc-conformance-RPLM_B_qualcomm_4
+++ b/tests/ref/fate/hevc-conformance-RPLM_B_qualcomm_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x82ff0cca
 0,          1,          1,        1,   149760, 0xcd05ba17
 0,          2,          2,        1,   149760, 0x33a5b924
diff --git a/tests/ref/fate/hevc-conformance-RPS_A_docomo_4 b/tests/ref/fate/hevc-conformance-RPS_A_docomo_4
index e29a74b..5ec1474 100644
--- a/tests/ref/fate/hevc-conformance-RPS_A_docomo_4
+++ b/tests/ref/fate/hevc-conformance-RPS_A_docomo_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0x0bdf13f8
 0,          2,          2,        1,   149760, 0x45e702c7
diff --git a/tests/ref/fate/hevc-conformance-RPS_B_qualcomm_5 b/tests/ref/fate/hevc-conformance-RPS_B_qualcomm_5
index 3b24e75..9c9d894 100644
--- a/tests/ref/fate/hevc-conformance-RPS_B_qualcomm_5
+++ b/tests/ref/fate/hevc-conformance-RPS_B_qualcomm_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xdb5e3b56
 0,          1,          1,        1,   149760, 0xe328e677
 0,          2,          2,        1,   149760, 0x8f18f4c0
diff --git a/tests/ref/fate/hevc-conformance-RPS_C_ericsson_5 b/tests/ref/fate/hevc-conformance-RPS_C_ericsson_5
index e97e7ea..840d816 100644
--- a/tests/ref/fate/hevc-conformance-RPS_C_ericsson_5
+++ b/tests/ref/fate/hevc-conformance-RPS_C_ericsson_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8ce7200b
 0,          1,          1,        1,   149760, 0x85340cda
 0,          2,          2,        1,   149760, 0x16fd1f91
diff --git a/tests/ref/fate/hevc-conformance-RPS_D_ericsson_6 b/tests/ref/fate/hevc-conformance-RPS_D_ericsson_6
index 2851704..9c0fc6c 100644
--- a/tests/ref/fate/hevc-conformance-RPS_D_ericsson_6
+++ b/tests/ref/fate/hevc-conformance-RPS_D_ericsson_6
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8ce7200b
 0,          1,          1,        1,   149760, 0x73610669
 0,          2,          2,        1,   149760, 0xc01620f4
diff --git a/tests/ref/fate/hevc-conformance-RPS_E_qualcomm_5 b/tests/ref/fate/hevc-conformance-RPS_E_qualcomm_5
index 82c25e1..51c6300 100644
--- a/tests/ref/fate/hevc-conformance-RPS_E_qualcomm_5
+++ b/tests/ref/fate/hevc-conformance-RPS_E_qualcomm_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0xd62a31bc
 0,          2,          2,        1,   149760, 0xec822f84
diff --git a/tests/ref/fate/hevc-conformance-RPS_F_docomo_1 b/tests/ref/fate/hevc-conformance-RPS_F_docomo_1
index 06ae9c1..0270e9d 100644
--- a/tests/ref/fate/hevc-conformance-RPS_F_docomo_1
+++ b/tests/ref/fate/hevc-conformance-RPS_F_docomo_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x8edb27d7
 0,          1,          1,        1,   149760, 0x0bdf13f8
 0,          2,          2,        1,   149760, 0x45e702c7
diff --git a/tests/ref/fate/hevc-conformance-RQT_A_HHI_4 b/tests/ref/fate/hevc-conformance-RQT_A_HHI_4
index 5f2b9da..c5a106e 100644
--- a/tests/ref/fate/hevc-conformance-RQT_A_HHI_4
+++ b/tests/ref/fate/hevc-conformance-RQT_A_HHI_4
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x5c0f5423
 0,          1,          1,        1,   599040, 0x3d23be58
diff --git a/tests/ref/fate/hevc-conformance-RQT_B_HHI_4 b/tests/ref/fate/hevc-conformance-RQT_B_HHI_4
index dcf2691..f4f0c26 100644
--- a/tests/ref/fate/hevc-conformance-RQT_B_HHI_4
+++ b/tests/ref/fate/hevc-conformance-RQT_B_HHI_4
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x69854954
 0,          1,          1,        1,   599040, 0x695ebc85
diff --git a/tests/ref/fate/hevc-conformance-RQT_C_HHI_4 b/tests/ref/fate/hevc-conformance-RQT_C_HHI_4
index 2e88350..6f66e4b 100644
--- a/tests/ref/fate/hevc-conformance-RQT_C_HHI_4
+++ b/tests/ref/fate/hevc-conformance-RQT_C_HHI_4
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x65433cfe
 0,          1,          1,        1,   599040, 0x9309e2c5
diff --git a/tests/ref/fate/hevc-conformance-RQT_D_HHI_4 b/tests/ref/fate/hevc-conformance-RQT_D_HHI_4
index 7f73896..016d9eb 100644
--- a/tests/ref/fate/hevc-conformance-RQT_D_HHI_4
+++ b/tests/ref/fate/hevc-conformance-RQT_D_HHI_4
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x88d741bf
 0,          1,          1,        1,   599040, 0xbbd9ab22
diff --git a/tests/ref/fate/hevc-conformance-RQT_E_HHI_4 b/tests/ref/fate/hevc-conformance-RQT_E_HHI_4
index f062318..0cb3767 100644
--- a/tests/ref/fate/hevc-conformance-RQT_E_HHI_4
+++ b/tests/ref/fate/hevc-conformance-RQT_E_HHI_4
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xce2e511d
 0,          1,          1,        1,   599040, 0xe55192d0
diff --git a/tests/ref/fate/hevc-conformance-RQT_F_HHI_4 b/tests/ref/fate/hevc-conformance-RQT_F_HHI_4
index 26bf5ac..f6904c6 100644
--- a/tests/ref/fate/hevc-conformance-RQT_F_HHI_4
+++ b/tests/ref/fate/hevc-conformance-RQT_F_HHI_4
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x65433cfe
 0,          1,          1,        1,   599040, 0x6f99cc5f
diff --git a/tests/ref/fate/hevc-conformance-RQT_G_HHI_4 b/tests/ref/fate/hevc-conformance-RQT_G_HHI_4
index d36ea01..ed67f43 100644
--- a/tests/ref/fate/hevc-conformance-RQT_G_HHI_4
+++ b/tests/ref/fate/hevc-conformance-RQT_G_HHI_4
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x5c0f5423
 0,          1,          1,        1,   599040, 0xe805b181
diff --git a/tests/ref/fate/hevc-conformance-SAO_A_MediaTek_4 b/tests/ref/fate/hevc-conformance-SAO_A_MediaTek_4
index 01226d9..d9066ff 100644
--- a/tests/ref/fate/hevc-conformance-SAO_A_MediaTek_4
+++ b/tests/ref/fate/hevc-conformance-SAO_A_MediaTek_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x304198c2
 0,          1,          1,        1,   149760, 0xe765e30d
 0,          2,          2,        1,   149760, 0x0130a054
diff --git a/tests/ref/fate/hevc-conformance-SAO_A_RExt_MediaTek_1 b/tests/ref/fate/hevc-conformance-SAO_A_RExt_MediaTek_1
index b6ed211..24736a9 100644
--- a/tests/ref/fate/hevc-conformance-SAO_A_RExt_MediaTek_1
+++ b/tests/ref/fate/hevc-conformance-SAO_A_RExt_MediaTek_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2560x1600
+#sar 0: 0/1
 0,          0,          0,        1, 24576000, 0x5b01ceed
 0,          1,          1,        1, 24576000, 0x043fa798
 0,          2,          2,        1, 24576000, 0x9ec62721
diff --git a/tests/ref/fate/hevc-conformance-SAO_B_MediaTek_5 b/tests/ref/fate/hevc-conformance-SAO_B_MediaTek_5
index 9da0268..1e593b1 100644
--- a/tests/ref/fate/hevc-conformance-SAO_B_MediaTek_5
+++ b/tests/ref/fate/hevc-conformance-SAO_B_MediaTek_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xe56f6a5c
 0,          1,          1,        1,   599040, 0x31ec1bb9
 0,          2,          2,        1,   599040, 0xf3ce0311
diff --git a/tests/ref/fate/hevc-conformance-SAO_C_Samsung_4 b/tests/ref/fate/hevc-conformance-SAO_C_Samsung_4
index f87921d..fa4cdfc 100644
--- a/tests/ref/fate/hevc-conformance-SAO_C_Samsung_4
+++ b/tests/ref/fate/hevc-conformance-SAO_C_Samsung_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xf923a1a0
 0,          1,          1,        1,   149760, 0x614d851a
 0,          2,          2,        1,   149760, 0xc3976ce4
diff --git a/tests/ref/fate/hevc-conformance-SAO_C_Samsung_5 b/tests/ref/fate/hevc-conformance-SAO_C_Samsung_5
index 4cb1f78..2344dce 100644
--- a/tests/ref/fate/hevc-conformance-SAO_C_Samsung_5
+++ b/tests/ref/fate/hevc-conformance-SAO_C_Samsung_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x6fe6508f
 0,          1,          1,        1,  3110400, 0xa56a3403
 0,          2,          2,        1,  3110400, 0x45db0973
diff --git a/tests/ref/fate/hevc-conformance-SAO_D_Samsung_4 b/tests/ref/fate/hevc-conformance-SAO_D_Samsung_4
index ce1cefe..df3e417 100644
--- a/tests/ref/fate/hevc-conformance-SAO_D_Samsung_4
+++ b/tests/ref/fate/hevc-conformance-SAO_D_Samsung_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x0d2edbbc
 0,          1,          1,        1,   149760, 0x4830af95
 0,          2,          2,        1,   149760, 0x39e8d3bb
diff --git a/tests/ref/fate/hevc-conformance-SAO_D_Samsung_5 b/tests/ref/fate/hevc-conformance-SAO_D_Samsung_5
index a1884dd..1a51cf3 100644
--- a/tests/ref/fate/hevc-conformance-SAO_D_Samsung_5
+++ b/tests/ref/fate/hevc-conformance-SAO_D_Samsung_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0xcfb2f251
 0,          1,          1,        1,  3110400, 0xc2621936
 0,          2,          2,        1,  3110400, 0x5cb42788
diff --git a/tests/ref/fate/hevc-conformance-SAO_E_Canon_4 b/tests/ref/fate/hevc-conformance-SAO_E_Canon_4
index 92aa7f4..7051b43 100644
--- a/tests/ref/fate/hevc-conformance-SAO_E_Canon_4
+++ b/tests/ref/fate/hevc-conformance-SAO_E_Canon_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x1613b277
 0,          1,          1,        1,   149760, 0xf92d5543
 0,          2,          2,        1,   149760, 0xf119ba8e
diff --git a/tests/ref/fate/hevc-conformance-SAO_F_Canon_3 b/tests/ref/fate/hevc-conformance-SAO_F_Canon_3
index cf24055..613e70d 100644
--- a/tests/ref/fate/hevc-conformance-SAO_F_Canon_3
+++ b/tests/ref/fate/hevc-conformance-SAO_F_Canon_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x92b5107a
 0,          1,          1,        1,   149760, 0x97eb31ef
 0,          2,          2,        1,   149760, 0xeb743e30
diff --git a/tests/ref/fate/hevc-conformance-SAO_G_Canon_3 b/tests/ref/fate/hevc-conformance-SAO_G_Canon_3
index 5ce6772..8f3f9ac 100644
--- a/tests/ref/fate/hevc-conformance-SAO_G_Canon_3
+++ b/tests/ref/fate/hevc-conformance-SAO_G_Canon_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xc4f239e0
 0,          1,          1,        1,   149760, 0xf57a2e44
 0,          2,          2,        1,   149760, 0xbf1e9995
diff --git a/tests/ref/fate/hevc-conformance-SDH_A_Orange_3 b/tests/ref/fate/hevc-conformance-SDH_A_Orange_3
index caf90ee..f3ef192 100644
--- a/tests/ref/fate/hevc-conformance-SDH_A_Orange_3
+++ b/tests/ref/fate/hevc-conformance-SDH_A_Orange_3
@@ -1,3 +1,7 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x0117aa5d
 0,          1,          1,        1,  3110400, 0xa737bc56
diff --git a/tests/ref/fate/hevc-conformance-SLICES_A_Rovi_3 b/tests/ref/fate/hevc-conformance-SLICES_A_Rovi_3
index f884f7f..c45dfd6 100644
--- a/tests/ref/fate/hevc-conformance-SLICES_A_Rovi_3
+++ b/tests/ref/fate/hevc-conformance-SLICES_A_Rovi_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   460800, 0x7f06cb02
 0,          1,          1,        1,   460800, 0x1ad483aa
 0,          2,          2,        1,   460800, 0x1bbbc991
diff --git a/tests/ref/fate/hevc-conformance-SLIST_A_Sony_4 b/tests/ref/fate/hevc-conformance-SLIST_A_Sony_4
index ebb65c3..9e68d0d 100644
--- a/tests/ref/fate/hevc-conformance-SLIST_A_Sony_4
+++ b/tests/ref/fate/hevc-conformance-SLIST_A_Sony_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xbd0eb43e
 0,          1,          1,        1,   599040, 0x4c3a98b5
 0,          2,          2,        1,   599040, 0x105410dc
diff --git a/tests/ref/fate/hevc-conformance-SLIST_B_Sony_8 b/tests/ref/fate/hevc-conformance-SLIST_B_Sony_8
index fc39039..0164b31 100644
--- a/tests/ref/fate/hevc-conformance-SLIST_B_Sony_8
+++ b/tests/ref/fate/hevc-conformance-SLIST_B_Sony_8
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xbd0eb43e
 0,          1,          1,        1,   599040, 0x3ea696c4
 0,          2,          2,        1,   599040, 0x866beffc
diff --git a/tests/ref/fate/hevc-conformance-SLIST_C_Sony_3 b/tests/ref/fate/hevc-conformance-SLIST_C_Sony_3
index 482e56f..b40fa41 100644
--- a/tests/ref/fate/hevc-conformance-SLIST_C_Sony_3
+++ b/tests/ref/fate/hevc-conformance-SLIST_C_Sony_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xc3e98658
 0,          1,          1,        1,   599040, 0x621fa0b7
 0,          2,          2,        1,   599040, 0x53b2e637
diff --git a/tests/ref/fate/hevc-conformance-SLIST_D_Sony_9 b/tests/ref/fate/hevc-conformance-SLIST_D_Sony_9
index 384f81f..d26b75f 100644
--- a/tests/ref/fate/hevc-conformance-SLIST_D_Sony_9
+++ b/tests/ref/fate/hevc-conformance-SLIST_D_Sony_9
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0xf3038515
 0,          1,          1,        1,   599040, 0xb1bc9386
 0,          2,          2,        1,   599040, 0xa069e86f
diff --git a/tests/ref/fate/hevc-conformance-SLPPLP_A_VIDYO_1 b/tests/ref/fate/hevc-conformance-SLPPLP_A_VIDYO_1
index bbb3cfe..6cd9643 100644
--- a/tests/ref/fate/hevc-conformance-SLPPLP_A_VIDYO_1
+++ b/tests/ref/fate/hevc-conformance-SLPPLP_A_VIDYO_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x88619f80
 0,          1,          1,        1,   149760, 0x550bdaf0
 0,          2,          2,        1,   149760, 0x99440a14
diff --git a/tests/ref/fate/hevc-conformance-SLPPLP_A_VIDYO_2 b/tests/ref/fate/hevc-conformance-SLPPLP_A_VIDYO_2
index bbb3cfe..6cd9643 100644
--- a/tests/ref/fate/hevc-conformance-SLPPLP_A_VIDYO_2
+++ b/tests/ref/fate/hevc-conformance-SLPPLP_A_VIDYO_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x88619f80
 0,          1,          1,        1,   149760, 0x550bdaf0
 0,          2,          2,        1,   149760, 0x99440a14
diff --git a/tests/ref/fate/hevc-conformance-STRUCT_A_Samsung_5 b/tests/ref/fate/hevc-conformance-STRUCT_A_Samsung_5
index da5cfa1..0916a9d 100644
--- a/tests/ref/fate/hevc-conformance-STRUCT_A_Samsung_5
+++ b/tests/ref/fate/hevc-conformance-STRUCT_A_Samsung_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x479fa7ca
 0,          1,          1,        1,   149760, 0x761fb3a3
 0,          2,          2,        1,   149760, 0xa0f4cd97
diff --git a/tests/ref/fate/hevc-conformance-STRUCT_B_Samsung_4 b/tests/ref/fate/hevc-conformance-STRUCT_B_Samsung_4
index c03111c..b95c176 100644
--- a/tests/ref/fate/hevc-conformance-STRUCT_B_Samsung_4
+++ b/tests/ref/fate/hevc-conformance-STRUCT_B_Samsung_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x4b489a60
 0,          1,          1,        1,   599040, 0x80369c9a
 0,          2,          2,        1,   599040, 0x33189b1a
diff --git a/tests/ref/fate/hevc-conformance-STRUCT_B_Samsung_6 b/tests/ref/fate/hevc-conformance-STRUCT_B_Samsung_6
index 811c790..6127f76 100644
--- a/tests/ref/fate/hevc-conformance-STRUCT_B_Samsung_6
+++ b/tests/ref/fate/hevc-conformance-STRUCT_B_Samsung_6
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 832x480
+#sar 0: 0/1
 0,          0,          0,        1,   599040, 0x10e6d882
 0,          1,          1,        1,   599040, 0x10e6d882
 0,          2,          2,        1,   599040, 0x10e6d882
diff --git a/tests/ref/fate/hevc-conformance-TILES_A_Cisco_2 b/tests/ref/fate/hevc-conformance-TILES_A_Cisco_2
index 63c9722..8d0b527 100644
--- a/tests/ref/fate/hevc-conformance-TILES_A_Cisco_2
+++ b/tests/ref/fate/hevc-conformance-TILES_A_Cisco_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0xfc052e85
 0,          1,          1,        1,  3110400, 0xfb49bf20
 0,          2,          2,        1,  3110400, 0x549eef2b
diff --git a/tests/ref/fate/hevc-conformance-TILES_B_Cisco_1 b/tests/ref/fate/hevc-conformance-TILES_B_Cisco_1
index 9c37121..b03a9c3 100644
--- a/tests/ref/fate/hevc-conformance-TILES_B_Cisco_1
+++ b/tests/ref/fate/hevc-conformance-TILES_B_Cisco_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  3110400, 0x3471f473
 0,          1,          1,        1,  3110400, 0xb371a3e8
 0,          2,          2,        1,  3110400, 0x6d83c623
diff --git a/tests/ref/fate/hevc-conformance-TMVP_A_MS_3 b/tests/ref/fate/hevc-conformance-TMVP_A_MS_3
index 531370d..d037d38 100644
--- a/tests/ref/fate/hevc-conformance-TMVP_A_MS_3
+++ b/tests/ref/fate/hevc-conformance-TMVP_A_MS_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xdb5e3b56
 0,          1,          1,        1,   149760, 0x6d4418eb
 0,          2,          2,        1,   149760, 0x0473e366
diff --git a/tests/ref/fate/hevc-conformance-TSCL_A_VIDYO_5 b/tests/ref/fate/hevc-conformance-TSCL_A_VIDYO_5
index 84d4219..7f87584 100644
--- a/tests/ref/fate/hevc-conformance-TSCL_A_VIDYO_5
+++ b/tests/ref/fate/hevc-conformance-TSCL_A_VIDYO_5
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xcfffa013
 0,          1,          1,        1,   149760, 0x5166146a
 0,          2,          2,        1,   149760, 0xc3cc318e
diff --git a/tests/ref/fate/hevc-conformance-TSCL_B_VIDYO_4 b/tests/ref/fate/hevc-conformance-TSCL_B_VIDYO_4
index 6ee24ac..c8b1924 100644
--- a/tests/ref/fate/hevc-conformance-TSCL_B_VIDYO_4
+++ b/tests/ref/fate/hevc-conformance-TSCL_B_VIDYO_4
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x88619f80
 0,          1,          1,        1,   149760, 0x550bdaf0
 0,          2,          2,        1,   149760, 0x99440a14
diff --git a/tests/ref/fate/hevc-conformance-TSKIP_A_MS_3 b/tests/ref/fate/hevc-conformance-TSKIP_A_MS_3
index b5eca3c..2f7ee57 100644
--- a/tests/ref/fate/hevc-conformance-TSKIP_A_MS_3
+++ b/tests/ref/fate/hevc-conformance-TSKIP_A_MS_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  1382400, 0xaea37937
 0,          1,          1,        1,  1382400, 0xea5c7b5d
 0,          2,          2,        1,  1382400, 0x4e41e421
diff --git a/tests/ref/fate/hevc-conformance-TUSIZE_A_Samsung_1 b/tests/ref/fate/hevc-conformance-TUSIZE_A_Samsung_1
index 4886a40..f0498e1 100644
--- a/tests/ref/fate/hevc-conformance-TUSIZE_A_Samsung_1
+++ b/tests/ref/fate/hevc-conformance-TUSIZE_A_Samsung_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2560x1600
+#sar 0: 0/1
 0,          0,          0,        1,  6144000, 0x3681421d
 0,          1,          1,        1,  6144000, 0xecf3f343
 0,          2,          2,        1,  6144000, 0x53742db2
diff --git a/tests/ref/fate/hevc-conformance-VPSID_A_VIDYO_1 b/tests/ref/fate/hevc-conformance-VPSID_A_VIDYO_1
index bbb3cfe..6cd9643 100644
--- a/tests/ref/fate/hevc-conformance-VPSID_A_VIDYO_1
+++ b/tests/ref/fate/hevc-conformance-VPSID_A_VIDYO_1
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x88619f80
 0,          1,          1,        1,   149760, 0x550bdaf0
 0,          2,          2,        1,   149760, 0x99440a14
diff --git a/tests/ref/fate/hevc-conformance-VPSID_A_VIDYO_2 b/tests/ref/fate/hevc-conformance-VPSID_A_VIDYO_2
index bbb3cfe..6cd9643 100644
--- a/tests/ref/fate/hevc-conformance-VPSID_A_VIDYO_2
+++ b/tests/ref/fate/hevc-conformance-VPSID_A_VIDYO_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x88619f80
 0,          1,          1,        1,   149760, 0x550bdaf0
 0,          2,          2,        1,   149760, 0x99440a14
diff --git a/tests/ref/fate/hevc-conformance-WPP_A_ericsson_MAIN10_2 b/tests/ref/fate/hevc-conformance-WPP_A_ericsson_MAIN10_2
index fe46c99..8bed654 100644
--- a/tests/ref/fate/hevc-conformance-WPP_A_ericsson_MAIN10_2
+++ b/tests/ref/fate/hevc-conformance-WPP_A_ericsson_MAIN10_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   299520, 0xa3f96d63
 0,          1,          1,        1,   299520, 0x5f788f3f
 0,          2,          2,        1,   299520, 0x41c7d0ae
diff --git a/tests/ref/fate/hevc-conformance-WPP_A_ericsson_MAIN_2 b/tests/ref/fate/hevc-conformance-WPP_A_ericsson_MAIN_2
index 497c802..1be833d 100644
--- a/tests/ref/fate/hevc-conformance-WPP_A_ericsson_MAIN_2
+++ b/tests/ref/fate/hevc-conformance-WPP_A_ericsson_MAIN_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xfbb3d914
 0,          1,          1,        1,   149760, 0xdccd707b
 0,          2,          2,        1,   149760, 0x32008963
diff --git a/tests/ref/fate/hevc-conformance-WPP_B_ericsson_MAIN10_2 b/tests/ref/fate/hevc-conformance-WPP_B_ericsson_MAIN10_2
index d199d38..b146668 100644
--- a/tests/ref/fate/hevc-conformance-WPP_B_ericsson_MAIN10_2
+++ b/tests/ref/fate/hevc-conformance-WPP_B_ericsson_MAIN10_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   299520, 0x66b3cef3
 0,          1,          1,        1,   299520, 0x99df880f
 0,          2,          2,        1,   299520, 0xb4a03801
diff --git a/tests/ref/fate/hevc-conformance-WPP_B_ericsson_MAIN_2 b/tests/ref/fate/hevc-conformance-WPP_B_ericsson_MAIN_2
index bb61b10..9ac63c1 100644
--- a/tests/ref/fate/hevc-conformance-WPP_B_ericsson_MAIN_2
+++ b/tests/ref/fate/hevc-conformance-WPP_B_ericsson_MAIN_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x3772de54
 0,          1,          1,        1,   149760, 0x571d885e
 0,          2,          2,        1,   149760, 0x71576f09
diff --git a/tests/ref/fate/hevc-conformance-WPP_C_ericsson_MAIN10_2 b/tests/ref/fate/hevc-conformance-WPP_C_ericsson_MAIN10_2
index b1e6312..ee951bb 100644
--- a/tests/ref/fate/hevc-conformance-WPP_C_ericsson_MAIN10_2
+++ b/tests/ref/fate/hevc-conformance-WPP_C_ericsson_MAIN10_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   299520, 0xbc71d699
 0,          1,          1,        1,   299520, 0x3207e1f9
 0,          2,          2,        1,   299520, 0xdd2087b5
diff --git a/tests/ref/fate/hevc-conformance-WPP_C_ericsson_MAIN_2 b/tests/ref/fate/hevc-conformance-WPP_C_ericsson_MAIN_2
index 49c4f21..12fbbf6 100644
--- a/tests/ref/fate/hevc-conformance-WPP_C_ericsson_MAIN_2
+++ b/tests/ref/fate/hevc-conformance-WPP_C_ericsson_MAIN_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x0948e521
 0,          1,          1,        1,   149760, 0x37afb384
 0,          2,          2,        1,   149760, 0xe1864c4a
diff --git a/tests/ref/fate/hevc-conformance-WPP_D_ericsson_MAIN10_2 b/tests/ref/fate/hevc-conformance-WPP_D_ericsson_MAIN10_2
index 83cf10c..6fc9a04 100644
--- a/tests/ref/fate/hevc-conformance-WPP_D_ericsson_MAIN10_2
+++ b/tests/ref/fate/hevc-conformance-WPP_D_ericsson_MAIN10_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x240
+#sar 0: 0/1
 0,          0,          0,        1,    46080, 0xc50ed6b4
 0,          1,          1,        1,    46080, 0x2aeac52d
 0,          2,          2,        1,    46080, 0xe3e36cd3
diff --git a/tests/ref/fate/hevc-conformance-WPP_D_ericsson_MAIN_2 b/tests/ref/fate/hevc-conformance-WPP_D_ericsson_MAIN_2
index 6e6fc32..dc469f6 100644
--- a/tests/ref/fate/hevc-conformance-WPP_D_ericsson_MAIN_2
+++ b/tests/ref/fate/hevc-conformance-WPP_D_ericsson_MAIN_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x240
+#sar 0: 0/1
 0,          0,          0,        1,    23040, 0x6977dbca
 0,          1,          1,        1,    23040, 0xd9bfcb5c
 0,          2,          2,        1,    23040, 0xbdd5a346
diff --git a/tests/ref/fate/hevc-conformance-WPP_E_ericsson_MAIN10_2 b/tests/ref/fate/hevc-conformance-WPP_E_ericsson_MAIN10_2
index dbf6f78..0dd096c 100644
--- a/tests/ref/fate/hevc-conformance-WPP_E_ericsson_MAIN10_2
+++ b/tests/ref/fate/hevc-conformance-WPP_E_ericsson_MAIN10_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x240
+#sar 0: 0/1
 0,          0,          0,        1,    92160, 0x591c992e
 0,          1,          1,        1,    92160, 0xe7a8cd8b
 0,          2,          2,        1,    92160, 0x2e7528bb
diff --git a/tests/ref/fate/hevc-conformance-WPP_E_ericsson_MAIN_2 b/tests/ref/fate/hevc-conformance-WPP_E_ericsson_MAIN_2
index ac478c6..e284c17 100644
--- a/tests/ref/fate/hevc-conformance-WPP_E_ericsson_MAIN_2
+++ b/tests/ref/fate/hevc-conformance-WPP_E_ericsson_MAIN_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x240
+#sar 0: 0/1
 0,          0,          0,        1,    46080, 0xcd234724
 0,          1,          1,        1,    46080, 0x66649579
 0,          2,          2,        1,    46080, 0x4317d38d
diff --git a/tests/ref/fate/hevc-conformance-WPP_F_ericsson_MAIN10_2 b/tests/ref/fate/hevc-conformance-WPP_F_ericsson_MAIN10_2
index 2f103b7..aa8452d 100644
--- a/tests/ref/fate/hevc-conformance-WPP_F_ericsson_MAIN10_2
+++ b/tests/ref/fate/hevc-conformance-WPP_F_ericsson_MAIN10_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x240
+#sar 0: 0/1
 0,          0,          0,        1,   138240, 0x99f196ae
 0,          1,          1,        1,   138240, 0x45f407de
 0,          2,          2,        1,   138240, 0xdaef815b
diff --git a/tests/ref/fate/hevc-conformance-WPP_F_ericsson_MAIN_2 b/tests/ref/fate/hevc-conformance-WPP_F_ericsson_MAIN_2
index 6256d96..1654ec1 100644
--- a/tests/ref/fate/hevc-conformance-WPP_F_ericsson_MAIN_2
+++ b/tests/ref/fate/hevc-conformance-WPP_F_ericsson_MAIN_2
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x240
+#sar 0: 0/1
 0,          0,          0,        1,    69120, 0x28326a13
 0,          1,          1,        1,    69120, 0x1f41a4a7
 0,          2,          2,        1,    69120, 0x803ceeb4
diff --git a/tests/ref/fate/hevc-conformance-WP_A_MAIN10_Toshiba_3 b/tests/ref/fate/hevc-conformance-WP_A_MAIN10_Toshiba_3
index b2dadba..4ca7eb2 100644
--- a/tests/ref/fate/hevc-conformance-WP_A_MAIN10_Toshiba_3
+++ b/tests/ref/fate/hevc-conformance-WP_A_MAIN10_Toshiba_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   299520, 0x7750edc7
 0,          1,          1,        1,   299520, 0x97fb359b
 0,          2,          2,        1,   299520, 0x89ac22bc
diff --git a/tests/ref/fate/hevc-conformance-WP_A_Toshiba_3 b/tests/ref/fate/hevc-conformance-WP_A_Toshiba_3
index a8c5df3..88f319c 100644
--- a/tests/ref/fate/hevc-conformance-WP_A_Toshiba_3
+++ b/tests/ref/fate/hevc-conformance-WP_A_Toshiba_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xf4bafc83
 0,          1,          1,        1,   149760, 0x611ca492
 0,          2,          2,        1,   149760, 0x8fa9bbb1
diff --git a/tests/ref/fate/hevc-conformance-WP_B_Toshiba_3 b/tests/ref/fate/hevc-conformance-WP_B_Toshiba_3
index 7dbc72b..ed69880 100644
--- a/tests/ref/fate/hevc-conformance-WP_B_Toshiba_3
+++ b/tests/ref/fate/hevc-conformance-WP_B_Toshiba_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xd8bf0c39
 0,          1,          1,        1,   149760, 0xad390a29
 0,          2,          2,        1,   149760, 0x0d310906
diff --git a/tests/ref/fate/hevc-conformance-WP_MAIN10_B_Toshiba_3 b/tests/ref/fate/hevc-conformance-WP_MAIN10_B_Toshiba_3
index 332c7df..0277764 100644
--- a/tests/ref/fate/hevc-conformance-WP_MAIN10_B_Toshiba_3
+++ b/tests/ref/fate/hevc-conformance-WP_MAIN10_B_Toshiba_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   299520, 0x6ecba46b
 0,          1,          1,        1,   299520, 0x54e6ef0a
 0,          2,          2,        1,   299520, 0x7a4d46c5
diff --git a/tests/ref/fate/hevc-conformance-cip_B_NEC_3 b/tests/ref/fate/hevc-conformance-cip_B_NEC_3
index 016f0f1..c8dfedf 100644
--- a/tests/ref/fate/hevc-conformance-cip_B_NEC_3
+++ b/tests/ref/fate/hevc-conformance-cip_B_NEC_3
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xcbda260f
 0,          1,          1,        1,   149760, 0xbd8d32a9
 0,          2,          2,        1,   149760, 0x39562006
diff --git a/tests/ref/fate/hevc-conformance-ipcm_A_NEC_3 b/tests/ref/fate/hevc-conformance-ipcm_A_NEC_3
index 145f590..4d34d32 100644
--- a/tests/ref/fate/hevc-conformance-ipcm_A_NEC_3
+++ b/tests/ref/fate/hevc-conformance-ipcm_A_NEC_3
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0x2356474c
diff --git a/tests/ref/fate/hevc-conformance-ipcm_B_NEC_3 b/tests/ref/fate/hevc-conformance-ipcm_B_NEC_3
index d917cbc..0dd1379 100644
--- a/tests/ref/fate/hevc-conformance-ipcm_B_NEC_3
+++ b/tests/ref/fate/hevc-conformance-ipcm_B_NEC_3
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xc80d43f8
diff --git a/tests/ref/fate/hevc-conformance-ipcm_C_NEC_3 b/tests/ref/fate/hevc-conformance-ipcm_C_NEC_3
index 6c89cea..4bc3fc6 100644
--- a/tests/ref/fate/hevc-conformance-ipcm_C_NEC_3
+++ b/tests/ref/fate/hevc-conformance-ipcm_C_NEC_3
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xb92d38ee
diff --git a/tests/ref/fate/hevc-conformance-ipcm_D_NEC_3 b/tests/ref/fate/hevc-conformance-ipcm_D_NEC_3
index 2ccff05..23d7aaa 100644
--- a/tests/ref/fate/hevc-conformance-ipcm_D_NEC_3
+++ b/tests/ref/fate/hevc-conformance-ipcm_D_NEC_3
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xa24d17f8
diff --git a/tests/ref/fate/hevc-conformance-ipcm_E_NEC_2 b/tests/ref/fate/hevc-conformance-ipcm_E_NEC_2
index 794c4ac..3f7d780 100644
--- a/tests/ref/fate/hevc-conformance-ipcm_E_NEC_2
+++ b/tests/ref/fate/hevc-conformance-ipcm_E_NEC_2
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 416x240
+#sar 0: 0/1
 0,          0,          0,        1,   149760, 0xf4582514
diff --git a/tests/ref/fate/hevc-paramchange-yuv420p-yuv420p10 b/tests/ref/fate/hevc-paramchange-yuv420p-yuv420p10
index f3cd550..73bf868 100644
--- a/tests/ref/fate/hevc-paramchange-yuv420p-yuv420p10
+++ b/tests/ref/fate/hevc-paramchange-yuv420p-yuv420p10
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1056x8440
+#sar 0: 0/1
 0,          0,          0,        1, 13368960, 0x830b3a1d
 0,          1,          1,        1, 13368960, 0x120ca009
 0,          2,          2,        1, 13368960, 0xc94e0d86
diff --git a/tests/ref/fate/id-cin-video b/tests/ref/fate/id-cin-video
index f55544f..469e239 100644
--- a/tests/ref/fate/id-cin-video
+++ b/tests/ref/fate/id-cin-video
@@ -1,5 +1,13 @@
 #tb 0: 1/14
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 #tb 1: 1/22050
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 22050
+#channel_layout 1: 3
 0,          0,          0,        1,   230400, 0x00000000
 1,          0,          0,     1575,     6300, 0xdd759df8
 0,          1,          1,        1,   230400, 0x3a3486b4
diff --git a/tests/ref/fate/iff-byterun1 b/tests/ref/fate/iff-byterun1
index 6f80c72..8e6f949 100644
--- a/tests/ref/fate/iff-byterun1
+++ b/tests/ref/fate/iff-byterun1
@@ -1,2 +1,6 @@
 #tb 0: 1/90000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 5/6
 0,          0,          0,        0,   230400, 0x35e51c62
diff --git a/tests/ref/fate/iff-ilbm b/tests/ref/fate/iff-ilbm
index a801aff..38c43eb 100644
--- a/tests/ref/fate/iff-ilbm
+++ b/tests/ref/fate/iff-ilbm
@@ -1,2 +1,6 @@
 #tb 0: 1/90000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        0,   230400, 0x0929e342
diff --git a/tests/ref/fate/indeo2 b/tests/ref/fate/indeo2
deleted file mode 100644
index 9f80f35..0000000
--- a/tests/ref/fate/indeo2
+++ /dev/null
@@ -1,131 +0,0 @@
-#tb 0: 66667/1000000
-0,          0,          0,        1,    21600, 0x57a2ba42
-0,          1,          1,        1,    21600, 0x61e09615
-0,          2,          2,        1,    21600, 0x826e4e63
-0,          3,          3,        1,    21600, 0x107716ec
-0,          4,          4,        1,    21600, 0xb35ce1f4
-0,          5,          5,        1,    21600, 0x12cab085
-0,          6,          6,        1,    21600, 0x2f917f69
-0,          7,          7,        1,    21600, 0x25aa3d6e
-0,          8,          8,        1,    21600, 0xab1bfbed
-0,          9,          9,        1,    21600, 0x9936dff9
-0,         10,         10,        1,    21600, 0xc23cd8e5
-0,         11,         11,        1,    21600, 0xa7ebbcaa
-0,         12,         12,        1,    21600, 0xd4dda045
-0,         13,         13,        1,    21600, 0xcbce6d7d
-0,         14,         14,        1,    21600, 0x3cf35baf
-0,         15,         15,        1,    21600, 0x16de6008
-0,         16,         16,        1,    21600, 0x49d41acf
-0,         17,         17,        1,    21600, 0x8c630034
-0,         18,         18,        1,    21600, 0x0b310296
-0,         19,         19,        1,    21600, 0x4887067d
-0,         20,         20,        1,    21600, 0x1219f29e
-0,         21,         21,        1,    21600, 0x3f3fc0c8
-0,         22,         22,        1,    21600, 0x1bd1d0fc
-0,         23,         23,        1,    21600, 0x913f9d4c
-0,         24,         24,        1,    21600, 0x69e9a6b4
-0,         25,         25,        1,    21600, 0xcc2e917f
-0,         26,         26,        1,    21600, 0xf6967e30
-0,         27,         27,        1,    21600, 0xdf816593
-0,         28,         28,        1,    21600, 0xfd945b75
-0,         29,         29,        1,    21600, 0x7d7e0224
-0,         30,         30,        1,    21600, 0x7246f584
-0,         31,         31,        1,    21600, 0x07b7ce82
-0,         32,         32,        1,    21600, 0xee16c291
-0,         33,         33,        1,    21600, 0xf4efb53a
-0,         34,         34,        1,    21600, 0x2e73a208
-0,         35,         35,        1,    21600, 0x1c2b6068
-0,         36,         36,        1,    21600, 0x004250de
-0,         37,         37,        1,    21600, 0x61d957d9
-0,         38,         38,        1,    21600, 0x8b5d2cb0
-0,         39,         39,        1,    21600, 0xc0a91fbc
-0,         40,         40,        1,    21600, 0xa38108fc
-0,         41,         41,        1,    21600, 0x551f03b9
-0,         42,         42,        1,    21600, 0x93def5ca
-0,         43,         43,        1,    21600, 0xe8ecf8bb
-0,         44,         44,        1,    21600, 0x4c04fbb0
-0,         45,         45,        1,    21600, 0x0e41dae4
-0,         46,         46,        1,    21600, 0xca9fb0df
-0,         47,         47,        1,    21600, 0xb123af19
-0,         48,         48,        1,    21600, 0xfd59be7a
-0,         49,         49,        1,    21600, 0x2c88b7a6
-0,         50,         50,        1,    21600, 0x64cc9a1f
-0,         51,         51,        1,    21600, 0x73d6a9ba
-0,         52,         52,        1,    21600, 0x79198a11
-0,         53,         53,        1,    21600, 0x0d4a8610
-0,         54,         54,        1,    21600, 0x352e71bc
-0,         55,         55,        1,    21600, 0x08aa627e
-0,         56,         56,        1,    21600, 0xbee36e45
-0,         57,         57,        1,    21600, 0x30de5c1b
-0,         58,         58,        1,    21600, 0x21d75484
-0,         59,         59,        1,    21600, 0xe0e91d52
-0,         60,         60,        1,    21600, 0x678c2ebb
-0,         61,         61,        1,    21600, 0x2080397b
-0,         62,         62,        1,    21600, 0x7dbc1333
-0,         63,         63,        1,    21600, 0x9c730ad0
-0,         64,         64,        1,    21600, 0x4da50f55
-0,         65,         65,        1,    21600, 0xdde5eaa7
-0,         66,         66,        1,    21600, 0x949ed4fa
-0,         67,         67,        1,    21600, 0x5d63bc54
-0,         68,         68,        1,    21600, 0xc5dcba4f
-0,         69,         69,        1,    21600, 0xd68caee1
-0,         70,         70,        1,    21600, 0xf7409fc9
-0,         71,         71,        1,    21600, 0x6b0ca3e5
-0,         72,         72,        1,    21600, 0xd133a108
-0,         73,         73,        1,    21600, 0xf2687b81
-0,         74,         74,        1,    21600, 0x6e94645d
-0,         75,         75,        1,    21600, 0xff7e7524
-0,         76,         76,        1,    21600, 0x8c7255dd
-0,         77,         77,        1,    21600, 0x84e979cf
-0,         78,         78,        1,    21600, 0xaa4e7127
-0,         79,         79,        1,    21600, 0x0b56708c
-0,         80,         80,        1,    21600, 0x38f086c4
-0,         81,         81,        1,    21600, 0x6a7086f6
-0,         82,         82,        1,    21600, 0x57a3619d
-0,         83,         83,        1,    21600, 0xee27639a
-0,         84,         84,        1,    21600, 0x754b7ec6
-0,         85,         85,        1,    21600, 0x2f7b428c
-0,         86,         86,        1,    21600, 0x0dc94603
-0,         87,         87,        1,    21600, 0xeede54d8
-0,         88,         88,        1,    21600, 0x587b4725
-0,         89,         89,        1,    21600, 0xe7c72c7a
-0,         90,         90,        1,    21600, 0x523949cb
-0,         91,         91,        1,    21600, 0xeade5385
-0,         92,         92,        1,    21600, 0x1a8f45c8
-0,         93,         93,        1,    21600, 0x814a393c
-0,         94,         94,        1,    21600, 0xe7b34887
-0,         95,         95,        1,    21600, 0x8eef3f5f
-0,         96,         96,        1,    21600, 0x56f12f08
-0,         97,         97,        1,    21600, 0xb2d02448
-0,         98,         98,        1,    21600, 0xb7d936db
-0,         99,         99,        1,    21600, 0x45f726ab
-0,        100,        100,        1,    21600, 0x6012404d
-0,        101,        101,        1,    21600, 0x273c254e
-0,        102,        102,        1,    21600, 0x38e82c19
-0,        103,        103,        1,    21600, 0x73653274
-0,        104,        104,        1,    21600, 0x2ff63b0c
-0,        105,        105,        1,    21600, 0x96d03611
-0,        106,        106,        1,    21600, 0xee8c29d7
-0,        107,        107,        1,    21600, 0xac043199
-0,        108,        108,        1,    21600, 0xd2c741a7
-0,        109,        109,        1,    21600, 0xdc7b2b81
-0,        110,        110,        1,    21600, 0x376f438f
-0,        111,        111,        1,    21600, 0x55442ff7
-0,        112,        112,        1,    21600, 0x653b1472
-0,        113,        113,        1,    21600, 0xc4293779
-0,        114,        114,        1,    21600, 0xc6553740
-0,        115,        115,        1,    21600, 0xcf441053
-0,        116,        116,        1,    21600, 0xb1531bce
-0,        117,        117,        1,    21600, 0x145323b3
-0,        118,        118,        1,    21600, 0x916c2e9e
-0,        119,        119,        1,    21600, 0xb89bfecc
-0,        120,        120,        1,    21600, 0x8e2415b9
-0,        121,        121,        1,    21600, 0x5af23021
-0,        122,        122,        1,    21600, 0x53e81c10
-0,        123,        123,        1,    21600, 0xf7f82a6f
-0,        124,        124,        1,    21600, 0x851121a2
-0,        125,        125,        1,    21600, 0xa8432bd2
-0,        126,        126,        1,    21600, 0x1a381799
-0,        127,        127,        1,    21600, 0xbb761384
-0,        128,        128,        1,    21600, 0xc8f328d5
-0,        129,        129,        1,    21600, 0xb3742e8a
diff --git a/tests/ref/fate/indeo2-delta b/tests/ref/fate/indeo2-delta
new file mode 100644
index 0000000..05a01fd
--- /dev/null
+++ b/tests/ref/fate/indeo2-delta
@@ -0,0 +1,119 @@
+#tb 0: 16567/250000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
+0,          0,          0,        1,    21600, 0xa3e914dd
+0,          1,          1,        1,    21600, 0x367eb420
+0,          2,          2,        1,    21600, 0x527488e2
+0,          3,          3,        1,    21600, 0x5e704dcb
+0,          4,          4,        1,    21600, 0xfbfb35d4
+0,          5,          5,        1,    21600, 0xf6e168de
+0,          6,          6,        1,    21600, 0x0b589818
+0,          7,          7,        1,    21600, 0xc67b2dbd
+0,          8,          8,        1,    21600, 0x002f4994
+0,          9,          9,        1,    21600, 0xe3a476f2
+0,         10,         10,        1,    21600, 0xbc5f0f39
+0,         11,         11,        1,    21600, 0xef095e3a
+0,         12,         12,        1,    21600, 0x6bb4f515
+0,         13,         13,        1,    21600, 0x1be1f0fa
+0,         14,         14,        1,    21600, 0x0d855464
+0,         15,         15,        1,    21600, 0x6711b47d
+0,         16,         16,        1,    21600, 0x14cb2640
+0,         17,         17,        1,    21600, 0x5b794027
+0,         18,         18,        1,    21600, 0xf8cfab3c
+0,         19,         19,        1,    21600, 0xe639b0c2
+0,         20,         20,        1,    21600, 0x403b3d7b
+0,         21,         21,        1,    21600, 0x364cbb6f
+0,         22,         22,        1,    21600, 0xadff6c72
+0,         23,         23,        1,    21600, 0x76c85b52
+0,         24,         24,        1,    21600, 0xbe85ec80
+0,         25,         25,        1,    21600, 0x1e9f9e50
+0,         26,         26,        1,    21600, 0xbd31bd82
+0,         27,         27,        1,    21600, 0x4445a12a
+0,         28,         28,        1,    21600, 0x08f25888
+0,         29,         29,        1,    21600, 0x73d45696
+0,         30,         30,        1,    21600, 0xbc681a10
+0,         31,         31,        1,    21600, 0x03f502be
+0,         32,         32,        1,    21600, 0x9206a757
+0,         33,         33,        1,    21600, 0x3ed5e1be
+0,         34,         34,        1,    21600, 0x76b636a9
+0,         35,         35,        1,    21600, 0x7d40ccb0
+0,         36,         36,        1,    21600, 0xa2955499
+0,         37,         37,        1,    21600, 0xf4b20c86
+0,         38,         38,        1,    21600, 0xe497d681
+0,         39,         39,        1,    21600, 0x831ef973
+0,         40,         40,        1,    21600, 0x43aa78e6
+0,         41,         41,        1,    21600, 0x26e4bdb6
+0,         42,         42,        1,    21600, 0xd04e9feb
+0,         43,         43,        1,    21600, 0x08ef4b58
+0,         44,         44,        1,    21600, 0x30b84cc3
+0,         45,         45,        1,    21600, 0x04e1dec0
+0,         46,         46,        1,    21600, 0xed4f24d5
+0,         47,         47,        1,    21600, 0xcc9f8d4c
+0,         48,         48,        1,    21600, 0x402ff69a
+0,         49,         49,        1,    21600, 0xd77a4e7b
+0,         50,         50,        1,    21600, 0xe614de71
+0,         51,         51,        1,    21600, 0x18daccbd
+0,         52,         52,        1,    21600, 0x87e896d1
+0,         53,         53,        1,    21600, 0x51d76264
+0,         54,         54,        1,    21600, 0x9b910304
+0,         55,         55,        1,    21600, 0xd3a7aa30
+0,         56,         56,        1,    21600, 0x40e4e926
+0,         57,         57,        1,    21600, 0x9bb5d703
+0,         58,         58,        1,    21600, 0x63fb1ac0
+0,         59,         59,        1,    21600, 0x1b9d851e
+0,         60,         60,        1,    21600, 0x36e4c0e6
+0,         61,         61,        1,    21600, 0x1f14b386
+0,         62,         62,        1,    21600, 0x01016e93
+0,         63,         63,        1,    21600, 0x8f192cc7
+0,         64,         64,        1,    21600, 0xa9caaeb0
+0,         65,         65,        1,    21600, 0xe9948a3d
+0,         66,         66,        1,    21600, 0xe870fa18
+0,         67,         67,        1,    21600, 0xc083eff5
+0,         68,         68,        1,    21600, 0x2f070225
+0,         69,         69,        1,    21600, 0x89cbd954
+0,         70,         70,        1,    21600, 0x448c4fbb
+0,         71,         71,        1,    21600, 0xe1ecfdbe
+0,         72,         72,        1,    21600, 0x20b3749b
+0,         73,         73,        1,    21600, 0x8ba8a3c6
+0,         74,         74,        1,    21600, 0x90c06421
+0,         75,         75,        1,    21600, 0x0e6bd5fc
+0,         76,         76,        1,    21600, 0x194425aa
+0,         77,         77,        1,    21600, 0x4038043a
+0,         78,         78,        1,    21600, 0x21545ede
+0,         79,         79,        1,    21600, 0x2ade8d52
+0,         80,         80,        1,    21600, 0xf504ad7e
+0,         81,         81,        1,    21600, 0xc58fcf10
+0,         82,         82,        1,    21600, 0x4b0af230
+0,         83,         83,        1,    21600, 0x3ff76b0b
+0,         84,         84,        1,    21600, 0x6d051bee
+0,         85,         85,        1,    21600, 0xc5d59208
+0,         86,         86,        1,    21600, 0xed5f81cf
+0,         87,         87,        1,    21600, 0x2c9976f9
+0,         88,         88,        1,    21600, 0xdd5b5f55
+0,         89,         89,        1,    21600, 0xcec73bc3
+0,         90,         90,        1,    21600, 0x46033a02
+0,         91,         91,        1,    21600, 0x00c6aade
+0,         92,         92,        1,    21600, 0x336049b3
+0,         93,         93,        1,    21600, 0xe1939479
+0,         94,         94,        1,    21600, 0xc77ca7e7
+0,         95,         95,        1,    21600, 0x40153489
+0,         96,         96,        1,    21600, 0x33253501
+0,         97,         97,        1,    21600, 0x10a321c1
+0,         98,         98,        1,    21600, 0x8720db67
+0,         99,         99,        1,    21600, 0x185b772e
+0,        100,        100,        1,    21600, 0xf4ce1986
+0,        101,        101,        1,    21600, 0x7234af91
+0,        102,        102,        1,    21600, 0x1cb75367
+0,        103,        103,        1,    21600, 0x7bc29377
+0,        104,        104,        1,    21600, 0xc3c047a1
+0,        105,        105,        1,    21600, 0xe6fb938c
+0,        106,        106,        1,    21600, 0x97ca5ab5
+0,        107,        107,        1,    21600, 0x7a9fe9bf
+0,        108,        108,        1,    21600, 0x53f892e4
+0,        109,        109,        1,    21600, 0x608a0bf6
+0,        110,        110,        1,    21600, 0x6052b96f
+0,        111,        111,        1,    21600, 0x61f689e7
+0,        112,        112,        1,    21600, 0x02a52e81
+0,        113,        113,        1,    21600, 0x43f01ae2
diff --git a/tests/ref/fate/indeo2-intra b/tests/ref/fate/indeo2-intra
new file mode 100644
index 0000000..0831d91
--- /dev/null
+++ b/tests/ref/fate/indeo2-intra
@@ -0,0 +1,135 @@
+#tb 0: 66667/1000000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
+0,          0,          0,        1,    21600, 0x57a2ba42
+0,          1,          1,        1,    21600, 0x61e09615
+0,          2,          2,        1,    21600, 0x826e4e63
+0,          3,          3,        1,    21600, 0x107716ec
+0,          4,          4,        1,    21600, 0xb35ce1f4
+0,          5,          5,        1,    21600, 0x12cab085
+0,          6,          6,        1,    21600, 0x2f917f69
+0,          7,          7,        1,    21600, 0x25aa3d6e
+0,          8,          8,        1,    21600, 0xab1bfbed
+0,          9,          9,        1,    21600, 0x9936dff9
+0,         10,         10,        1,    21600, 0xc23cd8e5
+0,         11,         11,        1,    21600, 0xa7ebbcaa
+0,         12,         12,        1,    21600, 0xd4dda045
+0,         13,         13,        1,    21600, 0xcbce6d7d
+0,         14,         14,        1,    21600, 0x3cf35baf
+0,         15,         15,        1,    21600, 0x16de6008
+0,         16,         16,        1,    21600, 0x49d41acf
+0,         17,         17,        1,    21600, 0x8c630034
+0,         18,         18,        1,    21600, 0x0b310296
+0,         19,         19,        1,    21600, 0x4887067d
+0,         20,         20,        1,    21600, 0x1219f29e
+0,         21,         21,        1,    21600, 0x3f3fc0c8
+0,         22,         22,        1,    21600, 0x1bd1d0fc
+0,         23,         23,        1,    21600, 0x913f9d4c
+0,         24,         24,        1,    21600, 0x69e9a6b4
+0,         25,         25,        1,    21600, 0xcc2e917f
+0,         26,         26,        1,    21600, 0xf6967e30
+0,         27,         27,        1,    21600, 0xdf816593
+0,         28,         28,        1,    21600, 0xfd945b75
+0,         29,         29,        1,    21600, 0x7d7e0224
+0,         30,         30,        1,    21600, 0x7246f584
+0,         31,         31,        1,    21600, 0x07b7ce82
+0,         32,         32,        1,    21600, 0xee16c291
+0,         33,         33,        1,    21600, 0xf4efb53a
+0,         34,         34,        1,    21600, 0x2e73a208
+0,         35,         35,        1,    21600, 0x1c2b6068
+0,         36,         36,        1,    21600, 0x004250de
+0,         37,         37,        1,    21600, 0x61d957d9
+0,         38,         38,        1,    21600, 0x8b5d2cb0
+0,         39,         39,        1,    21600, 0xc0a91fbc
+0,         40,         40,        1,    21600, 0xa38108fc
+0,         41,         41,        1,    21600, 0x551f03b9
+0,         42,         42,        1,    21600, 0x93def5ca
+0,         43,         43,        1,    21600, 0xe8ecf8bb
+0,         44,         44,        1,    21600, 0x4c04fbb0
+0,         45,         45,        1,    21600, 0x0e41dae4
+0,         46,         46,        1,    21600, 0xca9fb0df
+0,         47,         47,        1,    21600, 0xb123af19
+0,         48,         48,        1,    21600, 0xfd59be7a
+0,         49,         49,        1,    21600, 0x2c88b7a6
+0,         50,         50,        1,    21600, 0x64cc9a1f
+0,         51,         51,        1,    21600, 0x73d6a9ba
+0,         52,         52,        1,    21600, 0x79198a11
+0,         53,         53,        1,    21600, 0x0d4a8610
+0,         54,         54,        1,    21600, 0x352e71bc
+0,         55,         55,        1,    21600, 0x08aa627e
+0,         56,         56,        1,    21600, 0xbee36e45
+0,         57,         57,        1,    21600, 0x30de5c1b
+0,         58,         58,        1,    21600, 0x21d75484
+0,         59,         59,        1,    21600, 0xe0e91d52
+0,         60,         60,        1,    21600, 0x678c2ebb
+0,         61,         61,        1,    21600, 0x2080397b
+0,         62,         62,        1,    21600, 0x7dbc1333
+0,         63,         63,        1,    21600, 0x9c730ad0
+0,         64,         64,        1,    21600, 0x4da50f55
+0,         65,         65,        1,    21600, 0xdde5eaa7
+0,         66,         66,        1,    21600, 0x949ed4fa
+0,         67,         67,        1,    21600, 0x5d63bc54
+0,         68,         68,        1,    21600, 0xc5dcba4f
+0,         69,         69,        1,    21600, 0xd68caee1
+0,         70,         70,        1,    21600, 0xf7409fc9
+0,         71,         71,        1,    21600, 0x6b0ca3e5
+0,         72,         72,        1,    21600, 0xd133a108
+0,         73,         73,        1,    21600, 0xf2687b81
+0,         74,         74,        1,    21600, 0x6e94645d
+0,         75,         75,        1,    21600, 0xff7e7524
+0,         76,         76,        1,    21600, 0x8c7255dd
+0,         77,         77,        1,    21600, 0x84e979cf
+0,         78,         78,        1,    21600, 0xaa4e7127
+0,         79,         79,        1,    21600, 0x0b56708c
+0,         80,         80,        1,    21600, 0x38f086c4
+0,         81,         81,        1,    21600, 0x6a7086f6
+0,         82,         82,        1,    21600, 0x57a3619d
+0,         83,         83,        1,    21600, 0xee27639a
+0,         84,         84,        1,    21600, 0x754b7ec6
+0,         85,         85,        1,    21600, 0x2f7b428c
+0,         86,         86,        1,    21600, 0x0dc94603
+0,         87,         87,        1,    21600, 0xeede54d8
+0,         88,         88,        1,    21600, 0x587b4725
+0,         89,         89,        1,    21600, 0xe7c72c7a
+0,         90,         90,        1,    21600, 0x523949cb
+0,         91,         91,        1,    21600, 0xeade5385
+0,         92,         92,        1,    21600, 0x1a8f45c8
+0,         93,         93,        1,    21600, 0x814a393c
+0,         94,         94,        1,    21600, 0xe7b34887
+0,         95,         95,        1,    21600, 0x8eef3f5f
+0,         96,         96,        1,    21600, 0x56f12f08
+0,         97,         97,        1,    21600, 0xb2d02448
+0,         98,         98,        1,    21600, 0xb7d936db
+0,         99,         99,        1,    21600, 0x45f726ab
+0,        100,        100,        1,    21600, 0x6012404d
+0,        101,        101,        1,    21600, 0x273c254e
+0,        102,        102,        1,    21600, 0x38e82c19
+0,        103,        103,        1,    21600, 0x73653274
+0,        104,        104,        1,    21600, 0x2ff63b0c
+0,        105,        105,        1,    21600, 0x96d03611
+0,        106,        106,        1,    21600, 0xee8c29d7
+0,        107,        107,        1,    21600, 0xac043199
+0,        108,        108,        1,    21600, 0xd2c741a7
+0,        109,        109,        1,    21600, 0xdc7b2b81
+0,        110,        110,        1,    21600, 0x376f438f
+0,        111,        111,        1,    21600, 0x55442ff7
+0,        112,        112,        1,    21600, 0x653b1472
+0,        113,        113,        1,    21600, 0xc4293779
+0,        114,        114,        1,    21600, 0xc6553740
+0,        115,        115,        1,    21600, 0xcf441053
+0,        116,        116,        1,    21600, 0xb1531bce
+0,        117,        117,        1,    21600, 0x145323b3
+0,        118,        118,        1,    21600, 0x916c2e9e
+0,        119,        119,        1,    21600, 0xb89bfecc
+0,        120,        120,        1,    21600, 0x8e2415b9
+0,        121,        121,        1,    21600, 0x5af23021
+0,        122,        122,        1,    21600, 0x53e81c10
+0,        123,        123,        1,    21600, 0xf7f82a6f
+0,        124,        124,        1,    21600, 0x851121a2
+0,        125,        125,        1,    21600, 0xa8432bd2
+0,        126,        126,        1,    21600, 0x1a381799
+0,        127,        127,        1,    21600, 0xbb761384
+0,        128,        128,        1,    21600, 0xc8f328d5
+0,        129,        129,        1,    21600, 0xb3742e8a
diff --git a/tests/ref/fate/indeo3 b/tests/ref/fate/indeo3
deleted file mode 100644
index 0f55649..0000000
--- a/tests/ref/fate/indeo3
+++ /dev/null
@@ -1,41 +0,0 @@
-#tb 0: 1/10
-0,          0,          0,        1,    21600, 0x845098fc
-0,          1,          1,        1,    21600, 0xc28e8bf0
-0,          2,          2,        1,    21600, 0x2f418fb4
-0,          3,          3,        1,    21600, 0x051d7a0e
-0,          4,          4,        1,    21600, 0x1b36aa7c
-0,          5,          5,        1,    21600, 0xb9e2ad38
-0,          6,          6,        1,    21600, 0x8dc99b60
-0,          7,          7,        1,    21600, 0xa3fa789a
-0,          8,          8,        1,    21600, 0x1fdbade2
-0,          9,          9,        1,    21600, 0x4f4ac164
-0,         10,         10,        1,    21600, 0x0ea5cb50
-0,         11,         11,        1,    21600, 0xfb659528
-0,         12,         12,        1,    21600, 0xac5790f8
-0,         13,         13,        1,    21600, 0x9762beb4
-0,         14,         14,        1,    21600, 0x29b0da0a
-0,         15,         15,        1,    21600, 0x6d88b0da
-0,         16,         16,        1,    21600, 0x687b8efa
-0,         17,         17,        1,    21600, 0xcd726220
-0,         18,         18,        1,    21600, 0xa1766598
-0,         19,         19,        1,    21600, 0xff4b8074
-0,         20,         20,        1,    21600, 0x845098fc
-0,         21,         21,        1,    21600, 0xdb259e08
-0,         22,         22,        1,    21600, 0xb6bda5a0
-0,         23,         23,        1,    21600, 0xbb998962
-0,         24,         24,        1,    21600, 0x28aa7b7c
-0,         25,         25,        1,    21600, 0x1ad1a15c
-0,         26,         26,        1,    21600, 0xb535a128
-0,         27,         27,        1,    21600, 0x4dbf968a
-0,         28,         28,        1,    21600, 0xfe90a8d6
-0,         29,         29,        1,    21600, 0xf63fabf0
-0,         30,         30,        1,    21600, 0xd6fabe58
-0,         31,         31,        1,    21600, 0x172eb09c
-0,         32,         32,        1,    21600, 0x44f8a8fe
-0,         33,         33,        1,    21600, 0x29429a06
-0,         34,         34,        1,    21600, 0xb12f8cc4
-0,         35,         35,        1,    21600, 0xd0c78cb4
-0,         36,         36,        1,    21600, 0x97e17e0c
-0,         37,         37,        1,    21600, 0xf8ac6700
-0,         38,         38,        1,    21600, 0xf9c17c94
-0,         39,         39,        1,    21600, 0xb10e8c54
diff --git a/tests/ref/fate/indeo3-1 b/tests/ref/fate/indeo3-1
new file mode 100644
index 0000000..386e530
--- /dev/null
+++ b/tests/ref/fate/indeo3-1
@@ -0,0 +1,45 @@
+#tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
+0,          0,          0,        1,    21600, 0x845098fc
+0,          1,          1,        1,    21600, 0xc28e8bf0
+0,          2,          2,        1,    21600, 0x2f418fb4
+0,          3,          3,        1,    21600, 0x051d7a0e
+0,          4,          4,        1,    21600, 0x1b36aa7c
+0,          5,          5,        1,    21600, 0xb9e2ad38
+0,          6,          6,        1,    21600, 0x8dc99b60
+0,          7,          7,        1,    21600, 0xa3fa789a
+0,          8,          8,        1,    21600, 0x1fdbade2
+0,          9,          9,        1,    21600, 0x4f4ac164
+0,         10,         10,        1,    21600, 0x0ea5cb50
+0,         11,         11,        1,    21600, 0xfb659528
+0,         12,         12,        1,    21600, 0xac5790f8
+0,         13,         13,        1,    21600, 0x9762beb4
+0,         14,         14,        1,    21600, 0x29b0da0a
+0,         15,         15,        1,    21600, 0x6d88b0da
+0,         16,         16,        1,    21600, 0x687b8efa
+0,         17,         17,        1,    21600, 0xcd726220
+0,         18,         18,        1,    21600, 0xa1766598
+0,         19,         19,        1,    21600, 0xff4b8074
+0,         20,         20,        1,    21600, 0x845098fc
+0,         21,         21,        1,    21600, 0xdb259e08
+0,         22,         22,        1,    21600, 0xb6bda5a0
+0,         23,         23,        1,    21600, 0xbb998962
+0,         24,         24,        1,    21600, 0x28aa7b7c
+0,         25,         25,        1,    21600, 0x1ad1a15c
+0,         26,         26,        1,    21600, 0xb535a128
+0,         27,         27,        1,    21600, 0x4dbf968a
+0,         28,         28,        1,    21600, 0xfe90a8d6
+0,         29,         29,        1,    21600, 0xf63fabf0
+0,         30,         30,        1,    21600, 0xd6fabe58
+0,         31,         31,        1,    21600, 0x172eb09c
+0,         32,         32,        1,    21600, 0x44f8a8fe
+0,         33,         33,        1,    21600, 0x29429a06
+0,         34,         34,        1,    21600, 0xb12f8cc4
+0,         35,         35,        1,    21600, 0xd0c78cb4
+0,         36,         36,        1,    21600, 0x97e17e0c
+0,         37,         37,        1,    21600, 0xf8ac6700
+0,         38,         38,        1,    21600, 0xf9c17c94
+0,         39,         39,        1,    21600, 0xb10e8c54
diff --git a/tests/ref/fate/indeo3-2 b/tests/ref/fate/indeo3-2
index 702d06b..78e145e 100644
--- a/tests/ref/fate/indeo3-2
+++ b/tests/ref/fate/indeo3-2
@@ -1,4 +1,8 @@
 #tb 0: 200/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x188
+#sar 0: 0/1
 0,          0,          0,        1,    67680, 0x532a4c40
 0,         37,         37,        1,    67680, 0x63d2757a
 0,         38,         38,        1,    67680, 0xb1dcf7d3
diff --git a/tests/ref/fate/indeo4 b/tests/ref/fate/indeo4
index 7f60461..0a2b051 100644
--- a/tests/ref/fate/indeo4
+++ b/tests/ref/fate/indeo4
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,    86400, 0x98f5e422
 0,          1,          1,        1,    86400, 0x1864cb06
 0,          2,          2,        1,    86400, 0xb09532ef
diff --git a/tests/ref/fate/indeo5 b/tests/ref/fate/indeo5
index 7b91238..6be2818 100644
--- a/tests/ref/fate/indeo5
+++ b/tests/ref/fate/indeo5
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 240x180
+#sar 0: 0/1
 0,          0,          0,        1,    48600, 0x72d4193b
 0,          2,          2,        1,    48600, 0x36abd6f3
 0,          3,          3,        1,    48600, 0x99e582f7
diff --git a/tests/ref/fate/interplay-mve-16bit b/tests/ref/fate/interplay-mve-16bit
index b20e998..c1ec1ca 100644
--- a/tests/ref/fate/interplay-mve-16bit
+++ b/tests/ref/fate/interplay-mve-16bit
@@ -1,4 +1,8 @@
 #tb 0: 417/12500
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x320
+#sar 0: 0/1
 0,          0,          0,        1,   614400, 0x00000000
 0,          1,          1,        1,   614400, 0x00000000
 0,          2,          2,        1,   614400, 0x3c4ce011
diff --git a/tests/ref/fate/interplay-mve-8bit b/tests/ref/fate/interplay-mve-8bit
index b37bd6e..6fb5af3 100644
--- a/tests/ref/fate/interplay-mve-8bit
+++ b/tests/ref/fate/interplay-mve-8bit
@@ -1,4 +1,8 @@
 #tb 0: 8341/125000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 432x320
+#sar 0: 0/1
 0,          0,          0,        1,   414720, 0x2580d574
 0,          1,          1,        1,   414720, 0x97f55cd3
 0,          2,          2,        1,   414720, 0x9408fb63
diff --git a/tests/ref/fate/iscc b/tests/ref/fate/iscc
new file mode 100644
index 0000000..7c1bb49
--- /dev/null
+++ b/tests/ref/fate/iscc
@@ -0,0 +1,10 @@
+#tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1760x968
+#sar 0: 0/1
+0,          0,          0,        1,  6814720, 0x1365f8ef
+0,          1,          1,        1,  6814720, 0x90838983
+0,          2,          2,        1,  6814720, 0xf0cc3131
+0,          3,          3,        1,  6814720, 0xc07e404d
+0,          4,          4,        1,  6814720, 0x945962dd
diff --git a/tests/ref/fate/iv8-demux b/tests/ref/fate/iv8-demux
index 02b6314..518f3de 100644
--- a/tests/ref/fate/iv8-demux
+++ b/tests/ref/fate/iv8-demux
@@ -1,27 +1,31 @@
 #extradata 0:       19, 0x1f2604b9
 #tb 0: 1/90000
+#media_type 0: video
+#codec_id 0: mpeg4
+#dimensions 0: 704x576
+#sar 0: 1/1
 0,          0,          0,        0,    20883, 0x347191e2
-0,          0,       3600,        0,    20882, 0xe1573905
-0,       3600,       7200,        0,    20894, 0xd54f516a
-0,       7200,      10800,        0,    20891, 0x1b5c5039
-0,      10800,      14400,        0,    20883, 0x8e785b4d
-0,      14400,      18000,        0,    20870, 0xd26ca1f6
-0,      18000,      21600,        0,    21448, 0x946f5b2b
-0,      21600,      25200,        0,    21433, 0xb18687c5
-0,      25200,      28800,        0,    20865, 0xc0eb3fce
-0,      28800,      32399,        0,    20842, 0x9d0728ba
-0,      32399,      35999,        0,    20878, 0xf60f5dee
-0,      35999,      39600,        0,    20866, 0x3bde568f
-0,      39600,      43200,        0,    20884, 0x22736993
-0,      43200,      46800,        0,    20860, 0xf56f2fca
-0,      46800,      50400,        0,    20872, 0xf39e3cb3
-0,      50400,      53999,        0,    20835, 0xa3c4363b
-0,      53999,      57600,        0,    20905, 0x552853d1
-0,      57600,      61200,        0,    20874, 0xed0b91ec
-0,      61200,      64799,        0,    20877, 0xe1623e01
-0,      64799,      68399,        0,    20933, 0x19906564
-0,      68399,      72000,        0,    20891, 0x3d064fd3
-0,      72000,      75600,        0,    20834, 0xcb774dbc
-0,      75600,      79200,        0,    20870, 0xbc536589
-0,      79200,      82800,        0,    21421, 0xc99a68e4
-0,      82800,      86400,        0,    12869, 0x5684e304
+0,       3600,       3600,        0,    20882, 0xe1573905
+0,       7200,       7200,        0,    20894, 0xd54f516a
+0,      10800,      10800,        0,    20891, 0x1b5c5039
+0,      14400,      14400,        0,    20883, 0x8e785b4d
+0,      18000,      18000,        0,    20870, 0xd26ca1f6
+0,      21600,      21600,        0,    21448, 0x946f5b2b
+0,      25200,      25200,        0,    21433, 0xb18687c5
+0,      28800,      28800,        0,    20865, 0xc0eb3fce
+0,      32399,      32399,        0,    20842, 0x9d0728ba
+0,      35999,      35999,        0,    20878, 0xf60f5dee
+0,      39600,      39600,        0,    20866, 0x3bde568f
+0,      43200,      43200,        0,    20884, 0x22736993
+0,      46800,      46800,        0,    20860, 0xf56f2fca
+0,      50400,      50400,        0,    20872, 0xf39e3cb3
+0,      53999,      53999,        0,    20835, 0xa3c4363b
+0,      57600,      57600,        0,    20905, 0x552853d1
+0,      61200,      61200,        0,    20874, 0xed0b91ec
+0,      64799,      64799,        0,    20877, 0xe1623e01
+0,      68399,      68399,        0,    20933, 0x19906564
+0,      72000,      72000,        0,    20891, 0x3d064fd3
+0,      75600,      75600,        0,    20834, 0xcb774dbc
+0,      79200,      79200,        0,    20870, 0xbc536589
+0,      82800,      82800,        0,    21421, 0xc99a68e4
+0,      86400,      86400,        0,    12869, 0x5684e304
diff --git a/tests/ref/fate/jpeg2000-dcinema b/tests/ref/fate/jpeg2000-dcinema
index 08bbfdc..cdf8cd4 100644
--- a/tests/ref/fate/jpeg2000-dcinema
+++ b/tests/ref/fate/jpeg2000-dcinema
@@ -1,3 +1,7 @@
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 0,          0,          0,        1, 12441600, 0xfcf6a127
 0,          1,          1,        1, 12441600, 0x577b6a64
diff --git a/tests/ref/fate/jv b/tests/ref/fate/jv
index b0a6008..d90fe24 100644
--- a/tests/ref/fate/jv
+++ b/tests/ref/fate/jv
@@ -1,4 +1,8 @@
 #tb 0: 2/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x00000000
 0,          2,          2,        1,   192000, 0x331b1c12
 0,          3,          3,        1,   192000, 0xc2fa2d89
diff --git a/tests/ref/fate/jv-demux b/tests/ref/fate/jv-demux
index 51638df..280528c 100644
--- a/tests/ref/fate/jv-demux
+++ b/tests/ref/fate/jv-demux
@@ -1,5 +1,13 @@
 #tb 0: 2/25
+#media_type 0: video
+#codec_id 0: jv
+#dimensions 0: 320x200
+#sar 0: 0/1
 #tb 1: 1/22050
+#media_type 1: audio
+#codec_id 1: pcm_u8
+#sample_rate 1: 22050
+#channel_layout 1: 4
 0,          0,          0,        1,        6, 0x000a0003
 1,          0,          0,   131072,   131072, 0x14c664d6
 0,          1,          1,        1,      773, 0x11802a51
diff --git a/tests/ref/fate/kgv1 b/tests/ref/fate/kgv1
index 4f475bb..a3649bc 100644
--- a/tests/ref/fate/kgv1
+++ b/tests/ref/fate/kgv1
@@ -1,4 +1,8 @@
 #tb 0: 1/60
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   153600, 0x00000000
 0,          1,          1,        1,   153600, 0x00000000
 0,          2,          2,        1,   153600, 0x00000000
diff --git a/tests/ref/fate/kmvc b/tests/ref/fate/kmvc
index 8a733bb..9c7686b 100644
--- a/tests/ref/fate/kmvc
+++ b/tests/ref/fate/kmvc
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x160
+#sar 0: 0/1
 0,          0,          0,        1,   153600, 0x00000000
 0,          1,          1,        1,   153600, 0x00000000
 0,          2,          2,        1,   153600, 0x00000000
diff --git a/tests/ref/fate/lagarith-red b/tests/ref/fate/lagarith-red
index b5fb96b..0e065d6 100644
--- a/tests/ref/fate/lagarith-red
+++ b/tests/ref/fate/lagarith-red
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0x67dfe576
 0,          1,          1,        1,   230400, 0x67dfe576
 0,          2,          2,        1,   230400, 0x67dfe576
diff --git a/tests/ref/fate/lagarith-rgb24 b/tests/ref/fate/lagarith-rgb24
index 1eb2bc4..63250c6 100644
--- a/tests/ref/fate/lagarith-rgb24
+++ b/tests/ref/fate/lagarith-rgb24
@@ -1,4 +1,8 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 480x256
+#sar 0: 0/1
 0,          0,          0,        1,   368640, 0x26f74db2
 0,          1,          1,        1,   368640, 0x63b29ea4
 0,          2,          2,        1,   368640, 0x19467f03
diff --git a/tests/ref/fate/lagarith-rgb32 b/tests/ref/fate/lagarith-rgb32
index 490e2e5..8a4c4d2 100644
--- a/tests/ref/fate/lagarith-rgb32
+++ b/tests/ref/fate/lagarith-rgb32
@@ -1,4 +1,8 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,  1382400, 0x00000000
 0,          1,          1,        1,  1382400, 0x00000000
 0,          2,          2,        1,  1382400, 0x00000000
diff --git a/tests/ref/fate/lagarith-ticket4119 b/tests/ref/fate/lagarith-ticket4119
new file mode 100644
index 0000000..c46ef04
--- /dev/null
+++ b/tests/ref/fate/lagarith-ticket4119
@@ -0,0 +1,8 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x360
+#sar 0: 0/1
+0,          0,          0,        1,   691200, 0x00000000
+0,         25,         25,        1,   691200, 0xc88a6f24
+0,         50,         50,        1,   691200, 0x906d474c
diff --git a/tests/ref/fate/lagarith-ticket4119-cfr b/tests/ref/fate/lagarith-ticket4119-cfr
new file mode 100644
index 0000000..324fe44
--- /dev/null
+++ b/tests/ref/fate/lagarith-ticket4119-cfr
@@ -0,0 +1,79 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x360
+#sar 0: 0/1
+0,          0,          0,        1,   691200, 0x00000000
+0,          1,          1,        1,   691200, 0x00000000
+0,          2,          2,        1,   691200, 0x00000000
+0,          3,          3,        1,   691200, 0x00000000
+0,          4,          4,        1,   691200, 0x00000000
+0,          5,          5,        1,   691200, 0x00000000
+0,          6,          6,        1,   691200, 0x00000000
+0,          7,          7,        1,   691200, 0x00000000
+0,          8,          8,        1,   691200, 0x00000000
+0,          9,          9,        1,   691200, 0x00000000
+0,         10,         10,        1,   691200, 0x00000000
+0,         11,         11,        1,   691200, 0x00000000
+0,         12,         12,        1,   691200, 0x00000000
+0,         13,         13,        1,   691200, 0x00000000
+0,         14,         14,        1,   691200, 0x00000000
+0,         15,         15,        1,   691200, 0x00000000
+0,         16,         16,        1,   691200, 0x00000000
+0,         17,         17,        1,   691200, 0x00000000
+0,         18,         18,        1,   691200, 0x00000000
+0,         19,         19,        1,   691200, 0x00000000
+0,         20,         20,        1,   691200, 0x00000000
+0,         21,         21,        1,   691200, 0x00000000
+0,         22,         22,        1,   691200, 0x00000000
+0,         23,         23,        1,   691200, 0x00000000
+0,         24,         24,        1,   691200, 0xc88a6f24
+0,         25,         25,        1,   691200, 0xc88a6f24
+0,         26,         26,        1,   691200, 0xc88a6f24
+0,         27,         27,        1,   691200, 0xc88a6f24
+0,         28,         28,        1,   691200, 0xc88a6f24
+0,         29,         29,        1,   691200, 0xc88a6f24
+0,         30,         30,        1,   691200, 0xc88a6f24
+0,         31,         31,        1,   691200, 0xc88a6f24
+0,         32,         32,        1,   691200, 0xc88a6f24
+0,         33,         33,        1,   691200, 0xc88a6f24
+0,         34,         34,        1,   691200, 0xc88a6f24
+0,         35,         35,        1,   691200, 0xc88a6f24
+0,         36,         36,        1,   691200, 0xc88a6f24
+0,         37,         37,        1,   691200, 0xc88a6f24
+0,         38,         38,        1,   691200, 0xc88a6f24
+0,         39,         39,        1,   691200, 0xc88a6f24
+0,         40,         40,        1,   691200, 0xc88a6f24
+0,         41,         41,        1,   691200, 0xc88a6f24
+0,         42,         42,        1,   691200, 0xc88a6f24
+0,         43,         43,        1,   691200, 0xc88a6f24
+0,         44,         44,        1,   691200, 0xc88a6f24
+0,         45,         45,        1,   691200, 0xc88a6f24
+0,         46,         46,        1,   691200, 0xc88a6f24
+0,         47,         47,        1,   691200, 0xc88a6f24
+0,         48,         48,        1,   691200, 0xc88a6f24
+0,         49,         49,        1,   691200, 0x906d474c
+0,         50,         50,        1,   691200, 0x906d474c
+0,         51,         51,        1,   691200, 0x906d474c
+0,         52,         52,        1,   691200, 0x906d474c
+0,         53,         53,        1,   691200, 0x906d474c
+0,         54,         54,        1,   691200, 0x906d474c
+0,         55,         55,        1,   691200, 0x906d474c
+0,         56,         56,        1,   691200, 0x906d474c
+0,         57,         57,        1,   691200, 0x906d474c
+0,         58,         58,        1,   691200, 0x906d474c
+0,         59,         59,        1,   691200, 0x906d474c
+0,         60,         60,        1,   691200, 0x906d474c
+0,         61,         61,        1,   691200, 0x906d474c
+0,         62,         62,        1,   691200, 0x906d474c
+0,         63,         63,        1,   691200, 0x906d474c
+0,         64,         64,        1,   691200, 0x906d474c
+0,         65,         65,        1,   691200, 0x906d474c
+0,         66,         66,        1,   691200, 0x906d474c
+0,         67,         67,        1,   691200, 0x906d474c
+0,         68,         68,        1,   691200, 0x906d474c
+0,         69,         69,        1,   691200, 0x906d474c
+0,         70,         70,        1,   691200, 0x906d474c
+0,         71,         71,        1,   691200, 0x906d474c
+0,         72,         72,        1,   691200, 0x906d474c
+0,         73,         73,        1,   691200, 0x906d474c
diff --git a/tests/ref/fate/lagarith-ticket4119-drop b/tests/ref/fate/lagarith-ticket4119-drop
new file mode 100644
index 0000000..abc58d5
--- /dev/null
+++ b/tests/ref/fate/lagarith-ticket4119-drop
@@ -0,0 +1,8 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x360
+#sar 0: 0/1
+0,          0,          0,        1,   691200, 0x00000000
+0,          1,          1,        1,   691200, 0xc88a6f24
+0,          2,          2,        1,   691200, 0x906d474c
diff --git a/tests/ref/fate/lagarith-ticket4119-pass b/tests/ref/fate/lagarith-ticket4119-pass
new file mode 100644
index 0000000..c46ef04
--- /dev/null
+++ b/tests/ref/fate/lagarith-ticket4119-pass
@@ -0,0 +1,8 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x360
+#sar 0: 0/1
+0,          0,          0,        1,   691200, 0x00000000
+0,         25,         25,        1,   691200, 0xc88a6f24
+0,         50,         50,        1,   691200, 0x906d474c
diff --git a/tests/ref/fate/lagarith-ticket4119-vfr b/tests/ref/fate/lagarith-ticket4119-vfr
new file mode 100644
index 0000000..c46ef04
--- /dev/null
+++ b/tests/ref/fate/lagarith-ticket4119-vfr
@@ -0,0 +1,8 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x360
+#sar 0: 0/1
+0,          0,          0,        1,   691200, 0x00000000
+0,         25,         25,        1,   691200, 0xc88a6f24
+0,         50,         50,        1,   691200, 0x906d474c
diff --git a/tests/ref/fate/lagarith-yuy2 b/tests/ref/fate/lagarith-yuy2
index c5aed92..64a211e 100644
--- a/tests/ref/fate/lagarith-yuy2
+++ b/tests/ref/fate/lagarith-yuy2
@@ -1,2 +1,6 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x768
+#sar 0: 0/1
 0,          0,          0,        1,  1572864, 0xeed76a7d
diff --git a/tests/ref/fate/lagarith-yv12 b/tests/ref/fate/lagarith-yv12
index c9c9ff3..a79a3ba 100644
--- a/tests/ref/fate/lagarith-yv12
+++ b/tests/ref/fate/lagarith-yv12
@@ -1,3 +1,7 @@
 #tb 0: 1/60
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x240
+#sar 0: 0/1
 0,          0,          0,        1,    92160, 0x1dfdf5c1
 0,          1,          1,        1,    92160, 0x6965884f
diff --git a/tests/ref/fate/lmlm4-demux b/tests/ref/fate/lmlm4-demux
index 95df3e6..79cb539 100644
--- a/tests/ref/fate/lmlm4-demux
+++ b/tests/ref/fate/lmlm4-demux
@@ -1,6 +1,14 @@
 #extradata 0:       28, 0x2f140538
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: mpeg4
+#dimensions 0: 320x240
+#sar 0: 1/1
 #tb 1: 1/90000
+#media_type 1: audio
+#codec_id 1: mp2
+#sample_rate 1: 48000
+#channel_layout 1: 3
 0,          0, -9223372036854775808,        1,     5951, 0xe9118e0d
 1,          0,          0,     2160,      768, 0xaebcbebb
 1,       2160,       2160,     2160,      768, 0xaebcbebb
diff --git a/tests/ref/fate/loco-rgb b/tests/ref/fate/loco-rgb
index ad199f1..289e73f 100644
--- a/tests/ref/fate/loco-rgb
+++ b/tests/ref/fate/loco-rgb
@@ -1,4 +1,8 @@
 #tb 0: 71/500
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 188x128
+#sar 0: 0/1
 0,          0,          0,        1,    72192, 0x1847500c
 0,          1,          1,        1,    72192, 0x1b0e2e87
 0,          2,          2,        1,    72192, 0x293276c8
diff --git a/tests/ref/fate/loco-yuy2 b/tests/ref/fate/loco-yuy2
index 60a06bc..e963cda 100644
--- a/tests/ref/fate/loco-yuy2
+++ b/tests/ref/fate/loco-yuy2
@@ -1,4 +1,8 @@
 #tb 0: 71/500
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 188x128
+#sar 0: 0/1
 0,          0,          0,        1,    48128, 0x7795782d
 0,          1,          1,        1,    48128, 0x3d89bcf7
 0,          2,          2,        1,    48128, 0x170d200a
diff --git a/tests/ref/fate/lossless-wma24-1 b/tests/ref/fate/lossless-wma24-1
new file mode 100644
index 0000000..ddee31c
--- /dev/null
+++ b/tests/ref/fate/lossless-wma24-1
@@ -0,0 +1 @@
+9ade91f506bc025854f6ffea0d635bc6
diff --git a/tests/ref/fate/lossless-wma24-2 b/tests/ref/fate/lossless-wma24-2
new file mode 100644
index 0000000..5ebdfd1
--- /dev/null
+++ b/tests/ref/fate/lossless-wma24-2
@@ -0,0 +1 @@
+908ec5c16f497bf7d5658d2689d125c8
diff --git a/tests/ref/fate/lossless-wma24-rawtile b/tests/ref/fate/lossless-wma24-rawtile
new file mode 100644
index 0000000..96e5e21
--- /dev/null
+++ b/tests/ref/fate/lossless-wma24-rawtile
@@ -0,0 +1 @@
+337592f38a2218a5bc95ceb9b5e72c8b
diff --git a/tests/ref/fate/m4v b/tests/ref/fate/m4v
new file mode 100644
index 0000000..cebe443
--- /dev/null
+++ b/tests/ref/fate/m4v
@@ -0,0 +1,47 @@
+#tb 0: 1/60
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
+0,          0,          0,        1,   115200, 0x7262156b
+0,         11,         11,        1,   115200, 0xa6aebc2f
+0,         22,         22,        1,   115200, 0x9c7beba1
+0,         33,         33,        1,   115200, 0x556037a2
+0,         44,         44,        1,   115200, 0x532e3a23
+0,         60,         60,        1,   115200, 0x110511f4
+0,         71,         71,        1,   115200, 0xb7f929a4
+0,         82,         82,        1,   115200, 0xdab9f3c2
+0,         93,         93,        1,   115200, 0x441413dd
+0,        104,        104,        1,   115200, 0x01163f33
+0,        120,        120,        1,   115200, 0x47720c78
+0,        131,        131,        1,   115200, 0x07c21356
+0,        142,        142,        1,   115200, 0x085d4291
+0,        153,        153,        1,   115200, 0xf6db074c
+0,        164,        164,        1,   115200, 0x95093e75
+0,        180,        180,        1,   115200, 0x5f8118ef
+0,        191,        191,        1,   115200, 0x2b4de34a
+0,        202,        202,        1,   115200, 0x0a731857
+0,        213,        213,        1,   115200, 0xd75ef3be
+0,        224,        224,        1,   115200, 0x321cf5a9
+0,        240,        240,        1,   115200, 0x3eb222fd
+0,        251,        251,        1,   115200, 0xc7d92f3e
+0,        262,        262,        1,   115200, 0x6fda0366
+0,        273,        273,        1,   115200, 0x6bb61b03
+0,        284,        284,        1,   115200, 0x5f367ef8
+0,        300,        300,        1,   115200, 0x237d0c77
+0,        311,        311,        1,   115200, 0xafa813ef
+0,        322,        322,        1,   115200, 0x39263ef4
+0,        333,        333,        1,   115200, 0x47c70441
+0,        344,        344,        1,   115200, 0xd43fffb0
+0,        360,        360,        1,   115200, 0x75696afb
+0,        371,        371,        1,   115200, 0xb0f117a3
+0,        382,        382,        1,   115200, 0x002f42f0
+0,        393,        393,        1,   115200, 0xa192487e
+0,        404,        404,        1,   115200, 0x19a7072e
+0,        420,        420,        1,   115200, 0xc500669c
+0,        431,        431,        1,   115200, 0xe4636ba9
+0,        442,        442,        1,   115200, 0xdf3d5d86
+0,        453,        453,        1,   115200, 0xf30825d5
+0,        464,        464,        1,   115200, 0xe3c944a1
+0,        480,        480,        1,   115200, 0x8fec4420
+0,        491,        491,        1,   115200, 0x9381fdab
diff --git a/tests/ref/fate/m4v-cfr b/tests/ref/fate/m4v-cfr
new file mode 100644
index 0000000..4eee84d
--- /dev/null
+++ b/tests/ref/fate/m4v-cfr
@@ -0,0 +1,47 @@
+#tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
+0,          0,          0,        1,   115200, 0x7262156b
+0,          1,          1,        1,   115200, 0xa6aebc2f
+0,          2,          2,        1,   115200, 0x9c7beba1
+0,          3,          3,        1,   115200, 0x556037a2
+0,          4,          4,        1,   115200, 0x532e3a23
+0,          5,          5,        1,   115200, 0x110511f4
+0,          6,          6,        1,   115200, 0xb7f929a4
+0,          7,          7,        1,   115200, 0xdab9f3c2
+0,          8,          8,        1,   115200, 0x441413dd
+0,          9,          9,        1,   115200, 0x01163f33
+0,         10,         10,        1,   115200, 0x47720c78
+0,         11,         11,        1,   115200, 0x07c21356
+0,         12,         12,        1,   115200, 0x085d4291
+0,         13,         13,        1,   115200, 0xf6db074c
+0,         14,         14,        1,   115200, 0x95093e75
+0,         15,         15,        1,   115200, 0x5f8118ef
+0,         16,         16,        1,   115200, 0x2b4de34a
+0,         17,         17,        1,   115200, 0x0a731857
+0,         18,         18,        1,   115200, 0xd75ef3be
+0,         19,         19,        1,   115200, 0x321cf5a9
+0,         20,         20,        1,   115200, 0x3eb222fd
+0,         21,         21,        1,   115200, 0xc7d92f3e
+0,         22,         22,        1,   115200, 0x6fda0366
+0,         23,         23,        1,   115200, 0x6bb61b03
+0,         24,         24,        1,   115200, 0x5f367ef8
+0,         25,         25,        1,   115200, 0x237d0c77
+0,         26,         26,        1,   115200, 0xafa813ef
+0,         27,         27,        1,   115200, 0x39263ef4
+0,         28,         28,        1,   115200, 0x47c70441
+0,         29,         29,        1,   115200, 0xd43fffb0
+0,         30,         30,        1,   115200, 0x75696afb
+0,         31,         31,        1,   115200, 0xb0f117a3
+0,         32,         32,        1,   115200, 0x002f42f0
+0,         33,         33,        1,   115200, 0xa192487e
+0,         34,         34,        1,   115200, 0x19a7072e
+0,         35,         35,        1,   115200, 0xc500669c
+0,         36,         36,        1,   115200, 0xe4636ba9
+0,         37,         37,        1,   115200, 0xdf3d5d86
+0,         38,         38,        1,   115200, 0xf30825d5
+0,         39,         39,        1,   115200, 0xe3c944a1
+0,         40,         40,        1,   115200, 0x8fec4420
+0,         41,         41,        1,   115200, 0x9381fdab
diff --git a/tests/ref/fate/maxis-xa b/tests/ref/fate/maxis-xa
index c29738c..ae8124d 100644
--- a/tests/ref/fate/maxis-xa
+++ b/tests/ref/fate/maxis-xa
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: adpcm_ea_maxis_xa
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,       28,       30, 0x51750711
 0,         28,         28,       28,       30, 0x9ca20c2a
 0,         56,         56,       28,       30, 0x7551081f
diff --git a/tests/ref/fate/mdec b/tests/ref/fate/mdec
index b7aab62..ae438ed 100644
--- a/tests/ref/fate/mdec
+++ b/tests/ref/fate/mdec
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 304x224
+#sar 0: 0/1
 0,          0,          0,        1,   102144, 0x6edc83de
 0,          1,          1,        1,   102144, 0xd0534fda
 0,          2,          2,        1,   102144, 0x6447911f
diff --git a/tests/ref/fate/mdec-v3 b/tests/ref/fate/mdec-v3
index 7e4bbdb..471303f 100644
--- a/tests/ref/fate/mdec-v3
+++ b/tests/ref/fate/mdec-v3
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x160
+#sar 0: 0/1
 0,          0,          0,        1,    76800, 0x2677be82
 0,          1,          1,        1,    76800, 0x1f323c75
 0,          2,          2,        1,    76800, 0xc8be3be9
diff --git a/tests/ref/fate/mimic b/tests/ref/fate/mimic
index 217d487..e36e6a8 100644
--- a/tests/ref/fate/mimic
+++ b/tests/ref/fate/mimic
@@ -1,4 +1,8 @@
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        0,   115200, 0xa974d407
 0,        548,        548,        0,   115200, 0x72618b84
 0,       1088,       1088,        0,   115200, 0x87768573
diff --git a/tests/ref/fate/mjpegb b/tests/ref/fate/mjpegb
index ef8a00b..0298274 100644
--- a/tests/ref/fate/mjpegb
+++ b/tests/ref/fate/mjpegb
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    38400, 0x45311080
 0,          1,          1,        1,    38400, 0x9474f731
 0,          2,          2,        1,    38400, 0x429ebb12
diff --git a/tests/ref/fate/mkv b/tests/ref/fate/mkv
index 765798c..0e7f651 100644
--- a/tests/ref/fate/mkv
+++ b/tests/ref/fate/mkv
@@ -1,7 +1,15 @@
 #extradata 0:       35, 0xc3b20b70
 #extradata 1:        2, 0x00b200a1
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: h264
+#dimensions 0: 1024x576
+#sar 0: 1/1
 #tb 1: 1/1000
+#media_type 1: audio
+#codec_id 1: aac
+#sample_rate 1: 48000
+#channel_layout 1: 3
 0,        -42,          0,       41,    63501, 0x139d4c99
 0,          0,         84,       41,     5368, 0xd964b678, F=0x0
 1,          8,          8,       21,      528, 0x3c990ddf
diff --git a/tests/ref/fate/mkv-1242 b/tests/ref/fate/mkv-1242
new file mode 100644
index 0000000..1ba41a0
--- /dev/null
+++ b/tests/ref/fate/mkv-1242
@@ -0,0 +1,47 @@
+#extradata 0:       93, 0xc2a32e14
+#extradata 1:        2, 0x00b200a1
+#tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: h264
+#dimensions 0: 1280x718
+#sar 0: 1/1
+#tb 1: 1/1000
+#media_type 1: audio
+#codec_id 1: aac
+#sample_rate 1: 48000
+#channel_layout 1: 3
+0,        -42,          0,       41,     2969, 0xa7016742
+0,          0,         42,       41,      135, 0x33af1a9e, F=0x0
+1,          0,          0,       21,        6, 0x027e00e8
+1,         21,         21,       21,        6, 0x027e00e8
+0,         42,         83,       41,     9196, 0x24d8439f
+1,         42,         42,       21,        6, 0x027e00e8
+1,         63,         63,       21,        6, 0x027e00e8
+0,         83,        125,       41,     4926, 0xd7e2e492, F=0x0
+1,         85,         85,       21,        6, 0x027e00e8
+1,        106,        106,       21,       24, 0x886f0c1f
+0,        125,        167,       41,    11069, 0x44839c66
+1,        127,        127,       21,      550, 0xf863059c
+1,        148,        148,       22,      596, 0x32d414c1
+0,        167,        250,       41,     6143, 0xc25343dd, F=0x0
+1,        171,        171,       21,      247, 0x2d0776c9
+1,        192,        192,       21,      264, 0xf04a7b44
+0,        209,        209,       41,     4197, 0x3b9f74ad, F=0x0
+1,        213,        213,       21,      251, 0xc7628539
+1,        234,        234,       22,      243, 0x99ef768b
+0,        250,        334,       41,    17595, 0x1e502128, F=0x0
+1,        256,        256,       21,      257, 0x233f7ccc
+1,        277,        277,       21,      264, 0x7d9f7bd9
+0,        292,        292,       41,      741, 0xe6b94afc, F=0x0
+1,        298,        298,       21,      298, 0x51478f98
+1,        319,        319,       22,      323, 0x419d9938
+0,        334,        417,       41,    16138, 0xba72f2fe, F=0x0
+1,        341,        341,       21,      309, 0x6219980c
+1,        362,        362,       21,      325, 0x3fb3976f
+0,        375,        375,       41,      322, 0xd6bf790f, F=0x0
+1,        383,        383,       21,      325, 0xcd7a9fd6
+1,        404,        404,       22,      359, 0x6edeb91c
+1,        426,        426,       21,      333, 0xb8999fb7
+1,        447,        447,       21,      317, 0xf2589e1a
+1,        468,        468,       21,      319, 0x82ed9572
+1,        489,        489,       22,      473, 0xea54e696
diff --git a/tests/ref/fate/motionpixels b/tests/ref/fate/motionpixels
index c875275..b376cc2 100644
--- a/tests/ref/fate/motionpixels
+++ b/tests/ref/fate/motionpixels
@@ -1,4 +1,8 @@
 #tb 0: 66667/1000000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0xee05b509
 0,          1,          1,        1,   230400, 0x23b28b24
 0,          2,          2,        1,   230400, 0x4a4d6007
diff --git a/tests/ref/fate/mov-mp3-demux b/tests/ref/fate/mov-mp3-demux
new file mode 100644
index 0000000..fc96c58
--- /dev/null
+++ b/tests/ref/fate/mov-mp3-demux
@@ -0,0 +1,293 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: mp3
+#sample_rate 0: 44100
+#channel_layout 0: 3
+0,          0,          0,     1152,       36, 0x8e260589
+0,       1152,       1152,     1152,       36, 0x8e260589
+0,       2304,       2304,     1152,       36, 0x8e260589
+0,       3456,       3456,     1152,       36, 0x8e260589
+0,       4608,       4608,     1152,       36, 0x8e260589
+0,       5760,       5760,     1152,       36, 0x8e260589
+0,       6912,       6912,     1152,       69, 0xdb550f09
+0,       8064,       8064,     1152,      104, 0xbaeb1aa8
+0,       9216,       9216,     1152,      104, 0xbaeb1aa8
+0,      10368,      10368,     1152,      104, 0xbaeb1aa8
+0,      11520,      11520,     1152,      104, 0xbaeb1aa8
+0,      12672,      12672,     1152,      104, 0xbaeb1aa8
+0,      13824,      13824,     1152,      104, 0xbaeb1aa8
+0,      14976,      14976,     1152,       36, 0x8e260589
+0,      16128,      16128,     1152,      601, 0xc34f1dc9
+0,      17280,      17280,     1152,      716, 0x6c2665e5
+0,      18432,      18432,     1152,      672, 0xf9873f4b
+0,      19584,      19584,     1152,      631, 0xd13333cc
+0,      20736,      20736,     1152,      604, 0xc0bb13e5
+0,      21888,      21888,     1152,      642, 0x4e873319
+0,      23040,      23040,     1152,      631, 0xcf701e7d
+0,      24192,      24192,     1152,      632, 0x27773046
+0,      25344,      25344,     1152,      609, 0x7ec21e53
+0,      26496,      26496,     1152,      582, 0xd68e0d59
+0,      27648,      27648,     1152,      550, 0x5b1303ee
+0,      28800,      28800,     1152,      581, 0x73dc12e4
+0,      29952,      29952,     1152,      545, 0x530f085a
+0,      31104,      31104,     1152,      556, 0xff0cfd9a
+0,      32256,      32256,     1152,      567, 0x3c330743
+0,      33408,      33408,     1152,      564, 0x2c3a1144
+0,      34560,      34560,     1152,      913, 0x74b08ab7
+0,      35712,      35712,     1152,      681, 0x2669444a
+0,      36864,      36864,     1152,      615, 0x60a41b1a
+0,      38016,      38016,     1152,      670, 0x53793367
+0,      39168,      39168,     1152,      666, 0x8c453c1a
+0,      40320,      40320,     1152,      613, 0x679f17a4
+0,      41472,      41472,     1152,      561, 0x357405c0
+0,      42624,      42624,     1152,      527, 0x687afacb
+0,      43776,      43776,     1152,      515, 0xf99dfb73
+0,      44928,      44928,     1152,      560, 0xa9ca0767
+0,      46080,      46080,     1152,      550, 0xb1ce0990
+0,      47232,      47232,     1152,      494, 0x3fd2f2c8
+0,      48384,      48384,     1152,      518, 0x9c5b0242
+0,      49536,      49536,     1152,      520, 0xbfdc0877
+0,      50688,      50688,     1152,      512, 0x4988f94b
+0,      51840,      51840,     1152,      786, 0xf3cf61de
+0,      52992,      52992,     1152,      713, 0x2f1c46b4
+0,      54144,      54144,     1152,      616, 0x210327d8
+0,      55296,      55296,     1152,      632, 0x39d430d4
+0,      56448,      56448,     1152,      615, 0xd7231930
+0,      57600,      57600,     1152,      620, 0xb7023663
+0,      58752,      58752,     1152,      585, 0x9e90100a
+0,      59904,      59904,     1152,      583, 0xe4152b2a
+0,      61056,      61056,     1152,      614, 0x0d572ebf
+0,      62208,      62208,     1152,      636, 0x9d1f2e6b
+0,      63360,      63360,     1152,      603, 0x2e33240f
+0,      64512,      64512,     1152,      627, 0x2c7e204c
+0,      65664,      65664,     1152,      626, 0x5cc3254b
+0,      66816,      66816,     1152,      626, 0xe8fd34df
+0,      67968,      67968,     1152,      600, 0x33a926d5
+0,      69120,      69120,     1152,      777, 0x4cd66f53
+0,      70272,      70272,     1152,      753, 0x8b297901
+0,      71424,      71424,     1152,      657, 0xd10e302f
+0,      72576,      72576,     1152,      611, 0x484d2f44
+0,      73728,      73728,     1152,      640, 0x310b414a
+0,      74880,      74880,     1152,      580, 0x3b410cdb
+0,      76032,      76032,     1152,      574, 0x6aba282c
+0,      77184,      77184,     1152,      541, 0x59680d64
+0,      78336,      78336,     1152,      512, 0x0824f236
+0,      79488,      79488,     1152,      516, 0x6d1efaba
+0,      80640,      80640,     1152,      553, 0x942b0d90
+0,      81792,      81792,     1152,      564, 0xb8471180
+0,      82944,      82944,     1152,      550, 0xfb150964
+0,      84096,      84096,     1152,      534, 0xbc4e0254
+0,      85248,      85248,     1152,      529, 0x02b3f603
+0,      86400,      86400,     1152,      521, 0xe77a00f3
+0,      87552,      87552,     1152,      501, 0x0292f088
+0,      88704,      88704,     1152,      498, 0xd1f4eb60
+0,      89856,      89856,     1152,      495, 0xa9e8e882
+0,      91008,      91008,     1152,      487, 0x1b40edfd
+0,      92160,      92160,     1152,      492, 0xd8cde96f
+0,      93312,      93312,     1152,      480, 0x387be300
+0,      94464,      94464,     1152,      476, 0x4c6ae249
+0,      95616,      95616,     1152,      450, 0xd690d4f4
+0,      96768,      96768,     1152,      453, 0x1aafd73e
+0,      97920,      97920,     1152,      448, 0xe997d8d1
+0,      99072,      99072,     1152,      429, 0x5813c034
+0,     100224,     100224,     1152,      430, 0xcd4ac57b
+0,     101376,     101376,     1152,      416, 0xe466b916
+0,     102528,     102528,     1152,      425, 0x8f67b863
+0,     103680,     103680,     1152,      418, 0xc8faccfe
+0,     104832,     104832,     1152,      397, 0x932cb515
+0,     105984,     105984,     1152,      413, 0x0a64bdfc
+0,     107136,     107136,     1152,      408, 0xa4abcbe4
+0,     108288,     108288,     1152,      405, 0xb231c336
+0,     109440,     109440,     1152,      417, 0xda6ac762
+0,     110592,     110592,     1152,      404, 0xb2fdb983
+0,     111744,     111744,     1152,      420, 0x0478c7fc
+0,     112896,     112896,     1152,      414, 0x1a3fb9fb
+0,     114048,     114048,     1152,      411, 0xfda0c1a9
+0,     115200,     115200,     1152,      390, 0xe508c2ab
+0,     116352,     116352,     1152,      399, 0x610cc9ca
+0,     117504,     117504,     1152,      379, 0x04a4b4a3
+0,     118656,     118656,     1152,      383, 0x6217b91a
+0,     119808,     119808,     1152,      360, 0x1ca3aa4a
+0,     120960,     120960,     1152,      339, 0x26dca5ce
+0,     122112,     122112,     1152,      336, 0x0292a0b0
+0,     123264,     123264,     1152,      340, 0x4a24a36d
+0,     124416,     124416,     1152,      312, 0x45fc8afd
+0,     125568,     125568,     1152,      335, 0xb563a410
+0,     126720,     126720,     1152,      346, 0x0ab4a331
+0,     127872,     127872,     1152,      334, 0x327b9cfc
+0,     129024,     129024,     1152,      336, 0x55fda599
+0,     130176,     130176,     1152,      357, 0x9e6dade5
+0,     131328,     131328,     1152,      343, 0x3bf4a84a
+0,     132480,     132480,     1152,      330, 0x52d99957
+0,     133632,     133632,     1152,      358, 0x89bda76f
+0,     134784,     134784,     1152,      349, 0x6067a31d
+0,     135936,     135936,     1152,      357, 0x34dea77f
+0,     137088,     137088,     1152,      376, 0xd001b7d8
+0,     138240,     138240,     1152,      334, 0xa81d9b6b
+0,     139392,     139392,     1152,      369, 0x1fd5ab31
+0,     140544,     140544,     1152,      359, 0x7ffbae85
+0,     141696,     141696,     1152,      368, 0xa277a108
+0,     142848,     142848,     1152,      359, 0xea6da507
+0,     144000,     144000,     1152,      369, 0x437ab164
+0,     145152,     145152,     1152,      361, 0x1a2aa959
+0,     146304,     146304,     1152,      343, 0x83cfa2e2
+0,     147456,     147456,     1152,      369, 0x8558aeb6
+0,     148608,     148608,     1152,      355, 0x4d1da64d
+0,     149760,     149760,     1152,      364, 0x0fe9b2d8
+0,     150912,     150912,     1152,      355, 0xfc98aba5
+0,     152064,     152064,     1152,      390, 0x9d25b5c4
+0,     153216,     153216,     1152,      361, 0x9fe8ab24
+0,     154368,     154368,     1152,      364, 0x03ada717
+0,     155520,     155520,     1152,      379, 0xb06eb9e2
+0,     156672,     156672,     1152,      371, 0xc3aeb45c
+0,     157824,     157824,     1152,      895, 0x86d198dc
+0,     158976,     158976,     1152,      644, 0x1f1d376a
+0,     160128,     160128,     1152,      682, 0x4da84df6
+0,     161280,     161280,     1152,      675, 0xd41543be
+0,     162432,     162432,     1152,      642, 0xd5b04211
+0,     163584,     163584,     1152,      632, 0x45da38cd
+0,     164736,     164736,     1152,      597, 0x9f1611d3
+0,     165888,     165888,     1152,      574, 0x089f215f
+0,     167040,     167040,     1152,      578, 0x90880461
+0,     168192,     168192,     1152,      566, 0x38360e79
+0,     169344,     169344,     1152,      583, 0xe62e0ab6
+0,     170496,     170496,     1152,      593, 0xa55a19f8
+0,     171648,     171648,     1152,      625, 0xbf7d1b0f
+0,     172800,     172800,     1152,      574, 0xa719176a
+0,     173952,     173952,     1152,      605, 0xf5e517ef
+0,     175104,     175104,     1152,      804, 0x3a0a81ae
+0,     176256,     176256,     1152,      699, 0x880635bd
+0,     177408,     177408,     1152,      646, 0x79052faa
+0,     178560,     178560,     1152,      634, 0x2e8d2d8e
+0,     179712,     179712,     1152,      596, 0xc8281e87
+0,     180864,     180864,     1152,      605, 0xa5e73156
+0,     182016,     182016,     1152,      588, 0x7c8b1a55
+0,     183168,     183168,     1152,      566, 0x9e710ea4
+0,     184320,     184320,     1152,      624, 0x69072d37
+0,     185472,     185472,     1152,      600, 0xe84832fc
+0,     186624,     186624,     1152,      580, 0x29fd123a
+0,     187776,     187776,     1152,      562, 0xba300d11
+0,     188928,     188928,     1152,      577, 0x8a471fc9
+0,     190080,     190080,     1152,      588, 0x94fb1954
+0,     191232,     191232,     1152,      576, 0x6d7d1bcf
+0,     192384,     192384,     1152,      697, 0xc0a13955
+0,     193536,     193536,     1152,      805, 0xe5fb8aee
+0,     194688,     194688,     1152,      673, 0x645c4b23
+0,     195840,     195840,     1152,      635, 0xd40f2820
+0,     196992,     196992,     1152,      660, 0xb3d638b8
+0,     198144,     198144,     1152,      652, 0x7c21322a
+0,     199296,     199296,     1152,      623, 0x382a2735
+0,     200448,     200448,     1152,      606, 0xb0632a69
+0,     201600,     201600,     1152,      584, 0xfaa820eb
+0,     202752,     202752,     1152,      645, 0x774327c9
+0,     203904,     203904,     1152,      654, 0x96b41a4b
+0,     205056,     205056,     1152,      660, 0x57483145
+0,     206208,     206208,     1152,      606, 0xd61716f0
+0,     207360,     207360,     1152,      637, 0x6c8526ee
+0,     208512,     208512,     1152,      624, 0xcccf1f78
+0,     209664,     209664,     1152,      640, 0x966e2d58
+0,     210816,     210816,     1152,      868, 0x6f42a03e
+0,     211968,     211968,     1152,      712, 0x10195ab2
+0,     213120,     213120,     1152,      623, 0x3b3f24a8
+0,     214272,     214272,     1152,      618, 0xfb853122
+0,     215424,     215424,     1152,      606, 0x20922909
+0,     216576,     216576,     1152,      526, 0x05defcdd
+0,     217728,     217728,     1152,      538, 0xc18ffeef
+0,     218880,     218880,     1152,      508, 0x1943eba7
+0,     220032,     220032,     1152,      497, 0xf953fbb6
+0,     221184,     221184,     1152,      513, 0x3b35f026
+0,     222336,     222336,     1152,      530, 0x705b0333
+0,     223488,     223488,     1152,      528, 0x7c5800e9
+0,     224640,     224640,     1152,      517, 0x1601fa7e
+0,     225792,     225792,     1152,      501, 0x5045f61a
+0,     226944,     226944,     1152,      520, 0x254ee65d
+0,     228096,     228096,     1152,      827, 0x29644ce4
+0,     229248,     229248,     1152,      692, 0xb9d265ee
+0,     230400,     230400,     1152,      660, 0x050233c6
+0,     231552,     231552,     1152,      631, 0x0306284e
+0,     232704,     232704,     1152,      611, 0xf9ed2079
+0,     233856,     233856,     1152,      640, 0xd1ab3363
+0,     235008,     235008,     1152,      652, 0xaebf3b5a
+0,     236160,     236160,     1152,      619, 0xc64e280b
+0,     237312,     237312,     1152,      601, 0x647d258c
+0,     238464,     238464,     1152,      574, 0x0a2b1548
+0,     239616,     239616,     1152,      570, 0xd98e11bf
+0,     240768,     240768,     1152,      611, 0x04a81e85
+0,     241920,     241920,     1152,      525, 0x108ff5ee
+0,     243072,     243072,     1152,      569, 0x9a3b1319
+0,     244224,     244224,     1152,      574, 0xdc770a8d
+0,     245376,     245376,     1152,      831, 0x5ed066c7
+0,     246528,     246528,     1152,      722, 0xa8834f8b
+0,     247680,     247680,     1152,      730, 0x71f56be1
+0,     248832,     248832,     1152,      729, 0x9653694a
+0,     249984,     249984,     1152,      750, 0xf8716eb8
+0,     251136,     251136,     1152,      695, 0x541951fa
+0,     252288,     252288,     1152,      677, 0xbf575b05
+0,     253440,     253440,     1152,      639, 0x1f74352b
+0,     254592,     254592,     1152,      647, 0x87e43a7e
+0,     255744,     255744,     1152,      613, 0x09551766
+0,     256896,     256896,     1152,      564, 0xa067162a
+0,     258048,     258048,     1152,      539, 0xf2280791
+0,     259200,     259200,     1152,      516, 0x9cfef313
+0,     260352,     260352,     1152,      527, 0x5a94088f
+0,     261504,     261504,     1152,      528, 0x71d1f32b
+0,     262656,     262656,     1152,      511, 0xaf28f38c
+0,     263808,     263808,     1152,      519, 0x47a4f3e4
+0,     264960,     264960,     1152,      519, 0x6a67f4a4
+0,     266112,     266112,     1152,      514, 0xe176e6d1
+0,     267264,     267264,     1152,      525, 0xd194edac
+0,     268416,     268416,     1152,      527, 0x6d50f7c3
+0,     269568,     269568,     1152,      508, 0x3f8d05af
+0,     270720,     270720,     1152,      517, 0x7f48ec77
+0,     271872,     271872,     1152,      468, 0x73a2d82f
+0,     273024,     273024,     1152,      457, 0xc816cf16
+0,     274176,     274176,     1152,      434, 0x9e5bc930
+0,     275328,     275328,     1152,      443, 0xde0fd171
+0,     276480,     276480,     1152,      415, 0x5800b715
+0,     277632,     277632,     1152,      420, 0xeda9d20c
+0,     278784,     278784,     1152,      416, 0x4793c017
+0,     279936,     279936,     1152,      417, 0x5a37c00e
+0,     281088,     281088,     1152,      409, 0x02deb9ed
+0,     282240,     282240,     1152,      407, 0xd8b2b127
+0,     283392,     283392,     1152,      395, 0x787fba53
+0,     284544,     284544,     1152,      389, 0x3362b2b3
+0,     285696,     285696,     1152,      388, 0xe058af5d
+0,     286848,     286848,     1152,      374, 0xe1c0ad48
+0,     288000,     288000,     1152,      390, 0xa4f8b203
+0,     289152,     289152,     1152,      382, 0xe076b693
+0,     290304,     290304,     1152,      382, 0xa19ab1d1
+0,     291456,     291456,     1152,      389, 0x614db09b
+0,     292608,     292608,     1152,      375, 0x8e3bb1a9
+0,     293760,     293760,     1152,      375, 0x455daa5f
+0,     294912,     294912,     1152,      391, 0xd938ae9f
+0,     296064,     296064,     1152,      380, 0x6cebb555
+0,     297216,     297216,     1152,      381, 0xc42faf26
+0,     298368,     298368,     1152,      364, 0x6719a5b9
+0,     299520,     299520,     1152,      352, 0xd9aaa922
+0,     300672,     300672,     1152,      372, 0xfaceaab9
+0,     301824,     301824,     1152,      369, 0x1dd0b400
+0,     302976,     302976,     1152,      338, 0x1be49de3
+0,     304128,     304128,     1152,      340, 0x7f43a4af
+0,     305280,     305280,     1152,      344, 0x8f519ec0
+0,     306432,     306432,     1152,      355, 0xdcbda935
+0,     307584,     307584,     1152,      335, 0x69299219
+0,     308736,     308736,     1152,      331, 0x1f72a77c
+0,     309888,     309888,     1152,      353, 0xe28ba583
+0,     311040,     311040,     1152,      337, 0x70b69966
+0,     312192,     312192,     1152,      361, 0xbe73a133
+0,     313344,     313344,     1152,      369, 0x300ab491
+0,     314496,     314496,     1152,      381, 0x5913bf78
+0,     315648,     315648,     1152,      372, 0x544daa11
+0,     316800,     316800,     1152,      376, 0xdc04ba2b
+0,     317952,     317952,     1152,      337, 0xc3d095f5
+0,     319104,     319104,     1152,      345, 0x306da1c1
+0,     320256,     320256,     1152,      374, 0x8297b29e
+0,     321408,     321408,     1152,      347, 0xe7f2a33e
+0,     322560,     322560,     1152,      364, 0x9a7eb40c
+0,     323712,     323712,     1152,      358, 0x3bdca87c
+0,     324864,     324864,     1152,      339, 0x9d48a314
+0,     326016,     326016,     1152,      370, 0x78a6acb1
+0,     327168,     327168,     1152,      353, 0xb876a9ca
+0,     328320,     328320,     1152,      355, 0x82eab1cf
+0,     329472,     329472,     1152,      360, 0xa8cea2a9
+0,     330624,     330624,     1152,      547, 0x6176af27
diff --git a/tests/ref/fate/movenc b/tests/ref/fate/movenc
index 845ef54..d3a86bc 100644
--- a/tests/ref/fate/movenc
+++ b/tests/ref/fate/movenc
@@ -1,28 +1,137 @@
-249e02e3645ea5ca2c74397c62c53314 3269 non-empty-moov
-3281ff664e9a06e5a03ec6ea1729696c 3721 non-empty-moov-elst
-b408a545b1963a5ea82cf37208b66548 3629 non-empty-moov-no-elst
-a66c786022280c1f69ad7c98c719fa53 4435 ismv
-176a315a5385cb2e082d863e0fb22bf1 2891 empty-moov
-10eb3fdf6ed1400a1eec50746537159f 3283 empty-moov-no-elst
-bcd4d6d22f828f1061e13f3af459644f 3115 empty-moov-no-elst-no-adjust
-176a315a5385cb2e082d863e0fb22bf1 2891 delay-moov
-1398c80f1f5fd7f8e127bb5b17311016 3203 delay-moov-elst
-ed6dd0e0fd6d0d9d1145b201674325f6 2098 delay-moov-empty-track
-7f1dabd680135708c6ff359e4ab27165 2001 delay-moov-empty-track-flush
-39d798aa11a265c7906f9e11d4f303c0 1159 empty-moov-header
+write_data len 36, time nopts, type header atom ftyp
+write_data len 2335, time nopts, type header atom -
+write_data len 788, time 1000000, type sync atom moof
+write_data len 110, time nopts, type trailer atom -
+214242e9c7c93171d2f47f5b47776559 3269 non-empty-moov
+write_data len 36, time nopts, type header atom ftyp
+write_data len 2667, time nopts, type header atom -
+write_data len 908, time 966667, type sync atom moof
+write_data len 110, time nopts, type trailer atom -
+44467d568a3cc38d414fd8ed4b2a968f 3721 non-empty-moov-elst
+write_data len 36, time nopts, type header atom ftyp
+write_data len 2575, time nopts, type header atom -
+write_data len 908, time 1000000, type sync atom moof
+write_data len 110, time nopts, type trailer atom -
+de22b98a3885f9b4b83cdd48ff46aeb9 3629 non-empty-moov-no-elst
+write_data len 20, time nopts, type header atom ftyp
+write_data len 1171, time nopts, type header atom -
+write_data len 728, time 0, type sync atom moof
+write_data len 828, time nopts, type unknown atom -
+write_data len 728, time 1013106, type sync atom moof
+write_data len 812, time nopts, type unknown atom -
+write_data len 148, time nopts, type trailer atom -
+1f37c1a8e01651e8bebcd66f00b6a226 4435 ismv
+write_data len 36, time nopts, type header atom ftyp
+write_data len 1123, time nopts, type header atom -
+write_data len 796, time 0, type sync atom moof
+write_data len 788, time 1000000, type sync atom moof
+write_data len 148, time nopts, type trailer atom -
+ed8506ebfce4c41732205ae26a4759fd 2891 empty-moov
+write_data len 36, time nopts, type header atom ftyp
+write_data len 1123, time nopts, type header atom -
+write_data len 1068, time 0, type sync atom moof
+write_data len 908, time 1000000, type sync atom moof
+write_data len 148, time nopts, type trailer atom -
+1844ee6d19fd1e6daf2655632cf26310 3283 empty-moov-no-elst
+write_data len 36, time nopts, type header atom ftyp
+write_data len 1123, time nopts, type header atom -
+write_data len 900, time -33333, type sync atom moof
+write_data len 908, time 966667, type sync atom moof
+write_data len 148, time nopts, type trailer atom -
+139b27dbe2a80c2dc088d0c755f26033 3115 empty-moov-no-elst-no-adjust
+write_data len 1159, time nopts, type header atom ftyp
+write_data len 796, time 0, type sync atom moof
+write_data len 788, time 1000000, type sync atom moof
+write_data len 148, time nopts, type trailer atom -
+ed8506ebfce4c41732205ae26a4759fd 2891 delay-moov
+write_data len 1231, time nopts, type header atom ftyp
+write_data len 916, time -33333, type sync atom moof
+write_data len 908, time 966667, type sync atom moof
+write_data len 148, time nopts, type trailer atom -
+3ece148745cd64b4428530a4d1080a2d 3203 delay-moov-elst
+write_data len 1195, time nopts, type header atom ftyp
+write_data len 836, time 0, type sync atom moof
+write_data len 67, time nopts, type trailer atom -
+9562946a369e6fb570fb2fd7aa2fe728 2098 delay-moov-empty-track
+write_data len 1195, time nopts, type header atom ftyp
+write_data len 360, time 0, type sync atom moof
+write_data len 360, time 1000000, type sync atom moof
+write_data len 86, time nopts, type trailer atom -
+4c7832b81836331c6c37155dc31d95be 2001 delay-moov-empty-track-flush
+write_data len 36, time nopts, type header atom ftyp
+write_data len 1123, time nopts, type header atom -
+b7e3c768b9094ebe2fda44979a7f8985 1159 empty-moov-header
+write_data len 796, time 0, type sync atom moof
+write_data len 788, time 1000000, type sync atom moof
 a0165f4a26a409212b0946e981bdefb9 1584 empty-moov-content
-39d798aa11a265c7906f9e11d4f303c0 1159 delay-moov-header
+write_data len 148, time nopts, type trailer atom -
+write_data len 1159, time nopts, type header atom ftyp
+b7e3c768b9094ebe2fda44979a7f8985 1159 delay-moov-header
+write_data len 796, time 0, type sync atom moof
+write_data len 788, time 1000000, type sync atom moof
 a0165f4a26a409212b0946e981bdefb9 1584 delay-moov-content
+write_data len 148, time nopts, type trailer atom -
+write_data len 24, time nopts, type header atom -
+write_data len 1123, time nopts, type header atom -
+write_data len 884, time 0, type sync atom sidx
+write_data len 876, time 1000000, type sync atom sidx
 272a474cfd2a68cc5f05b426b14a2b7d 876 empty-moov-second-frag
+write_data len 148, time nopts, type trailer atom -
+write_data len 24, time nopts, type header atom -
+write_data len 1123, time nopts, type header atom -
+write_data len 876, time 1000000, type sync atom sidx
 272a474cfd2a68cc5f05b426b14a2b7d 876 empty-moov-second-frag-discont
+write_data len 110, time nopts, type trailer atom -
+write_data len 1219, time nopts, type header atom -
+write_data len 876, time 1000000, type sync atom sidx
 272a474cfd2a68cc5f05b426b14a2b7d 876 delay-moov-second-frag-discont
-6256445b9595de78be493e0faf2bc5d7 1219 delay-moov-elst-init
+write_data len 110, time nopts, type trailer atom -
+write_data len 1219, time nopts, type header atom ftyp
+6ec3698bcc86013e0016e3d47d230363 1219 delay-moov-elst-init
+write_data len 988, time -33333, type sync atom sidx
+write_data len 996, time 966667, type sync atom sidx
 fcae8f40e015b59aabc8d4a99a759ca1 996 delay-moov-elst-second-frag
-6256445b9595de78be493e0faf2bc5d7 1219 delay-moov-elst-init-discont
+write_data len 148, time nopts, type trailer atom -
+write_data len 1219, time nopts, type header atom ftyp
+6ec3698bcc86013e0016e3d47d230363 1219 delay-moov-elst-init-discont
+write_data len 996, time 966667, type sync atom sidx
 fcae8f40e015b59aabc8d4a99a759ca1 996 delay-moov-elst-second-frag-discont
-29f875e401df0fc3026995d12872ef21 1219 delay-moov-elst-signal-init
+write_data len 110, time nopts, type trailer atom -
+write_data len 1219, time nopts, type header atom ftyp
+c3681590a292cb9ca19a5a982e530166 1219 delay-moov-elst-signal-init
+write_data len 1004, time -33333, type sync atom sidx
+write_data len 996, time 966667, type sync atom sidx
 aa5462cc0d2144f72154d9c309edb57d 996 delay-moov-elst-signal-second-frag
-29f875e401df0fc3026995d12872ef21 1219 delay-moov-elst-signal-init-discont
+write_data len 148, time nopts, type trailer atom -
+write_data len 1219, time nopts, type header atom ftyp
+c3681590a292cb9ca19a5a982e530166 1219 delay-moov-elst-signal-init-discont
+write_data len 996, time 966667, type sync atom sidx
 aa5462cc0d2144f72154d9c309edb57d 996 delay-moov-elst-signal-second-frag-discont
-6cd6085f4f0ff536acfcb77cb658eb47 4935 vfr
-6cd6085f4f0ff536acfcb77cb658eb47 4935 vfr-noduration
+write_data len 110, time nopts, type trailer atom -
+write_data len 1219, time nopts, type header atom ftyp
+write_data len 2572, time -333333, type sync atom sidx
+write_data len 996, time 5166667, type sync atom sidx
+write_data len 148, time nopts, type trailer atom -
+f12d4a0e054abcc508cc0d28cb320e57 4935 vfr
+write_data len 1219, time nopts, type header atom ftyp
+write_data len 2572, time -333333, type sync atom sidx
+write_data len 996, time 5166667, type sync atom sidx
+write_data len 148, time nopts, type trailer atom -
+f12d4a0e054abcc508cc0d28cb320e57 4935 vfr-noduration
+write_data len 1231, time nopts, type header atom ftyp
+write_data len 1500, time -333333, type sync atom moof
+write_data len 1500, time nopts, type unknown atom -
+write_data len 916, time nopts, type unknown atom -
+write_data len 1500, time 9666667, type sync atom moof
+write_data len 1500, time nopts, type unknown atom -
+write_data len 1004, time nopts, type unknown atom -
+write_data len 148, time nopts, type trailer atom -
+3c2c3f98c8a047f0ecefff07570fd457 9299 large_frag
+write_data len 1231, time nopts, type header atom ftyp
+write_data len 684, time -33333, type sync atom moof
+write_data len 504, time 800000, type boundary atom moof
+write_data len 420, time 1266667, type boundary atom moof
+write_data len 668, time 1566667, type sync atom moof
+write_data len 440, time 2233333, type boundary atom moof
+write_data len 262, time nopts, type trailer atom -
+edd19deae2b70afcf2cd744b89b7013d 4209 vfr-noduration-interleave
diff --git a/tests/ref/fate/mpeg2-field-enc b/tests/ref/fate/mpeg2-field-enc
index bf8a01a..4c288a8 100644
--- a/tests/ref/fate/mpeg2-field-enc
+++ b/tests/ref/fate/mpeg2-field-enc
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
 0,          9,          9,        1,   622080, 0xb3b66c5c
 0,         10,         10,        1,   622080, 0x088ec02b
 0,         11,         11,        1,   622080, 0x7a36db21
diff --git a/tests/ref/fate/mpeg4-packed b/tests/ref/fate/mpeg4-packed
new file mode 100644
index 0000000..4336da0
--- /dev/null
+++ b/tests/ref/fate/mpeg4-packed
@@ -0,0 +1,21 @@
+#tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 544x352
+#sar 0: 1/1
+0,          0,          0,        1,   287232, 0x17288ed1
+0,          1,          1,        1,   287232, 0x17288ed1
+0,          2,          2,        1,   287232, 0x232dfda4
+0,          3,          3,        1,   287232, 0x1e880ed6
+0,          4,          4,        1,   287232, 0x60197d73
+0,          5,          5,        1,   287232, 0xe27a4c05
+0,          6,          6,        1,   287232, 0xa588b659
+0,          7,          7,        1,   287232, 0xaa111895
+0,          8,          8,        1,   287232, 0x39ad64c0
+0,          9,          9,        1,   287232, 0x2a046b62
+0,         10,         10,        1,   287232, 0x733dea31
+0,         11,         11,        1,   287232, 0x06e38bfc
+0,         12,         12,        1,   287232, 0xcc1d2de4
+0,         13,         13,        1,   287232, 0x207a0a62
+0,         14,         14,        1,   287232, 0x9ee6289f
+0,         15,         15,        1,   287232, 0x60dedf92
diff --git a/tests/ref/fate/mpeg4-resolution-change-down-down b/tests/ref/fate/mpeg4-resolution-change-down-down
index 02fcda5..df53794 100644
--- a/tests/ref/fate/mpeg4-resolution-change-down-down
+++ b/tests/ref/fate/mpeg4-resolution-change-down-down
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   460800, d65fcc79c7eb9ebd9d88dca3ebb15bf4
 0,          1,          1,        1,   460800, 6c86b8c7e8eae3d63b21342f233fb44e
diff --git a/tests/ref/fate/mpeg4-resolution-change-down-up b/tests/ref/fate/mpeg4-resolution-change-down-up
index 37e56d8..5236115 100644
--- a/tests/ref/fate/mpeg4-resolution-change-down-up
+++ b/tests/ref/fate/mpeg4-resolution-change-down-up
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   460800, d65fcc79c7eb9ebd9d88dca3ebb15bf4
 0,          1,          1,        1,   460800, 6c86b8c7e8eae3d63b21342f233fb44e
diff --git a/tests/ref/fate/mpeg4-resolution-change-up-down b/tests/ref/fate/mpeg4-resolution-change-up-down
index 36110c3..0930cb7 100644
--- a/tests/ref/fate/mpeg4-resolution-change-up-down
+++ b/tests/ref/fate/mpeg4-resolution-change-up-down
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 400x300
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   180000, 9fc6302026cf2a2dd310646b83c5dfa1
 0,          1,          1,        1,   180000, b1b2646c8df579ddf8676bc2488411a5
diff --git a/tests/ref/fate/mpeg4-resolution-change-up-up b/tests/ref/fate/mpeg4-resolution-change-up-up
index 8d1bbcd..ba812b6 100644
--- a/tests/ref/fate/mpeg4-resolution-change-up-up
+++ b/tests/ref/fate/mpeg4-resolution-change-up-up
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 7f952fd8bd40c32197afc21e2fa66404
 0,          1,          1,        1,   152064, 5b2cc25b04d9a9d33bcf5fe480505d68
diff --git a/tests/ref/fate/msmpeg4v1 b/tests/ref/fate/msmpeg4v1
index d67a0ef..946ede9 100644
--- a/tests/ref/fate/msmpeg4v1
+++ b/tests/ref/fate/msmpeg4v1
@@ -1,4 +1,8 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x240
+#sar 0: 0/1
 0,          0,          0,        1,   126720, 0x84284323
 0,          1,          1,        1,   126720, 0x336fe236
 0,          2,          2,        1,   126720, 0x901f1299
diff --git a/tests/ref/fate/msrle-8bit b/tests/ref/fate/msrle-8bit
index 5db1c24..202b3f0 100644
--- a/tests/ref/fate/msrle-8bit
+++ b/tests/ref/fate/msrle-8bit
@@ -1,4 +1,8 @@
 #tb 0: 83333/500000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 80x48
+#sar 0: 0/1
 0,          0,          0,        1,    11520, 0xaf416a66
 0,          1,          1,        1,    11520, 0x8ab76654
 0,          2,          2,        1,    11520, 0xd22880c4
diff --git a/tests/ref/fate/mss1-pal b/tests/ref/fate/mss1-pal
new file mode 100644
index 0000000..9baffb4
--- /dev/null
+++ b/tests/ref/fate/mss1-pal
@@ -0,0 +1,25 @@
+#tb 0: 12/23
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x768
+#sar 0: 0/1
+0,          1,          1,        1,   787456, 0x9369daec
+0,          2,          2,        1,   787456, 0x1c61a5b8
+0,          3,          3,        1,   787456, 0xb9c3af1f
+0,          4,          4,        1,   787456, 0xc078bec7
+0,          5,          5,        1,   787456, 0x31aece7b
+0,          6,          6,        1,   787456, 0x060a869e
+0,          7,          7,        1,   787456, 0x12bea936
+0,          8,          8,        1,   787456, 0xb493af19
+0,          9,          9,        1,   787456, 0xc8f4b0cc
+0,         10,         10,        1,   787456, 0x21e4aad0
+0,         11,         11,        1,   787456, 0xee84b8a0
+0,         12,         12,        1,   787456, 0xcec7b254
+0,         13,         13,        1,   787456, 0x90b98f22
+0,         14,         14,        1,   787456, 0x113ae355
+0,         15,         15,        1,   787456, 0xbe1dead9
+0,         17,         17,        1,   787456, 0x81167b2e
+0,         18,         18,        1,   787456, 0xc6d67b2e
+0,         20,         20,        1,   787456, 0xe14686ce
+0,         21,         21,        1,   787456, 0xc6d67b2e
+0,         22,         22,        1,   787456, 0x3ef162f6
diff --git a/tests/ref/fate/mss2-pal b/tests/ref/fate/mss2-pal
index ae8bd6f..a2fb12f 100644
--- a/tests/ref/fate/mss2-pal
+++ b/tests/ref/fate/mss2-pal
@@ -1,3 +1,7 @@
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x48
+#sar 0: 0/1
 0,          0,          0,        0,     9216, 0xd3c106ef
 0,        100,        100,        0,     9216, 0x8871f7c2
diff --git a/tests/ref/fate/mss2-pals b/tests/ref/fate/mss2-pals
index ae8bd6f..a2fb12f 100644
--- a/tests/ref/fate/mss2-pals
+++ b/tests/ref/fate/mss2-pals
@@ -1,3 +1,7 @@
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x48
+#sar 0: 0/1
 0,          0,          0,        0,     9216, 0xd3c106ef
 0,        100,        100,        0,     9216, 0x8871f7c2
diff --git a/tests/ref/fate/mss2-rgb555 b/tests/ref/fate/mss2-rgb555
index d15b3b4..10f1f03 100644
--- a/tests/ref/fate/mss2-rgb555
+++ b/tests/ref/fate/mss2-rgb555
@@ -1,3 +1,7 @@
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x48
+#sar 0: 0/1
 0,          0,          0,        0,     6144, 0x4145b7ae
 0,        100,        100,        0,     6144, 0x3b2b38de
diff --git a/tests/ref/fate/mss2-rgb555s b/tests/ref/fate/mss2-rgb555s
index d15b3b4..10f1f03 100644
--- a/tests/ref/fate/mss2-rgb555s
+++ b/tests/ref/fate/mss2-rgb555s
@@ -1,3 +1,7 @@
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x48
+#sar 0: 0/1
 0,          0,          0,        0,     6144, 0x4145b7ae
 0,        100,        100,        0,     6144, 0x3b2b38de
diff --git a/tests/ref/fate/mss2-wmv b/tests/ref/fate/mss2-wmv
index c54cff6..d9abbb3 100644
--- a/tests/ref/fate/mss2-wmv
+++ b/tests/ref/fate/mss2-wmv
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   230400, 0x00000000
 0,          3,          3,        1,   230400, 0xaf950008
 0,          4,          4,        1,   230400, 0x8d2a0010
diff --git a/tests/ref/fate/msvideo1-16bit b/tests/ref/fate/msvideo1-16bit
index f5c0e64..d28d92e 100644
--- a/tests/ref/fate/msvideo1-16bit
+++ b/tests/ref/fate/msvideo1-16bit
@@ -1,4 +1,8 @@
 #tb 0: 33369/500000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 148x148
+#sar 0: 0/1
 0,          0,          0,        1,    65712, 0x03ff25b8
 0,          1,          1,        1,    65712, 0xfca02276
 0,          2,          2,        1,    65712, 0xd23646e4
diff --git a/tests/ref/fate/msvideo1-8bit b/tests/ref/fate/msvideo1-8bit
index 74d54e8..b271438 100644
--- a/tests/ref/fate/msvideo1-8bit
+++ b/tests/ref/fate/msvideo1-8bit
@@ -1,4 +1,8 @@
 #tb 0: 10000/300003
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    57600, 0x8c3c5ee8
 0,          1,          1,        1,    57600, 0xb79800b1
 0,          2,          2,        1,    57600, 0x54a221be
diff --git a/tests/ref/fate/mszh b/tests/ref/fate/mszh
index 4ff76ff..007fe00 100644
--- a/tests/ref/fate/mszh
+++ b/tests/ref/fate/mszh
@@ -1,2 +1,6 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x240
+#sar 0: 0/1
 0,          0,          0,        1,   253440, 0x94af61e5
diff --git a/tests/ref/fate/mts2 b/tests/ref/fate/mts2
new file mode 100644
index 0000000..778fdfb
--- /dev/null
+++ b/tests/ref/fate/mts2
@@ -0,0 +1,133 @@
+#tb 0: 12/181
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1172x852
+#sar 0: 0/1
+0,          0,          0,        1,  2995632, 0xd99bcd57
+0,          3,          3,        1,  2995632, 0xd99bcd57
+0,          4,          4,        1,  2995632, 0xd99bcd57
+0,          5,          5,        1,  2995632, 0xd99bcd57
+0,          6,          6,        1,  2995632, 0xd99bcd57
+0,          7,          7,        1,  2995632, 0xd99bcd57
+0,          8,          8,        1,  2995632, 0xd99bcd57
+0,          9,          9,        1,  2995632, 0xd99bcd57
+0,         10,         10,        1,  2995632, 0xd99bcd57
+0,         11,         11,        1,  2995632, 0xd99bcd57
+0,         12,         12,        1,  2995632, 0xd99bcd57
+0,         13,         13,        1,  2995632, 0xd99bcd57
+0,         14,         14,        1,  2995632, 0xd99bcd57
+0,         15,         15,        1,  2995632, 0xd99bcd57
+0,         16,         16,        1,  2995632, 0xd99bcd57
+0,         17,         17,        1,  2995632, 0xd99bcd57
+0,         18,         18,        1,  2995632, 0xd99bcd57
+0,         19,         19,        1,  2995632, 0xd99bcd57
+0,         20,         20,        1,  2995632, 0xd99bcd57
+0,         21,         21,        1,  2995632, 0xd99bcd57
+0,         22,         22,        1,  2995632, 0xd99bcd57
+0,         23,         23,        1,  2995632, 0xd99bcd57
+0,         24,         24,        1,  2995632, 0xd99bcd57
+0,         25,         25,        1,  2995632, 0xd99bcd57
+0,         26,         26,        1,  2995632, 0xd99bcd57
+0,         27,         27,        1,  2995632, 0xd99bcd57
+0,         28,         28,        1,  2995632, 0xd99bcd57
+0,         29,         29,        1,  2995632, 0xd99bcd57
+0,         30,         30,        1,  2995632, 0xbeb35375
+0,         31,         31,        1,  2995632, 0xbeb35375
+0,         32,         32,        1,  2995632, 0xbeb35375
+0,         33,         33,        1,  2995632, 0xbeb35375
+0,         34,         34,        1,  2995632, 0xbeb35375
+0,         35,         35,        1,  2995632, 0xbeb35375
+0,         36,         36,        1,  2995632, 0xbeb35375
+0,         37,         37,        1,  2995632, 0xcaae4108
+0,         38,         38,        1,  2995632, 0xcaae4108
+0,         39,         39,        1,  2995632, 0xcaae4108
+0,         40,         40,        1,  2995632, 0xcaae4108
+0,         41,         41,        1,  2995632, 0xcaae4108
+0,         42,         42,        1,  2995632, 0xcaae4108
+0,         43,         43,        1,  2995632, 0x8aa38ce0
+0,         44,         44,        1,  2995632, 0x8aa38ce0
+0,         45,         45,        1,  2995632, 0x8aa38ce0
+0,         46,         46,        1,  2995632, 0x8aa38ce0
+0,         47,         47,        1,  2995632, 0x8aa38ce0
+0,         48,         48,        1,  2995632, 0x8aa38ce0
+0,         49,         49,        1,  2995632, 0x05885d30
+0,         50,         50,        1,  2995632, 0xd3eee8e8
+0,         51,         51,        1,  2995632, 0x0b82ea84
+0,         52,         52,        1,  2995632, 0x0b82ea84
+0,         53,         53,        1,  2995632, 0x19f32c5e
+0,         54,         54,        1,  2995632, 0x19f32c5e
+0,         55,         55,        1,  2995632, 0x19f32c5e
+0,         56,         56,        1,  2995632, 0x478b455c
+0,         57,         57,        1,  2995632, 0x08256940
+0,         58,         58,        1,  2995632, 0x08256940
+0,         59,         59,        1,  2995632, 0x08256940
+0,         60,         60,        1,  2995632, 0x188c88fc
+0,         61,         61,        1,  2995632, 0x7ff65403
+0,         62,         62,        1,  2995632, 0xef8686db
+0,         63,         63,        1,  2995632, 0x8ca34321
+0,         64,         64,        1,  2995632, 0x722e18d1
+0,         65,         65,        1,  2995632, 0x722e18d1
+0,         66,         66,        1,  2995632, 0x0f0c1574
+0,         67,         67,        1,  2995632, 0x0f0c1574
+0,         68,         68,        1,  2995632, 0x0f0c1574
+0,         69,         69,        1,  2995632, 0x440c5180
+0,         70,         70,        1,  2995632, 0x440c5180
+0,         71,         71,        1,  2995632, 0x440c5180
+0,         72,         72,        1,  2995632, 0x440c5180
+0,         73,         73,        1,  2995632, 0x440c5180
+0,         74,         74,        1,  2995632, 0x440c5180
+0,         75,         75,        1,  2995632, 0x440c5180
+0,         76,         76,        1,  2995632, 0x440c5180
+0,         77,         77,        1,  2995632, 0x50b9656c
+0,         78,         78,        1,  2995632, 0x50b9656c
+0,         79,         79,        1,  2995632, 0x50b9656c
+0,         80,         80,        1,  2995632, 0x50b9656c
+0,         81,         81,        1,  2995632, 0x29c17deb
+0,         82,         82,        1,  2995632, 0x6f868d8a
+0,         83,         83,        1,  2995632, 0x2ea88d55
+0,         84,         84,        1,  2995632, 0xe0208c8d
+0,         85,         85,        1,  2995632, 0x25084a8f
+0,         86,         86,        1,  2995632, 0xd0e3bddd
+0,         87,         87,        1,  2995632, 0xc9c3e0ff
+0,         88,         88,        1,  2995632, 0xcbefe0b1
+0,         89,         89,        1,  2995632, 0xd7b0e00d
+0,         90,         90,        1,  2995632, 0x2dc9dff8
+0,         91,         91,        1,  2995632, 0x1ea9a835
+0,         93,         93,        1,  2995632, 0x9be91cc7
+0,         94,         94,        1,  2995632, 0x27c31d09
+0,         95,         95,        1,  2995632, 0xc4d65c0c
+0,         96,         96,        1,  2995632, 0xc4d65c0c
+0,         97,         97,        1,  2995632, 0xc4d65c0c
+0,         98,         98,        1,  2995632, 0xc4d65c0c
+0,         99,         99,        1,  2995632, 0xc4d65c0c
+0,        100,        100,        1,  2995632, 0xceb7bde7
+0,        101,        101,        1,  2995632, 0xfbace8b0
+0,        102,        102,        1,  2995632, 0x18ab6b35
+0,        103,        103,        1,  2995632, 0x18ab6b35
+0,        104,        104,        1,  2995632, 0x18ab6b35
+0,        105,        105,        1,  2995632, 0x18ab6b35
+0,        106,        106,        1,  2995632, 0x18ab6b35
+0,        107,        107,        1,  2995632, 0x18ab6b35
+0,        108,        108,        1,  2995632, 0x18ab6b35
+0,        109,        109,        1,  2995632, 0x18ab6b35
+0,        110,        110,        1,  2995632, 0x18ab6b35
+0,        111,        111,        1,  2995632, 0x18ab6b35
+0,        112,        112,        1,  2995632, 0x18ab6b35
+0,        113,        113,        1,  2995632, 0x18ab6b35
+0,        114,        114,        1,  2995632, 0x18ab6b35
+0,        115,        115,        1,  2995632, 0x18ab6b35
+0,        116,        116,        1,  2995632, 0x18ab6b35
+0,        117,        117,        1,  2995632, 0x18ab6b35
+0,        118,        118,        1,  2995632, 0x18ab6b35
+0,        119,        119,        1,  2995632, 0x18ab6b35
+0,        120,        120,        1,  2995632, 0x18ab6b35
+0,        121,        121,        1,  2995632, 0x18ab6b35
+0,        122,        122,        1,  2995632, 0x18ab6b35
+0,        123,        123,        1,  2995632, 0x18ab6b35
+0,        124,        124,        1,  2995632, 0x18ab6b35
+0,        125,        125,        1,  2995632, 0x18ab6b35
+0,        126,        126,        1,  2995632, 0x18ab6b35
+0,        127,        127,        1,  2995632, 0x18ab6b35
+0,        128,        128,        1,  2995632, 0x18ab6b35
+0,        129,        129,        1,  2995632, 0x18ab6b35
+0,        130,        130,        1,  2995632, 0x68f6d0e7
diff --git a/tests/ref/fate/mts2-xesc b/tests/ref/fate/mts2-xesc
new file mode 100644
index 0000000..6d40741
--- /dev/null
+++ b/tests/ref/fate/mts2-xesc
@@ -0,0 +1,22 @@
+#tb 0: 12/185
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1368x768
+#sar 0: 0/1
+0,          0,          0,        1,  3151872, 0x90aa1943
+0,          3,          3,        1,  3151872, 0xbbe670de
+0,          4,          4,        1,  3151872, 0x818d8c1c
+0,          5,          5,        1,  3151872, 0xc2cf510d
+0,          6,          6,        1,  3151872, 0xff904cda
+0,          7,          7,        1,  3151872, 0xc843fce8
+0,          8,          8,        1,  3151872, 0xbfc24e6e
+0,          9,          9,        1,  3151872, 0x5eea45bc
+0,         10,         10,        1,  3151872, 0x86634b52
+0,         11,         11,        1,  3151872, 0x86634b52
+0,         12,         12,        1,  3151872, 0x86634b52
+0,         13,         13,        1,  3151872, 0x86634b52
+0,         14,         14,        1,  3151872, 0x86634b52
+0,         15,         15,        1,  3151872, 0x86634b52
+0,         16,         16,        1,  3151872, 0x86634b52
+0,         17,         17,        1,  3151872, 0xaf542632
+0,         18,         18,        1,  3151872, 0x8f16cdaf
diff --git a/tests/ref/fate/mtv b/tests/ref/fate/mtv
index 9e898ff..81711f7 100644
--- a/tests/ref/fate/mtv
+++ b/tests/ref/fate/mtv
@@ -1,6 +1,14 @@
 #extradata 0:        9, 0x116c033a
 #tb 0: 1/16
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 96x64
+#sar 0: 0/1
 #tb 1: 1/44100
+#media_type 1: audio
+#codec_id 1: mp3
+#sample_rate 1: 44100
+#channel_layout 1: 3
 0,          0,          0,        1,    12288, 0xc2258ebc
 1,          0,          0,     1152,      417, 0xae1cc66a
 1,       1152,       1152,     1152,      418, 0xdc3ec850
diff --git a/tests/ref/fate/mv-mvc1 b/tests/ref/fate/mv-mvc1
index 073c95a..5327af0 100644
--- a/tests/ref/fate/mv-mvc1
+++ b/tests/ref/fate/mv-mvc1
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 384x288
+#sar 0: 0/1
 0,          0,          0,        1,   221184, 0x340ab080
 0,          1,          1,        1,   221184, 0xc21105a0
 0,          2,          2,        1,   221184, 0xa7482ab3
diff --git a/tests/ref/fate/mv-mvc2 b/tests/ref/fate/mv-mvc2
index 99acdc0..7639f3d 100644
--- a/tests/ref/fate/mv-mvc2
+++ b/tests/ref/fate/mv-mvc2
@@ -1,4 +1,8 @@
 #tb 0: 1/60
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 168x188
+#sar 0: 1/1
 0,          0,          0,        1,   126336, 0xb50e8bb0
 0,          1,          1,        1,   126336, 0xdc260cfa
 0,          2,          2,        1,   126336, 0x2762f0d9
diff --git a/tests/ref/fate/mv-sgirle b/tests/ref/fate/mv-sgirle
index 60aff0a..3f5de2b 100644
--- a/tests/ref/fate/mv-sgirle
+++ b/tests/ref/fate/mv-sgirle
@@ -1,4 +1,8 @@
 #tb 0: 1/4
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 500x375
+#sar 0: 1/1
 0,          0,          0,        1,   187500, 0xf2c26a39
 0,          1,          1,        1,   187500, 0xf65e6ea5
 0,          2,          2,        1,   187500, 0x804f78d0
diff --git a/tests/ref/fate/mxf-demux b/tests/ref/fate/mxf-demux
index 3d9a2dc..66dea10 100644
--- a/tests/ref/fate/mxf-demux
+++ b/tests/ref/fate/mxf-demux
@@ -1,6 +1,14 @@
 #extradata 0:       18, 0x0b150244
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: mpeg4
+#dimensions 0: 352x288
+#sar 0: 16/11
 #tb 1: 1/8000
+#media_type 1: audio
+#codec_id 1: pcm_alaw
+#sample_rate 1: 8000
+#channel_layout 1: 3
 0,          0, -9223372036854775808,        1,     8468, 0xc0855553
 1,          0,          0,    16000,    32000, 0x479155e6
 0,          1, -9223372036854775808,        1,     3814, 0xa10783b4, F=0x0
diff --git a/tests/ref/fate/mxf-essencegroup-demux b/tests/ref/fate/mxf-essencegroup-demux
index 8420db9..8045cdd 100644
--- a/tests/ref/fate/mxf-essencegroup-demux
+++ b/tests/ref/fate/mxf-essencegroup-demux
@@ -1,2 +1,6 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 0,          0,          0,        1,  2080768, 0xe99233d9
diff --git a/tests/ref/fate/mxpeg b/tests/ref/fate/mxpeg
index 90af90f..9c5c1fa 100644
--- a/tests/ref/fate/mxpeg
+++ b/tests/ref/fate/mxpeg
@@ -1,4 +1,8 @@
 #tb 0: 4/63
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x960
+#sar 0: 0/1
 0,          0,          0,        1,  1843200, 0x868a4e64
 0,          4,          4,        1,  1843200, 0x8dda4373
 0,          6,          6,        1,  1843200, 0xfcde3afc
diff --git a/tests/ref/fate/nc-demux b/tests/ref/fate/nc-demux
index 98318ac..006addc 100644
--- a/tests/ref/fate/nc-demux
+++ b/tests/ref/fate/nc-demux
@@ -1,93 +1,97 @@
 #extradata 0:       19, 0x1afd0446
 #tb 0: 1/100
-0,          0, -9223372036854775808,        1,    19787, 0x75e463f3
-0,          1, -9223372036854775808,        1,    11913, 0x0f429c34, F=0x0
-0,          2, -9223372036854775808,        1,    14225, 0xbd3c704c, F=0x0
-0,          3, -9223372036854775808,        1,    10357, 0xbf232393, F=0x0
-0,          4, -9223372036854775808,        1,     9595, 0xf565d39e, F=0x0
-0,          5, -9223372036854775808,        1,     9262, 0x2afd6ce0, F=0x0
-0,          6, -9223372036854775808,        1,    12214, 0x6ae81d9b, F=0x0
-0,          7, -9223372036854775808,        1,    13920, 0x31b5b307, F=0x0
-0,          8, -9223372036854775808,        1,    10164, 0x141eca4e, F=0x0
-0,          9, -9223372036854775808,        1,     9516, 0xd5f2c42b, F=0x0
-0,         10, -9223372036854775808,        1,    10006, 0x80850a76, F=0x0
-0,         11, -9223372036854775808,        1,    11791, 0x10bc2dcd, F=0x0
-0,         12, -9223372036854775808,        1,    13756, 0xda1fee08, F=0x0
-0,         13, -9223372036854775808,        1,    10452, 0xbb3d62b0, F=0x0
-0,         14, -9223372036854775808,        1,     9171, 0x64ae10f6, F=0x0
-0,         15, -9223372036854775808,        1,     8816, 0x31ad8fcb, F=0x0
-0,         16, -9223372036854775808,        1,    13168, 0xea1085ac, F=0x0
-0,         17, -9223372036854775808,        1,    12797, 0x25143d22, F=0x0
-0,         18, -9223372036854775808,        1,    11324, 0x3a54b38e, F=0x0
-0,         19, -9223372036854775808,        1,     9173, 0x8b2bf552, F=0x0
-0,         20, -9223372036854775808,        1,     9247, 0x2e87226b, F=0x0
-0,         21, -9223372036854775808,        1,    14140, 0x1063786c, F=0x0
-0,         22, -9223372036854775808,        1,    14437, 0xde123a17, F=0x0
-0,         23, -9223372036854775808,        1,    11938, 0x3f1168f4, F=0x0
-0,         24, -9223372036854775808,        1,    11966, 0xdd6786ec, F=0x0
-0,         25, -9223372036854775808,        1,    13213, 0x8ab27c58, F=0x0
-0,         26, -9223372036854775808,        1,    11843, 0x90415d8b, F=0x0
-0,         27, -9223372036854775808,        1,    13345, 0x3c0e1793, F=0x0
-0,         28, -9223372036854775808,        1,     9977, 0x74fc7f4b, F=0x0
-0,         29, -9223372036854775808,        1,     9158, 0x0b5426a5, F=0x0
-0,         30, -9223372036854775808,        1,    12715, 0x0035d569, F=0x0
-0,         31, -9223372036854775808,        1,    19944, 0xe2887ba8
-0,         32, -9223372036854775808,        1,    12762, 0xb0f17939, F=0x0
-0,         33, -9223372036854775808,        1,    10260, 0x182b27aa, F=0x0
-0,         34, -9223372036854775808,        1,     7405, 0x227fe9bf, F=0x0
-0,         35, -9223372036854775808,        1,    13317, 0x1a678c62, F=0x0
-0,         36, -9223372036854775808,        1,    11304, 0x3277af6d, F=0x0
-0,         37, -9223372036854775808,        1,    13291, 0xe267616a, F=0x0
-0,         38, -9223372036854775808,        1,     8975, 0xe7eeacea, F=0x0
-0,         39, -9223372036854775808,        1,     8473, 0x8bb1cbff, F=0x0
-0,         40, -9223372036854775808,        1,    13878, 0xfd3d55bb, F=0x0
-0,         41, -9223372036854775808,        1,    11278, 0x61c7c55e, F=0x0
-0,         42, -9223372036854775808,        1,    13785, 0x2acbf88f, F=0x0
-0,         43, -9223372036854775808,        1,     9521, 0x99e2d065, F=0x0
-0,         44, -9223372036854775808,        1,     9340, 0xe5c96510, F=0x0
-0,         45, -9223372036854775808,        1,    12777, 0x4c3c7844, F=0x0
-0,         46, -9223372036854775808,        1,    10685, 0x39e0f42e, F=0x0
-0,         47, -9223372036854775808,        1,    14237, 0x9398d07f, F=0x0
-0,         48, -9223372036854775808,        1,     9021, 0x3343c7ec, F=0x0
-0,         49, -9223372036854775808,        1,     9327, 0xad489e86, F=0x0
-0,         50, -9223372036854775808,        1,    13507, 0xb1344f1c, F=0x0
-0,         51, -9223372036854775808,        1,    10199, 0x9a8868bf, F=0x0
-0,         52, -9223372036854775808,        1,    14535, 0xddb13f41, F=0x0
-0,         53, -9223372036854775808,        1,     8773, 0x3d8b6a79, F=0x0
-0,         54, -9223372036854775808,        1,    16084, 0x5d915de4, F=0x0
-0,         55, -9223372036854775808,        1,     9156, 0x5cb08a6a, F=0x0
-0,         56, -9223372036854775808,        1,    15027, 0xc23b1dc8, F=0x0
-0,         57, -9223372036854775808,        1,     8240, 0xd6d3526c, F=0x0
-0,         58, -9223372036854775808,        1,     8720, 0x439c43bf, F=0x0
-0,         59, -9223372036854775808,        1,    13684, 0x18fc82f0, F=0x0
-0,         60, -9223372036854775808,        1,     8829, 0xa3ebeb30, F=0x0
-0,         61, -9223372036854775808,        1,    14650, 0x99e8678c, F=0x0
-0,         62, -9223372036854775808,        1,    19626, 0x80a7ee5c
-0,         63, -9223372036854775808,        1,     7762, 0x7c209a12, F=0x0
-0,         64, -9223372036854775808,        1,    13636, 0xc89c1aa3, F=0x0
-0,         65, -9223372036854775808,        1,     8337, 0x749bf76a, F=0x0
-0,         66, -9223372036854775808,        1,    15098, 0xc98bc6dc, F=0x0
-0,         67, -9223372036854775808,        1,     9070, 0xcd4cf7f1, F=0x0
-0,         68, -9223372036854775808,        1,     8269, 0x90e95d54, F=0x0
-0,         69, -9223372036854775808,        1,    12672, 0x034888d0, F=0x0
-0,         70, -9223372036854775808,        1,     7519, 0x6c089672, F=0x0
-0,         71, -9223372036854775808,        1,    14439, 0x5d2478b9, F=0x0
-0,         72, -9223372036854775808,        1,     6928, 0x98fbaa67, F=0x0
-0,         73, -9223372036854775808,        1,     8735, 0x07643f1e, F=0x0
-0,         74, -9223372036854775808,        1,    13522, 0x55034cdb, F=0x0
-0,         75, -9223372036854775808,        1,     7807, 0xf5983103, F=0x0
-0,         76, -9223372036854775808,        1,    14484, 0xfc9cf260, F=0x0
-0,         77, -9223372036854775808,        1,     7193, 0x170a0fa1, F=0x0
-0,         78, -9223372036854775808,        1,     9444, 0x6f9be36f, F=0x0
-0,         79, -9223372036854775808,        1,    12598, 0x69b7609d, F=0x0
-0,         80, -9223372036854775808,        1,     7650, 0x1abaec9e, F=0x0
-0,         81, -9223372036854775808,        1,    15162, 0x2a87f723, F=0x0
-0,         82, -9223372036854775808,        1,     7752, 0xcca248aa, F=0x0
-0,         83, -9223372036854775808,        1,     9085, 0x1ca7d7e5, F=0x0
-0,         84, -9223372036854775808,        1,    13187, 0xababcc64, F=0x0
-0,         85, -9223372036854775808,        1,     7968, 0x64a28f46, F=0x0
-0,         86, -9223372036854775808,        1,    15474, 0xf34c587c, F=0x0
-0,         87, -9223372036854775808,        1,     8615, 0x61301034, F=0x0
-0,         88, -9223372036854775808,        1,    14129, 0x42c88bea, F=0x0
-0,         89, -9223372036854775808,        1,     7223, 0x675d7500, F=0x0
-0,         90, -9223372036854775808,        1,     3072, 0x4cb6254c, F=0x0
+#media_type 0: video
+#codec_id 0: mpeg4
+#dimensions 0: 720x576
+#sar 0: 1/1
+0,          0,          0,        1,    19787, 0x75e463f3
+0,          1,          1,        1,    11913, 0x0f429c34, F=0x0
+0,          2,          2,        1,    14225, 0xbd3c704c, F=0x0
+0,          3,          3,        1,    10357, 0xbf232393, F=0x0
+0,          4,          4,        1,     9595, 0xf565d39e, F=0x0
+0,          5,          5,        1,     9262, 0x2afd6ce0, F=0x0
+0,          6,          6,        1,    12214, 0x6ae81d9b, F=0x0
+0,          7,          7,        1,    13920, 0x31b5b307, F=0x0
+0,          8,          8,        1,    10164, 0x141eca4e, F=0x0
+0,          9,          9,        1,     9516, 0xd5f2c42b, F=0x0
+0,         10,         10,        1,    10006, 0x80850a76, F=0x0
+0,         11,         11,        1,    11791, 0x10bc2dcd, F=0x0
+0,         12,         12,        1,    13756, 0xda1fee08, F=0x0
+0,         13,         13,        1,    10452, 0xbb3d62b0, F=0x0
+0,         14,         14,        1,     9171, 0x64ae10f6, F=0x0
+0,         15,         15,        1,     8816, 0x31ad8fcb, F=0x0
+0,         16,         16,        1,    13168, 0xea1085ac, F=0x0
+0,         17,         17,        1,    12797, 0x25143d22, F=0x0
+0,         18,         18,        1,    11324, 0x3a54b38e, F=0x0
+0,         19,         19,        1,     9173, 0x8b2bf552, F=0x0
+0,         20,         20,        1,     9247, 0x2e87226b, F=0x0
+0,         21,         21,        1,    14140, 0x1063786c, F=0x0
+0,         22,         22,        1,    14437, 0xde123a17, F=0x0
+0,         23,         23,        1,    11938, 0x3f1168f4, F=0x0
+0,         24,         24,        1,    11966, 0xdd6786ec, F=0x0
+0,         25,         25,        1,    13213, 0x8ab27c58, F=0x0
+0,         26,         26,        1,    11843, 0x90415d8b, F=0x0
+0,         27,         27,        1,    13345, 0x3c0e1793, F=0x0
+0,         28,         28,        1,     9977, 0x74fc7f4b, F=0x0
+0,         29,         29,        1,     9158, 0x0b5426a5, F=0x0
+0,         30,         30,        1,    12715, 0x0035d569, F=0x0
+0,         31,         31,        1,    19944, 0xe2887ba8
+0,         32,         32,        1,    12762, 0xb0f17939, F=0x0
+0,         33,         33,        1,    10260, 0x182b27aa, F=0x0
+0,         34,         34,        1,     7405, 0x227fe9bf, F=0x0
+0,         35,         35,        1,    13317, 0x1a678c62, F=0x0
+0,         36,         36,        1,    11304, 0x3277af6d, F=0x0
+0,         37,         37,        1,    13291, 0xe267616a, F=0x0
+0,         38,         38,        1,     8975, 0xe7eeacea, F=0x0
+0,         39,         39,        1,     8473, 0x8bb1cbff, F=0x0
+0,         40,         40,        1,    13878, 0xfd3d55bb, F=0x0
+0,         41,         41,        1,    11278, 0x61c7c55e, F=0x0
+0,         42,         42,        1,    13785, 0x2acbf88f, F=0x0
+0,         43,         43,        1,     9521, 0x99e2d065, F=0x0
+0,         44,         44,        1,     9340, 0xe5c96510, F=0x0
+0,         45,         45,        1,    12777, 0x4c3c7844, F=0x0
+0,         46,         46,        1,    10685, 0x39e0f42e, F=0x0
+0,         47,         47,        1,    14237, 0x9398d07f, F=0x0
+0,         48,         48,        1,     9021, 0x3343c7ec, F=0x0
+0,         49,         49,        1,     9327, 0xad489e86, F=0x0
+0,         50,         50,        1,    13507, 0xb1344f1c, F=0x0
+0,         51,         51,        1,    10199, 0x9a8868bf, F=0x0
+0,         52,         52,        1,    14535, 0xddb13f41, F=0x0
+0,         53,         53,        1,     8773, 0x3d8b6a79, F=0x0
+0,         54,         54,        1,    16084, 0x5d915de4, F=0x0
+0,         55,         55,        1,     9156, 0x5cb08a6a, F=0x0
+0,         56,         56,        1,    15027, 0xc23b1dc8, F=0x0
+0,         57,         57,        1,     8240, 0xd6d3526c, F=0x0
+0,         58,         58,        1,     8720, 0x439c43bf, F=0x0
+0,         59,         59,        1,    13684, 0x18fc82f0, F=0x0
+0,         60,         60,        1,     8829, 0xa3ebeb30, F=0x0
+0,         61,         61,        1,    14650, 0x99e8678c, F=0x0
+0,         62,         62,        1,    19626, 0x80a7ee5c
+0,         63,         63,        1,     7762, 0x7c209a12, F=0x0
+0,         64,         64,        1,    13636, 0xc89c1aa3, F=0x0
+0,         65,         65,        1,     8337, 0x749bf76a, F=0x0
+0,         66,         66,        1,    15098, 0xc98bc6dc, F=0x0
+0,         67,         67,        1,     9070, 0xcd4cf7f1, F=0x0
+0,         68,         68,        1,     8269, 0x90e95d54, F=0x0
+0,         69,         69,        1,    12672, 0x034888d0, F=0x0
+0,         70,         70,        1,     7519, 0x6c089672, F=0x0
+0,         71,         71,        1,    14439, 0x5d2478b9, F=0x0
+0,         72,         72,        1,     6928, 0x98fbaa67, F=0x0
+0,         73,         73,        1,     8735, 0x07643f1e, F=0x0
+0,         74,         74,        1,    13522, 0x55034cdb, F=0x0
+0,         75,         75,        1,     7807, 0xf5983103, F=0x0
+0,         76,         76,        1,    14484, 0xfc9cf260, F=0x0
+0,         77,         77,        1,     7193, 0x170a0fa1, F=0x0
+0,         78,         78,        1,     9444, 0x6f9be36f, F=0x0
+0,         79,         79,        1,    12598, 0x69b7609d, F=0x0
+0,         80,         80,        1,     7650, 0x1abaec9e, F=0x0
+0,         81,         81,        1,    15162, 0x2a87f723, F=0x0
+0,         82,         82,        1,     7752, 0xcca248aa, F=0x0
+0,         83,         83,        1,     9085, 0x1ca7d7e5, F=0x0
+0,         84,         84,        1,    13187, 0xababcc64, F=0x0
+0,         85,         85,        1,     7968, 0x64a28f46, F=0x0
+0,         86,         86,        1,    15474, 0xf34c587c, F=0x0
+0,         87,         87,        1,     8615, 0x61301034, F=0x0
+0,         88,         88,        1,    14129, 0x42c88bea, F=0x0
+0,         89,         89,        1,     7223, 0x675d7500, F=0x0
+0,         90,         90,        1,     3072, 0x4cb6254c, F=0x0
diff --git a/tests/ref/fate/nsv-demux b/tests/ref/fate/nsv-demux
index 0ad08b1..7b9c000 100644
--- a/tests/ref/fate/nsv-demux
+++ b/tests/ref/fate/nsv-demux
@@ -1,5 +1,13 @@
 #tb 0: 1001/15000
+#media_type 0: video
+#codec_id 0: vp3
+#dimensions 0: 160x112
+#sar 0: 0/1
 #tb 1: 1/30000000
+#media_type 1: audio
+#codec_id 1: mp3
+#sample_rate 1: 11025
+#channel_layout 1: 4
 0,          0,          0,        1,       12, 0x1396035f
 0,          1,          1,        1,       24, 0x8ab80ac7, F=0x0
 0,          2,          2,        1,      208, 0x1de1603e, F=0x0
diff --git a/tests/ref/fate/nuv-rtjpeg b/tests/ref/fate/nuv-rtjpeg
index 96ead33..e4a5be6 100644
--- a/tests/ref/fate/nuv-rtjpeg
+++ b/tests/ref/fate/nuv-rtjpeg
@@ -1,4 +1,8 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 1/1
 0,          4,          4,        1,   460800, 0x54aedafe
 0,          5,          5,        1,   460800, 0xb7aa8b56
 0,          6,          6,        1,   460800, 0x283ea3b5
diff --git a/tests/ref/fate/nuv-rtjpeg-fh b/tests/ref/fate/nuv-rtjpeg-fh
index b2e04cb..0d50b44 100644
--- a/tests/ref/fate/nuv-rtjpeg-fh
+++ b/tests/ref/fate/nuv-rtjpeg-fh
@@ -1,4 +1,8 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x288
+#sar 0: 1/1
 0,         80,         80,        1,   221184, 0xdaf54f83
 0,         82,         82,        1,   221184, 0xeea3e3b4
 0,         83,         83,        1,   221184, 0x5f1a8525
diff --git a/tests/ref/fate/oggopus-demux b/tests/ref/fate/oggopus-demux
new file mode 100644
index 0000000..4621af6
--- /dev/null
+++ b/tests/ref/fate/oggopus-demux
@@ -0,0 +1,47 @@
+#extradata 0:       19, 0x399c0471
+#tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: opus
+#sample_rate 0: 48000
+#channel_layout 0: 3
+0,       -356,       -356,      960,      402, 0x89b1c40f
+0,        604,        604,      960,      216, 0x7bf97146
+0,       1564,       1564,      960,      215, 0x6cb86d8b
+0,       2524,       2524,      960,      218, 0x9cfd691c
+0,       3484,       3484,      960,      218, 0xd7fe6a94
+0,       4444,       4444,      960,      194, 0x35735de6
+0,       5404,       5404,      960,      216, 0x3ee6705a
+0,       6364,       6364,      960,      218, 0x67eb6cb1
+0,       7324,       7324,      960,      218, 0x32d0700d
+0,       8284,       8284,      960,      219, 0xcb7f6c60
+0,       9244,       9244,      960,      218, 0x9c866b33
+0,      10204,      10204,      960,      217, 0xfe3e6a53
+0,      11164,      11164,      960,      218, 0x13586833
+0,      12124,      12124,      960,      222, 0xbcb2669e
+0,      13084,      13084,      960,      218, 0x8dfc6e33
+0,      14044,      14044,      960,      217, 0xf5957051
+0,      15004,      15004,      960,      210, 0xed126e6b
+0,      15964,      15964,      960,      216, 0xbf947249
+0,      16924,      16924,      960,      203, 0x6c7e680a
+0,      17884,      17884,      960,      209, 0xf78f6af4
+0,      18844,      18844,      960,      217, 0xd60c684d
+0,      19804,      19804,      960,      218, 0x89056a7a
+0,      20764,      20764,      960,      219, 0x0bc674ad
+0,      21724,      21724,      960,      217, 0xb1d86d1a
+0,      22684,      22684,      960,      220, 0x433d685a
+0,      23644,      23644,      960,      364, 0x0c88be84
+0,      24604,      24604,      960,      221, 0x804a733d
+0,      25564,      25564,      960,      215, 0x6e9d6e9b
+0,      26524,      26524,      960,      215, 0x63016a83
+0,      27484,      27484,      960,      218, 0xf9a46fbe
+0,      28444,      28444,      960,      216, 0xa0d66c08
+0,      29404,      29404,      960,      216, 0xa2ca6d0a
+0,      30364,      30364,      960,      216, 0xf50e6f1d
+0,      31324,      31324,      960,      215, 0x6aaa70b6
+0,      32284,      32284,      960,      219, 0x7ceb6ba0
+0,      33244,      33244,      960,      220, 0x398d6ca9
+0,      34204,      34204,      960,      218, 0x7bd06ed5
+0,      35164,      35164,      960,      219, 0xe2906c62
+0,      36124,      36124,      960,      217, 0xcf316ba1
+0,      37084,      37084,      960,      217, 0x470b6eea
+0,      38044,      38044,      356,      359, 0x36c2a18a, S=1,       10, 0x0232005e
diff --git a/tests/ref/fate/oggvp8-demux b/tests/ref/fate/oggvp8-demux
index 96beb8c..fc686d4 100644
--- a/tests/ref/fate/oggvp8-demux
+++ b/tests/ref/fate/oggvp8-demux
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: vp8
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,     5014, 0x4798fa33
 0,          1,          1,        1,      822, 0x596486c5, F=0x0
 0,          2,          2,        1,      840, 0xf06490ba, F=0x0
diff --git a/tests/ref/fate/on2avc b/tests/ref/fate/on2avc
index ac08dae..2125cc6 100644
--- a/tests/ref/fate/on2avc
+++ b/tests/ref/fate/on2avc
@@ -1,4 +1,8 @@
 #tb 0: 1/16000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 16000
+#channel_layout 0: 4
 0,          0,          0,     1024,     2048, 0x00000000
 0,       1024,       1024,     1024,     2048, 0x96ee1301
 0,       2048,       2048,     1024,     2048, 0xe2a81605
diff --git a/tests/ref/fate/paf-audio b/tests/ref/fate/paf-audio
index ba47d5d..bb93ad5 100644
--- a/tests/ref/fate/paf-audio
+++ b/tests/ref/fate/paf-audio
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 3
 0,          0,          0,    57330,   229320, 0x062508b4
 0,      57330,      57330,    57330,   229320, 0x0a966cbf
 0,     114660,     114660,    57330,   229320, 0xee9bad45
diff --git a/tests/ref/fate/paf-demux b/tests/ref/fate/paf-demux
index 857fb54..0f281fe 100644
--- a/tests/ref/fate/paf-demux
+++ b/tests/ref/fate/paf-demux
@@ -1,5 +1,13 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: paf_video
+#dimensions 0: 256x192
+#sar 0: 0/1
 #tb 1: 1/22050
+#media_type 1: audio
+#codec_id 1: paf_audio
+#sample_rate 1: 22050
+#channel_layout 1: 3
 0,          0,          0,        1,   262144, 0x7f9a3c6a
 1,          0,          0,    57330,   131072, 0x255a6ac2
 0,          1,          1,        1,   260600, 0x0329e6f4, F=0x0
diff --git a/tests/ref/fate/paf-video b/tests/ref/fate/paf-video
index ed37c28..aa1fa82 100644
--- a/tests/ref/fate/paf-video
+++ b/tests/ref/fate/paf-video
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x192
+#sar 0: 0/1
 0,          0,          0,        1,   147456, 0x00000000
 0,          1,          1,        1,   147456, 0x7be40798
 0,          2,          2,        1,   147456, 0x44bc2fc0
diff --git a/tests/ref/fate/parseutils b/tests/ref/fate/parseutils
index 3306229..1aad5ec 100644
--- a/tests/ref/fate/parseutils
+++ b/tests/ref/fate/parseutils
@@ -83,3 +83,154 @@ now                      ->     1331972053.200000 = 2012-03-17T08:14:13Z
 42.1729                  ->             +42172900
 -1729.42                 ->           -1729420000
 12:34                    ->            +754000000
+
+Testing av_get_known_color_name()
+AliceBlue -> R(240) G(248) B(255) A(0)
+AntiqueWhite -> R(250) G(235) B(215) A(0)
+Aqua -> R(0) G(255) B(255) A(0)
+Aquamarine -> R(127) G(255) B(212) A(0)
+Azure -> R(240) G(255) B(255) A(0)
+Beige -> R(245) G(245) B(220) A(0)
+Bisque -> R(255) G(228) B(196) A(0)
+Black -> R(0) G(0) B(0) A(0)
+BlanchedAlmond -> R(255) G(235) B(205) A(0)
+Blue -> R(0) G(0) B(255) A(0)
+BlueViolet -> R(138) G(43) B(226) A(0)
+Brown -> R(165) G(42) B(42) A(0)
+BurlyWood -> R(222) G(184) B(135) A(0)
+CadetBlue -> R(95) G(158) B(160) A(0)
+Chartreuse -> R(127) G(255) B(0) A(0)
+Chocolate -> R(210) G(105) B(30) A(0)
+Coral -> R(255) G(127) B(80) A(0)
+CornflowerBlue -> R(100) G(149) B(237) A(0)
+Cornsilk -> R(255) G(248) B(220) A(0)
+Crimson -> R(220) G(20) B(60) A(0)
+Cyan -> R(0) G(255) B(255) A(0)
+DarkBlue -> R(0) G(0) B(139) A(0)
+DarkCyan -> R(0) G(139) B(139) A(0)
+DarkGoldenRod -> R(184) G(134) B(11) A(0)
+DarkGray -> R(169) G(169) B(169) A(0)
+DarkGreen -> R(0) G(100) B(0) A(0)
+DarkKhaki -> R(189) G(183) B(107) A(0)
+DarkMagenta -> R(139) G(0) B(139) A(0)
+DarkOliveGreen -> R(85) G(107) B(47) A(0)
+Darkorange -> R(255) G(140) B(0) A(0)
+DarkOrchid -> R(153) G(50) B(204) A(0)
+DarkRed -> R(139) G(0) B(0) A(0)
+DarkSalmon -> R(233) G(150) B(122) A(0)
+DarkSeaGreen -> R(143) G(188) B(143) A(0)
+DarkSlateBlue -> R(72) G(61) B(139) A(0)
+DarkSlateGray -> R(47) G(79) B(79) A(0)
+DarkTurquoise -> R(0) G(206) B(209) A(0)
+DarkViolet -> R(148) G(0) B(211) A(0)
+DeepPink -> R(255) G(20) B(147) A(0)
+DeepSkyBlue -> R(0) G(191) B(255) A(0)
+DimGray -> R(105) G(105) B(105) A(0)
+DodgerBlue -> R(30) G(144) B(255) A(0)
+FireBrick -> R(178) G(34) B(34) A(0)
+FloralWhite -> R(255) G(250) B(240) A(0)
+ForestGreen -> R(34) G(139) B(34) A(0)
+Fuchsia -> R(255) G(0) B(255) A(0)
+Gainsboro -> R(220) G(220) B(220) A(0)
+GhostWhite -> R(248) G(248) B(255) A(0)
+Gold -> R(255) G(215) B(0) A(0)
+GoldenRod -> R(218) G(165) B(32) A(0)
+Gray -> R(128) G(128) B(128) A(0)
+Green -> R(0) G(128) B(0) A(0)
+GreenYellow -> R(173) G(255) B(47) A(0)
+HoneyDew -> R(240) G(255) B(240) A(0)
+HotPink -> R(255) G(105) B(180) A(0)
+IndianRed -> R(205) G(92) B(92) A(0)
+Indigo -> R(75) G(0) B(130) A(0)
+Ivory -> R(255) G(255) B(240) A(0)
+Khaki -> R(240) G(230) B(140) A(0)
+Lavender -> R(230) G(230) B(250) A(0)
+LavenderBlush -> R(255) G(240) B(245) A(0)
+LawnGreen -> R(124) G(252) B(0) A(0)
+LemonChiffon -> R(255) G(250) B(205) A(0)
+LightBlue -> R(173) G(216) B(230) A(0)
+LightCoral -> R(240) G(128) B(128) A(0)
+LightCyan -> R(224) G(255) B(255) A(0)
+LightGoldenRodYellow -> R(250) G(250) B(210) A(0)
+LightGreen -> R(144) G(238) B(144) A(0)
+LightGrey -> R(211) G(211) B(211) A(0)
+LightPink -> R(255) G(182) B(193) A(0)
+LightSalmon -> R(255) G(160) B(122) A(0)
+LightSeaGreen -> R(32) G(178) B(170) A(0)
+LightSkyBlue -> R(135) G(206) B(250) A(0)
+LightSlateGray -> R(119) G(136) B(153) A(0)
+LightSteelBlue -> R(176) G(196) B(222) A(0)
+LightYellow -> R(255) G(255) B(224) A(0)
+Lime -> R(0) G(255) B(0) A(0)
+LimeGreen -> R(50) G(205) B(50) A(0)
+Linen -> R(250) G(240) B(230) A(0)
+Magenta -> R(255) G(0) B(255) A(0)
+Maroon -> R(128) G(0) B(0) A(0)
+MediumAquaMarine -> R(102) G(205) B(170) A(0)
+MediumBlue -> R(0) G(0) B(205) A(0)
+MediumOrchid -> R(186) G(85) B(211) A(0)
+MediumPurple -> R(147) G(112) B(216) A(0)
+MediumSeaGreen -> R(60) G(179) B(113) A(0)
+MediumSlateBlue -> R(123) G(104) B(238) A(0)
+MediumSpringGreen -> R(0) G(250) B(154) A(0)
+MediumTurquoise -> R(72) G(209) B(204) A(0)
+MediumVioletRed -> R(199) G(21) B(133) A(0)
+MidnightBlue -> R(25) G(25) B(112) A(0)
+MintCream -> R(245) G(255) B(250) A(0)
+MistyRose -> R(255) G(228) B(225) A(0)
+Moccasin -> R(255) G(228) B(181) A(0)
+NavajoWhite -> R(255) G(222) B(173) A(0)
+Navy -> R(0) G(0) B(128) A(0)
+OldLace -> R(253) G(245) B(230) A(0)
+Olive -> R(128) G(128) B(0) A(0)
+OliveDrab -> R(107) G(142) B(35) A(0)
+Orange -> R(255) G(165) B(0) A(0)
+OrangeRed -> R(255) G(69) B(0) A(0)
+Orchid -> R(218) G(112) B(214) A(0)
+PaleGoldenRod -> R(238) G(232) B(170) A(0)
+PaleGreen -> R(152) G(251) B(152) A(0)
+PaleTurquoise -> R(175) G(238) B(238) A(0)
+PaleVioletRed -> R(216) G(112) B(147) A(0)
+PapayaWhip -> R(255) G(239) B(213) A(0)
+PeachPuff -> R(255) G(218) B(185) A(0)
+Peru -> R(205) G(133) B(63) A(0)
+Pink -> R(255) G(192) B(203) A(0)
+Plum -> R(221) G(160) B(221) A(0)
+PowderBlue -> R(176) G(224) B(230) A(0)
+Purple -> R(128) G(0) B(128) A(0)
+Red -> R(255) G(0) B(0) A(0)
+RosyBrown -> R(188) G(143) B(143) A(0)
+RoyalBlue -> R(65) G(105) B(225) A(0)
+SaddleBrown -> R(139) G(69) B(19) A(0)
+Salmon -> R(250) G(128) B(114) A(0)
+SandyBrown -> R(244) G(164) B(96) A(0)
+SeaGreen -> R(46) G(139) B(87) A(0)
+SeaShell -> R(255) G(245) B(238) A(0)
+Sienna -> R(160) G(82) B(45) A(0)
+Silver -> R(192) G(192) B(192) A(0)
+SkyBlue -> R(135) G(206) B(235) A(0)
+SlateBlue -> R(106) G(90) B(205) A(0)
+SlateGray -> R(112) G(128) B(144) A(0)
+Snow -> R(255) G(250) B(250) A(0)
+SpringGreen -> R(0) G(255) B(127) A(0)
+SteelBlue -> R(70) G(130) B(180) A(0)
+Tan -> R(210) G(180) B(140) A(0)
+Teal -> R(0) G(128) B(128) A(0)
+Thistle -> R(216) G(191) B(216) A(0)
+Tomato -> R(255) G(99) B(71) A(0)
+Turquoise -> R(64) G(224) B(208) A(0)
+Violet -> R(238) G(130) B(238) A(0)
+Wheat -> R(245) G(222) B(179) A(0)
+White -> R(255) G(255) B(255) A(0)
+WhiteSmoke -> R(245) G(245) B(245) A(0)
+Yellow -> R(255) G(255) B(0) A(0)
+YellowGreen -> R(154) G(205) B(50) A(0)
+
+Testing av_find_info_tag()
+0. tag1 found: val1
+1. tag2 found: val2
+2. tag3 found: val3
+3. tag4 not found
+4. tag41 found: value 41
+5. 41 not found
+6. random1 not found
diff --git a/tests/ref/fate/pcm-planar b/tests/ref/fate/pcm-planar
index 91b4a78..5339447 100644
--- a/tests/ref/fate/pcm-planar
+++ b/tests/ref/fate/pcm-planar
@@ -1,4 +1,8 @@
 #tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 44100
+#channel_layout 0: 3
 0,          0,          0,     1471,     5884, 0x00000000
 0,       1471,       1471,     1471,     5884, 0x00000000
 0,       2942,       2942,     1472,     5888, 0x00000000
diff --git a/tests/ref/fate/pcm_dvd b/tests/ref/fate/pcm_dvd
index 6037451..8aa87cd 100644
--- a/tests/ref/fate/pcm_dvd
+++ b/tests/ref/fate/pcm_dvd
@@ -1,4 +1,8 @@
 #tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 48000
+#channel_layout 0: 3
 0,          0,          0,      334,     1336, 0x8e3c0abc
 0,        400,        400,      334,     1336, 0x99c41108
 0,        720,        720,      334,     1336, 0xd65be322
diff --git a/tests/ref/fate/pict b/tests/ref/fate/pict
index 0b764fc..f0f2e21 100644
--- a/tests/ref/fate/pict
+++ b/tests/ref/fate/pict
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x64
+#sar 0: 0/1
 0,          0,          0,        1,    49152, 0x144804b0
diff --git a/tests/ref/fate/pictor b/tests/ref/fate/pictor
index c89b608..2c7cf93 100644
--- a/tests/ref/fate/pictor
+++ b/tests/ref/fate/pictor
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 312x206
+#sar 0: 0/1
 0,          0,          0,        1,   192816, 0x29b9c158
diff --git a/tests/ref/fate/pmp-demux b/tests/ref/fate/pmp-demux
index b481db7..4b66427 100644
--- a/tests/ref/fate/pmp-demux
+++ b/tests/ref/fate/pmp-demux
@@ -1,4 +1,8 @@
 #tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: mp3
+#sample_rate 0: 44100
+#channel_layout 0: 3
 0,          0,          0,     1152,      417, 0xcb873fba
 0,       1152,       1152,     1152,      104, 0x6d521c5a
 0,       2304,       2304,     1152,      104, 0xb3af1d64
diff --git a/tests/ref/fate/png-gray16 b/tests/ref/fate/png-gray16
index 66fc601..cf0d9c2 100644
--- a/tests/ref/fate/png-gray16
+++ b/tests/ref/fate/png-gray16
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 1/1
 0,          0,          0,        1,    49152, 0xc71b77cd
diff --git a/tests/ref/fate/png-gray8 b/tests/ref/fate/png-gray8
index 9d30db6..77541ca 100644
--- a/tests/ref/fate/png-gray8
+++ b/tests/ref/fate/png-gray8
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 1/1
 0,          0,          0,        1,    49152, 0x55121b03
diff --git a/tests/ref/fate/png-rgb24 b/tests/ref/fate/png-rgb24
index c383836..54c8df8 100644
--- a/tests/ref/fate/png-rgb24
+++ b/tests/ref/fate/png-rgb24
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 72/72
 0,          0,          0,        1,    49152, 0xe0013dee
diff --git a/tests/ref/fate/png-rgb48 b/tests/ref/fate/png-rgb48
index b1159f1..dee849f 100644
--- a/tests/ref/fate/png-rgb48
+++ b/tests/ref/fate/png-rgb48
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 1/1
 0,          0,          0,        1,    49152, 0xcf0e902a
diff --git a/tests/ref/fate/png-rgba b/tests/ref/fate/png-rgba
index f20fe0c..e4d5bb8 100644
--- a/tests/ref/fate/png-rgba
+++ b/tests/ref/fate/png-rgba
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 1/1
 0,          0,          0,        1,    49152, 0x5017bc21
diff --git a/tests/ref/fate/png-ya16 b/tests/ref/fate/png-ya16
index dffdaf7..2797ec8 100644
--- a/tests/ref/fate/png-ya16
+++ b/tests/ref/fate/png-ya16
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 1/1
 0,          0,          0,        1,    49152, 0x0801ce78
diff --git a/tests/ref/fate/png-ya8 b/tests/ref/fate/png-ya8
index 1318af8..6fca461 100644
--- a/tests/ref/fate/png-ya8
+++ b/tests/ref/fate/png-ya8
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 1/1
 0,          0,          0,        1,    49152, 0x5a1481f8
diff --git a/tests/ref/fate/pngparser b/tests/ref/fate/pngparser
index 93005cf..111c41d 100644
--- a/tests/ref/fate/pngparser
+++ b/tests/ref/fate/pngparser
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 20x20
+#sar 0: 3543/3543
 0,          0,          0,        1,     1600, 0x01a481a9
 0,          1,          1,        1,     1600, 0x01a481a9
 0,          2,          2,        1,     1600, 0x01a481a9
diff --git a/tests/ref/fate/prores-422 b/tests/ref/fate/prores-422
index f402511..1ae4f5f 100644
--- a/tests/ref/fate/prores-422
+++ b/tests/ref/fate/prores-422
@@ -1,3 +1,7 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x57127dd9
 0,          1,          1,        1,  8294400, 0x57127dd9
diff --git a/tests/ref/fate/prores-422_hq b/tests/ref/fate/prores-422_hq
index 61a5014..4b4010d 100644
--- a/tests/ref/fate/prores-422_hq
+++ b/tests/ref/fate/prores-422_hq
@@ -1,3 +1,7 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x978851f4
 0,          1,          1,        1,  8294400, 0x978851f4
diff --git a/tests/ref/fate/prores-422_lt b/tests/ref/fate/prores-422_lt
index 3113c8a..853c500 100644
--- a/tests/ref/fate/prores-422_lt
+++ b/tests/ref/fate/prores-422_lt
@@ -1,3 +1,7 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x4ca110c7
 0,          1,          1,        1,  8294400, 0x4ca110c7
diff --git a/tests/ref/fate/prores-422_proxy b/tests/ref/fate/prores-422_proxy
index 5562dce..b77af3b 100644
--- a/tests/ref/fate/prores-422_proxy
+++ b/tests/ref/fate/prores-422_proxy
@@ -1,3 +1,7 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1,  8294400, 0x007ba770
 0,          1,          1,        1,  8294400, 0x007ba770
diff --git a/tests/ref/fate/prores-alpha b/tests/ref/fate/prores-alpha
index d64cfd5..f451d83 100644
--- a/tests/ref/fate/prores-alpha
+++ b/tests/ref/fate/prores-alpha
@@ -1,3 +1,7 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1, 16588800, 0x8e4dac48
 0,          1,          1,        1, 16588800, 0x8e4dac48
diff --git a/tests/ref/fate/prores-alpha_skip b/tests/ref/fate/prores-alpha_skip
index 559ec2b..a17cef8 100644
--- a/tests/ref/fate/prores-alpha_skip
+++ b/tests/ref/fate/prores-alpha_skip
@@ -1,3 +1,7 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 0/1
 0,          0,          0,        1, 12441600, 0xf11685dd
 0,          1,          1,        1, 12441600, 0xf11685dd
diff --git a/tests/ref/fate/prores-gray b/tests/ref/fate/prores-gray
new file mode 100644
index 0000000..22b79b9
--- /dev/null
+++ b/tests/ref/fate/prores-gray
@@ -0,0 +1,15 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/15
+#tb 1: 1/48000
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 48000
+#channel_layout 1: 3
+0,          0,          0,        1,  1658880, 0x43d9c9e2
+1,          0,          0,     1024,     4096, 0x6c8a9a18
+1,       1024,       1024,     1024,     4096, 0x960dadcf
+0,          1,          1,        1,  1658880, 0xa2a72f9b
+1,       2048,       2048,     1024,     4096, 0xa913cd55
diff --git a/tests/ref/fate/prores-transparency b/tests/ref/fate/prores-transparency
index 745e966..6a9c786 100644
--- a/tests/ref/fate/prores-transparency
+++ b/tests/ref/fate/prores-transparency
@@ -1,5 +1,13 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 #tb 1: 1/48000
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 48000
+#channel_layout 1: 3
 0,          0,          0,        1, 16588800, 0x7163b01a
 1,          0,          0,     1024,     4096, 0x00000000
 1,       1024,       1024,      896,     3584, 0x00000000
diff --git a/tests/ref/fate/prores-transparency_skip b/tests/ref/fate/prores-transparency_skip
index 5fd8d0b..569d2ba 100644
--- a/tests/ref/fate/prores-transparency_skip
+++ b/tests/ref/fate/prores-transparency_skip
@@ -1,5 +1,13 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 #tb 1: 1/48000
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 48000
+#channel_layout 1: 3
 0,          0,          0,        1, 12441600, 0x627d1548
 1,          0,          0,     1024,     4096, 0x00000000
 1,       1024,       1024,      896,     3584, 0x00000000
diff --git a/tests/ref/fate/psx-str-demux b/tests/ref/fate/psx-str-demux
index 42c5731..e346c52 100644
--- a/tests/ref/fate/psx-str-demux
+++ b/tests/ref/fate/psx-str-demux
@@ -1,5 +1,13 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: mdec
+#dimensions 0: 320x240
+#sar 0: 0/1
 #tb 1: 4/75
+#media_type 1: audio
+#codec_id 1: adpcm_xa
+#sample_rate 1: 37800
+#channel_layout 1: 3
 0,          0,          0,        1,     8832, 0x01ad3eeb
 1,          0,          0,        1,     2304, 0xf0ad1000
 1,          1,          1,        1,     2304, 0x69269ce6
diff --git a/tests/ref/fate/ptx b/tests/ref/fate/ptx
index 7edbbdd..3dee9c2 100644
--- a/tests/ref/fate/ptx
+++ b/tests/ref/fate/ptx
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x128
+#sar 0: 0/1
 0,          0,          0,        1,   393216, 0x30479950
diff --git a/tests/ref/fate/pva-demux b/tests/ref/fate/pva-demux
index 67d4844..4059af4 100644
--- a/tests/ref/fate/pva-demux
+++ b/tests/ref/fate/pva-demux
@@ -1,5 +1,13 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 544x576
+#sar 0: 24/17
 #tb 1: 1/90000
+#media_type 1: audio
+#codec_id 1: mp2
+#sample_rate 1: 48000
+#channel_layout 1: 3
 1,          0,          0,     2160,      384, 0x071abcc8
 1,       2160,       2160,     2160,      384, 0x31c9aee0
 1,       4320,       4320,     2160,      384, 0xa50eaa94
diff --git a/tests/ref/fate/qpeg b/tests/ref/fate/qpeg
index eca2924..1a98887 100644
--- a/tests/ref/fate/qpeg
+++ b/tests/ref/fate/qpeg
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0x0b712fba
 0,          1,          1,        1,   230400, 0x30252ac7
 0,          2,          2,        1,   230400, 0x6d98a787
diff --git a/tests/ref/fate/qtrle-16bit b/tests/ref/fate/qtrle-16bit
index 2021f2a..57651de 100644
--- a/tests/ref/fate/qtrle-16bit
+++ b/tests/ref/fate/qtrle-16bit
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    57600, 0xcf2d39fc
 0,          1,          1,        1,    57600, 0xfc9f6bed
 0,          2,          2,        1,    57600, 0x3f5805bb
diff --git a/tests/ref/fate/qtrle-1bit b/tests/ref/fate/qtrle-1bit
index 3eccc27..d2f10bc 100644
--- a/tests/ref/fate/qtrle-1bit
+++ b/tests/ref/fate/qtrle-1bit
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,    77824, 0xc298c68b
 0,          1,          1,        1,    77824, 0x22f7c63e
 0,          2,          2,        1,    77824, 0x2aacc669
diff --git a/tests/ref/fate/qtrle-24bit b/tests/ref/fate/qtrle-24bit
index a21b099..545e82e 100644
--- a/tests/ref/fate/qtrle-24bit
+++ b/tests/ref/fate/qtrle-24bit
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    57600, 0x3718ad00
 0,          1,          1,        1,    57600, 0x54861558
 0,          2,          2,        1,    57600, 0xea1d6233
diff --git a/tests/ref/fate/qtrle-2bit b/tests/ref/fate/qtrle-2bit
index 95c0f7c..633dd14 100644
--- a/tests/ref/fate/qtrle-2bit
+++ b/tests/ref/fate/qtrle-2bit
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0xb1ee55dc
 0,          1,          1,        1,   230400, 0x97c580bf
 0,          2,          2,        1,   230400, 0xd4bd57e8
diff --git a/tests/ref/fate/qtrle-32bit b/tests/ref/fate/qtrle-32bit
index ed6dc03..aaaf8d6 100644
--- a/tests/ref/fate/qtrle-32bit
+++ b/tests/ref/fate/qtrle-32bit
@@ -1,4 +1,8 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 0,          0,          0,        1,  1036800, 0x2a90d062
 0,          1,          1,        1,  1036800, 0x6565aded
 0,          2,          2,        1,  1036800, 0xf0b587d2
diff --git a/tests/ref/fate/qtrle-4bit b/tests/ref/fate/qtrle-4bit
index 74eb4ab..b09920b 100644
--- a/tests/ref/fate/qtrle-4bit
+++ b/tests/ref/fate/qtrle-4bit
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0x0655b3d9
 0,          1,          1,        1,   230400, 0x9c626fd3
 0,          2,          2,        1,   230400, 0x5bc95868
diff --git a/tests/ref/fate/qtrle-8bit b/tests/ref/fate/qtrle-8bit
index 5b30fbb..8da113d 100644
--- a/tests/ref/fate/qtrle-8bit
+++ b/tests/ref/fate/qtrle-8bit
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0x1492e3ed
 0,          1,          1,        1,   921600, 0x1492e3ed
 0,          2,          2,        1,   921600, 0x1492e3ed
diff --git a/tests/ref/fate/quickdraw b/tests/ref/fate/quickdraw
index eccb477..c3bb0a5 100644
--- a/tests/ref/fate/quickdraw
+++ b/tests/ref/fate/quickdraw
@@ -1,3 +1,7 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0xc0e68764
 0,          2,          2,        1,   921600, 0x01a16629
diff --git a/tests/ref/fate/r210 b/tests/ref/fate/r210
index 45bb10c..e3686fe 100644
--- a/tests/ref/fate/r210
+++ b/tests/ref/fate/r210
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,  1843200, 0xbd414b93
 0,          1,          1,        1,  1843200, 0x23298f1f
 0,          2,          2,        1,  1843200, 0x5a56df19
diff --git a/tests/ref/fate/ra3-144 b/tests/ref/fate/ra3-144
index 40bcaed..b5fb47b 100644
--- a/tests/ref/fate/ra3-144
+++ b/tests/ref/fate/ra3-144
@@ -1,4 +1,8 @@
 #tb 0: 1/8000
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 8000
+#channel_layout 0: 4
 0,          0,          0,      160,      320, 0x00000000
 0,        160,        160,      160,      320, 0x4cfd5d74
 0,        320,        320,      160,      320, 0xbb60fa3d
diff --git a/tests/ref/fate/redcode-demux b/tests/ref/fate/redcode-demux
index a7e2838..c08bbc8 100644
--- a/tests/ref/fate/redcode-demux
+++ b/tests/ref/fate/redcode-demux
@@ -1,5 +1,13 @@
 #tb 0: 1/240000
+#media_type 0: video
+#codec_id 0: jpeg2000
+#dimensions 0: 2048x1152
+#sar 0: 0/1
 #tb 1: 1/240000
+#media_type 1: audio
+#codec_id 1: pcm_s32be
+#sample_rate 1: 48000
+#channel_layout 1: 4
 0,          0,          0,    10010,  1626280, 0x5768c7d6
 1,          0,          0,    18140,    14816, 0xd185e8c7
 0,      10010,      10010,    10010,  1626092, 0x070bd882
diff --git a/tests/ref/fate/rgbapng-4816 b/tests/ref/fate/rgbapng-4816
new file mode 100644
index 0000000..99493bc
--- /dev/null
+++ b/tests/ref/fate/rgbapng-4816
@@ -0,0 +1,6 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 330x330
+#sar 0: 0/1
+0,          0,          0,        1,   435600, 0x961c0f09
diff --git a/tests/ref/fate/rl2 b/tests/ref/fate/rl2
index d7dd23d..9189822 100644
--- a/tests/ref/fate/rl2
+++ b/tests/ref/fate/rl2
@@ -1,4 +1,8 @@
 #tb 0: 1171/11025
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x7112a667
 0,          1,          1,        1,   192000, 0x6936abf3
 0,          2,          2,        1,   192000, 0xb1f08981
diff --git a/tests/ref/fate/roqvideo b/tests/ref/fate/roqvideo
index 9febedb..36eec54 100644
--- a/tests/ref/fate/roqvideo
+++ b/tests/ref/fate/roqvideo
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   393216, 0x56995aac
 0,          1,          1,        1,   393216, 0xf9ed5d6c
 0,          2,          2,        1,   393216, 0xd3285d75
diff --git a/tests/ref/fate/rpza b/tests/ref/fate/rpza
index a9ae3bb..3ad7e4c 100644
--- a/tests/ref/fate/rpza
+++ b/tests/ref/fate/rpza
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0x26a4728c
 0,          1,          1,        1,   230400, 0xa5ff0a21
 0,          2,          2,        1,   230400, 0x479d767d
diff --git a/tests/ref/fate/rscc b/tests/ref/fate/rscc
deleted file mode 100644
index 69dbfe1..0000000
--- a/tests/ref/fate/rscc
+++ /dev/null
@@ -1,6 +0,0 @@
-#tb 0: 1/10
-0,          0,          0,        1,  6814720, 0x1365f8ef
-0,          1,          1,        1,  6814720, 0x90838983
-0,          2,          2,        1,  6814720, 0xf0cc3131
-0,          3,          3,        1,  6814720, 0xc07e404d
-0,          4,          4,        1,  6814720, 0x945962dd
diff --git a/tests/ref/fate/rscc-16bit b/tests/ref/fate/rscc-16bit
new file mode 100644
index 0000000..3571964
--- /dev/null
+++ b/tests/ref/fate/rscc-16bit
@@ -0,0 +1,20 @@
+#tb 0: 100/2397
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
+0,          0,          0,        1,   153600, 0x33759daf
+0,          1,          1,        1,   153600, 0x43e0c910
+0,          2,          2,        1,   153600, 0x6c75a8f0
+0,          3,          3,        1,   153600, 0xaace1255
+0,          4,          4,        1,   153600, 0x42d3f439
+0,          5,          5,        1,   153600, 0xb225b396
+0,          6,          6,        1,   153600, 0xa615221c
+0,          7,          7,        1,   153600, 0x5401f5a9
+0,          8,          8,        1,   153600, 0xd274cef3
+0,          9,          9,        1,   153600, 0x7935f992
+0,         10,         10,        1,   153600, 0x7669e7c6
+0,         11,         11,        1,   153600, 0x527bd6a1
+0,         12,         12,        1,   153600, 0x0f33b2ed
+0,         13,         13,        1,   153600, 0xe62ddb32
+0,         14,         14,        1,   153600, 0x81541aa2
diff --git a/tests/ref/fate/rscc-24bit b/tests/ref/fate/rscc-24bit
new file mode 100644
index 0000000..c61ebd3
--- /dev/null
+++ b/tests/ref/fate/rscc-24bit
@@ -0,0 +1,6 @@
+#tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 854x480
+#sar 0: 0/1
+0,          0,          0,        1,  1229760, 0x9c99ba99
diff --git a/tests/ref/fate/rscc-32bit b/tests/ref/fate/rscc-32bit
new file mode 100644
index 0000000..b55b4b9
--- /dev/null
+++ b/tests/ref/fate/rscc-32bit
@@ -0,0 +1,13 @@
+#tb 0: 100/2397
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
+0,          0,          0,        1,   307200, 0xe36c2c38
+0,          1,          1,        1,   307200, 0xa2e3476b
+0,          2,          2,        1,   307200, 0x65167c95
+0,          3,          3,        1,   307200, 0x6acd02ac
+0,          4,          4,        1,   307200, 0x37935e0b
+0,          5,          5,        1,   307200, 0x8e6918bc
+0,          6,          6,        1,   307200, 0x0a246578
+0,          7,          7,        1,   307200, 0x9c1a2f4c
diff --git a/tests/ref/fate/rv20-1239 b/tests/ref/fate/rv20-1239
new file mode 100644
index 0000000..3be1b8b
--- /dev/null
+++ b/tests/ref/fate/rv20-1239
@@ -0,0 +1,95 @@
+#tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
+0,          0,          0,        1,    28800, 0xe41c0ee2
+0,          1,          1,        1,    28800, 0x08054520
+0,          2,          2,        1,    28800, 0x272b3ed7
+0,          3,          3,        1,    28800, 0x456551d0
+0,          4,          4,        1,    28800, 0x4f96457f
+0,          5,          5,        1,    28800, 0x4e78568a
+0,          6,          6,        1,    28800, 0xe79151f3
+0,          7,          7,        1,    28800, 0x6d7350d8
+0,          8,          8,        1,    28800, 0x397250b2
+0,          9,          9,        1,    28800, 0x518750ae
+0,         10,         10,        1,    28800, 0x4bfa4aa2
+0,         11,         11,        1,    28800, 0x085a5490
+0,         12,         12,        1,    28800, 0x7da56e74
+0,         13,         13,        1,    28800, 0xfdd08146
+0,         14,         14,        1,    28800, 0x99c295bd
+0,         15,         15,        1,    28800, 0xc8bc88f2
+0,         16,         16,        1,    28800, 0x986eaa72
+0,         17,         17,        1,    28800, 0xa3f9aa6f
+0,         18,         18,        1,    28800, 0xc1b4bed4
+0,         19,         19,        1,    28800, 0xf9a767bb
+0,         20,         20,        1,    28800, 0x72e6b420
+0,         21,         21,        1,    28800, 0x30e7eabd
+0,         22,         22,        1,    28800, 0xca100206
+0,         23,         23,        1,    28800, 0xe433f7b9
+0,         24,         24,        1,    28800, 0x1f70f4f2
+0,         25,         25,        1,    28800, 0x2e58f182
+0,         26,         26,        1,    28800, 0x4514cca8
+0,         27,         27,        1,    28800, 0xc0e1e144
+0,         28,         28,        1,    28800, 0x1a79e36a
+0,         29,         29,        1,    28800, 0x0729de0b
+0,         30,         30,        1,    28800, 0xd61ccbb1
+0,         31,         31,        1,    28800, 0x877aa65d
+0,         32,         32,        1,    28800, 0x7cabbc37
+0,         33,         33,        1,    28800, 0x6591b87c
+0,         34,         34,        1,    28800, 0x097dd8bc
+0,         35,         35,        1,    28800, 0xa4549f78
+0,         36,         36,        1,    28800, 0x109f91ef
+0,         37,         37,        1,    28800, 0x96a2c41b
+0,         38,         38,        1,    28800, 0x3b71e985
+0,         39,         39,        1,    28800, 0xbb76ff57
+0,         40,         40,        1,    28800, 0x26701ae1
+0,         41,         41,        1,    28800, 0x9da03e9b
+0,         42,         42,        1,    28800, 0x58fc3d9a
+0,         43,         43,        1,    28800, 0x67947735
+0,         44,         44,        1,    28800, 0x3961cea4
+0,         45,         45,        1,    28800, 0x68fe0f3a
+0,         46,         46,        1,    28800, 0x6623d61f
+0,         47,         47,        1,    28800, 0x7df2c4ff
+0,         48,         48,        1,    28800, 0xe9b9eaa6
+0,         49,         49,        1,    28800, 0xeec8c115
+0,         50,         50,        1,    28800, 0xbfd96ba4
+0,         51,         51,        1,    28800, 0x4d6dff71
+0,         52,         52,        1,    28800, 0x3ffbd6fe
+0,         53,         53,        1,    28800, 0x7aa5e42e
+0,         54,         54,        1,    28800, 0x4d05cf80
+0,         55,         55,        1,    28800, 0x9fb3b152
+0,         56,         56,        1,    28800, 0xc62b05b2
+0,         57,         57,        1,    28800, 0x82a2e7dd
+0,         58,         58,        1,    28800, 0x4611b76f
+0,         59,         59,        1,    28800, 0xc7f5acee
+0,         60,         60,        1,    28800, 0x19149cc8
+0,         61,         61,        1,    28800, 0xe97d5933
+0,         62,         62,        1,    28800, 0x92960b73
+0,         63,         63,        1,    28800, 0x2369d90f
+0,         64,         64,        1,    28800, 0x1d58d518
+0,         65,         65,        1,    28800, 0x2b29b6ee
+0,         66,         66,        1,    28800, 0xbfbb8b66
+0,         67,         67,        1,    28800, 0x6bf759d4
+0,         68,         68,        1,    28800, 0x8ccf3a60
+0,         69,         69,        1,    28800, 0x4b1b4623
+0,         70,         70,        1,    28800, 0xc1da9fc6
+0,         71,         71,        1,    28800, 0xb9bc1eed
+0,         72,         72,        1,    28800, 0x50f7d1eb
+0,         73,         73,        1,    28800, 0xf8c53f59
+0,         74,         74,        1,    28800, 0x950e3515
+0,         75,         75,        1,    28800, 0xe5dff457
+0,         76,         76,        1,    28800, 0x2dc3ad6a
+0,         77,         77,        1,    28800, 0x0559b63c
+0,         78,         78,        1,    28800, 0xa475bf46
+0,         79,         79,        1,    28800, 0x7861bbcf
+0,         80,         80,        1,    28800, 0x3e4ac44c
+0,         81,         81,        1,    28800, 0xfb5b99a0
+0,         82,         82,        1,    28800, 0x99299648
+0,         83,         83,        1,    28800, 0x384d48ac
+0,         84,         84,        1,    28800, 0xf17e18f7
+0,         85,         85,        1,    28800, 0xa9e00e3f
+0,         86,         86,        1,    28800, 0x5d110bb3
+0,         87,         87,        1,    28800, 0x337d3e31
+0,         88,         88,        1,    28800, 0xfea3737b
+0,         89,         89,        1,    28800, 0xce7d6020
diff --git a/tests/ref/fate/rv30 b/tests/ref/fate/rv30
index 70db647..c54aeea 100644
--- a/tests/ref/fate/rv30
+++ b/tests/ref/fate/rv30
@@ -1,4 +1,8 @@
 #tb 0: 32768/982057
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x240
+#sar 0: 0/1
 0,          0,          0,        1,   126720, 0xcefaec47
 0,          1,          1,        1,   126720, 0xa416ece5
 0,          2,          2,        1,   126720, 0xa416ece5
diff --git a/tests/ref/fate/rv40 b/tests/ref/fate/rv40
index 6159859..9cbb844 100644
--- a/tests/ref/fate/rv40
+++ b/tests/ref/fate/rv40
@@ -1,4 +1,8 @@
 #tb 0: 32768/785647
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 576x320
+#sar 0: 0/1
 0,          0,          0,        1,   276480, 0x5f7a0d4f
 0,          1,          1,        1,   276480, 0x5f7a0d4f
 0,          2,          2,        1,   276480, 0x5f7a0d4f
diff --git a/tests/ref/fate/sanm b/tests/ref/fate/sanm
index a882118..7a6690f 100644
--- a/tests/ref/fate/sanm
+++ b/tests/ref/fate/sanm
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0x00000000
 0,          1,          1,        1,   921600, 0x00000000
 0,          2,          2,        1,   921600, 0x00000000
diff --git a/tests/ref/fate/screenpresso b/tests/ref/fate/screenpresso
deleted file mode 100644
index bbdffb4..0000000
--- a/tests/ref/fate/screenpresso
+++ /dev/null
@@ -1,5 +0,0 @@
-#tb 0: 1/15
-0,          0,          0,        1,   691200, 0xfdbdfad6
-0,          1,          1,        1,   691200, 0xc5feb961
-0,          4,          4,        1,   691200, 0x4c8c7e23
-0,          8,          8,        1,   691200, 0xd95c89f8
diff --git a/tests/ref/fate/screenpresso-16bit b/tests/ref/fate/screenpresso-16bit
new file mode 100644
index 0000000..88c33a6
--- /dev/null
+++ b/tests/ref/fate/screenpresso-16bit
@@ -0,0 +1,13 @@
+#tb 0: 100/2397
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
+0,          0,          0,        1,   153600, 0x69a234de
+0,          1,          1,        1,   153600, 0x7f43aee5
+0,          2,          2,        1,   153600, 0x81030634
+0,          3,          3,        1,   153600, 0xf570d0ef
+0,          4,          4,        1,   153600, 0x386e8cec
+0,          5,          5,        1,   153600, 0xbe53af8f
+0,          6,          6,        1,   153600, 0xf92f48bd
+0,          7,          7,        1,   153600, 0x594472c5
diff --git a/tests/ref/fate/screenpresso-24bit b/tests/ref/fate/screenpresso-24bit
new file mode 100644
index 0000000..74195d4
--- /dev/null
+++ b/tests/ref/fate/screenpresso-24bit
@@ -0,0 +1,9 @@
+#tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x360
+#sar 0: 0/1
+0,          0,          0,        1,   691200, 0xfdbdfad6
+0,          1,          1,        1,   691200, 0xc5feb961
+0,          4,          4,        1,   691200, 0x4c8c7e23
+0,          8,          8,        1,   691200, 0xd95c89f8
diff --git a/tests/ref/fate/screenpresso-32bit b/tests/ref/fate/screenpresso-32bit
new file mode 100644
index 0000000..fc06ec2
--- /dev/null
+++ b/tests/ref/fate/screenpresso-32bit
@@ -0,0 +1,9 @@
+#tb 0: 100/2397
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
+0,          0,          0,        1,   307200, 0xa01f27cc
+0,          1,          1,        1,   307200, 0x5d83c4d0
+0,          2,          2,        1,   307200, 0xb7d7919f
+0,          3,          3,        1,   307200, 0x4d201450
diff --git a/tests/ref/fate/sgi-gray16 b/tests/ref/fate/sgi-gray16
index 0908746..8dba0f4 100644
--- a/tests/ref/fate/sgi-gray16
+++ b/tests/ref/fate/sgi-gray16
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   262144, 0x6c27f084
diff --git a/tests/ref/fate/sgi-gray16-rle b/tests/ref/fate/sgi-gray16-rle
index 09903d5..472835a 100644
--- a/tests/ref/fate/sgi-gray16-rle
+++ b/tests/ref/fate/sgi-gray16-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   262144, 0x65ef57ff
diff --git a/tests/ref/fate/sgi-gray8 b/tests/ref/fate/sgi-gray8
index b0e0606..55c12dc 100644
--- a/tests/ref/fate/sgi-gray8
+++ b/tests/ref/fate/sgi-gray8
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   131072, 0xb0702a94
diff --git a/tests/ref/fate/sgi-gray8-rle b/tests/ref/fate/sgi-gray8-rle
index b0e0606..55c12dc 100644
--- a/tests/ref/fate/sgi-gray8-rle
+++ b/tests/ref/fate/sgi-gray8-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   131072, 0xb0702a94
diff --git a/tests/ref/fate/sgi-rgb24 b/tests/ref/fate/sgi-rgb24
index 30aca1c..4326cab 100644
--- a/tests/ref/fate/sgi-rgb24
+++ b/tests/ref/fate/sgi-rgb24
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   393216, 0xa9b28fd9
diff --git a/tests/ref/fate/sgi-rgb24-rle b/tests/ref/fate/sgi-rgb24-rle
index 1128de5..d21bde1 100644
--- a/tests/ref/fate/sgi-rgb24-rle
+++ b/tests/ref/fate/sgi-rgb24-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   393216, 0xe96e1de2
diff --git a/tests/ref/fate/sgi-rgb48 b/tests/ref/fate/sgi-rgb48
index 8f3ca50..29fe302 100644
--- a/tests/ref/fate/sgi-rgb48
+++ b/tests/ref/fate/sgi-rgb48
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   786432, 0xee4aa667
diff --git a/tests/ref/fate/sgi-rgb48-rle b/tests/ref/fate/sgi-rgb48-rle
index 2cf0259..49fc973 100644
--- a/tests/ref/fate/sgi-rgb48-rle
+++ b/tests/ref/fate/sgi-rgb48-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   786432, 0xbc743bc4
diff --git a/tests/ref/fate/sgi-rgba b/tests/ref/fate/sgi-rgba
index 058f5f9..6a2d176 100644
--- a/tests/ref/fate/sgi-rgba
+++ b/tests/ref/fate/sgi-rgba
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   524288, 0x4ee5adbb
diff --git a/tests/ref/fate/sgi-rgba-rle b/tests/ref/fate/sgi-rgba-rle
index 058f5f9..6a2d176 100644
--- a/tests/ref/fate/sgi-rgba-rle
+++ b/tests/ref/fate/sgi-rgba-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,   524288, 0x4ee5adbb
diff --git a/tests/ref/fate/sgi-rgba64 b/tests/ref/fate/sgi-rgba64
index f4e939e..00181dc 100644
--- a/tests/ref/fate/sgi-rgba64
+++ b/tests/ref/fate/sgi-rgba64
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,  1048576, 0xc657e22b
diff --git a/tests/ref/fate/sgi-rgba64-rle b/tests/ref/fate/sgi-rgba64-rle
index cdf5fd0..354d391 100644
--- a/tests/ref/fate/sgi-rgba64-rle
+++ b/tests/ref/fate/sgi-rgba64-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x256
+#sar 0: 0/1
 0,          0,          0,        1,  1048576, 0xb619d0f1
diff --git a/tests/ref/fate/sierra-vmd-audio b/tests/ref/fate/sierra-vmd-audio
index 13d3567..2b9f8e8 100644
--- a/tests/ref/fate/sierra-vmd-audio
+++ b/tests/ref/fate/sierra-vmd-audio
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 4
 0,          0,          0,    61740,   123480, 0x3a794c13
 0,      61740,      61740,     2205,     4410, 0x109d04e0
 0,      63945,      63945,     2205,     4410, 0x224d244f
diff --git a/tests/ref/fate/sierra-vmd-video b/tests/ref/fate/sierra-vmd-video
index 668faee..b1b22e3 100644
--- a/tests/ref/fate/sierra-vmd-video
+++ b/tests/ref/fate/sierra-vmd-video
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0x54b4bfe2
 0,          1,          1,        1,   230400, 0x9e1460e3
 0,          2,          2,        1,   230400, 0x8136f21c
diff --git a/tests/ref/fate/siff-demux b/tests/ref/fate/siff-demux
index 692e504..687a518 100644
--- a/tests/ref/fate/siff-demux
+++ b/tests/ref/fate/siff-demux
@@ -1,5 +1,13 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: vb
+#dimensions 0: 320x240
+#sar 0: 0/1
 #tb 1: 1/22050
+#media_type 1: audio
+#codec_id 1: pcm_u8
+#sample_rate 1: 22050
+#channel_layout 1: 4
 0,          0,          0,        1,    15152, 0x14fc0f1f
 1,          0,          0,    22050,    22050, 0xa7d60d27
 0,          1,          1,        1,    15344, 0x31614bd7
diff --git a/tests/ref/fate/smacker-audio b/tests/ref/fate/smacker-audio
index 442f479..fbeb4be 100644
--- a/tests/ref/fate/smacker-audio
+++ b/tests/ref/fate/smacker-audio
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: pcm_s16le
+#sample_rate 0: 22050
+#channel_layout 0: 4
 0,          0,          0,    23620,    47240, 0x9974897c
 0,      23620,      23620,     1564,     3128, 0x7e4064b4
 0,      25184,      25184,     1564,     3128, 0x80883301
diff --git a/tests/ref/fate/smacker-video b/tests/ref/fate/smacker-video
index 8bd3071..9325d91 100644
--- a/tests/ref/fate/smacker-video
+++ b/tests/ref/fate/smacker-video
@@ -1,4 +1,8 @@
 #tb 0: 71/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x8926d7fc
 0,          1,          1,        1,   192000, 0x2506d384
 0,          2,          2,        1,   192000, 0x9a8dc93a
diff --git a/tests/ref/fate/smc b/tests/ref/fate/smc
index 1635b37..4802407 100644
--- a/tests/ref/fate/smc
+++ b/tests/ref/fate/smc
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0xf814fc90
 0,          1,          1,        1,   230400, 0xe1b13137
 0,          2,          2,        1,   230400, 0xa7f4d408
diff --git a/tests/ref/fate/smjpeg-demux b/tests/ref/fate/smjpeg-demux
index 637f28c..242a22f 100644
--- a/tests/ref/fate/smjpeg-demux
+++ b/tests/ref/fate/smjpeg-demux
@@ -1,5 +1,13 @@
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: mjpeg
+#dimensions 0: 320x240
+#sar 0: 1/1
 #tb 1: 1/1000
+#media_type 1: audio
+#codec_id 1: adpcm_ima_smjpeg
+#sample_rate 1: 22050
+#channel_layout 1: 4
 0,          0,          0,        0,      734, 0x5a042c2c
 1,          0,          0,       23,      260, 0x00000000
 1,         23,         23,       23,      260, 0x00000000
diff --git a/tests/ref/fate/smvjpeg b/tests/ref/fate/smvjpeg
index 1a012cd..360fad6 100644
--- a/tests/ref/fate/smvjpeg
+++ b/tests/ref/fate/smvjpeg
@@ -1,4 +1,8 @@
 #tb 0: 1/1
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x160
+#sar 0: 0/1
 0,          0,          0,        1,    30720, 0x3a821807
 0,          1,          1,        1,    30720, 0x95168e5d
 0,          2,          2,        1,    30720, 0xd4d98e45
diff --git a/tests/ref/fate/source b/tests/ref/fate/source
index ec0a98e..c7ea3da 100644
--- a/tests/ref/fate/source
+++ b/tests/ref/fate/source
@@ -5,7 +5,6 @@ compat/avisynth/windowsPorts/windows2linux.h
 libavcodec/file_open.c
 libavcodec/interplayacm.c
 libavcodec/log2_tab.c
-libavcodec/mathops.c
 libavcodec/reverse.c
 libavdevice/file_open.c
 libavfilter/log2_tab.c
diff --git a/tests/ref/fate/sp5x b/tests/ref/fate/sp5x
index 986c111..603535b 100644
--- a/tests/ref/fate/sp5x
+++ b/tests/ref/fate/sp5x
@@ -1,5 +1,13 @@
 #tb 0: 513/5000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 #tb 1: 1/8000
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 8000
+#channel_layout 1: 4
 0,          0,          0,        1,   115200, 0x8ebcb7f8
 1,          0,          0,     1024,     2048, 0x366ee71c
 0,          1,          1,        1,   115200, 0x1fa8e673
diff --git a/tests/ref/fate/sub-charenc b/tests/ref/fate/sub-charenc
index ed5cdbe..a056cd1 100644
--- a/tests/ref/fate/sub-charenc
+++ b/tests/ref/fate/sub-charenc
@@ -16,7 +16,7 @@ Dialogue: 0,0:01:22.17,0:01:24.05,Default,,0,0,0,,Учителят Ли е ту
 Dialogue: 0,0:01:45.48,0:01:47.32,Default,,0,0,0,,Шу Лиен!
 Dialogue: 0,0:01:54.53,0:01:57.24,Default,,0,0,0,,Ли Му Бай е тук.
 Dialogue: 0,0:02:05.83,0:02:09.00,Default,,0,0,0,,- Как вървят нещата?\N- Добре. Моля, влезте!
-Dialogue: 0,0:02:23.48,0:02:26.52,Default,,0,0,0,,Му Бай...\NМина много време.
+Dialogue: 0,0:02:23.48,0:02:26.53,Default,,0,0,0,,Му Бай...\NМина много време.
 Dialogue: 0,0:02:26.73,0:02:28.11,Default,,0,0,0,,Така е.
 Dialogue: 0,0:02:28.57,0:02:31.41,Default,,0,0,0,,- Как върви бизнесът?\N- Добре.
 Dialogue: 0,0:02:31.61,0:02:33.90,Default,,0,0,0,,- А ти как си?\N- Добре.
diff --git a/tests/ref/fate/sub-textenc b/tests/ref/fate/sub-textenc
index cb0db7f..f7d82ce 100644
--- a/tests/ref/fate/sub-textenc
+++ b/tests/ref/fate/sub-textenc
@@ -16,13 +16,13 @@ If you see this with the normal font, the player don't (fully) support font face
 Hidden
 
 4
-00:00:04,501 --> 00:00:07,501
+00:00:04,501 --> 00:00:07,500
 This text should be small
 This text should be normal
 This text should be big
 
 5
-00:00:07,501 --> 00:00:11,501
+00:00:07,501 --> 00:00:11,500
 This should be an E with an accent: È
 日本語
 This text should be bold, italics and underline
@@ -31,7 +31,7 @@ This text should be small and red
 This text should be big and brown
 
 6
-00:00:11,501 --> 00:00:14,501
+00:00:11,501 --> 00:00:14,500
 This line should be bold
 This line should be italics
 This line should be underline
@@ -40,7 +40,7 @@ Both lines
 should be underline
 
 7
-00:00:14,501 --> 00:00:17,501
+00:00:14,501 --> 00:00:17,500
 >
 It would be a good thing to
 hide invalid html tags that are closed and show the text in them
@@ -49,7 +49,7 @@ Show not opened tags</invalid_tag_not_opened>
 <
 
 8
-00:00:17,501 --> 00:00:20,501
+00:00:17,501 --> 00:00:20,500
 and also
 hide invalid html tags with parameters that are closed and show the text in them
 <invalid_tag_uc par=5>but show un-closed invalid html tags
@@ -57,66 +57,66 @@ This text should be showed underlined without problems also: 2<3,5>1,4<6
 This shouldn't be underlined
 
 9
-00:00:20,501 --> 00:00:21,501
+00:00:20,501 --> 00:00:21,500
 This text should be in the normal position...
 
 10
-00:00:21,501 --> 00:00:22,501
+00:00:21,501 --> 00:00:22,500
 This text should NOT be in the normal position
 
 11
-00:00:22,501 --> 00:00:24,501
+00:00:22,501 --> 00:00:24,500
 Implementation is the same of the ASS tag
 This text should be at the
 top and horizontally centered
 
 12
-00:00:22,501 --> 00:00:24,501
+00:00:22,501 --> 00:00:24,500
 This text should be at the
 middle and horizontally centered
 
 13
-00:00:22,501 --> 00:00:24,501
+00:00:22,501 --> 00:00:24,500
 This text should be at the
 bottom and horizontally centered
 
 14
-00:00:24,501 --> 00:00:26,501
+00:00:24,501 --> 00:00:26,500
 This text should be at the
 top and horizontally at the left
 
 15
-00:00:24,501 --> 00:00:26,501
+00:00:24,501 --> 00:00:26,500
 This text should be at the
 middle and horizontally at the left
 (The second position must be ignored)
 
 16
-00:00:24,501 --> 00:00:26,501
+00:00:24,501 --> 00:00:26,500
 This text should be at the
 bottom and horizontally at the left
 
 17
-00:00:26,501 --> 00:00:28,501
+00:00:26,501 --> 00:00:28,500
 This text should be at the
 top and horizontally at the right
 
 18
-00:00:26,501 --> 00:00:28,501
+00:00:26,501 --> 00:00:28,500
 This text should be at the
 middle and horizontally at the right
 
 19
-00:00:26,501 --> 00:00:28,501
+00:00:26,501 --> 00:00:28,500
 This text should be at the
 bottom and horizontally at the right
 
 20
-00:00:28,501 --> 00:00:31,501
+00:00:28,501 --> 00:00:31,500
 This could be the most difficult thing to implement
 
 21
-00:00:31,501 --> 00:00:50,501
+00:00:31,501 --> 00:00:50,500
 First text
 
 22
@@ -124,38 +124,38 @@ First text
 Second, it shouldn't overlap first
 
 23
-00:00:35,501 --> 00:00:37,501
+00:00:35,501 --> 00:00:37,500
 Third, it should replace second
 
 24
-00:00:36,501 --> 00:00:50,501
+00:00:36,501 --> 00:00:50,500
 Fourth, it shouldn't overlap first and third
 
 25
-00:00:40,501 --> 00:00:45,501
+00:00:40,501 --> 00:00:45,500
 Fifth, it should replace third
 
 26
-00:00:45,501 --> 00:00:50,501
+00:00:45,501 --> 00:00:50,500
 Sixth, it shouldn't be
 showed overlapped
 
 27
-00:00:50,501 --> 00:00:52,501
+00:00:50,501 --> 00:00:52,500
 TEXT 1 (bottom)
 
 28
-00:00:50,501 --> 00:00:52,501
+00:00:50,501 --> 00:00:52,500
 text 2
 
 29
-00:00:52,501 --> 00:00:54,501
+00:00:52,501 --> 00:00:54,500
 Hide these tags:
 also hide these tags:
 but show this: {normal text}
 
 30
-00:00:54,501 --> 00:01:00,501
+00:00:54,501 --> 00:01:00,500
 
 \ N is a forced line break
 \ h is a hard space
@@ -163,21 +163,21 @@ Normal spaces at the start and at the end of the line are trimmed while hard spa
 The\hline\hwill\hnever\hbreak\hautomatically\hright\hbefore\hor\hafter\ha\hhard\hspace.\h:-D
 
 31
-00:00:54,501 --> 00:00:56,501
+00:00:54,501 --> 00:00:56,500
 
 \h\h\h\h\hA (05 hard spaces followed by a letter)
 A (Normal  spaces followed by a letter)
 A (No hard spaces followed by a letter)
 
 32
-00:00:56,501 --> 00:00:58,501
+00:00:56,501 --> 00:00:58,500
 \h\h\h\h\hA (05 hard spaces followed by a letter)
 A (Normal  spaces followed by a letter)
 A (No hard spaces followed by a letter)
 Show this: \TEST and this: \-)
 
 33
-00:00:58,501 --> 00:01:00,501
+00:00:58,501 --> 00:01:00,500
 
 A letter followed by 05 hard spaces: A\h\h\h\h\h
 A letter followed by normal  spaces: A
@@ -188,26 +188,26 @@ A letter followed by no hard spaces: A
 ^--Forced line break
 
 34
-00:01:00,501 --> 00:01:02,501
+00:01:00,501 --> 00:01:02,500
 Both line should be strikethrough,
 yes.
 Correctly closed tags
 should be hidden.
 
 35
-00:01:02,501 --> 00:01:04,501
+00:01:02,501 --> 00:01:04,500
 It shouldn't be strikethrough,
 not opened tag showed as text.</s>
 Not opened tag showed as text.</xxxxx>
 
 36
-00:01:04,501 --> 00:01:06,501
+00:01:04,501 --> 00:01:06,500
 Three lines should be strikethrough,
 yes.
 <yyyy>Not closed tags showed as text
 
 37
-00:01:06,501 --> 00:01:08,501
+00:01:06,501 --> 00:01:08,500
 Both line should be strikethrough but
 the wrong closing tag should be showed</b>
 
diff --git a/tests/ref/fate/sub-webvttenc b/tests/ref/fate/sub-webvttenc
index dbeadb0..ba567c3 100644
--- a/tests/ref/fate/sub-webvttenc
+++ b/tests/ref/fate/sub-webvttenc
@@ -14,12 +14,12 @@ If you see this with the normal font, the player don't (fully) support font face
 00:04.500 --> 00:04.500
 Hidden
 
-00:04.501 --> 00:07.501
+00:04.501 --> 00:07.500
 This text should be small
 This text should be normal
 This text should be big
 
-00:07.501 --> 00:11.501
+00:07.501 --> 00:11.500
 This should be an E with an accent: È
 日本語
 <b><i><u>This text should be bold, italics and underline</u></i></b>
@@ -27,7 +27,7 @@ This text should be small and green
 This text should be small and red
 This text should be big and brown
 
-00:11.501 --> 00:14.501
+00:11.501 --> 00:14.500
 <b>This line should be bold</b>
 <i>This line should be italics</i>
 <u>This line should be underline</u>
@@ -35,7 +35,7 @@ This line should be strikethrough
 <u>Both lines
 should be underline</u>
 
-00:14.501 --> 00:17.501
+00:14.501 --> 00:17.500
 >
 It would be a good thing to
 hide invalid html tags that are closed and show the text in them
@@ -43,110 +43,110 @@ hide invalid html tags that are closed and show the text in them
 Show not opened tags</invalid_tag_not_opened>
 <
 
-00:17.501 --> 00:20.501
+00:17.501 --> 00:20.500
 and also
 hide invalid html tags with parameters that are closed and show the text in them
 <invalid_tag_uc par=5>but show un-closed invalid html tags
 <u>This text should be showed underlined without problems also: 2<3,5>1,4<6</u>
 This shouldn't be underlined
 
-00:20.501 --> 00:21.501
+00:20.501 --> 00:21.500
 This text should be in the normal position...
 
-00:21.501 --> 00:22.501
+00:21.501 --> 00:22.500
 This text should NOT be in the normal position
 
-00:22.501 --> 00:24.501
+00:22.501 --> 00:24.500
 Implementation is the same of the ASS tag
 This text should be at the
 top and horizontally centered
 
-00:22.501 --> 00:24.501
+00:22.501 --> 00:24.500
 This text should be at the
 middle and horizontally centered
 
-00:22.501 --> 00:24.501
+00:22.501 --> 00:24.500
 This text should be at the
 bottom and horizontally centered
 
-00:24.501 --> 00:26.501
+00:24.501 --> 00:26.500
 This text should be at the
 top and horizontally at the left
 
-00:24.501 --> 00:26.501
+00:24.501 --> 00:26.500
 This text should be at the
 middle and horizontally at the left
 (The second position must be ignored)
 
-00:24.501 --> 00:26.501
+00:24.501 --> 00:26.500
 This text should be at the
 bottom and horizontally at the left
 
-00:26.501 --> 00:28.501
+00:26.501 --> 00:28.500
 This text should be at the
 top and horizontally at the right
 
-00:26.501 --> 00:28.501
+00:26.501 --> 00:28.500
 This text should be at the
 middle and horizontally at the right
 
-00:26.501 --> 00:28.501
+00:26.501 --> 00:28.500
 This text should be at the
 bottom and horizontally at the right
 
-00:28.501 --> 00:31.501
+00:28.501 --> 00:31.500
 This could be the most difficult thing to implement
 
-00:31.501 --> 00:50.501
+00:31.501 --> 00:50.500
 First text
 
 00:33.500 --> 00:35.500
 Second, it shouldn't overlap first
 
-00:35.501 --> 00:37.501
+00:35.501 --> 00:37.500
 Third, it should replace second
 
-00:36.501 --> 00:50.501
+00:36.501 --> 00:50.500
 Fourth, it shouldn't overlap first and third
 
-00:40.501 --> 00:45.501
+00:40.501 --> 00:45.500
 Fifth, it should replace third
 
-00:45.501 --> 00:50.501
+00:45.501 --> 00:50.500
 Sixth, it shouldn't be
 showed overlapped
 
-00:50.501 --> 00:52.501
+00:50.501 --> 00:52.500
 TEXT 1 (bottom)
 
-00:50.501 --> 00:52.501
+00:50.501 --> 00:52.500
 text 2
 
-00:52.501 --> 00:54.501
+00:52.501 --> 00:54.500
 Hide these tags:
 also hide these tags:
 but show this: {normal text}
 
-00:54.501 --> 01:00.501
+00:54.501 --> 01:00.500
 
 \ N is a forced line break
 \ h is a hard space
 Normal spaces at the start and at the end of the line are trimmed while hard spaces are not trimmed.
 The\hline\hwill\hnever\hbreak\hautomatically\hright\hbefore\hor\hafter\ha\hhard\hspace.\h:-D
 
-00:54.501 --> 00:56.501
+00:54.501 --> 00:56.500
 
 \h\h\h\h\hA (05 hard spaces followed by a letter)
 A (Normal  spaces followed by a letter)
 A (No hard spaces followed by a letter)
 
-00:56.501 --> 00:58.501
+00:56.501 --> 00:58.500
 \h\h\h\h\hA (05 hard spaces followed by a letter)
 A (Normal  spaces followed by a letter)
 A (No hard spaces followed by a letter)
 Show this: \TEST and this: \-)
 
-00:58.501 --> 01:00.501
+00:58.501 --> 01:00.500
 
 A letter followed by 05 hard spaces: A\h\h\h\h\h
 A letter followed by normal  spaces: A
@@ -156,22 +156,22 @@ A letter followed by no hard spaces: A
 
 ^--Forced line break
 
-01:00.501 --> 01:02.501
+01:00.501 --> 01:02.500
 Both line should be strikethrough,
 yes.
 Correctly closed tags
 should be hidden.
 
-01:02.501 --> 01:04.501
+01:02.501 --> 01:04.500
 It shouldn't be strikethrough,
 not opened tag showed as text.</s>
 Not opened tag showed as text.</xxxxx>
 
-01:04.501 --> 01:06.501
+01:04.501 --> 01:06.500
 Three lines should be strikethrough,
 yes.
 <yyyy>Not closed tags showed as text
 
-01:06.501 --> 01:08.501
+01:06.501 --> 01:08.500
 Both line should be strikethrough but
 the wrong closing tag should be showed</b>
diff --git a/tests/ref/fate/sub2video b/tests/ref/fate/sub2video
index 3a03cbf..ace6d38 100644
--- a/tests/ref/fate/sub2video
+++ b/tests/ref/fate/sub2video
@@ -1,6 +1,12 @@
 #extradata 1:      150, 0x7c99258b
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 0/1
 #tb 1: 1/1000
+#media_type 1: subtitle
+#codec_id 1: dvd_subtitle
 0,          0,          0,        1,   518400, 0x83c27b82
 0,          1,          1,        1,   518400, 0x4051c7f9
 0,          2,          2,        1,   518400, 0xfb00e17e
diff --git a/tests/ref/fate/sunraster-1bit-raw b/tests/ref/fate/sunraster-1bit-raw
index 123e245..a55a541 100644
--- a/tests/ref/fate/sunraster-1bit-raw
+++ b/tests/ref/fate/sunraster-1bit-raw
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x512
+#sar 0: 0/1
 0,          0,          0,        1,    32768, 0x6d16e246
diff --git a/tests/ref/fate/sunraster-1bit-rle b/tests/ref/fate/sunraster-1bit-rle
index 123e245..a55a541 100644
--- a/tests/ref/fate/sunraster-1bit-rle
+++ b/tests/ref/fate/sunraster-1bit-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x512
+#sar 0: 0/1
 0,          0,          0,        1,    32768, 0x6d16e246
diff --git a/tests/ref/fate/sunraster-24bit-raw b/tests/ref/fate/sunraster-24bit-raw
index fa059ef..dc96609 100644
--- a/tests/ref/fate/sunraster-24bit-raw
+++ b/tests/ref/fate/sunraster-24bit-raw
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x512
+#sar 0: 0/1
 0,          0,          0,        1,   786432, 0xb4d417bf
diff --git a/tests/ref/fate/sunraster-24bit-rle b/tests/ref/fate/sunraster-24bit-rle
index fa059ef..dc96609 100644
--- a/tests/ref/fate/sunraster-24bit-rle
+++ b/tests/ref/fate/sunraster-24bit-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x512
+#sar 0: 0/1
 0,          0,          0,        1,   786432, 0xb4d417bf
diff --git a/tests/ref/fate/sunraster-8bit-raw b/tests/ref/fate/sunraster-8bit-raw
index 659b433..94a1014 100644
--- a/tests/ref/fate/sunraster-8bit-raw
+++ b/tests/ref/fate/sunraster-8bit-raw
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x512
+#sar 0: 0/1
 0,          0,          0,        1,   786432, 0xf4364008
diff --git a/tests/ref/fate/sunraster-8bit-rle b/tests/ref/fate/sunraster-8bit-rle
index 659b433..94a1014 100644
--- a/tests/ref/fate/sunraster-8bit-rle
+++ b/tests/ref/fate/sunraster-8bit-rle
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x512
+#sar 0: 0/1
 0,          0,          0,        1,   786432, 0xf4364008
diff --git a/tests/ref/fate/sunraster-8bit_gray-raw b/tests/ref/fate/sunraster-8bit_gray-raw
index 455af5f..d33a13c 100644
--- a/tests/ref/fate/sunraster-8bit_gray-raw
+++ b/tests/ref/fate/sunraster-8bit_gray-raw
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x768
+#sar 0: 0/1
 0,          0,          0,        1,   786432, 0x5859b48e
diff --git a/tests/ref/fate/svq1 b/tests/ref/fate/svq1
index 3bcf715..d53e295 100644
--- a/tests/ref/fate/svq1
+++ b/tests/ref/fate/svq1
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    21600, 0x7f9389e3
 0,          1,          1,        1,    21600, 0xcebb8896
 0,          2,          2,        1,    21600, 0xef51860a
diff --git a/tests/ref/fate/svq1-headerswap b/tests/ref/fate/svq1-headerswap
index d9f9597..81df227 100644
--- a/tests/ref/fate/svq1-headerswap
+++ b/tests/ref/fate/svq1-headerswap
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 293x178
+#sar 0: 0/1
 0,          0,          0,        1,    58814, 0x5caad04b
 0,          1,          1,        1,    58814, 0x98d8ceb8
 0,          2,          2,        1,    58814, 0x8925cdb0
diff --git a/tests/ref/fate/svq3 b/tests/ref/fate/svq3
index 073d10b..5d90c6b 100644
--- a/tests/ref/fate/svq3
+++ b/tests/ref/fate/svq3
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   115200, 0x2c810465
 0,          1,          1,        1,   115200, 0x010b5765
 0,          2,          2,        1,   115200, 0x2be11a4e
diff --git a/tests/ref/fate/targa-conformance-CBW8 b/tests/ref/fate/targa-conformance-CBW8
index 60270d7..be4bdc3 100644
--- a/tests/ref/fate/targa-conformance-CBW8
+++ b/tests/ref/fate/targa-conformance-CBW8
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x267e21ef
diff --git a/tests/ref/fate/targa-conformance-CCM8 b/tests/ref/fate/targa-conformance-CCM8
index 45bb181..d30fa72 100644
--- a/tests/ref/fate/targa-conformance-CCM8
+++ b/tests/ref/fate/targa-conformance-CCM8
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    65536, 0x47e97fe9
diff --git a/tests/ref/fate/targa-conformance-CTC16 b/tests/ref/fate/targa-conformance-CTC16
index e848ff8..15dfafd 100644
--- a/tests/ref/fate/targa-conformance-CTC16
+++ b/tests/ref/fate/targa-conformance-CTC16
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    32768, 0xa6b3d20d
diff --git a/tests/ref/fate/targa-conformance-CTC24 b/tests/ref/fate/targa-conformance-CTC24
index c95f406..d0b7d66 100644
--- a/tests/ref/fate/targa-conformance-CTC24
+++ b/tests/ref/fate/targa-conformance-CTC24
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    49152, 0xaca4bc29
diff --git a/tests/ref/fate/targa-conformance-CTC32 b/tests/ref/fate/targa-conformance-CTC32
index aad3bfc..1c43896 100644
--- a/tests/ref/fate/targa-conformance-CTC32
+++ b/tests/ref/fate/targa-conformance-CTC32
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    65536, 0xcf98bc29
diff --git a/tests/ref/fate/targa-conformance-UBW8 b/tests/ref/fate/targa-conformance-UBW8
index 60270d7..be4bdc3 100644
--- a/tests/ref/fate/targa-conformance-UBW8
+++ b/tests/ref/fate/targa-conformance-UBW8
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x267e21ef
diff --git a/tests/ref/fate/targa-conformance-UCM8 b/tests/ref/fate/targa-conformance-UCM8
index 45bb181..d30fa72 100644
--- a/tests/ref/fate/targa-conformance-UCM8
+++ b/tests/ref/fate/targa-conformance-UCM8
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    65536, 0x47e97fe9
diff --git a/tests/ref/fate/targa-conformance-UTC16 b/tests/ref/fate/targa-conformance-UTC16
index e848ff8..15dfafd 100644
--- a/tests/ref/fate/targa-conformance-UTC16
+++ b/tests/ref/fate/targa-conformance-UTC16
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    32768, 0xa6b3d20d
diff --git a/tests/ref/fate/targa-conformance-UTC24 b/tests/ref/fate/targa-conformance-UTC24
index c95f406..d0b7d66 100644
--- a/tests/ref/fate/targa-conformance-UTC24
+++ b/tests/ref/fate/targa-conformance-UTC24
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    49152, 0xaca4bc29
diff --git a/tests/ref/fate/targa-conformance-UTC32 b/tests/ref/fate/targa-conformance-UTC32
index aad3bfc..1c43896 100644
--- a/tests/ref/fate/targa-conformance-UTC32
+++ b/tests/ref/fate/targa-conformance-UTC32
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 128x128
+#sar 0: 0/1
 0,          0,          0,        1,    65536, 0xcf98bc29
diff --git a/tests/ref/fate/targa-top-to-bottom b/tests/ref/fate/targa-top-to-bottom
index 4d9577a..6cf1c95 100644
--- a/tests/ref/fate/targa-top-to-bottom
+++ b/tests/ref/fate/targa-top-to-bottom
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 0/1
 0,          0,          0,        1,   196608, 0xb29ec51a
diff --git a/tests/ref/fate/tdsc b/tests/ref/fate/tdsc
index d6925e9..de9f362 100644
--- a/tests/ref/fate/tdsc
+++ b/tests/ref/fate/tdsc
@@ -1,4 +1,8 @@
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1440x900
+#sar 0: 0/1
 0,          0,          0,        1,  3888000, 0x9c498657
 0,          7,          7,        1,  3888000, 0x72a2ae22
 0,          8,          8,        1,  3888000, 0x72a2ae22
diff --git a/tests/ref/fate/theora-coeff-level64 b/tests/ref/fate/theora-coeff-level64
index 4bfafaf..cc64bcc 100644
--- a/tests/ref/fate/theora-coeff-level64
+++ b/tests/ref/fate/theora-coeff-level64
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2960x1040
+#sar 0: 1/1
 0,          0,          0,        1,  4617600, 0x4ba6df50
 0,          1,          1,        1,  4617600, 0x419fdeaf
 0,          2,          2,        1,  4617600, 0xeb2edced
diff --git a/tests/ref/fate/theora-offset b/tests/ref/fate/theora-offset
index 5921657..b9a6e08 100644
--- a/tests/ref/fate/theora-offset
+++ b/tests/ref/fate/theora-offset
@@ -1,4 +1,8 @@
 #tb 0: 1/1
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x512
+#sar 0: 0/1
 0,          0,          0,        1,   393216, 0xdc998fa2
 0,          1,          1,        1,   393216, 0x979a8fbd
 0,          2,          2,        1,   393216, 0x979a8fbd
diff --git a/tests/ref/fate/thp b/tests/ref/fate/thp
index 52dd059..4323ac9 100644
--- a/tests/ref/fate/thp
+++ b/tests/ref/fate/thp
@@ -1,4 +1,8 @@
 #tb 0: 524288/15712911
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 608x320
+#sar 0: 0/1
 0,          0,          0,        1,   291840, 0xbd7e0b22
 0,          1,          1,        1,   291840, 0xf6e12ca5
 0,          2,          2,        1,   291840, 0x528c7049
diff --git a/tests/ref/fate/tiertex-seq b/tests/ref/fate/tiertex-seq
index 74407e7..3504dd4 100644
--- a/tests/ref/fate/tiertex-seq
+++ b/tests/ref/fate/tiertex-seq
@@ -1,5 +1,13 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x128
+#sar 0: 0/1
 #tb 1: 1/22050
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 22050
+#channel_layout 1: 4
 1,          0,          0,      882,     1764, 0x00000000
 1,        882,        882,      882,     1764, 0x80a253d9
 0,          2,          2,        1,    98304, 0x2e5db4a4
diff --git a/tests/ref/fate/tiff-fax-g3 b/tests/ref/fate/tiff-fax-g3
index fa7bc2f..ac1fff9 100644
--- a/tests/ref/fate/tiff-fax-g3
+++ b/tests/ref/fate/tiff-fax-g3
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2464x3248
+#sar 0: 1/1
 0,          0,          0,        1,  1000384, 0xb758eb8b
diff --git a/tests/ref/fate/tiff-fax-g3s b/tests/ref/fate/tiff-fax-g3s
index fa7bc2f..ac1fff9 100644
--- a/tests/ref/fate/tiff-fax-g3s
+++ b/tests/ref/fate/tiff-fax-g3s
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 2464x3248
+#sar 0: 1/1
 0,          0,          0,        1,  1000384, 0xb758eb8b
diff --git a/tests/ref/fate/tmv b/tests/ref/fate/tmv
index 6203e86..94437fa 100644
--- a/tests/ref/fate/tmv
+++ b/tests/ref/fate/tmv
@@ -1,5 +1,13 @@
 #tb 0: 184/11029
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 #tb 1: 1/22058
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 22058
+#channel_layout 1: 4
 0,          0,          0,        1,   192000, 0xc698297a
 1,          0,          0,      368,      736, 0xf63db497
 0,          1,          1,        1,   192000, 0x8d5bd6be
diff --git a/tests/ref/fate/truemotion1-15 b/tests/ref/fate/truemotion1-15
index af4a320..24d4c2c 100644
--- a/tests/ref/fate/truemotion1-15
+++ b/tests/ref/fate/truemotion1-15
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x168
+#sar 0: 1/1
 0,          0,          0,        1,   161280, 0x677c9fb3
 0,          1,          1,        1,   161280, 0xaa280e0a
 0,          2,          2,        1,   161280, 0x8a4d2225
diff --git a/tests/ref/fate/truemotion1-24 b/tests/ref/fate/truemotion1-24
index 73bb9e7..b41eae0 100644
--- a/tests/ref/fate/truemotion1-24
+++ b/tests/ref/fate/truemotion1-24
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 144x160
+#sar 0: 2/1
 0,          0,          0,        1,    69120, 0x68beb30f
 0,          1,          1,        1,    69120, 0x3976f5cf
 0,          2,          2,        1,    69120, 0xf815bc3c
diff --git a/tests/ref/fate/truemotion2 b/tests/ref/fate/truemotion2
index c263ba4..df25f61 100644
--- a/tests/ref/fate/truemotion2
+++ b/tests/ref/fate/truemotion2
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0x135cb509
 0,          1,          1,        1,   230400, 0x919a1ab7
 0,          2,          2,        1,   230400, 0x0af8722b
diff --git a/tests/ref/fate/ts-demux b/tests/ref/fate/ts-demux
new file mode 100644
index 0000000..c66e907
--- /dev/null
+++ b/tests/ref/fate/ts-demux
@@ -0,0 +1,31 @@
+#extradata 0:      150, 0xb4192fb9
+#tb 0: 1/90000
+#media_type 0: video
+#codec_id 0: mpeg2video
+#dimensions 0: 1280x720
+#sar 0: 1/1
+#tb 1: 1/90000
+#media_type 1: audio
+#codec_id 1: ac3
+#sample_rate 1: 48000
+#channel_layout 1: 60f
+1,          0,          0,     2880,     1536, 0x773ffeea, S=1,        1, 0x00bd00bd
+1,       2880,       2880,     2880,     1536, 0x6dc10748
+1,       5760,       5760,     2880,     1536, 0xbab5129c
+1,       8640,       8640,     2880,     1536, 0x602f034b
+1,      11520,      11520,     2880,      906, 0x69cdcbcd
+0,      32037,      36541,     1501,   114336, 0x37a215a8, S=1,        1, 0x00e000e0
+0,      33538,      33538,     1501,    12560, 0xb559a3d4, F=0x0, S=1,        1, 0x00e000e0
+0,      35040,      35040,     1501,    12704, 0x2614adf4, F=0x0, S=1,        1, 0x00e000e0
+0,      36541,      41046,     1501,    51976, 0x9ff1dbfe, F=0x0, S=1,        1, 0x00e000e0
+0,      38043,      38043,     1501,    13096, 0x4ff9ea23, F=0x0, S=1,        1, 0x00e000e0
+0,      39544,      39544,     1501,    13744, 0xf2b2402a, F=0x0, S=1,        1, 0x00e000e0
+0,      41046,      45550,     1501,    56568, 0x65f5aee1, F=0x0, S=1,        1, 0x00e000e0
+0,      42547,      42547,     1501,    14720, 0x8855866c, F=0x0, S=1,        1, 0x00e000e0
+0,      44049,      44049,     1501,    15216, 0x83cbc4fc, F=0x0, S=1,        1, 0x00e000e0
+0,      45550,      50055,     1501,    61720, 0xecda6b05, F=0x0, S=1,        1, 0x00e000e0
+0,      47052,      47052,     1501,    17416, 0xdf480c6d, F=0x0, S=1,        1, 0x00e000e0
+0,      48553,      48553,     1501,    18144, 0x1950624c, F=0x0, S=1,        1, 0x00e000e0
+0,      50055,      54559,     1501,    56848, 0xd4f315be, F=0x0, S=1,        1, 0x00e000e0
+0,      51556,      51556,     1501,    16296, 0xd391a1d0, F=0x0, S=1,        1, 0x00e000e0
+0,      53058,      53058,     1501,     4944, 0x4d88640e, F=0x0
diff --git a/tests/ref/fate/ts-opus-demux b/tests/ref/fate/ts-opus-demux
new file mode 100644
index 0000000..9d2da43
--- /dev/null
+++ b/tests/ref/fate/ts-opus-demux
@@ -0,0 +1,518 @@
+#extradata 0:       30, 0x53be0347
+#tb 0: 1/90000
+#media_type 0: audio
+#codec_id 0: opus
+#sample_rate 0: 48000
+#channel_layout 0: 63f
+0,          0,          0,     1800,      744, 0x172b615b, S=1,        1, 0x00bd00bd
+0,       1800,       1800,     1800,      743, 0x3f5b673d, S=1,        1, 0x00bd00bd
+0,       3600,       3600,     1800,      747, 0xe54e735d, S=1,        1, 0x00bd00bd
+0,       5400,       5400,     1800,      742, 0x5d0d8393, S=1,        1, 0x00bd00bd
+0,       7200,       7200,     1800,      752, 0x39267814, S=1,        1, 0x00bd00bd
+0,       9000,       9000,     1800,      753, 0x2131765e, S=1,        1, 0x00bd00bd
+0,      10800,      10800,     1800,      756, 0x5132827f, S=1,        1, 0x00bd00bd
+0,      12600,      12600,     1800,      761, 0x4857760b, S=1,        1, 0x00bd00bd
+0,      14400,      14400,     1800,      755, 0x87ab75d6, S=1,        1, 0x00bd00bd
+0,      16200,      16200,     1800,      760, 0xb8137907, S=1,        1, 0x00bd00bd
+0,      18000,      18000,     1800,      759, 0x722d7908, S=1,        1, 0x00bd00bd
+0,      19800,      19800,     1800,      760, 0x738674a6, S=1,        1, 0x00bd00bd
+0,      21600,      21600,     1800,      762, 0x4f807c28, S=1,        1, 0x00bd00bd
+0,      23400,      23400,     1800,      761, 0xea117c65, S=1,        1, 0x00bd00bd
+0,      25200,      25200,     1800,      758, 0xa8ad7d2f, S=1,        1, 0x00bd00bd
+0,      27000,      27000,     1800,      756, 0xbea5747a, S=1,        1, 0x00bd00bd
+0,      28800,      28800,     1800,      762, 0x62ce8ab7, S=1,        1, 0x00bd00bd
+0,      30600,      30600,     1800,      763, 0xd7d36ee9, S=1,        1, 0x00bd00bd
+0,      32400,      32400,     1800,      765, 0x068b7b14, S=1,        1, 0x00bd00bd
+0,      34200,      34200,     1800,      772, 0x7c4086f7, S=1,        1, 0x00bd00bd
+0,      36000,      36000,     1800,      817, 0x81828e8c, S=1,        1, 0x00bd00bd
+0,      37800,      37800,     1800,      828, 0x182d9622, S=1,        1, 0x00bd00bd
+0,      39600,      39600,     1800,      952, 0xcb36d7f3, S=1,        1, 0x00bd00bd
+0,      41400,      41400,     1800,      819, 0x94049c46, S=1,        1, 0x00bd00bd
+0,      43200,      43200,     1800,      816, 0x9a0794de, S=1,        1, 0x00bd00bd
+0,      45000,      45000,     1800,      825, 0x2745a0b5, S=1,        1, 0x00bd00bd
+0,      46800,      46800,     1800,      814, 0x4abc994c, S=1,        1, 0x00bd00bd
+0,      48600,      48600,     1800,      824, 0xe49b89ea, S=1,        1, 0x00bd00bd
+0,      50400,      50400,     1800,      815, 0x2f4b8673, S=1,        1, 0x00bd00bd
+0,      52200,      52200,     1800,      824, 0x703da79a, S=1,        1, 0x00bd00bd
+0,      54000,      54000,     1800,      822, 0x41e59285, S=1,        1, 0x00bd00bd
+0,      55800,      55800,     1800,      819, 0xbc4c8f4d, S=1,        1, 0x00bd00bd
+0,      57600,      57600,     1800,      817, 0xba7f9614, S=1,        1, 0x00bd00bd
+0,      59400,      59400,     1800,      826, 0x74cb9b10, S=1,        1, 0x00bd00bd
+0,      61200,      61200,     1800,      822, 0xab4ba435, S=1,        1, 0x00bd00bd
+0,      63000,      63000,     1800,      815, 0xf1209eeb, S=1,        1, 0x00bd00bd
+0,      64800,      64800,     1800,      820, 0x302b8f4a, S=1,        1, 0x00bd00bd
+0,      66600,      66600,     1800,      828, 0x16e29b1b, S=1,        1, 0x00bd00bd
+0,      68400,      68400,     1800,      828, 0x21dba353, S=1,        1, 0x00bd00bd
+0,      70200,      70200,     1800,      942, 0xf51cd517, S=1,        1, 0x00bd00bd
+0,      72000,      72000,     1800,      809, 0x22b29687, S=1,        1, 0x00bd00bd
+0,      73800,      73800,     1800,      823, 0x5a549e20, S=1,        1, 0x00bd00bd
+0,      75600,      75600,     1800,      827, 0x51bc9130, S=1,        1, 0x00bd00bd
+0,      77400,      77400,     1800,      823, 0x9a2d9334, S=1,        1, 0x00bd00bd
+0,      79200,      79200,     1800,      825, 0x6b2c8a1f, S=1,        1, 0x00bd00bd
+0,      81000,      81000,     1800,      828, 0xf11695c9, S=1,        1, 0x00bd00bd
+0,      82800,      82800,     1800,      823, 0xcdb79edf, S=1,        1, 0x00bd00bd
+0,      84600,      84600,     1800,      817, 0x5586950d, S=1,        1, 0x00bd00bd
+0,      86400,      86400,     1800,      813, 0xb4f79688, S=1,        1, 0x00bd00bd
+0,      88200,      88200,     1800,      809, 0xef8e9548, S=1,        1, 0x00bd00bd
+0,      90000,      90000,     1800,      813, 0x08e18b6c, S=1,        1, 0x00bd00bd
+0,      91800,      91800,     1800,      820, 0x94759346, S=1,        1, 0x00bd00bd
+0,      93600,      93600,     1800,      818, 0x7ba198dc, S=1,        1, 0x00bd00bd
+0,      95400,      95400,     1800,      825, 0x96d095fe, S=1,        1, 0x00bd00bd
+0,      97200,      97200,     1800,      808, 0xa72fa0ac, S=1,        1, 0x00bd00bd
+0,      99000,      99000,     1800,      774, 0x36c67f3c, S=1,        1, 0x00bd00bd
+0,     100800,     100800,     1800,      774, 0x08ac8292, S=1,        1, 0x00bd00bd
+0,     102600,     102600,     1800,      777, 0x866591ea, S=1,        1, 0x00bd00bd
+0,     104400,     104400,     1800,      776, 0xd3cb7ec6, S=1,        1, 0x00bd00bd
+0,     106200,     106200,     1800,      779, 0xc6927a93, S=1,        1, 0x00bd00bd
+0,     108000,     108000,     1800,      779, 0x73d182ca, S=1,        1, 0x00bd00bd
+0,     109800,     109800,     1800,      774, 0xd97871d2, S=1,        1, 0x00bd00bd
+0,     111600,     111600,     1800,      772, 0x37228529, S=1,        1, 0x00bd00bd
+0,     113400,     113400,     1800,      779, 0x9f618562, S=1,        1, 0x00bd00bd
+0,     115200,     115200,     1800,      774, 0xee078bd8, S=1,        1, 0x00bd00bd
+0,     117000,     117000,     1800,      772, 0xceed8003, S=1,        1, 0x00bd00bd
+0,     118800,     118800,     1800,      771, 0x8e478da2, S=1,        1, 0x00bd00bd
+0,     120600,     120600,     1800,      776, 0x4fae8319, S=1,        1, 0x00bd00bd
+0,     122400,     122400,     1800,      776, 0xea5d91ab, S=1,        1, 0x00bd00bd
+0,     124200,     124200,     1800,      777, 0x52b988f2, S=1,        1, 0x00bd00bd
+0,     126000,     126000,     1800,      779, 0xb25187e2, S=1,        1, 0x00bd00bd
+0,     127800,     127800,     1800,      779, 0xbe0c88de, S=1,        1, 0x00bd00bd
+0,     129600,     129600,     1800,      774, 0xaab58263, S=1,        1, 0x00bd00bd
+0,     131400,     131400,     1800,      779, 0xd1b58090, S=1,        1, 0x00bd00bd
+0,     133200,     133200,     1800,      782, 0x46229193, S=1,        1, 0x00bd00bd
+0,     135000,     135000,     1800,      776, 0x873c8e09, S=1,        1, 0x00bd00bd
+0,     136800,     136800,     1800,      778, 0x3ea578e8, S=1,        1, 0x00bd00bd
+0,     138600,     138600,     1800,      777, 0xebf88d2c, S=1,        1, 0x00bd00bd
+0,     140400,     140400,     1800,      785, 0x9a8886e2, S=1,        1, 0x00bd00bd
+0,     142200,     142200,     1800,      782, 0x000283d0, S=1,        1, 0x00bd00bd
+0,     144000,     144000,     1800,      782, 0x7c7f7e7f, S=1,        1, 0x00bd00bd
+0,     145800,     145800,     1800,      780, 0xdba17e74, S=1,        1, 0x00bd00bd
+0,     147600,     147600,     1800,      776, 0x7a77823a, S=1,        1, 0x00bd00bd
+0,     149400,     149400,     1800,      780, 0x570e8459, S=1,        1, 0x00bd00bd
+0,     151200,     151200,     1800,      784, 0x13008da0, S=1,        1, 0x00bd00bd
+0,     153000,     153000,     1800,      776, 0xf97b85bb, S=1,        1, 0x00bd00bd
+0,     154800,     154800,     1800,      777, 0x7ea88b95, S=1,        1, 0x00bd00bd
+0,     156600,     156600,     1800,      783, 0x45a07db2, S=1,        1, 0x00bd00bd
+0,     158400,     158400,     1800,      780, 0xc3598deb, S=1,        1, 0x00bd00bd
+0,     160200,     160200,     1800,      782, 0x4aee86d5, S=1,        1, 0x00bd00bd
+0,     162000,     162000,     1800,      848, 0x2ade9d75, S=1,        1, 0x00bd00bd
+0,     163800,     163800,     1800,      849, 0xc617a90e, S=1,        1, 0x00bd00bd
+0,     165600,     165600,     1800,      783, 0xc99d8348, S=1,        1, 0x00bd00bd
+0,     167400,     167400,     1800,      784, 0x01938414, S=1,        1, 0x00bd00bd
+0,     169200,     169200,     1800,      785, 0xaa1e7f3a, S=1,        1, 0x00bd00bd
+0,     171000,     171000,     1800,      783, 0x373984e5, S=1,        1, 0x00bd00bd
+0,     172800,     172800,     1800,      876, 0x30c3b045, S=1,        1, 0x00bd00bd
+0,     174600,     174600,     1800,      776, 0x54b58475, S=1,        1, 0x00bd00bd
+0,     176400,     176400,     1800,      787, 0x76e7856f, S=1,        1, 0x00bd00bd
+0,     178200,     178200,     1800,      781, 0xf1f680c2, S=1,        1, 0x00bd00bd
+0,     180000,     180000,     1800,      852, 0xae8baec5, S=1,        1, 0x00bd00bd
+0,     181800,     181800,     1800,      849, 0x270d9d75, S=1,        1, 0x00bd00bd
+0,     183600,     183600,     1800,      873, 0x3d20ae97, S=1,        1, 0x00bd00bd
+0,     185400,     185400,     1800,      843, 0x0ef4a2e0, S=1,        1, 0x00bd00bd
+0,     187200,     187200,     1800,      841, 0xf2c5ad85, S=1,        1, 0x00bd00bd
+0,     189000,     189000,     1800,      777, 0xebf88dbf, S=1,        1, 0x00bd00bd
+0,     190800,     190800,     1800,      846, 0x77bda358, S=1,        1, 0x00bd00bd
+0,     192600,     192600,     1800,      782, 0x47958532, S=1,        1, 0x00bd00bd
+0,     194400,     194400,     1800,      869, 0xa1c1ae39, S=1,        1, 0x00bd00bd
+0,     196200,     196200,     1800,      778, 0xa7428581, S=1,        1, 0x00bd00bd
+0,     198000,     198000,     1800,      777, 0x550e85c4, S=1,        1, 0x00bd00bd
+0,     199800,     199800,     1800,      870, 0x46c8c374, S=1,        1, 0x00bd00bd
+0,     201600,     201600,     1800,      782, 0x6a44850b, S=1,        1, 0x00bd00bd
+0,     203400,     203400,     1800,      777, 0xb956775e, S=1,        1, 0x00bd00bd
+0,     205200,     205200,     1800,      869, 0x3fc4b23a, S=1,        1, 0x00bd00bd
+0,     207000,     207000,     1800,      772, 0x81568572, S=1,        1, 0x00bd00bd
+0,     208800,     208800,     1800,      775, 0x77688738, S=1,        1, 0x00bd00bd
+0,     210600,     210600,     1800,      771, 0x1f2276f1, S=1,        1, 0x00bd00bd
+0,     212400,     212400,     1800,      778, 0x82ec7e07, S=1,        1, 0x00bd00bd
+0,     214200,     214200,     1800,      867, 0x1042acb8, S=1,        1, 0x00bd00bd
+0,     216000,     216000,     1800,      778, 0x3f007d1a, S=1,        1, 0x00bd00bd
+0,     217800,     217800,     1800,      774, 0x66a08780, S=1,        1, 0x00bd00bd
+0,     219600,     219600,     1800,      775, 0xebdc822d, S=1,        1, 0x00bd00bd
+0,     221400,     221400,     1800,      774, 0x33d7894e, S=1,        1, 0x00bd00bd
+0,     223200,     223200,     1800,      774, 0x734c7623, S=1,        1, 0x00bd00bd
+0,     225000,     225000,     1800,      772, 0xbb9977d2, S=1,        1, 0x00bd00bd
+0,     226800,     226800,     1800,      774, 0x8f8670d1, S=1,        1, 0x00bd00bd
+0,     228600,     228600,     1800,      775, 0x23857f28, S=1,        1, 0x00bd00bd
+0,     230400,     230400,     1800,      773, 0x709f6731, S=1,        1, 0x00bd00bd
+0,     232200,     232200,     1800,      773, 0xc1fa752e, S=1,        1, 0x00bd00bd
+0,     234000,     234000,     1800,      769, 0x2e337fe4, S=1,        1, 0x00bd00bd
+0,     235800,     235800,     1800,      774, 0x4ab07b6f, S=1,        1, 0x00bd00bd
+0,     237600,     237600,     1800,      779, 0x95d386f8, S=1,        1, 0x00bd00bd
+0,     239400,     239400,     1800,      782, 0x38637dc5, S=1,        1, 0x00bd00bd
+0,     241200,     241200,     1800,      779, 0x78a778d5, S=1,        1, 0x00bd00bd
+0,     243000,     243000,     1800,      778, 0xb945760f, S=1,        1, 0x00bd00bd
+0,     244800,     244800,     1800,      771, 0x6749751a, S=1,        1, 0x00bd00bd
+0,     246600,     246600,     1800,      775, 0x05cd7c6d, S=1,        1, 0x00bd00bd
+0,     248400,     248400,     1800,      777, 0x25587463, S=1,        1, 0x00bd00bd
+0,     250200,     250200,     1800,      773, 0x6ab97c1d, S=1,        1, 0x00bd00bd
+0,     252000,     252000,     1800,      777, 0x2b947d43, S=1,        1, 0x00bd00bd
+0,     253800,     253800,     1800,      777, 0x3f337893, S=1,        1, 0x00bd00bd
+0,     255600,     255600,     1800,      908, 0x64b1be4e, S=1,        1, 0x00bd00bd
+0,     257400,     257400,     1800,      777, 0xb480873e, S=1,        1, 0x00bd00bd
+0,     259200,     259200,     1800,      772, 0xb3ec76c2, S=1,        1, 0x00bd00bd
+0,     261000,     261000,     1800,      778, 0x4e7c7ef9, S=1,        1, 0x00bd00bd
+0,     262800,     262800,     1800,      776, 0xcdc6837f, S=1,        1, 0x00bd00bd
+0,     264600,     264600,     1800,      775, 0xf2508942, S=1,        1, 0x00bd00bd
+0,     266400,     266400,     1800,      772, 0x12907489, S=1,        1, 0x00bd00bd
+0,     268200,     268200,     1800,      778, 0x9c6f7ec4, S=1,        1, 0x00bd00bd
+0,     270000,     270000,     1800,      808, 0x00b68b53, S=1,        1, 0x00bd00bd
+0,     271800,     271800,     1800,      836, 0x5eafa13b, S=1,        1, 0x00bd00bd
+0,     273600,     273600,     1800,      913, 0x41bbb8ef, S=1,        1, 0x00bd00bd
+0,     275400,     275400,     1800,      837, 0xc87c9722, S=1,        1, 0x00bd00bd
+0,     277200,     277200,     1800,      834, 0x0f6a9e6b, S=1,        1, 0x00bd00bd
+0,     279000,     279000,     1800,      836, 0x4447af84, S=1,        1, 0x00bd00bd
+0,     280800,     280800,     1800,      832, 0x95bea5c4, S=1,        1, 0x00bd00bd
+0,     282600,     282600,     1800,      826, 0x17b7ab77, S=1,        1, 0x00bd00bd
+0,     284400,     284400,     1800,      817, 0x85eb9dec, S=1,        1, 0x00bd00bd
+0,     286200,     286200,     1800,      825, 0xe21489b4, S=1,        1, 0x00bd00bd
+0,     288000,     288000,     1800,      824, 0xa2719501, S=1,        1, 0x00bd00bd
+0,     289800,     289800,     1800,      828, 0xad3d8dfc, S=1,        1, 0x00bd00bd
+0,     291600,     291600,     1800,      833, 0x39419a9f, S=1,        1, 0x00bd00bd
+0,     293400,     293400,     1800,      832, 0x7b46b0d0, S=1,        1, 0x00bd00bd
+0,     295200,     295200,     1800,      896, 0x351aa129, S=1,        1, 0x00bd00bd
+0,     297000,     297000,     1800,      824, 0x215ba6a6, S=1,        1, 0x00bd00bd
+0,     298800,     298800,     1800,      812, 0x523aa6e4, S=1,        1, 0x00bd00bd
+0,     300600,     300600,     1800,      821, 0x3f3fa6df, S=1,        1, 0x00bd00bd
+0,     302400,     302400,     1800,      883, 0xa87a9886, S=1,        1, 0x00bd00bd
+0,     304200,     304200,     1800,      820, 0xe097a7ee, S=1,        1, 0x00bd00bd
+0,     306000,     306000,     1800,      835, 0xf3a3a496, S=1,        1, 0x00bd00bd
+0,     307800,     307800,     1800,      833, 0xa7d1a13e, S=1,        1, 0x00bd00bd
+0,     309600,     309600,     1800,      830, 0xab719f25, S=1,        1, 0x00bd00bd
+0,     311400,     311400,     1800,      820, 0x80599754, S=1,        1, 0x00bd00bd
+0,     313200,     313200,     1800,      815, 0x517e8dec, S=1,        1, 0x00bd00bd
+0,     315000,     315000,     1800,      827, 0x8e33855b, S=1,        1, 0x00bd00bd
+0,     316800,     316800,     1800,      819, 0x6a7d88a3, S=1,        1, 0x00bd00bd
+0,     318600,     318600,     1800,      828, 0x69b09497, S=1,        1, 0x00bd00bd
+0,     320400,     320400,     1800,      830, 0x72cb9f2a, S=1,        1, 0x00bd00bd
+0,     322200,     322200,     1800,      828, 0xb7299897, S=1,        1, 0x00bd00bd
+0,     324000,     324000,     1800,      829, 0x9dcaa4b8, S=1,        1, 0x00bd00bd
+0,     325800,     325800,     1800,      820, 0x6303a6bd, S=1,        1, 0x00bd00bd
+0,     327600,     327600,     1800,      823, 0xf1d694e7, S=1,        1, 0x00bd00bd
+0,     329400,     329400,     1800,      798, 0x6add8cfc, S=1,        1, 0x00bd00bd
+0,     331200,     331200,     1800,      772, 0xd7927331, S=1,        1, 0x00bd00bd
+0,     333000,     333000,     1800,      779, 0x82eb7660, S=1,        1, 0x00bd00bd
+0,     334800,     334800,     1800,      774, 0x50217e2b, S=1,        1, 0x00bd00bd
+0,     336600,     336600,     1800,      907, 0xfcd7bc7e, S=1,        1, 0x00bd00bd
+0,     338400,     338400,     1800,      772, 0x433b6c19, S=1,        1, 0x00bd00bd
+0,     340200,     340200,     1800,      777, 0xf3737c93, S=1,        1, 0x00bd00bd
+0,     342000,     342000,     1800,      777, 0x74c18580, S=1,        1, 0x00bd00bd
+0,     343800,     343800,     1800,      777, 0xb4d97b39, S=1,        1, 0x00bd00bd
+0,     345600,     345600,     1800,      775, 0xde3a85fd, S=1,        1, 0x00bd00bd
+0,     347400,     347400,     1800,      773, 0xf2fc8d11, S=1,        1, 0x00bd00bd
+0,     349200,     349200,     1800,      777, 0xac3f86d0, S=1,        1, 0x00bd00bd
+0,     351000,     351000,     1800,      777, 0x6a138265, S=1,        1, 0x00bd00bd
+0,     352800,     352800,     1800,      776, 0xfbb58ca1, S=1,        1, 0x00bd00bd
+0,     354600,     354600,     1800,      780, 0xd28a84cf, S=1,        1, 0x00bd00bd
+0,     356400,     356400,     1800,      776, 0x623a7e56, S=1,        1, 0x00bd00bd
+0,     358200,     358200,     1800,      778, 0xccb17d51, S=1,        1, 0x00bd00bd
+0,     360000,     360000,     1800,      774, 0x15747fcb, S=1,        1, 0x00bd00bd
+0,     361800,     361800,     1800,      778, 0xebf48852, S=1,        1, 0x00bd00bd
+0,     363600,     363600,     1800,      777, 0xec0d71f5, S=1,        1, 0x00bd00bd
+0,     365400,     365400,     1800,      773, 0xea328055, S=1,        1, 0x00bd00bd
+0,     367200,     367200,     1800,      782, 0xc47c8ba6, S=1,        1, 0x00bd00bd
+0,     369000,     369000,     1800,      780, 0x9de38ea5, S=1,        1, 0x00bd00bd
+0,     370800,     370800,     1800,      777, 0xa1d989c3, S=1,        1, 0x00bd00bd
+0,     372600,     372600,     1800,      775, 0xff8e829b, S=1,        1, 0x00bd00bd
+0,     374400,     374400,     1800,      777, 0x7f4685bd, S=1,        1, 0x00bd00bd
+0,     376200,     376200,     1800,      776, 0x911090ef, S=1,        1, 0x00bd00bd
+0,     378000,     378000,     1800,      778, 0x47a086b1, S=1,        1, 0x00bd00bd
+0,     379800,     379800,     1800,      775, 0x83f081f4, S=1,        1, 0x00bd00bd
+0,     381600,     381600,     1800,      775, 0xf7d48741, S=1,        1, 0x00bd00bd
+0,     383400,     383400,     1800,      779, 0x2c087a7b, S=1,        1, 0x00bd00bd
+0,     385200,     385200,     1800,      779, 0x5c77857a, S=1,        1, 0x00bd00bd
+0,     387000,     387000,     1800,      778, 0x46907b70, S=1,        1, 0x00bd00bd
+0,     388800,     388800,     1800,      780, 0xc3a88f68, S=1,        1, 0x00bd00bd
+0,     390600,     390600,     1800,      778, 0x35aa818b, S=1,        1, 0x00bd00bd
+0,     392400,     392400,     1800,      776, 0xfb3d749c, S=1,        1, 0x00bd00bd
+0,     394200,     394200,     1800,      777, 0x95e37fda, S=1,        1, 0x00bd00bd
+0,     396000,     396000,     1800,      841, 0xbfffa393, S=1,        1, 0x00bd00bd
+0,     397800,     397800,     1800,      777, 0x63858f67, S=1,        1, 0x00bd00bd
+0,     399600,     399600,     1800,      780, 0xe277884b, S=1,        1, 0x00bd00bd
+0,     401400,     401400,     1800,      777, 0x1e658659, S=1,        1, 0x00bd00bd
+0,     403200,     403200,     1800,      777, 0x0ed17df3, S=1,        1, 0x00bd00bd
+0,     405000,     405000,     1800,      778, 0x804b6fad, S=1,        1, 0x00bd00bd
+0,     406800,     406800,     1800,      778, 0x6b2c8512, S=1,        1, 0x00bd00bd
+0,     408600,     408600,     1800,      779, 0x6ca776d3, S=1,        1, 0x00bd00bd
+0,     410400,     410400,     1800,      776, 0x6a8b8ea9, S=1,        1, 0x00bd00bd
+0,     412200,     412200,     1800,      784, 0x1a367f43, S=1,        1, 0x00bd00bd
+0,     414000,     414000,     1800,      776, 0x19d2865a, S=1,        1, 0x00bd00bd
+0,     415800,     415800,     1800,      778, 0xb00d860f, S=1,        1, 0x00bd00bd
+0,     417600,     417600,     1800,      775, 0x9d4f7b80, S=1,        1, 0x00bd00bd
+0,     419400,     419400,     1800,      781, 0x42f1863b, S=1,        1, 0x00bd00bd
+0,     421200,     421200,     1800,      779, 0x6b669d4e, S=1,        1, 0x00bd00bd
+0,     423000,     423000,     1800,      846, 0x9a3fab04, S=1,        1, 0x00bd00bd
+0,     424800,     424800,     1800,      776, 0x2db875e2, S=1,        1, 0x00bd00bd
+0,     426600,     426600,     1800,      781, 0xbadf8580, S=1,        1, 0x00bd00bd
+0,     428400,     428400,     1800,      783, 0xed878378, S=1,        1, 0x00bd00bd
+0,     430200,     430200,     1800,      971, 0xf23af2a9, S=1,        1, 0x00bd00bd
+0,     432000,     432000,     1800,      970, 0xcecfee4f, S=1,        1, 0x00bd00bd
+0,     433800,     433800,     1800,      967, 0xc737eee7, S=1,        1, 0x00bd00bd
+0,     435600,     435600,     1800,      776, 0x113d8458, S=1,        1, 0x00bd00bd
+0,     437400,     437400,     1800,      971, 0xd8a3e77e, S=1,        1, 0x00bd00bd
+0,     439200,     439200,     1800,      962, 0xe454e344, S=1,        1, 0x00bd00bd
+0,     441000,     441000,     1800,      964, 0x01bce383, S=1,        1, 0x00bd00bd
+0,     442800,     442800,     1800,      773, 0xb257800b, S=1,        1, 0x00bd00bd
+0,     444600,     444600,     1800,      770, 0x390a8fc9, S=1,        1, 0x00bd00bd
+0,     446400,     446400,     1800,      964, 0xb377dc40, S=1,        1, 0x00bd00bd
+0,     448200,     448200,     1800,      958, 0x725dd1bc, S=1,        1, 0x00bd00bd
+0,     450000,     450000,     1800,      775, 0x71676ef9, S=1,        1, 0x00bd00bd
+0,     451800,     451800,     1800,      775, 0x302f7be4, S=1,        1, 0x00bd00bd
+0,     453600,     453600,     1800,      966, 0x15e2ddfc, S=1,        1, 0x00bd00bd
+0,     455400,     455400,     1800,      843, 0xa374a091, S=1,        1, 0x00bd00bd
+0,     457200,     457200,     1800,      846, 0xfeeea12f, S=1,        1, 0x00bd00bd
+0,     459000,     459000,     1800,      775, 0xba4278d4, S=1,        1, 0x00bd00bd
+0,     460800,     460800,     1800,      901, 0xc135cbd2, S=1,        1, 0x00bd00bd
+0,     462600,     462600,     1800,      958, 0x7785ce8a, S=1,        1, 0x00bd00bd
+0,     464400,     464400,     1800,      770, 0x93ff72e0, S=1,        1, 0x00bd00bd
+0,     466200,     466200,     1800,      773, 0x4b858520, S=1,        1, 0x00bd00bd
+0,     468000,     468000,     1800,      768, 0xf9718bc1, S=1,        1, 0x00bd00bd
+0,     469800,     469800,     1800,      776, 0x42978a5d, S=1,        1, 0x00bd00bd
+0,     471600,     471600,     1800,      771, 0xd40f85f4, S=1,        1, 0x00bd00bd
+0,     473400,     473400,     1800,      772, 0x9e39814e, S=1,        1, 0x00bd00bd
+0,     475200,     475200,     1800,      958, 0xa402dd54, S=1,        1, 0x00bd00bd
+0,     477000,     477000,     1800,      771, 0xef48765c, S=1,        1, 0x00bd00bd
+0,     478800,     478800,     1800,      770, 0x20367c7c, S=1,        1, 0x00bd00bd
+0,     480600,     480600,     1800,      959, 0xd855ce75, S=1,        1, 0x00bd00bd
+0,     482400,     482400,     1800,      769, 0x44e9805f, S=1,        1, 0x00bd00bd
+0,     484200,     484200,     1800,      840, 0x0ceb90b9, S=1,        1, 0x00bd00bd
+0,     486000,     486000,     1800,      769, 0xeb0b7c25, S=1,        1, 0x00bd00bd
+0,     487800,     487800,     1800,      767, 0x5c278027, S=1,        1, 0x00bd00bd
+0,     489600,     489600,     1800,      951, 0xa9b6dc3f, S=1,        1, 0x00bd00bd
+0,     491400,     491400,     1800,      769, 0x4082825f, S=1,        1, 0x00bd00bd
+0,     493200,     493200,     1800,      958, 0xd71fe68a, S=1,        1, 0x00bd00bd
+0,     495000,     495000,     1800,      773, 0x35f789cd, S=1,        1, 0x00bd00bd
+0,     496800,     496800,     1800,      771, 0xa15d7ecb, S=1,        1, 0x00bd00bd
+0,     498600,     498600,     1800,      768, 0x35e77aca, S=1,        1, 0x00bd00bd
+0,     500400,     500400,     1800,      765, 0xe23f73a5, S=1,        1, 0x00bd00bd
+0,     502200,     502200,     1800,      774, 0xa2ef7cac, S=1,        1, 0x00bd00bd
+0,     504000,     504000,     1800,      837, 0x235494f2, S=1,        1, 0x00bd00bd
+0,     505800,     505800,     1800,      773, 0x88538175, S=1,        1, 0x00bd00bd
+0,     507600,     507600,     1800,      773, 0x177981fa, S=1,        1, 0x00bd00bd
+0,     509400,     509400,     1800,      770, 0x273d7364, S=1,        1, 0x00bd00bd
+0,     511200,     511200,     1800,      770, 0x3e837bf6, S=1,        1, 0x00bd00bd
+0,     513000,     513000,     1800,      774, 0x08219078, S=1,        1, 0x00bd00bd
+0,     514800,     514800,     1800,      767, 0xeb5f797c, S=1,        1, 0x00bd00bd
+0,     516600,     516600,     1800,      774, 0x8eaa7a45, S=1,        1, 0x00bd00bd
+0,     518400,     518400,     1800,      833, 0x73249305, S=1,        1, 0x00bd00bd
+0,     520200,     520200,     1800,      774, 0x97e585d5, S=1,        1, 0x00bd00bd
+0,     522000,     522000,     1800,      768, 0x45b278fe, S=1,        1, 0x00bd00bd
+0,     523800,     523800,     1800,      773, 0xacf47d25, S=1,        1, 0x00bd00bd
+0,     525600,     525600,     1800,      768, 0xd382773d, S=1,        1, 0x00bd00bd
+0,     527400,     527400,     1800,      769, 0x20e97a5f, S=1,        1, 0x00bd00bd
+0,     529200,     529200,     1800,      767, 0x0ef67dab, S=1,        1, 0x00bd00bd
+0,     531000,     531000,     1800,      773, 0x5fa98693, S=1,        1, 0x00bd00bd
+0,     532800,     532800,     1800,      774, 0xd27686ab, S=1,        1, 0x00bd00bd
+0,     534600,     534600,     1800,      769, 0xc3d67ac2, S=1,        1, 0x00bd00bd
+0,     536400,     536400,     1800,      833, 0x80c89f70, S=1,        1, 0x00bd00bd
+0,     538200,     538200,     1800,      768, 0x5000776f, S=1,        1, 0x00bd00bd
+0,     540000,     540000,     1800,      772, 0x79b2812e, S=1,        1, 0x00bd00bd
+0,     541800,     541800,     1800,      839, 0x5276ad2b, S=1,        1, 0x00bd00bd
+0,     543600,     543600,     1800,      769, 0xa58279b1, S=1,        1, 0x00bd00bd
+0,     545400,     545400,     1800,      769, 0x826f8c2c, S=1,        1, 0x00bd00bd
+0,     547200,     547200,     1800,      771, 0x5a508980, S=1,        1, 0x00bd00bd
+0,     549000,     549000,     1800,      770, 0x659a7e09, S=1,        1, 0x00bd00bd
+0,     550800,     550800,     1800,      771, 0x30ef74db, S=1,        1, 0x00bd00bd
+0,     552600,     552600,     1800,      767, 0xc75d84cd, S=1,        1, 0x00bd00bd
+0,     554400,     554400,     1800,      899, 0x9881c627, S=1,        1, 0x00bd00bd
+0,     556200,     556200,     1800,      953, 0x0c90bd10, S=1,        1, 0x00bd00bd
+0,     558000,     558000,     1800,      770, 0x2cdf8498, S=1,        1, 0x00bd00bd
+0,     559800,     559800,     1800,      770, 0x0fdc7c67, S=1,        1, 0x00bd00bd
+0,     561600,     561600,     1800,      771, 0x721a7d42, S=1,        1, 0x00bd00bd
+0,     563400,     563400,     1800,      770, 0x164c71fc, S=1,        1, 0x00bd00bd
+0,     565200,     565200,     1800,      769, 0xc36f7c71, S=1,        1, 0x00bd00bd
+0,     567000,     567000,     1800,      896, 0xfad5bc39, S=1,        1, 0x00bd00bd
+0,     568800,     568800,     1800,      957, 0x08c8e4ff, S=1,        1, 0x00bd00bd
+0,     570600,     570600,     1800,      773, 0x009b81a0, S=1,        1, 0x00bd00bd
+0,     572400,     572400,     1800,      774, 0xa26d83e9, S=1,        1, 0x00bd00bd
+0,     574200,     574200,     1800,      956, 0x0544dde1, S=1,        1, 0x00bd00bd
+0,     576000,     576000,     1800,      768, 0x3e4887f3, S=1,        1, 0x00bd00bd
+0,     577800,     577800,     1800,      770, 0x24007a3a, S=1,        1, 0x00bd00bd
+0,     579600,     579600,     1800,      771, 0x14508287, S=1,        1, 0x00bd00bd
+0,     581400,     581400,     1800,      955, 0xa0f3de18, S=1,        1, 0x00bd00bd
+0,     583200,     583200,     1800,      953, 0xcb75d2ff, S=1,        1, 0x00bd00bd
+0,     585000,     585000,     1800,      767, 0x85ec747e, S=1,        1, 0x00bd00bd
+0,     586800,     586800,     1800,      768, 0x8b2971a1, S=1,        1, 0x00bd00bd
+0,     588600,     588600,     1800,      774, 0xc73b8a85, S=1,        1, 0x00bd00bd
+0,     590400,     590400,     1800,      835, 0xe77e9333, S=1,        1, 0x00bd00bd
+0,     592200,     592200,     1800,      768, 0x52428713, S=1,        1, 0x00bd00bd
+0,     594000,     594000,     1800,      769, 0xf62377f5, S=1,        1, 0x00bd00bd
+0,     595800,     595800,     1800,      771, 0xb0827990, S=1,        1, 0x00bd00bd
+0,     597600,     597600,     1800,      771, 0xb93a8522, S=1,        1, 0x00bd00bd
+0,     599400,     599400,     1800,      770, 0x9e748d23, S=1,        1, 0x00bd00bd
+0,     601200,     601200,     1800,      768, 0x92d6779e, S=1,        1, 0x00bd00bd
+0,     603000,     603000,     1800,      951, 0x371ae535, S=1,        1, 0x00bd00bd
+0,     604800,     604800,     1800,      950, 0xe273dfb9, S=1,        1, 0x00bd00bd
+0,     606600,     606600,     1800,      947, 0xe806d1f7, S=1,        1, 0x00bd00bd
+0,     608400,     608400,     1800,      956, 0x9c61d286, S=1,        1, 0x00bd00bd
+0,     610200,     610200,     1800,      951, 0x76b5ee35, S=1,        1, 0x00bd00bd
+0,     612000,     612000,     1800,      943, 0xcfe7e11b, S=1,        1, 0x00bd00bd
+0,     613800,     613800,     1800,      766, 0xcc83760a, S=1,        1, 0x00bd00bd
+0,     615600,     615600,     1800,      890, 0xafbbbb4d, S=1,        1, 0x00bd00bd
+0,     617400,     617400,     1800,      952, 0x6fbade31, S=1,        1, 0x00bd00bd
+0,     619200,     619200,     1800,      766, 0x49ba84d4, S=1,        1, 0x00bd00bd
+0,     621000,     621000,     1800,      767, 0xb29e6f83, S=1,        1, 0x00bd00bd
+0,     622800,     622800,     1800,      760, 0xffe47a95, S=1,        1, 0x00bd00bd
+0,     624600,     624600,     1800,      946, 0x768cddda, S=1,        1, 0x00bd00bd
+0,     626400,     626400,     1800,      769, 0x1a228c70, S=1,        1, 0x00bd00bd
+0,     628200,     628200,     1800,      760, 0xa6287fd7, S=1,        1, 0x00bd00bd
+0,     630000,     630000,     1800,      762, 0x1d2d76b1, S=1,        1, 0x00bd00bd
+0,     631800,     631800,     1800,      767, 0x047c845c, S=1,        1, 0x00bd00bd
+0,     633600,     633600,     1800,      767, 0xea6c7a91, S=1,        1, 0x00bd00bd
+0,     635400,     635400,     1800,      763, 0x49d47134, S=1,        1, 0x00bd00bd
+0,     637200,     637200,     1800,      760, 0xb29a6ea7, S=1,        1, 0x00bd00bd
+0,     639000,     639000,     1800,      763, 0x14458825, S=1,        1, 0x00bd00bd
+0,     640800,     640800,     1800,      764, 0x6f437f87, S=1,        1, 0x00bd00bd
+0,     642600,     642600,     1800,      764, 0xa1757bce, S=1,        1, 0x00bd00bd
+0,     644400,     644400,     1800,      763, 0x77b8863b, S=1,        1, 0x00bd00bd
+0,     646200,     646200,     1800,      763, 0x2edf70dd, S=1,        1, 0x00bd00bd
+0,     648000,     648000,     1800,      764, 0x96177b9f, S=1,        1, 0x00bd00bd
+0,     649800,     649800,     1800,      766, 0xa75168cf, S=1,        1, 0x00bd00bd
+0,     651600,     651600,     1800,      767, 0xba19756f, S=1,        1, 0x00bd00bd
+0,     653400,     653400,     1800,      765, 0x7e0676dd, S=1,        1, 0x00bd00bd
+0,     655200,     655200,     1800,      767, 0x60a18dbd, S=1,        1, 0x00bd00bd
+0,     657000,     657000,     1800,      763, 0x094d7636, S=1,        1, 0x00bd00bd
+0,     658800,     658800,     1800,      767, 0x0cfa8023, S=1,        1, 0x00bd00bd
+0,     660600,     660600,     1800,      768, 0x69ec81c5, S=1,        1, 0x00bd00bd
+0,     662400,     662400,     1800,      764, 0x153f78ff, S=1,        1, 0x00bd00bd
+0,     664200,     664200,     1800,      765, 0x08f98ede, S=1,        1, 0x00bd00bd
+0,     666000,     666000,     1800,      764, 0xb0547fe9, S=1,        1, 0x00bd00bd
+0,     667800,     667800,     1800,      769, 0x7b687865, S=1,        1, 0x00bd00bd
+0,     669600,     669600,     1800,      766, 0x238e80e1, S=1,        1, 0x00bd00bd
+0,     671400,     671400,     1800,      766, 0x684183f2, S=1,        1, 0x00bd00bd
+0,     673200,     673200,     1800,      829, 0xe9e0995d, S=1,        1, 0x00bd00bd
+0,     675000,     675000,     1800,      765, 0xa0047b3a, S=1,        1, 0x00bd00bd
+0,     676800,     676800,     1800,      766, 0x5afb7c11, S=1,        1, 0x00bd00bd
+0,     678600,     678600,     1800,      766, 0xce5f7f35, S=1,        1, 0x00bd00bd
+0,     680400,     680400,     1800,      898, 0x467ac6b9, S=1,        1, 0x00bd00bd
+0,     682200,     682200,     1800,      767, 0x594c7b13, S=1,        1, 0x00bd00bd
+0,     684000,     684000,     1800,      896, 0x79e8b3c6, S=1,        1, 0x00bd00bd
+0,     685800,     685800,     1800,      764, 0x1f9264c5, S=1,        1, 0x00bd00bd
+0,     687600,     687600,     1800,      762, 0x068c830f, S=1,        1, 0x00bd00bd
+0,     689400,     689400,     1800,      762, 0xd940760a, S=1,        1, 0x00bd00bd
+0,     691200,     691200,     1800,      763, 0xbad583c4, S=1,        1, 0x00bd00bd
+0,     693000,     693000,     1800,      947, 0xf61ed65c, S=1,        1, 0x00bd00bd
+0,     694800,     694800,     1800,      767, 0x03a078ea, S=1,        1, 0x00bd00bd
+0,     696600,     696600,     1800,      957, 0x7762e49b, S=1,        1, 0x00bd00bd
+0,     698400,     698400,     1800,      955, 0x1541d660, S=1,        1, 0x00bd00bd
+0,     700200,     700200,     1800,      767, 0xd6798911, S=1,        1, 0x00bd00bd
+0,     702000,     702000,     1800,      767, 0x4f317dff, S=1,        1, 0x00bd00bd
+0,     703800,     703800,     1800,      764, 0x47e17b33, S=1,        1, 0x00bd00bd
+0,     705600,     705600,     1800,      763, 0x0c0c86b8, S=1,        1, 0x00bd00bd
+0,     707400,     707400,     1800,      769, 0x18558aee, S=1,        1, 0x00bd00bd
+0,     709200,     709200,     1800,      766, 0xe0aa764b, S=1,        1, 0x00bd00bd
+0,     711000,     711000,     1800,      762, 0x87357d81, S=1,        1, 0x00bd00bd
+0,     712800,     712800,     1800,      766, 0xdc8b7167, S=1,        1, 0x00bd00bd
+0,     714600,     714600,     1800,      768, 0x7dbe92db, S=1,        1, 0x00bd00bd
+0,     716400,     716400,     1800,      765, 0xb451867e, S=1,        1, 0x00bd00bd
+0,     718200,     718200,     1800,      953, 0x12d7d687, S=1,        1, 0x00bd00bd
+0,     720000,     720000,     1800,      769, 0x649c7d28, S=1,        1, 0x00bd00bd
+0,     721800,     721800,     1800,      955, 0xce1fd2aa, S=1,        1, 0x00bd00bd
+0,     723600,     723600,     1800,      952, 0x247dd870, S=1,        1, 0x00bd00bd
+0,     725400,     725400,     1800,      951, 0x36d4da18, S=1,        1, 0x00bd00bd
+0,     727200,     727200,     1800,      954, 0xbe6bd18f, S=1,        1, 0x00bd00bd
+0,     729000,     729000,     1800,      948, 0xc770ca89, S=1,        1, 0x00bd00bd
+0,     730800,     730800,     1800,      761, 0x9c5d77ea, S=1,        1, 0x00bd00bd
+0,     732600,     732600,     1800,      763, 0xdedd88e0, S=1,        1, 0x00bd00bd
+0,     734400,     734400,     1800,      760, 0x742a8286, S=1,        1, 0x00bd00bd
+0,     736200,     736200,     1800,      764, 0x89917053, S=1,        1, 0x00bd00bd
+0,     738000,     738000,     1800,      764, 0x77447622, S=1,        1, 0x00bd00bd
+0,     739800,     739800,     1800,      946, 0x9ebad2bd, S=1,        1, 0x00bd00bd
+0,     741600,     741600,     1800,      758, 0x638a836d, S=1,        1, 0x00bd00bd
+0,     743400,     743400,     1800,      950, 0x285ec904, S=1,        1, 0x00bd00bd
+0,     745200,     745200,     1800,      769, 0x43107232, S=1,        1, 0x00bd00bd
+0,     747000,     747000,     1800,      764, 0x996b7a0f, S=1,        1, 0x00bd00bd
+0,     748800,     748800,     1800,      757, 0xa5356f50, S=1,        1, 0x00bd00bd
+0,     750600,     750600,     1800,      761, 0x628e7c55, S=1,        1, 0x00bd00bd
+0,     752400,     752400,     1800,      761, 0xcbcc7416, S=1,        1, 0x00bd00bd
+0,     754200,     754200,     1800,      759, 0x34bc71ba, S=1,        1, 0x00bd00bd
+0,     756000,     756000,     1800,      758, 0xcca27ff3, S=1,        1, 0x00bd00bd
+0,     757800,     757800,     1800,      767, 0x7ab882b6, S=1,        1, 0x00bd00bd
+0,     759600,     759600,     1800,      761, 0xcbd7854a, S=1,        1, 0x00bd00bd
+0,     761400,     761400,     1800,      828, 0x55be93e0, S=1,        1, 0x00bd00bd
+0,     763200,     763200,     1800,      759, 0xb6fb804c, S=1,        1, 0x00bd00bd
+0,     765000,     765000,     1800,      761, 0x331d7b48, S=1,        1, 0x00bd00bd
+0,     766800,     766800,     1800,      762, 0xa84e7e9b, S=1,        1, 0x00bd00bd
+0,     768600,     768600,     1800,      761, 0x97448037, S=1,        1, 0x00bd00bd
+0,     770400,     770400,     1800,      757, 0xc82186bc, S=1,        1, 0x00bd00bd
+0,     772200,     772200,     1800,      759, 0x82ab8746, S=1,        1, 0x00bd00bd
+0,     774000,     774000,     1800,      759, 0x884f6d1a, S=1,        1, 0x00bd00bd
+0,     775800,     775800,     1800,      761, 0xf2906fa9, S=1,        1, 0x00bd00bd
+0,     777600,     777600,     1800,      756, 0x3eb76a17, S=1,        1, 0x00bd00bd
+0,     779400,     779400,     1800,      765, 0x4de67a40, S=1,        1, 0x00bd00bd
+0,     781200,     781200,     1800,      759, 0x2e7c7b1e, S=1,        1, 0x00bd00bd
+0,     783000,     783000,     1800,      759, 0xdac278fa, S=1,        1, 0x00bd00bd
+0,     784800,     784800,     1800,      761, 0x5caf700e, S=1,        1, 0x00bd00bd
+0,     786600,     786600,     1800,      762, 0xd4107b13, S=1,        1, 0x00bd00bd
+0,     788400,     788400,     1800,      771, 0xe4f16cd4, S=1,        1, 0x00bd00bd
+0,     790200,     790200,     1800,      758, 0x96088772, S=1,        1, 0x00bd00bd
+0,     792000,     792000,     1800,      759, 0x68fd798d, S=1,        1, 0x00bd00bd
+0,     793800,     793800,     1800,      760, 0x7c896c77, S=1,        1, 0x00bd00bd
+0,     795600,     795600,     1800,      762, 0x10f07df6, S=1,        1, 0x00bd00bd
+0,     797400,     797400,     1800,      760, 0x902373b8, S=1,        1, 0x00bd00bd
+0,     799200,     799200,     1800,      760, 0xd9db8045, S=1,        1, 0x00bd00bd
+0,     801000,     801000,     1800,      757, 0x5164796e, S=1,        1, 0x00bd00bd
+0,     802800,     802800,     1800,      762, 0x41f278ba, S=1,        1, 0x00bd00bd
+0,     804600,     804600,     1800,      763, 0x04e676b1, S=1,        1, 0x00bd00bd
+0,     806400,     806400,     1800,      835, 0x035899d3, S=1,        1, 0x00bd00bd
+0,     808200,     808200,     1800,      758, 0x90b7828e, S=1,        1, 0x00bd00bd
+0,     810000,     810000,     1800,      761, 0x2f446e0e, S=1,        1, 0x00bd00bd
+0,     811800,     811800,     1800,      888, 0x3c6cb74c, S=1,        1, 0x00bd00bd
+0,     813600,     813600,     1800,      758, 0x8f267d72, S=1,        1, 0x00bd00bd
+0,     815400,     815400,     1800,      765, 0xaa2f7f16, S=1,        1, 0x00bd00bd
+0,     817200,     817200,     1800,      761, 0x8b3d7e23, S=1,        1, 0x00bd00bd
+0,     819000,     819000,     1800,      764, 0xd4d981fb, S=1,        1, 0x00bd00bd
+0,     820800,     820800,     1800,      762, 0xa98d740b, S=1,        1, 0x00bd00bd
+0,     822600,     822600,     1800,      767, 0xad358079, S=1,        1, 0x00bd00bd
+0,     824400,     824400,     1800,      759, 0x165875cb, S=1,        1, 0x00bd00bd
+0,     826200,     826200,     1800,      761, 0x65d17adf, S=1,        1, 0x00bd00bd
+0,     828000,     828000,     1800,      762, 0x89927901, S=1,        1, 0x00bd00bd
+0,     829800,     829800,     1800,      763, 0xdee4742c, S=1,        1, 0x00bd00bd
+0,     831600,     831600,     1800,      760, 0xd6197581, S=1,        1, 0x00bd00bd
+0,     833400,     833400,     1800,      832, 0x83398c5a, S=1,        1, 0x00bd00bd
+0,     835200,     835200,     1800,      761, 0x90a48500, S=1,        1, 0x00bd00bd
+0,     837000,     837000,     1800,      887, 0xf8fbc1cf, S=1,        1, 0x00bd00bd
+0,     838800,     838800,     1800,      765, 0x196f800a, S=1,        1, 0x00bd00bd
+0,     840600,     840600,     1800,      763, 0x70e581d8, S=1,        1, 0x00bd00bd
+0,     842400,     842400,     1800,      763, 0x79087b7d, S=1,        1, 0x00bd00bd
+0,     844200,     844200,     1800,      952, 0x5862f4fe, S=1,        1, 0x00bd00bd
+0,     846000,     846000,     1800,      953, 0x2c00dc09, S=1,        1, 0x00bd00bd
+0,     847800,     847800,     1800,      945, 0x66cbe386, S=1,        1, 0x00bd00bd
+0,     849600,     849600,     1800,      948, 0xe77fdca7, S=1,        1, 0x00bd00bd
+0,     851400,     851400,     1800,      951, 0xe532d54f, S=1,        1, 0x00bd00bd
+0,     853200,     853200,     1800,      826, 0xd0028f8f, S=1,        1, 0x00bd00bd
+0,     855000,     855000,     1800,      763, 0xd2a5722c, S=1,        1, 0x00bd00bd
+0,     856800,     856800,     1800,      763, 0x798090ab, S=1,        1, 0x00bd00bd
+0,     858600,     858600,     1800,      766, 0xbb498e19, S=1,        1, 0x00bd00bd
+0,     860400,     860400,     1800,      946, 0x463fc5aa, S=1,        1, 0x00bd00bd
+0,     862200,     862200,     1800,      762, 0xea638f8b, S=1,        1, 0x00bd00bd
+0,     864000,     864000,     1800,      765, 0x0eed7bd2, S=1,        1, 0x00bd00bd
+0,     865800,     865800,     1800,      763, 0xfb1b6eae, S=1,        1, 0x00bd00bd
+0,     867600,     867600,     1800,      761, 0xa48a7407, S=1,        1, 0x00bd00bd
+0,     869400,     869400,     1800,      760, 0xcd737c43, S=1,        1, 0x00bd00bd
+0,     871200,     871200,     1800,      757, 0xeffd7c1a, S=1,        1, 0x00bd00bd
+0,     873000,     873000,     1800,      757, 0x2f6272cb, S=1,        1, 0x00bd00bd
+0,     874800,     874800,     1800,      762, 0xe2a28223, S=1,        1, 0x00bd00bd
+0,     876600,     876600,     1800,      760, 0xecb47548, S=1,        1, 0x00bd00bd
+0,     878400,     878400,     1800,      763, 0x80ac8293, S=1,        1, 0x00bd00bd
+0,     880200,     880200,     1800,      764, 0x5a067114, S=1,        1, 0x00bd00bd
+0,     882000,     882000,     1800,      946, 0x7af2c695, S=1,        1, 0x00bd00bd
+0,     883800,     883800,     1800,      946, 0xaadeddb9, S=1,        1, 0x00bd00bd
+0,     885600,     885600,     1800,      949, 0x75bdd657, S=1,        1, 0x00bd00bd
+0,     887400,     887400,     1800,      946, 0x3fcdd17a, S=1,        1, 0x00bd00bd
+0,     889200,     889200,     1800,      940, 0x8441e164, S=1,        1, 0x00bd00bd
+0,     891000,     891000,     1800,      762, 0x062782a9, S=1,        1, 0x00bd00bd
+0,     892800,     892800,     1800,      759, 0xfda97d5b, S=1,        1, 0x00bd00bd
+0,     894600,     894600,     1800,      942, 0x030eda68, S=1,        1, 0x00bd00bd
+0,     896400,     896400,     1800,      764, 0x1be87f32, S=1,        1, 0x00bd00bd
+0,     898200,     898200,     1800,      759, 0x9dd577e7, S=1,        1, 0x00bd00bd
+0,     900000,     900000,     1800,      760, 0x321f7312, S=1,        1, 0x00bd00bd
+0,     901800,     901800,     1800,      757, 0xd81b7513, S=1,        1, 0x00bd00bd
+0,     903600,     903600,     1800,      941, 0x088cd7e7, S=1,        1, 0x00bd00bd
+0,     905400,     905400,     1800,      943, 0xc7efddbe, S=1,        1, 0x00bd00bd
+0,     907200,     907200,     1800,      759, 0x31ed7bd4, S=1,        1, 0x00bd00bd
+0,     909000,     909000,     1800,      759, 0xddd47489, S=1,        1, 0x00bd00bd
+0,     910800,     910800,     1800,      762, 0xb76a7c1f, S=1,        1, 0x00bd00bd
+0,     912600,     912600,     1800,      831, 0x88389ce4, S=1,        1, 0x00bd00bd
+0,     914400,     914400,     1800,      756, 0x961878d2, S=1,        1, 0x00bd00bd
+0,     916200,     916200,     1800,      760, 0xb4e583bc, S=1,        1, 0x00bd00bd
+0,     918000,     918000,     1800,      761, 0x2f597c42, S=1,        1, 0x00bd00bd
+0,     919800,     919800,     1800,      759, 0x43e972f1, S=1,        1, 0x00bd00bd
diff --git a/tests/ref/fate/tscc-15bit b/tests/ref/fate/tscc-15bit
index a2871ef..e854320 100644
--- a/tests/ref/fate/tscc-15bit
+++ b/tests/ref/fate/tscc-15bit
@@ -1,5 +1,13 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 548x400
+#sar 0: 0/1
 #tb 1: 1/11025
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 11025
+#channel_layout 1: 4
 0,          0,          0,        1,   657600, 0x50b3a0c2
 1,          0,          0,    11025,    22050, 0x1740aaec
 0,          1,          1,        1,   657600, 0x50b3a0c2
diff --git a/tests/ref/fate/tscc-32bit b/tests/ref/fate/tscc-32bit
index 4eef490..dfb37a9 100644
--- a/tests/ref/fate/tscc-32bit
+++ b/tests/ref/fate/tscc-32bit
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x768
+#sar 0: 0/1
 0,          0,          0,        1,  2359296, 0x76cccaa7
 0,          1,          1,        1,  2359296, 0x09c52bbf
 0,          2,          2,        1,  2359296, 0xc8746009
diff --git a/tests/ref/fate/tscc2-avi b/tests/ref/fate/tscc2-avi
index ad71b82..6f0e8a5 100644
--- a/tests/ref/fate/tscc2-avi
+++ b/tests/ref/fate/tscc2-avi
@@ -1,4 +1,8 @@
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0x7a2103c0
 0,          1,          1,        1,   230400, 0xd381c279
 0,          2,          2,        1,   230400, 0xd381c279
diff --git a/tests/ref/fate/tscc2-mov b/tests/ref/fate/tscc2-mov
index d73ff3f..8714a87 100644
--- a/tests/ref/fate/tscc2-mov
+++ b/tests/ref/fate/tscc2-mov
@@ -1,4 +1,8 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 892x441
+#sar 0: 0/1
 0,          0,          0,        1,  1180116, 0x01d01336
 0,          1,          1,        1,  1180116, 0x01d01336
 0,          2,          2,        1,  1180116, 0x01d01336
diff --git a/tests/ref/fate/txd-16bpp b/tests/ref/fate/txd-16bpp
index 33943f9..a3b1e23 100644
--- a/tests/ref/fate/txd-16bpp
+++ b/tests/ref/fate/txd-16bpp
@@ -1,4 +1,8 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 0/1
 0,          0,          0,        1,    16384, 0x4d39b4cb
 0,          1,          1,        1,    16384, 0x2a8d14b4
 0,          2,          2,        1,    16384, 0xe26793cb
diff --git a/tests/ref/fate/txd-odd b/tests/ref/fate/txd-odd
index fe7c615..6ea5811 100644
--- a/tests/ref/fate/txd-odd
+++ b/tests/ref/fate/txd-odd
@@ -1,2 +1,6 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 387x249
+#sar 0: 0/1
 0,          0,          0,        1,   385452, 0x055a14d6
diff --git a/tests/ref/fate/txd-pal8 b/tests/ref/fate/txd-pal8
index 61fee80..2c36668 100644
--- a/tests/ref/fate/txd-pal8
+++ b/tests/ref/fate/txd-pal8
@@ -1,2 +1,6 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x512
+#sar 0: 0/1
 0,          0,          0,        1,   786432, 0x56654d61
diff --git a/tests/ref/fate/ulti b/tests/ref/fate/ulti
index 4e9968b..4b3a762 100644
--- a/tests/ref/fate/ulti
+++ b/tests/ref/fate/ulti
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,    86400, 0x5d58253d
 0,          1,          1,        1,    86400, 0x0626d90d
 0,          2,          2,        1,    86400, 0x4ecb5048
diff --git a/tests/ref/fate/utvideo_rgb_left b/tests/ref/fate/utvideo_rgb_left
index d19a6b1..d2ccbce 100644
--- a/tests/ref/fate/utvideo_rgb_left
+++ b/tests/ref/fate/utvideo_rgb_left
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0x27e6001e
 0,          1,          1,        1,   921600, 0x7c0a92bc
 0,          2,          2,        1,   921600, 0x4d2be42c
diff --git a/tests/ref/fate/utvideo_rgb_median b/tests/ref/fate/utvideo_rgb_median
index f041285..913b697 100644
--- a/tests/ref/fate/utvideo_rgb_median
+++ b/tests/ref/fate/utvideo_rgb_median
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   921600, 0x9776611f
 0,          1,          1,        1,   921600, 0xdbfa64f4
 0,          2,          2,        1,   921600, 0xed2a0580
diff --git a/tests/ref/fate/utvideo_rgba_left b/tests/ref/fate/utvideo_rgba_left
index a7e0ed4..cb7876f 100644
--- a/tests/ref/fate/utvideo_rgba_left
+++ b/tests/ref/fate/utvideo_rgba_left
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,  1228800, 0xf1bc9432
 0,          1,          1,        1,  1228800, 0x8480d1e5
 0,          2,          2,        1,  1228800, 0xb01d5fb2
diff --git a/tests/ref/fate/utvideo_rgba_median b/tests/ref/fate/utvideo_rgba_median
index a7e0ed4..cb7876f 100644
--- a/tests/ref/fate/utvideo_rgba_median
+++ b/tests/ref/fate/utvideo_rgba_median
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,  1228800, 0xf1bc9432
 0,          1,          1,        1,  1228800, 0x8480d1e5
 0,          2,          2,        1,  1228800, 0xb01d5fb2
diff --git a/tests/ref/fate/utvideo_rgba_single_symbol b/tests/ref/fate/utvideo_rgba_single_symbol
index c0e0d98..553c835 100644
--- a/tests/ref/fate/utvideo_rgba_single_symbol
+++ b/tests/ref/fate/utvideo_rgba_single_symbol
@@ -1,2 +1,6 @@
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x768
+#sar 0: 0/1
 0,          0,          0,        1,  3145728, 0xac95c593
diff --git a/tests/ref/fate/utvideo_yuv420_left b/tests/ref/fate/utvideo_yuv420_left
index 026f8fb..3d12d7e 100644
--- a/tests/ref/fate/utvideo_yuv420_left
+++ b/tests/ref/fate/utvideo_yuv420_left
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   460800, 0xece98fc8
 0,          1,          1,        1,   460800, 0x9baf786b
 0,          2,          2,        1,   460800, 0x8e8e0510
diff --git a/tests/ref/fate/utvideo_yuv420_median b/tests/ref/fate/utvideo_yuv420_median
index 5662d8c..ccca7f8 100644
--- a/tests/ref/fate/utvideo_yuv420_median
+++ b/tests/ref/fate/utvideo_yuv420_median
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   460800, 0x6a817987
 0,          1,          1,        1,   460800, 0x2f713ec2
 0,          2,          2,        1,   460800, 0x003b560e
diff --git a/tests/ref/fate/utvideo_yuv422_left b/tests/ref/fate/utvideo_yuv422_left
index 438b32a..4e66cfc 100644
--- a/tests/ref/fate/utvideo_yuv422_left
+++ b/tests/ref/fate/utvideo_yuv422_left
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   614400, 0x9a6b8802
 0,          1,          1,        1,   614400, 0xaa8687e2
 0,          2,          2,        1,   614400, 0x2fe5bd40
diff --git a/tests/ref/fate/utvideo_yuv422_median b/tests/ref/fate/utvideo_yuv422_median
index 438b32a..4e66cfc 100644
--- a/tests/ref/fate/utvideo_yuv422_median
+++ b/tests/ref/fate/utvideo_yuv422_median
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x480
+#sar 0: 0/1
 0,          0,          0,        1,   614400, 0x9a6b8802
 0,          1,          1,        1,   614400, 0xaa8687e2
 0,          2,          2,        1,   614400, 0x2fe5bd40
diff --git a/tests/ref/fate/utvideoenc_rgb_left b/tests/ref/fate/utvideoenc_rgb_left
index f6adabe..a1d2000 100644
--- a/tests/ref/fate/utvideoenc_rgb_left
+++ b/tests/ref/fate/utvideoenc_rgb_left
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, c9a1741fb293b9ad21876492b5425a3b
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   182328, cd084b244939d7e0008d8e5ab3429dc1
 0,          1,          1,        1,   182336, c9c40672750f372134185901147fb776
diff --git a/tests/ref/fate/utvideoenc_rgb_median b/tests/ref/fate/utvideoenc_rgb_median
index 3d4c22b..b1558d7 100644
--- a/tests/ref/fate/utvideoenc_rgb_median
+++ b/tests/ref/fate/utvideoenc_rgb_median
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, c9a1741fb293b9ad21876492b5425a3b
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   182160, abcf4f477f74b696faca2fcff1f62aa9
 0,          1,          1,        1,   182104, 7cbcf339fa40c24522067295b39d637f
diff --git a/tests/ref/fate/utvideoenc_rgb_none b/tests/ref/fate/utvideoenc_rgb_none
index 839766b..403c807 100644
--- a/tests/ref/fate/utvideoenc_rgb_none
+++ b/tests/ref/fate/utvideoenc_rgb_none
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, c9a1741fb293b9ad21876492b5425a3b
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   301024, 44de62472f485410819707c44b53f276
 0,          1,          1,        1,   301036, ff3c28c23b15834a84c57b304610924f
diff --git a/tests/ref/fate/utvideoenc_rgba_left b/tests/ref/fate/utvideoenc_rgba_left
index 83e3cb4..eb3305d 100644
--- a/tests/ref/fate/utvideoenc_rgba_left
+++ b/tests/ref/fate/utvideoenc_rgba_left
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, 9881f4423f0a3b5da25a0574d3451eef
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   195260, a8fdb226460f210542e7aca6c12b0874
 0,          1,          1,        1,   195268, 45f098764ccba85dc641b7e401461c0a
diff --git a/tests/ref/fate/utvideoenc_rgba_median b/tests/ref/fate/utvideoenc_rgba_median
index 1588b6d..0cdab8d 100644
--- a/tests/ref/fate/utvideoenc_rgba_median
+++ b/tests/ref/fate/utvideoenc_rgba_median
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, 9881f4423f0a3b5da25a0574d3451eef
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   195092, d32d5a3dc88b9aef0826b565ee5dfbc6
 0,          1,          1,        1,   195036, ea13e3522d1f3aeddd47117c91eccc55
diff --git a/tests/ref/fate/utvideoenc_rgba_none b/tests/ref/fate/utvideoenc_rgba_none
index b8e0b41..65f0728 100644
--- a/tests/ref/fate/utvideoenc_rgba_none
+++ b/tests/ref/fate/utvideoenc_rgba_none
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, 9881f4423f0a3b5da25a0574d3451eef
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   301284, 55e84c6e1f41e48f47dcefb63e3c1efd
 0,          1,          1,        1,   301296, 12dab23dfd2c2d5b48bed2292b876688
diff --git a/tests/ref/fate/utvideoenc_yuv420_left b/tests/ref/fate/utvideoenc_yuv420_left
index ae79eff..5a5f0ed 100644
--- a/tests/ref/fate/utvideoenc_yuv420_left
+++ b/tests/ref/fate/utvideoenc_yuv420_left
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, 32fe9f95e57b78773a0fe54c47055a60
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    59796, dedd9623ead257b98e079c6d0479e5a9
 0,          1,          1,        1,    60012, 73ae403590ffc5962ff86b8dcb44ca50
diff --git a/tests/ref/fate/utvideoenc_yuv420_median b/tests/ref/fate/utvideoenc_yuv420_median
index 21e15b5..c236c4c 100644
--- a/tests/ref/fate/utvideoenc_yuv420_median
+++ b/tests/ref/fate/utvideoenc_yuv420_median
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, 32fe9f95e57b78773a0fe54c47055a60
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    62876, 5e2a5276e10b86511fb8101733bc4795
 0,          1,          1,        1,    62832, fb1e0a7b2bdbcbada9892e3db7be7821
diff --git a/tests/ref/fate/utvideoenc_yuv420_none b/tests/ref/fate/utvideoenc_yuv420_none
index 7f9b58d..f1606b3 100644
--- a/tests/ref/fate/utvideoenc_yuv420_none
+++ b/tests/ref/fate/utvideoenc_yuv420_none
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, 32fe9f95e57b78773a0fe54c47055a60
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   144508, 808a5bf7f8647095ed629c18bcd78c8e
 0,          1,          1,        1,   144496, 88d91b5aebecb8e3553dc5d25c11f663
diff --git a/tests/ref/fate/utvideoenc_yuv422_left b/tests/ref/fate/utvideoenc_yuv422_left
index 9da47a4..3581974 100644
--- a/tests/ref/fate/utvideoenc_yuv422_left
+++ b/tests/ref/fate/utvideoenc_yuv422_left
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, 7d613a4daaadf19228d42c98deb26024
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    91788, 2b29ead6a04f08e49c25cd89fe0c0e46
 0,          1,          1,        1,    92140, 011a3c92a1a6659b26db7de3c74cda41
diff --git a/tests/ref/fate/utvideoenc_yuv422_median b/tests/ref/fate/utvideoenc_yuv422_median
index 8241aae..b3f4296 100644
--- a/tests/ref/fate/utvideoenc_yuv422_median
+++ b/tests/ref/fate/utvideoenc_yuv422_median
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, 7d613a4daaadf19228d42c98deb26024
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    89732, c8dbbbed6c59cff00c7cead39cadd7d4
 0,          1,          1,        1,    89652, f1c995c2bcb13f9de97fd8c5da2637a1
diff --git a/tests/ref/fate/utvideoenc_yuv422_none b/tests/ref/fate/utvideoenc_yuv422_none
index bb97e21..5e785b7 100644
--- a/tests/ref/fate/utvideoenc_yuv422_none
+++ b/tests/ref/fate/utvideoenc_yuv422_none
@@ -1,7 +1,12 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
+#extradata 0,                              16, 7d613a4daaadf19228d42c98deb26024
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: utvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   191800, 4a5653458a4206bcbc584d5e6beb61f2
 0,          1,          1,        1,   191820, 2f77ced17c186b507864ea482016c913
diff --git a/tests/ref/fate/v210 b/tests/ref/fate/v210
index 7ad9dcf..1ff76f8 100644
--- a/tests/ref/fate/v210
+++ b/tests/ref/fate/v210
@@ -1,2 +1,6 @@
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  3686400, 0x8d5c3847
diff --git a/tests/ref/fate/v410dec b/tests/ref/fate/v410dec
index 98b2816..ed78e39 100644
--- a/tests/ref/fate/v410dec
+++ b/tests/ref/fate/v410dec
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 256x256
+#sar 0: 0/1
 0,          0,          0,        1,   393216, 0xfe11a6b0
diff --git a/tests/ref/fate/vb b/tests/ref/fate/vb
index 336d426..d5fdb04 100644
--- a/tests/ref/fate/vb
+++ b/tests/ref/fate/vb
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   230400, 0x3bd1d731
 0,          1,          1,        1,   230400, 0x9d0774c3
 0,          2,          2,        1,   230400, 0xa0faafe2
diff --git a/tests/ref/fate/vble b/tests/ref/fate/vble
index 8c4250f..62d9682 100644
--- a/tests/ref/fate/vble
+++ b/tests/ref/fate/vble
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  1382400, 0x5e1bc307
 0,          1,          1,        1,  1382400, 0x198795f7
 0,          2,          2,        1,  1382400, 0xa9102ac2
diff --git a/tests/ref/fate/vc1-ism b/tests/ref/fate/vc1-ism
index 7d3b0ab..1bd6c64 100644
--- a/tests/ref/fate/vc1-ism
+++ b/tests/ref/fate/vc1-ism
@@ -1,4 +1,8 @@
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 240x104
+#sar 0: 156/156
 0,          0,          0,        1,    37440, 0xd1bc5235
 0,          2,          2,        1,    37440, 0x158e6167
 0,          3,          3,        1,    37440, 0x0faa4481
diff --git a/tests/ref/fate/vc1_ilaced_twomv b/tests/ref/fate/vc1_ilaced_twomv
index 1b4d55f..fa56b29 100644
--- a/tests/ref/fate/vc1_ilaced_twomv
+++ b/tests/ref/fate/vc1_ilaced_twomv
@@ -1,4 +1,8 @@
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 0,          0,          0,        1,  3110400, 0x764f8856
 0,          2,          2,        1,  3110400, 0x3b615b79
 0,          3,          3,        1,  3110400, 0x4fbb6f84
diff --git a/tests/ref/fate/vc1_sa00040 b/tests/ref/fate/vc1_sa00040
index 79bff27..554b838 100644
--- a/tests/ref/fate/vc1_sa00040
+++ b/tests/ref/fate/vc1_sa00040
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 1/1
 0,          0,          0,        1,    38016, 0xa6f15db5
 0,          1,          1,        1,    38016, 0xa6f15db5
 0,          2,          2,        1,    38016, 0xa6f15db5
diff --git a/tests/ref/fate/vc1_sa00050 b/tests/ref/fate/vc1_sa00050
index 89a3840..d30b1bf 100644
--- a/tests/ref/fate/vc1_sa00050
+++ b/tests/ref/fate/vc1_sa00050
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 1/1
 0,          0,          0,        1,   115200, 0xb8830eef
 0,          1,          1,        1,   115200, 0xb8830eef
 0,          2,          2,        1,   115200, 0xb8830eef
diff --git a/tests/ref/fate/vc1_sa10091 b/tests/ref/fate/vc1_sa10091
index 33326d6..ebfe271 100644
--- a/tests/ref/fate/vc1_sa10091
+++ b/tests/ref/fate/vc1_sa10091
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 1/1
 0,          0,          0,        1,   518400, 0xae20b4fa
 0,          2,          2,        1,   518400, 0x2b4ccdf9
 0,          3,          3,        1,   518400, 0x2b4ccdf9
diff --git a/tests/ref/fate/vc1_sa10143 b/tests/ref/fate/vc1_sa10143
index c0ecc3b..d690481 100644
--- a/tests/ref/fate/vc1_sa10143
+++ b/tests/ref/fate/vc1_sa10143
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x480
+#sar 0: 1/1
 0,          0,          0,        1,   518400, 0x89407f55
 0,          2,          2,        1,   518400, 0xaa896afd
 0,          3,          3,        1,   518400, 0x0e69ff59
diff --git a/tests/ref/fate/vc1_sa20021 b/tests/ref/fate/vc1_sa20021
index 22989a0..450504f 100644
--- a/tests/ref/fate/vc1_sa20021
+++ b/tests/ref/fate/vc1_sa20021
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 704x480
+#sar 0: 1/1
 0,          0,          0,        1,   506880, 0x884bc093
 0,          2,          2,        1,   506880, 0x4b09548f
 0,          3,          3,        1,   506880, 0x195cbee1
diff --git a/tests/ref/fate/vcr1 b/tests/ref/fate/vcr1
index da21df4..983c52e 100644
--- a/tests/ref/fate/vcr1
+++ b/tests/ref/fate/vcr1
@@ -1,4 +1,8 @@
 #tb 0: 66099/1000000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    28512, 0x7165286d
 0,          1,          1,        1,    28512, 0x2b842acc
 0,          2,          2,        1,    28512, 0x6d1b8e85
diff --git a/tests/ref/fate/vcr2 b/tests/ref/fate/vcr2
index f7e1540..e25aa14 100644
--- a/tests/ref/fate/vcr2
+++ b/tests/ref/fate/vcr2
@@ -1,4 +1,8 @@
 #tb 0: 1001/15000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 0,          0,          0,        1,    38016, 0x50e93e0d
 0,          1,          1,        1,    38016, 0x6ac8627d
 0,          2,          2,        1,    38016, 0x6f38661e
diff --git a/tests/ref/fate/videoxl b/tests/ref/fate/videoxl
index 4d2db37..c5b4c81 100644
--- a/tests/ref/fate/videoxl
+++ b/tests/ref/fate/videoxl
@@ -1,4 +1,8 @@
 #tb 0: 71/500
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 188x128
+#sar 0: 0/1
 0,          0,          0,        1,    36096, 0xab1c53c1
 0,          1,          1,        1,    36096, 0x8b598ff3
 0,          2,          2,        1,    36096, 0xe9a5f3eb
diff --git a/tests/ref/fate/vmnc-16bit b/tests/ref/fate/vmnc-16bit
index 064b7fa..69cf095 100644
--- a/tests/ref/fate/vmnc-16bit
+++ b/tests/ref/fate/vmnc-16bit
@@ -1,4 +1,8 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x400
+#sar 0: 0/1
 0,          0,          0,        1,   864000, 0xd6929ea7
 0,          1,          1,        1,   864000, 0x9d5283fa
 0,          2,          2,        1,   864000, 0xcec52d42
diff --git a/tests/ref/fate/vmnc-32bit b/tests/ref/fate/vmnc-32bit
index d55d88f..71117b9 100644
--- a/tests/ref/fate/vmnc-32bit
+++ b/tests/ref/fate/vmnc-32bit
@@ -1,4 +1,8 @@
 #tb 0: 1/5
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1268x961
+#sar 0: 0/1
 0,          0,          0,        1,  3655644, 0x87973530
 0,          1,          1,        1,  3655644, 0x87973530
 0,          2,          2,        1,  3655644, 0x3c3167fd
diff --git a/tests/ref/fate/vorbis-1833-chapters b/tests/ref/fate/vorbis-1833-chapters
new file mode 100644
index 0000000..46bd77a
--- /dev/null
+++ b/tests/ref/fate/vorbis-1833-chapters
@@ -0,0 +1,36 @@
+[CHAPTER]
+id=1
+time_base=1/1000
+start=0
+start_time=0.000000
+end=5000
+end_time=5.000000
+TAG:title=start
+[/CHAPTER]
+[CHAPTER]
+id=2
+time_base=1/1000
+start=5000
+start_time=5.000000
+end=10500
+end_time=10.500000
+TAG:title=Five Seconds
+[/CHAPTER]
+[CHAPTER]
+id=3
+time_base=1/1000
+start=10500
+start_time=10.500000
+end=15000
+end_time=15.000000
+TAG:title=Ten point 5 seconds
+[/CHAPTER]
+[CHAPTER]
+id=4
+time_base=1/1000
+start=15000
+start_time=15.000000
+end=19849
+end_time=19.849000
+TAG:title=15 sec - over soon
+[/CHAPTER]
diff --git a/tests/ref/fate/vp31 b/tests/ref/fate/vp31
index 48221c1..e41d372 100644
--- a/tests/ref/fate/vp31
+++ b/tests/ref/fate/vp31
@@ -1,4 +1,8 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x272
+#sar 0: 0/1
 0,          0,          0,        1,   261120, 0xc50dec2b
 0,          1,          1,        1,   261120, 0xaa8d4441
 0,          2,          2,        1,   261120, 0x932b0d44
diff --git a/tests/ref/fate/vp5 b/tests/ref/fate/vp5
index 0e601ba..2116fb9 100644
--- a/tests/ref/fate/vp5
+++ b/tests/ref/fate/vp5
@@ -1,4 +1,8 @@
 #tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 512x304
+#sar 0: 0/1
 0,          0,          0,        1,   233472, 0x27488413
 0,          1,          1,        1,   233472, 0x4af384b5
 0,          2,          2,        1,   233472, 0x948d845d
diff --git a/tests/ref/fate/vp60 b/tests/ref/fate/vp60
index c1da72b..4becf2a 100644
--- a/tests/ref/fate/vp60
+++ b/tests/ref/fate/vp60
@@ -1,4 +1,8 @@
 #tb 0: 32767/982027
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 192x192
+#sar 0: 0/1
 0,          0,          0,        1,    55296, 0x6a3202a3
 0,          1,          1,        1,    55296, 0x2af202eb
 0,          2,          2,        1,    55296, 0xa1a40388
diff --git a/tests/ref/fate/vp61 b/tests/ref/fate/vp61
index be1fe53..2d3beea 100644
--- a/tests/ref/fate/vp61
+++ b/tests/ref/fate/vp61
@@ -1,4 +1,8 @@
 #tb 0: 32767/982027
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 112x112
+#sar 0: 0/1
 0,          0,          0,        1,    18816, 0xc3fe9fc7
 0,          1,          1,        1,    18816, 0x6ddf972f
 0,          2,          2,        1,    18816, 0x72808b6e
diff --git a/tests/ref/fate/vp6a b/tests/ref/fate/vp6a
index 1f2ddd9..b4f3363 100644
--- a/tests/ref/fate/vp6a
+++ b/tests/ref/fate/vp6a
@@ -1,4 +1,8 @@
 #tb 0: 1/4
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 300x180
+#sar 0: 0/1
 0,          0,          0,        1,   135000, 0x9dceed6d
 0,          1,          1,        1,   135000, 0x47e5778d
 0,          2,          2,        1,   135000, 0x5de36599
diff --git a/tests/ref/fate/vp6a-skip_alpha b/tests/ref/fate/vp6a-skip_alpha
index 91a099c..e2c435f 100644
--- a/tests/ref/fate/vp6a-skip_alpha
+++ b/tests/ref/fate/vp6a-skip_alpha
@@ -1,4 +1,8 @@
 #tb 0: 1/4
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 300x180
+#sar 0: 0/1
 0,          0,          0,        1,    81000, 0xcb92962d
 0,          1,          1,        1,    81000, 0xae381904
 0,          2,          2,        1,    81000, 0x1fcc0c75
diff --git a/tests/ref/fate/vp6f b/tests/ref/fate/vp6f
index edb555d..65e1131 100644
--- a/tests/ref/fate/vp6f
+++ b/tests/ref/fate/vp6f
@@ -1,4 +1,8 @@
 #tb 0: 1/10
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 112x80
+#sar 0: 0/1
 0,          0,          0,        1,    13440, 0x7cb0a22f
 0,          1,          1,        1,    13440, 0xdfcea6ba
 0,          2,          2,        1,    13440, 0x59b2a5da
diff --git a/tests/ref/fate/vp7 b/tests/ref/fate/vp7
index b014010..3af21f2 100644
--- a/tests/ref/fate/vp7
+++ b/tests/ref/fate/vp7
@@ -1,4 +1,8 @@
 #tb 0: 1001/12000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x176
+#sar 0: 0/1
 0,          0,          0,        1,    84480, 0xa7776101
 0,          1,          1,        1,    84480, 0xeb1560ca
 0,          2,          2,        1,    84480, 0x7a4e6123
diff --git a/tests/ref/fate/vp8-2451 b/tests/ref/fate/vp8-2451
new file mode 100644
index 0000000..f681695
--- /dev/null
+++ b/tests/ref/fate/vp8-2451
@@ -0,0 +1,112 @@
+#tb 0: 1001/24000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x360
+#sar 0: 1/1
+0,          0,          0,        1,   345600, 0xa1e65077
+0,          1,          1,        1,   345600, 0xa1e65077
+0,          2,          2,        1,   345600, 0xa1e65077
+0,          3,          3,        1,   345600, 0xa1e65077
+0,          4,          4,        1,   345600, 0xa1e65077
+0,          5,          5,        1,   345600, 0xa1e65077
+0,          6,          6,        1,   345600, 0xa1e65077
+0,          7,          7,        1,   345600, 0xa1e65077
+0,          8,          8,        1,   345600, 0xa1e65077
+0,          9,          9,        1,   345600, 0xa1e65077
+0,         10,         10,        1,   345600, 0xa1e65077
+0,         11,         11,        1,   345600, 0xa1e65077
+0,         12,         12,        1,   345600, 0xa1e65077
+0,         13,         13,        1,   345600, 0xa1e65077
+0,         14,         14,        1,   345600, 0xa1e65077
+0,         15,         15,        1,   345600, 0xa1e65077
+0,         16,         16,        1,   345600, 0xa1e65077
+0,         17,         17,        1,   345600, 0xa1e65077
+0,         18,         18,        1,   345600, 0xa1e65077
+0,         19,         19,        1,   345600, 0xa1e65077
+0,         20,         20,        1,   345600, 0xa1e65077
+0,         21,         21,        1,   345600, 0xa1e65077
+0,         22,         22,        1,   345600, 0xa1e65077
+0,         23,         23,        1,   345600, 0xa1e65077
+0,         24,         24,        1,   345600, 0xa1e65077
+0,         25,         25,        1,   345600, 0xa1e65077
+0,         26,         26,        1,   345600, 0xa1e65077
+0,         27,         27,        1,   345600, 0xa1e65077
+0,         28,         28,        1,   345600, 0xa1e65077
+0,         29,         29,        1,   345600, 0xa1e65077
+0,         30,         30,        1,   345600, 0xa1e65077
+0,         31,         31,        1,   345600, 0xa1e65077
+0,         32,         32,        1,   345600, 0x07059a25
+0,         33,         33,        1,   345600, 0xc917003c
+0,         34,         34,        1,   345600, 0xab5b7227
+0,         35,         35,        1,   345600, 0xd393c4c4
+0,         36,         36,        1,   345600, 0x7eab2e81
+0,         37,         37,        1,   345600, 0x203a9404
+0,         38,         38,        1,   345600, 0x0d84f956
+0,         39,         39,        1,   345600, 0xfed15b41
+0,         40,         40,        1,   345600, 0x1659bdb4
+0,         41,         41,        1,   345600, 0xffd82d2c
+0,         42,         42,        1,   345600, 0xeada9083
+0,         43,         43,        1,   345600, 0xeb28f693
+0,         44,         44,        1,   345600, 0xf2a8f693
+0,         45,         45,        1,   345600, 0xf2a8f693
+0,         46,         46,        1,   345600, 0xf2a8f693
+0,         47,         47,        1,   345600, 0xf2a8f693
+0,         48,         48,        1,   345600, 0xf2a8f693
+0,         49,         49,        1,   345600, 0xf2a8f693
+0,         50,         50,        1,   345600, 0xf2a8f693
+0,         51,         51,        1,   345600, 0xf2a8f693
+0,         52,         52,        1,   345600, 0xf2a8f693
+0,         53,         53,        1,   345600, 0xf2a8f693
+0,         54,         54,        1,   345600, 0xf2a8f693
+0,         55,         55,        1,   345600, 0xf2a8f693
+0,         56,         56,        1,   345600, 0xf2a8f693
+0,         57,         57,        1,   345600, 0x19cbf6d0
+0,         58,         58,        1,   345600, 0x19cbf6d0
+0,         59,         59,        1,   345600, 0x19cbf6d0
+0,         60,         60,        1,   345600, 0x19cbf6d0
+0,         61,         61,        1,   345600, 0x19cbf6d0
+0,         62,         62,        1,   345600, 0x19cbf6d0
+0,         63,         63,        1,   345600, 0x19cbf6d0
+0,         64,         64,        1,   345600, 0x19cbf6d0
+0,         65,         65,        1,   345600, 0x19cbf6d0
+0,         66,         66,        1,   345600, 0x19cbf6d0
+0,         67,         67,        1,   345600, 0x19cbf6d0
+0,         68,         68,        1,   345600, 0x19cbf6d0
+0,         69,         69,        1,   345600, 0x19cbf6d0
+0,         70,         70,        1,   345600, 0x19cbf6d0
+0,         71,         71,        1,   345600, 0x19cbf6d0
+0,         72,         72,        1,   345600, 0x19cbf6d0
+0,         73,         73,        1,   345600, 0x19cbf6d0
+0,         74,         74,        1,   345600, 0x19cbf6d0
+0,         75,         75,        1,   345600, 0x19cbf6d0
+0,         76,         76,        1,   345600, 0x19cbf6d0
+0,         77,         77,        1,   345600, 0x19cbf6d0
+0,         78,         78,        1,   345600, 0x19cbf6d0
+0,         79,         79,        1,   345600, 0x19cbf6d0
+0,         80,         80,        1,   345600, 0x19cbf6d0
+0,         81,         81,        1,   345600, 0x19cbf6d0
+0,         82,         82,        1,   345600, 0x19cbf6d0
+0,         83,         83,        1,   345600, 0x19cbf6d0
+0,         84,         84,        1,   345600, 0x19cbf6d0
+0,         85,         85,        1,   345600, 0x19cbf6d0
+0,         86,         86,        1,   345600, 0x19cbf6d0
+0,         87,         87,        1,   345600, 0x19cbf6d0
+0,         88,         88,        1,   345600, 0x19cbf6d0
+0,         89,         89,        1,   345600, 0x19cbf6d0
+0,         90,         90,        1,   345600, 0x19cbf6d0
+0,         91,         91,        1,   345600, 0x19cbf6d0
+0,         92,         92,        1,   345600, 0x19cbf6d0
+0,         93,         93,        1,   345600, 0x19cbf6d0
+0,         94,         94,        1,   345600, 0x19cbf6d0
+0,         95,         95,        1,   345600, 0x19cbf6d0
+0,         96,         96,        1,   345600, 0x19cbf6d0
+0,         97,         97,        1,   345600, 0x19cbf6d0
+0,         98,         98,        1,   345600, 0x19cbf6d0
+0,         99,         99,        1,   345600, 0x19cbf6d0
+0,        100,        100,        1,   345600, 0x19cbf6d0
+0,        101,        101,        1,   345600, 0x19cbf6d0
+0,        102,        102,        1,   345600, 0x19cbf6d0
+0,        103,        103,        1,   345600, 0x19cbf6d0
+0,        104,        104,        1,   345600, 0x19cbf6d0
+0,        105,        105,        1,   345600, 0x19cbf6d0
+0,        106,        106,        1,   345600, 0x19cbf6d0
diff --git a/tests/ref/fate/vp8-alpha b/tests/ref/fate/vp8-alpha
index 5b10725..4922d52 100644
--- a/tests/ref/fate/vp8-alpha
+++ b/tests/ref/fate/vp8-alpha
@@ -1,4 +1,8 @@
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: vp8
+#dimensions 0: 320x213
+#sar 0: 1/1
 0,          0,          0,       33,     2108, 0x59b92a34, S=2,     1900, 0x8fb3adc5,        8, 0x00000000
 0,         32,         32,       33,      142, 0x2f2a3fed, F=0x0, S=1,      160, 0xa13346af
 0,         65,         65,       33,      157, 0x17804767, F=0x0, S=1,      209, 0x64115f15
diff --git a/tests/ref/fate/vp8-sign-bias b/tests/ref/fate/vp8-sign-bias
index b503de8..36ffc02 100644
--- a/tests/ref/fate/vp8-sign-bias
+++ b/tests/ref/fate/vp8-sign-bias
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 854x480
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   614880, 12ce23b288485be3ddbc1db28c21517f
 0,          2,          2,        1,   614880, ce352e1079535ea058c0e9ad50f7cdb8
diff --git a/tests/ref/fate/vp8-size-change b/tests/ref/fate/vp8-size-change
index f581c99..741b6d6 100644
--- a/tests/ref/fate/vp8-size-change
+++ b/tests/ref/fate/vp8-size-change
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,  3110400, 7dde8cd136ab4b04a95d9856b941697e
 0,          1,          1,        1,  3110400, aa885f78cb6374b5bfcc66a4fc57026f
diff --git a/tests/ref/fate/vp8-test-vector-001 b/tests/ref/fate/vp8-test-vector-001
index ef38aa8..4abaf68 100644
--- a/tests/ref/fate/vp8-test-vector-001
+++ b/tests/ref/fate/vp8-test-vector-001
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, 83c78b5db579710f61f9354d5c51e8c8
 0,          1,          1,        1,    38016, 8d089d226f52d6cdaffdb3fcc080b75b
diff --git a/tests/ref/fate/vp8-test-vector-002 b/tests/ref/fate/vp8-test-vector-002
index 55149b0..3154a1a 100644
--- a/tests/ref/fate/vp8-test-vector-002
+++ b/tests/ref/fate/vp8-test-vector-002
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, 872e9922f37f0e92c767d33e0a15b8e0
 0,          1,          1,        1,    38016, ea5ad6c6ee4355018fc0ba83b5172836
diff --git a/tests/ref/fate/vp8-test-vector-003 b/tests/ref/fate/vp8-test-vector-003
index ffe3896..1e03bad 100644
--- a/tests/ref/fate/vp8-test-vector-003
+++ b/tests/ref/fate/vp8-test-vector-003
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, 96e6ce168b5ef377053e86ab5484e7f9
 0,          1,          1,        1,    38016, 10fd750292d8522ab7ee577043604789
diff --git a/tests/ref/fate/vp8-test-vector-004 b/tests/ref/fate/vp8-test-vector-004
index f7f5313..6de548f 100644
--- a/tests/ref/fate/vp8-test-vector-004
+++ b/tests/ref/fate/vp8-test-vector-004
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, 83c78b5db579710f61f9354d5c51e8c8
 0,          1,          1,        1,    38016, d173eb8a8211a05672b43206609c9034
diff --git a/tests/ref/fate/vp8-test-vector-005 b/tests/ref/fate/vp8-test-vector-005
index 3368c70..e1963a0 100644
--- a/tests/ref/fate/vp8-test-vector-005
+++ b/tests/ref/fate/vp8-test-vector-005
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, e7a4be434df4bb524ba56a03cba901f4
 0,          1,          1,        1,    38016, d903ade6d49e51485627c044fbb2190c
diff --git a/tests/ref/fate/vp8-test-vector-006 b/tests/ref/fate/vp8-test-vector-006
index 28c249c..4913043 100644
--- a/tests/ref/fate/vp8-test-vector-006
+++ b/tests/ref/fate/vp8-test-vector-006
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 175x143
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    37697, 9ca5df27b0158aca2a38dff946f58c41
 0,          1,          1,        1,    37697, 627129a99538ec1ac51be910ca92ebc4
diff --git a/tests/ref/fate/vp8-test-vector-007 b/tests/ref/fate/vp8-test-vector-007
index a0cb441..851ce7b 100644
--- a/tests/ref/fate/vp8-test-vector-007
+++ b/tests/ref/fate/vp8-test-vector-007
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, 98bd0af6928c144888a9c320270e9f0e
 0,          1,          1,        1,    38016, 9ff7cff703d58481acd233451388377c
diff --git a/tests/ref/fate/vp8-test-vector-008 b/tests/ref/fate/vp8-test-vector-008
index 0503c4e..00066a6 100644
--- a/tests/ref/fate/vp8-test-vector-008
+++ b/tests/ref/fate/vp8-test-vector-008
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/23
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1432x888
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,  1907424, 7146d3a72b6cb8e43ee5280ef8d661fe
 0,          1,          1,        1,  1907424, 5a537e9710158efb5ad2683a1d3b4c72
diff --git a/tests/ref/fate/vp8-test-vector-009 b/tests/ref/fate/vp8-test-vector-009
index f41f014..02a1aa7 100644
--- a/tests/ref/fate/vp8-test-vector-009
+++ b/tests/ref/fate/vp8-test-vector-009
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, b3a3121c796a60c88988fef5240a07fe
 0,          1,          1,        1,    38016, f25147764829cf837e00b8fd6383e2c4
diff --git a/tests/ref/fate/vp8-test-vector-010 b/tests/ref/fate/vp8-test-vector-010
index 2feeb63..74a7163 100644
--- a/tests/ref/fate/vp8-test-vector-010
+++ b/tests/ref/fate/vp8-test-vector-010
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   115200, 3441ec1a9b9d325c9aeda44e3b68377d
 0,          1,          1,        1,   115200, bff86a84fd673394f45c09d19a1ee0ac
diff --git a/tests/ref/fate/vp8-test-vector-011 b/tests/ref/fate/vp8-test-vector-011
index adf7235..14b2773 100644
--- a/tests/ref/fate/vp8-test-vector-011
+++ b/tests/ref/fate/vp8-test-vector-011
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, 83c78b5db579710f61f9354d5c51e8c8
 0,          1,          1,        1,    38016, 9b755a63c7c5352660a265f6e24991e1
diff --git a/tests/ref/fate/vp8-test-vector-012 b/tests/ref/fate/vp8-test-vector-012
index 3de64b6..27f728d 100644
--- a/tests/ref/fate/vp8-test-vector-012
+++ b/tests/ref/fate/vp8-test-vector-012
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, cc3069a59b6f4319761af2b39923a6e5
 0,          1,          1,        1,    38016, c0bc935941d994c6af6a864f02a90a62
diff --git a/tests/ref/fate/vp8-test-vector-013 b/tests/ref/fate/vp8-test-vector-013
index e31e6e6..05b0f21 100644
--- a/tests/ref/fate/vp8-test-vector-013
+++ b/tests/ref/fate/vp8-test-vector-013
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, ad137b9eae93daed28fe31fd5165b4d0
 0,          1,          1,        1,    38016, 7cd527f647680c0eb305050d27fb8092
diff --git a/tests/ref/fate/vp8-test-vector-014 b/tests/ref/fate/vp8-test-vector-014
index 689e24b..72b16a0 100644
--- a/tests/ref/fate/vp8-test-vector-014
+++ b/tests/ref/fate/vp8-test-vector-014
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 175x143
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    37697, 7a0356dc950e79744d79c98e391ebee9
 0,          1,          1,        1,    37697, 96e221e75c290dd847b8e55865073366
diff --git a/tests/ref/fate/vp8-test-vector-015 b/tests/ref/fate/vp8-test-vector-015
index 766c931..5024bd6 100644
--- a/tests/ref/fate/vp8-test-vector-015
+++ b/tests/ref/fate/vp8-test-vector-015
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   115200, 6b4c7cc0c6a7218362e43cffef6618c9
 0,          1,          1,        1,   115200, e132a7b1bb4fb15b1019092aedc0e599
diff --git a/tests/ref/fate/vp8-test-vector-016 b/tests/ref/fate/vp8-test-vector-016
index 4da7ff3..4c35a35 100644
--- a/tests/ref/fate/vp8-test-vector-016
+++ b/tests/ref/fate/vp8-test-vector-016
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, 905a823da31f71f9c25ebb8dfc9ddd3c
 0,          1,          1,        1,    38016, 9a1b97859b2f774954dbf96f45a22a0a
diff --git a/tests/ref/fate/vp8-test-vector-017 b/tests/ref/fate/vp8-test-vector-017
index 0d3fbea..db0527e 100644
--- a/tests/ref/fate/vp8-test-vector-017
+++ b/tests/ref/fate/vp8-test-vector-017
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 176x144
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    38016, 905a823da31f71f9c25ebb8dfc9ddd3c
 0,          1,          1,        1,    38016, f0f411dd067bff05d5d9c64e3f52a4b1
diff --git a/tests/ref/fate/vp9-00-quantizer-00 b/tests/ref/fate/vp9-00-quantizer-00
index e2afb9c..de1f54a 100644
--- a/tests/ref/fate/vp9-00-quantizer-00
+++ b/tests/ref/fate/vp9-00-quantizer-00
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, c3fbb7abbdb5bd4ed4a7e34768c17df1
 0,          1,          1,        1,   152064, 08203c2595bdb2d58ead6f921345d699
diff --git a/tests/ref/fate/vp9-00-quantizer-01 b/tests/ref/fate/vp9-00-quantizer-01
index 4d9b081..59c4974 100644
--- a/tests/ref/fate/vp9-00-quantizer-01
+++ b/tests/ref/fate/vp9-00-quantizer-01
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, f041b870cf9236d5f22e2b08a77d5958
 0,          1,          1,        1,   152064, cbdb7526986ae15592891488c9afc84c
diff --git a/tests/ref/fate/vp9-00-quantizer-02 b/tests/ref/fate/vp9-00-quantizer-02
index 09e6299..6cc92f4 100644
--- a/tests/ref/fate/vp9-00-quantizer-02
+++ b/tests/ref/fate/vp9-00-quantizer-02
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 98048cfdb4af5059f4085c5acc94ef8f
 0,          1,          1,        1,   152064, 8160183e1eed1d0af4427be216b8b9f7
diff --git a/tests/ref/fate/vp9-00-quantizer-03 b/tests/ref/fate/vp9-00-quantizer-03
index 0c22157..a7e3043 100644
--- a/tests/ref/fate/vp9-00-quantizer-03
+++ b/tests/ref/fate/vp9-00-quantizer-03
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 15c548208f5eda243a151a42f4d64855
 0,          1,          1,        1,   152064, e96d463dc8e9b27b1c2ec40f77eee6ef
diff --git a/tests/ref/fate/vp9-00-quantizer-04 b/tests/ref/fate/vp9-00-quantizer-04
index 730a012..df742fd 100644
--- a/tests/ref/fate/vp9-00-quantizer-04
+++ b/tests/ref/fate/vp9-00-quantizer-04
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 928c64a0747ac57ab50c1520d694fea7
 0,          1,          1,        1,   152064, a6f6daa293231e95ef30ed168f582c84
diff --git a/tests/ref/fate/vp9-00-quantizer-05 b/tests/ref/fate/vp9-00-quantizer-05
index 0f2dd7a..ca544a9 100644
--- a/tests/ref/fate/vp9-00-quantizer-05
+++ b/tests/ref/fate/vp9-00-quantizer-05
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 082460718b7d7046c8fb23184b7f71ca
 0,          1,          1,        1,   152064, 4a41aad51c40a92df72333e13f47d3fe
diff --git a/tests/ref/fate/vp9-00-quantizer-06 b/tests/ref/fate/vp9-00-quantizer-06
index c6c1282..d5de188 100644
--- a/tests/ref/fate/vp9-00-quantizer-06
+++ b/tests/ref/fate/vp9-00-quantizer-06
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, cfca1bed96ff62a69b2d841fda01c6b9
 0,          1,          1,        1,   152064, 9b4d61f1b998745c108f8eb67925e03d
diff --git a/tests/ref/fate/vp9-00-quantizer-07 b/tests/ref/fate/vp9-00-quantizer-07
index cdc6ec5..619ce46 100644
--- a/tests/ref/fate/vp9-00-quantizer-07
+++ b/tests/ref/fate/vp9-00-quantizer-07
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 6f5122064bead9d9882bec2698a6ed9c
 0,          1,          1,        1,   152064, 50dae67d2f57a76eece210dee8b6df9e
diff --git a/tests/ref/fate/vp9-00-quantizer-08 b/tests/ref/fate/vp9-00-quantizer-08
index f405cef..3bccbea 100644
--- a/tests/ref/fate/vp9-00-quantizer-08
+++ b/tests/ref/fate/vp9-00-quantizer-08
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, eb3d6985fcda5d93dd62d53354e8a093
 0,          1,          1,        1,   152064, 5b1f5b7780b4cafe1f75e56a0b526643
diff --git a/tests/ref/fate/vp9-00-quantizer-09 b/tests/ref/fate/vp9-00-quantizer-09
index bc5e86a..42ae12b 100644
--- a/tests/ref/fate/vp9-00-quantizer-09
+++ b/tests/ref/fate/vp9-00-quantizer-09
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, d7ccaf28c59875fe91983def5490d2b1
 0,          1,          1,        1,   152064, bd98fe9492054826748de840b4495309
diff --git a/tests/ref/fate/vp9-00-quantizer-10 b/tests/ref/fate/vp9-00-quantizer-10
index 93e46a9..c3a7d7a 100644
--- a/tests/ref/fate/vp9-00-quantizer-10
+++ b/tests/ref/fate/vp9-00-quantizer-10
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 20dda6231f9801c9c237c6d09d9939b6
 0,          1,          1,        1,   152064, 23c91e93807fb9a4ed5bd5bdd449d99f
diff --git a/tests/ref/fate/vp9-00-quantizer-11 b/tests/ref/fate/vp9-00-quantizer-11
index 0924f54..262978b 100644
--- a/tests/ref/fate/vp9-00-quantizer-11
+++ b/tests/ref/fate/vp9-00-quantizer-11
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 960833315ebcdee97f46c4d98d0f3fef
 0,          1,          1,        1,   152064, eec40507d17b64b7895a61cb87b2096a
diff --git a/tests/ref/fate/vp9-00-quantizer-12 b/tests/ref/fate/vp9-00-quantizer-12
index 9213e9d..c3dfd3d 100644
--- a/tests/ref/fate/vp9-00-quantizer-12
+++ b/tests/ref/fate/vp9-00-quantizer-12
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 6533224d3b6ba1ec0dd973bbe56c6349
 0,          1,          1,        1,   152064, 12ceadc6d28327a24a75f8c40b6084d1
diff --git a/tests/ref/fate/vp9-00-quantizer-13 b/tests/ref/fate/vp9-00-quantizer-13
index 80d1a6c..e3a70fc 100644
--- a/tests/ref/fate/vp9-00-quantizer-13
+++ b/tests/ref/fate/vp9-00-quantizer-13
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 7268de6756014f79a56dcf010c52a97f
 0,          1,          1,        1,   152064, 9e39e9b0e2295b8460dfa05f44762771
diff --git a/tests/ref/fate/vp9-00-quantizer-14 b/tests/ref/fate/vp9-00-quantizer-14
index e7ab21d..0cb48f3 100644
--- a/tests/ref/fate/vp9-00-quantizer-14
+++ b/tests/ref/fate/vp9-00-quantizer-14
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 57e9e333c641fa952f7485b788df225a
 0,          1,          1,        1,   152064, 551f0cea83dcdf4540c3983736757874
diff --git a/tests/ref/fate/vp9-00-quantizer-15 b/tests/ref/fate/vp9-00-quantizer-15
index 842ab6e..fdab517 100644
--- a/tests/ref/fate/vp9-00-quantizer-15
+++ b/tests/ref/fate/vp9-00-quantizer-15
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 17a0a2842856b9e89aede237648d5dda
 0,          1,          1,        1,   152064, c9fcade888a38621bebe3d4b41664245
diff --git a/tests/ref/fate/vp9-00-quantizer-16 b/tests/ref/fate/vp9-00-quantizer-16
index 7478558..ef45c9c 100644
--- a/tests/ref/fate/vp9-00-quantizer-16
+++ b/tests/ref/fate/vp9-00-quantizer-16
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 6cc2089e9a3d352fe10b59ccd935c677
 0,          1,          1,        1,   152064, d165bf7b9cb901e121a65038758d8613
diff --git a/tests/ref/fate/vp9-00-quantizer-17 b/tests/ref/fate/vp9-00-quantizer-17
index 3a5b1c1..f66de6c 100644
--- a/tests/ref/fate/vp9-00-quantizer-17
+++ b/tests/ref/fate/vp9-00-quantizer-17
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, bc80511c83162c09661f155cd29f6dd8
 0,          1,          1,        1,   152064, a62f1cbdb3f86d2fb4c880cfd917def5
diff --git a/tests/ref/fate/vp9-00-quantizer-18 b/tests/ref/fate/vp9-00-quantizer-18
index baf3bc3..60f7bc9 100644
--- a/tests/ref/fate/vp9-00-quantizer-18
+++ b/tests/ref/fate/vp9-00-quantizer-18
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, b2d350f6faa41cb50c2e8a9907d0f4a5
 0,          1,          1,        1,   152064, 39b4380d16bc8e093dd4dba475175fb3
diff --git a/tests/ref/fate/vp9-00-quantizer-19 b/tests/ref/fate/vp9-00-quantizer-19
index 2ba95e1..3c25ede 100644
--- a/tests/ref/fate/vp9-00-quantizer-19
+++ b/tests/ref/fate/vp9-00-quantizer-19
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 441e09be3c15fcb240afd74bb7a10a72
 0,          1,          1,        1,   152064, 32ae5dac876ca5d5ae6ab7c74f4dc25d
diff --git a/tests/ref/fate/vp9-00-quantizer-20 b/tests/ref/fate/vp9-00-quantizer-20
index 8119688..06a973f 100644
--- a/tests/ref/fate/vp9-00-quantizer-20
+++ b/tests/ref/fate/vp9-00-quantizer-20
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 7786eb9944dba0553e129133523a98c1
 0,          1,          1,        1,   152064, 206d888f8453427f10a40aa8bf5f6df0
diff --git a/tests/ref/fate/vp9-00-quantizer-21 b/tests/ref/fate/vp9-00-quantizer-21
index 0e94992..0fc00d1 100644
--- a/tests/ref/fate/vp9-00-quantizer-21
+++ b/tests/ref/fate/vp9-00-quantizer-21
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, aab95e195be71feca050a839d7b3154d
 0,          1,          1,        1,   152064, 02a05d699bbbdc477e34bb0dad9f0391
diff --git a/tests/ref/fate/vp9-00-quantizer-22 b/tests/ref/fate/vp9-00-quantizer-22
index 90533aa..3e6305e 100644
--- a/tests/ref/fate/vp9-00-quantizer-22
+++ b/tests/ref/fate/vp9-00-quantizer-22
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 41f853c3ee2d4611b645cc643d82e287
 0,          1,          1,        1,   152064, 1c240c653110ff8609ca0f0287a6496d
diff --git a/tests/ref/fate/vp9-00-quantizer-23 b/tests/ref/fate/vp9-00-quantizer-23
index d16d198..9ce2966 100644
--- a/tests/ref/fate/vp9-00-quantizer-23
+++ b/tests/ref/fate/vp9-00-quantizer-23
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, bc5b07369df50c8f97ce1a377fe513cf
 0,          1,          1,        1,   152064, ce62ddb4f3e305d0f8587ae8bb44cc79
diff --git a/tests/ref/fate/vp9-00-quantizer-24 b/tests/ref/fate/vp9-00-quantizer-24
index eccdfd6..8e37217 100644
--- a/tests/ref/fate/vp9-00-quantizer-24
+++ b/tests/ref/fate/vp9-00-quantizer-24
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 982d54041221c977b6f0e37a9236cc76
 0,          1,          1,        1,   152064, 57631e7f13f645c834e2944ebfd6d40e
diff --git a/tests/ref/fate/vp9-00-quantizer-25 b/tests/ref/fate/vp9-00-quantizer-25
index 70a76b3..00592e8 100644
--- a/tests/ref/fate/vp9-00-quantizer-25
+++ b/tests/ref/fate/vp9-00-quantizer-25
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, b0fb55f3f2f56b3d27038e83c10123ce
 0,          1,          1,        1,   152064, 9fcac3becdcc2d30d778a55eca4c2018
diff --git a/tests/ref/fate/vp9-00-quantizer-26 b/tests/ref/fate/vp9-00-quantizer-26
index d9308dc..6b6ddc9 100644
--- a/tests/ref/fate/vp9-00-quantizer-26
+++ b/tests/ref/fate/vp9-00-quantizer-26
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 4f645e0f354da77b9e2f2a6753c361da
 0,          1,          1,        1,   152064, b7542998ec298273ca662bc9b658d10e
diff --git a/tests/ref/fate/vp9-00-quantizer-27 b/tests/ref/fate/vp9-00-quantizer-27
index d2efd69..93234ba 100644
--- a/tests/ref/fate/vp9-00-quantizer-27
+++ b/tests/ref/fate/vp9-00-quantizer-27
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 6edc96a3747cad43828397045764206e
 0,          1,          1,        1,   152064, 5fbc65d20fdca1abd69079851ce676d3
diff --git a/tests/ref/fate/vp9-00-quantizer-28 b/tests/ref/fate/vp9-00-quantizer-28
index 85919fc..a17355e 100644
--- a/tests/ref/fate/vp9-00-quantizer-28
+++ b/tests/ref/fate/vp9-00-quantizer-28
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 5db3e910e70da38bb91d01d73acc33dd
 0,          1,          1,        1,   152064, b920ee7f7e61b7fdf9f44b1f738d0292
diff --git a/tests/ref/fate/vp9-00-quantizer-29 b/tests/ref/fate/vp9-00-quantizer-29
index cc6eae7..b0f56ef 100644
--- a/tests/ref/fate/vp9-00-quantizer-29
+++ b/tests/ref/fate/vp9-00-quantizer-29
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 3cb3e310be5305077efa6216f6f10654
 0,          1,          1,        1,   152064, 692d3e098af5978fe1a898ebc1a66a7a
diff --git a/tests/ref/fate/vp9-00-quantizer-30 b/tests/ref/fate/vp9-00-quantizer-30
index 4f26b58..8491c2f 100644
--- a/tests/ref/fate/vp9-00-quantizer-30
+++ b/tests/ref/fate/vp9-00-quantizer-30
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, e3b3cea66ea38c5dfba1aa73bb4c611d
 0,          1,          1,        1,   152064, 42bb3e54b19c3f4c4f7ee3a6ba012e19
diff --git a/tests/ref/fate/vp9-00-quantizer-31 b/tests/ref/fate/vp9-00-quantizer-31
index 4c9bf96..f9b8505 100644
--- a/tests/ref/fate/vp9-00-quantizer-31
+++ b/tests/ref/fate/vp9-00-quantizer-31
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 2523e9ecfd3781eafcd7da192dc105e9
 0,          1,          1,        1,   152064, 6d5feea012b9a1f51fc643633e728764
diff --git a/tests/ref/fate/vp9-00-quantizer-32 b/tests/ref/fate/vp9-00-quantizer-32
index ef49c4e..f93286c 100644
--- a/tests/ref/fate/vp9-00-quantizer-32
+++ b/tests/ref/fate/vp9-00-quantizer-32
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 0a0305eba36500ebf6cc6cc0f01f5a3b
 0,          1,          1,        1,   152064, 2c76bcd6763467f9057a726fbcf50ab1
diff --git a/tests/ref/fate/vp9-00-quantizer-33 b/tests/ref/fate/vp9-00-quantizer-33
index 374c44e..cbbc463 100644
--- a/tests/ref/fate/vp9-00-quantizer-33
+++ b/tests/ref/fate/vp9-00-quantizer-33
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, c68433e0e94047c220be9b629334f744
 0,          1,          1,        1,   152064, fcfa4dff7a39bc9c5e315849ecbb46ea
diff --git a/tests/ref/fate/vp9-00-quantizer-34 b/tests/ref/fate/vp9-00-quantizer-34
index aa9c833..dc9bc30 100644
--- a/tests/ref/fate/vp9-00-quantizer-34
+++ b/tests/ref/fate/vp9-00-quantizer-34
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, ad9dc2f912c137b014a33e2792c88a25
 0,          1,          1,        1,   152064, 11221ee4ea5c776f43af68756682cd5a
diff --git a/tests/ref/fate/vp9-00-quantizer-35 b/tests/ref/fate/vp9-00-quantizer-35
index 820725b..23effea 100644
--- a/tests/ref/fate/vp9-00-quantizer-35
+++ b/tests/ref/fate/vp9-00-quantizer-35
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 75031f898cccf303a64ab46b1f815389
 0,          1,          1,        1,   152064, a4fc864e7fbc470dfcab6207e0eea152
diff --git a/tests/ref/fate/vp9-00-quantizer-36 b/tests/ref/fate/vp9-00-quantizer-36
index 4a39a13..f43915d 100644
--- a/tests/ref/fate/vp9-00-quantizer-36
+++ b/tests/ref/fate/vp9-00-quantizer-36
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, c7824af009fde6cafdd8d39fae6bb6cf
 0,          1,          1,        1,   152064, 516a82d5fc4dfa3daf713ed2ec36041b
diff --git a/tests/ref/fate/vp9-00-quantizer-37 b/tests/ref/fate/vp9-00-quantizer-37
index 96e526f..1e4fd74 100644
--- a/tests/ref/fate/vp9-00-quantizer-37
+++ b/tests/ref/fate/vp9-00-quantizer-37
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, a2e5c820fd9733e18f9349fb658ca281
 0,          1,          1,        1,   152064, fb23e0bc64728a492a33d985032f21b8
diff --git a/tests/ref/fate/vp9-00-quantizer-38 b/tests/ref/fate/vp9-00-quantizer-38
index 9f61d33..7ae5444 100644
--- a/tests/ref/fate/vp9-00-quantizer-38
+++ b/tests/ref/fate/vp9-00-quantizer-38
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 8347bfb891317e89ef66781d6c28e24f
 0,          1,          1,        1,   152064, a5722f824d32deac042513a1a7dcdcd0
diff --git a/tests/ref/fate/vp9-00-quantizer-39 b/tests/ref/fate/vp9-00-quantizer-39
index 396a1a3..0241494 100644
--- a/tests/ref/fate/vp9-00-quantizer-39
+++ b/tests/ref/fate/vp9-00-quantizer-39
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 018968f97fac3bdff146cf22c1da5ef0
 0,          1,          1,        1,   152064, ca8b09b01e5132183395e238f1c7901e
diff --git a/tests/ref/fate/vp9-00-quantizer-40 b/tests/ref/fate/vp9-00-quantizer-40
index dc77394..2da4ea1 100644
--- a/tests/ref/fate/vp9-00-quantizer-40
+++ b/tests/ref/fate/vp9-00-quantizer-40
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 792660f6589ad5340be4bd0554435866
 0,          1,          1,        1,   152064, 68c84c8a15d679e0a73678b93215c62c
diff --git a/tests/ref/fate/vp9-00-quantizer-41 b/tests/ref/fate/vp9-00-quantizer-41
index 667549c..bb7623e 100644
--- a/tests/ref/fate/vp9-00-quantizer-41
+++ b/tests/ref/fate/vp9-00-quantizer-41
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, a456bdfc6c1c07b4cb3a3848843743b9
 0,          1,          1,        1,   152064, fe41a12b8cb6bc5667ba2179e076f3b0
diff --git a/tests/ref/fate/vp9-00-quantizer-42 b/tests/ref/fate/vp9-00-quantizer-42
index c7fbfbc..b1f5293 100644
--- a/tests/ref/fate/vp9-00-quantizer-42
+++ b/tests/ref/fate/vp9-00-quantizer-42
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, f016dd8431694d989700fb1ba71a5b2d
 0,          1,          1,        1,   152064, e89c3c5b935157b40f2fb0ab92415828
diff --git a/tests/ref/fate/vp9-00-quantizer-43 b/tests/ref/fate/vp9-00-quantizer-43
index 090ce6f..b25e1c0 100644
--- a/tests/ref/fate/vp9-00-quantizer-43
+++ b/tests/ref/fate/vp9-00-quantizer-43
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 7b8ab82625f3006bac89d4fb5197e71c
 0,          1,          1,        1,   152064, 18bd3716045563dfba2c72b640b3274b
diff --git a/tests/ref/fate/vp9-00-quantizer-44 b/tests/ref/fate/vp9-00-quantizer-44
index 130b5fa..1d378f6 100644
--- a/tests/ref/fate/vp9-00-quantizer-44
+++ b/tests/ref/fate/vp9-00-quantizer-44
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 66fde04d8320c750e56406feefd29979
 0,          1,          1,        1,   152064, f9d01d8fc1722ec345e624e14b404215
diff --git a/tests/ref/fate/vp9-00-quantizer-45 b/tests/ref/fate/vp9-00-quantizer-45
index 5cb7105..8155faa 100644
--- a/tests/ref/fate/vp9-00-quantizer-45
+++ b/tests/ref/fate/vp9-00-quantizer-45
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, cc97597b015896d73f3e60e7ae44c4da
 0,          1,          1,        1,   152064, fea98bc508f92135641ab99762444b14
diff --git a/tests/ref/fate/vp9-00-quantizer-46 b/tests/ref/fate/vp9-00-quantizer-46
index cb51f72..166423b 100644
--- a/tests/ref/fate/vp9-00-quantizer-46
+++ b/tests/ref/fate/vp9-00-quantizer-46
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 79ed95c741178bb3c0954f1f6f8e21a3
 0,          1,          1,        1,   152064, f02a06a5e2b5b7619c9a52c5bea0564d
diff --git a/tests/ref/fate/vp9-00-quantizer-47 b/tests/ref/fate/vp9-00-quantizer-47
index 0bf90b4..5e04899 100644
--- a/tests/ref/fate/vp9-00-quantizer-47
+++ b/tests/ref/fate/vp9-00-quantizer-47
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 9b98e948b8c2a822f21bd8419e6f4410
 0,          1,          1,        1,   152064, 491382d68c16c2a3c6f1746598bc4a97
diff --git a/tests/ref/fate/vp9-00-quantizer-48 b/tests/ref/fate/vp9-00-quantizer-48
index 2604a53..444278b 100644
--- a/tests/ref/fate/vp9-00-quantizer-48
+++ b/tests/ref/fate/vp9-00-quantizer-48
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, f0f095b0edae7262f44d7ed7ef84ded4
 0,          1,          1,        1,   152064, 0e833889ccac81d60251007d1baf6500
diff --git a/tests/ref/fate/vp9-00-quantizer-49 b/tests/ref/fate/vp9-00-quantizer-49
index 3403d1d..31e59fd 100644
--- a/tests/ref/fate/vp9-00-quantizer-49
+++ b/tests/ref/fate/vp9-00-quantizer-49
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 6c1b7b7827617fb9b8417aca2cfdbcaa
 0,          1,          1,        1,   152064, 4c1fc8a89297fdcf79f0faabd42b8684
diff --git a/tests/ref/fate/vp9-00-quantizer-50 b/tests/ref/fate/vp9-00-quantizer-50
index f2cdc8e..ca40c62 100644
--- a/tests/ref/fate/vp9-00-quantizer-50
+++ b/tests/ref/fate/vp9-00-quantizer-50
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, ca6142db68463487bc28c888ab38476c
 0,          1,          1,        1,   152064, 02a71153ec70f569524c3d814cb62f86
diff --git a/tests/ref/fate/vp9-00-quantizer-51 b/tests/ref/fate/vp9-00-quantizer-51
index 87ab57e..8b65d84 100644
--- a/tests/ref/fate/vp9-00-quantizer-51
+++ b/tests/ref/fate/vp9-00-quantizer-51
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, eece2627df1ddf0872256eb92352e179
 0,          1,          1,        1,   152064, 0ee9f221246ad747250e4b5e8ba586e2
diff --git a/tests/ref/fate/vp9-00-quantizer-52 b/tests/ref/fate/vp9-00-quantizer-52
index f3a14d1..e5bea45 100644
--- a/tests/ref/fate/vp9-00-quantizer-52
+++ b/tests/ref/fate/vp9-00-quantizer-52
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 7290039d974c4e50db9d69f9864bcdbe
 0,          1,          1,        1,   152064, 264765de9d02503038a4da54133b9f85
diff --git a/tests/ref/fate/vp9-00-quantizer-53 b/tests/ref/fate/vp9-00-quantizer-53
index 784925d..663bc5c 100644
--- a/tests/ref/fate/vp9-00-quantizer-53
+++ b/tests/ref/fate/vp9-00-quantizer-53
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 917af24da66f143a56a01eb2c2254285
 0,          1,          1,        1,   152064, 45a05d3bc644420519619e4115662a70
diff --git a/tests/ref/fate/vp9-00-quantizer-54 b/tests/ref/fate/vp9-00-quantizer-54
index daa6f5d..8d41782 100644
--- a/tests/ref/fate/vp9-00-quantizer-54
+++ b/tests/ref/fate/vp9-00-quantizer-54
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 6fea2820bb10a9dec9add4d2452b01f5
 0,          1,          1,        1,   152064, 74675169a4bfc2ff5463c4db5d85a79f
diff --git a/tests/ref/fate/vp9-00-quantizer-55 b/tests/ref/fate/vp9-00-quantizer-55
index 0a48cf9..676491a 100644
--- a/tests/ref/fate/vp9-00-quantizer-55
+++ b/tests/ref/fate/vp9-00-quantizer-55
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 11e5d196f6537fb7d85988d90195e556
 0,          1,          1,        1,   152064, 8536106795f7c93c5a43a11493527469
diff --git a/tests/ref/fate/vp9-00-quantizer-56 b/tests/ref/fate/vp9-00-quantizer-56
index f1f6069..44debaa 100644
--- a/tests/ref/fate/vp9-00-quantizer-56
+++ b/tests/ref/fate/vp9-00-quantizer-56
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 40839b7a3a40ec10f96b8a75224f646d
 0,          1,          1,        1,   152064, 11408dd73e8c45ddaab99f5c9650102b
diff --git a/tests/ref/fate/vp9-00-quantizer-57 b/tests/ref/fate/vp9-00-quantizer-57
index 499b57e..d506a0e 100644
--- a/tests/ref/fate/vp9-00-quantizer-57
+++ b/tests/ref/fate/vp9-00-quantizer-57
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, d0e9fa03dd48da4592ebaadb4e3794e0
 0,          1,          1,        1,   152064, 5172e29b1e04cd543833d6a68aab297c
diff --git a/tests/ref/fate/vp9-00-quantizer-58 b/tests/ref/fate/vp9-00-quantizer-58
index 2a10350..2c339e0 100644
--- a/tests/ref/fate/vp9-00-quantizer-58
+++ b/tests/ref/fate/vp9-00-quantizer-58
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, bef4a27d460e7697e038fe6f1c8bd597
 0,          1,          1,        1,   152064, 124674686cafc5f2ff5bc7ea412b8f3b
diff --git a/tests/ref/fate/vp9-00-quantizer-59 b/tests/ref/fate/vp9-00-quantizer-59
index 8ae9bd3..de3df90 100644
--- a/tests/ref/fate/vp9-00-quantizer-59
+++ b/tests/ref/fate/vp9-00-quantizer-59
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, ae9d99e9d16ef20073300559566844ae
 0,          1,          1,        1,   152064, da9405e5a6bfe4ed18d927ba2004008e
diff --git a/tests/ref/fate/vp9-00-quantizer-60 b/tests/ref/fate/vp9-00-quantizer-60
index a409462..5fee13a 100644
--- a/tests/ref/fate/vp9-00-quantizer-60
+++ b/tests/ref/fate/vp9-00-quantizer-60
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 9e66bb8e1b5e206ea4afe4bf2d335ac5
 0,          1,          1,        1,   152064, 092b74c905c12c1e87e90f5a79857736
diff --git a/tests/ref/fate/vp9-00-quantizer-61 b/tests/ref/fate/vp9-00-quantizer-61
index 92aa67f..877a5b1 100644
--- a/tests/ref/fate/vp9-00-quantizer-61
+++ b/tests/ref/fate/vp9-00-quantizer-61
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, d062dc6be246c8042744018765ef50a8
 0,          1,          1,        1,   152064, 45fd9cbacb6a91060a7e49a58a85869d
diff --git a/tests/ref/fate/vp9-00-quantizer-62 b/tests/ref/fate/vp9-00-quantizer-62
index d17d3d6..8ed9f1d 100644
--- a/tests/ref/fate/vp9-00-quantizer-62
+++ b/tests/ref/fate/vp9-00-quantizer-62
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 62f7e42fe653e81c5a65a25389e045b5
 0,          1,          1,        1,   152064, cb0cdd0b25689e0a43328550011d960d
diff --git a/tests/ref/fate/vp9-00-quantizer-63 b/tests/ref/fate/vp9-00-quantizer-63
index d7765be..bebe716 100644
--- a/tests/ref/fate/vp9-00-quantizer-63
+++ b/tests/ref/fate/vp9-00-quantizer-63
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 8467643dceff827e04acd82eeff1d1b0
 0,          1,          1,        1,   152064, c786f49d66f4dfd685dea9605821a19f
diff --git a/tests/ref/fate/vp9-01-sharpness-1 b/tests/ref/fate/vp9-01-sharpness-1
index 02e6e16..9017ca8 100644
--- a/tests/ref/fate/vp9-01-sharpness-1
+++ b/tests/ref/fate/vp9-01-sharpness-1
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, a2e5c820fd9733e18f9349fb658ca281
 0,          1,          1,        1,   152064, aa20a75be3a316193496706c9f760d08
diff --git a/tests/ref/fate/vp9-01-sharpness-2 b/tests/ref/fate/vp9-01-sharpness-2
index 51238c1..ea2464a 100644
--- a/tests/ref/fate/vp9-01-sharpness-2
+++ b/tests/ref/fate/vp9-01-sharpness-2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, a2e5c820fd9733e18f9349fb658ca281
 0,          1,          1,        1,   152064, cd94572239817ae7c9b07de739c3272b
diff --git a/tests/ref/fate/vp9-01-sharpness-3 b/tests/ref/fate/vp9-01-sharpness-3
index e1af6f6..79bff6a 100644
--- a/tests/ref/fate/vp9-01-sharpness-3
+++ b/tests/ref/fate/vp9-01-sharpness-3
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, a2e5c820fd9733e18f9349fb658ca281
 0,          1,          1,        1,   152064, 0d487a146393a0b8b84b4be1b371b507
diff --git a/tests/ref/fate/vp9-01-sharpness-4 b/tests/ref/fate/vp9-01-sharpness-4
index 977095f..d5393c3 100644
--- a/tests/ref/fate/vp9-01-sharpness-4
+++ b/tests/ref/fate/vp9-01-sharpness-4
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, a2e5c820fd9733e18f9349fb658ca281
 0,          1,          1,        1,   152064, 8bad76c55b5149169d64ce6512521de6
diff --git a/tests/ref/fate/vp9-01-sharpness-5 b/tests/ref/fate/vp9-01-sharpness-5
index c0cf715..93dfb0e 100644
--- a/tests/ref/fate/vp9-01-sharpness-5
+++ b/tests/ref/fate/vp9-01-sharpness-5
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, a2e5c820fd9733e18f9349fb658ca281
 0,          1,          1,        1,   152064, f1ce0a5d57a46c9ff1331804b7b03fdb
diff --git a/tests/ref/fate/vp9-01-sharpness-6 b/tests/ref/fate/vp9-01-sharpness-6
index 2e52d32..80c120c 100644
--- a/tests/ref/fate/vp9-01-sharpness-6
+++ b/tests/ref/fate/vp9-01-sharpness-6
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, a2e5c820fd9733e18f9349fb658ca281
 0,          1,          1,        1,   152064, 45d9ca07ed04210b1ebc743169bc8ec4
diff --git a/tests/ref/fate/vp9-01-sharpness-7 b/tests/ref/fate/vp9-01-sharpness-7
index b2b5fda..dc1ab3f 100644
--- a/tests/ref/fate/vp9-01-sharpness-7
+++ b/tests/ref/fate/vp9-01-sharpness-7
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, a2e5c820fd9733e18f9349fb658ca281
 0,          1,          1,        1,   152064, f719d0be18d16a448b4e7da3e2d9bf28
diff --git a/tests/ref/fate/vp9-02-size-08x08 b/tests/ref/fate/vp9-02-size-08x08
index 403a131..99cf18a 100644
--- a/tests/ref/fate/vp9-02-size-08x08
+++ b/tests/ref/fate/vp9-02-size-08x08
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x8
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,       96, 52def242c36123e5a8f5f53d6a971399
 0,          1,          1,        1,       96, 79c93360fbd47179400414bbfee0901c
diff --git a/tests/ref/fate/vp9-02-size-08x10 b/tests/ref/fate/vp9-02-size-08x10
index 01d8818..a4001de 100644
--- a/tests/ref/fate/vp9-02-size-08x10
+++ b/tests/ref/fate/vp9-02-size-08x10
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x10
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      120, ea3e0f807304b0eb2d3e329b0124f75c
 0,          1,          1,        1,      120, 8d13cf682d63e7eb13094f55d67fc458
diff --git a/tests/ref/fate/vp9-02-size-08x16 b/tests/ref/fate/vp9-02-size-08x16
index d72aafc..f143cd8 100644
--- a/tests/ref/fate/vp9-02-size-08x16
+++ b/tests/ref/fate/vp9-02-size-08x16
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x16
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      192, 0553e56a9d89aea496421885aab491f5
 0,          1,          1,        1,      192, b2a14cf676f7ebf3c50450050f76ad16
diff --git a/tests/ref/fate/vp9-02-size-08x18 b/tests/ref/fate/vp9-02-size-08x18
index 8615d7b..308d229 100644
--- a/tests/ref/fate/vp9-02-size-08x18
+++ b/tests/ref/fate/vp9-02-size-08x18
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x18
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      216, 4c41f93b1b280b37bc77d7047435eaa4
 0,          1,          1,        1,      216, c9c80fdba2ebc2b8c3490ae35e34f84f
diff --git a/tests/ref/fate/vp9-02-size-08x32 b/tests/ref/fate/vp9-02-size-08x32
index 55ab620..9ec35a4 100644
--- a/tests/ref/fate/vp9-02-size-08x32
+++ b/tests/ref/fate/vp9-02-size-08x32
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x32
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      384, f92a7777fd69aa2f2914d9a41c4828ba
 0,          1,          1,        1,      384, 62e1cc73487d2249a88a60e35a22d9c7
diff --git a/tests/ref/fate/vp9-02-size-08x34 b/tests/ref/fate/vp9-02-size-08x34
index bdcedbf..7e4bc5b 100644
--- a/tests/ref/fate/vp9-02-size-08x34
+++ b/tests/ref/fate/vp9-02-size-08x34
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x34
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      408, f3f2cd8f157466ff23dace85d77367ce
 0,          1,          1,        1,      408, 639d9b70a14062e95559c12d2b597f91
diff --git a/tests/ref/fate/vp9-02-size-08x64 b/tests/ref/fate/vp9-02-size-08x64
index 3226dfa..24dafb8 100644
--- a/tests/ref/fate/vp9-02-size-08x64
+++ b/tests/ref/fate/vp9-02-size-08x64
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x64
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      768, 764bd02b781a38c621a109c12f3d9393
 0,          1,          1,        1,      768, 79496bd2b9212026af816b3b7a0587d5
diff --git a/tests/ref/fate/vp9-02-size-08x66 b/tests/ref/fate/vp9-02-size-08x66
index 7aaa369..f52eb69 100644
--- a/tests/ref/fate/vp9-02-size-08x66
+++ b/tests/ref/fate/vp9-02-size-08x66
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 8x66
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      792, df20e8df89449fe50bb610e95a449a95
 0,          1,          1,        1,      792, 18f1a66d463274d1b0489f3a50e86857
diff --git a/tests/ref/fate/vp9-02-size-10x08 b/tests/ref/fate/vp9-02-size-10x08
index 5708cd3..b23509a 100644
--- a/tests/ref/fate/vp9-02-size-10x08
+++ b/tests/ref/fate/vp9-02-size-10x08
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 10x8
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      120, e1e66a88615da98523ef887f1463fc42
 0,          1,          1,        1,      120, 549842fa98c8faf572882d38b0aae390
diff --git a/tests/ref/fate/vp9-02-size-10x10 b/tests/ref/fate/vp9-02-size-10x10
index a60e36b..7a4831e 100644
--- a/tests/ref/fate/vp9-02-size-10x10
+++ b/tests/ref/fate/vp9-02-size-10x10
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 10x10
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      150, 083d638f2e147295d817bb14fff5e4f4
 0,          1,          1,        1,      150, 6dbdc445b6fd6bb99f2025cc2a40977e
diff --git a/tests/ref/fate/vp9-02-size-10x16 b/tests/ref/fate/vp9-02-size-10x16
index 659d491..ca0bcf2 100644
--- a/tests/ref/fate/vp9-02-size-10x16
+++ b/tests/ref/fate/vp9-02-size-10x16
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 10x16
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      240, fab07d6209d2413e0a434e1aaaa12154
 0,          1,          1,        1,      240, f9ffffdb96f98527ba2e553d1265edbb
diff --git a/tests/ref/fate/vp9-02-size-10x18 b/tests/ref/fate/vp9-02-size-10x18
index d4069c9..7f92d28 100644
--- a/tests/ref/fate/vp9-02-size-10x18
+++ b/tests/ref/fate/vp9-02-size-10x18
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 10x18
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      270, 0e9182e214aae732d94d007e5fe44888
 0,          1,          1,        1,      270, 2630e2674b5611d68218fddac08815e2
diff --git a/tests/ref/fate/vp9-02-size-10x32 b/tests/ref/fate/vp9-02-size-10x32
index f5ec31c..c84d822 100644
--- a/tests/ref/fate/vp9-02-size-10x32
+++ b/tests/ref/fate/vp9-02-size-10x32
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 10x32
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      480, 622e6407a051ea08706394d03330ffbf
 0,          1,          1,        1,      480, 1841a0daf7c3ef7be94e01fdb1d3968a
diff --git a/tests/ref/fate/vp9-02-size-10x34 b/tests/ref/fate/vp9-02-size-10x34
index 950b04e..a38aa2a 100644
--- a/tests/ref/fate/vp9-02-size-10x34
+++ b/tests/ref/fate/vp9-02-size-10x34
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 10x34
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      510, bfeeaf51f972fd0dfe9ee757083cbb54
 0,          1,          1,        1,      510, 10cd4ed6d762004846412d9cd0caa407
diff --git a/tests/ref/fate/vp9-02-size-10x64 b/tests/ref/fate/vp9-02-size-10x64
index 04a5e7e..77a05d5 100644
--- a/tests/ref/fate/vp9-02-size-10x64
+++ b/tests/ref/fate/vp9-02-size-10x64
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 10x64
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      960, 835254d0eecb17bed1f2b0f3a1638165
 0,          1,          1,        1,      960, c0c95ce9890eab339a0e0f8b26cb095c
diff --git a/tests/ref/fate/vp9-02-size-10x66 b/tests/ref/fate/vp9-02-size-10x66
index f26965a..72b25d8 100644
--- a/tests/ref/fate/vp9-02-size-10x66
+++ b/tests/ref/fate/vp9-02-size-10x66
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 10x66
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      990, 1bd8b2d3bf679c4b925780bf82e12fae
 0,          1,          1,        1,      990, a0254b4cd4928fe1080cd6f8828288a9
diff --git a/tests/ref/fate/vp9-02-size-16x08 b/tests/ref/fate/vp9-02-size-16x08
index 84e9b17..bdf3207 100644
--- a/tests/ref/fate/vp9-02-size-16x08
+++ b/tests/ref/fate/vp9-02-size-16x08
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x8
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      192, 68dccd167f9aa18df0840ebb8715eb68
 0,          1,          1,        1,      192, 65c90bb99fdbee7abf21031d34cb18dc
diff --git a/tests/ref/fate/vp9-02-size-16x10 b/tests/ref/fate/vp9-02-size-16x10
index 8490e4e..f1424a7 100644
--- a/tests/ref/fate/vp9-02-size-16x10
+++ b/tests/ref/fate/vp9-02-size-16x10
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x10
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      240, fb3cad61d7d9eb511758dbf87dd8abe1
 0,          1,          1,        1,      240, 4fbc1aa5559c8db2930803893bd6ba75
diff --git a/tests/ref/fate/vp9-02-size-16x16 b/tests/ref/fate/vp9-02-size-16x16
index fb6f0c8..f81f513 100644
--- a/tests/ref/fate/vp9-02-size-16x16
+++ b/tests/ref/fate/vp9-02-size-16x16
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x16
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      384, b5c9daafa548e54a8e33e9881fda33f4
 0,          1,          1,        1,      384, 1193acd7ea4b7aac968e35ef83c64378
diff --git a/tests/ref/fate/vp9-02-size-16x18 b/tests/ref/fate/vp9-02-size-16x18
index fadce55..018afe2 100644
--- a/tests/ref/fate/vp9-02-size-16x18
+++ b/tests/ref/fate/vp9-02-size-16x18
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x18
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      432, 5156b11cd9995d0c1638c9b0d2b0786c
 0,          1,          1,        1,      432, ef78557f93fb3ea770c7d49ab60edf21
diff --git a/tests/ref/fate/vp9-02-size-16x32 b/tests/ref/fate/vp9-02-size-16x32
index 02a2676..98e5f6a 100644
--- a/tests/ref/fate/vp9-02-size-16x32
+++ b/tests/ref/fate/vp9-02-size-16x32
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x32
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      768, c73d611490a5ddec6c690589deaf5e86
 0,          1,          1,        1,      768, 5d8eaeb222aa64abda59ce7b09b2f6d9
diff --git a/tests/ref/fate/vp9-02-size-16x34 b/tests/ref/fate/vp9-02-size-16x34
index 97e527f..4fb287f 100644
--- a/tests/ref/fate/vp9-02-size-16x34
+++ b/tests/ref/fate/vp9-02-size-16x34
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x34
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      816, b8bf711d9a1ce49180ed56407c8a4b0a
 0,          1,          1,        1,      816, 0457929b06ce46aec63d66bd38586e3f
diff --git a/tests/ref/fate/vp9-02-size-16x64 b/tests/ref/fate/vp9-02-size-16x64
index 63dbf24..c5b9f45 100644
--- a/tests/ref/fate/vp9-02-size-16x64
+++ b/tests/ref/fate/vp9-02-size-16x64
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x64
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1536, 925fdc485f3baa1ed145ae391519d7fd
 0,          1,          1,        1,     1536, d37af656da2d7a727c8451773495d5ed
diff --git a/tests/ref/fate/vp9-02-size-16x66 b/tests/ref/fate/vp9-02-size-16x66
index f7d0102..b3dadde 100644
--- a/tests/ref/fate/vp9-02-size-16x66
+++ b/tests/ref/fate/vp9-02-size-16x66
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x66
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1584, c7b0d91f362dff0a581434af6e902d43
 0,          1,          1,        1,     1584, d8b016ef59c6bc193b29d1c714f342c1
diff --git a/tests/ref/fate/vp9-02-size-18x08 b/tests/ref/fate/vp9-02-size-18x08
index 08aabcc..18edef9 100644
--- a/tests/ref/fate/vp9-02-size-18x08
+++ b/tests/ref/fate/vp9-02-size-18x08
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 18x8
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      216, 3219af4ef540636b0f67a989e9966059
 0,          1,          1,        1,      216, 1a3655c2cfd2ee332bc89da5b3faf778
diff --git a/tests/ref/fate/vp9-02-size-18x10 b/tests/ref/fate/vp9-02-size-18x10
index 9323a14..5949110 100644
--- a/tests/ref/fate/vp9-02-size-18x10
+++ b/tests/ref/fate/vp9-02-size-18x10
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 18x10
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      270, bf574489e9360b6475aa012c747e7924
 0,          1,          1,        1,      270, 851100301c2937312a6fd32f5aab5a09
diff --git a/tests/ref/fate/vp9-02-size-18x16 b/tests/ref/fate/vp9-02-size-18x16
index a3a91b9..bcd2857 100644
--- a/tests/ref/fate/vp9-02-size-18x16
+++ b/tests/ref/fate/vp9-02-size-18x16
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 18x16
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      432, 9535aaa2ea26fbdc16e7fe9cba3fc9b4
 0,          1,          1,        1,      432, 7f6e7ca33c0b27ff052dc2ab6721e37d
diff --git a/tests/ref/fate/vp9-02-size-18x18 b/tests/ref/fate/vp9-02-size-18x18
index b90faf3..58e690e 100644
--- a/tests/ref/fate/vp9-02-size-18x18
+++ b/tests/ref/fate/vp9-02-size-18x18
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 18x18
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      486, 83790b0e7004d8d89b7134ee1a88d885
 0,          1,          1,        1,      486, 0baf0bf556ae56d2f4b04567e6ac7ed9
diff --git a/tests/ref/fate/vp9-02-size-18x32 b/tests/ref/fate/vp9-02-size-18x32
index b7bd74b..37cabeb 100644
--- a/tests/ref/fate/vp9-02-size-18x32
+++ b/tests/ref/fate/vp9-02-size-18x32
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 18x32
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      864, 62eabc8819ded6ddba2c3a5029497cf0
 0,          1,          1,        1,      864, b760182fddf8bc05f149e80bbcb2c281
diff --git a/tests/ref/fate/vp9-02-size-18x34 b/tests/ref/fate/vp9-02-size-18x34
index 0f46da7..60889d4 100644
--- a/tests/ref/fate/vp9-02-size-18x34
+++ b/tests/ref/fate/vp9-02-size-18x34
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 18x34
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      918, 612cc424eaae924cb25c7732c422f752
 0,          1,          1,        1,      918, 010e8c2a814862529fcf8d7771ba2d7f
diff --git a/tests/ref/fate/vp9-02-size-18x64 b/tests/ref/fate/vp9-02-size-18x64
index 172422c..1ec161f 100644
--- a/tests/ref/fate/vp9-02-size-18x64
+++ b/tests/ref/fate/vp9-02-size-18x64
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 18x64
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1728, 72c74de547d9ed1b17bc962dbd5e0bb1
 0,          1,          1,        1,     1728, 462849f9e2204738e9f08b40e682a6ae
diff --git a/tests/ref/fate/vp9-02-size-18x66 b/tests/ref/fate/vp9-02-size-18x66
index c400956..f06a4d2 100644
--- a/tests/ref/fate/vp9-02-size-18x66
+++ b/tests/ref/fate/vp9-02-size-18x66
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 18x66
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1782, c3fc4a1593b9cc2f3752106af8539386
 0,          1,          1,        1,     1782, 7f2ffe6bc1750f6749bb5ad12cbaf34b
diff --git a/tests/ref/fate/vp9-02-size-32x08 b/tests/ref/fate/vp9-02-size-32x08
index 2df5adc..9a5783f 100644
--- a/tests/ref/fate/vp9-02-size-32x08
+++ b/tests/ref/fate/vp9-02-size-32x08
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 32x8
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      384, c7b30cde5664387b0f7a80d9b01e4fe2
 0,          1,          1,        1,      384, 2228a2a4e54ab5145525e5803c314dcd
diff --git a/tests/ref/fate/vp9-02-size-32x10 b/tests/ref/fate/vp9-02-size-32x10
index f5f45fb..f5f0d1e 100644
--- a/tests/ref/fate/vp9-02-size-32x10
+++ b/tests/ref/fate/vp9-02-size-32x10
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 32x10
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      480, 7c5b5df373ebfd31d210ff910e02213b
 0,          1,          1,        1,      480, c5b0a5e3eceb792b15818324a43aa2a8
diff --git a/tests/ref/fate/vp9-02-size-32x16 b/tests/ref/fate/vp9-02-size-32x16
index 4aac211..400d9f3 100644
--- a/tests/ref/fate/vp9-02-size-32x16
+++ b/tests/ref/fate/vp9-02-size-32x16
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 32x16
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      768, 7c2818db2632e5c5beee17e7105d9209
 0,          1,          1,        1,      768, cead72bd22995e98b54a91c7b4a20975
diff --git a/tests/ref/fate/vp9-02-size-32x18 b/tests/ref/fate/vp9-02-size-32x18
index 2b30219..7d58c32 100644
--- a/tests/ref/fate/vp9-02-size-32x18
+++ b/tests/ref/fate/vp9-02-size-32x18
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 32x18
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      864, 9da5409d344e7b8380688569e54803a5
 0,          1,          1,        1,      864, 9b51e14e2e624ee2b430e9eaf1a48798
diff --git a/tests/ref/fate/vp9-02-size-32x32 b/tests/ref/fate/vp9-02-size-32x32
index e9de2ed..8493c91 100644
--- a/tests/ref/fate/vp9-02-size-32x32
+++ b/tests/ref/fate/vp9-02-size-32x32
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 32x32
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1536, 117915db1856cee26f05a609c8c8de2e
 0,          1,          1,        1,     1536, 943771a98b26b174e88ed1f4e872e504
diff --git a/tests/ref/fate/vp9-02-size-32x34 b/tests/ref/fate/vp9-02-size-32x34
index e1e00fd..fa33b07 100644
--- a/tests/ref/fate/vp9-02-size-32x34
+++ b/tests/ref/fate/vp9-02-size-32x34
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 32x34
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1632, 770582911fd0095ebbeae384e87665ac
 0,          1,          1,        1,     1632, f99d7e3131f04413cba2f9de6818976d
diff --git a/tests/ref/fate/vp9-02-size-32x64 b/tests/ref/fate/vp9-02-size-32x64
index c39c88d..f70c27a 100644
--- a/tests/ref/fate/vp9-02-size-32x64
+++ b/tests/ref/fate/vp9-02-size-32x64
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 32x64
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     3072, caa8471a8b381d53c3e8fc627946a871
 0,          1,          1,        1,     3072, 2cba86ea14c0f28e242625b08f5e9b88
diff --git a/tests/ref/fate/vp9-02-size-32x66 b/tests/ref/fate/vp9-02-size-32x66
index d036df1..f7c0615 100644
--- a/tests/ref/fate/vp9-02-size-32x66
+++ b/tests/ref/fate/vp9-02-size-32x66
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 32x66
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     3168, 920ea4b8a00d41489d122d641d6e4fe5
 0,          1,          1,        1,     3168, 8bfc8d452a79f2978b8e973b77cbf8a8
diff --git a/tests/ref/fate/vp9-02-size-34x08 b/tests/ref/fate/vp9-02-size-34x08
index 5869186..0c35493 100644
--- a/tests/ref/fate/vp9-02-size-34x08
+++ b/tests/ref/fate/vp9-02-size-34x08
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 34x8
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      408, c14f2ba5b4582c9d3a488976814691b3
 0,          1,          1,        1,      408, 4387a4dce19007b7efb810b5a4069749
diff --git a/tests/ref/fate/vp9-02-size-34x10 b/tests/ref/fate/vp9-02-size-34x10
index a2ce10e..edcfdf9 100644
--- a/tests/ref/fate/vp9-02-size-34x10
+++ b/tests/ref/fate/vp9-02-size-34x10
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 34x10
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      510, fd7212b519783cf4831ce4bff91f2312
 0,          1,          1,        1,      510, 9768722ee939d80a6716865fdebca33d
diff --git a/tests/ref/fate/vp9-02-size-34x16 b/tests/ref/fate/vp9-02-size-34x16
index 0c8dc67..5628876 100644
--- a/tests/ref/fate/vp9-02-size-34x16
+++ b/tests/ref/fate/vp9-02-size-34x16
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 34x16
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      816, e443c43101be00470c6a61c1a2995b5a
 0,          1,          1,        1,      816, 1e79b1b46ec704d360b5fb725913b0f1
diff --git a/tests/ref/fate/vp9-02-size-34x18 b/tests/ref/fate/vp9-02-size-34x18
index 8c92b2d..5a7f3c8 100644
--- a/tests/ref/fate/vp9-02-size-34x18
+++ b/tests/ref/fate/vp9-02-size-34x18
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 34x18
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      918, ab7eabb355e5163e7451945018fadebd
 0,          1,          1,        1,      918, b9a77cc0c769535808996a6de7b374ff
diff --git a/tests/ref/fate/vp9-02-size-34x32 b/tests/ref/fate/vp9-02-size-34x32
index a9f804e..956d2e3 100644
--- a/tests/ref/fate/vp9-02-size-34x32
+++ b/tests/ref/fate/vp9-02-size-34x32
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 34x32
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1632, 7e334867e27046fabf0f39365311c38c
 0,          1,          1,        1,     1632, d2a49216ecedea62f546e54c1552f163
diff --git a/tests/ref/fate/vp9-02-size-34x34 b/tests/ref/fate/vp9-02-size-34x34
index 4bed149..931d422 100644
--- a/tests/ref/fate/vp9-02-size-34x34
+++ b/tests/ref/fate/vp9-02-size-34x34
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 34x34
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1734, 1bb98ba89abf6b86f47a851f8126e1ff
 0,          1,          1,        1,     1734, b960cc795c179afe7eec360c57fddd7f
diff --git a/tests/ref/fate/vp9-02-size-34x64 b/tests/ref/fate/vp9-02-size-34x64
index ac61f27..98c88ce 100644
--- a/tests/ref/fate/vp9-02-size-34x64
+++ b/tests/ref/fate/vp9-02-size-34x64
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 34x64
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     3264, 3856635223f578e1e7f7e7250a53cb8d
 0,          1,          1,        1,     3264, ee8d7c3a0ea165420d7e733b9e59219a
diff --git a/tests/ref/fate/vp9-02-size-34x66 b/tests/ref/fate/vp9-02-size-34x66
index 2bc9eb6..af0a212 100644
--- a/tests/ref/fate/vp9-02-size-34x66
+++ b/tests/ref/fate/vp9-02-size-34x66
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 34x66
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     3366, bf4e568217906ee4b58dc4707bee8ef6
 0,          1,          1,        1,     3366, f823f8c7b6e47ba43215f3becd35208e
diff --git a/tests/ref/fate/vp9-02-size-64x08 b/tests/ref/fate/vp9-02-size-64x08
index e1e01ee..5e7046a 100644
--- a/tests/ref/fate/vp9-02-size-64x08
+++ b/tests/ref/fate/vp9-02-size-64x08
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x8
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      768, d801797c94039b0a166d46e151ec912c
 0,          1,          1,        1,      768, 161ec22caa3689b214d9ab993424584b
diff --git a/tests/ref/fate/vp9-02-size-64x10 b/tests/ref/fate/vp9-02-size-64x10
index 046e7ee..143ba2a 100644
--- a/tests/ref/fate/vp9-02-size-64x10
+++ b/tests/ref/fate/vp9-02-size-64x10
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x10
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      960, 97eb5fd0599d482662eb0a1def5c5ef2
 0,          1,          1,        1,      960, dfdc1b61b478dcca8d411021486aa2ec
diff --git a/tests/ref/fate/vp9-02-size-64x16 b/tests/ref/fate/vp9-02-size-64x16
index 16cb5dd..67479f3 100644
--- a/tests/ref/fate/vp9-02-size-64x16
+++ b/tests/ref/fate/vp9-02-size-64x16
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x16
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1536, a43068a364cc42619e62406dcf17ddfc
 0,          1,          1,        1,     1536, 94691f93299bbf5b6ba3022b02b3e069
diff --git a/tests/ref/fate/vp9-02-size-64x18 b/tests/ref/fate/vp9-02-size-64x18
index 427acca..c7acad7 100644
--- a/tests/ref/fate/vp9-02-size-64x18
+++ b/tests/ref/fate/vp9-02-size-64x18
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x18
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1728, adf7e84a351847683f6a8dd177019e29
 0,          1,          1,        1,     1728, 8227cf283a27277fbab3d7826e340337
diff --git a/tests/ref/fate/vp9-02-size-64x32 b/tests/ref/fate/vp9-02-size-64x32
index a0f033e..88e29e0 100644
--- a/tests/ref/fate/vp9-02-size-64x32
+++ b/tests/ref/fate/vp9-02-size-64x32
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x32
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     3072, 931ab6a2482c3e84bc7ef8dfbc251307
 0,          1,          1,        1,     3072, 3552a9d8470a64ed627a6dbb799b7811
diff --git a/tests/ref/fate/vp9-02-size-64x34 b/tests/ref/fate/vp9-02-size-64x34
index a852272..ea41f01 100644
--- a/tests/ref/fate/vp9-02-size-64x34
+++ b/tests/ref/fate/vp9-02-size-64x34
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x34
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     3264, 68d00958a78e6252dd75d632806e2022
 0,          1,          1,        1,     3264, f7b6266e74200a669eecd241db787ee2
diff --git a/tests/ref/fate/vp9-02-size-64x64 b/tests/ref/fate/vp9-02-size-64x64
index 418febe..c9d0c21 100644
--- a/tests/ref/fate/vp9-02-size-64x64
+++ b/tests/ref/fate/vp9-02-size-64x64
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x64
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     6144, 35f17db9076fa20368fddfa01543c746
 0,          1,          1,        1,     6144, 61cd775dfc177262da9a91d3912e6718
diff --git a/tests/ref/fate/vp9-02-size-64x66 b/tests/ref/fate/vp9-02-size-64x66
index d358bd6..4bcd572 100644
--- a/tests/ref/fate/vp9-02-size-64x66
+++ b/tests/ref/fate/vp9-02-size-64x66
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 64x66
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     6336, 88587de65acfc85ff56daac8ef5d12e6
 0,          1,          1,        1,     6336, be41f6c788b929b5b6b27c5674f40abd
diff --git a/tests/ref/fate/vp9-02-size-66x08 b/tests/ref/fate/vp9-02-size-66x08
index 426f91b..0b26c5a 100644
--- a/tests/ref/fate/vp9-02-size-66x08
+++ b/tests/ref/fate/vp9-02-size-66x08
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 66x8
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      792, 3b16847e60786706fc339abc452746ff
 0,          1,          1,        1,      792, 365a5951cb127d6df183fe5d5000f493
diff --git a/tests/ref/fate/vp9-02-size-66x10 b/tests/ref/fate/vp9-02-size-66x10
index 8e0133a..0213fce 100644
--- a/tests/ref/fate/vp9-02-size-66x10
+++ b/tests/ref/fate/vp9-02-size-66x10
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 66x10
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,      990, 7cbd8c6b2fb35c0c3063cb7a379944c9
 0,          1,          1,        1,      990, 14062e74b98bed1ca982f408bc14326c
diff --git a/tests/ref/fate/vp9-02-size-66x16 b/tests/ref/fate/vp9-02-size-66x16
index 4bdc1ba..f9ee10e 100644
--- a/tests/ref/fate/vp9-02-size-66x16
+++ b/tests/ref/fate/vp9-02-size-66x16
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 66x16
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1584, fa2f292d273c37dc2804a70d1cae1e9d
 0,          1,          1,        1,     1584, ba75d90652c021bc7ca061352e6e94ce
diff --git a/tests/ref/fate/vp9-02-size-66x18 b/tests/ref/fate/vp9-02-size-66x18
index 3b395dd..1cb9bbd 100644
--- a/tests/ref/fate/vp9-02-size-66x18
+++ b/tests/ref/fate/vp9-02-size-66x18
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 66x18
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     1782, fda5ad9bf70a51b3a41bdcabf2cce32a
 0,          1,          1,        1,     1782, 91916fb20ad542a7a3ad276e6505f9b0
diff --git a/tests/ref/fate/vp9-02-size-66x32 b/tests/ref/fate/vp9-02-size-66x32
index 14b9cb0..20bfa78 100644
--- a/tests/ref/fate/vp9-02-size-66x32
+++ b/tests/ref/fate/vp9-02-size-66x32
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 66x32
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     3168, 013cd22aea6bfeccc8ec809abd52be5c
 0,          1,          1,        1,     3168, 0980adfb0ef879b3c960797272f025ad
diff --git a/tests/ref/fate/vp9-02-size-66x34 b/tests/ref/fate/vp9-02-size-66x34
index 79bc91c..012900f 100644
--- a/tests/ref/fate/vp9-02-size-66x34
+++ b/tests/ref/fate/vp9-02-size-66x34
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 66x34
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     3366, 6821eb3fcd1d10db32eff70468dcf9c1
 0,          1,          1,        1,     3366, ed0094d347d9f250d46b4903cbc14801
diff --git a/tests/ref/fate/vp9-02-size-66x64 b/tests/ref/fate/vp9-02-size-66x64
index a89e10f..cfd77d4 100644
--- a/tests/ref/fate/vp9-02-size-66x64
+++ b/tests/ref/fate/vp9-02-size-66x64
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 66x64
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     6336, 929086fbb3e117bd53110b64c1ee915b
 0,          1,          1,        1,     6336, 9ed45f5e40dd2393434e14a0c0160c63
diff --git a/tests/ref/fate/vp9-02-size-66x66 b/tests/ref/fate/vp9-02-size-66x66
index 73aa4e7..8560383 100644
--- a/tests/ref/fate/vp9-02-size-66x66
+++ b/tests/ref/fate/vp9-02-size-66x66
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 66x66
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,     6534, 69f9028d52f95d2e7f986c57b19fc018
 0,          1,          1,        1,     6534, 068e611f62b3f6222f6b1699748c8fbf
diff --git a/tests/ref/fate/vp9-03-deltaq b/tests/ref/fate/vp9-03-deltaq
index 293abad..3d13960 100644
--- a/tests/ref/fate/vp9-03-deltaq
+++ b/tests/ref/fate/vp9-03-deltaq
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x240
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   126720, 2f90d606edc511c8c960530dd915cb98
 0,          1,          1,        1,   126720, 7fd451a057d6341b2b0d116f59e41a13
diff --git a/tests/ref/fate/vp9-03-size-196x196 b/tests/ref/fate/vp9-03-size-196x196
index 1c4156b..7ac30a5 100644
--- a/tests/ref/fate/vp9-03-size-196x196
+++ b/tests/ref/fate/vp9-03-size-196x196
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 196x196
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    57624, 14cc1c34b8106e35238d4650a9123852
 0,          1,          1,        1,    57624, 66e0bb9136ea24e30b781a4610b428a1
diff --git a/tests/ref/fate/vp9-03-size-196x198 b/tests/ref/fate/vp9-03-size-196x198
index 294c7de..fd65de0 100644
--- a/tests/ref/fate/vp9-03-size-196x198
+++ b/tests/ref/fate/vp9-03-size-196x198
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 196x198
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    58212, d2bd2dfaf2ac22b3f2499844f228d89a
 0,          1,          1,        1,    58212, e066448baeb39da04b22d4d2ebd27b0a
diff --git a/tests/ref/fate/vp9-03-size-196x200 b/tests/ref/fate/vp9-03-size-196x200
index d0882e5..de59ee1 100644
--- a/tests/ref/fate/vp9-03-size-196x200
+++ b/tests/ref/fate/vp9-03-size-196x200
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 196x200
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    58800, b2f2ac3e3833ae1b4dd075fe00210373
 0,          1,          1,        1,    58800, c0cce05e56a07111fe62553fa3a87074
diff --git a/tests/ref/fate/vp9-03-size-196x202 b/tests/ref/fate/vp9-03-size-196x202
index 20f46ea..4a40674 100644
--- a/tests/ref/fate/vp9-03-size-196x202
+++ b/tests/ref/fate/vp9-03-size-196x202
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 196x202
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    59388, 7109d2ef160828ece26337f36fcfc092
 0,          1,          1,        1,    59388, bdaa6612f81a956d9b20d55a04df8346
diff --git a/tests/ref/fate/vp9-03-size-196x208 b/tests/ref/fate/vp9-03-size-196x208
index b1ffd8f..aee4445 100644
--- a/tests/ref/fate/vp9-03-size-196x208
+++ b/tests/ref/fate/vp9-03-size-196x208
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 196x208
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    61152, efa2a2a76a0fe709a78e491346cfcf29
 0,          1,          1,        1,    61152, 97de85e21b408878853fa870104707d7
diff --git a/tests/ref/fate/vp9-03-size-196x210 b/tests/ref/fate/vp9-03-size-196x210
index 7248874..bcfde20 100644
--- a/tests/ref/fate/vp9-03-size-196x210
+++ b/tests/ref/fate/vp9-03-size-196x210
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 196x210
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    61740, fccc18714a9ed3840bd6e9c6ca4858e5
 0,          1,          1,        1,    61740, a8f6eb43cf6ed670eb180c5051de06f7
diff --git a/tests/ref/fate/vp9-03-size-196x224 b/tests/ref/fate/vp9-03-size-196x224
index fb49188..0e9d64c 100644
--- a/tests/ref/fate/vp9-03-size-196x224
+++ b/tests/ref/fate/vp9-03-size-196x224
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 196x224
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    65856, 13263674ea5aa619250dfd139bda872f
 0,          1,          1,        1,    65856, 39f5cbd8917f2b3a1df8cf2b786266de
diff --git a/tests/ref/fate/vp9-03-size-196x226 b/tests/ref/fate/vp9-03-size-196x226
index 0ef318a..05c88ec 100644
--- a/tests/ref/fate/vp9-03-size-196x226
+++ b/tests/ref/fate/vp9-03-size-196x226
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 196x226
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    66444, 5cb240f10761f59687612ed589759800
 0,          1,          1,        1,    66444, 9d8d5b57336ddfa5c9c5100a0302197d
diff --git a/tests/ref/fate/vp9-03-size-198x196 b/tests/ref/fate/vp9-03-size-198x196
index 2d02a49..75af98d 100644
--- a/tests/ref/fate/vp9-03-size-198x196
+++ b/tests/ref/fate/vp9-03-size-198x196
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 198x196
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    58212, c980866a6f17d4107ce128ee112d74cf
 0,          1,          1,        1,    58212, d4d5d2a10e73f1d09919355dc4d63d48
diff --git a/tests/ref/fate/vp9-03-size-198x198 b/tests/ref/fate/vp9-03-size-198x198
index f458f53..9323e7c 100644
--- a/tests/ref/fate/vp9-03-size-198x198
+++ b/tests/ref/fate/vp9-03-size-198x198
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 198x198
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    58806, ee0760611da9938e72f551d219671c76
 0,          1,          1,        1,    58806, c512cb8a864c25318254438c7170f373
diff --git a/tests/ref/fate/vp9-03-size-198x200 b/tests/ref/fate/vp9-03-size-198x200
index 176b9d9..b7c340f 100644
--- a/tests/ref/fate/vp9-03-size-198x200
+++ b/tests/ref/fate/vp9-03-size-198x200
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 198x200
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    59400, fb0e8171b0f91d9b2ceb5430db27a67b
 0,          1,          1,        1,    59400, 73f121e6aa0e6290cfd06ac9b033c772
diff --git a/tests/ref/fate/vp9-03-size-198x202 b/tests/ref/fate/vp9-03-size-198x202
index 371a874..65e095e 100644
--- a/tests/ref/fate/vp9-03-size-198x202
+++ b/tests/ref/fate/vp9-03-size-198x202
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 198x202
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    59994, f5e1cf4cc56742fadddf42189a3f65e3
 0,          1,          1,        1,    59994, f3e8ca2c8deb29a6b5bfe415b39c901e
diff --git a/tests/ref/fate/vp9-03-size-198x208 b/tests/ref/fate/vp9-03-size-198x208
index 95b2e06..9b0a76e 100644
--- a/tests/ref/fate/vp9-03-size-198x208
+++ b/tests/ref/fate/vp9-03-size-198x208
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 198x208
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    61776, d45b561f81cbfcca8a1dddbc2bf8ca31
 0,          1,          1,        1,    61776, 3664f63b2e59e380622caadb7a05545e
diff --git a/tests/ref/fate/vp9-03-size-198x210 b/tests/ref/fate/vp9-03-size-198x210
index 1e2790a..7c8878a 100644
--- a/tests/ref/fate/vp9-03-size-198x210
+++ b/tests/ref/fate/vp9-03-size-198x210
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 198x210
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    62370, 8525a27170982c059d5904c1af3b43fb
 0,          1,          1,        1,    62370, c4eb329733913360384d3917a58f6f36
diff --git a/tests/ref/fate/vp9-03-size-198x224 b/tests/ref/fate/vp9-03-size-198x224
index 7cccf9b..09d20b7 100644
--- a/tests/ref/fate/vp9-03-size-198x224
+++ b/tests/ref/fate/vp9-03-size-198x224
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 198x224
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    66528, 5f69230bfd8bb485bd85552b18339fc0
 0,          1,          1,        1,    66528, f5c365774fc1d0bffd5025ce2e931aaf
diff --git a/tests/ref/fate/vp9-03-size-198x226 b/tests/ref/fate/vp9-03-size-198x226
index 81136e6..9fcbcd4 100644
--- a/tests/ref/fate/vp9-03-size-198x226
+++ b/tests/ref/fate/vp9-03-size-198x226
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 198x226
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    67122, 412c33a8fd71c99e68e6701b050b107c
 0,          1,          1,        1,    67122, 8e69483ff8a094096dd550b30be20dde
diff --git a/tests/ref/fate/vp9-03-size-200x196 b/tests/ref/fate/vp9-03-size-200x196
index 670d115..3326b23 100644
--- a/tests/ref/fate/vp9-03-size-200x196
+++ b/tests/ref/fate/vp9-03-size-200x196
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x196
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    58800, 651a0627c6cdaee8b46e1f8c4121a368
 0,          1,          1,        1,    58800, 3e63075148df16f69c933cf6c63e078c
diff --git a/tests/ref/fate/vp9-03-size-200x198 b/tests/ref/fate/vp9-03-size-200x198
index fd37506..66ccd0b 100644
--- a/tests/ref/fate/vp9-03-size-200x198
+++ b/tests/ref/fate/vp9-03-size-200x198
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x198
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    59400, d4b3578d800c747bcabaa484a140ffb0
 0,          1,          1,        1,    59400, a40f6f8c384c5dc3d5546d960bb6d9e5
diff --git a/tests/ref/fate/vp9-03-size-200x200 b/tests/ref/fate/vp9-03-size-200x200
index d5806a1..226e31a 100644
--- a/tests/ref/fate/vp9-03-size-200x200
+++ b/tests/ref/fate/vp9-03-size-200x200
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x200
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    60000, b339f4e563afadb25f43b8c05b12dc03
 0,          1,          1,        1,    60000, 3bd5280e7fb42400085b0b1dbba1905e
diff --git a/tests/ref/fate/vp9-03-size-200x202 b/tests/ref/fate/vp9-03-size-200x202
index 3f6ee8b..be0ff5f 100644
--- a/tests/ref/fate/vp9-03-size-200x202
+++ b/tests/ref/fate/vp9-03-size-200x202
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x202
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    60600, c4a13df44e66f06961dd72fc990439e9
 0,          1,          1,        1,    60600, 81c73b8d3806ad96af8f422914a253f8
diff --git a/tests/ref/fate/vp9-03-size-200x208 b/tests/ref/fate/vp9-03-size-200x208
index ea1cb0c..3622609 100644
--- a/tests/ref/fate/vp9-03-size-200x208
+++ b/tests/ref/fate/vp9-03-size-200x208
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x208
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    62400, 702748bec18c500dd41d93ae74b11d56
 0,          1,          1,        1,    62400, 4fb542190dab2fd673724d47451ff6ee
diff --git a/tests/ref/fate/vp9-03-size-200x210 b/tests/ref/fate/vp9-03-size-200x210
index 7c459d2..c0d172e 100644
--- a/tests/ref/fate/vp9-03-size-200x210
+++ b/tests/ref/fate/vp9-03-size-200x210
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x210
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    63000, 31ef44bd12ae702f306c55eba10d2ba7
 0,          1,          1,        1,    63000, 83e9d913f5aa058d79a81047ca45e4a2
diff --git a/tests/ref/fate/vp9-03-size-200x224 b/tests/ref/fate/vp9-03-size-200x224
index 19a786c..760c598 100644
--- a/tests/ref/fate/vp9-03-size-200x224
+++ b/tests/ref/fate/vp9-03-size-200x224
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x224
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    67200, 315d69847bf752a84231a368278eb0b6
 0,          1,          1,        1,    67200, d245738f8627fc345ab38a547bc7d352
diff --git a/tests/ref/fate/vp9-03-size-200x226 b/tests/ref/fate/vp9-03-size-200x226
index dd7967d..d4bf47b 100644
--- a/tests/ref/fate/vp9-03-size-200x226
+++ b/tests/ref/fate/vp9-03-size-200x226
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x226
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    67800, e45b6b9dce4a8509b7d26bc3cfdf7c86
 0,          1,          1,        1,    67800, ddb9d5033ecfa2d6e9a5505dce374bda
diff --git a/tests/ref/fate/vp9-03-size-202x196 b/tests/ref/fate/vp9-03-size-202x196
index 1af7c58..f40fda9 100644
--- a/tests/ref/fate/vp9-03-size-202x196
+++ b/tests/ref/fate/vp9-03-size-202x196
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 202x196
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    59388, 1261466179df96099e598e46c50fa7c1
 0,          1,          1,        1,    59388, cc0fe373cd0399cf0c95edf92d9ab01f
diff --git a/tests/ref/fate/vp9-03-size-202x198 b/tests/ref/fate/vp9-03-size-202x198
index d51ee96..1a7473c 100644
--- a/tests/ref/fate/vp9-03-size-202x198
+++ b/tests/ref/fate/vp9-03-size-202x198
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 202x198
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    59994, 181edc4ebeeff7f0527b93b84d5d8efb
 0,          1,          1,        1,    59994, 132c71b634fb67eed51fcdef1775b6b2
diff --git a/tests/ref/fate/vp9-03-size-202x200 b/tests/ref/fate/vp9-03-size-202x200
index f75e192..513dbf4 100644
--- a/tests/ref/fate/vp9-03-size-202x200
+++ b/tests/ref/fate/vp9-03-size-202x200
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 202x200
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    60600, 20c41d4a1271183dbbc7a44e6b90ea80
 0,          1,          1,        1,    60600, bd8c1fba8d8742f4d98b7d5097c8c828
diff --git a/tests/ref/fate/vp9-03-size-202x202 b/tests/ref/fate/vp9-03-size-202x202
index af7cb9a..5591e51 100644
--- a/tests/ref/fate/vp9-03-size-202x202
+++ b/tests/ref/fate/vp9-03-size-202x202
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 202x202
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    61206, 610cef52d35e9c641f2b8c10489c3d12
 0,          1,          1,        1,    61206, 1f84062e607d4798b0544739fe0da99c
diff --git a/tests/ref/fate/vp9-03-size-202x208 b/tests/ref/fate/vp9-03-size-202x208
index cc85d27..5909265 100644
--- a/tests/ref/fate/vp9-03-size-202x208
+++ b/tests/ref/fate/vp9-03-size-202x208
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 202x208
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    63024, d2128e290be81bb0700ebe19e3faed4f
 0,          1,          1,        1,    63024, dccaecb7e4ddb7e4224221a659af2a43
diff --git a/tests/ref/fate/vp9-03-size-202x210 b/tests/ref/fate/vp9-03-size-202x210
index d51fcc6..eda5a1f 100644
--- a/tests/ref/fate/vp9-03-size-202x210
+++ b/tests/ref/fate/vp9-03-size-202x210
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 202x210
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    63630, e4663a28cabbfdd3815efda2d38debcc
 0,          1,          1,        1,    63630, 3cc7dbec64e9f697f40d740a72c09fc7
diff --git a/tests/ref/fate/vp9-03-size-202x224 b/tests/ref/fate/vp9-03-size-202x224
index 0a36bd3..1024fe8 100644
--- a/tests/ref/fate/vp9-03-size-202x224
+++ b/tests/ref/fate/vp9-03-size-202x224
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 202x224
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    67872, 1d318f05310f6d40646f23c62c7eafe4
 0,          1,          1,        1,    67872, 42870bd73e1a0c5d84b986db3d24f0f0
diff --git a/tests/ref/fate/vp9-03-size-202x226 b/tests/ref/fate/vp9-03-size-202x226
index 6bc31f9..0572eea 100644
--- a/tests/ref/fate/vp9-03-size-202x226
+++ b/tests/ref/fate/vp9-03-size-202x226
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 202x226
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    68478, 5aa0f439c58c6335cd86d4238a8c4b68
 0,          1,          1,        1,    68478, 3616cc306ec05f89d9b0db63200e4abf
diff --git a/tests/ref/fate/vp9-03-size-208x196 b/tests/ref/fate/vp9-03-size-208x196
index b06557f..377dd24 100644
--- a/tests/ref/fate/vp9-03-size-208x196
+++ b/tests/ref/fate/vp9-03-size-208x196
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 208x196
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    61152, 6195975181969789e101a83a555d13f7
 0,          1,          1,        1,    61152, 2aca5e3307d68a5e969564a943b8e723
diff --git a/tests/ref/fate/vp9-03-size-208x198 b/tests/ref/fate/vp9-03-size-208x198
index 84da7dd..486f8d2 100644
--- a/tests/ref/fate/vp9-03-size-208x198
+++ b/tests/ref/fate/vp9-03-size-208x198
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 208x198
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    61776, 1f1fa3cdf865d8c75183f4ba6203b675
 0,          1,          1,        1,    61776, ead33ead8fea5bd5d831a79f4c75a590
diff --git a/tests/ref/fate/vp9-03-size-208x200 b/tests/ref/fate/vp9-03-size-208x200
index 0943abf..40d5d47 100644
--- a/tests/ref/fate/vp9-03-size-208x200
+++ b/tests/ref/fate/vp9-03-size-208x200
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 208x200
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    62400, ff2dda3ddbe8b461d960baba0ad132bf
 0,          1,          1,        1,    62400, d6935ac8f2250316f498e8f01afa04fd
diff --git a/tests/ref/fate/vp9-03-size-208x202 b/tests/ref/fate/vp9-03-size-208x202
index b181224..f7c58e2 100644
--- a/tests/ref/fate/vp9-03-size-208x202
+++ b/tests/ref/fate/vp9-03-size-208x202
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 208x202
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    63024, e5164f87feadf4b65257f578affc3e04
 0,          1,          1,        1,    63024, 6aee5a3b6c3a096dfc1594762b2b248f
diff --git a/tests/ref/fate/vp9-03-size-208x208 b/tests/ref/fate/vp9-03-size-208x208
index 7bcbfdc..fa50887 100644
--- a/tests/ref/fate/vp9-03-size-208x208
+++ b/tests/ref/fate/vp9-03-size-208x208
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 208x208
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    64896, 6bff7c1f4c5ef8412ebf669852c70de6
 0,          1,          1,        1,    64896, fdfd7a2308de9509a41fed2880a8f0f5
diff --git a/tests/ref/fate/vp9-03-size-208x210 b/tests/ref/fate/vp9-03-size-208x210
index 7dbccf6..92f2165 100644
--- a/tests/ref/fate/vp9-03-size-208x210
+++ b/tests/ref/fate/vp9-03-size-208x210
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 208x210
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    65520, b15c7e98ddd137237b062cb51667522f
 0,          1,          1,        1,    65520, 00c594c68b19ef39a79a38e86853dc64
diff --git a/tests/ref/fate/vp9-03-size-208x224 b/tests/ref/fate/vp9-03-size-208x224
index 70d64ea..0d17a9a 100644
--- a/tests/ref/fate/vp9-03-size-208x224
+++ b/tests/ref/fate/vp9-03-size-208x224
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 208x224
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    69888, 479d07bb96905ad7d5f0ec3ee12b41ba
 0,          1,          1,        1,    69888, 4b6555aaed8e5a45879773f1bf87962e
diff --git a/tests/ref/fate/vp9-03-size-208x226 b/tests/ref/fate/vp9-03-size-208x226
index 7d9020c..1e9c284 100644
--- a/tests/ref/fate/vp9-03-size-208x226
+++ b/tests/ref/fate/vp9-03-size-208x226
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 208x226
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    70512, 33aa4af6153570518c59960a0c959053
 0,          1,          1,        1,    70512, 024fa27dee80ad199528052aaa8d42c7
diff --git a/tests/ref/fate/vp9-03-size-210x196 b/tests/ref/fate/vp9-03-size-210x196
index a6813b4..28db1db 100644
--- a/tests/ref/fate/vp9-03-size-210x196
+++ b/tests/ref/fate/vp9-03-size-210x196
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 210x196
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    61740, 5c69f80da667bfd20394995e93e4cd2b
 0,          1,          1,        1,    61740, 13363cd8e52ca8c1053db1c84c111bc9
diff --git a/tests/ref/fate/vp9-03-size-210x198 b/tests/ref/fate/vp9-03-size-210x198
index c14d20c..b676c75 100644
--- a/tests/ref/fate/vp9-03-size-210x198
+++ b/tests/ref/fate/vp9-03-size-210x198
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 210x198
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    62370, d83ee2413e701ae405a2b74863d4c5a9
 0,          1,          1,        1,    62370, f2ebc0f7dc171e0e5d2911c7ee2df5e1
diff --git a/tests/ref/fate/vp9-03-size-210x200 b/tests/ref/fate/vp9-03-size-210x200
index 873525b..01f1093 100644
--- a/tests/ref/fate/vp9-03-size-210x200
+++ b/tests/ref/fate/vp9-03-size-210x200
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 210x200
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    63000, 2465560246c1ee24d937cb9cbc1422f1
 0,          1,          1,        1,    63000, 8926b628dcdf2182516822c7d0d778ec
diff --git a/tests/ref/fate/vp9-03-size-210x202 b/tests/ref/fate/vp9-03-size-210x202
index 91e229e..42924c5 100644
--- a/tests/ref/fate/vp9-03-size-210x202
+++ b/tests/ref/fate/vp9-03-size-210x202
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 210x202
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    63630, 5d01848aee2b324f2e356627f9c39532
 0,          1,          1,        1,    63630, b671fe34bc0e5a682baff929d26ea627
diff --git a/tests/ref/fate/vp9-03-size-210x208 b/tests/ref/fate/vp9-03-size-210x208
index a77ac5f..0d271b2 100644
--- a/tests/ref/fate/vp9-03-size-210x208
+++ b/tests/ref/fate/vp9-03-size-210x208
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 210x208
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    65520, 1156d318c00d299cf5bdc7e485966dab
 0,          1,          1,        1,    65520, a8094f8f1e7e04e54251bee8c4c800ce
diff --git a/tests/ref/fate/vp9-03-size-210x210 b/tests/ref/fate/vp9-03-size-210x210
index fa9f158..bac0e9c 100644
--- a/tests/ref/fate/vp9-03-size-210x210
+++ b/tests/ref/fate/vp9-03-size-210x210
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 210x210
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    66150, b65725c68978bdaaafdf735dfbafa9e3
 0,          1,          1,        1,    66150, 35be2f16bd5dedc9d3f7a016f0d71701
diff --git a/tests/ref/fate/vp9-03-size-210x224 b/tests/ref/fate/vp9-03-size-210x224
index 1e1d225..17ebe8a 100644
--- a/tests/ref/fate/vp9-03-size-210x224
+++ b/tests/ref/fate/vp9-03-size-210x224
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 210x224
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    70560, bb903b926c4b34ae336e21d65ad8fd25
 0,          1,          1,        1,    70560, c4c0bc3b112487e994d22176817ace3c
diff --git a/tests/ref/fate/vp9-03-size-210x226 b/tests/ref/fate/vp9-03-size-210x226
index 5563363..cfadeae 100644
--- a/tests/ref/fate/vp9-03-size-210x226
+++ b/tests/ref/fate/vp9-03-size-210x226
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 210x226
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    71190, 03707b2f5c392933f7336f380423a0a1
 0,          1,          1,        1,    71190, b388553c79573555a3b660f5e36d4e36
diff --git a/tests/ref/fate/vp9-03-size-224x196 b/tests/ref/fate/vp9-03-size-224x196
index 1275e9e..d8a2518 100644
--- a/tests/ref/fate/vp9-03-size-224x196
+++ b/tests/ref/fate/vp9-03-size-224x196
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 224x196
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    65856, 3ffc096f1b42b4d319d4a9efbefc7625
 0,          1,          1,        1,    65856, 78b3655d5cad30fa6b2c2d8fd29463de
diff --git a/tests/ref/fate/vp9-03-size-224x198 b/tests/ref/fate/vp9-03-size-224x198
index 39e0825..f132875 100644
--- a/tests/ref/fate/vp9-03-size-224x198
+++ b/tests/ref/fate/vp9-03-size-224x198
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 224x198
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    66528, cf35dffc80946e87bb9d3e18aab9d320
 0,          1,          1,        1,    66528, a76ac92f05e9b097f8ac5882e1ffe656
diff --git a/tests/ref/fate/vp9-03-size-224x200 b/tests/ref/fate/vp9-03-size-224x200
index 8fbc5b1..a38d414 100644
--- a/tests/ref/fate/vp9-03-size-224x200
+++ b/tests/ref/fate/vp9-03-size-224x200
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 224x200
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    67200, 0819e6d715c9b4d94f05f63a7ca86199
 0,          1,          1,        1,    67200, 9b9a4b01ed4c8a93687e45245b3092a3
diff --git a/tests/ref/fate/vp9-03-size-224x202 b/tests/ref/fate/vp9-03-size-224x202
index 3e212ac..ddf076e 100644
--- a/tests/ref/fate/vp9-03-size-224x202
+++ b/tests/ref/fate/vp9-03-size-224x202
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 224x202
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    67872, e1e3b4af5910383ff6f66b6ab1a29544
 0,          1,          1,        1,    67872, 8668ef92b72f35728ebb456665d48b95
diff --git a/tests/ref/fate/vp9-03-size-224x208 b/tests/ref/fate/vp9-03-size-224x208
index a925e1a..58d8617 100644
--- a/tests/ref/fate/vp9-03-size-224x208
+++ b/tests/ref/fate/vp9-03-size-224x208
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 224x208
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    69888, 85f08afadfd1204d4131b9ee9c8cc10b
 0,          1,          1,        1,    69888, f893de5432a082b3dffcf7499827f548
diff --git a/tests/ref/fate/vp9-03-size-224x210 b/tests/ref/fate/vp9-03-size-224x210
index 3c59459..d24dc4a 100644
--- a/tests/ref/fate/vp9-03-size-224x210
+++ b/tests/ref/fate/vp9-03-size-224x210
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 224x210
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    70560, 427421e5fd2087c6ff7b87a27982332f
 0,          1,          1,        1,    70560, b68311fd44e189e4174ac357d5415068
diff --git a/tests/ref/fate/vp9-03-size-224x224 b/tests/ref/fate/vp9-03-size-224x224
index 610578b..8183364 100644
--- a/tests/ref/fate/vp9-03-size-224x224
+++ b/tests/ref/fate/vp9-03-size-224x224
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 224x224
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    75264, bedd5d2725ffff06a50e23841bc2dfb8
 0,          1,          1,        1,    75264, 8c363f68b0b30f507563516aa99e23ac
diff --git a/tests/ref/fate/vp9-03-size-224x226 b/tests/ref/fate/vp9-03-size-224x226
index 874e595..a5a4ae7 100644
--- a/tests/ref/fate/vp9-03-size-224x226
+++ b/tests/ref/fate/vp9-03-size-224x226
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 224x226
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    75936, dca556e648a576b3973fbe4b34d0328c
 0,          1,          1,        1,    75936, 34a49e4aba4aca5c76ab0f751341c32b
diff --git a/tests/ref/fate/vp9-03-size-226x196 b/tests/ref/fate/vp9-03-size-226x196
index 43d55b9..f85bfb8 100644
--- a/tests/ref/fate/vp9-03-size-226x196
+++ b/tests/ref/fate/vp9-03-size-226x196
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 226x196
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    66444, 4757a31842453f806de2f2256329547e
 0,          1,          1,        1,    66444, fe5fb955a4143091c5bfae7c4a4afe0f
diff --git a/tests/ref/fate/vp9-03-size-226x198 b/tests/ref/fate/vp9-03-size-226x198
index fe2c477..dcb0852 100644
--- a/tests/ref/fate/vp9-03-size-226x198
+++ b/tests/ref/fate/vp9-03-size-226x198
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 226x198
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    67122, b97087eb8c53cf56dc44576912654fb2
 0,          1,          1,        1,    67122, 219bb68a59dc166806a5b5689a943b66
diff --git a/tests/ref/fate/vp9-03-size-226x200 b/tests/ref/fate/vp9-03-size-226x200
index b16c531..7622f29 100644
--- a/tests/ref/fate/vp9-03-size-226x200
+++ b/tests/ref/fate/vp9-03-size-226x200
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 226x200
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    67800, 0ae27db338f73f37eaed806b1c789593
 0,          1,          1,        1,    67800, 3f69273752f43699a3bc7b22a88cc3aa
diff --git a/tests/ref/fate/vp9-03-size-226x202 b/tests/ref/fate/vp9-03-size-226x202
index 818038d..b8a217c 100644
--- a/tests/ref/fate/vp9-03-size-226x202
+++ b/tests/ref/fate/vp9-03-size-226x202
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 226x202
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    68478, 0cd2876640e71de3a6df7839bd6f0b51
 0,          1,          1,        1,    68478, f887db6839c0cddd1ea9ae6bfd2cc16d
diff --git a/tests/ref/fate/vp9-03-size-226x208 b/tests/ref/fate/vp9-03-size-226x208
index cda6f99..cdf1113 100644
--- a/tests/ref/fate/vp9-03-size-226x208
+++ b/tests/ref/fate/vp9-03-size-226x208
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 226x208
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    70512, 6006cac6628cf9e7cea58aec07471b06
 0,          1,          1,        1,    70512, f7e994921248b6933920c984880ec96c
diff --git a/tests/ref/fate/vp9-03-size-226x210 b/tests/ref/fate/vp9-03-size-226x210
index fa83e1d..e903e82 100644
--- a/tests/ref/fate/vp9-03-size-226x210
+++ b/tests/ref/fate/vp9-03-size-226x210
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 226x210
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    71190, a6c1b7686202f5cc64335f92be595309
 0,          1,          1,        1,    71190, 3e573d4c693a39c5d6cd46b8873e99bb
diff --git a/tests/ref/fate/vp9-03-size-226x224 b/tests/ref/fate/vp9-03-size-226x224
index 50d81cb..425490e 100644
--- a/tests/ref/fate/vp9-03-size-226x224
+++ b/tests/ref/fate/vp9-03-size-226x224
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 226x224
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    75936, 80fb3a643384386beadc0991f171669d
 0,          1,          1,        1,    75936, 65a4a51163f49a75f8eeecd94cb2ba47
diff --git a/tests/ref/fate/vp9-03-size-226x226 b/tests/ref/fate/vp9-03-size-226x226
index 88b3c43..5c291e7 100644
--- a/tests/ref/fate/vp9-03-size-226x226
+++ b/tests/ref/fate/vp9-03-size-226x226
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 226x226
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    76614, f2370fc802dafdf5082beffc1907a9c6
 0,          1,          1,        1,    76614, aad6de7b986234a1d621935b272501c9
diff --git a/tests/ref/fate/vp9-05-resize b/tests/ref/fate/vp9-05-resize
index 4a3cd09..6b8823d 100644
--- a/tests/ref/fate/vp9-05-resize
+++ b/tests/ref/fate/vp9-05-resize
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 0/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 539e9964364c1db09ad18f2e01713799
 0,          1,          1,        1,   152064, fb76e673ba2a5342bfed8a1523e0a425
diff --git a/tests/ref/fate/vp9-06-bilinear b/tests/ref/fate/vp9-06-bilinear
index b175195..77369f8 100644
--- a/tests/ref/fate/vp9-06-bilinear
+++ b/tests/ref/fate/vp9-06-bilinear
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 818a5af531c921ae58dfedc75234f3c5
 0,          1,          1,        1,   152064, f863f8c68b5c87c721d345c5a894336d
diff --git a/tests/ref/fate/vp9-09-lf_deltas b/tests/ref/fate/vp9-09-lf_deltas
index 733a70c..278395f 100644
--- a/tests/ref/fate/vp9-09-lf_deltas
+++ b/tests/ref/fate/vp9-09-lf_deltas
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x240
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   126720, a83c7f4602f595fd09e97f8c8a7277ec
 0,          1,          1,        1,   126720, 53e1a3fd44932883a8dd112bbb0e359f
diff --git a/tests/ref/fate/vp9-10-show-existing-frame b/tests/ref/fate/vp9-10-show-existing-frame
index 6a2c904..aeed44a 100644
--- a/tests/ref/fate/vp9-10-show-existing-frame
+++ b/tests/ref/fate/vp9-10-show-existing-frame
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 18981342ec178e082519451062c3a67f
 0,          3,          3,        1,   152064, 04ab9dbeac49ec31be58f6e671698e05
diff --git a/tests/ref/fate/vp9-10-show-existing-frame2 b/tests/ref/fate/vp9-10-show-existing-frame2
index b0fa669..c93a09f 100644
--- a/tests/ref/fate/vp9-10-show-existing-frame2
+++ b/tests/ref/fate/vp9-10-show-existing-frame2
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 382b12c33cd86b38758706b8ebca8a85
 0,          1,          1,        1,   152064, 799544370b35c91711a5b49a28cf86a8
diff --git a/tests/ref/fate/vp9-15-segkey_adpq b/tests/ref/fate/vp9-15-segkey_adpq
index f12db8b..4e4adad 100644
--- a/tests/ref/fate/vp9-15-segkey_adpq
+++ b/tests/ref/fate/vp9-15-segkey_adpq
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 852x480
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   613440, d4f0e4b606ddb40b482aecb24cf3bc63
 0,          1,          1,        1,   613440, 692ec092bc5928fa6430d056e883759a
diff --git a/tests/ref/fate/vp9-16-intra-only b/tests/ref/fate/vp9-16-intra-only
index 1e8d280..a33e62e 100644
--- a/tests/ref/fate/vp9-16-intra-only
+++ b/tests/ref/fate/vp9-16-intra-only
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, d57529601178948afa4818c3c8938884
 0,          1,          1,        1,   152064, d47e00250c45733d64af067a417bcd06
diff --git a/tests/ref/fate/vp9-2pass-akiyo b/tests/ref/fate/vp9-2pass-akiyo
index 2f32092..59c5429 100644
--- a/tests/ref/fate/vp9-2pass-akiyo
+++ b/tests/ref/fate/vp9-2pass-akiyo
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, 043ce065a309514e1e8ebdcbb3c2458b
 0,          1,          1,        1,   152064, 8579c9cffd95b11db86158e518b2e34a
diff --git a/tests/ref/fate/vp9-parallelmode-akiyo b/tests/ref/fate/vp9-parallelmode-akiyo
index 9668c54..df31866 100644
--- a/tests/ref/fate/vp9-parallelmode-akiyo
+++ b/tests/ref/fate/vp9-parallelmode-akiyo
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, f5bc602db15c69545307e56990f9f9f7
 0,          1,          1,        1,   152064, b56428b6f97669938c8b9b05458fca70
diff --git a/tests/ref/fate/vp9-segmentation-aq-akiyo b/tests/ref/fate/vp9-segmentation-aq-akiyo
index 5c931b6..deb5ac5 100644
--- a/tests/ref/fate/vp9-segmentation-aq-akiyo
+++ b/tests/ref/fate/vp9-segmentation-aq-akiyo
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, b208eac12f0ae74a812bc9e314bdfac7
 0,          1,          1,        1,   152064, ebb2259451c3acf3ad6379d1f4092efb
diff --git a/tests/ref/fate/vp9-segmentation-sf-akiyo b/tests/ref/fate/vp9-segmentation-sf-akiyo
index 0fdb3f2..08f1305 100644
--- a/tests/ref/fate/vp9-segmentation-sf-akiyo
+++ b/tests/ref/fate/vp9-segmentation-sf-akiyo
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1001/30000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   152064, f4e04a0f92fab3a52d858bb222807ac0
 0,          1,          1,        1,   152064, 493cb96b8202a1518c6c9bdb848540e4
diff --git a/tests/ref/fate/vp9-tiling-pedestrian b/tests/ref/fate/vp9-tiling-pedestrian
index 2915323..4b25a29 100644
--- a/tests/ref/fate/vp9-tiling-pedestrian
+++ b/tests/ref/fate/vp9-tiling-pedestrian
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1920x1080
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        0,  3110400, 1e6c2e768a5107e57e6d626f0511193a
 0,         40,         40,        0,  3110400, 972d3e2b5ee2e3b0907218a243e4cb7d
diff --git a/tests/ref/fate/vp9-trac3849 b/tests/ref/fate/vp9-trac3849
index 4d129b3..6d6584a 100644
--- a/tests/ref/fate/vp9-trac3849
+++ b/tests/ref/fate/vp9-trac3849
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/30
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 640x360
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   345600, c2ee30cb4529fcbd61938af1887e2b45
 0,          1,          1,        1,   345600, 946e9bfee03777a07c122df038087d92
diff --git a/tests/ref/fate/vp9-trac4359 b/tests/ref/fate/vp9-trac4359
index cd271a7..0f50cff 100644
--- a/tests/ref/fate/vp9-trac4359
+++ b/tests/ref/fate/vp9-trac4359
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,  1382400, 2929e5318edee6cd6b24ede0c1015137
 0,          1,          1,        1,  1382400, ca0d83b04297da33a1aa17129a9fe9c9
diff --git a/tests/ref/fate/vp9p1-04-yuv422 b/tests/ref/fate/vp9p1-04-yuv422
index 59abfb0..3340e74 100644
--- a/tests/ref/fate/vp9p1-04-yuv422
+++ b/tests/ref/fate/vp9p1-04-yuv422
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    28800, b81b8a8444ac6ce4a4807c37e0a44c8b
 0,          1,          1,        1,    28800, 344458b82d35ea9944dc841643fc25c2
diff --git a/tests/ref/fate/vp9p1-04-yuv440 b/tests/ref/fate/vp9p1-04-yuv440
index 0c28f36..17c9f99 100644
--- a/tests/ref/fate/vp9p1-04-yuv440
+++ b/tests/ref/fate/vp9p1-04-yuv440
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    28800, 61157ad4fb02a254de8f34ae7b8915dc
 0,          1,          1,        1,    28800, 9431337382bf90d40aa417e297ac05da
diff --git a/tests/ref/fate/vp9p1-04-yuv444 b/tests/ref/fate/vp9p1-04-yuv444
index e9559c6..b7e5603 100644
--- a/tests/ref/fate/vp9p1-04-yuv444
+++ b/tests/ref/fate/vp9p1-04-yuv444
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x288
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   304128, 859df7b3661783e337a16ee79f3c20bc
 0,          1,          1,        1,   304128, 3b3ccf344cd5a478c4c1fa422497183d
diff --git a/tests/ref/fate/vp9p2-20-10bit-yuv420 b/tests/ref/fate/vp9p2-20-10bit-yuv420
index 297a178..535bd77 100644
--- a/tests/ref/fate/vp9p2-20-10bit-yuv420
+++ b/tests/ref/fate/vp9p2-20-10bit-yuv420
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    43200, c3964ed9065de7f839b8d878444c6140
 0,          1,          1,        1,    43200, 87595f7f53d6e84af9708dba72422cc4
diff --git a/tests/ref/fate/vp9p2-20-12bit-yuv420 b/tests/ref/fate/vp9p2-20-12bit-yuv420
index 1ba0094..e80859b 100644
--- a/tests/ref/fate/vp9p2-20-12bit-yuv420
+++ b/tests/ref/fate/vp9p2-20-12bit-yuv420
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    43200, 8403bd5a381737e1c2d737047f6a5a0b
 0,          1,          1,        1,    43200, 3c0bf7eecc3131e3598f6810d6b70539
diff --git a/tests/ref/fate/vp9p3-20-10bit-yuv422 b/tests/ref/fate/vp9p3-20-10bit-yuv422
index 5aaf056..53d7e66 100644
--- a/tests/ref/fate/vp9p3-20-10bit-yuv422
+++ b/tests/ref/fate/vp9p3-20-10bit-yuv422
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    57600, 18fed3eff623f0308561e5db0bc28691
 0,          1,          1,        1,    57600, 3f22b2269cd53738e955c4b27ff6abce
diff --git a/tests/ref/fate/vp9p3-20-10bit-yuv440 b/tests/ref/fate/vp9p3-20-10bit-yuv440
index cd3f383..8b5416e 100644
--- a/tests/ref/fate/vp9p3-20-10bit-yuv440
+++ b/tests/ref/fate/vp9p3-20-10bit-yuv440
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    57600, 504a347654ef41e568c484ab017f5387
 0,          1,          1,        1,    57600, 6110f151a39144da5616227d44b81c21
diff --git a/tests/ref/fate/vp9p3-20-10bit-yuv444 b/tests/ref/fate/vp9p3-20-10bit-yuv444
index ca218b8..8896186 100644
--- a/tests/ref/fate/vp9p3-20-10bit-yuv444
+++ b/tests/ref/fate/vp9p3-20-10bit-yuv444
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    86400, 06a4c4550dc31f75f842a4e65fc32398
 0,          1,          1,        1,    86400, f7feda15d5c2babc1f6438c72d4900e4
diff --git a/tests/ref/fate/vp9p3-20-12bit-yuv422 b/tests/ref/fate/vp9p3-20-12bit-yuv422
index 1a8a83b..ed4af26 100644
--- a/tests/ref/fate/vp9p3-20-12bit-yuv422
+++ b/tests/ref/fate/vp9p3-20-12bit-yuv422
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    57600, 442a6d932a163907303f1e08056b33b3
 0,          1,          1,        1,    57600, 80b21954eb522f0140e2226a03062839
diff --git a/tests/ref/fate/vp9p3-20-12bit-yuv440 b/tests/ref/fate/vp9p3-20-12bit-yuv440
index f6e4cf1..60d5c58 100644
--- a/tests/ref/fate/vp9p3-20-12bit-yuv440
+++ b/tests/ref/fate/vp9p3-20-12bit-yuv440
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    57600, 9c03fb4aa813522d9a44b3b309b85d19
 0,          1,          1,        1,    57600, 73081beafa17bc23a170172e311c0f54
diff --git a/tests/ref/fate/vp9p3-20-12bit-yuv444 b/tests/ref/fate/vp9p3-20-12bit-yuv444
index 2e53221..9b3b163 100644
--- a/tests/ref/fate/vp9p3-20-12bit-yuv444
+++ b/tests/ref/fate/vp9p3-20-12bit-yuv444
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/50
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x90
+#sar 0: 1/1
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,    86400, d9500a2c9e0b6b44935de019c3583194
 0,          1,          1,        1,    86400, 58edf3e69b332a2b62ca78a8dc99ea68
diff --git a/tests/ref/fate/vqa-cc b/tests/ref/fate/vqa-cc
index 8950f94..fd7bc70 100644
--- a/tests/ref/fate/vqa-cc
+++ b/tests/ref/fate/vqa-cc
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x00000000
 0,          1,          1,        1,   192000, 0x00000000
 0,          2,          2,        1,   192000, 0x00000000
diff --git a/tests/ref/fate/vqf-demux b/tests/ref/fate/vqf-demux
index 3c1dd35..2d26a72 100644
--- a/tests/ref/fate/vqf-demux
+++ b/tests/ref/fate/vqf-demux
@@ -1 +1 @@
-084a9bf92d4096c8156d1fce50dac8b8
+643ac05caf7ef16a8837933bf45281d5
diff --git a/tests/ref/fate/wav-ac3 b/tests/ref/fate/wav-ac3
new file mode 100644
index 0000000..fd27f74
--- /dev/null
+++ b/tests/ref/fate/wav-ac3
@@ -0,0 +1,47 @@
+#tb 0: 1/44100
+#media_type 0: audio
+#codec_id 0: ac3
+#sample_rate 0: 44100
+#channel_layout 0: 60f
+0,          0,          0,     1536,     2786, 0xe2fd0f40
+0,       1536,       1536,     1536,     2786, 0x7a6207c2
+0,       3072,       3072,     1536,     2786, 0x7a6207c2
+0,       4608,       4608,     1536,     2786, 0x7a6207c2
+0,       6144,       6144,     1536,     2786, 0x7a6207c2
+0,       7680,       7680,     1536,     2786, 0x7a6207c2
+0,       9216,       9216,     1536,     2786, 0x41be035e
+0,      10752,      10752,     1536,     2786, 0xc799072a
+0,      12288,      12288,     1536,     2786, 0xf5eb0603
+0,      13824,      13824,     1536,     2786, 0x3d330bb2
+0,      15360,      15360,     1536,     2786, 0x992206d2
+0,      16896,      16896,     1536,     2786, 0x89051878
+0,      18432,      18432,     1536,     2786, 0xe6291a6b
+0,      19968,      19968,     1536,     2786, 0x07c133b4
+0,      21504,      21504,     1536,     2786, 0x61c42e35
+0,      23040,      23040,     1536,     2786, 0x9ec542ae
+0,      24576,      24576,     1536,     2786, 0x42544e06
+0,      26112,      26112,     1536,     2786, 0x0c495e62
+0,      27648,      27648,     1536,     2786, 0x062f78bc
+0,      29184,      29184,     1536,     2786, 0x497a8be9
+0,      30720,      30720,     1536,     2786, 0xedae978e
+0,      32256,      32256,     1536,     2786, 0x77cfaa0f
+0,      33792,      33792,     1536,     2786, 0x1471b792
+0,      35328,      35328,     1536,     2786, 0x76b7daf9
+0,      36864,      36864,     1536,     2786, 0xfc85f35f
+0,      38400,      38400,     1536,     2786, 0xebf8213b
+0,      39936,      39936,     1536,     2786, 0x59e73f77
+0,      41472,      41472,     1536,     2786, 0x98615899
+0,      43008,      43008,     1536,     2786, 0xd9fc642c
+0,      44544,      44544,     1536,     2786, 0x10378c7c
+0,      46080,      46080,     1536,     2786, 0x1d6abbb1
+0,      47616,      47616,     1536,     2786, 0xbe28d007
+0,      49152,      49152,     1536,     2786, 0xa427f2c1
+0,      50688,      50688,     1536,     2786, 0xb43203a3
+0,      52224,      52224,     1536,     2786, 0xcb6d0f2b
+0,      53760,      53760,     1536,     2786, 0x7b833d5c
+0,      55296,      55296,     1536,     2786, 0x26477105
+0,      56832,      56832,     1536,     2786, 0xef16814d
+0,      58368,      58368,     1536,     2786, 0x2a43ae86
+0,      59904,      59904,     1536,     2786, 0x5af1ccb3
+0,      61440,      61440,     1536,     2786, 0x6fa20941
+0,      62976,      62976,     1536,     2786, 0x5d4f336a
diff --git a/tests/ref/fate/wc3movie-xan b/tests/ref/fate/wc3movie-xan
index 57b7f70..5812503 100644
--- a/tests/ref/fate/wc3movie-xan
+++ b/tests/ref/fate/wc3movie-xan
@@ -1,5 +1,13 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x165
+#sar 0: 0/1
 #tb 1: 1/22050
+#media_type 1: audio
+#codec_id 1: pcm_s16le
+#sample_rate 1: 22050
+#channel_layout 1: 4
 0,          0,          0,        1,   158400, 0x25aec781
 1,          0,          0,     1470,     2940, 0x92cee2a6
 0,          1,          1,        1,   158400, 0xda4dbf70
diff --git a/tests/ref/fate/westwood-aud b/tests/ref/fate/westwood-aud
index 9fab241..fedcd5d 100644
--- a/tests/ref/fate/westwood-aud
+++ b/tests/ref/fate/westwood-aud
@@ -1,4 +1,8 @@
 #tb 0: 1/22050
+#media_type 0: audio
+#codec_id 0: adpcm_ima_ws
+#sample_rate 0: 22050
+#channel_layout 0: 4
 0,          0,          0,     1024,      512, 0x6694cc55
 0,       1024,       1024,     1024,      512, 0xdbc5cb22
 0,       2048,       2048,     1024,      512, 0x8e5bcbfd
diff --git a/tests/ref/fate/wmv8-drm b/tests/ref/fate/wmv8-drm
index 12d8fbb..d802b5e 100644
--- a/tests/ref/fate/wmv8-drm
+++ b/tests/ref/fate/wmv8-drm
@@ -1,4 +1,8 @@
 #tb 0: 1/24
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x176
+#sar 0: 0/1
 0,          0,          0,        1,    84480, 0x7760a00b
 0,         29,         29,        1,    84480, 0xfe39a1db
 0,         30,         30,        1,    84480, 0xd71961b4
diff --git a/tests/ref/fate/wmv8-drm-nodec b/tests/ref/fate/wmv8-drm-nodec
index 279c8b6..83aa92d 100644
--- a/tests/ref/fate/wmv8-drm-nodec
+++ b/tests/ref/fate/wmv8-drm-nodec
@@ -1,7 +1,15 @@
 #extradata 0:        4, 0x021800a2
 #extradata 1:       46, 0x63d9043a
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: wmv3
+#dimensions 0: 320x176
+#sar 0: 0/1
 #tb 1: 1/1000
+#media_type 1: audio
+#codec_id 1: wmavoice
+#sample_rate 1: 22050
+#channel_layout 1: 4
 0,          0,          0,        0,      282, 0x000d949a
 1,          0,          0,        0,     1088, 0x5cd379bb
 1,        435,        435,        0,     1088, 0x8dfa1368
diff --git a/tests/ref/fate/wmv8-x8intra b/tests/ref/fate/wmv8-x8intra
index 1f75ce2..c9ed273 100644
--- a/tests/ref/fate/wmv8-x8intra
+++ b/tests/ref/fate/wmv8-x8intra
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x240
+#sar 0: 0/1
 0,          0,          0,        1,   115200, 0x03fbd838
 0,          3,          3,        1,   115200, 0x8911d86f
 0,          4,          4,        1,   115200, 0x7c5dd82e
@@ -19,447 +23,447 @@
 0,         43,         43,        1,   115200, 0x4e673027
 0,         44,         44,        1,   115200, 0x54717979
 0,         45,         45,        1,   115200, 0xf9e557c9
-0,         46,         46,        1,   115200, 0xefad6344
-0,         47,         47,        1,   115200, 0x07497ba3
-0,         48,         48,        1,   115200, 0xabef71d3
-0,         49,         49,        1,   115200, 0x5b8f5802
-0,         50,         50,        1,   115200, 0x8b920b76
-0,         51,         51,        1,   115200, 0xb93f0f04
-0,         52,         52,        1,   115200, 0xa31b18c0
-0,         53,         53,        1,   115200, 0x9116235b
-0,         54,         54,        1,   115200, 0xe54b1d0b
-0,         55,         55,        1,   115200, 0x35e7252a
-0,         56,         56,        1,   115200, 0x2cae31d5
-0,         57,         57,        1,   115200, 0x28493c57
-0,         58,         58,        1,   115200, 0xd8a445b5
-0,         59,         59,        1,   115200, 0xbf854c55
-0,         60,         60,        1,   115200, 0x3761555c
-0,         61,         61,        1,   115200, 0x07a35c8a
-0,         62,         62,        1,   115200, 0x848c6eb0
-0,         63,         63,        1,   115200, 0x8d7c77d1
-0,         64,         64,        1,   115200, 0x903980b7
-0,         65,         65,        1,   115200, 0xbd30898c
-0,         66,         66,        1,   115200, 0x31f78d25
-0,         67,         67,        1,   115200, 0x308aa19d
-0,         68,         68,        1,   115200, 0xf185948c
-0,         69,         69,        1,   115200, 0x8aeea0b9
-0,         70,         70,        1,   115200, 0x06669545
-0,         71,         71,        1,   115200, 0x4d3e84d7
-0,         72,         72,        1,   115200, 0x80007e9c
-0,         73,         73,        1,   115200, 0x7cad6ea5
-0,         74,         74,        1,   115200, 0xd5d747f6
-0,         75,         75,        1,   115200, 0xeddb43bf
-0,         76,         76,        1,   115200, 0x2d3c30b5
-0,         77,         77,        1,   115200, 0x7b465872
-0,         78,         78,        1,   115200, 0xd144b461
-0,         79,         79,        1,   115200, 0x36b0053e
-0,         80,         80,        1,   115200, 0xdf90ec64
-0,         81,         81,        1,   115200, 0xb59cecc6
-0,         82,         82,        1,   115200, 0x0469ed52
-0,         83,         83,        1,   115200, 0x2d7cf7cb
-0,         84,         84,        1,   115200, 0x8376bf2c
-0,         85,         85,        1,   115200, 0xd79dbd1e
-0,         86,         86,        1,   115200, 0xbc79996d
-0,         87,         87,        1,   115200, 0x524d0a62
-0,         88,         88,        1,   115200, 0x07798f44
-0,         89,         89,        1,   115200, 0xd8b85d49
-0,         90,         90,        1,   115200, 0x54126d07
-0,         91,         91,        1,   115200, 0x0346f350
-0,         92,         92,        1,   115200, 0x0feada4f
-0,         93,         93,        1,   115200, 0x74243c65
-0,         94,         94,        1,   115200, 0xbce280c8
-0,         95,         95,        1,   115200, 0xe9bc40c7
-0,         96,         96,        1,   115200, 0x72ecea21
-0,         97,         97,        1,   115200, 0xb4c32a43
-0,         98,         98,        1,   115200, 0x428a6276
-0,         99,         99,        1,   115200, 0xf67f9364
-0,        100,        100,        1,   115200, 0xf25e8858
-0,        101,        101,        1,   115200, 0x9739b909
-0,        102,        102,        1,   115200, 0x8a1b8f38
-0,        103,        103,        1,   115200, 0xe4a2cff1
-0,        104,        104,        1,   115200, 0xa800b83f
+0,         46,         46,        1,   115200, 0xbdcf6358
+0,         47,         47,        1,   115200, 0xd55c7bb7
+0,         48,         48,        1,   115200, 0x78d171e7
+0,         49,         49,        1,   115200, 0x28715816
+0,         50,         50,        1,   115200, 0x58740b8a
+0,         51,         51,        1,   115200, 0x86c10f18
+0,         52,         52,        1,   115200, 0x903918f9
+0,         53,         53,        1,   115200, 0x7f742394
+0,         54,         54,        1,   115200, 0xd3a91d44
+0,         55,         55,        1,   115200, 0x24452563
+0,         56,         56,        1,   115200, 0x1b0c320e
+0,         57,         57,        1,   115200, 0x3a493c8e
+0,         58,         58,        1,   115200, 0xebe445ec
+0,         59,         59,        1,   115200, 0xd2c54c8c
+0,         60,         60,        1,   115200, 0x4aa15593
+0,         61,         61,        1,   115200, 0x19a35cc1
+0,         62,         62,        1,   115200, 0x968c6ee7
+0,         63,         63,        1,   115200, 0x9f7c7808
+0,         64,         64,        1,   115200, 0xa23980ee
+0,         65,         65,        1,   115200, 0xcf3089c3
+0,         66,         66,        1,   115200, 0x43f78d5c
+0,         67,         67,        1,   115200, 0x43caa1d4
+0,         68,         68,        1,   115200, 0x025594c3
+0,         69,         69,        1,   115200, 0x5ec8a11c
+0,         70,         70,        1,   115200, 0x7f2a959b
+0,         71,         71,        1,   115200, 0xc602852d
+0,         72,         72,        1,   115200, 0x67737ef5
+0,         73,         73,        1,   115200, 0x81e06efe
+0,         74,         74,        1,   115200, 0xdb0a484f
+0,         75,         75,        1,   115200, 0xf30e4418
+0,         76,         76,        1,   115200, 0xbdd1310d
+0,         77,         77,        1,   115200, 0x0d2a58ca
+0,         78,         78,        1,   115200, 0xa428b4ba
+0,         79,         79,        1,   115200, 0x4b850596
+0,         80,         80,        1,   115200, 0x38d3ecc0
+0,         81,         81,        1,   115200, 0x6bb0ed23
+0,         82,         82,        1,   115200, 0xb56eedaf
+0,         83,         83,        1,   115200, 0xde81f828
+0,         84,         84,        1,   115200, 0x334abf89
+0,         85,         85,        1,   115200, 0x8e8ebd78
+0,         86,         86,        1,   115200, 0x96ba99c8
+0,         87,         87,        1,   115200, 0x2c8e0abd
+0,         88,         88,        1,   115200, 0xe1ab8f9f
+0,         89,         89,        1,   115200, 0xb2f95da4
+0,         90,         90,        1,   115200, 0x2e536d62
+0,         91,         91,        1,   115200, 0xdd78f3ab
+0,         92,         92,        1,   115200, 0xea1cdaaa
+0,         93,         93,        1,   115200, 0x4e653cc0
+0,         94,         94,        1,   115200, 0x95e38123
+0,         95,         95,        1,   115200, 0x20964119
+0,         96,         96,        1,   115200, 0xcd08ea74
+0,         97,         97,        1,   115200, 0x0eee2a96
+0,         98,         98,        1,   115200, 0x966662c9
+0,         99,         99,        1,   115200, 0x975893b4
+0,        100,        100,        1,   115200, 0x0aa888a7
+0,        101,        101,        1,   115200, 0x80dab966
+0,        102,        102,        1,   115200, 0x78bb8f95
+0,        103,        103,        1,   115200, 0x9c71d03f
+0,        104,        104,        1,   115200, 0xbe5db887
 0,        105,        105,        1,   115200, 0xa88e00d0
-0,        106,        106,        1,   115200, 0x5786082e
-0,        107,        107,        1,   115200, 0xc7205eeb
-0,        108,        108,        1,   115200, 0x9ad02d6b
-0,        109,        109,        1,   115200, 0x5314185d
-0,        110,        110,        1,   115200, 0x015b6351
-0,        111,        111,        1,   115200, 0x51a5c2e1
-0,        112,        112,        1,   115200, 0xc232ec26
-0,        113,        113,        1,   115200, 0x35b30ffc
-0,        114,        114,        1,   115200, 0x2b947acd
-0,        115,        115,        1,   115200, 0xcf1a7971
-0,        116,        116,        1,   115200, 0x70055748
-0,        117,        117,        1,   115200, 0x774b61e6
-0,        118,        118,        1,   115200, 0x74da78a7
-0,        119,        119,        1,   115200, 0x13b5523c
-0,        120,        120,        1,   115200, 0xe27050a0
-0,        121,        121,        1,   115200, 0x073156b0
-0,        122,        122,        1,   115200, 0x9a3662d4
-0,        123,        123,        1,   115200, 0x8c90139c
-0,        124,        124,        1,   115200, 0x45cdeb08
-0,        125,        125,        1,   115200, 0x046ff217
-0,        126,        126,        1,   115200, 0xa6b0a863
-0,        127,        127,        1,   115200, 0xa9c2427a
-0,        128,        128,        1,   115200, 0x7d478df1
-0,        129,        129,        1,   115200, 0x9f426504
-0,        130,        130,        1,   115200, 0x89723d89
-0,        131,        131,        1,   115200, 0x851dd023
-0,        132,        132,        1,   115200, 0xe6ed007d
-0,        133,        133,        1,   115200, 0xfe5cb08d
-0,        134,        134,        1,   115200, 0xc96e52bd
-0,        135,        135,        1,   115200, 0x15c5ffe8
-0,        136,        136,        1,   115200, 0x54540656
-0,        137,        137,        1,   115200, 0xa5e8dbec
-0,        138,        138,        1,   115200, 0x35edde29
-0,        139,        139,        1,   115200, 0xbbb6cb36
-0,        140,        140,        1,   115200, 0x59c5ed50
-0,        141,        141,        1,   115200, 0x7e8a497a
-0,        142,        142,        1,   115200, 0x16586d33
-0,        143,        143,        1,   115200, 0x19dfd6e6
-0,        144,        144,        1,   115200, 0x7ea8574a
-0,        145,        145,        1,   115200, 0x58567b44
-0,        146,        146,        1,   115200, 0x0d2d049e
-0,        147,        147,        1,   115200, 0x7c2d7b00
-0,        148,        148,        1,   115200, 0x92debda6
-0,        149,        149,        1,   115200, 0x1e4cfcc1
-0,        150,        150,        1,   115200, 0xf58b742e
-0,        151,        151,        1,   115200, 0xc2089e8b
-0,        152,        152,        1,   115200, 0x1b4f01e8
-0,        153,        153,        1,   115200, 0x113b1e76
-0,        154,        154,        1,   115200, 0x0f154b48
-0,        155,        155,        1,   115200, 0xf82f5795
-0,        156,        156,        1,   115200, 0xa9f68f5c
-0,        157,        157,        1,   115200, 0xd37992fa
-0,        158,        158,        1,   115200, 0x5e08b0ad
-0,        159,        159,        1,   115200, 0xacf77f50
-0,        160,        160,        1,   115200, 0x4a37945b
-0,        161,        161,        1,   115200, 0x9d2670b7
-0,        162,        162,        1,   115200, 0x7f7e5d76
-0,        163,        163,        1,   115200, 0x357d3ec3
-0,        164,        164,        1,   115200, 0xe4622287
-0,        165,        165,        1,   115200, 0x95260aa6
-0,        166,        166,        1,   115200, 0xff87049a
-0,        167,        167,        1,   115200, 0x5b91c76b
-0,        168,        168,        1,   115200, 0xe5fca44c
-0,        169,        169,        1,   115200, 0xccc46ee1
-0,        170,        170,        1,   115200, 0x0aec53e8
-0,        171,        171,        1,   115200, 0x7509537f
-0,        172,        172,        1,   115200, 0xd6516a81
-0,        173,        173,        1,   115200, 0xbc14562b
-0,        174,        174,        1,   115200, 0xe3f9619e
-0,        175,        175,        1,   115200, 0x2cbe35ef
-0,        176,        176,        1,   115200, 0xd78a40b9
-0,        177,        177,        1,   115200, 0x2cfa08cd
-0,        178,        178,        1,   115200, 0x3ece09fe
-0,        179,        179,        1,   115200, 0xc445d43a
-0,        180,        180,        1,   115200, 0xe1cbacdd
-0,        181,        181,        1,   115200, 0x7a03b421
-0,        182,        182,        1,   115200, 0x7c80ab27
-0,        183,        183,        1,   115200, 0xececae60
-0,        184,        184,        1,   115200, 0xef00c6b3
-0,        185,        185,        1,   115200, 0xcdc9e78d
-0,        186,        186,        1,   115200, 0xa5170dd1
-0,        187,        187,        1,   115200, 0xfe561e1f
-0,        188,        188,        1,   115200, 0xc5d056f9
-0,        189,        189,        1,   115200, 0xf0267284
-0,        190,        190,        1,   115200, 0xcdc4a09a
-0,        191,        191,        1,   115200, 0xa8c8af40
-0,        192,        192,        1,   115200, 0x0c0cc987
-0,        193,        193,        1,   115200, 0x13a0cc64
-0,        194,        194,        1,   115200, 0x0ff3e6fe
-0,        195,        195,        1,   115200, 0x7fbfe852
-0,        196,        196,        1,   115200, 0x62ea0273
-0,        197,        197,        1,   115200, 0x8d021330
-0,        198,        198,        1,   115200, 0x7ac6321a
-0,        199,        199,        1,   115200, 0xefc92de8
-0,        200,        200,        1,   115200, 0x4be95c24
-0,        201,        201,        1,   115200, 0xf62c79b0
-0,        202,        202,        1,   115200, 0x1d9f85c6
-0,        203,        203,        1,   115200, 0x13b6ad8f
-0,        204,        204,        1,   115200, 0x3d96e451
-0,        205,        205,        1,   115200, 0x0891f3c4
-0,        206,        206,        1,   115200, 0xc728f8cd
-0,        207,        207,        1,   115200, 0x9481ee74
-0,        208,        208,        1,   115200, 0xaf95fcf9
-0,        209,        209,        1,   115200, 0x856fe48d
-0,        210,        210,        1,   115200, 0x5b9c03da
-0,        211,        211,        1,   115200, 0x98f80228
-0,        212,        212,        1,   115200, 0xa4e52148
-0,        213,        213,        1,   115200, 0x65bc4b91
-0,        214,        214,        1,   115200, 0x0c166312
-0,        215,        215,        1,   115200, 0x4657a356
-0,        216,        216,        1,   115200, 0xf17e0003
-0,        217,        217,        1,   115200, 0x95a81738
-0,        218,        218,        1,   115200, 0xb02d6bd9
-0,        219,        219,        1,   115200, 0x2594e89d
-0,        220,        220,        1,   115200, 0x5c4a1349
-0,        221,        221,        1,   115200, 0xbc9d5875
-0,        222,        222,        1,   115200, 0xd935b307
-0,        223,        223,        1,   115200, 0x2114cb84
-0,        224,        224,        1,   115200, 0xbe58130c
-0,        225,        225,        1,   115200, 0x7a3d2b2b
-0,        226,        226,        1,   115200, 0xe5753e6b
-0,        227,        227,        1,   115200, 0xc84042cc
-0,        228,        228,        1,   115200, 0x98ef4c58
-0,        229,        229,        1,   115200, 0x2cb83bff
-0,        230,        230,        1,   115200, 0x4e58433a
-0,        231,        231,        1,   115200, 0x7ec26734
-0,        232,        232,        1,   115200, 0x49168d07
-0,        233,        233,        1,   115200, 0xfc9e82f2
-0,        234,        234,        1,   115200, 0x49976c26
-0,        235,        235,        1,   115200, 0xa12466ff
-0,        236,        236,        1,   115200, 0x98ae6499
-0,        237,        237,        1,   115200, 0xc8575e78
-0,        238,        238,        1,   115200, 0xc6596cd2
-0,        239,        239,        1,   115200, 0x83d9a068
-0,        240,        240,        1,   115200, 0xe819b560
-0,        241,        241,        1,   115200, 0xb07ac3c3
-0,        242,        242,        1,   115200, 0x3d79ef5b
-0,        243,        243,        1,   115200, 0xbc6800e0
-0,        244,        244,        1,   115200, 0xc78c15f8
-0,        245,        245,        1,   115200, 0xcb91360b
-0,        246,        246,        1,   115200, 0x6c657143
-0,        247,        247,        1,   115200, 0x636391d1
-0,        248,        248,        1,   115200, 0xb519e49d
-0,        249,        249,        1,   115200, 0xb65d00c5
-0,        250,        250,        1,   115200, 0x14672ba8
-0,        251,        251,        1,   115200, 0xb65d389f
-0,        252,        252,        1,   115200, 0xe88e991b
-0,        253,        253,        1,   115200, 0x6a7bad4e
-0,        254,        254,        1,   115200, 0xd305eca1
+0,        106,        106,        1,   115200, 0xc7b50827
+0,        107,        107,        1,   115200, 0xf9155ed3
+0,        108,        108,        1,   115200, 0x8dd72d44
+0,        109,        109,        1,   115200, 0xee38183a
+0,        110,        110,        1,   115200, 0xea2b6329
+0,        111,        111,        1,   115200, 0xf556c2b3
+0,        112,        112,        1,   115200, 0x90edebf9
+0,        113,        113,        1,   115200, 0x4f440fdf
+0,        114,        114,        1,   115200, 0xfdec7a9d
+0,        115,        115,        1,   115200, 0xc7927952
+0,        116,        116,        1,   115200, 0xdd475704
+0,        117,        117,        1,   115200, 0x974a61a5
+0,        118,        118,        1,   115200, 0xbf2b785e
+0,        119,        119,        1,   115200, 0x5de451fa
+0,        120,        120,        1,   115200, 0x3fac503e
+0,        121,        121,        1,   115200, 0xc6785643
+0,        122,        122,        1,   115200, 0xe6666254
+0,        123,        123,        1,   115200, 0x1a05130c
+0,        124,        124,        1,   115200, 0x082cea5d
+0,        125,        125,        1,   115200, 0x473ef142
+0,        126,        126,        1,   115200, 0x9769a776
+0,        127,        127,        1,   115200, 0xe6e841af
+0,        128,        128,        1,   115200, 0xa44c8d1e
+0,        129,        129,        1,   115200, 0xd03d641b
+0,        130,        130,        1,   115200, 0x3aea3c9e
+0,        131,        131,        1,   115200, 0x09efcf21
+0,        132,        132,        1,   115200, 0xeeb6ff64
+0,        133,        133,        1,   115200, 0xa310af6f
+0,        134,        134,        1,   115200, 0x2488519e
+0,        135,        135,        1,   115200, 0x48e1febf
+0,        136,        136,        1,   115200, 0x76d00513
+0,        137,        137,        1,   115200, 0xa28eda81
+0,        138,        138,        1,   115200, 0xc2cbdcae
+0,        139,        139,        1,   115200, 0xd976c9b2
+0,        140,        140,        1,   115200, 0xb0abebab
+0,        141,        141,        1,   115200, 0x32be4765
+0,        142,        142,        1,   115200, 0xc0a36b11
+0,        143,        143,        1,   115200, 0xb6d1d47f
+0,        144,        144,        1,   115200, 0xab7954a6
+0,        145,        145,        1,   115200, 0xc485789c
+0,        146,        146,        1,   115200, 0xa07101b6
+0,        147,        147,        1,   115200, 0x6297780a
+0,        148,        148,        1,   115200, 0xf550ba94
+0,        149,        149,        1,   115200, 0x9b77f994
+0,        150,        150,        1,   115200, 0xb0e870ad
+0,        151,        151,        1,   115200, 0x2dd89b0b
+0,        152,        152,        1,   115200, 0x36dcfe2f
+0,        153,        153,        1,   115200, 0x3e5e1a8f
+0,        154,        154,        1,   115200, 0xb8394740
+0,        155,        155,        1,   115200, 0xbfc852fc
+0,        156,        156,        1,   115200, 0x5b3f8aa2
+0,        157,        157,        1,   115200, 0xc29d8e3a
+0,        158,        158,        1,   115200, 0x7300abd8
+0,        159,        159,        1,   115200, 0xd1dd7a3b
+0,        160,        160,        1,   115200, 0xe5978f39
+0,        161,        161,        1,   115200, 0x235c6b8d
+0,        162,        162,        1,   115200, 0xec1b5805
+0,        163,        163,        1,   115200, 0x16d23946
+0,        164,        164,        1,   115200, 0xa8de1cf4
+0,        165,        165,        1,   115200, 0x5e730512
+0,        166,        166,        1,   115200, 0x1250feed
+0,        167,        167,        1,   115200, 0x0928c190
+0,        168,        168,        1,   115200, 0xa25d9e5c
+0,        169,        169,        1,   115200, 0x921068ea
+0,        170,        170,        1,   115200, 0x2c974ddb
+0,        171,        171,        1,   115200, 0x35ae4d75
+0,        172,        172,        1,   115200, 0xec0c6469
+0,        173,        173,        1,   115200, 0x22704fad
+0,        174,        174,        1,   115200, 0x0a9a5aed
+0,        175,        175,        1,   115200, 0x45192f2f
+0,        176,        176,        1,   115200, 0xc07b39f4
+0,        177,        177,        1,   115200, 0x32c60215
+0,        178,        178,        1,   115200, 0xda65035e
+0,        179,        179,        1,   115200, 0x99d0cd81
+0,        180,        180,        1,   115200, 0xd08ca5e3
+0,        181,        181,        1,   115200, 0x82cdad17
+0,        182,        182,        1,   115200, 0x2587a420
+0,        183,        183,        1,   115200, 0x85cba73d
+0,        184,        184,        1,   115200, 0x4677bf89
+0,        185,        185,        1,   115200, 0x84c2e034
+0,        186,        186,        1,   115200, 0xd343066c
+0,        187,        187,        1,   115200, 0xdec716a1
+0,        188,        188,        1,   115200, 0x93c04f5d
+0,        189,        189,        1,   115200, 0xce126ac4
+0,        190,        190,        1,   115200, 0xa20098c5
+0,        191,        191,        1,   115200, 0x9a4ca711
+0,        192,        192,        1,   115200, 0xfae9c154
+0,        193,        193,        1,   115200, 0xb34cc431
+0,        194,        194,        1,   115200, 0x923cdec2
+0,        195,        195,        1,   115200, 0x60ffdfe8
+0,        196,        196,        1,   115200, 0xa3e6f9f2
+0,        197,        197,        1,   115200, 0x374f0a47
+0,        198,        198,        1,   115200, 0x8fb228f1
+0,        199,        199,        1,   115200, 0x4c1a24bf
+0,        200,        200,        1,   115200, 0x768a52d1
+0,        201,        201,        1,   115200, 0x5bf77025
+0,        202,        202,        1,   115200, 0x6ca67c2a
+0,        203,        203,        1,   115200, 0x107ca3e9
+0,        204,        204,        1,   115200, 0x4abeda93
+0,        205,        205,        1,   115200, 0x750be9ff
+0,        206,        206,        1,   115200, 0x28c5eee3
+0,        207,        207,        1,   115200, 0xa1b0e4b2
+0,        208,        208,        1,   115200, 0x2ae7f33d
+0,        209,        209,        1,   115200, 0xf29cdae0
+0,        210,        210,        1,   115200, 0xd470f9ed
+0,        211,        211,        1,   115200, 0x2d22f832
+0,        212,        212,        1,   115200, 0xc5b91780
+0,        213,        213,        1,   115200, 0x3d8e4151
+0,        214,        214,        1,   115200, 0x459f58e0
+0,        215,        215,        1,   115200, 0x8dc198fe
+0,        216,        216,        1,   115200, 0x2479f579
+0,        217,        217,        1,   115200, 0xc2040c21
+0,        218,        218,        1,   115200, 0x39ad60d5
+0,        219,        219,        1,   115200, 0x9329dd37
+0,        220,        220,        1,   115200, 0xa08807da
+0,        221,        221,        1,   115200, 0xbf514cd1
+0,        222,        222,        1,   115200, 0x8b66a779
+0,        223,        223,        1,   115200, 0x865ebff5
+0,        224,        224,        1,   115200, 0x5967074c
+0,        225,        225,        1,   115200, 0xd5521f60
+0,        226,        226,        1,   115200, 0x462c329c
+0,        227,        227,        1,   115200, 0xbefd36fb
+0,        228,        228,        1,   115200, 0x6f58403b
+0,        229,        229,        1,   115200, 0xe4af2fac
+0,        230,        230,        1,   115200, 0x46453662
+0,        231,        231,        1,   115200, 0x72cc59e8
+0,        232,        232,        1,   115200, 0xd6c67f8e
+0,        233,        233,        1,   115200, 0xd35674a7
+0,        234,        234,        1,   115200, 0x65785ddb
+0,        235,        235,        1,   115200, 0xfd7958aa
+0,        236,        236,        1,   115200, 0x93e45607
+0,        237,        237,        1,   115200, 0x196a4fa5
+0,        238,        238,        1,   115200, 0xe33a5dac
+0,        239,        239,        1,   115200, 0x4e66904a
+0,        240,        240,        1,   115200, 0xc1e3a50a
+0,        241,        241,        1,   115200, 0xa685b351
+0,        242,        242,        1,   115200, 0xee2fdeb7
+0,        243,        243,        1,   115200, 0x189cefdd
+0,        244,        244,        1,   115200, 0xbdf90506
+0,        245,        245,        1,   115200, 0xe72c23d2
+0,        246,        246,        1,   115200, 0xa3f65e7b
+0,        247,        247,        1,   115200, 0x8bc67eee
+0,        248,        248,        1,   115200, 0xd305d09b
+0,        249,        249,        1,   115200, 0xc521eba5
+0,        250,        250,        1,   115200, 0x16cf161f
+0,        251,        251,        1,   115200, 0x2ce322b5
+0,        252,        252,        1,   115200, 0x57ce82b4
+0,        253,        253,        1,   115200, 0x8da896b9
+0,        254,        254,        1,   115200, 0xc16ad590
 0,        255,        255,        1,   115200, 0x8cdbe729
-0,        256,        256,        1,   115200, 0x0d1bfd9a
-0,        257,        257,        1,   115200, 0xef740a06
-0,        258,        258,        1,   115200, 0x1cd423df
-0,        259,        259,        1,   115200, 0xf78616ba
-0,        260,        260,        1,   115200, 0xcc0b2b81
-0,        261,        261,        1,   115200, 0x434e4ae9
-0,        262,        262,        1,   115200, 0xf2d461ec
-0,        263,        263,        1,   115200, 0xc75f6a15
-0,        264,        264,        1,   115200, 0x71038c87
-0,        265,        265,        1,   115200, 0x7a55ab55
-0,        266,        266,        1,   115200, 0xeef2e1de
-0,        267,        267,        1,   115200, 0xd2600c3d
-0,        268,        268,        1,   115200, 0xdd872452
-0,        269,        269,        1,   115200, 0xd1361fcd
-0,        270,        270,        1,   115200, 0xda4f0d12
-0,        271,        271,        1,   115200, 0xba061920
-0,        272,        272,        1,   115200, 0x4b2ef9ed
-0,        273,        273,        1,   115200, 0x11dfab08
-0,        274,        274,        1,   115200, 0x7a603fc2
-0,        275,        275,        1,   115200, 0x61690ad9
-0,        276,        276,        1,   115200, 0x481ac8b9
-0,        277,        277,        1,   115200, 0xea35570d
+0,        256,        256,        1,   115200, 0x69eafd96
+0,        257,        257,        1,   115200, 0xd9e40a03
+0,        258,        258,        1,   115200, 0xb91423e1
+0,        259,        259,        1,   115200, 0x09b516bd
+0,        260,        260,        1,   115200, 0x20292b85
+0,        261,        261,        1,   115200, 0x8cbb4aeb
+0,        262,        262,        1,   115200, 0x99b761ec
+0,        263,        263,        1,   115200, 0x28406a14
+0,        264,        264,        1,   115200, 0xea368c86
+0,        265,        265,        1,   115200, 0xf388ab54
+0,        266,        266,        1,   115200, 0x263fe1de
+0,        267,        267,        1,   115200, 0xc3410c39
+0,        268,        268,        1,   115200, 0xc056244d
+0,        269,        269,        1,   115200, 0x99c51fc5
+0,        270,        270,        1,   115200, 0x7e4a0d07
+0,        271,        271,        1,   115200, 0xcd911916
+0,        272,        272,        1,   115200, 0x8bd0fa21
+0,        273,        273,        1,   115200, 0xd1a1ab71
+0,        274,        274,        1,   115200, 0xbc904028
+0,        275,        275,        1,   115200, 0xfd480acc
+0,        276,        276,        1,   115200, 0x1cb5c8b5
+0,        277,        277,        1,   115200, 0xcad15709
 0,        278,        278,        1,   115200, 0xdd306f19
 0,        279,        279,        1,   115200, 0x3f975f1b
 0,        280,        280,        1,   115200, 0x2386cd1f
-0,        281,        281,        1,   115200, 0x1b77f573
+0,        281,        281,        1,   115200, 0xcaa4f5b0
 0,        282,        282,        1,   115200, 0x8ce213de
 0,        283,        283,        1,   115200, 0x5f7407c6
 0,        284,        284,        1,   115200, 0x01b3ee00
 0,        285,        285,        1,   115200, 0x92759715
 0,        286,        286,        1,   115200, 0x4a208e1e
 0,        287,        287,        1,   115200, 0x6e1b80a5
-0,        288,        288,        1,   115200, 0x298c7621
-0,        289,        289,        1,   115200, 0x0e255da8
-0,        290,        290,        1,   115200, 0xabd661ca
-0,        291,        291,        1,   115200, 0x6f045226
-0,        292,        292,        1,   115200, 0x396a5e4c
-0,        293,        293,        1,   115200, 0x4bd53915
-0,        294,        294,        1,   115200, 0xaf9631b3
-0,        295,        295,        1,   115200, 0xb2602290
-0,        296,        296,        1,   115200, 0xb1272f1b
-0,        297,        297,        1,   115200, 0xe8d23699
-0,        298,        298,        1,   115200, 0xd6e2558d
-0,        299,        299,        1,   115200, 0xf1270106
-0,        300,        300,        1,   115200, 0x6ab1fc4f
-0,        301,        301,        1,   115200, 0x4a9b5c6f
-0,        302,        302,        1,   115200, 0x14177b61
-0,        303,        303,        1,   115200, 0x8f7f7971
-0,        304,        304,        1,   115200, 0x165973cd
-0,        305,        305,        1,   115200, 0x341c4ba5
-0,        306,        306,        1,   115200, 0x08df3902
-0,        307,        307,        1,   115200, 0x4c1e386a
-0,        308,        308,        1,   115200, 0x1b1c387c
-0,        309,        309,        1,   115200, 0xe42fdb83
-0,        310,        310,        1,   115200, 0x5bb2ad2e
-0,        311,        311,        1,   115200, 0x31924902
-0,        312,        312,        1,   115200, 0x5a290e9a
-0,        313,        313,        1,   115200, 0x15d6ea45
-0,        314,        314,        1,   115200, 0xb5adc34d
-0,        315,        315,        1,   115200, 0xb210a956
-0,        316,        316,        1,   115200, 0x79478dac
-0,        317,        317,        1,   115200, 0x626a3fa9
-0,        318,        318,        1,   115200, 0x6b0e370d
-0,        319,        319,        1,   115200, 0x1f1113ec
-0,        320,        320,        1,   115200, 0x362efa10
-0,        321,        321,        1,   115200, 0xca8de637
-0,        322,        322,        1,   115200, 0x432e1f19
-0,        323,        323,        1,   115200, 0xa2c93031
-0,        324,        324,        1,   115200, 0x63294fcc
-0,        325,        325,        1,   115200, 0x1c1d5928
-0,        326,        326,        1,   115200, 0xe5fb45ea
-0,        327,        327,        1,   115200, 0x0712cc77
-0,        328,        328,        1,   115200, 0xaef1c94b
-0,        329,        329,        1,   115200, 0x30c8a84e
-0,        330,        330,        1,   115200, 0xd6896b75
-0,        331,        331,        1,   115200, 0x7f8839cb
-0,        332,        332,        1,   115200, 0xcd69d7d4
-0,        333,        333,        1,   115200, 0xa6f3cdaa
-0,        334,        334,        1,   115200, 0xccbdc609
-0,        335,        335,        1,   115200, 0x2d3f77d7
-0,        336,        336,        1,   115200, 0x18f8582d
-0,        337,        337,        1,   115200, 0xe88717bb
-0,        338,        338,        1,   115200, 0xb42fd44b
-0,        339,        339,        1,   115200, 0x7edaa5b7
-0,        340,        340,        1,   115200, 0xef399a7b
-0,        341,        341,        1,   115200, 0x11d75f35
-0,        342,        342,        1,   115200, 0xc0717b78
+0,        288,        288,        1,   115200, 0xe78c7622
+0,        289,        289,        1,   115200, 0xcc255da9
+0,        290,        290,        1,   115200, 0x69e561cb
+0,        291,        291,        1,   115200, 0x2d135227
+0,        292,        292,        1,   115200, 0xfc6a5e4d
+0,        293,        293,        1,   115200, 0x81473914
+0,        294,        294,        1,   115200, 0xe50831b2
+0,        295,        295,        1,   115200, 0xe7d2228f
+0,        296,        296,        1,   115200, 0xe6992f1a
+0,        297,        297,        1,   115200, 0x1e533698
+0,        298,        298,        1,   115200, 0x0c63558c
+0,        299,        299,        1,   115200, 0x54990104
+0,        300,        300,        1,   115200, 0xce14fc4d
+0,        301,        301,        1,   115200, 0x760b5c6e
+0,        302,        302,        1,   115200, 0x14157b61
+0,        303,        303,        1,   115200, 0x62ca7972
+0,        304,        304,        1,   115200, 0xe99573ce
+0,        305,        305,        1,   115200, 0x36df4b8d
+0,        306,        306,        1,   115200, 0x272238ea
+0,        307,        307,        1,   115200, 0x606e3863
+0,        308,        308,        1,   115200, 0x8b143873
+0,        309,        309,        1,   115200, 0x2e46db9e
+0,        310,        310,        1,   115200, 0x1131ad78
+0,        311,        311,        1,   115200, 0x52f34951
+0,        312,        312,        1,   115200, 0xd4590eea
+0,        313,        313,        1,   115200, 0x44ddeaa2
+0,        314,        314,        1,   115200, 0xbc83c399
+0,        315,        315,        1,   115200, 0x5e9da9a7
+0,        316,        316,        1,   115200, 0xca6a8dfc
+0,        317,        317,        1,   115200, 0xe17b3ff8
+0,        318,        318,        1,   115200, 0xea1f375c
+0,        319,        319,        1,   115200, 0xa265143b
+0,        320,        320,        1,   115200, 0xe788fa1e
+0,        321,        321,        1,   115200, 0xd58be649
+0,        322,        322,        1,   115200, 0x740c1f19
+0,        323,        323,        1,   115200, 0xfab3302f
+0,        324,        324,        1,   115200, 0x1c954fc7
+0,        325,        325,        1,   115200, 0xd57a5923
+0,        326,        326,        1,   115200, 0x099745d9
+0,        327,        327,        1,   115200, 0x2e61cc66
+0,        328,        328,        1,   115200, 0xdb3ec93a
+0,        329,        329,        1,   115200, 0x553ba839
+0,        330,        330,        1,   115200, 0xfafc6b60
+0,        331,        331,        1,   115200, 0xa3fb39b6
+0,        332,        332,        1,   115200, 0x7fb9d7be
+0,        333,        333,        1,   115200, 0x7e73cd93
+0,        334,        334,        1,   115200, 0xa43ec5f2
+0,        335,        335,        1,   115200, 0x3ec077c1
+0,        336,        336,        1,   115200, 0xc4275815
+0,        337,        337,        1,   115200, 0xf84c17bf
+0,        338,        338,        1,   115200, 0x1f54d44d
+0,        339,        339,        1,   115200, 0x566fa5bb
+0,        340,        340,        1,   115200, 0x82179a82
+0,        341,        341,        1,   115200, 0xf8865f3d
+0,        342,        342,        1,   115200, 0xa5fb7b80
 0,        343,        343,        1,   115200, 0x9aebc04d
 0,        344,        344,        1,   115200, 0x44c705fc
 0,        345,        345,        1,   115200, 0xd322add3
-0,        346,        346,        1,   115200, 0x0f5f0b79
-0,        347,        347,        1,   115200, 0x54a15070
-0,        348,        348,        1,   115200, 0xd11553df
-0,        349,        349,        1,   115200, 0x6f3ed910
-0,        350,        350,        1,   115200, 0x6d3a3c17
-0,        351,        351,        1,   115200, 0x434ebc13
-0,        352,        352,        1,   115200, 0xcf07ecb2
-0,        353,        353,        1,   115200, 0x1c94497e
-0,        354,        354,        1,   115200, 0x83c13cbc
-0,        355,        355,        1,   115200, 0x4a8ba4f5
-0,        356,        356,        1,   115200, 0x922a393f
-0,        357,        357,        1,   115200, 0x44024959
-0,        358,        358,        1,   115200, 0x23f18ebd
-0,        359,        359,        1,   115200, 0x2cdf1146
-0,        360,        360,        1,   115200, 0x8a7d402c
-0,        361,        361,        1,   115200, 0x42d67bb3
-0,        362,        362,        1,   115200, 0x7045ff2c
-0,        363,        363,        1,   115200, 0xb67a4f15
-0,        364,        364,        1,   115200, 0x7481f311
-0,        365,        365,        1,   115200, 0xe394ff8d
-0,        366,        366,        1,   115200, 0x2ca16f23
-0,        367,        367,        1,   115200, 0xd53238e1
-0,        368,        368,        1,   115200, 0xe28a80c9
-0,        369,        369,        1,   115200, 0x043ccd51
-0,        370,        370,        1,   115200, 0x2e950d80
-0,        371,        371,        1,   115200, 0xf7394c6e
-0,        372,        372,        1,   115200, 0xae46d2c8
-0,        373,        373,        1,   115200, 0x4b54df85
-0,        374,        374,        1,   115200, 0x636f4ca5
-0,        375,        375,        1,   115200, 0x2c687754
-0,        376,        376,        1,   115200, 0x0ddea0f9
-0,        377,        377,        1,   115200, 0x82b08dfd
-0,        378,        378,        1,   115200, 0x5db58c25
-0,        379,        379,        1,   115200, 0x9b975eaa
-0,        380,        380,        1,   115200, 0x2cbe4bf1
-0,        381,        381,        1,   115200, 0xc8873bd7
-0,        382,        382,        1,   115200, 0x9aa357f2
-0,        383,        383,        1,   115200, 0x526e5392
-0,        384,        384,        1,   115200, 0x30aa5d18
-0,        385,        385,        1,   115200, 0x1fe738b4
-0,        386,        386,        1,   115200, 0x9cec04ad
-0,        387,        387,        1,   115200, 0x3ddd922d
-0,        388,        388,        1,   115200, 0xc6578bbb
-0,        389,        389,        1,   115200, 0x413c35ae
-0,        390,        390,        1,   115200, 0x90095ab3
-0,        391,        391,        1,   115200, 0x8ae84371
-0,        392,        392,        1,   115200, 0x1c935404
-0,        393,        393,        1,   115200, 0x213f37e8
-0,        394,        394,        1,   115200, 0x19ab39e6
-0,        395,        395,        1,   115200, 0x795bf82f
-0,        396,        396,        1,   115200, 0xe238fccf
-0,        397,        397,        1,   115200, 0xe2c0d69e
-0,        398,        398,        1,   115200, 0xa1e9d34c
-0,        399,        399,        1,   115200, 0xedf3d303
-0,        400,        400,        1,   115200, 0x40fac156
-0,        401,        401,        1,   115200, 0x1bc59ddb
-0,        402,        402,        1,   115200, 0x4295a2ab
-0,        403,        403,        1,   115200, 0xc337809d
-0,        404,        404,        1,   115200, 0x4a329996
-0,        405,        405,        1,   115200, 0xb4fa76b4
-0,        406,        406,        1,   115200, 0xb49b7d18
-0,        407,        407,        1,   115200, 0xfab67262
-0,        408,        408,        1,   115200, 0x31919404
-0,        409,        409,        1,   115200, 0x983d896c
-0,        410,        410,        1,   115200, 0x8594939e
-0,        411,        411,        1,   115200, 0x9fb8932a
-0,        412,        412,        1,   115200, 0xb9f3af07
-0,        413,        413,        1,   115200, 0x5904c5b4
-0,        414,        414,        1,   115200, 0xf6e095d6
-0,        415,        415,        1,   115200, 0xd168bd86
-0,        416,        416,        1,   115200, 0x39151a63
-0,        417,        417,        1,   115200, 0x9e426f6d
-0,        418,        418,        1,   115200, 0x0c6d7d1d
-0,        419,        419,        1,   115200, 0x65f787ca
-0,        420,        420,        1,   115200, 0xf42288c6
-0,        421,        421,        1,   115200, 0x565b8d91
-0,        422,        422,        1,   115200, 0xd72e882f
-0,        423,        423,        1,   115200, 0x8def886c
-0,        424,        424,        1,   115200, 0x1d5e7800
-0,        425,        425,        1,   115200, 0x628276f7
-0,        426,        426,        1,   115200, 0x00e27d0f
-0,        427,        427,        1,   115200, 0x52df7737
-0,        428,        428,        1,   115200, 0xf98f6303
-0,        429,        429,        1,   115200, 0x9a2d2d65
-0,        430,        430,        1,   115200, 0xd8cb25f5
-0,        431,        431,        1,   115200, 0x68071ce1
-0,        432,        432,        1,   115200, 0x4c6218c9
-0,        433,        433,        1,   115200, 0xaf0a11a3
-0,        434,        434,        1,   115200, 0xfa0a0fb9
-0,        435,        435,        1,   115200, 0xc61414fb
-0,        436,        436,        1,   115200, 0x3a8b0e94
-0,        437,        437,        1,   115200, 0x1eab0e92
-0,        438,        438,        1,   115200, 0xc726028c
-0,        439,        439,        1,   115200, 0x2da2f5de
-0,        440,        440,        1,   115200, 0x7672e92f
-0,        441,        441,        1,   115200, 0x7edae686
-0,        442,        442,        1,   115200, 0x9a6ce3c6
-0,        443,        443,        1,   115200, 0x9f69e74c
-0,        444,        444,        1,   115200, 0x73fbf502
-0,        445,        445,        1,   115200, 0xff81f5b8
-0,        446,        446,        1,   115200, 0x2b8bf7de
-0,        447,        447,        1,   115200, 0xcd00f380
-0,        448,        448,        1,   115200, 0x4cedfe7c
-0,        449,        449,        1,   115200, 0xcd30fbb4
-0,        450,        450,        1,   115200, 0x4b7df228
-0,        451,        451,        1,   115200, 0xedc7e5df
-0,        452,        452,        1,   115200, 0x687ae0f5
-0,        453,        453,        1,   115200, 0x8127e2b9
-0,        454,        454,        1,   115200, 0xe31ae11c
-0,        455,        455,        1,   115200, 0xece5e5c5
-0,        456,        456,        1,   115200, 0x4f1bdfe4
-0,        457,        457,        1,   115200, 0x65c5dfe3
-0,        458,        458,        1,   115200, 0xfc89d51f
+0,        346,        346,        1,   115200, 0xf4230b76
+0,        347,        347,        1,   115200, 0xaa915069
+0,        348,        348,        1,   115200, 0x518d53d8
+0,        349,        349,        1,   115200, 0xefa7d909
+0,        350,        350,        1,   115200, 0x803c3c0e
+0,        351,        351,        1,   115200, 0x5650bc0a
+0,        352,        352,        1,   115200, 0x8b34ecab
+0,        353,        353,        1,   115200, 0x975c4976
+0,        354,        354,        1,   115200, 0x700e3cb4
+0,        355,        355,        1,   115200, 0xef27a4ec
+0,        356,        356,        1,   115200, 0x2b953936
+0,        357,        357,        1,   115200, 0xcf9b4956
+0,        358,        358,        1,   115200, 0xae4a8eba
+0,        359,        359,        1,   115200, 0xf8821144
+0,        360,        360,        1,   115200, 0x97c2402c
+0,        361,        361,        1,   115200, 0x209b7bb3
+0,        362,        362,        1,   115200, 0xd22fff2c
+0,        363,        363,        1,   115200, 0xe85b4f16
+0,        364,        364,        1,   115200, 0x0659f318
+0,        365,        365,        1,   115200, 0x6e2bff98
+0,        366,        366,        1,   115200, 0xc6626f2f
+0,        367,        367,        1,   115200, 0x123138e2
+0,        368,        368,        1,   115200, 0x69e680ab
+0,        369,        369,        1,   115200, 0xe4d7cd1d
+0,        370,        370,        1,   115200, 0x4ca10d47
+0,        371,        371,        1,   115200, 0x633a4c39
+0,        372,        372,        1,   115200, 0x64ded292
+0,        373,        373,        1,   115200, 0x88d2df42
+0,        374,        374,        1,   115200, 0x998f4c63
+0,        375,        375,        1,   115200, 0x753c76f9
+0,        376,        376,        1,   115200, 0x9d7ba0a6
+0,        377,        377,        1,   115200, 0x68798da5
+0,        378,        378,        1,   115200, 0xb5b18bc3
+0,        379,        379,        1,   115200, 0x20245e49
+0,        380,        380,        1,   115200, 0xf15d4b8f
+0,        381,        381,        1,   115200, 0x17f83b69
+0,        382,        382,        1,   115200, 0xcc545783
+0,        383,        383,        1,   115200, 0x3dad530e
+0,        384,        384,        1,   115200, 0x6b465c94
+0,        385,        385,        1,   115200, 0xbc5f3831
+0,        386,        386,        1,   115200, 0x1b2f042d
+0,        387,        387,        1,   115200, 0xaec391ac
+0,        388,        388,        1,   115200, 0x99fa8b2a
+0,        389,        389,        1,   115200, 0xf78d3524
+0,        390,        390,        1,   115200, 0xe6255a24
+0,        391,        391,        1,   115200, 0x253542c6
+0,        392,        392,        1,   115200, 0xfab05365
+0,        393,        393,        1,   115200, 0x406a3749
+0,        394,        394,        1,   115200, 0xaf0f3935
+0,        395,        395,        1,   115200, 0x0d9ff780
+0,        396,        396,        1,   115200, 0xfadcfc15
+0,        397,        397,        1,   115200, 0x8267d5ad
+0,        398,        398,        1,   115200, 0xd705d250
+0,        399,        399,        1,   115200, 0x18f9d1f2
+0,        400,        400,        1,   115200, 0xd92bc045
+0,        401,        401,        1,   115200, 0x439b9ca0
+0,        402,        402,        1,   115200, 0xcb80a14c
+0,        403,        403,        1,   115200, 0xee887f49
+0,        404,        404,        1,   115200, 0xfba297eb
+0,        405,        405,        1,   115200, 0x0e2f744b
+0,        406,        406,        1,   115200, 0xaa227aa7
+0,        407,        407,        1,   115200, 0xd7bc6fff
+0,        408,        408,        1,   115200, 0x295c91cf
+0,        409,        409,        1,   115200, 0xc5678733
+0,        410,        410,        1,   115200, 0xc8d49120
+0,        411,        411,        1,   115200, 0xb14e90b9
+0,        412,        412,        1,   115200, 0x6a09acab
+0,        413,        413,        1,   115200, 0xb9aec358
+0,        414,        414,        1,   115200, 0xeb3695b2
+0,        415,        415,        1,   115200, 0xc5bebd62
+0,        416,        416,        1,   115200, 0x2d6b1a3f
+0,        417,        417,        1,   115200, 0x92986f49
+0,        418,        418,        1,   115200, 0x00c37cf9
+0,        419,        419,        1,   115200, 0x5a4d87a6
+0,        420,        420,        1,   115200, 0xe87888a2
+0,        421,        421,        1,   115200, 0x4ab18d6d
+0,        422,        422,        1,   115200, 0xcb84880b
+0,        423,        423,        1,   115200, 0x82458848
+0,        424,        424,        1,   115200, 0x11b477dc
+0,        425,        425,        1,   115200, 0x56d876d3
+0,        426,        426,        1,   115200, 0xf5297ceb
+0,        427,        427,        1,   115200, 0x47357713
+0,        428,        428,        1,   115200, 0xede562df
+0,        429,        429,        1,   115200, 0xabf42d38
+0,        430,        430,        1,   115200, 0xea9225c8
+0,        431,        431,        1,   115200, 0x79ce1cb4
+0,        432,        432,        1,   115200, 0x0cd418b4
+0,        433,        433,        1,   115200, 0x6f7c118e
+0,        434,        434,        1,   115200, 0xbbbc0fa4
+0,        435,        435,        1,   115200, 0x890514e6
+0,        436,        436,        1,   115200, 0x9c4d0e7d
+0,        437,        437,        1,   115200, 0x56260e76
+0,        438,        438,        1,   115200, 0x7dc80258
+0,        439,        439,        1,   115200, 0xa990f5a3
+0,        440,        440,        1,   115200, 0x2174e913
+0,        441,        441,        1,   115200, 0x8296e674
+0,        442,        442,        1,   115200, 0x9e28e3b4
+0,        443,        443,        1,   115200, 0x404ce72b
+0,        444,        444,        1,   115200, 0xc7cbf4ec
+0,        445,        445,        1,   115200, 0x5ce0f5a1
+0,        446,        446,        1,   115200, 0x88dbf7c7
+0,        447,        447,        1,   115200, 0x26daf35a
+0,        448,        448,        1,   115200, 0x5cfdfe63
+0,        449,        449,        1,   115200, 0xdd40fb9b
+0,        450,        450,        1,   115200, 0x5b8df20f
+0,        451,        451,        1,   115200, 0x4f2ce5ac
+0,        452,        452,        1,   115200, 0xc9d0e0c2
+0,        453,        453,        1,   115200, 0x51c7e2a6
+0,        454,        454,        1,   115200, 0xb3bae109
+0,        455,        455,        1,   115200, 0xbd85e5b2
+0,        456,        456,        1,   115200, 0x1fbbdfd1
+0,        457,        457,        1,   115200, 0x3665dfd0
+0,        458,        458,        1,   115200, 0xcd29d50c
 0,        459,        459,        1,   115200, 0xedd1c6bc
-0,        460,        460,        1,   115200, 0x2913d073
-0,        461,        461,        1,   115200, 0xf196fbbe
-0,        462,        462,        1,   115200, 0xc0be13e1
-0,        463,        463,        1,   115200, 0x55b21f01
-0,        464,        464,        1,   115200, 0xb16b2364
-0,        465,        465,        1,   115200, 0x4a8632db
-0,        466,        466,        1,   115200, 0x44c94426
-0,        467,        467,        1,   115200, 0xe5470b01
-0,        468,        468,        1,   115200, 0xd895d5d0
-0,        469,        469,        1,   115200, 0xe98715c2
-0,        470,        470,        1,   115200, 0x2688599b
-0,        471,        471,        1,   115200, 0x8e4889aa
-0,        472,        472,        1,   115200, 0x658bcd8d
-0,        473,        473,        1,   115200, 0xf0090c06
-0,        474,        474,        1,   115200, 0xefd9bd28
-0,        475,        475,        1,   115200, 0x45009bb4
-0,        476,        476,        1,   115200, 0x7ebd1655
-0,        477,        477,        1,   115200, 0x64ff7898
-0,        478,        478,        1,   115200, 0x4a9384f1
-0,        479,        479,        1,   115200, 0xd80f0701
-0,        480,        480,        1,   115200, 0x2f855116
-0,        481,        481,        1,   115200, 0x0c1313cb
-0,        482,        482,        1,   115200, 0xf4df4d19
-0,        483,        483,        1,   115200, 0xde6218fb
-0,        484,        484,        1,   115200, 0xce26e6b4
-0,        485,        485,        1,   115200, 0x848af931
-0,        486,        486,        1,   115200, 0x86770a97
+0,        460,        460,        1,   115200, 0xebc2d072
+0,        461,        461,        1,   115200, 0xe2e5fbbd
+0,        462,        462,        1,   115200, 0x616a13dc
+0,        463,        463,        1,   115200, 0xf64f1efc
+0,        464,        464,        1,   115200, 0x5356235f
+0,        465,        465,        1,   115200, 0xafc032d5
+0,        466,        466,        1,   115200, 0xaa034420
+0,        467,        467,        1,   115200, 0x007e0afa
+0,        468,        468,        1,   115200, 0x077ad5c8
+0,        469,        469,        1,   115200, 0x8fc815b8
+0,        470,        470,        1,   115200, 0x95b85990
+0,        471,        471,        1,   115200, 0x46f5899f
+0,        472,        472,        1,   115200, 0x1e37cd82
+0,        473,        473,        1,   115200, 0x3ce90bfd
+0,        474,        474,        1,   115200, 0xbb95bd1d
+0,        475,        475,        1,   115200, 0xd4aa9ba8
+0,        476,        476,        1,   115200, 0x0e761649
+0,        477,        477,        1,   115200, 0x49ad7886
+0,        478,        478,        1,   115200, 0x2f4184df
+0,        479,        479,        1,   115200, 0x80b906ee
+0,        480,        480,        1,   115200, 0x62405100
+0,        481,        481,        1,   115200, 0x3ece13b5
+0,        482,        482,        1,   115200, 0x3abd4cfc
+0,        483,        483,        1,   115200, 0x91b418e3
+0,        484,        484,        1,   115200, 0xde1ce68e
+0,        485,        485,        1,   115200, 0xfc47f912
+0,        486,        486,        1,   115200, 0x5b380a6f
 0,        487,        487,        1,   115200, 0x8f35c3c0
 0,        488,        488,        1,   115200, 0xb26dc220
 0,        489,        489,        1,   115200, 0x3d5bbfce
@@ -472,3 +476,4 @@
 0,        496,        496,        1,   115200, 0xb5b8b866
 0,        497,        497,        1,   115200, 0xafcc1019
 0,        510,        510,        1,   115200, 0x623b0ff3
+0,        512,        512,        1,   115200, 0x1d6f10b5
diff --git a/tests/ref/fate/wnv1 b/tests/ref/fate/wnv1
index 4de35bf..5d48aed 100644
--- a/tests/ref/fate/wnv1
+++ b/tests/ref/fate/wnv1
@@ -1,4 +1,8 @@
 #tb 0: 13333/200000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 160x120
+#sar 0: 0/1
 0,          0,          0,        1,    38400, 0x4c3fdc2f
 0,          1,          1,        1,    38400, 0x11c9d0cb
 0,          2,          2,        1,    38400, 0x6c37fd7f
diff --git a/tests/ref/fate/wtv-demux b/tests/ref/fate/wtv-demux
index 904d78b..306fe00 100644
--- a/tests/ref/fate/wtv-demux
+++ b/tests/ref/fate/wtv-demux
@@ -1,7 +1,15 @@
 #extradata 0:       86, 0xc7ca09e5
 #extradata 1:       22, 0x12dc010c
 #tb 0: 1/10000000
+#media_type 0: video
+#codec_id 0: mpeg2video
+#dimensions 0: 720x576
+#sar 0: 64/45
 #tb 1: 1/10000000
+#media_type 1: audio
+#codec_id 1: mp2
+#sample_rate 1: 48000
+#channel_layout 1: 3
 1,         -2,         -2,   240000,      576, 0x9b6e1638
 1,     239998,     239998,   240000,      576, 0x0ca91183
 1,     479998,     479998,   240000,      576, 0xec6a180f
diff --git a/tests/ref/fate/xbm10 b/tests/ref/fate/xbm10
index 0038891..57a70d2 100644
--- a/tests/ref/fate/xbm10
+++ b/tests/ref/fate/xbm10
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 16x16
+#sar 0: 0/1
 0,          0,          0,        1,       32, 0x777f0737
diff --git a/tests/ref/fate/xbm11 b/tests/ref/fate/xbm11
index 77192b3..8385281 100644
--- a/tests/ref/fate/xbm11
+++ b/tests/ref/fate/xbm11
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 200x190
+#sar 0: 0/1
 0,          0,          0,        1,     4750, 0xc85f0b6d
diff --git a/tests/ref/fate/xface b/tests/ref/fate/xface
index 7f1f1e6..05a955c 100644
--- a/tests/ref/fate/xface
+++ b/tests/ref/fate/xface
@@ -1,2 +1,6 @@
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 48x48
+#sar 0: 0/1
 0,          0,          0,        1,      288, 0x87ddaef8
diff --git a/tests/ref/fate/xmv-demux b/tests/ref/fate/xmv-demux
index d13270a..5840129 100644
--- a/tests/ref/fate/xmv-demux
+++ b/tests/ref/fate/xmv-demux
@@ -1,6 +1,14 @@
 #extradata 0:        4, 0x015a00ad
 #tb 0: 1/1000
+#media_type 0: video
+#codec_id 0: wmv2
+#dimensions 0: 640x480
+#sar 0: 0/1
 #tb 1: 16/11025
+#media_type 1: audio
+#codec_id 1: adpcm_ima_wav
+#sample_rate 1: 44100
+#channel_layout 1: 3
 0,          0,          0,        0,     1508, 0xefceba48
 1,          0,          0,       83,     5976, 0xfa2c2db9
 1,         83,         83,       83,     5976, 0x256b935c
@@ -84,33 +92,33 @@
 0,       4640,       4640,        0,      100, 0x45023894, F=0x0
 0,       4680,       4680,        0,      948, 0xa65ed345, F=0x0
 0,       4720,       4720,        0,     2808, 0xd7285746, F=0x0
-0,       4760,       4760,       40,     5372, 0x05794175, F=0x0
+0,       4760,       4760,        0,     5372, 0x05794175, F=0x0
 1,       3307,       3307,       21,     1512, 0xed8b3f4b
-0,       4800,       4800,       40,    11596, 0x8636eca7, F=0x0
+0,       4800,       4800,        0,    11596, 0x8636eca7, F=0x0
 1,       3328,       3328,       21,     1512, 0xa27d3891
-0,       4840,       4840,       40,    11524, 0xe1f39be3, F=0x0
+0,       4840,       4840,        0,    11524, 0xe1f39be3, F=0x0
 1,       3349,       3349,       21,     1512, 0xb0f13eb6
-0,       4880,       4880,       40,    23392, 0xab053f05, F=0x0
+0,       4880,       4880,        0,    23392, 0xab053f05, F=0x0
 1,       3370,       3370,       23,     1656, 0xe5a98324
-0,       4920,       4920,       40,     4560, 0x03197d07, F=0x0
+0,       4920,       4920,        0,     4560, 0x03197d07, F=0x0
 1,       3393,       3393,       31,     2232, 0x15445433
-0,       4960,       4960,       40,     4440, 0x1cc361a2, F=0x0
+0,       4960,       4960,        0,     4440, 0x1cc361a2, F=0x0
 1,       3424,       3424,       31,     2232, 0x5cb348a9
-0,       5000,       5000,       40,    23688, 0x16030634, F=0x0
+0,       5000,       5000,        0,    23688, 0x16030634, F=0x0
 1,       3455,       3455,       31,     2232, 0xf10347da
-0,       5040,       5040,       40,    16132, 0xf0eca799, F=0x0
+0,       5040,       5040,        0,    16132, 0xf0eca799, F=0x0
 1,       3486,       3486,       34,     2448, 0x3e16a175
-0,       5080,       5080,       40,    29896, 0x0c0988ea, F=0x0
+0,       5080,       5080,        0,    29896, 0x0c0988ea, F=0x0
 1,       3520,       3520,       35,     2520, 0x17e3ca2b
-0,       5120,       5120,       40,    19956, 0x0093aa0b, F=0x0
+0,       5120,       5120,        0,    19956, 0x0093aa0b, F=0x0
 1,       3555,       3555,       27,     1944, 0x35c2de84
-0,       5160,       5160,       40,    16392, 0x8829a9ca, F=0x0
+0,       5160,       5160,        0,    16392, 0x8829a9ca, F=0x0
 1,       3582,       3582,       27,     1944, 0x55b4db40
-0,       5200,       5200,       40,    16772, 0x9a4a546d, F=0x0
+0,       5200,       5200,        0,    16772, 0x9a4a546d, F=0x0
 1,       3609,       3609,       29,     2088, 0xdaae14b2
-0,       5240,       5240,       40,     8920, 0xcd8ca203, F=0x0
+0,       5240,       5240,        0,     8920, 0xcd8ca203, F=0x0
 1,       3638,       3638,       27,     1944, 0x92ccd37f
-0,       5280,       5280,       40,     9632, 0x53c1d37b, F=0x0
+0,       5280,       5280,        0,     9632, 0x53c1d37b, F=0x0
 1,       3665,       3665,       27,     1944, 0x70efede1
 0,       5320,       5320,       40,     8976, 0xfe4da2cc, F=0x0
 1,       3692,       3692,       27,     1944, 0x7601d304
diff --git a/tests/ref/fate/xvid-custom-matrix b/tests/ref/fate/xvid-custom-matrix
index c00a24b..32f629f 100644
--- a/tests/ref/fate/xvid-custom-matrix
+++ b/tests/ref/fate/xvid-custom-matrix
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/11
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   622080, 870e846b6b001d3e34fa87df96297e28
 0,          1,          1,        1,   622080, de1a3dd9fcc32086ecdffd4591a8defa
diff --git a/tests/ref/fate/xvid-idct b/tests/ref/fate/xvid-idct
index 2fc93ee..cdbba2f 100644
--- a/tests/ref/fate/xvid-idct
+++ b/tests/ref/fate/xvid-idct
@@ -1,7 +1,11 @@
 #format: frame checksums
-#version: 1
+#version: 2
 #hash: MD5
 #tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 720x576
+#sar 0: 16/11
 #stream#, dts,        pts, duration,     size, hash
 0,          0,          0,        1,   622080, 8fe318df973b5d7669e6d28ebf03b229
 0,          1,          1,        1,   622080, 3568d92074e0298a2027f990004fe1a6
diff --git a/tests/ref/fate/xxan-wc4 b/tests/ref/fate/xxan-wc4
index 88dcc98..ae3bda3 100644
--- a/tests/ref/fate/xxan-wc4
+++ b/tests/ref/fate/xxan-wc4
@@ -1,4 +1,8 @@
 #tb 0: 1/15
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x165
+#sar 0: 0/1
 0,          0,          0,        1,    79360, 0x8537821b
 0,          1,          1,        1,    79360, 0x110c4343
 0,          2,          2,        1,    79360, 0xa85105bb
diff --git a/tests/ref/fate/yop b/tests/ref/fate/yop
index 1920281..9d615b1 100644
--- a/tests/ref/fate/yop
+++ b/tests/ref/fate/yop
@@ -1,4 +1,8 @@
 #tb 0: 1/12
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 580x174
+#sar 0: 1/2
 0,          0,          0,        1,   302760, 0xf24dfa37
 0,          1,          1,        1,   302760, 0xcedcbb6c
 0,          2,          2,        1,   302760, 0xc87716a2
diff --git a/tests/ref/fate/zerocodec b/tests/ref/fate/zerocodec
index 2d368c3..10f9d4c 100644
--- a/tests/ref/fate/zerocodec
+++ b/tests/ref/fate/zerocodec
@@ -1,4 +1,8 @@
 #tb 0: 417083/10000000
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1280x720
+#sar 0: 0/1
 0,          0,          0,        1,  1843200, 0x04154bd5
 0,          1,          1,        1,  1843200, 0x3a872d04
 0,          2,          2,        1,  1843200, 0x3b1304a0
diff --git a/tests/ref/fate/zlib b/tests/ref/fate/zlib
index 4ff76ff..007fe00 100644
--- a/tests/ref/fate/zlib
+++ b/tests/ref/fate/zlib
@@ -1,2 +1,6 @@
 #tb 0: 100/2997
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 352x240
+#sar 0: 0/1
 0,          0,          0,        1,   253440, 0x94af61e5
diff --git a/tests/ref/fate/zmbv-15bit b/tests/ref/fate/zmbv-15bit
index 384bb65..d3bee30 100644
--- a/tests/ref/fate/zmbv-15bit
+++ b/tests/ref/fate/zmbv-15bit
@@ -1,4 +1,8 @@
 #tb 0: 250000/1585341
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x8f9020f2
 0,          1,          1,        1,   192000, 0xbfba7f63
 0,          2,          2,        1,   192000, 0x96b48d11
diff --git a/tests/ref/fate/zmbv-16bit b/tests/ref/fate/zmbv-16bit
index cb39014..d650e08 100644
--- a/tests/ref/fate/zmbv-16bit
+++ b/tests/ref/fate/zmbv-16bit
@@ -1,4 +1,8 @@
 #tb 0: 250000/1585341
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0xe869dc94
 0,          1,          1,        1,   192000, 0x742932f2
 0,          2,          2,        1,   192000, 0x742932f2
diff --git a/tests/ref/fate/zmbv-32bit b/tests/ref/fate/zmbv-32bit
index e1df123..ff4d69f 100644
--- a/tests/ref/fate/zmbv-32bit
+++ b/tests/ref/fate/zmbv-32bit
@@ -1,4 +1,8 @@
 #tb 0: 250000/1585341
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x3ac10e8e
 0,          1,          1,        1,   192000, 0xb772ee57
 0,          2,          2,        1,   192000, 0x9b6e648a
diff --git a/tests/ref/fate/zmbv-8bit b/tests/ref/fate/zmbv-8bit
index 9f02ae3..7c2fab6 100644
--- a/tests/ref/fate/zmbv-8bit
+++ b/tests/ref/fate/zmbv-8bit
@@ -1,4 +1,8 @@
 #tb 0: 1000000/70086303
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 320x200
+#sar 0: 0/1
 0,          0,          0,        1,   192000, 0x5234b617
 0,          1,          1,        1,   192000, 0x5234b617
 0,          2,          2,        1,   192000, 0x5234b617
diff --git a/tests/ref/lavf-fate/avi_cram b/tests/ref/lavf-fate/avi_cram
new file mode 100644
index 0000000..82882fb
--- /dev/null
+++ b/tests/ref/lavf-fate/avi_cram
@@ -0,0 +1,3 @@
+6fc88702c23b895c305c5e1f51a0904e *./tests/data/lavf-fate/lavf.avi
+928260 ./tests/data/lavf-fate/lavf.avi
+./tests/data/lavf-fate/lavf.avi CRC=0xa4770de2
diff --git a/tests/ref/lavf-fate/mov_qtrle_mace6 b/tests/ref/lavf-fate/mov_qtrle_mace6
new file mode 100644
index 0000000..b6ecea5
--- /dev/null
+++ b/tests/ref/lavf-fate/mov_qtrle_mace6
@@ -0,0 +1,3 @@
+db3e70328340fcb3cd0e06c215fadaa3 *./tests/data/lavf-fate/lavf.mov
+1270387 ./tests/data/lavf-fate/lavf.mov
+./tests/data/lavf-fate/lavf.mov CRC=0x5ec66f68
diff --git a/tests/ref/lavf/au b/tests/ref/lavf/au
index ede4926..dcd02f3 100644
--- a/tests/ref/lavf/au
+++ b/tests/ref/lavf/au
@@ -1,3 +1,3 @@
-aa5ec1f82ac07c653ffc527b0f0dc10d *./tests/data/lavf/lavf.au
-88232 ./tests/data/lavf/lavf.au
+5228ad3783888c45a08dac5ab6118794 *./tests/data/lavf/lavf.au
+88240 ./tests/data/lavf/lavf.au
 ./tests/data/lavf/lavf.au CRC=0x3a1da17e
diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv
index 39a48d8..72fc291 100644
--- a/tests/ref/lavf/mkv
+++ b/tests/ref/lavf/mkv
@@ -1,6 +1,6 @@
-7c6509f597fb57bab002cbceec960011 *./tests/data/lavf/lavf.mkv
-472872 ./tests/data/lavf/lavf.mkv
+c081514c38735524ab09dbd2a498b7b3 *./tests/data/lavf/lavf.mkv
+472875 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
-5f8cb4b7e98610347dd8d0d58a828a0f *./tests/data/lavf/lavf.mkv
-320548 ./tests/data/lavf/lavf.mkv
+d1fc3a31150d00aebbd674862640f701 *./tests/data/lavf/lavf.mkv
+320551 ./tests/data/lavf/lavf.mkv
 ./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
diff --git a/tests/ref/lavf/mov b/tests/ref/lavf/mov
index 72d962a..2e1f24d 100644
--- a/tests/ref/lavf/mov
+++ b/tests/ref/lavf/mov
@@ -10,3 +10,12 @@ ba3b8b49e420510a0d417400dbedfc2d *./tests/data/lavf/lavf.mov
 fd0e4de8e7f6d0c8c0681d7020f00f50 *./tests/data/lavf/lavf.mov
 356921 ./tests/data/lavf/lavf.mov
 ./tests/data/lavf/lavf.mov CRC=0xbb2b949b
+ebca72c186a4f3ba9bb17d9cb5b74fef *./tests/data/lavf/lavf.mp4
+312457 ./tests/data/lavf/lavf.mp4
+./tests/data/lavf/lavf.mp4 CRC=0x9d9a638a
+9944512475d82d2d601f3c96101bdf9c *./tests/data/lavf/lavf.mp4
+321343 ./tests/data/lavf/lavf.mp4
+./tests/data/lavf/lavf.mp4 CRC=0xe8130120
+7b3e71f294901067046c09f03a426bdc *./tests/data/lavf/lavf.mp4
+312001 ./tests/data/lavf/lavf.mp4
+./tests/data/lavf/lavf.mp4 CRC=0x9d9a638a
diff --git a/tests/ref/lavf/ts b/tests/ref/lavf/ts
index 1381f09..2be3526 100644
--- a/tests/ref/lavf/ts
+++ b/tests/ref/lavf/ts
@@ -1,3 +1,3 @@
-cca6bca512605bbde20b7aa5cccf4850 *./tests/data/lavf/lavf.ts
+38f4b14d43a0e416be8d598628997cbc *./tests/data/lavf/lavf.ts
 407020 ./tests/data/lavf/lavf.ts
 ./tests/data/lavf/lavf.ts CRC=0x71287e25
diff --git a/tests/ref/seek/cache-pipe b/tests/ref/seek/cache-pipe
new file mode 100644
index 0000000..b6a42e8
--- /dev/null
+++ b/tests/ref/seek/cache-pipe
@@ -0,0 +1,49 @@
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   1451 size:   440
+ret: 0         st:-1 flags:0  ts:-1.000000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   1451 size:   440
+ret: 0         st:-1 flags:1  ts: 1.894167
+ret: 0         st: 0 flags:1 dts: 1.880816 pts: 1.880816 pos:  31544 size:   418
+ret: 0         st: 0 flags:0  ts: 0.788334
+ret: 0         st: 0 flags:1 dts: 0.809796 pts: 0.809796 pos:  14407 size:   418
+ret:-1         st: 0 flags:1  ts:-0.317499
+ret: 0         st:-1 flags:0  ts: 2.576668
+ret: 0         st: 0 flags:1 dts: 2.586122 pts: 2.586122 pos:  42828 size:   418
+ret: 0         st:-1 flags:1  ts: 1.470835
+ret: 0         st: 0 flags:1 dts: 1.462857 pts: 1.462857 pos:  24856 size:   418
+ret: 0         st: 0 flags:0  ts: 0.365002
+ret: 0         st: 0 flags:1 dts: 0.365714 pts: 0.365714 pos:   7302 size:   418
+ret:-1         st: 0 flags:1  ts:-0.740831
+ret: 0         st:-1 flags:0  ts: 2.153336
+ret: 0         st: 0 flags:1 dts: 2.168163 pts: 2.168163 pos:  36141 size:   418
+ret: 0         st:-1 flags:1  ts: 1.047503
+ret: 0         st: 0 flags:1 dts: 1.044898 pts: 1.044898 pos:  18169 size:   418
+ret: 0         st: 0 flags:0  ts:-0.058330
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   1451 size:   440
+ret: 0         st: 0 flags:1  ts: 2.835837
+ret: 0         st: 0 flags:1 dts: 2.821224 pts: 2.821224 pos:  46590 size:   418
+ret: 0         st:-1 flags:0  ts: 1.730004
+ret: 0         st: 0 flags:1 dts: 1.750204 pts: 1.750204 pos:  29454 size:   418
+ret: 0         st:-1 flags:1  ts: 0.624171
+ret: 0         st: 0 flags:1 dts: 0.600816 pts: 0.600816 pos:  11064 size:   418
+ret: 0         st: 0 flags:0  ts:-0.481662
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   1451 size:   440
+ret: 0         st: 0 flags:1  ts: 2.412505
+ret: 0         st: 0 flags:1 dts: 2.403265 pts: 2.403265 pos:  39903 size:   418
+ret: 0         st:-1 flags:0  ts: 1.306672
+ret: 0         st: 0 flags:1 dts: 1.332245 pts: 1.332245 pos:  22766 size:   418
+ret: 0         st:-1 flags:1  ts: 0.200839
+ret: 0         st: 0 flags:1 dts: 0.182857 pts: 0.182857 pos:   4376 size:   418
+ret: 0         st: 0 flags:0  ts:-0.904994
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   1451 size:   440
+ret: 0         st: 0 flags:1  ts: 1.989173
+ret: 0         st: 0 flags:1 dts: 1.985306 pts: 1.985306 pos:  33215 size:   418
+ret: 0         st:-1 flags:0  ts: 0.883340
+ret: 0         st: 0 flags:1 dts: 0.888163 pts: 0.888163 pos:  15661 size:   418
+ret:-1         st:-1 flags:1  ts:-0.222493
+ret: 0         st: 0 flags:0  ts: 2.671674
+ret: 0         st: 0 flags:1 dts: 2.690612 pts: 2.690612 pos:  44500 size:   418
+ret: 0         st: 0 flags:1  ts: 1.565841
+ret: 0         st: 0 flags:1 dts: 1.541224 pts: 1.541224 pos:  26110 size:   418
+ret: 0         st:-1 flags:0  ts: 0.460008
+ret: 0         st: 0 flags:1 dts: 0.470204 pts: 0.470204 pos:   8974 size:   418
+ret:-1         st:-1 flags:1  ts:-0.645825
diff --git a/tests/ref/seek/lavf-au b/tests/ref/seek/lavf-au
index d5a70b2..8edce58 100644
--- a/tests/ref/seek/lavf-au
+++ b/tests/ref/seek/lavf-au
@@ -1,53 +1,53 @@
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     40 size:  2048
 ret: 0         st:-1 flags:0  ts:-1.000000
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     40 size:  2048
 ret: 0         st:-1 flags:1  ts: 1.894167
 ret:-EOF
 ret: 0         st: 0 flags:0  ts: 0.788345
-ret: 0         st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos:  69564 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.788345 pts: 0.788345 pos:  69572 size:  2048
 ret: 0         st: 0 flags:1  ts:-0.317506
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     40 size:  2048
 ret: 0         st:-1 flags:0  ts: 2.576668
 ret:-EOF
 ret: 0         st:-1 flags:1  ts: 1.470835
 ret:-EOF
 ret: 0         st: 0 flags:0  ts: 0.365011
-ret: 0         st: 0 flags:1 dts: 0.365011 pts: 0.365011 pos:  32226 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.365011 pts: 0.365011 pos:  32234 size:  2048
 ret: 0         st: 0 flags:1  ts:-0.740839
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     40 size:  2048
 ret: 0         st:-1 flags:0  ts: 2.153336
 ret:-EOF
 ret: 0         st:-1 flags:1  ts: 1.047503
 ret:-EOF
 ret: 0         st: 0 flags:0  ts:-0.058322
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     40 size:  2048
 ret: 0         st: 0 flags:1  ts: 2.835828
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 1.730004
 ret:-EOF
 ret: 0         st:-1 flags:1  ts: 0.624171
-ret: 0         st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos:  55084 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.624172 pts: 0.624172 pos:  55092 size:  2048
 ret: 0         st: 0 flags:0  ts:-0.481655
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     40 size:  2048
 ret: 0         st: 0 flags:1  ts: 2.412494
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 1.306672
 ret:-EOF
 ret: 0         st:-1 flags:1  ts: 0.200839
-ret: 0         st: 0 flags:1 dts: 0.200839 pts: 0.200839 pos:  17746 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.200839 pts: 0.200839 pos:  17754 size:  2048
 ret: 0         st: 0 flags:0  ts:-0.904989
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     40 size:  2048
 ret: 0         st: 0 flags:1  ts: 1.989184
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 0.883340
-ret: 0         st: 0 flags:1 dts: 0.883333 pts: 0.883333 pos:  77942 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.883333 pts: 0.883333 pos:  77950 size:  2048
 ret: 0         st:-1 flags:1  ts:-0.222493
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     40 size:  2048
 ret: 0         st: 0 flags:0  ts: 2.671678
 ret:-EOF
 ret: 0         st: 0 flags:1  ts: 1.565850
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 0.460008
-ret: 0         st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos:  40604 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.460000 pts: 0.460000 pos:  40612 size:  2048
 ret: 0         st:-1 flags:1  ts:-0.645825
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  2048
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     40 size:  2048
diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv
index af13ddb..bf34766 100644
--- a/tests/ref/seek/lavf-mkv
+++ b/tests/ref/seek/lavf-mkv
@@ -1,48 +1,48 @@
-ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    797 size:   208
+ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    800 size:   208
 ret: 0         st:-1 flags:0  ts:-1.000000
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013 size: 27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1016 size: 27837
 ret: 0         st:-1 flags:1  ts: 1.894167
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292430 size: 27834
 ret: 0         st: 0 flags:0  ts: 0.788000
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292430 size: 27834
 ret: 0         st: 0 flags:1  ts:-0.317000
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013 size: 27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1016 size: 27837
 ret:-1         st: 1 flags:0  ts: 2.577000
 ret: 0         st: 1 flags:1  ts: 1.471000
-ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320268 size:   209
+ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320271 size:   209
 ret: 0         st:-1 flags:0  ts: 0.365002
-ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146980 size: 27925
+ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146983 size: 27925
 ret: 0         st:-1 flags:1  ts:-0.740831
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013 size: 27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1016 size: 27837
 ret:-1         st: 0 flags:0  ts: 2.153000
 ret: 0         st: 0 flags:1  ts: 1.048000
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292430 size: 27834
 ret: 0         st: 1 flags:0  ts:-0.058000
-ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    797 size:   208
+ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    800 size:   208
 ret: 0         st: 1 flags:1  ts: 2.836000
-ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320268 size:   209
+ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320271 size:   209
 ret:-1         st:-1 flags:0  ts: 1.730004
 ret: 0         st:-1 flags:1  ts: 0.624171
-ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146980 size: 27925
+ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146983 size: 27925
 ret: 0         st: 0 flags:0  ts:-0.482000
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013 size: 27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1016 size: 27837
 ret: 0         st: 0 flags:1  ts: 2.413000
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292430 size: 27834
 ret:-1         st: 1 flags:0  ts: 1.307000
 ret: 0         st: 1 flags:1  ts: 0.201000
-ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    797 size:   208
+ret: 0         st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos:    800 size:   208
 ret: 0         st:-1 flags:0  ts:-0.904994
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013 size: 27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1016 size: 27837
 ret: 0         st:-1 flags:1  ts: 1.989173
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292430 size: 27834
 ret: 0         st: 0 flags:0  ts: 0.883000
-ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292427 size: 27834
+ret: 0         st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292430 size: 27834
 ret: 0         st: 0 flags:1  ts:-0.222000
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013 size: 27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1016 size: 27837
 ret:-1         st: 1 flags:0  ts: 2.672000
 ret: 0         st: 1 flags:1  ts: 1.566000
-ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320268 size:   209
+ret: 0         st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320271 size:   209
 ret: 0         st:-1 flags:0  ts: 0.460008
-ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146980 size: 27925
+ret: 0         st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146983 size: 27925
 ret: 0         st:-1 flags:1  ts:-0.645825
-ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1013 size: 27837
+ret: 0         st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos:   1016 size: 27837
diff --git a/tests/ref/seek/lavf-pbmpipe b/tests/ref/seek/lavf-pbmpipe
index 25bb68f..2782a9f 100644
--- a/tests/ref/seek/lavf-pbmpipe
+++ b/tests/ref/seek/lavf-pbmpipe
@@ -1,27 +1,31 @@
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     -1 size:317075
-ret:-1         st:-1 flags:0  ts:-1.000000
-ret:-1         st:-1 flags:1  ts: 1.894167
-ret:-1         st: 0 flags:0  ts: 0.800000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size: 12683
+ret: 0         st:-1 flags:0  ts:-1.000000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size: 12683
+ret:-EINVAL    st:-1 flags:1  ts: 1.894167
+ret:-EINVAL    st: 0 flags:0  ts: 0.800000
 ret:-1         st: 0 flags:1  ts:-0.320000
-ret:-1         st:-1 flags:0  ts: 2.576668
-ret:-1         st:-1 flags:1  ts: 1.470835
-ret:-1         st: 0 flags:0  ts: 0.360000
+ret:-EINVAL    st:-1 flags:0  ts: 2.576668
+ret:-EINVAL    st:-1 flags:1  ts: 1.470835
+ret:-EINVAL    st: 0 flags:0  ts: 0.360000
 ret:-1         st: 0 flags:1  ts:-0.760000
-ret:-1         st:-1 flags:0  ts: 2.153336
-ret:-1         st:-1 flags:1  ts: 1.047503
-ret:-1         st: 0 flags:0  ts:-0.040000
-ret:-1         st: 0 flags:1  ts: 2.840000
-ret:-1         st:-1 flags:0  ts: 1.730004
-ret:-1         st:-1 flags:1  ts: 0.624171
-ret:-1         st: 0 flags:0  ts:-0.480000
-ret:-1         st: 0 flags:1  ts: 2.400000
-ret:-1         st:-1 flags:0  ts: 1.306672
-ret:-1         st:-1 flags:1  ts: 0.200839
-ret:-1         st: 0 flags:0  ts:-0.920000
-ret:-1         st: 0 flags:1  ts: 2.000000
-ret:-1         st:-1 flags:0  ts: 0.883340
+ret:-EINVAL    st:-1 flags:0  ts: 2.153336
+ret:-EINVAL    st:-1 flags:1  ts: 1.047503
+ret: 0         st: 0 flags:0  ts:-0.040000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size: 12683
+ret:-EINVAL    st: 0 flags:1  ts: 2.840000
+ret:-EINVAL    st:-1 flags:0  ts: 1.730004
+ret:-EINVAL    st:-1 flags:1  ts: 0.624171
+ret: 0         st: 0 flags:0  ts:-0.480000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size: 12683
+ret:-EINVAL    st: 0 flags:1  ts: 2.400000
+ret:-EINVAL    st:-1 flags:0  ts: 1.306672
+ret:-EINVAL    st:-1 flags:1  ts: 0.200839
+ret: 0         st: 0 flags:0  ts:-0.920000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size: 12683
+ret:-EINVAL    st: 0 flags:1  ts: 2.000000
+ret:-EINVAL    st:-1 flags:0  ts: 0.883340
 ret:-1         st:-1 flags:1  ts:-0.222493
-ret:-1         st: 0 flags:0  ts: 2.680000
-ret:-1         st: 0 flags:1  ts: 1.560000
-ret:-1         st:-1 flags:0  ts: 0.460008
+ret:-EINVAL    st: 0 flags:0  ts: 2.680000
+ret:-EINVAL    st: 0 flags:1  ts: 1.560000
+ret:-EINVAL    st:-1 flags:0  ts: 0.460008
 ret:-1         st:-1 flags:1  ts:-0.645825
diff --git a/tests/ref/seek/lavf-pgmpipe b/tests/ref/seek/lavf-pgmpipe
index 57b4e4a..66415c4 100644
--- a/tests/ref/seek/lavf-pgmpipe
+++ b/tests/ref/seek/lavf-pgmpipe
@@ -1,27 +1,31 @@
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     -1 size:2534775
-ret:-1         st:-1 flags:0  ts:-1.000000
-ret:-1         st:-1 flags:1  ts: 1.894167
-ret:-1         st: 0 flags:0  ts: 0.800000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:101391
+ret: 0         st:-1 flags:0  ts:-1.000000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:101391
+ret:-EINVAL    st:-1 flags:1  ts: 1.894167
+ret:-EINVAL    st: 0 flags:0  ts: 0.800000
 ret:-1         st: 0 flags:1  ts:-0.320000
-ret:-1         st:-1 flags:0  ts: 2.576668
-ret:-1         st:-1 flags:1  ts: 1.470835
-ret:-1         st: 0 flags:0  ts: 0.360000
+ret:-EINVAL    st:-1 flags:0  ts: 2.576668
+ret:-EINVAL    st:-1 flags:1  ts: 1.470835
+ret:-EINVAL    st: 0 flags:0  ts: 0.360000
 ret:-1         st: 0 flags:1  ts:-0.760000
-ret:-1         st:-1 flags:0  ts: 2.153336
-ret:-1         st:-1 flags:1  ts: 1.047503
-ret:-1         st: 0 flags:0  ts:-0.040000
-ret:-1         st: 0 flags:1  ts: 2.840000
-ret:-1         st:-1 flags:0  ts: 1.730004
-ret:-1         st:-1 flags:1  ts: 0.624171
-ret:-1         st: 0 flags:0  ts:-0.480000
-ret:-1         st: 0 flags:1  ts: 2.400000
-ret:-1         st:-1 flags:0  ts: 1.306672
-ret:-1         st:-1 flags:1  ts: 0.200839
-ret:-1         st: 0 flags:0  ts:-0.920000
-ret:-1         st: 0 flags:1  ts: 2.000000
-ret:-1         st:-1 flags:0  ts: 0.883340
+ret:-EINVAL    st:-1 flags:0  ts: 2.153336
+ret:-EINVAL    st:-1 flags:1  ts: 1.047503
+ret: 0         st: 0 flags:0  ts:-0.040000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:101391
+ret:-EINVAL    st: 0 flags:1  ts: 2.840000
+ret:-EINVAL    st:-1 flags:0  ts: 1.730004
+ret:-EINVAL    st:-1 flags:1  ts: 0.624171
+ret: 0         st: 0 flags:0  ts:-0.480000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:101391
+ret:-EINVAL    st: 0 flags:1  ts: 2.400000
+ret:-EINVAL    st:-1 flags:0  ts: 1.306672
+ret:-EINVAL    st:-1 flags:1  ts: 0.200839
+ret: 0         st: 0 flags:0  ts:-0.920000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:101391
+ret:-EINVAL    st: 0 flags:1  ts: 2.000000
+ret:-EINVAL    st:-1 flags:0  ts: 0.883340
 ret:-1         st:-1 flags:1  ts:-0.222493
-ret:-1         st: 0 flags:0  ts: 2.680000
-ret:-1         st: 0 flags:1  ts: 1.560000
-ret:-1         st:-1 flags:0  ts: 0.460008
+ret:-EINVAL    st: 0 flags:0  ts: 2.680000
+ret:-EINVAL    st: 0 flags:1  ts: 1.560000
+ret:-EINVAL    st:-1 flags:0  ts: 0.460008
 ret:-1         st:-1 flags:1  ts:-0.645825
diff --git a/tests/ref/seek/lavf-ppmpipe b/tests/ref/seek/lavf-ppmpipe
index 7087494..29a9425 100644
--- a/tests/ref/seek/lavf-ppmpipe
+++ b/tests/ref/seek/lavf-ppmpipe
@@ -1,27 +1,31 @@
-ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     -1 size:7603575
-ret:-1         st:-1 flags:0  ts:-1.000000
-ret:-1         st:-1 flags:1  ts: 1.894167
-ret:-1         st: 0 flags:0  ts: 0.800000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:304143
+ret: 0         st:-1 flags:0  ts:-1.000000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:304143
+ret:-EINVAL    st:-1 flags:1  ts: 1.894167
+ret:-EINVAL    st: 0 flags:0  ts: 0.800000
 ret:-1         st: 0 flags:1  ts:-0.320000
-ret:-1         st:-1 flags:0  ts: 2.576668
-ret:-1         st:-1 flags:1  ts: 1.470835
-ret:-1         st: 0 flags:0  ts: 0.360000
+ret:-EINVAL    st:-1 flags:0  ts: 2.576668
+ret:-EINVAL    st:-1 flags:1  ts: 1.470835
+ret:-EINVAL    st: 0 flags:0  ts: 0.360000
 ret:-1         st: 0 flags:1  ts:-0.760000
-ret:-1         st:-1 flags:0  ts: 2.153336
-ret:-1         st:-1 flags:1  ts: 1.047503
-ret:-1         st: 0 flags:0  ts:-0.040000
-ret:-1         st: 0 flags:1  ts: 2.840000
-ret:-1         st:-1 flags:0  ts: 1.730004
-ret:-1         st:-1 flags:1  ts: 0.624171
-ret:-1         st: 0 flags:0  ts:-0.480000
-ret:-1         st: 0 flags:1  ts: 2.400000
-ret:-1         st:-1 flags:0  ts: 1.306672
-ret:-1         st:-1 flags:1  ts: 0.200839
-ret:-1         st: 0 flags:0  ts:-0.920000
-ret:-1         st: 0 flags:1  ts: 2.000000
-ret:-1         st:-1 flags:0  ts: 0.883340
+ret:-EINVAL    st:-1 flags:0  ts: 2.153336
+ret:-EINVAL    st:-1 flags:1  ts: 1.047503
+ret: 0         st: 0 flags:0  ts:-0.040000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:304143
+ret:-EINVAL    st: 0 flags:1  ts: 2.840000
+ret:-EINVAL    st:-1 flags:0  ts: 1.730004
+ret:-EINVAL    st:-1 flags:1  ts: 0.624171
+ret: 0         st: 0 flags:0  ts:-0.480000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:304143
+ret:-EINVAL    st: 0 flags:1  ts: 2.400000
+ret:-EINVAL    st:-1 flags:0  ts: 1.306672
+ret:-EINVAL    st:-1 flags:1  ts: 0.200839
+ret: 0         st: 0 flags:0  ts:-0.920000
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:      0 size:304143
+ret:-EINVAL    st: 0 flags:1  ts: 2.000000
+ret:-EINVAL    st:-1 flags:0  ts: 0.883340
 ret:-1         st:-1 flags:1  ts:-0.222493
-ret:-1         st: 0 flags:0  ts: 2.680000
-ret:-1         st: 0 flags:1  ts: 1.560000
-ret:-1         st:-1 flags:0  ts: 0.460008
+ret:-EINVAL    st: 0 flags:0  ts: 2.680000
+ret:-EINVAL    st: 0 flags:1  ts: 1.560000
+ret:-EINVAL    st:-1 flags:0  ts: 0.460008
 ret:-1         st:-1 flags:1  ts:-0.645825
diff --git a/tests/ref/seek/lavf-ts b/tests/ref/seek/lavf-ts
index e57651e..f980824 100644
--- a/tests/ref/seek/lavf-ts
+++ b/tests/ref/seek/lavf-ts
@@ -1,53 +1,53 @@
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st:-1 flags:0  ts:-1.000000
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st:-1 flags:1  ts: 1.894167
-ret: 0         st: 0 flags:1 dts: 1.880000 pts: 1.920000 pos: 189692 size: 24786
+ret: 0         st: 0 flags:1 dts: 1.880000 pts: 1.920000 pos: 189692 size: 24800
 ret: 0         st: 0 flags:0  ts: 0.788333
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st: 0 flags:1  ts:-0.317500
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st: 1 flags:0  ts: 2.576667
-ret: 0         st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size:   209
+ret: 0         st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size:   223
 ret: 0         st: 1 flags:1  ts: 1.470833
-ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   208
+ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   222
 ret: 0         st:-1 flags:0  ts: 0.365002
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st:-1 flags:1  ts:-0.740831
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st: 0 flags:0  ts: 2.153333
-ret: 0         st: 1 flags:1 dts: 1.794811 pts: 1.794811 pos: 322608 size:   209
+ret: 0         st: 1 flags:1 dts: 1.794811 pts: 1.794811 pos: 322608 size:   223
 ret: 0         st: 0 flags:1  ts: 1.047500
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st: 1 flags:0  ts:-0.058333
-ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   208
+ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   222
 ret: 0         st: 1 flags:1  ts: 2.835833
-ret: 0         st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size:   209
+ret: 0         st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size:   223
 ret: 0         st:-1 flags:0  ts: 1.730004
-ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   208
+ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   222
 ret: 0         st:-1 flags:1  ts: 0.624171
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st: 0 flags:0  ts:-0.481667
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st: 0 flags:1  ts: 2.412500
-ret: 0         st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size:   209
+ret: 0         st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size:   223
 ret: 0         st: 1 flags:0  ts: 1.306667
-ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   208
+ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   222
 ret: 0         st: 1 flags:1  ts: 0.200844
-ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   208
+ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   222
 ret: 0         st:-1 flags:0  ts:-0.904994
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st:-1 flags:1  ts: 1.989173
-ret: 0         st: 0 flags:0 dts: 1.960000 pts: 2.000000 pos: 235000 size: 15019
+ret: 0         st: 0 flags:0 dts: 1.960000 pts: 2.000000 pos: 235000 size: 15033
 ret: 0         st: 0 flags:0  ts: 0.883344
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st: 0 flags:1  ts:-0.222489
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st: 1 flags:0  ts: 2.671678
-ret: 0         st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size:   209
+ret: 0         st: 1 flags:1 dts: 2.160522 pts: 2.160522 pos: 404576 size:   223
 ret: 0         st: 1 flags:1  ts: 1.565844
-ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   208
+ret: 0         st: 1 flags:1 dts: 1.429089 pts: 1.429089 pos: 159988 size:   222
 ret: 0         st:-1 flags:0  ts: 0.460008
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
 ret: 0         st:-1 flags:1  ts:-0.645825
-ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24801
+ret: 0         st: 0 flags:1 dts: 1.400000 pts: 1.440000 pos:    564 size: 24815
diff --git a/tests/ref/seek/lavf-voc b/tests/ref/seek/lavf-voc
index 483c782..014c251 100644
--- a/tests/ref/seek/lavf-voc
+++ b/tests/ref/seek/lavf-voc
@@ -4,13 +4,13 @@ ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  1024
 ret: 0         st:-1 flags:1  ts: 1.894167
 ret:-EOF
 ret: 0         st: 0 flags:0  ts: 0.788330
-ret: 0         st: 0 flags:1 dts: 0.800773 pts: 0.800773 pos:  33956 size:  1024
+ret: 0         st: 0 flags:1 dts: 0.800773 pts: 0.800773 pos:  34984 size:  1024
 ret:-1         st: 0 flags:1  ts:-0.317494
 ret:-1         st:-1 flags:0  ts: 2.576668
 ret: 0         st:-1 flags:1  ts: 1.470835
 ret:-EOF
 ret: 0         st: 0 flags:0  ts: 0.365012
-ret: 0         st: 0 flags:1 dts: 0.376834 pts: 0.376834 pos:  15452 size:  1024
+ret: 0         st: 0 flags:1 dts: 0.376834 pts: 0.376834 pos:  16480 size:  1024
 ret:-1         st: 0 flags:1  ts:-0.740834
 ret:-1         st:-1 flags:0  ts: 2.153336
 ret: 0         st:-1 flags:1  ts: 1.047503
@@ -21,24 +21,24 @@ ret: 0         st: 0 flags:1  ts: 2.835848
 ret:-EOF
 ret:-1         st:-1 flags:0  ts: 1.730004
 ret: 0         st:-1 flags:1  ts: 0.624171
-ret: 0         st: 0 flags:1 dts: 0.612356 pts: 0.612356 pos:  25732 size:  1024
+ret: 0         st: 0 flags:1 dts: 0.612356 pts: 0.612356 pos:  26760 size:  1024
 ret: 0         st: 0 flags:0  ts:-0.481669
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  1024
 ret: 0         st: 0 flags:1  ts: 2.412507
 ret:-EOF
 ret:-1         st:-1 flags:0  ts: 1.306672
 ret: 0         st:-1 flags:1  ts: 0.200839
-ret: 0         st: 0 flags:1 dts: 0.188417 pts: 0.188417 pos:   7228 size:  1024
+ret: 0         st: 0 flags:1 dts: 0.188417 pts: 0.188417 pos:   8256 size:  1024
 ret: 0         st: 0 flags:0  ts:-0.904986
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     32 size:  1024
 ret: 0         st: 0 flags:1  ts: 1.989167
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 0.883340
-ret: 0         st: 0 flags:1 dts: 0.894981 pts: 0.894981 pos:  38068 size:  1024
+ret: 0         st: 0 flags:1 dts: 0.894981 pts: 0.894981 pos:  39096 size:  1024
 ret:-1         st:-1 flags:1  ts:-0.222493
 ret:-1         st: 0 flags:0  ts: 2.671673
 ret: 0         st: 0 flags:1  ts: 1.565849
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 0.460008
-ret: 0         st: 0 flags:1 dts: 0.471043 pts: 0.471043 pos:  19564 size:  1024
+ret: 0         st: 0 flags:1 dts: 0.471043 pts: 0.471043 pos:  20592 size:  1024
 ret:-1         st:-1 flags:1  ts:-0.645825
diff --git a/tests/ref/seek/lavf-yuv4mpeg b/tests/ref/seek/lavf-yuv4mpeg
index 60c3036..6be9ba9 100644
--- a/tests/ref/seek/lavf-yuv4mpeg
+++ b/tests/ref/seek/lavf-yuv4mpeg
@@ -1,53 +1,45 @@
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:     64 size:152064
-ret: 0         st:-1 flags:0  ts:-1.000000
-ret: 0         st: 0 flags:1 dts: 0.040000 pts: 0.040000 pos: 152134 size:152064
+ret:-1         st:-1 flags:0  ts:-1.000000
 ret: 0         st:-1 flags:1  ts: 1.894167
 ret:-EOF
 ret: 0         st: 0 flags:0  ts: 0.800000
 ret: 0         st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:3041464 size:152064
-ret: 0         st: 0 flags:1  ts:-0.320000
-ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.840000 pos:3193534 size:152064
+ret:-1         st: 0 flags:1  ts:-0.320000
 ret: 0         st:-1 flags:0  ts: 2.576668
 ret:-EOF
 ret: 0         st:-1 flags:1  ts: 1.470835
 ret:-EOF
 ret: 0         st: 0 flags:0  ts: 0.360000
 ret: 0         st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1368694 size:152064
-ret: 0         st: 0 flags:1  ts:-0.760000
-ret: 0         st: 0 flags:1 dts: 0.400000 pts: 0.400000 pos:1520764 size:152064
+ret:-1         st: 0 flags:1  ts:-0.760000
 ret: 0         st:-1 flags:0  ts: 2.153336
 ret:-EOF
 ret: 0         st:-1 flags:1  ts: 1.047503
 ret:-EOF
-ret: 0         st: 0 flags:0  ts:-0.040000
-ret:-EOF
+ret:-1         st: 0 flags:0  ts:-0.040000
 ret: 0         st: 0 flags:1  ts: 2.840000
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 1.730004
 ret:-EOF
 ret: 0         st:-1 flags:1  ts: 0.624171
 ret: 0         st: 0 flags:1 dts: 0.640000 pts: 0.640000 pos:2433184 size:152064
-ret: 0         st: 0 flags:0  ts:-0.480000
-ret: 0         st: 0 flags:1 dts: 0.680000 pts: 0.680000 pos:2585254 size:152064
+ret:-1         st: 0 flags:0  ts:-0.480000
 ret: 0         st: 0 flags:1  ts: 2.400000
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 1.306672
 ret:-EOF
 ret: 0         st:-1 flags:1  ts: 0.200839
 ret: 0         st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos: 760414 size:152064
-ret: 0         st: 0 flags:0  ts:-0.920000
-ret: 0         st: 0 flags:1 dts: 0.240000 pts: 0.240000 pos: 912484 size:152064
+ret:-1         st: 0 flags:0  ts:-0.920000
 ret: 0         st: 0 flags:1  ts: 2.000000
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 0.883340
 ret: 0         st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:3345604 size:152064
-ret: 0         st:-1 flags:1  ts:-0.222493
-ret: 0         st: 0 flags:1 dts: 0.920000 pts: 0.920000 pos:3497674 size:152064
+ret:-1         st:-1 flags:1  ts:-0.222493
 ret: 0         st: 0 flags:0  ts: 2.680000
 ret:-EOF
 ret: 0         st: 0 flags:1  ts: 1.560000
 ret:-EOF
 ret: 0         st:-1 flags:0  ts: 0.460008
 ret: 0         st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:1824904 size:152064
-ret: 0         st:-1 flags:1  ts:-0.645825
-ret: 0         st: 0 flags:1 dts: 0.520000 pts: 0.520000 pos:1976974 size:152064
+ret:-1         st:-1 flags:1  ts:-0.645825
diff --git a/tests/ref/vsynth/vsynth1-bpp1 b/tests/ref/vsynth/vsynth1-bpp1
index 0bd1a77..af1fb0e 100644
--- a/tests/ref/vsynth/vsynth1-bpp1
+++ b/tests/ref/vsynth/vsynth1-bpp1
@@ -1,4 +1,4 @@
-611de0803ff6bd0ef385dde59964a105 *tests/data/fate/vsynth1-bpp1.avi
-640452 tests/data/fate/vsynth1-bpp1.avi
-576b690e8a8921c54d777463b63a8307 *tests/data/fate/vsynth1-bpp1.out.rawvideo
-stddev:   97.41 PSNR:  8.36 MAXDIFF:  238 bytes:  7603200/  7603200
+a0b35707a9aa7144e3e1c70c1d01f4ce *tests/data/fate/vsynth1-bpp1.avi
+640460 tests/data/fate/vsynth1-bpp1.avi
+cd1e1448d9895561347ceb66d0add34d *tests/data/fate/vsynth1-bpp1.out.rawvideo
+stddev:   84.48 PSNR:  9.60 MAXDIFF:  218 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth1-vc2-420p b/tests/ref/vsynth/vsynth1-vc2-420p
new file mode 100644
index 0000000..e925c53
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-vc2-420p
@@ -0,0 +1,4 @@
+fb8fffcfc17558c87dd11a67ccb0f615 *tests/data/fate/vsynth1-vc2-420p.mov
+1155415 tests/data/fate/vsynth1-vc2-420p.mov
+387696707c79cf1a6c9aeff4024226b9 *tests/data/fate/vsynth1-vc2-420p.out.rawvideo
+stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth1-vc2-420p10 b/tests/ref/vsynth/vsynth1-vc2-420p10
new file mode 100644
index 0000000..037c77c
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-vc2-420p10
@@ -0,0 +1,4 @@
+1365742985b6315f6796c765aa17f39e *tests/data/fate/vsynth1-vc2-420p10.mov
+1417047 tests/data/fate/vsynth1-vc2-420p10.mov
+d3deedfa461a2696f82910890412fa2d *tests/data/fate/vsynth1-vc2-420p10.out.rawvideo
+stddev:    0.60 PSNR: 52.47 MAXDIFF:    1 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth1-vc2-420p12 b/tests/ref/vsynth/vsynth1-vc2-420p12
new file mode 100644
index 0000000..b0c56af
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-vc2-420p12
@@ -0,0 +1,4 @@
+08a844d17940cd612da269fb08430628 *tests/data/fate/vsynth1-vc2-420p12.mov
+1746007 tests/data/fate/vsynth1-vc2-420p12.mov
+5a78509638a96b0fa17c1b7e9159fd24 *tests/data/fate/vsynth1-vc2-420p12.out.rawvideo
+stddev:    0.67 PSNR: 51.48 MAXDIFF:    1 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth1-vc2-422p b/tests/ref/vsynth/vsynth1-vc2-422p
new file mode 100644
index 0000000..8fc6188
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-vc2-422p
@@ -0,0 +1,4 @@
+19f01a985e87e14664e0e5d14c02d046 *tests/data/fate/vsynth1-vc2-422p.mov
+1229783 tests/data/fate/vsynth1-vc2-422p.mov
+57a7f41235e7f9f094aa7ba5bdc82f02 *tests/data/fate/vsynth1-vc2-422p.out.rawvideo
+stddev:    1.89 PSNR: 42.58 MAXDIFF:   23 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth1-vc2-422p10 b/tests/ref/vsynth/vsynth1-vc2-422p10
new file mode 100644
index 0000000..ac1072f
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-vc2-422p10
@@ -0,0 +1,4 @@
+88e3488e4689cf06e75959c71e2f9d96 *tests/data/fate/vsynth1-vc2-422p10.mov
+1684055 tests/data/fate/vsynth1-vc2-422p10.mov
+f35dd1c1df4726bb1d75d95e321b0698 *tests/data/fate/vsynth1-vc2-422p10.out.rawvideo
+stddev:    1.88 PSNR: 42.61 MAXDIFF:   23 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth1-vc2-422p12 b/tests/ref/vsynth/vsynth1-vc2-422p12
new file mode 100644
index 0000000..0ad4798
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-vc2-422p12
@@ -0,0 +1,4 @@
+b162a7c531fb06f436c79b38fb3d7403 *tests/data/fate/vsynth1-vc2-422p12.mov
+2135131 tests/data/fate/vsynth1-vc2-422p12.mov
+1b56b3d127320c0e6c643e3430b7ffd1 *tests/data/fate/vsynth1-vc2-422p12.out.rawvideo
+stddev:    1.88 PSNR: 42.62 MAXDIFF:   23 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth1-vc2-444p b/tests/ref/vsynth/vsynth1-vc2-444p
new file mode 100644
index 0000000..d01e938
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-vc2-444p
@@ -0,0 +1,4 @@
+b3f0d987dcb0b5d1eb0b87f356ad21c4 *tests/data/fate/vsynth1-vc2-444p.mov
+1593810 tests/data/fate/vsynth1-vc2-444p.mov
+791cf0f21558ad4a4cad43da05628e06 *tests/data/fate/vsynth1-vc2-444p.out.rawvideo
+stddev:    2.69 PSNR: 39.51 MAXDIFF:   37 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth1-vc2-444p10 b/tests/ref/vsynth/vsynth1-vc2-444p10
new file mode 100644
index 0000000..af00746
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-vc2-444p10
@@ -0,0 +1,4 @@
+ef286696c5d37277b4064c4f87f6e564 *tests/data/fate/vsynth1-vc2-444p10.mov
+2167643 tests/data/fate/vsynth1-vc2-444p10.mov
+0e2cd6d0e1d68ffee64d269dcb57d66d *tests/data/fate/vsynth1-vc2-444p10.out.rawvideo
+stddev:    2.69 PSNR: 39.53 MAXDIFF:   37 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth1-vc2-444p12 b/tests/ref/vsynth/vsynth1-vc2-444p12
new file mode 100644
index 0000000..6a71b67
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-vc2-444p12
@@ -0,0 +1,4 @@
+21aaed7828fa847ce5b75399efbc768c *tests/data/fate/vsynth1-vc2-444p12.mov
+2755159 tests/data/fate/vsynth1-vc2-444p12.mov
+55998114d7386d219a49011c8b804a58 *tests/data/fate/vsynth1-vc2-444p12.out.rawvideo
+stddev:    2.69 PSNR: 39.53 MAXDIFF:   37 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth2-bpp1 b/tests/ref/vsynth/vsynth2-bpp1
index d283d6c..4005755 100644
--- a/tests/ref/vsynth/vsynth2-bpp1
+++ b/tests/ref/vsynth/vsynth2-bpp1
@@ -1,4 +1,4 @@
-b51ad49892eb8f8912c5a983718a17bb *tests/data/fate/vsynth2-bpp1.avi
-640452 tests/data/fate/vsynth2-bpp1.avi
-338fb9039a4564e471bf8179f0c48a95 *tests/data/fate/vsynth2-bpp1.out.rawvideo
-stddev:   80.40 PSNR: 10.02 MAXDIFF:  238 bytes:  7603200/  7603200
+a0330430d7dbd76cbd6d099b778397e8 *tests/data/fate/vsynth2-bpp1.avi
+640460 tests/data/fate/vsynth2-bpp1.avi
+f0dfc0e87e5d96bce29a5944b1bd7471 *tests/data/fate/vsynth2-bpp1.out.rawvideo
+stddev:   68.98 PSNR: 11.36 MAXDIFF:  218 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth2-vc2-420p b/tests/ref/vsynth/vsynth2-vc2-420p
new file mode 100644
index 0000000..f355e8d
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-vc2-420p
@@ -0,0 +1,4 @@
+ac4df937fed73532bd8713b0e07870c9 *tests/data/fate/vsynth2-vc2-420p.mov
+860743 tests/data/fate/vsynth2-vc2-420p.mov
+01389f7ae4f2a3dc0d7b8384d435fd83 *tests/data/fate/vsynth2-vc2-420p.out.rawvideo
+stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth2-vc2-420p10 b/tests/ref/vsynth/vsynth2-vc2-420p10
new file mode 100644
index 0000000..9de40d2
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-vc2-420p10
@@ -0,0 +1,4 @@
+1197f8108683b9eb6b0777adb2db1aa8 *tests/data/fate/vsynth2-vc2-420p10.mov
+1181271 tests/data/fate/vsynth2-vc2-420p10.mov
+75174cb90e76c433f6d769531d573ac2 *tests/data/fate/vsynth2-vc2-420p10.out.rawvideo
+stddev:    0.63 PSNR: 52.11 MAXDIFF:    1 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth2-vc2-420p12 b/tests/ref/vsynth/vsynth2-vc2-420p12
new file mode 100644
index 0000000..660a1ee
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-vc2-420p12
@@ -0,0 +1,4 @@
+0e6b3aefd70fca45e67dc8cbc99640e8 *tests/data/fate/vsynth2-vc2-420p12.mov
+1525079 tests/data/fate/vsynth2-vc2-420p12.mov
+b4d45651e20faa7a0bb84a0738638c48 *tests/data/fate/vsynth2-vc2-420p12.out.rawvideo
+stddev:    0.73 PSNR: 50.84 MAXDIFF:    1 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth2-vc2-422p b/tests/ref/vsynth/vsynth2-vc2-422p
new file mode 100644
index 0000000..83689a7
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-vc2-422p
@@ -0,0 +1,4 @@
+b2573399e0ed62ede66b1708de86412a *tests/data/fate/vsynth2-vc2-422p.mov
+1035207 tests/data/fate/vsynth2-vc2-422p.mov
+c14eb0038a5dba9382f42f750d46ed3c *tests/data/fate/vsynth2-vc2-422p.out.rawvideo
+stddev:    0.35 PSNR: 57.21 MAXDIFF:    7 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth2-vc2-422p10 b/tests/ref/vsynth/vsynth2-vc2-422p10
new file mode 100644
index 0000000..af9a0b1
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-vc2-422p10
@@ -0,0 +1,4 @@
+ca65de033b17c67be94356e0b6e0b128 *tests/data/fate/vsynth2-vc2-422p10.mov
+1321687 tests/data/fate/vsynth2-vc2-422p10.mov
+8f629e5cea24cc804d6aeadceacf0b2a *tests/data/fate/vsynth2-vc2-422p10.out.rawvideo
+stddev:    0.37 PSNR: 56.66 MAXDIFF:    7 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth2-vc2-422p12 b/tests/ref/vsynth/vsynth2-vc2-422p12
new file mode 100644
index 0000000..16f978a
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-vc2-422p12
@@ -0,0 +1,4 @@
+4e95706b063adbcc1f7f82a4e7d7d027 *tests/data/fate/vsynth2-vc2-422p12.mov
+1752535 tests/data/fate/vsynth2-vc2-422p12.mov
+7241b922e7c17d14701567db6c743a9e *tests/data/fate/vsynth2-vc2-422p12.out.rawvideo
+stddev:    0.37 PSNR: 56.73 MAXDIFF:    7 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth2-vc2-444p b/tests/ref/vsynth/vsynth2-vc2-444p
new file mode 100644
index 0000000..8397996
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-vc2-444p
@@ -0,0 +1,4 @@
+644a39d1b853f44722a4332d5a13797e *tests/data/fate/vsynth2-vc2-444p.mov
+1202386 tests/data/fate/vsynth2-vc2-444p.mov
+6b35f3ddc3b52f4424237d4191a2461f *tests/data/fate/vsynth2-vc2-444p.out.rawvideo
+stddev:    0.44 PSNR: 55.07 MAXDIFF:   10 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth2-vc2-444p10 b/tests/ref/vsynth/vsynth2-vc2-444p10
new file mode 100644
index 0000000..7d9367a
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-vc2-444p10
@@ -0,0 +1,4 @@
+36cfc3da2ab6ff6d48f17ab43e77774d *tests/data/fate/vsynth2-vc2-444p10.mov
+1603927 tests/data/fate/vsynth2-vc2-444p10.mov
+d5c80ee1881a0306b0487e3c868529a3 *tests/data/fate/vsynth2-vc2-444p10.out.rawvideo
+stddev:    0.48 PSNR: 54.46 MAXDIFF:   10 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth2-vc2-444p12 b/tests/ref/vsynth/vsynth2-vc2-444p12
new file mode 100644
index 0000000..0009830
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-vc2-444p12
@@ -0,0 +1,4 @@
+6117c2ee6d5c22ee5a0b0ac6b70e6c17 *tests/data/fate/vsynth2-vc2-444p12.mov
+2145499 tests/data/fate/vsynth2-vc2-444p12.mov
+38836be5c12b951c9b280d15fe3b31ce *tests/data/fate/vsynth2-vc2-444p12.out.rawvideo
+stddev:    0.48 PSNR: 54.46 MAXDIFF:   10 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth3-bpp1 b/tests/ref/vsynth/vsynth3-bpp1
index 5a65728..3c8c47a 100644
--- a/tests/ref/vsynth/vsynth3-bpp1
+++ b/tests/ref/vsynth/vsynth3-bpp1
@@ -1,4 +1,4 @@
-98852649c5201df7d85d0e9b5a5b9f15 *tests/data/fate/vsynth3-bpp1.avi
-15352 tests/data/fate/vsynth3-bpp1.avi
-0b1ea21b69d384564dd3a978065443b2 *tests/data/fate/vsynth3-bpp1.out.rawvideo
-stddev:   97.64 PSNR:  8.34 MAXDIFF:  248 bytes:    86700/    86700
+4c8777a88a9e52b99d5a345acffcbf06 *tests/data/fate/vsynth3-bpp1.avi
+20460 tests/data/fate/vsynth3-bpp1.avi
+52ae74ef7910e5b603c12288d425b9ae *tests/data/fate/vsynth3-bpp1.out.rawvideo
+stddev:   84.76 PSNR:  9.57 MAXDIFF:  232 bytes:    86700/    86700
diff --git a/tests/ref/vsynth/vsynth3-rgb b/tests/ref/vsynth/vsynth3-rgb
index c0a8563..f67d285 100644
--- a/tests/ref/vsynth/vsynth3-rgb
+++ b/tests/ref/vsynth/vsynth3-rgb
@@ -1,4 +1,4 @@
-a2cb86007b8945e2d1399b56585b983a *tests/data/fate/vsynth3-rgb.avi
-180252 tests/data/fate/vsynth3-rgb.avi
+000bd5f3251bfd6a2a2b590b2d16fe0b *tests/data/fate/vsynth3-rgb.avi
+183652 tests/data/fate/vsynth3-rgb.avi
 693aff10c094f8bd31693f74cf79d2b2 *tests/data/fate/vsynth3-rgb.out.rawvideo
 stddev:    3.67 PSNR: 36.82 MAXDIFF:   43 bytes:    86700/    86700
diff --git a/tests/ref/vsynth/vsynth_lena-bpp1 b/tests/ref/vsynth/vsynth_lena-bpp1
index 63ab9e1..3489989 100644
--- a/tests/ref/vsynth/vsynth_lena-bpp1
+++ b/tests/ref/vsynth/vsynth_lena-bpp1
@@ -1,4 +1,4 @@
-2859022fac452b59e49a1189c4fbb3ec *tests/data/fate/vsynth_lena-bpp1.avi
-640452 tests/data/fate/vsynth_lena-bpp1.avi
-3be3497f8ca548c9196dcecc5bc7cb2b *tests/data/fate/vsynth_lena-bpp1.out.rawvideo
-stddev:   96.52 PSNR:  8.44 MAXDIFF:  231 bytes:  7603200/  7603200
+32673399a8442e397a608839eb3e95cb *tests/data/fate/vsynth_lena-bpp1.avi
+640460 tests/data/fate/vsynth_lena-bpp1.avi
+6183ba861d4e48d4aaefc514fde270e5 *tests/data/fate/vsynth_lena-bpp1.out.rawvideo
+stddev:   83.28 PSNR:  9.72 MAXDIFF:  215 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth_lena-ffv1-v3-yuv420 b/tests/ref/vsynth/vsynth_lena-ffv1-v3-yuv420
deleted file mode 100644
index 7db437e..0000000
--- a/tests/ref/vsynth/vsynth_lena-ffv1-v3-yuv420
+++ /dev/null
@@ -1,4 +0,0 @@
-ed72c22374718589ffacd7ea15424687 *tests/data/fate/vsynth_lena-ffv1-v3-yuv420.avi
-3547792 tests/data/fate/vsynth_lena-ffv1-v3-yuv420.avi
-dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth_lena-ffv1-v3-yuv420.out.rawvideo
-stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth_lena-vc2-420p b/tests/ref/vsynth/vsynth_lena-vc2-420p
new file mode 100644
index 0000000..89966c2
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-vc2-420p
@@ -0,0 +1,4 @@
+b920eaf484af9ed3fbff4a85d043b544 *tests/data/fate/vsynth_lena-vc2-420p.mov
+849735 tests/data/fate/vsynth_lena-vc2-420p.mov
+b1c660113acab8eb4075f3d9fbb9cee9 *tests/data/fate/vsynth_lena-vc2-420p.out.rawvideo
+stddev:    0.00 PSNR:999.99 MAXDIFF:    0 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth_lena-vc2-420p10 b/tests/ref/vsynth/vsynth_lena-vc2-420p10
new file mode 100644
index 0000000..6428dd1
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-vc2-420p10
@@ -0,0 +1,4 @@
+5bccec653c330f03b90065a84fad9b4b *tests/data/fate/vsynth_lena-vc2-420p10.mov
+1154775 tests/data/fate/vsynth_lena-vc2-420p10.mov
+32265ec286c54104b3be8f11c519da1b *tests/data/fate/vsynth_lena-vc2-420p10.out.rawvideo
+stddev:    0.61 PSNR: 52.34 MAXDIFF:    1 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth_lena-vc2-420p12 b/tests/ref/vsynth/vsynth_lena-vc2-420p12
new file mode 100644
index 0000000..e62b2b6
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-vc2-420p12
@@ -0,0 +1,4 @@
+d27a6d3517cc9a6d22e338f4b206545c *tests/data/fate/vsynth_lena-vc2-420p12.mov
+1516759 tests/data/fate/vsynth_lena-vc2-420p12.mov
+bc62f1c3bade7224c55219dba8a3c6af *tests/data/fate/vsynth_lena-vc2-420p12.out.rawvideo
+stddev:    0.68 PSNR: 51.39 MAXDIFF:    1 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth_lena-vc2-422p b/tests/ref/vsynth/vsynth_lena-vc2-422p
new file mode 100644
index 0000000..6f95838
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-vc2-422p
@@ -0,0 +1,4 @@
+94d3a24e9eec6cb88c84780796adbec5 *tests/data/fate/vsynth_lena-vc2-422p.mov
+1049287 tests/data/fate/vsynth_lena-vc2-422p.mov
+c4b2e69278c822f22655344068ea486d *tests/data/fate/vsynth_lena-vc2-422p.out.rawvideo
+stddev:    0.26 PSNR: 59.82 MAXDIFF:    5 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth_lena-vc2-422p10 b/tests/ref/vsynth/vsynth_lena-vc2-422p10
new file mode 100644
index 0000000..11904c2
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-vc2-422p10
@@ -0,0 +1,4 @@
+fc955b863eb3f22694d37e8a70085a6c *tests/data/fate/vsynth_lena-vc2-422p10.mov
+1294039 tests/data/fate/vsynth_lena-vc2-422p10.mov
+e5ea17416bda234ae58f27dea27e8135 *tests/data/fate/vsynth_lena-vc2-422p10.out.rawvideo
+stddev:    0.30 PSNR: 58.58 MAXDIFF:    5 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth_lena-vc2-422p12 b/tests/ref/vsynth/vsynth_lena-vc2-422p12
new file mode 100644
index 0000000..51a62d0
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-vc2-422p12
@@ -0,0 +1,4 @@
+2cef57ce35f32642c829f24a0ca3e260 *tests/data/fate/vsynth_lena-vc2-422p12.mov
+1768027 tests/data/fate/vsynth_lena-vc2-422p12.mov
+bd374304997834410a69ee6c6e047d19 *tests/data/fate/vsynth_lena-vc2-422p12.out.rawvideo
+stddev:    0.29 PSNR: 58.76 MAXDIFF:    5 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth_lena-vc2-444p b/tests/ref/vsynth/vsynth_lena-vc2-444p
new file mode 100644
index 0000000..bf77918
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-vc2-444p
@@ -0,0 +1,4 @@
+cbdf2421fdd6cf0789c1f308009666f6 *tests/data/fate/vsynth_lena-vc2-444p.mov
+1174738 tests/data/fate/vsynth_lena-vc2-444p.mov
+f9306b14ff827ced1a992301d1ab02ca *tests/data/fate/vsynth_lena-vc2-444p.out.rawvideo
+stddev:    0.38 PSNR: 56.43 MAXDIFF:    6 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth_lena-vc2-444p10 b/tests/ref/vsynth/vsynth_lena-vc2-444p10
new file mode 100644
index 0000000..10a33e2
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-vc2-444p10
@@ -0,0 +1,4 @@
+acda7042ecc5b917824d9cf62ee3b46c *tests/data/fate/vsynth_lena-vc2-444p10.mov
+1577815 tests/data/fate/vsynth_lena-vc2-444p10.mov
+da13c67fe1c6d98dd73e92a6ba006edc *tests/data/fate/vsynth_lena-vc2-444p10.out.rawvideo
+stddev:    0.42 PSNR: 55.56 MAXDIFF:    7 bytes:  7603200/   760320
diff --git a/tests/ref/vsynth/vsynth_lena-vc2-444p12 b/tests/ref/vsynth/vsynth_lena-vc2-444p12
new file mode 100644
index 0000000..7d6c211
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-vc2-444p12
@@ -0,0 +1,4 @@
+a31f2e6a54896fb8c02272c9f50db716 *tests/data/fate/vsynth_lena-vc2-444p12.mov
+2134875 tests/data/fate/vsynth_lena-vc2-444p12.mov
+a505434ec95362772a57d274f63a3f5a *tests/data/fate/vsynth_lena-vc2-444p12.out.rawvideo
+stddev:    0.42 PSNR: 55.58 MAXDIFF:    7 bytes:  7603200/   760320
diff --git a/tests/tiny_psnr.c b/tests/tiny_psnr.c
index 338845e..d01aa29 100644
--- a/tests/tiny_psnr.c
+++ b/tests/tiny_psnr.c
@@ -132,13 +132,13 @@ static double get_f64l(uint8_t *p)
 
 static int run_psnr(FILE *f[2], int len, int shift, int skip_bytes)
 {
-    int i, j;
+    uint64_t i, j;
     uint64_t sse = 0;
     double sse_d = 0.0;
     uint8_t buf[2][SIZE];
     int64_t max    = (1LL << (8 * len)) - 1;
-    int size0      = 0;
-    int size1      = 0;
+    uint64_t size0   = 0;
+    uint64_t size1   = 0;
     uint64_t maxdist = 0;
     double maxdist_d = 0.0;
     int noseek;
@@ -233,7 +233,7 @@ static int run_psnr(FILE *f[2], int len, int shift, int skip_bytes)
         else
             psnr = 1000 * F - 1; // floating point free infinity :)
 
-        printf("stddev:%5d.%02d PSNR:%3d.%02d MAXDIFF:%5"PRIu64" bytes:%9d/%9d\n",
+        printf("stddev:%5d.%02d PSNR:%3d.%02d MAXDIFF:%5"PRIu64" bytes:%9"PRIu64"/%9"PRIu64"\n",
                (int)(dev / F), (int)(dev % F),
                (int)(psnr / F), (int)(psnr % F),
                maxdist, size0, size1);
@@ -254,7 +254,7 @@ static int run_psnr(FILE *f[2], int len, int shift, int skip_bytes)
 
         maxdist = maxdist_d * scale;
 
-        printf("stddev:%10.2f PSNR:%s MAXDIFF:%10"PRIu64" bytes:%9d/%9d\n",
+        printf("stddev:%10.2f PSNR:%s MAXDIFF:%10"PRIu64" bytes:%9"PRIu64"/%9"PRIu64"\n",
                dev * scale, psnr_str, maxdist, size0, size1);
         return psnr;
     }
diff --git a/tools/dvd2concat b/tools/dvd2concat
index 02371e0..8effee8 100755
--- a/tools/dvd2concat
+++ b/tools/dvd2concat
@@ -36,7 +36,7 @@ I<path/to/dvd/structure> is the path to the DVD structure hierarchy; it
 normally contains a directory named B<VIDEO_TS>. It must not be encrypted
 with CSS.
 
-I<file.concat> is the output file. It can be used a input to ffmpeg.
+I<file.concat> is the output file. It can be used as an input to ffmpeg.
 It will require the B<-safe 0> option.
 
 =cut
diff --git a/tools/ismindex.c b/tools/ismindex.c
index dfef118..5917d42 100644
--- a/tools/ismindex.c
+++ b/tools/ismindex.c
@@ -453,41 +453,41 @@ fail:
     return err;
 }
 
-static int get_private_data(struct Track *track, AVCodecContext *codec)
+static int get_private_data(struct Track *track, AVCodecParameters *codecpar)
 {
     track->codec_private_size = 0;
-    track->codec_private      = av_mallocz(codec->extradata_size);
+    track->codec_private      = av_mallocz(codecpar->extradata_size);
     if (!track->codec_private)
         return AVERROR(ENOMEM);
-    track->codec_private_size = codec->extradata_size;
-    memcpy(track->codec_private, codec->extradata, codec->extradata_size);
+    track->codec_private_size = codecpar->extradata_size;
+    memcpy(track->codec_private, codecpar->extradata, codecpar->extradata_size);
     return 0;
 }
 
-static int get_video_private_data(struct Track *track, AVCodecContext *codec)
+static int get_video_private_data(struct Track *track, AVCodecParameters *codecpar)
 {
     AVIOContext *io = NULL;
     uint16_t sps_size, pps_size;
     int err;
 
-    if (codec->codec_id == AV_CODEC_ID_VC1)
-        return get_private_data(track, codec);
+    if (codecpar->codec_id == AV_CODEC_ID_VC1)
+        return get_private_data(track, codecpar);
 
     if ((err = avio_open_dyn_buf(&io)) < 0)
         goto fail;
     err = AVERROR(EINVAL);
-    if (codec->extradata_size < 11 || codec->extradata[0] != 1)
+    if (codecpar->extradata_size < 11 || codecpar->extradata[0] != 1)
         goto fail;
-    sps_size = AV_RB16(&codec->extradata[6]);
-    if (11 + sps_size > codec->extradata_size)
+    sps_size = AV_RB16(&codecpar->extradata[6]);
+    if (11 + sps_size > codecpar->extradata_size)
         goto fail;
     avio_wb32(io, 0x00000001);
-    avio_write(io, &codec->extradata[8], sps_size);
-    pps_size = AV_RB16(&codec->extradata[9 + sps_size]);
-    if (11 + sps_size + pps_size > codec->extradata_size)
+    avio_write(io, &codecpar->extradata[8], sps_size);
+    pps_size = AV_RB16(&codecpar->extradata[9 + sps_size]);
+    if (11 + sps_size + pps_size > codecpar->extradata_size)
         goto fail;
     avio_wb32(io, 0x00000001);
-    avio_write(io, &codec->extradata[11 + sps_size], pps_size);
+    avio_write(io, &codecpar->extradata[11 + sps_size], pps_size);
     err = 0;
 
 fail:
@@ -527,7 +527,7 @@ static int handle_file(struct Tracks *tracks, const char *file, int split,
         struct Track **temp;
         AVStream *st = ctx->streams[i];
 
-        if (st->codec->bit_rate == 0) {
+        if (st->codecpar->bit_rate == 0) {
             fprintf(stderr, "Skipping track %d in %s as it has zero bitrate\n",
                     st->id, file);
             continue;
@@ -553,12 +553,12 @@ static int handle_file(struct Tracks *tracks, const char *file, int split,
         if ((ptr = strrchr(file, '/')))
             track->name = ptr + 1;
 
-        track->bitrate   = st->codec->bit_rate;
+        track->bitrate   = st->codecpar->bit_rate;
         track->track_id  = st->id;
         track->timescale = st->time_base.den;
         track->duration  = st->duration;
-        track->is_audio  = st->codec->codec_type == AVMEDIA_TYPE_AUDIO;
-        track->is_video  = st->codec->codec_type == AVMEDIA_TYPE_VIDEO;
+        track->is_audio  = st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;
+        track->is_video  = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
 
         if (!track->is_audio && !track->is_video) {
             fprintf(stderr,
@@ -576,30 +576,30 @@ static int handle_file(struct Tracks *tracks, const char *file, int split,
             if (tracks->audio_track < 0)
                 tracks->audio_track = tracks->nb_tracks;
             tracks->nb_audio_tracks++;
-            track->channels    = st->codec->channels;
-            track->sample_rate = st->codec->sample_rate;
-            if (st->codec->codec_id == AV_CODEC_ID_AAC) {
+            track->channels    = st->codecpar->channels;
+            track->sample_rate = st->codecpar->sample_rate;
+            if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
                 track->fourcc    = "AACL";
                 track->tag       = 255;
                 track->blocksize = 4;
-            } else if (st->codec->codec_id == AV_CODEC_ID_WMAPRO) {
+            } else if (st->codecpar->codec_id == AV_CODEC_ID_WMAPRO) {
                 track->fourcc    = "WMAP";
-                track->tag       = st->codec->codec_tag;
-                track->blocksize = st->codec->block_align;
+                track->tag       = st->codecpar->codec_tag;
+                track->blocksize = st->codecpar->block_align;
             }
-            get_private_data(track, st->codec);
+            get_private_data(track, st->codecpar);
         }
         if (track->is_video) {
             if (tracks->video_track < 0)
                 tracks->video_track = tracks->nb_tracks;
             tracks->nb_video_tracks++;
-            track->width  = st->codec->width;
-            track->height = st->codec->height;
-            if (st->codec->codec_id == AV_CODEC_ID_H264)
+            track->width  = st->codecpar->width;
+            track->height = st->codecpar->height;
+            if (st->codecpar->codec_id == AV_CODEC_ID_H264)
                 track->fourcc = "H264";
-            else if (st->codec->codec_id == AV_CODEC_ID_VC1)
+            else if (st->codecpar->codec_id == AV_CODEC_ID_VC1)
                 track->fourcc = "WVC1";
-            get_video_private_data(track, st->codec);
+            get_video_private_data(track, st->codecpar);
         }
 
         tracks->nb_tracks++;
diff --git a/tools/sidxindex.c b/tools/sidxindex.c
index 504c595..be28461 100644
--- a/tools/sidxindex.c
+++ b/tools/sidxindex.c
@@ -52,22 +52,23 @@ struct Tracks {
     int multiple_tracks_per_file;
 };
 
-static void set_codec_str(AVCodecContext *codec, char *str, int size)
+static void set_codec_str(AVCodecParameters *codecpar, char *str, int size)
 {
-    switch (codec->codec_id) {
+    switch (codecpar->codec_id) {
     case AV_CODEC_ID_H264:
         snprintf(str, size, "avc1");
-        if (codec->extradata_size >= 4 && codec->extradata[0] == 1) {
+        if (codecpar->extradata_size >= 4 && codecpar->extradata[0] == 1) {
             av_strlcatf(str, size, ".%02x%02x%02x",
-                        codec->extradata[1], codec->extradata[2], codec->extradata[3]);
+                        codecpar->extradata[1], codecpar->extradata[2],
+                        codecpar->extradata[3]);
         }
         break;
     case AV_CODEC_ID_AAC:
         snprintf(str, size, "mp4a.40"); // 0x40 is the mp4 object type for AAC
-        if (codec->extradata_size >= 2) {
-            int aot = codec->extradata[0] >> 3;
+        if (codecpar->extradata_size >= 2) {
+            int aot = codecpar->extradata[0] >> 3;
             if (aot == 31)
-                aot = ((AV_RB16(codec->extradata) >> 5) & 0x3f) + 32;
+                aot = ((AV_RB16(codecpar->extradata) >> 5) & 0x3f) + 32;
             av_strlcatf(str, size, ".%d", aot);
         }
         break;
@@ -145,7 +146,7 @@ static int handle_file(struct Tracks *tracks, const char *file)
         struct Track **temp;
         AVStream *st = ctx->streams[i];
 
-        if (st->codec->bit_rate == 0) {
+        if (st->codecpar->bit_rate == 0) {
             fprintf(stderr, "Skipping track %d in %s as it has zero bitrate\n",
                     st->id, file);
             continue;
@@ -170,12 +171,12 @@ static int handle_file(struct Tracks *tracks, const char *file)
         if ((ptr = strrchr(file, '/')))
             track->name = ptr + 1;
 
-        track->bitrate   = st->codec->bit_rate;
+        track->bitrate   = st->codecpar->bit_rate;
         track->track_id  = st->id;
         track->timescale = st->time_base.den;
         track->duration  = st->duration;
-        track->is_audio  = st->codec->codec_type == AVMEDIA_TYPE_AUDIO;
-        track->is_video  = st->codec->codec_type == AVMEDIA_TYPE_VIDEO;
+        track->is_audio  = st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;
+        track->is_video  = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
 
         if (!track->is_audio && !track->is_video) {
             fprintf(stderr,
@@ -190,14 +191,14 @@ static int handle_file(struct Tracks *tracks, const char *file)
                                                 track->timescale, AV_ROUND_UP));
 
         if (track->is_audio) {
-            track->channels    = st->codec->channels;
-            track->sample_rate = st->codec->sample_rate;
+            track->channels    = st->codecpar->channels;
+            track->sample_rate = st->codecpar->sample_rate;
         }
         if (track->is_video) {
-            track->width  = st->codec->width;
-            track->height = st->codec->height;
+            track->width  = st->codecpar->width;
+            track->height = st->codecpar->height;
         }
-        set_codec_str(st->codec, track->codec_str, sizeof(track->codec_str));
+        set_codec_str(st->codecpar, track->codec_str, sizeof(track->codec_str));
 
         tracks->nb_tracks++;
     }
diff --git a/version.sh b/version.sh
index a9d7e39..edc4dd3 100755
--- a/version.sh
+++ b/version.sh
@@ -46,7 +46,7 @@ if [ -z "$2" ]; then
 fi
 
 NEW_REVISION="#define FFMPEG_VERSION \"$version\""
-OLD_REVISION=$(cat "$2" 2> /dev/null | head -3 | tail -1)
+OLD_REVISION=$(cat "$2" 2> /dev/null | head -4 | tail -1)
 
 # String used for preprocessor guard
 GUARD=$(echo "$2" | sed 's/\//_/' | sed 's/\./_/' | tr '[:lower:]' '[:upper:]' | sed 's/LIB//')

-- 
ffmpeg packaging



More information about the pkg-multimedia-commits mailing list